From 13bed58ce8748d430a26e353a09b89f9d613a71f Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Thu, 5 May 2016 13:32:57 +0800 Subject: regulator: fixed: add support for ACPI interface Add support to retrieve fixed voltage configure information through ACPI interface. This is needed for Intel Bay Trail devices, where a GPIO is used to control the USB vbus. Signed-off-by: Lu Baolu Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 988a7472c2ab..a43b0e8a438d 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include struct fixed_voltage_data { struct regulator_desc desc; @@ -94,6 +97,44 @@ of_get_fixed_voltage_config(struct device *dev, return config; } +/** + * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info + * @dev: device requesting for fixed_voltage_config + * @desc: regulator description + * + * Populates fixed_voltage_config structure by extracting data through ACPI + * interface, returns a pointer to the populated structure of NULL if memory + * alloc fails. + */ +static struct fixed_voltage_config * +acpi_get_fixed_voltage_config(struct device *dev, + const struct regulator_desc *desc) +{ + struct fixed_voltage_config *config; + const char *supply_name; + struct gpio_desc *gpiod; + int ret; + + config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL); + if (!config) + return ERR_PTR(-ENOMEM); + + ret = device_property_read_string(dev, "supply-name", &supply_name); + if (!ret) + config->supply_name = supply_name; + + gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS); + if (IS_ERR(gpiod)) + return ERR_PTR(-ENODEV); + + config->gpio = desc_to_gpio(gpiod); + config->enable_high = device_property_read_bool(dev, + "enable-active-high"); + gpiod_put(gpiod); + + return config; +} + static struct regulator_ops fixed_voltage_ops = { }; @@ -114,6 +155,11 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) &drvdata->desc); if (IS_ERR(config)) return PTR_ERR(config); + } else if (ACPI_HANDLE(&pdev->dev)) { + config = acpi_get_fixed_voltage_config(&pdev->dev, + &drvdata->desc); + if (IS_ERR(config)) + return PTR_ERR(config); } else { config = dev_get_platdata(&pdev->dev); } -- cgit v1.2.3 From 1bb0802460da42cd552e03060a65e3f303905088 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 16 Sep 2016 15:49:33 -0400 Subject: tty, workqueue: remove keventd_up() usage Now that workqueue can handle work item queueing from very early during boot, there is no need to delay schedule_work() while !keventd_up(). Remove it. Signed-off-by: Tejun Heo Cc: Jiri Slaby Cc: Alan Cox --- drivers/tty/vt/vt.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2705ca960e92..f76ad4c1fc4c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -3924,10 +3924,6 @@ void unblank_screen(void) */ static void blank_screen_t(unsigned long dummy) { - if (unlikely(!keventd_up())) { - mod_timer(&console_timer, jiffies + (blankinterval * HZ)); - return; - } blank_timer_expired = 1; schedule_work(&console_work); } -- cgit v1.2.3 From 9f04a1f2b389a656486c1f9f918a3305569fba6a Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 16 Aug 2016 23:26:43 +0300 Subject: drm: dw_hdmi: use of_get_i2c_adapter_by_node interface This change is needed to properly lock I2C bus driver, which serves DDC. The change fixes an overflow over zero of I2C bus driver user counter: root@imx6q:~# lsmod Not tainted dw_hdmi_ahb_audio 4082 0 - Live 0xbf02c000 dw_hdmi_imx 3498 0 - Live 0xbf00d000 dw_hdmi 16398 2 dw_hdmi_ahb_audio,dw_hdmi_imx, Live 0xbf004000 i2c_imx 16687 0 - Live 0xbf017000 root@imx6q:~# rmmod dw_hdmi_imx root@imx6q:~# lsmod Not tainted dw_hdmi_ahb_audio 4082 0 - Live 0xbf02c000 dw_hdmi 16398 1 dw_hdmi_ahb_audio, Live 0xbf004000 i2c_imx 16687 -1 - Live 0xbf017000 ^^ root@imx6q:~# rmmod i2c_imx rmmod: ERROR: Module i2c_imx is in use Note that prior to this change put_device() coupled with of_find_i2c_adapter_by_node() was missing on error path of dw_hdmi_bind(), added i2c_put_adapter() there along with the change. Signed-off-by: Vladimir Zapolskiy Acked-by: Russell King Cc: Fabio Estevam Signed-off-by: Philipp Zabel --- drivers/gpu/drm/bridge/dw-hdmi.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 77ab47341658..ce3527cd0d25 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -1686,7 +1686,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); if (ddc_node) { - hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); + hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); of_node_put(ddc_node); if (!hdmi->ddc) { dev_dbg(hdmi->dev, "failed to read ddc node\n"); @@ -1698,20 +1698,22 @@ int dw_hdmi_bind(struct device *dev, struct device *master, } hdmi->regs = devm_ioremap_resource(dev, iores); - if (IS_ERR(hdmi->regs)) - return PTR_ERR(hdmi->regs); + if (IS_ERR(hdmi->regs)) { + ret = PTR_ERR(hdmi->regs); + goto err_res; + } hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); if (IS_ERR(hdmi->isfr_clk)) { ret = PTR_ERR(hdmi->isfr_clk); dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret); - return ret; + goto err_res; } ret = clk_prepare_enable(hdmi->isfr_clk); if (ret) { dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret); - return ret; + goto err_res; } hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); @@ -1797,6 +1799,8 @@ err_iahb: clk_disable_unprepare(hdmi->iahb_clk); err_isfr: clk_disable_unprepare(hdmi->isfr_clk); +err_res: + i2c_put_adapter(hdmi->ddc); return ret; } -- cgit v1.2.3 From 3efc2fa3b777e65e344a7612d38a8278e78a0514 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 24 Aug 2016 08:46:37 +0300 Subject: drm: bridge/dw_hdmi: add dw hdmi i2c bus adapter support The change adds support of internal HDMI I2C master controller, this subdevice is used by default, if "ddc-i2c-bus" DT property is omitted. The main purpose of this functionality is to support reading EDID from an HDMI monitor on boards, which don't have an I2C bus connected to DDC pins. The current implementation does not support "I2C Master Interface Extended Read Mode" to read data addressed by non-zero segment pointer, this means that if EDID has more than 1 extension blocks, EDID reading operation won't succeed, in my practice all tested HDMI monitors have at maximum one extension block. Signed-off-by: Vladimir Zapolskiy Acked-by: Rob Herring Tested-by: Philipp Zabel Signed-off-by: Philipp Zabel --- .../devicetree/bindings/display/bridge/dw_hdmi.txt | 4 +- drivers/gpu/drm/bridge/dw-hdmi.c | 265 ++++++++++++++++++++- drivers/gpu/drm/bridge/dw-hdmi.h | 19 ++ 3 files changed, 281 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt b/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt index dc1452f0d5d8..5e9a84d6e5f1 100644 --- a/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt +++ b/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt @@ -19,7 +19,9 @@ Required properties: Optional properties - reg-io-width: the width of the reg:1,4, default set to 1 if not present -- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing +- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing, + if the property is omitted, a functionally reduced I2C bus + controller on DW HDMI is probed - clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec" Example: diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index ce3527cd0d25..cdf0a3a2e6f8 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -1,14 +1,15 @@ /* + * DesignWare High-Definition Multimedia Interface (HDMI) driver + * + * Copyright (C) 2013-2015 Mentor Graphics Inc. * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2010, Guennadi Liakhovetski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * Designware High-Definition Multimedia Interface (HDMI) driver - * - * Copyright (C) 2010, Guennadi Liakhovetski */ #include #include @@ -101,6 +102,17 @@ struct hdmi_data_info { struct hdmi_vmode video_mode; }; +struct dw_hdmi_i2c { + struct i2c_adapter adap; + + struct mutex lock; /* used to serialize data transfers */ + struct completion cmp; + u8 stat; + + u8 slave_reg; + bool is_regaddr; +}; + struct dw_hdmi { struct drm_connector connector; struct drm_encoder *encoder; @@ -111,6 +123,7 @@ struct dw_hdmi { struct device *dev; struct clk *isfr_clk; struct clk *iahb_clk; + struct dw_hdmi_i2c *i2c; struct hdmi_data_info hdmi_data; const struct dw_hdmi_plat_data *plat_data; @@ -198,6 +211,201 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, hdmi_modb(hdmi, data << shift, mask, reg); } +static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi) +{ + /* Software reset */ + hdmi_writeb(hdmi, 0x00, HDMI_I2CM_SOFTRSTZ); + + /* Set Standard Mode speed (determined to be 100KHz on iMX6) */ + hdmi_writeb(hdmi, 0x00, HDMI_I2CM_DIV); + + /* Set done, not acknowledged and arbitration interrupt polarities */ + hdmi_writeb(hdmi, HDMI_I2CM_INT_DONE_POL, HDMI_I2CM_INT); + hdmi_writeb(hdmi, HDMI_I2CM_CTLINT_NAC_POL | HDMI_I2CM_CTLINT_ARB_POL, + HDMI_I2CM_CTLINT); + + /* Clear DONE and ERROR interrupts */ + hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, + HDMI_IH_I2CM_STAT0); + + /* Mute DONE and ERROR interrupts */ + hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, + HDMI_IH_MUTE_I2CM_STAT0); +} + +static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi, + unsigned char *buf, unsigned int length) +{ + struct dw_hdmi_i2c *i2c = hdmi->i2c; + int stat; + + if (!i2c->is_regaddr) { + dev_dbg(hdmi->dev, "set read register address to 0\n"); + i2c->slave_reg = 0x00; + i2c->is_regaddr = true; + } + + while (length--) { + reinit_completion(&i2c->cmp); + + hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS); + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ, + HDMI_I2CM_OPERATION); + + stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); + if (!stat) + return -EAGAIN; + + /* Check for error condition on the bus */ + if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) + return -EIO; + + *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI); + } + + return 0; +} + +static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi, + unsigned char *buf, unsigned int length) +{ + struct dw_hdmi_i2c *i2c = hdmi->i2c; + int stat; + + if (!i2c->is_regaddr) { + /* Use the first write byte as register address */ + i2c->slave_reg = buf[0]; + length--; + buf++; + i2c->is_regaddr = true; + } + + while (length--) { + reinit_completion(&i2c->cmp); + + hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO); + hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS); + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE, + HDMI_I2CM_OPERATION); + + stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); + if (!stat) + return -EAGAIN; + + /* Check for error condition on the bus */ + if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) + return -EIO; + } + + return 0; +} + +static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct dw_hdmi *hdmi = i2c_get_adapdata(adap); + struct dw_hdmi_i2c *i2c = hdmi->i2c; + u8 addr = msgs[0].addr; + int i, ret = 0; + + dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr); + + for (i = 0; i < num; i++) { + if (msgs[i].addr != addr) { + dev_warn(hdmi->dev, + "unsupported transfer, changed slave address\n"); + return -EOPNOTSUPP; + } + + if (msgs[i].len == 0) { + dev_dbg(hdmi->dev, + "unsupported transfer %d/%d, no data\n", + i + 1, num); + return -EOPNOTSUPP; + } + } + + mutex_lock(&i2c->lock); + + /* Unmute DONE and ERROR interrupts */ + hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0); + + /* Set slave device address taken from the first I2C message */ + hdmi_writeb(hdmi, addr, HDMI_I2CM_SLAVE); + + /* Set slave device register address on transfer */ + i2c->is_regaddr = false; + + for (i = 0; i < num; i++) { + dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n", + i + 1, num, msgs[i].len, msgs[i].flags); + + if (msgs[i].flags & I2C_M_RD) + ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len); + else + ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len); + + if (ret < 0) + break; + } + + if (!ret) + ret = num; + + /* Mute DONE and ERROR interrupts */ + hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, + HDMI_IH_MUTE_I2CM_STAT0); + + mutex_unlock(&i2c->lock); + + return ret; +} + +static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm dw_hdmi_algorithm = { + .master_xfer = dw_hdmi_i2c_xfer, + .functionality = dw_hdmi_i2c_func, +}; + +static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi) +{ + struct i2c_adapter *adap; + struct dw_hdmi_i2c *i2c; + int ret; + + i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return ERR_PTR(-ENOMEM); + + mutex_init(&i2c->lock); + init_completion(&i2c->cmp); + + adap = &i2c->adap; + adap->class = I2C_CLASS_DDC; + adap->owner = THIS_MODULE; + adap->dev.parent = hdmi->dev; + adap->algo = &dw_hdmi_algorithm; + strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name)); + i2c_set_adapdata(adap, hdmi); + + ret = i2c_add_adapter(adap); + if (ret) { + dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name); + devm_kfree(hdmi->dev, i2c); + return ERR_PTR(ret); + } + + hdmi->i2c = i2c; + + dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); + + return adap; +} + static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, unsigned int n) { @@ -1517,16 +1725,40 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { .mode_set = dw_hdmi_bridge_mode_set, }; +static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi) +{ + struct dw_hdmi_i2c *i2c = hdmi->i2c; + unsigned int stat; + + stat = hdmi_readb(hdmi, HDMI_IH_I2CM_STAT0); + if (!stat) + return IRQ_NONE; + + hdmi_writeb(hdmi, stat, HDMI_IH_I2CM_STAT0); + + i2c->stat = stat; + + complete(&i2c->cmp); + + return IRQ_HANDLED; +} + static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) { struct dw_hdmi *hdmi = dev_id; u8 intr_stat; + irqreturn_t ret = IRQ_NONE; + + if (hdmi->i2c) + ret = dw_hdmi_i2c_irq(hdmi); intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); - if (intr_stat) + if (intr_stat) { hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); + return IRQ_WAKE_THREAD; + } - return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE; + return ret; } static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) @@ -1751,6 +1983,13 @@ int dw_hdmi_bind(struct device *dev, struct device *master, */ hdmi_init_clk_regenerator(hdmi); + /* If DDC bus is not specified, try to register HDMI I2C bus */ + if (!hdmi->ddc) { + hdmi->ddc = dw_hdmi_i2c_adapter(hdmi); + if (IS_ERR(hdmi->ddc)) + hdmi->ddc = NULL; + } + /* * Configure registers related to HDMI interrupt * generation before registering IRQ. @@ -1791,11 +2030,20 @@ int dw_hdmi_bind(struct device *dev, struct device *master, hdmi->audio = platform_device_register_full(&pdevinfo); } + /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */ + if (hdmi->i2c) + dw_hdmi_i2c_init(hdmi); + dev_set_drvdata(dev, hdmi); return 0; err_iahb: + if (hdmi->i2c) { + i2c_del_adapter(&hdmi->i2c->adap); + hdmi->ddc = NULL; + } + clk_disable_unprepare(hdmi->iahb_clk); err_isfr: clk_disable_unprepare(hdmi->isfr_clk); @@ -1821,13 +2069,18 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data) clk_disable_unprepare(hdmi->iahb_clk); clk_disable_unprepare(hdmi->isfr_clk); - i2c_put_adapter(hdmi->ddc); + + if (hdmi->i2c) + i2c_del_adapter(&hdmi->i2c->adap); + else + i2c_put_adapter(hdmi->ddc); } EXPORT_SYMBOL_GPL(dw_hdmi_unbind); MODULE_AUTHOR("Sascha Hauer "); MODULE_AUTHOR("Andy Yan "); MODULE_AUTHOR("Yakir Yang "); +MODULE_AUTHOR("Vladimir Zapolskiy "); MODULE_DESCRIPTION("DW HDMI transmitter driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:dw-hdmi"); diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h index fc9a560429d6..6aadc840e888 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.h +++ b/drivers/gpu/drm/bridge/dw-hdmi.h @@ -566,6 +566,10 @@ enum { HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2, HDMI_IH_PHY_STAT0_HPD = 0x1, +/* IH_I2CM_STAT0 and IH_MUTE_I2CM_STAT0 field values */ + HDMI_IH_I2CM_STAT0_DONE = 0x2, + HDMI_IH_I2CM_STAT0_ERROR = 0x1, + /* IH_MUTE_I2CMPHY_STAT0 field values */ HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2, HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1, @@ -1032,6 +1036,21 @@ enum { HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2, HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2, HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0, + +/* I2CM_OPERATION field values */ + HDMI_I2CM_OPERATION_WRITE = 0x10, + HDMI_I2CM_OPERATION_READ_EXT = 0x2, + HDMI_I2CM_OPERATION_READ = 0x1, + +/* I2CM_INT field values */ + HDMI_I2CM_INT_DONE_POL = 0x8, + HDMI_I2CM_INT_DONE_MASK = 0x4, + +/* I2CM_CTLINT field values */ + HDMI_I2CM_CTLINT_NAC_POL = 0x80, + HDMI_I2CM_CTLINT_NAC_MASK = 0x40, + HDMI_I2CM_CTLINT_ARB_POL = 0x8, + HDMI_I2CM_CTLINT_ARB_MASK = 0x4, }; #endif /* __DW_HDMI_H__ */ -- cgit v1.2.3 From f7d3c970f43a599c7545bfa821761cdb1bef8e23 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:24 +0300 Subject: drm/i915/dsi: don't debug log "missing" sequences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not interesting. They are not "missing", they are just not part of the VBT sequences for the panel. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/54909b29802398d23f1d26f6589671e69688f904.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index cd154ce6b6c1..a537c71cdcc6 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -385,11 +385,8 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) return; data = dev_priv->vbt.dsi.sequence[seq_id]; - if (!data) { - DRM_DEBUG_KMS("MIPI sequence %d - %s not available\n", - seq_id, sequence_name(seq_id)); + if (!data) return; - } WARN_ON(*data != seq_id); -- cgit v1.2.3 From 0b9407c39864b878543c61b719e9ba5a7bfeb0c6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:25 +0300 Subject: drm/i915/dsi: add debug logging to element execution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just simple breadcrumbs for now. While at it, rename the i2c skip function. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/d11c40a99f5ef2419ede87a2ac1858e4c60768b8.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index a537c71cdcc6..89f77a142521 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -126,6 +126,8 @@ static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, u16 len; enum port port; + DRM_DEBUG_KMS("\n"); + flags = *data++; type = *data++; @@ -199,6 +201,8 @@ static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data) { u32 delay = *((const u32 *) data); + DRM_DEBUG_KMS("\n"); + usleep_range(delay, delay + 10); data += 4; @@ -307,6 +311,8 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) u8 gpio_source, gpio_index; bool value; + DRM_DEBUG_KMS("\n"); + if (dev_priv->vbt.dsi.seq_version >= 3) data++; @@ -331,8 +337,10 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) return data; } -static const u8 *mipi_exec_i2c_skip(struct intel_dsi *intel_dsi, const u8 *data) +static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data) { + DRM_DEBUG_KMS("Skipping I2C element execution\n"); + return data + *(data + 6) + 7; } @@ -342,7 +350,7 @@ static const fn_mipi_elem_exec exec_elem[] = { [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet, [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, - [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c_skip, + [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c, }; /* -- cgit v1.2.3 From 044aad65ee02abe2c51e06052df03a5c3f573f78 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:26 +0300 Subject: drm/i915/dsi: add skip functions for spi and pmic elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In sequence block v3 these are gracefully skipped anyway, but add the functions so we can have some debug breadcrumbs. v2: the pmic block is 15 bytes (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/d102ef1f21e6ea9a17655ef31593e68343336a48.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 89f77a142521..29156995a265 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -344,6 +344,20 @@ static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data) return data + *(data + 6) + 7; } +static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data) +{ + DRM_DEBUG_KMS("Skipping SPI element execution\n"); + + return data + *(data + 5) + 6; +} + +static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data) +{ + DRM_DEBUG_KMS("Skipping PMIC element execution\n"); + + return data + 15; +} + typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, const u8 *data); static const fn_mipi_elem_exec exec_elem[] = { @@ -351,6 +365,8 @@ static const fn_mipi_elem_exec exec_elem[] = { [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c, + [MIPI_SEQ_ELEM_SPI] = mipi_exec_spi, + [MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic, }; /* -- cgit v1.2.3 From b1cb1bd29189a017bf2aab879ba7fe22b62c3abe Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:27 +0300 Subject: drm/i915/dsi: update reset and power sequences in panel prepare/unprepare hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the documentation alone, it's anyone's guess when exactly we should be running these sequences. Add power on/off sequences where they feel logical and update assert/deassert reset. The drm panel hooks don't currently offer us more granularity anyway. v2: update assert/deassert reset as well (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1543320494df953fa073e136248238eaa1eed059.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 29156995a265..2c5d14eb7851 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -459,6 +459,8 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) static int vbt_panel_prepare(struct drm_panel *panel) { generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET); + generic_exec_sequence(panel, MIPI_SEQ_POWER_ON); + generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET); generic_exec_sequence(panel, MIPI_SEQ_INIT_OTP); return 0; @@ -466,7 +468,8 @@ static int vbt_panel_prepare(struct drm_panel *panel) static int vbt_panel_unprepare(struct drm_panel *panel) { - generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET); + generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET); + generic_exec_sequence(panel, MIPI_SEQ_POWER_OFF); return 0; } -- cgit v1.2.3 From 416062d017e20e5493f4e764658b104287ce6c4c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:28 +0300 Subject: drm/i915/dsi: run backlight on/off sequences in panel enable/disable hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the documentation alone, it's anyone's guess when exactly we should be running these sequences. Add them where it feels logical. The drm panel hooks don't currently offer us more granularity anyway. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/267c4a2bde2076af18e9b8335c0bef2e26ea3112.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 2c5d14eb7851..24953f9f7e1d 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -477,12 +477,14 @@ static int vbt_panel_unprepare(struct drm_panel *panel) static int vbt_panel_enable(struct drm_panel *panel) { generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_ON); + generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_ON); return 0; } static int vbt_panel_disable(struct drm_panel *panel) { + generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_OFF); generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_OFF); return 0; -- cgit v1.2.3 From 4b4f497e13f0195dd305d0b1dea06291e1e6f521 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:29 +0300 Subject: drm/i915/bios: log about presence of DSI sequences we do not run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Leave behind some debugging clues in case some panels don't work properly. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/b36302b24676af511f4bbf702be21cc7e8f987c2.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index c6e69e4cfa83..83667e8cdd6b 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -996,6 +996,10 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, goto err; } + /* Log about presence of sequences we won't run. */ + if (seq_id == MIPI_SEQ_TEAR_ON || seq_id == MIPI_SEQ_TEAR_OFF) + DRM_DEBUG_KMS("Unsupported sequence %u\n", seq_id); + dev_priv->vbt.dsi.sequence[seq_id] = data + index; if (sequence->version >= 3) -- cgit v1.2.3 From 8e4f768c434e3c197a1b6d59c8e6d0807b10c4cd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:30 +0300 Subject: drm/i915/dsi: double check element parsing against size if present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be a little paranoid in case the specs change or something. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/27050d48d0ff3d58e79fcacc41ced4c071b01424.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 24953f9f7e1d..9f279a3d0f74 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -441,7 +441,15 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) operation_size = *data++; if (mipi_elem_exec) { + const u8 *next = data + operation_size; + data = mipi_elem_exec(intel_dsi, data); + + /* Consistency check if we have size. */ + if (operation_size && data != next) { + DRM_ERROR("Inconsistent operation size\n"); + return; + } } else if (operation_size) { /* We have size, skip. */ DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n", -- cgit v1.2.3 From 32b421e79e6b546da1d469f1229403ac9142d695 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 13:35:25 +0300 Subject: drm/i915/backlight: setup and cache pwm alternate increment value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will also be needed later on when setting up the alternate increment in backlight enable. Cc: Shawn Lee Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/9984b20bc59aee90b83caf59ce91f3fb122c9627.1474281249.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 810c89eb6863..1b451e759976 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -263,6 +263,7 @@ struct intel_panel { bool enabled; bool combination_mode; /* gen 2/4 only */ bool active_low_pwm; + bool alternate_pwm_increment; /* lpt+ */ /* PWM chip */ bool util_pin_active_low; /* bxt+ */ diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index c10e9b0405e8..8bc43205d6a0 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1242,10 +1242,10 @@ static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_panel *panel = &connector->panel; u32 mul; - if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY) + if (panel->backlight.alternate_pwm_increment) mul = 128; else mul = 16; @@ -1261,9 +1261,10 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_panel *panel = &connector->panel; u32 mul, clock; - if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY) + if (panel->backlight.alternate_pwm_increment) mul = 16; else mul = 128; @@ -1414,6 +1415,13 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pch_ctl1, pch_ctl2, val; + bool alt; + + if (HAS_PCH_LPT(dev_priv)) + alt = I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; + else + alt = I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; + panel->backlight.alternate_pwm_increment = alt; pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; -- cgit v1.2.3 From e29aff05f239f8dd24e9ee7816fd96726e20105a Mon Sep 17 00:00:00 2001 From: Shawn Lee Date: Mon, 19 Sep 2016 13:35:26 +0300 Subject: drm/i915/backlight: setup backlight pwm alternate increment on backlight enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backlight enable is supposed to do a full setup of the backlight. We were missing the PWM alternate increment bit in the south chicken registers on lpt+ pch. This potentially caused a PWM frequency change when the chicken register value was lost e.g. on suspend. v2 by Jani, rebase on the patch caching alt increment Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97486 References: https://bugs.freedesktop.org/show_bug.cgi?id=67454 Cc: Cooper Chiou Cc: Wei Shun Chen Cc: Gary C Wang Cc: stable@vger.kernel.org # v4.4+ 32b421e79e6b drm/i915/backlight: setup and cache... Cc: stable@vger.kernel.org # v4.4+ Reviewed-by: Ville Syrjälä Signed-off-by: Shawn Lee Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/8265f5935bd31c039ddfc82819d26c2ca1ae9cba.1474281249.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_panel.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 8bc43205d6a0..be4b4d546fd9 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -841,7 +841,7 @@ static void lpt_enable_backlight(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - u32 pch_ctl1, pch_ctl2; + u32 pch_ctl1, pch_ctl2, schicken; pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { @@ -850,6 +850,22 @@ static void lpt_enable_backlight(struct intel_connector *connector) I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); } + if (HAS_PCH_LPT(dev_priv)) { + schicken = I915_READ(SOUTH_CHICKEN2); + if (panel->backlight.alternate_pwm_increment) + schicken |= LPT_PWM_GRANULARITY; + else + schicken &= ~LPT_PWM_GRANULARITY; + I915_WRITE(SOUTH_CHICKEN2, schicken); + } else { + schicken = I915_READ(SOUTH_CHICKEN1); + if (panel->backlight.alternate_pwm_increment) + schicken |= SPT_PWM_GRANULARITY; + else + schicken &= ~SPT_PWM_GRANULARITY; + I915_WRITE(SOUTH_CHICKEN1, schicken); + } + pch_ctl2 = panel->backlight.max << 16; I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); -- cgit v1.2.3 From 51f592050a523fc5882f9b8b4e9259422e41e848 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 14 Sep 2016 13:04:13 +0300 Subject: drm/i915: Unlock PPS registers after GPU reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reapply the PPS register unlock workaround after GPU reset on platforms where the reset clobbers the display HW state. This at least gets rid of the related WARN during LVDS encoder enabling on PNV. Fixes: ed6143b8f75 ("drm/i915/lvds: Restore initial HW state during encoder enabling") Reported-by: Ville Syrjälä Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1473847453-4771-1-git-send-email-imre.deak@intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 69b80d078f06..18fdbb7f6c28 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3627,6 +3627,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) intel_runtime_pm_disable_interrupts(dev_priv); intel_runtime_pm_enable_interrupts(dev_priv); + intel_pps_unlock_regs_wa(dev_priv); intel_modeset_init_hw(dev); spin_lock_irq(&dev_priv->irq_lock); -- cgit v1.2.3 From d636951ec01bcb2b7dee02f75ff4815714785a53 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 20 Sep 2016 16:54:32 +0300 Subject: drm/i915: Cleanup instdone collection Consolidate the instdone logic so we can get a bit fancier. This patch also removes the duplicated print of INSTDONE[0]. v2: (Imre) - Rebased on top of hangcheck INSTDONE changes. - Move all INSTDONE registers into a single struct, store it within the engine error struct during error capturing. Signed-off-by: Ben Widawsky Signed-off-by: Imre Deak Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1474379673-28326-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 41 +++++++++++----- drivers/gpu/drm/i915/i915_drv.h | 8 ++-- drivers/gpu/drm/i915/i915_gpu_error.c | 84 +++++++++++++++++++++++---------- drivers/gpu/drm/i915/i915_irq.c | 69 ++++++++++++++++++--------- drivers/gpu/drm/i915/i915_reg.h | 1 - drivers/gpu/drm/i915/intel_ringbuffer.h | 10 +++- 6 files changed, 151 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a6d174ac6652..ba155c038d0e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1277,15 +1277,36 @@ out: return ret; } +static void i915_instdone_info(struct drm_i915_private *dev_priv, + struct seq_file *m, + struct intel_instdone *instdone) +{ + seq_printf(m, "\t\tINSTDONE: 0x%08x\n", + instdone->instdone); + + if (INTEL_GEN(dev_priv) <= 3) + return; + + seq_printf(m, "\t\tSC_INSTDONE: 0x%08x\n", + instdone->slice_common); + + if (INTEL_GEN(dev_priv) <= 6) + return; + + seq_printf(m, "\t\tSAMPLER_INSTDONE: 0x%08x\n", + instdone->sampler); + seq_printf(m, "\t\tROW_INSTDONE: 0x%08x\n", + instdone->row); +} + static int i915_hangcheck_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_engine_cs *engine; u64 acthd[I915_NUM_ENGINES]; u32 seqno[I915_NUM_ENGINES]; - u32 instdone[I915_NUM_INSTDONE_REG]; + struct intel_instdone instdone; enum intel_engine_id id; - int j; if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) seq_printf(m, "Wedged\n"); @@ -1308,7 +1329,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seqno[id] = intel_engine_get_seqno(engine); } - i915_get_extra_instdone(dev_priv, instdone); + i915_get_engine_instdone(dev_priv, RCS, &instdone); intel_runtime_pm_put(dev_priv); @@ -1336,18 +1357,14 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seq_printf(m, "\taction = %d\n", engine->hangcheck.action); if (engine->id == RCS) { - seq_puts(m, "\tinstdone read ="); - - for (j = 0; j < I915_NUM_INSTDONE_REG; j++) - seq_printf(m, " 0x%08x", instdone[j]); + seq_puts(m, "\tinstdone read =\n"); - seq_puts(m, "\n\tinstdone accu ="); + i915_instdone_info(dev_priv, m, &instdone); - for (j = 0; j < I915_NUM_INSTDONE_REG; j++) - seq_printf(m, " 0x%08x", - engine->hangcheck.instdone[j]); + seq_puts(m, "\tinstdone accu =\n"); - seq_puts(m, "\n"); + i915_instdone_info(dev_priv, m, + &engine->hangcheck.instdone); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4dd307ed4336..356899543d4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -759,7 +759,7 @@ struct drm_i915_error_state { u32 gam_ecochk; u32 gab_ctl; u32 gfx_mode; - u32 extra_instdone[I915_NUM_INSTDONE_REG]; + u64 fence[I915_MAX_NUM_FENCES]; struct intel_overlay_error_state *overlay; struct intel_display_error_state *display; @@ -791,7 +791,6 @@ struct drm_i915_error_state { u32 hws; u32 ipeir; u32 ipehr; - u32 instdone; u32 bbstate; u32 instpm; u32 instps; @@ -802,6 +801,7 @@ struct drm_i915_error_state { u64 faddr; u32 rc_psmi; /* sleep state */ u32 semaphore_mboxes[I915_NUM_ENGINES - 1]; + struct intel_instdone instdone; struct drm_i915_error_object { int page_count; @@ -3542,7 +3542,9 @@ void i915_error_state_get(struct drm_device *dev, void i915_error_state_put(struct i915_error_state_file_priv *error_priv); void i915_destroy_error_state(struct drm_device *dev); -void i915_get_extra_instdone(struct drm_i915_private *dev_priv, uint32_t *instdone); +void i915_get_engine_instdone(struct drm_i915_private *dev_priv, + enum intel_engine_id engine_id, + struct intel_instdone *instdone); const char *i915_cache_level_str(struct drm_i915_private *i915, int type); /* i915_cmd_parser.c */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 334f15df7c8d..6a2775aad354 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -228,6 +228,27 @@ static const char *hangcheck_action_to_str(enum intel_engine_hangcheck_action a) return "unknown"; } +static void error_print_instdone(struct drm_i915_error_state_buf *m, + struct drm_i915_error_engine *ee) +{ + err_printf(m, " INSTDONE: 0x%08x\n", + ee->instdone.instdone); + + if (ee->engine_id != RCS || INTEL_GEN(m->i915) <= 3) + return; + + err_printf(m, " SC_INSTDONE: 0x%08x\n", + ee->instdone.slice_common); + + if (INTEL_GEN(m->i915) <= 6) + return; + + err_printf(m, " SAMPLER_INSTDONE: 0x%08x\n", + ee->instdone.sampler); + err_printf(m, " ROW_INSTDONE: 0x%08x\n", + ee->instdone.row); +} + static void error_print_engine(struct drm_i915_error_state_buf *m, struct drm_i915_error_engine *ee) { @@ -242,7 +263,9 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, (u32)(ee->acthd>>32), (u32)ee->acthd); err_printf(m, " IPEIR: 0x%08x\n", ee->ipeir); err_printf(m, " IPEHR: 0x%08x\n", ee->ipehr); - err_printf(m, " INSTDONE: 0x%08x\n", ee->instdone); + + error_print_instdone(m, ee); + if (ee->batchbuffer) { u64 start = ee->batchbuffer->gtt_offset; u64 end = start + ee->batchbuffer->gtt_size; @@ -402,10 +425,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, for (i = 0; i < dev_priv->num_fence_regs; i++) err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); - for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++) - err_printf(m, " INSTDONE_%d: 0x%08x\n", i, - error->extra_instdone[i]); - if (INTEL_INFO(dev)->gen >= 6) { err_printf(m, "ERROR: 0x%08x\n", error->error); @@ -855,7 +874,8 @@ static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv, if (engine_id) *engine_id = i; - return error->engine[i].ipehr ^ error->engine[i].instdone; + return error->engine[i].ipehr ^ + error->engine[i].instdone.instdone; } } @@ -998,7 +1018,6 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base)); ee->ipeir = I915_READ(RING_IPEIR(engine->mmio_base)); ee->ipehr = I915_READ(RING_IPEHR(engine->mmio_base)); - ee->instdone = I915_READ(RING_INSTDONE(engine->mmio_base)); ee->instps = I915_READ(RING_INSTPS(engine->mmio_base)); ee->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); if (INTEL_GEN(dev_priv) >= 8) { @@ -1010,9 +1029,10 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->faddr = I915_READ(DMA_FADD_I8XX); ee->ipeir = I915_READ(IPEIR); ee->ipehr = I915_READ(IPEHR); - ee->instdone = I915_READ(GEN2_INSTDONE); } + i915_get_engine_instdone(dev_priv, engine->id, &ee->instdone); + ee->waiting = intel_engine_has_waiter(engine); ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); ee->acthd = intel_engine_get_active_head(engine); @@ -1372,8 +1392,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, } error->eir = I915_READ(EIR); error->pgtbl_er = I915_READ(PGTBL_ER); - - i915_get_extra_instdone(dev_priv, error->extra_instdone); } static void i915_error_capture_msg(struct drm_i915_private *dev_priv, @@ -1532,20 +1550,38 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type) } /* NB: please notice the memset */ -void i915_get_extra_instdone(struct drm_i915_private *dev_priv, - uint32_t *instdone) +void i915_get_engine_instdone(struct drm_i915_private *dev_priv, + enum intel_engine_id engine_id, + struct intel_instdone *instdone) { - memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG); - - if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv)) - instdone[0] = I915_READ(GEN2_INSTDONE); - else if (IS_GEN4(dev_priv) || IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) { - instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE)); - instdone[1] = I915_READ(GEN4_INSTDONE1); - } else if (INTEL_GEN(dev_priv) >= 7) { - instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE)); - instdone[1] = I915_READ(GEN7_SC_INSTDONE); - instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); - instdone[3] = I915_READ(GEN7_ROW_INSTDONE); + u32 mmio_base = dev_priv->engine[engine_id].mmio_base; + + memset(instdone, 0, sizeof(*instdone)); + + switch (INTEL_GEN(dev_priv)) { + default: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine_id != RCS) + break; + + instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); + instdone->sampler = I915_READ(GEN7_SAMPLER_INSTDONE); + instdone->row = I915_READ(GEN7_ROW_INSTDONE); + + break; + case 6: + case 5: + case 4: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine_id == RCS) + /* HACK: Using the wrong struct member */ + instdone->slice_common = I915_READ(GEN4_INSTDONE1); + break; + case 3: + case 2: + instdone->instdone = I915_READ(GEN2_INSTDONE); + break; } } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c128fdbd24e4..371647c4c53c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2545,18 +2545,36 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) wake_up_all(&dev_priv->gpu_error.reset_queue); } +static inline void +i915_err_print_instdone(struct drm_i915_private *dev_priv, + struct intel_instdone *instdone) +{ + pr_err(" INSTDONE: 0x%08x\n", instdone->instdone); + + if (INTEL_GEN(dev_priv) <= 3) + return; + + pr_err(" SC_INSTDONE: 0x%08x\n", instdone->slice_common); + + if (INTEL_GEN(dev_priv) <= 6) + return; + + pr_err(" SAMPLER_INSTDONE: 0x%08x\n", instdone->sampler); + pr_err(" ROW_INSTDONE: 0x%08x\n", instdone->row); +} + static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) { - uint32_t instdone[I915_NUM_INSTDONE_REG]; + struct intel_instdone instdone; u32 eir = I915_READ(EIR); - int pipe, i; + int pipe; if (!eir) return; pr_err("render error detected, EIR: 0x%08x\n", eir); - i915_get_extra_instdone(dev_priv, instdone); + i915_get_engine_instdone(dev_priv, RCS, &instdone); if (IS_G4X(dev_priv)) { if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) { @@ -2564,8 +2582,7 @@ static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965)); pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965)); - for (i = 0; i < ARRAY_SIZE(instdone); i++) - pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]); + i915_err_print_instdone(dev_priv, &instdone); pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS)); pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965)); I915_WRITE(IPEIR_I965, ipeir); @@ -2600,8 +2617,7 @@ static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) if (eir & I915_ERROR_INSTRUCTION) { pr_err("instruction error\n"); pr_err(" INSTPM: 0x%08x\n", I915_READ(INSTPM)); - for (i = 0; i < ARRAY_SIZE(instdone); i++) - pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]); + i915_err_print_instdone(dev_priv, &instdone); if (INTEL_GEN(dev_priv) < 4) { u32 ipeir = I915_READ(IPEIR); @@ -2948,31 +2964,42 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) engine->hangcheck.deadlock = 0; } +static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone) +{ + u32 tmp = current_instdone | *old_instdone; + bool unchanged; + + unchanged = tmp == *old_instdone; + *old_instdone |= tmp; + + return unchanged; +} + static bool subunits_stuck(struct intel_engine_cs *engine) { - u32 instdone[I915_NUM_INSTDONE_REG]; + struct drm_i915_private *dev_priv = engine->i915; + struct intel_instdone instdone; + struct intel_instdone *accu_instdone = &engine->hangcheck.instdone; bool stuck; - int i; if (engine->id != RCS) return true; - i915_get_extra_instdone(engine->i915, instdone); + i915_get_engine_instdone(dev_priv, RCS, &instdone); /* There might be unstable subunit states even when * actual head is not moving. Filter out the unstable ones by * accumulating the undone -> done transitions and only * consider those as progress. */ - stuck = true; - for (i = 0; i < I915_NUM_INSTDONE_REG; i++) { - const u32 tmp = instdone[i] | engine->hangcheck.instdone[i]; - - if (tmp != engine->hangcheck.instdone[i]) - stuck = false; - - engine->hangcheck.instdone[i] |= tmp; - } + stuck = instdone_unchanged(instdone.instdone, + &accu_instdone->instdone); + stuck &= instdone_unchanged(instdone.slice_common, + &accu_instdone->slice_common); + stuck &= instdone_unchanged(instdone.sampler, + &accu_instdone->sampler); + stuck &= instdone_unchanged(instdone.row, + &accu_instdone->row); return stuck; } @@ -2983,7 +3010,7 @@ head_stuck(struct intel_engine_cs *engine, u64 acthd) if (acthd != engine->hangcheck.acthd) { /* Clear subunit states on head movement */ - memset(engine->hangcheck.instdone, 0, + memset(&engine->hangcheck.instdone, 0, sizeof(engine->hangcheck.instdone)); return HANGCHECK_ACTIVE; @@ -3153,7 +3180,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) /* Clear head and subunit states on seqno movement */ acthd = 0; - memset(engine->hangcheck.instdone, 0, + memset(&engine->hangcheck.instdone, 0, sizeof(engine->hangcheck.instdone)); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 70d96162def6..41331455a111 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1708,7 +1708,6 @@ enum skl_disp_power_wells { #define GEN7_SC_INSTDONE _MMIO(0x7100) #define GEN7_SAMPLER_INSTDONE _MMIO(0xe160) #define GEN7_ROW_INSTDONE _MMIO(0xe164) -#define I915_NUM_INSTDONE_REG 4 #define RING_IPEIR(base) _MMIO((base)+0x64) #define RING_IPEHR(base) _MMIO((base)+0x68) /* diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 7f64d611159b..4ff47023e68d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -73,13 +73,21 @@ enum intel_engine_hangcheck_action { #define HANGCHECK_SCORE_RING_HUNG 31 +struct intel_instdone { + u32 instdone; + /* The following exist only in the RCS engine */ + u32 slice_common; + u32 sampler; + u32 row; +}; + struct intel_engine_hangcheck { u64 acthd; u32 seqno; int score; enum intel_engine_hangcheck_action action; int deadlock; - u32 instdone[I915_NUM_INSTDONE_REG]; + struct intel_instdone instdone; }; struct intel_ring { -- cgit v1.2.3 From f9e613728090e7fe4e755bf56df17cbc277bac3f Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 20 Sep 2016 16:54:33 +0300 Subject: drm/i915: Try to print INSTDONE bits for all slice/subslice v2: (Imre) - Access only subslices that are known to exist. - Reset explicitly the MCR selector to slice/sub-slice ID 0 after the readout. - Use the subslice INSTDONE bits for the hangcheck/subunits-stuck detection too. - Take the uncore lock for the MCR-select/subslice-readout sequence. Signed-off-by: Ben Widawsky Signed-off-by: Imre Deak Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1474379673-28326-2-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 14 ++++-- drivers/gpu/drm/i915/i915_gpu_error.c | 76 ++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/i915_irq.c | 25 ++++++++--- drivers/gpu/drm/i915/i915_reg.h | 5 +++ drivers/gpu/drm/i915/intel_ringbuffer.h | 23 +++++++++- 5 files changed, 125 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ba155c038d0e..d3f83c5ab70b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1281,6 +1281,9 @@ static void i915_instdone_info(struct drm_i915_private *dev_priv, struct seq_file *m, struct intel_instdone *instdone) { + int slice; + int subslice; + seq_printf(m, "\t\tINSTDONE: 0x%08x\n", instdone->instdone); @@ -1293,10 +1296,13 @@ static void i915_instdone_info(struct drm_i915_private *dev_priv, if (INTEL_GEN(dev_priv) <= 6) return; - seq_printf(m, "\t\tSAMPLER_INSTDONE: 0x%08x\n", - instdone->sampler); - seq_printf(m, "\t\tROW_INSTDONE: 0x%08x\n", - instdone->row); + for_each_instdone_slice_subslice(dev_priv, slice, subslice) + seq_printf(m, "\t\tSAMPLER_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, instdone->sampler[slice][subslice]); + + for_each_instdone_slice_subslice(dev_priv, slice, subslice) + seq_printf(m, "\t\tROW_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, instdone->row[slice][subslice]); } static int i915_hangcheck_info(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 6a2775aad354..2bbab226a46c 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -231,6 +231,9 @@ static const char *hangcheck_action_to_str(enum intel_engine_hangcheck_action a) static void error_print_instdone(struct drm_i915_error_state_buf *m, struct drm_i915_error_engine *ee) { + int slice; + int subslice; + err_printf(m, " INSTDONE: 0x%08x\n", ee->instdone.instdone); @@ -243,10 +246,15 @@ static void error_print_instdone(struct drm_i915_error_state_buf *m, if (INTEL_GEN(m->i915) <= 6) return; - err_printf(m, " SAMPLER_INSTDONE: 0x%08x\n", - ee->instdone.sampler); - err_printf(m, " ROW_INSTDONE: 0x%08x\n", - ee->instdone.row); + for_each_instdone_slice_subslice(m->i915, slice, subslice) + err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, + ee->instdone.sampler[slice][subslice]); + + for_each_instdone_slice_subslice(m->i915, slice, subslice) + err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, + ee->instdone.row[slice][subslice]); } static void error_print_engine(struct drm_i915_error_state_buf *m, @@ -1549,12 +1557,52 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type) } } +static inline uint32_t +read_subslice_reg(struct drm_i915_private *dev_priv, int slice, + int subslice, i915_reg_t reg) +{ + uint32_t mcr; + uint32_t ret; + enum forcewake_domains fw_domains; + + fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, + FW_REG_READ); + fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, + GEN8_MCR_SELECTOR, + FW_REG_READ | FW_REG_WRITE); + + spin_lock_irq(&dev_priv->uncore.lock); + intel_uncore_forcewake_get__locked(dev_priv, fw_domains); + + mcr = I915_READ_FW(GEN8_MCR_SELECTOR); + /* + * The HW expects the slice and sublice selectors to be reset to 0 + * after reading out the registers. + */ + WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); + mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); + mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); + I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); + + ret = I915_READ_FW(reg); + + mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); + I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); + + intel_uncore_forcewake_put__locked(dev_priv, fw_domains); + spin_unlock_irq(&dev_priv->uncore.lock); + + return ret; +} + /* NB: please notice the memset */ void i915_get_engine_instdone(struct drm_i915_private *dev_priv, enum intel_engine_id engine_id, struct intel_instdone *instdone) { u32 mmio_base = dev_priv->engine[engine_id].mmio_base; + int slice; + int subslice; memset(instdone, 0, sizeof(*instdone)); @@ -1566,8 +1614,24 @@ void i915_get_engine_instdone(struct drm_i915_private *dev_priv, break; instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); - instdone->sampler = I915_READ(GEN7_SAMPLER_INSTDONE); - instdone->row = I915_READ(GEN7_ROW_INSTDONE); + for_each_instdone_slice_subslice(dev_priv, slice, subslice) { + instdone->sampler[slice][subslice] = + read_subslice_reg(dev_priv, slice, subslice, + GEN7_SAMPLER_INSTDONE); + instdone->row[slice][subslice] = + read_subslice_reg(dev_priv, slice, subslice, + GEN7_ROW_INSTDONE); + } + break; + case 7: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine_id != RCS) + break; + + instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); + instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); + instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); break; case 6: diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 371647c4c53c..a5c02f6ea6a0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2549,6 +2549,9 @@ static inline void i915_err_print_instdone(struct drm_i915_private *dev_priv, struct intel_instdone *instdone) { + int slice; + int subslice; + pr_err(" INSTDONE: 0x%08x\n", instdone->instdone); if (INTEL_GEN(dev_priv) <= 3) @@ -2559,8 +2562,13 @@ i915_err_print_instdone(struct drm_i915_private *dev_priv, if (INTEL_GEN(dev_priv) <= 6) return; - pr_err(" SAMPLER_INSTDONE: 0x%08x\n", instdone->sampler); - pr_err(" ROW_INSTDONE: 0x%08x\n", instdone->row); + for_each_instdone_slice_subslice(dev_priv, slice, subslice) + pr_err(" SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, instdone->sampler[slice][subslice]); + + for_each_instdone_slice_subslice(dev_priv, slice, subslice) + pr_err(" ROW_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, instdone->row[slice][subslice]); } static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) @@ -2981,6 +2989,8 @@ static bool subunits_stuck(struct intel_engine_cs *engine) struct intel_instdone instdone; struct intel_instdone *accu_instdone = &engine->hangcheck.instdone; bool stuck; + int slice; + int subslice; if (engine->id != RCS) return true; @@ -2996,10 +3006,13 @@ static bool subunits_stuck(struct intel_engine_cs *engine) &accu_instdone->instdone); stuck &= instdone_unchanged(instdone.slice_common, &accu_instdone->slice_common); - stuck &= instdone_unchanged(instdone.sampler, - &accu_instdone->sampler); - stuck &= instdone_unchanged(instdone.row, - &accu_instdone->row); + + for_each_instdone_slice_subslice(dev_priv, slice, subslice) { + stuck &= instdone_unchanged(instdone.sampler[slice][subslice], + &accu_instdone->sampler[slice][subslice]); + stuck &= instdone_unchanged(instdone.row[slice][subslice], + &accu_instdone->row[slice][subslice]); + } return stuck; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 41331455a111..8d44cee710f0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1708,6 +1708,11 @@ enum skl_disp_power_wells { #define GEN7_SC_INSTDONE _MMIO(0x7100) #define GEN7_SAMPLER_INSTDONE _MMIO(0xe160) #define GEN7_ROW_INSTDONE _MMIO(0xe164) +#define GEN8_MCR_SELECTOR _MMIO(0xfdc) +#define GEN8_MCR_SLICE(slice) (((slice) & 3) << 26) +#define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3) +#define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24) +#define GEN8_MCR_SUBSLICE_MASK GEN8_MCR_SUBSLICE(3) #define RING_IPEIR(base) _MMIO((base)+0x64) #define RING_IPEHR(base) _MMIO((base)+0x68) /* diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 4ff47023e68d..66553bdb0a47 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -73,12 +73,31 @@ enum intel_engine_hangcheck_action { #define HANGCHECK_SCORE_RING_HUNG 31 +#define I915_MAX_SLICES 3 +#define I915_MAX_SUBSLICES 3 + +#define instdone_slice_mask(dev_priv__) \ + (INTEL_GEN(dev_priv__) == 7 ? \ + 1 : INTEL_INFO(dev_priv__)->sseu.slice_mask) + +#define instdone_subslice_mask(dev_priv__) \ + (INTEL_GEN(dev_priv__) == 7 ? \ + 1 : INTEL_INFO(dev_priv__)->sseu.subslice_mask) + +#define for_each_instdone_slice_subslice(dev_priv__, slice__, subslice__) \ + for ((slice__) = 0, (subslice__) = 0; \ + (slice__) < I915_MAX_SLICES; \ + (subslice__) = ((subslice__) + 1) < I915_MAX_SUBSLICES ? (subslice__) + 1 : 0, \ + (slice__) += ((subslice__) == 0)) \ + for_each_if((BIT(slice__) & instdone_slice_mask(dev_priv__)) && \ + (BIT(subslice__) & instdone_subslice_mask(dev_priv__))) + struct intel_instdone { u32 instdone; /* The following exist only in the RCS engine */ u32 slice_common; - u32 sampler; - u32 row; + u32 sampler[I915_MAX_SLICES][I915_MAX_SUBSLICES]; + u32 row[I915_MAX_SLICES][I915_MAX_SUBSLICES]; }; struct intel_engine_hangcheck { -- cgit v1.2.3 From 6277c8d07b8f1b667f672628f88b18e831e67517 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 20 Sep 2016 14:58:19 +0300 Subject: drm/i915: Queue page flip work via a low latency, unbound workqueue While user space has control over the scheduling priority of its page flipping thread, the corresponding work the driver schedules for MMIO flips always runs from the generic system workqueue which has some scheduling overhead due it being CPU bound. This would hinder an application that wants more stringent guarantees over flip timing (to avoid missing a flip at the next frame count). Fix this by scheduling the work from the unbound system workqueue which provides for minimal scheduling latency. v2: - Use an unbound workqueue instead of a high-prio one. (Tvrtko, Chris) v3: - Use the system unbound wq instead of a dedicated one. (Maarten) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97775 Testcase: igt/kms_cursor_legacy CC: Chris Wilson CC: Maarten Lankhorst CC: Tvrtko Ursulin Signed-off-by: Imre Deak Reviewed-by: Tvrtko Ursulin (v1) Reviewed-by: Chris Wilson Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1474372699-22841-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 18fdbb7f6c28..f7b2f8f609e7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12266,7 +12266,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->flip_queued_req = i915_gem_active_get(&obj->last_write, &obj->base.dev->struct_mutex); - schedule_work(&work->mmio_work); + queue_work(system_unbound_wq, &work->mmio_work); } else { request = i915_gem_request_alloc(engine, engine->last_context); if (IS_ERR(request)) { -- cgit v1.2.3 From f2a91d1a6f5960c08f1ca60bd076f4dc020c50c6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Sep 2016 14:51:06 +0100 Subject: drm/i915: Restore current RPS state after reset Following commit 821ed7df6e2a ("drm/i915: Update reset path to fix incomplete requests") we no longer mark the context as lost on reset as we keep the requests (and contexts) alive. However, RPS remains reset and we need to restore the current state to match the in-flight requests. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97824 Fixes: 821ed7df6e2a ("drm/i915: Update reset path to fix incomplete requests") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Cc: Arun Siluvery Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160921135108.29574-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 9 --------- drivers/gpu/drm/i915/i915_gem.c | 7 +++++++ drivers/gpu/drm/i915/i915_irq.c | 6 ++++++ 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7f4e8adec8a8..8ae5853ea3c6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1786,15 +1786,6 @@ void i915_reset(struct drm_i915_private *dev_priv) goto error; } - /* - * rps/rc6 re-init is necessary to restore state lost after the - * reset and the re-install of gt irqs. Skip for ironlake per - * previous concerns that it doesn't respond well to some forms - * of re-init after reset. - */ - intel_sanitize_gt_powersave(dev_priv); - intel_autoenable_gt_powersave(dev_priv); - wakeup: wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS); return; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c8bd02277b7d..aeb46658ab3c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2628,6 +2628,13 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) i915_gem_reset_engine(engine); i915_gem_restore_fences(&dev_priv->drm); + + if (dev_priv->gt.awake) { + intel_sanitize_gt_powersave(dev_priv); + intel_enable_gt_powersave(dev_priv); + if (INTEL_GEN(dev_priv) >= 6) + gen6_rps_busy(dev_priv); + } } static void nop_submit_request(struct drm_i915_gem_request *request) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a5c02f6ea6a0..f8c0beaadf30 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -350,6 +350,9 @@ void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) { + if (READ_ONCE(dev_priv->rps.interrupts_enabled)) + return; + spin_lock_irq(&dev_priv->irq_lock); WARN_ON_ONCE(dev_priv->rps.pm_iir); WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); @@ -368,6 +371,9 @@ u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask) void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) { + if (!READ_ONCE(dev_priv->rps.interrupts_enabled)) + return; + spin_lock_irq(&dev_priv->irq_lock); dev_priv->rps.interrupts_enabled = false; -- cgit v1.2.3 From 6a800eabba34945c2986d70114b41d564bad52a8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Sep 2016 14:51:07 +0100 Subject: drm/i915: Only shrink the unbound objects during freeze At the point of creating the hibernation image, the runtime power manage core is disabled - and using the rpm functions triggers a warn. i915_gem_shrink_all() tries to unbind objects, which requires device access and so tries to how an rpm reference triggering a warning: [ 44.235420] ------------[ cut here ]------------ [ 44.235424] WARNING: CPU: 2 PID: 2199 at drivers/gpu/drm/i915/intel_runtime_pm.c:2688 intel_runtime_pm_get_if_in_use+0xe6/0xf0 [ 44.235426] WARN_ON_ONCE(ret < 0) [ 44.235445] Modules linked in: ctr ccm arc4 rt2800usb rt2x00usb rt2800lib rt2x00lib crc_ccitt mac80211 cmac cfg80211 btusb rfcomm bnep btrtl btbcm btintel bluetooth dcdbas x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_realtek crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec_generic aesni_intel snd_hda_codec_hdmi aes_x86_64 lrw gf128mul snd_hda_intel glue_helper ablk_helper cryptd snd_hda_codec hid_multitouch joydev snd_hda_core binfmt_misc i2c_hid serio_raw snd_pcm acpi_pad snd_timer snd i2c_designware_platform 8250_dw nls_iso8859_1 i2c_designware_core lpc_ich mfd_core soundcore usbhid hid psmouse ahci libahci [ 44.235447] CPU: 2 PID: 2199 Comm: kworker/u8:8 Not tainted 4.8.0-rc5+ #130 [ 44.235447] Hardware name: Dell Inc. XPS 13 9343/0310JH, BIOS A07 11/11/2015 [ 44.235450] Workqueue: events_unbound async_run_entry_fn [ 44.235453] 0000000000000000 ffff8801b2f7fb98 ffffffff81306c2f ffff8801b2f7fbe8 [ 44.235454] 0000000000000000 ffff8801b2f7fbd8 ffffffff81056c01 00000a801f50ecc0 [ 44.235456] ffff88020ce50000 ffff88020ce59b60 ffffffff81a60b5c ffffffff81414840 [ 44.235456] Call Trace: [ 44.235459] [] dump_stack+0x4d/0x6e [ 44.235461] [] __warn+0xd1/0xf0 [ 44.235464] [] ? i915_pm_suspend_late+0x30/0x30 [ 44.235465] [] warn_slowpath_fmt+0x4f/0x60 [ 44.235468] [] ? pm_runtime_get_if_in_use+0x6e/0xa0 [ 44.235469] [] intel_runtime_pm_get_if_in_use+0xe6/0xf0 [ 44.235471] [] i915_gem_shrink+0x306/0x360 [ 44.235473] [] ? pci_platform_power_transition+0x24/0x90 [ 44.235475] [] ? i915_pm_suspend_late+0x30/0x30 [ 44.235476] [] i915_gem_shrink_all+0x1b/0x30 [ 44.235478] [] i915_gem_freeze_late+0x33/0x90 [ 44.235479] [] i915_pm_freeze_late+0x37/0x40 [ 44.235481] [] dpm_run_callback+0x4e/0x130 [ 44.235483] [] __device_suspend_late+0xdb/0x1f0 [ 44.235484] [] async_suspend_late+0x1f/0xa0 [ 44.235486] [] async_run_entry_fn+0x37/0x150 [ 44.235488] [] process_one_work+0x148/0x3f0 [ 44.235490] [] worker_thread+0x12b/0x490 [ 44.235491] [] ? process_one_work+0x3f0/0x3f0 [ 44.235492] [] kthread+0xc9/0xe0 [ 44.235495] [] ret_from_fork+0x1f/0x40 [ 44.235496] [] ? kthread_park+0x60/0x60 [ 44.235497] ---[ end trace e438706b97c7f132 ]--- Alternatively, to actually shrink everything we have to do so slightly earlier in the hibernation process. To keep lockdep silent, we need to take struct_mutex for the shrinker even though we know that we are the only user during the freeze. Fixes: 7aab2d534e35 ("drm/i915: Shrink objects prior to hibernation") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160921135108.29574-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 12 +++++++++++- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8ae5853ea3c6..bfb2efd8d4d4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1863,7 +1863,17 @@ static int i915_pm_resume(struct device *kdev) /* freeze: before creating the hibernation_image */ static int i915_pm_freeze(struct device *kdev) { - return i915_pm_suspend(kdev); + int ret; + + ret = i915_pm_suspend(kdev); + if (ret) + return ret; + + ret = i915_gem_freeze(kdev_to_i915(kdev)); + if (ret) + return ret; + + return 0; } static int i915_pm_freeze_late(struct device *kdev) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 356899543d4b..008c74bfabad 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3076,6 +3076,7 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data, void i915_gem_load_init(struct drm_device *dev); void i915_gem_load_cleanup(struct drm_device *dev); void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); +int i915_gem_freeze(struct drm_i915_private *dev_priv); int i915_gem_freeze_late(struct drm_i915_private *dev_priv); void *i915_gem_object_alloc(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index aeb46658ab3c..1418c1c522cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4593,6 +4593,19 @@ void i915_gem_load_cleanup(struct drm_device *dev) rcu_barrier(); } +int i915_gem_freeze(struct drm_i915_private *dev_priv) +{ + intel_runtime_pm_get(dev_priv); + + mutex_lock(&dev_priv->drm.struct_mutex); + i915_gem_shrink_all(dev_priv); + mutex_unlock(&dev_priv->drm.struct_mutex); + + intel_runtime_pm_put(dev_priv); + + return 0; +} + int i915_gem_freeze_late(struct drm_i915_private *dev_priv) { struct drm_i915_gem_object *obj; @@ -4616,7 +4629,8 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) * the objects as well. */ - i915_gem_shrink_all(dev_priv); + mutex_lock(&dev_priv->drm.struct_mutex); + i915_gem_shrink(dev_priv, -1UL, I915_SHRINK_UNBOUND); for (p = phases; *p; p++) { list_for_each_entry(obj, *p, global_list) { @@ -4624,6 +4638,7 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) obj->base.write_domain = I915_GEM_DOMAIN_CPU; } } + mutex_unlock(&dev_priv->drm.struct_mutex); return 0; } -- cgit v1.2.3 From bafb2f7d4755bf1571bd5e9a03b97f3fc4fe69ae Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Sep 2016 14:51:08 +0100 Subject: drm/i915/execlists: Reset RING registers upon resume There is a disparity in the context image saved to disk and our own bookkeeping - that is we presume the RING_HEAD and RING_TAIL match our stored ce->ring->tail value. However, as we emit WA_TAIL_DWORDS into the ring but may not tell the GPU about them, the GPU may be lagging behind our bookkeeping. Upon hibernation we do not save stolen pages, presuming that their contents are volatile. This means that although we start writing into the ring at tail, the GPU starts executing from its HEAD and there may be some garbage in between and so the GPU promptly hangs upon resume. Testcase: igt/gem_exec_suspend/basic-S4 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96526 Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160921135108.29574-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 50 +++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 251143361f31..39417b77bff2 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2129,30 +2129,42 @@ error_deref_obj: void intel_lr_context_resume(struct drm_i915_private *dev_priv) { - struct i915_gem_context *ctx = dev_priv->kernel_context; struct intel_engine_cs *engine; + struct i915_gem_context *ctx; + + /* Because we emit WA_TAIL_DWORDS there may be a disparity + * between our bookkeeping in ce->ring->head and ce->ring->tail and + * that stored in context. As we only write new commands from + * ce->ring->tail onwards, everything before that is junk. If the GPU + * starts reading from its RING_HEAD from the context, it may try to + * execute that junk and die. + * + * So to avoid that we reset the context images upon resume. For + * simplicity, we just zero everything out. + */ + list_for_each_entry(ctx, &dev_priv->context_list, link) { + for_each_engine(engine, dev_priv) { + struct intel_context *ce = &ctx->engine[engine->id]; + u32 *reg; - for_each_engine(engine, dev_priv) { - struct intel_context *ce = &ctx->engine[engine->id]; - void *vaddr; - uint32_t *reg_state; - - if (!ce->state) - continue; - - vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB); - if (WARN_ON(IS_ERR(vaddr))) - continue; + if (!ce->state) + continue; - reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; + reg = i915_gem_object_pin_map(ce->state->obj, + I915_MAP_WB); + if (WARN_ON(IS_ERR(reg))) + continue; - reg_state[CTX_RING_HEAD+1] = 0; - reg_state[CTX_RING_TAIL+1] = 0; + reg += LRC_STATE_PN * PAGE_SIZE / sizeof(*reg); + reg[CTX_RING_HEAD+1] = 0; + reg[CTX_RING_TAIL+1] = 0; - ce->state->obj->dirty = true; - i915_gem_object_unpin_map(ce->state->obj); + ce->state->obj->dirty = true; + i915_gem_object_unpin_map(ce->state->obj); - ce->ring->head = 0; - ce->ring->tail = 0; + ce->ring->head = ce->ring->tail = 0; + ce->ring->last_retired_head = -1; + intel_ring_update_space(ce->ring); + } } } -- cgit v1.2.3 From 5748be60ea66a7f299fc28bf1ebe3f63a5a266e8 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 19 Sep 2016 18:24:37 -0700 Subject: drm/i915: Standardize port type for DVO encoders Changing the return type from 'char' to 'enum port' in intel_dvo_port_name() makes it easier to later move the port information to intel_encoder. In addition, the port type conforms to what we have elsewhere. Removing the last conditional that handles invalid port because dvo_reg is intialized to valid values for all DVO devices at definition. v2: Changed return type, for real (Jani) Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Lyude Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1474334681-22690-2-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_dvo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 2e452c505e7e..648975588cc2 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -412,16 +412,14 @@ intel_dvo_get_current_mode(struct drm_connector *connector) return mode; } -static char intel_dvo_port_name(i915_reg_t dvo_reg) +static enum port intel_dvo_port(i915_reg_t dvo_reg) { if (i915_mmio_reg_equal(dvo_reg, DVOA)) - return 'A'; + return PORT_A; else if (i915_mmio_reg_equal(dvo_reg, DVOB)) - return 'B'; - else if (i915_mmio_reg_equal(dvo_reg, DVOC)) - return 'C'; + return PORT_B; else - return '?'; + return PORT_C; } void intel_dvo_init(struct drm_device *dev) @@ -464,6 +462,7 @@ void intel_dvo_init(struct drm_device *dev) bool dvoinit; enum pipe pipe; uint32_t dpll[I915_MAX_PIPES]; + enum port port; /* Allow the I2C driver info to specify the GPIO to be used in * special cases, but otherwise default to what's defined @@ -511,9 +510,10 @@ void intel_dvo_init(struct drm_device *dev) if (!dvoinit) continue; + port = intel_dvo_port(dvo->dvo_reg); drm_encoder_init(dev, &intel_encoder->base, &intel_dvo_enc_funcs, encoder_type, - "DVO %c", intel_dvo_port_name(dvo->dvo_reg)); + "DVO %c", port_name(port)); intel_encoder->type = INTEL_OUTPUT_DVO; intel_encoder->crtc_mask = (1 << 0) | (1 << 1); -- cgit v1.2.3 From 03cdc1d4f79573a59392986fb4b50c55d47cff71 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 19 Sep 2016 18:24:38 -0700 Subject: drm/i915: Store port enum in intel_encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Storing the port enum in intel_encoder makes it convenient to know the port attached to an encoder. Moving the port information up from intel_digital_port to intel_encoder avoids unecessary intel_digital_port access and handles MST encoders cleanly without requiring conditional checks for them (thanks danvet). v2: Renamed the port enum member from 'attached_port' to 'port' (danvet) Fixed missing initialization of port in intel_sdvo.c (danvet) v3: Fixed missing initialization of port in intel_crt.c (Ville) v4: Storing port for DVO encoders too. Signed-off-by: Dhinakaran Pandiyan Cc: Daniel Vetter Cc: Ville Syrjälä Acked-by: Daniel Vetter Reviewed-by: Lyude Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1474334681-22690-3-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_crt.c | 2 ++ drivers/gpu/drm/i915/intel_ddi.c | 1 + drivers/gpu/drm/i915/intel_dp.c | 1 + drivers/gpu/drm/i915/intel_dp_mst.c | 1 + drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_dsi.c | 1 + drivers/gpu/drm/i915/intel_dvo.c | 2 ++ drivers/gpu/drm/i915/intel_hdmi.c | 1 + drivers/gpu/drm/i915/intel_lvds.c | 3 ++- drivers/gpu/drm/i915/intel_sdvo.c | 1 + drivers/gpu/drm/i915/intel_tv.c | 2 ++ 12 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 008c74bfabad..46462b181f5e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -185,6 +185,7 @@ enum plane { #define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites[(p)] + (s) + 'A') enum port { + PORT_NONE = -1, PORT_A = 0, PORT_B, PORT_C, diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index dfbcf16b41df..88ebbdde185a 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -917,10 +917,12 @@ void intel_crt_init(struct drm_device *dev) if (I915_HAS_HOTPLUG(dev)) crt->base.hpd_pin = HPD_CRT; if (HAS_DDI(dev)) { + crt->base.port = PORT_E; crt->base.get_config = hsw_crt_get_config; crt->base.get_hw_state = intel_ddi_get_hw_state; crt->base.post_disable = hsw_post_disable_crt; } else { + crt->base.port = PORT_NONE; crt->base.get_config = intel_crt_get_config; crt->base.get_hw_state = intel_crt_get_hw_state; } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 15d47c87def6..35f0b7c9d0a6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2520,6 +2520,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_dig_port->max_lanes = max_lanes; intel_encoder->type = INTEL_OUTPUT_UNKNOWN; + intel_encoder->port = port; intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index acd0c51f74d5..0568fb53b7cd 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5832,6 +5832,7 @@ bool intel_dp_init(struct drm_device *dev, intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); } intel_encoder->cloneable = 0; + intel_encoder->port = port; intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; dev_priv->hotplug.irq_port[port] = intel_dig_port; diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 54a9d7610d8f..3ffbd69e4551 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -523,6 +523,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe)); intel_encoder->type = INTEL_OUTPUT_DP_MST; + intel_encoder->port = intel_dig_port->port; intel_encoder->crtc_mask = 0x7; intel_encoder->cloneable = 0; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1b451e759976..14da0422fce8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -206,6 +206,7 @@ struct intel_encoder { struct drm_encoder base; enum intel_output_type type; + enum port port; unsigned int cloneable; void (*hot_plug)(struct intel_encoder *); bool (*compute_config)(struct intel_encoder *, diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index b2e3d3a334f7..727adaace96c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1488,6 +1488,7 @@ void intel_dsi_init(struct drm_device *dev) intel_connector->get_hw_state = intel_connector_get_hw_state; + intel_encoder->port = port; /* * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI * port C. BXT isn't limited like this. diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 648975588cc2..cd574900cd8d 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -516,7 +516,9 @@ void intel_dvo_init(struct drm_device *dev) "DVO %c", port_name(port)); intel_encoder->type = INTEL_OUTPUT_DVO; + intel_encoder->port = port; intel_encoder->crtc_mask = (1 << 0) | (1 << 1); + switch (dvo->type) { case INTEL_DVO_CHIP_TMDS: intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) | diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c51073f78730..8d49800064df 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1972,6 +1972,7 @@ void intel_hdmi_init(struct drm_device *dev, } intel_encoder->type = INTEL_OUTPUT_HDMI; + intel_encoder->port = port; if (IS_CHERRYVIEW(dev)) { if (port == PORT_D) intel_encoder->crtc_mask = 1 << 2; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 4987d972e60a..c44f074f54ae 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -1064,8 +1064,9 @@ void intel_lvds_init(struct drm_device *dev) intel_connector->get_hw_state = intel_connector_get_hw_state; intel_connector_attach_encoder(intel_connector, intel_encoder); - intel_encoder->type = INTEL_OUTPUT_LVDS; + intel_encoder->type = INTEL_OUTPUT_LVDS; + intel_encoder->port = PORT_NONE; intel_encoder->cloneable = 0; if (HAS_PCH_SPLIT(dev)) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c551024d4871..a061b0029797 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2981,6 +2981,7 @@ bool intel_sdvo_init(struct drm_device *dev, /* encoder type will be decided later */ intel_encoder = &intel_sdvo->base; intel_encoder->type = INTEL_OUTPUT_SDVO; + intel_encoder->port = port; drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0, "SDVO %c", port_name(port)); diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index d960e4866595..3988c45f9e5f 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1610,7 +1610,9 @@ intel_tv_init(struct drm_device *dev) intel_connector->get_hw_state = intel_connector_get_hw_state; intel_connector_attach_encoder(intel_connector, intel_encoder); + intel_encoder->type = INTEL_OUTPUT_TVOUT; + intel_encoder->port = PORT_NONE; intel_encoder->crtc_mask = (1 << 0) | (1 << 1); intel_encoder->cloneable = 0; intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1)); -- cgit v1.2.3 From d8dee42a3307901572e0730d9cac02f26635afed Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 19 Sep 2016 18:24:39 -0700 Subject: drm/i915: Switch to using port stored in intel_encoder Now that we have the port enum stored in intel_encoder, use that instead of dereferencing intel_dig_port. Saves us a few locals. struct intel_encoder variables have been renamed to be consistent and convey type information. v2: Fix incorrect 'enum port' member names - s/attached_port/port Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Lyude Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1474334681-22690-4-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index a421171bd2ed..11677659f08f 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -276,17 +276,15 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder) } static void hsw_audio_codec_enable(struct drm_connector *connector, - struct intel_encoder *encoder, + struct intel_encoder *intel_encoder, const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); enum pipe pipe = intel_crtc->pipe; + enum port port = intel_encoder->port; struct i915_audio_component *acomp = dev_priv->audio_component; const uint8_t *eld = connector->eld; - struct intel_digital_port *intel_dig_port = - enc_to_dig_port(&encoder->base); - enum port port = intel_dig_port->port; uint32_t tmp; int len, i; int n, rate; @@ -355,12 +353,12 @@ static void hsw_audio_codec_enable(struct drm_connector *connector, mutex_unlock(&dev_priv->av_mutex); } -static void ilk_audio_codec_disable(struct intel_encoder *encoder) +static void ilk_audio_codec_disable(struct intel_encoder *intel_encoder) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - enum port port = enc_to_dig_port(&encoder->base)->port; + struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); + struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); enum pipe pipe = intel_crtc->pipe; + enum port port = intel_encoder->port; uint32_t tmp, eldv; i915_reg_t aud_config, aud_cntrl_st2; @@ -400,13 +398,13 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder) } static void ilk_audio_codec_enable(struct drm_connector *connector, - struct intel_encoder *encoder, + struct intel_encoder *intel_encoder, const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - enum port port = enc_to_dig_port(&encoder->base)->port; + struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); enum pipe pipe = intel_crtc->pipe; + enum port port = intel_encoder->port; uint8_t *eld = connector->eld; uint32_t tmp, eldv; int len, i; @@ -490,11 +488,10 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; struct drm_connector *connector; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(encoder->dev); struct i915_audio_component *acomp = dev_priv->audio_component; struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); - enum port port = intel_dig_port->port; + enum port port = intel_encoder->port; connector = drm_select_eld(encoder); if (!connector) @@ -537,11 +534,10 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) void intel_audio_codec_disable(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(encoder->dev); struct i915_audio_component *acomp = dev_priv->audio_component; struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); - enum port port = intel_dig_port->port; + enum port port = intel_encoder->port; if (dev_priv->display.audio_codec_disable) dev_priv->display.audio_codec_disable(intel_encoder); -- cgit v1.2.3 From f1a3acea26f89de17399726e1451fc7bb5376573 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 19 Sep 2016 18:24:40 -0700 Subject: drm/i915: Move audio_connector to intel_encoder With DP MST, a digital_port can carry more than one audio stream. Hence, more than one audio_connector needs to be attached to intel_digital_port in such cases. However, each stream is associated with an unique encoder. So, instead of creating an array of audio_connectors per port, move audio_connector from struct intel_digital_port to struct intel_encoder. This also simplifies access to the right audio_connector from codec functions in intel_audio.c that receive intel_encoder. v2: Removed locals that are not needed anymore. v3: No code change except for minor change in context. Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Lyude Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1474334681-22690-5-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 12 ++++-------- drivers/gpu/drm/i915/intel_drv.h | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 11677659f08f..fb22a2bc85e6 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -490,7 +490,6 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) struct drm_connector *connector; struct drm_i915_private *dev_priv = to_i915(encoder->dev); struct i915_audio_component *acomp = dev_priv->audio_component; - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); enum port port = intel_encoder->port; connector = drm_select_eld(encoder); @@ -515,7 +514,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) adjusted_mode); mutex_lock(&dev_priv->av_mutex); - intel_dig_port->audio_connector = connector; + intel_encoder->audio_connector = connector; /* referred in audio callbacks */ dev_priv->dig_port_map[port] = intel_encoder; mutex_unlock(&dev_priv->av_mutex); @@ -536,14 +535,13 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder) struct drm_encoder *encoder = &intel_encoder->base; struct drm_i915_private *dev_priv = to_i915(encoder->dev); struct i915_audio_component *acomp = dev_priv->audio_component; - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); enum port port = intel_encoder->port; if (dev_priv->display.audio_codec_disable) dev_priv->display.audio_codec_disable(intel_encoder); mutex_lock(&dev_priv->av_mutex); - intel_dig_port->audio_connector = NULL; + intel_encoder->audio_connector = NULL; dev_priv->dig_port_map[port] = NULL; mutex_unlock(&dev_priv->av_mutex); @@ -704,7 +702,6 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_encoder *intel_encoder; - struct intel_digital_port *intel_dig_port; const u8 *eld; int ret = -EINVAL; @@ -713,10 +710,9 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, /* intel_encoder might be NULL for DP MST */ if (intel_encoder) { ret = 0; - intel_dig_port = enc_to_dig_port(&intel_encoder->base); - *enabled = intel_dig_port->audio_connector != NULL; + *enabled = intel_encoder->audio_connector != NULL; if (*enabled) { - eld = intel_dig_port->audio_connector->eld; + eld = intel_encoder->audio_connector->eld; ret = drm_eld_size(eld); memcpy(buf, eld, min(max_bytes, ret)); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 14da0422fce8..f56dad8f222e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -248,6 +248,8 @@ struct intel_encoder { void (*suspend)(struct intel_encoder *); int crtc_mask; enum hpd_pin hpd_pin; + /* for communication with audio component; protected by av_mutex */ + const struct drm_connector *audio_connector; }; struct intel_panel { @@ -960,8 +962,6 @@ struct intel_digital_port { enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool); bool release_cl2_override; uint8_t max_lanes; - /* for communication with audio component; protected by av_mutex */ - const struct drm_connector *audio_connector; }; struct intel_dp_mst_encoder { -- cgit v1.2.3 From 3708d5e082c39913b26bd06845ffe80a0b689e2a Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 19 Sep 2016 18:24:41 -0700 Subject: drm/i915: start adding dp mst audio (This patch is developed by Dave Airlie originally) This patch adds support for DP MST audio in i915. Enable audio codec when DP MST is enabled if has_audio flag is set. Disable audio codec when DP MST is disabled if has_audio flag is set. Another separated patches to support DP MST audio will be implemented in audio driver. v2: Rebased. Signed-off-by: Libin Yang Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Lyude Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1474334681-22690-6-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 19 ++++++++++++++++++- drivers/gpu/drm/i915/intel_ddi.c | 20 +++++++++++++++----- drivers/gpu/drm/i915/intel_dp_mst.c | 18 ++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 2 ++ 4 files changed, 53 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d3f83c5ab70b..3c6a06df3dc9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2888,6 +2888,20 @@ static void intel_dp_info(struct seq_file *m, &intel_dp->aux); } +static void intel_dp_mst_info(struct seq_file *m, + struct intel_connector *intel_connector) +{ + struct intel_encoder *intel_encoder = intel_connector->encoder; + struct intel_dp_mst_encoder *intel_mst = + enc_to_mst(&intel_encoder->base); + struct intel_digital_port *intel_dig_port = intel_mst->primary; + struct intel_dp *intel_dp = &intel_dig_port->dp; + bool has_audio = drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, + intel_connector->port); + + seq_printf(m, "\taudio support: %s\n", yesno(has_audio)); +} + static void intel_hdmi_info(struct seq_file *m, struct intel_connector *intel_connector) { @@ -2930,7 +2944,10 @@ static void intel_connector_info(struct seq_file *m, switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_eDP: - intel_dp_info(m, intel_connector); + if (intel_encoder->type == INTEL_OUTPUT_DP_MST) + intel_dp_mst_info(m, intel_connector); + else + intel_dp_info(m, intel_connector); break; case DRM_MODE_CONNECTOR_LVDS: if (intel_encoder->type == INTEL_OUTPUT_LVDS) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 35f0b7c9d0a6..07cba6c0b1b5 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2227,6 +2227,19 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) udelay(600); } +bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, + struct intel_crtc *intel_crtc) +{ + u32 temp; + + if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { + temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); + if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) + return true; + } + return false; +} + void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -2292,11 +2305,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, break; } - if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { - temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); - if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) - pipe_config->has_audio = true; - } + pipe_config->has_audio = + intel_ddi_is_audio_enabled(dev_priv, intel_crtc); if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.bpp && pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 3ffbd69e4551..2fc9f81fdd41 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -37,6 +37,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; struct intel_dp *intel_dp = &intel_dig_port->dp; + struct intel_connector *connector = + to_intel_connector(conn_state->connector); struct drm_atomic_state *state; int bpp; int lane_count, slots; @@ -59,6 +61,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, state = pipe_config->base.state; + if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, connector->port)) + pipe_config->has_audio = true; mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp); pipe_config->pbn = mst_pbn; @@ -84,6 +88,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, struct intel_dp *intel_dp = &intel_dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int ret; DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); @@ -94,6 +99,10 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, if (ret) { DRM_ERROR("failed to update payload %d\n", ret); } + if (old_crtc_state->has_audio) { + intel_audio_codec_disable(encoder); + intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); + } } static void intel_mst_post_disable_dp(struct intel_encoder *encoder, @@ -206,6 +215,12 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder, ret = drm_dp_check_act_status(&intel_dp->mst_mgr); ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr); + if (pipe_config->has_audio) { + DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", + pipe_name(intel_mst->pipe)); + intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); + intel_audio_codec_enable(encoder); + } } static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder, @@ -228,6 +243,9 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder, enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; u32 temp, flags = 0; + pipe_config->has_audio = + intel_ddi_is_audio_enabled(dev_priv, crtc); + temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) flags |= DRM_MODE_FLAG_PHSYNC; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f56dad8f222e..5e9c15e5e58d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1156,6 +1156,8 @@ bool intel_ddi_pll_select(struct intel_crtc *crtc, void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp); bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); +bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, + struct intel_crtc *intel_crtc); void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); struct intel_encoder * -- cgit v1.2.3 From efab0698f94dd71fac5d946ad664a280441daedb Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 15 Sep 2016 16:28:54 +0300 Subject: drm/i915: keep declarations in i915_drv.h Fix sparse warnings: drivers/gpu/drm/i915/i915_drv.c:1179:5: warning: symbol 'i915_driver_load' was not declared. Should it be static? drivers/gpu/drm/i915/i915_drv.c:1267:6: warning: symbol 'i915_driver_unload' was not declared. Should it be static? drivers/gpu/drm/i915/i915_drv.c:2444:25: warning: symbol 'i915_pm_ops' was not declared. Should it be static? Fixes: 42f5551d2769 ("drm/i915: Split out the PCI driver interface to i915_pci.c") Cc: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473946137-1931-3-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 5 +++++ drivers/gpu/drm/i915/i915_pci.c | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 46462b181f5e..98f52dab27d4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2886,6 +2886,11 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); #endif +extern const struct dev_pm_ops i915_pm_ops; + +extern int i915_driver_load(struct pci_dev *pdev, + const struct pci_device_id *ent); +extern void i915_driver_unload(struct drm_device *dev); extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); extern void i915_reset(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 687c768833b3..31e6edd08dd0 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -431,9 +431,6 @@ static const struct pci_device_id pciidlist[] = { }; MODULE_DEVICE_TABLE(pci, pciidlist); -extern int i915_driver_load(struct pci_dev *pdev, - const struct pci_device_id *ent); - static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct intel_device_info *intel_info = @@ -463,8 +460,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return i915_driver_load(pdev, ent); } -extern void i915_driver_unload(struct drm_device *dev); - static void i915_pci_remove(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); @@ -473,8 +468,6 @@ static void i915_pci_remove(struct pci_dev *pdev) drm_dev_unref(dev); } -extern const struct dev_pm_ops i915_pm_ops; - static struct pci_driver i915_pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, -- cgit v1.2.3 From f931894194b9395313d1c34f95ceb8d91f49790d Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Wed, 21 Sep 2016 13:02:48 -0700 Subject: drm/i915/dp: DP audio API changes for MST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DP MST provides the capability to send multiple video and audio streams through a single port. This requires the API's between i915 and audio drivers to distinguish between multiple audio capable displays that can be connected to a port. Currently only the port identity is shared in the APIs. This patch adds support for MST with an additional parameter 'int pipe'. The existing parameter 'port' does not change it's meaning. pipe = MST : display pipe that the stream originates from Non-MST : -1 Affected APIs: struct i915_audio_component_ops - int (*sync_audio_rate)(struct device *, int port, int rate); + int (*sync_audio_rate)(struct device *, int port, int pipe, + int rate); - int (*get_eld)(struct device *, int port, bool *enabled, - unsigned char *buf, int max_bytes); + int (*get_eld)(struct device *, int port, int pipe, + bool *enabled, unsigned char *buf, int max_bytes); struct i915_audio_component_audio_ops - void (*pin_eld_notify)(void *audio_ptr, int port); + void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); This patch makes dummy changes in the audio drivers (thanks Libin) for build to succeed. The audio side drivers will send the right 'pipe' values for MST in patches that will follow. v2: Renamed the new API parameter from 'dev_id' to 'pipe'. (Jim, Ville) Included Asoc driver API compatibility changes from Jeeja. Added WARN_ON() for invalid pipe in get_saved_encoder(). (Takashi) Added comment for av_enc_map[] definition. (Takashi) v3: Fixed logic error introduced while renaming 'dev_id' as 'pipe' (Ville) Renamed get_saved_encoder() to get_saved_enc() to reduce line length v4: Rebased. Parameter check for pipe < -1 values in get_saved_enc() (Ville) Switched to for_each_pipe() in get_saved_enc() (Ville) Renamed 'pipe' to 'dev_id' in audio side code (Takashi) v5: Included a comment for the dev_id arg. (Libin) Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Takashi Iwai Reviewed-by: Ville Syrjälä Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1474488168-2343-1-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/intel_audio.c | 94 ++++++++++++++++++++++++++------------ include/drm/i915_component.h | 6 +-- include/sound/hda_i915.h | 11 +++-- sound/hda/hdac_i915.c | 18 +++++--- sound/pci/hda/patch_hdmi.c | 7 +-- sound/soc/codecs/hdac_hdmi.c | 2 +- 7 files changed, 94 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 98f52dab27d4..e76dc41f683c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2080,7 +2080,8 @@ struct drm_i915_private { /* perform PHY state sanity checks? */ bool chv_phy_assert[2]; - struct intel_encoder *dig_port_map[I915_MAX_PORTS]; + /* Used to save the pipe-to-encoder mapping for audio */ + struct intel_encoder *av_enc_map[I915_MAX_PIPES]; /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index fb22a2bc85e6..1f168e27af10 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -491,6 +491,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) struct drm_i915_private *dev_priv = to_i915(encoder->dev); struct i915_audio_component *acomp = dev_priv->audio_component; enum port port = intel_encoder->port; + enum pipe pipe = crtc->pipe; connector = drm_select_eld(encoder); if (!connector) @@ -515,12 +516,18 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) mutex_lock(&dev_priv->av_mutex); intel_encoder->audio_connector = connector; + /* referred in audio callbacks */ - dev_priv->dig_port_map[port] = intel_encoder; + dev_priv->av_enc_map[pipe] = intel_encoder; mutex_unlock(&dev_priv->av_mutex); + /* audio drivers expect pipe = -1 to indicate Non-MST cases */ + if (intel_encoder->type != INTEL_OUTPUT_DP_MST) + pipe = -1; + if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) - acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port); + acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + (int) port, (int) pipe); } /** @@ -536,17 +543,24 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder) struct drm_i915_private *dev_priv = to_i915(encoder->dev); struct i915_audio_component *acomp = dev_priv->audio_component; enum port port = intel_encoder->port; + struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); + enum pipe pipe = crtc->pipe; if (dev_priv->display.audio_codec_disable) dev_priv->display.audio_codec_disable(intel_encoder); mutex_lock(&dev_priv->av_mutex); intel_encoder->audio_connector = NULL; - dev_priv->dig_port_map[port] = NULL; + dev_priv->av_enc_map[pipe] = NULL; mutex_unlock(&dev_priv->av_mutex); + /* audio drivers expect pipe = -1 to indicate Non-MST cases */ + if (intel_encoder->type != INTEL_OUTPUT_DP_MST) + pipe = -1; + if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) - acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port); + acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + (int) port, (int) pipe); } /** @@ -621,15 +635,40 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) return dev_priv->cdclk_freq; } -static int i915_audio_component_sync_audio_rate(struct device *kdev, - int port, int rate) +static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, + int port, int pipe) +{ + + if (WARN_ON(pipe >= I915_MAX_PIPES)) + return NULL; + + /* MST */ + if (pipe >= 0) + return dev_priv->av_enc_map[pipe]; + + /* Non-MST */ + for_each_pipe(dev_priv, pipe) { + struct intel_encoder *encoder; + + encoder = dev_priv->av_enc_map[pipe]; + if (encoder == NULL) + continue; + + if (port == encoder->port) + return encoder; + } + + return NULL; +} + +static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, + int pipe, int rate) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_encoder *intel_encoder; struct intel_crtc *crtc; struct drm_display_mode *mode; struct i915_audio_component *acomp = dev_priv->audio_component; - enum pipe pipe = INVALID_PIPE; u32 tmp; int n; int err = 0; @@ -643,25 +682,20 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, i915_audio_component_get_power(kdev); mutex_lock(&dev_priv->av_mutex); + /* 1. get the pipe */ - intel_encoder = dev_priv->dig_port_map[port]; - /* intel_encoder might be NULL for DP MST */ + intel_encoder = get_saved_enc(dev_priv, port, pipe); if (!intel_encoder || !intel_encoder->base.crtc || intel_encoder->type != INTEL_OUTPUT_HDMI) { - DRM_DEBUG_KMS("no valid port %c\n", port_name(port)); + DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port)); err = -ENODEV; goto unlock; } + + /* pipe passed from the audio driver will be -1 for Non-MST case */ crtc = to_intel_crtc(intel_encoder->base.crtc); pipe = crtc->pipe; - if (pipe == INVALID_PIPE) { - DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port)); - err = -ENODEV; - goto unlock; - } - DRM_DEBUG_KMS("pipe %c connects port %c\n", - pipe_name(pipe), port_name(port)); mode = &crtc->config->base.adjusted_mode; /* port must be valid now, otherwise the pipe will be invalid */ @@ -697,7 +731,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, } static int i915_audio_component_get_eld(struct device *kdev, int port, - bool *enabled, + int pipe, bool *enabled, unsigned char *buf, int max_bytes) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); @@ -706,16 +740,20 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, int ret = -EINVAL; mutex_lock(&dev_priv->av_mutex); - intel_encoder = dev_priv->dig_port_map[port]; - /* intel_encoder might be NULL for DP MST */ - if (intel_encoder) { - ret = 0; - *enabled = intel_encoder->audio_connector != NULL; - if (*enabled) { - eld = intel_encoder->audio_connector->eld; - ret = drm_eld_size(eld); - memcpy(buf, eld, min(max_bytes, ret)); - } + + intel_encoder = get_saved_enc(dev_priv, port, pipe); + if (!intel_encoder) { + DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port)); + mutex_unlock(&dev_priv->av_mutex); + return ret; + } + + ret = 0; + *enabled = intel_encoder->audio_connector != NULL; + if (*enabled) { + eld = intel_encoder->audio_connector->eld; + ret = drm_eld_size(eld); + memcpy(buf, eld, min(max_bytes, ret)); } mutex_unlock(&dev_priv->av_mutex); diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h index b46fa0ef3005..545c6e0fea7d 100644 --- a/include/drm/i915_component.h +++ b/include/drm/i915_component.h @@ -64,7 +64,7 @@ struct i915_audio_component_ops { * Called from audio driver. After audio driver sets the * sample rate, it will call this function to set n/cts */ - int (*sync_audio_rate)(struct device *, int port, int rate); + int (*sync_audio_rate)(struct device *, int port, int pipe, int rate); /** * @get_eld: fill the audio state and ELD bytes for the given port * @@ -77,7 +77,7 @@ struct i915_audio_component_ops { * Note that the returned size may be over @max_bytes. Then it * implies that only a part of ELD has been copied to the buffer. */ - int (*get_eld)(struct device *, int port, bool *enabled, + int (*get_eld)(struct device *, int port, int pipe, bool *enabled, unsigned char *buf, int max_bytes); }; @@ -97,7 +97,7 @@ struct i915_audio_component_audio_ops { * status accordingly (even when the HDA controller is in power save * mode). */ - void (*pin_eld_notify)(void *audio_ptr, int port); + void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); }; /** diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h index 796cabf6be5e..5ab972e116ec 100644 --- a/include/sound/hda_i915.h +++ b/include/sound/hda_i915.h @@ -10,8 +10,9 @@ int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); int snd_hdac_display_power(struct hdac_bus *bus, bool enable); void snd_hdac_i915_set_bclk(struct hdac_bus *bus); -int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int rate); -int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, + int dev_id, int rate); +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, bool *audio_enabled, char *buffer, int max_bytes); int snd_hdac_i915_init(struct hdac_bus *bus); int snd_hdac_i915_exit(struct hdac_bus *bus); @@ -29,13 +30,13 @@ static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus) { } static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec, - hda_nid_t nid, int rate) + hda_nid_t nid, int dev_id, int rate) { return 0; } static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, - bool *audio_enabled, char *buffer, - int max_bytes) + int dev_id, bool *audio_enabled, + char *buffer, int max_bytes) { return -ENODEV; } diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index c9af022676c2..0659bf389489 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -193,6 +193,7 @@ static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid) * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate * @codec: HDA codec * @nid: the pin widget NID + * @dev_id: device identifier * @rate: the sample rate to set * * This function is supposed to be used only by a HD-audio controller @@ -201,18 +202,20 @@ static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid) * This function sets N/CTS value based on the given sample rate. * Returns zero for success, or a negative error code. */ -int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int rate) +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, + int dev_id, int rate) { struct hdac_bus *bus = codec->bus; struct i915_audio_component *acomp = bus->audio_component; - int port; + int port, pipe; if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) return -ENODEV; port = pin2port(codec, nid); if (port < 0) return -EINVAL; - return acomp->ops->sync_audio_rate(acomp->dev, port, rate); + pipe = dev_id; + return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate); } EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); @@ -220,6 +223,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); * snd_hdac_acomp_get_eld - Get the audio state and ELD via component * @codec: HDA codec * @nid: the pin widget NID + * @dev_id: device identifier * @audio_enabled: the pointer to store the current audio state * @buffer: the buffer pointer to store ELD bytes * @max_bytes: the max bytes to be stored on @buffer @@ -236,12 +240,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); * thus it may be over @max_bytes. If it's over @max_bytes, it implies * that only a part of ELD bytes have been fetched. */ -int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, bool *audio_enabled, char *buffer, int max_bytes) { struct hdac_bus *bus = codec->bus; struct i915_audio_component *acomp = bus->audio_component; - int port; + int port, pipe; if (!acomp || !acomp->ops || !acomp->ops->get_eld) return -ENODEV; @@ -249,7 +253,9 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, port = pin2port(codec, nid); if (port < 0) return -EINVAL; - return acomp->ops->get_eld(acomp->dev, port, audio_enabled, + + pipe = dev_id; + return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled, buffer, max_bytes); } EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 56e5204ac9c1..cf9bc042fe96 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1485,7 +1485,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec, mutex_lock(&per_pin->lock); eld->monitor_present = false; - size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, + size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, -1, &eld->monitor_present, eld->eld_buffer, ELD_MAX_SIZE); if (size > 0) { @@ -1744,7 +1744,8 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, /* Call sync_audio_rate to set the N/CTS/M manually if necessary */ /* Todo: add DP1.2 MST audio support later */ if (codec_has_acomp(codec)) - snd_hdac_sync_audio_rate(&codec->core, pin_nid, runtime->rate); + snd_hdac_sync_audio_rate(&codec->core, pin_nid, -1, + runtime->rate); non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); mutex_lock(&per_pin->lock); @@ -2290,7 +2291,7 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg, snd_hda_codec_set_power_to_all(codec, fg, power_state); } -static void intel_pin_eld_notify(void *audio_ptr, int port) +static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) { struct hda_codec *codec = audio_ptr; int pin_nid; diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 4e181b270d95..dc0129b75a4b 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1368,7 +1368,7 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, return hdac_hdmi_init_dai_map(edev); } -static void hdac_hdmi_eld_notify_cb(void *aptr, int port) +static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) { struct hdac_ext_device *edev = aptr; struct hdac_hdmi_priv *hdmi = edev->private_data; -- cgit v1.2.3 From a1427af59977894d20b1b5ea61f4b2856c7d1833 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 22 Sep 2016 11:43:42 +0200 Subject: iio: accel: sca3000_core: avoid potentially uninitialized variable The newly added __sca3000_get_base_freq function handles all valid modes of the SCA3000_REG_ADDR_MODE register, but gcc notices that any other value (i.e. 0x00) causes the base_freq variable to not get initialized: drivers/staging/iio/accel/sca3000_core.c: In function 'sca3000_write_raw': drivers/staging/iio/accel/sca3000_core.c:527:23: error: 'base_freq' may be used uninitialized in this function [-Werror=maybe-uninitialized] This adds explicit error handling for unexpected register values, to ensure this cannot happen. Fixes: e0f3fc9b47e6 ("iio: accel: sca3000_core: implemented IIO_CHAN_INFO_SAMP_FREQ") Signed-off-by: Arnd Bergmann Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/sca3000_core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index d626125d7af9..564b36d4f648 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -468,6 +468,8 @@ static inline int __sca3000_get_base_freq(struct sca3000_state *st, case SCA3000_MEAS_MODE_OP_2: *base_freq = info->option_mode_2_freq; break; + default: + ret = -EINVAL; } error_ret: return ret; -- cgit v1.2.3 From 59dc1c8619e9f89987f36f03c5047fc2af642215 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 22 Sep 2016 11:42:30 +0200 Subject: iio:pressure: zpa2326: remove redundant "DEBUG" ifdef The -Wempty-body gcc warning triggers in the newly added zpa2326 driver: drivers/iio/pressure/zpa2326.c: In function 'zpa2326_dequeue_pressure': drivers/iio/pressure/zpa2326.c:578:3: error: suggest braces around empty body in an 'if' statement [-Werror=empty-body] The use of an empty statement behind 'if (...)' is harmless here, but it shows that the dev_dbg() macro is not used correctly: when the "DEBUG" macro is not set, dev_dbg() already defaults to a no-operation, though one that lets the compiler know that the arguments are used, and lets it check the format string. Fixing this also simplifies the driver. Fixes: 03b262f2bbf4 ("iio:pressure: initial zpa2326 barometer support") Signed-off-by: Arnd Bergmann Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/zpa2326.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index 19d2eb46fda6..c720c3ac0b9b 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -147,12 +147,8 @@ struct zpa2326_private { #define zpa2326_warn(_idev, _format, _arg...) \ dev_warn(_idev->dev.parent, _format, ##_arg) -#ifdef DEBUG #define zpa2326_dbg(_idev, _format, _arg...) \ dev_dbg(_idev->dev.parent, _format, ##_arg) -#else -#define zpa2326_dbg(_idev, _format, _arg...) -#endif bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg) { -- cgit v1.2.3 From 61a585d664c78274c53fe466ef1dd0408917fd74 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 13 Sep 2016 10:38:57 -0300 Subject: drm/i915/fbc: disable FBC on FIFO underruns Ever since I started working on FBC I was already aware that FBC can really amplify the FIFO underrun symptoms. On systems where FIFO underruns were harmless error messages, enabling FBC would cause the underruns to give black screens. We recently tried to enable FBC on Haswell and got reports of a system that would hang after some hours of uptime, and the first bad commit was the one that enabled FBC. We also observed that this system had FIFO underrun error messages on its dmesg. Although we don't have any evidence that fixing the underruns would solve the bug and make FBC work properly on this machine, IMHO it's better if we minimize the amount of possible problems by just giving up FBC whenever we detect an underrun. v2: New version, different implementation and commit message. v3: Clarify the fact that we run from an IRQ handler (Chris). v4: Also add the underrun_detected check at can_choose() to avoid misleading dmesg messages (DK). v5: Fix Engrish, use READ_ONCE on the unlocked read (Chris). Cc: Stefan Richter Cc: Lyude Cc: stevenhoneyman@gmail.com Cc: Dhinakaran Pandiyan Cc: Chris Wilson Signed-off-by: Paulo Zanoni Reviewed-by: Chris Wilson Reviewed-by: Dhinakaran Pandiyan Link: http://patchwork.freedesktop.org/patch/msgid/1473773937-19758-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_fbc.c | 67 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_fifo_underrun.c | 2 + 4 files changed, 73 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e76dc41f683c..c0f0f11752a2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -973,6 +973,9 @@ struct intel_fbc { bool enabled; bool active; + bool underrun_detected; + struct work_struct underrun_work; + struct intel_fbc_state_cache { struct { unsigned int mode_flags; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5e9c15e5e58d..6df0f2f2308a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1516,6 +1516,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, void intel_fbc_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin); void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); +void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv); /* intel_hdmi.c */ void intel_hdmi_init(struct drm_device *dev, i915_reg_t hdmi_reg, enum port port); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index faa67624e1ed..617189ae04b4 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -774,6 +774,14 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; + /* We don't need to use a state cache here since this information is + * global for all CRTC. + */ + if (fbc->underrun_detected) { + fbc->no_fbc_reason = "underrun detected"; + return false; + } + if (!cache->plane.visible) { fbc->no_fbc_reason = "primary plane not visible"; return false; @@ -859,6 +867,11 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc) return false; } + if (fbc->underrun_detected) { + fbc->no_fbc_reason = "underrun detected"; + return false; + } + if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) { fbc->no_fbc_reason = "no enabled pipes can have FBC"; return false; @@ -1221,6 +1234,59 @@ void intel_fbc_global_disable(struct drm_i915_private *dev_priv) cancel_work_sync(&fbc->work.work); } +static void intel_fbc_underrun_work_fn(struct work_struct *work) +{ + struct drm_i915_private *dev_priv = + container_of(work, struct drm_i915_private, fbc.underrun_work); + struct intel_fbc *fbc = &dev_priv->fbc; + + mutex_lock(&fbc->lock); + + /* Maybe we were scheduled twice. */ + if (fbc->underrun_detected) + goto out; + + DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n"); + fbc->underrun_detected = true; + + intel_fbc_deactivate(dev_priv); +out: + mutex_unlock(&fbc->lock); +} + +/** + * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun + * @dev_priv: i915 device instance + * + * Without FBC, most underruns are harmless and don't really cause too many + * problems, except for an annoying message on dmesg. With FBC, underruns can + * become black screens or even worse, especially when paired with bad + * watermarks. So in order for us to be on the safe side, completely disable FBC + * in case we ever detect a FIFO underrun on any pipe. An underrun on any pipe + * already suggests that watermarks may be bad, so try to be as safe as + * possible. + * + * This function is called from the IRQ handler. + */ +void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv) +{ + struct intel_fbc *fbc = &dev_priv->fbc; + + if (!fbc_supported(dev_priv)) + return; + + /* There's no guarantee that underrun_detected won't be set to true + * right after this check and before the work is scheduled, but that's + * not a problem since we'll check it again under the work function + * while FBC is locked. This check here is just to prevent us from + * unnecessarily scheduling the work, and it relies on the fact that we + * never switch underrun_detect back to false after it's true. */ + if (READ_ONCE(fbc->underrun_detected)) + return; + + schedule_work(&fbc->underrun_work); +} + /** * intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking * @dev_priv: i915 device instance @@ -1292,6 +1358,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) enum pipe pipe; INIT_WORK(&fbc->work.work, intel_fbc_work_fn); + INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn); mutex_init(&fbc->lock); fbc->enabled = false; fbc->active = false; diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 2aa744081f09..ebb4fed8322e 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -372,6 +372,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) DRM_ERROR("CPU pipe %c FIFO underrun\n", pipe_name(pipe)); + + intel_fbc_handle_fifo_underrun_irq(dev_priv); } /** -- cgit v1.2.3 From 4c0b8a8bc49c477be9467f614b6b4ec479736019 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 19 Aug 2016 19:03:23 -0300 Subject: drm/i915: don't forget to set intel_crtc->dspaddr_offset on SKL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We never remembered to set it (so it was zero), but this was not a problem in the past due to the way handled the hardware registers. Unfortunately we changed how we set the hardware and forgot to set intel_crtc->dspaddr_offset. This started to reflect on a few kms_frontbuffer_tracking subtests that relied on page flips with CRTCs that don't point to the x:0,y:0 coordinates of the frontbuffer. After the page flip the CRTC was showing the x:0,y:0 coordinate of the frontbuffer instead of x:500,y:500. This problem is present even if we don't enable FBC or PSR. While trying to bisect it I realized that the first bad commit actually just gives me a black screen for the mentioned tests instead of showing the wrong x:0,y:0 offsets. A few commits later the black screen problem goes away and we get to the point where the code is today, but I'll consider the black screen as the first bad commit since it's the point where the IGT subtests start to fail. Fixes: 6687c9062c46 ("drm/i915: Rewrite fb rotation GTT handling") Testcase: kms_frontbuffer_tracking/fbc-1p-primscrn-shrfb-pgflip-blt Testcase: kms_frontbuffer_tracking/fbc-1p-primscrn-shrfb-evflip-blt Testcase: kms_frontbuffer_tracking/fbc-1p-shrfb-fliptrack Cc: Ville Syrjälä Cc: Sivakumar Thulasimani Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1471644203-23463-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f7b2f8f609e7..4775c06f4474 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3408,6 +3408,8 @@ static void skylake_update_primary_plane(struct drm_plane *plane, dst_w--; dst_h--; + intel_crtc->dspaddr_offset = surf_addr; + intel_crtc->adjusted_x = src_x; intel_crtc->adjusted_y = src_y; -- cgit v1.2.3 From 1b14adcaf659d988adccda778f286d2be628a1e6 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 24 Sep 2016 12:01:54 +0000 Subject: iio: accel: mma7660: fix non static symbol warning Fixes the following sparse warning: drivers/iio/accel/mma7660.c:42:11: warning: symbol 'mma7660_nscale' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma7660.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index 03beadf14ad3..3a40774cca74 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -39,7 +39,7 @@ #define MMA7660_SCALE_AVAIL "0.467142857" -const int mma7660_nscale = 467142857; +static const int mma7660_nscale = 467142857; #define MMA7660_CHANNEL(reg, axis) { \ .type = IIO_ACCEL, \ -- cgit v1.2.3 From 057ac1acdfc4743f066fcefe359385cad00549eb Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 23 Sep 2016 22:30:32 +0200 Subject: iio: Use kmalloc_array() in iio_scan_mask_set() A multiplication for the size determination of a memory allocation indicated that an array data structure should be processed. Thus use the corresponding function "kmalloc_array". This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 158aaf44dd95..b12830b09c7d 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -307,10 +307,9 @@ static int iio_scan_mask_set(struct iio_dev *indio_dev, const unsigned long *mask; unsigned long *trialmask; - trialmask = kmalloc(sizeof(*trialmask)* - BITS_TO_LONGS(indio_dev->masklength), - GFP_KERNEL); - + trialmask = kmalloc_array(BITS_TO_LONGS(indio_dev->masklength), + sizeof(*trialmask), + GFP_KERNEL); if (trialmask == NULL) return -ENOMEM; if (!indio_dev->masklength) { -- cgit v1.2.3 From 58b90a8d2c397ab8498d1b2a610e6ae40b6ad0f6 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 24 Sep 2016 01:34:48 +0530 Subject: drivers: iio: max1027: Fix sparse warning: "dubious: x | !y" Fixing below warning: drivers/iio/adc/max1027.c:241:34: warning: dubious: x | !y . Signed-off-by: Sandhya Bankar Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1027.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index 712fbd2b1f16..d60181822833 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -238,7 +238,9 @@ static int max1027_read_single_value(struct iio_dev *indio_dev, /* Configure conversion register with the requested chan */ st->reg = MAX1027_CONV_REG | MAX1027_CHAN(chan->channel) | - MAX1027_NOSCAN | !!(chan->type == IIO_TEMP); + MAX1027_NOSCAN; + if (chan->type == IIO_TEMP) + st->reg |= MAX1027_TEMP; ret = spi_write(st->spi, &st->reg, 1); if (ret < 0) { dev_err(&indio_dev->dev, -- cgit v1.2.3 From a117f378f44150e6d13d2f19740fb757425b651f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 Sep 2016 16:59:44 +0300 Subject: drm/i915/skl: drop workarounds for A0 and B0 revisions Pre-production hardware is not supported. Reviewed-by: Paulo Zanoni Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/7929af62a68504c84038a8db1625bd96ebaa9e6f.1474034059.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 4 ---- drivers/gpu/drm/i915/intel_dp_link_training.c | 3 --- drivers/gpu/drm/i915/intel_guc_loader.c | 5 ++--- drivers/gpu/drm/i915/intel_lrc.c | 8 +++----- drivers/gpu/drm/i915/intel_ringbuffer.c | 21 ++++++--------------- 5 files changed, 11 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0568fb53b7cd..57da2b7510df 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1299,10 +1299,6 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; - /* WaDisableHBR2:skl */ - if (IS_SKL_REVID(dev, 0, SKL_REVID_B0)) - return false; - if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) || (INTEL_INFO(dev)->gen >= 9)) return true; diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index c438b02184cb..0048b520baf7 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -225,9 +225,6 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) * Intel platforms that support HBR2 also support TPS3. TPS3 support is * also mandatory for downstream devices that support HBR2. However, not * all sinks follow the spec. - * - * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is - * supported in source but still not enabled. */ source_tps3 = intel_dp_source_supports_hbr2(intel_dp); sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 6fd39efb7894..acc1dbdd024e 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -375,9 +375,8 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) /* Enable MIA caching. GuC clock gating is disabled. */ I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); - /* WaDisableMinuteIaClockGating:skl,bxt */ - if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || - IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { + /* WaDisableMinuteIaClockGating:bxt */ + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) & ~GUC_ENABLE_MIA_CLOCK_GATING)); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 39417b77bff2..47f7afa538a1 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -269,8 +269,7 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->i915; engine->disable_lite_restore_wa = - (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || - IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) && + IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) && (engine->id == VCS || engine->id == VCS2); engine->ctx_desc_template = GEN8_CTX_VALID; @@ -1068,9 +1067,8 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine, { uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); - /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ - if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_B0) || - IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) { + /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */ + if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) { wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1)); wa_ctx_emit_reg(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0); wa_ctx_emit(batch, index, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 7a74750076c5..2faf64f9f256 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -851,15 +851,13 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); - /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ - if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || - IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) + /* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */ + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, GEN9_DG_MIRROR_FIX_ENABLE); - /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ - if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || - IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { + /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */ + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, GEN9_RHWO_OPTIMIZATION_DISABLE); /* @@ -1023,15 +1021,8 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) GEN8_LQSC_RO_PERF_DIS); /* WaEnableGapsTsvCreditFix:skl */ - if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) { - I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | - GEN9_GAPS_TSV_CREDIT_DISABLE)); - } - - /* WaDisablePowerCompilerClockGating:skl */ - if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0)) - WA_SET_BIT_MASKED(HIZ_CHICKEN, - BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); + I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | + GEN9_GAPS_TSV_CREDIT_DISABLE)); /* WaBarrierPerformanceFixDisable:skl */ if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0)) -- cgit v1.2.3 From 0d0b8dcf946407ee21aeaebcb15212087002fdf4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 Sep 2016 16:59:45 +0300 Subject: drm/i915/skl: drop workarounds for C0 revision Pre-production hardware is not supported. Reviewed-by: Paulo Zanoni Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/ed7b784306b35fa5215b9c04de79a2bc48585503.1474034059.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_guc_loader.c | 3 +-- drivers/gpu/drm/i915/intel_ringbuffer.c | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index acc1dbdd024e..a4e37c8db782 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -382,8 +382,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) } /* WaC6DisallowByGfxPause*/ - if (IS_SKL_REVID(dev, 0, SKL_REVID_C0) || - IS_BXT_REVID(dev, 0, BXT_REVID_B0)) + if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); if (IS_BROXTON(dev)) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 2faf64f9f256..474ce843de42 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -882,9 +882,8 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, GEN9_CCS_TLB_PREFETCH_ENABLE); - /* WaDisableMaskBasedCammingInRCC:skl,bxt */ - if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) || - IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) + /* WaDisableMaskBasedCammingInRCC:bxt */ + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, PIXEL_MASK_CAMMING_DISABLE); -- cgit v1.2.3 From 9fc736e833d226853fd53843e35d6a1d542394ed Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 Sep 2016 16:59:46 +0300 Subject: drm/i915/skl: drop workarounds for D0 revision Pre-production hardware is not supported. Reviewed-by: Paulo Zanoni Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/d28d21ceddeec226b5d1a20a7382bee9a72709a4.1474034059.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 10 ++++------ drivers/gpu/drm/i915/intel_pm.c | 3 +-- drivers/gpu/drm/i915/intel_ringbuffer.c | 12 ++---------- 3 files changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 47f7afa538a1..ca649ccc6613 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -994,9 +994,8 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine, struct drm_i915_private *dev_priv = engine->i915; uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); - /* WaDisableCtxRestoreArbitration:skl,bxt */ - if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) || - IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) + /* WaDisableCtxRestoreArbitration:bxt */ + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE); /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */ @@ -1095,9 +1094,8 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine, wa_ctx_emit(batch, index, MI_NOOP); } - /* WaDisableCtxRestoreArbitration:skl,bxt */ - if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_D0) || - IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) + /* WaDisableCtxRestoreArbitration:bxt */ + if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_ENABLE); wa_ctx_emit(batch, index, MI_BATCH_BUFFER_END); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2df06b703e3d..a860c4082eb8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5335,8 +5335,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) rc6_mask = GEN6_RC_CTL_RC6_ENABLE; DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE)); /* WaRsUseTimeoutMode */ - if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) || - IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */ I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | GEN7_RC_CTL_TO_MODE | diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 474ce843de42..6880082b9166 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1000,10 +1000,8 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) * until D0 which is the default case so this is equivalent to * !WaDisablePerCtxtPreemptionGranularityControl:skl */ - if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) { - I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, - _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); - } + I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, + _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) { /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ @@ -1023,12 +1021,6 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE)); - /* WaBarrierPerformanceFixDisable:skl */ - if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0)) - WA_SET_BIT_MASKED(HDC_CHICKEN0, - HDC_FENCE_DEST_SLM_DISABLE | - HDC_BARRIER_PERFORMANCE_DISABLE); - /* WaDisableSbeCacheDispatchPortSharing:skl */ if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) WA_SET_BIT_MASKED( -- cgit v1.2.3 From 3be192e92ddcad15f7bf6b4b9e3f195eb8c1fe76 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 Sep 2016 16:59:47 +0300 Subject: drm/i915/skl: drop workarounds for E0 revision Pre-production hardware is not supported. Reviewed-by: Paulo Zanoni Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/0633a02177195703502ef2396aab03efc0314334.1474034059.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 5 ++--- drivers/gpu/drm/i915/intel_ringbuffer.c | 14 -------------- 2 files changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ca649ccc6613..2d8eb2eb2b72 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -845,13 +845,12 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine, uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES); /* - * WaDisableLSQCROPERFforOCL:skl,kbl + * WaDisableLSQCROPERFforOCL:kbl * This WA is implemented in skl_init_clock_gating() but since * this batch updates GEN8_L3SQCREG4 with default value we need to * set this bit here to retain the WA during flush. */ - if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0) || - IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) + if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS; wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 | diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 6880082b9166..68dc27f6ba0a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1003,20 +1003,6 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); - if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) { - /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ - I915_WRITE(FF_SLICE_CS_CHICKEN2, - _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); - } - - /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes - * involving this register should also be added to WA batch as required. - */ - if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) - /* WaDisableLSQCROPERFforOCL:skl */ - I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | - GEN8_LQSC_RO_PERF_DIS); - /* WaEnableGapsTsvCreditFix:skl */ I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE)); -- cgit v1.2.3 From 3ec92362cda4c4a2c1ba699b6e8f2cc2e3b4306a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 Sep 2016 16:59:48 +0300 Subject: drm/i915/skl: drop workarounds for F0 revision Pre-production hardware is not supported. Reviewed-by: Paulo Zanoni Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/e5433e6430dcfd941209c4d8103035ddb13d17b4.1474034059.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_ringbuffer.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 68dc27f6ba0a..67ea9dd5921e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1007,12 +1007,6 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE)); - /* WaDisableSbeCacheDispatchPortSharing:skl */ - if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) - WA_SET_BIT_MASKED( - GEN7_HALF_SLICE_CHICKEN1, - GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); - /* WaDisableGafsUnitClkGating:skl */ WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); -- cgit v1.2.3 From 16dcdc4edbcf5cb130004737f2548401776170f1 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:27 -0300 Subject: drm/i915: SAGV is not SKL-only, so rename a few things The plan is to introduce intel_has_sagv() and then use it to discover which platforms actually support it. I thought about keeping the functions with their current skl names, but found two problems: (i) skl_has_sagv() would become a very confusing name, and (ii) intel_atomic_commit_tail() doesn't seem to be calling any functions whose name start with a platform name, so the "intel_" naming scheme seems make more sense than the "firstplatorm_" naming scheme here. Cc: stable@vger.kernel.org Reviewed-by: Lyude Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-2-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 10 +++++----- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- drivers/gpu/drm/i915/intel_drv.h | 6 +++--- drivers/gpu/drm/i915/intel_pm.c | 26 +++++++++++++------------- 4 files changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c0f0f11752a2..23bc43d23d2c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1988,11 +1988,11 @@ struct drm_i915_private { struct vlv_s0ix_state vlv_s0ix_state; enum { - I915_SKL_SAGV_UNKNOWN = 0, - I915_SKL_SAGV_DISABLED, - I915_SKL_SAGV_ENABLED, - I915_SKL_SAGV_NOT_CONTROLLED - } skl_sagv_status; + I915_SAGV_UNKNOWN = 0, + I915_SAGV_DISABLED, + I915_SAGV_ENABLED, + I915_SAGV_NOT_CONTROLLED + } sagv_status; struct { /* diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4775c06f4474..87a7063dca79 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14361,8 +14361,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) * SKL workaround: bspec recommends we disable the SAGV when we * have more then one pipe enabled */ - if (IS_SKYLAKE(dev_priv) && !skl_can_enable_sagv(state)) - skl_disable_sagv(dev_priv); + if (IS_SKYLAKE(dev_priv) && !intel_can_enable_sagv(state)) + intel_disable_sagv(dev_priv); intel_modeset_verify_disabled(dev); } @@ -14420,8 +14420,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) } if (IS_SKYLAKE(dev_priv) && intel_state->modeset && - skl_can_enable_sagv(state)) - skl_enable_sagv(dev_priv); + intel_can_enable_sagv(state)) + intel_enable_sagv(dev_priv); drm_atomic_helper_commit_hw_done(state); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6df0f2f2308a..5fdae7fcee07 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1746,9 +1746,9 @@ void ilk_wm_get_hw_state(struct drm_device *dev); void skl_wm_get_hw_state(struct drm_device *dev); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb /* out */); -bool skl_can_enable_sagv(struct drm_atomic_state *state); -int skl_enable_sagv(struct drm_i915_private *dev_priv); -int skl_disable_sagv(struct drm_i915_private *dev_priv); +bool intel_can_enable_sagv(struct drm_atomic_state *state); +int intel_enable_sagv(struct drm_i915_private *dev_priv); +int intel_disable_sagv(struct drm_i915_private *dev_priv); bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, const struct skl_ddb_allocation *new, enum pipe pipe); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a860c4082eb8..4e50d3313441 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2889,12 +2889,12 @@ skl_wm_plane_id(const struct intel_plane *plane) * - We're not using an interlaced display configuration */ int -skl_enable_sagv(struct drm_i915_private *dev_priv) +intel_enable_sagv(struct drm_i915_private *dev_priv) { int ret; - if (dev_priv->skl_sagv_status == I915_SKL_SAGV_NOT_CONTROLLED || - dev_priv->skl_sagv_status == I915_SKL_SAGV_ENABLED) + if (dev_priv->sagv_status == I915_SAGV_NOT_CONTROLLED || + dev_priv->sagv_status == I915_SAGV_ENABLED) return 0; DRM_DEBUG_KMS("Enabling the SAGV\n"); @@ -2912,19 +2912,19 @@ skl_enable_sagv(struct drm_i915_private *dev_priv) */ if (ret == -ENXIO) { DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); - dev_priv->skl_sagv_status = I915_SKL_SAGV_NOT_CONTROLLED; + dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; return 0; } else if (ret < 0) { DRM_ERROR("Failed to enable the SAGV\n"); return ret; } - dev_priv->skl_sagv_status = I915_SKL_SAGV_ENABLED; + dev_priv->sagv_status = I915_SAGV_ENABLED; return 0; } static int -skl_do_sagv_disable(struct drm_i915_private *dev_priv) +intel_do_sagv_disable(struct drm_i915_private *dev_priv) { int ret; uint32_t temp = GEN9_SAGV_DISABLE; @@ -2938,19 +2938,19 @@ skl_do_sagv_disable(struct drm_i915_private *dev_priv) } int -skl_disable_sagv(struct drm_i915_private *dev_priv) +intel_disable_sagv(struct drm_i915_private *dev_priv) { int ret, result; - if (dev_priv->skl_sagv_status == I915_SKL_SAGV_NOT_CONTROLLED || - dev_priv->skl_sagv_status == I915_SKL_SAGV_DISABLED) + if (dev_priv->sagv_status == I915_SAGV_NOT_CONTROLLED || + dev_priv->sagv_status == I915_SAGV_DISABLED) return 0; DRM_DEBUG_KMS("Disabling the SAGV\n"); mutex_lock(&dev_priv->rps.hw_lock); /* bspec says to keep retrying for at least 1 ms */ - ret = wait_for(result = skl_do_sagv_disable(dev_priv), 1); + ret = wait_for(result = intel_do_sagv_disable(dev_priv), 1); mutex_unlock(&dev_priv->rps.hw_lock); if (ret == -ETIMEDOUT) { @@ -2964,18 +2964,18 @@ skl_disable_sagv(struct drm_i915_private *dev_priv) */ if (result == -ENXIO) { DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); - dev_priv->skl_sagv_status = I915_SKL_SAGV_NOT_CONTROLLED; + dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; return 0; } else if (result < 0) { DRM_ERROR("Failed to disable the SAGV\n"); return result; } - dev_priv->skl_sagv_status = I915_SKL_SAGV_DISABLED; + dev_priv->sagv_status = I915_SAGV_DISABLED; return 0; } -bool skl_can_enable_sagv(struct drm_atomic_state *state) +bool intel_can_enable_sagv(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; struct drm_i915_private *dev_priv = to_i915(dev); -- cgit v1.2.3 From 56feca91973459d0b62cbb2610b62d341025ed89 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:28 -0300 Subject: drm/i915: introduce intel_has_sagv() And use it to move knowledge about the SAGV-supporting platforms from the callers to the SAGV code. We'll add more platforms to intel_has_sagv(), so IMHO it makes more sense to move all this to a single function instead of patching all the callers every time we add SAGV support to a new platform. v2: Move I915_SAGV_NOT_CONTROLLED to the new function (Lyude). Cc: stable@vger.kernel.org Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-3-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 5 ++--- drivers/gpu/drm/i915/intel_pm.c | 22 ++++++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 87a7063dca79..e31d3e6d6647 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14361,7 +14361,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) * SKL workaround: bspec recommends we disable the SAGV when we * have more then one pipe enabled */ - if (IS_SKYLAKE(dev_priv) && !intel_can_enable_sagv(state)) + if (!intel_can_enable_sagv(state)) intel_disable_sagv(dev_priv); intel_modeset_verify_disabled(dev); @@ -14419,8 +14419,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state); } - if (IS_SKYLAKE(dev_priv) && intel_state->modeset && - intel_can_enable_sagv(state)) + if (intel_state->modeset && intel_can_enable_sagv(state)) intel_enable_sagv(dev_priv); drm_atomic_helper_commit_hw_done(state); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4e50d3313441..4210165f2567 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2877,6 +2877,13 @@ skl_wm_plane_id(const struct intel_plane *plane) } } +static bool +intel_has_sagv(struct drm_i915_private *dev_priv) +{ + return IS_SKYLAKE(dev_priv) && + dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED; +} + /* * SAGV dynamically adjusts the system agent voltage and clock frequencies * depending on power and performance requirements. The display engine access @@ -2893,8 +2900,10 @@ intel_enable_sagv(struct drm_i915_private *dev_priv) { int ret; - if (dev_priv->sagv_status == I915_SAGV_NOT_CONTROLLED || - dev_priv->sagv_status == I915_SAGV_ENABLED) + if (!intel_has_sagv(dev_priv)) + return 0; + + if (dev_priv->sagv_status == I915_SAGV_ENABLED) return 0; DRM_DEBUG_KMS("Enabling the SAGV\n"); @@ -2942,8 +2951,10 @@ intel_disable_sagv(struct drm_i915_private *dev_priv) { int ret, result; - if (dev_priv->sagv_status == I915_SAGV_NOT_CONTROLLED || - dev_priv->sagv_status == I915_SAGV_DISABLED) + if (!intel_has_sagv(dev_priv)) + return 0; + + if (dev_priv->sagv_status == I915_SAGV_DISABLED) return 0; DRM_DEBUG_KMS("Disabling the SAGV\n"); @@ -2984,6 +2995,9 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) enum pipe pipe; int level, plane; + if (!intel_has_sagv(dev_priv)) + return false; + /* * SKL workaround: bspec recommends we disable the SAGV when we have * more then one pipe enabled -- cgit v1.2.3 From 6e3100ec21e7c774a0fc01e36a1e0739530c2f71 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:29 -0300 Subject: drm/i915/kbl: KBL also needs to run the SAGV code According to BSpec, it's the "core CPUs" that need the code, which means SKL and KBL, but not BXT. I don't have a KBL to test this patch on it. v2: Only SKL should have I915_SAGV_NOT_CONTROLLED. Cc: stable@vger.kernel.org Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-4-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4210165f2567..92b05254b3d7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2880,8 +2880,14 @@ skl_wm_plane_id(const struct intel_plane *plane) static bool intel_has_sagv(struct drm_i915_private *dev_priv) { - return IS_SKYLAKE(dev_priv) && - dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED; + if (IS_KABYLAKE(dev_priv)) + return true; + + if (IS_SKYLAKE(dev_priv) && + dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED) + return true; + + return false; } /* @@ -2919,7 +2925,7 @@ intel_enable_sagv(struct drm_i915_private *dev_priv) * Some skl systems, pre-release machines in particular, * don't actually have an SAGV. */ - if (ret == -ENXIO) { + if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) { DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; return 0; @@ -2973,7 +2979,7 @@ intel_disable_sagv(struct drm_i915_private *dev_priv) * Some skl systems, pre-release machines in particular, * don't actually have an SAGV. */ - if (result == -ENXIO) { + if (IS_SKYLAKE(dev_priv) && result == -ENXIO) { DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; return 0; -- cgit v1.2.3 From 0727e40a48a1d08cf54ce2c01e120864b92e59bf Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:30 -0300 Subject: drm/i915/gen9: fix the WaWmMemoryReadLatency implementation Bspec says: "The mailbox response data may not account for memory read latency. If the mailbox response data for level 0 is 0us, add 2 microseconds to the result for each valid level." This means we should only do the +2 in case wm[0] == 0, not always. So split the sanitizing implementation from the WA implementation and fix the WA implementation. v2: Add Fixes tag (Maarten). Fixes: 367294be7c25 ("drm/i915/gen9: Add 2us read latency to WM level") Cc: stable@vger.kernel.org Cc: Vandana Kannan Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-5-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 42 +++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 92b05254b3d7..93fce737402c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2126,33 +2126,35 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) wm[7] = (val >> GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT) & GEN9_MEM_LATENCY_LEVEL_MASK; + /* + * If a level n (n > 1) has a 0us latency, all levels m (m >= n) + * need to be disabled. We make sure to sanitize the values out + * of the punit to satisfy this requirement. + */ + for (level = 1; level <= max_level; level++) { + if (wm[level] == 0) { + for (i = level + 1; i <= max_level; i++) + wm[i] = 0; + break; + } + } + /* * WaWmMemoryReadLatency:skl * * punit doesn't take into account the read latency so we need - * to add 2us to the various latency levels we retrieve from - * the punit. - * - W0 is a bit special in that it's the only level that - * can't be disabled if we want to have display working, so - * we always add 2us there. - * - For levels >=1, punit returns 0us latency when they are - * disabled, so we respect that and don't add 2us then - * - * Additionally, if a level n (n > 1) has a 0us latency, all - * levels m (m >= n) need to be disabled. We make sure to - * sanitize the values out of the punit to satisfy this - * requirement. + * to add 2us to the various latency levels we retrieve from the + * punit when level 0 response data us 0us. */ - wm[0] += 2; - for (level = 1; level <= max_level; level++) - if (wm[level] != 0) + if (wm[0] == 0) { + wm[0] += 2; + for (level = 1; level <= max_level; level++) { + if (wm[level] == 0) + break; wm[level] += 2; - else { - for (i = level + 1; i <= max_level; i++) - wm[i] = 0; - - break; } + } + } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { uint64_t sskpd = I915_READ64(MCH_SSKPD); -- cgit v1.2.3 From 1186fa85eb9b3cc0589990fbc39617e50e38759a Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:31 -0300 Subject: drm/i915/gen9: minimum scanlines for Y tile is not always 4 During watermarks calculations, this value is used in 3 different places. Only one of them was not using a hardcoded 4. Move the code up so everybody can benefit from the actual value. This should only help on situations with Y tiling + 90/270 rotation + 1 or 2 bpp or NV12. Cc: stable@vger.kernel.org Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-6-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 56 +++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 93fce737402c..fbab3eae27b8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3495,7 +3495,8 @@ static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latenc static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, uint32_t horiz_pixels, uint8_t cpp, - uint64_t tiling, uint32_t latency) + uint64_t tiling, uint32_t latency, + uint32_t y_min_scanlines) { uint32_t ret; uint32_t plane_bytes_per_line, plane_blocks_per_line; @@ -3508,9 +3509,9 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, if (tiling == I915_FORMAT_MOD_Y_TILED || tiling == I915_FORMAT_MOD_Yf_TILED) { - plane_bytes_per_line *= 4; + plane_bytes_per_line *= y_min_scanlines; plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); - plane_blocks_per_line /= 4; + plane_blocks_per_line /= y_min_scanlines; } else if (tiling == DRM_FORMAT_MOD_NONE) { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; } else { @@ -3567,6 +3568,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint8_t cpp; uint32_t width = 0, height = 0; uint32_t plane_pixel_rate; + uint32_t y_min_scanlines; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { *enabled = false; @@ -3582,38 +3584,44 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, cpp = drm_format_plane_cpp(fb->pixel_format, 0); plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); + if (intel_rotation_90_or_270(pstate->rotation)) { + int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? + drm_format_plane_cpp(fb->pixel_format, 1) : + drm_format_plane_cpp(fb->pixel_format, 0); + + switch (cpp) { + case 1: + y_min_scanlines = 16; + break; + case 2: + y_min_scanlines = 8; + break; + default: + WARN(1, "Unsupported pixel depth for rotation"); + case 4: + y_min_scanlines = 4; + break; + } + } else { + y_min_scanlines = 4; + } + method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); method2 = skl_wm_method2(plane_pixel_rate, cstate->base.adjusted_mode.crtc_htotal, width, cpp, fb->modifier[0], - latency); + latency, + y_min_scanlines); plane_bytes_per_line = width * cpp; plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { - uint32_t min_scanlines = 4; - uint32_t y_tile_minimum; - if (intel_rotation_90_or_270(pstate->rotation)) { - int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? - drm_format_plane_cpp(fb->pixel_format, 1) : - drm_format_plane_cpp(fb->pixel_format, 0); - - switch (cpp) { - case 1: - min_scanlines = 16; - break; - case 2: - min_scanlines = 8; - break; - case 8: - WARN(1, "Unsupported pixel depth for rotation"); - } - } - y_tile_minimum = plane_blocks_per_line * min_scanlines; + uint32_t y_tile_minimum = plane_blocks_per_line * + y_min_scanlines; selected_result = max(method2, y_tile_minimum); } else { if ((ddb_allocation / plane_blocks_per_line) >= 1) @@ -3628,7 +3636,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (level >= 1 && level <= 7) { if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) - res_lines += 4; + res_lines += y_min_scanlines; else res_blocks++; } -- cgit v1.2.3 From 7a1a8aed67e0a60772defe3f6499eb340da48634 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:32 -0300 Subject: drm/i915/gen9: fix plane_blocks_per_line on watermarks calculations The confusing thing is that plane_blocks_per_line is listed as part of the method 2 calculation but is also used for other things. We calculated it in two different places and different ways: one inside skl_wm_method2() and the other inside skl_compute_plane_wm(). The skl_wm_method2() implementation is the one that matches the specification. With this patch we fix the skl_compute_plane_wm() calculation and just pass it as a parameter to skl_wm_method2(). We also take care to not modify the value of plane_bytes_per_line since we're going to rely on it having a correct value in later patches. This should affect the watermarks for Linear and Y-tiled. From my analysis, it looks like the two plane_blocks_per_line variables got out of sync on 0fda65680e92, but we can't really say that commit was a regression, it looks like just an incomplete fix. There's always the possibility that 0fda65680e92 matched our specification at that time, and then later the specification changed. v2: Try to add a "Fixes" tag (Maarten). Fixes: 0fda65680e92 ("drm/i915/skl: Update watermarks for Y tiling") Cc: stable@vger.kernel.org Cc: Tvrtko Ursulin Reviewed-by: Lyude Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-7-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fbab3eae27b8..051eda99a53a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3494,30 +3494,14 @@ static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latenc } static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, - uint32_t horiz_pixels, uint8_t cpp, - uint64_t tiling, uint32_t latency, - uint32_t y_min_scanlines) + uint32_t latency, uint32_t plane_blocks_per_line) { uint32_t ret; - uint32_t plane_bytes_per_line, plane_blocks_per_line; uint32_t wm_intermediate_val; if (latency == 0) return UINT_MAX; - plane_bytes_per_line = horiz_pixels * cpp; - - if (tiling == I915_FORMAT_MOD_Y_TILED || - tiling == I915_FORMAT_MOD_Yf_TILED) { - plane_bytes_per_line *= y_min_scanlines; - plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); - plane_blocks_per_line /= y_min_scanlines; - } else if (tiling == DRM_FORMAT_MOD_NONE) { - plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; - } else { - plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); - } - wm_intermediate_val = latency * pixel_rate; ret = DIV_ROUND_UP(wm_intermediate_val, pipe_htotal * 1000) * plane_blocks_per_line; @@ -3606,17 +3590,24 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_min_scanlines = 4; } + plane_bytes_per_line = width * cpp; + if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + plane_blocks_per_line = + DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512); + plane_blocks_per_line /= y_min_scanlines; + } else if (fb->modifier[0] == DRM_FORMAT_MOD_NONE) { + plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + + 1; + } else { + plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); + } + method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); method2 = skl_wm_method2(plane_pixel_rate, cstate->base.adjusted_mode.crtc_htotal, - width, - cpp, - fb->modifier[0], latency, - y_min_scanlines); - - plane_bytes_per_line = width * cpp; - plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); + plane_blocks_per_line); if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { -- cgit v1.2.3 From 75676ed423a6acf9e2b1df52fbc036a51e11fb7a Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:33 -0300 Subject: drm/i915/gen9: fix the watermark res_blocks value We forgot the "res_blocks += y_tile_minimum" that's described on step V of our documentation. Again, this should only affect the Y tiling cases. It looks like the relevant code was introduced in 0fda65680e92, but there's always the possibility that it matched our specification when it was introduced, and then the specification changed while the code stayed the same. So we can't really say this was a regression, but let's try to add a "Fixes" tag anyway to help backporting. v2: Try to add a "Fixes" tag (Maarten). Fixes: 0fda65680e92 ("drm/i915/skl: Update watermarks for Y tiling") Cc: stable@vger.kernel.org Cc: Tvrtko Ursulin Reviewed-by: Lyude Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-8-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 051eda99a53a..fd7465cd9b21 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3552,7 +3552,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint8_t cpp; uint32_t width = 0, height = 0; uint32_t plane_pixel_rate; - uint32_t y_min_scanlines; + uint32_t y_tile_minimum, y_min_scanlines; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { *enabled = false; @@ -3609,10 +3609,10 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, latency, plane_blocks_per_line); + y_tile_minimum = plane_blocks_per_line * y_min_scanlines; + if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { - uint32_t y_tile_minimum = plane_blocks_per_line * - y_min_scanlines; selected_result = max(method2, y_tile_minimum); } else { if ((ddb_allocation / plane_blocks_per_line) >= 1) @@ -3626,10 +3626,12 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (level >= 1 && level <= 7) { if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + res_blocks += y_tile_minimum; res_lines += y_min_scanlines; - else + } else { res_blocks++; + } } if (res_blocks >= ddb_allocation || res_lines > 31) { -- cgit v1.2.3 From f1db3eafe5a2ad39caa8315f9b5403759e0c5520 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:34 -0300 Subject: drm/i915/gen9: implement missing case for SKL watermarks calculation This should affect linear and X tiled planes on really small htotal cases. It doesn't seem to be a very feasible case, but let's implement it since it's on the specification and it's better to have it and never need than not have it and realize we needed it. Reviewed-by: Lyude Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-9-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fd7465cd9b21..d5e77382697f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3615,7 +3615,10 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { selected_result = max(method2, y_tile_minimum); } else { - if ((ddb_allocation / plane_blocks_per_line) >= 1) + if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) && + (plane_bytes_per_line / 512 < 1)) + selected_result = method2; + else if ((ddb_allocation / plane_blocks_per_line) >= 1) selected_result = min(method1, method2); else selected_result = method1; -- cgit v1.2.3 From 86a462bcad329ca9232547857d466cc3012d7c2e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 22 Sep 2016 18:00:35 -0300 Subject: drm/i915/gen9: fail the modeset instead of WARNing on unsupported config Now that this code is part of the compute stage we can return -EINVAL to prevent the modeset instead of giving a WARN and trying anyway. v2: - Fix typo (Paul Menzel). - Add MISSING_CASE() (Ville, Maarten). Reported-by: Lyude Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474578035-424-10-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d5e77382697f..5b47888c49a7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3580,11 +3580,12 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, case 2: y_min_scanlines = 8; break; - default: - WARN(1, "Unsupported pixel depth for rotation"); case 4: y_min_scanlines = 4; break; + default: + MISSING_CASE(cpp); + return -EINVAL; } } else { y_min_scanlines = 4; -- cgit v1.2.3 From bc4ec7c83976fe03d2be75a8f64ea825f7b42867 Mon Sep 17 00:00:00 2001 From: "Nagaraju, Vathsala" Date: Thu, 22 Sep 2016 14:19:53 +0530 Subject: drm/i915: don't report compression when fbc is disabled When i915_fbc_status is read while fbc is disabled, it reports compressing to be true, which is confusing. Report compressing only when fbc is enabled. v2 (from Paulo): commit message capitalization. Signed-off-by: vathsala nagaraju Reviewed-by: Paulo Zanoni Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1474534193-9527-1-git-send-email-vathsala.nagaraju@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3c6a06df3dc9..6dd325145a0a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1658,7 +1658,8 @@ static int i915_fbc_status(struct seq_file *m, void *unused) seq_printf(m, "FBC disabled: %s\n", dev_priv->fbc.no_fbc_reason); - if (INTEL_GEN(dev_priv) >= 7) + if (intel_fbc_is_active(dev_priv) && + INTEL_GEN(dev_priv) >= 7) seq_printf(m, "Compressing: %s\n", yesno(I915_READ(FBC_STATUS2) & FBC_COMPRESSION_MASK)); -- cgit v1.2.3 From 4ff40a41527ae24969431ae879d06169e14dfc08 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 26 Sep 2016 15:07:51 +0300 Subject: drm/i915: add a few missing platform tags to workaround tags Cc: Paulo Zanoni Reviewed-by: Paulo Zanoni Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1474891672-23414-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_guc_loader.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index a4e37c8db782..7ace96be82a8 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -381,7 +381,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) ~GUC_ENABLE_MIA_CLOCK_GATING)); } - /* WaC6DisallowByGfxPause*/ + /* WaC6DisallowByGfxPause:bxt */ if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5b47888c49a7..5d39ad2c2b7f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5361,7 +5361,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) if (intel_enable_rc6() & INTEL_RC6_ENABLE) rc6_mask = GEN6_RC_CTL_RC6_ENABLE; DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE)); - /* WaRsUseTimeoutMode */ + /* WaRsUseTimeoutMode:bxt */ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */ I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | -- cgit v1.2.3 From 4fc7e845f3e2c4c928bf792e43c69af969999a2c Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 26 Sep 2016 15:07:52 +0300 Subject: drm/i915/skl: tell the user about pre-production hardware We just removed the implementation for all the pre-production workarounds, so now tell the user that we expect his machine to not work properly. Also convert this to DRM_ERROR so we can more easily spot these problems in bug reports and CI/QA runs. Cc: Jani Nikula Signed-off-by: Paulo Zanoni Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1474891672-23414-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index bfb2efd8d4d4..9c1543240e27 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -771,6 +771,19 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) destroy_workqueue(dev_priv->wq); } +/* + * We don't keep the workarounds for pre-production hardware, so we expect our + * driver to fail on these machines in one way or another. A little warning on + * dmesg may help both the user and the bug triagers. + */ +static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv) +{ + if (IS_HSW_EARLY_SDV(dev_priv) || + IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) + DRM_ERROR("This is a pre-production stepping. " + "It may not be fully functional.\n"); +} + /** * i915_driver_init_early - setup state not requiring device access * @dev_priv: device private @@ -838,13 +851,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, intel_device_info_dump(dev_priv); - /* Not all pre-production machines fall into this category, only the - * very first ones. Almost everything should work, except for maybe - * suspend/resume. And we don't implement workarounds that affect only - * pre-production machines. */ - if (IS_HSW_EARLY_SDV(dev_priv)) - DRM_INFO("This is an early pre-production Haswell machine. " - "It may not be fully functional.\n"); + intel_detect_preproduction_hw(dev_priv); return 0; -- cgit v1.2.3 From a04139c4cf289119cdfb6081af602f7a452fb7c2 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 26 Sep 2016 17:54:31 +0300 Subject: drm/i915/bxt: Fix HDMI DPLL configuration a277ca7dc01d should've been a no-functional-change commit, but it removed the initialization of the dpll_hw_state for HDMI outputs, resulting in state mismatches and a failed modeset with blank screen. Fix this by reinstating the dpll_hw_state initialization. v2: - Make bxt_ddi_hdmi_set_dpll_hw_state() static. Cc: Manasi Navare Cc: Ander Conselvan de Oliveira Cc: Durgadoss R Cc: Rodrigo Vivi Fixes: a277ca7dc01d ("drm/i915: Split bxt_ddi_pll_select()") Signed-off-by: Imre Deak Reviewed-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1474901671-22719-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dpll_mgr.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index c26d18a574b6..1c59ca50c430 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1694,21 +1694,32 @@ bool bxt_ddi_dp_set_dpll_hw_state(int clock, return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state); } +static bool +bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state, int clock, + struct intel_dpll_hw_state *dpll_hw_state) +{ + struct bxt_clk_div clk_div = { }; + + bxt_ddi_hdmi_pll_dividers(intel_crtc, crtc_state, clock, &clk_div); + + return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state); +} + static struct intel_shared_dpll * bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { - struct bxt_clk_div clk_div = {0}; - struct intel_dpll_hw_state dpll_hw_state = {0}; + struct intel_dpll_hw_state dpll_hw_state = { }; struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_digital_port *intel_dig_port; struct intel_shared_dpll *pll; int i, clock = crtc_state->port_clock; - if (encoder->type == INTEL_OUTPUT_HDMI - && !bxt_ddi_hdmi_pll_dividers(crtc, crtc_state, - clock, &clk_div)) + if (encoder->type == INTEL_OUTPUT_HDMI && + !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock, + &dpll_hw_state)) return NULL; if ((encoder->type == INTEL_OUTPUT_DP || -- cgit v1.2.3 From 38e442fc8ba11b32e57f4837e1aa695f3751b99c Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 24 Sep 2016 00:50:22 +0530 Subject: drivers: iio: dac: Fix sparse warning Fixing below warnings: drivers/iio/dac/ad5592r.c:58:41: warning: incorrect type in argument 2 (different base types) drivers/iio/dac/ad5592r.c:58:41: expected unsigned short [usertype] *buf drivers/iio/dac/ad5592r.c:58:41: got restricted __be16 * drivers/iio/dac/ad5592r.c:62:41: warning: incorrect type in argument 2 (different base types) drivers/iio/dac/ad5592r.c:62:41: expected unsigned short [usertype] *buf drivers/iio/dac/ad5592r.c:62:41: got restricted __be16 * drivers/iio/dac/ad5592r.c:92:41: warning: incorrect type in argument 2 (different base types) drivers/iio/dac/ad5592r.c:92:41: expected unsigned short [usertype] *buf drivers/iio/dac/ad5592r.c:92:41: got restricted __be16 * drivers/iio/dac/ad5592r.c:110:41: warning: incorrect type in argument 2 (different base types) drivers/iio/dac/ad5592r.c:110:41: expected unsigned short [usertype] *buf drivers/iio/dac/ad5592r.c:110:41: got restricted __be16 * Signed-off-by: Sandhya Bankar Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5592r.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c index 0b235a2c7359..6eed5b7729be 100644 --- a/drivers/iio/dac/ad5592r.c +++ b/drivers/iio/dac/ad5592r.c @@ -17,7 +17,7 @@ #define AD5592R_GPIO_READBACK_EN BIT(10) #define AD5592R_LDAC_READBACK_EN BIT(6) -static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, u16 *buf) +static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, __be16 *buf) { struct spi_device *spi = container_of(st->dev, struct spi_device, dev); struct spi_transfer t = { -- cgit v1.2.3 From 43ece27e70b2c756e45306791955507f0533e248 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Sep 2016 17:19:41 +0200 Subject: iio:trigger: Add helper function to verify that a trigger belongs to the same device Some triggers can only be attached to the IIO device that corresponds to the same physical device. Currently each driver that requires this implements its own trigger validation function. Introduce a new helper function called iio_trigger_validate_own_device() that can be used to do this check. Having a common implementation avoids code duplication and unnecessary boiler-plate code. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 21 +++++++++++++++++++++ include/linux/iio/trigger.h | 2 ++ 2 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index e1e104845e38..978729f6d7c4 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -717,6 +717,27 @@ bool iio_trigger_using_own(struct iio_dev *indio_dev) } EXPORT_SYMBOL(iio_trigger_using_own); +/** + * iio_trigger_validate_own_device - Check if a trigger and IIO device belong to + * the same device + * @trig: The IIO trigger to check + * @indio_dev: the IIO device to check + * + * This function can be used as the validate_device callback for triggers that + * can only be attached to their own device. + * + * Return: 0 if both the trigger and the IIO device belong to the same + * device, -EINVAL otherwise. + */ +int iio_trigger_validate_own_device(struct iio_trigger *trig, + struct iio_dev *indio_dev) +{ + if (indio_dev->dev.parent != trig->dev.parent) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL(iio_trigger_validate_own_device); + void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { indio_dev->groups[indio_dev->groupcounter++] = diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index 4f1154f7a33c..ea08302f2d7b 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -170,6 +170,8 @@ void iio_trigger_free(struct iio_trigger *trig); */ bool iio_trigger_using_own(struct iio_dev *indio_dev); +int iio_trigger_validate_own_device(struct iio_trigger *trig, + struct iio_dev *indio_dev); #else struct iio_trigger; -- cgit v1.2.3 From 19808e0467a05ee4a3008f9d586ce32d5b34aba8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Sep 2016 17:19:42 +0200 Subject: iio:mma8452: Use new iio_trigger_validate_own_device() helper Use the new iio_trigger_validate_own_device() to verify that the trigger can only be attached to the matching IIO device rather than using a custom variant. While the implementation of iio_trigger_validate_own_device() and the custom variant and are not identical their behaviour is. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index d41e1b588e68..1c7051581513 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1347,20 +1347,9 @@ static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig, return mma8452_change_config(data, MMA8452_CTRL_REG4, reg); } -static int mma8452_validate_device(struct iio_trigger *trig, - struct iio_dev *indio_dev) -{ - struct iio_dev *indio = iio_trigger_get_drvdata(trig); - - if (indio != indio_dev) - return -EINVAL; - - return 0; -} - static const struct iio_trigger_ops mma8452_trigger_ops = { .set_trigger_state = mma8452_data_rdy_trigger_set_state, - .validate_device = mma8452_validate_device, + .validate_device = iio_trigger_validate_own_device, .owner = THIS_MODULE, }; -- cgit v1.2.3 From bea15d5139b9eef3ca368b95c4dbd6621bff9a5c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Sep 2016 17:19:43 +0200 Subject: iio:max1027: Use iio_trigger_validate_own_device() helper Use the new iio_trigger_validate_own_device() to verify that the trigger can only be attached to the matching IIO device rather than using a custom variant. While the implementation of iio_trigger_validate_own_device() and the custom variant and are not identical their behaviour is. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1027.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index d60181822833..3b7c4f78f37a 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -362,17 +362,6 @@ static int max1027_set_trigger_state(struct iio_trigger *trig, bool state) return 0; } -static int max1027_validate_device(struct iio_trigger *trig, - struct iio_dev *indio_dev) -{ - struct iio_dev *indio = iio_trigger_get_drvdata(trig); - - if (indio != indio_dev) - return -EINVAL; - - return 0; -} - static irqreturn_t max1027_trigger_handler(int irq, void *private) { struct iio_poll_func *pf = (struct iio_poll_func *)private; @@ -393,7 +382,7 @@ static irqreturn_t max1027_trigger_handler(int irq, void *private) static const struct iio_trigger_ops max1027_trigger_ops = { .owner = THIS_MODULE, - .validate_device = &max1027_validate_device, + .validate_device = &iio_trigger_validate_own_device, .set_trigger_state = &max1027_set_trigger_state, }; -- cgit v1.2.3 From aa16c6bd0e09dc043b6ea200f729c8c440d40b57 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Sep 2016 17:19:44 +0200 Subject: iio:adc: Add support for AD7766/AD7767 Add support for the AD7766, AD7766-1, AD7766-2, AD7767, AD7767-1, AD7767-2 Analog to Digital converters. It's a family of single channel 24-bit SAR ADCs. They are all digital interface compatible and the main difference is the internal decimation rate and analog performance. For communication with the host processor a SPI interface is used. In addition the part has a data ready pin that is pulsed for one MCLK cycle when a conversion has completed and can be used as a IIO trigger. Datasheets: http://www.analog.com/media/en/technical-documentation/data-sheets/AD7766.pdf http://www.analog.com/media/en/technical-documentation/data-sheets/AD7767.pdf Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 12 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ad7766.c | 330 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 drivers/iio/adc/ad7766.c (limited to 'drivers') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 7edcf3238620..60426685d55d 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -58,6 +58,18 @@ config AD7476 To compile this driver as a module, choose M here: the module will be called ad7476. +config AD7766 + tristate "Analog Devices AD7766/AD7767 ADC driver" + depends on SPI_MASTER + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Analog Devices AD7766, AD7766-1, + AD7766-2, AD7767, AD7767-1, AD7767-2 SPI analog to digital converters. + + To compile this driver as a module, choose M here: the module will be + called ad7766. + config AD7791 tristate "Analog Devices AD7791 ADC driver" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 7a40c04c311f..96894b32300d 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7298) += ad7298.o obj-$(CONFIG_AD7923) += ad7923.o obj-$(CONFIG_AD7476) += ad7476.o +obj-$(CONFIG_AD7766) += ad7766.o obj-$(CONFIG_AD7791) += ad7791.o obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7887) += ad7887.o diff --git a/drivers/iio/adc/ad7766.c b/drivers/iio/adc/ad7766.c new file mode 100644 index 000000000000..d906686c48eb --- /dev/null +++ b/drivers/iio/adc/ad7766.c @@ -0,0 +1,330 @@ +/* + * AD7766/AD7767 SPI ADC driver + * + * Copyright 2016 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct ad7766_chip_info { + unsigned int decimation_factor; +}; + +enum { + AD7766_SUPPLY_AVDD = 0, + AD7766_SUPPLY_DVDD = 1, + AD7766_SUPPLY_VREF = 2, + AD7766_NUM_SUPPLIES = 3 +}; + +struct ad7766 { + const struct ad7766_chip_info *chip_info; + struct spi_device *spi; + struct clk *mclk; + struct gpio_desc *pd_gpio; + struct regulator_bulk_data reg[AD7766_NUM_SUPPLIES]; + + struct iio_trigger *trig; + + struct spi_transfer xfer; + struct spi_message msg; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + * Make the buffer large enough for one 24 bit sample and one 64 bit + * aligned 64 bit timestamp. + */ + unsigned char data[ALIGN(3, sizeof(s64)) + sizeof(s64)] + ____cacheline_aligned; +}; + +/* + * AD7766 and AD7767 variations are interface compatible, the main difference is + * analog performance. Both parts will use the same ID. + */ +enum ad7766_device_ids { + ID_AD7766, + ID_AD7766_1, + ID_AD7766_2, +}; + +static irqreturn_t ad7766_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7766 *ad7766 = iio_priv(indio_dev); + int ret; + + ret = spi_sync(ad7766->spi, &ad7766->msg); + if (ret < 0) + goto done; + + iio_push_to_buffers_with_timestamp(indio_dev, ad7766->data, + pf->timestamp); +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int ad7766_preenable(struct iio_dev *indio_dev) +{ + struct ad7766 *ad7766 = iio_priv(indio_dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ad7766->reg), ad7766->reg); + if (ret < 0) { + dev_err(&ad7766->spi->dev, "Failed to enable supplies: %d\n", + ret); + return ret; + } + + ret = clk_prepare_enable(ad7766->mclk); + if (ret < 0) { + dev_err(&ad7766->spi->dev, "Failed to enable MCLK: %d\n", ret); + regulator_bulk_disable(ARRAY_SIZE(ad7766->reg), ad7766->reg); + return ret; + } + + if (ad7766->pd_gpio) + gpiod_set_value(ad7766->pd_gpio, 0); + + return 0; +} + +static int ad7766_postdisable(struct iio_dev *indio_dev) +{ + struct ad7766 *ad7766 = iio_priv(indio_dev); + + if (ad7766->pd_gpio) + gpiod_set_value(ad7766->pd_gpio, 1); + + /* + * The PD pin is synchronous to the clock, so give it some time to + * notice the change before we disable the clock. + */ + msleep(20); + + clk_disable_unprepare(ad7766->mclk); + regulator_bulk_disable(ARRAY_SIZE(ad7766->reg), ad7766->reg); + + return 0; +} + +static int ad7766_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, int *val2, long info) +{ + struct ad7766 *ad7766 = iio_priv(indio_dev); + struct regulator *vref = ad7766->reg[AD7766_SUPPLY_VREF].consumer; + int scale_uv; + + switch (info) { + case IIO_CHAN_INFO_SCALE: + scale_uv = regulator_get_voltage(vref); + if (scale_uv < 0) + return scale_uv; + *val = scale_uv / 1000; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = clk_get_rate(ad7766->mclk) / + ad7766->chip_info->decimation_factor; + return IIO_VAL_INT; + } + return -EINVAL; +} + +static const struct iio_chan_spec ad7766_channels[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static const struct ad7766_chip_info ad7766_chip_info[] = { + [ID_AD7766] = { + .decimation_factor = 8, + }, + [ID_AD7766_1] = { + .decimation_factor = 16, + }, + [ID_AD7766_2] = { + .decimation_factor = 32, + }, +}; + +static const struct iio_buffer_setup_ops ad7766_buffer_setup_ops = { + .preenable = &ad7766_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, + .postdisable = &ad7766_postdisable, +}; + +static const struct iio_info ad7766_info = { + .driver_module = THIS_MODULE, + .read_raw = &ad7766_read_raw, +}; + +static irqreturn_t ad7766_irq(int irq, void *private) +{ + iio_trigger_poll(private); + return IRQ_HANDLED; +} + +static int ad7766_set_trigger_state(struct iio_trigger *trig, bool enable) +{ + struct ad7766 *ad7766 = iio_trigger_get_drvdata(trig); + + if (enable) + enable_irq(ad7766->spi->irq); + else + disable_irq(ad7766->spi->irq); + + return 0; +} + +static const struct iio_trigger_ops ad7766_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = ad7766_set_trigger_state, + .validate_device = iio_trigger_validate_own_device, +}; + +static int ad7766_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct iio_dev *indio_dev; + struct ad7766 *ad7766; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*ad7766)); + if (!indio_dev) + return -ENOMEM; + + ad7766 = iio_priv(indio_dev); + ad7766->chip_info = &ad7766_chip_info[id->driver_data]; + + ad7766->mclk = devm_clk_get(&spi->dev, "mclk"); + if (IS_ERR(ad7766->mclk)) + return PTR_ERR(ad7766->mclk); + + ad7766->reg[AD7766_SUPPLY_AVDD].supply = "avdd"; + ad7766->reg[AD7766_SUPPLY_DVDD].supply = "dvdd"; + ad7766->reg[AD7766_SUPPLY_VREF].supply = "vref"; + + ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(ad7766->reg), + ad7766->reg); + if (IS_ERR(ad7766->reg)) + return PTR_ERR(ad7766->reg); + + ad7766->pd_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown", + GPIOD_OUT_HIGH); + if (IS_ERR(ad7766->pd_gpio)) + return PTR_ERR(ad7766->pd_gpio); + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad7766_channels; + indio_dev->num_channels = ARRAY_SIZE(ad7766_channels); + indio_dev->info = &ad7766_info; + + if (spi->irq > 0) { + ad7766->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", + indio_dev->name, indio_dev->id); + if (!ad7766->trig) + return -ENOMEM; + + ad7766->trig->ops = &ad7766_trigger_ops; + ad7766->trig->dev.parent = &spi->dev; + iio_trigger_set_drvdata(ad7766->trig, ad7766); + + ret = devm_request_irq(&spi->dev, spi->irq, ad7766_irq, + IRQF_TRIGGER_FALLING, dev_name(&spi->dev), + ad7766->trig); + if (ret < 0) + return ret; + + /* + * The device generates interrupts as long as it is powered up. + * Some platforms might not allow the option to power it down so + * disable the interrupt to avoid extra load on the system + */ + disable_irq(spi->irq); + + ret = devm_iio_trigger_register(&spi->dev, ad7766->trig); + if (ret) + return ret; + } + + spi_set_drvdata(spi, indio_dev); + + ad7766->spi = spi; + + /* First byte always 0 */ + ad7766->xfer.rx_buf = &ad7766->data[1]; + ad7766->xfer.len = 3; + + spi_message_init(&ad7766->msg); + spi_message_add_tail(&ad7766->xfer, &ad7766->msg); + + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + &iio_pollfunc_store_time, &ad7766_trigger_handler, + &ad7766_buffer_setup_ops); + if (ret) + return ret; + + ret = devm_iio_device_register(&spi->dev, indio_dev); + if (ret) + return ret; + return 0; +} + +static const struct spi_device_id ad7766_id[] = { + {"ad7766", ID_AD7766}, + {"ad7766-1", ID_AD7766_1}, + {"ad7766-2", ID_AD7766_2}, + {"ad7767", ID_AD7766}, + {"ad7767-1", ID_AD7766_1}, + {"ad7767-2", ID_AD7766_2}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad7766_id); + +static struct spi_driver ad7766_driver = { + .driver = { + .name = "ad7766", + }, + .probe = ad7766_probe, + .id_table = ad7766_id, +}; +module_spi_driver(ad7766_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD7766 and AD7767 ADCs driver support"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 2a20af722dde611b6b060af18dff651a8db96073 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 24 Sep 2016 21:44:55 +0530 Subject: drivers: iio: light: Fix sparse warnings Fixing below warnings: drivers/iio/light/max44000.c:217:18: warning: cast to restricted __be16 drivers/iio/light/max44000.c:217:18: warning: cast to restricted __be16 drivers/iio/light/max44000.c:217:18: warning: cast to restricted __be16 drivers/iio/light/max44000.c:217:18: warning: cast to restricted __be16 Signed-off-by: Sandhya Bankar Signed-off-by: Jonathan Cameron --- drivers/iio/light/max44000.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index 6511b20a2a29..a144ca3461fc 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -204,17 +204,18 @@ static int max44000_write_alspga(struct max44000_data *data, int val) static int max44000_read_alsval(struct max44000_data *data) { u16 regval; + __be16 val; int alstim, ret; ret = regmap_bulk_read(data->regmap, MAX44000_REG_ALS_DATA_HI, - ®val, sizeof(regval)); + &val, sizeof(val)); if (ret < 0) return ret; alstim = ret = max44000_read_alstim(data); if (ret < 0) return ret; - regval = be16_to_cpu(regval); + regval = be16_to_cpu(val); /* * Overflow is explained on datasheet page 17. -- cgit v1.2.3 From 0023e67dd8951737588b8af0469446df3ec52afe Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 23 Sep 2016 23:04:07 -0700 Subject: iio: inkern: add iio_read_channel_offset helper Allow access to underlying channel IIO_CHAN_INFO_OFFSET from a consumer. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 39 ++++++++++++++++++++++++++------------- include/linux/iio/consumer.h | 13 +++++++++++++ 2 files changed, 39 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index c4757e6367e7..29df11572858 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -658,6 +658,31 @@ err_unlock: } EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); +static int iio_read_channel_attribute(struct iio_channel *chan, + int *val, int *val2, + enum iio_chan_info_enum attribute) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = iio_channel_read(chan, val, val2, attribute); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} + +int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2) +{ + return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_OFFSET); +} +EXPORT_SYMBOL_GPL(iio_read_channel_offset); + int iio_read_channel_processed(struct iio_channel *chan, int *val) { int ret; @@ -687,19 +712,7 @@ EXPORT_SYMBOL_GPL(iio_read_channel_processed); int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) { - int ret; - - mutex_lock(&chan->indio_dev->info_exist_lock); - if (chan->indio_dev->info == NULL) { - ret = -ENODEV; - goto err_unlock; - } - - ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE); -err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); - - return ret; + return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_SCALE); } EXPORT_SYMBOL_GPL(iio_read_channel_scale); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 9edccfba1ffb..638157234357 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -235,6 +235,19 @@ int iio_write_channel_raw(struct iio_channel *chan, int val); int iio_get_channel_type(struct iio_channel *channel, enum iio_chan_type *type); +/** + * iio_read_channel_offset() - read the offset value for a channel + * @chan: The channel being queried. + * @val: First part of value read back. + * @val2: Second part of value read back. + * + * Note returns a description of what is in val and val2, such + * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val + * + val2/1e6 + */ +int iio_read_channel_offset(struct iio_channel *chan, int *val, + int *val2); + /** * iio_read_channel_scale() - read the scale value for a channel * @chan: The channel being queried. -- cgit v1.2.3 From 92f0afb5b2be2e137ff223654af51f521dd74c3a Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Sun, 18 Sep 2016 15:42:15 -0700 Subject: iio: adc: ti-adc161s626: add regulator support Allow IIO_CHAN_INFO_SCALE and IIO_CHAN_INFO_OFFSET attributes for processing by checking voltage from a regulator. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/adc/ti-adc161s626.txt | 2 + drivers/iio/adc/ti-adc161s626.c | 55 +++++++++++++++++----- 2 files changed, 46 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt index 9ed2315781e4..3d25011f0c99 100644 --- a/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt +++ b/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt @@ -3,6 +3,7 @@ Required properties: - compatible: Should be "ti,adc141s626" or "ti,adc161s626" - reg: spi chip select number for the device + - vdda-supply: supply voltage to VDDA pin Recommended properties: - spi-max-frequency: Definition as per @@ -11,6 +12,7 @@ Recommended properties: Example: adc@0 { compatible = "ti,adc161s626"; + vdda-supply = <&vdda_fixed>; reg = <0>; spi-max-frequency = <4300000>; }; diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c index f94b69f9c288..4836a0d7aef5 100644 --- a/drivers/iio/adc/ti-adc161s626.c +++ b/drivers/iio/adc/ti-adc161s626.c @@ -27,6 +27,7 @@ #include #include #include +#include #define TI_ADC_DRV_NAME "ti-adc161s626" @@ -39,7 +40,9 @@ static const struct iio_chan_spec ti_adc141s626_channels[] = { { .type = IIO_VOLTAGE, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), .scan_index = 0, .scan_type = { .sign = 's', @@ -54,7 +57,9 @@ static const struct iio_chan_spec ti_adc161s626_channels[] = { { .type = IIO_VOLTAGE, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), .scan_index = 0, .scan_type = { .sign = 's', @@ -68,6 +73,8 @@ static const struct iio_chan_spec ti_adc161s626_channels[] = { struct ti_adc_data { struct iio_dev *indio_dev; struct spi_device *spi; + struct regulator *ref; + u8 read_size; u8 shift; @@ -135,18 +142,32 @@ static int ti_adc_read_raw(struct iio_dev *indio_dev, struct ti_adc_data *data = iio_priv(indio_dev); int ret; - if (mask != IIO_CHAN_INFO_RAW) - return -EINVAL; + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + ret = ti_adc_read_measurement(data, chan, val); + iio_device_release_direct_mode(indio_dev); - ret = ti_adc_read_measurement(data, chan, val); - iio_device_release_direct_mode(indio_dev); + if (ret) + return ret; - if (!ret) return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + ret = regulator_get_voltage(data->ref); + if (ret < 0) + return ret; + + *val = ret / 1000; + *val2 = chan->scan_type.realbits; + + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + *val = 1 << (chan->scan_type.realbits - 1); + return IIO_VAL_INT; + } return 0; } @@ -191,10 +212,17 @@ static int ti_adc_probe(struct spi_device *spi) break; } + data->ref = devm_regulator_get(&spi->dev, "vdda"); + if (!IS_ERR(data->ref)) { + ret = regulator_enable(data->ref); + if (ret < 0) + return ret; + } + ret = iio_triggered_buffer_setup(indio_dev, NULL, ti_adc_trigger_handler, NULL); if (ret) - return ret; + goto error_regulator_disable; ret = iio_device_register(indio_dev); if (ret) @@ -205,15 +233,20 @@ static int ti_adc_probe(struct spi_device *spi) error_unreg_buffer: iio_triggered_buffer_cleanup(indio_dev); +error_regulator_disable: + regulator_disable(data->ref); + return ret; } static int ti_adc_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ti_adc_data *data = iio_priv(indio_dev); iio_device_unregister(indio_dev); iio_triggered_buffer_cleanup(indio_dev); + regulator_disable(data->ref); return 0; } -- cgit v1.2.3 From 67e17300dc1d76091d2d513d6aa57e50af2c9648 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Sat, 24 Sep 2016 21:03:00 -0700 Subject: iio: potentiostat: add LMP91000 support Add support for the LMP91000 potentiostat which is used for chemical sensing applications. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- .../bindings/iio/potentiostat/lmp91000.txt | 30 ++ drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/iio/potentiostat/Kconfig | 22 + drivers/iio/potentiostat/Makefile | 6 + drivers/iio/potentiostat/lmp91000.c | 446 +++++++++++++++++++++ 6 files changed, 506 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt create mode 100644 drivers/iio/potentiostat/Kconfig create mode 100644 drivers/iio/potentiostat/Makefile create mode 100644 drivers/iio/potentiostat/lmp91000.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt b/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt new file mode 100644 index 000000000000..b9b621e94cd7 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt @@ -0,0 +1,30 @@ +* Texas Instruments LMP91000 potentiostat + +http://www.ti.com/lit/ds/symlink/lmp91000.pdf + +Required properties: + + - compatible: should be "ti,lmp91000" + - reg: the I2C address of the device + - io-channels: the phandle of the iio provider + + - ti,external-tia-resistor: if the property ti,tia-gain-ohm is not defined this + needs to be set to signal that an external resistor value is being used. + +Optional properties: + + - ti,tia-gain-ohm: ohm value of the internal resistor for the transimpedance + amplifier. Must be 2750, 3500, 7000, 14000, 35000, 120000, or 350000 ohms. + + - ti,rload-ohm: ohm value of the internal resistor load applied to the gas + sensor. Must be 10, 33, 50, or 100 (default) ohms. + +Example: + +lmp91000@48 { + compatible = "ti,lmp91000"; + reg = <0x48>; + ti,tia-gain-ohm = <7500>; + ti,rload = <100>; + io-channels = <&adc>; +}; diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 6743b18194fb..a31a8cf2c330 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -87,6 +87,7 @@ if IIO_TRIGGER source "drivers/iio/trigger/Kconfig" endif #IIO_TRIGGER source "drivers/iio/potentiometer/Kconfig" +source "drivers/iio/potentiostat/Kconfig" source "drivers/iio/pressure/Kconfig" source "drivers/iio/proximity/Kconfig" source "drivers/iio/temperature/Kconfig" diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 87e4c4369e2f..2b6e2762a886 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -29,6 +29,7 @@ obj-y += light/ obj-y += magnetometer/ obj-y += orientation/ obj-y += potentiometer/ +obj-y += potentiostat/ obj-y += pressure/ obj-y += proximity/ obj-y += temperature/ diff --git a/drivers/iio/potentiostat/Kconfig b/drivers/iio/potentiostat/Kconfig new file mode 100644 index 000000000000..1e3baf2cc97d --- /dev/null +++ b/drivers/iio/potentiostat/Kconfig @@ -0,0 +1,22 @@ +# +# Potentiostat drivers +# +# When adding new entries keep the list in alphabetical order + +menu "Digital potentiostats" + +config LMP91000 + tristate "Texas Instruments LMP91000 potentiostat driver" + depends on I2C + select REGMAP_I2C + select IIO_BUFFER + select IIO_BUFFER_CB + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for the Texas Instruments + LMP91000 digital potentiostat chip. + + To compile this driver as a module, choose M here: the + module will be called lmp91000 + +endmenu diff --git a/drivers/iio/potentiostat/Makefile b/drivers/iio/potentiostat/Makefile new file mode 100644 index 000000000000..64d315ef4449 --- /dev/null +++ b/drivers/iio/potentiostat/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for industrial I/O potentiostat drivers +# + +# When adding new entries keep the list in alphabetical order +obj-$(CONFIG_LMP91000) += lmp91000.o diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c new file mode 100644 index 000000000000..e22714365022 --- /dev/null +++ b/drivers/iio/potentiostat/lmp91000.c @@ -0,0 +1,446 @@ +/* + * lmp91000.c - Support for Texas Instruments digital potentiostats + * + * Copyright (C) 2016 Matt Ranostay + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * TODO: bias voltage + polarity control, and multiple chip support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LMP91000_REG_LOCK 0x01 +#define LMP91000_REG_TIACN 0x10 +#define LMP91000_REG_TIACN_GAIN_SHIFT 2 + +#define LMP91000_REG_REFCN 0x11 +#define LMP91000_REG_REFCN_EXT_REF 0x20 +#define LMP91000_REG_REFCN_50_ZERO 0x80 + +#define LMP91000_REG_MODECN 0x12 +#define LMP91000_REG_MODECN_3LEAD 0x03 +#define LMP91000_REG_MODECN_TEMP 0x07 + +#define LMP91000_DRV_NAME "lmp91000" + +static const int lmp91000_tia_gain[] = { 0, 2750, 3500, 7000, 14000, 35000, + 120000, 350000 }; + +static const int lmp91000_rload[] = { 10, 33, 50, 100 }; + +#define LMP91000_TEMP_BASE -40 + +static const u16 lmp91000_temp_lut[] = { + 1875, 1867, 1860, 1852, 1844, 1836, 1828, 1821, 1813, 1805, + 1797, 1789, 1782, 1774, 1766, 1758, 1750, 1742, 1734, 1727, + 1719, 1711, 1703, 1695, 1687, 1679, 1671, 1663, 1656, 1648, + 1640, 1632, 1624, 1616, 1608, 1600, 1592, 1584, 1576, 1568, + 1560, 1552, 1544, 1536, 1528, 1520, 1512, 1504, 1496, 1488, + 1480, 1472, 1464, 1456, 1448, 1440, 1432, 1424, 1415, 1407, + 1399, 1391, 1383, 1375, 1367, 1359, 1351, 1342, 1334, 1326, + 1318, 1310, 1302, 1293, 1285, 1277, 1269, 1261, 1253, 1244, + 1236, 1228, 1220, 1212, 1203, 1195, 1187, 1179, 1170, 1162, + 1154, 1146, 1137, 1129, 1121, 1112, 1104, 1096, 1087, 1079, + 1071, 1063, 1054, 1046, 1038, 1029, 1021, 1012, 1004, 996, + 987, 979, 971, 962, 954, 945, 937, 929, 920, 912, + 903, 895, 886, 878, 870, 861 }; + +static const struct regmap_config lmp91000_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +struct lmp91000_data { + struct regmap *regmap; + struct device *dev; + + struct iio_trigger *trig; + struct iio_cb_buffer *cb_buffer; + struct iio_channel *adc_chan; + + struct completion completion; + u8 chan_select; + + u32 buffer[4]; /* 64-bit data + 64-bit timestamp */ +}; + +static const struct iio_chan_spec lmp91000_channels[] = { + { /* chemical channel mV */ + .type = IIO_VOLTAGE, + .channel = 0, + .address = LMP91000_REG_MODECN_3LEAD, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), + { /* temperature channel mV */ + .type = IIO_TEMP, + .channel = 1, + .address = LMP91000_REG_MODECN_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, + }, +}; + +static int lmp91000_read(struct lmp91000_data *data, int channel, int *val) +{ + int state, ret; + + ret = regmap_read(data->regmap, LMP91000_REG_MODECN, &state); + if (ret) + return -EINVAL; + + ret = regmap_write(data->regmap, LMP91000_REG_MODECN, channel); + if (ret) + return -EINVAL; + + /* delay till first temperature reading is complete */ + if ((state != channel) && (channel == LMP91000_REG_MODECN_TEMP)) + usleep_range(3000, 4000); + + data->chan_select = channel != LMP91000_REG_MODECN_3LEAD; + + iio_trigger_poll_chained(data->trig); + + ret = wait_for_completion_timeout(&data->completion, HZ); + reinit_completion(&data->completion); + + if (!ret) + return -ETIMEDOUT; + + *val = data->buffer[data->chan_select]; + + return 0; +} + +static irqreturn_t lmp91000_buffer_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct lmp91000_data *data = iio_priv(indio_dev); + int ret, val; + + memset(data->buffer, 0, sizeof(data->buffer)); + + ret = lmp91000_read(data, LMP91000_REG_MODECN_3LEAD, &val); + if (!ret) { + data->buffer[0] = val; + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns(indio_dev)); + } + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int lmp91000_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct lmp91000_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: { + int ret = iio_channel_start_all_cb(data->cb_buffer); + + if (ret) + return ret; + + ret = lmp91000_read(data, chan->address, val); + + iio_channel_stop_all_cb(data->cb_buffer); + + if (ret) + return ret; + + if (mask == IIO_CHAN_INFO_PROCESSED) { + int tmp, i; + + ret = iio_convert_raw_to_processed(data->adc_chan, + *val, &tmp, 1); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(lmp91000_temp_lut); i++) + if (lmp91000_temp_lut[i] < tmp) + break; + + *val = (LMP91000_TEMP_BASE + i) * 1000; + } + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_OFFSET: + return iio_read_channel_offset(data->adc_chan, val, val2); + case IIO_CHAN_INFO_SCALE: + return iio_read_channel_scale(data->adc_chan, val, val2); + } + + return -EINVAL; +} + +static const struct iio_info lmp91000_info = { + .driver_module = THIS_MODULE, + .read_raw = lmp91000_read_raw, +}; + +static int lmp91000_read_config(struct lmp91000_data *data) +{ + struct device *dev = data->dev; + struct device_node *np = dev->of_node; + unsigned int reg, val; + int i, ret; + + ret = of_property_read_u32(np, "ti,tia-gain-ohm", &val); + if (ret) { + if (of_property_read_bool(np, "ti,external-tia-resistor")) + val = 0; + else { + dev_err(dev, "no ti,tia-gain-ohm defined"); + return ret; + } + } + + ret = -EINVAL; + for (i = 0; i < ARRAY_SIZE(lmp91000_tia_gain); i++) { + if (lmp91000_tia_gain[i] == val) { + reg = i << LMP91000_REG_TIACN_GAIN_SHIFT; + ret = 0; + break; + } + } + + if (ret) { + dev_err(dev, "invalid ti,tia-gain-ohm %d\n", val); + return ret; + } + + ret = of_property_read_u32(np, "ti,rload-ohm", &val); + if (ret) { + val = 100; + dev_info(dev, "no ti,rload-ohm defined, default to %d\n", val); + } + + ret = -EINVAL; + for (i = 0; i < ARRAY_SIZE(lmp91000_rload); i++) { + if (lmp91000_rload[i] == val) { + reg |= i; + ret = 0; + break; + } + } + + if (ret) { + dev_err(dev, "invalid ti,rload-ohm %d\n", val); + return ret; + } + + regmap_write(data->regmap, LMP91000_REG_LOCK, 0); + regmap_write(data->regmap, LMP91000_REG_TIACN, reg); + regmap_write(data->regmap, LMP91000_REG_REFCN, LMP91000_REG_REFCN_EXT_REF + | LMP91000_REG_REFCN_50_ZERO); + regmap_write(data->regmap, LMP91000_REG_LOCK, 1); + + return 0; +} + +static int lmp91000_buffer_cb(const void *val, void *private) +{ + struct iio_dev *indio_dev = private; + struct lmp91000_data *data = iio_priv(indio_dev); + + data->buffer[data->chan_select] = *((int *)val); + complete_all(&data->completion); + + return 0; +} + +static const struct iio_trigger_ops lmp91000_trigger_ops = { + .owner = THIS_MODULE, +}; + + +static int lmp91000_buffer_preenable(struct iio_dev *indio_dev) +{ + struct lmp91000_data *data = iio_priv(indio_dev); + + return iio_channel_start_all_cb(data->cb_buffer); +} + +static int lmp91000_buffer_predisable(struct iio_dev *indio_dev) +{ + struct lmp91000_data *data = iio_priv(indio_dev); + + iio_channel_stop_all_cb(data->cb_buffer); + + return 0; +} + +static const struct iio_buffer_setup_ops lmp91000_buffer_setup_ops = { + .preenable = lmp91000_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = lmp91000_buffer_predisable, +}; + +static int lmp91000_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct lmp91000_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &lmp91000_info; + indio_dev->channels = lmp91000_channels; + indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels); + indio_dev->name = LMP91000_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + i2c_set_clientdata(client, indio_dev); + + data = iio_priv(indio_dev); + data->dev = dev; + data->regmap = devm_regmap_init_i2c(client, &lmp91000_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(dev, "regmap initialization failed.\n"); + return PTR_ERR(data->regmap); + } + + data->trig = devm_iio_trigger_alloc(data->dev, "%s-mux%d", + indio_dev->name, indio_dev->id); + if (!data->trig) { + dev_err(dev, "cannot allocate iio trigger.\n"); + return -ENOMEM; + } + + data->trig->ops = &lmp91000_trigger_ops; + data->trig->dev.parent = dev; + init_completion(&data->completion); + + ret = lmp91000_read_config(data); + if (ret) + return ret; + + ret = iio_trigger_set_immutable(iio_channel_cb_get_iio_dev(data->cb_buffer), + data->trig); + if (ret) { + dev_err(dev, "cannot set immutable trigger.\n"); + return ret; + } + + ret = iio_trigger_register(data->trig); + if (ret) { + dev_err(dev, "cannot register iio trigger.\n"); + return ret; + } + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + &lmp91000_buffer_handler, + &lmp91000_buffer_setup_ops); + if (ret) + goto error_unreg_trigger; + + data->cb_buffer = iio_channel_get_all_cb(dev, &lmp91000_buffer_cb, + indio_dev); + + if (IS_ERR(data->cb_buffer)) { + if (PTR_ERR(data->cb_buffer) == -ENODEV) + ret = -EPROBE_DEFER; + else + ret = PTR_ERR(data->cb_buffer); + + goto error_unreg_buffer; + } + + data->adc_chan = iio_channel_cb_get_channels(data->cb_buffer); + + ret = iio_device_register(indio_dev); + if (ret) + goto error_unreg_cb_buffer; + + return 0; + +error_unreg_cb_buffer: + iio_channel_release_all_cb(data->cb_buffer); + +error_unreg_buffer: + iio_triggered_buffer_cleanup(indio_dev); + +error_unreg_trigger: + iio_trigger_unregister(data->trig); + + return ret; +} + +static int lmp91000_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct lmp91000_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + iio_channel_stop_all_cb(data->cb_buffer); + iio_channel_release_all_cb(data->cb_buffer); + + iio_triggered_buffer_cleanup(indio_dev); + iio_trigger_unregister(data->trig); + + return 0; +} + +static const struct of_device_id lmp91000_of_match[] = { + { .compatible = "ti,lmp91000", }, + { }, +}; +MODULE_DEVICE_TABLE(of, lmp91000_of_match); + +static const struct i2c_device_id lmp91000_id[] = { + { "lmp91000", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, lmp91000_id); + +static struct i2c_driver lmp91000_driver = { + .driver = { + .name = LMP91000_DRV_NAME, + .of_match_table = of_match_ptr(lmp91000_of_match), + }, + .probe = lmp91000_probe, + .remove = lmp91000_remove, + .id_table = lmp91000_id, +}; +module_i2c_driver(lmp91000_driver); + +MODULE_AUTHOR("Matt Ranostay "); +MODULE_DESCRIPTION("LMP91000 digital potentiostat"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 69c72ec9c80bbd206c6fac73874d73e69cc623b4 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 25 Sep 2016 18:33:17 +0530 Subject: drivers: iio: magnetometer: Fix sparse endianness warnings cast to restricted __be16 Fix the following sparse endianness warnings: drivers/iio/magnetometer/ak8975.c:716:16: warning: cast to restricted __le16 drivers/iio/magnetometer/ak8975.c:837:19: warning: cast to restricted __le16 drivers/iio/magnetometer/ak8975.c:838:19: warning: cast to restricted __le16 drivers/iio/magnetometer/ak8975.c:839:19: warning: cast to restricted __le16 Signed-off-by: Sandhya Bankar Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index af8606cc7812..825369fb1c57 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -690,6 +690,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) struct ak8975_data *data = iio_priv(indio_dev); const struct i2c_client *client = data->client; const struct ak_def *def = data->def; + __le16 rval; u16 buff; int ret; @@ -703,7 +704,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) ret = i2c_smbus_read_i2c_block_data_or_emulated( client, def->data_regs[index], - sizeof(buff), (u8*)&buff); + sizeof(rval), (u8*)&rval); if (ret < 0) goto exit; @@ -713,7 +714,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) pm_runtime_put_autosuspend(&data->client->dev); /* Swap bytes and convert to valid range. */ - buff = le16_to_cpu(buff); + buff = le16_to_cpu(rval); *val = clamp_t(s16, buff, -def->range, def->range); return IIO_VAL_INT; @@ -813,6 +814,7 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev) const struct ak_def *def = data->def; int ret; s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */ + __le16 fval[3]; mutex_lock(&data->lock); @@ -826,17 +828,17 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev) */ ret = i2c_smbus_read_i2c_block_data_or_emulated(client, def->data_regs[0], - 3 * sizeof(buff[0]), - (u8 *)buff); + 3 * sizeof(fval[0]), + (u8 *)fval); if (ret < 0) goto unlock; mutex_unlock(&data->lock); /* Clamp to valid range. */ - buff[0] = clamp_t(s16, le16_to_cpu(buff[0]), -def->range, def->range); - buff[1] = clamp_t(s16, le16_to_cpu(buff[1]), -def->range, def->range); - buff[2] = clamp_t(s16, le16_to_cpu(buff[2]), -def->range, def->range); + buff[0] = clamp_t(s16, le16_to_cpu(fval[0]), -def->range, def->range); + buff[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range); + buff[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range); iio_push_to_buffers_with_timestamp(indio_dev, buff, iio_get_time_ns(indio_dev)); -- cgit v1.2.3 From 7fd1accc9fc46c27687f2ea767d84c146790ef1c Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Sun, 25 Sep 2016 07:41:05 -0400 Subject: staging: iio: isl29018: remove unused variable and defines Removes unused variable and associated #defines that was found using make W=1. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index a767a43c995c..2a055d6c32ba 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -62,16 +62,6 @@ #define ISL29035_BOUT_SHIFT 0x07 #define ISL29035_BOUT_MASK (0x01 << ISL29035_BOUT_SHIFT) -#define ISL29018_INT_TIME_AVAIL "0.090000 0.005630 0.000351 0.000021" -#define ISL29023_INT_TIME_AVAIL "0.090000 0.005600 0.000352 0.000022" -#define ISL29035_INT_TIME_AVAIL "0.105000 0.006500 0.000410 0.000025" - -static const char * const int_time_avail[] = { - ISL29018_INT_TIME_AVAIL, - ISL29023_INT_TIME_AVAIL, - ISL29035_INT_TIME_AVAIL, -}; - enum isl29018_int_time { ISL29018_INT_TIME_16, ISL29018_INT_TIME_12, -- cgit v1.2.3 From 528021fcd21fdffad83563710f1186d9b3d21718 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Sun, 25 Sep 2016 07:41:06 -0400 Subject: staging: iio: isl29018: made error handling consistent Changed the processing of IIO_CHAN_INFO_INT_TIME in isl29018_write_raw() to unlock the mutex and return at the end of the function if invalid input is passed in. This makes the error handling code consistent with the processing of IIO_CHAN_INFO_CALIBSCALE and IIO_CHAN_INFO_SCALE within the same function. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 2a055d6c32ba..f03122c66045 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -356,13 +356,8 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, } break; case IIO_CHAN_INFO_INT_TIME: - if (chan->type == IIO_LIGHT) { - if (val) { - mutex_unlock(&chip->lock); - return -EINVAL; - } + if (chan->type == IIO_LIGHT && !val) ret = isl29018_set_integration_time(chip, val2); - } break; case IIO_CHAN_INFO_SCALE: if (chan->type == IIO_LIGHT) -- cgit v1.2.3 From ea908ab69e7531bcebaf42e9c0c6f0b95a04330f Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Sun, 25 Sep 2016 07:41:07 -0400 Subject: staging: iio: isl29018: fix comparison between signed and unsigned integers Fixes warning found by make W=2: warning: comparison between signed and unsigned integer expressions Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index f03122c66045..30dc1da95459 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -100,7 +100,8 @@ struct isl29018_chip { static int isl29018_set_integration_time(struct isl29018_chip *chip, unsigned int utime) { - int i, ret; + unsigned int i; + int ret; unsigned int int_time, new_int_time; for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) { @@ -135,7 +136,8 @@ static int isl29018_set_integration_time(struct isl29018_chip *chip, static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale) { - int i, ret; + unsigned int i; + int ret; struct isl29018_scale new_scale; for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) { @@ -271,7 +273,8 @@ static ssize_t isl29018_show_scale_available(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); - int i, len = 0; + unsigned int i; + int len = 0; for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) len += sprintf(buf + len, "%d.%06d ", @@ -288,7 +291,8 @@ static ssize_t isl29018_show_int_time_available(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); - int i, len = 0; + unsigned int i; + int len = 0; for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) len += sprintf(buf + len, "0.%06d ", -- cgit v1.2.3 From d306ddbad1b21287eb4a779dbc1d1e782f2fb1e1 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Mon, 26 Sep 2016 10:31:38 +0530 Subject: Staging:iio:adc:ad7280a: constify attribute_group structures Check for attribute_group structures that are only stored in the attrs filed of iio_info structure. As the attrs field of iio_info structures is constant, so these attribute_group structures can also be declared constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; struct iio_info x; @@ x.attrs=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: drivers/staging/iio/adc/ad7280a.o text data bss dec hex filename 6487 584 776 7847 1ea7 drivers/staging/iio/adc/ad7280a.o File size after: drivers/staging/iio/adc/ad7280a.o text data bss dec hex filename 6551 544 776 7871 1ebf drivers/staging/iio/adc/ad7280a.o Signed-off-by: Bhumika Goyal Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7280a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 2177f1dd2b5d..b460dda7eb65 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -478,7 +478,7 @@ static ssize_t ad7280_store_balance_timer(struct device *dev, static struct attribute *ad7280_attributes[AD7280A_MAX_CHAIN * AD7280A_CELLS_PER_DEV * 2 + 1]; -static struct attribute_group ad7280_attrs_group = { +static const struct attribute_group ad7280_attrs_group = { .attrs = ad7280_attributes, }; -- cgit v1.2.3 From 1cb357695849542b71ad8f76b2c2cba308b27e24 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Mon, 26 Sep 2016 10:31:39 +0530 Subject: Staging:iio:light:tsl2583: constify attribute_group structures Check for attribute_group structures that are only stored in the attrs filed of iio_info structure. As the attrs field of iio_info structures is constant, so these attribute_group structures can also be declared constant. Done using coccinelle @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; struct iio_info x; @@ x.attrs=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: drivers/staging/iio/light/tsl2583.o text data bss dec hex filename 6529 1052 0 7581 1d9d drivers/staging/iio/light/tsl2583.o File size after: drivers/staging/iio/light/tsl2583.o text data bss dec hex filename 6593 988 0 7581 1d9d drivers/staging/iio/light/tsl2583.o Signed-off-by: Bhumika Goyal Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 05b4ad4e941c..08f1583ee34e 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -803,7 +803,7 @@ static struct attribute *sysfs_attrs_ctrl[] = { NULL }; -static struct attribute_group tsl2583_attribute_group = { +static const struct attribute_group tsl2583_attribute_group = { .attrs = sysfs_attrs_ctrl, }; -- cgit v1.2.3 From 577c543005dbb809b7880ac17c3f760b20af60e2 Mon Sep 17 00:00:00 2001 From: "Navare, Manasi D" Date: Tue, 27 Sep 2016 16:36:53 -0700 Subject: drm/i915: Code cleanup to use dev_priv and INTEL_GEN Replace dev with dev_priv and INTEL_INFO with INTEL_GEN v1: * Rebased on drm-nightly (Jani Nikula) * Separated from the link training patch series Signed-off-by: Manasi Navare Reviewed-by: Mika Kahola Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1475019413-19811-1-git-send-email-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 57da2b7510df..9448d898d80b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1297,10 +1297,10 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); - if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) || - (INTEL_INFO(dev)->gen >= 9)) + if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) || + IS_BROADWELL(dev_priv) || (INTEL_GEN(dev_priv) >= 9)) return true; else return false; @@ -1310,13 +1310,13 @@ static int intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); int size; - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { *source_rates = bxt_rates; size = ARRAY_SIZE(bxt_rates); - } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { *source_rates = skl_rates; size = ARRAY_SIZE(skl_rates); } else { -- cgit v1.2.3 From 7d7f8633a82763577727762ff3ac1df3017cb8fe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 11:30:46 +0300 Subject: drm/i915: Allow PCH DPLL sharing regardless of DPLL_SDVO_HIGH_SPEED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DPLL_SDVO_HIGH_SPEED must be set for SDVO/HDMI/DP, but nowhere is it forbidden to set it for LVDS/CRT as well. So let's also set it on CRT to make it possible to share the DPLL between HDMI and CRT. What that bit apparently does is enable the x5 clock to the port, which then pumps out the bits on both edges of the clock. The DAC doesn't need that clock since it's not pumping out bits, but I don't think it hurts to have the DPLL output that clock anyway. This is fairly important on IVB since it has only two DPLLs with three pipes. So trying to drive three or more PCH ports with three pipes is only possible when at least one of the DPLLs gets shared between two of the pipes. SNB doesn't really need to do this since it has only two pipes. It could be done to avoid enabling the second DPLL at all in certain cases, but I'm not sure that's such a huge win. So let's not do it for SNB, at least for now. On ILK it never makes sense as the DPLLs can't be shared. v2: Just always enable the high speed clock to keep things simple (Daniel) Beef up the commit message a bit (Daniel) Cc: Nick Yamane Cc: Daniel Vetter Cc: stable@vger.kernel.org Tested-by: Nick Yamane Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97204 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1474878646-17711-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Ander Conselvan de Oliveira --- drivers/gpu/drm/i915/intel_display.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e31d3e6d6647..8a24c4492ce2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9510,6 +9510,24 @@ static void ironlake_compute_dpll(struct intel_crtc *intel_crtc, if (intel_crtc_has_dp_encoder(crtc_state)) dpll |= DPLL_SDVO_HIGH_SPEED; + /* + * The high speed IO clock is only really required for + * SDVO/HDMI/DP, but we also enable it for CRT to make it + * possible to share the DPLL between CRT and HDMI. Enabling + * the clock needlessly does no real harm, except use up a + * bit of power potentially. + * + * We'll limit this to IVB with 3 pipes, since it has only two + * DPLLs and so DPLL sharing is the only way to get three pipes + * driving PCH ports at the same time. On SNB we could do this, + * and potentially avoid enabling the second DPLL, but it's not + * clear if it''s a win or loss power wise. No point in doing + * this on ILK at all since it has a fixed DPLL<->pipe mapping. + */ + if (INTEL_INFO(dev_priv)->num_pipes == 3 && + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) + dpll |= DPLL_SDVO_HIGH_SPEED; + /* compute bitmask from p1 value */ dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; /* also FPA1 */ -- cgit v1.2.3 From be754b101f70076f6375c84db4e8bcc517a4524f Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Wed, 28 Sep 2016 23:55:04 -0700 Subject: Revert "drm/i915: start adding dp mst audio" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts 'commit 3708d5e082c3 ("drm/i915: start adding dp mst audio")' because it breaks MST multi-monitor setups on some platforms. Fixes: 3708d5e082c3 ("drm/i915: start adding dp mst audio") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97907 Signed-off-by: Dhinakaran Pandiyan Reported-by: Kim Lidström Cc: Libin Yang Cc: Lyude Cc: Jani Nikula Cc: Rodrigo Vivi Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1475132104-2754-1-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 19 +------------------ drivers/gpu/drm/i915/intel_ddi.c | 20 +++++--------------- drivers/gpu/drm/i915/intel_dp_mst.c | 18 ------------------ drivers/gpu/drm/i915/intel_drv.h | 2 -- 4 files changed, 6 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6dd325145a0a..eb91444707d2 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2889,20 +2889,6 @@ static void intel_dp_info(struct seq_file *m, &intel_dp->aux); } -static void intel_dp_mst_info(struct seq_file *m, - struct intel_connector *intel_connector) -{ - struct intel_encoder *intel_encoder = intel_connector->encoder; - struct intel_dp_mst_encoder *intel_mst = - enc_to_mst(&intel_encoder->base); - struct intel_digital_port *intel_dig_port = intel_mst->primary; - struct intel_dp *intel_dp = &intel_dig_port->dp; - bool has_audio = drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, - intel_connector->port); - - seq_printf(m, "\taudio support: %s\n", yesno(has_audio)); -} - static void intel_hdmi_info(struct seq_file *m, struct intel_connector *intel_connector) { @@ -2945,10 +2931,7 @@ static void intel_connector_info(struct seq_file *m, switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_eDP: - if (intel_encoder->type == INTEL_OUTPUT_DP_MST) - intel_dp_mst_info(m, intel_connector); - else - intel_dp_info(m, intel_connector); + intel_dp_info(m, intel_connector); break; case DRM_MODE_CONNECTOR_LVDS: if (intel_encoder->type == INTEL_OUTPUT_LVDS) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 07cba6c0b1b5..35f0b7c9d0a6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2227,19 +2227,6 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) udelay(600); } -bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, - struct intel_crtc *intel_crtc) -{ - u32 temp; - - if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { - temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); - if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) - return true; - } - return false; -} - void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -2305,8 +2292,11 @@ void intel_ddi_get_config(struct intel_encoder *encoder, break; } - pipe_config->has_audio = - intel_ddi_is_audio_enabled(dev_priv, intel_crtc); + if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { + temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); + if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) + pipe_config->has_audio = true; + } if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.bpp && pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 2fc9f81fdd41..3ffbd69e4551 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -37,8 +37,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; struct intel_dp *intel_dp = &intel_dig_port->dp; - struct intel_connector *connector = - to_intel_connector(conn_state->connector); struct drm_atomic_state *state; int bpp; int lane_count, slots; @@ -61,8 +59,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, state = pipe_config->base.state; - if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, connector->port)) - pipe_config->has_audio = true; mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp); pipe_config->pbn = mst_pbn; @@ -88,7 +84,6 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, struct intel_dp *intel_dp = &intel_dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int ret; DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); @@ -99,10 +94,6 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, if (ret) { DRM_ERROR("failed to update payload %d\n", ret); } - if (old_crtc_state->has_audio) { - intel_audio_codec_disable(encoder); - intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); - } } static void intel_mst_post_disable_dp(struct intel_encoder *encoder, @@ -215,12 +206,6 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder, ret = drm_dp_check_act_status(&intel_dp->mst_mgr); ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr); - if (pipe_config->has_audio) { - DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", - pipe_name(intel_mst->pipe)); - intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); - intel_audio_codec_enable(encoder); - } } static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder, @@ -243,9 +228,6 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder, enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; u32 temp, flags = 0; - pipe_config->has_audio = - intel_ddi_is_audio_enabled(dev_priv, crtc); - temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) flags |= DRM_MODE_FLAG_PHSYNC; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5fdae7fcee07..3f6c1a8fbd09 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1156,8 +1156,6 @@ bool intel_ddi_pll_select(struct intel_crtc *crtc, void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp); bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); -bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, - struct intel_crtc *intel_crtc); void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); struct intel_encoder * -- cgit v1.2.3 From 7f60e200e254cd53ad1bd74a56bdd23e813ac4b7 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 29 Sep 2016 16:36:48 -0300 Subject: drm/i915/gen9: only add the planes actually affected by ddb changes We were previously adding all the planes owned by the CRTC even when the ddb partitioning didn't change for them. As a consequence, a lot of functions were being called when we were just moving the cursor around the screen, such as skylake_update_primary_plane(). This was causing flickering on the primary plane when moving the cursor. I'm not 100% sure which operation caused the flickering, but we were writing to a lot of registers, so it could be any of these writes. With this patch, just moving the mouse won't add the primary plane to the commit since it won't trigger a change in DDB partitioning. v2: Use skl_ddb_entry_equal() (Lyude). v3: Change Reported-and-bisected-by: to Reported-by: for checkpatch Fixes: 05a76d3d6ad1 ("drm/i915/skl: Ensure pipes with changed wms get added to the state") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97888 Cc: Mike Lothian Cc: stable@vger.kernel.org Reported-by: Mike Lothian Signed-off-by: Paulo Zanoni Signed-off-by: Lyude Link: http://patchwork.freedesktop.org/patch/msgid/1475177808-29955-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5d39ad2c2b7f..425544b1f733 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3966,6 +3966,41 @@ pipes_modified(struct drm_atomic_state *state) return ret; } +int +skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) +{ + struct drm_atomic_state *state = cstate->base.state; + struct drm_device *dev = state->dev; + struct drm_crtc *crtc = cstate->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; + struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; + struct drm_plane_state *plane_state; + struct drm_plane *plane; + enum pipe pipe = intel_crtc->pipe; + int id; + + WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc)); + + drm_for_each_plane_mask(plane, dev, crtc->state->plane_mask) { + id = skl_wm_plane_id(to_intel_plane(plane)); + + if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][id], + &new_ddb->plane[pipe][id]) && + skl_ddb_entry_equal(&cur_ddb->y_plane[pipe][id], + &new_ddb->y_plane[pipe][id])) + continue; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) + return PTR_ERR(plane_state); + } + + return 0; +} + static int skl_compute_ddb(struct drm_atomic_state *state) { @@ -4030,7 +4065,7 @@ skl_compute_ddb(struct drm_atomic_state *state) if (ret) return ret; - ret = drm_atomic_add_affected_planes(state, &intel_crtc->base); + ret = skl_ddb_add_affected_planes(cstate); if (ret) return ret; } -- cgit v1.2.3 From 028199660d8f53f1856bbe8cf6771d3351eaa182 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 26 Sep 2016 20:20:17 -0400 Subject: staging: iio: isl29018: use IIO_DEVICE_ATTR_{RO, RW} macros Use the IIO_DEVICE_ATTR_RO and IIO_DEVICE_ATTR_RW macros to create the device attributes. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 30dc1da95459..19f282c13651 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -268,8 +268,9 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, return 0; } -static ssize_t isl29018_show_scale_available(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t in_illuminance_scale_available_show + (struct device *dev, struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); @@ -286,8 +287,9 @@ static ssize_t isl29018_show_scale_available(struct device *dev, return len; } -static ssize_t isl29018_show_int_time_available(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t in_illuminance_integration_time_available_show + (struct device *dev, struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); @@ -303,9 +305,9 @@ static ssize_t isl29018_show_int_time_available(struct device *dev, return len; } -static ssize_t isl29018_show_prox_infrared_suppression(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t proximity_on_chip_ambient_infrared_suppression_show + (struct device *dev, struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); @@ -317,9 +319,9 @@ static ssize_t isl29018_show_prox_infrared_suppression(struct device *dev, return sprintf(buf, "%d\n", chip->prox_scheme); } -static ssize_t isl29018_store_prox_infrared_suppression(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t proximity_on_chip_ambient_infrared_suppression_store + (struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); @@ -471,14 +473,9 @@ static const struct iio_chan_spec isl29023_channels[] = { ISL29018_IR_CHANNEL, }; -static IIO_DEVICE_ATTR(in_illuminance_integration_time_available, S_IRUGO, - isl29018_show_int_time_available, NULL, 0); -static IIO_DEVICE_ATTR(in_illuminance_scale_available, S_IRUGO, - isl29018_show_scale_available, NULL, 0); -static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, - S_IRUGO | S_IWUSR, - isl29018_show_prox_infrared_suppression, - isl29018_store_prox_infrared_suppression, 0); +static IIO_DEVICE_ATTR_RO(in_illuminance_integration_time_available, 0); +static IIO_DEVICE_ATTR_RO(in_illuminance_scale_available, 0); +static IIO_DEVICE_ATTR_RW(proximity_on_chip_ambient_infrared_suppression, 0); #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) -- cgit v1.2.3 From 5faf98cb319bc7ce7cef080be1bbebba44233332 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 26 Sep 2016 20:20:18 -0400 Subject: staging: iio: isl29018: fixed race condition in in_illuminance_scale_available_show() in_illuminance_scale_available_show() references the isl29018_chip->int_time variable in three places inside a for loop. The value of the int_time variable can be updated by the isl29018_set_integration_time() function, which is called by the isl29018_write_raw() function. isl29018_write_raw() locks a mutex specific to this driver when the integration time variable is updated. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 19f282c13651..990c6e52bafe 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -277,10 +277,12 @@ static ssize_t in_illuminance_scale_available_show unsigned int i; int len = 0; + mutex_lock(&chip->lock); for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) len += sprintf(buf + len, "%d.%06d ", isl29018_scales[chip->int_time][i].scale, isl29018_scales[chip->int_time][i].uscale); + mutex_unlock(&chip->lock); buf[len - 1] = '\n'; -- cgit v1.2.3 From 5611cd6fc61dbccdba61656bea9c5c1634b51e46 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 26 Sep 2016 20:20:19 -0400 Subject: staging: iio: isl29018: change isl29018_read_raw() to only have one exit point When the chip is in a suspended state, isl29018_read_raw() will return -EBUSY. Change the function so that it only has a single exit point. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 990c6e52bafe..3a4d79d7e23c 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -390,8 +390,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, mutex_lock(&chip->lock); if (chip->suspended) { - mutex_unlock(&chip->lock); - return -EBUSY; + ret = -EBUSY; + goto read_done; } switch (mask) { case IIO_CHAN_INFO_RAW: @@ -438,6 +438,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, default: break; } + +read_done: mutex_unlock(&chip->lock); return ret; } -- cgit v1.2.3 From 00053566385e3e7a2f81f0fd2fa09bccce1589f2 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 26 Sep 2016 20:20:20 -0400 Subject: staging: iio: isl29018: check if the chip is in a suspended state Add a check to isl29018_write_raw() to ensure that the chip is not in a suspended state. This makes the code consistent with what is present in isl29018_read_raw(). Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 3a4d79d7e23c..51226bd337c5 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -355,6 +355,10 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, int ret = -EINVAL; mutex_lock(&chip->lock); + if (chip->suspended) { + ret = -EBUSY; + goto write_done; + } switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { @@ -374,8 +378,9 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, default: break; } - mutex_unlock(&chip->lock); +write_done: + mutex_unlock(&chip->lock); return ret; } -- cgit v1.2.3 From 9ecca12edde435efc6d08f7a1e877ba9929a6c93 Mon Sep 17 00:00:00 2001 From: Marcin Malagowski Date: Mon, 26 Sep 2016 19:23:06 +0200 Subject: iio: pressure: Add driver for Honeywell ABP family This patch adds minimal driver for the Honeywell Amplified Basic Pressure sensors series. Sensors are pretty simple but are available in many variants: - psi/mbar/kPa output, - analog/i2c/spi, - gage/differential measurement, - different measure ranges etc. Refer to datasheets for more details: http://sensing.honeywell.com/honeywell-sensing-basic-board-mount-pressure-sensors-abp-series-datasheet-323005128-c-en.pdf http://sensing.honeywell.com/index.php%3Fci_id%3D45841 Driver internals: - i2c only. measure request is done by the SMBUS QUICK cmd, so if the i2c bus doesn't support it, it is required to send a dummy byte to trigger measurement, - since iio sysfs expects kilopascals, mbar-variants are treated as their respective kPa-s, hence i2c id-table has doubled entries in one line: { "abp060mg", ABP006KG }, { "abp006kg", ABP006KG }, - psi-variants have prescaled values in config, - no temperature reads yet. Work remained: - optional temperature channel, - SPI support, - DT binding. Changes since v1: - mutex is now locked in read_raw(), - corrected error codes, - fixed coding style issues, - renamed few defines and functions abp -> abp060mg (some structs left as they were to keep the sensible meaning). Signed-off-by: Marcin Malagowski Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 10 ++ drivers/iio/pressure/Makefile | 1 + drivers/iio/pressure/abp060mg.c | 276 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 drivers/iio/pressure/abp060mg.c (limited to 'drivers') diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index cc090d803465..2347bb74521a 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -5,6 +5,16 @@ menu "Pressure sensors" +config ABP060MG + tristate "Honeywell ABP pressure sensor driver" + depends on I2C + help + Say yes here to build support for the Honeywell ABP pressure + sensors. + + To compile this driver as a module, choose M here: the module + will be called abp060mg. + config BMP280 tristate "Bosch Sensortec BMP180/BMP280 pressure sensor I2C driver" depends on (I2C || SPI_MASTER) diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index fff77185a5cc..de3dbc81dc5a 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_ABP060MG) += abp060mg.o obj-$(CONFIG_BMP280) += bmp280.o bmp280-objs := bmp280-core.o bmp280-regmap.o obj-$(CONFIG_BMP280_I2C) += bmp280-i2c.o diff --git a/drivers/iio/pressure/abp060mg.c b/drivers/iio/pressure/abp060mg.c new file mode 100644 index 000000000000..43bdd0b9155f --- /dev/null +++ b/drivers/iio/pressure/abp060mg.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2016 - Marcin Malagowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define ABP060MG_ERROR_MASK 0xC000 +#define ABP060MG_RESP_TIME_MS 40 +#define ABP060MG_MIN_COUNTS 1638 /* = 0x0666 (10% of u14) */ +#define ABP060MG_MAX_COUNTS 14745 /* = 0x3999 (90% of u14) */ +#define ABP060MG_NUM_COUNTS (ABP060MG_MAX_COUNTS - ABP060MG_MIN_COUNTS) + +enum abp_variant { + /* gage [kPa] */ + ABP006KG, ABP010KG, ABP016KG, ABP025KG, ABP040KG, ABP060KG, ABP100KG, + ABP160KG, ABP250KG, ABP400KG, ABP600KG, ABP001GG, + /* differential [kPa] */ + ABP006KD, ABP010KD, ABP016KD, ABP025KD, ABP040KD, ABP060KD, ABP100KD, + ABP160KD, ABP250KD, ABP400KD, + /* gage [psi] */ + ABP001PG, ABP005PG, ABP015PG, ABP030PG, ABP060PG, ABP100PG, ABP150PG, + /* differential [psi] */ + ABP001PD, ABP005PD, ABP015PD, ABP030PD, ABP060PD, +}; + +struct abp_config { + int min; + int max; +}; + +static struct abp_config abp_config[] = { + /* mbar & kPa variants */ + [ABP006KG] = { .min = 0, .max = 6000 }, + [ABP010KG] = { .min = 0, .max = 10000 }, + [ABP016KG] = { .min = 0, .max = 16000 }, + [ABP025KG] = { .min = 0, .max = 25000 }, + [ABP040KG] = { .min = 0, .max = 40000 }, + [ABP060KG] = { .min = 0, .max = 60000 }, + [ABP100KG] = { .min = 0, .max = 100000 }, + [ABP160KG] = { .min = 0, .max = 160000 }, + [ABP250KG] = { .min = 0, .max = 250000 }, + [ABP400KG] = { .min = 0, .max = 400000 }, + [ABP600KG] = { .min = 0, .max = 600000 }, + [ABP001GG] = { .min = 0, .max = 1000000 }, + [ABP006KD] = { .min = -6000, .max = 6000 }, + [ABP010KD] = { .min = -10000, .max = 10000 }, + [ABP016KD] = { .min = -16000, .max = 16000 }, + [ABP025KD] = { .min = -25000, .max = 25000 }, + [ABP040KD] = { .min = -40000, .max = 40000 }, + [ABP060KD] = { .min = -60000, .max = 60000 }, + [ABP100KD] = { .min = -100000, .max = 100000 }, + [ABP160KD] = { .min = -160000, .max = 160000 }, + [ABP250KD] = { .min = -250000, .max = 250000 }, + [ABP400KD] = { .min = -400000, .max = 400000 }, + /* psi variants (1 psi ~ 6895 Pa) */ + [ABP001PG] = { .min = 0, .max = 6985 }, + [ABP005PG] = { .min = 0, .max = 34474 }, + [ABP015PG] = { .min = 0, .max = 103421 }, + [ABP030PG] = { .min = 0, .max = 206843 }, + [ABP060PG] = { .min = 0, .max = 413686 }, + [ABP100PG] = { .min = 0, .max = 689476 }, + [ABP150PG] = { .min = 0, .max = 1034214 }, + [ABP001PD] = { .min = -6895, .max = 6895 }, + [ABP005PD] = { .min = -34474, .max = 34474 }, + [ABP015PD] = { .min = -103421, .max = 103421 }, + [ABP030PD] = { .min = -206843, .max = 206843 }, + [ABP060PD] = { .min = -413686, .max = 413686 }, +}; + +struct abp_state { + struct i2c_client *client; + struct mutex lock; + + /* + * bus-dependent MEASURE_REQUEST length. + * If no SMBUS_QUICK support, need to send dummy byte + */ + int mreq_len; + + /* model-dependent values (calculated on probe) */ + int scale; + int offset; +}; + +static const struct iio_chan_spec abp060mg_channels[] = { + { + .type = IIO_PRESSURE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static int abp060mg_get_measurement(struct abp_state *state, int *val) +{ + struct i2c_client *client = state->client; + __be16 buf[2]; + u16 pressure; + int ret; + + buf[0] = 0; + ret = i2c_master_send(client, (u8 *)&buf, state->mreq_len); + if (ret < 0) + return ret; + + msleep_interruptible(ABP060MG_RESP_TIME_MS); + + ret = i2c_master_recv(client, (u8 *)&buf, sizeof(buf)); + if (ret < 0) + return ret; + + pressure = be16_to_cpu(buf[0]); + if (pressure & ABP060MG_ERROR_MASK) + return -EIO; + + if (pressure < ABP060MG_MIN_COUNTS || pressure > ABP060MG_MAX_COUNTS) + return -EIO; + + *val = pressure; + + return IIO_VAL_INT; +} + +static int abp060mg_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct abp_state *state = iio_priv(indio_dev); + int ret; + + mutex_lock(&state->lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = abp060mg_get_measurement(state, val); + break; + case IIO_CHAN_INFO_OFFSET: + *val = state->offset; + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SCALE: + *val = state->scale; + *val2 = ABP060MG_NUM_COUNTS * 1000; /* to kPa */ + ret = IIO_VAL_FRACTIONAL; + break; + default: + ret = -EINVAL; + break; + } + + mutex_unlock(&state->lock); + return ret; +} + +static const struct iio_info abp060mg_info = { + .driver_module = THIS_MODULE, + .read_raw = abp060mg_read_raw, +}; + +static void abp060mg_init_device(struct iio_dev *indio_dev, unsigned long id) +{ + struct abp_state *state = iio_priv(indio_dev); + struct abp_config *cfg = &abp_config[id]; + + state->scale = cfg->max - cfg->min; + state->offset = -ABP060MG_MIN_COUNTS; + + if (cfg->min < 0) /* differential */ + state->offset -= ABP060MG_NUM_COUNTS >> 1; +} + +static int abp060mg_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct abp_state *state; + unsigned long cfg_id = id->driver_data; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state)); + if (!indio_dev) + return -ENOMEM; + + state = iio_priv(indio_dev); + i2c_set_clientdata(client, state); + state->client = client; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK)) + state->mreq_len = 1; + + abp060mg_init_device(indio_dev, cfg_id); + + indio_dev->dev.parent = &client->dev; + indio_dev->name = dev_name(&client->dev); + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &abp060mg_info; + + indio_dev->channels = abp060mg_channels; + indio_dev->num_channels = ARRAY_SIZE(abp060mg_channels); + + mutex_init(&state->lock); + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id abp060mg_id_table[] = { + /* mbar & kPa variants (abp060m [60 mbar] == abp006k [6 kPa]) */ + /* gage: */ + { "abp060mg", ABP006KG }, { "abp006kg", ABP006KG }, + { "abp100mg", ABP010KG }, { "abp010kg", ABP010KG }, + { "abp160mg", ABP016KG }, { "abp016kg", ABP016KG }, + { "abp250mg", ABP025KG }, { "abp025kg", ABP025KG }, + { "abp400mg", ABP040KG }, { "abp040kg", ABP040KG }, + { "abp600mg", ABP060KG }, { "abp060kg", ABP060KG }, + { "abp001bg", ABP100KG }, { "abp100kg", ABP100KG }, + { "abp1_6bg", ABP160KG }, { "abp160kg", ABP160KG }, + { "abp2_5bg", ABP250KG }, { "abp250kg", ABP250KG }, + { "abp004bg", ABP400KG }, { "abp400kg", ABP400KG }, + { "abp006bg", ABP600KG }, { "abp600kg", ABP600KG }, + { "abp010bg", ABP001GG }, { "abp001gg", ABP001GG }, + /* differential: */ + { "abp060md", ABP006KD }, { "abp006kd", ABP006KD }, + { "abp100md", ABP010KD }, { "abp010kd", ABP010KD }, + { "abp160md", ABP016KD }, { "abp016kd", ABP016KD }, + { "abp250md", ABP025KD }, { "abp025kd", ABP025KD }, + { "abp400md", ABP040KD }, { "abp040kd", ABP040KD }, + { "abp600md", ABP060KD }, { "abp060kd", ABP060KD }, + { "abp001bd", ABP100KD }, { "abp100kd", ABP100KD }, + { "abp1_6bd", ABP160KD }, { "abp160kd", ABP160KD }, + { "abp2_5bd", ABP250KD }, { "abp250kd", ABP250KD }, + { "abp004bd", ABP400KD }, { "abp400kd", ABP400KD }, + /* psi variants */ + /* gage: */ + { "abp001pg", ABP001PG }, + { "abp005pg", ABP005PG }, + { "abp015pg", ABP015PG }, + { "abp030pg", ABP030PG }, + { "abp060pg", ABP060PG }, + { "abp100pg", ABP100PG }, + { "abp150pg", ABP150PG }, + /* differential: */ + { "abp001pd", ABP001PD }, + { "abp005pd", ABP005PD }, + { "abp015pd", ABP015PD }, + { "abp030pd", ABP030PD }, + { "abp060pd", ABP060PD }, + { /* empty */ }, +}; +MODULE_DEVICE_TABLE(i2c, abp060mg_id_table); + +static struct i2c_driver abp060mg_driver = { + .driver = { + .name = "abp060mg", + }, + .probe = abp060mg_probe, + .id_table = abp060mg_id_table, +}; +module_i2c_driver(abp060mg_driver); + +MODULE_AUTHOR("Marcin Malagowski "); +MODULE_DESCRIPTION("Honeywell ABP pressure sensor driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 1a8f324aa1f2237caef1c6633734785bbdcffeed Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 28 Sep 2016 13:59:49 -0400 Subject: iio: Implement counter channel type and info constants Quadrature encoders, such as rotary encoders and linear encoders, are devices which are capable of encoding the relative position and direction of motion of a shaft. This patch introduces several IIO constants for supporting quadrature encoder counter devices. IIO_COUNT: Current count (main data provided by the counter device) IIO_INDEX: Counter device index value Signed-off-by: William Breathitt Gray Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 18 ++++++++++++++++++ drivers/iio/industrialio-core.c | 2 ++ include/uapi/linux/iio/types.h | 2 ++ 3 files changed, 22 insertions(+) (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index fee35c00cc4e..b8f220f978dd 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -329,6 +329,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_pressure_scale What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale What: /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_scale +What: /sys/bus/iio/devices/iio:deviceX/in_countY_scale KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -1579,3 +1580,20 @@ Contact: linux-iio@vger.kernel.org Description: Raw (unscaled no offset etc.) electric conductivity reading that can be processed to siemens per meter. + +What: /sys/bus/iio/devices/iio:deviceX/in_countY_raw +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Raw counter device counts from channel Y. For quadrature + counters, multiplication by an available [Y]_scale results in + the counts of a single quadrature signal phase from channel Y. + +What: /sys/bus/iio/devices/iio:deviceX/in_indexY_raw +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Raw counter device index value from channel Y. This attribute + provides an absolute positional reference (e.g. a pulse once per + revolution) which may be used to home positional systems as + required. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index fc340ed3dca1..649725bc15c1 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -81,6 +81,8 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_PH] = "ph", [IIO_UVINDEX] = "uvindex", [IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity", + [IIO_COUNT] = "count", + [IIO_INDEX] = "index", }; static const char * const iio_modifier_names[] = { diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 22e5e589a274..e54d14a7f876 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -40,6 +40,8 @@ enum iio_chan_type { IIO_PH, IIO_UVINDEX, IIO_ELECTRICALCONDUCTIVITY, + IIO_COUNT, + IIO_INDEX, }; enum iio_modifier { -- cgit v1.2.3 From 28e5d3bb0325e71ef9b53a9cb4242cdfb55fd8c5 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 28 Sep 2016 14:00:01 -0400 Subject: iio: 104-quad-8: Add IIO support for the ACCES 104-QUAD-8 The ACCES 104-QUAD-8 is a general purpose quadrature encoder counter/interface board. The 104-QUAD-8 is capable of monitoring the outputs of eight encoders via four on-board LSI/CSI LS7266R1 24-bit dual-axis quadrature counter chips. Core functions handled by the LS7266R1, such as direction and total count, are available. Performing a write to a counter's IIO_CHAN_INFO_RAW sets the counter and also clears the counter's respective error flag. Although the counters have a 25-bit range, only the lower 24 bits may be set, either directly or via a counter's preset attribute. Interrupts are not supported by this driver. This driver adds IIO support for the ACCES 104-QUAD-8 and ACCES 104-QUAD-4. The base port addresses for the devices may be configured via the base array module parameter. Signed-off-by: William Breathitt Gray Signed-off-by: Jonathan Cameron --- .../ABI/testing/sysfs-bus-iio-counter-104-quad-8 | 125 +++++ MAINTAINERS | 6 + drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/iio/counter/104-quad-8.c | 593 +++++++++++++++++++++ drivers/iio/counter/Kconfig | 24 + drivers/iio/counter/Makefile | 7 + 7 files changed, 757 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 create mode 100644 drivers/iio/counter/104-quad-8.c create mode 100644 drivers/iio/counter/Kconfig create mode 100644 drivers/iio/counter/Makefile (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 new file mode 100644 index 000000000000..ba676520b953 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 @@ -0,0 +1,125 @@ +What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available +What: /sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available +What: /sys/bus/iio/devices/iio:deviceX/in_count_noise_error_available +What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available +What: /sys/bus/iio/devices/iio:deviceX/in_index_index_polarity_available +What: /sys/bus/iio/devices/iio:deviceX/in_index_synchronous_mode_available +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Discrete set of available values for the respective counter + configuration are listed in this file. + +What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Read-only attribute that indicates whether the counter for + channel Y is counting up or down. + +What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_mode +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Count mode for channel Y. Four count modes are available: + normal, range limit, non-recycle, and modulo-n. The preset value + for channel Y is used by the count mode where required. + + Normal: + Counting is continuous in either direction. + + Range Limit: + An upper or lower limit is set, mimicking limit switches + in the mechanical counterpart. The upper limit is set to + the preset value, while the lower limit is set to 0. The + counter freezes at count = preset when counting up, and + at count = 0 when counting down. At either of these + limits, the counting is resumed only when the count + direction is reversed. + + Non-recycle: + Counter is disabled whenever a 24-bit count overflow or + underflow takes place. The counter is re-enabled when a + new count value is loaded to the counter via a preset + operation or write to raw. + + Modulo-N: + A count boundary is set between 0 and the preset value. + The counter is reset to 0 at count = preset when + counting up, while the counter is set to the preset + value at count = 0 when counting down; the counter does + not freeze at the bundary points, but counts + continuously throughout. + +What: /sys/bus/iio/devices/iio:deviceX/in_countY_noise_error +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Read-only attribute that indicates whether excessive noise is + present at the channel Y count inputs in quadrature clock mode; + irrelevant in non-quadrature clock mode. + +What: /sys/bus/iio/devices/iio:deviceX/in_countY_preset +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + If the counter device supports preset registers, the preset + count for channel Y is provided by this attribute. + +What: /sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Configure channel Y counter for non-quadrature or quadrature + clock mode. Selecting non-quadrature clock mode will disable + synchronous load mode. In quadrature clock mode, the channel Y + scale attribute selects the encoder phase division (scale of 1 + selects full-cycle, scale of 0.5 selects half-cycle, scale of + 0.25 selects quarter-cycle) processed by the channel Y counter. + + Non-quadrature: + The filter and decoder circuit are bypassed. Encoder A + input serves as the count input and B as the UP/DOWN + direction control input, with B = 1 selecting UP Count + mode and B = 0 selecting Down Count mode. + + Quadrature: + Encoder A and B inputs are digitally filtered and + decoded for UP/DN clock. + +What: /sys/bus/iio/devices/iio:deviceX/in_countY_set_to_preset_on_index +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Whether to set channel Y counter with channel Y preset value + when channel Y index input is active, or continuously count. + Valid attribute values are boolean. + +What: /sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Active level of channel Y index input; irrelevant in + non-synchronous load mode. + +What: /sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode +KernelVersion: 4.9 +Contact: linux-iio@vger.kernel.org +Description: + Configure channel Y counter for non-synchronous or synchronous + load mode. Synchronous load mode cannot be selected in + non-quadrature clock mode. + + Non-synchronous: + A logic low level is the active level at this index + input. The index function (as enabled via + set_to_preset_on_index) is performed directly on the + active level of the index input. + + Synchronous: + Intended for interfacing with encoder Index output in + quadrature clock mode. The active level is configured + via index_polarity. The index function (as enabled via + set_to_preset_on_index) is performed synchronously with + the quadrature clock on the active level of the index + input. diff --git a/MAINTAINERS b/MAINTAINERS index e013c2be6d23..982dff301045 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -255,6 +255,12 @@ L: linux-gpio@vger.kernel.org S: Maintained F: drivers/gpio/gpio-104-idio-16.c +ACCES 104-QUAD-8 IIO DRIVER +M: William Breathitt Gray +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/iio/counter/104-quad-8.c + ACENIC DRIVER M: Jes Sorensen L: linux-acenic@sunsite.dk diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index a31a8cf2c330..a918270d6f54 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -73,6 +73,7 @@ source "drivers/iio/adc/Kconfig" source "drivers/iio/amplifiers/Kconfig" source "drivers/iio/chemical/Kconfig" source "drivers/iio/common/Kconfig" +source "drivers/iio/counter/Kconfig" source "drivers/iio/dac/Kconfig" source "drivers/iio/dummy/Kconfig" source "drivers/iio/frequency/Kconfig" diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 2b6e2762a886..33fa4026f92c 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -18,6 +18,7 @@ obj-y += amplifiers/ obj-y += buffer/ obj-y += chemical/ obj-y += common/ +obj-y += counter/ obj-y += dac/ obj-y += dummy/ obj-y += gyro/ diff --git a/drivers/iio/counter/104-quad-8.c b/drivers/iio/counter/104-quad-8.c new file mode 100644 index 000000000000..2d2ee353dde7 --- /dev/null +++ b/drivers/iio/counter/104-quad-8.c @@ -0,0 +1,593 @@ +/* + * IIO driver for the ACCES 104-QUAD-8 + * Copyright (C) 2016 William Breathitt Gray + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QUAD8_EXTENT 32 + +static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)]; +static unsigned int num_quad8; +module_param_array(base, uint, &num_quad8, 0); +MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); + +#define QUAD8_NUM_COUNTERS 8 + +/** + * struct quad8_iio - IIO device private data structure + * @preset: array of preset values + * @count_mode: array of count mode configurations + * @quadrature_mode: array of quadrature mode configurations + * @quadrature_scale: array of quadrature mode scale configurations + * @ab_enable: array of A and B inputs enable configurations + * @preset_enable: array of set_to_preset_on_index attribute configurations + * @synchronous_mode: array of index function synchronous mode configurations + * @index_polarity: array of index function polarity configurations + * @base: base port address of the IIO device + */ +struct quad8_iio { + unsigned int preset[QUAD8_NUM_COUNTERS]; + unsigned int count_mode[QUAD8_NUM_COUNTERS]; + unsigned int quadrature_mode[QUAD8_NUM_COUNTERS]; + unsigned int quadrature_scale[QUAD8_NUM_COUNTERS]; + unsigned int ab_enable[QUAD8_NUM_COUNTERS]; + unsigned int preset_enable[QUAD8_NUM_COUNTERS]; + unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; + unsigned int index_polarity[QUAD8_NUM_COUNTERS]; + unsigned int base; +}; + +static int quad8_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long mask) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + const int base_offset = priv->base + 2 * chan->channel; + unsigned int flags; + unsigned int borrow; + unsigned int carry; + int i; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (chan->type == IIO_INDEX) { + *val = !!(inb(priv->base + 0x16) & BIT(chan->channel)); + return IIO_VAL_INT; + } + + flags = inb(base_offset); + borrow = flags & BIT(0); + carry = !!(flags & BIT(1)); + + /* Borrow XOR Carry effectively doubles count range */ + *val = (borrow ^ carry) << 24; + + /* Reset Byte Pointer; transfer Counter to Output Latch */ + outb(0x11, base_offset + 1); + + for (i = 0; i < 3; i++) + *val |= (unsigned int)inb(base_offset) << (8 * i); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_ENABLE: + *val = priv->ab_enable[chan->channel]; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 1; + *val2 = priv->quadrature_scale[chan->channel]; + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + +static int quad8_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + const int base_offset = priv->base + 2 * chan->channel; + int i; + unsigned int ior_cfg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (chan->type == IIO_INDEX) + return -EINVAL; + + /* Only 24-bit values are supported */ + if ((unsigned int)val > 0xFFFFFF) + return -EINVAL; + + /* Reset Byte Pointer */ + outb(0x01, base_offset + 1); + + /* Counter can only be set via Preset Register */ + for (i = 0; i < 3; i++) + outb(val >> (8 * i), base_offset); + + /* Transfer Preset Register to Counter */ + outb(0x08, base_offset + 1); + + /* Reset Byte Pointer */ + outb(0x01, base_offset + 1); + + /* Set Preset Register back to original value */ + val = priv->preset[chan->channel]; + for (i = 0; i < 3; i++) + outb(val >> (8 * i), base_offset); + + /* Reset Borrow, Carry, Compare, and Sign flags */ + outb(0x02, base_offset + 1); + /* Reset Error flag */ + outb(0x06, base_offset + 1); + + return 0; + case IIO_CHAN_INFO_ENABLE: + /* only boolean values accepted */ + if (val < 0 || val > 1) + return -EINVAL; + + priv->ab_enable[chan->channel] = val; + + ior_cfg = val | priv->preset_enable[chan->channel] << 1; + + /* Load I/O control configuration */ + outb(0x40 | ior_cfg, base_offset); + + return 0; + case IIO_CHAN_INFO_SCALE: + /* Quadrature scaling only available in quadrature mode */ + if (!priv->quadrature_mode[chan->channel] && (val2 || val != 1)) + return -EINVAL; + + /* Only three gain states (1, 0.5, 0.25) */ + if (val == 1 && !val2) + priv->quadrature_scale[chan->channel] = 0; + else if (!val) + switch (val2) { + case 500000: + priv->quadrature_scale[chan->channel] = 1; + break; + case 250000: + priv->quadrature_scale[chan->channel] = 2; + break; + default: + return -EINVAL; + } + else + return -EINVAL; + + return 0; + } + + return -EINVAL; +} + +static const struct iio_info quad8_info = { + .driver_module = THIS_MODULE, + .read_raw = quad8_read_raw, + .write_raw = quad8_write_raw +}; + +static ssize_t quad8_read_preset(struct iio_dev *indio_dev, uintptr_t private, + const struct iio_chan_spec *chan, char *buf) +{ + const struct quad8_iio *const priv = iio_priv(indio_dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", priv->preset[chan->channel]); +} + +static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private, + const struct iio_chan_spec *chan, const char *buf, size_t len) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + const int base_offset = priv->base + 2 * chan->channel; + unsigned int preset; + int ret; + int i; + + ret = kstrtouint(buf, 0, &preset); + if (ret) + return ret; + + /* Only 24-bit values are supported */ + if (preset > 0xFFFFFF) + return -EINVAL; + + priv->preset[chan->channel] = preset; + + /* Reset Byte Pointer */ + outb(0x01, base_offset + 1); + + /* Set Preset Register */ + for (i = 0; i < 3; i++) + outb(preset >> (8 * i), base_offset); + + return len; +} + +static ssize_t quad8_read_set_to_preset_on_index(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) +{ + const struct quad8_iio *const priv = iio_priv(indio_dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + priv->preset_enable[chan->channel]); +} + +static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + const int base_offset = priv->base + 2 * chan->channel; + bool preset_enable; + int ret; + unsigned int ior_cfg; + + ret = kstrtobool(buf, &preset_enable); + if (ret) + return ret; + + priv->preset_enable[chan->channel] = preset_enable; + + ior_cfg = priv->ab_enable[chan->channel] | + (unsigned int)preset_enable << 1; + + /* Load I/O control configuration to Input / Output Control Register */ + outb(0x40 | ior_cfg, base_offset); + + return len; +} + +static const char *const quad8_noise_error_states[] = { + "No excessive noise is present at the count inputs", + "Excessive noise is present at the count inputs" +}; + +static int quad8_get_noise_error(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + const int base_offset = priv->base + 2 * chan->channel + 1; + + return !!(inb(base_offset) & BIT(4)); +} + +static const struct iio_enum quad8_noise_error_enum = { + .items = quad8_noise_error_states, + .num_items = ARRAY_SIZE(quad8_noise_error_states), + .get = quad8_get_noise_error +}; + +static const char *const quad8_count_direction_states[] = { + "down", + "up" +}; + +static int quad8_get_count_direction(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + const int base_offset = priv->base + 2 * chan->channel + 1; + + return !!(inb(base_offset) & BIT(5)); +} + +static const struct iio_enum quad8_count_direction_enum = { + .items = quad8_count_direction_states, + .num_items = ARRAY_SIZE(quad8_count_direction_states), + .get = quad8_get_count_direction +}; + +static const char *const quad8_count_modes[] = { + "normal", + "range limit", + "non-recycle", + "modulo-n" +}; + +static int quad8_set_count_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int count_mode) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + unsigned int mode_cfg = count_mode << 1; + const int base_offset = priv->base + 2 * chan->channel + 1; + + priv->count_mode[chan->channel] = count_mode; + + /* Add quadrature mode configuration */ + if (priv->quadrature_mode[chan->channel]) + mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3; + + /* Load mode configuration to Counter Mode Register */ + outb(0x20 | mode_cfg, base_offset); + + return 0; +} + +static int quad8_get_count_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + const struct quad8_iio *const priv = iio_priv(indio_dev); + + return priv->count_mode[chan->channel]; +} + +static const struct iio_enum quad8_count_mode_enum = { + .items = quad8_count_modes, + .num_items = ARRAY_SIZE(quad8_count_modes), + .set = quad8_set_count_mode, + .get = quad8_get_count_mode +}; + +static const char *const quad8_synchronous_modes[] = { + "non-synchronous", + "synchronous" +}; + +static int quad8_set_synchronous_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int synchronous_mode) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + const unsigned int idr_cfg = synchronous_mode | + priv->index_polarity[chan->channel] << 1; + const int base_offset = priv->base + 2 * chan->channel + 1; + + /* Index function must be non-synchronous in non-quadrature mode */ + if (synchronous_mode && !priv->quadrature_mode[chan->channel]) + return -EINVAL; + + priv->synchronous_mode[chan->channel] = synchronous_mode; + + /* Load Index Control configuration to Index Control Register */ + outb(0x40 | idr_cfg, base_offset); + + return 0; +} + +static int quad8_get_synchronous_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + const struct quad8_iio *const priv = iio_priv(indio_dev); + + return priv->synchronous_mode[chan->channel]; +} + +static const struct iio_enum quad8_synchronous_mode_enum = { + .items = quad8_synchronous_modes, + .num_items = ARRAY_SIZE(quad8_synchronous_modes), + .set = quad8_set_synchronous_mode, + .get = quad8_get_synchronous_mode +}; + +static const char *const quad8_quadrature_modes[] = { + "non-quadrature", + "quadrature" +}; + +static int quad8_set_quadrature_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int quadrature_mode) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + unsigned int mode_cfg = priv->count_mode[chan->channel] << 1; + const int base_offset = priv->base + 2 * chan->channel + 1; + + if (quadrature_mode) + mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3; + else { + /* Quadrature scaling only available in quadrature mode */ + priv->quadrature_scale[chan->channel] = 0; + + /* Synchronous function not supported in non-quadrature mode */ + if (priv->synchronous_mode[chan->channel]) + quad8_set_synchronous_mode(indio_dev, chan, 0); + } + + priv->quadrature_mode[chan->channel] = quadrature_mode; + + /* Load mode configuration to Counter Mode Register */ + outb(0x20 | mode_cfg, base_offset); + + return 0; +} + +static int quad8_get_quadrature_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + const struct quad8_iio *const priv = iio_priv(indio_dev); + + return priv->quadrature_mode[chan->channel]; +} + +static const struct iio_enum quad8_quadrature_mode_enum = { + .items = quad8_quadrature_modes, + .num_items = ARRAY_SIZE(quad8_quadrature_modes), + .set = quad8_set_quadrature_mode, + .get = quad8_get_quadrature_mode +}; + +static const char *const quad8_index_polarity_modes[] = { + "negative", + "positive" +}; + +static int quad8_set_index_polarity(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int index_polarity) +{ + struct quad8_iio *const priv = iio_priv(indio_dev); + const unsigned int idr_cfg = priv->synchronous_mode[chan->channel] | + index_polarity << 1; + const int base_offset = priv->base + 2 * chan->channel + 1; + + priv->index_polarity[chan->channel] = index_polarity; + + /* Load Index Control configuration to Index Control Register */ + outb(0x40 | idr_cfg, base_offset); + + return 0; +} + +static int quad8_get_index_polarity(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + const struct quad8_iio *const priv = iio_priv(indio_dev); + + return priv->index_polarity[chan->channel]; +} + +static const struct iio_enum quad8_index_polarity_enum = { + .items = quad8_index_polarity_modes, + .num_items = ARRAY_SIZE(quad8_index_polarity_modes), + .set = quad8_set_index_polarity, + .get = quad8_get_index_polarity +}; + +static const struct iio_chan_spec_ext_info quad8_count_ext_info[] = { + { + .name = "preset", + .shared = IIO_SEPARATE, + .read = quad8_read_preset, + .write = quad8_write_preset + }, + { + .name = "set_to_preset_on_index", + .shared = IIO_SEPARATE, + .read = quad8_read_set_to_preset_on_index, + .write = quad8_write_set_to_preset_on_index + }, + IIO_ENUM("noise_error", IIO_SEPARATE, &quad8_noise_error_enum), + IIO_ENUM_AVAILABLE("noise_error", &quad8_noise_error_enum), + IIO_ENUM("count_direction", IIO_SEPARATE, &quad8_count_direction_enum), + IIO_ENUM_AVAILABLE("count_direction", &quad8_count_direction_enum), + IIO_ENUM("count_mode", IIO_SEPARATE, &quad8_count_mode_enum), + IIO_ENUM_AVAILABLE("count_mode", &quad8_count_mode_enum), + IIO_ENUM("quadrature_mode", IIO_SEPARATE, &quad8_quadrature_mode_enum), + IIO_ENUM_AVAILABLE("quadrature_mode", &quad8_quadrature_mode_enum), + {} +}; + +static const struct iio_chan_spec_ext_info quad8_index_ext_info[] = { + IIO_ENUM("synchronous_mode", IIO_SEPARATE, + &quad8_synchronous_mode_enum), + IIO_ENUM_AVAILABLE("synchronous_mode", &quad8_synchronous_mode_enum), + IIO_ENUM("index_polarity", IIO_SEPARATE, &quad8_index_polarity_enum), + IIO_ENUM_AVAILABLE("index_polarity", &quad8_index_polarity_enum), + {} +}; + +#define QUAD8_COUNT_CHAN(_chan) { \ + .type = IIO_COUNT, \ + .channel = (_chan), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_ENABLE) | BIT(IIO_CHAN_INFO_SCALE), \ + .ext_info = quad8_count_ext_info, \ + .indexed = 1 \ +} + +#define QUAD8_INDEX_CHAN(_chan) { \ + .type = IIO_INDEX, \ + .channel = (_chan), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .ext_info = quad8_index_ext_info, \ + .indexed = 1 \ +} + +static const struct iio_chan_spec quad8_channels[] = { + QUAD8_COUNT_CHAN(0), QUAD8_INDEX_CHAN(0), + QUAD8_COUNT_CHAN(1), QUAD8_INDEX_CHAN(1), + QUAD8_COUNT_CHAN(2), QUAD8_INDEX_CHAN(2), + QUAD8_COUNT_CHAN(3), QUAD8_INDEX_CHAN(3), + QUAD8_COUNT_CHAN(4), QUAD8_INDEX_CHAN(4), + QUAD8_COUNT_CHAN(5), QUAD8_INDEX_CHAN(5), + QUAD8_COUNT_CHAN(6), QUAD8_INDEX_CHAN(6), + QUAD8_COUNT_CHAN(7), QUAD8_INDEX_CHAN(7) +}; + +static int quad8_probe(struct device *dev, unsigned int id) +{ + struct iio_dev *indio_dev; + struct quad8_iio *priv; + int i, j; + unsigned int base_offset; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + if (!devm_request_region(dev, base[id], QUAD8_EXTENT, + dev_name(dev))) { + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", + base[id], base[id] + QUAD8_EXTENT); + return -EBUSY; + } + + indio_dev->info = &quad8_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->num_channels = ARRAY_SIZE(quad8_channels); + indio_dev->channels = quad8_channels; + indio_dev->name = dev_name(dev); + + priv = iio_priv(indio_dev); + priv->base = base[id]; + + /* Reset all counters and disable interrupt function */ + outb(0x01, base[id] + 0x11); + /* Set initial configuration for all counters */ + for (i = 0; i < QUAD8_NUM_COUNTERS; i++) { + base_offset = base[id] + 2 * i; + /* Reset Byte Pointer */ + outb(0x01, base_offset + 1); + /* Reset Preset Register */ + for (j = 0; j < 3; j++) + outb(0x00, base_offset); + /* Reset Borrow, Carry, Compare, and Sign flags */ + outb(0x04, base_offset + 1); + /* Reset Error flag */ + outb(0x06, base_offset + 1); + /* Binary encoding; Normal count; non-quadrature mode */ + outb(0x20, base_offset + 1); + /* Disable A and B inputs; preset on index; FLG1 as Carry */ + outb(0x40, base_offset + 1); + /* Disable index function; negative index polarity */ + outb(0x60, base_offset + 1); + } + /* Enable all counters */ + outb(0x00, base[id] + 0x11); + + return devm_iio_device_register(dev, indio_dev); +} + +static struct isa_driver quad8_driver = { + .probe = quad8_probe, + .driver = { + .name = "104-quad-8" + } +}; + +module_isa_driver(quad8_driver, num_quad8); + +MODULE_AUTHOR("William Breathitt Gray "); +MODULE_DESCRIPTION("ACCES 104-QUAD-8 IIO driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/counter/Kconfig b/drivers/iio/counter/Kconfig new file mode 100644 index 000000000000..44627f6e4861 --- /dev/null +++ b/drivers/iio/counter/Kconfig @@ -0,0 +1,24 @@ +# +# Counter devices +# +# When adding new entries keep the list in alphabetical order + +menu "Counters" + +config 104_QUAD_8 + tristate "ACCES 104-QUAD-8 driver" + depends on X86 && ISA_BUS_API + help + Say yes here to build support for the ACCES 104-QUAD-8 quadrature + encoder counter/interface device family (104-QUAD-8, 104-QUAD-4). + + Performing a write to a counter's IIO_CHAN_INFO_RAW sets the counter and + also clears the counter's respective error flag. Although the counters + have a 25-bit range, only the lower 24 bits may be set, either directly + or via a counter's preset attribute. Interrupts are not supported by + this driver. + + The base port addresses for the devices may be configured via the base + array module parameter. + +endmenu diff --git a/drivers/iio/counter/Makefile b/drivers/iio/counter/Makefile new file mode 100644 index 000000000000..007e88411648 --- /dev/null +++ b/drivers/iio/counter/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for IIO counter devices +# + +# When adding new entries keep the list in alphabetical order + +obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o -- cgit v1.2.3 From 6d01a4d3fbd1082b3de976531699953e30f39a15 Mon Sep 17 00:00:00 2001 From: Anchal Jain Date: Mon, 3 Oct 2016 18:38:28 +0530 Subject: staging: iio: cdc: ad7152: Add blank line after declarations to increase readability Add a blank line after the function to increase the readability of the code. Signed-off-by: Anchal Jain Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7152.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index 485d0a5af53c..928f70085bd1 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -134,6 +134,7 @@ static inline ssize_t ad7152_start_calib(struct device *dev, mutex_unlock(&indio_dev->mlock); return len; } + static ssize_t ad7152_start_offset_calib(struct device *dev, struct device_attribute *attr, const char *buf, @@ -142,6 +143,7 @@ static ssize_t ad7152_start_offset_calib(struct device *dev, return ad7152_start_calib(dev, attr, buf, len, AD7152_CONF_MODE_OFFS_CAL); } + static ssize_t ad7152_start_gain_calib(struct device *dev, struct device_attribute *attr, const char *buf, @@ -317,6 +319,7 @@ out: mutex_unlock(&indio_dev->mlock); return ret; } + static int ad7152_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, @@ -470,6 +473,7 @@ static const struct iio_chan_spec ad7152_channels[] = { BIT(IIO_CHAN_INFO_SCALE), } }; + /* * device probe and remove */ -- cgit v1.2.3 From dda960335e020835f7f1c12760e7f0b525b451e2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 3 Oct 2016 13:45:14 +0100 Subject: drm/i915: Just clear the mmiodebug before a register access When we enable the per-register access mmiodebug, it is to detect which access is illegal. Reporting on earlier untraced access outside of the mmiodebug does not help debugging (as the suspicion is immediately put upon the current register which is not at fault)! References: https://bugs.freedesktop.org/show_bug.cgi?id=97985 Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Cc: stable@vger.kernel.org Link: http://patchwork.freedesktop.org/patch/msgid/20161003124516.12388-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_uncore.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index a9b6c936aadd..ee2306a79747 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -796,10 +796,9 @@ __unclaimed_reg_debug(struct drm_i915_private *dev_priv, const bool read, const bool before) { - if (WARN(check_for_unclaimed_mmio(dev_priv), - "Unclaimed register detected %s %s register 0x%x\n", - before ? "before" : "after", - read ? "reading" : "writing to", + if (WARN(check_for_unclaimed_mmio(dev_priv) && !before, + "Unclaimed %s register 0x%x\n", + read ? "read from" : "write to", i915_mmio_reg_offset(reg))) i915.mmio_debug--; /* Only report the first N failures */ } -- cgit v1.2.3 From 5f12b80a0b42da253691ca03828033014bb786eb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 3 Oct 2016 13:45:15 +0100 Subject: drm/i915: Unalias obj->phys_handle and obj->userptr We use obj->phys_handle to choose the pread/pwrite path, but as obj->phys_handle is a union with obj->userptr, we then mistakenly use the phys_handle path for userptr objects within pread/pwrite. Testcase: igt/gem_userptr_blits/forbidden-operations Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97519 Signed-off-by: Chris Wilson Cc: stable@vger.kernel.org Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161003124516.12388-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 23bc43d23d2c..dbcac9379ffd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2281,21 +2281,19 @@ struct drm_i915_gem_object { /** Record of address bit 17 of each page at last unbind. */ unsigned long *bit_17; - union { - /** for phy allocated objects */ - struct drm_dma_handle *phys_handle; - - struct i915_gem_userptr { - uintptr_t ptr; - unsigned read_only :1; - unsigned workers :4; + struct i915_gem_userptr { + uintptr_t ptr; + unsigned read_only :1; + unsigned workers :4; #define I915_GEM_USERPTR_MAX_WORKERS 15 - struct i915_mm_struct *mm; - struct i915_mmu_object *mmu_object; - struct work_struct *work; - } userptr; - }; + struct i915_mm_struct *mm; + struct i915_mmu_object *mmu_object; + struct work_struct *work; + } userptr; + + /** for phys allocated objects */ + struct drm_dma_handle *phys_handle; }; static inline struct drm_i915_gem_object * -- cgit v1.2.3 From 348b9b1192144e13b779f8f9be301d492bebaff2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 3 Oct 2016 13:45:16 +0100 Subject: drm/i915: Use correct index for backtracking HUNG semaphores When decoding the semaphores inside hangcheck, we need to use the hw-id and not the local array index. Fixes: de1add360522 ("drm/i915: Decouple execbuf uAPI ...") Testcase: igt/gem_exec_whisper/hang # gen6-7 Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Cc: Daniel Vetter Cc: stable@vger.kernel.org Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161003124516.12388-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_irq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f8c0beaadf30..bd6c8b0eeaef 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2846,7 +2846,7 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, if (engine == signaller) continue; - if (offset == signaller->semaphore.signal_ggtt[engine->id]) + if (offset == signaller->semaphore.signal_ggtt[engine->hw_id]) return signaller; } } else { @@ -2856,13 +2856,13 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, if(engine == signaller) continue; - if (sync_bits == signaller->semaphore.mbox.wait[engine->id]) + if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id]) return signaller; } } - DRM_DEBUG_DRIVER("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n", - engine->id, ipehr, offset); + DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n", + engine->name, ipehr, offset); return ERR_PTR(-ENODEV); } -- cgit v1.2.3 From e0e1bec8550114b0571f3867bb355f79b464b1d4 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 2 Oct 2016 00:45:12 +0530 Subject: Staging: iio: ad7280a: constify attribute_group structures Check for attribute_group structures that are only stored in the event_attrs filed of iio_info structure. As the event_attrs field of iio_info structures is constant, so these attribute_group structures can also be declared constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; struct iio_info x; @@ x.event_attrs=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: text data bss dec hex filename 6271 672 776 7719 1e27 drivers/staging/iio/adc/ad7280a.o File size after: text data bss dec hex filename 6335 608 776 7719 1e27 drivers/staging/iio/adc/ad7280a.o Signed-off-by: Bhumika Goyal Acked-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7280a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index b460dda7eb65..ee679ac0368f 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -777,7 +777,7 @@ static struct attribute *ad7280_event_attributes[] = { NULL, }; -static struct attribute_group ad7280_event_attrs_group = { +static const struct attribute_group ad7280_event_attrs_group = { .attrs = ad7280_event_attributes, }; -- cgit v1.2.3 From 0fa90023f23ced839cde3bcc0be4e06b3fc34895 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 2 Oct 2016 00:45:13 +0530 Subject: Staging: iio: ad7816: constify attribute_group structures Check for attribute_group structures that are only stored in the event_attrs filed of iio_info structure. As the event_attrs field of iio_info structures is constant, so these attribute_group structures can also be declared constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; struct iio_info x; @@ x.event_attrs=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: text data bss dec hex filename 3295 768 0 4063 fdf drivers/staging/iio/adc/ad7816.o File size after: text data bss dec hex filename 3359 736 0 4095 fff drivers/staging/iio/adc/ad7816.o Signed-off-by: Bhumika Goyal Acked-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7816.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 5e8115b01011..72551f827382 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -327,7 +327,7 @@ static struct attribute *ad7816_event_attributes[] = { NULL, }; -static struct attribute_group ad7816_event_attribute_group = { +static const struct attribute_group ad7816_event_attribute_group = { .attrs = ad7816_event_attributes, .name = "events", }; -- cgit v1.2.3 From f0c816161c6b66aced601b7f245e10b65d7efe67 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 2 Oct 2016 00:45:14 +0530 Subject: Staging: iio: addac: constify attribute_group structures Check for attribute_group structures that are only stored in the event_attrs filed of iio_info structure. As the event_attrs field of iio_info structures is constant, so these attribute_group structures can also be declared constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; struct iio_info x; @@ x.event_attrs=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: text data bss dec hex filename 11013 6096 0 17109 42d5 drivers/staging/iio/addac/adt7316.o File size after: text data bss dec hex filename 11141 5968 0 17109 42d5 drivers/staging/iio/addac/adt7316.o Signed-off-by: Bhumika Goyal Acked-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 3faffe59c933..a7d90c8bac5e 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -2039,7 +2039,7 @@ static struct attribute *adt7316_event_attributes[] = { NULL, }; -static struct attribute_group adt7316_event_attribute_group = { +static const struct attribute_group adt7316_event_attribute_group = { .attrs = adt7316_event_attributes, .name = "events", }; @@ -2060,7 +2060,7 @@ static struct attribute *adt7516_event_attributes[] = { NULL, }; -static struct attribute_group adt7516_event_attribute_group = { +static const struct attribute_group adt7516_event_attribute_group = { .attrs = adt7516_event_attributes, .name = "events", }; -- cgit v1.2.3 From 23123cd8d3384e4f1df4aae0a6a6220347dd0765 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 2 Oct 2016 00:45:15 +0530 Subject: Staging: iio: ad7150: constify attribute_group structures Check for attribute_group structures that are only stored in the event_attrs filed of iio_info structure. As the event_attrs field of iio_info structures is constant, so these attribute_group structures can also be declared constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; struct iio_info x; @@ x.event_attrs=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: text data bss dec hex filename 3561 1152 8 4721 1271 drivers/staging/iio/cdc/ad7150.o File size after: text data bss dec hex filename 3625 1088 8 4721 1271 drivers/staging/iio/cdc/ad7150.o Signed-off-by: Bhumika Goyal Acked-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 5578a077fcfb..6998c3ddfb6a 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -562,7 +562,7 @@ static struct attribute *ad7150_event_attributes[] = { NULL, }; -static struct attribute_group ad7150_event_attribute_group = { +static const struct attribute_group ad7150_event_attribute_group = { .attrs = ad7150_event_attributes, .name = "events", }; -- cgit v1.2.3 From 7f709dcda46105f617329630d97f5c97cea5b068 Mon Sep 17 00:00:00 2001 From: Ico Doornekamp Date: Sat, 1 Oct 2016 19:30:14 +0200 Subject: iio: magnetometer: ak8974: small endianness fixes Fixes two cases of 'cast to restricted __le16' as reported by sparse. Signed-off-by: Ico Doornekamp Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8974.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 217353145676..ce09d771c1fb 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -287,7 +287,7 @@ static int ak8974_await_drdy(struct ak8974 *ak8974) return 0; } -static int ak8974_getresult(struct ak8974 *ak8974, s16 *result) +static int ak8974_getresult(struct ak8974 *ak8974, __le16 *result) { unsigned int src; int ret; @@ -395,7 +395,7 @@ static int ak8974_selftest(struct ak8974 *ak8974) static int ak8974_get_u16_val(struct ak8974 *ak8974, u8 reg, u16 *val) { int ret; - u16 bulk; + __le16 bulk; ret = regmap_bulk_read(ak8974->map, reg, &bulk, 2); if (ret) @@ -453,7 +453,7 @@ static int ak8974_read_raw(struct iio_dev *indio_dev, long mask) { struct ak8974 *ak8974 = iio_priv(indio_dev); - s16 hw_values[3]; + __le16 hw_values[3]; int ret = -EINVAL; pm_runtime_get_sync(&ak8974->i2c->dev); @@ -494,7 +494,7 @@ static void ak8974_fill_buffer(struct iio_dev *indio_dev) { struct ak8974 *ak8974 = iio_priv(indio_dev); int ret; - s16 hw_values[8]; /* Three axes + 64bit padding */ + __le16 hw_values[8]; /* Three axes + 64bit padding */ pm_runtime_get_sync(&ak8974->i2c->dev); mutex_lock(&ak8974->lock); -- cgit v1.2.3 From d9c409d67131e62f357b43cf03af4c0caab45721 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Oct 2016 10:53:48 +0300 Subject: drm/i915: keep CONFIG_DRM_FBDEV_EMULATION=n function stubs together Move the outcast intel_fbdev_output_poll_changed() stub for CONFIG_DRM_FBDEV_EMULATION=n next to its friends. Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1475567628-5529-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_display.c | 6 ------ drivers/gpu/drm/i915/intel_drv.h | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8a24c4492ce2..f0ca31d4a506 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15827,12 +15827,6 @@ intel_user_framebuffer_create(struct drm_device *dev, return fb; } -#ifndef CONFIG_DRM_FBDEV_EMULATION -static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) -{ -} -#endif - static const struct drm_mode_config_funcs intel_mode_funcs = { .fb_create = intel_user_framebuffer_create, .output_poll_changed = intel_fbdev_output_poll_changed, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3f6c1a8fbd09..74df0fc66861 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1488,6 +1488,10 @@ static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state, bo { } +static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) +{ +} + static inline void intel_fbdev_restore_mode(struct drm_device *dev) { } -- cgit v1.2.3 From ff64aa1e630087381511c4d25de0657824f40efa Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Oct 2016 12:54:12 +0300 Subject: drm/i915: workaround sparse warning on variable length arrays Fix sparse warning: drivers/gpu/drm/i915/intel_device_info.c:195:31: warning: Variable length array is used. In truth the array does have constant length, but sparse is too dumb to realize. This is a bit ugly, but silence the warning no matter what. Fixes: 91bedd34abf0 ("drm/i915/bdw: Check for slice, subslice and EU count for BDW") Reviewed-by: Joonas Lahtinen Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1475574853-4178-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_device_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 73b6858600ac..1b20e160bc1f 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -192,7 +192,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; const int s_max = 3, ss_max = 3, eu_max = 8; int s, ss; - u32 fuse2, eu_disable[s_max]; + u32 fuse2, eu_disable[3]; /* s_max */ fuse2 = I915_READ(GEN8_FUSE2); sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; -- cgit v1.2.3 From e9b825f4e98c53213072dd6f1dedaed82994a450 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:16 +0100 Subject: drm/i915: Remove redundant hsw_write* mmio functions They are completely identical to gen6_write* ones. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index ee2306a79747..18249e35bb02 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1054,21 +1054,6 @@ gen6_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool GEN6_WRITE_FOOTER; \ } -#define __hsw_write(x) \ -static void \ -hsw_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ - u32 __fifo_ret = 0; \ - GEN6_WRITE_HEADER; \ - if (NEEDS_FORCE_WAKE(offset)) { \ - __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ - } \ - __raw_i915_write##x(dev_priv, reg, val); \ - if (unlikely(__fifo_ret)) { \ - gen6_gt_check_fifodbg(dev_priv); \ - } \ - GEN6_WRITE_FOOTER; \ -} - #define __gen8_write(x) \ static void \ gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ @@ -1115,9 +1100,6 @@ __chv_write(32) __gen8_write(8) __gen8_write(16) __gen8_write(32) -__hsw_write(8) -__hsw_write(16) -__hsw_write(32) __gen6_write(8) __gen6_write(16) __gen6_write(32) @@ -1125,7 +1107,6 @@ __gen6_write(32) #undef __gen9_write #undef __chv_write #undef __gen8_write -#undef __hsw_write #undef __gen6_write #undef GEN6_WRITE_FOOTER #undef GEN6_WRITE_HEADER @@ -1342,11 +1323,7 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) break; case 7: case 6: - if (IS_HASWELL(dev_priv)) { - ASSIGN_WRITE_MMIO_VFUNCS(hsw); - } else { - ASSIGN_WRITE_MMIO_VFUNCS(gen6); - } + ASSIGN_WRITE_MMIO_VFUNCS(gen6); if (IS_VALLEYVIEW(dev_priv)) { ASSIGN_READ_MMIO_VFUNCS(vlv); -- cgit v1.2.3 From 003342a50021132603180d98e49bd17d63e38ccf Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:17 +0100 Subject: drm/i915: Keep track of active forcewake domains in a bitmask There are current places in the code, and there will be more in the future, which iterate the forcewake domains to find out which ones are currently active. To save them from doing this iteration, we can cheaply keep a mask of active domains in dev_priv->uncore.fw_domains_active. This has no cost in terms of object size, even manages to shrink it overall by 368 bytes on my config. Signed-off-by: Tvrtko Ursulin Cc: "Paneri, Praveen" Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_uncore.c | 54 ++++++++++++++++--------------------- 2 files changed, 25 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dbcac9379ffd..925239d1ea39 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -588,7 +588,9 @@ struct intel_uncore { struct intel_uncore_funcs funcs; unsigned fifo_count; + enum forcewake_domains fw_domains; + enum forcewake_domains fw_domains_active; struct intel_uncore_forcewake_domain { struct drm_i915_private *i915; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 18249e35bb02..ef40121afbaa 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -231,19 +231,21 @@ intel_uncore_fw_release_timer(struct hrtimer *timer) { struct intel_uncore_forcewake_domain *domain = container_of(timer, struct intel_uncore_forcewake_domain, timer); + struct drm_i915_private *dev_priv = domain->i915; unsigned long irqflags; - assert_rpm_device_not_suspended(domain->i915); + assert_rpm_device_not_suspended(dev_priv); - spin_lock_irqsave(&domain->i915->uncore.lock, irqflags); + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (WARN_ON(domain->wake_count == 0)) domain->wake_count++; - if (--domain->wake_count == 0) - domain->i915->uncore.funcs.force_wake_put(domain->i915, - 1 << domain->id); + if (--domain->wake_count == 0) { + dev_priv->uncore.funcs.force_wake_put(dev_priv, domain->mask); + dev_priv->uncore.fw_domains_active &= ~domain->mask; + } - spin_unlock_irqrestore(&domain->i915->uncore.lock, irqflags); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); return HRTIMER_NORESTART; } @@ -254,7 +256,7 @@ void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, unsigned long irqflags; struct intel_uncore_forcewake_domain *domain; int retry_count = 100; - enum forcewake_domains fw = 0, active_domains; + enum forcewake_domains fw, active_domains; /* Hold uncore.lock across reset to prevent any register access * with forcewake not set correctly. Wait until all pending @@ -291,10 +293,7 @@ void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, WARN_ON(active_domains); - for_each_fw_domain(domain, dev_priv) - if (domain->wake_count) - fw |= domain->mask; - + fw = dev_priv->uncore.fw_domains_active; if (fw) dev_priv->uncore.funcs.force_wake_put(dev_priv, fw); @@ -443,9 +442,6 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, { struct intel_uncore_forcewake_domain *domain; - if (!dev_priv->uncore.funcs.force_wake_get) - return; - fw_domains &= dev_priv->uncore.fw_domains; for_each_fw_domain_masked(domain, fw_domains, dev_priv) { @@ -453,8 +449,10 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, fw_domains &= ~domain->mask; } - if (fw_domains) + if (fw_domains) { dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); + dev_priv->uncore.fw_domains_active |= fw_domains; + } } /** @@ -509,9 +507,6 @@ static void __intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, { struct intel_uncore_forcewake_domain *domain; - if (!dev_priv->uncore.funcs.force_wake_put) - return; - fw_domains &= dev_priv->uncore.fw_domains; for_each_fw_domain_masked(domain, fw_domains, dev_priv) { @@ -567,13 +562,10 @@ void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv, void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) { - struct intel_uncore_forcewake_domain *domain; - if (!dev_priv->uncore.funcs.force_wake_get) return; - for_each_fw_domain(domain, dev_priv) - WARN_ON(domain->wake_count); + WARN_ON(dev_priv->uncore.fw_domains_active); } /* We give fast paths for the really cool registers */ @@ -877,18 +869,18 @@ static inline void __force_wake_auto(struct drm_i915_private *dev_priv, if (WARN_ON(!fw_domains)) return; - /* Ideally GCC would be constant-fold and eliminate this loop */ - for_each_fw_domain_masked(domain, fw_domains, dev_priv) { - if (domain->wake_count) { - fw_domains &= ~domain->mask; - continue; - } + /* Turn on all requested but inactive supported forcewake domains. */ + fw_domains &= dev_priv->uncore.fw_domains; + fw_domains &= ~dev_priv->uncore.fw_domains_active; - fw_domain_arm_timer(domain); - } + if (fw_domains) { + /* Ideally GCC would be constant-fold and eliminate this loop */ + for_each_fw_domain_masked(domain, fw_domains, dev_priv) + fw_domain_arm_timer(domain); - if (fw_domains) dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); + dev_priv->uncore.fw_domains_active |= fw_domains; + } } #define __gen6_read(x) \ -- cgit v1.2.3 From c521b0c898b0339d4d5fc091849211c5f469f1bd Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:18 +0100 Subject: drm/i915: Do not inline forcewake taking in mmio accessors Once we know we need to take new forcewakes, that being a slow operation, it does not make sense to inline that code into every mmio accessor. Move it to a separate function and save some code. v2: Be explicit with noinline and remove stale comment. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index ef40121afbaa..7ae38165f1bb 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -861,11 +861,21 @@ __gen2_read(64) trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ return val -static inline void __force_wake_auto(struct drm_i915_private *dev_priv, - enum forcewake_domains fw_domains) +static noinline void ___force_wake_auto(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) { struct intel_uncore_forcewake_domain *domain; + for_each_fw_domain_masked(domain, fw_domains, dev_priv) + fw_domain_arm_timer(domain); + + dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); + dev_priv->uncore.fw_domains_active |= fw_domains; +} + +static inline void __force_wake_auto(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) +{ if (WARN_ON(!fw_domains)) return; @@ -873,14 +883,8 @@ static inline void __force_wake_auto(struct drm_i915_private *dev_priv, fw_domains &= dev_priv->uncore.fw_domains; fw_domains &= ~dev_priv->uncore.fw_domains_active; - if (fw_domains) { - /* Ideally GCC would be constant-fold and eliminate this loop */ - for_each_fw_domain_masked(domain, fw_domains, dev_priv) - fw_domain_arm_timer(domain); - - dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); - dev_priv->uncore.fw_domains_active |= fw_domains; - } + if (fw_domains) + ___force_wake_auto(dev_priv, fw_domains); } #define __gen6_read(x) \ -- cgit v1.2.3 From 9fc1117cf8ca7a5100f2e86682cd4050a75f7f4d Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:19 +0100 Subject: drm/i915: Data driven register to forcewake domains lookup Move finding the correct forcewake domains to take for register access from code to a mapping table. This will allow more interesting work in the following patches and is easier to review if singled out early. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 212 ++++++++++++++++++------------------ 1 file changed, 103 insertions(+), 109 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 7ae38165f1bb..6a0f5fdf6ad1 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -581,28 +581,52 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) __fwd; \ }) -#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end)) +struct intel_forcewake_range +{ + u32 start; + u32 end; + + enum forcewake_domains domains; +}; -#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \ - (REG_RANGE((reg), 0x2000, 0x4000) || \ - REG_RANGE((reg), 0x5000, 0x8000) || \ - REG_RANGE((reg), 0xB000, 0x12000) || \ - REG_RANGE((reg), 0x2E000, 0x30000)) +static enum forcewake_domains +find_fw_domain(u32 offset, const struct intel_forcewake_range *ranges, + unsigned int num_ranges) +{ + unsigned int i; + struct intel_forcewake_range *entry = + (struct intel_forcewake_range *)ranges; + + for (i = 0; i < num_ranges; i++, entry++) { + if (offset >= entry->start && offset <= entry->end) + return entry->domains; + } + + return -1; +} -#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg) \ - (REG_RANGE((reg), 0x12000, 0x14000) || \ - REG_RANGE((reg), 0x22000, 0x24000) || \ - REG_RANGE((reg), 0x30000, 0x40000)) +#define GEN_FW_RANGE(s, e, d) \ + { .start = (s), .end = (e), .domains = (d) } + +static const struct intel_forcewake_range __vlv_fw_ranges[] = { + GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x5000, 0x7fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xb000, 0x11fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x2e000, 0x2ffff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), +}; #define __vlv_reg_read_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ - if (!NEEDS_FORCE_WAKE(offset)) \ - __fwd = 0; \ - else if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER; \ - else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_MEDIA; \ + if (NEEDS_FORCE_WAKE((offset))) { \ + __fwd = find_fw_domain(offset, __vlv_fw_ranges, \ + ARRAY_SIZE(__vlv_fw_ranges)); \ + if (__fwd == -1 ) \ + __fwd = 0; \ + } \ __fwd; \ }) @@ -636,104 +660,78 @@ static bool is_gen8_shadowed(u32 offset) __fwd; \ }) -#define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \ - (REG_RANGE((reg), 0x2000, 0x4000) || \ - REG_RANGE((reg), 0x5200, 0x8000) || \ - REG_RANGE((reg), 0x8300, 0x8500) || \ - REG_RANGE((reg), 0xB000, 0xB480) || \ - REG_RANGE((reg), 0xE000, 0xE800)) - -#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg) \ - (REG_RANGE((reg), 0x8800, 0x8900) || \ - REG_RANGE((reg), 0xD000, 0xD800) || \ - REG_RANGE((reg), 0x12000, 0x14000) || \ - REG_RANGE((reg), 0x1A000, 0x1C000) || \ - REG_RANGE((reg), 0x1E800, 0x1EA00) || \ - REG_RANGE((reg), 0x30000, 0x38000)) - -#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg) \ - (REG_RANGE((reg), 0x4000, 0x5000) || \ - REG_RANGE((reg), 0x8000, 0x8300) || \ - REG_RANGE((reg), 0x8500, 0x8600) || \ - REG_RANGE((reg), 0x9000, 0xB000) || \ - REG_RANGE((reg), 0xF000, 0x10000)) +static const struct intel_forcewake_range __chv_fw_ranges[] = { + GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xe000, 0xe7ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8800, 0x88ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x1a000, 0x1bfff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x1e800, 0x1e9ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x30000, 0x37fff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x4000, 0x4fff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x8000, 0x82ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x8500, 0x85ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x9000, 0xafff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), + GEN_FW_RANGE(0xf000, 0xffff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), +}; #define __chv_reg_read_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ - if (!NEEDS_FORCE_WAKE(offset)) \ - __fwd = 0; \ - else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER; \ - else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_MEDIA; \ - else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ + if (NEEDS_FORCE_WAKE((offset))) { \ + __fwd = find_fw_domain(offset, __chv_fw_ranges, \ + ARRAY_SIZE(__chv_fw_ranges)); \ + if (__fwd == -1 ) \ + __fwd = 0; \ + } \ __fwd; \ }) #define __chv_reg_write_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ - if (!NEEDS_FORCE_WAKE(offset) || is_gen8_shadowed(offset)) \ - __fwd = 0; \ - else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER; \ - else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_MEDIA; \ - else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ + if (NEEDS_FORCE_WAKE((offset)) && !is_gen8_shadowed(offset)) { \ + __fwd = find_fw_domain(offset, __chv_fw_ranges, \ + ARRAY_SIZE(__chv_fw_ranges)); \ + if (__fwd == -1 ) \ + __fwd = 0; \ + } \ __fwd; \ }) -#define FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) \ - REG_RANGE((reg), 0xB00, 0x2000) - -#define FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) \ - (REG_RANGE((reg), 0x2000, 0x2700) || \ - REG_RANGE((reg), 0x3000, 0x4000) || \ - REG_RANGE((reg), 0x5200, 0x8000) || \ - REG_RANGE((reg), 0x8140, 0x8160) || \ - REG_RANGE((reg), 0x8300, 0x8500) || \ - REG_RANGE((reg), 0x8C00, 0x8D00) || \ - REG_RANGE((reg), 0xB000, 0xB480) || \ - REG_RANGE((reg), 0xE000, 0xE900) || \ - REG_RANGE((reg), 0x24400, 0x24800)) - -#define FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) \ - (REG_RANGE((reg), 0x8130, 0x8140) || \ - REG_RANGE((reg), 0x8800, 0x8A00) || \ - REG_RANGE((reg), 0xD000, 0xD800) || \ - REG_RANGE((reg), 0x12000, 0x14000) || \ - REG_RANGE((reg), 0x1A000, 0x1EA00) || \ - REG_RANGE((reg), 0x30000, 0x40000)) - -#define FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg) \ - REG_RANGE((reg), 0x9400, 0x9800) - -#define FORCEWAKE_GEN9_BLITTER_RANGE_OFFSET(reg) \ - ((reg) < 0x40000 && \ - !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) && \ - !FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) && \ - !FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) && \ - !FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) - -#define SKL_NEEDS_FORCE_WAKE(reg) \ - ((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg)) +static const struct intel_forcewake_range __gen9_fw_ranges[] = { + GEN_FW_RANGE(0xb00, 0x1fff, 0), /* uncore range */ + GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8c00, 0x8cff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xe000, 0xe8ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x24400, 0x247ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x9400, 0x97ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x8130, 0x813f, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x8800, 0x89ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x1a000, 0x1e9ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), +}; #define __gen9_reg_read_fw_domains(offset) \ ({ \ - enum forcewake_domains __fwd; \ - if (!SKL_NEEDS_FORCE_WAKE(offset)) \ - __fwd = 0; \ - else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER; \ - else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_MEDIA; \ - else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ - else \ - __fwd = FORCEWAKE_BLITTER; \ + enum forcewake_domains __fwd = 0; \ + if (NEEDS_FORCE_WAKE((offset))) { \ + __fwd = find_fw_domain(offset, __gen9_fw_ranges, \ + ARRAY_SIZE(__gen9_fw_ranges)); \ + if (__fwd == -1 ) \ + __fwd = FORCEWAKE_BLITTER; \ + } \ __fwd; \ }) @@ -759,17 +757,13 @@ static bool is_gen9_shadowed(u32 offset) #define __gen9_reg_write_fw_domains(offset) \ ({ \ - enum forcewake_domains __fwd; \ - if (!SKL_NEEDS_FORCE_WAKE(offset) || is_gen9_shadowed(offset)) \ - __fwd = 0; \ - else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER; \ - else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_MEDIA; \ - else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \ - __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ - else \ - __fwd = FORCEWAKE_BLITTER; \ + enum forcewake_domains __fwd = 0; \ + if (NEEDS_FORCE_WAKE((offset)) && !is_gen9_shadowed(offset)) { \ + __fwd = find_fw_domain(offset, __gen9_fw_ranges, \ + ARRAY_SIZE(__gen9_fw_ranges)); \ + if (__fwd == -1 ) \ + __fwd = FORCEWAKE_BLITTER; \ + } \ __fwd; \ }) -- cgit v1.2.3 From b008123966a45bfda9ef71d35a0b76957d639291 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:20 +0100 Subject: drm/i915: Sort forcewake mapping tables Sorting the tables (verified at runtime to help during development) is another prerequisite for interesting work which will follow. v2: * Remove const away cast and improve comments. (Chris Wilson) * Check tables only when debug option is enabled. v3: Use IS_ENABLED. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 56 ++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 6a0f5fdf6ad1..aa84c40e3957 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -605,16 +605,35 @@ find_fw_domain(u32 offset, const struct intel_forcewake_range *ranges, return -1; } +static void +intel_fw_table_check(const struct intel_forcewake_range *ranges, + unsigned int num_ranges) +{ + s32 prev; + unsigned int i; + + if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG)) + return; + + for (i = 0, prev = -1; i < num_ranges; i++, ranges++) { + WARN_ON_ONCE(prev >= (s32)ranges->start); + prev = ranges->start; + WARN_ON_ONCE(prev >= (s32)ranges->end); + prev = ranges->end; + } +} + #define GEN_FW_RANGE(s, e, d) \ { .start = (s), .end = (e), .domains = (d) } +/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */ static const struct intel_forcewake_range __vlv_fw_ranges[] = { GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER), GEN_FW_RANGE(0x5000, 0x7fff, FORCEWAKE_RENDER), GEN_FW_RANGE(0xb000, 0x11fff, FORCEWAKE_RENDER), - GEN_FW_RANGE(0x2e000, 0x2ffff, FORCEWAKE_RENDER), GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x2e000, 0x2ffff, FORCEWAKE_RENDER), GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), }; @@ -660,23 +679,24 @@ static bool is_gen8_shadowed(u32 offset) __fwd; \ }) +/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */ static const struct intel_forcewake_range __chv_fw_ranges[] = { GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x4000, 0x4fff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8000, 0x82ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), - GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), - GEN_FW_RANGE(0xe000, 0xe7ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8500, 0x85ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), GEN_FW_RANGE(0x8800, 0x88ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x9000, 0xafff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), + GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0xe000, 0xe7ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xf000, 0xffff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), GEN_FW_RANGE(0x1a000, 0x1bfff, FORCEWAKE_MEDIA), GEN_FW_RANGE(0x1e800, 0x1e9ff, FORCEWAKE_MEDIA), GEN_FW_RANGE(0x30000, 0x37fff, FORCEWAKE_MEDIA), - GEN_FW_RANGE(0x4000, 0x4fff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), - GEN_FW_RANGE(0x8000, 0x82ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), - GEN_FW_RANGE(0x8500, 0x85ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), - GEN_FW_RANGE(0x9000, 0xafff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), - GEN_FW_RANGE(0xf000, 0xffff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), }; #define __chv_reg_read_fw_domains(offset) \ @@ -703,23 +723,24 @@ static const struct intel_forcewake_range __chv_fw_ranges[] = { __fwd; \ }) +/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */ static const struct intel_forcewake_range __gen9_fw_ranges[] = { GEN_FW_RANGE(0xb00, 0x1fff, 0), /* uncore range */ GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER), GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER), GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8130, 0x813f, FORCEWAKE_MEDIA), GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER), GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8800, 0x89ff, FORCEWAKE_MEDIA), GEN_FW_RANGE(0x8c00, 0x8cff, FORCEWAKE_RENDER), - GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), - GEN_FW_RANGE(0xe000, 0xe8ff, FORCEWAKE_RENDER), - GEN_FW_RANGE(0x24400, 0x247ff, FORCEWAKE_RENDER), GEN_FW_RANGE(0x9400, 0x97ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), - GEN_FW_RANGE(0x8130, 0x813f, FORCEWAKE_MEDIA), - GEN_FW_RANGE(0x8800, 0x89ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0xe000, 0xe8ff, FORCEWAKE_RENDER), GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), GEN_FW_RANGE(0x1a000, 0x1e9ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x24400, 0x247ff, FORCEWAKE_RENDER), GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), }; @@ -1298,11 +1319,17 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) switch (INTEL_INFO(dev_priv)->gen) { default: case 9: + intel_fw_table_check(__gen9_fw_ranges, + ARRAY_SIZE(__gen9_fw_ranges)); + ASSIGN_WRITE_MMIO_VFUNCS(gen9); ASSIGN_READ_MMIO_VFUNCS(gen9); break; case 8: if (IS_CHERRYVIEW(dev_priv)) { + intel_fw_table_check(__chv_fw_ranges, + ARRAY_SIZE(__chv_fw_ranges)); + ASSIGN_WRITE_MMIO_VFUNCS(chv); ASSIGN_READ_MMIO_VFUNCS(chv); @@ -1316,6 +1343,9 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) ASSIGN_WRITE_MMIO_VFUNCS(gen6); if (IS_VALLEYVIEW(dev_priv)) { + intel_fw_table_check(__vlv_fw_ranges, + ARRAY_SIZE(__vlv_fw_ranges)); + ASSIGN_READ_MMIO_VFUNCS(vlv); } else { ASSIGN_READ_MMIO_VFUNCS(gen6); -- cgit v1.2.3 From 91e630b9e636954708e933015e7f02f8bcd8b320 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:21 +0100 Subject: drm/i915: Use binary search when looking up forcewake domains Instead of the existing linear seach, now that we have sorted range tables, we can do a binary search on them for some potential miniscule performance gain, but more importantly for elegance and code size. Hopefully the perfomance gain is sufficient to offset the function calls which were not there before. v2: Removed const cast away. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index aa84c40e3957..aa898153cbed 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -26,6 +26,7 @@ #include "i915_vgpu.h" #include +#include #define FORCEWAKE_ACK_TIMEOUT_MS 50 @@ -589,20 +590,30 @@ struct intel_forcewake_range enum forcewake_domains domains; }; +static int fw_range_cmp(const void *key, const void *elt) +{ + const struct intel_forcewake_range *entry = elt; + u32 offset = (u32)((unsigned long)key); + + if (offset < entry->start) + return -1; + else if (offset > entry->end) + return 1; + else + return 0; +} + static enum forcewake_domains find_fw_domain(u32 offset, const struct intel_forcewake_range *ranges, unsigned int num_ranges) { - unsigned int i; - struct intel_forcewake_range *entry = - (struct intel_forcewake_range *)ranges; + struct intel_forcewake_range *entry; - for (i = 0; i < num_ranges; i++, entry++) { - if (offset >= entry->start && offset <= entry->end) - return entry->domains; - } + entry = bsearch((void *)(unsigned long)offset, (const void *)ranges, + num_ranges, sizeof(struct intel_forcewake_range), + fw_range_cmp); - return -1; + return entry ? entry->domains : -1; } static void -- cgit v1.2.3 From 0dd356bb6ff556e064672b0aa70908ca4567c7ff Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:22 +0100 Subject: drm/i915: Eliminate Gen9 special case If we insert blitter forcewake domain entries in the range table we can eliminate that special case and simplify the code in a few macros. This will enable more unification later. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index aa898153cbed..37df0080af68 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -613,7 +613,7 @@ find_fw_domain(u32 offset, const struct intel_forcewake_range *ranges, num_ranges, sizeof(struct intel_forcewake_range), fw_range_cmp); - return entry ? entry->domains : -1; + return entry ? entry->domains : 0; } static void @@ -651,12 +651,9 @@ static const struct intel_forcewake_range __vlv_fw_ranges[] = { #define __vlv_reg_read_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ - if (NEEDS_FORCE_WAKE((offset))) { \ + if (NEEDS_FORCE_WAKE((offset))) \ __fwd = find_fw_domain(offset, __vlv_fw_ranges, \ ARRAY_SIZE(__vlv_fw_ranges)); \ - if (__fwd == -1 ) \ - __fwd = 0; \ - } \ __fwd; \ }) @@ -713,57 +710,63 @@ static const struct intel_forcewake_range __chv_fw_ranges[] = { #define __chv_reg_read_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ - if (NEEDS_FORCE_WAKE((offset))) { \ + if (NEEDS_FORCE_WAKE((offset))) \ __fwd = find_fw_domain(offset, __chv_fw_ranges, \ ARRAY_SIZE(__chv_fw_ranges)); \ - if (__fwd == -1 ) \ - __fwd = 0; \ - } \ __fwd; \ }) #define __chv_reg_write_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ - if (NEEDS_FORCE_WAKE((offset)) && !is_gen8_shadowed(offset)) { \ + if (NEEDS_FORCE_WAKE((offset)) && !is_gen8_shadowed(offset)) \ __fwd = find_fw_domain(offset, __chv_fw_ranges, \ ARRAY_SIZE(__chv_fw_ranges)); \ - if (__fwd == -1 ) \ - __fwd = 0; \ - } \ __fwd; \ }) /* *Must* be sorted by offset ranges! See intel_fw_table_check(). */ static const struct intel_forcewake_range __gen9_fw_ranges[] = { + GEN_FW_RANGE(0x0, 0xaff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0xb00, 0x1fff, 0), /* uncore range */ GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x2700, 0x2fff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x4000, 0x51ff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8000, 0x812f, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x8130, 0x813f, FORCEWAKE_MEDIA), GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8160, 0x82ff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8500, 0x87ff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x8800, 0x89ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x8a00, 0x8bff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x8c00, 0x8cff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8d00, 0x93ff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x9400, 0x97ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x9800, 0xafff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xb480, 0xbfff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0xd800, 0xdfff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0xe000, 0xe8ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xe900, 0x11fff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x14000, 0x19fff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x1a000, 0x1e9ff, FORCEWAKE_MEDIA), + GEN_FW_RANGE(0x1ea00, 0x243ff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x24400, 0x247ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x24800, 0x2ffff, FORCEWAKE_BLITTER), GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), }; #define __gen9_reg_read_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ - if (NEEDS_FORCE_WAKE((offset))) { \ + if (NEEDS_FORCE_WAKE((offset))) \ __fwd = find_fw_domain(offset, __gen9_fw_ranges, \ ARRAY_SIZE(__gen9_fw_ranges)); \ - if (__fwd == -1 ) \ - __fwd = FORCEWAKE_BLITTER; \ - } \ __fwd; \ }) @@ -790,12 +793,9 @@ static bool is_gen9_shadowed(u32 offset) #define __gen9_reg_write_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ - if (NEEDS_FORCE_WAKE((offset)) && !is_gen9_shadowed(offset)) { \ + if (NEEDS_FORCE_WAKE((offset)) && !is_gen9_shadowed(offset)) \ __fwd = find_fw_domain(offset, __gen9_fw_ranges, \ ARRAY_SIZE(__gen9_fw_ranges)); \ - if (__fwd == -1 ) \ - __fwd = FORCEWAKE_BLITTER; \ - } \ __fwd; \ }) -- cgit v1.2.3 From 15157970f7c517a1e5759f506833086956c7d60a Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:23 +0100 Subject: drm/i915: Store the active forcewake range table pointer If we store this in the uncore structure we are on a good way to show more commonality between the per-platform implementations. v2: Constify table pointer and correct coding style. (Chris Wilson) v3: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 10 ++++++ drivers/gpu/drm/i915/intel_uncore.c | 68 ++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 925239d1ea39..f8c66eea06bc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -582,9 +582,19 @@ struct intel_uncore_funcs { uint32_t val, bool trace); }; +struct intel_forcewake_range { + u32 start; + u32 end; + + enum forcewake_domains domains; +}; + struct intel_uncore { spinlock_t lock; /** lock is also taken in irq contexts. */ + const struct intel_forcewake_range *fw_domains_table; + unsigned int fw_domains_table_entries; + struct intel_uncore_funcs funcs; unsigned fifo_count; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 37df0080af68..8642e6555193 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -582,14 +582,6 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) __fwd; \ }) -struct intel_forcewake_range -{ - u32 start; - u32 end; - - enum forcewake_domains domains; -}; - static int fw_range_cmp(const void *key, const void *elt) { const struct intel_forcewake_range *entry = elt; @@ -604,28 +596,38 @@ static int fw_range_cmp(const void *key, const void *elt) } static enum forcewake_domains -find_fw_domain(u32 offset, const struct intel_forcewake_range *ranges, - unsigned int num_ranges) +find_fw_domain(struct drm_i915_private *dev_priv, u32 offset) { - struct intel_forcewake_range *entry; + const struct intel_forcewake_range *table, *entry; + unsigned int num_entries; - entry = bsearch((void *)(unsigned long)offset, (const void *)ranges, - num_ranges, sizeof(struct intel_forcewake_range), + table = dev_priv->uncore.fw_domains_table; + num_entries = dev_priv->uncore.fw_domains_table_entries; + + entry = bsearch((void *)(unsigned long)offset, (const void *)table, + num_entries, sizeof(struct intel_forcewake_range), fw_range_cmp); return entry ? entry->domains : 0; } static void -intel_fw_table_check(const struct intel_forcewake_range *ranges, - unsigned int num_ranges) +intel_fw_table_check(struct drm_i915_private *dev_priv) { + const struct intel_forcewake_range *ranges; + unsigned int num_ranges; s32 prev; unsigned int i; if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG)) return; + ranges = dev_priv->uncore.fw_domains_table; + if (!ranges) + return; + + num_ranges = dev_priv->uncore.fw_domains_table_entries; + for (i = 0, prev = -1; i < num_ranges; i++, ranges++) { WARN_ON_ONCE(prev >= (s32)ranges->start); prev = ranges->start; @@ -652,8 +654,7 @@ static const struct intel_forcewake_range __vlv_fw_ranges[] = { ({ \ enum forcewake_domains __fwd = 0; \ if (NEEDS_FORCE_WAKE((offset))) \ - __fwd = find_fw_domain(offset, __vlv_fw_ranges, \ - ARRAY_SIZE(__vlv_fw_ranges)); \ + __fwd = find_fw_domain(dev_priv, offset); \ __fwd; \ }) @@ -711,8 +712,7 @@ static const struct intel_forcewake_range __chv_fw_ranges[] = { ({ \ enum forcewake_domains __fwd = 0; \ if (NEEDS_FORCE_WAKE((offset))) \ - __fwd = find_fw_domain(offset, __chv_fw_ranges, \ - ARRAY_SIZE(__chv_fw_ranges)); \ + __fwd = find_fw_domain(dev_priv, offset); \ __fwd; \ }) @@ -720,8 +720,7 @@ static const struct intel_forcewake_range __chv_fw_ranges[] = { ({ \ enum forcewake_domains __fwd = 0; \ if (NEEDS_FORCE_WAKE((offset)) && !is_gen8_shadowed(offset)) \ - __fwd = find_fw_domain(offset, __chv_fw_ranges, \ - ARRAY_SIZE(__chv_fw_ranges)); \ + __fwd = find_fw_domain(dev_priv, offset); \ __fwd; \ }) @@ -765,8 +764,7 @@ static const struct intel_forcewake_range __gen9_fw_ranges[] = { ({ \ enum forcewake_domains __fwd = 0; \ if (NEEDS_FORCE_WAKE((offset))) \ - __fwd = find_fw_domain(offset, __gen9_fw_ranges, \ - ARRAY_SIZE(__gen9_fw_ranges)); \ + __fwd = find_fw_domain(dev_priv, offset); \ __fwd; \ }) @@ -794,8 +792,7 @@ static bool is_gen9_shadowed(u32 offset) ({ \ enum forcewake_domains __fwd = 0; \ if (NEEDS_FORCE_WAKE((offset)) && !is_gen9_shadowed(offset)) \ - __fwd = find_fw_domain(offset, __gen9_fw_ranges, \ - ARRAY_SIZE(__gen9_fw_ranges)); \ + __fwd = find_fw_domain(dev_priv, offset); \ __fwd; \ }) @@ -1317,6 +1314,13 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) WARN_ON(dev_priv->uncore.fw_domains == 0); } +#define ASSIGN_FW_DOMAINS_TABLE(d) \ +{ \ + dev_priv->uncore.fw_domains_table = \ + (struct intel_forcewake_range *)(d); \ + dev_priv->uncore.fw_domains_table_entries = ARRAY_SIZE((d)); \ +} + void intel_uncore_init(struct drm_i915_private *dev_priv) { i915_check_vgpu(dev_priv); @@ -1330,17 +1334,13 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) switch (INTEL_INFO(dev_priv)->gen) { default: case 9: - intel_fw_table_check(__gen9_fw_ranges, - ARRAY_SIZE(__gen9_fw_ranges)); - + ASSIGN_FW_DOMAINS_TABLE(__gen9_fw_ranges); ASSIGN_WRITE_MMIO_VFUNCS(gen9); ASSIGN_READ_MMIO_VFUNCS(gen9); break; case 8: if (IS_CHERRYVIEW(dev_priv)) { - intel_fw_table_check(__chv_fw_ranges, - ARRAY_SIZE(__chv_fw_ranges)); - + ASSIGN_FW_DOMAINS_TABLE(__chv_fw_ranges); ASSIGN_WRITE_MMIO_VFUNCS(chv); ASSIGN_READ_MMIO_VFUNCS(chv); @@ -1354,9 +1354,7 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) ASSIGN_WRITE_MMIO_VFUNCS(gen6); if (IS_VALLEYVIEW(dev_priv)) { - intel_fw_table_check(__vlv_fw_ranges, - ARRAY_SIZE(__vlv_fw_ranges)); - + ASSIGN_FW_DOMAINS_TABLE(__vlv_fw_ranges); ASSIGN_READ_MMIO_VFUNCS(vlv); } else { ASSIGN_READ_MMIO_VFUNCS(gen6); @@ -1374,6 +1372,8 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) break; } + intel_fw_table_check(dev_priv); + if (intel_vgpu_active(dev_priv)) { ASSIGN_WRITE_MMIO_VFUNCS(vgpu); ASSIGN_READ_MMIO_VFUNCS(vgpu); -- cgit v1.2.3 From 895833bd97fb03bb391710f5d4f9bc092813d847 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:24 +0100 Subject: drm/i915: Remove identical macros Remove some macros which are now obviously identical. v2: Added HAS_FWTABLE macro and simplified intel_uncore_forcewake_for_read. (Joonas Lahtinen) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 70 +++++++++++-------------------------- 1 file changed, 20 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 8642e6555193..1e6aa4db0e6a 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -639,6 +639,11 @@ intel_fw_table_check(struct drm_i915_private *dev_priv) #define GEN_FW_RANGE(s, e, d) \ { .start = (s), .end = (e), .domains = (d) } +#define HAS_FWTABLE(dev_priv) \ + (IS_GEN9(dev_priv) || \ + IS_CHERRYVIEW(dev_priv) || \ + IS_VALLEYVIEW(dev_priv)) + /* *Must* be sorted by offset ranges! See intel_fw_table_check(). */ static const struct intel_forcewake_range __vlv_fw_ranges[] = { GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER), @@ -650,7 +655,7 @@ static const struct intel_forcewake_range __vlv_fw_ranges[] = { GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), }; -#define __vlv_reg_read_fw_domains(offset) \ +#define __fwtable_reg_read_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ if (NEEDS_FORCE_WAKE((offset))) \ @@ -708,14 +713,6 @@ static const struct intel_forcewake_range __chv_fw_ranges[] = { GEN_FW_RANGE(0x30000, 0x37fff, FORCEWAKE_MEDIA), }; -#define __chv_reg_read_fw_domains(offset) \ -({ \ - enum forcewake_domains __fwd = 0; \ - if (NEEDS_FORCE_WAKE((offset))) \ - __fwd = find_fw_domain(dev_priv, offset); \ - __fwd; \ -}) - #define __chv_reg_write_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ @@ -760,14 +757,6 @@ static const struct intel_forcewake_range __gen9_fw_ranges[] = { GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), }; -#define __gen9_reg_read_fw_domains(offset) \ -({ \ - enum forcewake_domains __fwd = 0; \ - if (NEEDS_FORCE_WAKE((offset))) \ - __fwd = find_fw_domain(dev_priv, offset); \ - __fwd; \ -}) - static const i915_reg_t gen9_shadowed_regs[] = { RING_TAIL(RENDER_RING_BASE), RING_TAIL(GEN6_BSD_RING_BASE), @@ -927,7 +916,7 @@ static u##x \ vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_READ_HEADER(x); \ - fw_engine = __vlv_reg_read_fw_domains(offset); \ + fw_engine = __fwtable_reg_read_fw_domains(offset); \ if (fw_engine) \ __force_wake_auto(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ @@ -939,7 +928,7 @@ static u##x \ chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_READ_HEADER(x); \ - fw_engine = __chv_reg_read_fw_domains(offset); \ + fw_engine = __fwtable_reg_read_fw_domains(offset); \ if (fw_engine) \ __force_wake_auto(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ @@ -951,7 +940,7 @@ static u##x \ gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_READ_HEADER(x); \ - fw_engine = __gen9_reg_read_fw_domains(offset); \ + fw_engine = __fwtable_reg_read_fw_domains(offset); \ if (fw_engine) \ __force_wake_auto(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ @@ -1823,35 +1812,16 @@ static enum forcewake_domains intel_uncore_forcewake_for_read(struct drm_i915_private *dev_priv, i915_reg_t reg) { + u32 offset = i915_mmio_reg_offset(reg); enum forcewake_domains fw_domains; - if (intel_vgpu_active(dev_priv)) - return 0; - - switch (INTEL_GEN(dev_priv)) { - case 9: - fw_domains = __gen9_reg_read_fw_domains(i915_mmio_reg_offset(reg)); - break; - case 8: - if (IS_CHERRYVIEW(dev_priv)) - fw_domains = __chv_reg_read_fw_domains(i915_mmio_reg_offset(reg)); - else - fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg)); - break; - case 7: - case 6: - if (IS_VALLEYVIEW(dev_priv)) - fw_domains = __vlv_reg_read_fw_domains(i915_mmio_reg_offset(reg)); - else - fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg)); - break; - default: - MISSING_CASE(INTEL_INFO(dev_priv)->gen); - case 5: /* forcewake was introduced with gen6 */ - case 4: - case 3: - case 2: - return 0; + if (HAS_FWTABLE(dev_priv)) { + fw_domains = __fwtable_reg_read_fw_domains(offset); + } else if (INTEL_GEN(dev_priv) >= 6) { + fw_domains = __gen6_reg_read_fw_domains(offset); + } else { + WARN_ON(!IS_GEN(dev_priv, 2, 5)); + fw_domains = 0; } WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); @@ -1865,9 +1835,6 @@ intel_uncore_forcewake_for_write(struct drm_i915_private *dev_priv, { enum forcewake_domains fw_domains; - if (intel_vgpu_active(dev_priv)) - return 0; - switch (INTEL_GEN(dev_priv)) { case 9: fw_domains = __gen9_reg_write_fw_domains(i915_mmio_reg_offset(reg)); @@ -1918,6 +1885,9 @@ intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv, WARN_ON(!op); + if (intel_vgpu_active(dev_priv)) + return 0; + if (op & FW_REG_READ) fw_domains = intel_uncore_forcewake_for_read(dev_priv, reg); -- cgit v1.2.3 From 6044c4a3710212cf4a68340744ba0bdc069d5928 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:25 +0100 Subject: drm/i915: Remove identical mmio read functions It is now obvious VLV, CHV and Gen9 mmio read fcuntions are completely identical so we can remove the three copies and just keep the newly named generic implementation. v2: Use fwtable naming consistently. (Joonas Lahtinen) Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 54 +++++++------------------------------ 1 file changed, 10 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 1e6aa4db0e6a..2807e88d9c3e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -911,9 +911,9 @@ gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ GEN6_READ_FOOTER; \ } -#define __vlv_read(x) \ +#define __fwtable_read(x) \ static u##x \ -vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ +fwtable_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_READ_HEADER(x); \ fw_engine = __fwtable_reg_read_fw_domains(offset); \ @@ -923,50 +923,16 @@ vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ GEN6_READ_FOOTER; \ } -#define __chv_read(x) \ -static u##x \ -chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ - enum forcewake_domains fw_engine; \ - GEN6_READ_HEADER(x); \ - fw_engine = __fwtable_reg_read_fw_domains(offset); \ - if (fw_engine) \ - __force_wake_auto(dev_priv, fw_engine); \ - val = __raw_i915_read##x(dev_priv, reg); \ - GEN6_READ_FOOTER; \ -} - -#define __gen9_read(x) \ -static u##x \ -gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ - enum forcewake_domains fw_engine; \ - GEN6_READ_HEADER(x); \ - fw_engine = __fwtable_reg_read_fw_domains(offset); \ - if (fw_engine) \ - __force_wake_auto(dev_priv, fw_engine); \ - val = __raw_i915_read##x(dev_priv, reg); \ - GEN6_READ_FOOTER; \ -} - -__gen9_read(8) -__gen9_read(16) -__gen9_read(32) -__gen9_read(64) -__chv_read(8) -__chv_read(16) -__chv_read(32) -__chv_read(64) -__vlv_read(8) -__vlv_read(16) -__vlv_read(32) -__vlv_read(64) +__fwtable_read(8) +__fwtable_read(16) +__fwtable_read(32) +__fwtable_read(64) __gen6_read(8) __gen6_read(16) __gen6_read(32) __gen6_read(64) -#undef __gen9_read -#undef __chv_read -#undef __vlv_read +#undef __fwtable_read #undef __gen6_read #undef GEN6_READ_FOOTER #undef GEN6_READ_HEADER @@ -1325,13 +1291,13 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) case 9: ASSIGN_FW_DOMAINS_TABLE(__gen9_fw_ranges); ASSIGN_WRITE_MMIO_VFUNCS(gen9); - ASSIGN_READ_MMIO_VFUNCS(gen9); + ASSIGN_READ_MMIO_VFUNCS(fwtable); break; case 8: if (IS_CHERRYVIEW(dev_priv)) { ASSIGN_FW_DOMAINS_TABLE(__chv_fw_ranges); ASSIGN_WRITE_MMIO_VFUNCS(chv); - ASSIGN_READ_MMIO_VFUNCS(chv); + ASSIGN_READ_MMIO_VFUNCS(fwtable); } else { ASSIGN_WRITE_MMIO_VFUNCS(gen8); @@ -1344,7 +1310,7 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv)) { ASSIGN_FW_DOMAINS_TABLE(__vlv_fw_ranges); - ASSIGN_READ_MMIO_VFUNCS(vlv); + ASSIGN_READ_MMIO_VFUNCS(fwtable); } else { ASSIGN_READ_MMIO_VFUNCS(gen6); } -- cgit v1.2.3 From 22d48c55ba5fbc9ecff51b0bdca829abd2b508cb Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:26 +0100 Subject: drm/i915: Remove identical write mmmio functions We notice two identical copies of the shadow register table and following from that removal can also unify CHV and Gen9 write mmio functions and macros into a single implementation. v2: Name fwtable consistently and use HAS_FWTABLE. (Joonas Lahtinen) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 94 ++++++++----------------------------- 1 file changed, 19 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 2807e88d9c3e..fbcc3039db10 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -713,7 +713,7 @@ static const struct intel_forcewake_range __chv_fw_ranges[] = { GEN_FW_RANGE(0x30000, 0x37fff, FORCEWAKE_MEDIA), }; -#define __chv_reg_write_fw_domains(offset) \ +#define __fwtable_reg_write_fw_domains(offset) \ ({ \ enum forcewake_domains __fwd = 0; \ if (NEEDS_FORCE_WAKE((offset)) && !is_gen8_shadowed(offset)) \ @@ -757,34 +757,6 @@ static const struct intel_forcewake_range __gen9_fw_ranges[] = { GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), }; -static const i915_reg_t gen9_shadowed_regs[] = { - RING_TAIL(RENDER_RING_BASE), - RING_TAIL(GEN6_BSD_RING_BASE), - RING_TAIL(VEBOX_RING_BASE), - RING_TAIL(BLT_RING_BASE), - GEN6_RPNSWREQ, - GEN6_RC_VIDEO_FREQ, - /* TODO: Other registers are not yet used */ -}; - -static bool is_gen9_shadowed(u32 offset) -{ - int i; - for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++) - if (offset == gen9_shadowed_regs[i].reg) - return true; - - return false; -} - -#define __gen9_reg_write_fw_domains(offset) \ -({ \ - enum forcewake_domains __fwd = 0; \ - if (NEEDS_FORCE_WAKE((offset)) && !is_gen9_shadowed(offset)) \ - __fwd = find_fw_domain(dev_priv, offset); \ - __fwd; \ -}) - static void ilk_dummy_write(struct drm_i915_private *dev_priv) { @@ -1040,37 +1012,21 @@ gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool GEN6_WRITE_FOOTER; \ } -#define __chv_write(x) \ +#define __fwtable_write(x) \ static void \ -chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ +fwtable_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_WRITE_HEADER; \ - fw_engine = __chv_reg_write_fw_domains(offset); \ + fw_engine = __fwtable_reg_write_fw_domains(offset); \ if (fw_engine) \ __force_wake_auto(dev_priv, fw_engine); \ __raw_i915_write##x(dev_priv, reg, val); \ GEN6_WRITE_FOOTER; \ } -#define __gen9_write(x) \ -static void \ -gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \ - bool trace) { \ - enum forcewake_domains fw_engine; \ - GEN6_WRITE_HEADER; \ - fw_engine = __gen9_reg_write_fw_domains(offset); \ - if (fw_engine) \ - __force_wake_auto(dev_priv, fw_engine); \ - __raw_i915_write##x(dev_priv, reg, val); \ - GEN6_WRITE_FOOTER; \ -} - -__gen9_write(8) -__gen9_write(16) -__gen9_write(32) -__chv_write(8) -__chv_write(16) -__chv_write(32) +__fwtable_write(8) +__fwtable_write(16) +__fwtable_write(32) __gen8_write(8) __gen8_write(16) __gen8_write(32) @@ -1078,8 +1034,7 @@ __gen6_write(8) __gen6_write(16) __gen6_write(32) -#undef __gen9_write -#undef __chv_write +#undef __fwtable_write #undef __gen8_write #undef __gen6_write #undef GEN6_WRITE_FOOTER @@ -1290,13 +1245,13 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) default: case 9: ASSIGN_FW_DOMAINS_TABLE(__gen9_fw_ranges); - ASSIGN_WRITE_MMIO_VFUNCS(gen9); + ASSIGN_WRITE_MMIO_VFUNCS(fwtable); ASSIGN_READ_MMIO_VFUNCS(fwtable); break; case 8: if (IS_CHERRYVIEW(dev_priv)) { ASSIGN_FW_DOMAINS_TABLE(__chv_fw_ranges); - ASSIGN_WRITE_MMIO_VFUNCS(chv); + ASSIGN_WRITE_MMIO_VFUNCS(fwtable); ASSIGN_READ_MMIO_VFUNCS(fwtable); } else { @@ -1799,29 +1754,18 @@ static enum forcewake_domains intel_uncore_forcewake_for_write(struct drm_i915_private *dev_priv, i915_reg_t reg) { + u32 offset = i915_mmio_reg_offset(reg); enum forcewake_domains fw_domains; - switch (INTEL_GEN(dev_priv)) { - case 9: - fw_domains = __gen9_reg_write_fw_domains(i915_mmio_reg_offset(reg)); - break; - case 8: - if (IS_CHERRYVIEW(dev_priv)) - fw_domains = __chv_reg_write_fw_domains(i915_mmio_reg_offset(reg)); - else - fw_domains = __gen8_reg_write_fw_domains(i915_mmio_reg_offset(reg)); - break; - case 7: - case 6: + if (HAS_FWTABLE(dev_priv) && !IS_VALLEYVIEW(dev_priv)) { + fw_domains = __fwtable_reg_write_fw_domains(offset); + } else if (IS_GEN8(dev_priv)) { + fw_domains = __gen8_reg_write_fw_domains(offset); + } else if (IS_GEN(dev_priv, 6, 7)) { fw_domains = FORCEWAKE_RENDER; - break; - default: - MISSING_CASE(INTEL_INFO(dev_priv)->gen); - case 5: - case 4: - case 3: - case 2: - return 0; + } else { + WARN_ON(!IS_GEN(dev_priv, 2, 5)); + fw_domains = 0; } WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); -- cgit v1.2.3 From 47188574a966b9b9ba0aa5a0fa88d934a331dc07 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:27 +0100 Subject: drm/i915: Sort the shadow register table Also verify the order at runtime. This was we can start using binary search on it in a following patch. v2: Add comment on the sorted array and only check it when debug option is enabled. v3: Use IS_ENABLED. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen (v1) Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index fbcc3039db10..d7c9b6bc6e5e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -663,16 +663,34 @@ static const struct intel_forcewake_range __vlv_fw_ranges[] = { __fwd; \ }) +/* *Must* be sorted by offset! See intel_shadow_table_check(). */ static const i915_reg_t gen8_shadowed_regs[] = { - GEN6_RPNSWREQ, - GEN6_RC_VIDEO_FREQ, - RING_TAIL(RENDER_RING_BASE), - RING_TAIL(GEN6_BSD_RING_BASE), - RING_TAIL(VEBOX_RING_BASE), - RING_TAIL(BLT_RING_BASE), + RING_TAIL(RENDER_RING_BASE), /* 0x2000 (base) */ + GEN6_RPNSWREQ, /* 0xA008 */ + GEN6_RC_VIDEO_FREQ, /* 0xA00C */ + RING_TAIL(GEN6_BSD_RING_BASE), /* 0x12000 (base) */ + RING_TAIL(VEBOX_RING_BASE), /* 0x1a000 (base) */ + RING_TAIL(BLT_RING_BASE), /* 0x22000 (base) */ /* TODO: Other registers are not yet used */ }; +static void intel_shadow_table_check(void) +{ + const i915_reg_t *reg = gen8_shadowed_regs; + s32 prev; + u32 offset; + unsigned int i; + + if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG)) + return; + + for (i = 0, prev = -1; i < ARRAY_SIZE(gen8_shadowed_regs); i++, reg++) { + offset = i915_mmio_reg_offset(*reg); + WARN_ON_ONCE(prev >= (s32)offset); + prev = offset; + } +} + static bool is_gen8_shadowed(u32 offset) { int i; @@ -1283,6 +1301,8 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) } intel_fw_table_check(dev_priv); + if (INTEL_GEN(dev_priv) >= 8) + intel_shadow_table_check(); if (intel_vgpu_active(dev_priv)) { ASSIGN_WRITE_MMIO_VFUNCS(vgpu); -- cgit v1.2.3 From 5a659383816aa548e7a1049d3dd5dd552966acac Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:28 +0100 Subject: drm/i915: Use binary search when looking for shadowed registers Simply replace the linear search with the kernel's binary search implementation. There is only six registers currently in that table so this may not be that interesting. It adds a function call so hopefully remains performance neutral for now. v2: No need for manual conversion to bool for return. (Joonas Lahtinen) Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_uncore.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index d7c9b6bc6e5e..8ac684598cec 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -691,14 +691,30 @@ static void intel_shadow_table_check(void) } } +static int mmio_reg_cmp(const void *key, const void *elt) +{ + u32 offset = (u32)(unsigned long)key; + i915_reg_t *reg = (i915_reg_t *)elt; + + if (offset < i915_mmio_reg_offset(*reg)) + return -1; + else if (offset > i915_mmio_reg_offset(*reg)) + return 1; + else + return 0; +} + static bool is_gen8_shadowed(u32 offset) { - int i; - for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++) - if (offset == gen8_shadowed_regs[i].reg) - return true; + i915_reg_t *reg; - return false; + reg = bsearch((void *)(unsigned long)offset, + (const void *)gen8_shadowed_regs, + ARRAY_SIZE(gen8_shadowed_regs), + sizeof(i915_reg_t), + mmio_reg_cmp); + + return reg; } #define __gen8_reg_write_fw_domains(offset) \ -- cgit v1.2.3 From 9480dbf074417ef8b06ba3923b8648f49c85265b Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Oct 2016 09:29:29 +0100 Subject: drm/i915: Inline binary search Instead of using bsearch library function make a local generator macro out of it so the comparison callback can be inlined. Signed-off-by: Tvrtko Ursulin Suggested-by: Chris Wilson Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1475569769-31108-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_uncore.c | 56 ++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 8ac684598cec..e2b188dcf908 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -26,7 +26,6 @@ #include "i915_vgpu.h" #include -#include #define FORCEWAKE_ACK_TIMEOUT_MS 50 @@ -582,11 +581,8 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) __fwd; \ }) -static int fw_range_cmp(const void *key, const void *elt) +static int fw_range_cmp(u32 offset, const struct intel_forcewake_range *entry) { - const struct intel_forcewake_range *entry = elt; - u32 offset = (u32)((unsigned long)key); - if (offset < entry->start) return -1; else if (offset > entry->end) @@ -595,17 +591,33 @@ static int fw_range_cmp(const void *key, const void *elt) return 0; } +/* Copied and "macroized" from lib/bsearch.c */ +#define BSEARCH(key, base, num, cmp) ({ \ + unsigned int start__ = 0, end__ = (num); \ + typeof(base) result__ = NULL; \ + while (start__ < end__) { \ + unsigned int mid__ = start__ + (end__ - start__) / 2; \ + int ret__ = (cmp)((key), (base) + mid__); \ + if (ret__ < 0) { \ + end__ = mid__; \ + } else if (ret__ > 0) { \ + start__ = mid__ + 1; \ + } else { \ + result__ = (base) + mid__; \ + break; \ + } \ + } \ + result__; \ +}) + static enum forcewake_domains find_fw_domain(struct drm_i915_private *dev_priv, u32 offset) { - const struct intel_forcewake_range *table, *entry; - unsigned int num_entries; + const struct intel_forcewake_range *entry; - table = dev_priv->uncore.fw_domains_table; - num_entries = dev_priv->uncore.fw_domains_table_entries; - - entry = bsearch((void *)(unsigned long)offset, (const void *)table, - num_entries, sizeof(struct intel_forcewake_range), + entry = BSEARCH(offset, + dev_priv->uncore.fw_domains_table, + dev_priv->uncore.fw_domains_table_entries, fw_range_cmp); return entry ? entry->domains : 0; @@ -691,14 +703,13 @@ static void intel_shadow_table_check(void) } } -static int mmio_reg_cmp(const void *key, const void *elt) +static int mmio_reg_cmp(u32 key, const i915_reg_t *reg) { - u32 offset = (u32)(unsigned long)key; - i915_reg_t *reg = (i915_reg_t *)elt; + u32 offset = i915_mmio_reg_offset(*reg); - if (offset < i915_mmio_reg_offset(*reg)) + if (key < offset) return -1; - else if (offset > i915_mmio_reg_offset(*reg)) + else if (key > offset) return 1; else return 0; @@ -706,15 +717,10 @@ static int mmio_reg_cmp(const void *key, const void *elt) static bool is_gen8_shadowed(u32 offset) { - i915_reg_t *reg; - - reg = bsearch((void *)(unsigned long)offset, - (const void *)gen8_shadowed_regs, - ARRAY_SIZE(gen8_shadowed_regs), - sizeof(i915_reg_t), - mmio_reg_cmp); + const i915_reg_t *regs = gen8_shadowed_regs; - return reg; + return BSEARCH(offset, regs, ARRAY_SIZE(gen8_shadowed_regs), + mmio_reg_cmp); } #define __gen8_reg_write_fw_domains(offset) \ -- cgit v1.2.3 From bb7791bd2bd424938edb269a17ab154c0d341327 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Oct 2016 12:29:17 +0300 Subject: drm/i915: make skl_ddb_add_affected_planes static Fix sparse warning: drivers/gpu/drm/i915/intel_pm.c:3970:1: warning: symbol 'skl_ddb_add_affected_planes' was not declared. Should it be static? Fixes: 7f60e200e254 ("drm/i915/gen9: only add the planes actually affected by ddb changes") Cc: Lyude Cc: Paulo Zanoni Reviewed-by: Joonas Lahtinen Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1475573357-30562-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 425544b1f733..7f1748a1e614 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3966,7 +3966,7 @@ pipes_modified(struct drm_atomic_state *state) return ret; } -int +static int skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) { struct drm_atomic_state *state = cstate->base.state; -- cgit v1.2.3 From 615e5000830dd24b8dc6876a6a1babbeda998fdf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Oct 2016 12:54:13 +0300 Subject: drm/i915: silence io mapping/unmapping sparse warnings on different address spaces drivers/gpu/drm/i915/i915_gem_execbuffer.c:432:52: warning: incorrect type in argument 1 (different address spaces) drivers/gpu/drm/i915/i915_gem_execbuffer.c:432:52: expected void [noderef] *vaddr drivers/gpu/drm/i915/i915_gem_execbuffer.c:432:52: got void * drivers/gpu/drm/i915/i915_gem_execbuffer.c:477:15: warning: incorrect type in assignment (different address spaces) drivers/gpu/drm/i915/i915_gem_execbuffer.c:477:15: expected void *vaddr drivers/gpu/drm/i915/i915_gem_execbuffer.c:477:15: got void [noderef] * Cc: Chris Wilson Reviewed-by: Joonas Lahtinen Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1475574853-4178-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 33c85227643d..e88786ea1219 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -429,7 +429,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, } if (cache->vaddr) { - io_mapping_unmap_atomic(unmask_page(cache->vaddr)); + io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr)); } else { struct i915_vma *vma; int ret; @@ -474,7 +474,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, offset += page << PAGE_SHIFT; } - vaddr = io_mapping_map_atomic_wc(&cache->i915->ggtt.mappable, offset); + vaddr = (void __force *) io_mapping_map_atomic_wc(&cache->i915->ggtt.mappable, offset); cache->page = page; cache->vaddr = (unsigned long)vaddr; -- cgit v1.2.3 From ac86aa5755dbd8b127f03c5a0bf641caf73378f2 Mon Sep 17 00:00:00 2001 From: Maharaja Kennadyrajan Date: Wed, 28 Sep 2016 15:11:53 +0300 Subject: ath10k: provide provision to get Transmit Power Control stats for 10.4 This patch helps to get the TPC stats for 10.4 fw variants. Signed-off-by: Maharaja Kennadyrajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 54df425bb0fc..4829513550a9 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5397,6 +5397,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) case WMI_10_4_PDEV_BSS_CHAN_INFO_EVENTID: ath10k_wmi_event_pdev_bss_chan_info(ar, skb); break; + case WMI_10_4_PDEV_TPC_CONFIG_EVENTID: + ath10k_wmi_event_pdev_tpc_config(ar, skb); + break; default: ath10k_warn(ar, "Unknown eventid: %d\n", id); break; @@ -8153,6 +8156,7 @@ static const struct wmi_ops wmi_10_4_ops = { .get_vdev_subtype = ath10k_wmi_10_4_op_get_vdev_subtype, .gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info, .gen_echo = ath10k_wmi_op_gen_echo, + .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, }; int ath10k_wmi_attach(struct ath10k *ar) -- cgit v1.2.3 From bafe492610d58ec66cc149b19c51774efd95344a Mon Sep 17 00:00:00 2001 From: Anilkumar Kolli Date: Wed, 28 Sep 2016 15:11:53 +0300 Subject: ath10k: add cc_wraparound type for QCA9888 and QCA9884 During offchannel scan, iw survey dump shows wrong values. Fix this by assigning cycle counter wranarround type for QCA9888 and QCA9884, they share same config with QCA4019. Signed-off-by: Anilkumar Kolli Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 21ae8d663e67..867a8403b15b 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -198,6 +198,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = "qca9984/qca9994 hw1.0", .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR, .uart_pin = 7, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, .otp_exe_param = 0x00000700, .continuous_frag_desc = true, .cck_rate_map_rev2 = true, @@ -223,6 +224,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = "qca9888 hw2.0", .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, .otp_exe_param = 0x00000700, .continuous_frag_desc = true, .channel_counters_freq_hz = 150000, -- cgit v1.2.3 From d291d8e0592ad5effaaa1af7de95dc9bfecc4f9e Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 28 Sep 2016 15:11:57 +0300 Subject: ath: export alpha2 helper This will be helpful for drivers that can acquire alpha2 regulatory codes. Signed-off-by: Michal Kazior Signed-off-by: Bartosz Markowski Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/regd.c | 3 ++- drivers/net/wireless/ath/regd.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index f8506037736f..43afa83a9f0c 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -449,7 +449,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, } } -static u16 ath_regd_find_country_by_name(char *alpha2) +u16 ath_regd_find_country_by_name(char *alpha2) { unsigned int i; @@ -460,6 +460,7 @@ static u16 ath_regd_find_country_by_name(char *alpha2) return -1; } +EXPORT_SYMBOL(ath_regd_find_country_by_name); static int __ath_reg_dyn_country(struct wiphy *wiphy, struct ath_regulatory *reg, diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 565d3075f06e..5d80be213fac 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -251,6 +251,7 @@ enum CountryCode { bool ath_is_world_regd(struct ath_regulatory *reg); bool ath_is_49ghz_allowed(u16 redomain); +u16 ath_regd_find_country_by_name(char *alpha2); int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, void (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request)); -- cgit v1.2.3 From 209b2a68de76c888002a4d054ef27b78ae9d2de2 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Wed, 28 Sep 2016 15:11:58 +0300 Subject: ath10k: add platform regulatory domain support This overrides whatever regulatory the device EEPROM contains and uses what the platform says instead - in this implementation the ACPI driver. In case the hint is not programmed or corrupted (0xffff) the device falls back to the eeprom programmed settings. Signed-off-by: Bartosz Markowski [kvalo@qca.qualcomm.com: remove ifdef, change error handling, change info messages to dbg] Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 113 ++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 3 files changed, 114 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index dda49af1eb74..c091306bca33 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -713,6 +713,7 @@ struct ath10k { u32 phy_capability; u32 hw_min_tx_power; u32 hw_max_tx_power; + u32 hw_eeprom_rd; u32 ht_cap_info; u32 vht_cap_info; u32 num_rf_chains; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 76297d69f1ed..ed71b95a661d 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -19,6 +19,7 @@ #include #include +#include #include "hif.h" #include "core.h" @@ -3179,7 +3180,8 @@ static void ath10k_mac_vif_handle_tx_pause(struct ath10k_vif *arvif, ath10k_mac_vif_tx_unlock(arvif, pause_id); break; default: - ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n", + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "received unknown tx pause action %d on vdev %i, ignoring\n", action, arvif->vdev_id); break; } @@ -7789,6 +7791,109 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id) return arvif_iter.arvif; } +#define WRD_METHOD "WRDD" +#define WRDD_WIFI (0x07) + +static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd) +{ + union acpi_object *mcc_pkg; + union acpi_object *domain_type; + union acpi_object *mcc_value; + u32 i; + + if (wrdd->type != ACPI_TYPE_PACKAGE || + wrdd->package.count < 2 || + wrdd->package.elements[0].type != ACPI_TYPE_INTEGER || + wrdd->package.elements[0].integer.value != 0) { + ath10k_warn(ar, "ignoring malformed/unsupported wrdd structure\n"); + return 0; + } + + for (i = 1; i < wrdd->package.count; ++i) { + mcc_pkg = &wrdd->package.elements[i]; + + if (mcc_pkg->type != ACPI_TYPE_PACKAGE) + continue; + if (mcc_pkg->package.count < 2) + continue; + if (mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER || + mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) + continue; + + domain_type = &mcc_pkg->package.elements[0]; + if (domain_type->integer.value != WRDD_WIFI) + continue; + + mcc_value = &mcc_pkg->package.elements[1]; + return mcc_value->integer.value; + } + return 0; +} + +static int ath10k_mac_get_wrdd_regulatory(struct ath10k *ar, u16 *rd) +{ + struct pci_dev __maybe_unused *pdev = to_pci_dev(ar->dev); + acpi_handle root_handle; + acpi_handle handle; + struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_status status; + u32 alpha2_code; + char alpha2[3]; + + root_handle = ACPI_HANDLE(&pdev->dev); + if (!root_handle) + return -EOPNOTSUPP; + + status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle); + if (ACPI_FAILURE(status)) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "failed to get wrd method %d\n", status); + return -EIO; + } + + status = acpi_evaluate_object(handle, NULL, NULL, &wrdd); + if (ACPI_FAILURE(status)) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "failed to call wrdc %d\n", status); + return -EIO; + } + + alpha2_code = ath10k_mac_wrdd_get_mcc(ar, wrdd.pointer); + kfree(wrdd.pointer); + if (!alpha2_code) + return -EIO; + + alpha2[0] = (alpha2_code >> 8) & 0xff; + alpha2[1] = (alpha2_code >> 0) & 0xff; + alpha2[2] = '\0'; + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "regulatory hint from WRDD (alpha2-code): %s\n", alpha2); + + *rd = ath_regd_find_country_by_name(alpha2); + if (*rd == 0xffff) + return -EIO; + + *rd |= COUNTRY_ERD_FLAG; + return 0; +} + +static int ath10k_mac_init_rd(struct ath10k *ar) +{ + int ret; + u16 rd; + + ret = ath10k_mac_get_wrdd_regulatory(ar, &rd); + if (ret) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "fallback to eeprom programmed regulatory settings\n"); + rd = ar->hw_eeprom_rd; + } + + ar->ath_common.regulatory.current_rd = rd; + return 0; +} + int ath10k_mac_register(struct ath10k *ar) { static const u32 cipher_suites[] = { @@ -8012,6 +8117,12 @@ int ath10k_mac_register(struct ath10k *ar) ar->running_fw->fw_file.fw_features)) ar->ops->wake_tx_queue = NULL; + ret = ath10k_mac_init_rd(ar); + if (ret) { + ath10k_err(ar, "failed to derive regdom: %d\n", ret); + goto err_dfs_detector_exit; + } + ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy, ath10k_reg_notifier); if (ret) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 4829513550a9..b4cfaf9aa0ac 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4676,7 +4676,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff); ar->phy_capability = __le32_to_cpu(arg.phy_capab); ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains); - ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd); + ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd); ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", arg.service_map, arg.service_map_len); -- cgit v1.2.3 From ebee76f7fa46851775942624fe6c7b80559a408a Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 28 Sep 2016 15:11:58 +0300 Subject: ath10k: allow setting coverage class Unfortunately ath10k does not generally allow modifying the coverage class with the stock firmware and Qualcomm has so far refused to implement this feature so that it can be properly supported in ath10k. If we however know the registers that need to be modified for proper operation with a higher coverage class, then we can do these modifications from the driver. This is a hack and might cause subtle problems but as it's not enabled by default (only when user space changes the coverage class explicitly) it should not cause new problems for existing setups. But still this should be considered as an experimental feature and used with caution. This patch implements the support for first generation cards (QCA9880, QCA9887 and so on) which are based on a core that is similar to ath9k. The registers are modified in place and need to be re-written every time the firmware sets them. To achieve this the register status is verified after certain WMI events from the firmware. The coverage class may not be modified temporarily right after the card re-initializes the registers. This is for example the case during scanning. Thanks to Sebastian Gottschall for initially working on a userspace support for this. This patch wouldn't have been possible without this documentation. Signed-off-by: Benjamin Berg Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 11 +++ drivers/net/wireless/ath/ath10k/core.h | 13 +++ drivers/net/wireless/ath/ath10k/debug.h | 22 +++++ drivers/net/wireless/ath/ath10k/hw.c | 142 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/hw.h | 28 ++++++- drivers/net/wireless/ath/ath10k/mac.c | 19 +++++ drivers/net/wireless/ath/ath10k/wmi.c | 48 +++++++++++ 7 files changed, 282 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 867a8403b15b..7005e2a98726 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1562,6 +1562,15 @@ static void ath10k_core_restart(struct work_struct *work) mutex_unlock(&ar->conf_mutex); } +static void ath10k_core_set_coverage_class_work(struct work_struct *work) +{ + struct ath10k *ar = container_of(work, struct ath10k, + set_coverage_class_work); + + if (ar->hw_params.hw_ops->set_coverage_class) + ar->hw_params.hw_ops->set_coverage_class(ar, -1); +} + static int ath10k_core_init_firmware_features(struct ath10k *ar) { struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file; @@ -2344,6 +2353,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, INIT_WORK(&ar->register_work, ath10k_core_register_work); INIT_WORK(&ar->restart_work, ath10k_core_restart); + INIT_WORK(&ar->set_coverage_class_work, + ath10k_core_set_coverage_class_work); init_dummy_netdev(&ar->napi_dev); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index c091306bca33..6e5aa2d09699 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -912,6 +912,19 @@ struct ath10k { struct net_device napi_dev; struct napi_struct napi; + struct work_struct set_coverage_class_work; + /* protected by conf_mutex */ + struct { + /* writing also protected by data_lock */ + s16 coverage_class; + + u32 reg_phyclk; + u32 reg_slottime_conf; + u32 reg_slottime_orig; + u32 reg_ack_cts_timeout_conf; + u32 reg_ack_cts_timeout_orig; + } fw_coverage; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index c458fa96a6d4..335512b11ca2 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -94,7 +94,19 @@ int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw, void ath10k_debug_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ethtool_stats *stats, u64 *data); + +static inline u64 ath10k_debug_get_fw_dbglog_mask(struct ath10k *ar) +{ + return ar->debug.fw_dbglog_mask; +} + +static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar) +{ + return ar->debug.fw_dbglog_level; +} + #else + static inline int ath10k_debug_start(struct ath10k *ar) { return 0; @@ -144,6 +156,16 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) return NULL; } +static inline u64 ath10k_debug_get_fw_dbglog_mask(struct ath10k *ar) +{ + return 0; +} + +static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar) +{ + return 0; +} + #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0) #define ath10k_debug_get_et_strings NULL diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 675e75d66db2..33fb26833cd0 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -17,11 +17,14 @@ #include #include "core.h" #include "hw.h" +#include "hif.h" +#include "wmi-ops.h" const struct ath10k_hw_regs qca988x_regs = { .rtc_soc_base_address = 0x00004000, .rtc_wmac_base_address = 0x00005000, .soc_core_base_address = 0x00009000, + .wlan_mac_base_address = 0x00020000, .ce_wrapper_base_address = 0x00057000, .ce0_base_address = 0x00057400, .ce1_base_address = 0x00057800, @@ -48,6 +51,7 @@ const struct ath10k_hw_regs qca6174_regs = { .rtc_soc_base_address = 0x00000800, .rtc_wmac_base_address = 0x00001000, .soc_core_base_address = 0x0003a000, + .wlan_mac_base_address = 0x00020000, .ce_wrapper_base_address = 0x00034000, .ce0_base_address = 0x00034400, .ce1_base_address = 0x00034800, @@ -74,6 +78,7 @@ const struct ath10k_hw_regs qca99x0_regs = { .rtc_soc_base_address = 0x00080000, .rtc_wmac_base_address = 0x00000000, .soc_core_base_address = 0x00082000, + .wlan_mac_base_address = 0x00030000, .ce_wrapper_base_address = 0x0004d000, .ce0_base_address = 0x0004a000, .ce1_base_address = 0x0004a400, @@ -109,6 +114,7 @@ const struct ath10k_hw_regs qca99x0_regs = { const struct ath10k_hw_regs qca4019_regs = { .rtc_soc_base_address = 0x00080000, .soc_core_base_address = 0x00082000, + .wlan_mac_base_address = 0x00030000, .ce_wrapper_base_address = 0x0004d000, .ce0_base_address = 0x0004a000, .ce1_base_address = 0x0004a400, @@ -220,7 +226,143 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, survey->time_busy = CCNT_TO_MSEC(ar, rcc); } +/* The firmware does not support setting the coverage class. Instead this + * function monitors and modifies the corresponding MAC registers. + */ +static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar, + s16 value) +{ + u32 slottime_reg; + u32 slottime; + u32 timeout_reg; + u32 ack_timeout; + u32 cts_timeout; + u32 phyclk_reg; + u32 phyclk; + u64 fw_dbglog_mask; + u32 fw_dbglog_level; + + mutex_lock(&ar->conf_mutex); + + /* Only modify registers if the core is started. */ + if ((ar->state != ATH10K_STATE_ON) && + (ar->state != ATH10K_STATE_RESTARTED)) + goto unlock; + + /* Retrieve the current values of the two registers that need to be + * adjusted. + */ + slottime_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS + + WAVE1_PCU_GBL_IFS_SLOT); + timeout_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS + + WAVE1_PCU_ACK_CTS_TIMEOUT); + phyclk_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS + + WAVE1_PHYCLK); + phyclk = MS(phyclk_reg, WAVE1_PHYCLK_USEC) + 1; + + if (value < 0) + value = ar->fw_coverage.coverage_class; + + /* Break out if the coverage class and registers have the expected + * value. + */ + if (value == ar->fw_coverage.coverage_class && + slottime_reg == ar->fw_coverage.reg_slottime_conf && + timeout_reg == ar->fw_coverage.reg_ack_cts_timeout_conf && + phyclk_reg == ar->fw_coverage.reg_phyclk) + goto unlock; + + /* Store new initial register values from the firmware. */ + if (slottime_reg != ar->fw_coverage.reg_slottime_conf) + ar->fw_coverage.reg_slottime_orig = slottime_reg; + if (timeout_reg != ar->fw_coverage.reg_ack_cts_timeout_conf) + ar->fw_coverage.reg_ack_cts_timeout_orig = timeout_reg; + ar->fw_coverage.reg_phyclk = phyclk_reg; + + /* Calculat new value based on the (original) firmware calculation. */ + slottime_reg = ar->fw_coverage.reg_slottime_orig; + timeout_reg = ar->fw_coverage.reg_ack_cts_timeout_orig; + + /* Do some sanity checks on the slottime register. */ + if (slottime_reg % phyclk) { + ath10k_warn(ar, + "failed to set coverage class: expected integer microsecond value in register\n"); + + goto store_regs; + } + + slottime = MS(slottime_reg, WAVE1_PCU_GBL_IFS_SLOT); + slottime = slottime / phyclk; + if (slottime != 9 && slottime != 20) { + ath10k_warn(ar, + "failed to set coverage class: expected slot time of 9 or 20us in HW register. It is %uus.\n", + slottime); + + goto store_regs; + } + + /* Recalculate the register values by adding the additional propagation + * delay (3us per coverage class). + */ + + slottime = MS(slottime_reg, WAVE1_PCU_GBL_IFS_SLOT); + slottime += value * 3 * phyclk; + slottime = min_t(u32, slottime, WAVE1_PCU_GBL_IFS_SLOT_MAX); + slottime = SM(slottime, WAVE1_PCU_GBL_IFS_SLOT); + slottime_reg = (slottime_reg & ~WAVE1_PCU_GBL_IFS_SLOT_MASK) | slottime; + + /* Update ack timeout (lower halfword). */ + ack_timeout = MS(timeout_reg, WAVE1_PCU_ACK_CTS_TIMEOUT_ACK); + ack_timeout += 3 * value * phyclk; + ack_timeout = min_t(u32, ack_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_MAX); + ack_timeout = SM(ack_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_ACK); + + /* Update cts timeout (upper halfword). */ + cts_timeout = MS(timeout_reg, WAVE1_PCU_ACK_CTS_TIMEOUT_CTS); + cts_timeout += 3 * value * phyclk; + cts_timeout = min_t(u32, cts_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_MAX); + cts_timeout = SM(cts_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_CTS); + + timeout_reg = ack_timeout | cts_timeout; + + ath10k_hif_write32(ar, + WLAN_MAC_BASE_ADDRESS + WAVE1_PCU_GBL_IFS_SLOT, + slottime_reg); + ath10k_hif_write32(ar, + WLAN_MAC_BASE_ADDRESS + WAVE1_PCU_ACK_CTS_TIMEOUT, + timeout_reg); + + /* Ensure we have a debug level of WARN set for the case that the + * coverage class is larger than 0. This is important as we need to + * set the registers again if the firmware does an internal reset and + * this way we will be notified of the event. + */ + fw_dbglog_mask = ath10k_debug_get_fw_dbglog_mask(ar); + fw_dbglog_level = ath10k_debug_get_fw_dbglog_level(ar); + + if (value > 0) { + if (fw_dbglog_level > ATH10K_DBGLOG_LEVEL_WARN) + fw_dbglog_level = ATH10K_DBGLOG_LEVEL_WARN; + fw_dbglog_mask = ~0; + } + + ath10k_wmi_dbglog_cfg(ar, fw_dbglog_mask, fw_dbglog_level); + +store_regs: + /* After an error we will not retry setting the coverage class. */ + spin_lock_bh(&ar->data_lock); + ar->fw_coverage.coverage_class = value; + spin_unlock_bh(&ar->data_lock); + + ar->fw_coverage.reg_slottime_conf = slottime_reg; + ar->fw_coverage.reg_ack_cts_timeout_conf = timeout_reg; + +unlock: + mutex_unlock(&ar->conf_mutex); +} + const struct ath10k_hw_ops qca988x_ops = { + .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, }; static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd) diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 6038b7486f1d..883547f3347c 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -230,6 +230,7 @@ struct ath10k_hw_regs { u32 rtc_soc_base_address; u32 rtc_wmac_base_address; u32 soc_core_base_address; + u32 wlan_mac_base_address; u32 ce_wrapper_base_address; u32 ce0_base_address; u32 ce1_base_address; @@ -418,6 +419,7 @@ struct htt_rx_desc; /* Defines needed for Rx descriptor abstraction */ struct ath10k_hw_ops { int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd); + void (*set_coverage_class)(struct ath10k *ar, s16 value); }; extern const struct ath10k_hw_ops qca988x_ops; @@ -614,7 +616,7 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, #define WLAN_SI_BASE_ADDRESS 0x00010000 #define WLAN_GPIO_BASE_ADDRESS 0x00014000 #define WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 -#define WLAN_MAC_BASE_ADDRESS 0x00020000 +#define WLAN_MAC_BASE_ADDRESS ar->regs->wlan_mac_base_address #define EFUSE_BASE_ADDRESS 0x00030000 #define FPGA_REG_BASE_ADDRESS 0x00039000 #define WLAN_UART2_BASE_ADDRESS 0x00054c00 @@ -814,4 +816,28 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, #define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB) +/* Register definitions for first generation ath10k cards. These cards include + * a mac thich has a register allocation similar to ath9k and at least some + * registers including the ones relevant for modifying the coverage class are + * identical to the ath9k definitions. + * These registers are usually managed by the ath10k firmware. However by + * overriding them it is possible to support coverage class modifications. + */ +#define WAVE1_PCU_ACK_CTS_TIMEOUT 0x8014 +#define WAVE1_PCU_ACK_CTS_TIMEOUT_MAX 0x00003FFF +#define WAVE1_PCU_ACK_CTS_TIMEOUT_ACK_MASK 0x00003FFF +#define WAVE1_PCU_ACK_CTS_TIMEOUT_ACK_LSB 0 +#define WAVE1_PCU_ACK_CTS_TIMEOUT_CTS_MASK 0x3FFF0000 +#define WAVE1_PCU_ACK_CTS_TIMEOUT_CTS_LSB 16 + +#define WAVE1_PCU_GBL_IFS_SLOT 0x1070 +#define WAVE1_PCU_GBL_IFS_SLOT_MASK 0x0000FFFF +#define WAVE1_PCU_GBL_IFS_SLOT_MAX 0x0000FFFF +#define WAVE1_PCU_GBL_IFS_SLOT_LSB 0 +#define WAVE1_PCU_GBL_IFS_SLOT_RESV0 0xFFFF0000 + +#define WAVE1_PHYCLK 0x801C +#define WAVE1_PHYCLK_USEC_MASK 0x0000007F +#define WAVE1_PHYCLK_USEC_LSB 0 + #endif /* _HW_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ed71b95a661d..2e5d2ca6d816 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -5412,6 +5412,20 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&ar->conf_mutex); } +static void ath10k_mac_op_set_coverage_class(struct ieee80211_hw *hw, s16 value) +{ + struct ath10k *ar = hw->priv; + + /* This function should never be called if setting the coverage class + * is not supported on this hardware. + */ + if (!ar->hw_params.hw_ops->set_coverage_class) { + WARN_ON_ONCE(1); + return; + } + ar->hw_params.hw_ops->set_coverage_class(ar, value); +} + static int ath10k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) @@ -7437,6 +7451,7 @@ static const struct ieee80211_ops ath10k_ops = { .remove_interface = ath10k_remove_interface, .configure_filter = ath10k_configure_filter, .bss_info_changed = ath10k_bss_info_changed, + .set_coverage_class = ath10k_mac_op_set_coverage_class, .hw_scan = ath10k_hw_scan, .cancel_hw_scan = ath10k_cancel_hw_scan, .set_key = ath10k_set_key, @@ -8123,6 +8138,10 @@ int ath10k_mac_register(struct ath10k *ar) goto err_dfs_detector_exit; } + /* Disable set_coverage_class for chipsets that do not support it. */ + if (!ar->hw_params.hw_ops->set_coverage_class) + ar->ops->set_coverage_class = NULL; + ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy, ath10k_reg_notifier); if (ret) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index b4cfaf9aa0ac..387c4eede388 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4931,6 +4931,23 @@ exit: return 0; } +static inline void ath10k_wmi_queue_set_coverage_class_work(struct ath10k *ar) +{ + if (ar->hw_params.hw_ops->set_coverage_class) { + spin_lock_bh(&ar->data_lock); + + /* This call only ensures that the modified coverage class + * persists in case the firmware sets the registers back to + * their default value. So calling it is only necessary if the + * coverage class has a non-zero value. + */ + if (ar->fw_coverage.coverage_class) + queue_work(ar->workqueue, &ar->set_coverage_class_work); + + spin_unlock_bh(&ar->data_lock); + } +} + static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; @@ -4951,6 +4968,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) return; case WMI_SCAN_EVENTID: ath10k_wmi_event_scan(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_CHAN_INFO_EVENTID: ath10k_wmi_event_chan_info(ar, skb); @@ -4960,15 +4978,18 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_DEBUG_MESG_EVENTID: ath10k_wmi_event_debug_mesg(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_UPDATE_STATS_EVENTID: ath10k_wmi_event_update_stats(ar, skb); break; case WMI_VDEV_START_RESP_EVENTID: ath10k_wmi_event_vdev_start_resp(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_VDEV_STOPPED_EVENTID: ath10k_wmi_event_vdev_stopped(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_PEER_STA_KICKOUT_EVENTID: ath10k_wmi_event_peer_sta_kickout(ar, skb); @@ -4984,12 +5005,14 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_ROAM_EVENTID: ath10k_wmi_event_roam(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_PROFILE_MATCH: ath10k_wmi_event_profile_match(ar, skb); break; case WMI_DEBUG_PRINT_EVENTID: ath10k_wmi_event_debug_print(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_PDEV_QVIT_EVENTID: ath10k_wmi_event_pdev_qvit(ar, skb); @@ -5038,6 +5061,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) return; case WMI_READY_EVENTID: ath10k_wmi_event_ready(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; default: ath10k_warn(ar, "Unknown eventid: %d\n", id); @@ -5081,6 +5105,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb) return; case WMI_10X_SCAN_EVENTID: ath10k_wmi_event_scan(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10X_CHAN_INFO_EVENTID: ath10k_wmi_event_chan_info(ar, skb); @@ -5090,15 +5115,18 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_10X_DEBUG_MESG_EVENTID: ath10k_wmi_event_debug_mesg(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10X_UPDATE_STATS_EVENTID: ath10k_wmi_event_update_stats(ar, skb); break; case WMI_10X_VDEV_START_RESP_EVENTID: ath10k_wmi_event_vdev_start_resp(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10X_VDEV_STOPPED_EVENTID: ath10k_wmi_event_vdev_stopped(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10X_PEER_STA_KICKOUT_EVENTID: ath10k_wmi_event_peer_sta_kickout(ar, skb); @@ -5114,12 +5142,14 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_10X_ROAM_EVENTID: ath10k_wmi_event_roam(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10X_PROFILE_MATCH: ath10k_wmi_event_profile_match(ar, skb); break; case WMI_10X_DEBUG_PRINT_EVENTID: ath10k_wmi_event_debug_print(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10X_PDEV_QVIT_EVENTID: ath10k_wmi_event_pdev_qvit(ar, skb); @@ -5159,6 +5189,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb) return; case WMI_10X_READY_EVENTID: ath10k_wmi_event_ready(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10X_PDEV_UTF_EVENTID: /* ignore utf events */ @@ -5205,6 +5236,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) return; case WMI_10_2_SCAN_EVENTID: ath10k_wmi_event_scan(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_CHAN_INFO_EVENTID: ath10k_wmi_event_chan_info(ar, skb); @@ -5214,15 +5246,18 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_10_2_DEBUG_MESG_EVENTID: ath10k_wmi_event_debug_mesg(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_UPDATE_STATS_EVENTID: ath10k_wmi_event_update_stats(ar, skb); break; case WMI_10_2_VDEV_START_RESP_EVENTID: ath10k_wmi_event_vdev_start_resp(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_VDEV_STOPPED_EVENTID: ath10k_wmi_event_vdev_stopped(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_PEER_STA_KICKOUT_EVENTID: ath10k_wmi_event_peer_sta_kickout(ar, skb); @@ -5238,12 +5273,14 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_10_2_ROAM_EVENTID: ath10k_wmi_event_roam(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_PROFILE_MATCH: ath10k_wmi_event_profile_match(ar, skb); break; case WMI_10_2_DEBUG_PRINT_EVENTID: ath10k_wmi_event_debug_print(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_PDEV_QVIT_EVENTID: ath10k_wmi_event_pdev_qvit(ar, skb); @@ -5274,15 +5311,18 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_10_2_VDEV_STANDBY_REQ_EVENTID: ath10k_wmi_event_vdev_standby_req(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_VDEV_RESUME_REQ_EVENTID: ath10k_wmi_event_vdev_resume_req(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_SERVICE_READY_EVENTID: ath10k_wmi_event_service_ready(ar, skb); return; case WMI_10_2_READY_EVENTID: ath10k_wmi_event_ready(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_2_PDEV_TEMPERATURE_EVENTID: ath10k_wmi_event_temperature(ar, skb); @@ -5345,12 +5385,14 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_10_4_DEBUG_MESG_EVENTID: ath10k_wmi_event_debug_mesg(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_4_SERVICE_READY_EVENTID: ath10k_wmi_event_service_ready(ar, skb); return; case WMI_10_4_SCAN_EVENTID: ath10k_wmi_event_scan(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_4_CHAN_INFO_EVENTID: ath10k_wmi_event_chan_info(ar, skb); @@ -5360,12 +5402,14 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_10_4_READY_EVENTID: ath10k_wmi_event_ready(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_4_PEER_STA_KICKOUT_EVENTID: ath10k_wmi_event_peer_sta_kickout(ar, skb); break; case WMI_10_4_ROAM_EVENTID: ath10k_wmi_event_roam(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_4_HOST_SWBA_EVENTID: ath10k_wmi_event_host_swba(ar, skb); @@ -5375,12 +5419,15 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) break; case WMI_10_4_DEBUG_PRINT_EVENTID: ath10k_wmi_event_debug_print(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_4_VDEV_START_RESP_EVENTID: ath10k_wmi_event_vdev_start_resp(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_4_VDEV_STOPPED_EVENTID: ath10k_wmi_event_vdev_stopped(ar, skb); + ath10k_wmi_queue_set_coverage_class_work(ar); break; case WMI_10_4_WOW_WAKEUP_HOST_EVENTID: case WMI_10_4_PEER_RATECODE_LIST_EVENTID: @@ -6099,6 +6146,7 @@ void ath10k_wmi_start_scan_init(struct ath10k *ar, | WMI_SCAN_EVENT_COMPLETED | WMI_SCAN_EVENT_BSS_CHANNEL | WMI_SCAN_EVENT_FOREIGN_CHANNEL + | WMI_SCAN_EVENT_FOREIGN_CHANNEL_EXIT | WMI_SCAN_EVENT_DEQUEUED; arg->scan_ctrl_flags |= WMI_SCAN_CHAN_STAT_EVENT; arg->n_bssids = 1; -- cgit v1.2.3 From 62ae14b1edca0aaf27b84b3fa069177dd794e37f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 4 Oct 2016 21:11:25 +0100 Subject: drm/i915: Share the computation of ring size for RING_CTL register Since both legacy and execlists want to populate the RING_CTL register, share the computation of the right bits for the ring->size. We can then stop masking errors and explicitly forbid them during creation! Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161004201132.21801-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_lrc.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 5 ++--- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8d44cee710f0..acc767a52d8e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1605,6 +1605,7 @@ enum skl_disp_power_wells { #define RING_HEAD(base) _MMIO((base)+0x34) #define RING_START(base) _MMIO((base)+0x38) #define RING_CTL(base) _MMIO((base)+0x3c) +#define RING_CTL_SIZE(size) ((size) - PAGE_SIZE) /* in bytes -> pages */ #define RING_SYNC_0(base) _MMIO((base)+0x40) #define RING_SYNC_1(base) _MMIO((base)+0x44) #define RING_SYNC_2(base) _MMIO((base)+0x48) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 2d8eb2eb2b72..5ede272eb4d2 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1946,7 +1946,7 @@ populate_lr_context(struct i915_gem_context *ctx, RING_START(engine->mmio_base), 0); ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, RING_CTL(engine->mmio_base), - ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); + RING_CTL_SIZE(ring->size) | RING_VALID); ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, RING_BBADDR_UDW(engine->mmio_base), 0); ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 67ea9dd5921e..8206e2aa03c6 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -585,9 +585,7 @@ static int init_ring_common(struct intel_engine_cs *engine) I915_WRITE_TAIL(engine, ring->tail); (void)I915_READ_TAIL(engine); - I915_WRITE_CTL(engine, - ((ring->size - PAGE_SIZE) & RING_NR_PAGES) - | RING_VALID); + I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID); /* If the head is still not zero, the ring is dead */ if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base), @@ -1951,6 +1949,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size) struct i915_vma *vma; GEM_BUG_ON(!is_power_of_2(size)); + GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES); ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) -- cgit v1.2.3 From a3aabe86a3406b9946a4f7707762a833a58dfe9c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 4 Oct 2016 21:11:26 +0100 Subject: drm/i915/execlists: Reinitialise context image after GPU hang On Braswell, at least, we observe that the context image is written in multiple phases. The first phase is to clear the register state, and subsequently rewrite it. A GPU reset at the right moment can interrupt the context update leaving it corrupt, and our update of the RING_HEAD is not sufficient to restart the engine afterwards. To recover, we need to reset the registers back to their original values. The context state is lost. What we need is a better mechanism to serialise the reset with pending flushes from the GPU. Fixes: 821ed7df6e2a ("drm/i915: Update reset path to fix incomplete requests") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161004201132.21801-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 103 +++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 5ede272eb4d2..0ea992ba2723 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -226,10 +226,16 @@ enum { /* Typical size of the average request (2 pipecontrols and a MI_BB) */ #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ +#define WA_TAIL_DWORDS 2 + static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, struct intel_engine_cs *engine); static int intel_lr_context_pin(struct i915_gem_context *ctx, struct intel_engine_cs *engine); +static void execlists_init_reg_state(u32 *reg_state, + struct i915_gem_context *ctx, + struct intel_engine_cs *engine, + struct intel_ring *ring); /** * intel_sanitize_enable_execlists() - sanitize i915.enable_execlists @@ -707,7 +713,6 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx, { struct intel_context *ce = &ctx->engine[engine->id]; void *vaddr; - u32 *lrc_reg_state; int ret; lockdep_assert_held(&ctx->i915->drm.struct_mutex); @@ -726,17 +731,16 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx, goto unpin_vma; } - lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; - ret = intel_ring_pin(ce->ring); if (ret) goto unpin_map; intel_lr_context_descriptor_update(ctx, engine); - lrc_reg_state[CTX_RING_BUFFER_START+1] = + ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; + ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = i915_ggtt_offset(ce->ring->vma); - ce->lrc_reg_state = lrc_reg_state; + ce->state->obj->dirty = true; /* Invalidate GuC TLB. */ @@ -1284,8 +1288,21 @@ static void reset_common_ring(struct intel_engine_cs *engine, struct execlist_port *port = engine->execlist_port; struct intel_context *ce = &request->ctx->engine[engine->id]; + /* We want a simple context + ring to execute the breadcrumb update. + * We cannot rely on the context being intact across the GPU hang, + * so clear it and rebuild just what we need for the breadcrumb. + * All pending requests for this context will be zapped, and any + * future request will be after userspace has had the opportunity + * to recreate its own state. + */ + execlists_init_reg_state(ce->lrc_reg_state, + request->ctx, engine, ce->ring); + /* Move the RING_HEAD onto the breadcrumb, past the hanging batch */ + ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = + i915_ggtt_offset(ce->ring->vma); ce->lrc_reg_state[CTX_RING_HEAD+1] = request->postfix; + request->ring->head = request->postfix; request->ring->last_retired_head = -1; intel_ring_update_space(request->ring); @@ -1305,6 +1322,9 @@ static void reset_common_ring(struct intel_engine_cs *engine, GEM_BUG_ON(request->ctx != port[0].request->ctx); port[0].count = 0; port[1].count = 0; + + /* Reset WaIdleLiteRestore:bdw,skl as well */ + request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32); } static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) @@ -1542,7 +1562,6 @@ static void bxt_a_seqno_barrier(struct intel_engine_cs *engine) * used as a workaround for not being allowed to do lite * restore with HEAD==TAIL (WaIdleLiteRestore). */ -#define WA_TAIL_DWORDS 2 static int gen8_emit_request(struct drm_i915_gem_request *request) { @@ -1889,38 +1908,13 @@ static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *engine) return indirect_ctx_offset; } -static int -populate_lr_context(struct i915_gem_context *ctx, - struct drm_i915_gem_object *ctx_obj, - struct intel_engine_cs *engine, - struct intel_ring *ring) +static void execlists_init_reg_state(u32 *reg_state, + struct i915_gem_context *ctx, + struct intel_engine_cs *engine, + struct intel_ring *ring) { - struct drm_i915_private *dev_priv = ctx->i915; - struct i915_hw_ppgtt *ppgtt = ctx->ppgtt; - void *vaddr; - u32 *reg_state; - int ret; - - if (!ppgtt) - ppgtt = dev_priv->mm.aliasing_ppgtt; - - ret = i915_gem_object_set_to_cpu_domain(ctx_obj, true); - if (ret) { - DRM_DEBUG_DRIVER("Could not set to CPU domain\n"); - return ret; - } - - vaddr = i915_gem_object_pin_map(ctx_obj, I915_MAP_WB); - if (IS_ERR(vaddr)) { - ret = PTR_ERR(vaddr); - DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret); - return ret; - } - ctx_obj->dirty = true; - - /* The second page of the context object contains some fields which must - * be set up prior to the first execution. */ - reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; + struct drm_i915_private *dev_priv = engine->i915; + struct i915_hw_ppgtt *ppgtt = ctx->ppgtt ?: dev_priv->mm.aliasing_ppgtt; /* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM * commands followed by (reg, value) pairs. The values we are setting here are @@ -1934,14 +1928,11 @@ populate_lr_context(struct i915_gem_context *ctx, _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH | CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | (HAS_RESOURCE_STREAMER(dev_priv) ? - CTX_CTRL_RS_CTX_ENABLE : 0))); + CTX_CTRL_RS_CTX_ENABLE : 0))); ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(engine->mmio_base), 0); ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(engine->mmio_base), 0); - /* Ring buffer start address is not known until the buffer is pinned. - * It is written to the context image in execlists_update_context() - */ ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, RING_START(engine->mmio_base), 0); ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, @@ -2024,6 +2015,36 @@ populate_lr_context(struct i915_gem_context *ctx, ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE, make_rpcs(dev_priv)); } +} + +static int +populate_lr_context(struct i915_gem_context *ctx, + struct drm_i915_gem_object *ctx_obj, + struct intel_engine_cs *engine, + struct intel_ring *ring) +{ + void *vaddr; + int ret; + + ret = i915_gem_object_set_to_cpu_domain(ctx_obj, true); + if (ret) { + DRM_DEBUG_DRIVER("Could not set to CPU domain\n"); + return ret; + } + + vaddr = i915_gem_object_pin_map(ctx_obj, I915_MAP_WB); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret); + return ret; + } + ctx_obj->dirty = true; + + /* The second page of the context object contains some fields which must + * be set up prior to the first execution. */ + + execlists_init_reg_state(vaddr + LRC_STATE_PN * PAGE_SIZE, + ctx, engine, ring); i915_gem_object_unpin_map(ctx_obj); -- cgit v1.2.3 From c87d50cc9fcc634e09d239e6d10293319eafae5f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 4 Oct 2016 21:11:27 +0100 Subject: drm/i915/execlists: Move clearing submission count from reset to init After a GPU reset, we want to replay our queue of requests. However, the GPU reset clobbered the state and we only fixup the state for the guilty request - and engines deemed innocent we try to leave untouched so that we recover as completely as possible. However, we need to clear the sw tracking of the ELSP ports even for innocent requests, so move the clear to the common path of init_hw (from reset_hw). Reported-by: Mika Kuoppala Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161004201132.21801-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 0ea992ba2723..936f6f63f626 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1242,8 +1242,12 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) intel_engine_init_hangcheck(engine); - if (!execlists_elsp_idle(engine)) + /* After a GPU reset, we may have requests to replay */ + if (!execlists_elsp_idle(engine)) { + engine->execlist_port[0].count = 0; + engine->execlist_port[1].count = 0; execlists_submit_ports(engine); + } return 0; } @@ -1318,10 +1322,7 @@ static void reset_common_ring(struct intel_engine_cs *engine, memset(&port[1], 0, sizeof(port[1])); } - /* CS is stopped, and we will resubmit both ports on resume */ GEM_BUG_ON(request->ctx != port[0].request->ctx); - port[0].count = 0; - port[1].count = 0; /* Reset WaIdleLiteRestore:bdw,skl as well */ request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32); -- cgit v1.2.3 From 9e60ab0387817c6a9440f448aff7c8514b32d31b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 4 Oct 2016 21:11:28 +0100 Subject: drm/i915: Disable irqs across GPU reset Whilst we reset the GPU, we want to prevent execlists from submitting new work (which it does via an interrupt handler). To achieve this we disable the irq (and drain the irq tasklet) around the reset. When we enable it again afters, the interrupt queue should be empty and we can reinitialise from a known state without fear of the tasklet running concurrently. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161004201132.21801-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 19 +++++++++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 2 -- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9c1543240e27..89d322215c84 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1728,6 +1728,21 @@ int i915_resume_switcheroo(struct drm_device *dev) return i915_drm_resume(dev); } +static void disable_engines_irq(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *engine; + + /* Ensure irq handler finishes, and not run again. */ + disable_irq(dev_priv->drm.irq); + for_each_engine(engine, dev_priv) + tasklet_kill(&engine->irq_tasklet); +} + +static void enable_engines_irq(struct drm_i915_private *dev_priv) +{ + enable_irq(dev_priv->drm.irq); +} + /** * i915_reset - reset chip after a hang * @dev: drm device to reset @@ -1761,7 +1776,11 @@ void i915_reset(struct drm_i915_private *dev_priv) error->reset_count++; pr_notice("drm/i915: Resetting chip after gpu hang\n"); + + disable_engines_irq(dev_priv); ret = intel_gpu_reset(dev_priv, ALL_ENGINES); + enable_engines_irq(dev_priv); + if (ret) { if (ret != -ENODEV) DRM_ERROR("Failed to reset chip: %i\n", ret); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1418c1c522cb..0cae8acdf906 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2581,8 +2581,6 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) struct i915_gem_context *incomplete_ctx; bool ring_hung; - /* Ensure irq handler finishes, and not run again. */ - tasklet_kill(&engine->irq_tasklet); if (engine->irq_seqno_barrier) engine->irq_seqno_barrier(engine); -- cgit v1.2.3 From 77c607013e208ed212845ce2565f24145393fee1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 4 Oct 2016 21:11:29 +0100 Subject: drm/i915: Double check hangcheck.seqno after reset Check that there was not a late recovery between us declaring the GPU hung and processing the reset. If the GPU did recover by itself, let the request remain on the active list and see if it hangs again! Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161004201132.21801-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0cae8acdf906..a89a88922448 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2589,6 +2589,9 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) return; ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG; + if (engine->hangcheck.seqno != intel_engine_get_seqno(engine)) + ring_hung = false; + i915_set_reset_status(request->ctx, ring_hung); if (!ring_hung) return; -- cgit v1.2.3 From cdb324bde5700725f04172bbeb6ef0bbbb6886c3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 4 Oct 2016 21:11:30 +0100 Subject: drm/i915: Show bounds of active request in the ring on GPU hang Include the position of the active request in the ring, and display that alongside the current RING registers (on a GPU hang). Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161004201132.21801-6-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/i915_gpu_error.c | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f8c66eea06bc..4613f031d127 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -788,6 +788,9 @@ struct drm_i915_error_state { struct i915_address_space *vm; int num_requests; + /* position of active request inside the ring */ + u32 rq_head, rq_post, rq_tail; + /* our own tracking of ring head and tail */ u32 cpu_ring_head; u32 cpu_ring_tail; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 2bbab226a46c..8b85efbdfa04 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -262,8 +262,9 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, { err_printf(m, "%s command stream:\n", engine_str(ee->engine_id)); err_printf(m, " START: 0x%08x\n", ee->start); - err_printf(m, " HEAD: 0x%08x\n", ee->head); - err_printf(m, " TAIL: 0x%08x\n", ee->tail); + err_printf(m, " HEAD: 0x%08x\n [0x%08x]", ee->head, ee->rq_head); + err_printf(m, " TAIL: 0x%08x [0x%08x, 0x%08x]\n", + ee->tail, ee->rq_post, ee->rq_tail); err_printf(m, " CTL: 0x%08x\n", ee->ctl); err_printf(m, " MODE: 0x%08x\n", ee->mode); err_printf(m, " HWS: 0x%08x\n", ee->hws); @@ -1230,6 +1231,10 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv, error->simulated |= request->ctx->flags & CONTEXT_NO_ERROR_CAPTURE; + ee->rq_head = request->head; + ee->rq_post = request->postfix; + ee->rq_tail = request->tail; + ring = request->ring; ee->cpu_ring_head = ring->head; ee->cpu_ring_tail = ring->tail; -- cgit v1.2.3 From 1b36595ffb350c8bec5be8894c5a43f0581864c0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 4 Oct 2016 21:11:31 +0100 Subject: drm/i915: Show RING registers through debugfs Knowing where the RINGs are pointing is extremely useful in diagnosing if the engines are executing the ringbuffers you expect - and igt may be suppressing the usual method of looking in the GPU error state. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161004201132.21801-7-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 239 ++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_engine_cs.c | 30 ++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 16 --- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 4 files changed, 179 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index eb91444707d2..fe2bc485565b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -645,6 +645,23 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) return 0; } +static void print_request(struct seq_file *m, + struct drm_i915_gem_request *rq, + const char *prefix) +{ + struct pid *pid = rq->ctx->pid; + struct task_struct *task; + + rcu_read_lock(); + task = pid ? pid_task(pid, PIDTYPE_PID) : NULL; + seq_printf(m, "%s%x [%x:%x] @ %d: %s [%d]\n", prefix, + rq->fence.seqno, rq->ctx->hw_id, rq->fence.seqno, + jiffies_to_msecs(jiffies - rq->emitted_jiffies), + task ? task->comm : "", + task ? task->pid : -1); + rcu_read_unlock(); +} + static int i915_gem_request_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -668,19 +685,8 @@ static int i915_gem_request_info(struct seq_file *m, void *data) continue; seq_printf(m, "%s requests: %d\n", engine->name, count); - list_for_each_entry(req, &engine->request_list, link) { - struct pid *pid = req->ctx->pid; - struct task_struct *task; - - rcu_read_lock(); - task = pid ? pid_task(pid, PIDTYPE_PID) : NULL; - seq_printf(m, " %x @ %d: %s [%d]\n", - req->fence.seqno, - (int) (jiffies - req->emitted_jiffies), - task ? task->comm : "", - task ? task->pid : -1); - rcu_read_unlock(); - } + list_for_each_entry(req, &engine->request_list, link) + print_request(m, req, " "); any++; } @@ -2046,84 +2052,6 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) return 0; } -static int i915_execlists(struct seq_file *m, void *data) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct intel_engine_cs *engine; - u32 status_pointer; - u8 read_pointer; - u8 write_pointer; - u32 status; - u32 ctx_id; - struct list_head *cursor; - int i, ret; - - if (!i915.enable_execlists) { - seq_puts(m, "Logical Ring Contexts are disabled\n"); - return 0; - } - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - - intel_runtime_pm_get(dev_priv); - - for_each_engine(engine, dev_priv) { - struct drm_i915_gem_request *head_req = NULL; - int count = 0; - - seq_printf(m, "%s\n", engine->name); - - status = I915_READ(RING_EXECLIST_STATUS_LO(engine)); - ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(engine)); - seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n", - status, ctx_id); - - status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); - seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer); - - read_pointer = GEN8_CSB_READ_PTR(status_pointer); - write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); - if (read_pointer > write_pointer) - write_pointer += GEN8_CSB_ENTRIES; - seq_printf(m, "\tRead pointer: 0x%08X, write pointer 0x%08X\n", - read_pointer, write_pointer); - - for (i = 0; i < GEN8_CSB_ENTRIES; i++) { - status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, i)); - ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, i)); - - seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n", - i, status, ctx_id); - } - - spin_lock_bh(&engine->execlist_lock); - list_for_each(cursor, &engine->execlist_queue) - count++; - head_req = list_first_entry_or_null(&engine->execlist_queue, - struct drm_i915_gem_request, - execlist_link); - spin_unlock_bh(&engine->execlist_lock); - - seq_printf(m, "\t%d requests in queue\n", count); - if (head_req) { - seq_printf(m, "\tHead request context: %u\n", - head_req->ctx->hw_id); - seq_printf(m, "\tHead request tail: %u\n", - head_req->tail); - } - - seq_putc(m, '\n'); - } - - intel_runtime_pm_put(dev_priv); - mutex_unlock(&dev->struct_mutex); - - return 0; -} - static const char *swizzle_string(unsigned swizzle) { switch (swizzle) { @@ -3136,6 +3064,133 @@ static int i915_display_info(struct seq_file *m, void *unused) return 0; } +static int i915_engine_info(struct seq_file *m, void *unused) +{ + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct intel_engine_cs *engine; + + for_each_engine(engine, dev_priv) { + struct intel_breadcrumbs *b = &engine->breadcrumbs; + struct drm_i915_gem_request *rq; + struct rb_node *rb; + u64 addr; + + seq_printf(m, "%s\n", engine->name); + seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [score %d]\n", + intel_engine_get_seqno(engine), + engine->last_submitted_seqno, + engine->hangcheck.seqno, + engine->hangcheck.score); + + rcu_read_lock(); + + seq_printf(m, "\tRequests:\n"); + + rq = list_first_entry(&engine->request_list, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->request_list) + print_request(m, rq, "\t\tfirst "); + + rq = list_last_entry(&engine->request_list, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->request_list) + print_request(m, rq, "\t\tlast "); + + rq = i915_gem_find_active_request(engine); + if (rq) { + print_request(m, rq, "\t\tactive "); + seq_printf(m, + "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n", + rq->head, rq->postfix, rq->tail, + rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, + rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); + } + + seq_printf(m, "\tRING_START: 0x%08x [0x%08x]\n", + I915_READ(RING_START(engine->mmio_base)), + rq ? i915_ggtt_offset(rq->ring->vma) : 0); + seq_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n", + I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR, + rq ? rq->ring->head : 0); + seq_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n", + I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR, + rq ? rq->ring->tail : 0); + seq_printf(m, "\tRING_CTL: 0x%08x [%s]\n", + I915_READ(RING_CTL(engine->mmio_base)), + I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : ""); + + rcu_read_unlock(); + + addr = intel_engine_get_active_head(engine); + seq_printf(m, "\tACTHD: 0x%08x_%08x\n", + upper_32_bits(addr), lower_32_bits(addr)); + addr = intel_engine_get_last_batch_head(engine); + seq_printf(m, "\tBBADDR: 0x%08x_%08x\n", + upper_32_bits(addr), lower_32_bits(addr)); + + if (i915.enable_execlists) { + u32 ptr, read, write; + + seq_printf(m, "\tExeclist status: 0x%08x %08x\n", + I915_READ(RING_EXECLIST_STATUS_LO(engine)), + I915_READ(RING_EXECLIST_STATUS_HI(engine))); + + ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); + read = GEN8_CSB_READ_PTR(ptr); + write = GEN8_CSB_WRITE_PTR(ptr); + seq_printf(m, "\tExeclist CSB read %d, write %d\n", + read, write); + if (read >= GEN8_CSB_ENTRIES) + read = 0; + if (write >= GEN8_CSB_ENTRIES) + write = 0; + if (read > write) + write += GEN8_CSB_ENTRIES; + while (read < write) { + unsigned int idx = ++read % GEN8_CSB_ENTRIES; + + seq_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n", + idx, + I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)), + I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx))); + } + + rcu_read_lock(); + rq = READ_ONCE(engine->execlist_port[0].request); + if (rq) + print_request(m, rq, "\t\tELSP[0] "); + else + seq_printf(m, "\t\tELSP[0] idle\n"); + rq = READ_ONCE(engine->execlist_port[1].request); + if (rq) + print_request(m, rq, "\t\tELSP[1] "); + else + seq_printf(m, "\t\tELSP[1] idle\n"); + rcu_read_unlock(); + } else if (INTEL_GEN(dev_priv) > 6) { + seq_printf(m, "\tPP_DIR_BASE: 0x%08x\n", + I915_READ(RING_PP_DIR_BASE(engine))); + seq_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n", + I915_READ(RING_PP_DIR_BASE_READ(engine))); + seq_printf(m, "\tPP_DIR_DCLV: 0x%08x\n", + I915_READ(RING_PP_DIR_DCLV(engine))); + } + + spin_lock(&b->lock); + for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { + struct intel_wait *w = container_of(rb, typeof(*w), node); + + seq_printf(m, "\t%s [%d] waiting for %x\n", + w->tsk->comm, w->tsk->pid, w->seqno); + } + spin_unlock(&b->lock); + + seq_puts(m, "\n"); + } + + return 0; +} + static int i915_semaphore_status(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -5290,7 +5345,6 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, {"i915_context_status", i915_context_status, 0}, {"i915_dump_lrc", i915_dump_lrc, 0}, - {"i915_execlists", i915_execlists, 0}, {"i915_forcewake_domains", i915_forcewake_domains, 0}, {"i915_swizzle_info", i915_swizzle_info, 0}, {"i915_ppgtt_info", i915_ppgtt_info, 0}, @@ -5302,6 +5356,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_power_domain_info", i915_power_domain_info, 0}, {"i915_dmc_info", i915_dmc_info, 0}, {"i915_display_info", i915_display_info, 0}, + {"i915_engine_info", i915_engine_info, 0}, {"i915_semaphore_status", i915_semaphore_status, 0}, {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, {"i915_dp_mst_info", i915_dp_mst_info, 0}, diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index e405f1080296..d00ec805f93d 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -334,3 +334,33 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) intel_engine_cleanup_cmd_parser(engine); i915_gem_batch_pool_fini(&engine->batch_pool); } + +u64 intel_engine_get_active_head(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + u64 acthd; + + if (INTEL_GEN(dev_priv) >= 8) + acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), + RING_ACTHD_UDW(engine->mmio_base)); + else if (INTEL_GEN(dev_priv) >= 4) + acthd = I915_READ(RING_ACTHD(engine->mmio_base)); + else + acthd = I915_READ(ACTHD); + + return acthd; +} + +u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + u64 bbaddr; + + if (INTEL_GEN(dev_priv) >= 8) + bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base), + RING_BBADDR_UDW(engine->mmio_base)); + else + bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); + + return bbaddr; +} diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8206e2aa03c6..35f359e38f4d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -405,22 +405,6 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) return gen8_emit_pipe_control(req, flags, scratch_addr); } -u64 intel_engine_get_active_head(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - u64 acthd; - - if (INTEL_GEN(dev_priv) >= 8) - acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), - RING_ACTHD_UDW(engine->mmio_base)); - else if (INTEL_GEN(dev_priv) >= 4) - acthd = I915_READ(RING_ACTHD(engine->mmio_base)); - else - acthd = I915_READ(ACTHD); - - return acthd; -} - static void ring_setup_phys_status_page(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 66553bdb0a47..498931f0b1f1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -541,6 +541,8 @@ int intel_init_blt_ring_buffer(struct intel_engine_cs *engine); int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine); u64 intel_engine_get_active_head(struct intel_engine_cs *engine); +u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine); + static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) { return intel_read_status_page(engine, I915_GEM_HWS_INDEX); -- cgit v1.2.3 From 33f53719d13a61979ca6578b280ed247eb81cdd4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 4 Oct 2016 21:11:32 +0100 Subject: drm/i915: Show waiters in i915_hangcheck_info It is convenient to know what processes are waiting when looking at hangcheck status in debugfs. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161004201132.21801-8-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index fe2bc485565b..98f536d94797 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1353,6 +1353,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seq_printf(m, "Hangcheck inactive\n"); for_each_engine_id(engine, dev_priv, id) { + struct intel_breadcrumbs *b = &engine->breadcrumbs; + struct rb_node *rb; + seq_printf(m, "%s:\n", engine->name); seq_printf(m, "\tseqno = %x [current %x, last %x]\n", engine->hangcheck.seqno, @@ -1362,6 +1365,15 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) yesno(intel_engine_has_waiter(engine)), yesno(test_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings))); + spin_lock(&b->lock); + for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { + struct intel_wait *w = container_of(rb, typeof(*w), node); + + seq_printf(m, "\t%s [%d] waiting for %x\n", + w->tsk->comm, w->tsk->pid, w->seqno); + } + spin_unlock(&b->lock); + seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n", (long long)engine->hangcheck.acthd, (long long)acthd[id]); -- cgit v1.2.3 From 27d4efc5591a5853de54713bc717de73c8951e17 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 3 Oct 2016 10:55:15 +0300 Subject: drm/i915: Move long hpd handling into the hotplug work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can't rely on connector->status in the detect() hook if the long hpd was already handled by the dig_port_work as that won't update connector->status. Thus we have to defer the long hpd handling entirely until the hotplug work runs to avoid the double long hpd handling the "detect_done" flag is trying to prevent. We'll start to depend on connector->status being up to date in a following patch. Cc: Damien Cassou Cc: freedesktop.org@gp.mailgun.org Cc: Arno Cc: Shubhangi Shrivastava Cc: Sivakumar Thulasimani Cc: Ander Conselvan de Oliveira Cc: stable@vger.kernel.org Tested-by: Arno Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=83348 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1475481316-8194-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Ander Conselvan de Oliveira --- drivers/gpu/drm/i915/intel_dp.c | 48 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9448d898d80b..96caa469e3a8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4827,36 +4827,34 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) port_name(intel_dig_port->port), long_hpd ? "long" : "short"); + if (long_hpd) { + intel_dp->detect_done = false; + return IRQ_NONE; + } + power_domain = intel_display_port_aux_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); - if (long_hpd) { - intel_dp_long_pulse(intel_dp->attached_connector); - if (intel_dp->is_mst) - ret = IRQ_HANDLED; - goto put_power; - - } else { - if (intel_dp->is_mst) { - if (intel_dp_check_mst_status(intel_dp) == -EINVAL) { - /* - * If we were in MST mode, and device is not - * there, get out of MST mode - */ - DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", - intel_dp->is_mst, intel_dp->mst_mgr.mst_state); - intel_dp->is_mst = false; - drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, - intel_dp->is_mst); - goto put_power; - } + if (intel_dp->is_mst) { + if (intel_dp_check_mst_status(intel_dp) == -EINVAL) { + /* + * If we were in MST mode, and device is not + * there, get out of MST mode + */ + DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", + intel_dp->is_mst, intel_dp->mst_mgr.mst_state); + intel_dp->is_mst = false; + drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, + intel_dp->is_mst); + intel_dp->detect_done = false; + goto put_power; } + } - if (!intel_dp->is_mst) { - if (!intel_dp_short_pulse(intel_dp)) { - intel_dp_long_pulse(intel_dp->attached_connector); - goto put_power; - } + if (!intel_dp->is_mst) { + if (!intel_dp_short_pulse(intel_dp)) { + intel_dp->detect_done = false; + goto put_power; } } -- cgit v1.2.3 From 5cb651a7959310ef4dbb0b93f005b10286789656 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 3 Oct 2016 10:55:16 +0300 Subject: drm/i915: Allow DP to work w/o EDID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow returning "connected" or "unknown" connector status for DP branch devices that don't have an EDID. Currently we'd claim the thing as "disconnected" if there is no EDID. This stuff used to broken already, I think, but it got more broken by commit f21a21983ef1 ("drm/i915: Splitting intel_dp_detect") Cc: Damien Cassou Cc: freedesktop.org@gp.mailgun.org Cc: Arno Cc: Shubhangi Shrivastava Cc: Sivakumar Thulasimani Cc: Ander Conselvan de Oliveira Cc: stable@vger.kernel.org Tested-by: Arno Fixes: f21a21983ef1 ("drm/i915: Splitting intel_dp_detect") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=83348 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1475481316-8194-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Ander Conselvan de Oliveira --- drivers/gpu/drm/i915/intel_dp.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 96caa469e3a8..5992093e1814 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4333,7 +4333,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) intel_dp->has_audio = false; } -static void +static enum drm_connector_status intel_dp_long_pulse(struct intel_connector *intel_connector) { struct drm_connector *connector = &intel_connector->base; @@ -4357,7 +4357,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) else status = connector_status_disconnected; - if (status != connector_status_connected) { + if (status == connector_status_disconnected) { intel_dp->compliance_test_active = 0; intel_dp->compliance_test_type = 0; intel_dp->compliance_test_data = 0; @@ -4419,8 +4419,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp->aux.i2c_defer_count = 0; intel_dp_set_edid(intel_dp); - - status = connector_status_connected; + if (is_edp(intel_dp) || intel_connector->detect_edid) + status = connector_status_connected; intel_dp->detect_done = true; /* Try to read the source of the interrupt */ @@ -4439,12 +4439,11 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) } out: - if ((status != connector_status_connected) && - (intel_dp->is_mst == false)) + if (status != connector_status_connected && !intel_dp->is_mst) intel_dp_unset_edid(intel_dp); intel_display_power_put(to_i915(dev), power_domain); - return; + return status; } static enum drm_connector_status @@ -4453,7 +4452,7 @@ intel_dp_detect(struct drm_connector *connector, bool force) struct intel_dp *intel_dp = intel_attached_dp(connector); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *intel_encoder = &intel_dig_port->base; - struct intel_connector *intel_connector = to_intel_connector(connector); + enum drm_connector_status status = connector->status; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); @@ -4468,14 +4467,11 @@ intel_dp_detect(struct drm_connector *connector, bool force) /* If full detect is not performed yet, do a full detect */ if (!intel_dp->detect_done) - intel_dp_long_pulse(intel_dp->attached_connector); + status = intel_dp_long_pulse(intel_dp->attached_connector); intel_dp->detect_done = false; - if (is_edp(intel_dp) || intel_connector->detect_edid) - return connector_status_connected; - else - return connector_status_disconnected; + return status; } static void -- cgit v1.2.3 From 604db6509ddaa7df7765dbddc7b48036a2b31dfa Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 5 Oct 2016 13:50:16 +0300 Subject: drm/i915: Reduce trickery in DEV_INFO_FOR_EACH_FLAG Get rid of SEP_SEMICOLON and SEP_BLANK in DEV_INFO_FOR_EACH_FLAG. Consolidate the debug output so that instead of one huge line with "cap1,cap2,capN" each capability is split to own line and displayed as "capN: [yes|no]" to make the dumps more historically informative. v2: - Do not break auto-indent by keeping semicolon after macro (Jani) - Consolidate and use yesno() in all locations (Chris) Cc: Jani Nikula Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 98 +++++++++++++++----------------- drivers/gpu/drm/i915/i915_gpu_error.c | 4 +- drivers/gpu/drm/i915/intel_device_info.c | 16 ++---- 4 files changed, 54 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 98f536d94797..1a1cc9b5dabb 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -79,10 +79,8 @@ static int i915_capabilities(struct seq_file *m, void *data) seq_printf(m, "gen: %d\n", INTEL_GEN(dev_priv)); seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv)); #define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x)) -#define SEP_SEMICOLON ; - DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON); + DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG -#undef SEP_SEMICOLON return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4613f031d127..28024e7ca68a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -646,55 +646,52 @@ struct intel_csr { uint32_t allowed_dc_mask; }; -#define DEV_INFO_FOR_EACH_FLAG(func, sep) \ - func(is_mobile) sep \ - func(is_i85x) sep \ - func(is_i915g) sep \ - func(is_i945gm) sep \ - func(is_g33) sep \ - func(hws_needs_physical) sep \ - func(is_g4x) sep \ - func(is_pineview) sep \ - func(is_broadwater) sep \ - func(is_crestline) sep \ - func(is_ivybridge) sep \ - func(is_valleyview) sep \ - func(is_cherryview) sep \ - func(is_haswell) sep \ - func(is_broadwell) sep \ - func(is_skylake) sep \ - func(is_broxton) sep \ - func(is_kabylake) sep \ - func(is_preliminary) sep \ - func(has_fbc) sep \ - func(has_psr) sep \ - func(has_runtime_pm) sep \ - func(has_csr) sep \ - func(has_resource_streamer) sep \ - func(has_rc6) sep \ - func(has_rc6p) sep \ - func(has_dp_mst) sep \ - func(has_gmbus_irq) sep \ - func(has_hw_contexts) sep \ - func(has_logical_ring_contexts) sep \ - func(has_l3_dpf) sep \ - func(has_gmch_display) sep \ - func(has_guc) sep \ - func(has_pipe_cxsr) sep \ - func(has_hotplug) sep \ - func(cursor_needs_physical) sep \ - func(has_overlay) sep \ - func(overlay_needs_physical) sep \ - func(supports_tv) sep \ - func(has_llc) sep \ - func(has_snoop) sep \ - func(has_ddi) sep \ - func(has_fpga_dbg) sep \ +#define DEV_INFO_FOR_EACH_FLAG(func) \ + func(is_mobile); \ + func(is_i85x); \ + func(is_i915g); \ + func(is_i945gm); \ + func(is_g33); \ + func(hws_needs_physical); \ + func(is_g4x); \ + func(is_pineview); \ + func(is_broadwater); \ + func(is_crestline); \ + func(is_ivybridge); \ + func(is_valleyview); \ + func(is_cherryview); \ + func(is_haswell); \ + func(is_broadwell); \ + func(is_skylake); \ + func(is_broxton); \ + func(is_kabylake); \ + func(is_preliminary); \ + func(has_fbc); \ + func(has_psr); \ + func(has_runtime_pm); \ + func(has_csr); \ + func(has_resource_streamer); \ + func(has_rc6); \ + func(has_rc6p); \ + func(has_dp_mst); \ + func(has_gmbus_irq); \ + func(has_hw_contexts); \ + func(has_logical_ring_contexts); \ + func(has_l3_dpf); \ + func(has_gmch_display); \ + func(has_guc); \ + func(has_pipe_cxsr); \ + func(has_hotplug); \ + func(cursor_needs_physical); \ + func(has_overlay); \ + func(overlay_needs_physical); \ + func(supports_tv); \ + func(has_llc); \ + func(has_snoop); \ + func(has_ddi); \ + func(has_fpga_dbg); \ func(has_pooled_eu) -#define DEFINE_FLAG(name) u8 name:1 -#define SEP_SEMICOLON ; - struct sseu_dev_info { u8 slice_mask; u8 subslice_mask; @@ -722,7 +719,9 @@ struct intel_device_info { u16 gen_mask; u8 ring_mask; /* Rings supported by the HW */ u8 num_rings; - DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON); +#define DEFINE_FLAG(name) u8 name:1 + DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG); +#undef DEFINE_FLAG u16 ddb_size; /* in blocks */ /* Register offsets for the various display pipes and transcoders */ int pipe_offsets[I915_MAX_TRANSCODERS]; @@ -739,9 +738,6 @@ struct intel_device_info { } color; }; -#undef DEFINE_FLAG -#undef SEP_SEMICOLON - struct intel_display_error_state; struct drm_i915_error_state { diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 8b85efbdfa04..b5b58692ac5a 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -357,10 +357,8 @@ static void err_print_capabilities(struct drm_i915_error_state_buf *m, const struct intel_device_info *info) { #define PRINT_FLAG(x) err_printf(m, #x ": %s\n", yesno(info->x)) -#define SEP_SEMICOLON ; - DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON); + DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG -#undef SEP_SEMICOLON } int i915_error_state_to_str(struct drm_i915_error_state_buf *m, diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 1b20e160bc1f..d6a8f11813d5 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -28,20 +28,14 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv) { const struct intel_device_info *info = &dev_priv->info; -#define PRINT_S(name) "%s" -#define SEP_EMPTY -#define PRINT_FLAG(name) info->name ? #name "," : "" -#define SEP_COMMA , - DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags=" - DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY), + DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x", info->gen, dev_priv->drm.pdev->device, - dev_priv->drm.pdev->revision, - DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA)); -#undef PRINT_S -#undef SEP_EMPTY + dev_priv->drm.pdev->revision); +#define PRINT_FLAG(name) \ + DRM_DEBUG_DRIVER("i915 device info: " #name ": %s", yesno(info->name)) + DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG -#undef SEP_COMMA } static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From 566c56a493ea17fd321abb60d59bfb274489bb18 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 5 Oct 2016 13:50:17 +0300 Subject: drm/i915: Sort DEV_INFO_FOR_EACH_FLAG Sort DEV_INFO_FOR_EACH_FLAG to alphabetical order (except is_*). v2: - Add comments in the hope of maintaining order (Chris) Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1475664617-24541-1-git-send-email-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 28024e7ca68a..a219a3534750 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -647,12 +647,12 @@ struct intel_csr { }; #define DEV_INFO_FOR_EACH_FLAG(func) \ + /* Keep is_* in chronological order */ \ func(is_mobile); \ func(is_i85x); \ func(is_i915g); \ func(is_i945gm); \ func(is_g33); \ - func(hws_needs_physical); \ func(is_g4x); \ func(is_pineview); \ func(is_broadwater); \ @@ -666,31 +666,33 @@ struct intel_csr { func(is_broxton); \ func(is_kabylake); \ func(is_preliminary); \ - func(has_fbc); \ - func(has_psr); \ - func(has_runtime_pm); \ + /* Keep has_* in alphabetical order */ \ func(has_csr); \ - func(has_resource_streamer); \ - func(has_rc6); \ - func(has_rc6p); \ + func(has_ddi); \ func(has_dp_mst); \ + func(has_fbc); \ + func(has_fpga_dbg); \ func(has_gmbus_irq); \ - func(has_hw_contexts); \ - func(has_logical_ring_contexts); \ - func(has_l3_dpf); \ func(has_gmch_display); \ func(has_guc); \ - func(has_pipe_cxsr); \ func(has_hotplug); \ - func(cursor_needs_physical); \ - func(has_overlay); \ - func(overlay_needs_physical); \ - func(supports_tv); \ + func(has_hw_contexts); \ + func(has_l3_dpf); \ func(has_llc); \ + func(has_logical_ring_contexts); \ + func(has_overlay); \ + func(has_pipe_cxsr); \ + func(has_pooled_eu); \ + func(has_psr); \ + func(has_rc6); \ + func(has_rc6p); \ + func(has_resource_streamer); \ + func(has_runtime_pm); \ func(has_snoop); \ - func(has_ddi); \ - func(has_fpga_dbg); \ - func(has_pooled_eu) + func(cursor_needs_physical); \ + func(hws_needs_physical); \ + func(overlay_needs_physical); \ + func(supports_tv) struct sseu_dev_info { u8 slice_mask; -- cgit v1.2.3 From 3605d751d5dd82ad1586bed72a0ebc84d81e20c7 Mon Sep 17 00:00:00 2001 From: James Minor Date: Mon, 3 Oct 2016 13:00:02 -0500 Subject: ath6kl: fix busreqs so they can be reused when sg is cleaned up To reuse the busreqs in case of hardware restart, they must be properly reinitialized. If the scat_req pointer isn't reset to 0, __ath6kl_sdio_write_async() will assume there is sg work to be done (causing a kernel OOPS). Signed-off-by: James Minor Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index eab0ab976af2..96ed0604b4e0 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -703,8 +703,10 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar) * ath6kl_hif_rw_comp_handler() with status -ECANCELED so * that the packet is properly freed? */ - if (s_req->busrequest) + if (s_req->busrequest) { + s_req->busrequest->scat_req = 0; ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest); + } kfree(s_req->virt_dma_buf); kfree(s_req->sgentries); kfree(s_req); -- cgit v1.2.3 From db14b18a73a1ceaac96124e7918aa9e484f80dbb Mon Sep 17 00:00:00 2001 From: James Minor Date: Mon, 3 Oct 2016 13:00:03 -0500 Subject: ath6kl: after cleanup properly reflect that sg is disabled This allows the hardware to be restarted, as it will cause the sg to be reinitialized. Signed-off-by: James Minor Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 96ed0604b4e0..8261e242fd1e 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -714,6 +714,8 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar) spin_lock_bh(&ar_sdio->scat_lock); } spin_unlock_bh(&ar_sdio->scat_lock); + + ar_sdio->scatter_enabled = false; } /* setup of HIF scatter resources */ -- cgit v1.2.3 From fdb6e4839e3ad98b9b51be00e1f99d63db402030 Mon Sep 17 00:00:00 2001 From: James Minor Date: Mon, 3 Oct 2016 13:00:04 -0500 Subject: ath6kl: configure SDIO when power is reapplied When power is removed from the device, all of the SDIO settings return to default. Fix that by reconfiguring after power is applied. Signed-off-by: James Minor Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 8261e242fd1e..c2df075d2d56 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -75,6 +75,8 @@ struct ath6kl_sdio { #define CMD53_ARG_FIXED_ADDRESS 0 #define CMD53_ARG_INCR_ADDRESS 1 +static int ath6kl_sdio_config(struct ath6kl *ar); + static inline struct ath6kl_sdio *ath6kl_sdio_priv(struct ath6kl *ar) { return ar->hif_priv; @@ -526,8 +528,15 @@ static int ath6kl_sdio_power_on(struct ath6kl *ar) */ msleep(10); + ret = ath6kl_sdio_config(ar); + if (ret) { + ath6kl_err("Failed to config sdio: %d\n", ret); + goto out; + } + ar_sdio->is_disabled = false; +out: return ret; } -- cgit v1.2.3 From 26aa23396ed34343ba55cae985160856246dafbb Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 12:20:44 +0300 Subject: Revert "Skip intel_crt_init for Dell XPS 8700" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 10b6ee4a87811a110cb01eaca01eb04da6801baf. According to [1] Dell XPS8700 VBT says 'int_crt_support 0', so thanks to commit e4abb733bb72 ("drm/i915: Check VBT for CRT port presence on HSW/BDW") we no longer need to blacklist it based on DMI. Looking through the bug report, SFUSE_STRAP based detection was apparently also tried and failed, but the VBT based one should still work just fine. The commit says that the symptom was a frozen machine, but based on the bug report it doesn't look like the CRT detection was at least directly responsible for such a drastic outcome. Cc: Giacomo Comes References: https://bugs.freedesktop.org/show_bug.cgi?id=73559 References: http://lists.freedesktop.org/archives/intel-gfx/2014-January/038178.html [1] Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1474881646-1326-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 88ebbdde185a..ba372c239d48 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -823,14 +823,6 @@ static const struct dmi_system_id intel_no_crt[] = { DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), }, }, - { - .callback = intel_no_crt_dmi_callback, - .ident = "DELL XPS 8700", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"), - }, - }, { } }; -- cgit v1.2.3 From f0dfb1a81a9d2c093afd5866d406d9a55df1e52f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 12:20:45 +0300 Subject: drm/i915: Register shadow VGA even when it produces spurious detection results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having a shadow VGA connector is useful for testing purposes. We currently skip registering the connector on machines where the CRT detect falsely reports it as connected. Let's instead move the the blacklist check to the detect callback (and hpd setup) and if we get a match we always report the connector as disconnected. This way we get a shadow VGA connector to help with testing, while we still avoid the user facing problems from the incorrect detection results. commit 8ca4013d702d ("CHROMIUM: i915: Add DMI override to skip CRT initialization on ZGB") doesn't provide much in the way of details as to why 'ACER ZGB' was added to the blacklist. Trying to trace it further leads me to a chromeos bugreport I can't access. So based on the fact that the commit added the "/* Skip machines without VGA that falsely report hotplug events */" comment, I'm going to assume that it was just spurious CRT detection. So it should be safe to move the blacklist to just block the detection and hpd without causing a regression on said machine. In fact Stéphane confirmed on irc that the problem was indeed just crappy hotplug detect: "22:29 < marcheu> vsyrjala: the port isn't there, but the load detect is improperly stubbed in hw 22:29 < marcheu> vsyrjala: so it floats" so this change should be perfectly fine. v2: Add irc quote from Stéphane Cc: Duncan Laurie Cc: Olof Johansson Cc: Stéphane Marchesin Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1474881646-1326-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 47 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index ba372c239d48..e3753804c619 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -643,6 +643,24 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe) return status; } +static int intel_spurious_crt_detect_dmi_callback(const struct dmi_system_id *id) +{ + DRM_DEBUG_DRIVER("Skipping CRT detection for %s\n", id->ident); + return 1; +} + +static const struct dmi_system_id intel_spurious_crt_detect[] = { + { + .callback = intel_spurious_crt_detect_dmi_callback, + .ident = "ACER ZGB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ACER"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), + }, + }, + { } +}; + static enum drm_connector_status intel_crt_detect(struct drm_connector *connector, bool force) { @@ -659,6 +677,10 @@ intel_crt_detect(struct drm_connector *connector, bool force) connector->base.id, connector->name, force); + /* Skip machines without VGA that falsely report hotplug events */ + if (dmi_check_system(intel_spurious_crt_detect)) + return connector_status_disconnected; + power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); @@ -808,24 +830,6 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { .destroy = intel_encoder_destroy, }; -static int intel_no_crt_dmi_callback(const struct dmi_system_id *id) -{ - DRM_INFO("Skipping CRT initialization for %s\n", id->ident); - return 1; -} - -static const struct dmi_system_id intel_no_crt[] = { - { - .callback = intel_no_crt_dmi_callback, - .ident = "ACER ZGB", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ACER"), - DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), - }, - }, - { } -}; - void intel_crt_init(struct drm_device *dev) { struct drm_connector *connector; @@ -835,10 +839,6 @@ void intel_crt_init(struct drm_device *dev) i915_reg_t adpa_reg; u32 adpa; - /* Skip machines without VGA that falsely report hotplug events */ - if (dmi_check_system(intel_no_crt)) - return; - if (HAS_PCH_SPLIT(dev)) adpa_reg = PCH_ADPA; else if (IS_VALLEYVIEW(dev)) @@ -906,7 +906,8 @@ void intel_crt_init(struct drm_device *dev) crt->base.disable = intel_disable_crt; } crt->base.enable = intel_enable_crt; - if (I915_HAS_HOTPLUG(dev)) + if (I915_HAS_HOTPLUG(dev) && + !dmi_check_system(intel_spurious_crt_detect)) crt->base.hpd_pin = HPD_CRT; if (HAS_DDI(dev)) { crt->base.port = PORT_E; -- cgit v1.2.3 From 69a44b16cba895ff761c1763508c271a084950b5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 12:20:46 +0300 Subject: drm/i915: Add spurious CRT DMI match for Intel DZ77BH-55K MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel DZ77BH-55K board doest't have a physical VGA connector, and yet it always detects that something is connected there. Add it to the DMI blacklist to ignore the spurious detection results. Allows me to drop 'video=VGA-1:d' from my kernel cmdline. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1474881646-1326-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index e3753804c619..4a7b6c595ec2 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -658,6 +658,14 @@ static const struct dmi_system_id intel_spurious_crt_detect[] = { DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), }, }, + { + .callback = intel_spurious_crt_detect_dmi_callback, + .ident = "Intel DZ77BH-55K", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "DZ77BH-55K"), + }, + }, { } }; -- cgit v1.2.3 From 8687b3ec852e89630bac650f15136811c7b4c1dc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Oct 2016 07:53:24 +0100 Subject: drm/i915: Distinguish last emitted request from last submitted request In order not to trigger hangcheck on a idle-but-waiting engine, we need to distinguish between the pending request queue and the actual execution queue. This is done later in "drm/i915: Enable multiple timelines" but for now we need a temporary fix to prevent blaming the wrong engine for a GPU hang. (Note that this causes a temporary subtle change in how we decide when to allow a waitboost to be re-awarded back to the waiter, the temporary effect is that if the wait is upon the most current execution the wait is given for free, instead of checking to see if the client stalled itself. This will be repaired in "drm/i915: Enable multiple timelines".) Fixes: 0a046a0e93d2 ("drm/i915: Nonblocking request submission") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98104 Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Mika Kuoppala Reviewed-by: Joonas Lahtinen Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161007065327.24515-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 5 +++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 40978bc12ceb..8832f8ec1583 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -328,6 +328,7 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) switch (state) { case FENCE_COMPLETE: + request->engine->last_submitted_seqno = request->fence.seqno; request->engine->submit_request(request); break; @@ -641,8 +642,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) &request->submitq); request->emitted_jiffies = jiffies; - request->previous_seqno = engine->last_submitted_seqno; - engine->last_submitted_seqno = request->fence.seqno; + request->previous_seqno = engine->last_pending_seqno; + engine->last_pending_seqno = request->fence.seqno; i915_gem_active_set(&engine->last_request, request); list_add_tail(&request->link, &engine->request_list); list_add_tail(&request->ring_link, &ring->request_list); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 498931f0b1f1..34954ca03a4a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -355,6 +355,7 @@ struct intel_engine_cs { * inspecting request list. */ u32 last_submitted_seqno; + u32 last_pending_seqno; /* An RCU guarded pointer to the last request. No reference is * held to the request, users must carefully acquire a reference to -- cgit v1.2.3 From d7f7633557503bd231347d8896b9a6fb08f84e00 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Oct 2016 07:53:25 +0100 Subject: drm/i915: Force relocations via cpu if we run out of idle aperture If we run out of enough aperture space to fit the entire object, we fallback to trying to insert a single page. However, if that also fails, we currently fail to userspace with an unexpected ENOSPC. (ENOSPC means to userspace that their batch could not be fitted within the GTT.) Prior to commit e8cb909ac3ab ("drm/i915: Fallback to single page GTT mmappings for relocations") the approach is to fallback to using the slow CPU relocation path in case of iomapping failure, and that is the behaviour we need to restore. Fixes: e8cb909ac3ab ("drm/i915: Fallback to single page GTT mmappings...") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98101 Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161007065327.24515-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index e88786ea1219..72c7c1855e70 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -451,8 +451,8 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, 0, ggtt->mappable_end, DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT); - if (ret) - return ERR_PTR(ret); + if (ret) /* no inactive aperture space, use cpu reloc */ + return NULL; } else { ret = i915_vma_put_fence(vma); if (ret) { -- cgit v1.2.3 From ad07dfcddf1394e6fed094e7fb426b4242a6814e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Oct 2016 07:53:26 +0100 Subject: drm/i915: Reset the breadcrumbs IRQ more carefully Along with the interrupt, we want to restore the fake-irq and wait-timeout detection. If we use the breadcrumbs interface to setup the interrupt as it wants, the auxiliary timers will also be restored. v2: Cancel both timers as well, sanitize the IMR. Fixes: 821ed7df6e2a ("drm/i915: Update reset path to fix incomplete requests") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161007065327.24515-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_breadcrumbs.c | 33 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_engine_cs.c | 15 --------------- drivers/gpu/drm/i915/intel_lrc.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 5 files changed, 34 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 9bad14d22c95..495611b7068d 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -578,6 +578,36 @@ int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine) return 0; } +static void cancel_fake_irq(struct intel_engine_cs *engine) +{ + struct intel_breadcrumbs *b = &engine->breadcrumbs; + + del_timer_sync(&b->hangcheck); + del_timer_sync(&b->fake_irq); + clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); +} + +void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) +{ + struct intel_breadcrumbs *b = &engine->breadcrumbs; + + cancel_fake_irq(engine); + spin_lock(&b->lock); + + __intel_breadcrumbs_disable_irq(b); + if (intel_engine_has_waiter(engine)) { + b->timeout = wait_timeout(); + __intel_breadcrumbs_enable_irq(b); + if (READ_ONCE(b->irq_posted)) + wake_up_process(b->first_wait->tsk); + } else { + /* sanitize the IMR and unmask any auxiliary interrupts */ + irq_disable(engine); + } + + spin_unlock(&b->lock); +} + void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) { struct intel_breadcrumbs *b = &engine->breadcrumbs; @@ -585,8 +615,7 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) if (!IS_ERR_OR_NULL(b->signaler)) kthread_stop(b->signaler); - del_timer_sync(&b->hangcheck); - del_timer_sync(&b->fake_irq); + cancel_fake_irq(engine); } unsigned int intel_kick_waiters(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index d00ec805f93d..480584c09306 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -210,9 +210,6 @@ void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno) void intel_engine_init_hangcheck(struct intel_engine_cs *engine) { memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); - clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); - if (intel_engine_has_waiter(engine)) - i915_queue_hangcheck(engine->i915); } static void intel_engine_init_requests(struct intel_engine_cs *engine) @@ -307,18 +304,6 @@ int intel_engine_init_common(struct intel_engine_cs *engine) return 0; } -void intel_engine_reset_irq(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - - spin_lock_irq(&dev_priv->irq_lock); - if (intel_engine_has_waiter(engine)) - engine->irq_enable(engine); - else - engine->irq_disable(engine); - spin_unlock_irq(&dev_priv->irq_lock); -} - /** * intel_engines_cleanup_common - cleans up the engine state created by * the common initiailizers. diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 936f6f63f626..44904e298bfc 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1230,7 +1230,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) lrc_init_hws(engine); - intel_engine_reset_irq(engine); + intel_engine_reset_breadcrumbs(engine); I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 35f359e38f4d..729f373782e2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -548,7 +548,7 @@ static int init_ring_common(struct intel_engine_cs *engine) else intel_ring_setup_status_page(engine); - intel_engine_reset_irq(engine); + intel_engine_reset_breadcrumbs(engine); /* Enforce ordering by reading HEAD register back */ I915_READ_HEAD(engine); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 34954ca03a4a..124f4646958d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -520,7 +520,6 @@ int __intel_ring_space(int head, int tail, int size); void intel_ring_update_space(struct intel_ring *ring); void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno); -void intel_engine_reset_irq(struct intel_engine_cs *engine); void intel_engine_setup_common(struct intel_engine_cs *engine); int intel_engine_init_common(struct intel_engine_cs *engine); @@ -614,6 +613,7 @@ static inline bool intel_engine_wakeup(const struct intel_engine_cs *engine) return wakeup; } +void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); unsigned int intel_kick_waiters(struct drm_i915_private *i915); unsigned int intel_kick_signalers(struct drm_i915_private *i915); -- cgit v1.2.3 From 5ba899082cbffb779ccb39420fe1718850daf857 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Oct 2016 07:53:27 +0100 Subject: drm/i915/guc: Unwind GuC workqueue reservation if request construction fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We reserve space in the GuC workqueue for submitting the request in the future. However, if we fail to construct the request, we need to give that reserved space back to the system. Fixes: dadd481bfe55 ("drm/i915/guc: Prepare for nonblocking execbuf submission") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97978 Signed-off-by: Chris Wilson Cc: Michał Winiarski Reviewed-by: Michał Winiarski Link: http://patchwork.freedesktop.org/patch/msgid/20161007065327.24515-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_guc_submission.c | 12 ++++++++++++ drivers/gpu/drm/i915/intel_guc.h | 1 + drivers/gpu/drm/i915/intel_lrc.c | 17 ++++++++++------- 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 43358e18d34c..3106dcc06fe9 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -451,6 +451,18 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request) return ret; } +void i915_guc_wq_unreserve(struct drm_i915_gem_request *request) +{ + const size_t wqi_size = sizeof(struct guc_wq_item); + struct i915_guc_client *gc = request->i915->guc.execbuf_client; + + GEM_BUG_ON(READ_ONCE(gc->wq_rsvd) < wqi_size); + + spin_lock(&gc->wq_lock); + gc->wq_rsvd -= wqi_size; + spin_unlock(&gc->wq_lock); +} + /* Construct a Work Item and append it to the GuC's Work Queue */ static void guc_wq_item_append(struct i915_guc_client *gc, struct drm_i915_gem_request *rq) diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index b1ba86958811..5cdf7aa75be5 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -160,6 +160,7 @@ extern int intel_guc_resume(struct drm_device *dev); int i915_guc_submission_init(struct drm_i915_private *dev_priv); int i915_guc_submission_enable(struct drm_i915_private *dev_priv); int i915_guc_wq_reserve(struct drm_i915_gem_request *rq); +void i915_guc_wq_unreserve(struct drm_i915_gem_request *request); void i915_guc_submission_disable(struct drm_i915_private *dev_priv); void i915_guc_submission_fini(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 44904e298bfc..10fcea57e4dd 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -626,6 +626,10 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request request->ring = ce->ring; + ret = intel_lr_context_pin(request->ctx, engine); + if (ret) + return ret; + if (i915.enable_guc_submission) { /* * Check that the GuC has space for the request before @@ -634,21 +638,17 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request */ ret = i915_guc_wq_reserve(request); if (ret) - return ret; + goto err_unpin; } - ret = intel_lr_context_pin(request->ctx, engine); - if (ret) - return ret; - ret = intel_ring_begin(request, 0); if (ret) - goto err_unpin; + goto err_unreserve; if (!ce->initialised) { ret = engine->init_context(request); if (ret) - goto err_unpin; + goto err_unreserve; ce->initialised = true; } @@ -663,6 +663,9 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request request->reserved_space -= EXECLISTS_REQUEST_SIZE; return 0; +err_unreserve: + if (i915.enable_guc_submission) + i915_guc_wq_unreserve(request); err_unpin: intel_lr_context_unpin(request->ctx, engine); return ret; -- cgit v1.2.3 From b321a38d2407c7e425c54bc09be909a34e49f740 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Sun, 9 Oct 2016 00:05:39 +0800 Subject: staging: iio: ad7606: fix improper setting of oversampling pins The oversampling ratio is controlled using the oversampling pins, OS [2:0] with OS2 being the MSB control bit, and OS0 the LSB control bit. The gpio connected to the OS2 pin is not being set correctly, only OS0 and OS1 pins are being set. Fix the typo to allow proper control of the oversampling pins. Signed-off-by: Eva Rachel Retuya Fixes: b9618c0 ("staging: IIO: ADC: New driver for AD7606/AD7606-6/AD7606-4") Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index f79ee61851f6..cbd6bc52050f 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -189,7 +189,7 @@ static ssize_t ad7606_store_oversampling_ratio(struct device *dev, mutex_lock(&indio_dev->mlock); gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1); gpio_set_value(st->pdata->gpio_os1, (ret >> 1) & 1); - gpio_set_value(st->pdata->gpio_os1, (ret >> 2) & 1); + gpio_set_value(st->pdata->gpio_os2, (ret >> 2) & 1); st->oversampling = lval; mutex_unlock(&indio_dev->mlock); -- cgit v1.2.3 From 4a5936dac5aac2b8a01d861281c0d9fa05251cac Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Sun, 9 Oct 2016 00:05:40 +0800 Subject: staging: iio: ad7606: implement IIO_CHAN_INFO_OVERSAMPLING_RATIO This driver predates the availability of IIO_CHAN_INFO_OVERSAMPLING_RATIO attribute wherein usage has some advantages like it can be accessed by in-kernel consumers as well as reduces the code size. Therefore, use IIO_CHAN_INFO_OVERSAMPLING_RATIO to implement the oversampling_ratio attribute instead of using IIO_DEVICE_ATTR() macro. Move code from the functions associated with IIO_DEVICE_ATTR() into the read_raw hook as well as add the write_raw hook with both masks set to IIO_CHAN_INFO_OVERSAMPLING_RATIO. Signed-off-by: Eva Rachel Retuya Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 67 ++++++++++++++++------------------- 1 file changed, 31 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index cbd6bc52050f..204222517a39 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -103,6 +103,9 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, *val = st->range * 2; *val2 = st->chip_info->channels[0].scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = st->oversampling; + return IIO_VAL_INT; } return -EINVAL; } @@ -145,16 +148,6 @@ static IIO_DEVICE_ATTR(in_voltage_range, S_IRUGO | S_IWUSR, ad7606_show_range, ad7606_store_range, 0); static IIO_CONST_ATTR(in_voltage_range_available, "5000 10000"); -static ssize_t ad7606_show_oversampling_ratio(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%u\n", st->oversampling); -} - static int ad7606_oversampling_get_index(unsigned int val) { unsigned char supported[] = {0, 2, 4, 8, 16, 32, 64}; @@ -167,44 +160,43 @@ static int ad7606_oversampling_get_index(unsigned int val) return -EINVAL; } -static ssize_t ad7606_store_oversampling_ratio(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static int ad7606_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7606_state *st = iio_priv(indio_dev); - unsigned long lval; int ret; - ret = kstrtoul(buf, 10, &lval); - if (ret) - return ret; + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + if (val2) + return -EINVAL; + ret = ad7606_oversampling_get_index(val); + if (ret < 0) { + dev_err(st->dev, "oversampling %d is not supported\n", + val); + return ret; + } - ret = ad7606_oversampling_get_index(lval); - if (ret < 0) { - dev_err(dev, "oversampling %lu is not supported\n", lval); - return ret; + mutex_lock(&indio_dev->mlock); + gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1); + gpio_set_value(st->pdata->gpio_os1, (ret >> 1) & 1); + gpio_set_value(st->pdata->gpio_os2, (ret >> 2) & 1); + st->oversampling = val; + mutex_unlock(&indio_dev->mlock); + return 0; + default: + return -EINVAL; } - - mutex_lock(&indio_dev->mlock); - gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1); - gpio_set_value(st->pdata->gpio_os1, (ret >> 1) & 1); - gpio_set_value(st->pdata->gpio_os2, (ret >> 2) & 1); - st->oversampling = lval; - mutex_unlock(&indio_dev->mlock); - - return count; } -static IIO_DEVICE_ATTR(oversampling_ratio, S_IRUGO | S_IWUSR, - ad7606_show_oversampling_ratio, - ad7606_store_oversampling_ratio, 0); static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64"); static struct attribute *ad7606_attributes_os_and_range[] = { &iio_dev_attr_in_voltage_range.dev_attr.attr, &iio_const_attr_in_voltage_range_available.dev_attr.attr, - &iio_dev_attr_oversampling_ratio.dev_attr.attr, &iio_const_attr_oversampling_ratio_available.dev_attr.attr, NULL, }; @@ -214,7 +206,6 @@ static const struct attribute_group ad7606_attribute_group_os_and_range = { }; static struct attribute *ad7606_attributes_os[] = { - &iio_dev_attr_oversampling_ratio.dev_attr.attr, &iio_const_attr_oversampling_ratio_available.dev_attr.attr, NULL, }; @@ -241,6 +232,8 @@ static const struct attribute_group ad7606_attribute_group_range = { .address = num, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .info_mask_shared_by_all = \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .scan_index = num, \ .scan_type = { \ .sign = 's', \ @@ -429,12 +422,14 @@ static const struct iio_info ad7606_info_no_os_or_range = { static const struct iio_info ad7606_info_os_and_range = { .driver_module = THIS_MODULE, .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, .attrs = &ad7606_attribute_group_os_and_range, }; static const struct iio_info ad7606_info_os = { .driver_module = THIS_MODULE, .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, .attrs = &ad7606_attribute_group_os, }; -- cgit v1.2.3 From 738bb80e3e3d7d8c0109c796ca5e7c4b6f1f558f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 10 Oct 2016 10:20:22 +0200 Subject: drm/i915: Update DRIVER_DATE to 20161010 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a219a3534750..54d860e1c0fc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -70,7 +70,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20160919" +#define DRIVER_DATE "20161010" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v1.2.3 From e1bc84d0071f59c8b38232e2cb093c47c47e4f9f Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Fri, 7 Oct 2016 12:39:34 -0700 Subject: HID: sony: Fix race condition in sony_probe Early on the sony_probe function calls hid_hw_start to start the hardware. Afterwards it issues some hardware requests, initializes other functionality like Force Feedback, power classes and others. However by the time hid_hw_start returns, the device nodes have already been created, which leads to a race condition by user space applications which may detect the device prior to completion of initialization. We have observed this problem many times, this patch fixes the problem. This patch moves most of sony_probe to sony_input_configured, which is called prior to device registration. This fixes the race condition and the same approach is used in other HID drivers. Signed-off-by: Roderick Colenbrander Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 117 ++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b0bb99a821bd..afa82198defb 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1387,28 +1387,6 @@ static int sony_register_touchpad(struct hid_input *hi, int touch_count, return 0; } -static int sony_input_configured(struct hid_device *hdev, - struct hid_input *hidinput) -{ - struct sony_sc *sc = hid_get_drvdata(hdev); - int ret; - - /* - * The Dualshock 4 touchpad supports 2 touches and has a - * resolution of 1920x942 (44.86 dots/mm). - */ - if (sc->quirks & DUALSHOCK4_CONTROLLER) { - ret = sony_register_touchpad(hidinput, 2, 1920, 942); - if (ret) { - hid_err(sc->hdev, - "Unable to initialize multi-touch slots: %d\n", - ret); - return ret; - } - } - - return 0; -} /* * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller @@ -2329,45 +2307,12 @@ static inline void sony_cancel_work_sync(struct sony_sc *sc) cancel_work_sync(&sc->state_worker); } -static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) +static int sony_input_configured(struct hid_device *hdev, + struct hid_input *hidinput) { - int ret; + struct sony_sc *sc = hid_get_drvdata(hdev); int append_dev_id; - unsigned long quirks = id->driver_data; - struct sony_sc *sc; - unsigned int connect_mask = HID_CONNECT_DEFAULT; - - if (!strcmp(hdev->name, "FutureMax Dance Mat")) - quirks |= FUTUREMAX_DANCE_MAT; - - sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); - if (sc == NULL) { - hid_err(hdev, "can't alloc sony descriptor\n"); - return -ENOMEM; - } - - spin_lock_init(&sc->lock); - - sc->quirks = quirks; - hid_set_drvdata(hdev, sc); - sc->hdev = hdev; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - return ret; - } - - if (sc->quirks & VAIO_RDESC_CONSTANT) - connect_mask |= HID_CONNECT_HIDDEV_FORCE; - else if (sc->quirks & SIXAXIS_CONTROLLER) - connect_mask |= HID_CONNECT_HIDDEV_FORCE; - - ret = hid_hw_start(hdev, connect_mask); - if (ret) { - hid_err(hdev, "hw start failed\n"); - return ret; - } + int ret; ret = sony_set_device_id(sc); if (ret < 0) { @@ -2427,6 +2372,18 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) } } + /* + * The Dualshock 4 touchpad supports 2 touches and has a + * resolution of 1920x942 (44.86 dots/mm). + */ + ret = sony_register_touchpad(hidinput, 2, 1920, 942); + if (ret) { + hid_err(sc->hdev, + "Unable to initialize multi-touch slots: %d\n", + ret); + return ret; + } + sony_init_output_report(sc, dualshock4_send_output_report); } else if (sc->quirks & MOTION_CONTROLLER) { sony_init_output_report(sc, motion_send_output_report); @@ -2482,6 +2439,48 @@ err_stop: return ret; } +static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret; + unsigned long quirks = id->driver_data; + struct sony_sc *sc; + unsigned int connect_mask = HID_CONNECT_DEFAULT; + + if (!strcmp(hdev->name, "FutureMax Dance Mat")) + quirks |= FUTUREMAX_DANCE_MAT; + + sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); + if (sc == NULL) { + hid_err(hdev, "can't alloc sony descriptor\n"); + return -ENOMEM; + } + + spin_lock_init(&sc->lock); + + sc->quirks = quirks; + hid_set_drvdata(hdev, sc); + sc->hdev = hdev; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); + return ret; + } + + if (sc->quirks & VAIO_RDESC_CONSTANT) + connect_mask |= HID_CONNECT_HIDDEV_FORCE; + else if (sc->quirks & SIXAXIS_CONTROLLER) + connect_mask |= HID_CONNECT_HIDDEV_FORCE; + + ret = hid_hw_start(hdev, connect_mask); + if (ret) { + hid_err(hdev, "hw start failed\n"); + return ret; + } + + return ret; +} + static void sony_remove(struct hid_device *hdev) { struct sony_sc *sc = hid_get_drvdata(hdev); -- cgit v1.2.3 From 2c159de05082a70d3b3e75d8e167f4b5ca996405 Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Fri, 7 Oct 2016 12:39:35 -0700 Subject: HID: sony: Adjust HID report size name definitions Put the report type (feature / output) in the report size definitions. This prevents name collisions later on for other different reports, which use the same report id, but have a different size. Signed-off-by: Roderick Colenbrander Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index afa82198defb..43bb24cc5fc3 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1019,10 +1019,10 @@ struct motion_output_report_02 { u8 rumble; }; -#define DS4_REPORT_0x02_SIZE 37 -#define DS4_REPORT_0x05_SIZE 32 -#define DS4_REPORT_0x11_SIZE 78 -#define DS4_REPORT_0x81_SIZE 7 +#define DS4_FEATURE_REPORT_0x02_SIZE 37 +#define DS4_FEATURE_REPORT_0x81_SIZE 7 +#define DS4_OUTPUT_REPORT_0x05_SIZE 32 +#define DS4_OUTPUT_REPORT_0x11_SIZE 78 #define SIXAXIS_REPORT_0xF2_SIZE 17 #define SIXAXIS_REPORT_0xF5_SIZE 8 #define MOTION_REPORT_0x02_SIZE 49 @@ -1461,11 +1461,11 @@ static int dualshock4_set_operational_bt(struct hid_device *hdev) u8 *buf; int ret; - buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); + buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE, + ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); kfree(buf); @@ -1870,12 +1870,12 @@ static void dualshock4_send_output_report(struct sony_sc *sc) * 0xD0 - 66hz */ if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { - memset(buf, 0, DS4_REPORT_0x05_SIZE); + memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE); buf[0] = 0x05; buf[1] = 0xFF; offset = 4; } else { - memset(buf, 0, DS4_REPORT_0x11_SIZE); + memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE); buf[0] = 0x11; buf[1] = 0x80; buf[3] = 0x0F; @@ -1903,9 +1903,9 @@ static void dualshock4_send_output_report(struct sony_sc *sc) buf[offset++] = sc->led_delay_off[3]; if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) - hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE); + hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE); else - hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE, + hid_hw_raw_request(hdev, 0x11, buf, DS4_OUTPUT_REPORT_0x11_SIZE, HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); } @@ -1950,10 +1950,10 @@ static int sony_allocate_output_report(struct sony_sc *sc) kmalloc(sizeof(union sixaxis_output_report_01), GFP_KERNEL); else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) - sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE, + sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE, GFP_KERNEL); else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) - sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, + sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE, GFP_KERNEL); else if (sc->quirks & MOTION_CONTROLLER) sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, @@ -2198,7 +2198,7 @@ static int sony_check_add(struct sony_sc *sc) return 0; } } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { - buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL); + buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -2208,10 +2208,10 @@ static int sony_check_add(struct sony_sc *sc) * offset 1. */ ret = hid_hw_raw_request(sc->hdev, 0x81, buf, - DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT, + DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); - if (ret != DS4_REPORT_0x81_SIZE) { + if (ret != DS4_FEATURE_REPORT_0x81_SIZE) { hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); ret = ret < 0 ? ret : -EINVAL; goto out_free; -- cgit v1.2.3 From 49b9ca6c6c361a19d223ff84bd0ff871c01b528a Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Fri, 7 Oct 2016 12:39:36 -0700 Subject: HID: sony: Perform CRC check on bluetooth input packets Signed-off-by: Roderick Colenbrander Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 43bb24cc5fc3..34988ce9434a 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include "hid-ids.h" @@ -1021,6 +1023,7 @@ struct motion_output_report_02 { #define DS4_FEATURE_REPORT_0x02_SIZE 37 #define DS4_FEATURE_REPORT_0x81_SIZE 7 +#define DS4_INPUT_REPORT_0x11_SIZE 78 #define DS4_OUTPUT_REPORT_0x05_SIZE 32 #define DS4_OUTPUT_REPORT_0x11_SIZE 78 #define SIXAXIS_REPORT_0xF2_SIZE 17 @@ -1324,6 +1327,21 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && rd[0] == 0x11 && size == 78)) { + if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { + /* CRC check */ + u8 bthdr = 0xA1; + u32 crc; + u32 report_crc; + + crc = crc32_le(0xFFFFFFFF, &bthdr, 1); + crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4); + report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]); + if (crc != report_crc) { + hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n", + report_crc, crc); + return -EILSEQ; + } + } dualshock4_parse_report(sc, rd, size); } -- cgit v1.2.3 From e7ef53adbf47734e90f9fd6e2a7a57df6f1fbc6b Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Fri, 7 Oct 2016 12:39:37 -0700 Subject: HID: sony: Send ds4 output reports on output end-point Add a CRC value to each output report. This removes the need for the 'no output reports on interrupt end-point' quirk. Signed-off-by: Roderick Colenbrander Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 34988ce9434a..24f7d1937264 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1895,7 +1895,7 @@ static void dualshock4_send_output_report(struct sony_sc *sc) } else { memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE); buf[0] = 0x11; - buf[1] = 0x80; + buf[1] = 0xC0; /* HID + CRC */ buf[3] = 0x0F; offset = 6; } @@ -1922,9 +1922,16 @@ static void dualshock4_send_output_report(struct sony_sc *sc) if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE); - else - hid_hw_raw_request(hdev, 0x11, buf, DS4_OUTPUT_REPORT_0x11_SIZE, - HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); + else { + /* CRC generation */ + u8 bthdr = 0xA2; + u32 crc; + + crc = crc32_le(0xFFFFFFFF, &bthdr, 1); + crc = ~crc32_le(crc, buf, DS4_OUTPUT_REPORT_0x11_SIZE-4); + put_unaligned_le32(crc, &buf[74]); + hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x11_SIZE); + } } static void motion_send_output_report(struct sony_sc *sc) @@ -2378,11 +2385,6 @@ static int sony_input_configured(struct hid_device *hdev, sony_init_output_report(sc, sixaxis_send_output_report); } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { - /* - * The DualShock 4 wants output reports sent on the ctrl - * endpoint when connected via Bluetooth. - */ - hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; ret = dualshock4_set_operational_bt(hdev); if (ret < 0) { hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); -- cgit v1.2.3 From cdc1c0215ab449077cd160dde4fcd1c5f41dec6e Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Fri, 7 Oct 2016 12:39:38 -0700 Subject: HID: sony: Handle multiple touch events input record Read the touch history field in the HID descriptor and use this value to determine how many touch events to read from the report. As part of this patch, we did a first attempt of making the offset calculation code less magical. Signed-off-by: Roderick Colenbrander Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 78 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 24f7d1937264..b206d856d351 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1030,6 +1030,12 @@ struct motion_output_report_02 { #define SIXAXIS_REPORT_0xF5_SIZE 8 #define MOTION_REPORT_0x02_SIZE 49 +/* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an + * additional +2. + */ +#define DS4_INPUT_REPORT_BATTERY_OFFSET 30 +#define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33 + static DEFINE_SPINLOCK(sony_dev_list_lock); static LIST_HEAD(sony_device_list); static DEFINE_IDA(sony_device_id_allocator); @@ -1226,19 +1232,17 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) struct hid_input, list); struct input_dev *input_dev = hidinput->input; unsigned long flags; - int n, offset; + int n, m, offset, num_touch_data, max_touch_data; u8 cable_state, battery_capacity, battery_charging; - /* - * Battery and touchpad data starts at byte 30 in the USB report and - * 32 in Bluetooth report. - */ - offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32; + /* When using Bluetooth the header is 2 bytes longer, so skip these. */ + int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2; /* - * The lower 4 bits of byte 30 contain the battery level + * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level * and the 5th bit contains the USB cable state. */ + offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET; cable_state = (rd[offset] >> 4) & 0x01; battery_capacity = rd[offset] & 0x0F; @@ -1265,30 +1269,52 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) sc->battery_charging = battery_charging; spin_unlock_irqrestore(&sc->lock, flags); - offset += 5; - /* - * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB - * and 37 on Bluetooth. - * The first 7 bits of the first byte is a counter and bit 8 is a touch - * indicator that is 0 when pressed and 1 when not pressed. - * The next 3 bytes are two 12 bit touch coordinates, X and Y. - * The data for the second touch is in the same format and immediatly - * follows the data for the first. + * The Dualshock 4 multi-touch trackpad data starts at offset 33 on USB + * and 35 on Bluetooth. + * The first byte indicates the number of touch data in the report. + * Trackpad data starts 2 bytes later (e.g. 35 for USB). */ - for (n = 0; n < 2; n++) { - u16 x, y; + offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET; + max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 3 : 4; + if (rd[offset] > 0 && rd[offset] <= max_touch_data) + num_touch_data = rd[offset]; + else + num_touch_data = 1; + offset += 1; - x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); - y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); + for (m = 0; m < num_touch_data; m++) { + /* Skip past timestamp */ + offset += 1; - input_mt_slot(input_dev, n); - input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, - !(rd[offset] >> 7)); - input_report_abs(input_dev, ABS_MT_POSITION_X, x); - input_report_abs(input_dev, ABS_MT_POSITION_Y, y); + /* + * The first 7 bits of the first byte is a counter and bit 8 is + * a touch indicator that is 0 when pressed and 1 when not + * pressed. + * The next 3 bytes are two 12 bit touch coordinates, X and Y. + * The data for the second touch is in the same format and + * immediately follows the data for the first. + */ + for (n = 0; n < 2; n++) { + u16 x, y; + bool active; + + x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); + y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); + + active = !(rd[offset] >> 7); + input_mt_slot(input_dev, n); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, active); - offset += 4; + if (active) { + input_report_abs(input_dev, ABS_MT_POSITION_X, x); + input_report_abs(input_dev, ABS_MT_POSITION_Y, y); + } + + offset += 4; + } + input_mt_sync_frame(input_dev); + input_sync(input_dev); } } -- cgit v1.2.3 From bdae9e0e95364123fb7d372872bd7efd1760867c Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Fri, 7 Oct 2016 12:39:39 -0700 Subject: HID: sony: Adjust value range for motion sensors The motion sensor values are 16-bit, so make the value range match. It is hard to reach the upper values, but they can be reached. At least the current accelerometer value of 8192 is very easy to pass. It is still not nice that the motion sensors live in no man's land in between ABS_MISC and ABS_MT_SLOT, but that's something for another time, which the proposed ABS_ACCEL_*/ABS_GYRO_* were meant for. Signed-off-by: Roderick Colenbrander Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b206d856d351..bd847906c770 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -405,14 +405,14 @@ static u8 dualshock4_usb_rdesc[] = { 0x19, 0x40, /* Usage Minimum (40h), */ 0x29, 0x42, /* Usage Maximum (42h), */ 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ - 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 0x75, 0x10, /* Report Size (16), */ 0x95, 0x03, /* Report Count (3), */ 0x81, 0x02, /* Input (Variable), */ 0x19, 0x43, /* Usage Minimum (43h), */ 0x29, 0x45, /* Usage Maximum (45h), */ - 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ - 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 0x95, 0x03, /* Report Count (3), */ 0x81, 0x02, /* Input (Variable), */ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ @@ -714,14 +714,14 @@ static u8 dualshock4_bt_rdesc[] = { 0x19, 0x40, /* Usage Minimum (40h), */ 0x29, 0x42, /* Usage Maximum (42h), */ 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ - 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 0x75, 0x10, /* Report Size (16), */ 0x95, 0x03, /* Report Count (3), */ 0x81, 0x02, /* Input (Variable), */ 0x19, 0x43, /* Usage Minimum (43h), */ 0x29, 0x45, /* Usage Maximum (45h), */ - 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ - 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 0x95, 0x03, /* Report Count (3), */ 0x81, 0x02, /* Input (Variable), */ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ -- cgit v1.2.3 From cf1015d65d7c8a5504a4c03afb60fb86bff0f032 Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Fri, 7 Oct 2016 12:39:40 -0700 Subject: HID: sony: Update device ids Support additional DS4 model. Signed-off-by: Roderick Colenbrander Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 ++ drivers/hid/hid-ids.h | 1 + drivers/hid/hid-sony.c | 4 ++++ 3 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2b89c701076f..5ed2f572430f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2059,6 +2059,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index cd59c79eebdd..27f82cc4ada4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -899,6 +899,7 @@ #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 #define USB_DEVICE_ID_SONY_PS4_CONTROLLER 0x05c4 +#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc #define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index bd847906c770..14763cdf6393 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -2641,6 +2641,10 @@ static const struct hid_device_id sony_devices[] = { .driver_data = DUALSHOCK4_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), .driver_data = DUALSHOCK4_CONTROLLER_BT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), + .driver_data = DUALSHOCK4_CONTROLLER_USB }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), + .driver_data = DUALSHOCK4_CONTROLLER_BT }, /* Nyko Core Controller for PS3 */ { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER }, -- cgit v1.2.3 From 465350d0db06e280dfd7998392269358bba30813 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 11 Oct 2016 09:20:20 +0100 Subject: drm/i915: Remove self-harming shrink_all on get_pages_gtt fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we notice the system under memory pressure, we try to evict some driver pages before asking the VM to shrink all caches. As a final step in that process, we tried to evict everything, including active buffers. This is harming ourselves, and we can mix shrinking all caches as well as our residual buffers (after the first pass of trying to shrink just our own buffers). Signed-off-by: Chris Wilson Reviewed-by: Michał Winiarski Link: http://patchwork.freedesktop.org/patch/msgid/20161011082021.14606-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a89a88922448..ec0a3149baeb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2264,7 +2264,6 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) * our own buffer, now let the real VM do its job and * go down in flames if truly OOM. */ - i915_gem_shrink_all(dev_priv); page = shmem_read_mapping_page(mapping, i); if (IS_ERR(page)) { ret = PTR_ERR(page); -- cgit v1.2.3 From 871dfbd67d4ecbcc83fc9e80a310ca9bf3c44c40 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 11 Oct 2016 09:20:21 +0100 Subject: drm/i915: Allow compaction upto SWIOTLB max segment size commit 1625e7e549c5 ("drm/i915: make compact dma scatter lists creation work with SWIOTLB backend") took a heavy handed approach to undo the scatterlist compaction in the face of SWIOTLB. (The compaction hit a bug whereby we tried to pass a segment larger than SWIOTLB could handle.) We can be a little more intelligent and try compacting the scatterlist up to the maximum SWIOTLB segment size (when using SWIOTLB). v2: Tidy sg_mark_end() and cpp Signed-off-by: Chris Wilson CC: Imre Deak CC: Daniel Vetter Cc: Konrad Rzeszutek Wilk Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161011082021.14606-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ec0a3149baeb..9eb9ccdd8c8d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2208,6 +2208,15 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) return 0; } +static unsigned long swiotlb_max_size(void) +{ +#if IS_ENABLED(CONFIG_SWIOTLB) + return rounddown(swiotlb_nr_tbl() << IO_TLB_SHIFT, PAGE_SIZE); +#else + return 0; +#endif +} + static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) { @@ -2219,6 +2228,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) struct sgt_iter sgt_iter; struct page *page; unsigned long last_pfn = 0; /* suppress gcc warning */ + unsigned long max_segment; int ret; gfp_t gfp; @@ -2229,6 +2239,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); + max_segment = swiotlb_max_size(); + if (!max_segment) + max_segment = obj->base.size; + st = kmalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) return -ENOMEM; @@ -2270,15 +2284,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) goto err_pages; } } -#ifdef CONFIG_SWIOTLB - if (swiotlb_nr_tbl()) { - st->nents++; - sg_set_page(sg, page, PAGE_SIZE, 0); - sg = sg_next(sg); - continue; - } -#endif - if (!i || page_to_pfn(page) != last_pfn + 1) { + if (!i || + sg->length >= max_segment || + page_to_pfn(page) != last_pfn + 1) { if (i) sg = sg_next(sg); st->nents++; @@ -2291,9 +2299,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) /* Check that the i965g/gm workaround works. */ WARN_ON((gfp & __GFP_DMA32) && (last_pfn >= 0x00100000UL)); } -#ifdef CONFIG_SWIOTLB - if (!swiotlb_nr_tbl()) -#endif + if (sg) /* loop terminated early; short sg table */ sg_mark_end(sg); obj->pages = st; -- cgit v1.2.3 From 908b1232252edf6c7e29800e091cfbbb9f5f3570 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 11 Oct 2016 10:06:56 +0100 Subject: drm/i915: Convert open-coded use of vma_pages() If we want to know how many pages a VMA spans, we can use vma_pages() to find out. We have one such invocation inside our faulthandler, so convert it. (We have two other that want the size in bytes rather than pages, food for future thought.) Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161011090656.29554-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9eb9ccdd8c8d..fdd496e6c081 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1813,8 +1813,7 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf) view.params.partial.offset = rounddown(page_offset, chunk_size); view.params.partial.size = min_t(unsigned int, chunk_size, - (area->vm_end - area->vm_start) / PAGE_SIZE - - view.params.partial.offset); + vma_pages(area) - view.params.partial.offset); /* If the partial covers the entire object, just create a * normal VMA. -- cgit v1.2.3 From 6b1576aa875347c6454d911a2e001138c2cec7d5 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 10 Oct 2016 09:25:24 -0500 Subject: spi: Add Flag to Enable Slave Select with GPIO Chip Select. Some SPI masters require slave selection before the transfer can begin [1]. The SPI framework currently selects the chip using either 1) the internal CS mechanism or 2) the GPIO CS, but not both. This patch adds a new master->flags define to indicate both the GPIO CS and the internal chip select mechanism should be used. Tested On: Altera CycloneV development kit Compile tested for build errors on x86_64 (allyesconfigs) [1] DesignWare dw_apb_ssi Databook, Version 3.20a (page 39) Signed-off-by: Thor Thayer Signed-off-by: Mark Brown --- drivers/spi/spi.c | 9 +++++++-- include/linux/spi/spi.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8146ccd35a1a..8708da7c8140 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -697,10 +697,15 @@ static void spi_set_cs(struct spi_device *spi, bool enable) if (spi->mode & SPI_CS_HIGH) enable = !enable; - if (gpio_is_valid(spi->cs_gpio)) + if (gpio_is_valid(spi->cs_gpio)) { gpio_set_value(spi->cs_gpio, !enable); - else if (spi->master->set_cs) + /* Some SPI masters need both GPIO CS & slave_select */ + if ((spi->master->flags & SPI_MASTER_GPIO_SS) && + spi->master->set_cs) + spi->master->set_cs(spi, !enable); + } else if (spi->master->set_cs) { spi->master->set_cs(spi, !enable); + } } #ifdef CONFIG_HAS_DMA diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 4b743ac35396..75c6bd0ac605 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -442,6 +442,7 @@ struct spi_master { #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ #define SPI_MASTER_MUST_RX BIT(3) /* requires rx */ #define SPI_MASTER_MUST_TX BIT(4) /* requires tx */ +#define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */ /* * on some hardware transfer / message size may be constrained -- cgit v1.2.3 From 80b444e57948ea4bd5a89fb1f8c404ddab6c1973 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 10 Oct 2016 09:25:25 -0500 Subject: spi: dw: Set GPIO_SS flag to toggle Slave Select on GPIO CS The Designware SPI master requires slave selection before the transfer can begin [1]. This patch uses the new master flag to indicate both the GPIO CS and the internal chip select should be used. Tested On: Altera CycloneV development kit Compile tested for build errors on x86_64 (allyesconfigs) [1] DesignWare dw_apb_ssi Databook, Version 3.20a (page 39) Signed-off-by: Thor Thayer Signed-off-by: Mark Brown --- drivers/spi/spi-dw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 27960e46135d..b715a26a9148 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -502,6 +502,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) master->handle_err = dw_spi_handle_err; master->max_speed_hz = dws->max_freq; master->dev.of_node = dev->of_node; + master->flags = SPI_MASTER_GPIO_SS; /* Basic HW init */ spi_hw_init(dev, dws); -- cgit v1.2.3 From 6c26291d1fe50d7f237812e2ba4ff46337df281a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 10 Oct 2016 18:04:00 +0300 Subject: drm/i915/audio: abstract audio config update Prepare for using the same code for updating HSW_AUD_CFG register. No functional changes. Cc: Libin Yang Reviewed-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/56fe0662990289c647f998c11089133ca92ebb68.1476111629.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 68 ++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 1f168e27af10..d452e7b86053 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -245,6 +245,45 @@ static void g4x_audio_codec_enable(struct drm_connector *connector, I915_WRITE(G4X_AUD_CNTL_ST, tmp); } +static void hsw_audio_config_update(struct intel_crtc *intel_crtc, + enum port port, + const struct drm_display_mode *adjusted_mode) +{ + struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); + struct i915_audio_component *acomp = dev_priv->audio_component; + enum pipe pipe = intel_crtc->pipe; + int n, rate; + u32 tmp; + + tmp = I915_READ(HSW_AUD_CFG(pipe)); + tmp &= ~AUD_CONFIG_N_VALUE_INDEX; + tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; + if (intel_crtc_has_dp_encoder(intel_crtc->config)) + tmp |= AUD_CONFIG_N_VALUE_INDEX; + else + tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); + + tmp &= ~AUD_CONFIG_N_PROG_ENABLE; + if (audio_rate_need_prog(intel_crtc, adjusted_mode)) { + if (!acomp) + rate = 0; + else if (port >= PORT_A && port <= PORT_E) + rate = acomp->aud_sample_rate[port]; + else { + DRM_ERROR("invalid port: %d\n", port); + rate = 0; + } + + n = audio_config_get_n(adjusted_mode, rate); + if (n != 0) + tmp = audio_config_setup_n_reg(n, tmp); + else + DRM_DEBUG_KMS("no suitable N value is found\n"); + } + + I915_WRITE(HSW_AUD_CFG(pipe), tmp); +} + static void hsw_audio_codec_disable(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -283,11 +322,9 @@ static void hsw_audio_codec_enable(struct drm_connector *connector, struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); enum pipe pipe = intel_crtc->pipe; enum port port = intel_encoder->port; - struct i915_audio_component *acomp = dev_priv->audio_component; const uint8_t *eld = connector->eld; uint32_t tmp; int len, i; - int n, rate; DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n", pipe_name(pipe), drm_eld_size(eld)); @@ -323,32 +360,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector, I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); /* Enable timestamps */ - tmp = I915_READ(HSW_AUD_CFG(pipe)); - tmp &= ~AUD_CONFIG_N_VALUE_INDEX; - tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; - if (intel_crtc_has_dp_encoder(intel_crtc->config)) - tmp |= AUD_CONFIG_N_VALUE_INDEX; - else - tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); - - tmp &= ~AUD_CONFIG_N_PROG_ENABLE; - if (audio_rate_need_prog(intel_crtc, adjusted_mode)) { - if (!acomp) - rate = 0; - else if (port >= PORT_A && port <= PORT_E) - rate = acomp->aud_sample_rate[port]; - else { - DRM_ERROR("invalid port: %d\n", port); - rate = 0; - } - n = audio_config_get_n(adjusted_mode, rate); - if (n != 0) - tmp = audio_config_setup_n_reg(n, tmp); - else - DRM_DEBUG_KMS("no suitable N value is found\n"); - } - - I915_WRITE(HSW_AUD_CFG(pipe), tmp); + hsw_audio_config_update(intel_crtc, port, adjusted_mode); mutex_unlock(&dev_priv->av_mutex); } -- cgit v1.2.3 From 3af306d905b530bf076a983b14af23d133772eea Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 10 Oct 2016 18:04:01 +0300 Subject: drm/i915/audio: port is going to be just fine, simplify checks If it was wrong, we'd be screwed already. Cc: Libin Yang Reviewed-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/8cf454ccefc05b234aa81c45a4ce9018e7c9324f.1476111629.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index d452e7b86053..58a222f36a87 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -251,8 +251,9 @@ static void hsw_audio_config_update(struct intel_crtc *intel_crtc, { struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); struct i915_audio_component *acomp = dev_priv->audio_component; + int rate = acomp ? acomp->aud_sample_rate[port] : 0; enum pipe pipe = intel_crtc->pipe; - int n, rate; + int n; u32 tmp; tmp = I915_READ(HSW_AUD_CFG(pipe)); @@ -265,15 +266,6 @@ static void hsw_audio_config_update(struct intel_crtc *intel_crtc, tmp &= ~AUD_CONFIG_N_PROG_ENABLE; if (audio_rate_need_prog(intel_crtc, adjusted_mode)) { - if (!acomp) - rate = 0; - else if (port >= PORT_A && port <= PORT_E) - rate = acomp->aud_sample_rate[port]; - else { - DRM_ERROR("invalid port: %d\n", port); - rate = 0; - } - n = audio_config_get_n(adjusted_mode, rate); if (n != 0) tmp = audio_config_setup_n_reg(n, tmp); -- cgit v1.2.3 From 8f1ec181b12e8ac04e9690f1b122a6779ad2acc2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 10 Oct 2016 18:04:02 +0300 Subject: drm/i915/audio: use the same code for updating audio config It gets fragile to duplicate the code for updating HSW_AUD_CFG. The only change should be that the hdmi pixel clock is also updated in i915_audio_component_sync_audio_rate(), but it should not be any different. Cc: Libin Yang Reviewed-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/e0e88ec00c0ed1734083153b55283efd3116be5c.1476111629.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 58a222f36a87..c8336db298b3 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -671,10 +671,8 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_encoder *intel_encoder; struct intel_crtc *crtc; - struct drm_display_mode *mode; + struct drm_display_mode *adjusted_mode; struct i915_audio_component *acomp = dev_priv->audio_component; - u32 tmp; - int n; int err = 0; /* HSW, BDW, SKL, KBL need this fix */ @@ -700,33 +698,12 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, crtc = to_intel_crtc(intel_encoder->base.crtc); pipe = crtc->pipe; - mode = &crtc->config->base.adjusted_mode; + adjusted_mode = &crtc->config->base.adjusted_mode; /* port must be valid now, otherwise the pipe will be invalid */ acomp->aud_sample_rate[port] = rate; - /* 2. check whether to set the N/CTS/M manually or not */ - if (!audio_rate_need_prog(crtc, mode)) { - tmp = I915_READ(HSW_AUD_CFG(pipe)); - tmp &= ~AUD_CONFIG_N_PROG_ENABLE; - I915_WRITE(HSW_AUD_CFG(pipe), tmp); - goto unlock; - } - - n = audio_config_get_n(mode, rate); - if (n == 0) { - DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n", - port_name(port)); - tmp = I915_READ(HSW_AUD_CFG(pipe)); - tmp &= ~AUD_CONFIG_N_PROG_ENABLE; - I915_WRITE(HSW_AUD_CFG(pipe), tmp); - goto unlock; - } - - /* 3. set the N/CTS/M */ - tmp = I915_READ(HSW_AUD_CFG(pipe)); - tmp = audio_config_setup_n_reg(n, tmp); - I915_WRITE(HSW_AUD_CFG(pipe), tmp); + hsw_audio_config_update(crtc, port, adjusted_mode); unlock: mutex_unlock(&dev_priv->av_mutex); -- cgit v1.2.3 From 12e87f23c6278eda2fec540f078e08f1ad63b4fe Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 10 Oct 2016 18:04:03 +0300 Subject: drm/i915/audio: split dp and hdmi audio config update The code for dp and hdmi are already different, and they're about to diverge even more. Split them for clarity in future work. No functional changes. Cc: Libin Yang Reviewed-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/41b8e24fed92effafaef69675ddabfa2008b4d31.1476111629.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 55 +++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index c8336db298b3..dcbe6b9cbc43 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -148,18 +148,6 @@ static uint32_t audio_config_setup_n_reg(int n, uint32_t val) return tmp; } -/* check whether N/CTS/M need be set manually */ -static bool audio_rate_need_prog(struct intel_crtc *crtc, - const struct drm_display_mode *mode) -{ - if (((mode->clock == TMDS_297M) || - (mode->clock == TMDS_296M)) && - intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) - return true; - else - return false; -} - static bool intel_eld_uptodate(struct drm_connector *connector, i915_reg_t reg_eldv, uint32_t bits_eldv, i915_reg_t reg_elda, uint32_t bits_elda, @@ -245,9 +233,26 @@ static void g4x_audio_codec_enable(struct drm_connector *connector, I915_WRITE(G4X_AUD_CNTL_ST, tmp); } -static void hsw_audio_config_update(struct intel_crtc *intel_crtc, - enum port port, - const struct drm_display_mode *adjusted_mode) +static void +hsw_dp_audio_config_update(struct intel_crtc *intel_crtc, enum port port, + const struct drm_display_mode *adjusted_mode) +{ + struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); + enum pipe pipe = intel_crtc->pipe; + u32 tmp; + + tmp = I915_READ(HSW_AUD_CFG(pipe)); + tmp &= ~AUD_CONFIG_N_VALUE_INDEX; + tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; + tmp &= ~AUD_CONFIG_N_PROG_ENABLE; + tmp |= AUD_CONFIG_N_VALUE_INDEX; + + I915_WRITE(HSW_AUD_CFG(pipe), tmp); +} + +static void +hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, + const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); struct i915_audio_component *acomp = dev_priv->audio_component; @@ -259,13 +264,11 @@ static void hsw_audio_config_update(struct intel_crtc *intel_crtc, tmp = I915_READ(HSW_AUD_CFG(pipe)); tmp &= ~AUD_CONFIG_N_VALUE_INDEX; tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; - if (intel_crtc_has_dp_encoder(intel_crtc->config)) - tmp |= AUD_CONFIG_N_VALUE_INDEX; - else - tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); - tmp &= ~AUD_CONFIG_N_PROG_ENABLE; - if (audio_rate_need_prog(intel_crtc, adjusted_mode)) { + tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); + + if (adjusted_mode->clock == TMDS_296M || + adjusted_mode->clock == TMDS_297M) { n = audio_config_get_n(adjusted_mode, rate); if (n != 0) tmp = audio_config_setup_n_reg(n, tmp); @@ -276,6 +279,16 @@ static void hsw_audio_config_update(struct intel_crtc *intel_crtc, I915_WRITE(HSW_AUD_CFG(pipe), tmp); } +static void +hsw_audio_config_update(struct intel_crtc *intel_crtc, enum port port, + const struct drm_display_mode *adjusted_mode) +{ + if (intel_crtc_has_dp_encoder(intel_crtc->config)) + hsw_dp_audio_config_update(intel_crtc, port, adjusted_mode); + else + hsw_hdmi_audio_config_update(intel_crtc, port, adjusted_mode); +} + static void hsw_audio_codec_disable(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); -- cgit v1.2.3 From 4bd2d6f680e39a910f76b50ba21ad22bc6177628 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 10 Oct 2016 18:04:04 +0300 Subject: drm/i915/audio: set proper N/MCTS on more platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch applies setting proper N/M, N/CTS on more platforms. Reviewed-by: Ville Syrjälä Signed-off-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/073f8aaf302df1b638dd33b0ddf46930bcdfea99.1476111629.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index dcbe6b9cbc43..8f6cc15ca39c 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -688,11 +688,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, struct i915_audio_component *acomp = dev_priv->audio_component; int err = 0; - /* HSW, BDW, SKL, KBL need this fix */ - if (!IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv) && - !IS_BROADWELL(dev_priv) && - !IS_HASWELL(dev_priv)) + if (!HAS_DDI(dev_priv)) return 0; i915_audio_component_get_power(kdev); -- cgit v1.2.3 From a7c4efbfbe45f7f9e09bc6ff27e9762b89354449 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 10 Oct 2016 18:04:05 +0300 Subject: drm/i915/audio: HDMI audio gets the TMDS clock by crtc_clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDMI audio should use crtc_clock to get the TMDS clock. This patch renames mode to adjusted_mode to unify the name. Reviewed-by: Ville Syrjälä Signed-off-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/8945ac6bdae9c63a563bdd60b44dd316254e4752.1476111629.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 8f6cc15ca39c..34f55f2f44d7 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -121,13 +121,14 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted return hdmi_audio_clock[i].config; } -static int audio_config_get_n(const struct drm_display_mode *mode, int rate) +static int audio_config_get_n(const struct drm_display_mode *adjusted_mode, + int rate) { int i; for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) { if ((rate == aud_ncts[i].sample_rate) && - (mode->clock == aud_ncts[i].clock)) { + (adjusted_mode->crtc_clock == aud_ncts[i].clock)) { return aud_ncts[i].n; } } @@ -267,8 +268,8 @@ hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, tmp &= ~AUD_CONFIG_N_PROG_ENABLE; tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); - if (adjusted_mode->clock == TMDS_296M || - adjusted_mode->clock == TMDS_297M) { + if (adjusted_mode->crtc_clock == TMDS_296M || + adjusted_mode->crtc_clock == TMDS_297M) { n = audio_config_get_n(adjusted_mode, rate); if (n != 0) tmp = audio_config_setup_n_reg(n, tmp); -- cgit v1.2.3 From 2561389a128cd15e97036b209856e53a546df9b7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 10 Oct 2016 18:04:06 +0300 Subject: drm/i915/audio: add register macros for audio config N value Have generic macros in line with the rest of the register bit definition macros instead of a dedicated function in intel_audio.c, and use them. No functional changes. Cc: Libin Yang Reviewed-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/c8709b065ba5cb91b85c54f4e099219e4e68b192.1476111629.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_audio.c | 23 ++++++----------------- 2 files changed, 10 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index acc767a52d8e..595d196f753f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7332,6 +7332,10 @@ enum { #define AUD_CONFIG_UPPER_N_MASK (0xff << 20) #define AUD_CONFIG_LOWER_N_SHIFT 4 #define AUD_CONFIG_LOWER_N_MASK (0xfff << 4) +#define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK) +#define AUD_CONFIG_N(n) \ + (((((n) >> 12) & 0xff) << AUD_CONFIG_UPPER_N_SHIFT) | \ + (((n) & 0xfff) << AUD_CONFIG_LOWER_N_SHIFT)) #define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 #define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16) #define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 34f55f2f44d7..db46ead0c28c 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -135,20 +135,6 @@ static int audio_config_get_n(const struct drm_display_mode *adjusted_mode, return 0; } -static uint32_t audio_config_setup_n_reg(int n, uint32_t val) -{ - int n_low, n_up; - uint32_t tmp = val; - - n_low = n & 0xfff; - n_up = (n >> 12) & 0xff; - tmp &= ~(AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK); - tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) | - (n_low << AUD_CONFIG_LOWER_N_SHIFT) | - AUD_CONFIG_N_PROG_ENABLE); - return tmp; -} - static bool intel_eld_uptodate(struct drm_connector *connector, i915_reg_t reg_eldv, uint32_t bits_eldv, i915_reg_t reg_elda, uint32_t bits_elda, @@ -271,10 +257,13 @@ hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, if (adjusted_mode->crtc_clock == TMDS_296M || adjusted_mode->crtc_clock == TMDS_297M) { n = audio_config_get_n(adjusted_mode, rate); - if (n != 0) - tmp = audio_config_setup_n_reg(n, tmp); - else + if (n != 0) { + tmp &= ~AUD_CONFIG_N_MASK; + tmp |= AUD_CONFIG_N(n); + tmp |= AUD_CONFIG_N_PROG_ENABLE; + } else { DRM_DEBUG_KMS("no suitable N value is found\n"); + } } I915_WRITE(HSW_AUD_CFG(pipe), tmp); -- cgit v1.2.3 From 9eeb7304f3ae300c3a0dda6ff84cc7c3c8053fa0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 10 Oct 2016 18:04:07 +0300 Subject: drm/i915/audio: rename N value getter to emphasize it's for hdmi We'll be getting a function and a table for dp parameters soon enough, so rename the function and table for hdmi. No functional changes. Cc: Libin Yang Reviewed-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/3d1c61cab70b6a2966db9b6115b76edbd747a835.1476111629.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index db46ead0c28c..904e7c36c79c 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -81,7 +81,7 @@ static const struct { int clock; int n; int cts; -} aud_ncts[] = { +} hdmi_aud_ncts[] = { { 44100, TMDS_296M, 4459, 234375 }, { 44100, TMDS_297M, 4704, 247500 }, { 48000, TMDS_296M, 5824, 281250 }, @@ -121,15 +121,15 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted return hdmi_audio_clock[i].config; } -static int audio_config_get_n(const struct drm_display_mode *adjusted_mode, - int rate) +static int audio_config_hdmi_get_n(const struct drm_display_mode *adjusted_mode, + int rate) { int i; - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) { - if ((rate == aud_ncts[i].sample_rate) && - (adjusted_mode->crtc_clock == aud_ncts[i].clock)) { - return aud_ncts[i].n; + for (i = 0; i < ARRAY_SIZE(hdmi_aud_ncts); i++) { + if (rate == hdmi_aud_ncts[i].sample_rate && + adjusted_mode->crtc_clock == hdmi_aud_ncts[i].clock) { + return hdmi_aud_ncts[i].n; } } return 0; @@ -256,7 +256,7 @@ hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, if (adjusted_mode->crtc_clock == TMDS_296M || adjusted_mode->crtc_clock == TMDS_297M) { - n = audio_config_get_n(adjusted_mode, rate); + n = audio_config_hdmi_get_n(adjusted_mode, rate); if (n != 0) { tmp &= ~AUD_CONFIG_N_MASK; tmp |= AUD_CONFIG_N(n); -- cgit v1.2.3 From 5a920b85f2c6e3fd7d9dd9bb3f3345e9085e2360 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 4 Oct 2016 14:37:32 -0300 Subject: drm/i915/gen9: fix DDB partitioning for multi-screen cases With the previous code we were only recomputing the DDB partitioning for the CRTCs included in the atomic commit, so any other active CRTCs would end up having their DDB registers zeroed. In this patch we make sure that the computed state starts as a copy of the current partitioning, and then we only zero the DDBs that we're actually going to recompute. How to reproduce the bug: 1 - Enable the primary plane on pipe A 2 - Enable the primary plane on pipe B 3 - Enable the cursor or sprite plane on pipe A Step 3 will zero the DDB partitioning for pipe B since it's not included in the commit that enabled the cursor or sprite for pipe A. I expect this to fix many FIFO underrun problems on gen9+. v2: - Mention the cursor on the steps to reproduce the problem (Paulo). - Add Testcase tag provided by Maarten (Maarten). Testcase: kms_cursor_legacy.cursorA-vs-flipB-atomic-transitions Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96226 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96828 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97450 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97596 Bugzilla: https://www.phoronix.com/scan.php?page=news_item&px=Intel-Skylake-Multi-Screen-Woes Cc: stable@vger.kernel.org Signed-off-by: Paulo Zanoni Reviewed-by: Lyude Link: http://patchwork.freedesktop.org/patch/msgid/1475602652-17326-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7f1748a1e614..fe6c1c61c388 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3362,13 +3362,15 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, int num_active; int id, i; + /* Clear the partitioning for disabled planes. */ + memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); + memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); + if (WARN_ON(!state)) return 0; if (!cstate->base.active) { ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0; - memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); - memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); return 0; } @@ -4054,6 +4056,12 @@ skl_compute_ddb(struct drm_atomic_state *state) intel_state->wm_results.dirty_pipes = ~0; } + /* + * We're not recomputing for the pipes not included in the commit, so + * make sure we start with the current state. + */ + memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb)); + for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { struct intel_crtc_state *cstate; -- cgit v1.2.3 From 569906e2032ebbdd56e820ba60368cd803234cec Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 8 Oct 2016 14:34:24 +0200 Subject: iio: accel: Add driver for dmard10 3-axis Accelerometer Add a driver for the Domintech ARD10 3-axis Accelerometer, based on the android driver found here: https://github.com/domintech/dmard10 Signed-off-by: Hans de Goede Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/i2c/trivial-devices.txt | 1 + drivers/iio/accel/Kconfig | 10 + drivers/iio/accel/Makefile | 1 + drivers/iio/accel/dmard10.c | 266 +++++++++++++++++++++ 4 files changed, 278 insertions(+) create mode 100644 drivers/iio/accel/dmard10.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index fc78f9a68bf0..b0a43955852c 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -39,6 +39,7 @@ dallas,ds75 Digital Thermometer and Thermostat dlg,da9053 DA9053: flexible system level PMIC with multicore support dlg,da9063 DA9063: system PMIC for quad-core application processors domintech,dmard09 DMARD09: 3-axis Accelerometer +domintech,dmard10 DMARD10: 3-axis Accelerometer epson,rx8010 I2C-BUS INTERFACE REAL TIME CLOCK MODULE epson,rx8025 High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 2b791fe1e2bc..d59cfe7d4e5b 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -73,6 +73,16 @@ config DMARD09 Choosing M will build the driver as a module. If so, the module will be called dmard09. +config DMARD10 + tristate "Domintech DMARD10 3-axis Accelerometer Driver" + depends on I2C + help + Say yes here to get support for the Domintech DMARD10 3-axis + accelerometer. + + Choosing M will build the driver as a module. If so, the module + will be called dmard10. + config HID_SENSOR_ACCEL_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index f5d3ddee619e..cb0e04b2dcb6 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o obj-$(CONFIG_DMARD06) += dmard06.o obj-$(CONFIG_DMARD09) += dmard09.o +obj-$(CONFIG_DMARD10) += dmard10.o obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c new file mode 100644 index 000000000000..b8736cc75656 --- /dev/null +++ b/drivers/iio/accel/dmard10.c @@ -0,0 +1,266 @@ +/** + * IIO driver for the 3-axis accelerometer Domintech ARD10. + * + * Copyright (c) 2016 Hans de Goede + * Copyright (c) 2012 Domintech Technology Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#define DMARD10_REG_ACTR 0x00 +#define DMARD10_REG_AFEM 0x0c +#define DMARD10_REG_STADR 0x12 +#define DMARD10_REG_STAINT 0x1c +#define DMARD10_REG_MISC2 0x1f +#define DMARD10_REG_PD 0x21 + +#define DMARD10_MODE_OFF 0x00 +#define DMARD10_MODE_STANDBY 0x02 +#define DMARD10_MODE_ACTIVE 0x06 +#define DMARD10_MODE_READ_OTP 0x12 +#define DMARD10_MODE_RESET_DATA_PATH 0x82 + +/* AFEN set 1, ATM[2:0]=b'000 (normal), EN_Z/Y/X/T=1 */ +#define DMARD10_VALUE_AFEM_AFEN_NORMAL 0x8f +/* ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ) */ +#define DMARD10_VALUE_CKSEL_ODR_100_204 0x74 +/* INTC[6:5]=b'00 */ +#define DMARD10_VALUE_INTC 0x00 +/* TAP1/TAP2 Average 2 */ +#define DMARD10_VALUE_TAPNS_AVE_2 0x11 + +#define DMARD10_VALUE_STADR 0x55 +#define DMARD10_VALUE_STAINT 0xaa +#define DMARD10_VALUE_MISC2_OSCA_EN 0x08 +#define DMARD10_VALUE_PD_RST 0x52 + +/* Offsets into the buffer read in dmard10_read_raw() */ +#define DMARD10_X_OFFSET 1 +#define DMARD10_Y_OFFSET 2 +#define DMARD10_Z_OFFSET 3 + +/* + * a value of + or -128 corresponds to + or - 1G + * scale = 9.81 / 128 = 0.076640625 + */ + +static const int dmard10_nscale = 76640625; + +#define DMARD10_CHANNEL(reg, axis) { \ + .type = IIO_ACCEL, \ + .address = reg, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec dmard10_channels[] = { + DMARD10_CHANNEL(DMARD10_X_OFFSET, X), + DMARD10_CHANNEL(DMARD10_Y_OFFSET, Y), + DMARD10_CHANNEL(DMARD10_Z_OFFSET, Z), +}; + +struct dmard10_data { + struct i2c_client *client; +}; + +/* Init sequence taken from the android driver */ +static int dmard10_reset(struct i2c_client *client) +{ + unsigned char buffer[7]; + int ret; + + /* 1. Powerdown reset */ + ret = i2c_smbus_write_byte_data(client, DMARD10_REG_PD, + DMARD10_VALUE_PD_RST); + if (ret < 0) + return ret; + + /* + * 2. ACTR => Standby mode => Download OTP to parameter reg => + * Standby mode => Reset data path => Standby mode + */ + buffer[0] = DMARD10_REG_ACTR; + buffer[1] = DMARD10_MODE_STANDBY; + buffer[2] = DMARD10_MODE_READ_OTP; + buffer[3] = DMARD10_MODE_STANDBY; + buffer[4] = DMARD10_MODE_RESET_DATA_PATH; + buffer[5] = DMARD10_MODE_STANDBY; + ret = i2c_master_send(client, buffer, 6); + if (ret < 0) + return ret; + + /* 3. OSCA_EN = 1, TSTO = b'000 (INT1 = normal, TEST0 = normal) */ + ret = i2c_smbus_write_byte_data(client, DMARD10_REG_MISC2, + DMARD10_VALUE_MISC2_OSCA_EN); + if (ret < 0) + return ret; + + /* 4. AFEN = 1 (AFE will powerdown after ADC) */ + buffer[0] = DMARD10_REG_AFEM; + buffer[1] = DMARD10_VALUE_AFEM_AFEN_NORMAL; + buffer[2] = DMARD10_VALUE_CKSEL_ODR_100_204; + buffer[3] = DMARD10_VALUE_INTC; + buffer[4] = DMARD10_VALUE_TAPNS_AVE_2; + buffer[5] = 0x00; /* DLYC, no delay timing */ + buffer[6] = 0x07; /* INTD=1 push-pull, INTA=1 active high, AUTOT=1 */ + ret = i2c_master_send(client, buffer, 7); + if (ret < 0) + return ret; + + /* 5. Activation mode */ + ret = i2c_smbus_write_byte_data(client, DMARD10_REG_ACTR, + DMARD10_MODE_ACTIVE); + if (ret < 0) + return ret; + + return 0; +} + +/* Shutdown sequence taken from the android driver */ +static int dmard10_shutdown(struct i2c_client *client) +{ + unsigned char buffer[3]; + + buffer[0] = DMARD10_REG_ACTR; + buffer[1] = DMARD10_MODE_STANDBY; + buffer[2] = DMARD10_MODE_OFF; + + return i2c_master_send(client, buffer, 3); +} + +static int dmard10_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct dmard10_data *data = iio_priv(indio_dev); + __le16 buf[4]; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + /* + * Read 8 bytes starting at the REG_STADR register, trying to + * read the individual X, Y, Z registers will always read 0. + */ + ret = i2c_smbus_read_i2c_block_data(data->client, + DMARD10_REG_STADR, + sizeof(buf), (u8 *)buf); + if (ret < 0) + return ret; + ret = le16_to_cpu(buf[chan->address]); + *val = sign_extend32(ret, 12); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = dmard10_nscale; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static const struct iio_info dmard10_info = { + .driver_module = THIS_MODULE, + .read_raw = dmard10_read_raw, +}; + +static int dmard10_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct dmard10_data *data; + + /* These 2 registers have special POR reset values used for id */ + ret = i2c_smbus_read_byte_data(client, DMARD10_REG_STADR); + if (ret != DMARD10_VALUE_STADR) + return (ret < 0) ? ret : -ENODEV; + + ret = i2c_smbus_read_byte_data(client, DMARD10_REG_STAINT); + if (ret != DMARD10_VALUE_STAINT) + return (ret < 0) ? ret : -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) { + dev_err(&client->dev, "iio allocation failed!\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &dmard10_info; + indio_dev->name = "dmard10"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = dmard10_channels; + indio_dev->num_channels = ARRAY_SIZE(dmard10_channels); + + ret = dmard10_reset(client); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "device_register failed\n"); + dmard10_shutdown(client); + } + + return ret; +} + +static int dmard10_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + + return dmard10_shutdown(client); +} + +#ifdef CONFIG_PM_SLEEP +static int dmard10_suspend(struct device *dev) +{ + return dmard10_shutdown(to_i2c_client(dev)); +} + +static int dmard10_resume(struct device *dev) +{ + return dmard10_reset(to_i2c_client(dev)); +} +#endif + +static SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend, dmard10_resume); + +static const struct i2c_device_id dmard10_i2c_id[] = { + {"dmard10", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id); + +static struct i2c_driver dmard10_driver = { + .driver = { + .name = "dmard10", + .pm = &dmard10_pm_ops, + }, + .probe = dmard10_probe, + .remove = dmard10_remove, + .id_table = dmard10_i2c_id, +}; + +module_i2c_driver(dmard10_driver); + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("Domintech ARD10 3-Axis Accelerometer driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 598893e9cb64d9c74152db6174c4d7a6036a84e8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 8 Oct 2016 14:34:25 +0200 Subject: iio: accel: Add driver for the MiraMEMS DA311 3-axis 12-bit digital accelerometer This driver is based on the DA311 Android driver which can be found here: https://git.matricom.net/Firmware/kernel_amlogic_meson-common/tree/1e70113a5befd07debb68f537156def84c5be57a/drivers/amlogic/input/sensor the mir3da_* files are the DA311 driver. Unfortunately there is no datasheet. Signed-off-by: Hans de Goede Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/i2c/trivial-devices.txt | 1 + drivers/iio/accel/Kconfig | 10 + drivers/iio/accel/Makefile | 1 + drivers/iio/accel/da311.c | 305 +++++++++++++++++++++ 4 files changed, 317 insertions(+) create mode 100644 drivers/iio/accel/da311.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index b0a43955852c..decdd3e636bf 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -125,6 +125,7 @@ microchip,mcp4662-502 Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem microchip,mcp4662-103 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k) microchip,mcp4662-503 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k) microchip,mcp4662-104 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k) +miramems,da311 MiraMEMS DA311 3-axis 12-bit digital accelerometer national,lm63 Temperature sensor with integrated fan control national,lm75 I2C TEMP SENSOR national,lm80 Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index d59cfe7d4e5b..8945e70a797c 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -52,6 +52,16 @@ config BMC150_ACCEL_SPI tristate select REGMAP_SPI +config DA311 + tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver" + depends on I2C + help + Say yes here to build support for the MiraMEMS DA311 3-axis 12-bit + digital accelerometer. + + To compile this driver as a module, choose M here: the + module will be called da311. + config DMARD06 tristate "Domintech DMARD06 Digital Accelerometer Driver" depends on OF || COMPILE_TEST diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index cb0e04b2dcb6..ade13ae5d056 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o +obj-$(CONFIG_DA311) += da311.o obj-$(CONFIG_DMARD06) += dmard06.o obj-$(CONFIG_DMARD09) += dmard09.o obj-$(CONFIG_DMARD10) += dmard10.o diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c new file mode 100644 index 000000000000..537cfa8b6edf --- /dev/null +++ b/drivers/iio/accel/da311.c @@ -0,0 +1,305 @@ +/** + * IIO driver for the MiraMEMS DA311 3-axis accelerometer + * + * Copyright (c) 2016 Hans de Goede + * Copyright (c) 2011-2013 MiraMEMS Sensing Technology Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#define DA311_CHIP_ID 0x13 + +/* + * Note register addressed go from 0 - 0x3f and then wrap. + * For some reason there are 2 banks with 0 - 0x3f addresses, + * rather then a single 0-0x7f bank. + */ + +/* Bank 0 regs */ +#define DA311_REG_BANK 0x0000 +#define DA311_REG_LDO_REG 0x0006 +#define DA311_REG_CHIP_ID 0x000f +#define DA311_REG_TEMP_CFG_REG 0x001f +#define DA311_REG_CTRL_REG1 0x0020 +#define DA311_REG_CTRL_REG3 0x0022 +#define DA311_REG_CTRL_REG4 0x0023 +#define DA311_REG_CTRL_REG5 0x0024 +#define DA311_REG_CTRL_REG6 0x0025 +#define DA311_REG_STATUS_REG 0x0027 +#define DA311_REG_OUT_X_L 0x0028 +#define DA311_REG_OUT_X_H 0x0029 +#define DA311_REG_OUT_Y_L 0x002a +#define DA311_REG_OUT_Y_H 0x002b +#define DA311_REG_OUT_Z_L 0x002c +#define DA311_REG_OUT_Z_H 0x002d +#define DA311_REG_INT1_CFG 0x0030 +#define DA311_REG_INT1_SRC 0x0031 +#define DA311_REG_INT1_THS 0x0032 +#define DA311_REG_INT1_DURATION 0x0033 +#define DA311_REG_INT2_CFG 0x0034 +#define DA311_REG_INT2_SRC 0x0035 +#define DA311_REG_INT2_THS 0x0036 +#define DA311_REG_INT2_DURATION 0x0037 +#define DA311_REG_CLICK_CFG 0x0038 +#define DA311_REG_CLICK_SRC 0x0039 +#define DA311_REG_CLICK_THS 0x003a +#define DA311_REG_TIME_LIMIT 0x003b +#define DA311_REG_TIME_LATENCY 0x003c +#define DA311_REG_TIME_WINDOW 0x003d + +/* Bank 1 regs */ +#define DA311_REG_SOFT_RESET 0x0105 +#define DA311_REG_OTP_XOFF_L 0x0110 +#define DA311_REG_OTP_XOFF_H 0x0111 +#define DA311_REG_OTP_YOFF_L 0x0112 +#define DA311_REG_OTP_YOFF_H 0x0113 +#define DA311_REG_OTP_ZOFF_L 0x0114 +#define DA311_REG_OTP_ZOFF_H 0x0115 +#define DA311_REG_OTP_XSO 0x0116 +#define DA311_REG_OTP_YSO 0x0117 +#define DA311_REG_OTP_ZSO 0x0118 +#define DA311_REG_OTP_TRIM_OSC 0x011b +#define DA311_REG_LPF_ABSOLUTE 0x011c +#define DA311_REG_TEMP_OFF1 0x0127 +#define DA311_REG_TEMP_OFF2 0x0128 +#define DA311_REG_TEMP_OFF3 0x0129 +#define DA311_REG_OTP_TRIM_THERM_H 0x011a + +/* + * a value of + or -1024 corresponds to + or - 1G + * scale = 9.81 / 1024 = 0.009580078 + */ + +static const int da311_nscale = 9580078; + +#define DA311_CHANNEL(reg, axis) { \ + .type = IIO_ACCEL, \ + .address = reg, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec da311_channels[] = { + /* | 0x80 comes from the android driver */ + DA311_CHANNEL(DA311_REG_OUT_X_L | 0x80, X), + DA311_CHANNEL(DA311_REG_OUT_Y_L | 0x80, Y), + DA311_CHANNEL(DA311_REG_OUT_Z_L | 0x80, Z), +}; + +struct da311_data { + struct i2c_client *client; +}; + +static int da311_register_mask_write(struct i2c_client *client, u16 addr, + u8 mask, u8 data) +{ + int ret; + u8 tmp_data = 0; + + if (addr & 0xff00) { + /* Select bank 1 */ + ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x01); + if (ret < 0) + return ret; + } + + if (mask != 0xff) { + ret = i2c_smbus_read_byte_data(client, addr); + if (ret < 0) + return ret; + tmp_data = ret; + } + + tmp_data &= ~mask; + tmp_data |= data & mask; + ret = i2c_smbus_write_byte_data(client, addr & 0xff, tmp_data); + if (ret < 0) + return ret; + + if (addr & 0xff00) { + /* Back to bank 0 */ + ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x00); + if (ret < 0) + return ret; + } + + return 0; +} + +/* Init sequence taken from the android driver */ +static int da311_reset(struct i2c_client *client) +{ + const struct { + u16 addr; + u8 mask; + u8 data; + } init_data[] = { + { DA311_REG_TEMP_CFG_REG, 0xff, 0x08 }, + { DA311_REG_CTRL_REG5, 0xff, 0x80 }, + { DA311_REG_CTRL_REG4, 0x30, 0x00 }, + { DA311_REG_CTRL_REG1, 0xff, 0x6f }, + { DA311_REG_TEMP_CFG_REG, 0xff, 0x88 }, + { DA311_REG_LDO_REG, 0xff, 0x02 }, + { DA311_REG_OTP_TRIM_OSC, 0xff, 0x27 }, + { DA311_REG_LPF_ABSOLUTE, 0xff, 0x30 }, + { DA311_REG_TEMP_OFF1, 0xff, 0x3f }, + { DA311_REG_TEMP_OFF2, 0xff, 0xff }, + { DA311_REG_TEMP_OFF3, 0xff, 0x0f }, + }; + int i, ret; + + /* Reset */ + ret = da311_register_mask_write(client, DA311_REG_SOFT_RESET, + 0xff, 0xaa); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(init_data); i++) { + ret = da311_register_mask_write(client, + init_data[i].addr, + init_data[i].mask, + init_data[i].data); + if (ret < 0) + return ret; + } + + return 0; +} + +static int da311_enable(struct i2c_client *client, bool enable) +{ + u8 data = enable ? 0x00 : 0x20; + + return da311_register_mask_write(client, DA311_REG_TEMP_CFG_REG, + 0x20, data); +} + +static int da311_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct da311_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = i2c_smbus_read_word_data(data->client, chan->address); + if (ret < 0) + return ret; + /* + * Values are 12 bits, stored as 16 bits with the 4 + * least significant bits always 0. + */ + *val = (short)ret >> 4; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = da311_nscale; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static const struct iio_info da311_info = { + .driver_module = THIS_MODULE, + .read_raw = da311_read_raw, +}; + +static int da311_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct da311_data *data; + + ret = i2c_smbus_read_byte_data(client, DA311_REG_CHIP_ID); + if (ret != DA311_CHIP_ID) + return (ret < 0) ? ret : -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &da311_info; + indio_dev->name = "da311"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = da311_channels; + indio_dev->num_channels = ARRAY_SIZE(da311_channels); + + ret = da311_reset(client); + if (ret < 0) + return ret; + + ret = da311_enable(client, true); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "device_register failed\n"); + da311_enable(client, false); + } + + return ret; +} + +static int da311_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + + return da311_enable(client, false); +} + +#ifdef CONFIG_PM_SLEEP +static int da311_suspend(struct device *dev) +{ + return da311_enable(to_i2c_client(dev), false); +} + +static int da311_resume(struct device *dev) +{ + return da311_enable(to_i2c_client(dev), true); +} +#endif + +static SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume); + +static const struct i2c_device_id da311_i2c_id[] = { + {"da311", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, da311_i2c_id); + +static struct i2c_driver da311_driver = { + .driver = { + .name = "da311", + .pm = &da311_pm_ops, + }, + .probe = da311_probe, + .remove = da311_remove, + .id_table = da311_i2c_id, +}; + +module_i2c_driver(da311_driver); + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("MiraMEMS DA311 3-Axis Accelerometer driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From a13e831fcaa7e8af0387aef629d1835cf39c59f0 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Wed, 5 Oct 2016 11:06:21 +0800 Subject: staging: iio: ad7192: implement IIO_CHAN_INFO_SAMP_FREQ This driver predates the availability of IIO_CHAN_INFO_SAMP_FREQ attribute wherein usage has some advantages like it can be accessed by in-kernel consumers as well as reduces the code size. Therefore, use IIO_CHAN_INFO_SAMP_FREQ to implement the sampling_frequency attribute instead of using IIO_DEV_ATTR_SAMP_FREQ() macro. Move code from the functions associated with IIO_DEV_ATTR_SAMP_FREQ() into respective read and write hooks with the mask set to IIO_CHAN_INFO_SAMP_FREQ. Signed-off-by: Eva Rachel Retuya Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 84 ++++++++++++---------------------- include/linux/iio/adc/ad_sigma_delta.h | 1 + 2 files changed, 30 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 1cf6b79801a9..bfa12ceb1e1f 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -322,57 +322,6 @@ out: return ret; } -static ssize_t ad7192_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7192_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", st->mclk / - (st->f_order * 1024 * AD7192_MODE_RATE(st->mode))); -} - -static ssize_t ad7192_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7192_state *st = iio_priv(indio_dev); - unsigned long lval; - int div, ret; - - ret = kstrtoul(buf, 10, &lval); - if (ret) - return ret; - if (lval == 0) - return -EINVAL; - - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - div = st->mclk / (lval * st->f_order * 1024); - if (div < 1 || div > 1023) { - ret = -EINVAL; - goto out; - } - - st->mode &= ~AD7192_MODE_RATE(-1); - st->mode |= AD7192_MODE_RATE(div); - ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); - -out: - iio_device_release_direct_mode(indio_dev); - - return ret ? ret : len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - ad7192_read_frequency, - ad7192_write_frequency); - static ssize_t ad7192_show_scale_available(struct device *dev, struct device_attribute *attr, char *buf) @@ -471,7 +420,6 @@ static IIO_DEVICE_ATTR(ac_excitation_en, S_IRUGO | S_IWUSR, AD7192_REG_MODE); static struct attribute *ad7192_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_in_v_m_v_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, @@ -484,7 +432,6 @@ static const struct attribute_group ad7192_attribute_group = { }; static struct attribute *ad7195_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_in_v_m_v_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, @@ -536,6 +483,10 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, if (chan->type == IIO_TEMP) *val -= 273 * ad7192_get_temp_scale(unipolar); return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = st->mclk / + (st->f_order * 1024 * AD7192_MODE_RATE(st->mode)); + return IIO_VAL_INT; } return -EINVAL; @@ -548,7 +499,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, long mask) { struct ad7192_state *st = iio_priv(indio_dev); - int ret, i; + int ret, i, div; unsigned int tmp; ret = iio_device_claim_direct_mode(indio_dev); @@ -572,6 +523,22 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, break; } break; + case IIO_CHAN_INFO_SAMP_FREQ: + if (!val) { + ret = -EINVAL; + break; + } + + div = st->mclk / (val * st->f_order * 1024); + if (div < 1 || div > 1023) { + ret = -EINVAL; + break; + } + + st->mode &= ~AD7192_MODE_RATE(-1); + st->mode |= AD7192_MODE_RATE(div); + ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + break; default: ret = -EINVAL; } @@ -585,7 +552,14 @@ static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, long mask) { - return IIO_VAL_INT_PLUS_NANO; + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT; + default: + return -EINVAL; + } } static const struct iio_info ad7192_info = { diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h index e7fdec4db9da..5ba430cc9a87 100644 --- a/include/linux/iio/adc/ad_sigma_delta.h +++ b/include/linux/iio/adc/ad_sigma_delta.h @@ -136,6 +136,7 @@ int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig); .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_OFFSET), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = (_si), \ .scan_type = { \ .sign = 'u', \ -- cgit v1.2.3 From f225951dbb9d02c80d09cb81b070b3af73a68de9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 8 Oct 2016 20:15:27 +0200 Subject: iio: accel: Add driver for the MiraMEMS DA280 3-axis 14-bit digital accelerometer Add an iio driver for the MiraMEMS DA280 3-axis 14-bit accelerometer, as well as for the DA226 which is a fully compatible 2-axis version. Datasheets for the DA280 and DA226 can be found at the manufacturers site: http://www.miramems.com/en/products.asp?list=1 Signed-off-by: Hans de Goede Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/i2c/trivial-devices.txt | 2 + drivers/iio/accel/Kconfig | 10 ++ drivers/iio/accel/Makefile | 1 + drivers/iio/accel/da280.c | 183 +++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 drivers/iio/accel/da280.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index decdd3e636bf..307f13bc81f2 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -125,6 +125,8 @@ microchip,mcp4662-502 Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem microchip,mcp4662-103 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k) microchip,mcp4662-503 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k) microchip,mcp4662-104 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k) +miramems,da226 MiraMEMS DA226 2-axis 14-bit digital accelerometer +miramems,da280 MiraMEMS DA280 3-axis 14-bit digital accelerometer miramems,da311 MiraMEMS DA311 3-axis 12-bit digital accelerometer national,lm63 Temperature sensor with integrated fan control national,lm75 I2C TEMP SENSOR diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 8945e70a797c..878e3c9449de 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -52,6 +52,16 @@ config BMC150_ACCEL_SPI tristate select REGMAP_SPI +config DA280 + tristate "MiraMEMS DA280 3-axis 14-bit digital accelerometer driver" + depends on I2C + help + Say yes here to build support for the MiraMEMS DA280 3-axis 14-bit + digital accelerometer. + + To compile this driver as a module, choose M here: the + module will be called da280. + config DA311 tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver" depends on I2C diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index ade13ae5d056..0aa574957047 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o +obj-$(CONFIG_DA280) += da280.o obj-$(CONFIG_DA311) += da311.o obj-$(CONFIG_DMARD06) += dmard06.o obj-$(CONFIG_DMARD09) += dmard09.o diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c new file mode 100644 index 000000000000..ed8343aeac9c --- /dev/null +++ b/drivers/iio/accel/da280.c @@ -0,0 +1,183 @@ +/** + * IIO driver for the MiraMEMS DA280 3-axis accelerometer and + * IIO driver for the MiraMEMS DA226 2-axis accelerometer + * + * Copyright (c) 2016 Hans de Goede + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#define DA280_REG_CHIP_ID 0x01 +#define DA280_REG_ACC_X_LSB 0x02 +#define DA280_REG_ACC_Y_LSB 0x04 +#define DA280_REG_ACC_Z_LSB 0x06 +#define DA280_REG_MODE_BW 0x11 + +#define DA280_CHIP_ID 0x13 +#define DA280_MODE_ENABLE 0x1e +#define DA280_MODE_DISABLE 0x9e + +enum { da226, da280 }; + +/* + * a value of + or -4096 corresponds to + or - 1G + * scale = 9.81 / 4096 = 0.002395019 + */ + +static const int da280_nscale = 2395019; + +#define DA280_CHANNEL(reg, axis) { \ + .type = IIO_ACCEL, \ + .address = reg, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec da280_channels[] = { + DA280_CHANNEL(DA280_REG_ACC_X_LSB, X), + DA280_CHANNEL(DA280_REG_ACC_Y_LSB, Y), + DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z), +}; + +struct da280_data { + struct i2c_client *client; +}; + +static int da280_enable(struct i2c_client *client, bool enable) +{ + u8 data = enable ? DA280_MODE_ENABLE : DA280_MODE_DISABLE; + + return i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW, data); +} + +static int da280_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct da280_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = i2c_smbus_read_word_data(data->client, chan->address); + if (ret < 0) + return ret; + /* + * Values are 14 bits, stored as 16 bits with the 2 + * least significant bits always 0. + */ + *val = (short)ret >> 2; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = da280_nscale; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static const struct iio_info da280_info = { + .driver_module = THIS_MODULE, + .read_raw = da280_read_raw, +}; + +static int da280_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct da280_data *data; + + ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID); + if (ret != DA280_CHIP_ID) + return (ret < 0) ? ret : -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &da280_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = da280_channels; + if (id->driver_data == da226) { + indio_dev->name = "da226"; + indio_dev->num_channels = 2; + } else { + indio_dev->name = "da280"; + indio_dev->num_channels = 3; + } + + ret = da280_enable(client, true); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "device_register failed\n"); + da280_enable(client, false); + } + + return ret; +} + +static int da280_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + + return da280_enable(client, false); +} + +#ifdef CONFIG_PM_SLEEP +static int da280_suspend(struct device *dev) +{ + return da280_enable(to_i2c_client(dev), false); +} + +static int da280_resume(struct device *dev) +{ + return da280_enable(to_i2c_client(dev), true); +} +#endif + +static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume); + +static const struct i2c_device_id da280_i2c_id[] = { + { "da226", da226 }, + { "da280", da280 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, da280_i2c_id); + +static struct i2c_driver da280_driver = { + .driver = { + .name = "da280", + .pm = &da280_pm_ops, + }, + .probe = da280_probe, + .remove = da280_remove, + .id_table = da280_i2c_id, +}; + +module_i2c_driver(da280_driver); + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("MiraMEMS DA280 3-Axis Accelerometer driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 73d2ad96fd9cdb8efff6844368610dcb72dcf7ba Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Tue, 4 Oct 2016 02:29:06 +0530 Subject: Staging: iio: meter: ade7758_core: implement IIO_CHAN_INFO_SAMP_FREQ This driver predates the availability of IIO_CHAN_INFO_SAMP_FREQ attribute wherein usage has some advantages like it can be accessed by in-kernel consumers as well as reduces the code size. Hence moving functionality from IIO_DEV_ATTR_SAMP_FREQ attribute into IIO_CHAN_INFO_SAMP_FREQ handlers. Also Adding ade7758_read_raw() and ade7758_write_raw() to allow reading/writing the element as well. Signed-off-by: Sandhya Bankar Signed-off-by: Jonathan Cameron --- drivers/staging/iio/meter/ade7758_core.c | 86 +++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index ebb8a1993303..3af8f77b8e41 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -465,38 +465,26 @@ err_ret: return ret; } -static ssize_t ade7758_read_frequency(struct device *dev, - struct device_attribute *attr, char *buf) +static int ade7758_read_samp_freq(struct device *dev, int *val) { int ret; u8 t; - int sps; ret = ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, &t); if (ret) return ret; t = (t >> 5) & 0x3; - sps = 26040 / (1 << t); + *val = 26040 / (1 << t); - return sprintf(buf, "%d SPS\n", sps); + return 0; } -static ssize_t ade7758_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static int ade7758_write_samp_freq(struct device *dev, int val) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - u16 val; int ret; u8 reg, t; - ret = kstrtou16(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - switch (val) { case 26040: t = 0; @@ -525,9 +513,49 @@ static ssize_t ade7758_write_frequency(struct device *dev, ret = ade7758_spi_write_reg_8(dev, ADE7758_WAVMODE, reg); out: - mutex_unlock(&indio_dev->mlock); + return ret; +} - return ret ? ret : len; +static int ade7758_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&indio_dev->mlock); + ret = ade7758_read_samp_freq(&indio_dev->dev, val); + mutex_unlock(&indio_dev->mlock); + return ret; + default: + return -EINVAL; + } + + return ret; +} + +static int ade7758_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&indio_dev->mlock); + ret = ade7758_write_samp_freq(&indio_dev->dev, val); + mutex_unlock(&indio_dev->mlock); + return ret; + default: + return -EINVAL; + } + + return ret; } static IIO_DEV_ATTR_TEMP_RAW(ade7758_read_8bit); @@ -553,17 +581,12 @@ static IIO_DEV_ATTR_BVAHR(ade7758_read_16bit, static IIO_DEV_ATTR_CVAHR(ade7758_read_16bit, ADE7758_CVAHR); -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - ade7758_read_frequency, - ade7758_write_frequency); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26040 13020 6510 3255"); static struct attribute *ade7758_attributes[] = { &iio_dev_attr_in_temp_raw.dev_attr.attr, &iio_const_attr_in_temp_offset.dev_attr.attr, &iio_const_attr_in_temp_scale.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_awatthr.dev_attr.attr, &iio_dev_attr_bwatthr.dev_attr.attr, @@ -611,6 +634,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 0, + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE), .scan_index = 0, .scan_type = { @@ -622,6 +646,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .type = IIO_CURRENT, .indexed = 1, .channel = 0, + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT), .scan_index = 1, .scan_type = { @@ -634,6 +659,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 0, .extend_name = "apparent", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR), .scan_index = 2, .scan_type = { @@ -646,6 +672,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 0, .extend_name = "active", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR), .scan_index = 3, .scan_type = { @@ -658,6 +685,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 0, .extend_name = "reactive", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR), .scan_index = 4, .scan_type = { @@ -669,6 +697,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 1, + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE), .scan_index = 5, .scan_type = { @@ -680,6 +709,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .type = IIO_CURRENT, .indexed = 1, .channel = 1, + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT), .scan_index = 6, .scan_type = { @@ -692,6 +722,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 1, .extend_name = "apparent", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR), .scan_index = 7, .scan_type = { @@ -704,6 +735,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 1, .extend_name = "active", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR), .scan_index = 8, .scan_type = { @@ -716,6 +748,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 1, .extend_name = "reactive", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR), .scan_index = 9, .scan_type = { @@ -727,6 +760,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 2, + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE), .scan_index = 10, .scan_type = { @@ -738,6 +772,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .type = IIO_CURRENT, .indexed = 1, .channel = 2, + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT), .scan_index = 11, .scan_type = { @@ -750,6 +785,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 2, .extend_name = "apparent", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR), .scan_index = 12, .scan_type = { @@ -762,6 +798,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 2, .extend_name = "active", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR), .scan_index = 13, .scan_type = { @@ -774,6 +811,7 @@ static const struct iio_chan_spec ade7758_channels[] = { .indexed = 1, .channel = 2, .extend_name = "reactive", + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR), .scan_index = 14, .scan_type = { @@ -787,6 +825,8 @@ static const struct iio_chan_spec ade7758_channels[] = { static const struct iio_info ade7758_info = { .attrs = &ade7758_attribute_group, + .read_raw = &ade7758_read_raw, + .write_raw = &ade7758_write_raw, .driver_module = THIS_MODULE, }; -- cgit v1.2.3 From e748e2801a70eb0da6dbc2db1407185a2883533d Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 6 Oct 2016 20:48:34 -0400 Subject: staging: iio: isl29018: add documentation about the infrared suppression Add documentation from the ISL29018 Data Sheet (FN6619.4, Oct 8, 2012) about the infrared suppression that can be controlled with the proximity_on_chip_ambient_infrared_suppression sysfs attribute. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 51226bd337c5..52bfb1cbe8e0 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -307,6 +307,24 @@ static ssize_t in_illuminance_integration_time_available_show return len; } +/* + * From ISL29018 Data Sheet (FN6619.4, Oct 8, 2012) regarding the + * infrared suppression: + * + * Proximity Sensing Scheme: Bit 7. This bit programs the function + * of the proximity detection. Logic 0 of this bit, Scheme 0, makes + * full n (4, 8, 12, 16) bits (unsigned) proximity detection. The range + * of Scheme 0 proximity count is from 0 to 2^n. Logic 1 of this bit, + * Scheme 1, makes n-1 (3, 7, 11, 15) bits (2's complementary) + * proximity_less_ambient detection. The range of Scheme 1 + * proximity count is from -2^(n-1) to 2^(n-1) . The sign bit is extended + * for resolutions less than 16. While Scheme 0 has wider dynamic + * range, Scheme 1 proximity detection is less affected by the + * ambient IR noise variation. + * + * 0 Sensing IR from LED and ambient + * 1 Sensing IR from LED with ambient IR rejection + */ static ssize_t proximity_on_chip_ambient_infrared_suppression_show (struct device *dev, struct device_attribute *attr, char *buf) -- cgit v1.2.3 From 1e8a655db2f4dd8777eda08c2af7d1381b9eecca Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Sun, 2 Oct 2016 12:06:48 +0200 Subject: net: mv643xx_eth: use phydev from struct net_device The private structure contain a pointer to phydev, but the structure net_device already contain such pointer. So we can remove the pointer phydev in the private structure, and update the driver to use the one contained in struct net_device. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 88 +++++++++++++++--------------- 1 file changed, 43 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 55831188bc32..ae7370daf6fa 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -384,8 +384,6 @@ struct mv643xx_eth_private { struct net_device *dev; - struct phy_device *phy; - struct timer_list mib_counters_timer; spinlock_t mib_counters_lock; struct mib_counters mib_counters; @@ -1236,7 +1234,7 @@ static void mv643xx_eth_adjust_link(struct net_device *dev) DISABLE_AUTO_NEG_FOR_FLOW_CTRL | DISABLE_AUTO_NEG_FOR_DUPLEX; - if (mp->phy->autoneg == AUTONEG_ENABLE) { + if (dev->phydev->autoneg == AUTONEG_ENABLE) { /* enable auto negotiation */ pscr &= ~autoneg_disable; goto out_write; @@ -1244,7 +1242,7 @@ static void mv643xx_eth_adjust_link(struct net_device *dev) pscr |= autoneg_disable; - if (mp->phy->speed == SPEED_1000) { + if (dev->phydev->speed == SPEED_1000) { /* force gigabit, half duplex not supported */ pscr |= SET_GMII_SPEED_TO_1000; pscr |= SET_FULL_DUPLEX_MODE; @@ -1253,12 +1251,12 @@ static void mv643xx_eth_adjust_link(struct net_device *dev) pscr &= ~SET_GMII_SPEED_TO_1000; - if (mp->phy->speed == SPEED_100) + if (dev->phydev->speed == SPEED_100) pscr |= SET_MII_SPEED_TO_100; else pscr &= ~SET_MII_SPEED_TO_100; - if (mp->phy->duplex == DUPLEX_FULL) + if (dev->phydev->duplex == DUPLEX_FULL) pscr |= SET_FULL_DUPLEX_MODE; else pscr &= ~SET_FULL_DUPLEX_MODE; @@ -1500,11 +1498,12 @@ static int mv643xx_eth_get_settings_phy(struct mv643xx_eth_private *mp, struct ethtool_cmd *cmd) { + struct net_device *dev = mp->dev; int err; - err = phy_read_status(mp->phy); + err = phy_read_status(dev->phydev); if (err == 0) - err = phy_ethtool_gset(mp->phy, cmd); + err = phy_ethtool_gset(dev->phydev, cmd); /* * The MAC does not support 1000baseT_Half. @@ -1553,23 +1552,21 @@ mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp, static void mv643xx_eth_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct mv643xx_eth_private *mp = netdev_priv(dev); wol->supported = 0; wol->wolopts = 0; - if (mp->phy) - phy_ethtool_get_wol(mp->phy, wol); + if (dev->phydev) + phy_ethtool_get_wol(dev->phydev, wol); } static int mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct mv643xx_eth_private *mp = netdev_priv(dev); int err; - if (mp->phy == NULL) + if (!dev->phydev) return -EOPNOTSUPP; - err = phy_ethtool_set_wol(mp->phy, wol); + err = phy_ethtool_set_wol(dev->phydev, wol); /* Given that mv643xx_eth works without the marvell-specific PHY driver, * this debugging hint is useful to have. */ @@ -1583,7 +1580,7 @@ mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct mv643xx_eth_private *mp = netdev_priv(dev); - if (mp->phy != NULL) + if (dev->phydev) return mv643xx_eth_get_settings_phy(mp, cmd); else return mv643xx_eth_get_settings_phyless(mp, cmd); @@ -1592,10 +1589,9 @@ mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct mv643xx_eth_private *mp = netdev_priv(dev); int ret; - if (mp->phy == NULL) + if (!dev->phydev) return -EINVAL; /* @@ -1603,7 +1599,7 @@ mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) */ cmd->advertising &= ~ADVERTISED_1000baseT_Half; - ret = phy_ethtool_sset(mp->phy, cmd); + ret = phy_ethtool_sset(dev->phydev, cmd); if (!ret) mv643xx_eth_adjust_link(dev); return ret; @@ -1622,12 +1618,10 @@ static void mv643xx_eth_get_drvinfo(struct net_device *dev, static int mv643xx_eth_nway_reset(struct net_device *dev) { - struct mv643xx_eth_private *mp = netdev_priv(dev); - - if (mp->phy == NULL) + if (!dev->phydev) return -EINVAL; - return genphy_restart_aneg(mp->phy); + return genphy_restart_aneg(dev->phydev); } static int @@ -2326,19 +2320,20 @@ static inline void oom_timer_wrapper(unsigned long data) static void port_start(struct mv643xx_eth_private *mp) { + struct net_device *dev = mp->dev; u32 pscr; int i; /* * Perform PHY reset, if there is a PHY. */ - if (mp->phy != NULL) { + if (dev->phydev) { struct ethtool_cmd cmd; - mv643xx_eth_get_settings(mp->dev, &cmd); - phy_init_hw(mp->phy); - mv643xx_eth_set_settings(mp->dev, &cmd); - phy_start(mp->phy); + mv643xx_eth_get_settings(dev, &cmd); + phy_init_hw(dev->phydev); + mv643xx_eth_set_settings(dev, &cmd); + phy_start(dev->phydev); } /* @@ -2350,7 +2345,7 @@ static void port_start(struct mv643xx_eth_private *mp) wrlp(mp, PORT_SERIAL_CONTROL, pscr); pscr |= DO_NOT_FORCE_LINK_FAIL; - if (mp->phy == NULL) + if (!dev->phydev) pscr |= FORCE_LINK_PASS; wrlp(mp, PORT_SERIAL_CONTROL, pscr); @@ -2534,8 +2529,8 @@ static int mv643xx_eth_stop(struct net_device *dev) del_timer_sync(&mp->rx_oom); netif_carrier_off(dev); - if (mp->phy) - phy_stop(mp->phy); + if (dev->phydev) + phy_stop(dev->phydev); free_irq(dev->irq, dev); port_reset(mp); @@ -2553,13 +2548,12 @@ static int mv643xx_eth_stop(struct net_device *dev) static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct mv643xx_eth_private *mp = netdev_priv(dev); int ret; - if (mp->phy == NULL) + if (!dev->phydev) return -ENOTSUPP; - ret = phy_mii_ioctl(mp->phy, ifr, cmd); + ret = phy_mii_ioctl(dev->phydev, ifr, cmd); if (!ret) mv643xx_eth_adjust_link(dev); return ret; @@ -3006,7 +3000,8 @@ static struct phy_device *phy_scan(struct mv643xx_eth_private *mp, static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) { - struct phy_device *phy = mp->phy; + struct net_device *dev = mp->dev; + struct phy_device *phy = dev->phydev; if (speed == 0) { phy->autoneg = AUTONEG_ENABLE; @@ -3024,6 +3019,7 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) { + struct net_device *dev = mp->dev; u32 pscr; pscr = rdlp(mp, PORT_SERIAL_CONTROL); @@ -3033,7 +3029,7 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) } pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED; - if (mp->phy == NULL) { + if (!dev->phydev) { pscr |= DISABLE_AUTO_NEG_SPEED_GMII; if (speed == SPEED_1000) pscr |= SET_GMII_SPEED_TO_1000; @@ -3072,6 +3068,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) struct mv643xx_eth_platform_data *pd; struct mv643xx_eth_private *mp; struct net_device *dev; + struct phy_device *phydev = NULL; struct resource *res; int err; @@ -3127,18 +3124,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev) err = 0; if (pd->phy_node) { - mp->phy = of_phy_connect(mp->dev, pd->phy_node, - mv643xx_eth_adjust_link, 0, - PHY_INTERFACE_MODE_GMII); - if (!mp->phy) + phydev = of_phy_connect(mp->dev, pd->phy_node, + mv643xx_eth_adjust_link, 0, + PHY_INTERFACE_MODE_GMII); + if (!phydev) err = -ENODEV; else - phy_addr_set(mp, mp->phy->mdio.addr); + phy_addr_set(mp, phydev->mdio.addr); } else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) { - mp->phy = phy_scan(mp, pd->phy_addr); + phydev = phy_scan(mp, pd->phy_addr); - if (IS_ERR(mp->phy)) - err = PTR_ERR(mp->phy); + if (IS_ERR(phydev)) + err = PTR_ERR(phydev); else phy_init(mp, pd->speed, pd->duplex); } @@ -3222,10 +3219,11 @@ out: static int mv643xx_eth_remove(struct platform_device *pdev) { struct mv643xx_eth_private *mp = platform_get_drvdata(pdev); + struct net_device *dev = mp->dev; unregister_netdev(mp->dev); - if (mp->phy != NULL) - phy_disconnect(mp->phy); + if (dev->phydev) + phy_disconnect(dev->phydev); cancel_work_sync(&mp->tx_timeout_task); if (!IS_ERR(mp->clk)) -- cgit v1.2.3 From a54e1612bc3dd4a3974b69a6043dd4ddbab14e6d Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Sun, 2 Oct 2016 12:06:49 +0200 Subject: net: mv643xx_eth: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 84 +++++++++++++++++++----------- 1 file changed, 53 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index ae7370daf6fa..18e6bb6e3867 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -1495,56 +1495,69 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = { }; static int -mv643xx_eth_get_settings_phy(struct mv643xx_eth_private *mp, - struct ethtool_cmd *cmd) +mv643xx_eth_get_link_ksettings_phy(struct mv643xx_eth_private *mp, + struct ethtool_link_ksettings *cmd) { struct net_device *dev = mp->dev; int err; + u32 supported, advertising; err = phy_read_status(dev->phydev); if (err == 0) - err = phy_ethtool_gset(dev->phydev, cmd); + err = phy_ethtool_ksettings_get(dev->phydev, cmd); /* * The MAC does not support 1000baseT_Half. */ - cmd->supported &= ~SUPPORTED_1000baseT_Half; - cmd->advertising &= ~ADVERTISED_1000baseT_Half; + ethtool_convert_link_mode_to_legacy_u32(&supported, + cmd->link_modes.supported); + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + supported &= ~SUPPORTED_1000baseT_Half; + advertising &= ~ADVERTISED_1000baseT_Half; + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + advertising); return err; } static int -mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp, - struct ethtool_cmd *cmd) +mv643xx_eth_get_link_ksettings_phyless(struct mv643xx_eth_private *mp, + struct ethtool_link_ksettings *cmd) { u32 port_status; + u32 supported, advertising; port_status = rdlp(mp, PORT_STATUS); - cmd->supported = SUPPORTED_MII; - cmd->advertising = ADVERTISED_MII; + supported = SUPPORTED_MII; + advertising = ADVERTISED_MII; switch (port_status & PORT_SPEED_MASK) { case PORT_SPEED_10: - ethtool_cmd_speed_set(cmd, SPEED_10); + cmd->base.speed = SPEED_10; break; case PORT_SPEED_100: - ethtool_cmd_speed_set(cmd, SPEED_100); + cmd->base.speed = SPEED_100; break; case PORT_SPEED_1000: - ethtool_cmd_speed_set(cmd, SPEED_1000); + cmd->base.speed = SPEED_1000; break; default: - cmd->speed = -1; + cmd->base.speed = -1; break; } - cmd->duplex = (port_status & FULL_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; - cmd->port = PORT_MII; - cmd->phy_address = 0; - cmd->transceiver = XCVR_INTERNAL; - cmd->autoneg = AUTONEG_DISABLE; - cmd->maxtxpkt = 1; - cmd->maxrxpkt = 1; + cmd->base.duplex = (port_status & FULL_DUPLEX) ? + DUPLEX_FULL : DUPLEX_HALF; + cmd->base.port = PORT_MII; + cmd->base.phy_address = 0; + cmd->base.autoneg = AUTONEG_DISABLE; + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + advertising); return 0; } @@ -1576,19 +1589,23 @@ mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) } static int -mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +mv643xx_eth_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) { struct mv643xx_eth_private *mp = netdev_priv(dev); if (dev->phydev) - return mv643xx_eth_get_settings_phy(mp, cmd); + return mv643xx_eth_get_link_ksettings_phy(mp, cmd); else - return mv643xx_eth_get_settings_phyless(mp, cmd); + return mv643xx_eth_get_link_ksettings_phyless(mp, cmd); } static int -mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +mv643xx_eth_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) { + struct ethtool_link_ksettings c = *cmd; + u32 advertising; int ret; if (!dev->phydev) @@ -1597,9 +1614,13 @@ mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) /* * The MAC does not support 1000baseT_Half. */ - cmd->advertising &= ~ADVERTISED_1000baseT_Half; + ethtool_convert_link_mode_to_legacy_u32(&advertising, + c.link_modes.advertising); + advertising &= ~ADVERTISED_1000baseT_Half; + ethtool_convert_legacy_u32_to_link_mode(c.link_modes.advertising, + advertising); - ret = phy_ethtool_sset(dev->phydev, cmd); + ret = phy_ethtool_ksettings_set(dev->phydev, &c); if (!ret) mv643xx_eth_adjust_link(dev); return ret; @@ -1746,8 +1767,6 @@ static int mv643xx_eth_get_sset_count(struct net_device *dev, int sset) } static const struct ethtool_ops mv643xx_eth_ethtool_ops = { - .get_settings = mv643xx_eth_get_settings, - .set_settings = mv643xx_eth_set_settings, .get_drvinfo = mv643xx_eth_get_drvinfo, .nway_reset = mv643xx_eth_nway_reset, .get_link = ethtool_op_get_link, @@ -1761,6 +1780,8 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = { .get_ts_info = ethtool_op_get_ts_info, .get_wol = mv643xx_eth_get_wol, .set_wol = mv643xx_eth_set_wol, + .get_link_ksettings = mv643xx_eth_get_link_ksettings, + .set_link_ksettings = mv643xx_eth_set_link_ksettings, }; @@ -2328,11 +2349,12 @@ static void port_start(struct mv643xx_eth_private *mp) * Perform PHY reset, if there is a PHY. */ if (dev->phydev) { - struct ethtool_cmd cmd; + struct ethtool_link_ksettings cmd; - mv643xx_eth_get_settings(dev, &cmd); + mv643xx_eth_get_link_ksettings(dev, &cmd); phy_init_hw(dev->phydev); - mv643xx_eth_set_settings(dev, &cmd); + mv643xx_eth_set_link_ksettings( + dev, (const struct ethtool_link_ksettings *)&cmd); phy_start(dev->phydev); } -- cgit v1.2.3 From d6d50c7ea42d3659782695bfebf4ae6548d00db5 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Mon, 3 Oct 2016 08:28:19 +0200 Subject: net: stmmac: use phydev from struct net_device The private structure contain a pointer to phydev, but the structure net_device already contain such pointer. So we can remove the pointer phydev in the private structure, and update the driver to use the one contained in struct net_device. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 4 +-- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 - .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 18 +++++----- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 40 ++++++++++------------ 4 files changed, 30 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index bec6963ac71e..5ad1dfb40f2b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -367,8 +367,8 @@ static int socfpga_dwmac_resume(struct device *dev) * control register 0, and can be modified by the phy driver * framework. */ - if (priv->phydev) - phy_resume(priv->phydev); + if (ndev->phydev) + phy_resume(ndev->phydev); return stmmac_resume(dev); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 8dc9056c1001..f94e0282451b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -90,7 +90,6 @@ struct stmmac_priv { struct mac_device_info *hw; spinlock_t lock; - struct phy_device *phydev ____cacheline_aligned_in_smp; int oldlink; int speed; int oldduplex; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 1e06173fc9d7..ac823bf6c712 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -273,7 +273,7 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) { struct stmmac_priv *priv = netdev_priv(dev); - struct phy_device *phy = priv->phydev; + struct phy_device *phy = dev->phydev; int rc; if (priv->hw->pcs & STMMAC_PCS_RGMII || @@ -359,7 +359,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) { struct stmmac_priv *priv = netdev_priv(dev); - struct phy_device *phy = priv->phydev; + struct phy_device *phy = dev->phydev; int rc; if (priv->hw->pcs & STMMAC_PCS_RGMII || @@ -468,12 +468,12 @@ stmmac_get_pauseparam(struct net_device *netdev, if (!adv_lp.pause) return; } else { - if (!(priv->phydev->supported & SUPPORTED_Pause) || - !(priv->phydev->supported & SUPPORTED_Asym_Pause)) + if (!(netdev->phydev->supported & SUPPORTED_Pause) || + !(netdev->phydev->supported & SUPPORTED_Asym_Pause)) return; } - pause->autoneg = priv->phydev->autoneg; + pause->autoneg = netdev->phydev->autoneg; if (priv->flow_ctrl & FLOW_RX) pause->rx_pause = 1; @@ -487,7 +487,7 @@ stmmac_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct stmmac_priv *priv = netdev_priv(netdev); - struct phy_device *phy = priv->phydev; + struct phy_device *phy = netdev->phydev; int new_pause = FLOW_OFF; if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) { @@ -547,7 +547,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, } } if (priv->eee_enabled) { - int val = phy_get_eee_err(priv->phydev); + int val = phy_get_eee_err(dev->phydev); if (val) priv->xstats.phy_eee_wakeup_error_n = val; } @@ -666,7 +666,7 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev, edata->eee_active = priv->eee_active; edata->tx_lpi_timer = priv->tx_lpi_timer; - return phy_ethtool_get_eee(priv->phydev, edata); + return phy_ethtool_get_eee(dev->phydev, edata); } static int stmmac_ethtool_op_set_eee(struct net_device *dev, @@ -691,7 +691,7 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev, priv->tx_lpi_timer = edata->tx_lpi_timer; } - return phy_ethtool_set_eee(priv->phydev, edata); + return phy_ethtool_set_eee(dev->phydev, edata); } static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 4c8c60af7985..1a06c87e3935 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -221,7 +221,8 @@ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv) */ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) { - struct phy_device *phydev = priv->phydev; + struct net_device *ndev = priv->dev; + struct phy_device *phydev = ndev->phydev; if (likely(priv->plat->fix_mac_speed)) priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed); @@ -279,6 +280,7 @@ static void stmmac_eee_ctrl_timer(unsigned long arg) */ bool stmmac_eee_init(struct stmmac_priv *priv) { + struct net_device *ndev = priv->dev; unsigned long flags; bool ret = false; @@ -295,7 +297,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv) int tx_lpi_timer = priv->tx_lpi_timer; /* Check if the PHY supports EEE */ - if (phy_init_eee(priv->phydev, 1)) { + if (phy_init_eee(ndev->phydev, 1)) { /* To manage at run-time if the EEE cannot be supported * anymore (for example because the lp caps have been * changed). @@ -327,7 +329,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv) tx_lpi_timer); } /* Set HW EEE according to the speed */ - priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link); + priv->hw->mac->set_eee_pls(priv->hw, ndev->phydev->link); ret = true; spin_unlock_irqrestore(&priv->lock, flags); @@ -691,7 +693,7 @@ static void stmmac_release_ptp(struct stmmac_priv *priv) static void stmmac_adjust_link(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); - struct phy_device *phydev = priv->phydev; + struct phy_device *phydev = dev->phydev; unsigned long flags; int new_state = 0; unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; @@ -874,8 +876,6 @@ static int stmmac_init_phy(struct net_device *dev) pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)" " Link = %d\n", dev->name, phydev->phy_id, phydev->link); - priv->phydev = phydev; - return 0; } @@ -1800,8 +1800,8 @@ static int stmmac_open(struct net_device *dev) stmmac_init_tx_coalesce(priv); - if (priv->phydev) - phy_start(priv->phydev); + if (dev->phydev) + phy_start(dev->phydev); /* Request the IRQ lines */ ret = request_irq(dev->irq, stmmac_interrupt, @@ -1848,8 +1848,8 @@ wolirq_error: init_error: free_dma_desc_resources(priv); dma_desc_error: - if (priv->phydev) - phy_disconnect(priv->phydev); + if (dev->phydev) + phy_disconnect(dev->phydev); return ret; } @@ -1868,10 +1868,9 @@ static int stmmac_release(struct net_device *dev) del_timer_sync(&priv->eee_ctrl_timer); /* Stop and disconnect the PHY */ - if (priv->phydev) { - phy_stop(priv->phydev); - phy_disconnect(priv->phydev); - priv->phydev = NULL; + if (dev->phydev) { + phy_stop(dev->phydev); + phy_disconnect(dev->phydev); } netif_stop_queue(dev); @@ -2863,7 +2862,6 @@ static void stmmac_poll_controller(struct net_device *dev) */ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct stmmac_priv *priv = netdev_priv(dev); int ret = -EOPNOTSUPP; if (!netif_running(dev)) @@ -2873,9 +2871,9 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) case SIOCGMIIPHY: case SIOCGMIIREG: case SIOCSMIIREG: - if (!priv->phydev) + if (!dev->phydev) return -EINVAL; - ret = phy_mii_ioctl(priv->phydev, rq, cmd); + ret = phy_mii_ioctl(dev->phydev, rq, cmd); break; case SIOCSHWTSTAMP: ret = stmmac_hwtstamp_ioctl(dev, rq); @@ -3428,8 +3426,8 @@ int stmmac_suspend(struct device *dev) if (!ndev || !netif_running(ndev)) return 0; - if (priv->phydev) - phy_stop(priv->phydev); + if (ndev->phydev) + phy_stop(ndev->phydev); spin_lock_irqsave(&priv->lock, flags); @@ -3523,8 +3521,8 @@ int stmmac_resume(struct device *dev) spin_unlock_irqrestore(&priv->lock, flags); - if (priv->phydev) - phy_start(priv->phydev); + if (ndev->phydev) + phy_start(ndev->phydev); return 0; } -- cgit v1.2.3 From 1685e785cc8812fe3069cd4a7ac6c0a346c6e0aa Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Mon, 3 Oct 2016 08:28:20 +0200 Subject: net: stmmac: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 97 +++++++++++++--------- 1 file changed, 56 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index ac823bf6c712..3fe9340b748f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -269,8 +269,8 @@ static void stmmac_ethtool_getdrvinfo(struct net_device *dev, strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); } -static int stmmac_ethtool_getsettings(struct net_device *dev, - struct ethtool_cmd *cmd) +static int stmmac_ethtool_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) { struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phy = dev->phydev; @@ -279,15 +279,16 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, if (priv->hw->pcs & STMMAC_PCS_RGMII || priv->hw->pcs & STMMAC_PCS_SGMII) { struct rgmii_adv adv; + u32 supported, advertising, lp_advertising; if (!priv->xstats.pcs_link) { - ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); - cmd->duplex = DUPLEX_UNKNOWN; + cmd->base.speed = SPEED_UNKNOWN; + cmd->base.duplex = DUPLEX_UNKNOWN; return 0; } - cmd->duplex = priv->xstats.pcs_duplex; + cmd->base.duplex = priv->xstats.pcs_duplex; - ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed); + cmd->base.speed = priv->xstats.pcs_speed; /* Get and convert ADV/LP_ADV from the HW AN registers */ if (!priv->hw->mac->pcs_get_adv_lp) @@ -297,45 +298,59 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, /* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */ + ethtool_convert_link_mode_to_legacy_u32( + &supported, cmd->link_modes.supported); + ethtool_convert_link_mode_to_legacy_u32( + &advertising, cmd->link_modes.advertising); + ethtool_convert_link_mode_to_legacy_u32( + &lp_advertising, cmd->link_modes.lp_advertising); + if (adv.pause & STMMAC_PCS_PAUSE) - cmd->advertising |= ADVERTISED_Pause; + advertising |= ADVERTISED_Pause; if (adv.pause & STMMAC_PCS_ASYM_PAUSE) - cmd->advertising |= ADVERTISED_Asym_Pause; + advertising |= ADVERTISED_Asym_Pause; if (adv.lp_pause & STMMAC_PCS_PAUSE) - cmd->lp_advertising |= ADVERTISED_Pause; + lp_advertising |= ADVERTISED_Pause; if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE) - cmd->lp_advertising |= ADVERTISED_Asym_Pause; + lp_advertising |= ADVERTISED_Asym_Pause; /* Reg49[3] always set because ANE is always supported */ - cmd->autoneg = ADVERTISED_Autoneg; - cmd->supported |= SUPPORTED_Autoneg; - cmd->advertising |= ADVERTISED_Autoneg; - cmd->lp_advertising |= ADVERTISED_Autoneg; + cmd->base.autoneg = ADVERTISED_Autoneg; + supported |= SUPPORTED_Autoneg; + advertising |= ADVERTISED_Autoneg; + lp_advertising |= ADVERTISED_Autoneg; if (adv.duplex) { - cmd->supported |= (SUPPORTED_1000baseT_Full | - SUPPORTED_100baseT_Full | - SUPPORTED_10baseT_Full); - cmd->advertising |= (ADVERTISED_1000baseT_Full | - ADVERTISED_100baseT_Full | - ADVERTISED_10baseT_Full); + supported |= (SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full | + SUPPORTED_10baseT_Full); + advertising |= (ADVERTISED_1000baseT_Full | + ADVERTISED_100baseT_Full | + ADVERTISED_10baseT_Full); } else { - cmd->supported |= (SUPPORTED_1000baseT_Half | - SUPPORTED_100baseT_Half | - SUPPORTED_10baseT_Half); - cmd->advertising |= (ADVERTISED_1000baseT_Half | - ADVERTISED_100baseT_Half | - ADVERTISED_10baseT_Half); + supported |= (SUPPORTED_1000baseT_Half | + SUPPORTED_100baseT_Half | + SUPPORTED_10baseT_Half); + advertising |= (ADVERTISED_1000baseT_Half | + ADVERTISED_100baseT_Half | + ADVERTISED_10baseT_Half); } if (adv.lp_duplex) - cmd->lp_advertising |= (ADVERTISED_1000baseT_Full | - ADVERTISED_100baseT_Full | - ADVERTISED_10baseT_Full); + lp_advertising |= (ADVERTISED_1000baseT_Full | + ADVERTISED_100baseT_Full | + ADVERTISED_10baseT_Full); else - cmd->lp_advertising |= (ADVERTISED_1000baseT_Half | - ADVERTISED_100baseT_Half | - ADVERTISED_10baseT_Half); - cmd->port = PORT_OTHER; + lp_advertising |= (ADVERTISED_1000baseT_Half | + ADVERTISED_100baseT_Half | + ADVERTISED_10baseT_Half); + cmd->base.port = PORT_OTHER; + + ethtool_convert_legacy_u32_to_link_mode( + cmd->link_modes.supported, supported); + ethtool_convert_legacy_u32_to_link_mode( + cmd->link_modes.advertising, advertising); + ethtool_convert_legacy_u32_to_link_mode( + cmd->link_modes.lp_advertising, lp_advertising); return 0; } @@ -350,13 +365,13 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, "link speed / duplex setting\n", dev->name); return -EBUSY; } - cmd->transceiver = XCVR_INTERNAL; - rc = phy_ethtool_gset(phy, cmd); + rc = phy_ethtool_ksettings_get(phy, cmd); return rc; } -static int stmmac_ethtool_setsettings(struct net_device *dev, - struct ethtool_cmd *cmd) +static int +stmmac_ethtool_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) { struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phy = dev->phydev; @@ -367,7 +382,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause; /* Only support ANE */ - if (cmd->autoneg != AUTONEG_ENABLE) + if (cmd->base.autoneg != AUTONEG_ENABLE) return -EINVAL; mask &= (ADVERTISED_1000baseT_Half | @@ -389,7 +404,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, } spin_lock(&priv->lock); - rc = phy_ethtool_sset(phy, cmd); + rc = phy_ethtool_ksettings_set(phy, cmd); spin_unlock(&priv->lock); return rc; @@ -850,8 +865,6 @@ static int stmmac_set_tunable(struct net_device *dev, static const struct ethtool_ops stmmac_ethtool_ops = { .begin = stmmac_check_if_running, .get_drvinfo = stmmac_ethtool_getdrvinfo, - .get_settings = stmmac_ethtool_getsettings, - .set_settings = stmmac_ethtool_setsettings, .get_msglevel = stmmac_ethtool_getmsglevel, .set_msglevel = stmmac_ethtool_setmsglevel, .get_regs = stmmac_ethtool_gregs, @@ -871,6 +884,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = { .set_coalesce = stmmac_set_coalesce, .get_tunable = stmmac_get_tunable, .set_tunable = stmmac_set_tunable, + .get_link_ksettings = stmmac_ethtool_get_link_ksettings, + .set_link_ksettings = stmmac_ethtool_set_link_ksettings, }; void stmmac_set_ethtool_ops(struct net_device *netdev) -- cgit v1.2.3 From 2479876d460f9e7730c4ebc4e591325d6e5a5a0e Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Sat, 8 Oct 2016 17:46:15 +0200 Subject: net: ti: cpsw: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index c6cff3d2ff05..6d4b8a2e0cf6 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1967,27 +1967,30 @@ static int cpsw_get_ts_info(struct net_device *ndev, return 0; } -static int cpsw_get_settings(struct net_device *ndev, - struct ethtool_cmd *ecmd) +static int cpsw_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *ecmd) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; int slave_no = cpsw_slave_index(cpsw, priv); if (cpsw->slaves[slave_no].phy) - return phy_ethtool_gset(cpsw->slaves[slave_no].phy, ecmd); + return phy_ethtool_ksettings_get(cpsw->slaves[slave_no].phy, + ecmd); else return -EOPNOTSUPP; } -static int cpsw_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) +static int cpsw_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *ecmd) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; int slave_no = cpsw_slave_index(cpsw, priv); if (cpsw->slaves[slave_no].phy) - return phy_ethtool_sset(cpsw->slaves[slave_no].phy, ecmd); + return phy_ethtool_ksettings_set(cpsw->slaves[slave_no].phy, + ecmd); else return -EOPNOTSUPP; } @@ -2245,8 +2248,6 @@ static const struct ethtool_ops cpsw_ethtool_ops = { .set_msglevel = cpsw_set_msglevel, .get_link = ethtool_op_get_link, .get_ts_info = cpsw_get_ts_info, - .get_settings = cpsw_get_settings, - .set_settings = cpsw_set_settings, .get_coalesce = cpsw_get_coalesce, .set_coalesce = cpsw_set_coalesce, .get_sset_count = cpsw_get_sset_count, @@ -2262,6 +2263,8 @@ static const struct ethtool_ops cpsw_ethtool_ops = { .complete = cpsw_ethtool_op_complete, .get_channels = cpsw_get_channels, .set_channels = cpsw_set_channels, + .get_link_ksettings = cpsw_get_link_ksettings, + .set_link_ksettings = cpsw_set_link_ksettings, }; static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_common *cpsw, -- cgit v1.2.3 From 86e3a04002378610d77d3941f45ebbf531cf605e Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Sat, 8 Oct 2016 19:48:15 +0200 Subject: net: ti: netcp_ethss: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/netcp_ethss.c | 42 +++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index d543298d6750..48cb04fb7e0c 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -1840,8 +1840,8 @@ static void keystone_get_ethtool_stats(struct net_device *ndev, spin_unlock_bh(&gbe_dev->hw_stats_lock); } -static int keystone_get_settings(struct net_device *ndev, - struct ethtool_cmd *cmd) +static int keystone_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *cmd) { struct netcp_intf *netcp = netdev_priv(ndev); struct phy_device *phy = ndev->phydev; @@ -1858,20 +1858,28 @@ static int keystone_get_settings(struct net_device *ndev, if (!gbe_intf->slave) return -EINVAL; - ret = phy_ethtool_gset(phy, cmd); + ret = phy_ethtool_ksettings_get(phy, cmd); if (!ret) - cmd->port = gbe_intf->slave->phy_port_t; + cmd->base.port = gbe_intf->slave->phy_port_t; return ret; } -static int keystone_set_settings(struct net_device *ndev, - struct ethtool_cmd *cmd) +static int keystone_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd) { struct netcp_intf *netcp = netdev_priv(ndev); struct phy_device *phy = ndev->phydev; struct gbe_intf *gbe_intf; - u32 features = cmd->advertising & cmd->supported; + u8 port = cmd->base.port; + u32 advertising, supported; + u32 features; + + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + ethtool_convert_link_mode_to_legacy_u32(&supported, + cmd->link_modes.supported); + features = advertising & supported; if (!phy) return -EINVAL; @@ -1883,25 +1891,25 @@ static int keystone_set_settings(struct net_device *ndev, if (!gbe_intf->slave) return -EINVAL; - if (cmd->port != gbe_intf->slave->phy_port_t) { - if ((cmd->port == PORT_TP) && !(features & ADVERTISED_TP)) + if (port != gbe_intf->slave->phy_port_t) { + if ((port == PORT_TP) && !(features & ADVERTISED_TP)) return -EINVAL; - if ((cmd->port == PORT_AUI) && !(features & ADVERTISED_AUI)) + if ((port == PORT_AUI) && !(features & ADVERTISED_AUI)) return -EINVAL; - if ((cmd->port == PORT_BNC) && !(features & ADVERTISED_BNC)) + if ((port == PORT_BNC) && !(features & ADVERTISED_BNC)) return -EINVAL; - if ((cmd->port == PORT_MII) && !(features & ADVERTISED_MII)) + if ((port == PORT_MII) && !(features & ADVERTISED_MII)) return -EINVAL; - if ((cmd->port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE)) + if ((port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE)) return -EINVAL; } - gbe_intf->slave->phy_port_t = cmd->port; - return phy_ethtool_sset(phy, cmd); + gbe_intf->slave->phy_port_t = port; + return phy_ethtool_ksettings_set(phy, cmd); } static const struct ethtool_ops keystone_ethtool_ops = { @@ -1912,8 +1920,8 @@ static const struct ethtool_ops keystone_ethtool_ops = { .get_strings = keystone_get_stat_strings, .get_sset_count = keystone_get_sset_count, .get_ethtool_stats = keystone_get_ethtool_stats, - .get_settings = keystone_get_settings, - .set_settings = keystone_set_settings, + .get_link_ksettings = keystone_get_link_ksettings, + .set_link_ksettings = keystone_set_link_ksettings, }; #define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \ -- cgit v1.2.3 From 6e76510e7e19bfdca65042ccd52543011ed92047 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Sun, 9 Oct 2016 12:07:04 +0200 Subject: net: usb: lan78xx: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 70 +++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index db558b8b32fe..13f033cebf2d 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1092,7 +1092,7 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex, static int lan78xx_link_reset(struct lan78xx_net *dev) { struct phy_device *phydev = dev->net->phydev; - struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; + struct ethtool_link_ksettings ecmd; int ladv, radv, ret; u32 buf; @@ -1126,12 +1126,12 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) } else if (phydev->link && !dev->link_on) { dev->link_on = true; - phy_ethtool_gset(phydev, &ecmd); + phy_ethtool_ksettings_get(phydev, &ecmd); ret = phy_read(phydev, LAN88XX_INT_STS); if (dev->udev->speed == USB_SPEED_SUPER) { - if (ethtool_cmd_speed(&ecmd) == 1000) { + if (ecmd.base.speed == 1000) { /* disable U2 */ ret = lan78xx_read_reg(dev, USB_CFG1, &buf); buf &= ~USB_CFG1_DEV_U2_INIT_EN_; @@ -1159,9 +1159,10 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) netif_dbg(dev, link, dev->net, "speed: %u duplex: %d anadv: 0x%04x anlpa: 0x%04x", - ethtool_cmd_speed(&ecmd), ecmd.duplex, ladv, radv); + ecmd.base.speed, ecmd.base.duplex, ladv, radv); - ret = lan78xx_update_flowcontrol(dev, ecmd.duplex, ladv, radv); + ret = lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv, + radv); phy_mac_interrupt(phydev, 1); if (!timer_pending(&dev->stat_monitor)) { @@ -1484,7 +1485,8 @@ static void lan78xx_set_mdix_status(struct net_device *net, __u8 mdix_ctrl) dev->mdix_ctrl = mdix_ctrl; } -static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd) +static int lan78xx_get_link_ksettings(struct net_device *net, + struct ethtool_link_ksettings *cmd) { struct lan78xx_net *dev = netdev_priv(net); struct phy_device *phydev = net->phydev; @@ -1495,20 +1497,20 @@ static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd) if (ret < 0) return ret; - ret = phy_ethtool_gset(phydev, cmd); + ret = phy_ethtool_ksettings_get(phydev, cmd); buf = lan78xx_get_mdix_status(net); buf &= LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; if (buf == LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_) { - cmd->eth_tp_mdix = ETH_TP_MDI_AUTO; - cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; + cmd->base.eth_tp_mdix = ETH_TP_MDI_AUTO; + cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; } else if (buf == LAN88XX_EXT_MODE_CTRL_MDI_) { - cmd->eth_tp_mdix = ETH_TP_MDI; - cmd->eth_tp_mdix_ctrl = ETH_TP_MDI; + cmd->base.eth_tp_mdix = ETH_TP_MDI; + cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI; } else if (buf == LAN88XX_EXT_MODE_CTRL_MDI_X_) { - cmd->eth_tp_mdix = ETH_TP_MDI_X; - cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_X; + cmd->base.eth_tp_mdix = ETH_TP_MDI_X; + cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_X; } usb_autopm_put_interface(dev->intf); @@ -1516,7 +1518,8 @@ static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd) return ret; } -static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd) +static int lan78xx_set_link_ksettings(struct net_device *net, + const struct ethtool_link_ksettings *cmd) { struct lan78xx_net *dev = netdev_priv(net); struct phy_device *phydev = net->phydev; @@ -1527,14 +1530,13 @@ static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd) if (ret < 0) return ret; - if (dev->mdix_ctrl != cmd->eth_tp_mdix_ctrl) { - lan78xx_set_mdix_status(net, cmd->eth_tp_mdix_ctrl); - } + if (dev->mdix_ctrl != cmd->base.eth_tp_mdix_ctrl) + lan78xx_set_mdix_status(net, cmd->base.eth_tp_mdix_ctrl); /* change speed & duplex */ - ret = phy_ethtool_sset(phydev, cmd); + ret = phy_ethtool_ksettings_set(phydev, cmd); - if (!cmd->autoneg) { + if (!cmd->base.autoneg) { /* force link down */ temp = phy_read(phydev, MII_BMCR); phy_write(phydev, MII_BMCR, temp | BMCR_LOOPBACK); @@ -1552,9 +1554,9 @@ static void lan78xx_get_pause(struct net_device *net, { struct lan78xx_net *dev = netdev_priv(net); struct phy_device *phydev = net->phydev; - struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; + struct ethtool_link_ksettings ecmd; - phy_ethtool_gset(phydev, &ecmd); + phy_ethtool_ksettings_get(phydev, &ecmd); pause->autoneg = dev->fc_autoneg; @@ -1570,12 +1572,12 @@ static int lan78xx_set_pause(struct net_device *net, { struct lan78xx_net *dev = netdev_priv(net); struct phy_device *phydev = net->phydev; - struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; + struct ethtool_link_ksettings ecmd; int ret; - phy_ethtool_gset(phydev, &ecmd); + phy_ethtool_ksettings_get(phydev, &ecmd); - if (pause->autoneg && !ecmd.autoneg) { + if (pause->autoneg && !ecmd.base.autoneg) { ret = -EINVAL; goto exit; } @@ -1587,13 +1589,21 @@ static int lan78xx_set_pause(struct net_device *net, if (pause->tx_pause) dev->fc_request_control |= FLOW_CTRL_TX; - if (ecmd.autoneg) { + if (ecmd.base.autoneg) { u32 mii_adv; + u32 advertising; + + ethtool_convert_link_mode_to_legacy_u32( + &advertising, ecmd.link_modes.advertising); - ecmd.advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); + advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control); - ecmd.advertising |= mii_adv_to_ethtool_adv_t(mii_adv); - phy_ethtool_sset(phydev, &ecmd); + advertising |= mii_adv_to_ethtool_adv_t(mii_adv); + + ethtool_convert_legacy_u32_to_link_mode( + ecmd.link_modes.advertising, advertising); + + phy_ethtool_ksettings_set(phydev, &ecmd); } dev->fc_autoneg = pause->autoneg; @@ -1609,8 +1619,6 @@ static const struct ethtool_ops lan78xx_ethtool_ops = { .get_drvinfo = lan78xx_get_drvinfo, .get_msglevel = lan78xx_get_msglevel, .set_msglevel = lan78xx_set_msglevel, - .get_settings = lan78xx_get_settings, - .set_settings = lan78xx_set_settings, .get_eeprom_len = lan78xx_ethtool_get_eeprom_len, .get_eeprom = lan78xx_ethtool_get_eeprom, .set_eeprom = lan78xx_ethtool_set_eeprom, @@ -1623,6 +1631,8 @@ static const struct ethtool_ops lan78xx_ethtool_ops = { .set_eee = lan78xx_set_eee, .get_pauseparam = lan78xx_get_pause, .set_pauseparam = lan78xx_set_pause, + .get_link_ksettings = lan78xx_get_link_ksettings, + .set_link_ksettings = lan78xx_set_link_ksettings, }; static int lan78xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) -- cgit v1.2.3 From 751d6fd18fb3c6cc123dce844200ddbf5a8ad1a8 Mon Sep 17 00:00:00 2001 From: Iyappan Subramanian Date: Thu, 6 Oct 2016 14:35:57 -0700 Subject: drivers: net: xgene: fix: Use GPIO to get link status The link value reported by the link status register is not reliable when no SPF module inserted. This patchset fixes this issue by using GPIO to determine the link status. Signed-off-by: Iyappan Subramanian Signed-off-by: Quan Nguyen Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 6 +++++- drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 1 + drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 19 +++++++++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 429f18fc5503..f75d9556152f 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1381,9 +1381,13 @@ static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; - if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) + pdata->sfp_gpio_en = false; + if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII || + (!device_property_present(dev, "sfp-gpios") && + !device_property_present(dev, "rxlos-gpios"))) return; + pdata->sfp_gpio_en = true; pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN); if (IS_ERR(pdata->sfp_rdy)) pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN); diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h index 0cda58f5a840..011965b54d1f 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h @@ -219,6 +219,7 @@ struct xgene_enet_pdata { u8 rx_delay; bool mdio_driver; struct gpio_desc *sfp_rdy; + bool sfp_gpio_en; }; struct xgene_indirect_ctl { diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c index 6475f383ba83..d1758b072623 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c @@ -415,16 +415,31 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata, xgene_enet_wr_ring_if(pdata, addr, data); } +static int xgene_enet_gpio_lookup(struct xgene_enet_pdata *pdata) +{ + struct device *dev = &pdata->pdev->dev; + + pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN); + if (IS_ERR(pdata->sfp_rdy)) + pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN); + + if (IS_ERR(pdata->sfp_rdy)) + return -ENODEV; + + return 0; +} + static void xgene_enet_link_state(struct work_struct *work) { struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work), struct xgene_enet_pdata, link_work); - struct gpio_desc *sfp_rdy = pdata->sfp_rdy; struct net_device *ndev = pdata->ndev; u32 link_status, poll_interval; link_status = xgene_enet_link_status(pdata); - if (link_status && !IS_ERR(sfp_rdy) && !gpiod_get_value(sfp_rdy)) + if (pdata->sfp_gpio_en && link_status && + (!IS_ERR(pdata->sfp_rdy) || !xgene_enet_gpio_lookup(pdata)) && + !gpiod_get_value(pdata->sfp_rdy)) link_status = 0; if (link_status) { -- cgit v1.2.3 From 69b624983f94f2a877449c1e6c34f21c97440f25 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 6 Jul 2016 23:04:56 +0900 Subject: drm/nouveau/ibus/gk20a: use udelay() in interrupt context gk20a_ibus_init_ibus_ring() can be called from gk20a_ibus_intr(), in non-interruptible context. Replace use of usleep_range() with udelay(). Reported-by: Thierry Reding Signed-off-by: Alexandre Courbot Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c index b7159b338fac..1a4ab825852c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c @@ -29,7 +29,7 @@ gk20a_ibus_init_ibus_ring(struct nvkm_subdev *ibus) nvkm_mask(device, 0x137250, 0x3f, 0); nvkm_mask(device, 0x000200, 0x20, 0); - usleep_range(20, 30); + udelay(20); nvkm_mask(device, 0x000200, 0x20, 0x20); nvkm_wr32(device, 0x12004c, 0x4); -- cgit v1.2.3 From 9936aeeaebce816ba428eedf4da4b1a8e92e77f9 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 27 Jul 2016 01:00:31 -0400 Subject: drm/nouveau/nouveau: bios pointers may be unaligned, use proper accessors This can show up on SPARC or other architectures that don't handle unaligned accesses. The kernel normally fixes these up, but it shouldn't have to. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96836 Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.h | 6 ++---- drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 0067586eb015..18eb061ccafb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -31,10 +31,8 @@ #define DCB_LOC_ON_CHIP 0 -#define ROM16(x) le16_to_cpu(*(u16 *)&(x)) -#define ROM32(x) le32_to_cpu(*(u32 *)&(x)) -#define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); }) -#define ROM64(x) le64_to_cpu(*(u64 *)&(x)) +#define ROM16(x) get_unaligned_le16(&(x)) +#define ROM32(x) get_unaligned_le32(&(x)) #define ROMPTR(d,x) ({ \ struct nouveau_drm *drm = nouveau_drm((d)); \ ROM16(x) ? &drm->vbios.data[ROM16(x)] : NULL; \ diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c index 45a2f8e784f9..9abfa5e2fe9f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c @@ -23,8 +23,8 @@ */ #include "mxms.h" -#define ROM16(x) le16_to_cpu(*(u16 *)&(x)) -#define ROM32(x) le32_to_cpu(*(u32 *)&(x)) +#define ROM16(x) get_unaligned_le16(&(x)) +#define ROM32(x) get_unaligned_le32(&(x)) static u8 * mxms_data(struct nvkm_mxm *mxm) -- cgit v1.2.3 From a8c119a4d0af1633eb37af87c61b632646894329 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Wed, 27 Jul 2016 21:49:47 +0200 Subject: drm/nouveau/iccsense: Parse the resistors and config the right way Previously we parsed that table a bit wrong: 1. The entry layout depends on the sensor type used. 2. We have all resitors in one entry for the INA3221. 3. The config is already included in the vbios. This commit addresses that issue and with that we should be able to read out the right power consumption for every GPU with a INA209, INA219 and INA3221. Signed-off-by: Karol Herbst Signed-off-by: Ben Skeggs --- .../nouveau/include/nvkm/subdev/bios/iccsense.h | 10 +- .../gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c | 33 +++++- .../gpu/drm/nouveau/nvkm/subdev/iccsense/base.c | 129 +++++++-------------- .../gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h | 2 +- 4 files changed, 82 insertions(+), 92 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h index 9cb97477248b..e933d3eede70 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h @@ -1,10 +1,16 @@ #ifndef __NVBIOS_ICCSENSE_H__ #define __NVBIOS_ICCSENSE_H__ +struct pwr_rail_resistor_t { + u8 mohm; + bool enabled; +}; + struct pwr_rail_t { u8 mode; u8 extdev_id; - u8 resistor_mohm; - u8 rail; + u8 resistor_count; + struct pwr_rail_resistor_t resistors[3]; + u16 config; }; struct nvbios_iccsense { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c index 084328028af1..aafd5e17b1c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c @@ -23,6 +23,7 @@ */ #include #include +#include #include static u16 @@ -77,23 +78,47 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense) return -ENOMEM; for (i = 0; i < cnt; ++i) { + struct nvbios_extdev_func extdev; struct pwr_rail_t *rail = &iccsense->rail[i]; + u8 res_start = 0; + int r; + entry = table + hdr + i * len; switch(ver) { case 0x10: rail->mode = nvbios_rd08(bios, entry + 0x1); rail->extdev_id = nvbios_rd08(bios, entry + 0x2); - rail->resistor_mohm = nvbios_rd08(bios, entry + 0x3); - rail->rail = nvbios_rd08(bios, entry + 0x4); + res_start = 0x3; break; case 0x20: rail->mode = nvbios_rd08(bios, entry); rail->extdev_id = nvbios_rd08(bios, entry + 0x1); - rail->resistor_mohm = nvbios_rd08(bios, entry + 0x5); - rail->rail = nvbios_rd08(bios, entry + 0x6); + res_start = 0x5; + break; + }; + + if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev)) + continue; + + switch (extdev.type) { + case NVBIOS_EXTDEV_INA209: + case NVBIOS_EXTDEV_INA219: + rail->resistor_count = 1; + break; + case NVBIOS_EXTDEV_INA3221: + rail->resistor_count = 3; + break; + default: + rail->resistor_count = 0; break; }; + + for (r = 0; r < rail->resistor_count; ++r) { + rail->resistors[r].mohm = nvbios_rd08(bios, entry + res_start + r * 2); + rail->resistors[r].enabled = !(nvbios_rd08(bios, entry + res_start + r * 2 + 1) & 0x40); + } + rail->config = nvbios_rd16(bios, entry + res_start + rail->resistor_count * 2); } return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c index 41bd5d0f7692..658355fc9354 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -95,61 +95,13 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, 40 * 8); } -static void -nvkm_iccsense_ina209_config(struct nvkm_iccsense *iccsense, - struct nvkm_iccsense_sensor *sensor) -{ - struct nvkm_subdev *subdev = &iccsense->subdev; - /* configuration: - * 0x0007: 0x0007 shunt and bus continous - * 0x0078: 0x0078 128 samples shunt - * 0x0780: 0x0780 128 samples bus - * 0x1800: 0x0000 +-40 mV shunt range - * 0x2000: 0x0000 16V FSR - */ - u16 value = 0x07ff; - nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value); - nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value); -} - -static void -nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense, - struct nvkm_iccsense_sensor *sensor) -{ - struct nvkm_subdev *subdev = &iccsense->subdev; - /* configuration: - * 0x0007: 0x0007 shunt and bus continous - * 0x0031: 0x0000 140 us conversion time shunt - * 0x01c0: 0x0000 140 us conversion time bus - * 0x0f00: 0x0f00 1024 samples - * 0x7000: 0x?000 channels - */ - u16 value = 0x0e07; - if (sensor->rail_mask & 0x1) - value |= 0x1 << 14; - if (sensor->rail_mask & 0x2) - value |= 0x1 << 13; - if (sensor->rail_mask & 0x4) - value |= 0x1 << 12; - nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value); - nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value); -} - static void nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense, struct nvkm_iccsense_sensor *sensor) { - switch (sensor->type) { - case NVBIOS_EXTDEV_INA209: - case NVBIOS_EXTDEV_INA219: - nvkm_iccsense_ina209_config(iccsense, sensor); - break; - case NVBIOS_EXTDEV_INA3221: - nvkm_iccsense_ina3221_config(iccsense, sensor); - break; - default: - break; - } + struct nvkm_subdev *subdev = &iccsense->subdev; + nvkm_trace(subdev, "write config of extdev %i: 0x%04x\n", sensor->id, sensor->config); + nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, sensor->config); } int @@ -196,7 +148,6 @@ nvkm_iccsense_dtor(struct nvkm_subdev *subdev) static struct nvkm_iccsense_sensor* nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id) { - struct nvkm_subdev *subdev = &iccsense->subdev; struct nvkm_bios *bios = subdev->device->bios; struct nvkm_i2c *i2c = subdev->device->i2c; @@ -245,7 +196,7 @@ nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id) sensor->type = extdev.type; sensor->i2c = &i2c_bus->i2c; sensor->addr = addr; - sensor->rail_mask = 0x0; + sensor->config = 0x0; return sensor; } @@ -273,48 +224,56 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) iccsense->data_valid = true; for (i = 0; i < stbl.nr_entry; ++i) { - struct pwr_rail_t *r = &stbl.rail[i]; - struct nvkm_iccsense_rail *rail; + struct pwr_rail_t *pwr_rail = &stbl.rail[i]; struct nvkm_iccsense_sensor *sensor; - int (*read)(struct nvkm_iccsense *, - struct nvkm_iccsense_rail *); + int r; - if (!r->mode || r->resistor_mohm == 0) + if (pwr_rail->mode != 1 || !pwr_rail->resistor_count) continue; - sensor = nvkm_iccsense_get_sensor(iccsense, r->extdev_id); + sensor = nvkm_iccsense_get_sensor(iccsense, pwr_rail->extdev_id); if (!sensor) continue; - switch (sensor->type) { - case NVBIOS_EXTDEV_INA209: - if (r->rail != 0) - continue; - read = nvkm_iccsense_ina209_read; - break; - case NVBIOS_EXTDEV_INA219: - if (r->rail != 0) + if (!sensor->config) + sensor->config = pwr_rail->config; + else if (sensor->config != pwr_rail->config) + nvkm_error(subdev, "config mismatch found for extdev %i\n", pwr_rail->extdev_id); + + for (r = 0; r < pwr_rail->resistor_count; ++r) { + struct nvkm_iccsense_rail *rail; + struct pwr_rail_resistor_t *res = &pwr_rail->resistors[r]; + int (*read)(struct nvkm_iccsense *, + struct nvkm_iccsense_rail *); + + if (!res->mohm || !res->enabled) continue; - read = nvkm_iccsense_ina219_read; - break; - case NVBIOS_EXTDEV_INA3221: - if (r->rail >= 3) + + switch (sensor->type) { + case NVBIOS_EXTDEV_INA209: + read = nvkm_iccsense_ina209_read; + break; + case NVBIOS_EXTDEV_INA219: + read = nvkm_iccsense_ina219_read; + break; + case NVBIOS_EXTDEV_INA3221: + read = nvkm_iccsense_ina3221_read; + break; + default: continue; - read = nvkm_iccsense_ina3221_read; - break; - default: - continue; + } + + rail = kmalloc(sizeof(*rail), GFP_KERNEL); + if (!rail) + return -ENOMEM; + + rail->read = read; + rail->sensor = sensor; + rail->idx = r; + rail->mohm = res->mohm; + nvkm_debug(subdev, "create rail for extdev %i: { idx: %i, mohm: %i }\n", pwr_rail->extdev_id, r, rail->mohm); + list_add_tail(&rail->head, &iccsense->rails); } - - rail = kmalloc(sizeof(*rail), GFP_KERNEL); - if (!rail) - return -ENOMEM; - sensor->rail_mask |= 1 << r->rail; - rail->read = read; - rail->sensor = sensor; - rail->idx = r->rail; - rail->mohm = r->resistor_mohm; - list_add_tail(&rail->head, &iccsense->rails); } return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h index b72c31d2f908..e90e0f6ed008 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h @@ -10,7 +10,7 @@ struct nvkm_iccsense_sensor { enum nvbios_extdev_type type; struct i2c_adapter *i2c; u8 addr; - u8 rail_mask; + u16 config; }; struct nvkm_iccsense_rail { -- cgit v1.2.3 From cc90badd3c077ee18f82114988dbd53faf8f34c3 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/clk: Fix potential NULL pointer access when there is no fb subdev Signed-off-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 7102c25320fc..1defd3215ed3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -175,7 +175,7 @@ static int nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei) { struct nvkm_subdev *subdev = &clk->subdev; - struct nvkm_ram *ram = subdev->device->fb->ram; + struct nvkm_fb *fb = subdev->device->fb; struct nvkm_pci *pci = subdev->device->pci; struct nvkm_pstate *pstate; int ret, idx = 0; @@ -190,7 +190,8 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei) nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width); - if (ram && ram->func->calc) { + if (fb && fb->ram && fb->ram->func->calc) { + struct nvkm_ram *ram = fb->ram; int khz = pstate->base.domain[nv_clk_src_mem]; do { ret = ram->func->calc(ram, khz); -- cgit v1.2.3 From 380b1cadb0ef26165ba4b15fcf1bd2f1d82d0c29 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:10 +0200 Subject: drm/nouveau/fb/ramgk104: Touch 0x62c000 only when there is a display engine Signed-off-by: Karol Herbst Tested-by: Aidan Epstein Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c index 1fa3ade468ae..93b30d92776c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c @@ -259,7 +259,9 @@ gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq) ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000); ram_block(fuc); - ram_wr32(fuc, 0x62c000, 0x0f0f0000); + + if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP)) + ram_wr32(fuc, 0x62c000, 0x0f0f0000); /* MR1: turn termination on early, for some reason.. */ if ((ram->base.mr[1] & 0x03c) != 0x030) { @@ -658,7 +660,9 @@ gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq) gk104_ram_train(fuc, 0x80020000, 0x01000000); ram_unblock(fuc); - ram_wr32(fuc, 0x62c000, 0x0f0f0f00); + + if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP)) + ram_wr32(fuc, 0x62c000, 0x0f0f0f00); if (next->bios.rammap_11_08_01) data = 0x00000800; @@ -706,7 +710,9 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq) ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000); ram_block(fuc); - ram_wr32(fuc, 0x62c000, 0x0f0f0000); + + if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP)) + ram_wr32(fuc, 0x62c000, 0x0f0f0000); if (vc == 1 && ram_have(fuc, gpio2E)) { u32 temp = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]); @@ -936,7 +942,9 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq) ram_nsec(fuc, 1000); ram_unblock(fuc); - ram_wr32(fuc, 0x62c000, 0x0f0f0f00); + + if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP)) + ram_wr32(fuc, 0x62c000, 0x0f0f0f00); if (next->bios.rammap_11_08_01) data = 0x00000800; -- cgit v1.2.3 From 32dd7f2329765f428a824d91819bb8db7af432c5 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/bios/volt: Handle voltage table version 0x50 with zeroed header Some Fermi+ GPUs specify VID information via voltage table entries, rather than describing them as a range in the header. The mask may be bigger than 0x1fffff, but this value is already >2V, so it will be fine for now. This patch fixes volting issues on those cards enabling them to switch cstates. v6: rework message Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Tested-by: Pierre Moreau Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c index 6e0a33648be9..81a47b22617a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c @@ -142,7 +142,10 @@ nvbios_volt_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len, info->vid = nvbios_rd08(bios, volt + 0x01) >> 2; break; case 0x40: + break; case 0x50: + info->voltage = nvbios_rd32(bios, volt) & 0x001fffff; + info->vid = (nvbios_rd32(bios, volt) >> 23) & 0xff; break; } return volt; -- cgit v1.2.3 From 17f486de6a56ee255eaa6dae272f70255cc41d3d Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/volt: Properly detect entry based voltage tables There is a field in the voltage table which tells us if the VIDs are taken from the entries or calculated through the header. v2: Don't break older versions. v5: Reverse flag name. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Tested-by: Pierre Moreau Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h | 5 +++-- drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c | 12 +++++++++--- drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 7 +++++-- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h index b0df610cec2b..23f3d1b93ebb 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h @@ -13,8 +13,9 @@ struct nvbios_volt { u32 base; /* GPIO mode */ - u8 vidmask; - s16 step; + bool ranged; + u8 vidmask; + s16 step; /* PWM mode */ u32 pwm_freq; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c index 81a47b22617a..4504822ace51 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c @@ -75,20 +75,24 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, case 0x12: info->type = NVBIOS_VOLT_GPIO; info->vidmask = nvbios_rd08(bios, volt + 0x04); + info->ranged = false; break; case 0x20: info->type = NVBIOS_VOLT_GPIO; info->vidmask = nvbios_rd08(bios, volt + 0x05); + info->ranged = false; break; case 0x30: info->type = NVBIOS_VOLT_GPIO; info->vidmask = nvbios_rd08(bios, volt + 0x04); + info->ranged = false; break; case 0x40: info->type = NVBIOS_VOLT_GPIO; info->base = nvbios_rd32(bios, volt + 0x04); info->step = nvbios_rd16(bios, volt + 0x08); info->vidmask = nvbios_rd08(bios, volt + 0x0b); + info->ranged = true; /* XXX: find the flag byte */ /*XXX*/ info->min = 0; info->max = info->base; @@ -104,9 +108,11 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, info->pwm_freq = nvbios_rd32(bios, volt + 0x5) / 1000; info->pwm_range = nvbios_rd32(bios, volt + 0x16); } else { - info->type = NVBIOS_VOLT_GPIO; - info->vidmask = nvbios_rd08(bios, volt + 0x06); - info->step = nvbios_rd16(bios, volt + 0x16); + info->type = NVBIOS_VOLT_GPIO; + info->vidmask = nvbios_rd08(bios, volt + 0x06); + info->step = nvbios_rd16(bios, volt + 0x16); + info->ranged = + !!(nvbios_rd08(bios, volt + 0x4) & 0x2); } break; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 1c3d23b0e84a..53a1cba6ad8d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -112,6 +112,7 @@ nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition) static void nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt) { + struct nvkm_subdev *subdev = &bios->subdev; struct nvbios_volt_entry ivid; struct nvbios_volt info; u8 ver, hdr, cnt, len; @@ -119,7 +120,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt) int i; data = nvbios_volt_parse(bios, &ver, &hdr, &cnt, &len, &info); - if (data && info.vidmask && info.base && info.step) { + if (data && info.vidmask && info.base && info.step && info.ranged) { + nvkm_debug(subdev, "found ranged based VIDs\n"); volt->min_uv = info.min; volt->max_uv = info.max; for (i = 0; i < info.vidmask + 1; i++) { @@ -132,7 +134,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt) info.base += info.step; } volt->vid_mask = info.vidmask; - } else if (data && info.vidmask) { + } else if (data && info.vidmask && !info.ranged) { + nvkm_debug(subdev, "found entry based VIDs\n"); volt->min_uv = 0xffffffff; volt->max_uv = 0; for (i = 0; i < cnt; i++) { -- cgit v1.2.3 From 17d063dbdce3bab04957b2281dcdceecb7407170 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/clk: Don't create cstates with voltages higher than what the gpu can do nvkm_volt_map_min is a copy of nvkm_volt_map, which always returns the lowest possible voltage for a cstate. nvkm_volt_map will get a temperature parameter there later and also fix the voltage calculation, so that this functions will be completly different later. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Tested-by: Pierre Moreau Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 4 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index b765f4ffcde6..fc68825ffcbb 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h @@ -17,6 +17,7 @@ struct nvkm_volt { u32 min_uv; }; +int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id); int nvkm_volt_get(struct nvkm_volt *); int nvkm_volt_set_id(struct nvkm_volt *, u8 id, int condition); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 1defd3215ed3..2881b2ceda32 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -138,6 +138,7 @@ static int nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate) { struct nvkm_bios *bios = clk->subdev.device->bios; + struct nvkm_volt *volt = clk->subdev.device->volt; const struct nvkm_domain *domain = clk->domains; struct nvkm_cstate *cstate = NULL; struct nvbios_cstepX cstepX; @@ -148,6 +149,9 @@ nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate) if (!data) return -ENOENT; + if (volt && nvkm_volt_map_min(volt, cstepX.voltage) > volt->max_uv) + return -EINVAL; + cstate = kzalloc(sizeof(*cstate), GFP_KERNEL); if (!cstate) return -ENOMEM; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 53a1cba6ad8d..6eeb9d9de334 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -65,6 +65,28 @@ nvkm_volt_set(struct nvkm_volt *volt, u32 uv) return ret; } +int +nvkm_volt_map_min(struct nvkm_volt *volt, u8 id) +{ + struct nvkm_bios *bios = volt->subdev.device->bios; + struct nvbios_vmap_entry info; + u8 ver, len; + u16 vmap; + + vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info); + if (vmap) { + if (info.link != 0xff) { + int ret = nvkm_volt_map_min(volt, info.link); + if (ret < 0) + return ret; + info.min += ret; + } + return info.min; + } + + return id ? id * 10000 : -ENODEV; +} + static int nvkm_volt_map(struct nvkm_volt *volt, u8 id) { -- cgit v1.2.3 From 4a4555a7f1dd60fe34336f440ff1de73313820ee Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/volt: Parse the max voltage map entries There are at least three "max" entries, which specify the max voltage. Because they are actually normal voltage map entries, they can also be affected by the temperature. Nvidia respects those entries and if they get changed, nvidia uses the lower voltage from all three. We shouldn't exceed those voltages at any given time. v2: State what those entries do in the source. v3: Add the third max entry. v5: Better describe the entries. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h | 3 +++ drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h | 10 ++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c | 10 ++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 13 +++++++++++++ 4 files changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h index 6633c6db9281..ae2f27be3f29 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h @@ -1,6 +1,9 @@ #ifndef __NVBIOS_VMAP_H__ #define __NVBIOS_VMAP_H__ struct nvbios_vmap { + u8 max0; + u8 max1; + u8 max2; }; u16 nvbios_vmap_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index fc68825ffcbb..2612a04c49bb 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h @@ -15,6 +15,16 @@ struct nvkm_volt { u32 max_uv; u32 min_uv; + + /* + * These are fully functional map entries creating a sw ceiling for + * the voltage. These all can describe different kind of curves, so + * that for any given temperature a different one can return the lowest + * value of all three. + */ + u8 max0_id; + u8 max1_id; + u8 max2_id; }; int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c index 2f13db745948..f2295e180e5e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c @@ -61,7 +61,17 @@ nvbios_vmap_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, memset(info, 0x00, sizeof(*info)); switch (!!vmap * *ver) { case 0x10: + info->max0 = 0xff; + info->max1 = 0xff; + info->max2 = 0xff; + break; case 0x20: + info->max0 = nvbios_rd08(bios, vmap + 0x7); + info->max1 = nvbios_rd08(bios, vmap + 0x8); + if (*len >= 0xc) + info->max2 = nvbios_rd08(bios, vmap + 0xc); + else + info->max2 = 0xff; break; } return vmap; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 6eeb9d9de334..8445e4c9fe54 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -216,9 +216,22 @@ nvkm_volt_ctor(const struct nvkm_volt_func *func, struct nvkm_device *device, /* Assuming the non-bios device should build the voltage table later */ if (bios) { + u8 ver, hdr, cnt, len; + struct nvbios_vmap vmap; + nvkm_volt_parse_bios(bios, volt); nvkm_debug(&volt->subdev, "min: %iuv max: %iuv\n", volt->min_uv, volt->max_uv); + + if (nvbios_vmap_parse(bios, &ver, &hdr, &cnt, &len, &vmap)) { + volt->max0_id = vmap.max0; + volt->max1_id = vmap.max1; + volt->max2_id = vmap.max2; + } else { + volt->max0_id = 0xff; + volt->max1_id = 0xff; + volt->max2_id = 0xff; + } } if (volt->vid_nr) { -- cgit v1.2.3 From fa6c4d8e2c614817c956a4ab59ab8bb24fb3653f Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/volt: Add min_id parameter to nvkm_volt_set_id Each pstate has its own voltage map entry like each cstate has. The voltages of those entries act as a floor value for the currently selected pstate and nvidia never sets a voltage below them. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6 ++++-- drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 5 ++++- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index 2612a04c49bb..06d45934b6a0 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h @@ -29,7 +29,7 @@ struct nvkm_volt { int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id); int nvkm_volt_get(struct nvkm_volt *); -int nvkm_volt_set_id(struct nvkm_volt *, u8 id, int condition); +int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, int condition); int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **); int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 2881b2ceda32..9ee24ec2869b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -99,7 +99,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) } if (volt) { - ret = nvkm_volt_set_id(volt, cstate->voltage, +1); + ret = nvkm_volt_set_id(volt, cstate->voltage, + pstate->base.voltage, +1); if (ret && ret != -ENODEV) { nvkm_error(subdev, "failed to raise voltage: %d\n", ret); return ret; @@ -113,7 +114,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) } if (volt) { - ret = nvkm_volt_set_id(volt, cstate->voltage, -1); + ret = nvkm_volt_set_id(volt, cstate->voltage, + pstate->base.voltage, -1); if (ret && ret != -ENODEV) nvkm_error(subdev, "failed to lower voltage: %d\n", ret); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 8445e4c9fe54..960505be5e28 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -110,7 +110,7 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id) } int -nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition) +nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, u8 min_id, int condition) { int ret; @@ -123,6 +123,9 @@ nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition) if (!condition || prev < 0 || (condition < 0 && ret < prev) || (condition > 0 && ret > prev)) { + int min = nvkm_volt_map(volt, min_id); + if (min >= 0) + ret = max(min, ret); ret = nvkm_volt_set(volt, ret); } else { ret = 0; -- cgit v1.2.3 From 761c8f69afdf34c100ccdde1df01163cda4f25e8 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/clk: Add index field to nvkm_cstate It is better to read out the id out of the cstate struct directly instead of iterating over the list of cstates over and over again. Especially when we start saving pointers to a nvkm_cstate struct, it makes things easier. v5: Rename field to id. Signed-off-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h index fb54417bc458..70c8665756ca 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h @@ -52,6 +52,7 @@ struct nvkm_cstate { struct list_head head; u8 voltage; u32 domain[nv_clk_src_max]; + u8 id; }; struct nvkm_pstate { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 9ee24ec2869b..23cc04c37c07 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -160,6 +160,7 @@ nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate) *cstate = pstate->base; cstate->voltage = cstepX.voltage; + cstate->id = idx; while (domain && domain->name != nv_clk_src_max) { if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) { -- cgit v1.2.3 From 61a8b84f1cff6051f51b30ad96417dd948dc72da Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sun, 17 Jul 2016 09:40:23 +0200 Subject: drm/nouveau/clk: Let nvkm_clk_tstate take a temperature value This way other subdevs can notify the clk subdev about temperature changes without the need of clk to poll that value. Also make this function safe to be called from an interrupt handler. Signed-off-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 19 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h index 70c8665756ca..0cf3d86e399a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h @@ -94,8 +94,8 @@ struct nvkm_clk { int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */ int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */ int astate; /* perfmon adjustment (base) */ - int tstate; /* thermal adjustment (max-) */ int dstate; /* display adjustment (min+) */ + u8 temp; bool allow_reclock; @@ -111,7 +111,7 @@ int nvkm_clk_read(struct nvkm_clk *, enum nv_clk_src); int nvkm_clk_ustate(struct nvkm_clk *, int req, int pwr); int nvkm_clk_astate(struct nvkm_clk *, int req, int rel, bool wait); int nvkm_clk_dstate(struct nvkm_clk *, int req, int rel); -int nvkm_clk_tstate(struct nvkm_clk *, int req, int rel); +int nvkm_clk_tstate(struct nvkm_clk *, u8 temperature); int nv04_clk_new(struct nvkm_device *, int, struct nvkm_clk **); int nv40_clk_new(struct nvkm_device *, int, struct nvkm_clk **); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 23cc04c37c07..88a517c33842 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -222,14 +222,14 @@ nvkm_pstate_work(struct work_struct *work) return; clk->pwrsrc = power_supply_is_system_supplied(); - nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n", + nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d°C D %d\n", clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc, - clk->astate, clk->tstate, clk->dstate); + clk->astate, clk->temp, clk->dstate); pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc; if (clk->state_nr && pstate != -1) { pstate = (pstate < 0) ? clk->astate : pstate; - pstate = min(pstate, clk->state_nr - 1 + clk->tstate); + pstate = min(pstate, clk->state_nr - 1); pstate = max(pstate, clk->dstate); } else { pstate = clk->pstate = -1; @@ -456,13 +456,12 @@ nvkm_clk_astate(struct nvkm_clk *clk, int req, int rel, bool wait) } int -nvkm_clk_tstate(struct nvkm_clk *clk, int req, int rel) +nvkm_clk_tstate(struct nvkm_clk *clk, u8 temp) { - if (!rel) clk->tstate = req; - if ( rel) clk->tstate += rel; - clk->tstate = min(clk->tstate, 0); - clk->tstate = max(clk->tstate, -(clk->state_nr - 1)); - return nvkm_pstate_calc(clk, true); + if (clk->temp == temp) + return 0; + clk->temp = temp; + return nvkm_pstate_calc(clk, false); } int @@ -532,9 +531,9 @@ nvkm_clk_init(struct nvkm_subdev *subdev) return clk->func->init(clk); clk->astate = clk->state_nr - 1; - clk->tstate = 0; clk->dstate = 0; clk->pstate = -1; + clk->temp = 90; /* reasonable default value */ nvkm_pstate_calc(clk, true); return 0; } -- cgit v1.2.3 From 8d08c264d2b26c7b9c10790f95464b21e28dc30d Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/volt: Add temperature parameter to nvkm_volt_map The voltage entries actually may map to a different voltage depending on the current temperature. v2: Only read the temperature when actually needed. v5: Be smarter about using max(). Don't read the temperature anymore. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 12 +++++++----- 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index 06d45934b6a0..6fd933df763e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h @@ -29,7 +29,8 @@ struct nvkm_volt { int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id); int nvkm_volt_get(struct nvkm_volt *); -int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, int condition); +int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, u8 temp, + int condition); int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **); int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 88a517c33842..98168be93515 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -100,7 +100,7 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) if (volt) { ret = nvkm_volt_set_id(volt, cstate->voltage, - pstate->base.voltage, +1); + pstate->base.voltage, clk->temp, +1); if (ret && ret != -ENODEV) { nvkm_error(subdev, "failed to raise voltage: %d\n", ret); return ret; @@ -115,7 +115,7 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) if (volt) { ret = nvkm_volt_set_id(volt, cstate->voltage, - pstate->base.voltage, -1); + pstate->base.voltage, clk->temp, -1); if (ret && ret != -ENODEV) nvkm_error(subdev, "failed to lower voltage: %d\n", ret); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 960505be5e28..40ba088a5c81 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -26,6 +26,7 @@ #include #include #include +#include int nvkm_volt_get(struct nvkm_volt *volt) @@ -88,7 +89,7 @@ nvkm_volt_map_min(struct nvkm_volt *volt, u8 id) } static int -nvkm_volt_map(struct nvkm_volt *volt, u8 id) +nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp) { struct nvkm_bios *bios = volt->subdev.device->bios; struct nvbios_vmap_entry info; @@ -98,7 +99,7 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id) vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info); if (vmap) { if (info.link != 0xff) { - int ret = nvkm_volt_map(volt, info.link); + int ret = nvkm_volt_map(volt, info.link, temp); if (ret < 0) return ret; info.min += ret; @@ -110,20 +111,21 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id) } int -nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, u8 min_id, int condition) +nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, u8 min_id, u8 temp, + int condition) { int ret; if (volt->func->set_id) return volt->func->set_id(volt, id, condition); - ret = nvkm_volt_map(volt, id); + ret = nvkm_volt_map(volt, id, temp); if (ret >= 0) { int prev = nvkm_volt_get(volt); if (!condition || prev < 0 || (condition < 0 && ret < prev) || (condition > 0 && ret > prev)) { - int min = nvkm_volt_map(volt, min_id); + int min = nvkm_volt_map(volt, min_id, temp); if (min >= 0) ret = max(min, ret); ret = nvkm_volt_set(volt, ret); -- cgit v1.2.3 From 0d6f81003e9ecc2d6552be92d3d894c916097552 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/clk: Fixup cstate selection Now the cstatei parameter can be used of the nvkm_cstate_prog function to select a specific cstate. v5: Make a constant for the magic value. Use list_last_entry. Add nvkm_cstate_get here instead of in the next commit. Signed-off-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h | 4 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h index 0cf3d86e399a..cc2a976446a9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h @@ -6,6 +6,10 @@ struct nvbios_pll; struct nvkm_pll_vals; +#define NVKM_CLK_CSTATE_DEFAULT -1 /* POSTed default */ +#define NVKM_CLK_CSTATE_BASE -2 /* pstate base */ +#define NVKM_CLK_CSTATE_HIGHEST -3 /* highest possible */ + enum nv_clk_src { nv_clk_src_crystal, nv_clk_src_href, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 98168be93515..688c908908d8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -74,6 +74,21 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust, /****************************************************************************** * C-States *****************************************************************************/ +static struct nvkm_cstate * +nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) +{ + struct nvkm_cstate *cstate; + if (cstatei == NVKM_CLK_CSTATE_HIGHEST) + return list_last_entry(&pstate->list, typeof(*cstate), head); + else { + list_for_each_entry(cstate, &pstate->list, head) { + if (cstate->id == cstatei) + return cstate; + } + } + return NULL; +} + static int nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) { @@ -85,7 +100,7 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) int ret; if (!list_empty(&pstate->list)) { - cstate = list_entry(pstate->list.prev, typeof(*cstate), head); + cstate = nvkm_cstate_get(clk, pstate, cstatei); } else { cstate = &pstate->base; } @@ -208,7 +223,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei) ram->func->tidy(ram); } - return nvkm_cstate_prog(clk, pstate, 0); + return nvkm_cstate_prog(clk, pstate, NVKM_CLK_CSTATE_HIGHEST); } static void -- cgit v1.2.3 From 1f7f3d91ad38afc706f838fb5a642b21d28e4485 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sat, 16 Jul 2016 15:26:25 +0200 Subject: drm/nouveau/clk: Respect voltage limits in nvkm_cstate_prog We should never allow to select a cstate which current voltage (depending on the temperature) is higher than 1. the max volt entries in the voltage map table. 2. what tha gpu actually can volt to. v3: Use find_best for all cstates before actually trying. Add nvkm_cstate_get function to get cstate by index. v5: Cstates with voltages lower then min_uv are valid. Move nvkm_cstate_get into the previous commit. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 52 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 2 +- 3 files changed, 54 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index 6fd933df763e..441f6e7079d2 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h @@ -27,6 +27,7 @@ struct nvkm_volt { u8 max2_id; }; +int nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temperature); int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id); int nvkm_volt_get(struct nvkm_volt *); int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, u8 temp, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 688c908908d8..60392b2edcbb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -74,6 +74,57 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust, /****************************************************************************** * C-States *****************************************************************************/ +static bool +nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate, + u32 max_volt, int temp) +{ + struct nvkm_volt *volt = clk->subdev.device->volt; + int voltage; + + if (!volt) + return true; + + voltage = nvkm_volt_map(volt, cstate->voltage, temp); + if (voltage < 0) + return false; + return voltage <= min(max_volt, volt->max_uv); +} + +static struct nvkm_cstate * +nvkm_cstate_find_best(struct nvkm_clk *clk, struct nvkm_pstate *pstate, + struct nvkm_cstate *start) +{ + struct nvkm_device *device = clk->subdev.device; + struct nvkm_volt *volt = device->volt; + struct nvkm_cstate *cstate; + int max_volt; + + if (!pstate || !start) + return NULL; + + if (!volt) + return start; + + max_volt = volt->max_uv; + if (volt->max0_id != 0xff) + max_volt = min(max_volt, + nvkm_volt_map(volt, volt->max0_id, clk->temp)); + if (volt->max1_id != 0xff) + max_volt = min(max_volt, + nvkm_volt_map(volt, volt->max1_id, clk->temp)); + if (volt->max2_id != 0xff) + max_volt = min(max_volt, + nvkm_volt_map(volt, volt->max2_id, clk->temp)); + + for (cstate = start; &cstate->head != &pstate->list; + cstate = list_entry(cstate->head.prev, typeof(*cstate), head)) { + if (nvkm_cstate_valid(clk, cstate, max_volt, clk->temp)) + break; + } + + return cstate; +} + static struct nvkm_cstate * nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) { @@ -101,6 +152,7 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) if (!list_empty(&pstate->list)) { cstate = nvkm_cstate_get(clk, pstate, cstatei); + cstate = nvkm_cstate_find_best(clk, pstate, cstate); } else { cstate = &pstate->base; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 40ba088a5c81..5e07bd3aaccc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -88,7 +88,7 @@ nvkm_volt_map_min(struct nvkm_volt *volt, u8 id) return id ? id * 10000 : -ENODEV; } -static int +int nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp) { struct nvkm_bios *bios = volt->subdev.device->bios; -- cgit v1.2.3 From f26493d22fbc42ee6645a1628b50d334048c99f3 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/bios: Add parsing of VPSTATE table This table contains three important clocks: base clock: This is the non boosted max clock. tdp clock: The clock at wich the vbios guarentees the TDP won't ever be exceeded at max load (seems to be always the same as the base clock, but behaves differently). boost clock: The avg clock the gpu will stay boosted to. It doesn't seem to affect the behaviour of the nvidia driver at all though. v2: Make clear that base/boost/tdp fields are ids. v5: Rename Base clock to vpstate. Make vbios pointers 32bit. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- .../drm/nouveau/include/nvkm/subdev/bios/vpstate.h | 24 +++++++ drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c | 82 ++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h new file mode 100644 index 000000000000..87f804fc3a88 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h @@ -0,0 +1,24 @@ +#ifndef __NVBIOS_VPSTATE_H__ +#define __NVBIOS_VPSTATE_H__ +struct nvbios_vpstate_header { + u32 offset; + + u8 version; + u8 hlen; + u8 ecount; + u8 elen; + u8 scount; + u8 slen; + + u8 base_id; + u8 boost_id; + u8 tdp_id; +}; +struct nvbios_vpstate_entry { + u8 pstate; + u16 clock_mhz; +}; +int nvbios_vpstate_parse(struct nvkm_bios *, struct nvbios_vpstate_header *); +int nvbios_vpstate_entry(struct nvkm_bios *, struct nvbios_vpstate_header *, + u8 idx, struct nvbios_vpstate_entry *); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild index dbcb0ef21587..be57220a2e01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild @@ -31,6 +31,7 @@ nvkm-y += nvkm/subdev/bios/timing.o nvkm-y += nvkm/subdev/bios/therm.o nvkm-y += nvkm/subdev/bios/vmap.o nvkm-y += nvkm/subdev/bios/volt.o +nvkm-y += nvkm/subdev/bios/vpstate.o nvkm-y += nvkm/subdev/bios/xpio.o nvkm-y += nvkm/subdev/bios/M0203.o nvkm-y += nvkm/subdev/bios/M0205.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c new file mode 100644 index 000000000000..f199270163d2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c @@ -0,0 +1,82 @@ +/* + * Copyright 2016 Karol Herbst + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Karol Herbst + */ +#include +#include +#include + +static u32 +nvbios_vpstate_offset(struct nvkm_bios *b) +{ + struct bit_entry bit_P; + + if (!bit_entry(b, 'P', &bit_P)) { + if (bit_P.version == 2) + return nvbios_rd32(b, bit_P.offset + 0x38); + } + + return 0x0000; +} + +int +nvbios_vpstate_parse(struct nvkm_bios *b, struct nvbios_vpstate_header *h) +{ + if (!h) + return -EINVAL; + + h->offset = nvbios_vpstate_offset(b); + if (!h->offset) + return -ENODEV; + + h->version = nvbios_rd08(b, h->offset); + switch (h->version) { + case 0x10: + h->hlen = nvbios_rd08(b, h->offset + 0x1); + h->elen = nvbios_rd08(b, h->offset + 0x2); + h->slen = nvbios_rd08(b, h->offset + 0x3); + h->scount = nvbios_rd08(b, h->offset + 0x4); + h->ecount = nvbios_rd08(b, h->offset + 0x5); + + h->base_id = nvbios_rd08(b, h->offset + 0x0f); + h->boost_id = nvbios_rd08(b, h->offset + 0x10); + h->tdp_id = nvbios_rd08(b, h->offset + 0x11); + return 0; + default: + return -EINVAL; + } +} + +int +nvbios_vpstate_entry(struct nvkm_bios *b, struct nvbios_vpstate_header *h, + u8 idx, struct nvbios_vpstate_entry *e) +{ + u32 offset; + + if (!e || !h || idx > h->ecount) + return -EINVAL; + + offset = h->offset + h->hlen + idx * (h->elen + (h->slen * h->scount)); + e->pstate = nvbios_rd08(b, offset); + e->clock_mhz = nvbios_rd16(b, offset + 0x5); + return 0; +} -- cgit v1.2.3 From 4b9ce6e7b68683ac3874f9ebb243eb6f29c46812 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/clk: Allow boosting only when NvBoost is set 0: base clock from the vbios is max clock (default) 1: boost only to boost clock from the vbios 2: boost to max clock available v2: Moved into nvkm_cstate_valid. v4: Check the existence of the clocks before limiting. v5: Default to boost level 0. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h | 9 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 33 ++++++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c | 2 +- 4 files changed, 42 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h index cc2a976446a9..e5275f742977 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h @@ -72,7 +72,8 @@ struct nvkm_pstate { struct nvkm_domain { enum nv_clk_src name; u8 bios; /* 0xff for none */ -#define NVKM_CLK_DOM_FLAG_CORE 0x01 +#define NVKM_CLK_DOM_FLAG_CORE 0x01 +#define NVKM_CLK_DOM_FLAG_VPSTATE 0x02 u8 flags; const char *mname; int mdiv; @@ -102,6 +103,12 @@ struct nvkm_clk { u8 temp; bool allow_reclock; +#define NVKM_CLK_BOOST_NONE 0x0 +#define NVKM_CLK_BOOST_BIOS 0x1 +#define NVKM_CLK_BOOST_FULL 0x2 + u8 boost_mode; + u32 base_khz; + u32 boost_khz; /*XXX: die, these are here *only* to support the completely * bat-shit insane what-was-nouveau_hw.c code diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 60392b2edcbb..fa1c12185e19 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -78,9 +79,25 @@ static bool nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate, u32 max_volt, int temp) { + const struct nvkm_domain *domain = clk->domains; struct nvkm_volt *volt = clk->subdev.device->volt; int voltage; + while (domain && domain->name != nv_clk_src_max) { + if (domain->flags & NVKM_CLK_DOM_FLAG_VPSTATE) { + u32 freq = cstate->domain[domain->name]; + switch (clk->boost_mode) { + case NVKM_CLK_BOOST_NONE: + if (clk->base_khz && freq > clk->base_khz) + return false; + case NVKM_CLK_BOOST_BIOS: + if (clk->boost_khz && freq > clk->boost_khz) + return false; + } + } + domain++; + } + if (!volt) return true; @@ -635,10 +652,22 @@ int nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device, int index, bool allow_reclock, struct nvkm_clk *clk) { + struct nvkm_subdev *subdev = &clk->subdev; + struct nvkm_bios *bios = device->bios; int ret, idx, arglen; const char *mode; + struct nvbios_vpstate_header h; + + nvkm_subdev_ctor(&nvkm_clk, device, index, subdev); + + if (bios && !nvbios_vpstate_parse(bios, &h)) { + struct nvbios_vpstate_entry base, boost; + if (!nvbios_vpstate_entry(bios, &h, h.boost_id, &boost)) + clk->boost_khz = boost.clock_mhz * 1000; + if (!nvbios_vpstate_entry(bios, &h, h.base_id, &base)) + clk->base_khz = base.clock_mhz * 1000; + } - nvkm_subdev_ctor(&nvkm_clk, device, index, &clk->subdev); clk->func = func; INIT_LIST_HEAD(&clk->states); clk->domains = func->domains; @@ -681,6 +710,8 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device, if (mode) clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen); + clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost", + NVKM_CLK_BOOST_NONE); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c index 89d5543118cf..7f67f9f5a550 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c @@ -457,7 +457,7 @@ gf100_clk = { { nv_clk_src_hubk06 , 0x00 }, { nv_clk_src_hubk01 , 0x01 }, { nv_clk_src_copy , 0x02 }, - { nv_clk_src_gpc , 0x03, 0, "core", 2000 }, + { nv_clk_src_gpc , 0x03, NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 }, { nv_clk_src_rop , 0x04 }, { nv_clk_src_mem , 0x05, 0, "memory", 1000 }, { nv_clk_src_vdec , 0x06 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c index 06bc0d2d6ae1..0b37e3da7feb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c @@ -491,7 +491,7 @@ gk104_clk = { .domains = { { nv_clk_src_crystal, 0xff }, { nv_clk_src_href , 0xff }, - { nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 }, + { nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE | NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 }, { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE }, { nv_clk_src_rop , 0x02, NVKM_CLK_DOM_FLAG_CORE }, { nv_clk_src_mem , 0x03, 0, "memory", 500 }, -- cgit v1.2.3 From 5e00e3263ba68bd32337063a43aa8467b27acd1d Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/volt: Don't require perfect fit If we calculate the voltage in the table right, we get all kinds of values, which never fit the hardware steps, so we use the closest higher value the hardware can do. v3: Simplify the implementation. v5: Initialize best_err with volt->max_uv. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 5e07bd3aaccc..ec59d58becdc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -51,18 +51,30 @@ static int nvkm_volt_set(struct nvkm_volt *volt, u32 uv) { struct nvkm_subdev *subdev = &volt->subdev; - int i, ret = -EINVAL; + int i, ret = -EINVAL, best_err = volt->max_uv, best = -1; if (volt->func->volt_set) return volt->func->volt_set(volt, uv); for (i = 0; i < volt->vid_nr; i++) { - if (volt->vid[i].uv == uv) { - ret = volt->func->vid_set(volt, volt->vid[i].vid); - nvkm_debug(subdev, "set %duv: %d\n", uv, ret); + int err = volt->vid[i].uv - uv; + if (err < 0 || err > best_err) + continue; + + best_err = err; + best = i; + if (best_err == 0) break; - } } + + if (best == -1) { + nvkm_error(subdev, "couldn't set %iuv\n", uv); + return ret; + } + + ret = volt->func->vid_set(volt, volt->vid[best].vid); + nvkm_debug(subdev, "set req %duv to %duv: %d\n", uv, + volt->vid[best].uv, ret); return ret; } -- cgit v1.2.3 From 5c3b16ee1db65d2fc86b58e36f51b22862923d8c Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:08 +0200 Subject: drm/nouveau/bios/vmap: unk0 field is the mode Depending on the value a different formular is used to calculated the voltage for this entry. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h index ae2f27be3f29..8fa1294c27b7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h @@ -11,7 +11,7 @@ u16 nvbios_vmap_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_vmap *); struct nvbios_vmap_entry { - u8 unk0; + u8 mode; u8 link; u32 min; u32 max; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c index f2295e180e5e..32bd8b1d154f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c @@ -105,7 +105,7 @@ nvbios_vmap_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len, info->arg[2] = nvbios_rd32(bios, vmap + 0x10); break; case 0x20: - info->unk0 = nvbios_rd08(bios, vmap + 0x00); + info->mode = nvbios_rd08(bios, vmap + 0x00); info->link = nvbios_rd08(bios, vmap + 0x01); info->min = nvbios_rd32(bios, vmap + 0x02); info->max = nvbios_rd32(bios, vmap + 0x06); -- cgit v1.2.3 From a3c950f2ac2c56f2c40bfacd779a72e4f3dc7cd2 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sun, 17 Jul 2016 20:02:33 +0200 Subject: drm/nouveau/volt: Add implementation for gf100 Since gf100 we need a speedo value for calculating the voltage. The readout will be added in a later patch. Signed-off-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 17 +++++---- drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c | 44 ++++++++++++++++++++++ 4 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index 441f6e7079d2..bc8e9c9dcf16 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h @@ -34,6 +34,7 @@ int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, u8 temp, int condition); int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **); +int gf100_volt_new(struct nvkm_device *, int, struct nvkm_volt **); int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **); int gk20a_volt_new(struct nvkm_device *, int, struct nvkm_volt **); int gm20b_volt_new(struct nvkm_device *, int, struct nvkm_volt **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 7218a067a6c5..53d171729353 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -1357,7 +1357,7 @@ nvc0_chipset = { .pmu = gf100_pmu_new, .therm = gt215_therm_new, .timer = nv41_timer_new, - .volt = nv40_volt_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .ce[1] = gf100_ce_new, .disp = gt215_disp_new, @@ -1394,7 +1394,7 @@ nvc1_chipset = { .pmu = gf100_pmu_new, .therm = gt215_therm_new, .timer = nv41_timer_new, - .volt = nv40_volt_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .disp = gt215_disp_new, .dma = gf100_dma_new, @@ -1430,7 +1430,7 @@ nvc3_chipset = { .pmu = gf100_pmu_new, .therm = gt215_therm_new, .timer = nv41_timer_new, - .volt = nv40_volt_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .disp = gt215_disp_new, .dma = gf100_dma_new, @@ -1466,7 +1466,7 @@ nvc4_chipset = { .pmu = gf100_pmu_new, .therm = gt215_therm_new, .timer = nv41_timer_new, - .volt = nv40_volt_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .ce[1] = gf100_ce_new, .disp = gt215_disp_new, @@ -1503,7 +1503,7 @@ nvc8_chipset = { .pmu = gf100_pmu_new, .therm = gt215_therm_new, .timer = nv41_timer_new, - .volt = nv40_volt_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .ce[1] = gf100_ce_new, .disp = gt215_disp_new, @@ -1540,7 +1540,7 @@ nvce_chipset = { .pmu = gf100_pmu_new, .therm = gt215_therm_new, .timer = nv41_timer_new, - .volt = nv40_volt_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .ce[1] = gf100_ce_new, .disp = gt215_disp_new, @@ -1577,7 +1577,7 @@ nvcf_chipset = { .pmu = gf100_pmu_new, .therm = gt215_therm_new, .timer = nv41_timer_new, - .volt = nv40_volt_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .disp = gt215_disp_new, .dma = gf100_dma_new, @@ -1612,6 +1612,7 @@ nvd7_chipset = { .pci = gf106_pci_new, .therm = gf119_therm_new, .timer = nv41_timer_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .disp = gf119_disp_new, .dma = gf119_dma_new, @@ -1647,7 +1648,7 @@ nvd9_chipset = { .pmu = gf119_pmu_new, .therm = gf119_therm_new, .timer = nv41_timer_new, - .volt = nv40_volt_new, + .volt = gf100_volt_new, .ce[0] = gf100_ce_new, .disp = gf119_disp_new, .dma = gf119_dma_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild index c34076223b7b..bcd179ba11d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild @@ -1,6 +1,7 @@ nvkm-y += nvkm/subdev/volt/base.o nvkm-y += nvkm/subdev/volt/gpio.o nvkm-y += nvkm/subdev/volt/nv40.o +nvkm-y += nvkm/subdev/volt/gf100.o nvkm-y += nvkm/subdev/volt/gk104.o nvkm-y += nvkm/subdev/volt/gk20a.o nvkm-y += nvkm/subdev/volt/gm20b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c new file mode 100644 index 000000000000..c21100fda47e --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c @@ -0,0 +1,44 @@ +/* + * Copyright 2016 Karol Herbst + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Karol Herbst + */ +#include "priv.h" + +static const struct nvkm_volt_func +gf100_volt = { + .vid_get = nvkm_voltgpio_get, + .vid_set = nvkm_voltgpio_set, +}; + +int +gf100_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt) +{ + struct nvkm_volt *volt; + int ret; + + ret = nvkm_volt_new_(&gf100_volt, device, index, &volt); + *pvolt = volt; + if (ret) + return ret; + + return nvkm_voltgpio_init(volt); +} -- cgit v1.2.3 From 08de5743db9250dc915d85f9f7d1a9016a8f8975 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sun, 17 Jul 2016 20:05:45 +0200 Subject: drm/nouveau/volt/gf100-: Add speedo v5: Squashed speedo related commits. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 24 ++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c | 26 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c | 21 +++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h | 4 ++++ 5 files changed, 77 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index bc8e9c9dcf16..08ef9983c643 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h @@ -25,6 +25,8 @@ struct nvkm_volt { u8 max0_id; u8 max1_id; u8 max2_id; + + int speedo; }; int nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temperature); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index ec59d58becdc..771419ff8338 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -195,6 +195,14 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt) } } +static int +nvkm_volt_speedo_read(struct nvkm_volt *volt) +{ + if (volt->func->speedo_read) + return volt->func->speedo_read(volt); + return -EINVAL; +} + static int nvkm_volt_init(struct nvkm_subdev *subdev) { @@ -209,6 +217,21 @@ nvkm_volt_init(struct nvkm_subdev *subdev) return 0; } +static int +nvkm_volt_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_volt *volt = nvkm_volt(subdev); + + volt->speedo = nvkm_volt_speedo_read(volt); + if (volt->speedo > 0) + nvkm_debug(&volt->subdev, "speedo %x\n", volt->speedo); + + if (volt->func->oneinit) + return volt->func->oneinit(volt); + + return 0; +} + static void * nvkm_volt_dtor(struct nvkm_subdev *subdev) { @@ -219,6 +242,7 @@ static const struct nvkm_subdev_func nvkm_volt = { .dtor = nvkm_volt_dtor, .init = nvkm_volt_init, + .oneinit = nvkm_volt_oneinit, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c index c21100fda47e..d9ed6925ca64 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c @@ -23,10 +23,36 @@ */ #include "priv.h" +#include + +static int +gf100_volt_speedo_read(struct nvkm_volt *volt) +{ + struct nvkm_device *device = volt->subdev.device; + struct nvkm_fuse *fuse = device->fuse; + + if (!fuse) + return -EINVAL; + + return nvkm_fuse_read(fuse, 0x1cc); +} + +int +gf100_volt_oneinit(struct nvkm_volt *volt) +{ + struct nvkm_subdev *subdev = &volt->subdev; + if (volt->speedo <= 0) + nvkm_error(subdev, "couldn't find speedo value, volting not " + "possible\n"); + return 0; +} + static const struct nvkm_volt_func gf100_volt = { + .oneinit = gf100_volt_oneinit, .vid_get = nvkm_voltgpio_get, .vid_set = nvkm_voltgpio_set, + .speedo_read = gf100_volt_speedo_read, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c index 420bd84d8483..b2c5d1166a13 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c @@ -27,6 +27,7 @@ #include #include #include +#include #define gk104_volt(p) container_of((p), struct gk104_volt, base) struct gk104_volt { @@ -64,13 +65,33 @@ gk104_volt_set(struct nvkm_volt *base, u32 uv) return 0; } +static int +gk104_volt_speedo_read(struct nvkm_volt *volt) +{ + struct nvkm_device *device = volt->subdev.device; + struct nvkm_fuse *fuse = device->fuse; + int ret; + + if (!fuse) + return -EINVAL; + + nvkm_wr32(device, 0x122634, 0x0); + ret = nvkm_fuse_read(fuse, 0x3a8); + nvkm_wr32(device, 0x122634, 0x41); + return ret; +} + static const struct nvkm_volt_func gk104_volt_pwm = { + .oneinit = gf100_volt_oneinit, .volt_get = gk104_volt_get, .volt_set = gk104_volt_set, + .speedo_read = gk104_volt_speedo_read, }, gk104_volt_gpio = { + .oneinit = gf100_volt_oneinit, .vid_get = nvkm_voltgpio_get, .vid_set = nvkm_voltgpio_set, + .speedo_read = gk104_volt_speedo_read, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h index d5140d991161..354bafe4b4e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h @@ -9,11 +9,13 @@ int nvkm_volt_new_(const struct nvkm_volt_func *, struct nvkm_device *, int index, struct nvkm_volt **); struct nvkm_volt_func { + int (*oneinit)(struct nvkm_volt *); int (*volt_get)(struct nvkm_volt *); int (*volt_set)(struct nvkm_volt *, u32 uv); int (*vid_get)(struct nvkm_volt *); int (*vid_set)(struct nvkm_volt *, u8 vid); int (*set_id)(struct nvkm_volt *, u8 id, int condition); + int (*speedo_read)(struct nvkm_volt *); }; int nvkm_voltgpio_init(struct nvkm_volt *); @@ -23,4 +25,6 @@ int nvkm_voltgpio_set(struct nvkm_volt *, u8); int nvkm_voltpwm_init(struct nvkm_volt *volt); int nvkm_voltpwm_get(struct nvkm_volt *volt); int nvkm_voltpwm_set(struct nvkm_volt *volt, u32 uv); + +int gf100_volt_oneinit(struct nvkm_volt *); #endif -- cgit v1.2.3 From 114653c7593a4dd52cc1721b0d325d43b00e2371 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 12 Jul 2016 21:36:09 +0200 Subject: drm/nouveau/volt: Make use of cvb coefficients I'm quite sure that those coefficients are real close, because while testing the biggest error compared to nvidia was around -1.5% (biggest error with right coefficients is 12.5mV / 600mV = 2%). These coefficients were REed by modifing the voltage map entries and by calculating the set voltage back until I was able to forecast which voltage nvidia sets for a given voltage map entry. With these formulars I am able to precisely predict at which exact temperature Nvidia down- or upvolts due to a changed therm reading. That's why I am quite sure these are right, or at least really really close. v4: Use better coefficients and speedo. v5: Add error message when speedo is missing. Signed-off-by: Karol Herbst Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 38 +++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 771419ff8338..90d234231eed 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -110,13 +110,47 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp) vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info); if (vmap) { + s64 result; + + if (volt->speedo < 0) + return volt->speedo; + + if (ver == 0x10 || (ver == 0x20 && info.mode == 0)) { + result = (s64)info.arg[0] / 10; + result += ((s64)info.arg[1] * volt->speedo) / 10; + result += ((s64)info.arg[2] * volt->speedo * volt->speedo) / 100000; + } else if (ver == 0x20) { + switch (info.mode) { + /* 0x0 handled above! */ + case 0x1: + result = ((s64)info.arg[0] * 15625) >> 18; + result += ((s64)info.arg[1] * volt->speedo * 15625) >> 18; + result += ((s64)info.arg[2] * temp * 15625) >> 10; + result += ((s64)info.arg[3] * volt->speedo * temp * 15625) >> 18; + result += ((s64)info.arg[4] * volt->speedo * volt->speedo * 15625) >> 30; + result += ((s64)info.arg[5] * temp * temp * 15625) >> 18; + break; + case 0x3: + result = (info.min + info.max) / 2; + break; + case 0x2: + default: + result = info.min; + break; + } + } else { + return -ENODEV; + } + + result = min(max(result, (s64)info.min), (s64)info.max); + if (info.link != 0xff) { int ret = nvkm_volt_map(volt, info.link, temp); if (ret < 0) return ret; - info.min += ret; + result += ret; } - return info.min; + return result; } return id ? id * 10000 : -ENODEV; -- cgit v1.2.3 From ebaf3e70aabea8e3d86d977ab96261d7452b7a0d Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sun, 17 Jul 2016 21:36:49 +0200 Subject: drm/nouveau/fb/ram: Use Kepler implementation on Maxwell This enables memory reclocking on Maxwell. Sadly without a PMU firmware it is useless for gm20x gpus. Signed-off-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c | 8 +++++++- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c | 12 +----------- 3 files changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h index b9ec0ae6723a..b60068b7d8f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h @@ -24,6 +24,7 @@ int gf100_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **); +int gk104_ram_ctor(struct nvkm_fb *, struct nvkm_ram **, u32); int gk104_ram_init(struct nvkm_ram *ram); /* RAM type-specific MR calculation routines */ diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c index 93b30d92776c..7904fa41acef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c @@ -1537,6 +1537,12 @@ gk104_ram_func = { int gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +{ + return gk104_ram_ctor(fb, pram, 0x022554); +} + +int +gk104_ram_ctor(struct nvkm_fb *fb, struct nvkm_ram **pram, u32 maskaddr) { struct nvkm_subdev *subdev = &fb->subdev; struct nvkm_device *device = subdev->device; @@ -1552,7 +1558,7 @@ gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) return -ENOMEM; *pram = &ram->base; - ret = gf100_ram_ctor(&gk104_ram_func, fb, 0x022554, &ram->base); + ret = gf100_ram_ctor(&gk104_ram_func, fb, maskaddr, &ram->base); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c index 43d807f6ca71..ac862d1d77bd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c @@ -23,18 +23,8 @@ */ #include "ram.h" -static const struct nvkm_ram_func -gm107_ram_func = { - .init = gk104_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, -}; - int gm107_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL))) - return -ENOMEM; - - return gf100_ram_ctor(&gm107_ram_func, fb, 0x021c14, *pram); + return gk104_ram_ctor(fb, pram, 0x021c14); } -- cgit v1.2.3 From 8d021d71b3247937a26ffdf313fd53a9d58778b7 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Thu, 25 Aug 2016 03:57:07 +0300 Subject: drm/nouveau/drm/nouveau: add a LED driver for the NVIDIA logo We received a donation of a Titan which has this useless feature allowing users to control the brightness of the LED behind the logo of NVIDIA. In the true spirit of open source, let's expose that to the users of very expensive cards! This patch hooks up this LED/PWM to the LED subsystem which allows blinking it in sync with cpu/disk/network/whatever activity (heartbeat is quite nice!). Users may also implement some breathing effect or morse code support in the userspace if they feel like it. v2: - surround the use of the LED framework with ifdef CONFIG_LEDS_CLASS v3: - avoid using ifdefs everywhere, follow the recommendations of /doc/Documentation/CodingStyle. Suggested by Emil Velikov. v4 (Ben): - squashed series of fixes from ml Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Kbuild | 1 + .../drm/nouveau/include/nvkm/subdev/bios/gpio.h | 1 + drivers/gpu/drm/nouveau/nouveau_drm.c | 7 ++ drivers/gpu/drm/nouveau/nouveau_drv.h | 3 + drivers/gpu/drm/nouveau/nouveau_led.c | 139 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_led.h | 57 +++++++++ 6 files changed, 208 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/nouveau_led.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_led.h (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index 2527bf4ca5d9..fde6e3656636 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild @@ -22,6 +22,7 @@ nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o nouveau-y += nouveau_drm.o nouveau-y += nouveau_hwmon.o nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o +nouveau-$(CONFIG_LEDS_CLASS) += nouveau_led.o nouveau-y += nouveau_nvif.o nouveau-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o nouveau-y += nouveau_usif.o # userspace <-> nvif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h index a47d46dda704..b7a54e605469 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h @@ -6,6 +6,7 @@ enum dcb_gpio_func_name { DCB_GPIO_TVDAC1 = 0x2d, DCB_GPIO_FAN = 0x09, DCB_GPIO_FAN_SENSE = 0x3d, + DCB_GPIO_LOGO_LED_PWM = 0x84, DCB_GPIO_UNUSED = 0xff, DCB_GPIO_VID0 = 0x04, DCB_GPIO_VID1 = 0x05, diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 3100fd88a015..6adf94789417 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -47,6 +47,7 @@ #include "nouveau_ttm.h" #include "nouveau_gem.h" #include "nouveau_vga.h" +#include "nouveau_led.h" #include "nouveau_hwmon.h" #include "nouveau_acpi.h" #include "nouveau_bios.h" @@ -475,6 +476,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) nouveau_hwmon_init(dev); nouveau_accel_init(drm); nouveau_fbcon_init(dev); + nouveau_led_init(dev); if (nouveau_runtime_pm != 0) { pm_runtime_use_autosuspend(dev->dev); @@ -510,6 +512,7 @@ nouveau_drm_unload(struct drm_device *dev) pm_runtime_forbid(dev->dev); } + nouveau_led_fini(dev); nouveau_fbcon_fini(dev); nouveau_accel_fini(drm); nouveau_hwmon_fini(dev); @@ -561,6 +564,8 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) struct nouveau_cli *cli; int ret; + nouveau_led_suspend(dev); + if (dev->mode_config.num_crtc) { NV_INFO(drm, "suspending console...\n"); nouveau_fbcon_set_suspend(dev, 1); @@ -649,6 +654,8 @@ nouveau_do_resume(struct drm_device *dev, bool runtime) nouveau_fbcon_set_suspend(dev, 0); } + nouveau_led_resume(dev); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 822a0212cd48..c0e2b3207503 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -166,6 +166,9 @@ struct nouveau_drm { struct nouveau_hwmon *hwmon; struct nouveau_debugfs *debugfs; + /* led management */ + struct nouveau_led *led; + /* display power reference */ bool have_disp_power_ref; diff --git a/drivers/gpu/drm/nouveau/nouveau_led.c b/drivers/gpu/drm/nouveau/nouveau_led.c new file mode 100644 index 000000000000..3e2f1b6cd4df --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_led.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 Martin Peres + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* + * Authors: + * Martin Peres + */ + +#include + +#include "nouveau_led.h" +#include + +static enum led_brightness +nouveau_led_get_brightness(struct led_classdev *led) +{ + struct drm_device *drm_dev = container_of(led, struct nouveau_led, led)->dev; + struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct nvif_object *device = &drm->device.object; + u32 div, duty; + + div = nvif_rd32(device, 0x61c880) & 0x00ffffff; + duty = nvif_rd32(device, 0x61c884) & 0x00ffffff; + + if (div > 0) + return duty * LED_FULL / div; + else + return 0; +} + +static void +nouveau_led_set_brightness(struct led_classdev *led, enum led_brightness value) +{ + struct drm_device *drm_dev = container_of(led, struct nouveau_led, led)->dev; + struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct nvif_object *device = &drm->device.object; + + u32 input_clk = 27e6; /* PDISPLAY.SOR[1].PWM is connected to the crystal */ + u32 freq = 100; /* this is what nvidia uses and it should be good-enough */ + u32 div, duty; + + div = input_clk / freq; + duty = value * div / LED_FULL; + + /* for now, this is safe to directly poke those registers because: + * - A: nvidia never puts the logo led to any other PWM controler + * than PDISPLAY.SOR[1].PWM. + * - B: nouveau does not touch these registers anywhere else + */ + nvif_wr32(device, 0x61c880, div); + nvif_wr32(device, 0x61c884, 0xc0000000 | duty); +} + + +int +nouveau_led_init(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvkm_gpio *gpio = nvxx_gpio(&drm->device); + struct dcb_gpio_func logo_led; + int ret; + + if (!gpio) + return 0; + + /* check that there is a GPIO controlling the logo LED */ + if (nvkm_gpio_find(gpio, 0, DCB_GPIO_LOGO_LED_PWM, 0xff, &logo_led)) + return 0; + + drm->led = kzalloc(sizeof(*drm->led), GFP_KERNEL); + if (!drm->led) + return -ENOMEM; + drm->led->dev = dev; + + drm->led->led.name = "nvidia-logo"; + drm->led->led.max_brightness = 255; + drm->led->led.brightness_get = nouveau_led_get_brightness; + drm->led->led.brightness_set = nouveau_led_set_brightness; + + ret = led_classdev_register(dev->dev, &drm->led->led); + if (ret) { + kfree(drm->led); + return ret; + } + + return 0; +} + +void +nouveau_led_suspend(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + + if (drm->led) + led_classdev_suspend(&drm->led->led); +} + +void +nouveau_led_resume(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + + if (drm->led) + led_classdev_resume(&drm->led->led); +} + +void +nouveau_led_fini(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + + if (drm->led) { + led_classdev_unregister(&drm->led->led); + kfree(drm->led); + drm->led = NULL; + } +} diff --git a/drivers/gpu/drm/nouveau/nouveau_led.h b/drivers/gpu/drm/nouveau/nouveau_led.h new file mode 100644 index 000000000000..187ecdb82002 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_led.h @@ -0,0 +1,57 @@ +/* + * Copyright 2015 Martin Peres + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Martin Peres + */ + +#ifndef __NOUVEAU_LED_H__ +#define __NOUVEAU_LED_H__ + +#include "nouveau_drv.h" + +struct led_classdev; + +struct nouveau_led { + struct drm_device *dev; + + struct led_classdev led; +}; + +static inline struct nouveau_led * +nouveau_led(struct drm_device *dev) +{ + return nouveau_drm(dev)->led; +} + +/* nouveau_led.c */ +#if IS_ENABLED(CONFIG_LEDS_CLASS) +int nouveau_led_init(struct drm_device *dev); +void nouveau_led_suspend(struct drm_device *dev); +void nouveau_led_resume(struct drm_device *dev); +void nouveau_led_fini(struct drm_device *dev); +#else +static inline int nouveau_led_init(struct drm_device *dev) { return 0; }; +static inline void nouveau_led_suspend(struct drm_device *dev) { }; +static inline void nouveau_led_resume(struct drm_device *dev) { }; +static inline void nouveau_led_fini(struct drm_device *dev) { }; +#endif + +#endif -- cgit v1.2.3 From 1cc88ab9542441b3371104872eefc4924408aaa3 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 27 Aug 2016 21:32:34 -0400 Subject: drm/nouveau/gr/nv3x: add 0x0597 kelvin 3d class support Tested on a NV34. There are reports of this also working on the other nv3x chips. Largely useful for testing software written for NV2x without having the actual hardware available. Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c index f1e15a4d4f64..b4e3c50badc7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c @@ -187,6 +187,7 @@ nv30_gr = { { -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */ { -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */ { -1, -1, 0x0397, &nv04_gr_object }, /* rankine */ + { -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */ {} } }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c index 300f5ed5de0b..e7ed04b935cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c @@ -123,6 +123,7 @@ nv34_gr = { { -1, -1, 0x0389, &nv04_gr_object }, /* sifm (nv30) */ { -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */ { -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */ + { -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */ { -1, -1, 0x0697, &nv04_gr_object }, /* rankine */ {} } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c index 740df0f52c38..5e8abacbacc6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c @@ -124,6 +124,7 @@ nv35_gr = { { -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */ { -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */ { -1, -1, 0x0497, &nv04_gr_object }, /* rankine */ + { -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */ {} } }; -- cgit v1.2.3 From d6c6035af7ccadd647832681d6b2a53d4c8705de Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sun, 18 Sep 2016 20:58:53 +0800 Subject: drm/nouveau/core: add missing header dependencies We get 2 warnings when building kernel with W=1: drivers/gpu/drm/nouveau/nvkm/core/firmware.c:34:1: warning: no previous prototype for 'nvkm_firmware_get' [-Wmissing-prototypes] drivers/gpu/drm/nouveau/nvkm/core/firmware.c:58:1: warning: no previous prototype for 'nvkm_firmware_put' [-Wmissing-prototypes] In fact, both functions are declared in drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h, so this patch adds missing header dependencies. Signed-off-by: Baoyou Xie Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c index 34ecd4a7e0c1..058ff46b5f16 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c @@ -20,6 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ #include +#include /** * nvkm_firmware_get - load firmware from the official nvidia/chip/ directory -- cgit v1.2.3 From 321c258e9192377cff2cb34b9d12fca0ee60b13f Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 16 Sep 2016 18:09:12 +0900 Subject: drm/nouveau/volt: use kernel's 64-bit signed division function Doing direct 64 bit divisions in kernel code leads to references to undefined symbols on 32 bit architectures. Replace such divisions with calls to div64_s64 to make the module usable on 32 bit archs. Signed-off-by: Alexandre Courbot Reviewed-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 90d234231eed..e8569b04b55d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -116,9 +116,9 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp) return volt->speedo; if (ver == 0x10 || (ver == 0x20 && info.mode == 0)) { - result = (s64)info.arg[0] / 10; - result += ((s64)info.arg[1] * volt->speedo) / 10; - result += ((s64)info.arg[2] * volt->speedo * volt->speedo) / 100000; + result = div64_s64((s64)info.arg[0], 10); + result += div64_s64((s64)info.arg[1] * volt->speedo, 10); + result += div64_s64((s64)info.arg[2] * volt->speedo * volt->speedo, 100000); } else if (ver == 0x20) { switch (info.mode) { /* 0x0 handled above! */ -- cgit v1.2.3 From 97163967acab56bff26d31914426a625e5acfa67 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Tue, 13 Sep 2016 20:17:32 +0800 Subject: drm/nouveau/disp: remove unused function in sorg94.c We get 1 warning when building kernel with W=1: drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c:49:1: warning: no previous prototype for 'g94_sor_output_new' [-Wmissing-prototypes] In fact, this function is called by no one and not exported, so this patch removes it. Signed-off-by: Baoyou Xie Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c index 1bb9d661e9b3..4510cb6e10a8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c @@ -45,14 +45,6 @@ static const struct nvkm_output_func g94_sor_output_func = { }; -int -g94_sor_output_new(struct nvkm_disp *disp, int index, - struct dcb_output *dcbE, struct nvkm_output **poutp) -{ - return nvkm_output_new_(&g94_sor_output_func, disp, - index, dcbE, poutp); -} - /******************************************************************************* * DisplayPort ******************************************************************************/ -- cgit v1.2.3 From f9c0715e39f09bd5ea6f6357a4ce7a969b673007 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 May 2016 16:28:30 +1000 Subject: drm/nouveau/bar/nv50: fix bar2 vm size The BAR2 page table was being made WAY too big - oops. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c index 370dcd8ff7b5..6eff637ac301 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c @@ -84,7 +84,7 @@ nv50_bar_oneinit(struct nvkm_bar *base) start = 0x0100000000ULL; limit = start + device->func->resource_size(device, 3); - ret = nvkm_vm_new(device, start, limit, start, &bar3_lock, &vm); + ret = nvkm_vm_new(device, start, limit - start, start, &bar3_lock, &vm); if (ret) return ret; @@ -117,7 +117,7 @@ nv50_bar_oneinit(struct nvkm_bar *base) start = 0x0000000000ULL; limit = start + device->func->resource_size(device, 1); - ret = nvkm_vm_new(device, start, limit--, start, &bar1_lock, &vm); + ret = nvkm_vm_new(device, start, limit-- - start, start, &bar1_lock, &vm); if (ret) return ret; -- cgit v1.2.3 From bbe1f94a8b3f2e8622dd400a6827d3242005d951 Mon Sep 17 00:00:00 2001 From: Faris Alsalama Date: Sat, 21 May 2016 14:41:43 -0400 Subject: drm/nouveau/kms: add Maxwell to backlight initialization Signed-off-by: Faris Alsalama Acked-by: Acked-by: Pierre Moreau Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_backlight.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index f5101be806cb..5e2c5685b4dd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -232,6 +232,7 @@ nouveau_backlight_init(struct drm_device *dev) case NV_DEVICE_INFO_V0_TESLA: case NV_DEVICE_INFO_V0_FERMI: case NV_DEVICE_INFO_V0_KEPLER: + case NV_DEVICE_INFO_V0_MAXWELL: return nv50_backlight_init(connector); default: break; -- cgit v1.2.3 From 38f5359354d487f2492a3cdec862682c8b15e216 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 6 Oct 2016 16:49:28 +0100 Subject: drm/nouveau/pci: set streaming DMA mask early Some subdevices (i.e., fb/nv50.c and fb/gf100.c) map a scratch page using dma_map_page() way before the TTM layer has had a chance to set the DMA mask. This may prevent the driver from loading at all on platforms whose system memory is not covered by the default DMA mask of 32-bit (i.e., when all RAM is above 4 GB). So set a preliminary DMA mask right after constructing the PCI device, and base it on the .dma_bits member of the MMU subdevice, which is what the TTM layer will base the DMA mask on as well. Signed-off-by: Ard Biesheuvel Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c | 37 +++++++++++++++++------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c index b1b693219db3..8f13bcd4040c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c @@ -1664,14 +1664,31 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, *pdevice = &pdev->device; pdev->pdev = pci_dev; - return nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev, - pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE : - pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ? - NVKM_DEVICE_AGP : NVKM_DEVICE_PCI, - (u64)pci_domain_nr(pci_dev->bus) << 32 | - pci_dev->bus->number << 16 | - PCI_SLOT(pci_dev->devfn) << 8 | - PCI_FUNC(pci_dev->devfn), name, - cfg, dbg, detect, mmio, subdev_mask, - &pdev->device); + ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev, + pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE : + pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ? + NVKM_DEVICE_AGP : NVKM_DEVICE_PCI, + (u64)pci_domain_nr(pci_dev->bus) << 32 | + pci_dev->bus->number << 16 | + PCI_SLOT(pci_dev->devfn) << 8 | + PCI_FUNC(pci_dev->devfn), name, + cfg, dbg, detect, mmio, subdev_mask, + &pdev->device); + + if (ret) + return ret; + + /* + * Set a preliminary DMA mask based on the .dma_bits member of the + * MMU subdevice. This allows other subdevices to create DMA mappings + * in their init() or oneinit() methods, which may be called before the + * TTM layer sets the DMA mask definitively. + * This is necessary for platforms where the default DMA mask of 32 + * does not cover any system memory, i.e., when all RAM is > 4 GB. + */ + if (subdev_mask & BIT(NVKM_SUBDEV_MMU)) + dma_set_mask_and_coherent(&pci_dev->dev, + DMA_BIT_MASK(pdev->device.mmu->dma_bits)); + + return 0; } -- cgit v1.2.3 From ebf7655aebe6a4e339a269130b399f5f7b0bf4b9 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 6 Oct 2016 16:49:29 +0100 Subject: drm/nouveau/fb/gf100: defer DMA mapping of scratch page to oneinit() hook The 100c10 scratch page is mapped using dma_map_page() before the TTM layer has had a chance to set the DMA mask. This means we are still running with the default of 32 when this code executes, and this causes problems for platforms with no memory below 4 GB (such as AMD Seattle) So move the dma_map_page() to the .oneinit hook, which executes after the DMA mask has been set. Signed-off-by: Ard Biesheuvel Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c index 76433cc66fff..3841ad6be99e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c @@ -50,24 +50,33 @@ gf100_fb_intr(struct nvkm_fb *base) } int -gf100_fb_oneinit(struct nvkm_fb *fb) +gf100_fb_oneinit(struct nvkm_fb *base) { - struct nvkm_device *device = fb->subdev.device; + struct gf100_fb *fb = gf100_fb(base); + struct nvkm_device *device = fb->base.subdev.device; int ret, size = 0x1000; size = nvkm_longopt(device->cfgopt, "MmuDebugBufferSize", size); size = min(size, 0x1000); ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000, - false, &fb->mmu_rd); + false, &fb->base.mmu_rd); if (ret) return ret; ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000, - false, &fb->mmu_wr); + false, &fb->base.mmu_wr); if (ret) return ret; + fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (fb->r100c10_page) { + fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0, + PAGE_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(device->dev, fb->r100c10)) + return -EFAULT; + } + return 0; } @@ -123,14 +132,6 @@ gf100_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, nvkm_fb_ctor(func, device, index, &fb->base); *pfb = &fb->base; - fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (fb->r100c10_page) { - fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0, - PAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(device->dev, fb->r100c10)) - return -EFAULT; - } - return 0; } -- cgit v1.2.3 From 2ecf7c43d78093a24aa44c0a14a335457f065bb2 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 6 Oct 2016 16:49:30 +0100 Subject: drm/nouveau/fb/nv50: defer DMA mapping of scratch page to oneinit() hook The 100c08 scratch page is mapped using dma_map_page() before the TTM layer has had a chance to set the DMA mask. This means we are still running with the default of 32 when this code executes, and this causes problems for platforms with no memory below 4 GB (such as AMD Seattle) So move the dma_map_page() to the .oneinit hook, which executes after the DMA mask has been set. Signed-off-by: Ard Biesheuvel Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c | 28 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c index 1b5fb02eab2a..0595e0722bfc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c @@ -210,6 +210,23 @@ nv50_fb_intr(struct nvkm_fb *base) nvkm_fifo_chan_put(fifo, flags, &chan); } +static int +nv50_fb_oneinit(struct nvkm_fb *base) +{ + struct nv50_fb *fb = nv50_fb(base); + struct nvkm_device *device = fb->base.subdev.device; + + fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (fb->r100c08_page) { + fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0, + PAGE_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(device->dev, fb->r100c08)) + return -EFAULT; + } + + return 0; +} + static void nv50_fb_init(struct nvkm_fb *base) { @@ -245,6 +262,7 @@ nv50_fb_dtor(struct nvkm_fb *base) static const struct nvkm_fb_func nv50_fb_ = { .dtor = nv50_fb_dtor, + .oneinit = nv50_fb_oneinit, .init = nv50_fb_init, .intr = nv50_fb_intr, .ram_new = nv50_fb_ram_new, @@ -263,16 +281,6 @@ nv50_fb_new_(const struct nv50_fb_func *func, struct nvkm_device *device, fb->func = func; *pfb = &fb->base; - fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (fb->r100c08_page) { - fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0, - PAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(device->dev, fb->r100c08)) - return -EFAULT; - } else { - nvkm_warn(&fb->base.subdev, "failed 100c08 page alloc\n"); - } - return 0; } -- cgit v1.2.3 From 40006c4355e3469330317a77dfff300802265d20 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 12 Oct 2016 10:18:54 +0300 Subject: drm/i915: Remove unused BSM_MASK causing warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove never used BSM{,_MASK}. BSM_MASK #define also causes a warning. include/drm/i915_drm.h:96:34: warning: result of ‘65535 << 20’ requires 37 bits to represent, but ‘int’ only has 32 bits [-Wshiftoverflow=] #define INTEL_BSM_MASK (0xFFFF << 20) Reported-by: Linus Torvalds Signed-off-by: Joonas Lahtinen Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1476256734-6457-1-git-send-email-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/i915_reg.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 595d196f753f..5f7aecbba549 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -86,8 +86,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define DEVEN 0x54 #define DEVEN_MCHBAR_EN (1 << 28) -#define BSM 0x5c -#define BSM_MASK (0xFFFF << 20) +/* BSM in include/drm/i915_drm.h */ #define HPLLCC 0xc0 /* 85x only */ #define GC_CLOCK_CONTROL_MASK (0x7 << 0) -- cgit v1.2.3 From 246ad56e25b4005648cd54e0f0ab8f0357f8a42a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Oct 2016 12:09:52 +0200 Subject: mac80211_hwsim: make multi-channel ops const Instead of building the multi-channel ops at runtime, declare the common ops with a macro and build both that way, so that the multi-channel ops can also be const. As a side effect, due to the removed code, this decreases the size of the module (while shifting data from .bss to .text due to the newly added const). Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 79 ++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 431f13b4faf6..f9ba0772e471 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2256,35 +2256,51 @@ static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw, WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); } +#define HWSIM_COMMON_OPS \ + .tx = mac80211_hwsim_tx, \ + .start = mac80211_hwsim_start, \ + .stop = mac80211_hwsim_stop, \ + .add_interface = mac80211_hwsim_add_interface, \ + .change_interface = mac80211_hwsim_change_interface, \ + .remove_interface = mac80211_hwsim_remove_interface, \ + .config = mac80211_hwsim_config, \ + .configure_filter = mac80211_hwsim_configure_filter, \ + .bss_info_changed = mac80211_hwsim_bss_info_changed, \ + .sta_add = mac80211_hwsim_sta_add, \ + .sta_remove = mac80211_hwsim_sta_remove, \ + .sta_notify = mac80211_hwsim_sta_notify, \ + .set_tim = mac80211_hwsim_set_tim, \ + .conf_tx = mac80211_hwsim_conf_tx, \ + .get_survey = mac80211_hwsim_get_survey, \ + CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) \ + .ampdu_action = mac80211_hwsim_ampdu_action, \ + .flush = mac80211_hwsim_flush, \ + .get_tsf = mac80211_hwsim_get_tsf, \ + .set_tsf = mac80211_hwsim_set_tsf, \ + .get_et_sset_count = mac80211_hwsim_get_et_sset_count, \ + .get_et_stats = mac80211_hwsim_get_et_stats, \ + .get_et_strings = mac80211_hwsim_get_et_strings, + static const struct ieee80211_ops mac80211_hwsim_ops = { - .tx = mac80211_hwsim_tx, - .start = mac80211_hwsim_start, - .stop = mac80211_hwsim_stop, - .add_interface = mac80211_hwsim_add_interface, - .change_interface = mac80211_hwsim_change_interface, - .remove_interface = mac80211_hwsim_remove_interface, - .config = mac80211_hwsim_config, - .configure_filter = mac80211_hwsim_configure_filter, - .bss_info_changed = mac80211_hwsim_bss_info_changed, - .sta_add = mac80211_hwsim_sta_add, - .sta_remove = mac80211_hwsim_sta_remove, - .sta_notify = mac80211_hwsim_sta_notify, - .set_tim = mac80211_hwsim_set_tim, - .conf_tx = mac80211_hwsim_conf_tx, - .get_survey = mac80211_hwsim_get_survey, - CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) - .ampdu_action = mac80211_hwsim_ampdu_action, + HWSIM_COMMON_OPS .sw_scan_start = mac80211_hwsim_sw_scan, .sw_scan_complete = mac80211_hwsim_sw_scan_complete, - .flush = mac80211_hwsim_flush, - .get_tsf = mac80211_hwsim_get_tsf, - .set_tsf = mac80211_hwsim_set_tsf, - .get_et_sset_count = mac80211_hwsim_get_et_sset_count, - .get_et_stats = mac80211_hwsim_get_et_stats, - .get_et_strings = mac80211_hwsim_get_et_strings, }; -static struct ieee80211_ops mac80211_hwsim_mchan_ops; +static const struct ieee80211_ops mac80211_hwsim_mchan_ops = { + HWSIM_COMMON_OPS + .hw_scan = mac80211_hwsim_hw_scan, + .cancel_hw_scan = mac80211_hwsim_cancel_hw_scan, + .sw_scan_start = NULL, + .sw_scan_complete = NULL, + .remain_on_channel = mac80211_hwsim_roc, + .cancel_remain_on_channel = mac80211_hwsim_croc, + .add_chanctx = mac80211_hwsim_add_chanctx, + .remove_chanctx = mac80211_hwsim_remove_chanctx, + .change_chanctx = mac80211_hwsim_change_chanctx, + .assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx, + .unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx, +}; struct hwsim_new_radio_params { unsigned int channels; @@ -3360,21 +3376,6 @@ static int __init init_mac80211_hwsim(void) if (channels < 1) return -EINVAL; - mac80211_hwsim_mchan_ops = mac80211_hwsim_ops; - mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan; - mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan; - mac80211_hwsim_mchan_ops.sw_scan_start = NULL; - mac80211_hwsim_mchan_ops.sw_scan_complete = NULL; - mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc; - mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc; - mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx; - mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx; - mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx; - mac80211_hwsim_mchan_ops.assign_vif_chanctx = - mac80211_hwsim_assign_vif_chanctx; - mac80211_hwsim_mchan_ops.unassign_vif_chanctx = - mac80211_hwsim_unassign_vif_chanctx; - spin_lock_init(&hwsim_radio_lock); err = register_pernet_device(&hwsim_net_ops); -- cgit v1.2.3 From 0e70447605f49699b877fea1039b2c5335529d96 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 10:05:17 +0100 Subject: drm/i915: Move common code out of i915_gpu_error.c In the next patch, I want to conditionally compile i915_gpu_error.c and that requires moving the functions used by debug out of i915_gpu_error.c! Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161012090522.367-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 3 - drivers/gpu/drm/i915/i915_gpu_error.c | 106 +------------------------------- drivers/gpu/drm/i915/i915_irq.c | 4 +- drivers/gpu/drm/i915/intel_engine_cs.c | 104 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 + 6 files changed, 111 insertions(+), 111 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 20689f1cd719..f6762e00f872 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1339,7 +1339,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seqno[id] = intel_engine_get_seqno(engine); } - i915_get_engine_instdone(dev_priv, RCS, &instdone); + intel_engine_get_instdone(&dev_priv->engine[RCS], &instdone); intel_runtime_pm_put(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 54d860e1c0fc..4553a5372008 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3564,9 +3564,6 @@ void i915_error_state_get(struct drm_device *dev, void i915_error_state_put(struct i915_error_state_file_priv *error_priv); void i915_destroy_error_state(struct drm_device *dev); -void i915_get_engine_instdone(struct drm_i915_private *dev_priv, - enum intel_engine_id engine_id, - struct intel_instdone *instdone); const char *i915_cache_level_str(struct drm_i915_private *i915, int type); /* i915_cmd_parser.c */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index b5b58692ac5a..04205c82f0c9 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1038,7 +1038,7 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->ipehr = I915_READ(IPEHR); } - i915_get_engine_instdone(dev_priv, engine->id, &ee->instdone); + intel_engine_get_instdone(engine, &ee->instdone); ee->waiting = intel_engine_has_waiter(engine); ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); @@ -1548,107 +1548,3 @@ void i915_destroy_error_state(struct drm_device *dev) if (error) kref_put(&error->ref, i915_error_state_free); } - -const char *i915_cache_level_str(struct drm_i915_private *i915, int type) -{ - switch (type) { - case I915_CACHE_NONE: return " uncached"; - case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; - case I915_CACHE_L3_LLC: return " L3+LLC"; - case I915_CACHE_WT: return " WT"; - default: return ""; - } -} - -static inline uint32_t -read_subslice_reg(struct drm_i915_private *dev_priv, int slice, - int subslice, i915_reg_t reg) -{ - uint32_t mcr; - uint32_t ret; - enum forcewake_domains fw_domains; - - fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, - FW_REG_READ); - fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, - GEN8_MCR_SELECTOR, - FW_REG_READ | FW_REG_WRITE); - - spin_lock_irq(&dev_priv->uncore.lock); - intel_uncore_forcewake_get__locked(dev_priv, fw_domains); - - mcr = I915_READ_FW(GEN8_MCR_SELECTOR); - /* - * The HW expects the slice and sublice selectors to be reset to 0 - * after reading out the registers. - */ - WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); - mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); - mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); - I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); - - ret = I915_READ_FW(reg); - - mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); - I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); - - intel_uncore_forcewake_put__locked(dev_priv, fw_domains); - spin_unlock_irq(&dev_priv->uncore.lock); - - return ret; -} - -/* NB: please notice the memset */ -void i915_get_engine_instdone(struct drm_i915_private *dev_priv, - enum intel_engine_id engine_id, - struct intel_instdone *instdone) -{ - u32 mmio_base = dev_priv->engine[engine_id].mmio_base; - int slice; - int subslice; - - memset(instdone, 0, sizeof(*instdone)); - - switch (INTEL_GEN(dev_priv)) { - default: - instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); - - if (engine_id != RCS) - break; - - instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); - for_each_instdone_slice_subslice(dev_priv, slice, subslice) { - instdone->sampler[slice][subslice] = - read_subslice_reg(dev_priv, slice, subslice, - GEN7_SAMPLER_INSTDONE); - instdone->row[slice][subslice] = - read_subslice_reg(dev_priv, slice, subslice, - GEN7_ROW_INSTDONE); - } - break; - case 7: - instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); - - if (engine_id != RCS) - break; - - instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); - instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); - instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); - - break; - case 6: - case 5: - case 4: - instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); - - if (engine_id == RCS) - /* HACK: Using the wrong struct member */ - instdone->slice_common = I915_READ(GEN4_INSTDONE1); - break; - case 3: - case 2: - instdone->instdone = I915_READ(GEN2_INSTDONE); - break; - } -} diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index bd6c8b0eeaef..ddff6f9b869c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2588,7 +2588,7 @@ static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) pr_err("render error detected, EIR: 0x%08x\n", eir); - i915_get_engine_instdone(dev_priv, RCS, &instdone); + intel_engine_get_instdone(&dev_priv->engine[RCS], &instdone); if (IS_G4X(dev_priv)) { if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) { @@ -3001,7 +3001,7 @@ static bool subunits_stuck(struct intel_engine_cs *engine) if (engine->id != RCS) return true; - i915_get_engine_instdone(dev_priv, RCS, &instdone); + intel_engine_get_instdone(engine, &instdone); /* There might be unstable subunit states even when * actual head is not moving. Filter out the unstable ones by diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 480584c09306..1d597feba97f 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -349,3 +349,107 @@ u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) return bbaddr; } + +const char *i915_cache_level_str(struct drm_i915_private *i915, int type) +{ + switch (type) { + case I915_CACHE_NONE: return " uncached"; + case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; + case I915_CACHE_L3_LLC: return " L3+LLC"; + case I915_CACHE_WT: return " WT"; + default: return ""; + } +} + +static inline uint32_t +read_subslice_reg(struct drm_i915_private *dev_priv, int slice, + int subslice, i915_reg_t reg) +{ + uint32_t mcr; + uint32_t ret; + enum forcewake_domains fw_domains; + + fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, + FW_REG_READ); + fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, + GEN8_MCR_SELECTOR, + FW_REG_READ | FW_REG_WRITE); + + spin_lock_irq(&dev_priv->uncore.lock); + intel_uncore_forcewake_get__locked(dev_priv, fw_domains); + + mcr = I915_READ_FW(GEN8_MCR_SELECTOR); + /* + * The HW expects the slice and sublice selectors to be reset to 0 + * after reading out the registers. + */ + WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); + mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); + mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); + I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); + + ret = I915_READ_FW(reg); + + mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); + I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); + + intel_uncore_forcewake_put__locked(dev_priv, fw_domains); + spin_unlock_irq(&dev_priv->uncore.lock); + + return ret; +} + +/* NB: please notice the memset */ +void intel_engine_get_instdone(struct intel_engine_cs *engine, + struct intel_instdone *instdone) +{ + struct drm_i915_private *dev_priv = engine->i915; + u32 mmio_base = engine->mmio_base; + int slice; + int subslice; + + memset(instdone, 0, sizeof(*instdone)); + + switch (INTEL_GEN(dev_priv)) { + default: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine->id != RCS) + break; + + instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); + for_each_instdone_slice_subslice(dev_priv, slice, subslice) { + instdone->sampler[slice][subslice] = + read_subslice_reg(dev_priv, slice, subslice, + GEN7_SAMPLER_INSTDONE); + instdone->row[slice][subslice] = + read_subslice_reg(dev_priv, slice, subslice, + GEN7_ROW_INSTDONE); + } + break; + case 7: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine->id != RCS) + break; + + instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); + instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); + instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); + + break; + case 6: + case 5: + case 4: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine->id == RCS) + /* HACK: Using the wrong struct member */ + instdone->slice_common = I915_READ(GEN4_INSTDONE1); + break; + case 3: + case 2: + instdone->instdone = I915_READ(GEN2_INSTDONE); + break; + } +} diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 124f4646958d..36eff9765cc2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -550,6 +550,9 @@ static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) int init_workarounds_ring(struct intel_engine_cs *engine); +void intel_engine_get_instdone(struct intel_engine_cs *engine, + struct intel_instdone *instdone); + /* * Arbitrary size for largest possible 'add request' sequence. The code paths * are complex and variable. Empirical measurement shows that the worst case -- cgit v1.2.3 From 98a2f411671fe08612ff0ef977136253606a6ef7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 10:05:18 +0100 Subject: drm/i915: Allow disabling error capture We currently capture the GPU state after we detect a hang. This is vital for us to both triage and debug hangs in the wild (post-mortem debugging). However, it comes at the cost of running some potentially dangerous code (since it has to make very few assumption about the state of the driver) that is quite resource intensive. This patch introduces both a method to disable error capture at runtime (for users who hit bugs at runtime and need a workaround) and to disable error capture at compiletime (for realtime users who want to minimise any possible latency, and never require error capture, saving ~30k of code). The cost is that we now have to be wary of (and test!) a kconfig flag and a module parameter. The effect of the module parameter is easy to verify through code inspection and runtime testing, but a kconfig flag needs regular compile checking. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Acked-by: Jani Nikula Acked-by: Daniel Vetter gpu_error.first_error)) return; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 768ad89d9cd4..629e4334719c 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = { .load_detect_test = 0, .force_reset_modeset_test = 0, .reset = true, + .error_capture = true, .invert_brightness = 0, .disable_display = 0, .enable_cmd_parser = 1, @@ -115,6 +116,14 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type, module_param_named_unsafe(reset, i915.reset, bool, 0600); MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)"); +#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) +module_param_named(error_capture, i915.error_capture, bool, 0600); +MODULE_PARM_DESC(error_capture, + "Record the GPU state following a hang. " + "This information in /sys/class/drm/card/error is vital for " + "triaging and debugging hangs."); +#endif + module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644); MODULE_PARM_DESC(enable_hangcheck, "Periodically check GPU activity for detecting hangs. " diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 3a0dd78ddb38..94efc899c1ef 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -59,6 +59,7 @@ struct i915_params { bool load_detect_test; bool force_reset_modeset_test; bool reset; + bool error_capture; bool disable_display; bool verbose_state_checks; bool nuclear_pageflip; diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 1012eeea1324..47590ab08d7e 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -514,6 +514,8 @@ static const struct attribute *vlv_attrs[] = { NULL, }; +#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) + static ssize_t error_state_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) @@ -571,6 +573,21 @@ static struct bin_attribute error_state_attr = { .write = error_state_write, }; +static void i915_setup_error_capture(struct device *kdev) +{ + if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr)) + DRM_ERROR("error_state sysfs setup failed\n"); +} + +static void i915_teardown_error_capture(struct device *kdev) +{ + sysfs_remove_bin_file(&kdev->kobj, &error_state_attr); +} +#else +static void i915_setup_error_capture(struct device *kdev) {} +static void i915_teardown_error_capture(struct device *kdev) {} +#endif + void i915_setup_sysfs(struct drm_i915_private *dev_priv) { struct device *kdev = dev_priv->drm.primary->kdev; @@ -617,17 +634,15 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) if (ret) DRM_ERROR("RPS sysfs setup failed\n"); - ret = sysfs_create_bin_file(&kdev->kobj, - &error_state_attr); - if (ret) - DRM_ERROR("error_state sysfs setup failed\n"); + i915_setup_error_capture(kdev); } void i915_teardown_sysfs(struct drm_i915_private *dev_priv) { struct device *kdev = dev_priv->drm.primary->kdev; - sysfs_remove_bin_file(&kdev->kobj, &error_state_attr); + i915_teardown_error_capture(kdev); + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) sysfs_remove_files(&kdev->kobj, vlv_attrs); else diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e4bdd3a6a6e3..cfcb03f82016 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -17097,6 +17097,8 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state) return 0; } +#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) + struct intel_display_error_state { u32 power_well_driver; @@ -17279,3 +17281,5 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync); } } + +#endif diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index a24bc8c7889f..8c411bfc3b3f 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1470,6 +1470,8 @@ void intel_cleanup_overlay(struct drm_i915_private *dev_priv) kfree(dev_priv->overlay); } +#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) + struct intel_overlay_error_state { struct overlay_registers regs; unsigned long base; @@ -1587,3 +1589,5 @@ intel_overlay_print_error_state(struct drm_i915_error_state_buf *m, P(UVSCALEV); #undef P } + +#endif -- cgit v1.2.3 From 9f267eb8d2ea0a87f694da3f236067335e8cb7b9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 10:05:19 +0100 Subject: drm/i915: Stop the machine whilst capturing the GPU crash dump The error state is purposefully racy as we expect it to be called at any time and so have avoided any locking whilst capturing the crash dump. However, with multi-engine GPUs and multiple CPUs, those races can manifest into OOPSes as we attempt to chase dangling pointers freed on other CPUs. Under discussion are lots of ways to slow down normal operation in order to protect the post-mortem error capture, but what it we take the opposite approach and freeze the machine whilst the error capture runs (note the GPU may still running, but as long as we don't process any of the results the driver's bookkeeping will be static). Note that by of itself, this is not a complete fix. It also depends on the compiler barriers in list_add/list_del to prevent traversing the lists into the void. We also depend that we only require state from carefully controlled sources - i.e. all the state we require for post-mortem debugging should be reachable from the request itself so that we only have to worry about retrieving the request carefully. Once we have the request, we know that all pointers from it are intact. v2: Avoid drm_clflush_pages() inside stop_machine() as it may use stop_machine() itself for its wbinvd fallback. Signed-off-by: Chris Wilson Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161012090522.367-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Kconfig | 1 + drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gpu_error.c | 46 +++++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 8844b99bd760..3eff42e4a441 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -4,6 +4,7 @@ config DRM_I915 depends on X86 && PCI select INTEL_GTT select INTERVAL_TREE + select STOP_MACHINE # we need shmfs for the swappable backing store, and in particular # the shmem_readpage() which depends upon tmpfs select SHMEM diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 380590b30bbf..4199e8aa436a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -746,6 +746,8 @@ struct drm_i915_error_state { struct kref ref; struct timeval time; + struct drm_i915_private *i915; + char error_msg[128]; bool simulated; int iommu; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index c88c0d192a60..159d6d7e0cee 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -28,6 +28,7 @@ */ #include +#include #include "i915_drv.h" static const char *engine_str(int engine) @@ -744,14 +745,12 @@ i915_error_object_create(struct drm_i915_private *dev_priv, dst->page_count = num_pages; while (num_pages--) { - unsigned long flags; void *d; d = kmalloc(PAGE_SIZE, GFP_ATOMIC); if (d == NULL) goto unwind; - local_irq_save(flags); if (use_ggtt) { void __iomem *s; @@ -770,15 +769,10 @@ i915_error_object_create(struct drm_i915_private *dev_priv, page = i915_gem_object_get_page(src, i); - drm_clflush_pages(&page, 1); - s = kmap_atomic(page); memcpy(d, s, PAGE_SIZE); kunmap_atomic(s); - - drm_clflush_pages(&page, 1); } - local_irq_restore(flags); dst->pages[i++] = d; reloc_offset += PAGE_SIZE; @@ -1447,6 +1441,31 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv, sizeof(error->device_info)); } +static int capture(void *data) +{ + struct drm_i915_error_state *error = data; + + /* Ensure that what we readback from memory matches what the GPU sees */ + wbinvd(); + + i915_capture_gen_state(error->i915, error); + i915_capture_reg_state(error->i915, error); + i915_gem_record_fences(error->i915, error); + i915_gem_record_rings(error->i915, error); + i915_capture_active_buffers(error->i915, error); + i915_capture_pinned_buffers(error->i915, error); + + do_gettimeofday(&error->time); + + error->overlay = intel_overlay_capture_error_state(error->i915); + error->display = intel_display_capture_error_state(error->i915); + + /* And make sure we don't leave trash in the CPU cache */ + wbinvd(); + + return 0; +} + /** * i915_capture_error_state - capture an error record for later analysis * @dev: drm device @@ -1478,18 +1497,9 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, } kref_init(&error->ref); + error->i915 = dev_priv; - i915_capture_gen_state(dev_priv, error); - i915_capture_reg_state(dev_priv, error); - i915_gem_record_fences(dev_priv, error); - i915_gem_record_rings(dev_priv, error); - i915_capture_active_buffers(dev_priv, error); - i915_capture_pinned_buffers(dev_priv, error); - - do_gettimeofday(&error->time); - - error->overlay = intel_overlay_capture_error_state(dev_priv); - error->display = intel_display_capture_error_state(dev_priv); + stop_machine(capture, error, NULL); i915_error_capture_msg(dev_priv, error, engine_mask, error_msg); DRM_INFO("%s\n", error->error_msg); -- cgit v1.2.3 From 95374d759ac795c33ad4fd6f684bc5a5e280e7a4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 10:05:20 +0100 Subject: drm/i915: Always use the GTT for error capture Since the GTT provides universal access to any GPU page, we can use it to reduce our plethora of read methods to just one. It also has the important characteristic of being exactly what the GPU sees - if there are incoherency problems, seeing the batch as executed (rather than as trapped inside the cpu cache) is important. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161012090522.367-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 43 ++++++++---- drivers/gpu/drm/i915/i915_gem_gtt.h | 2 + drivers/gpu/drm/i915/i915_gpu_error.c | 120 ++++++++++++---------------------- 3 files changed, 74 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0bb4232f66bc..2d846aa39ca5 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2717,6 +2717,7 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) */ struct i915_ggtt *ggtt = &dev_priv->ggtt; unsigned long hole_start, hole_end; + struct i915_hw_ppgtt *ppgtt; struct drm_mm_node *entry; int ret; @@ -2724,6 +2725,15 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) if (ret) return ret; + /* Reserve a mappable slot for our lockless error capture */ + ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm, + &ggtt->error_capture, + 4096, 0, -1, + 0, ggtt->mappable_end, + 0, 0); + if (ret) + return ret; + /* Clear any non-preallocated blocks */ drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) { DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", @@ -2738,25 +2748,21 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) true); if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) { - struct i915_hw_ppgtt *ppgtt; - ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); - if (!ppgtt) - return -ENOMEM; + if (!ppgtt) { + ret = -ENOMEM; + goto err; + } ret = __hw_ppgtt_init(ppgtt, dev_priv); - if (ret) { - kfree(ppgtt); - return ret; - } + if (ret) + goto err_ppgtt; - if (ppgtt->base.allocate_va_range) + if (ppgtt->base.allocate_va_range) { ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0, ppgtt->base.total); - if (ret) { - ppgtt->base.cleanup(&ppgtt->base); - kfree(ppgtt); - return ret; + if (ret) + goto err_ppgtt_cleanup; } ppgtt->base.clear_range(&ppgtt->base, @@ -2770,6 +2776,14 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) } return 0; + +err_ppgtt_cleanup: + ppgtt->base.cleanup(&ppgtt->base); +err_ppgtt: + kfree(ppgtt); +err: + drm_mm_remove_node(&ggtt->error_capture); + return ret; } /** @@ -2788,6 +2802,9 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) i915_gem_cleanup_stolen(&dev_priv->drm); + if (drm_mm_node_allocated(&ggtt->error_capture)) + drm_mm_remove_node(&ggtt->error_capture); + if (drm_mm_initialized(&ggtt->base.mm)) { intel_vgt_deballoon(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index ec78be2f8c77..bd93fb8f99d2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -450,6 +450,8 @@ struct i915_ggtt { bool do_idle_maps; int mtrr; + + struct drm_mm_node error_capture; }; struct i915_hw_ppgtt { diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 159d6d7e0cee..b3b2e6c1c6c6 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -656,7 +656,7 @@ static void i915_error_object_free(struct drm_i915_error_object *obj) return; for (page = 0; page < obj->page_count; page++) - kfree(obj->pages[page]); + free_page((unsigned long)obj->pages[page]); kfree(obj); } @@ -693,98 +693,69 @@ static void i915_error_state_free(struct kref *error_ref) kfree(error); } +static int compress_page(void *src, struct drm_i915_error_object *dst) +{ + unsigned long page; + + page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); + if (!page) + return -ENOMEM; + + dst->pages[dst->page_count++] = (void *)page; + + memcpy((void *)page, src, PAGE_SIZE); + return 0; +} + static struct drm_i915_error_object * -i915_error_object_create(struct drm_i915_private *dev_priv, +i915_error_object_create(struct drm_i915_private *i915, struct i915_vma *vma) { - struct i915_ggtt *ggtt = &dev_priv->ggtt; - struct drm_i915_gem_object *src; + struct i915_ggtt *ggtt = &i915->ggtt; + const u64 slot = ggtt->error_capture.start; struct drm_i915_error_object *dst; - int num_pages; - bool use_ggtt; - int i = 0; - u64 reloc_offset; + unsigned long num_pages; + struct sgt_iter iter; + dma_addr_t dma; if (!vma) return NULL; - src = vma->obj; - if (!src->pages) - return NULL; - - num_pages = src->base.size >> PAGE_SHIFT; - - dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC); + num_pages = min_t(u64, vma->size, vma->obj->base.size) >> PAGE_SHIFT; + dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), + GFP_ATOMIC | __GFP_NOWARN); if (!dst) return NULL; dst->gtt_offset = vma->node.start; dst->gtt_size = vma->node.size; + dst->page_count = 0; - reloc_offset = dst->gtt_offset; - use_ggtt = (src->cache_level == I915_CACHE_NONE && - (vma->flags & I915_VMA_GLOBAL_BIND) && - reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end); - - /* Cannot access stolen address directly, try to use the aperture */ - if (src->stolen) { - use_ggtt = true; - - if (!(vma->flags & I915_VMA_GLOBAL_BIND)) - goto unwind; - - reloc_offset = vma->node.start; - if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end) - goto unwind; - } + for_each_sgt_dma(dma, iter, vma->pages) { + void __iomem *s; + int ret; - /* Cannot access snooped pages through the aperture */ - if (use_ggtt && src->cache_level != I915_CACHE_NONE && - !HAS_LLC(dev_priv)) - goto unwind; + ggtt->base.insert_page(&ggtt->base, dma, slot, + I915_CACHE_NONE, 0); - dst->page_count = num_pages; - while (num_pages--) { - void *d; + s = io_mapping_map_atomic_wc(&ggtt->mappable, slot); + ret = compress_page((void * __force)s, dst); + io_mapping_unmap_atomic(s); - d = kmalloc(PAGE_SIZE, GFP_ATOMIC); - if (d == NULL) + if (ret) goto unwind; - - if (use_ggtt) { - void __iomem *s; - - /* Simply ignore tiling or any overlapping fence. - * It's part of the error state, and this hopefully - * captures what the GPU read. - */ - - s = io_mapping_map_atomic_wc(&ggtt->mappable, - reloc_offset); - memcpy_fromio(d, s, PAGE_SIZE); - io_mapping_unmap_atomic(s); - } else { - struct page *page; - void *s; - - page = i915_gem_object_get_page(src, i); - - s = kmap_atomic(page); - memcpy(d, s, PAGE_SIZE); - kunmap_atomic(s); - } - - dst->pages[i++] = d; - reloc_offset += PAGE_SIZE; } - - return dst; + goto out; unwind: - while (i--) - kfree(dst->pages[i]); + while (dst->page_count--) + free_page((unsigned long)dst->pages[dst->page_count]); kfree(dst); - return NULL; + dst = NULL; + +out: + ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE, true); + return dst; } /* The error capture is special as tries to run underneath the normal @@ -1445,9 +1416,6 @@ static int capture(void *data) { struct drm_i915_error_state *error = data; - /* Ensure that what we readback from memory matches what the GPU sees */ - wbinvd(); - i915_capture_gen_state(error->i915, error); i915_capture_reg_state(error->i915, error); i915_gem_record_fences(error->i915, error); @@ -1460,9 +1428,6 @@ static int capture(void *data) error->overlay = intel_overlay_capture_error_state(error->i915); error->display = intel_display_capture_error_state(error->i915); - /* And make sure we don't leave trash in the CPU cache */ - wbinvd(); - return 0; } @@ -1539,7 +1504,6 @@ void i915_error_state_get(struct drm_device *dev, if (error_priv->error) kref_get(&error_priv->error->ref); spin_unlock_irq(&dev_priv->gpu_error.lock); - } void i915_error_state_put(struct i915_error_state_file_priv *error_priv) -- cgit v1.2.3 From fc4c79c37e822719cab447a448af0b48f4a52418 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 10:05:21 +0100 Subject: drm/i915: Consolidate error object printing Leave all the pretty printing to userspace and simplify the error capture to only have a single common object printer. It makes the kernel code more compact, and the refactoring allows us to apply more complex transformations like compressing the output. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161012090522.367-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gpu_error.c | 100 +++++++++------------------------- 1 file changed, 25 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index b3b2e6c1c6c6..22bd2187ea37 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -341,10 +341,22 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) } static void print_error_obj(struct drm_i915_error_state_buf *m, + struct intel_engine_cs *engine, + const char *name, struct drm_i915_error_object *obj) { int page, offset, elt; + if (!obj) + return; + + if (name) { + err_printf(m, "%s --- %s = 0x%08x %08x\n", + engine ? engine->name : "global", name, + upper_32_bits(obj->gtt_offset), + lower_32_bits(obj->gtt_offset)); + } + for (page = offset = 0; page < obj->page_count; page++) { for (elt = 0; elt < PAGE_SIZE/4; elt++) { err_printf(m, "%08x : %08x\n", offset, @@ -370,8 +382,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, struct pci_dev *pdev = dev_priv->drm.pdev; struct drm_i915_error_state *error = error_priv->error; struct drm_i915_error_object *obj; - int i, j, offset, elt; int max_hangcheck_score; + int i, j; if (!error) { err_printf(m, "no error state collected\n"); @@ -491,15 +503,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, " --- gtt_offset = 0x%08x %08x\n", upper_32_bits(obj->gtt_offset), lower_32_bits(obj->gtt_offset)); - print_error_obj(m, obj); - } - - obj = ee->wa_batchbuffer; - if (obj) { - err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n", - dev_priv->engine[i].name, - lower_32_bits(obj->gtt_offset)); - print_error_obj(m, obj); + print_error_obj(m, &dev_priv->engine[i], NULL, obj); } if (ee->num_requests) { @@ -531,77 +535,23 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } } - if ((obj = ee->ringbuffer)) { - err_printf(m, "%s --- ringbuffer = 0x%08x\n", - dev_priv->engine[i].name, - lower_32_bits(obj->gtt_offset)); - print_error_obj(m, obj); - } + print_error_obj(m, &dev_priv->engine[i], + "ringbuffer", ee->ringbuffer); - if ((obj = ee->hws_page)) { - u64 hws_offset = obj->gtt_offset; - u32 *hws_page = &obj->pages[0][0]; + print_error_obj(m, &dev_priv->engine[i], + "HW Status", ee->hws_page); - if (i915.enable_execlists) { - hws_offset += LRC_PPHWSP_PN * PAGE_SIZE; - hws_page = &obj->pages[LRC_PPHWSP_PN][0]; - } - err_printf(m, "%s --- HW Status = 0x%08llx\n", - dev_priv->engine[i].name, hws_offset); - offset = 0; - for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { - err_printf(m, "[%04x] %08x %08x %08x %08x\n", - offset, - hws_page[elt], - hws_page[elt+1], - hws_page[elt+2], - hws_page[elt+3]); - offset += 16; - } - } + print_error_obj(m, &dev_priv->engine[i], + "HW context", ee->ctx); - obj = ee->wa_ctx; - if (obj) { - u64 wa_ctx_offset = obj->gtt_offset; - u32 *wa_ctx_page = &obj->pages[0][0]; - struct intel_engine_cs *engine = &dev_priv->engine[RCS]; - u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size + - engine->wa_ctx.per_ctx.size); - - err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n", - dev_priv->engine[i].name, wa_ctx_offset); - offset = 0; - for (elt = 0; elt < wa_ctx_size; elt += 4) { - err_printf(m, "[%04x] %08x %08x %08x %08x\n", - offset, - wa_ctx_page[elt + 0], - wa_ctx_page[elt + 1], - wa_ctx_page[elt + 2], - wa_ctx_page[elt + 3]); - offset += 16; - } - } + print_error_obj(m, &dev_priv->engine[i], + "WA context", ee->wa_ctx); - if ((obj = ee->ctx)) { - err_printf(m, "%s --- HW Context = 0x%08x\n", - dev_priv->engine[i].name, - lower_32_bits(obj->gtt_offset)); - print_error_obj(m, obj); - } + print_error_obj(m, &dev_priv->engine[i], + "WA batchbuffer", ee->wa_batchbuffer); } - if ((obj = error->semaphore)) { - err_printf(m, "Semaphore page = 0x%08x\n", - lower_32_bits(obj->gtt_offset)); - for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { - err_printf(m, "[%04x] %08x %08x %08x %08x\n", - elt * 4, - obj->pages[0][elt], - obj->pages[0][elt+1], - obj->pages[0][elt+2], - obj->pages[0][elt+3]); - } - } + print_error_obj(m, NULL, "Semaphores", error->semaphore); if (error->overlay) intel_overlay_print_error_state(m, error->overlay); -- cgit v1.2.3 From 0a97015d45ee4d5b1d0b93596e8319c9c2ecdb5b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 10:05:22 +0100 Subject: drm/i915: Compress GPU objects in error state Our error states are quickly growing, pinning kernel memory with them. The majority of the space is taken up by the error objects. These compress well using zlib and without decode are mostly meaningless, so encoding them does not hinder quickly parsing the error state for familiarity. v2: Make the zlib dependency optional Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161012090522.367-6-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Kconfig | 12 +++ drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_gpu_error.c | 176 ++++++++++++++++++++++++++++++---- 3 files changed, 169 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 3eff42e4a441..6aedc96aa412 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -60,6 +60,18 @@ config DRM_I915_CAPTURE_ERROR If in doubt, say "Y". +config DRM_I915_COMPRESS_ERROR + bool "Compress GPU error state" + depends on DRM_I915_CAPTURE_ERROR + select ZLIB_DEFLATE + default y + help + This option selects ZLIB_DEFLATE if it isn't already + selected and causes any error state captured upon a GPU hang + to be compressed using zlib. + + If in doubt, say "Y". + config DRM_I915_USERPTR bool "Always enable userptr support" depends on DRM_I915 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4199e8aa436a..bf397b643cc0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -820,9 +820,10 @@ struct drm_i915_error_state { struct intel_instdone instdone; struct drm_i915_error_object { - int page_count; u64 gtt_offset; u64 gtt_size; + int page_count; + int unused; u32 *pages[0]; } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 22bd2187ea37..78cc13b9b2a5 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -29,6 +29,7 @@ #include #include +#include #include "i915_drv.h" static const char *engine_str(int engine) @@ -173,6 +174,110 @@ static void i915_error_puts(struct drm_i915_error_state_buf *e, #define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__) #define err_puts(e, s) i915_error_puts(e, s) +#ifdef CONFIG_DRM_I915_COMPRESS_ERROR + +static bool compress_init(struct z_stream_s *zstream) +{ + memset(zstream, 0, sizeof(*zstream)); + + zstream->workspace = + kmalloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), + GFP_ATOMIC | __GFP_NOWARN); + if (!zstream->workspace) + return false; + + if (zlib_deflateInit(zstream, Z_DEFAULT_COMPRESSION) != Z_OK) { + kfree(zstream->workspace); + return false; + } + + return true; +} + +static int compress_page(struct z_stream_s *zstream, + void *src, + struct drm_i915_error_object *dst) +{ + zstream->next_in = src; + zstream->avail_in = PAGE_SIZE; + + do { + if (zstream->avail_out == 0) { + unsigned long page; + + page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); + if (!page) + return -ENOMEM; + + dst->pages[dst->page_count++] = (void *)page; + + zstream->next_out = (void *)page; + zstream->avail_out = PAGE_SIZE; + } + + if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK) + return -EIO; + } while (zstream->avail_in); + + /* Fallback to uncompressed if we increase size? */ + if (0 && zstream->total_out > zstream->total_in) + return -E2BIG; + + return 0; +} + +static void compress_fini(struct z_stream_s *zstream, + struct drm_i915_error_object *dst) +{ + if (dst) { + zlib_deflate(zstream, Z_FINISH); + dst->unused = zstream->avail_out; + } + + zlib_deflateEnd(zstream); + kfree(zstream->workspace); +} + +static void err_compression_marker(struct drm_i915_error_state_buf *m) +{ + err_puts(m, ":"); +} + +#else + +static bool compress_init(struct z_stream_s *zstream) +{ + return true; +} + +static int compress_page(struct z_stream_s *zstream, + void *src, + struct drm_i915_error_object *dst) +{ + unsigned long page; + + page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); + if (!page) + return -ENOMEM; + + dst->pages[dst->page_count++] = + memcpy((void *)page, src, PAGE_SIZE); + + return 0; +} + +static void compress_fini(struct z_stream_s *zstream, + struct drm_i915_error_object *dst) +{ +} + +static void err_compression_marker(struct drm_i915_error_state_buf *m) +{ + err_puts(m, "~"); +} + +#endif + static void print_error_buffers(struct drm_i915_error_state_buf *m, const char *name, struct drm_i915_error_buffer *err, @@ -340,12 +445,36 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) va_end(args); } +static int +ascii85_encode_len(int len) +{ + return DIV_ROUND_UP(len, 4); +} + +static bool +ascii85_encode(u32 in, char *out) +{ + int i; + + if (in == 0) + return false; + + out[5] = '\0'; + for (i = 5; i--; ) { + out[i] = '!' + in % 85; + in /= 85; + } + + return true; +} + static void print_error_obj(struct drm_i915_error_state_buf *m, struct intel_engine_cs *engine, const char *name, struct drm_i915_error_object *obj) { - int page, offset, elt; + char out[6]; + int page; if (!obj) return; @@ -357,13 +486,23 @@ static void print_error_obj(struct drm_i915_error_state_buf *m, lower_32_bits(obj->gtt_offset)); } - for (page = offset = 0; page < obj->page_count; page++) { - for (elt = 0; elt < PAGE_SIZE/4; elt++) { - err_printf(m, "%08x : %08x\n", offset, - obj->pages[page][elt]); - offset += 4; + err_compression_marker(m); + for (page = 0; page < obj->page_count; page++) { + int i, len; + + len = PAGE_SIZE; + if (page == obj->page_count - 1) + len -= obj->unused; + len = ascii85_encode_len(len); + + for (i = 0; i < len; i++) { + if (ascii85_encode(obj->pages[page][i], out)) + err_puts(m, out); + else + err_puts(m, "z"); } } + err_puts(m, "\n"); } static void err_print_capabilities(struct drm_i915_error_state_buf *m, @@ -643,20 +782,6 @@ static void i915_error_state_free(struct kref *error_ref) kfree(error); } -static int compress_page(void *src, struct drm_i915_error_object *dst) -{ - unsigned long page; - - page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); - if (!page) - return -ENOMEM; - - dst->pages[dst->page_count++] = (void *)page; - - memcpy((void *)page, src, PAGE_SIZE); - return 0; -} - static struct drm_i915_error_object * i915_error_object_create(struct drm_i915_private *i915, struct i915_vma *vma) @@ -664,6 +789,7 @@ i915_error_object_create(struct drm_i915_private *i915, struct i915_ggtt *ggtt = &i915->ggtt; const u64 slot = ggtt->error_capture.start; struct drm_i915_error_object *dst; + struct z_stream_s zstream; unsigned long num_pages; struct sgt_iter iter; dma_addr_t dma; @@ -672,6 +798,7 @@ i915_error_object_create(struct drm_i915_private *i915, return NULL; num_pages = min_t(u64, vma->size, vma->obj->base.size) >> PAGE_SHIFT; + num_pages = DIV_ROUND_UP(10 * num_pages, 8); /* worstcase zlib growth */ dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC | __GFP_NOWARN); if (!dst) @@ -680,6 +807,12 @@ i915_error_object_create(struct drm_i915_private *i915, dst->gtt_offset = vma->node.start; dst->gtt_size = vma->node.size; dst->page_count = 0; + dst->unused = 0; + + if (!compress_init(&zstream)) { + kfree(dst); + return NULL; + } for_each_sgt_dma(dma, iter, vma->pages) { void __iomem *s; @@ -689,7 +822,7 @@ i915_error_object_create(struct drm_i915_private *i915, I915_CACHE_NONE, 0); s = io_mapping_map_atomic_wc(&ggtt->mappable, slot); - ret = compress_page((void * __force)s, dst); + ret = compress_page(&zstream, (void __force *)s, dst); io_mapping_unmap_atomic(s); if (ret) @@ -704,6 +837,7 @@ unwind: dst = NULL; out: + compress_fini(&zstream, dst); ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE, true); return dst; } -- cgit v1.2.3 From 0fea2ed61e7fc5f31520cf2476f33bdf2d6756ab Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:24 +0100 Subject: drm/amdgpu: Remove call to reservation_object_test_signaled_rcu before wait MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since fence_wait_timeout_reservation_object_wait_timeout_rcu() with a timeout of 0 becomes reservation_object_test_signaled_rcu(), we do not need to handle such conversion in the caller. The only challenge are those callers that wish to differentiate the error code between the nonblocking busy check and potentially blocking wait. Signed-off-by: Chris Wilson Cc: Alex Deucher Cc: Christian König Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index a7ea9a3b454e..e0171c75b60c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -407,10 +407,8 @@ int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data, return -ENOENT; } robj = gem_to_amdgpu_bo(gobj); - if (timeout == 0) - ret = reservation_object_test_signaled_rcu(robj->tbo.resv, true); - else - ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, timeout); + ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, + timeout); /* ret == 0 means not signaled, * ret > 0 means signaled -- cgit v1.2.3 From cd34db4a526c370fa0ca21b046b3a2636c481f56 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:25 +0100 Subject: drm/etnaviv: Remove manual call to reservation_object_test_signaled_rcu before wait Since fence_wait_timeout_reservation_object_wait_timeout_rcu() with a timeout of 0 becomes reservation_object_test_signaled_rcu(), we do not need to handle such conversion in the caller. The only challenge are those callers that wish to differentiate the error code between the nonblocking busy check and potentially blocking wait. Signed-off-by: Chris Wilson Cc: Lucas Stach Cc: Russell King Cc: Christian Gmeiner Reviewed-by: Daniel Vetter Acked-by: Lucas Stach Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 5ce3603e6eac..9ffca2478e02 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -409,20 +409,16 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); struct drm_device *dev = obj->dev; bool write = !!(op & ETNA_PREP_WRITE); - int ret; - - if (op & ETNA_PREP_NOSYNC) { - if (!reservation_object_test_signaled_rcu(etnaviv_obj->resv, - write)) - return -EBUSY; - } else { - unsigned long remain = etnaviv_timeout_to_jiffies(timeout); - - ret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv, - write, true, remain); - if (ret <= 0) - return ret == 0 ? -ETIMEDOUT : ret; - } + unsigned long remain = + op & ETNA_PREP_NOSYNC ? 0 : etnaviv_timeout_to_jiffies(timeout); + long lret; + + lret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv, + write, true, remain); + if (lret < 0) + return lret; + else if (lret == 0) + return remain == 0 ? -EBUSY : -ETIMEDOUT; if (etnaviv_obj->flags & ETNA_BO_CACHED) { if (!etnaviv_obj->sgt) { -- cgit v1.2.3 From 491d8a1dd8bea5fb8295af006d44b543053e65c2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:27 +0100 Subject: drm/nouveau: Remove call to reservation_object_test_signaled_rcu before wait Since fence_wait_timeout_reservation_object_wait_timeout_rcu() with a timeout of 0 becomes reservation_object_test_signaled_rcu(), we do not need to handle such conversion in the caller. The only challenge are those callers that wish to differentiate the error code between the nonblocking busy check and potentially blocking wait. Signed-off-by: Chris Wilson Cc: Ben Skeggs Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/nouveau/nouveau_gem.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 72e2399bce39..0bd7164bc817 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -861,6 +861,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, struct nouveau_bo *nvbo; bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE); + long lret; int ret; gem = drm_gem_object_lookup(file_priv, req->handle); @@ -868,19 +869,15 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, return -ENOENT; nvbo = nouveau_gem_object(gem); - if (no_wait) - ret = reservation_object_test_signaled_rcu(nvbo->bo.resv, write) ? 0 : -EBUSY; - else { - long lret; + lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, + no_wait ? 0 : 30 * HZ); + if (!lret) + ret = -EBUSY; + else if (lret > 0) + ret = 0; + else + ret = lret; - lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, 30 * HZ); - if (!lret) - ret = -EBUSY; - else if (lret > 0) - ret = 0; - else - ret = lret; - } nouveau_bo_sync_for_cpu(nvbo); drm_gem_object_unreference_unlocked(gem); -- cgit v1.2.3 From 998a7aa1bdeb10e06e4ac7bff533145339fa1256 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:28 +0100 Subject: drm/vmwgfx: Remove call to reservation_object_test_signaled_rcu before wait Since fence_wait_timeout_reservation_object_wait_timeout_rcu() with a timeout of 0 becomes reservation_object_test_signaled_rcu(), we do not need to handle such conversion in the caller. The only challenge are those callers that wish to differentiate the error code between the nonblocking busy check and potentially blocking wait. Signed-off-by: Chris Wilson Cc: Sinclair Yeh Cc: Thomas Hellstrom Reviewed-by: Sinclair Yeh Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 6a328d507a28..1a85fb2d4dc6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -574,10 +574,8 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo, bool nonblock = !!(flags & drm_vmw_synccpu_dontblock); long lret; - if (nonblock) - return reservation_object_test_signaled_rcu(bo->resv, true) ? 0 : -EBUSY; - - lret = reservation_object_wait_timeout_rcu(bo->resv, true, true, MAX_SCHEDULE_TIMEOUT); + lret = reservation_object_wait_timeout_rcu(bo->resv, true, true, + nonblock ? 0 : MAX_SCHEDULE_TIMEOUT); if (!lret) return -EBUSY; else if (lret < 0) -- cgit v1.2.3 From fedf54132d2410c3949036e3f611ab8dd9dbe89e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:30 +0100 Subject: dma-buf: Restart reservation_object_get_fences_rcu() after writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be completely generic, we have to double check the read seqlock after acquiring a reference to the fence. If the driver is allocating fences from a SLAB_DESTROY_BY_RCU, or similar freelist, then within an RCU grace period a fence may be freed and reallocated. The RCU read side critical section does not prevent this reallocation, instead we have to inspect the reservation's seqlock to double check if the fences have been reassigned as we were acquiring our reference. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Christian König Cc: Alex Deucher Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-7-chris@chris-wilson.co.uk --- drivers/dma-buf/reservation.c | 71 +++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 723d8af988e5..ba3e25dab95b 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -280,18 +280,24 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, unsigned *pshared_count, struct fence ***pshared) { - unsigned shared_count = 0; - unsigned retry = 1; - struct fence **shared = NULL, *fence_excl = NULL; - int ret = 0; + struct fence **shared = NULL; + struct fence *fence_excl; + unsigned int shared_count; + int ret = 1; - while (retry) { + do { struct reservation_object_list *fobj; unsigned seq; + unsigned int i; - seq = read_seqcount_begin(&obj->seq); + shared_count = i = 0; rcu_read_lock(); + seq = read_seqcount_begin(&obj->seq); + + fence_excl = rcu_dereference(obj->fence_excl); + if (fence_excl && !fence_get_rcu(fence_excl)) + goto unlock; fobj = rcu_dereference(obj->fence); if (fobj) { @@ -309,52 +315,37 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, } ret = -ENOMEM; - shared_count = 0; break; } shared = nshared; - memcpy(shared, fobj->shared, sz); shared_count = fobj->shared_count; - } else - shared_count = 0; - fence_excl = rcu_dereference(obj->fence_excl); - - retry = read_seqcount_retry(&obj->seq, seq); - if (retry) - goto unlock; - - if (!fence_excl || fence_get_rcu(fence_excl)) { - unsigned i; for (i = 0; i < shared_count; ++i) { - if (fence_get_rcu(shared[i])) - continue; - - /* uh oh, refcount failed, abort and retry */ - while (i--) - fence_put(shared[i]); - - if (fence_excl) { - fence_put(fence_excl); - fence_excl = NULL; - } - - retry = 1; - break; + shared[i] = rcu_dereference(fobj->shared[i]); + if (!fence_get_rcu(shared[i])) + break; } - } else - retry = 1; + } + + if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) { + while (i--) + fence_put(shared[i]); + fence_put(fence_excl); + goto unlock; + } + ret = 0; unlock: rcu_read_unlock(); - } - *pshared_count = shared_count; - if (shared_count) - *pshared = shared; - else { - *pshared = NULL; + } while (ret); + + if (!shared_count) { kfree(shared); + shared = NULL; } + + *pshared_count = shared_count; + *pshared = shared; *pfence_excl = fence_excl; return ret; -- cgit v1.2.3 From 1cec20f0ea0e3bc617aed47e0936f17386c131f9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:31 +0100 Subject: dma-buf: Restart reservation_object_wait_timeout_rcu() after writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be completely generic, we have to double check the read seqlock after acquiring a reference to the fence. If the driver is allocating fences from a SLAB_DESTROY_BY_RCU, or similar freelist, then within an RCU grace period a fence may be freed and reallocated. The RCU read side critical section does not prevent this reallocation, instead we have to inspect the reservation's seqlock to double check if the fences have been reassigned as we were acquiring our reference. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Christian König Cc: Alex Deucher Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-8-chris@chris-wilson.co.uk --- drivers/dma-buf/reservation.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index ba3e25dab95b..648e5d0325f9 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -388,9 +388,6 @@ retry: if (fobj) shared_count = fobj->shared_count; - if (read_seqcount_retry(&obj->seq, seq)) - goto unlock_retry; - for (i = 0; i < shared_count; ++i) { struct fence *lfence = rcu_dereference(fobj->shared[i]); @@ -413,9 +410,6 @@ retry: if (!shared_count) { struct fence *fence_excl = rcu_dereference(obj->fence_excl); - if (read_seqcount_retry(&obj->seq, seq)) - goto unlock_retry; - if (fence_excl && !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) { if (!fence_get_rcu(fence_excl)) @@ -430,6 +424,11 @@ retry: rcu_read_unlock(); if (fence) { + if (read_seqcount_retry(&obj->seq, seq)) { + fence_put(fence); + goto retry; + } + ret = fence_wait_timeout(fence, intr, ret); fence_put(fence); if (ret > 0 && wait_all && (i + 1 < shared_count)) -- cgit v1.2.3 From b68d8379c28ddfe74b78be9414082f281332d86c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:32 +0100 Subject: dma-buf: Restart reservation_object_test_signaled_rcu() after writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be completely generic, we have to double check the read seqlock after acquiring a reference to the fence. If the driver is allocating fences from a SLAB_DESTROY_BY_RCU, or similar freelist, then within an RCU grace period a fence may be freed and reallocated. The RCU read side critical section does not prevent this reallocation, instead we have to inspect the reservation's seqlock to double check if the fences have been reassigned as we were acquiring our reference. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Christian König Cc: Alex Deucher Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-9-chris@chris-wilson.co.uk --- drivers/dma-buf/reservation.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 648e5d0325f9..82de59f7cbbd 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -474,12 +474,13 @@ bool reservation_object_test_signaled_rcu(struct reservation_object *obj, bool test_all) { unsigned seq, shared_count; - int ret = true; + int ret; + rcu_read_lock(); retry: + ret = true; shared_count = 0; seq = read_seqcount_begin(&obj->seq); - rcu_read_lock(); if (test_all) { unsigned i; @@ -490,46 +491,35 @@ retry: if (fobj) shared_count = fobj->shared_count; - if (read_seqcount_retry(&obj->seq, seq)) - goto unlock_retry; - for (i = 0; i < shared_count; ++i) { struct fence *fence = rcu_dereference(fobj->shared[i]); ret = reservation_object_test_signaled_single(fence); if (ret < 0) - goto unlock_retry; + goto retry; else if (!ret) break; } - /* - * There could be a read_seqcount_retry here, but nothing cares - * about whether it's the old or newer fence pointers that are - * signaled. That race could still have happened after checking - * read_seqcount_retry. If you care, use ww_mutex_lock. - */ + if (read_seqcount_retry(&obj->seq, seq)) + goto retry; } if (!shared_count) { struct fence *fence_excl = rcu_dereference(obj->fence_excl); - if (read_seqcount_retry(&obj->seq, seq)) - goto unlock_retry; - if (fence_excl) { ret = reservation_object_test_signaled_single( fence_excl); if (ret < 0) - goto unlock_retry; + goto retry; + + if (read_seqcount_retry(&obj->seq, seq)) + goto retry; } } rcu_read_unlock(); return ret; - -unlock_retry: - rcu_read_unlock(); - goto retry; } EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu); -- cgit v1.2.3 From 4676dc838b37ed8c6f3da4571cb4a04cbd604801 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 12:48:26 +0100 Subject: drm/i915: Use fence_write() from rpm resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During rpm resume we restore the fences, but we do not have the protection of struct_mutex. This rules out updating the activity tracking on the fences, and requires us to rely on the rpm as the serialisation barrier instead. [ 350.298052] [drm:intel_runtime_resume [i915]] Resuming device [ 350.308606] [ 350.310520] =============================== [ 350.315560] [ INFO: suspicious RCU usage. ] [ 350.320554] 4.8.0-rc8-bsw-rapl+ #3133 Tainted: G U W [ 350.327208] ------------------------------- [ 350.331977] ../drivers/gpu/drm/i915/i915_gem_request.h:371 suspicious rcu_dereference_protected() usage! [ 350.342619] [ 350.342619] other info that might help us debug this: [ 350.342619] [ 350.351593] [ 350.351593] rcu_scheduler_active = 1, debug_locks = 0 [ 350.358952] 3 locks held by Xorg/320: [ 350.363077] #0: (&dev->mode_config.mutex){+.+.+.}, at: [] drm_modeset_lock_all+0x3c/0xd0 [drm] [ 350.375162] #1: (crtc_ww_class_acquire){+.+.+.}, at: [] drm_modeset_lock_all+0x46/0xd0 [drm] [ 350.387022] #2: (crtc_ww_class_mutex){+.+.+.}, at: [] drm_modeset_lock+0x36/0x110 [drm] [ 350.398236] [ 350.398236] stack backtrace: [ 350.403196] CPU: 1 PID: 320 Comm: Xorg Tainted: G U W 4.8.0-rc8-bsw-rapl+ #3133 [ 350.412457] Hardware name: Intel Corporation CHERRYVIEW C0 PLATFORM/Braswell CRB, BIOS BRAS.X64.X088.R00.1510270350 10/27/2015 [ 350.425212] 0000000000000000 ffff8801680a78c8 ffffffff81332187 ffff88016c5c5000 [ 350.433611] 0000000000000001 ffff8801680a78f8 ffffffff810ca6da ffff88016cc8b0f0 [ 350.442012] ffff88016cc80000 ffff88016cc80000 ffff880177ad0000 ffff8801680a7948 [ 350.450409] Call Trace: [ 350.453165] [] dump_stack+0x67/0x90 [ 350.458931] [] lockdep_rcu_suspicious+0xea/0x120 [ 350.466002] [] fence_update+0xbd/0x670 [i915] [ 350.472766] [] i915_gem_restore_fences+0x52/0x70 [i915] [ 350.480496] [] vlv_resume_prepare+0x72/0x570 [i915] [ 350.487839] [] intel_runtime_resume+0x102/0x210 [i915] [ 350.495442] [] pci_pm_runtime_resume+0x7f/0xb0 [ 350.502274] [] ? pci_restore_standard_config+0x40/0x40 [ 350.509883] [] __rpm_callback+0x35/0x70 [ 350.516037] [] ? pci_restore_standard_config+0x40/0x40 [ 350.523646] [] rpm_callback+0x24/0x80 [ 350.529604] [] ? pci_restore_standard_config+0x40/0x40 [ 350.537212] [] rpm_resume+0x4ad/0x740 [ 350.543161] [] __pm_runtime_resume+0x51/0x80 [ 350.549824] [] intel_runtime_pm_get+0x28/0x90 [i915] [ 350.557265] [] intel_display_power_get+0x23/0x50 [i915] [ 350.565001] [] intel_atomic_commit_tail+0xdfd/0x10b0 [i915] [ 350.573106] [] ? drm_atomic_helper_swap_state+0x159/0x300 [drm_kms_helper] [ 350.582659] [] ? _raw_spin_unlock+0x31/0x50 [ 350.589205] [] ? drm_atomic_helper_swap_state+0x159/0x300 [drm_kms_helper] [ 350.598787] [] intel_atomic_commit+0x3b5/0x500 [i915] [ 350.606319] [] ? drm_atomic_set_crtc_for_connector+0xcc/0x100 [drm] [ 350.615209] [] drm_atomic_commit+0x49/0x50 [drm] [ 350.622242] [] drm_atomic_helper_set_config+0x88/0xc0 [drm_kms_helper] [ 350.631419] [] drm_mode_set_config_internal+0x6c/0x120 [drm] [ 350.639623] [] drm_mode_setcrtc+0x22c/0x4d0 [drm] [ 350.646760] [] drm_ioctl+0x209/0x460 [drm] [ 350.653217] [] ? drm_mode_getcrtc+0x150/0x150 [drm] [ 350.660536] [] ? __lock_is_held+0x4a/0x70 [ 350.666885] [] do_vfs_ioctl+0x93/0x6b0 [ 350.672939] [] ? __fget+0x113/0x200 [ 350.678797] [] ? __fget+0x5/0x200 [ 350.684361] [] SyS_ioctl+0x44/0x80 [ 350.690030] [] do_syscall_64+0x5b/0x120 [ 350.696184] [] entry_SYSCALL64_slow_path+0x25/0x25 Note we also have to remember the lesson from commit 4fc788f5ee3d ("drm/i915: Flush delayed fence releases after reset") where we have to flush any changes to the fence on restore. v2: Replace call to release user mmaps with an assertion that they have already been zapped. Fixes: 49ef5294cda2 ("drm/i915: Move fence tracking from object to vma") Reported-by: Ville Syrjälä Signed-off-by: Chris Wilson Cc: Ville Syrjälä Cc: Joonas Lahtinen Cc: Mika Kuoppala Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161012114827.17031-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_fence.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index 8df1fa7234e8..2c7ba0ee127c 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -290,6 +290,8 @@ i915_vma_put_fence(struct i915_vma *vma) { struct drm_i915_fence_reg *fence = vma->fence; + assert_rpm_wakelock_held(to_i915(vma->vm->dev)); + if (!fence) return 0; @@ -341,6 +343,8 @@ i915_vma_get_fence(struct i915_vma *vma) struct drm_i915_fence_reg *fence; struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL; + assert_rpm_wakelock_held(to_i915(vma->vm->dev)); + /* Just update our place in the LRU if our fence is getting reused. */ if (vma->fence) { fence = vma->fence; @@ -371,6 +375,12 @@ void i915_gem_restore_fences(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); int i; + /* Note that this may be called outside of struct_mutex, by + * runtime suspend/resume. The barrier we require is enforced by + * rpm itself - all access to fences/GTT are only within an rpm + * wakeref, and to acquire that wakeref you must pass through here. + */ + for (i = 0; i < dev_priv->num_fence_regs; i++) { struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; struct i915_vma *vma = reg->vma; @@ -379,10 +389,17 @@ void i915_gem_restore_fences(struct drm_device *dev) * Commit delayed tiling changes if we have an object still * attached to the fence, otherwise just clear the fence. */ - if (vma && !i915_gem_object_is_tiled(vma->obj)) + if (vma && !i915_gem_object_is_tiled(vma->obj)) { + GEM_BUG_ON(!reg->dirty); + GEM_BUG_ON(vma->obj->fault_mappable); + + list_move(®->link, &dev_priv->mm.fence_list); + vma->fence = NULL; vma = NULL; + } - fence_update(reg, vma); + fence_write(reg, vma); + reg->vma = vma; } } -- cgit v1.2.3 From 8baa1f04b9ed8afe8d2d9f3884b335b1bab984d0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 12:48:27 +0100 Subject: drm/i915: Update debugfs describe_obj() to show fault-mappable The current meaning of whether an object has a GGTT vma is very ill-defined (and note we don't check for any partials either), it just means that at some point it was in the GGTT but it may not be now. The information we really care about here is whether it is taking up precious mappable aperture space. This is the obj->fault_mappable flag. We have a redundant long form reprinting of this information, so remove that in favour of the compact flag. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161012114827.17031-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 358663e833d6..2e312e0f2670 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -107,7 +107,7 @@ static char get_tiling_flag(struct drm_i915_gem_object *obj) static char get_global_flag(struct drm_i915_gem_object *obj) { - return i915_gem_object_to_ggtt(obj, NULL) ? 'g' : ' '; + return obj->fault_mappable ? 'g' : ' '; } static char get_pin_mapped_flag(struct drm_i915_gem_object *obj) @@ -186,15 +186,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) } if (obj->stolen) seq_printf(m, " (stolen: %08llx)", obj->stolen->start); - if (obj->pin_display || obj->fault_mappable) { - char s[3], *t = s; - if (obj->pin_display) - *t++ = 'p'; - if (obj->fault_mappable) - *t++ = 'f'; - *t = '\0'; - seq_printf(m, " (%s mappable)", s); - } engine = i915_gem_active_get_engine(&obj->last_write, &dev_priv->drm.struct_mutex); -- cgit v1.2.3 From 45353ce59b3ec606e0a35386ac04210b1656e829 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Oct 2016 13:48:24 +0100 Subject: drm/i915: Treat a framebuffer reference as an active reference whilst shrinking Treat a framebuffer reference with the same priority as an active reference whilst shrinking. Framebuffers are likely to be reused and typically cost more to migrate to and from GPU memory (on LLC architectures we need to clflush), so defer the temptation to purge them during a kswapd run until we have run out of cheap buffers. Signed-off-by: Chris Wilson Reviewed-by: John Harrison Link: http://patchwork.freedesktop.org/patch/msgid/20161012124824.23521-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 1c237d02f30b..de25b6e0a101 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -182,8 +182,9 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, !is_vmalloc_addr(obj->mapping)) continue; - if ((flags & I915_SHRINK_ACTIVE) == 0 && - i915_gem_object_is_active(obj)) + if (!(flags & I915_SHRINK_ACTIVE) && + (i915_gem_object_is_active(obj) || + obj->framebuffer_references)) continue; if (!can_release_pages(obj)) -- cgit v1.2.3 From 024b6a63138c1e6988927f9a90b6b43b8d4fe6f5 Mon Sep 17 00:00:00 2001 From: Shyam Saini Date: Mon, 10 Oct 2016 04:37:16 +0530 Subject: gpu: drm: gma500: Use vma_pages() Replace explicit computation of vma page count by a call to vma_pages() Signed-off-by: Shyam Saini Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476054436-9378-1-git-send-email-mayhs11saini@gmail.com --- drivers/gpu/drm/gma500/framebuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 3a44e705db53..0fde8503607c 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -124,7 +124,7 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) unsigned long phys_addr = (unsigned long)dev_priv->stolen_base + psbfb->gtt->offset; - page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + page_num = vma_pages(vma); address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -- cgit v1.2.3 From 9c9a7f94840f50324c9abab547ad224272c822fa Mon Sep 17 00:00:00 2001 From: Jiang Biao Date: Tue, 11 Oct 2016 14:03:45 +0800 Subject: drm/gma500: remove useless comment Remove useless comment in framebuffer.c. Signed-off-by: Jiang Biao Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476165825-12137-1-git-send-email-jiang.biao2@zte.com.cn --- drivers/gpu/drm/gma500/framebuffer.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 0fde8503607c..aee2f9733457 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -298,7 +298,6 @@ static struct drm_framebuffer *psb_framebuffer_create * psbfb_alloc - allocate frame buffer memory * @dev: the DRM device * @aligned_size: space needed - * @force: fall back to GEM buffers if need be * * Allocate the frame buffer. In the usual case we get a GTT range that * is stolen memory backed and life is simple. If there isn't sufficient -- cgit v1.2.3 From 1550333c597a98fc1bb529167ecf22333a3b4b39 Mon Sep 17 00:00:00 2001 From: Jiang Biao Date: Wed, 12 Oct 2016 10:18:19 +0800 Subject: drm/gma500: add comments for new parameters Added comments for new parameters. Signed-off-by: Jiang Biao Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476238699-25820-1-git-send-email-jiang.biao2@zte.com.cn --- drivers/gpu/drm/gma500/gtt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 8f69225ce2b4..76aea2e7fb9d 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -76,6 +76,7 @@ static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) * psb_gtt_insert - put an object into the GTT * @dev: our DRM device * @r: our GTT range + * @resume: on resume * * Take our preallocated GTT range and insert the GEM object into * the GTT. This is protected via the gtt mutex which the caller @@ -321,6 +322,7 @@ out: * @len: length (bytes) of address space required * @name: resource name * @backed: resource should be backed by stolen pages + * @align: requested alignment * * Ask the kernel core to find us a suitable range of addresses * to use for a GTT mapping. -- cgit v1.2.3 From f7741aa75e76440f4e9ecfe512feebe9bce33ca8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 12 Oct 2016 09:22:27 +0300 Subject: drm/savage: dereferencing an error pointer A recent cleanup changed the kmalloc() + copy_from_user() to memdup_user() but the error handling wasn't updated so we might call kfree(-EFAULT) and crash. Fixes: a6e3918bcdb1 ('GPU-DRM-Savage: Use memdup_user() rather than duplicating') Signed-off-by: Dan Carpenter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161012062227.GU12841@mwanda --- drivers/gpu/drm/savage/savage_state.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c index 3dc0d8ff95ec..2db89bed52e8 100644 --- a/drivers/gpu/drm/savage/savage_state.c +++ b/drivers/gpu/drm/savage/savage_state.c @@ -1004,6 +1004,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ kvb_addr = memdup_user(cmdbuf->vb_addr, cmdbuf->vb_size); if (IS_ERR(kvb_addr)) { ret = PTR_ERR(kvb_addr); + kvb_addr = NULL; goto done; } cmdbuf->vb_addr = kvb_addr; -- cgit v1.2.3 From 1c777c5d1dcdf8fa0223fcff35fb387b5bb9517a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 12 Oct 2016 17:46:37 +0300 Subject: drm/i915/hsw: Fix GPU hang during resume from S3-devices state Currently resuming on HSW from S3 pm_test/devices state leads to an unrecoverable GPU hang. Resetting the GPU during suspend fixes this. For a full S3 cycle this change only means the reset happens earlier (before reaching S3). For S4 the reset will happen now both during the freeze and quiesce phases, which is a benefit since it will guarantee that the GPU is idle before creating and loading the hibernation image. Cc: Mika Kuoppala Cc: Chris Wilson Suggested-by: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1476283597-580-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 28 ++-------------------------- drivers/gpu/drm/i915/i915_gem.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 89d322215c84..e9b3bfcb347a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -532,32 +532,6 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { static void i915_gem_fini(struct drm_device *dev) { - struct drm_i915_private *dev_priv = to_i915(dev); - - /* - * Neither the BIOS, ourselves or any other kernel - * expects the system to be in execlists mode on startup, - * so we need to reset the GPU back to legacy mode. And the only - * known way to disable logical contexts is through a GPU reset. - * - * So in order to leave the system in a known default configuration, - * always reset the GPU upon unload. Afterwards we then clean up the - * GEM state tracking, flushing off the requests and leaving the - * system in a known idle state. - * - * Note that is of the upmost importance that the GPU is idle and - * all stray writes are flushed *before* we dismantle the backing - * storage for the pinned objects. - * - * However, since we are uncertain that reseting the GPU on older - * machines is a good idea, we don't - just in case it leaves the - * machine in an unusable condition. - */ - if (HAS_HW_CONTEXTS(dev)) { - int reset = intel_gpu_reset(dev_priv, ALL_ENGINES); - WARN_ON(reset && reset != -ENODEV); - } - mutex_lock(&dev->struct_mutex); i915_gem_cleanup_engines(dev); i915_gem_context_fini(dev); @@ -636,6 +610,8 @@ static int i915_load_modeset_init(struct drm_device *dev) return 0; cleanup_gem: + if (i915_gem_suspend(dev)) + DRM_ERROR("failed to idle hardware; continuing to unload!\n"); i915_gem_fini(dev); cleanup_irq: intel_guc_fini(dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fdd496e6c081..830df36ca14c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4273,6 +4273,30 @@ int i915_gem_suspend(struct drm_device *dev) */ WARN_ON(dev_priv->gt.awake); + /* + * Neither the BIOS, ourselves or any other kernel + * expects the system to be in execlists mode on startup, + * so we need to reset the GPU back to legacy mode. And the only + * known way to disable logical contexts is through a GPU reset. + * + * So in order to leave the system in a known default configuration, + * always reset the GPU upon unload and suspend. Afterwards we then + * clean up the GEM state tracking, flushing off the requests and + * leaving the system in a known idle state. + * + * Note that is of the upmost importance that the GPU is idle and + * all stray writes are flushed *before* we dismantle the backing + * storage for the pinned objects. + * + * However, since we are uncertain that resetting the GPU on older + * machines is a good idea, we don't - just in case it leaves the + * machine in an unusable condition. + */ + if (HAS_HW_CONTEXTS(dev)) { + int reset = intel_gpu_reset(dev_priv, ALL_ENGINES); + WARN_ON(reset && reset != -ENODEV); + } + return 0; err: -- cgit v1.2.3 From e227300c8395dffaa7614ce7c7666a82180ebc60 Mon Sep 17 00:00:00 2001 From: Purushottam Kushwaha Date: Wed, 12 Oct 2016 18:25:35 +0530 Subject: cfg80211: pass struct to interface combination check/iter Move the growing parameter list to a structure for the interface combination check and iteration functions in cfg80211 and mac80211 to make the code easier to understand. Signed-off-by: Purushottam Kushwaha [edit commit message] Signed-off-by: Johannes Berg --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 22 ++++++----- include/net/cfg80211.h | 46 +++++++++++----------- net/mac80211/util.c | 44 ++++++++++----------- net/wireless/util.c | 28 ++++++------- 4 files changed, 68 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index b777e1b2f87a..2295336355df 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -414,23 +414,24 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, struct brcmf_cfg80211_vif *vif, enum nl80211_iftype new_type) { - int iftype_num[NUM_NL80211_IFTYPES]; struct brcmf_cfg80211_vif *pos; bool check_combos = false; int ret = 0; + struct iface_combination_params params = { + .num_different_channels = 1, + }; - memset(&iftype_num[0], 0, sizeof(iftype_num)); list_for_each_entry(pos, &cfg->vif_list, list) if (pos == vif) { - iftype_num[new_type]++; + params.iftype_num[new_type]++; } else { /* concurrent interfaces so need check combinations */ check_combos = true; - iftype_num[pos->wdev.iftype]++; + params.iftype_num[pos->wdev.iftype]++; } if (check_combos) - ret = cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); + ret = cfg80211_check_combinations(cfg->wiphy, ¶ms); return ret; } @@ -438,15 +439,16 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg, enum nl80211_iftype new_type) { - int iftype_num[NUM_NL80211_IFTYPES]; struct brcmf_cfg80211_vif *pos; + struct iface_combination_params params = { + .num_different_channels = 1, + }; - memset(&iftype_num[0], 0, sizeof(iftype_num)); list_for_each_entry(pos, &cfg->vif_list, list) - iftype_num[pos->wdev.iftype]++; + params.iftype_num[pos->wdev.iftype]++; - iftype_num[new_type]++; - return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); + params.iftype_num[new_type]++; + return cfg80211_check_combinations(cfg->wiphy, ¶ms); } static void convert_key_from_CPU(struct brcmf_wsec_key *key, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index fe78f02a242e..ea108541e1e0 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -771,6 +771,26 @@ struct cfg80211_csa_settings { u8 count; }; +/** + * struct iface_combination_params - input parameters for interface combinations + * + * Used to pass interface combination parameters + * + * @num_different_channels: the number of different channels we want + * to use for verification + * @radar_detect: a bitmap where each bit corresponds to a channel + * width where radar detection is needed, as in the definition of + * &struct ieee80211_iface_combination.@radar_detect_widths + * @iftype_num: array with the number of interfaces of each interface + * type. The index is the interface type as specified in &enum + * nl80211_iftype. + */ +struct iface_combination_params { + int num_different_channels; + u8 radar_detect; + int iftype_num[NUM_NL80211_IFTYPES]; +}; + /** * enum station_parameters_apply_mask - station parameter values to apply * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) @@ -5575,36 +5595,20 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy); * cfg80211_check_combinations - check interface combinations * * @wiphy: the wiphy - * @num_different_channels: the number of different channels we want - * to use for verification - * @radar_detect: a bitmap where each bit corresponds to a channel - * width where radar detection is needed, as in the definition of - * &struct ieee80211_iface_combination.@radar_detect_widths - * @iftype_num: array with the numbers of interfaces of each interface - * type. The index is the interface type as specified in &enum - * nl80211_iftype. + * @params: the interface combinations parameter * * This function can be called by the driver to check whether a * combination of interfaces and their types are allowed according to * the interface combinations. */ int cfg80211_check_combinations(struct wiphy *wiphy, - const int num_different_channels, - const u8 radar_detect, - const int iftype_num[NUM_NL80211_IFTYPES]); + struct iface_combination_params *params); /** * cfg80211_iter_combinations - iterate over matching combinations * * @wiphy: the wiphy - * @num_different_channels: the number of different channels we want - * to use for verification - * @radar_detect: a bitmap where each bit corresponds to a channel - * width where radar detection is needed, as in the definition of - * &struct ieee80211_iface_combination.@radar_detect_widths - * @iftype_num: array with the numbers of interfaces of each interface - * type. The index is the interface type as specified in &enum - * nl80211_iftype. + * @params: the interface combinations parameter * @iter: function to call for each matching combination * @data: pointer to pass to iter function * @@ -5613,9 +5617,7 @@ int cfg80211_check_combinations(struct wiphy *wiphy, * purposes. */ int cfg80211_iter_combinations(struct wiphy *wiphy, - const int num_different_channels, - const u8 radar_detect, - const int iftype_num[NUM_NL80211_IFTYPES], + struct iface_combination_params *params, void (*iter)(const struct ieee80211_iface_combination *c, void *data), void *data); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 545c79a42a77..031273a61d27 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -3308,10 +3308,11 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee80211_sub_if_data *sdata_iter; enum nl80211_iftype iftype = sdata->wdev.iftype; - int num[NUM_NL80211_IFTYPES]; struct ieee80211_chanctx *ctx; - int num_different_channels = 0; int total = 1; + struct iface_combination_params params = { + .radar_detect = radar_detect, + }; lockdep_assert_held(&local->chanctx_mtx); @@ -3322,9 +3323,6 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, !chandef->chan)) return -EINVAL; - if (chandef) - num_different_channels = 1; - if (WARN_ON(iftype >= NUM_NL80211_IFTYPES)) return -EINVAL; @@ -3335,24 +3333,26 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, return 0; } - memset(num, 0, sizeof(num)); + if (chandef) + params.num_different_channels = 1; if (iftype != NL80211_IFTYPE_UNSPECIFIED) - num[iftype] = 1; + params.iftype_num[iftype] = 1; list_for_each_entry(ctx, &local->chanctx_list, list) { if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) continue; - radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); + params.radar_detect |= + ieee80211_chanctx_radar_detect(local, ctx); if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { - num_different_channels++; + params.num_different_channels++; continue; } if (chandef && chanmode == IEEE80211_CHANCTX_SHARED && cfg80211_chandef_compatible(chandef, &ctx->conf.def)) continue; - num_different_channels++; + params.num_different_channels++; } list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) { @@ -3365,16 +3365,14 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype)) continue; - num[wdev_iter->iftype]++; + params.iftype_num[wdev_iter->iftype]++; total++; } - if (total == 1 && !radar_detect) + if (total == 1 && !params.radar_detect) return 0; - return cfg80211_check_combinations(local->hw.wiphy, - num_different_channels, - radar_detect, num); + return cfg80211_check_combinations(local->hw.wiphy, ¶ms); } static void @@ -3390,12 +3388,10 @@ ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c, int ieee80211_max_num_channels(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; - int num[NUM_NL80211_IFTYPES] = {}; struct ieee80211_chanctx *ctx; - int num_different_channels = 0; - u8 radar_detect = 0; u32 max_num_different_channels = 1; int err; + struct iface_combination_params params = {0}; lockdep_assert_held(&local->chanctx_mtx); @@ -3403,17 +3399,17 @@ int ieee80211_max_num_channels(struct ieee80211_local *local) if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) continue; - num_different_channels++; + params.num_different_channels++; - radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); + params.radar_detect |= + ieee80211_chanctx_radar_detect(local, ctx); } list_for_each_entry_rcu(sdata, &local->interfaces, list) - num[sdata->wdev.iftype]++; + params.iftype_num[sdata->wdev.iftype]++; - err = cfg80211_iter_combinations(local->hw.wiphy, - num_different_channels, radar_detect, - num, ieee80211_iter_max_chans, + err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms, + ieee80211_iter_max_chans, &max_num_different_channels); if (err < 0) return err; diff --git a/net/wireless/util.c b/net/wireless/util.c index 8edce22d1b93..0d69b257793d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1580,9 +1580,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, } int cfg80211_iter_combinations(struct wiphy *wiphy, - const int num_different_channels, - const u8 radar_detect, - const int iftype_num[NUM_NL80211_IFTYPES], + struct iface_combination_params *params, void (*iter)(const struct ieee80211_iface_combination *c, void *data), void *data) @@ -1593,7 +1591,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, int num_interfaces = 0; u32 used_iftypes = 0; - if (radar_detect) { + if (params->radar_detect) { rcu_read_lock(); regdom = rcu_dereference(cfg80211_regdomain); if (regdom) @@ -1602,8 +1600,8 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, } for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { - num_interfaces += iftype_num[iftype]; - if (iftype_num[iftype] > 0 && + num_interfaces += params->iftype_num[iftype]; + if (params->iftype_num[iftype] > 0 && !(wiphy->software_iftypes & BIT(iftype))) used_iftypes |= BIT(iftype); } @@ -1617,7 +1615,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, if (num_interfaces > c->max_interfaces) continue; - if (num_different_channels > c->num_different_channels) + if (params->num_different_channels > c->num_different_channels) continue; limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, @@ -1632,16 +1630,17 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, all_iftypes |= limits[j].types; if (!(limits[j].types & BIT(iftype))) continue; - if (limits[j].max < iftype_num[iftype]) + if (limits[j].max < params->iftype_num[iftype]) goto cont; - limits[j].max -= iftype_num[iftype]; + limits[j].max -= params->iftype_num[iftype]; } } - if (radar_detect != (c->radar_detect_widths & radar_detect)) + if (params->radar_detect != + (c->radar_detect_widths & params->radar_detect)) goto cont; - if (radar_detect && c->radar_detect_regions && + if (params->radar_detect && c->radar_detect_regions && !(c->radar_detect_regions & BIT(region))) goto cont; @@ -1675,14 +1674,11 @@ cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c, } int cfg80211_check_combinations(struct wiphy *wiphy, - const int num_different_channels, - const u8 radar_detect, - const int iftype_num[NUM_NL80211_IFTYPES]) + struct iface_combination_params *params) { int err, num = 0; - err = cfg80211_iter_combinations(wiphy, num_different_channels, - radar_detect, iftype_num, + err = cfg80211_iter_combinations(wiphy, params, cfg80211_iter_sum_ifcombs, &num); if (err) return err; -- cgit v1.2.3 From 44a655cae3043453f9dd8076538712d52e2e0ce4 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:09:23 +0100 Subject: drm/i915: Shrink cxsr_latency_table unsigned long is too wide - use smaller types in struct cxsr_latency to save 800-something bytes of .rodata. v2: All data even fits in u16 for even more saving. (Ville Syrjala) v3: Move bitfields to the end of the struct. (Joonas Lahtinen) Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++-------- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f48e79ae2ac6..1663000023b9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -807,14 +807,14 @@ struct intel_watermark_params { }; struct cxsr_latency { - int is_desktop; - int is_ddr3; - unsigned long fsb_freq; - unsigned long mem_freq; - unsigned long display_sr; - unsigned long display_hpll_disable; - unsigned long cursor_sr; - unsigned long cursor_hpll_disable; + u16 fsb_freq; + u16 mem_freq; + u16 display_sr; + u16 display_hpll_disable; + u16 cursor_sr; + u16 cursor_hpll_disable; + bool is_desktop : 1; + bool is_ddr3 : 1; }; #define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fe6c1c61c388..6d1d4022dbdb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -252,8 +252,8 @@ static const struct cxsr_latency cxsr_latency_table[] = { {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */ }; -static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, - int is_ddr3, +static const struct cxsr_latency *intel_get_cxsr_latency(bool is_desktop, + bool is_ddr3, int fsb, int mem) { -- cgit v1.2.3 From 579627ea1897b7e05d43698db28a579af808000c Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:09:24 +0100 Subject: drm/i915: Shrink sdvo_cmd_names Pack the struct _sdvo_cmd_name to save 736 bytes of .rodata. This is fine since the name pointers are used only for debug. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index a061b0029797..9f352aac9526 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -307,7 +307,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) static const struct _sdvo_cmd_name { u8 cmd; const char *name; -} sdvo_cmd_names[] = { +} __attribute__ ((packed)) sdvo_cmd_names[] = { SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), -- cgit v1.2.3 From ae9400cab1bec3b3981b8fd7ae66c58ae5104551 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:09:25 +0100 Subject: drm/i915: Shrink per-platform watermark configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use types of more appropriate size in struct intel_watermark_params to save 512 bytes of .rodata. Signed-off-by: Tvrtko Ursulin Acked-by: Ville Syrjälä Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/intel_drv.h | 10 +++++----- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1663000023b9..07b93f23b8bf 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -799,11 +799,11 @@ struct intel_plane { }; struct intel_watermark_params { - unsigned long fifo_size; - unsigned long max_wm; - unsigned long default_wm; - unsigned long guard_size; - unsigned long cacheline_size; + u16 fifo_size; + u16 max_wm; + u8 default_wm; + u8 guard_size; + u8 cacheline_size; }; struct cxsr_latency { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6d1d4022dbdb..38081387802d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -775,13 +775,13 @@ static bool g4x_check_srwm(struct drm_device *dev, display_wm, cursor_wm); if (display_wm > display->max_wm) { - DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n", + DRM_DEBUG_KMS("display watermark is too large(%d/%u), disabling\n", display_wm, display->max_wm); return false; } if (cursor_wm > cursor->max_wm) { - DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n", + DRM_DEBUG_KMS("cursor watermark is too large(%d/%u), disabling\n", cursor_wm, cursor->max_wm); return false; } -- cgit v1.2.3 From db49296ba1e9140f507ab55424e7376d564a0504 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:09:26 +0100 Subject: drm/i915: Shrink TV modes const data Make struct video_levels and struct tv_mode use data types of sufficient width to save approximately one kilobyte in the .rodata section. v2: Do not align struct members. (Jani Nikula, Joonas Lahtinen) Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1476353366-13931-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_tv.c | 46 +++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 3988c45f9e5f..a0301a5dc249 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -86,7 +86,8 @@ struct intel_tv { }; struct video_levels { - int blank, black, burst; + u16 blank, black; + u8 burst; }; struct color_conversion { @@ -339,34 +340,43 @@ static const struct video_levels component_levels = { struct tv_mode { const char *name; - int clock; - int refresh; /* in millihertz (for precision) */ + + u32 clock; + u16 refresh; /* in millihertz (for precision) */ u32 oversample; - int hsync_end, hblank_start, hblank_end, htotal; - bool progressive, trilevel_sync, component_only; - int vsync_start_f1, vsync_start_f2, vsync_len; - bool veq_ena; - int veq_start_f1, veq_start_f2, veq_len; - int vi_end_f1, vi_end_f2, nbr_end; - bool burst_ena; - int hburst_start, hburst_len; - int vburst_start_f1, vburst_end_f1; - int vburst_start_f2, vburst_end_f2; - int vburst_start_f3, vburst_end_f3; - int vburst_start_f4, vburst_end_f4; + u8 hsync_end; + u16 hblank_start, hblank_end, htotal; + bool progressive : 1, trilevel_sync : 1, component_only : 1; + u8 vsync_start_f1, vsync_start_f2, vsync_len; + bool veq_ena : 1; + u8 veq_start_f1, veq_start_f2, veq_len; + u8 vi_end_f1, vi_end_f2; + u16 nbr_end; + bool burst_ena : 1; + u8 hburst_start, hburst_len; + u8 vburst_start_f1; + u16 vburst_end_f1; + u8 vburst_start_f2; + u16 vburst_end_f2; + u8 vburst_start_f3; + u16 vburst_end_f3; + u8 vburst_start_f4; + u16 vburst_end_f4; /* * subcarrier programming */ - int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc; + u16 dda2_size, dda3_size; + u8 dda1_inc; + u16 dda2_inc, dda3_inc; u32 sc_reset; - bool pal_burst; + bool pal_burst : 1; /* * blank/black levels */ const struct video_levels *composite_levels, *svideo_levels; const struct color_conversion *composite_color, *svideo_color; const u32 *filter_table; - int max_srcw; + u16 max_srcw; }; -- cgit v1.2.3 From 35ca039e0a45fad3b15834059b4ad6697dbc7484 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 13 Oct 2016 11:18:14 +0100 Subject: drm/i915: Record the current requests queue for execlists upon hang Mika wanted to know what requests were pending at the time of a hang as we now track which requests we have submitted to the hardware. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161013101815.26978-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_gpu_error.c | 64 ++++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bf397b643cc0..6360e807c6ba 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -832,10 +832,11 @@ struct drm_i915_error_state { struct drm_i915_error_request { long jiffies; pid_t pid; + u32 context; u32 seqno; u32 head; u32 tail; - } *requests; + } *requests, execlist[2]; struct drm_i915_error_waiter { char comm[TASK_COMM_LEN]; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 78cc13b9b2a5..026b78c66219 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -363,6 +363,20 @@ static void error_print_instdone(struct drm_i915_error_state_buf *m, ee->instdone.row[slice][subslice]); } +static void error_print_request(struct drm_i915_error_state_buf *m, + const char *prefix, + struct drm_i915_error_request *erq) +{ + if (!erq->seqno) + return; + + err_printf(m, "%s pid %d, seqno %8x:%08x, emitted %dms ago, head %08x, tail %08x\n", + prefix, erq->pid, + erq->context, erq->seqno, + jiffies_to_msecs(jiffies - erq->jiffies), + erq->head, erq->tail); +} + static void error_print_engine(struct drm_i915_error_state_buf *m, struct drm_i915_error_engine *ee) { @@ -434,6 +448,8 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, err_printf(m, " hangcheck: %s [%d]\n", hangcheck_action_to_str(ee->hangcheck_action), ee->hangcheck_score); + error_print_request(m, " ELSP[0]: ", &ee->execlist[0]); + error_print_request(m, " ELSP[1]: ", &ee->execlist[1]); } void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) @@ -649,14 +665,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, "%s --- %d requests\n", dev_priv->engine[i].name, ee->num_requests); - for (j = 0; j < ee->num_requests; j++) { - err_printf(m, " pid %d, seqno 0x%08x, emitted %ld, head 0x%08x, tail 0x%08x\n", - ee->requests[j].pid, - ee->requests[j].seqno, - ee->requests[j].jiffies, - ee->requests[j].head, - ee->requests[j].tail); - } + for (j = 0; j < ee->num_requests; j++) + error_print_request(m, " ", &ee->requests[j]); } if (IS_ERR(ee->waiters)) { @@ -1155,6 +1165,20 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, } } +static void record_request(struct drm_i915_gem_request *request, + struct drm_i915_error_request *erq) +{ + erq->context = request->ctx->hw_id; + erq->seqno = request->fence.seqno; + erq->jiffies = request->emitted_jiffies; + erq->head = request->head; + erq->tail = request->tail; + + rcu_read_lock(); + erq->pid = request->ctx->pid ? pid_nr(request->ctx->pid) : 0; + rcu_read_unlock(); +} + static void engine_record_requests(struct intel_engine_cs *engine, struct drm_i915_gem_request *first, struct drm_i915_error_engine *ee) @@ -1178,8 +1202,6 @@ static void engine_record_requests(struct intel_engine_cs *engine, count = 0; request = first; list_for_each_entry_from(request, &engine->request_list, link) { - struct drm_i915_error_request *erq; - if (count >= ee->num_requests) { /* * If the ring request list was changed in @@ -1199,19 +1221,22 @@ static void engine_record_requests(struct intel_engine_cs *engine, break; } - erq = &ee->requests[count++]; - erq->seqno = request->fence.seqno; - erq->jiffies = request->emitted_jiffies; - erq->head = request->head; - erq->tail = request->tail; - - rcu_read_lock(); - erq->pid = request->ctx->pid ? pid_nr(request->ctx->pid) : 0; - rcu_read_unlock(); + record_request(request, &ee->requests[count++]); } ee->num_requests = count; } +static void error_record_engine_execlists(struct intel_engine_cs *engine, + struct drm_i915_error_engine *ee) +{ + unsigned int n; + + for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) + if (engine->execlist_port[n].request) + record_request(engine->execlist_port[n].request, + &ee->execlist[n]); +} + static void i915_gem_record_rings(struct drm_i915_private *dev_priv, struct drm_i915_error_state *error) { @@ -1236,6 +1261,7 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv, error_record_engine_registers(error, engine, ee); error_record_engine_waiters(engine, ee); + error_record_engine_execlists(engine, ee); request = i915_gem_find_active_request(engine); if (request) { -- cgit v1.2.3 From 06392e3b21a20e66b668cd58d28f6b8ff920ef17 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 13 Oct 2016 11:18:15 +0100 Subject: drm/i915: Fix misplaced '\n' in printing the GPU error's RING_HEAD '\n' is supposed to be at the end of the line, not in the middle. Fixes: cdb324bde570 ("drm/i915: Show bounds of active request in the ring...") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20161013101815.26978-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 026b78c66219..cd38948107e7 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -382,7 +382,7 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, { err_printf(m, "%s command stream:\n", engine_str(ee->engine_id)); err_printf(m, " START: 0x%08x\n", ee->start); - err_printf(m, " HEAD: 0x%08x\n [0x%08x]", ee->head, ee->rq_head); + err_printf(m, " HEAD: 0x%08x [0x%08x]\n", ee->head, ee->rq_head); err_printf(m, " TAIL: 0x%08x [0x%08x, 0x%08x]\n", ee->tail, ee->rq_post, ee->rq_tail); err_printf(m, " CTL: 0x%08x\n", ee->ctl); -- cgit v1.2.3 From a52ad514fdf3b8a57ca4322c92d2d8d5c6182485 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 7 Oct 2016 22:04:34 -0400 Subject: net: deprecate eth_change_mtu, remove usage With centralized MTU checking, there's nothing productive done by eth_change_mtu that isn't already done in dev_set_mtu, so mark it as deprecated and remove all usage of it in the kernel. All callers have been audited for calls to alloc_etherdev* or ether_setup directly, which means they all have a valid dev->min_mtu and dev->max_mtu. Now eth_change_mtu prints out a netdev_warn about being deprecated, for the benefit of out-of-tree drivers that might be utilizing it. Of note, dvb_net.c actually had dev->mtu = 4096, while using eth_change_mtu, meaning that if you ever tried changing it's mtu, you couldn't set it above 1500 anymore. It's now getting dev->max_mtu also set to 4096 to remedy that. v2: fix up lantiq_etop, missed breakage due to drive not compiling on x86 CC: netdev@vger.kernel.org Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- arch/m68k/emu/nfeth.c | 1 - drivers/isdn/hysdn/hysdn_net.c | 1 - drivers/media/dvb-core/dvb_net.c | 2 +- drivers/net/appletalk/ipddp.c | 1 - drivers/net/cris/eth_v10.c | 1 - drivers/net/ethernet/3com/3c509.c | 1 - drivers/net/ethernet/3com/3c515.c | 1 - drivers/net/ethernet/3com/3c574_cs.c | 1 - drivers/net/ethernet/3com/3c589_cs.c | 1 - drivers/net/ethernet/3com/3c59x.c | 2 -- drivers/net/ethernet/3com/typhoon.c | 1 - drivers/net/ethernet/8390/8390.c | 1 - drivers/net/ethernet/8390/8390p.c | 1 - drivers/net/ethernet/8390/ax88796.c | 1 - drivers/net/ethernet/8390/axnet_cs.c | 1 - drivers/net/ethernet/8390/etherh.c | 1 - drivers/net/ethernet/8390/hydra.c | 1 - drivers/net/ethernet/8390/mac8390.c | 1 - drivers/net/ethernet/8390/mcf8390.c | 1 - drivers/net/ethernet/8390/ne2k-pci.c | 1 - drivers/net/ethernet/8390/pcnet_cs.c | 1 - drivers/net/ethernet/8390/smc-ultra.c | 1 - drivers/net/ethernet/8390/wd.c | 1 - drivers/net/ethernet/8390/zorro8390.c | 1 - drivers/net/ethernet/adaptec/starfire.c | 1 - drivers/net/ethernet/adi/bfin_mac.c | 1 - drivers/net/ethernet/allwinner/sun4i-emac.c | 1 - drivers/net/ethernet/amd/a2065.c | 1 - drivers/net/ethernet/amd/am79c961a.c | 1 - drivers/net/ethernet/amd/ariadne.c | 1 - drivers/net/ethernet/amd/atarilance.c | 1 - drivers/net/ethernet/amd/au1000_eth.c | 1 - drivers/net/ethernet/amd/declance.c | 1 - drivers/net/ethernet/amd/hplance.c | 1 - drivers/net/ethernet/amd/lance.c | 1 - drivers/net/ethernet/amd/mvme147.c | 1 - drivers/net/ethernet/amd/ni65.c | 1 - drivers/net/ethernet/amd/nmclan_cs.c | 1 - drivers/net/ethernet/amd/pcnet32.c | 1 - drivers/net/ethernet/amd/sun3lance.c | 1 - drivers/net/ethernet/amd/sunlance.c | 1 - drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 1 - drivers/net/ethernet/apple/bmac.c | 1 - drivers/net/ethernet/apple/mace.c | 1 - drivers/net/ethernet/apple/macmace.c | 1 - drivers/net/ethernet/aurora/nb8800.c | 1 - drivers/net/ethernet/cadence/macb.c | 1 - drivers/net/ethernet/cirrus/cs89x0.c | 1 - drivers/net/ethernet/cirrus/ep93xx_eth.c | 1 - drivers/net/ethernet/cirrus/mac89x0.c | 1 - drivers/net/ethernet/davicom/dm9000.c | 1 - drivers/net/ethernet/dec/tulip/de2104x.c | 1 - drivers/net/ethernet/dec/tulip/de4x5.c | 1 - drivers/net/ethernet/dec/tulip/dmfe.c | 1 - drivers/net/ethernet/dec/tulip/tulip_core.c | 1 - drivers/net/ethernet/dec/tulip/uli526x.c | 1 - drivers/net/ethernet/dec/tulip/winbond-840.c | 1 - drivers/net/ethernet/dec/tulip/xircom_cb.c | 1 - drivers/net/ethernet/dnet.c | 1 - drivers/net/ethernet/ec_bhf.c | 1 - drivers/net/ethernet/fealnx.c | 1 - drivers/net/ethernet/freescale/fec_main.c | 1 - drivers/net/ethernet/freescale/fec_mpc52xx.c | 1 - drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 1 - drivers/net/ethernet/freescale/ucc_geth.c | 1 - drivers/net/ethernet/fujitsu/fmvj18x_cs.c | 1 - drivers/net/ethernet/hisilicon/hip04_eth.c | 1 - drivers/net/ethernet/hisilicon/hisi_femac.c | 1 - drivers/net/ethernet/hp/hp100.c | 2 -- drivers/net/ethernet/i825xx/82596.c | 1 - drivers/net/ethernet/i825xx/ether1.c | 1 - drivers/net/ethernet/i825xx/lib82596.c | 1 - drivers/net/ethernet/i825xx/sun3_82586.c | 1 - drivers/net/ethernet/ibm/emac/core.c | 1 - drivers/net/ethernet/korina.c | 1 - drivers/net/ethernet/lantiq_etop.c | 18 ++++++++---------- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 - drivers/net/ethernet/micrel/ks8851.c | 1 - drivers/net/ethernet/micrel/ks8851_mll.c | 1 - drivers/net/ethernet/microchip/enc28j60.c | 1 - drivers/net/ethernet/moxa/moxart_ether.c | 1 - drivers/net/ethernet/natsemi/jazzsonic.c | 1 - drivers/net/ethernet/natsemi/macsonic.c | 1 - drivers/net/ethernet/natsemi/xtsonic.c | 1 - drivers/net/ethernet/netx-eth.c | 1 - drivers/net/ethernet/nuvoton/w90p910_ether.c | 1 - drivers/net/ethernet/nxp/lpc_eth.c | 1 - drivers/net/ethernet/packetengines/hamachi.c | 1 - drivers/net/ethernet/packetengines/yellowfin.c | 1 - drivers/net/ethernet/qlogic/qla3xxx.c | 1 - drivers/net/ethernet/rdc/r6040.c | 1 - drivers/net/ethernet/realtek/atp.c | 1 - drivers/net/ethernet/renesas/ravb_main.c | 1 - drivers/net/ethernet/renesas/sh_eth.c | 2 -- drivers/net/ethernet/seeq/ether3.c | 1 - drivers/net/ethernet/seeq/sgiseeq.c | 1 - drivers/net/ethernet/sgi/ioc3-eth.c | 1 - drivers/net/ethernet/sgi/meth.c | 1 - drivers/net/ethernet/silan/sc92031.c | 1 - drivers/net/ethernet/sis/sis190.c | 1 - drivers/net/ethernet/sis/sis900.c | 1 - drivers/net/ethernet/smsc/epic100.c | 1 - drivers/net/ethernet/smsc/smc911x.c | 1 - drivers/net/ethernet/smsc/smc9194.c | 1 - drivers/net/ethernet/smsc/smc91c92_cs.c | 1 - drivers/net/ethernet/smsc/smc91x.c | 1 - drivers/net/ethernet/smsc/smsc911x.c | 1 - drivers/net/ethernet/sun/sunbmac.c | 1 - drivers/net/ethernet/sun/sunhme.c | 1 - drivers/net/ethernet/sun/sunqe.c | 1 - drivers/net/ethernet/ti/cpmac.c | 1 - drivers/net/ethernet/ti/cpsw.c | 1 - drivers/net/ethernet/ti/tlan.c | 1 - drivers/net/ethernet/toshiba/tc35815.c | 1 - drivers/net/ethernet/tundra/tsi108_eth.c | 1 - drivers/net/ethernet/via/via-rhine.c | 1 - drivers/net/ethernet/wiznet/w5100.c | 1 - drivers/net/ethernet/wiznet/w5300.c | 1 - drivers/net/ethernet/xircom/xirc2ps_cs.c | 1 - drivers/net/ethernet/xscale/ixp4xx_eth.c | 1 - drivers/net/plip/plip.c | 1 - drivers/net/sb1000.c | 1 - drivers/net/usb/catc.c | 1 - drivers/net/usb/kaweth.c | 1 - drivers/net/usb/pegasus.c | 1 - drivers/net/usb/r8152.c | 3 ++- drivers/net/usb/rtl8150.c | 1 - drivers/net/wan/sbni.c | 1 - drivers/net/wireless/intersil/prism54/islpci_dev.c | 1 - drivers/net/wireless/mac80211_hwsim.c | 1 - drivers/net/wireless/marvell/libertas/main.c | 1 - drivers/net/wireless/ray_cs.c | 1 - drivers/net/wireless/wl3501_cs.c | 1 - drivers/net/wireless/zydas/zd1201.c | 1 - drivers/staging/rtl8188eu/os_dep/mon.c | 1 - drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 1 - drivers/staging/rtl8192u/r8192U_core.c | 1 - drivers/staging/slicoss/slicoss.c | 1 - include/uapi/linux/if_ether.h | 2 ++ net/atm/br2684.c | 2 -- net/bluetooth/bnep/netdev.c | 1 - net/ethernet/eth.c | 5 +++-- net/irda/irlan/irlan_eth.c | 1 - 143 files changed, 16 insertions(+), 156 deletions(-) (limited to 'drivers') diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c index a0985fd088d1..fc4be028c418 100644 --- a/arch/m68k/emu/nfeth.c +++ b/arch/m68k/emu/nfeth.c @@ -184,7 +184,6 @@ static const struct net_device_ops nfeth_netdev_ops = { .ndo_start_xmit = nfeth_xmit, .ndo_tx_timeout = nfeth_tx_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index 5609deee7cd3..b93a4e9a8d34 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -232,7 +232,6 @@ static const struct net_device_ops hysdn_netdev_ops = { .ndo_open = net_open, .ndo_stop = net_close, .ndo_start_xmit = net_send_packet, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index 9914f69a4a02..0da622f5fe69 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -1198,7 +1198,6 @@ static const struct net_device_ops dvb_netdev_ops = { .ndo_start_xmit = dvb_net_tx, .ndo_set_rx_mode = dvb_net_set_multicast_list, .ndo_set_mac_address = dvb_net_set_mac, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; @@ -1209,6 +1208,7 @@ static void dvb_net_setup(struct net_device *dev) dev->header_ops = &dvb_header_ops; dev->netdev_ops = &dvb_netdev_ops; dev->mtu = 4096; + dev->max_mtu = 4096; dev->flags |= IFF_NOARP; } diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c index e90c6a7333d7..31f89f1c6123 100644 --- a/drivers/net/appletalk/ipddp.c +++ b/drivers/net/appletalk/ipddp.c @@ -59,7 +59,6 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static const struct net_device_ops ipddp_netdev_ops = { .ndo_start_xmit = ipddp_xmit, .ndo_do_ioctl = ipddp_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index 221f5f011ff9..e128826aa117 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -264,7 +264,6 @@ static const struct net_device_ops e100_netdev_ops = { .ndo_do_ioctl = e100_ioctl, .ndo_set_mac_address = e100_set_mac_address, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_config = e100_set_config, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = e100_netpoll, diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index 91ada52f776b..9f9a5f440e2f 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -508,7 +508,6 @@ static const struct net_device_ops netdev_ops = { .ndo_get_stats = el3_get_stats, .ndo_set_rx_mode = set_multicast_list, .ndo_tx_timeout = el3_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c index b26e038b4a0e..b9f4c463e516 100644 --- a/drivers/net/ethernet/3com/3c515.c +++ b/drivers/net/ethernet/3com/3c515.c @@ -570,7 +570,6 @@ static const struct net_device_ops netdev_ops = { .ndo_tx_timeout = corkscrew_timeout, .ndo_get_stats = corkscrew_get_stats, .ndo_set_rx_mode = set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c index b88afd759307..9359a37fedc0 100644 --- a/drivers/net/ethernet/3com/3c574_cs.c +++ b/drivers/net/ethernet/3com/3c574_cs.c @@ -254,7 +254,6 @@ static const struct net_device_ops el3_netdev_ops = { .ndo_get_stats = el3_get_stats, .ndo_do_ioctl = el3_ioctl, .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c index 71396e4b87e3..e28254a00599 100644 --- a/drivers/net/ethernet/3com/3c589_cs.c +++ b/drivers/net/ethernet/3com/3c589_cs.c @@ -188,7 +188,6 @@ static const struct net_device_ops el3_netdev_ops = { .ndo_set_config = el3_config, .ndo_get_stats = el3_get_stats, .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 9133e7926da5..3ecf61382269 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -1062,7 +1062,6 @@ static const struct net_device_ops boomrang_netdev_ops = { .ndo_do_ioctl = vortex_ioctl, #endif .ndo_set_rx_mode = set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1080,7 +1079,6 @@ static const struct net_device_ops vortex_netdev_ops = { .ndo_do_ioctl = vortex_ioctl, #endif .ndo_set_rx_mode = set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c index 8f8418d2ac4a..506b507b4158 100644 --- a/drivers/net/ethernet/3com/typhoon.c +++ b/drivers/net/ethernet/3com/typhoon.c @@ -2255,7 +2255,6 @@ static const struct net_device_ops typhoon_netdev_ops = { .ndo_get_stats = typhoon_get_stats, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, }; static int diff --git a/drivers/net/ethernet/8390/8390.c b/drivers/net/ethernet/8390/8390.c index 5db1f55abef4..a43544af257b 100644 --- a/drivers/net/ethernet/8390/8390.c +++ b/drivers/net/ethernet/8390/8390.c @@ -64,7 +64,6 @@ const struct net_device_ops ei_netdev_ops = { .ndo_set_rx_mode = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, #endif diff --git a/drivers/net/ethernet/8390/8390p.c b/drivers/net/ethernet/8390/8390p.c index e8fc2e87e840..46d2257c4430 100644 --- a/drivers/net/ethernet/8390/8390p.c +++ b/drivers/net/ethernet/8390/8390p.c @@ -69,7 +69,6 @@ const struct net_device_ops eip_netdev_ops = { .ndo_set_rx_mode = eip_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = eip_poll, #endif diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index 39ca9350d1b2..b0a3b85fc6f8 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -536,7 +536,6 @@ static const struct net_device_ops ax_netdev_ops = { .ndo_set_rx_mode = ax_ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ax_ei_poll, #endif diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c index 4ea717d68c95..1d84a0544ace 100644 --- a/drivers/net/ethernet/8390/axnet_cs.c +++ b/drivers/net/ethernet/8390/axnet_cs.c @@ -134,7 +134,6 @@ static const struct net_device_ops axnet_netdev_ops = { .ndo_tx_timeout = axnet_tx_timeout, .ndo_get_stats = get_stats, .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c index d686b9cac29f..11cbf22ad201 100644 --- a/drivers/net/ethernet/8390/etherh.c +++ b/drivers/net/ethernet/8390/etherh.c @@ -654,7 +654,6 @@ static const struct net_device_ops etherh_netdev_ops = { .ndo_set_rx_mode = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = __ei_poll, #endif diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c index 0fe19d609c2e..8ae249195301 100644 --- a/drivers/net/ethernet/8390/hydra.c +++ b/drivers/net/ethernet/8390/hydra.c @@ -105,7 +105,6 @@ static const struct net_device_ops hydra_netdev_ops = { .ndo_set_rx_mode = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = __ei_poll, #endif diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c index b9283901136e..9497f18eaba0 100644 --- a/drivers/net/ethernet/8390/mac8390.c +++ b/drivers/net/ethernet/8390/mac8390.c @@ -483,7 +483,6 @@ static const struct net_device_ops mac8390_netdev_ops = { .ndo_set_rx_mode = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = __ei_poll, #endif diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c index e1c055574a11..4bb967bc879e 100644 --- a/drivers/net/ethernet/8390/mcf8390.c +++ b/drivers/net/ethernet/8390/mcf8390.c @@ -308,7 +308,6 @@ static const struct net_device_ops mcf8390_netdev_ops = { .ndo_set_rx_mode = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = __ei_poll, #endif diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c index 57e97910c728..07355302443d 100644 --- a/drivers/net/ethernet/8390/ne2k-pci.c +++ b/drivers/net/ethernet/8390/ne2k-pci.c @@ -209,7 +209,6 @@ static const struct net_device_ops ne2k_netdev_ops = { .ndo_set_rx_mode = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, #endif diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c index 2f79d29f17f2..63079a6e20d9 100644 --- a/drivers/net/ethernet/8390/pcnet_cs.c +++ b/drivers/net/ethernet/8390/pcnet_cs.c @@ -227,7 +227,6 @@ static const struct net_device_ops pcnet_netdev_ops = { .ndo_do_ioctl = ei_ioctl, .ndo_set_rx_mode = ei_set_multicast_list, .ndo_tx_timeout = ei_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/8390/smc-ultra.c b/drivers/net/ethernet/8390/smc-ultra.c index 139385dcdaa7..364b6514f65f 100644 --- a/drivers/net/ethernet/8390/smc-ultra.c +++ b/drivers/net/ethernet/8390/smc-ultra.c @@ -195,7 +195,6 @@ static const struct net_device_ops ultra_netdev_ops = { .ndo_set_rx_mode = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ultra_poll, #endif diff --git a/drivers/net/ethernet/8390/wd.c b/drivers/net/ethernet/8390/wd.c index dd7d816bde52..ad019cbc698f 100644 --- a/drivers/net/ethernet/8390/wd.c +++ b/drivers/net/ethernet/8390/wd.c @@ -156,7 +156,6 @@ static const struct net_device_ops wd_netdev_ops = { .ndo_set_rx_mode = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, #endif diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c index 8308728fad05..6d93956b293b 100644 --- a/drivers/net/ethernet/8390/zorro8390.c +++ b/drivers/net/ethernet/8390/zorro8390.c @@ -284,7 +284,6 @@ static const struct net_device_ops zorro8390_netdev_ops = { .ndo_set_rx_mode = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = __ei_poll, #endif diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index 8af2c88d5b33..4a9a16e25666 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -634,7 +634,6 @@ static const struct net_device_ops netdev_ops = { .ndo_get_stats = get_stats, .ndo_set_rx_mode = set_rx_mode, .ndo_do_ioctl = netdev_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef VLAN_SUPPORT diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index 00f9ee3fc3e5..88164529b52a 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c @@ -1571,7 +1571,6 @@ static const struct net_device_ops bfin_mac_netdev_ops = { .ndo_set_rx_mode = bfin_mac_set_multicast_list, .ndo_do_ioctl = bfin_mac_ioctl, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = bfin_mac_poll_controller, #endif diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 6ffdff68bfc4..af27f9dbedf2 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -773,7 +773,6 @@ static const struct net_device_ops emac_netdev_ops = { .ndo_tx_timeout = emac_timeout, .ndo_set_rx_mode = emac_set_rx_mode, .ndo_do_ioctl = emac_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = emac_set_mac_address, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index a83cd1c4ce1d..ee4b94e3cda9 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c @@ -665,7 +665,6 @@ static const struct net_device_ops lance_netdev_ops = { .ndo_tx_timeout = lance_tx_timeout, .ndo_set_rx_mode = lance_set_multicast, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c index fcdf5dda448f..b11e910850f7 100644 --- a/drivers/net/ethernet/amd/am79c961a.c +++ b/drivers/net/ethernet/amd/am79c961a.c @@ -663,7 +663,6 @@ static const struct net_device_ops am79c961_netdev_ops = { .ndo_set_rx_mode = am79c961_setmulticastlist, .ndo_tx_timeout = am79c961_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = am79c961_poll_controller, diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c index 968b7bfac8fc..5fd7b15b0574 100644 --- a/drivers/net/ethernet/amd/ariadne.c +++ b/drivers/net/ethernet/amd/ariadne.c @@ -706,7 +706,6 @@ static const struct net_device_ops ariadne_netdev_ops = { .ndo_get_stats = ariadne_get_stats, .ndo_set_rx_mode = set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c index d2bc8e5dcd23..e53ccc3b7d8d 100644 --- a/drivers/net/ethernet/amd/atarilance.c +++ b/drivers/net/ethernet/amd/atarilance.c @@ -460,7 +460,6 @@ static const struct net_device_ops lance_netdev_ops = { .ndo_set_mac_address = lance_set_mac_address, .ndo_tx_timeout = lance_tx_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static unsigned long __init lance_probe1( struct net_device *dev, diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index df664187cd82..a3c90fe5de00 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -1103,7 +1103,6 @@ static const struct net_device_ops au1000_netdev_ops = { .ndo_tx_timeout = au1000_tx_timeout, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static int au1000_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c index b799c7ac899b..76e5fc7adff5 100644 --- a/drivers/net/ethernet/amd/declance.c +++ b/drivers/net/ethernet/amd/declance.c @@ -1013,7 +1013,6 @@ static const struct net_device_ops lance_netdev_ops = { .ndo_start_xmit = lance_start_xmit, .ndo_tx_timeout = lance_tx_timeout, .ndo_set_rx_mode = lance_set_multicast, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/amd/hplance.c b/drivers/net/ethernet/amd/hplance.c index 6c9de117ffc6..c3dbf1c8a269 100644 --- a/drivers/net/ethernet/amd/hplance.c +++ b/drivers/net/ethernet/amd/hplance.c @@ -72,7 +72,6 @@ static const struct net_device_ops hplance_netdev_ops = { .ndo_stop = hplance_close, .ndo_start_xmit = lance_start_xmit, .ndo_set_rx_mode = lance_set_multicast, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c index abb1ba228b26..61a641f23149 100644 --- a/drivers/net/ethernet/amd/lance.c +++ b/drivers/net/ethernet/amd/lance.c @@ -461,7 +461,6 @@ static const struct net_device_ops lance_netdev_ops = { .ndo_get_stats = lance_get_stats, .ndo_set_rx_mode = set_multicast_list, .ndo_tx_timeout = lance_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/amd/mvme147.c b/drivers/net/ethernet/amd/mvme147.c index 0660ac5846bb..0a920448522f 100644 --- a/drivers/net/ethernet/amd/mvme147.c +++ b/drivers/net/ethernet/amd/mvme147.c @@ -62,7 +62,6 @@ static const struct net_device_ops lance_netdev_ops = { .ndo_start_xmit = lance_start_xmit, .ndo_set_rx_mode = lance_set_multicast, .ndo_tx_timeout = lance_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c index cda53db75f17..5985bf220a8d 100644 --- a/drivers/net/ethernet/amd/ni65.c +++ b/drivers/net/ethernet/amd/ni65.c @@ -407,7 +407,6 @@ static const struct net_device_ops ni65_netdev_ops = { .ndo_start_xmit = ni65_send_packet, .ndo_tx_timeout = ni65_timeout, .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c index 2807e181647b..113a3b3cc50c 100644 --- a/drivers/net/ethernet/amd/nmclan_cs.c +++ b/drivers/net/ethernet/amd/nmclan_cs.c @@ -427,7 +427,6 @@ static const struct net_device_ops mace_netdev_ops = { .ndo_set_config = mace_config, .ndo_get_stats = mace_get_stats, .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index c22bf52d3320..adc7ab99a2f6 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -1527,7 +1527,6 @@ static const struct net_device_ops pcnet32_netdev_ops = { .ndo_get_stats = pcnet32_get_stats, .ndo_set_rx_mode = pcnet32_set_multicast_list, .ndo_do_ioctl = pcnet32_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c index 3d8c6b2cdea4..12bb4f1489fc 100644 --- a/drivers/net/ethernet/amd/sun3lance.c +++ b/drivers/net/ethernet/amd/sun3lance.c @@ -299,7 +299,6 @@ static const struct net_device_ops lance_netdev_ops = { .ndo_start_xmit = lance_start_xmit, .ndo_set_rx_mode = set_multicast_list, .ndo_set_mac_address = NULL, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index 9b56b40259dc..291ca5187f12 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c @@ -1294,7 +1294,6 @@ static const struct net_device_ops sparc_lance_ops = { .ndo_start_xmit = lance_start_xmit, .ndo_set_rx_mode = lance_set_multicast, .ndo_tx_timeout = lance_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index f75d9556152f..3fc7b0db952b 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1252,7 +1252,6 @@ static const struct net_device_ops xgene_ndev_ops = { .ndo_start_xmit = xgene_enet_start_xmit, .ndo_tx_timeout = xgene_enet_timeout, .ndo_get_stats64 = xgene_enet_get_stats64, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = xgene_enet_set_mac_address, }; diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index a65d7a60f116..2b2d87089987 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -1237,7 +1237,6 @@ static const struct net_device_ops bmac_netdev_ops = { .ndo_start_xmit = bmac_output, .ndo_set_rx_mode = bmac_set_multicast, .ndo_set_mac_address = bmac_set_address, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c index e58a7c73766e..96dd5300e0e5 100644 --- a/drivers/net/ethernet/apple/mace.c +++ b/drivers/net/ethernet/apple/mace.c @@ -102,7 +102,6 @@ static const struct net_device_ops mace_netdev_ops = { .ndo_start_xmit = mace_xmit_start, .ndo_set_rx_mode = mace_set_multicast, .ndo_set_mac_address = mace_set_address, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c index 89914ca17a49..857df9c45f04 100644 --- a/drivers/net/ethernet/apple/macmace.c +++ b/drivers/net/ethernet/apple/macmace.c @@ -186,7 +186,6 @@ static const struct net_device_ops mace_netdev_ops = { .ndo_tx_timeout = mace_tx_timeout, .ndo_set_rx_mode = mace_set_multicast, .ndo_set_mac_address = mace_set_address, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c index b047fd607b83..453dc0967125 100644 --- a/drivers/net/ethernet/aurora/nb8800.c +++ b/drivers/net/ethernet/aurora/nb8800.c @@ -1032,7 +1032,6 @@ static const struct net_device_ops nb8800_netdev_ops = { .ndo_set_mac_address = nb8800_set_mac_address, .ndo_set_rx_mode = nb8800_set_rx_mode, .ndo_do_ioctl = nb8800_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index b32444a3ed79..20e72044b765 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -2793,7 +2793,6 @@ static const struct net_device_ops at91ether_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = macb_ioctl, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = at91ether_poll_controller, #endif diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index c363b58552e9..3647b28e8de0 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -1266,7 +1266,6 @@ static const struct net_device_ops net_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = net_poll_controller, #endif - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c index de9f7c97d916..9119af088821 100644 --- a/drivers/net/ethernet/cirrus/ep93xx_eth.c +++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c @@ -749,7 +749,6 @@ static const struct net_device_ops ep93xx_netdev_ops = { .ndo_start_xmit = ep93xx_xmit, .ndo_do_ioctl = ep93xx_ioctl, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c index 07719676c305..b600fbbbf679 100644 --- a/drivers/net/ethernet/cirrus/mac89x0.c +++ b/drivers/net/ethernet/cirrus/mac89x0.c @@ -172,7 +172,6 @@ static const struct net_device_ops mac89x0_netdev_ops = { .ndo_set_rx_mode = set_multicast_list, .ndo_set_mac_address = set_mac_address, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; /* Probe for the CS8900 card in slot E. We won't bother looking diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index f45385f5c6e5..f1a81c52afe3 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1382,7 +1382,6 @@ static const struct net_device_ops dm9000_netdev_ops = { .ndo_tx_timeout = dm9000_timeout, .ndo_set_rx_mode = dm9000_hash_table, .ndo_do_ioctl = dm9000_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_features = dm9000_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index cadcee645f74..90c573b8ccaf 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c @@ -1956,7 +1956,6 @@ static const struct net_device_ops de_netdev_ops = { .ndo_start_xmit = de_start_xmit, .ndo_get_stats = de_get_stats, .ndo_tx_timeout = de_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 6620fc861c47..51fda3a6b13f 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -1085,7 +1085,6 @@ static const struct net_device_ops de4x5_netdev_ops = { .ndo_get_stats = de4x5_get_stats, .ndo_set_rx_mode = set_multicast_list, .ndo_do_ioctl = de4x5_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address= eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c index 8ed0fd8b1dda..df4994919456 100644 --- a/drivers/net/ethernet/dec/tulip/dmfe.c +++ b/drivers/net/ethernet/dec/tulip/dmfe.c @@ -352,7 +352,6 @@ static const struct net_device_ops netdev_ops = { .ndo_stop = dmfe_stop, .ndo_start_xmit = dmfe_start_xmit, .ndo_set_rx_mode = dmfe_set_filter_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index bbde90bc74fe..5f1377449b8f 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -1282,7 +1282,6 @@ static const struct net_device_ops tulip_netdev_ops = { .ndo_get_stats = tulip_get_stats, .ndo_do_ioctl = private_ioctl, .ndo_set_rx_mode = set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c index e750b5ddc0fb..e1c4133b8787 100644 --- a/drivers/net/ethernet/dec/tulip/uli526x.c +++ b/drivers/net/ethernet/dec/tulip/uli526x.c @@ -269,7 +269,6 @@ static const struct net_device_ops netdev_ops = { .ndo_stop = uli526x_stop, .ndo_start_xmit = uli526x_start_xmit, .ndo_set_rx_mode = uli526x_set_filter_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c index 1f62b9423851..feda96d585e7 100644 --- a/drivers/net/ethernet/dec/tulip/winbond-840.c +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c @@ -353,7 +353,6 @@ static const struct net_device_ops netdev_ops = { .ndo_set_rx_mode = set_rx_mode, .ndo_do_ioctl = netdev_ioctl, .ndo_tx_timeout = tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c index 0e721cedfa67..19e4ea15b504 100644 --- a/drivers/net/ethernet/dec/tulip/xircom_cb.c +++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c @@ -174,7 +174,6 @@ static const struct net_device_ops netdev_ops = { .ndo_open = xircom_open, .ndo_stop = xircom_close, .ndo_start_xmit = xircom_start_xmit, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c index c3b64cdd0dec..2a17c59f69f9 100644 --- a/drivers/net/ethernet/dnet.c +++ b/drivers/net/ethernet/dnet.c @@ -767,7 +767,6 @@ static const struct net_device_ops dnet_netdev_ops = { .ndo_do_ioctl = dnet_ioctl, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static int dnet_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c index f7b42483921c..57650953ff83 100644 --- a/drivers/net/ethernet/ec_bhf.c +++ b/drivers/net/ethernet/ec_bhf.c @@ -482,7 +482,6 @@ static const struct net_device_ops ec_bhf_netdev_ops = { .ndo_open = ec_bhf_open, .ndo_stop = ec_bhf_stop, .ndo_get_stats64 = ec_bhf_get_stats, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr }; diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index c08bd763172a..6967b287b6e7 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c @@ -472,7 +472,6 @@ static const struct net_device_ops netdev_ops = { .ndo_set_rx_mode = set_rx_mode, .ndo_do_ioctl = mii_ioctl, .ndo_tx_timeout = fealnx_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 48a033e64423..4ce8179aa4ff 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3055,7 +3055,6 @@ static const struct net_device_ops fec_netdev_ops = { .ndo_stop = fec_enet_close, .ndo_start_xmit = fec_enet_start_xmit, .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = fec_timeout, .ndo_set_mac_address = fec_set_mac_address, diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 446ae9d60c71..aa8cf5d2a53c 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -802,7 +802,6 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = { .ndo_set_mac_address = mpc52xx_fec_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = mpc52xx_fec_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_tx_timeout = mpc52xx_fec_tx_timeout, .ndo_get_stats = mpc52xx_fec_get_stats, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index dc120c148d97..925d1bca6a26 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -912,7 +912,6 @@ static const struct net_device_ops fs_enet_netdev_ops = { .ndo_do_ioctl = fs_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = fs_enet_netpoll, #endif diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 186ef8f16c80..786182480a73 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -3681,7 +3681,6 @@ static const struct net_device_ops ucc_geth_netdev_ops = { .ndo_start_xmit = ucc_geth_start_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = ucc_geth_set_mac_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_rx_mode = ucc_geth_set_multi, .ndo_tx_timeout = ucc_geth_timeout, .ndo_do_ioctl = ucc_geth_ioctl, diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c index 399cfd217288..51c4abc51bf4 100644 --- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c +++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c @@ -225,7 +225,6 @@ static const struct net_device_ops fjn_netdev_ops = { .ndo_tx_timeout = fjn_tx_timeout, .ndo_set_config = fjn_config, .ndo_set_rx_mode = set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index 39778892b3b3..3c99ca420f57 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -769,7 +769,6 @@ static const struct net_device_ops hip04_netdev_ops = { .ndo_set_mac_address = hip04_set_mac_address, .ndo_tx_timeout = hip04_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static int hip04_alloc_ring(struct net_device *ndev, struct device *d) diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c index ced185962ef8..49863068c59e 100644 --- a/drivers/net/ethernet/hisilicon/hisi_femac.c +++ b/drivers/net/ethernet/hisilicon/hisi_femac.c @@ -712,7 +712,6 @@ static const struct net_device_ops hisi_femac_netdev_ops = { .ndo_do_ioctl = hisi_femac_net_ioctl, .ndo_set_mac_address = hisi_femac_set_mac_address, .ndo_set_rx_mode = hisi_femac_net_set_rx_mode, - .ndo_change_mtu = eth_change_mtu, }; static void hisi_femac_core_reset(struct hisi_femac_priv *priv) diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c index 631dbc7b4dbb..1a31bee6e728 100644 --- a/drivers/net/ethernet/hp/hp100.c +++ b/drivers/net/ethernet/hp/hp100.c @@ -427,7 +427,6 @@ static const struct net_device_ops hp100_bm_netdev_ops = { .ndo_start_xmit = hp100_start_xmit_bm, .ndo_get_stats = hp100_get_stats, .ndo_set_rx_mode = hp100_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; @@ -438,7 +437,6 @@ static const struct net_device_ops hp100_netdev_ops = { .ndo_start_xmit = hp100_start_xmit, .ndo_get_stats = hp100_get_stats, .ndo_set_rx_mode = hp100_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c index ce235b776793..945883842533 100644 --- a/drivers/net/ethernet/i825xx/82596.c +++ b/drivers/net/ethernet/i825xx/82596.c @@ -1118,7 +1118,6 @@ static const struct net_device_ops i596_netdev_ops = { .ndo_start_xmit = i596_start_xmit, .ndo_set_rx_mode = set_multicast_list, .ndo_tx_timeout = i596_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c index 5d353c660068..dc983450354b 100644 --- a/drivers/net/ethernet/i825xx/ether1.c +++ b/drivers/net/ethernet/i825xx/ether1.c @@ -981,7 +981,6 @@ static const struct net_device_ops ether1_netdev_ops = { .ndo_set_rx_mode = ether1_setmulticastlist, .ndo_tx_timeout = ether1_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c index 3dbc53c21baa..e86773325cbe 100644 --- a/drivers/net/ethernet/i825xx/lib82596.c +++ b/drivers/net/ethernet/i825xx/lib82596.c @@ -1037,7 +1037,6 @@ static const struct net_device_ops i596_netdev_ops = { .ndo_start_xmit = i596_start_xmit, .ndo_set_rx_mode = set_multicast_list, .ndo_tx_timeout = i596_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c index 21c84cc9c871..8bb15a8c2a40 100644 --- a/drivers/net/ethernet/i825xx/sun3_82586.c +++ b/drivers/net/ethernet/i825xx/sun3_82586.c @@ -337,7 +337,6 @@ static const struct net_device_ops sun3_82586_netdev_ops = { .ndo_get_stats = sun3_82586_get_stats, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, }; static int __init sun3_82586_probe1(struct net_device *dev,int ioaddr) diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 8f139197f1aa..5d804a544674 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -2718,7 +2718,6 @@ static const struct net_device_ops emac_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = emac_set_mac_address, .ndo_start_xmit = emac_start_xmit, - .ndo_change_mtu = eth_change_mtu, }; static const struct net_device_ops emac_gige_netdev_ops = { diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 1799fe1415df..cbeea915f026 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1085,7 +1085,6 @@ static const struct net_device_ops korina_netdev_ops = { .ndo_set_rx_mode = korina_multicast_list, .ndo_tx_timeout = korina_tx_timeout, .ndo_do_ioctl = korina_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 91e09d68b7e2..1a739d71f1c2 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -519,18 +519,16 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev) static int ltq_etop_change_mtu(struct net_device *dev, int new_mtu) { - int ret = eth_change_mtu(dev, new_mtu); + struct ltq_etop_priv *priv = netdev_priv(dev); + unsigned long flags; - if (!ret) { - struct ltq_etop_priv *priv = netdev_priv(dev); - unsigned long flags; + dev->mtu = new_mtu; - spin_lock_irqsave(&priv->lock, flags); - ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu, - LTQ_ETOP_IGPLEN); - spin_unlock_irqrestore(&priv->lock, flags); - } - return ret; + spin_lock_irqsave(&priv->lock, flags); + ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu, LTQ_ETOP_IGPLEN); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; } static int diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 4a62ffd7729d..8f80e618ae59 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -2243,7 +2243,6 @@ static const struct net_device_ops mtk_netdev_ops = { .ndo_set_mac_address = mtk_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = mtk_do_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_tx_timeout = mtk_tx_timeout, .ndo_get_stats64 = mtk_get_stats64, .ndo_fix_features = mtk_fix_features, diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 1edc973df4c4..e7e1aff40bd9 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -1063,7 +1063,6 @@ static const struct net_device_ops ks8851_netdev_ops = { .ndo_start_xmit = ks8851_start_xmit, .ndo_set_mac_address = ks8851_set_mac_address, .ndo_set_rx_mode = ks8851_set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index 2fc5cd56c0a8..db628078a4e6 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -1285,7 +1285,6 @@ static const struct net_device_ops ks_netdev_ops = { .ndo_start_xmit = ks_start_xmit, .ndo_set_mac_address = ks_set_mac_address, .ndo_set_rx_mode = ks_set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index 0a26b11ca8f6..045b9106c0ff 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -1544,7 +1544,6 @@ static const struct net_device_ops enc28j60_netdev_ops = { .ndo_set_rx_mode = enc28j60_set_multicast_list, .ndo_set_mac_address = enc28j60_set_mac_address, .ndo_tx_timeout = enc28j60_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index 4367dd6879a2..9774b50cff6e 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -444,7 +444,6 @@ static struct net_device_ops moxart_netdev_ops = { .ndo_set_rx_mode = moxart_mac_set_rx_mode, .ndo_set_mac_address = moxart_set_mac_address, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static int moxart_mac_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c index acf3f11e38cc..a6caeb567c0d 100644 --- a/drivers/net/ethernet/natsemi/jazzsonic.c +++ b/drivers/net/ethernet/natsemi/jazzsonic.c @@ -110,7 +110,6 @@ static const struct net_device_ops sonic_netdev_ops = { .ndo_get_stats = sonic_get_stats, .ndo_set_rx_mode = sonic_multicast_list, .ndo_tx_timeout = sonic_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index d98f5b8a1c66..3ca6ae7caf55 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -190,7 +190,6 @@ static const struct net_device_ops macsonic_netdev_ops = { .ndo_tx_timeout = sonic_tx_timeout, .ndo_get_stats = sonic_get_stats, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c index 7007d212f3e4..9ee0f69a83c0 100644 --- a/drivers/net/ethernet/natsemi/xtsonic.c +++ b/drivers/net/ethernet/natsemi/xtsonic.c @@ -124,7 +124,6 @@ static const struct net_device_ops xtsonic_netdev_ops = { .ndo_set_rx_mode = sonic_multicast_list, .ndo_tx_timeout = sonic_tx_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c index adbc47f2d132..df4188cb43e0 100644 --- a/drivers/net/ethernet/netx-eth.c +++ b/drivers/net/ethernet/netx-eth.c @@ -304,7 +304,6 @@ static const struct net_device_ops netx_eth_netdev_ops = { .ndo_start_xmit = netx_eth_hard_start_xmit, .ndo_tx_timeout = netx_eth_timeout, .ndo_set_rx_mode = netx_eth_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index 712d8bcb7d8c..119f6dca71f0 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c @@ -915,7 +915,6 @@ static const struct net_device_ops w90p910_ether_netdev_ops = { .ndo_set_mac_address = w90p910_set_mac_address, .ndo_do_ioctl = w90p910_ether_ioctl, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static void __init get_mac_address(struct net_device *dev) diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 8e13ec84c538..dd6b0d0f7fa5 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1256,7 +1256,6 @@ static const struct net_device_ops lpc_netdev_ops = { .ndo_do_ioctl = lpc_eth_ioctl, .ndo_set_mac_address = lpc_set_mac_address, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static int lpc_eth_drv_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c index 91be2f02ef1c..2d04679a923a 100644 --- a/drivers/net/ethernet/packetengines/hamachi.c +++ b/drivers/net/ethernet/packetengines/hamachi.c @@ -568,7 +568,6 @@ static const struct net_device_ops hamachi_netdev_ops = { .ndo_start_xmit = hamachi_start_xmit, .ndo_get_stats = hamachi_get_stats, .ndo_set_rx_mode = set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_tx_timeout = hamachi_tx_timeout, diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c index fb1d1031b091..2a2ca5fa0c69 100644 --- a/drivers/net/ethernet/packetengines/yellowfin.c +++ b/drivers/net/ethernet/packetengines/yellowfin.c @@ -360,7 +360,6 @@ static const struct net_device_ops netdev_ops = { .ndo_stop = yellowfin_close, .ndo_start_xmit = yellowfin_start_xmit, .ndo_set_rx_mode = set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = netdev_ioctl, diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index b09a6b80d107..5c100ab86c00 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -3755,7 +3755,6 @@ static const struct net_device_ops ql3xxx_netdev_ops = { .ndo_open = ql3xxx_open, .ndo_start_xmit = ql3xxx_send, .ndo_stop = ql3xxx_close, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = ql3xxx_set_mac_address, .ndo_tx_timeout = ql3xxx_tx_timeout, diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c index 5ef5d728c250..4ff4e0491406 100644 --- a/drivers/net/ethernet/rdc/r6040.c +++ b/drivers/net/ethernet/rdc/r6040.c @@ -969,7 +969,6 @@ static const struct net_device_ops r6040_netdev_ops = { .ndo_start_xmit = r6040_start_xmit, .ndo_get_stats = r6040_get_stats, .ndo_set_rx_mode = r6040_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = r6040_ioctl, diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c index 5cb96785fb63..570ed3bd3cbf 100644 --- a/drivers/net/ethernet/realtek/atp.c +++ b/drivers/net/ethernet/realtek/atp.c @@ -245,7 +245,6 @@ static const struct net_device_ops atp_netdev_ops = { .ndo_start_xmit = atp_send_packet, .ndo_set_rx_mode = set_rx_mode, .ndo_tx_timeout = tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 630536bc72f9..27cfec3154c8 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1780,7 +1780,6 @@ static const struct net_device_ops ravb_netdev_ops = { .ndo_do_ioctl = ravb_do_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, }; /* MDIO bus init function */ diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 05b0dc55de77..e443695c2757 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2914,7 +2914,6 @@ static const struct net_device_ops sh_eth_netdev_ops = { .ndo_do_ioctl = sh_eth_do_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, }; static const struct net_device_ops sh_eth_netdev_ops_tsu = { @@ -2929,7 +2928,6 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = { .ndo_do_ioctl = sh_eth_do_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, }; #ifdef CONFIG_OF diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c index bdac936a68bc..244c1e171017 100644 --- a/drivers/net/ethernet/seeq/ether3.c +++ b/drivers/net/ethernet/seeq/ether3.c @@ -745,7 +745,6 @@ static const struct net_device_ops ether3_netdev_ops = { .ndo_set_rx_mode = ether3_setmulticastlist, .ndo_tx_timeout = ether3_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c index c2bd5378ffda..ed34196028b8 100644 --- a/drivers/net/ethernet/seeq/sgiseeq.c +++ b/drivers/net/ethernet/seeq/sgiseeq.c @@ -714,7 +714,6 @@ static const struct net_device_ops sgiseeq_netdev_ops = { .ndo_tx_timeout = timeout, .ndo_set_rx_mode = sgiseeq_set_multicast, .ndo_set_mac_address = sgiseeq_set_mac_address, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 7a254da85dd7..42051ab98cf0 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -1225,7 +1225,6 @@ static const struct net_device_ops ioc3_netdev_ops = { .ndo_do_ioctl = ioc3_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = ioc3_set_mac_address, - .ndo_change_mtu = eth_change_mtu, }; static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c index aaa80f13859b..69d2d30e5ef1 100644 --- a/drivers/net/ethernet/sgi/meth.c +++ b/drivers/net/ethernet/sgi/meth.c @@ -815,7 +815,6 @@ static const struct net_device_ops meth_netdev_ops = { .ndo_start_xmit = meth_tx, .ndo_do_ioctl = meth_ioctl, .ndo_tx_timeout = meth_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_set_rx_mode = meth_set_rx_mode, diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c index 7426f8b21252..6c2e2b311c16 100644 --- a/drivers/net/ethernet/silan/sc92031.c +++ b/drivers/net/ethernet/silan/sc92031.c @@ -1386,7 +1386,6 @@ static const struct net_device_ops sc92031_netdev_ops = { .ndo_open = sc92031_open, .ndo_stop = sc92031_stop, .ndo_set_rx_mode = sc92031_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_tx_timeout = sc92031_tx_timeout, diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c index 27be6c869315..210e35d079dd 100644 --- a/drivers/net/ethernet/sis/sis190.c +++ b/drivers/net/ethernet/sis/sis190.c @@ -1833,7 +1833,6 @@ static const struct net_device_ops sis190_netdev_ops = { .ndo_start_xmit = sis190_start_xmit, .ndo_tx_timeout = sis190_tx_timeout, .ndo_set_rx_mode = sis190_set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = sis190_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 6f85276376e8..39fca6c0b68d 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -400,7 +400,6 @@ static const struct net_device_ops sis900_netdev_ops = { .ndo_start_xmit = sis900_start_xmit, .ndo_set_config = sis900_set_config, .ndo_set_rx_mode = set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = mii_ioctl, diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c index 7186b89269ad..fe9760ffab51 100644 --- a/drivers/net/ethernet/smsc/epic100.c +++ b/drivers/net/ethernet/smsc/epic100.c @@ -313,7 +313,6 @@ static const struct net_device_ops epic_netdev_ops = { .ndo_get_stats = epic_get_stats, .ndo_set_rx_mode = set_rx_mode, .ndo_do_ioctl = netdev_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index cb49c9654f0a..4f19c6166182 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -1753,7 +1753,6 @@ static const struct net_device_ops smc911x_netdev_ops = { .ndo_start_xmit = smc911x_hard_start_xmit, .ndo_tx_timeout = smc911x_timeout, .ndo_set_rx_mode = smc911x_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c index d496888b85d3..c8d84679ede7 100644 --- a/drivers/net/ethernet/smsc/smc9194.c +++ b/drivers/net/ethernet/smsc/smc9194.c @@ -809,7 +809,6 @@ static const struct net_device_ops smc_netdev_ops = { .ndo_start_xmit = smc_wait_to_send_packet, .ndo_tx_timeout = smc_timeout, .ndo_set_rx_mode = smc_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c index db3c696d7002..f1c75e291e55 100644 --- a/drivers/net/ethernet/smsc/smc91c92_cs.c +++ b/drivers/net/ethernet/smsc/smc91c92_cs.c @@ -294,7 +294,6 @@ static const struct net_device_ops smc_netdev_ops = { .ndo_set_config = s9k_config, .ndo_set_rx_mode = set_rx_mode, .ndo_do_ioctl = smc_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 73212590d04a..9b4780f87863 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -1762,7 +1762,6 @@ static const struct net_device_ops smc_netdev_ops = { .ndo_start_xmit = smc_hard_start_xmit, .ndo_tx_timeout = smc_timeout, .ndo_set_rx_mode = smc_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index e9b8579e6241..cdb343f0c6e0 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2152,7 +2152,6 @@ static const struct net_device_ops smsc911x_netdev_ops = { .ndo_get_stats = smsc911x_get_stats, .ndo_set_rx_mode = smsc911x_set_multicast_list, .ndo_do_ioctl = smsc911x_do_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = smsc911x_set_mac_address, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index aa4f9d2d8fa9..ea89ef3b48fb 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -1064,7 +1064,6 @@ static const struct net_device_ops bigmac_ops = { .ndo_get_stats = bigmac_get_stats, .ndo_set_rx_mode = bigmac_set_multicast, .ndo_tx_timeout = bigmac_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index cf4dcff051d5..ca96408058b0 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -2669,7 +2669,6 @@ static const struct net_device_ops hme_netdev_ops = { .ndo_tx_timeout = happy_meal_tx_timeout, .ndo_get_stats = happy_meal_get_stats, .ndo_set_rx_mode = happy_meal_set_multicast, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c index 9b825780b3be..c5ef711f6567 100644 --- a/drivers/net/ethernet/sun/sunqe.c +++ b/drivers/net/ethernet/sun/sunqe.c @@ -823,7 +823,6 @@ static const struct net_device_ops qec_ops = { .ndo_start_xmit = qe_start_xmit, .ndo_set_rx_mode = qe_set_multicast, .ndo_tx_timeout = qe_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c index fa0cfda24fd9..c56e7030c44e 100644 --- a/drivers/net/ethernet/ti/cpmac.c +++ b/drivers/net/ethernet/ti/cpmac.c @@ -1068,7 +1068,6 @@ static const struct net_device_ops cpmac_netdev_ops = { .ndo_tx_timeout = cpmac_tx_timeout, .ndo_set_rx_mode = cpmac_set_multicast_list, .ndo_do_ioctl = cpmac_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, }; diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 6d4b8a2e0cf6..b1ddf89a19be 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1883,7 +1883,6 @@ static const struct net_device_ops cpsw_netdev_ops = { .ndo_set_mac_address = cpsw_ndo_set_mac_address, .ndo_do_ioctl = cpsw_ndo_ioctl, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_tx_timeout = cpsw_ndo_tx_timeout, .ndo_set_rx_mode = cpsw_ndo_set_rx_mode, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index ece0ea0f6b38..4a3eeb10d45b 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -772,7 +772,6 @@ static const struct net_device_ops tlan_netdev_ops = { .ndo_get_stats = tlan_get_stats, .ndo_set_rx_mode = tlan_set_multicast_list, .ndo_do_ioctl = tlan_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index 5b01b3fa9fec..3be61ed28741 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c @@ -747,7 +747,6 @@ static const struct net_device_ops tc35815_netdev_ops = { .ndo_tx_timeout = tc35815_tx_timeout, .ndo_do_ioctl = tc35815_ioctl, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = tc35815_poll_controller, diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index 8fd131207ee1..f153ad729ce5 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -1548,7 +1548,6 @@ static const struct net_device_ops tsi108_netdev_ops = { .ndo_do_ioctl = tsi108_do_ioctl, .ndo_set_mac_address = tsi108_set_mac, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static int diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 9d14731cdcb1..ba5c54249055 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -890,7 +890,6 @@ static const struct net_device_ops rhine_netdev_ops = { .ndo_start_xmit = rhine_start_tx, .ndo_get_stats64 = rhine_get_stats64, .ndo_set_rx_mode = rhine_set_rx_mode, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = netdev_ioctl, diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index d2349a1bc6ba..e1296ef2cf66 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -1045,7 +1045,6 @@ static const struct net_device_ops w5100_netdev_ops = { .ndo_set_rx_mode = w5100_set_rx_mode, .ndo_set_mac_address = w5100_set_macaddr, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static int w5100_mmio_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c index ca31a57dbc86..724fabd38a23 100644 --- a/drivers/net/ethernet/wiznet/w5300.c +++ b/drivers/net/ethernet/wiznet/w5300.c @@ -536,7 +536,6 @@ static const struct net_device_ops w5300_netdev_ops = { .ndo_set_rx_mode = w5300_set_rx_mode, .ndo_set_mac_address = w5300_set_macaddr, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static int w5300_hw_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c index ddced28e8247..3b08ec766076 100644 --- a/drivers/net/ethernet/xircom/xirc2ps_cs.c +++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c @@ -466,7 +466,6 @@ static const struct net_device_ops netdev_ops = { .ndo_set_config = do_config, .ndo_do_ioctl = do_ioctl, .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 7f127dc1b7ba..46cc33b9e926 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1379,7 +1379,6 @@ static const struct net_device_ops ixp4xx_netdev_ops = { .ndo_start_xmit = eth_xmit, .ndo_set_rx_mode = eth_set_mcast_list, .ndo_do_ioctl = eth_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/plip/plip.c b/drivers/net/plip/plip.c index 9c4b41a4df7d..3c55ea357f35 100644 --- a/drivers/net/plip/plip.c +++ b/drivers/net/plip/plip.c @@ -270,7 +270,6 @@ static const struct net_device_ops plip_netdev_ops = { .ndo_stop = plip_close, .ndo_start_xmit = plip_tx_packet, .ndo_do_ioctl = plip_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index aad0b59d41e3..8b8b53259783 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -141,7 +141,6 @@ static const struct net_device_ops sb1000_netdev_ops = { .ndo_start_xmit = sb1000_start_xmit, .ndo_do_ioctl = sb1000_dev_ioctl, .ndo_stop = sb1000_close, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index d9ca05d3ac8e..a1f2f6f1e614 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -761,7 +761,6 @@ static const struct net_device_ops catc_netdev_ops = { .ndo_tx_timeout = catc_tx_timeout, .ndo_set_rx_mode = catc_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 66b34ddbe216..338aed5da14d 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -982,7 +982,6 @@ static const struct net_device_ops kaweth_netdev_ops = { .ndo_tx_timeout = kaweth_tx_timeout, .ndo_set_rx_mode = kaweth_set_rx_mode, .ndo_get_stats = kaweth_netdev_stats, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 1434e5dd5f9c..399f7ee57aea 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -1273,7 +1273,6 @@ static const struct net_device_ops pegasus_netdev_ops = { .ndo_set_rx_mode = pegasus_set_multicast, .ndo_get_stats = pegasus_netdev_stats, .ndo_tx_timeout = pegasus_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 44d439f50961..2886946ca371 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -4113,7 +4113,8 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu) switch (tp->version) { case RTL_VER_01: case RTL_VER_02: - return eth_change_mtu(dev, new_mtu); + dev->mtu = new_mtu; + return 0; default: break; } diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 7c72bfac89d0..93a1bda1c1e5 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -847,7 +847,6 @@ static const struct net_device_ops rtl8150_netdev_ops = { .ndo_set_rx_mode = rtl8150_set_multicast, .ndo_set_mac_address = rtl8150_set_mac_address, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 3a421ca8a4d0..3f83be98d469 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -211,7 +211,6 @@ static const struct net_device_ops sbni_netdev_ops = { .ndo_start_xmit = sbni_start_xmit, .ndo_set_rx_mode = set_multicast_list, .ndo_do_ioctl = sbni_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/wireless/intersil/prism54/islpci_dev.c b/drivers/net/wireless/intersil/prism54/islpci_dev.c index 84a42012aeae..325176d4d796 100644 --- a/drivers/net/wireless/intersil/prism54/islpci_dev.c +++ b/drivers/net/wireless/intersil/prism54/islpci_dev.c @@ -808,7 +808,6 @@ static const struct net_device_ops islpci_netdev_ops = { .ndo_start_xmit = islpci_eth_transmit, .ndo_tx_timeout = islpci_eth_tx_timeout, .ndo_set_mac_address = prism54_set_mac_address, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 431f13b4faf6..e95b79bccf9b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2791,7 +2791,6 @@ static void mac80211_hwsim_free(void) static const struct net_device_ops hwsim_netdev_ops = { .ndo_start_xmit = hwsim_mon_xmit, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c index 8541cbed786d..e3500203715c 100644 --- a/drivers/net/wireless/marvell/libertas/main.c +++ b/drivers/net/wireless/marvell/libertas/main.c @@ -945,7 +945,6 @@ static const struct net_device_ops lbs_netdev_ops = { .ndo_start_xmit = lbs_hard_start_xmit, .ndo_set_mac_address = lbs_set_mac_address, .ndo_set_rx_mode = lbs_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 0881ba8535f4..4fdc7223c894 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -272,7 +272,6 @@ static const struct net_device_ops ray_netdev_ops = { .ndo_set_config = ray_dev_config, .ndo_get_stats = ray_get_stats, .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 932f3f81e8cf..d9d29ab88184 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1853,7 +1853,6 @@ static const struct net_device_ops wl3501_netdev_ops = { .ndo_stop = wl3501_close, .ndo_start_xmit = wl3501_hard_start_xmit, .ndo_tx_timeout = wl3501_tx_timeout, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c index dea049b2556f..de7ff395977a 100644 --- a/drivers/net/wireless/zydas/zd1201.c +++ b/drivers/net/wireless/zydas/zd1201.c @@ -1724,7 +1724,6 @@ static const struct net_device_ops zd1201_netdev_ops = { .ndo_tx_timeout = zd1201_tx_timeout, .ndo_set_rx_mode = zd1201_set_multicast, .ndo_set_mac_address = zd1201_set_mac_address, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c index d976e5e18d50..c9c9821cfc32 100644 --- a/drivers/staging/rtl8188eu/os_dep/mon.c +++ b/drivers/staging/rtl8188eu/os_dep/mon.c @@ -145,7 +145,6 @@ static netdev_tx_t mon_xmit(struct sk_buff *skb, struct net_device *dev) static const struct net_device_ops mon_netdev_ops = { .ndo_start_xmit = mon_xmit, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 4c30eea45f89..5f53fbd565ef 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -2545,7 +2545,6 @@ static const struct net_device_ops rtl8192_netdev_ops = { .ndo_set_rx_mode = _rtl92e_set_multicast, .ndo_set_mac_address = _rtl92e_set_mac_adr, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_start_xmit = rtllib_xmit, }; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 457eeb5f5239..fdb03dccb449 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -4930,7 +4930,6 @@ static const struct net_device_ops rtl8192_netdev_ops = { .ndo_set_rx_mode = r8192_set_multicast, .ndo_set_mac_address = r8192_set_mac_adr, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_start_xmit = ieee80211_xmit, }; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 062307ad7fed..2802b900f8ee 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -2880,7 +2880,6 @@ static const struct net_device_ops slic_netdev_ops = { .ndo_get_stats = slic_get_stats, .ndo_set_rx_mode = slic_mcast_set_list, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static u32 slic_card_locate(struct adapter *adapter) diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index 117d02e0fc31..864d6f2b2cb0 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -35,6 +35,8 @@ #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ #define ETH_FCS_LEN 4 /* Octets in the FCS */ +#define ETH_MIN_MTU 68 /* Min IPv4 MTU per RFC791 */ + /* * These are the defined Ethernet Protocol ID's. */ diff --git a/net/atm/br2684.c b/net/atm/br2684.c index aa0047c5c467..c7d82f4e8422 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -620,14 +620,12 @@ error: static const struct net_device_ops br2684_netdev_ops = { .ndo_start_xmit = br2684_start_xmit, .ndo_set_mac_address = br2684_mac_addr, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; static const struct net_device_ops br2684_netdev_ops_routed = { .ndo_start_xmit = br2684_start_xmit, .ndo_set_mac_address = br2684_mac_addr, - .ndo_change_mtu = eth_change_mtu }; static void br2684_setup(struct net_device *netdev) diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index f4fcb4a9d5c1..0f25ddc319e2 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -211,7 +211,6 @@ static const struct net_device_ops bnep_netdev_ops = { .ndo_set_rx_mode = bnep_net_set_mc_list, .ndo_set_mac_address = bnep_net_set_mac_addr, .ndo_tx_timeout = bnep_net_timeout, - .ndo_change_mtu = eth_change_mtu, }; diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 66dff5e3d772..f983c102ebe3 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -322,8 +322,7 @@ EXPORT_SYMBOL(eth_mac_addr); */ int eth_change_mtu(struct net_device *dev, int new_mtu) { - if (new_mtu < 68 || new_mtu > ETH_DATA_LEN) - return -EINVAL; + netdev_warn(dev, "%s is deprecated\n", __func__); dev->mtu = new_mtu; return 0; } @@ -357,6 +356,8 @@ void ether_setup(struct net_device *dev) dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; dev->mtu = ETH_DATA_LEN; + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = ETH_DATA_LEN; dev->addr_len = ETH_ALEN; dev->tx_queue_len = 1000; /* Ethernet wants good queues */ dev->flags = IFF_BROADCAST|IFF_MULTICAST; diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index d8b7267280c3..8192eaea4ecd 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -51,7 +51,6 @@ static const struct net_device_ops irlan_eth_netdev_ops = { .ndo_stop = irlan_eth_close, .ndo_start_xmit = irlan_eth_xmit, .ndo_set_rx_mode = irlan_eth_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, }; -- cgit v1.2.3 From 7543d11682ef4ddc13d289b423c07356cc0d3672 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 4 Oct 2016 21:19:59 +0530 Subject: ath10k: cleanup calling ath10k_htt_rx_h_unchain 'ath10k_htt_rx_h_unchain' needs to be called only if the return value from 'ath10k_htt_rx_amsdu_pop' is 1('chained msdu's'), this change makes it more explicit and avoids doing a skb_peek, fetching rx descriptor pointer, checking rx msdu decap format for the case of ret = 0 (unchained msdus). Found this change during code walk through, not sure if this addresses any issue. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 0b4c1562420f..285b235268d7 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1463,8 +1463,7 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu) } static void ath10k_htt_rx_h_unchain(struct ath10k *ar, - struct sk_buff_head *amsdu, - bool chained) + struct sk_buff_head *amsdu) { struct sk_buff *first; struct htt_rx_desc *rxd; @@ -1475,9 +1474,6 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar, decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1), RX_MSDU_START_INFO1_DECAP_FORMAT); - if (!chained) - return; - /* FIXME: Current unchaining logic can only handle simple case of raw * msdu chaining. If decapping is other than raw the chaining may be * more complex and this isn't handled by the current code. Don't even @@ -1555,7 +1551,11 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) num_msdus = skb_queue_len(&amsdu); ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); - ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0); + + /* only for ret = 1 indicates chained msdus */ + if (ret > 0) + ath10k_htt_rx_h_unchain(ar, &amsdu); + ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); -- cgit v1.2.3 From ebaa4b1620bf69f2bc43cb45ea85fbafdaec23c3 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Mon, 10 Oct 2016 19:51:18 +0530 Subject: ath10k: fix kernel panic due to race in accessing arvif list arvifs list is traversed within data_lock spin_lock in tasklet context to fill channel information from the corresponding vif. This means any access to arvifs list for add/del operations should also be protected with the same spin_lock to avoid the race. Fix this by performing list add/del on arvfis within the data_lock. This could fix kernel panic something like the below. LR is at ath10k_htt_rx_pktlog_completion_handler+0x100/0xb6c [ath10k_core] PC is at ath10k_htt_rx_pktlog_completion_handler+0x1c0/0xb6c [ath10k_core] Internal error: Oops: 17 [#1] PREEMPT SMP ARM [] (ath10k_htt_rx_pktlog_completion_handler+0x2f4/0xb6c [ath10k_core]) [] (ath10k_htt_txrx_compl_task+0x8b4/0x1188 [ath10k_core]) [] (tasklet_action+0x8c/0xec) [] (__do_softirq+0xdc/0x208) [] (irq_exit+0x84/0xe0) [] (__handle_domain_irq+0x80/0xa0) [] (gic_handle_irq+0x38/0x5c) [] (__irq_svc+0x40/0x74) (gdb) list *(ath10k_htt_rx_pktlog_completion_handler+0x1c0) 0x136c0 is in ath10k_htt_rx_h_channel (drivers/net/wireless/ath/ath10k/htt_rx.c:769) 764 struct cfg80211_chan_def def; 765 766 lockdep_assert_held(&ar->data_lock); 767 768 list_for_each_entry(arvif, &ar->arvifs, list) { 769 if (arvif->vdev_id == vdev_id && 770 ath10k_mac_vif_chan(arvif->vif, &def) == 0) 771 return def.chan; 772 } 773 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 2e5d2ca6d816..691b7b58c584 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4931,7 +4931,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, } ar->free_vdev_map &= ~(1LL << arvif->vdev_id); + spin_lock_bh(&ar->data_lock); list_add(&arvif->list, &ar->arvifs); + spin_unlock_bh(&ar->data_lock); /* It makes no sense to have firmware do keepalives. mac80211 already * takes care of this with idle connection polling. @@ -5082,7 +5084,9 @@ err_peer_delete: err_vdev_delete: ath10k_wmi_vdev_delete(ar, arvif->vdev_id); ar->free_vdev_map |= 1LL << arvif->vdev_id; + spin_lock_bh(&ar->data_lock); list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); err: if (arvif->beacon_buf) { @@ -5128,7 +5132,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, arvif->vdev_id, ret); ar->free_vdev_map |= 1LL << arvif->vdev_id; + spin_lock_bh(&ar->data_lock); list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); if (arvif->vdev_type == WMI_VDEV_TYPE_AP || arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { -- cgit v1.2.3 From e463139a726276cd2995ed21c809504d6470f061 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 9 Aug 2016 15:02:26 +0800 Subject: ath9k: change entropy formula for easier understanding The quality of ADC entropy is 10 bits of min-entropy for a 32-bit value, change '(((x) * 8 * 320) >> 10)' to '(((x) * 8 * 10) >> 5)' for easier understanding. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c index d38e50f96db7..568b1c6c2b2b 100644 --- a/drivers/net/wireless/ath/ath9k/rng.c +++ b/drivers/net/wireless/ath/ath9k/rng.c @@ -22,7 +22,7 @@ #include "ar9003_phy.h" #define ATH9K_RNG_BUF_SIZE 320 -#define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 320) >> 10) /* quality: 320/1024 */ +#define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 10) >> 5) /* quality: 10/32 */ static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size) { -- cgit v1.2.3 From ad16d2ed8fa80e7f4f0d0da32129ed2c9caca3b4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 13 Oct 2016 09:55:04 +0100 Subject: drm/i915: Skip unbinding large unmappable global buffers If the user requests a mappable binding to the global GTT, we will first unbind an existing mapping if it doesn't match. We will unbind even if there is no possibility that the object can fit in the mappable aperture. This may lead to a ping-pong migration of the object, for example igt/gem_exec_big. v2: Comment upon the reasoning, or lack thereof!, behind the choice of magic numbers. Testcase: igt/gem_exec_big Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161013085504.30705-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin node.start < start); + GEM_BUG_ON(vma->node.start + vma->node.size > end); } GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level)); @@ -3798,7 +3801,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, u64 alignment, u64 flags) { - struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base; + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct i915_address_space *vm = &dev_priv->ggtt.base; struct i915_vma *vma; int ret; @@ -3811,6 +3815,41 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, (i915_vma_is_pinned(vma) || i915_vma_is_active(vma))) return ERR_PTR(-ENOSPC); + if (flags & PIN_MAPPABLE) { + u32 fence_size; + + fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size, + i915_gem_object_get_tiling(obj)); + /* If the required space is larger than the available + * aperture, we will not able to find a slot for the + * object and unbinding the object now will be in + * vain. Worse, doing so may cause us to ping-pong + * the object in and out of the Global GTT and + * waste a lot of cycles under the mutex. + */ + if (fence_size > dev_priv->ggtt.mappable_end) + return ERR_PTR(-E2BIG); + + /* If NONBLOCK is set the caller is optimistically + * trying to cache the full object within the mappable + * aperture, and *must* have a fallback in place for + * situations where we cannot bind the object. We + * can be a little more lax here and use the fallback + * more often to avoid costly migrations of ourselves + * and other objects within the aperture. + * + * Half-the-aperture is used as a simple heuristic. + * More interesting would to do search for a free + * block prior to making the commitment to unbind. + * That caters for the self-harm case, and with a + * little more heuristics (e.g. NOFAULT, NOEVICT) + * we could try to minimise harm to others. + */ + if (flags & PIN_NONBLOCK && + fence_size > dev_priv->ggtt.mappable_end / 2) + return ERR_PTR(-ENOSPC); + } + WARN(i915_vma_is_pinned(vma), "bo is already pinned in ggtt with incorrect alignment:" " offset=%08x, req.alignment=%llx," -- cgit v1.2.3 From baac789832ac91d477dc3c69f8d7bf84babd74cf Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Wed, 12 Oct 2016 12:38:49 +0200 Subject: s390/netiucv: get rid of one memcpy in netiucv_printuser Save a memcpy in netiucv_printuser(). Signed-off-by: Ursula Braun Reported-by: David Binderman Signed-off-by: David S. Miller --- drivers/s390/net/netiucv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index b0e8ffdf864b..88b6e9c56b4c 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -302,8 +302,7 @@ static char *netiucv_printuser(struct iucv_connection *conn) if (memcmp(conn->userdata, iucvMagic_ebcdic, 16)) { tmp_uid[8] = '\0'; tmp_udat[16] = '\0'; - memcpy(tmp_uid, conn->userid, 8); - memcpy(tmp_uid, netiucv_printname(tmp_uid, 8), 8); + memcpy(tmp_uid, netiucv_printname(conn->userid, 8), 8); memcpy(tmp_udat, conn->userdata, 16); EBCASC(tmp_udat, 16); memcpy(tmp_udat, netiucv_printname(tmp_udat, 16), 16); -- cgit v1.2.3 From 9edebf11a4aa6349fecaedd673516fcf1999956a Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Wed, 12 Oct 2016 12:38:50 +0200 Subject: s390/netiucv: improve checking of sysfs attribute buffer High values are always wrong for netiucv's sysfs attribute "buffer". But the current code does not detect values between 2**31 and 2**32 as invalid. Choosing type "unsigned int" for variable "bs1" and making use of "kstrtouint()" improves the syntax checking for "buffer". Signed-off-by: Ursula Braun Reported-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/s390/net/netiucv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 88b6e9c56b4c..2f0f3918172a 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1563,21 +1563,21 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr, { struct netiucv_priv *priv = dev_get_drvdata(dev); struct net_device *ndev = priv->conn->netdev; - char *e; - int bs1; + unsigned int bs1; + int rc; IUCV_DBF_TEXT(trace, 3, __func__); if (count >= 39) return -EINVAL; - bs1 = simple_strtoul(buf, &e, 0); + rc = kstrtouint(buf, 0, &bs1); - if (e && (!isspace(*e))) { - IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %02x\n", - *e); + if (rc == -EINVAL) { + IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %s\n", + buf); return -EINVAL; } - if (bs1 > NETIUCV_BUFSIZE_MAX) { + if ((rc == -ERANGE) || (bs1 > NETIUCV_BUFSIZE_MAX)) { IUCV_DBF_TEXT_(setup, 2, "buffer_write: buffer size %d too large\n", bs1); -- cgit v1.2.3 From f7e3a16c4a80add7ab965fb5d50dbe5f29ec1628 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 12 Oct 2016 12:38:51 +0200 Subject: s390/lcs: remove trailing space at end of dev_err message There is a trailing white space at the end of a dev_err message that does nothing useful - remove it. Signed-off-by: Colin Ian King Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/lcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 251db0a02e73..211b31d9f157 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1888,7 +1888,7 @@ lcs_stop_device(struct net_device *dev) rc = lcs_stopcard(card); if (rc) dev_err(&card->dev->dev, - " Shutting down the LCS device failed\n "); + " Shutting down the LCS device failed\n"); return rc; } -- cgit v1.2.3 From f7170e2eb8f6bf7ef2032cc0659cd38740bf5b97 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 13 Oct 2016 11:55:08 +0300 Subject: drm/i915: fix a read size argument We want to read 3 bytes here, but because the parenthesis are in the wrong place we instead read: sizeof(intel_dp->edp_dpcd) == sizeof(intel_dp->edp_dpcd) which is one byte. Fixes: fe5a66f91c88 ("drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP") Reviewed-by: Chris Wilson Cc: Signed-off-by: Dan Carpenter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161013085508.GJ16198@mwanda --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5992093e1814..496141e3b4d3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3547,8 +3547,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) /* Read the eDP Display control capabilities registers */ if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) && drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, - intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd) == - sizeof(intel_dp->edp_dpcd))) + intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == + sizeof(intel_dp->edp_dpcd)) DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd), intel_dp->edp_dpcd); -- cgit v1.2.3 From 86e83e35d190a9b553384e0e711091a4e9643998 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Oct 2016 20:49:52 +0100 Subject: drm/i915: Merge duplicate gen4 and vlv/chv enable vblank callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gen4/vlv/chv all use the same bits in pipestat to enable the vblank interrupt, so they can share the same callbacks to enable/disable. Signed-off-by: Chris Wilson Cc: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20161007194953.15616-1-chris@chris-wilson.co.uk Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 59 +++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ddff6f9b869c..91077e426c77 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2718,45 +2718,40 @@ void i915_handle_error(struct drm_i915_private *dev_priv, /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ -static int i915_enable_vblank(struct drm_device *dev, unsigned int pipe) +static int i8xx_enable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - if (INTEL_INFO(dev)->gen >= 4) - i915_enable_pipestat(dev_priv, pipe, - PIPE_START_VBLANK_INTERRUPT_STATUS); - else - i915_enable_pipestat(dev_priv, pipe, - PIPE_VBLANK_INTERRUPT_STATUS); + i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; } -static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) +static int i965_enable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; - uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) : - DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - ilk_enable_display_irq(dev_priv, bit); + i915_enable_pipestat(dev_priv, pipe, + PIPE_START_VBLANK_INTERRUPT_STATUS); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; } -static int valleyview_enable_vblank(struct drm_device *dev, unsigned int pipe) +static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; + uint32_t bit = INTEL_GEN(dev) >= 7 ? + DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, pipe, - PIPE_START_VBLANK_INTERRUPT_STATUS); + ilk_enable_display_irq(dev_priv, bit); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; @@ -2777,38 +2772,36 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ -static void i915_disable_vblank(struct drm_device *dev, unsigned int pipe) +static void i8xx_disable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_disable_pipestat(dev_priv, pipe, - PIPE_VBLANK_INTERRUPT_STATUS | - PIPE_START_VBLANK_INTERRUPT_STATUS); + i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe) +static void i965_disable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; - uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) : - DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - ilk_disable_display_irq(dev_priv, bit); + i915_disable_pipestat(dev_priv, pipe, + PIPE_START_VBLANK_INTERRUPT_STATUS); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -static void valleyview_disable_vblank(struct drm_device *dev, unsigned int pipe) +static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; + uint32_t bit = INTEL_GEN(dev) >= 7 ? + DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_disable_pipestat(dev_priv, pipe, - PIPE_START_VBLANK_INTERRUPT_STATUS); + ilk_disable_display_irq(dev_priv, bit); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } @@ -4579,16 +4572,16 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_preinstall = cherryview_irq_preinstall; dev->driver->irq_postinstall = cherryview_irq_postinstall; dev->driver->irq_uninstall = cherryview_irq_uninstall; - dev->driver->enable_vblank = valleyview_enable_vblank; - dev->driver->disable_vblank = valleyview_disable_vblank; + dev->driver->enable_vblank = i965_enable_vblank; + dev->driver->disable_vblank = i965_disable_vblank; dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; } else if (IS_VALLEYVIEW(dev_priv)) { dev->driver->irq_handler = valleyview_irq_handler; dev->driver->irq_preinstall = valleyview_irq_preinstall; dev->driver->irq_postinstall = valleyview_irq_postinstall; dev->driver->irq_uninstall = valleyview_irq_uninstall; - dev->driver->enable_vblank = valleyview_enable_vblank; - dev->driver->disable_vblank = valleyview_disable_vblank; + dev->driver->enable_vblank = i965_enable_vblank; + dev->driver->disable_vblank = i965_disable_vblank; dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; } else if (INTEL_INFO(dev_priv)->gen >= 8) { dev->driver->irq_handler = gen8_irq_handler; @@ -4617,21 +4610,25 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_postinstall = i8xx_irq_postinstall; dev->driver->irq_handler = i8xx_irq_handler; dev->driver->irq_uninstall = i8xx_irq_uninstall; + dev->driver->enable_vblank = i8xx_enable_vblank; + dev->driver->disable_vblank = i8xx_disable_vblank; } else if (IS_GEN3(dev_priv)) { dev->driver->irq_preinstall = i915_irq_preinstall; dev->driver->irq_postinstall = i915_irq_postinstall; dev->driver->irq_uninstall = i915_irq_uninstall; dev->driver->irq_handler = i915_irq_handler; + dev->driver->enable_vblank = i8xx_enable_vblank; + dev->driver->disable_vblank = i8xx_disable_vblank; } else { dev->driver->irq_preinstall = i965_irq_preinstall; dev->driver->irq_postinstall = i965_irq_postinstall; dev->driver->irq_uninstall = i965_irq_uninstall; dev->driver->irq_handler = i965_irq_handler; + dev->driver->enable_vblank = i965_enable_vblank; + dev->driver->disable_vblank = i965_disable_vblank; } if (I915_HAS_HOTPLUG(dev_priv)) dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; - dev->driver->enable_vblank = i915_enable_vblank; - dev->driver->disable_vblank = i915_disable_vblank; } } -- cgit v1.2.3 From 3b3f1650b1ca46a4225e0bf72804779b161e27b6 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Thu, 13 Oct 2016 22:44:48 +0530 Subject: drm/i915: Allocate intel_engine_cs structure only for the enabled engines With the possibility of addition of many more number of rings in future, the drm_i915_private structure could bloat as an array, of type intel_engine_cs, is embedded inside it. struct intel_engine_cs engine[I915_NUM_ENGINES]; Though this is still fine as generally there is only a single instance of drm_i915_private structure used, but not all of the possible rings would be enabled or active on most of the platforms. Some memory can be saved by allocating intel_engine_cs structure only for the enabled/active engines. Currently the engine/ring ID is kept static and dev_priv->engine[] is simply indexed using the enums defined in intel_engine_id. To save memory and continue using the static engine/ring IDs, 'engine' is defined as an array of pointers. struct intel_engine_cs *engine[I915_NUM_ENGINES]; dev_priv->engine[engine_ID] will be NULL for disabled engine instances. There is a text size reduction of 928 bytes, from 1028200 to 1027272, for i915.o file (but for i915.ko file text size remain same as 1193131 bytes). v2: - Remove the engine iterator field added in drm_i915_private structure, instead pass a local iterator variable to the for_each_engine** macros. (Chris) - Do away with intel_engine_initialized() and instead directly use the NULL pointer check on engine pointer. (Chris) v3: - Remove for_each_engine_id() macro, as the updated macro for_each_engine() can be used in place of it. (Chris) - Protect the access to Render engine Fault register with a NULL check, as engine specific init is done later in Driver load sequence. v4: - Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris) - Kill the superfluous init_engine_lists(). v5: - Cleanup the intel_engines_init() & intel_engines_setup(), with respect to allocation of intel_engine_cs structure. (Chris) v6: - Rebase. v7: - Optimize the for_each_engine_masked() macro. (Chris) - Change the type of 'iter' local variable to enum intel_engine_id. (Chris) - Rebase. v8: Rebase. v9: Rebase. v10: - For index calculation use engine ID instead of pointer based arithmetic in intel_engine_sync_index() as engine pointers are not contiguous now (Chris) - For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas) - Use for_each_engine macro for cleanup in intel_engines_init() and remove check for NULL engine pointer in cleanup() routines. (Joonas) v11: Rebase. Cc: Chris Wilson Signed-off-by: Akash Goel Reviewed-by: Joonas Lahtinen Signed-off-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com --- drivers/gpu/drm/i915/i915_cmd_parser.c | 3 +- drivers/gpu/drm/i915/i915_debugfs.c | 59 ++++++++++++++++++------------ drivers/gpu/drm/i915/i915_drv.c | 11 +++--- drivers/gpu/drm/i915/i915_drv.h | 22 ++++------- drivers/gpu/drm/i915/i915_gem.c | 29 +++++++-------- drivers/gpu/drm/i915/i915_gem_context.c | 15 +++++--- drivers/gpu/drm/i915/i915_gem_evict.c | 3 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 6 +-- drivers/gpu/drm/i915/i915_gem_gtt.c | 14 +++++-- drivers/gpu/drm/i915/i915_gem_request.c | 5 ++- drivers/gpu/drm/i915/i915_gpu_error.c | 28 +++++++------- drivers/gpu/drm/i915/i915_guc_submission.c | 12 +++--- drivers/gpu/drm/i915/i915_irq.c | 46 ++++++++++++----------- drivers/gpu/drm/i915/intel_breadcrumbs.c | 6 ++- drivers/gpu/drm/i915/intel_display.c | 8 ++-- drivers/gpu/drm/i915/intel_engine_cs.c | 26 +++++++++---- drivers/gpu/drm/i915/intel_guc_loader.c | 6 ++- drivers/gpu/drm/i915/intel_lrc.c | 11 +++--- drivers/gpu/drm/i915/intel_overlay.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 17 ++++++--- drivers/gpu/drm/i915/intel_ringbuffer.c | 15 ++++---- drivers/gpu/drm/i915/intel_ringbuffer.h | 8 +--- 22 files changed, 194 insertions(+), 158 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 70980f82a15b..f191d7b66b1d 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1308,10 +1308,11 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; bool active = false; /* If the command parser is not enabled, report 0 - unsupported */ - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { if (intel_engine_needs_cmd_parser(engine)) { active = true; break; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 2e312e0f2670..b20c1ccbd427 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -150,7 +150,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) obj->base.size / 1024, obj->base.read_domains, obj->base.write_domain); - for_each_engine_id(engine, dev_priv, id) + for_each_engine(engine, dev_priv, id) seq_printf(m, "%x ", i915_gem_active_get_seqno(&obj->last_read[id], &obj->base.dev->struct_mutex)); @@ -323,11 +323,12 @@ static void print_batch_pool_stats(struct seq_file *m, struct drm_i915_gem_object *obj; struct file_stats stats; struct intel_engine_cs *engine; + enum intel_engine_id id; int j; memset(&stats, 0, sizeof(stats)); - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { list_for_each_entry(obj, &engine->batch_pool.cache_list[j], @@ -596,6 +597,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) struct drm_device *dev = &dev_priv->drm; struct drm_i915_gem_object *obj; struct intel_engine_cs *engine; + enum intel_engine_id id; int total = 0; int ret, j; @@ -603,7 +605,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) if (ret) return ret; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { int count; @@ -655,8 +657,9 @@ static int i915_gem_request_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_device *dev = &dev_priv->drm; - struct intel_engine_cs *engine; struct drm_i915_gem_request *req; + struct intel_engine_cs *engine; + enum intel_engine_id id; int ret, any; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -664,7 +667,7 @@ static int i915_gem_request_info(struct seq_file *m, void *data) return ret; any = 0; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { int count; count = 0; @@ -710,8 +713,9 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) i915_ring_seqno_info(m, engine); return 0; @@ -722,6 +726,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_engine_cs *engine; + enum intel_engine_id id; int i, pipe; intel_runtime_pm_get(dev_priv); @@ -890,7 +895,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "Graphics Interrupt mask: %08x\n", I915_READ(GTIMR)); } - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { if (INTEL_GEN(dev_priv) >= 6) { seq_printf(m, "Graphics Interrupt mask (%s): %08x\n", @@ -938,7 +943,7 @@ static int i915_hws_info(struct seq_file *m, void *data) const u32 *hws; int i; - engine = &dev_priv->engine[(uintptr_t)node->info_ent->data]; + engine = dev_priv->engine[(uintptr_t)node->info_ent->data]; hws = engine->status_page.page_addr; if (hws == NULL) return 0; @@ -1329,12 +1334,12 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); - for_each_engine_id(engine, dev_priv, id) { + for_each_engine(engine, dev_priv, id) { acthd[id] = intel_engine_get_active_head(engine); seqno[id] = intel_engine_get_seqno(engine); } - intel_engine_get_instdone(&dev_priv->engine[RCS], &instdone); + intel_engine_get_instdone(dev_priv->engine[RCS], &instdone); intel_runtime_pm_put(dev_priv); @@ -1345,7 +1350,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) } else seq_printf(m, "Hangcheck inactive\n"); - for_each_engine_id(engine, dev_priv, id) { + for_each_engine(engine, dev_priv, id) { struct intel_breadcrumbs *b = &engine->breadcrumbs; struct rb_node *rb; @@ -1944,6 +1949,7 @@ static int i915_context_status(struct seq_file *m, void *unused) struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; struct i915_gem_context *ctx; + enum intel_engine_id id; int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -1970,7 +1976,7 @@ static int i915_context_status(struct seq_file *m, void *unused) seq_putc(m, ctx->remap_slice ? 'R' : 'r'); seq_putc(m, '\n'); - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { struct intel_context *ce = &ctx->engine[engine->id]; seq_printf(m, "%s: ", engine->name); @@ -2037,6 +2043,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; struct i915_gem_context *ctx; + enum intel_engine_id id; int ret; if (!i915.enable_execlists) { @@ -2049,7 +2056,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) return ret; list_for_each_entry(ctx, &dev_priv->context_list, link) - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) i915_dump_lrc_obj(m, ctx, engine); mutex_unlock(&dev->struct_mutex); @@ -2158,14 +2165,15 @@ static int per_file_ctx(int id, void *ptr, void *data) static void gen8_ppgtt_info(struct seq_file *m, struct drm_i915_private *dev_priv) { - struct intel_engine_cs *engine; struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; + struct intel_engine_cs *engine; + enum intel_engine_id id; int i; if (!ppgtt) return; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { seq_printf(m, "%s\n", engine->name); for (i = 0; i < 4; i++) { u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i)); @@ -2180,11 +2188,12 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; if (IS_GEN6(dev_priv)) seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE)); - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { seq_printf(m, "%s\n", engine->name); if (IS_GEN7(dev_priv)) seq_printf(m, "GFX_MODE: 0x%08x\n", @@ -2253,9 +2262,10 @@ out_unlock: static int count_irq_waiters(struct drm_i915_private *i915) { struct intel_engine_cs *engine; + enum intel_engine_id id; int count = 0; - for_each_engine(engine, i915) + for_each_engine(engine, i915, id) count += intel_engine_has_waiter(engine); return count; @@ -2418,7 +2428,7 @@ static void i915_guc_client_info(struct seq_file *m, seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail); seq_printf(m, "\tLast submission result: %d\n", client->retcode); - for_each_engine_id(engine, dev_priv, id) { + for_each_engine(engine, dev_priv, id) { u64 submissions = client->submissions[id]; tot += submissions; seq_printf(m, "\tSubmissions: %llu %s\n", @@ -2461,7 +2471,7 @@ static int i915_guc_info(struct seq_file *m, void *data) seq_printf(m, "GuC last action error code: %d\n", guc.action_err); seq_printf(m, "\nGuC submissions:\n"); - for_each_engine_id(engine, dev_priv, id) { + for_each_engine(engine, dev_priv, id) { u64 submissions = guc.submissions[id]; total += submissions; seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n", @@ -3082,8 +3092,9 @@ static int i915_engine_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { struct intel_breadcrumbs *b = &engine->breadcrumbs; struct drm_i915_gem_request *rq; struct rb_node *rb; @@ -3231,7 +3242,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) page = i915_gem_object_get_page(dev_priv->semaphore->obj, 0); seqno = (uint64_t *)kmap_atomic(page); - for_each_engine_id(engine, dev_priv, id) { + for_each_engine(engine, dev_priv, id) { uint64_t offset; seq_printf(m, "%s\n", engine->name); @@ -3256,7 +3267,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) kunmap_atomic(seqno); } else { seq_puts(m, " Last signal:"); - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) for (j = 0; j < num_rings; j++) seq_printf(m, "0x%08x\n", I915_READ(engine->semaphore.mbox.signal[j])); @@ -3264,7 +3275,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) } seq_puts(m, "\nSync seqno:\n"); - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { for (j = 0; j < num_rings; j++) seq_printf(m, " 0x%08x ", engine->semaphore.sync_seqno[j]); @@ -3320,7 +3331,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); seq_printf(m, "Workarounds applied: %d\n", workarounds->count); - for_each_engine_id(engine, dev_priv, id) + for_each_engine(engine, dev_priv, id) seq_printf(m, "HW whitelist count for %s: %d\n", engine->name, workarounds->hw_whitelist_count[id]); for (i = 0; i < workarounds->count; ++i) { diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e9b3bfcb347a..8c3d4761dfa0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -255,16 +255,16 @@ static int i915_getparam(struct drm_device *dev, void *data, value = dev_priv->overlay ? 1 : 0; break; case I915_PARAM_HAS_BSD: - value = intel_engine_initialized(&dev_priv->engine[VCS]); + value = !!dev_priv->engine[VCS]; break; case I915_PARAM_HAS_BLT: - value = intel_engine_initialized(&dev_priv->engine[BCS]); + value = !!dev_priv->engine[BCS]; break; case I915_PARAM_HAS_VEBOX: - value = intel_engine_initialized(&dev_priv->engine[VECS]); + value = !!dev_priv->engine[VECS]; break; case I915_PARAM_HAS_BSD2: - value = intel_engine_initialized(&dev_priv->engine[VCS2]); + value = !!dev_priv->engine[VCS2]; break; case I915_PARAM_HAS_EXEC_CONSTANTS: value = INTEL_GEN(dev_priv) >= 4; @@ -1707,10 +1707,11 @@ int i915_resume_switcheroo(struct drm_device *dev) static void disable_engines_irq(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; /* Ensure irq handler finishes, and not run again. */ disable_irq(dev_priv->drm.irq); - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) tasklet_kill(&engine->irq_tasklet); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6360e807c6ba..9e830b58b06b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1808,7 +1808,7 @@ struct drm_i915_private { struct pci_dev *bridge_dev; struct i915_gem_context *kernel_context; - struct intel_engine_cs engine[I915_NUM_ENGINES]; + struct intel_engine_cs *engine[I915_NUM_ENGINES]; struct i915_vma *semaphore; u32 next_seqno; @@ -2125,19 +2125,11 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) } /* Simple iterator over all initialised engines */ -#define for_each_engine(engine__, dev_priv__) \ - for ((engine__) = &(dev_priv__)->engine[0]; \ - (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \ - (engine__)++) \ - for_each_if (intel_engine_initialized(engine__)) - -/* Iterator with engine_id */ -#define for_each_engine_id(engine__, dev_priv__, id__) \ - for ((engine__) = &(dev_priv__)->engine[0], (id__) = 0; \ - (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \ - (engine__)++) \ - for_each_if (((id__) = (engine__)->id, \ - intel_engine_initialized(engine__))) +#define for_each_engine(engine__, dev_priv__, id__) \ + for ((id__) = 0; \ + (id__) < I915_NUM_ENGINES; \ + (id__)++) \ + for_each_if ((engine__) = (dev_priv__)->engine[(id__)]) #define __mask_next_bit(mask) ({ \ int __idx = ffs(mask) - 1; \ @@ -2148,7 +2140,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) /* Iterator over subset of engines selected by mask */ #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \ - tmp__ ? (engine__ = &(dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; ) + tmp__ ? (engine__ = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; ) enum hdmi_force_audio { HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 77dc0590ecc7..fb460cc2857c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2626,10 +2626,11 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) void i915_gem_reset(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; i915_gem_retire_requests(dev_priv); - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) i915_gem_reset_engine(engine); i915_gem_restore_fences(&dev_priv->drm); @@ -2677,12 +2678,13 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine) void i915_gem_set_wedged(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; lockdep_assert_held(&dev_priv->drm.struct_mutex); set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); i915_gem_context_lost(dev_priv); - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) i915_gem_cleanup_engine(engine); mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); @@ -2721,6 +2723,7 @@ i915_gem_idle_work_handler(struct work_struct *work) container_of(work, typeof(*dev_priv), gt.idle_work.work); struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; + enum intel_engine_id id; bool rearm_hangcheck; if (!READ_ONCE(dev_priv->gt.awake)) @@ -2743,7 +2746,7 @@ i915_gem_idle_work_handler(struct work_struct *work) if (dev_priv->gt.active_engines) goto out_unlock; - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) i915_gem_batch_pool_fini(&engine->batch_pool); GEM_BUG_ON(!dev_priv->gt.awake); @@ -2936,9 +2939,10 @@ int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, unsigned int flags) { struct intel_engine_cs *engine; + enum intel_engine_id id; int ret; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { if (engine->last_context == NULL) continue; @@ -3181,7 +3185,7 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj) */ wmb(); if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv)) - POSTING_READ(RING_ACTHD(dev_priv->engine[RCS].mmio_base)); + POSTING_READ(RING_ACTHD(dev_priv->engine[RCS]->mmio_base)); intel_fb_obj_flush(obj, false, write_origin(obj, I915_GEM_DOMAIN_GTT)); @@ -4416,6 +4420,7 @@ i915_gem_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_engine_cs *engine; + enum intel_engine_id id; int ret; /* Double layer security blanket, see i915_gem_init() */ @@ -4459,7 +4464,7 @@ i915_gem_init_hw(struct drm_device *dev) } /* Need to do basic initialisation of all rings first: */ - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { ret = engine->init_hw(engine); if (ret) goto out; @@ -4558,17 +4563,12 @@ i915_gem_cleanup_engines(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) dev_priv->gt.cleanup_engine(engine); } -static void -init_engine_lists(struct intel_engine_cs *engine) -{ - INIT_LIST_HEAD(&engine->request_list); -} - void i915_gem_load_init_fences(struct drm_i915_private *dev_priv) { @@ -4605,7 +4605,6 @@ void i915_gem_load_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int i; dev_priv->objects = kmem_cache_create("i915_gem_object", @@ -4629,8 +4628,6 @@ i915_gem_load_init(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->mm.unbound_list); INIT_LIST_HEAD(&dev_priv->mm.bound_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); - for (i = 0; i < I915_NUM_ENGINES; i++) - init_engine_lists(&dev_priv->engine[i]); INIT_DELAYED_WORK(&dev_priv->gt.retire_work, i915_gem_retire_work_handler); INIT_DELAYED_WORK(&dev_priv->gt.idle_work, diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index df10f4e95736..481ec43f8180 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -474,10 +474,11 @@ int i915_gem_context_init(struct drm_device *dev) void i915_gem_context_lost(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; lockdep_assert_held(&dev_priv->drm.struct_mutex); - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { if (engine->last_context) { i915_gem_context_unpin(engine->last_context, engine); engine->last_context = NULL; @@ -492,13 +493,13 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv) if (!i915_gem_context_is_default(ctx)) continue; - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) ctx->engine[engine->id].initialised = false; ctx->remap_slice = ALL_L3_SLICES(dev_priv); } - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { struct intel_context *kce = &dev_priv->kernel_context->engine[engine->id]; @@ -563,6 +564,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) struct drm_i915_private *dev_priv = req->i915; struct intel_ring *ring = req->ring; struct intel_engine_cs *engine = req->engine; + enum intel_engine_id id; u32 flags = hw_flags | MI_MM_SPACE_GTT; const int num_rings = /* Use an extended w/a on ivb+ if signalling from other rings */ @@ -605,7 +607,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_engine(signaller, dev_priv) { + for_each_engine(signaller, dev_priv, id) { if (signaller == engine) continue; @@ -634,7 +636,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_engine(signaller, dev_priv) { + for_each_engine(signaller, dev_priv, id) { if (signaller == engine) continue; @@ -929,8 +931,9 @@ int i915_switch_context(struct drm_i915_gem_request *req) int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { struct drm_i915_gem_request *req; int ret; diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 5b6f81c1dbca..b5e9e669f50f 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -37,8 +37,9 @@ static bool gpu_is_idle(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { if (intel_engine_is_active(engine)) return false; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 72c7c1855e70..fa4d27ca0c18 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1599,12 +1599,12 @@ eb_select_engine(struct drm_i915_private *dev_priv, return NULL; } - engine = &dev_priv->engine[_VCS(bsd_idx)]; + engine = dev_priv->engine[_VCS(bsd_idx)]; } else { - engine = &dev_priv->engine[user_ring_map[user_ring_id]]; + engine = dev_priv->engine[user_ring_map[user_ring_id]]; } - if (!intel_engine_initialized(engine)) { + if (!engine) { DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id); return NULL; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2d846aa39ca5..0a45063b465f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1728,8 +1728,9 @@ static void gen8_ppgtt_enable(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0; I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level)); @@ -1741,6 +1742,7 @@ static void gen7_ppgtt_enable(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); struct intel_engine_cs *engine; uint32_t ecochk, ecobits; + enum intel_engine_id id; ecobits = I915_READ(GAC_ECO_BITS); I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); @@ -1754,7 +1756,7 @@ static void gen7_ppgtt_enable(struct drm_device *dev) } I915_WRITE(GAM_ECOCHK, ecochk); - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { /* GFX_MODE is per-ring on gen7+ */ I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); @@ -2239,11 +2241,12 @@ static bool needs_idle_maps(struct drm_i915_private *dev_priv) void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; if (INTEL_INFO(dev_priv)->gen < 6) return; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { u32 fault_reg; fault_reg = I915_READ(RING_FAULT_REG(engine)); if (fault_reg & RING_FAULT_VALID) { @@ -2260,7 +2263,10 @@ void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) fault_reg & ~RING_FAULT_VALID); } } - POSTING_READ(RING_FAULT_REG(&dev_priv->engine[RCS])); + + /* Engine specific init may not have been done till this point. */ + if (dev_priv->engine[RCS]) + POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS])); } static void i915_ggtt_flush(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 8832f8ec1583..74ede1f53372 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -256,10 +256,11 @@ static int i915_gem_check_wedge(struct drm_i915_private *dev_priv) static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) { struct intel_engine_cs *engine; + enum intel_engine_id id; int ret; /* Carefully retire all requests without writing to the rings */ - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { ret = intel_engine_idle(engine, I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED); @@ -276,7 +277,7 @@ static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) } /* Finally reset hw state */ - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) intel_engine_init_seqno(engine, seqno); return 0; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index cd38948107e7..8d4b9eb8718a 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -632,7 +632,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, len += scnprintf(buf + len, sizeof(buf), "%s%s", first ? "" : ", ", - dev_priv->engine[j].name); + dev_priv->engine[j]->name); first = 0; } scnprintf(buf + len, sizeof(buf), ")"); @@ -650,7 +650,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, obj = ee->batchbuffer; if (obj) { - err_puts(m, dev_priv->engine[i].name); + err_puts(m, dev_priv->engine[i]->name); if (ee->pid != -1) err_printf(m, " (submitted by %s [%d])", ee->comm, @@ -658,12 +658,12 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, " --- gtt_offset = 0x%08x %08x\n", upper_32_bits(obj->gtt_offset), lower_32_bits(obj->gtt_offset)); - print_error_obj(m, &dev_priv->engine[i], NULL, obj); + print_error_obj(m, dev_priv->engine[i], NULL, obj); } if (ee->num_requests) { err_printf(m, "%s --- %d requests\n", - dev_priv->engine[i].name, + dev_priv->engine[i]->name, ee->num_requests); for (j = 0; j < ee->num_requests; j++) error_print_request(m, " ", &ee->requests[j]); @@ -671,10 +671,10 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if (IS_ERR(ee->waiters)) { err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n", - dev_priv->engine[i].name); + dev_priv->engine[i]->name); } else if (ee->num_waiters) { err_printf(m, "%s --- %d waiters\n", - dev_priv->engine[i].name, + dev_priv->engine[i]->name, ee->num_waiters); for (j = 0; j < ee->num_waiters; j++) { err_printf(m, " seqno 0x%08x for %s [%d]\n", @@ -684,19 +684,19 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } } - print_error_obj(m, &dev_priv->engine[i], + print_error_obj(m, dev_priv->engine[i], "ringbuffer", ee->ringbuffer); - print_error_obj(m, &dev_priv->engine[i], + print_error_obj(m, dev_priv->engine[i], "HW Status", ee->hws_page); - print_error_obj(m, &dev_priv->engine[i], + print_error_obj(m, dev_priv->engine[i], "HW context", ee->ctx); - print_error_obj(m, &dev_priv->engine[i], + print_error_obj(m, dev_priv->engine[i], "WA context", ee->wa_ctx); - print_error_obj(m, &dev_priv->engine[i], + print_error_obj(m, dev_priv->engine[i], "WA batchbuffer", ee->wa_batchbuffer); } @@ -977,7 +977,7 @@ static void gen8_record_semaphore_state(struct drm_i915_error_state *error, if (!error->semaphore) return; - for_each_engine_id(to, dev_priv, id) { + for_each_engine(to, dev_priv, id) { int idx; u16 signal_offset; u32 *tmp; @@ -1247,14 +1247,14 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv, i915_error_object_create(dev_priv, dev_priv->semaphore); for (i = 0; i < I915_NUM_ENGINES; i++) { - struct intel_engine_cs *engine = &dev_priv->engine[i]; + struct intel_engine_cs *engine = dev_priv->engine[i]; struct drm_i915_error_engine *ee = &error->engine[i]; struct drm_i915_gem_request *request; ee->pid = -1; ee->engine_id = -1; - if (!intel_engine_initialized(engine)) + if (!engine) continue; ee->engine_id = i; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 3106dcc06fe9..a1f76c8f8cde 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -917,6 +917,7 @@ static void guc_addon_create(struct intel_guc *guc) struct guc_policies *policies; struct guc_mmio_reg_state *reg_state; struct intel_engine_cs *engine; + enum intel_engine_id id; struct page *page; u32 size; @@ -944,10 +945,10 @@ static void guc_addon_create(struct intel_guc *guc) * so its address won't change after we've told the GuC where * to find it. */ - engine = &dev_priv->engine[RCS]; + engine = dev_priv->engine[RCS]; ads->golden_context_lrca = engine->status_page.ggtt_offset; - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine); /* GuC scheduling policies */ @@ -960,7 +961,7 @@ static void guc_addon_create(struct intel_guc *guc) /* MMIO reg state */ reg_state = (void *)policies + sizeof(struct guc_policies); - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { reg_state->mmio_white_list[engine->guc_id].mmio_start = engine->mmio_base + GUC_MMIO_WHITE_LIST_START; @@ -1014,9 +1015,10 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv) int i915_guc_submission_enable(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; + struct drm_i915_gem_request *request; struct i915_guc_client *client; struct intel_engine_cs *engine; - struct drm_i915_gem_request *request; + enum intel_engine_id id; /* client for execbuf submission */ client = guc_client_alloc(dev_priv, @@ -1033,7 +1035,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) guc_init_doorbell_hw(guc); /* Take over from manual control of ELSP (execlists) */ - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { engine->submit_request = i915_guc_submit; /* Replay the current set of previously submitted requests */ diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 91077e426c77..89380c830cc0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1058,8 +1058,9 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) static bool any_waiters(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) if (intel_engine_has_waiter(engine)) return true; @@ -1257,20 +1258,20 @@ static void ilk_gt_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) { if (gt_iir & GT_RENDER_USER_INTERRUPT) - notify_ring(&dev_priv->engine[RCS]); + notify_ring(dev_priv->engine[RCS]); if (gt_iir & ILK_BSD_USER_INTERRUPT) - notify_ring(&dev_priv->engine[VCS]); + notify_ring(dev_priv->engine[VCS]); } static void snb_gt_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) { if (gt_iir & GT_RENDER_USER_INTERRUPT) - notify_ring(&dev_priv->engine[RCS]); + notify_ring(dev_priv->engine[RCS]); if (gt_iir & GT_BSD_USER_INTERRUPT) - notify_ring(&dev_priv->engine[VCS]); + notify_ring(dev_priv->engine[VCS]); if (gt_iir & GT_BLT_USER_INTERRUPT) - notify_ring(&dev_priv->engine[BCS]); + notify_ring(dev_priv->engine[BCS]); if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | GT_BSD_CS_ERROR_INTERRUPT | @@ -1340,21 +1341,21 @@ static void gen8_gt_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir[4]) { if (gt_iir[0]) { - gen8_cs_irq_handler(&dev_priv->engine[RCS], + gen8_cs_irq_handler(dev_priv->engine[RCS], gt_iir[0], GEN8_RCS_IRQ_SHIFT); - gen8_cs_irq_handler(&dev_priv->engine[BCS], + gen8_cs_irq_handler(dev_priv->engine[BCS], gt_iir[0], GEN8_BCS_IRQ_SHIFT); } if (gt_iir[1]) { - gen8_cs_irq_handler(&dev_priv->engine[VCS], + gen8_cs_irq_handler(dev_priv->engine[VCS], gt_iir[1], GEN8_VCS1_IRQ_SHIFT); - gen8_cs_irq_handler(&dev_priv->engine[VCS2], + gen8_cs_irq_handler(dev_priv->engine[VCS2], gt_iir[1], GEN8_VCS2_IRQ_SHIFT); } if (gt_iir[3]) - gen8_cs_irq_handler(&dev_priv->engine[VECS], + gen8_cs_irq_handler(dev_priv->engine[VECS], gt_iir[3], GEN8_VECS_IRQ_SHIFT); if (gt_iir[2] & dev_priv->pm_rps_events) @@ -1598,7 +1599,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) if (HAS_VEBOX(dev_priv)) { if (pm_iir & PM_VEBOX_USER_INTERRUPT) - notify_ring(&dev_priv->engine[VECS]); + notify_ring(dev_priv->engine[VECS]); if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); @@ -2588,7 +2589,7 @@ static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) pr_err("render error detected, EIR: 0x%08x\n", eir); - intel_engine_get_instdone(&dev_priv->engine[RCS], &instdone); + intel_engine_get_instdone(dev_priv->engine[RCS], &instdone); if (IS_G4X(dev_priv)) { if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) { @@ -2833,9 +2834,10 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, { struct drm_i915_private *dev_priv = engine->i915; struct intel_engine_cs *signaller; + enum intel_engine_id id; if (INTEL_GEN(dev_priv) >= 8) { - for_each_engine(signaller, dev_priv) { + for_each_engine(signaller, dev_priv, id) { if (engine == signaller) continue; @@ -2845,7 +2847,7 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, } else { u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; - for_each_engine(signaller, dev_priv) { + for_each_engine(signaller, dev_priv, id) { if(engine == signaller) continue; @@ -2966,8 +2968,9 @@ static int semaphore_passed(struct intel_engine_cs *engine) static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) engine->hangcheck.deadlock = 0; } @@ -3094,6 +3097,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) container_of(work, typeof(*dev_priv), gpu_error.hangcheck_work.work); struct intel_engine_cs *engine; + enum intel_engine_id id; unsigned int hung = 0, stuck = 0; int busy_count = 0; #define BUSY 1 @@ -3113,7 +3117,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) */ intel_uncore_arm_unclaimed_mmio_detection(dev_priv); - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { bool busy = intel_engine_has_waiter(engine); u64 acthd; u32 seqno; @@ -4004,7 +4008,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) new_iir = I915_READ16(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(&dev_priv->engine[RCS]); + notify_ring(dev_priv->engine[RCS]); for_each_pipe(dev_priv, pipe) { int plane = pipe; @@ -4201,7 +4205,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(&dev_priv->engine[RCS]); + notify_ring(dev_priv->engine[RCS]); for_each_pipe(dev_priv, pipe) { int plane = pipe; @@ -4433,9 +4437,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(&dev_priv->engine[RCS]); + notify_ring(dev_priv->engine[RCS]); if (iir & I915_BSD_USER_INTERRUPT) - notify_ring(&dev_priv->engine[VCS]); + notify_ring(dev_priv->engine[VCS]); for_each_pipe(dev_priv, pipe) { if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 495611b7068d..23fc1042fed4 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -621,6 +621,7 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) unsigned int intel_kick_waiters(struct drm_i915_private *i915) { struct intel_engine_cs *engine; + enum intel_engine_id id; unsigned int mask = 0; /* To avoid the task_struct disappearing beneath us as we wake up @@ -628,7 +629,7 @@ unsigned int intel_kick_waiters(struct drm_i915_private *i915) * RCU lock, i.e. as we call wake_up_process() we must be holding the * rcu_read_lock(). */ - for_each_engine(engine, i915) + for_each_engine(engine, i915, id) if (unlikely(intel_engine_wakeup(engine))) mask |= intel_engine_flag(engine); @@ -638,9 +639,10 @@ unsigned int intel_kick_waiters(struct drm_i915_private *i915) unsigned int intel_kick_signalers(struct drm_i915_private *i915) { struct intel_engine_cs *engine; + enum intel_engine_id id; unsigned int mask = 0; - for_each_engine(engine, i915) { + for_each_engine(engine, i915, id) { if (unlikely(READ_ONCE(engine->breadcrumbs.first_signal))) { wake_up_process(engine->breadcrumbs.signaler); mask |= intel_engine_flag(engine); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cfcb03f82016..645a779b7ea4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12243,19 +12243,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1; if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { - engine = &dev_priv->engine[BCS]; + engine = dev_priv->engine[BCS]; if (fb->modifier[0] != old_fb->modifier[0]) /* vlv: DISPLAY_FLIP fails to change tiling */ engine = NULL; } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { - engine = &dev_priv->engine[BCS]; + engine = dev_priv->engine[BCS]; } else if (INTEL_INFO(dev)->gen >= 7) { engine = i915_gem_active_get_engine(&obj->last_write, &obj->base.dev->struct_mutex); if (engine == NULL || engine->id != RCS) - engine = &dev_priv->engine[BCS]; + engine = dev_priv->engine[BCS]; } else { - engine = &dev_priv->engine[RCS]; + engine = dev_priv->engine[RCS]; } mmio_flip = use_mmio_flip(engine, obj); diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 1d597feba97f..fba6edd9f819 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -82,12 +82,17 @@ static const struct engine_info { }, }; -static struct intel_engine_cs * +static int intel_engine_setup(struct drm_i915_private *dev_priv, enum intel_engine_id id) { const struct engine_info *info = &intel_engines[id]; - struct intel_engine_cs *engine = &dev_priv->engine[id]; + struct intel_engine_cs *engine; + + GEM_BUG_ON(dev_priv->engine[id]); + engine = kzalloc(sizeof(*engine), GFP_KERNEL); + if (!engine) + return -ENOMEM; engine->id = id; engine->i915 = dev_priv; @@ -97,7 +102,8 @@ intel_engine_setup(struct drm_i915_private *dev_priv, engine->mmio_base = info->mmio_base; engine->irq_shift = info->irq_shift; - return engine; + dev_priv->engine[id] = engine; + return 0; } /** @@ -112,6 +118,8 @@ int intel_engines_init(struct drm_device *dev) struct intel_device_info *device_info = mkwrite_device_info(dev_priv); unsigned int mask = 0; int (*init)(struct intel_engine_cs *engine); + struct intel_engine_cs *engine; + enum intel_engine_id id; unsigned int i; int ret; @@ -131,7 +139,11 @@ int intel_engines_init(struct drm_device *dev) if (!init) continue; - ret = init(intel_engine_setup(dev_priv, i)); + ret = intel_engine_setup(dev_priv, i); + if (ret) + goto cleanup; + + ret = init(dev_priv->engine[i]); if (ret) goto cleanup; @@ -151,11 +163,11 @@ int intel_engines_init(struct drm_device *dev) return 0; cleanup: - for (i = 0; i < I915_NUM_ENGINES; i++) { + for_each_engine(engine, dev_priv, id) { if (i915.enable_execlists) - intel_logical_ring_cleanup(&dev_priv->engine[i]); + intel_logical_ring_cleanup(engine); else - intel_engine_cleanup(&dev_priv->engine[i]); + intel_engine_cleanup(engine); } return ret; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 7ace96be82a8..95c6751d598d 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -100,12 +100,13 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) static void guc_interrupts_release(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; int irqs; /* tell all command streamers NOT to forward interrupts or vblank to GuC */ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) I915_WRITE(RING_MODE_GEN7(engine), irqs); /* route all GT interrupts to the host */ @@ -117,12 +118,13 @@ static void guc_interrupts_release(struct drm_i915_private *dev_priv) static void guc_interrupts_capture(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; int irqs; u32 tmp; /* tell all command streamers to forward interrupts (but not vblank) to GuC */ irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) I915_WRITE(RING_MODE_GEN7(engine), irqs); /* route USER_INTERRUPT to Host, all others are sent to GuC. */ diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 10fcea57e4dd..bc86585b9fbb 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1648,9 +1648,6 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv; - if (!intel_engine_initialized(engine)) - return; - /* * Tasklet cannot be active at this point due intel_mark_active/idle * so this is just for documentation. @@ -1677,13 +1674,16 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) lrc_destroy_wa_ctx_obj(engine); engine->i915 = NULL; + dev_priv->engine[engine->id] = NULL; + kfree(engine); } void intel_execlists_enable_submission(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) engine->submit_request = execlists_submit_request; } @@ -2151,6 +2151,7 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; struct i915_gem_context *ctx; + enum intel_engine_id id; /* Because we emit WA_TAIL_DWORDS there may be a disparity * between our bookkeeping in ce->ring->head and ce->ring->tail and @@ -2163,7 +2164,7 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv) * simplicity, we just zero everything out. */ list_for_each_entry(ctx, &dev_priv->context_list, link) { - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { struct intel_context *ce = &ctx->engine[engine->id]; u32 *reg; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 8c411bfc3b3f..25bcd4a178d3 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -233,7 +233,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, static struct drm_i915_gem_request *alloc_request(struct intel_overlay *overlay) { struct drm_i915_private *dev_priv = overlay->i915; - struct intel_engine_cs *engine = &dev_priv->engine[RCS]; + struct intel_engine_cs *engine = dev_priv->engine[RCS]; return i915_gem_request_alloc(engine, dev_priv->kernel_context); } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 38081387802d..15f21c6eb4f4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5367,6 +5367,7 @@ static void gen9_enable_rps(struct drm_i915_private *dev_priv) static void gen9_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; uint32_t rc6_mask = 0; /* 1a: Software RC state - RC0 */ @@ -5388,7 +5389,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16); I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); if (HAS_GUC(dev_priv)) @@ -5433,6 +5434,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) static void gen8_enable_rps(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; uint32_t rc6_mask = 0; /* 1a: Software RC state - RC0 */ @@ -5449,7 +5451,7 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); if (IS_BROADWELL(dev_priv)) @@ -5509,6 +5511,7 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv) static void gen6_enable_rps(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; u32 rc6vids, rc6_mask = 0; u32 gtfifodbg; int rc6_mode; @@ -5542,7 +5545,7 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); @@ -5991,6 +5994,7 @@ static void valleyview_cleanup_gt_powersave(struct drm_i915_private *dev_priv) static void cherryview_enable_rps(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; u32 gtfifodbg, val, rc6_mode = 0, pcbr; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); @@ -6017,7 +6021,7 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); @@ -6079,6 +6083,7 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv) static void valleyview_enable_rps(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; u32 gtfifodbg, val, rc6_mode = 0; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); @@ -6118,7 +6123,7 @@ static void valleyview_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv, id) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); @@ -6801,7 +6806,7 @@ static void __intel_autoenable_gt_powersave(struct work_struct *work) if (READ_ONCE(dev_priv->rps.enabled)) goto out; - rcs = &dev_priv->engine[RCS]; + rcs = dev_priv->engine[RCS]; if (rcs->last_context) goto out; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 729f373782e2..e107455b0168 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1228,7 +1228,7 @@ static int gen8_rcs_signal(struct drm_i915_gem_request *req) if (ret) return ret; - for_each_engine_id(waiter, dev_priv, id) { + for_each_engine(waiter, dev_priv, id) { u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) continue; @@ -1265,7 +1265,7 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *req) if (ret) return ret; - for_each_engine_id(waiter, dev_priv, id) { + for_each_engine(waiter, dev_priv, id) { u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) continue; @@ -1292,6 +1292,7 @@ static int gen6_signal(struct drm_i915_gem_request *req) struct intel_ring *ring = req->ring; struct drm_i915_private *dev_priv = req->i915; struct intel_engine_cs *engine; + enum intel_engine_id id; int ret, num_rings; num_rings = INTEL_INFO(dev_priv)->num_rings; @@ -1299,7 +1300,7 @@ static int gen6_signal(struct drm_i915_gem_request *req) if (ret) return ret; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { i915_reg_t mbox_reg; if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK)) @@ -2091,9 +2092,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv; - if (!intel_engine_initialized(engine)) - return; - dev_priv = engine->i915; if (engine->buffer) { @@ -2120,13 +2118,16 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) intel_ring_context_unpin(dev_priv->kernel_context, engine); engine->i915 = NULL; + dev_priv->engine[engine->id] = NULL; + kfree(engine); } void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv) { + for_each_engine(engine, dev_priv, id) { engine->buffer->head = engine->buffer->tail; engine->buffer->last_retired_head = -1; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 36eff9765cc2..32b2e6332ccf 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -395,12 +395,6 @@ struct intel_engine_cs { u32 (*get_cmd_length_mask)(u32 cmd_header); }; -static inline bool -intel_engine_initialized(const struct intel_engine_cs *engine) -{ - return engine->i915 != NULL; -} - static inline unsigned intel_engine_flag(const struct intel_engine_cs *engine) { @@ -421,7 +415,7 @@ intel_engine_sync_index(struct intel_engine_cs *engine, * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs; */ - idx = (other - engine) - 1; + idx = (other->id - engine->id) - 1; if (idx < 0) idx += I915_NUM_ENGINES; -- cgit v1.2.3 From 28a60dee2ce6021fa6b304bc6761b71120635ad8 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 2 Sep 2016 12:41:29 +0800 Subject: drm/i915/gvt: vGPU HW resource management This patch introduces the GVT-g vGPU HW resource management. Under GVT-g virtualizaion environment, each vGPU requires portions HW resources, including aperture, hidden GM space, and fence registers. When creating a vGPU, GVT-g will request these HW resources from host, and return them to host after a vGPU is destroyed. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/aperture_gm.c | 341 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/debug.h | 3 + drivers/gpu/drm/i915/gvt/gvt.c | 5 +- drivers/gpu/drm/i915/gvt/gvt.h | 89 +++++++++ drivers/gpu/drm/i915/intel_gvt.h | 1 + 6 files changed, 439 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/aperture_gm.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index d0f21a6ad60d..867910902b82 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,5 +1,5 @@ GVT_DIR := gvt -GVT_SOURCE := gvt.o +GVT_SOURCE := gvt.o aperture_gm.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c new file mode 100644 index 000000000000..e0211f83bd93 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -0,0 +1,341 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Kevin Tian + * Dexuan Cui + * + * Contributors: + * Pei Zhang + * Min He + * Niu Bing + * Yulei Zhang + * Zhenyu Wang + * Zhi Wang + * + */ + +#include "i915_drv.h" + +#define MB_TO_BYTES(mb) ((mb) << 20ULL) +#define BYTES_TO_MB(b) ((b) >> 20ULL) + +#define HOST_LOW_GM_SIZE MB_TO_BYTES(128) +#define HOST_HIGH_GM_SIZE MB_TO_BYTES(384) +#define HOST_FENCE 4 + +static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct drm_i915_private *dev_priv = gvt->dev_priv; + u32 alloc_flag, search_flag; + u64 start, end, size; + struct drm_mm_node *node; + int retried = 0; + int ret; + + if (high_gm) { + search_flag = DRM_MM_SEARCH_BELOW; + alloc_flag = DRM_MM_CREATE_TOP; + node = &vgpu->gm.high_gm_node; + size = vgpu_hidden_sz(vgpu); + start = gvt_hidden_gmadr_base(gvt); + end = gvt_hidden_gmadr_end(gvt); + } else { + search_flag = DRM_MM_SEARCH_DEFAULT; + alloc_flag = DRM_MM_CREATE_DEFAULT; + node = &vgpu->gm.low_gm_node; + size = vgpu_aperture_sz(vgpu); + start = gvt_aperture_gmadr_base(gvt); + end = gvt_aperture_gmadr_end(gvt); + } + + mutex_lock(&dev_priv->drm.struct_mutex); +search_again: + ret = drm_mm_insert_node_in_range_generic(&dev_priv->ggtt.base.mm, + node, size, 4096, 0, + start, end, search_flag, + alloc_flag); + if (ret) { + ret = i915_gem_evict_something(&dev_priv->ggtt.base, + size, 4096, 0, start, end, 0); + if (ret == 0 && ++retried < 3) + goto search_again; + + gvt_err("fail to alloc %s gm space from host, retried %d\n", + high_gm ? "high" : "low", retried); + } + mutex_unlock(&dev_priv->drm.struct_mutex); + return ret; +} + +static int alloc_vgpu_gm(struct intel_vgpu *vgpu) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct drm_i915_private *dev_priv = gvt->dev_priv; + int ret; + + ret = alloc_gm(vgpu, false); + if (ret) + return ret; + + ret = alloc_gm(vgpu, true); + if (ret) + goto out_free_aperture; + + gvt_dbg_core("vgpu%d: alloc low GM start %llx size %llx\n", vgpu->id, + vgpu_aperture_offset(vgpu), vgpu_aperture_sz(vgpu)); + + gvt_dbg_core("vgpu%d: alloc high GM start %llx size %llx\n", vgpu->id, + vgpu_hidden_offset(vgpu), vgpu_hidden_sz(vgpu)); + + return 0; +out_free_aperture: + mutex_lock(&dev_priv->drm.struct_mutex); + drm_mm_remove_node(&vgpu->gm.low_gm_node); + mutex_unlock(&dev_priv->drm.struct_mutex); + return ret; +} + +static void free_vgpu_gm(struct intel_vgpu *vgpu) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + + mutex_lock(&dev_priv->drm.struct_mutex); + drm_mm_remove_node(&vgpu->gm.low_gm_node); + drm_mm_remove_node(&vgpu->gm.high_gm_node); + mutex_unlock(&dev_priv->drm.struct_mutex); +} + +/** + * intel_vgpu_write_fence - write fence registers owned by a vGPU + * @vgpu: vGPU instance + * @fence: vGPU fence register number + * @value: Fence register value to be written + * + * This function is used to write fence registers owned by a vGPU. The vGPU + * fence register number will be translated into HW fence register number. + * + */ +void intel_vgpu_write_fence(struct intel_vgpu *vgpu, + u32 fence, u64 value) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct drm_i915_private *dev_priv = gvt->dev_priv; + struct drm_i915_fence_reg *reg; + i915_reg_t fence_reg_lo, fence_reg_hi; + + if (WARN_ON(fence > vgpu_fence_sz(vgpu))) + return; + + reg = vgpu->fence.regs[fence]; + if (WARN_ON(!reg)) + return; + + fence_reg_lo = FENCE_REG_GEN6_LO(reg->id); + fence_reg_hi = FENCE_REG_GEN6_HI(reg->id); + + I915_WRITE(fence_reg_lo, 0); + POSTING_READ(fence_reg_lo); + + I915_WRITE(fence_reg_hi, upper_32_bits(value)); + I915_WRITE(fence_reg_lo, lower_32_bits(value)); + POSTING_READ(fence_reg_lo); +} + +static void free_vgpu_fence(struct intel_vgpu *vgpu) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct drm_i915_private *dev_priv = gvt->dev_priv; + struct drm_i915_fence_reg *reg; + u32 i; + + if (WARN_ON(!vgpu_fence_sz(vgpu))) + return; + + mutex_lock(&dev_priv->drm.struct_mutex); + for (i = 0; i < vgpu_fence_sz(vgpu); i++) { + reg = vgpu->fence.regs[i]; + intel_vgpu_write_fence(vgpu, i, 0); + list_add_tail(®->link, + &dev_priv->mm.fence_list); + } + mutex_unlock(&dev_priv->drm.struct_mutex); +} + +static int alloc_vgpu_fence(struct intel_vgpu *vgpu) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct drm_i915_private *dev_priv = gvt->dev_priv; + struct drm_i915_fence_reg *reg; + int i; + struct list_head *pos, *q; + + /* Request fences from host */ + mutex_lock(&dev_priv->drm.struct_mutex); + i = 0; + list_for_each_safe(pos, q, &dev_priv->mm.fence_list) { + reg = list_entry(pos, struct drm_i915_fence_reg, link); + if (reg->pin_count || reg->vma) + continue; + list_del(pos); + vgpu->fence.regs[i] = reg; + intel_vgpu_write_fence(vgpu, i, 0); + if (++i == vgpu_fence_sz(vgpu)) + break; + } + if (i != vgpu_fence_sz(vgpu)) + goto out_free_fence; + + mutex_unlock(&dev_priv->drm.struct_mutex); + return 0; +out_free_fence: + /* Return fences to host, if fail */ + for (i = 0; i < vgpu_fence_sz(vgpu); i++) { + reg = vgpu->fence.regs[i]; + if (!reg) + continue; + list_add_tail(®->link, + &dev_priv->mm.fence_list); + } + mutex_unlock(&dev_priv->drm.struct_mutex); + return -ENOSPC; +} + +static void free_resource(struct intel_vgpu *vgpu) +{ + struct intel_gvt *gvt = vgpu->gvt; + + gvt->gm.vgpu_allocated_low_gm_size -= vgpu_aperture_sz(vgpu); + gvt->gm.vgpu_allocated_high_gm_size -= vgpu_hidden_sz(vgpu); + gvt->fence.vgpu_allocated_fence_num -= vgpu_fence_sz(vgpu); +} + +static int alloc_resource(struct intel_vgpu *vgpu, + struct intel_vgpu_creation_params *param) +{ + struct intel_gvt *gvt = vgpu->gvt; + unsigned long request, avail, max, taken; + const char *item; + + if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) { + gvt_err("Invalid vGPU creation params\n"); + return -EINVAL; + } + + item = "low GM space"; + max = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE; + taken = gvt->gm.vgpu_allocated_low_gm_size; + avail = max - taken; + request = MB_TO_BYTES(param->low_gm_sz); + + if (request > avail) + goto no_enough_resource; + + vgpu_aperture_sz(vgpu) = request; + + item = "high GM space"; + max = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE; + taken = gvt->gm.vgpu_allocated_high_gm_size; + avail = max - taken; + request = MB_TO_BYTES(param->high_gm_sz); + + if (request > avail) + goto no_enough_resource; + + vgpu_hidden_sz(vgpu) = request; + + item = "fence"; + max = gvt_fence_sz(gvt) - HOST_FENCE; + taken = gvt->fence.vgpu_allocated_fence_num; + avail = max - taken; + request = param->fence_sz; + + if (request > avail) + goto no_enough_resource; + + vgpu_fence_sz(vgpu) = request; + + gvt->gm.vgpu_allocated_low_gm_size += MB_TO_BYTES(param->low_gm_sz); + gvt->gm.vgpu_allocated_high_gm_size += MB_TO_BYTES(param->high_gm_sz); + gvt->fence.vgpu_allocated_fence_num += param->fence_sz; + return 0; + +no_enough_resource: + gvt_err("vgpu%d: fail to allocate resource %s\n", vgpu->id, item); + gvt_err("vgpu%d: request %luMB avail %luMB max %luMB taken %luMB\n", + vgpu->id, BYTES_TO_MB(request), BYTES_TO_MB(avail), + BYTES_TO_MB(max), BYTES_TO_MB(taken)); + return -ENOSPC; +} + +/** + * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU + * @vgpu: a vGPU + * + * This function is used to free the HW resource owned by a vGPU. + * + */ +void intel_vgpu_free_resource(struct intel_vgpu *vgpu) +{ + free_vgpu_gm(vgpu); + free_vgpu_fence(vgpu); + free_resource(vgpu); +} + +/** + * intel_alloc_vgpu_resource - allocate HW resource for a vGPU + * @vgpu: vGPU + * @param: vGPU creation params + * + * This function is used to allocate HW resource for a vGPU. User specifies + * the resource configuration through the creation params. + * + * Returns: + * zero on success, negative error code if failed. + * + */ +int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu, + struct intel_vgpu_creation_params *param) +{ + int ret; + + ret = alloc_resource(vgpu, param); + if (ret) + return ret; + + ret = alloc_vgpu_gm(vgpu); + if (ret) + goto out_free_resource; + + ret = alloc_vgpu_fence(vgpu); + if (ret) + goto out_free_vgpu_gm; + + return 0; + +out_free_vgpu_gm: + free_vgpu_gm(vgpu); +out_free_resource: + free_resource(vgpu); + return ret; +} diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index 7ef412be665f..f9f0923feb9e 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -24,6 +24,9 @@ #ifndef __GVT_DEBUG_H__ #define __GVT_DEBUG_H__ +#define gvt_err(fmt, args...) \ + DRM_ERROR("gvt: "fmt, ##args) + #define gvt_dbg_core(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args) diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 927f4579f5b6..6ec5b937af63 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -84,7 +84,7 @@ int intel_gvt_init_host(void) static void init_device_info(struct intel_gvt *gvt) { - if (IS_BROADWELL(gvt->dev_priv)) + if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) gvt->device_info.max_support_vgpus = 8; /* This function will grow large in GVT device model patches. */ } @@ -135,6 +135,9 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) gvt_dbg_core("init gvt device\n"); + mutex_init(&gvt->lock); + gvt->dev_priv = dev_priv; + init_device_info(gvt); /* * Other initialization of GVT components will be introduce here. diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index fb619a6e519d..f42cdf74d577 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -48,10 +48,39 @@ struct intel_gvt_device_info { /* This data structure will grow bigger in GVT device model patches */ }; +/* GM resources owned by a vGPU */ +struct intel_vgpu_gm { + u64 aperture_sz; + u64 hidden_sz; + struct drm_mm_node low_gm_node; + struct drm_mm_node high_gm_node; +}; + +#define INTEL_GVT_MAX_NUM_FENCES 32 + +/* Fences owned by a vGPU */ +struct intel_vgpu_fence { + struct drm_i915_fence_reg *regs[INTEL_GVT_MAX_NUM_FENCES]; + u32 base; + u32 size; +}; + struct intel_vgpu { struct intel_gvt *gvt; int id; unsigned long handle; /* vGPU handle used by hypervisor MPT modules */ + + struct intel_vgpu_fence fence; + struct intel_vgpu_gm gm; +}; + +struct intel_gvt_gm { + unsigned long vgpu_allocated_low_gm_size; + unsigned long vgpu_allocated_high_gm_size; +}; + +struct intel_gvt_fence { + unsigned long vgpu_allocated_fence_num; }; struct intel_gvt { @@ -62,8 +91,68 @@ struct intel_gvt { struct idr vgpu_idr; /* vGPU IDR pool */ struct intel_gvt_device_info device_info; + struct intel_gvt_gm gm; + struct intel_gvt_fence fence; }; +/* Aperture/GM space definitions for GVT device */ +#define gvt_aperture_sz(gvt) (gvt->dev_priv->ggtt.mappable_end) +#define gvt_aperture_pa_base(gvt) (gvt->dev_priv->ggtt.mappable_base) + +#define gvt_ggtt_gm_sz(gvt) (gvt->dev_priv->ggtt.base.total) +#define gvt_hidden_sz(gvt) (gvt_ggtt_gm_sz(gvt) - gvt_aperture_sz(gvt)) + +#define gvt_aperture_gmadr_base(gvt) (0) +#define gvt_aperture_gmadr_end(gvt) (gvt_aperture_gmadr_base(gvt) \ + + gvt_aperture_sz(gvt) - 1) + +#define gvt_hidden_gmadr_base(gvt) (gvt_aperture_gmadr_base(gvt) \ + + gvt_aperture_sz(gvt)) +#define gvt_hidden_gmadr_end(gvt) (gvt_hidden_gmadr_base(gvt) \ + + gvt_hidden_sz(gvt) - 1) + +#define gvt_fence_sz(gvt) (gvt->dev_priv->num_fence_regs) + +/* Aperture/GM space definitions for vGPU */ +#define vgpu_aperture_offset(vgpu) ((vgpu)->gm.low_gm_node.start) +#define vgpu_hidden_offset(vgpu) ((vgpu)->gm.high_gm_node.start) +#define vgpu_aperture_sz(vgpu) ((vgpu)->gm.aperture_sz) +#define vgpu_hidden_sz(vgpu) ((vgpu)->gm.hidden_sz) + +#define vgpu_aperture_pa_base(vgpu) \ + (gvt_aperture_pa_base(vgpu->gvt) + vgpu_aperture_offset(vgpu)) + +#define vgpu_ggtt_gm_sz(vgpu) ((vgpu)->gm.aperture_sz + (vgpu)->gm.hidden_sz) + +#define vgpu_aperture_pa_end(vgpu) \ + (vgpu_aperture_pa_base(vgpu) + vgpu_aperture_sz(vgpu) - 1) + +#define vgpu_aperture_gmadr_base(vgpu) (vgpu_aperture_offset(vgpu)) +#define vgpu_aperture_gmadr_end(vgpu) \ + (vgpu_aperture_gmadr_base(vgpu) + vgpu_aperture_sz(vgpu) - 1) + +#define vgpu_hidden_gmadr_base(vgpu) (vgpu_hidden_offset(vgpu)) +#define vgpu_hidden_gmadr_end(vgpu) \ + (vgpu_hidden_gmadr_base(vgpu) + vgpu_hidden_sz(vgpu) - 1) + +#define vgpu_fence_base(vgpu) (vgpu->fence.base) +#define vgpu_fence_sz(vgpu) (vgpu->fence.size) + +struct intel_vgpu_creation_params { + __u64 handle; + __u64 low_gm_sz; /* in MB */ + __u64 high_gm_sz; /* in MB */ + __u64 fence_sz; + __s32 primary; + __u64 vgpu_id; +}; + +int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu, + struct intel_vgpu_creation_params *param); +void intel_vgpu_free_resource(struct intel_vgpu *vgpu); +void intel_vgpu_write_fence(struct intel_vgpu *vgpu, + u32 fence, u64 value); + #include "mpt.h" #endif diff --git a/drivers/gpu/drm/i915/intel_gvt.h b/drivers/gpu/drm/i915/intel_gvt.h index 960211df74db..0f00105f4c5d 100644 --- a/drivers/gpu/drm/i915/intel_gvt.h +++ b/drivers/gpu/drm/i915/intel_gvt.h @@ -24,6 +24,7 @@ #ifndef _INTEL_GVT_H_ #define _INTEL_GVT_H_ +#include "i915_pvinfo.h" #include "gvt/gvt.h" #ifdef CONFIG_DRM_I915_GVT -- cgit v1.2.3 From 12d14cc43b34706283246917329b2182163ba9aa Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Tue, 30 Aug 2016 11:06:17 +0800 Subject: drm/i915/gvt: Introduce a framework for tracking HW registers. This patch introduces a framework for tracking HW registers on different GEN platforms. Accesses to GEN HW registers from VMs will be trapped by hypervisor. It will forward these emulation requests to GVT-g device model, which requires this framework to search for related register descriptions. Each MMIO entry in this framework describes a GEN HW registers, e.g. offset, length, whether it contains RO bits, whether it can be accessed by LRIs...and also emulation handlers for emulating register reading and writing. - Use i915 MMIO register definition & statement.(Joonas) Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/gvt.c | 30 ++++- drivers/gpu/drm/i915/gvt/gvt.h | 20 ++- drivers/gpu/drm/i915/gvt/handlers.c | 247 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/mmio.h | 89 +++++++++++++ 5 files changed, 379 insertions(+), 9 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/handlers.c create mode 100644 drivers/gpu/drm/i915/gvt/mmio.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 867910902b82..61b5b61f01f5 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,5 +1,5 @@ GVT_DIR := gvt -GVT_SOURCE := gvt.o aperture_gm.o +GVT_SOURCE := gvt.o aperture_gm.o handlers.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 6ec5b937af63..9f5c9bd83bc9 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -19,6 +19,15 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. + * + * Authors: + * Kevin Tian + * Eddie Dong + * + * Contributors: + * Niu Bing + * Zhi Wang + * */ #include @@ -84,9 +93,12 @@ int intel_gvt_init_host(void) static void init_device_info(struct intel_gvt *gvt) { - if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) - gvt->device_info.max_support_vgpus = 8; - /* This function will grow large in GVT device model patches. */ + struct intel_gvt_device_info *info = &gvt->device_info; + + if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { + info->max_support_vgpus = 8; + info->mmio_size = 2 * 1024 * 1024; + } } /** @@ -104,7 +116,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) if (WARN_ON(!gvt->initialized)) return; - /* Other de-initialization of GVT components will be introduced. */ + intel_gvt_clean_mmio_info(gvt); gvt->initialized = false; } @@ -123,6 +135,8 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) int intel_gvt_init_device(struct drm_i915_private *dev_priv) { struct intel_gvt *gvt = &dev_priv->gvt; + int ret; + /* * Cannot initialize GVT device without intel_gvt_host gets * initialized first. @@ -139,9 +153,11 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) gvt->dev_priv = dev_priv; init_device_info(gvt); - /* - * Other initialization of GVT components will be introduce here. - */ + + ret = intel_gvt_setup_mmio_info(gvt); + if (ret) + return ret; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index f42cdf74d577..024ad97eba12 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -19,6 +19,15 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. + * + * Authors: + * Kevin Tian + * Eddie Dong + * + * Contributors: + * Niu Bing + * Zhi Wang + * */ #ifndef _GVT_H_ @@ -26,6 +35,7 @@ #include "debug.h" #include "hypercall.h" +#include "mmio.h" #define GVT_MAX_VGPU 8 @@ -45,7 +55,7 @@ extern struct intel_gvt_host intel_gvt_host; /* Describe per-platform limitations. */ struct intel_gvt_device_info { u32 max_support_vgpus; - /* This data structure will grow bigger in GVT device model patches */ + u32 mmio_size; }; /* GM resources owned by a vGPU */ @@ -83,6 +93,13 @@ struct intel_gvt_fence { unsigned long vgpu_allocated_fence_num; }; +#define INTEL_GVT_MMIO_HASH_BITS 9 + +struct intel_gvt_mmio { + u32 *mmio_attribute; + DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS); +}; + struct intel_gvt { struct mutex lock; bool initialized; @@ -93,6 +110,7 @@ struct intel_gvt { struct intel_gvt_device_info device_info; struct intel_gvt_gm gm; struct intel_gvt_fence fence; + struct intel_gvt_mmio mmio; }; /* Aperture/GM space definitions for GVT device */ diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c new file mode 100644 index 000000000000..62222189906b --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -0,0 +1,247 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Kevin Tian + * Eddie Dong + * Zhiyuan Lv + * + * Contributors: + * Min He + * Tina Zhang + * Pei Zhang + * Niu Bing + * Ping Gao + * Zhi Wang + * + + */ + +#include "i915_drv.h" + +/* Register contains RO bits */ +#define F_RO (1 << 0) +/* Register contains graphics address */ +#define F_GMADR (1 << 1) +/* Mode mask registers with high 16 bits as the mask bits */ +#define F_MODE_MASK (1 << 2) +/* This reg can be accessed by GPU commands */ +#define F_CMD_ACCESS (1 << 3) +/* This reg has been accessed by a VM */ +#define F_ACCESSED (1 << 4) +/* This reg has been accessed through GPU commands */ +#define F_CMD_ACCESSED (1 << 5) +/* This reg could be accessed by unaligned address */ +#define F_UNALIGN (1 << 6) + +unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt) +{ + if (IS_BROADWELL(gvt->dev_priv)) + return D_BDW; + else if (IS_SKYLAKE(gvt->dev_priv)) + return D_SKL; + + return 0; +} + +bool intel_gvt_match_device(struct intel_gvt *gvt, + unsigned long device) +{ + return intel_gvt_get_device_type(gvt) & device; +} + +static int new_mmio_info(struct intel_gvt *gvt, + u32 offset, u32 flags, u32 size, + u32 addr_mask, u32 ro_mask, u32 device, + void *read, void *write) +{ + struct intel_gvt_mmio_info *info, *p; + u32 start, end, i; + + if (!intel_gvt_match_device(gvt, device)) + return 0; + + if (WARN_ON(!IS_ALIGNED(offset, 4))) + return -EINVAL; + + start = offset; + end = offset + size; + + for (i = start; i < end; i += 4) { + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->offset = i; + p = intel_gvt_find_mmio_info(gvt, info->offset); + if (p) + gvt_err("dup mmio definition offset %x\n", + info->offset); + info->size = size; + info->length = (i + 4) < end ? 4 : (end - i); + info->addr_mask = addr_mask; + info->device = device; + info->read = read; + info->write = write; + gvt->mmio.mmio_attribute[info->offset / 4] = flags; + INIT_HLIST_NODE(&info->node); + hash_add(gvt->mmio.mmio_info_table, &info->node, info->offset); + } + return 0; +} + +#define MMIO_F(reg, s, f, am, rm, d, r, w) do { \ + ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \ + f, s, am, rm, d, r, w); \ + if (ret) \ + return ret; \ +} while (0) + +#define MMIO_D(reg, d) \ + MMIO_F(reg, 4, 0, 0, 0, d, NULL, NULL) + +#define MMIO_DH(reg, d, r, w) \ + MMIO_F(reg, 4, 0, 0, 0, d, r, w) + +#define MMIO_DFH(reg, d, f, r, w) \ + MMIO_F(reg, 4, f, 0, 0, d, r, w) + +#define MMIO_GM(reg, d, r, w) \ + MMIO_F(reg, 4, F_GMADR, 0xFFFFF000, 0, d, r, w) + +#define MMIO_RO(reg, d, f, rm, r, w) \ + MMIO_F(reg, 4, F_RO | f, 0, rm, d, r, w) + +#define MMIO_RING_F(prefix, s, f, am, rm, d, r, w) do { \ + MMIO_F(prefix(RENDER_RING_BASE), s, f, am, rm, d, r, w); \ + MMIO_F(prefix(BLT_RING_BASE), s, f, am, rm, d, r, w); \ + MMIO_F(prefix(GEN6_BSD_RING_BASE), s, f, am, rm, d, r, w); \ + MMIO_F(prefix(VEBOX_RING_BASE), s, f, am, rm, d, r, w); \ +} while (0) + +#define MMIO_RING_D(prefix, d) \ + MMIO_RING_F(prefix, 4, 0, 0, 0, d, NULL, NULL) + +#define MMIO_RING_DFH(prefix, d, f, r, w) \ + MMIO_RING_F(prefix, 4, f, 0, 0, d, r, w) + +#define MMIO_RING_GM(prefix, d, r, w) \ + MMIO_RING_F(prefix, 4, F_GMADR, 0xFFFF0000, 0, d, r, w) + +#define MMIO_RING_RO(prefix, d, f, rm, r, w) \ + MMIO_RING_F(prefix, 4, F_RO | f, 0, rm, d, r, w) + +static int init_generic_mmio_info(struct intel_gvt *gvt) +{ + int ret; + + MMIO_F(0, 0, 0, 0, 0, D_ALL, NULL, NULL); + return 0; +} + +static int init_broadwell_mmio_info(struct intel_gvt *gvt) +{ + int ret; + + MMIO_F(0, 0, 0, 0, 0, D_ALL, NULL, NULL); + return 0; +} + +/** + * intel_gvt_find_mmio_info - find MMIO information entry by aligned offset + * @gvt: GVT device + * @offset: register offset + * + * This function is used to find the MMIO information entry from hash table + * + * Returns: + * pointer to MMIO information entry, NULL if not exists + */ +struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt, + unsigned int offset) +{ + struct intel_gvt_mmio_info *e; + + WARN_ON(!IS_ALIGNED(offset, 4)); + + hash_for_each_possible(gvt->mmio.mmio_info_table, e, node, offset) { + if (e->offset == offset) + return e; + } + return NULL; +} + +/** + * intel_gvt_clean_mmio_info - clean up MMIO information table for GVT device + * @gvt: GVT device + * + * This function is called at the driver unloading stage, to clean up the MMIO + * information table of GVT device + * + */ +void intel_gvt_clean_mmio_info(struct intel_gvt *gvt) +{ + struct hlist_node *tmp; + struct intel_gvt_mmio_info *e; + int i; + + hash_for_each_safe(gvt->mmio.mmio_info_table, i, tmp, e, node) + kfree(e); + + vfree(gvt->mmio.mmio_attribute); + gvt->mmio.mmio_attribute = NULL; +} + +/** + * intel_gvt_setup_mmio_info - setup MMIO information table for GVT device + * @gvt: GVT device + * + * This function is called at the initialization stage, to setup the MMIO + * information table for GVT device + * + * Returns: + * zero on success, negative if failed. + */ +int intel_gvt_setup_mmio_info(struct intel_gvt *gvt) +{ + struct intel_gvt_device_info *info = &gvt->device_info; + struct drm_i915_private *dev_priv = gvt->dev_priv; + int ret; + + gvt->mmio.mmio_attribute = vzalloc(info->mmio_size); + if (!gvt->mmio.mmio_attribute) + return -ENOMEM; + + ret = init_generic_mmio_info(gvt); + if (ret) + goto err; + + if (IS_BROADWELL(dev_priv)) { + ret = init_broadwell_mmio_info(gvt); + if (ret) + goto err; + } + return 0; +err: + intel_gvt_clean_mmio_info(gvt); + return ret; +} diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h new file mode 100644 index 000000000000..1fb1b49f912c --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/mmio.h @@ -0,0 +1,89 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ke Yu + * Kevin Tian + * Dexuan Cui + * + * Contributors: + * Tina Zhang + * Min He + * Niu Bing + * Zhi Wang + * + */ + +#ifndef _GVT_MMIO_H_ +#define _GVT_MMIO_H_ + +struct intel_gvt; +struct intel_vgpu; + +#define D_SNB (1 << 0) +#define D_IVB (1 << 1) +#define D_HSW (1 << 2) +#define D_BDW (1 << 3) +#define D_SKL (1 << 4) + +#define D_GEN9PLUS (D_SKL) +#define D_GEN8PLUS (D_BDW | D_SKL) +#define D_GEN75PLUS (D_HSW | D_BDW | D_SKL) +#define D_GEN7PLUS (D_IVB | D_HSW | D_BDW | D_SKL) + +#define D_SKL_PLUS (D_SKL) +#define D_BDW_PLUS (D_BDW | D_SKL) +#define D_HSW_PLUS (D_HSW | D_BDW | D_SKL) +#define D_IVB_PLUS (D_IVB | D_HSW | D_BDW | D_SKL) + +#define D_PRE_BDW (D_SNB | D_IVB | D_HSW) +#define D_PRE_SKL (D_SNB | D_IVB | D_HSW | D_BDW) +#define D_ALL (D_SNB | D_IVB | D_HSW | D_BDW | D_SKL) + +struct intel_gvt_mmio_info { + u32 offset; + u32 size; + u32 length; + u32 addr_mask; + u64 ro_mask; + u32 device; + int (*read)(struct intel_vgpu *, unsigned int, void *, unsigned int); + int (*write)(struct intel_vgpu *, unsigned int, void *, unsigned int); + u32 addr_range; + struct hlist_node node; +}; + +unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt); +bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device); + +int intel_gvt_setup_mmio_info(struct intel_gvt *gvt); +void intel_gvt_clean_mmio_info(struct intel_gvt *gvt); + +struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt, + unsigned int offset); +#define INTEL_GVT_MMIO_OFFSET(reg) ({ \ + typeof(reg) __reg = reg; \ + u32 *offset = (u32 *)&__reg; \ + *offset; \ +}) + +#endif -- cgit v1.2.3 From 579cea5f30f2c70215492e987bb439a3e50c6371 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Thu, 30 Jun 2016 12:45:34 -0400 Subject: drm/i915/gvt: golden virtual HW state management Each vGPU expects a golden virtual HW state, which is just the state after system is freshly powered on. GVT-g will try to load the golden virtual HW state via kernel firmware interface. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/firmware.c | 308 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/gvt.c | 11 ++ drivers/gpu/drm/i915/gvt/gvt.h | 12 ++ 4 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/gvt/firmware.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 61b5b61f01f5..ebbb90a6dca5 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,5 +1,5 @@ GVT_DIR := gvt -GVT_SOURCE := gvt.o aperture_gm.o handlers.o +GVT_SOURCE := gvt.o aperture_gm.o handlers.o firmware.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/firmware.c b/drivers/gpu/drm/i915/gvt/firmware.c new file mode 100644 index 000000000000..4578a4d69a09 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/firmware.c @@ -0,0 +1,308 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Zhi Wang + * + * Contributors: + * Changbin Du + * + */ + +#include +#include + +#include "i915_drv.h" + +#define FIRMWARE_VERSION (0x0) + +struct gvt_firmware_header { + u64 magic; + u32 crc32; /* protect the data after this field */ + u32 version; + u64 cfg_space_size; + u64 cfg_space_offset; /* offset in the file */ + u64 mmio_size; + u64 mmio_offset; /* offset in the file */ + unsigned char data[1]; +}; + +#define RD(offset) (readl(mmio + offset.reg)) +#define WR(v, offset) (writel(v, mmio + offset.reg)) + +static void bdw_forcewake_get(void *mmio) +{ + WR(_MASKED_BIT_DISABLE(0xffff), FORCEWAKE_MT); + + RD(ECOBUS); + + if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL) == 0, 50)) + gvt_err("fail to wait forcewake idle\n"); + + WR(_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL), FORCEWAKE_MT); + + if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL), 50)) + gvt_err("fail to wait forcewake ack\n"); + + if (wait_for((RD(GEN6_GT_THREAD_STATUS_REG) & + GEN6_GT_THREAD_STATUS_CORE_MASK) == 0, 50)) + gvt_err("fail to wait c0 wake up\n"); +} + +#undef RD +#undef WR + +#define dev_to_drm_minor(d) dev_get_drvdata((d)) + +static ssize_t +gvt_firmware_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t offset, size_t count) +{ + memcpy(buf, attr->private + offset, count); + return count; +} + +static struct bin_attribute firmware_attr = { + .attr = {.name = "gvt_firmware", .mode = (S_IRUSR)}, + .read = gvt_firmware_read, + .write = NULL, + .mmap = NULL, +}; + +static int expose_firmware_sysfs(struct intel_gvt *gvt, void *mmio) +{ + struct intel_gvt_device_info *info = &gvt->device_info; + struct pci_dev *pdev = gvt->dev_priv->drm.pdev; + struct intel_gvt_mmio_info *e; + struct gvt_firmware_header *h; + void *firmware; + void *p; + unsigned long size; + int i; + int ret; + + size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1; + firmware = vmalloc(size); + if (!firmware) + return -ENOMEM; + + h = firmware; + + h->magic = VGT_MAGIC; + h->version = FIRMWARE_VERSION; + h->cfg_space_size = info->cfg_space_size; + h->cfg_space_offset = offsetof(struct gvt_firmware_header, data); + h->mmio_size = info->mmio_size; + h->mmio_offset = h->cfg_space_offset + h->cfg_space_size; + + p = firmware + h->cfg_space_offset; + + for (i = 0; i < h->cfg_space_size; i += 4) + pci_read_config_dword(pdev, i, p + i); + + memcpy(gvt->firmware.cfg_space, p, info->cfg_space_size); + + p = firmware + h->mmio_offset; + + hash_for_each(gvt->mmio.mmio_info_table, i, e, node) { + int j; + + for (j = 0; j < e->length; j += 4) + *(u32 *)(p + e->offset + j) = + readl(mmio + e->offset + j); + } + + memcpy(gvt->firmware.mmio, p, info->mmio_size); + + firmware_attr.size = size; + firmware_attr.private = firmware; + + ret = device_create_bin_file(&pdev->dev, &firmware_attr); + if (ret) { + vfree(firmware); + return ret; + } + return 0; +} + +static void clean_firmware_sysfs(struct intel_gvt *gvt) +{ + struct pci_dev *pdev = gvt->dev_priv->drm.pdev; + + device_remove_bin_file(&pdev->dev, &firmware_attr); + vfree(firmware_attr.private); +} + +/** + * intel_gvt_free_firmware - free GVT firmware + * @gvt: intel gvt device + * + */ +void intel_gvt_free_firmware(struct intel_gvt *gvt) +{ + if (!gvt->firmware.firmware_loaded) + clean_firmware_sysfs(gvt); + + kfree(gvt->firmware.cfg_space); + kfree(gvt->firmware.mmio); +} + +static int verify_firmware(struct intel_gvt *gvt, + const struct firmware *fw) +{ + struct intel_gvt_device_info *info = &gvt->device_info; + struct drm_i915_private *dev_priv = gvt->dev_priv; + struct pci_dev *pdev = dev_priv->drm.pdev; + struct gvt_firmware_header *h; + unsigned long id, crc32_start; + const void *mem; + const char *item; + u64 file, request; + + h = (struct gvt_firmware_header *)fw->data; + + crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4; + mem = fw->data + crc32_start; + +#define VERIFY(s, a, b) do { \ + item = (s); file = (u64)(a); request = (u64)(b); \ + if ((a) != (b)) \ + goto invalid_firmware; \ +} while (0) + + VERIFY("magic number", h->magic, VGT_MAGIC); + VERIFY("version", h->version, FIRMWARE_VERSION); + VERIFY("crc32", h->crc32, crc32_le(0, mem, fw->size - crc32_start)); + VERIFY("cfg space size", h->cfg_space_size, info->cfg_space_size); + VERIFY("mmio size", h->mmio_size, info->mmio_size); + + mem = (fw->data + h->cfg_space_offset); + + id = *(u16 *)(mem + PCI_VENDOR_ID); + VERIFY("vender id", id, pdev->vendor); + + id = *(u16 *)(mem + PCI_DEVICE_ID); + VERIFY("device id", id, pdev->device); + + id = *(u8 *)(mem + PCI_REVISION_ID); + VERIFY("revision id", id, pdev->revision); + +#undef VERIFY + return 0; + +invalid_firmware: + gvt_dbg_core("Invalid firmware: %s [file] 0x%llx [request] 0x%llx\n", + item, file, request); + return -EINVAL; +} + +#define GVT_FIRMWARE_PATH "i915/gvt" + +/** + * intel_gvt_load_firmware - load GVT firmware + * @gvt: intel gvt device + * + */ +int intel_gvt_load_firmware(struct intel_gvt *gvt) +{ + struct intel_gvt_device_info *info = &gvt->device_info; + struct drm_i915_private *dev_priv = gvt->dev_priv; + struct pci_dev *pdev = dev_priv->drm.pdev; + struct intel_gvt_firmware *firmware = &gvt->firmware; + struct gvt_firmware_header *h; + const struct firmware *fw; + char *path; + void *mmio, *mem; + int ret; + + path = kmalloc(PATH_MAX, GFP_KERNEL); + if (!path) + return -ENOMEM; + + mem = kmalloc(info->cfg_space_size, GFP_KERNEL); + if (!mem) { + kfree(path); + return -ENOMEM; + } + + firmware->cfg_space = mem; + + mem = kmalloc(info->mmio_size, GFP_KERNEL); + if (!mem) { + kfree(path); + kfree(firmware->cfg_space); + return -ENOMEM; + } + + firmware->mmio = mem; + + mmio = pci_iomap(pdev, info->mmio_bar, info->mmio_size); + if (!mmio) { + kfree(path); + kfree(firmware->cfg_space); + kfree(firmware->mmio); + return -EINVAL; + } + + if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) + bdw_forcewake_get(mmio); + + sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%04x.golden_hw_state", + GVT_FIRMWARE_PATH, pdev->vendor, pdev->device, + pdev->revision); + + gvt_dbg_core("request hw state firmware %s...\n", path); + + ret = request_firmware(&fw, path, &dev_priv->drm.pdev->dev); + kfree(path); + + if (ret) + goto expose_firmware; + + gvt_dbg_core("success.\n"); + + ret = verify_firmware(gvt, fw); + if (ret) + goto out_free_fw; + + gvt_dbg_core("verified.\n"); + + h = (struct gvt_firmware_header *)fw->data; + + memcpy(firmware->cfg_space, fw->data + h->cfg_space_offset, + h->cfg_space_size); + memcpy(firmware->mmio, fw->data + h->mmio_offset, + h->mmio_size); + + release_firmware(fw); + firmware->firmware_loaded = true; + pci_iounmap(pdev, mmio); + return 0; + +out_free_fw: + release_firmware(fw); +expose_firmware: + expose_firmware_sysfs(gvt, mmio); + pci_iounmap(pdev, mmio); + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 9f5c9bd83bc9..2c03dad28718 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -98,6 +98,8 @@ static void init_device_info(struct intel_gvt *gvt) if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { info->max_support_vgpus = 8; info->mmio_size = 2 * 1024 * 1024; + info->cfg_space_size = 256; + info->mmio_bar = 0; } } @@ -117,6 +119,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) return; intel_gvt_clean_mmio_info(gvt); + intel_gvt_free_firmware(gvt); gvt->initialized = false; } @@ -158,7 +161,15 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (ret) return ret; + ret = intel_gvt_load_firmware(gvt); + if (ret) + goto out_clean_mmio_info; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; + +out_clean_mmio_info: + intel_gvt_clean_mmio_info(gvt); + return ret; } diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 024ad97eba12..e8759680e952 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -56,6 +56,8 @@ extern struct intel_gvt_host intel_gvt_host; struct intel_gvt_device_info { u32 max_support_vgpus; u32 mmio_size; + u32 cfg_space_size; + u32 mmio_bar; }; /* GM resources owned by a vGPU */ @@ -100,6 +102,12 @@ struct intel_gvt_mmio { DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS); }; +struct intel_gvt_firmware { + void *cfg_space; + void *mmio; + bool firmware_loaded; +}; + struct intel_gvt { struct mutex lock; bool initialized; @@ -111,8 +119,12 @@ struct intel_gvt { struct intel_gvt_gm gm; struct intel_gvt_fence fence; struct intel_gvt_mmio mmio; + struct intel_gvt_firmware firmware; }; +void intel_gvt_free_firmware(struct intel_gvt *gvt); +int intel_gvt_load_firmware(struct intel_gvt *gvt); + /* Aperture/GM space definitions for GVT device */ #define gvt_aperture_sz(gvt) (gvt->dev_priv->ggtt.mappable_end) #define gvt_aperture_pa_base(gvt) (gvt->dev_priv->ggtt.mappable_base) -- cgit v1.2.3 From 82d375d1b56820fd094da15c82562661b6a8f344 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Tue, 5 Jul 2016 12:40:49 -0400 Subject: drm/i915/gvt: Introduce basic vGPU life cycle management A vGPU represents a virtual Intel GEN hardware, which consists following virtual resources: - Configuration space (virtualized) - HW registers (virtualized) - GGTT memory space (partitioned) - GPU page table (shadowed) - Fence registers (partitioned) * virtualized: fully emulated by GVT-g. * partitioned: Only a part of the HW resource is allowed to be accessed by VM. * shadowed: Resource needs to be translated and shadowed before getting applied into HW. This patch introduces vGPU life cycle management framework, which is responsible for creating/destroying a vGPU and preparing/free resources related to a vGPU. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/gvt.h | 71 ++++++++++++ drivers/gpu/drm/i915/gvt/hypercall.h | 11 ++ drivers/gpu/drm/i915/gvt/mpt.h | 33 ++++++ drivers/gpu/drm/i915/gvt/reg.h | 33 ++++++ drivers/gpu/drm/i915/gvt/vgpu.c | 215 +++++++++++++++++++++++++++++++++++ 6 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/gvt/reg.h create mode 100644 drivers/gpu/drm/i915/gvt/vgpu.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index ebbb90a6dca5..18216bcbf134 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,5 +1,5 @@ GVT_DIR := gvt -GVT_SOURCE := gvt.o aperture_gm.o handlers.o firmware.o +GVT_SOURCE := gvt.o aperture_gm.o handlers.o firmware.o vgpu.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index e8759680e952..e00c2d66f658 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -36,6 +36,7 @@ #include "debug.h" #include "hypercall.h" #include "mmio.h" +#include "reg.h" #define GVT_MAX_VGPU 8 @@ -77,13 +78,37 @@ struct intel_vgpu_fence { u32 size; }; +struct intel_vgpu_mmio { + void *vreg; + void *sreg; +}; + +#define INTEL_GVT_MAX_CFG_SPACE_SZ 256 +#define INTEL_GVT_MAX_BAR_NUM 4 + +struct intel_vgpu_pci_bar { + u64 size; + bool tracked; +}; + +struct intel_vgpu_cfg_space { + unsigned char virtual_cfg_space[INTEL_GVT_MAX_CFG_SPACE_SZ]; + struct intel_vgpu_pci_bar bar[INTEL_GVT_MAX_BAR_NUM]; +}; + +#define vgpu_cfg_space(vgpu) ((vgpu)->cfg_space.virtual_cfg_space) + struct intel_vgpu { struct intel_gvt *gvt; int id; unsigned long handle; /* vGPU handle used by hypervisor MPT modules */ + bool active; + bool resetting; struct intel_vgpu_fence fence; struct intel_vgpu_gm gm; + struct intel_vgpu_cfg_space cfg_space; + struct intel_vgpu_mmio mmio; }; struct intel_gvt_gm { @@ -183,6 +208,52 @@ void intel_vgpu_free_resource(struct intel_vgpu *vgpu); void intel_vgpu_write_fence(struct intel_vgpu *vgpu, u32 fence, u64 value); +/* Macros for easily accessing vGPU virtual/shadow register */ +#define vgpu_vreg(vgpu, reg) \ + (*(u32 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg))) +#define vgpu_vreg8(vgpu, reg) \ + (*(u8 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg))) +#define vgpu_vreg16(vgpu, reg) \ + (*(u16 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg))) +#define vgpu_vreg64(vgpu, reg) \ + (*(u64 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg))) +#define vgpu_sreg(vgpu, reg) \ + (*(u32 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg))) +#define vgpu_sreg8(vgpu, reg) \ + (*(u8 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg))) +#define vgpu_sreg16(vgpu, reg) \ + (*(u16 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg))) +#define vgpu_sreg64(vgpu, reg) \ + (*(u64 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg))) + +#define for_each_active_vgpu(gvt, vgpu, id) \ + idr_for_each_entry((&(gvt)->vgpu_idr), (vgpu), (id)) \ + for_each_if(vgpu->active) + +static inline void intel_vgpu_write_pci_bar(struct intel_vgpu *vgpu, + u32 offset, u32 val, bool low) +{ + u32 *pval; + + /* BAR offset should be 32 bits algiend */ + offset = rounddown(offset, 4); + pval = (u32 *)(vgpu_cfg_space(vgpu) + offset); + + if (low) { + /* + * only update bit 31 - bit 4, + * leave the bit 3 - bit 0 unchanged. + */ + *pval = (val & GENMASK(31, 4)) | (*pval & GENMASK(3, 0)); + } +} + +struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, + struct intel_vgpu_creation_params * + param); + +void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu); + #include "mpt.h" #endif diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index 254df8bf1f35..eff8af56e012 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -19,6 +19,15 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. + * + * Authors: + * Eddie Dong + * Dexuan Cui + * Jike Song + * + * Contributors: + * Zhi Wang + * */ #ifndef _GVT_HYPERCALL_H_ @@ -30,6 +39,8 @@ */ struct intel_gvt_mpt { int (*detect_host)(void); + int (*attach_vgpu)(void *vgpu, unsigned long *handle); + void (*detach_vgpu)(unsigned long handle); }; extern struct intel_gvt_mpt xengt_mpt; diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index 03601e3ffa7c..f78186884a5c 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -19,6 +19,15 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. + * + * Authors: + * Eddie Dong + * Dexuan Cui + * Jike Song + * + * Contributors: + * Zhi Wang + * */ #ifndef _GVT_MPT_H_ @@ -46,4 +55,28 @@ static inline int intel_gvt_hypervisor_detect_host(void) return intel_gvt_host.mpt->detect_host(); } +/** + * intel_gvt_hypervisor_attach_vgpu - call hypervisor to initialize vGPU + * related stuffs inside hypervisor. + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline int intel_gvt_hypervisor_attach_vgpu(struct intel_vgpu *vgpu) +{ + return intel_gvt_host.mpt->attach_vgpu(vgpu, &vgpu->handle); +} + +/** + * intel_gvt_hypervisor_detach_vgpu - call hypervisor to release vGPU + * related stuffs inside hypervisor. + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu) +{ + intel_gvt_host.mpt->detach_vgpu(vgpu->handle); +} + #endif /* _GVT_MPT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h new file mode 100644 index 000000000000..3172fb3f8d76 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/reg.h @@ -0,0 +1,33 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _GVT_REG_H +#define _GVT_REG_H + +#define INTEL_GVT_PCI_CLASS_VGA_OTHER 0x80 + +#define INTEL_GVT_PCI_GMCH_CONTROL 0x50 +#define BDW_GMCH_GMS_SHIFT 8 +#define BDW_GMCH_GMS_MASK 0xff + +#endif diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c new file mode 100644 index 000000000000..0f1a59b9156a --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -0,0 +1,215 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eddie Dong + * Kevin Tian + * + * Contributors: + * Ping Gao + * Zhi Wang + * Bing Niu + * + */ + +#include "i915_drv.h" + +static void clean_vgpu_mmio(struct intel_vgpu *vgpu) +{ + vfree(vgpu->mmio.vreg); + vgpu->mmio.vreg = vgpu->mmio.sreg = NULL; +} + +static int setup_vgpu_mmio(struct intel_vgpu *vgpu) +{ + struct intel_gvt *gvt = vgpu->gvt; + const struct intel_gvt_device_info *info = &gvt->device_info; + + vgpu->mmio.vreg = vzalloc(info->mmio_size * 2); + if (!vgpu->mmio.vreg) + return -ENOMEM; + + vgpu->mmio.sreg = vgpu->mmio.vreg + info->mmio_size; + + memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size); + memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size); + return 0; +} + +static void setup_vgpu_cfg_space(struct intel_vgpu *vgpu, + struct intel_vgpu_creation_params *param) +{ + struct intel_gvt *gvt = vgpu->gvt; + const struct intel_gvt_device_info *info = &gvt->device_info; + u16 *gmch_ctl; + int i; + + memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space, + info->cfg_space_size); + + if (!param->primary) { + vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] = + INTEL_GVT_PCI_CLASS_VGA_OTHER; + vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] = + INTEL_GVT_PCI_CLASS_VGA_OTHER; + } + + /* Show guest that there isn't any stolen memory.*/ + gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL); + *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT); + + intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2, + gvt_aperture_pa_base(gvt), true); + + vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO + | PCI_COMMAND_MEMORY + | PCI_COMMAND_MASTER); + /* + * Clear the bar upper 32bit and let guest to assign the new value + */ + memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4); + memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4); + + for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) { + vgpu->cfg_space.bar[i].size = pci_resource_len( + gvt->dev_priv->drm.pdev, i * 2); + vgpu->cfg_space.bar[i].tracked = false; + } +} + +static void populate_pvinfo_page(struct intel_vgpu *vgpu) +{ + /* setup the ballooning information */ + vgpu_vreg64(vgpu, vgtif_reg(magic)) = VGT_MAGIC; + vgpu_vreg(vgpu, vgtif_reg(version_major)) = 1; + vgpu_vreg(vgpu, vgtif_reg(version_minor)) = 0; + vgpu_vreg(vgpu, vgtif_reg(display_ready)) = 0; + vgpu_vreg(vgpu, vgtif_reg(vgt_id)) = vgpu->id; + vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) = + vgpu_aperture_gmadr_base(vgpu); + vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) = + vgpu_aperture_sz(vgpu); + vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.base)) = + vgpu_hidden_gmadr_base(vgpu); + vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.size)) = + vgpu_hidden_sz(vgpu); + + vgpu_vreg(vgpu, vgtif_reg(avail_rs.fence_num)) = vgpu_fence_sz(vgpu); + + gvt_dbg_core("Populate PVINFO PAGE for vGPU %d\n", vgpu->id); + gvt_dbg_core("aperture base [GMADR] 0x%llx size 0x%llx\n", + vgpu_aperture_gmadr_base(vgpu), vgpu_aperture_sz(vgpu)); + gvt_dbg_core("hidden base [GMADR] 0x%llx size=0x%llx\n", + vgpu_hidden_gmadr_base(vgpu), vgpu_hidden_sz(vgpu)); + gvt_dbg_core("fence size %d\n", vgpu_fence_sz(vgpu)); + + WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE); +} + +/** + * intel_gvt_destroy_vgpu - destroy a virtual GPU + * @vgpu: virtual GPU + * + * This function is called when user wants to destroy a virtual GPU. + * + */ +void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) +{ + struct intel_gvt *gvt = vgpu->gvt; + + mutex_lock(&gvt->lock); + + vgpu->active = false; + idr_remove(&gvt->vgpu_idr, vgpu->id); + + intel_gvt_hypervisor_detach_vgpu(vgpu); + intel_vgpu_free_resource(vgpu); + clean_vgpu_mmio(vgpu); + vfree(vgpu); + + mutex_unlock(&gvt->lock); +} + +/** + * intel_gvt_create_vgpu - create a virtual GPU + * @gvt: GVT device + * @param: vGPU creation parameters + * + * This function is called when user wants to create a virtual GPU. + * + * Returns: + * pointer to intel_vgpu, error pointer if failed. + */ +struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, + struct intel_vgpu_creation_params *param) +{ + struct intel_vgpu *vgpu; + int ret; + + gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n", + param->handle, param->low_gm_sz, param->high_gm_sz, + param->fence_sz); + + vgpu = vzalloc(sizeof(*vgpu)); + if (!vgpu) + return ERR_PTR(-ENOMEM); + + mutex_lock(&gvt->lock); + + ret = idr_alloc(&gvt->vgpu_idr, vgpu, 1, GVT_MAX_VGPU, GFP_KERNEL); + if (ret < 0) + goto out_free_vgpu; + + vgpu->id = ret; + vgpu->handle = param->handle; + vgpu->gvt = gvt; + + setup_vgpu_cfg_space(vgpu, param); + + ret = setup_vgpu_mmio(vgpu); + if (ret) + goto out_free_vgpu; + + ret = intel_vgpu_alloc_resource(vgpu, param); + if (ret) + goto out_clean_vgpu_mmio; + + populate_pvinfo_page(vgpu); + + ret = intel_gvt_hypervisor_attach_vgpu(vgpu); + if (ret) + goto out_clean_vgpu_resource; + + vgpu->active = true; + mutex_unlock(&gvt->lock); + + return vgpu; + +out_clean_vgpu_resource: + intel_vgpu_free_resource(vgpu); +out_clean_vgpu_mmio: + clean_vgpu_mmio(vgpu); +out_free_vgpu: + vfree(vgpu); + mutex_unlock(&gvt->lock); + return ERR_PTR(ret); +} -- cgit v1.2.3 From 3f728236c5166052f88474412059cc63540cd27a Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Thu, 17 Sep 2015 07:26:44 +0800 Subject: drm/i915/gvt: trace stub v2: - Make checkpatch.pl happy(Joonas) Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/trace.h | 49 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/trace_points.c | 36 ++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/gvt/trace.h create mode 100644 drivers/gpu/drm/i915/gvt/trace_points.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 18216bcbf134..8fd4e18fbd4f 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,5 +1,5 @@ GVT_DIR := gvt -GVT_SOURCE := gvt.o aperture_gm.o handlers.o firmware.o vgpu.o +GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h new file mode 100644 index 000000000000..86bde96909b0 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/trace.h @@ -0,0 +1,49 @@ +/* + * Copyright © 2011-2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Jike Song + * + * Contributors: + * Zhi Wang + * + */ + +#if !defined(_GVT_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) +#define _GVT_TRACE_H_ + +#include +#include +#include +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM gvt + +#endif /* _GVT_TRACE_H_ */ + +/* This part must be out of protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace +#include diff --git a/drivers/gpu/drm/i915/gvt/trace_points.c b/drivers/gpu/drm/i915/gvt/trace_points.c new file mode 100644 index 000000000000..a3deed692b9c --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/trace_points.c @@ -0,0 +1,36 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Jike Song + * + * Contributors: + * Zhi Wang + * + */ + +#include "trace.h" + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "trace.h" +#endif -- cgit v1.2.3 From c8fe6a6811a7186656379d0c27e85325a966077a Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Thu, 17 Sep 2015 09:22:08 +0800 Subject: drm/i915/gvt: vGPU interrupt virtualization. This patch introduces vGPU interrupt emulation framework. The vGPU intrerrupt emulation framework is an event-based interrupt emulation framework. It's responsible for emulating GEN hardware interrupts during emulating other HW behaviour. It consists several components: - Descriptions of interrupt register bit - Upper level <-> lower level interrupt mapping - GEN HW IER/IMR/IIR register emulation routines - Event-based interrupt propagation interface When a GVT-g component wants to inject an interrupt to a VM during a emulation, first it should specify the event needs to be emulated and the framework will deal with the rest of emulation: - Generating related virtual IIR bit according to virtual IER and IMRs, - Generate related virtual upper level virtual IIR bit accodring to the per-platform interrupt mapping - Injecting a MSI to VM Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 3 +- drivers/gpu/drm/i915/gvt/debug.h | 5 +- drivers/gpu/drm/i915/gvt/gvt.c | 10 +- drivers/gpu/drm/i915/gvt/gvt.h | 10 +- drivers/gpu/drm/i915/gvt/hypercall.h | 1 + drivers/gpu/drm/i915/gvt/interrupt.c | 714 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/interrupt.h | 223 +++++++++++ drivers/gpu/drm/i915/gvt/mpt.h | 38 ++ 8 files changed, 998 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/interrupt.c create mode 100644 drivers/gpu/drm/i915/gvt/interrupt.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 8fd4e18fbd4f..41b74de2d028 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,5 +1,6 @@ GVT_DIR := gvt -GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o +GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ + interrupt.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index f9f0923feb9e..1be93e855d7e 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -30,8 +30,7 @@ #define gvt_dbg_core(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args) -/* - * Other GVT debug stuff will be introduced in the GVT device model patches. - */ +#define gvt_dbg_irq(fmt, args...) \ + DRM_DEBUG_DRIVER("gvt: irq: "fmt, ##args) #endif diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 2c03dad28718..29efe454b1cd 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -97,9 +97,10 @@ static void init_device_info(struct intel_gvt *gvt) if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { info->max_support_vgpus = 8; - info->mmio_size = 2 * 1024 * 1024; info->cfg_space_size = 256; + info->mmio_size = 2 * 1024 * 1024; info->mmio_bar = 0; + info->msi_cap_offset = IS_SKYLAKE(gvt->dev_priv) ? 0xac : 0x90; } } @@ -118,6 +119,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) if (WARN_ON(!gvt->initialized)) return; + intel_gvt_clean_irq(gvt); intel_gvt_clean_mmio_info(gvt); intel_gvt_free_firmware(gvt); @@ -165,10 +167,16 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (ret) goto out_clean_mmio_info; + ret = intel_gvt_init_irq(gvt); + if (ret) + goto out_free_firmware; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; +out_free_firmware: + intel_gvt_free_firmware(gvt); out_clean_mmio_info: intel_gvt_clean_mmio_info(gvt); return ret; diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index e00c2d66f658..655e6afb0aca 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -37,6 +37,7 @@ #include "hypercall.h" #include "mmio.h" #include "reg.h" +#include "interrupt.h" #define GVT_MAX_VGPU 8 @@ -56,9 +57,10 @@ extern struct intel_gvt_host intel_gvt_host; /* Describe per-platform limitations. */ struct intel_gvt_device_info { u32 max_support_vgpus; - u32 mmio_size; u32 cfg_space_size; + u32 mmio_size; u32 mmio_bar; + unsigned long msi_cap_offset; }; /* GM resources owned by a vGPU */ @@ -98,6 +100,10 @@ struct intel_vgpu_cfg_space { #define vgpu_cfg_space(vgpu) ((vgpu)->cfg_space.virtual_cfg_space) +struct intel_vgpu_irq { + bool irq_warn_once[INTEL_GVT_EVENT_MAX]; +}; + struct intel_vgpu { struct intel_gvt *gvt; int id; @@ -109,6 +115,7 @@ struct intel_vgpu { struct intel_vgpu_gm gm; struct intel_vgpu_cfg_space cfg_space; struct intel_vgpu_mmio mmio; + struct intel_vgpu_irq irq; }; struct intel_gvt_gm { @@ -145,6 +152,7 @@ struct intel_gvt { struct intel_gvt_fence fence; struct intel_gvt_mmio mmio; struct intel_gvt_firmware firmware; + struct intel_gvt_irq irq; }; void intel_gvt_free_firmware(struct intel_gvt *gvt); diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index eff8af56e012..f43614eb3b14 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -41,6 +41,7 @@ struct intel_gvt_mpt { int (*detect_host)(void); int (*attach_vgpu)(void *vgpu, unsigned long *handle); void (*detach_vgpu)(unsigned long handle); + int (*inject_msi)(unsigned long handle, u32 addr, u16 data); }; extern struct intel_gvt_mpt xengt_mpt; diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c new file mode 100644 index 000000000000..d90c5f660b00 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/interrupt.c @@ -0,0 +1,714 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Kevin Tian + * Zhi Wang + * + * Contributors: + * Min he + * + */ + +#include "i915_drv.h" + +/* common offset among interrupt control registers */ +#define regbase_to_isr(base) (base) +#define regbase_to_imr(base) (base + 0x4) +#define regbase_to_iir(base) (base + 0x8) +#define regbase_to_ier(base) (base + 0xC) + +#define iir_to_regbase(iir) (iir - 0x8) +#define ier_to_regbase(ier) (ier - 0xC) + +#define get_event_virt_handler(irq, e) (irq->events[e].v_handler) +#define get_irq_info(irq, e) (irq->events[e].info) + +#define irq_to_gvt(irq) \ + container_of(irq, struct intel_gvt, irq) + +static void update_upstream_irq(struct intel_vgpu *vgpu, + struct intel_gvt_irq_info *info); + +const char * const irq_name[INTEL_GVT_EVENT_MAX] = { + [RCS_MI_USER_INTERRUPT] = "Render CS MI USER INTERRUPT", + [RCS_DEBUG] = "Render EU debug from SVG", + [RCS_MMIO_SYNC_FLUSH] = "Render MMIO sync flush status", + [RCS_CMD_STREAMER_ERR] = "Render CS error interrupt", + [RCS_PIPE_CONTROL] = "Render PIPE CONTROL notify", + [RCS_WATCHDOG_EXCEEDED] = "Render CS Watchdog counter exceeded", + [RCS_PAGE_DIRECTORY_FAULT] = "Render page directory faults", + [RCS_AS_CONTEXT_SWITCH] = "Render AS Context Switch Interrupt", + + [VCS_MI_USER_INTERRUPT] = "Video CS MI USER INTERRUPT", + [VCS_MMIO_SYNC_FLUSH] = "Video MMIO sync flush status", + [VCS_CMD_STREAMER_ERR] = "Video CS error interrupt", + [VCS_MI_FLUSH_DW] = "Video MI FLUSH DW notify", + [VCS_WATCHDOG_EXCEEDED] = "Video CS Watchdog counter exceeded", + [VCS_PAGE_DIRECTORY_FAULT] = "Video page directory faults", + [VCS_AS_CONTEXT_SWITCH] = "Video AS Context Switch Interrupt", + [VCS2_MI_USER_INTERRUPT] = "VCS2 Video CS MI USER INTERRUPT", + [VCS2_MI_FLUSH_DW] = "VCS2 Video MI FLUSH DW notify", + [VCS2_AS_CONTEXT_SWITCH] = "VCS2 Context Switch Interrupt", + + [BCS_MI_USER_INTERRUPT] = "Blitter CS MI USER INTERRUPT", + [BCS_MMIO_SYNC_FLUSH] = "Billter MMIO sync flush status", + [BCS_CMD_STREAMER_ERR] = "Blitter CS error interrupt", + [BCS_MI_FLUSH_DW] = "Blitter MI FLUSH DW notify", + [BCS_PAGE_DIRECTORY_FAULT] = "Blitter page directory faults", + [BCS_AS_CONTEXT_SWITCH] = "Blitter AS Context Switch Interrupt", + + [VECS_MI_FLUSH_DW] = "Video Enhanced Streamer MI FLUSH DW notify", + [VECS_AS_CONTEXT_SWITCH] = "VECS Context Switch Interrupt", + + [PIPE_A_FIFO_UNDERRUN] = "Pipe A FIFO underrun", + [PIPE_A_CRC_ERR] = "Pipe A CRC error", + [PIPE_A_CRC_DONE] = "Pipe A CRC done", + [PIPE_A_VSYNC] = "Pipe A vsync", + [PIPE_A_LINE_COMPARE] = "Pipe A line compare", + [PIPE_A_ODD_FIELD] = "Pipe A odd field", + [PIPE_A_EVEN_FIELD] = "Pipe A even field", + [PIPE_A_VBLANK] = "Pipe A vblank", + [PIPE_B_FIFO_UNDERRUN] = "Pipe B FIFO underrun", + [PIPE_B_CRC_ERR] = "Pipe B CRC error", + [PIPE_B_CRC_DONE] = "Pipe B CRC done", + [PIPE_B_VSYNC] = "Pipe B vsync", + [PIPE_B_LINE_COMPARE] = "Pipe B line compare", + [PIPE_B_ODD_FIELD] = "Pipe B odd field", + [PIPE_B_EVEN_FIELD] = "Pipe B even field", + [PIPE_B_VBLANK] = "Pipe B vblank", + [PIPE_C_VBLANK] = "Pipe C vblank", + [DPST_PHASE_IN] = "DPST phase in event", + [DPST_HISTOGRAM] = "DPST histogram event", + [GSE] = "GSE", + [DP_A_HOTPLUG] = "DP A Hotplug", + [AUX_CHANNEL_A] = "AUX Channel A", + [PERF_COUNTER] = "Performance counter", + [POISON] = "Poison", + [GTT_FAULT] = "GTT fault", + [PRIMARY_A_FLIP_DONE] = "Primary Plane A flip done", + [PRIMARY_B_FLIP_DONE] = "Primary Plane B flip done", + [PRIMARY_C_FLIP_DONE] = "Primary Plane C flip done", + [SPRITE_A_FLIP_DONE] = "Sprite Plane A flip done", + [SPRITE_B_FLIP_DONE] = "Sprite Plane B flip done", + [SPRITE_C_FLIP_DONE] = "Sprite Plane C flip done", + + [PCU_THERMAL] = "PCU Thermal Event", + [PCU_PCODE2DRIVER_MAILBOX] = "PCU pcode2driver mailbox event", + + [FDI_RX_INTERRUPTS_TRANSCODER_A] = "FDI RX Interrupts Combined A", + [AUDIO_CP_CHANGE_TRANSCODER_A] = "Audio CP Change Transcoder A", + [AUDIO_CP_REQUEST_TRANSCODER_A] = "Audio CP Request Transcoder A", + [FDI_RX_INTERRUPTS_TRANSCODER_B] = "FDI RX Interrupts Combined B", + [AUDIO_CP_CHANGE_TRANSCODER_B] = "Audio CP Change Transcoder B", + [AUDIO_CP_REQUEST_TRANSCODER_B] = "Audio CP Request Transcoder B", + [FDI_RX_INTERRUPTS_TRANSCODER_C] = "FDI RX Interrupts Combined C", + [AUDIO_CP_CHANGE_TRANSCODER_C] = "Audio CP Change Transcoder C", + [AUDIO_CP_REQUEST_TRANSCODER_C] = "Audio CP Request Transcoder C", + [ERR_AND_DBG] = "South Error and Debug Interupts Combined", + [GMBUS] = "Gmbus", + [SDVO_B_HOTPLUG] = "SDVO B hotplug", + [CRT_HOTPLUG] = "CRT Hotplug", + [DP_B_HOTPLUG] = "DisplayPort/HDMI/DVI B Hotplug", + [DP_C_HOTPLUG] = "DisplayPort/HDMI/DVI C Hotplug", + [DP_D_HOTPLUG] = "DisplayPort/HDMI/DVI D Hotplug", + [AUX_CHANNEL_B] = "AUX Channel B", + [AUX_CHANNEL_C] = "AUX Channel C", + [AUX_CHANNEL_D] = "AUX Channel D", + [AUDIO_POWER_STATE_CHANGE_B] = "Audio Power State change Port B", + [AUDIO_POWER_STATE_CHANGE_C] = "Audio Power State change Port C", + [AUDIO_POWER_STATE_CHANGE_D] = "Audio Power State change Port D", + + [INTEL_GVT_EVENT_RESERVED] = "RESERVED EVENTS!!!", +}; + +static inline struct intel_gvt_irq_info *regbase_to_irq_info( + struct intel_gvt *gvt, + unsigned int reg) +{ + struct intel_gvt_irq *irq = &gvt->irq; + int i; + + for_each_set_bit(i, irq->irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX) { + if (i915_mmio_reg_offset(irq->info[i]->reg_base) == reg) + return irq->info[i]; + } + + return NULL; +} + +/** + * intel_vgpu_reg_imr_handler - Generic IMR register emulation write handler + * @vgpu: a vGPU + * @reg: register offset written by guest + * @p_data: register data written by guest + * @bytes: register data length + * + * This function is used to emulate the generic IMR register bit change + * behavior. + * + * Returns: + * Zero on success, negative error code if failed. + * + */ +int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu, + unsigned int reg, void *p_data, unsigned int bytes) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_irq_ops *ops = gvt->irq.ops; + u32 changed, masked, unmasked; + u32 imr = *(u32 *)p_data; + + gvt_dbg_irq("write IMR %x with val %x\n", + reg, imr); + + gvt_dbg_irq("old vIMR %x\n", vgpu_vreg(vgpu, reg)); + + /* figure out newly masked/unmasked bits */ + changed = vgpu_vreg(vgpu, reg) ^ imr; + masked = (vgpu_vreg(vgpu, reg) & changed) ^ changed; + unmasked = masked ^ changed; + + gvt_dbg_irq("changed %x, masked %x, unmasked %x\n", + changed, masked, unmasked); + + vgpu_vreg(vgpu, reg) = imr; + + ops->check_pending_irq(vgpu); + gvt_dbg_irq("IRQ: new vIMR %x\n", vgpu_vreg(vgpu, reg)); + return 0; +} + +/** + * intel_vgpu_reg_master_irq_handler - master IRQ write emulation handler + * @vgpu: a vGPU + * @reg: register offset written by guest + * @p_data: register data written by guest + * @bytes: register data length + * + * This function is used to emulate the master IRQ register on gen8+. + * + * Returns: + * Zero on success, negative error code if failed. + * + */ +int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu, + unsigned int reg, void *p_data, unsigned int bytes) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_irq_ops *ops = gvt->irq.ops; + u32 changed, enabled, disabled; + u32 ier = *(u32 *)p_data; + u32 virtual_ier = vgpu_vreg(vgpu, reg); + + gvt_dbg_irq("write master irq reg %x with val %x\n", + reg, ier); + + gvt_dbg_irq("old vreg %x\n", vgpu_vreg(vgpu, reg)); + + /* + * GEN8_MASTER_IRQ is a special irq register, + * only bit 31 is allowed to be modified + * and treated as an IER bit. + */ + ier &= GEN8_MASTER_IRQ_CONTROL; + virtual_ier &= GEN8_MASTER_IRQ_CONTROL; + vgpu_vreg(vgpu, reg) &= ~GEN8_MASTER_IRQ_CONTROL; + vgpu_vreg(vgpu, reg) |= ier; + + /* figure out newly enabled/disable bits */ + changed = virtual_ier ^ ier; + enabled = (virtual_ier & changed) ^ changed; + disabled = enabled ^ changed; + + gvt_dbg_irq("changed %x, enabled %x, disabled %x\n", + changed, enabled, disabled); + + ops->check_pending_irq(vgpu); + gvt_dbg_irq("new vreg %x\n", vgpu_vreg(vgpu, reg)); + return 0; +} + +/** + * intel_vgpu_reg_ier_handler - Generic IER write emulation handler + * @vgpu: a vGPU + * @reg: register offset written by guest + * @p_data: register data written by guest + * @bytes: register data length + * + * This function is used to emulate the generic IER register behavior. + * + * Returns: + * Zero on success, negative error code if failed. + * + */ +int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu, + unsigned int reg, void *p_data, unsigned int bytes) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_irq_ops *ops = gvt->irq.ops; + struct intel_gvt_irq_info *info; + u32 changed, enabled, disabled; + u32 ier = *(u32 *)p_data; + + gvt_dbg_irq("write IER %x with val %x\n", + reg, ier); + + gvt_dbg_irq("old vIER %x\n", vgpu_vreg(vgpu, reg)); + + /* figure out newly enabled/disable bits */ + changed = vgpu_vreg(vgpu, reg) ^ ier; + enabled = (vgpu_vreg(vgpu, reg) & changed) ^ changed; + disabled = enabled ^ changed; + + gvt_dbg_irq("changed %x, enabled %x, disabled %x\n", + changed, enabled, disabled); + vgpu_vreg(vgpu, reg) = ier; + + info = regbase_to_irq_info(gvt, ier_to_regbase(reg)); + if (WARN_ON(!info)) + return -EINVAL; + + if (info->has_upstream_irq) + update_upstream_irq(vgpu, info); + + ops->check_pending_irq(vgpu); + gvt_dbg_irq("new vIER %x\n", vgpu_vreg(vgpu, reg)); + return 0; +} + +/** + * intel_vgpu_reg_iir_handler - Generic IIR write emulation handler + * @vgpu: a vGPU + * @reg: register offset written by guest + * @p_data: register data written by guest + * @bytes: register data length + * + * This function is used to emulate the generic IIR register behavior. + * + * Returns: + * Zero on success, negative error code if failed. + * + */ +int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg, + void *p_data, unsigned int bytes) +{ + struct intel_gvt_irq_info *info = regbase_to_irq_info(vgpu->gvt, + iir_to_regbase(reg)); + u32 iir = *(u32 *)p_data; + + gvt_dbg_irq("write IIR %x with val %x\n", reg, iir); + + if (WARN_ON(!info)) + return -EINVAL; + + vgpu_vreg(vgpu, reg) &= ~iir; + + if (info->has_upstream_irq) + update_upstream_irq(vgpu, info); + return 0; +} + +static struct intel_gvt_irq_map gen8_irq_map[] = { + { INTEL_GVT_IRQ_INFO_MASTER, 0, INTEL_GVT_IRQ_INFO_GT0, 0xffff }, + { INTEL_GVT_IRQ_INFO_MASTER, 1, INTEL_GVT_IRQ_INFO_GT0, 0xffff0000 }, + { INTEL_GVT_IRQ_INFO_MASTER, 2, INTEL_GVT_IRQ_INFO_GT1, 0xffff }, + { INTEL_GVT_IRQ_INFO_MASTER, 3, INTEL_GVT_IRQ_INFO_GT1, 0xffff0000 }, + { INTEL_GVT_IRQ_INFO_MASTER, 4, INTEL_GVT_IRQ_INFO_GT2, 0xffff }, + { INTEL_GVT_IRQ_INFO_MASTER, 6, INTEL_GVT_IRQ_INFO_GT3, 0xffff }, + { INTEL_GVT_IRQ_INFO_MASTER, 16, INTEL_GVT_IRQ_INFO_DE_PIPE_A, ~0 }, + { INTEL_GVT_IRQ_INFO_MASTER, 17, INTEL_GVT_IRQ_INFO_DE_PIPE_B, ~0 }, + { INTEL_GVT_IRQ_INFO_MASTER, 18, INTEL_GVT_IRQ_INFO_DE_PIPE_C, ~0 }, + { INTEL_GVT_IRQ_INFO_MASTER, 20, INTEL_GVT_IRQ_INFO_DE_PORT, ~0 }, + { INTEL_GVT_IRQ_INFO_MASTER, 22, INTEL_GVT_IRQ_INFO_DE_MISC, ~0 }, + { INTEL_GVT_IRQ_INFO_MASTER, 23, INTEL_GVT_IRQ_INFO_PCH, ~0 }, + { INTEL_GVT_IRQ_INFO_MASTER, 30, INTEL_GVT_IRQ_INFO_PCU, ~0 }, + { -1, -1, ~0 }, +}; + +static void update_upstream_irq(struct intel_vgpu *vgpu, + struct intel_gvt_irq_info *info) +{ + struct intel_gvt_irq *irq = &vgpu->gvt->irq; + struct intel_gvt_irq_map *map = irq->irq_map; + struct intel_gvt_irq_info *up_irq_info = NULL; + u32 set_bits = 0; + u32 clear_bits = 0; + int bit; + u32 val = vgpu_vreg(vgpu, + regbase_to_iir(i915_mmio_reg_offset(info->reg_base))) + & vgpu_vreg(vgpu, + regbase_to_ier(i915_mmio_reg_offset(info->reg_base))); + + if (!info->has_upstream_irq) + return; + + for (map = irq->irq_map; map->up_irq_bit != -1; map++) { + if (info->group != map->down_irq_group) + continue; + + if (!up_irq_info) + up_irq_info = irq->info[map->up_irq_group]; + else + WARN_ON(up_irq_info != irq->info[map->up_irq_group]); + + bit = map->up_irq_bit; + + if (val & map->down_irq_bitmask) + set_bits |= (1 << bit); + else + clear_bits |= (1 << bit); + } + + WARN_ON(!up_irq_info); + + if (up_irq_info->group == INTEL_GVT_IRQ_INFO_MASTER) { + u32 isr = i915_mmio_reg_offset(up_irq_info->reg_base); + + vgpu_vreg(vgpu, isr) &= ~clear_bits; + vgpu_vreg(vgpu, isr) |= set_bits; + } else { + u32 iir = regbase_to_iir( + i915_mmio_reg_offset(up_irq_info->reg_base)); + u32 imr = regbase_to_imr( + i915_mmio_reg_offset(up_irq_info->reg_base)); + + vgpu_vreg(vgpu, iir) |= (set_bits & ~vgpu_vreg(vgpu, imr)); + } + + if (up_irq_info->has_upstream_irq) + update_upstream_irq(vgpu, up_irq_info); +} + +static void init_irq_map(struct intel_gvt_irq *irq) +{ + struct intel_gvt_irq_map *map; + struct intel_gvt_irq_info *up_info, *down_info; + int up_bit; + + for (map = irq->irq_map; map->up_irq_bit != -1; map++) { + up_info = irq->info[map->up_irq_group]; + up_bit = map->up_irq_bit; + down_info = irq->info[map->down_irq_group]; + + set_bit(up_bit, up_info->downstream_irq_bitmap); + down_info->has_upstream_irq = true; + + gvt_dbg_irq("[up] grp %d bit %d -> [down] grp %d bitmask %x\n", + up_info->group, up_bit, + down_info->group, map->down_irq_bitmask); + } +} + +/* =======================vEvent injection===================== */ +static int inject_virtual_interrupt(struct intel_vgpu *vgpu) +{ + return intel_gvt_hypervisor_inject_msi(vgpu); +} + +static void propagate_event(struct intel_gvt_irq *irq, + enum intel_gvt_event_type event, struct intel_vgpu *vgpu) +{ + struct intel_gvt_irq_info *info; + unsigned int reg_base; + int bit; + + info = get_irq_info(irq, event); + if (WARN_ON(!info)) + return; + + reg_base = i915_mmio_reg_offset(info->reg_base); + bit = irq->events[event].bit; + + if (!test_bit(bit, (void *)&vgpu_vreg(vgpu, + regbase_to_imr(reg_base)))) { + gvt_dbg_irq("set bit (%d) for (%s) for vgpu (%d)\n", + bit, irq_name[event], vgpu->id); + set_bit(bit, (void *)&vgpu_vreg(vgpu, + regbase_to_iir(reg_base))); + } +} + +/* =======================vEvent Handlers===================== */ +static void handle_default_event_virt(struct intel_gvt_irq *irq, + enum intel_gvt_event_type event, struct intel_vgpu *vgpu) +{ + if (!vgpu->irq.irq_warn_once[event]) { + gvt_dbg_core("vgpu%d: IRQ receive event %d (%s)\n", + vgpu->id, event, irq_name[event]); + vgpu->irq.irq_warn_once[event] = true; + } + propagate_event(irq, event, vgpu); +} + +/* =====================GEN specific logic======================= */ +/* GEN8 interrupt routines. */ + +#define DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(regname, regbase) \ +static struct intel_gvt_irq_info gen8_##regname##_info = { \ + .name = #regname"-IRQ", \ + .reg_base = (regbase), \ + .bit_to_event = {[0 ... INTEL_GVT_IRQ_BITWIDTH-1] = \ + INTEL_GVT_EVENT_RESERVED}, \ +} + +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt0, GEN8_GT_ISR(0)); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt1, GEN8_GT_ISR(1)); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt2, GEN8_GT_ISR(2)); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt3, GEN8_GT_ISR(3)); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_a, GEN8_DE_PIPE_ISR(PIPE_A)); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_b, GEN8_DE_PIPE_ISR(PIPE_B)); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_c, GEN8_DE_PIPE_ISR(PIPE_C)); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_port, GEN8_DE_PORT_ISR); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_misc, GEN8_DE_MISC_ISR); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(pcu, GEN8_PCU_ISR); +DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(master, GEN8_MASTER_IRQ); + +static struct intel_gvt_irq_info gvt_base_pch_info = { + .name = "PCH-IRQ", + .reg_base = SDEISR, + .bit_to_event = {[0 ... INTEL_GVT_IRQ_BITWIDTH-1] = + INTEL_GVT_EVENT_RESERVED}, +}; + +static void gen8_check_pending_irq(struct intel_vgpu *vgpu) +{ + struct intel_gvt_irq *irq = &vgpu->gvt->irq; + int i; + + if (!(vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ)) & + GEN8_MASTER_IRQ_CONTROL)) + return; + + for_each_set_bit(i, irq->irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX) { + struct intel_gvt_irq_info *info = irq->info[i]; + u32 reg_base; + + if (!info->has_upstream_irq) + continue; + + reg_base = i915_mmio_reg_offset(info->reg_base); + if ((vgpu_vreg(vgpu, regbase_to_iir(reg_base)) + & vgpu_vreg(vgpu, regbase_to_ier(reg_base)))) + update_upstream_irq(vgpu, info); + } + + if (vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ)) + & ~GEN8_MASTER_IRQ_CONTROL) + inject_virtual_interrupt(vgpu); +} + +static void gen8_init_irq( + struct intel_gvt_irq *irq) +{ + struct intel_gvt *gvt = irq_to_gvt(irq); + +#define SET_BIT_INFO(s, b, e, i) \ + do { \ + s->events[e].bit = b; \ + s->events[e].info = s->info[i]; \ + s->info[i]->bit_to_event[b] = e;\ + } while (0) + +#define SET_IRQ_GROUP(s, g, i) \ + do { \ + s->info[g] = i; \ + (i)->group = g; \ + set_bit(g, s->irq_info_bitmap); \ + } while (0) + + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_MASTER, &gen8_master_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT0, &gen8_gt0_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT1, &gen8_gt1_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT2, &gen8_gt2_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT3, &gen8_gt3_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_A, &gen8_de_pipe_a_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_B, &gen8_de_pipe_b_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_C, &gen8_de_pipe_c_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PORT, &gen8_de_port_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_MISC, &gen8_de_misc_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_PCU, &gen8_pcu_info); + SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_PCH, &gvt_base_pch_info); + + /* GEN8 level 2 interrupts. */ + + /* GEN8 interrupt GT0 events */ + SET_BIT_INFO(irq, 0, RCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT0); + SET_BIT_INFO(irq, 4, RCS_PIPE_CONTROL, INTEL_GVT_IRQ_INFO_GT0); + SET_BIT_INFO(irq, 8, RCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT0); + + SET_BIT_INFO(irq, 16, BCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT0); + SET_BIT_INFO(irq, 20, BCS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT0); + SET_BIT_INFO(irq, 24, BCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT0); + + /* GEN8 interrupt GT1 events */ + SET_BIT_INFO(irq, 0, VCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT1); + SET_BIT_INFO(irq, 4, VCS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT1); + SET_BIT_INFO(irq, 8, VCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT1); + + if (HAS_BSD2(gvt->dev_priv)) { + SET_BIT_INFO(irq, 16, VCS2_MI_USER_INTERRUPT, + INTEL_GVT_IRQ_INFO_GT1); + SET_BIT_INFO(irq, 20, VCS2_MI_FLUSH_DW, + INTEL_GVT_IRQ_INFO_GT1); + SET_BIT_INFO(irq, 24, VCS2_AS_CONTEXT_SWITCH, + INTEL_GVT_IRQ_INFO_GT1); + } + + /* GEN8 interrupt GT3 events */ + SET_BIT_INFO(irq, 0, VECS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT3); + SET_BIT_INFO(irq, 4, VECS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT3); + SET_BIT_INFO(irq, 8, VECS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT3); + + SET_BIT_INFO(irq, 0, PIPE_A_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_A); + SET_BIT_INFO(irq, 0, PIPE_B_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_B); + SET_BIT_INFO(irq, 0, PIPE_C_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_C); + + /* GEN8 interrupt DE PORT events */ + SET_BIT_INFO(irq, 0, AUX_CHANNEL_A, INTEL_GVT_IRQ_INFO_DE_PORT); + SET_BIT_INFO(irq, 3, DP_A_HOTPLUG, INTEL_GVT_IRQ_INFO_DE_PORT); + + /* GEN8 interrupt DE MISC events */ + SET_BIT_INFO(irq, 0, GSE, INTEL_GVT_IRQ_INFO_DE_MISC); + + /* PCH events */ + SET_BIT_INFO(irq, 17, GMBUS, INTEL_GVT_IRQ_INFO_PCH); + SET_BIT_INFO(irq, 19, CRT_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH); + SET_BIT_INFO(irq, 21, DP_B_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH); + SET_BIT_INFO(irq, 22, DP_C_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH); + SET_BIT_INFO(irq, 23, DP_D_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH); + + if (IS_BROADWELL(gvt->dev_priv)) { + SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_PCH); + SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_PCH); + SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_PCH); + + SET_BIT_INFO(irq, 4, PRIMARY_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A); + SET_BIT_INFO(irq, 5, SPRITE_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A); + + SET_BIT_INFO(irq, 4, PRIMARY_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B); + SET_BIT_INFO(irq, 5, SPRITE_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B); + + SET_BIT_INFO(irq, 4, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); + SET_BIT_INFO(irq, 5, SPRITE_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); + } else if (IS_SKYLAKE(gvt->dev_priv)) { + SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_DE_PORT); + SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_DE_PORT); + SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_DE_PORT); + + SET_BIT_INFO(irq, 3, PRIMARY_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A); + SET_BIT_INFO(irq, 3, PRIMARY_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B); + SET_BIT_INFO(irq, 3, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); + } + + /* GEN8 interrupt PCU events */ + SET_BIT_INFO(irq, 24, PCU_THERMAL, INTEL_GVT_IRQ_INFO_PCU); + SET_BIT_INFO(irq, 25, PCU_PCODE2DRIVER_MAILBOX, INTEL_GVT_IRQ_INFO_PCU); +} + +static struct intel_gvt_irq_ops gen8_irq_ops = { + .init_irq = gen8_init_irq, + .check_pending_irq = gen8_check_pending_irq, +}; + +/** + * intel_vgpu_trigger_virtual_event - Trigger a virtual event for a vGPU + * @vgpu: a vGPU + * @event: interrupt event + * + * This function is used to trigger a virtual interrupt event for vGPU. + * The caller provides the event to be triggered, the framework itself + * will emulate the IRQ register bit change. + * + */ +void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu, + enum intel_gvt_event_type event) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_irq *irq = &gvt->irq; + gvt_event_virt_handler_t handler; + struct intel_gvt_irq_ops *ops = gvt->irq.ops; + + handler = get_event_virt_handler(irq, event); + WARN_ON(!handler); + + handler(irq, event, vgpu); + + ops->check_pending_irq(vgpu); +} + +static void init_events( + struct intel_gvt_irq *irq) +{ + int i; + + for (i = 0; i < INTEL_GVT_EVENT_MAX; i++) { + irq->events[i].info = NULL; + irq->events[i].v_handler = handle_default_event_virt; + } +} + +/** + * intel_gvt_clean_irq - clean up GVT-g IRQ emulation subsystem + * @gvt: a GVT device + * + * This function is called at driver unloading stage, to clean up GVT-g IRQ + * emulation subsystem. + * + */ +void intel_gvt_clean_irq(struct intel_gvt *gvt) +{ +} + +/** + * intel_gvt_init_irq - initialize GVT-g IRQ emulation subsystem + * @gvt: a GVT device + * + * This function is called at driver loading stage, to initialize the GVT-g IRQ + * emulation subsystem. + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_gvt_init_irq(struct intel_gvt *gvt) +{ + struct intel_gvt_irq *irq = &gvt->irq; + + gvt_dbg_core("init irq framework\n"); + + if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { + irq->ops = &gen8_irq_ops; + irq->irq_map = gen8_irq_map; + } else { + WARN_ON(1); + return -ENODEV; + } + + /* common event initialization */ + init_events(irq); + + /* gen specific initialization */ + irq->ops->init_irq(irq); + + init_irq_map(irq); + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/interrupt.h b/drivers/gpu/drm/i915/gvt/interrupt.h new file mode 100644 index 000000000000..28d5d32d6017 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/interrupt.h @@ -0,0 +1,223 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Kevin Tian + * Zhi Wang + * + * Contributors: + * Min he + * + */ + +#ifndef _GVT_INTERRUPT_H_ +#define _GVT_INTERRUPT_H_ + +enum intel_gvt_event_type { + RCS_MI_USER_INTERRUPT = 0, + RCS_DEBUG, + RCS_MMIO_SYNC_FLUSH, + RCS_CMD_STREAMER_ERR, + RCS_PIPE_CONTROL, + RCS_L3_PARITY_ERR, + RCS_WATCHDOG_EXCEEDED, + RCS_PAGE_DIRECTORY_FAULT, + RCS_AS_CONTEXT_SWITCH, + RCS_MONITOR_BUFF_HALF_FULL, + + VCS_MI_USER_INTERRUPT, + VCS_MMIO_SYNC_FLUSH, + VCS_CMD_STREAMER_ERR, + VCS_MI_FLUSH_DW, + VCS_WATCHDOG_EXCEEDED, + VCS_PAGE_DIRECTORY_FAULT, + VCS_AS_CONTEXT_SWITCH, + + VCS2_MI_USER_INTERRUPT, + VCS2_MI_FLUSH_DW, + VCS2_AS_CONTEXT_SWITCH, + + BCS_MI_USER_INTERRUPT, + BCS_MMIO_SYNC_FLUSH, + BCS_CMD_STREAMER_ERR, + BCS_MI_FLUSH_DW, + BCS_PAGE_DIRECTORY_FAULT, + BCS_AS_CONTEXT_SWITCH, + + VECS_MI_USER_INTERRUPT, + VECS_MI_FLUSH_DW, + VECS_AS_CONTEXT_SWITCH, + + PIPE_A_FIFO_UNDERRUN, + PIPE_B_FIFO_UNDERRUN, + PIPE_A_CRC_ERR, + PIPE_B_CRC_ERR, + PIPE_A_CRC_DONE, + PIPE_B_CRC_DONE, + PIPE_A_ODD_FIELD, + PIPE_B_ODD_FIELD, + PIPE_A_EVEN_FIELD, + PIPE_B_EVEN_FIELD, + PIPE_A_LINE_COMPARE, + PIPE_B_LINE_COMPARE, + PIPE_C_LINE_COMPARE, + PIPE_A_VBLANK, + PIPE_B_VBLANK, + PIPE_C_VBLANK, + PIPE_A_VSYNC, + PIPE_B_VSYNC, + PIPE_C_VSYNC, + PRIMARY_A_FLIP_DONE, + PRIMARY_B_FLIP_DONE, + PRIMARY_C_FLIP_DONE, + SPRITE_A_FLIP_DONE, + SPRITE_B_FLIP_DONE, + SPRITE_C_FLIP_DONE, + + PCU_THERMAL, + PCU_PCODE2DRIVER_MAILBOX, + + DPST_PHASE_IN, + DPST_HISTOGRAM, + GSE, + DP_A_HOTPLUG, + AUX_CHANNEL_A, + PERF_COUNTER, + POISON, + GTT_FAULT, + ERROR_INTERRUPT_COMBINED, + + FDI_RX_INTERRUPTS_TRANSCODER_A, + AUDIO_CP_CHANGE_TRANSCODER_A, + AUDIO_CP_REQUEST_TRANSCODER_A, + FDI_RX_INTERRUPTS_TRANSCODER_B, + AUDIO_CP_CHANGE_TRANSCODER_B, + AUDIO_CP_REQUEST_TRANSCODER_B, + FDI_RX_INTERRUPTS_TRANSCODER_C, + AUDIO_CP_CHANGE_TRANSCODER_C, + AUDIO_CP_REQUEST_TRANSCODER_C, + ERR_AND_DBG, + GMBUS, + SDVO_B_HOTPLUG, + CRT_HOTPLUG, + DP_B_HOTPLUG, + DP_C_HOTPLUG, + DP_D_HOTPLUG, + AUX_CHANNEL_B, + AUX_CHANNEL_C, + AUX_CHANNEL_D, + AUDIO_POWER_STATE_CHANGE_B, + AUDIO_POWER_STATE_CHANGE_C, + AUDIO_POWER_STATE_CHANGE_D, + + INTEL_GVT_EVENT_RESERVED, + INTEL_GVT_EVENT_MAX, +}; + +struct intel_gvt_irq; +struct intel_gvt; + +typedef void (*gvt_event_virt_handler_t)(struct intel_gvt_irq *irq, + enum intel_gvt_event_type event, struct intel_vgpu *vgpu); + +struct intel_gvt_irq_ops { + void (*init_irq)(struct intel_gvt_irq *irq); + void (*check_pending_irq)(struct intel_vgpu *vgpu); +}; + +/* the list of physical interrupt control register groups */ +enum intel_gvt_irq_type { + INTEL_GVT_IRQ_INFO_GT, + INTEL_GVT_IRQ_INFO_DPY, + INTEL_GVT_IRQ_INFO_PCH, + INTEL_GVT_IRQ_INFO_PM, + + INTEL_GVT_IRQ_INFO_MASTER, + INTEL_GVT_IRQ_INFO_GT0, + INTEL_GVT_IRQ_INFO_GT1, + INTEL_GVT_IRQ_INFO_GT2, + INTEL_GVT_IRQ_INFO_GT3, + INTEL_GVT_IRQ_INFO_DE_PIPE_A, + INTEL_GVT_IRQ_INFO_DE_PIPE_B, + INTEL_GVT_IRQ_INFO_DE_PIPE_C, + INTEL_GVT_IRQ_INFO_DE_PORT, + INTEL_GVT_IRQ_INFO_DE_MISC, + INTEL_GVT_IRQ_INFO_AUD, + INTEL_GVT_IRQ_INFO_PCU, + + INTEL_GVT_IRQ_INFO_MAX, +}; + +#define INTEL_GVT_IRQ_BITWIDTH 32 + +/* device specific interrupt bit definitions */ +struct intel_gvt_irq_info { + char *name; + i915_reg_t reg_base; + enum intel_gvt_event_type bit_to_event[INTEL_GVT_IRQ_BITWIDTH]; + unsigned long warned; + int group; + DECLARE_BITMAP(downstream_irq_bitmap, INTEL_GVT_IRQ_BITWIDTH); + bool has_upstream_irq; +}; + +/* per-event information */ +struct intel_gvt_event_info { + int bit; /* map to register bit */ + int policy; /* forwarding policy */ + struct intel_gvt_irq_info *info; /* register info */ + gvt_event_virt_handler_t v_handler; /* for v_event */ +}; + +struct intel_gvt_irq_map { + int up_irq_group; + int up_irq_bit; + int down_irq_group; + u32 down_irq_bitmask; +}; + +/* structure containing device specific IRQ state */ +struct intel_gvt_irq { + struct intel_gvt_irq_ops *ops; + struct intel_gvt_irq_info *info[INTEL_GVT_IRQ_INFO_MAX]; + DECLARE_BITMAP(irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX); + struct intel_gvt_event_info events[INTEL_GVT_EVENT_MAX]; + DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX); + struct intel_gvt_irq_map *irq_map; +}; + +int intel_gvt_init_irq(struct intel_gvt *gvt); +void intel_gvt_clean_irq(struct intel_gvt *gvt); + +void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu, + enum intel_gvt_event_type event); + +int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg, + void *p_data, unsigned int bytes); +int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu, + unsigned int reg, void *p_data, unsigned int bytes); +int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu, + unsigned int reg, void *p_data, unsigned int bytes); +int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu, + unsigned int reg, void *p_data, unsigned int bytes); + +#endif /* _GVT_INTERRUPT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index f78186884a5c..31a837195745 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -79,4 +79,42 @@ static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu) intel_gvt_host.mpt->detach_vgpu(vgpu->handle); } +#define MSI_CAP_CONTROL(offset) (offset + 2) +#define MSI_CAP_ADDRESS(offset) (offset + 4) +#define MSI_CAP_DATA(offset) (offset + 8) +#define MSI_CAP_EN 0x1 + +/** + * intel_gvt_hypervisor_inject_msi - inject a MSI interrupt into vGPU + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline int intel_gvt_hypervisor_inject_msi(struct intel_vgpu *vgpu) +{ + unsigned long offset = vgpu->gvt->device_info.msi_cap_offset; + u16 control, data; + u32 addr; + int ret; + + control = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_CONTROL(offset)); + addr = *(u32 *)(vgpu_cfg_space(vgpu) + MSI_CAP_ADDRESS(offset)); + data = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_DATA(offset)); + + /* Do not generate MSI if MSIEN is disable */ + if (!(control & MSI_CAP_EN)) + return 0; + + if (WARN(control & GENMASK(15, 1), "only support one MSI format\n")) + return -EINVAL; + + gvt_dbg_irq("vgpu%d: inject msi address %x data%x\n", vgpu->id, addr, + data); + + ret = intel_gvt_host.mpt->inject_msi(vgpu->handle, addr, data); + if (ret) + return ret; + return 0; +} + #endif /* _GVT_MPT_H_ */ -- cgit v1.2.3 From 2707e44466881d6b0a8ed05a429dcf0940c22f60 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Mon, 28 Mar 2016 23:23:16 +0800 Subject: drm/i915/gvt: vGPU graphics memory virtualization The vGPU graphics memory emulation framework is responsible for graphics memory table virtualization. Under virtualization environment, a VM will populate the page table entry with guest page frame number(GPFN/GFN), while HW needs a page table filled with MFN(Machine frame number). The relationship between GFN and MFN(Machine frame number) is managed by hypervisor, while GEN HW doesn't have such knowledge to translate a GFN. To solve this gap, shadow GGTT/PPGTT page table is introdcued. For GGTT, the GFN inside the guest GGTT page table entry will be translated into MFN and written into physical GTT MMIO registers when guest write virtual GTT MMIO registers. For PPGTT, a shadow PPGTT page table will be created and write-protected translated from guest PPGTT page table. And the shadow page table root pointers will be written into the shadow context after a guest workload is shadowed. vGPU graphics memory emulation framework consists: - Per-GEN HW platform page table entry bits extract/de-extract routines. - GTT MMIO register emulation handlers, which will call hypercall to do GFN->MFN translation when guest write GTT MMIO register - PPGTT shadow page table routines, e.g. shadow create/destroy/out-of-sync Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/debug.h | 3 + drivers/gpu/drm/i915/gvt/gtt.c | 2231 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/gtt.h | 270 ++++ drivers/gpu/drm/i915/gvt/gvt.c | 10 + drivers/gpu/drm/i915/gvt/gvt.h | 38 + drivers/gpu/drm/i915/gvt/hypercall.h | 8 + drivers/gpu/drm/i915/gvt/mpt.h | 107 ++ drivers/gpu/drm/i915/gvt/trace.h | 185 +++ drivers/gpu/drm/i915/gvt/vgpu.c | 7 + 10 files changed, 2860 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/gvt/gtt.c create mode 100644 drivers/gpu/drm/i915/gvt/gtt.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 41b74de2d028..40eef5b40505 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,6 +1,6 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ - interrupt.o + interrupt.o gtt.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index 1be93e855d7e..82269b750aac 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -33,4 +33,7 @@ #define gvt_dbg_irq(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: irq: "fmt, ##args) +#define gvt_dbg_mm(fmt, args...) \ + DRM_DEBUG_DRIVER("gvt: mm: "fmt, ##args) + #endif diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c new file mode 100644 index 000000000000..29de179920e8 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -0,0 +1,2231 @@ +/* + * GTT virtualization + * + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Zhi Wang + * Zhenyu Wang + * Xiao Zheng + * + * Contributors: + * Min He + * Bing Niu + * + */ + +#include "i915_drv.h" +#include "trace.h" + +static bool enable_out_of_sync = false; +static int preallocated_oos_pages = 8192; + +/* + * validate a gm address and related range size, + * translate it to host gm address + */ +bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size) +{ + if ((!vgpu_gmadr_is_valid(vgpu, addr)) || (size + && !vgpu_gmadr_is_valid(vgpu, addr + size - 1))) { + gvt_err("vgpu%d: invalid range gmadr 0x%llx size 0x%x\n", + vgpu->id, addr, size); + return false; + } + return true; +} + +/* translate a guest gmadr to host gmadr */ +int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr) +{ + if (WARN(!vgpu_gmadr_is_valid(vgpu, g_addr), + "invalid guest gmadr %llx\n", g_addr)) + return -EACCES; + + if (vgpu_gmadr_is_aperture(vgpu, g_addr)) + *h_addr = vgpu_aperture_gmadr_base(vgpu) + + (g_addr - vgpu_aperture_offset(vgpu)); + else + *h_addr = vgpu_hidden_gmadr_base(vgpu) + + (g_addr - vgpu_hidden_offset(vgpu)); + return 0; +} + +/* translate a host gmadr to guest gmadr */ +int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr) +{ + if (WARN(!gvt_gmadr_is_valid(vgpu->gvt, h_addr), + "invalid host gmadr %llx\n", h_addr)) + return -EACCES; + + if (gvt_gmadr_is_aperture(vgpu->gvt, h_addr)) + *g_addr = vgpu_aperture_gmadr_base(vgpu) + + (h_addr - gvt_aperture_gmadr_base(vgpu->gvt)); + else + *g_addr = vgpu_hidden_gmadr_base(vgpu) + + (h_addr - gvt_hidden_gmadr_base(vgpu->gvt)); + return 0; +} + +int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index, + unsigned long *h_index) +{ + u64 h_addr; + int ret; + + ret = intel_gvt_ggtt_gmadr_g2h(vgpu, g_index << GTT_PAGE_SHIFT, + &h_addr); + if (ret) + return ret; + + *h_index = h_addr >> GTT_PAGE_SHIFT; + return 0; +} + +int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, + unsigned long *g_index) +{ + u64 g_addr; + int ret; + + ret = intel_gvt_ggtt_gmadr_h2g(vgpu, h_index << GTT_PAGE_SHIFT, + &g_addr); + if (ret) + return ret; + + *g_index = g_addr >> GTT_PAGE_SHIFT; + return 0; +} + +#define gtt_type_is_entry(type) \ + (type > GTT_TYPE_INVALID && type < GTT_TYPE_PPGTT_ENTRY \ + && type != GTT_TYPE_PPGTT_PTE_ENTRY \ + && type != GTT_TYPE_PPGTT_ROOT_ENTRY) + +#define gtt_type_is_pt(type) \ + (type >= GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX) + +#define gtt_type_is_pte_pt(type) \ + (type == GTT_TYPE_PPGTT_PTE_PT) + +#define gtt_type_is_root_pointer(type) \ + (gtt_type_is_entry(type) && type > GTT_TYPE_PPGTT_ROOT_ENTRY) + +#define gtt_init_entry(e, t, p, v) do { \ + (e)->type = t; \ + (e)->pdev = p; \ + memcpy(&(e)->val64, &v, sizeof(v)); \ +} while (0) + +enum { + GTT_TYPE_INVALID = -1, + + GTT_TYPE_GGTT_PTE, + + GTT_TYPE_PPGTT_PTE_4K_ENTRY, + GTT_TYPE_PPGTT_PTE_2M_ENTRY, + GTT_TYPE_PPGTT_PTE_1G_ENTRY, + + GTT_TYPE_PPGTT_PTE_ENTRY, + + GTT_TYPE_PPGTT_PDE_ENTRY, + GTT_TYPE_PPGTT_PDP_ENTRY, + GTT_TYPE_PPGTT_PML4_ENTRY, + + GTT_TYPE_PPGTT_ROOT_ENTRY, + + GTT_TYPE_PPGTT_ROOT_L3_ENTRY, + GTT_TYPE_PPGTT_ROOT_L4_ENTRY, + + GTT_TYPE_PPGTT_ENTRY, + + GTT_TYPE_PPGTT_PTE_PT, + GTT_TYPE_PPGTT_PDE_PT, + GTT_TYPE_PPGTT_PDP_PT, + GTT_TYPE_PPGTT_PML4_PT, + + GTT_TYPE_MAX, +}; + +/* + * Mappings between GTT_TYPE* enumerations. + * Following information can be found according to the given type: + * - type of next level page table + * - type of entry inside this level page table + * - type of entry with PSE set + * + * If the given type doesn't have such a kind of information, + * e.g. give a l4 root entry type, then request to get its PSE type, + * give a PTE page table type, then request to get its next level page + * table type, as we know l4 root entry doesn't have a PSE bit, + * and a PTE page table doesn't have a next level page table type, + * GTT_TYPE_INVALID will be returned. This is useful when traversing a + * page table. + */ + +struct gtt_type_table_entry { + int entry_type; + int next_pt_type; + int pse_entry_type; +}; + +#define GTT_TYPE_TABLE_ENTRY(type, e_type, npt_type, pse_type) \ + [type] = { \ + .entry_type = e_type, \ + .next_pt_type = npt_type, \ + .pse_entry_type = pse_type, \ + } + +static struct gtt_type_table_entry gtt_type_table[] = { + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L4_ENTRY, + GTT_TYPE_PPGTT_ROOT_L4_ENTRY, + GTT_TYPE_PPGTT_PML4_PT, + GTT_TYPE_INVALID), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_PT, + GTT_TYPE_PPGTT_PML4_ENTRY, + GTT_TYPE_PPGTT_PDP_PT, + GTT_TYPE_INVALID), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_ENTRY, + GTT_TYPE_PPGTT_PML4_ENTRY, + GTT_TYPE_PPGTT_PDP_PT, + GTT_TYPE_INVALID), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_PT, + GTT_TYPE_PPGTT_PDP_ENTRY, + GTT_TYPE_PPGTT_PDE_PT, + GTT_TYPE_PPGTT_PTE_1G_ENTRY), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L3_ENTRY, + GTT_TYPE_PPGTT_ROOT_L3_ENTRY, + GTT_TYPE_PPGTT_PDE_PT, + GTT_TYPE_PPGTT_PTE_1G_ENTRY), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_ENTRY, + GTT_TYPE_PPGTT_PDP_ENTRY, + GTT_TYPE_PPGTT_PDE_PT, + GTT_TYPE_PPGTT_PTE_1G_ENTRY), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_PT, + GTT_TYPE_PPGTT_PDE_ENTRY, + GTT_TYPE_PPGTT_PTE_PT, + GTT_TYPE_PPGTT_PTE_2M_ENTRY), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_ENTRY, + GTT_TYPE_PPGTT_PDE_ENTRY, + GTT_TYPE_PPGTT_PTE_PT, + GTT_TYPE_PPGTT_PTE_2M_ENTRY), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_PT, + GTT_TYPE_PPGTT_PTE_4K_ENTRY, + GTT_TYPE_INVALID, + GTT_TYPE_INVALID), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_4K_ENTRY, + GTT_TYPE_PPGTT_PTE_4K_ENTRY, + GTT_TYPE_INVALID, + GTT_TYPE_INVALID), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_2M_ENTRY, + GTT_TYPE_PPGTT_PDE_ENTRY, + GTT_TYPE_INVALID, + GTT_TYPE_PPGTT_PTE_2M_ENTRY), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_1G_ENTRY, + GTT_TYPE_PPGTT_PDP_ENTRY, + GTT_TYPE_INVALID, + GTT_TYPE_PPGTT_PTE_1G_ENTRY), + GTT_TYPE_TABLE_ENTRY(GTT_TYPE_GGTT_PTE, + GTT_TYPE_GGTT_PTE, + GTT_TYPE_INVALID, + GTT_TYPE_INVALID), +}; + +static inline int get_next_pt_type(int type) +{ + return gtt_type_table[type].next_pt_type; +} + +static inline int get_entry_type(int type) +{ + return gtt_type_table[type].entry_type; +} + +static inline int get_pse_type(int type) +{ + return gtt_type_table[type].pse_entry_type; +} + +static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index) +{ + void *addr = (u64 *)dev_priv->ggtt.gsm + index; + u64 pte; + +#ifdef readq + pte = readq(addr); +#else + pte = ioread32(addr); + pte |= ioread32(addr + 4) << 32; +#endif + return pte; +} + +static void write_pte64(struct drm_i915_private *dev_priv, + unsigned long index, u64 pte) +{ + void *addr = (u64 *)dev_priv->ggtt.gsm + index; + +#ifdef writeq + writeq(pte, addr); +#else + iowrite32((u32)pte, addr); + iowrite32(pte >> 32, addr + 4); +#endif + I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); + POSTING_READ(GFX_FLSH_CNTL_GEN6); +} + +static inline struct intel_gvt_gtt_entry *gtt_get_entry64(void *pt, + struct intel_gvt_gtt_entry *e, + unsigned long index, bool hypervisor_access, unsigned long gpa, + struct intel_vgpu *vgpu) +{ + const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; + int ret; + + if (WARN_ON(info->gtt_entry_size != 8)) + return e; + + if (hypervisor_access) { + ret = intel_gvt_hypervisor_read_gpa(vgpu, gpa + + (index << info->gtt_entry_size_shift), + &e->val64, 8); + WARN_ON(ret); + } else if (!pt) { + e->val64 = read_pte64(vgpu->gvt->dev_priv, index); + } else { + e->val64 = *((u64 *)pt + index); + } + return e; +} + +static inline struct intel_gvt_gtt_entry *gtt_set_entry64(void *pt, + struct intel_gvt_gtt_entry *e, + unsigned long index, bool hypervisor_access, unsigned long gpa, + struct intel_vgpu *vgpu) +{ + const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; + int ret; + + if (WARN_ON(info->gtt_entry_size != 8)) + return e; + + if (hypervisor_access) { + ret = intel_gvt_hypervisor_write_gpa(vgpu, gpa + + (index << info->gtt_entry_size_shift), + &e->val64, 8); + WARN_ON(ret); + } else if (!pt) { + write_pte64(vgpu->gvt->dev_priv, index, e->val64); + } else { + *((u64 *)pt + index) = e->val64; + } + return e; +} + +#define GTT_HAW 46 + +#define ADDR_1G_MASK (((1UL << (GTT_HAW - 30 + 1)) - 1) << 30) +#define ADDR_2M_MASK (((1UL << (GTT_HAW - 21 + 1)) - 1) << 21) +#define ADDR_4K_MASK (((1UL << (GTT_HAW - 12 + 1)) - 1) << 12) + +static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e) +{ + unsigned long pfn; + + if (e->type == GTT_TYPE_PPGTT_PTE_1G_ENTRY) + pfn = (e->val64 & ADDR_1G_MASK) >> 12; + else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY) + pfn = (e->val64 & ADDR_2M_MASK) >> 12; + else + pfn = (e->val64 & ADDR_4K_MASK) >> 12; + return pfn; +} + +static void gen8_gtt_set_pfn(struct intel_gvt_gtt_entry *e, unsigned long pfn) +{ + if (e->type == GTT_TYPE_PPGTT_PTE_1G_ENTRY) { + e->val64 &= ~ADDR_1G_MASK; + pfn &= (ADDR_1G_MASK >> 12); + } else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY) { + e->val64 &= ~ADDR_2M_MASK; + pfn &= (ADDR_2M_MASK >> 12); + } else { + e->val64 &= ~ADDR_4K_MASK; + pfn &= (ADDR_4K_MASK >> 12); + } + + e->val64 |= (pfn << 12); +} + +static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry *e) +{ + /* Entry doesn't have PSE bit. */ + if (get_pse_type(e->type) == GTT_TYPE_INVALID) + return false; + + e->type = get_entry_type(e->type); + if (!(e->val64 & (1 << 7))) + return false; + + e->type = get_pse_type(e->type); + return true; +} + +static bool gen8_gtt_test_present(struct intel_gvt_gtt_entry *e) +{ + /* + * i915 writes PDP root pointer registers without present bit, + * it also works, so we need to treat root pointer entry + * specifically. + */ + if (e->type == GTT_TYPE_PPGTT_ROOT_L3_ENTRY + || e->type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) + return (e->val64 != 0); + else + return (e->val64 & (1 << 0)); +} + +static void gtt_entry_clear_present(struct intel_gvt_gtt_entry *e) +{ + e->val64 &= ~(1 << 0); +} + +/* + * Per-platform GMA routines. + */ +static unsigned long gma_to_ggtt_pte_index(unsigned long gma) +{ + unsigned long x = (gma >> GTT_PAGE_SHIFT); + + trace_gma_index(__func__, gma, x); + return x; +} + +#define DEFINE_PPGTT_GMA_TO_INDEX(prefix, ename, exp) \ +static unsigned long prefix##_gma_to_##ename##_index(unsigned long gma) \ +{ \ + unsigned long x = (exp); \ + trace_gma_index(__func__, gma, x); \ + return x; \ +} + +DEFINE_PPGTT_GMA_TO_INDEX(gen8, pte, (gma >> 12 & 0x1ff)); +DEFINE_PPGTT_GMA_TO_INDEX(gen8, pde, (gma >> 21 & 0x1ff)); +DEFINE_PPGTT_GMA_TO_INDEX(gen8, l3_pdp, (gma >> 30 & 0x3)); +DEFINE_PPGTT_GMA_TO_INDEX(gen8, l4_pdp, (gma >> 30 & 0x1ff)); +DEFINE_PPGTT_GMA_TO_INDEX(gen8, pml4, (gma >> 39 & 0x1ff)); + +static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = { + .get_entry = gtt_get_entry64, + .set_entry = gtt_set_entry64, + .clear_present = gtt_entry_clear_present, + .test_present = gen8_gtt_test_present, + .test_pse = gen8_gtt_test_pse, + .get_pfn = gen8_gtt_get_pfn, + .set_pfn = gen8_gtt_set_pfn, +}; + +static struct intel_gvt_gtt_gma_ops gen8_gtt_gma_ops = { + .gma_to_ggtt_pte_index = gma_to_ggtt_pte_index, + .gma_to_pte_index = gen8_gma_to_pte_index, + .gma_to_pde_index = gen8_gma_to_pde_index, + .gma_to_l3_pdp_index = gen8_gma_to_l3_pdp_index, + .gma_to_l4_pdp_index = gen8_gma_to_l4_pdp_index, + .gma_to_pml4_index = gen8_gma_to_pml4_index, +}; + +static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p, + struct intel_gvt_gtt_entry *m) +{ + struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; + unsigned long gfn, mfn; + + *m = *p; + + if (!ops->test_present(p)) + return 0; + + gfn = ops->get_pfn(p); + + mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn); + if (mfn == INTEL_GVT_INVALID_ADDR) { + gvt_err("fail to translate gfn: 0x%lx\n", gfn); + return -ENXIO; + } + + ops->set_pfn(m, mfn); + return 0; +} + +/* + * MM helpers. + */ +struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm, + void *page_table, struct intel_gvt_gtt_entry *e, + unsigned long index) +{ + struct intel_gvt *gvt = mm->vgpu->gvt; + struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; + + e->type = mm->page_table_entry_type; + + ops->get_entry(page_table, e, index, false, 0, mm->vgpu); + ops->test_pse(e); + return e; +} + +struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm, + void *page_table, struct intel_gvt_gtt_entry *e, + unsigned long index) +{ + struct intel_gvt *gvt = mm->vgpu->gvt; + struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; + + return ops->set_entry(page_table, e, index, false, 0, mm->vgpu); +} + +/* + * PPGTT shadow page table helpers. + */ +static inline struct intel_gvt_gtt_entry *ppgtt_spt_get_entry( + struct intel_vgpu_ppgtt_spt *spt, + void *page_table, int type, + struct intel_gvt_gtt_entry *e, unsigned long index, + bool guest) +{ + struct intel_gvt *gvt = spt->vgpu->gvt; + struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; + + e->type = get_entry_type(type); + + if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n")) + return e; + + ops->get_entry(page_table, e, index, guest, + spt->guest_page.gfn << GTT_PAGE_SHIFT, + spt->vgpu); + ops->test_pse(e); + return e; +} + +static inline struct intel_gvt_gtt_entry *ppgtt_spt_set_entry( + struct intel_vgpu_ppgtt_spt *spt, + void *page_table, int type, + struct intel_gvt_gtt_entry *e, unsigned long index, + bool guest) +{ + struct intel_gvt *gvt = spt->vgpu->gvt; + struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; + + if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n")) + return e; + + return ops->set_entry(page_table, e, index, guest, + spt->guest_page.gfn << GTT_PAGE_SHIFT, + spt->vgpu); +} + +#define ppgtt_get_guest_entry(spt, e, index) \ + ppgtt_spt_get_entry(spt, NULL, \ + spt->guest_page_type, e, index, true) + +#define ppgtt_set_guest_entry(spt, e, index) \ + ppgtt_spt_set_entry(spt, NULL, \ + spt->guest_page_type, e, index, true) + +#define ppgtt_get_shadow_entry(spt, e, index) \ + ppgtt_spt_get_entry(spt, spt->shadow_page.vaddr, \ + spt->shadow_page.type, e, index, false) + +#define ppgtt_set_shadow_entry(spt, e, index) \ + ppgtt_spt_set_entry(spt, spt->shadow_page.vaddr, \ + spt->shadow_page.type, e, index, false) + +/** + * intel_vgpu_init_guest_page - init a guest page data structure + * @vgpu: a vGPU + * @p: a guest page data structure + * @gfn: guest memory page frame number + * @handler: function will be called when target guest memory page has + * been modified. + * + * This function is called when user wants to track a guest memory page. + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *p, + unsigned long gfn, + int (*handler)(void *, u64, void *, int), + void *data) +{ + INIT_HLIST_NODE(&p->node); + + p->writeprotection = false; + p->gfn = gfn; + p->handler = handler; + p->data = data; + p->oos_page = NULL; + p->write_cnt = 0; + + hash_add(vgpu->gtt.guest_page_hash_table, &p->node, p->gfn); + return 0; +} + +static int detach_oos_page(struct intel_vgpu *vgpu, + struct intel_vgpu_oos_page *oos_page); + +/** + * intel_vgpu_clean_guest_page - release the resource owned by guest page data + * structure + * @vgpu: a vGPU + * @p: a tracked guest page + * + * This function is called when user tries to stop tracking a guest memory + * page. + */ +void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *p) +{ + if (!hlist_unhashed(&p->node)) + hash_del(&p->node); + + if (p->oos_page) + detach_oos_page(vgpu, p->oos_page); + + if (p->writeprotection) + intel_gvt_hypervisor_unset_wp_page(vgpu, p); +} + +/** + * intel_vgpu_find_guest_page - find a guest page data structure by GFN. + * @vgpu: a vGPU + * @gfn: guest memory page frame number + * + * This function is called when emulation logic wants to know if a trapped GFN + * is a tracked guest page. + * + * Returns: + * Pointer to guest page data structure, NULL if failed. + */ +struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( + struct intel_vgpu *vgpu, unsigned long gfn) +{ + struct intel_vgpu_guest_page *p; + + hash_for_each_possible(vgpu->gtt.guest_page_hash_table, + p, node, gfn) { + if (p->gfn == gfn) + return p; + } + return NULL; +} + +static inline int init_shadow_page(struct intel_vgpu *vgpu, + struct intel_vgpu_shadow_page *p, int type) +{ + p->vaddr = page_address(p->page); + p->type = type; + + INIT_HLIST_NODE(&p->node); + + p->mfn = intel_gvt_hypervisor_virt_to_mfn(p->vaddr); + if (p->mfn == INTEL_GVT_INVALID_ADDR) + return -EFAULT; + + hash_add(vgpu->gtt.shadow_page_hash_table, &p->node, p->mfn); + return 0; +} + +static inline void clean_shadow_page(struct intel_vgpu_shadow_page *p) +{ + if (!hlist_unhashed(&p->node)) + hash_del(&p->node); +} + +static inline struct intel_vgpu_shadow_page *find_shadow_page( + struct intel_vgpu *vgpu, unsigned long mfn) +{ + struct intel_vgpu_shadow_page *p; + + hash_for_each_possible(vgpu->gtt.shadow_page_hash_table, + p, node, mfn) { + if (p->mfn == mfn) + return p; + } + return NULL; +} + +#define guest_page_to_ppgtt_spt(ptr) \ + container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page) + +#define shadow_page_to_ppgtt_spt(ptr) \ + container_of(ptr, struct intel_vgpu_ppgtt_spt, shadow_page) + +static void *alloc_spt(gfp_t gfp_mask) +{ + struct intel_vgpu_ppgtt_spt *spt; + + spt = kzalloc(sizeof(*spt), gfp_mask); + if (!spt) + return NULL; + + spt->shadow_page.page = alloc_page(gfp_mask); + if (!spt->shadow_page.page) { + kfree(spt); + return NULL; + } + return spt; +} + +static void free_spt(struct intel_vgpu_ppgtt_spt *spt) +{ + __free_page(spt->shadow_page.page); + kfree(spt); +} + +static void ppgtt_free_shadow_page(struct intel_vgpu_ppgtt_spt *spt) +{ + trace_spt_free(spt->vgpu->id, spt, spt->shadow_page.type); + + clean_shadow_page(&spt->shadow_page); + intel_vgpu_clean_guest_page(spt->vgpu, &spt->guest_page); + list_del_init(&spt->post_shadow_list); + + free_spt(spt); +} + +static void ppgtt_free_all_shadow_page(struct intel_vgpu *vgpu) +{ + struct hlist_node *n; + struct intel_vgpu_shadow_page *sp; + int i; + + hash_for_each_safe(vgpu->gtt.shadow_page_hash_table, i, n, sp, node) + ppgtt_free_shadow_page(shadow_page_to_ppgtt_spt(sp)); +} + +static int ppgtt_handle_guest_write_page_table_bytes(void *gp, + u64 pa, void *p_data, int bytes); + +static int ppgtt_write_protection_handler(void *gp, u64 pa, + void *p_data, int bytes) +{ + struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp; + int ret; + + if (bytes != 4 && bytes != 8) + return -EINVAL; + + if (!gpt->writeprotection) + return -EINVAL; + + ret = ppgtt_handle_guest_write_page_table_bytes(gp, + pa, p_data, bytes); + if (ret) + return ret; + return ret; +} + +static int reclaim_one_mm(struct intel_gvt *gvt); + +static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_shadow_page( + struct intel_vgpu *vgpu, int type, unsigned long gfn) +{ + struct intel_vgpu_ppgtt_spt *spt = NULL; + int ret; + +retry: + spt = alloc_spt(GFP_KERNEL | __GFP_ZERO); + if (!spt) { + if (reclaim_one_mm(vgpu->gvt)) + goto retry; + + gvt_err("fail to allocate ppgtt shadow page\n"); + return ERR_PTR(-ENOMEM); + } + + spt->vgpu = vgpu; + spt->guest_page_type = type; + atomic_set(&spt->refcount, 1); + INIT_LIST_HEAD(&spt->post_shadow_list); + + /* + * TODO: guest page type may be different with shadow page type, + * when we support PSE page in future. + */ + ret = init_shadow_page(vgpu, &spt->shadow_page, type); + if (ret) { + gvt_err("fail to initialize shadow page for spt\n"); + goto err; + } + + ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page, + gfn, ppgtt_write_protection_handler, NULL); + if (ret) { + gvt_err("fail to initialize guest page for spt\n"); + goto err; + } + + trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn); + return spt; +err: + ppgtt_free_shadow_page(spt); + return ERR_PTR(ret); +} + +static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page( + struct intel_vgpu *vgpu, unsigned long mfn) +{ + struct intel_vgpu_shadow_page *p = find_shadow_page(vgpu, mfn); + + if (p) + return shadow_page_to_ppgtt_spt(p); + + gvt_err("vgpu%d: fail to find ppgtt shadow page: 0x%lx\n", + vgpu->id, mfn); + return NULL; +} + +#define pt_entry_size_shift(spt) \ + ((spt)->vgpu->gvt->device_info.gtt_entry_size_shift) + +#define pt_entries(spt) \ + (GTT_PAGE_SIZE >> pt_entry_size_shift(spt)) + +#define for_each_present_guest_entry(spt, e, i) \ + for (i = 0; i < pt_entries(spt); i++) \ + if (spt->vgpu->gvt->gtt.pte_ops->test_present( \ + ppgtt_get_guest_entry(spt, e, i))) + +#define for_each_present_shadow_entry(spt, e, i) \ + for (i = 0; i < pt_entries(spt); i++) \ + if (spt->vgpu->gvt->gtt.pte_ops->test_present( \ + ppgtt_get_shadow_entry(spt, e, i))) + +static void ppgtt_get_shadow_page(struct intel_vgpu_ppgtt_spt *spt) +{ + int v = atomic_read(&spt->refcount); + + trace_spt_refcount(spt->vgpu->id, "inc", spt, v, (v + 1)); + + atomic_inc(&spt->refcount); +} + +static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt); + +static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu, + struct intel_gvt_gtt_entry *e) +{ + struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; + struct intel_vgpu_ppgtt_spt *s; + + if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(e->type)))) + return -EINVAL; + + if (ops->get_pfn(e) == vgpu->gtt.scratch_page_mfn) + return 0; + + s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e)); + if (!s) { + gvt_err("vgpu%d: fail to find shadow page: mfn: 0x%lx\n", + vgpu->id, ops->get_pfn(e)); + return -ENXIO; + } + return ppgtt_invalidate_shadow_page(s); +} + +static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) +{ + struct intel_gvt_gtt_entry e; + unsigned long index; + int ret; + int v = atomic_read(&spt->refcount); + + trace_spt_change(spt->vgpu->id, "die", spt, + spt->guest_page.gfn, spt->shadow_page.type); + + trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1)); + + if (atomic_dec_return(&spt->refcount) > 0) + return 0; + + if (gtt_type_is_pte_pt(spt->shadow_page.type)) + goto release; + + for_each_present_shadow_entry(spt, &e, index) { + if (!gtt_type_is_pt(get_next_pt_type(e.type))) { + gvt_err("GVT doesn't support pse bit for now\n"); + return -EINVAL; + } + ret = ppgtt_invalidate_shadow_page_by_shadow_entry( + spt->vgpu, &e); + if (ret) + goto fail; + } +release: + trace_spt_change(spt->vgpu->id, "release", spt, + spt->guest_page.gfn, spt->shadow_page.type); + ppgtt_free_shadow_page(spt); + return 0; +fail: + gvt_err("vgpu%d: fail: shadow page %p shadow entry 0x%llx type %d\n", + spt->vgpu->id, spt, e.val64, e.type); + return ret; +} + +static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt); + +static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry( + struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *we) +{ + struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; + struct intel_vgpu_ppgtt_spt *s = NULL; + struct intel_vgpu_guest_page *g; + int ret; + + if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) { + ret = -EINVAL; + goto fail; + } + + g = intel_vgpu_find_guest_page(vgpu, ops->get_pfn(we)); + if (g) { + s = guest_page_to_ppgtt_spt(g); + ppgtt_get_shadow_page(s); + } else { + int type = get_next_pt_type(we->type); + + s = ppgtt_alloc_shadow_page(vgpu, type, ops->get_pfn(we)); + if (IS_ERR(s)) { + ret = PTR_ERR(s); + goto fail; + } + + ret = intel_gvt_hypervisor_set_wp_page(vgpu, &s->guest_page); + if (ret) + goto fail; + + ret = ppgtt_populate_shadow_page(s); + if (ret) + goto fail; + + trace_spt_change(vgpu->id, "new", s, s->guest_page.gfn, + s->shadow_page.type); + } + return s; +fail: + gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", + vgpu->id, s, we->val64, we->type); + return ERR_PTR(ret); +} + +static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se, + struct intel_vgpu_ppgtt_spt *s, struct intel_gvt_gtt_entry *ge) +{ + struct intel_gvt_gtt_pte_ops *ops = s->vgpu->gvt->gtt.pte_ops; + + se->type = ge->type; + se->val64 = ge->val64; + + ops->set_pfn(se, s->shadow_page.mfn); +} + +static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) +{ + struct intel_vgpu *vgpu = spt->vgpu; + struct intel_vgpu_ppgtt_spt *s; + struct intel_gvt_gtt_entry se, ge; + unsigned long i; + int ret; + + trace_spt_change(spt->vgpu->id, "born", spt, + spt->guest_page.gfn, spt->shadow_page.type); + + if (gtt_type_is_pte_pt(spt->shadow_page.type)) { + for_each_present_guest_entry(spt, &ge, i) { + ret = gtt_entry_p2m(vgpu, &ge, &se); + if (ret) + goto fail; + ppgtt_set_shadow_entry(spt, &se, i); + } + return 0; + } + + for_each_present_guest_entry(spt, &ge, i) { + if (!gtt_type_is_pt(get_next_pt_type(ge.type))) { + gvt_err("GVT doesn't support pse bit now\n"); + ret = -EINVAL; + goto fail; + } + + s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge); + if (IS_ERR(s)) { + ret = PTR_ERR(s); + goto fail; + } + ppgtt_get_shadow_entry(spt, &se, i); + ppgtt_generate_shadow_entry(&se, s, &ge); + ppgtt_set_shadow_entry(spt, &se, i); + } + return 0; +fail: + gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", + vgpu->id, spt, ge.val64, ge.type); + return ret; +} + +static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt, + struct intel_gvt_gtt_entry *we, unsigned long index) +{ + struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); + struct intel_vgpu_shadow_page *sp = &spt->shadow_page; + struct intel_vgpu *vgpu = spt->vgpu; + struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; + struct intel_gvt_gtt_entry e; + int ret; + + trace_gpt_change(spt->vgpu->id, "remove", spt, sp->type, + we->val64, index); + + ppgtt_get_shadow_entry(spt, &e, index); + if (!ops->test_present(&e)) + return 0; + + if (ops->get_pfn(&e) == vgpu->gtt.scratch_page_mfn) + return 0; + + if (gtt_type_is_pt(get_next_pt_type(we->type))) { + struct intel_vgpu_guest_page *g = + intel_vgpu_find_guest_page(vgpu, ops->get_pfn(we)); + if (!g) { + gvt_err("fail to find guest page\n"); + ret = -ENXIO; + goto fail; + } + ret = ppgtt_invalidate_shadow_page(guest_page_to_ppgtt_spt(g)); + if (ret) + goto fail; + } + ops->set_pfn(&e, vgpu->gtt.scratch_page_mfn); + ppgtt_set_shadow_entry(spt, &e, index); + return 0; +fail: + gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", + vgpu->id, spt, we->val64, we->type); + return ret; +} + +static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt, + struct intel_gvt_gtt_entry *we, unsigned long index) +{ + struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); + struct intel_vgpu_shadow_page *sp = &spt->shadow_page; + struct intel_vgpu *vgpu = spt->vgpu; + struct intel_gvt_gtt_entry m; + struct intel_vgpu_ppgtt_spt *s; + int ret; + + trace_gpt_change(spt->vgpu->id, "add", spt, sp->type, + we->val64, index); + + if (gtt_type_is_pt(get_next_pt_type(we->type))) { + s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, we); + if (IS_ERR(s)) { + ret = PTR_ERR(s); + goto fail; + } + ppgtt_get_shadow_entry(spt, &m, index); + ppgtt_generate_shadow_entry(&m, s, we); + ppgtt_set_shadow_entry(spt, &m, index); + } else { + ret = gtt_entry_p2m(vgpu, we, &m); + if (ret) + goto fail; + ppgtt_set_shadow_entry(spt, &m, index); + } + return 0; +fail: + gvt_err("vgpu%d: fail: spt %p guest entry 0x%llx type %d\n", vgpu->id, + spt, we->val64, we->type); + return ret; +} + +static int sync_oos_page(struct intel_vgpu *vgpu, + struct intel_vgpu_oos_page *oos_page) +{ + const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; + struct intel_vgpu_ppgtt_spt *spt = + guest_page_to_ppgtt_spt(oos_page->guest_page); + struct intel_gvt_gtt_entry old, new, m; + int index; + int ret; + + trace_oos_change(vgpu->id, "sync", oos_page->id, + oos_page->guest_page, spt->guest_page_type); + + old.type = new.type = get_entry_type(spt->guest_page_type); + old.val64 = new.val64 = 0; + + for (index = 0; index < (GTT_PAGE_SIZE >> info->gtt_entry_size_shift); + index++) { + ops->get_entry(oos_page->mem, &old, index, false, 0, vgpu); + ops->get_entry(NULL, &new, index, true, + oos_page->guest_page->gfn << PAGE_SHIFT, vgpu); + + if (old.val64 == new.val64 + && !test_and_clear_bit(index, spt->post_shadow_bitmap)) + continue; + + trace_oos_sync(vgpu->id, oos_page->id, + oos_page->guest_page, spt->guest_page_type, + new.val64, index); + + ret = gtt_entry_p2m(vgpu, &new, &m); + if (ret) + return ret; + + ops->set_entry(oos_page->mem, &new, index, false, 0, vgpu); + ppgtt_set_shadow_entry(spt, &m, index); + } + + oos_page->guest_page->write_cnt = 0; + list_del_init(&spt->post_shadow_list); + return 0; +} + +static int detach_oos_page(struct intel_vgpu *vgpu, + struct intel_vgpu_oos_page *oos_page) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_vgpu_ppgtt_spt *spt = + guest_page_to_ppgtt_spt(oos_page->guest_page); + + trace_oos_change(vgpu->id, "detach", oos_page->id, + oos_page->guest_page, spt->guest_page_type); + + oos_page->guest_page->write_cnt = 0; + oos_page->guest_page->oos_page = NULL; + oos_page->guest_page = NULL; + + list_del_init(&oos_page->vm_list); + list_move_tail(&oos_page->list, &gvt->gtt.oos_page_free_list_head); + + return 0; +} + +static int attach_oos_page(struct intel_vgpu *vgpu, + struct intel_vgpu_oos_page *oos_page, + struct intel_vgpu_guest_page *gpt) +{ + struct intel_gvt *gvt = vgpu->gvt; + int ret; + + ret = intel_gvt_hypervisor_read_gpa(vgpu, gpt->gfn << GTT_PAGE_SHIFT, + oos_page->mem, GTT_PAGE_SIZE); + if (ret) + return ret; + + oos_page->guest_page = gpt; + gpt->oos_page = oos_page; + + list_move_tail(&oos_page->list, &gvt->gtt.oos_page_use_list_head); + + trace_oos_change(vgpu->id, "attach", gpt->oos_page->id, + gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type); + return 0; +} + +static int ppgtt_set_guest_page_sync(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *gpt) +{ + int ret; + + ret = intel_gvt_hypervisor_set_wp_page(vgpu, gpt); + if (ret) + return ret; + + trace_oos_change(vgpu->id, "set page sync", gpt->oos_page->id, + gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type); + + list_del_init(&gpt->oos_page->vm_list); + return sync_oos_page(vgpu, gpt->oos_page); +} + +static int ppgtt_allocate_oos_page(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *gpt) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt *gtt = &gvt->gtt; + struct intel_vgpu_oos_page *oos_page = gpt->oos_page; + int ret; + + WARN(oos_page, "shadow PPGTT page has already has a oos page\n"); + + if (list_empty(>t->oos_page_free_list_head)) { + oos_page = container_of(gtt->oos_page_use_list_head.next, + struct intel_vgpu_oos_page, list); + ret = ppgtt_set_guest_page_sync(vgpu, oos_page->guest_page); + if (ret) + return ret; + ret = detach_oos_page(vgpu, oos_page); + if (ret) + return ret; + } else + oos_page = container_of(gtt->oos_page_free_list_head.next, + struct intel_vgpu_oos_page, list); + return attach_oos_page(vgpu, oos_page, gpt); +} + +static int ppgtt_set_guest_page_oos(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *gpt) +{ + struct intel_vgpu_oos_page *oos_page = gpt->oos_page; + + if (WARN(!oos_page, "shadow PPGTT page should have a oos page\n")) + return -EINVAL; + + trace_oos_change(vgpu->id, "set page out of sync", gpt->oos_page->id, + gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type); + + list_add_tail(&oos_page->vm_list, &vgpu->gtt.oos_page_list_head); + return intel_gvt_hypervisor_unset_wp_page(vgpu, gpt); +} + +/** + * intel_vgpu_sync_oos_pages - sync all the out-of-synced shadow for vGPU + * @vgpu: a vGPU + * + * This function is called before submitting a guest workload to host, + * to sync all the out-of-synced shadow for vGPU + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu) +{ + struct list_head *pos, *n; + struct intel_vgpu_oos_page *oos_page; + int ret; + + if (!enable_out_of_sync) + return 0; + + list_for_each_safe(pos, n, &vgpu->gtt.oos_page_list_head) { + oos_page = container_of(pos, + struct intel_vgpu_oos_page, vm_list); + ret = ppgtt_set_guest_page_sync(vgpu, oos_page->guest_page); + if (ret) + return ret; + } + return 0; +} + +/* + * The heart of PPGTT shadow page table. + */ +static int ppgtt_handle_guest_write_page_table( + struct intel_vgpu_guest_page *gpt, + struct intel_gvt_gtt_entry *we, unsigned long index) +{ + struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); + struct intel_vgpu *vgpu = spt->vgpu; + struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; + struct intel_gvt_gtt_entry ge; + + int old_present, new_present; + int ret; + + ppgtt_get_guest_entry(spt, &ge, index); + + old_present = ops->test_present(&ge); + new_present = ops->test_present(we); + + ppgtt_set_guest_entry(spt, we, index); + + if (old_present) { + ret = ppgtt_handle_guest_entry_removal(gpt, &ge, index); + if (ret) + goto fail; + } + if (new_present) { + ret = ppgtt_handle_guest_entry_add(gpt, we, index); + if (ret) + goto fail; + } + return 0; +fail: + gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d.\n", + vgpu->id, spt, we->val64, we->type); + return ret; +} + +static inline bool can_do_out_of_sync(struct intel_vgpu_guest_page *gpt) +{ + return enable_out_of_sync + && gtt_type_is_pte_pt( + guest_page_to_ppgtt_spt(gpt)->guest_page_type) + && gpt->write_cnt >= 2; +} + +static void ppgtt_set_post_shadow(struct intel_vgpu_ppgtt_spt *spt, + unsigned long index) +{ + set_bit(index, spt->post_shadow_bitmap); + if (!list_empty(&spt->post_shadow_list)) + return; + + list_add_tail(&spt->post_shadow_list, + &spt->vgpu->gtt.post_shadow_list_head); +} + +/** + * intel_vgpu_flush_post_shadow - flush the post shadow transactions + * @vgpu: a vGPU + * + * This function is called before submitting a guest workload to host, + * to flush all the post shadows for a vGPU. + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu) +{ + struct list_head *pos, *n; + struct intel_vgpu_ppgtt_spt *spt; + struct intel_gvt_gtt_entry ge, e; + unsigned long index; + int ret; + + list_for_each_safe(pos, n, &vgpu->gtt.post_shadow_list_head) { + spt = container_of(pos, struct intel_vgpu_ppgtt_spt, + post_shadow_list); + + for_each_set_bit(index, spt->post_shadow_bitmap, + GTT_ENTRY_NUM_IN_ONE_PAGE) { + ppgtt_get_guest_entry(spt, &ge, index); + e = ge; + e.val64 = 0; + ppgtt_set_guest_entry(spt, &e, index); + + ret = ppgtt_handle_guest_write_page_table( + &spt->guest_page, &ge, index); + if (ret) + return ret; + clear_bit(index, spt->post_shadow_bitmap); + } + list_del_init(&spt->post_shadow_list); + } + return 0; +} + +static int ppgtt_handle_guest_write_page_table_bytes(void *gp, + u64 pa, void *p_data, int bytes) +{ + struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp; + struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); + struct intel_vgpu *vgpu = spt->vgpu; + struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; + const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; + struct intel_gvt_gtt_entry we; + unsigned long index; + int ret; + + index = (pa & (PAGE_SIZE - 1)) >> info->gtt_entry_size_shift; + + ppgtt_get_guest_entry(spt, &we, index); + memcpy((void *)&we.val64 + (pa & (info->gtt_entry_size - 1)), + p_data, bytes); + + ops->test_pse(&we); + + if (bytes == info->gtt_entry_size) { + ret = ppgtt_handle_guest_write_page_table(gpt, &we, index); + if (ret) + return ret; + } else { + struct intel_gvt_gtt_entry ge; + + ppgtt_get_guest_entry(spt, &ge, index); + + if (!test_bit(index, spt->post_shadow_bitmap)) { + ret = ppgtt_handle_guest_entry_removal(gpt, + &ge, index); + if (ret) + return ret; + } + + ppgtt_set_post_shadow(spt, index); + ppgtt_set_guest_entry(spt, &we, index); + } + + if (!enable_out_of_sync) + return 0; + + gpt->write_cnt++; + + if (gpt->oos_page) + ops->set_entry(gpt->oos_page->mem, &we, index, + false, 0, vgpu); + + if (can_do_out_of_sync(gpt)) { + if (!gpt->oos_page) + ppgtt_allocate_oos_page(vgpu, gpt); + + ret = ppgtt_set_guest_page_oos(vgpu, gpt); + if (ret < 0) + return ret; + } + return 0; +} + +/* + * mm page table allocation policy for bdw+ + * - for ggtt, only virtual page table will be allocated. + * - for ppgtt, dedicated virtual/shadow page table will be allocated. + */ +static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm) +{ + struct intel_vgpu *vgpu = mm->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + const struct intel_gvt_device_info *info = &gvt->device_info; + void *mem; + + if (mm->type == INTEL_GVT_MM_PPGTT) { + mm->page_table_entry_cnt = 4; + mm->page_table_entry_size = mm->page_table_entry_cnt * + info->gtt_entry_size; + mem = kzalloc(mm->has_shadow_page_table ? + mm->page_table_entry_size * 2 + : mm->page_table_entry_size, + GFP_ATOMIC); + if (!mem) + return -ENOMEM; + mm->virtual_page_table = mem; + if (!mm->has_shadow_page_table) + return 0; + mm->shadow_page_table = mem + mm->page_table_entry_size; + } else if (mm->type == INTEL_GVT_MM_GGTT) { + mm->page_table_entry_cnt = + (gvt_ggtt_gm_sz(gvt) >> GTT_PAGE_SHIFT); + mm->page_table_entry_size = mm->page_table_entry_cnt * + info->gtt_entry_size; + mem = vzalloc(mm->page_table_entry_size); + if (!mem) + return -ENOMEM; + mm->virtual_page_table = mem; + } + return 0; +} + +static void gen8_mm_free_page_table(struct intel_vgpu_mm *mm) +{ + if (mm->type == INTEL_GVT_MM_PPGTT) { + kfree(mm->virtual_page_table); + } else if (mm->type == INTEL_GVT_MM_GGTT) { + if (mm->virtual_page_table) + vfree(mm->virtual_page_table); + } + mm->virtual_page_table = mm->shadow_page_table = NULL; +} + +static void invalidate_mm(struct intel_vgpu_mm *mm) +{ + struct intel_vgpu *vgpu = mm->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt *gtt = &gvt->gtt; + struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops; + struct intel_gvt_gtt_entry se; + int i; + + if (WARN_ON(!mm->has_shadow_page_table || !mm->shadowed)) + return; + + for (i = 0; i < mm->page_table_entry_cnt; i++) { + ppgtt_get_shadow_root_entry(mm, &se, i); + if (!ops->test_present(&se)) + continue; + ppgtt_invalidate_shadow_page_by_shadow_entry( + vgpu, &se); + se.val64 = 0; + ppgtt_set_shadow_root_entry(mm, &se, i); + + trace_gpt_change(vgpu->id, "destroy root pointer", + NULL, se.type, se.val64, i); + } + mm->shadowed = false; +} + +/** + * intel_vgpu_destroy_mm - destroy a mm object + * @mm: a kref object + * + * This function is used to destroy a mm object for vGPU + * + */ +void intel_vgpu_destroy_mm(struct kref *mm_ref) +{ + struct intel_vgpu_mm *mm = container_of(mm_ref, typeof(*mm), ref); + struct intel_vgpu *vgpu = mm->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt *gtt = &gvt->gtt; + + if (!mm->initialized) + goto out; + + list_del(&mm->list); + list_del(&mm->lru_list); + + if (mm->has_shadow_page_table) + invalidate_mm(mm); + + gtt->mm_free_page_table(mm); +out: + kfree(mm); +} + +static int shadow_mm(struct intel_vgpu_mm *mm) +{ + struct intel_vgpu *vgpu = mm->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt *gtt = &gvt->gtt; + struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops; + struct intel_vgpu_ppgtt_spt *spt; + struct intel_gvt_gtt_entry ge, se; + int i; + int ret; + + if (WARN_ON(!mm->has_shadow_page_table || mm->shadowed)) + return 0; + + mm->shadowed = true; + + for (i = 0; i < mm->page_table_entry_cnt; i++) { + ppgtt_get_guest_root_entry(mm, &ge, i); + if (!ops->test_present(&ge)) + continue; + + trace_gpt_change(vgpu->id, __func__, NULL, + ge.type, ge.val64, i); + + spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge); + if (IS_ERR(spt)) { + gvt_err("fail to populate guest root pointer\n"); + ret = PTR_ERR(spt); + goto fail; + } + ppgtt_generate_shadow_entry(&se, spt, &ge); + ppgtt_set_shadow_root_entry(mm, &se, i); + + trace_gpt_change(vgpu->id, "populate root pointer", + NULL, se.type, se.val64, i); + } + return 0; +fail: + invalidate_mm(mm); + return ret; +} + +/** + * intel_vgpu_create_mm - create a mm object for a vGPU + * @vgpu: a vGPU + * @mm_type: mm object type, should be PPGTT or GGTT + * @virtual_page_table: page table root pointers. Could be NULL if user wants + * to populate shadow later. + * @page_table_level: describe the page table level of the mm object + * @pde_base_index: pde root pointer base in GGTT MMIO. + * + * This function is used to create a mm object for a vGPU. + * + * Returns: + * Zero on success, negative error code in pointer if failed. + */ +struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, + int mm_type, void *virtual_page_table, int page_table_level, + u32 pde_base_index) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt *gtt = &gvt->gtt; + struct intel_vgpu_mm *mm; + int ret; + + mm = kzalloc(sizeof(*mm), GFP_ATOMIC); + if (!mm) { + ret = -ENOMEM; + goto fail; + } + + mm->type = mm_type; + + if (page_table_level == 1) + mm->page_table_entry_type = GTT_TYPE_GGTT_PTE; + else if (page_table_level == 3) + mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY; + else if (page_table_level == 4) + mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY; + else { + WARN_ON(1); + ret = -EINVAL; + goto fail; + } + + mm->page_table_level = page_table_level; + mm->pde_base_index = pde_base_index; + + mm->vgpu = vgpu; + mm->has_shadow_page_table = !!(mm_type == INTEL_GVT_MM_PPGTT); + + kref_init(&mm->ref); + atomic_set(&mm->pincount, 0); + INIT_LIST_HEAD(&mm->list); + INIT_LIST_HEAD(&mm->lru_list); + list_add_tail(&mm->list, &vgpu->gtt.mm_list_head); + + ret = gtt->mm_alloc_page_table(mm); + if (ret) { + gvt_err("fail to allocate page table for mm\n"); + goto fail; + } + + mm->initialized = true; + + if (virtual_page_table) + memcpy(mm->virtual_page_table, virtual_page_table, + mm->page_table_entry_size); + + if (mm->has_shadow_page_table) { + ret = shadow_mm(mm); + if (ret) + goto fail; + list_add_tail(&mm->lru_list, &gvt->gtt.mm_lru_list_head); + } + return mm; +fail: + gvt_err("fail to create mm\n"); + if (mm) + intel_gvt_mm_unreference(mm); + return ERR_PTR(ret); +} + +/** + * intel_vgpu_unpin_mm - decrease the pin count of a vGPU mm object + * @mm: a vGPU mm object + * + * This function is called when user doesn't want to use a vGPU mm object + */ +void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm) +{ + if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT)) + return; + + atomic_dec(&mm->pincount); +} + +/** + * intel_vgpu_pin_mm - increase the pin count of a vGPU mm object + * @vgpu: a vGPU + * + * This function is called when user wants to use a vGPU mm object. If this + * mm object hasn't been shadowed yet, the shadow will be populated at this + * time. + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm) +{ + int ret; + + if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT)) + return 0; + + atomic_inc(&mm->pincount); + + if (!mm->shadowed) { + ret = shadow_mm(mm); + if (ret) + return ret; + } + + list_del_init(&mm->lru_list); + list_add_tail(&mm->lru_list, &mm->vgpu->gvt->gtt.mm_lru_list_head); + return 0; +} + +static int reclaim_one_mm(struct intel_gvt *gvt) +{ + struct intel_vgpu_mm *mm; + struct list_head *pos, *n; + + list_for_each_safe(pos, n, &gvt->gtt.mm_lru_list_head) { + mm = container_of(pos, struct intel_vgpu_mm, lru_list); + + if (mm->type != INTEL_GVT_MM_PPGTT) + continue; + if (atomic_read(&mm->pincount)) + continue; + + list_del_init(&mm->lru_list); + invalidate_mm(mm); + return 1; + } + return 0; +} + +/* + * GMA translation APIs. + */ +static inline int ppgtt_get_next_level_entry(struct intel_vgpu_mm *mm, + struct intel_gvt_gtt_entry *e, unsigned long index, bool guest) +{ + struct intel_vgpu *vgpu = mm->vgpu; + struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; + struct intel_vgpu_ppgtt_spt *s; + + if (WARN_ON(!mm->has_shadow_page_table)) + return -EINVAL; + + s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e)); + if (!s) + return -ENXIO; + + if (!guest) + ppgtt_get_shadow_entry(s, e, index); + else + ppgtt_get_guest_entry(s, e, index); + return 0; +} + +/** + * intel_vgpu_gma_to_gpa - translate a gma to GPA + * @mm: mm object. could be a PPGTT or GGTT mm object + * @gma: graphics memory address in this mm object + * + * This function is used to translate a graphics memory address in specific + * graphics memory space to guest physical address. + * + * Returns: + * Guest physical address on success, INTEL_GVT_INVALID_ADDR if failed. + */ +unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma) +{ + struct intel_vgpu *vgpu = mm->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt_pte_ops *pte_ops = gvt->gtt.pte_ops; + struct intel_gvt_gtt_gma_ops *gma_ops = gvt->gtt.gma_ops; + unsigned long gpa = INTEL_GVT_INVALID_ADDR; + unsigned long gma_index[4]; + struct intel_gvt_gtt_entry e; + int i, index; + int ret; + + if (mm->type != INTEL_GVT_MM_GGTT && mm->type != INTEL_GVT_MM_PPGTT) + return INTEL_GVT_INVALID_ADDR; + + if (mm->type == INTEL_GVT_MM_GGTT) { + if (!vgpu_gmadr_is_valid(vgpu, gma)) + goto err; + + ggtt_get_guest_entry(mm, &e, + gma_ops->gma_to_ggtt_pte_index(gma)); + gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT) + + (gma & ~GTT_PAGE_MASK); + + trace_gma_translate(vgpu->id, "ggtt", 0, 0, gma, gpa); + return gpa; + } + + switch (mm->page_table_level) { + case 4: + ppgtt_get_shadow_root_entry(mm, &e, 0); + gma_index[0] = gma_ops->gma_to_pml4_index(gma); + gma_index[1] = gma_ops->gma_to_l4_pdp_index(gma); + gma_index[2] = gma_ops->gma_to_pde_index(gma); + gma_index[3] = gma_ops->gma_to_pte_index(gma); + index = 4; + break; + case 3: + ppgtt_get_shadow_root_entry(mm, &e, + gma_ops->gma_to_l3_pdp_index(gma)); + gma_index[0] = gma_ops->gma_to_pde_index(gma); + gma_index[1] = gma_ops->gma_to_pte_index(gma); + index = 2; + break; + case 2: + ppgtt_get_shadow_root_entry(mm, &e, + gma_ops->gma_to_pde_index(gma)); + gma_index[0] = gma_ops->gma_to_pte_index(gma); + index = 1; + break; + default: + WARN_ON(1); + goto err; + } + + /* walk into the shadow page table and get gpa from guest entry */ + for (i = 0; i < index; i++) { + ret = ppgtt_get_next_level_entry(mm, &e, gma_index[i], + (i == index - 1)); + if (ret) + goto err; + } + + gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT) + + (gma & ~GTT_PAGE_MASK); + + trace_gma_translate(vgpu->id, "ppgtt", 0, + mm->page_table_level, gma, gpa); + return gpa; +err: + gvt_err("invalid mm type: %d gma %lx\n", mm->type, gma); + return INTEL_GVT_INVALID_ADDR; +} + +static int emulate_gtt_mmio_read(struct intel_vgpu *vgpu, + unsigned int off, void *p_data, unsigned int bytes) +{ + struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm; + const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; + unsigned long index = off >> info->gtt_entry_size_shift; + struct intel_gvt_gtt_entry e; + + if (bytes != 4 && bytes != 8) + return -EINVAL; + + ggtt_get_guest_entry(ggtt_mm, &e, index); + memcpy(p_data, (void *)&e.val64 + (off & (info->gtt_entry_size - 1)), + bytes); + return 0; +} + +/** + * intel_vgpu_emulate_gtt_mmio_read - emulate GTT MMIO register read + * @vgpu: a vGPU + * @off: register offset + * @p_data: data will be returned to guest + * @bytes: data length + * + * This function is used to emulate the GTT MMIO register read + * + * Returns: + * Zero on success, error code if failed. + */ +int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, unsigned int off, + void *p_data, unsigned int bytes) +{ + const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; + int ret; + + if (bytes != 4 && bytes != 8) + return -EINVAL; + + off -= info->gtt_start_offset; + ret = emulate_gtt_mmio_read(vgpu, off, p_data, bytes); + return ret; +} + +static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, + void *p_data, unsigned int bytes) +{ + struct intel_gvt *gvt = vgpu->gvt; + const struct intel_gvt_device_info *info = &gvt->device_info; + struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm; + struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; + unsigned long g_gtt_index = off >> info->gtt_entry_size_shift; + unsigned long gma; + struct intel_gvt_gtt_entry e, m; + int ret; + + if (bytes != 4 && bytes != 8) + return -EINVAL; + + gma = g_gtt_index << GTT_PAGE_SHIFT; + + /* the VM may configure the whole GM space when ballooning is used */ + if (WARN_ONCE(!vgpu_gmadr_is_valid(vgpu, gma), + "vgpu%d: found oob ggtt write, offset %x\n", + vgpu->id, off)) { + return 0; + } + + ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index); + + memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data, + bytes); + + if (ops->test_present(&e)) { + ret = gtt_entry_p2m(vgpu, &e, &m); + if (ret) { + gvt_err("vgpu%d: fail to translate guest gtt entry\n", + vgpu->id); + return ret; + } + } else { + m = e; + m.val64 = 0; + } + + ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index); + ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); + return 0; +} + +/* + * intel_vgpu_emulate_gtt_mmio_write - emulate GTT MMIO register write + * @vgpu: a vGPU + * @off: register offset + * @p_data: data from guest write + * @bytes: data length + * + * This function is used to emulate the GTT MMIO register write + * + * Returns: + * Zero on success, error code if failed. + */ +int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, + void *p_data, unsigned int bytes) +{ + const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; + int ret; + + if (bytes != 4 && bytes != 8) + return -EINVAL; + + off -= info->gtt_start_offset; + ret = emulate_gtt_mmio_write(vgpu, off, p_data, bytes); + return ret; +} + +bool intel_gvt_create_scratch_page(struct intel_vgpu *vgpu) +{ + struct intel_vgpu_gtt *gtt = &vgpu->gtt; + void *p; + void *vaddr; + unsigned long mfn; + + gtt->scratch_page = alloc_page(GFP_KERNEL); + if (!gtt->scratch_page) { + gvt_err("Failed to allocate scratch page.\n"); + return -ENOMEM; + } + + /* set to zero */ + p = kmap_atomic(gtt->scratch_page); + memset(p, 0, PAGE_SIZE); + kunmap_atomic(p); + + /* translate page to mfn */ + vaddr = page_address(gtt->scratch_page); + mfn = intel_gvt_hypervisor_virt_to_mfn(vaddr); + + if (mfn == INTEL_GVT_INVALID_ADDR) { + gvt_err("fail to translate vaddr:0x%llx\n", (u64)vaddr); + __free_page(gtt->scratch_page); + gtt->scratch_page = NULL; + return -ENXIO; + } + + gtt->scratch_page_mfn = mfn; + gvt_dbg_core("vgpu%d create scratch page: mfn=0x%lx\n", vgpu->id, mfn); + return 0; +} + +void intel_gvt_release_scratch_page(struct intel_vgpu *vgpu) +{ + if (vgpu->gtt.scratch_page != NULL) { + __free_page(vgpu->gtt.scratch_page); + vgpu->gtt.scratch_page = NULL; + vgpu->gtt.scratch_page_mfn = 0; + } +} + +/** + * intel_vgpu_init_gtt - initialize per-vGPU graphics memory virulization + * @vgpu: a vGPU + * + * This function is used to initialize per-vGPU graphics memory virtualization + * components. + * + * Returns: + * Zero on success, error code if failed. + */ +int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) +{ + struct intel_vgpu_gtt *gtt = &vgpu->gtt; + struct intel_vgpu_mm *ggtt_mm; + + hash_init(gtt->guest_page_hash_table); + hash_init(gtt->shadow_page_hash_table); + + INIT_LIST_HEAD(>t->mm_list_head); + INIT_LIST_HEAD(>t->oos_page_list_head); + INIT_LIST_HEAD(>t->post_shadow_list_head); + + ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT, + NULL, 1, 0); + if (IS_ERR(ggtt_mm)) { + gvt_err("fail to create mm for ggtt.\n"); + return PTR_ERR(ggtt_mm); + } + + gtt->ggtt_mm = ggtt_mm; + + intel_gvt_create_scratch_page(vgpu); + return 0; +} + +/** + * intel_vgpu_clean_gtt - clean up per-vGPU graphics memory virulization + * @vgpu: a vGPU + * + * This function is used to clean up per-vGPU graphics memory virtualization + * components. + * + * Returns: + * Zero on success, error code if failed. + */ +void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu) +{ + struct list_head *pos, *n; + struct intel_vgpu_mm *mm; + + ppgtt_free_all_shadow_page(vgpu); + intel_gvt_release_scratch_page(vgpu); + + list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) { + mm = container_of(pos, struct intel_vgpu_mm, list); + vgpu->gvt->gtt.mm_free_page_table(mm); + list_del(&mm->list); + list_del(&mm->lru_list); + kfree(mm); + } +} + +static void clean_spt_oos(struct intel_gvt *gvt) +{ + struct intel_gvt_gtt *gtt = &gvt->gtt; + struct list_head *pos, *n; + struct intel_vgpu_oos_page *oos_page; + + WARN(!list_empty(>t->oos_page_use_list_head), + "someone is still using oos page\n"); + + list_for_each_safe(pos, n, >t->oos_page_free_list_head) { + oos_page = container_of(pos, struct intel_vgpu_oos_page, list); + list_del(&oos_page->list); + kfree(oos_page); + } +} + +static int setup_spt_oos(struct intel_gvt *gvt) +{ + struct intel_gvt_gtt *gtt = &gvt->gtt; + struct intel_vgpu_oos_page *oos_page; + int i; + int ret; + + INIT_LIST_HEAD(>t->oos_page_free_list_head); + INIT_LIST_HEAD(>t->oos_page_use_list_head); + + for (i = 0; i < preallocated_oos_pages; i++) { + oos_page = kzalloc(sizeof(*oos_page), GFP_KERNEL); + if (!oos_page) { + gvt_err("fail to pre-allocate oos page\n"); + ret = -ENOMEM; + goto fail; + } + + INIT_LIST_HEAD(&oos_page->list); + INIT_LIST_HEAD(&oos_page->vm_list); + oos_page->id = i; + list_add_tail(&oos_page->list, >t->oos_page_free_list_head); + } + + gvt_dbg_mm("%d oos pages preallocated\n", i); + + return 0; +fail: + clean_spt_oos(gvt); + return ret; +} + +/** + * intel_vgpu_find_ppgtt_mm - find a PPGTT mm object + * @vgpu: a vGPU + * @page_table_level: PPGTT page table level + * @root_entry: PPGTT page table root pointers + * + * This function is used to find a PPGTT mm object from mm object pool + * + * Returns: + * pointer to mm object on success, NULL if failed. + */ +struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, + int page_table_level, void *root_entry) +{ + struct list_head *pos; + struct intel_vgpu_mm *mm; + u64 *src, *dst; + + list_for_each(pos, &vgpu->gtt.mm_list_head) { + mm = container_of(pos, struct intel_vgpu_mm, list); + if (mm->type != INTEL_GVT_MM_PPGTT) + continue; + + if (mm->page_table_level != page_table_level) + continue; + + src = root_entry; + dst = mm->virtual_page_table; + + if (page_table_level == 3) { + if (src[0] == dst[0] + && src[1] == dst[1] + && src[2] == dst[2] + && src[3] == dst[3]) + return mm; + } else { + if (src[0] == dst[0]) + return mm; + } + } + return NULL; +} + +/** + * intel_vgpu_g2v_create_ppgtt_mm - create a PPGTT mm object from + * g2v notification + * @vgpu: a vGPU + * @page_table_level: PPGTT page table level + * + * This function is used to create a PPGTT mm object from a guest to GVT-g + * notification. + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, + int page_table_level) +{ + u64 *pdp = (u64 *)&vgpu_vreg64(vgpu, vgtif_reg(pdp[0])); + struct intel_vgpu_mm *mm; + + if (WARN_ON((page_table_level != 4) && (page_table_level != 3))) + return -EINVAL; + + mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp); + if (mm) { + intel_gvt_mm_reference(mm); + } else { + mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_PPGTT, + pdp, page_table_level, 0); + if (IS_ERR(mm)) { + gvt_err("fail to create mm\n"); + return PTR_ERR(mm); + } + } + return 0; +} + +/** + * intel_vgpu_g2v_destroy_ppgtt_mm - destroy a PPGTT mm object from + * g2v notification + * @vgpu: a vGPU + * @page_table_level: PPGTT page table level + * + * This function is used to create a PPGTT mm object from a guest to GVT-g + * notification. + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, + int page_table_level) +{ + u64 *pdp = (u64 *)&vgpu_vreg64(vgpu, vgtif_reg(pdp[0])); + struct intel_vgpu_mm *mm; + + if (WARN_ON((page_table_level != 4) && (page_table_level != 3))) + return -EINVAL; + + mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp); + if (!mm) { + gvt_err("fail to find ppgtt instance.\n"); + return -EINVAL; + } + intel_gvt_mm_unreference(mm); + return 0; +} + +/** + * intel_gvt_init_gtt - initialize mm components of a GVT device + * @gvt: GVT device + * + * This function is called at the initialization stage, to initialize + * the mm components of a GVT device. + * + * Returns: + * zero on success, negative error code if failed. + */ +int intel_gvt_init_gtt(struct intel_gvt *gvt) +{ + int ret; + + gvt_dbg_core("init gtt\n"); + + if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { + gvt->gtt.pte_ops = &gen8_gtt_pte_ops; + gvt->gtt.gma_ops = &gen8_gtt_gma_ops; + gvt->gtt.mm_alloc_page_table = gen8_mm_alloc_page_table; + gvt->gtt.mm_free_page_table = gen8_mm_free_page_table; + } else { + return -ENODEV; + } + + if (enable_out_of_sync) { + ret = setup_spt_oos(gvt); + if (ret) { + gvt_err("fail to initialize SPT oos\n"); + return ret; + } + } + INIT_LIST_HEAD(&gvt->gtt.mm_lru_list_head); + return 0; +} + +/** + * intel_gvt_clean_gtt - clean up mm components of a GVT device + * @gvt: GVT device + * + * This function is called at the driver unloading stage, to clean up the + * the mm components of a GVT device. + * + */ +void intel_gvt_clean_gtt(struct intel_gvt *gvt) +{ + if (enable_out_of_sync) + clean_spt_oos(gvt); +} diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h new file mode 100644 index 000000000000..e4dcde78f3f9 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/gtt.h @@ -0,0 +1,270 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Zhi Wang + * Zhenyu Wang + * Xiao Zheng + * + * Contributors: + * Min He + * Bing Niu + * + */ + +#ifndef _GVT_GTT_H_ +#define _GVT_GTT_H_ + +#define GTT_PAGE_SHIFT 12 +#define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT) +#define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1)) + +struct intel_vgpu_mm; + +#define INTEL_GVT_GTT_HASH_BITS 8 +#define INTEL_GVT_INVALID_ADDR (~0UL) + +struct intel_gvt_gtt_entry { + u64 val64; + int type; +}; + +struct intel_gvt_gtt_pte_ops { + struct intel_gvt_gtt_entry *(*get_entry)(void *pt, + struct intel_gvt_gtt_entry *e, + unsigned long index, bool hypervisor_access, unsigned long gpa, + struct intel_vgpu *vgpu); + struct intel_gvt_gtt_entry *(*set_entry)(void *pt, + struct intel_gvt_gtt_entry *e, + unsigned long index, bool hypervisor_access, unsigned long gpa, + struct intel_vgpu *vgpu); + bool (*test_present)(struct intel_gvt_gtt_entry *e); + void (*clear_present)(struct intel_gvt_gtt_entry *e); + bool (*test_pse)(struct intel_gvt_gtt_entry *e); + void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn); + unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e); +}; + +struct intel_gvt_gtt_gma_ops { + unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma); + unsigned long (*gma_to_pte_index)(unsigned long gma); + unsigned long (*gma_to_pde_index)(unsigned long gma); + unsigned long (*gma_to_l3_pdp_index)(unsigned long gma); + unsigned long (*gma_to_l4_pdp_index)(unsigned long gma); + unsigned long (*gma_to_pml4_index)(unsigned long gma); +}; + +struct intel_gvt_gtt { + struct intel_gvt_gtt_pte_ops *pte_ops; + struct intel_gvt_gtt_gma_ops *gma_ops; + int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm); + void (*mm_free_page_table)(struct intel_vgpu_mm *mm); + struct list_head oos_page_use_list_head; + struct list_head oos_page_free_list_head; + struct list_head mm_lru_list_head; +}; + +enum { + INTEL_GVT_MM_GGTT = 0, + INTEL_GVT_MM_PPGTT, +}; + +struct intel_vgpu_mm { + int type; + bool initialized; + bool shadowed; + + int page_table_entry_type; + u32 page_table_entry_size; + u32 page_table_entry_cnt; + void *virtual_page_table; + void *shadow_page_table; + + int page_table_level; + bool has_shadow_page_table; + u32 pde_base_index; + + struct list_head list; + struct kref ref; + atomic_t pincount; + struct list_head lru_list; + struct intel_vgpu *vgpu; +}; + +extern struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry( + struct intel_vgpu_mm *mm, + void *page_table, struct intel_gvt_gtt_entry *e, + unsigned long index); + +extern struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry( + struct intel_vgpu_mm *mm, + void *page_table, struct intel_gvt_gtt_entry *e, + unsigned long index); + +#define ggtt_get_guest_entry(mm, e, index) \ + intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) + +#define ggtt_set_guest_entry(mm, e, index) \ + intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) + +#define ggtt_get_shadow_entry(mm, e, index) \ + intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) + +#define ggtt_set_shadow_entry(mm, e, index) \ + intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) + +#define ppgtt_get_guest_root_entry(mm, e, index) \ + intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) + +#define ppgtt_set_guest_root_entry(mm, e, index) \ + intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) + +#define ppgtt_get_shadow_root_entry(mm, e, index) \ + intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) + +#define ppgtt_set_shadow_root_entry(mm, e, index) \ + intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) + +extern struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, + int mm_type, void *virtual_page_table, int page_table_level, + u32 pde_base_index); +extern void intel_vgpu_destroy_mm(struct kref *mm_ref); + +struct intel_vgpu_guest_page; + +struct intel_vgpu_gtt { + struct intel_vgpu_mm *ggtt_mm; + unsigned long active_ppgtt_mm_bitmap; + struct list_head mm_list_head; + DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS); + DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); + atomic_t n_write_protected_guest_page; + struct list_head oos_page_list_head; + struct list_head post_shadow_list_head; + struct page *scratch_page; + unsigned long scratch_page_mfn; +}; + +extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu); +extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu); + +extern int intel_gvt_init_gtt(struct intel_gvt *gvt); +extern void intel_gvt_clean_gtt(struct intel_gvt *gvt); + +extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu, + int page_table_level, void *root_entry); + +struct intel_vgpu_oos_page; + +struct intel_vgpu_shadow_page { + void *vaddr; + struct page *page; + int type; + struct hlist_node node; + unsigned long mfn; +}; + +struct intel_vgpu_guest_page { + struct hlist_node node; + bool writeprotection; + unsigned long gfn; + int (*handler)(void *, u64, void *, int); + void *data; + unsigned long write_cnt; + struct intel_vgpu_oos_page *oos_page; +}; + +struct intel_vgpu_oos_page { + struct intel_vgpu_guest_page *guest_page; + struct list_head list; + struct list_head vm_list; + int id; + unsigned char mem[GTT_PAGE_SIZE]; +}; + +#define GTT_ENTRY_NUM_IN_ONE_PAGE 512 + +struct intel_vgpu_ppgtt_spt { + struct intel_vgpu_shadow_page shadow_page; + struct intel_vgpu_guest_page guest_page; + int guest_page_type; + atomic_t refcount; + struct intel_vgpu *vgpu; + DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE); + struct list_head post_shadow_list; +}; + +int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *guest_page, + unsigned long gfn, + int (*handler)(void *gp, u64, void *, int), + void *data); + +void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *guest_page); + +int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *guest_page); + +void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *guest_page); + +struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( + struct intel_vgpu *vgpu, unsigned long gfn); + +int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu); + +int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu); + +static inline void intel_gvt_mm_reference(struct intel_vgpu_mm *mm) +{ + kref_get(&mm->ref); +} + +static inline void intel_gvt_mm_unreference(struct intel_vgpu_mm *mm) +{ + kref_put(&mm->ref, intel_vgpu_destroy_mm); +} + +int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm); + +void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm); + +unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, + unsigned long gma); + +struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, + int page_table_level, void *root_entry); + +int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, + int page_table_level); + +int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, + int page_table_level); + +int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, + unsigned int off, void *p_data, unsigned int bytes); + +int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, + unsigned int off, void *p_data, unsigned int bytes); + +#endif /* _GVT_GTT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 29efe454b1cd..5063c672736d 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -101,6 +101,9 @@ static void init_device_info(struct intel_gvt *gvt) info->mmio_size = 2 * 1024 * 1024; info->mmio_bar = 0; info->msi_cap_offset = IS_SKYLAKE(gvt->dev_priv) ? 0xac : 0x90; + info->gtt_start_offset = 8 * 1024 * 1024; + info->gtt_entry_size = 8; + info->gtt_entry_size_shift = 3; } } @@ -119,6 +122,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) if (WARN_ON(!gvt->initialized)) return; + intel_gvt_clean_gtt(gvt); intel_gvt_clean_irq(gvt); intel_gvt_clean_mmio_info(gvt); intel_gvt_free_firmware(gvt); @@ -171,10 +175,16 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (ret) goto out_free_firmware; + ret = intel_gvt_init_gtt(gvt); + if (ret) + goto out_clean_irq; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; +out_clean_irq: + intel_gvt_clean_irq(gvt); out_free_firmware: intel_gvt_free_firmware(gvt); out_clean_mmio_info: diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 655e6afb0aca..11267e73671a 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -38,6 +38,7 @@ #include "mmio.h" #include "reg.h" #include "interrupt.h" +#include "gtt.h" #define GVT_MAX_VGPU 8 @@ -61,6 +62,9 @@ struct intel_gvt_device_info { u32 mmio_size; u32 mmio_bar; unsigned long msi_cap_offset; + u32 gtt_start_offset; + u32 gtt_entry_size; + u32 gtt_entry_size_shift; }; /* GM resources owned by a vGPU */ @@ -116,6 +120,7 @@ struct intel_vgpu { struct intel_vgpu_cfg_space cfg_space; struct intel_vgpu_mmio mmio; struct intel_vgpu_irq irq; + struct intel_vgpu_gtt gtt; }; struct intel_gvt_gm { @@ -153,6 +158,7 @@ struct intel_gvt { struct intel_gvt_mmio mmio; struct intel_gvt_firmware firmware; struct intel_gvt_irq irq; + struct intel_gvt_gtt gtt; }; void intel_gvt_free_firmware(struct intel_gvt *gvt); @@ -262,6 +268,38 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu); +/* validating GM functions */ +#define vgpu_gmadr_is_aperture(vgpu, gmadr) \ + ((gmadr >= vgpu_aperture_gmadr_base(vgpu)) && \ + (gmadr <= vgpu_aperture_gmadr_end(vgpu))) + +#define vgpu_gmadr_is_hidden(vgpu, gmadr) \ + ((gmadr >= vgpu_hidden_gmadr_base(vgpu)) && \ + (gmadr <= vgpu_hidden_gmadr_end(vgpu))) + +#define vgpu_gmadr_is_valid(vgpu, gmadr) \ + ((vgpu_gmadr_is_aperture(vgpu, gmadr) || \ + (vgpu_gmadr_is_hidden(vgpu, gmadr)))) + +#define gvt_gmadr_is_aperture(gvt, gmadr) \ + ((gmadr >= gvt_aperture_gmadr_base(gvt)) && \ + (gmadr <= gvt_aperture_gmadr_end(gvt))) + +#define gvt_gmadr_is_hidden(gvt, gmadr) \ + ((gmadr >= gvt_hidden_gmadr_base(gvt)) && \ + (gmadr <= gvt_hidden_gmadr_end(gvt))) + +#define gvt_gmadr_is_valid(gvt, gmadr) \ + (gvt_gmadr_is_aperture(gvt, gmadr) || \ + gvt_gmadr_is_hidden(gvt, gmadr)) + +bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size); +int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr); +int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr); +int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index, + unsigned long *h_index); +int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, + unsigned long *g_index); #include "mpt.h" #endif diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index f43614eb3b14..67d8b1a26e73 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -42,6 +42,14 @@ struct intel_gvt_mpt { int (*attach_vgpu)(void *vgpu, unsigned long *handle); void (*detach_vgpu)(unsigned long handle); int (*inject_msi)(unsigned long handle, u32 addr, u16 data); + unsigned long (*from_virt_to_mfn)(void *p); + int (*set_wp_page)(unsigned long handle, u64 gfn); + int (*unset_wp_page)(unsigned long handle, u64 gfn); + int (*read_gpa)(unsigned long handle, unsigned long gpa, void *buf, + unsigned long len); + int (*write_gpa)(unsigned long handle, unsigned long gpa, void *buf, + unsigned long len); + unsigned long (*gfn_to_mfn)(unsigned long handle, unsigned long gfn); }; extern struct intel_gvt_mpt xengt_mpt; diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index 31a837195745..46664771cc58 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -117,4 +117,111 @@ static inline int intel_gvt_hypervisor_inject_msi(struct intel_vgpu *vgpu) return 0; } +/** + * intel_gvt_hypervisor_set_wp_page - translate a host VA into MFN + * @p: host kernel virtual address + * + * Returns: + * MFN on success, INTEL_GVT_INVALID_ADDR if failed. + */ +static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p) +{ + return intel_gvt_host.mpt->from_virt_to_mfn(p); +} + +/** + * intel_gvt_hypervisor_set_wp_page - set a guest page to write-protected + * @vgpu: a vGPU + * @p: intel_vgpu_guest_page + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline int intel_gvt_hypervisor_set_wp_page(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *p) +{ + int ret; + + if (p->writeprotection) + return 0; + + ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, p->gfn); + if (ret) + return ret; + p->writeprotection = true; + atomic_inc(&vgpu->gtt.n_write_protected_guest_page); + return 0; +} + +/** + * intel_gvt_hypervisor_unset_wp_page - remove the write-protection of a + * guest page + * @vgpu: a vGPU + * @p: intel_vgpu_guest_page + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline int intel_gvt_hypervisor_unset_wp_page(struct intel_vgpu *vgpu, + struct intel_vgpu_guest_page *p) +{ + int ret; + + if (!p->writeprotection) + return 0; + + ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, p->gfn); + if (ret) + return ret; + p->writeprotection = false; + atomic_dec(&vgpu->gtt.n_write_protected_guest_page); + return 0; +} + +/** + * intel_gvt_hypervisor_read_gpa - copy data from GPA to host data buffer + * @vgpu: a vGPU + * @gpa: guest physical address + * @buf: host data buffer + * @len: data length + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline int intel_gvt_hypervisor_read_gpa(struct intel_vgpu *vgpu, + unsigned long gpa, void *buf, unsigned long len) +{ + return intel_gvt_host.mpt->read_gpa(vgpu->handle, gpa, buf, len); +} + +/** + * intel_gvt_hypervisor_write_gpa - copy data from host data buffer to GPA + * @vgpu: a vGPU + * @gpa: guest physical address + * @buf: host data buffer + * @len: data length + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline int intel_gvt_hypervisor_write_gpa(struct intel_vgpu *vgpu, + unsigned long gpa, void *buf, unsigned long len) +{ + return intel_gvt_host.mpt->write_gpa(vgpu->handle, gpa, buf, len); +} + +/** + * intel_gvt_hypervisor_gfn_to_mfn - translate a GFN to MFN + * @vgpu: a vGPU + * @gpfn: guest pfn + * + * Returns: + * MFN on success, INTEL_GVT_INVALID_ADDR if failed. + */ +static inline unsigned long intel_gvt_hypervisor_gfn_to_mfn( + struct intel_vgpu *vgpu, unsigned long gfn) +{ + return intel_gvt_host.mpt->gfn_to_mfn(vgpu->handle, gfn); +} + #endif /* _GVT_MPT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h index 86bde96909b0..27577dcfd9d8 100644 --- a/drivers/gpu/drm/i915/gvt/trace.h +++ b/drivers/gpu/drm/i915/gvt/trace.h @@ -39,6 +39,191 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM gvt +TRACE_EVENT(spt_alloc, + TP_PROTO(int id, void *spt, int type, unsigned long mfn, + unsigned long gpt_gfn), + + TP_ARGS(id, spt, type, mfn, gpt_gfn), + + TP_STRUCT__entry( + __field(int, id) + __field(void *, spt) + __field(int, type) + __field(unsigned long, mfn) + __field(unsigned long, gpt_gfn) + ), + + TP_fast_assign( + __entry->id = id; + __entry->spt = spt; + __entry->type = type; + __entry->mfn = mfn; + __entry->gpt_gfn = gpt_gfn; + ), + + TP_printk("VM%d [alloc] spt %p type %d mfn 0x%lx gfn 0x%lx\n", + __entry->id, + __entry->spt, + __entry->type, + __entry->mfn, + __entry->gpt_gfn) +); + +TRACE_EVENT(spt_free, + TP_PROTO(int id, void *spt, int type), + + TP_ARGS(id, spt, type), + + TP_STRUCT__entry( + __field(int, id) + __field(void *, spt) + __field(int, type) + ), + + TP_fast_assign( + __entry->id = id; + __entry->spt = spt; + __entry->type = type; + ), + + TP_printk("VM%u [free] spt %p type %d\n", + __entry->id, + __entry->spt, + __entry->type) +); + +#define MAX_BUF_LEN 256 + +TRACE_EVENT(gma_index, + TP_PROTO(const char *prefix, unsigned long gma, + unsigned long index), + + TP_ARGS(prefix, gma, index), + + TP_STRUCT__entry( + __array(char, buf, MAX_BUF_LEN) + ), + + TP_fast_assign( + snprintf(__entry->buf, MAX_BUF_LEN, + "%s gma 0x%lx index 0x%lx\n", prefix, gma, index); + ), + + TP_printk("%s", __entry->buf) +); + +TRACE_EVENT(gma_translate, + TP_PROTO(int id, char *type, int ring_id, int pt_level, + unsigned long gma, unsigned long gpa), + + TP_ARGS(id, type, ring_id, pt_level, gma, gpa), + + TP_STRUCT__entry( + __array(char, buf, MAX_BUF_LEN) + ), + + TP_fast_assign( + snprintf(__entry->buf, MAX_BUF_LEN, + "VM%d %s ring %d pt_level %d gma 0x%lx -> gpa 0x%lx\n", + id, type, ring_id, pt_level, gma, gpa); + ), + + TP_printk("%s", __entry->buf) +); + +TRACE_EVENT(spt_refcount, + TP_PROTO(int id, char *action, void *spt, int before, int after), + + TP_ARGS(id, action, spt, before, after), + + TP_STRUCT__entry( + __array(char, buf, MAX_BUF_LEN) + ), + + TP_fast_assign( + snprintf(__entry->buf, MAX_BUF_LEN, + "VM%d [%s] spt %p before %d -> after %d\n", + id, action, spt, before, after); + ), + + TP_printk("%s", __entry->buf) +); + +TRACE_EVENT(spt_change, + TP_PROTO(int id, char *action, void *spt, unsigned long gfn, + int type), + + TP_ARGS(id, action, spt, gfn, type), + + TP_STRUCT__entry( + __array(char, buf, MAX_BUF_LEN) + ), + + TP_fast_assign( + snprintf(__entry->buf, MAX_BUF_LEN, + "VM%d [%s] spt %p gfn 0x%lx type %d\n", + id, action, spt, gfn, type); + ), + + TP_printk("%s", __entry->buf) +); + +TRACE_EVENT(gpt_change, + TP_PROTO(int id, const char *tag, void *spt, int type, u64 v, + unsigned long index), + + TP_ARGS(id, tag, spt, type, v, index), + + TP_STRUCT__entry( + __array(char, buf, MAX_BUF_LEN) + ), + + TP_fast_assign( + snprintf(__entry->buf, MAX_BUF_LEN, + "VM%d [%s] spt %p type %d entry 0x%llx index 0x%lx\n", + id, tag, spt, type, v, index); + ), + + TP_printk("%s", __entry->buf) +); + +TRACE_EVENT(oos_change, + TP_PROTO(int id, const char *tag, int page_id, void *gpt, int type), + + TP_ARGS(id, tag, page_id, gpt, type), + + TP_STRUCT__entry( + __array(char, buf, MAX_BUF_LEN) + ), + + TP_fast_assign( + snprintf(__entry->buf, MAX_BUF_LEN, + "VM%d [oos %s] page id %d gpt %p type %d\n", + id, tag, page_id, gpt, type); + ), + + TP_printk("%s", __entry->buf) +); + +TRACE_EVENT(oos_sync, + TP_PROTO(int id, int page_id, void *gpt, int type, u64 v, + unsigned long index), + + TP_ARGS(id, page_id, gpt, type, v, index), + + TP_STRUCT__entry( + __array(char, buf, MAX_BUF_LEN) + ), + + TP_fast_assign( + snprintf(__entry->buf, MAX_BUF_LEN, + "VM%d [oos sync] page id %d gpt %p type %d entry 0x%llx index 0x%lx\n", + id, page_id, gpt, type, v, index); + ), + + TP_printk("%s", __entry->buf) +); + #endif /* _GVT_TRACE_H_ */ /* This part must be out of protection */ diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 0f1a59b9156a..a610f5a32947 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -141,6 +141,7 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) vgpu->active = false; idr_remove(&gvt->vgpu_idr, vgpu->id); + intel_vgpu_clean_gtt(vgpu); intel_gvt_hypervisor_detach_vgpu(vgpu); intel_vgpu_free_resource(vgpu); clean_vgpu_mmio(vgpu); @@ -199,11 +200,17 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, if (ret) goto out_clean_vgpu_resource; + ret = intel_vgpu_init_gtt(vgpu); + if (ret) + goto out_detach_hypervisor_vgpu; + vgpu->active = true; mutex_unlock(&gvt->lock); return vgpu; +out_detach_hypervisor_vgpu: + intel_gvt_hypervisor_detach_vgpu(vgpu); out_clean_vgpu_resource: intel_vgpu_free_resource(vgpu); out_clean_vgpu_mmio: -- cgit v1.2.3 From 4d60c5fd3f8751ea751d6dc6cfe0c1620420ccf8 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Wed, 20 Jul 2016 01:14:38 -0400 Subject: drm/i915/gvt: vGPU PCI configuration space virtualization This patch introduces vGPU PCI configuration space virtualization. - Adjust the trapped GPFN(Guest Page Frame Number) window of virtual GEN PCI BAR 0 when guest initializes PCI BAR 0 address. - Emulate OpRegion when guest touches OpRegion. - Pass-through a part of aperture to guest when guest initializes aperture BAR. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/cfg_space.c | 287 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/gvt.c | 12 ++ drivers/gpu/drm/i915/gvt/gvt.h | 30 +++ drivers/gpu/drm/i915/gvt/hypercall.h | 14 ++ drivers/gpu/drm/i915/gvt/mpt.h | 42 +++++ drivers/gpu/drm/i915/gvt/opregion.c | 343 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/reg.h | 23 +++ drivers/gpu/drm/i915/gvt/vgpu.c | 9 + 9 files changed, 761 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/gvt/cfg_space.c create mode 100644 drivers/gpu/drm/i915/gvt/opregion.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 40eef5b40505..7f185b09a500 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,6 +1,6 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ - interrupt.o gtt.o + interrupt.o gtt.o cfg_space.o opregion.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c new file mode 100644 index 000000000000..16360e449ed0 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -0,0 +1,287 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eddie Dong + * Jike Song + * + * Contributors: + * Zhi Wang + * Min He + * Bing Niu + * + */ + +#include "i915_drv.h" + +enum { + INTEL_GVT_PCI_BAR_GTTMMIO = 0, + INTEL_GVT_PCI_BAR_APERTURE, + INTEL_GVT_PCI_BAR_PIO, + INTEL_GVT_PCI_BAR_MAX, +}; + +/** + * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_emulate_cfg_read(void *__vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + struct intel_vgpu *vgpu = __vgpu; + + if (WARN_ON(bytes > 4)) + return -EINVAL; + + if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ)) + return -EINVAL; + + memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes); + return 0; +} + +static int map_aperture(struct intel_vgpu *vgpu, bool map) +{ + u64 first_gfn, first_mfn; + u64 val; + int ret; + + if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) + return 0; + + val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2]; + if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) + val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); + else + val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); + + first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT; + first_mfn = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT; + + ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn, + first_mfn, + vgpu_aperture_sz(vgpu) + >> PAGE_SHIFT, map, + GVT_MAP_APERTURE); + if (ret) + return ret; + + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map; + return 0; +} + +static int trap_gttmmio(struct intel_vgpu *vgpu, bool trap) +{ + u64 start, end; + u64 val; + int ret; + + if (trap == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked) + return 0; + + val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_0]; + if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) + start = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0); + else + start = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0); + + start &= ~GENMASK(3, 0); + end = start + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size - 1; + + ret = intel_gvt_hypervisor_set_trap_area(vgpu, start, end, trap); + if (ret) + return ret; + + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap; + return 0; +} + +static int emulate_pci_command_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + u8 old = vgpu_cfg_space(vgpu)[offset]; + u8 new = *(u8 *)p_data; + u8 changed = old ^ new; + int ret; + + if (!(changed & PCI_COMMAND_MEMORY)) + return 0; + + if (old & PCI_COMMAND_MEMORY) { + ret = trap_gttmmio(vgpu, false); + if (ret) + return ret; + ret = map_aperture(vgpu, false); + if (ret) + return ret; + } else { + ret = trap_gttmmio(vgpu, true); + if (ret) + return ret; + ret = map_aperture(vgpu, true); + if (ret) + return ret; + } + + memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); + return 0; +} + +static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + unsigned int bar_index = + (rounddown(offset, 8) % PCI_BASE_ADDRESS_0) / 8; + u32 new = *(u32 *)(p_data); + bool lo = IS_ALIGNED(offset, 8); + u64 size; + int ret = 0; + bool mmio_enabled = + vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY; + + if (WARN_ON(bar_index >= INTEL_GVT_PCI_BAR_MAX)) + return -EINVAL; + + if (new == 0xffffffff) { + /* + * Power-up software can determine how much address + * space the device requires by writing a value of + * all 1's to the register and then reading the value + * back. The device will return 0's in all don't-care + * address bits. + */ + size = vgpu->cfg_space.bar[bar_index].size; + if (lo) { + new = rounddown(new, size); + } else { + u32 val = vgpu_cfg_space(vgpu)[rounddown(offset, 8)]; + /* for 32bit mode bar it returns all-0 in upper 32 + * bit, for 64bit mode bar it will calculate the + * size with lower 32bit and return the corresponding + * value + */ + if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) + new &= (~(size-1)) >> 32; + else + new = 0; + } + /* + * Unmapp & untrap the BAR, since guest hasn't configured a + * valid GPA + */ + switch (bar_index) { + case INTEL_GVT_PCI_BAR_GTTMMIO: + ret = trap_gttmmio(vgpu, false); + break; + case INTEL_GVT_PCI_BAR_APERTURE: + ret = map_aperture(vgpu, false); + break; + } + intel_vgpu_write_pci_bar(vgpu, offset, new, lo); + } else { + /* + * Unmapp & untrap the old BAR first, since guest has + * re-configured the BAR + */ + switch (bar_index) { + case INTEL_GVT_PCI_BAR_GTTMMIO: + ret = trap_gttmmio(vgpu, false); + break; + case INTEL_GVT_PCI_BAR_APERTURE: + ret = map_aperture(vgpu, false); + break; + } + intel_vgpu_write_pci_bar(vgpu, offset, new, lo); + /* Track the new BAR */ + if (mmio_enabled) { + switch (bar_index) { + case INTEL_GVT_PCI_BAR_GTTMMIO: + ret = trap_gttmmio(vgpu, true); + break; + case INTEL_GVT_PCI_BAR_APERTURE: + ret = map_aperture(vgpu, true); + break; + } + } + } + return ret; +} + +/** + * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space write + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_emulate_cfg_write(void *__vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + struct intel_vgpu *vgpu = __vgpu; + int ret; + + if (WARN_ON(bytes > 4)) + return -EINVAL; + + if (WARN_ON(offset + bytes >= INTEL_GVT_MAX_CFG_SPACE_SZ)) + return -EINVAL; + + /* First check if it's PCI_COMMAND */ + if (IS_ALIGNED(offset, 2) && offset == PCI_COMMAND) { + if (WARN_ON(bytes > 2)) + return -EINVAL; + return emulate_pci_command_write(vgpu, offset, p_data, bytes); + } + + switch (rounddown(offset, 4)) { + case PCI_BASE_ADDRESS_0: + case PCI_BASE_ADDRESS_1: + case PCI_BASE_ADDRESS_2: + case PCI_BASE_ADDRESS_3: + if (WARN_ON(!IS_ALIGNED(offset, 4))) + return -EINVAL; + return emulate_pci_bar_write(vgpu, offset, p_data, bytes); + + case INTEL_GVT_PCI_SWSCI: + if (WARN_ON(!IS_ALIGNED(offset, 4))) + return -EINVAL; + ret = intel_vgpu_emulate_opregion_request(vgpu, *(u32 *)p_data); + if (ret) + return ret; + break; + + case INTEL_GVT_PCI_OPREGION: + if (WARN_ON(!IS_ALIGNED(offset, 4))) + return -EINVAL; + ret = intel_vgpu_init_opregion(vgpu, *(u32 *)p_data); + if (ret) + return ret; + + memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); + break; + default: + memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); + break; + } + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 5063c672736d..c6e063ec6c5d 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -42,6 +42,11 @@ static const char * const supported_hypervisors[] = { [INTEL_GVT_HYPERVISOR_KVM] = "KVM", }; +struct intel_gvt_io_emulation_ops intel_gvt_io_emulation_ops = { + .emulate_cfg_read = intel_vgpu_emulate_cfg_read, + .emulate_cfg_write = intel_vgpu_emulate_cfg_write, +}; + /** * intel_gvt_init_host - Load MPT modules and detect if we're running in host * @gvt: intel gvt device @@ -122,6 +127,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) if (WARN_ON(!gvt->initialized)) return; + intel_gvt_clean_opregion(gvt); intel_gvt_clean_gtt(gvt); intel_gvt_clean_irq(gvt); intel_gvt_clean_mmio_info(gvt); @@ -179,10 +185,16 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (ret) goto out_clean_irq; + ret = intel_gvt_init_opregion(gvt); + if (ret) + goto out_clean_gtt; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; +out_clean_gtt: + intel_gvt_clean_gtt(gvt); out_clean_irq: intel_gvt_clean_irq(gvt); out_free_firmware: diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 11267e73671a..f895c9242a28 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -108,6 +108,14 @@ struct intel_vgpu_irq { bool irq_warn_once[INTEL_GVT_EVENT_MAX]; }; +struct intel_vgpu_opregion { + void *va; + u32 gfn[INTEL_GVT_OPREGION_PAGES]; + struct page *pages[INTEL_GVT_OPREGION_PAGES]; +}; + +#define vgpu_opregion(vgpu) (&(vgpu->opregion)) + struct intel_vgpu { struct intel_gvt *gvt; int id; @@ -121,6 +129,7 @@ struct intel_vgpu { struct intel_vgpu_mmio mmio; struct intel_vgpu_irq irq; struct intel_vgpu_gtt gtt; + struct intel_vgpu_opregion opregion; }; struct intel_gvt_gm { @@ -145,6 +154,11 @@ struct intel_gvt_firmware { bool firmware_loaded; }; +struct intel_gvt_opregion { + void *opregion_va; + u32 opregion_pa; +}; + struct intel_gvt { struct mutex lock; bool initialized; @@ -159,6 +173,7 @@ struct intel_gvt { struct intel_gvt_firmware firmware; struct intel_gvt_irq irq; struct intel_gvt_gtt gtt; + struct intel_gvt_opregion opregion; }; void intel_gvt_free_firmware(struct intel_gvt *gvt); @@ -300,6 +315,21 @@ int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index, unsigned long *h_index); int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, unsigned long *g_index); + +int intel_vgpu_emulate_cfg_read(void *__vgpu, unsigned int offset, + void *p_data, unsigned int bytes); + +int intel_vgpu_emulate_cfg_write(void *__vgpu, unsigned int offset, + void *p_data, unsigned int bytes); + +void intel_gvt_clean_opregion(struct intel_gvt *gvt); +int intel_gvt_init_opregion(struct intel_gvt *gvt); + +void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu); +int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa); + +int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci); + #include "mpt.h" #endif diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index 67d8b1a26e73..b5ffd78afd02 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -33,6 +33,15 @@ #ifndef _GVT_HYPERCALL_H_ #define _GVT_HYPERCALL_H_ +struct intel_gvt_io_emulation_ops { + int (*emulate_cfg_read)(void *, unsigned int, + void *, unsigned int); + int (*emulate_cfg_write)(void *, unsigned int, + void *, unsigned int); +}; + +extern struct intel_gvt_io_emulation_ops *gvt_io_emulation_ops; + /* * Specific GVT-g MPT modules function collections. Currently GVT-g supports * both Xen and KVM by providing dedicated hypervisor-related MPT modules. @@ -50,6 +59,11 @@ struct intel_gvt_mpt { int (*write_gpa)(unsigned long handle, unsigned long gpa, void *buf, unsigned long len); unsigned long (*gfn_to_mfn)(unsigned long handle, unsigned long gfn); + int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn, + unsigned long mfn, unsigned int nr, bool map, + int type); + int (*set_trap_area)(unsigned long handle, u64 start, u64 end, + bool map); }; extern struct intel_gvt_mpt xengt_mpt; diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index 46664771cc58..67858782d327 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -224,4 +224,46 @@ static inline unsigned long intel_gvt_hypervisor_gfn_to_mfn( return intel_gvt_host.mpt->gfn_to_mfn(vgpu->handle, gfn); } +enum { + GVT_MAP_APERTURE = 0, + GVT_MAP_OPREGION, +}; + +/** + * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN + * @vgpu: a vGPU + * @gfn: guest PFN + * @mfn: host PFN + * @nr: amount of PFNs + * @map: map or unmap + * @type: map type + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline int intel_gvt_hypervisor_map_gfn_to_mfn( + struct intel_vgpu *vgpu, unsigned long gfn, + unsigned long mfn, unsigned int nr, + bool map, int type) +{ + return intel_gvt_host.mpt->map_gfn_to_mfn(vgpu->handle, gfn, mfn, nr, + map, type); +} + +/** + * intel_gvt_hypervisor_set_trap_area - Trap a guest PA region + * @vgpu: a vGPU + * @start: the beginning of the guest physical address region + * @end: the end of the guest physical address region + * @map: map or unmap + * + * Returns: + * Zero on success, negative error code if failed. + */ +static inline int intel_gvt_hypervisor_set_trap_area( + struct intel_vgpu *vgpu, u64 start, u64 end, bool map) +{ + return intel_gvt_host.mpt->set_trap_area(vgpu->handle, start, end, map); +} + #endif /* _GVT_MPT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c new file mode 100644 index 000000000000..46cc2407a0a2 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -0,0 +1,343 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include "i915_drv.h" + +static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa) +{ + void *host_va = vgpu->gvt->opregion.opregion_va; + u8 *buf; + int i; + + if (WARN((vgpu_opregion(vgpu)->va), + "vgpu%d: opregion has been initialized already.\n", + vgpu->id)) + return -EINVAL; + + vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_ATOMIC | + GFP_DMA32 | __GFP_ZERO, + INTEL_GVT_OPREGION_PORDER); + + if (!vgpu_opregion(vgpu)->va) + return -ENOMEM; + + memcpy_fromio(vgpu_opregion(vgpu)->va, host_va, + INTEL_GVT_OPREGION_SIZE); + + for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) + vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i; + + /* for unknown reason, the value in LID field is incorrect + * which block the windows guest, so workaround it by force + * setting it to "OPEN" + */ + buf = (u8 *)vgpu_opregion(vgpu)->va; + buf[INTEL_GVT_OPREGION_CLID] = 0x3; + + return 0; +} + +static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map) +{ + u64 mfn; + int i, ret; + + for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) { + mfn = intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu) + + i * PAGE_SIZE); + if (mfn == INTEL_GVT_INVALID_ADDR) { + gvt_err("fail to get MFN from VA\n"); + return -EINVAL; + } + ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, + vgpu_opregion(vgpu)->gfn[i], + mfn, 1, map, GVT_MAP_OPREGION); + if (ret) { + gvt_err("fail to map GFN to MFN, errno: %d\n", ret); + return ret; + } + } + return 0; +} + +/** + * intel_vgpu_clean_opregion - clean the stuff used to emulate opregion + * @vgpu: a vGPU + * + */ +void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu) +{ + int i; + + gvt_dbg_core("vgpu%d: clean vgpu opregion\n", vgpu->id); + + if (!vgpu_opregion(vgpu)->va) + return; + + if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) { + vunmap(vgpu_opregion(vgpu)->va); + for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) { + if (vgpu_opregion(vgpu)->pages[i]) { + put_page(vgpu_opregion(vgpu)->pages[i]); + vgpu_opregion(vgpu)->pages[i] = NULL; + } + } + } else { + map_vgpu_opregion(vgpu, false); + free_pages((unsigned long)vgpu_opregion(vgpu)->va, + INTEL_GVT_OPREGION_PORDER); + } + + vgpu_opregion(vgpu)->va = NULL; +} + +/** + * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion + * @vgpu: a vGPU + * @gpa: guest physical address of opregion + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa) +{ + int ret; + + gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id); + + if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) { + gvt_dbg_core("emulate opregion from kernel\n"); + + ret = init_vgpu_opregion(vgpu, gpa); + if (ret) + return ret; + + ret = map_vgpu_opregion(vgpu, true); + if (ret) + return ret; + } else { + gvt_dbg_core("emulate opregion from userspace\n"); + + /* + * If opregion pages are not allocated from host kenrel, + * most of the params are meaningless + */ + ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, + 0, /* not used */ + 0, /* not used */ + 2, /* not used */ + 1, + GVT_MAP_OPREGION); + if (ret) + return ret; + } + return 0; +} + +/** + * intel_gvt_clean_opregion - clean host opergion related stuffs + * @gvt: a GVT device + * + */ +void intel_gvt_clean_opregion(struct intel_gvt *gvt) +{ + iounmap(gvt->opregion.opregion_va); + gvt->opregion.opregion_va = NULL; +} + +/** + * intel_gvt_init_opregion - initialize host opergion related stuffs + * @gvt: a GVT device + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_gvt_init_opregion(struct intel_gvt *gvt) +{ + gvt_dbg_core("init host opregion\n"); + + pci_read_config_dword(gvt->dev_priv->drm.pdev, INTEL_GVT_PCI_OPREGION, + &gvt->opregion.opregion_pa); + + gvt->opregion.opregion_va = acpi_os_ioremap(gvt->opregion.opregion_pa, + INTEL_GVT_OPREGION_SIZE); + if (!gvt->opregion.opregion_va) { + gvt_err("fail to map host opregion\n"); + return -EFAULT; + } + return 0; +} + +#define GVT_OPREGION_FUNC(scic) \ + ({ \ + u32 __ret; \ + __ret = (scic & OPREGION_SCIC_FUNC_MASK) >> \ + OPREGION_SCIC_FUNC_SHIFT; \ + __ret; \ + }) + +#define GVT_OPREGION_SUBFUNC(scic) \ + ({ \ + u32 __ret; \ + __ret = (scic & OPREGION_SCIC_SUBFUNC_MASK) >> \ + OPREGION_SCIC_SUBFUNC_SHIFT; \ + __ret; \ + }) + +static const char *opregion_func_name(u32 func) +{ + const char *name = NULL; + + switch (func) { + case 0 ... 3: + case 5: + case 7 ... 15: + name = "Reserved"; + break; + + case 4: + name = "Get BIOS Data"; + break; + + case 6: + name = "System BIOS Callbacks"; + break; + + default: + name = "Unknown"; + break; + } + return name; +} + +static const char *opregion_subfunc_name(u32 subfunc) +{ + const char *name = NULL; + + switch (subfunc) { + case 0: + name = "Supported Calls"; + break; + + case 1: + name = "Requested Callbacks"; + break; + + case 2 ... 3: + case 8 ... 9: + name = "Reserved"; + break; + + case 5: + name = "Boot Display"; + break; + + case 6: + name = "TV-Standard/Video-Connector"; + break; + + case 7: + name = "Internal Graphics"; + break; + + case 10: + name = "Spread Spectrum Clocks"; + break; + + case 11: + name = "Get AKSV"; + break; + + default: + name = "Unknown"; + break; + } + return name; +}; + +static bool querying_capabilities(u32 scic) +{ + u32 func, subfunc; + + func = GVT_OPREGION_FUNC(scic); + subfunc = GVT_OPREGION_SUBFUNC(scic); + + if ((func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA && + subfunc == INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS) + || (func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA && + subfunc == INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS) + || (func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS && + subfunc == INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS)) { + return true; + } + return false; +} + +/** + * intel_vgpu_emulate_opregion_request - emulating OpRegion request + * @vgpu: a vGPU + * @swsci: SWSCI request + * + * Returns: + * Zero on success, negative error code if failed + */ +int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci) +{ + u32 *scic, *parm; + u32 func, subfunc; + + scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC; + parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM; + + if (!(swsci & SWSCI_SCI_SELECT)) { + gvt_err("vgpu%d: requesting SMI service\n", vgpu->id); + return 0; + } + /* ignore non 0->1 trasitions */ + if ((vgpu_cfg_space(vgpu)[INTEL_GVT_PCI_SWSCI] + & SWSCI_SCI_TRIGGER) || + !(swsci & SWSCI_SCI_TRIGGER)) { + return 0; + } + + func = GVT_OPREGION_FUNC(*scic); + subfunc = GVT_OPREGION_SUBFUNC(*scic); + if (!querying_capabilities(*scic)) { + gvt_err("vgpu%d: requesting runtime service: func \"%s\"," + " subfunc \"%s\"\n", + vgpu->id, + opregion_func_name(func), + opregion_subfunc_name(subfunc)); + /* + * emulate exit status of function call, '0' means + * "failure, generic, unsupported or unknown cause" + */ + *scic &= ~OPREGION_SCIC_EXIT_MASK; + return 0; + } + + *scic = 0; + *parm = 0; + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h index 3172fb3f8d76..932c86b9b7bf 100644 --- a/drivers/gpu/drm/i915/gvt/reg.h +++ b/drivers/gpu/drm/i915/gvt/reg.h @@ -30,4 +30,27 @@ #define BDW_GMCH_GMS_SHIFT 8 #define BDW_GMCH_GMS_MASK 0xff +#define INTEL_GVT_PCI_SWSCI 0xe8 +#define SWSCI_SCI_SELECT (1 << 15) +#define SWSCI_SCI_TRIGGER 1 + +#define INTEL_GVT_PCI_OPREGION 0xfc + +#define INTEL_GVT_OPREGION_CLID 0x1AC +#define INTEL_GVT_OPREGION_SCIC 0x200 +#define OPREGION_SCIC_FUNC_MASK 0x1E +#define OPREGION_SCIC_FUNC_SHIFT 1 +#define OPREGION_SCIC_SUBFUNC_MASK 0xFF00 +#define OPREGION_SCIC_SUBFUNC_SHIFT 8 +#define OPREGION_SCIC_EXIT_MASK 0xE0 +#define INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA 4 +#define INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS 6 +#define INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS 0 +#define INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS 1 +#define INTEL_GVT_OPREGION_PARM 0x204 + +#define INTEL_GVT_OPREGION_PAGES 2 +#define INTEL_GVT_OPREGION_PORDER 1 +#define INTEL_GVT_OPREGION_SIZE (2 * 4096) + #endif diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index a610f5a32947..53308698929a 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -141,6 +141,7 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) vgpu->active = false; idr_remove(&gvt->vgpu_idr, vgpu->id); + intel_vgpu_clean_opregion(vgpu); intel_vgpu_clean_gtt(vgpu); intel_gvt_hypervisor_detach_vgpu(vgpu); intel_vgpu_free_resource(vgpu); @@ -204,11 +205,19 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, if (ret) goto out_detach_hypervisor_vgpu; + if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) { + ret = intel_vgpu_init_opregion(vgpu, 0); + if (ret) + goto out_clean_gtt; + } + vgpu->active = true; mutex_unlock(&gvt->lock); return vgpu; +out_clean_gtt: + intel_vgpu_clean_gtt(vgpu); out_detach_hypervisor_vgpu: intel_gvt_hypervisor_detach_vgpu(vgpu); out_clean_vgpu_resource: -- cgit v1.2.3 From e39c5add322184de3be052d438dfd24375bfeaea Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 2 Sep 2016 13:33:29 +0800 Subject: drm/i915/gvt: vGPU MMIO virtualization This patch introduces the generic vGPU MMIO emulation intercept framework. The MPT modules will request GVT-g core logic to emulate MMIO read/write through IO emulation operations callback when hypervisor trapped a guest GTTMMIO read/write. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/debug.h | 3 + drivers/gpu/drm/i915/gvt/gvt.c | 2 + drivers/gpu/drm/i915/gvt/gvt.h | 3 + drivers/gpu/drm/i915/gvt/handlers.c | 1583 +++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/gvt/hypercall.h | 10 +- drivers/gpu/drm/i915/gvt/mmio.c | 305 +++++++ drivers/gpu/drm/i915/gvt/mmio.h | 16 + drivers/gpu/drm/i915/gvt/reg.h | 19 + drivers/gpu/drm/i915/gvt/vgpu.c | 5 + 10 files changed, 1938 insertions(+), 10 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/mmio.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 7f185b09a500..1a783a19bc4d 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,6 +1,6 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ - interrupt.o gtt.o cfg_space.o opregion.o + interrupt.o gtt.o cfg_space.o opregion.o mmio.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index 82269b750aac..47fabb065ac5 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -36,4 +36,7 @@ #define gvt_dbg_mm(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: mm: "fmt, ##args) +#define gvt_dbg_mmio(fmt, args...) \ + DRM_DEBUG_DRIVER("gvt: mmio: "fmt, ##args) + #endif diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index c6e063ec6c5d..6b5061bfebb0 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -45,6 +45,8 @@ static const char * const supported_hypervisors[] = { struct intel_gvt_io_emulation_ops intel_gvt_io_emulation_ops = { .emulate_cfg_read = intel_vgpu_emulate_cfg_read, .emulate_cfg_write = intel_vgpu_emulate_cfg_write, + .emulate_mmio_read = intel_vgpu_emulate_mmio_read, + .emulate_mmio_write = intel_vgpu_emulate_mmio_write, }; /** diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index f895c9242a28..2560c3aaac45 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -87,6 +87,7 @@ struct intel_vgpu_fence { struct intel_vgpu_mmio { void *vreg; void *sreg; + bool disable_warn_untrack; }; #define INTEL_GVT_MAX_CFG_SPACE_SZ 256 @@ -184,6 +185,8 @@ int intel_gvt_load_firmware(struct intel_gvt *gvt); #define gvt_aperture_pa_base(gvt) (gvt->dev_priv->ggtt.mappable_base) #define gvt_ggtt_gm_sz(gvt) (gvt->dev_priv->ggtt.base.total) +#define gvt_ggtt_sz(gvt) \ + ((gvt->dev_priv->ggtt.base.total >> PAGE_SHIFT) << 3) #define gvt_hidden_sz(gvt) (gvt_ggtt_gm_sz(gvt) - gvt_aperture_sz(gvt)) #define gvt_aperture_gmadr_base(gvt) (0) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 62222189906b..b29c3bfdc599 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -38,6 +38,13 @@ #include "i915_drv.h" +/* XXX FIXME i915 has changed PP_XXX definition */ +#define PCH_PP_STATUS _MMIO(0xc7200) +#define PCH_PP_CONTROL _MMIO(0xc7204) +#define PCH_PP_ON_DELAYS _MMIO(0xc7208) +#define PCH_PP_OFF_DELAYS _MMIO(0xc720c) +#define PCH_PP_DIVISOR _MMIO(0xc7210) + /* Register contains RO bits */ #define F_RO (1 << 0) /* Register contains graphics address */ @@ -69,6 +76,18 @@ bool intel_gvt_match_device(struct intel_gvt *gvt, return intel_gvt_get_device_type(gvt) & device; } +static void read_vreg(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); +} + +static void write_vreg(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes); +} + static int new_mmio_info(struct intel_gvt *gvt, u32 offset, u32 flags, u32 size, u32 addr_mask, u32 ro_mask, u32 device, @@ -100,8 +119,8 @@ static int new_mmio_info(struct intel_gvt *gvt, info->length = (i + 4) < end ? 4 : (end - i); info->addr_mask = addr_mask; info->device = device; - info->read = read; - info->write = write; + info->read = read ? read : intel_vgpu_default_mmio_read; + info->write = write ? write : intel_vgpu_default_mmio_write; gvt->mmio.mmio_attribute[info->offset / 4] = flags; INIT_HLIST_NODE(&info->node); hash_add(gvt->mmio.mmio_info_table, &info->node, info->offset); @@ -109,6 +128,282 @@ static int new_mmio_info(struct intel_gvt *gvt, return 0; } +#define offset_to_fence_num(offset) \ + ((offset - i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) >> 3) + +#define fence_num_to_offset(num) \ + (num * 8 + i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) + +static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu, + unsigned int fence_num, void *p_data, unsigned int bytes) +{ + if (fence_num >= vgpu_fence_sz(vgpu)) { + gvt_err("vgpu%d: found oob fence register access\n", + vgpu->id); + gvt_err("vgpu%d: total fence num %d access fence num %d\n", + vgpu->id, vgpu_fence_sz(vgpu), fence_num); + memset(p_data, 0, bytes); + } + return 0; +} + +static int fence_mmio_read(struct intel_vgpu *vgpu, unsigned int off, + void *p_data, unsigned int bytes) +{ + int ret; + + ret = sanitize_fence_mmio_access(vgpu, offset_to_fence_num(off), + p_data, bytes); + if (ret) + return ret; + read_vreg(vgpu, off, p_data, bytes); + return 0; +} + +static int fence_mmio_write(struct intel_vgpu *vgpu, unsigned int off, + void *p_data, unsigned int bytes) +{ + unsigned int fence_num = offset_to_fence_num(off); + int ret; + + ret = sanitize_fence_mmio_access(vgpu, fence_num, p_data, bytes); + if (ret) + return ret; + write_vreg(vgpu, off, p_data, bytes); + + intel_vgpu_write_fence(vgpu, fence_num, + vgpu_vreg64(vgpu, fence_num_to_offset(fence_num))); + return 0; +} + +#define CALC_MODE_MASK_REG(old, new) \ + (((new) & GENMASK(31, 16)) \ + | ((((old) & GENMASK(15, 0)) & ~((new) >> 16)) \ + | ((new) & ((new) >> 16)))) + +static int mul_force_wake_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + u32 old, new; + uint32_t ack_reg_offset; + + old = vgpu_vreg(vgpu, offset); + new = CALC_MODE_MASK_REG(old, *(u32 *)p_data); + + if (IS_SKYLAKE(vgpu->gvt->dev_priv)) { + switch (offset) { + case FORCEWAKE_RENDER_GEN9_REG: + ack_reg_offset = FORCEWAKE_ACK_RENDER_GEN9_REG; + break; + case FORCEWAKE_BLITTER_GEN9_REG: + ack_reg_offset = FORCEWAKE_ACK_BLITTER_GEN9_REG; + break; + case FORCEWAKE_MEDIA_GEN9_REG: + ack_reg_offset = FORCEWAKE_ACK_MEDIA_GEN9_REG; + break; + default: + /*should not hit here*/ + gvt_err("invalid forcewake offset 0x%x\n", offset); + return 1; + } + } else { + ack_reg_offset = FORCEWAKE_ACK_HSW_REG; + } + + vgpu_vreg(vgpu, offset) = new; + vgpu_vreg(vgpu, ack_reg_offset) = (new & GENMASK(15, 0)); + return 0; +} + +static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 data; + u32 bitmap = 0; + + data = vgpu_vreg(vgpu, offset); + + if (data & GEN6_GRDOM_FULL) { + gvt_dbg_mmio("vgpu%d: request full GPU reset\n", vgpu->id); + bitmap = 0xff; + } + if (data & GEN6_GRDOM_RENDER) { + gvt_dbg_mmio("vgpu%d: request RCS reset\n", vgpu->id); + bitmap |= (1 << RCS); + } + if (data & GEN6_GRDOM_MEDIA) { + gvt_dbg_mmio("vgpu%d: request VCS reset\n", vgpu->id); + bitmap |= (1 << VCS); + } + if (data & GEN6_GRDOM_BLT) { + gvt_dbg_mmio("vgpu%d: request BCS Reset\n", vgpu->id); + bitmap |= (1 << BCS); + } + if (data & GEN6_GRDOM_VECS) { + gvt_dbg_mmio("vgpu%d: request VECS Reset\n", vgpu->id); + bitmap |= (1 << VECS); + } + if (data & GEN8_GRDOM_MEDIA2) { + gvt_dbg_mmio("vgpu%d: request VCS2 Reset\n", vgpu->id); + if (HAS_BSD2(vgpu->gvt->dev_priv)) + bitmap |= (1 << VCS2); + } + return 0; +} + +#define _vgtif_reg(x) \ + (VGT_PVINFO_PAGE + offsetof(struct vgt_if, x)) + +static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + bool invalid_read = false; + + read_vreg(vgpu, offset, p_data, bytes); + + switch (offset) { + case _vgtif_reg(magic) ... _vgtif_reg(vgt_id): + if (offset + bytes > _vgtif_reg(vgt_id) + 4) + invalid_read = true; + break; + case _vgtif_reg(avail_rs.mappable_gmadr.base) ... + _vgtif_reg(avail_rs.fence_num): + if (offset + bytes > + _vgtif_reg(avail_rs.fence_num) + 4) + invalid_read = true; + break; + case 0x78010: /* vgt_caps */ + case 0x7881c: + break; + default: + invalid_read = true; + break; + } + if (invalid_read) + gvt_err("invalid pvinfo read: [%x:%x] = %x\n", + offset, bytes, *(u32 *)p_data); + return 0; +} + +static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) +{ + int ret = 0; + + switch (notification) { + case VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE: + ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 3); + break; + case VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY: + ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 3); + break; + case VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE: + ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 4); + break; + case VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY: + ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 4); + break; + case VGT_G2V_EXECLIST_CONTEXT_CREATE: + case VGT_G2V_EXECLIST_CONTEXT_DESTROY: + case 1: /* Remove this in guest driver. */ + break; + default: + gvt_err("Invalid PV notification %d\n", notification); + } + return ret; +} + +static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 data; + int ret; + + write_vreg(vgpu, offset, p_data, bytes); + data = vgpu_vreg(vgpu, offset); + + switch (offset) { + case _vgtif_reg(display_ready): + case _vgtif_reg(g2v_notify): + ret = handle_g2v_notification(vgpu, data); + break; + /* add xhot and yhot to handled list to avoid error log */ + case 0x78830: + case 0x78834: + case _vgtif_reg(pdp[0].lo): + case _vgtif_reg(pdp[0].hi): + case _vgtif_reg(pdp[1].lo): + case _vgtif_reg(pdp[1].hi): + case _vgtif_reg(pdp[2].lo): + case _vgtif_reg(pdp[2].hi): + case _vgtif_reg(pdp[3].lo): + case _vgtif_reg(pdp[3].hi): + case _vgtif_reg(execlist_context_descriptor_lo): + case _vgtif_reg(execlist_context_descriptor_hi): + break; + default: + gvt_err("invalid pvinfo write offset %x bytes %x data %x\n", + offset, bytes, data); + break; + } + return 0; +} + +static int fpga_dbg_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + write_vreg(vgpu, offset, p_data, bytes); + + if (vgpu_vreg(vgpu, offset) & FPGA_DBG_RM_NOCLAIM) + vgpu_vreg(vgpu, offset) &= ~FPGA_DBG_RM_NOCLAIM; + return 0; +} + +static int dma_ctrl_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 mode = *(u32 *)p_data; + + if (GFX_MODE_BIT_SET_IN_MASK(mode, START_DMA)) { + WARN_ONCE(1, "VM(%d): iGVT-g doesn't supporte GuC\n", + vgpu->id); + return 0; + } + + return 0; +} + +static int gen9_trtte_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + u32 trtte = *(u32 *)p_data; + + if ((trtte & 1) && (trtte & (1 << 1)) == 0) { + WARN(1, "VM(%d): Use physical address for TRTT!\n", + vgpu->id); + return -EINVAL; + } + write_vreg(vgpu, offset, p_data, bytes); + /* TRTTE is not per-context */ + I915_WRITE(_MMIO(offset), vgpu_vreg(vgpu, offset)); + + return 0; +} + +static int gen9_trtt_chicken_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + u32 val = *(u32 *)p_data; + + if (val & 1) { + /* unblock hw logic */ + I915_WRITE(_MMIO(offset), val); + } + write_vreg(vgpu, offset, p_data, bytes); + return 0; +} + #define MMIO_F(reg, s, f, am, rm, d, r, w) do { \ ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \ f, s, am, rm, d, r, w); \ @@ -152,20 +447,1193 @@ static int new_mmio_info(struct intel_gvt *gvt, static int init_generic_mmio_info(struct intel_gvt *gvt) { + struct drm_i915_private *dev_priv = gvt->dev_priv; int ret; - MMIO_F(0, 0, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_RING_DFH(RING_IMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler); + + MMIO_DFH(SDEIMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler); + MMIO_DFH(SDEIER, D_ALL, 0, NULL, intel_vgpu_reg_ier_handler); + MMIO_DFH(SDEIIR, D_ALL, 0, NULL, intel_vgpu_reg_iir_handler); + MMIO_D(SDEISR, D_ALL); + + MMIO_RING_D(RING_HWSTAM, D_ALL); + + MMIO_GM(RENDER_HWS_PGA_GEN7, D_ALL, NULL, NULL); + MMIO_GM(BSD_HWS_PGA_GEN7, D_ALL, NULL, NULL); + MMIO_GM(BLT_HWS_PGA_GEN7, D_ALL, NULL, NULL); + MMIO_GM(VEBOX_HWS_PGA_GEN7, D_ALL, NULL, NULL); + +#define RING_REG(base) (base + 0x28) + MMIO_RING_D(RING_REG, D_ALL); +#undef RING_REG + +#define RING_REG(base) (base + 0x134) + MMIO_RING_D(RING_REG, D_ALL); +#undef RING_REG + + MMIO_GM(0x2148, D_ALL, NULL, NULL); + MMIO_GM(CCID, D_ALL, NULL, NULL); + MMIO_GM(0x12198, D_ALL, NULL, NULL); + MMIO_D(GEN7_CXT_SIZE, D_ALL); + + MMIO_RING_D(RING_TAIL, D_ALL); + MMIO_RING_D(RING_HEAD, D_ALL); + MMIO_RING_D(RING_CTL, D_ALL); + MMIO_RING_D(RING_ACTHD, D_ALL); + MMIO_RING_GM(RING_START, D_ALL, NULL, NULL); + + /* RING MODE */ +#define RING_REG(base) (base + 0x29c) + MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, NULL); +#undef RING_REG + + MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS, NULL, NULL); + MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS, NULL, NULL); + + MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(CACHE_MODE_1, D_ALL, F_MODE_MASK, NULL, NULL); + + MMIO_DFH(0x20dc, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(_3D_CHICKEN3, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0x2088, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0x20e4, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0x2470, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_D(GAM_ECOCHK, D_ALL); + MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_D(0x9030, D_ALL); + MMIO_D(0x20a0, D_ALL); + MMIO_D(0x2420, D_ALL); + MMIO_D(0x2430, D_ALL); + MMIO_D(0x2434, D_ALL); + MMIO_D(0x2438, D_ALL); + MMIO_D(0x243c, D_ALL); + MMIO_DFH(0x7018, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0xe184, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0xe100, D_ALL, F_MODE_MASK, NULL, NULL); + + /* display */ + MMIO_F(0x60220, 0x20, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_D(0x602a0, D_ALL); + + MMIO_D(0x65050, D_ALL); + MMIO_D(0x650b4, D_ALL); + + MMIO_D(0xc4040, D_ALL); + MMIO_D(DERRMR, D_ALL); + + MMIO_D(PIPEDSL(PIPE_A), D_ALL); + MMIO_D(PIPEDSL(PIPE_B), D_ALL); + MMIO_D(PIPEDSL(PIPE_C), D_ALL); + MMIO_D(PIPEDSL(_PIPE_EDP), D_ALL); + + MMIO_DH(PIPECONF(PIPE_A), D_ALL, NULL, NULL); + MMIO_DH(PIPECONF(PIPE_B), D_ALL, NULL, NULL); + MMIO_DH(PIPECONF(PIPE_C), D_ALL, NULL, NULL); + MMIO_DH(PIPECONF(_PIPE_EDP), D_ALL, NULL, NULL); + + MMIO_D(PIPESTAT(PIPE_A), D_ALL); + MMIO_D(PIPESTAT(PIPE_B), D_ALL); + MMIO_D(PIPESTAT(PIPE_C), D_ALL); + MMIO_D(PIPESTAT(_PIPE_EDP), D_ALL); + + MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_A), D_ALL); + MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_B), D_ALL); + MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_C), D_ALL); + MMIO_D(PIPE_FLIPCOUNT_G4X(_PIPE_EDP), D_ALL); + + MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_A), D_ALL); + MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_B), D_ALL); + MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_C), D_ALL); + MMIO_D(PIPE_FRMCOUNT_G4X(_PIPE_EDP), D_ALL); + + MMIO_D(CURCNTR(PIPE_A), D_ALL); + MMIO_D(CURCNTR(PIPE_B), D_ALL); + MMIO_D(CURCNTR(PIPE_C), D_ALL); + + MMIO_D(CURPOS(PIPE_A), D_ALL); + MMIO_D(CURPOS(PIPE_B), D_ALL); + MMIO_D(CURPOS(PIPE_C), D_ALL); + + MMIO_D(CURBASE(PIPE_A), D_ALL); + MMIO_D(CURBASE(PIPE_B), D_ALL); + MMIO_D(CURBASE(PIPE_C), D_ALL); + + MMIO_D(0x700ac, D_ALL); + MMIO_D(0x710ac, D_ALL); + MMIO_D(0x720ac, D_ALL); + + MMIO_D(0x70090, D_ALL); + MMIO_D(0x70094, D_ALL); + MMIO_D(0x70098, D_ALL); + MMIO_D(0x7009c, D_ALL); + + MMIO_D(DSPCNTR(PIPE_A), D_ALL); + MMIO_D(DSPADDR(PIPE_A), D_ALL); + MMIO_D(DSPSTRIDE(PIPE_A), D_ALL); + MMIO_D(DSPPOS(PIPE_A), D_ALL); + MMIO_D(DSPSIZE(PIPE_A), D_ALL); + MMIO_D(DSPSURF(PIPE_A), D_ALL); + MMIO_D(DSPOFFSET(PIPE_A), D_ALL); + MMIO_D(DSPSURFLIVE(PIPE_A), D_ALL); + + MMIO_D(DSPCNTR(PIPE_B), D_ALL); + MMIO_D(DSPADDR(PIPE_B), D_ALL); + MMIO_D(DSPSTRIDE(PIPE_B), D_ALL); + MMIO_D(DSPPOS(PIPE_B), D_ALL); + MMIO_D(DSPSIZE(PIPE_B), D_ALL); + MMIO_D(DSPSURF(PIPE_B), D_ALL); + MMIO_D(DSPOFFSET(PIPE_B), D_ALL); + MMIO_D(DSPSURFLIVE(PIPE_B), D_ALL); + + MMIO_D(DSPCNTR(PIPE_C), D_ALL); + MMIO_D(DSPADDR(PIPE_C), D_ALL); + MMIO_D(DSPSTRIDE(PIPE_C), D_ALL); + MMIO_D(DSPPOS(PIPE_C), D_ALL); + MMIO_D(DSPSIZE(PIPE_C), D_ALL); + MMIO_D(DSPSURF(PIPE_C), D_ALL); + MMIO_D(DSPOFFSET(PIPE_C), D_ALL); + MMIO_D(DSPSURFLIVE(PIPE_C), D_ALL); + + MMIO_D(SPRCTL(PIPE_A), D_ALL); + MMIO_D(SPRLINOFF(PIPE_A), D_ALL); + MMIO_D(SPRSTRIDE(PIPE_A), D_ALL); + MMIO_D(SPRPOS(PIPE_A), D_ALL); + MMIO_D(SPRSIZE(PIPE_A), D_ALL); + MMIO_D(SPRKEYVAL(PIPE_A), D_ALL); + MMIO_D(SPRKEYMSK(PIPE_A), D_ALL); + MMIO_D(SPRSURF(PIPE_A), D_ALL); + MMIO_D(SPRKEYMAX(PIPE_A), D_ALL); + MMIO_D(SPROFFSET(PIPE_A), D_ALL); + MMIO_D(SPRSCALE(PIPE_A), D_ALL); + MMIO_D(SPRSURFLIVE(PIPE_A), D_ALL); + + MMIO_D(SPRCTL(PIPE_B), D_ALL); + MMIO_D(SPRLINOFF(PIPE_B), D_ALL); + MMIO_D(SPRSTRIDE(PIPE_B), D_ALL); + MMIO_D(SPRPOS(PIPE_B), D_ALL); + MMIO_D(SPRSIZE(PIPE_B), D_ALL); + MMIO_D(SPRKEYVAL(PIPE_B), D_ALL); + MMIO_D(SPRKEYMSK(PIPE_B), D_ALL); + MMIO_D(SPRSURF(PIPE_B), D_ALL); + MMIO_D(SPRKEYMAX(PIPE_B), D_ALL); + MMIO_D(SPROFFSET(PIPE_B), D_ALL); + MMIO_D(SPRSCALE(PIPE_B), D_ALL); + MMIO_D(SPRSURFLIVE(PIPE_B), D_ALL); + + MMIO_D(SPRCTL(PIPE_C), D_ALL); + MMIO_D(SPRLINOFF(PIPE_C), D_ALL); + MMIO_D(SPRSTRIDE(PIPE_C), D_ALL); + MMIO_D(SPRPOS(PIPE_C), D_ALL); + MMIO_D(SPRSIZE(PIPE_C), D_ALL); + MMIO_D(SPRKEYVAL(PIPE_C), D_ALL); + MMIO_D(SPRKEYMSK(PIPE_C), D_ALL); + MMIO_D(SPRSURF(PIPE_C), D_ALL); + MMIO_D(SPRKEYMAX(PIPE_C), D_ALL); + MMIO_D(SPROFFSET(PIPE_C), D_ALL); + MMIO_D(SPRSCALE(PIPE_C), D_ALL); + MMIO_D(SPRSURFLIVE(PIPE_C), D_ALL); + + MMIO_F(LGC_PALETTE(PIPE_A, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(LGC_PALETTE(PIPE_B, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(LGC_PALETTE(PIPE_C, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_D(HTOTAL(TRANSCODER_A), D_ALL); + MMIO_D(HBLANK(TRANSCODER_A), D_ALL); + MMIO_D(HSYNC(TRANSCODER_A), D_ALL); + MMIO_D(VTOTAL(TRANSCODER_A), D_ALL); + MMIO_D(VBLANK(TRANSCODER_A), D_ALL); + MMIO_D(VSYNC(TRANSCODER_A), D_ALL); + MMIO_D(BCLRPAT(TRANSCODER_A), D_ALL); + MMIO_D(VSYNCSHIFT(TRANSCODER_A), D_ALL); + MMIO_D(PIPESRC(TRANSCODER_A), D_ALL); + + MMIO_D(HTOTAL(TRANSCODER_B), D_ALL); + MMIO_D(HBLANK(TRANSCODER_B), D_ALL); + MMIO_D(HSYNC(TRANSCODER_B), D_ALL); + MMIO_D(VTOTAL(TRANSCODER_B), D_ALL); + MMIO_D(VBLANK(TRANSCODER_B), D_ALL); + MMIO_D(VSYNC(TRANSCODER_B), D_ALL); + MMIO_D(BCLRPAT(TRANSCODER_B), D_ALL); + MMIO_D(VSYNCSHIFT(TRANSCODER_B), D_ALL); + MMIO_D(PIPESRC(TRANSCODER_B), D_ALL); + + MMIO_D(HTOTAL(TRANSCODER_C), D_ALL); + MMIO_D(HBLANK(TRANSCODER_C), D_ALL); + MMIO_D(HSYNC(TRANSCODER_C), D_ALL); + MMIO_D(VTOTAL(TRANSCODER_C), D_ALL); + MMIO_D(VBLANK(TRANSCODER_C), D_ALL); + MMIO_D(VSYNC(TRANSCODER_C), D_ALL); + MMIO_D(BCLRPAT(TRANSCODER_C), D_ALL); + MMIO_D(VSYNCSHIFT(TRANSCODER_C), D_ALL); + MMIO_D(PIPESRC(TRANSCODER_C), D_ALL); + + MMIO_D(HTOTAL(TRANSCODER_EDP), D_ALL); + MMIO_D(HBLANK(TRANSCODER_EDP), D_ALL); + MMIO_D(HSYNC(TRANSCODER_EDP), D_ALL); + MMIO_D(VTOTAL(TRANSCODER_EDP), D_ALL); + MMIO_D(VBLANK(TRANSCODER_EDP), D_ALL); + MMIO_D(VSYNC(TRANSCODER_EDP), D_ALL); + MMIO_D(BCLRPAT(TRANSCODER_EDP), D_ALL); + MMIO_D(VSYNCSHIFT(TRANSCODER_EDP), D_ALL); + + MMIO_D(PIPE_DATA_M1(TRANSCODER_A), D_ALL); + MMIO_D(PIPE_DATA_N1(TRANSCODER_A), D_ALL); + MMIO_D(PIPE_DATA_M2(TRANSCODER_A), D_ALL); + MMIO_D(PIPE_DATA_N2(TRANSCODER_A), D_ALL); + MMIO_D(PIPE_LINK_M1(TRANSCODER_A), D_ALL); + MMIO_D(PIPE_LINK_N1(TRANSCODER_A), D_ALL); + MMIO_D(PIPE_LINK_M2(TRANSCODER_A), D_ALL); + MMIO_D(PIPE_LINK_N2(TRANSCODER_A), D_ALL); + + MMIO_D(PIPE_DATA_M1(TRANSCODER_B), D_ALL); + MMIO_D(PIPE_DATA_N1(TRANSCODER_B), D_ALL); + MMIO_D(PIPE_DATA_M2(TRANSCODER_B), D_ALL); + MMIO_D(PIPE_DATA_N2(TRANSCODER_B), D_ALL); + MMIO_D(PIPE_LINK_M1(TRANSCODER_B), D_ALL); + MMIO_D(PIPE_LINK_N1(TRANSCODER_B), D_ALL); + MMIO_D(PIPE_LINK_M2(TRANSCODER_B), D_ALL); + MMIO_D(PIPE_LINK_N2(TRANSCODER_B), D_ALL); + + MMIO_D(PIPE_DATA_M1(TRANSCODER_C), D_ALL); + MMIO_D(PIPE_DATA_N1(TRANSCODER_C), D_ALL); + MMIO_D(PIPE_DATA_M2(TRANSCODER_C), D_ALL); + MMIO_D(PIPE_DATA_N2(TRANSCODER_C), D_ALL); + MMIO_D(PIPE_LINK_M1(TRANSCODER_C), D_ALL); + MMIO_D(PIPE_LINK_N1(TRANSCODER_C), D_ALL); + MMIO_D(PIPE_LINK_M2(TRANSCODER_C), D_ALL); + MMIO_D(PIPE_LINK_N2(TRANSCODER_C), D_ALL); + + MMIO_D(PIPE_DATA_M1(TRANSCODER_EDP), D_ALL); + MMIO_D(PIPE_DATA_N1(TRANSCODER_EDP), D_ALL); + MMIO_D(PIPE_DATA_M2(TRANSCODER_EDP), D_ALL); + MMIO_D(PIPE_DATA_N2(TRANSCODER_EDP), D_ALL); + MMIO_D(PIPE_LINK_M1(TRANSCODER_EDP), D_ALL); + MMIO_D(PIPE_LINK_N1(TRANSCODER_EDP), D_ALL); + MMIO_D(PIPE_LINK_M2(TRANSCODER_EDP), D_ALL); + MMIO_D(PIPE_LINK_N2(TRANSCODER_EDP), D_ALL); + + MMIO_D(PF_CTL(PIPE_A), D_ALL); + MMIO_D(PF_WIN_SZ(PIPE_A), D_ALL); + MMIO_D(PF_WIN_POS(PIPE_A), D_ALL); + MMIO_D(PF_VSCALE(PIPE_A), D_ALL); + MMIO_D(PF_HSCALE(PIPE_A), D_ALL); + + MMIO_D(PF_CTL(PIPE_B), D_ALL); + MMIO_D(PF_WIN_SZ(PIPE_B), D_ALL); + MMIO_D(PF_WIN_POS(PIPE_B), D_ALL); + MMIO_D(PF_VSCALE(PIPE_B), D_ALL); + MMIO_D(PF_HSCALE(PIPE_B), D_ALL); + + MMIO_D(PF_CTL(PIPE_C), D_ALL); + MMIO_D(PF_WIN_SZ(PIPE_C), D_ALL); + MMIO_D(PF_WIN_POS(PIPE_C), D_ALL); + MMIO_D(PF_VSCALE(PIPE_C), D_ALL); + MMIO_D(PF_HSCALE(PIPE_C), D_ALL); + + MMIO_D(WM0_PIPEA_ILK, D_ALL); + MMIO_D(WM0_PIPEB_ILK, D_ALL); + MMIO_D(WM0_PIPEC_IVB, D_ALL); + MMIO_D(WM1_LP_ILK, D_ALL); + MMIO_D(WM2_LP_ILK, D_ALL); + MMIO_D(WM3_LP_ILK, D_ALL); + MMIO_D(WM1S_LP_ILK, D_ALL); + MMIO_D(WM2S_LP_IVB, D_ALL); + MMIO_D(WM3S_LP_IVB, D_ALL); + + MMIO_D(BLC_PWM_CPU_CTL2, D_ALL); + MMIO_D(BLC_PWM_CPU_CTL, D_ALL); + MMIO_D(BLC_PWM_PCH_CTL1, D_ALL); + MMIO_D(BLC_PWM_PCH_CTL2, D_ALL); + + MMIO_D(0x48268, D_ALL); + + MMIO_F(PCH_GMBUS0, 4 * 4, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(PCH_GPIOA, 6 * 4, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0xe4f00, 0x28, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_F(_PCH_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, NULL); + MMIO_F(_PCH_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, NULL); + MMIO_F(_PCH_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, NULL); + + MMIO_RO(PCH_ADPA, D_ALL, 0, + ADPA_CRT_HOTPLUG_MONITOR_MASK, NULL, NULL); + + MMIO_DH(_PCH_TRANSACONF, D_ALL, NULL, NULL); + MMIO_DH(_PCH_TRANSBCONF, D_ALL, NULL, NULL); + + MMIO_DH(FDI_RX_IIR(PIPE_A), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_IIR(PIPE_B), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_IIR(PIPE_C), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_IMR(PIPE_A), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_IMR(PIPE_B), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_IMR(PIPE_C), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_CTL(PIPE_A), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_CTL(PIPE_B), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_CTL(PIPE_C), D_ALL, NULL, NULL); + + MMIO_D(_PCH_TRANS_HTOTAL_A, D_ALL); + MMIO_D(_PCH_TRANS_HBLANK_A, D_ALL); + MMIO_D(_PCH_TRANS_HSYNC_A, D_ALL); + MMIO_D(_PCH_TRANS_VTOTAL_A, D_ALL); + MMIO_D(_PCH_TRANS_VBLANK_A, D_ALL); + MMIO_D(_PCH_TRANS_VSYNC_A, D_ALL); + MMIO_D(_PCH_TRANS_VSYNCSHIFT_A, D_ALL); + + MMIO_D(_PCH_TRANS_HTOTAL_B, D_ALL); + MMIO_D(_PCH_TRANS_HBLANK_B, D_ALL); + MMIO_D(_PCH_TRANS_HSYNC_B, D_ALL); + MMIO_D(_PCH_TRANS_VTOTAL_B, D_ALL); + MMIO_D(_PCH_TRANS_VBLANK_B, D_ALL); + MMIO_D(_PCH_TRANS_VSYNC_B, D_ALL); + MMIO_D(_PCH_TRANS_VSYNCSHIFT_B, D_ALL); + + MMIO_D(_PCH_TRANSA_DATA_M1, D_ALL); + MMIO_D(_PCH_TRANSA_DATA_N1, D_ALL); + MMIO_D(_PCH_TRANSA_DATA_M2, D_ALL); + MMIO_D(_PCH_TRANSA_DATA_N2, D_ALL); + MMIO_D(_PCH_TRANSA_LINK_M1, D_ALL); + MMIO_D(_PCH_TRANSA_LINK_N1, D_ALL); + MMIO_D(_PCH_TRANSA_LINK_M2, D_ALL); + MMIO_D(_PCH_TRANSA_LINK_N2, D_ALL); + + MMIO_D(TRANS_DP_CTL(PIPE_A), D_ALL); + MMIO_D(TRANS_DP_CTL(PIPE_B), D_ALL); + MMIO_D(TRANS_DP_CTL(PIPE_C), D_ALL); + + MMIO_D(TVIDEO_DIP_CTL(PIPE_A), D_ALL); + MMIO_D(TVIDEO_DIP_DATA(PIPE_A), D_ALL); + MMIO_D(TVIDEO_DIP_GCP(PIPE_A), D_ALL); + + MMIO_D(TVIDEO_DIP_CTL(PIPE_B), D_ALL); + MMIO_D(TVIDEO_DIP_DATA(PIPE_B), D_ALL); + MMIO_D(TVIDEO_DIP_GCP(PIPE_B), D_ALL); + + MMIO_D(TVIDEO_DIP_CTL(PIPE_C), D_ALL); + MMIO_D(TVIDEO_DIP_DATA(PIPE_C), D_ALL); + MMIO_D(TVIDEO_DIP_GCP(PIPE_C), D_ALL); + + MMIO_D(_FDI_RXA_MISC, D_ALL); + MMIO_D(_FDI_RXB_MISC, D_ALL); + MMIO_D(_FDI_RXA_TUSIZE1, D_ALL); + MMIO_D(_FDI_RXA_TUSIZE2, D_ALL); + MMIO_D(_FDI_RXB_TUSIZE1, D_ALL); + MMIO_D(_FDI_RXB_TUSIZE2, D_ALL); + + MMIO_DH(PCH_PP_CONTROL, D_ALL, NULL, NULL); + MMIO_D(PCH_PP_DIVISOR, D_ALL); + MMIO_D(PCH_PP_STATUS, D_ALL); + MMIO_D(PCH_LVDS, D_ALL); + MMIO_D(_PCH_DPLL_A, D_ALL); + MMIO_D(_PCH_DPLL_B, D_ALL); + MMIO_D(_PCH_FPA0, D_ALL); + MMIO_D(_PCH_FPA1, D_ALL); + MMIO_D(_PCH_FPB0, D_ALL); + MMIO_D(_PCH_FPB1, D_ALL); + MMIO_D(PCH_DREF_CONTROL, D_ALL); + MMIO_D(PCH_RAWCLK_FREQ, D_ALL); + MMIO_D(PCH_DPLL_SEL, D_ALL); + + MMIO_D(0x61208, D_ALL); + MMIO_D(0x6120c, D_ALL); + MMIO_D(PCH_PP_ON_DELAYS, D_ALL); + MMIO_D(PCH_PP_OFF_DELAYS, D_ALL); + + MMIO_DH(0xe651c, D_ALL, NULL, NULL); + MMIO_DH(0xe661c, D_ALL, NULL, NULL); + MMIO_DH(0xe671c, D_ALL, NULL, NULL); + MMIO_DH(0xe681c, D_ALL, NULL, NULL); + MMIO_DH(0xe6c04, D_ALL, NULL, NULL); + MMIO_DH(0xe6e1c, D_ALL, NULL, NULL); + + MMIO_RO(PCH_PORT_HOTPLUG, D_ALL, 0, + PORTA_HOTPLUG_STATUS_MASK + | PORTB_HOTPLUG_STATUS_MASK + | PORTC_HOTPLUG_STATUS_MASK + | PORTD_HOTPLUG_STATUS_MASK, + NULL, NULL); + + MMIO_DH(LCPLL_CTL, D_ALL, NULL, NULL); + MMIO_D(FUSE_STRAP, D_ALL); + MMIO_D(DIGITAL_PORT_HOTPLUG_CNTRL, D_ALL); + + MMIO_D(DISP_ARB_CTL, D_ALL); + MMIO_D(DISP_ARB_CTL2, D_ALL); + + MMIO_D(ILK_DISPLAY_CHICKEN1, D_ALL); + MMIO_D(ILK_DISPLAY_CHICKEN2, D_ALL); + MMIO_D(ILK_DSPCLK_GATE_D, D_ALL); + + MMIO_D(SOUTH_CHICKEN1, D_ALL); + MMIO_DH(SOUTH_CHICKEN2, D_ALL, NULL, NULL); + MMIO_D(_TRANSA_CHICKEN1, D_ALL); + MMIO_D(_TRANSB_CHICKEN1, D_ALL); + MMIO_D(SOUTH_DSPCLK_GATE_D, D_ALL); + MMIO_D(_TRANSA_CHICKEN2, D_ALL); + MMIO_D(_TRANSB_CHICKEN2, D_ALL); + + MMIO_D(ILK_DPFC_CB_BASE, D_ALL); + MMIO_D(ILK_DPFC_CONTROL, D_ALL); + MMIO_D(ILK_DPFC_RECOMP_CTL, D_ALL); + MMIO_D(ILK_DPFC_STATUS, D_ALL); + MMIO_D(ILK_DPFC_FENCE_YOFF, D_ALL); + MMIO_D(ILK_DPFC_CHICKEN, D_ALL); + MMIO_D(ILK_FBC_RT_BASE, D_ALL); + + MMIO_D(IPS_CTL, D_ALL); + + MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BY(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BU(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BV(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_MODE(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_A), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_A), D_ALL); + + MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BY(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BU(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BV(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_MODE(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_B), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_B), D_ALL); + + MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BY(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BU(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_COEFF_BV(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_MODE(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_C), D_ALL); + MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_C), D_ALL); + + MMIO_D(0x60110, D_ALL); + MMIO_D(0x61110, D_ALL); + MMIO_F(0x70400, 0x40, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x71400, 0x40, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x72400, 0x40, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x70440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); + MMIO_F(0x71440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); + MMIO_F(0x72440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); + MMIO_F(0x7044c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); + MMIO_F(0x7144c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); + MMIO_F(0x7244c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); + + MMIO_D(PIPE_WM_LINETIME(PIPE_A), D_ALL); + MMIO_D(PIPE_WM_LINETIME(PIPE_B), D_ALL); + MMIO_D(PIPE_WM_LINETIME(PIPE_C), D_ALL); + MMIO_D(SPLL_CTL, D_ALL); + MMIO_D(_WRPLL_CTL1, D_ALL); + MMIO_D(_WRPLL_CTL2, D_ALL); + MMIO_D(PORT_CLK_SEL(PORT_A), D_ALL); + MMIO_D(PORT_CLK_SEL(PORT_B), D_ALL); + MMIO_D(PORT_CLK_SEL(PORT_C), D_ALL); + MMIO_D(PORT_CLK_SEL(PORT_D), D_ALL); + MMIO_D(PORT_CLK_SEL(PORT_E), D_ALL); + MMIO_D(TRANS_CLK_SEL(TRANSCODER_A), D_ALL); + MMIO_D(TRANS_CLK_SEL(TRANSCODER_B), D_ALL); + MMIO_D(TRANS_CLK_SEL(TRANSCODER_C), D_ALL); + + MMIO_D(HSW_NDE_RSTWRN_OPT, D_ALL); + MMIO_D(0x46508, D_ALL); + + MMIO_D(0x49080, D_ALL); + MMIO_D(0x49180, D_ALL); + MMIO_D(0x49280, D_ALL); + + MMIO_F(0x49090, 0x14, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x49190, 0x14, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x49290, 0x14, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_D(GAMMA_MODE(PIPE_A), D_ALL); + MMIO_D(GAMMA_MODE(PIPE_B), D_ALL); + MMIO_D(GAMMA_MODE(PIPE_C), D_ALL); + + MMIO_D(0x4a400, D_ALL); + MMIO_D(0x4ac00, D_ALL); + MMIO_D(0x4b400, D_ALL); + + MMIO_D(PIPE_MULT(PIPE_A), D_ALL); + MMIO_D(PIPE_MULT(PIPE_B), D_ALL); + MMIO_D(PIPE_MULT(PIPE_C), D_ALL); + + MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_A), D_ALL); + MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_B), D_ALL); + MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_C), D_ALL); + + MMIO_DH(SFUSE_STRAP, D_ALL, NULL, NULL); + MMIO_D(SBI_ADDR, D_ALL); + MMIO_DH(SBI_DATA, D_ALL, NULL, NULL); + MMIO_DH(SBI_CTL_STAT, D_ALL, NULL, NULL); + MMIO_D(PIXCLK_GATE, D_ALL); + + MMIO_F(_DPA_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_RO(DDI_BUF_CTL(PORT_A), D_ALL, 0, + DDI_INIT_DISPLAY_DETECTED, NULL, NULL); + MMIO_RO(DDI_BUF_CTL(PORT_B), D_ALL, 0, + DDI_INIT_DISPLAY_DETECTED, NULL, NULL); + MMIO_RO(DDI_BUF_CTL(PORT_C), D_ALL, 0, + DDI_INIT_DISPLAY_DETECTED, NULL, NULL); + MMIO_RO(DDI_BUF_CTL(PORT_D), D_ALL, 0, + DDI_INIT_DISPLAY_DETECTED, NULL, NULL); + MMIO_RO(DDI_BUF_CTL(PORT_E), D_ALL, 0, + DDI_INIT_DISPLAY_DETECTED, NULL, NULL); + + MMIO_DH(DP_TP_CTL(PORT_A), D_ALL, NULL, NULL); + MMIO_DH(DP_TP_CTL(PORT_B), D_ALL, NULL, NULL); + MMIO_DH(DP_TP_CTL(PORT_C), D_ALL, NULL, NULL); + MMIO_DH(DP_TP_CTL(PORT_D), D_ALL, NULL, NULL); + MMIO_DH(DP_TP_CTL(PORT_E), D_ALL, NULL, NULL); + + MMIO_RO(DP_TP_STATUS(PORT_A), D_ALL, 0, + (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); + MMIO_RO(DP_TP_STATUS(PORT_B), D_ALL, 0, + (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); + MMIO_RO(DP_TP_STATUS(PORT_C), D_ALL, 0, + (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); + MMIO_RO(DP_TP_STATUS(PORT_D), D_ALL, 0, + (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); + MMIO_RO(DP_TP_STATUS(PORT_E), D_ALL, 0, + (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); + + MMIO_F(_DDI_BUF_TRANS_A, 0x50, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x64e60, 0x50, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x64eC0, 0x50, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x64f20, 0x50, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x64f80, 0x50, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_D(HSW_AUD_CFG(PIPE_A), D_ALL); + MMIO_D(HSW_AUD_PIN_ELD_CP_VLD, D_ALL); + + MMIO_DH(_TRANS_DDI_FUNC_CTL_A, D_ALL, NULL, NULL); + MMIO_DH(_TRANS_DDI_FUNC_CTL_B, D_ALL, NULL, NULL); + MMIO_DH(_TRANS_DDI_FUNC_CTL_C, D_ALL, NULL, NULL); + MMIO_DH(_TRANS_DDI_FUNC_CTL_EDP, D_ALL, NULL, NULL); + + MMIO_D(_TRANSA_MSA_MISC, D_ALL); + MMIO_D(_TRANSB_MSA_MISC, D_ALL); + MMIO_D(_TRANSC_MSA_MISC, D_ALL); + MMIO_D(_TRANS_EDP_MSA_MISC, D_ALL); + + MMIO_DH(FORCEWAKE, D_ALL, NULL, NULL); + MMIO_D(FORCEWAKE_ACK, D_ALL); + MMIO_D(GEN6_GT_CORE_STATUS, D_ALL); + MMIO_D(GEN6_GT_THREAD_STATUS_REG, D_ALL); + MMIO_D(GTFIFODBG, D_ALL); + MMIO_D(GTFIFOCTL, D_ALL); + MMIO_DH(FORCEWAKE_MT, D_PRE_SKL, NULL, mul_force_wake_write); + MMIO_DH(FORCEWAKE_ACK_HSW, D_HSW | D_BDW, NULL, NULL); + MMIO_D(ECOBUS, D_ALL); + MMIO_DH(GEN6_RC_CONTROL, D_ALL, NULL, NULL); + MMIO_DH(GEN6_RC_STATE, D_ALL, NULL, NULL); + MMIO_D(GEN6_RPNSWREQ, D_ALL); + MMIO_D(GEN6_RC_VIDEO_FREQ, D_ALL); + MMIO_D(GEN6_RP_DOWN_TIMEOUT, D_ALL); + MMIO_D(GEN6_RP_INTERRUPT_LIMITS, D_ALL); + MMIO_D(GEN6_RPSTAT1, D_ALL); + MMIO_D(GEN6_RP_CONTROL, D_ALL); + MMIO_D(GEN6_RP_UP_THRESHOLD, D_ALL); + MMIO_D(GEN6_RP_DOWN_THRESHOLD, D_ALL); + MMIO_D(GEN6_RP_CUR_UP_EI, D_ALL); + MMIO_D(GEN6_RP_CUR_UP, D_ALL); + MMIO_D(GEN6_RP_PREV_UP, D_ALL); + MMIO_D(GEN6_RP_CUR_DOWN_EI, D_ALL); + MMIO_D(GEN6_RP_CUR_DOWN, D_ALL); + MMIO_D(GEN6_RP_PREV_DOWN, D_ALL); + MMIO_D(GEN6_RP_UP_EI, D_ALL); + MMIO_D(GEN6_RP_DOWN_EI, D_ALL); + MMIO_D(GEN6_RP_IDLE_HYSTERSIS, D_ALL); + MMIO_D(GEN6_RC1_WAKE_RATE_LIMIT, D_ALL); + MMIO_D(GEN6_RC6_WAKE_RATE_LIMIT, D_ALL); + MMIO_D(GEN6_RC6pp_WAKE_RATE_LIMIT, D_ALL); + MMIO_D(GEN6_RC_EVALUATION_INTERVAL, D_ALL); + MMIO_D(GEN6_RC_IDLE_HYSTERSIS, D_ALL); + MMIO_D(GEN6_RC_SLEEP, D_ALL); + MMIO_D(GEN6_RC1e_THRESHOLD, D_ALL); + MMIO_D(GEN6_RC6_THRESHOLD, D_ALL); + MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL); + MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL); + MMIO_D(GEN6_PMINTRMSK, D_ALL); + MMIO_DH(HSW_PWR_WELL_BIOS, D_HSW | D_BDW, NULL, NULL); + MMIO_DH(HSW_PWR_WELL_DRIVER, D_HSW | D_BDW, NULL, NULL); + MMIO_DH(HSW_PWR_WELL_KVMR, D_HSW | D_BDW, NULL, NULL); + MMIO_DH(HSW_PWR_WELL_DEBUG, D_HSW | D_BDW, NULL, NULL); + MMIO_DH(HSW_PWR_WELL_CTL5, D_HSW | D_BDW, NULL, NULL); + MMIO_DH(HSW_PWR_WELL_CTL6, D_HSW | D_BDW, NULL, NULL); + + MMIO_D(RSTDBYCTL, D_ALL); + + MMIO_DH(GEN6_GDRST, D_ALL, NULL, gdrst_mmio_write); + MMIO_F(FENCE_REG_GEN6_LO(0), 0x80, 0, 0, 0, D_ALL, fence_mmio_read, fence_mmio_write); + MMIO_F(VGT_PVINFO_PAGE, VGT_PVINFO_SIZE, F_UNALIGN, 0, 0, D_ALL, pvinfo_mmio_read, pvinfo_mmio_write); + MMIO_DH(CPU_VGACNTRL, D_ALL, NULL, NULL); + + MMIO_F(MCHBAR_MIRROR_BASE_SNB, 0x40000, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_D(TILECTL, D_ALL); + + MMIO_D(GEN6_UCGCTL1, D_ALL); + MMIO_D(GEN6_UCGCTL2, D_ALL); + + MMIO_F(0x4f000, 0x90, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_D(GEN6_PCODE_MAILBOX, D_PRE_SKL); + MMIO_D(GEN6_PCODE_DATA, D_ALL); + MMIO_D(0x13812c, D_ALL); + MMIO_DH(GEN7_ERR_INT, D_ALL, NULL, NULL); + MMIO_D(HSW_EDRAM_CAP, D_ALL); + MMIO_D(HSW_IDICR, D_ALL); + MMIO_DH(GFX_FLSH_CNTL_GEN6, D_ALL, NULL, NULL); + + MMIO_D(0x3c, D_ALL); + MMIO_D(0x860, D_ALL); + MMIO_D(ECOSKPD, D_ALL); + MMIO_D(0x121d0, D_ALL); + MMIO_D(GEN6_BLITTER_ECOSKPD, D_ALL); + MMIO_D(0x41d0, D_ALL); + MMIO_D(GAC_ECO_BITS, D_ALL); + MMIO_D(0x6200, D_ALL); + MMIO_D(0x6204, D_ALL); + MMIO_D(0x6208, D_ALL); + MMIO_D(0x7118, D_ALL); + MMIO_D(0x7180, D_ALL); + MMIO_D(0x7408, D_ALL); + MMIO_D(0x7c00, D_ALL); + MMIO_D(GEN6_MBCTL, D_ALL); + MMIO_D(0x911c, D_ALL); + MMIO_D(0x9120, D_ALL); + + MMIO_D(GAB_CTL, D_ALL); + MMIO_D(0x48800, D_ALL); + MMIO_D(0xce044, D_ALL); + MMIO_D(0xe6500, D_ALL); + MMIO_D(0xe6504, D_ALL); + MMIO_D(0xe6600, D_ALL); + MMIO_D(0xe6604, D_ALL); + MMIO_D(0xe6700, D_ALL); + MMIO_D(0xe6704, D_ALL); + MMIO_D(0xe6800, D_ALL); + MMIO_D(0xe6804, D_ALL); + MMIO_D(PCH_GMBUS4, D_ALL); + MMIO_D(PCH_GMBUS5, D_ALL); + + MMIO_D(0x902c, D_ALL); + MMIO_D(0xec008, D_ALL); + MMIO_D(0xec00c, D_ALL); + MMIO_D(0xec008 + 0x18, D_ALL); + MMIO_D(0xec00c + 0x18, D_ALL); + MMIO_D(0xec008 + 0x18 * 2, D_ALL); + MMIO_D(0xec00c + 0x18 * 2, D_ALL); + MMIO_D(0xec008 + 0x18 * 3, D_ALL); + MMIO_D(0xec00c + 0x18 * 3, D_ALL); + MMIO_D(0xec408, D_ALL); + MMIO_D(0xec40c, D_ALL); + MMIO_D(0xec408 + 0x18, D_ALL); + MMIO_D(0xec40c + 0x18, D_ALL); + MMIO_D(0xec408 + 0x18 * 2, D_ALL); + MMIO_D(0xec40c + 0x18 * 2, D_ALL); + MMIO_D(0xec408 + 0x18 * 3, D_ALL); + MMIO_D(0xec40c + 0x18 * 3, D_ALL); + MMIO_D(0xfc810, D_ALL); + MMIO_D(0xfc81c, D_ALL); + MMIO_D(0xfc828, D_ALL); + MMIO_D(0xfc834, D_ALL); + MMIO_D(0xfcc00, D_ALL); + MMIO_D(0xfcc0c, D_ALL); + MMIO_D(0xfcc18, D_ALL); + MMIO_D(0xfcc24, D_ALL); + MMIO_D(0xfd000, D_ALL); + MMIO_D(0xfd00c, D_ALL); + MMIO_D(0xfd018, D_ALL); + MMIO_D(0xfd024, D_ALL); + MMIO_D(0xfd034, D_ALL); + + MMIO_DH(FPGA_DBG, D_ALL, NULL, fpga_dbg_mmio_write); + MMIO_D(0x2054, D_ALL); + MMIO_D(0x12054, D_ALL); + MMIO_D(0x22054, D_ALL); + MMIO_D(0x1a054, D_ALL); + + MMIO_D(0x44070, D_ALL); + + MMIO_D(0x215c, D_HSW_PLUS); + MMIO_DFH(0x2178, D_ALL, F_CMD_ACCESS, NULL, NULL); + MMIO_DFH(0x217c, D_ALL, F_CMD_ACCESS, NULL, NULL); + MMIO_DFH(0x12178, D_ALL, F_CMD_ACCESS, NULL, NULL); + MMIO_DFH(0x1217c, D_ALL, F_CMD_ACCESS, NULL, NULL); + + MMIO_F(0x2290, 8, 0, 0, 0, D_HSW_PLUS, NULL, NULL); + MMIO_D(OACONTROL, D_HSW); + MMIO_D(0x2b00, D_BDW_PLUS); + MMIO_D(0x2360, D_BDW_PLUS); + MMIO_F(0x5200, 32, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x5240, 32, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(0x5280, 16, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_DFH(0x1c17c, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); + MMIO_DFH(0x1c178, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); + MMIO_D(BCS_SWCTRL, D_ALL); + + MMIO_F(HS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(DS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(IA_VERTICES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(IA_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(VS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(GS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(GS_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(CL_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(CL_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(PS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(PS_DEPTH_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_DH(0x4260, D_BDW_PLUS, NULL, NULL); + MMIO_DH(0x4264, D_BDW_PLUS, NULL, NULL); + MMIO_DH(0x4268, D_BDW_PLUS, NULL, NULL); + MMIO_DH(0x426c, D_BDW_PLUS, NULL, NULL); + MMIO_DH(0x4270, D_BDW_PLUS, NULL, NULL); + MMIO_DFH(0x4094, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); + return 0; } static int init_broadwell_mmio_info(struct intel_gvt *gvt) { + struct drm_i915_private *dev_priv = gvt->dev_priv; int ret; - MMIO_F(0, 0, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_DH(RING_IMR(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, + intel_vgpu_reg_imr_handler); + + MMIO_DH(GEN8_GT_IMR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_GT_IER(0), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_GT_IIR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_GT_ISR(0), D_BDW_PLUS); + + MMIO_DH(GEN8_GT_IMR(1), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_GT_IER(1), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_GT_IIR(1), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_GT_ISR(1), D_BDW_PLUS); + + MMIO_DH(GEN8_GT_IMR(2), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_GT_IER(2), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_GT_IIR(2), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_GT_ISR(2), D_BDW_PLUS); + + MMIO_DH(GEN8_GT_IMR(3), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_GT_IER(3), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_GT_IIR(3), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_GT_ISR(3), D_BDW_PLUS); + + MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_A), D_BDW_PLUS, NULL, + intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_DE_PIPE_IER(PIPE_A), D_BDW_PLUS, NULL, + intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_A), D_BDW_PLUS, NULL, + intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_DE_PIPE_ISR(PIPE_A), D_BDW_PLUS); + + MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_B), D_BDW_PLUS, NULL, + intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_DE_PIPE_IER(PIPE_B), D_BDW_PLUS, NULL, + intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_B), D_BDW_PLUS, NULL, + intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_DE_PIPE_ISR(PIPE_B), D_BDW_PLUS); + + MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_C), D_BDW_PLUS, NULL, + intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_DE_PIPE_IER(PIPE_C), D_BDW_PLUS, NULL, + intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_C), D_BDW_PLUS, NULL, + intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_DE_PIPE_ISR(PIPE_C), D_BDW_PLUS); + + MMIO_DH(GEN8_DE_PORT_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_DE_PORT_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_DE_PORT_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_DE_PORT_ISR, D_BDW_PLUS); + + MMIO_DH(GEN8_DE_MISC_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_DE_MISC_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_DE_MISC_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_DE_MISC_ISR, D_BDW_PLUS); + + MMIO_DH(GEN8_PCU_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); + MMIO_DH(GEN8_PCU_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); + MMIO_DH(GEN8_PCU_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); + MMIO_D(GEN8_PCU_ISR, D_BDW_PLUS); + + MMIO_DH(GEN8_MASTER_IRQ, D_BDW_PLUS, NULL, + intel_vgpu_reg_master_irq_handler); + + MMIO_D(RING_HWSTAM(GEN8_BSD2_RING_BASE), D_BDW_PLUS); + MMIO_D(0x1c134, D_BDW_PLUS); + + MMIO_D(RING_TAIL(GEN8_BSD2_RING_BASE), D_BDW_PLUS); + MMIO_D(RING_HEAD(GEN8_BSD2_RING_BASE), D_BDW_PLUS); + MMIO_GM(RING_START(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL); + MMIO_D(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS); + MMIO_D(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS); + MMIO_D(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS); + MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); + MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, + NULL, NULL); + MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, + NULL, NULL); + MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, + NULL, NULL); + + MMIO_RING_D(RING_ACTHD_UDW, D_BDW_PLUS); + +#define RING_REG(base) (base + 0x230) + MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, NULL); + MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL); +#undef RING_REG + +#define RING_REG(base) (base + 0x234) + MMIO_RING_F(RING_REG, 8, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL); + MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0, ~0LL, D_BDW_PLUS, NULL, NULL); +#undef RING_REG + +#define RING_REG(base) (base + 0x244) + MMIO_RING_D(RING_REG, D_BDW_PLUS); + MMIO_D(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS); +#undef RING_REG + +#define RING_REG(base) (base + 0x370) + MMIO_RING_F(RING_REG, 48, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL); + MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 48, F_RO, 0, ~0, D_BDW_PLUS, + NULL, NULL); +#undef RING_REG + +#define RING_REG(base) (base + 0x3a0) + MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); + MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, NULL, NULL); +#undef RING_REG + + MMIO_D(PIPEMISC(PIPE_A), D_BDW_PLUS); + MMIO_D(PIPEMISC(PIPE_B), D_BDW_PLUS); + MMIO_D(PIPEMISC(PIPE_C), D_BDW_PLUS); + MMIO_D(0x1c1d0, D_BDW_PLUS); + MMIO_D(GEN6_MBCUNIT_SNPCR, D_BDW_PLUS); + MMIO_D(GEN7_MISCCPCTL, D_BDW_PLUS); + MMIO_D(0x1c054, D_BDW_PLUS); + + MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS); + MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS); + + MMIO_D(GAMTARBMODE, D_BDW_PLUS); + +#define RING_REG(base) (base + 0x270) + MMIO_RING_F(RING_REG, 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL); + MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL); +#undef RING_REG + + MMIO_RING_GM(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL); + MMIO_GM(0x1c080, D_BDW_PLUS, NULL, NULL); + + MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); + + MMIO_D(CHICKEN_PIPESL_1(PIPE_A), D_BDW); + MMIO_D(CHICKEN_PIPESL_1(PIPE_B), D_BDW); + MMIO_D(CHICKEN_PIPESL_1(PIPE_C), D_BDW); + + MMIO_D(WM_MISC, D_BDW); + MMIO_D(BDW_EDP_PSR_BASE, D_BDW); + + MMIO_D(0x66c00, D_BDW_PLUS); + MMIO_D(0x66c04, D_BDW_PLUS); + + MMIO_D(HSW_GTT_CACHE_EN, D_BDW_PLUS); + + MMIO_D(GEN8_EU_DISABLE0, D_BDW_PLUS); + MMIO_D(GEN8_EU_DISABLE1, D_BDW_PLUS); + MMIO_D(GEN8_EU_DISABLE2, D_BDW_PLUS); + + MMIO_D(0xfdc, D_BDW); + MMIO_D(GEN8_ROW_CHICKEN, D_BDW_PLUS); + MMIO_D(GEN7_ROW_CHICKEN2, D_BDW_PLUS); + MMIO_D(GEN8_UCGCTL6, D_BDW_PLUS); + + MMIO_D(0xb1f0, D_BDW); + MMIO_D(0xb1c0, D_BDW); + MMIO_DFH(GEN8_L3SQCREG4, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); + MMIO_D(0xb100, D_BDW); + MMIO_D(0xb10c, D_BDW); + MMIO_D(0xb110, D_BDW); + + MMIO_DH(0x24d0, D_BDW_PLUS, NULL, NULL); + MMIO_DH(0x24d4, D_BDW_PLUS, NULL, NULL); + MMIO_DH(0x24d8, D_BDW_PLUS, NULL, NULL); + MMIO_DH(0x24dc, D_BDW_PLUS, NULL, NULL); + + MMIO_D(0x83a4, D_BDW); + MMIO_D(GEN8_L3_LRA_1_GPGPU, D_BDW_PLUS); + + MMIO_D(0x8430, D_BDW); + + MMIO_D(0x110000, D_BDW_PLUS); + + MMIO_D(0x48400, D_BDW_PLUS); + + MMIO_D(0x6e570, D_BDW_PLUS); + MMIO_D(0x65f10, D_BDW_PLUS); + + MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0xe180, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); + + MMIO_D(0x2248, D_BDW); + return 0; } +static int init_skl_mmio_info(struct intel_gvt *gvt) +{ + struct drm_i915_private *dev_priv = gvt->dev_priv; + int ret; + + MMIO_DH(FORCEWAKE_RENDER_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); + MMIO_DH(FORCEWAKE_ACK_RENDER_GEN9, D_SKL_PLUS, NULL, NULL); + MMIO_DH(FORCEWAKE_BLITTER_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); + MMIO_DH(FORCEWAKE_ACK_BLITTER_GEN9, D_SKL_PLUS, NULL, NULL); + MMIO_DH(FORCEWAKE_MEDIA_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); + MMIO_DH(FORCEWAKE_ACK_MEDIA_GEN9, D_SKL_PLUS, NULL, NULL); + + MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, NULL); + + MMIO_D(HSW_PWR_WELL_BIOS, D_SKL); + MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, NULL); + + MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL, NULL, NULL); + MMIO_D(0xa210, D_SKL_PLUS); + MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); + MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); + MMIO_DH(0x4ddc, D_SKL, NULL, NULL); + MMIO_DH(0x42080, D_SKL, NULL, NULL); + MMIO_D(0x45504, D_SKL); + MMIO_D(0x45520, D_SKL); + MMIO_D(0x46000, D_SKL); + MMIO_DH(0x46010, D_SKL, NULL, NULL); + MMIO_DH(0x46014, D_SKL, NULL, NULL); + MMIO_D(0x6C040, D_SKL); + MMIO_D(0x6C048, D_SKL); + MMIO_D(0x6C050, D_SKL); + MMIO_D(0x6C044, D_SKL); + MMIO_D(0x6C04C, D_SKL); + MMIO_D(0x6C054, D_SKL); + MMIO_D(0x6c058, D_SKL); + MMIO_D(0x6c05c, D_SKL); + MMIO_DH(0x6c060, D_SKL, NULL, NULL); + + MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL, NULL, NULL); + + MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL, NULL, NULL); + + MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL, NULL, NULL); + MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL, NULL, NULL); + + MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL); + + MMIO_DH(PLANE_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL); + + MMIO_DH(PLANE_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL); + MMIO_DH(PLANE_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL); + + MMIO_DH(CUR_BUF_CFG(PIPE_A), D_SKL, NULL, NULL); + MMIO_DH(CUR_BUF_CFG(PIPE_B), D_SKL, NULL, NULL); + MMIO_DH(CUR_BUF_CFG(PIPE_C), D_SKL, NULL, NULL); + + MMIO_F(PLANE_WM(PIPE_A, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(PLANE_WM(PIPE_A, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(PLANE_WM(PIPE_A, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + + MMIO_F(PLANE_WM(PIPE_B, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(PLANE_WM(PIPE_B, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(PLANE_WM(PIPE_B, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + + MMIO_F(PLANE_WM(PIPE_C, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(PLANE_WM(PIPE_C, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(PLANE_WM(PIPE_C, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + + MMIO_F(CUR_WM(PIPE_A, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(CUR_WM(PIPE_B, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(CUR_WM(PIPE_C, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); + + MMIO_DH(PLANE_WM_TRANS(PIPE_A, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_WM_TRANS(PIPE_A, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_WM_TRANS(PIPE_A, 2), D_SKL, NULL, NULL); + + MMIO_DH(PLANE_WM_TRANS(PIPE_B, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_WM_TRANS(PIPE_B, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_WM_TRANS(PIPE_B, 2), D_SKL, NULL, NULL); + + MMIO_DH(PLANE_WM_TRANS(PIPE_C, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_WM_TRANS(PIPE_C, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_WM_TRANS(PIPE_C, 2), D_SKL, NULL, NULL); + + MMIO_DH(CUR_WM_TRANS(PIPE_A), D_SKL, NULL, NULL); + MMIO_DH(CUR_WM_TRANS(PIPE_B), D_SKL, NULL, NULL); + MMIO_DH(CUR_WM_TRANS(PIPE_C), D_SKL, NULL, NULL); + + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL); + + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL); + + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL); + MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL); + + MMIO_DH(_REG_701C0(PIPE_A, 1), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_A, 2), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_A, 3), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_A, 4), D_SKL, NULL, NULL); + + MMIO_DH(_REG_701C0(PIPE_B, 1), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_B, 2), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_B, 3), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_B, 4), D_SKL, NULL, NULL); + + MMIO_DH(_REG_701C0(PIPE_C, 1), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_C, 2), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_C, 3), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C0(PIPE_C, 4), D_SKL, NULL, NULL); + + MMIO_DH(_REG_701C4(PIPE_A, 1), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_A, 2), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_A, 3), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_A, 4), D_SKL, NULL, NULL); + + MMIO_DH(_REG_701C4(PIPE_B, 1), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_B, 2), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_B, 3), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_B, 4), D_SKL, NULL, NULL); + + MMIO_DH(_REG_701C4(PIPE_C, 1), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_C, 2), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_C, 3), D_SKL, NULL, NULL); + MMIO_DH(_REG_701C4(PIPE_C, 4), D_SKL, NULL, NULL); + + MMIO_D(0x70380, D_SKL); + MMIO_D(0x71380, D_SKL); + MMIO_D(0x72380, D_SKL); + MMIO_D(0x7039c, D_SKL); + + MMIO_F(0x80000, 0x3000, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_D(0x8f074, D_SKL); + MMIO_D(0x8f004, D_SKL); + MMIO_D(0x8f034, D_SKL); + + MMIO_D(0xb11c, D_SKL); + + MMIO_D(0x51000, D_SKL); + MMIO_D(0x6c00c, D_SKL); + + MMIO_F(0xc800, 0x7f8, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(0xb020, 0x80, 0, 0, 0, D_SKL, NULL, NULL); + + MMIO_D(0xd08, D_SKL); + MMIO_D(0x20e0, D_SKL); + MMIO_D(0x20ec, D_SKL); + + /* TRTT */ + MMIO_D(0x4de0, D_SKL); + MMIO_D(0x4de4, D_SKL); + MMIO_D(0x4de8, D_SKL); + MMIO_D(0x4dec, D_SKL); + MMIO_D(0x4df0, D_SKL); + MMIO_DH(0x4df4, D_SKL, NULL, gen9_trtte_write); + MMIO_DH(0x4dfc, D_SKL, NULL, gen9_trtt_chicken_write); + + MMIO_D(0x45008, D_SKL); + + MMIO_D(0x46430, D_SKL); + + MMIO_D(0x46520, D_SKL); + + MMIO_D(0xc403c, D_SKL); + MMIO_D(0xb004, D_SKL); + MMIO_DH(DMA_CTRL, D_SKL_PLUS, NULL, dma_ctrl_write); + + MMIO_D(0x65900, D_SKL); + MMIO_D(0x1082c0, D_SKL); + MMIO_D(0x4068, D_SKL); + MMIO_D(0x67054, D_SKL); + MMIO_D(0x6e560, D_SKL); + MMIO_D(0x6e554, D_SKL); + MMIO_D(0x2b20, D_SKL); + MMIO_D(0x65f00, D_SKL); + MMIO_D(0x65f08, D_SKL); + MMIO_D(0x320f0, D_SKL); + + MMIO_D(_REG_VCS2_EXCC, D_SKL); + MMIO_D(0x70034, D_SKL); + MMIO_D(0x71034, D_SKL); + MMIO_D(0x72034, D_SKL); + + MMIO_D(_PLANE_KEYVAL_1(PIPE_A), D_SKL); + MMIO_D(_PLANE_KEYVAL_1(PIPE_B), D_SKL); + MMIO_D(_PLANE_KEYVAL_1(PIPE_C), D_SKL); + MMIO_D(_PLANE_KEYMSK_1(PIPE_A), D_SKL); + MMIO_D(_PLANE_KEYMSK_1(PIPE_B), D_SKL); + MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL); + + MMIO_D(0x44500, D_SKL); + return 0; +} /** * intel_gvt_find_mmio_info - find MMIO information entry by aligned offset * @gvt: GVT device @@ -239,9 +1707,116 @@ int intel_gvt_setup_mmio_info(struct intel_gvt *gvt) ret = init_broadwell_mmio_info(gvt); if (ret) goto err; + } else if (IS_SKYLAKE(dev_priv)) { + ret = init_broadwell_mmio_info(gvt); + if (ret) + goto err; + ret = init_skl_mmio_info(gvt); + if (ret) + goto err; } return 0; err: intel_gvt_clean_mmio_info(gvt); return ret; } + +/** + * intel_gvt_mmio_set_accessed - mark a MMIO has been accessed + * @gvt: a GVT device + * @offset: register offset + * + */ +void intel_gvt_mmio_set_accessed(struct intel_gvt *gvt, unsigned int offset) +{ + gvt->mmio.mmio_attribute[offset >> 2] |= + F_ACCESSED; +} + +/** + * intel_gvt_mmio_is_cmd_accessed - mark a MMIO could be accessed by command + * @gvt: a GVT device + * @offset: register offset + * + */ +bool intel_gvt_mmio_is_cmd_access(struct intel_gvt *gvt, + unsigned int offset) +{ + return gvt->mmio.mmio_attribute[offset >> 2] & + F_CMD_ACCESS; +} + +/** + * intel_gvt_mmio_is_unalign - mark a MMIO could be accessed unaligned + * @gvt: a GVT device + * @offset: register offset + * + */ +bool intel_gvt_mmio_is_unalign(struct intel_gvt *gvt, + unsigned int offset) +{ + return gvt->mmio.mmio_attribute[offset >> 2] & + F_UNALIGN; +} + +/** + * intel_gvt_mmio_set_cmd_accessed - mark a MMIO has been accessed by command + * @gvt: a GVT device + * @offset: register offset + * + */ +void intel_gvt_mmio_set_cmd_accessed(struct intel_gvt *gvt, + unsigned int offset) +{ + gvt->mmio.mmio_attribute[offset >> 2] |= + F_CMD_ACCESSED; +} + +/** + * intel_gvt_mmio_has_mode_mask - if a MMIO has a mode mask + * @gvt: a GVT device + * @offset: register offset + * + * Returns: + * True if a MMIO has a mode mask in its higher 16 bits, false if it isn't. + * + */ +bool intel_gvt_mmio_has_mode_mask(struct intel_gvt *gvt, unsigned int offset) +{ + return gvt->mmio.mmio_attribute[offset >> 2] & + F_MODE_MASK; +} + +/** + * intel_vgpu_default_mmio_read - default MMIO read handler + * @vgpu: a vGPU + * @offset: access offset + * @p_data: data return buffer + * @bytes: access data length + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + read_vreg(vgpu, offset, p_data, bytes); + return 0; +} + +/** + * intel_t_default_mmio_write - default MMIO write handler + * @vgpu: a vGPU + * @offset: access offset + * @p_data: write data buffer + * @bytes: access data length + * + * Returns: + * Zero on success, negative error code if failed. + */ +int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + write_vreg(vgpu, offset, p_data, bytes); + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index b5ffd78afd02..027ef558d91c 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -34,13 +34,13 @@ #define _GVT_HYPERCALL_H_ struct intel_gvt_io_emulation_ops { - int (*emulate_cfg_read)(void *, unsigned int, - void *, unsigned int); - int (*emulate_cfg_write)(void *, unsigned int, - void *, unsigned int); + int (*emulate_cfg_read)(void *, unsigned int, void *, unsigned int); + int (*emulate_cfg_write)(void *, unsigned int, void *, unsigned int); + int (*emulate_mmio_read)(void *, u64, void *, unsigned int); + int (*emulate_mmio_write)(void *, u64, void *, unsigned int); }; -extern struct intel_gvt_io_emulation_ops *gvt_io_emulation_ops; +extern struct intel_gvt_io_emulation_ops intel_gvt_io_emulation_ops; /* * Specific GVT-g MPT modules function collections. Currently GVT-g supports diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c new file mode 100644 index 000000000000..ce3af95d049f --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -0,0 +1,305 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ke Yu + * Kevin Tian + * Dexuan Cui + * + * Contributors: + * Tina Zhang + * Min He + * Niu Bing + * Zhi Wang + * + */ + +#include "i915_drv.h" + +/** + * intel_vgpu_gpa_to_mmio_offset - translate a GPA to MMIO offset + * @vgpu: a vGPU + * + * Returns: + * Zero on success, negative error code if failed + */ +int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa) +{ + u64 gttmmio_gpa = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0) & + ~GENMASK(3, 0); + return gpa - gttmmio_gpa; +} + +#define reg_is_mmio(gvt, reg) \ + (reg >= 0 && reg < gvt->device_info.mmio_size) + +#define reg_is_gtt(gvt, reg) \ + (reg >= gvt->device_info.gtt_start_offset \ + && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt)) + +/** + * intel_vgpu_emulate_mmio_read - emulate MMIO read + * @vgpu: a vGPU + * @pa: guest physical address + * @p_data: data return buffer + * @bytes: access data length + * + * Returns: + * Zero on success, negative error code if failed + */ +int intel_vgpu_emulate_mmio_read(void *__vgpu, uint64_t pa, + void *p_data, unsigned int bytes) +{ + struct intel_vgpu *vgpu = __vgpu; + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_mmio_info *mmio; + unsigned int offset = 0; + int ret = -EINVAL; + + mutex_lock(&gvt->lock); + + if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { + struct intel_vgpu_guest_page *gp; + + gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); + if (gp) { + ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, + p_data, bytes); + if (ret) { + gvt_err("vgpu%d: guest page read error %d, " + "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n", + vgpu->id, ret, + gp->gfn, pa, *(u32 *)p_data, bytes); + } + mutex_unlock(&gvt->lock); + return ret; + } + } + + offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa); + + if (WARN_ON(bytes > 8)) + goto err; + + if (reg_is_gtt(gvt, offset)) { + if (WARN_ON(!IS_ALIGNED(offset, 4) && !IS_ALIGNED(offset, 8))) + goto err; + if (WARN_ON(bytes != 4 && bytes != 8)) + goto err; + if (WARN_ON(!reg_is_gtt(gvt, offset + bytes - 1))) + goto err; + + ret = intel_vgpu_emulate_gtt_mmio_read(vgpu, offset, + p_data, bytes); + if (ret) + goto err; + mutex_unlock(&gvt->lock); + return ret; + } + + if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) { + ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, p_data, bytes); + mutex_unlock(&gvt->lock); + return ret; + } + + if (WARN_ON(!reg_is_mmio(gvt, offset + bytes - 1))) + goto err; + + mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4)); + if (!mmio && !vgpu->mmio.disable_warn_untrack) { + gvt_err("vgpu%d: read untracked MMIO %x len %d val %x\n", + vgpu->id, offset, bytes, *(u32 *)p_data); + + if (offset == 0x206c) { + gvt_err("------------------------------------------\n"); + gvt_err("vgpu%d: likely triggers a gfx reset\n", + vgpu->id); + gvt_err("------------------------------------------\n"); + vgpu->mmio.disable_warn_untrack = true; + } + } + + if (!intel_gvt_mmio_is_unalign(gvt, offset)) { + if (WARN_ON(!IS_ALIGNED(offset, bytes))) + goto err; + } + + if (mmio) { + if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) { + if (WARN_ON(offset + bytes > mmio->offset + mmio->size)) + goto err; + if (WARN_ON(mmio->offset != offset)) + goto err; + } + ret = mmio->read(vgpu, offset, p_data, bytes); + } else + ret = intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); + + if (ret) + goto err; + + intel_gvt_mmio_set_accessed(gvt, offset); + mutex_unlock(&gvt->lock); + return 0; +err: + gvt_err("vgpu%d: fail to emulate MMIO read %08x len %d\n", + vgpu->id, offset, bytes); + mutex_unlock(&gvt->lock); + return ret; +} + +/** + * intel_vgpu_emulate_mmio_write - emulate MMIO write + * @vgpu: a vGPU + * @pa: guest physical address + * @p_data: write data buffer + * @bytes: access data length + * + * Returns: + * Zero on success, negative error code if failed + */ +int intel_vgpu_emulate_mmio_write(void *__vgpu, uint64_t pa, + void *p_data, unsigned int bytes) +{ + struct intel_vgpu *vgpu = __vgpu; + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_mmio_info *mmio; + unsigned int offset = 0; + u32 old_vreg = 0, old_sreg = 0; + int ret = -EINVAL; + + mutex_lock(&gvt->lock); + + if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { + struct intel_vgpu_guest_page *gp; + + gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); + if (gp) { + ret = gp->handler(gp, pa, p_data, bytes); + if (ret) { + gvt_err("vgpu%d: guest page write error %d, " + "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n", + vgpu->id, ret, + gp->gfn, pa, *(u32 *)p_data, bytes); + } + mutex_unlock(&gvt->lock); + return ret; + } + } + + offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa); + + if (WARN_ON(bytes > 8)) + goto err; + + if (reg_is_gtt(gvt, offset)) { + if (WARN_ON(!IS_ALIGNED(offset, 4) && !IS_ALIGNED(offset, 8))) + goto err; + if (WARN_ON(bytes != 4 && bytes != 8)) + goto err; + if (WARN_ON(!reg_is_gtt(gvt, offset + bytes - 1))) + goto err; + + ret = intel_vgpu_emulate_gtt_mmio_write(vgpu, offset, + p_data, bytes); + if (ret) + goto err; + mutex_unlock(&gvt->lock); + return ret; + } + + if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) { + ret = intel_gvt_hypervisor_write_gpa(vgpu, pa, p_data, bytes); + mutex_unlock(&gvt->lock); + return ret; + } + + mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4)); + if (!mmio && !vgpu->mmio.disable_warn_untrack) + gvt_err("vgpu%d: write untracked MMIO %x len %d val %x\n", + vgpu->id, offset, bytes, *(u32 *)p_data); + + if (!intel_gvt_mmio_is_unalign(gvt, offset)) { + if (WARN_ON(!IS_ALIGNED(offset, bytes))) + goto err; + } + + if (mmio) { + u64 ro_mask = mmio->ro_mask; + + if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) { + if (WARN_ON(offset + bytes > mmio->offset + mmio->size)) + goto err; + if (WARN_ON(mmio->offset != offset)) + goto err; + } + + if (intel_gvt_mmio_has_mode_mask(gvt, mmio->offset)) { + old_vreg = vgpu_vreg(vgpu, offset); + old_sreg = vgpu_sreg(vgpu, offset); + } + + if (!ro_mask) { + ret = mmio->write(vgpu, offset, p_data, bytes); + } else { + /* Protect RO bits like HW */ + u64 data = 0; + + /* all register bits are RO. */ + if (ro_mask == ~(u64)0) { + gvt_err("vgpu%d: try to write RO reg %x\n", + vgpu->id, offset); + ret = 0; + goto out; + } + /* keep the RO bits in the virtual register */ + memcpy(&data, p_data, bytes); + data &= ~mmio->ro_mask; + data |= vgpu_vreg(vgpu, offset) & mmio->ro_mask; + ret = mmio->write(vgpu, offset, &data, bytes); + } + + /* higher 16bits of mode ctl regs are mask bits for change */ + if (intel_gvt_mmio_has_mode_mask(gvt, mmio->offset)) { + u32 mask = vgpu_vreg(vgpu, offset) >> 16; + + vgpu_vreg(vgpu, offset) = (old_vreg & ~mask) + | (vgpu_vreg(vgpu, offset) & mask); + vgpu_sreg(vgpu, offset) = (old_sreg & ~mask) + | (vgpu_sreg(vgpu, offset) & mask); + } + } else + ret = intel_vgpu_default_mmio_write(vgpu, offset, p_data, + bytes); + if (ret) + goto err; +out: + intel_gvt_mmio_set_accessed(gvt, offset); + mutex_unlock(&gvt->lock); + return 0; +err: + gvt_err("vgpu%d: fail to emulate MMIO write %08x len %d\n", + vgpu->id, offset, bytes); + mutex_unlock(&gvt->lock); + return ret; +} diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index 1fb1b49f912c..9dc739a01892 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h @@ -86,4 +86,20 @@ struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt, *offset; \ }) +int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa); +int intel_vgpu_emulate_mmio_read(void *__vgpu, u64 pa, void *p_data, + unsigned int bytes); +int intel_vgpu_emulate_mmio_write(void *__vgpu, u64 pa, void *p_data, + unsigned int bytes); +bool intel_gvt_mmio_is_cmd_access(struct intel_gvt *gvt, + unsigned int offset); +bool intel_gvt_mmio_is_unalign(struct intel_gvt *gvt, unsigned int offset); +void intel_gvt_mmio_set_accessed(struct intel_gvt *gvt, unsigned int offset); +void intel_gvt_mmio_set_cmd_accessed(struct intel_gvt *gvt, + unsigned int offset); +bool intel_gvt_mmio_has_mode_mask(struct intel_gvt *gvt, unsigned int offset); +int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes); +int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes); #endif diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h index 932c86b9b7bf..4842cb97c892 100644 --- a/drivers/gpu/drm/i915/gvt/reg.h +++ b/drivers/gpu/drm/i915/gvt/reg.h @@ -53,4 +53,23 @@ #define INTEL_GVT_OPREGION_PORDER 1 #define INTEL_GVT_OPREGION_SIZE (2 * 4096) +#define VGT_SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B) + +#define _REG_VECS_EXCC 0x1A028 +#define _REG_VCS2_EXCC 0x1c028 + +#define _REG_701C0(pipe, plane) (0x701c0 + pipe * 0x1000 + (plane - 1) * 0x100) +#define _REG_701C4(pipe, plane) (0x701c4 + pipe * 0x1000 + (plane - 1) * 0x100) + +#define GFX_MODE_BIT_SET_IN_MASK(val, bit) \ + ((((bit) & 0xffff0000) == 0) && !!((val) & (((bit) << 16)))) + +#define FORCEWAKE_RENDER_GEN9_REG 0xa278 +#define FORCEWAKE_ACK_RENDER_GEN9_REG 0x0D84 +#define FORCEWAKE_BLITTER_GEN9_REG 0xa188 +#define FORCEWAKE_ACK_BLITTER_GEN9_REG 0x130044 +#define FORCEWAKE_MEDIA_GEN9_REG 0xa270 +#define FORCEWAKE_ACK_MEDIA_GEN9_REG 0x0D88 +#define FORCEWAKE_ACK_HSW_REG 0x130044 + #endif diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 53308698929a..2d4aaa781757 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -52,6 +52,11 @@ static int setup_vgpu_mmio(struct intel_vgpu *vgpu) memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size); memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size); + + vgpu_vreg(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0; + + /* set the bit 0:2(Core C-State ) to C0 */ + vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0; return 0; } -- cgit v1.2.3 From 04d348ae3f0aea6523bc3b0688b5fc90c1c60d0e Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Mon, 25 Apr 2016 18:28:56 -0400 Subject: drm/i915/gvt: vGPU display virtualization This patch introduces the GVT-g display virtualization. It consists a collection of display MMIO handlers, like power well register handler, pipe register handler, plane register handler, which will emulate all display MMIOs behavior to support virtual mode setting sequence for guest. Signed-off-by: Bing Niu Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/debug.h | 3 + drivers/gpu/drm/i915/gvt/display.c | 329 ++++++++++ drivers/gpu/drm/i915/gvt/display.h | 163 +++++ drivers/gpu/drm/i915/gvt/edid.c | 531 +++++++++++++++++ drivers/gpu/drm/i915/gvt/edid.h | 150 +++++ drivers/gpu/drm/i915/gvt/gvt.c | 54 ++ drivers/gpu/drm/i915/gvt/gvt.h | 30 + drivers/gpu/drm/i915/gvt/handlers.c | 1091 ++++++++++++++++++++++++++++++---- drivers/gpu/drm/i915/gvt/interrupt.c | 26 + drivers/gpu/drm/i915/gvt/interrupt.h | 6 + drivers/gpu/drm/i915/gvt/vgpu.c | 7 + 12 files changed, 2277 insertions(+), 115 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/display.c create mode 100644 drivers/gpu/drm/i915/gvt/display.h create mode 100644 drivers/gpu/drm/i915/gvt/edid.c create mode 100644 drivers/gpu/drm/i915/gvt/edid.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 1a783a19bc4d..f87cd7fe9574 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,6 +1,6 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ - interrupt.o gtt.o cfg_space.o opregion.o mmio.o + interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index 47fabb065ac5..5c21c585ac00 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -39,4 +39,7 @@ #define gvt_dbg_mmio(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: mmio: "fmt, ##args) +#define gvt_dbg_dpy(fmt, args...) \ + DRM_DEBUG_DRIVER("gvt: dpy: "fmt, ##args) + #endif diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c new file mode 100644 index 000000000000..534000b91681 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -0,0 +1,329 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ke Yu + * Zhiyuan Lv + * + * Contributors: + * Terrence Xu + * Changbin Du + * Bing Niu + * Zhi Wang + * + */ + +#include "i915_drv.h" + +static int get_edp_pipe(struct intel_vgpu *vgpu) +{ + u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP); + int pipe = -1; + + switch (data & TRANS_DDI_EDP_INPUT_MASK) { + case TRANS_DDI_EDP_INPUT_A_ON: + case TRANS_DDI_EDP_INPUT_A_ONOFF: + pipe = PIPE_A; + break; + case TRANS_DDI_EDP_INPUT_B_ONOFF: + pipe = PIPE_B; + break; + case TRANS_DDI_EDP_INPUT_C_ONOFF: + pipe = PIPE_C; + break; + } + return pipe; +} + +static int edp_pipe_is_enabled(struct intel_vgpu *vgpu) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + + if (!(vgpu_vreg(vgpu, PIPECONF(_PIPE_EDP)) & PIPECONF_ENABLE)) + return 0; + + if (!(vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP) & TRANS_DDI_FUNC_ENABLE)) + return 0; + return 1; +} + +static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + + if (WARN_ON(pipe < PIPE_A || pipe >= I915_MAX_PIPES)) + return -EINVAL; + + if (vgpu_vreg(vgpu, PIPECONF(pipe)) & PIPECONF_ENABLE) + return 1; + + if (edp_pipe_is_enabled(vgpu) && + get_edp_pipe(vgpu) == pipe) + return 1; + return 0; +} + +/* EDID with 1024x768 as its resolution */ +static unsigned char virtual_dp_monitor_edid[] = { + /*Header*/ + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + /* Vendor & Product Identification */ + 0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17, + /* Version & Revision */ + 0x01, 0x04, + /* Basic Display Parameters & Features */ + 0xa5, 0x34, 0x20, 0x78, 0x23, + /* Color Characteristics */ + 0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54, + /* Established Timings: maximum resolution is 1024x768 */ + 0x21, 0x08, 0x00, + /* Standard Timings. All invalid */ + 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, + /* 18 Byte Data Blocks 1: invalid */ + 0x00, 0x00, 0x80, 0xa0, 0x70, 0xb0, + 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, + /* 18 Byte Data Blocks 2: invalid */ + 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + /* 18 Byte Data Blocks 3: invalid */ + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x48, + 0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20, + /* 18 Byte Data Blocks 4: invalid */ + 0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30, + 0x44, 0x58, 0x51, 0x0a, 0x20, 0x20, + /* Extension Block Count */ + 0x00, + /* Checksum */ + 0xef, +}; + +#define DPCD_HEADER_SIZE 0xb + +u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { + 0x11, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void emulate_monitor_status_change(struct intel_vgpu *vgpu) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTB_HOTPLUG_CPT | + SDE_PORTC_HOTPLUG_CPT | + SDE_PORTD_HOTPLUG_CPT); + + if (IS_SKYLAKE(dev_priv)) + vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT | + SDE_PORTE_HOTPLUG_SPT); + + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) + vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT; + + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) + vgpu_vreg(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT; + + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D)) + vgpu_vreg(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT; + + if (IS_SKYLAKE(dev_priv) && + intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) { + vgpu_vreg(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT; + } + + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) { + if (IS_BROADWELL(dev_priv)) + vgpu_vreg(vgpu, GEN8_DE_PORT_ISR) |= + GEN8_PORT_DP_A_HOTPLUG; + else + vgpu_vreg(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT; + } +} + +static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num) +{ + struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num); + + kfree(port->edid); + port->edid = NULL; + + kfree(port->dpcd); + port->dpcd = NULL; +} + +static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num, + int type) +{ + struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num); + + port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL); + if (!port->edid) + return -ENOMEM; + + port->dpcd = kzalloc(sizeof(*(port->dpcd)), GFP_KERNEL); + if (!port->dpcd) { + kfree(port->edid); + return -ENOMEM; + } + + memcpy(port->edid->edid_block, virtual_dp_monitor_edid, + EDID_SIZE); + port->edid->data_valid = true; + + memcpy(port->dpcd->data, dpcd_fix_data, DPCD_HEADER_SIZE); + port->dpcd->data_valid = true; + port->dpcd->data[DPCD_SINK_COUNT] = 0x1; + port->type = type; + + emulate_monitor_status_change(vgpu); + return 0; +} + +/** + * intel_gvt_check_vblank_emulation - check if vblank emulation timer should + * be turned on/off when a virtual pipe is enabled/disabled. + * @gvt: a GVT device + * + * This function is used to turn on/off vblank timer according to currently + * enabled/disabled virtual pipes. + * + */ +void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt) +{ + struct intel_gvt_irq *irq = &gvt->irq; + struct intel_vgpu *vgpu; + bool have_enabled_pipe = false; + int pipe, id; + + if (WARN_ON(!mutex_is_locked(&gvt->lock))) + return; + + hrtimer_cancel(&irq->vblank_timer.timer); + + for_each_active_vgpu(gvt, vgpu, id) { + for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) { + have_enabled_pipe = + pipe_is_enabled(vgpu, pipe); + if (have_enabled_pipe) + break; + } + } + + if (have_enabled_pipe) + hrtimer_start(&irq->vblank_timer.timer, + ktime_add_ns(ktime_get(), irq->vblank_timer.period), + HRTIMER_MODE_ABS); +} + +static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + struct intel_vgpu_irq *irq = &vgpu->irq; + int vblank_event[] = { + [PIPE_A] = PIPE_A_VBLANK, + [PIPE_B] = PIPE_B_VBLANK, + [PIPE_C] = PIPE_C_VBLANK, + }; + int event; + + if (pipe < PIPE_A || pipe > PIPE_C) + return; + + for_each_set_bit(event, irq->flip_done_event[pipe], + INTEL_GVT_EVENT_MAX) { + clear_bit(event, irq->flip_done_event[pipe]); + if (!pipe_is_enabled(vgpu, pipe)) + continue; + + vgpu_vreg(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++; + intel_vgpu_trigger_virtual_event(vgpu, event); + } + + if (pipe_is_enabled(vgpu, pipe)) { + vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(pipe))++; + intel_vgpu_trigger_virtual_event(vgpu, vblank_event[pipe]); + } +} + +static void emulate_vblank(struct intel_vgpu *vgpu) +{ + int pipe; + + for_each_pipe(vgpu->gvt->dev_priv, pipe) + emulate_vblank_on_pipe(vgpu, pipe); +} + +/** + * intel_gvt_emulate_vblank - trigger vblank events for vGPUs on GVT device + * @gvt: a GVT device + * + * This function is used to trigger vblank interrupts for vGPUs on GVT device + * + */ +void intel_gvt_emulate_vblank(struct intel_gvt *gvt) +{ + struct intel_vgpu *vgpu; + int id; + + if (WARN_ON(!mutex_is_locked(&gvt->lock))) + return; + + for_each_active_vgpu(gvt, vgpu, id) + emulate_vblank(vgpu); +} + +/** + * intel_vgpu_clean_display - clean vGPU virtual display emulation + * @vgpu: a vGPU + * + * This function is used to clean vGPU virtual display emulation stuffs + * + */ +void intel_vgpu_clean_display(struct intel_vgpu *vgpu) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + + if (IS_SKYLAKE(dev_priv)) + clean_virtual_dp_monitor(vgpu, PORT_D); + else + clean_virtual_dp_monitor(vgpu, PORT_B); +} + +/** + * intel_vgpu_init_display- initialize vGPU virtual display emulation + * @vgpu: a vGPU + * + * This function is used to initialize vGPU virtual display emulation stuffs + * + * Returns: + * Zero on success, negative error code if failed. + * + */ +int intel_vgpu_init_display(struct intel_vgpu *vgpu) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + + intel_vgpu_init_i2c_edid(vgpu); + + if (IS_SKYLAKE(dev_priv)) + return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D); + else + return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B); +} diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h new file mode 100644 index 000000000000..7a60cb848268 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/display.h @@ -0,0 +1,163 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ke Yu + * Zhiyuan Lv + * + * Contributors: + * Terrence Xu + * Changbin Du + * Bing Niu + * Zhi Wang + * + */ + +#ifndef _GVT_DISPLAY_H_ +#define _GVT_DISPLAY_H_ + +#define SBI_REG_MAX 20 +#define DPCD_SIZE 0x700 + +#define intel_vgpu_port(vgpu, port) \ + (&(vgpu->display.ports[port])) + +#define intel_vgpu_has_monitor_on_port(vgpu, port) \ + (intel_vgpu_port(vgpu, port)->edid && \ + intel_vgpu_port(vgpu, port)->edid->data_valid) + +#define intel_vgpu_port_is_dp(vgpu, port) \ + ((intel_vgpu_port(vgpu, port)->type == GVT_DP_A) || \ + (intel_vgpu_port(vgpu, port)->type == GVT_DP_B) || \ + (intel_vgpu_port(vgpu, port)->type == GVT_DP_C) || \ + (intel_vgpu_port(vgpu, port)->type == GVT_DP_D)) + +#define INTEL_GVT_MAX_UEVENT_VARS 3 + +/* DPCD start */ +#define DPCD_SIZE 0x700 + +/* DPCD */ +#define DP_SET_POWER 0x600 +#define DP_SET_POWER_D0 0x1 +#define AUX_NATIVE_WRITE 0x8 +#define AUX_NATIVE_READ 0x9 + +#define AUX_NATIVE_REPLY_MASK (0x3 << 4) +#define AUX_NATIVE_REPLY_ACK (0x0 << 4) +#define AUX_NATIVE_REPLY_NAK (0x1 << 4) +#define AUX_NATIVE_REPLY_DEFER (0x2 << 4) + +#define AUX_BURST_SIZE 16 + +/* DPCD addresses */ +#define DPCD_REV 0x000 +#define DPCD_MAX_LINK_RATE 0x001 +#define DPCD_MAX_LANE_COUNT 0x002 + +#define DPCD_TRAINING_PATTERN_SET 0x102 +#define DPCD_SINK_COUNT 0x200 +#define DPCD_LANE0_1_STATUS 0x202 +#define DPCD_LANE2_3_STATUS 0x203 +#define DPCD_LANE_ALIGN_STATUS_UPDATED 0x204 +#define DPCD_SINK_STATUS 0x205 + +/* link training */ +#define DPCD_TRAINING_PATTERN_SET_MASK 0x03 +#define DPCD_LINK_TRAINING_DISABLED 0x00 +#define DPCD_TRAINING_PATTERN_1 0x01 +#define DPCD_TRAINING_PATTERN_2 0x02 + +#define DPCD_CP_READY_MASK (1 << 6) + +/* lane status */ +#define DPCD_LANES_CR_DONE 0x11 +#define DPCD_LANES_EQ_DONE 0x22 +#define DPCD_SYMBOL_LOCKED 0x44 + +#define DPCD_INTERLANE_ALIGN_DONE 0x01 + +#define DPCD_SINK_IN_SYNC 0x03 +/* DPCD end */ + +#define SBI_RESPONSE_MASK 0x3 +#define SBI_RESPONSE_SHIFT 0x1 +#define SBI_STAT_MASK 0x1 +#define SBI_STAT_SHIFT 0x0 +#define SBI_OPCODE_SHIFT 8 +#define SBI_OPCODE_MASK (0xff << SBI_OPCODE_SHIFT) +#define SBI_CMD_IORD 2 +#define SBI_CMD_IOWR 3 +#define SBI_CMD_CRRD 6 +#define SBI_CMD_CRWR 7 +#define SBI_ADDR_OFFSET_SHIFT 16 +#define SBI_ADDR_OFFSET_MASK (0xffff << SBI_ADDR_OFFSET_SHIFT) + +struct intel_vgpu_sbi_register { + unsigned int offset; + u32 value; +}; + +struct intel_vgpu_sbi { + int number; + struct intel_vgpu_sbi_register registers[SBI_REG_MAX]; +}; + +enum intel_gvt_plane_type { + PRIMARY_PLANE = 0, + CURSOR_PLANE, + SPRITE_PLANE, + MAX_PLANE +}; + +struct intel_vgpu_dpcd_data { + bool data_valid; + u8 data[DPCD_SIZE]; +}; + +enum intel_vgpu_port_type { + GVT_CRT = 0, + GVT_DP_A, + GVT_DP_B, + GVT_DP_C, + GVT_DP_D, + GVT_HDMI_B, + GVT_HDMI_C, + GVT_HDMI_D, + GVT_PORT_MAX +}; + +struct intel_vgpu_port { + /* per display EDID information */ + struct intel_vgpu_edid_data *edid; + /* per display DPCD information */ + struct intel_vgpu_dpcd_data *dpcd; + int type; +}; + +void intel_gvt_emulate_vblank(struct intel_gvt *gvt); +void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt); + +int intel_vgpu_init_display(struct intel_vgpu *vgpu); +void intel_vgpu_clean_display(struct intel_vgpu *vgpu); + +#endif diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c new file mode 100644 index 000000000000..a07e4276126c --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/edid.c @@ -0,0 +1,531 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ke Yu + * Zhiyuan Lv + * + * Contributors: + * Terrence Xu + * Changbin Du + * Bing Niu + * Zhi Wang + * + */ + +#include "i915_drv.h" + +#define GMBUS1_TOTAL_BYTES_SHIFT 16 +#define GMBUS1_TOTAL_BYTES_MASK 0x1ff +#define gmbus1_total_byte_count(v) (((v) >> \ + GMBUS1_TOTAL_BYTES_SHIFT) & GMBUS1_TOTAL_BYTES_MASK) +#define gmbus1_slave_addr(v) (((v) & 0xff) >> 1) +#define gmbus1_slave_index(v) (((v) >> 8) & 0xff) +#define gmbus1_bus_cycle(v) (((v) >> 25) & 0x7) + +/* GMBUS0 bits definitions */ +#define _GMBUS_PIN_SEL_MASK (0x7) + +static unsigned char edid_get_byte(struct intel_vgpu *vgpu) +{ + struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid; + unsigned char chr = 0; + + if (edid->state == I2C_NOT_SPECIFIED || !edid->slave_selected) { + gvt_err("Driver tries to read EDID without proper sequence!\n"); + return 0; + } + if (edid->current_edid_read >= EDID_SIZE) { + gvt_err("edid_get_byte() exceeds the size of EDID!\n"); + return 0; + } + + if (!edid->edid_available) { + gvt_err("Reading EDID but EDID is not available!\n"); + return 0; + } + + if (intel_vgpu_has_monitor_on_port(vgpu, edid->port)) { + struct intel_vgpu_edid_data *edid_data = + intel_vgpu_port(vgpu, edid->port)->edid; + + chr = edid_data->edid_block[edid->current_edid_read]; + edid->current_edid_read++; + } else { + gvt_err("No EDID available during the reading?\n"); + } + return chr; +} + +static inline int get_port_from_gmbus0(u32 gmbus0) +{ + int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK; + int port = -EINVAL; + + if (port_select == 2) + port = PORT_E; + else if (port_select == 4) + port = PORT_C; + else if (port_select == 5) + port = PORT_B; + else if (port_select == 6) + port = PORT_D; + return port; +} + +static void reset_gmbus_controller(struct intel_vgpu *vgpu) +{ + vgpu_vreg(vgpu, PCH_GMBUS2) = GMBUS_HW_RDY; + if (!vgpu->display.i2c_edid.edid_available) + vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_SATOER; + vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE; +} + +/* GMBUS0 */ +static int gmbus0_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + int port, pin_select; + + memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes); + + pin_select = vgpu_vreg(vgpu, offset) & _GMBUS_PIN_SEL_MASK; + + intel_vgpu_init_i2c_edid(vgpu); + + if (pin_select == 0) + return 0; + + port = get_port_from_gmbus0(pin_select); + if (WARN_ON(port < 0)) + return 0; + + vgpu->display.i2c_edid.state = I2C_GMBUS; + vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE; + + vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE; + vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY | GMBUS_HW_WAIT_PHASE; + + if (intel_vgpu_has_monitor_on_port(vgpu, port) && + !intel_vgpu_port_is_dp(vgpu, port)) { + vgpu->display.i2c_edid.port = port; + vgpu->display.i2c_edid.edid_available = true; + vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_SATOER; + } else + vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_SATOER; + return 0; +} + +static int gmbus1_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; + u32 slave_addr; + u32 wvalue = *(u32 *)p_data; + + if (vgpu_vreg(vgpu, offset) & GMBUS_SW_CLR_INT) { + if (!(wvalue & GMBUS_SW_CLR_INT)) { + vgpu_vreg(vgpu, offset) &= ~GMBUS_SW_CLR_INT; + reset_gmbus_controller(vgpu); + } + /* + * TODO: "This bit is cleared to zero when an event + * causes the HW_RDY bit transition to occur " + */ + } else { + /* + * per bspec setting this bit can cause: + * 1) INT status bit cleared + * 2) HW_RDY bit asserted + */ + if (wvalue & GMBUS_SW_CLR_INT) { + vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_INT; + vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY; + } + + /* For virtualization, we suppose that HW is always ready, + * so GMBUS_SW_RDY should always be cleared + */ + if (wvalue & GMBUS_SW_RDY) + wvalue &= ~GMBUS_SW_RDY; + + i2c_edid->gmbus.total_byte_count = + gmbus1_total_byte_count(wvalue); + slave_addr = gmbus1_slave_addr(wvalue); + + /* vgpu gmbus only support EDID */ + if (slave_addr == EDID_ADDR) { + i2c_edid->slave_selected = true; + } else if (slave_addr != 0) { + gvt_dbg_dpy( + "vgpu%d: unsupported gmbus slave addr(0x%x)\n" + " gmbus operations will be ignored.\n", + vgpu->id, slave_addr); + } + + if (wvalue & GMBUS_CYCLE_INDEX) + i2c_edid->current_edid_read = + gmbus1_slave_index(wvalue); + + i2c_edid->gmbus.cycle_type = gmbus1_bus_cycle(wvalue); + switch (gmbus1_bus_cycle(wvalue)) { + case GMBUS_NOCYCLE: + break; + case GMBUS_STOP: + /* From spec: + * This can only cause a STOP to be generated + * if a GMBUS cycle is generated, the GMBUS is + * currently in a data/wait/idle phase, or it is in a + * WAIT phase + */ + if (gmbus1_bus_cycle(vgpu_vreg(vgpu, offset)) + != GMBUS_NOCYCLE) { + intel_vgpu_init_i2c_edid(vgpu); + /* After the 'stop' cycle, hw state would become + * 'stop phase' and then 'idle phase' after a + * few milliseconds. In emulation, we just set + * it as 'idle phase' ('stop phase' is not + * visible in gmbus interface) + */ + i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE; + vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE; + } + break; + case NIDX_NS_W: + case IDX_NS_W: + case NIDX_STOP: + case IDX_STOP: + /* From hw spec the GMBUS phase + * transition like this: + * START (-->INDEX) -->DATA + */ + i2c_edid->gmbus.phase = GMBUS_DATA_PHASE; + vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_ACTIVE; + break; + default: + gvt_err("Unknown/reserved GMBUS cycle detected!\n"); + break; + } + /* + * From hw spec the WAIT state will be + * cleared: + * (1) in a new GMBUS cycle + * (2) by generating a stop + */ + vgpu_vreg(vgpu, offset) = wvalue; + } + return 0; +} + +static int gmbus3_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + WARN_ON(1); + return 0; +} + +static int gmbus3_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + int i; + unsigned char byte_data; + struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; + int byte_left = i2c_edid->gmbus.total_byte_count - + i2c_edid->current_edid_read; + int byte_count = byte_left; + u32 reg_data = 0; + + /* Data can only be recevied if previous settings correct */ + if (vgpu_vreg(vgpu, PCH_GMBUS1) & GMBUS_SLAVE_READ) { + if (byte_left <= 0) { + memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); + return 0; + } + + if (byte_count > 4) + byte_count = 4; + for (i = 0; i < byte_count; i++) { + byte_data = edid_get_byte(vgpu); + reg_data |= (byte_data << (i << 3)); + } + + memcpy(&vgpu_vreg(vgpu, offset), ®_data, byte_count); + memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); + + if (byte_left <= 4) { + switch (i2c_edid->gmbus.cycle_type) { + case NIDX_STOP: + case IDX_STOP: + i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE; + break; + case NIDX_NS_W: + case IDX_NS_W: + default: + i2c_edid->gmbus.phase = GMBUS_WAIT_PHASE; + break; + } + intel_vgpu_init_i2c_edid(vgpu); + } + /* + * Read GMBUS3 during send operation, + * return the latest written value + */ + } else { + memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); + gvt_err("vgpu%d: warning: gmbus3 read with nothing returned\n", + vgpu->id); + } + return 0; +} + +static int gmbus2_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 value = vgpu_vreg(vgpu, offset); + + if (!(vgpu_vreg(vgpu, offset) & GMBUS_INUSE)) + vgpu_vreg(vgpu, offset) |= GMBUS_INUSE; + memcpy(p_data, (void *)&value, bytes); + return 0; +} + +static int gmbus2_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 wvalue = *(u32 *)p_data; + + if (wvalue & GMBUS_INUSE) + vgpu_vreg(vgpu, offset) &= ~GMBUS_INUSE; + /* All other bits are read-only */ + return 0; +} + +/** + * intel_gvt_i2c_handle_gmbus_read - emulate gmbus register mmio read + * @vgpu: a vGPU + * + * This function is used to emulate gmbus register mmio read + * + * Returns: + * Zero on success, negative error code if failed. + * + */ +int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + if (WARN_ON(bytes > 8 && (offset & (bytes - 1)))) + return -EINVAL; + + if (offset == i915_mmio_reg_offset(PCH_GMBUS2)) + return gmbus2_mmio_read(vgpu, offset, p_data, bytes); + else if (offset == i915_mmio_reg_offset(PCH_GMBUS3)) + return gmbus3_mmio_read(vgpu, offset, p_data, bytes); + + memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); + return 0; +} + +/** + * intel_gvt_i2c_handle_gmbus_write - emulate gmbus register mmio write + * @vgpu: a vGPU + * + * This function is used to emulate gmbus register mmio write + * + * Returns: + * Zero on success, negative error code if failed. + * + */ +int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + if (WARN_ON(bytes > 8 && (offset & (bytes - 1)))) + return -EINVAL; + + if (offset == i915_mmio_reg_offset(PCH_GMBUS0)) + return gmbus0_mmio_write(vgpu, offset, p_data, bytes); + else if (offset == i915_mmio_reg_offset(PCH_GMBUS1)) + return gmbus1_mmio_write(vgpu, offset, p_data, bytes); + else if (offset == i915_mmio_reg_offset(PCH_GMBUS2)) + return gmbus2_mmio_write(vgpu, offset, p_data, bytes); + else if (offset == i915_mmio_reg_offset(PCH_GMBUS3)) + return gmbus3_mmio_write(vgpu, offset, p_data, bytes); + + memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes); + return 0; +} + +enum { + AUX_CH_CTL = 0, + AUX_CH_DATA1, + AUX_CH_DATA2, + AUX_CH_DATA3, + AUX_CH_DATA4, + AUX_CH_DATA5 +}; + +static inline int get_aux_ch_reg(unsigned int offset) +{ + int reg; + + switch (offset & 0xff) { + case 0x10: + reg = AUX_CH_CTL; + break; + case 0x14: + reg = AUX_CH_DATA1; + break; + case 0x18: + reg = AUX_CH_DATA2; + break; + case 0x1c: + reg = AUX_CH_DATA3; + break; + case 0x20: + reg = AUX_CH_DATA4; + break; + case 0x24: + reg = AUX_CH_DATA5; + break; + default: + reg = -1; + break; + } + return reg; +} + +#define AUX_CTL_MSG_LENGTH(reg) \ + ((reg & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> \ + DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) + +/** + * intel_gvt_i2c_handle_aux_ch_write - emulate AUX channel register write + * @vgpu: a vGPU + * + * This function is used to emulate AUX channel register write + * + */ +void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu, + int port_idx, + unsigned int offset, + void *p_data) +{ + struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; + int msg_length, ret_msg_size; + int msg, addr, ctrl, op; + u32 value = *(u32 *)p_data; + int aux_data_for_write = 0; + int reg = get_aux_ch_reg(offset); + + if (reg != AUX_CH_CTL) { + vgpu_vreg(vgpu, offset) = value; + return; + } + + msg_length = AUX_CTL_MSG_LENGTH(value); + // check the msg in DATA register. + msg = vgpu_vreg(vgpu, offset + 4); + addr = (msg >> 8) & 0xffff; + ctrl = (msg >> 24) & 0xff; + op = ctrl >> 4; + if (!(value & DP_AUX_CH_CTL_SEND_BUSY)) { + /* The ctl write to clear some states */ + return; + } + + /* Always set the wanted value for vms. */ + ret_msg_size = (((op & 0x1) == GVT_AUX_I2C_READ) ? 2 : 1); + vgpu_vreg(vgpu, offset) = + DP_AUX_CH_CTL_DONE | + ((ret_msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) & + DP_AUX_CH_CTL_MESSAGE_SIZE_MASK); + + if (msg_length == 3) { + if (!(op & GVT_AUX_I2C_MOT)) { + /* stop */ + intel_vgpu_init_i2c_edid(vgpu); + } else { + /* start or restart */ + i2c_edid->aux_ch.i2c_over_aux_ch = true; + i2c_edid->aux_ch.aux_ch_mot = true; + if (addr == 0) { + /* reset the address */ + intel_vgpu_init_i2c_edid(vgpu); + } else if (addr == EDID_ADDR) { + i2c_edid->state = I2C_AUX_CH; + i2c_edid->port = port_idx; + i2c_edid->slave_selected = true; + if (intel_vgpu_has_monitor_on_port(vgpu, + port_idx) && + intel_vgpu_port_is_dp(vgpu, port_idx)) + i2c_edid->edid_available = true; + } + } + } else if ((op & 0x1) == GVT_AUX_I2C_WRITE) { + /* TODO + * We only support EDID reading from I2C_over_AUX. And + * we do not expect the index mode to be used. Right now + * the WRITE operation is ignored. It is good enough to + * support the gfx driver to do EDID access. + */ + } else { + if (WARN_ON((op & 0x1) != GVT_AUX_I2C_READ)) + return; + if (WARN_ON(msg_length != 4)) + return; + if (i2c_edid->edid_available && i2c_edid->slave_selected) { + unsigned char val = edid_get_byte(vgpu); + + aux_data_for_write = (val << 16); + } + } + /* write the return value in AUX_CH_DATA reg which includes: + * ACK of I2C_WRITE + * returned byte if it is READ + */ + + aux_data_for_write |= (GVT_AUX_I2C_REPLY_ACK & 0xff) << 24; + vgpu_vreg(vgpu, offset + 4) = aux_data_for_write; +} + +/** + * intel_vgpu_init_i2c_edid - initialize vGPU i2c edid emulation + * @vgpu: a vGPU + * + * This function is used to initialize vGPU i2c edid emulation stuffs + * + */ +void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu) +{ + struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid; + + edid->state = I2C_NOT_SPECIFIED; + + edid->port = -1; + edid->slave_selected = false; + edid->edid_available = false; + edid->current_edid_read = 0; + + memset(&edid->gmbus, 0, sizeof(struct intel_vgpu_i2c_gmbus)); + + edid->aux_ch.i2c_over_aux_ch = false; + edid->aux_ch.aux_ch_mot = false; +} diff --git a/drivers/gpu/drm/i915/gvt/edid.h b/drivers/gpu/drm/i915/gvt/edid.h new file mode 100644 index 000000000000..de366b1d5196 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/edid.h @@ -0,0 +1,150 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ke Yu + * Zhiyuan Lv + * + * Contributors: + * Terrence Xu + * Changbin Du + * Bing Niu + * Zhi Wang + * + */ + +#ifndef _GVT_EDID_H_ +#define _GVT_EDID_H_ + +#define EDID_SIZE 128 +#define EDID_ADDR 0x50 /* Linux hvm EDID addr */ + +#define GVT_AUX_NATIVE_WRITE 0x8 +#define GVT_AUX_NATIVE_READ 0x9 +#define GVT_AUX_I2C_WRITE 0x0 +#define GVT_AUX_I2C_READ 0x1 +#define GVT_AUX_I2C_STATUS 0x2 +#define GVT_AUX_I2C_MOT 0x4 +#define GVT_AUX_I2C_REPLY_ACK (0x0 << 6) + +struct intel_vgpu_edid_data { + bool data_valid; + unsigned char edid_block[EDID_SIZE]; +}; + +enum gmbus_cycle_type { + GMBUS_NOCYCLE = 0x0, + NIDX_NS_W = 0x1, + IDX_NS_W = 0x3, + GMBUS_STOP = 0x4, + NIDX_STOP = 0x5, + IDX_STOP = 0x7 +}; + +/* + * States of GMBUS + * + * GMBUS0-3 could be related to the EDID virtualization. Another two GMBUS + * registers, GMBUS4 (interrupt mask) and GMBUS5 (2 byte indes register), are + * not considered here. Below describes the usage of GMBUS registers that are + * cared by the EDID virtualization + * + * GMBUS0: + * R/W + * port selection. value of bit0 - bit2 corresponds to the GPIO registers. + * + * GMBUS1: + * R/W Protect + * Command and Status. + * bit0 is the direction bit: 1 is read; 0 is write. + * bit1 - bit7 is slave 7-bit address. + * bit16 - bit24 total byte count (ignore?) + * + * GMBUS2: + * Most of bits are read only except bit 15 (IN_USE) + * Status register + * bit0 - bit8 current byte count + * bit 11: hardware ready; + * + * GMBUS3: + * Read/Write + * Data for transfer + */ + +/* From hw specs, Other phases like START, ADDRESS, INDEX + * are invisible to GMBUS MMIO interface. So no definitions + * in below enum types + */ +enum gvt_gmbus_phase { + GMBUS_IDLE_PHASE = 0, + GMBUS_DATA_PHASE, + GMBUS_WAIT_PHASE, + //GMBUS_STOP_PHASE, + GMBUS_MAX_PHASE +}; + +struct intel_vgpu_i2c_gmbus { + unsigned int total_byte_count; /* from GMBUS1 */ + enum gmbus_cycle_type cycle_type; + enum gvt_gmbus_phase phase; +}; + +struct intel_vgpu_i2c_aux_ch { + bool i2c_over_aux_ch; + bool aux_ch_mot; +}; + +enum i2c_state { + I2C_NOT_SPECIFIED = 0, + I2C_GMBUS = 1, + I2C_AUX_CH = 2 +}; + +/* I2C sequences cannot interleave. + * GMBUS and AUX_CH sequences cannot interleave. + */ +struct intel_vgpu_i2c_edid { + enum i2c_state state; + + unsigned int port; + bool slave_selected; + bool edid_available; + unsigned int current_edid_read; + + struct intel_vgpu_i2c_gmbus gmbus; + struct intel_vgpu_i2c_aux_ch aux_ch; +}; + +void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu); + +int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes); + +int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes); + +void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu, + int port_idx, + unsigned int offset, + void *p_data); + +#endif /*_GVT_EDID_H_*/ diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 6b5061bfebb0..27e1dd9a2570 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -32,6 +32,7 @@ #include #include +#include #include "i915_drv.h" @@ -114,6 +115,52 @@ static void init_device_info(struct intel_gvt *gvt) } } +static int gvt_service_thread(void *data) +{ + struct intel_gvt *gvt = (struct intel_gvt *)data; + int ret; + + gvt_dbg_core("service thread start\n"); + + while (!kthread_should_stop()) { + ret = wait_event_interruptible(gvt->service_thread_wq, + kthread_should_stop() || gvt->service_request); + + if (kthread_should_stop()) + break; + + if (WARN_ONCE(ret, "service thread is waken up by signal.\n")) + continue; + + if (test_and_clear_bit(INTEL_GVT_REQUEST_EMULATE_VBLANK, + (void *)&gvt->service_request)) { + mutex_lock(&gvt->lock); + intel_gvt_emulate_vblank(gvt); + mutex_unlock(&gvt->lock); + } + } + + return 0; +} + +static void clean_service_thread(struct intel_gvt *gvt) +{ + kthread_stop(gvt->service_thread); +} + +static int init_service_thread(struct intel_gvt *gvt) +{ + init_waitqueue_head(&gvt->service_thread_wq); + + gvt->service_thread = kthread_run(gvt_service_thread, + gvt, "gvt_service_thread"); + if (IS_ERR(gvt->service_thread)) { + gvt_err("fail to start service thread.\n"); + return PTR_ERR(gvt->service_thread); + } + return 0; +} + /** * intel_gvt_clean_device - clean a GVT device * @gvt: intel gvt device @@ -129,6 +176,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) if (WARN_ON(!gvt->initialized)) return; + clean_service_thread(gvt); intel_gvt_clean_opregion(gvt); intel_gvt_clean_gtt(gvt); intel_gvt_clean_irq(gvt); @@ -191,10 +239,16 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (ret) goto out_clean_gtt; + ret = init_service_thread(gvt); + if (ret) + goto out_clean_opregion; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; +out_clean_opregion: + intel_gvt_clean_opregion(gvt); out_clean_gtt: intel_gvt_clean_gtt(gvt); out_clean_irq: diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 2560c3aaac45..1619881dbd51 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -39,6 +39,8 @@ #include "reg.h" #include "interrupt.h" #include "gtt.h" +#include "display.h" +#include "edid.h" #define GVT_MAX_VGPU 8 @@ -105,8 +107,12 @@ struct intel_vgpu_cfg_space { #define vgpu_cfg_space(vgpu) ((vgpu)->cfg_space.virtual_cfg_space) +#define INTEL_GVT_MAX_PIPE 4 + struct intel_vgpu_irq { bool irq_warn_once[INTEL_GVT_EVENT_MAX]; + DECLARE_BITMAP(flip_done_event[INTEL_GVT_MAX_PIPE], + INTEL_GVT_EVENT_MAX); }; struct intel_vgpu_opregion { @@ -117,6 +123,14 @@ struct intel_vgpu_opregion { #define vgpu_opregion(vgpu) (&(vgpu->opregion)) +#define INTEL_GVT_MAX_PORT 5 + +struct intel_vgpu_display { + struct intel_vgpu_i2c_edid i2c_edid; + struct intel_vgpu_port ports[INTEL_GVT_MAX_PORT]; + struct intel_vgpu_sbi sbi; +}; + struct intel_vgpu { struct intel_gvt *gvt; int id; @@ -131,6 +145,7 @@ struct intel_vgpu { struct intel_vgpu_irq irq; struct intel_vgpu_gtt gtt; struct intel_vgpu_opregion opregion; + struct intel_vgpu_display display; }; struct intel_gvt_gm { @@ -175,8 +190,23 @@ struct intel_gvt { struct intel_gvt_irq irq; struct intel_gvt_gtt gtt; struct intel_gvt_opregion opregion; + + struct task_struct *service_thread; + wait_queue_head_t service_thread_wq; + unsigned long service_request; }; +enum { + INTEL_GVT_REQUEST_EMULATE_VBLANK = 0, +}; + +static inline void intel_gvt_request_service(struct intel_gvt *gvt, + int service) +{ + set_bit(service, (void *)&gvt->service_request); + wake_up(&gvt->service_thread_wq); +} + void intel_gvt_free_firmware(struct intel_gvt *gvt); int intel_gvt_load_firmware(struct intel_gvt *gvt); diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index b29c3bfdc599..194778b374ff 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -251,6 +251,704 @@ static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, return 0; } +static int gmbus_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + return intel_gvt_i2c_handle_gmbus_read(vgpu, offset, p_data, bytes); +} + +static int gmbus_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + return intel_gvt_i2c_handle_gmbus_write(vgpu, offset, p_data, bytes); +} + +static int pch_pp_control_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + write_vreg(vgpu, offset, p_data, bytes); + + if (vgpu_vreg(vgpu, offset) & PANEL_POWER_ON) { + vgpu_vreg(vgpu, PCH_PP_STATUS) |= PP_ON; + vgpu_vreg(vgpu, PCH_PP_STATUS) |= PP_SEQUENCE_STATE_ON_IDLE; + vgpu_vreg(vgpu, PCH_PP_STATUS) &= ~PP_SEQUENCE_POWER_DOWN; + vgpu_vreg(vgpu, PCH_PP_STATUS) &= ~PP_CYCLE_DELAY_ACTIVE; + + } else + vgpu_vreg(vgpu, PCH_PP_STATUS) &= + ~(PP_ON | PP_SEQUENCE_POWER_DOWN + | PP_CYCLE_DELAY_ACTIVE); + return 0; +} + +static int transconf_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + write_vreg(vgpu, offset, p_data, bytes); + + if (vgpu_vreg(vgpu, offset) & TRANS_ENABLE) + vgpu_vreg(vgpu, offset) |= TRANS_STATE_ENABLE; + else + vgpu_vreg(vgpu, offset) &= ~TRANS_STATE_ENABLE; + return 0; +} + +static int lcpll_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + write_vreg(vgpu, offset, p_data, bytes); + + if (vgpu_vreg(vgpu, offset) & LCPLL_PLL_DISABLE) + vgpu_vreg(vgpu, offset) &= ~LCPLL_PLL_LOCK; + else + vgpu_vreg(vgpu, offset) |= LCPLL_PLL_LOCK; + + if (vgpu_vreg(vgpu, offset) & LCPLL_CD_SOURCE_FCLK) + vgpu_vreg(vgpu, offset) |= LCPLL_CD_SOURCE_FCLK_DONE; + else + vgpu_vreg(vgpu, offset) &= ~LCPLL_CD_SOURCE_FCLK_DONE; + + return 0; +} + +static int dpy_reg_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + *(u32 *)p_data = (1 << 17); + return 0; +} + +static int dpy_reg_mmio_read_2(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + *(u32 *)p_data = 3; + return 0; +} + +static int dpy_reg_mmio_read_3(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + *(u32 *)p_data = (0x2f << 16); + return 0; +} + +static int pipeconf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 data; + + write_vreg(vgpu, offset, p_data, bytes); + data = vgpu_vreg(vgpu, offset); + + if (data & PIPECONF_ENABLE) + vgpu_vreg(vgpu, offset) |= I965_PIPECONF_ACTIVE; + else + vgpu_vreg(vgpu, offset) &= ~I965_PIPECONF_ACTIVE; + intel_gvt_check_vblank_emulation(vgpu->gvt); + return 0; +} + +static int ddi_buf_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + write_vreg(vgpu, offset, p_data, bytes); + + if (vgpu_vreg(vgpu, offset) & DDI_BUF_CTL_ENABLE) { + vgpu_vreg(vgpu, offset) &= ~DDI_BUF_IS_IDLE; + } else { + vgpu_vreg(vgpu, offset) |= DDI_BUF_IS_IDLE; + if (offset == i915_mmio_reg_offset(DDI_BUF_CTL(PORT_E))) + vgpu_vreg(vgpu, DP_TP_STATUS(PORT_E)) + &= ~DP_TP_STATUS_AUTOTRAIN_DONE; + } + return 0; +} + +static int fdi_rx_iir_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + vgpu_vreg(vgpu, offset) &= ~*(u32 *)p_data; + return 0; +} + +#define FDI_LINK_TRAIN_PATTERN1 0 +#define FDI_LINK_TRAIN_PATTERN2 1 + +static int fdi_auto_training_started(struct intel_vgpu *vgpu) +{ + u32 ddi_buf_ctl = vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_E)); + u32 rx_ctl = vgpu_vreg(vgpu, _FDI_RXA_CTL); + u32 tx_ctl = vgpu_vreg(vgpu, DP_TP_CTL(PORT_E)); + + if ((ddi_buf_ctl & DDI_BUF_CTL_ENABLE) && + (rx_ctl & FDI_RX_ENABLE) && + (rx_ctl & FDI_AUTO_TRAINING) && + (tx_ctl & DP_TP_CTL_ENABLE) && + (tx_ctl & DP_TP_CTL_FDI_AUTOTRAIN)) + return 1; + else + return 0; +} + +static int check_fdi_rx_train_status(struct intel_vgpu *vgpu, + enum pipe pipe, unsigned int train_pattern) +{ + i915_reg_t fdi_rx_imr, fdi_tx_ctl, fdi_rx_ctl; + unsigned int fdi_rx_check_bits, fdi_tx_check_bits; + unsigned int fdi_rx_train_bits, fdi_tx_train_bits; + unsigned int fdi_iir_check_bits; + + fdi_rx_imr = FDI_RX_IMR(pipe); + fdi_tx_ctl = FDI_TX_CTL(pipe); + fdi_rx_ctl = FDI_RX_CTL(pipe); + + if (train_pattern == FDI_LINK_TRAIN_PATTERN1) { + fdi_rx_train_bits = FDI_LINK_TRAIN_PATTERN_1_CPT; + fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_1; + fdi_iir_check_bits = FDI_RX_BIT_LOCK; + } else if (train_pattern == FDI_LINK_TRAIN_PATTERN2) { + fdi_rx_train_bits = FDI_LINK_TRAIN_PATTERN_2_CPT; + fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_2; + fdi_iir_check_bits = FDI_RX_SYMBOL_LOCK; + } else { + gvt_err("Invalid train pattern %d\n", train_pattern); + return -EINVAL; + } + + fdi_rx_check_bits = FDI_RX_ENABLE | fdi_rx_train_bits; + fdi_tx_check_bits = FDI_TX_ENABLE | fdi_tx_train_bits; + + /* If imr bit has been masked */ + if (vgpu_vreg(vgpu, fdi_rx_imr) & fdi_iir_check_bits) + return 0; + + if (((vgpu_vreg(vgpu, fdi_tx_ctl) & fdi_tx_check_bits) + == fdi_tx_check_bits) + && ((vgpu_vreg(vgpu, fdi_rx_ctl) & fdi_rx_check_bits) + == fdi_rx_check_bits)) + return 1; + else + return 0; +} + +#define INVALID_INDEX (~0U) + +static unsigned int calc_index(unsigned int offset, unsigned int start, + unsigned int next, unsigned int end, i915_reg_t i915_end) +{ + unsigned int range = next - start; + + if (!end) + end = i915_mmio_reg_offset(i915_end); + if (offset < start || offset > end) + return INVALID_INDEX; + offset -= start; + return offset / range; +} + +#define FDI_RX_CTL_TO_PIPE(offset) \ + calc_index(offset, _FDI_RXA_CTL, _FDI_RXB_CTL, 0, FDI_RX_CTL(PIPE_C)) + +#define FDI_TX_CTL_TO_PIPE(offset) \ + calc_index(offset, _FDI_TXA_CTL, _FDI_TXB_CTL, 0, FDI_TX_CTL(PIPE_C)) + +#define FDI_RX_IMR_TO_PIPE(offset) \ + calc_index(offset, _FDI_RXA_IMR, _FDI_RXB_IMR, 0, FDI_RX_IMR(PIPE_C)) + +static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + i915_reg_t fdi_rx_iir; + unsigned int index; + int ret; + + if (FDI_RX_CTL_TO_PIPE(offset) != INVALID_INDEX) + index = FDI_RX_CTL_TO_PIPE(offset); + else if (FDI_TX_CTL_TO_PIPE(offset) != INVALID_INDEX) + index = FDI_TX_CTL_TO_PIPE(offset); + else if (FDI_RX_IMR_TO_PIPE(offset) != INVALID_INDEX) + index = FDI_RX_IMR_TO_PIPE(offset); + else { + gvt_err("Unsupport registers %x\n", offset); + return -EINVAL; + } + + write_vreg(vgpu, offset, p_data, bytes); + + fdi_rx_iir = FDI_RX_IIR(index); + + ret = check_fdi_rx_train_status(vgpu, index, FDI_LINK_TRAIN_PATTERN1); + if (ret < 0) + return ret; + if (ret) + vgpu_vreg(vgpu, fdi_rx_iir) |= FDI_RX_BIT_LOCK; + + ret = check_fdi_rx_train_status(vgpu, index, FDI_LINK_TRAIN_PATTERN2); + if (ret < 0) + return ret; + if (ret) + vgpu_vreg(vgpu, fdi_rx_iir) |= FDI_RX_SYMBOL_LOCK; + + if (offset == _FDI_RXA_CTL) + if (fdi_auto_training_started(vgpu)) + vgpu_vreg(vgpu, DP_TP_STATUS(PORT_E)) |= + DP_TP_STATUS_AUTOTRAIN_DONE; + return 0; +} + +#define DP_TP_CTL_TO_PORT(offset) \ + calc_index(offset, _DP_TP_CTL_A, _DP_TP_CTL_B, 0, DP_TP_CTL(PORT_E)) + +static int dp_tp_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + i915_reg_t status_reg; + unsigned int index; + u32 data; + + write_vreg(vgpu, offset, p_data, bytes); + + index = DP_TP_CTL_TO_PORT(offset); + data = (vgpu_vreg(vgpu, offset) & GENMASK(10, 8)) >> 8; + if (data == 0x2) { + status_reg = DP_TP_STATUS(index); + vgpu_vreg(vgpu, status_reg) |= (1 << 25); + } + return 0; +} + +static int dp_tp_status_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + u32 reg_val; + u32 sticky_mask; + + reg_val = *((u32 *)p_data); + sticky_mask = GENMASK(27, 26) | (1 << 24); + + vgpu_vreg(vgpu, offset) = (reg_val & ~sticky_mask) | + (vgpu_vreg(vgpu, offset) & sticky_mask); + vgpu_vreg(vgpu, offset) &= ~(reg_val & sticky_mask); + return 0; +} + +static int pch_adpa_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + u32 data; + + write_vreg(vgpu, offset, p_data, bytes); + data = vgpu_vreg(vgpu, offset); + + if (data & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) + vgpu_vreg(vgpu, offset) &= ~ADPA_CRT_HOTPLUG_FORCE_TRIGGER; + return 0; +} + +static int south_chicken2_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + u32 data; + + write_vreg(vgpu, offset, p_data, bytes); + data = vgpu_vreg(vgpu, offset); + + if (data & FDI_MPHY_IOSFSB_RESET_CTL) + vgpu_vreg(vgpu, offset) |= FDI_MPHY_IOSFSB_RESET_STATUS; + else + vgpu_vreg(vgpu, offset) &= ~FDI_MPHY_IOSFSB_RESET_STATUS; + return 0; +} + +#define DSPSURF_TO_PIPE(offset) \ + calc_index(offset, _DSPASURF, _DSPBSURF, 0, DSPSURF(PIPE_C)) + +static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + unsigned int index = DSPSURF_TO_PIPE(offset); + i915_reg_t surflive_reg = DSPSURFLIVE(index); + int flip_event[] = { + [PIPE_A] = PRIMARY_A_FLIP_DONE, + [PIPE_B] = PRIMARY_B_FLIP_DONE, + [PIPE_C] = PRIMARY_C_FLIP_DONE, + }; + + write_vreg(vgpu, offset, p_data, bytes); + vgpu_vreg(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset); + + set_bit(flip_event[index], vgpu->irq.flip_done_event[index]); + return 0; +} + +#define SPRSURF_TO_PIPE(offset) \ + calc_index(offset, _SPRA_SURF, _SPRB_SURF, 0, SPRSURF(PIPE_C)) + +static int spr_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + unsigned int index = SPRSURF_TO_PIPE(offset); + i915_reg_t surflive_reg = SPRSURFLIVE(index); + int flip_event[] = { + [PIPE_A] = SPRITE_A_FLIP_DONE, + [PIPE_B] = SPRITE_B_FLIP_DONE, + [PIPE_C] = SPRITE_C_FLIP_DONE, + }; + + write_vreg(vgpu, offset, p_data, bytes); + vgpu_vreg(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset); + + set_bit(flip_event[index], vgpu->irq.flip_done_event[index]); + return 0; +} + +static int trigger_aux_channel_interrupt(struct intel_vgpu *vgpu, + unsigned int reg) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + enum intel_gvt_event_type event; + + if (reg == _DPA_AUX_CH_CTL) + event = AUX_CHANNEL_A; + else if (reg == _PCH_DPB_AUX_CH_CTL || reg == _DPB_AUX_CH_CTL) + event = AUX_CHANNEL_B; + else if (reg == _PCH_DPC_AUX_CH_CTL || reg == _DPC_AUX_CH_CTL) + event = AUX_CHANNEL_C; + else if (reg == _PCH_DPD_AUX_CH_CTL || reg == _DPD_AUX_CH_CTL) + event = AUX_CHANNEL_D; + else { + WARN_ON(true); + return -EINVAL; + } + + intel_vgpu_trigger_virtual_event(vgpu, event); + return 0; +} + +static int dp_aux_ch_ctl_trans_done(struct intel_vgpu *vgpu, u32 value, + unsigned int reg, int len, bool data_valid) +{ + /* mark transaction done */ + value |= DP_AUX_CH_CTL_DONE; + value &= ~DP_AUX_CH_CTL_SEND_BUSY; + value &= ~DP_AUX_CH_CTL_RECEIVE_ERROR; + + if (data_valid) + value &= ~DP_AUX_CH_CTL_TIME_OUT_ERROR; + else + value |= DP_AUX_CH_CTL_TIME_OUT_ERROR; + + /* message size */ + value &= ~(0xf << 20); + value |= (len << 20); + vgpu_vreg(vgpu, reg) = value; + + if (value & DP_AUX_CH_CTL_INTERRUPT) + return trigger_aux_channel_interrupt(vgpu, reg); + return 0; +} + +static void dp_aux_ch_ctl_link_training(struct intel_vgpu_dpcd_data *dpcd, + uint8_t t) +{ + if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == DPCD_TRAINING_PATTERN_1) { + /* training pattern 1 for CR */ + /* set LANE0_CR_DONE, LANE1_CR_DONE */ + dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_CR_DONE; + /* set LANE2_CR_DONE, LANE3_CR_DONE */ + dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_CR_DONE; + } else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == + DPCD_TRAINING_PATTERN_2) { + /* training pattern 2 for EQ */ + /* Set CHANNEL_EQ_DONE and SYMBOL_LOCKED for Lane0_1 */ + dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_EQ_DONE; + dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_SYMBOL_LOCKED; + /* Set CHANNEL_EQ_DONE and SYMBOL_LOCKED for Lane2_3 */ + dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_EQ_DONE; + dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_SYMBOL_LOCKED; + /* set INTERLANE_ALIGN_DONE */ + dpcd->data[DPCD_LANE_ALIGN_STATUS_UPDATED] |= + DPCD_INTERLANE_ALIGN_DONE; + } else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == + DPCD_LINK_TRAINING_DISABLED) { + /* finish link training */ + /* set sink status as synchronized */ + dpcd->data[DPCD_SINK_STATUS] = DPCD_SINK_IN_SYNC; + } +} + +#define _REG_HSW_DP_AUX_CH_CTL(dp) \ + ((dp) ? (_PCH_DPB_AUX_CH_CTL + ((dp)-1)*0x100) : 0x64010) + +#define _REG_SKL_DP_AUX_CH_CTL(dp) (0x64010 + (dp) * 0x100) + +#define OFFSET_TO_DP_AUX_PORT(offset) (((offset) & 0xF00) >> 8) + +#define dpy_is_valid_port(port) \ + (((port) >= PORT_A) && ((port) < I915_MAX_PORTS)) + +static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + struct intel_vgpu_display *display = &vgpu->display; + int msg, addr, ctrl, op, len; + int port_index = OFFSET_TO_DP_AUX_PORT(offset); + struct intel_vgpu_dpcd_data *dpcd = NULL; + struct intel_vgpu_port *port = NULL; + u32 data; + + if (!dpy_is_valid_port(port_index)) { + gvt_err("GVT(%d): Unsupported DP port access!\n", vgpu->id); + return 0; + } + + write_vreg(vgpu, offset, p_data, bytes); + data = vgpu_vreg(vgpu, offset); + + if (IS_SKYLAKE(vgpu->gvt->dev_priv) && + offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) { + /* SKL DPB/C/D aux ctl register changed */ + return 0; + } else if (IS_BROADWELL(vgpu->gvt->dev_priv) && + offset != _REG_HSW_DP_AUX_CH_CTL(port_index)) { + /* write to the data registers */ + return 0; + } + + if (!(data & DP_AUX_CH_CTL_SEND_BUSY)) { + /* just want to clear the sticky bits */ + vgpu_vreg(vgpu, offset) = 0; + return 0; + } + + port = &display->ports[port_index]; + dpcd = port->dpcd; + + /* read out message from DATA1 register */ + msg = vgpu_vreg(vgpu, offset + 4); + addr = (msg >> 8) & 0xffff; + ctrl = (msg >> 24) & 0xff; + len = msg & 0xff; + op = ctrl >> 4; + + if (op == GVT_AUX_NATIVE_WRITE) { + int t; + uint8_t buf[16]; + + if ((addr + len + 1) >= DPCD_SIZE) { + /* + * Write request exceeds what we supported, + * DCPD spec: When a Source Device is writing a DPCD + * address not supported by the Sink Device, the Sink + * Device shall reply with AUX NACK and “M” equal to + * zero. + */ + + /* NAK the write */ + vgpu_vreg(vgpu, offset + 4) = AUX_NATIVE_REPLY_NAK; + dp_aux_ch_ctl_trans_done(vgpu, data, offset, 2, true); + return 0; + } + + /* + * Write request format: (command + address) occupies + * 3 bytes, followed by (len + 1) bytes of data. + */ + if (WARN_ON((len + 4) > AUX_BURST_SIZE)) + return -EINVAL; + + /* unpack data from vreg to buf */ + for (t = 0; t < 4; t++) { + u32 r = vgpu_vreg(vgpu, offset + 8 + t * 4); + + buf[t * 4] = (r >> 24) & 0xff; + buf[t * 4 + 1] = (r >> 16) & 0xff; + buf[t * 4 + 2] = (r >> 8) & 0xff; + buf[t * 4 + 3] = r & 0xff; + } + + /* write to virtual DPCD */ + if (dpcd && dpcd->data_valid) { + for (t = 0; t <= len; t++) { + int p = addr + t; + + dpcd->data[p] = buf[t]; + /* check for link training */ + if (p == DPCD_TRAINING_PATTERN_SET) + dp_aux_ch_ctl_link_training(dpcd, + buf[t]); + } + } + + /* ACK the write */ + vgpu_vreg(vgpu, offset + 4) = 0; + dp_aux_ch_ctl_trans_done(vgpu, data, offset, 1, + dpcd && dpcd->data_valid); + return 0; + } + + if (op == GVT_AUX_NATIVE_READ) { + int idx, i, ret = 0; + + if ((addr + len + 1) >= DPCD_SIZE) { + /* + * read request exceeds what we supported + * DPCD spec: A Sink Device receiving a Native AUX CH + * read request for an unsupported DPCD address must + * reply with an AUX ACK and read data set equal to + * zero instead of replying with AUX NACK. + */ + + /* ACK the READ*/ + vgpu_vreg(vgpu, offset + 4) = 0; + vgpu_vreg(vgpu, offset + 8) = 0; + vgpu_vreg(vgpu, offset + 12) = 0; + vgpu_vreg(vgpu, offset + 16) = 0; + vgpu_vreg(vgpu, offset + 20) = 0; + + dp_aux_ch_ctl_trans_done(vgpu, data, offset, len + 2, + true); + return 0; + } + + for (idx = 1; idx <= 5; idx++) { + /* clear the data registers */ + vgpu_vreg(vgpu, offset + 4 * idx) = 0; + } + + /* + * Read reply format: ACK (1 byte) plus (len + 1) bytes of data. + */ + if (WARN_ON((len + 2) > AUX_BURST_SIZE)) + return -EINVAL; + + /* read from virtual DPCD to vreg */ + /* first 4 bytes: [ACK][addr][addr+1][addr+2] */ + if (dpcd && dpcd->data_valid) { + for (i = 1; i <= (len + 1); i++) { + int t; + + t = dpcd->data[addr + i - 1]; + t <<= (24 - 8 * (i % 4)); + ret |= t; + + if ((i % 4 == 3) || (i == (len + 1))) { + vgpu_vreg(vgpu, offset + + (i / 4 + 1) * 4) = ret; + ret = 0; + } + } + } + dp_aux_ch_ctl_trans_done(vgpu, data, offset, len + 2, + dpcd && dpcd->data_valid); + return 0; + } + + /* i2c transaction starts */ + intel_gvt_i2c_handle_aux_ch_write(vgpu, port_index, offset, p_data); + + if (data & DP_AUX_CH_CTL_INTERRUPT) + trigger_aux_channel_interrupt(vgpu, offset); + return 0; +} + +static int vga_control_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + bool vga_disable; + + write_vreg(vgpu, offset, p_data, bytes); + vga_disable = vgpu_vreg(vgpu, offset) & VGA_DISP_DISABLE; + + gvt_dbg_core("vgpu%d: %s VGA mode\n", vgpu->id, + vga_disable ? "Disable" : "Enable"); + return 0; +} + +static u32 read_virtual_sbi_register(struct intel_vgpu *vgpu, + unsigned int sbi_offset) +{ + struct intel_vgpu_display *display = &vgpu->display; + int num = display->sbi.number; + int i; + + for (i = 0; i < num; ++i) + if (display->sbi.registers[i].offset == sbi_offset) + break; + + if (i == num) + return 0; + + return display->sbi.registers[i].value; +} + +static void write_virtual_sbi_register(struct intel_vgpu *vgpu, + unsigned int offset, u32 value) +{ + struct intel_vgpu_display *display = &vgpu->display; + int num = display->sbi.number; + int i; + + for (i = 0; i < num; ++i) { + if (display->sbi.registers[i].offset == offset) + break; + } + + if (i == num) { + if (num == SBI_REG_MAX) { + gvt_err("vgpu%d: SBI caching meets maximum limits\n", + vgpu->id); + return; + } + display->sbi.number++; + } + + display->sbi.registers[i].offset = offset; + display->sbi.registers[i].value = value; +} + +static int sbi_data_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + if (((vgpu_vreg(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >> + SBI_OPCODE_SHIFT) == SBI_CMD_CRRD) { + unsigned int sbi_offset = (vgpu_vreg(vgpu, SBI_ADDR) & + SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT; + vgpu_vreg(vgpu, offset) = read_virtual_sbi_register(vgpu, + sbi_offset); + } + read_vreg(vgpu, offset, p_data, bytes); + return 0; +} + +static bool sbi_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 data; + + write_vreg(vgpu, offset, p_data, bytes); + data = vgpu_vreg(vgpu, offset); + + data &= ~(SBI_STAT_MASK << SBI_STAT_SHIFT); + data |= SBI_READY; + + data &= ~(SBI_RESPONSE_MASK << SBI_RESPONSE_SHIFT); + data |= SBI_RESPONSE_SUCCESS; + + vgpu_vreg(vgpu, offset) = data; + + if (((vgpu_vreg(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >> + SBI_OPCODE_SHIFT) == SBI_CMD_CRWR) { + unsigned int sbi_offset = (vgpu_vreg(vgpu, SBI_ADDR) & + SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT; + + write_virtual_sbi_register(vgpu, sbi_offset, + vgpu_vreg(vgpu, SBI_DATA)); + } + return 0; +} + #define _vgtif_reg(x) \ (VGT_PVINFO_PAGE + offsetof(struct vgt_if, x)) @@ -312,6 +1010,23 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) return ret; } +static int send_display_ready_uevent(struct intel_vgpu *vgpu, int ready) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj; + char *env[3] = {NULL, NULL, NULL}; + char vmid_str[20]; + char display_ready_str[20]; + + snprintf(display_ready_str, 20, "GVT_DISPLAY_READY=%d\n", ready); + env[0] = display_ready_str; + + snprintf(vmid_str, 20, "VMID=%d", vgpu->id); + env[1] = vmid_str; + + return kobject_uevent_env(kobj, KOBJ_ADD, env); +} + static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { @@ -323,6 +1038,8 @@ static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, switch (offset) { case _vgtif_reg(display_ready): + send_display_ready_uevent(vgpu, data ? 1 : 0); + break; case _vgtif_reg(g2v_notify): ret = handle_g2v_notification(vgpu, data); break; @@ -348,6 +1065,34 @@ static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, return 0; } +static int pf_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + u32 val = *(u32 *)p_data; + + if ((offset == _PS_1A_CTRL || offset == _PS_2A_CTRL || + offset == _PS_1B_CTRL || offset == _PS_2B_CTRL || + offset == _PS_1C_CTRL) && (val & PS_PLANE_SEL_MASK) != 0) { + WARN_ONCE(true, "VM(%d): guest is trying to scaling a plane\n", + vgpu->id); + return 0; + } + + return intel_vgpu_default_mmio_write(vgpu, offset, p_data, bytes); +} + +static int power_well_ctl_mmio_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + write_vreg(vgpu, offset, p_data, bytes); + + if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_ENABLE_REQUEST) + vgpu_vreg(vgpu, offset) |= HSW_PWR_WELL_STATE_ENABLED; + else + vgpu_vreg(vgpu, offset) &= ~HSW_PWR_WELL_STATE_ENABLED; + return 0; +} + static int fpga_dbg_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { @@ -404,6 +1149,119 @@ static int gen9_trtt_chicken_write(struct intel_vgpu *vgpu, unsigned int offset, return 0; } +static int dpll_status_read(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 v = 0; + + if (vgpu_vreg(vgpu, 0x46010) & (1 << 31)) + v |= (1 << 0); + + if (vgpu_vreg(vgpu, 0x46014) & (1 << 31)) + v |= (1 << 8); + + if (vgpu_vreg(vgpu, 0x46040) & (1 << 31)) + v |= (1 << 16); + + if (vgpu_vreg(vgpu, 0x46060) & (1 << 31)) + v |= (1 << 24); + + vgpu_vreg(vgpu, offset) = v; + + return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); +} + +static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 value = *(u32 *)p_data; + u32 cmd = value & 0xff; + u32 *data0 = &vgpu_vreg(vgpu, GEN6_PCODE_DATA); + + switch (cmd) { + case 0x6: + /** + * "Read memory latency" command on gen9. + * Below memory latency values are read + * from skylake platform. + */ + if (!*data0) + *data0 = 0x1e1a1100; + else + *data0 = 0x61514b3d; + break; + case 0x5: + *data0 |= 0x1; + break; + } + + gvt_dbg_core("VM(%d) write %x to mailbox, return data0 %x\n", + vgpu->id, value, *data0); + + value &= ~(1 << 31); + return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes); +} + +static int skl_power_well_ctl_write(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + u32 v = *(u32 *)p_data; + + v &= (1 << 31) | (1 << 29) | (1 << 9) | + (1 << 7) | (1 << 5) | (1 << 3) | (1 << 1); + v |= (v >> 1); + + return intel_vgpu_default_mmio_write(vgpu, offset, &v, bytes); +} + +static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + i915_reg_t reg = {.reg = offset}; + + switch (offset) { + case 0x4ddc: + vgpu_vreg(vgpu, offset) = 0x8000003c; + break; + case 0x42080: + vgpu_vreg(vgpu, offset) = 0x8000; + break; + default: + return -EINVAL; + } + + /** + * TODO: need detect stepping info after gvt contain such information + * 0x4ddc enabled after C0, 0x42080 enabled after E0. + */ + I915_WRITE(reg, vgpu_vreg(vgpu, offset)); + return 0; +} + +static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 v = *(u32 *)p_data; + + /* other bits are MBZ. */ + v &= (1 << 31) | (1 << 30); + v & (1 << 31) ? (v |= (1 << 30)) : (v &= ~(1 << 30)); + + vgpu_vreg(vgpu, offset) = v; + + return 0; +} + +static int ring_timestamp_mmio_read(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + + vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset)); + return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); +} + #define MMIO_F(reg, s, f, am, rm, d, r, w) do { \ ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \ f, s, am, rm, d, r, w); \ @@ -490,8 +1348,10 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK, NULL, NULL); MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK, NULL, NULL); - MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS, NULL, NULL); - MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS, NULL, NULL); + MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS, + ring_timestamp_mmio_read, NULL); + MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS, + ring_timestamp_mmio_read, NULL); MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK, NULL, NULL); MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK, NULL, NULL); @@ -531,10 +1391,10 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(PIPEDSL(PIPE_C), D_ALL); MMIO_D(PIPEDSL(_PIPE_EDP), D_ALL); - MMIO_DH(PIPECONF(PIPE_A), D_ALL, NULL, NULL); - MMIO_DH(PIPECONF(PIPE_B), D_ALL, NULL, NULL); - MMIO_DH(PIPECONF(PIPE_C), D_ALL, NULL, NULL); - MMIO_DH(PIPECONF(_PIPE_EDP), D_ALL, NULL, NULL); + MMIO_DH(PIPECONF(PIPE_A), D_ALL, NULL, pipeconf_mmio_write); + MMIO_DH(PIPECONF(PIPE_B), D_ALL, NULL, pipeconf_mmio_write); + MMIO_DH(PIPECONF(PIPE_C), D_ALL, NULL, pipeconf_mmio_write); + MMIO_DH(PIPECONF(_PIPE_EDP), D_ALL, NULL, pipeconf_mmio_write); MMIO_D(PIPESTAT(PIPE_A), D_ALL); MMIO_D(PIPESTAT(PIPE_B), D_ALL); @@ -577,7 +1437,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(DSPSTRIDE(PIPE_A), D_ALL); MMIO_D(DSPPOS(PIPE_A), D_ALL); MMIO_D(DSPSIZE(PIPE_A), D_ALL); - MMIO_D(DSPSURF(PIPE_A), D_ALL); + MMIO_DH(DSPSURF(PIPE_A), D_ALL, NULL, pri_surf_mmio_write); MMIO_D(DSPOFFSET(PIPE_A), D_ALL); MMIO_D(DSPSURFLIVE(PIPE_A), D_ALL); @@ -586,7 +1446,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(DSPSTRIDE(PIPE_B), D_ALL); MMIO_D(DSPPOS(PIPE_B), D_ALL); MMIO_D(DSPSIZE(PIPE_B), D_ALL); - MMIO_D(DSPSURF(PIPE_B), D_ALL); + MMIO_DH(DSPSURF(PIPE_B), D_ALL, NULL, pri_surf_mmio_write); MMIO_D(DSPOFFSET(PIPE_B), D_ALL); MMIO_D(DSPSURFLIVE(PIPE_B), D_ALL); @@ -595,7 +1455,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(DSPSTRIDE(PIPE_C), D_ALL); MMIO_D(DSPPOS(PIPE_C), D_ALL); MMIO_D(DSPSIZE(PIPE_C), D_ALL); - MMIO_D(DSPSURF(PIPE_C), D_ALL); + MMIO_DH(DSPSURF(PIPE_C), D_ALL, NULL, pri_surf_mmio_write); MMIO_D(DSPOFFSET(PIPE_C), D_ALL); MMIO_D(DSPSURFLIVE(PIPE_C), D_ALL); @@ -606,7 +1466,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(SPRSIZE(PIPE_A), D_ALL); MMIO_D(SPRKEYVAL(PIPE_A), D_ALL); MMIO_D(SPRKEYMSK(PIPE_A), D_ALL); - MMIO_D(SPRSURF(PIPE_A), D_ALL); + MMIO_DH(SPRSURF(PIPE_A), D_ALL, NULL, spr_surf_mmio_write); MMIO_D(SPRKEYMAX(PIPE_A), D_ALL); MMIO_D(SPROFFSET(PIPE_A), D_ALL); MMIO_D(SPRSCALE(PIPE_A), D_ALL); @@ -619,7 +1479,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(SPRSIZE(PIPE_B), D_ALL); MMIO_D(SPRKEYVAL(PIPE_B), D_ALL); MMIO_D(SPRKEYMSK(PIPE_B), D_ALL); - MMIO_D(SPRSURF(PIPE_B), D_ALL); + MMIO_DH(SPRSURF(PIPE_B), D_ALL, NULL, spr_surf_mmio_write); MMIO_D(SPRKEYMAX(PIPE_B), D_ALL); MMIO_D(SPROFFSET(PIPE_B), D_ALL); MMIO_D(SPRSCALE(PIPE_B), D_ALL); @@ -632,7 +1492,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(SPRSIZE(PIPE_C), D_ALL); MMIO_D(SPRKEYVAL(PIPE_C), D_ALL); MMIO_D(SPRKEYMSK(PIPE_C), D_ALL); - MMIO_D(SPRSURF(PIPE_C), D_ALL); + MMIO_DH(SPRSURF(PIPE_C), D_ALL, NULL, spr_surf_mmio_write); MMIO_D(SPRKEYMAX(PIPE_C), D_ALL); MMIO_D(SPROFFSET(PIPE_C), D_ALL); MMIO_D(SPRSCALE(PIPE_C), D_ALL); @@ -752,29 +1612,32 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(0x48268, D_ALL); - MMIO_F(PCH_GMBUS0, 4 * 4, 0, 0, 0, D_ALL, NULL, NULL); - MMIO_F(PCH_GPIOA, 6 * 4, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_F(PCH_GMBUS0, 4 * 4, 0, 0, 0, D_ALL, gmbus_mmio_read, + gmbus_mmio_write); + MMIO_F(PCH_GPIOA, 6 * 4, F_UNALIGN, 0, 0, D_ALL, NULL, NULL); MMIO_F(0xe4f00, 0x28, 0, 0, 0, D_ALL, NULL, NULL); - MMIO_F(_PCH_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, NULL); - MMIO_F(_PCH_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, NULL); - MMIO_F(_PCH_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, NULL); + MMIO_F(_PCH_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, + dp_aux_ch_ctl_mmio_write); + MMIO_F(_PCH_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, + dp_aux_ch_ctl_mmio_write); + MMIO_F(_PCH_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, + dp_aux_ch_ctl_mmio_write); - MMIO_RO(PCH_ADPA, D_ALL, 0, - ADPA_CRT_HOTPLUG_MONITOR_MASK, NULL, NULL); + MMIO_RO(PCH_ADPA, D_ALL, 0, ADPA_CRT_HOTPLUG_MONITOR_MASK, NULL, pch_adpa_mmio_write); - MMIO_DH(_PCH_TRANSACONF, D_ALL, NULL, NULL); - MMIO_DH(_PCH_TRANSBCONF, D_ALL, NULL, NULL); + MMIO_DH(_PCH_TRANSACONF, D_ALL, NULL, transconf_mmio_write); + MMIO_DH(_PCH_TRANSBCONF, D_ALL, NULL, transconf_mmio_write); - MMIO_DH(FDI_RX_IIR(PIPE_A), D_ALL, NULL, NULL); - MMIO_DH(FDI_RX_IIR(PIPE_B), D_ALL, NULL, NULL); - MMIO_DH(FDI_RX_IIR(PIPE_C), D_ALL, NULL, NULL); - MMIO_DH(FDI_RX_IMR(PIPE_A), D_ALL, NULL, NULL); - MMIO_DH(FDI_RX_IMR(PIPE_B), D_ALL, NULL, NULL); - MMIO_DH(FDI_RX_IMR(PIPE_C), D_ALL, NULL, NULL); - MMIO_DH(FDI_RX_CTL(PIPE_A), D_ALL, NULL, NULL); - MMIO_DH(FDI_RX_CTL(PIPE_B), D_ALL, NULL, NULL); - MMIO_DH(FDI_RX_CTL(PIPE_C), D_ALL, NULL, NULL); + MMIO_DH(FDI_RX_IIR(PIPE_A), D_ALL, NULL, fdi_rx_iir_mmio_write); + MMIO_DH(FDI_RX_IIR(PIPE_B), D_ALL, NULL, fdi_rx_iir_mmio_write); + MMIO_DH(FDI_RX_IIR(PIPE_C), D_ALL, NULL, fdi_rx_iir_mmio_write); + MMIO_DH(FDI_RX_IMR(PIPE_A), D_ALL, NULL, update_fdi_rx_iir_status); + MMIO_DH(FDI_RX_IMR(PIPE_B), D_ALL, NULL, update_fdi_rx_iir_status); + MMIO_DH(FDI_RX_IMR(PIPE_C), D_ALL, NULL, update_fdi_rx_iir_status); + MMIO_DH(FDI_RX_CTL(PIPE_A), D_ALL, NULL, update_fdi_rx_iir_status); + MMIO_DH(FDI_RX_CTL(PIPE_B), D_ALL, NULL, update_fdi_rx_iir_status); + MMIO_DH(FDI_RX_CTL(PIPE_C), D_ALL, NULL, update_fdi_rx_iir_status); MMIO_D(_PCH_TRANS_HTOTAL_A, D_ALL); MMIO_D(_PCH_TRANS_HBLANK_A, D_ALL); @@ -824,7 +1687,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(_FDI_RXB_TUSIZE1, D_ALL); MMIO_D(_FDI_RXB_TUSIZE2, D_ALL); - MMIO_DH(PCH_PP_CONTROL, D_ALL, NULL, NULL); + MMIO_DH(PCH_PP_CONTROL, D_ALL, NULL, pch_pp_control_mmio_write); MMIO_D(PCH_PP_DIVISOR, D_ALL); MMIO_D(PCH_PP_STATUS, D_ALL); MMIO_D(PCH_LVDS, D_ALL); @@ -843,12 +1706,12 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(PCH_PP_ON_DELAYS, D_ALL); MMIO_D(PCH_PP_OFF_DELAYS, D_ALL); - MMIO_DH(0xe651c, D_ALL, NULL, NULL); - MMIO_DH(0xe661c, D_ALL, NULL, NULL); - MMIO_DH(0xe671c, D_ALL, NULL, NULL); - MMIO_DH(0xe681c, D_ALL, NULL, NULL); - MMIO_DH(0xe6c04, D_ALL, NULL, NULL); - MMIO_DH(0xe6e1c, D_ALL, NULL, NULL); + MMIO_DH(0xe651c, D_ALL, dpy_reg_mmio_read, NULL); + MMIO_DH(0xe661c, D_ALL, dpy_reg_mmio_read, NULL); + MMIO_DH(0xe671c, D_ALL, dpy_reg_mmio_read, NULL); + MMIO_DH(0xe681c, D_ALL, dpy_reg_mmio_read, NULL); + MMIO_DH(0xe6c04, D_ALL, dpy_reg_mmio_read_2, NULL); + MMIO_DH(0xe6e1c, D_ALL, dpy_reg_mmio_read_3, NULL); MMIO_RO(PCH_PORT_HOTPLUG, D_ALL, 0, PORTA_HOTPLUG_STATUS_MASK @@ -857,7 +1720,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) | PORTD_HOTPLUG_STATUS_MASK, NULL, NULL); - MMIO_DH(LCPLL_CTL, D_ALL, NULL, NULL); + MMIO_DH(LCPLL_CTL, D_ALL, NULL, lcpll_ctl_mmio_write); MMIO_D(FUSE_STRAP, D_ALL); MMIO_D(DIGITAL_PORT_HOTPLUG_CNTRL, D_ALL); @@ -869,7 +1732,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(ILK_DSPCLK_GATE_D, D_ALL); MMIO_D(SOUTH_CHICKEN1, D_ALL); - MMIO_DH(SOUTH_CHICKEN2, D_ALL, NULL, NULL); + MMIO_DH(SOUTH_CHICKEN2, D_ALL, NULL, south_chicken2_mmio_write); MMIO_D(_TRANSA_CHICKEN1, D_ALL); MMIO_D(_TRANSB_CHICKEN1, D_ALL); MMIO_D(SOUTH_DSPCLK_GATE_D, D_ALL); @@ -928,6 +1791,18 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_C), D_ALL); MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_C), D_ALL); + MMIO_D(PREC_PAL_INDEX(PIPE_A), D_ALL); + MMIO_D(PREC_PAL_DATA(PIPE_A), D_ALL); + MMIO_F(PREC_PAL_GC_MAX(PIPE_A, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_D(PREC_PAL_INDEX(PIPE_B), D_ALL); + MMIO_D(PREC_PAL_DATA(PIPE_B), D_ALL); + MMIO_F(PREC_PAL_GC_MAX(PIPE_B, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL); + + MMIO_D(PREC_PAL_INDEX(PIPE_C), D_ALL); + MMIO_D(PREC_PAL_DATA(PIPE_C), D_ALL); + MMIO_F(PREC_PAL_GC_MAX(PIPE_C, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL); + MMIO_D(0x60110, D_ALL); MMIO_D(0x61110, D_ALL); MMIO_F(0x70400, 0x40, 0, 0, 0, D_ALL, NULL, NULL); @@ -970,10 +1845,6 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(GAMMA_MODE(PIPE_B), D_ALL); MMIO_D(GAMMA_MODE(PIPE_C), D_ALL); - MMIO_D(0x4a400, D_ALL); - MMIO_D(0x4ac00, D_ALL); - MMIO_D(0x4b400, D_ALL); - MMIO_D(PIPE_MULT(PIPE_A), D_ALL); MMIO_D(PIPE_MULT(PIPE_B), D_ALL); MMIO_D(PIPE_MULT(PIPE_C), D_ALL); @@ -984,39 +1855,30 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_DH(SFUSE_STRAP, D_ALL, NULL, NULL); MMIO_D(SBI_ADDR, D_ALL); - MMIO_DH(SBI_DATA, D_ALL, NULL, NULL); - MMIO_DH(SBI_CTL_STAT, D_ALL, NULL, NULL); + MMIO_DH(SBI_DATA, D_ALL, sbi_data_mmio_read, NULL); + MMIO_DH(SBI_CTL_STAT, D_ALL, NULL, sbi_ctl_mmio_write); MMIO_D(PIXCLK_GATE, D_ALL); - MMIO_F(_DPA_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_ALL, NULL, NULL); - - MMIO_RO(DDI_BUF_CTL(PORT_A), D_ALL, 0, - DDI_INIT_DISPLAY_DETECTED, NULL, NULL); - MMIO_RO(DDI_BUF_CTL(PORT_B), D_ALL, 0, - DDI_INIT_DISPLAY_DETECTED, NULL, NULL); - MMIO_RO(DDI_BUF_CTL(PORT_C), D_ALL, 0, - DDI_INIT_DISPLAY_DETECTED, NULL, NULL); - MMIO_RO(DDI_BUF_CTL(PORT_D), D_ALL, 0, - DDI_INIT_DISPLAY_DETECTED, NULL, NULL); - MMIO_RO(DDI_BUF_CTL(PORT_E), D_ALL, 0, - DDI_INIT_DISPLAY_DETECTED, NULL, NULL); - - MMIO_DH(DP_TP_CTL(PORT_A), D_ALL, NULL, NULL); - MMIO_DH(DP_TP_CTL(PORT_B), D_ALL, NULL, NULL); - MMIO_DH(DP_TP_CTL(PORT_C), D_ALL, NULL, NULL); - MMIO_DH(DP_TP_CTL(PORT_D), D_ALL, NULL, NULL); - MMIO_DH(DP_TP_CTL(PORT_E), D_ALL, NULL, NULL); - - MMIO_RO(DP_TP_STATUS(PORT_A), D_ALL, 0, - (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); - MMIO_RO(DP_TP_STATUS(PORT_B), D_ALL, 0, - (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); - MMIO_RO(DP_TP_STATUS(PORT_C), D_ALL, 0, - (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); - MMIO_RO(DP_TP_STATUS(PORT_D), D_ALL, 0, - (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); - MMIO_RO(DP_TP_STATUS(PORT_E), D_ALL, 0, - (1 << 27) | (1 << 26) | (1 << 24), NULL, NULL); + MMIO_F(_DPA_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_ALL, NULL, + dp_aux_ch_ctl_mmio_write); + + MMIO_DH(DDI_BUF_CTL(PORT_A), D_ALL, NULL, ddi_buf_ctl_mmio_write); + MMIO_DH(DDI_BUF_CTL(PORT_B), D_ALL, NULL, ddi_buf_ctl_mmio_write); + MMIO_DH(DDI_BUF_CTL(PORT_C), D_ALL, NULL, ddi_buf_ctl_mmio_write); + MMIO_DH(DDI_BUF_CTL(PORT_D), D_ALL, NULL, ddi_buf_ctl_mmio_write); + MMIO_DH(DDI_BUF_CTL(PORT_E), D_ALL, NULL, ddi_buf_ctl_mmio_write); + + MMIO_DH(DP_TP_CTL(PORT_A), D_ALL, NULL, dp_tp_ctl_mmio_write); + MMIO_DH(DP_TP_CTL(PORT_B), D_ALL, NULL, dp_tp_ctl_mmio_write); + MMIO_DH(DP_TP_CTL(PORT_C), D_ALL, NULL, dp_tp_ctl_mmio_write); + MMIO_DH(DP_TP_CTL(PORT_D), D_ALL, NULL, dp_tp_ctl_mmio_write); + MMIO_DH(DP_TP_CTL(PORT_E), D_ALL, NULL, dp_tp_ctl_mmio_write); + + MMIO_DH(DP_TP_STATUS(PORT_A), D_ALL, NULL, dp_tp_status_mmio_write); + MMIO_DH(DP_TP_STATUS(PORT_B), D_ALL, NULL, dp_tp_status_mmio_write); + MMIO_DH(DP_TP_STATUS(PORT_C), D_ALL, NULL, dp_tp_status_mmio_write); + MMIO_DH(DP_TP_STATUS(PORT_D), D_ALL, NULL, dp_tp_status_mmio_write); + MMIO_DH(DP_TP_STATUS(PORT_E), D_ALL, NULL, NULL); MMIO_F(_DDI_BUF_TRANS_A, 0x50, 0, 0, 0, D_ALL, NULL, NULL); MMIO_F(0x64e60, 0x50, 0, 0, 0, D_ALL, NULL, NULL); @@ -1076,19 +1938,19 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL); MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL); MMIO_D(GEN6_PMINTRMSK, D_ALL); - MMIO_DH(HSW_PWR_WELL_BIOS, D_HSW | D_BDW, NULL, NULL); - MMIO_DH(HSW_PWR_WELL_DRIVER, D_HSW | D_BDW, NULL, NULL); - MMIO_DH(HSW_PWR_WELL_KVMR, D_HSW | D_BDW, NULL, NULL); - MMIO_DH(HSW_PWR_WELL_DEBUG, D_HSW | D_BDW, NULL, NULL); - MMIO_DH(HSW_PWR_WELL_CTL5, D_HSW | D_BDW, NULL, NULL); - MMIO_DH(HSW_PWR_WELL_CTL6, D_HSW | D_BDW, NULL, NULL); + MMIO_DH(HSW_PWR_WELL_BIOS, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_DRIVER, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_KVMR, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_DEBUG, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_CTL5, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_CTL6, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); MMIO_D(RSTDBYCTL, D_ALL); MMIO_DH(GEN6_GDRST, D_ALL, NULL, gdrst_mmio_write); MMIO_F(FENCE_REG_GEN6_LO(0), 0x80, 0, 0, 0, D_ALL, fence_mmio_read, fence_mmio_write); MMIO_F(VGT_PVINFO_PAGE, VGT_PVINFO_SIZE, F_UNALIGN, 0, 0, D_ALL, pvinfo_mmio_read, pvinfo_mmio_write); - MMIO_DH(CPU_VGACNTRL, D_ALL, NULL, NULL); + MMIO_DH(CPU_VGACNTRL, D_ALL, NULL, vga_control_mmio_write); MMIO_F(MCHBAR_MIRROR_BASE_SNB, 0x40000, 0, 0, 0, D_ALL, NULL, NULL); @@ -1301,8 +2163,8 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) NULL, NULL); MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, NULL, NULL); - MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, - NULL, NULL); + MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, + ring_timestamp_mmio_read, NULL); MMIO_RING_D(RING_ACTHD_UDW, D_BDW_PLUS); @@ -1422,24 +2284,24 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_DH(FORCEWAKE_MEDIA_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); MMIO_DH(FORCEWAKE_ACK_MEDIA_GEN9, D_SKL_PLUS, NULL, NULL); - MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, NULL); - MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, NULL); - MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, NULL); + MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); + MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); + MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); MMIO_D(HSW_PWR_WELL_BIOS, D_SKL); - MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, NULL); + MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, skl_power_well_ctl_write); - MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL, NULL, NULL); + MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL, NULL, mailbox_write); MMIO_D(0xa210, D_SKL_PLUS); MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); - MMIO_DH(0x4ddc, D_SKL, NULL, NULL); - MMIO_DH(0x42080, D_SKL, NULL, NULL); + MMIO_DH(0x4ddc, D_SKL, NULL, skl_misc_ctl_write); + MMIO_DH(0x42080, D_SKL, NULL, skl_misc_ctl_write); MMIO_D(0x45504, D_SKL); MMIO_D(0x45520, D_SKL); MMIO_D(0x46000, D_SKL); - MMIO_DH(0x46010, D_SKL, NULL, NULL); - MMIO_DH(0x46014, D_SKL, NULL, NULL); + MMIO_DH(0x46010, D_SKL, NULL, skl_lcpll_write); + MMIO_DH(0x46014, D_SKL, NULL, skl_lcpll_write); MMIO_D(0x6C040, D_SKL); MMIO_D(0x6C048, D_SKL); MMIO_D(0x6C050, D_SKL); @@ -1448,28 +2310,28 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_D(0x6C054, D_SKL); MMIO_D(0x6c058, D_SKL); MMIO_D(0x6c05c, D_SKL); - MMIO_DH(0x6c060, D_SKL, NULL, NULL); - - MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL, NULL, NULL); - - MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL, NULL, NULL); - - MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL, NULL, NULL); - MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL, NULL, NULL); + MMIO_DH(0X6c060, D_SKL, dpll_status_read, NULL); + + MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL, NULL, pf_write); + + MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL, NULL, pf_write); + + MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL, NULL, pf_write); + MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL, NULL, pf_write); MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL); MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL); @@ -1634,6 +2496,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_D(0x44500, D_SKL); return 0; } + /** * intel_gvt_find_mmio_info - find MMIO information entry by aligned offset * @gvt: GVT device diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c index d90c5f660b00..84d7174d0081 100644 --- a/drivers/gpu/drm/i915/gvt/interrupt.c +++ b/drivers/gpu/drm/i915/gvt/interrupt.c @@ -667,6 +667,21 @@ static void init_events( } } +static enum hrtimer_restart vblank_timer_fn(struct hrtimer *data) +{ + struct intel_gvt_vblank_timer *vblank_timer; + struct intel_gvt_irq *irq; + struct intel_gvt *gvt; + + vblank_timer = container_of(data, struct intel_gvt_vblank_timer, timer); + irq = container_of(vblank_timer, struct intel_gvt_irq, vblank_timer); + gvt = container_of(irq, struct intel_gvt, irq); + + intel_gvt_request_service(gvt, INTEL_GVT_REQUEST_EMULATE_VBLANK); + hrtimer_add_expires_ns(&vblank_timer->timer, vblank_timer->period); + return HRTIMER_RESTART; +} + /** * intel_gvt_clean_irq - clean up GVT-g IRQ emulation subsystem * @gvt: a GVT device @@ -677,8 +692,13 @@ static void init_events( */ void intel_gvt_clean_irq(struct intel_gvt *gvt) { + struct intel_gvt_irq *irq = &gvt->irq; + + hrtimer_cancel(&irq->vblank_timer.timer); } +#define VBLNAK_TIMER_PERIOD 16000000 + /** * intel_gvt_init_irq - initialize GVT-g IRQ emulation subsystem * @gvt: a GVT device @@ -692,6 +712,7 @@ void intel_gvt_clean_irq(struct intel_gvt *gvt) int intel_gvt_init_irq(struct intel_gvt *gvt) { struct intel_gvt_irq *irq = &gvt->irq; + struct intel_gvt_vblank_timer *vblank_timer = &irq->vblank_timer; gvt_dbg_core("init irq framework\n"); @@ -710,5 +731,10 @@ int intel_gvt_init_irq(struct intel_gvt *gvt) irq->ops->init_irq(irq); init_irq_map(irq); + + hrtimer_init(&vblank_timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + vblank_timer->timer.function = vblank_timer_fn; + vblank_timer->period = VBLNAK_TIMER_PERIOD; + return 0; } diff --git a/drivers/gpu/drm/i915/gvt/interrupt.h b/drivers/gpu/drm/i915/gvt/interrupt.h index 28d5d32d6017..3136527b7e5c 100644 --- a/drivers/gpu/drm/i915/gvt/interrupt.h +++ b/drivers/gpu/drm/i915/gvt/interrupt.h @@ -195,6 +195,11 @@ struct intel_gvt_irq_map { u32 down_irq_bitmask; }; +struct intel_gvt_vblank_timer { + struct hrtimer timer; + u64 period; +}; + /* structure containing device specific IRQ state */ struct intel_gvt_irq { struct intel_gvt_irq_ops *ops; @@ -203,6 +208,7 @@ struct intel_gvt_irq { struct intel_gvt_event_info events[INTEL_GVT_EVENT_MAX]; DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX); struct intel_gvt_irq_map *irq_map; + struct intel_gvt_vblank_timer vblank_timer; }; int intel_gvt_init_irq(struct intel_gvt *gvt); diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 2d4aaa781757..47ed0a085e4c 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -146,6 +146,7 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) vgpu->active = false; idr_remove(&gvt->vgpu_idr, vgpu->id); + intel_vgpu_clean_display(vgpu); intel_vgpu_clean_opregion(vgpu); intel_vgpu_clean_gtt(vgpu); intel_gvt_hypervisor_detach_vgpu(vgpu); @@ -216,11 +217,17 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, goto out_clean_gtt; } + ret = intel_vgpu_init_display(vgpu); + if (ret) + goto out_clean_opregion; + vgpu->active = true; mutex_unlock(&gvt->lock); return vgpu; +out_clean_opregion: + intel_vgpu_clean_opregion(vgpu); out_clean_gtt: intel_vgpu_clean_gtt(vgpu); out_detach_hypervisor_vgpu: -- cgit v1.2.3 From 8453d674ae7e63f629a91fe4124df7a7dc9c74cd Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Sun, 1 May 2016 02:48:25 -0400 Subject: drm/i915/gvt: vGPU execlist virtualization This patch introduces the vGPU execlist virtualization. Under virtulization environment, HW execlist interface are fully emulated including virtual CSB emulation, virtual execlist emulation. The framework will emulate the virtual CSB according to the guest workload running status Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 3 +- drivers/gpu/drm/i915/gvt/debug.h | 3 + drivers/gpu/drm/i915/gvt/execlist.c | 386 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/execlist.h | 137 +++++++++++++ drivers/gpu/drm/i915/gvt/gvt.h | 3 + drivers/gpu/drm/i915/gvt/vgpu.c | 6 + 6 files changed, 537 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/gvt/execlist.c create mode 100644 drivers/gpu/drm/i915/gvt/execlist.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index f87cd7fe9574..f15197390d76 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,6 +1,7 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ - interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o + interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ + execlist.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index 5c21c585ac00..a7e0e7956ee9 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -42,4 +42,7 @@ #define gvt_dbg_dpy(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: dpy: "fmt, ##args) +#define gvt_dbg_el(fmt, args...) \ + DRM_DEBUG_DRIVER("gvt: el: "fmt, ##args) + #endif diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c new file mode 100644 index 000000000000..3c38e2a2dba3 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -0,0 +1,386 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Zhiyuan Lv + * Zhi Wang + * + * Contributors: + * Min He + * Bing Niu + * Ping Gao + * Tina Zhang + * + */ + +#include "i915_drv.h" + +#define _EL_OFFSET_STATUS 0x234 +#define _EL_OFFSET_STATUS_BUF 0x370 +#define _EL_OFFSET_STATUS_PTR 0x3A0 + +#define execlist_ring_mmio(gvt, ring_id, offset) \ + (gvt->dev_priv->engine[ring_id].mmio_base + (offset)) + +#define valid_context(ctx) ((ctx)->valid) +#define same_context(a, b) (((a)->context_id == (b)->context_id) && \ + ((a)->lrca == (b)->lrca)) + +static int context_switch_events[] = { + [RCS] = RCS_AS_CONTEXT_SWITCH, + [BCS] = BCS_AS_CONTEXT_SWITCH, + [VCS] = VCS_AS_CONTEXT_SWITCH, + [VCS2] = VCS2_AS_CONTEXT_SWITCH, + [VECS] = VECS_AS_CONTEXT_SWITCH, +}; + +static int ring_id_to_context_switch_event(int ring_id) +{ + if (WARN_ON(ring_id < RCS && ring_id > + ARRAY_SIZE(context_switch_events))) + return -EINVAL; + + return context_switch_events[ring_id]; +} + +static void switch_virtual_execlist_slot(struct intel_vgpu_execlist *execlist) +{ + gvt_dbg_el("[before] running slot %d/context %x pending slot %d\n", + execlist->running_slot ? + execlist->running_slot->index : -1, + execlist->running_context ? + execlist->running_context->context_id : 0, + execlist->pending_slot ? + execlist->pending_slot->index : -1); + + execlist->running_slot = execlist->pending_slot; + execlist->pending_slot = NULL; + execlist->running_context = execlist->running_context ? + &execlist->running_slot->ctx[0] : NULL; + + gvt_dbg_el("[after] running slot %d/context %x pending slot %d\n", + execlist->running_slot ? + execlist->running_slot->index : -1, + execlist->running_context ? + execlist->running_context->context_id : 0, + execlist->pending_slot ? + execlist->pending_slot->index : -1); +} + +static void emulate_execlist_status(struct intel_vgpu_execlist *execlist) +{ + struct intel_vgpu_execlist_slot *running = execlist->running_slot; + struct intel_vgpu_execlist_slot *pending = execlist->pending_slot; + struct execlist_ctx_descriptor_format *desc = execlist->running_context; + struct intel_vgpu *vgpu = execlist->vgpu; + struct execlist_status_format status; + int ring_id = execlist->ring_id; + u32 status_reg = execlist_ring_mmio(vgpu->gvt, + ring_id, _EL_OFFSET_STATUS); + + status.ldw = vgpu_vreg(vgpu, status_reg); + status.udw = vgpu_vreg(vgpu, status_reg + 4); + + if (running) { + status.current_execlist_pointer = !!running->index; + status.execlist_write_pointer = !!!running->index; + status.execlist_0_active = status.execlist_0_valid = + !!!(running->index); + status.execlist_1_active = status.execlist_1_valid = + !!(running->index); + } else { + status.context_id = 0; + status.execlist_0_active = status.execlist_0_valid = 0; + status.execlist_1_active = status.execlist_1_valid = 0; + } + + status.context_id = desc ? desc->context_id : 0; + status.execlist_queue_full = !!(pending); + + vgpu_vreg(vgpu, status_reg) = status.ldw; + vgpu_vreg(vgpu, status_reg + 4) = status.udw; + + gvt_dbg_el("vgpu%d: status reg offset %x ldw %x udw %x\n", + vgpu->id, status_reg, status.ldw, status.udw); +} + +static void emulate_csb_update(struct intel_vgpu_execlist *execlist, + struct execlist_context_status_format *status, + bool trigger_interrupt_later) +{ + struct intel_vgpu *vgpu = execlist->vgpu; + int ring_id = execlist->ring_id; + struct execlist_context_status_pointer_format ctx_status_ptr; + u32 write_pointer; + u32 ctx_status_ptr_reg, ctx_status_buf_reg, offset; + + ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id, + _EL_OFFSET_STATUS_PTR); + ctx_status_buf_reg = execlist_ring_mmio(vgpu->gvt, ring_id, + _EL_OFFSET_STATUS_BUF); + + ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg); + + write_pointer = ctx_status_ptr.write_ptr; + + if (write_pointer == 0x7) + write_pointer = 0; + else { + ++write_pointer; + write_pointer %= 0x6; + } + + offset = ctx_status_buf_reg + write_pointer * 8; + + vgpu_vreg(vgpu, offset) = status->ldw; + vgpu_vreg(vgpu, offset + 4) = status->udw; + + ctx_status_ptr.write_ptr = write_pointer; + vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; + + gvt_dbg_el("vgpu%d: w pointer %u reg %x csb l %x csb h %x\n", + vgpu->id, write_pointer, offset, status->ldw, status->udw); + + if (trigger_interrupt_later) + return; + + intel_vgpu_trigger_virtual_event(vgpu, + ring_id_to_context_switch_event(execlist->ring_id)); +} + +int emulate_execlist_ctx_schedule_out( + struct intel_vgpu_execlist *execlist, + struct execlist_ctx_descriptor_format *ctx) +{ + struct intel_vgpu_execlist_slot *running = execlist->running_slot; + struct intel_vgpu_execlist_slot *pending = execlist->pending_slot; + struct execlist_ctx_descriptor_format *ctx0 = &running->ctx[0]; + struct execlist_ctx_descriptor_format *ctx1 = &running->ctx[1]; + struct execlist_context_status_format status; + + memset(&status, 0, sizeof(status)); + + gvt_dbg_el("schedule out context id %x\n", ctx->context_id); + + if (WARN_ON(!same_context(ctx, execlist->running_context))) { + gvt_err("schedule out context is not running context," + "ctx id %x running ctx id %x\n", + ctx->context_id, + execlist->running_context->context_id); + return -EINVAL; + } + + /* ctx1 is valid, ctx0/ctx is scheduled-out -> element switch */ + if (valid_context(ctx1) && same_context(ctx0, ctx)) { + gvt_dbg_el("ctx 1 valid, ctx/ctx 0 is scheduled-out\n"); + + execlist->running_context = ctx1; + + emulate_execlist_status(execlist); + + status.context_complete = status.element_switch = 1; + status.context_id = ctx->context_id; + + emulate_csb_update(execlist, &status, false); + /* + * ctx1 is not valid, ctx == ctx0 + * ctx1 is valid, ctx1 == ctx + * --> last element is finished + * emulate: + * active-to-idle if there is *no* pending execlist + * context-complete if there *is* pending execlist + */ + } else if ((!valid_context(ctx1) && same_context(ctx0, ctx)) + || (valid_context(ctx1) && same_context(ctx1, ctx))) { + gvt_dbg_el("need to switch virtual execlist slot\n"); + + switch_virtual_execlist_slot(execlist); + + emulate_execlist_status(execlist); + + status.context_complete = status.active_to_idle = 1; + status.context_id = ctx->context_id; + + if (!pending) { + emulate_csb_update(execlist, &status, false); + } else { + emulate_csb_update(execlist, &status, true); + + memset(&status, 0, sizeof(status)); + + status.idle_to_active = 1; + status.context_id = 0; + + emulate_csb_update(execlist, &status, false); + } + } else { + WARN_ON(1); + return -EINVAL; + } + + return 0; +} + +static struct intel_vgpu_execlist_slot *get_next_execlist_slot( + struct intel_vgpu_execlist *execlist) +{ + struct intel_vgpu *vgpu = execlist->vgpu; + int ring_id = execlist->ring_id; + u32 status_reg = execlist_ring_mmio(vgpu->gvt, ring_id, + _EL_OFFSET_STATUS); + struct execlist_status_format status; + + status.ldw = vgpu_vreg(vgpu, status_reg); + status.udw = vgpu_vreg(vgpu, status_reg + 4); + + if (status.execlist_queue_full) { + gvt_err("virtual execlist slots are full\n"); + return NULL; + } + + return &execlist->slot[status.execlist_write_pointer]; +} + +int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist, + struct execlist_ctx_descriptor_format ctx[2]) +{ + struct intel_vgpu_execlist_slot *running = execlist->running_slot; + struct intel_vgpu_execlist_slot *slot = + get_next_execlist_slot(execlist); + + struct execlist_ctx_descriptor_format *ctx0, *ctx1; + struct execlist_context_status_format status; + + gvt_dbg_el("emulate schedule-in\n"); + + if (!slot) { + gvt_err("no available execlist slot\n"); + return -EINVAL; + } + + memset(&status, 0, sizeof(status)); + memset(slot->ctx, 0, sizeof(slot->ctx)); + + slot->ctx[0] = ctx[0]; + slot->ctx[1] = ctx[1]; + + gvt_dbg_el("alloc slot index %d ctx 0 %x ctx 1 %x\n", + slot->index, ctx[0].context_id, + ctx[1].context_id); + + /* + * no running execlist, make this write bundle as running execlist + * -> idle-to-active + */ + if (!running) { + gvt_dbg_el("no current running execlist\n"); + + execlist->running_slot = slot; + execlist->pending_slot = NULL; + execlist->running_context = &slot->ctx[0]; + + gvt_dbg_el("running slot index %d running context %x\n", + execlist->running_slot->index, + execlist->running_context->context_id); + + emulate_execlist_status(execlist); + + status.idle_to_active = 1; + status.context_id = 0; + + emulate_csb_update(execlist, &status, false); + return 0; + } + + ctx0 = &running->ctx[0]; + ctx1 = &running->ctx[1]; + + gvt_dbg_el("current running slot index %d ctx 0 %x ctx 1 %x\n", + running->index, ctx0->context_id, ctx1->context_id); + + /* + * already has an running execlist + * a. running ctx1 is valid, + * ctx0 is finished, and running ctx1 == new execlist ctx[0] + * b. running ctx1 is not valid, + * ctx0 == new execlist ctx[0] + * ----> lite-restore + preempted + */ + if ((valid_context(ctx1) && same_context(ctx1, &slot->ctx[0]) && + /* condition a */ + (!same_context(ctx0, execlist->running_context))) || + (!valid_context(ctx1) && + same_context(ctx0, &slot->ctx[0]))) { /* condition b */ + gvt_dbg_el("need to switch virtual execlist slot\n"); + + execlist->pending_slot = slot; + switch_virtual_execlist_slot(execlist); + + emulate_execlist_status(execlist); + + status.lite_restore = status.preempted = 1; + status.context_id = ctx[0].context_id; + + emulate_csb_update(execlist, &status, false); + } else { + gvt_dbg_el("emulate as pending slot\n"); + /* + * otherwise + * --> emulate pending execlist exist + but no preemption case + */ + execlist->pending_slot = slot; + emulate_execlist_status(execlist); + } + return 0; +} + +static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id) +{ + struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id]; + struct execlist_context_status_pointer_format ctx_status_ptr; + u32 ctx_status_ptr_reg; + + memset(execlist, 0, sizeof(*execlist)); + + execlist->vgpu = vgpu; + execlist->ring_id = ring_id; + execlist->slot[0].index = 0; + execlist->slot[1].index = 1; + + ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id, + _EL_OFFSET_STATUS_PTR); + + ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg); + ctx_status_ptr.read_ptr = ctx_status_ptr.write_ptr = 0x7; + vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; +} + +int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) +{ + int i; + + /* each ring has a virtual execlist engine */ + for (i = 0; i < I915_NUM_ENGINES; i++) + init_vgpu_execlist(vgpu, i); + + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/execlist.h b/drivers/gpu/drm/i915/gvt/execlist.h new file mode 100644 index 000000000000..428f54358ae8 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/execlist.h @@ -0,0 +1,137 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Zhiyuan Lv + * Zhi Wang + * + * Contributors: + * Min He + * Bing Niu + * Ping Gao + * Tina Zhang + * + */ + +#ifndef _GVT_EXECLIST_H_ +#define _GVT_EXECLIST_H_ + +struct execlist_ctx_descriptor_format { + union { + u32 udw; + u32 context_id; + }; + union { + u32 ldw; + struct { + u32 valid : 1; + u32 force_pd_restore : 1; + u32 force_restore : 1; + u32 addressing_mode : 2; + u32 llc_coherency : 1; + u32 fault_handling : 2; + u32 privilege_access : 1; + u32 reserved : 3; + u32 lrca : 20; + }; + }; +}; + +struct execlist_status_format { + union { + u32 ldw; + struct { + u32 current_execlist_pointer :1; + u32 execlist_write_pointer :1; + u32 execlist_queue_full :1; + u32 execlist_1_valid :1; + u32 execlist_0_valid :1; + u32 last_ctx_switch_reason :9; + u32 current_active_elm_status :2; + u32 arbitration_enable :1; + u32 execlist_1_active :1; + u32 execlist_0_active :1; + u32 reserved :13; + }; + }; + union { + u32 udw; + u32 context_id; + }; +}; + +struct execlist_context_status_pointer_format { + union { + u32 dw; + struct { + u32 write_ptr :3; + u32 reserved :5; + u32 read_ptr :3; + u32 reserved2 :5; + u32 mask :16; + }; + }; +}; + +struct execlist_context_status_format { + union { + u32 ldw; + struct { + u32 idle_to_active :1; + u32 preempted :1; + u32 element_switch :1; + u32 active_to_idle :1; + u32 context_complete :1; + u32 wait_on_sync_flip :1; + u32 wait_on_vblank :1; + u32 wait_on_semaphore :1; + u32 wait_on_scanline :1; + u32 reserved :2; + u32 semaphore_wait_mode :1; + u32 display_plane :3; + u32 lite_restore :1; + u32 reserved_2 :16; + }; + }; + union { + u32 udw; + u32 context_id; + }; +}; + +struct intel_vgpu_execlist_slot { + struct execlist_ctx_descriptor_format ctx[2]; + u32 index; +}; + +struct intel_vgpu_execlist { + struct intel_vgpu_execlist_slot slot[2]; + struct intel_vgpu_execlist_slot *running_slot; + struct intel_vgpu_execlist_slot *pending_slot; + struct execlist_ctx_descriptor_format *running_context; + int ring_id; + struct intel_vgpu *vgpu; +}; + +int intel_vgpu_init_execlist(struct intel_vgpu *vgpu); + +#endif /*_GVT_EXECLIST_H_*/ diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 1619881dbd51..82f932a24e7d 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -41,6 +41,7 @@ #include "gtt.h" #include "display.h" #include "edid.h" +#include "execlist.h" #define GVT_MAX_VGPU 8 @@ -146,6 +147,8 @@ struct intel_vgpu { struct intel_vgpu_gtt gtt; struct intel_vgpu_opregion opregion; struct intel_vgpu_display display; + /* TODO: move the declaration of intel_gvt.h to a proper place. */ + struct intel_vgpu_execlist execlist[I915_NUM_ENGINES]; }; struct intel_gvt_gm { diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 47ed0a085e4c..e806b0e4035a 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -221,11 +221,17 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, if (ret) goto out_clean_opregion; + ret = intel_vgpu_init_execlist(vgpu); + if (ret) + goto out_clean_display; + vgpu->active = true; mutex_unlock(&gvt->lock); return vgpu; +out_clean_display: + intel_vgpu_clean_display(vgpu); out_clean_opregion: intel_vgpu_clean_opregion(vgpu); out_clean_gtt: -- cgit v1.2.3 From 28c4c6ca7f794b2d5ac8773d43311e95f6518415 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Sun, 1 May 2016 05:22:47 -0400 Subject: drm/i915/gvt: vGPU workload submission This patch introduces the vGPU workload submission logics. Under virtualization environment, guest will submit workload through virtual execlist submit port. The submitted workload load will be wrapped into an gvt workload which will be picked by GVT workload scheduler and executed on host i915 later. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 294 ++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/gvt/execlist.h | 48 ++++++ drivers/gpu/drm/i915/gvt/gvt.h | 5 +- drivers/gpu/drm/i915/gvt/handlers.c | 38 ++++- drivers/gpu/drm/i915/gvt/reg.h | 5 + drivers/gpu/drm/i915/gvt/scheduler.h | 64 ++++++++ drivers/gpu/drm/i915/gvt/vgpu.c | 1 + 7 files changed, 449 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/scheduler.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 3c38e2a2dba3..f149847cbd17 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -167,7 +167,7 @@ static void emulate_csb_update(struct intel_vgpu_execlist *execlist, ring_id_to_context_switch_event(execlist->ring_id)); } -int emulate_execlist_ctx_schedule_out( +static int emulate_execlist_ctx_schedule_out( struct intel_vgpu_execlist *execlist, struct execlist_ctx_descriptor_format *ctx) { @@ -260,7 +260,7 @@ static struct intel_vgpu_execlist_slot *get_next_execlist_slot( return &execlist->slot[status.execlist_write_pointer]; } -int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist, +static int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist, struct execlist_ctx_descriptor_format ctx[2]) { struct intel_vgpu_execlist_slot *running = execlist->running_slot; @@ -353,6 +353,279 @@ int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist, return 0; } +static void free_workload(struct intel_vgpu_workload *workload) +{ + intel_vgpu_unpin_mm(workload->shadow_mm); + intel_gvt_mm_unreference(workload->shadow_mm); + kmem_cache_free(workload->vgpu->workloads, workload); +} + +#define get_desc_from_elsp_dwords(ed, i) \ + ((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2])) + +static int prepare_execlist_workload(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + struct execlist_ctx_descriptor_format ctx[2]; + int ring_id = workload->ring_id; + + intel_vgpu_pin_mm(workload->shadow_mm); + intel_vgpu_sync_oos_pages(workload->vgpu); + intel_vgpu_flush_post_shadow(workload->vgpu); + if (!workload->emulate_schedule_in) + return 0; + + ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1); + ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0); + + return emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx); +} + +static int complete_execlist_workload(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + struct intel_vgpu_execlist *execlist = + &vgpu->execlist[workload->ring_id]; + struct intel_vgpu_workload *next_workload; + struct list_head *next = workload_q_head(vgpu, workload->ring_id)->next; + bool lite_restore = false; + int ret; + + gvt_dbg_el("complete workload %p status %d\n", workload, + workload->status); + + if (workload->status) + goto out; + + if (!list_empty(workload_q_head(vgpu, workload->ring_id))) { + struct execlist_ctx_descriptor_format *this_desc, *next_desc; + + next_workload = container_of(next, + struct intel_vgpu_workload, list); + this_desc = &workload->ctx_desc; + next_desc = &next_workload->ctx_desc; + + lite_restore = same_context(this_desc, next_desc); + } + + if (lite_restore) { + gvt_dbg_el("next context == current - no schedule-out\n"); + free_workload(workload); + return 0; + } + + ret = emulate_execlist_ctx_schedule_out(execlist, &workload->ctx_desc); + if (ret) + goto err; +out: + free_workload(workload); + return 0; +err: + free_workload(workload); + return ret; +} + +#define RING_CTX_OFF(x) \ + offsetof(struct execlist_ring_context, x) + +static void read_guest_pdps(struct intel_vgpu *vgpu, + u64 ring_context_gpa, u32 pdp[8]) +{ + u64 gpa; + int i; + + gpa = ring_context_gpa + RING_CTX_OFF(pdp3_UDW.val); + + for (i = 0; i < 8; i++) + intel_gvt_hypervisor_read_gpa(vgpu, + gpa + i * 8, &pdp[7 - i], 4); +} + +static int prepare_mm(struct intel_vgpu_workload *workload) +{ + struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc; + struct intel_vgpu_mm *mm; + int page_table_level; + u32 pdp[8]; + + if (desc->addressing_mode == 1) { /* legacy 32-bit */ + page_table_level = 3; + } else if (desc->addressing_mode == 3) { /* legacy 64 bit */ + page_table_level = 4; + } else { + gvt_err("Advanced Context mode(SVM) is not supported!\n"); + return -EINVAL; + } + + read_guest_pdps(workload->vgpu, workload->ring_context_gpa, pdp); + + mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, page_table_level, pdp); + if (mm) { + intel_gvt_mm_reference(mm); + } else { + + mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT, + pdp, page_table_level, 0); + if (IS_ERR(mm)) { + gvt_err("fail to create mm object.\n"); + return PTR_ERR(mm); + } + } + workload->shadow_mm = mm; + return 0; +} + +#define get_last_workload(q) \ + (list_empty(q) ? NULL : container_of(q->prev, \ + struct intel_vgpu_workload, list)) + +bool submit_context(struct intel_vgpu *vgpu, int ring_id, + struct execlist_ctx_descriptor_format *desc, + bool emulate_schedule_in) +{ + struct list_head *q = workload_q_head(vgpu, ring_id); + struct intel_vgpu_workload *last_workload = get_last_workload(q); + struct intel_vgpu_workload *workload = NULL; + u64 ring_context_gpa; + u32 head, tail, start, ctl, ctx_ctl; + int ret; + + ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, + (u32)((desc->lrca + 1) << GTT_PAGE_SHIFT)); + if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) { + gvt_err("invalid guest context LRCA: %x\n", desc->lrca); + return -EINVAL; + } + + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + + RING_CTX_OFF(ring_header.val), &head, 4); + + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + + RING_CTX_OFF(ring_tail.val), &tail, 4); + + head &= RB_HEAD_OFF_MASK; + tail &= RB_TAIL_OFF_MASK; + + if (last_workload && same_context(&last_workload->ctx_desc, desc)) { + gvt_dbg_el("ring id %d cur workload == last\n", ring_id); + gvt_dbg_el("ctx head %x real head %lx\n", head, + last_workload->rb_tail); + /* + * cannot use guest context head pointer here, + * as it might not be updated at this time + */ + head = last_workload->rb_tail; + } + + gvt_dbg_el("ring id %d begin a new workload\n", ring_id); + + workload = kmem_cache_zalloc(vgpu->workloads, GFP_KERNEL); + if (!workload) + return -ENOMEM; + + /* record some ring buffer register values for scan and shadow */ + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + + RING_CTX_OFF(rb_start.val), &start, 4); + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + + RING_CTX_OFF(rb_ctrl.val), &ctl, 4); + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + + RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4); + + INIT_LIST_HEAD(&workload->list); + + init_waitqueue_head(&workload->shadow_ctx_status_wq); + atomic_set(&workload->shadow_ctx_active, 0); + + workload->vgpu = vgpu; + workload->ring_id = ring_id; + workload->ctx_desc = *desc; + workload->ring_context_gpa = ring_context_gpa; + workload->rb_head = head; + workload->rb_tail = tail; + workload->rb_start = start; + workload->rb_ctl = ctl; + workload->prepare = prepare_execlist_workload; + workload->complete = complete_execlist_workload; + workload->status = -EINPROGRESS; + workload->emulate_schedule_in = emulate_schedule_in; + + if (emulate_schedule_in) + memcpy(&workload->elsp_dwords, + &vgpu->execlist[ring_id].elsp_dwords, + sizeof(workload->elsp_dwords)); + + gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n", + workload, ring_id, head, tail, start, ctl); + + gvt_dbg_el("workload %p emulate schedule_in %d\n", workload, + emulate_schedule_in); + + ret = prepare_mm(workload); + if (ret) { + kmem_cache_free(vgpu->workloads, workload); + return ret; + } + + queue_workload(workload); + return 0; +} + +int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id) +{ + struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id]; + struct execlist_ctx_descriptor_format *desc[2], valid_desc[2]; + unsigned long valid_desc_bitmap = 0; + bool emulate_schedule_in = true; + int ret; + int i; + + memset(valid_desc, 0, sizeof(valid_desc)); + + desc[0] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 1); + desc[1] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 0); + + for (i = 0; i < 2; i++) { + if (!desc[i]->valid) + continue; + + if (!desc[i]->privilege_access) { + gvt_err("vgpu%d: unexpected GGTT elsp submission\n", + vgpu->id); + return -EINVAL; + } + + /* TODO: add another guest context checks here. */ + set_bit(i, &valid_desc_bitmap); + valid_desc[i] = *desc[i]; + } + + if (!valid_desc_bitmap) { + gvt_err("vgpu%d: no valid desc in a elsp submission\n", + vgpu->id); + return -EINVAL; + } + + if (!test_bit(0, (void *)&valid_desc_bitmap) && + test_bit(1, (void *)&valid_desc_bitmap)) { + gvt_err("vgpu%d: weird elsp submission, desc 0 is not valid\n", + vgpu->id); + return -EINVAL; + } + + /* submit workload */ + for_each_set_bit(i, (void *)&valid_desc_bitmap, 2) { + ret = submit_context(vgpu, ring_id, &valid_desc[i], + emulate_schedule_in); + if (ret) { + gvt_err("vgpu%d: fail to schedule workload\n", + vgpu->id); + return ret; + } + emulate_schedule_in = false; + } + return 0; +} + static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id) { struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id]; @@ -374,13 +647,28 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id) vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; } +void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu) +{ + kmem_cache_destroy(vgpu->workloads); +} + int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) { int i; /* each ring has a virtual execlist engine */ - for (i = 0; i < I915_NUM_ENGINES; i++) + for (i = 0; i < I915_NUM_ENGINES; i++) { init_vgpu_execlist(vgpu, i); + INIT_LIST_HEAD(&vgpu->workload_q_head[i]); + } + + vgpu->workloads = kmem_cache_create("gvt-g vgpu workload", + sizeof(struct intel_vgpu_workload), 0, + SLAB_HWCACHE_ALIGN, + NULL); + + if (!vgpu->workloads) + return -ENOMEM; return 0; } diff --git a/drivers/gpu/drm/i915/gvt/execlist.h b/drivers/gpu/drm/i915/gvt/execlist.h index 428f54358ae8..13614fb4e572 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.h +++ b/drivers/gpu/drm/i915/gvt/execlist.h @@ -118,6 +118,49 @@ struct execlist_context_status_format { }; }; +struct execlist_mmio_pair { + u32 addr; + u32 val; +}; + +/* The first 52 dwords in register state context */ +struct execlist_ring_context { + u32 nop1; + u32 lri_cmd_1; + struct execlist_mmio_pair ctx_ctrl; + struct execlist_mmio_pair ring_header; + struct execlist_mmio_pair ring_tail; + struct execlist_mmio_pair rb_start; + struct execlist_mmio_pair rb_ctrl; + struct execlist_mmio_pair bb_cur_head_UDW; + struct execlist_mmio_pair bb_cur_head_LDW; + struct execlist_mmio_pair bb_state; + struct execlist_mmio_pair second_bb_addr_UDW; + struct execlist_mmio_pair second_bb_addr_LDW; + struct execlist_mmio_pair second_bb_state; + struct execlist_mmio_pair bb_per_ctx_ptr; + struct execlist_mmio_pair rcs_indirect_ctx; + struct execlist_mmio_pair rcs_indirect_ctx_offset; + u32 nop2; + u32 nop3; + u32 nop4; + u32 lri_cmd_2; + struct execlist_mmio_pair ctx_timestamp; + struct execlist_mmio_pair pdp3_UDW; + struct execlist_mmio_pair pdp3_LDW; + struct execlist_mmio_pair pdp2_UDW; + struct execlist_mmio_pair pdp2_LDW; + struct execlist_mmio_pair pdp1_UDW; + struct execlist_mmio_pair pdp1_LDW; + struct execlist_mmio_pair pdp0_UDW; + struct execlist_mmio_pair pdp0_LDW; +}; + +struct intel_vgpu_elsp_dwords { + u32 data[4]; + u32 index; +}; + struct intel_vgpu_execlist_slot { struct execlist_ctx_descriptor_format ctx[2]; u32 index; @@ -130,8 +173,13 @@ struct intel_vgpu_execlist { struct execlist_ctx_descriptor_format *running_context; int ring_id; struct intel_vgpu *vgpu; + struct intel_vgpu_elsp_dwords elsp_dwords; }; +void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu); + int intel_vgpu_init_execlist(struct intel_vgpu *vgpu); +int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id); + #endif /*_GVT_EXECLIST_H_*/ diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 82f932a24e7d..414163695e07 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -42,6 +42,7 @@ #include "display.h" #include "edid.h" #include "execlist.h" +#include "scheduler.h" #define GVT_MAX_VGPU 8 @@ -147,8 +148,9 @@ struct intel_vgpu { struct intel_vgpu_gtt gtt; struct intel_vgpu_opregion opregion; struct intel_vgpu_display display; - /* TODO: move the declaration of intel_gvt.h to a proper place. */ struct intel_vgpu_execlist execlist[I915_NUM_ENGINES]; + struct list_head workload_q_head[I915_NUM_ENGINES]; + struct kmem_cache *workloads; }; struct intel_gvt_gm { @@ -193,6 +195,7 @@ struct intel_gvt { struct intel_gvt_irq irq; struct intel_gvt_gtt gtt; struct intel_gvt_opregion opregion; + struct intel_gvt_workload_scheduler scheduler; struct task_struct *service_thread; wait_queue_head_t service_thread_wq; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 194778b374ff..970804aed381 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -128,6 +128,18 @@ static int new_mmio_info(struct intel_gvt *gvt, return 0; } +static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg) +{ + int i; + + reg &= ~GENMASK(11, 0); + for (i = 0; i < I915_NUM_ENGINES; i++) { + if (gvt->dev_priv->engine[i].mmio_base == reg) + return i; + } + return -1; +} + #define offset_to_fence_num(offset) \ ((offset - i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) >> 3) @@ -1262,6 +1274,28 @@ static int ring_timestamp_mmio_read(struct intel_vgpu *vgpu, return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); } +static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); + struct intel_vgpu_execlist *execlist; + u32 data = *(u32 *)p_data; + int ret; + + if (WARN_ON(ring_id < 0)) + return -EINVAL; + + execlist = &vgpu->execlist[ring_id]; + + execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data; + if (execlist->elsp_dwords.index == 3) + ret = intel_vgpu_submit_execlist(vgpu, ring_id); + + ++execlist->elsp_dwords.index; + execlist->elsp_dwords.index &= 0x3; + return 0; +} + #define MMIO_F(reg, s, f, am, rm, d, r, w) do { \ ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \ f, s, am, rm, d, r, w); \ @@ -2169,8 +2203,8 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) MMIO_RING_D(RING_ACTHD_UDW, D_BDW_PLUS); #define RING_REG(base) (base + 0x230) - MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, NULL); - MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL); + MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, elsp_mmio_write); + MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, elsp_mmio_write); #undef RING_REG #define RING_REG(base) (base + 0x234) diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h index 4842cb97c892..0dfe789d8f02 100644 --- a/drivers/gpu/drm/i915/gvt/reg.h +++ b/drivers/gpu/drm/i915/gvt/reg.h @@ -72,4 +72,9 @@ #define FORCEWAKE_ACK_MEDIA_GEN9_REG 0x0D88 #define FORCEWAKE_ACK_HSW_REG 0x130044 +#define RB_HEAD_OFF_MASK ((1U << 21) - (1U << 2)) +#define RB_TAIL_OFF_MASK ((1U << 21) - (1U << 3)) +#define RB_TAIL_SIZE_MASK ((1U << 21) - (1U << 12)) +#define _RING_CTL_BUF_SIZE(ctl) (((ctl) & RB_TAIL_SIZE_MASK) + GTT_PAGE_SIZE) + #endif diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h new file mode 100644 index 000000000000..8884749f0bd4 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -0,0 +1,64 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _GVT_SCHEDULER_H_ +#define _GVT_SCHEDULER_H_ + +struct intel_gvt_workload_scheduler { + struct list_head workload_q_head[I915_NUM_ENGINES]; +}; + +struct intel_vgpu_workload { + struct intel_vgpu *vgpu; + int ring_id; + struct drm_i915_gem_request *req; + /* if this workload has been dispatched to i915? */ + bool dispatched; + int status; + + struct intel_vgpu_mm *shadow_mm; + + /* different submission model may need different handler */ + int (*prepare)(struct intel_vgpu_workload *); + int (*complete)(struct intel_vgpu_workload *); + struct list_head list; + + /* execlist context information */ + struct execlist_ctx_descriptor_format ctx_desc; + struct execlist_ring_context *ring_context; + unsigned long rb_head, rb_tail, rb_ctl, rb_start; + struct intel_vgpu_elsp_dwords elsp_dwords; + bool emulate_schedule_in; + atomic_t shadow_ctx_active; + wait_queue_head_t shadow_ctx_status_wq; + u64 ring_context_gpa; +}; + +#define workload_q_head(vgpu, ring_id) \ + (&(vgpu->workload_q_head[ring_id])) + +#define queue_workload(workload) \ + list_add_tail(&workload->list, \ + workload_q_head(workload->vgpu, workload->ring_id)) + +#endif diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index e806b0e4035a..705a23c1ed85 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -146,6 +146,7 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) vgpu->active = false; idr_remove(&gvt->vgpu_idr, vgpu->id); + intel_vgpu_clean_execlist(vgpu); intel_vgpu_clean_display(vgpu); intel_vgpu_clean_opregion(vgpu); intel_vgpu_clean_gtt(vgpu); -- cgit v1.2.3 From e473405783c064a9d859d108010581bae8e9af40 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Sun, 1 May 2016 07:42:16 -0400 Subject: drm/i915/gvt: vGPU workload scheduler This patch introduces the vGPU workload scheduler routines. GVT workload scheduler is responsible for picking and executing GVT workload from current scheduled vGPU. Before the workload is submitted to host i915, the guest execlist context will be shadowed in the host GVT shadow context. the instructions in guest ring buffer will be copied into GVT shadow ring buffer. Then GVT-g workload scheduler will scan the instructions in guest ring buffer and submit it to host i915. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/debug.h | 3 + drivers/gpu/drm/i915/gvt/execlist.c | 24 +- drivers/gpu/drm/i915/gvt/execlist.h | 3 + drivers/gpu/drm/i915/gvt/gvt.c | 9 +- drivers/gpu/drm/i915/gvt/gvt.h | 3 + drivers/gpu/drm/i915/gvt/handlers.c | 25 +- drivers/gpu/drm/i915/gvt/scheduler.c | 554 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/scheduler.h | 39 ++- drivers/gpu/drm/i915/gvt/vgpu.c | 7 + 10 files changed, 661 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/scheduler.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index f15197390d76..2d1a5c398a18 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,7 +1,7 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ - execlist.o + execlist.o scheduler.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index a7e0e7956ee9..a3f49d544bdb 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -45,4 +45,7 @@ #define gvt_dbg_el(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: el: "fmt, ##args) +#define gvt_dbg_sched(fmt, args...) \ + DRM_DEBUG_DRIVER("gvt: sched: "fmt, ##args) + #endif diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index f149847cbd17..5ae738e16678 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -394,7 +394,7 @@ static int complete_execlist_workload(struct intel_vgpu_workload *workload) gvt_dbg_el("complete workload %p status %d\n", workload, workload->status); - if (workload->status) + if (workload->status || vgpu->resetting) goto out; if (!list_empty(workload_q_head(vgpu, workload->ring_id))) { @@ -672,3 +672,25 @@ int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) return 0; } + +void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu, + unsigned long ring_bitmap) +{ + int bit; + struct list_head *pos, *n; + struct intel_vgpu_workload *workload = NULL; + + for_each_set_bit(bit, &ring_bitmap, sizeof(ring_bitmap) * 8) { + if (bit >= I915_NUM_ENGINES) + break; + /* free the unsubmited workload in the queue */ + list_for_each_safe(pos, n, &vgpu->workload_q_head[bit]) { + workload = container_of(pos, + struct intel_vgpu_workload, list); + list_del_init(&workload->list); + free_workload(workload); + } + + init_vgpu_execlist(vgpu, bit); + } +} diff --git a/drivers/gpu/drm/i915/gvt/execlist.h b/drivers/gpu/drm/i915/gvt/execlist.h index 13614fb4e572..635f31c6dcc1 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.h +++ b/drivers/gpu/drm/i915/gvt/execlist.h @@ -182,4 +182,7 @@ int intel_vgpu_init_execlist(struct intel_vgpu *vgpu); int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id); +void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu, + unsigned long ring_bitmap); + #endif /*_GVT_EXECLIST_H_*/ diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 27e1dd9a2570..5bf8488beaef 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -177,6 +177,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) return; clean_service_thread(gvt); + intel_gvt_clean_workload_scheduler(gvt); intel_gvt_clean_opregion(gvt); intel_gvt_clean_gtt(gvt); intel_gvt_clean_irq(gvt); @@ -239,14 +240,20 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (ret) goto out_clean_gtt; - ret = init_service_thread(gvt); + ret = intel_gvt_init_workload_scheduler(gvt); if (ret) goto out_clean_opregion; + ret = init_service_thread(gvt); + if (ret) + goto out_clean_workload_scheduler; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; +out_clean_workload_scheduler: + intel_gvt_clean_workload_scheduler(gvt); out_clean_opregion: intel_gvt_clean_opregion(gvt); out_clean_gtt: diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 414163695e07..ae716cf22f69 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -151,6 +151,9 @@ struct intel_vgpu { struct intel_vgpu_execlist execlist[I915_NUM_ENGINES]; struct list_head workload_q_head[I915_NUM_ENGINES]; struct kmem_cache *workloads; + atomic_t running_workload_num; + struct i915_gem_context *shadow_ctx; + struct notifier_block shadow_ctx_notifier_block; }; struct intel_gvt_gm { diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 970804aed381..04da35c2600a 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -227,11 +227,32 @@ static int mul_force_wake_write(struct intel_vgpu *vgpu, return 0; } +static int handle_device_reset(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes, unsigned long bitmap) +{ + struct intel_gvt_workload_scheduler *scheduler = + &vgpu->gvt->scheduler; + + vgpu->resetting = true; + + if (scheduler->current_vgpu == vgpu) { + mutex_unlock(&vgpu->gvt->lock); + intel_gvt_wait_vgpu_idle(vgpu); + mutex_lock(&vgpu->gvt->lock); + } + + intel_vgpu_reset_execlist(vgpu, bitmap); + + vgpu->resetting = false; + + return 0; +} + static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { u32 data; - u32 bitmap = 0; + u64 bitmap = 0; data = vgpu_vreg(vgpu, offset); @@ -260,7 +281,7 @@ static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, if (HAS_BSD2(vgpu->gvt->dev_priv)) bitmap |= (1 << VCS2); } - return 0; + return handle_device_reset(vgpu, offset, p_data, bytes, bitmap); } static int gmbus_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c new file mode 100644 index 000000000000..2302a97cebf6 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -0,0 +1,554 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Zhi Wang + * + * Contributors: + * Ping Gao + * Tina Zhang + * Chanbin Du + * Min He + * Bing Niu + * Zhenyu Wang + * + */ + +#include "i915_drv.h" + +#include + +#define RING_CTX_OFF(x) \ + offsetof(struct execlist_ring_context, x) + +void set_context_pdp_root_pointer(struct execlist_ring_context *ring_context, + u32 pdp[8]) +{ + struct execlist_mmio_pair *pdp_pair = &ring_context->pdp3_UDW; + int i; + + for (i = 0; i < 8; i++) + pdp_pair[i].val = pdp[7 - i]; +} + +static int populate_shadow_context(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + int ring_id = workload->ring_id; + struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; + struct drm_i915_gem_object *ctx_obj = + shadow_ctx->engine[ring_id].state->obj; + struct execlist_ring_context *shadow_ring_context; + struct page *page; + void *dst; + unsigned long context_gpa, context_page_num; + int i; + + gvt_dbg_sched("ring id %d workload lrca %x", ring_id, + workload->ctx_desc.lrca); + + context_page_num = intel_lr_context_size( + &gvt->dev_priv->engine[ring_id]); + + context_page_num = context_page_num >> PAGE_SHIFT; + + if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS) + context_page_num = 19; + + i = 2; + + while (i < context_page_num) { + context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, + (u32)((workload->ctx_desc.lrca + i) << + GTT_PAGE_SHIFT)); + if (context_gpa == INTEL_GVT_INVALID_ADDR) { + gvt_err("Invalid guest context descriptor\n"); + return -EINVAL; + } + + page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i); + dst = kmap_atomic(page); + intel_gvt_hypervisor_read_gpa(vgpu, context_gpa, dst, + GTT_PAGE_SIZE); + kunmap_atomic(dst); + i++; + } + + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); + shadow_ring_context = kmap_atomic(page); + +#define COPY_REG(name) \ + intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \ + + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4) + + COPY_REG(ctx_ctrl); + COPY_REG(ctx_timestamp); + + if (ring_id == RCS) { + COPY_REG(bb_per_ctx_ptr); + COPY_REG(rcs_indirect_ctx); + COPY_REG(rcs_indirect_ctx_offset); + } +#undef COPY_REG + + set_context_pdp_root_pointer(shadow_ring_context, + workload->shadow_mm->shadow_page_table); + + intel_gvt_hypervisor_read_gpa(vgpu, + workload->ring_context_gpa + + sizeof(*shadow_ring_context), + (void *)shadow_ring_context + + sizeof(*shadow_ring_context), + GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); + + kunmap_atomic(shadow_ring_context); + return 0; +} + +static int shadow_context_status_change(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct intel_vgpu *vgpu = container_of(nb, + struct intel_vgpu, shadow_ctx_notifier_block); + struct drm_i915_gem_request *req = + (struct drm_i915_gem_request *)data; + struct intel_gvt_workload_scheduler *scheduler = + &vgpu->gvt->scheduler; + struct intel_vgpu_workload *workload = + scheduler->current_workload[req->engine->id]; + + switch (action) { + case INTEL_CONTEXT_SCHEDULE_IN: + atomic_set(&workload->shadow_ctx_active, 1); + break; + case INTEL_CONTEXT_SCHEDULE_OUT: + atomic_set(&workload->shadow_ctx_active, 0); + break; + default: + WARN_ON(1); + return NOTIFY_OK; + } + wake_up(&workload->shadow_ctx_status_wq); + return NOTIFY_OK; +} + +static int dispatch_workload(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + int ring_id = workload->ring_id; + struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; + struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; + int ret; + + gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n", + ring_id, workload); + + shadow_ctx->desc_template = workload->ctx_desc.addressing_mode << + GEN8_CTX_ADDRESSING_MODE_SHIFT; + + workload->req = i915_gem_request_alloc(&dev_priv->engine[ring_id], + shadow_ctx); + if (IS_ERR_OR_NULL(workload->req)) { + gvt_err("fail to allocate gem request\n"); + workload->status = PTR_ERR(workload->req); + workload->req = NULL; + return workload->status; + } + + gvt_dbg_sched("ring id %d get i915 gem request %p\n", + ring_id, workload->req); + + mutex_lock(&gvt->lock); + + ret = populate_shadow_context(workload); + if (ret) + goto err; + + if (workload->prepare) { + ret = workload->prepare(workload); + if (ret) + goto err; + } + + mutex_unlock(&gvt->lock); + + gvt_dbg_sched("ring id %d submit workload to i915 %p\n", + ring_id, workload->req); + + i915_add_request_no_flush(workload->req); + + workload->dispatched = true; + return 0; +err: + workload->status = ret; + if (workload->req) + workload->req = NULL; + + mutex_unlock(&gvt->lock); + return ret; +} + +static struct intel_vgpu_workload *pick_next_workload( + struct intel_gvt *gvt, int ring_id) +{ + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; + struct intel_vgpu_workload *workload = NULL; + + mutex_lock(&gvt->lock); + + /* + * no current vgpu / will be scheduled out / no workload + * bail out + */ + if (!scheduler->current_vgpu) { + gvt_dbg_sched("ring id %d stop - no current vgpu\n", ring_id); + goto out; + } + + if (scheduler->need_reschedule) { + gvt_dbg_sched("ring id %d stop - will reschedule\n", ring_id); + goto out; + } + + if (list_empty(workload_q_head(scheduler->current_vgpu, ring_id))) { + gvt_dbg_sched("ring id %d stop - no available workload\n", + ring_id); + goto out; + } + + /* + * still have current workload, maybe the workload disptacher + * fail to submit it for some reason, resubmit it. + */ + if (scheduler->current_workload[ring_id]) { + workload = scheduler->current_workload[ring_id]; + gvt_dbg_sched("ring id %d still have current workload %p\n", + ring_id, workload); + goto out; + } + + /* + * pick a workload as current workload + * once current workload is set, schedule policy routines + * will wait the current workload is finished when trying to + * schedule out a vgpu. + */ + scheduler->current_workload[ring_id] = container_of( + workload_q_head(scheduler->current_vgpu, ring_id)->next, + struct intel_vgpu_workload, list); + + workload = scheduler->current_workload[ring_id]; + + gvt_dbg_sched("ring id %d pick new workload %p\n", ring_id, workload); + + atomic_inc(&workload->vgpu->running_workload_num); +out: + mutex_unlock(&gvt->lock); + return workload; +} + +static void update_guest_context(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + int ring_id = workload->ring_id; + struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; + struct drm_i915_gem_object *ctx_obj = + shadow_ctx->engine[ring_id].state->obj; + struct execlist_ring_context *shadow_ring_context; + struct page *page; + void *src; + unsigned long context_gpa, context_page_num; + int i; + + gvt_dbg_sched("ring id %d workload lrca %x\n", ring_id, + workload->ctx_desc.lrca); + + context_page_num = intel_lr_context_size( + &gvt->dev_priv->engine[ring_id]); + + context_page_num = context_page_num >> PAGE_SHIFT; + + if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS) + context_page_num = 19; + + i = 2; + + while (i < context_page_num) { + context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, + (u32)((workload->ctx_desc.lrca + i) << + GTT_PAGE_SHIFT)); + if (context_gpa == INTEL_GVT_INVALID_ADDR) { + gvt_err("invalid guest context descriptor\n"); + return; + } + + page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i); + src = kmap_atomic(page); + intel_gvt_hypervisor_write_gpa(vgpu, context_gpa, src, + GTT_PAGE_SIZE); + kunmap_atomic(src); + i++; + } + + intel_gvt_hypervisor_write_gpa(vgpu, workload->ring_context_gpa + + RING_CTX_OFF(ring_header.val), &workload->rb_tail, 4); + + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); + shadow_ring_context = kmap_atomic(page); + +#define COPY_REG(name) \ + intel_gvt_hypervisor_write_gpa(vgpu, workload->ring_context_gpa + \ + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4) + + COPY_REG(ctx_ctrl); + COPY_REG(ctx_timestamp); + +#undef COPY_REG + + intel_gvt_hypervisor_write_gpa(vgpu, + workload->ring_context_gpa + + sizeof(*shadow_ring_context), + (void *)shadow_ring_context + + sizeof(*shadow_ring_context), + GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); + + kunmap_atomic(shadow_ring_context); +} + +static void complete_current_workload(struct intel_gvt *gvt, int ring_id) +{ + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; + struct intel_vgpu_workload *workload; + + mutex_lock(&gvt->lock); + + workload = scheduler->current_workload[ring_id]; + + if (!workload->status && !workload->vgpu->resetting) { + wait_event(workload->shadow_ctx_status_wq, + !atomic_read(&workload->shadow_ctx_active)); + + update_guest_context(workload); + } + + gvt_dbg_sched("ring id %d complete workload %p status %d\n", + ring_id, workload, workload->status); + + scheduler->current_workload[ring_id] = NULL; + + atomic_dec(&workload->vgpu->running_workload_num); + + list_del_init(&workload->list); + workload->complete(workload); + + wake_up(&scheduler->workload_complete_wq); + mutex_unlock(&gvt->lock); +} + +struct workload_thread_param { + struct intel_gvt *gvt; + int ring_id; +}; + +static int workload_thread(void *priv) +{ + struct workload_thread_param *p = (struct workload_thread_param *)priv; + struct intel_gvt *gvt = p->gvt; + int ring_id = p->ring_id; + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; + struct intel_vgpu_workload *workload = NULL; + int ret; + bool need_force_wake = IS_SKYLAKE(gvt->dev_priv); + + kfree(p); + + gvt_dbg_core("workload thread for ring %d started\n", ring_id); + + while (!kthread_should_stop()) { + ret = wait_event_interruptible(scheduler->waitq[ring_id], + kthread_should_stop() || + (workload = pick_next_workload(gvt, ring_id))); + + WARN_ON_ONCE(ret); + + if (kthread_should_stop()) + break; + + gvt_dbg_sched("ring id %d next workload %p vgpu %d\n", + workload->ring_id, workload, + workload->vgpu->id); + + intel_runtime_pm_get(gvt->dev_priv); + + /* + * Always take i915 big lock first + */ + ret = i915_mutex_lock_interruptible(&gvt->dev_priv->drm); + if (ret < 0) { + gvt_err("i915 submission is not available, retry\n"); + schedule_timeout(1); + continue; + } + + gvt_dbg_sched("ring id %d will dispatch workload %p\n", + workload->ring_id, workload); + + if (need_force_wake) + intel_uncore_forcewake_get(gvt->dev_priv, + FORCEWAKE_ALL); + + ret = dispatch_workload(workload); + if (ret) { + gvt_err("fail to dispatch workload, skip\n"); + goto complete; + } + + gvt_dbg_sched("ring id %d wait workload %p\n", + workload->ring_id, workload); + + workload->status = i915_wait_request(workload->req, + I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, + NULL, NULL); + if (workload->status != 0) + gvt_err("fail to wait workload, skip\n"); + +complete: + gvt_dbg_sched("will complete workload %p\n, status: %d\n", + workload, workload->status); + + complete_current_workload(gvt, ring_id); + + if (need_force_wake) + intel_uncore_forcewake_put(gvt->dev_priv, + FORCEWAKE_ALL); + + mutex_unlock(&gvt->dev_priv->drm.struct_mutex); + + intel_runtime_pm_put(gvt->dev_priv); + } + return 0; +} + +void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; + + if (atomic_read(&vgpu->running_workload_num)) { + gvt_dbg_sched("wait vgpu idle\n"); + + wait_event(scheduler->workload_complete_wq, + !atomic_read(&vgpu->running_workload_num)); + } +} + +void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt) +{ + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; + int i; + + gvt_dbg_core("clean workload scheduler\n"); + + for (i = 0; i < I915_NUM_ENGINES; i++) { + if (scheduler->thread[i]) { + kthread_stop(scheduler->thread[i]); + scheduler->thread[i] = NULL; + } + } +} + +int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt) +{ + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; + struct workload_thread_param *param = NULL; + int ret; + int i; + + gvt_dbg_core("init workload scheduler\n"); + + init_waitqueue_head(&scheduler->workload_complete_wq); + + for (i = 0; i < I915_NUM_ENGINES; i++) { + init_waitqueue_head(&scheduler->waitq[i]); + + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) { + ret = -ENOMEM; + goto err; + } + + param->gvt = gvt; + param->ring_id = i; + + scheduler->thread[i] = kthread_run(workload_thread, param, + "gvt workload %d", i); + if (IS_ERR(scheduler->thread[i])) { + gvt_err("fail to create workload thread\n"); + ret = PTR_ERR(scheduler->thread[i]); + goto err; + } + } + return 0; +err: + intel_gvt_clean_workload_scheduler(gvt); + kfree(param); + param = NULL; + return ret; +} + +void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + + atomic_notifier_chain_unregister(&vgpu->shadow_ctx->status_notifier, + &vgpu->shadow_ctx_notifier_block); + + mutex_lock(&dev_priv->drm.struct_mutex); + + /* a little hacky to mark as ctx closed */ + vgpu->shadow_ctx->closed = true; + i915_gem_context_put(vgpu->shadow_ctx); + + mutex_unlock(&dev_priv->drm.struct_mutex); +} + +int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu) +{ + atomic_set(&vgpu->running_workload_num, 0); + + vgpu->shadow_ctx = i915_gem_context_create_gvt( + &vgpu->gvt->dev_priv->drm); + if (IS_ERR(vgpu->shadow_ctx)) + return PTR_ERR(vgpu->shadow_ctx); + + vgpu->shadow_ctx->engine[RCS].initialised = true; + + vgpu->shadow_ctx_notifier_block.notifier_call = + shadow_context_status_change; + + atomic_notifier_chain_register(&vgpu->shadow_ctx->status_notifier, + &vgpu->shadow_ctx_notifier_block); + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 8884749f0bd4..9206cc02c8a8 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -19,13 +19,32 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. + * + * Authors: + * Zhi Wang + * + * Contributors: + * Ping Gao + * Tina Zhang + * Chanbin Du + * Min He + * Bing Niu + * Zhenyu Wang + * */ #ifndef _GVT_SCHEDULER_H_ #define _GVT_SCHEDULER_H_ struct intel_gvt_workload_scheduler { - struct list_head workload_q_head[I915_NUM_ENGINES]; + struct intel_vgpu *current_vgpu; + struct intel_vgpu *next_vgpu; + struct intel_vgpu_workload *current_workload[I915_NUM_ENGINES]; + bool need_reschedule; + + wait_queue_head_t workload_complete_wq; + struct task_struct *thread[I915_NUM_ENGINES]; + wait_queue_head_t waitq[I915_NUM_ENGINES]; }; struct intel_vgpu_workload { @@ -47,6 +66,7 @@ struct intel_vgpu_workload { struct execlist_ctx_descriptor_format ctx_desc; struct execlist_ring_context *ring_context; unsigned long rb_head, rb_tail, rb_ctl, rb_start; + bool restore_inhibit; struct intel_vgpu_elsp_dwords elsp_dwords; bool emulate_schedule_in; atomic_t shadow_ctx_active; @@ -57,8 +77,21 @@ struct intel_vgpu_workload { #define workload_q_head(vgpu, ring_id) \ (&(vgpu->workload_q_head[ring_id])) -#define queue_workload(workload) \ +#define queue_workload(workload) do { \ list_add_tail(&workload->list, \ - workload_q_head(workload->vgpu, workload->ring_id)) + workload_q_head(workload->vgpu, workload->ring_id)); \ + wake_up(&workload->vgpu->gvt-> \ + scheduler.waitq[workload->ring_id]); \ +} while (0) + +int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt); + +void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt); + +void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu); + +int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu); + +void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu); #endif diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 705a23c1ed85..609ec55bbf5f 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -146,6 +146,7 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) vgpu->active = false; idr_remove(&gvt->vgpu_idr, vgpu->id); + intel_vgpu_clean_gvt_context(vgpu); intel_vgpu_clean_execlist(vgpu); intel_vgpu_clean_display(vgpu); intel_vgpu_clean_opregion(vgpu); @@ -226,11 +227,17 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, if (ret) goto out_clean_display; + ret = intel_vgpu_init_gvt_context(vgpu); + if (ret) + goto out_clean_execlist; + vgpu->active = true; mutex_unlock(&gvt->lock); return vgpu; +out_clean_execlist: + intel_vgpu_clean_execlist(vgpu); out_clean_display: intel_vgpu_clean_display(vgpu); out_clean_opregion: -- cgit v1.2.3 From 4b63960ebd3f4c41caca6a8dca68751b34e61e9b Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Sun, 1 May 2016 17:09:58 -0400 Subject: drm/i915/gvt: vGPU schedule policy framework This patch introduces a vGPU schedule policy framework, with a timer based schedule policy module for now Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/gvt.c | 9 +- drivers/gpu/drm/i915/gvt/gvt.h | 2 + drivers/gpu/drm/i915/gvt/handlers.c | 27 ++- drivers/gpu/drm/i915/gvt/sched_policy.c | 291 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/sched_policy.h | 58 +++++++ drivers/gpu/drm/i915/gvt/scheduler.h | 3 + drivers/gpu/drm/i915/gvt/vgpu.c | 14 ++ 8 files changed, 402 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/sched_policy.c create mode 100644 drivers/gpu/drm/i915/gvt/sched_policy.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 2d1a5c398a18..21000b183b95 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,7 +1,7 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ - execlist.o scheduler.o + execlist.o scheduler.o sched_policy.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 5bf8488beaef..7f13efbbd93a 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -177,6 +177,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) return; clean_service_thread(gvt); + intel_gvt_clean_sched_policy(gvt); intel_gvt_clean_workload_scheduler(gvt); intel_gvt_clean_opregion(gvt); intel_gvt_clean_gtt(gvt); @@ -244,14 +245,20 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (ret) goto out_clean_opregion; - ret = init_service_thread(gvt); + ret = intel_gvt_init_sched_policy(gvt); if (ret) goto out_clean_workload_scheduler; + ret = init_service_thread(gvt); + if (ret) + goto out_clean_sched_policy; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; +out_clean_sched_policy: + intel_gvt_clean_sched_policy(gvt); out_clean_workload_scheduler: intel_gvt_clean_workload_scheduler(gvt); out_clean_opregion: diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index ae716cf22f69..6d37468631b7 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -43,6 +43,7 @@ #include "edid.h" #include "execlist.h" #include "scheduler.h" +#include "sched_policy.h" #define GVT_MAX_VGPU 8 @@ -139,6 +140,7 @@ struct intel_vgpu { unsigned long handle; /* vGPU handle used by hypervisor MPT modules */ bool active; bool resetting; + void *sched_data; struct intel_vgpu_fence fence; struct intel_vgpu_gm gm; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 04da35c2600a..8e8bda584c94 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -235,6 +235,7 @@ static int handle_device_reset(struct intel_vgpu *vgpu, unsigned int offset, vgpu->resetting = true; + intel_vgpu_stop_schedule(vgpu); if (scheduler->current_vgpu == vgpu) { mutex_unlock(&vgpu->gvt->lock); intel_gvt_wait_vgpu_idle(vgpu); @@ -1317,6 +1318,28 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, return 0; } +static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, + void *p_data, unsigned int bytes) +{ + u32 data = *(u32 *)p_data; + int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); + bool enable_execlist; + + write_vreg(vgpu, offset, p_data, bytes); + if ((data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)) + || (data & _MASKED_BIT_DISABLE(GFX_RUN_LIST_ENABLE))) { + enable_execlist = !!(data & GFX_RUN_LIST_ENABLE); + + gvt_dbg_core("EXECLIST %s on ring %d\n", + (enable_execlist ? "enabling" : "disabling"), + ring_id); + + if (enable_execlist) + intel_vgpu_start_schedule(vgpu); + } + return 0; +} + #define MMIO_F(reg, s, f, am, rm, d, r, w) do { \ ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \ f, s, am, rm, d, r, w); \ @@ -1398,7 +1421,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) /* RING MODE */ #define RING_REG(base) (base + 0x29c) - MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, NULL); + MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, ring_mode_mmio_write); #undef RING_REG MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK, NULL, NULL); @@ -2213,7 +2236,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) MMIO_D(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS); MMIO_D(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS); MMIO_D(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS); - MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); + MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, ring_mode_mmio_write); MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, NULL, NULL); MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c new file mode 100644 index 000000000000..c607354c3798 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -0,0 +1,291 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Anhua Xu + * Kevin Tian + * + * Contributors: + * Min He + * Bing Niu + * Zhi Wang + * + */ + +#include "i915_drv.h" + +static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu) +{ + struct intel_vgpu_execlist *execlist; + int i; + + for (i = 0; i < I915_NUM_ENGINES; i++) { + execlist = &vgpu->execlist[i]; + if (!list_empty(workload_q_head(vgpu, i))) + return true; + } + + return false; +} + +static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) +{ + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; + int i; + + /* no target to schedule */ + if (!scheduler->next_vgpu) + return; + + gvt_dbg_sched("try to schedule next vgpu %d\n", + scheduler->next_vgpu->id); + + /* + * after the flag is set, workload dispatch thread will + * stop dispatching workload for current vgpu + */ + scheduler->need_reschedule = true; + + /* still have uncompleted workload? */ + for (i = 0; i < I915_NUM_ENGINES; i++) { + if (scheduler->current_workload[i]) { + gvt_dbg_sched("still have running workload\n"); + return; + } + } + + gvt_dbg_sched("switch to next vgpu %d\n", + scheduler->next_vgpu->id); + + /* switch current vgpu */ + scheduler->current_vgpu = scheduler->next_vgpu; + scheduler->next_vgpu = NULL; + + scheduler->need_reschedule = false; + + /* wake up workload dispatch thread */ + for (i = 0; i < I915_NUM_ENGINES; i++) + wake_up(&scheduler->waitq[i]); +} + +struct tbs_vgpu_data { + struct list_head list; + struct intel_vgpu *vgpu; + /* put some per-vgpu sched stats here */ +}; + +struct tbs_sched_data { + struct intel_gvt *gvt; + struct delayed_work work; + unsigned long period; + struct list_head runq_head; +}; + +#define GVT_DEFAULT_TIME_SLICE (1 * HZ / 1000) + +static void tbs_sched_func(struct work_struct *work) +{ + struct tbs_sched_data *sched_data = container_of(work, + struct tbs_sched_data, work.work); + struct tbs_vgpu_data *vgpu_data; + + struct intel_gvt *gvt = sched_data->gvt; + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; + + struct intel_vgpu *vgpu = NULL; + struct list_head *pos, *head; + + mutex_lock(&gvt->lock); + + /* no vgpu or has already had a target */ + if (list_empty(&sched_data->runq_head) || scheduler->next_vgpu) + goto out; + + if (scheduler->current_vgpu) { + vgpu_data = scheduler->current_vgpu->sched_data; + head = &vgpu_data->list; + } else { + gvt_dbg_sched("no current vgpu search from q head\n"); + head = &sched_data->runq_head; + } + + /* search a vgpu with pending workload */ + list_for_each(pos, head) { + if (pos == &sched_data->runq_head) + continue; + + vgpu_data = container_of(pos, struct tbs_vgpu_data, list); + if (!vgpu_has_pending_workload(vgpu_data->vgpu)) + continue; + + vgpu = vgpu_data->vgpu; + break; + } + + if (vgpu) { + scheduler->next_vgpu = vgpu; + gvt_dbg_sched("pick next vgpu %d\n", vgpu->id); + } +out: + if (scheduler->next_vgpu) { + gvt_dbg_sched("try to schedule next vgpu %d\n", + scheduler->next_vgpu->id); + try_to_schedule_next_vgpu(gvt); + } + + /* + * still have vgpu on runq + * or last schedule haven't finished due to running workload + */ + if (!list_empty(&sched_data->runq_head) || scheduler->next_vgpu) + schedule_delayed_work(&sched_data->work, sched_data->period); + + mutex_unlock(&gvt->lock); +} + +static int tbs_sched_init(struct intel_gvt *gvt) +{ + struct intel_gvt_workload_scheduler *scheduler = + &gvt->scheduler; + + struct tbs_sched_data *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + INIT_LIST_HEAD(&data->runq_head); + INIT_DELAYED_WORK(&data->work, tbs_sched_func); + data->period = GVT_DEFAULT_TIME_SLICE; + data->gvt = gvt; + + scheduler->sched_data = data; + return 0; +} + +static void tbs_sched_clean(struct intel_gvt *gvt) +{ + struct intel_gvt_workload_scheduler *scheduler = + &gvt->scheduler; + struct tbs_sched_data *data = scheduler->sched_data; + + cancel_delayed_work(&data->work); + kfree(data); + scheduler->sched_data = NULL; +} + +static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu) +{ + struct tbs_vgpu_data *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->vgpu = vgpu; + INIT_LIST_HEAD(&data->list); + + vgpu->sched_data = data; + return 0; +} + +static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu) +{ + kfree(vgpu->sched_data); + vgpu->sched_data = NULL; +} + +static void tbs_sched_start_schedule(struct intel_vgpu *vgpu) +{ + struct tbs_sched_data *sched_data = vgpu->gvt->scheduler.sched_data; + struct tbs_vgpu_data *vgpu_data = vgpu->sched_data; + + if (!list_empty(&vgpu_data->list)) + return; + + list_add_tail(&vgpu_data->list, &sched_data->runq_head); + schedule_delayed_work(&sched_data->work, sched_data->period); +} + +static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu) +{ + struct tbs_vgpu_data *vgpu_data = vgpu->sched_data; + + list_del_init(&vgpu_data->list); +} + +struct intel_gvt_sched_policy_ops tbs_schedule_ops = { + .init = tbs_sched_init, + .clean = tbs_sched_clean, + .init_vgpu = tbs_sched_init_vgpu, + .clean_vgpu = tbs_sched_clean_vgpu, + .start_schedule = tbs_sched_start_schedule, + .stop_schedule = tbs_sched_stop_schedule, +}; + +int intel_gvt_init_sched_policy(struct intel_gvt *gvt) +{ + gvt->scheduler.sched_ops = &tbs_schedule_ops; + + return gvt->scheduler.sched_ops->init(gvt); +} + +void intel_gvt_clean_sched_policy(struct intel_gvt *gvt) +{ + gvt->scheduler.sched_ops->clean(gvt); +} + +int intel_vgpu_init_sched_policy(struct intel_vgpu *vgpu) +{ + return vgpu->gvt->scheduler.sched_ops->init_vgpu(vgpu); +} + +void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu) +{ + vgpu->gvt->scheduler.sched_ops->clean_vgpu(vgpu); +} + +void intel_vgpu_start_schedule(struct intel_vgpu *vgpu) +{ + gvt_dbg_core("vgpu%d: start schedule\n", vgpu->id); + + vgpu->gvt->scheduler.sched_ops->start_schedule(vgpu); +} + +void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) +{ + struct intel_gvt_workload_scheduler *scheduler = + &vgpu->gvt->scheduler; + + gvt_dbg_core("vgpu%d: stop schedule\n", vgpu->id); + + scheduler->sched_ops->stop_schedule(vgpu); + + if (scheduler->next_vgpu == vgpu) + scheduler->next_vgpu = NULL; + + if (scheduler->current_vgpu == vgpu) { + /* stop workload dispatching */ + scheduler->need_reschedule = true; + scheduler->current_vgpu = NULL; + } +} diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.h b/drivers/gpu/drm/i915/gvt/sched_policy.h new file mode 100644 index 000000000000..bb8b9097e41a --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/sched_policy.h @@ -0,0 +1,58 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Anhua Xu + * Kevin Tian + * + * Contributors: + * Min He + * Bing Niu + * Zhi Wang + * + */ + +#ifndef __GVT_SCHED_POLICY__ +#define __GVT_SCHED_POLICY__ + +struct intel_gvt_sched_policy_ops { + int (*init)(struct intel_gvt *gvt); + void (*clean)(struct intel_gvt *gvt); + int (*init_vgpu)(struct intel_vgpu *vgpu); + void (*clean_vgpu)(struct intel_vgpu *vgpu); + void (*start_schedule)(struct intel_vgpu *vgpu); + void (*stop_schedule)(struct intel_vgpu *vgpu); +}; + +int intel_gvt_init_sched_policy(struct intel_gvt *gvt); + +void intel_gvt_clean_sched_policy(struct intel_gvt *gvt); + +int intel_vgpu_init_sched_policy(struct intel_vgpu *vgpu); + +void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu); + +void intel_vgpu_start_schedule(struct intel_vgpu *vgpu); + +void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu); + +#endif diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 9206cc02c8a8..2500438d7aa7 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -45,6 +45,9 @@ struct intel_gvt_workload_scheduler { wait_queue_head_t workload_complete_wq; struct task_struct *thread[I915_NUM_ENGINES]; wait_queue_head_t waitq[I915_NUM_ENGINES]; + + void *sched_data; + struct intel_gvt_sched_policy_ops *sched_ops; }; struct intel_vgpu_workload { diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 609ec55bbf5f..c9b8e184f5cb 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -146,6 +146,14 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) vgpu->active = false; idr_remove(&gvt->vgpu_idr, vgpu->id); + if (atomic_read(&vgpu->running_workload_num)) { + mutex_unlock(&gvt->lock); + intel_gvt_wait_vgpu_idle(vgpu); + mutex_lock(&gvt->lock); + } + + intel_vgpu_stop_schedule(vgpu); + intel_vgpu_clean_sched_policy(vgpu); intel_vgpu_clean_gvt_context(vgpu); intel_vgpu_clean_execlist(vgpu); intel_vgpu_clean_display(vgpu); @@ -231,11 +239,17 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, if (ret) goto out_clean_execlist; + ret = intel_vgpu_init_sched_policy(vgpu); + if (ret) + goto out_clean_shadow_ctx; + vgpu->active = true; mutex_unlock(&gvt->lock); return vgpu; +out_clean_shadow_ctx: + intel_vgpu_clean_gvt_context(vgpu); out_clean_execlist: intel_vgpu_clean_execlist(vgpu); out_clean_display: -- cgit v1.2.3 From 178657139307126b22d226df0823223d6dfe91ba Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Sun, 1 May 2016 19:02:37 -0400 Subject: drm/i915/gvt: vGPU context switch As different VM may configure different render MMIOs when executing workload, to schedule workloads between different VM, the render MMIOs have to be switched. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/debug.h | 3 + drivers/gpu/drm/i915/gvt/gvt.h | 2 + drivers/gpu/drm/i915/gvt/handlers.c | 41 ++++- drivers/gpu/drm/i915/gvt/render.c | 290 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/render.h | 43 ++++++ drivers/gpu/drm/i915/gvt/scheduler.c | 4 + drivers/gpu/drm/i915/gvt/vgpu.c | 1 + 8 files changed, 380 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/render.c create mode 100644 drivers/gpu/drm/i915/gvt/render.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index 21000b183b95..e05556cd0f78 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,7 +1,7 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ - execlist.o scheduler.o sched_policy.o + execlist.o scheduler.o sched_policy.o render.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index a3f49d544bdb..76e50eeef7f3 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -48,4 +48,7 @@ #define gvt_dbg_sched(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: sched: "fmt, ##args) +#define gvt_dbg_render(fmt, args...) \ + DRM_DEBUG_DRIVER("gvt: render: "fmt, ##args) + #endif diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 6d37468631b7..dfe398d47496 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -44,6 +44,7 @@ #include "execlist.h" #include "scheduler.h" #include "sched_policy.h" +#include "render.h" #define GVT_MAX_VGPU 8 @@ -154,6 +155,7 @@ struct intel_vgpu { struct list_head workload_q_head[I915_NUM_ENGINES]; struct kmem_cache *workloads; atomic_t running_workload_num; + DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); struct i915_gem_context *shadow_ctx; struct notifier_block shadow_ctx_notifier_block; }; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 8e8bda584c94..d59a934b6e32 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1340,6 +1340,37 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, return 0; } +static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu, + unsigned int offset, void *p_data, unsigned int bytes) +{ + int rc = 0; + unsigned int id = 0; + + switch (offset) { + case 0x4260: + id = RCS; + break; + case 0x4264: + id = VCS; + break; + case 0x4268: + id = VCS2; + break; + case 0x426c: + id = BCS; + break; + case 0x4270: + id = VECS; + break; + default: + rc = -EINVAL; + break; + } + set_bit(id, (void *)vgpu->tlb_handle_pending); + + return rc; +} + #define MMIO_F(reg, s, f, am, rm, d, r, w) do { \ ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \ f, s, am, rm, d, r, w); \ @@ -2147,11 +2178,11 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_F(CL_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); MMIO_F(PS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); MMIO_F(PS_DEPTH_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); - MMIO_DH(0x4260, D_BDW_PLUS, NULL, NULL); - MMIO_DH(0x4264, D_BDW_PLUS, NULL, NULL); - MMIO_DH(0x4268, D_BDW_PLUS, NULL, NULL); - MMIO_DH(0x426c, D_BDW_PLUS, NULL, NULL); - MMIO_DH(0x4270, D_BDW_PLUS, NULL, NULL); + MMIO_DH(0x4260, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); + MMIO_DH(0x4264, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); + MMIO_DH(0x4268, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); + MMIO_DH(0x426c, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); + MMIO_DH(0x4270, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); MMIO_DFH(0x4094, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); return 0; diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c new file mode 100644 index 000000000000..f54ab8540b12 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -0,0 +1,290 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eddie Dong + * Kevin Tian + * + * Contributors: + * Zhi Wang + * Changbin Du + * Zhenyu Wang + * Tina Zhang + * Bing Niu + * + */ + +#include "i915_drv.h" + +struct render_mmio { + int ring_id; + i915_reg_t reg; + u32 mask; + bool in_context; + u32 value; +}; + +static struct render_mmio gen8_render_mmio_list[] = { + {RCS, _MMIO(0x229c), 0xffff, false}, + {RCS, _MMIO(0x2248), 0x0, false}, + {RCS, _MMIO(0x2098), 0x0, false}, + {RCS, _MMIO(0x20c0), 0xffff, true}, + {RCS, _MMIO(0x24d0), 0, false}, + {RCS, _MMIO(0x24d4), 0, false}, + {RCS, _MMIO(0x24d8), 0, false}, + {RCS, _MMIO(0x24dc), 0, false}, + {RCS, _MMIO(0x7004), 0xffff, true}, + {RCS, _MMIO(0x7008), 0xffff, true}, + {RCS, _MMIO(0x7000), 0xffff, true}, + {RCS, _MMIO(0x7010), 0xffff, true}, + {RCS, _MMIO(0x7300), 0xffff, true}, + {RCS, _MMIO(0x83a4), 0xffff, true}, + + {BCS, _MMIO(0x2229c), 0xffff, false}, + {BCS, _MMIO(0x2209c), 0xffff, false}, + {BCS, _MMIO(0x220c0), 0xffff, false}, + {BCS, _MMIO(0x22098), 0x0, false}, + {BCS, _MMIO(0x22028), 0x0, false}, +}; + +static struct render_mmio gen9_render_mmio_list[] = { + {RCS, _MMIO(0x229c), 0xffff, false}, + {RCS, _MMIO(0x2248), 0x0, false}, + {RCS, _MMIO(0x2098), 0x0, false}, + {RCS, _MMIO(0x20c0), 0xffff, true}, + {RCS, _MMIO(0x24d0), 0, false}, + {RCS, _MMIO(0x24d4), 0, false}, + {RCS, _MMIO(0x24d8), 0, false}, + {RCS, _MMIO(0x24dc), 0, false}, + {RCS, _MMIO(0x7004), 0xffff, true}, + {RCS, _MMIO(0x7008), 0xffff, true}, + {RCS, _MMIO(0x7000), 0xffff, true}, + {RCS, _MMIO(0x7010), 0xffff, true}, + {RCS, _MMIO(0x7300), 0xffff, true}, + {RCS, _MMIO(0x83a4), 0xffff, true}, + + {RCS, _MMIO(0x40e0), 0, false}, + {RCS, _MMIO(0x40e4), 0, false}, + {RCS, _MMIO(0x2580), 0xffff, true}, + {RCS, _MMIO(0x7014), 0xffff, true}, + {RCS, _MMIO(0x20ec), 0xffff, false}, + {RCS, _MMIO(0xb118), 0, false}, + {RCS, _MMIO(0xe100), 0xffff, true}, + {RCS, _MMIO(0xe180), 0xffff, true}, + {RCS, _MMIO(0xe184), 0xffff, true}, + {RCS, _MMIO(0xe188), 0xffff, true}, + {RCS, _MMIO(0xe194), 0xffff, true}, + {RCS, _MMIO(0x4de0), 0, false}, + {RCS, _MMIO(0x4de4), 0, false}, + {RCS, _MMIO(0x4de8), 0, false}, + {RCS, _MMIO(0x4dec), 0, false}, + {RCS, _MMIO(0x4df0), 0, false}, + {RCS, _MMIO(0x4df4), 0, false}, + + {BCS, _MMIO(0x2229c), 0xffff, false}, + {BCS, _MMIO(0x2209c), 0xffff, false}, + {BCS, _MMIO(0x220c0), 0xffff, false}, + {BCS, _MMIO(0x22098), 0x0, false}, + {BCS, _MMIO(0x22028), 0x0, false}, + + {VCS2, _MMIO(0x1c028), 0xffff, false}, + + {VECS, _MMIO(0x1a028), 0xffff, false}, +}; + +static u32 gen9_render_mocs[I915_NUM_ENGINES][64]; +static u32 gen9_render_mocs_L3[32]; + +static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + i915_reg_t reg; + u32 regs[] = { + [RCS] = 0x4260, + [VCS] = 0x4264, + [VCS2] = 0x4268, + [BCS] = 0x426c, + [VECS] = 0x4270, + }; + + if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) + return; + + if (!test_and_clear_bit(ring_id, (void *)vgpu->tlb_handle_pending)) + return; + + reg = _MMIO(regs[ring_id]); + + I915_WRITE(reg, 0x1); + + if (wait_for_atomic((I915_READ(reg) == 0), 50)) + gvt_err("timeout in invalidate ring (%d) tlb\n", ring_id); + + gvt_dbg_core("invalidate TLB for ring %d\n", ring_id); +} + +static void load_mocs(struct intel_vgpu *vgpu, int ring_id) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + i915_reg_t offset, l3_offset; + u32 regs[] = { + [RCS] = 0xc800, + [VCS] = 0xc900, + [VCS2] = 0xca00, + [BCS] = 0xcc00, + [VECS] = 0xcb00, + }; + int i; + + if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) + return; + + if (!IS_SKYLAKE(dev_priv)) + return; + + for (i = 0; i < 64; i++) { + gen9_render_mocs[ring_id][i] = I915_READ(offset); + I915_WRITE(offset, vgpu_vreg(vgpu, offset)); + POSTING_READ(offset); + offset.reg += 4; + } + + if (ring_id == RCS) { + l3_offset.reg = 0xb020; + for (i = 0; i < 32; i++) { + gen9_render_mocs_L3[i] = I915_READ(l3_offset); + I915_WRITE(l3_offset, vgpu_vreg(vgpu, offset)); + POSTING_READ(l3_offset); + l3_offset.reg += 4; + } + } +} + +static void restore_mocs(struct intel_vgpu *vgpu, int ring_id) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + i915_reg_t offset, l3_offset; + u32 regs[] = { + [RCS] = 0xc800, + [VCS] = 0xc900, + [VCS2] = 0xca00, + [BCS] = 0xcc00, + [VECS] = 0xcb00, + }; + int i; + + if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) + return; + + if (!IS_SKYLAKE(dev_priv)) + return; + + for (i = 0; i < 64; i++) { + vgpu_vreg(vgpu, offset) = I915_READ(offset); + I915_WRITE(offset, gen9_render_mocs[ring_id][i]); + POSTING_READ(offset); + offset.reg += 4; + } + + if (ring_id == RCS) { + l3_offset.reg = 0xb020; + for (i = 0; i < 32; i++) { + vgpu_vreg(vgpu, l3_offset) = I915_READ(l3_offset); + I915_WRITE(l3_offset, gen9_render_mocs_L3[i]); + POSTING_READ(l3_offset); + l3_offset.reg += 4; + } + } +} + +void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + struct render_mmio *mmio; + u32 v; + int i, array_size; + + if (IS_SKYLAKE(vgpu->gvt->dev_priv)) { + mmio = gen9_render_mmio_list; + array_size = ARRAY_SIZE(gen9_render_mmio_list); + load_mocs(vgpu, ring_id); + } else { + mmio = gen8_render_mmio_list; + array_size = ARRAY_SIZE(gen8_render_mmio_list); + } + + for (i = 0; i < array_size; i++, mmio++) { + if (mmio->ring_id != ring_id) + continue; + + mmio->value = I915_READ(mmio->reg); + if (mmio->mask) + v = vgpu_vreg(vgpu, mmio->reg) | (mmio->mask << 16); + else + v = vgpu_vreg(vgpu, mmio->reg); + + I915_WRITE(mmio->reg, v); + POSTING_READ(mmio->reg); + + gvt_dbg_render("load reg %x old %x new %x\n", + i915_mmio_reg_offset(mmio->reg), + mmio->value, v); + } + handle_tlb_pending_event(vgpu, ring_id); +} + +void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + struct render_mmio *mmio; + u32 v; + int i, array_size; + + if (IS_SKYLAKE(dev_priv)) { + mmio = gen9_render_mmio_list; + array_size = ARRAY_SIZE(gen9_render_mmio_list); + restore_mocs(vgpu, ring_id); + } else { + mmio = gen8_render_mmio_list; + array_size = ARRAY_SIZE(gen8_render_mmio_list); + } + + for (i = 0; i < array_size; i++, mmio++) { + if (mmio->ring_id != ring_id) + continue; + + vgpu_vreg(vgpu, mmio->reg) = I915_READ(mmio->reg); + + if (mmio->mask) { + vgpu_vreg(vgpu, mmio->reg) &= ~(mmio->mask << 16); + v = mmio->value | (mmio->mask << 16); + } else + v = mmio->value; + + I915_WRITE(mmio->reg, v); + POSTING_READ(mmio->reg); + + gvt_dbg_render("restore reg %x old %x new %x\n", + i915_mmio_reg_offset(mmio->reg), + mmio->value, v); + } +} diff --git a/drivers/gpu/drm/i915/gvt/render.h b/drivers/gpu/drm/i915/gvt/render.h new file mode 100644 index 000000000000..dac1a3cc458b --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/render.h @@ -0,0 +1,43 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eddie Dong + * Kevin Tian + * + * Contributors: + * Zhi Wang + * Changbin Du + * Zhenyu Wang + * Tina Zhang + * Bing Niu + * + */ + +#ifndef __GVT_RENDER_H__ +#define __GVT_RENDER_H__ + +void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id); + +void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id); + +#endif diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 2302a97cebf6..2f96302c7b21 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -139,9 +139,13 @@ static int shadow_context_status_change(struct notifier_block *nb, switch (action) { case INTEL_CONTEXT_SCHEDULE_IN: + intel_gvt_load_render_mmio(workload->vgpu, + workload->ring_id); atomic_set(&workload->shadow_ctx_active, 1); break; case INTEL_CONTEXT_SCHEDULE_OUT: + intel_gvt_restore_render_mmio(workload->vgpu, + workload->ring_id); atomic_set(&workload->shadow_ctx_active, 0); break; default: diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index c9b8e184f5cb..e5e0a72336c8 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -200,6 +200,7 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, vgpu->id = ret; vgpu->handle = param->handle; vgpu->gvt = gvt; + bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES); setup_vgpu_cfg_space(vgpu, param); -- cgit v1.2.3 From be1da7070aeaee23ff659c1a8cd992789ff86da4 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Tue, 3 May 2016 18:26:57 -0400 Subject: drm/i915/gvt: vGPU command scanner This patch introduces a command scanner to scan guest command buffers. Signed-off-by: Yulei Zhang Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/Makefile | 2 +- drivers/gpu/drm/i915/gvt/cmd_parser.c | 2878 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/cmd_parser.h | 49 + drivers/gpu/drm/i915/gvt/debug.h | 3 + drivers/gpu/drm/i915/gvt/execlist.c | 158 +- drivers/gpu/drm/i915/gvt/gvt.c | 11 +- drivers/gpu/drm/i915/gvt/gvt.h | 4 + drivers/gpu/drm/i915/gvt/interrupt.h | 4 + drivers/gpu/drm/i915/gvt/scheduler.c | 14 + drivers/gpu/drm/i915/gvt/scheduler.h | 41 +- drivers/gpu/drm/i915/gvt/trace.h | 52 + 11 files changed, 3212 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/i915/gvt/cmd_parser.c create mode 100644 drivers/gpu/drm/i915/gvt/cmd_parser.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index e05556cd0f78..34ea4776af70 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -1,7 +1,7 @@ GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ - execlist.o scheduler.o sched_policy.o render.o + execlist.o scheduler.o sched_policy.o render.o cmd_parser.o ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c new file mode 100644 index 000000000000..5808ee7c1935 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -0,0 +1,2878 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ke Yu + * Kevin Tian + * Zhiyuan Lv + * + * Contributors: + * Min He + * Ping Gao + * Tina Zhang + * Yulei Zhang + * Zhi Wang + * + */ + +#include +#include "i915_drv.h" +#include "trace.h" + +#define INVALID_OP (~0U) + +#define OP_LEN_MI 9 +#define OP_LEN_2D 10 +#define OP_LEN_3D_MEDIA 16 +#define OP_LEN_MFX_VC 16 +#define OP_LEN_VEBOX 16 + +#define CMD_TYPE(cmd) (((cmd) >> 29) & 7) + +struct sub_op_bits { + int hi; + int low; +}; +struct decode_info { + char *name; + int op_len; + int nr_sub_op; + struct sub_op_bits *sub_op; +}; + +#define MAX_CMD_BUDGET 0x7fffffff +#define MI_WAIT_FOR_PLANE_C_FLIP_PENDING (1<<15) +#define MI_WAIT_FOR_PLANE_B_FLIP_PENDING (1<<9) +#define MI_WAIT_FOR_PLANE_A_FLIP_PENDING (1<<1) + +#define MI_WAIT_FOR_SPRITE_C_FLIP_PENDING (1<<20) +#define MI_WAIT_FOR_SPRITE_B_FLIP_PENDING (1<<10) +#define MI_WAIT_FOR_SPRITE_A_FLIP_PENDING (1<<2) + +/* Render Command Map */ + +/* MI_* command Opcode (28:23) */ +#define OP_MI_NOOP 0x0 +#define OP_MI_SET_PREDICATE 0x1 /* HSW+ */ +#define OP_MI_USER_INTERRUPT 0x2 +#define OP_MI_WAIT_FOR_EVENT 0x3 +#define OP_MI_FLUSH 0x4 +#define OP_MI_ARB_CHECK 0x5 +#define OP_MI_RS_CONTROL 0x6 /* HSW+ */ +#define OP_MI_REPORT_HEAD 0x7 +#define OP_MI_ARB_ON_OFF 0x8 +#define OP_MI_URB_ATOMIC_ALLOC 0x9 /* HSW+ */ +#define OP_MI_BATCH_BUFFER_END 0xA +#define OP_MI_SUSPEND_FLUSH 0xB +#define OP_MI_PREDICATE 0xC /* IVB+ */ +#define OP_MI_TOPOLOGY_FILTER 0xD /* IVB+ */ +#define OP_MI_SET_APPID 0xE /* IVB+ */ +#define OP_MI_RS_CONTEXT 0xF /* HSW+ */ +#define OP_MI_LOAD_SCAN_LINES_INCL 0x12 /* HSW+ */ +#define OP_MI_DISPLAY_FLIP 0x14 +#define OP_MI_SEMAPHORE_MBOX 0x16 +#define OP_MI_SET_CONTEXT 0x18 +#define OP_MI_MATH 0x1A +#define OP_MI_URB_CLEAR 0x19 +#define OP_MI_SEMAPHORE_SIGNAL 0x1B /* BDW+ */ +#define OP_MI_SEMAPHORE_WAIT 0x1C /* BDW+ */ + +#define OP_MI_STORE_DATA_IMM 0x20 +#define OP_MI_STORE_DATA_INDEX 0x21 +#define OP_MI_LOAD_REGISTER_IMM 0x22 +#define OP_MI_UPDATE_GTT 0x23 +#define OP_MI_STORE_REGISTER_MEM 0x24 +#define OP_MI_FLUSH_DW 0x26 +#define OP_MI_CLFLUSH 0x27 +#define OP_MI_REPORT_PERF_COUNT 0x28 +#define OP_MI_LOAD_REGISTER_MEM 0x29 /* HSW+ */ +#define OP_MI_LOAD_REGISTER_REG 0x2A /* HSW+ */ +#define OP_MI_RS_STORE_DATA_IMM 0x2B /* HSW+ */ +#define OP_MI_LOAD_URB_MEM 0x2C /* HSW+ */ +#define OP_MI_STORE_URM_MEM 0x2D /* HSW+ */ +#define OP_MI_2E 0x2E /* BDW+ */ +#define OP_MI_2F 0x2F /* BDW+ */ +#define OP_MI_BATCH_BUFFER_START 0x31 + +/* Bit definition for dword 0 */ +#define _CMDBIT_BB_START_IN_PPGTT (1UL << 8) + +#define OP_MI_CONDITIONAL_BATCH_BUFFER_END 0x36 + +#define BATCH_BUFFER_ADDR_MASK ((1UL << 32) - (1U << 2)) +#define BATCH_BUFFER_ADDR_HIGH_MASK ((1UL << 16) - (1U)) +#define BATCH_BUFFER_ADR_SPACE_BIT(x) (((x) >> 8) & 1U) +#define BATCH_BUFFER_2ND_LEVEL_BIT(x) ((x) >> 22 & 1U) + +/* 2D command: Opcode (28:22) */ +#define OP_2D(x) ((2<<7) | x) + +#define OP_XY_SETUP_BLT OP_2D(0x1) +#define OP_XY_SETUP_CLIP_BLT OP_2D(0x3) +#define OP_XY_SETUP_MONO_PATTERN_SL_BLT OP_2D(0x11) +#define OP_XY_PIXEL_BLT OP_2D(0x24) +#define OP_XY_SCANLINES_BLT OP_2D(0x25) +#define OP_XY_TEXT_BLT OP_2D(0x26) +#define OP_XY_TEXT_IMMEDIATE_BLT OP_2D(0x31) +#define OP_XY_COLOR_BLT OP_2D(0x50) +#define OP_XY_PAT_BLT OP_2D(0x51) +#define OP_XY_MONO_PAT_BLT OP_2D(0x52) +#define OP_XY_SRC_COPY_BLT OP_2D(0x53) +#define OP_XY_MONO_SRC_COPY_BLT OP_2D(0x54) +#define OP_XY_FULL_BLT OP_2D(0x55) +#define OP_XY_FULL_MONO_SRC_BLT OP_2D(0x56) +#define OP_XY_FULL_MONO_PATTERN_BLT OP_2D(0x57) +#define OP_XY_FULL_MONO_PATTERN_MONO_SRC_BLT OP_2D(0x58) +#define OP_XY_MONO_PAT_FIXED_BLT OP_2D(0x59) +#define OP_XY_MONO_SRC_COPY_IMMEDIATE_BLT OP_2D(0x71) +#define OP_XY_PAT_BLT_IMMEDIATE OP_2D(0x72) +#define OP_XY_SRC_COPY_CHROMA_BLT OP_2D(0x73) +#define OP_XY_FULL_IMMEDIATE_PATTERN_BLT OP_2D(0x74) +#define OP_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT OP_2D(0x75) +#define OP_XY_PAT_CHROMA_BLT OP_2D(0x76) +#define OP_XY_PAT_CHROMA_BLT_IMMEDIATE OP_2D(0x77) + +/* 3D/Media Command: Pipeline Type(28:27) Opcode(26:24) Sub Opcode(23:16) */ +#define OP_3D_MEDIA(sub_type, opcode, sub_opcode) \ + ((3 << 13) | ((sub_type) << 11) | ((opcode) << 8) | (sub_opcode)) + +#define OP_STATE_PREFETCH OP_3D_MEDIA(0x0, 0x0, 0x03) + +#define OP_STATE_BASE_ADDRESS OP_3D_MEDIA(0x0, 0x1, 0x01) +#define OP_STATE_SIP OP_3D_MEDIA(0x0, 0x1, 0x02) +#define OP_3D_MEDIA_0_1_4 OP_3D_MEDIA(0x0, 0x1, 0x04) + +#define OP_3DSTATE_VF_STATISTICS_GM45 OP_3D_MEDIA(0x1, 0x0, 0x0B) + +#define OP_PIPELINE_SELECT OP_3D_MEDIA(0x1, 0x1, 0x04) + +#define OP_MEDIA_VFE_STATE OP_3D_MEDIA(0x2, 0x0, 0x0) +#define OP_MEDIA_CURBE_LOAD OP_3D_MEDIA(0x2, 0x0, 0x1) +#define OP_MEDIA_INTERFACE_DESCRIPTOR_LOAD OP_3D_MEDIA(0x2, 0x0, 0x2) +#define OP_MEDIA_GATEWAY_STATE OP_3D_MEDIA(0x2, 0x0, 0x3) +#define OP_MEDIA_STATE_FLUSH OP_3D_MEDIA(0x2, 0x0, 0x4) + +#define OP_MEDIA_OBJECT OP_3D_MEDIA(0x2, 0x1, 0x0) +#define OP_MEDIA_OBJECT_PRT OP_3D_MEDIA(0x2, 0x1, 0x2) +#define OP_MEDIA_OBJECT_WALKER OP_3D_MEDIA(0x2, 0x1, 0x3) +#define OP_GPGPU_WALKER OP_3D_MEDIA(0x2, 0x1, 0x5) + +#define OP_3DSTATE_CLEAR_PARAMS OP_3D_MEDIA(0x3, 0x0, 0x04) /* IVB+ */ +#define OP_3DSTATE_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x05) /* IVB+ */ +#define OP_3DSTATE_STENCIL_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x06) /* IVB+ */ +#define OP_3DSTATE_HIER_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x07) /* IVB+ */ +#define OP_3DSTATE_VERTEX_BUFFERS OP_3D_MEDIA(0x3, 0x0, 0x08) +#define OP_3DSTATE_VERTEX_ELEMENTS OP_3D_MEDIA(0x3, 0x0, 0x09) +#define OP_3DSTATE_INDEX_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x0A) +#define OP_3DSTATE_VF_STATISTICS OP_3D_MEDIA(0x3, 0x0, 0x0B) +#define OP_3DSTATE_VF OP_3D_MEDIA(0x3, 0x0, 0x0C) /* HSW+ */ +#define OP_3DSTATE_CC_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x0E) +#define OP_3DSTATE_SCISSOR_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x0F) +#define OP_3DSTATE_VS OP_3D_MEDIA(0x3, 0x0, 0x10) +#define OP_3DSTATE_GS OP_3D_MEDIA(0x3, 0x0, 0x11) +#define OP_3DSTATE_CLIP OP_3D_MEDIA(0x3, 0x0, 0x12) +#define OP_3DSTATE_SF OP_3D_MEDIA(0x3, 0x0, 0x13) +#define OP_3DSTATE_WM OP_3D_MEDIA(0x3, 0x0, 0x14) +#define OP_3DSTATE_CONSTANT_VS OP_3D_MEDIA(0x3, 0x0, 0x15) +#define OP_3DSTATE_CONSTANT_GS OP_3D_MEDIA(0x3, 0x0, 0x16) +#define OP_3DSTATE_CONSTANT_PS OP_3D_MEDIA(0x3, 0x0, 0x17) +#define OP_3DSTATE_SAMPLE_MASK OP_3D_MEDIA(0x3, 0x0, 0x18) +#define OP_3DSTATE_CONSTANT_HS OP_3D_MEDIA(0x3, 0x0, 0x19) /* IVB+ */ +#define OP_3DSTATE_CONSTANT_DS OP_3D_MEDIA(0x3, 0x0, 0x1A) /* IVB+ */ +#define OP_3DSTATE_HS OP_3D_MEDIA(0x3, 0x0, 0x1B) /* IVB+ */ +#define OP_3DSTATE_TE OP_3D_MEDIA(0x3, 0x0, 0x1C) /* IVB+ */ +#define OP_3DSTATE_DS OP_3D_MEDIA(0x3, 0x0, 0x1D) /* IVB+ */ +#define OP_3DSTATE_STREAMOUT OP_3D_MEDIA(0x3, 0x0, 0x1E) /* IVB+ */ +#define OP_3DSTATE_SBE OP_3D_MEDIA(0x3, 0x0, 0x1F) /* IVB+ */ +#define OP_3DSTATE_PS OP_3D_MEDIA(0x3, 0x0, 0x20) /* IVB+ */ +#define OP_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP OP_3D_MEDIA(0x3, 0x0, 0x21) /* IVB+ */ +#define OP_3DSTATE_VIEWPORT_STATE_POINTERS_CC OP_3D_MEDIA(0x3, 0x0, 0x23) /* IVB+ */ +#define OP_3DSTATE_BLEND_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x24) /* IVB+ */ +#define OP_3DSTATE_DEPTH_STENCIL_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x25) /* IVB+ */ +#define OP_3DSTATE_BINDING_TABLE_POINTERS_VS OP_3D_MEDIA(0x3, 0x0, 0x26) /* IVB+ */ +#define OP_3DSTATE_BINDING_TABLE_POINTERS_HS OP_3D_MEDIA(0x3, 0x0, 0x27) /* IVB+ */ +#define OP_3DSTATE_BINDING_TABLE_POINTERS_DS OP_3D_MEDIA(0x3, 0x0, 0x28) /* IVB+ */ +#define OP_3DSTATE_BINDING_TABLE_POINTERS_GS OP_3D_MEDIA(0x3, 0x0, 0x29) /* IVB+ */ +#define OP_3DSTATE_BINDING_TABLE_POINTERS_PS OP_3D_MEDIA(0x3, 0x0, 0x2A) /* IVB+ */ +#define OP_3DSTATE_SAMPLER_STATE_POINTERS_VS OP_3D_MEDIA(0x3, 0x0, 0x2B) /* IVB+ */ +#define OP_3DSTATE_SAMPLER_STATE_POINTERS_HS OP_3D_MEDIA(0x3, 0x0, 0x2C) /* IVB+ */ +#define OP_3DSTATE_SAMPLER_STATE_POINTERS_DS OP_3D_MEDIA(0x3, 0x0, 0x2D) /* IVB+ */ +#define OP_3DSTATE_SAMPLER_STATE_POINTERS_GS OP_3D_MEDIA(0x3, 0x0, 0x2E) /* IVB+ */ +#define OP_3DSTATE_SAMPLER_STATE_POINTERS_PS OP_3D_MEDIA(0x3, 0x0, 0x2F) /* IVB+ */ +#define OP_3DSTATE_URB_VS OP_3D_MEDIA(0x3, 0x0, 0x30) /* IVB+ */ +#define OP_3DSTATE_URB_HS OP_3D_MEDIA(0x3, 0x0, 0x31) /* IVB+ */ +#define OP_3DSTATE_URB_DS OP_3D_MEDIA(0x3, 0x0, 0x32) /* IVB+ */ +#define OP_3DSTATE_URB_GS OP_3D_MEDIA(0x3, 0x0, 0x33) /* IVB+ */ +#define OP_3DSTATE_GATHER_CONSTANT_VS OP_3D_MEDIA(0x3, 0x0, 0x34) /* HSW+ */ +#define OP_3DSTATE_GATHER_CONSTANT_GS OP_3D_MEDIA(0x3, 0x0, 0x35) /* HSW+ */ +#define OP_3DSTATE_GATHER_CONSTANT_HS OP_3D_MEDIA(0x3, 0x0, 0x36) /* HSW+ */ +#define OP_3DSTATE_GATHER_CONSTANT_DS OP_3D_MEDIA(0x3, 0x0, 0x37) /* HSW+ */ +#define OP_3DSTATE_GATHER_CONSTANT_PS OP_3D_MEDIA(0x3, 0x0, 0x38) /* HSW+ */ +#define OP_3DSTATE_DX9_CONSTANTF_VS OP_3D_MEDIA(0x3, 0x0, 0x39) /* HSW+ */ +#define OP_3DSTATE_DX9_CONSTANTF_PS OP_3D_MEDIA(0x3, 0x0, 0x3A) /* HSW+ */ +#define OP_3DSTATE_DX9_CONSTANTI_VS OP_3D_MEDIA(0x3, 0x0, 0x3B) /* HSW+ */ +#define OP_3DSTATE_DX9_CONSTANTI_PS OP_3D_MEDIA(0x3, 0x0, 0x3C) /* HSW+ */ +#define OP_3DSTATE_DX9_CONSTANTB_VS OP_3D_MEDIA(0x3, 0x0, 0x3D) /* HSW+ */ +#define OP_3DSTATE_DX9_CONSTANTB_PS OP_3D_MEDIA(0x3, 0x0, 0x3E) /* HSW+ */ +#define OP_3DSTATE_DX9_LOCAL_VALID_VS OP_3D_MEDIA(0x3, 0x0, 0x3F) /* HSW+ */ +#define OP_3DSTATE_DX9_LOCAL_VALID_PS OP_3D_MEDIA(0x3, 0x0, 0x40) /* HSW+ */ +#define OP_3DSTATE_DX9_GENERATE_ACTIVE_VS OP_3D_MEDIA(0x3, 0x0, 0x41) /* HSW+ */ +#define OP_3DSTATE_DX9_GENERATE_ACTIVE_PS OP_3D_MEDIA(0x3, 0x0, 0x42) /* HSW+ */ +#define OP_3DSTATE_BINDING_TABLE_EDIT_VS OP_3D_MEDIA(0x3, 0x0, 0x43) /* HSW+ */ +#define OP_3DSTATE_BINDING_TABLE_EDIT_GS OP_3D_MEDIA(0x3, 0x0, 0x44) /* HSW+ */ +#define OP_3DSTATE_BINDING_TABLE_EDIT_HS OP_3D_MEDIA(0x3, 0x0, 0x45) /* HSW+ */ +#define OP_3DSTATE_BINDING_TABLE_EDIT_DS OP_3D_MEDIA(0x3, 0x0, 0x46) /* HSW+ */ +#define OP_3DSTATE_BINDING_TABLE_EDIT_PS OP_3D_MEDIA(0x3, 0x0, 0x47) /* HSW+ */ + +#define OP_3DSTATE_VF_INSTANCING OP_3D_MEDIA(0x3, 0x0, 0x49) /* BDW+ */ +#define OP_3DSTATE_VF_SGVS OP_3D_MEDIA(0x3, 0x0, 0x4A) /* BDW+ */ +#define OP_3DSTATE_VF_TOPOLOGY OP_3D_MEDIA(0x3, 0x0, 0x4B) /* BDW+ */ +#define OP_3DSTATE_WM_CHROMAKEY OP_3D_MEDIA(0x3, 0x0, 0x4C) /* BDW+ */ +#define OP_3DSTATE_PS_BLEND OP_3D_MEDIA(0x3, 0x0, 0x4D) /* BDW+ */ +#define OP_3DSTATE_WM_DEPTH_STENCIL OP_3D_MEDIA(0x3, 0x0, 0x4E) /* BDW+ */ +#define OP_3DSTATE_PS_EXTRA OP_3D_MEDIA(0x3, 0x0, 0x4F) /* BDW+ */ +#define OP_3DSTATE_RASTER OP_3D_MEDIA(0x3, 0x0, 0x50) /* BDW+ */ +#define OP_3DSTATE_SBE_SWIZ OP_3D_MEDIA(0x3, 0x0, 0x51) /* BDW+ */ +#define OP_3DSTATE_WM_HZ_OP OP_3D_MEDIA(0x3, 0x0, 0x52) /* BDW+ */ +#define OP_3DSTATE_COMPONENT_PACKING OP_3D_MEDIA(0x3, 0x0, 0x55) /* SKL+ */ + +#define OP_3DSTATE_DRAWING_RECTANGLE OP_3D_MEDIA(0x3, 0x1, 0x00) +#define OP_3DSTATE_SAMPLER_PALETTE_LOAD0 OP_3D_MEDIA(0x3, 0x1, 0x02) +#define OP_3DSTATE_CHROMA_KEY OP_3D_MEDIA(0x3, 0x1, 0x04) +#define OP_SNB_3DSTATE_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x05) +#define OP_3DSTATE_POLY_STIPPLE_OFFSET OP_3D_MEDIA(0x3, 0x1, 0x06) +#define OP_3DSTATE_POLY_STIPPLE_PATTERN OP_3D_MEDIA(0x3, 0x1, 0x07) +#define OP_3DSTATE_LINE_STIPPLE OP_3D_MEDIA(0x3, 0x1, 0x08) +#define OP_3DSTATE_AA_LINE_PARAMS OP_3D_MEDIA(0x3, 0x1, 0x0A) +#define OP_3DSTATE_GS_SVB_INDEX OP_3D_MEDIA(0x3, 0x1, 0x0B) +#define OP_3DSTATE_SAMPLER_PALETTE_LOAD1 OP_3D_MEDIA(0x3, 0x1, 0x0C) +#define OP_3DSTATE_MULTISAMPLE_BDW OP_3D_MEDIA(0x3, 0x0, 0x0D) +#define OP_SNB_3DSTATE_STENCIL_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x0E) +#define OP_SNB_3DSTATE_HIER_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x0F) +#define OP_SNB_3DSTATE_CLEAR_PARAMS OP_3D_MEDIA(0x3, 0x1, 0x10) +#define OP_3DSTATE_MONOFILTER_SIZE OP_3D_MEDIA(0x3, 0x1, 0x11) +#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_VS OP_3D_MEDIA(0x3, 0x1, 0x12) /* IVB+ */ +#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_HS OP_3D_MEDIA(0x3, 0x1, 0x13) /* IVB+ */ +#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_DS OP_3D_MEDIA(0x3, 0x1, 0x14) /* IVB+ */ +#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_GS OP_3D_MEDIA(0x3, 0x1, 0x15) /* IVB+ */ +#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_PS OP_3D_MEDIA(0x3, 0x1, 0x16) /* IVB+ */ +#define OP_3DSTATE_SO_DECL_LIST OP_3D_MEDIA(0x3, 0x1, 0x17) +#define OP_3DSTATE_SO_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x18) +#define OP_3DSTATE_BINDING_TABLE_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x19) /* HSW+ */ +#define OP_3DSTATE_GATHER_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x1A) /* HSW+ */ +#define OP_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x1B) /* HSW+ */ +#define OP_3DSTATE_SAMPLE_PATTERN OP_3D_MEDIA(0x3, 0x1, 0x1C) +#define OP_PIPE_CONTROL OP_3D_MEDIA(0x3, 0x2, 0x00) +#define OP_3DPRIMITIVE OP_3D_MEDIA(0x3, 0x3, 0x00) + +/* VCCP Command Parser */ + +/* + * Below MFX and VBE cmd definition is from vaapi intel driver project (BSD License) + * git://anongit.freedesktop.org/vaapi/intel-driver + * src/i965_defines.h + * + */ + +#define OP_MFX(pipeline, op, sub_opa, sub_opb) \ + (3 << 13 | \ + (pipeline) << 11 | \ + (op) << 8 | \ + (sub_opa) << 5 | \ + (sub_opb)) + +#define OP_MFX_PIPE_MODE_SELECT OP_MFX(2, 0, 0, 0) /* ALL */ +#define OP_MFX_SURFACE_STATE OP_MFX(2, 0, 0, 1) /* ALL */ +#define OP_MFX_PIPE_BUF_ADDR_STATE OP_MFX(2, 0, 0, 2) /* ALL */ +#define OP_MFX_IND_OBJ_BASE_ADDR_STATE OP_MFX(2, 0, 0, 3) /* ALL */ +#define OP_MFX_BSP_BUF_BASE_ADDR_STATE OP_MFX(2, 0, 0, 4) /* ALL */ +#define OP_2_0_0_5 OP_MFX(2, 0, 0, 5) /* ALL */ +#define OP_MFX_STATE_POINTER OP_MFX(2, 0, 0, 6) /* ALL */ +#define OP_MFX_QM_STATE OP_MFX(2, 0, 0, 7) /* IVB+ */ +#define OP_MFX_FQM_STATE OP_MFX(2, 0, 0, 8) /* IVB+ */ +#define OP_MFX_PAK_INSERT_OBJECT OP_MFX(2, 0, 2, 8) /* IVB+ */ +#define OP_MFX_STITCH_OBJECT OP_MFX(2, 0, 2, 0xA) /* IVB+ */ + +#define OP_MFD_IT_OBJECT OP_MFX(2, 0, 1, 9) /* ALL */ + +#define OP_MFX_WAIT OP_MFX(1, 0, 0, 0) /* IVB+ */ +#define OP_MFX_AVC_IMG_STATE OP_MFX(2, 1, 0, 0) /* ALL */ +#define OP_MFX_AVC_QM_STATE OP_MFX(2, 1, 0, 1) /* ALL */ +#define OP_MFX_AVC_DIRECTMODE_STATE OP_MFX(2, 1, 0, 2) /* ALL */ +#define OP_MFX_AVC_SLICE_STATE OP_MFX(2, 1, 0, 3) /* ALL */ +#define OP_MFX_AVC_REF_IDX_STATE OP_MFX(2, 1, 0, 4) /* ALL */ +#define OP_MFX_AVC_WEIGHTOFFSET_STATE OP_MFX(2, 1, 0, 5) /* ALL */ +#define OP_MFD_AVC_PICID_STATE OP_MFX(2, 1, 1, 5) /* HSW+ */ +#define OP_MFD_AVC_DPB_STATE OP_MFX(2, 1, 1, 6) /* IVB+ */ +#define OP_MFD_AVC_SLICEADDR OP_MFX(2, 1, 1, 7) /* IVB+ */ +#define OP_MFD_AVC_BSD_OBJECT OP_MFX(2, 1, 1, 8) /* ALL */ +#define OP_MFC_AVC_PAK_OBJECT OP_MFX(2, 1, 2, 9) /* ALL */ + +#define OP_MFX_VC1_PRED_PIPE_STATE OP_MFX(2, 2, 0, 1) /* ALL */ +#define OP_MFX_VC1_DIRECTMODE_STATE OP_MFX(2, 2, 0, 2) /* ALL */ +#define OP_MFD_VC1_SHORT_PIC_STATE OP_MFX(2, 2, 1, 0) /* IVB+ */ +#define OP_MFD_VC1_LONG_PIC_STATE OP_MFX(2, 2, 1, 1) /* IVB+ */ +#define OP_MFD_VC1_BSD_OBJECT OP_MFX(2, 2, 1, 8) /* ALL */ + +#define OP_MFX_MPEG2_PIC_STATE OP_MFX(2, 3, 0, 0) /* ALL */ +#define OP_MFX_MPEG2_QM_STATE OP_MFX(2, 3, 0, 1) /* ALL */ +#define OP_MFD_MPEG2_BSD_OBJECT OP_MFX(2, 3, 1, 8) /* ALL */ +#define OP_MFC_MPEG2_SLICEGROUP_STATE OP_MFX(2, 3, 2, 3) /* ALL */ +#define OP_MFC_MPEG2_PAK_OBJECT OP_MFX(2, 3, 2, 9) /* ALL */ + +#define OP_MFX_2_6_0_0 OP_MFX(2, 6, 0, 0) /* IVB+ */ +#define OP_MFX_2_6_0_8 OP_MFX(2, 6, 0, 8) /* IVB+ */ +#define OP_MFX_2_6_0_9 OP_MFX(2, 6, 0, 9) /* IVB+ */ + +#define OP_MFX_JPEG_PIC_STATE OP_MFX(2, 7, 0, 0) +#define OP_MFX_JPEG_HUFF_TABLE_STATE OP_MFX(2, 7, 0, 2) +#define OP_MFD_JPEG_BSD_OBJECT OP_MFX(2, 7, 1, 8) + +#define OP_VEB(pipeline, op, sub_opa, sub_opb) \ + (3 << 13 | \ + (pipeline) << 11 | \ + (op) << 8 | \ + (sub_opa) << 5 | \ + (sub_opb)) + +#define OP_VEB_SURFACE_STATE OP_VEB(2, 4, 0, 0) +#define OP_VEB_STATE OP_VEB(2, 4, 0, 2) +#define OP_VEB_DNDI_IECP_STATE OP_VEB(2, 4, 0, 3) + +struct parser_exec_state; + +typedef int (*parser_cmd_handler)(struct parser_exec_state *s); + +#define GVT_CMD_HASH_BITS 7 + +/* which DWords need address fix */ +#define ADDR_FIX_1(x1) (1 << (x1)) +#define ADDR_FIX_2(x1, x2) (ADDR_FIX_1(x1) | ADDR_FIX_1(x2)) +#define ADDR_FIX_3(x1, x2, x3) (ADDR_FIX_1(x1) | ADDR_FIX_2(x2, x3)) +#define ADDR_FIX_4(x1, x2, x3, x4) (ADDR_FIX_1(x1) | ADDR_FIX_3(x2, x3, x4)) +#define ADDR_FIX_5(x1, x2, x3, x4, x5) (ADDR_FIX_1(x1) | ADDR_FIX_4(x2, x3, x4, x5)) + +struct cmd_info { + char *name; + u32 opcode; + +#define F_LEN_MASK (1U<<0) +#define F_LEN_CONST 1U +#define F_LEN_VAR 0U + +/* + * command has its own ip advance logic + * e.g. MI_BATCH_START, MI_BATCH_END + */ +#define F_IP_ADVANCE_CUSTOM (1<<1) + +#define F_POST_HANDLE (1<<2) + u32 flag; + +#define R_RCS (1 << RCS) +#define R_VCS1 (1 << VCS) +#define R_VCS2 (1 << VCS2) +#define R_VCS (R_VCS1 | R_VCS2) +#define R_BCS (1 << BCS) +#define R_VECS (1 << VECS) +#define R_ALL (R_RCS | R_VCS | R_BCS | R_VECS) + /* rings that support this cmd: BLT/RCS/VCS/VECS */ + uint16_t rings; + + /* devices that support this cmd: SNB/IVB/HSW/... */ + uint16_t devices; + + /* which DWords are address that need fix up. + * bit 0 means a 32-bit non address operand in command + * bit 1 means address operand, which could be 32-bit + * or 64-bit depending on different architectures.( + * defined by "gmadr_bytes_in_cmd" in intel_gvt. + * No matter the address length, each address only takes + * one bit in the bitmap. + */ + uint16_t addr_bitmap; + + /* flag == F_LEN_CONST : command length + * flag == F_LEN_VAR : length bias bits + * Note: length is in DWord + */ + uint8_t len; + + parser_cmd_handler handler; +}; + +struct cmd_entry { + struct hlist_node hlist; + struct cmd_info *info; +}; + +enum { + RING_BUFFER_INSTRUCTION, + BATCH_BUFFER_INSTRUCTION, + BATCH_BUFFER_2ND_LEVEL, +}; + +enum { + GTT_BUFFER, + PPGTT_BUFFER +}; + +struct parser_exec_state { + struct intel_vgpu *vgpu; + int ring_id; + + int buf_type; + + /* batch buffer address type */ + int buf_addr_type; + + /* graphics memory address of ring buffer start */ + unsigned long ring_start; + unsigned long ring_size; + unsigned long ring_head; + unsigned long ring_tail; + + /* instruction graphics memory address */ + unsigned long ip_gma; + + /* mapped va of the instr_gma */ + void *ip_va; + void *rb_va; + + void *ret_bb_va; + /* next instruction when return from batch buffer to ring buffer */ + unsigned long ret_ip_gma_ring; + + /* next instruction when return from 2nd batch buffer to batch buffer */ + unsigned long ret_ip_gma_bb; + + /* batch buffer address type (GTT or PPGTT) + * used when ret from 2nd level batch buffer + */ + int saved_buf_addr_type; + + struct cmd_info *info; + + struct intel_vgpu_workload *workload; +}; + +#define gmadr_dw_number(s) \ + (s->vgpu->gvt->device_info.gmadr_bytes_in_cmd >> 2) + +unsigned long bypass_scan_mask = 0; +bool bypass_batch_buffer_scan = true; + +/* ring ALL, type = 0 */ +static struct sub_op_bits sub_op_mi[] = { + {31, 29}, + {28, 23}, +}; + +static struct decode_info decode_info_mi = { + "MI", + OP_LEN_MI, + ARRAY_SIZE(sub_op_mi), + sub_op_mi, +}; + +/* ring RCS, command type 2 */ +static struct sub_op_bits sub_op_2d[] = { + {31, 29}, + {28, 22}, +}; + +static struct decode_info decode_info_2d = { + "2D", + OP_LEN_2D, + ARRAY_SIZE(sub_op_2d), + sub_op_2d, +}; + +/* ring RCS, command type 3 */ +static struct sub_op_bits sub_op_3d_media[] = { + {31, 29}, + {28, 27}, + {26, 24}, + {23, 16}, +}; + +static struct decode_info decode_info_3d_media = { + "3D_Media", + OP_LEN_3D_MEDIA, + ARRAY_SIZE(sub_op_3d_media), + sub_op_3d_media, +}; + +/* ring VCS, command type 3 */ +static struct sub_op_bits sub_op_mfx_vc[] = { + {31, 29}, + {28, 27}, + {26, 24}, + {23, 21}, + {20, 16}, +}; + +static struct decode_info decode_info_mfx_vc = { + "MFX_VC", + OP_LEN_MFX_VC, + ARRAY_SIZE(sub_op_mfx_vc), + sub_op_mfx_vc, +}; + +/* ring VECS, command type 3 */ +static struct sub_op_bits sub_op_vebox[] = { + {31, 29}, + {28, 27}, + {26, 24}, + {23, 21}, + {20, 16}, +}; + +static struct decode_info decode_info_vebox = { + "VEBOX", + OP_LEN_VEBOX, + ARRAY_SIZE(sub_op_vebox), + sub_op_vebox, +}; + +static struct decode_info *ring_decode_info[I915_NUM_ENGINES][8] = { + [RCS] = { + &decode_info_mi, + NULL, + NULL, + &decode_info_3d_media, + NULL, + NULL, + NULL, + NULL, + }, + + [VCS] = { + &decode_info_mi, + NULL, + NULL, + &decode_info_mfx_vc, + NULL, + NULL, + NULL, + NULL, + }, + + [BCS] = { + &decode_info_mi, + NULL, + &decode_info_2d, + NULL, + NULL, + NULL, + NULL, + NULL, + }, + + [VECS] = { + &decode_info_mi, + NULL, + NULL, + &decode_info_vebox, + NULL, + NULL, + NULL, + NULL, + }, + + [VCS2] = { + &decode_info_mi, + NULL, + NULL, + &decode_info_mfx_vc, + NULL, + NULL, + NULL, + NULL, + }, +}; + +static inline u32 get_opcode(u32 cmd, int ring_id) +{ + struct decode_info *d_info; + + if (ring_id >= I915_NUM_ENGINES) + return INVALID_OP; + + d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)]; + if (d_info == NULL) + return INVALID_OP; + + return cmd >> (32 - d_info->op_len); +} + +static inline struct cmd_info *find_cmd_entry(struct intel_gvt *gvt, + unsigned int opcode, int ring_id) +{ + struct cmd_entry *e; + + hash_for_each_possible(gvt->cmd_table, e, hlist, opcode) { + if ((opcode == e->info->opcode) && + (e->info->rings & (1 << ring_id))) + return e->info; + } + return NULL; +} + +static inline struct cmd_info *get_cmd_info(struct intel_gvt *gvt, + u32 cmd, int ring_id) +{ + u32 opcode; + + opcode = get_opcode(cmd, ring_id); + if (opcode == INVALID_OP) + return NULL; + + return find_cmd_entry(gvt, opcode, ring_id); +} + +static inline u32 sub_op_val(u32 cmd, u32 hi, u32 low) +{ + return (cmd >> low) & ((1U << (hi - low + 1)) - 1); +} + +static inline void print_opcode(u32 cmd, int ring_id) +{ + struct decode_info *d_info; + int i; + + if (ring_id >= I915_NUM_ENGINES) + return; + + d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)]; + if (d_info == NULL) + return; + + gvt_err("opcode=0x%x %s sub_ops:", + cmd >> (32 - d_info->op_len), d_info->name); + + for (i = 0; i < d_info->nr_sub_op; i++) + pr_err("0x%x ", sub_op_val(cmd, d_info->sub_op[i].hi, + d_info->sub_op[i].low)); + + pr_err("\n"); +} + +static inline u32 *cmd_ptr(struct parser_exec_state *s, int index) +{ + return s->ip_va + (index << 2); +} + +static inline u32 cmd_val(struct parser_exec_state *s, int index) +{ + return *cmd_ptr(s, index); +} + +static void parser_exec_state_dump(struct parser_exec_state *s) +{ + int cnt = 0; + int i; + + gvt_err(" vgpu%d RING%d: ring_start(%08lx) ring_end(%08lx)" + " ring_head(%08lx) ring_tail(%08lx)\n", s->vgpu->id, + s->ring_id, s->ring_start, s->ring_start + s->ring_size, + s->ring_head, s->ring_tail); + + gvt_err(" %s %s ip_gma(%08lx) ", + s->buf_type == RING_BUFFER_INSTRUCTION ? + "RING_BUFFER" : "BATCH_BUFFER", + s->buf_addr_type == GTT_BUFFER ? + "GTT" : "PPGTT", s->ip_gma); + + if (s->ip_va == NULL) { + gvt_err(" ip_va(NULL)"); + return; + } + + gvt_err(" ip_va=%p: %08x %08x %08x %08x\n", + s->ip_va, cmd_val(s, 0), cmd_val(s, 1), + cmd_val(s, 2), cmd_val(s, 3)); + + print_opcode(cmd_val(s, 0), s->ring_id); + + /* print the whole page to trace */ + pr_err(" ip_va=%p: %08x %08x %08x %08x\n", + s->ip_va, cmd_val(s, 0), cmd_val(s, 1), + cmd_val(s, 2), cmd_val(s, 3)); + + s->ip_va = (u32 *)((((u64)s->ip_va) >> 12) << 12); + + while (cnt < 1024) { + pr_err("ip_va=%p: ", s->ip_va); + for (i = 0; i < 8; i++) + pr_err("%08x ", cmd_val(s, i)); + pr_err("\n"); + + s->ip_va += 8 * sizeof(u32); + cnt += 8; + } +} + +static inline void update_ip_va(struct parser_exec_state *s) +{ + unsigned long len = 0; + + if (WARN_ON(s->ring_head == s->ring_tail)) + return; + + if (s->buf_type == RING_BUFFER_INSTRUCTION) { + unsigned long ring_top = s->ring_start + s->ring_size; + + if (s->ring_head > s->ring_tail) { + if (s->ip_gma >= s->ring_head && s->ip_gma < ring_top) + len = (s->ip_gma - s->ring_head); + else if (s->ip_gma >= s->ring_start && + s->ip_gma <= s->ring_tail) + len = (ring_top - s->ring_head) + + (s->ip_gma - s->ring_start); + } else + len = (s->ip_gma - s->ring_head); + + s->ip_va = s->rb_va + len; + } else {/* shadow batch buffer */ + s->ip_va = s->ret_bb_va; + } +} + +static inline int ip_gma_set(struct parser_exec_state *s, + unsigned long ip_gma) +{ + WARN_ON(!IS_ALIGNED(ip_gma, 4)); + + s->ip_gma = ip_gma; + update_ip_va(s); + return 0; +} + +static inline int ip_gma_advance(struct parser_exec_state *s, + unsigned int dw_len) +{ + s->ip_gma += (dw_len << 2); + + if (s->buf_type == RING_BUFFER_INSTRUCTION) { + if (s->ip_gma >= s->ring_start + s->ring_size) + s->ip_gma -= s->ring_size; + update_ip_va(s); + } else { + s->ip_va += (dw_len << 2); + } + + return 0; +} + +static inline int get_cmd_length(struct cmd_info *info, u32 cmd) +{ + if ((info->flag & F_LEN_MASK) == F_LEN_CONST) + return info->len; + else + return (cmd & ((1U << info->len) - 1)) + 2; + return 0; +} + +static inline int cmd_length(struct parser_exec_state *s) +{ + return get_cmd_length(s->info, cmd_val(s, 0)); +} + +/* do not remove this, some platform may need clflush here */ +#define patch_value(s, addr, val) do { \ + *addr = val; \ +} while (0) + +static bool is_shadowed_mmio(unsigned int offset) +{ + bool ret = false; + + if ((offset == 0x2168) || /*BB current head register UDW */ + (offset == 0x2140) || /*BB current header register */ + (offset == 0x211c) || /*second BB header register UDW */ + (offset == 0x2114)) { /*second BB header register UDW */ + ret = true; + } + return ret; +} + +static int cmd_reg_handler(struct parser_exec_state *s, + unsigned int offset, unsigned int index, char *cmd) +{ + struct intel_vgpu *vgpu = s->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + + if (offset + 4 > gvt->device_info.mmio_size) { + gvt_err("%s access to (%x) outside of MMIO range\n", + cmd, offset); + return -EINVAL; + } + + if (!intel_gvt_mmio_is_cmd_access(gvt, offset)) { + gvt_err("vgpu%d: %s access to non-render register (%x)\n", + s->vgpu->id, cmd, offset); + return 0; + } + + if (is_shadowed_mmio(offset)) { + gvt_err("vgpu%d: found access of shadowed MMIO %x\n", + s->vgpu->id, offset); + return 0; + } + + if (offset == i915_mmio_reg_offset(DERRMR) || + offset == i915_mmio_reg_offset(FORCEWAKE_MT)) { + /* Writing to HW VGT_PVINFO_PAGE offset will be discarded */ + patch_value(s, cmd_ptr(s, index), VGT_PVINFO_PAGE); + } + + /* TODO: Update the global mask if this MMIO is a masked-MMIO */ + intel_gvt_mmio_set_cmd_accessed(gvt, offset); + return 0; +} + +#define cmd_reg(s, i) \ + (cmd_val(s, i) & GENMASK(22, 2)) + +#define cmd_reg_inhibit(s, i) \ + (cmd_val(s, i) & GENMASK(22, 18)) + +#define cmd_gma(s, i) \ + (cmd_val(s, i) & GENMASK(31, 2)) + +#define cmd_gma_hi(s, i) \ + (cmd_val(s, i) & GENMASK(15, 0)) + +static int cmd_handler_lri(struct parser_exec_state *s) +{ + int i, ret = 0; + int cmd_len = cmd_length(s); + struct intel_gvt *gvt = s->vgpu->gvt; + + for (i = 1; i < cmd_len; i += 2) { + if (IS_BROADWELL(gvt->dev_priv) && + (s->ring_id != RCS)) { + if (s->ring_id == BCS && + cmd_reg(s, i) == + i915_mmio_reg_offset(DERRMR)) + ret |= 0; + else + ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0; + } + if (ret) + break; + ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lri"); + } + return ret; +} + +static int cmd_handler_lrr(struct parser_exec_state *s) +{ + int i, ret = 0; + int cmd_len = cmd_length(s); + + for (i = 1; i < cmd_len; i += 2) { + if (IS_BROADWELL(s->vgpu->gvt->dev_priv)) + ret |= ((cmd_reg_inhibit(s, i) || + (cmd_reg_inhibit(s, i + 1)))) ? + -EINVAL : 0; + if (ret) + break; + ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrr-src"); + ret |= cmd_reg_handler(s, cmd_reg(s, i + 1), i, "lrr-dst"); + } + return ret; +} + +static inline int cmd_address_audit(struct parser_exec_state *s, + unsigned long guest_gma, int op_size, bool index_mode); + +static int cmd_handler_lrm(struct parser_exec_state *s) +{ + struct intel_gvt *gvt = s->vgpu->gvt; + int gmadr_bytes = gvt->device_info.gmadr_bytes_in_cmd; + unsigned long gma; + int i, ret = 0; + int cmd_len = cmd_length(s); + + for (i = 1; i < cmd_len;) { + if (IS_BROADWELL(gvt->dev_priv)) + ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0; + if (ret) + break; + ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrm"); + if (cmd_val(s, 0) & (1 << 22)) { + gma = cmd_gma(s, i + 1); + if (gmadr_bytes == 8) + gma |= (cmd_gma_hi(s, i + 2)) << 32; + ret |= cmd_address_audit(s, gma, sizeof(u32), false); + } + i += gmadr_dw_number(s) + 1; + } + return ret; +} + +static int cmd_handler_srm(struct parser_exec_state *s) +{ + int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; + unsigned long gma; + int i, ret = 0; + int cmd_len = cmd_length(s); + + for (i = 1; i < cmd_len;) { + ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "srm"); + if (cmd_val(s, 0) & (1 << 22)) { + gma = cmd_gma(s, i + 1); + if (gmadr_bytes == 8) + gma |= (cmd_gma_hi(s, i + 2)) << 32; + ret |= cmd_address_audit(s, gma, sizeof(u32), false); + } + i += gmadr_dw_number(s) + 1; + } + return ret; +} + +struct cmd_interrupt_event { + int pipe_control_notify; + int mi_flush_dw; + int mi_user_interrupt; +}; + +struct cmd_interrupt_event cmd_interrupt_events[] = { + [RCS] = { + .pipe_control_notify = RCS_PIPE_CONTROL, + .mi_flush_dw = INTEL_GVT_EVENT_RESERVED, + .mi_user_interrupt = RCS_MI_USER_INTERRUPT, + }, + [BCS] = { + .pipe_control_notify = INTEL_GVT_EVENT_RESERVED, + .mi_flush_dw = BCS_MI_FLUSH_DW, + .mi_user_interrupt = BCS_MI_USER_INTERRUPT, + }, + [VCS] = { + .pipe_control_notify = INTEL_GVT_EVENT_RESERVED, + .mi_flush_dw = VCS_MI_FLUSH_DW, + .mi_user_interrupt = VCS_MI_USER_INTERRUPT, + }, + [VCS2] = { + .pipe_control_notify = INTEL_GVT_EVENT_RESERVED, + .mi_flush_dw = VCS2_MI_FLUSH_DW, + .mi_user_interrupt = VCS2_MI_USER_INTERRUPT, + }, + [VECS] = { + .pipe_control_notify = INTEL_GVT_EVENT_RESERVED, + .mi_flush_dw = VECS_MI_FLUSH_DW, + .mi_user_interrupt = VECS_MI_USER_INTERRUPT, + }, +}; + +static int cmd_handler_pipe_control(struct parser_exec_state *s) +{ + int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; + unsigned long gma; + bool index_mode = false; + unsigned int post_sync; + int ret = 0; + + post_sync = (cmd_val(s, 1) & PIPE_CONTROL_POST_SYNC_OP_MASK) >> 14; + + /* LRI post sync */ + if (cmd_val(s, 1) & PIPE_CONTROL_MMIO_WRITE) + ret = cmd_reg_handler(s, cmd_reg(s, 2), 1, "pipe_ctrl"); + /* post sync */ + else if (post_sync) { + if (post_sync == 2) + ret = cmd_reg_handler(s, 0x2350, 1, "pipe_ctrl"); + else if (post_sync == 3) + ret = cmd_reg_handler(s, 0x2358, 1, "pipe_ctrl"); + else if (post_sync == 1) { + /* check ggtt*/ + if ((cmd_val(s, 2) & (1 << 2))) { + gma = cmd_val(s, 2) & GENMASK(31, 3); + if (gmadr_bytes == 8) + gma |= (cmd_gma_hi(s, 3)) << 32; + /* Store Data Index */ + if (cmd_val(s, 1) & (1 << 21)) + index_mode = true; + ret |= cmd_address_audit(s, gma, sizeof(u64), + index_mode); + } + } + } + + if (ret) + return ret; + + if (cmd_val(s, 1) & PIPE_CONTROL_NOTIFY) + set_bit(cmd_interrupt_events[s->ring_id].pipe_control_notify, + s->workload->pending_events); + return 0; +} + +static int cmd_handler_mi_user_interrupt(struct parser_exec_state *s) +{ + set_bit(cmd_interrupt_events[s->ring_id].mi_user_interrupt, + s->workload->pending_events); + return 0; +} + +static int cmd_advance_default(struct parser_exec_state *s) +{ + return ip_gma_advance(s, cmd_length(s)); +} + +static int cmd_handler_mi_batch_buffer_end(struct parser_exec_state *s) +{ + int ret; + + if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) { + s->buf_type = BATCH_BUFFER_INSTRUCTION; + ret = ip_gma_set(s, s->ret_ip_gma_bb); + s->buf_addr_type = s->saved_buf_addr_type; + } else { + s->buf_type = RING_BUFFER_INSTRUCTION; + s->buf_addr_type = GTT_BUFFER; + if (s->ret_ip_gma_ring >= s->ring_start + s->ring_size) + s->ret_ip_gma_ring -= s->ring_size; + ret = ip_gma_set(s, s->ret_ip_gma_ring); + } + return ret; +} + +struct mi_display_flip_command_info { + int pipe; + int plane; + int event; + i915_reg_t stride_reg; + i915_reg_t ctrl_reg; + i915_reg_t surf_reg; + u64 stride_val; + u64 tile_val; + u64 surf_val; + bool async_flip; +}; + +struct plane_code_mapping { + int pipe; + int plane; + int event; +}; + +static int gen8_decode_mi_display_flip(struct parser_exec_state *s, + struct mi_display_flip_command_info *info) +{ + struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; + struct plane_code_mapping gen8_plane_code[] = { + [0] = {PIPE_A, PLANE_A, PRIMARY_A_FLIP_DONE}, + [1] = {PIPE_B, PLANE_A, PRIMARY_B_FLIP_DONE}, + [2] = {PIPE_A, PLANE_B, SPRITE_A_FLIP_DONE}, + [3] = {PIPE_B, PLANE_B, SPRITE_B_FLIP_DONE}, + [4] = {PIPE_C, PLANE_A, PRIMARY_C_FLIP_DONE}, + [5] = {PIPE_C, PLANE_B, SPRITE_C_FLIP_DONE}, + }; + u32 dword0, dword1, dword2; + u32 v; + + dword0 = cmd_val(s, 0); + dword1 = cmd_val(s, 1); + dword2 = cmd_val(s, 2); + + v = (dword0 & GENMASK(21, 19)) >> 19; + if (WARN_ON(v >= ARRAY_SIZE(gen8_plane_code))) + return -EINVAL; + + info->pipe = gen8_plane_code[v].pipe; + info->plane = gen8_plane_code[v].plane; + info->event = gen8_plane_code[v].event; + info->stride_val = (dword1 & GENMASK(15, 6)) >> 6; + info->tile_val = (dword1 & 0x1); + info->surf_val = (dword2 & GENMASK(31, 12)) >> 12; + info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1); + + if (info->plane == PLANE_A) { + info->ctrl_reg = DSPCNTR(info->pipe); + info->stride_reg = DSPSTRIDE(info->pipe); + info->surf_reg = DSPSURF(info->pipe); + } else if (info->plane == PLANE_B) { + info->ctrl_reg = SPRCTL(info->pipe); + info->stride_reg = SPRSTRIDE(info->pipe); + info->surf_reg = SPRSURF(info->pipe); + } else { + WARN_ON(1); + return -EINVAL; + } + return 0; +} + +static int skl_decode_mi_display_flip(struct parser_exec_state *s, + struct mi_display_flip_command_info *info) +{ + struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; + u32 dword0 = cmd_val(s, 0); + u32 dword1 = cmd_val(s, 1); + u32 dword2 = cmd_val(s, 2); + u32 plane = (dword0 & GENMASK(12, 8)) >> 8; + + switch (plane) { + case MI_DISPLAY_FLIP_SKL_PLANE_1_A: + info->pipe = PIPE_A; + info->event = PRIMARY_A_FLIP_DONE; + break; + case MI_DISPLAY_FLIP_SKL_PLANE_1_B: + info->pipe = PIPE_B; + info->event = PRIMARY_B_FLIP_DONE; + break; + case MI_DISPLAY_FLIP_SKL_PLANE_1_C: + info->pipe = PIPE_B; + info->event = PRIMARY_C_FLIP_DONE; + break; + default: + gvt_err("unknown plane code %d\n", plane); + return -EINVAL; + } + + info->pipe = PRIMARY_PLANE; + info->stride_val = (dword1 & GENMASK(15, 6)) >> 6; + info->tile_val = (dword1 & GENMASK(2, 0)); + info->surf_val = (dword2 & GENMASK(31, 12)) >> 12; + info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1); + + info->ctrl_reg = DSPCNTR(info->pipe); + info->stride_reg = DSPSTRIDE(info->pipe); + info->surf_reg = DSPSURF(info->pipe); + + return 0; +} + +static int gen8_check_mi_display_flip(struct parser_exec_state *s, + struct mi_display_flip_command_info *info) +{ + struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; + u32 stride, tile; + + if (!info->async_flip) + return 0; + + if (IS_SKYLAKE(dev_priv)) { + stride = vgpu_vreg(s->vgpu, info->stride_reg) & GENMASK(9, 0); + tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) & + GENMASK(12, 10)) >> 10; + } else { + stride = (vgpu_vreg(s->vgpu, info->stride_reg) & + GENMASK(15, 6)) >> 6; + tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) & (1 << 10)) >> 10; + } + + if (stride != info->stride_val) + gvt_dbg_cmd("cannot change stride during async flip\n"); + + if (tile != info->tile_val) + gvt_dbg_cmd("cannot change tile during async flip\n"); + + return 0; +} + +static int gen8_update_plane_mmio_from_mi_display_flip( + struct parser_exec_state *s, + struct mi_display_flip_command_info *info) +{ + struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; + struct intel_vgpu *vgpu = s->vgpu; + +#define write_bits(reg, e, s, v) do { \ + vgpu_vreg(vgpu, reg) &= ~GENMASK(e, s); \ + vgpu_vreg(vgpu, reg) |= (v << s); \ +} while (0) + + write_bits(info->surf_reg, 31, 12, info->surf_val); + if (IS_SKYLAKE(dev_priv)) + write_bits(info->stride_reg, 9, 0, info->stride_val); + else + write_bits(info->stride_reg, 15, 6, info->stride_val); + write_bits(info->ctrl_reg, IS_SKYLAKE(dev_priv) ? 12 : 10, + 10, info->tile_val); + +#undef write_bits + + vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(info->pipe))++; + intel_vgpu_trigger_virtual_event(vgpu, info->event); + return 0; +} + +static int decode_mi_display_flip(struct parser_exec_state *s, + struct mi_display_flip_command_info *info) +{ + struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; + + if (IS_BROADWELL(dev_priv)) + return gen8_decode_mi_display_flip(s, info); + if (IS_SKYLAKE(dev_priv)) + return skl_decode_mi_display_flip(s, info); + + return -ENODEV; +} + +static int check_mi_display_flip(struct parser_exec_state *s, + struct mi_display_flip_command_info *info) +{ + struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; + + if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) + return gen8_check_mi_display_flip(s, info); + return -ENODEV; +} + +static int update_plane_mmio_from_mi_display_flip( + struct parser_exec_state *s, + struct mi_display_flip_command_info *info) +{ + struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; + + if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) + return gen8_update_plane_mmio_from_mi_display_flip(s, info); + return -ENODEV; +} + +static int cmd_handler_mi_display_flip(struct parser_exec_state *s) +{ + struct mi_display_flip_command_info info; + int ret; + int i; + int len = cmd_length(s); + + ret = decode_mi_display_flip(s, &info); + if (ret) { + gvt_err("fail to decode MI display flip command\n"); + return ret; + } + + ret = check_mi_display_flip(s, &info); + if (ret) { + gvt_err("invalid MI display flip command\n"); + return ret; + } + + ret = update_plane_mmio_from_mi_display_flip(s, &info); + if (ret) { + gvt_err("fail to update plane mmio\n"); + return ret; + } + + for (i = 0; i < len; i++) + patch_value(s, cmd_ptr(s, i), MI_NOOP); + return 0; +} + +static bool is_wait_for_flip_pending(u32 cmd) +{ + return cmd & (MI_WAIT_FOR_PLANE_A_FLIP_PENDING | + MI_WAIT_FOR_PLANE_B_FLIP_PENDING | + MI_WAIT_FOR_PLANE_C_FLIP_PENDING | + MI_WAIT_FOR_SPRITE_A_FLIP_PENDING | + MI_WAIT_FOR_SPRITE_B_FLIP_PENDING | + MI_WAIT_FOR_SPRITE_C_FLIP_PENDING); +} + +static int cmd_handler_mi_wait_for_event(struct parser_exec_state *s) +{ + u32 cmd = cmd_val(s, 0); + + if (!is_wait_for_flip_pending(cmd)) + return 0; + + patch_value(s, cmd_ptr(s, 0), MI_NOOP); + return 0; +} + +static unsigned long get_gma_bb_from_cmd(struct parser_exec_state *s, int index) +{ + unsigned long addr; + unsigned long gma_high, gma_low; + int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; + + if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8)) + return INTEL_GVT_INVALID_ADDR; + + gma_low = cmd_val(s, index) & BATCH_BUFFER_ADDR_MASK; + if (gmadr_bytes == 4) { + addr = gma_low; + } else { + gma_high = cmd_val(s, index + 1) & BATCH_BUFFER_ADDR_HIGH_MASK; + addr = (((unsigned long)gma_high) << 32) | gma_low; + } + return addr; +} + +static inline int cmd_address_audit(struct parser_exec_state *s, + unsigned long guest_gma, int op_size, bool index_mode) +{ + struct intel_vgpu *vgpu = s->vgpu; + u32 max_surface_size = vgpu->gvt->device_info.max_surface_size; + int i; + int ret; + + if (op_size > max_surface_size) { + gvt_err("command address audit fail name %s\n", s->info->name); + return -EINVAL; + } + + if (index_mode) { + if (guest_gma >= GTT_PAGE_SIZE / sizeof(u64)) { + ret = -EINVAL; + goto err; + } + } else if ((!vgpu_gmadr_is_valid(s->vgpu, guest_gma)) || + (!vgpu_gmadr_is_valid(s->vgpu, + guest_gma + op_size - 1))) { + ret = -EINVAL; + goto err; + } + return 0; +err: + gvt_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n", + s->info->name, guest_gma, op_size); + + pr_err("cmd dump: "); + for (i = 0; i < cmd_length(s); i++) { + if (!(i % 4)) + pr_err("\n%08x ", cmd_val(s, i)); + else + pr_err("%08x ", cmd_val(s, i)); + } + pr_err("\nvgpu%d: aperture 0x%llx - 0x%llx, hidden 0x%llx - 0x%llx\n", + vgpu->id, + vgpu_aperture_gmadr_base(vgpu), + vgpu_aperture_gmadr_end(vgpu), + vgpu_hidden_gmadr_base(vgpu), + vgpu_hidden_gmadr_end(vgpu)); + return ret; +} + +static int cmd_handler_mi_store_data_imm(struct parser_exec_state *s) +{ + int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; + int op_size = (cmd_length(s) - 3) * sizeof(u32); + int core_id = (cmd_val(s, 2) & (1 << 0)) ? 1 : 0; + unsigned long gma, gma_low, gma_high; + int ret = 0; + + /* check ppggt */ + if (!(cmd_val(s, 0) & (1 << 22))) + return 0; + + gma = cmd_val(s, 2) & GENMASK(31, 2); + + if (gmadr_bytes == 8) { + gma_low = cmd_val(s, 1) & GENMASK(31, 2); + gma_high = cmd_val(s, 2) & GENMASK(15, 0); + gma = (gma_high << 32) | gma_low; + core_id = (cmd_val(s, 1) & (1 << 0)) ? 1 : 0; + } + ret = cmd_address_audit(s, gma + op_size * core_id, op_size, false); + return ret; +} + +static inline int unexpected_cmd(struct parser_exec_state *s) +{ + gvt_err("vgpu%d: Unexpected %s in command buffer!\n", + s->vgpu->id, s->info->name); + return -EINVAL; +} + +static int cmd_handler_mi_semaphore_wait(struct parser_exec_state *s) +{ + return unexpected_cmd(s); +} + +static int cmd_handler_mi_report_perf_count(struct parser_exec_state *s) +{ + return unexpected_cmd(s); +} + +static int cmd_handler_mi_op_2e(struct parser_exec_state *s) +{ + return unexpected_cmd(s); +} + +static int cmd_handler_mi_op_2f(struct parser_exec_state *s) +{ + int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; + int op_size = ((1 << (cmd_val(s, 0) & GENMASK(20, 19) >> 19)) * + sizeof(u32)); + unsigned long gma, gma_high; + int ret = 0; + + if (!(cmd_val(s, 0) & (1 << 22))) + return ret; + + gma = cmd_val(s, 1) & GENMASK(31, 2); + if (gmadr_bytes == 8) { + gma_high = cmd_val(s, 2) & GENMASK(15, 0); + gma = (gma_high << 32) | gma; + } + ret = cmd_address_audit(s, gma, op_size, false); + return ret; +} + +static int cmd_handler_mi_store_data_index(struct parser_exec_state *s) +{ + return unexpected_cmd(s); +} + +static int cmd_handler_mi_clflush(struct parser_exec_state *s) +{ + return unexpected_cmd(s); +} + +static int cmd_handler_mi_conditional_batch_buffer_end( + struct parser_exec_state *s) +{ + return unexpected_cmd(s); +} + +static int cmd_handler_mi_update_gtt(struct parser_exec_state *s) +{ + return unexpected_cmd(s); +} + +static int cmd_handler_mi_flush_dw(struct parser_exec_state *s) +{ + int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; + unsigned long gma; + bool index_mode = false; + int ret = 0; + + /* Check post-sync and ppgtt bit */ + if (((cmd_val(s, 0) >> 14) & 0x3) && (cmd_val(s, 1) & (1 << 2))) { + gma = cmd_val(s, 1) & GENMASK(31, 3); + if (gmadr_bytes == 8) + gma |= (cmd_val(s, 2) & GENMASK(15, 0)) << 32; + /* Store Data Index */ + if (cmd_val(s, 0) & (1 << 21)) + index_mode = true; + ret = cmd_address_audit(s, gma, sizeof(u64), index_mode); + } + /* Check notify bit */ + if ((cmd_val(s, 0) & (1 << 8))) + set_bit(cmd_interrupt_events[s->ring_id].mi_flush_dw, + s->workload->pending_events); + return ret; +} + +static void addr_type_update_snb(struct parser_exec_state *s) +{ + if ((s->buf_type == RING_BUFFER_INSTRUCTION) && + (BATCH_BUFFER_ADR_SPACE_BIT(cmd_val(s, 0)) == 1)) { + s->buf_addr_type = PPGTT_BUFFER; + } +} + + +static int copy_gma_to_hva(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm, + unsigned long gma, unsigned long end_gma, void *va) +{ + unsigned long copy_len, offset; + unsigned long len = 0; + unsigned long gpa; + + while (gma != end_gma) { + gpa = intel_vgpu_gma_to_gpa(mm, gma); + if (gpa == INTEL_GVT_INVALID_ADDR) { + gvt_err("invalid gma address: %lx\n", gma); + return -EFAULT; + } + + offset = gma & (GTT_PAGE_SIZE - 1); + + copy_len = (end_gma - gma) >= (GTT_PAGE_SIZE - offset) ? + GTT_PAGE_SIZE - offset : end_gma - gma; + + intel_gvt_hypervisor_read_gpa(vgpu, gpa, va + len, copy_len); + + len += copy_len; + gma += copy_len; + } + return 0; +} + + +/* + * Check whether a batch buffer needs to be scanned. Currently + * the only criteria is based on privilege. + */ +static int batch_buffer_needs_scan(struct parser_exec_state *s) +{ + struct intel_gvt *gvt = s->vgpu->gvt; + + if (bypass_batch_buffer_scan) + return 0; + + if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { + /* BDW decides privilege based on address space */ + if (cmd_val(s, 0) & (1 << 8)) + return 0; + } + return 1; +} + +static uint32_t find_bb_size(struct parser_exec_state *s) +{ + unsigned long gma = 0; + struct cmd_info *info; + uint32_t bb_size = 0; + uint32_t cmd_len = 0; + bool met_bb_end = false; + u32 cmd; + + /* get the start gm address of the batch buffer */ + gma = get_gma_bb_from_cmd(s, 1); + cmd = cmd_val(s, 0); + + info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); + if (info == NULL) { + gvt_err("unknown cmd 0x%x, opcode=0x%x\n", + cmd, get_opcode(cmd, s->ring_id)); + return -EINVAL; + } + do { + copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, + gma, gma + 4, &cmd); + info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); + if (info == NULL) { + gvt_err("unknown cmd 0x%x, opcode=0x%x\n", + cmd, get_opcode(cmd, s->ring_id)); + return -EINVAL; + } + + if (info->opcode == OP_MI_BATCH_BUFFER_END) { + met_bb_end = true; + } else if (info->opcode == OP_MI_BATCH_BUFFER_START) { + if (BATCH_BUFFER_2ND_LEVEL_BIT(cmd) == 0) { + /* chained batch buffer */ + met_bb_end = true; + } + } + cmd_len = get_cmd_length(info, cmd) << 2; + bb_size += cmd_len; + gma += cmd_len; + + } while (!met_bb_end); + + return bb_size; +} + +static u32 *vmap_batch(struct drm_i915_gem_object *obj, + unsigned int start, unsigned int len) +{ + int i; + void *addr = NULL; + struct sg_page_iter sg_iter; + int first_page = start >> PAGE_SHIFT; + int last_page = (len + start + 4095) >> PAGE_SHIFT; + int npages = last_page - first_page; + struct page **pages; + + pages = drm_malloc_ab(npages, sizeof(*pages)); + if (pages == NULL) { + DRM_DEBUG_DRIVER("Failed to get space for pages\n"); + goto finish; + } + + i = 0; + for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, + first_page) { + pages[i++] = sg_page_iter_page(&sg_iter); + if (i == npages) + break; + } + + addr = vmap(pages, i, 0, PAGE_KERNEL); + if (addr == NULL) { + DRM_DEBUG_DRIVER("Failed to vmap pages\n"); + goto finish; + } + +finish: + if (pages) + drm_free_large(pages); + return (u32 *)addr; +} + + +static int perform_bb_shadow(struct parser_exec_state *s) +{ + struct intel_shadow_bb_entry *entry_obj; + unsigned long gma = 0; + uint32_t bb_size; + void *dst = NULL; + int ret = 0; + + /* get the start gm address of the batch buffer */ + gma = get_gma_bb_from_cmd(s, 1); + + /* get the size of the batch buffer */ + bb_size = find_bb_size(s); + + /* allocate shadow batch buffer */ + entry_obj = kmalloc(sizeof(*entry_obj), GFP_KERNEL); + if (entry_obj == NULL) + return -ENOMEM; + + entry_obj->obj = i915_gem_object_create(&(s->vgpu->gvt->dev_priv->drm), + round_up(bb_size, PAGE_SIZE)); + if (entry_obj->obj == NULL) + return -ENOMEM; + entry_obj->len = bb_size; + INIT_LIST_HEAD(&entry_obj->list); + + ret = i915_gem_object_get_pages(entry_obj->obj); + if (ret) + return ret; + + i915_gem_object_pin_pages(entry_obj->obj); + + /* get the va of the shadow batch buffer */ + dst = (void *)vmap_batch(entry_obj->obj, 0, bb_size); + if (!dst) { + gvt_err("failed to vmap shadow batch\n"); + ret = -ENOMEM; + goto unpin_src; + } + + ret = i915_gem_object_set_to_cpu_domain(entry_obj->obj, false); + if (ret) { + gvt_err("failed to set shadow batch to CPU\n"); + goto unmap_src; + } + + entry_obj->va = dst; + entry_obj->bb_start_cmd_va = s->ip_va; + + /* copy batch buffer to shadow batch buffer*/ + ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, + gma, gma + bb_size, dst); + if (ret) { + gvt_err("fail to copy guest ring buffer\n"); + return ret; + } + + list_add(&entry_obj->list, &s->workload->shadow_bb); + /* + * ip_va saves the virtual address of the shadow batch buffer, while + * ip_gma saves the graphics address of the original batch buffer. + * As the shadow batch buffer is just a copy from the originial one, + * it should be right to use shadow batch buffer'va and original batch + * buffer's gma in pair. After all, we don't want to pin the shadow + * buffer here (too early). + */ + s->ip_va = dst; + s->ip_gma = gma; + + return 0; + +unmap_src: + vunmap(dst); +unpin_src: + i915_gem_object_unpin_pages(entry_obj->obj); + + return ret; +} + +static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s) +{ + bool second_level; + int ret = 0; + + if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) { + gvt_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n"); + return -EINVAL; + } + + second_level = BATCH_BUFFER_2ND_LEVEL_BIT(cmd_val(s, 0)) == 1; + if (second_level && (s->buf_type != BATCH_BUFFER_INSTRUCTION)) { + gvt_err("Jumping to 2nd level BB from RB is not allowed\n"); + return -EINVAL; + } + + s->saved_buf_addr_type = s->buf_addr_type; + addr_type_update_snb(s); + if (s->buf_type == RING_BUFFER_INSTRUCTION) { + s->ret_ip_gma_ring = s->ip_gma + cmd_length(s) * sizeof(u32); + s->buf_type = BATCH_BUFFER_INSTRUCTION; + } else if (second_level) { + s->buf_type = BATCH_BUFFER_2ND_LEVEL; + s->ret_ip_gma_bb = s->ip_gma + cmd_length(s) * sizeof(u32); + s->ret_bb_va = s->ip_va + cmd_length(s) * sizeof(u32); + } + + if (batch_buffer_needs_scan(s)) { + ret = perform_bb_shadow(s); + if (ret < 0) + gvt_err("invalid shadow batch buffer\n"); + } else { + /* emulate a batch buffer end to do return right */ + ret = cmd_handler_mi_batch_buffer_end(s); + if (ret < 0) + return ret; + } + + return ret; +} + +static struct cmd_info cmd_info[] = { + {"MI_NOOP", OP_MI_NOOP, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL}, + + {"MI_SET_PREDICATE", OP_MI_SET_PREDICATE, F_LEN_CONST, R_ALL, D_ALL, + 0, 1, NULL}, + + {"MI_USER_INTERRUPT", OP_MI_USER_INTERRUPT, F_LEN_CONST, R_ALL, D_ALL, + 0, 1, cmd_handler_mi_user_interrupt}, + + {"MI_WAIT_FOR_EVENT", OP_MI_WAIT_FOR_EVENT, F_LEN_CONST, R_RCS | R_BCS, + D_ALL, 0, 1, cmd_handler_mi_wait_for_event}, + + {"MI_FLUSH", OP_MI_FLUSH, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL}, + + {"MI_ARB_CHECK", OP_MI_ARB_CHECK, F_LEN_CONST, R_ALL, D_ALL, 0, 1, + NULL}, + + {"MI_RS_CONTROL", OP_MI_RS_CONTROL, F_LEN_CONST, R_RCS, D_ALL, 0, 1, + NULL}, + + {"MI_REPORT_HEAD", OP_MI_REPORT_HEAD, F_LEN_CONST, R_ALL, D_ALL, 0, 1, + NULL}, + + {"MI_ARB_ON_OFF", OP_MI_ARB_ON_OFF, F_LEN_CONST, R_ALL, D_ALL, 0, 1, + NULL}, + + {"MI_URB_ATOMIC_ALLOC", OP_MI_URB_ATOMIC_ALLOC, F_LEN_CONST, R_RCS, + D_ALL, 0, 1, NULL}, + + {"MI_BATCH_BUFFER_END", OP_MI_BATCH_BUFFER_END, + F_IP_ADVANCE_CUSTOM | F_LEN_CONST, R_ALL, D_ALL, 0, 1, + cmd_handler_mi_batch_buffer_end}, + + {"MI_SUSPEND_FLUSH", OP_MI_SUSPEND_FLUSH, F_LEN_CONST, R_ALL, D_ALL, + 0, 1, NULL}, + + {"MI_PREDICATE", OP_MI_PREDICATE, F_LEN_CONST, R_RCS, D_ALL, 0, 1, + NULL}, + + {"MI_TOPOLOGY_FILTER", OP_MI_TOPOLOGY_FILTER, F_LEN_CONST, R_ALL, + D_ALL, 0, 1, NULL}, + + {"MI_SET_APPID", OP_MI_SET_APPID, F_LEN_CONST, R_ALL, D_ALL, 0, 1, + NULL}, + + {"MI_RS_CONTEXT", OP_MI_RS_CONTEXT, F_LEN_CONST, R_RCS, D_ALL, 0, 1, + NULL}, + + {"MI_DISPLAY_FLIP", OP_MI_DISPLAY_FLIP, F_LEN_VAR | F_POST_HANDLE, + R_RCS | R_BCS, D_ALL, 0, 8, cmd_handler_mi_display_flip}, + + {"MI_SEMAPHORE_MBOX", OP_MI_SEMAPHORE_MBOX, F_LEN_VAR, R_ALL, D_ALL, + 0, 8, NULL}, + + {"MI_MATH", OP_MI_MATH, F_LEN_VAR, R_ALL, D_ALL, 0, 8, NULL}, + + {"MI_URB_CLEAR", OP_MI_URB_CLEAR, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"ME_SEMAPHORE_SIGNAL", OP_MI_SEMAPHORE_SIGNAL, F_LEN_VAR, R_ALL, + D_BDW_PLUS, 0, 8, NULL}, + + {"ME_SEMAPHORE_WAIT", OP_MI_SEMAPHORE_WAIT, F_LEN_VAR, R_ALL, D_BDW_PLUS, + ADDR_FIX_1(2), 8, cmd_handler_mi_semaphore_wait}, + + {"MI_STORE_DATA_IMM", OP_MI_STORE_DATA_IMM, F_LEN_VAR, R_ALL, D_BDW_PLUS, + ADDR_FIX_1(1), 10, cmd_handler_mi_store_data_imm}, + + {"MI_STORE_DATA_INDEX", OP_MI_STORE_DATA_INDEX, F_LEN_VAR, R_ALL, D_ALL, + 0, 8, cmd_handler_mi_store_data_index}, + + {"MI_LOAD_REGISTER_IMM", OP_MI_LOAD_REGISTER_IMM, F_LEN_VAR, R_ALL, + D_ALL, 0, 8, cmd_handler_lri}, + + {"MI_UPDATE_GTT", OP_MI_UPDATE_GTT, F_LEN_VAR, R_ALL, D_BDW_PLUS, 0, 10, + cmd_handler_mi_update_gtt}, + + {"MI_STORE_REGISTER_MEM", OP_MI_STORE_REGISTER_MEM, F_LEN_VAR, R_ALL, + D_ALL, ADDR_FIX_1(2), 8, cmd_handler_srm}, + + {"MI_FLUSH_DW", OP_MI_FLUSH_DW, F_LEN_VAR, R_ALL, D_ALL, 0, 6, + cmd_handler_mi_flush_dw}, + + {"MI_CLFLUSH", OP_MI_CLFLUSH, F_LEN_VAR, R_ALL, D_ALL, ADDR_FIX_1(1), + 10, cmd_handler_mi_clflush}, + + {"MI_REPORT_PERF_COUNT", OP_MI_REPORT_PERF_COUNT, F_LEN_VAR, R_ALL, + D_ALL, ADDR_FIX_1(1), 6, cmd_handler_mi_report_perf_count}, + + {"MI_LOAD_REGISTER_MEM", OP_MI_LOAD_REGISTER_MEM, F_LEN_VAR, R_ALL, + D_ALL, ADDR_FIX_1(2), 8, cmd_handler_lrm}, + + {"MI_LOAD_REGISTER_REG", OP_MI_LOAD_REGISTER_REG, F_LEN_VAR, R_ALL, + D_ALL, 0, 8, cmd_handler_lrr}, + + {"MI_RS_STORE_DATA_IMM", OP_MI_RS_STORE_DATA_IMM, F_LEN_VAR, R_RCS, + D_ALL, 0, 8, NULL}, + + {"MI_LOAD_URB_MEM", OP_MI_LOAD_URB_MEM, F_LEN_VAR, R_RCS, D_ALL, + ADDR_FIX_1(2), 8, NULL}, + + {"MI_STORE_URM_MEM", OP_MI_STORE_URM_MEM, F_LEN_VAR, R_RCS, D_ALL, + ADDR_FIX_1(2), 8, NULL}, + + {"MI_OP_2E", OP_MI_2E, F_LEN_VAR, R_ALL, D_BDW_PLUS, ADDR_FIX_2(1, 2), + 8, cmd_handler_mi_op_2e}, + + {"MI_OP_2F", OP_MI_2F, F_LEN_VAR, R_ALL, D_BDW_PLUS, ADDR_FIX_1(1), + 8, cmd_handler_mi_op_2f}, + + {"MI_BATCH_BUFFER_START", OP_MI_BATCH_BUFFER_START, + F_IP_ADVANCE_CUSTOM, R_ALL, D_ALL, 0, 8, + cmd_handler_mi_batch_buffer_start}, + + {"MI_CONDITIONAL_BATCH_BUFFER_END", OP_MI_CONDITIONAL_BATCH_BUFFER_END, + F_LEN_VAR, R_ALL, D_ALL, ADDR_FIX_1(2), 8, + cmd_handler_mi_conditional_batch_buffer_end}, + + {"MI_LOAD_SCAN_LINES_INCL", OP_MI_LOAD_SCAN_LINES_INCL, F_LEN_CONST, + R_RCS | R_BCS, D_ALL, 0, 2, NULL}, + + {"XY_SETUP_BLT", OP_XY_SETUP_BLT, F_LEN_VAR, R_BCS, D_ALL, + ADDR_FIX_2(4, 7), 8, NULL}, + + {"XY_SETUP_CLIP_BLT", OP_XY_SETUP_CLIP_BLT, F_LEN_VAR, R_BCS, D_ALL, + 0, 8, NULL}, + + {"XY_SETUP_MONO_PATTERN_SL_BLT", OP_XY_SETUP_MONO_PATTERN_SL_BLT, + F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL}, + + {"XY_PIXEL_BLT", OP_XY_PIXEL_BLT, F_LEN_VAR, R_BCS, D_ALL, 0, 8, NULL}, + + {"XY_SCANLINES_BLT", OP_XY_SCANLINES_BLT, F_LEN_VAR, R_BCS, D_ALL, + 0, 8, NULL}, + + {"XY_TEXT_BLT", OP_XY_TEXT_BLT, F_LEN_VAR, R_BCS, D_ALL, + ADDR_FIX_1(3), 8, NULL}, + + {"XY_TEXT_IMMEDIATE_BLT", OP_XY_TEXT_IMMEDIATE_BLT, F_LEN_VAR, R_BCS, + D_ALL, 0, 8, NULL}, + + {"XY_COLOR_BLT", OP_XY_COLOR_BLT, F_LEN_VAR, R_BCS, D_ALL, + ADDR_FIX_1(4), 8, NULL}, + + {"XY_PAT_BLT", OP_XY_PAT_BLT, F_LEN_VAR, R_BCS, D_ALL, + ADDR_FIX_2(4, 5), 8, NULL}, + + {"XY_MONO_PAT_BLT", OP_XY_MONO_PAT_BLT, F_LEN_VAR, R_BCS, D_ALL, + ADDR_FIX_1(4), 8, NULL}, + + {"XY_SRC_COPY_BLT", OP_XY_SRC_COPY_BLT, F_LEN_VAR, R_BCS, D_ALL, + ADDR_FIX_2(4, 7), 8, NULL}, + + {"XY_MONO_SRC_COPY_BLT", OP_XY_MONO_SRC_COPY_BLT, F_LEN_VAR, R_BCS, + D_ALL, ADDR_FIX_2(4, 5), 8, NULL}, + + {"XY_FULL_BLT", OP_XY_FULL_BLT, F_LEN_VAR, R_BCS, D_ALL, 0, 8, NULL}, + + {"XY_FULL_MONO_SRC_BLT", OP_XY_FULL_MONO_SRC_BLT, F_LEN_VAR, R_BCS, + D_ALL, ADDR_FIX_3(4, 5, 8), 8, NULL}, + + {"XY_FULL_MONO_PATTERN_BLT", OP_XY_FULL_MONO_PATTERN_BLT, F_LEN_VAR, + R_BCS, D_ALL, ADDR_FIX_2(4, 7), 8, NULL}, + + {"XY_FULL_MONO_PATTERN_MONO_SRC_BLT", + OP_XY_FULL_MONO_PATTERN_MONO_SRC_BLT, + F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 5), 8, NULL}, + + {"XY_MONO_PAT_FIXED_BLT", OP_XY_MONO_PAT_FIXED_BLT, F_LEN_VAR, R_BCS, + D_ALL, ADDR_FIX_1(4), 8, NULL}, + + {"XY_MONO_SRC_COPY_IMMEDIATE_BLT", OP_XY_MONO_SRC_COPY_IMMEDIATE_BLT, + F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL}, + + {"XY_PAT_BLT_IMMEDIATE", OP_XY_PAT_BLT_IMMEDIATE, F_LEN_VAR, R_BCS, + D_ALL, ADDR_FIX_1(4), 8, NULL}, + + {"XY_SRC_COPY_CHROMA_BLT", OP_XY_SRC_COPY_CHROMA_BLT, F_LEN_VAR, R_BCS, + D_ALL, ADDR_FIX_2(4, 7), 8, NULL}, + + {"XY_FULL_IMMEDIATE_PATTERN_BLT", OP_XY_FULL_IMMEDIATE_PATTERN_BLT, + F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 7), 8, NULL}, + + {"XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT", + OP_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT, + F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 5), 8, NULL}, + + {"XY_PAT_CHROMA_BLT", OP_XY_PAT_CHROMA_BLT, F_LEN_VAR, R_BCS, D_ALL, + ADDR_FIX_2(4, 5), 8, NULL}, + + {"XY_PAT_CHROMA_BLT_IMMEDIATE", OP_XY_PAT_CHROMA_BLT_IMMEDIATE, + F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL}, + + {"3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP", + OP_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_VIEWPORT_STATE_POINTERS_CC", + OP_3DSTATE_VIEWPORT_STATE_POINTERS_CC, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_BLEND_STATE_POINTERS", + OP_3DSTATE_BLEND_STATE_POINTERS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DEPTH_STENCIL_STATE_POINTERS", + OP_3DSTATE_DEPTH_STENCIL_STATE_POINTERS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_BINDING_TABLE_POINTERS_VS", + OP_3DSTATE_BINDING_TABLE_POINTERS_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_BINDING_TABLE_POINTERS_HS", + OP_3DSTATE_BINDING_TABLE_POINTERS_HS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_BINDING_TABLE_POINTERS_DS", + OP_3DSTATE_BINDING_TABLE_POINTERS_DS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_BINDING_TABLE_POINTERS_GS", + OP_3DSTATE_BINDING_TABLE_POINTERS_GS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_BINDING_TABLE_POINTERS_PS", + OP_3DSTATE_BINDING_TABLE_POINTERS_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SAMPLER_STATE_POINTERS_VS", + OP_3DSTATE_SAMPLER_STATE_POINTERS_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SAMPLER_STATE_POINTERS_HS", + OP_3DSTATE_SAMPLER_STATE_POINTERS_HS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SAMPLER_STATE_POINTERS_DS", + OP_3DSTATE_SAMPLER_STATE_POINTERS_DS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SAMPLER_STATE_POINTERS_GS", + OP_3DSTATE_SAMPLER_STATE_POINTERS_GS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SAMPLER_STATE_POINTERS_PS", + OP_3DSTATE_SAMPLER_STATE_POINTERS_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_URB_VS", OP_3DSTATE_URB_VS, F_LEN_VAR, R_RCS, D_ALL, + 0, 8, NULL}, + + {"3DSTATE_URB_HS", OP_3DSTATE_URB_HS, F_LEN_VAR, R_RCS, D_ALL, + 0, 8, NULL}, + + {"3DSTATE_URB_DS", OP_3DSTATE_URB_DS, F_LEN_VAR, R_RCS, D_ALL, + 0, 8, NULL}, + + {"3DSTATE_URB_GS", OP_3DSTATE_URB_GS, F_LEN_VAR, R_RCS, D_ALL, + 0, 8, NULL}, + + {"3DSTATE_GATHER_CONSTANT_VS", OP_3DSTATE_GATHER_CONSTANT_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_GATHER_CONSTANT_GS", OP_3DSTATE_GATHER_CONSTANT_GS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_GATHER_CONSTANT_HS", OP_3DSTATE_GATHER_CONSTANT_HS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_GATHER_CONSTANT_DS", OP_3DSTATE_GATHER_CONSTANT_DS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_GATHER_CONSTANT_PS", OP_3DSTATE_GATHER_CONSTANT_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DX9_CONSTANTF_VS", OP_3DSTATE_DX9_CONSTANTF_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 11, NULL}, + + {"3DSTATE_DX9_CONSTANTF_PS", OP_3DSTATE_DX9_CONSTANTF_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 11, NULL}, + + {"3DSTATE_DX9_CONSTANTI_VS", OP_3DSTATE_DX9_CONSTANTI_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DX9_CONSTANTI_PS", OP_3DSTATE_DX9_CONSTANTI_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DX9_CONSTANTB_VS", OP_3DSTATE_DX9_CONSTANTB_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DX9_CONSTANTB_PS", OP_3DSTATE_DX9_CONSTANTB_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DX9_LOCAL_VALID_VS", OP_3DSTATE_DX9_LOCAL_VALID_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DX9_LOCAL_VALID_PS", OP_3DSTATE_DX9_LOCAL_VALID_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DX9_GENERATE_ACTIVE_VS", OP_3DSTATE_DX9_GENERATE_ACTIVE_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DX9_GENERATE_ACTIVE_PS", OP_3DSTATE_DX9_GENERATE_ACTIVE_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_BINDING_TABLE_EDIT_VS", OP_3DSTATE_BINDING_TABLE_EDIT_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, + + {"3DSTATE_BINDING_TABLE_EDIT_GS", OP_3DSTATE_BINDING_TABLE_EDIT_GS, + F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, + + {"3DSTATE_BINDING_TABLE_EDIT_HS", OP_3DSTATE_BINDING_TABLE_EDIT_HS, + F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, + + {"3DSTATE_BINDING_TABLE_EDIT_DS", OP_3DSTATE_BINDING_TABLE_EDIT_DS, + F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, + + {"3DSTATE_BINDING_TABLE_EDIT_PS", OP_3DSTATE_BINDING_TABLE_EDIT_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, + + {"3DSTATE_VF_INSTANCING", OP_3DSTATE_VF_INSTANCING, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_VF_SGVS", OP_3DSTATE_VF_SGVS, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8, + NULL}, + + {"3DSTATE_VF_TOPOLOGY", OP_3DSTATE_VF_TOPOLOGY, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_WM_CHROMAKEY", OP_3DSTATE_WM_CHROMAKEY, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_PS_BLEND", OP_3DSTATE_PS_BLEND, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, + 8, NULL}, + + {"3DSTATE_WM_DEPTH_STENCIL", OP_3DSTATE_WM_DEPTH_STENCIL, F_LEN_VAR, + R_RCS, D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_PS_EXTRA", OP_3DSTATE_PS_EXTRA, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, + 8, NULL}, + + {"3DSTATE_RASTER", OP_3DSTATE_RASTER, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8, + NULL}, + + {"3DSTATE_SBE_SWIZ", OP_3DSTATE_SBE_SWIZ, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8, + NULL}, + + {"3DSTATE_WM_HZ_OP", OP_3DSTATE_WM_HZ_OP, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8, + NULL}, + + {"3DSTATE_VERTEX_BUFFERS", OP_3DSTATE_VERTEX_BUFFERS, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_VERTEX_ELEMENTS", OP_3DSTATE_VERTEX_ELEMENTS, F_LEN_VAR, + R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_INDEX_BUFFER", OP_3DSTATE_INDEX_BUFFER, F_LEN_VAR, R_RCS, + D_BDW_PLUS, ADDR_FIX_1(2), 8, NULL}, + + {"3DSTATE_VF_STATISTICS", OP_3DSTATE_VF_STATISTICS, F_LEN_CONST, + R_RCS, D_ALL, 0, 1, NULL}, + + {"3DSTATE_VF", OP_3DSTATE_VF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_CC_STATE_POINTERS", OP_3DSTATE_CC_STATE_POINTERS, F_LEN_VAR, + R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SCISSOR_STATE_POINTERS", OP_3DSTATE_SCISSOR_STATE_POINTERS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_GS", OP_3DSTATE_GS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_CLIP", OP_3DSTATE_CLIP, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_WM", OP_3DSTATE_WM, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_CONSTANT_GS", OP_3DSTATE_CONSTANT_GS, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_CONSTANT_PS", OP_3DSTATE_CONSTANT_PS, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_SAMPLE_MASK", OP_3DSTATE_SAMPLE_MASK, F_LEN_VAR, R_RCS, + D_ALL, 0, 8, NULL}, + + {"3DSTATE_CONSTANT_HS", OP_3DSTATE_CONSTANT_HS, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_CONSTANT_DS", OP_3DSTATE_CONSTANT_DS, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_HS", OP_3DSTATE_HS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_TE", OP_3DSTATE_TE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DS", OP_3DSTATE_DS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_STREAMOUT", OP_3DSTATE_STREAMOUT, F_LEN_VAR, R_RCS, + D_ALL, 0, 8, NULL}, + + {"3DSTATE_SBE", OP_3DSTATE_SBE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_PS", OP_3DSTATE_PS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_DRAWING_RECTANGLE", OP_3DSTATE_DRAWING_RECTANGLE, F_LEN_VAR, + R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SAMPLER_PALETTE_LOAD0", OP_3DSTATE_SAMPLER_PALETTE_LOAD0, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_CHROMA_KEY", OP_3DSTATE_CHROMA_KEY, F_LEN_VAR, R_RCS, D_ALL, + 0, 8, NULL}, + + {"3DSTATE_DEPTH_BUFFER", OP_3DSTATE_DEPTH_BUFFER, F_LEN_VAR, R_RCS, + D_ALL, ADDR_FIX_1(2), 8, NULL}, + + {"3DSTATE_POLY_STIPPLE_OFFSET", OP_3DSTATE_POLY_STIPPLE_OFFSET, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_POLY_STIPPLE_PATTERN", OP_3DSTATE_POLY_STIPPLE_PATTERN, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_LINE_STIPPLE", OP_3DSTATE_LINE_STIPPLE, F_LEN_VAR, R_RCS, + D_ALL, 0, 8, NULL}, + + {"3DSTATE_AA_LINE_PARAMS", OP_3DSTATE_AA_LINE_PARAMS, F_LEN_VAR, R_RCS, + D_ALL, 0, 8, NULL}, + + {"3DSTATE_GS_SVB_INDEX", OP_3DSTATE_GS_SVB_INDEX, F_LEN_VAR, R_RCS, + D_ALL, 0, 8, NULL}, + + {"3DSTATE_SAMPLER_PALETTE_LOAD1", OP_3DSTATE_SAMPLER_PALETTE_LOAD1, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_MULTISAMPLE", OP_3DSTATE_MULTISAMPLE_BDW, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"3DSTATE_STENCIL_BUFFER", OP_3DSTATE_STENCIL_BUFFER, F_LEN_VAR, R_RCS, + D_ALL, ADDR_FIX_1(2), 8, NULL}, + + {"3DSTATE_HIER_DEPTH_BUFFER", OP_3DSTATE_HIER_DEPTH_BUFFER, F_LEN_VAR, + R_RCS, D_ALL, ADDR_FIX_1(2), 8, NULL}, + + {"3DSTATE_CLEAR_PARAMS", OP_3DSTATE_CLEAR_PARAMS, F_LEN_VAR, + R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_PUSH_CONSTANT_ALLOC_VS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_VS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_PUSH_CONSTANT_ALLOC_HS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_HS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_PUSH_CONSTANT_ALLOC_DS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_DS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_PUSH_CONSTANT_ALLOC_GS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_GS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_PUSH_CONSTANT_ALLOC_PS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_PS, + F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_MONOFILTER_SIZE", OP_3DSTATE_MONOFILTER_SIZE, F_LEN_VAR, + R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SO_DECL_LIST", OP_3DSTATE_SO_DECL_LIST, F_LEN_VAR, R_RCS, + D_ALL, 0, 9, NULL}, + + {"3DSTATE_SO_BUFFER", OP_3DSTATE_SO_BUFFER, F_LEN_VAR, R_RCS, D_BDW_PLUS, + ADDR_FIX_2(2, 4), 8, NULL}, + + {"3DSTATE_BINDING_TABLE_POOL_ALLOC", + OP_3DSTATE_BINDING_TABLE_POOL_ALLOC, + F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL}, + + {"3DSTATE_GATHER_POOL_ALLOC", OP_3DSTATE_GATHER_POOL_ALLOC, + F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL}, + + {"3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC", + OP_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC, + F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL}, + + {"3DSTATE_SAMPLE_PATTERN", OP_3DSTATE_SAMPLE_PATTERN, F_LEN_VAR, R_RCS, + D_BDW_PLUS, 0, 8, NULL}, + + {"PIPE_CONTROL", OP_PIPE_CONTROL, F_LEN_VAR, R_RCS, D_ALL, + ADDR_FIX_1(2), 8, cmd_handler_pipe_control}, + + {"3DPRIMITIVE", OP_3DPRIMITIVE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"PIPELINE_SELECT", OP_PIPELINE_SELECT, F_LEN_CONST, R_RCS, D_ALL, 0, + 1, NULL}, + + {"STATE_PREFETCH", OP_STATE_PREFETCH, F_LEN_VAR, R_RCS, D_ALL, + ADDR_FIX_1(1), 8, NULL}, + + {"STATE_SIP", OP_STATE_SIP, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"STATE_BASE_ADDRESS", OP_STATE_BASE_ADDRESS, F_LEN_VAR, R_RCS, D_BDW_PLUS, + ADDR_FIX_5(1, 3, 4, 5, 6), 8, NULL}, + + {"OP_3D_MEDIA_0_1_4", OP_3D_MEDIA_0_1_4, F_LEN_VAR, R_RCS, D_ALL, + ADDR_FIX_1(1), 8, NULL}, + + {"3DSTATE_VS", OP_3DSTATE_VS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_SF", OP_3DSTATE_SF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, + + {"3DSTATE_CONSTANT_VS", OP_3DSTATE_CONSTANT_VS, F_LEN_VAR, R_RCS, D_BDW_PLUS, + 0, 8, NULL}, + + {"3DSTATE_COMPONENT_PACKING", OP_3DSTATE_COMPONENT_PACKING, F_LEN_VAR, R_RCS, + D_SKL_PLUS, 0, 8, NULL}, + + {"MEDIA_INTERFACE_DESCRIPTOR_LOAD", OP_MEDIA_INTERFACE_DESCRIPTOR_LOAD, + F_LEN_VAR, R_RCS, D_ALL, 0, 16, NULL}, + + {"MEDIA_GATEWAY_STATE", OP_MEDIA_GATEWAY_STATE, F_LEN_VAR, R_RCS, D_ALL, + 0, 16, NULL}, + + {"MEDIA_STATE_FLUSH", OP_MEDIA_STATE_FLUSH, F_LEN_VAR, R_RCS, D_ALL, + 0, 16, NULL}, + + {"MEDIA_OBJECT", OP_MEDIA_OBJECT, F_LEN_VAR, R_RCS, D_ALL, 0, 16, NULL}, + + {"MEDIA_CURBE_LOAD", OP_MEDIA_CURBE_LOAD, F_LEN_VAR, R_RCS, D_ALL, + 0, 16, NULL}, + + {"MEDIA_OBJECT_PRT", OP_MEDIA_OBJECT_PRT, F_LEN_VAR, R_RCS, D_ALL, + 0, 16, NULL}, + + {"MEDIA_OBJECT_WALKER", OP_MEDIA_OBJECT_WALKER, F_LEN_VAR, R_RCS, D_ALL, + 0, 16, NULL}, + + {"GPGPU_WALKER", OP_GPGPU_WALKER, F_LEN_VAR, R_RCS, D_ALL, + 0, 8, NULL}, + + {"MEDIA_VFE_STATE", OP_MEDIA_VFE_STATE, F_LEN_VAR, R_RCS, D_ALL, 0, 16, + NULL}, + + {"3DSTATE_VF_STATISTICS_GM45", OP_3DSTATE_VF_STATISTICS_GM45, + F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL}, + + {"MFX_PIPE_MODE_SELECT", OP_MFX_PIPE_MODE_SELECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_SURFACE_STATE", OP_MFX_SURFACE_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_PIPE_BUF_ADDR_STATE", OP_MFX_PIPE_BUF_ADDR_STATE, F_LEN_VAR, + R_VCS, D_BDW_PLUS, 0, 12, NULL}, + + {"MFX_IND_OBJ_BASE_ADDR_STATE", OP_MFX_IND_OBJ_BASE_ADDR_STATE, + F_LEN_VAR, R_VCS, D_BDW_PLUS, 0, 12, NULL}, + + {"MFX_BSP_BUF_BASE_ADDR_STATE", OP_MFX_BSP_BUF_BASE_ADDR_STATE, + F_LEN_VAR, R_VCS, D_BDW_PLUS, ADDR_FIX_3(1, 3, 5), 12, NULL}, + + {"OP_2_0_0_5", OP_2_0_0_5, F_LEN_VAR, R_VCS, D_BDW_PLUS, 0, 12, NULL}, + + {"MFX_STATE_POINTER", OP_MFX_STATE_POINTER, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_QM_STATE", OP_MFX_QM_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_FQM_STATE", OP_MFX_FQM_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_PAK_INSERT_OBJECT", OP_MFX_PAK_INSERT_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_STITCH_OBJECT", OP_MFX_STITCH_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_IT_OBJECT", OP_MFD_IT_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_WAIT", OP_MFX_WAIT, F_LEN_VAR, + R_VCS, D_ALL, 0, 6, NULL}, + + {"MFX_AVC_IMG_STATE", OP_MFX_AVC_IMG_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_AVC_QM_STATE", OP_MFX_AVC_QM_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_AVC_DIRECTMODE_STATE", OP_MFX_AVC_DIRECTMODE_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_AVC_SLICE_STATE", OP_MFX_AVC_SLICE_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_AVC_REF_IDX_STATE", OP_MFX_AVC_REF_IDX_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_AVC_WEIGHTOFFSET_STATE", OP_MFX_AVC_WEIGHTOFFSET_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_AVC_PICID_STATE", OP_MFD_AVC_PICID_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + {"MFD_AVC_DPB_STATE", OP_MFD_AVC_DPB_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_AVC_BSD_OBJECT", OP_MFD_AVC_BSD_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_AVC_SLICEADDR", OP_MFD_AVC_SLICEADDR, F_LEN_VAR, + R_VCS, D_ALL, ADDR_FIX_1(2), 12, NULL}, + + {"MFC_AVC_PAK_OBJECT", OP_MFC_AVC_PAK_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_VC1_PRED_PIPE_STATE", OP_MFX_VC1_PRED_PIPE_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_VC1_DIRECTMODE_STATE", OP_MFX_VC1_DIRECTMODE_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_VC1_SHORT_PIC_STATE", OP_MFD_VC1_SHORT_PIC_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_VC1_LONG_PIC_STATE", OP_MFD_VC1_LONG_PIC_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_VC1_BSD_OBJECT", OP_MFD_VC1_BSD_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFC_MPEG2_SLICEGROUP_STATE", OP_MFC_MPEG2_SLICEGROUP_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFC_MPEG2_PAK_OBJECT", OP_MFC_MPEG2_PAK_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_MPEG2_PIC_STATE", OP_MFX_MPEG2_PIC_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_MPEG2_QM_STATE", OP_MFX_MPEG2_QM_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_MPEG2_BSD_OBJECT", OP_MFD_MPEG2_BSD_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_2_6_0_0", OP_MFX_2_6_0_0, F_LEN_VAR, R_VCS, D_ALL, + 0, 16, NULL}, + + {"MFX_2_6_0_9", OP_MFX_2_6_0_9, F_LEN_VAR, R_VCS, D_ALL, 0, 16, NULL}, + + {"MFX_2_6_0_8", OP_MFX_2_6_0_8, F_LEN_VAR, R_VCS, D_ALL, 0, 16, NULL}, + + {"MFX_JPEG_PIC_STATE", OP_MFX_JPEG_PIC_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFX_JPEG_HUFF_TABLE_STATE", OP_MFX_JPEG_HUFF_TABLE_STATE, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"MFD_JPEG_BSD_OBJECT", OP_MFD_JPEG_BSD_OBJECT, F_LEN_VAR, + R_VCS, D_ALL, 0, 12, NULL}, + + {"VEBOX_STATE", OP_VEB_STATE, F_LEN_VAR, R_VECS, D_ALL, 0, 12, NULL}, + + {"VEBOX_SURFACE_STATE", OP_VEB_SURFACE_STATE, F_LEN_VAR, R_VECS, D_ALL, + 0, 12, NULL}, + + {"VEB_DI_IECP", OP_VEB_DNDI_IECP_STATE, F_LEN_VAR, R_VECS, D_BDW_PLUS, + 0, 20, NULL}, +}; + +static void add_cmd_entry(struct intel_gvt *gvt, struct cmd_entry *e) +{ + hash_add(gvt->cmd_table, &e->hlist, e->info->opcode); +} + +#define GVT_MAX_CMD_LENGTH 20 /* In Dword */ + +static void trace_cs_command(struct parser_exec_state *s, + cycles_t cost_pre_cmd_handler, cycles_t cost_cmd_handler) +{ + /* This buffer is used by ftrace to store all commands copied from + * guest gma space. Sometimes commands can cross pages, this should + * not be handled in ftrace logic. So this is just used as a + * 'bounce buffer' + */ + u32 cmd_trace_buf[GVT_MAX_CMD_LENGTH]; + int i; + u32 cmd_len = cmd_length(s); + /* The chosen value of GVT_MAX_CMD_LENGTH are just based on + * following two considerations: + * 1) From observation, most common ring commands is not that long. + * But there are execeptions. So it indeed makes sence to observe + * longer commands. + * 2) From the performance and debugging point of view, dumping all + * contents of very commands is not necessary. + * We mgith shrink GVT_MAX_CMD_LENGTH or remove this trace event in + * future for performance considerations. + */ + if (unlikely(cmd_len > GVT_MAX_CMD_LENGTH)) { + gvt_dbg_cmd("cmd length exceed tracing limitation!\n"); + cmd_len = GVT_MAX_CMD_LENGTH; + } + + for (i = 0; i < cmd_len; i++) + cmd_trace_buf[i] = cmd_val(s, i); + + trace_gvt_command(s->vgpu->id, s->ring_id, s->ip_gma, cmd_trace_buf, + cmd_len, s->buf_type == RING_BUFFER_INSTRUCTION, + cost_pre_cmd_handler, cost_cmd_handler); +} + +/* call the cmd handler, and advance ip */ +static int cmd_parser_exec(struct parser_exec_state *s) +{ + struct cmd_info *info; + u32 cmd; + int ret = 0; + cycles_t t0, t1, t2; + struct parser_exec_state s_before_advance_custom; + + t0 = get_cycles(); + + cmd = cmd_val(s, 0); + + info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); + if (info == NULL) { + gvt_err("unknown cmd 0x%x, opcode=0x%x\n", + cmd, get_opcode(cmd, s->ring_id)); + return -EINVAL; + } + + gvt_dbg_cmd("%s\n", info->name); + + s->info = info; + + t1 = get_cycles(); + + memcpy(&s_before_advance_custom, s, sizeof(struct parser_exec_state)); + + if (info->handler) { + ret = info->handler(s); + if (ret < 0) { + gvt_err("%s handler error\n", info->name); + return ret; + } + } + t2 = get_cycles(); + + trace_cs_command(&s_before_advance_custom, t1 - t0, t2 - t1); + + if (!(info->flag & F_IP_ADVANCE_CUSTOM)) { + ret = cmd_advance_default(s); + if (ret) { + gvt_err("%s IP advance error\n", info->name); + return ret; + } + } + return 0; +} + +static inline bool gma_out_of_range(unsigned long gma, + unsigned long gma_head, unsigned int gma_tail) +{ + if (gma_tail >= gma_head) + return (gma < gma_head) || (gma > gma_tail); + else + return (gma > gma_tail) && (gma < gma_head); +} + +static int command_scan(struct parser_exec_state *s, + unsigned long rb_head, unsigned long rb_tail, + unsigned long rb_start, unsigned long rb_len) +{ + + unsigned long gma_head, gma_tail, gma_bottom; + int ret = 0; + + gma_head = rb_start + rb_head; + gma_tail = rb_start + rb_tail; + gma_bottom = rb_start + rb_len; + + gvt_dbg_cmd("scan_start: start=%lx end=%lx\n", gma_head, gma_tail); + + while (s->ip_gma != gma_tail) { + if (s->buf_type == RING_BUFFER_INSTRUCTION) { + if (!(s->ip_gma >= rb_start) || + !(s->ip_gma < gma_bottom)) { + gvt_err("ip_gma %lx out of ring scope." + "(base:0x%lx, bottom: 0x%lx)\n", + s->ip_gma, rb_start, + gma_bottom); + parser_exec_state_dump(s); + return -EINVAL; + } + if (gma_out_of_range(s->ip_gma, gma_head, gma_tail)) { + gvt_err("ip_gma %lx out of range." + "base 0x%lx head 0x%lx tail 0x%lx\n", + s->ip_gma, rb_start, + rb_head, rb_tail); + parser_exec_state_dump(s); + break; + } + } + ret = cmd_parser_exec(s); + if (ret) { + gvt_err("cmd parser error\n"); + parser_exec_state_dump(s); + break; + } + } + + gvt_dbg_cmd("scan_end\n"); + + return ret; +} + +static int scan_workload(struct intel_vgpu_workload *workload) +{ + unsigned long gma_head, gma_tail, gma_bottom; + struct parser_exec_state s; + int ret = 0; + + /* ring base is page aligned */ + if (WARN_ON(!IS_ALIGNED(workload->rb_start, GTT_PAGE_SIZE))) + return -EINVAL; + + gma_head = workload->rb_start + workload->rb_head; + gma_tail = workload->rb_start + workload->rb_tail; + gma_bottom = workload->rb_start + _RING_CTL_BUF_SIZE(workload->rb_ctl); + + s.buf_type = RING_BUFFER_INSTRUCTION; + s.buf_addr_type = GTT_BUFFER; + s.vgpu = workload->vgpu; + s.ring_id = workload->ring_id; + s.ring_start = workload->rb_start; + s.ring_size = _RING_CTL_BUF_SIZE(workload->rb_ctl); + s.ring_head = gma_head; + s.ring_tail = gma_tail; + s.rb_va = workload->shadow_ring_buffer_va; + s.workload = workload; + + if (bypass_scan_mask & (1 << workload->ring_id)) + return 0; + + ret = ip_gma_set(&s, gma_head); + if (ret) + goto out; + + ret = command_scan(&s, workload->rb_head, workload->rb_tail, + workload->rb_start, _RING_CTL_BUF_SIZE(workload->rb_ctl)); + +out: + return ret; +} + +static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + + unsigned long gma_head, gma_tail, gma_bottom, ring_size, ring_tail; + struct parser_exec_state s; + int ret = 0; + + /* ring base is page aligned */ + if (WARN_ON(!IS_ALIGNED(wa_ctx->indirect_ctx.guest_gma, GTT_PAGE_SIZE))) + return -EINVAL; + + ring_tail = wa_ctx->indirect_ctx.size + 3 * sizeof(uint32_t); + ring_size = round_up(wa_ctx->indirect_ctx.size + CACHELINE_BYTES, + PAGE_SIZE); + gma_head = wa_ctx->indirect_ctx.guest_gma; + gma_tail = wa_ctx->indirect_ctx.guest_gma + ring_tail; + gma_bottom = wa_ctx->indirect_ctx.guest_gma + ring_size; + + s.buf_type = RING_BUFFER_INSTRUCTION; + s.buf_addr_type = GTT_BUFFER; + s.vgpu = wa_ctx->workload->vgpu; + s.ring_id = wa_ctx->workload->ring_id; + s.ring_start = wa_ctx->indirect_ctx.guest_gma; + s.ring_size = ring_size; + s.ring_head = gma_head; + s.ring_tail = gma_tail; + s.rb_va = wa_ctx->indirect_ctx.shadow_va; + s.workload = wa_ctx->workload; + + ret = ip_gma_set(&s, gma_head); + if (ret) + goto out; + + ret = command_scan(&s, 0, ring_tail, + wa_ctx->indirect_ctx.guest_gma, ring_size); +out: + return ret; +} + +static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + int ring_id = workload->ring_id; + struct i915_gem_context *shadow_ctx = vgpu->shadow_ctx; + struct intel_ring *ring = shadow_ctx->engine[ring_id].ring; + unsigned long gma_head, gma_tail, gma_top, guest_rb_size; + unsigned int copy_len = 0; + int ret; + + guest_rb_size = _RING_CTL_BUF_SIZE(workload->rb_ctl); + + /* calculate workload ring buffer size */ + workload->rb_len = (workload->rb_tail + guest_rb_size - + workload->rb_head) % guest_rb_size; + + gma_head = workload->rb_start + workload->rb_head; + gma_tail = workload->rb_start + workload->rb_tail; + gma_top = workload->rb_start + guest_rb_size; + + /* allocate shadow ring buffer */ + ret = intel_ring_begin(workload->req, workload->rb_len / 4); + if (ret) + return ret; + + /* get shadow ring buffer va */ + workload->shadow_ring_buffer_va = ring->vaddr + ring->tail; + + /* head > tail --> copy head <-> top */ + if (gma_head > gma_tail) { + ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, + gma_head, gma_top, + workload->shadow_ring_buffer_va); + if (ret) { + gvt_err("fail to copy guest ring buffer\n"); + return ret; + } + copy_len = gma_top - gma_head; + gma_head = workload->rb_start; + } + + /* copy head or start <-> tail */ + ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, + gma_head, gma_tail, + workload->shadow_ring_buffer_va + copy_len); + if (ret) { + gvt_err("fail to copy guest ring buffer\n"); + return ret; + } + ring->tail += workload->rb_len; + intel_ring_advance(ring); + return 0; +} + +int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) +{ + int ret; + + ret = shadow_workload_ring_buffer(workload); + if (ret) { + gvt_err("fail to shadow workload ring_buffer\n"); + return ret; + } + + ret = scan_workload(workload); + if (ret) { + gvt_err("scan workload error\n"); + return ret; + } + return 0; +} + +static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + struct drm_device *dev = &wa_ctx->workload->vgpu->gvt->dev_priv->drm; + int ctx_size = wa_ctx->indirect_ctx.size; + unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma; + int ret = 0; + void *dest = NULL; + + wa_ctx->indirect_ctx.obj = i915_gem_object_create(dev, + round_up(ctx_size + CACHELINE_BYTES, PAGE_SIZE)); + if (wa_ctx->indirect_ctx.obj == NULL) + return -ENOMEM; + + ret = i915_gem_object_get_pages(wa_ctx->indirect_ctx.obj); + if (ret) + return ret; + + i915_gem_object_pin_pages(wa_ctx->indirect_ctx.obj); + + /* get the va of the shadow batch buffer */ + dest = (void *)vmap_batch(wa_ctx->indirect_ctx.obj, 0, + ctx_size + CACHELINE_BYTES); + if (!dest) { + gvt_err("failed to vmap shadow indirect ctx\n"); + ret = -ENOMEM; + goto unpin_src; + } + + ret = i915_gem_object_set_to_cpu_domain(wa_ctx->indirect_ctx.obj, + false); + if (ret) { + gvt_err("failed to set shadow indirect ctx to CPU\n"); + goto unmap_src; + } + + wa_ctx->indirect_ctx.shadow_va = dest; + + memset(dest, 0, round_up(ctx_size + CACHELINE_BYTES, PAGE_SIZE)); + + ret = copy_gma_to_hva(wa_ctx->workload->vgpu, + wa_ctx->workload->vgpu->gtt.ggtt_mm, + guest_gma, guest_gma + ctx_size, dest); + if (ret) { + gvt_err("fail to copy guest indirect ctx\n"); + return ret; + } + + return 0; + +unmap_src: + vunmap(dest); +unpin_src: + i915_gem_object_unpin_pages(wa_ctx->indirect_ctx.obj); + + return ret; +} + +static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + uint32_t per_ctx_start[CACHELINE_DWORDS] = {0}; + unsigned char *bb_start_sva; + + per_ctx_start[0] = 0x18800001; + per_ctx_start[1] = wa_ctx->per_ctx.guest_gma; + + bb_start_sva = (unsigned char *)wa_ctx->indirect_ctx.shadow_va + + wa_ctx->indirect_ctx.size; + + memcpy(bb_start_sva, per_ctx_start, CACHELINE_BYTES); + + return 0; +} + +int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + int ret; + + if (wa_ctx->indirect_ctx.size == 0) + return 0; + + ret = shadow_indirect_ctx(wa_ctx); + if (ret) { + gvt_err("fail to shadow indirect ctx\n"); + return ret; + } + + combine_wa_ctx(wa_ctx); + + ret = scan_wa_ctx(wa_ctx); + if (ret) { + gvt_err("scan wa ctx error\n"); + return ret; + } + + return 0; +} + +static struct cmd_info *find_cmd_entry_any_ring(struct intel_gvt *gvt, + unsigned int opcode, int rings) +{ + struct cmd_info *info = NULL; + unsigned int ring; + + for_each_set_bit(ring, (unsigned long *)&rings, I915_NUM_ENGINES) { + info = find_cmd_entry(gvt, opcode, ring); + if (info) + break; + } + return info; +} + +static int init_cmd_table(struct intel_gvt *gvt) +{ + int i; + struct cmd_entry *e; + struct cmd_info *info; + unsigned int gen_type; + + gen_type = intel_gvt_get_device_type(gvt); + + for (i = 0; i < ARRAY_SIZE(cmd_info); i++) { + if (!(cmd_info[i].devices & gen_type)) + continue; + + e = kzalloc(sizeof(*e), GFP_KERNEL); + if (!e) + return -ENOMEM; + + e->info = &cmd_info[i]; + info = find_cmd_entry_any_ring(gvt, + e->info->opcode, e->info->rings); + if (info) { + gvt_err("%s %s duplicated\n", e->info->name, + info->name); + return -EEXIST; + } + + INIT_HLIST_NODE(&e->hlist); + add_cmd_entry(gvt, e); + gvt_dbg_cmd("add %-30s op %04x flag %x devs %02x rings %02x\n", + e->info->name, e->info->opcode, e->info->flag, + e->info->devices, e->info->rings); + } + return 0; +} + +static void clean_cmd_table(struct intel_gvt *gvt) +{ + struct hlist_node *tmp; + struct cmd_entry *e; + int i; + + hash_for_each_safe(gvt->cmd_table, i, tmp, e, hlist) + kfree(e); + + hash_init(gvt->cmd_table); +} + +void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt) +{ + clean_cmd_table(gvt); +} + +int intel_gvt_init_cmd_parser(struct intel_gvt *gvt) +{ + int ret; + + ret = init_cmd_table(gvt); + if (ret) { + intel_gvt_clean_cmd_parser(gvt); + return ret; + } + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.h b/drivers/gpu/drm/i915/gvt/cmd_parser.h new file mode 100644 index 000000000000..bed33514103c --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.h @@ -0,0 +1,49 @@ +/* + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ke Yu + * Kevin Tian + * Zhiyuan Lv + * + * Contributors: + * Min He + * Ping Gao + * Tina Zhang + * Yulei Zhang + * Zhi Wang + * + */ +#ifndef _GVT_CMD_PARSER_H_ +#define _GVT_CMD_PARSER_H_ + +#define GVT_CMD_HASH_BITS 7 + +void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt); + +int intel_gvt_init_cmd_parser(struct intel_gvt *gvt); + +int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload); + +int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx); + +#endif diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index 76e50eeef7f3..68cba7bd980a 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -51,4 +51,7 @@ #define gvt_dbg_render(fmt, args...) \ DRM_DEBUG_DRIVER("gvt: render: "fmt, ##args) +#define gvt_dbg_cmd(fmt, args...) \ + DRM_DEBUG_DRIVER("gvt: cmd: "fmt, ##args) + #endif diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 5ae738e16678..4a00ee7ff020 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -363,6 +363,109 @@ static void free_workload(struct intel_vgpu_workload *workload) #define get_desc_from_elsp_dwords(ed, i) \ ((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2])) + +#define BATCH_BUFFER_ADDR_MASK ((1UL << 32) - (1U << 2)) +#define BATCH_BUFFER_ADDR_HIGH_MASK ((1UL << 16) - (1U)) +static int set_gma_to_bb_cmd(struct intel_shadow_bb_entry *entry_obj, + unsigned long add, int gmadr_bytes) +{ + if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8)) + return -1; + + *((u32 *)(entry_obj->bb_start_cmd_va + (1 << 2))) = add & + BATCH_BUFFER_ADDR_MASK; + if (gmadr_bytes == 8) { + *((u32 *)(entry_obj->bb_start_cmd_va + (2 << 2))) = + add & BATCH_BUFFER_ADDR_HIGH_MASK; + } + + return 0; +} + +static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) +{ + int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd; + struct i915_vma *vma; + unsigned long gma; + + /* pin the gem object to ggtt */ + if (!list_empty(&workload->shadow_bb)) { + struct intel_shadow_bb_entry *entry_obj = + list_first_entry(&workload->shadow_bb, + struct intel_shadow_bb_entry, + list); + struct intel_shadow_bb_entry *temp; + + list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb, + list) { + vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, + 0, 0); + if (IS_ERR(vma)) { + gvt_err("Cannot pin\n"); + return; + } + i915_gem_object_unpin_pages(entry_obj->obj); + + /* update the relocate gma with shadow batch buffer*/ + gma = i915_gem_object_ggtt_offset(entry_obj->obj, NULL); + WARN_ON(!IS_ALIGNED(gma, 4)); + set_gma_to_bb_cmd(entry_obj, gma, gmadr_bytes); + } + } +} + +static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + int ring_id = wa_ctx->workload->ring_id; + struct i915_gem_context *shadow_ctx = + wa_ctx->workload->vgpu->shadow_ctx; + struct drm_i915_gem_object *ctx_obj = + shadow_ctx->engine[ring_id].state->obj; + struct execlist_ring_context *shadow_ring_context; + struct page *page; + + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); + shadow_ring_context = kmap_atomic(page); + + shadow_ring_context->bb_per_ctx_ptr.val = + (shadow_ring_context->bb_per_ctx_ptr.val & + (~PER_CTX_ADDR_MASK)) | wa_ctx->per_ctx.shadow_gma; + shadow_ring_context->rcs_indirect_ctx.val = + (shadow_ring_context->rcs_indirect_ctx.val & + (~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma; + + kunmap_atomic(shadow_ring_context); + return 0; +} + +static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + struct i915_vma *vma; + unsigned long gma; + unsigned char *per_ctx_va = + (unsigned char *)wa_ctx->indirect_ctx.shadow_va + + wa_ctx->indirect_ctx.size; + + if (wa_ctx->indirect_ctx.size == 0) + return; + + vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL, 0, 0, 0); + if (IS_ERR(vma)) { + gvt_err("Cannot pin indirect ctx obj\n"); + return; + } + i915_gem_object_unpin_pages(wa_ctx->indirect_ctx.obj); + + gma = i915_gem_object_ggtt_offset(wa_ctx->indirect_ctx.obj, NULL); + WARN_ON(!IS_ALIGNED(gma, CACHELINE_BYTES)); + wa_ctx->indirect_ctx.shadow_gma = gma; + + wa_ctx->per_ctx.shadow_gma = *((unsigned int *)per_ctx_va + 1); + memset(per_ctx_va, 0, CACHELINE_BYTES); + + update_wa_ctx_2_shadow_ctx(wa_ctx); +} + static int prepare_execlist_workload(struct intel_vgpu_workload *workload) { struct intel_vgpu *vgpu = workload->vgpu; @@ -372,6 +475,8 @@ static int prepare_execlist_workload(struct intel_vgpu_workload *workload) intel_vgpu_pin_mm(workload->shadow_mm); intel_vgpu_sync_oos_pages(workload->vgpu); intel_vgpu_flush_post_shadow(workload->vgpu); + prepare_shadow_batch_buffer(workload); + prepare_shadow_wa_ctx(&workload->wa_ctx); if (!workload->emulate_schedule_in) return 0; @@ -381,6 +486,35 @@ static int prepare_execlist_workload(struct intel_vgpu_workload *workload) return emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx); } +static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) +{ + /* release all the shadow batch buffer */ + if (!list_empty(&workload->shadow_bb)) { + struct intel_shadow_bb_entry *entry_obj = + list_first_entry(&workload->shadow_bb, + struct intel_shadow_bb_entry, + list); + struct intel_shadow_bb_entry *temp; + + list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb, + list) { + drm_gem_object_unreference(&(entry_obj->obj->base)); + kvfree(entry_obj->va); + list_del(&entry_obj->list); + kfree(entry_obj); + } + } +} + +static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + if (wa_ctx->indirect_ctx.size == 0) + return; + + drm_gem_object_unreference(&(wa_ctx->indirect_ctx.obj->base)); + kvfree(wa_ctx->indirect_ctx.shadow_va); +} + static int complete_execlist_workload(struct intel_vgpu_workload *workload) { struct intel_vgpu *vgpu = workload->vgpu; @@ -394,6 +528,9 @@ static int complete_execlist_workload(struct intel_vgpu_workload *workload) gvt_dbg_el("complete workload %p status %d\n", workload, workload->status); + release_shadow_batch_buffer(workload); + release_shadow_wa_ctx(&workload->wa_ctx); + if (workload->status || vgpu->resetting) goto out; @@ -487,7 +624,7 @@ bool submit_context(struct intel_vgpu *vgpu, int ring_id, struct intel_vgpu_workload *last_workload = get_last_workload(q); struct intel_vgpu_workload *workload = NULL; u64 ring_context_gpa; - u32 head, tail, start, ctl, ctx_ctl; + u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx; int ret; ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, @@ -532,6 +669,7 @@ bool submit_context(struct intel_vgpu *vgpu, int ring_id, RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4); INIT_LIST_HEAD(&workload->list); + INIT_LIST_HEAD(&workload->shadow_bb); init_waitqueue_head(&workload->shadow_ctx_status_wq); atomic_set(&workload->shadow_ctx_active, 0); @@ -549,6 +687,24 @@ bool submit_context(struct intel_vgpu *vgpu, int ring_id, workload->status = -EINPROGRESS; workload->emulate_schedule_in = emulate_schedule_in; + if (ring_id == RCS) { + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + + RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4); + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + + RING_CTX_OFF(rcs_indirect_ctx.val), &indirect_ctx, 4); + + workload->wa_ctx.indirect_ctx.guest_gma = + indirect_ctx & INDIRECT_CTX_ADDR_MASK; + workload->wa_ctx.indirect_ctx.size = + (indirect_ctx & INDIRECT_CTX_SIZE_MASK) * + CACHELINE_BYTES; + workload->wa_ctx.per_ctx.guest_gma = + per_ctx & PER_CTX_ADDR_MASK; + workload->wa_ctx.workload = workload; + + WARN_ON(workload->wa_ctx.indirect_ctx.size && !(per_ctx & 0x1)); + } + if (emulate_schedule_in) memcpy(&workload->elsp_dwords, &vgpu->execlist[ring_id].elsp_dwords, diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 7f13efbbd93a..e72e26c61a15 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -112,6 +112,8 @@ static void init_device_info(struct intel_gvt *gvt) info->gtt_start_offset = 8 * 1024 * 1024; info->gtt_entry_size = 8; info->gtt_entry_size_shift = 3; + info->gmadr_bytes_in_cmd = 8; + info->max_surface_size = 36 * 1024 * 1024; } } @@ -177,6 +179,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) return; clean_service_thread(gvt); + intel_gvt_clean_cmd_parser(gvt); intel_gvt_clean_sched_policy(gvt); intel_gvt_clean_workload_scheduler(gvt); intel_gvt_clean_opregion(gvt); @@ -249,14 +252,20 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (ret) goto out_clean_workload_scheduler; - ret = init_service_thread(gvt); + ret = intel_gvt_init_cmd_parser(gvt); if (ret) goto out_clean_sched_policy; + ret = init_service_thread(gvt); + if (ret) + goto out_clean_cmd_parser; + gvt_dbg_core("gvt device creation is done\n"); gvt->initialized = true; return 0; +out_clean_cmd_parser: + intel_gvt_clean_cmd_parser(gvt); out_clean_sched_policy: intel_gvt_clean_sched_policy(gvt); out_clean_workload_scheduler: diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index dfe398d47496..1564554b7459 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -45,6 +45,7 @@ #include "scheduler.h" #include "sched_policy.h" #include "render.h" +#include "cmd_parser.h" #define GVT_MAX_VGPU 8 @@ -71,6 +72,8 @@ struct intel_gvt_device_info { u32 gtt_start_offset; u32 gtt_entry_size; u32 gtt_entry_size_shift; + int gmadr_bytes_in_cmd; + u32 max_surface_size; }; /* GM resources owned by a vGPU */ @@ -203,6 +206,7 @@ struct intel_gvt { struct intel_gvt_gtt gtt; struct intel_gvt_opregion opregion; struct intel_gvt_workload_scheduler scheduler; + DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS); struct task_struct *service_thread; wait_queue_head_t service_thread_wq; diff --git a/drivers/gpu/drm/i915/gvt/interrupt.h b/drivers/gpu/drm/i915/gvt/interrupt.h index 3136527b7e5c..5313fb1b33e1 100644 --- a/drivers/gpu/drm/i915/gvt/interrupt.h +++ b/drivers/gpu/drm/i915/gvt/interrupt.h @@ -226,4 +226,8 @@ int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu, int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu, unsigned int reg, void *p_data, unsigned int bytes); +int gvt_ring_id_to_pipe_control_notify_event(int ring_id); +int gvt_ring_id_to_mi_flush_dw_event(int ring_id); +int gvt_ring_id_to_mi_user_interrupt_event(int ring_id); + #endif /* _GVT_INTERRUPT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 2f96302c7b21..732672b7d22b 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -185,6 +185,14 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) mutex_lock(&gvt->lock); + ret = intel_gvt_scan_and_shadow_workload(workload); + if (ret) + goto err; + + ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx); + if (ret) + goto err; + ret = populate_shadow_context(workload); if (ret) goto err; @@ -345,6 +353,7 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id) { struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; struct intel_vgpu_workload *workload; + int event; mutex_lock(&gvt->lock); @@ -355,6 +364,11 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id) !atomic_read(&workload->shadow_ctx_active)); update_guest_context(workload); + + for_each_set_bit(event, workload->pending_events, + INTEL_GVT_EVENT_MAX) + intel_vgpu_trigger_virtual_event(workload->vgpu, + event); } gvt_dbg_sched("ring id %d complete workload %p status %d\n", diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 2500438d7aa7..3b30c28bff51 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -50,6 +50,29 @@ struct intel_gvt_workload_scheduler { struct intel_gvt_sched_policy_ops *sched_ops; }; +#define INDIRECT_CTX_ADDR_MASK 0xffffffc0 +#define INDIRECT_CTX_SIZE_MASK 0x3f +struct shadow_indirect_ctx { + struct drm_i915_gem_object *obj; + unsigned long guest_gma; + unsigned long shadow_gma; + void *shadow_va; + uint32_t size; +}; + +#define PER_CTX_ADDR_MASK 0xfffff000 +struct shadow_per_ctx { + unsigned long guest_gma; + unsigned long shadow_gma; +}; + +struct intel_shadow_wa_ctx { + struct intel_vgpu_workload *workload; + struct shadow_indirect_ctx indirect_ctx; + struct shadow_per_ctx per_ctx; + +}; + struct intel_vgpu_workload { struct intel_vgpu *vgpu; int ring_id; @@ -65,16 +88,32 @@ struct intel_vgpu_workload { int (*complete)(struct intel_vgpu_workload *); struct list_head list; + DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX); + void *shadow_ring_buffer_va; + /* execlist context information */ struct execlist_ctx_descriptor_format ctx_desc; struct execlist_ring_context *ring_context; - unsigned long rb_head, rb_tail, rb_ctl, rb_start; + unsigned long rb_head, rb_tail, rb_ctl, rb_start, rb_len; bool restore_inhibit; struct intel_vgpu_elsp_dwords elsp_dwords; bool emulate_schedule_in; atomic_t shadow_ctx_active; wait_queue_head_t shadow_ctx_status_wq; u64 ring_context_gpa; + + /* shadow batch buffer */ + struct list_head shadow_bb; + struct intel_shadow_wa_ctx wa_ctx; +}; + +/* Intel shadow batch buffer is a i915 gem object */ +struct intel_shadow_bb_entry { + struct list_head list; + struct drm_i915_gem_object *obj; + void *va; + unsigned long len; + void *bb_start_cmd_va; }; #define workload_q_head(vgpu, ring_id) \ diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h index 27577dcfd9d8..53a2d10cf3f1 100644 --- a/drivers/gpu/drm/i915/gvt/trace.h +++ b/drivers/gpu/drm/i915/gvt/trace.h @@ -224,6 +224,58 @@ TRACE_EVENT(oos_sync, TP_printk("%s", __entry->buf) ); +#define MAX_CMD_STR_LEN 256 +TRACE_EVENT(gvt_command, + TP_PROTO(u8 vm_id, u8 ring_id, u32 ip_gma, u32 *cmd_va, u32 cmd_len, bool ring_buffer_cmd, cycles_t cost_pre_cmd_handler, cycles_t cost_cmd_handler), + + TP_ARGS(vm_id, ring_id, ip_gma, cmd_va, cmd_len, ring_buffer_cmd, cost_pre_cmd_handler, cost_cmd_handler), + + TP_STRUCT__entry( + __field(u8, vm_id) + __field(u8, ring_id) + __field(int, i) + __array(char, tmp_buf, MAX_CMD_STR_LEN) + __array(char, cmd_str, MAX_CMD_STR_LEN) + ), + + TP_fast_assign( + __entry->vm_id = vm_id; + __entry->ring_id = ring_id; + __entry->cmd_str[0] = '\0'; + snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "VM(%d) Ring(%d): %s ip(%08x) pre handler cost (%llu), handler cost (%llu) ", vm_id, ring_id, ring_buffer_cmd ? "RB":"BB", ip_gma, cost_pre_cmd_handler, cost_cmd_handler); + strcat(__entry->cmd_str, __entry->tmp_buf); + entry->i = 0; + while (cmd_len > 0) { + if (cmd_len >= 8) { + snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x %08x %08x %08x %08x %08x %08x ", + cmd_va[__entry->i], cmd_va[__entry->i+1], cmd_va[__entry->i+2], cmd_va[__entry->i+3], + cmd_va[__entry->i+4], cmd_va[__entry->i+5], cmd_va[__entry->i+6], cmd_va[__entry->i+7]); + __entry->i += 8; + cmd_len -= 8; + strcat(__entry->cmd_str, __entry->tmp_buf); + } else if (cmd_len >= 4) { + snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x %08x %08x ", + cmd_va[__entry->i], cmd_va[__entry->i+1], cmd_va[__entry->i+2], cmd_va[__entry->i+3]); + __entry->i += 4; + cmd_len -= 4; + strcat(__entry->cmd_str, __entry->tmp_buf); + } else if (cmd_len >= 2) { + snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x ", cmd_va[__entry->i], cmd_va[__entry->i+1]); + __entry->i += 2; + cmd_len -= 2; + strcat(__entry->cmd_str, __entry->tmp_buf); + } else if (cmd_len == 1) { + snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x ", cmd_va[__entry->i]); + __entry->i += 1; + cmd_len -= 1; + strcat(__entry->cmd_str, __entry->tmp_buf); + } + } + strcat(__entry->cmd_str, "\n"); + ), + + TP_printk("%s", __entry->cmd_str) +); #endif /* _GVT_TRACE_H_ */ /* This part must be out of protection */ -- cgit v1.2.3 From 21196a81c2d8bc9d79e1cbd896f668106da4f75d Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Thu, 13 Oct 2016 22:13:04 +0800 Subject: drm/i915/gvt: Support GVT-g on Skylake GVT-g supports Intel Skylake platform. Enable it. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/intel_gvt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index 434f4d5c553d..8e8596da89b1 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -39,6 +39,8 @@ static bool is_supported_device(struct drm_i915_private *dev_priv) { if (IS_BROADWELL(dev_priv)) return true; + if (IS_SKYLAKE(dev_priv)) + return true; return false; } -- cgit v1.2.3 From 4f8036a28112ed6ca3688ece4e865509bacd51ed Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:02:52 +0100 Subject: drm/i915: Make HAS_DDI and HAS_PCH_LPT_LP only take dev_priv This saves 3248 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 8 +++--- drivers/gpu/drm/i915/intel_crt.c | 10 +++---- drivers/gpu/drm/i915/intel_display.c | 49 ++++++++++++++++++----------------- drivers/gpu/drm/i915/intel_dp.c | 16 ++++++------ drivers/gpu/drm/i915/intel_dpll_mgr.c | 4 +-- drivers/gpu/drm/i915/intel_hdmi.c | 10 +++---- drivers/gpu/drm/i915/intel_pm.c | 4 +-- drivers/gpu/drm/i915/intel_psr.c | 8 +++--- 8 files changed, 56 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9e830b58b06b..a2ba8fa4269b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2811,7 +2811,7 @@ struct drm_i915_cmd_table { #define HAS_DP_MST(dev) (INTEL_INFO(dev)->has_dp_mst) -#define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) +#define HAS_DDI(dev_priv) ((dev_priv)->info.has_ddi) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr) #define HAS_RUNTIME_PM(dev) (INTEL_INFO(dev)->has_runtime_pm) @@ -2850,8 +2850,10 @@ struct drm_i915_cmd_table { #define HAS_PCH_KBP(dev) (INTEL_PCH_TYPE(dev) == PCH_KBP) #define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT) #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) -#define HAS_PCH_LPT_LP(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) -#define HAS_PCH_LPT_H(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) +#define HAS_PCH_LPT_LP(dev_priv) \ + ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) +#define HAS_PCH_LPT_H(dev_priv) \ + ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) #define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 4a7b6c595ec2..d4b9b166de5d 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -280,13 +280,13 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) pipe_config->has_pch_encoder = true; /* LPT FDI RX only supports 8bpc. */ - if (HAS_PCH_LPT(dev)) { + if (HAS_PCH_LPT(dev_priv)) { if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) { DRM_DEBUG_KMS("LPT only supports 24bpp\n"); return false; @@ -296,7 +296,7 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, } /* FDI must always be 2.7 GHz */ - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) pipe_config->port_clock = 135000 * 2; return true; @@ -917,7 +917,7 @@ void intel_crt_init(struct drm_device *dev) if (I915_HAS_HOTPLUG(dev) && !dmi_check_system(intel_spurious_crt_detect)) crt->base.hpd_pin = HPD_CRT; - if (HAS_DDI(dev)) { + if (HAS_DDI(dev_priv)) { crt->base.port = PORT_E; crt->base.get_config = hsw_crt_get_config; crt->base.get_hw_state = intel_ddi_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 645a779b7ea4..bec80f76bd01 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1187,19 +1187,17 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, onoff(state), onoff(cur_state)); } -void assert_panel_unlocked(struct drm_i915_private *dev_priv, - enum pipe pipe) +void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_device *dev = &dev_priv->drm; i915_reg_t pp_reg; u32 val; enum pipe panel_pipe = PIPE_A; bool locked = true; - if (WARN_ON(HAS_DDI(dev))) + if (WARN_ON(HAS_DDI(dev_priv))) return; - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev_priv)) { u32 port_sel; pp_reg = PP_CONTROL(0); @@ -1209,7 +1207,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) panel_pipe = PIPE_B; /* XXX: else fix for eDP */ - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { /* presumably write lock depends on pipe, not port select */ pp_reg = PP_CONTROL(pipe); panel_pipe = pipe; @@ -5696,13 +5694,13 @@ static enum intel_display_power_domain port_to_aux_power_domain(enum port port) enum intel_display_power_domain intel_display_port_power_domain(struct intel_encoder *intel_encoder) { - struct drm_device *dev = intel_encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); struct intel_digital_port *intel_dig_port; switch (intel_encoder->type) { case INTEL_OUTPUT_UNKNOWN: /* Only DDI platforms should ever use this output type */ - WARN_ON_ONCE(!HAS_DDI(dev)); + WARN_ON_ONCE(!HAS_DDI(dev_priv)); case INTEL_OUTPUT_DP: case INTEL_OUTPUT_HDMI: case INTEL_OUTPUT_EDP: @@ -5723,7 +5721,7 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder) enum intel_display_power_domain intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder) { - struct drm_device *dev = intel_encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); struct intel_digital_port *intel_dig_port; switch (intel_encoder->type) { @@ -5736,7 +5734,7 @@ intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder) * what's the status of the given connectors, play safe and * run the DP detection too. */ - WARN_ON_ONCE(!HAS_DDI(dev)); + WARN_ON_ONCE(!HAS_DDI(dev_priv)); case INTEL_OUTPUT_DP: case INTEL_OUTPUT_EDP: intel_dig_port = enc_to_dig_port(&intel_encoder->base); @@ -9196,7 +9194,8 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread, if (WARN(with_fdi && !with_spread, "FDI requires downspread\n")) with_spread = true; - if (WARN(HAS_PCH_LPT_LP(dev) && with_fdi, "LP PCH doesn't have FDI\n")) + if (WARN(HAS_PCH_LPT_LP(dev_priv) && + with_fdi, "LP PCH doesn't have FDI\n")) with_fdi = false; mutex_lock(&dev_priv->sb_lock); @@ -9219,7 +9218,7 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread, } } - reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0; + reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0; tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); @@ -9235,7 +9234,7 @@ static void lpt_disable_clkout_dp(struct drm_device *dev) mutex_lock(&dev_priv->sb_lock); - reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0; + reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0; tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); @@ -10203,7 +10202,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("Enabling package C8+\n"); - if (HAS_PCH_LPT_LP(dev)) { + if (HAS_PCH_LPT_LP(dev_priv)) { val = I915_READ(SOUTH_DSPCLK_GATE_D); val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; I915_WRITE(SOUTH_DSPCLK_GATE_D, val); @@ -10223,7 +10222,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv) hsw_restore_lcpll(dev_priv); lpt_init_pch_refclk(dev); - if (HAS_PCH_LPT_LP(dev)) { + if (HAS_PCH_LPT_LP(dev_priv)) { val = I915_READ(SOUTH_DSPCLK_GATE_D); val |= PCH_LP_PARTITION_LEVEL_DISABLE; I915_WRITE(SOUTH_DSPCLK_GATE_D, val); @@ -10845,7 +10844,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, } cntl |= pipe << 28; /* Connect to correct pipe */ - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) cntl |= CURSOR_PIPE_CSC_ENABLE; if (plane_state->base.rotation == DRM_ROTATE_180) @@ -12745,6 +12744,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, const char *context) { struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct drm_plane *plane; struct intel_plane *intel_plane; struct intel_plane_state *state; @@ -12827,7 +12827,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->dpll_hw_state.ctrl1, pipe_config->dpll_hw_state.cfgcr1, pipe_config->dpll_hw_state.cfgcr2); - } else if (HAS_DDI(dev)) { + } else if (HAS_DDI(dev_priv)) { DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", pipe_config->dpll_hw_state.wrpll, pipe_config->dpll_hw_state.spll); @@ -12905,7 +12905,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) switch (encoder->type) { unsigned int port_mask; case INTEL_OUTPUT_UNKNOWN: - if (WARN_ON(!HAS_DDI(dev))) + if (WARN_ON(!HAS_DDI(to_i915(dev)))) break; case INTEL_OUTPUT_DP: case INTEL_OUTPUT_HDMI: @@ -13729,7 +13729,7 @@ intel_modeset_verify_disabled(struct drm_device *dev) static void update_scanline_offset(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); /* * The scanline counter increments at the leading edge of hsync. @@ -13749,7 +13749,7 @@ static void update_scanline_offset(struct intel_crtc *crtc) * there's an extra 1 line difference. So we need to add two instead of * one to the value. */ - if (IS_GEN2(dev)) { + if (IS_GEN2(dev_priv)) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; int vtotal; @@ -13758,7 +13758,7 @@ static void update_scanline_offset(struct intel_crtc *crtc) vtotal /= 2; crtc->scanline_offset = vtotal - 1; - } else if (HAS_DDI(dev) && + } else if (HAS_DDI(dev_priv) && intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) { crtc->scanline_offset = 2; } else @@ -15327,11 +15327,12 @@ static bool intel_crt_present(struct drm_device *dev) if (IS_CHERRYVIEW(dev)) return false; - if (HAS_PCH_LPT_H(dev) && I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED) + if (HAS_PCH_LPT_H(dev_priv) && + I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED) return false; /* DDI E can't be used if DDI A requires 4 lanes */ - if (HAS_DDI(dev) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) + if (HAS_DDI(dev_priv) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) return false; if (!dev_priv->vbt.int_crt_support) @@ -15405,7 +15406,7 @@ static void intel_setup_outputs(struct drm_device *dev) intel_ddi_init(dev, PORT_C); intel_dsi_init(dev); - } else if (HAS_DDI(dev)) { + } else if (HAS_DDI(dev_priv)) { int found; /* diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 496141e3b4d3..a5c562850d47 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1565,7 +1565,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, max_clock = common_len - 1; - if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A) + if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A) pipe_config->has_pch_encoder = true; pipe_config->has_drrs = false; @@ -1707,7 +1707,7 @@ found: to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco; } - if (!HAS_DDI(dev)) + if (!HAS_DDI(dev_priv)) intel_dp_set_clock(encoder, pipe_config); return true; @@ -2632,7 +2632,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, DRM_DEBUG_KMS("Using DP training pattern TPS%d\n", dp_train_pat & DP_TRAINING_PATTERN_MASK); - if (HAS_DDI(dev)) { + if (HAS_DDI(dev_priv)) { uint32_t temp = I915_READ(DP_TP_CTL(port)); if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) @@ -3339,7 +3339,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) uint32_t signal_levels, mask = 0; uint8_t train_set = intel_dp->train_set[0]; - if (HAS_DDI(dev)) { + if (HAS_DDI(dev_priv)) { signal_levels = ddi_signal_levels(intel_dp); if (IS_BROXTON(dev)) @@ -3398,7 +3398,7 @@ void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) enum port port = intel_dig_port->port; uint32_t val; - if (!HAS_DDI(dev)) + if (!HAS_DDI(dev_priv)) return; val = I915_READ(DP_TP_CTL(port)); @@ -3433,7 +3433,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = to_i915(dev); uint32_t DP = intel_dp->DP; - if (WARN_ON(HAS_DDI(dev))) + if (WARN_ON(HAS_DDI(dev_priv))) return; if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)) @@ -5659,7 +5659,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, else intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl; - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain; /* Preserve the current hw state. */ @@ -5701,7 +5701,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_connector_attach_encoder(intel_connector, intel_encoder); - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; else intel_connector->get_hw_state = intel_connector_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 1c59ca50c430..d0c59c1793ef 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1855,7 +1855,7 @@ void intel_shared_dpll_init(struct drm_device *dev) dpll_mgr = &skl_pll_mgr; else if (IS_BROXTON(dev)) dpll_mgr = &bxt_pll_mgr; - else if (HAS_DDI(dev)) + else if (HAS_DDI(dev_priv)) dpll_mgr = &hsw_pll_mgr; else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) dpll_mgr = &pch_pll_mgr; @@ -1883,7 +1883,7 @@ void intel_shared_dpll_init(struct drm_device *dev) BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); /* FIXME: Move this to a more suitable place */ - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) intel_ddi_pll_init(dev); } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 8d46f5836746..09b2146f157f 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -50,7 +50,7 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) struct drm_i915_private *dev_priv = to_i915(dev); uint32_t enabled_bits; - enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; + enabled_bits = HAS_DDI(dev_priv) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; WARN(I915_READ(intel_hdmi->hdmi_reg) & enabled_bits, "HDMI port enabled, expecting disabled\n"); @@ -1312,7 +1312,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock; int clock_12bpc = clock_8bpc * 3 / 2; @@ -1339,7 +1339,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, clock_12bpc *= 2; } - if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) + if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv)) pipe_config->has_pch_encoder = true; if (pipe_config->has_hdmi_sink && intel_hdmi->has_audio) @@ -1892,7 +1892,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi->write_infoframe = g4x_write_infoframe; intel_hdmi->set_infoframes = g4x_set_infoframes; intel_hdmi->infoframe_enabled = g4x_infoframe_enabled; - } else if (HAS_DDI(dev)) { + } else if (HAS_DDI(dev_priv)) { intel_hdmi->write_infoframe = hsw_write_infoframe; intel_hdmi->set_infoframes = hsw_set_infoframes; intel_hdmi->infoframe_enabled = hsw_infoframe_enabled; @@ -1906,7 +1906,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi->infoframe_enabled = cpt_infoframe_enabled; } - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; else intel_connector->get_hw_state = intel_connector_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 15f21c6eb4f4..81c8b529d565 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7145,7 +7145,7 @@ static void lpt_init_clock_gating(struct drm_device *dev) * TODO: this bit should only be enabled when really needed, then * disabled when not needed anymore in order to save power. */ - if (HAS_PCH_LPT_LP(dev)) + if (HAS_PCH_LPT_LP(dev_priv)) I915_WRITE(SOUTH_DSPCLK_GATE_D, I915_READ(SOUTH_DSPCLK_GATE_D) | PCH_LP_PARTITION_LEVEL_DISABLE); @@ -7160,7 +7160,7 @@ static void lpt_suspend_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (HAS_PCH_LPT_LP(dev)) { + if (HAS_PCH_LPT_LP(dev_priv)) { uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D); val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 108ba1e5d658..9e2fbac9776e 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -344,7 +344,7 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) * ones. Since by Display design transcoder EDP is tied to port A * we can safely escape based on the port A. */ - if (HAS_DDI(dev) && dig_port->port != PORT_A) { + if (HAS_DDI(dev_priv) && dig_port->port != PORT_A) { DRM_DEBUG_KMS("PSR condition failed: Port not supported\n"); return false; } @@ -402,7 +402,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->psr.lock); /* Enable/Re-enable PSR on the host */ - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) /* On HSW+ after we enable PSR on source it will activate it * as soon as it match configure idle_frame count. So * we just actually enable it here on activation time. @@ -448,7 +448,7 @@ void intel_psr_enable(struct intel_dp *intel_dp) dev_priv->psr.busy_frontbuffer_bits = 0; - if (HAS_DDI(dev)) { + if (HAS_DDI(dev_priv)) { hsw_psr_setup_vsc(intel_dp); if (dev_priv->psr.psr2_support) { @@ -580,7 +580,7 @@ void intel_psr_disable(struct intel_dp *intel_dp) } /* Disable PSR on Source */ - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) hsw_psr_disable(intel_dp); else vlv_psr_disable(intel_dp); -- cgit v1.2.3 From 6e266956a57f878a6d648aed8e0380688e6f48c5 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:02:53 +0100 Subject: drm/i915: Make INTEL_PCH_TYPE & co only take dev_priv This saves 1872 bytes of .rodata strings. v2: * Rebase. * Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 16 ++++++------ drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 4 +-- drivers/gpu/drm/i915/i915_irq.c | 20 +++++++-------- drivers/gpu/drm/i915/intel_audio.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 25 +++++++++--------- drivers/gpu/drm/i915/intel_display.c | 48 ++++++++++++++++++----------------- drivers/gpu/drm/i915/intel_dp.c | 27 ++++++++++---------- drivers/gpu/drm/i915/intel_dpll_mgr.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 19 +++++++------- drivers/gpu/drm/i915/intel_i2c.c | 2 +- drivers/gpu/drm/i915/intel_lvds.c | 22 ++++++++-------- drivers/gpu/drm/i915/intel_pm.c | 6 ++--- drivers/gpu/drm/i915/intel_sdvo.c | 12 ++++----- 14 files changed, 107 insertions(+), 100 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a2ba8fa4269b..d9c2086bc351 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2846,18 +2846,18 @@ struct drm_i915_cmd_table { #define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000 #define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ -#define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type) -#define HAS_PCH_KBP(dev) (INTEL_PCH_TYPE(dev) == PCH_KBP) -#define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT) -#define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) +#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type) +#define HAS_PCH_KBP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_KBP) +#define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT) +#define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT) #define HAS_PCH_LPT_LP(dev_priv) \ ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) #define HAS_PCH_LPT_H(dev_priv) \ ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) -#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) -#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) -#define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP) -#define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE) +#define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT) +#define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX) +#define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) +#define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE) #define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->has_gmch_display) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fb460cc2857c..997628a63dba 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4433,7 +4433,7 @@ i915_gem_init_hw(struct drm_device *dev) I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ? LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); - if (HAS_PCH_NOP(dev)) { + if (HAS_PCH_NOP(dev_priv)) { if (IS_IVYBRIDGE(dev)) { u32 temp = I915_READ(GEN7_MSG_CTL); temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 8d4b9eb8718a..eee2c1102efb 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -589,7 +589,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, for (i = 0; i < 4; i++) err_printf(m, "GTIER gt %d: 0x%08x\n", i, error->gtier[i]); - } else if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev)) + } else if (HAS_PCH_SPLIT(dev_priv) || IS_VALLEYVIEW(dev_priv)) err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]); err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); @@ -1468,7 +1468,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, error->ier = I915_READ(GEN8_DE_MISC_IER); for (i = 0; i < 4; i++) error->gtier[i] = I915_READ(GEN8_GT_IER(i)); - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { error->ier = I915_READ(DEIER); error->gtier[0] = I915_READ(GTIER); } else if (IS_GEN2(dev)) { diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 89380c830cc0..5aed25669af0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3234,12 +3234,12 @@ static void ibx_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (HAS_PCH_NOP(dev)) + if (HAS_PCH_NOP(dev_priv)) return; GEN5_IRQ_RESET(SDE); - if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev)) + if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) I915_WRITE(SERR_INT, 0xffffffff); } @@ -3255,7 +3255,7 @@ static void ibx_irq_pre_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (HAS_PCH_NOP(dev)) + if (HAS_PCH_NOP(dev_priv)) return; WARN_ON(I915_READ(SDEIER) != 0); @@ -3380,7 +3380,7 @@ static void gen8_irq_reset(struct drm_device *dev) GEN5_IRQ_RESET(GEN8_DE_MISC_); GEN5_IRQ_RESET(GEN8_PCU_); - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) ibx_irq_reset(dev); } @@ -3569,10 +3569,10 @@ static void ibx_irq_postinstall(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); u32 mask; - if (HAS_PCH_NOP(dev)) + if (HAS_PCH_NOP(dev_priv)) return; - if (HAS_PCH_IBX(dev)) + if (HAS_PCH_IBX(dev_priv)) mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; else mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; @@ -3793,13 +3793,13 @@ static int gen8_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) ibx_irq_pre_postinstall(dev); gen8_gt_irq_postinstall(dev_priv); gen8_de_irq_postinstall(dev_priv); - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) ibx_irq_postinstall(dev); I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); @@ -4596,11 +4596,11 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->disable_vblank = gen8_disable_vblank; if (IS_BROXTON(dev)) dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; - else if (HAS_PCH_SPT(dev) || HAS_PCH_KBP(dev)) + else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_KBP(dev_priv)) dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; else dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { dev->driver->irq_handler = ironlake_irq_handler; dev->driver->irq_preinstall = ironlake_irq_reset; dev->driver->irq_postinstall = ironlake_irq_postinstall; diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 81df29ca4947..e20da59b1020 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -430,7 +430,7 @@ static void ilk_audio_codec_enable(struct drm_connector *connector, * infrastructure is not there yet. */ - if (HAS_PCH_IBX(connector->dev)) { + if (HAS_PCH_IBX(dev_priv)) { hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); aud_config = IBX_AUD_CFG(pipe); aud_cntl_st = IBX_AUD_CNTL_ST(pipe); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index d4b9b166de5d..f8919ef3a7af 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -84,7 +84,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, if (!(tmp & ADPA_DAC_ENABLE)) goto out; - if (HAS_PCH_CPT(dev)) + if (HAS_PCH_CPT(dev_priv)) *pipe = PORT_TO_PIPE_CPT(tmp); else *pipe = PORT_TO_PIPE(tmp); @@ -165,16 +165,16 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, adpa |= ADPA_VSYNC_ACTIVE_HIGH; /* For CPT allow 3 pipe config, for others just use A or B */ - if (HAS_PCH_LPT(dev)) + if (HAS_PCH_LPT(dev_priv)) ; /* Those bits don't exist here */ - else if (HAS_PCH_CPT(dev)) + else if (HAS_PCH_CPT(dev_priv)) adpa |= PORT_TRANS_SEL_CPT(crtc->pipe); else if (crtc->pipe == 0) adpa |= ADPA_PIPE_A_SELECT; else adpa |= ADPA_PIPE_B_SELECT; - if (!HAS_PCH_SPLIT(dev)) + if (!HAS_PCH_SPLIT(dev_priv)) I915_WRITE(BCLRPAT(crtc->pipe), 0); switch (mode) { @@ -241,7 +241,8 @@ intel_crt_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; - int max_dotclk = to_i915(dev)->max_dotclk_freq; + struct drm_i915_private *dev_priv = to_i915(dev); + int max_dotclk = dev_priv->max_dotclk_freq; int max_clock; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) @@ -250,7 +251,7 @@ intel_crt_mode_valid(struct drm_connector *connector, if (mode->clock < 25000) return MODE_CLOCK_LOW; - if (HAS_PCH_LPT(dev)) + if (HAS_PCH_LPT(dev_priv)) max_clock = 180000; else if (IS_VALLEYVIEW(dev)) /* @@ -269,7 +270,7 @@ intel_crt_mode_valid(struct drm_connector *connector, return MODE_CLOCK_HIGH; /* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */ - if (HAS_PCH_LPT(dev) && + if (HAS_PCH_LPT(dev_priv) && (ironlake_get_lanes_required(mode->clock, 270000, 24) > 2)) return MODE_CLOCK_HIGH; @@ -312,7 +313,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) /* The first time through, trigger an explicit detection cycle */ if (crt->force_hotplug_required) { - bool turn_off_dac = HAS_PCH_SPLIT(dev); + bool turn_off_dac = HAS_PCH_SPLIT(dev_priv); u32 save_adpa; crt->force_hotplug_required = 0; @@ -419,7 +420,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) bool ret = false; int i, tries = 0; - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) return intel_ironlake_crt_detect_hotplug(connector); if (IS_VALLEYVIEW(dev)) @@ -847,7 +848,7 @@ void intel_crt_init(struct drm_device *dev) i915_reg_t adpa_reg; u32 adpa; - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) adpa_reg = PCH_ADPA; else if (IS_VALLEYVIEW(dev)) adpa_reg = VLV_ADPA; @@ -907,7 +908,7 @@ void intel_crt_init(struct drm_device *dev) crt->adpa_reg = adpa_reg; crt->base.compute_config = intel_crt_compute_config; - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev_priv)) { crt->base.disable = pch_disable_crt; crt->base.post_disable = pch_post_disable_crt; } else { @@ -944,7 +945,7 @@ void intel_crt_init(struct drm_device *dev) * polarity and link reversal bits or not, instead of relying on the * BIOS. */ - if (HAS_PCH_LPT(dev)) { + if (HAS_PCH_LPT(dev_priv)) { u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT | FDI_RX_LINK_REVERSAL_OVERRIDE; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bec80f76bd01..61abc8f2728e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1784,7 +1784,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_device *dev = &dev_priv->drm; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); i915_reg_t reg; @@ -1797,7 +1796,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, assert_fdi_tx_enabled(dev_priv, pipe); assert_fdi_rx_enabled(dev_priv, pipe); - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { /* Workaround: Set the timing override bit before enabling the * pch transcoder. */ reg = TRANS_CHICKEN2(pipe); @@ -1875,7 +1874,6 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_device *dev = &dev_priv->drm; i915_reg_t reg; uint32_t val; @@ -1896,7 +1894,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, 50)) DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe)); - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { /* Workaround: Clear the timing override chicken bit again. */ reg = TRANS_CHICKEN2(pipe); val = I915_READ(reg); @@ -3710,7 +3708,7 @@ static void intel_update_pipe_config(struct intel_crtc *crtc, if (pipe_config->pch_pfit.enabled) skylake_pfit_enable(crtc); - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { if (pipe_config->pch_pfit.enabled) ironlake_pfit_enable(crtc); else if (old_crtc_state->pch_pfit.enabled) @@ -3741,7 +3739,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_NORMAL_CPT; } else { @@ -3899,7 +3897,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; } else { @@ -3952,7 +3950,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; } else { @@ -4206,7 +4204,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) udelay(100); /* Ironlake workaround, disable clock pointer after downing FDI */ - if (HAS_PCH_IBX(dev)) + if (HAS_PCH_IBX(dev_priv)) I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); /* still set train pattern 1 */ @@ -4218,7 +4216,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; } else { @@ -4554,7 +4552,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) /* We need to program the right clock selection before writing the pixel * mutliplier into the DPLL. */ - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { u32 sel; temp = I915_READ(PCH_DPLL_SEL); @@ -4584,7 +4582,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) intel_fdi_normal_train(crtc); /* For PCH DP, enable TRANS_DP_CTL */ - if (HAS_PCH_CPT(dev) && intel_crtc_has_dp_encoder(intel_crtc->config)) { + if (HAS_PCH_CPT(dev_priv) && + intel_crtc_has_dp_encoder(intel_crtc->config)) { const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; @@ -5378,7 +5377,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_enable(crtc, pipe_config, old_state); - if (HAS_PCH_CPT(dev)) + if (HAS_PCH_CPT(dev_priv)) cpt_verify_modeset(dev, intel_crtc->pipe); /* Must wait for vblank to avoid spurious PCH FIFO underruns */ @@ -5560,7 +5559,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, if (intel_crtc->config->has_pch_encoder) { ironlake_disable_pch_transcoder(dev_priv, pipe); - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { i915_reg_t reg; u32 temp; @@ -8946,7 +8945,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) } } - if (HAS_PCH_IBX(dev)) { + if (HAS_PCH_IBX(dev_priv)) { has_ck505 = dev_priv->vbt.display_clock_mode; can_ssc = has_ck505; } else { @@ -9342,9 +9341,11 @@ static void lpt_init_pch_refclk(struct drm_device *dev) */ void intel_init_pch_refclk(struct drm_device *dev) { - if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) + struct drm_i915_private *dev_priv = to_i915(dev); + + if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) ironlake_init_pch_refclk(dev); - else if (HAS_PCH_LPT(dev)) + else if (HAS_PCH_LPT(dev_priv)) lpt_init_pch_refclk(dev); } @@ -9473,7 +9474,7 @@ static void ironlake_compute_dpll(struct intel_crtc *intel_crtc, if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { if ((intel_panel_use_ssc(dev_priv) && dev_priv->vbt.lvds_ssc_freq == 100000) || - (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev))) + (HAS_PCH_IBX(dev_priv) && intel_is_dual_link_lvds(dev))) factor = 25; } else if (crtc_state->sdvo_tv_clock) factor = 20; @@ -11311,7 +11312,7 @@ static int i9xx_pll_refclk(struct drm_device *dev, if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) return dev_priv->vbt.lvds_ssc_freq; - else if (HAS_PCH_SPLIT(dev)) + else if (HAS_PCH_SPLIT(dev_priv)) return 120000; else if (!IS_GEN2(dev)) return 96000; @@ -14896,6 +14897,7 @@ const struct drm_plane_funcs intel_plane_funcs = { static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, int pipe) { + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *primary = NULL; struct intel_plane_state *state = NULL; const uint32_t *intel_primary_formats; @@ -14930,7 +14932,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, primary->update_plane = skylake_update_primary_plane; primary->disable_plane = skylake_disable_primary_plane; - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { intel_primary_formats = i965_primary_formats; num_formats = ARRAY_SIZE(i965_primary_formats); @@ -15438,7 +15440,7 @@ static void intel_setup_outputs(struct drm_device *dev) dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi)) intel_ddi_init(dev, PORT_E); - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { int found; dpd_is_edp = intel_dp_is_edp(dev, PORT_D); @@ -16357,7 +16359,7 @@ void intel_modeset_init(struct drm_device *dev) * BIOS isn't using it, don't assume it will work even if the VBT * indicates as much. */ - if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { + if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) { bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) & DREF_SSC1_ENABLE); @@ -16906,7 +16908,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev) vlv_wm_get_hw_state(dev); else if (IS_GEN9(dev)) skl_wm_get_hw_state(dev); - else if (HAS_PCH_SPLIT(dev)) + else if (HAS_PCH_SPLIT(dev_priv)) ilk_wm_get_hw_state(dev); for_each_intel_crtc(dev, crtc) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a5c562850d47..ec456ebaa91a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1336,13 +1336,14 @@ intel_dp_set_clock(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); const struct dp_link_dpll *divisor = NULL; int i, count = 0; if (IS_G4X(dev)) { divisor = gen4_dpll; count = ARRAY_SIZE(gen4_dpll); - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { divisor = pch_dpll; count = ARRAY_SIZE(pch_dpll); } else if (IS_CHERRYVIEW(dev)) { @@ -1776,7 +1777,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, intel_dp->DP |= DP_ENHANCED_FRAMING; intel_dp->DP |= crtc->pipe << 29; - } else if (HAS_PCH_CPT(dev) && port != PORT_A) { + } else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { u32 trans_dp; intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; @@ -1788,7 +1789,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, trans_dp &= ~TRANS_DP_ENH_FRAMING; I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); } else { - if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && + if (!HAS_PCH_SPLIT(dev_priv) && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && pipe_config->limited_color_range) intel_dp->DP |= DP_COLOR_RANGE_16_235; @@ -2442,7 +2443,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, if (IS_GEN7(dev) && port == PORT_A) { *pipe = PORT_TO_PIPE_CPT(tmp); - } else if (HAS_PCH_CPT(dev) && port != PORT_A) { + } else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { enum pipe p; for_each_pipe(dev_priv, p) { @@ -2485,7 +2486,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A; - if (HAS_PCH_CPT(dev) && port != PORT_A) { + if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { u32 trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe)); if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH) @@ -2511,8 +2512,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->base.adjusted_mode.flags |= flags; - if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && - !IS_CHERRYVIEW(dev) && tmp & DP_COLOR_RANGE_16_235) + if (!HAS_PCH_SPLIT(dev_priv) && !IS_VALLEYVIEW(dev_priv) && + !IS_CHERRYVIEW(dev_priv) && tmp & DP_COLOR_RANGE_16_235) pipe_config->limited_color_range = true; pipe_config->lane_count = @@ -2659,7 +2660,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, I915_WRITE(DP_TP_CTL(port), temp); } else if ((IS_GEN7(dev) && port == PORT_A) || - (HAS_PCH_CPT(dev) && port != PORT_A)) { + (HAS_PCH_CPT(dev_priv) && port != PORT_A)) { *DP &= ~DP_LINK_TRAIN_MASK_CPT; switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { @@ -2989,7 +2990,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; else if (IS_GEN7(dev) && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; - else if (HAS_PCH_CPT(dev) && port != PORT_A) + else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; else return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; @@ -3442,7 +3443,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) DRM_DEBUG_KMS("\n"); if ((IS_GEN7(dev) && port == PORT_A) || - (HAS_PCH_CPT(dev) && port != PORT_A)) { + (HAS_PCH_CPT(dev_priv) && port != PORT_A)) { DP &= ~DP_LINK_TRAIN_MASK_CPT; DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; } else { @@ -3464,7 +3465,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) * to transcoder A after disabling it to allow the * matching HDMI port to be enabled on transcoder A. */ - if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) { + if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B && port != PORT_A) { /* * We get CPU/PCH FIFO underruns on the other pipe when * doing the workaround. Sweep them under the rug. @@ -5085,7 +5086,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, * power sequencer any more. */ if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { port_sel = PANEL_PORT_SELECT_VLV(port); - } else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { + } else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) { if (port == PORT_A) port_sel = PANEL_PORT_SELECT_DPA; else @@ -5649,7 +5650,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider; else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider; - else if (HAS_PCH_SPLIT(dev)) + else if (HAS_PCH_SPLIT(dev_priv)) intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider; else intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index d0c59c1793ef..c37ce1263142 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1857,7 +1857,7 @@ void intel_shared_dpll_init(struct drm_device *dev) dpll_mgr = &bxt_pll_mgr; else if (HAS_DDI(dev_priv)) dpll_mgr = &hsw_pll_mgr; - else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) + else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) dpll_mgr = &pch_pll_mgr; if (!dpll_mgr) { diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 09b2146f157f..397e10f4b6f0 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -864,7 +864,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); hdmi_val = SDVO_ENCODING_HDMI; - if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) + if (!HAS_PCH_SPLIT(dev_priv) && crtc->config->limited_color_range) hdmi_val |= HDMI_COLOR_RANGE_16_235; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; @@ -879,7 +879,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) if (crtc->config->has_hdmi_sink) hdmi_val |= HDMI_MODE_SELECT_HDMI; - if (HAS_PCH_CPT(dev)) + if (HAS_PCH_CPT(dev_priv)) hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); else if (IS_CHERRYVIEW(dev)) hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe); @@ -911,7 +911,7 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, if (!(tmp & SDVO_ENABLE)) goto out; - if (HAS_PCH_CPT(dev)) + if (HAS_PCH_CPT(dev_priv)) *pipe = PORT_TO_PIPE_CPT(tmp); else if (IS_CHERRYVIEW(dev)) *pipe = SDVO_PORT_TO_PIPE_CHV(tmp); @@ -956,7 +956,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, if (tmp & SDVO_AUDIO_ENABLE) pipe_config->has_audio = true; - if (!HAS_PCH_SPLIT(dev) && + if (!HAS_PCH_SPLIT(dev_priv) && tmp & HDMI_COLOR_RANGE_16_235) pipe_config->limited_color_range = true; @@ -1141,7 +1141,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder, * to transcoder A after disabling it to allow the * matching DP port to be enabled on transcoder A. */ - if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B) { + if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) { /* * We get CPU/PCH FIFO underruns on the other pipe when * doing the workaround. Sweep them under the rug. @@ -1896,7 +1896,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi->write_infoframe = hsw_write_infoframe; intel_hdmi->set_infoframes = hsw_set_infoframes; intel_hdmi->infoframe_enabled = hsw_infoframe_enabled; - } else if (HAS_PCH_IBX(dev)) { + } else if (HAS_PCH_IBX(dev_priv)) { intel_hdmi->write_infoframe = ibx_write_infoframe; intel_hdmi->set_infoframes = ibx_set_infoframes; intel_hdmi->infoframe_enabled = ibx_infoframe_enabled; @@ -1929,6 +1929,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, void intel_hdmi_init(struct drm_device *dev, i915_reg_t hdmi_reg, enum port port) { + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_digital_port *intel_dig_port; struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; @@ -1949,7 +1950,7 @@ void intel_hdmi_init(struct drm_device *dev, DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port)); intel_encoder->compute_config = intel_hdmi_compute_config; - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev_priv)) { intel_encoder->disable = pch_disable_hdmi; intel_encoder->post_disable = pch_post_disable_hdmi; } else { @@ -1970,9 +1971,9 @@ void intel_hdmi_init(struct drm_device *dev, intel_encoder->post_disable = vlv_hdmi_post_disable; } else { intel_encoder->pre_enable = intel_hdmi_pre_enable; - if (HAS_PCH_CPT(dev)) + if (HAS_PCH_CPT(dev_priv)) intel_encoder->enable = cpt_enable_hdmi; - else if (HAS_PCH_IBX(dev)) + else if (HAS_PCH_IBX(dev_priv)) intel_encoder->enable = ibx_enable_hdmi; else intel_encoder->enable = g4x_enable_hdmi; diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 79aab9ad6faa..1410330ec9bb 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -633,7 +633,7 @@ int intel_setup_gmbus(struct drm_device *dev) unsigned int pin; int ret; - if (HAS_PCH_NOP(dev)) + if (HAS_PCH_NOP(dev_priv)) return 0; if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 2e943bd1c3cf..baaf2ed897ef 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -106,7 +106,7 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, if (!(tmp & LVDS_PORT_EN)) goto out; - if (HAS_PCH_CPT(dev)) + if (HAS_PCH_CPT(dev_priv)) *pipe = PORT_TO_PIPE_CPT(tmp); else *pipe = PORT_TO_PIPE(tmp); @@ -396,7 +396,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - struct drm_device *dev = intel_encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&intel_encoder->base); struct intel_connector *intel_connector = @@ -406,7 +406,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, unsigned int lvds_bpp; /* Should never happen!! */ - if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) { + if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) { DRM_ERROR("Can't support LVDS on pipe A\n"); return false; } @@ -431,7 +431,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, intel_fixed_panel_mode(intel_connector->panel.fixed_mode, adjusted_mode); - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev_priv)) { pipe_config->has_pch_encoder = true; intel_pch_panel_fitting(intel_crtc, pipe_config, @@ -566,7 +566,7 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, * and as part of the cleanup in the hw state restore we also redisable * the vga plane. */ - if (!HAS_PCH_SPLIT(dev)) + if (!HAS_PCH_SPLIT(dev_priv)) intel_display_resume(dev); dev_priv->modeset_restore = MODESET_DONE; @@ -951,9 +951,11 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) static bool intel_lvds_supported(struct drm_device *dev) { + struct drm_i915_private *dev_priv = to_i915(dev); + /* With the introduction of the PCH we gained a dedicated * LVDS presence pin, use it. */ - if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) + if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) return true; /* Otherwise LVDS was only attached to mobile products, @@ -997,14 +999,14 @@ void intel_lvds_init(struct drm_device *dev) if (dmi_check_system(intel_no_lvds)) return; - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) lvds_reg = PCH_LVDS; else lvds_reg = LVDS; lvds = I915_READ(lvds_reg); - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev_priv)) { if ((lvds & LVDS_DETECTED) == 0) return; if (dev_priv->vbt.edp.support) { @@ -1068,7 +1070,7 @@ void intel_lvds_init(struct drm_device *dev) intel_encoder->type = INTEL_OUTPUT_LVDS; intel_encoder->port = PORT_NONE; intel_encoder->cloneable = 0; - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); else if (IS_GEN4(dev)) intel_encoder->crtc_mask = (1 << 0) | (1 << 1); @@ -1158,7 +1160,7 @@ void intel_lvds_init(struct drm_device *dev) */ /* Ironlake: FIXME if still fail, not try pipe mode now */ - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) goto failed; pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 81c8b529d565..73be4792bbd4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7426,7 +7426,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) snpcr |= GEN6_MBC_SNPCR_MED; I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); - if (!HAS_PCH_NOP(dev)) + if (!HAS_PCH_NOP(dev_priv)) cpt_init_clock_gating(dev); gen6_check_mch_setup(dev); @@ -7669,7 +7669,7 @@ void intel_init_clock_gating(struct drm_device *dev) void intel_suspend_hw(struct drm_device *dev) { - if (HAS_PCH_LPT(dev)) + if (HAS_PCH_LPT(to_i915(dev))) lpt_suspend_hw(dev); } @@ -7745,7 +7745,7 @@ void intel_init_pm(struct drm_device *dev) skl_setup_wm_latency(dev); dev_priv->display.update_wm = skl_update_wm; dev_priv->display.compute_global_watermarks = skl_compute_wm; - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { ilk_setup_wm_latency(dev); if ((IS_GEN5(dev) && dev_priv->wm.pri_latency[1] && diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 9f352aac9526..f5ee2ae0fa12 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -251,7 +251,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) * HW workaround, need to write this twice for issue * that may result in first write getting masked. */ - if (HAS_PCH_IBX(dev)) { + if (HAS_PCH_IBX(dev_priv)) { I915_WRITE(intel_sdvo->sdvo_reg, val); POSTING_READ(intel_sdvo->sdvo_reg); } @@ -1133,7 +1133,7 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n"); pipe_config->pipe_bpp = 8*3; - if (HAS_PCH_SPLIT(encoder->base.dev)) + if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) pipe_config->has_pch_encoder = true; /* We need to construct preferred input timings based on our @@ -1273,7 +1273,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, /* The real mode polarity is set by the SDVO commands, using * struct intel_sdvo_dtd. */ sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH; - if (!HAS_PCH_SPLIT(dev) && crtc_state->limited_color_range) + if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range) sdvox |= HDMI_COLOR_RANGE_16_235; if (INTEL_INFO(dev)->gen < 5) sdvox |= SDVO_BORDER_ENABLE; @@ -1286,7 +1286,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; } - if (INTEL_PCH_TYPE(dev) >= PCH_CPT) + if (INTEL_PCH_TYPE(dev_priv) >= PCH_CPT) sdvox |= SDVO_PIPE_SEL_CPT(crtc->pipe); else sdvox |= SDVO_PIPE_SEL(crtc->pipe); @@ -1339,7 +1339,7 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder, if (!(tmp & SDVO_ENABLE) && (active_outputs == 0)) return false; - if (HAS_PCH_CPT(dev)) + if (HAS_PCH_CPT(dev_priv)) *pipe = PORT_TO_PIPE_CPT(tmp); else *pipe = PORT_TO_PIPE(tmp); @@ -2997,7 +2997,7 @@ bool intel_sdvo_init(struct drm_device *dev, } intel_encoder->compute_config = intel_sdvo_compute_config; - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev_priv)) { intel_encoder->disable = pch_disable_sdvo; intel_encoder->post_disable = pch_post_disable_sdvo; } else { -- cgit v1.2.3 From 49cff963dd14ecc4520ad094afa258cbeee4bb23 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:02:54 +0100 Subject: drm/i915: Make HAS_GMCH_DISPLAY only take dev_priv More .rodata string saving by avoid __I915__ magic inside WARNs. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_color.c | 6 +++--- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_fifo_underrun.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 5 +++-- 7 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d9c2086bc351..04f4a4f7dbd0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2859,7 +2859,7 @@ struct drm_i915_cmd_table { #define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) #define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE) -#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->has_gmch_display) +#define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.has_gmch_display) /* DPF == dynamic parity feature */ #define HAS_L3_DPF(dev) (INTEL_INFO(dev)->has_l3_dpf) diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index 95a72771eea6..5362c07932d3 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -273,7 +273,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, enum pipe pipe = intel_crtc->pipe; int i; - if (HAS_GMCH_DISPLAY(dev)) { + if (HAS_GMCH_DISPLAY(dev_priv)) { if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) assert_dsi_pll_enabled(dev_priv); else @@ -288,7 +288,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, (drm_color_lut_extract(lut[i].green, 8) << 8) | drm_color_lut_extract(lut[i].blue, 8); - if (HAS_GMCH_DISPLAY(dev)) + if (HAS_GMCH_DISPLAY(dev_priv)) I915_WRITE(PALETTE(pipe, i), word); else I915_WRITE(LGC_PALETTE(pipe, i), word); @@ -297,7 +297,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, for (i = 0; i < 256; i++) { uint32_t word = (i << 16) | (i << 8) | i; - if (HAS_GMCH_DISPLAY(dev)) + if (HAS_GMCH_DISPLAY(dev_priv)) I915_WRITE(PALETTE(pipe, i), word); else I915_WRITE(LGC_PALETTE(pipe, i), word); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 61abc8f2728e..8ac5dd0796e3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5034,7 +5034,7 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) * event which is after the vblank start event, so we need to have a * wait-for-vblank between disabling the plane and the pipe. */ - if (HAS_GMCH_DISPLAY(dev)) { + if (HAS_GMCH_DISPLAY(dev_priv)) { intel_set_memory_cxsr(dev_priv, false); dev_priv->wm.vlv.cxsr = false; intel_wait_for_vblank(dev, pipe); @@ -5099,7 +5099,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) intel_pre_disable_primary(&crtc->base); } - if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev)) { + if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev_priv)) { crtc->wm.cxsr_allowed = false; /* @@ -10893,7 +10893,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, pos |= y << CURSOR_Y_SHIFT; /* ILK+ do this automagically */ - if (HAS_GMCH_DISPLAY(dev) && + if (HAS_GMCH_DISPLAY(dev_priv) && plane_state->base.rotation == DRM_ROTATE_180) { base += (plane_state->base.crtc_h * plane_state->base.crtc_w - 1) * 4; @@ -16591,7 +16591,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) if (crtc->active && !intel_crtc_has_encoders(crtc)) intel_crtc_disable_noatomic(&crtc->base); - if (crtc->active || HAS_GMCH_DISPLAY(dev)) { + if (crtc->active || HAS_GMCH_DISPLAY(dev_priv)) { /* * We start out with underrun reporting disabled to avoid races. * For correct bookkeeping mark this on active crtcs. diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ec456ebaa91a..d2fd3702e415 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1583,7 +1583,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, return ret; } - if (HAS_GMCH_DISPLAY(dev)) + if (HAS_GMCH_DISPLAY(dev_priv)) intel_gmch_panel_fitting(intel_crtc, pipe_config, intel_connector->panel.fitting_mode); else diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 727adaace96c..5b1e445a80d0 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1346,7 +1346,7 @@ static int intel_dsi_set_property(struct drm_connector *connector, DRM_DEBUG_KMS("no scaling not supported\n"); return -EINVAL; } - if (HAS_GMCH_DISPLAY(dev) && + if (HAS_GMCH_DISPLAY(to_i915(dev)) && val == DRM_MODE_SCALE_CENTER) { DRM_DEBUG_KMS("centering not supported\n"); return -EINVAL; diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index ebb4fed8322e..076893cc3890 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -254,7 +254,7 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, old = !intel_crtc->cpu_fifo_underrun_disabled; intel_crtc->cpu_fifo_underrun_disabled = !enable; - if (HAS_GMCH_DISPLAY(dev)) + if (HAS_GMCH_DISPLAY(dev_priv)) i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old); else if (IS_GEN5(dev) || IS_GEN6(dev)) ironlake_set_fifo_underrun_reporting(dev, pipe, enable); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 397e10f4b6f0..ad3ff4fe63cf 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1265,6 +1265,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, { struct intel_hdmi *hdmi = intel_attached_hdmi(connector); struct drm_device *dev = intel_hdmi_to_dev(hdmi); + struct drm_i915_private *dev_priv = to_i915(dev); enum drm_mode_status status; int clock; int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; @@ -1287,7 +1288,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, status = hdmi_port_clock_valid(hdmi, clock, true); /* if we can't do 8bpc we may still be able to do 12bpc */ - if (!HAS_GMCH_DISPLAY(dev) && status != MODE_OK) + if (!HAS_GMCH_DISPLAY(dev_priv) && status != MODE_OK) status = hdmi_port_clock_valid(hdmi, clock * 3 / 2, true); return status; @@ -1297,7 +1298,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc_state->base.crtc->dev; - if (HAS_GMCH_DISPLAY(dev)) + if (HAS_GMCH_DISPLAY(to_i915(dev))) return false; /* -- cgit v1.2.3 From 6772ffe0235937414e6ab2de0f44adb1cb794408 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:02:55 +0100 Subject: drm/i915: Make HAS_RUNTIME_PM only take dev_priv Saves 960 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8c3d4761dfa0..8183743ef422 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2285,7 +2285,7 @@ static int intel_runtime_suspend(struct device *kdev) if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6()))) return -ENODEV; - if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev))) + if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv))) return -ENODEV; DRM_DEBUG_KMS("Suspending device\n"); @@ -2389,7 +2389,7 @@ static int intel_runtime_resume(struct device *kdev) struct drm_i915_private *dev_priv = to_i915(dev); int ret = 0; - if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev))) + if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv))) return -ENODEV; DRM_DEBUG_KMS("Resuming device\n"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 04f4a4f7dbd0..2cad4d74109c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2814,12 +2814,12 @@ struct drm_i915_cmd_table { #define HAS_DDI(dev_priv) ((dev_priv)->info.has_ddi) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr) -#define HAS_RUNTIME_PM(dev) (INTEL_INFO(dev)->has_runtime_pm) #define HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) #define HAS_RC6p(dev) (INTEL_INFO(dev)->has_rc6p) #define HAS_CSR(dev) (INTEL_INFO(dev)->has_csr) +#define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm) /* * For now, anything with a GuC requires uCode loading, and then supports * command submission once loaded. But these are logically independent diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 6c11168facd6..ed1faf14f777 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2758,7 +2758,6 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv) void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = dev_priv->drm.pdev; - struct drm_device *dev = &dev_priv->drm; struct device *kdev = &pdev->dev; pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */ @@ -2770,7 +2769,7 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) * so the driver's own RPM reference tracking asserts also work on * platforms without RPM support. */ - if (!HAS_RUNTIME_PM(dev)) { + if (!HAS_RUNTIME_PM(dev_priv)) { pm_runtime_dont_use_autosuspend(kdev); pm_runtime_get_sync(kdev); } else { -- cgit v1.2.3 From 70006ad6d8059dd9aa473a2bb739b6151c0ae117 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:02:56 +0100 Subject: drm/i915: Do not use INTEL_INFO(dev_priv)->ring_mask inside WARNs Saves 1520 bytes of .rodata strings. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/intel_engine_cs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index fba6edd9f819..2dc94812bea5 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -116,6 +116,7 @@ int intel_engines_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_device_info *device_info = mkwrite_device_info(dev_priv); + unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask; unsigned int mask = 0; int (*init)(struct intel_engine_cs *engine); struct intel_engine_cs *engine; @@ -123,8 +124,8 @@ int intel_engines_init(struct drm_device *dev) unsigned int i; int ret; - WARN_ON(INTEL_INFO(dev_priv)->ring_mask == 0); - WARN_ON(INTEL_INFO(dev_priv)->ring_mask & + WARN_ON(ring_mask == 0); + WARN_ON(ring_mask & GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES)); for (i = 0; i < ARRAY_SIZE(intel_engines); i++) { @@ -155,7 +156,7 @@ int intel_engines_init(struct drm_device *dev) * are added to the driver by a warning and disabling the forgotten * engines. */ - if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask)) + if (WARN_ON(mask != ring_mask)) device_info->ring_mask = mask; device_info->num_rings = hweight32(mask); -- cgit v1.2.3 From c1812bdbe006c79e9c21fd50d642ac9f8cbe0504 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:02:57 +0100 Subject: drm/i915: Make IS_GEN-range macro only take dev_priv Saves 944 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2cad4d74109c..100740e50e70 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2612,7 +2612,7 @@ struct drm_i915_cmd_table { * * Use GEN_FOREVER for unbound start and or end. */ -#define IS_GEN(p, s, e) ({ \ +#define IS_GEN(dev_priv, s, e) ({ \ unsigned int __s = (s), __e = (e); \ BUILD_BUG_ON(!__builtin_constant_p(s)); \ BUILD_BUG_ON(!__builtin_constant_p(e)); \ @@ -2622,7 +2622,7 @@ struct drm_i915_cmd_table { __e = BITS_PER_LONG - 1; \ else \ __e = (e) - 1; \ - !!(INTEL_INFO(p)->gen_mask & GENMASK((__e), (__s))); \ + !!((dev_priv)->info.gen_mask & GENMASK((__e), (__s))); \ }) /* -- cgit v1.2.3 From 50a0bc90541689b9b834bf93d9ba815e05423a18 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:02:58 +0100 Subject: drm/i915: Make INTEL_DEVID only take dev_priv Saves 4472 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.c | 14 +++-- drivers/gpu/drm/i915/i915_drv.h | 111 +++++++++++++++++---------------- drivers/gpu/drm/i915/i915_gem.c | 36 +++++------ drivers/gpu/drm/i915/i915_gem_stolen.c | 6 +- drivers/gpu/drm/i915/i915_gem_tiling.c | 3 +- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 58 +++++++++-------- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_i2c.c | 5 +- drivers/gpu/drm/i915/intel_lvds.c | 9 ++- drivers/gpu/drm/i915/intel_pm.c | 26 ++++---- drivers/gpu/drm/i915/intel_sdvo.c | 11 ++-- drivers/gpu/drm/i915/intel_tv.c | 4 +- 15 files changed, 151 insertions(+), 142 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8183743ef422..bb14e9521c5e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -188,12 +188,14 @@ static void intel_detect_pch(struct drm_device *dev) dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint PCH\n"); WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); - WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev)); + WARN_ON(IS_HSW_ULT(dev_priv) || + IS_BDW_ULT(dev_priv)); } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); - WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev)); + WARN_ON(!IS_HSW_ULT(dev_priv) && + !IS_BDW_ULT(dev_priv)); } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); @@ -422,7 +424,7 @@ intel_setup_mchbar(struct drm_device *dev) dev_priv->mchbar_need_disable = false; - if (IS_I915G(dev) || IS_I915GM(dev)) { + if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp); enabled = !!(temp & DEVEN_MCHBAR_EN); } else { @@ -440,7 +442,7 @@ intel_setup_mchbar(struct drm_device *dev) dev_priv->mchbar_need_disable = true; /* Space is allocated or reserved, so enable it. */ - if (IS_I915G(dev) || IS_I915GM(dev)) { + if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { pci_write_config_dword(dev_priv->bridge_dev, DEVEN, temp | DEVEN_MCHBAR_EN); } else { @@ -456,7 +458,7 @@ intel_teardown_mchbar(struct drm_device *dev) int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; if (dev_priv->mchbar_need_disable) { - if (IS_I915G(dev) || IS_I915GM(dev)) { + if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { u32 deven_val; pci_read_config_dword(dev_priv->bridge_dev, DEVEN, @@ -1053,7 +1055,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) * be lost or delayed, but we use them anyways to avoid * stuck interrupts on some machines. */ - if (!IS_I945G(dev) && !IS_I945GM(dev)) { + if (!IS_I945G(dev_priv) && !IS_I945GM(dev_priv)) { if (pci_enable_msi(pdev) < 0) DRM_DEBUG_DRIVER("can't enable MSI"); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 100740e50e70..c05d5c8b6449 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2601,7 +2601,8 @@ struct drm_i915_cmd_table { }) #define INTEL_INFO(p) (&__I915__(p)->info) #define INTEL_GEN(p) (INTEL_INFO(p)->gen) -#define INTEL_DEVID(p) (INTEL_INFO(p)->device_id) + +#define INTEL_DEVID(dev_priv) ((dev_priv)->info.device_id) #define REVID_FOREVER 0xff #define INTEL_REVID(p) (__I915__(p)->drm.pdev->revision) @@ -2633,27 +2634,27 @@ struct drm_i915_cmd_table { #define IS_REVID(p, since, until) \ (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until)) -#define IS_I830(dev) (INTEL_DEVID(dev) == 0x3577) -#define IS_845G(dev) (INTEL_DEVID(dev) == 0x2562) +#define IS_I830(dev_priv) (INTEL_DEVID(dev_priv) == 0x3577) +#define IS_845G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2562) #define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) -#define IS_I865G(dev) (INTEL_DEVID(dev) == 0x2572) +#define IS_I865G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2572) #define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) -#define IS_I915GM(dev) (INTEL_DEVID(dev) == 0x2592) -#define IS_I945G(dev) (INTEL_DEVID(dev) == 0x2772) +#define IS_I915GM(dev_priv) (INTEL_DEVID(dev_priv) == 0x2592) +#define IS_I945G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2772) #define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) #define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) -#define IS_GM45(dev) (INTEL_DEVID(dev) == 0x2A42) +#define IS_GM45(dev_priv) (INTEL_DEVID(dev_priv) == 0x2A42) #define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x) -#define IS_PINEVIEW_G(dev) (INTEL_DEVID(dev) == 0xa001) -#define IS_PINEVIEW_M(dev) (INTEL_DEVID(dev) == 0xa011) +#define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001) +#define IS_PINEVIEW_M(dev_priv) (INTEL_DEVID(dev_priv) == 0xa011) #define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) #define IS_G33(dev) (INTEL_INFO(dev)->is_g33) -#define IS_IRONLAKE_M(dev) (INTEL_DEVID(dev) == 0x0046) +#define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046) #define IS_IVYBRIDGE(dev) (INTEL_INFO(dev)->is_ivybridge) -#define IS_IVB_GT1(dev) (INTEL_DEVID(dev) == 0x0156 || \ - INTEL_DEVID(dev) == 0x0152 || \ - INTEL_DEVID(dev) == 0x015a) +#define IS_IVB_GT1(dev_priv) (INTEL_DEVID(dev_priv) == 0x0156 || \ + INTEL_DEVID(dev_priv) == 0x0152 || \ + INTEL_DEVID(dev_priv) == 0x015a) #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) #define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview) #define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) @@ -2662,44 +2663,44 @@ struct drm_i915_cmd_table { #define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton) #define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) -#define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ - (INTEL_DEVID(dev) & 0xFF00) == 0x0C00) -#define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ - ((INTEL_DEVID(dev) & 0xf) == 0x6 || \ - (INTEL_DEVID(dev) & 0xf) == 0xb || \ - (INTEL_DEVID(dev) & 0xf) == 0xe)) +#define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \ + (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00) +#define IS_BDW_ULT(dev_priv) (IS_BROADWELL(dev_priv) && \ + ((INTEL_DEVID(dev_priv) & 0xf) == 0x6 || \ + (INTEL_DEVID(dev_priv) & 0xf) == 0xb || \ + (INTEL_DEVID(dev_priv) & 0xf) == 0xe)) /* ULX machines are also considered ULT. */ -#define IS_BDW_ULX(dev) (IS_BROADWELL(dev) && \ - (INTEL_DEVID(dev) & 0xf) == 0xe) -#define IS_BDW_GT3(dev) (IS_BROADWELL(dev) && \ - (INTEL_DEVID(dev) & 0x00F0) == 0x0020) -#define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \ - (INTEL_DEVID(dev) & 0xFF00) == 0x0A00) -#define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ - (INTEL_DEVID(dev) & 0x00F0) == 0x0020) +#define IS_BDW_ULX(dev_priv) (IS_BROADWELL(dev_priv) && \ + (INTEL_DEVID(dev_priv) & 0xf) == 0xe) +#define IS_BDW_GT3(dev_priv) (IS_BROADWELL(dev_priv) && \ + (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) +#define IS_HSW_ULT(dev_priv) (IS_HASWELL(dev_priv) && \ + (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0A00) +#define IS_HSW_GT3(dev_priv) (IS_HASWELL(dev_priv) && \ + (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) /* ULX machines are also considered ULT. */ -#define IS_HSW_ULX(dev) (INTEL_DEVID(dev) == 0x0A0E || \ - INTEL_DEVID(dev) == 0x0A1E) -#define IS_SKL_ULT(dev) (INTEL_DEVID(dev) == 0x1906 || \ - INTEL_DEVID(dev) == 0x1913 || \ - INTEL_DEVID(dev) == 0x1916 || \ - INTEL_DEVID(dev) == 0x1921 || \ - INTEL_DEVID(dev) == 0x1926) -#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ - INTEL_DEVID(dev) == 0x1915 || \ - INTEL_DEVID(dev) == 0x191E) -#define IS_KBL_ULT(dev) (INTEL_DEVID(dev) == 0x5906 || \ - INTEL_DEVID(dev) == 0x5913 || \ - INTEL_DEVID(dev) == 0x5916 || \ - INTEL_DEVID(dev) == 0x5921 || \ - INTEL_DEVID(dev) == 0x5926) -#define IS_KBL_ULX(dev) (INTEL_DEVID(dev) == 0x590E || \ - INTEL_DEVID(dev) == 0x5915 || \ - INTEL_DEVID(dev) == 0x591E) -#define IS_SKL_GT3(dev) (IS_SKYLAKE(dev) && \ - (INTEL_DEVID(dev) & 0x00F0) == 0x0020) -#define IS_SKL_GT4(dev) (IS_SKYLAKE(dev) && \ - (INTEL_DEVID(dev) & 0x00F0) == 0x0030) +#define IS_HSW_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x0A0E || \ + INTEL_DEVID(dev_priv) == 0x0A1E) +#define IS_SKL_ULT(dev_priv) (INTEL_DEVID(dev_priv) == 0x1906 || \ + INTEL_DEVID(dev_priv) == 0x1913 || \ + INTEL_DEVID(dev_priv) == 0x1916 || \ + INTEL_DEVID(dev_priv) == 0x1921 || \ + INTEL_DEVID(dev_priv) == 0x1926) +#define IS_SKL_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x190E || \ + INTEL_DEVID(dev_priv) == 0x1915 || \ + INTEL_DEVID(dev_priv) == 0x191E) +#define IS_KBL_ULT(dev_priv) (INTEL_DEVID(dev_priv) == 0x5906 || \ + INTEL_DEVID(dev_priv) == 0x5913 || \ + INTEL_DEVID(dev_priv) == 0x5916 || \ + INTEL_DEVID(dev_priv) == 0x5921 || \ + INTEL_DEVID(dev_priv) == 0x5926) +#define IS_KBL_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x590E || \ + INTEL_DEVID(dev_priv) == 0x5915 || \ + INTEL_DEVID(dev_priv) == 0x591E) +#define IS_SKL_GT3(dev_priv) (IS_SKYLAKE(dev_priv) && \ + (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) +#define IS_SKL_GT4(dev_priv) (IS_SKYLAKE(dev_priv) && \ + (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0030) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) @@ -2778,7 +2779,7 @@ struct drm_i915_cmd_table { #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) /* Early gen2 have a totally busted CS tlb and require pinned batches. */ -#define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev)) +#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_845G(dev_priv)) /* WaRsDisableCoarsePowerGating:skl,bxt */ #define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \ @@ -2798,8 +2799,9 @@ struct drm_i915_cmd_table { /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte * rows, which changed the alignment requirements and fence programming. */ -#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \ - IS_I915GM(dev))) +#define HAS_128_BYTE_Y_TILING(dev_priv) (!IS_GEN2(dev_priv) && \ + !(IS_I915G(dev_priv) || \ + IS_I915GM(dev_priv))) #define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) @@ -2807,7 +2809,7 @@ struct drm_i915_cmd_table { #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) #define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) -#define HAS_IPS(dev) (IS_HSW_ULT(dev) || IS_BROADWELL(dev)) +#define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv)) #define HAS_DP_MST(dev) (INTEL_INFO(dev)->has_dp_mst) @@ -2863,7 +2865,8 @@ struct drm_i915_cmd_table { /* DPF == dynamic parity feature */ #define HAS_L3_DPF(dev) (INTEL_INFO(dev)->has_l3_dpf) -#define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev)) +#define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \ + 2 : HAS_L3_DPF(dev_priv)) #define GT_FREQUENCY_MULTIPLIER 50 #define GEN9_FREQ_SCALER 3 diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 997628a63dba..ed24907ed471 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4388,30 +4388,28 @@ void i915_gem_init_swizzling(struct drm_device *dev) BUG(); } -static void init_unused_ring(struct drm_device *dev, u32 base) +static void init_unused_ring(struct drm_i915_private *dev_priv, u32 base) { - struct drm_i915_private *dev_priv = to_i915(dev); - I915_WRITE(RING_CTL(base), 0); I915_WRITE(RING_HEAD(base), 0); I915_WRITE(RING_TAIL(base), 0); I915_WRITE(RING_START(base), 0); } -static void init_unused_rings(struct drm_device *dev) -{ - if (IS_I830(dev)) { - init_unused_ring(dev, PRB1_BASE); - init_unused_ring(dev, SRB0_BASE); - init_unused_ring(dev, SRB1_BASE); - init_unused_ring(dev, SRB2_BASE); - init_unused_ring(dev, SRB3_BASE); - } else if (IS_GEN2(dev)) { - init_unused_ring(dev, SRB0_BASE); - init_unused_ring(dev, SRB1_BASE); - } else if (IS_GEN3(dev)) { - init_unused_ring(dev, PRB1_BASE); - init_unused_ring(dev, PRB2_BASE); +static void init_unused_rings(struct drm_i915_private *dev_priv) +{ + if (IS_I830(dev_priv)) { + init_unused_ring(dev_priv, PRB1_BASE); + init_unused_ring(dev_priv, SRB0_BASE); + init_unused_ring(dev_priv, SRB1_BASE); + init_unused_ring(dev_priv, SRB2_BASE); + init_unused_ring(dev_priv, SRB3_BASE); + } else if (IS_GEN2(dev_priv)) { + init_unused_ring(dev_priv, SRB0_BASE); + init_unused_ring(dev_priv, SRB1_BASE); + } else if (IS_GEN3(dev_priv)) { + init_unused_ring(dev_priv, PRB1_BASE); + init_unused_ring(dev_priv, PRB2_BASE); } } @@ -4430,7 +4428,7 @@ i915_gem_init_hw(struct drm_device *dev) I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf)); if (IS_HASWELL(dev)) - I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ? + I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev_priv) ? LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); if (HAS_PCH_NOP(dev_priv)) { @@ -4453,7 +4451,7 @@ i915_gem_init_hw(struct drm_device *dev) * will prevent c3 entry. Makes sure all unused rings * are totally idle. */ - init_unused_rings(dev); + init_unused_rings(dev_priv); BUG_ON(!dev_priv->kernel_context); diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 59989e8ee5dc..cbea6fb83ce5 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -115,7 +115,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) pci_read_config_dword(pdev, INTEL_BSM, &bsm); base = bsm & INTEL_BSM_MASK; - } else if (IS_I865G(dev)) { + } else if (IS_I865G(dev_priv)) { u32 tseg_size = 0; u16 toud = 0; u8 tmp; @@ -154,7 +154,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) tom = tmp * MB(32); base = tom - tseg_size - ggtt->stolen_size; - } else if (IS_845G(dev)) { + } else if (IS_845G(dev_priv)) { u32 tseg_size = 0; u32 tom; u8 tmp; @@ -178,7 +178,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) tom = tmp * MB(32); base = tom - tseg_size - ggtt->stolen_size; - } else if (IS_I830(dev)) { + } else if (IS_I830(dev_priv)) { u32 tseg_size = 0; u32 tom; u8 tmp; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index a14b1e3d4c78..89d1d234a1b4 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -62,6 +62,7 @@ static bool i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) { + struct drm_i915_private *dev_priv = to_i915(dev); int tile_width; /* Linear is always fine */ @@ -72,7 +73,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) return false; if (IS_GEN2(dev) || - (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) + (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev_priv))) tile_width = 128; else tile_width = 512; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5aed25669af0..c2a960eb0290 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3653,7 +3653,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) ibx_irq_postinstall(dev); - if (IS_IRONLAKE_M(dev)) { + if (IS_IRONLAKE_M(dev_priv)) { /* Enable PCU event interrupts * * spinlocking not required here for correctness since interrupt diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index f8919ef3a7af..d4388c03b4da 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -431,7 +431,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) * to get a reliable result. */ - if (IS_G4X(dev) && !IS_GM45(dev)) + if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) tries = 2; else tries = 1; @@ -894,7 +894,7 @@ void intel_crt_init(struct drm_device *dev) crt->base.type = INTEL_OUTPUT_ANALOG; crt->base.cloneable = (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_HDMI); - if (IS_I830(dev)) + if (IS_I830(dev_priv)) crt->base.crtc_mask = (1 << 0); else crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8ac5dd0796e3..b60a37f7dca1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1230,10 +1230,9 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) static void assert_cursor(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { - struct drm_device *dev = &dev_priv->drm; bool cur_state; - if (IS_845G(dev) || IS_I865G(dev)) + if (IS_845G(dev_priv) || IS_I865G(dev_priv)) cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; else cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; @@ -1617,11 +1616,11 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) assert_pipe_disabled(dev_priv, crtc->pipe); /* PLL is protected by panel, make sure we can write it */ - if (IS_MOBILE(dev) && !IS_I830(dev)) + if (IS_MOBILE(dev_priv) && !IS_I830(dev_priv)) assert_panel_unlocked(dev_priv, crtc->pipe); /* Enable DVO 2x clock on both PLLs if necessary */ - if (IS_I830(dev) && intel_num_dvo_pipes(dev) > 0) { + if (IS_I830(dev_priv) && intel_num_dvo_pipes(dev) > 0) { /* * It appears to be important that we don't enable this * for the current pipe before otherwise configuring the @@ -1686,7 +1685,7 @@ static void i9xx_disable_pll(struct intel_crtc *crtc) enum pipe pipe = crtc->pipe; /* Disable DVO 2x clock on both PLLs if necessary */ - if (IS_I830(dev) && + if (IS_I830(dev_priv) && intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO) && !intel_num_dvo_pipes(dev)) { I915_WRITE(DPLL(PIPE_B), @@ -5390,7 +5389,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, /* IPS only exists on ULT machines and is tied to pipe A. */ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc) { - return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A; + return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A; } static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, @@ -5862,9 +5861,9 @@ static void intel_update_max_cdclk(struct drm_device *dev) */ if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) dev_priv->max_cdclk_freq = 450000; - else if (IS_BDW_ULX(dev)) + else if (IS_BDW_ULX(dev_priv)) dev_priv->max_cdclk_freq = 450000; - else if (IS_BDW_ULT(dev)) + else if (IS_BDW_ULT(dev_priv)) dev_priv->max_cdclk_freq = 540000; else dev_priv->max_cdclk_freq = 675000; @@ -7223,7 +7222,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay) return -EINVAL; - if (HAS_IPS(dev)) + if (HAS_IPS(dev_priv)) hsw_compute_ips_config(crtc, pipe_config); if (pipe_config->has_pch_encoder) @@ -7361,7 +7360,7 @@ static int haswell_get_display_clock_speed(struct drm_device *dev) return 450000; else if (freq == LCPLL_CLK_FREQ_450) return 450000; - else if (IS_HSW_ULT(dev)) + else if (IS_HSW_ULT(dev_priv)) return 337500; else return 540000; @@ -7531,7 +7530,7 @@ static unsigned int intel_hpll_vco(struct drm_device *dev) uint8_t tmp = 0; /* FIXME other chipsets? */ - if (IS_GM45(dev)) + if (IS_GM45(dev_priv)) vco_table = ctg_vco; else if (IS_G4X(dev)) vco_table = elk_vco; @@ -8150,7 +8149,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, else dpll |= DPLLB_MODE_DAC_SERIAL; - if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { + if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || IS_G33(dev_priv)) { dpll |= (crtc_state->pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; } @@ -8229,7 +8228,8 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc, dpll |= PLL_P2_DIVIDE_BY_4; } - if (!IS_I830(dev) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO)) + if (!IS_I830(dev_priv) && + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO)) dpll |= DPLL_DVO_2X_MODE; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && @@ -8652,7 +8652,8 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(dev); uint32_t tmp; - if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev))) + if (INTEL_GEN(dev_priv) <= 3 && + (IS_I830(dev_priv) || !IS_MOBILE(dev_priv))) return; tmp = I915_READ(PFIT_CONTROL); @@ -8862,7 +8863,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, ((tmp & DPLL_MD_UDI_MULTIPLIER_MASK) >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1; pipe_config->dpll_hw_state.dpll_md = tmp; - } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { + } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || + IS_G33(dev_priv)) { tmp = I915_READ(DPLL(crtc->pipe)); pipe_config->pixel_multiplier = ((tmp & SDVO_MULTIPLIER_MASK) @@ -8880,7 +8882,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, * on 830. Filter it out here so that we don't * report errors due to that. */ - if (IS_I830(dev)) + if (IS_I830(dev_priv)) pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE; pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe)); @@ -10902,13 +10904,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, I915_WRITE(CURPOS(pipe), pos); - if (IS_845G(dev) || IS_I865G(dev)) + if (IS_845G(dev_priv) || IS_I865G(dev_priv)) i845_update_cursor(crtc, base, plane_state); else i9xx_update_cursor(crtc, base, plane_state); } -static bool cursor_size_ok(struct drm_device *dev, +static bool cursor_size_ok(struct drm_i915_private *dev_priv, uint32_t width, uint32_t height) { if (width == 0 || height == 0) @@ -10920,11 +10922,11 @@ static bool cursor_size_ok(struct drm_device *dev, * the precision of the register. Everything else requires * square cursors, limited to a few power-of-two sizes. */ - if (IS_845G(dev) || IS_I865G(dev)) { + if (IS_845G(dev_priv) || IS_I865G(dev_priv)) { if ((width & 63) != 0) return false; - if (width > (IS_845G(dev) ? 64 : 512)) + if (width > (IS_845G(dev_priv) ? 64 : 512)) return false; if (height > 1023) @@ -10933,7 +10935,7 @@ static bool cursor_size_ok(struct drm_device *dev, switch (width | height) { case 256: case 128: - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) return false; case 64: break; @@ -11375,7 +11377,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, else port_clock = i9xx_calc_dpll_params(refclk, &clock); } else { - u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS); + u32 lvds = IS_I830(dev_priv) ? 0 : I915_READ(LVDS); bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN); if (is_lvds) { @@ -14656,6 +14658,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct drm_framebuffer *fb = new_state->fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb); @@ -14707,7 +14710,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, if (plane->type == DRM_PLANE_TYPE_CURSOR && INTEL_INFO(dev)->cursor_needs_physical) { - int align = IS_I830(dev) ? 16 * 1024 : 256; + int align = IS_I830(dev_priv) ? 16 * 1024 : 256; ret = i915_gem_object_attach_phys(obj, align); if (ret) DRM_DEBUG_KMS("failed to attach phys object\n"); @@ -15029,7 +15032,8 @@ intel_check_cursor_plane(struct drm_plane *plane, return 0; /* Check for which cursor types we support */ - if (!cursor_size_ok(plane->dev, state->base.crtc_w, state->base.crtc_h)) { + if (!cursor_size_ok(to_i915(plane->dev), state->base.crtc_w, + state->base.crtc_h)) { DRM_DEBUG("Cursor dimension %dx%d not supported\n", state->base.crtc_w, state->base.crtc_h); return -EINVAL; @@ -15323,7 +15327,7 @@ static bool intel_crt_present(struct drm_device *dev) if (INTEL_INFO(dev)->gen >= 9) return false; - if (IS_HSW_ULT(dev) || IS_BDW_ULT(dev)) + if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) return false; if (IS_CHERRYVIEW(dev)) @@ -16382,8 +16386,8 @@ void intel_modeset_init(struct drm_device *dev) dev->mode_config.max_height = 8192; } - if (IS_845G(dev) || IS_I865G(dev)) { - dev->mode_config.cursor_width = IS_845G(dev) ? 64 : 512; + if (IS_845G(dev_priv) || IS_I865G(dev_priv)) { + dev->mode_config.cursor_width = IS_845G(dev_priv) ? 64 : 512; dev->mode_config.cursor_height = 1023; } else if (IS_GEN2(dev)) { dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d2fd3702e415..0a9f2b90f3af 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5748,7 +5748,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, * 0xd. Failure to do so will result in spurious interrupts being * generated on the port when a cable is not attached. */ - if (IS_G4X(dev) && !IS_GM45(dev)) { + if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) { u32 temp = I915_READ(PEG_BAND_GAP_DATA); I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ad3ff4fe63cf..6607c4e3c36c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1921,7 +1921,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, * 0xd. Failure to do so will result in spurious interrupts being * generated on the port when a cable is not attached. */ - if (IS_G4X(dev) && !IS_GM45(dev)) { + if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) { u32 temp = I915_READ(PEG_BAND_GAP_DATA); I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); } diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 1410330ec9bb..afb2652919d0 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -138,11 +138,10 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) static u32 get_reserved(struct intel_gmbus *bus) { struct drm_i915_private *dev_priv = bus->dev_priv; - struct drm_device *dev = &dev_priv->drm; u32 reserved = 0; /* On most chips, these bits must be preserved in software. */ - if (!IS_I830(dev) && !IS_845G(dev)) + if (!IS_I830(dev_priv) && !IS_845G(dev_priv)) reserved = I915_READ_NOTRACE(bus->gpio_reg) & (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE); @@ -674,7 +673,7 @@ int intel_setup_gmbus(struct drm_device *dev) bus->reg0 = pin | GMBUS_RATE_100KHZ; /* gmbus seems to be broken on i830 */ - if (IS_I830(dev)) + if (IS_I830(dev_priv)) bus->force_bit = 1; intel_gpio_setup(bus, pin); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index baaf2ed897ef..1c47f99917e6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -949,10 +949,8 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; } -static bool intel_lvds_supported(struct drm_device *dev) +static bool intel_lvds_supported(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - /* With the introduction of the PCH we gained a dedicated * LVDS presence pin, use it. */ if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) @@ -960,7 +958,8 @@ static bool intel_lvds_supported(struct drm_device *dev) /* Otherwise LVDS was only attached to mobile products, * except for the inglorious 830gm */ - if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev)) + if (INTEL_GEN(dev_priv) <= 4 && + IS_MOBILE(dev_priv) && !IS_I830(dev_priv)) return true; return false; @@ -992,7 +991,7 @@ void intel_lvds_init(struct drm_device *dev) int pipe; u8 pin; - if (!intel_lvds_supported(dev)) + if (!intel_lvds_supported(dev_priv)) return; /* Skip init on machines we know falsely report LVDS */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 73be4792bbd4..15af477d0974 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -334,12 +334,12 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0; I915_WRITE(DSPFW3, val); POSTING_READ(DSPFW3); - } else if (IS_I945G(dev) || IS_I945GM(dev)) { + } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) { val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) : _MASKED_BIT_DISABLE(FW_BLC_SELF_EN); I915_WRITE(FW_BLC_SELF, val); POSTING_READ(FW_BLC_SELF); - } else if (IS_I915GM(dev)) { + } else if (IS_I915GM(dev_priv)) { /* * FIXME can't find a bit like this for 915G, and * and yet it does have the related watermark in @@ -648,8 +648,10 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) u32 reg; unsigned long wm; - latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, - dev_priv->fsb_freq, dev_priv->mem_freq); + latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv), + dev_priv->is_ddr3, + dev_priv->fsb_freq, + dev_priv->mem_freq); if (!latency) { DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); intel_set_memory_cxsr(dev_priv, false); @@ -1579,7 +1581,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); - if (IS_I915GM(dev) && enabled) { + if (IS_I915GM(dev_priv) && enabled) { struct drm_i915_gem_object *obj; obj = intel_fb_obj(enabled->primary->state->fb); @@ -1609,7 +1611,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) unsigned long line_time_us; int entries; - if (IS_I915GM(dev) || IS_I945GM(dev)) + if (IS_I915GM(dev_priv) || IS_I945GM(dev_priv)) cpp = 4; line_time_us = max(htotal * 1000 / clock, 1); @@ -1623,7 +1625,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) if (srwm < 0) srwm = 1; - if (IS_I945G(dev) || IS_I945GM(dev)) + if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff)); else @@ -6943,7 +6945,7 @@ static void ironlake_init_clock_gating(struct drm_device *dev) * The bit 22 of 0x42004 * The bit 7,8,9 of 0x42020. */ - if (IS_IRONLAKE_M(dev)) { + if (IS_IRONLAKE_M(dev_priv)) { /* WaFbcAsynchFlipDisableFbcQueue:ilk */ I915_WRITE(ILK_DISPLAY_CHICKEN1, I915_READ(ILK_DISPLAY_CHICKEN1) | @@ -7353,7 +7355,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) CHICKEN3_DGMG_DONE_FIX_DISABLE); /* WaDisablePSDDualDispatchEnable:ivb */ - if (IS_IVB_GT1(dev)) + if (IS_IVB_GT1(dev_priv)) I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); @@ -7369,7 +7371,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) GEN7_WA_FOR_GEN7_L3_CONTROL); I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE); - if (IS_IVB_GT1(dev)) + if (IS_IVB_GT1(dev_priv)) I915_WRITE(GEN7_ROW_CHICKEN2, _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); else { @@ -7563,7 +7565,7 @@ static void g4x_init_clock_gating(struct drm_device *dev) dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | OVRUNIT_CLOCK_GATE_DISABLE | OVCUNIT_CLOCK_GATE_DISABLE; - if (IS_GM45(dev)) + if (IS_GM45(dev_priv)) dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; I915_WRITE(DSPCLK_GATE_D, dspclk_gate); @@ -7770,7 +7772,7 @@ void intel_init_pm(struct drm_device *dev) vlv_setup_wm_latency(dev); dev_priv->display.update_wm = vlv_update_wm; } else if (IS_PINEVIEW(dev)) { - if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), + if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv), dev_priv->is_ddr3, dev_priv->fsb_freq, dev_priv->mem_freq)) { diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f5ee2ae0fa12..49fb95d03d74 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1296,7 +1296,8 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, if (INTEL_INFO(dev)->gen >= 4) { /* done in crtc_mode_set as the dpll_md reg must be written early */ - } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { + } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || + IS_G33(dev_priv)) { /* done in crtc_mode_set as it lives inside the dpll register */ } else { sdvox |= (crtc_state->pixel_multiplier - 1) @@ -1389,7 +1390,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, * encoder->get_config we so already have a valid pixel multplier on all * other platfroms. */ - if (IS_I915G(dev) || IS_I915GM(dev)) { + if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { pipe_config->pixel_multiplier = ((sdvox & SDVO_PORT_MULTIPLY_MASK) >> SDVO_PORT_MULTIPLY_SHIFT) + 1; @@ -1595,15 +1596,15 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo) { - struct drm_device *dev = intel_sdvo->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev); uint16_t hotplug; - if (!I915_HAS_HOTPLUG(dev)) + if (!I915_HAS_HOTPLUG(dev_priv)) return 0; /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise * on the line. */ - if (IS_I945G(dev) || IS_I945GM(dev)) + if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) return 0; if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index a0301a5dc249..7118fb55f57f 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1105,7 +1105,7 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder, tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT; /* Enable two fixes for the chips that need them. */ - if (IS_I915GM(dev)) + if (IS_I915GM(dev_priv)) tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX; set_tv_mode_timings(dev_priv, tv_mode, burst_ena); @@ -1230,7 +1230,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv, * The TV sense state should be cleared to zero on cantiga platform. Otherwise * the TV is misdetected. This is hardware requirement. */ - if (IS_GM45(dev)) + if (IS_GM45(dev_priv)) tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL); -- cgit v1.2.3 From fd6b8f43c9e9a3adc384423a1d3dfeefd38655ea Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 14 Oct 2016 10:13:06 +0100 Subject: drm/i915: Make IS_IVYBRIDGE only take dev_priv Saves 848 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) v3: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.c | 19 +++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ drivers/gpu/drm/i915/intel_pm.c | 13 +++++++------ drivers/gpu/drm/i915/intel_sprite.c | 2 +- 7 files changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index bb14e9521c5e..b1142aaf50ec 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -114,7 +114,7 @@ static bool i915_error_injected(struct drm_i915_private *dev_priv) fmt, ##__VA_ARGS__) -static enum intel_pch intel_virt_detect_pch(struct drm_device *dev) +static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) { enum intel_pch ret = PCH_NOP; @@ -125,16 +125,16 @@ static enum intel_pch intel_virt_detect_pch(struct drm_device *dev) * make an educated guess as to which PCH is really there. */ - if (IS_GEN5(dev)) { + if (IS_GEN5(dev_priv)) { ret = PCH_IBX; DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n"); - } else if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { + } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) { ret = PCH_CPT; DRM_DEBUG_KMS("Assuming CouarPoint PCH\n"); - } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { ret = PCH_LPT; DRM_DEBUG_KMS("Assuming LynxPoint PCH\n"); - } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { ret = PCH_SPT; DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n"); } @@ -178,12 +178,14 @@ static void intel_detect_pch(struct drm_device *dev) } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found CougarPoint PCH\n"); - WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev))); + WARN_ON(!(IS_GEN6(dev_priv) || + IS_IVYBRIDGE(dev_priv))); } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { /* PantherPoint is CPT compatible */ dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found PantherPoint PCH\n"); - WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev))); + WARN_ON(!(IS_GEN6(dev_priv) || + IS_IVYBRIDGE(dev_priv))); } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint PCH\n"); @@ -217,7 +219,8 @@ static void intel_detect_pch(struct drm_device *dev) PCI_SUBVENDOR_ID_REDHAT_QUMRANET && pch->subsystem_device == PCI_SUBDEVICE_ID_QEMU)) { - dev_priv->pch_type = intel_virt_detect_pch(dev); + dev_priv->pch_type = + intel_virt_detect_pch(dev_priv); } else continue; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c05d5c8b6449..7aa1b8d6b399 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2651,7 +2651,7 @@ struct drm_i915_cmd_table { #define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) #define IS_G33(dev) (INTEL_INFO(dev)->is_g33) #define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046) -#define IS_IVYBRIDGE(dev) (INTEL_INFO(dev)->is_ivybridge) +#define IS_IVYBRIDGE(dev_priv) ((dev_priv)->info.is_ivybridge) #define IS_IVB_GT1(dev_priv) (INTEL_DEVID(dev_priv) == 0x0156 || \ INTEL_DEVID(dev_priv) == 0x0152 || \ INTEL_DEVID(dev_priv) == 0x015a) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ed24907ed471..aed4d28ab71e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4432,7 +4432,7 @@ i915_gem_init_hw(struct drm_device *dev) LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); if (HAS_PCH_NOP(dev_priv)) { - if (IS_IVYBRIDGE(dev)) { + if (IS_IVYBRIDGE(dev_priv)) { u32 temp = I915_READ(GEN7_MSG_CTL); temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK); I915_WRITE(GEN7_MSG_CTL, temp); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 481ec43f8180..5dca32ac1c67 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -192,7 +192,7 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) * This is only applicable for Ivy Bridge devices since * later platforms don't have L3 control bits in the PTE. */ - if (IS_IVYBRIDGE(dev)) { + if (IS_IVYBRIDGE(to_i915(dev))) { ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC); /* Failure shouldn't ever happen this early */ if (WARN_ON(ret)) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b60a37f7dca1..95ab2c075ce2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3727,7 +3727,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) /* enable normal train */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); - if (IS_IVYBRIDGE(dev)) { + if (IS_IVYBRIDGE(dev_priv)) { temp &= ~FDI_LINK_TRAIN_NONE_IVB; temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; } else { @@ -3752,7 +3752,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) udelay(1000); /* IVB wants error correction enabled */ - if (IS_IVYBRIDGE(dev)) + if (IS_IVYBRIDGE(dev_priv)) I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE); } @@ -4538,7 +4538,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) assert_pch_transcoder_disabled(dev_priv, pipe); - if (IS_IVYBRIDGE(dev)) + if (IS_IVYBRIDGE(dev_priv)) ivybridge_update_fdi_bc_bifurcation(intel_crtc); /* Write the TU size bits before fdi link training, so that error @@ -4852,7 +4852,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc) * as some pre-programmed values are broken, * e.g. x201. */ - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) + if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | PF_PIPE_SEL_IVB(pipe)); else @@ -12249,7 +12249,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (fb->modifier[0] != old_fb->modifier[0]) /* vlv: DISPLAY_FLIP fails to change tiling */ engine = NULL; - } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { + } else if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) { engine = dev_priv->engine[BCS]; } else if (INTEL_INFO(dev)->gen >= 7) { engine = i915_gem_active_get_engine(&obj->last_write, @@ -12525,7 +12525,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, * cstate->update_wm was already set above, so this flag will * take effect when we commit and program watermarks. */ - if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev) && + if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) && needs_scaling(to_intel_plane_state(plane_state)) && !needs_scaling(old_plane_state)) pipe_config->disable_lp_wm = true; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 15af477d0974..0b3ab7254f0a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2191,14 +2191,15 @@ static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5]) wm[0] = 13; } -static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5]) +static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv, + uint16_t wm[5]) { /* ILK cursor LP0 latency is 1300 ns */ - if (IS_GEN5(dev)) + if (IS_GEN5(dev_priv)) wm[0] = 13; /* WaDoubleCursorLP3Latency:ivb */ - if (IS_IVYBRIDGE(dev)) + if (IS_IVYBRIDGE(dev_priv)) wm[3] *= 2; } @@ -2294,7 +2295,7 @@ static void ilk_setup_wm_latency(struct drm_device *dev) sizeof(dev_priv->wm.pri_latency)); intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency); - intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency); + intel_fixup_cur_wm_latency(dev_priv, dev_priv->wm.cur_latency); intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency); intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency); @@ -2522,7 +2523,7 @@ static void ilk_wm_merge(struct drm_device *dev, int last_enabled_level = max_level; /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */ - if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) && + if ((INTEL_GEN(dev_priv) <= 6 || IS_IVYBRIDGE(dev_priv)) && config->num_pipes_active > 1) last_enabled_level = 0; @@ -4625,7 +4626,7 @@ void ilk_wm_get_hw_state(struct drm_device *dev) if (IS_HASWELL(dev) || IS_BROADWELL(dev)) hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; - else if (IS_IVYBRIDGE(dev)) + else if (IS_IVYBRIDGE(dev_priv)) hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ? INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 73a521fdf1bd..d0f798ce6bb2 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1084,7 +1084,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) case 7: case 8: - if (IS_IVYBRIDGE(dev)) { + if (IS_IVYBRIDGE(to_i915(dev))) { intel_plane->can_scale = true; intel_plane->max_downscale = 2; } else { -- cgit v1.2.3 From 8652744b647e267f7a6902263c424a7dc29d6648 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:00 +0100 Subject: drm/i915: Make IS_BROADWELL only take dev_priv Saves 1808 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.c | 6 ++++-- drivers/gpu/drm/i915/i915_drv.h | 6 +++--- drivers/gpu/drm/i915/i915_gem.c | 5 +++-- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/intel_color.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 21 +++++++++++---------- drivers/gpu/drm/i915/intel_dp.c | 19 ++++++++++--------- drivers/gpu/drm/i915/intel_pm.c | 20 +++++++++++--------- drivers/gpu/drm/i915/intel_psr.c | 4 ++-- drivers/gpu/drm/i915/intel_runtime_pm.c | 3 +-- drivers/gpu/drm/i915/intel_sprite.c | 8 ++++---- 11 files changed, 52 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b1142aaf50ec..ef7bed81c6a0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -189,13 +189,15 @@ static void intel_detect_pch(struct drm_device *dev) } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint PCH\n"); - WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); + WARN_ON(!IS_HASWELL(dev_priv) && + !IS_BROADWELL(dev_priv)); WARN_ON(IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); - WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); + WARN_ON(!IS_HASWELL(dev_priv) && + !IS_BROADWELL(dev_priv)); WARN_ON(!IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7aa1b8d6b399..705b931c9249 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2658,7 +2658,7 @@ struct drm_i915_cmd_table { #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) #define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview) #define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) -#define IS_BROADWELL(dev) (INTEL_INFO(dev)->is_broadwell) +#define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell) #define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake) #define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton) #define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake) @@ -2765,8 +2765,8 @@ struct drm_i915_cmd_table { #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) #define HAS_SNOOP(dev) (INTEL_INFO(dev)->has_snoop) #define HAS_EDRAM(dev) (!!(__I915__(dev)->edram_cap & EDRAM_ENABLED)) -#define HAS_WT(dev) ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \ - HAS_EDRAM(dev)) +#define HAS_WT(dev_priv) ((IS_HASWELL(dev_priv) || \ + IS_BROADWELL(dev_priv)) && HAS_EDRAM(dev_priv)) #define HWS_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->hws_needs_physical) #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->has_hw_contexts) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index aed4d28ab71e..3ad827448b4b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3480,7 +3480,7 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, level = I915_CACHE_LLC; break; case I915_CACHING_DISPLAY: - level = HAS_WT(dev) ? I915_CACHE_WT : I915_CACHE_NONE; + level = HAS_WT(dev_priv) ? I915_CACHE_WT : I915_CACHE_NONE; break; default: return -EINVAL; @@ -3538,7 +3538,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, * with that bit in the PTE to main memory with just one PIPE_CONTROL. */ ret = i915_gem_object_set_cache_level(obj, - HAS_WT(obj->base.dev) ? I915_CACHE_WT : I915_CACHE_NONE); + HAS_WT(to_i915(obj->base.dev)) ? + I915_CACHE_WT : I915_CACHE_NONE); if (ret) { vma = ERR_PTR(ret); goto err_unpin_display; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0a45063b465f..463bf732f16f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2131,7 +2131,7 @@ static void gtt_write_workarounds(struct drm_device *dev) * workarounds here even if they get overwritten by GPU reset. */ /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */ - if (IS_BROADWELL(dev)) + if (IS_BROADWELL(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); else if (IS_CHERRYVIEW(dev)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index 5362c07932d3..be76ef88678c 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -540,8 +540,8 @@ void intel_color_init(struct drm_crtc *crtc) } else if (IS_HASWELL(dev)) { dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; dev_priv->display.load_luts = haswell_load_luts; - } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) || - IS_BROXTON(dev) || IS_KABYLAKE(dev)) { + } else if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv) || + IS_BROXTON(dev_priv) || IS_KABYLAKE(dev_priv)) { dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; dev_priv->display.load_luts = broadwell_load_luts; } else { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 95ab2c075ce2..6fa3a9ddd84c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3139,7 +3139,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, dspcntr = DISPPLANE_GAMMA_ENABLE; dspcntr |= DISPLAY_PLANE_ENABLE; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; switch (fb->pixel_format) { @@ -3168,7 +3168,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) dspcntr |= DISPPLANE_TILED; - if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) + if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; intel_add_fb_offsets(&x, &y, plane_state, 0); @@ -3179,7 +3179,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, if (rotation == DRM_ROTATE_180) { dspcntr |= DISPPLANE_ROTATE_180; - if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { + if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { x += (crtc_state->pipe_src_w - 1); y += (crtc_state->pipe_src_h - 1); } @@ -3196,7 +3196,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, I915_WRITE(DSPSURF(plane), intel_fb_gtt_offset(fb, rotation) + intel_crtc->dspaddr_offset); - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { I915_WRITE(DSPOFFSET(plane), (y << 16) | x); } else { I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); @@ -4877,7 +4877,7 @@ void hsw_enable_ips(struct intel_crtc *crtc) */ assert_plane_enabled(dev_priv, crtc->plane); - if (IS_BROADWELL(dev)) { + if (IS_BROADWELL(dev_priv)) { mutex_lock(&dev_priv->rps.hw_lock); WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000)); mutex_unlock(&dev_priv->rps.hw_lock); @@ -4909,7 +4909,7 @@ void hsw_disable_ips(struct intel_crtc *crtc) return; assert_plane_enabled(dev_priv, crtc->plane); - if (IS_BROADWELL(dev)) { + if (IS_BROADWELL(dev_priv)) { mutex_lock(&dev_priv->rps.hw_lock); WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); mutex_unlock(&dev_priv->rps.hw_lock); @@ -5852,7 +5852,7 @@ static void intel_update_max_cdclk(struct drm_device *dev) dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco); } else if (IS_BROXTON(dev)) { dev_priv->max_cdclk_freq = 624000; - } else if (IS_BROADWELL(dev)) { + } else if (IS_BROADWELL(dev_priv)) { /* * FIXME with extra cooling we can allow * 540 MHz for ULX and 675 Mhz for ULT. @@ -7021,6 +7021,7 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state) static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, struct intel_crtc_state *pipe_config) { + struct drm_i915_private *dev_priv = to_i915(dev); struct drm_atomic_state *state = pipe_config->base.state; struct intel_crtc *other_crtc; struct intel_crtc_state *other_crtc_state; @@ -7033,7 +7034,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, return -EINVAL; } - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { if (pipe_config->fdi_lanes > 2) { DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n", pipe_config->fdi_lanes); @@ -9881,7 +9882,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; base = I915_READ(DSPSURF(pipe)) & 0xfffff000; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { offset = I915_READ(DSPOFFSET(pipe)); } else { if (plane_config->tiling) @@ -17244,7 +17245,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, return; err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes); - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) err_printf(m, "PWR_WELL_CTL2: %08x\n", error->power_well_driver); for_each_pipe(dev_priv, i) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0a9f2b90f3af..d62f318bf758 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -821,15 +821,16 @@ static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp, uint32_t aux_clock_divider) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = + to_i915(intel_dig_port->base.base.dev); uint32_t precharge, timeout; - if (IS_GEN6(dev)) + if (IS_GEN6(dev_priv)) precharge = 3; else precharge = 5; - if (IS_BROADWELL(dev) && intel_dig_port->port == PORT_A) + if (IS_BROADWELL(dev_priv) && intel_dig_port->port == PORT_A) timeout = DP_AUX_CH_CTL_TIME_OUT_600us; else timeout = DP_AUX_CH_CTL_TIME_OUT_400us; @@ -2999,10 +3000,10 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) uint8_t intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) { - struct drm_device *dev = intel_dp_to_dev(intel_dp); + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); enum port port = dp_to_dig_port(intel_dp)->port; - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: return DP_TRAIN_PRE_EMPH_LEVEL_3; @@ -3015,7 +3016,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) default: return DP_TRAIN_PRE_EMPH_LEVEL_0; } - } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: return DP_TRAIN_PRE_EMPH_LEVEL_3; @@ -3027,7 +3028,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) default: return DP_TRAIN_PRE_EMPH_LEVEL_0; } - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: return DP_TRAIN_PRE_EMPH_LEVEL_3; @@ -3039,7 +3040,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) default: return DP_TRAIN_PRE_EMPH_LEVEL_0; } - } else if (IS_GEN7(dev) && port == PORT_A) { + } else if (IS_GEN7(dev_priv) && port == PORT_A) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: return DP_TRAIN_PRE_EMPH_LEVEL_2; @@ -5648,7 +5649,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, /* intel_dp vfuncs */ if (INTEL_INFO(dev)->gen >= 9) intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider; - else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider; else if (HAS_PCH_SPLIT(dev_priv)) intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0b3ab7254f0a..78b781adef93 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2157,7 +2157,7 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) } } - } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { uint64_t sskpd = I915_READ64(MCH_SSKPD); wm[0] = (sskpd >> 56) & 0xFF; @@ -2205,12 +2205,14 @@ static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv, int ilk_wm_max_level(const struct drm_device *dev) { + struct drm_i915_private *dev_priv = to_i915(dev); + /* how many WM levels are we expecting */ - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return 7; - else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) return 4; - else if (INTEL_INFO(dev)->gen >= 6) + else if (INTEL_GEN(dev_priv) >= 6) return 3; else return 2; @@ -2393,7 +2395,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm)); pipe_wm->wm[0] = pipe_wm->raw_wm[0]; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) pipe_wm->linetime = hsw_compute_linetime_wm(cstate); if (!ilk_validate_pipe_wm(dev, pipe_wm)) @@ -2580,7 +2582,7 @@ static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level) { struct drm_i915_private *dev_priv = to_i915(dev); - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) return 2 * level; else return dev_priv->wm.pri_latency[level]; @@ -2804,7 +2806,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]); if (dirty & WM_DIRTY_DDB) { - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { val = I915_READ(WM_MISC); if (results->partitioning == INTEL_DDB_PART_1_2) val &= ~WM_MISC_DATA_PARTITION_5_6; @@ -4415,7 +4417,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) }; hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]); - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); memset(active, 0, sizeof(*active)); @@ -4623,7 +4625,7 @@ void ilk_wm_get_hw_state(struct drm_device *dev) hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB); } - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; else if (IS_IVYBRIDGE(dev_priv)) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 9e2fbac9776e..d0667f9d9178 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -827,14 +827,14 @@ void intel_psr_init(struct drm_device *dev) /* Per platform default */ if (i915.enable_psr == -1) { - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) i915.enable_psr = 1; else i915.enable_psr = 0; } /* Set link_standby x link_off defaults */ - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) /* HSW and BDW require workarounds that we don't implement. */ dev_priv->psr.link_standby = false; else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index ed1faf14f777..77ef03cb6163 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -288,7 +288,6 @@ void intel_display_set_init_power(struct drm_i915_private *dev_priv, static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = dev_priv->drm.pdev; - struct drm_device *dev = &dev_priv->drm; /* * After we re-enable the power well, if we touch VGA register 0x3d5 @@ -304,7 +303,7 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); vga_put(pdev, VGA_RSRC_LEGACY_IO); - if (IS_BROADWELL(dev)) + if (IS_BROADWELL(dev_priv)) gen8_irq_power_well_post_enable(dev_priv, 1 << PIPE_C | 1 << PIPE_B); } diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index d0f798ce6bb2..fefd3034aead 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -542,12 +542,12 @@ ivb_update_plane(struct drm_plane *plane, if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) sprctl |= SPRITE_TILED; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; else sprctl |= SPRITE_TRICKLE_FEED_DISABLE; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) sprctl |= SPRITE_PIPE_CSC_ENABLE; /* Sizes are 0 based */ @@ -566,7 +566,7 @@ ivb_update_plane(struct drm_plane *plane, sprctl |= SPRITE_ROTATE_180; /* HSW and BDW does this automagically in hardware */ - if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { + if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { x += src_w; y += src_h; } @@ -590,7 +590,7 @@ ivb_update_plane(struct drm_plane *plane, /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET * register */ - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) I915_WRITE(SPROFFSET(pipe), (y << 16) | x); else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); -- cgit v1.2.3 From 772c2a519cec26546b070aed71fc1ff0c5f31459 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:01 +0100 Subject: drm/i915: Make IS_HASWELL only take dev_priv Saves 2432 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 ++-- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- drivers/gpu/drm/i915/intel_color.c | 4 ++-- drivers/gpu/drm/i915/intel_ddi.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 23 ++++++++++------------- drivers/gpu/drm/i915/intel_psr.c | 6 +++--- 9 files changed, 24 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 705b931c9249..6fa237739fdc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2657,7 +2657,7 @@ struct drm_i915_cmd_table { INTEL_DEVID(dev_priv) == 0x015a) #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) #define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview) -#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) +#define IS_HASWELL(dev_priv) ((dev_priv)->info.is_haswell) #define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell) #define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake) #define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3ad827448b4b..16c93cecdab5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4428,7 +4428,7 @@ i915_gem_init_hw(struct drm_device *dev) if (HAS_EDRAM(dev) && INTEL_GEN(dev_priv) < 9) I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf)); - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev_priv)) I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev_priv) ? LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 463bf732f16f..179f16b19515 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1748,7 +1748,7 @@ static void gen7_ppgtt_enable(struct drm_device *dev) I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); ecochk = I915_READ(GAM_ECOCHK); - if (IS_HASWELL(dev)) { + if (IS_HASWELL(dev_priv)) { ecochk |= ECOCHK_PPGTT_WB_HSW; } else { ecochk |= ECOCHK_PPGTT_LLC_IVB; @@ -2060,7 +2060,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.pte_encode = ggtt->base.pte_encode; if (intel_vgpu_active(dev_priv) || IS_GEN6(dev)) ppgtt->switch_mm = gen6_mm_switch; - else if (IS_HASWELL(dev)) + else if (IS_HASWELL(dev_priv)) ppgtt->switch_mm = hsw_mm_switch; else if (IS_GEN7(dev)) ppgtt->switch_mm = gen7_mm_switch; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c2a960eb0290..4eae1beb0d4f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3591,8 +3591,8 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) dev_priv->gt_irq_mask = ~0; if (HAS_L3_DPF(dev)) { /* L3 parity interrupt is always unmasked. */ - dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev); - gt_irqs |= GT_PARITY_ERROR(dev); + dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev_priv); + gt_irqs |= GT_PARITY_ERROR(dev_priv); } gt_irqs |= GT_RENDER_USER_INTERRUPT; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5f7aecbba549..00efaa13974d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2093,9 +2093,9 @@ enum skl_disp_power_wells { #define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */ #define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */ -#define GT_PARITY_ERROR(dev) \ +#define GT_PARITY_ERROR(dev_priv) \ (GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \ - (IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0)) + (IS_HASWELL(dev_priv) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0)) /* These are all the "old" interrupts */ #define ILK_BSD_USER_INTERRUPT (1<<5) diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index be76ef88678c..da76a799411a 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -326,7 +326,7 @@ static void haswell_load_luts(struct drm_crtc_state *crtc_state) * Workaround : Do not read or write the pipe palette/gamma data while * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. */ - if (IS_HASWELL(dev) && intel_crtc_state->ips_enabled && + if (IS_HASWELL(dev_priv) && intel_crtc_state->ips_enabled && (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) { hsw_disable_ips(intel_crtc); reenable_ips = true; @@ -537,7 +537,7 @@ void intel_color_init(struct drm_crtc *crtc) if (IS_CHERRYVIEW(dev)) { dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix; dev_priv->display.load_luts = cherryview_load_luts; - } else if (IS_HASWELL(dev)) { + } else if (IS_HASWELL(dev_priv)) { dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; dev_priv->display.load_luts = haswell_load_luts; } else if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv) || diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 35f0b7c9d0a6..cd7128b89b4d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1189,7 +1189,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) * eDP when not using the panel fitter, and when not * using motion blur mitigation (which we don't * support). */ - if (IS_HASWELL(dev) && + if (IS_HASWELL(dev_priv) && (intel_crtc->config->pch_pfit.enabled || intel_crtc->config->pch_pfit.force_thru)) temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6fa3a9ddd84c..e057b5480b49 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5501,7 +5501,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, /* If we change the relative order between pipe/planes enabling, we need * to change the workaround. */ hsw_workaround_pipe = pipe_config->hsw_workaround_pipe; - if (IS_HASWELL(dev) && hsw_workaround_pipe != INVALID_PIPE) { + if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) { intel_wait_for_vblank(dev, hsw_workaround_pipe); intel_wait_for_vblank(dev, hsw_workaround_pipe); } @@ -8299,7 +8299,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) * programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is * documented on the DDI_FUNC_CTL register description, EDP Input Select * bits. */ - if (IS_HASWELL(dev) && cpu_transcoder == TRANSCODER_EDP && + if (IS_HASWELL(dev_priv) && cpu_transcoder == TRANSCODER_EDP && (pipe == PIPE_B || pipe == PIPE_C)) I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder))); @@ -10026,7 +10026,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n"); I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, "CPU PWM1 enabled\n"); - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev_priv)) I915_STATE_WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE, "CPU PWM2 enabled\n"); I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE, @@ -10046,9 +10046,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; - - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev_priv)) return I915_READ(D_COMP_HSW); else return I915_READ(D_COMP_BDW); @@ -10056,9 +10054,7 @@ static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv) static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val) { - struct drm_device *dev = &dev_priv->drm; - - if (IS_HASWELL(dev)) { + if (IS_HASWELL(dev_priv)) { mutex_lock(&dev_priv->rps.hw_lock); if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val)) @@ -10735,7 +10731,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, ironlake_get_pfit_config(crtc, pipe_config); } - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev_priv)) pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && (I915_READ(IPS_CTL) & IPS_ENABLE); @@ -13195,6 +13191,7 @@ intel_pipe_config_compare(struct drm_device *dev, struct intel_crtc_state *pipe_config, bool adjust) { + struct drm_i915_private *dev_priv = to_i915(dev); bool ret = true; #define INTEL_ERR_OR_DBG_KMS(fmt, ...) \ @@ -13340,7 +13337,7 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(pixel_multiplier); PIPE_CONF_CHECK_I(has_hdmi_sink); - if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) || + if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) PIPE_CONF_CHECK_I(limited_color_range); PIPE_CONF_CHECK_I(has_infoframe); @@ -13381,7 +13378,7 @@ intel_pipe_config_compare(struct drm_device *dev, } /* BDW+ don't expose a synchronous way to read the state */ - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev_priv)) PIPE_CONF_CHECK_I(ips_enabled); PIPE_CONF_CHECK_I(double_wide); @@ -17262,7 +17259,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, err_printf(m, " SIZE: %08x\n", error->plane[i].size); err_printf(m, " POS: %08x\n", error->plane[i].pos); } - if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) + if (INTEL_GEN(dev_priv) <= 7 && !IS_HASWELL(dev_priv)) err_printf(m, " ADDR: %08x\n", error->plane[i].addr); if (INTEL_INFO(dev)->gen >= 4) { err_printf(m, " SURF: %08x\n", error->plane[i].surface); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index d0667f9d9178..4a973b34348a 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -268,7 +268,7 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT; val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev_priv)) val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; if (dev_priv->psr.link_standby) @@ -360,14 +360,14 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) return false; } - if (IS_HASWELL(dev) && + if (IS_HASWELL(dev_priv) && I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) & S3D_ENABLE) { DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n"); return false; } - if (IS_HASWELL(dev) && + if (IS_HASWELL(dev_priv) && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); return false; -- cgit v1.2.3 From 0853723b8956acc9690ace7ab6ea1f50bb997b52 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:02 +0100 Subject: drm/i915: Make IS_KABYLAKE only take dev_priv Saves 1320 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.c | 10 +++++----- drivers/gpu/drm/i915/i915_drv.h | 6 +++--- drivers/gpu/drm/i915/i915_gem_stolen.c | 2 +- drivers/gpu/drm/i915/intel_ddi.c | 16 ++++++++-------- drivers/gpu/drm/i915/intel_display.c | 10 +++++----- drivers/gpu/drm/i915/intel_dpll_mgr.c | 2 +- drivers/gpu/drm/i915/intel_guc_loader.c | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 2 +- 8 files changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ef7bed81c6a0..5dd56d9ea905 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -203,17 +203,17 @@ static void intel_detect_pch(struct drm_device *dev) } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); - WARN_ON(!IS_SKYLAKE(dev) && - !IS_KABYLAKE(dev)); + WARN_ON(!IS_SKYLAKE(dev_priv) && + !IS_KABYLAKE(dev_priv)); } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); - WARN_ON(!IS_SKYLAKE(dev) && - !IS_KABYLAKE(dev)); + WARN_ON(!IS_SKYLAKE(dev_priv) && + !IS_KABYLAKE(dev_priv)); } else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_KBP; DRM_DEBUG_KMS("Found KabyPoint PCH\n"); - WARN_ON(!IS_KABYLAKE(dev)); + WARN_ON(!IS_KABYLAKE(dev_priv)); } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) || ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6fa237739fdc..40b86dcb781b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2661,7 +2661,7 @@ struct drm_i915_cmd_table { #define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell) #define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake) #define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton) -#define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake) +#define IS_KABYLAKE(dev_priv) ((dev_priv)->info.is_kabylake) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00) @@ -2728,8 +2728,8 @@ struct drm_i915_cmd_table { #define KBL_REVID_D0 0x3 #define KBL_REVID_E0 0x4 -#define IS_KBL_REVID(p, since, until) \ - (IS_KABYLAKE(p) && IS_REVID(p, since, until)) +#define IS_KBL_REVID(dev_priv, since, until) \ + (IS_KABYLAKE(dev_priv) && IS_REVID(dev_priv, since, until)) /* * The genX designation typically refers to the render engine, so render diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index cbea6fb83ce5..3508120b8c90 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -456,7 +456,7 @@ int i915_gem_init_stolen(struct drm_device *dev) break; default: if (IS_BROADWELL(dev_priv) || - IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev)) + IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) bdw_get_stolen_reserved(dev_priv, &reserved_base, &reserved_size); else diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cd7128b89b4d..07164e250adf 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1020,13 +1020,13 @@ static void bxt_ddi_clock_get(struct intel_encoder *encoder, void intel_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (INTEL_INFO(dev)->gen <= 8) + if (INTEL_GEN(dev_priv) <= 8) hsw_ddi_clock_get(encoder, pipe_config); - else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) skl_ddi_clock_get(encoder, pipe_config); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) bxt_ddi_clock_get(encoder, pipe_config); } @@ -1081,14 +1081,14 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, bool intel_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state) { - struct drm_device *dev = intel_crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); struct intel_encoder *intel_encoder = intel_ddi_get_crtc_new_encoder(crtc_state); - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) return skl_ddi_pll_select(intel_crtc, crtc_state, intel_encoder); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) return bxt_ddi_pll_select(intel_crtc, crtc_state, intel_encoder); else @@ -1742,7 +1742,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, intel_edp_panel_off(intel_dp); } - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) | DPLL_CTRL2_DDI_CLK_OFF(port))); else if (INTEL_INFO(dev)->gen < 9) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e057b5480b49..1a2b3be4d882 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5828,7 +5828,7 @@ static void intel_update_max_cdclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; int max_cdclk, vco; @@ -10646,7 +10646,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) skylake_get_ddi_pll(dev_priv, port, pipe_config); else if (IS_BROXTON(dev)) bxt_get_ddi_pll(dev_priv, port, pipe_config); @@ -12821,7 +12821,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->dpll_hw_state.pll9, pipe_config->dpll_hw_state.pll10, pipe_config->dpll_hw_state.pcsdw12); - } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { DRM_DEBUG_KMS("dpll_hw_state: " "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n", pipe_config->dpll_hw_state.ctrl1, @@ -15420,7 +15420,7 @@ static void intel_setup_outputs(struct drm_device *dev) */ found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED; /* WaIgnoreDDIAStrap: skl */ - if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + if (found || IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) intel_ddi_init(dev, PORT_A); /* DDI B, C and D detection is indicated by the SFUSE_STRAP @@ -15436,7 +15436,7 @@ static void intel_setup_outputs(struct drm_device *dev) /* * On SKL we don't have a way to detect DDI-E so we rely on VBT. */ - if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && + if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp || dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi || dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi)) diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index c37ce1263142..7cf9d91c0746 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1851,7 +1851,7 @@ void intel_shared_dpll_init(struct drm_device *dev) const struct dpll_info *dpll_info; int i; - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) dpll_mgr = &skl_pll_mgr; else if (IS_BROXTON(dev)) dpll_mgr = &bxt_pll_mgr; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 95c6751d598d..8eb49685dfdd 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -736,7 +736,7 @@ void intel_guc_init(struct drm_device *dev) fw_path = I915_BXT_GUC_UCODE; guc_fw->guc_fw_major_wanted = BXT_FW_MAJOR; guc_fw->guc_fw_minor_wanted = BXT_FW_MINOR; - } else if (IS_KABYLAKE(dev)) { + } else if (IS_KABYLAKE(dev_priv)) { fw_path = I915_KBL_GUC_UCODE; guc_fw->guc_fw_major_wanted = KBL_FW_MAJOR; guc_fw->guc_fw_minor_wanted = KBL_FW_MINOR; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 77ef03cb6163..025fbd522819 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2594,7 +2594,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) power_domains->initializing = true; - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { skl_display_core_init(dev_priv, resume); } else if (IS_BROXTON(dev)) { bxt_display_core_init(dev_priv, resume); -- cgit v1.2.3 From d9486e65010fedbdbf8337e0d890213620e782f4 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:03 +0100 Subject: drm/i915: Make IS_SKYLAKE only take dev_priv Saves 1016 bytes of .rodata strings and couple hundred of .text. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/intel_guc_loader.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 40b86dcb781b..a354d0e948ec 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2659,7 +2659,7 @@ struct drm_i915_cmd_table { #define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview) #define IS_HASWELL(dev_priv) ((dev_priv)->info.is_haswell) #define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell) -#define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake) +#define IS_SKYLAKE(dev_priv) ((dev_priv)->info.is_skylake) #define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton) #define IS_KABYLAKE(dev_priv) ((dev_priv)->info.is_kabylake) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 179f16b19515..1f788d10b56b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2135,7 +2135,7 @@ static void gtt_write_workarounds(struct drm_device *dev) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); else if (IS_CHERRYVIEW(dev)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); - else if (IS_SKYLAKE(dev)) + else if (IS_SKYLAKE(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); else if (IS_BROXTON(dev)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 8eb49685dfdd..688b68a7ae1e 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -728,7 +728,7 @@ void intel_guc_init(struct drm_device *dev) if (!HAS_GUC_UCODE(dev)) { fw_path = NULL; - } else if (IS_SKYLAKE(dev)) { + } else if (IS_SKYLAKE(dev_priv)) { fw_path = I915_SKL_GUC_UCODE; guc_fw->guc_fw_major_wanted = SKL_FW_MAJOR; guc_fw->guc_fw_minor_wanted = SKL_FW_MINOR; -- cgit v1.2.3 From e2d214ae2b343abbdc073a800fed924bdd124cfe Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:04 +0100 Subject: drm/i915: Make IS_BROXTON only take dev_priv Saves 1392 bytes of .rodata strings. Also change a few function/macro prototypes in i915_gem_gtt.c from dev to dev_priv where it made more sense to do so. v2: Add parantheses around dev_priv. (Ville Syrjala) v3: Mention function prototype changes. (David Weinehall) Signed-off-by: Tvrtko Ursulin Cc: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst Reviewed-by: David Weinehall --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 5 +++-- drivers/gpu/drm/i915/i915_gem_gtt.c | 40 +++++++++++++++++---------------- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 31 ++++++++++++++----------- drivers/gpu/drm/i915/intel_dp.c | 16 ++++++------- drivers/gpu/drm/i915/intel_dpll_mgr.c | 2 +- drivers/gpu/drm/i915/intel_dsi.c | 27 +++++++++++----------- drivers/gpu/drm/i915/intel_dsi_pll.c | 26 ++++++++++----------- drivers/gpu/drm/i915/intel_guc_loader.c | 8 +++---- drivers/gpu/drm/i915/intel_hdmi.c | 6 ++--- drivers/gpu/drm/i915/intel_runtime_pm.c | 2 +- 13 files changed, 89 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5dd56d9ea905..64e31cd25dea 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2414,7 +2414,7 @@ static int intel_runtime_resume(struct device *kdev) if (IS_GEN6(dev_priv)) intel_init_pch_refclk(dev); - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { bxt_disable_dc9(dev_priv); bxt_display_core_init(dev_priv, true); if (dev_priv->csr.dmc_payload && diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a354d0e948ec..39d685020f6e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2660,7 +2660,7 @@ struct drm_i915_cmd_table { #define IS_HASWELL(dev_priv) ((dev_priv)->info.is_haswell) #define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell) #define IS_SKYLAKE(dev_priv) ((dev_priv)->info.is_skylake) -#define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton) +#define IS_BROXTON(dev_priv) ((dev_priv)->info.is_broxton) #define IS_KABYLAKE(dev_priv) ((dev_priv)->info.is_kabylake) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \ @@ -2720,7 +2720,8 @@ struct drm_i915_cmd_table { #define BXT_REVID_B0 0x3 #define BXT_REVID_C0 0x9 -#define IS_BXT_REVID(p, since, until) (IS_BROXTON(p) && IS_REVID(p, since, until)) +#define IS_BXT_REVID(dev_priv, since, until) \ + (IS_BROXTON(dev_priv) && IS_REVID(dev_priv, since, until)) #define KBL_REVID_A0 0x0 #define KBL_REVID_B0 0x1 diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1f788d10b56b..1eef0de03159 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -373,27 +373,29 @@ static void *kmap_page_dma(struct i915_page_dma *p) /* We use the flushing unmap only with ppgtt structures: * page directories, page tables and scratch pages. */ -static void kunmap_page_dma(struct drm_device *dev, void *vaddr) +static void kunmap_page_dma(struct drm_i915_private *dev_priv, void *vaddr) { /* There are only few exceptions for gen >=6. chv and bxt. * And we are not sure about the latter so play safe for now. */ - if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) + if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv)) drm_clflush_virt_range(vaddr, PAGE_SIZE); kunmap_atomic(vaddr); } #define kmap_px(px) kmap_page_dma(px_base(px)) -#define kunmap_px(ppgtt, vaddr) kunmap_page_dma((ppgtt)->base.dev, (vaddr)) +#define kunmap_px(ppgtt, vaddr) \ + kunmap_page_dma(to_i915((ppgtt)->base.dev), (vaddr)) #define setup_px(dev, px) setup_page_dma((dev), px_base(px)) #define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px)) -#define fill_px(dev, px, v) fill_page_dma((dev), px_base(px), (v)) -#define fill32_px(dev, px, v) fill_page_dma_32((dev), px_base(px), (v)) +#define fill_px(dev_priv, px, v) fill_page_dma((dev_priv), px_base(px), (v)) +#define fill32_px(dev_priv, px, v) \ + fill_page_dma_32((dev_priv), px_base(px), (v)) -static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p, - const uint64_t val) +static void fill_page_dma(struct drm_i915_private *dev_priv, + struct i915_page_dma *p, const uint64_t val) { int i; uint64_t * const vaddr = kmap_page_dma(p); @@ -401,17 +403,17 @@ static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p, for (i = 0; i < 512; i++) vaddr[i] = val; - kunmap_page_dma(dev, vaddr); + kunmap_page_dma(dev_priv, vaddr); } -static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p, - const uint32_t val32) +static void fill_page_dma_32(struct drm_i915_private *dev_priv, + struct i915_page_dma *p, const uint32_t val32) { uint64_t v = val32; v = v << 32 | val32; - fill_page_dma(dev, p, v); + fill_page_dma(dev_priv, p, v); } static int @@ -474,7 +476,7 @@ static void gen8_initialize_pt(struct i915_address_space *vm, scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, true); - fill_px(vm->dev, pt, scratch_pte); + fill_px(to_i915(vm->dev), pt, scratch_pte); } static void gen6_initialize_pt(struct i915_address_space *vm, @@ -487,7 +489,7 @@ static void gen6_initialize_pt(struct i915_address_space *vm, scratch_pte = vm->pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, true, 0); - fill32_px(vm->dev, pt, scratch_pte); + fill32_px(to_i915(vm->dev), pt, scratch_pte); } static struct i915_page_directory *alloc_pd(struct drm_device *dev) @@ -534,7 +536,7 @@ static void gen8_initialize_pd(struct i915_address_space *vm, scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC); - fill_px(vm->dev, pd, scratch_pde); + fill_px(to_i915(vm->dev), pd, scratch_pde); } static int __pdp_init(struct drm_device *dev, @@ -615,7 +617,7 @@ static void gen8_initialize_pdp(struct i915_address_space *vm, scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC); - fill_px(vm->dev, pdp, scratch_pdpe); + fill_px(to_i915(vm->dev), pdp, scratch_pdpe); } static void gen8_initialize_pml4(struct i915_address_space *vm, @@ -626,7 +628,7 @@ static void gen8_initialize_pml4(struct i915_address_space *vm, scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC); - fill_px(vm->dev, pml4, scratch_pml4e); + fill_px(to_i915(vm->dev), pml4, scratch_pml4e); } static void @@ -2137,7 +2139,7 @@ static void gtt_write_workarounds(struct drm_device *dev) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); else if (IS_SKYLAKE(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); } @@ -2918,7 +2920,7 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) * resort to an uncached mapping. The WC issue is easily caught by the * readback check when writing GTT PTE entries. */ - if (IS_BROXTON(ggtt->base.dev)) + if (IS_BROXTON(to_i915(ggtt->base.dev))) ggtt->gsm = ioremap_nocache(phys_addr, size); else ggtt->gsm = ioremap_wc(phys_addr, size); @@ -3290,7 +3292,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) ggtt->base.closed = false; if (INTEL_INFO(dev)->gen >= 8) { - if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) + if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv)) chv_setup_private_ppat(dev_priv); else bdw_setup_private_ppat(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4eae1beb0d4f..a450edaec33d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -4594,7 +4594,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_uninstall = gen8_irq_uninstall; dev->driver->enable_vblank = gen8_enable_vblank; dev->driver->disable_vblank = gen8_disable_vblank; - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_KBP(dev_priv)) dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 07164e250adf..a76afd7a6616 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2509,7 +2509,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) * configuration so that we use the proper lane count for our * calculations. */ - if (IS_BROXTON(dev) && port == PORT_A) { + if (IS_BROXTON(dev_priv) && port == PORT_A) { if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) { DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n"); intel_dig_port->saved_port_bits |= DDI_A_4_LANES; @@ -2533,7 +2533,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) * On BXT A0/A1, sw needs to activate DDIA HPD logic and * interrupts to check the external panel connection. */ - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) && port == PORT_B) + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) && port == PORT_B) dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port; else dev_priv->hotplug.irq_port[port] = intel_dig_port; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1a2b3be4d882..e07c34478e09 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -600,7 +600,7 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock) * the given connectors. */ -static bool intel_PLL_is_valid(struct drm_device *dev, +static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv, const struct intel_limit *limit, const struct dpll *clock) { @@ -613,12 +613,13 @@ static bool intel_PLL_is_valid(struct drm_device *dev, if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) INTELPllInvalid("m1 out of range\n"); - if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && - !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) + if (!IS_PINEVIEW(dev_priv) && !IS_VALLEYVIEW(dev_priv) && + !IS_CHERRYVIEW(dev_priv) && !IS_BROXTON(dev_priv)) if (clock->m1 <= clock->m2) INTELPllInvalid("m1 <= m2\n"); - if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) { + if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) && + !IS_BROXTON(dev_priv)) { if (clock->p < limit->p.min || limit->p.max < clock->p) INTELPllInvalid("p out of range\n"); if (clock->m < limit->m.min || limit->m.max < clock->m) @@ -698,7 +699,8 @@ i9xx_find_best_dpll(const struct intel_limit *limit, int this_err; i9xx_calc_dpll_params(refclk, &clock); - if (!intel_PLL_is_valid(dev, limit, + if (!intel_PLL_is_valid(to_i915(dev), + limit, &clock)) continue; if (match_clock && @@ -753,7 +755,8 @@ pnv_find_best_dpll(const struct intel_limit *limit, int this_err; pnv_calc_dpll_params(refclk, &clock); - if (!intel_PLL_is_valid(dev, limit, + if (!intel_PLL_is_valid(to_i915(dev), + limit, &clock)) continue; if (match_clock && @@ -813,7 +816,8 @@ g4x_find_best_dpll(const struct intel_limit *limit, int this_err; i9xx_calc_dpll_params(refclk, &clock); - if (!intel_PLL_is_valid(dev, limit, + if (!intel_PLL_is_valid(to_i915(dev), + limit, &clock)) continue; @@ -909,7 +913,8 @@ vlv_find_best_dpll(const struct intel_limit *limit, vlv_calc_dpll_params(refclk, &clock); - if (!intel_PLL_is_valid(dev, limit, + if (!intel_PLL_is_valid(to_i915(dev), + limit, &clock)) continue; @@ -977,7 +982,7 @@ chv_find_best_dpll(const struct intel_limit *limit, chv_calc_dpll_params(refclk, &clock); - if (!intel_PLL_is_valid(dev, limit, &clock)) + if (!intel_PLL_is_valid(to_i915(dev), limit, &clock)) continue; if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock, @@ -5850,7 +5855,7 @@ static void intel_update_max_cdclk(struct drm_device *dev) max_cdclk = 308571; dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco); - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { dev_priv->max_cdclk_freq = 624000; } else if (IS_BROADWELL(dev_priv)) { /* @@ -10648,7 +10653,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) skylake_get_ddi_pll(dev_priv, port, pipe_config); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) bxt_get_ddi_pll(dev_priv, port, pipe_config); else haswell_get_ddi_pll(dev_priv, port, pipe_config); @@ -12806,7 +12811,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled); DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, " "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n", @@ -15399,7 +15404,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (intel_crt_present(dev)) intel_crt_init(dev); - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { /* * FIXME: Broxton doesn't support port detection via the * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d62f318bf758..28962788b08b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -571,7 +571,7 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv) struct intel_encoder *encoder; if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && - !IS_BROXTON(dev))) + !IS_BROXTON(dev_priv))) return; /* @@ -591,7 +591,7 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv) continue; intel_dp = enc_to_intel_dp(&encoder->base); - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) intel_dp->pps_reset = true; else intel_dp->pps_pipe = INVALID_PIPE; @@ -2981,7 +2981,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = to_i915(dev); enum port port = dp_to_dig_port(intel_dp)->port; - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; else if (INTEL_INFO(dev)->gen >= 9) { if (dev_priv->vbt.edp.low_vswing && port == PORT_A) @@ -3344,7 +3344,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) if (HAS_DDI(dev_priv)) { signal_levels = ddi_signal_levels(intel_dp); - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) signal_levels = 0; else mask = DDI_BUF_EMP_MASK; @@ -5072,7 +5072,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); /* Compute the divisor for the pp clock, simply match the Bspec * formula. */ - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { pp_div = I915_READ(regs.pp_ctrl); pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK; pp_div |= (DIV_ROUND_UP((seq->t11_t12 + 1), 1000) @@ -5098,7 +5098,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, I915_WRITE(regs.pp_on, pp_on); I915_WRITE(regs.pp_off, pp_off); - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) I915_WRITE(regs.pp_ctrl, pp_div); else I915_WRITE(regs.pp_div, pp_div); @@ -5106,7 +5106,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", I915_READ(regs.pp_on), I915_READ(regs.pp_off), - IS_BROXTON(dev) ? + IS_BROXTON(dev_priv) ? (I915_READ(regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK) : I915_READ(regs.pp_div)); } @@ -5715,7 +5715,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, break; case PORT_B: intel_encoder->hpd_pin = HPD_PORT_B; - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) intel_encoder->hpd_pin = HPD_PORT_A; break; case PORT_C: diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 7cf9d91c0746..605d0b509f24 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1853,7 +1853,7 @@ void intel_shared_dpll_init(struct drm_device *dev) if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) dpll_mgr = &skl_pll_mgr; - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) dpll_mgr = &bxt_pll_mgr; else if (HAS_DDI(dev_priv)) dpll_mgr = &hsw_pll_mgr; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 5b1e445a80d0..48e8dd108f4f 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -437,11 +437,11 @@ static void vlv_dsi_device_ready(struct intel_encoder *encoder) static void intel_dsi_device_ready(struct intel_encoder *encoder) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_dsi_device_ready(encoder); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) bxt_dsi_device_ready(encoder); } @@ -464,7 +464,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder) } for_each_dsi_port(port, intel_dsi->ports) { - i915_reg_t port_ctrl = IS_BROXTON(dev) ? + i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ? BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); u32 temp; @@ -494,7 +494,7 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder) enum port port; for_each_dsi_port(port, intel_dsi->ports) { - i915_reg_t port_ctrl = IS_BROXTON(dev) ? + i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ? BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); u32 temp; @@ -656,7 +656,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder) static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) { - struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; @@ -664,7 +663,7 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); for_each_dsi_port(port, intel_dsi->ports) { /* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */ - i915_reg_t port_ctrl = IS_BROXTON(dev) ? + i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ? BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A); u32 val; @@ -762,7 +761,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, /* XXX: this only works for one DSI output */ for_each_dsi_port(port, intel_dsi->ports) { - i915_reg_t ctrl_reg = IS_BROXTON(dev) ? + i915_reg_t ctrl_reg = IS_BROXTON(dev_priv) ? BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); bool enabled = I915_READ(ctrl_reg) & DPI_ENABLE; @@ -970,11 +969,11 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, static void intel_dsi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 pclk; DRM_DEBUG_KMS("\n"); - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) bxt_dsi_get_pipe_config(encoder, pipe_config); pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp, @@ -1066,7 +1065,7 @@ static void set_dsi_timings(struct drm_encoder *encoder, hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio); for_each_dsi_port(port, intel_dsi->ports) { - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { /* * Program hdisplay and vdisplay on MIPI transcoder. * This is different from calculated hactive and @@ -1153,7 +1152,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, tmp &= ~READ_REQUEST_PRIORITY_MASK; I915_WRITE(MIPI_CTRL(port), tmp | READ_REQUEST_PRIORITY_HIGH); - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { enum pipe pipe = intel_crtc->pipe; tmp = I915_READ(MIPI_CTRL(port)); @@ -1242,7 +1241,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, I915_WRITE(MIPI_INIT_COUNT(port), txclkesc(intel_dsi->escape_clk_div, 100)); - if (IS_BROXTON(dev) && (!intel_dsi->dual_link)) { + if (IS_BROXTON(dev_priv) && (!intel_dsi->dual_link)) { /* * BXT spec says write MIPI_INIT_COUNT for * both the ports, even if only one is @@ -1452,7 +1451,7 @@ void intel_dsi_init(struct drm_device *dev) if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { dev_priv->mipi_mmio_base = VLV_MIPI_BASE; - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { dev_priv->mipi_mmio_base = BXT_MIPI_BASE; } else { DRM_ERROR("Unsupported Mipi device to reg base"); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 6ab58a01b18e..56eff6004bc0 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -351,7 +351,7 @@ static u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp, u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp, struct intel_crtc_state *config) { - if (IS_BROXTON(encoder->base.dev)) + if (IS_BROXTON(to_i915(encoder->base.dev))) return bxt_dsi_get_pclk(encoder, pipe_bpp, config); else return vlv_dsi_get_pclk(encoder, pipe_bpp, config); @@ -515,11 +515,11 @@ bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv) int intel_compute_dsi_pll(struct intel_encoder *encoder, struct intel_crtc_state *config) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return vlv_compute_dsi_pll(encoder, config); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) return bxt_compute_dsi_pll(encoder, config); return -ENODEV; @@ -528,21 +528,21 @@ int intel_compute_dsi_pll(struct intel_encoder *encoder, void intel_enable_dsi_pll(struct intel_encoder *encoder, const struct intel_crtc_state *config) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_enable_dsi_pll(encoder, config); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) bxt_enable_dsi_pll(encoder, config); } void intel_disable_dsi_pll(struct intel_encoder *encoder) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_disable_dsi_pll(encoder); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) bxt_disable_dsi_pll(encoder); } @@ -564,10 +564,10 @@ static void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) { - struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) bxt_dsi_reset_clocks(encoder, port); - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_dsi_reset_clocks(encoder, port); } diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 688b68a7ae1e..4a34a607e90e 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -378,16 +378,16 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); /* WaDisableMinuteIaClockGating:bxt */ - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) & ~GUC_ENABLE_MIA_CLOCK_GATING)); } /* WaC6DisallowByGfxPause:bxt */ - if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE); else I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); @@ -732,7 +732,7 @@ void intel_guc_init(struct drm_device *dev) fw_path = I915_SKL_GUC_UCODE; guc_fw->guc_fw_major_wanted = SKL_FW_MAJOR; guc_fw->guc_fw_minor_wanted = SKL_FW_MINOR; - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { fw_path = I915_BXT_GUC_UCODE; guc_fw->guc_fw_major_wanted = BXT_FW_MAJOR; guc_fw->guc_fw_minor_wanted = BXT_FW_MINOR; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 6607c4e3c36c..f6562451c47e 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1241,7 +1241,7 @@ static enum drm_mode_status hdmi_port_clock_valid(struct intel_hdmi *hdmi, int clock, bool respect_downstream_limits) { - struct drm_device *dev = intel_hdmi_to_dev(hdmi); + struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); if (clock < 25000) return MODE_CLOCK_LOW; @@ -1249,11 +1249,11 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, return MODE_CLOCK_HIGH; /* BXT DPLL can't generate 223-240 MHz */ - if (IS_BROXTON(dev) && clock > 223333 && clock < 240000) + if (IS_BROXTON(dev_priv) && clock > 223333 && clock < 240000) return MODE_CLOCK_RANGE; /* CHV DPLL can't generate 216-240 MHz */ - if (IS_CHERRYVIEW(dev) && clock > 216000 && clock < 240000) + if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000) return MODE_CLOCK_RANGE; return MODE_OK; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 025fbd522819..e4bb85c9c6e1 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2596,7 +2596,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { skl_display_core_init(dev_priv, resume); - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { bxt_display_core_init(dev_priv, resume); } else if (IS_CHERRYVIEW(dev)) { mutex_lock(&power_domains->lock); -- cgit v1.2.3 From 3c9192bc08dd96b641ce65d7596a7f56a73334d8 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:05 +0100 Subject: drm/i915: Make HAS_L3_DPF only take dev_priv Saves 472 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_irq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 39d685020f6e..93ce0e9ada50 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2865,7 +2865,7 @@ struct drm_i915_cmd_table { #define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.has_gmch_display) /* DPF == dynamic parity feature */ -#define HAS_L3_DPF(dev) (INTEL_INFO(dev)->has_l3_dpf) +#define HAS_L3_DPF(dev_priv) ((dev_priv)->info.has_l3_dpf) #define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \ 2 : HAS_L3_DPF(dev_priv)) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a450edaec33d..d09f16edff76 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3589,7 +3589,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) pm_irqs = gt_irqs = 0; dev_priv->gt_irq_mask = ~0; - if (HAS_L3_DPF(dev)) { + if (HAS_L3_DPF(dev_priv)) { /* L3 parity interrupt is always unmasked. */ dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev_priv); gt_irqs |= GT_PARITY_ERROR(dev_priv); -- cgit v1.2.3 From 9beb5fea044e32848b56bb3c17f79d3ed2a2efb8 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:06 +0100 Subject: drm/i915: Make IS_G4X only take dev_priv Saves 472 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 5 +++-- drivers/gpu/drm/i915/i915_suspend.c | 4 ++-- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 40 ++++++++++++++++++---------------- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 4 ++-- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 8 files changed, 33 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 93ce0e9ada50..f9ef7334f6dd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2645,7 +2645,7 @@ struct drm_i915_cmd_table { #define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) #define IS_GM45(dev_priv) (INTEL_DEVID(dev_priv) == 0x2A42) -#define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x) +#define IS_G4X(dev_priv) ((dev_priv)->info.is_g4x) #define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001) #define IS_PINEVIEW_M(dev_priv) (INTEL_DEVID(dev_priv) == 0xa011) #define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 3508120b8c90..d1b40bce0249 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -204,7 +204,8 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) return 0; /* make sure we don't clobber the GTT if it's within stolen memory */ - if (INTEL_INFO(dev)->gen <= 4 && !IS_G33(dev) && !IS_G4X(dev)) { + if (INTEL_GEN(dev_priv) <= 4 && !IS_G33(dev_priv) && + !IS_G4X(dev_priv)) { struct { u32 start, end; } stolen[2] = { @@ -437,7 +438,7 @@ int i915_gem_init_stolen(struct drm_device *dev) case 3: break; case 4: - if (IS_G4X(dev)) + if (IS_G4X(dev_priv)) g4x_get_stolen_reserved(dev_priv, &reserved_base, &reserved_size); break; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a0af170062b1..7870856fccd0 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -38,7 +38,7 @@ static void i915_save_display(struct drm_device *dev) dev_priv->regfile.saveDSPARB = I915_READ(DSPARB); /* save FBC interval */ - if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev)) + if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv)) dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL); } @@ -54,7 +54,7 @@ static void i915_restore_display(struct drm_device *dev) intel_fbc_global_disable(dev_priv); /* restore FBC interval */ - if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev)) + if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv)) I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL); i915_redisable_vga(dev); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index d4388c03b4da..d456786f5813 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -771,7 +771,7 @@ static int intel_crt_get_modes(struct drm_connector *connector) i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin); ret = intel_crt_ddc_get_modes(connector, i2c); - if (ret || !IS_G4X(dev)) + if (ret || !IS_G4X(dev_priv)) goto out; /* Try to probe digital port for output in DVI-I -> VGA mode. */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e07c34478e09..749bc3299206 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3071,7 +3071,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, fb->modifier[0] == I915_FORMAT_MOD_X_TILED) dspcntr |= DISPPLANE_TILED; - if (IS_G4X(dev)) + if (IS_G4X(dev_priv)) dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; intel_add_fb_offsets(&x, &y, plane_state, 0); @@ -7224,7 +7224,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, /* Cantiga+ cannot handle modes with a hsync front porch of 0. * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw. */ - if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) && + if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) && adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay) return -EINVAL; @@ -7538,7 +7538,7 @@ static unsigned int intel_hpll_vco(struct drm_device *dev) /* FIXME other chipsets? */ if (IS_GM45(dev_priv)) vco_table = ctg_vco; - else if (IS_G4X(dev)) + else if (IS_G4X(dev_priv)) vco_table = elk_vco; else if (IS_CRESTLINE(dev)) vco_table = cl_vco; @@ -8172,7 +8172,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; else { dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; - if (IS_G4X(dev) && reduced_clock) + if (IS_G4X(dev_priv) && reduced_clock) dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; } switch (clock->p2) { @@ -8414,7 +8414,8 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) pipeconf |= PIPECONF_DOUBLE_WIDE; /* only g4x and later have fancy bpc/dither controls */ - if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || + IS_CHERRYVIEW(dev_priv)) { /* Bspec claims that we can't use dithering for 30bpp pipes. */ if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30) pipeconf |= PIPECONF_DITHER_EN | @@ -8831,7 +8832,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (!(tmp & PIPECONF_ENABLE)) goto out; - if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || + IS_CHERRYVIEW(dev_priv)) { switch (tmp & PIPECONF_BPC_MASK) { case PIPECONF_6BPC: pipe_config->pipe_bpp = 18; @@ -11580,7 +11582,7 @@ static bool __pageflip_finished_cs(struct intel_crtc *crtc, * really needed there. But since ctg has the registers, * include it in the check anyway. */ - if (INTEL_INFO(dev)->gen < 5 && !IS_G4X(dev)) + if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) return true; /* @@ -12243,7 +12245,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, atomic_inc(&intel_crtc->unpin_work_count); - if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) + if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1; if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { @@ -12703,15 +12705,16 @@ static int compute_baseline_pipe_bpp(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { - struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct drm_atomic_state *state; struct drm_connector *connector; struct drm_connector_state *connector_state; int bpp, i; - if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))) + if ((IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || + IS_CHERRYVIEW(dev_priv))) bpp = 10*3; - else if (INTEL_INFO(dev)->gen >= 5) + else if (INTEL_GEN(dev_priv) >= 5) bpp = 12*3; else bpp = 8*3; @@ -13402,7 +13405,7 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_X(dsi_pll.ctrl); PIPE_CONF_CHECK_X(dsi_pll.div); - if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) + if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) PIPE_CONF_CHECK_I(pipe_bpp); PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock); @@ -14964,7 +14967,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, intel_primary_formats, num_formats, DRM_PLANE_TYPE_PRIMARY, "plane 1%c", pipe_name(pipe)); - else if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) + else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) ret = drm_universal_plane_init(dev, &primary->base, 0, &intel_plane_funcs, intel_primary_formats, num_formats, @@ -15525,12 +15528,12 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) { DRM_DEBUG_KMS("probing SDVOB\n"); found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B); - if (!found && IS_G4X(dev)) { + if (!found && IS_G4X(dev_priv)) { DRM_DEBUG_KMS("probing HDMI on SDVOB\n"); intel_hdmi_init(dev, GEN4_HDMIB, PORT_B); } - if (!found && IS_G4X(dev)) + if (!found && IS_G4X(dev_priv)) intel_dp_init(dev, DP_B, PORT_B); } @@ -15543,16 +15546,15 @@ static void intel_setup_outputs(struct drm_device *dev) if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) { - if (IS_G4X(dev)) { + if (IS_G4X(dev_priv)) { DRM_DEBUG_KMS("probing HDMI on SDVOC\n"); intel_hdmi_init(dev, GEN4_HDMIC, PORT_C); } - if (IS_G4X(dev)) + if (IS_G4X(dev_priv)) intel_dp_init(dev, DP_C, PORT_C); } - if (IS_G4X(dev) && - (I915_READ(DP_D) & DP_DETECTED)) + if (IS_G4X(dev_priv) && (I915_READ(DP_D) & DP_DETECTED)) intel_dp_init(dev, DP_D, PORT_D); } else if (IS_GEN2(dev)) intel_dvo_init(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 28962788b08b..63bf500edbbd 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1341,7 +1341,7 @@ intel_dp_set_clock(struct intel_encoder *encoder, const struct dp_link_dpll *divisor = NULL; int i, count = 0; - if (IS_G4X(dev)) { + if (IS_G4X(dev_priv)) { divisor = gen4_dpll; count = ARRAY_SIZE(gen4_dpll); } else if (HAS_PCH_SPLIT(dev_priv)) { diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index f6562451c47e..c7d9cddf4e3e 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1889,7 +1889,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi->write_infoframe = vlv_write_infoframe; intel_hdmi->set_infoframes = vlv_set_infoframes; intel_hdmi->infoframe_enabled = vlv_infoframe_enabled; - } else if (IS_G4X(dev)) { + } else if (IS_G4X(dev_priv)) { intel_hdmi->write_infoframe = g4x_write_infoframe; intel_hdmi->set_infoframes = g4x_set_infoframes; intel_hdmi->infoframe_enabled = g4x_infoframe_enabled; @@ -1996,7 +1996,7 @@ void intel_hdmi_init(struct drm_device *dev, * to work on real hardware. And since g4x can send infoframes to * only one port anyway, nothing is lost by allowing it. */ - if (IS_G4X(dev)) + if (IS_G4X(dev_priv)) intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI; intel_dig_port->port = port; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 78b781adef93..0e3d557f214b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -326,7 +326,7 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0); POSTING_READ(FW_BLC_SELF_VLV); dev_priv->wm.vlv.cxsr = enable; - } else if (IS_G4X(dev) || IS_CRESTLINE(dev)) { + } else if (IS_G4X(dev_priv) || IS_CRESTLINE(dev_priv)) { I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0); POSTING_READ(FW_BLC_SELF); } else if (IS_PINEVIEW(dev)) { @@ -7789,7 +7789,7 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.update_wm = NULL; } else dev_priv->display.update_wm = pineview_update_wm; - } else if (IS_G4X(dev)) { + } else if (IS_G4X(dev_priv)) { dev_priv->display.update_wm = g4x_update_wm; } else if (IS_GEN4(dev)) { dev_priv->display.update_wm = i965_update_wm; -- cgit v1.2.3 From 920a14b2459701196e42a47c7bc1559582e79ab9 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 14 Oct 2016 10:13:44 +0100 Subject: drm/i915: Make IS_CHERRYVIEW only take dev_priv Saves 864 bytes of .rodata strings and ~100 of .text. v2: Add parantheses around dev_priv. (Ville Syrjala) v3: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 8 ++-- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/intel_audio.c | 4 +- drivers/gpu/drm/i915/intel_color.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 67 +++++++++++++++++---------------- drivers/gpu/drm/i915/intel_dp.c | 55 ++++++++++++++------------- drivers/gpu/drm/i915/intel_dsi.c | 8 ++-- drivers/gpu/drm/i915/intel_hdmi.c | 10 ++--- drivers/gpu/drm/i915/intel_i2c.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 4 +- drivers/gpu/drm/i915/intel_psr.c | 4 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 2 +- drivers/gpu/drm/i915/intel_sprite.c | 10 +++-- 14 files changed, 93 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 64e31cd25dea..1b4cfaa0e0e1 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -424,7 +424,7 @@ intel_setup_mchbar(struct drm_device *dev) u32 temp; bool enabled; - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return; dev_priv->mchbar_need_disable = false; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f9ef7334f6dd..15e81cf01ce2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2656,7 +2656,7 @@ struct drm_i915_cmd_table { INTEL_DEVID(dev_priv) == 0x0152 || \ INTEL_DEVID(dev_priv) == 0x015a) #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) -#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview) +#define IS_CHERRYVIEW(dev_priv) ((dev_priv)->info.is_cherryview) #define IS_HASWELL(dev_priv) ((dev_priv)->info.is_haswell) #define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell) #define IS_SKYLAKE(dev_priv) ((dev_priv)->info.is_skylake) @@ -3847,11 +3847,11 @@ __raw_write(64, q) #define INTEL_BROADCAST_RGB_FULL 1 #define INTEL_BROADCAST_RGB_LIMITED 2 -static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev) +static inline i915_reg_t i915_vgacntrl_reg(struct drm_i915_private *dev_priv) { - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return VLV_VGACNTRL; - else if (INTEL_INFO(dev)->gen >= 5) + else if (INTEL_GEN(dev_priv) >= 5) return CPU_VGACNTRL; else return VGACNTRL; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1eef0de03159..c3c3f28aa5a1 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2135,7 +2135,7 @@ static void gtt_write_workarounds(struct drm_device *dev) /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */ if (IS_BROADWELL(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); - else if (IS_CHERRYVIEW(dev)) + else if (IS_CHERRYVIEW(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); else if (IS_SKYLAKE(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index e20da59b1020..7093cfbb62b1 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -435,8 +435,8 @@ static void ilk_audio_codec_enable(struct drm_connector *connector, aud_config = IBX_AUD_CFG(pipe); aud_cntl_st = IBX_AUD_CNTL_ST(pipe); aud_cntrl_st2 = IBX_AUD_CNTL_ST2; - } else if (IS_VALLEYVIEW(connector->dev) || - IS_CHERRYVIEW(connector->dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || + IS_CHERRYVIEW(dev_priv)) { hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); aud_config = VLV_AUD_CFG(pipe); aud_cntl_st = VLV_AUD_CNTL_ST(pipe); diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index da76a799411a..445108855275 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -534,7 +534,7 @@ void intel_color_init(struct drm_crtc *crtc) drm_mode_crtc_set_gamma_size(crtc, 256); - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix; dev_priv->display.load_luts = cherryview_load_luts; } else if (IS_HASWELL(dev_priv)) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 749bc3299206..aaa1c707f6f1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -849,7 +849,7 @@ static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq, * For CHV ignore the error and consider only the P value. * Prefer a bigger P value based on HW requirements. */ - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(to_i915(dev))) { *error_ppm = 0; return calculated_clock->p > best_clock->p; @@ -1332,7 +1332,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, "plane %d assertion failure, should be off on pipe %c but is still active\n", sprite, pipe_name(pipe)); } - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { for_each_sprite(dev_priv, pipe, sprite) { u32 val = I915_READ(SPCNTR(pipe, sprite)); I915_STATE_WARN(val & SP_ENABLE, @@ -3033,7 +3033,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, ((crtc_state->pipe_src_h - 1) << 16) | (crtc_state->pipe_src_w - 1)); I915_WRITE(DSPPOS(plane), 0); - } else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) { + } else if (IS_CHERRYVIEW(dev_priv) && plane == PLANE_B) { I915_WRITE(PRIMSIZE(plane), ((crtc_state->pipe_src_h - 1) << 16) | (crtc_state->pipe_src_w - 1)); @@ -5872,7 +5872,7 @@ static void intel_update_max_cdclk(struct drm_device *dev) dev_priv->max_cdclk_freq = 540000; else dev_priv->max_cdclk_freq = 675000; - } else if (IS_CHERRYVIEW(dev)) { + } else if (IS_CHERRYVIEW(dev_priv)) { dev_priv->max_cdclk_freq = 320000; } else if (IS_VALLEYVIEW(dev)) { dev_priv->max_cdclk_freq = 400000; @@ -6674,7 +6674,7 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state) */ intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A); - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) cherryview_set_cdclk(dev, req_cdclk); else valleyview_set_cdclk(dev, req_cdclk); @@ -6702,7 +6702,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, intel_set_pipe_timings(intel_crtc); intel_set_pipe_src_size(intel_crtc); - if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) { + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { struct drm_i915_private *dev_priv = to_i915(dev); I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY); @@ -6717,7 +6717,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_pre_pll_enable(crtc, pipe_config, old_state); - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { chv_prepare_pll(intel_crtc, intel_crtc->config); chv_enable_pll(intel_crtc, intel_crtc->config); } else { @@ -6836,7 +6836,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_encoders_post_disable(crtc, old_crtc_state, old_state); if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) { - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) chv_disable_pll(dev_priv, pipe); else if (IS_VALLEYVIEW(dev)) vlv_disable_pll(dev_priv, pipe); @@ -7803,8 +7803,8 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, * for gen < 8) and if DRRS is supported (to make sure the * registers are not unnecessarily accessed). */ - if (m2_n2 && (IS_CHERRYVIEW(dev) || INTEL_INFO(dev)->gen < 8) && - crtc->config->has_drrs) { + if (m2_n2 && (IS_CHERRYVIEW(dev_priv) || + INTEL_GEN(dev_priv) < 8) && crtc->config->has_drrs) { I915_WRITE(PIPE_DATA_M2(transcoder), TU_SIZE(m2_n2->tu) | m2_n2->gmch_m); I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n); @@ -8106,7 +8106,7 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, pipe_config->pixel_multiplier = 1; pipe_config->dpll = *dpll; - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(to_i915(dev))) { chv_compute_dpll(crtc, pipe_config); chv_prepare_pll(crtc, pipe_config); chv_enable_pll(crtc, pipe_config); @@ -8131,7 +8131,7 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, */ void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe) { - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(to_i915(dev))) chv_disable_pll(to_i915(dev), pipe); else vlv_disable_pll(to_i915(dev), pipe); @@ -8455,7 +8455,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) } else pipeconf |= PIPECONF_PROGRESSIVE; - if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && intel_crtc->config->limited_color_range) pipeconf |= PIPECONF_COLOR_RANGE_SELECT; @@ -8849,7 +8849,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, } } - if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && (tmp & PIPECONF_COLOR_RANGE_SELECT)) pipe_config->limited_color_range = true; @@ -8863,7 +8863,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (INTEL_INFO(dev)->gen >= 4) { /* No way to read it out on pipes B and C */ - if (IS_CHERRYVIEW(dev) && crtc->pipe != PIPE_A) + if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) tmp = dev_priv->chv_dpll_md[crtc->pipe]; else tmp = I915_READ(DPLL_MD(crtc->pipe)); @@ -8884,7 +8884,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, pipe_config->pixel_multiplier = 1; } pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe)); - if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { + if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) { /* * DPLL_DVO_2X_MODE must be enabled for both DPLLs * on 830. Filter it out here so that we don't @@ -8902,7 +8902,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, DPLL_PORTB_READY_MASK); } - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) chv_crtc_clock_get(crtc, pipe_config); else if (IS_VALLEYVIEW(dev)) vlv_crtc_clock_get(crtc, pipe_config); @@ -12248,7 +12248,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1; - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { engine = dev_priv->engine[BCS]; if (fb->modifier[0] != old_fb->modifier[0]) /* vlv: DISPLAY_FLIP fails to change tiling */ @@ -13346,7 +13346,7 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(pixel_multiplier); PIPE_CONF_CHECK_I(has_hdmi_sink); if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) || - IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) PIPE_CONF_CHECK_I(limited_color_range); PIPE_CONF_CHECK_I(has_infoframe); @@ -15066,7 +15066,7 @@ intel_check_cursor_plane(struct drm_plane *plane, * display power well must be turned off and on again. * Refuse the put the cursor into that compromised position. */ - if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C && + if (IS_CHERRYVIEW(to_i915(plane->dev)) && pipe == PIPE_C && state->base.visible && state->base.crtc_x < 0) { DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); return -EINVAL; @@ -15336,7 +15336,7 @@ static bool intel_crt_present(struct drm_device *dev) if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) return false; - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) return false; if (HAS_PCH_LPT_H(dev_priv) && @@ -15477,7 +15477,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(PCH_DP_D) & DP_DETECTED) intel_dp_init(dev, PCH_DP_D, PORT_D); - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { bool has_edp, has_port; /* @@ -15509,7 +15509,7 @@ static void intel_setup_outputs(struct drm_device *dev) if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp) intel_hdmi_init(dev, VLV_HDMIC, PORT_C); - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { /* * eDP not supported on port D, * so no need to worry about it @@ -15627,10 +15627,10 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { }; static -u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier, - uint32_t pixel_format) +u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv, + uint64_t fb_modifier, uint32_t pixel_format) { - u32 gen = INTEL_INFO(dev)->gen; + u32 gen = INTEL_INFO(dev_priv)->gen; if (gen >= 9) { int cpp = drm_format_plane_cpp(pixel_format, 0); @@ -15639,7 +15639,8 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier, * pixels and 32K bytes." */ return min(8192 * cpp, 32768); - } else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { + } else if (gen >= 5 && !IS_VALLEYVIEW(dev_priv) && + !IS_CHERRYVIEW(dev_priv)) { return 32*1024; } else if (gen >= 4) { if (fb_modifier == I915_FORMAT_MOD_X_TILED) @@ -15726,7 +15727,7 @@ static int intel_framebuffer_init(struct drm_device *dev, return -EINVAL; } - pitch_limit = intel_fb_pitch_limit(dev, mode_cmd->modifier[0], + pitch_limit = intel_fb_pitch_limit(dev_priv, mode_cmd->modifier[0], mode_cmd->pixel_format); if (mode_cmd->pitches[0] > pitch_limit) { DRM_DEBUG("%s pitch (%u) must be at less than %d\n", @@ -15764,7 +15765,7 @@ static int intel_framebuffer_init(struct drm_device *dev, } break; case DRM_FORMAT_ABGR8888: - if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && + if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) && INTEL_INFO(dev)->gen < 9) { format_name = drm_get_format_name(mode_cmd->pixel_format); DRM_DEBUG("unsupported pixel format: %s\n", format_name); @@ -15783,7 +15784,7 @@ static int intel_framebuffer_init(struct drm_device *dev, } break; case DRM_FORMAT_ABGR2101010: - if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { + if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) { format_name = drm_get_format_name(mode_cmd->pixel_format); DRM_DEBUG("unsupported pixel format: %s\n", format_name); kfree(format_name); @@ -16230,7 +16231,7 @@ static void i915_disable_vga(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); struct pci_dev *pdev = dev_priv->drm.pdev; u8 sr1; - i915_reg_t vga_reg = i915_vgacntrl_reg(dev); + i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv); /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */ vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); @@ -16675,7 +16676,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) void i915_redisable_vga_power_on(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - i915_reg_t vga_reg = i915_vgacntrl_reg(dev); + i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv); if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) { DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); @@ -16913,7 +16914,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev) pll->on = false; } - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_wm_get_hw_state(dev); else if (IS_GEN9(dev)) skl_wm_get_hw_state(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 63bf500edbbd..03379baffe49 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -344,7 +344,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) DP |= DP_PORT_WIDTH(1); DP |= DP_LINK_TRAIN_PAT_1; - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) DP |= DP_PIPE_SELECT_CHV(pipe); else if (pipe == PIPE_B) DP |= DP_PIPEB_SELECT; @@ -356,10 +356,10 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) * So enable temporarily it if it's not already enabled. */ if (!pll_enabled) { - release_cl_override = IS_CHERRYVIEW(dev) && + release_cl_override = IS_CHERRYVIEW(dev_priv) && !chv_phy_powergate_ch(dev_priv, phy, ch, true); - if (vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ? + if (vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev_priv) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) { DRM_ERROR("Failed to force on pll for pipe %c!\n", pipe_name(pipe)); @@ -570,7 +570,7 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv) struct drm_device *dev = &dev_priv->drm; struct intel_encoder *encoder; - if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && + if (WARN_ON(!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) && !IS_BROXTON(dev_priv))) return; @@ -664,7 +664,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code, pps_lock(intel_dp); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); i915_reg_t pp_ctrl_reg, pp_div_reg; u32 pp_div; @@ -692,7 +692,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); - if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && intel_dp->pps_pipe == INVALID_PIPE) return false; @@ -706,7 +706,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); - if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && intel_dp->pps_pipe == INVALID_PIPE) return false; @@ -1347,7 +1347,7 @@ intel_dp_set_clock(struct intel_encoder *encoder, } else if (HAS_PCH_SPLIT(dev_priv)) { divisor = pch_dpll; count = ARRAY_SIZE(pch_dpll); - } else if (IS_CHERRYVIEW(dev)) { + } else if (IS_CHERRYVIEW(dev_priv)) { divisor = chv_dpll; count = ARRAY_SIZE(chv_dpll); } else if (IS_VALLEYVIEW(dev)) { @@ -1791,7 +1791,8 @@ static void intel_dp_prepare(struct intel_encoder *encoder, I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); } else { if (!HAS_PCH_SPLIT(dev_priv) && !IS_VALLEYVIEW(dev) && - !IS_CHERRYVIEW(dev) && pipe_config->limited_color_range) + !IS_CHERRYVIEW(dev_priv) && + pipe_config->limited_color_range) intel_dp->DP |= DP_COLOR_RANGE_16_235; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -1803,7 +1804,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) intel_dp->DP |= DP_ENHANCED_FRAMING; - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) intel_dp->DP |= DP_PIPE_SELECT_CHV(crtc->pipe); else if (crtc->pipe == PIPE_B) intel_dp->DP |= DP_PIPEB_SELECT; @@ -2459,7 +2460,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", i915_mmio_reg_offset(intel_dp->output_reg)); - } else if (IS_CHERRYVIEW(dev)) { + } else if (IS_CHERRYVIEW(dev_priv)) { *pipe = DP_PORT_TO_PIPE_CHV(tmp); } else { *pipe = PORT_TO_PIPE(tmp); @@ -2681,7 +2682,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, } } else { - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) *DP &= ~DP_LINK_TRAIN_MASK_CHV; else *DP &= ~DP_LINK_TRAIN_MASK; @@ -2697,7 +2698,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, *DP |= DP_LINK_TRAIN_PAT_2; break; case DP_TRAINING_PATTERN_3: - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { *DP |= DP_LINK_TRAIN_PAT_3_CHV; } else { DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); @@ -2747,7 +2748,7 @@ static void intel_enable_dp(struct intel_encoder *encoder, pps_lock(intel_dp); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_init_panel_power_sequencer(intel_dp); intel_dp_enable_port(intel_dp, pipe_config); @@ -2758,10 +2759,10 @@ static void intel_enable_dp(struct intel_encoder *encoder, pps_unlock(intel_dp); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { unsigned int lane_mask = 0x0; - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count); vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp), @@ -2987,7 +2988,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) if (dev_priv->vbt.edp.low_vswing && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; else if (IS_GEN7(dev) && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; @@ -3348,7 +3349,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) signal_levels = 0; else mask = DDI_BUF_EMP_MASK; - } else if (IS_CHERRYVIEW(dev)) { + } else if (IS_CHERRYVIEW(dev_priv)) { signal_levels = chv_signal_levels(intel_dp); } else if (IS_VALLEYVIEW(dev)) { signal_levels = vlv_signal_levels(intel_dp); @@ -3448,7 +3449,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) DP &= ~DP_LINK_TRAIN_MASK_CPT; DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; } else { - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) DP &= ~DP_LINK_TRAIN_MASK_CHV; else DP &= ~DP_LINK_TRAIN_MASK; @@ -5085,7 +5086,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, /* Haswell doesn't have any port selection bits for the panel * power sequencer any more. */ - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { port_sel = PANEL_PORT_SELECT_VLV(port); } else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) { if (port == PORT_A) @@ -5114,7 +5115,9 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, static void intel_dp_pps_init(struct drm_device *dev, struct intel_dp *intel_dp) { - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + struct drm_i915_private *dev_priv = to_i915(dev); + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { vlv_initial_power_sequencer_setup(intel_dp); } else { intel_dp_init_panel_power_sequencer(dev, intel_dp); @@ -5584,7 +5587,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } mutex_unlock(&dev->mode_config.mutex); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { intel_dp->edp_notifier.notifier_call = edp_notify_handler; register_reboot_notifier(&intel_dp->edp_notifier); @@ -5593,7 +5596,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, * If the current pipe isn't valid, try the PPS pipe, and if that * fails just assume pipe A. */ - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) pipe = DP_PORT_TO_PIPE_CHV(intel_dp->DP); else pipe = PORT_TO_PIPE(intel_dp->DP); @@ -5682,7 +5685,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_encoder->type = INTEL_OUTPUT_EDP; /* eDP only on port B and/or C on vlv/chv */ - if (WARN_ON((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + if (WARN_ON((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && is_edp(intel_dp) && port != PORT_B && port != PORT_C)) return false; @@ -5792,7 +5795,7 @@ bool intel_dp_init(struct drm_device *dev, intel_encoder->get_hw_state = intel_dp_get_hw_state; intel_encoder->get_config = intel_dp_get_config; intel_encoder->suspend = intel_dp_encoder_suspend; - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; intel_encoder->pre_enable = chv_pre_enable_dp; intel_encoder->enable = vlv_enable_dp; @@ -5815,7 +5818,7 @@ bool intel_dp_init(struct drm_device *dev, intel_dig_port->max_lanes = 4; intel_encoder->type = INTEL_OUTPUT_DP; - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { if (port == PORT_D) intel_encoder->crtc_mask = 1 << 2; else diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 48e8dd108f4f..4e0d025490a3 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -740,7 +740,6 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - struct drm_device *dev = encoder->base.dev; enum intel_display_power_domain power_domain; enum port port; bool active = false; @@ -770,7 +769,8 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, * bit in port C control register does not get set. As a * workaround, check pipe B conf instead. */ - if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && port == PORT_C) + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && + port == PORT_C) enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE; /* Try command mode if video mode not enabled */ @@ -1137,7 +1137,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, } for_each_dsi_port(port, intel_dsi->ports) { - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { /* * escape clock divider, 20MHz, shared for A and C. * device ready must be off when doing this! txclkesc? @@ -1449,7 +1449,7 @@ void intel_dsi_init(struct drm_device *dev) if (!intel_bios_is_dsi_present(dev_priv, &port)) return; - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->mipi_mmio_base = VLV_MIPI_BASE; } else if (IS_BROXTON(dev_priv)) { dev_priv->mipi_mmio_base = BXT_MIPI_BASE; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c7d9cddf4e3e..c8243dc4d2b9 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -881,7 +881,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) if (HAS_PCH_CPT(dev_priv)) hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); - else if (IS_CHERRYVIEW(dev)) + else if (IS_CHERRYVIEW(dev_priv)) hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe); else hdmi_val |= SDVO_PIPE_SEL(crtc->pipe); @@ -913,7 +913,7 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, if (HAS_PCH_CPT(dev_priv)) *pipe = PORT_TO_PIPE_CPT(tmp); - else if (IS_CHERRYVIEW(dev)) + else if (IS_CHERRYVIEW(dev_priv)) *pipe = SDVO_PORT_TO_PIPE_CHV(tmp); else *pipe = PORT_TO_PIPE(tmp); @@ -1885,7 +1885,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, BUG(); } - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { intel_hdmi->write_infoframe = vlv_write_infoframe; intel_hdmi->set_infoframes = vlv_set_infoframes; intel_hdmi->infoframe_enabled = vlv_infoframe_enabled; @@ -1959,7 +1959,7 @@ void intel_hdmi_init(struct drm_device *dev, } intel_encoder->get_hw_state = intel_hdmi_get_hw_state; intel_encoder->get_config = intel_hdmi_get_config; - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable; intel_encoder->pre_enable = chv_hdmi_pre_enable; intel_encoder->enable = vlv_enable_hdmi; @@ -1982,7 +1982,7 @@ void intel_hdmi_init(struct drm_device *dev, intel_encoder->type = INTEL_OUTPUT_HDMI; intel_encoder->port = port; - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { if (port == PORT_D) intel_encoder->crtc_mask = 1 << 2; else diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index afb2652919d0..d04185e1edd6 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -635,7 +635,7 @@ int intel_setup_gmbus(struct drm_device *dev) if (HAS_PCH_NOP(dev_priv)) return 0; - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE; else if (!HAS_GMCH_DISPLAY(dev_priv)) dev_priv->gpio_mmio_base = diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0e3d557f214b..d36b5071e066 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -322,7 +322,7 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) struct drm_device *dev = &dev_priv->drm; u32 val; - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0); POSTING_READ(FW_BLC_SELF_VLV); dev_priv->wm.vlv.cxsr = enable; @@ -7768,7 +7768,7 @@ void intel_init_pm(struct drm_device *dev) DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); } - } else if (IS_CHERRYVIEW(dev)) { + } else if (IS_CHERRYVIEW(dev_priv)) { vlv_setup_wm_latency(dev); dev_priv->display.update_wm = vlv_update_wm; } else if (IS_VALLEYVIEW(dev)) { diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 4a973b34348a..271a3e29ff23 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -354,7 +354,7 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) return false; } - if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && !dev_priv->psr.link_standby) { DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n"); return false; @@ -837,7 +837,7 @@ void intel_psr_init(struct drm_device *dev) if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) /* HSW and BDW require workarounds that we don't implement. */ dev_priv->psr.link_standby = false; - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) /* On VLV and CHV only standby mode is supported. */ dev_priv->psr.link_standby = true; else diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index e4bb85c9c6e1..3a6e1a93aed9 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2598,7 +2598,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) skl_display_core_init(dev_priv, resume); } else if (IS_BROXTON(dev_priv)) { bxt_display_core_init(dev_priv, resume); - } else if (IS_CHERRYVIEW(dev)) { + } else if (IS_CHERRYVIEW(dev_priv)) { mutex_lock(&power_domains->lock); chv_phy_control_init(dev_priv); mutex_unlock(&power_domains->lock); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index fefd3034aead..f760d5fcbe48 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -450,7 +450,7 @@ vlv_update_plane(struct drm_plane *dplane, if (key->flags & I915_SET_COLORKEY_SOURCE) sprctl |= SP_SOURCE_KEY; - if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) chv_update_csc(intel_plane, fb->pixel_format); I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); @@ -944,6 +944,7 @@ intel_check_sprite_plane(struct drm_plane *plane, int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_i915_private *dev_priv = to_i915(dev); struct drm_intel_sprite_colorkey *set = data; struct drm_plane *plane; struct drm_plane_state *plane_state; @@ -955,7 +956,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) return -EINVAL; - if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && set->flags & I915_SET_COLORKEY_DESTINATION) return -EINVAL; @@ -1042,6 +1043,7 @@ static uint32_t skl_plane_formats[] = { int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) { + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *intel_plane = NULL; struct intel_plane_state *state = NULL; unsigned long possible_crtcs; @@ -1084,7 +1086,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) case 7: case 8: - if (IS_IVYBRIDGE(to_i915(dev))) { + if (IS_IVYBRIDGE(dev_priv)) { intel_plane->can_scale = true; intel_plane->max_downscale = 2; } else { @@ -1092,7 +1094,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->max_downscale = 1; } - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { intel_plane->update_plane = vlv_update_plane; intel_plane->disable_plane = vlv_disable_plane; -- cgit v1.2.3 From 11a914c28679f19d7daf4218c698ac6c3e184e1a Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:08 +0100 Subject: drm/i915: Make IS_VALLEYVIEW only take dev_priv Saves 944 bytes of .rodata strings and 128 bytes of .text. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem_fence.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 4 ++-- drivers/gpu/drm/i915/intel_crt.c | 6 +++--- drivers/gpu/drm/i915/intel_display.c | 6 +++--- drivers/gpu/drm/i915/intel_dp.c | 8 ++++---- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 3 +-- 9 files changed, 17 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 15e81cf01ce2..38b8efd90fed 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2655,7 +2655,7 @@ struct drm_i915_cmd_table { #define IS_IVB_GT1(dev_priv) (INTEL_DEVID(dev_priv) == 0x0156 || \ INTEL_DEVID(dev_priv) == 0x0152 || \ INTEL_DEVID(dev_priv) == 0x015a) -#define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) +#define IS_VALLEYVIEW(dev_priv) ((dev_priv)->info.is_valleyview) #define IS_CHERRYVIEW(dev_priv) ((dev_priv)->info.is_cherryview) #define IS_HASWELL(dev_priv) ((dev_priv)->info.is_haswell) #define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell) diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index 2c7ba0ee127c..b6591940a0a8 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -465,7 +465,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; - if (INTEL_INFO(dev)->gen >= 8 || IS_VALLEYVIEW(dev)) { + if (INTEL_GEN(dev_priv) >= 8 || IS_VALLEYVIEW(dev_priv)) { /* * On BDW+, swizzling is not used. We leave the CPU memory * controller in charge of optimizing memory accesses without diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index eee2c1102efb..9cdd818c082f 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1424,7 +1424,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, */ /* 1: Registers specific to a single generation */ - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv)) { error->gtier[0] = I915_READ(GTIER); error->ier = I915_READ(VLV_IER); error->forcewake = I915_READ_FW(FORCEWAKE_VLV); @@ -1473,7 +1473,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, error->gtier[0] = I915_READ(GTIER); } else if (IS_GEN2(dev)) { error->ier = I915_READ16(IER); - } else if (!IS_VALLEYVIEW(dev)) { + } else if (!IS_VALLEYVIEW(dev_priv)) { error->ier = I915_READ(IER); } error->eir = I915_READ(EIR); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index d456786f5813..d92c3edf10ff 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -253,7 +253,7 @@ intel_crt_mode_valid(struct drm_connector *connector, if (HAS_PCH_LPT(dev_priv)) max_clock = 180000; - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv)) /* * 270 MHz due to current DPLL limits, * DAC limit supposedly 355 MHz. @@ -423,7 +423,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) if (HAS_PCH_SPLIT(dev_priv)) return intel_ironlake_crt_detect_hotplug(connector); - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv)) return valleyview_crt_detect_hotplug(connector); /* @@ -850,7 +850,7 @@ void intel_crt_init(struct drm_device *dev) if (HAS_PCH_SPLIT(dev_priv)) adpa_reg = PCH_ADPA; - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv)) adpa_reg = VLV_ADPA; else adpa_reg = ADPA; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index aaa1c707f6f1..2f389d333424 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5874,7 +5874,7 @@ static void intel_update_max_cdclk(struct drm_device *dev) dev_priv->max_cdclk_freq = 675000; } else if (IS_CHERRYVIEW(dev_priv)) { dev_priv->max_cdclk_freq = 320000; - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv)) { dev_priv->max_cdclk_freq = 400000; } else { /* otherwise assume cdclk is fixed */ @@ -6838,7 +6838,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) { if (IS_CHERRYVIEW(dev_priv)) chv_disable_pll(dev_priv, pipe); - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv)) vlv_disable_pll(dev_priv, pipe); else i9xx_disable_pll(intel_crtc); @@ -8904,7 +8904,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (IS_CHERRYVIEW(dev_priv)) chv_crtc_clock_get(crtc, pipe_config); - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv)) vlv_crtc_clock_get(crtc, pipe_config); else i9xx_crtc_clock_get(crtc, pipe_config); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 03379baffe49..f6c1c2e00d3f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1350,7 +1350,7 @@ intel_dp_set_clock(struct intel_encoder *encoder, } else if (IS_CHERRYVIEW(dev_priv)) { divisor = chv_dpll; count = ARRAY_SIZE(chv_dpll); - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv)) { divisor = vlv_dpll; count = ARRAY_SIZE(vlv_dpll); } @@ -1790,7 +1790,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, trans_dp &= ~TRANS_DP_ENH_FRAMING; I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); } else { - if (!HAS_PCH_SPLIT(dev_priv) && !IS_VALLEYVIEW(dev) && + if (!HAS_PCH_SPLIT(dev_priv) && !IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) && pipe_config->limited_color_range) intel_dp->DP |= DP_COLOR_RANGE_16_235; @@ -3351,7 +3351,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) mask = DDI_BUF_EMP_MASK; } else if (IS_CHERRYVIEW(dev_priv)) { signal_levels = chv_signal_levels(intel_dp); - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv)) { signal_levels = vlv_signal_levels(intel_dp); } else if (IS_GEN7(dev) && port == PORT_A) { signal_levels = gen7_edp_signal_levels(train_set); @@ -5801,7 +5801,7 @@ bool intel_dp_init(struct drm_device *dev, intel_encoder->enable = vlv_enable_dp; intel_encoder->post_disable = chv_post_disable_dp; intel_encoder->post_pll_disable = chv_dp_post_pll_disable; - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv)) { intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable; intel_encoder->pre_enable = vlv_pre_enable_dp; intel_encoder->enable = vlv_enable_dp; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c8243dc4d2b9..501334242d38 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1965,7 +1965,7 @@ void intel_hdmi_init(struct drm_device *dev, intel_encoder->enable = vlv_enable_hdmi; intel_encoder->post_disable = chv_hdmi_post_disable; intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable; - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv)) { intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; intel_encoder->pre_enable = vlv_hdmi_pre_enable; intel_encoder->enable = vlv_enable_hdmi; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d36b5071e066..8967a8d2378b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7771,7 +7771,7 @@ void intel_init_pm(struct drm_device *dev) } else if (IS_CHERRYVIEW(dev_priv)) { vlv_setup_wm_latency(dev); dev_priv->display.update_wm = vlv_update_wm; - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv)) { vlv_setup_wm_latency(dev); dev_priv->display.update_wm = vlv_update_wm; } else if (IS_PINEVIEW(dev)) { diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 3a6e1a93aed9..ee56a8756c07 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2589,7 +2589,6 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) */ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) { - struct drm_device *dev = &dev_priv->drm; struct i915_power_domains *power_domains = &dev_priv->power_domains; power_domains->initializing = true; @@ -2602,7 +2601,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) mutex_lock(&power_domains->lock); chv_phy_control_init(dev_priv); mutex_unlock(&power_domains->lock); - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv)) { mutex_lock(&power_domains->lock); vlv_cmnlane_wa(dev_priv); mutex_unlock(&power_domains->lock); -- cgit v1.2.3 From 55b8f2a76dff09e0972c93de57cd507ba6237020 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 14 Oct 2016 09:17:22 +0100 Subject: drm/i915: Make INTEL_GEN only take dev_priv Saves 968 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) v3: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem_render_state.c | 6 +++--- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_sprite.c | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 38b8efd90fed..1a4b22918cf0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2600,8 +2600,8 @@ struct drm_i915_cmd_table { __p; \ }) #define INTEL_INFO(p) (&__I915__(p)->info) -#define INTEL_GEN(p) (INTEL_INFO(p)->gen) +#define INTEL_GEN(dev_priv) ((dev_priv)->info.gen) #define INTEL_DEVID(dev_priv) ((dev_priv)->info.device_id) #define REVID_FOREVER 0xff diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 95b7e9afd5f8..a98c0f42badd 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -72,9 +72,9 @@ render_state_get_rodata(const struct drm_i915_gem_request *req) static int render_state_setup(struct render_state *so) { - struct drm_device *dev = so->vma->vm->dev; + struct drm_i915_private *dev_priv = to_i915(so->vma->vm->dev); const struct intel_renderstate_rodata *rodata = so->rodata; - const bool has_64bit_reloc = INTEL_GEN(dev) >= 8; + const bool has_64bit_reloc = INTEL_GEN(dev_priv) >= 8; unsigned int i = 0, reloc_index = 0; struct page *page; u32 *d; @@ -115,7 +115,7 @@ static int render_state_setup(struct render_state *so) so->aux_batch_offset = i * sizeof(u32); - if (HAS_POOLED_EU(dev)) { + if (HAS_POOLED_EU(dev_priv)) { /* * We always program 3x6 pool config but depending upon which * subslice is disabled HW drops down to appropriate config diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d09f16edff76..1de6dd4c602d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2748,7 +2748,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; - uint32_t bit = INTEL_GEN(dev) >= 7 ? + uint32_t bit = INTEL_GEN(dev_priv) >= 7 ? DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); @@ -2798,7 +2798,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; - uint32_t bit = INTEL_GEN(dev) >= 7 ? + uint32_t bit = INTEL_GEN(dev_priv) >= 7 ? DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2f389d333424..3186f181ed85 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12450,7 +12450,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, struct drm_framebuffer *fb = plane_state->fb; int ret; - if (INTEL_GEN(dev) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) { + if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) { ret = skl_update_scaler_plane( to_intel_crtc_state(crtc_state), to_intel_plane_state(plane_state)); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index f760d5fcbe48..8b4748839c07 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -753,7 +753,7 @@ intel_check_sprite_plane(struct drm_plane *plane, struct intel_crtc_state *crtc_state, struct intel_plane_state *state) { - struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = to_i915(plane->dev); struct drm_crtc *crtc = state->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); @@ -797,7 +797,7 @@ intel_check_sprite_plane(struct drm_plane *plane, } /* setup can_scale, min_scale, max_scale */ - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { /* use scaler when colorkey is not required */ if (state->ckey.flags == I915_SET_COLORKEY_NONE) { can_scale = 1; @@ -913,7 +913,7 @@ intel_check_sprite_plane(struct drm_plane *plane, width_bytes = ((src_x * cpp) & 63) + src_w * cpp; - if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 || + if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 || width_bytes > 4096 || fb->pitches[0] > 4096)) { DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); return -EINVAL; @@ -932,7 +932,7 @@ intel_check_sprite_plane(struct drm_plane *plane, dst->y1 = crtc_y; dst->y2 = crtc_y + crtc_h; - if (INTEL_GEN(dev) >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { ret = skl_check_plane_surface(state); if (ret) return ret; -- cgit v1.2.3 From 5db9401983ac7bf9ddc45de54c53ccfa31d21774 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 13 Oct 2016 11:03:10 +0100 Subject: drm/i915: Make IS_GEN macros only take dev_priv Saves 1416 bytes of .rodata strings. v2: Add parantheses around dev_priv. (Ville Syrjala) Signed-off-by: Tvrtko Ursulin Reviewed-by: David Weinehall Acked-by: Daniel Vetter Acked-by: Jani Nikula Acked-by: Chris Wilson Acked-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1476352990-2504-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 6 +-- drivers/gpu/drm/i915/i915_drv.h | 16 +++--- drivers/gpu/drm/i915/i915_gem.c | 8 +-- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 +- drivers/gpu/drm/i915/i915_gem_fence.c | 9 ++-- drivers/gpu/drm/i915/i915_gem_gtt.c | 10 ++-- drivers/gpu/drm/i915/i915_gem_stolen.c | 4 +- drivers/gpu/drm/i915/i915_gem_tiling.c | 4 +- drivers/gpu/drm/i915/i915_gpu_error.c | 10 ++-- drivers/gpu/drm/i915/i915_irq.c | 4 +- drivers/gpu/drm/i915/i915_suspend.c | 4 +- drivers/gpu/drm/i915/intel_crt.c | 6 +-- drivers/gpu/drm/i915/intel_display.c | 41 ++++++++------- drivers/gpu/drm/i915/intel_dp.c | 20 +++---- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_fifo_underrun.c | 6 +-- drivers/gpu/drm/i915/intel_guc_loader.c | 3 +- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 83 +++++++++++++++--------------- drivers/gpu/drm/i915/intel_sprite.c | 4 +- 21 files changed, 126 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b20c1ccbd427..515c206ba653 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4558,7 +4558,7 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) else if (IS_VALLEYVIEW(dev_priv)) num_levels = 1; else - num_levels = ilk_wm_max_level(dev) + 1; + num_levels = ilk_wm_max_level(dev_priv) + 1; drm_modeset_lock_all(dev); @@ -4674,7 +4674,7 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, else if (IS_VALLEYVIEW(dev_priv)) num_levels = 1; else - num_levels = ilk_wm_max_level(dev) + 1; + num_levels = ilk_wm_max_level(dev_priv) + 1; if (len >= sizeof(tmp)) return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1b4cfaa0e0e1..69ff489fb683 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -174,7 +174,7 @@ static void intel_detect_pch(struct drm_device *dev) if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_IBX; DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); - WARN_ON(!IS_GEN5(dev)); + WARN_ON(!IS_GEN5(dev_priv)); } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found CougarPoint PCH\n"); @@ -860,7 +860,7 @@ static int i915_mmio_setup(struct drm_device *dev) int mmio_bar; int mmio_size; - mmio_bar = IS_GEN2(dev) ? 1 : 0; + mmio_bar = IS_GEN2(dev_priv) ? 1 : 0; /* * Before gen4, the registers and the GTT are behind different BARs. * However, from gen4 onwards, the registers and the GTT are shared @@ -1013,7 +1013,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) pci_set_master(pdev); /* overlay on gen2 is broken and can't address above 1G */ - if (IS_GEN2(dev)) { + if (IS_GEN2(dev_priv)) { ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30)); if (ret) { DRM_ERROR("failed to set DMA mask\n"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1a4b22918cf0..fe875b27a6bf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2738,14 +2738,14 @@ struct drm_i915_cmd_table { * have their own (e.g. HAS_PCH_SPLIT for ILK+ display, IS_foo for particular * chips, etc.). */ -#define IS_GEN2(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(1))) -#define IS_GEN3(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(2))) -#define IS_GEN4(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(3))) -#define IS_GEN5(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(4))) -#define IS_GEN6(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(5))) -#define IS_GEN7(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(6))) -#define IS_GEN8(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(7))) -#define IS_GEN9(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(8))) +#define IS_GEN2(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(1))) +#define IS_GEN3(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(2))) +#define IS_GEN4(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(3))) +#define IS_GEN5(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(4))) +#define IS_GEN6(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(5))) +#define IS_GEN7(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(6))) +#define IS_GEN8(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(7))) +#define IS_GEN9(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(8))) #define ENGINE_MASK(id) BIT(id) #define RENDER_RING ENGINE_MASK(RCS) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 16c93cecdab5..cbda30543c70 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4375,15 +4375,15 @@ void i915_gem_init_swizzling(struct drm_device *dev) I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | DISP_TILE_SURFACE_SWIZZLING); - if (IS_GEN5(dev)) + if (IS_GEN5(dev_priv)) return; I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL); - if (IS_GEN6(dev)) + if (IS_GEN6(dev_priv)) I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB)); - else if (IS_GEN7(dev)) + else if (IS_GEN7(dev_priv)) I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB)); - else if (IS_GEN8(dev)) + else if (IS_GEN8(dev_priv)) I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_BDW)); else BUG(); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index fa4d27ca0c18..6a5aea292f7e 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -572,7 +572,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, struct drm_i915_gem_relocation_entry *reloc, struct reloc_cache *cache) { - struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); struct drm_gem_object *target_obj; struct drm_i915_gem_object *target_i915_obj; struct i915_vma *target_vma; @@ -591,7 +591,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and * pipe_control writes because the gpu doesn't properly redirect them * through the ppgtt for non_secure batchbuffers. */ - if (unlikely(IS_GEN6(dev) && + if (unlikely(IS_GEN6(dev_priv) && reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION)) { ret = i915_vma_bind(target_vma, target_i915_obj->cache_level, PIN_GLOBAL); diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index b6591940a0a8..a6daf2deab74 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -504,19 +504,20 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) swizzle_y = I915_BIT_6_SWIZZLE_NONE; } } - } else if (IS_GEN5(dev)) { + } else if (IS_GEN5(dev_priv)) { /* On Ironlake whatever DRAM config, GPU always do * same swizzling setup. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; - } else if (IS_GEN2(dev)) { + } else if (IS_GEN2(dev_priv)) { /* As far as we know, the 865 doesn't have these bit 6 * swizzling issues. */ swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; - } else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) { + } else if (IS_MOBILE(dev_priv) || (IS_GEN3(dev_priv) && + !IS_G33(dev_priv))) { uint32_t dcc; /* On 9xx chipsets, channel interleave by the CPU is @@ -554,7 +555,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) } /* check for L-shaped memory aka modified enhanced addressing */ - if (IS_GEN4(dev) && + if (IS_GEN4(dev_priv) && !(I915_READ(DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) { swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c3c3f28aa5a1..3069b56300ff 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2060,11 +2060,11 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) int ret; ppgtt->base.pte_encode = ggtt->base.pte_encode; - if (intel_vgpu_active(dev_priv) || IS_GEN6(dev)) + if (intel_vgpu_active(dev_priv) || IS_GEN6(dev_priv)) ppgtt->switch_mm = gen6_mm_switch; else if (IS_HASWELL(dev_priv)) ppgtt->switch_mm = hsw_mm_switch; - else if (IS_GEN7(dev)) + else if (IS_GEN7(dev_priv)) ppgtt->switch_mm = gen7_mm_switch; else BUG(); @@ -2161,6 +2161,8 @@ static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt, int i915_ppgtt_init_hw(struct drm_device *dev) { + struct drm_i915_private *dev_priv = to_i915(dev); + gtt_write_workarounds(dev); /* In the case of execlists, PPGTT is enabled by the context descriptor @@ -2172,9 +2174,9 @@ int i915_ppgtt_init_hw(struct drm_device *dev) if (!USES_PPGTT(dev)) return 0; - if (IS_GEN6(dev)) + if (IS_GEN6(dev_priv)) gen6_ppgtt_enable(dev); - else if (IS_GEN7(dev)) + else if (IS_GEN7(dev_priv)) gen7_ppgtt_enable(dev); else if (INTEL_INFO(dev)->gen >= 8) gen8_ppgtt_enable(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index d1b40bce0249..f4f6d3a48b05 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -215,7 +215,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) u64 ggtt_start, ggtt_end; ggtt_start = I915_READ(PGTBL_CTL); - if (IS_GEN4(dev)) + if (IS_GEN4(dev_priv)) ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) | (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28; else @@ -271,7 +271,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) * GEN3 firmware likes to smash pci bridges into the stolen * range. Apparently this works. */ - if (r == NULL && !IS_GEN3(dev)) { + if (r == NULL && !IS_GEN3(dev_priv)) { DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", base, base + (uint32_t)ggtt->stolen_size); base = 0; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 89d1d234a1b4..c21bc0068d20 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -72,7 +72,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) if (tiling_mode > I915_TILING_LAST) return false; - if (IS_GEN2(dev) || + if (IS_GEN2(dev_priv) || (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev_priv))) tile_width = 128; else @@ -91,7 +91,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) if (stride > 8192) return false; - if (IS_GEN3(dev)) { + if (IS_GEN3(dev_priv)) { if (size > I830_FENCE_MAX_SIZE_VAL << 20) return false; } else { diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 9cdd818c082f..e9d282270c72 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -610,7 +610,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg); } - if (IS_GEN7(dev)) + if (IS_GEN7(dev_priv)) err_printf(m, "ERR_INT: 0x%08x\n", error->err_int); for (i = 0; i < ARRAY_SIZE(error->engine); i++) { @@ -1430,7 +1430,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, error->forcewake = I915_READ_FW(FORCEWAKE_VLV); } - if (IS_GEN7(dev)) + if (IS_GEN7(dev_priv)) error->err_int = I915_READ(GEN7_ERR_INT); if (INTEL_INFO(dev)->gen >= 8) { @@ -1438,7 +1438,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, error->fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1); } - if (IS_GEN6(dev)) { + if (IS_GEN6(dev_priv)) { error->forcewake = I915_READ_FW(FORCEWAKE); error->gab_ctl = I915_READ(GAB_CTL); error->gfx_mode = I915_READ(GFX_MODE); @@ -1455,7 +1455,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, } /* 3: Feature specific registers */ - if (IS_GEN6(dev) || IS_GEN7(dev)) { + if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { error->gam_ecochk = I915_READ(GAM_ECOCHK); error->gac_eco = I915_READ(GAC_ECO_BITS); } @@ -1471,7 +1471,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, } else if (HAS_PCH_SPLIT(dev_priv)) { error->ier = I915_READ(DEIER); error->gtier[0] = I915_READ(GTIER); - } else if (IS_GEN2(dev)) { + } else if (IS_GEN2(dev_priv)) { error->ier = I915_READ16(IER); } else if (!IS_VALLEYVIEW(dev_priv)) { error->ier = I915_READ(IER); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1de6dd4c602d..b4a99dd54e6b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3330,7 +3330,7 @@ static void ironlake_irq_reset(struct drm_device *dev) I915_WRITE(HWSTAM, 0xffffffff); GEN5_IRQ_RESET(DE); - if (IS_GEN7(dev)) + if (IS_GEN7(dev_priv)) I915_WRITE(GEN7_ERR_INT, 0xffffffff); gen5_gt_irq_reset(dev); @@ -3596,7 +3596,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) } gt_irqs |= GT_RENDER_USER_INTERRUPT; - if (IS_GEN5(dev)) { + if (IS_GEN5(dev_priv)) { gt_irqs |= ILK_BSD_USER_INTERRUPT; } else { gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 7870856fccd0..344cbf39cfa9 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -70,7 +70,7 @@ int i915_save_state(struct drm_device *dev) i915_save_display(dev); - if (IS_GEN4(dev)) + if (IS_GEN4(dev_priv)) pci_read_config_word(pdev, GCDGMBUS, &dev_priv->regfile.saveGCDGMBUS); @@ -116,7 +116,7 @@ int i915_restore_state(struct drm_device *dev) i915_gem_restore_fences(dev); - if (IS_GEN4(dev)) + if (IS_GEN4(dev_priv)) pci_write_config_word(pdev, GCDGMBUS, dev_priv->regfile.saveGCDGMBUS); i915_restore_display(dev); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index d92c3edf10ff..a97151fcb9f4 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -259,7 +259,7 @@ intel_crt_mode_valid(struct drm_connector *connector, * DAC limit supposedly 355 MHz. */ max_clock = 270000; - else if (IS_GEN3(dev) || IS_GEN4(dev)) + else if (IS_GEN3(dev_priv) || IS_GEN4(dev_priv)) max_clock = 400000; else max_clock = 350000; @@ -567,7 +567,7 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe) /* Set the border color to purple. */ I915_WRITE(bclrpat_reg, 0x500050); - if (!IS_GEN2(dev)) { + if (!IS_GEN2(dev_priv)) { uint32_t pipeconf = I915_READ(pipeconf_reg); I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); POSTING_READ(pipeconf_reg); @@ -899,7 +899,7 @@ void intel_crt_init(struct drm_device *dev) else crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) connector->interlace_allowed = 0; else connector->interlace_allowed = 1; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3186f181ed85..60c699e2c2af 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1045,7 +1045,7 @@ static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe) u32 line1, line2; u32 line_mask; - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) line_mask = DSL_LINEMASK_GEN2; else line_mask = DSL_LINEMASK_GEN3; @@ -3945,7 +3945,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_2; - if (IS_GEN6(dev)) { + if (IS_GEN6(dev_priv)) { temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; /* SNB-B */ temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; @@ -4983,7 +4983,7 @@ intel_post_enable_primary(struct drm_crtc *crtc) * FIXME: Need to fix the logic to work when we turn off all planes * but leave the pipe running. */ - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); /* Underruns don't always raise interrupts, so check manually. */ @@ -5006,7 +5006,7 @@ intel_pre_disable_primary(struct drm_crtc *crtc) * FIXME: Need to fix the logic to work when we turn off all planes * but leave the pipe running. */ - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); /* @@ -6773,7 +6773,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc->active = true; - if (!IS_GEN2(dev)) + if (!IS_GEN2(dev_priv)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); intel_encoders_pre_enable(crtc, pipe_config, old_state); @@ -6821,7 +6821,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, * On gen2 planes are double buffered but the pipe isn't, so we must * wait for planes to fully turn off before disabling the pipe. */ - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) intel_wait_for_vblank(dev, pipe); intel_encoders_disable(crtc, old_crtc_state, old_state); @@ -6846,7 +6846,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state); - if (!IS_GEN2(dev)) + if (!IS_GEN2(dev_priv)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); } @@ -9844,7 +9844,7 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc, /* We currently do not free assignements of panel fitters on * ivb/hsw (since we don't use the higher upscaling modes which * differentiates them) so just WARN about this case for now. */ - if (IS_GEN7(dev)) { + if (IS_GEN7(dev_priv)) { WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) != PF_PIPE_SEL_IVB(crtc->pipe)); } @@ -11320,7 +11320,7 @@ static int i9xx_pll_refclk(struct drm_device *dev, return dev_priv->vbt.lvds_ssc_freq; else if (HAS_PCH_SPLIT(dev_priv)) return 120000; - else if (!IS_GEN2(dev)) + else if (!IS_GEN2(dev_priv)) return 96000; else return 48000; @@ -11353,7 +11353,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; } - if (!IS_GEN2(dev)) { + if (!IS_GEN2(dev_priv)) { if (IS_PINEVIEW(dev)) clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); @@ -11852,6 +11852,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_ring *ring = req->ring; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t plane_bit = 0; @@ -11880,7 +11881,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, * 48bits addresses, and we need a NOOP for the batch size to * stay even. */ - if (IS_GEN8(dev)) + if (IS_GEN8(dev_priv)) len += 2; } @@ -11917,7 +11918,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | DERRMR_PIPEB_PRI_FLIP_DONE | DERRMR_PIPEC_PRI_FLIP_DONE)); - if (IS_GEN8(dev)) + if (IS_GEN8(dev_priv)) intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT); else @@ -11926,7 +11927,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, intel_ring_emit_reg(ring, DERRMR); intel_ring_emit(ring, i915_ggtt_offset(req->engine->scratch) + 256); - if (IS_GEN8(dev)) { + if (IS_GEN8(dev_priv)) { intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_NOOP); } @@ -15320,7 +15321,7 @@ static bool has_edp_a(struct drm_device *dev) if ((I915_READ(DP_A) & DP_DETECTED) == 0) return false; - if (IS_GEN5(dev) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE)) + if (IS_GEN5(dev_priv) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE)) return false; return true; @@ -15522,7 +15523,7 @@ static void intel_setup_outputs(struct drm_device *dev) } intel_dsi_init(dev); - } else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) { + } else if (!IS_GEN2(dev_priv) && !IS_PINEVIEW(dev_priv)) { bool found = false; if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) { @@ -15556,7 +15557,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (IS_G4X(dev_priv) && (I915_READ(DP_D) & DP_DETECTED)) intel_dp_init(dev, DP_D, PORT_D); - } else if (IS_GEN2(dev)) + } else if (IS_GEN2(dev_priv)) intel_dvo_init(dev); if (SUPPORTS_TV(dev)) @@ -16381,10 +16382,10 @@ void intel_modeset_init(struct drm_device *dev) } } - if (IS_GEN2(dev)) { + if (IS_GEN2(dev_priv)) { dev->mode_config.max_width = 2048; dev->mode_config.max_height = 2048; - } else if (IS_GEN3(dev)) { + } else if (IS_GEN3(dev_priv)) { dev->mode_config.max_width = 4096; dev->mode_config.max_height = 4096; } else { @@ -16395,7 +16396,7 @@ void intel_modeset_init(struct drm_device *dev) if (IS_845G(dev_priv) || IS_I865G(dev_priv)) { dev->mode_config.cursor_width = IS_845G(dev_priv) ? 64 : 512; dev->mode_config.cursor_height = 1023; - } else if (IS_GEN2(dev)) { + } else if (IS_GEN2(dev_priv)) { dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH; dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT; } else { @@ -16916,7 +16917,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_wm_get_hw_state(dev); - else if (IS_GEN9(dev)) + else if (IS_GEN9(dev_priv)) skl_wm_get_hw_state(dev); else if (HAS_PCH_SPLIT(dev_priv)) ilk_wm_get_hw_state(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f6c1c2e00d3f..bc03f61d94f1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1767,7 +1767,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, /* Split out the IBX/CPU vs CPT settings */ - if (IS_GEN7(dev) && port == PORT_A) { + if (IS_GEN7(dev_priv) && port == PORT_A) { if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) intel_dp->DP |= DP_SYNC_HS_HIGH; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) @@ -2113,7 +2113,7 @@ static void edp_panel_on(struct intel_dp *intel_dp) pp_ctrl_reg = _pp_ctrl_reg(intel_dp); pp = ironlake_get_pp_control(intel_dp); - if (IS_GEN5(dev)) { + if (IS_GEN5(dev_priv)) { /* ILK workaround: disable reset around power sequence */ pp &= ~PANEL_POWER_RESET; I915_WRITE(pp_ctrl_reg, pp); @@ -2121,7 +2121,7 @@ static void edp_panel_on(struct intel_dp *intel_dp) } pp |= PANEL_POWER_ON; - if (!IS_GEN5(dev)) + if (!IS_GEN5(dev_priv)) pp |= PANEL_POWER_RESET; I915_WRITE(pp_ctrl_reg, pp); @@ -2130,7 +2130,7 @@ static void edp_panel_on(struct intel_dp *intel_dp) wait_panel_on(intel_dp); intel_dp->last_power_on = jiffies; - if (IS_GEN5(dev)) { + if (IS_GEN5(dev_priv)) { pp |= PANEL_POWER_RESET; /* restore panel reset bit */ I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); @@ -2443,7 +2443,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, if (!(tmp & DP_PORT_EN)) goto out; - if (IS_GEN7(dev) && port == PORT_A) { + if (IS_GEN7(dev_priv) && port == PORT_A) { *pipe = PORT_TO_PIPE_CPT(tmp); } else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { enum pipe p; @@ -2661,7 +2661,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, } I915_WRITE(DP_TP_CTL(port), temp); - } else if ((IS_GEN7(dev) && port == PORT_A) || + } else if ((IS_GEN7(dev_priv) && port == PORT_A) || (HAS_PCH_CPT(dev_priv) && port != PORT_A)) { *DP &= ~DP_LINK_TRAIN_MASK_CPT; @@ -2990,7 +2990,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; - else if (IS_GEN7(dev) && port == PORT_A) + else if (IS_GEN7(dev_priv) && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; @@ -3353,10 +3353,10 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) signal_levels = chv_signal_levels(intel_dp); } else if (IS_VALLEYVIEW(dev_priv)) { signal_levels = vlv_signal_levels(intel_dp); - } else if (IS_GEN7(dev) && port == PORT_A) { + } else if (IS_GEN7(dev_priv) && port == PORT_A) { signal_levels = gen7_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; - } else if (IS_GEN6(dev) && port == PORT_A) { + } else if (IS_GEN6(dev_priv) && port == PORT_A) { signal_levels = gen6_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB; } else { @@ -3444,7 +3444,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) DRM_DEBUG_KMS("\n"); - if ((IS_GEN7(dev) && port == PORT_A) || + if ((IS_GEN7(dev_priv) && port == PORT_A) || (HAS_PCH_CPT(dev_priv) && port != PORT_A)) { DP &= ~DP_LINK_TRAIN_MASK_CPT; DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 07b93f23b8bf..a885b2ac9618 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1722,7 +1722,7 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, /* intel_pm.c */ void intel_init_clock_gating(struct drm_device *dev); void intel_suspend_hw(struct drm_device *dev); -int ilk_wm_max_level(const struct drm_device *dev); +int ilk_wm_max_level(const struct drm_i915_private *dev_priv); void intel_update_watermarks(struct drm_crtc *crtc); void intel_init_pm(struct drm_device *dev); void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 076893cc3890..3018f4f589c8 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -256,11 +256,11 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, if (HAS_GMCH_DISPLAY(dev_priv)) i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old); - else if (IS_GEN5(dev) || IS_GEN6(dev)) + else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) ironlake_set_fifo_underrun_reporting(dev, pipe, enable); - else if (IS_GEN7(dev)) + else if (IS_GEN7(dev_priv)) ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old); - else if (IS_GEN8(dev) || IS_GEN9(dev)) + else if (IS_GEN8(dev_priv) || IS_GEN9(dev_priv)) broadwell_set_fifo_underrun_reporting(dev, pipe, enable); return old; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 4a34a607e90e..678b51a24a23 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -349,7 +349,6 @@ static u32 guc_wopcm_size(struct drm_i915_private *dev_priv) static int guc_ucode_xfer(struct drm_i915_private *dev_priv) { struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; - struct drm_device *dev = &dev_priv->drm; struct i915_vma *vma; int ret; @@ -392,7 +391,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) else I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); - if (IS_GEN9(dev)) { + if (IS_GEN9(dev_priv)) { /* DOP Clock Gating Enable for GuC clocks */ I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE | I915_READ(GEN7_MISCCPCTL))); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 1c47f99917e6..199b90c7907a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -1071,7 +1071,7 @@ void intel_lvds_init(struct drm_device *dev) intel_encoder->cloneable = 0; if (HAS_PCH_SPLIT(dev_priv)) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); - else if (IS_GEN4(dev)) + else if (IS_GEN4(dev_priv)) intel_encoder->crtc_mask = (1 << 0) | (1 << 1); else intel_encoder->crtc_mask = (1 << 1); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8967a8d2378b..48b3904c4aeb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1530,7 +1530,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) if (IS_I945GM(dev)) wm_info = &i945_wm_info; - else if (!IS_GEN2(dev)) + else if (!IS_GEN2(dev_priv)) wm_info = &i915_wm_info; else wm_info = &i830_a_wm_info; @@ -1540,7 +1540,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode; int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) cpp = 4; adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; @@ -1554,7 +1554,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) planea_wm = wm_info->max_wm; } - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) wm_info = &i830_bc_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 1); @@ -1562,7 +1562,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode; int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) cpp = 4; adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; @@ -2082,10 +2082,10 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) { struct drm_i915_private *dev_priv = to_i915(dev); - if (IS_GEN9(dev)) { + if (IS_GEN9(dev_priv)) { uint32_t val; int ret, i; - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(dev_priv); /* read the first set of memory latencies[0:3] */ val = 0; /* data0 to be programmed to 0 for first set */ @@ -2184,10 +2184,11 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) } } -static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5]) +static void intel_fixup_spr_wm_latency(struct drm_i915_private *dev_priv, + uint16_t wm[5]) { /* ILK sprite LP0 latency is 1300 ns */ - if (IS_GEN5(dev)) + if (IS_GEN5(dev_priv)) wm[0] = 13; } @@ -2203,10 +2204,8 @@ static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv, wm[3] *= 2; } -int ilk_wm_max_level(const struct drm_device *dev) +int ilk_wm_max_level(const struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - /* how many WM levels are we expecting */ if (INTEL_GEN(dev_priv) >= 9) return 7; @@ -2218,11 +2217,11 @@ int ilk_wm_max_level(const struct drm_device *dev) return 2; } -static void intel_print_wm_latency(struct drm_device *dev, +static void intel_print_wm_latency(struct drm_i915_private *dev_priv, const char *name, const uint16_t wm[8]) { - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(dev_priv); for (level = 0; level <= max_level; level++) { unsigned int latency = wm[level]; @@ -2237,7 +2236,7 @@ static void intel_print_wm_latency(struct drm_device *dev, * - latencies are in us on gen9. * - before then, WM1+ latency values are in 0.5us units */ - if (IS_GEN9(dev)) + if (IS_GEN9(dev_priv)) latency *= 10; else if (level > 0) latency *= 5; @@ -2251,7 +2250,7 @@ static void intel_print_wm_latency(struct drm_device *dev, static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv, uint16_t wm[5], uint16_t min) { - int level, max_level = ilk_wm_max_level(&dev_priv->drm); + int level, max_level = ilk_wm_max_level(dev_priv); if (wm[0] >= min) return false; @@ -2280,9 +2279,9 @@ static void snb_wm_latency_quirk(struct drm_device *dev) return; DRM_DEBUG_KMS("WM latency values increased to avoid potential underruns\n"); - intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency); - intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency); - intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); + intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); + intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); + intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); } static void ilk_setup_wm_latency(struct drm_device *dev) @@ -2296,14 +2295,14 @@ static void ilk_setup_wm_latency(struct drm_device *dev) memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency, sizeof(dev_priv->wm.pri_latency)); - intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency); + intel_fixup_spr_wm_latency(dev_priv, dev_priv->wm.spr_latency); intel_fixup_cur_wm_latency(dev_priv, dev_priv->wm.cur_latency); - intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency); - intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency); - intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); + intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); + intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); + intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); - if (IS_GEN6(dev)) + if (IS_GEN6(dev_priv)) snb_wm_latency_quirk(dev); } @@ -2312,7 +2311,7 @@ static void skl_setup_wm_latency(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); intel_read_wm_latency(dev, dev_priv->wm.skl_latency); - intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency); + intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency); } static bool ilk_validate_pipe_wm(struct drm_device *dev, @@ -2350,7 +2349,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) struct intel_plane_state *pristate = NULL; struct intel_plane_state *sprstate = NULL; struct intel_plane_state *curstate = NULL; - int level, max_level = ilk_wm_max_level(dev), usable_level; + int level, max_level = ilk_wm_max_level(dev_priv), usable_level; struct ilk_wm_maximums max; pipe_wm = &cstate->wm.ilk.optimal; @@ -2437,7 +2436,7 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev, { struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate; struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk; - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(to_i915(dev)); /* * Start with the final, target watermarks, then combine with the @@ -2521,7 +2520,7 @@ static void ilk_wm_merge(struct drm_device *dev, struct intel_pipe_wm *merged) { struct drm_i915_private *dev_priv = to_i915(dev); - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(dev_priv); int last_enabled_level = max_level; /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */ @@ -2561,7 +2560,7 @@ static void ilk_wm_merge(struct drm_device *dev, * What we should check here is whether FBC can be * enabled sometime later. */ - if (IS_GEN5(dev) && !merged->fbc_wm_enabled && + if (IS_GEN5(dev_priv) && !merged->fbc_wm_enabled && intel_fbc_is_active(dev_priv)) { for (level = 2; level <= max_level; level++) { struct intel_wm_level *wm = &merged->wm[level]; @@ -2661,7 +2660,7 @@ static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev, struct intel_pipe_wm *r1, struct intel_pipe_wm *r2) { - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(to_i915(dev)); int level1 = 0, level2 = 0; for (level = 1; level <= max_level; level++) { @@ -3035,7 +3034,7 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) continue; /* Find the highest enabled wm level for this plane */ - for (level = ilk_wm_max_level(dev); + for (level = ilk_wm_max_level(dev_priv); intel_state->wm_results.plane[pipe][plane][level] == 0; --level) { } @@ -3778,7 +3777,7 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, { struct drm_device *dev = cstate->base.crtc->dev; const struct drm_i915_private *dev_priv = to_i915(dev); - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(dev_priv); int ret; for (level = 0; level <= max_level; level++) { @@ -3799,7 +3798,7 @@ static void skl_compute_wm_results(struct drm_device *dev, struct skl_wm_values *r, struct intel_crtc *intel_crtc) { - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(to_i915(dev)); enum pipe pipe = intel_crtc->pipe; uint32_t temp; int i; @@ -3868,7 +3867,7 @@ void skl_write_plane_wm(struct intel_crtc *intel_crtc, struct drm_crtc *crtc = &intel_crtc->base; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(dev_priv); enum pipe pipe = intel_crtc->pipe; for (level = 0; level <= max_level; level++) { @@ -3889,7 +3888,7 @@ void skl_write_cursor_wm(struct intel_crtc *intel_crtc, struct drm_crtc *crtc = &intel_crtc->base; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(dev_priv); enum pipe pipe = intel_crtc->pipe; for (level = 0; level <= max_level; level++) { @@ -4339,7 +4338,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) int level, i, max_level; uint32_t temp; - max_level = ilk_wm_max_level(dev); + max_level = ilk_wm_max_level(dev_priv); hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); @@ -4439,7 +4438,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK; active->linetime = hw->wm_linetime[pipe]; } else { - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(dev_priv); /* * For inactive pipes, all watermark levels @@ -7742,7 +7741,7 @@ void intel_init_pm(struct drm_device *dev) /* For cxsr */ if (IS_PINEVIEW(dev)) i915_pineview_get_mem_freq(dev); - else if (IS_GEN5(dev)) + else if (IS_GEN5(dev_priv)) i915_ironlake_get_mem_freq(dev); /* For FIFO watermark updates */ @@ -7753,9 +7752,9 @@ void intel_init_pm(struct drm_device *dev) } else if (HAS_PCH_SPLIT(dev_priv)) { ilk_setup_wm_latency(dev); - if ((IS_GEN5(dev) && dev_priv->wm.pri_latency[1] && + if ((IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[1] && dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) || - (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] && + (!IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[0] && dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm; dev_priv->display.compute_intermediate_wm = @@ -7791,12 +7790,12 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.update_wm = pineview_update_wm; } else if (IS_G4X(dev_priv)) { dev_priv->display.update_wm = g4x_update_wm; - } else if (IS_GEN4(dev)) { + } else if (IS_GEN4(dev_priv)) { dev_priv->display.update_wm = i965_update_wm; - } else if (IS_GEN3(dev)) { + } else if (IS_GEN3(dev_priv)) { dev_priv->display.update_wm = i9xx_update_wm; dev_priv->display.get_fifo_size = i9xx_get_fifo_size; - } else if (IS_GEN2(dev)) { + } else if (IS_GEN2(dev_priv)) { if (INTEL_INFO(dev)->num_pipes == 1) { dev_priv->display.update_wm = i845_update_wm; dev_priv->display.get_fifo_size = i845_get_fifo_size; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 8b4748839c07..c7d9a20e370d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -680,7 +680,7 @@ ilk_update_plane(struct drm_plane *plane, if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) dvscntr |= DVS_TILED; - if (IS_GEN6(dev)) + if (IS_GEN6(dev_priv)) dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ /* Sizes are 0 based */ @@ -1075,7 +1075,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->update_plane = ilk_update_plane; intel_plane->disable_plane = ilk_disable_plane; - if (IS_GEN6(dev)) { + if (IS_GEN6(dev_priv)) { plane_formats = snb_plane_formats; num_plane_formats = ARRAY_SIZE(snb_plane_formats); } else { -- cgit v1.2.3 From 4c494a5769cd0de92638b25960ba0158c36088a6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 13 Oct 2016 14:34:06 +0300 Subject: drm/i915: Fix mismatched INIT power domain disabling during suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the display INIT power domain disabling/enabling happens in a mismatched way in the suspend/resume_early hooks respectively. This can leave display power wells incorrectly disabled in the resume hook if the suspend sequence is aborted for some reason resulting in the suspend/resume hooks getting called but the suspend_late/resume_early hooks being skipped. In particular this change fixes "Unclaimed read from register 0x1e1204" on BYT/BSW triggered from i915_drm_resume()-> intel_pps_unlock_regs_wa() when suspending with /sys/power/pm_test set to devices. Fixes: 85e90679335f ("drm/i915: disable power wells on suspend") Cc: Ville Syrjälä Cc: David Weinehall Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1476358446-11621-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 69ff489fb683..1fddc2ccada2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1437,8 +1437,6 @@ static int i915_drm_suspend(struct drm_device *dev) dev_priv->suspend_count++; - intel_display_set_init_power(dev_priv, false); - intel_csr_ucode_suspend(dev_priv); out: @@ -1456,6 +1454,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) disable_rpm_wakeref_asserts(dev_priv); + intel_display_set_init_power(dev_priv, false); + fw_csr = !IS_BROXTON(dev_priv) && suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; /* -- cgit v1.2.3 From 4fb84d991ef2172d425234391d7215978345f6cd Mon Sep 17 00:00:00 2001 From: Michał Winiarski Date: Thu, 13 Oct 2016 14:02:40 +0200 Subject: drm/i915: Remove unused "valid" parameter from pte_encode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We never used any invalid ptes, those were put in place for a possibility of doing gpu faults. However our batchbuffers are not restricted in length, so everything needs to be pointing to something and thus out-of-bounds is pointing to scratch. Remove the valid flag as it is always true. v2: Expand commit msg, patch reorder (Mika) Cc: Chris Wilson Cc: Michel Thierry Reviewed-by: Joonas Lahtinen Reviewed-by: Mika Kuoppala Signed-off-by: Michał Winiarski Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1476360162-24062-1-git-send-email-michal.winiarski@intel.com --- drivers/gpu/drm/i915/i915_gem.c | 6 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 98 ++++++++++++------------------ drivers/gpu/drm/i915/i915_gem_gtt.h | 5 +- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- 5 files changed, 46 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cbda30543c70..fe92e28ea0a8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -919,8 +919,7 @@ out_unpin: if (node.allocated) { wmb(); ggtt->base.clear_range(&ggtt->base, - node.start, node.size, - true); + node.start, node.size); i915_gem_object_unpin_pages(obj); remove_mappable_node(&node); } else { @@ -1228,8 +1227,7 @@ out_unpin: if (node.allocated) { wmb(); ggtt->base.clear_range(&ggtt->base, - node.start, node.size, - true); + node.start, node.size); i915_gem_object_unpin_pages(obj); remove_mappable_node(&node); } else { diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 6a5aea292f7e..1d02e74ce62d 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -370,8 +370,7 @@ static void reloc_cache_fini(struct reloc_cache *cache) ggtt->base.clear_range(&ggtt->base, cache->node.start, - cache->node.size, - true); + cache->node.size); drm_mm_remove_node(&cache->node); } else { i915_vma_unpin((struct i915_vma *)cache->node.mm); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 3069b56300ff..6de50e44954d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -191,15 +191,13 @@ static void ppgtt_unbind_vma(struct i915_vma *vma) { vma->vm->clear_range(vma->vm, vma->node.start, - vma->size, - true); + vma->size); } static gen8_pte_t gen8_pte_encode(dma_addr_t addr, - enum i915_cache_level level, - bool valid) + enum i915_cache_level level) { - gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0; + gen8_pte_t pte = _PAGE_PRESENT | _PAGE_RW; pte |= addr; switch (level) { @@ -234,9 +232,9 @@ static gen8_pde_t gen8_pde_encode(const dma_addr_t addr, static gen6_pte_t snb_pte_encode(dma_addr_t addr, enum i915_cache_level level, - bool valid, u32 unused) + u32 unused) { - gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; + gen6_pte_t pte = GEN6_PTE_VALID; pte |= GEN6_PTE_ADDR_ENCODE(addr); switch (level) { @@ -256,9 +254,9 @@ static gen6_pte_t snb_pte_encode(dma_addr_t addr, static gen6_pte_t ivb_pte_encode(dma_addr_t addr, enum i915_cache_level level, - bool valid, u32 unused) + u32 unused) { - gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; + gen6_pte_t pte = GEN6_PTE_VALID; pte |= GEN6_PTE_ADDR_ENCODE(addr); switch (level) { @@ -280,9 +278,9 @@ static gen6_pte_t ivb_pte_encode(dma_addr_t addr, static gen6_pte_t byt_pte_encode(dma_addr_t addr, enum i915_cache_level level, - bool valid, u32 flags) + u32 flags) { - gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; + gen6_pte_t pte = GEN6_PTE_VALID; pte |= GEN6_PTE_ADDR_ENCODE(addr); if (!(flags & PTE_READ_ONLY)) @@ -296,9 +294,9 @@ static gen6_pte_t byt_pte_encode(dma_addr_t addr, static gen6_pte_t hsw_pte_encode(dma_addr_t addr, enum i915_cache_level level, - bool valid, u32 unused) + u32 unused) { - gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; + gen6_pte_t pte = GEN6_PTE_VALID; pte |= HSW_PTE_ADDR_ENCODE(addr); if (level != I915_CACHE_NONE) @@ -309,9 +307,9 @@ static gen6_pte_t hsw_pte_encode(dma_addr_t addr, static gen6_pte_t iris_pte_encode(dma_addr_t addr, enum i915_cache_level level, - bool valid, u32 unused) + u32 unused) { - gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; + gen6_pte_t pte = GEN6_PTE_VALID; pte |= HSW_PTE_ADDR_ENCODE(addr); switch (level) { @@ -474,7 +472,7 @@ static void gen8_initialize_pt(struct i915_address_space *vm, gen8_pte_t scratch_pte; scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC, true); + I915_CACHE_LLC); fill_px(to_i915(vm->dev), pt, scratch_pte); } @@ -487,7 +485,7 @@ static void gen6_initialize_pt(struct i915_address_space *vm, WARN_ON(vm->scratch_page.daddr == 0); scratch_pte = vm->pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC, true, 0); + I915_CACHE_LLC, 0); fill32_px(to_i915(vm->dev), pt, scratch_pte); } @@ -765,13 +763,11 @@ static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm, } static void gen8_ppgtt_clear_range(struct i915_address_space *vm, - uint64_t start, - uint64_t length, - bool use_scratch) + uint64_t start, uint64_t length) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC, use_scratch); + I915_CACHE_LLC); if (!USES_FULL_48BIT_PPGTT(vm->dev)) { gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length, @@ -811,7 +807,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, pt_vaddr[pte] = gen8_pte_encode(sg_page_iter_dma_address(sg_iter), - cache_level, true); + cache_level); if (++pte == GEN8_PTES) { kunmap_px(ppgtt, pt_vaddr); pt_vaddr = NULL; @@ -1454,7 +1450,7 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) uint64_t start = ppgtt->base.start; uint64_t length = ppgtt->base.total; gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC, true); + I915_CACHE_LLC); if (!USES_FULL_48BIT_PPGTT(vm->dev)) { gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m); @@ -1571,7 +1567,7 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) uint32_t start = ppgtt->base.start, length = ppgtt->base.total; scratch_pte = vm->pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC, true, 0); + I915_CACHE_LLC, 0); gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde) { u32 expected; @@ -1786,8 +1782,7 @@ static void gen6_ppgtt_enable(struct drm_device *dev) /* PPGTT support for Sandybdrige/Gen6 and later */ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, uint64_t start, - uint64_t length, - bool use_scratch) + uint64_t length) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); gen6_pte_t *pt_vaddr, scratch_pte; @@ -1798,7 +1793,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, unsigned last_pte, i; scratch_pte = vm->pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC, true, 0); + I915_CACHE_LLC, 0); while (num_entries) { last_pte = first_pte + num_entries; @@ -1836,7 +1831,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]); pt_vaddr[act_pte] = - vm->pte_encode(addr, cache_level, true, flags); + vm->pte_encode(addr, cache_level, flags); if (++act_pte == GEN6_PTES) { kunmap_px(ppgtt, pt_vaddr); @@ -2296,8 +2291,7 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) i915_check_and_clear_faults(dev_priv); - ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total, - true); + ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total); i915_ggtt_flush(dev_priv); } @@ -2331,7 +2325,7 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm, rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); - gen8_set_pte(pte, gen8_pte_encode(addr, level, true)); + gen8_set_pte(pte, gen8_pte_encode(addr, level)); I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); @@ -2358,7 +2352,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); for_each_sgt_dma(addr, sgt_iter, st) { - gtt_entry = gen8_pte_encode(addr, level, true); + gtt_entry = gen8_pte_encode(addr, level); gen8_set_pte(>t_entries[i++], gtt_entry); } @@ -2422,7 +2416,7 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm, rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); - iowrite32(vm->pte_encode(addr, level, true, flags), pte); + iowrite32(vm->pte_encode(addr, level, flags), pte); I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); @@ -2455,7 +2449,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); for_each_sgt_dma(addr, sgt_iter, st) { - gtt_entry = vm->pte_encode(addr, level, true, flags); + gtt_entry = vm->pte_encode(addr, level, flags); iowrite32(gtt_entry, >t_entries[i++]); } @@ -2479,16 +2473,12 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, } static void nop_clear_range(struct i915_address_space *vm, - uint64_t start, - uint64_t length, - bool use_scratch) + uint64_t start, uint64_t length) { } static void gen8_ggtt_clear_range(struct i915_address_space *vm, - uint64_t start, - uint64_t length, - bool use_scratch) + uint64_t start, uint64_t length) { struct drm_i915_private *dev_priv = to_i915(vm->dev); struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); @@ -2508,8 +2498,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, num_entries = max_entries; scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC, - use_scratch); + I915_CACHE_LLC); for (i = 0; i < num_entries; i++) gen8_set_pte(>t_base[i], scratch_pte); readl(gtt_base); @@ -2519,8 +2508,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, static void gen6_ggtt_clear_range(struct i915_address_space *vm, uint64_t start, - uint64_t length, - bool use_scratch) + uint64_t length) { struct drm_i915_private *dev_priv = to_i915(vm->dev); struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); @@ -2540,7 +2528,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, num_entries = max_entries; scratch_pte = vm->pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC, use_scratch, 0); + I915_CACHE_LLC, 0); for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); @@ -2587,8 +2575,7 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm, static void i915_ggtt_clear_range(struct i915_address_space *vm, uint64_t start, - uint64_t length, - bool unused) + uint64_t length) { struct drm_i915_private *dev_priv = to_i915(vm->dev); unsigned first_entry = start >> PAGE_SHIFT; @@ -2672,13 +2659,11 @@ static void ggtt_unbind_vma(struct i915_vma *vma) if (vma->flags & I915_VMA_GLOBAL_BIND) vma->vm->clear_range(vma->vm, - vma->node.start, size, - true); + vma->node.start, size); if (vma->flags & I915_VMA_LOCAL_BIND && appgtt) appgtt->base.clear_range(&appgtt->base, - vma->node.start, size, - true); + vma->node.start, size); } void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) @@ -2749,13 +2734,12 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", hole_start, hole_end); ggtt->base.clear_range(&ggtt->base, hole_start, - hole_end - hole_start, true); + hole_end - hole_start); } /* And finally clear the reserved guard page */ ggtt->base.clear_range(&ggtt->base, - ggtt->base.total - PAGE_SIZE, PAGE_SIZE, - true); + ggtt->base.total - PAGE_SIZE, PAGE_SIZE); if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) { ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); @@ -2777,8 +2761,7 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) ppgtt->base.clear_range(&ppgtt->base, ppgtt->base.start, - ppgtt->base.total, - true); + ppgtt->base.total); dev_priv->mm.aliasing_ppgtt = ppgtt; WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma); @@ -3264,8 +3247,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) i915_check_and_clear_faults(dev_priv); /* First fill our portion of the GTT with scratch pages */ - ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total, - true); + ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total); ggtt->base.closed = true; /* skip rewriting PTE on VMA unbind */ diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index bd93fb8f99d2..c241d8143255 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -395,7 +395,7 @@ struct i915_address_space { /* FIXME: Need a more generic return type */ gen6_pte_t (*pte_encode)(dma_addr_t addr, enum i915_cache_level level, - bool valid, u32 flags); /* Create a valid PTE */ + u32 flags); /* Create a valid PTE */ /* flags for pte_encode */ #define PTE_READ_ONLY (1<<0) int (*allocate_va_range)(struct i915_address_space *vm, @@ -403,8 +403,7 @@ struct i915_address_space { uint64_t length); void (*clear_range)(struct i915_address_space *vm, uint64_t start, - uint64_t length, - bool use_scratch); + uint64_t length); void (*insert_page)(struct i915_address_space *vm, dma_addr_t addr, uint64_t offset, diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index e9d282270c72..a8ce358850d1 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -848,7 +848,7 @@ unwind: out: compress_fini(&zstream, dst); - ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE, true); + ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE); return dst; } -- cgit v1.2.3 From d209b9c3cd281e4543e1150d173388b6d8f29a42 Mon Sep 17 00:00:00 2001 From: Michał Winiarski Date: Thu, 13 Oct 2016 14:02:41 +0200 Subject: drm/i915/gtt: Split gen8_ppgtt_clear_pte_range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's use more top-down approach, where each gen8_ppgtt_clear_* function is responsible for clearing the struct passed as an argument and calling relevant clear_range functions on lower-level tables. Doing this rather than operating on PTE ranges makes the implementation of shrinking page tables quite simple. v2: Drop min when calculating num_entries, no negation in 48b ppgtt check, no newlines in vars block (Joonas) Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Michel Thierry Cc: Mika Kuoppala Signed-off-by: Michał Winiarski Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1476360162-24062-2-git-send-email-michal.winiarski@intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.c | 107 +++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6de50e44954d..2350fdfe38c4 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -706,59 +706,78 @@ static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt, return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4)); } -static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm, - struct i915_page_directory_pointer *pdp, - uint64_t start, - uint64_t length, - gen8_pte_t scratch_pte) +static void gen8_ppgtt_clear_pt(struct i915_address_space *vm, + struct i915_page_table *pt, + uint64_t start, + uint64_t length) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); + + unsigned int pte_start = gen8_pte_index(start); + unsigned int num_entries = gen8_pte_count(start, length); + uint64_t pte; gen8_pte_t *pt_vaddr; - unsigned pdpe = gen8_pdpe_index(start); - unsigned pde = gen8_pde_index(start); - unsigned pte = gen8_pte_index(start); - unsigned num_entries = length >> PAGE_SHIFT; - unsigned last_pte, i; + gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, + I915_CACHE_LLC); - if (WARN_ON(!pdp)) + if (WARN_ON(!px_page(pt))) return; - while (num_entries) { - struct i915_page_directory *pd; - struct i915_page_table *pt; + bitmap_clear(pt->used_ptes, pte_start, num_entries); - if (WARN_ON(!pdp->page_directory[pdpe])) - break; + pt_vaddr = kmap_px(pt); + + for (pte = pte_start; pte < num_entries; pte++) + pt_vaddr[pte] = scratch_pte; - pd = pdp->page_directory[pdpe]; + kunmap_px(ppgtt, pt_vaddr); +} + +static void gen8_ppgtt_clear_pd(struct i915_address_space *vm, + struct i915_page_directory *pd, + uint64_t start, + uint64_t length) +{ + struct i915_page_table *pt; + uint64_t pde; + gen8_for_each_pde(pt, pd, start, length, pde) { if (WARN_ON(!pd->page_table[pde])) break; - pt = pd->page_table[pde]; + gen8_ppgtt_clear_pt(vm, pt, start, length); + } +} - if (WARN_ON(!px_page(pt))) - break; +static void gen8_ppgtt_clear_pdp(struct i915_address_space *vm, + struct i915_page_directory_pointer *pdp, + uint64_t start, + uint64_t length) +{ + struct i915_page_directory *pd; + uint64_t pdpe; - last_pte = pte + num_entries; - if (last_pte > GEN8_PTES) - last_pte = GEN8_PTES; + gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { + if (WARN_ON(!pdp->page_directory[pdpe])) + break; - pt_vaddr = kmap_px(pt); + gen8_ppgtt_clear_pd(vm, pd, start, length); + } +} - for (i = pte; i < last_pte; i++) { - pt_vaddr[i] = scratch_pte; - num_entries--; - } +static void gen8_ppgtt_clear_pml4(struct i915_address_space *vm, + struct i915_pml4 *pml4, + uint64_t start, + uint64_t length) +{ + struct i915_page_directory_pointer *pdp; + uint64_t pml4e; - kunmap_px(ppgtt, pt_vaddr); + gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) { + if (WARN_ON(!pml4->pdps[pml4e])) + break; - pte = 0; - if (++pde == I915_PDES) { - if (++pdpe == I915_PDPES_PER_PDP(vm->dev)) - break; - pde = 0; - } + gen8_ppgtt_clear_pdp(vm, pdp, start, length); } } @@ -766,21 +785,11 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, uint64_t start, uint64_t length) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, - I915_CACHE_LLC); - if (!USES_FULL_48BIT_PPGTT(vm->dev)) { - gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length, - scratch_pte); - } else { - uint64_t pml4e; - struct i915_page_directory_pointer *pdp; - - gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) { - gen8_ppgtt_clear_pte_range(vm, pdp, start, length, - scratch_pte); - } - } + if (USES_FULL_48BIT_PPGTT(vm->dev)) + gen8_ppgtt_clear_pml4(vm, &ppgtt->pml4, start, length); + else + gen8_ppgtt_clear_pdp(vm, &ppgtt->pdp, start, length); } static void -- cgit v1.2.3 From 2ce5179fe8260f8ad60da4d3f594cfda3f9ad57b Mon Sep 17 00:00:00 2001 From: Michał Winiarski Date: Thu, 13 Oct 2016 14:02:42 +0200 Subject: drm/i915/gtt: Free unused lower-level page tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since "Dynamic page table allocations" were introduced, our page tables can grow (being dynamically allocated) with address space range usage. Unfortunately, their lifetime is bound to vm. This is not a huge problem when we're not using softpin - drm_mm is creating an upper bound on used range by causing addresses for our VMAs to eventually be reused. With softpin, long lived contexts can drain the system out of memory even with a single "small" object. For example: bo = bo_alloc(size); while(true) offset += size; exec(bo, offset); Will cause us to create new allocations until all memory in the system is used for tracking GPU pages (even though almost all PTEs in this vm are pointing to scratch). Let's free unused page tables in clear_range to prevent this - if no entries are used, we can safely free it and return this information to the caller (so that higher-level entry is pointing to scratch). v2: Document return value and free semantics (Joonas) v3: No newlines in vars block (Joonas) v4: Drop redundant local 'reduce' variable v5: Handle CI fail with enable_ppgtt=2 Cc: Michel Thierry Cc: Mika Kuoppala Reviewed-by: Chris Wilson Reviewed-by: Joonas Lahtinen Signed-off-by: Michał Winiarski Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1476360162-24062-3-git-send-email-michal.winiarski@intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.c | 81 +++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2350fdfe38c4..062fb0ad75da 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -706,13 +706,15 @@ static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt, return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4)); } -static void gen8_ppgtt_clear_pt(struct i915_address_space *vm, +/* Removes entries from a single page table, releasing it if it's empty. + * Caller can use the return value to update higher-level entries. + */ +static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm, struct i915_page_table *pt, uint64_t start, uint64_t length) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - unsigned int pte_start = gen8_pte_index(start); unsigned int num_entries = gen8_pte_count(start, length); uint64_t pte; @@ -721,63 +723,126 @@ static void gen8_ppgtt_clear_pt(struct i915_address_space *vm, I915_CACHE_LLC); if (WARN_ON(!px_page(pt))) - return; + return false; bitmap_clear(pt->used_ptes, pte_start, num_entries); + if (bitmap_empty(pt->used_ptes, GEN8_PTES)) { + free_pt(vm->dev, pt); + return true; + } + pt_vaddr = kmap_px(pt); for (pte = pte_start; pte < num_entries; pte++) pt_vaddr[pte] = scratch_pte; kunmap_px(ppgtt, pt_vaddr); + + return false; } -static void gen8_ppgtt_clear_pd(struct i915_address_space *vm, +/* Removes entries from a single page dir, releasing it if it's empty. + * Caller can use the return value to update higher-level entries + */ +static bool gen8_ppgtt_clear_pd(struct i915_address_space *vm, struct i915_page_directory *pd, uint64_t start, uint64_t length) { + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); struct i915_page_table *pt; uint64_t pde; + gen8_pde_t *pde_vaddr; + gen8_pde_t scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), + I915_CACHE_LLC); gen8_for_each_pde(pt, pd, start, length, pde) { if (WARN_ON(!pd->page_table[pde])) break; - gen8_ppgtt_clear_pt(vm, pt, start, length); + if (gen8_ppgtt_clear_pt(vm, pt, start, length)) { + __clear_bit(pde, pd->used_pdes); + pde_vaddr = kmap_px(pd); + pde_vaddr[pde] = scratch_pde; + kunmap_px(ppgtt, pde_vaddr); + } + } + + if (bitmap_empty(pd->used_pdes, I915_PDES)) { + free_pd(vm->dev, pd); + return true; } + + return false; } -static void gen8_ppgtt_clear_pdp(struct i915_address_space *vm, +/* Removes entries from a single page dir pointer, releasing it if it's empty. + * Caller can use the return value to update higher-level entries + */ +static bool gen8_ppgtt_clear_pdp(struct i915_address_space *vm, struct i915_page_directory_pointer *pdp, uint64_t start, uint64_t length) { + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); struct i915_page_directory *pd; uint64_t pdpe; + gen8_ppgtt_pdpe_t *pdpe_vaddr; + gen8_ppgtt_pdpe_t scratch_pdpe = + gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC); gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { if (WARN_ON(!pdp->page_directory[pdpe])) break; - gen8_ppgtt_clear_pd(vm, pd, start, length); + if (gen8_ppgtt_clear_pd(vm, pd, start, length)) { + __clear_bit(pdpe, pdp->used_pdpes); + if (USES_FULL_48BIT_PPGTT(vm->dev)) { + pdpe_vaddr = kmap_px(pdp); + pdpe_vaddr[pdpe] = scratch_pdpe; + kunmap_px(ppgtt, pdpe_vaddr); + } + } + } + + if (USES_FULL_48BIT_PPGTT(vm->dev) && + bitmap_empty(pdp->used_pdpes, I915_PDPES_PER_PDP(vm->dev))) { + free_pdp(vm->dev, pdp); + return true; } + + return false; } +/* Removes entries from a single pml4. + * This is the top-level structure in 4-level page tables used on gen8+. + * Empty entries are always scratch pml4e. + */ static void gen8_ppgtt_clear_pml4(struct i915_address_space *vm, struct i915_pml4 *pml4, uint64_t start, uint64_t length) { + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); struct i915_page_directory_pointer *pdp; uint64_t pml4e; + gen8_ppgtt_pml4e_t *pml4e_vaddr; + gen8_ppgtt_pml4e_t scratch_pml4e = + gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC); + + GEM_BUG_ON(!USES_FULL_48BIT_PPGTT(vm->dev)); gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) { if (WARN_ON(!pml4->pdps[pml4e])) break; - gen8_ppgtt_clear_pdp(vm, pdp, start, length); + if (gen8_ppgtt_clear_pdp(vm, pdp, start, length)) { + __clear_bit(pml4e, pml4->used_pml4es); + pml4e_vaddr = kmap_px(pml4); + pml4e_vaddr[pml4e] = scratch_pml4e; + kunmap_px(ppgtt, pml4e_vaddr); + } } } -- cgit v1.2.3 From ba18a9314a94f4a54b4d0c5e0f1dc85af28eca35 Mon Sep 17 00:00:00 2001 From: David Arcari Date: Thu, 13 Oct 2016 11:30:44 +0200 Subject: Revert "HID: i2c-hid: Add support for ACPI GPIO interrupts" This reverts commit a485923efbb8 ("HID: i2c-hid: Add support for ACPI GPIO interrupts") and commit a7d2bf25a483 ("HID: i2c-hid: Do not fail probing if gpiolib is not enabled") at the same time. Since commit c884fbd45214 ("gpio / ACPI: Add support for retrieving GpioInt resources from a device") i2c_core already set the IRQ by looking into the ACPI tree and retrieving the gpioInt. So we just have some boiler-plate here that is not needed anymore. The only downside effect here is that now we are not exiting early enough if the irq is set to -EPROBE_DEFER or any other error, but this is going to be fixed in the following patch. Signed-off-by: David Arcari Signed-off-by: Benjamin Tissoires Reviewed-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 71 +++++++++++-------------------------------- 1 file changed, 18 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index b3ec4f2de875..4cd606c0d89c 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -37,7 +37,6 @@ #include #include #include -#include #include @@ -145,8 +144,6 @@ struct i2c_hid { unsigned long flags; /* device flags */ wait_queue_head_t wait; /* For waiting the interrupt */ - struct gpio_desc *desc; - int irq; struct i2c_hid_platform_data pdata; @@ -808,16 +805,16 @@ static int i2c_hid_init_irq(struct i2c_client *client) struct i2c_hid *ihid = i2c_get_clientdata(client); int ret; - dev_dbg(&client->dev, "Requesting IRQ: %d\n", ihid->irq); + dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq); - ret = request_threaded_irq(ihid->irq, NULL, i2c_hid_irq, + ret = request_threaded_irq(client->irq, NULL, i2c_hid_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ihid); if (ret < 0) { dev_warn(&client->dev, "Could not register for %s interrupt, irq = %d," " ret = %d\n", - client->name, ihid->irq, ret); + client->name, client->irq, ret); return ret; } @@ -864,14 +861,6 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid) } #ifdef CONFIG_ACPI - -/* Default GPIO mapping */ -static const struct acpi_gpio_params i2c_hid_irq_gpio = { 0, 0, true }; -static const struct acpi_gpio_mapping i2c_hid_acpi_gpios[] = { - { "gpios", &i2c_hid_irq_gpio, 1 }, - { }, -}; - static int i2c_hid_acpi_pdata(struct i2c_client *client, struct i2c_hid_platform_data *pdata) { @@ -882,7 +871,6 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, union acpi_object *obj; struct acpi_device *adev; acpi_handle handle; - int ret; handle = ACPI_HANDLE(&client->dev); if (!handle || acpi_bus_get_device(handle, &adev)) @@ -898,9 +886,7 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, pdata->hid_descriptor_address = obj->integer.value; ACPI_FREE(obj); - /* GPIOs are optional */ - ret = acpi_dev_add_driver_gpios(adev, i2c_hid_acpi_gpios); - return ret < 0 && ret != -ENXIO ? ret : 0; + return 0; } static const struct acpi_device_id i2c_hid_acpi_match[] = { @@ -964,6 +950,12 @@ static int i2c_hid_probe(struct i2c_client *client, dbg_hid("HID probe called for i2c 0x%02x\n", client->addr); + if (!client->irq) { + dev_err(&client->dev, + "HID over i2c has not been provided an Int IRQ\n"); + return -EINVAL; + } + ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL); if (!ihid) return -ENOMEM; @@ -983,23 +975,6 @@ static int i2c_hid_probe(struct i2c_client *client, ihid->pdata = *platform_data; } - if (client->irq > 0) { - ihid->irq = client->irq; - } else if (ACPI_COMPANION(&client->dev)) { - ihid->desc = gpiod_get(&client->dev, NULL, GPIOD_IN); - if (IS_ERR(ihid->desc)) { - dev_err(&client->dev, "Failed to get GPIO interrupt\n"); - return PTR_ERR(ihid->desc); - } - - ihid->irq = gpiod_to_irq(ihid->desc); - if (ihid->irq < 0) { - gpiod_put(ihid->desc); - dev_err(&client->dev, "Failed to convert GPIO to IRQ\n"); - return ihid->irq; - } - } - i2c_set_clientdata(client, ihid); ihid->client = client; @@ -1064,16 +1039,13 @@ err_mem_free: hid_destroy_device(hid); err_irq: - free_irq(ihid->irq, ihid); + free_irq(client->irq, ihid); err_pm: pm_runtime_put_noidle(&client->dev); pm_runtime_disable(&client->dev); err: - if (ihid->desc) - gpiod_put(ihid->desc); - i2c_hid_free_buffers(ihid); kfree(ihid); return ret; @@ -1092,18 +1064,13 @@ static int i2c_hid_remove(struct i2c_client *client) hid = ihid->hid; hid_destroy_device(hid); - free_irq(ihid->irq, ihid); + free_irq(client->irq, ihid); if (ihid->bufsize) i2c_hid_free_buffers(ihid); - if (ihid->desc) - gpiod_put(ihid->desc); - kfree(ihid); - acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev)); - return 0; } @@ -1142,11 +1109,11 @@ static int i2c_hid_suspend(struct device *dev) /* Save some power */ i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); - disable_irq(ihid->irq); + disable_irq(client->irq); } if (device_may_wakeup(&client->dev)) { - wake_status = enable_irq_wake(ihid->irq); + wake_status = enable_irq_wake(client->irq); if (!wake_status) ihid->irq_wake_enabled = true; else @@ -1166,7 +1133,7 @@ static int i2c_hid_resume(struct device *dev) int wake_status; if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) { - wake_status = disable_irq_wake(ihid->irq); + wake_status = disable_irq_wake(client->irq); if (!wake_status) ihid->irq_wake_enabled = false; else @@ -1179,7 +1146,7 @@ static int i2c_hid_resume(struct device *dev) pm_runtime_set_active(dev); pm_runtime_enable(dev); - enable_irq(ihid->irq); + enable_irq(client->irq); ret = i2c_hid_hwreset(client); if (ret) return ret; @@ -1197,19 +1164,17 @@ static int i2c_hid_resume(struct device *dev) static int i2c_hid_runtime_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct i2c_hid *ihid = i2c_get_clientdata(client); i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); - disable_irq(ihid->irq); + disable_irq(client->irq); return 0; } static int i2c_hid_runtime_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct i2c_hid *ihid = i2c_get_clientdata(client); - enable_irq(ihid->irq); + enable_irq(client->irq); i2c_hid_set_power(client, I2C_HID_PWR_ON); return 0; } -- cgit v1.2.3 From 93d26aeab54cc91119760bc4f1f22bff9a987d70 Mon Sep 17 00:00:00 2001 From: David Arcari Date: Thu, 13 Oct 2016 11:30:45 +0200 Subject: HID: i2c-hid: exit if the IRQ is not valid When i2c-core doesn't find the IRQ associated to the GPIO because the gpiochip is not available, it assigns -EPROBE_DEFER to the irq. We need to bail out there and on any other error in an IRQ. Signed-off-by: David Arcari Signed-off-by: Benjamin Tissoires Reviewed-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 4cd606c0d89c..fe6b4e0eab4a 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -956,6 +956,13 @@ static int i2c_hid_probe(struct i2c_client *client, return -EINVAL; } + if (client->irq < 0) { + if (client->irq != -EPROBE_DEFER) + dev_err(&client->dev, + "HID over i2c doesn't have a valid IRQ\n"); + return client->irq; + } + ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL); if (!ihid) return -ENOMEM; -- cgit v1.2.3 From 4f58e6dceb0e44ca8f21568ed81e1df24e55964c Mon Sep 17 00:00:00 2001 From: "Allan W. Nielsen" Date: Wed, 12 Oct 2016 15:47:51 +0200 Subject: net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs. Edge-Rate cleanup include the following: - Updated device tree bindings documentation for edge-rate - The edge-rate is now specified as a "slowdown", meaning that it is now being specified as positive values instead of negative (both documentation and implementation wise). - Only explicitly documented values for "vsc8531,vddmac" and "vsc8531,edge-slowdown" are accepted by the device driver. - Deleted include/dt-bindings/net/mscc-phy-vsc8531.h as it was not needed. - Read/validate devicetree settings in probe instead of init Signed-off-by: Allan W. Nielsen Signed-off-by: Raju Lakkaraju Signed-off-by: David S. Miller --- .../devicetree/bindings/net/mscc-phy-vsc8531.txt | 51 ++++---- drivers/net/phy/mscc.c | 135 ++++++++++----------- include/dt-bindings/net/mscc-phy-vsc8531.h | 21 ---- 3 files changed, 90 insertions(+), 117 deletions(-) delete mode 100644 include/dt-bindings/net/mscc-phy-vsc8531.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt b/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt index 99c7eb0a00c8..bdefefc66594 100644 --- a/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt +++ b/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt @@ -6,22 +6,27 @@ Required properties: Documentation/devicetree/bindings/net/phy.txt Optional properties: -- vsc8531,vddmac : The vddmac in mV. +- vsc8531,vddmac : The vddmac in mV. Allowed values is listed + in the first row of Table 1 (below). + This property is only used in combination + with the 'edge-slowdown' property. + Default value is 3300. - vsc8531,edge-slowdown : % the edge should be slowed down relative to - the fastest possible edge time. Native sign - need not enter. + the fastest possible edge time. Edge rate sets the drive strength of the MAC - interface output signals. Changing the drive - strength will affect the edge rate of the output - signal. The goal of this setting is to help - reduce electrical emission (EMI) by being able - to reprogram drive strength and in effect slow - down the edge rate if desired. Table 1 shows the - impact to the edge rate per VDDMAC supply for each - drive strength setting. - Ref: Table:1 - Edge rate change below. - -Note: see dt-bindings/net/mscc-phy-vsc8531.h for applicable values + interface output signals. Changing the + drive strength will affect the edge rate of + the output signal. The goal of this setting + is to help reduce electrical emission (EMI) + by being able to reprogram drive strength + and in effect slow down the edge rate if + desired. + To adjust the edge-slowdown, the 'vddmac' + must be specified. Table 1 lists the + supported edge-slowdown values for a given + 'vddmac'. + Default value is 0%. + Ref: Table:1 - Edge rate change (below). Table: 1 - Edge rate change ----------------------------------------------------------------| @@ -29,23 +34,23 @@ Table: 1 - Edge rate change | | | 3300 mV 2500 mV 1800 mV 1500 mV | |---------------------------------------------------------------| -| Default Deafult Default Default | +| 0% 0% 0% 0% | | (Fastest) (recommended) (recommended) | |---------------------------------------------------------------| -| -2% -3% -5% -6% | +| 2% 3% 5% 6% | |---------------------------------------------------------------| -| -4% -6% -9% -14% | +| 4% 6% 9% 14% | |---------------------------------------------------------------| -| -7% -10% -16% -21% | +| 7% 10% 16% 21% | |(recommended) (recommended) | |---------------------------------------------------------------| -| -10% -14% -23% -29% | +| 10% 14% 23% 29% | |---------------------------------------------------------------| -| -17% -23% -35% -42% | +| 17% 23% 35% 42% | |---------------------------------------------------------------| -| -29% -37% -52% -58% | +| 29% 37% 52% 58% | |---------------------------------------------------------------| -| -53% -63% -76% -77% | +| 53% 63% 76% 77% | | (slowest) | |---------------------------------------------------------------| @@ -54,5 +59,5 @@ Example: vsc8531_0: ethernet-phy@0 { compatible = "ethernet-phy-id0007.0570"; vsc8531,vddmac = <3300>; - vsc8531,edge-slowdown = <21>; + vsc8531,edge-slowdown = <7>; }; diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index 77a6671d572e..113616b92abb 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -12,7 +12,6 @@ #include #include #include -#include #include enum rgmii_rx_clock_delay { @@ -69,23 +68,29 @@ enum rgmii_rx_clock_delay { #define PHY_ID_VSC8531 0x00070570 #define PHY_ID_VSC8541 0x00070770 -struct edge_rate_table { - u16 vddmac; - int slowdown[MSCC_SLOWDOWN_MAX]; -}; +#define MSCC_VDDMAC_1500 1500 +#define MSCC_VDDMAC_1800 1800 +#define MSCC_VDDMAC_2500 2500 +#define MSCC_VDDMAC_3300 3300 -struct edge_rate_table edge_table[MSCC_VDDMAC_MAX] = { - {3300, { 0, -2, -4, -7, -10, -17, -29, -53} }, - {2500, { 0, -3, -6, -10, -14, -23, -37, -63} }, - {1800, { 0, -5, -9, -16, -23, -35, -52, -76} }, - {1500, { 0, -6, -14, -21, -29, -42, -58, -77} }, +struct vsc8531_private { + int rate_magic; }; -struct vsc8531_private { - u8 edge_slowdown; +#ifdef CONFIG_OF_MDIO +struct vsc8531_edge_rate_table { u16 vddmac; + u8 slowdown[8]; }; +static const struct vsc8531_edge_rate_table edge_table[] = { + {MSCC_VDDMAC_3300, { 0, 2, 4, 7, 10, 17, 29, 53} }, + {MSCC_VDDMAC_2500, { 0, 3, 6, 10, 14, 23, 37, 63} }, + {MSCC_VDDMAC_1800, { 0, 5, 9, 16, 23, 35, 52, 76} }, + {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} }, +}; +#endif /* CONFIG_OF_MDIO */ + static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page) { int rc; @@ -205,29 +210,43 @@ out_unlock: mutex_unlock(&phydev->lock); } -static u8 edge_rate_magic_get(u16 vddmac, - int slowdown) +#ifdef CONFIG_OF_MDIO +static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev) { - int rc = (MSCC_SLOWDOWN_MAX - 1); - u8 vdd; u8 sd; + u16 vdd; + int rc, i, j; + struct device *dev = &phydev->mdio.dev; + struct device_node *of_node = dev->of_node; + u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown); - for (vdd = 0; vdd < MSCC_VDDMAC_MAX; vdd++) { - if (edge_table[vdd].vddmac == vddmac) { - for (sd = 0; sd < MSCC_SLOWDOWN_MAX; sd++) { - if (edge_table[vdd].slowdown[sd] <= slowdown) { - rc = (MSCC_SLOWDOWN_MAX - sd - 1); - break; - } - } - } - } + if (!of_node) + return -ENODEV; - return rc; + rc = of_property_read_u16(of_node, "vsc8531,vddmac", &vdd); + if (rc != 0) + vdd = MSCC_VDDMAC_3300; + + rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown", &sd); + if (rc != 0) + sd = 0; + + for (i = 0; i < ARRAY_SIZE(edge_table); i++) + if (edge_table[i].vddmac == vdd) + for (j = 0; j < sd_array_size; j++) + if (edge_table[i].slowdown[j] == sd) + return (sd_array_size - j - 1); + + return -EINVAL; +} +#else +static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev) +{ + return 0; } +#endif /* CONFIG_OF_MDIO */ -static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, - u8 edge_rate) +static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate) { int rc; u16 reg_val; @@ -308,45 +327,10 @@ out_unlock: return rc; } -#ifdef CONFIG_OF_MDIO -static int vsc8531_of_init(struct phy_device *phydev) -{ - int rc; - struct vsc8531_private *vsc8531 = phydev->priv; - struct device *dev = &phydev->mdio.dev; - struct device_node *of_node = dev->of_node; - - if (!of_node) - return -ENODEV; - - rc = of_property_read_u16(of_node, "vsc8531,vddmac", - &vsc8531->vddmac); - if (rc == -EINVAL) - vsc8531->vddmac = MSCC_VDDMAC_3300; - rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown", - &vsc8531->edge_slowdown); - if (rc == -EINVAL) - vsc8531->edge_slowdown = 0; - - rc = 0; - return rc; -} -#else -static int vsc8531_of_init(struct phy_device *phydev) -{ - return 0; -} -#endif /* CONFIG_OF_MDIO */ - static int vsc85xx_config_init(struct phy_device *phydev) { int rc; struct vsc8531_private *vsc8531 = phydev->priv; - u8 edge_rate; - - rc = vsc8531_of_init(phydev); - if (rc) - return rc; rc = vsc85xx_default_config(phydev); if (rc) @@ -356,9 +340,7 @@ static int vsc85xx_config_init(struct phy_device *phydev) if (rc) return rc; - edge_rate = edge_rate_magic_get(vsc8531->vddmac, - -(int)vsc8531->edge_slowdown); - rc = vsc85xx_edge_rate_cntl_set(phydev, edge_rate); + rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic); if (rc) return rc; @@ -396,14 +378,21 @@ static int vsc85xx_config_intr(struct phy_device *phydev) static int vsc85xx_probe(struct phy_device *phydev) { + int rate_magic; struct vsc8531_private *vsc8531; + rate_magic = vsc85xx_edge_rate_magic_get(phydev); + if (rate_magic < 0) + return rate_magic; + vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); if (!vsc8531) return -ENOMEM; phydev->priv = vsc8531; + vsc8531->rate_magic = rate_magic; + return 0; } @@ -424,9 +413,9 @@ static struct phy_driver vsc85xx_driver[] = { .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, - .probe = &vsc85xx_probe, - .set_wol = &vsc85xx_wol_set, - .get_wol = &vsc85xx_wol_get, + .probe = &vsc85xx_probe, + .set_wol = &vsc85xx_wol_set, + .get_wol = &vsc85xx_wol_get, }, { .phy_id = PHY_ID_VSC8541, @@ -443,9 +432,9 @@ static struct phy_driver vsc85xx_driver[] = { .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, - .probe = &vsc85xx_probe, - .set_wol = &vsc85xx_wol_set, - .get_wol = &vsc85xx_wol_get, + .probe = &vsc85xx_probe, + .set_wol = &vsc85xx_wol_set, + .get_wol = &vsc85xx_wol_get, } }; diff --git a/include/dt-bindings/net/mscc-phy-vsc8531.h b/include/dt-bindings/net/mscc-phy-vsc8531.h deleted file mode 100644 index 2383dd20ff43..000000000000 --- a/include/dt-bindings/net/mscc-phy-vsc8531.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Device Tree constants for Microsemi VSC8531 PHY - * - * Author: Nagaraju Lakkaraju - * - * License: Dual MIT/GPL - * Copyright (c) 2016 Microsemi Corporation - */ - -#ifndef _DT_BINDINGS_MSCC_VSC8531_H -#define _DT_BINDINGS_MSCC_VSC8531_H - -/* MAC interface Edge rate control VDDMAC in milli Volts */ -#define MSCC_VDDMAC_3300 3300 -#define MSCC_VDDMAC_2500 2500 -#define MSCC_VDDMAC_1800 1800 -#define MSCC_VDDMAC_1500 1500 -#define MSCC_VDDMAC_MAX 4 -#define MSCC_SLOWDOWN_MAX 8 - -#endif -- cgit v1.2.3 From 5724b8b5694794829a071c6da7dd0bc146df0756 Mon Sep 17 00:00:00 2001 From: Shmulik Ladkani Date: Thu, 13 Oct 2016 09:06:43 +0300 Subject: net/sched: tc_mirred: Rename public predicates 'is_tcf_mirred_redirect' and 'is_tcf_mirred_mirror' These accessors are used in various drivers that support tc offloading, to detect properties of a given 'tc_action'. 'is_tcf_mirred_redirect' tests that the action is TCA_EGRESS_REDIR. 'is_tcf_mirred_mirror' tests that the action is TCA_EGRESS_MIRROR. As a prep towards supporting INGRESS redir/mirror, rename these predicates to reflect their true meaning: s/is_tcf_mirred_redirect/is_tcf_mirred_egress_redirect/ s/is_tcf_mirred_mirror/is_tcf_mirred_egress_mirror/ Signed-off-by: Shmulik Ladkani Cc: Hariprasad S Cc: Jeff Kirsher Cc: Saeed Mahameed Cc: Jiri Pirko Cc: Ido Schimmel Cc: Jakub Kicinski Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 +++- drivers/net/ethernet/netronome/nfp/nfp_net_offload.c | 2 +- include/net/tc_act/tc_mirred.h | 4 ++-- 6 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c index 49d2debb334e..52af62e0ecb6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c @@ -113,7 +113,7 @@ static int fill_action_fields(struct adapter *adap, } /* Re-direct to specified port in hardware. */ - if (is_tcf_mirred_redirect(a)) { + if (is_tcf_mirred_egress_redirect(a)) { struct net_device *n_dev; unsigned int i, index; bool found = false; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index a244d9a67264..784b0b98ab2f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -8410,7 +8410,7 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter, } /* Redirect to a VF or a offloaded macvlan */ - if (is_tcf_mirred_redirect(a)) { + if (is_tcf_mirred_egress_redirect(a)) { int ifindex = tcf_mirred_ifindex(a); err = handle_redirect_action(adapter, ifindex, queue, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index ce8c54d18906..135a95bcc392 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -404,7 +404,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, continue; } - if (is_tcf_mirred_redirect(a)) { + if (is_tcf_mirred_egress_redirect(a)) { int ifindex = tcf_mirred_ifindex(a); struct net_device *out_dev; struct mlx5e_priv *out_priv; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 1ec0a4ce3c46..43a5eddc2c11 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1237,8 +1237,10 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port, tcf_exts_to_list(cls->exts, &actions); list_for_each_entry(a, &actions, list) { - if (!is_tcf_mirred_mirror(a) || protocol != htons(ETH_P_ALL)) + if (!is_tcf_mirred_egress_mirror(a) || + protocol != htons(ETH_P_ALL)) { return -ENOTSUPP; + } err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port, cls, a, ingress); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c b/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c index 8acfb631a0ea..cfed40c0e310 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c @@ -128,7 +128,7 @@ nfp_net_bpf_get_act(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf) if (is_tcf_gact_shot(a)) return NN_ACT_TC_DROP; - if (is_tcf_mirred_redirect(a) && + if (is_tcf_mirred_egress_redirect(a) && tcf_mirred_ifindex(a) == nn->netdev->ifindex) return NN_ACT_TC_REDIR; } diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h index 95431092c4b6..604bc31e23ab 100644 --- a/include/net/tc_act/tc_mirred.h +++ b/include/net/tc_act/tc_mirred.h @@ -14,7 +14,7 @@ struct tcf_mirred { }; #define to_mirred(a) ((struct tcf_mirred *)a) -static inline bool is_tcf_mirred_redirect(const struct tc_action *a) +static inline bool is_tcf_mirred_egress_redirect(const struct tc_action *a) { #ifdef CONFIG_NET_CLS_ACT if (a->ops && a->ops->type == TCA_ACT_MIRRED) @@ -23,7 +23,7 @@ static inline bool is_tcf_mirred_redirect(const struct tc_action *a) return false; } -static inline bool is_tcf_mirred_mirror(const struct tc_action *a) +static inline bool is_tcf_mirred_egress_mirror(const struct tc_action *a) { #ifdef CONFIG_NET_CLS_ACT if (a->ops && a->ops->type == TCA_ACT_MIRRED) -- cgit v1.2.3 From c3aaa403840a5ccd305fb5e73f3cbfac6453b5e5 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Fri, 14 Oct 2016 05:19:17 -0400 Subject: qed: Pass MAC hints to VFs Some hypervisors can support MAC hints to their VFs. Even though we don't have such a hypervisor API in linux, we add sufficient logic for the VF to be able to receive such hints and set the mac accordingly - as long as the VF has not been set with a MAC already. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_vf.c | 4 ++-- drivers/net/ethernet/qlogic/qede/qede_main.c | 6 +++++- include/linux/qed/qed_eth_if.h | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c index abf5bf11f865..f580bf4c97f0 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.c +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c @@ -1230,8 +1230,8 @@ static void qed_handle_bulletin_change(struct qed_hwfn *hwfn) is_mac_exist = qed_vf_bulletin_get_forced_mac(hwfn, mac, &is_mac_forced); - if (is_mac_exist && is_mac_forced && cookie) - ops->force_mac(cookie, mac); + if (is_mac_exist && cookie) + ops->force_mac(cookie, mac, !!is_mac_forced); /* Always update link configuration according to bulletin */ qed_link_update(hwfn); diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 343038ca047d..9866d952e3e1 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -171,10 +171,14 @@ static struct pci_driver qede_pci_driver = { #endif }; -static void qede_force_mac(void *dev, u8 *mac) +static void qede_force_mac(void *dev, u8 *mac, bool forced) { struct qede_dev *edev = dev; + /* MAC hints take effect only if we haven't set one already */ + if (is_valid_ether_addr(edev->ndev->dev_addr) && !forced) + return; + ether_addr_copy(edev->ndev->dev_addr, mac); ether_addr_copy(edev->primary_mac, mac); } diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h index 33c24ebc9b7f..1c779486c30d 100644 --- a/include/linux/qed/qed_eth_if.h +++ b/include/linux/qed/qed_eth_if.h @@ -129,7 +129,7 @@ struct qed_tunn_params { struct qed_eth_cb_ops { struct qed_common_cb_ops common; - void (*force_mac) (void *dev, u8 *mac); + void (*force_mac) (void *dev, u8 *mac, bool forced); }; #ifdef CONFIG_DCB -- cgit v1.2.3 From a150241ccf31f8606f5ceb2208fd421066c17e07 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 14 Oct 2016 05:19:18 -0400 Subject: qede: GSO support for tunnels with outer csum This patch adds GSO support for GRE and UDP tunnels where outer checksums are enabled. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede.h | 1 + drivers/net/ethernet/qlogic/qede/qede_main.c | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 28c0e9f42c9e..f50e5270ad30 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -320,6 +320,7 @@ struct qede_fastpath { #define XMIT_L4_CSUM BIT(0) #define XMIT_LSO BIT(1) #define XMIT_ENC BIT(2) +#define XMIT_ENC_GSO_L4_CSUM BIT(3) #define QEDE_CSUM_ERROR BIT(0) #define QEDE_CSUM_UNNECESSARY BIT(1) diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 9866d952e3e1..7d5dc1e15fc4 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -400,8 +400,19 @@ static u32 qede_xmit_type(struct qede_dev *edev, (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6)) *ipv6_ext = 1; - if (skb->encapsulation) + if (skb->encapsulation) { rc |= XMIT_ENC; + if (skb_is_gso(skb)) { + unsigned short gso_type = skb_shinfo(skb)->gso_type; + + if ((gso_type & SKB_GSO_UDP_TUNNEL_CSUM) || + (gso_type & SKB_GSO_GRE_CSUM)) + rc |= XMIT_ENC_GSO_L4_CSUM; + + rc |= XMIT_LSO; + return rc; + } + } if (skb_is_gso(skb)) rc |= XMIT_LSO; @@ -637,6 +648,12 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb, if (unlikely(xmit_type & XMIT_ENC)) { first_bd->data.bd_flags.bitfields |= 1 << ETH_TX_1ST_BD_FLAGS_TUNN_IP_CSUM_SHIFT; + + if (xmit_type & XMIT_ENC_GSO_L4_CSUM) { + u8 tmp = ETH_TX_1ST_BD_FLAGS_TUNN_L4_CSUM_SHIFT; + + first_bd->data.bd_flags.bitfields |= 1 << tmp; + } hlen = qede_get_skb_hlen(skb, true); } else { first_bd->data.bd_flags.bitfields |= @@ -2320,11 +2337,14 @@ static void qede_init_ndev(struct qede_dev *edev) /* Encap features*/ hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_TSO_ECN; + NETIF_F_TSO_ECN | NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_GSO_GRE_CSUM; ndev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GSO_GRE | - NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM; + NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_GSO_GRE_CSUM; ndev->vlan_features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM | NETIF_F_HIGHDMA; -- cgit v1.2.3 From 256958538ae2616e4aa14efab8c0d11df1e188db Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 14 Oct 2016 05:19:19 -0400 Subject: qede: Prevent GSO on long Geneve headers Due to hardware limitation, when transmitting a geneve-encapsulated packet with more than 32 bytes worth of geneve options the hardware would not be able to crack the packet and consider it a regular UDP packet. This implements the ndo_features_check() in qede in order to prevent GSO on said transmitted packets. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede_main.c | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 7d5dc1e15fc4..6c2b09c255d5 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -2240,6 +2240,40 @@ static void qede_udp_tunnel_del(struct net_device *dev, schedule_delayed_work(&edev->sp_task, 0); } +/* 8B udp header + 8B base tunnel header + 32B option length */ +#define QEDE_MAX_TUN_HDR_LEN 48 + +static netdev_features_t qede_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + if (skb->encapsulation) { + u8 l4_proto = 0; + + switch (vlan_get_protocol(skb)) { + case htons(ETH_P_IP): + l4_proto = ip_hdr(skb)->protocol; + break; + case htons(ETH_P_IPV6): + l4_proto = ipv6_hdr(skb)->nexthdr; + break; + default: + return features; + } + + /* Disable offloads for geneve tunnels, as HW can't parse + * the geneve header which has option length greater than 32B. + */ + if ((l4_proto == IPPROTO_UDP) && + ((skb_inner_mac_header(skb) - + skb_transport_header(skb)) > QEDE_MAX_TUN_HDR_LEN)) + return features & ~(NETIF_F_CSUM_MASK | + NETIF_F_GSO_MASK); + } + + return features; +} + static const struct net_device_ops qede_netdev_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, @@ -2264,6 +2298,7 @@ static const struct net_device_ops qede_netdev_ops = { #endif .ndo_udp_tunnel_add = qede_udp_tunnel_add, .ndo_udp_tunnel_del = qede_udp_tunnel_del, + .ndo_features_check = qede_features_check, }; /* ------------------------------------------------------------------------- -- cgit v1.2.3 From 7b7e70f979e34ed84d725eab8ea42921ab6f42e3 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Fri, 14 Oct 2016 05:19:20 -0400 Subject: qed*: Allow unicast filtering Apparently qede fails to set IFF_UNICAST_FLT, and as a result is not actually performing unicast MAC filtering. While we're at it - relax a hard-coded limitation that limits each interface into using at most 15 unicast MAC addresses before turning promiscuous. Instead utilize the HW resources to their limit. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_l2.c | 12 ++++++++++-- drivers/net/ethernet/qlogic/qede/qede_main.c | 4 +++- include/linux/qed/qed_eth_if.h | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index ddd410a91e13..6b0e22d9fe4c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1652,6 +1652,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev, if (IS_PF(cdev)) { int max_vf_vlan_filters = 0; + int max_vf_mac_filters = 0; if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { for_each_hwfn(cdev, i) @@ -1665,11 +1666,18 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev, info->num_queues = cdev->num_hwfns; } - if (IS_QED_SRIOV(cdev)) + if (IS_QED_SRIOV(cdev)) { max_vf_vlan_filters = cdev->p_iov_info->total_vfs * QED_ETH_VF_NUM_VLAN_FILTERS; - info->num_vlan_filters = RESC_NUM(&cdev->hwfns[0], QED_VLAN) - + max_vf_mac_filters = cdev->p_iov_info->total_vfs * + QED_ETH_VF_NUM_MAC_FILTERS; + } + info->num_vlan_filters = RESC_NUM(QED_LEADING_HWFN(cdev), + QED_VLAN) - max_vf_vlan_filters; + info->num_mac_filters = RESC_NUM(QED_LEADING_HWFN(cdev), + QED_MAC) - + max_vf_mac_filters; ether_addr_copy(info->port_mac, cdev->hwfns[0].hw_info.hw_mac_addr); diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 6c2b09c255d5..0e483afc2b87 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -2365,6 +2365,8 @@ static void qede_init_ndev(struct qede_dev *edev) qede_set_ethtool_ops(ndev); + ndev->priv_flags = IFF_UNICAST_FLT; + /* user-changeble features */ hw_features = NETIF_F_GRO | NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | @@ -3937,7 +3939,7 @@ static void qede_config_rx_mode(struct net_device *ndev) /* Check for promiscuous */ if ((ndev->flags & IFF_PROMISC) || - (uc_count > 15)) { /* @@@TBD resource allocation - 1 */ + (uc_count > edev->dev_info.num_mac_filters - 1)) { accept_flags = QED_FILTER_RX_MODE_TYPE_PROMISC; } else { /* Add MAC filters according to the unicast secondary macs */ diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h index 1c779486c30d..15130805d792 100644 --- a/include/linux/qed/qed_eth_if.h +++ b/include/linux/qed/qed_eth_if.h @@ -23,6 +23,7 @@ struct qed_dev_eth_info { u8 port_mac[ETH_ALEN]; u8 num_vlan_filters; + u16 num_mac_filters; /* Legacy VF - this affects the datapath, so qede has to know */ bool is_legacy; -- cgit v1.2.3 From c59f5291fd63f9892c8f1d4b94247aeea92305c5 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Fri, 14 Oct 2016 05:19:21 -0400 Subject: qed: Allow chance for fast ramrod completions Whenever a ramrod is being sent for some device configuration, the driver is going to sleep at least 5ms between each iteration of polling on the completion of the ramrod. However, in almost every configuration scenario the firmware would be able to comply and complete the ramrod in a manner of several usecs. This is especially important in cases where there might be a lot of sequential configurations applying to the hardware [e.g., RoCE], in which case the existing scheme might cause some visible user delays. This patch changes the completion scheme - instead of immediately starting to sleep for a 'long' period, allow the device to quickly poll on the first iteration after a couple of usecs. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_spq.c | 85 +++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index caff41544898..259a6156c761 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -37,7 +37,11 @@ ***************************************************************************/ #define SPQ_HIGH_PRI_RESERVE_DEFAULT (1) -#define SPQ_BLOCK_SLEEP_LENGTH (1000) + +#define SPQ_BLOCK_DELAY_MAX_ITER (10) +#define SPQ_BLOCK_DELAY_US (10) +#define SPQ_BLOCK_SLEEP_MAX_ITER (1000) +#define SPQ_BLOCK_SLEEP_MS (5) /*************************************************************************** * Blocking Imp. (BLOCK/EBLOCK mode) @@ -57,53 +61,81 @@ static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn, smp_wmb(); } -static int qed_spq_block(struct qed_hwfn *p_hwfn, - struct qed_spq_entry *p_ent, - u8 *p_fw_ret) +static int __qed_spq_block(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent, + u8 *p_fw_ret, bool sleep_between_iter) { - int sleep_count = SPQ_BLOCK_SLEEP_LENGTH; struct qed_spq_comp_done *comp_done; - int rc; + u32 iter_cnt; comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie; - while (sleep_count) { - /* validate we receive completion update */ + iter_cnt = sleep_between_iter ? SPQ_BLOCK_SLEEP_MAX_ITER + : SPQ_BLOCK_DELAY_MAX_ITER; + + while (iter_cnt--) { + /* Validate we receive completion update */ smp_rmb(); if (comp_done->done == 1) { if (p_fw_ret) *p_fw_ret = comp_done->fw_return_code; return 0; } - usleep_range(5000, 10000); - sleep_count--; + + if (sleep_between_iter) + msleep(SPQ_BLOCK_SLEEP_MS); + else + udelay(SPQ_BLOCK_DELAY_US); } + return -EBUSY; +} + +static int qed_spq_block(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent, + u8 *p_fw_ret, bool skip_quick_poll) +{ + struct qed_spq_comp_done *comp_done; + int rc; + + /* A relatively short polling period w/o sleeping, to allow the FW to + * complete the ramrod and thus possibly to avoid the following sleeps. + */ + if (!skip_quick_poll) { + rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, false); + if (!rc) + return 0; + } + + /* Move to polling with a sleeping period between iterations */ + rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true); + if (!rc) + return 0; + DP_INFO(p_hwfn, "Ramrod is stuck, requesting MCP drain\n"); rc = qed_mcp_drain(p_hwfn, p_hwfn->p_main_ptt); - if (rc != 0) + if (rc) { DP_NOTICE(p_hwfn, "MCP drain failed\n"); + goto err; + } /* Retry after drain */ - sleep_count = SPQ_BLOCK_SLEEP_LENGTH; - while (sleep_count) { - /* validate we receive completion update */ - smp_rmb(); - if (comp_done->done == 1) { - if (p_fw_ret) - *p_fw_ret = comp_done->fw_return_code; - return 0; - } - usleep_range(5000, 10000); - sleep_count--; - } + rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true); + if (!rc) + return 0; + comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie; if (comp_done->done == 1) { if (p_fw_ret) *p_fw_ret = comp_done->fw_return_code; return 0; } - - DP_NOTICE(p_hwfn, "Ramrod is stuck, MCP drain failed\n"); +err: + DP_NOTICE(p_hwfn, + "Ramrod is stuck [CID %08x cmd %02x protocol %02x echo %04x]\n", + le32_to_cpu(p_ent->elem.hdr.cid), + p_ent->elem.hdr.cmd_id, + p_ent->elem.hdr.protocol_id, + le16_to_cpu(p_ent->elem.hdr.echo)); return -EBUSY; } @@ -729,7 +761,8 @@ int qed_spq_post(struct qed_hwfn *p_hwfn, * access p_ent here to see whether it's successful or not. * Thus, after gaining the answer perform the cleanup here. */ - rc = qed_spq_block(p_hwfn, p_ent, fw_return_code); + rc = qed_spq_block(p_hwfn, p_ent, fw_return_code, + p_ent->queue == &p_spq->unlimited_pending); if (p_ent->queue == &p_spq->unlimited_pending) { /* This is an allocated p_ent which does not need to -- cgit v1.2.3 From 7eff82b0fc26937d23e59d3de8a1930b25d4738c Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Fri, 14 Oct 2016 05:19:22 -0400 Subject: qed: Handle malicious VFs events Malicious VFs might be caught in several different methods: - Misusing their bar permission and being blocked by hardware. - Misusing their fastpath logic and being blocked by firmware. - Misusing their interaction with their PF via hw-channel, and being blocked by PF driver. On the first two items, firmware would indicate to driver that the VF is to be considered malicious, but would sometime still allow the VF to communicate with the PF [depending on the exact nature of the malicious activity done by the VF]. The current existing logic on the PF side lacks handling of such events, and might allow the PF to perform some incorrect configuration on behalf of a VF that was previously indicated as malicious. The new scheme is simple - Once the PF determines a VF is malicious it would: a. Ignore any further requests on behalf of the VF-driver. b. Prevent any configurations initiated by the hyperuser for the malicious VF, as firmware isn't willing to serve such. The malicious indication would be cleared upon the VF flr, after which it would become usable once again. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_sriov.c | 114 +++++++++++++++++++++++----- drivers/net/ethernet/qlogic/qed/qed_sriov.h | 1 + drivers/net/ethernet/qlogic/qed/qed_vf.h | 1 + 3 files changed, 96 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index d2d6621fe0e5..6f029f91e4de 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -109,7 +109,8 @@ static int qed_sp_vf_stop(struct qed_hwfn *p_hwfn, } static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn, - int rel_vf_id, bool b_enabled_only) + int rel_vf_id, + bool b_enabled_only, bool b_non_malicious) { if (!p_hwfn->pf_iov_info) { DP_NOTICE(p_hwfn->cdev, "No iov info\n"); @@ -124,6 +125,10 @@ static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn, b_enabled_only) return false; + if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) && + b_non_malicious) + return false; + return true; } @@ -138,7 +143,8 @@ static struct qed_vf_info *qed_iov_get_vf_info(struct qed_hwfn *p_hwfn, return NULL; } - if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id, b_enabled_only)) + if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id, + b_enabled_only, false)) vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id]; else DP_ERR(p_hwfn, "qed_iov_get_vf_info: VF[%d] is not enabled\n", @@ -542,7 +548,8 @@ int qed_iov_hw_info(struct qed_hwfn *p_hwfn) return 0; } -static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid) +bool _qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, + int vfid, bool b_fail_malicious) { /* Check PF supports sriov */ if (IS_VF(p_hwfn->cdev) || !IS_QED_SRIOV(p_hwfn->cdev) || @@ -550,12 +557,17 @@ static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid) return false; /* Check VF validity */ - if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true)) + if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious)) return false; return true; } +bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid) +{ + return _qed_iov_pf_sanity_check(p_hwfn, vfid, true); +} + static void qed_iov_set_vf_to_disable(struct qed_dev *cdev, u16 rel_vf_id, u8 to_disable) { @@ -652,6 +664,9 @@ static int qed_iov_enable_vf_access(struct qed_hwfn *p_hwfn, qed_iov_vf_igu_reset(p_hwfn, p_ptt, vf); + /* It's possible VF was previously considered malicious */ + vf->b_malicious = false; + rc = qed_mcp_config_vf_msix(p_hwfn, p_ptt, vf->abs_vf_id, vf->num_sbs); if (rc) return rc; @@ -2804,6 +2819,13 @@ qed_iov_execute_vf_flr_cleanup(struct qed_hwfn *p_hwfn, return rc; } + /* Workaround to make VF-PF channel ready, as FW + * doesn't do that as a part of FLR. + */ + REG_WR(p_hwfn, + GTT_BAR0_MAP_REG_USDM_RAM + + USTORM_VF_PF_CHANNEL_READY_OFFSET(vfid), 1); + /* VF_STOPPED has to be set only after final cleanup * but prior to re-enabling the VF. */ @@ -2942,7 +2964,8 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn, mbx->first_tlv = mbx->req_virt->first_tlv; /* check if tlv type is known */ - if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) { + if (qed_iov_tlv_supported(mbx->first_tlv.tl.type) && + !p_vf->b_malicious) { switch (mbx->first_tlv.tl.type) { case CHANNEL_TLV_ACQUIRE: qed_iov_vf_mbx_acquire(p_hwfn, p_ptt, p_vf); @@ -2984,6 +3007,15 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn, qed_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf); break; } + } else if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) { + DP_VERBOSE(p_hwfn, QED_MSG_IOV, + "VF [%02x] - considered malicious; Ignoring TLV [%04x]\n", + p_vf->abs_vf_id, mbx->first_tlv.tl.type); + + qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf, + mbx->first_tlv.tl.type, + sizeof(struct pfvf_def_resp_tlv), + PFVF_STATUS_MALICIOUS); } else { /* unknown TLV - this may belong to a VF driver from the future * - a version written after this PF driver was written, which @@ -3033,20 +3065,30 @@ static void qed_iov_pf_get_and_clear_pending_events(struct qed_hwfn *p_hwfn, memset(p_pending_events, 0, sizeof(u64) * QED_VF_ARRAY_LENGTH); } -static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn, - u16 abs_vfid, struct regpair *vf_msg) +static struct qed_vf_info *qed_sriov_get_vf_from_absid(struct qed_hwfn *p_hwfn, + u16 abs_vfid) { - u8 min = (u8)p_hwfn->cdev->p_iov_info->first_vf_in_pf; - struct qed_vf_info *p_vf; + u8 min = (u8) p_hwfn->cdev->p_iov_info->first_vf_in_pf; - if (!qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min)) { + if (!_qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) { DP_VERBOSE(p_hwfn, QED_MSG_IOV, - "Got a message from VF [abs 0x%08x] that cannot be handled by PF\n", + "Got indication for VF [abs 0x%08x] that cannot be handled by PF\n", abs_vfid); - return 0; + return NULL; } - p_vf = &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min]; + + return &p_hwfn->pf_iov_info->vfs_array[(u8) abs_vfid - min]; +} + +static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn, + u16 abs_vfid, struct regpair *vf_msg) +{ + struct qed_vf_info *p_vf = qed_sriov_get_vf_from_absid(p_hwfn, + abs_vfid); + + if (!p_vf) + return 0; /* List the physical address of the request so that handler * could later on copy the message from it. @@ -3060,6 +3102,23 @@ static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn, return 0; } +static void qed_sriov_vfpf_malicious(struct qed_hwfn *p_hwfn, + struct malicious_vf_eqe_data *p_data) +{ + struct qed_vf_info *p_vf; + + p_vf = qed_sriov_get_vf_from_absid(p_hwfn, p_data->vf_id); + + if (!p_vf) + return; + + DP_INFO(p_hwfn, + "VF [%d] - Malicious behavior [%02x]\n", + p_vf->abs_vf_id, p_data->err_id); + + p_vf->b_malicious = true; +} + int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, u8 opcode, __le16 echo, union event_ring_data *data) { @@ -3067,6 +3126,9 @@ int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, case COMMON_EVENT_VF_PF_CHANNEL: return qed_sriov_vfpf_msg(p_hwfn, le16_to_cpu(echo), &data->vf_pf_channel.msg_addr); + case COMMON_EVENT_MALICIOUS_VF: + qed_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf); + return 0; default: DP_INFO(p_hwfn->cdev, "Unknown sriov eqe event 0x%02x\n", opcode); @@ -3083,7 +3145,7 @@ u16 qed_iov_get_next_active_vf(struct qed_hwfn *p_hwfn, u16 rel_vf_id) goto out; for (i = rel_vf_id; i < p_iov->total_vfs; i++) - if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true)) + if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false)) return i; out: @@ -3130,6 +3192,12 @@ static void qed_iov_bulletin_set_forced_mac(struct qed_hwfn *p_hwfn, return; } + if (vf_info->b_malicious) { + DP_NOTICE(p_hwfn->cdev, + "Can't set forced MAC to malicious VF [%d]\n", vfid); + return; + } + feature = 1 << MAC_ADDR_FORCED; memcpy(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN); @@ -3153,6 +3221,12 @@ static void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn, return; } + if (vf_info->b_malicious) { + DP_NOTICE(p_hwfn->cdev, + "Can't set forced vlan to malicious VF [%d]\n", vfid); + return; + } + feature = 1 << VLAN_ADDR_FORCED; vf_info->bulletin.p_virt->pvid = pvid; if (pvid) @@ -3367,7 +3441,7 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled) qed_for_each_vf(hwfn, j) { int k; - if (!qed_iov_is_valid_vfid(hwfn, j, true)) + if (!qed_iov_is_valid_vfid(hwfn, j, true, false)) continue; /* Wait until VF is disabled before releasing */ @@ -3425,7 +3499,7 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num) num_sbs = min_t(int, sb_cnt_info.sb_free_blk, limit); for (i = 0; i < num; i++) { - if (!qed_iov_is_valid_vfid(hwfn, i, false)) + if (!qed_iov_is_valid_vfid(hwfn, i, false, true)) continue; rc = qed_iov_init_hw_for_vf(hwfn, @@ -3477,7 +3551,7 @@ static int qed_sriov_pf_set_mac(struct qed_dev *cdev, u8 *mac, int vfid) return -EINVAL; } - if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) { + if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) { DP_VERBOSE(cdev, QED_MSG_IOV, "Cannot set VF[%d] MAC (VF is not active)\n", vfid); return -EINVAL; @@ -3509,7 +3583,7 @@ static int qed_sriov_pf_set_vlan(struct qed_dev *cdev, u16 vid, int vfid) return -EINVAL; } - if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) { + if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) { DP_VERBOSE(cdev, QED_MSG_IOV, "Cannot set VF[%d] MAC (VF is not active)\n", vfid); return -EINVAL; @@ -3543,7 +3617,7 @@ static int qed_get_vf_config(struct qed_dev *cdev, if (IS_VF(cdev)) return -EINVAL; - if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) { + if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, false)) { DP_VERBOSE(cdev, QED_MSG_IOV, "VF index [%d] isn't active\n", vf_id); return -EINVAL; @@ -3647,7 +3721,7 @@ static int qed_set_vf_link_state(struct qed_dev *cdev, if (IS_VF(cdev)) return -EINVAL; - if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) { + if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, true)) { DP_VERBOSE(cdev, QED_MSG_IOV, "VF index [%d] isn't active\n", vf_id); return -EINVAL; diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.h b/drivers/net/ethernet/qlogic/qed/qed_sriov.h index 0dd23e409b3f..3cf515b1b427 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.h @@ -132,6 +132,7 @@ struct qed_vf_info { struct qed_iov_vf_mbx vf_mbx; enum vf_state state; bool b_init; + bool b_malicious; u8 to_disable; struct qed_bulletin bulletin; diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.h b/drivers/net/ethernet/qlogic/qed/qed_vf.h index 35db7a28aa13..944745b7c4c0 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.h +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.h @@ -40,6 +40,7 @@ enum { PFVF_STATUS_NOT_SUPPORTED, PFVF_STATUS_NO_RESOURCE, PFVF_STATUS_FORCED, + PFVF_STATUS_MALICIOUS, }; /* vf pf channel tlvs */ -- cgit v1.2.3 From d5df7688b6a36dbb5611a58229a5e294cd978999 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 14 Oct 2016 05:19:23 -0400 Subject: qed: Fix possible race when reading firmware return code. While handling SPQ ramrod completion, there is a possible race where driver might not read updated fw return code based on ramrod completion done. This patch ensures that fw return code is written first and then completion done flag is updated using appropriate memory barriers. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_sp.h | 4 ++-- drivers/net/ethernet/qlogic/qed/qed_spq.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h index 652c90819758..27c450fd2193 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h @@ -111,8 +111,8 @@ union qed_spq_req_comp { }; struct qed_spq_comp_done { - u64 done; - u8 fw_return_code; + unsigned int done; + u8 fw_return_code; }; struct qed_spq_entry { diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index 259a6156c761..6c05402ea4dc 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -54,11 +54,10 @@ static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn, comp_done = (struct qed_spq_comp_done *)cookie; - comp_done->done = 0x1; - comp_done->fw_return_code = fw_return_code; + comp_done->fw_return_code = fw_return_code; - /* make update visible to waiting thread */ - smp_wmb(); + /* Make sure completion done is visible on waiting thread */ + smp_store_release(&comp_done->done, 0x1); } static int __qed_spq_block(struct qed_hwfn *p_hwfn, @@ -74,8 +73,9 @@ static int __qed_spq_block(struct qed_hwfn *p_hwfn, while (iter_cnt--) { /* Validate we receive completion update */ - smp_rmb(); - if (comp_done->done == 1) { + if (READ_ONCE(comp_done->done) == 1) { + /* Read updated FW return value */ + smp_read_barrier_depends(); if (p_fw_ret) *p_fw_ret = comp_done->fw_return_code; return 0; -- cgit v1.2.3 From 462d807474783dfc7d0c412f320749aebcc5f8fc Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 14 Oct 2016 20:27:25 +0900 Subject: fjes: ethtool -d support for fjes driver This patch adds implementation of supporting ethtool -d for fjes driver. By using ethtool -d, you can get registers dump of Exetnded socket device. # ethtool -d es0 Offset Values ------ ------ 0x0000: 01 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 0x0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0020: 02 00 00 80 02 00 00 80 64 a6 58 08 07 00 00 00 0x0030: 00 00 00 00 28 80 00 00 00 00 f9 e3 06 00 00 00 0x0040: 00 00 00 00 18 00 00 00 80 a4 58 08 07 00 00 00 0x0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0080: 00 00 00 00 00 00 e0 7f 00 00 01 00 00 00 01 00 0x0090: 00 00 00 00 Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_ethtool.c | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'drivers') diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c index 9c218e140c41..8397634ffbe1 100644 --- a/drivers/net/fjes/fjes_ethtool.c +++ b/drivers/net/fjes/fjes_ethtool.c @@ -121,12 +121,60 @@ static int fjes_get_settings(struct net_device *netdev, return 0; } +static int fjes_get_regs_len(struct net_device *netdev) +{ +#define FJES_REGS_LEN 37 + return FJES_REGS_LEN * sizeof(u32); +} + +static void fjes_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct fjes_adapter *adapter = netdev_priv(netdev); + struct fjes_hw *hw = &adapter->hw; + u32 *regs_buff = p; + + memset(p, 0, FJES_REGS_LEN * sizeof(u32)); + + regs->version = 1; + + /* Information registers */ + regs_buff[0] = rd32(XSCT_OWNER_EPID); + regs_buff[1] = rd32(XSCT_MAX_EP); + + /* Device Control registers */ + regs_buff[4] = rd32(XSCT_DCTL); + + /* Command Control registers */ + regs_buff[8] = rd32(XSCT_CR); + regs_buff[9] = rd32(XSCT_CS); + regs_buff[10] = rd32(XSCT_SHSTSAL); + regs_buff[11] = rd32(XSCT_SHSTSAH); + + regs_buff[13] = rd32(XSCT_REQBL); + regs_buff[14] = rd32(XSCT_REQBAL); + regs_buff[15] = rd32(XSCT_REQBAH); + + regs_buff[17] = rd32(XSCT_RESPBL); + regs_buff[18] = rd32(XSCT_RESPBAL); + regs_buff[19] = rd32(XSCT_RESPBAH); + + /* Interrupt Control registers */ + regs_buff[32] = rd32(XSCT_IS); + regs_buff[33] = rd32(XSCT_IMS); + regs_buff[34] = rd32(XSCT_IMC); + regs_buff[35] = rd32(XSCT_IG); + regs_buff[36] = rd32(XSCT_ICTL); +} + static const struct ethtool_ops fjes_ethtool_ops = { .get_settings = fjes_get_settings, .get_drvinfo = fjes_get_drvinfo, .get_ethtool_stats = fjes_get_ethtool_stats, .get_strings = fjes_get_strings, .get_sset_count = fjes_get_sset_count, + .get_regs = fjes_get_regs, + .get_regs_len = fjes_get_regs_len, }; void fjes_set_ethtool_ops(struct net_device *netdev) -- cgit v1.2.3 From 21b7efbc5e910487c86f93ac88194dadbacac6e8 Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 14 Oct 2016 20:27:32 +0900 Subject: fjes: Enhance ethtool -S for fjes driver This patch enhances ethtool -S for fjes driver so that EP related statistics can be retrieved. The following statistics can be displayed via ethtool -S: ep%d_com_regist_buf_exec ep%d_com_unregist_buf_exec ep%d_send_intr_rx ep%d_send_intr_unshare ep%d_send_intr_zoneupdate ep%d_recv_intr_rx ep%d_recv_intr_unshare ep%d_recv_intr_stop ep%d_recv_intr_zoneupdate ep%d_tx_buffer_full ep%d_tx_dropped_not_shared ep%d_tx_dropped_ver_mismatch ep%d_tx_dropped_buf_size_mismatch ep%d_tx_dropped_vlanid_mismatch Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_ethtool.c | 70 ++++++++++++++++++++++++++++++++++++++++- drivers/net/fjes/fjes_hw.c | 9 ++++++ drivers/net/fjes/fjes_hw.h | 19 +++++++++++ drivers/net/fjes/fjes_main.c | 44 +++++++++++++++++++++++--- 4 files changed, 137 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c index 8397634ffbe1..68ef28709c98 100644 --- a/drivers/net/fjes/fjes_ethtool.c +++ b/drivers/net/fjes/fjes_ethtool.c @@ -49,10 +49,18 @@ static const struct fjes_stats fjes_gstrings_stats[] = { FJES_STAT("tx_dropped", stats64.tx_dropped), }; +#define FJES_EP_STATS_LEN 14 +#define FJES_STATS_LEN \ + (ARRAY_SIZE(fjes_gstrings_stats) + \ + ((&((struct fjes_adapter *)netdev_priv(netdev))->hw)->max_epid - 1) * \ + FJES_EP_STATS_LEN) + static void fjes_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct fjes_adapter *adapter = netdev_priv(netdev); + struct fjes_hw *hw = &adapter->hw; + int epidx; char *p; int i; @@ -61,11 +69,39 @@ static void fjes_get_ethtool_stats(struct net_device *netdev, data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } + for (epidx = 0; epidx < hw->max_epid; epidx++) { + if (epidx == hw->my_epid) + continue; + data[i++] = hw->ep_shm_info[epidx].ep_stats + .com_regist_buf_exec; + data[i++] = hw->ep_shm_info[epidx].ep_stats + .com_unregist_buf_exec; + data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_rx; + data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_unshare; + data[i++] = hw->ep_shm_info[epidx].ep_stats + .send_intr_zoneupdate; + data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_rx; + data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_unshare; + data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_stop; + data[i++] = hw->ep_shm_info[epidx].ep_stats + .recv_intr_zoneupdate; + data[i++] = hw->ep_shm_info[epidx].ep_stats.tx_buffer_full; + data[i++] = hw->ep_shm_info[epidx].ep_stats + .tx_dropped_not_shared; + data[i++] = hw->ep_shm_info[epidx].ep_stats + .tx_dropped_ver_mismatch; + data[i++] = hw->ep_shm_info[epidx].ep_stats + .tx_dropped_buf_size_mismatch; + data[i++] = hw->ep_shm_info[epidx].ep_stats + .tx_dropped_vlanid_mismatch; + } } static void fjes_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { + struct fjes_adapter *adapter = netdev_priv(netdev); + struct fjes_hw *hw = &adapter->hw; u8 *p = data; int i; @@ -76,6 +112,38 @@ static void fjes_get_strings(struct net_device *netdev, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } + for (i = 0; i < hw->max_epid; i++) { + if (i == hw->my_epid) + continue; + sprintf(p, "ep%u_com_regist_buf_exec", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_com_unregist_buf_exec", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_send_intr_rx", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_send_intr_unshare", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_send_intr_zoneupdate", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_recv_intr_rx", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_recv_intr_unshare", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_recv_intr_stop", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_recv_intr_zoneupdate", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_tx_buffer_full", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_tx_dropped_not_shared", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_tx_dropped_ver_mismatch", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_tx_dropped_buf_size_mismatch", i); + p += ETH_GSTRING_LEN; + sprintf(p, "ep%u_tx_dropped_vlanid_mismatch", i); + p += ETH_GSTRING_LEN; + } break; } } @@ -84,7 +152,7 @@ static int fjes_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { case ETH_SS_STATS: - return ARRAY_SIZE(fjes_gstrings_stats); + return FJES_STATS_LEN; default: return -EOPNOTSUPP; } diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index 0dbafedc0a34..82b56e8170bc 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c @@ -752,6 +752,7 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw) case EP_PARTNER_SHARED: fjes_hw_raise_interrupt(hw, epidx, REG_ICTL_MASK_TXRX_STOP_REQ); + hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1; break; default: break; @@ -1062,6 +1063,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work) break; } mutex_unlock(&hw->hw_info.lock); + + hw->ep_shm_info[epidx].ep_stats + .com_regist_buf_exec += 1; } if (test_bit(epidx, &unshare_bit)) { @@ -1085,6 +1089,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work) mutex_unlock(&hw->hw_info.lock); + hw->ep_shm_info[epidx].ep_stats + .com_unregist_buf_exec += 1; + if (ret == 0) { spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf( @@ -1099,6 +1106,8 @@ static void fjes_hw_update_zone_task(struct work_struct *work) fjes_hw_raise_interrupt(hw, epidx, REG_ICTL_MASK_TXRX_STOP_REQ); + hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1; + set_bit(epidx, &hw->txrx_stop_req_bit); spin_lock_irqsave(&hw->rx_status_lock, flags); hw->ep_shm_info[epidx].tx. diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h index 1445ac99d6e3..205182ef0b52 100644 --- a/drivers/net/fjes/fjes_hw.h +++ b/drivers/net/fjes/fjes_hw.h @@ -228,6 +228,24 @@ union ep_buffer_info { }; +/* statistics of EP */ +struct fjes_drv_ep_stats { + u64 com_regist_buf_exec; + u64 com_unregist_buf_exec; + u64 send_intr_rx; + u64 send_intr_unshare; + u64 send_intr_zoneupdate; + u64 recv_intr_rx; + u64 recv_intr_unshare; + u64 recv_intr_stop; + u64 recv_intr_zoneupdate; + u64 tx_buffer_full; + u64 tx_dropped_not_shared; + u64 tx_dropped_ver_mismatch; + u64 tx_dropped_buf_size_mismatch; + u64 tx_dropped_vlanid_mismatch; +}; + /* buffer pair for Extended Partition */ struct ep_share_mem_info { struct epbuf_handler { @@ -238,6 +256,7 @@ struct ep_share_mem_info { } tx, rx; struct rtnl_link_stats64 net_stats; + struct fjes_drv_ep_stats ep_stats; u16 tx_status_work; diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index e46b1ebbbff4..03e238327dd5 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -366,6 +366,8 @@ static int fjes_setup_resources(struct fjes_adapter *adapter) FJES_ZONING_STATUS_ENABLE)) { fjes_hw_raise_interrupt(hw, epidx, REG_ICTL_MASK_INFO_UPDATE); + hw->ep_shm_info[epidx].ep_stats + .send_intr_zoneupdate += 1; } } @@ -397,6 +399,9 @@ static int fjes_setup_resources(struct fjes_adapter *adapter) adapter->force_reset = true; return result; } + + hw->ep_shm_info[epidx].ep_stats + .com_regist_buf_exec += 1; } } @@ -422,6 +427,8 @@ static void fjes_free_resources(struct fjes_adapter *adapter) result = fjes_hw_unregister_buff_addr(hw, epidx); mutex_unlock(&hw->hw_info.lock); + hw->ep_shm_info[epidx].ep_stats.com_unregist_buf_exec += 1; + if (result) reset_flag = true; @@ -567,6 +574,7 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work) FJES_RX_POLL_WORK)) { fjes_hw_raise_interrupt(hw, epid, REG_ICTL_MASK_RX_DATA); + hw->ep_shm_info[epid].ep_stats.send_intr_rx += 1; } } @@ -663,6 +671,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid); if (pstatus != EP_PARTNER_SHARED) { + if (!is_multi) + hw->ep_shm_info[dest_epid].ep_stats + .tx_dropped_not_shared += 1; ret = NETDEV_TX_OK; } else if (!fjes_hw_check_epbuf_version( &adapter->hw.ep_shm_info[dest_epid].rx, 0)) { @@ -670,6 +681,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) adapter->stats64.tx_carrier_errors += 1; hw->ep_shm_info[dest_epid].net_stats .tx_carrier_errors += 1; + hw->ep_shm_info[dest_epid].ep_stats + .tx_dropped_ver_mismatch += 1; ret = NETDEV_TX_OK; } else if (!fjes_hw_check_mtu( @@ -679,12 +692,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1; adapter->stats64.tx_errors += 1; hw->ep_shm_info[dest_epid].net_stats.tx_errors += 1; + hw->ep_shm_info[dest_epid].ep_stats + .tx_dropped_buf_size_mismatch += 1; ret = NETDEV_TX_OK; } else if (vlan && !fjes_hw_check_vlan_id( &adapter->hw.ep_shm_info[dest_epid].rx, vlan_id)) { + hw->ep_shm_info[dest_epid].ep_stats + .tx_dropped_vlanid_mismatch += 1; ret = NETDEV_TX_OK; } else { if (len < VLAN_ETH_HLEN) { @@ -718,6 +735,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ret = NETDEV_TX_OK; } else { netif_trans_update(netdev); + hw->ep_shm_info[dest_epid].ep_stats + .tx_buffer_full += 1; netif_tx_stop_queue(cur_queue); if (!work_pending(&adapter->tx_stall_task)) @@ -970,21 +989,33 @@ static irqreturn_t fjes_intr(int irq, void *data) icr = fjes_hw_capture_interrupt_status(hw); if (icr & REG_IS_MASK_IS_ASSERT) { - if (icr & REG_ICTL_MASK_RX_DATA) + if (icr & REG_ICTL_MASK_RX_DATA) { fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID); + hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats + .recv_intr_rx += 1; + } - if (icr & REG_ICTL_MASK_DEV_STOP_REQ) + if (icr & REG_ICTL_MASK_DEV_STOP_REQ) { fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID); + hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats + .recv_intr_stop += 1; + } - if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) + if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) { fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID); + hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats + .recv_intr_unshare += 1; + } if (icr & REG_ICTL_MASK_TXRX_STOP_DONE) fjes_hw_set_irqmask(hw, REG_ICTL_MASK_TXRX_STOP_DONE, true); - if (icr & REG_ICTL_MASK_INFO_UPDATE) + if (icr & REG_ICTL_MASK_INFO_UPDATE) { fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID); + hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats + .recv_intr_zoneupdate += 1; + } ret = IRQ_HANDLED; } else { @@ -1364,6 +1395,8 @@ static void fjes_watch_unshare_task(struct work_struct *work) break; } mutex_unlock(&hw->hw_info.lock); + hw->ep_shm_info[epidx].ep_stats + .com_unregist_buf_exec += 1; spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, @@ -1406,6 +1439,9 @@ static void fjes_watch_unshare_task(struct work_struct *work) } mutex_unlock(&hw->hw_info.lock); + hw->ep_shm_info[epidx].ep_stats + .com_unregist_buf_exec += 1; + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf( &hw->ep_shm_info[epidx].tx, -- cgit v1.2.3 From 82f6aea801e3732fe4bf41af46ebe352bf24fde8 Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 14 Oct 2016 20:27:38 +0900 Subject: fjes: Add tracepoints in fjes driver This patch adds tracepoints in fjes driver. This is useful for debugging purpose. Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/Makefile | 2 +- drivers/net/fjes/fjes_hw.c | 25 +++- drivers/net/fjes/fjes_main.c | 5 + drivers/net/fjes/fjes_trace.c | 30 ++++ drivers/net/fjes/fjes_trace.h | 311 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 369 insertions(+), 4 deletions(-) create mode 100644 drivers/net/fjes/fjes_trace.c create mode 100644 drivers/net/fjes/fjes_trace.h (limited to 'drivers') diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile index 523e3d7cf7aa..6705d1b523d5 100644 --- a/drivers/net/fjes/Makefile +++ b/drivers/net/fjes/Makefile @@ -27,4 +27,4 @@ obj-$(CONFIG_FUJITSU_ES) += fjes.o -fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o +fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o fjes_trace.o diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index 82b56e8170bc..dba59dcc410f 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c @@ -21,6 +21,7 @@ #include "fjes_hw.h" #include "fjes.h" +#include "fjes_trace.h" static void fjes_hw_update_zone_task(struct work_struct *); static void fjes_hw_epstop_task(struct work_struct *); @@ -371,7 +372,7 @@ fjes_hw_issue_request_command(struct fjes_hw *hw, enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN; union REG_CR cr; union REG_CS cs; - int timeout; + int timeout = FJES_COMMAND_REQ_TIMEOUT * 1000; cr.reg = 0; cr.bits.req_start = 1; @@ -408,6 +409,8 @@ fjes_hw_issue_request_command(struct fjes_hw *hw, } } + trace_fjes_hw_issue_request_command(&cr, &cs, timeout, ret); + return ret; } @@ -427,11 +430,13 @@ int fjes_hw_request_info(struct fjes_hw *hw) res_buf->info.code = 0; ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO); + trace_fjes_hw_request_info(hw, res_buf); result = 0; if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) != res_buf->info.length) { + trace_fjes_hw_request_info_err("Invalid res_buf"); result = -ENOMSG; } else if (ret == FJES_CMD_STATUS_NORMAL) { switch (res_buf->info.code) { @@ -448,6 +453,7 @@ int fjes_hw_request_info(struct fjes_hw *hw) result = -EPERM; break; case FJES_CMD_STATUS_TIMEOUT: + trace_fjes_hw_request_info_err("Timeout"); result = -EBUSY; break; case FJES_CMD_STATUS_ERROR_PARAM: @@ -512,6 +518,8 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid, res_buf->share_buffer.length = 0; res_buf->share_buffer.code = 0; + trace_fjes_hw_register_buff_addr_req(req_buf, buf_pair); + ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER); timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000; @@ -532,16 +540,20 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid, result = 0; + trace_fjes_hw_register_buff_addr(res_buf, timeout); + if (res_buf->share_buffer.length != - FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) + FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) { + trace_fjes_hw_register_buff_addr_err("Invalid res_buf"); result = -ENOMSG; - else if (ret == FJES_CMD_STATUS_NORMAL) { + } else if (ret == FJES_CMD_STATUS_NORMAL) { switch (res_buf->share_buffer.code) { case FJES_CMD_REQ_RES_CODE_NORMAL: result = 0; set_bit(dest_epid, &hw->hw_info.buffer_share_bit); break; case FJES_CMD_REQ_RES_CODE_BUSY: + trace_fjes_hw_register_buff_addr_err("Busy Timeout"); result = -EBUSY; break; default: @@ -554,6 +566,7 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid, result = -EPERM; break; case FJES_CMD_STATUS_TIMEOUT: + trace_fjes_hw_register_buff_addr_err("Timeout"); result = -EBUSY; break; case FJES_CMD_STATUS_ERROR_PARAM: @@ -595,6 +608,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid) res_buf->unshare_buffer.length = 0; res_buf->unshare_buffer.code = 0; + trace_fjes_hw_unregister_buff_addr_req(req_buf); ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER); timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000; @@ -616,8 +630,11 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid) result = 0; + trace_fjes_hw_unregister_buff_addr(res_buf, timeout); + if (res_buf->unshare_buffer.length != FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) { + trace_fjes_hw_unregister_buff_addr_err("Invalid res_buf"); result = -ENOMSG; } else if (ret == FJES_CMD_STATUS_NORMAL) { switch (res_buf->unshare_buffer.code) { @@ -626,6 +643,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid) clear_bit(dest_epid, &hw->hw_info.buffer_share_bit); break; case FJES_CMD_REQ_RES_CODE_BUSY: + trace_fjes_hw_unregister_buff_addr_err("Busy Timeout"); result = -EBUSY; break; default: @@ -638,6 +656,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid) result = -EPERM; break; case FJES_CMD_STATUS_TIMEOUT: + trace_fjes_hw_unregister_buff_addr_err("Timeout"); result = -EBUSY; break; case FJES_CMD_STATUS_ERROR_PARAM: diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 03e238327dd5..4c135ae11978 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -27,6 +27,7 @@ #include #include "fjes.h" +#include "fjes_trace.h" #define MAJ 1 #define MIN 1 @@ -904,6 +905,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter, unsigned long flags; status = fjes_hw_get_partner_ep_status(hw, src_epid); + trace_fjes_txrx_stop_req_irq_pre(hw, src_epid, status); switch (status) { case EP_PARTNER_UNSHARE: case EP_PARTNER_COMPLETE: @@ -934,6 +936,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter, } break; } + trace_fjes_txrx_stop_req_irq_post(hw, src_epid); } static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid) @@ -945,6 +948,7 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid) set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit); status = fjes_hw_get_partner_ep_status(hw, src_epid); + trace_fjes_stop_req_irq_pre(hw, src_epid, status); switch (status) { case EP_PARTNER_WAITING: spin_lock_irqsave(&hw->rx_status_lock, flags); @@ -968,6 +972,7 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid) queue_work(adapter->control_wq, &hw->epstop_task); break; } + trace_fjes_stop_req_irq_post(hw, src_epid); } static void fjes_update_zone_irq(struct fjes_adapter *adapter, diff --git a/drivers/net/fjes/fjes_trace.c b/drivers/net/fjes/fjes_trace.c new file mode 100644 index 000000000000..066fa765d5bb --- /dev/null +++ b/drivers/net/fjes/fjes_trace.c @@ -0,0 +1,30 @@ +/* + * FUJITSU Extended Socket Network Device driver + * Copyright (c) 2015-2016 FUJITSU LIMITED + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + */ + +#include + +#ifndef __CHECKER__ +#include "fjes_hw.h" + +#define CREATE_TRACE_POINTS +#include "fjes_trace.h" + +#endif /* __CHECKER__ */ diff --git a/drivers/net/fjes/fjes_trace.h b/drivers/net/fjes/fjes_trace.h new file mode 100644 index 000000000000..1f0a48933f46 --- /dev/null +++ b/drivers/net/fjes/fjes_trace.h @@ -0,0 +1,311 @@ +/* + * FUJITSU Extended Socket Network Device driver + * Copyright (c) 2015-2016 FUJITSU LIMITED + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + */ + +#if !defined(FJES_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) +#define FJES_TRACE_H_ + +#include +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM fjes + +/* tracepoints for fjes_hw.c */ + +TRACE_EVENT(fjes_hw_issue_request_command, + TP_PROTO(union REG_CR *cr, union REG_CS *cs, int timeout, + enum fjes_dev_command_response_e ret), + TP_ARGS(cr, cs, timeout, ret), + TP_STRUCT__entry( + __field(u16, cr_req) + __field(u8, cr_error) + __field(u16, cr_err_info) + __field(u8, cr_req_start) + __field(u16, cs_req) + __field(u8, cs_busy) + __field(u8, cs_complete) + __field(int, timeout) + __field(int, ret); + ), + TP_fast_assign( + __entry->cr_req = cr->bits.req_code; + __entry->cr_error = cr->bits.error; + __entry->cr_err_info = cr->bits.err_info; + __entry->cr_req_start = cr->bits.req_start; + __entry->cs_req = cs->bits.req_code; + __entry->cs_busy = cs->bits.busy; + __entry->cs_complete = cs->bits.complete; + __entry->timeout = timeout; + __entry->ret = ret; + ), + TP_printk("CR=[req=%04x, error=%u, err_info=%04x, req_start=%u], CS=[req=%04x, busy=%u, complete=%u], timeout=%d, ret=%d", + __entry->cr_req, __entry->cr_error, __entry->cr_err_info, + __entry->cr_req_start, __entry->cs_req, __entry->cs_busy, + __entry->cs_complete, __entry->timeout, __entry->ret) +); + +TRACE_EVENT(fjes_hw_request_info, + TP_PROTO(struct fjes_hw *hw, union fjes_device_command_res *res_buf), + TP_ARGS(hw, res_buf), + TP_STRUCT__entry( + __field(int, length) + __field(int, code) + __dynamic_array(u8, zone, hw->max_epid) + __dynamic_array(u8, status, hw->max_epid) + ), + TP_fast_assign( + int x; + + __entry->length = res_buf->info.length; + __entry->code = res_buf->info.code; + for (x = 0; x < hw->max_epid; x++) { + *((u8 *)__get_dynamic_array(zone) + x) = + res_buf->info.info[x].zone; + *((u8 *)__get_dynamic_array(status) + x) = + res_buf->info.info[x].es_status; + } + ), + TP_printk("res_buf=[length=%d, code=%d, es_zones=%s, es_status=%s]", + __entry->length, __entry->code, + __print_array(__get_dynamic_array(zone), + __get_dynamic_array_len(zone) / sizeof(u8), + sizeof(u8)), + __print_array(__get_dynamic_array(status), + __get_dynamic_array_len(status) / sizeof(u8), + sizeof(u8))) +); + +TRACE_EVENT(fjes_hw_request_info_err, + TP_PROTO(char *err), + TP_ARGS(err), + TP_STRUCT__entry( + __string(err, err) + ), + TP_fast_assign( + __assign_str(err, err); + ), + TP_printk("%s", __get_str(err)) +); + +TRACE_EVENT(fjes_hw_register_buff_addr_req, + TP_PROTO(union fjes_device_command_req *req_buf, + struct ep_share_mem_info *buf_pair), + TP_ARGS(req_buf, buf_pair), + TP_STRUCT__entry( + __field(int, length) + __field(int, epid) + __field(u64, tx) + __field(size_t, tx_size) + __field(u64, rx) + __field(size_t, rx_size) + ), + TP_fast_assign( + void *tx, *rx; + + tx = (void *)buf_pair->tx.buffer; + rx = (void *)buf_pair->rx.buffer; + __entry->length = req_buf->share_buffer.length; + __entry->epid = req_buf->share_buffer.epid; + __entry->tx_size = buf_pair->tx.size; + __entry->rx_size = buf_pair->rx.size; + __entry->tx = page_to_phys(vmalloc_to_page(tx)) + + offset_in_page(tx); + __entry->rx = page_to_phys(vmalloc_to_page(rx)) + + offset_in_page(rx); + ), + TP_printk("req_buf=[length=%d, epid=%d], TX=[phy=0x%016llx, size=%zu], RX=[phy=0x%016llx, size=%zu]", + __entry->length, __entry->epid, __entry->tx, __entry->tx_size, + __entry->rx, __entry->rx_size) +); + +TRACE_EVENT(fjes_hw_register_buff_addr, + TP_PROTO(union fjes_device_command_res *res_buf, int timeout), + TP_ARGS(res_buf, timeout), + TP_STRUCT__entry( + __field(int, length) + __field(int, code) + __field(int, timeout) + ), + TP_fast_assign( + __entry->length = res_buf->share_buffer.length; + __entry->code = res_buf->share_buffer.code; + __entry->timeout = timeout; + ), + TP_printk("res_buf=[length=%d, code=%d], timeout=%d", + __entry->length, __entry->code, __entry->timeout) +); + +TRACE_EVENT(fjes_hw_register_buff_addr_err, + TP_PROTO(char *err), + TP_ARGS(err), + TP_STRUCT__entry( + __string(err, err) + ), + TP_fast_assign( + __assign_str(err, err); + ), + TP_printk("%s", __get_str(err)) +); + +TRACE_EVENT(fjes_hw_unregister_buff_addr_req, + TP_PROTO(union fjes_device_command_req *req_buf), + TP_ARGS(req_buf), + TP_STRUCT__entry( + __field(int, length) + __field(int, epid) + ), + TP_fast_assign( + __entry->length = req_buf->unshare_buffer.length; + __entry->epid = req_buf->unshare_buffer.epid; + ), + TP_printk("req_buf=[length=%d, epid=%d]", + __entry->length, __entry->epid) +); + +TRACE_EVENT(fjes_hw_unregister_buff_addr, + TP_PROTO(union fjes_device_command_res *res_buf, int timeout), + TP_ARGS(res_buf, timeout), + TP_STRUCT__entry( + __field(int, length) + __field(int, code) + __field(int, timeout) + ), + TP_fast_assign( + __entry->length = res_buf->unshare_buffer.length; + __entry->code = res_buf->unshare_buffer.code; + __entry->timeout = timeout; + ), + TP_printk("res_buf=[length=%d, code=%d], timeout=%d", + __entry->length, __entry->code, __entry->timeout) +); + +TRACE_EVENT(fjes_hw_unregister_buff_addr_err, + TP_PROTO(char *err), + TP_ARGS(err), + TP_STRUCT__entry( + __string(err, err) + ), + TP_fast_assign( + __assign_str(err, err); + ), + TP_printk("%s", __get_str(err)) +); + +/* tracepoints for fjes_main.c */ + +TRACE_EVENT(fjes_txrx_stop_req_irq_pre, + TP_PROTO(struct fjes_hw *hw, int src_epid, + enum ep_partner_status status), + TP_ARGS(hw, src_epid, status), + TP_STRUCT__entry( + __field(int, src_epid) + __field(enum ep_partner_status, status) + __field(u8, ep_status) + __field(unsigned long, txrx_stop_req_bit) + __field(u16, rx_status) + ), + TP_fast_assign( + __entry->src_epid = src_epid; + __entry->status = status; + __entry->ep_status = hw->hw_info.share->ep_status[src_epid]; + __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit; + __entry->rx_status = + hw->ep_shm_info[src_epid].tx.info->v1i.rx_status; + ), + TP_printk("epid=%d, partner_status=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x", + __entry->src_epid, __entry->status, __entry->ep_status, + __entry->txrx_stop_req_bit, __entry->rx_status) +); + +TRACE_EVENT(fjes_txrx_stop_req_irq_post, + TP_PROTO(struct fjes_hw *hw, int src_epid), + TP_ARGS(hw, src_epid), + TP_STRUCT__entry( + __field(int, src_epid) + __field(u8, ep_status) + __field(unsigned long, txrx_stop_req_bit) + __field(u16, rx_status) + ), + TP_fast_assign( + __entry->src_epid = src_epid; + __entry->ep_status = hw->hw_info.share->ep_status[src_epid]; + __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit; + __entry->rx_status = hw->ep_shm_info[src_epid].tx.info->v1i.rx_status; + ), + TP_printk("epid=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x", + __entry->src_epid, __entry->ep_status, + __entry->txrx_stop_req_bit, __entry->rx_status) +); + +TRACE_EVENT(fjes_stop_req_irq_pre, + TP_PROTO(struct fjes_hw *hw, int src_epid, + enum ep_partner_status status), + TP_ARGS(hw, src_epid, status), + TP_STRUCT__entry( + __field(int, src_epid) + __field(enum ep_partner_status, status) + __field(u8, ep_status) + __field(unsigned long, txrx_stop_req_bit) + __field(u16, rx_status) + ), + TP_fast_assign( + __entry->src_epid = src_epid; + __entry->status = status; + __entry->ep_status = hw->hw_info.share->ep_status[src_epid]; + __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit; + __entry->rx_status = + hw->ep_shm_info[src_epid].tx.info->v1i.rx_status; + ), + TP_printk("epid=%d, partner_status=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x", + __entry->src_epid, __entry->status, __entry->ep_status, + __entry->txrx_stop_req_bit, __entry->rx_status) +); + +TRACE_EVENT(fjes_stop_req_irq_post, + TP_PROTO(struct fjes_hw *hw, int src_epid), + TP_ARGS(hw, src_epid), + TP_STRUCT__entry( + __field(int, src_epid) + __field(u8, ep_status) + __field(unsigned long, txrx_stop_req_bit) + __field(u16, rx_status) + ), + TP_fast_assign( + __entry->src_epid = src_epid; + __entry->ep_status = hw->hw_info.share->ep_status[src_epid]; + __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit; + __entry->rx_status = + hw->ep_shm_info[src_epid].tx.info->v1i.rx_status; + ), + TP_printk("epid=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x", + __entry->src_epid, __entry->ep_status, + __entry->txrx_stop_req_bit, __entry->rx_status) +); + +#endif /* FJES_TRACE_H_ */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH ../../../drivers/net/fjes +#define TRACE_INCLUDE_FILE fjes_trace + +/* This part must be outside protection */ +#include -- cgit v1.2.3 From b6ba737d0b290b272452a2362088222a248fc8da Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 14 Oct 2016 20:27:45 +0900 Subject: fjes: ethtool -w and -W support for fjes driver This patch adds implementation of supporting ethtool -w and -W for fjes driver. You can enable and disable firmware debug mode by using ethtool -W, and also retrieve firmware activity information by using ethtool -w. This is useful for debugging. Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_ethtool.c | 63 ++++++++++++++++++ drivers/net/fjes/fjes_hw.c | 137 ++++++++++++++++++++++++++++++++++++++++ drivers/net/fjes/fjes_hw.h | 15 +++++ drivers/net/fjes/fjes_trace.h | 69 ++++++++++++++++++++ 4 files changed, 284 insertions(+) (limited to 'drivers') diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c index 68ef28709c98..6575f880f1be 100644 --- a/drivers/net/fjes/fjes_ethtool.c +++ b/drivers/net/fjes/fjes_ethtool.c @@ -235,6 +235,66 @@ static void fjes_get_regs(struct net_device *netdev, regs_buff[36] = rd32(XSCT_ICTL); } +static int fjes_set_dump(struct net_device *netdev, struct ethtool_dump *dump) +{ + struct fjes_adapter *adapter = netdev_priv(netdev); + struct fjes_hw *hw = &adapter->hw; + int ret = 0; + + if (dump->flag) { + if (hw->debug_mode) + return -EPERM; + + hw->debug_mode = dump->flag; + + /* enable debug mode */ + mutex_lock(&hw->hw_info.lock); + ret = fjes_hw_start_debug(hw); + mutex_unlock(&hw->hw_info.lock); + + if (ret) + hw->debug_mode = 0; + } else { + if (!hw->debug_mode) + return -EPERM; + + /* disable debug mode */ + mutex_lock(&hw->hw_info.lock); + ret = fjes_hw_stop_debug(hw); + mutex_unlock(&hw->hw_info.lock); + } + + return ret; +} + +static int fjes_get_dump_flag(struct net_device *netdev, + struct ethtool_dump *dump) +{ + struct fjes_adapter *adapter = netdev_priv(netdev); + struct fjes_hw *hw = &adapter->hw; + + dump->len = hw->hw_info.trace_size; + dump->version = 1; + dump->flag = hw->debug_mode; + + return 0; +} + +static int fjes_get_dump_data(struct net_device *netdev, + struct ethtool_dump *dump, void *buf) +{ + struct fjes_adapter *adapter = netdev_priv(netdev); + struct fjes_hw *hw = &adapter->hw; + int ret = 0; + + if (hw->hw_info.trace) + memcpy(buf, hw->hw_info.trace, hw->hw_info.trace_size); + else + ret = -EPERM; + + return ret; +} + static const struct ethtool_ops fjes_ethtool_ops = { .get_settings = fjes_get_settings, .get_drvinfo = fjes_get_drvinfo, @@ -243,6 +303,9 @@ static const struct ethtool_ops fjes_ethtool_ops = { .get_sset_count = fjes_get_sset_count, .get_regs = fjes_get_regs, .get_regs_len = fjes_get_regs_len, + .set_dump = fjes_set_dump, + .get_dump_flag = fjes_get_dump_flag, + .get_dump_data = fjes_get_dump_data, }; void fjes_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index dba59dcc410f..9c652c04375b 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c @@ -343,6 +343,9 @@ int fjes_hw_init(struct fjes_hw *hw) ret = fjes_hw_setup(hw); + hw->hw_info.trace = vzalloc(FJES_DEBUG_BUFFER_SIZE); + hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE; + return ret; } @@ -351,6 +354,18 @@ void fjes_hw_exit(struct fjes_hw *hw) int ret; if (hw->base) { + + if (hw->debug_mode) { + /* disable debug mode */ + mutex_lock(&hw->hw_info.lock); + fjes_hw_stop_debug(hw); + mutex_unlock(&hw->hw_info.lock); + } + vfree(hw->hw_info.trace); + hw->hw_info.trace = NULL; + hw->hw_info.trace_size = 0; + hw->debug_mode = 0; + ret = fjes_hw_reset(hw); if (ret) pr_err("%s: reset error", __func__); @@ -1175,3 +1190,125 @@ static void fjes_hw_epstop_task(struct work_struct *work) } } } + +int fjes_hw_start_debug(struct fjes_hw *hw) +{ + union fjes_device_command_req *req_buf = hw->hw_info.req_buf; + union fjes_device_command_res *res_buf = hw->hw_info.res_buf; + enum fjes_dev_command_response_e ret; + int page_count; + int result = 0; + void *addr; + int i; + + if (!hw->hw_info.trace) + return -EPERM; + memset(hw->hw_info.trace, 0, FJES_DEBUG_BUFFER_SIZE); + + memset(req_buf, 0, hw->hw_info.req_buf_size); + memset(res_buf, 0, hw->hw_info.res_buf_size); + + req_buf->start_trace.length = + FJES_DEV_COMMAND_START_DBG_REQ_LEN(hw->hw_info.trace_size); + req_buf->start_trace.mode = hw->debug_mode; + req_buf->start_trace.buffer_len = hw->hw_info.trace_size; + page_count = hw->hw_info.trace_size / FJES_DEBUG_PAGE_SIZE; + for (i = 0; i < page_count; i++) { + addr = ((u8 *)hw->hw_info.trace) + i * FJES_DEBUG_PAGE_SIZE; + req_buf->start_trace.buffer[i] = + (__le64)(page_to_phys(vmalloc_to_page(addr)) + + offset_in_page(addr)); + } + + res_buf->start_trace.length = 0; + res_buf->start_trace.code = 0; + + trace_fjes_hw_start_debug_req(req_buf); + ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_START_DEBUG); + trace_fjes_hw_start_debug(res_buf); + + if (res_buf->start_trace.length != + FJES_DEV_COMMAND_START_DBG_RES_LEN) { + result = -ENOMSG; + trace_fjes_hw_start_debug_err("Invalid res_buf"); + } else if (ret == FJES_CMD_STATUS_NORMAL) { + switch (res_buf->start_trace.code) { + case FJES_CMD_REQ_RES_CODE_NORMAL: + result = 0; + break; + default: + result = -EPERM; + break; + } + } else { + switch (ret) { + case FJES_CMD_STATUS_UNKNOWN: + result = -EPERM; + break; + case FJES_CMD_STATUS_TIMEOUT: + trace_fjes_hw_start_debug_err("Busy Timeout"); + result = -EBUSY; + break; + case FJES_CMD_STATUS_ERROR_PARAM: + case FJES_CMD_STATUS_ERROR_STATUS: + default: + result = -EPERM; + break; + } + } + + return result; +} + +int fjes_hw_stop_debug(struct fjes_hw *hw) +{ + union fjes_device_command_req *req_buf = hw->hw_info.req_buf; + union fjes_device_command_res *res_buf = hw->hw_info.res_buf; + enum fjes_dev_command_response_e ret; + int result = 0; + + if (!hw->hw_info.trace) + return -EPERM; + + memset(req_buf, 0, hw->hw_info.req_buf_size); + memset(res_buf, 0, hw->hw_info.res_buf_size); + req_buf->stop_trace.length = FJES_DEV_COMMAND_STOP_DBG_REQ_LEN; + + res_buf->stop_trace.length = 0; + res_buf->stop_trace.code = 0; + + ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_STOP_DEBUG); + trace_fjes_hw_stop_debug(res_buf); + + if (res_buf->stop_trace.length != FJES_DEV_COMMAND_STOP_DBG_RES_LEN) { + trace_fjes_hw_stop_debug_err("Invalid res_buf"); + result = -ENOMSG; + } else if (ret == FJES_CMD_STATUS_NORMAL) { + switch (res_buf->stop_trace.code) { + case FJES_CMD_REQ_RES_CODE_NORMAL: + result = 0; + hw->debug_mode = 0; + break; + default: + result = -EPERM; + break; + } + } else { + switch (ret) { + case FJES_CMD_STATUS_UNKNOWN: + result = -EPERM; + break; + case FJES_CMD_STATUS_TIMEOUT: + result = -EBUSY; + trace_fjes_hw_stop_debug_err("Busy Timeout"); + break; + case FJES_CMD_STATUS_ERROR_PARAM: + case FJES_CMD_STATUS_ERROR_STATUS: + default: + result = -EPERM; + break; + } + } + + return result; +} diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h index 205182ef0b52..3a6da0996a0e 100644 --- a/drivers/net/fjes/fjes_hw.h +++ b/drivers/net/fjes/fjes_hw.h @@ -33,6 +33,9 @@ struct fjes_hw; #define EP_BUFFER_SUPPORT_VLAN_MAX 4 #define EP_BUFFER_INFO_SIZE 4096 +#define FJES_DEBUG_PAGE_SIZE 4096 +#define FJES_DEBUG_BUFFER_SIZE (16 * FJES_DEBUG_PAGE_SIZE) + #define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3 * 8) /* sec */ #define FJES_COMMAND_REQ_TIMEOUT ((5 + 1) * 3 * 8) /* sec */ #define FJES_COMMAND_REQ_BUFF_TIMEOUT (60 * 3) /* sec */ @@ -94,6 +97,12 @@ struct fjes_hw; #define FJES_DEV_RES_BUF_SIZE(maxep) \ FJES_DEV_COMMAND_INFO_RES_LEN(maxep) +#define FJES_DEV_COMMAND_START_DBG_REQ_LEN(byte) \ + (16 + (8 * (byte) / FJES_DEBUG_PAGE_SIZE)) +#define FJES_DEV_COMMAND_START_DBG_RES_LEN (8) +#define FJES_DEV_COMMAND_STOP_DBG_REQ_LEN (4) +#define FJES_DEV_COMMAND_STOP_DBG_RES_LEN (8) + /* Frame & MTU */ struct esmem_frame { __le32 frame_size; @@ -173,6 +182,8 @@ enum fjes_dev_command_request_type { FJES_CMD_REQ_INFO = 0x0001, FJES_CMD_REQ_SHARE_BUFFER = 0x0002, FJES_CMD_REQ_UNSHARE_BUFFER = 0x0004, + FJES_CMD_REQ_START_DEBUG = 0x0100, + FJES_CMD_REQ_STOP_DEBUG = 0x0200, }; /* parameter for command control */ @@ -321,6 +332,8 @@ struct fjes_hw { struct fjes_hw_info hw_info; spinlock_t rx_status_lock; /* spinlock for rx_status */ + + u32 debug_mode; }; int fjes_hw_init(struct fjes_hw *); @@ -353,4 +366,6 @@ void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *); void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *); int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t); +int fjes_hw_start_debug(struct fjes_hw *); +int fjes_hw_stop_debug(struct fjes_hw *); #endif /* FJES_HW_H_ */ diff --git a/drivers/net/fjes/fjes_trace.h b/drivers/net/fjes/fjes_trace.h index 1f0a48933f46..22e8f1a4f9ee 100644 --- a/drivers/net/fjes/fjes_trace.h +++ b/drivers/net/fjes/fjes_trace.h @@ -209,6 +209,75 @@ TRACE_EVENT(fjes_hw_unregister_buff_addr_err, TP_printk("%s", __get_str(err)) ); +TRACE_EVENT(fjes_hw_start_debug_req, + TP_PROTO(union fjes_device_command_req *req_buf), + TP_ARGS(req_buf), + TP_STRUCT__entry( + __field(int, length) + __field(int, mode) + __field(phys_addr_t, buffer) + ), + TP_fast_assign( + __entry->length = req_buf->start_trace.length; + __entry->mode = req_buf->start_trace.mode; + __entry->buffer = req_buf->start_trace.buffer[0]; + ), + TP_printk("req_buf=[length=%d, mode=%d, buffer=%p]", + __entry->length, __entry->mode, (void *)__entry->buffer) +); + +TRACE_EVENT(fjes_hw_start_debug, + TP_PROTO(union fjes_device_command_res *res_buf), + TP_ARGS(res_buf), + TP_STRUCT__entry( + __field(int, length) + __field(int, code) + ), + TP_fast_assign( + __entry->length = res_buf->start_trace.length; + __entry->code = res_buf->start_trace.code; + ), + TP_printk("res_buf=[length=%d, code=%d]", __entry->length, __entry->code) +); + +TRACE_EVENT(fjes_hw_start_debug_err, + TP_PROTO(char *err), + TP_ARGS(err), + TP_STRUCT__entry( + __string(err, err) + ), + TP_fast_assign( + __assign_str(err, err) + ), + TP_printk("%s", __get_str(err)) +); + +TRACE_EVENT(fjes_hw_stop_debug, + TP_PROTO(union fjes_device_command_res *res_buf), + TP_ARGS(res_buf), + TP_STRUCT__entry( + __field(int, length) + __field(int, code) + ), + TP_fast_assign( + __entry->length = res_buf->stop_trace.length; + __entry->code = res_buf->stop_trace.code; + ), + TP_printk("res_buf=[length=%d, code=%d]", __entry->length, __entry->code) +); + +TRACE_EVENT(fjes_hw_stop_debug_err, + TP_PROTO(char *err), + TP_ARGS(err), + TP_STRUCT__entry( + __string(err, err) + ), + TP_fast_assign( + __assign_str(err, err) + ), + TP_printk("%s", __get_str(err)) +); + /* tracepoints for fjes_main.c */ TRACE_EVENT(fjes_txrx_stop_req_irq_pre, -- cgit v1.2.3 From c753119e6d1a26a3df04d6fe69d75049082e3f32 Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 14 Oct 2016 20:28:07 +0900 Subject: fjes: Add debugfs entry for EP status information in fjes driver This patch adds debugfs entry to show EP status information. You can get each EP's status information like the following: # cat /sys/kernel/debug/fjes/fjes.0/status EPID STATUS SAME_ZONE CONNECTED ep0 shared Y Y ep1 - - - ep2 unshared N N ep3 unshared N N ep4 unshared N N ep5 unshared N N ep6 unshared N N ep7 unshared N N Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/Makefile | 2 +- drivers/net/fjes/fjes.h | 16 ++++++ drivers/net/fjes/fjes_debugfs.c | 117 ++++++++++++++++++++++++++++++++++++++++ drivers/net/fjes/fjes_main.c | 12 ++++- 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 drivers/net/fjes/fjes_debugfs.c (limited to 'drivers') diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile index 6705d1b523d5..bc47b354c104 100644 --- a/drivers/net/fjes/Makefile +++ b/drivers/net/fjes/Makefile @@ -27,4 +27,4 @@ obj-$(CONFIG_FUJITSU_ES) += fjes.o -fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o fjes_trace.o +fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o fjes_trace.o fjes_debugfs.o diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h index a592fe21c698..0372be3ad8e3 100644 --- a/drivers/net/fjes/fjes.h +++ b/drivers/net/fjes/fjes.h @@ -66,6 +66,10 @@ struct fjes_adapter { bool interrupt_watch_enable; struct fjes_hw hw; + +#ifdef CONFIG_DEBUG_FS + struct dentry *dbg_adapter; +#endif }; extern char fjes_driver_name[]; @@ -74,4 +78,16 @@ extern const u32 fjes_support_mtu[]; void fjes_set_ethtool_ops(struct net_device *); +#ifdef CONFIG_DEBUG_FS +void fjes_dbg_adapter_init(struct fjes_adapter *adapter); +void fjes_dbg_adapter_exit(struct fjes_adapter *adapter); +void fjes_dbg_init(void); +void fjes_dbg_exit(void); +#else +static inline void fjes_dbg_adapter_init(struct fjes_adapter *adapter) {} +static inline void fjes_dbg_adapter_exit(struct fjes_adapter *adapter) {} +static inline void fjes_dbg_init(void) {} +static inline void fjes_dbg_exit(void) {} +#endif /* CONFIG_DEBUG_FS */ + #endif /* FJES_H_ */ diff --git a/drivers/net/fjes/fjes_debugfs.c b/drivers/net/fjes/fjes_debugfs.c new file mode 100644 index 000000000000..30052ebd52bf --- /dev/null +++ b/drivers/net/fjes/fjes_debugfs.c @@ -0,0 +1,117 @@ +/* + * FUJITSU Extended Socket Network Device driver + * Copyright (c) 2015-2016 FUJITSU LIMITED + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + */ + +/* debugfs support for fjes driver */ + +#ifdef CONFIG_DEBUG_FS + +#include +#include +#include + +#include "fjes.h" + +static struct dentry *fjes_debug_root; + +static const char * const ep_status_string[] = { + "unshared", + "shared", + "waiting", + "complete", +}; + +static int fjes_dbg_status_show(struct seq_file *m, void *v) +{ + struct fjes_adapter *adapter = m->private; + struct fjes_hw *hw = &adapter->hw; + int max_epid = hw->max_epid; + int my_epid = hw->my_epid; + int epidx; + + seq_puts(m, "EPID\tSTATUS SAME_ZONE CONNECTED\n"); + for (epidx = 0; epidx < max_epid; epidx++) { + if (epidx == my_epid) { + seq_printf(m, "ep%d\t%-16c %-16c %-16c\n", + epidx, '-', '-', '-'); + } else { + seq_printf(m, "ep%d\t%-16s %-16c %-16c\n", + epidx, + ep_status_string[fjes_hw_get_partner_ep_status(hw, epidx)], + fjes_hw_epid_is_same_zone(hw, epidx) ? 'Y' : 'N', + fjes_hw_epid_is_shared(hw->hw_info.share, epidx) ? 'Y' : 'N'); + } + } + + return 0; +} + +static int fjes_dbg_status_open(struct inode *inode, struct file *file) +{ + return single_open(file, fjes_dbg_status_show, inode->i_private); +} + +static const struct file_operations fjes_dbg_status_fops = { + .owner = THIS_MODULE, + .open = fjes_dbg_status_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void fjes_dbg_adapter_init(struct fjes_adapter *adapter) +{ + const char *name = dev_name(&adapter->plat_dev->dev); + struct dentry *pfile; + + adapter->dbg_adapter = debugfs_create_dir(name, fjes_debug_root); + if (!adapter->dbg_adapter) { + dev_err(&adapter->plat_dev->dev, + "debugfs entry for %s failed\n", name); + return; + } + + pfile = debugfs_create_file("status", 0444, adapter->dbg_adapter, + adapter, &fjes_dbg_status_fops); + if (!pfile) + dev_err(&adapter->plat_dev->dev, + "debugfs status for %s failed\n", name); +} + +void fjes_dbg_adapter_exit(struct fjes_adapter *adapter) +{ + debugfs_remove_recursive(adapter->dbg_adapter); + adapter->dbg_adapter = NULL; +} + +void fjes_dbg_init(void) +{ + fjes_debug_root = debugfs_create_dir(fjes_driver_name, NULL); + if (!fjes_debug_root) + pr_info("init of debugfs failed\n"); +} + +void fjes_dbg_exit(void) +{ + debugfs_remove_recursive(fjes_debug_root); + fjes_debug_root = NULL; +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 4c135ae11978..359e7a5ca4c6 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -1257,6 +1257,8 @@ static int fjes_probe(struct platform_device *plat_dev) netif_carrier_off(netdev); + fjes_dbg_adapter_init(adapter); + return 0; err_hw_exit: @@ -1274,6 +1276,8 @@ static int fjes_remove(struct platform_device *plat_dev) struct fjes_adapter *adapter = netdev_priv(netdev); struct fjes_hw *hw = &adapter->hw; + fjes_dbg_adapter_exit(adapter); + cancel_delayed_work_sync(&adapter->interrupt_watch_task); cancel_work_sync(&adapter->unshare_watch_task); cancel_work_sync(&adapter->raise_intr_rxdata_task); @@ -1478,9 +1482,13 @@ static int __init fjes_init_module(void) pr_info("%s - version %s - %s\n", fjes_driver_string, fjes_driver_version, fjes_copyright); + fjes_dbg_init(); + result = platform_driver_register(&fjes_driver); - if (result < 0) + if (result < 0) { + fjes_dbg_exit(); return result; + } result = acpi_bus_register_driver(&fjes_acpi_driver); if (result < 0) @@ -1490,6 +1498,7 @@ static int __init fjes_init_module(void) fail_acpi_driver: platform_driver_unregister(&fjes_driver); + fjes_dbg_exit(); return result; } @@ -1500,6 +1509,7 @@ static void __exit fjes_exit_module(void) { acpi_bus_unregister_driver(&fjes_acpi_driver); platform_driver_unregister(&fjes_driver); + fjes_dbg_exit(); } module_exit(fjes_exit_module); -- cgit v1.2.3 From 8f87d7750515a4b6f92947ebe012bf6a503ed48e Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 14 Oct 2016 20:28:15 +0900 Subject: fjes: Update fjes driver version : 1.2 Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 359e7a5ca4c6..f36eb4ad40b7 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -30,7 +30,7 @@ #include "fjes_trace.h" #define MAJ 1 -#define MIN 1 +#define MIN 2 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) #define DRV_NAME "fjes" char fjes_driver_name[] = DRV_NAME; -- cgit v1.2.3 From c13fb7789096596f7cd5a64b24dbb66116bfc519 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 14 Oct 2016 14:55:02 +0100 Subject: drm/i915: Fix cxsr_latency_table reorg I have re-ordered some struct members in patch: commit 44a655cae3043453f9dd8076538712d52e2e0ce4 Author: Tvrtko Ursulin Date: Thu Oct 13 11:09:23 2016 +0100 drm/i915: Shrink cxsr_latency_table but that particular one is not initialized with named initializers which broke it. Move the bitfields back at the beginning. Space saving is still there. Signed-off-by: Tvrtko Ursulin Fixes: 44a655cae304 ("drm/i915: Shrink cxsr_latency_table") Cc: Joonas Lahtinen Cc: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476453302-7580-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a885b2ac9618..5bc115496355 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -807,14 +807,14 @@ struct intel_watermark_params { }; struct cxsr_latency { + bool is_desktop : 1; + bool is_ddr3 : 1; u16 fsb_freq; u16 mem_freq; u16 display_sr; u16 display_hpll_disable; u16 cursor_sr; u16 cursor_hpll_disable; - bool is_desktop : 1; - bool is_ddr3 : 1; }; #define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base) -- cgit v1.2.3 From ab530f63e7fbac2b0a233da9d31e21a86d1863f5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 15 Oct 2016 17:40:30 +0200 Subject: ipvlan: constify l3mdev_ops structure This l3mdev_ops structure is only stored in the l3mdev_ops field of a net_device structure. This field is declared const, so the l3mdev_ops structure can be declared as const also. Additionally drop the __read_mostly annotation. The semantic patch that adds const is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct l3mdev_ops i@p = { ... }; @ok@ identifier r.i; struct net_device *e; position p; @@ e->l3mdev_ops = &i@p; @bad@ position p != {r.p,ok.p}; identifier r.i; struct l3mdev_ops e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct l3mdev_ops i = { ... }; // The effect on the layout of the .o file is shown by the following output of the size command, first before then after the transformation: text data bss dec hex filename 7364 466 52 7882 1eca drivers/net/ipvlan/ipvlan_main.o 7412 434 52 7898 1eda drivers/net/ipvlan/ipvlan_main.o Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index f442eb366863..ab90b22e778c 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -26,7 +26,7 @@ static struct nf_hook_ops ipvl_nfops[] __read_mostly = { }, }; -static struct l3mdev_ops ipvl_l3mdev_ops __read_mostly = { +static const struct l3mdev_ops ipvl_l3mdev_ops = { .l3mdev_l3_rcv = ipvlan_l3_rcv, }; -- cgit v1.2.3 From 7126bc2e8d60c2a00539bf96b1005f3015be87a5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 15 Oct 2016 19:09:13 -0400 Subject: lustre: switch to use of ->d_init() Signed-off-by: Al Viro --- drivers/staging/lustre/lustre/llite/dcache.c | 33 +++++----------------- .../staging/lustre/lustre/llite/llite_internal.h | 17 ++--------- drivers/staging/lustre/lustre/llite/llite_nfs.c | 22 ++++----------- drivers/staging/lustre/lustre/llite/namei.c | 13 +-------- drivers/staging/lustre/lustre/llite/statahead.c | 4 +-- 5 files changed, 18 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 0e45d8fc4d7c..65bf0c401b44 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -57,9 +57,6 @@ static void ll_release(struct dentry *de) LASSERT(de); lld = ll_d2d(de); - if (!lld) /* NFS copies the de->d_op methods (bug 4655) */ - return; - if (lld->lld_it) { ll_intent_release(lld->lld_it); kfree(lld->lld_it); @@ -126,30 +123,13 @@ static int ll_ddelete(const struct dentry *de) return 0; } -int ll_d_init(struct dentry *de) +static int ll_d_init(struct dentry *de) { - CDEBUG(D_DENTRY, "ldd on dentry %pd (%p) parent %p inode %p refc %d\n", - de, de, de->d_parent, d_inode(de), d_count(de)); - - if (!de->d_fsdata) { - struct ll_dentry_data *lld; - - lld = kzalloc(sizeof(*lld), GFP_NOFS); - if (likely(lld)) { - spin_lock(&de->d_lock); - if (likely(!de->d_fsdata)) { - de->d_fsdata = lld; - __d_lustre_invalidate(de); - } else { - kfree(lld); - } - spin_unlock(&de->d_lock); - } else { - return -ENOMEM; - } - } - LASSERT(de->d_op == &ll_d_ops); - + struct ll_dentry_data *lld = kzalloc(sizeof(*lld), GFP_KERNEL); + if (unlikely(!lld)) + return -ENOMEM; + lld->lld_invalid = 1; + de->d_fsdata = lld; return 0; } @@ -300,6 +280,7 @@ static int ll_revalidate_nd(struct dentry *dentry, unsigned int flags) } const struct dentry_operations ll_d_ops = { + .d_init = ll_d_init, .d_revalidate = ll_revalidate_nd, .d_release = ll_release, .d_delete = ll_ddelete, diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 4bc551279aa4..507c6039b7a9 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -801,7 +801,6 @@ int ll_hsm_release(struct inode *inode); /* llite/dcache.c */ -int ll_d_init(struct dentry *de); extern const struct dentry_operations ll_d_ops; void ll_intent_drop_lock(struct lookup_intent *); void ll_intent_release(struct lookup_intent *); @@ -1189,7 +1188,7 @@ dentry_may_statahead(struct inode *dir, struct dentry *dentry) * 'lld_sa_generation == lli->lli_sa_generation'. */ ldd = ll_d2d(dentry); - if (ldd && ldd->lld_sa_generation == lli->lli_sa_generation) + if (ldd->lld_sa_generation == lli->lli_sa_generation) return false; return true; @@ -1317,17 +1316,7 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode, static inline int d_lustre_invalid(const struct dentry *dentry) { - struct ll_dentry_data *lld = ll_d2d(dentry); - - return !lld || lld->lld_invalid; -} - -static inline void __d_lustre_invalidate(struct dentry *dentry) -{ - struct ll_dentry_data *lld = ll_d2d(dentry); - - if (lld) - lld->lld_invalid = 1; + return ll_d2d(dentry)->lld_invalid; } /* @@ -1343,7 +1332,7 @@ static inline void d_lustre_invalidate(struct dentry *dentry, int nested) spin_lock_nested(&dentry->d_lock, nested ? DENTRY_D_LOCK_NESTED : DENTRY_D_LOCK_NORMAL); - __d_lustre_invalidate(dentry); + ll_d2d(dentry)->lld_invalid = 1; /* * We should be careful about dentries created by d_obtain_alias(). * These dentries are not put in the dentry tree, instead they are diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 709230571b4b..2ad9dc2665f3 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -169,22 +169,12 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren /* N.B. d_obtain_alias() drops inode ref on error */ result = d_obtain_alias(inode); if (!IS_ERR(result)) { - int rc; - - rc = ll_d_init(result); - if (rc < 0) { - dput(result); - result = ERR_PTR(rc); - } else { - struct ll_dentry_data *ldd = ll_d2d(result); - - /* - * Need to signal to the ll_intent_file_open that - * we came from NFS and so opencache needs to be - * enabled for this one - */ - ldd->lld_nfs_dentry = 1; - } + /* + * Need to signal to the ll_intent_file_open that + * we came from NFS and so opencache needs to be + * enabled for this one + */ + ll_d2d(result)->lld_nfs_dentry = 1; } return result; diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 180f35e3afd9..31a771319cbc 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -395,17 +395,9 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) */ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de) { - struct dentry *new; - int rc; - if (inode) { - new = ll_find_alias(inode, de); + struct dentry *new = ll_find_alias(inode, de); if (new) { - rc = ll_d_init(new); - if (rc < 0) { - dput(new); - return ERR_PTR(rc); - } d_move(new, de); iput(inode); CDEBUG(D_DENTRY, @@ -414,9 +406,6 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de) return new; } } - rc = ll_d_init(de); - if (rc < 0) - return ERR_PTR(rc); d_add(de, inode); CDEBUG(D_DENTRY, "Add dentry %p inode %p refc %d flags %#x\n", de, d_inode(de), d_count(de), de->d_flags); diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 0677513476ec..166323fddc44 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1513,9 +1513,7 @@ out_unplug: */ ldd = ll_d2d(*dentryp); lli = ll_i2info(dir); - /* ldd can be NULL if llite lookup failed. */ - if (ldd) - ldd->lld_sa_generation = lli->lli_sa_generation; + ldd->lld_sa_generation = lli->lli_sa_generation; sa_put(sai, entry); return rc; } -- cgit v1.2.3 From 3f2fe461c7548153dec239f44ff2aebafc8e7fdf Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 18 Aug 2016 11:56:01 -0700 Subject: soc: rockchip: power-domain: Don't (incorrectly) set rk3399 up/down counts On rk3288 it was important that powerdown and powerup counts for the CPU/GPU in the kernel because: * The power on default was crazy long. * We couldn't rely on the firmware to set this up because really this wasn't the firmware's job--the kernel was the only one that really cared about bringing up / down CPUs and the GPU and doing suspend / resume (which involves bringing up / down CPUs). On newer ARM systems (like rk3399) ARM Trusted Firmware is in charge of bringing up and down the CPUs and it really should be in charge of setting all these counts right. After all ATF is in charge of suspend / resume and CPU up / down. Let's get out of the way and let ATF do its job. A few other motivations for doing this: * Depending on another configuration (PMU_24M_EN_CFG) these counts can be either in 24M or 32k cycles. Thus, though ATF isn't really so involved in bringing up the GPU, ATF should probably manage the counts for everything so it can also manage the 24M / 32k choice. * It turns out that (right now) 24M mode is broken on rk3399 and not being used. That means that the count the kernel was programming in (24) was not 1 us (which it seems was intended) but was actually .75 ms * On rk3399 there are actually 2 separate registers for setting CPU up/down time plus 1 register for GPU up/down time. The curent kernel code actually was putting the register for the "little" cores in the "CPU" slot and the register for the "big" cores in the "GPU" slot. It was never initting the GPU counts. Note: this change assumes that ATF will actually set these values at boot, as I'm proposing in . Signed-off-by: Douglas Anderson [ATF change has landed] Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 7acd1517dd37..5f106b16e622 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -597,10 +597,12 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev) * Configure power up and down transition delays for CORE * and GPU domains. */ - rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset, - pmu_info->core_power_transition_time); - rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset, - pmu_info->gpu_power_transition_time); + if (pmu_info->core_power_transition_time) + rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset, + pmu_info->core_power_transition_time); + if (pmu_info->gpu_pwrcnt_offset) + rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset, + pmu_info->gpu_power_transition_time); error = -ENODEV; @@ -722,11 +724,7 @@ static const struct rockchip_pmu_info rk3399_pmu = { .idle_offset = 0x64, .ack_offset = 0x68, - .core_pwrcnt_offset = 0x9c, - .gpu_pwrcnt_offset = 0xa4, - - .core_power_transition_time = 24, - .gpu_power_transition_time = 24, + /* ARM Trusted Firmware manages power transition times */ .num_domains = ARRAY_SIZE(rk3399_pm_domains), .domain_info = rk3399_pm_domains, -- cgit v1.2.3 From 166beccd47e11e4d27477e8ca1d7eda47cf3b2da Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Oct 2016 11:52:06 -0700 Subject: staging/vchi: Convert to current get_user_pages() arguments. Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index c29040fdf9a7..18f268ee6d4b 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -420,7 +420,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, *need_release = 0; /* do not try and release vmalloc pages */ } else { down_read(&task->mm->mmap_sem); - actual_pages = get_user_pages(task, task->mm, + actual_pages = get_user_pages( (unsigned long)buf & ~(PAGE_SIZE - 1), num_pages, (type == PAGELIST_READ) /*Write */ , diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index e11c0e07471b..56c2c48f6801 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -1473,8 +1473,7 @@ dump_phys_mem(void *virt_addr, uint32_t num_bytes) } down_read(¤t->mm->mmap_sem); - rc = get_user_pages(current, /* task */ - current->mm, /* mm */ + rc = get_user_pages( (unsigned long)virt_addr, /* start */ num_pages, /* len */ 0, /* write */ -- cgit v1.2.3 From 232664b386e125962682165353971fba5cb13527 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Oct 2016 11:52:07 -0700 Subject: staging/vchi: Update for rename of page_cache_release() to put_page(). Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 4 ++-- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 18f268ee6d4b..4cb5bff23728 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -439,7 +439,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, while (actual_pages > 0) { actual_pages--; - page_cache_release(pages[actual_pages]); + put_page(pages[actual_pages]); } kfree(pagelist); if (actual_pages == 0) @@ -578,7 +578,7 @@ free_pagelist(PAGELIST_T *pagelist, int actual) offset = 0; set_page_dirty(pg); } - page_cache_release(pg); + put_page(pg); } } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 56c2c48f6801..47df1af2219d 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -1512,7 +1512,7 @@ dump_phys_mem(void *virt_addr, uint32_t num_bytes) kunmap(page); for (page_idx = 0; page_idx < num_pages; page_idx++) - page_cache_release(pages[page_idx]); + put_page(pages[page_idx]); kfree(pages); } -- cgit v1.2.3 From 9872fa751e0bad862161c442d44b7ea597e23676 Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Thu, 6 Oct 2016 11:07:44 +0300 Subject: Staging: sm750fb: fix do not add new typedefs warning This patch fixes the checkpatch.pl warning: "WARNING: do not add new typedefs". Hiding a variables of type 'struct' is not always a good idea,because when we passing them as parameters we tempt to forget that in this proces we work with stack memory and allocatting struct on stack is something that we should manage carefuly. It is also delete the '_t' from the name of the structs and treat a line over 80 character issue in ddk750_mode.c, that appear after my modification. Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 8 ++++---- drivers/staging/sm750fb/ddk750_chip.h | 16 +++++++--------- drivers/staging/sm750fb/ddk750_mode.c | 5 +++-- drivers/staging/sm750fb/sm750_hw.c | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 839d6730bde9..c62ebc159236 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -54,7 +54,7 @@ static unsigned int get_mxclk_freq(void) */ static void setChipClock(unsigned int frequency) { - pll_value_t pll; + struct pll_value pll; unsigned int ulActualMxClk; /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */ @@ -206,7 +206,7 @@ unsigned int ddk750_getVMSize(void) return data; } -int ddk750_initHw(initchip_param_t *pInitParam) +int ddk750_initHw(struct initchip_param *pInitParam) { unsigned int reg; @@ -305,7 +305,7 @@ int ddk750_initHw(initchip_param_t *pInitParam) * M = {1,...,255} * N = {2,...,15} */ -unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) +unsigned int calcPllValue(unsigned int request_orig, struct pll_value *pll) { /* as sm750 register definition, * N located in 2,15 and M located in 1,255 @@ -373,7 +373,7 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) return ret; } -unsigned int formatPllReg(pll_value_t *pPLL) +unsigned int formatPllReg(struct pll_value *pPLL) { #ifndef VALIDATION_CHIP unsigned int POD = pPLL->POD; diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h index 14357fd1cc6b..a4ee35917fde 100644 --- a/drivers/staging/sm750fb/ddk750_chip.h +++ b/drivers/staging/sm750fb/ddk750_chip.h @@ -25,7 +25,7 @@ typedef enum _clock_type_t { } clock_type_t; -typedef struct _pll_value_t { +struct pll_value { clock_type_t clockType; unsigned long inputFreq; /* Input clock frequency to the PLL */ @@ -34,11 +34,10 @@ typedef struct _pll_value_t { unsigned long N; unsigned long OD; unsigned long POD; -} -pll_value_t; +}; /* input struct to initChipParam() function */ -typedef struct _initchip_param_t { +struct initchip_param { unsigned short powerMode; /* Use power mode 0 or 1 */ unsigned short chipClock; /** * Speed of main chip clock in MHz unit @@ -66,14 +65,13 @@ typedef struct _initchip_param_t { */ /* More initialization parameter can be added if needed */ -} -initchip_param_t; +}; logical_chip_type_t sm750_get_chip_type(void); -unsigned int calcPllValue(unsigned int request, pll_value_t *pll); -unsigned int formatPllReg(pll_value_t *pPLL); +unsigned int calcPllValue(unsigned int request, struct pll_value *pll); +unsigned int formatPllReg(struct pll_value *pPLL); void ddk750_set_mmio(void __iomem *, unsigned short, char); unsigned int ddk750_getVMSize(void); -int ddk750_initHw(initchip_param_t *); +int ddk750_initHw(struct initchip_param *); #endif diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index 05b83646c2d5..4bbf0c47dc16 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -72,7 +72,8 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, /* only timing related registers will be programed */ -static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) +static int programModeRegisters(mode_parameter_t *pModeParam, + struct pll_value *pll) { int ret = 0; int cnt = 0; @@ -201,7 +202,7 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock) { - pll_value_t pll; + struct pll_value pll; unsigned int uiActualPixelClk; pll.inputFreq = DEFAULT_INPUT_CLOCK; diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 7dd208caa5eb..74a97b40a17d 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -100,7 +100,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) if (parm->master_clk == 0) parm->master_clk = parm->chip_clk / 3; - ddk750_initHw((initchip_param_t *)&sm750_dev->initParm); + ddk750_initHw((struct initchip_param *)&sm750_dev->initParm); /* for sm718, open pci burst */ if (sm750_dev->devid == 0x718) { POKE32(SYSTEM_CTRL, -- cgit v1.2.3 From 14c681ea83adcbb33ed31c50cda1a2297bbade7e Mon Sep 17 00:00:00 2001 From: Muraru Mihaela Date: Mon, 3 Oct 2016 17:55:18 +0300 Subject: Staging: sm750fb: use unsigned int instead unsigned This patch fixes a WARNING: Prefer 'unsigned int' to bare use of 'unsigned', found by checkpatch.pl. By fixing this the types of the parameters of the function become more explicit. Signed-off-by: Muraru Mihaela Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 7d90e250142c..8770a46c3c67 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -575,11 +575,11 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var, return hw_sm750_crtc_checkMode(crtc, var); } -static int lynxfb_ops_setcolreg(unsigned regno, - unsigned red, - unsigned green, - unsigned blue, - unsigned transp, +static int lynxfb_ops_setcolreg(unsigned int regno, + unsigned int red, + unsigned int green, + unsigned int blue, + unsigned int transp, struct fb_info *info) { struct lynxfb_par *par; -- cgit v1.2.3 From 3d30311c0e4d834c94e6a27d6242a942d6a76b85 Mon Sep 17 00:00:00 2001 From: Varsha Rao Date: Sun, 9 Oct 2016 16:43:56 +0530 Subject: staging: vt6655: Removes unnecessary blank lines. This patch fixes the checkpatch issue of multiple blank lines, by removing them. Signed-off-by: Varsha Rao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 1 - drivers/staging/vt6655/device_main.c | 1 - drivers/staging/vt6655/mac.c | 1 - drivers/staging/vt6655/power.c | 1 - drivers/staging/vt6655/power.h | 1 - 5 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index de503a316e71..7c3ae92d00e4 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -2162,7 +2162,6 @@ bool BBbVT3253Init(struct vnt_private *priv) byVT3253B0_AIROHA2230[ii][0], byVT3253B0_AIROHA2230[ii][1]); - /* {{ RobertYu:20050223, request by JerryChung */ /* Init ANT B select,TX Config CR09 = 0x61->0x45, * 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index f109eeac358d..9b2ec257b9f3 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1272,7 +1272,6 @@ static void vnt_remove_interface(struct ieee80211_hw *hw, priv->op_mode = NL80211_IFTYPE_UNSPECIFIED; } - static int vnt_config(struct ieee80211_hw *hw, u32 changed) { struct vnt_private *priv = hw->priv; diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 8e13f7f41415..d3f4eb2d02af 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -147,7 +147,6 @@ void MACvSetShortRetryLimit(struct vnt_private *priv, iowrite8(byRetryLimit, io_base + MAC_REG_SRT); } - /* * Description: * Set 802.11 Long Retry Limit diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 7d6e7464ae51..1506b1bb5d55 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -133,7 +133,6 @@ PSvDisablePowerSaving( priv->bPWBitOn = false; } - /* * * Routine Description: diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h index d82dd8d6d68b..d619c426b941 100644 --- a/drivers/staging/vt6655/power.h +++ b/drivers/staging/vt6655/power.h @@ -46,7 +46,6 @@ PSvEnablePowerSaving( unsigned short wListenInterval ); - bool PSbIsNextTBTTWakeUp( struct vnt_private * -- cgit v1.2.3 From cb026e398852729cae02b105cf42a1863df78988 Mon Sep 17 00:00:00 2001 From: Sidhant Gupta Date: Mon, 3 Oct 2016 16:21:09 +0530 Subject: staging: greybus: Fix a commit coding style issue. Fixes a comment coding style warning by adding 2 blank lines. Issue found by checkpatch. Signed-off-by: Sidhant Gupta Acked-by: Johan Hovold Reviewed-by: Vaishali Thakkar Acked-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/arche-apb-ctrl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 70323aa11f24..103d629043cd 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -285,8 +285,10 @@ static ssize_t state_store(struct device *dev, if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING) return count; - /* First we want to make sure we power off everything - * and then enter FW flashing state */ + /* + * First we want to make sure we power off everything + * and then enter FW flashing state + */ poweroff_seq(pdev); ret = fw_flashing_seq(pdev); } else { -- cgit v1.2.3 From 1047cc1359a2f502fc7a148dcaf7ebcaba8c62bc Mon Sep 17 00:00:00 2001 From: Hisao Tanabe Date: Mon, 3 Oct 2016 23:45:15 +0900 Subject: staging: greybus: fix block comment This patch fix the coding style problem of block comment detected by the checkpatch.pl. WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Hisao Tanabe Acked-by: Johan Hovold Acked-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/arche-apb-ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 103d629043cd..3fda0cd6bb42 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -183,7 +183,7 @@ static int standby_boot_seq(struct platform_device *pdev) * Pasted from WDM spec, * - A falling edge on POWEROFF_L is detected (a) * - WDM enters standby mode, but no output signals are changed - * */ + */ /* TODO: POWEROFF_L is input to WDM module */ apb->state = ARCHE_PLATFORM_STATE_STANDBY; -- cgit v1.2.3 From a2a87b224b33f30ca5172945c132e39260e95403 Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman Date: Tue, 4 Oct 2016 13:06:10 -0700 Subject: staging: greybus: Add blank line after declaration Add a blank line after a declaration. Error found by checkpatch. Signed-off-by: Elizabeth Ferdman Reviewed-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_topology.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index b6251691a33d..5c76067a55f7 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -114,6 +114,7 @@ static int gbaudio_map_widgetname(struct gbaudio_module_info *module, const char *name) { struct gbaudio_widget *widget; + list_for_each_entry(widget, &module->widget_list, list) { if (!strncmp(widget->name, name, NAME_SIZE)) return widget->id; -- cgit v1.2.3 From 02ae32f754a6cb006a7dc5305bf6e5ade1a95095 Mon Sep 17 00:00:00 2001 From: Chase Metzger Date: Thu, 6 Oct 2016 19:38:41 -0700 Subject: drivers: staging: greybus: Fixed CHECKS for brace issues Added braces to else statements where checkpatch complained. Signed-off-by: Chase Metzger Acked-by: Viresh Kumar Reviewed-by: Vaibhav Agarwal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_topology.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 5c76067a55f7..8b216ca99cf9 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -1045,8 +1045,10 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, control->texts = (const char * const *) gb_generate_enum_strings(module, gbenum); control->items = gbenum->items; - } else + } else { csize = sizeof(struct gb_audio_control); + } + *w_size += csize; curr = (void *)curr + csize; list_add(&control->list, &module->widget_ctl_list); @@ -1191,8 +1193,9 @@ static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module, control->texts = (const char * const *) gb_generate_enum_strings(module, gbenum); control->items = gbenum->items; - } else + } else { csize = sizeof(struct gb_audio_control); + } list_add(&control->list, &module->ctl_list); dev_dbg(module->dev, "%d:%s created of type %d\n", curr->id, -- cgit v1.2.3 From 43ff7f53de2294a83dcf84b35de6ffa1ffafae9d Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 6 Oct 2016 23:40:01 +0530 Subject: Staging: vc04_services: vchiq_arm: Remove unused function remote_event_destroy Remove function remote_event_destroy as it is not used anywhere in the kernel. Function detected using Coccinelle but changes done by hand. Script: @initialize:python@ @@ def display(name,p): print(name,p[0].file) @r1@ identifier func; type T; position p; @@ static T func@p(...) { ... } @r@ identifier r1.func; @@ func @script:python depends on !r@ func << r1.func; p << r1.p; @@ display(func,p) Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 2c98da4307df..7ed32772997d 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -414,12 +414,6 @@ remote_event_create(REMOTE_EVENT_T *event) sema_init(event->event, 0); } -static inline void -remote_event_destroy(REMOTE_EVENT_T *event) -{ - (void)event; -} - static inline int remote_event_wait(REMOTE_EVENT_T *event) { -- cgit v1.2.3 From 91171c3414c6c69b580875ade6c84573f2a52977 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Sun, 2 Oct 2016 22:27:57 -0400 Subject: staging: lustre: obdclass: fix race during key quiescency Upon umount, presumably of last device using same OSD back-end, to prepare for module unload, lu_context_key_quiesce() is run to remove all module's key reference in any context linked on lu_context_remembered list. Threads must protect against such transversal processing when exiting from its context. Signed-off-by: Bruno Faccini Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5264 Reviewed-on: http://review.whamcloud.com/13103 Reviewed-by: Mike Pershin Reviewed-by: Alex Zhuravlev Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lu_object.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 054e567e6c8d..f0e74c66d424 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -1663,6 +1663,9 @@ void lu_context_exit(struct lu_context *ctx) ctx->lc_state = LCS_LEFT; if (ctx->lc_tags & LCT_HAS_EXIT && ctx->lc_value) { for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) { + /* could race with key quiescency */ + if (ctx->lc_tags & LCT_REMEMBER) + spin_lock(&lu_keys_guard); if (ctx->lc_value[i]) { struct lu_context_key *key; @@ -1671,6 +1674,8 @@ void lu_context_exit(struct lu_context *ctx) key->lct_exit(ctx, key, ctx->lc_value[i]); } + if (ctx->lc_tags & LCT_REMEMBER) + spin_unlock(&lu_keys_guard); } } } -- cgit v1.2.3 From fbe93b34fa2aab20594ae4333d917c1c6080a004 Mon Sep 17 00:00:00 2001 From: Patrick Valentin Date: Sun, 2 Oct 2016 22:27:58 -0400 Subject: staging: lustre: obdclass: Add synchro in lu_context_key_degister() When unloading a module, it may happen that lu_context_key_degister() removes a key while a thread is either registering it in a new context (lu_context_init(), lu_context_refill()), or using it when exiting from a context (lu_context__exit(), lu_context__fini()). In these cases, we reference a key which no longer exists, and the system crashes either because we use a *POISON'ed* pointer in key_fini() -> key->lct_fini(), or because one of the following assertions fails: - lu_context_key_degister(): ASSERTION(cfs_atomic_read(&key->lct_used) == 1) failed: key has instances: 2 - lu_context_exit(): ASSERTION(key != NULL) - key_fini(): ASSERTION(atomic_read(&key->lct_used) > 1) This can also leads to SLAB objects which are not freed: slab error in kmem_cache_destroy(): cache `echo_thread_kmem': Can't free all objects Note: ptlrpc service threads need to call lu_context_init/fini in each loop (for each RPC), and this could be a big performance issue on fat SMP machines if we add serialization by a spinlock and need to lock/unlock it for multiple times for each RPC. So the aim of this patch, which only impacts some low frequently used functions, is: 1) to add a synchronization in lu_context_key_quiesce(), also called by lu_context_key_degister(), to wait until all key::lct_init() methods have completed, by serializing with keys_fill() 2) to add a synchronization in lu_context_key_degister(), to wait until all transient contexts referencing this key have run key::lct_fini() method Signed-off-by: Patrick Valentin Signed-off-by: Gregoire Pichon Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6049 Reviewed-on: http://review.whamcloud.com/13164 Reviewed-by: Fan Yong Reviewed-by: Alex Zhuravlev Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lu_object.c | 58 ++++++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index f0e74c66d424..e031fd297eb6 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -1311,6 +1311,7 @@ enum { static struct lu_context_key *lu_keys[LU_CONTEXT_KEY_NR] = { NULL, }; static DEFINE_SPINLOCK(lu_keys_guard); +static atomic_t lu_key_initing_cnt = ATOMIC_INIT(0); /** * Global counter incremented whenever key is registered, unregistered, @@ -1385,6 +1386,19 @@ void lu_context_key_degister(struct lu_context_key *key) ++key_set_version; spin_lock(&lu_keys_guard); key_fini(&lu_shrink_env.le_ctx, key->lct_index); + + /** + * Wait until all transient contexts referencing this key have + * run lu_context_key::lct_fini() method. + */ + while (atomic_read(&key->lct_used) > 1) { + spin_unlock(&lu_keys_guard); + CDEBUG(D_INFO, "lu_context_key_degister: \"%s\" %p, %d\n", + key->lct_owner ? key->lct_owner->name : "", key, + atomic_read(&key->lct_used)); + schedule(); + spin_lock(&lu_keys_guard); + } if (lu_keys[key->lct_index]) { lu_keys[key->lct_index] = NULL; lu_ref_fini(&key->lct_reference); @@ -1510,11 +1524,26 @@ void lu_context_key_quiesce(struct lu_context_key *key) * XXX layering violation. */ cl_env_cache_purge(~0); - key->lct_tags |= LCT_QUIESCENT; /* * XXX memory barrier has to go here. */ spin_lock(&lu_keys_guard); + key->lct_tags |= LCT_QUIESCENT; + + /** + * Wait until all lu_context_key::lct_init() methods + * have completed. + */ + while (atomic_read(&lu_key_initing_cnt) > 0) { + spin_unlock(&lu_keys_guard); + CDEBUG(D_INFO, "lu_context_key_quiesce: \"%s\" %p, %d (%d)\n", + key->lct_owner ? key->lct_owner->name : "", + key, atomic_read(&key->lct_used), + atomic_read(&lu_key_initing_cnt)); + schedule(); + spin_lock(&lu_keys_guard); + } + list_for_each_entry(ctx, &lu_context_remembered, lc_remember) key_fini(ctx, key->lct_index); spin_unlock(&lu_keys_guard); @@ -1546,6 +1575,19 @@ static int keys_fill(struct lu_context *ctx) { unsigned int i; + /* + * A serialisation with lu_context_key_quiesce() is needed, but some + * "key->lct_init()" are calling kernel memory allocation routine and + * can't be called while holding a spin_lock. + * "lu_keys_guard" is held while incrementing "lu_key_initing_cnt" + * to ensure the start of the serialisation. + * An atomic_t variable is still used, in order not to reacquire the + * lock when decrementing the counter. + */ + spin_lock(&lu_keys_guard); + atomic_inc(&lu_key_initing_cnt); + spin_unlock(&lu_keys_guard); + LINVRNT(ctx->lc_value); for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) { struct lu_context_key *key; @@ -1563,12 +1605,19 @@ static int keys_fill(struct lu_context *ctx) LINVRNT(key->lct_init); LINVRNT(key->lct_index == i); + LASSERT(key->lct_owner); + if (!(ctx->lc_tags & LCT_NOREF) && + !try_module_get(key->lct_owner)) { + /* module is unloading, skip this key */ + continue; + } + value = key->lct_init(ctx, key); - if (IS_ERR(value)) + if (unlikely(IS_ERR(value))) { + atomic_dec(&lu_key_initing_cnt); return PTR_ERR(value); + } - if (!(ctx->lc_tags & LCT_NOREF)) - try_module_get(key->lct_owner); lu_ref_add_atomic(&key->lct_reference, "ctx", ctx); atomic_inc(&key->lct_used); /* @@ -1582,6 +1631,7 @@ static int keys_fill(struct lu_context *ctx) } ctx->lc_version = key_set_version; } + atomic_dec(&lu_key_initing_cnt); return 0; } -- cgit v1.2.3 From 0cd9993113732bea8a86ec4da6c7eee64bcb89ae Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:27:59 -0400 Subject: staging: lustre: llite: remove client Size on MDS support Size on MDS support have been in preview since at least 2.0.0. Remove support for it from lustre/llite/. Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6047 Reviewed-on: http://review.whamcloud.com/13126 Reviewed-by: Andreas Dilger Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/Makefile | 2 +- drivers/staging/lustre/lustre/llite/file.c | 97 +---- drivers/staging/lustre/lustre/llite/glimpse.c | 109 +++--- drivers/staging/lustre/lustre/llite/llite_close.c | 395 --------------------- .../staging/lustre/lustre/llite/llite_internal.h | 56 +-- drivers/staging/lustre/lustre/llite/llite_lib.c | 127 +------ drivers/staging/lustre/lustre/llite/namei.c | 8 - drivers/staging/lustre/lustre/llite/vvp_dev.c | 3 +- drivers/staging/lustre/lustre/llite/vvp_internal.h | 18 +- drivers/staging/lustre/lustre/llite/vvp_io.c | 11 - drivers/staging/lustre/lustre/llite/vvp_object.c | 4 +- drivers/staging/lustre/lustre/llite/vvp_page.c | 24 +- drivers/staging/lustre/lustre/llite/vvp_req.c | 13 +- 13 files changed, 91 insertions(+), 776 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/llite/llite_close.c (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index 1ac0940bd8df..3690bee45f09 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_LUSTRE_FS) += lustre.o -lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \ +lustre-y := dcache.o dir.o file.o llite_lib.o llite_nfs.o \ rw.o namei.o symlink.o llite_mmap.o range_lock.o \ xattr.o xattr_cache.o rw26.o super25.o statahead.o \ glimpse.o lcommon_cl.o lcommon_misc.o \ diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index e1d784bae064..811eb8bcefdb 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -86,7 +86,6 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, op_data->op_attr.ia_size = i_size_read(inode); op_data->op_attr_blocks = inode->i_blocks; op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags); - op_data->op_ioepoch = ll_i2info(inode)->lli_ioepoch; if (fh) op_data->op_handle = *fh; @@ -95,8 +94,7 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, } /** - * Closes the IO epoch and packs all the attributes into @op_data for - * the CLOSE rpc. + * Packs all the attributes into @op_data for the CLOSE rpc. */ static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data, struct obd_client_handle *och) @@ -108,11 +106,7 @@ static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data, if (!(och->och_flags & FMODE_WRITE)) goto out; - if (!exp_connect_som(ll_i2mdexp(inode)) || !S_ISREG(inode->i_mode)) - op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS; - else - ll_ioepoch_close(inode, op_data, &och, 0); - + op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS; out: ll_pack_inode2opdata(inode, op_data, &och->och_fh); ll_prep_md_op_data(op_data, inode, NULL, NULL, @@ -128,7 +122,6 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, struct md_op_data *op_data; struct ptlrpc_request *req = NULL; struct obd_device *obd = class_exp2obd(exp); - int epoch_close = 1; int rc; if (!obd) { @@ -157,22 +150,9 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, op_data->op_lease_handle = och->och_lease_handle; op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS; } - epoch_close = op_data->op_flags & MF_EPOCH_CLOSE; + rc = md_close(md_exp, op_data, och->och_mod, &req); - if (rc == -EAGAIN) { - /* This close must have the epoch closed. */ - LASSERT(epoch_close); - /* MDS has instructed us to obtain Size-on-MDS attribute from - * OSTs and send setattr to back to MDS. - */ - rc = ll_som_update(inode, op_data); - if (rc) { - CERROR("%s: inode "DFID" mdc Size-on-MDS update failed: rc = %d\n", - ll_i2mdexp(inode)->exp_obd->obd_name, - PFID(ll_inode2fid(inode)), rc); - rc = 0; - } - } else if (rc) { + if (rc) { CERROR("%s: inode "DFID" mdc close failed: rc = %d\n", ll_i2mdexp(inode)->exp_obd->obd_name, PFID(ll_inode2fid(inode)), rc); @@ -200,15 +180,10 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, ll_finish_md_op_data(op_data); out: - if (exp_connect_som(exp) && !epoch_close && - S_ISREG(inode->i_mode) && (och->och_flags & FMODE_WRITE)) { - ll_queue_done_writing(inode, LLIF_DONE_WRITING); - } else { - md_clear_open_replay_data(md_exp, och); - /* Free @och if it is not waiting for DONE_WRITING. */ - och->och_fh.cookie = DEAD_HANDLE_MAGIC; - kfree(och); - } + md_clear_open_replay_data(md_exp, och); + och->och_fh.cookie = DEAD_HANDLE_MAGIC; + kfree(och); + if (req) /* This is close request */ ptlrpc_req_finished(req); return rc; @@ -437,20 +412,6 @@ out: return rc; } -/** - * Assign an obtained @ioepoch to client's inode. No lock is needed, MDS does - * not believe attributes if a few ioepoch holders exist. Attributes for - * previous ioepoch if new one is opened are also skipped by MDS. - */ -void ll_ioepoch_open(struct ll_inode_info *lli, __u64 ioepoch) -{ - if (ioepoch && lli->lli_ioepoch != ioepoch) { - lli->lli_ioepoch = ioepoch; - CDEBUG(D_INODE, "Epoch %llu opened on "DFID"\n", - ioepoch, PFID(&lli->lli_fid)); - } -} - static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it, struct obd_client_handle *och) { @@ -470,23 +431,17 @@ static int ll_local_open(struct file *file, struct lookup_intent *it, struct ll_file_data *fd, struct obd_client_handle *och) { struct inode *inode = file_inode(file); - struct ll_inode_info *lli = ll_i2info(inode); LASSERT(!LUSTRE_FPRIVATE(file)); LASSERT(fd); if (och) { - struct mdt_body *body; int rc; rc = ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och); if (rc != 0) return rc; - - body = req_capsule_server_get(&it->it_request->rq_pill, - &RMF_MDT_BODY); - ll_ioepoch_open(lli, body->mbo_ioepoch); } LUSTRE_FPRIVATE(file) = fd; @@ -912,7 +867,7 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, /* Fills the obdo with the attributes for the lsm */ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, - struct obdo *obdo, __u64 ioepoch, int dv_flags) + struct obdo *obdo, int dv_flags) { struct ptlrpc_request_set *set; struct obd_info oinfo = { }; @@ -924,13 +879,11 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, oinfo.oi_oa = obdo; oinfo.oi_oa->o_oi = lsm->lsm_oi; oinfo.oi_oa->o_mode = S_IFREG; - oinfo.oi_oa->o_ioepoch = ioepoch; oinfo.oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE | OBD_MD_FLBLOCKS | OBD_MD_FLBLKSZ | OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME | - OBD_MD_FLGROUP | OBD_MD_FLEPOCH | - OBD_MD_FLDATAVERSION; + OBD_MD_FLGROUP | OBD_MD_FLDATAVERSION; if (dv_flags & (LL_DV_WR_FLUSH | LL_DV_RD_FLUSH)) { oinfo.oi_oa->o_valid |= OBD_MD_FLFLAGS; oinfo.oi_oa->o_flags |= OBD_FL_SRVLOCK; @@ -961,32 +914,6 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, return rc; } -/** - * Performs the getattr on the inode and updates its fields. - * If @sync != 0, perform the getattr under the server-side lock. - */ -int ll_inode_getattr(struct inode *inode, struct obdo *obdo, - __u64 ioepoch, int sync) -{ - struct lov_stripe_md *lsm; - int rc; - - lsm = ccc_inode_lsm_get(inode); - rc = ll_lsm_getattr(lsm, ll_i2dtexp(inode), - obdo, ioepoch, sync ? LL_DV_RD_FLUSH : 0); - if (rc == 0) { - struct ost_id *oi = lsm ? &lsm->lsm_oi : &obdo->o_oi; - - obdo_refresh_inode(inode, obdo, obdo->o_valid); - CDEBUG(D_INODE, "objid " DOSTID " size %llu, blocks %llu, blksize %lu\n", - POSTID(oi), i_size_read(inode), - (unsigned long long)inode->i_blocks, - 1UL << inode->i_blkbits); - } - ccc_inode_lsm_put(inode, lsm); - return rc; -} - int ll_merge_attr(const struct lu_env *env, struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); @@ -1049,7 +976,7 @@ int ll_glimpse_ioctl(struct ll_sb_info *sbi, struct lov_stripe_md *lsm, struct obdo obdo = { 0 }; int rc; - rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, &obdo, 0, 0); + rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, &obdo, 0); if (rc == 0) { st->st_size = obdo.o_size; st->st_blocks = obdo.o_blocks; @@ -1784,7 +1711,7 @@ int ll_data_version(struct inode *inode, __u64 *data_version, int flags) goto out; } - rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, obdo, 0, flags); + rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, obdo, flags); if (rc == 0) { if (!(obdo->o_valid & OBD_MD_FLDATAVERSION)) rc = -EOPNOTSUPP; diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index 22507b9c6d69..0d1ffadeab46 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -82,65 +82,62 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, { struct ll_inode_info *lli = ll_i2info(inode); const struct lu_fid *fid = lu_object_fid(&clob->co_lu); - int result; + int result = 0; - result = 0; - if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) { - CDEBUG(D_DLMTRACE, "Glimpsing inode " DFID "\n", PFID(fid)); - if (lli->lli_has_smd) { - struct cl_lock *lock = vvp_env_lock(env); - struct cl_lock_descr *descr = &lock->cll_descr; - - /* NOTE: this looks like DLM lock request, but it may - * not be one. Due to CEF_ASYNC flag (translated - * to LDLM_FL_HAS_INTENT by osc), this is - * glimpse request, that won't revoke any - * conflicting DLM locks held. Instead, - * ll_glimpse_callback() will be called on each - * client holding a DLM lock against this file, - * and resulting size will be returned for each - * stripe. DLM lock on [0, EOF] is acquired only - * if there were no conflicting locks. If there - * were conflicting locks, enqueuing or waiting - * fails with -ENAVAIL, but valid inode - * attributes are returned anyway. - */ - *descr = whole_file; - descr->cld_obj = clob; - descr->cld_mode = CLM_READ; - descr->cld_enq_flags = CEF_ASYNC | CEF_MUST; - if (agl) - descr->cld_enq_flags |= CEF_AGL; - /* - * CEF_ASYNC is used because glimpse sub-locks cannot - * deadlock (because they never conflict with other - * locks) and, hence, can be enqueued out-of-order. - * - * CEF_MUST protects glimpse lock from conversion into - * a lockless mode. - */ - result = cl_lock_request(env, io, lock); - if (result < 0) - return result; - - if (!agl) { - ll_merge_attr(env, inode); - if (i_size_read(inode) > 0 && - inode->i_blocks == 0) { - /* - * LU-417: Add dirty pages block count - * lest i_blocks reports 0, some "cp" or - * "tar" may think it's a completely - * sparse file and skip it. - */ - inode->i_blocks = dirty_cnt(inode); - } - } - cl_lock_release(env, lock); - } else { - CDEBUG(D_DLMTRACE, "No objects for inode\n"); + CDEBUG(D_DLMTRACE, "Glimpsing inode " DFID "\n", PFID(fid)); + if (lli->lli_has_smd) { + struct cl_lock *lock = vvp_env_lock(env); + struct cl_lock_descr *descr = &lock->cll_descr; + + /* NOTE: this looks like DLM lock request, but it may + * not be one. Due to CEF_ASYNC flag (translated + * to LDLM_FL_HAS_INTENT by osc), this is + * glimpse request, that won't revoke any + * conflicting DLM locks held. Instead, + * ll_glimpse_callback() will be called on each + * client holding a DLM lock against this file, + * and resulting size will be returned for each + * stripe. DLM lock on [0, EOF] is acquired only + * if there were no conflicting locks. If there + * were conflicting locks, enqueuing or waiting + * fails with -ENAVAIL, but valid inode + * attributes are returned anyway. + */ + *descr = whole_file; + descr->cld_obj = clob; + descr->cld_mode = CLM_READ; + descr->cld_enq_flags = CEF_ASYNC | CEF_MUST; + if (agl) + descr->cld_enq_flags |= CEF_AGL; + /* + * CEF_ASYNC is used because glimpse sub-locks cannot + * deadlock (because they never conflict with other + * locks) and, hence, can be enqueued out-of-order. + * + * CEF_MUST protects glimpse lock from conversion into + * a lockless mode. + */ + result = cl_lock_request(env, io, lock); + if (result < 0) + return result; + + if (!agl) { ll_merge_attr(env, inode); + if (i_size_read(inode) > 0 && !inode->i_blocks) { + /* + * LU-417: Add dirty pages block count + * lest i_blocks reports 0, some "cp" or + * "tar" may think it's a completely + * sparse file and skip it. + */ + inode->i_blocks = dirty_cnt(inode); + } } + + cl_lock_release(env, lock); + } else { + CDEBUG(D_DLMTRACE, "No objects for inode\n"); + ll_merge_attr(env, inode); } return result; diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c deleted file mode 100644 index 8644631bf2ba..000000000000 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/llite/llite_close.c - * - * Lustre Lite routines to issue a secondary close after writeback - */ - -#include - -#define DEBUG_SUBSYSTEM S_LLITE - -#include "llite_internal.h" - -/** records that a write is in flight */ -void vvp_write_pending(struct vvp_object *club, struct vvp_page *page) -{ - struct ll_inode_info *lli = ll_i2info(club->vob_inode); - - spin_lock(&lli->lli_lock); - lli->lli_flags |= LLIF_SOM_DIRTY; - if (page && list_empty(&page->vpg_pending_linkage)) - list_add(&page->vpg_pending_linkage, &club->vob_pending_list); - spin_unlock(&lli->lli_lock); -} - -/** records that a write has completed */ -void vvp_write_complete(struct vvp_object *club, struct vvp_page *page) -{ - struct ll_inode_info *lli = ll_i2info(club->vob_inode); - int rc = 0; - - spin_lock(&lli->lli_lock); - if (page && !list_empty(&page->vpg_pending_linkage)) { - list_del_init(&page->vpg_pending_linkage); - rc = 1; - } - spin_unlock(&lli->lli_lock); - if (rc) - ll_queue_done_writing(club->vob_inode, 0); -} - -/** Queues DONE_WRITING if - * - done writing is allowed; - * - inode has no no dirty pages; - */ -void ll_queue_done_writing(struct inode *inode, unsigned long flags) -{ - struct ll_inode_info *lli = ll_i2info(inode); - struct vvp_object *club = cl2vvp(ll_i2info(inode)->lli_clob); - - spin_lock(&lli->lli_lock); - lli->lli_flags |= flags; - - if ((lli->lli_flags & LLIF_DONE_WRITING) && - list_empty(&club->vob_pending_list)) { - struct ll_close_queue *lcq = ll_i2sbi(inode)->ll_lcq; - - if (lli->lli_flags & LLIF_MDS_SIZE_LOCK) - CWARN("%s: file "DFID"(flags %u) Size-on-MDS valid, done writing allowed and no diry pages\n", - ll_get_fsname(inode->i_sb, NULL, 0), - PFID(ll_inode2fid(inode)), lli->lli_flags); - /* DONE_WRITING is allowed and inode has no dirty page. */ - spin_lock(&lcq->lcq_lock); - - LASSERT(list_empty(&lli->lli_close_list)); - CDEBUG(D_INODE, "adding inode "DFID" to close list\n", - PFID(ll_inode2fid(inode))); - list_add_tail(&lli->lli_close_list, &lcq->lcq_head); - - /* Avoid a concurrent insertion into the close thread queue: - * an inode is already in the close thread, open(), write(), - * close() happen, epoch is closed as the inode is marked as - * LLIF_EPOCH_PENDING. When pages are written inode should not - * be inserted into the queue again, clear this flag to avoid - * it. - */ - lli->lli_flags &= ~LLIF_DONE_WRITING; - - wake_up(&lcq->lcq_waitq); - spin_unlock(&lcq->lcq_lock); - } - spin_unlock(&lli->lli_lock); -} - -/** Pack SOM attributes info @opdata for CLOSE, DONE_WRITING rpc. */ -void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data) -{ - struct ll_inode_info *lli = ll_i2info(inode); - - op_data->op_flags |= MF_SOM_CHANGE; - /* Check if Size-on-MDS attributes are valid. */ - if (lli->lli_flags & LLIF_MDS_SIZE_LOCK) - CERROR("%s: inode "DFID"(flags %u) MDS holds lock on Size-on-MDS attributes\n", - ll_get_fsname(inode->i_sb, NULL, 0), - PFID(ll_inode2fid(inode)), lli->lli_flags); - - if (!cl_local_size(inode)) { - /* Send Size-on-MDS Attributes if valid. */ - op_data->op_attr.ia_valid |= ATTR_MTIME_SET | ATTR_CTIME_SET | - ATTR_ATIME_SET | ATTR_SIZE | ATTR_BLOCKS; - } -} - -/** Closes ioepoch and packs Size-on-MDS attribute if needed into @op_data. */ -void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data, - struct obd_client_handle **och, unsigned long flags) -{ - struct ll_inode_info *lli = ll_i2info(inode); - struct vvp_object *club = cl2vvp(ll_i2info(inode)->lli_clob); - - spin_lock(&lli->lli_lock); - if (!(list_empty(&club->vob_pending_list))) { - if (!(lli->lli_flags & LLIF_EPOCH_PENDING)) { - LASSERT(*och); - LASSERT(!lli->lli_pending_och); - /* Inode is dirty and there is no pending write done - * request yet, DONE_WRITE is to be sent later. - */ - lli->lli_flags |= LLIF_EPOCH_PENDING; - lli->lli_pending_och = *och; - spin_unlock(&lli->lli_lock); - - inode = igrab(inode); - LASSERT(inode); - goto out; - } - if (flags & LLIF_DONE_WRITING) { - /* Some pages are still dirty, it is early to send - * DONE_WRITE. Wait until all pages will be flushed - * and try DONE_WRITE again later. - */ - LASSERT(!(lli->lli_flags & LLIF_DONE_WRITING)); - lli->lli_flags |= LLIF_DONE_WRITING; - spin_unlock(&lli->lli_lock); - - inode = igrab(inode); - LASSERT(inode); - goto out; - } - } - CDEBUG(D_INODE, "Epoch %llu closed on "DFID"\n", - ll_i2info(inode)->lli_ioepoch, PFID(&lli->lli_fid)); - op_data->op_flags |= MF_EPOCH_CLOSE; - - if (flags & LLIF_DONE_WRITING) { - LASSERT(lli->lli_flags & LLIF_SOM_DIRTY); - LASSERT(!(lli->lli_flags & LLIF_DONE_WRITING)); - *och = lli->lli_pending_och; - lli->lli_pending_och = NULL; - lli->lli_flags &= ~LLIF_EPOCH_PENDING; - } else { - /* Pack Size-on-MDS inode attributes only if they has changed */ - if (!(lli->lli_flags & LLIF_SOM_DIRTY)) { - spin_unlock(&lli->lli_lock); - goto out; - } - - /* There is a pending DONE_WRITE -- close epoch with no - * attribute change. - */ - if (lli->lli_flags & LLIF_EPOCH_PENDING) { - spin_unlock(&lli->lli_lock); - goto out; - } - } - - LASSERT(list_empty(&club->vob_pending_list)); - lli->lli_flags &= ~LLIF_SOM_DIRTY; - spin_unlock(&lli->lli_lock); - ll_done_writing_attr(inode, op_data); - -out: - return; -} - -/** - * Cliens updates SOM attributes on MDS (including llog cookies): - * obd_getattr with no lock and md_setattr. - */ -int ll_som_update(struct inode *inode, struct md_op_data *op_data) -{ - struct ll_inode_info *lli = ll_i2info(inode); - struct ptlrpc_request *request = NULL; - __u32 old_flags; - struct obdo *oa; - int rc; - - LASSERT(op_data); - if (lli->lli_flags & LLIF_MDS_SIZE_LOCK) - CERROR("%s: inode "DFID"(flags %u) MDS holds lock on Size-on-MDS attributes\n", - ll_get_fsname(inode->i_sb, NULL, 0), - PFID(ll_inode2fid(inode)), lli->lli_flags); - - oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!oa) { - CERROR("can't allocate memory for Size-on-MDS update.\n"); - return -ENOMEM; - } - - old_flags = op_data->op_flags; - op_data->op_flags = MF_SOM_CHANGE; - - /* If inode is already in another epoch, skip getattr from OSTs. */ - if (lli->lli_ioepoch == op_data->op_ioepoch) { - rc = ll_inode_getattr(inode, oa, op_data->op_ioepoch, - old_flags & MF_GETATTR_LOCK); - if (rc) { - oa->o_valid = 0; - if (rc != -ENOENT) - CERROR("%s: inode_getattr failed - unable to send a Size-on-MDS attribute update for inode "DFID": rc = %d\n", - ll_get_fsname(inode->i_sb, NULL, 0), - PFID(ll_inode2fid(inode)), rc); - } else { - CDEBUG(D_INODE, "Size-on-MDS update on "DFID"\n", - PFID(&lli->lli_fid)); - } - /* Install attributes into op_data. */ - md_from_obdo(op_data, oa, oa->o_valid); - } - - rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, - NULL, 0, NULL, 0, &request, NULL); - ptlrpc_req_finished(request); - - kmem_cache_free(obdo_cachep, oa); - return rc; -} - -/** - * Closes the ioepoch and packs all the attributes into @op_data for - * DONE_WRITING rpc. - */ -static void ll_prepare_done_writing(struct inode *inode, - struct md_op_data *op_data, - struct obd_client_handle **och) -{ - ll_ioepoch_close(inode, op_data, och, LLIF_DONE_WRITING); - /* If there is no @och, we do not do D_W yet. */ - if (!*och) - return; - - ll_pack_inode2opdata(inode, op_data, &(*och)->och_fh); - ll_prep_md_op_data(op_data, inode, NULL, NULL, - 0, 0, LUSTRE_OPC_ANY, NULL); -} - -/** Send a DONE_WRITING rpc. */ -static void ll_done_writing(struct inode *inode) -{ - struct obd_client_handle *och = NULL; - struct md_op_data *op_data; - int rc; - - LASSERT(exp_connect_som(ll_i2mdexp(inode))); - - op_data = kzalloc(sizeof(*op_data), GFP_NOFS); - if (!op_data) - return; - - ll_prepare_done_writing(inode, op_data, &och); - /* If there is no @och, we do not do D_W yet. */ - if (!och) - goto out; - - rc = md_done_writing(ll_i2sbi(inode)->ll_md_exp, op_data, NULL); - if (rc == -EAGAIN) - /* MDS has instructed us to obtain Size-on-MDS attribute from - * OSTs and send setattr to back to MDS. - */ - rc = ll_som_update(inode, op_data); - else if (rc) { - CERROR("%s: inode "DFID" mdc done_writing failed: rc = %d\n", - ll_get_fsname(inode->i_sb, NULL, 0), - PFID(ll_inode2fid(inode)), rc); - } -out: - ll_finish_md_op_data(op_data); - if (och) { - md_clear_open_replay_data(ll_i2sbi(inode)->ll_md_exp, och); - kfree(och); - } -} - -static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq) -{ - struct ll_inode_info *lli = NULL; - - spin_lock(&lcq->lcq_lock); - - if (!list_empty(&lcq->lcq_head)) { - lli = list_entry(lcq->lcq_head.next, struct ll_inode_info, - lli_close_list); - list_del_init(&lli->lli_close_list); - } else if (atomic_read(&lcq->lcq_stop)) { - lli = ERR_PTR(-EALREADY); - } - - spin_unlock(&lcq->lcq_lock); - return lli; -} - -static int ll_close_thread(void *arg) -{ - struct ll_close_queue *lcq = arg; - - complete(&lcq->lcq_comp); - - while (1) { - struct l_wait_info lwi = { 0 }; - struct ll_inode_info *lli; - struct inode *inode; - - l_wait_event_exclusive(lcq->lcq_waitq, - (lli = ll_close_next_lli(lcq)) != NULL, - &lwi); - if (IS_ERR(lli)) - break; - - inode = ll_info2i(lli); - CDEBUG(D_INFO, "done_writing for inode "DFID"\n", - PFID(ll_inode2fid(inode))); - ll_done_writing(inode); - iput(inode); - } - - CDEBUG(D_INFO, "ll_close exiting\n"); - complete(&lcq->lcq_comp); - return 0; -} - -int ll_close_thread_start(struct ll_close_queue **lcq_ret) -{ - struct ll_close_queue *lcq; - struct task_struct *task; - - if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CLOSE_THREAD)) - return -EINTR; - - lcq = kzalloc(sizeof(*lcq), GFP_NOFS); - if (!lcq) - return -ENOMEM; - - spin_lock_init(&lcq->lcq_lock); - INIT_LIST_HEAD(&lcq->lcq_head); - init_waitqueue_head(&lcq->lcq_waitq); - init_completion(&lcq->lcq_comp); - - task = kthread_run(ll_close_thread, lcq, "ll_close"); - if (IS_ERR(task)) { - kfree(lcq); - return PTR_ERR(task); - } - - wait_for_completion(&lcq->lcq_comp); - *lcq_ret = lcq; - return 0; -} - -void ll_close_thread_shutdown(struct ll_close_queue *lcq) -{ - init_completion(&lcq->lcq_comp); - atomic_inc(&lcq->lcq_stop); - wake_up(&lcq->lcq_waitq); - wait_for_completion(&lcq->lcq_comp); - kfree(lcq); -} diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 4bc551279aa4..a66891d4b32a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -98,28 +98,17 @@ struct ll_grouplock { }; enum lli_flags { - /* MDS has an authority for the Size-on-MDS attributes. */ - LLIF_MDS_SIZE_LOCK = (1 << 0), - /* Epoch close is postponed. */ - LLIF_EPOCH_PENDING = (1 << 1), - /* DONE WRITING is allowed. */ - LLIF_DONE_WRITING = (1 << 2), - /* Sizeon-on-MDS attributes are changed. An attribute update needs to - * be sent to MDS. - */ - LLIF_SOM_DIRTY = (1 << 3), /* File data is modified. */ - LLIF_DATA_MODIFIED = (1 << 4), + LLIF_DATA_MODIFIED = BIT(0), /* File is being restored */ - LLIF_FILE_RESTORING = (1 << 5), + LLIF_FILE_RESTORING = BIT(1), /* Xattr cache is attached to the file */ - LLIF_XATTR_CACHE = (1 << 6), + LLIF_XATTR_CACHE = BIT(2), }; struct ll_inode_info { __u32 lli_inode_magic; __u32 lli_flags; - __u64 lli_ioepoch; spinlock_t lli_lock; struct posix_acl *lli_posix_acl; @@ -129,14 +118,6 @@ struct ll_inode_info { /* master inode fid for stripe directory */ struct lu_fid lli_pfid; - struct list_head lli_close_list; - - /* handle is to be sent to MDS later on done_writing and setattr. - * Open handle data are needed for the recovery to reconstruct - * the inode state on the MDS. XXX: recovery is not ready yet. - */ - struct obd_client_handle *lli_pending_och; - /* We need all three because every inode may be opened in different * modes */ @@ -400,7 +381,7 @@ enum stats_track_type { #define LL_SBI_LOCALFLOCK 0x200 /* Local flocks support by kernel */ #define LL_SBI_LRU_RESIZE 0x400 /* lru resize support */ #define LL_SBI_LAZYSTATFS 0x800 /* lazystatfs mount option */ -#define LL_SBI_SOM_PREVIEW 0x1000 /* SOM preview mount option */ +/* LL_SBI_SOM_PREVIEW 0x1000 SOM preview mount option, obsolete */ #define LL_SBI_32BIT_API 0x2000 /* generate 32 bit inodes. */ #define LL_SBI_64BIT_HASH 0x4000 /* support 64-bits dir hash/offset */ #define LL_SBI_AGL_ENABLED 0x8000 /* enable agl */ @@ -466,10 +447,10 @@ struct ll_sb_info { int ll_flags; unsigned int ll_umounting:1, - ll_xattr_cache_enabled:1; - struct lustre_client_ocd ll_lco; + ll_xattr_cache_enabled:1, + ll_client_common_fill_super_succeeded:1; - struct ll_close_queue *ll_lcq; + struct lustre_client_ocd ll_lco; struct lprocfs_stats *ll_stats; /* lprocfs stats counter */ @@ -764,15 +745,8 @@ int ll_file_open(struct inode *inode, struct file *file); int ll_file_release(struct inode *inode, struct file *file); int ll_glimpse_ioctl(struct ll_sb_info *sbi, struct lov_stripe_md *lsm, lstat_t *st); -void ll_ioepoch_open(struct ll_inode_info *lli, __u64 ioepoch); int ll_release_openhandle(struct inode *, struct lookup_intent *); int ll_md_real_close(struct inode *inode, fmode_t fmode); -void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data, - struct obd_client_handle **och, unsigned long flags); -void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data); -int ll_som_update(struct inode *inode, struct md_op_data *op_data); -int ll_inode_getattr(struct inode *inode, struct obdo *obdo, - __u64 ioepoch, int sync); void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, struct lustre_handle *fh); int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat); @@ -891,18 +865,6 @@ int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid); /* llite/symlink.c */ extern const struct inode_operations ll_fast_symlink_inode_operations; -/* llite/llite_close.c */ -struct ll_close_queue { - spinlock_t lcq_lock; - struct list_head lcq_head; - wait_queue_head_t lcq_waitq; - struct completion lcq_comp; - atomic_t lcq_stop; -}; - -void vvp_write_pending(struct vvp_object *club, struct vvp_page *page); -void vvp_write_complete(struct vvp_object *club, struct vvp_page *page); - /** * IO arguments for various VFS I/O interfaces. */ @@ -945,10 +907,6 @@ static inline struct vvp_io_args *ll_env_args(const struct lu_env *env) return &ll_env_info(env)->lti_args; } -void ll_queue_done_writing(struct inode *inode, unsigned long flags); -void ll_close_thread_shutdown(struct ll_close_queue *lcq); -int ll_close_thread_start(struct ll_close_queue **lcq_ret); - /* llite/llite_mmap.c */ int ll_teardown_mmaps(struct address_space *mapping, __u64 first, __u64 last); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index e5c62f4ce3d8..4ebf20cf2518 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -193,9 +193,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_OPEN_BY_FID | OBD_CONNECT_DIR_STRIPE; - if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) - data->ocd_connect_flags |= OBD_CONNECT_SOM; - if (sbi->ll_flags & LL_SBI_LRU_RESIZE) data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; #ifdef CONFIG_FS_POSIX_ACL @@ -357,9 +354,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS; - if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) - data->ocd_connect_flags |= OBD_CONNECT_SOM; - if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_CKSUM)) { /* OBD_CONNECT_CKSUM should always be set, even if checksums are * disabled by default, because it can still be enabled on the @@ -488,12 +482,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, goto out_root; } - err = ll_close_thread_start(&sbi->ll_lcq); - if (err) { - CERROR("cannot start close thread: rc %d\n", err); - goto out_root; - } - checksum = sbi->ll_flags & LL_SBI_CHECKSUM; err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM), KEY_CHECKSUM, sizeof(checksum), &checksum, @@ -633,8 +621,6 @@ static void client_common_put_super(struct super_block *sb) { struct ll_sb_info *sbi = ll_s2sbi(sb); - ll_close_thread_shutdown(sbi->ll_lcq); - cl_sb_fini(sb); obd_fid_fini(sbi->ll_dt_exp->exp_obd); @@ -766,11 +752,6 @@ static int ll_options(char *options, int *flags) *flags &= ~tmp; goto next; } - tmp = ll_set_opt("som_preview", s1, LL_SBI_SOM_PREVIEW); - if (tmp) { - *flags |= tmp; - goto next; - } tmp = ll_set_opt("32bitapi", s1, LL_SBI_32BIT_API); if (tmp) { *flags |= tmp; @@ -804,14 +785,11 @@ void ll_lli_init(struct ll_inode_info *lli) { lli->lli_inode_magic = LLI_INODE_MAGIC; lli->lli_flags = 0; - lli->lli_ioepoch = 0; lli->lli_maxbytes = MAX_LFS_FILESIZE; spin_lock_init(&lli->lli_lock); lli->lli_posix_acl = NULL; /* Do not set lli_fid, it has been initialized already. */ fid_zero(&lli->lli_pfid); - INIT_LIST_HEAD(&lli->lli_close_list); - lli->lli_pending_och = NULL; lli->lli_mds_read_och = NULL; lli->lli_mds_write_och = NULL; lli->lli_mds_exec_och = NULL; @@ -941,6 +919,8 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) /* connections, registrations, sb setup */ err = client_common_fill_super(sb, md, dt, mnt); + if (!err) + sbi->ll_client_common_fill_super_succeeded = 1; out_free: kfree(md); @@ -1002,7 +982,7 @@ void ll_put_super(struct super_block *sb) } } - if (sbi->ll_lcq) { + if (sbi->ll_client_common_fill_super_succeeded) { /* Only if client_common_fill_super succeeded */ client_common_put_super(sb); } @@ -1272,9 +1252,6 @@ void ll_clear_inode(struct inode *inode) LASSERT(lli->lli_opendir_pid == 0); } - spin_lock(&lli->lli_lock); - ll_i2info(inode)->lli_flags &= ~LLIF_MDS_SIZE_LOCK; - spin_unlock(&lli->lli_lock); md_null_inode(sbi->ll_md_exp, ll_inode2fid(inode)); LASSERT(!lli->lli_open_fd_write_count); @@ -1369,48 +1346,12 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, rc = simple_setattr(dentry, &op_data->op_attr); op_data->op_attr.ia_valid = ia_valid; - /* Extract epoch data if obtained. */ - op_data->op_handle = md.body->mbo_handle; - op_data->op_ioepoch = md.body->mbo_ioepoch; - rc = ll_update_inode(inode, &md); ptlrpc_req_finished(request); return rc; } -/* Close IO epoch and send Size-on-MDS attribute update. */ -static int ll_setattr_done_writing(struct inode *inode, - struct md_op_data *op_data, - struct md_open_data *mod) -{ - struct ll_inode_info *lli = ll_i2info(inode); - int rc = 0; - - if (!S_ISREG(inode->i_mode)) - return 0; - - CDEBUG(D_INODE, "Epoch %llu closed on "DFID" for truncate\n", - op_data->op_ioepoch, PFID(&lli->lli_fid)); - - op_data->op_flags = MF_EPOCH_CLOSE; - ll_done_writing_attr(inode, op_data); - ll_pack_inode2opdata(inode, op_data, NULL); - - rc = md_done_writing(ll_i2sbi(inode)->ll_md_exp, op_data, mod); - if (rc == -EAGAIN) - /* MDS has instructed us to obtain Size-on-MDS attribute - * from OSTs and send setattr to back to MDS. - */ - rc = ll_som_update(inode, op_data); - else if (rc) { - CERROR("%s: inode "DFID" mdc truncate failed: rc = %d\n", - ll_i2sbi(inode)->ll_md_exp->exp_obd->obd_name, - PFID(ll_inode2fid(inode)), rc); - } - return rc; -} - /* If this inode has objects allocated to it (lsm != NULL), then the OST * object(s) determine the file size and mtime. Otherwise, the MDS will * keep these values until such a time that objects are allocated for it. @@ -1433,7 +1374,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) struct md_op_data *op_data = NULL; struct md_open_data *mod = NULL; bool file_is_released = false; - int rc = 0, rc1 = 0; + int rc = 0; CDEBUG(D_VFSTRACE, "%s: setattr inode "DFID"(%p) from %llu to %llu, valid %x, hsm_import %d\n", ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), inode, @@ -1536,11 +1477,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) memcpy(&op_data->op_attr, attr, sizeof(*attr)); - /* Open epoch for truncate. */ - if (exp_connect_som(ll_i2mdexp(inode)) && !hsm_import && - (attr->ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) - op_data->op_flags = MF_EPOCH_OPEN; - rc = ll_md_setattr(dentry, op_data, &mod); if (rc) goto out; @@ -1552,7 +1488,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) spin_unlock(&lli->lli_lock); } - ll_ioepoch_open(lli, op_data->op_ioepoch); if (!S_ISREG(inode->i_mode) || file_is_released) { rc = 0; goto out; @@ -1575,12 +1510,8 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) up_write(&lli->lli_trunc_sem); } out: - if (op_data->op_ioepoch) { - rc1 = ll_setattr_done_writing(inode, op_data, mod); - if (!rc) - rc = rc1; - } - ll_finish_md_op_data(op_data); + if (op_data) + ll_finish_md_op_data(op_data); if (!S_ISDIR(inode->i_mode)) { inode_lock(inode); @@ -1828,48 +1759,11 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT(fid_seq(&lli->lli_fid) != 0); if (body->mbo_valid & OBD_MD_FLSIZE) { - if (exp_connect_som(ll_i2mdexp(inode)) && - S_ISREG(inode->i_mode)) { - struct lustre_handle lockh; - enum ldlm_mode mode; - - /* As it is possible a blocking ast has been processed - * by this time, we need to check there is an UPDATE - * lock on the client and set LLIF_MDS_SIZE_LOCK holding - * it. - */ - mode = ll_take_md_lock(inode, MDS_INODELOCK_UPDATE, - &lockh, LDLM_FL_CBPENDING, - LCK_CR | LCK_CW | - LCK_PR | LCK_PW); - if (mode) { - if (lli->lli_flags & (LLIF_DONE_WRITING | - LLIF_EPOCH_PENDING | - LLIF_SOM_DIRTY)) { - CERROR("%s: inode "DFID" flags %u still has size authority! do not trust the size got from MDS\n", - sbi->ll_md_exp->exp_obd->obd_name, - PFID(ll_inode2fid(inode)), - lli->lli_flags); - } else { - /* Use old size assignment to avoid - * deadlock bz14138 & bz14326 - */ - i_size_write(inode, body->mbo_size); - spin_lock(&lli->lli_lock); - lli->lli_flags |= LLIF_MDS_SIZE_LOCK; - spin_unlock(&lli->lli_lock); - } - ldlm_lock_decref(&lockh, mode); - } - } else { - /* Use old size assignment to avoid - * deadlock bz14138 & bz14326 - */ - i_size_write(inode, body->mbo_size); + i_size_write(inode, body->mbo_size); - CDEBUG(D_VFSTRACE, "inode=%lu, updating i_size %llu\n", - inode->i_ino, (unsigned long long)body->mbo_size); - } + CDEBUG(D_VFSTRACE, "inode=" DFID ", updating i_size %llu\n", + PFID(ll_inode2fid(inode)), + (unsigned long long)body->mbo_size); if (body->mbo_valid & OBD_MD_FLBLOCKS) inode->i_blocks = body->mbo_blocks; @@ -2164,7 +2058,6 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req) return; op_data->op_fid1 = body->mbo_fid1; - op_data->op_ioepoch = body->mbo_ioepoch; op_data->op_handle = body->mbo_handle; op_data->op_mod_time = get_seconds(); md_close(exp, op_data, NULL, &close_req); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 180f35e3afd9..a69c8af7a567 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -254,14 +254,6 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, PFID(ll_inode2fid(inode)), rc); } - if (bits & MDS_INODELOCK_UPDATE) { - struct ll_inode_info *lli = ll_i2info(inode); - - spin_lock(&lli->lli_lock); - lli->lli_flags &= ~LLIF_MDS_SIZE_LOCK; - spin_unlock(&lli->lli_lock); - } - if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) { struct ll_inode_info *lli = ll_i2info(inode); diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 8aa8ecc09a48..cab95acd869a 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -521,11 +521,10 @@ static void vvp_pgcache_page_show(const struct lu_env *env, vpg = cl2vvp_page(cl_page_at(page, &vvp_device_type)); vmpage = vpg->vpg_page; - seq_printf(seq, " %5i | %p %p %s %s %s %s | %p "DFID"(%p) %lu %u [", + seq_printf(seq, " %5i | %p %p %s %s %s | %p " DFID "(%p) %lu %u [", 0 /* gen */, vpg, page, "none", - vpg->vpg_write_queued ? "wq" : "- ", vpg->vpg_defer_uptodate ? "du" : "- ", PageWriteback(vmpage) ? "wb" : "-", vmpage, PFID(ll_inode2fid(vmpage->mapping->host)), diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 4464ad258387..2dca1fce4b41 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -194,14 +194,6 @@ struct vvp_object { struct cl_object vob_cl; struct inode *vob_inode; - /** - * A list of dirty pages pending IO in the cache. Used by - * SOM. Protected by ll_inode_info::lli_lock. - * - * \see vvp_page::vpg_pending_linkage - */ - struct list_head vob_pending_list; - /** * Number of transient pages. This is no longer protected by i_sem, * and needs to be atomic. This is not actually used for anything, @@ -235,15 +227,7 @@ struct vvp_object { struct vvp_page { struct cl_page_slice vpg_cl; unsigned int vpg_defer_uptodate:1, - vpg_ra_used:1, - vpg_write_queued:1; - /** - * Non-empty iff this page is already counted in - * vvp_object::vob_pending_list. This list is only used as a flag, - * that is, never iterated through, only checked for list_empty(), but - * having a list is useful for debugging. - */ - struct list_head vpg_pending_linkage; + vpg_ra_used:1; /** VM page */ struct page *vpg_page; }; diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 2b7f182a15e2..3e47f6642c48 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -770,16 +770,11 @@ static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io, static void write_commit_callback(const struct lu_env *env, struct cl_io *io, struct cl_page *page) { - struct vvp_page *vpg; struct page *vmpage = page->cp_vmpage; - struct cl_object *clob = cl_io_top(io)->ci_obj; SetPageUptodate(vmpage); set_page_dirty(vmpage); - vpg = cl2vvp_page(cl_object_page_slice(clob, page)); - vvp_write_pending(cl2vvp(clob), vpg); - cl_page_disown(env, io, page); /* held in ll_cl_init() */ @@ -1014,13 +1009,7 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio) static void mkwrite_commit_callback(const struct lu_env *env, struct cl_io *io, struct cl_page *page) { - struct vvp_page *vpg; - struct cl_object *clob = cl_io_top(io)->ci_obj; - set_page_dirty(page->cp_vmpage); - - vpg = cl2vvp_page(cl_object_page_slice(clob, page)); - vvp_write_pending(cl2vvp(clob), vpg); } static int vvp_io_fault_start(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index b57195d15674..3214885bd1da 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -65,8 +65,7 @@ static int vvp_object_print(const struct lu_env *env, void *cookie, struct inode *inode = obj->vob_inode; struct ll_inode_info *lli; - (*p)(env, cookie, "(%s %d %d) inode: %p ", - list_empty(&obj->vob_pending_list) ? "-" : "+", + (*p)(env, cookie, "(%d %d) inode: %p ", atomic_read(&obj->vob_transient_pages), atomic_read(&obj->vob_mmap_cnt), inode); if (inode) { @@ -240,7 +239,6 @@ static int vvp_object_init(const struct lu_env *env, struct lu_object *obj, const struct cl_object_conf *cconf; cconf = lu2cl_conf(conf); - INIT_LIST_HEAD(&vob->vob_pending_list); lu_object_add(obj, below); result = vvp_object_init0(env, vob, cconf); } else { diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 046e84d7a158..0041cd8f0ce5 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -162,8 +162,6 @@ static void vvp_page_delete(const struct lu_env *env, LASSERT((struct cl_page *)vmpage->private == page); LASSERT(inode == vvp_object_inode(obj)); - vvp_write_complete(cl2vvp(obj), cl2vvp_page(slice)); - /* Drop the reference count held in vvp_page_init */ refc = atomic_dec_return(&page->cp_ref); LASSERTF(refc >= 1, "page = %p, refc = %d\n", page, refc); @@ -221,8 +219,6 @@ static int vvp_page_prep_write(const struct lu_env *env, if (!pg->cp_sync_io) set_page_writeback(vmpage); - vvp_write_pending(cl2vvp(slice->cpl_obj), cl2vvp_page(slice)); - return 0; } @@ -287,19 +283,6 @@ static void vvp_page_completion_write(const struct lu_env *env, CL_PAGE_HEADER(D_PAGE, env, pg, "completing WRITE with %d\n", ioret); - /* - * TODO: Actually it makes sense to add the page into oap pending - * list again and so that we don't need to take the page out from - * SoM write pending list, if we just meet a recoverable error, - * -ENOMEM, etc. - * To implement this, we just need to return a non zero value in - * ->cpo_completion method. The underlying transfer should be notified - * and then re-add the page into pending transfer queue. -jay - */ - - vpg->vpg_write_queued = 0; - vvp_write_complete(cl2vvp(slice->cpl_obj), vpg); - if (pg->cp_sync_io) { LASSERT(PageLocked(vmpage)); LASSERT(!PageWriteback(vmpage)); @@ -341,7 +324,6 @@ static int vvp_page_make_ready(const struct lu_env *env, LASSERT(pg->cp_state == CPS_CACHED); /* This actually clears the dirty bit in the radix tree. */ set_page_writeback(vmpage); - vvp_write_pending(cl2vvp(slice->cpl_obj), cl2vvp_page(slice)); CL_PAGE_HEADER(D_PAGE, env, pg, "readied\n"); } else if (pg->cp_state == CPS_PAGEOUT) { /* is it possible for osc_flush_async_page() to already @@ -378,9 +360,8 @@ static int vvp_page_print(const struct lu_env *env, struct vvp_page *vpg = cl2vvp_page(slice); struct page *vmpage = vpg->vpg_page; - (*printer)(env, cookie, LUSTRE_VVP_NAME "-page@%p(%d:%d:%d) vm@%p ", - vpg, vpg->vpg_defer_uptodate, vpg->vpg_ra_used, - vpg->vpg_write_queued, vmpage); + (*printer)(env, cookie, LUSTRE_VVP_NAME "-page@%p(%d:%d) vm@%p ", + vpg, vpg->vpg_defer_uptodate, vpg->vpg_ra_used, vmpage); if (vmpage) { (*printer)(env, cookie, "%lx %d:%d %lx %lu %slru", (long)vmpage->flags, page_count(vmpage), @@ -539,7 +520,6 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, vpg->vpg_page = vmpage; get_page(vmpage); - INIT_LIST_HEAD(&vpg->vpg_pending_linkage); if (page->cp_type == CPT_CACHEABLE) { /* in cache, decref in vvp_page_delete */ atomic_inc(&page->cp_ref); diff --git a/drivers/staging/lustre/lustre/llite/vvp_req.c b/drivers/staging/lustre/lustre/llite/vvp_req.c index e3f4c790d646..a8892e4c8846 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_req.c +++ b/drivers/staging/lustre/lustre/llite/vvp_req.c @@ -56,8 +56,6 @@ static inline struct vvp_req *cl2vvp_req(const struct cl_req_slice *slice) * * - o_parent_ver * - * - o_ioepoch, - * */ static void vvp_req_attr_set(const struct lu_env *env, const struct cl_req_slice *slice, @@ -72,14 +70,9 @@ static void vvp_req_attr_set(const struct lu_env *env, inode = vvp_object_inode(obj); valid_flags = OBD_MD_FLTYPE; - if (slice->crs_req->crq_type == CRT_WRITE) { - if (flags & OBD_MD_FLEPOCH) { - oa->o_valid |= OBD_MD_FLEPOCH; - oa->o_ioepoch = ll_i2info(inode)->lli_ioepoch; - valid_flags |= OBD_MD_FLMTIME | OBD_MD_FLCTIME | - OBD_MD_FLUID | OBD_MD_FLGID; - } - } + if (slice->crs_req->crq_type == CRT_WRITE) + valid_flags |= OBD_MD_FLMTIME | OBD_MD_FLCTIME | + OBD_MD_FLUID | OBD_MD_FLGID; obdo_from_inode(oa, inode, valid_flags & flags); obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_INVALID_PFID)) -- cgit v1.2.3 From f28f1a4581cbeaaa3098655761440fd2774e4abb Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:00 -0400 Subject: staging: lustre: obd: remove client Size on MDS support Remove the unused OBD MD API method md_done_writing(). Remove the unused logcookie and struct md_open_data ** parameters from md_setattr(). Remove the unused functions iattr_from_obdo(), md_from_obdo(), and obdo_refresh_inode(). Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6047 Reviewed-on: http://review.whamcloud.com/13169 Reviewed-by: Andreas Dilger Reviewed-by: Jinshan Xiong Reviewed-by: Henri Doreau Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 2 - drivers/staging/lustre/lustre/include/obd.h | 7 +- drivers/staging/lustre/lustre/include/obd_class.h | 22 +---- drivers/staging/lustre/lustre/llite/dir.c | 3 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 12 +-- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 31 +------- drivers/staging/lustre/lustre/lov/lov_request.c | 14 ---- drivers/staging/lustre/lustre/mdc/mdc_internal.h | 5 +- drivers/staging/lustre/lustre/mdc/mdc_lib.c | 20 +---- drivers/staging/lustre/lustre/mdc/mdc_reint.c | 58 ++------------ drivers/staging/lustre/lustre/mdc/mdc_request.c | 93 +--------------------- drivers/staging/lustre/lustre/obdclass/Makefile | 2 +- .../lustre/lustre/obdclass/linux/linux-obdo.c | 80 ------------------- drivers/staging/lustre/lustre/obdclass/obdo.c | 65 --------------- 14 files changed, 26 insertions(+), 388 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 72eaee95c6b8..d1645458fa76 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2049,8 +2049,6 @@ enum md_op_flags { MF_GET_MDT_IDX = (1 << 9), }; -#define MF_SOM_LOCAL_FLAGS (MF_SOM_CHANGE | MF_EPOCH_OPEN | MF_EPOCH_CLOSE) - #define LUSTRE_BFLAG_UNCOMMITTED_WRITES 0x1 /* these should be identical to their EXT4_*_FL counterparts, they are diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f6fc4dd05bd6..51d5487b7d2b 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -789,8 +789,6 @@ struct md_op_data { __u64 op_valid; loff_t op_attr_blocks; - /* Size-on-MDS epoch and flags. */ - __u64 op_ioepoch; __u32 op_flags; /* Various operation flags. */ @@ -992,8 +990,6 @@ struct md_ops { int (*create)(struct obd_export *, struct md_op_data *, const void *, size_t, umode_t, uid_t, gid_t, cfs_cap_t, __u64, struct ptlrpc_request **); - int (*done_writing)(struct obd_export *, struct md_op_data *, - struct md_open_data *); int (*enqueue)(struct obd_export *, struct ldlm_enqueue_info *, const ldlm_policy_data_t *, struct lookup_intent *, struct md_op_data *, @@ -1012,8 +1008,7 @@ struct md_ops { const char *, size_t, const char *, size_t, struct ptlrpc_request **); int (*setattr)(struct obd_export *, struct md_op_data *, void *, - size_t, void *, size_t, struct ptlrpc_request **, - struct md_open_data **mod); + size_t, struct ptlrpc_request **); int (*sync)(struct obd_export *, const struct lu_fid *, struct ptlrpc_request **); int (*read_page)(struct obd_export *, struct md_op_data *, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 16094dbec08b..2ea102dd2940 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -269,10 +269,8 @@ static inline int lprocfs_climp_check(struct obd_device *obd) struct inode; struct lu_attr; struct obdo; -void obdo_refresh_inode(struct inode *dst, const struct obdo *src, u32 valid); void obdo_to_ioobj(const struct obdo *oa, struct obd_ioobj *ioobj); -void md_from_obdo(struct md_op_data *op_data, const struct obdo *oa, u32 valid); #define OBT(dev) (dev)->obd_type #define OBP(dev, op) (dev)->obd_type->typ_dt_ops->op @@ -1346,18 +1344,6 @@ static inline int md_create(struct obd_export *exp, struct md_op_data *op_data, return rc; } -static inline int md_done_writing(struct obd_export *exp, - struct md_op_data *op_data, - struct md_open_data *mod) -{ - int rc; - - EXP_CHECK_MD_OP(exp, done_writing); - EXP_MD_COUNTER_INCREMENT(exp, done_writing); - rc = MDP(exp->exp_obd, done_writing)(exp, op_data, mod); - return rc; -} - static inline int md_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, const ldlm_policy_data_t *policy, @@ -1428,16 +1414,14 @@ static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data, } static inline int md_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, size_t ealen, void *ea2, size_t ea2len, - struct ptlrpc_request **request, - struct md_open_data **mod) + void *ea, size_t ealen, + struct ptlrpc_request **request) { int rc; EXP_CHECK_MD_OP(exp, setattr); EXP_MD_COUNTER_INCREMENT(exp, setattr); - rc = MDP(exp->exp_obd, setattr)(exp, op_data, ea, ealen, - ea2, ea2len, request, mod); + rc = MDP(exp->exp_obd, setattr)(exp, op_data, ea, ealen, request); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 7f32a539d260..36413273a86b 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -501,8 +501,7 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, return PTR_ERR(op_data); /* swabbing is done in lov_setstripe() on server side */ - rc = md_setattr(sbi->ll_md_exp, op_data, lump, lum_size, - NULL, 0, &req, NULL); + rc = md_setattr(sbi->ll_md_exp, op_data, lump, lum_size, &req); ll_finish_md_op_data(op_data); ptlrpc_req_finished(req); if (rc) { diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 4ebf20cf2518..84a377a99f42 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1295,8 +1295,7 @@ void ll_clear_inode(struct inode *inode) #define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) -static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, - struct md_open_data **mod) +static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data) { struct lustre_md md; struct inode *inode = d_inode(dentry); @@ -1309,8 +1308,7 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, if (IS_ERR(op_data)) return PTR_ERR(op_data); - rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, NULL, 0, - &request, mod); + rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, &request); if (rc) { ptlrpc_req_finished(request); if (rc == -ENOENT) { @@ -1372,7 +1370,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) struct inode *inode = d_inode(dentry); struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; - struct md_open_data *mod = NULL; bool file_is_released = false; int rc = 0; @@ -1477,7 +1474,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) memcpy(&op_data->op_attr, attr, sizeof(*attr)); - rc = ll_md_setattr(dentry, op_data, &mod); + rc = ll_md_setattr(dentry, op_data); if (rc) goto out; @@ -1896,8 +1893,7 @@ int ll_iocontrol(struct inode *inode, struct file *file, op_data->op_attr_flags = flags; op_data->op_attr.ia_valid |= ATTR_ATTR_FLAG; - rc = md_setattr(sbi->ll_md_exp, op_data, - NULL, 0, NULL, 0, &req, NULL); + rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, &req); ll_finish_md_op_data(op_data); ptlrpc_req_finished(req); if (rc) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 7dbb2b946acf..b401ffb14477 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1728,27 +1728,6 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, return rc; } -static int lmv_done_writing(struct obd_export *exp, - struct md_op_data *op_data, - struct md_open_data *mod) -{ - struct obd_device *obd = exp->exp_obd; - struct lmv_obd *lmv = &obd->u.lmv; - struct lmv_tgt_desc *tgt; - int rc; - - rc = lmv_check_connect(obd); - if (rc) - return rc; - - tgt = lmv_find_target(lmv, &op_data->op_fid1); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); - - rc = md_done_writing(tgt->ltd_exp, op_data, mod); - return rc; -} - static int lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, const ldlm_policy_data_t *policy, @@ -2065,9 +2044,7 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, } static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, size_t ealen, void *ea2, size_t ea2len, - struct ptlrpc_request **request, - struct md_open_data **mod) + void *ea, size_t ealen, struct ptlrpc_request **request) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2086,10 +2063,7 @@ static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data, if (IS_ERR(tgt)) return PTR_ERR(tgt); - rc = md_setattr(tgt->ltd_exp, op_data, ea, ealen, ea2, - ea2len, request, mod); - - return rc; + return md_setattr(tgt->ltd_exp, op_data, ea, ealen, request); } static int lmv_sync(struct obd_export *exp, const struct lu_fid *fid, @@ -3363,7 +3337,6 @@ static struct md_ops lmv_md_ops = { .null_inode = lmv_null_inode, .close = lmv_close, .create = lmv_create, - .done_writing = lmv_done_writing, .enqueue = lmv_enqueue, .getattr = lmv_getattr, .getxattr = lmv_getxattr, diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 09dcaf484c89..8e4070223e10 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -214,15 +214,6 @@ static int common_attr_done(struct lov_request_set *set) CERROR("No stripes had valid attrs\n"); rc = -EIO; } - if ((set->set_oi->oi_oa->o_valid & OBD_MD_FLEPOCH) && - (set->set_oi->oi_md->lsm_stripe_count != attrset)) { - /* When we take attributes of some epoch, we require all the - * ost to be active. - */ - CERROR("Not all the stripes had valid attrs\n"); - rc = -EIO; - goto out; - } tmp_oa->o_oi = set->set_oi->oi_oa->o_oi; memcpy(set->set_oi->oi_oa, tmp_oa, sizeof(*set->set_oi->oi_oa)); @@ -284,11 +275,6 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) { CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx); - if (oinfo->oi_oa->o_valid & OBD_MD_FLEPOCH) { - /* SOM requires all the OSTs to be active. */ - rc = -EIO; - goto out_set; - } continue; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index f446c1c2584b..d2af8e7d934d 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -46,7 +46,7 @@ void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, size_t size, void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, u32 flags, struct md_op_data *data, size_t ea_size); void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - void *ea, size_t ealen, void *ea2, size_t ea2len); + void *ea, size_t ealen); void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, const void *data, size_t datalen, umode_t mode, uid_t uid, gid_t gid, cfs_cap_t capability, __u64 rdev); @@ -105,8 +105,7 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, const char *new, size_t newlen, struct ptlrpc_request **request); int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, size_t ealen, void *ea2, size_t ea2len, - struct ptlrpc_request **request, struct md_open_data **mod); + void *ea, size_t ealen, struct ptlrpc_request **request); int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request); int mdc_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index aac7e04873e2..709440b62323 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -139,7 +139,7 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_time = op_data->op_mod_time; rec->cr_suppgid1 = op_data->op_suppgids[0]; rec->cr_suppgid2 = op_data->op_suppgids[1]; - flags = op_data->op_flags & MF_SOM_LOCAL_FLAGS; + flags = 0; if (op_data->op_bias & MDS_CREATE_VOLATILE) flags |= MDS_OPEN_VOLATILE; set_mrc_cr_flags(rec, flags); @@ -302,15 +302,14 @@ static void mdc_ioepoch_pack(struct mdt_ioepoch *epoch, struct md_op_data *op_data) { memcpy(&epoch->handle, &op_data->op_handle, sizeof(epoch->handle)); - epoch->ioepoch = op_data->op_ioepoch; - epoch->flags = op_data->op_flags & MF_SOM_LOCAL_FLAGS; + epoch->ioepoch = 0; + epoch->flags = 0; } void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - void *ea, size_t ealen, void *ea2, size_t ea2len) + void *ea, size_t ealen) { struct mdt_rec_setattr *rec; - struct mdt_ioepoch *epoch; struct lov_user_md *lum = NULL; CLASSERT(sizeof(struct mdt_rec_reint) == @@ -318,11 +317,6 @@ void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); mdc_setattr_pack_rec(rec, op_data); - if (op_data->op_flags & (MF_SOM_CHANGE | MF_EPOCH_OPEN)) { - epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH); - mdc_ioepoch_pack(epoch, op_data); - } - if (ealen == 0) return; @@ -335,12 +329,6 @@ void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, } else { memcpy(lum, ea, ealen); } - - if (ea2len == 0) - return; - - memcpy(req_capsule_client_get(&req->rq_pill, &RMF_LOGCOOKIES), ea2, - ea2len); } void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index c921e471fa27..6f62a95bff5b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -99,8 +99,7 @@ int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, } int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, size_t ealen, void *ea2, size_t ea2len, - struct ptlrpc_request **request, struct md_open_data **mod) + void *ea, size_t ealen, struct ptlrpc_request **request) { LIST_HEAD(cancels); struct ptlrpc_request *req; @@ -122,12 +121,9 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, ldlm_lock_list_put(&cancels, l_bl_ast, count); return -ENOMEM; } - if ((op_data->op_flags & (MF_SOM_CHANGE | MF_EPOCH_OPEN)) == 0) - req_capsule_set_size(&req->rq_pill, &RMF_MDT_EPOCH, RCL_CLIENT, - 0); + req_capsule_set_size(&req->rq_pill, &RMF_MDT_EPOCH, RCL_CLIENT, 0); req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, ealen); - req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_CLIENT, - ea2len); + req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_CLIENT, 0); rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); if (rc) { @@ -141,57 +137,17 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, CDEBUG(D_INODE, "setting mtime %ld, ctime %ld\n", LTIME_S(op_data->op_attr.ia_mtime), LTIME_S(op_data->op_attr.ia_ctime)); - mdc_setattr_pack(req, op_data, ea, ealen, ea2, ea2len); + mdc_setattr_pack(req, op_data, ea, ealen); ptlrpc_request_set_replen(req); - if (mod && (op_data->op_flags & MF_EPOCH_OPEN) && - req->rq_import->imp_replayable) { - LASSERT(!*mod); - - *mod = obd_mod_alloc(); - if (!*mod) { - DEBUG_REQ(D_ERROR, req, "Can't allocate md_open_data"); - } else { - req->rq_replay = 1; - req->rq_cb_data = *mod; - (*mod)->mod_open_req = req; - req->rq_commit_cb = mdc_commit_open; - (*mod)->mod_is_create = true; - /** - * Take an extra reference on \var mod, it protects \var - * mod from being freed on eviction (commit callback is - * called despite rq_replay flag). - * Will be put on mdc_done_writing(). - */ - obd_mod_get(*mod); - } - } rc = mdc_reint(req, rpc_lock, LUSTRE_IMP_FULL); - /* Save the obtained info in the original RPC for the replay case. */ - if (rc == 0 && (op_data->op_flags & MF_EPOCH_OPEN)) { - struct mdt_ioepoch *epoch; - struct mdt_body *body; - - epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH); - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - epoch->handle = body->mbo_handle; - epoch->ioepoch = body->mbo_ioepoch; - req->rq_replay_cb = mdc_replay_open; - /** bug 3633, open may be committed and estale answer is not error */ - } else if (rc == -ESTALE && (op_data->op_flags & MF_SOM_CHANGE)) { - rc = 0; - } else if (rc == -ERESTARTSYS) { + if (rc == -ERESTARTSYS) rc = 0; - } + *request = req; - if (rc && req->rq_commit_cb) { - /* Put an extra reference on \var mod on error case. */ - if (mod && *mod) - obd_mod_put(*mod); - req->rq_commit_cb(req); - } + return rc; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index f56ea643f9bf..3ef1bae27896 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -528,10 +528,6 @@ static int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md) return 0; } -/** - * Handles both OPEN and SETATTR RPCs for OPEN-CLOSE and SETATTR-DONE_WRITING - * RPC chains. - */ void mdc_replay_open(struct ptlrpc_request *req) { struct md_open_data *mod = req->rq_cb_data; @@ -565,7 +561,7 @@ void mdc_replay_open(struct ptlrpc_request *req) __u32 opc = lustre_msg_get_opc(close_req->rq_reqmsg); struct mdt_ioepoch *epoch; - LASSERT(opc == MDS_CLOSE || opc == MDS_DONE_WRITING); + LASSERT(opc == MDS_CLOSE); epoch = req_capsule_client_get(&close_req->rq_pill, &RMF_MDT_EPOCH); LASSERT(epoch); @@ -715,22 +711,6 @@ static int mdc_clear_open_replay_data(struct obd_export *exp, return 0; } -/* Prepares the request for the replay by the given reply */ -static void mdc_close_handle_reply(struct ptlrpc_request *req, - struct md_op_data *op_data, int rc) { - struct mdt_body *repbody; - struct mdt_ioepoch *epoch; - - if (req && rc == -EAGAIN) { - repbody = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH); - - epoch->flags |= MF_SOM_AU; - if (repbody->mbo_valid & OBD_MD_FLGETATTRLOCK) - op_data->op_flags |= MF_GETATTR_LOCK; - } -} - static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, struct md_open_data *mod, struct ptlrpc_request **request) { @@ -857,79 +837,9 @@ out: obd_mod_put(mod); } *request = req; - mdc_close_handle_reply(req, op_data, rc); return rc < 0 ? rc : saved_rc; } -static int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, - struct md_open_data *mod) -{ - struct obd_device *obd = class_exp2obd(exp); - struct ptlrpc_request *req; - int rc; - - req = ptlrpc_request_alloc(class_exp2cliimp(exp), - &RQF_MDS_DONE_WRITING); - if (!req) - return -ENOMEM; - - rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_DONE_WRITING); - if (rc) { - ptlrpc_request_free(req); - return rc; - } - - if (mod) { - LASSERTF(mod->mod_open_req && - mod->mod_open_req->rq_type != LI_POISON, - "POISONED setattr %p!\n", mod->mod_open_req); - - mod->mod_close_req = req; - DEBUG_REQ(D_HA, mod->mod_open_req, "matched setattr"); - /* We no longer want to preserve this setattr for replay even - * though the open was committed. b=3632, b=3633 - */ - spin_lock(&mod->mod_open_req->rq_lock); - mod->mod_open_req->rq_replay = 0; - spin_unlock(&mod->mod_open_req->rq_lock); - } - - mdc_close_pack(req, op_data); - ptlrpc_request_set_replen(req); - - mdc_get_rpc_lock(obd->u.cli.cl_close_lock, NULL); - rc = ptlrpc_queue_wait(req); - mdc_put_rpc_lock(obd->u.cli.cl_close_lock, NULL); - - if (rc == -ESTALE) { - /** - * it can be allowed error after 3633 if open or setattr were - * committed and server failed before close was sent. - * Let's check if mod exists and return no error in that case - */ - if (mod) { - if (mod->mod_open_req->rq_committed) - rc = 0; - } - } - - if (mod) { - if (rc != 0) - mod->mod_close_req = NULL; - LASSERT(mod->mod_open_req); - mdc_free_open(mod); - - /* Since now, mod is accessed through setattr req only, - * thus DW req does not keep a reference on mod anymore. - */ - obd_mod_put(mod); - } - - mdc_close_handle_reply(req, op_data, rc); - ptlrpc_req_finished(req); - return rc; -} - static int mdc_getpage(struct obd_export *exp, const struct lu_fid *fid, u64 offset, struct page **pages, int npages, struct ptlrpc_request **request) @@ -2889,7 +2799,6 @@ static struct md_ops mdc_md_ops = { .null_inode = mdc_null_inode, .close = mdc_close, .create = mdc_create, - .done_writing = mdc_done_writing, .enqueue = mdc_enqueue, .getattr = mdc_getattr, .getattr_name = mdc_getattr_name, diff --git a/drivers/staging/lustre/lustre/obdclass/Makefile b/drivers/staging/lustre/lustre/obdclass/Makefile index b42e109b30e0..af570c0db15b 100644 --- a/drivers/staging/lustre/lustre/obdclass/Makefile +++ b/drivers/staging/lustre/lustre/obdclass/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_LUSTRE_FS) += obdclass.o -obdclass-y := linux/linux-module.o linux/linux-obdo.o linux/linux-sysctl.o \ +obdclass-y := linux/linux-module.o linux/linux-sysctl.o \ llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \ genops.o uuid.o lprocfs_status.o lprocfs_counters.o \ lustre_handles.o lustre_peer.o statfs_pack.o linkea.o \ diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c deleted file mode 100644 index 41b77a30feb3..000000000000 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/obdclass/linux/linux-obdo.c - * - * Object Devices Class Driver - * These are the only exported functions, they provide some generic - * infrastructure for managing object devices - */ - -#define DEBUG_SUBSYSTEM S_CLASS - -#include -#include "../../include/obd_class.h" -#include "../../include/lustre/lustre_idl.h" - -#include - -void obdo_refresh_inode(struct inode *dst, const struct obdo *src, u32 valid) -{ - valid &= src->o_valid; - - if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME)) - CDEBUG(D_INODE, - "valid %#llx, cur time %lu/%lu, new %llu/%llu\n", - src->o_valid, LTIME_S(dst->i_mtime), - LTIME_S(dst->i_ctime), src->o_mtime, src->o_ctime); - - if (valid & OBD_MD_FLATIME && src->o_atime > LTIME_S(dst->i_atime)) - LTIME_S(dst->i_atime) = src->o_atime; - if (valid & OBD_MD_FLMTIME && src->o_mtime > LTIME_S(dst->i_mtime)) - LTIME_S(dst->i_mtime) = src->o_mtime; - if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime)) - LTIME_S(dst->i_ctime) = src->o_ctime; - if (valid & OBD_MD_FLSIZE) - i_size_write(dst, src->o_size); - /* optimum IO size */ - if (valid & OBD_MD_FLBLKSZ && src->o_blksize > (1 << dst->i_blkbits)) - dst->i_blkbits = ffs(src->o_blksize) - 1; - - if (dst->i_blkbits < PAGE_SHIFT) - dst->i_blkbits = PAGE_SHIFT; - - /* allocation of space */ - if (valid & OBD_MD_FLBLOCKS && src->o_blocks > dst->i_blocks) - /* - * XXX shouldn't overflow be checked here like in - * obdo_to_inode(). - */ - dst->i_blocks = src->o_blocks; -} -EXPORT_SYMBOL(obdo_refresh_inode); diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c index 79104a66da96..c52b9e07d7dd 100644 --- a/drivers/staging/lustre/lustre/obdclass/obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/obdo.c @@ -124,68 +124,3 @@ void obdo_to_ioobj(const struct obdo *oa, struct obd_ioobj *ioobj) ioobj->ioo_max_brw = 0; } EXPORT_SYMBOL(obdo_to_ioobj); - -static void iattr_from_obdo(struct iattr *attr, const struct obdo *oa, - u32 valid) -{ - valid &= oa->o_valid; - - if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME)) - CDEBUG(D_INODE, "valid %#llx, new time %llu/%llu\n", - oa->o_valid, oa->o_mtime, oa->o_ctime); - - attr->ia_valid = 0; - if (valid & OBD_MD_FLATIME) { - LTIME_S(attr->ia_atime) = oa->o_atime; - attr->ia_valid |= ATTR_ATIME; - } - if (valid & OBD_MD_FLMTIME) { - LTIME_S(attr->ia_mtime) = oa->o_mtime; - attr->ia_valid |= ATTR_MTIME; - } - if (valid & OBD_MD_FLCTIME) { - LTIME_S(attr->ia_ctime) = oa->o_ctime; - attr->ia_valid |= ATTR_CTIME; - } - if (valid & OBD_MD_FLSIZE) { - attr->ia_size = oa->o_size; - attr->ia_valid |= ATTR_SIZE; - } -#if 0 /* you shouldn't be able to change a file's type with setattr */ - if (valid & OBD_MD_FLTYPE) { - attr->ia_mode = (attr->ia_mode & ~S_IFMT) | - (oa->o_mode & S_IFMT); - attr->ia_valid |= ATTR_MODE; - } -#endif - if (valid & OBD_MD_FLMODE) { - attr->ia_mode = (attr->ia_mode & S_IFMT) | - (oa->o_mode & ~S_IFMT); - attr->ia_valid |= ATTR_MODE; - if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) && - !capable(CFS_CAP_FSETID)) - attr->ia_mode &= ~S_ISGID; - } - if (valid & OBD_MD_FLUID) { - attr->ia_uid = make_kuid(&init_user_ns, oa->o_uid); - attr->ia_valid |= ATTR_UID; - } - if (valid & OBD_MD_FLGID) { - attr->ia_gid = make_kgid(&init_user_ns, oa->o_gid); - attr->ia_valid |= ATTR_GID; - } -} - -void md_from_obdo(struct md_op_data *op_data, const struct obdo *oa, u32 valid) -{ - iattr_from_obdo(&op_data->op_attr, oa, valid); - if (valid & OBD_MD_FLBLOCKS) { - op_data->op_attr_blocks = oa->o_blocks; - op_data->op_attr.ia_valid |= ATTR_BLOCKS; - } - if (valid & OBD_MD_FLFLAGS) { - op_data->op_attr_flags = oa->o_flags; - op_data->op_attr.ia_valid |= ATTR_ATTR_FLAG; - } -} -EXPORT_SYMBOL(md_from_obdo); -- cgit v1.2.3 From 1e1db2a97be57702fecd859efbe6e60fafc9b349 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Sun, 2 Oct 2016 22:28:01 -0400 Subject: staging: lustre: clio: Revise read ahead implementation In this implementation, read ahead will hold the underlying DLM lock to add read ahead pages. A new cl_io operation cio_read_ahead() is added for this purpose. It takes parameter cl_read_ahead{} so that each layer can adjust it by their own requirements. For example, at OSC layer, it will make sure the read ahead region is covered by a LDLM lock; at the LOV layer, it will make sure that the region won't cross stripe boundary. Legacy callback cpo_is_under_lock() is removed. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3259 Reviewed-on: http://review.whamcloud.com/10859 Reviewed-by: John L. Hammond Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/cl_object.h | 63 +++--- .../staging/lustre/lustre/llite/llite_internal.h | 7 +- drivers/staging/lustre/lustre/llite/rw.c | 218 +++++++++++++-------- drivers/staging/lustre/lustre/llite/vvp_io.c | 47 ++--- drivers/staging/lustre/lustre/llite/vvp_page.c | 16 -- drivers/staging/lustre/lustre/lov/lov_io.c | 58 ++++++ drivers/staging/lustre/lustre/lov/lov_page.c | 46 ----- drivers/staging/lustre/lustre/obdclass/cl_io.c | 57 ++---- drivers/staging/lustre/lustre/obdclass/cl_page.c | 47 ----- drivers/staging/lustre/lustre/osc/osc_cache.c | 3 +- drivers/staging/lustre/lustre/osc/osc_internal.h | 17 +- drivers/staging/lustre/lustre/osc/osc_io.c | 41 +++- drivers/staging/lustre/lustre/osc/osc_lock.c | 12 +- drivers/staging/lustre/lustre/osc/osc_page.c | 20 -- 14 files changed, 312 insertions(+), 340 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 89292c93dcd5..bf93c1e63d33 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -884,26 +884,6 @@ struct cl_page_operations { /** Destructor. Frees resources and slice itself. */ void (*cpo_fini)(const struct lu_env *env, struct cl_page_slice *slice); - - /** - * Checks whether the page is protected by a cl_lock. This is a - * per-layer method, because certain layers have ways to check for the - * lock much more efficiently than through the generic locks scan, or - * implement locking mechanisms separate from cl_lock, e.g., - * LL_FILE_GROUP_LOCKED in vvp. If \a pending is true, check for locks - * being canceled, or scheduled for cancellation as soon as the last - * user goes away, too. - * - * \retval -EBUSY: page is protected by a lock of a given mode; - * \retval -ENODATA: page is not protected by a lock; - * \retval 0: this layer cannot decide. - * - * \see cl_page_is_under_lock() - */ - int (*cpo_is_under_lock)(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io, pgoff_t *max); - /** * Optional debugging helper. Prints given page slice. * @@ -1365,7 +1345,6 @@ struct cl_2queue { * (3) sort all locks to avoid dead-locks, and acquire them * * (4) process the chunk: call per-page methods - * (cl_io_operations::cio_read_page() for read, * cl_io_operations::cio_prepare_write(), * cl_io_operations::cio_commit_write() for write) * @@ -1467,6 +1446,31 @@ struct cl_io_slice { typedef void (*cl_commit_cbt)(const struct lu_env *, struct cl_io *, struct cl_page *); + +struct cl_read_ahead { + /* + * Maximum page index the readahead window will end. + * This is determined DLM lock coverage, RPC and stripe boundary. + * cra_end is included. + */ + pgoff_t cra_end; + /* + * Release routine. If readahead holds resources underneath, this + * function should be called to release it. + */ + void (*cra_release)(const struct lu_env *env, void *cbdata); + /* Callback data for cra_release routine */ + void *cra_cbdata; +}; + +static inline void cl_read_ahead_release(const struct lu_env *env, + struct cl_read_ahead *ra) +{ + if (ra->cra_release) + ra->cra_release(env, ra->cra_cbdata); + memset(ra, 0, sizeof(*ra)); +} + /** * Per-layer io operations. * \see vvp_io_ops, lov_io_ops, lovsub_io_ops, osc_io_ops @@ -1573,16 +1577,13 @@ struct cl_io_operations { struct cl_page_list *queue, int from, int to, cl_commit_cbt cb); /** - * Read missing page. - * - * Called by a top-level cl_io_operations::op[CIT_READ]::cio_start() - * method, when it hits not-up-to-date page in the range. Optional. + * Decide maximum read ahead extent * * \pre io->ci_type == CIT_READ */ - int (*cio_read_page)(const struct lu_env *env, - const struct cl_io_slice *slice, - const struct cl_page_slice *page); + int (*cio_read_ahead)(const struct lu_env *env, + const struct cl_io_slice *slice, + pgoff_t start, struct cl_read_ahead *ra); /** * Optional debugging helper. Print given io slice. */ @@ -2302,8 +2303,6 @@ void cl_page_discard(const struct lu_env *env, struct cl_io *io, void cl_page_delete(const struct lu_env *env, struct cl_page *pg); int cl_page_is_vmlocked(const struct lu_env *env, const struct cl_page *pg); void cl_page_export(const struct lu_env *env, struct cl_page *pg, int uptodate); -int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, pgoff_t *max_index); loff_t cl_offset(const struct cl_object *obj, pgoff_t idx); pgoff_t cl_index(const struct cl_object *obj, loff_t offset); size_t cl_page_size(const struct cl_object *obj); @@ -2414,8 +2413,6 @@ int cl_io_lock_add(const struct lu_env *env, struct cl_io *io, struct cl_io_lock_link *link); int cl_io_lock_alloc_add(const struct lu_env *env, struct cl_io *io, struct cl_lock_descr *descr); -int cl_io_read_page(const struct lu_env *env, struct cl_io *io, - struct cl_page *page); int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io, enum cl_req_type iot, struct cl_2queue *queue); int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io, @@ -2424,6 +2421,8 @@ int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io, int cl_io_commit_async(const struct lu_env *env, struct cl_io *io, struct cl_page_list *queue, int from, int to, cl_commit_cbt cb); +int cl_io_read_ahead(const struct lu_env *env, struct cl_io *io, + pgoff_t start, struct cl_read_ahead *ra); int cl_io_is_going(const struct lu_env *env); /** diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index a66891d4b32a..3ea2d4bf0782 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -722,9 +722,7 @@ int ll_writepage(struct page *page, struct writeback_control *wbc); int ll_writepages(struct address_space *, struct writeback_control *wbc); int ll_readpage(struct file *file, struct page *page); void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras); -int ll_readahead(const struct lu_env *env, struct cl_io *io, - struct cl_page_list *queue, struct ll_readahead_state *ras, - bool hit); +int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io); struct ll_cl_context *ll_cl_find(struct file *file); void ll_cl_add(struct file *file, const struct lu_env *env, struct cl_io *io); void ll_cl_remove(struct file *file, const struct lu_env *env); @@ -1009,9 +1007,6 @@ int cl_sb_init(struct super_block *sb); int cl_sb_fini(struct super_block *sb); void ll_io_init(struct cl_io *io, const struct file *file, int write); -void ras_update(struct ll_sb_info *sbi, struct inode *inode, - struct ll_readahead_state *ras, unsigned long index, - unsigned hit); void ll_ra_count_put(struct ll_sb_info *sbi, unsigned long len); void ll_ra_stats_inc(struct inode *inode, enum ra_stat which); diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 50c0152ba022..80cb8e0d6666 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -180,90 +180,73 @@ void ll_ras_enter(struct file *f) spin_unlock(&ras->ras_lock); } -static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io, - struct cl_page_list *queue, struct cl_page *page, - struct cl_object *clob, pgoff_t *max_index) +/** + * Initiates read-ahead of a page with given index. + * + * \retval +ve: page was already uptodate so it will be skipped + * from being added; + * \retval -ve: page wasn't added to \a queue for error; + * \retval 0: page was added into \a queue for read ahead. + */ +static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io, + struct cl_page_list *queue, pgoff_t index) { - struct page *vmpage = page->cp_vmpage; + enum ra_stat which = _NR_RA_STAT; /* keep gcc happy */ + struct cl_object *clob = io->ci_obj; + struct inode *inode = vvp_object_inode(clob); + const char *msg = NULL; + struct cl_page *page; struct vvp_page *vpg; - int rc; + struct page *vmpage; + int rc = 0; + + vmpage = grab_cache_page_nowait(inode->i_mapping, index); + if (!vmpage) { + which = RA_STAT_FAILED_GRAB_PAGE; + msg = "g_c_p_n failed"; + rc = -EBUSY; + goto out; + } + + /* Check if vmpage was truncated or reclaimed */ + if (vmpage->mapping != inode->i_mapping) { + which = RA_STAT_WRONG_GRAB_PAGE; + msg = "g_c_p_n returned invalid page"; + rc = -EBUSY; + goto out; + } + + page = cl_page_find(env, clob, vmpage->index, vmpage, CPT_CACHEABLE); + if (IS_ERR(page)) { + which = RA_STAT_FAILED_GRAB_PAGE; + msg = "cl_page_find failed"; + rc = PTR_ERR(page); + goto out; + } - rc = 0; - cl_page_assume(env, io, page); lu_ref_add(&page->cp_reference, "ra", current); + cl_page_assume(env, io, page); vpg = cl2vvp_page(cl_object_page_slice(clob, page)); if (!vpg->vpg_defer_uptodate && !PageUptodate(vmpage)) { - CDEBUG(D_READA, "page index %lu, max_index: %lu\n", - vvp_index(vpg), *max_index); - if (*max_index == 0 || vvp_index(vpg) > *max_index) - rc = cl_page_is_under_lock(env, io, page, max_index); - if (rc == 0) { - vpg->vpg_defer_uptodate = 1; - vpg->vpg_ra_used = 0; - cl_page_list_add(queue, page); - rc = 1; - } else { - cl_page_discard(env, io, page); - rc = -ENOLCK; - } + vpg->vpg_defer_uptodate = 1; + vpg->vpg_ra_used = 0; + cl_page_list_add(queue, page); } else { /* skip completed pages */ cl_page_unassume(env, io, page); + /* This page is already uptodate, returning a positive number + * to tell the callers about this + */ + rc = 1; } + lu_ref_del(&page->cp_reference, "ra", current); cl_page_put(env, page); - return rc; -} - -/** - * Initiates read-ahead of a page with given index. - * - * \retval +ve: page was added to \a queue. - * - * \retval -ENOLCK: there is no extent lock for this part of a file, stop - * read-ahead. - * - * \retval -ve, 0: page wasn't added to \a queue for other reason. - */ -static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io, - struct cl_page_list *queue, - pgoff_t index, pgoff_t *max_index) -{ - struct cl_object *clob = io->ci_obj; - struct inode *inode = vvp_object_inode(clob); - struct page *vmpage; - struct cl_page *page; - enum ra_stat which = _NR_RA_STAT; /* keep gcc happy */ - int rc = 0; - const char *msg = NULL; - - vmpage = grab_cache_page_nowait(inode->i_mapping, index); +out: if (vmpage) { - /* Check if vmpage was truncated or reclaimed */ - if (vmpage->mapping == inode->i_mapping) { - page = cl_page_find(env, clob, vmpage->index, - vmpage, CPT_CACHEABLE); - if (!IS_ERR(page)) { - rc = cl_read_ahead_page(env, io, queue, - page, clob, max_index); - if (rc == -ENOLCK) { - which = RA_STAT_FAILED_MATCH; - msg = "lock match failed"; - } - } else { - which = RA_STAT_FAILED_GRAB_PAGE; - msg = "cl_page_find failed"; - } - } else { - which = RA_STAT_WRONG_GRAB_PAGE; - msg = "g_c_p_n returned invalid page"; - } - if (rc != 1) + if (rc) unlock_page(vmpage); put_page(vmpage); - } else { - which = RA_STAT_FAILED_GRAB_PAGE; - msg = "g_c_p_n failed"; } if (msg) { ll_ra_stats_inc(inode, which); @@ -378,12 +361,12 @@ static int ll_read_ahead_pages(const struct lu_env *env, struct cl_io *io, struct cl_page_list *queue, struct ra_io_arg *ria, unsigned long *reserved_pages, - unsigned long *ra_end) + pgoff_t *ra_end) { + struct cl_read_ahead ra = { 0 }; int rc, count = 0; bool stride_ria; pgoff_t page_idx; - pgoff_t max_index = 0; LASSERT(ria); RIA_DEBUG(ria); @@ -392,14 +375,23 @@ static int ll_read_ahead_pages(const struct lu_env *env, for (page_idx = ria->ria_start; page_idx <= ria->ria_end && *reserved_pages > 0; page_idx++) { if (ras_inside_ra_window(page_idx, ria)) { + if (!ra.cra_end || ra.cra_end < page_idx) { + cl_read_ahead_release(env, &ra); + + rc = cl_io_read_ahead(env, io, page_idx, &ra); + if (rc < 0) + break; + + LASSERTF(ra.cra_end >= page_idx, + "object: %p, indcies %lu / %lu\n", + io->ci_obj, ra.cra_end, page_idx); + } + /* If the page is inside the read-ahead window*/ - rc = ll_read_ahead_page(env, io, queue, - page_idx, &max_index); - if (rc == 1) { + rc = ll_read_ahead_page(env, io, queue, page_idx); + if (!rc) { (*reserved_pages)--; count++; - } else if (rc == -ENOLCK) { - break; } } else if (stride_ria) { /* If it is not in the read-ahead window, and it is @@ -425,19 +417,21 @@ static int ll_read_ahead_pages(const struct lu_env *env, } } } + cl_read_ahead_release(env, &ra); + *ra_end = page_idx; return count; } -int ll_readahead(const struct lu_env *env, struct cl_io *io, - struct cl_page_list *queue, struct ll_readahead_state *ras, - bool hit) +static int ll_readahead(const struct lu_env *env, struct cl_io *io, + struct cl_page_list *queue, + struct ll_readahead_state *ras, bool hit) { struct vvp_io *vio = vvp_env_io(env); struct ll_thread_info *lti = ll_env_info(env); struct cl_attr *attr = vvp_env_thread_attr(env); - unsigned long start = 0, end = 0, reserved; - unsigned long ra_end, len, mlen = 0; + unsigned long len, mlen = 0, reserved; + pgoff_t ra_end, start = 0, end = 0; struct inode *inode; struct ra_io_arg *ria = <i->lti_ria; struct cl_object *clob; @@ -575,8 +569,8 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, * if the region we failed to issue read-ahead on is still ahead * of the app and behind the next index to start read-ahead from */ - CDEBUG(D_READA, "ra_end %lu end %lu stride end %lu\n", - ra_end, end, ria->ria_end); + CDEBUG(D_READA, "ra_end = %lu end = %lu stride end = %lu pages = %d\n", + ra_end, end, ria->ria_end, ret); if (ra_end != end + 1) { ll_ra_stats_inc(inode, RA_STAT_FAILED_REACH_END); @@ -737,9 +731,9 @@ static void ras_increase_window(struct inode *inode, ra->ra_max_pages_per_file); } -void ras_update(struct ll_sb_info *sbi, struct inode *inode, - struct ll_readahead_state *ras, unsigned long index, - unsigned hit) +static void ras_update(struct ll_sb_info *sbi, struct inode *inode, + struct ll_readahead_state *ras, unsigned long index, + unsigned int hit) { struct ll_ra_info *ra = &sbi->ll_ra_info; int zero = 0, stride_detect = 0, ra_miss = 0; @@ -1087,6 +1081,56 @@ void ll_cl_remove(struct file *file, const struct lu_env *env) write_unlock(&fd->fd_lock); } +static int ll_io_read_page(const struct lu_env *env, struct cl_io *io, + struct cl_page *page) +{ + struct inode *inode = vvp_object_inode(page->cp_obj); + struct ll_file_data *fd = vvp_env_io(env)->vui_fd; + struct ll_readahead_state *ras = &fd->fd_ras; + struct cl_2queue *queue = &io->ci_queue; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct vvp_page *vpg; + int rc = 0; + + vpg = cl2vvp_page(cl_object_page_slice(page->cp_obj, page)); + if (sbi->ll_ra_info.ra_max_pages_per_file > 0 && + sbi->ll_ra_info.ra_max_pages > 0) + ras_update(sbi, inode, ras, vvp_index(vpg), + vpg->vpg_defer_uptodate); + + if (vpg->vpg_defer_uptodate) { + vpg->vpg_ra_used = 1; + cl_page_export(env, page, 1); + } + + cl_2queue_init(queue); + /* + * Add page into the queue even when it is marked uptodate above. + * this will unlock it automatically as part of cl_page_list_disown(). + */ + cl_page_list_add(&queue->c2_qin, page); + if (sbi->ll_ra_info.ra_max_pages_per_file > 0 && + sbi->ll_ra_info.ra_max_pages > 0) { + int rc2; + + rc2 = ll_readahead(env, io, &queue->c2_qin, ras, + vpg->vpg_defer_uptodate); + CDEBUG(D_READA, DFID "%d pages read ahead at %lu\n", + PFID(ll_inode2fid(inode)), rc2, vvp_index(vpg)); + } + + if (queue->c2_qin.pl_nr > 0) + rc = cl_io_submit_rw(env, io, CRT_READ, queue); + + /* + * Unlock unsent pages in case of error. + */ + cl_page_list_disown(env, io, &queue->c2_qin); + cl_2queue_fini(env, queue); + + return rc; +} + int ll_readpage(struct file *file, struct page *vmpage) { struct cl_object *clob = ll_i2info(file_inode(file))->lli_clob; @@ -1110,7 +1154,7 @@ int ll_readpage(struct file *file, struct page *vmpage) LASSERT(page->cp_type == CPT_CACHEABLE); if (likely(!PageUptodate(vmpage))) { cl_page_assume(env, io, page); - result = cl_io_read_page(env, io, page); + result = ll_io_read_page(env, io, page); } else { /* Page from a non-object file. */ unlock_page(vmpage); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 3e47f6642c48..d1d4b232824f 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -1191,40 +1191,23 @@ static int vvp_io_fsync_start(const struct lu_env *env, return 0; } -static int vvp_io_read_page(const struct lu_env *env, - const struct cl_io_slice *ios, - const struct cl_page_slice *slice) +static int vvp_io_read_ahead(const struct lu_env *env, + const struct cl_io_slice *ios, + pgoff_t start, struct cl_read_ahead *ra) { - struct cl_io *io = ios->cis_io; - struct vvp_page *vpg = cl2vvp_page(slice); - struct cl_page *page = slice->cpl_page; - struct inode *inode = vvp_object_inode(slice->cpl_obj); - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ll_file_data *fd = cl2vvp_io(env, ios)->vui_fd; - struct ll_readahead_state *ras = &fd->fd_ras; - struct cl_2queue *queue = &io->ci_queue; - - if (sbi->ll_ra_info.ra_max_pages_per_file && - sbi->ll_ra_info.ra_max_pages) - ras_update(sbi, inode, ras, vvp_index(vpg), - vpg->vpg_defer_uptodate); - - if (vpg->vpg_defer_uptodate) { - vpg->vpg_ra_used = 1; - cl_page_export(env, page, 1); - } - /* - * Add page into the queue even when it is marked uptodate above. - * this will unlock it automatically as part of cl_page_list_disown(). - */ + int result = 0; - cl_page_list_add(&queue->c2_qin, page); - if (sbi->ll_ra_info.ra_max_pages_per_file && - sbi->ll_ra_info.ra_max_pages) - ll_readahead(env, io, &queue->c2_qin, ras, - vpg->vpg_defer_uptodate); + if (ios->cis_io->ci_type == CIT_READ || + ios->cis_io->ci_type == CIT_FAULT) { + struct vvp_io *vio = cl2vvp_io(env, ios); - return 0; + if (unlikely(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { + ra->cra_end = CL_PAGE_EOF; + result = 1; /* no need to call down */ + } + } + + return result; } static void vvp_io_end(const struct lu_env *env, const struct cl_io_slice *ios) @@ -1271,7 +1254,7 @@ static const struct cl_io_operations vvp_io_ops = { .cio_fini = vvp_io_fini } }, - .cio_read_page = vvp_io_read_page, + .cio_read_ahead = vvp_io_read_ahead, }; int vvp_io_init(const struct lu_env *env, struct cl_object *obj, diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 0041cd8f0ce5..25490a5188d3 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -339,20 +339,6 @@ static int vvp_page_make_ready(const struct lu_env *env, return result; } -static int vvp_page_is_under_lock(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io, pgoff_t *max_index) -{ - if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE || - io->ci_type == CIT_FAULT) { - struct vvp_io *vio = vvp_env_io(env); - - if (unlikely(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) - *max_index = CL_PAGE_EOF; - } - return 0; -} - static int vvp_page_print(const struct lu_env *env, const struct cl_page_slice *slice, void *cookie, lu_printer_t printer) @@ -397,7 +383,6 @@ static const struct cl_page_operations vvp_page_ops = { .cpo_is_vmlocked = vvp_page_is_vmlocked, .cpo_fini = vvp_page_fini, .cpo_print = vvp_page_print, - .cpo_is_under_lock = vvp_page_is_under_lock, .io = { [CRT_READ] = { .cpo_prep = vvp_page_prep_read, @@ -496,7 +481,6 @@ static const struct cl_page_operations vvp_transient_page_ops = { .cpo_fini = vvp_transient_page_fini, .cpo_is_vmlocked = vvp_transient_page_is_vmlocked, .cpo_print = vvp_page_print, - .cpo_is_under_lock = vvp_page_is_under_lock, .io = { [CRT_READ] = { .cpo_prep = vvp_transient_page_prep, diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index d10157985ed9..e75e5d2e7f08 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -555,6 +555,63 @@ static void lov_io_unlock(const struct lu_env *env, LASSERT(rc == 0); } +static int lov_io_read_ahead(const struct lu_env *env, + const struct cl_io_slice *ios, + pgoff_t start, struct cl_read_ahead *ra) +{ + struct lov_io *lio = cl2lov_io(env, ios); + struct lov_object *loo = lio->lis_object; + struct cl_object *obj = lov2cl(loo); + struct lov_layout_raid0 *r0 = lov_r0(loo); + unsigned int pps; /* pages per stripe */ + struct lov_io_sub *sub; + pgoff_t ra_end; + loff_t suboff; + int stripe; + int rc; + + stripe = lov_stripe_number(loo->lo_lsm, cl_offset(obj, start)); + if (unlikely(!r0->lo_sub[stripe])) + return -EIO; + + sub = lov_sub_get(env, lio, stripe); + + lov_stripe_offset(loo->lo_lsm, cl_offset(obj, start), stripe, &suboff); + rc = cl_io_read_ahead(sub->sub_env, sub->sub_io, + cl_index(lovsub2cl(r0->lo_sub[stripe]), suboff), + ra); + lov_sub_put(sub); + + CDEBUG(D_READA, DFID " cra_end = %lu, stripes = %d, rc = %d\n", + PFID(lu_object_fid(lov2lu(loo))), ra->cra_end, r0->lo_nr, rc); + if (rc) + return rc; + + /** + * Adjust the stripe index by layout of raid0. ra->cra_end is + * the maximum page index covered by an underlying DLM lock. + * This function converts cra_end from stripe level to file + * level, and make sure it's not beyond stripe boundary. + */ + if (r0->lo_nr == 1) /* single stripe file */ + return 0; + + /* cra_end is stripe level, convert it into file level */ + ra_end = ra->cra_end; + if (ra_end != CL_PAGE_EOF) + ra_end = lov_stripe_pgoff(loo->lo_lsm, ra_end, stripe); + + pps = loo->lo_lsm->lsm_stripe_size >> PAGE_SHIFT; + + CDEBUG(D_READA, DFID " max_index = %lu, pps = %u, stripe_size = %u, stripe no = %u, start index = %lu\n", + PFID(lu_object_fid(lov2lu(loo))), ra_end, pps, + loo->lo_lsm->lsm_stripe_size, stripe, start); + + /* never exceed the end of the stripe */ + ra->cra_end = min_t(pgoff_t, ra_end, start + pps - start % pps - 1); + return 0; +} + /** * lov implementation of cl_operations::cio_submit() method. It takes a list * of pages in \a queue, splits it into per-stripe sub-lists, invokes @@ -801,6 +858,7 @@ static const struct cl_io_operations lov_io_ops = { .cio_fini = lov_io_fini } }, + .cio_read_ahead = lov_io_read_ahead, .cio_submit = lov_io_submit, .cio_commit_async = lov_io_commit_async, }; diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index 00bfabad78eb..62ceb6dfdfdf 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -49,51 +49,6 @@ * */ -/** - * Adjust the stripe index by layout of raid0. @max_index is the maximum - * page index covered by an underlying DLM lock. - * This function converts max_index from stripe level to file level, and make - * sure it's not beyond one stripe. - */ -static int lov_raid0_page_is_under_lock(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *unused, - pgoff_t *max_index) -{ - struct lov_object *loo = cl2lov(slice->cpl_obj); - struct lov_layout_raid0 *r0 = lov_r0(loo); - pgoff_t index = *max_index; - unsigned int pps; /* pages per stripe */ - - CDEBUG(D_READA, DFID "*max_index = %lu, nr = %d\n", - PFID(lu_object_fid(lov2lu(loo))), index, r0->lo_nr); - - if (index == 0) /* the page is not covered by any lock */ - return 0; - - if (r0->lo_nr == 1) /* single stripe file */ - return 0; - - /* max_index is stripe level, convert it into file level */ - if (index != CL_PAGE_EOF) { - int stripeno = lov_page_stripe(slice->cpl_page); - *max_index = lov_stripe_pgoff(loo->lo_lsm, index, stripeno); - } - - /* calculate the end of current stripe */ - pps = loo->lo_lsm->lsm_stripe_size >> PAGE_SHIFT; - index = slice->cpl_index + pps - slice->cpl_index % pps - 1; - - CDEBUG(D_READA, DFID "*max_index = %lu, index = %lu, pps = %u, stripe_size = %u, stripe no = %u, page index = %lu\n", - PFID(lu_object_fid(lov2lu(loo))), *max_index, index, pps, - loo->lo_lsm->lsm_stripe_size, lov_page_stripe(slice->cpl_page), - slice->cpl_index); - - /* never exceed the end of the stripe */ - *max_index = min_t(pgoff_t, *max_index, index); - return 0; -} - static int lov_raid0_page_print(const struct lu_env *env, const struct cl_page_slice *slice, void *cookie, lu_printer_t printer) @@ -104,7 +59,6 @@ static int lov_raid0_page_print(const struct lu_env *env, } static const struct cl_page_operations lov_raid0_page_ops = { - .cpo_is_under_lock = lov_raid0_page_is_under_lock, .cpo_print = lov_raid0_page_print }; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index bc4b7b6b9a20..577f76edea00 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -586,67 +586,32 @@ void cl_io_end(const struct lu_env *env, struct cl_io *io) } EXPORT_SYMBOL(cl_io_end); -static const struct cl_page_slice * -cl_io_slice_page(const struct cl_io_slice *ios, struct cl_page *page) -{ - const struct cl_page_slice *slice; - - slice = cl_page_at(page, ios->cis_obj->co_lu.lo_dev->ld_type); - LINVRNT(slice); - return slice; -} - /** - * Called by read io, when page has to be read from the server. + * Called by read io, to decide the readahead extent * - * \see cl_io_operations::cio_read_page() + * \see cl_io_operations::cio_read_ahead() */ -int cl_io_read_page(const struct lu_env *env, struct cl_io *io, - struct cl_page *page) +int cl_io_read_ahead(const struct lu_env *env, struct cl_io *io, + pgoff_t start, struct cl_read_ahead *ra) { const struct cl_io_slice *scan; - struct cl_2queue *queue; int result = 0; LINVRNT(io->ci_type == CIT_READ || io->ci_type == CIT_FAULT); - LINVRNT(cl_page_is_owned(page, io)); LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED); LINVRNT(cl_io_invariant(io)); - queue = &io->ci_queue; - - cl_2queue_init(queue); - /* - * ->cio_read_page() methods called in the loop below are supposed to - * never block waiting for network (the only subtle point is the - * creation of new pages for read-ahead that might result in cache - * shrinking, but currently only clean pages are shrunk and this - * requires no network io). - * - * Should this ever starts blocking, retry loop would be needed for - * "parallel io" (see CLO_REPEAT loops in cl_lock.c). - */ cl_io_for_each(scan, io) { - if (scan->cis_iop->cio_read_page) { - const struct cl_page_slice *slice; + if (!scan->cis_iop->cio_read_ahead) + continue; - slice = cl_io_slice_page(scan, page); - LINVRNT(slice); - result = scan->cis_iop->cio_read_page(env, scan, slice); - if (result != 0) - break; - } + result = scan->cis_iop->cio_read_ahead(env, scan, start, ra); + if (result) + break; } - if (result == 0 && queue->c2_qin.pl_nr > 0) - result = cl_io_submit_rw(env, io, CRT_READ, queue); - /* - * Unlock unsent pages in case of error. - */ - cl_page_list_disown(env, io, &queue->c2_qin); - cl_2queue_fini(env, queue); - return result; + return result > 0 ? 0 : result; } -EXPORT_SYMBOL(cl_io_read_page); +EXPORT_SYMBOL(cl_io_read_ahead); /** * Commit a list of contiguous pages into writeback cache. diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 63973ba096da..40b7beee5e7b 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -390,30 +390,6 @@ EXPORT_SYMBOL(cl_page_at); __result; \ }) -#define CL_PAGE_INVOKE_REVERSE(_env, _page, _op, _proto, ...) \ -({ \ - const struct lu_env *__env = (_env); \ - struct cl_page *__page = (_page); \ - const struct cl_page_slice *__scan; \ - int __result; \ - ptrdiff_t __op = (_op); \ - int (*__method)_proto; \ - \ - __result = 0; \ - list_for_each_entry_reverse(__scan, &__page->cp_layers, \ - cpl_linkage) { \ - __method = *(void **)((char *)__scan->cpl_ops + __op); \ - if (__method) { \ - __result = (*__method)(__env, __scan, ## __VA_ARGS__); \ - if (__result != 0) \ - break; \ - } \ - } \ - if (__result > 0) \ - __result = 0; \ - __result; \ -}) - #define CL_PAGE_INVOID(_env, _page, _op, _proto, ...) \ do { \ const struct lu_env *__env = (_env); \ @@ -926,29 +902,6 @@ int cl_page_flush(const struct lu_env *env, struct cl_io *io, } EXPORT_SYMBOL(cl_page_flush); -/** - * Checks whether page is protected by any extent lock is at least required - * mode. - * - * \return the same as in cl_page_operations::cpo_is_under_lock() method. - * \see cl_page_operations::cpo_is_under_lock() - */ -int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, pgoff_t *max_index) -{ - int rc; - - PINVRNT(env, page, cl_page_invariant(page)); - - rc = CL_PAGE_INVOKE_REVERSE(env, page, CL_PAGE_OP(cpo_is_under_lock), - (const struct lu_env *, - const struct cl_page_slice *, - struct cl_io *, pgoff_t *), - io, max_index); - return rc; -} -EXPORT_SYMBOL(cl_page_is_under_lock); - /** * Tells transfer engine that only part of a page is to be transmitted. * diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 4bbe219add98..b6459579b6a4 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -3158,7 +3158,8 @@ static int check_and_discard_cb(const struct lu_env *env, struct cl_io *io, struct cl_page *page = ops->ops_cl.cpl_page; /* refresh non-overlapped index */ - tmp = osc_dlmlock_at_pgoff(env, osc, index, 0, 0); + tmp = osc_dlmlock_at_pgoff(env, osc, index, + OSC_DAP_FL_TEST_LOCK); if (tmp) { __u64 end = tmp->l_policy_data.l_extent.end; /* Cache the first-non-overlapped index so as to skip diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 67fe0a254991..9a61c9b652d6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -199,8 +199,23 @@ void osc_inc_unstable_pages(struct ptlrpc_request *req); void osc_dec_unstable_pages(struct ptlrpc_request *req); bool osc_over_unstable_soft_limit(struct client_obd *cli); +/** + * Bit flags for osc_dlm_lock_at_pageoff(). + */ +enum osc_dap_flags { + /** + * Just check if the desired lock exists, it won't hold reference + * count on lock. + */ + OSC_DAP_FL_TEST_LOCK = BIT(0), + /** + * Return the lock even if it is being canceled. + */ + OSC_DAP_FL_CANCELING = BIT(1), +}; + struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env, struct osc_object *obj, pgoff_t index, - int pending, int canceling); + enum osc_dap_flags flags); #endif /* OSC_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 8a559cbcdd0c..47c63710d749 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -88,6 +88,44 @@ static void osc_io_fini(const struct lu_env *env, const struct cl_io_slice *io) { } +static void osc_read_ahead_release(const struct lu_env *env, void *cbdata) +{ + struct ldlm_lock *dlmlock = cbdata; + struct lustre_handle lockh; + + ldlm_lock2handle(dlmlock, &lockh); + ldlm_lock_decref(&lockh, LCK_PR); + LDLM_LOCK_PUT(dlmlock); +} + +static int osc_io_read_ahead(const struct lu_env *env, + const struct cl_io_slice *ios, + pgoff_t start, struct cl_read_ahead *ra) +{ + struct osc_object *osc = cl2osc(ios->cis_obj); + struct ldlm_lock *dlmlock; + int result = -ENODATA; + + dlmlock = osc_dlmlock_at_pgoff(env, osc, start, 0); + if (dlmlock) { + if (dlmlock->l_req_mode != LCK_PR) { + struct lustre_handle lockh; + + ldlm_lock2handle(dlmlock, &lockh); + ldlm_lock_addref(&lockh, LCK_PR); + ldlm_lock_decref(&lockh, dlmlock->l_req_mode); + } + + ra->cra_end = cl_index(osc2cl(osc), + dlmlock->l_policy_data.l_extent.end); + ra->cra_release = osc_read_ahead_release; + ra->cra_cbdata = dlmlock; + result = 0; + } + + return result; +} + /** * An implementation of cl_io_operations::cio_io_submit() method for osc * layer. Iterates over pages in the in-queue, prepares each for io by calling @@ -724,6 +762,7 @@ static const struct cl_io_operations osc_io_ops = { .cio_fini = osc_io_fini } }, + .cio_read_ahead = osc_io_read_ahead, .cio_submit = osc_io_submit, .cio_commit_async = osc_io_commit_async }; @@ -798,7 +837,7 @@ static void osc_req_attr_set(const struct lu_env *env, struct cl_page, cp_flight); opg = osc_cl_page_osc(apage, NULL); lock = osc_dlmlock_at_pgoff(env, cl2osc(obj), osc_index(opg), - 1, 1); + OSC_DAP_FL_TEST_LOCK | OSC_DAP_FL_CANCELING); if (!lock && !opg->ops_srvlock) { struct ldlm_resource *res; struct ldlm_res_id *resname; diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 39a8a5851603..a42cb9871152 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -1180,7 +1180,7 @@ int osc_lock_init(const struct lu_env *env, */ struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env, struct osc_object *obj, pgoff_t index, - int pending, int canceling) + enum osc_dap_flags dap_flags) { struct osc_thread_info *info = osc_env_info(env); struct ldlm_res_id *resname = &info->oti_resname; @@ -1194,9 +1194,10 @@ struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env, osc_index2policy(policy, osc2cl(obj), index, index); policy->l_extent.gid = LDLM_GID_ANY; - flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK; - if (pending) - flags |= LDLM_FL_CBPENDING; + flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING; + if (dap_flags & OSC_DAP_FL_TEST_LOCK) + flags |= LDLM_FL_TEST_LOCK; + /* * It is fine to match any group lock since there could be only one * with a uniq gid and it conflicts with all other lock modes too @@ -1204,7 +1205,8 @@ struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env, again: mode = ldlm_lock_match(osc_export(obj)->exp_obd->obd_namespace, flags, resname, LDLM_EXTENT, policy, - LCK_PR | LCK_PW | LCK_GROUP, &lockh, canceling); + LCK_PR | LCK_PW | LCK_GROUP, &lockh, + dap_flags & OSC_DAP_FL_CANCELING); if (mode != 0) { lock = ldlm_handle2lock(&lockh); /* RACE: the lock is cancelled so let's try again */ diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 2a7a70aa9e80..399d36b11a32 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -117,25 +117,6 @@ void osc_index2policy(ldlm_policy_data_t *policy, const struct cl_object *obj, policy->l_extent.end = cl_offset(obj, end + 1) - 1; } -static int osc_page_is_under_lock(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *unused, pgoff_t *max_index) -{ - struct osc_page *opg = cl2osc_page(slice); - struct ldlm_lock *dlmlock; - int result = -ENODATA; - - dlmlock = osc_dlmlock_at_pgoff(env, cl2osc(slice->cpl_obj), - osc_index(opg), 1, 0); - if (dlmlock) { - *max_index = cl_index(slice->cpl_obj, - dlmlock->l_policy_data.l_extent.end); - LDLM_LOCK_PUT(dlmlock); - result = 0; - } - return result; -} - static const char *osc_list(struct list_head *head) { return list_empty(head) ? "-" : "+"; @@ -276,7 +257,6 @@ static int osc_page_flush(const struct lu_env *env, static const struct cl_page_operations osc_page_ops = { .cpo_print = osc_page_print, .cpo_delete = osc_page_delete, - .cpo_is_under_lock = osc_page_is_under_lock, .cpo_clip = osc_page_clip, .cpo_cancel = osc_page_cancel, .cpo_flush = osc_page_flush -- cgit v1.2.3 From e7226dd4da4857844c935b260dd86b8e2b5f4d64 Mon Sep 17 00:00:00 2001 From: frank zago Date: Sun, 2 Oct 2016 22:28:02 -0400 Subject: staging: lustre: ldlm: remove unnecessary EXPORT_SYMBOL A lot of symbols don't need to be exported at all because they are only used in the module they belong to. Signed-off-by: frank zago Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5829 Reviewed-on: http://review.whamcloud.com/13324 Reviewed-by: James Simmons Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 3 --- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c | 2 -- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c | 6 ------ drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 3 --- drivers/staging/lustre/lustre/ldlm/ldlm_resource.c | 4 ---- 5 files changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 3c48b4fb96f1..ace8cb220c7f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -512,7 +512,6 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock, return 0; } -EXPORT_SYMBOL(ldlm_lock_change_resource); /** \defgroup ldlm_handles LDLM HANDLES * Ways to get hold of locks without any addresses. @@ -595,7 +594,6 @@ void ldlm_lock2desc(struct ldlm_lock *lock, struct ldlm_lock_desc *desc) &lock->l_policy_data, &desc->l_policy_data); } -EXPORT_SYMBOL(ldlm_lock2desc); /** * Add a lock to list of conflicting locks to send AST to. @@ -1147,7 +1145,6 @@ void ldlm_lock_fail_match_locked(struct ldlm_lock *lock) wake_up_all(&lock->l_waitq); } } -EXPORT_SYMBOL(ldlm_lock_fail_match_locked); /** * Mark lock as "matchable" by OST. diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index fde697ebaadc..c32b414c93ba 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -858,7 +858,6 @@ int ldlm_get_ref(void) return rc; } -EXPORT_SYMBOL(ldlm_get_ref); void ldlm_put_ref(void) { @@ -875,7 +874,6 @@ void ldlm_put_ref(void) } mutex_unlock(&ldlm_ref_mutex); } -EXPORT_SYMBOL(ldlm_put_ref); static ssize_t cancel_unused_locks_before_replay_show(struct kobject *kobj, struct attribute *attr, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 9a1136e32dfc..b29c9561a712 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -684,7 +684,6 @@ int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns, return rc; } -EXPORT_SYMBOL(ldlm_pool_init); void ldlm_pool_fini(struct ldlm_pool *pl) { @@ -698,7 +697,6 @@ void ldlm_pool_fini(struct ldlm_pool *pl) */ POISON(pl, 0x5a, sizeof(*pl)); } -EXPORT_SYMBOL(ldlm_pool_fini); /** * Add new taken ldlm lock \a lock into pool \a pl accounting. @@ -724,7 +722,6 @@ void ldlm_pool_add(struct ldlm_pool *pl, struct ldlm_lock *lock) * with too long call paths. */ } -EXPORT_SYMBOL(ldlm_pool_add); /** * Remove ldlm lock \a lock from pool \a pl accounting. @@ -743,7 +740,6 @@ void ldlm_pool_del(struct ldlm_pool *pl, struct ldlm_lock *lock) lprocfs_counter_incr(pl->pl_stats, LDLM_POOL_CANCEL_STAT); } -EXPORT_SYMBOL(ldlm_pool_del); /** * Returns current \a pl SLV. @@ -1095,7 +1091,6 @@ int ldlm_pools_init(void) return rc; } -EXPORT_SYMBOL(ldlm_pools_init); void ldlm_pools_fini(void) { @@ -1104,4 +1099,3 @@ void ldlm_pools_fini(void) ldlm_pools_thread_stop(); } -EXPORT_SYMBOL(ldlm_pools_fini); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 35ba6f14d95f..98730a353247 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1022,7 +1022,6 @@ int ldlm_cli_update_pool(struct ptlrpc_request *req) return 0; } -EXPORT_SYMBOL(ldlm_cli_update_pool); /** * Client side lock cancel. @@ -1125,7 +1124,6 @@ int ldlm_cli_cancel_list_local(struct list_head *cancels, int count, return count; } -EXPORT_SYMBOL(ldlm_cli_cancel_list_local); /** * Cancel as many locks as possible w/o sending any RPCs (e.g. to write back @@ -2048,4 +2046,3 @@ int ldlm_replay_locks(struct obd_import *imp) return rc; } -EXPORT_SYMBOL(ldlm_replay_locks); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index a09c25aea698..07cb955600fb 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -999,7 +999,6 @@ void ldlm_namespace_get(struct ldlm_namespace *ns) { atomic_inc(&ns->ns_bref); } -EXPORT_SYMBOL(ldlm_namespace_get); /* This is only for callers that care about refcount */ static int ldlm_namespace_get_return(struct ldlm_namespace *ns) @@ -1014,7 +1013,6 @@ void ldlm_namespace_put(struct ldlm_namespace *ns) spin_unlock(&ns->ns_lock); } } -EXPORT_SYMBOL(ldlm_namespace_put); /** Should be called with ldlm_namespace_lock(client) taken. */ void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *ns, @@ -1323,7 +1321,6 @@ void ldlm_dump_all_namespaces(ldlm_side_t client, int level) mutex_unlock(ldlm_namespace_lock(client)); } -EXPORT_SYMBOL(ldlm_dump_all_namespaces); static int ldlm_res_hash_dump(struct cfs_hash *hs, struct cfs_hash_bd *bd, struct hlist_node *hnode, void *arg) @@ -1360,7 +1357,6 @@ void ldlm_namespace_dump(int level, struct ldlm_namespace *ns) ns->ns_next_dump = cfs_time_shift(10); spin_unlock(&ns->ns_lock); } -EXPORT_SYMBOL(ldlm_namespace_dump); /** * Print information about all locks in this resource to debug log. -- cgit v1.2.3 From cbd4d4a8e319050100db4e05d896cee65f011d25 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Sun, 2 Oct 2016 22:28:03 -0400 Subject: staging: lustre: llite: remove duplicate fiemap defines * replace struct ll_user_fiemap with struct fiemap * replace struct ll_fiemap_extent with struct fiemap_extent * remove kernel defined FIEMAP_EXTENT_* constants * remove kernel defined FIEMAP_FLAG_* flags * add member prefix for struct ll_fiemap_info_key * Add cl_object_operations::coo_fiemap(). * Add cl_object_fiemap() to get FIEMAP mappings. Signed-off-by: Bobi Jam Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5823 Reviewed-on: http://review.whamcloud.com/12535 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6201 Reviewed-on: http://review.whamcloud.com/13608 Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Reviewed-by: Yang Sheng Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/cl_object.h | 9 + .../lustre/lustre/include/lustre/ll_fiemap.h | 75 +-- .../lustre/lustre/include/lustre/lustre_idl.h | 8 +- .../lustre/lustre/include/lustre/lustre_user.h | 1 - drivers/staging/lustre/lustre/llite/file.c | 126 +----- drivers/staging/lustre/lustre/lov/lov_obd.c | 421 ----------------- drivers/staging/lustre/lustre/lov/lov_object.c | 504 ++++++++++++++++++++- drivers/staging/lustre/lustre/obdclass/cl_object.c | 32 ++ drivers/staging/lustre/lustre/osc/osc_object.c | 91 +++- drivers/staging/lustre/lustre/osc/osc_request.c | 98 ---- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 4 +- drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 134 +++--- 12 files changed, 742 insertions(+), 761 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index bf93c1e63d33..3af9aa3bac38 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -400,6 +400,12 @@ struct cl_object_operations { */ int (*coo_getstripe)(const struct lu_env *env, struct cl_object *obj, struct lov_user_md __user *lum); + /** + * Get FIEMAP mapping from the object. + */ + int (*coo_fiemap)(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *fmkey, + struct fiemap *fiemap, size_t *buflen); }; /** @@ -2184,6 +2190,9 @@ int cl_object_prune(const struct lu_env *env, struct cl_object *obj); void cl_object_kill(const struct lu_env *env, struct cl_object *obj); int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, struct lov_user_md __user *lum); +int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *fmkey, struct fiemap *fiemap, + size_t *buflen); /** * Returns true, iff \a o0 and \a o1 are slices of the same object. diff --git a/drivers/staging/lustre/lustre/include/lustre/ll_fiemap.h b/drivers/staging/lustre/lustre/include/lustre/ll_fiemap.h index c2340d643e84..b8ad5559a3b9 100644 --- a/drivers/staging/lustre/lustre/include/lustre/ll_fiemap.h +++ b/drivers/staging/lustre/lustre/include/lustre/ll_fiemap.h @@ -41,79 +41,24 @@ #ifndef _LUSTRE_FIEMAP_H #define _LUSTRE_FIEMAP_H -struct ll_fiemap_extent { - __u64 fe_logical; /* logical offset in bytes for the start of - * the extent from the beginning of the file - */ - __u64 fe_physical; /* physical offset in bytes for the start - * of the extent from the beginning of the disk - */ - __u64 fe_length; /* length in bytes for this extent */ - __u64 fe_reserved64[2]; - __u32 fe_flags; /* FIEMAP_EXTENT_* flags for this extent */ - __u32 fe_device; /* device number for this extent */ - __u32 fe_reserved[2]; -}; - -struct ll_user_fiemap { - __u64 fm_start; /* logical offset (inclusive) at - * which to start mapping (in) - */ - __u64 fm_length; /* logical length of mapping which - * userspace wants (in) - */ - __u32 fm_flags; /* FIEMAP_FLAG_* flags for request (in/out) */ - __u32 fm_mapped_extents;/* number of extents that were mapped (out) */ - __u32 fm_extent_count; /* size of fm_extents array (in) */ - __u32 fm_reserved; - struct ll_fiemap_extent fm_extents[0]; /* array of mapped extents (out) */ -}; - -#define FIEMAP_MAX_OFFSET (~0ULL) +#ifndef __KERNEL__ +#include +#include +#endif -#define FIEMAP_FLAG_SYNC 0x00000001 /* sync file data before - * map - */ -#define FIEMAP_FLAG_XATTR 0x00000002 /* map extended attribute - * tree - */ -#define FIEMAP_EXTENT_LAST 0x00000001 /* Last extent in file. */ -#define FIEMAP_EXTENT_UNKNOWN 0x00000002 /* Data location unknown. */ -#define FIEMAP_EXTENT_DELALLOC 0x00000004 /* Location still pending. - * Sets EXTENT_UNKNOWN. - */ -#define FIEMAP_EXTENT_ENCODED 0x00000008 /* Data can not be read - * while fs is unmounted - */ -#define FIEMAP_EXTENT_DATA_ENCRYPTED 0x00000080 /* Data is encrypted by fs. - * Sets EXTENT_NO_DIRECT. - */ -#define FIEMAP_EXTENT_NOT_ALIGNED 0x00000100 /* Extent offsets may not be - * block aligned. - */ -#define FIEMAP_EXTENT_DATA_INLINE 0x00000200 /* Data mixed with metadata. - * Sets EXTENT_NOT_ALIGNED.*/ -#define FIEMAP_EXTENT_DATA_TAIL 0x00000400 /* Multiple files in block. - * Sets EXTENT_NOT_ALIGNED. - */ -#define FIEMAP_EXTENT_UNWRITTEN 0x00000800 /* Space allocated, but - * no data (i.e. zero). - */ -#define FIEMAP_EXTENT_MERGED 0x00001000 /* File does not natively - * support extents. Result - * merged for efficiency. - */ +/* XXX: We use fiemap_extent::fe_reserved[0] */ +#define fe_device fe_reserved[0] static inline size_t fiemap_count_to_size(size_t extent_count) { - return (sizeof(struct ll_user_fiemap) + extent_count * - sizeof(struct ll_fiemap_extent)); + return sizeof(struct fiemap) + extent_count * + sizeof(struct fiemap_extent); } static inline unsigned fiemap_size_to_count(size_t array_size) { - return ((array_size - sizeof(struct ll_user_fiemap)) / - sizeof(struct ll_fiemap_extent)); + return (array_size - sizeof(struct fiemap)) / + sizeof(struct fiemap_extent); } #define FIEMAP_FLAG_DEVICE_ORDER 0x40000000 /* return device ordered mapping */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index d1645458fa76..42107165020c 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -3331,14 +3331,14 @@ struct ost_body { /* Key for FIEMAP to be used in get_info calls */ struct ll_fiemap_info_key { - char name[8]; - struct obdo oa; - struct ll_user_fiemap fiemap; + char lfik_name[8]; + struct obdo lfik_oa; + struct fiemap lfik_fiemap; }; void lustre_swab_ost_body(struct ost_body *b); void lustre_swab_ost_last_id(__u64 *id); -void lustre_swab_fiemap(struct ll_user_fiemap *fiemap); +void lustre_swab_fiemap(struct fiemap *fiemap); void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum); void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum); diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 6fc985571cba..dced31f48759 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -82,7 +82,6 @@ typedef struct stat lstat_t; #define FSFILT_IOC_SETVERSION _IOW('f', 4, long) #define FSFILT_IOC_GETVERSION_OLD _IOR('v', 1, long) #define FSFILT_IOC_SETVERSION_OLD _IOW('v', 2, long) -#define FSFILT_IOC_FIEMAP _IOWR('f', 11, struct ll_user_fiemap) #endif /* FIEMAP flags supported by Lustre */ diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 811eb8bcefdb..162b8103a454 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1506,15 +1506,17 @@ out: /** * Get size for inode for which FIEMAP mapping is requested. * Make the FIEMAP get_info call and returns the result. + * + * \param fiemap kernel buffer to hold extens + * \param num_bytes kernel buffer size */ -static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap, +static int ll_do_fiemap(struct inode *inode, struct fiemap *fiemap, size_t num_bytes) { - struct obd_export *exp = ll_i2dtexp(inode); - struct lov_stripe_md *lsm = NULL; - struct ll_fiemap_info_key fm_key = { .name = KEY_FIEMAP, }; - __u32 vallen = num_bytes; - int rc; + struct ll_fiemap_info_key fmkey = { .lfik_name = KEY_FIEMAP, }; + struct lu_env *env; + int refcheck; + int rc = 0; /* Checks for fiemap flags */ if (fiemap->fm_flags & ~LUSTRE_FIEMAP_FLAGS_COMPAT) { @@ -1529,21 +1531,9 @@ static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap, return rc; } - lsm = ccc_inode_lsm_get(inode); - if (!lsm) - return -ENOENT; - - /* If the stripe_count > 1 and the application does not understand - * DEVICE_ORDER flag, then it cannot interpret the extents correctly. - */ - if (lsm->lsm_stripe_count > 1 && - !(fiemap->fm_flags & FIEMAP_FLAG_DEVICE_ORDER)) { - rc = -EOPNOTSUPP; - goto out; - } - - fm_key.oa.o_oi = lsm->lsm_oi; - fm_key.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP; + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + return PTR_ERR(env); if (i_size_read(inode) == 0) { rc = ll_glimpse_size(inode); @@ -1551,24 +1541,23 @@ static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap, goto out; } - obdo_from_inode(&fm_key.oa, inode, OBD_MD_FLSIZE); - obdo_set_parent_fid(&fm_key.oa, &ll_i2info(inode)->lli_fid); + fmkey.lfik_oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP; + obdo_from_inode(&fmkey.lfik_oa, inode, OBD_MD_FLSIZE); + obdo_set_parent_fid(&fmkey.lfik_oa, &ll_i2info(inode)->lli_fid); + /* If filesize is 0, then there would be no objects for mapping */ - if (fm_key.oa.o_size == 0) { + if (fmkey.lfik_oa.o_size == 0) { fiemap->fm_mapped_extents = 0; rc = 0; goto out; } - memcpy(&fm_key.fiemap, fiemap, sizeof(*fiemap)); - - rc = obd_get_info(NULL, exp, sizeof(fm_key), &fm_key, &vallen, - fiemap, lsm); - if (rc) - CERROR("obd_get_info failed: rc = %d\n", rc); + memcpy(&fmkey.lfik_fiemap, fiemap, sizeof(*fiemap)); + rc = cl_object_fiemap(env, ll_i2info(inode)->lli_clob, + &fmkey, fiemap, &num_bytes); out: - ccc_inode_lsm_put(inode, lsm); + cl_env_put(env, &refcheck); return rc; } @@ -1616,68 +1605,6 @@ gf_free: return rc; } -static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg) -{ - struct ll_user_fiemap *fiemap_s; - size_t num_bytes, ret_bytes; - unsigned int extent_count; - int rc = 0; - - /* Get the extent count so we can calculate the size of - * required fiemap buffer - */ - if (get_user(extent_count, - &((struct ll_user_fiemap __user *)arg)->fm_extent_count)) - return -EFAULT; - - if (extent_count >= - (SIZE_MAX - sizeof(*fiemap_s)) / sizeof(struct ll_fiemap_extent)) - return -EINVAL; - num_bytes = sizeof(*fiemap_s) + (extent_count * - sizeof(struct ll_fiemap_extent)); - - fiemap_s = libcfs_kvzalloc(num_bytes, GFP_NOFS); - if (!fiemap_s) - return -ENOMEM; - - /* get the fiemap value */ - if (copy_from_user(fiemap_s, (struct ll_user_fiemap __user *)arg, - sizeof(*fiemap_s))) { - rc = -EFAULT; - goto error; - } - - /* If fm_extent_count is non-zero, read the first extent since - * it is used to calculate end_offset and device from previous - * fiemap call. - */ - if (extent_count) { - if (copy_from_user(&fiemap_s->fm_extents[0], - (char __user *)arg + sizeof(*fiemap_s), - sizeof(struct ll_fiemap_extent))) { - rc = -EFAULT; - goto error; - } - } - - rc = ll_do_fiemap(inode, fiemap_s, num_bytes); - if (rc) - goto error; - - ret_bytes = sizeof(struct ll_user_fiemap); - - if (extent_count != 0) - ret_bytes += (fiemap_s->fm_mapped_extents * - sizeof(struct ll_fiemap_extent)); - - if (copy_to_user((void __user *)arg, fiemap_s, ret_bytes)) - rc = -EFAULT; - -error: - kvfree(fiemap_s); - return rc; -} - /* * Read the data_version for inode. * @@ -2119,8 +2046,6 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_LOV_GETSTRIPE: return ll_file_getstripe(inode, (struct lov_user_md __user *)arg); - case FSFILT_IOC_FIEMAP: - return ll_ioctl_fiemap(inode, arg); case FSFILT_IOC_GETFLAGS: case FSFILT_IOC_SETFLAGS: return ll_iocontrol(inode, file, cmd, arg); @@ -3022,13 +2947,12 @@ static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, { int rc; size_t num_bytes; - struct ll_user_fiemap *fiemap; + struct fiemap *fiemap; unsigned int extent_count = fieinfo->fi_extents_max; num_bytes = sizeof(*fiemap) + (extent_count * - sizeof(struct ll_fiemap_extent)); + sizeof(struct fiemap_extent)); fiemap = libcfs_kvzalloc(num_bytes, GFP_NOFS); - if (!fiemap) return -ENOMEM; @@ -3036,9 +2960,10 @@ static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, fiemap->fm_extent_count = fieinfo->fi_extents_max; fiemap->fm_start = start; fiemap->fm_length = len; + if (extent_count > 0 && copy_from_user(&fiemap->fm_extents[0], fieinfo->fi_extents_start, - sizeof(struct ll_fiemap_extent)) != 0) { + sizeof(struct fiemap_extent))) { rc = -EFAULT; goto out; } @@ -3050,11 +2975,10 @@ static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, if (extent_count > 0 && copy_to_user(fieinfo->fi_extents_start, &fiemap->fm_extents[0], fiemap->fm_mapped_extents * - sizeof(struct ll_fiemap_extent)) != 0) { + sizeof(struct fiemap_extent))) { rc = -EFAULT; goto out; } - out: kvfree(fiemap); return rc; diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index b23016f7ec26..02c7087df710 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -51,7 +51,6 @@ #include "../include/lprocfs_status.h" #include "../include/lustre_param.h" #include "../include/cl_object.h" -#include "../include/lustre/ll_fiemap.h" #include "../include/lustre_fid.h" #include "lov_internal.h" @@ -1391,423 +1390,6 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, return rc; } -#define FIEMAP_BUFFER_SIZE 4096 - -/** - * Non-zero fe_logical indicates that this is a continuation FIEMAP - * call. The local end offset and the device are sent in the first - * fm_extent. This function calculates the stripe number from the index. - * This function returns a stripe_no on which mapping is to be restarted. - * - * This function returns fm_end_offset which is the in-OST offset at which - * mapping should be restarted. If fm_end_offset=0 is returned then caller - * will re-calculate proper offset in next stripe. - * Note that the first extent is passed to lov_get_info via the value field. - * - * \param fiemap fiemap request header - * \param lsm striping information for the file - * \param fm_start logical start of mapping - * \param fm_end logical end of mapping - * \param start_stripe starting stripe will be returned in this - */ -static u64 fiemap_calc_fm_end_offset(struct ll_user_fiemap *fiemap, - struct lov_stripe_md *lsm, u64 fm_start, - u64 fm_end, int *start_stripe) -{ - u64 local_end = fiemap->fm_extents[0].fe_logical; - u64 lun_start, lun_end; - u64 fm_end_offset; - int stripe_no = -1, i; - - if (fiemap->fm_extent_count == 0 || - fiemap->fm_extents[0].fe_logical == 0) - return 0; - - /* Find out stripe_no from ost_index saved in the fe_device */ - for (i = 0; i < lsm->lsm_stripe_count; i++) { - struct lov_oinfo *oinfo = lsm->lsm_oinfo[i]; - - if (lov_oinfo_is_dummy(oinfo)) - continue; - - if (oinfo->loi_ost_idx == fiemap->fm_extents[0].fe_device) { - stripe_no = i; - break; - } - } - if (stripe_no == -1) - return -EINVAL; - - /* If we have finished mapping on previous device, shift logical - * offset to start of next device - */ - if ((lov_stripe_intersects(lsm, stripe_no, fm_start, fm_end, - &lun_start, &lun_end)) != 0 && - local_end < lun_end) { - fm_end_offset = local_end; - *start_stripe = stripe_no; - } else { - /* This is a special value to indicate that caller should - * calculate offset in next stripe. - */ - fm_end_offset = 0; - *start_stripe = (stripe_no + 1) % lsm->lsm_stripe_count; - } - - return fm_end_offset; -} - -/** - * We calculate on which OST the mapping will end. If the length of mapping - * is greater than (stripe_size * stripe_count) then the last_stripe will - * will be one just before start_stripe. Else we check if the mapping - * intersects each OST and find last_stripe. - * This function returns the last_stripe and also sets the stripe_count - * over which the mapping is spread - * - * \param lsm striping information for the file - * \param fm_start logical start of mapping - * \param fm_end logical end of mapping - * \param start_stripe starting stripe of the mapping - * \param stripe_count the number of stripes across which to map is returned - * - * \retval last_stripe return the last stripe of the mapping - */ -static int fiemap_calc_last_stripe(struct lov_stripe_md *lsm, u64 fm_start, - u64 fm_end, int start_stripe, - int *stripe_count) -{ - int last_stripe; - u64 obd_start, obd_end; - int i, j; - - if (fm_end - fm_start > lsm->lsm_stripe_size * lsm->lsm_stripe_count) { - last_stripe = start_stripe < 1 ? lsm->lsm_stripe_count - 1 : - start_stripe - 1; - *stripe_count = lsm->lsm_stripe_count; - } else { - for (j = 0, i = start_stripe; j < lsm->lsm_stripe_count; - i = (i + 1) % lsm->lsm_stripe_count, j++) { - if ((lov_stripe_intersects(lsm, i, fm_start, fm_end, - &obd_start, &obd_end)) == 0) - break; - } - *stripe_count = j; - last_stripe = (start_stripe + j - 1) % lsm->lsm_stripe_count; - } - - return last_stripe; -} - -/** - * Set fe_device and copy extents from local buffer into main return buffer. - * - * \param fiemap fiemap request header - * \param lcl_fm_ext array of local fiemap extents to be copied - * \param ost_index OST index to be written into the fm_device field for each - extent - * \param ext_count number of extents to be copied - * \param current_extent where to start copying in main extent array - */ -static void fiemap_prepare_and_copy_exts(struct ll_user_fiemap *fiemap, - struct ll_fiemap_extent *lcl_fm_ext, - int ost_index, unsigned int ext_count, - int current_extent) -{ - char *to; - int ext; - - for (ext = 0; ext < ext_count; ext++) { - lcl_fm_ext[ext].fe_device = ost_index; - lcl_fm_ext[ext].fe_flags |= FIEMAP_EXTENT_NET; - } - - /* Copy fm_extent's from fm_local to return buffer */ - to = (char *)fiemap + fiemap_count_to_size(current_extent); - memcpy(to, lcl_fm_ext, ext_count * sizeof(struct ll_fiemap_extent)); -} - -/** - * Break down the FIEMAP request and send appropriate calls to individual OSTs. - * This also handles the restarting of FIEMAP calls in case mapping overflows - * the available number of extents in single call. - */ -static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, - __u32 *vallen, void *val, struct lov_stripe_md *lsm) -{ - struct ll_fiemap_info_key *fm_key = key; - struct ll_user_fiemap *fiemap = val; - struct ll_user_fiemap *fm_local = NULL; - struct ll_fiemap_extent *lcl_fm_ext; - int count_local; - unsigned int get_num_extents = 0; - int ost_index = 0, actual_start_stripe, start_stripe; - u64 fm_start, fm_end, fm_length, fm_end_offset; - u64 curr_loc; - int current_extent = 0, rc = 0, i; - /* Whether have we collected enough extents */ - bool enough = false; - int ost_eof = 0; /* EOF for object */ - int ost_done = 0; /* done with required mapping for this OST? */ - int last_stripe; - int cur_stripe = 0, cur_stripe_wrap = 0, stripe_count; - unsigned int buffer_size = FIEMAP_BUFFER_SIZE; - - if (!lsm_has_objects(lsm)) { - if (lsm && lsm_is_released(lsm) && (fm_key->fiemap.fm_start < - fm_key->oa.o_size)) { - /* - * released file, return a minimal FIEMAP if - * request fits in file-size. - */ - fiemap->fm_mapped_extents = 1; - fiemap->fm_extents[0].fe_logical = - fm_key->fiemap.fm_start; - if (fm_key->fiemap.fm_start + fm_key->fiemap.fm_length < - fm_key->oa.o_size) { - fiemap->fm_extents[0].fe_length = - fm_key->fiemap.fm_length; - } else { - fiemap->fm_extents[0].fe_length = - fm_key->oa.o_size - fm_key->fiemap.fm_start; - fiemap->fm_extents[0].fe_flags |= - (FIEMAP_EXTENT_UNKNOWN | - FIEMAP_EXTENT_LAST); - } - } - rc = 0; - goto out; - } - - if (fiemap_count_to_size(fm_key->fiemap.fm_extent_count) < buffer_size) - buffer_size = fiemap_count_to_size(fm_key->fiemap.fm_extent_count); - - fm_local = libcfs_kvzalloc(buffer_size, GFP_NOFS); - if (!fm_local) { - rc = -ENOMEM; - goto out; - } - lcl_fm_ext = &fm_local->fm_extents[0]; - - count_local = fiemap_size_to_count(buffer_size); - - memcpy(fiemap, &fm_key->fiemap, sizeof(*fiemap)); - fm_start = fiemap->fm_start; - fm_length = fiemap->fm_length; - /* Calculate start stripe, last stripe and length of mapping */ - start_stripe = lov_stripe_number(lsm, fm_start); - actual_start_stripe = start_stripe; - fm_end = (fm_length == ~0ULL ? fm_key->oa.o_size : - fm_start + fm_length - 1); - /* If fm_length != ~0ULL but fm_start+fm_length-1 exceeds file size */ - if (fm_end > fm_key->oa.o_size) - fm_end = fm_key->oa.o_size; - - last_stripe = fiemap_calc_last_stripe(lsm, fm_start, fm_end, - actual_start_stripe, - &stripe_count); - - fm_end_offset = fiemap_calc_fm_end_offset(fiemap, lsm, fm_start, - fm_end, &start_stripe); - if (fm_end_offset == -EINVAL) { - rc = -EINVAL; - goto out; - } - - if (fiemap_count_to_size(fiemap->fm_extent_count) > *vallen) - fiemap->fm_extent_count = fiemap_size_to_count(*vallen); - if (fiemap->fm_extent_count == 0) { - get_num_extents = 1; - count_local = 0; - } - /* Check each stripe */ - for (cur_stripe = start_stripe, i = 0; i < stripe_count; - i++, cur_stripe = (cur_stripe + 1) % lsm->lsm_stripe_count) { - u64 req_fm_len; /* Stores length of required mapping */ - u64 len_mapped_single_call; - u64 lun_start, lun_end, obd_object_end; - unsigned int ext_count; - - cur_stripe_wrap = cur_stripe; - - /* Find out range of mapping on this stripe */ - if ((lov_stripe_intersects(lsm, cur_stripe, fm_start, fm_end, - &lun_start, &obd_object_end)) == 0) - continue; - - if (lov_oinfo_is_dummy(lsm->lsm_oinfo[cur_stripe])) { - rc = -EIO; - goto out; - } - - /* If this is a continuation FIEMAP call and we are on - * starting stripe then lun_start needs to be set to - * fm_end_offset - */ - if (fm_end_offset != 0 && cur_stripe == start_stripe) - lun_start = fm_end_offset; - - if (fm_length != ~0ULL) { - /* Handle fm_start + fm_length overflow */ - if (fm_start + fm_length < fm_start) - fm_length = ~0ULL - fm_start; - lun_end = lov_size_to_stripe(lsm, fm_start + fm_length, - cur_stripe); - } else { - lun_end = ~0ULL; - } - - if (lun_start == lun_end) - continue; - - req_fm_len = obd_object_end - lun_start; - fm_local->fm_length = 0; - len_mapped_single_call = 0; - - /* If the output buffer is very large and the objects have many - * extents we may need to loop on a single OST repeatedly - */ - ost_eof = 0; - ost_done = 0; - do { - if (get_num_extents == 0) { - /* Don't get too many extents. */ - if (current_extent + count_local > - fiemap->fm_extent_count) - count_local = fiemap->fm_extent_count - - current_extent; - } - - lun_start += len_mapped_single_call; - fm_local->fm_length = req_fm_len - len_mapped_single_call; - req_fm_len = fm_local->fm_length; - fm_local->fm_extent_count = enough ? 1 : count_local; - fm_local->fm_mapped_extents = 0; - fm_local->fm_flags = fiemap->fm_flags; - - fm_key->oa.o_oi = lsm->lsm_oinfo[cur_stripe]->loi_oi; - ost_index = lsm->lsm_oinfo[cur_stripe]->loi_ost_idx; - - if (ost_index < 0 || - ost_index >= lov->desc.ld_tgt_count) { - rc = -EINVAL; - goto out; - } - - /* If OST is inactive, return extent with UNKNOWN flag */ - if (!lov->lov_tgts[ost_index]->ltd_active) { - fm_local->fm_flags |= FIEMAP_EXTENT_LAST; - fm_local->fm_mapped_extents = 1; - - lcl_fm_ext[0].fe_logical = lun_start; - lcl_fm_ext[0].fe_length = obd_object_end - - lun_start; - lcl_fm_ext[0].fe_flags |= FIEMAP_EXTENT_UNKNOWN; - - goto inactive_tgt; - } - - fm_local->fm_start = lun_start; - fm_local->fm_flags &= ~FIEMAP_FLAG_DEVICE_ORDER; - memcpy(&fm_key->fiemap, fm_local, sizeof(*fm_local)); - *vallen = fiemap_count_to_size(fm_local->fm_extent_count); - rc = obd_get_info(NULL, - lov->lov_tgts[ost_index]->ltd_exp, - keylen, key, vallen, fm_local, lsm); - if (rc != 0) - goto out; - -inactive_tgt: - ext_count = fm_local->fm_mapped_extents; - if (ext_count == 0) { - ost_done = 1; - /* If last stripe has hole at the end, - * then we need to return - */ - if (cur_stripe_wrap == last_stripe) { - fiemap->fm_mapped_extents = 0; - goto finish; - } - break; - } else if (enough) { - /* - * We've collected enough extents and there are - * more extents after it. - */ - goto finish; - } - - /* If we just need num of extents then go to next device */ - if (get_num_extents) { - current_extent += ext_count; - break; - } - - len_mapped_single_call = - lcl_fm_ext[ext_count - 1].fe_logical - - lun_start + lcl_fm_ext[ext_count - 1].fe_length; - - /* Have we finished mapping on this device? */ - if (req_fm_len <= len_mapped_single_call) - ost_done = 1; - - /* Clear the EXTENT_LAST flag which can be present on - * last extent - */ - if (lcl_fm_ext[ext_count - 1].fe_flags & - FIEMAP_EXTENT_LAST) - lcl_fm_ext[ext_count - 1].fe_flags &= - ~FIEMAP_EXTENT_LAST; - - curr_loc = lov_stripe_size(lsm, - lcl_fm_ext[ext_count - 1].fe_logical + - lcl_fm_ext[ext_count - 1].fe_length, - cur_stripe); - if (curr_loc >= fm_key->oa.o_size) - ost_eof = 1; - - fiemap_prepare_and_copy_exts(fiemap, lcl_fm_ext, - ost_index, ext_count, - current_extent); - - current_extent += ext_count; - - /* Ran out of available extents? */ - if (current_extent >= fiemap->fm_extent_count) - enough = true; - } while (ost_done == 0 && ost_eof == 0); - - if (cur_stripe_wrap == last_stripe) - goto finish; - } - -finish: - /* Indicate that we are returning device offsets unless file just has - * single stripe - */ - if (lsm->lsm_stripe_count > 1) - fiemap->fm_flags |= FIEMAP_FLAG_DEVICE_ORDER; - - if (get_num_extents) - goto skip_last_device_calc; - - /* Check if we have reached the last stripe and whether mapping for that - * stripe is done. - */ - if (cur_stripe_wrap == last_stripe) { - if (ost_done || ost_eof) - fiemap->fm_extents[current_extent - 1].fe_flags |= - FIEMAP_EXTENT_LAST; - } - -skip_last_device_calc: - fiemap->fm_mapped_extents = current_extent; - -out: - kvfree(fm_local); - return rc; -} - static int lov_get_info(const struct lu_env *env, struct obd_export *exp, __u32 keylen, void *key, __u32 *vallen, void *val, struct lov_stripe_md *lsm) @@ -1827,9 +1409,6 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp, rc = 0; goto out; - } else if (KEY_IS(KEY_FIEMAP)) { - rc = lov_fiemap(lov, keylen, key, vallen, val, lsm); - goto out; } else if (KEY_IS(KEY_TGT_COUNT)) { *((int *)val) = lov->desc.ld_tgt_count; rc = 0; diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 52f736338887..07bef44c7439 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -313,6 +313,40 @@ static int lov_init_released(const struct lu_env *env, return 0; } +static struct cl_object *lov_find_subobj(const struct lu_env *env, + struct lov_object *lov, + struct lov_stripe_md *lsm, + int stripe_idx) +{ + struct lov_device *dev = lu2lov_dev(lov2lu(lov)->lo_dev); + struct lov_oinfo *oinfo = lsm->lsm_oinfo[stripe_idx]; + struct lov_thread_info *lti = lov_env_info(env); + struct lu_fid *ofid = <i->lti_fid; + struct cl_device *subdev; + struct cl_object *result; + int ost_idx; + int rc; + + if (lov->lo_type != LLT_RAID0) { + result = NULL; + goto out; + } + + ost_idx = oinfo->loi_ost_idx; + rc = ostid_to_fid(ofid, &oinfo->loi_oi, ost_idx); + if (rc) { + result = NULL; + goto out; + } + + subdev = lovsub2cl_dev(dev->ld_target[ost_idx]); + result = lov_sub_find(env, subdev, ofid, NULL); +out: + if (!result) + result = ERR_PTR(-EINVAL); + return result; +} + static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov, union lov_layout_state *state) { @@ -911,6 +945,473 @@ int lov_lock_init(const struct lu_env *env, struct cl_object *obj, io); } +/** + * We calculate on which OST the mapping will end. If the length of mapping + * is greater than (stripe_size * stripe_count) then the last_stripe will + * will be one just before start_stripe. Else we check if the mapping + * intersects each OST and find last_stripe. + * This function returns the last_stripe and also sets the stripe_count + * over which the mapping is spread + * + * \param lsm [in] striping information for the file + * \param fm_start [in] logical start of mapping + * \param fm_end [in] logical end of mapping + * \param start_stripe [in] starting stripe of the mapping + * \param stripe_count [out] the number of stripes across which to map is + * returned + * + * \retval last_stripe return the last stripe of the mapping + */ +static int fiemap_calc_last_stripe(struct lov_stripe_md *lsm, + loff_t fm_start, loff_t fm_end, + int start_stripe, int *stripe_count) +{ + int last_stripe; + loff_t obd_start; + loff_t obd_end; + int i, j; + + if (fm_end - fm_start > lsm->lsm_stripe_size * lsm->lsm_stripe_count) { + last_stripe = (start_stripe < 1 ? lsm->lsm_stripe_count - 1 : + start_stripe - 1); + *stripe_count = lsm->lsm_stripe_count; + } else { + for (j = 0, i = start_stripe; j < lsm->lsm_stripe_count; + i = (i + 1) % lsm->lsm_stripe_count, j++) { + if (!(lov_stripe_intersects(lsm, i, fm_start, fm_end, + &obd_start, &obd_end))) + break; + } + *stripe_count = j; + last_stripe = (start_stripe + j - 1) % lsm->lsm_stripe_count; + } + + return last_stripe; +} + +/** + * Set fe_device and copy extents from local buffer into main return buffer. + * + * \param fiemap [out] fiemap to hold all extents + * \param lcl_fm_ext [in] array of fiemap extents get from OSC layer + * \param ost_index [in] OST index to be written into the fm_device + * field for each extent + * \param ext_count [in] number of extents to be copied + * \param current_extent [in] where to start copying in the extent array + */ +static void fiemap_prepare_and_copy_exts(struct fiemap *fiemap, + struct fiemap_extent *lcl_fm_ext, + int ost_index, unsigned int ext_count, + int current_extent) +{ + unsigned int ext; + char *to; + + for (ext = 0; ext < ext_count; ext++) { + lcl_fm_ext[ext].fe_device = ost_index; + lcl_fm_ext[ext].fe_flags |= FIEMAP_EXTENT_NET; + } + + /* Copy fm_extent's from fm_local to return buffer */ + to = (char *)fiemap + fiemap_count_to_size(current_extent); + memcpy(to, lcl_fm_ext, ext_count * sizeof(struct fiemap_extent)); +} + +#define FIEMAP_BUFFER_SIZE 4096 + +/** + * Non-zero fe_logical indicates that this is a continuation FIEMAP + * call. The local end offset and the device are sent in the first + * fm_extent. This function calculates the stripe number from the index. + * This function returns a stripe_no on which mapping is to be restarted. + * + * This function returns fm_end_offset which is the in-OST offset at which + * mapping should be restarted. If fm_end_offset=0 is returned then caller + * will re-calculate proper offset in next stripe. + * Note that the first extent is passed to lov_get_info via the value field. + * + * \param fiemap [in] fiemap request header + * \param lsm [in] striping information for the file + * \param fm_start [in] logical start of mapping + * \param fm_end [in] logical end of mapping + * \param start_stripe [out] starting stripe will be returned in this + */ +static loff_t fiemap_calc_fm_end_offset(struct fiemap *fiemap, + struct lov_stripe_md *lsm, + loff_t fm_start, loff_t fm_end, + int *start_stripe) +{ + loff_t local_end = fiemap->fm_extents[0].fe_logical; + loff_t lun_start, lun_end; + loff_t fm_end_offset; + int stripe_no = -1; + int i; + + if (!fiemap->fm_extent_count || !fiemap->fm_extents[0].fe_logical) + return 0; + + /* Find out stripe_no from ost_index saved in the fe_device */ + for (i = 0; i < lsm->lsm_stripe_count; i++) { + struct lov_oinfo *oinfo = lsm->lsm_oinfo[i]; + + if (lov_oinfo_is_dummy(oinfo)) + continue; + + if (oinfo->loi_ost_idx == fiemap->fm_extents[0].fe_device) { + stripe_no = i; + break; + } + } + + if (stripe_no == -1) + return -EINVAL; + + /* + * If we have finished mapping on previous device, shift logical + * offset to start of next device + */ + if (lov_stripe_intersects(lsm, stripe_no, fm_start, fm_end, + &lun_start, &lun_end) && + local_end < lun_end) { + fm_end_offset = local_end; + *start_stripe = stripe_no; + } else { + /* This is a special value to indicate that caller should + * calculate offset in next stripe. + */ + fm_end_offset = 0; + *start_stripe = (stripe_no + 1) % lsm->lsm_stripe_count; + } + + return fm_end_offset; +} + +/** + * Break down the FIEMAP request and send appropriate calls to individual OSTs. + * This also handles the restarting of FIEMAP calls in case mapping overflows + * the available number of extents in single call. + * + * \param env [in] lustre environment + * \param obj [in] file object + * \param fmkey [in] fiemap request header and other info + * \param fiemap [out] fiemap buffer holding retrived map extents + * \param buflen [in/out] max buffer length of @fiemap, when iterate + * each OST, it is used to limit max map needed + * \retval 0 success + * \retval < 0 error + */ +static int lov_object_fiemap(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *fmkey, + struct fiemap *fiemap, size_t *buflen) +{ + struct lov_obd *lov = lu2lov_dev(obj->co_lu.lo_dev)->ld_lov; + unsigned int buffer_size = FIEMAP_BUFFER_SIZE; + struct fiemap_extent *lcl_fm_ext; + struct cl_object *subobj = NULL; + struct fiemap *fm_local = NULL; + struct lov_stripe_md *lsm; + loff_t fm_start; + loff_t fm_end; + loff_t fm_length; + loff_t fm_end_offset; + int count_local; + int ost_index = 0; + int start_stripe; + int current_extent = 0; + int rc = 0; + int last_stripe; + int cur_stripe = 0; + int cur_stripe_wrap = 0; + int stripe_count; + /* Whether have we collected enough extents */ + bool enough = false; + /* EOF for object */ + bool ost_eof = false; + /* done with required mapping for this OST? */ + bool ost_done = false; + + lsm = lov_lsm_addref(cl2lov(obj)); + if (!lsm) + return -ENODATA; + + /** + * If the stripe_count > 1 and the application does not understand + * DEVICE_ORDER flag, it cannot interpret the extents correctly. + */ + if (lsm->lsm_stripe_count > 1 && + !(fiemap->fm_flags & FIEMAP_FLAG_DEVICE_ORDER)) { + rc = -ENOTSUPP; + goto out; + } + + if (lsm_is_released(lsm)) { + if (fiemap->fm_start < fmkey->lfik_oa.o_size) { + /** + * released file, return a minimal FIEMAP if + * request fits in file-size. + */ + fiemap->fm_mapped_extents = 1; + fiemap->fm_extents[0].fe_logical = fiemap->fm_start; + if (fiemap->fm_start + fiemap->fm_length < + fmkey->lfik_oa.o_size) + fiemap->fm_extents[0].fe_length = + fiemap->fm_length; + else + fiemap->fm_extents[0].fe_length = + fmkey->lfik_oa.o_size - + fiemap->fm_start; + fiemap->fm_extents[0].fe_flags |= + FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_LAST; + } + rc = 0; + goto out; + } + + if (fiemap_count_to_size(fiemap->fm_extent_count) < buffer_size) + buffer_size = fiemap_count_to_size(fiemap->fm_extent_count); + + fm_local = libcfs_kvzalloc(buffer_size, GFP_NOFS); + if (!fm_local) { + rc = -ENOMEM; + goto out; + } + lcl_fm_ext = &fm_local->fm_extents[0]; + count_local = fiemap_size_to_count(buffer_size); + + fm_start = fiemap->fm_start; + fm_length = fiemap->fm_length; + /* Calculate start stripe, last stripe and length of mapping */ + start_stripe = lov_stripe_number(lsm, fm_start); + fm_end = (fm_length == ~0ULL) ? fmkey->lfik_oa.o_size : + fm_start + fm_length - 1; + /* If fm_length != ~0ULL but fm_start_fm_length-1 exceeds file size */ + if (fm_end > fmkey->lfik_oa.o_size) + fm_end = fmkey->lfik_oa.o_size; + + last_stripe = fiemap_calc_last_stripe(lsm, fm_start, fm_end, + start_stripe, &stripe_count); + fm_end_offset = fiemap_calc_fm_end_offset(fiemap, lsm, fm_start, fm_end, + &start_stripe); + if (fm_end_offset == -EINVAL) { + rc = -EINVAL; + goto out; + } + + /** + * Requested extent count exceeds the fiemap buffer size, shrink our + * ambition. + */ + if (fiemap_count_to_size(fiemap->fm_extent_count) > *buflen) + fiemap->fm_extent_count = fiemap_size_to_count(*buflen); + if (!fiemap->fm_extent_count) + count_local = 0; + + /* Check each stripe */ + for (cur_stripe = start_stripe; stripe_count > 0; + --stripe_count, + cur_stripe = (cur_stripe + 1) % lsm->lsm_stripe_count) { + loff_t req_fm_len; /* Stores length of required mapping */ + loff_t len_mapped_single_call; + loff_t lun_start; + loff_t lun_end; + loff_t obd_object_end; + unsigned int ext_count; + + cur_stripe_wrap = cur_stripe; + + /* Find out range of mapping on this stripe */ + if (!(lov_stripe_intersects(lsm, cur_stripe, fm_start, fm_end, + &lun_start, &obd_object_end))) + continue; + + if (lov_oinfo_is_dummy(lsm->lsm_oinfo[cur_stripe])) { + rc = -EIO; + goto out; + } + + /* + * If this is a continuation FIEMAP call and we are on + * starting stripe then lun_start needs to be set to + * fm_end_offset + */ + if (fm_end_offset && cur_stripe == start_stripe) + lun_start = fm_end_offset; + + if (fm_length != ~0ULL) { + /* Handle fm_start + fm_length overflow */ + if (fm_start + fm_length < fm_start) + fm_length = ~0ULL - fm_start; + lun_end = lov_size_to_stripe(lsm, fm_start + fm_length, + cur_stripe); + } else { + lun_end = ~0ULL; + } + + if (lun_start == lun_end) + continue; + + req_fm_len = obd_object_end - lun_start; + fm_local->fm_length = 0; + len_mapped_single_call = 0; + + /* find lobsub object */ + subobj = lov_find_subobj(env, cl2lov(obj), lsm, + cur_stripe); + if (IS_ERR(subobj)) { + rc = PTR_ERR(subobj); + goto out; + } + /* + * If the output buffer is very large and the objects have many + * extents we may need to loop on a single OST repeatedly + */ + ost_eof = false; + ost_done = false; + do { + if (fiemap->fm_extent_count > 0) { + /* Don't get too many extents. */ + if (current_extent + count_local > + fiemap->fm_extent_count) + count_local = fiemap->fm_extent_count - + current_extent; + } + + lun_start += len_mapped_single_call; + fm_local->fm_length = req_fm_len - + len_mapped_single_call; + req_fm_len = fm_local->fm_length; + fm_local->fm_extent_count = enough ? 1 : count_local; + fm_local->fm_mapped_extents = 0; + fm_local->fm_flags = fiemap->fm_flags; + + ost_index = lsm->lsm_oinfo[cur_stripe]->loi_ost_idx; + + if (ost_index < 0 || + ost_index >= lov->desc.ld_tgt_count) { + rc = -EINVAL; + goto obj_put; + } + /* + * If OST is inactive, return extent with UNKNOWN + * flag. + */ + if (!lov->lov_tgts[ost_index]->ltd_active) { + fm_local->fm_flags |= FIEMAP_EXTENT_LAST; + fm_local->fm_mapped_extents = 1; + + lcl_fm_ext[0].fe_logical = lun_start; + lcl_fm_ext[0].fe_length = obd_object_end - + lun_start; + lcl_fm_ext[0].fe_flags |= FIEMAP_EXTENT_UNKNOWN; + + goto inactive_tgt; + } + + fm_local->fm_start = lun_start; + fm_local->fm_flags &= ~FIEMAP_FLAG_DEVICE_ORDER; + memcpy(&fmkey->lfik_fiemap, fm_local, sizeof(*fm_local)); + *buflen = fiemap_count_to_size(fm_local->fm_extent_count); + + rc = cl_object_fiemap(env, subobj, fmkey, fm_local, + buflen); + if (rc) + goto obj_put; +inactive_tgt: + ext_count = fm_local->fm_mapped_extents; + if (!ext_count) { + ost_done = true; + /* + * If last stripe has hold at the end, + * we need to return + */ + if (cur_stripe_wrap == last_stripe) { + fiemap->fm_mapped_extents = 0; + goto finish; + } + break; + } else if (enough) { + /* + * We've collected enough extents and there are + * more extents after it. + */ + goto finish; + } + + /* If we just need num of extents, got to next device */ + if (!fiemap->fm_extent_count) { + current_extent += ext_count; + break; + } + + /* prepare to copy retrived map extents */ + len_mapped_single_call = + lcl_fm_ext[ext_count - 1].fe_logical - + lun_start + lcl_fm_ext[ext_count - 1].fe_length; + + /* Have we finished mapping on this device? */ + if (req_fm_len <= len_mapped_single_call) + ost_done = true; + + /* + * Clear the EXTENT_LAST flag which can be present on + * the last extent + */ + if (lcl_fm_ext[ext_count - 1].fe_flags & + FIEMAP_EXTENT_LAST) + lcl_fm_ext[ext_count - 1].fe_flags &= + ~FIEMAP_EXTENT_LAST; + + if (lov_stripe_size(lsm, + lcl_fm_ext[ext_count - 1].fe_logical + + lcl_fm_ext[ext_count - 1].fe_length, + cur_stripe) >= fmkey->lfik_oa.o_size) + ost_eof = true; + + fiemap_prepare_and_copy_exts(fiemap, lcl_fm_ext, + ost_index, ext_count, + current_extent); + current_extent += ext_count; + + /* Ran out of available extents? */ + if (current_extent >= fiemap->fm_extent_count) + enough = true; + } while (!ost_done && !ost_eof); + + cl_object_put(env, subobj); + subobj = NULL; + + if (cur_stripe_wrap == last_stripe) + goto finish; + } /* for each stripe */ +finish: + /* + * Indicate that we are returning device offsets unless file just has + * single stripe + */ + if (lsm->lsm_stripe_count > 1) + fiemap->fm_flags |= FIEMAP_FLAG_DEVICE_ORDER; + + if (!fiemap->fm_extent_count) + goto skip_last_device_calc; + + /* + * Check if we have reached the last stripe and whether mapping for that + * stripe is done. + */ + if ((cur_stripe_wrap == last_stripe) && (ost_done || ost_eof)) + fiemap->fm_extents[current_extent - 1].fe_flags |= + FIEMAP_EXTENT_LAST; +skip_last_device_calc: + fiemap->fm_mapped_extents = current_extent; +obj_put: + if (subobj) + cl_object_put(env, subobj); +out: + kvfree(fm_local); + lov_lsm_put(obj, lsm); + return rc; +} + static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj, struct lov_user_md __user *lum) { @@ -934,7 +1435,8 @@ static const struct cl_object_operations lov_ops = { .coo_attr_get = lov_attr_get, .coo_attr_update = lov_attr_update, .coo_conf_set = lov_conf_set, - .coo_getstripe = lov_object_getstripe + .coo_getstripe = lov_object_getstripe, + .coo_fiemap = lov_object_fiemap, }; static const struct lu_object_operations lov_lu_obj_ops = { diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 3199dd4a3b72..4ad2ee5719ca 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -342,6 +342,38 @@ int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, } EXPORT_SYMBOL(cl_object_getstripe); +/** + * Get fiemap extents from file object. + * + * \param env [in] lustre environment + * \param obj [in] file object + * \param key [in] fiemap request argument + * \param fiemap [out] fiemap extents mapping retrived + * \param buflen [in] max buffer length of @fiemap + * + * \retval 0 success + * \retval < 0 error + */ +int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *key, + struct fiemap *fiemap, size_t *buflen) +{ + struct lu_object_header *top; + int result = 0; + + top = obj->co_lu.lo_header; + list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) { + if (obj->co_ops->coo_fiemap) { + result = obj->co_ops->coo_fiemap(env, obj, key, fiemap, + buflen); + if (result) + break; + } + } + return result; +} +EXPORT_SYMBOL(cl_object_fiemap); + /** * Helper function removing all object locks, and marking object for * deletion. All object pages must have been deleted at this point. diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c index aae3a2d4243f..dc0c17300cd4 100644 --- a/drivers/staging/lustre/lustre/osc/osc_object.c +++ b/drivers/staging/lustre/lustre/osc/osc_object.c @@ -218,6 +218,94 @@ static int osc_object_prune(const struct lu_env *env, struct cl_object *obj) return 0; } +static int osc_object_fiemap(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *fmkey, + struct fiemap *fiemap, size_t *buflen) +{ + struct obd_export *exp = osc_export(cl2osc(obj)); + ldlm_policy_data_t policy; + struct ptlrpc_request *req; + struct lustre_handle lockh; + struct ldlm_res_id resid; + enum ldlm_mode mode = 0; + struct fiemap *reply; + char *tmp; + int rc; + + fmkey->lfik_oa.o_oi = cl2osc(obj)->oo_oinfo->loi_oi; + if (!(fmkey->lfik_fiemap.fm_flags & FIEMAP_FLAG_SYNC)) + goto skip_locking; + + policy.l_extent.start = fmkey->lfik_fiemap.fm_start & PAGE_MASK; + + if (OBD_OBJECT_EOF - fmkey->lfik_fiemap.fm_length <= + fmkey->lfik_fiemap.fm_start + PAGE_SIZE - 1) + policy.l_extent.end = OBD_OBJECT_EOF; + else + policy.l_extent.end = (fmkey->lfik_fiemap.fm_start + + fmkey->lfik_fiemap.fm_length + + PAGE_SIZE - 1) & PAGE_MASK; + + ostid_build_res_name(&fmkey->lfik_oa.o_oi, &resid); + mode = ldlm_lock_match(exp->exp_obd->obd_namespace, + LDLM_FL_BLOCK_GRANTED | LDLM_FL_LVB_READY, + &resid, LDLM_EXTENT, &policy, + LCK_PR | LCK_PW, &lockh, 0); + if (mode) { /* lock is cached on client */ + if (mode != LCK_PR) { + ldlm_lock_addref(&lockh, LCK_PR); + ldlm_lock_decref(&lockh, LCK_PW); + } + } else { /* no cached lock, needs acquire lock on server side */ + fmkey->lfik_oa.o_valid |= OBD_MD_FLFLAGS; + fmkey->lfik_oa.o_flags |= OBD_FL_SRVLOCK; + } + +skip_locking: + req = ptlrpc_request_alloc(class_exp2cliimp(exp), + &RQF_OST_GET_INFO_FIEMAP); + if (!req) { + rc = -ENOMEM; + goto drop_lock; + } + + req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_KEY, RCL_CLIENT, + sizeof(*fmkey)); + req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, RCL_CLIENT, + *buflen); + req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, RCL_SERVER, + *buflen); + + rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO); + if (rc) { + ptlrpc_request_free(req); + goto drop_lock; + } + tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_KEY); + memcpy(tmp, fmkey, sizeof(*fmkey)); + tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_VAL); + memcpy(tmp, fiemap, *buflen); + ptlrpc_request_set_replen(req); + + rc = ptlrpc_queue_wait(req); + if (rc) + goto fini_req; + + reply = req_capsule_server_get(&req->rq_pill, &RMF_FIEMAP_VAL); + if (!reply) { + rc = -EPROTO; + goto fini_req; + } + + memcpy(fiemap, reply, *buflen); +fini_req: + ptlrpc_req_finished(req); +drop_lock: + if (mode) + ldlm_lock_decref(&lockh, LCK_PR); + return rc; +} + void osc_object_set_contended(struct osc_object *obj) { obj->oo_contention_time = cfs_time_current(); @@ -263,7 +351,8 @@ static const struct cl_object_operations osc_ops = { .coo_attr_get = osc_attr_get, .coo_attr_update = osc_attr_update, .coo_glimpse = osc_object_glimpse, - .coo_prune = osc_object_prune + .coo_prune = osc_object_prune, + .coo_fiemap = osc_object_fiemap, }; static const struct lu_object_operations osc_lu_obj_ops = { diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 749781f022e2..963a4858a657 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2543,103 +2543,6 @@ out: return err; } -static int osc_get_info(const struct lu_env *env, struct obd_export *exp, - u32 keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm) -{ - if (!vallen || !val) - return -EFAULT; - - if (KEY_IS(KEY_FIEMAP)) { - struct ll_fiemap_info_key *fm_key = key; - struct ldlm_res_id res_id; - ldlm_policy_data_t policy; - struct lustre_handle lockh; - enum ldlm_mode mode = 0; - struct ptlrpc_request *req; - struct ll_user_fiemap *reply; - char *tmp; - int rc; - - if (!(fm_key->fiemap.fm_flags & FIEMAP_FLAG_SYNC)) - goto skip_locking; - - policy.l_extent.start = fm_key->fiemap.fm_start & - PAGE_MASK; - - if (OBD_OBJECT_EOF - fm_key->fiemap.fm_length <= - fm_key->fiemap.fm_start + PAGE_SIZE - 1) - policy.l_extent.end = OBD_OBJECT_EOF; - else - policy.l_extent.end = (fm_key->fiemap.fm_start + - fm_key->fiemap.fm_length + - PAGE_SIZE - 1) & PAGE_MASK; - - ostid_build_res_name(&fm_key->oa.o_oi, &res_id); - mode = ldlm_lock_match(exp->exp_obd->obd_namespace, - LDLM_FL_BLOCK_GRANTED | - LDLM_FL_LVB_READY, - &res_id, LDLM_EXTENT, &policy, - LCK_PR | LCK_PW, &lockh, 0); - if (mode) { /* lock is cached on client */ - if (mode != LCK_PR) { - ldlm_lock_addref(&lockh, LCK_PR); - ldlm_lock_decref(&lockh, LCK_PW); - } - } else { /* no cached lock, needs acquire lock on server side */ - fm_key->oa.o_valid |= OBD_MD_FLFLAGS; - fm_key->oa.o_flags |= OBD_FL_SRVLOCK; - } - -skip_locking: - req = ptlrpc_request_alloc(class_exp2cliimp(exp), - &RQF_OST_GET_INFO_FIEMAP); - if (!req) { - rc = -ENOMEM; - goto drop_lock; - } - - req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_KEY, - RCL_CLIENT, keylen); - req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, - RCL_CLIENT, *vallen); - req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, - RCL_SERVER, *vallen); - - rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO); - if (rc) { - ptlrpc_request_free(req); - goto drop_lock; - } - - tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_KEY); - memcpy(tmp, key, keylen); - tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_VAL); - memcpy(tmp, val, *vallen); - - ptlrpc_request_set_replen(req); - rc = ptlrpc_queue_wait(req); - if (rc) - goto fini_req; - - reply = req_capsule_server_get(&req->rq_pill, &RMF_FIEMAP_VAL); - if (!reply) { - rc = -EPROTO; - goto fini_req; - } - - memcpy(val, reply, *vallen); -fini_req: - ptlrpc_req_finished(req); -drop_lock: - if (mode) - ldlm_lock_decref(&lockh, LCK_PR); - return rc; - } - - return -EINVAL; -} - static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp, u32 keylen, void *key, u32 vallen, void *val, struct ptlrpc_request_set *set) @@ -3112,7 +3015,6 @@ static struct obd_ops osc_obd_ops = { .setattr = osc_setattr, .setattr_async = osc_setattr_async, .iocontrol = osc_iocontrol, - .get_info = osc_get_info, .set_info_async = osc_set_info_async, .import_event = osc_import_event, .process_config = osc_process_config, diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 871768511e8c..36b86aee3346 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1772,7 +1772,7 @@ void lustre_swab_fid2path(struct getinfo_fid2path *gf) } EXPORT_SYMBOL(lustre_swab_fid2path); -static void lustre_swab_fiemap_extent(struct ll_fiemap_extent *fm_extent) +static void lustre_swab_fiemap_extent(struct fiemap_extent *fm_extent) { __swab64s(&fm_extent->fe_logical); __swab64s(&fm_extent->fe_physical); @@ -1781,7 +1781,7 @@ static void lustre_swab_fiemap_extent(struct ll_fiemap_extent *fm_extent) __swab32s(&fm_extent->fe_device); } -void lustre_swab_fiemap(struct ll_user_fiemap *fiemap) +void lustre_swab_fiemap(struct fiemap *fiemap) { __u32 i; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index b05b1f935e4c..1000bee085bc 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -3520,21 +3520,21 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct llogd_conn_body *)0)->lgdc_ctxt_idx) == 4, "found %lld\n", (long long)(int)sizeof(((struct llogd_conn_body *)0)->lgdc_ctxt_idx)); - /* Checks for struct ll_fiemap_info_key */ + /* Checks for struct fiemap_info_key */ LASSERTF((int)sizeof(struct ll_fiemap_info_key) == 248, "found %lld\n", (long long)(int)sizeof(struct ll_fiemap_info_key)); - LASSERTF((int)offsetof(struct ll_fiemap_info_key, name[8]) == 8, "found %lld\n", - (long long)(int)offsetof(struct ll_fiemap_info_key, name[8])); - LASSERTF((int)sizeof(((struct ll_fiemap_info_key *)0)->name[8]) == 1, "found %lld\n", - (long long)(int)sizeof(((struct ll_fiemap_info_key *)0)->name[8])); - LASSERTF((int)offsetof(struct ll_fiemap_info_key, oa) == 8, "found %lld\n", - (long long)(int)offsetof(struct ll_fiemap_info_key, oa)); - LASSERTF((int)sizeof(((struct ll_fiemap_info_key *)0)->oa) == 208, "found %lld\n", - (long long)(int)sizeof(((struct ll_fiemap_info_key *)0)->oa)); - LASSERTF((int)offsetof(struct ll_fiemap_info_key, fiemap) == 216, "found %lld\n", - (long long)(int)offsetof(struct ll_fiemap_info_key, fiemap)); - LASSERTF((int)sizeof(((struct ll_fiemap_info_key *)0)->fiemap) == 32, "found %lld\n", - (long long)(int)sizeof(((struct ll_fiemap_info_key *)0)->fiemap)); + LASSERTF((int)offsetof(struct ll_fiemap_info_key, lfik_name[8]) == 8, "found %lld\n", + (long long)(int)offsetof(struct ll_fiemap_info_key, lfik_name[8])); + LASSERTF((int)sizeof(((struct ll_fiemap_info_key *)0)->lfik_name[8]) == 1, "found %lld\n", + (long long)(int)sizeof(((struct ll_fiemap_info_key *)0)->lfik_name[8])); + LASSERTF((int)offsetof(struct ll_fiemap_info_key, lfik_oa) == 8, "found %lld\n", + (long long)(int)offsetof(struct ll_fiemap_info_key, lfik_oa)); + LASSERTF((int)sizeof(((struct ll_fiemap_info_key *)0)->lfik_oa) == 208, "found %lld\n", + (long long)(int)sizeof(((struct ll_fiemap_info_key *)0)->lfik_oa)); + LASSERTF((int)offsetof(struct ll_fiemap_info_key, lfik_fiemap) == 216, "found %lld\n", + (long long)(int)offsetof(struct ll_fiemap_info_key, lfik_fiemap)); + LASSERTF((int)sizeof(((struct ll_fiemap_info_key *)0)->lfik_fiemap) == 32, "found %lld\n", + (long long)(int)sizeof(((struct ll_fiemap_info_key *)0)->lfik_fiemap)); /* Checks for struct mgs_target_info */ LASSERTF((int)sizeof(struct mgs_target_info) == 4544, "found %lld\n", @@ -3670,64 +3670,64 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct getinfo_fid2path *)0)->gf_path[0]) == 1, "found %lld\n", (long long)(int)sizeof(((struct getinfo_fid2path *)0)->gf_path[0])); - /* Checks for struct ll_user_fiemap */ - LASSERTF((int)sizeof(struct ll_user_fiemap) == 32, "found %lld\n", - (long long)(int)sizeof(struct ll_user_fiemap)); - LASSERTF((int)offsetof(struct ll_user_fiemap, fm_start) == 0, "found %lld\n", - (long long)(int)offsetof(struct ll_user_fiemap, fm_start)); - LASSERTF((int)sizeof(((struct ll_user_fiemap *)0)->fm_start) == 8, "found %lld\n", - (long long)(int)sizeof(((struct ll_user_fiemap *)0)->fm_start)); - LASSERTF((int)offsetof(struct ll_user_fiemap, fm_length) == 8, "found %lld\n", - (long long)(int)offsetof(struct ll_user_fiemap, fm_length)); - LASSERTF((int)sizeof(((struct ll_user_fiemap *)0)->fm_length) == 8, "found %lld\n", - (long long)(int)sizeof(((struct ll_user_fiemap *)0)->fm_length)); - LASSERTF((int)offsetof(struct ll_user_fiemap, fm_flags) == 16, "found %lld\n", - (long long)(int)offsetof(struct ll_user_fiemap, fm_flags)); - LASSERTF((int)sizeof(((struct ll_user_fiemap *)0)->fm_flags) == 4, "found %lld\n", - (long long)(int)sizeof(((struct ll_user_fiemap *)0)->fm_flags)); - LASSERTF((int)offsetof(struct ll_user_fiemap, fm_mapped_extents) == 20, "found %lld\n", - (long long)(int)offsetof(struct ll_user_fiemap, fm_mapped_extents)); - LASSERTF((int)sizeof(((struct ll_user_fiemap *)0)->fm_mapped_extents) == 4, "found %lld\n", - (long long)(int)sizeof(((struct ll_user_fiemap *)0)->fm_mapped_extents)); - LASSERTF((int)offsetof(struct ll_user_fiemap, fm_extent_count) == 24, "found %lld\n", - (long long)(int)offsetof(struct ll_user_fiemap, fm_extent_count)); - LASSERTF((int)sizeof(((struct ll_user_fiemap *)0)->fm_extent_count) == 4, "found %lld\n", - (long long)(int)sizeof(((struct ll_user_fiemap *)0)->fm_extent_count)); - LASSERTF((int)offsetof(struct ll_user_fiemap, fm_reserved) == 28, "found %lld\n", - (long long)(int)offsetof(struct ll_user_fiemap, fm_reserved)); - LASSERTF((int)sizeof(((struct ll_user_fiemap *)0)->fm_reserved) == 4, "found %lld\n", - (long long)(int)sizeof(((struct ll_user_fiemap *)0)->fm_reserved)); - LASSERTF((int)offsetof(struct ll_user_fiemap, fm_extents) == 32, "found %lld\n", - (long long)(int)offsetof(struct ll_user_fiemap, fm_extents)); - LASSERTF((int)sizeof(((struct ll_user_fiemap *)0)->fm_extents) == 0, "found %lld\n", - (long long)(int)sizeof(((struct ll_user_fiemap *)0)->fm_extents)); + /* Checks for struct fiemap */ + LASSERTF((int)sizeof(struct fiemap) == 32, "found %lld\n", + (long long)(int)sizeof(struct fiemap)); + LASSERTF((int)offsetof(struct fiemap, fm_start) == 0, "found %lld\n", + (long long)(int)offsetof(struct fiemap, fm_start)); + LASSERTF((int)sizeof(((struct fiemap *)0)->fm_start) == 8, "found %lld\n", + (long long)(int)sizeof(((struct fiemap *)0)->fm_start)); + LASSERTF((int)offsetof(struct fiemap, fm_length) == 8, "found %lld\n", + (long long)(int)offsetof(struct fiemap, fm_length)); + LASSERTF((int)sizeof(((struct fiemap *)0)->fm_length) == 8, "found %lld\n", + (long long)(int)sizeof(((struct fiemap *)0)->fm_length)); + LASSERTF((int)offsetof(struct fiemap, fm_flags) == 16, "found %lld\n", + (long long)(int)offsetof(struct fiemap, fm_flags)); + LASSERTF((int)sizeof(((struct fiemap *)0)->fm_flags) == 4, "found %lld\n", + (long long)(int)sizeof(((struct fiemap *)0)->fm_flags)); + LASSERTF((int)offsetof(struct fiemap, fm_mapped_extents) == 20, "found %lld\n", + (long long)(int)offsetof(struct fiemap, fm_mapped_extents)); + LASSERTF((int)sizeof(((struct fiemap *)0)->fm_mapped_extents) == 4, "found %lld\n", + (long long)(int)sizeof(((struct fiemap *)0)->fm_mapped_extents)); + LASSERTF((int)offsetof(struct fiemap, fm_extent_count) == 24, "found %lld\n", + (long long)(int)offsetof(struct fiemap, fm_extent_count)); + LASSERTF((int)sizeof(((struct fiemap *)0)->fm_extent_count) == 4, "found %lld\n", + (long long)(int)sizeof(((struct fiemap *)0)->fm_extent_count)); + LASSERTF((int)offsetof(struct fiemap, fm_reserved) == 28, "found %lld\n", + (long long)(int)offsetof(struct fiemap, fm_reserved)); + LASSERTF((int)sizeof(((struct fiemap *)0)->fm_reserved) == 4, "found %lld\n", + (long long)(int)sizeof(((struct fiemap *)0)->fm_reserved)); + LASSERTF((int)offsetof(struct fiemap, fm_extents) == 32, "found %lld\n", + (long long)(int)offsetof(struct fiemap, fm_extents)); + LASSERTF((int)sizeof(((struct fiemap *)0)->fm_extents) == 0, "found %lld\n", + (long long)(int)sizeof(((struct fiemap *)0)->fm_extents)); CLASSERT(FIEMAP_FLAG_SYNC == 0x00000001); CLASSERT(FIEMAP_FLAG_XATTR == 0x00000002); CLASSERT(FIEMAP_FLAG_DEVICE_ORDER == 0x40000000); - /* Checks for struct ll_fiemap_extent */ - LASSERTF((int)sizeof(struct ll_fiemap_extent) == 56, "found %lld\n", - (long long)(int)sizeof(struct ll_fiemap_extent)); - LASSERTF((int)offsetof(struct ll_fiemap_extent, fe_logical) == 0, "found %lld\n", - (long long)(int)offsetof(struct ll_fiemap_extent, fe_logical)); - LASSERTF((int)sizeof(((struct ll_fiemap_extent *)0)->fe_logical) == 8, "found %lld\n", - (long long)(int)sizeof(((struct ll_fiemap_extent *)0)->fe_logical)); - LASSERTF((int)offsetof(struct ll_fiemap_extent, fe_physical) == 8, "found %lld\n", - (long long)(int)offsetof(struct ll_fiemap_extent, fe_physical)); - LASSERTF((int)sizeof(((struct ll_fiemap_extent *)0)->fe_physical) == 8, "found %lld\n", - (long long)(int)sizeof(((struct ll_fiemap_extent *)0)->fe_physical)); - LASSERTF((int)offsetof(struct ll_fiemap_extent, fe_length) == 16, "found %lld\n", - (long long)(int)offsetof(struct ll_fiemap_extent, fe_length)); - LASSERTF((int)sizeof(((struct ll_fiemap_extent *)0)->fe_length) == 8, "found %lld\n", - (long long)(int)sizeof(((struct ll_fiemap_extent *)0)->fe_length)); - LASSERTF((int)offsetof(struct ll_fiemap_extent, fe_flags) == 40, "found %lld\n", - (long long)(int)offsetof(struct ll_fiemap_extent, fe_flags)); - LASSERTF((int)sizeof(((struct ll_fiemap_extent *)0)->fe_flags) == 4, "found %lld\n", - (long long)(int)sizeof(((struct ll_fiemap_extent *)0)->fe_flags)); - LASSERTF((int)offsetof(struct ll_fiemap_extent, fe_device) == 44, "found %lld\n", - (long long)(int)offsetof(struct ll_fiemap_extent, fe_device)); - LASSERTF((int)sizeof(((struct ll_fiemap_extent *)0)->fe_device) == 4, "found %lld\n", - (long long)(int)sizeof(((struct ll_fiemap_extent *)0)->fe_device)); + /* Checks for struct fiemap_extent */ + LASSERTF((int)sizeof(struct fiemap_extent) == 56, "found %lld\n", + (long long)(int)sizeof(struct fiemap_extent)); + LASSERTF((int)offsetof(struct fiemap_extent, fe_logical) == 0, "found %lld\n", + (long long)(int)offsetof(struct fiemap_extent, fe_logical)); + LASSERTF((int)sizeof(((struct fiemap_extent *)0)->fe_logical) == 8, "found %lld\n", + (long long)(int)sizeof(((struct fiemap_extent *)0)->fe_logical)); + LASSERTF((int)offsetof(struct fiemap_extent, fe_physical) == 8, "found %lld\n", + (long long)(int)offsetof(struct fiemap_extent, fe_physical)); + LASSERTF((int)sizeof(((struct fiemap_extent *)0)->fe_physical) == 8, "found %lld\n", + (long long)(int)sizeof(((struct fiemap_extent *)0)->fe_physical)); + LASSERTF((int)offsetof(struct fiemap_extent, fe_length) == 16, "found %lld\n", + (long long)(int)offsetof(struct fiemap_extent, fe_length)); + LASSERTF((int)sizeof(((struct fiemap_extent *)0)->fe_length) == 8, "found %lld\n", + (long long)(int)sizeof(((struct fiemap_extent *)0)->fe_length)); + LASSERTF((int)offsetof(struct fiemap_extent, fe_flags) == 40, "found %lld\n", + (long long)(int)offsetof(struct fiemap_extent, fe_flags)); + LASSERTF((int)sizeof(((struct fiemap_extent *)0)->fe_flags) == 4, "found %lld\n", + (long long)(int)sizeof(((struct fiemap_extent *)0)->fe_flags)); + LASSERTF((int)offsetof(struct fiemap_extent, fe_reserved[0]) == 44, "found %lld\n", + (long long)(int)offsetof(struct fiemap_extent, fe_reserved[0])); + LASSERTF((int)sizeof(((struct fiemap_extent *)0)->fe_reserved[0]) == 4, "found %lld\n", + (long long)(int)sizeof(((struct fiemap_extent *)0)->fe_reserved[0])); CLASSERT(FIEMAP_EXTENT_LAST == 0x00000001); CLASSERT(FIEMAP_EXTENT_UNKNOWN == 0x00000002); CLASSERT(FIEMAP_EXTENT_DELALLOC == 0x00000004); -- cgit v1.2.3 From bb0c9db9bee2ce86c66c51582a238cf76b8543d0 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Sun, 2 Oct 2016 22:28:04 -0400 Subject: staging: lustre: ptlrpc: ret -ECONNREFUSED if not context found in req Return -ECONNREFUSED instead of -ENOMEM in sptlrpc_req_get_ctx() if no context is found in req. It is more graceful. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6356 Reviewed-on: http://review.whamcloud.com/14043 Reviewed-by: Dmitry Eremin Reviewed-by: Andrew Perepechko Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/sec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index a7416cd9ac71..12f02ed6a91d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -379,7 +379,7 @@ int sptlrpc_req_get_ctx(struct ptlrpc_request *req) if (!req->rq_cli_ctx) { CERROR("req %p: fail to get context\n", req); - return -ENOMEM; + return -ECONNREFUSED; } return 0; -- cgit v1.2.3 From d0d3caaed9e1babafb5a883e02e596740acba854 Mon Sep 17 00:00:00 2001 From: wang di Date: Sun, 2 Oct 2016 22:28:05 -0400 Subject: staging: lustre: llite: default dir stripe index only for mkdir Default dir stripe index should only work during mkdir, otherwise it will cause other open/create request being sent to the wrong MDT. Signed-off-by: wang di Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6373 Reviewed-on: http://review.whamcloud.com/14096 Reviewed-by: Alex Zhuravlev Reviewed-by: Fan Yong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 84a377a99f42..ba9e5ff97f67 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2269,8 +2269,9 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, op_data->op_default_stripe_offset = -1; if (S_ISDIR(i1->i_mode)) { op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md; - op_data->op_default_stripe_offset = - ll_i2info(i1)->lli_def_stripe_offset; + if (opc == LUSTRE_OPC_MKDIR) + op_data->op_default_stripe_offset = + ll_i2info(i1)->lli_def_stripe_offset; } if (i2) { -- cgit v1.2.3 From 239fd5d41f9b24e06dc747f02dc108e9b8cffb28 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Sun, 2 Oct 2016 22:28:06 -0400 Subject: staging: lustre: libcfs: shortcut to create CPT from NUMA topology If user wants to create CPT table that can match numa topology, she has to query cpu & numa topology, then provide a pattern string to describe the topology, this is inconvenient. To improve it, this patch can support shortcut expression "N" or "n" to create CPT table from NUMA & CPU topology Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6325 Reviewed-on: http://review.whamcloud.com/14049 Reviewed-by: Olaf Weber Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/libcfs/linux/linux-cpu.c | 48 ++++++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c index e8b1a61420de..464b27923ac0 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c @@ -55,6 +55,8 @@ MODULE_PARM_DESC(cpu_npartitions, "# of CPU partitions"); * i.e: "N 0[0,1] 1[2,3]" the first character 'N' means numbers in bracket * are NUMA node ID, number before bracket is CPU partition ID. * + * i.e: "N", shortcut expression to create CPT from NUMA & CPU topology + * * NB: If user specified cpu_pattern, cpu_npartitions will be ignored */ static char *cpu_pattern = ""; @@ -818,11 +820,14 @@ static struct cfs_cpt_table * cfs_cpt_table_create_pattern(char *pattern) { struct cfs_cpt_table *cptab; - char *str = pattern; + char *str; int node = 0; int high; - int ncpt; + int ncpt = 0; + int cpt; + int rc; int c; + int i; for (ncpt = 0;; ncpt++) { /* quick scan bracket */ str = strchr(str, '['); @@ -834,7 +839,20 @@ cfs_cpt_table_create_pattern(char *pattern) str = cfs_trimwhite(pattern); if (*str == 'n' || *str == 'N') { pattern = str + 1; - node = 1; + if (*pattern != '\0') { + node = 1; + } else { /* shortcut to create CPT from NUMA & CPU topology */ + node = -1; + ncpt = num_online_nodes(); + } + } + + if (!ncpt) { /* scanning bracket which is mark of partition */ + for (str = pattern;; str++, ncpt++) { + str = strchr(str, '['); + if (!str) + break; + } } if (ncpt == 0 || @@ -845,21 +863,35 @@ cfs_cpt_table_create_pattern(char *pattern) return NULL; } - high = node ? MAX_NUMNODES - 1 : nr_cpu_ids - 1; - cptab = cfs_cpt_table_alloc(ncpt); if (!cptab) { CERROR("Failed to allocate cpu partition table\n"); return NULL; } + if (node < 0) { /* shortcut to create CPT from NUMA & CPU topology */ + cpt = 0; + + for_each_online_node(i) { + if (cpt >= ncpt) { + CERROR("CPU changed while setting CPU partition table, %d/%d\n", + cpt, ncpt); + goto failed; + } + + rc = cfs_cpt_set_node(cptab, cpt++, i); + if (!rc) + goto failed; + } + return cptab; + } + + high = node ? MAX_NUMNODES - 1 : nr_cpu_ids - 1; + for (str = cfs_trimwhite(pattern), c = 0;; c++) { struct cfs_range_expr *range; struct cfs_expr_list *el; char *bracket = strchr(str, '['); - int cpt; - int rc; - int i; int n; if (!bracket) { -- cgit v1.2.3 From 872cbbdf1d6405fdb203e9d0038ac97cc99e3aff Mon Sep 17 00:00:00 2001 From: Gregoire Pichon Date: Sun, 2 Oct 2016 22:28:07 -0400 Subject: staging: lustre: ptlrpc: Add OBD_CONNECT_MULTIMODRPCS flag The new OBD_CONNECT_MULTIMODRPCS connection flag indicates the support of multiple modify RPCs in parallel. It can be specified by the client within the connection request and by the server within the connection reply. The new ocd_maxmodrpcs connection data specifies the maximum modify RPCs in parallel supported by the server. To allow the MDS to send the new ocd_maxmodrpcs field, it has been required to modify RMF_CONNECT_DATA so that its size includes the new field. This change leads to remove the ocd_connect_data_v1 structure. Note that the client has been allocating an extra 16*sizeof(__u64) for the obd_connect_data reply since 2.0 and even in later versions of 1.8) so there is no problem for the MDS to just send the full reply size. This patch fixes a bug in __req_capsule_get() since it wasn't checking RMF_F_NO_SIZE_CHECK when receiving the message. This allows legacy clients (with version lower that this commit) to send connection request with ocd_connect_data structure size smaller (actually size is ocd_connect_data_v1 structure size) than new server ocd_connect_data structure size. This patch also fixes a bug in the routine that displays the import's connect data. Signed-off-by: Gregoire Pichon Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5319 Reviewed-on: http://review.whamcloud.com/#/c/13960 Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 26 +++++----------------- .../lustre/lustre/obdclass/lprocfs_status.c | 7 ++++-- drivers/staging/lustre/lustre/ptlrpc/layout.c | 5 +++-- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 3 +++ drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 14 ++++++++++-- 5 files changed, 29 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 42107165020c..b88807f5a58b 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1282,6 +1282,9 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); */ #define OBD_CONNECT_LFSCK 0x40000000000000ULL/* support online LFSCK */ #define OBD_CONNECT_UNLINK_CLOSE 0x100000000000000ULL/* close file in unlink */ +#define OBD_CONNECT_MULTIMODRPCS 0x200000000000000ULL /* support multiple modify + * RPCs in parallel + */ #define OBD_CONNECT_DIR_STRIPE 0x400000000000000ULL/* striped DNE dir */ /* XXX README XXX: @@ -1313,25 +1316,6 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); * If we eventually have separate connect data for different types, which we * almost certainly will, then perhaps we stick a union in here. */ -struct obd_connect_data_v1 { - __u64 ocd_connect_flags; /* OBD_CONNECT_* per above */ - __u32 ocd_version; /* lustre release version number */ - __u32 ocd_grant; /* initial cache grant amount (bytes) */ - __u32 ocd_index; /* LOV index to connect to */ - __u32 ocd_brw_size; /* Maximum BRW size in bytes, must be 2^n */ - __u64 ocd_ibits_known; /* inode bits this client understands */ - __u8 ocd_blocksize; /* log2 of the backend filesystem blocksize */ - __u8 ocd_inodespace; /* log2 of the per-inode space consumption */ - __u16 ocd_grant_extent; /* per-extent grant overhead, in 1K blocks */ - __u32 ocd_unused; /* also fix lustre_swab_connect */ - __u64 ocd_transno; /* first transno from client to be replayed */ - __u32 ocd_group; /* MDS group on OST */ - __u32 ocd_cksum_types; /* supported checksum algorithms */ - __u32 ocd_max_easize; /* How big LOV EA can be on MDS */ - __u32 ocd_instance; /* also fix lustre_swab_connect */ - __u64 ocd_maxbytes; /* Maximum stripe size in bytes */ -}; - struct obd_connect_data { __u64 ocd_connect_flags; /* OBD_CONNECT_* per above */ __u32 ocd_version; /* lustre release version number */ @@ -1354,7 +1338,9 @@ struct obd_connect_data { * any field after ocd_maxbytes on the receiver without a valid flag * may result in out-of-bound memory access and kernel oops. */ - __u64 padding1; /* added 2.1.0. also fix lustre_swab_connect */ + __u16 ocd_maxmodrpcs; /* Maximum modify RPCs in parallel */ + __u16 padding0; /* added 2.1.0. also fix lustre_swab_connect */ + __u32 padding1; /* added 2.1.0. also fix lustre_swab_connect */ __u64 padding2; /* added 2.1.0. also fix lustre_swab_connect */ __u64 padding3; /* added 2.1.0. also fix lustre_swab_connect */ __u64 padding4; /* added 2.1.0. also fix lustre_swab_connect */ diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 852a5acfefab..b520c96feb3c 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -100,7 +100,7 @@ static const char * const obd_connect_names[] = { "lfsck", "unknown", "unlink_close", - "unknown", + "multi_mod_rpcs", "dir_stripe", "unknown", NULL @@ -127,7 +127,7 @@ EXPORT_SYMBOL(obd_connect_flags2str); static void obd_connect_data_seqprint(struct seq_file *m, struct obd_connect_data *ocd) { - int flags; + u64 flags; LASSERT(ocd); flags = ocd->ocd_connect_flags; @@ -172,6 +172,9 @@ static void obd_connect_data_seqprint(struct seq_file *m, if (flags & OBD_CONNECT_MAXBYTES) seq_printf(m, " max_object_bytes: %llx\n", ocd->ocd_maxbytes); + if (flags & OBD_CONNECT_MULTIMODRPCS) + seq_printf(m, " max_mod_rpcs: %hu\n", + ocd->ocd_maxmodrpcs); } int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index 839ef3e80c1a..4ea84545ced2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -1874,13 +1874,14 @@ static void *__req_capsule_get(struct req_capsule *pill, getter = (field->rmf_flags & RMF_F_STRING) ? (typeof(getter))lustre_msg_string : lustre_msg_buf; - if (field->rmf_flags & RMF_F_STRUCT_ARRAY) { + if (field->rmf_flags & (RMF_F_STRUCT_ARRAY | RMF_F_NO_SIZE_CHECK)) { /* * We've already asserted that field->rmf_size > 0 in * req_layout_init(). */ len = lustre_msg_buflen(msg, offset); - if ((len % field->rmf_size) != 0) { + if (!(field->rmf_flags & RMF_F_NO_SIZE_CHECK) && + (len % field->rmf_size)) { CERROR("%s: array field size mismatch %d modulo %u != 0 (%d)\n", field->rmf_name, len, field->rmf_size, loc); return NULL; diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 36b86aee3346..2dc0b79bf5bc 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1492,6 +1492,9 @@ void lustre_swab_connect(struct obd_connect_data *ocd) __swab32s(&ocd->ocd_max_easize); if (ocd->ocd_connect_flags & OBD_CONNECT_MAXBYTES) __swab64s(&ocd->ocd_maxbytes); + if (ocd->ocd_connect_flags & OBD_CONNECT_MULTIMODRPCS) + __swab16s(&ocd->ocd_maxmodrpcs); + CLASSERT(offsetof(typeof(*ocd), padding0)); CLASSERT(offsetof(typeof(*ocd), padding1) != 0); CLASSERT(offsetof(typeof(*ocd), padding2) != 0); CLASSERT(offsetof(typeof(*ocd), padding3) != 0); diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 1000bee085bc..fabfe943c614 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -905,9 +905,17 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct obd_connect_data, ocd_maxbytes)); LASSERTF((int)sizeof(((struct obd_connect_data *)0)->ocd_maxbytes) == 8, "found %lld\n", (long long)(int)sizeof(((struct obd_connect_data *)0)->ocd_maxbytes)); - LASSERTF((int)offsetof(struct obd_connect_data, padding1) == 72, "found %lld\n", + LASSERTF((int)offsetof(struct obd_connect_data, ocd_maxmodrpcs) == 72, "found %lld\n", + (long long)(int)offsetof(struct obd_connect_data, ocd_maxmodrpcs)); + LASSERTF((int)sizeof(((struct obd_connect_data *)0)->ocd_maxmodrpcs) == 2, "found %lld\n", + (long long)(int)sizeof(((struct obd_connect_data *)0)->ocd_maxmodrpcs)); + LASSERTF((int)offsetof(struct obd_connect_data, padding0) == 74, "found %lld\n", + (long long)(int)offsetof(struct obd_connect_data, padding0)); + LASSERTF((int)sizeof(((struct obd_connect_data *)0)->padding0) == 2, "found %lld\n", + (long long)(int)sizeof(((struct obd_connect_data *)0)->padding0)); + LASSERTF((int)offsetof(struct obd_connect_data, padding1) == 76, "found %lld\n", (long long)(int)offsetof(struct obd_connect_data, padding1)); - LASSERTF((int)sizeof(((struct obd_connect_data *)0)->padding1) == 8, "found %lld\n", + LASSERTF((int)sizeof(((struct obd_connect_data *)0)->padding1) == 4, "found %lld\n", (long long)(int)sizeof(((struct obd_connect_data *)0)->padding1)); LASSERTF((int)offsetof(struct obd_connect_data, padding2) == 80, "found %lld\n", (long long)(int)offsetof(struct obd_connect_data, padding2)); @@ -1075,6 +1083,8 @@ void lustre_assert_wire_constants(void) OBD_CONNECT_LFSCK); LASSERTF(OBD_CONNECT_UNLINK_CLOSE == 0x100000000000000ULL, "found 0x%.16llxULL\n", OBD_CONNECT_UNLINK_CLOSE); + LASSERTF(OBD_CONNECT_MULTIMODRPCS == 0x200000000000000ULL, "found 0x%.16llxULL\n", + OBD_CONNECT_MULTIMODRPCS); LASSERTF(OBD_CONNECT_DIR_STRIPE == 0x400000000000000ULL, "found 0x%.16llxULL\n", OBD_CONNECT_DIR_STRIPE); LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n", -- cgit v1.2.3 From 2a99f829472e0c33f65630ae92f34dbc3e60ebd2 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Sun, 2 Oct 2016 22:28:08 -0400 Subject: staging: lustre: clio: get rid of lov_stripe_md reference Get rid of lov_stripe_md reference in setting file's stripe info. Signed-off-by: Bobi Jam Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5823 Reviewed-on: http://review.whamcloud.com/12639 Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 162b8103a454..c1db5a17e30c 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1186,27 +1186,14 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, __u64 flags, struct lov_user_md *lum, int lum_size) { - struct lov_stripe_md *lsm = NULL; struct lookup_intent oit = { .it_op = IT_OPEN, .it_flags = flags | MDS_OPEN_BY_FID, }; int rc = 0; - lsm = ccc_inode_lsm_get(inode); - if (lsm) { - ccc_inode_lsm_put(inode, lsm); - CDEBUG(D_IOCTL, "stripe already exists for inode "DFID"\n", - PFID(ll_inode2fid(inode))); - rc = -EEXIST; - goto out; - } - ll_inode_size_lock(inode); rc = ll_intent_file_open(dentry, lum, lum_size, &oit); - if (rc < 0) - goto out_unlock; - rc = oit.it_status; if (rc < 0) goto out_unlock; @@ -1215,8 +1202,6 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, out_unlock: ll_inode_size_unlock(inode); ll_intent_release(&oit); - ccc_inode_lsm_put(inode, lsm); -out: return rc; } -- cgit v1.2.3 From 933eb397362900c64c95b702296ae871ee12f5f8 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:09 -0400 Subject: staging: lustre: clio: use CIT_SETATTR for FSFILT_IOC_SETFLAGS Add handling of inode flags to the handlers of CIT_SETATTR in lov and osc. In the FSFILT_IOC_SETFLAGS case of ll_iocontrol() use cl_setattr_ost() rather than obd_setattr_rqset() to set inode flags on OST objects. Remove the then unused OBD API methods obd_setattr_rqset() and obd_setattr_async() along with their supporting functions. Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5823 Reviewed-on: http://review.whamcloud.com/13422 Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/cl_object.h | 3 +- .../staging/lustre/lustre/include/lustre_compat.h | 2 + drivers/staging/lustre/lustre/include/obd.h | 3 - drivers/staging/lustre/lustre/include/obd_class.h | 39 ------ drivers/staging/lustre/lustre/llite/lcommon_cl.c | 8 +- .../staging/lustre/lustre/llite/llite_internal.h | 3 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 33 ++---- drivers/staging/lustre/lustre/llite/vvp_io.c | 15 ++- drivers/staging/lustre/lustre/lov/lov_internal.h | 6 - drivers/staging/lustre/lustre/lov/lov_io.c | 2 + drivers/staging/lustre/lustre/lov/lov_obd.c | 82 ------------- drivers/staging/lustre/lustre/lov/lov_request.c | 131 --------------------- drivers/staging/lustre/lustre/osc/osc_internal.h | 7 +- drivers/staging/lustre/lustre/osc/osc_io.c | 29 +++-- drivers/staging/lustre/lustre/osc/osc_request.c | 19 +-- 15 files changed, 60 insertions(+), 322 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 3af9aa3bac38..0b66d027e151 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1772,9 +1772,10 @@ struct cl_io { struct cl_io_rw_common ci_rw; struct cl_setattr_io { struct ost_lvb sa_attr; + unsigned int sa_attr_flags; unsigned int sa_valid; int sa_stripe_index; - struct lu_fid *sa_parent_fid; + const struct lu_fid *sa_parent_fid; } ci_setattr; struct cl_fault_io { /** page index within file. */ diff --git a/drivers/staging/lustre/lustre/include/lustre_compat.h b/drivers/staging/lustre/lustre/include/lustre_compat.h index 567c438e93cb..300e96fb032a 100644 --- a/drivers/staging/lustre/lustre/include/lustre_compat.h +++ b/drivers/staging/lustre/lustre/include/lustre_compat.h @@ -74,4 +74,6 @@ # define ext2_find_next_zero_bit find_next_zero_bit_le #endif +#define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) + #endif /* _LUSTRE_COMPAT_H */ diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 51d5487b7d2b..fe05cc6568f3 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -896,9 +896,6 @@ struct obd_ops { struct obdo *oa, struct obd_trans_info *oti); int (*setattr)(const struct lu_env *, struct obd_export *exp, struct obd_info *oinfo, struct obd_trans_info *oti); - int (*setattr_async)(struct obd_export *exp, struct obd_info *oinfo, - struct obd_trans_info *oti, - struct ptlrpc_request_set *rqset); int (*getattr)(const struct lu_env *env, struct obd_export *exp, struct obd_info *oinfo); int (*getattr_async)(struct obd_export *exp, struct obd_info *oinfo, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 2ea102dd2940..b2ced8b1cc8f 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -749,45 +749,6 @@ static inline int obd_setattr(const struct lu_env *env, struct obd_export *exp, return rc; } -/* This performs all the requests set init/wait/destroy actions. */ -static inline int obd_setattr_rqset(struct obd_export *exp, - struct obd_info *oinfo, - struct obd_trans_info *oti) -{ - struct ptlrpc_request_set *set = NULL; - int rc; - - EXP_CHECK_DT_OP(exp, setattr_async); - EXP_COUNTER_INCREMENT(exp, setattr_async); - - set = ptlrpc_prep_set(); - if (!set) - return -ENOMEM; - - rc = OBP(exp->exp_obd, setattr_async)(exp, oinfo, oti, set); - if (rc == 0) - rc = ptlrpc_set_wait(set); - ptlrpc_set_destroy(set); - return rc; -} - -/* This adds all the requests into @set if @set != NULL, otherwise - * all requests are sent asynchronously without waiting for response. - */ -static inline int obd_setattr_async(struct obd_export *exp, - struct obd_info *oinfo, - struct obd_trans_info *oti, - struct ptlrpc_request_set *set) -{ - int rc; - - EXP_CHECK_DT_OP(exp, setattr_async); - EXP_COUNTER_INCREMENT(exp, setattr_async); - - rc = OBP(exp->exp_obd, setattr_async)(exp, oinfo, oti, set); - return rc; -} - static inline int obd_add_conn(struct obd_import *imp, struct obd_uuid *uuid, int priority) { diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 084330d08f7a..64f4aed5f076 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -80,7 +80,8 @@ int cl_inode_fini_refcheck; */ static DEFINE_MUTEX(cl_inode_fini_guard); -int cl_setattr_ost(struct inode *inode, const struct iattr *attr) +int cl_setattr_ost(struct cl_object *obj, const struct iattr *attr, + unsigned int attr_flags) { struct lu_env *env; struct cl_io *io; @@ -92,14 +93,15 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) return PTR_ERR(env); io = vvp_env_thread_io(env); - io->ci_obj = ll_i2info(inode)->lli_clob; + io->ci_obj = obj; io->u.ci_setattr.sa_attr.lvb_atime = LTIME_S(attr->ia_atime); io->u.ci_setattr.sa_attr.lvb_mtime = LTIME_S(attr->ia_mtime); io->u.ci_setattr.sa_attr.lvb_ctime = LTIME_S(attr->ia_ctime); io->u.ci_setattr.sa_attr.lvb_size = attr->ia_size; + io->u.ci_setattr.sa_attr_flags = attr_flags; io->u.ci_setattr.sa_valid = attr->ia_valid; - io->u.ci_setattr.sa_parent_fid = ll_inode2fid(inode); + io->u.ci_setattr.sa_parent_fid = lu_object_fid(&obj->co_lu); again: if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 3ea2d4bf0782..e843d326e096 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1336,7 +1336,8 @@ int ll_page_sync_io(const struct lu_env *env, struct cl_io *io, int ll_getparent(struct file *file, struct getparent __user *arg); /* lcommon_cl.c */ -int cl_setattr_ost(struct inode *inode, const struct iattr *attr); +int cl_setattr_ost(struct cl_object *obj, const struct iattr *attr, + unsigned int attr_flags); extern struct lu_env *cl_inode_fini_env; extern int cl_inode_fini_refcheck; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index ba9e5ff97f67..f836c82a0b55 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1502,7 +1502,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) */ if (attr->ia_valid & ATTR_SIZE) down_write(&lli->lli_trunc_sem); - rc = cl_setattr_ost(inode, attr); + rc = cl_setattr_ost(ll_i2info(inode)->lli_clob, attr, 0); if (attr->ia_valid & ATTR_SIZE) up_write(&lli->lli_trunc_sem); } @@ -1879,9 +1879,9 @@ int ll_iocontrol(struct inode *inode, struct file *file, return put_user(flags, (int __user *)arg); } case FSFILT_IOC_SETFLAGS: { - struct lov_stripe_md *lsm; - struct obd_info oinfo = { }; struct md_op_data *op_data; + struct cl_object *obj; + struct iattr *attr; if (get_user(flags, (int __user *)arg)) return -EFAULT; @@ -1901,30 +1901,17 @@ int ll_iocontrol(struct inode *inode, struct file *file, inode->i_flags = ll_ext_to_inode_flags(flags); - lsm = ccc_inode_lsm_get(inode); - if (!lsm_has_objects(lsm)) { - ccc_inode_lsm_put(inode, lsm); + obj = ll_i2info(inode)->lli_clob; + if (!obj) return 0; - } - oinfo.oi_oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!oinfo.oi_oa) { - ccc_inode_lsm_put(inode, lsm); + attr = kzalloc(sizeof(*attr), GFP_NOFS); + if (!attr) return -ENOMEM; - } - oinfo.oi_md = lsm; - oinfo.oi_oa->o_oi = lsm->lsm_oi; - oinfo.oi_oa->o_flags = flags; - oinfo.oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS | - OBD_MD_FLGROUP; - obdo_set_parent_fid(oinfo.oi_oa, &ll_i2info(inode)->lli_fid); - rc = obd_setattr_rqset(sbi->ll_dt_exp, &oinfo, NULL); - kmem_cache_free(obdo_cachep, oinfo.oi_oa); - ccc_inode_lsm_put(inode, lsm); - - if (rc && rc != -EPERM && rc != -EACCES) - CERROR("osc_setattr_async fails: rc = %d\n", rc); + attr->ia_valid = ATTR_ATTR_FLAG; + rc = cl_setattr_ost(obj, attr, flags); + kfree(attr); return rc; } default: diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index d1d4b232824f..1a4b89723bc6 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -551,9 +551,16 @@ static int vvp_io_setattr_lock(const struct lu_env *env, if (new_size == 0) enqflags = CEF_DISCARD_DATA; } else { - if ((io->u.ci_setattr.sa_attr.lvb_mtime >= - io->u.ci_setattr.sa_attr.lvb_ctime) || - (io->u.ci_setattr.sa_attr.lvb_atime >= + unsigned int valid = io->u.ci_setattr.sa_valid; + + if (!(valid & TIMES_SET_FLAGS)) + return 0; + + if ((!(valid & ATTR_MTIME) || + io->u.ci_setattr.sa_attr.lvb_mtime >= + io->u.ci_setattr.sa_attr.lvb_ctime) && + (!(valid & ATTR_ATIME) || + io->u.ci_setattr.sa_attr.lvb_atime >= io->u.ci_setattr.sa_attr.lvb_ctime)) return 0; new_size = 0; @@ -624,7 +631,7 @@ static int vvp_io_setattr_start(const struct lu_env *env, if (cl_io_is_trunc(io)) result = vvp_io_setattr_trunc(env, ios, inode, io->u.ci_setattr.sa_attr.lvb_size); - if (result == 0) + if (!result && io->u.ci_setattr.sa_valid & TIMES_SET_FLAGS) result = vvp_io_setattr_time(env, ios); return result; } diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 07e5ede3e952..4743c65c96f6 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -155,12 +155,6 @@ int lov_update_common_set(struct lov_request_set *set, int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set **reqset); int lov_fini_getattr_set(struct lov_request_set *set); -int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo, - struct obd_trans_info *oti, - struct lov_request_set **reqset); -int lov_update_setattr_set(struct lov_request_set *set, - struct lov_request *req, int rc); -int lov_fini_setattr_set(struct lov_request_set *set); int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo, struct lov_request_set **reqset); int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs, diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index e75e5d2e7f08..369718e97d43 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -86,6 +86,8 @@ static void lov_io_sub_inherit(struct cl_io *io, struct lov_io *lio, switch (io->ci_type) { case CIT_SETATTR: { io->u.ci_setattr.sa_attr = parent->u.ci_setattr.sa_attr; + io->u.ci_setattr.sa_attr_flags = + parent->u.ci_setattr.sa_attr_flags; io->u.ci_setattr.sa_valid = parent->u.ci_setattr.sa_valid; io->u.ci_setattr.sa_stripe_index = stripe; io->u.ci_setattr.sa_parent_fid = diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 02c7087df710..30903fc26fdd 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1047,87 +1047,6 @@ out: return rc ? rc : err; } -static int lov_setattr_interpret(struct ptlrpc_request_set *rqset, - void *data, int rc) -{ - struct lov_request_set *lovset = (struct lov_request_set *)data; - int err; - - if (rc) - atomic_set(&lovset->set_completes, 0); - err = lov_fini_setattr_set(lovset); - return rc ? rc : err; -} - -/* If @oti is given, the request goes from MDS and responses from OSTs are not - * needed. Otherwise, a client is waiting for responses. - */ -static int lov_setattr_async(struct obd_export *exp, struct obd_info *oinfo, - struct obd_trans_info *oti, - struct ptlrpc_request_set *rqset) -{ - struct lov_request_set *set; - struct lov_request *req; - struct lov_obd *lov; - int rc = 0; - - LASSERT(oinfo); - ASSERT_LSM_MAGIC(oinfo->oi_md); - if (oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE) { - LASSERT(oti); - LASSERT(oti->oti_logcookies); - } - - if (!exp || !exp->exp_obd) - return -ENODEV; - - lov = &exp->exp_obd->u.lov; - rc = lov_prep_setattr_set(exp, oinfo, oti, &set); - if (rc) - return rc; - - CDEBUG(D_INFO, "objid "DOSTID": %ux%u byte stripes\n", - POSTID(&oinfo->oi_md->lsm_oi), - oinfo->oi_md->lsm_stripe_count, - oinfo->oi_md->lsm_stripe_size); - - list_for_each_entry(req, &set->set_list, rq_link) { - if (oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE) - oti->oti_logcookies = set->set_cookies + req->rq_stripe; - - CDEBUG(D_INFO, "objid " DOSTID "[%d] has subobj " DOSTID " at idx%u\n", - POSTID(&oinfo->oi_oa->o_oi), req->rq_stripe, - POSTID(&req->rq_oi.oi_oa->o_oi), req->rq_idx); - - rc = obd_setattr_async(lov->lov_tgts[req->rq_idx]->ltd_exp, - &req->rq_oi, oti, rqset); - if (rc) { - CERROR("error: setattr objid "DOSTID" subobj" - DOSTID" on OST idx %d: rc = %d\n", - POSTID(&set->set_oi->oi_oa->o_oi), - POSTID(&req->rq_oi.oi_oa->o_oi), - req->rq_idx, rc); - break; - } - } - - /* If we are not waiting for responses on async requests, return. */ - if (rc || !rqset || list_empty(&rqset->set_requests)) { - int err; - - if (rc) - atomic_set(&set->set_completes, 0); - err = lov_fini_setattr_set(set); - return rc ? rc : err; - } - - LASSERT(!rqset->set_interpret); - rqset->set_interpret = lov_setattr_interpret; - rqset->set_arg = (void *)set; - - return 0; -} - int lov_statfs_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { struct lov_request_set *lovset = (struct lov_request_set *)data; @@ -1613,7 +1532,6 @@ static struct obd_ops lov_obd_ops = { .packmd = lov_packmd, .unpackmd = lov_unpackmd, .getattr_async = lov_getattr_async, - .setattr_async = lov_setattr_async, .iocontrol = lov_iocontrol, .get_info = lov_get_info, .set_info_async = lov_set_info_async, diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 8e4070223e10..048e597fffe6 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -311,137 +311,6 @@ out_set: return rc; } -int lov_fini_setattr_set(struct lov_request_set *set) -{ - int rc = 0; - - if (!set) - return 0; - LASSERT(set->set_exp); - if (atomic_read(&set->set_completes)) { - rc = common_attr_done(set); - /* FIXME update qos data here */ - } - - lov_put_reqset(set); - return rc; -} - -int lov_update_setattr_set(struct lov_request_set *set, - struct lov_request *req, int rc) -{ - struct lov_obd *lov = &req->rq_rqset->set_exp->exp_obd->u.lov; - struct lov_stripe_md *lsm = req->rq_rqset->set_oi->oi_md; - - lov_update_set(set, req, rc); - - /* grace error on inactive ost */ - if (rc && !(lov->lov_tgts[req->rq_idx] && - lov->lov_tgts[req->rq_idx]->ltd_active)) - rc = 0; - - if (rc == 0) { - if (req->rq_oi.oi_oa->o_valid & OBD_MD_FLCTIME) - lsm->lsm_oinfo[req->rq_stripe]->loi_lvb.lvb_ctime = - req->rq_oi.oi_oa->o_ctime; - if (req->rq_oi.oi_oa->o_valid & OBD_MD_FLMTIME) - lsm->lsm_oinfo[req->rq_stripe]->loi_lvb.lvb_mtime = - req->rq_oi.oi_oa->o_mtime; - if (req->rq_oi.oi_oa->o_valid & OBD_MD_FLATIME) - lsm->lsm_oinfo[req->rq_stripe]->loi_lvb.lvb_atime = - req->rq_oi.oi_oa->o_atime; - } - - return rc; -} - -/* The callback for osc_setattr_async that finalizes a request info when a - * response is received. - */ -static int cb_setattr_update(void *cookie, int rc) -{ - struct obd_info *oinfo = cookie; - struct lov_request *lovreq; - - lovreq = container_of(oinfo, struct lov_request, rq_oi); - return lov_update_setattr_set(lovreq->rq_rqset, lovreq, rc); -} - -int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo, - struct obd_trans_info *oti, - struct lov_request_set **reqset) -{ - struct lov_request_set *set; - struct lov_obd *lov = &exp->exp_obd->u.lov; - int rc = 0, i; - - set = kzalloc(sizeof(*set), GFP_NOFS); - if (!set) - return -ENOMEM; - lov_init_set(set); - - set->set_exp = exp; - set->set_oi = oinfo; - if (oti && oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE) - set->set_cookies = oti->oti_logcookies; - - for (i = 0; i < oinfo->oi_md->lsm_stripe_count; i++) { - struct lov_oinfo *loi = oinfo->oi_md->lsm_oinfo[i]; - struct lov_request *req; - - if (lov_oinfo_is_dummy(loi)) - continue; - - if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) { - CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx); - continue; - } - - req = kzalloc(sizeof(*req), GFP_NOFS); - if (!req) { - rc = -ENOMEM; - goto out_set; - } - req->rq_stripe = i; - req->rq_idx = loi->loi_ost_idx; - - req->rq_oi.oi_oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!req->rq_oi.oi_oa) { - kfree(req); - rc = -ENOMEM; - goto out_set; - } - memcpy(req->rq_oi.oi_oa, oinfo->oi_oa, - sizeof(*req->rq_oi.oi_oa)); - req->rq_oi.oi_oa->o_oi = loi->loi_oi; - req->rq_oi.oi_oa->o_stripe_idx = i; - req->rq_oi.oi_cb_up = cb_setattr_update; - - if (oinfo->oi_oa->o_valid & OBD_MD_FLSIZE) { - int off = lov_stripe_offset(oinfo->oi_md, - oinfo->oi_oa->o_size, i, - &req->rq_oi.oi_oa->o_size); - - if (off < 0 && req->rq_oi.oi_oa->o_size) - req->rq_oi.oi_oa->o_size--; - - CDEBUG(D_INODE, "stripe %d has size %llu/%llu\n", - i, req->rq_oi.oi_oa->o_size, - oinfo->oi_oa->o_size); - } - lov_set_add_req(req, set); - } - if (!set->set_count) { - rc = -EIO; - goto out_set; - } - *reqset = set; - return rc; -out_set: - lov_fini_setattr_set(set); - return rc; -} - #define LOV_U64_MAX ((__u64)~0ULL) #define LOV_SUM_MAX(tot, add) \ do { \ diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 9a61c9b652d6..90ea0d16b3c5 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -119,10 +119,9 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id, __u64 *flags, void *data, struct lustre_handle *lockh, int unref); -int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo, - struct obd_trans_info *oti, - obd_enqueue_update_f upcall, void *cookie, - struct ptlrpc_request_set *rqset); +int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, + obd_enqueue_update_f upcall, void *cookie, + struct ptlrpc_request_set *rqset); int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset); diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 47c63710d749..a96addf79c22 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -524,11 +524,19 @@ static int osc_io_setattr_start(const struct lu_env *env, oa->o_oi = loi->loi_oi; obdo_set_parent_fid(oa, io->u.ci_setattr.sa_parent_fid); oa->o_stripe_idx = io->u.ci_setattr.sa_stripe_index; - oa->o_mtime = attr->cat_mtime; - oa->o_atime = attr->cat_atime; - oa->o_ctime = attr->cat_ctime; - oa->o_valid |= OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLATIME | - OBD_MD_FLCTIME | OBD_MD_FLMTIME; + oa->o_valid |= OBD_MD_FLID | OBD_MD_FLGROUP; + if (ia_valid & ATTR_CTIME) { + oa->o_valid |= OBD_MD_FLCTIME; + oa->o_ctime = attr->cat_ctime; + } + if (ia_valid & ATTR_ATIME) { + oa->o_valid |= OBD_MD_FLATIME; + oa->o_atime = attr->cat_atime; + } + if (ia_valid & ATTR_MTIME) { + oa->o_valid |= OBD_MD_FLMTIME; + oa->o_mtime = attr->cat_mtime; + } if (ia_valid & ATTR_SIZE) { oa->o_size = size; oa->o_blocks = OBD_OBJECT_EOF; @@ -541,6 +549,10 @@ static int osc_io_setattr_start(const struct lu_env *env, } else { LASSERT(oio->oi_lockless == 0); } + if (ia_valid & ATTR_ATTR_FLAG) { + oa->o_flags = io->u.ci_setattr.sa_attr_flags; + oa->o_valid |= OBD_MD_FLFLAGS; + } oinfo.oi_oa = oa; init_completion(&cbargs->opc_sync); @@ -550,10 +562,9 @@ static int osc_io_setattr_start(const struct lu_env *env, &oinfo, osc_async_upcall, cbargs, PTLRPCD_SET); else - result = osc_setattr_async_base(osc_export(cl2osc(obj)), - &oinfo, NULL, - osc_async_upcall, - cbargs, PTLRPCD_SET); + result = osc_setattr_async(osc_export(cl2osc(obj)), + &oinfo, osc_async_upcall, + cbargs, PTLRPCD_SET); cbargs->opc_rpc_sent = result == 0; } return result; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 963a4858a657..de2f52269b26 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -341,10 +341,9 @@ out: return rc; } -int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo, - struct obd_trans_info *oti, - obd_enqueue_update_f upcall, void *cookie, - struct ptlrpc_request_set *rqset) +int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, + obd_enqueue_update_f upcall, void *cookie, + struct ptlrpc_request_set *rqset) { struct ptlrpc_request *req; struct osc_setattr_args *sa; @@ -360,9 +359,6 @@ int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo, return rc; } - if (oti && oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE) - oinfo->oi_oa->o_lcookie = *oti->oti_logcookies; - osc_pack_req_body(req, oinfo); ptlrpc_request_set_replen(req); @@ -390,14 +386,6 @@ int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo, return 0; } -static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, - struct obd_trans_info *oti, - struct ptlrpc_request_set *rqset) -{ - return osc_setattr_async_base(exp, oinfo, oti, - oinfo->oi_cb_up, oinfo, rqset); -} - static int osc_create(const struct lu_env *env, struct obd_export *exp, struct obdo *oa, struct obd_trans_info *oti) { @@ -3013,7 +3001,6 @@ static struct obd_ops osc_obd_ops = { .getattr = osc_getattr, .getattr_async = osc_getattr_async, .setattr = osc_setattr, - .setattr_async = osc_setattr_async, .iocontrol = osc_iocontrol, .set_info_async = osc_set_info_async, .import_event = osc_import_event, -- cgit v1.2.3 From e33115e3371579ff1b4f8cd8300889d5b3ea8c49 Mon Sep 17 00:00:00 2001 From: Gregoire Pichon Date: Sun, 2 Oct 2016 22:28:10 -0400 Subject: staging: lustre: ptlrpc: Add a tag field to ptlrpc messages The new tag field is used as a virtual index for multiple modifying RPCs management. It is set by the client and allows the target to release in-memory reply data when the tag is reused by a new RPC. The tag field replaces the unused last_seen field of ptlrpcd_body structure. Additionally, the last_xid field is used to transfer the highest XID for which a reply has been received and does not have an unreplied lower-numbered XID. Signed-off-by: Gregoire Pichon Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5319 Reviewed-on: http://review.whamcloud.com/14095 Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 12 ++++--- drivers/staging/lustre/lustre/include/lustre_net.h | 2 ++ .../staging/lustre/lustre/ptlrpc/pack_generic.c | 39 +++++++++++++++++++++- drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 32 +++++++++++++----- 4 files changed, 72 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index b88807f5a58b..4f6eeec44bcd 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1099,8 +1099,10 @@ struct ptlrpc_body_v3 { __u32 pb_version; __u32 pb_opc; __u32 pb_status; - __u64 pb_last_xid; - __u64 pb_last_seen; + __u64 pb_last_xid; /* highest replied XID without lower unreplied XID */ + __u16 pb_tag; /* virtual slot idx for multiple modifying RPCs */ + __u16 pb_padding0; + __u32 pb_padding1; __u64 pb_last_committed; __u64 pb_transno; __u32 pb_flags; @@ -1125,8 +1127,10 @@ struct ptlrpc_body_v2 { __u32 pb_version; __u32 pb_opc; __u32 pb_status; - __u64 pb_last_xid; - __u64 pb_last_seen; + __u64 pb_last_xid; /* highest replied XID without lower unreplied XID */ + __u16 pb_tag; /* virtual slot idx for multiple modifying RPCs */ + __u16 pb_padding0; + __u32 pb_padding1; __u64 pb_last_committed; __u64 pb_transno; __u32 pb_flags; diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index e9aba99ee52a..ab80330bdeea 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -2652,6 +2652,7 @@ struct lustre_handle *lustre_msg_get_handle(struct lustre_msg *msg); __u32 lustre_msg_get_type(struct lustre_msg *msg); void lustre_msg_add_version(struct lustre_msg *msg, u32 version); __u32 lustre_msg_get_opc(struct lustre_msg *msg); +__u16 lustre_msg_get_tag(struct lustre_msg *msg); __u64 lustre_msg_get_last_committed(struct lustre_msg *msg); __u64 *lustre_msg_get_versions(struct lustre_msg *msg); __u64 lustre_msg_get_transno(struct lustre_msg *msg); @@ -2670,6 +2671,7 @@ void lustre_msg_set_handle(struct lustre_msg *msg, struct lustre_handle *handle); void lustre_msg_set_type(struct lustre_msg *msg, __u32 type); void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc); +void lustre_msg_set_tag(struct lustre_msg *msg, __u16 tag); void lustre_msg_set_versions(struct lustre_msg *msg, __u64 *versions); void lustre_msg_set_transno(struct lustre_msg *msg, __u64 transno); void lustre_msg_set_status(struct lustre_msg *msg, __u32 status); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 2dc0b79bf5bc..30556495cd7b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -942,6 +942,25 @@ __u32 lustre_msg_get_opc(struct lustre_msg *msg) } EXPORT_SYMBOL(lustre_msg_get_opc); +__u16 lustre_msg_get_tag(struct lustre_msg *msg) +{ + switch (msg->lm_magic) { + case LUSTRE_MSG_MAGIC_V2: { + struct ptlrpc_body *pb = lustre_msg_ptlrpc_body(msg); + + if (!pb) { + CERROR("invalid msg %p: no ptlrpc body!\n", msg); + return 0; + } + return pb->pb_tag; + } + default: + CERROR("incorrect message magic: %08x\n", msg->lm_magic); + return 0; + } +} +EXPORT_SYMBOL(lustre_msg_get_tag); + __u64 lustre_msg_get_last_committed(struct lustre_msg *msg) { switch (msg->lm_magic) { @@ -1236,6 +1255,22 @@ void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc) } } +void lustre_msg_set_tag(struct lustre_msg *msg, __u16 tag) +{ + switch (msg->lm_magic) { + case LUSTRE_MSG_MAGIC_V2: { + struct ptlrpc_body *pb = lustre_msg_ptlrpc_body(msg); + + LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg); + pb->pb_tag = tag; + return; + } + default: + LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); + } +} +EXPORT_SYMBOL(lustre_msg_set_tag); + void lustre_msg_set_versions(struct lustre_msg *msg, __u64 *versions) { switch (msg->lm_magic) { @@ -1442,7 +1477,7 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *b) __swab32s(&b->pb_opc); __swab32s(&b->pb_status); __swab64s(&b->pb_last_xid); - __swab64s(&b->pb_last_seen); + __swab16s(&b->pb_tag); __swab64s(&b->pb_last_committed); __swab64s(&b->pb_transno); __swab32s(&b->pb_flags); @@ -1456,6 +1491,8 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *b) __swab64s(&b->pb_pre_versions[1]); __swab64s(&b->pb_pre_versions[2]); __swab64s(&b->pb_pre_versions[3]); + CLASSERT(offsetof(typeof(*b), pb_padding0) != 0); + CLASSERT(offsetof(typeof(*b), pb_padding1) != 0); CLASSERT(offsetof(typeof(*b), pb_padding) != 0); /* While we need to maintain compatibility between * clients and servers without ptlrpc_body_v2 (< 2.3) diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index fabfe943c614..95b991d6f8ea 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -635,10 +635,18 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct ptlrpc_body_v3, pb_last_xid)); LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_xid) == 8, "found %lld\n", (long long)(int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_xid)); - LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_last_seen) == 32, "found %lld\n", - (long long)(int)offsetof(struct ptlrpc_body_v3, pb_last_seen)); - LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_seen) == 8, "found %lld\n", - (long long)(int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_seen)); + LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_tag) == 32, "found %lld\n", + (long long)(int)offsetof(struct ptlrpc_body_v3, pb_tag)); + LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_tag) == 2, "found %lld\n", + (long long)(int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_tag)); + LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_padding0) == 34, "found %lld\n", + (long long)(int)offsetof(struct ptlrpc_body_v3, pb_padding0)); + LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding0) == 2, "found %lld\n", + (long long)(int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding0)); + LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_padding1) == 36, "found %lld\n", + (long long)(int)offsetof(struct ptlrpc_body_v3, pb_padding1)); + LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding1) == 4, "found %lld\n", + (long long)(int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding1)); LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_last_committed) == 40, "found %lld\n", (long long)(int)offsetof(struct ptlrpc_body_v3, pb_last_committed)); LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_committed) == 8, "found %lld\n", @@ -713,10 +721,18 @@ void lustre_assert_wire_constants(void) (int)offsetof(struct ptlrpc_body_v3, pb_last_xid), (int)offsetof(struct ptlrpc_body_v2, pb_last_xid)); LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_xid) == (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_last_xid), "%d != %d\n", (int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_xid), (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_last_xid)); - LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_last_seen) == (int)offsetof(struct ptlrpc_body_v2, pb_last_seen), "%d != %d\n", - (int)offsetof(struct ptlrpc_body_v3, pb_last_seen), (int)offsetof(struct ptlrpc_body_v2, pb_last_seen)); - LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_seen) == (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_last_seen), "%d != %d\n", - (int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_seen), (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_last_seen)); + LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_tag) == (int)offsetof(struct ptlrpc_body_v2, pb_tag), "%d != %d\n", + (int)offsetof(struct ptlrpc_body_v3, pb_tag), (int)offsetof(struct ptlrpc_body_v2, pb_tag)); + LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_tag) == (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_tag), "%d != %d\n", + (int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_tag), (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_tag)); + LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_padding0) == (int)offsetof(struct ptlrpc_body_v2, pb_padding0), "%d != %d\n", + (int)offsetof(struct ptlrpc_body_v3, pb_padding0), (int)offsetof(struct ptlrpc_body_v2, pb_padding0)); + LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding0) == (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_padding0), "%d != %d\n", + (int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding0), (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_padding0)); + LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_padding1) == (int)offsetof(struct ptlrpc_body_v2, pb_padding1), "%d != %d\n", + (int)offsetof(struct ptlrpc_body_v3, pb_padding1), (int)offsetof(struct ptlrpc_body_v2, pb_padding1)); + LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding1) == (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_padding1), "%d != %d\n", + (int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding1), (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_padding1)); LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_last_committed) == (int)offsetof(struct ptlrpc_body_v2, pb_last_committed), "%d != %d\n", (int)offsetof(struct ptlrpc_body_v3, pb_last_committed), (int)offsetof(struct ptlrpc_body_v2, pb_last_committed)); LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_last_committed) == (int)sizeof(((struct ptlrpc_body_v2 *)0)->pb_last_committed), "%d != %d\n", -- cgit v1.2.3 From db431dad75198b03ba47769b920843b4557c02cd Mon Sep 17 00:00:00 2001 From: Wu Libin Date: Sun, 2 Oct 2016 22:28:11 -0400 Subject: staging: lustre: osc: fix bug when setting max_pages_per_rpc After setting like "lctl set_param -P osc.*.max_pages_per_rpc", it is possible that the function osc_obd_max_pages_per_rpc_seq_write will be called before ocd_brw_size has been set when mount. ocd_brw_size is meaningless when it is zero. So it should not be the limit at that time. Signed-off-by: Wu Libin Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6421 Reviewed-on: http://review.whamcloud.com/14333 Reviewed-by: Emoly Liu Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/lproc_osc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index f0062d44ee03..a837362d903d 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -585,7 +585,8 @@ static ssize_t max_pages_per_rpc_store(struct kobject *kobj, chunk_mask = ~((1 << (cli->cl_chunkbits - PAGE_SHIFT)) - 1); /* max_pages_per_rpc must be chunk aligned */ val = (val + ~chunk_mask) & chunk_mask; - if (val == 0 || val > ocd->ocd_brw_size >> PAGE_SHIFT) { + if (!val || (ocd->ocd_brw_size && + val > ocd->ocd_brw_size >> PAGE_SHIFT)) { return -ERANGE; } spin_lock(&cli->cl_loi_list_lock); -- cgit v1.2.3 From 594efc4244b0ccd73d0bebf86db3261c3a951f9d Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Sun, 2 Oct 2016 22:28:12 -0400 Subject: staging: lustre: ldlm: Do not use cbpending for group locks Currently, the CBPENDING flag is set on group locks when the osc lock above them is released (osc_cancel_base). This results in a situation where a new group lock request on a resource does not match an existing group lock because LDLM_FL_CBPENDING is set on the existing lock. So two group locks are granted on the same resource, which is not valid, since a given client can only have one group lock on a particular resource. Since group locks are manually released and not called back like other LDLM locks, the CBPENDING flag doesn't make sense. Since they must be manually released, they also cannot go in the LDLM LRU cache and must be fully released immediately once they are no longer in use. This was previously accomplished by setting CBPENDING when the corresponding osc lock is released, but as noted above, this prevents the group lock matching some future lock requests. This patch uses the fact that group locks have an l_writers reference which they keep until they are manually released, so we remove them when they have no more reader or writer references, without checking cbpending. Signed-off-by: Patrick Farrell Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6368 Reviewed-on: http://review.whamcloud.com/14093 Reviewed-by: frank zago Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 11 +++++++---- drivers/staging/lustre/lustre/osc/osc_internal.h | 1 - drivers/staging/lustre/lustre/osc/osc_lock.c | 2 +- drivers/staging/lustre/lustre/osc/osc_request.c | 10 ---------- 4 files changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index ace8cb220c7f..cc116bae83d2 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -784,11 +784,16 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode) } if (!lock->l_readers && !lock->l_writers && - ldlm_is_cbpending(lock)) { + (ldlm_is_cbpending(lock) || lock->l_req_mode == LCK_GROUP)) { /* If we received a blocked AST and this was the last reference, * run the callback. + * Group locks are special: + * They must not go in LRU, but they are not called back + * like non-group locks, instead they are manually released. + * They have an l_writers reference which they keep until + * they are manually released, so we remove them when they have + * no more reader or writer references. - LU-6368 */ - LDLM_DEBUG(lock, "final decref done on cbpending lock"); LDLM_LOCK_GET(lock); /* dropped by bl thread */ @@ -844,8 +849,6 @@ EXPORT_SYMBOL(ldlm_lock_decref); * Decrease reader/writer refcount for LDLM lock with handle * \a lockh and mark it for subsequent cancellation once r/w refcount * drops to zero instead of putting into LRU. - * - * Typical usage is for GROUP locks which we cannot allow to be cached. */ void ldlm_lock_decref_and_cancel(const struct lustre_handle *lockh, __u32 mode) { diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 90ea0d16b3c5..64684c4a8d51 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -112,7 +112,6 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, osc_enqueue_upcall_f upcall, void *cookie, struct ldlm_enqueue_info *einfo, struct ptlrpc_request_set *rqset, int async, int agl); -int osc_cancel_base(struct lustre_handle *lockh, __u32 mode); int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id, __u32 type, ldlm_policy_data_t *policy, __u32 mode, diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index a42cb9871152..45d5e6d6325b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -1009,7 +1009,7 @@ static void osc_lock_detach(const struct lu_env *env, struct osc_lock *olck) if (olck->ols_hold) { olck->ols_hold = 0; - osc_cancel_base(&olck->ols_handle, olck->ols_einfo.ei_mode); + ldlm_lock_decref(&olck->ols_handle, olck->ols_einfo.ei_mode); olck->ols_handle.cookie = 0ULL; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index de2f52269b26..21cd48b0bcbc 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2336,16 +2336,6 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id, return rc; } -int osc_cancel_base(struct lustre_handle *lockh, __u32 mode) -{ - if (unlikely(mode == LCK_GROUP)) - ldlm_lock_decref_and_cancel(lockh, mode); - else - ldlm_lock_decref(lockh, mode); - - return 0; -} - static int osc_statfs_interpret(const struct lu_env *env, struct ptlrpc_request *req, struct osc_async_args *aa, int rc) -- cgit v1.2.3 From e6104c874cd2b1d2aad8d1a1dd271a79aab72011 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sun, 2 Oct 2016 22:28:13 -0400 Subject: staging: lustre: ptlrpc: remove old protocol compatibility Some old protocol compatibility workarounds are still present in master that should have been removed when LUSTRE_MSG_MAGIC_V1 was. In particular, the process for upgrading LUSTRE_MSG_MAGIC_V1 to LUSTRE_MSG_MAGIC_V2 had the client to connect to the server with the V1 protocol with op_flag=MSG_CONNECT_NEXT_VER set, and if the server supported the V2 protocol it would reply with LUSTRE_MSG_MAGIC_V2. This ensured that if the new client connected to an old server the connection would be allowed. However, even with V1 protocol support removed, the 2.x clients are still connecting with NEXT_VER set. In b1_8 this flag was contingent on LUSTRE_MSG_MAGIC_V1 being used, which is how it should have been in 2.x as well. A few other cleanups are be done at the same time: - disallow 1.8 clients (or at least those that don't understand OBD_CONNECT_FULL20) so we can remove workarounds for 1.8 clients - remove support for pre-2.1 DLM flock lock handling - don't workaround the lack of MDS_ATTR_xTIME_SET flags in setattr - always set MSGHDR_CKSUM_INCOMPAT18 (it can eventually be removed) Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6349 Reviewed-on: http://review.whamcloud.com/14006 Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Liang Zhen Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 18 ++---------------- drivers/staging/lustre/lustre/ldlm/ldlm_internal.h | 7 ++----- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 19 +++---------------- drivers/staging/lustre/lustre/ptlrpc/import.c | 11 ++--------- 4 files changed, 9 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 861f36f039b5..98838e7b4e79 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -612,22 +612,8 @@ granted: } EXPORT_SYMBOL(ldlm_flock_completion_ast); -void ldlm_flock_policy_wire18_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy) -{ - memset(lpolicy, 0, sizeof(*lpolicy)); - lpolicy->l_flock.start = wpolicy->l_flock.lfw_start; - lpolicy->l_flock.end = wpolicy->l_flock.lfw_end; - lpolicy->l_flock.pid = wpolicy->l_flock.lfw_pid; - /* Compat code, old clients had no idea about owner field and - * relied solely on pid for ownership. Introduced in LU-104, 2.1, - * April 2011 - */ - lpolicy->l_flock.owner = wpolicy->l_flock.lfw_pid; -} - -void ldlm_flock_policy_wire21_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy) +void ldlm_flock_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, + ldlm_policy_data_t *lpolicy) { memset(lpolicy, 0, sizeof(*lpolicy)); lpolicy->l_flock.start = wpolicy->l_flock.lfw_start; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index 5e82cfc245b2..0099ff376ad9 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -329,10 +329,7 @@ void ldlm_extent_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, ldlm_policy_data_t *lpolicy); void ldlm_extent_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, ldlm_wire_policy_data_t *wpolicy); -void ldlm_flock_policy_wire18_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy); -void ldlm_flock_policy_wire21_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy); - +void ldlm_flock_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, + ldlm_policy_data_t *lpolicy); void ldlm_flock_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, ldlm_wire_policy_data_t *wpolicy); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index cc116bae83d2..22b4a52c4711 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -63,17 +63,10 @@ static char *ldlm_typename[] = { [LDLM_IBITS] = "IBT", }; -static ldlm_policy_wire_to_local_t ldlm_policy_wire18_to_local[] = { +static ldlm_policy_wire_to_local_t ldlm_policy_wire_to_local[] = { [LDLM_PLAIN - LDLM_MIN_TYPE] = ldlm_plain_policy_wire_to_local, [LDLM_EXTENT - LDLM_MIN_TYPE] = ldlm_extent_policy_wire_to_local, - [LDLM_FLOCK - LDLM_MIN_TYPE] = ldlm_flock_policy_wire18_to_local, - [LDLM_IBITS - LDLM_MIN_TYPE] = ldlm_ibits_policy_wire_to_local, -}; - -static ldlm_policy_wire_to_local_t ldlm_policy_wire21_to_local[] = { - [LDLM_PLAIN - LDLM_MIN_TYPE] = ldlm_plain_policy_wire_to_local, - [LDLM_EXTENT - LDLM_MIN_TYPE] = ldlm_extent_policy_wire_to_local, - [LDLM_FLOCK - LDLM_MIN_TYPE] = ldlm_flock_policy_wire21_to_local, + [LDLM_FLOCK - LDLM_MIN_TYPE] = ldlm_flock_policy_wire_to_local, [LDLM_IBITS - LDLM_MIN_TYPE] = ldlm_ibits_policy_wire_to_local, }; @@ -106,14 +99,8 @@ void ldlm_convert_policy_to_local(struct obd_export *exp, enum ldlm_type type, ldlm_policy_data_t *lpolicy) { ldlm_policy_wire_to_local_t convert; - int new_client; - /** some badness for 2.0.0 clients, but 2.0.0 isn't supported */ - new_client = (exp_connect_flags(exp) & OBD_CONNECT_FULL20) != 0; - if (new_client) - convert = ldlm_policy_wire21_to_local[type - LDLM_MIN_TYPE]; - else - convert = ldlm_policy_wire18_to_local[type - LDLM_MIN_TYPE]; + convert = ldlm_policy_wire_to_local[type - LDLM_MIN_TYPE]; convert(wpolicy, lpolicy); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index a23d0a05b574..b2457846b37d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -691,8 +691,6 @@ int ptlrpc_connect_import(struct obd_import *imp) request->rq_timeout = INITIAL_CONNECT_TIMEOUT; lustre_msg_set_timeout(request->rq_reqmsg, request->rq_timeout); - lustre_msg_add_op_flags(request->rq_reqmsg, MSG_CONNECT_NEXT_VER); - request->rq_no_resend = 1; request->rq_no_delay = 1; request->rq_send_state = LUSTRE_IMP_CONNECTING; @@ -873,8 +871,7 @@ static int ptlrpc_connect_set_flags(struct obd_import *imp, ocd->ocd_connect_flags; } - if ((ocd->ocd_connect_flags & OBD_CONNECT_AT) && - (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) + if (ocd->ocd_connect_flags & OBD_CONNECT_AT) /* * We need a per-message support flag, because * a. we don't know if the incoming connect reply @@ -889,11 +886,7 @@ static int ptlrpc_connect_set_flags(struct obd_import *imp, else imp->imp_msghdr_flags &= ~MSGHDR_AT_SUPPORT; - if ((ocd->ocd_connect_flags & OBD_CONNECT_FULL20) && - (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) - imp->imp_msghdr_flags |= MSGHDR_CKSUM_INCOMPAT18; - else - imp->imp_msghdr_flags &= ~MSGHDR_CKSUM_INCOMPAT18; + imp->imp_msghdr_flags |= MSGHDR_CKSUM_INCOMPAT18; return 0; } -- cgit v1.2.3 From 8a4939e5fa69cae4d2ed35581a33c69b34ad9721 Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Sun, 2 Oct 2016 22:28:14 -0400 Subject: staging: lustre: llite: Report first encountered error Failures in ll_ioc_copy_{start,end} are reported to coordinator. The return code delivered to the caller should indicate what this error was, not whether coordinator was successfully notified. Signed-off-by: Henri Doreau Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5683 Reviewed-on: http://review.whamcloud.com/14335 Reviewed-by: Jinshan Xiong Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 36413273a86b..68675ebf5d56 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -681,7 +681,7 @@ static int ll_ioc_copy_start(struct super_block *sb, struct hsm_copy *copy) { struct ll_sb_info *sbi = ll_s2sbi(sb); struct hsm_progress_kernel hpk; - int rc; + int rc2, rc = 0; /* Forge a hsm_progress based on data from copy. */ hpk.hpk_fid = copy->hc_hai.hai_fid; @@ -731,10 +731,10 @@ progress: /* On error, the request should be considered as completed */ if (hpk.hpk_errval > 0) hpk.hpk_flags |= HP_FLAG_COMPLETED; - rc = obd_iocontrol(LL_IOC_HSM_PROGRESS, sbi->ll_md_exp, sizeof(hpk), - &hpk, NULL); + rc2 = obd_iocontrol(LL_IOC_HSM_PROGRESS, sbi->ll_md_exp, sizeof(hpk), + &hpk, NULL); - return rc; + return rc ? rc : rc2; } /** @@ -756,7 +756,7 @@ static int ll_ioc_copy_end(struct super_block *sb, struct hsm_copy *copy) { struct ll_sb_info *sbi = ll_s2sbi(sb); struct hsm_progress_kernel hpk; - int rc; + int rc2, rc = 0; /* If you modify the logic here, also check llapi_hsm_copy_end(). */ /* Take care: copy->hc_hai.hai_action, len, gid and data are not @@ -830,10 +830,10 @@ static int ll_ioc_copy_end(struct super_block *sb, struct hsm_copy *copy) } progress: - rc = obd_iocontrol(LL_IOC_HSM_PROGRESS, sbi->ll_md_exp, sizeof(hpk), - &hpk, NULL); + rc2 = obd_iocontrol(LL_IOC_HSM_PROGRESS, sbi->ll_md_exp, sizeof(hpk), + &hpk, NULL); - return rc; + return rc ? rc : rc2; } static int copy_and_ioctl(int cmd, struct obd_export *exp, -- cgit v1.2.3 From 0bce7b932aded4d24690f990cb6663b9c5435121 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Sun, 2 Oct 2016 22:28:15 -0400 Subject: staging: lustre: ptlrpc: dont take unwrap in req_waittime calculation Do not take unwrap time in req_waittime calculation on client part as decryption is not related to request service time. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6356 Reviewed-on: http://review.whamcloud.com/14404 Reviewed-by: Dmitry Eremin Reviewed-by: Jeremy Filizetti Reviewed-by: Andrew Perepechko Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 8c51d51a678b..fa4d3c9836f8 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1206,6 +1206,10 @@ static int after_reply(struct ptlrpc_request *req) return 0; } + ktime_get_real_ts64(&work_start); + timediff = (work_start.tv_sec - req->rq_sent_tv.tv_sec) * USEC_PER_SEC + + (work_start.tv_nsec - req->rq_sent_tv.tv_nsec) / + NSEC_PER_USEC; /* * NB Until this point, the whole of the incoming message, * including buflens, status etc is in the sender's byte order. @@ -1258,10 +1262,6 @@ static int after_reply(struct ptlrpc_request *req) return 0; } - ktime_get_real_ts64(&work_start); - timediff = (work_start.tv_sec - req->rq_sent_tv.tv_sec) * USEC_PER_SEC + - (work_start.tv_nsec - req->rq_sent_tv.tv_nsec) / - NSEC_PER_USEC; if (obd->obd_svc_stats) { lprocfs_counter_add(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, timediff); -- cgit v1.2.3 From a823acf590343f1cd15b305f860271caf31d1674 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:16 -0400 Subject: staging: lustre: remove Size on MDS support Remove unused definitions related to Size on MDS support from lustre/include/lustre/lustre_idl.h. Remove unused code from several places in lustre/. Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6047 Reviewed-on: http://review.whamcloud.com/13443 Reviewed-by: Andreas Dilger Reviewed-by: Mike Pershin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 41 ++++----------- .../lustre/lustre/include/lustre_req_layout.h | 1 - drivers/staging/lustre/lustre/include/obd.h | 8 +++ .../staging/lustre/lustre/include/obd_support.h | 4 +- drivers/staging/lustre/lustre/mdc/mdc_lib.c | 7 +-- drivers/staging/lustre/lustre/mdc/mdc_request.c | 4 +- drivers/staging/lustre/lustre/ptlrpc/layout.c | 6 --- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 7 +-- drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 58 ++++++---------------- 9 files changed, 46 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 4f6eeec44bcd..17feb71ea485 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -310,7 +310,7 @@ static inline int range_compare_loc(const struct lu_seq_range *r1, */ enum lma_compat { LMAC_HSM = 0x00000001, - LMAC_SOM = 0x00000002, +/* LMAC_SOM = 0x00000002, obsolete since 2.8.0 */ LMAC_NOT_IN_OI = 0x00000004, /* the object does NOT need OI mapping */ LMAC_FID_ON_OST = 0x00000008, /* For OST-object, its OI mapping is * under /O//d. @@ -1923,7 +1923,7 @@ enum mds_cmd { MDS_PIN = 42, /* obsolete, never used in a release */ MDS_UNPIN = 43, /* obsolete, never used in a release */ MDS_SYNC = 44, - MDS_DONE_WRITING = 45, + MDS_DONE_WRITING = 45, /* obsolete since 2.8.0 */ MDS_SET_INFO = 46, MDS_QUOTACHECK = 47, MDS_QUOTACTL = 48, @@ -2021,24 +2021,6 @@ enum { #define MDS_STATUS_CONN 1 #define MDS_STATUS_LOV 2 -/* mdt_thread_info.mti_flags. */ -enum md_op_flags { - /* The flag indicates Size-on-MDS attributes are changed. */ - MF_SOM_CHANGE = (1 << 0), - /* Flags indicates an epoch opens or closes. */ - MF_EPOCH_OPEN = (1 << 1), - MF_EPOCH_CLOSE = (1 << 2), - MF_MDC_CANCEL_FID1 = (1 << 3), - MF_MDC_CANCEL_FID2 = (1 << 4), - MF_MDC_CANCEL_FID3 = (1 << 5), - MF_MDC_CANCEL_FID4 = (1 << 6), - /* There is a pending attribute update. */ - MF_SOM_AU = (1 << 7), - /* Cancel OST locks while getattr OST attributes. */ - MF_GETATTR_LOCK = (1 << 8), - MF_GET_MDT_IDX = (1 << 9), -}; - #define LUSTRE_BFLAG_UNCOMMITTED_WRITES 0x1 /* these should be identical to their EXT4_*_FL counterparts, they are @@ -2123,10 +2105,10 @@ struct mdt_body { void lustre_swab_mdt_body(struct mdt_body *b); struct mdt_ioepoch { - struct lustre_handle handle; - __u64 ioepoch; - __u32 flags; - __u32 padding; + struct lustre_handle mio_handle; + __u64 mio_unused1; /* was ioepoch */ + __u32 mio_unused2; /* was flags */ + __u32 mio_padding; }; void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b); @@ -2195,12 +2177,9 @@ void lustre_swab_mdt_rec_setattr(struct mdt_rec_setattr *sa); #define MDS_FMODE_CLOSED 00000000 #define MDS_FMODE_EXEC 00000004 -/* IO Epoch is opened on a closed file. */ -#define MDS_FMODE_EPOCH 01000000 -/* IO Epoch is opened on a file truncate. */ -#define MDS_FMODE_TRUNC 02000000 -/* Size-on-MDS Attribute Update is pending. */ -#define MDS_FMODE_SOM 04000000 +/* MDS_FMODE_EPOCH 01000000 obsolete since 2.8.0 */ +/* MDS_FMODE_TRUNC 02000000 obsolete since 2.8.0 */ +/* MDS_FMODE_SOM 04000000 obsolete since 2.8.0 */ #define MDS_OPEN_CREATED 00000010 #define MDS_OPEN_CROSS 00000020 @@ -2246,7 +2225,7 @@ enum mds_op_bias { MDS_CROSS_REF = 1 << 1, MDS_VTX_BYPASS = 1 << 2, MDS_PERM_BYPASS = 1 << 3, - MDS_SOM = 1 << 4, +/* MDS_SOM = 1 << 4, obsolete since 2.8.0 */ MDS_QUOTA_IGNORE = 1 << 5, MDS_CLOSE_CLEANUP = 1 << 6, MDS_KEEP_ORPHAN = 1 << 7, diff --git a/drivers/staging/lustre/lustre/include/lustre_req_layout.h b/drivers/staging/lustre/lustre/include/lustre_req_layout.h index a13558e53274..dd8717eca859 100644 --- a/drivers/staging/lustre/lustre/include/lustre_req_layout.h +++ b/drivers/staging/lustre/lustre/include/lustre_req_layout.h @@ -154,7 +154,6 @@ extern struct req_format RQF_MDS_DISCONNECT; extern struct req_format RQF_MDS_GET_INFO; extern struct req_format RQF_MDS_READPAGE; extern struct req_format RQF_MDS_WRITEPAGE; -extern struct req_format RQF_MDS_DONE_WRITING; extern struct req_format RQF_MDS_REINT; extern struct req_format RQF_MDS_REINT_CREATE; extern struct req_format RQF_MDS_REINT_CREATE_ACL; diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index fe05cc6568f3..5c31376200ee 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -755,6 +755,14 @@ static inline int it_to_lock_mode(struct lookup_intent *it) return -EINVAL; } +enum md_op_flags { + MF_MDC_CANCEL_FID1 = BIT(0), + MF_MDC_CANCEL_FID2 = BIT(1), + MF_MDC_CANCEL_FID3 = BIT(2), + MF_MDC_CANCEL_FID4 = BIT(3), + MF_GET_MDT_IDX = BIT(4), +}; + enum md_cli_flags { CLI_SET_MEA = BIT(0), CLI_RM_ENTRY = BIT(1), diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index b346a7f10aa4..9d2d6f8d7926 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -172,8 +172,8 @@ extern char obd_jobid_var[]; #define OBD_FAIL_MDS_ALL_REQUEST_NET 0x123 #define OBD_FAIL_MDS_SYNC_NET 0x124 #define OBD_FAIL_MDS_SYNC_PACK 0x125 -#define OBD_FAIL_MDS_DONE_WRITING_NET 0x126 -#define OBD_FAIL_MDS_DONE_WRITING_PACK 0x127 +/* OBD_FAIL_MDS_DONE_WRITING_NET 0x126 obsolete since 2.8.0 */ +/* OBD_FAIL_MDS_DONE_WRITING_PACK 0x127 obsolete since 2.8.0 */ #define OBD_FAIL_MDS_ALLOC_OBDO 0x128 #define OBD_FAIL_MDS_PAUSE_OPEN 0x129 #define OBD_FAIL_MDS_STATFS_LCW_SLEEP 0x12a diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 709440b62323..19250722083a 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -301,9 +301,10 @@ static void mdc_setattr_pack_rec(struct mdt_rec_setattr *rec, static void mdc_ioepoch_pack(struct mdt_ioepoch *epoch, struct md_op_data *op_data) { - memcpy(&epoch->handle, &op_data->op_handle, sizeof(epoch->handle)); - epoch->ioepoch = 0; - epoch->flags = 0; + epoch->mio_handle = op_data->op_handle; + epoch->mio_unused1 = 0; + epoch->mio_unused2 = 0; + epoch->mio_padding = 0; } void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 3ef1bae27896..d996326d70d6 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -567,9 +567,9 @@ void mdc_replay_open(struct ptlrpc_request *req) LASSERT(epoch); if (och) - LASSERT(!memcmp(&old, &epoch->handle, sizeof(old))); + LASSERT(!memcmp(&old, &epoch->mio_handle, sizeof(old))); DEBUG_REQ(D_HA, close_req, "updating close body with new fh"); - epoch->handle = body->mbo_handle; + epoch->mio_handle = body->mbo_handle; } } diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index 4ea84545ced2..358c124e31ab 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -669,7 +669,6 @@ static struct req_format *req_formats[] = { &RQF_MDS_RELEASE_CLOSE, &RQF_MDS_READPAGE, &RQF_MDS_WRITEPAGE, - &RQF_MDS_DONE_WRITING, &RQF_MDS_REINT, &RQF_MDS_REINT_CREATE, &RQF_MDS_REINT_CREATE_ACL, @@ -1386,11 +1385,6 @@ struct req_format RQF_MDS_RELEASE_CLOSE = mdt_release_close_client, mds_last_unlink_server); EXPORT_SYMBOL(RQF_MDS_RELEASE_CLOSE); -struct req_format RQF_MDS_DONE_WRITING = - DEFINE_REQ_FMT0("MDS_DONE_WRITING", - mdt_close_client, mdt_body_only); -EXPORT_SYMBOL(RQF_MDS_DONE_WRITING); - struct req_format RQF_MDS_READPAGE = DEFINE_REQ_FMT0("MDS_READPAGE", mdt_body_capa, mdt_body_only); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 30556495cd7b..bca781af854b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1715,9 +1715,10 @@ void lustre_swab_mdt_body(struct mdt_body *b) void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b) { /* handle is opaque */ - __swab64s(&b->ioepoch); - __swab32s(&b->flags); - CLASSERT(offsetof(typeof(*b), padding) != 0); + /* mio_handle is opaque */ + CLASSERT(offsetof(typeof(*b), mio_unused1)); + CLASSERT(offsetof(typeof(*b), mio_unused2)); + CLASSERT(offsetof(typeof(*b), mio_padding)); } void lustre_swab_mgs_target_info(struct mgs_target_info *mti) diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 95b991d6f8ea..09c1025e297a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -220,24 +220,6 @@ void lustre_assert_wire_constants(void) (long long)MDS_STATUS_LOV); LASSERTF(LUSTRE_BFLAG_UNCOMMITTED_WRITES == 1, "found %lld\n", (long long)LUSTRE_BFLAG_UNCOMMITTED_WRITES); - LASSERTF(MF_SOM_CHANGE == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)MF_SOM_CHANGE); - LASSERTF(MF_EPOCH_OPEN == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)MF_EPOCH_OPEN); - LASSERTF(MF_EPOCH_CLOSE == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)MF_EPOCH_CLOSE); - LASSERTF(MF_MDC_CANCEL_FID1 == 0x00000008UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID1); - LASSERTF(MF_MDC_CANCEL_FID2 == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID2); - LASSERTF(MF_MDC_CANCEL_FID3 == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID3); - LASSERTF(MF_MDC_CANCEL_FID4 == 0x00000040UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID4); - LASSERTF(MF_SOM_AU == 0x00000080UL, "found 0x%.8xUL\n", - (unsigned)MF_SOM_AU); - LASSERTF(MF_GETATTR_LOCK == 0x00000100UL, "found 0x%.8xUL\n", - (unsigned)MF_GETATTR_LOCK); LASSERTF(MDS_ATTR_MODE == 0x0000000000000001ULL, "found 0x%.16llxULL\n", (long long)MDS_ATTR_MODE); LASSERTF(MDS_ATTR_UID == 0x0000000000000002ULL, "found 0x%.16llxULL\n", @@ -423,8 +405,6 @@ void lustre_assert_wire_constants(void) (unsigned)LMAI_RELEASED); LASSERTF(LMAC_HSM == 0x00000001UL, "found 0x%.8xUL\n", (unsigned)LMAC_HSM); - LASSERTF(LMAC_SOM == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)LMAC_SOM); LASSERTF(LMAC_NOT_IN_OI == 0x00000004UL, "found 0x%.8xUL\n", (unsigned)LMAC_NOT_IN_OI); LASSERTF(LMAC_FID_ON_OST == 0x00000008UL, "found 0x%.8xUL\n", @@ -1883,12 +1863,6 @@ void lustre_assert_wire_constants(void) MDS_FMODE_CLOSED); LASSERTF(MDS_FMODE_EXEC == 000000000004UL, "found 0%.11oUL\n", MDS_FMODE_EXEC); - LASSERTF(MDS_FMODE_EPOCH == 000001000000UL, "found 0%.11oUL\n", - MDS_FMODE_EPOCH); - LASSERTF(MDS_FMODE_TRUNC == 000002000000UL, "found 0%.11oUL\n", - MDS_FMODE_TRUNC); - LASSERTF(MDS_FMODE_SOM == 000004000000UL, "found 0%.11oUL\n", - MDS_FMODE_SOM); LASSERTF(MDS_OPEN_CREATED == 000000000010UL, "found 0%.11oUL\n", MDS_OPEN_CREATED); LASSERTF(MDS_OPEN_CROSS == 000000000020UL, "found 0%.11oUL\n", @@ -1947,22 +1921,22 @@ void lustre_assert_wire_constants(void) /* Checks for struct mdt_ioepoch */ LASSERTF((int)sizeof(struct mdt_ioepoch) == 24, "found %lld\n", (long long)(int)sizeof(struct mdt_ioepoch)); - LASSERTF((int)offsetof(struct mdt_ioepoch, handle) == 0, "found %lld\n", - (long long)(int)offsetof(struct mdt_ioepoch, handle)); - LASSERTF((int)sizeof(((struct mdt_ioepoch *)0)->handle) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_ioepoch *)0)->handle)); - LASSERTF((int)offsetof(struct mdt_ioepoch, ioepoch) == 8, "found %lld\n", - (long long)(int)offsetof(struct mdt_ioepoch, ioepoch)); - LASSERTF((int)sizeof(((struct mdt_ioepoch *)0)->ioepoch) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_ioepoch *)0)->ioepoch)); - LASSERTF((int)offsetof(struct mdt_ioepoch, flags) == 16, "found %lld\n", - (long long)(int)offsetof(struct mdt_ioepoch, flags)); - LASSERTF((int)sizeof(((struct mdt_ioepoch *)0)->flags) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_ioepoch *)0)->flags)); - LASSERTF((int)offsetof(struct mdt_ioepoch, padding) == 20, "found %lld\n", - (long long)(int)offsetof(struct mdt_ioepoch, padding)); - LASSERTF((int)sizeof(((struct mdt_ioepoch *)0)->padding) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_ioepoch *)0)->padding)); + LASSERTF((int)offsetof(struct mdt_ioepoch, mio_handle) == 0, "found %lld\n", + (long long)(int)offsetof(struct mdt_ioepoch, mio_handle)); + LASSERTF((int)sizeof(((struct mdt_ioepoch *)0)->mio_handle) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_ioepoch *)0)->mio_handle)); + LASSERTF((int)offsetof(struct mdt_ioepoch, mio_unused1) == 8, "found %lld\n", + (long long)(int)offsetof(struct mdt_ioepoch, mio_unused1)); + LASSERTF((int)sizeof(((struct mdt_ioepoch *)0)->mio_unused1) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_ioepoch *)0)->mio_unused1)); + LASSERTF((int)offsetof(struct mdt_ioepoch, mio_unused2) == 16, "found %lld\n", + (long long)(int)offsetof(struct mdt_ioepoch, mio_unused2)); + LASSERTF((int)sizeof(((struct mdt_ioepoch *)0)->mio_unused2) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_ioepoch *)0)->mio_unused2)); + LASSERTF((int)offsetof(struct mdt_ioepoch, mio_padding) == 20, "found %lld\n", + (long long)(int)offsetof(struct mdt_ioepoch, mio_padding)); + LASSERTF((int)sizeof(((struct mdt_ioepoch *)0)->mio_padding) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_ioepoch *)0)->mio_padding)); /* Checks for struct mdt_rec_setattr */ LASSERTF((int)sizeof(struct mdt_rec_setattr) == 136, "found %lld\n", -- cgit v1.2.3 From 6ffa4ec96c8c54f2ad893aba6f833f20e9864d32 Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Sun, 2 Oct 2016 22:28:17 -0400 Subject: staging: lustre: mdc: Removed unneeded NULL check Do not bother checking the return value of changelog_kuc_hdr() against NULL since this value was dereferenced earlier. Signed-off-by: Henri Doreau Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4189 Reviewed-on: http://review.whamcloud.com/12919 Reviewed-by: John L. Hammond Reviewed-by: Faccini Bruno Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_request.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index d996326d70d6..206f5d013525 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1867,10 +1867,8 @@ static int mdc_changelog_send_thread(void *csdata) /* Send EOF no matter what our result */ kuch = changelog_kuc_hdr(cs->cs_buf, sizeof(*kuch), cs->cs_flags); - if (kuch) { - kuch->kuc_msgtype = CL_EOF; - libcfs_kkuc_msg_put(cs->cs_fp, kuch); - } + kuch->kuc_msgtype = CL_EOF; + libcfs_kkuc_msg_put(cs->cs_fp, kuch); out: fput(cs->cs_fp); -- cgit v1.2.3 From 7c6564d02a217d666274d7b1a2e1f609a98df5ab Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:18 -0400 Subject: staging: lustre: obd: remove unused LSM parameters Remove unused struct lov_stripe_md * parameters from obd_get_info(), mgc_enqueue(), and osc_brw_prep_request(). Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/13426 Reviewed-by: Andreas Dilger Reviewed-by: Lai Siyao Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 3 +-- drivers/staging/lustre/lustre/include/obd_class.h | 6 ++---- drivers/staging/lustre/lustre/llite/dir.c | 2 +- drivers/staging/lustre/lustre/llite/lcommon_misc.c | 2 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 6 +++--- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 8 +++----- drivers/staging/lustre/lustre/lov/lov_obd.c | 3 +-- drivers/staging/lustre/lustre/mdc/mdc_request.c | 5 ++--- drivers/staging/lustre/lustre/mgc/mgc_request.c | 9 ++++----- drivers/staging/lustre/lustre/obdclass/obd_mount.c | 2 +- drivers/staging/lustre/lustre/osc/osc_request.c | 7 ++----- 11 files changed, 21 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 5c31376200ee..c72a1e179a2d 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -845,8 +845,7 @@ struct obd_ops { int (*iocontrol)(unsigned int cmd, struct obd_export *exp, int len, void *karg, void __user *uarg); int (*get_info)(const struct lu_env *env, struct obd_export *, - __u32 keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm); + __u32 keylen, void *key, __u32 *vallen, void *val); int (*set_info_async)(const struct lu_env *, struct obd_export *, __u32 keylen, void *key, __u32 vallen, void *val, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index b2ced8b1cc8f..7a5d75aa3517 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -415,16 +415,14 @@ static inline int class_devno_max(void) static inline int obd_get_info(const struct lu_env *env, struct obd_export *exp, __u32 keylen, - void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm) + void *key, __u32 *vallen, void *val) { int rc; EXP_CHECK_DT_OP(exp, get_info); EXP_COUNTER_INCREMENT(exp, get_info); - rc = OBP(exp->exp_obd, get_info)(env, exp, keylen, key, vallen, val, - lsm); + rc = OBP(exp->exp_obd, get_info)(env, exp, keylen, key, vallen, val); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 68675ebf5d56..12e9a388ed43 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1535,7 +1535,7 @@ out_quotactl: exp = count ? sbi->ll_md_exp : sbi->ll_dt_exp; vallen = sizeof(count); rc = obd_get_info(NULL, exp, sizeof(KEY_TGT_COUNT), - KEY_TGT_COUNT, &vallen, &count, NULL); + KEY_TGT_COUNT, &vallen, &count); if (rc) { CERROR("get target count failed: %d\n", rc); return rc; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index fb346c12dad2..07d38e55454b 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -54,7 +54,7 @@ int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp) __u16 stripes, def_stripes; rc = obd_get_info(NULL, dt_exp, sizeof(KEY_LOVDESC), KEY_LOVDESC, - &valsize, &desc, NULL); + &valsize, &desc); if (rc) return rc; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index f836c82a0b55..150cd5b8b96a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -285,7 +285,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, size = sizeof(*data); err = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_CONN_DATA), - KEY_CONN_DATA, &size, data, NULL); + KEY_CONN_DATA, &size, data); if (err) { CERROR("%s: Get connect data failed: rc = %d\n", sbi->ll_md_exp->exp_obd->obd_name, err); @@ -563,7 +563,7 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize) *lmmsize = obd_size_diskmd(sbi->ll_dt_exp, NULL); size = sizeof(int); rc = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_MAX_EASIZE), - KEY_MAX_EASIZE, &size, lmmsize, NULL); + KEY_MAX_EASIZE, &size, lmmsize); if (rc) CERROR("Get max mdsize error rc %d\n", rc); @@ -587,7 +587,7 @@ int ll_get_default_mdsize(struct ll_sb_info *sbi, int *lmmsize) size = sizeof(int); rc = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_DEFAULT_EASIZE), - KEY_DEFAULT_EASIZE, &size, lmmsize, NULL); + KEY_DEFAULT_EASIZE, &size, lmmsize); if (rc) CERROR("Get default mdsize error rc %d\n", rc); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index b401ffb14477..7bd7e1585b9c 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2628,14 +2628,12 @@ static int lmv_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) * \param[in] key identifier of key to get value for * \param[in] vallen size of \a val * \param[out] val pointer to storage location for value - * \param[in] lsm optional striping metadata of object * * \retval 0 on success * \retval negative negated errno on failure */ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, - __u32 keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm) + __u32 keylen, void *key, __u32 *vallen, void *val) { struct obd_device *obd; struct lmv_obd *lmv; @@ -2667,7 +2665,7 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, continue; if (!obd_get_info(env, tgt->ltd_exp, keylen, key, - vallen, val, NULL)) + vallen, val)) return 0; } return -EINVAL; @@ -2683,7 +2681,7 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, * desc. */ rc = obd_get_info(env, lmv->tgts[0]->ltd_exp, keylen, key, - vallen, val, NULL); + vallen, val); if (!rc && KEY_IS(KEY_CONN_DATA)) exp->exp_connect_data = *(struct obd_connect_data *)val; return rc; diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 30903fc26fdd..44f53c7c6c8b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1310,8 +1310,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, } static int lov_get_info(const struct lu_env *env, struct obd_export *exp, - __u32 keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm) + __u32 keylen, void *key, __u32 *vallen, void *val) { struct obd_device *obddev = class_exp2obd(exp); struct lov_obd *lov = &obddev->u.lov; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 206f5d013525..7b9fb9026bdf 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1456,7 +1456,7 @@ static int mdc_ioc_fid2path(struct obd_export *exp, struct getinfo_fid2path *gf) /* Val is struct getinfo_fid2path result plus path */ vallen = sizeof(*gf) + gf->gf_pathlen; - rc = obd_get_info(NULL, exp, keylen, key, &vallen, gf, NULL); + rc = obd_get_info(NULL, exp, keylen, key, &vallen, gf); if (rc != 0 && rc != -EREMOTE) goto out; @@ -2436,8 +2436,7 @@ static int mdc_set_info_async(const struct lu_env *env, } static int mdc_get_info(const struct lu_env *env, struct obd_export *exp, - __u32 keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm) + __u32 keylen, void *key, __u32 *vallen, void *val) { int rc = -EINVAL; diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 23374cae5133..1a0e59a6e745 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -887,8 +887,8 @@ static int mgc_set_mgs_param(struct obd_export *exp, } /* Take a config lock so we can get cancel notifications */ -static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm, - __u32 type, ldlm_policy_data_t *policy, __u32 mode, +static int mgc_enqueue(struct obd_export *exp, __u32 type, + ldlm_policy_data_t *policy, __u32 mode, __u64 *flags, void *bl_cb, void *cp_cb, void *gl_cb, void *data, __u32 lvb_len, void *lvb_swabber, struct lustre_handle *lockh) @@ -1059,8 +1059,7 @@ static int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp, } static int mgc_get_info(const struct lu_env *env, struct obd_export *exp, - __u32 keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *unused) + __u32 keylen, void *key, __u32 *vallen, void *val) { int rc = -EINVAL; @@ -1582,7 +1581,7 @@ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld) cld->cld_cfg.cfg_instance, cld->cld_cfg.cfg_last_idx + 1); /* Get the cfg lock on the llog */ - rcl = mgc_enqueue(mgc->u.cli.cl_mgc_mgsexp, NULL, LDLM_PLAIN, NULL, + rcl = mgc_enqueue(mgc->u.cli.cl_mgc_mgsexp, LDLM_PLAIN, NULL, LCK_CR, &flags, NULL, NULL, NULL, cld, 0, NULL, &lockh); if (rcl == 0) { diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 0d3a3b05a637..59fbc29aae94 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -261,7 +261,7 @@ int lustre_start_mgc(struct super_block *sb) rc = obd_get_info(NULL, obd->obd_self_export, strlen(KEY_CONN_DATA), KEY_CONN_DATA, - &vallen, data, NULL); + &vallen, data); LASSERT(rc == 0); has_ir = OCD_HAS_FLAG(data, IMP_RECOV); if (has_ir ^ !(*flags & LMD_FLG_NOIR)) { diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 21cd48b0bcbc..0413b88a128f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1139,8 +1139,7 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count, } static int osc_brw_prep_request(int cmd, struct client_obd *cli, - struct obdo *oa, - struct lov_stripe_md *lsm, u32 page_count, + struct obdo *oa, u32 page_count, struct brw_page **pga, struct ptlrpc_request **reqp, int reserve, @@ -1557,7 +1556,6 @@ static int osc_brw_redo_request(struct ptlrpc_request *request, rc = osc_brw_prep_request(lustre_msg_get_opc(request->rq_reqmsg) == OST_WRITE ? OBD_BRW_WRITE : OBD_BRW_READ, aa->aa_cli, aa->aa_oa, - NULL /* lsm unused by osc currently */, aa->aa_page_count, aa->aa_ppga, &new_req, 0, 1); if (rc) @@ -1902,8 +1900,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, } sort_brw_pages(pga, page_count); - rc = osc_brw_prep_request(cmd, cli, oa, NULL, page_count, - pga, &req, 1, 0); + rc = osc_brw_prep_request(cmd, cli, oa, page_count, pga, &req, 1, 0); if (rc != 0) { CERROR("prep_req failed: %d\n", rc); goto out; -- cgit v1.2.3 From e3d86358071312ba99be648af5528ef588d3b3f8 Mon Sep 17 00:00:00 2001 From: wang di Date: Sun, 2 Oct 2016 22:28:19 -0400 Subject: staging: lustre: mgc: MGC should retry for invalid import After http://review.whamcloud.com/#/c/9967/ is landed, mgc does not wait the import connected(state = FULL), then enqueue and retrieve config log, which will cause the mount process to fail, especially if the mgc is shared by multiple targets. So once mgc enqueue is failed, it will give another chance to wait the import to recover, if the import comes back in time, it will try to enqueue again. Otherwise it will use local config log. Signed-off-by: wang di Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5420 Reviewed-on: http://review.whamcloud.com/11258 Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_ha.h | 1 + drivers/staging/lustre/lustre/mgc/mgc_request.c | 85 +++++++++++++++++++++-- drivers/staging/lustre/lustre/ptlrpc/import.c | 3 +- 3 files changed, 81 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_ha.h b/drivers/staging/lustre/lustre/include/lustre_ha.h index cde7ed702c86..dec1e99d594d 100644 --- a/drivers/staging/lustre/lustre/include/lustre_ha.h +++ b/drivers/staging/lustre/lustre/include/lustre_ha.h @@ -53,6 +53,7 @@ void ptlrpc_activate_import(struct obd_import *imp); void ptlrpc_deactivate_import(struct obd_import *imp); void ptlrpc_invalidate_import(struct obd_import *imp); void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt); +void ptlrpc_pinger_force(struct obd_import *imp); /** @} ha */ diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 1a0e59a6e745..7b5ac4485e3c 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -1552,14 +1552,52 @@ out_free: return rc; } -/** Get a config log from the MGS and process it. - * This func is called for both clients and servers. - * Copy the log locally before parsing it if appropriate (non-MGS server) +static bool mgc_import_in_recovery(struct obd_import *imp) +{ + bool in_recovery = true; + + spin_lock(&imp->imp_lock); + if (imp->imp_state == LUSTRE_IMP_FULL || + imp->imp_state == LUSTRE_IMP_CLOSED) + in_recovery = false; + spin_unlock(&imp->imp_lock); + + return in_recovery; +} + +/** + * Get a configuration log from the MGS and process it. + * + * This function is called for both clients and servers to process the + * configuration log from the MGS. The MGC enqueues a DLM lock on the + * log from the MGS, and if the lock gets revoked the MGC will be notified + * by the lock cancellation callback that the config log has changed, + * and will enqueue another MGS lock on it, and then continue processing + * the new additions to the end of the log. + * + * Since the MGC import is not replayable, if the import is being evicted + * (rcl == -ESHUTDOWN, \see ptlrpc_import_delay_req()), retry to process + * the log until recovery is finished or the import is closed. + * + * Make a local copy of the log before parsing it if appropriate (non-MGS + * server) so that the server can start even when the MGS is down. + * + * There shouldn't be multiple processes running process_log at once -- + * sounds like badness. It actually might be fine, as long as they're not + * trying to update from the same log simultaneously, in which case we + * should use a per-log semaphore instead of cld_lock. + * + * \param[in] mgc MGC device by which to fetch the configuration log + * \param[in] cld log processing state (stored in lock callback data) + * + * \retval 0 on success + * \retval negative errno on failure */ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld) { struct lustre_handle lockh = { 0 }; __u64 flags = LDLM_FL_NO_LRU; + bool retry = false; int rc = 0, rcl; LASSERT(cld); @@ -1569,6 +1607,7 @@ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld) * we're not trying to update from the same log * simultaneously (in which case we should use a per-log sem.) */ +restart: mutex_lock(&cld->cld_lock); if (cld->cld_stopping) { mutex_unlock(&cld->cld_lock); @@ -1592,10 +1631,42 @@ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld) } else { CDEBUG(D_MGC, "Can't get cfg lock: %d\n", rcl); - /* mark cld_lostlock so that it will requeue - * after MGC becomes available. - */ - cld->cld_lostlock = 1; + if (rcl == -ESHUTDOWN && + atomic_read(&mgc->u.cli.cl_mgc_refcount) > 0 && !retry) { + int secs = cfs_time_seconds(obd_timeout); + struct obd_import *imp; + struct l_wait_info lwi; + + mutex_unlock(&cld->cld_lock); + imp = class_exp2cliimp(mgc->u.cli.cl_mgc_mgsexp); + + /* + * Let's force the pinger, and wait the import to be + * connected, note: since mgc import is non-replayable, + * and even the import state is disconnected, it does + * not mean the "recovery" is stopped, so we will keep + * waitting until timeout or the import state is + * FULL or closed + */ + ptlrpc_pinger_force(imp); + + lwi = LWI_TIMEOUT(secs, NULL, NULL); + l_wait_event(imp->imp_recovery_waitq, + !mgc_import_in_recovery(imp), &lwi); + + if (imp->imp_state == LUSTRE_IMP_FULL) { + retry = true; + goto restart; + } else { + mutex_lock(&cld->cld_lock); + cld->cld_lostlock = 1; + } + } else { + /* mark cld_lostlock so that it will requeue + * after MGC becomes available. + */ + cld->cld_lostlock = 1; + } /* Get extra reference, it will be put in requeue thread */ config_log_get(cld); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index b2457846b37d..2bdaf2ba2f16 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -396,7 +396,7 @@ void ptlrpc_activate_import(struct obd_import *imp) } EXPORT_SYMBOL(ptlrpc_activate_import); -static void ptlrpc_pinger_force(struct obd_import *imp) +void ptlrpc_pinger_force(struct obd_import *imp) { CDEBUG(D_HA, "%s: waking up pinger s:%s\n", obd2cli_tgt(imp->imp_obd), ptlrpc_import_state_name(imp->imp_state)); @@ -408,6 +408,7 @@ static void ptlrpc_pinger_force(struct obd_import *imp) if (imp->imp_state != LUSTRE_IMP_CONNECTING) ptlrpc_pinger_wake_up(); } +EXPORT_SYMBOL(ptlrpc_pinger_force); void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt) { -- cgit v1.2.3 From f0cf21abcccca7a2250f4000517081dac7c79b2a Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:20 -0400 Subject: staging: lustre: clio: add CIT_DATA_VERSION and remove IOC_LOV_GETINFO During development a new api, cl_object_obd_info_get() and cl_object_data_version() which then were later replaced by a better solution CIT_DATA_VERSION. For the case of the upstream client their is no point in introducing a API to only have it removed later. Due to the way the patches landed with their dependencies it is not possible to separate out two patches. These two combined patches do the following: * Add a new cl_io type CIT_DATA_VERSION to get file data version. * Remove the unused IOC_LOV_GETINFO ioctl. * Remove ll_glimpse_ioctl() and ll_lsm_getattr(). * Remove the OBD API method obd_getattr_async(). Signed-off-by: John L. Hammond Signed-off-by: Bobi Jam Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5823 Reviewed-on: http://review.whamcloud.com/12748 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6356 Reviewed-on: http://review.whamcloud.com/14649 Reviewed-by: Henri Doreau Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/cl_object.h | 6 + .../lustre/lustre/include/lustre/lustre_user.h | 6 +- drivers/staging/lustre/lustre/include/obd.h | 2 - drivers/staging/lustre/lustre/include/obd_class.h | 13 -- drivers/staging/lustre/lustre/llite/dir.c | 71 ---------- drivers/staging/lustre/lustre/llite/file.c | 125 +++++------------- .../staging/lustre/lustre/llite/llite_internal.h | 2 - drivers/staging/lustre/lustre/lov/lov_internal.h | 4 - drivers/staging/lustre/lustre/lov/lov_io.c | 40 ++++++ drivers/staging/lustre/lustre/lov/lov_merge.c | 50 ------- drivers/staging/lustre/lustre/lov/lov_obd.c | 69 ---------- drivers/staging/lustre/lustre/lov/lov_request.c | 144 --------------------- drivers/staging/lustre/lustre/obdclass/cl_io.c | 1 + drivers/staging/lustre/lustre/osc/osc_io.c | 105 +++++++++++++++ drivers/staging/lustre/lustre/osc/osc_request.c | 59 --------- 15 files changed, 189 insertions(+), 508 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 0b66d027e151..e46a510251ea 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1373,6 +1373,8 @@ enum cl_io_type { CIT_WRITE, /** truncate, utime system calls */ CIT_SETATTR, + /** get data version */ + CIT_DATA_VERSION, /** * page fault handling */ @@ -1777,6 +1779,10 @@ struct cl_io { int sa_stripe_index; const struct lu_fid *sa_parent_fid; } ci_setattr; + struct cl_data_version_io { + u64 dv_data_version; + int dv_flags; + } ci_data_version; struct cl_fault_io { /** page index within file. */ pgoff_t ft_index; diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index dced31f48759..043fc1cc8cb3 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -63,9 +63,13 @@ #if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64) typedef struct stat64 lstat_t; #define lstat_f lstat64 +#define fstat_f fstat64 +#define fstatat_f fstatat64 #else typedef struct stat lstat_t; #define lstat_f lstat +#define fstat_f fstat +#define fstatat_f fstatat #endif #define HAVE_LOV_USER_MDS_DATA @@ -234,7 +238,7 @@ struct ost_id { /* #define LL_IOC_POLL_QUOTACHECK 161 OBD_IOC_POLL_QUOTACHECK */ /* #define LL_IOC_QUOTACTL 162 OBD_IOC_QUOTACTL */ #define IOC_OBD_STATFS _IOWR('f', 164, struct obd_statfs *) -#define IOC_LOV_GETINFO _IOWR('f', 165, struct lov_user_mds_data *) +/* IOC_LOV_GETINFO 165 obsolete */ #define LL_IOC_FLUSHCTX _IOW('f', 166, long) /* LL_IOC_RMTACL 167 obsolete */ #define LL_IOC_GETOBDCOUNT _IOR('f', 168, long) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index c72a1e179a2d..f254d88108c6 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -905,8 +905,6 @@ struct obd_ops { struct obd_info *oinfo, struct obd_trans_info *oti); int (*getattr)(const struct lu_env *env, struct obd_export *exp, struct obd_info *oinfo); - int (*getattr_async)(struct obd_export *exp, struct obd_info *oinfo, - struct ptlrpc_request_set *set); int (*preprw)(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *remote, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 7a5d75aa3517..cb7160e0a99f 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -721,19 +721,6 @@ static inline int obd_getattr(const struct lu_env *env, struct obd_export *exp, return rc; } -static inline int obd_getattr_async(struct obd_export *exp, - struct obd_info *oinfo, - struct ptlrpc_request_set *set) -{ - int rc; - - EXP_CHECK_DT_OP(exp, getattr_async); - EXP_COUNTER_INCREMENT(exp, getattr_async); - - rc = OBP(exp->exp_obd, getattr_async)(exp, oinfo, set); - return rc; -} - static inline int obd_setattr(const struct lu_env *env, struct obd_export *exp, struct obd_info *oinfo, struct obd_trans_info *oti) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 12e9a388ed43..360d97f279ea 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1369,77 +1369,6 @@ out_req: ll_putname(filename); return rc; } - case IOC_LOV_GETINFO: { - struct lov_user_mds_data __user *lumd; - struct lov_stripe_md *lsm; - struct lov_user_md __user *lum; - struct lov_mds_md *lmm; - int lmmsize; - lstat_t st; - - lumd = (struct lov_user_mds_data __user *)arg; - lum = &lumd->lmd_lmm; - - rc = ll_get_max_mdsize(sbi, &lmmsize); - if (rc) - return rc; - - lmm = libcfs_kvzalloc(lmmsize, GFP_NOFS); - if (!lmm) - return -ENOMEM; - if (copy_from_user(lmm, lum, lmmsize)) { - rc = -EFAULT; - goto free_lmm; - } - - switch (lmm->lmm_magic) { - case LOV_USER_MAGIC_V1: - if (cpu_to_le32(LOV_USER_MAGIC_V1) == LOV_USER_MAGIC_V1) - break; - /* swab objects first so that stripes num will be sane */ - lustre_swab_lov_user_md_objects( - ((struct lov_user_md_v1 *)lmm)->lmm_objects, - ((struct lov_user_md_v1 *)lmm)->lmm_stripe_count); - lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lmm); - break; - case LOV_USER_MAGIC_V3: - if (cpu_to_le32(LOV_USER_MAGIC_V3) == LOV_USER_MAGIC_V3) - break; - /* swab objects first so that stripes num will be sane */ - lustre_swab_lov_user_md_objects( - ((struct lov_user_md_v3 *)lmm)->lmm_objects, - ((struct lov_user_md_v3 *)lmm)->lmm_stripe_count); - lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); - break; - default: - rc = -EINVAL; - goto free_lmm; - } - - rc = obd_unpackmd(sbi->ll_dt_exp, &lsm, lmm, lmmsize); - if (rc < 0) { - rc = -ENOMEM; - goto free_lmm; - } - - /* Perform glimpse_size operation. */ - memset(&st, 0, sizeof(st)); - - rc = ll_glimpse_ioctl(sbi, lsm, &st); - if (rc) - goto free_lsm; - - if (copy_to_user(&lumd->lmd_st, &st, sizeof(st))) { - rc = -EFAULT; - goto free_lsm; - } - -free_lsm: - obd_free_memmd(sbi->ll_dt_exp, &lsm); -free_lmm: - kvfree(lmm); - return rc; - } case OBD_IOC_QUOTACHECK: { struct obd_quotactl *oqctl; int error = 0; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index c1db5a17e30c..608e61576f2c 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -865,55 +865,6 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, inode, och, NULL); } -/* Fills the obdo with the attributes for the lsm */ -static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, - struct obdo *obdo, int dv_flags) -{ - struct ptlrpc_request_set *set; - struct obd_info oinfo = { }; - int rc; - - LASSERT(lsm); - - oinfo.oi_md = lsm; - oinfo.oi_oa = obdo; - oinfo.oi_oa->o_oi = lsm->lsm_oi; - oinfo.oi_oa->o_mode = S_IFREG; - oinfo.oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | - OBD_MD_FLSIZE | OBD_MD_FLBLOCKS | - OBD_MD_FLBLKSZ | OBD_MD_FLATIME | - OBD_MD_FLMTIME | OBD_MD_FLCTIME | - OBD_MD_FLGROUP | OBD_MD_FLDATAVERSION; - if (dv_flags & (LL_DV_WR_FLUSH | LL_DV_RD_FLUSH)) { - oinfo.oi_oa->o_valid |= OBD_MD_FLFLAGS; - oinfo.oi_oa->o_flags |= OBD_FL_SRVLOCK; - if (dv_flags & LL_DV_WR_FLUSH) - oinfo.oi_oa->o_flags |= OBD_FL_FLUSH; - } - - set = ptlrpc_prep_set(); - if (!set) { - CERROR("cannot allocate ptlrpc set: rc = %d\n", -ENOMEM); - rc = -ENOMEM; - } else { - rc = obd_getattr_async(exp, &oinfo, set); - if (rc == 0) - rc = ptlrpc_set_wait(set); - ptlrpc_set_destroy(set); - } - if (rc == 0) { - oinfo.oi_oa->o_valid &= (OBD_MD_FLBLOCKS | OBD_MD_FLBLKSZ | - OBD_MD_FLATIME | OBD_MD_FLMTIME | - OBD_MD_FLCTIME | OBD_MD_FLSIZE | - OBD_MD_FLDATAVERSION | OBD_MD_FLFLAGS); - if (dv_flags & LL_DV_WR_FLUSH && - !(oinfo.oi_oa->o_valid & OBD_MD_FLFLAGS && - oinfo.oi_oa->o_flags & OBD_FL_FLUSH)) - return -ENOTSUPP; - } - return rc; -} - int ll_merge_attr(const struct lu_env *env, struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); @@ -970,23 +921,6 @@ out_size_unlock: return rc; } -int ll_glimpse_ioctl(struct ll_sb_info *sbi, struct lov_stripe_md *lsm, - lstat_t *st) -{ - struct obdo obdo = { 0 }; - int rc; - - rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, &obdo, 0); - if (rc == 0) { - st->st_size = obdo.o_size; - st->st_blocks = obdo.o_blocks; - st->st_mtime = obdo.o_mtime; - st->st_atime = obdo.o_atime; - st->st_ctime = obdo.o_ctime; - } - return rc; -} - static bool file_is_noatime(const struct file *file) { const struct vfsmount *mnt = file->f_path.mnt; @@ -1596,45 +1530,50 @@ gf_free: * This value is computed using stripe object version on OST. * Version is computed using server side locking. * - * @param sync if do sync on the OST side; + * @param flags if do sync on the OST side; * 0: no sync * LL_DV_RD_FLUSH: flush dirty pages, LCK_PR on OSTs * LL_DV_WR_FLUSH: drop all caching pages, LCK_PW on OSTs */ int ll_data_version(struct inode *inode, __u64 *data_version, int flags) { - struct lov_stripe_md *lsm = NULL; - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct obdo *obdo = NULL; - int rc; + struct cl_object *obj = ll_i2info(inode)->lli_clob; + struct lu_env *env; + struct cl_io *io; + int refcheck; + int result; - /* If no stripe, we consider version is 0. */ - lsm = ccc_inode_lsm_get(inode); - if (!lsm_has_objects(lsm)) { + /* If no file object initialized, we consider its version is 0. */ + if (!obj) { *data_version = 0; - CDEBUG(D_INODE, "No object for inode\n"); - rc = 0; - goto out; + return 0; } - obdo = kzalloc(sizeof(*obdo), GFP_NOFS); - if (!obdo) { - rc = -ENOMEM; - goto out; - } + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + return PTR_ERR(env); - rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, obdo, flags); - if (rc == 0) { - if (!(obdo->o_valid & OBD_MD_FLDATAVERSION)) - rc = -EOPNOTSUPP; - else - *data_version = obdo->o_data_version; - } + io = vvp_env_thread_io(env); + io->ci_obj = obj; + io->u.ci_data_version.dv_data_version = 0; + io->u.ci_data_version.dv_flags = flags; - kfree(obdo); -out: - ccc_inode_lsm_put(inode, lsm); - return rc; +restart: + if (!cl_io_init(env, io, CIT_DATA_VERSION, io->ci_obj)) + result = cl_io_loop(env, io); + else + result = io->ci_result; + + *data_version = io->u.ci_data_version.dv_data_version; + + cl_io_fini(env, io); + + if (unlikely(io->ci_need_restart)) + goto restart; + + cl_env_put(env, &refcheck); + + return result; } /* diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index e843d326e096..a0aefeb9cbf0 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -741,8 +741,6 @@ enum ldlm_mode ll_take_md_lock(struct inode *inode, __u64 bits, enum ldlm_mode mode); int ll_file_open(struct inode *inode, struct file *file); int ll_file_release(struct inode *inode, struct file *file); -int ll_glimpse_ioctl(struct ll_sb_info *sbi, - struct lov_stripe_md *lsm, lstat_t *st); int ll_release_openhandle(struct inode *, struct lookup_intent *); int ll_md_real_close(struct inode *inode, fmode_t fmode); void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 4743c65c96f6..fffc18ccd97e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -132,8 +132,6 @@ static inline void lov_put_reqset(struct lov_request_set *set) (char *)((lv)->lov_tgts[index]->ltd_uuid.uuid) /* lov_merge.c */ -void lov_merge_attrs(struct obdo *tgt, struct obdo *src, u64 valid, - struct lov_stripe_md *lsm, int stripeno, int *set); int lov_merge_lvb_kms(struct lov_stripe_md *lsm, struct ost_lvb *lvb, __u64 *kms_place); @@ -150,8 +148,6 @@ pgoff_t lov_stripe_pgoff(struct lov_stripe_md *lsm, pgoff_t stripe_index, int stripe); /* lov_request.c */ -int lov_update_common_set(struct lov_request_set *set, - struct lov_request *req, int rc); int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set **reqset); int lov_fini_getattr_set(struct lov_request_set *set); diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 369718e97d43..d6be6136ed54 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -100,6 +100,12 @@ static void lov_io_sub_inherit(struct cl_io *io, struct lov_io *lio, } break; } + case CIT_DATA_VERSION: { + io->u.ci_data_version.dv_data_version = 0; + io->u.ci_data_version.dv_flags = + parent->u.ci_data_version.dv_flags; + break; + } case CIT_FAULT: { struct cl_object *obj = parent->ci_obj; loff_t off = cl_offset(obj, parent->u.ci_fault.ft_index); @@ -339,6 +345,11 @@ static int lov_io_slice_init(struct lov_io *lio, struct lov_object *obj, lio->lis_endpos = OBD_OBJECT_EOF; break; + case CIT_DATA_VERSION: + lio->lis_pos = 0; + lio->lis_endpos = OBD_OBJECT_EOF; + break; + case CIT_FAULT: { pgoff_t index = io->u.ci_fault.ft_index; @@ -516,6 +527,24 @@ static int lov_io_end_wrapper(const struct lu_env *env, struct cl_io *io) return 0; } +static void +lov_io_data_version_end(const struct lu_env *env, const struct cl_io_slice *ios) +{ + struct lov_io *lio = cl2lov_io(env, ios); + struct cl_io *parent = lio->lis_cl.cis_io; + struct lov_io_sub *sub; + + list_for_each_entry(sub, &lio->lis_active, sub_linkage) { + lov_io_end_wrapper(env, sub->sub_io); + + parent->u.ci_data_version.dv_data_version += + sub->sub_io->u.ci_data_version.dv_data_version; + + if (!parent->ci_result) + parent->ci_result = sub->sub_io->ci_result; + } +} + static int lov_io_iter_fini_wrapper(const struct lu_env *env, struct cl_io *io) { cl_io_iter_fini(env, io); @@ -838,6 +867,15 @@ static const struct cl_io_operations lov_io_ops = { .cio_start = lov_io_start, .cio_end = lov_io_end }, + [CIT_DATA_VERSION] = { + .cio_fini = lov_io_fini, + .cio_iter_init = lov_io_iter_init, + .cio_iter_fini = lov_io_iter_fini, + .cio_lock = lov_io_lock, + .cio_unlock = lov_io_unlock, + .cio_start = lov_io_start, + .cio_end = lov_io_data_version_end, + }, [CIT_FAULT] = { .cio_fini = lov_io_fini, .cio_iter_init = lov_io_iter_init, @@ -969,6 +1007,7 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj, break; case CIT_FSYNC: case CIT_SETATTR: + case CIT_DATA_VERSION: result = 1; break; case CIT_WRITE: @@ -1004,6 +1043,7 @@ int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, LASSERTF(0, "invalid type %d\n", io->ci_type); case CIT_MISC: case CIT_FSYNC: + case CIT_DATA_VERSION: result = 1; break; case CIT_SETATTR: diff --git a/drivers/staging/lustre/lustre/lov/lov_merge.c b/drivers/staging/lustre/lustre/lov/lov_merge.c index 674af106b50b..391dfd207177 100644 --- a/drivers/staging/lustre/lustre/lov/lov_merge.c +++ b/drivers/staging/lustre/lustre/lov/lov_merge.c @@ -104,53 +104,3 @@ int lov_merge_lvb_kms(struct lov_stripe_md *lsm, lvb->lvb_ctime = current_ctime; return rc; } - -void lov_merge_attrs(struct obdo *tgt, struct obdo *src, u64 valid, - struct lov_stripe_md *lsm, int stripeno, int *set) -{ - valid &= src->o_valid; - - if (*set) { - tgt->o_valid &= valid; - if (valid & OBD_MD_FLSIZE) { - /* this handles sparse files properly */ - u64 lov_size; - - lov_size = lov_stripe_size(lsm, src->o_size, stripeno); - if (lov_size > tgt->o_size) - tgt->o_size = lov_size; - } - if (valid & OBD_MD_FLBLOCKS) - tgt->o_blocks += src->o_blocks; - if (valid & OBD_MD_FLBLKSZ) - tgt->o_blksize += src->o_blksize; - if (valid & OBD_MD_FLCTIME && tgt->o_ctime < src->o_ctime) - tgt->o_ctime = src->o_ctime; - if (valid & OBD_MD_FLMTIME && tgt->o_mtime < src->o_mtime) - tgt->o_mtime = src->o_mtime; - if (valid & OBD_MD_FLDATAVERSION) - tgt->o_data_version += src->o_data_version; - - /* handle flags */ - if (valid & OBD_MD_FLFLAGS) - tgt->o_flags &= src->o_flags; - else - tgt->o_flags = 0; - } else { - memcpy(tgt, src, sizeof(*tgt)); - tgt->o_oi = lsm->lsm_oi; - tgt->o_valid = valid; - if (valid & OBD_MD_FLSIZE) - tgt->o_size = lov_stripe_size(lsm, src->o_size, - stripeno); - tgt->o_flags = 0; - if (valid & OBD_MD_FLFLAGS) - tgt->o_flags = src->o_flags; - } - - /* data_version needs to be valid on all stripes to be correct! */ - if (!(valid & OBD_MD_FLDATAVERSION)) - tgt->o_valid &= ~OBD_MD_FLDATAVERSION; - - *set += 1; -} diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 44f53c7c6c8b..019fe952396b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -979,74 +979,6 @@ do { \ "%p->lsm_magic=%x\n", (lsmp), (lsmp)->lsm_magic); \ } while (0) -static int lov_getattr_interpret(struct ptlrpc_request_set *rqset, - void *data, int rc) -{ - struct lov_request_set *lovset = (struct lov_request_set *)data; - int err; - - /* don't do attribute merge if this async op failed */ - if (rc) - atomic_set(&lovset->set_completes, 0); - err = lov_fini_getattr_set(lovset); - return rc ? rc : err; -} - -static int lov_getattr_async(struct obd_export *exp, struct obd_info *oinfo, - struct ptlrpc_request_set *rqset) -{ - struct lov_request_set *lovset; - struct lov_obd *lov; - struct lov_request *req; - int rc = 0, err; - - LASSERT(oinfo); - ASSERT_LSM_MAGIC(oinfo->oi_md); - - if (!exp || !exp->exp_obd) - return -ENODEV; - - lov = &exp->exp_obd->u.lov; - - rc = lov_prep_getattr_set(exp, oinfo, &lovset); - if (rc) - return rc; - - CDEBUG(D_INFO, "objid "DOSTID": %ux%u byte stripes\n", - POSTID(&oinfo->oi_md->lsm_oi), oinfo->oi_md->lsm_stripe_count, - oinfo->oi_md->lsm_stripe_size); - - list_for_each_entry(req, &lovset->set_list, rq_link) { - CDEBUG(D_INFO, "objid " DOSTID "[%d] has subobj " DOSTID " at idx%u\n", - POSTID(&oinfo->oi_oa->o_oi), req->rq_stripe, - POSTID(&req->rq_oi.oi_oa->o_oi), req->rq_idx); - rc = obd_getattr_async(lov->lov_tgts[req->rq_idx]->ltd_exp, - &req->rq_oi, rqset); - if (rc) { - CERROR("%s: getattr objid "DOSTID" subobj" - DOSTID" on OST idx %d: rc = %d\n", - exp->exp_obd->obd_name, - POSTID(&oinfo->oi_oa->o_oi), - POSTID(&req->rq_oi.oi_oa->o_oi), - req->rq_idx, rc); - goto out; - } - } - - if (!list_empty(&rqset->set_requests)) { - LASSERT(rc == 0); - LASSERT(!rqset->set_interpret); - rqset->set_interpret = lov_getattr_interpret; - rqset->set_arg = (void *)lovset; - return rc; - } -out: - if (rc) - atomic_set(&lovset->set_completes, 0); - err = lov_fini_getattr_set(lovset); - return rc ? rc : err; -} - int lov_statfs_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { struct lov_request_set *lovset = (struct lov_request_set *)data; @@ -1530,7 +1462,6 @@ static struct obd_ops lov_obd_ops = { .statfs_async = lov_statfs_async, .packmd = lov_packmd, .unpackmd = lov_unpackmd, - .getattr_async = lov_getattr_async, .iocontrol = lov_iocontrol, .get_info = lov_get_info, .set_info_async = lov_set_info_async, diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 048e597fffe6..42e66d1541a6 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -97,22 +97,6 @@ static void lov_update_set(struct lov_request_set *set, wake_up(&set->set_waitq); } -int lov_update_common_set(struct lov_request_set *set, - struct lov_request *req, int rc) -{ - struct lov_obd *lov = &set->set_exp->exp_obd->u.lov; - - lov_update_set(set, req, rc); - - /* grace error on inactive ost */ - if (rc && !(lov->lov_tgts[req->rq_idx] && - lov->lov_tgts[req->rq_idx]->ltd_active)) - rc = 0; - - /* FIXME in raid1 regime, should return 0 */ - return rc; -} - static void lov_set_add_req(struct lov_request *req, struct lov_request_set *set) { @@ -183,134 +167,6 @@ out: return rc; } -static int common_attr_done(struct lov_request_set *set) -{ - struct lov_request *req; - struct obdo *tmp_oa; - int rc = 0, attrset = 0; - - if (!set->set_oi->oi_oa) - return 0; - - if (!atomic_read(&set->set_success)) - return -EIO; - - tmp_oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!tmp_oa) { - rc = -ENOMEM; - goto out; - } - - list_for_each_entry(req, &set->set_list, rq_link) { - if (!req->rq_complete || req->rq_rc) - continue; - if (req->rq_oi.oi_oa->o_valid == 0) /* inactive stripe */ - continue; - lov_merge_attrs(tmp_oa, req->rq_oi.oi_oa, - req->rq_oi.oi_oa->o_valid, - set->set_oi->oi_md, req->rq_stripe, &attrset); - } - if (!attrset) { - CERROR("No stripes had valid attrs\n"); - rc = -EIO; - } - - tmp_oa->o_oi = set->set_oi->oi_oa->o_oi; - memcpy(set->set_oi->oi_oa, tmp_oa, sizeof(*set->set_oi->oi_oa)); -out: - if (tmp_oa) - kmem_cache_free(obdo_cachep, tmp_oa); - return rc; -} - -int lov_fini_getattr_set(struct lov_request_set *set) -{ - int rc = 0; - - if (!set) - return 0; - LASSERT(set->set_exp); - if (atomic_read(&set->set_completes)) - rc = common_attr_done(set); - - lov_put_reqset(set); - - return rc; -} - -/* The callback for osc_getattr_async that finalizes a request info when a - * response is received. - */ -static int cb_getattr_update(void *cookie, int rc) -{ - struct obd_info *oinfo = cookie; - struct lov_request *lovreq; - - lovreq = container_of(oinfo, struct lov_request, rq_oi); - return lov_update_common_set(lovreq->rq_rqset, lovreq, rc); -} - -int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, - struct lov_request_set **reqset) -{ - struct lov_request_set *set; - struct lov_obd *lov = &exp->exp_obd->u.lov; - int rc = 0, i; - - set = kzalloc(sizeof(*set), GFP_NOFS); - if (!set) - return -ENOMEM; - lov_init_set(set); - - set->set_exp = exp; - set->set_oi = oinfo; - - for (i = 0; i < oinfo->oi_md->lsm_stripe_count; i++) { - struct lov_oinfo *loi; - struct lov_request *req; - - loi = oinfo->oi_md->lsm_oinfo[i]; - if (lov_oinfo_is_dummy(loi)) - continue; - - if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) { - CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx); - continue; - } - - req = kzalloc(sizeof(*req), GFP_NOFS); - if (!req) { - rc = -ENOMEM; - goto out_set; - } - - req->rq_stripe = i; - req->rq_idx = loi->loi_ost_idx; - - req->rq_oi.oi_oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!req->rq_oi.oi_oa) { - kfree(req); - rc = -ENOMEM; - goto out_set; - } - memcpy(req->rq_oi.oi_oa, oinfo->oi_oa, - sizeof(*req->rq_oi.oi_oa)); - req->rq_oi.oi_oa->o_oi = loi->loi_oi; - req->rq_oi.oi_cb_up = cb_getattr_update; - - lov_set_add_req(req, set); - } - if (!set->set_count) { - rc = -EIO; - goto out_set; - } - *reqset = set; - return rc; -out_set: - lov_fini_getattr_set(set); - return rc; -} - #define LOV_U64_MAX ((__u64)~0ULL) #define LOV_SUM_MAX(tot, add) \ do { \ diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 577f76edea00..c5621adeef86 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -126,6 +126,7 @@ void cl_io_fini(const struct lu_env *env, struct cl_io *io) switch (io->ci_type) { case CIT_READ: case CIT_WRITE: + case CIT_DATA_VERSION: break; case CIT_FAULT: break; diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index a96addf79c22..b4e062df389f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -606,6 +606,107 @@ static void osc_io_setattr_end(const struct lu_env *env, } } +struct osc_data_version_args { + struct osc_io *dva_oio; +}; + +static int +osc_data_version_interpret(const struct lu_env *env, struct ptlrpc_request *req, + void *arg, int rc) +{ + struct osc_data_version_args *dva = arg; + struct osc_io *oio = dva->dva_oio; + const struct ost_body *body; + + if (rc < 0) + goto out; + + body = req_capsule_server_get(&req->rq_pill, &RMF_OST_BODY); + if (!body) { + rc = -EPROTO; + goto out; + } + + lustre_get_wire_obdo(&req->rq_import->imp_connect_data, &oio->oi_oa, + &body->oa); +out: + oio->oi_cbarg.opc_rc = rc; + complete(&oio->oi_cbarg.opc_sync); + + return 0; +} + +static int osc_io_data_version_start(const struct lu_env *env, + const struct cl_io_slice *slice) +{ + struct cl_data_version_io *dv = &slice->cis_io->u.ci_data_version; + struct osc_io *oio = cl2osc_io(env, slice); + struct osc_async_cbargs *cbargs = &oio->oi_cbarg; + struct osc_object *obj = cl2osc(slice->cis_obj); + struct obd_export *exp = osc_export(obj); + struct lov_oinfo *loi = obj->oo_oinfo; + struct osc_data_version_args *dva; + struct obdo *oa = &oio->oi_oa; + struct ptlrpc_request *req; + struct ost_body *body; + int rc; + + memset(oa, 0, sizeof(*oa)); + oa->o_oi = loi->loi_oi; + oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP; + + if (dv->dv_flags & (LL_DV_RD_FLUSH | LL_DV_WR_FLUSH)) { + oa->o_valid |= OBD_MD_FLFLAGS; + oa->o_flags |= OBD_FL_SRVLOCK; + if (dv->dv_flags & LL_DV_WR_FLUSH) + oa->o_flags |= OBD_FL_FLUSH; + } + + init_completion(&cbargs->opc_sync); + + req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR); + if (!req) + return -ENOMEM; + + rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GETATTR); + if (rc < 0) { + ptlrpc_request_free(req); + return rc; + } + + body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY); + lustre_set_wire_obdo(&req->rq_import->imp_connect_data, &body->oa, oa); + + ptlrpc_request_set_replen(req); + req->rq_interpret_reply = osc_data_version_interpret; + CLASSERT(sizeof(*dva) <= sizeof(req->rq_async_args)); + dva = ptlrpc_req_async_args(req); + dva->dva_oio = oio; + + ptlrpcd_add_req(req); + + return 0; +} + +static void osc_io_data_version_end(const struct lu_env *env, + const struct cl_io_slice *slice) +{ + struct cl_data_version_io *dv = &slice->cis_io->u.ci_data_version; + struct osc_io *oio = cl2osc_io(env, slice); + struct osc_async_cbargs *cbargs = &oio->oi_cbarg; + + wait_for_completion(&cbargs->opc_sync); + + if (cbargs->opc_rc) { + slice->cis_io->ci_result = cbargs->opc_rc; + } else if (!(oio->oi_oa.o_valid & OBD_MD_FLDATAVERSION)) { + slice->cis_io->ci_result = -EOPNOTSUPP; + } else { + dv->dv_data_version = oio->oi_oa.o_data_version; + slice->cis_io->ci_result = 0; + } +} + static int osc_io_read_start(const struct lu_env *env, const struct cl_io_slice *slice) { @@ -759,6 +860,10 @@ static const struct cl_io_operations osc_io_ops = { .cio_start = osc_io_setattr_start, .cio_end = osc_io_setattr_end }, + [CIT_DATA_VERSION] = { + .cio_start = osc_io_data_version_start, + .cio_end = osc_io_data_version_end, + }, [CIT_FAULT] = { .cio_start = osc_io_fault_start, .cio_end = osc_io_end, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 0413b88a128f..2e4d2d5963fc 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -177,64 +177,6 @@ static inline void osc_pack_req_body(struct ptlrpc_request *req, oinfo->oi_oa); } -static int osc_getattr_interpret(const struct lu_env *env, - struct ptlrpc_request *req, - struct osc_async_args *aa, int rc) -{ - struct ost_body *body; - - if (rc != 0) - goto out; - - body = req_capsule_server_get(&req->rq_pill, &RMF_OST_BODY); - if (body) { - CDEBUG(D_INODE, "mode: %o\n", body->oa.o_mode); - lustre_get_wire_obdo(&req->rq_import->imp_connect_data, - aa->aa_oi->oi_oa, &body->oa); - - /* This should really be sent by the OST */ - aa->aa_oi->oi_oa->o_blksize = DT_MAX_BRW_SIZE; - aa->aa_oi->oi_oa->o_valid |= OBD_MD_FLBLKSZ; - } else { - CDEBUG(D_INFO, "can't unpack ost_body\n"); - rc = -EPROTO; - aa->aa_oi->oi_oa->o_valid = 0; - } -out: - rc = aa->aa_oi->oi_cb_up(aa->aa_oi, rc); - return rc; -} - -static int osc_getattr_async(struct obd_export *exp, struct obd_info *oinfo, - struct ptlrpc_request_set *set) -{ - struct ptlrpc_request *req; - struct osc_async_args *aa; - int rc; - - req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR); - if (!req) - return -ENOMEM; - - rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GETATTR); - if (rc) { - ptlrpc_request_free(req); - return rc; - } - - osc_pack_req_body(req, oinfo); - - ptlrpc_request_set_replen(req); - req->rq_interpret_reply = (ptlrpc_interpterer_t)osc_getattr_interpret; - - CLASSERT(sizeof(*aa) <= sizeof(req->rq_async_args)); - aa = ptlrpc_req_async_args(req); - aa->aa_oi = oinfo; - - ptlrpc_set_add_req(set, req); - return 0; -} - static int osc_getattr(const struct lu_env *env, struct obd_export *exp, struct obd_info *oinfo) { @@ -2986,7 +2928,6 @@ static struct obd_ops osc_obd_ops = { .create = osc_create, .destroy = osc_destroy, .getattr = osc_getattr, - .getattr_async = osc_getattr_async, .setattr = osc_setattr, .iocontrol = osc_iocontrol, .set_info_async = osc_set_info_async, -- cgit v1.2.3 From 55554f31e97878133d8b2bdf495504e1c557081c Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:21 -0400 Subject: staging: lustre: lov: add cl_object_layout_get() Add cl_object_layout_get() to return the layout and generation of an object. Replace some direct accesses to object LSM with calls to this function. In ll_getxattr() factor out the LOV xattr specific handling into a new function ll_getxattr_lov() which calls cl_object_layout_get(). In ll_listxattr() call ll_getxattr_lov() to determine if a lustre.lov xattr should be emitted. Add lov_lsm_pack() to generate LOV xattrs from a LSM. Remove the unused functions ccc_inode_lsm_{get,put}() and lov_lsm_get(). Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/13680 Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/cl_object.h | 27 +++ .../lustre/lustre/include/lustre/lustre_user.h | 3 + drivers/staging/lustre/lustre/llite/file.c | 149 +++++++------ drivers/staging/lustre/lustre/llite/lcommon_cl.c | 19 -- .../staging/lustre/lustre/llite/llite_internal.h | 5 - drivers/staging/lustre/lustre/llite/llite_lib.c | 33 ++- drivers/staging/lustre/lustre/llite/vvp_internal.h | 13 -- drivers/staging/lustre/lustre/llite/vvp_object.c | 4 +- drivers/staging/lustre/lustre/llite/xattr.c | 234 +++++++++++---------- drivers/staging/lustre/lustre/lov/lov_internal.h | 2 + drivers/staging/lustre/lustre/lov/lov_object.c | 51 +++-- drivers/staging/lustre/lustre/lov/lov_pack.c | 99 +++++---- drivers/staging/lustre/lustre/obdclass/cl_object.c | 14 ++ 13 files changed, 364 insertions(+), 289 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index e46a510251ea..b80539daeee1 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -301,6 +301,26 @@ enum { OBJECT_CONF_WAIT = 2 }; +enum { + CL_LAYOUT_GEN_NONE = (u32)-2, /* layout lock was cancelled */ + CL_LAYOUT_GEN_EMPTY = (u32)-1, /* for empty layout */ +}; + +struct cl_layout { + /** the buffer to return the layout in lov_mds_md format. */ + struct lu_buf cl_buf; + /** size of layout in lov_mds_md format. */ + size_t cl_size; + /** Layout generation. */ + u32 cl_layout_gen; + /** + * True if this is a released file. + * Temporarily added for released file truncate in ll_setattr_raw(). + * It will be removed later. -Jinshan + */ + bool cl_is_released; +}; + /** * Operations implemented for each cl object layer. * @@ -406,6 +426,11 @@ struct cl_object_operations { int (*coo_fiemap)(const struct lu_env *env, struct cl_object *obj, struct ll_fiemap_info_key *fmkey, struct fiemap *fiemap, size_t *buflen); + /** + * Get layout and generation of the object. + */ + int (*coo_layout_get)(const struct lu_env *env, struct cl_object *obj, + struct cl_layout *layout); }; /** @@ -2200,6 +2225,8 @@ int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj, struct ll_fiemap_info_key *fmkey, struct fiemap *fiemap, size_t *buflen); +int cl_object_layout_get(const struct lu_env *env, struct cl_object *obj, + struct cl_layout *cl); /** * Returns true, iff \a o0 and \a o1 are slices of the same object. diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 043fc1cc8cb3..80fecbac1047 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -346,6 +346,9 @@ enum ll_lease_type { #define LOV_ALL_STRIPES 0xffff /* only valid for directories */ #define LOV_V1_INSANE_STRIPE_COUNT 65532 /* maximum stripe count bz13933 */ +#define XATTR_LUSTRE_PREFIX "lustre." +#define XATTR_LUSTRE_LOV "lustre.lov" + #define lov_user_ost_data lov_user_ost_data_v1 struct lov_user_ost_data_v1 { /* per-stripe data structure */ struct ost_id l_ost_oi; /* OST object ID */ diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 608e61576f2c..2f2dcce28b51 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3145,35 +3145,51 @@ ll_iocontrol_call(struct inode *inode, struct file *file, int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf) { struct ll_inode_info *lli = ll_i2info(inode); + struct cl_object *obj = lli->lli_clob; struct cl_env_nest nest; struct lu_env *env; - int result; + int rc; - if (!lli->lli_clob) + if (!obj) return 0; env = cl_env_nested_get(&nest); if (IS_ERR(env)) return PTR_ERR(env); - result = cl_conf_set(env, lli->lli_clob, conf); - cl_env_nested_put(&nest, env); + rc = cl_conf_set(env, obj, conf); + if (rc < 0) + goto out; if (conf->coc_opc == OBJECT_CONF_SET) { struct ldlm_lock *lock = conf->coc_lock; + struct cl_layout cl = { + .cl_layout_gen = 0, + }; LASSERT(lock); LASSERT(ldlm_has_layout(lock)); - if (result == 0) { - /* it can only be allowed to match after layout is - * applied to inode otherwise false layout would be - * seen. Applying layout should happen before dropping - * the intent lock. - */ - ldlm_lock_allow_match(lock); - } + + /* it can only be allowed to match after layout is + * applied to inode otherwise false layout would be + * seen. Applying layout should happen before dropping + * the intent lock. + */ + ldlm_lock_allow_match(lock); + + rc = cl_object_layout_get(env, obj, &cl); + if (rc < 0) + goto out; + + CDEBUG(D_VFSTRACE, DFID ": layout version change: %u -> %u\n", + PFID(&lli->lli_fid), ll_layout_version_get(lli), + cl.cl_layout_gen); + ll_layout_version_set(lli, cl.cl_layout_gen); + lli->lli_has_smd = lsm_has_objects(conf->u.coc_md->lsm); } - return result; +out: + cl_env_nested_put(&nest, env); + return rc; } /* Fetch layout from MDT with getxattr request, if it's not ready yet */ @@ -3252,7 +3268,7 @@ out: * in this function. */ static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode, - struct inode *inode, __u32 *gen, bool reconf) + struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); @@ -3269,8 +3285,8 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode, LASSERT(lock); LASSERT(ldlm_has_layout(lock)); - LDLM_DEBUG(lock, "File "DFID"(%p) being reconfigured: %d", - PFID(&lli->lli_fid), inode, reconf); + LDLM_DEBUG(lock, "File " DFID "(%p) being reconfigured", + PFID(&lli->lli_fid), inode); /* in case this is a caching lock and reinstate with new inode */ md_set_lock_data(sbi->ll_md_exp, lockh, inode, NULL); @@ -3281,15 +3297,8 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode, /* checking lvb_ready is racy but this is okay. The worst case is * that multi processes may configure the file on the same time. */ - if (lvb_ready || !reconf) { - rc = -ENODATA; - if (lvb_ready) { - /* layout_gen must be valid if layout lock is not - * cancelled and stripe has already set - */ - *gen = ll_layout_version_get(lli); - rc = 0; - } + if (lvb_ready) { + rc = 0; goto out; } @@ -3305,19 +3314,17 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode, if (lock->l_lvb_data) { rc = obd_unpackmd(sbi->ll_dt_exp, &md.lsm, lock->l_lvb_data, lock->l_lvb_len); - if (rc >= 0) { - *gen = LL_LAYOUT_GEN_EMPTY; - if (md.lsm) - *gen = md.lsm->lsm_layout_gen; - rc = 0; - } else { + if (rc < 0) { CERROR("%s: file " DFID " unpackmd error: %d\n", ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), rc); + goto out; } + + LASSERTF(md.lsm, "lvb_data = %p, lvb_len = %u\n", + lock->l_lvb_data, lock->l_lvb_len); + rc = 0; } - if (rc < 0) - goto out; /* set layout to file. Unlikely this will fail as old layout was * surely eliminated @@ -3359,20 +3366,7 @@ out: return rc; } -/** - * This function checks if there exists a LAYOUT lock on the client side, - * or enqueues it if it doesn't have one in cache. - * - * This function will not hold layout lock so it may be revoked any time after - * this function returns. Any operations depend on layout should be redone - * in that case. - * - * This function should be called before lov_io_init() to get an uptodate - * layout version, the caller should save the version number and after IO - * is finished, this function should be called again to verify that layout - * is not changed during IO time. - */ -int ll_layout_refresh(struct inode *inode, __u32 *gen) +static int ll_layout_refresh_locked(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); @@ -3388,17 +3382,6 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) }; int rc; - *gen = ll_layout_version_get(lli); - if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK) || *gen != LL_LAYOUT_GEN_NONE) - return 0; - - /* sanity checks */ - LASSERT(fid_is_sane(ll_inode2fid(inode))); - LASSERT(S_ISREG(inode->i_mode)); - - /* take layout lock mutex to enqueue layout lock exclusively. */ - mutex_lock(&lli->lli_layout_mutex); - again: /* mostly layout lock is caching on the local side, so try to match * it before grabbing layout lock mutex. @@ -3406,20 +3389,16 @@ again: mode = ll_take_md_lock(inode, MDS_INODELOCK_LAYOUT, &lockh, 0, LCK_CR | LCK_CW | LCK_PR | LCK_PW); if (mode != 0) { /* hit cached lock */ - rc = ll_layout_lock_set(&lockh, mode, inode, gen, true); + rc = ll_layout_lock_set(&lockh, mode, inode); if (rc == -EAGAIN) goto again; - - mutex_unlock(&lli->lli_layout_mutex); return rc; } op_data = ll_prep_md_op_data(NULL, inode, inode, NULL, 0, 0, LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) { - mutex_unlock(&lli->lli_layout_mutex); + if (IS_ERR(op_data)) return PTR_ERR(op_data); - } /* have to enqueue one */ memset(&it, 0, sizeof(it)); @@ -3443,10 +3422,50 @@ again: if (rc == 0) { /* set lock data in case this is a new lock */ ll_set_lock_data(sbi->ll_md_exp, inode, &it, NULL); - rc = ll_layout_lock_set(&lockh, mode, inode, gen, true); + rc = ll_layout_lock_set(&lockh, mode, inode); if (rc == -EAGAIN) goto again; } + + return rc; +} + +/** + * This function checks if there exists a LAYOUT lock on the client side, + * or enqueues it if it doesn't have one in cache. + * + * This function will not hold layout lock so it may be revoked any time after + * this function returns. Any operations depend on layout should be redone + * in that case. + * + * This function should be called before lov_io_init() to get an uptodate + * layout version, the caller should save the version number and after IO + * is finished, this function should be called again to verify that layout + * is not changed during IO time. + */ +int ll_layout_refresh(struct inode *inode, __u32 *gen) +{ + struct ll_inode_info *lli = ll_i2info(inode); + struct ll_sb_info *sbi = ll_i2sbi(inode); + int rc; + + *gen = ll_layout_version_get(lli); + if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK) || *gen != CL_LAYOUT_GEN_NONE) + return 0; + + /* sanity checks */ + LASSERT(fid_is_sane(ll_inode2fid(inode))); + LASSERT(S_ISREG(inode->i_mode)); + + /* take layout lock mutex to enqueue layout lock exclusively. */ + mutex_lock(&lli->lli_layout_mutex); + + rc = ll_layout_refresh_locked(inode); + if (rc < 0) + goto out; + + *gen = ll_layout_version_get(lli); +out: mutex_unlock(&lli->lli_layout_mutex); return rc; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 64f4aed5f076..bd98ec273db5 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -304,22 +304,3 @@ __u32 cl_fid_build_gen(const struct lu_fid *fid) gen = fid_flatten(fid) >> 32; return gen; } - -/* lsm is unreliable after hsm implementation as layout can be changed at - * any time. This is only to support old, non-clio-ized interfaces. It will - * cause deadlock if clio operations are called with this extra layout refcount - * because in case the layout changed during the IO, ll_layout_refresh() will - * have to wait for the refcount to become zero to destroy the older layout. - * - * Notice that the lsm returned by this function may not be valid unless called - * inside layout lock - MDS_INODELOCK_LAYOUT. - */ -struct lov_stripe_md *ccc_inode_lsm_get(struct inode *inode) -{ - return lov_lsm_get(ll_i2info(inode)->lli_clob); -} - -inline void ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm) -{ - lov_lsm_put(ll_i2info(inode)->lli_clob, lsm); -} diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index a0aefeb9cbf0..44cbbda462e4 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1316,11 +1316,6 @@ static inline void d_lustre_revalidate(struct dentry *dentry) spin_unlock(&dentry->d_lock); } -enum { - LL_LAYOUT_GEN_NONE = ((__u32)-2), /* layout lock was cancelled */ - LL_LAYOUT_GEN_EMPTY = ((__u32)-1) /* for empty layout */ -}; - int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf); int ll_layout_refresh(struct inode *inode, __u32 *gen); int ll_layout_restore(struct inode *inode, loff_t start, __u64 length); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 150cd5b8b96a..8d8b9a961551 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -800,7 +800,7 @@ void ll_lli_init(struct ll_inode_info *lli) spin_lock_init(&lli->lli_agl_lock); lli->lli_has_smd = false; spin_lock_init(&lli->lli_layout_lock); - ll_layout_version_set(lli, LL_LAYOUT_GEN_NONE); + ll_layout_version_set(lli, CL_LAYOUT_GEN_NONE); lli->lli_clob = NULL; init_rwsem(&lli->lli_xattrs_list_rwsem); @@ -1441,14 +1441,33 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) * but other attributes must be set */ if (S_ISREG(inode->i_mode)) { - struct lov_stripe_md *lsm; + struct cl_layout cl = { + .cl_is_released = false, + }; + struct lu_env *env; + int refcheck; __u32 gen; - ll_layout_refresh(inode, &gen); - lsm = ccc_inode_lsm_get(inode); - if (lsm && lsm->lsm_pattern & LOV_PATTERN_F_RELEASED) - file_is_released = true; - ccc_inode_lsm_put(inode, lsm); + rc = ll_layout_refresh(inode, &gen); + if (rc < 0) + goto out; + + /* + * XXX: the only place we need to know the layout type, + * this will be removed by a later patch. -Jinshan + */ + env = cl_env_get(&refcheck); + if (IS_ERR(env)) { + rc = PTR_ERR(env); + goto out; + } + + rc = cl_object_layout_get(env, lli->lli_clob, &cl); + cl_env_put(env, &refcheck); + if (rc < 0) + goto out; + + file_is_released = cl.cl_is_released; if (!hsm_import && attr->ia_valid & ATTR_SIZE) { if (file_is_released) { diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 2dca1fce4b41..a8e6aeb6aacd 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -309,21 +309,8 @@ static inline struct vvp_lock *cl2vvp_lock(const struct cl_lock_slice *slice) # define CLOBINVRNT(env, clob, expr) \ ((void)sizeof(env), (void)sizeof(clob), (void)sizeof(!!(expr))) -/** - * New interfaces to get and put lov_stripe_md from lov layer. This violates - * layering because lov_stripe_md is supposed to be a private data in lov. - * - * NB: If you find you have to use these interfaces for your new code, please - * think about it again. These interfaces may be removed in the future for - * better layering. - */ -struct lov_stripe_md *lov_lsm_get(struct cl_object *clobj); -void lov_lsm_put(struct cl_object *clobj, struct lov_stripe_md *lsm); int lov_read_and_clear_async_rc(struct cl_object *clob); -struct lov_stripe_md *ccc_inode_lsm_get(struct inode *inode); -void ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm); - int vvp_io_init(const struct lu_env *env, struct cl_object *obj, struct cl_io *io); int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io); diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 3214885bd1da..420a649bcfd7 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -132,7 +132,7 @@ static int vvp_conf_set(const struct lu_env *env, struct cl_object *obj, CDEBUG(D_VFSTRACE, DFID ": losing layout lock\n", PFID(&lli->lli_fid)); - ll_layout_version_set(lli, LL_LAYOUT_GEN_NONE); + ll_layout_version_set(lli, CL_LAYOUT_GEN_NONE); /* Clean up page mmap for this inode. * The reason for us to do this is that if the page has @@ -164,7 +164,7 @@ static int vvp_conf_set(const struct lu_env *env, struct cl_object *obj, PFID(&lli->lli_fid), lli->lli_layout_gen); lli->lli_has_smd = false; - ll_layout_version_set(lli, LL_LAYOUT_GEN_EMPTY); + ll_layout_version_set(lli, CL_LAYOUT_GEN_EMPTY); } return 0; } diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index e070adb7a3cc..b8b5c3279ad8 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -353,80 +353,99 @@ static int ll_xattr_get_common(const struct xattr_handler *handler, OBD_MD_FLXATTR); } -static int ll_xattr_get(const struct xattr_handler *handler, - struct dentry *dentry, struct inode *inode, - const char *name, void *buffer, size_t size) +static ssize_t ll_getxattr_lov(struct inode *inode, void *buf, size_t buf_size) { - LASSERT(inode); - LASSERT(name); + ssize_t rc; - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), xattr %s\n", - PFID(ll_inode2fid(inode)), inode, name); - - if (!strcmp(name, "lov")) { - struct lov_stripe_md *lsm; - struct lov_user_md *lump; - struct lov_mds_md *lmm = NULL; - struct ptlrpc_request *request = NULL; - int rc = 0, lmmsize = 0; + if (S_ISREG(inode->i_mode)) { + struct cl_object *obj = ll_i2info(inode)->lli_clob; + struct cl_layout cl = { + .cl_buf.lb_buf = buf, + .cl_buf.lb_len = buf_size, + }; + struct lu_env *env; + int refcheck; + + if (!obj) + return -ENODATA; - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + return PTR_ERR(env); - if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) - return -ENODATA; + rc = cl_object_layout_get(env, obj, &cl); + if (rc < 0) + goto out_env; - lsm = ccc_inode_lsm_get(inode); - if (!lsm) { - if (S_ISDIR(inode->i_mode)) { - rc = ll_dir_getstripe(inode, (void **)&lmm, - &lmmsize, &request, 0); - } else { - rc = -ENODATA; - } - } else { - /* LSM is present already after lookup/getattr call. - * we need to grab layout lock once it is implemented - */ - rc = obd_packmd(ll_i2dtexp(inode), &lmm, lsm); - lmmsize = rc; + if (!cl.cl_size) { + rc = -ENODATA; + goto out_env; } - ccc_inode_lsm_put(inode, lsm); + rc = cl.cl_size; + + if (!buf_size) + goto out_env; + + LASSERT(buf && rc <= buf_size); + + /* + * Do not return layout gen for getxattr() since + * otherwise it would confuse tar --xattr by + * recognizing layout gen as stripe offset when the + * file is restored. See LU-2809. + */ + ((struct lov_mds_md *)buf)->lmm_layout_gen = 0; +out_env: + cl_env_put(env, &refcheck); + + return rc; + } else if (S_ISDIR(inode->i_mode)) { + struct ptlrpc_request *req = NULL; + struct lov_mds_md *lmm = NULL; + int lmm_size = 0; + + rc = ll_dir_getstripe(inode, (void **)&lmm, &lmm_size, + &req, 0); if (rc < 0) - goto out; + goto out_req; - if (size == 0) { - /* used to call ll_get_max_mdsize() forward to get - * the maximum buffer size, while some apps (such as - * rsync 3.0.x) care much about the exact xattr value - * size - */ - rc = lmmsize; - goto out; + if (!buf_size) { + rc = lmm_size; + goto out_req; } - if (size < lmmsize) { - CERROR("server bug: replied size %d > %d for %pd (%s)\n", - lmmsize, (int)size, dentry, name); + if (buf_size < lmm_size) { rc = -ERANGE; - goto out; + goto out_req; } - lump = buffer; - memcpy(lump, lmm, lmmsize); - /* do not return layout gen for getxattr otherwise it would - * confuse tar --xattr by recognizing layout gen as stripe - * offset when the file is restored. See LU-2809. - */ - lump->lmm_layout_gen = 0; + memcpy(buf, lmm, lmm_size); + rc = lmm_size; +out_req: + if (req) + ptlrpc_req_finished(req); - rc = lmmsize; -out: - if (request) - ptlrpc_req_finished(request); - else if (lmm) - obd_free_diskmd(ll_i2dtexp(inode), &lmm); return rc; + } else { + return -ENODATA; + } +} + +static int ll_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) +{ + LASSERT(inode); + LASSERT(name); + + CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p), xattr %s\n", + PFID(ll_inode2fid(inode)), inode, name); + + if (!strcmp(name, "lov")) { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); + + return ll_getxattr_lov(inode, buffer, size); } return ll_xattr_get_common(handler, dentry, inode, name, buffer, size); @@ -435,10 +454,10 @@ out: ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) { struct inode *inode = d_inode(dentry); - int rc = 0, rc2 = 0; - struct lov_mds_md *lmm = NULL; - struct ptlrpc_request *request = NULL; - int lmmsize; + struct ll_sb_info *sbi = ll_i2sbi(inode); + char *xattr_name; + ssize_t rc, rc2; + size_t len, rem; LASSERT(inode); @@ -450,65 +469,48 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) rc = ll_xattr_list(inode, NULL, XATTR_OTHER_T, buffer, size, OBD_MD_FLXATTRLS); if (rc < 0) - goto out; - - if (buffer) { - struct ll_sb_info *sbi = ll_i2sbi(inode); - char *xattr_name = buffer; - int xlen, rem = rc; - - while (rem > 0) { - xlen = strnlen(xattr_name, rem - 1) + 1; - rem -= xlen; - if (xattr_type_filter(sbi, - get_xattr_type(xattr_name)) == 0) { - /* skip OK xattr type - * leave it in buffer - */ - xattr_name += xlen; - continue; - } - /* move up remaining xattrs in buffer - * removing the xattr that is not OK - */ - memmove(xattr_name, xattr_name + xlen, rem); - rc -= xlen; + return rc; + /* + * If we're being called to get the size of the xattr list + * (buf_size == 0) then just assume that a lustre.lov xattr + * exists. + */ + if (!size) + return rc + sizeof(XATTR_LUSTRE_LOV); + + xattr_name = buffer; + rem = rc; + + while (rem > 0) { + len = strnlen(xattr_name, rem - 1) + 1; + rem -= len; + if (!xattr_type_filter(sbi, get_xattr_type(xattr_name))) { + /* Skip OK xattr type leave it in buffer */ + xattr_name += len; + continue; } - } - if (S_ISREG(inode->i_mode)) { - if (!ll_i2info(inode)->lli_has_smd) - rc2 = -1; - } else if (S_ISDIR(inode->i_mode)) { - rc2 = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, - &request, 0); + + /* + * Move up remaining xattrs in buffer + * removing the xattr that is not OK + */ + memmove(xattr_name, xattr_name + len, rem); + rc -= len; } - if (rc2 < 0) { - rc2 = 0; - goto out; - } else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) { - const int prefix_len = sizeof(XATTR_LUSTRE_PREFIX) - 1; - const size_t name_len = sizeof("lov") - 1; - const size_t total_len = prefix_len + name_len + 1; - - if (((rc + total_len) > size) && buffer) { - ptlrpc_req_finished(request); - return -ERANGE; - } + rc2 = ll_getxattr_lov(inode, NULL, 0); + if (rc2 == -ENODATA) + return rc; - if (buffer) { - buffer += rc; - memcpy(buffer, XATTR_LUSTRE_PREFIX, prefix_len); - memcpy(buffer + prefix_len, "lov", name_len); - buffer[prefix_len + name_len] = '\0'; - } - rc2 = total_len; - } -out: - ptlrpc_req_finished(request); - rc = rc + rc2; + if (rc2 < 0) + return rc2; - return rc; + if (size < rc + sizeof(XATTR_LUSTRE_LOV)) + return -ERANGE; + + memcpy(buffer + rc, XATTR_LUSTRE_LOV, sizeof(XATTR_LUSTRE_LOV)); + + return rc + sizeof(XATTR_LUSTRE_LOV); } static const struct xattr_handler ll_user_xattr_handler = { diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index fffc18ccd97e..60397a28ef58 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -176,6 +176,8 @@ int lov_del_target(struct obd_device *obd, __u32 index, struct obd_uuid *uuidp, int gen); /* lov_pack.c */ +ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf, + size_t buf_size); int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmm, struct lov_stripe_md *lsm); int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 07bef44c7439..d39724ac0fd1 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -75,12 +75,11 @@ struct lov_layout_operations { static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov); -void lov_lsm_put(struct cl_object *unused, struct lov_stripe_md *lsm) +static void lov_lsm_put(struct lov_stripe_md *lsm) { if (lsm) lov_free_memmd(&lsm); } -EXPORT_SYMBOL(lov_lsm_put); /***************************************************************************** * @@ -1408,7 +1407,7 @@ obj_put: cl_object_put(env, subobj); out: kvfree(fm_local); - lov_lsm_put(obj, lsm); + lov_lsm_put(lsm); return rc; } @@ -1424,10 +1423,37 @@ static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj, return -ENODATA; rc = lov_getstripe(cl2lov(obj), lsm, lum); - lov_lsm_put(obj, lsm); + lov_lsm_put(lsm); return rc; } +static int lov_object_layout_get(const struct lu_env *env, + struct cl_object *obj, + struct cl_layout *cl) +{ + struct lov_object *lov = cl2lov(obj); + struct lov_stripe_md *lsm = lov_lsm_addref(lov); + struct lu_buf *buf = &cl->cl_buf; + ssize_t rc; + + if (!lsm) { + cl->cl_size = 0; + cl->cl_layout_gen = CL_LAYOUT_GEN_EMPTY; + cl->cl_is_released = false; + + return 0; + } + + cl->cl_size = lov_mds_md_size(lsm->lsm_stripe_count, lsm->lsm_magic); + cl->cl_layout_gen = lsm->lsm_layout_gen; + cl->cl_is_released = lsm_is_released(lsm); + + rc = lov_lsm_pack(lsm, buf->lb_buf, buf->lb_len); + lov_lsm_put(lsm); + + return rc < 0 ? rc : 0; +} + static const struct cl_object_operations lov_ops = { .coo_page_init = lov_page_init, .coo_lock_init = lov_lock_init, @@ -1436,6 +1462,7 @@ static const struct cl_object_operations lov_ops = { .coo_attr_update = lov_attr_update, .coo_conf_set = lov_conf_set, .coo_getstripe = lov_object_getstripe, + .coo_layout_get = lov_object_layout_get, .coo_fiemap = lov_object_fiemap, }; @@ -1488,22 +1515,6 @@ struct lov_stripe_md *lov_lsm_addref(struct lov_object *lov) return lsm; } -struct lov_stripe_md *lov_lsm_get(struct cl_object *clobj) -{ - struct lu_object *luobj; - struct lov_stripe_md *lsm = NULL; - - if (!clobj) - return NULL; - - luobj = lu_object_locate(&cl_object_header(clobj)->coh_lu, - &lov_device_type); - if (luobj) - lsm = lov_lsm_addref(lu2lov(luobj)); - return lsm; -} -EXPORT_SYMBOL(lov_lsm_get); - int lov_read_and_clear_async_rc(struct cl_object *clob) { struct lu_object *luobj; diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index be6e9857ce2a..1156ef986422 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -97,6 +97,62 @@ void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm) le16_to_cpu(lmm->lmm_stripe_count)); } +/** + * Pack LOV striping metadata for disk storage format (in little + * endian byte order). + * + * This follows the getxattr() conventions. If \a buf_size is zero + * then return the size needed. If \a buf_size is too small then + * return -ERANGE. Otherwise return the size of the result. + */ +ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf, + size_t buf_size) +{ + struct lov_ost_data_v1 *lmm_objects; + struct lov_mds_md_v1 *lmmv1 = buf; + struct lov_mds_md_v3 *lmmv3 = buf; + size_t lmm_size; + unsigned int i; + + lmm_size = lov_mds_md_size(lsm->lsm_stripe_count, lsm->lsm_magic); + if (!buf_size) + return lmm_size; + + if (buf_size < lmm_size) + return -ERANGE; + + /* + * lmmv1 and lmmv3 point to the same struct and have the + * same first fields + */ + lmmv1->lmm_magic = cpu_to_le32(lsm->lsm_magic); + lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi); + lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); + lmmv1->lmm_stripe_count = cpu_to_le16(lsm->lsm_stripe_count); + lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); + lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen); + + if (lsm->lsm_magic == LOV_MAGIC_V3) { + CLASSERT(sizeof(lsm->lsm_pool_name) == + sizeof(lmmv3->lmm_pool_name)); + strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, + sizeof(lmmv3->lmm_pool_name)); + lmm_objects = lmmv3->lmm_objects; + } else { + lmm_objects = lmmv1->lmm_objects; + } + + for (i = 0; i < lsm->lsm_stripe_count; i++) { + struct lov_oinfo *loi = lsm->lsm_oinfo[i]; + + ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); + lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); + lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); + } + + return lmm_size; +} + /* Pack LOV object metadata for disk storage. It is packed in LE byte * order and is opaque to the networking layer. * @@ -108,13 +164,8 @@ void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm) int lov_obd_packmd(struct lov_obd *lov, struct lov_mds_md **lmmp, struct lov_stripe_md *lsm) { - struct lov_mds_md_v1 *lmmv1; - struct lov_mds_md_v3 *lmmv3; __u16 stripe_count; - struct lov_ost_data_v1 *lmm_objects; int lmm_size, lmm_magic; - int i; - int cplen = 0; if (lsm) { lmm_magic = lsm->lsm_magic; @@ -177,46 +228,10 @@ int lov_obd_packmd(struct lov_obd *lov, struct lov_mds_md **lmmp, CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d\n", lmm_magic, lmm_size); - lmmv1 = *lmmp; - lmmv3 = (struct lov_mds_md_v3 *)*lmmp; - if (lmm_magic == LOV_MAGIC_V3) - lmmv3->lmm_magic = cpu_to_le32(LOV_MAGIC_V3); - else - lmmv1->lmm_magic = cpu_to_le32(LOV_MAGIC_V1); - if (!lsm) return lmm_size; - /* lmmv1 and lmmv3 point to the same struct and have the - * same first fields - */ - lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi); - lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); - lmmv1->lmm_stripe_count = cpu_to_le16(stripe_count); - lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); - lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen); - if (lsm->lsm_magic == LOV_MAGIC_V3) { - cplen = strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, - sizeof(lmmv3->lmm_pool_name)); - if (cplen >= sizeof(lmmv3->lmm_pool_name)) - return -E2BIG; - lmm_objects = lmmv3->lmm_objects; - } else { - lmm_objects = lmmv1->lmm_objects; - } - - for (i = 0; i < stripe_count; i++) { - struct lov_oinfo *loi = lsm->lsm_oinfo[i]; - /* XXX LOV STACKING call down to osc_packmd() to do packing */ - LASSERTF(ostid_id(&loi->loi_oi) != 0, "lmm_oi "DOSTID - " stripe %u/%u idx %u\n", POSTID(&lmmv1->lmm_oi), - i, stripe_count, loi->loi_ost_idx); - ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); - lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); - lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); - } - - return lmm_size; + return lov_lsm_pack(lsm, *lmmp, lmm_size); } int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 4ad2ee5719ca..dd80b8307774 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -374,6 +374,20 @@ int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj, } EXPORT_SYMBOL(cl_object_fiemap); +int cl_object_layout_get(const struct lu_env *env, struct cl_object *obj, + struct cl_layout *cl) +{ + struct lu_object_header *top = obj->co_lu.lo_header; + + list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) { + if (obj->co_ops->coo_layout_get) + return obj->co_ops->coo_layout_get(env, obj, cl); + } + + return -EOPNOTSUPP; +} +EXPORT_SYMBOL(cl_object_layout_get); + /** * Helper function removing all object locks, and marking object for * deletion. All object pages must have been deleted at this point. -- cgit v1.2.3 From 85cb63bc68a7b18fcc2966346b0ed774812973d9 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Sun, 2 Oct 2016 22:28:22 -0400 Subject: staging: lustre: llite: remove lli_has_smd Remove the lli_has_smd flag from struct ll_inode_info. The empty layout case will be handled by the LOV layer. Remove the unused function cl_local_size(). Signed-off-by: Jinshan Xiong Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/13690 Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 7 -- drivers/staging/lustre/lustre/llite/glimpse.c | 134 +++++++-------------- drivers/staging/lustre/lustre/llite/lcommon_cl.c | 1 - .../staging/lustre/lustre/llite/llite_internal.h | 2 - drivers/staging/lustre/lustre/llite/llite_lib.c | 8 +- drivers/staging/lustre/lustre/llite/rw26.c | 4 - drivers/staging/lustre/lustre/llite/vvp_object.c | 19 --- drivers/staging/lustre/lustre/lov/lov_io.c | 9 +- 8 files changed, 55 insertions(+), 129 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 2f2dcce28b51..0accf2867055 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -632,12 +632,6 @@ restart: if (!S_ISREG(inode->i_mode)) goto out_och_free; - if (!lli->lli_has_smd && - (cl_is_lov_delay_create(file->f_flags) || - (file->f_mode & FMODE_WRITE) == 0)) { - CDEBUG(D_INODE, "object creation was delayed\n"); - goto out_och_free; - } cl_lov_delay_create_clear(&file->f_flags); goto out_och_free; @@ -3185,7 +3179,6 @@ int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf) PFID(&lli->lli_fid), ll_layout_version_get(lli), cl.cl_layout_gen); ll_layout_version_set(lli, cl.cl_layout_gen); - lli->lli_has_smd = lsm_has_objects(conf->u.coc_md->lsm); } out: cl_env_nested_put(&nest, env); diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index 0d1ffadeab46..504498de536e 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -80,66 +80,60 @@ blkcnt_t dirty_cnt(struct inode *inode) int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, struct inode *inode, struct cl_object *clob, int agl) { - struct ll_inode_info *lli = ll_i2info(inode); const struct lu_fid *fid = lu_object_fid(&clob->co_lu); + struct cl_lock *lock = vvp_env_lock(env); + struct cl_lock_descr *descr = &lock->cll_descr; int result = 0; CDEBUG(D_DLMTRACE, "Glimpsing inode " DFID "\n", PFID(fid)); - if (lli->lli_has_smd) { - struct cl_lock *lock = vvp_env_lock(env); - struct cl_lock_descr *descr = &lock->cll_descr; - - /* NOTE: this looks like DLM lock request, but it may - * not be one. Due to CEF_ASYNC flag (translated - * to LDLM_FL_HAS_INTENT by osc), this is - * glimpse request, that won't revoke any - * conflicting DLM locks held. Instead, - * ll_glimpse_callback() will be called on each - * client holding a DLM lock against this file, - * and resulting size will be returned for each - * stripe. DLM lock on [0, EOF] is acquired only - * if there were no conflicting locks. If there - * were conflicting locks, enqueuing or waiting - * fails with -ENAVAIL, but valid inode - * attributes are returned anyway. - */ - *descr = whole_file; - descr->cld_obj = clob; - descr->cld_mode = CLM_READ; - descr->cld_enq_flags = CEF_ASYNC | CEF_MUST; - if (agl) - descr->cld_enq_flags |= CEF_AGL; - /* - * CEF_ASYNC is used because glimpse sub-locks cannot - * deadlock (because they never conflict with other - * locks) and, hence, can be enqueued out-of-order. - * - * CEF_MUST protects glimpse lock from conversion into - * a lockless mode. - */ - result = cl_lock_request(env, io, lock); - if (result < 0) - return result; - - if (!agl) { - ll_merge_attr(env, inode); - if (i_size_read(inode) > 0 && !inode->i_blocks) { - /* - * LU-417: Add dirty pages block count - * lest i_blocks reports 0, some "cp" or - * "tar" may think it's a completely - * sparse file and skip it. - */ - inode->i_blocks = dirty_cnt(inode); - } - } - cl_lock_release(env, lock); - } else { - CDEBUG(D_DLMTRACE, "No objects for inode\n"); + /* NOTE: this looks like DLM lock request, but it may + * not be one. Due to CEF_ASYNC flag (translated + * to LDLM_FL_HAS_INTENT by osc), this is + * glimpse request, that won't revoke any + * conflicting DLM locks held. Instead, + * ll_glimpse_callback() will be called on each + * client holding a DLM lock against this file, + * and resulting size will be returned for each + * stripe. DLM lock on [0, EOF] is acquired only + * if there were no conflicting locks. If there + * were conflicting locks, enqueuing or waiting + * fails with -ENAVAIL, but valid inode + * attributes are returned anyway. + */ + *descr = whole_file; + descr->cld_obj = clob; + descr->cld_mode = CLM_READ; + descr->cld_enq_flags = CEF_ASYNC | CEF_MUST; + if (agl) + descr->cld_enq_flags |= CEF_AGL; + /* + * CEF_ASYNC is used because glimpse sub-locks cannot + * deadlock (because they never conflict with other + * locks) and, hence, can be enqueued out-of-order. + * + * CEF_MUST protects glimpse lock from conversion into + * a lockless mode. + */ + result = cl_lock_request(env, io, lock); + if (result < 0) + return result; + + if (!agl) { ll_merge_attr(env, inode); + if (i_size_read(inode) > 0 && !inode->i_blocks) { + /* + * LU-417: Add dirty pages block count + * lest i_blocks reports 0, some "cp" or + * "tar" may think it's a completely + * sparse file and skip it. + */ + inode->i_blocks = dirty_cnt(inode); + } } + cl_lock_release(env, lock); + return result; } @@ -209,39 +203,3 @@ again: } return result; } - -int cl_local_size(struct inode *inode) -{ - struct lu_env *env = NULL; - struct cl_io *io = NULL; - struct cl_object *clob; - int result; - int refcheck; - - if (!ll_i2info(inode)->lli_has_smd) - return 0; - - result = cl_io_get(inode, &env, &io, &refcheck); - if (result <= 0) - return result; - - clob = io->ci_obj; - result = cl_io_init(env, io, CIT_MISC, clob); - if (result > 0) { - result = io->ci_result; - } else if (result == 0) { - struct cl_lock *lock = vvp_env_lock(env); - - lock->cll_descr = whole_file; - lock->cll_descr.cld_enq_flags = CEF_PEEK; - lock->cll_descr.cld_obj = clob; - result = cl_lock_request(env, io, lock); - if (result == 0) { - ll_merge_attr(env, inode); - cl_lock_release(env, lock); - } - } - cl_io_fini(env, io); - cl_env_put(env, &refcheck); - return result; -} diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index bd98ec273db5..4087db0244a9 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -184,7 +184,6 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md) * locked by I_NEW bit. */ lli->lli_clob = clob; - lli->lli_has_smd = lsm_has_objects(md->lsm); lu_object_ref_add(&clob->co_lu, "inode", inode); } else { result = PTR_ERR(clob); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 44cbbda462e4..c972eac8689e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -226,7 +226,6 @@ struct ll_inode_info { * In the future, if more members are added only for directory, * some of the following members can be moved into u.f. */ - bool lli_has_smd; struct cl_object *lli_clob; /* mutex to request for layout lock exclusively. */ @@ -1337,7 +1336,6 @@ extern int cl_inode_fini_refcheck; int cl_file_inode_init(struct inode *inode, struct lustre_md *md); void cl_inode_fini(struct inode *inode); -int cl_local_size(struct inode *inode); __u64 cl_fid_build_ino(const struct lu_fid *fid, int api32); __u32 cl_fid_build_gen(const struct lu_fid *fid); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 8d8b9a961551..09f30ece391c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -798,7 +798,6 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_open_fd_exec_count = 0; mutex_init(&lli->lli_och_mutex); spin_lock_init(&lli->lli_agl_lock); - lli->lli_has_smd = false; spin_lock_init(&lli->lli_layout_lock); ll_layout_version_set(lli, CL_LAYOUT_GEN_NONE); lli->lli_clob = NULL; @@ -1290,7 +1289,6 @@ void ll_clear_inode(struct inode *inode) * cl_object still uses inode lsm. */ cl_inode_fini(inode); - lli->lli_has_smd = false; } #define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) @@ -1688,9 +1686,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT((lsm != NULL) == ((body->mbo_valid & OBD_MD_FLEASIZE) != 0)); if (lsm) { - if (!lli->lli_has_smd && - !(sbi->ll_flags & LL_SBI_LAYOUT_LOCK)) - cl_file_inode_init(inode, md); + cl_file_inode_init(inode, md); lli->lli_maxbytes = lsm->lsm_maxbytes; if (lli->lli_maxbytes > MAX_LFS_FILESIZE) @@ -1802,8 +1798,6 @@ int ll_read_inode2(struct inode *inode, void *opaque) CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", PFID(&lli->lli_fid), inode); - LASSERT(!lli->lli_has_smd); - /* Core attributes from the MDS first. This is a new inode, and * the VFS doesn't zero times in the core inode so we have to do * it ourselves. They will be overwritten by either MDS or OST diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 26f3a37873a7..67010beab8f1 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -347,13 +347,9 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) loff_t file_offset = iocb->ki_pos; ssize_t count = iov_iter_count(iter); ssize_t tot_bytes = 0, result = 0; - struct ll_inode_info *lli = ll_i2info(inode); long size = MAX_DIO_SIZE; int refcheck; - if (!lli->lli_has_smd) - return -EBADF; - /* FIXME: io smaller than PAGE_SIZE is broken on ia64 ??? */ if ((file_offset & ~PAGE_MASK) || (count & ~PAGE_MASK)) return -EINVAL; diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 420a649bcfd7..cc0f3daad12c 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -145,27 +145,8 @@ static int vvp_conf_set(const struct lu_env *env, struct cl_object *obj, */ unmap_mapping_range(conf->coc_inode->i_mapping, 0, OBD_OBJECT_EOF, 0); - - return 0; } - if (conf->coc_opc != OBJECT_CONF_SET) - return 0; - - if (conf->u.coc_md && conf->u.coc_md->lsm) { - CDEBUG(D_VFSTRACE, DFID ": layout version change: %u -> %u\n", - PFID(&lli->lli_fid), lli->lli_layout_gen, - conf->u.coc_md->lsm->lsm_layout_gen); - - lli->lli_has_smd = lsm_has_objects(conf->u.coc_md->lsm); - ll_layout_version_set(lli, conf->u.coc_md->lsm->lsm_layout_gen); - } else { - CDEBUG(D_VFSTRACE, DFID ": layout nuked: %u.\n", - PFID(&lli->lli_fid), lli->lli_layout_gen); - - lli->lli_has_smd = false; - ll_layout_version_set(lli, CL_LAYOUT_GEN_EMPTY); - } return 0; } diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index d6be6136ed54..a1d1ec9dd72e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -918,6 +918,13 @@ static void lov_empty_io_fini(const struct lu_env *env, wake_up_all(&lov->lo_waitq); } +static int lov_empty_io_submit(const struct lu_env *env, + const struct cl_io_slice *ios, + enum cl_req_type crt, struct cl_2queue *queue) +{ + return -EBADF; +} + static void lov_empty_impossible(const struct lu_env *env, struct cl_io_slice *ios) { @@ -968,7 +975,7 @@ static const struct cl_io_operations lov_empty_io_ops = { .cio_fini = lov_empty_io_fini } }, - .cio_submit = LOV_EMPTY_IMPOSSIBLE, + .cio_submit = lov_empty_io_submit, .cio_commit_async = LOV_EMPTY_IMPOSSIBLE }; -- cgit v1.2.3 From 090a648530c13adc7e27ed2bb0a6d48b66635c1f Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:23 -0400 Subject: staging: lustre: llite: add cl_object_maxbytes() Add cl_object_maxbytes() to return the maximum supported size of a cl_object. Remove the lli_maxbytes member from struct ll_inode_info. Change the lsm_maxbytes member of struct lov_stripe_md from __u64 to loff_t. Correct the computation of lsm_maxbytes in the released layout case. Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/13694 Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/cl_object.h | 5 + drivers/staging/lustre/lustre/include/obd.h | 2 +- .../staging/lustre/lustre/llite/llite_internal.h | 10 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 8 +- drivers/staging/lustre/lustre/lov/lov_ea.c | 191 +++++++++------------ drivers/staging/lustre/lustre/lov/lov_object.c | 17 ++ drivers/staging/lustre/lustre/obdclass/cl_object.c | 15 ++ 7 files changed, 130 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index b80539daeee1..dfef4bce3f85 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -431,6 +431,10 @@ struct cl_object_operations { */ int (*coo_layout_get)(const struct lu_env *env, struct cl_object *obj, struct cl_layout *layout); + /** + * Get maximum size of the object. + */ + loff_t (*coo_maxbytes)(struct cl_object *obj); }; /** @@ -2227,6 +2231,7 @@ int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj, size_t *buflen); int cl_object_layout_get(const struct lu_env *env, struct cl_object *obj, struct cl_layout *cl); +loff_t cl_object_maxbytes(struct cl_object *obj); /** * Returns true, iff \a o0 and \a o1 are slices of the same object. diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f254d88108c6..8372debbf966 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -88,7 +88,7 @@ struct lov_stripe_md { /* maximum possible file size, might change as OSTs status changes, * e.g. disconnected, deactivated */ - __u64 lsm_maxbytes; + loff_t lsm_maxbytes; struct ost_id lsm_oi; __u32 lsm_magic; __u32 lsm_stripe_size; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index c972eac8689e..675a41a89e3d 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -185,7 +185,6 @@ struct ll_inode_info { struct { struct mutex lli_size_mutex; char *lli_symlink_name; - __u64 lli_maxbytes; /* * struct rw_semaphore { * signed long count; // align d.d_def_acl @@ -977,9 +976,14 @@ static inline struct lu_fid *ll_inode2fid(struct inode *inode) return fid; } -static inline __u64 ll_file_maxbytes(struct inode *inode) +static inline loff_t ll_file_maxbytes(struct inode *inode) { - return ll_i2info(inode)->lli_maxbytes; + struct cl_object *obj = ll_i2info(inode)->lli_clob; + + if (!obj) + return MAX_LFS_FILESIZE; + + return min_t(loff_t, cl_object_maxbytes(obj), MAX_LFS_FILESIZE); } /* llite/xattr.c */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 09f30ece391c..dea103ceec81 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -785,7 +785,6 @@ void ll_lli_init(struct ll_inode_info *lli) { lli->lli_inode_magic = LLI_INODE_MAGIC; lli->lli_flags = 0; - lli->lli_maxbytes = MAX_LFS_FILESIZE; spin_lock_init(&lli->lli_lock); lli->lli_posix_acl = NULL; /* Do not set lli_fid, it has been initialized already. */ @@ -1685,14 +1684,9 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) struct ll_sb_info *sbi = ll_i2sbi(inode); LASSERT((lsm != NULL) == ((body->mbo_valid & OBD_MD_FLEASIZE) != 0)); - if (lsm) { + if (lsm) cl_file_inode_init(inode, md); - lli->lli_maxbytes = lsm->lsm_maxbytes; - if (lli->lli_maxbytes > MAX_LFS_FILESIZE) - lli->lli_maxbytes = MAX_LFS_FILESIZE; - } - if (S_ISDIR(inode->i_mode)) { int rc; diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c index 214c561767e0..63dcd294bfac 100644 --- a/drivers/staging/lustre/lustre/lov/lov_ea.c +++ b/drivers/staging/lustre/lustre/lov/lov_ea.c @@ -117,9 +117,43 @@ void lsm_free_plain(struct lov_stripe_md *lsm) kvfree(lsm); } -static void lsm_unpackmd_common(struct lov_stripe_md *lsm, - struct lov_mds_md *lmm) +/* + * Find minimum stripe maxbytes value. For inactive or + * reconnecting targets use LUSTRE_EXT3_STRIPE_MAXBYTES. + */ +static loff_t lov_tgt_maxbytes(struct lov_tgt_desc *tgt) +{ + loff_t maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; + struct obd_import *imp; + + if (!tgt->ltd_active) + return maxbytes; + + imp = tgt->ltd_obd->u.cli.cl_import; + if (!imp) + return maxbytes; + + spin_lock(&imp->imp_lock); + if (imp->imp_state == LUSTRE_IMP_FULL && + (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_MAXBYTES) && + imp->imp_connect_data.ocd_maxbytes > 0) + maxbytes = imp->imp_connect_data.ocd_maxbytes; + + spin_unlock(&imp->imp_lock); + + return maxbytes; +} + +static int lsm_unpackmd_common(struct lov_obd *lov, + struct lov_stripe_md *lsm, + struct lov_mds_md *lmm, + struct lov_ost_data_v1 *objects) { + loff_t stripe_maxbytes = LLONG_MAX; + unsigned int stripe_count; + struct lov_oinfo *loi; + unsigned int i; + /* * This supposes lov_mds_md_v1/v3 first fields are * are the same @@ -129,6 +163,45 @@ static void lsm_unpackmd_common(struct lov_stripe_md *lsm, lsm->lsm_pattern = le32_to_cpu(lmm->lmm_pattern); lsm->lsm_layout_gen = le16_to_cpu(lmm->lmm_layout_gen); lsm->lsm_pool_name[0] = '\0'; + + stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count; + + for (i = 0; i < stripe_count; i++) { + loff_t tgt_bytes; + + loi = lsm->lsm_oinfo[i]; + ostid_le_to_cpu(&objects[i].l_ost_oi, &loi->loi_oi); + loi->loi_ost_idx = le32_to_cpu(objects[i].l_ost_idx); + loi->loi_ost_gen = le32_to_cpu(objects[i].l_ost_gen); + if (lov_oinfo_is_dummy(loi)) + continue; + + if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) { + CERROR("OST index %d more than OST count %d\n", + loi->loi_ost_idx, lov->desc.ld_tgt_count); + lov_dump_lmm_v1(D_WARNING, lmm); + return -EINVAL; + } + + if (!lov->lov_tgts[loi->loi_ost_idx]) { + CERROR("OST index %d missing\n", loi->loi_ost_idx); + lov_dump_lmm_v1(D_WARNING, lmm); + return -EINVAL; + } + + tgt_bytes = lov_tgt_maxbytes(lov->lov_tgts[loi->loi_ost_idx]); + stripe_maxbytes = min_t(loff_t, stripe_maxbytes, tgt_bytes); + } + + if (stripe_maxbytes == LLONG_MAX) + stripe_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; + + if (!lsm->lsm_stripe_count) + lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count; + else + lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count; + + return 0; } static void @@ -147,30 +220,6 @@ lsm_stripe_by_offset_plain(struct lov_stripe_md *lsm, int *stripeno, *swidth = (u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count; } -/* Find minimum stripe maxbytes value. For inactive or - * reconnecting targets use LUSTRE_EXT3_STRIPE_MAXBYTES. - */ -static void lov_tgt_maxbytes(struct lov_tgt_desc *tgt, __u64 *stripe_maxbytes) -{ - struct obd_import *imp = tgt->ltd_obd->u.cli.cl_import; - - if (!imp || !tgt->ltd_active) { - *stripe_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; - return; - } - - spin_lock(&imp->imp_lock); - if (imp->imp_state == LUSTRE_IMP_FULL && - (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_MAXBYTES) && - imp->imp_connect_data.ocd_maxbytes > 0) { - if (*stripe_maxbytes > imp->imp_connect_data.ocd_maxbytes) - *stripe_maxbytes = imp->imp_connect_data.ocd_maxbytes; - } else { - *stripe_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; - } - spin_unlock(&imp->imp_lock); -} - static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes, __u16 *stripe_count) { @@ -197,45 +246,7 @@ static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes, static int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm, struct lov_mds_md_v1 *lmm) { - struct lov_oinfo *loi; - int i; - int stripe_count; - __u64 stripe_maxbytes = OBD_OBJECT_EOF; - - lsm_unpackmd_common(lsm, lmm); - - stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count; - - for (i = 0; i < stripe_count; i++) { - /* XXX LOV STACKING call down to osc_unpackmd() */ - loi = lsm->lsm_oinfo[i]; - ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi); - loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx); - loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen); - if (lov_oinfo_is_dummy(loi)) - continue; - - if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) { - CERROR("OST index %d more than OST count %d\n", - loi->loi_ost_idx, lov->desc.ld_tgt_count); - lov_dump_lmm_v1(D_WARNING, lmm); - return -EINVAL; - } - if (!lov->lov_tgts[loi->loi_ost_idx]) { - CERROR("OST index %d missing\n", loi->loi_ost_idx); - lov_dump_lmm_v1(D_WARNING, lmm); - return -EINVAL; - } - /* calculate the minimum stripe max bytes */ - lov_tgt_maxbytes(lov->lov_tgts[loi->loi_ost_idx], - &stripe_maxbytes); - } - - lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count; - if (lsm->lsm_stripe_count == 0) - lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count; - - return 0; + return lsm_unpackmd_common(lov, lsm, lmm, lmm->lmm_objects); } const struct lsm_operations lsm_v1_ops = { @@ -275,55 +286,21 @@ static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes, } static int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm, - struct lov_mds_md *lmmv1) + struct lov_mds_md *lmm) { - struct lov_mds_md_v3 *lmm; - struct lov_oinfo *loi; - int i; - int stripe_count; - __u64 stripe_maxbytes = OBD_OBJECT_EOF; - int cplen = 0; - - lmm = (struct lov_mds_md_v3 *)lmmv1; + struct lov_mds_md_v3 *lmm_v3 = (struct lov_mds_md_v3 *)lmm; + size_t cplen = 0; + int rc; - lsm_unpackmd_common(lsm, (struct lov_mds_md_v1 *)lmm); + rc = lsm_unpackmd_common(lov, lsm, lmm, lmm_v3->lmm_objects); + if (rc) + return rc; - stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count; - - cplen = strlcpy(lsm->lsm_pool_name, lmm->lmm_pool_name, + cplen = strlcpy(lsm->lsm_pool_name, lmm_v3->lmm_pool_name, sizeof(lsm->lsm_pool_name)); if (cplen >= sizeof(lsm->lsm_pool_name)) return -E2BIG; - for (i = 0; i < stripe_count; i++) { - /* XXX LOV STACKING call down to osc_unpackmd() */ - loi = lsm->lsm_oinfo[i]; - ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi); - loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx); - loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen); - if (lov_oinfo_is_dummy(loi)) - continue; - - if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) { - CERROR("OST index %d more than OST count %d\n", - loi->loi_ost_idx, lov->desc.ld_tgt_count); - lov_dump_lmm_v3(D_WARNING, lmm); - return -EINVAL; - } - if (!lov->lov_tgts[loi->loi_ost_idx]) { - CERROR("OST index %d missing\n", loi->loi_ost_idx); - lov_dump_lmm_v3(D_WARNING, lmm); - return -EINVAL; - } - /* calculate the minimum stripe max bytes */ - lov_tgt_maxbytes(lov->lov_tgts[loi->loi_ost_idx], - &stripe_maxbytes); - } - - lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count; - if (lsm->lsm_stripe_count == 0) - lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count; - return 0; } diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index d39724ac0fd1..82b99e040b25 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -1454,6 +1454,22 @@ static int lov_object_layout_get(const struct lu_env *env, return rc < 0 ? rc : 0; } +static loff_t lov_object_maxbytes(struct cl_object *obj) +{ + struct lov_object *lov = cl2lov(obj); + struct lov_stripe_md *lsm = lov_lsm_addref(lov); + loff_t maxbytes; + + if (!lsm) + return LLONG_MAX; + + maxbytes = lsm->lsm_maxbytes; + + lov_lsm_put(lsm); + + return maxbytes; +} + static const struct cl_object_operations lov_ops = { .coo_page_init = lov_page_init, .coo_lock_init = lov_lock_init, @@ -1463,6 +1479,7 @@ static const struct cl_object_operations lov_ops = { .coo_conf_set = lov_conf_set, .coo_getstripe = lov_object_getstripe, .coo_layout_get = lov_object_layout_get, + .coo_maxbytes = lov_object_maxbytes, .coo_fiemap = lov_object_fiemap, }; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index dd80b8307774..cda01b83f281 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -388,6 +388,21 @@ int cl_object_layout_get(const struct lu_env *env, struct cl_object *obj, } EXPORT_SYMBOL(cl_object_layout_get); +loff_t cl_object_maxbytes(struct cl_object *obj) +{ + struct lu_object_header *top = obj->co_lu.lo_header; + loff_t maxbytes = LLONG_MAX; + + list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) { + if (obj->co_ops->coo_maxbytes) + maxbytes = min_t(loff_t, obj->co_ops->coo_maxbytes(obj), + maxbytes); + } + + return maxbytes; +} +EXPORT_SYMBOL(cl_object_maxbytes); + /** * Helper function removing all object locks, and marking object for * deletion. All object pages must have been deleted at this point. -- cgit v1.2.3 From ef3a1d2a82bba70f836b324137f0fa3e6c61db1c Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Sun, 2 Oct 2016 22:28:24 -0400 Subject: staging: lustre: hsm: make HSM modification requests replayable There are several HSM requests which modify data on server and reply on Lustre recovery, e.g. they should replay changes in case of recovery. Patch allows such requests to be replayed in recovery time and they are issued from client using mdc_rpc_lock to serialize them and avoid concurrent last_rcvd update on server. Signed-off-by: Mikhail Pershin Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5939 Reviewed-on: http://review.whamcloud.com/13684 Reviewed-by: Jinshan Xiong Reviewed-by: Faccini Bruno Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_request.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 7b9fb9026bdf..1d1eaa5238ad 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1505,7 +1505,9 @@ static int mdc_ioc_hsm_progress(struct obd_export *exp, ptlrpc_request_set_replen(req); - rc = mdc_queue_wait(req); + mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL); + rc = ptlrpc_queue_wait(req); + mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL); out: ptlrpc_req_finished(req); return rc; @@ -1683,7 +1685,9 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp, ptlrpc_request_set_replen(req); - rc = mdc_queue_wait(req); + mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL); + rc = ptlrpc_queue_wait(req); + mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL); out: ptlrpc_req_finished(req); return rc; @@ -1746,7 +1750,9 @@ static int mdc_ioc_hsm_request(struct obd_export *exp, ptlrpc_request_set_replen(req); - rc = mdc_queue_wait(req); + mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL); + rc = ptlrpc_queue_wait(req); + mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL); out: ptlrpc_req_finished(req); return rc; -- cgit v1.2.3 From d0365097bac63e478d6c3a8e1a0c333336457057 Mon Sep 17 00:00:00 2001 From: Chris Horn Date: Sun, 2 Oct 2016 22:28:25 -0400 Subject: staging: lustre: ptlrpc: Move NRS structures out of lustre_net.h NRS specific structures are not needed in the rest of the PtlRPC code. It is more appropriate for these structures to be defined in a separate header. This commit creates a lustre_nrs.h header for the generic NRS structures, and policy-specific headers for the various NRS policies. Signed-off-by: Chris Horn Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2667 Reviewed-on: http://review.whamcloud.com/13966 Reviewed-by: Henri Doreau Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_net.h | 712 +------------------- drivers/staging/lustre/lustre/include/lustre_nrs.h | 717 +++++++++++++++++++++ .../lustre/lustre/include/lustre_nrs_fifo.h | 70 ++ 3 files changed, 788 insertions(+), 711 deletions(-) create mode 100644 drivers/staging/lustre/lustre/include/lustre_nrs.h create mode 100644 drivers/staging/lustre/lustre/include/lustre_nrs_fifo.h (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index ab80330bdeea..730223822e1c 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -515,717 +515,7 @@ struct lu_env; struct ldlm_lock; -/** - * \defgroup nrs Network Request Scheduler - * @{ - */ -struct ptlrpc_nrs_policy; -struct ptlrpc_nrs_resource; -struct ptlrpc_nrs_request; - -/** - * NRS control operations. - * - * These are common for all policies. - */ -enum ptlrpc_nrs_ctl { - /** - * Not a valid opcode. - */ - PTLRPC_NRS_CTL_INVALID, - /** - * Activate the policy. - */ - PTLRPC_NRS_CTL_START, - /** - * Reserved for multiple primary policies, which may be a possibility - * in the future. - */ - PTLRPC_NRS_CTL_STOP, - /** - * Policies can start using opcodes from this value and onwards for - * their own purposes; the assigned value itself is arbitrary. - */ - PTLRPC_NRS_CTL_1ST_POL_SPEC = 0x20, -}; - -/** - * ORR policy operations - */ -enum nrs_ctl_orr { - NRS_CTL_ORR_RD_QUANTUM = PTLRPC_NRS_CTL_1ST_POL_SPEC, - NRS_CTL_ORR_WR_QUANTUM, - NRS_CTL_ORR_RD_OFF_TYPE, - NRS_CTL_ORR_WR_OFF_TYPE, - NRS_CTL_ORR_RD_SUPP_REQ, - NRS_CTL_ORR_WR_SUPP_REQ, -}; - -/** - * NRS policy operations. - * - * These determine the behaviour of a policy, and are called in response to - * NRS core events. - */ -struct ptlrpc_nrs_pol_ops { - /** - * Called during policy registration; this operation is optional. - * - * \param[in,out] policy The policy being initialized - */ - int (*op_policy_init)(struct ptlrpc_nrs_policy *policy); - /** - * Called during policy unregistration; this operation is optional. - * - * \param[in,out] policy The policy being unregistered/finalized - */ - void (*op_policy_fini)(struct ptlrpc_nrs_policy *policy); - /** - * Called when activating a policy via lprocfs; policies allocate and - * initialize their resources here; this operation is optional. - * - * \param[in,out] policy The policy being started - * - * \see nrs_policy_start_locked() - */ - int (*op_policy_start)(struct ptlrpc_nrs_policy *policy); - /** - * Called when deactivating a policy via lprocfs; policies deallocate - * their resources here; this operation is optional - * - * \param[in,out] policy The policy being stopped - * - * \see nrs_policy_stop0() - */ - void (*op_policy_stop)(struct ptlrpc_nrs_policy *policy); - /** - * Used for policy-specific operations; i.e. not generic ones like - * \e PTLRPC_NRS_CTL_START and \e PTLRPC_NRS_CTL_GET_INFO; analogous - * to an ioctl; this operation is optional. - * - * \param[in,out] policy The policy carrying out operation \a opc - * \param[in] opc The command operation being carried out - * \param[in,out] arg An generic buffer for communication between the - * user and the control operation - * - * \retval -ve error - * \retval 0 success - * - * \see ptlrpc_nrs_policy_control() - */ - int (*op_policy_ctl)(struct ptlrpc_nrs_policy *policy, - enum ptlrpc_nrs_ctl opc, void *arg); - - /** - * Called when obtaining references to the resources of the resource - * hierarchy for a request that has arrived for handling at the PTLRPC - * service. Policies should return -ve for requests they do not wish - * to handle. This operation is mandatory. - * - * \param[in,out] policy The policy we're getting resources for. - * \param[in,out] nrq The request we are getting resources for. - * \param[in] parent The parent resource of the resource being - * requested; set to NULL if none. - * \param[out] resp The resource is to be returned here; the - * fallback policy in an NRS head should - * \e always return a non-NULL pointer value. - * \param[in] moving_req When set, signifies that this is an attempt - * to obtain resources for a request being moved - * to the high-priority NRS head by - * ldlm_lock_reorder_req(). - * This implies two things: - * 1. We are under obd_export::exp_rpc_lock and - * so should not sleep. - * 2. We should not perform non-idempotent or can - * skip performing idempotent operations that - * were carried out when resources were first - * taken for the request when it was initialized - * in ptlrpc_nrs_req_initialize(). - * - * \retval 0, +ve The level of the returned resource in the resource - * hierarchy; currently only 0 (for a non-leaf resource) - * and 1 (for a leaf resource) are supported by the - * framework. - * \retval -ve error - * - * \see ptlrpc_nrs_req_initialize() - * \see ptlrpc_nrs_hpreq_add_nolock() - */ - int (*op_res_get)(struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq, - const struct ptlrpc_nrs_resource *parent, - struct ptlrpc_nrs_resource **resp, - bool moving_req); - /** - * Called when releasing references taken for resources in the resource - * hierarchy for the request; this operation is optional. - * - * \param[in,out] policy The policy the resource belongs to - * \param[in] res The resource to be freed - * - * \see ptlrpc_nrs_req_finalize() - * \see ptlrpc_nrs_hpreq_add_nolock() - */ - void (*op_res_put)(struct ptlrpc_nrs_policy *policy, - const struct ptlrpc_nrs_resource *res); - - /** - * Obtains a request for handling from the policy, and optionally - * removes the request from the policy; this operation is mandatory. - * - * \param[in,out] policy The policy to poll - * \param[in] peek When set, signifies that we just want to - * examine the request, and not handle it, so the - * request is not removed from the policy. - * \param[in] force When set, it will force a policy to return a - * request if it has one queued. - * - * \retval NULL No request available for handling - * \retval valid-pointer The request polled for handling - * - * \see ptlrpc_nrs_req_get_nolock() - */ - struct ptlrpc_nrs_request * - (*op_req_get)(struct ptlrpc_nrs_policy *policy, bool peek, - bool force); - /** - * Called when attempting to add a request to a policy for later - * handling; this operation is mandatory. - * - * \param[in,out] policy The policy on which to enqueue \a nrq - * \param[in,out] nrq The request to enqueue - * - * \retval 0 success - * \retval != 0 error - * - * \see ptlrpc_nrs_req_add_nolock() - */ - int (*op_req_enqueue)(struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); - /** - * Removes a request from the policy's set of pending requests. Normally - * called after a request has been polled successfully from the policy - * for handling; this operation is mandatory. - * - * \param[in,out] policy The policy the request \a nrq belongs to - * \param[in,out] nrq The request to dequeue - */ - void (*op_req_dequeue)(struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); - /** - * Called after the request being carried out. Could be used for - * job/resource control; this operation is optional. - * - * \param[in,out] policy The policy which is stopping to handle request - * \a nrq - * \param[in,out] nrq The request - * - * \pre assert_spin_locked(&svcpt->scp_req_lock) - * - * \see ptlrpc_nrs_req_stop_nolock() - */ - void (*op_req_stop)(struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); - /** - * Registers the policy's lprocfs interface with a PTLRPC service. - * - * \param[in] svc The service - * - * \retval 0 success - * \retval != 0 error - */ - int (*op_lprocfs_init)(struct ptlrpc_service *svc); - /** - * Unegisters the policy's lprocfs interface with a PTLRPC service. - * - * In cases of failed policy registration in - * \e ptlrpc_nrs_policy_register(), this function may be called for a - * service which has not registered the policy successfully, so - * implementations of this method should make sure their operations are - * safe in such cases. - * - * \param[in] svc The service - */ - void (*op_lprocfs_fini)(struct ptlrpc_service *svc); -}; - -/** - * Policy flags - */ -enum nrs_policy_flags { - /** - * Fallback policy, use this flag only on a single supported policy per - * service. The flag cannot be used on policies that use - * \e PTLRPC_NRS_FL_REG_EXTERN - */ - PTLRPC_NRS_FL_FALLBACK = (1 << 0), - /** - * Start policy immediately after registering. - */ - PTLRPC_NRS_FL_REG_START = (1 << 1), - /** - * This is a policy registering from a module different to the one NRS - * core ships in (currently ptlrpc). - */ - PTLRPC_NRS_FL_REG_EXTERN = (1 << 2), -}; - -/** - * NRS queue type. - * - * Denotes whether an NRS instance is for handling normal or high-priority - * RPCs, or whether an operation pertains to one or both of the NRS instances - * in a service. - */ -enum ptlrpc_nrs_queue_type { - PTLRPC_NRS_QUEUE_REG = (1 << 0), - PTLRPC_NRS_QUEUE_HP = (1 << 1), - PTLRPC_NRS_QUEUE_BOTH = (PTLRPC_NRS_QUEUE_REG | PTLRPC_NRS_QUEUE_HP) -}; - -/** - * NRS head - * - * A PTLRPC service has at least one NRS head instance for handling normal - * priority RPCs, and may optionally have a second NRS head instance for - * handling high-priority RPCs. Each NRS head maintains a list of available - * policies, of which one and only one policy is acting as the fallback policy, - * and optionally a different policy may be acting as the primary policy. For - * all RPCs handled by this NRS head instance, NRS core will first attempt to - * enqueue the RPC using the primary policy (if any). The fallback policy is - * used in the following cases: - * - when there was no primary policy in the - * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED state at the time the request - * was initialized. - * - when the primary policy that was at the - * ptlrpc_nrs_pol_state::PTLRPC_NRS_POL_STATE_STARTED state at the time the - * RPC was initialized, denoted it did not wish, or for some other reason was - * not able to handle the request, by returning a non-valid NRS resource - * reference. - * - when the primary policy that was at the - * ptlrpc_nrs_pol_state::PTLRPC_NRS_POL_STATE_STARTED state at the time the - * RPC was initialized, fails later during the request enqueueing stage. - * - * \see nrs_resource_get_safe() - * \see nrs_request_enqueue() - */ -struct ptlrpc_nrs { - spinlock_t nrs_lock; - /** XXX Possibly replace svcpt->scp_req_lock with another lock here. */ - /** - * List of registered policies - */ - struct list_head nrs_policy_list; - /** - * List of policies with queued requests. Policies that have any - * outstanding requests are queued here, and this list is queried - * in a round-robin manner from NRS core when obtaining a request - * for handling. This ensures that requests from policies that at some - * point transition away from the - * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED state are drained. - */ - struct list_head nrs_policy_queued; - /** - * Service partition for this NRS head - */ - struct ptlrpc_service_part *nrs_svcpt; - /** - * Primary policy, which is the preferred policy for handling RPCs - */ - struct ptlrpc_nrs_policy *nrs_policy_primary; - /** - * Fallback policy, which is the backup policy for handling RPCs - */ - struct ptlrpc_nrs_policy *nrs_policy_fallback; - /** - * This NRS head handles either HP or regular requests - */ - enum ptlrpc_nrs_queue_type nrs_queue_type; - /** - * # queued requests from all policies in this NRS head - */ - unsigned long nrs_req_queued; - /** - * # scheduled requests from all policies in this NRS head - */ - unsigned long nrs_req_started; - /** - * # policies on this NRS - */ - unsigned nrs_num_pols; - /** - * This NRS head is in progress of starting a policy - */ - unsigned nrs_policy_starting:1; - /** - * In progress of shutting down the whole NRS head; used during - * unregistration - */ - unsigned nrs_stopping:1; -}; - -#define NRS_POL_NAME_MAX 16 - -struct ptlrpc_nrs_pol_desc; - -/** - * Service compatibility predicate; this determines whether a policy is adequate - * for handling RPCs of a particular PTLRPC service. - * - * XXX:This should give the same result during policy registration and - * unregistration, and for all partitions of a service; so the result should not - * depend on temporal service or other properties, that may influence the - * result. - */ -typedef bool (*nrs_pol_desc_compat_t) (const struct ptlrpc_service *svc, - const struct ptlrpc_nrs_pol_desc *desc); - -struct ptlrpc_nrs_pol_conf { - /** - * Human-readable policy name - */ - char nc_name[NRS_POL_NAME_MAX]; - /** - * NRS operations for this policy - */ - const struct ptlrpc_nrs_pol_ops *nc_ops; - /** - * Service compatibility predicate - */ - nrs_pol_desc_compat_t nc_compat; - /** - * Set for policies that support a single ptlrpc service, i.e. ones that - * have \a pd_compat set to nrs_policy_compat_one(). The variable value - * depicts the name of the single service that such policies are - * compatible with. - */ - const char *nc_compat_svc_name; - /** - * Owner module for this policy descriptor; policies registering from a - * different module to the one the NRS framework is held within - * (currently ptlrpc), should set this field to THIS_MODULE. - */ - struct module *nc_owner; - /** - * Policy registration flags; a bitmask of \e nrs_policy_flags - */ - unsigned nc_flags; -}; - -/** - * NRS policy registering descriptor - * - * Is used to hold a description of a policy that can be passed to NRS core in - * order to register the policy with NRS heads in different PTLRPC services. - */ -struct ptlrpc_nrs_pol_desc { - /** - * Human-readable policy name - */ - char pd_name[NRS_POL_NAME_MAX]; - /** - * Link into nrs_core::nrs_policies - */ - struct list_head pd_list; - /** - * NRS operations for this policy - */ - const struct ptlrpc_nrs_pol_ops *pd_ops; - /** - * Service compatibility predicate - */ - nrs_pol_desc_compat_t pd_compat; - /** - * Set for policies that are compatible with only one PTLRPC service. - * - * \see ptlrpc_nrs_pol_conf::nc_compat_svc_name - */ - const char *pd_compat_svc_name; - /** - * Owner module for this policy descriptor. - * - * We need to hold a reference to the module whenever we might make use - * of any of the module's contents, i.e. - * - If one or more instances of the policy are at a state where they - * might be handling a request, i.e. - * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED or - * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPING as we will have to - * call into the policy's ptlrpc_nrs_pol_ops() handlers. A reference - * is taken on the module when - * \e ptlrpc_nrs_pol_desc::pd_refs becomes 1, and released when it - * becomes 0, so that we hold only one reference to the module maximum - * at any time. - * - * We do not need to hold a reference to the module, even though we - * might use code and data from the module, in the following cases: - * - During external policy registration, because this should happen in - * the module's init() function, in which case the module is safe from - * removal because a reference is being held on the module by the - * kernel, and iirc kmod (and I guess module-init-tools also) will - * serialize any racing processes properly anyway. - * - During external policy unregistration, because this should happen - * in a module's exit() function, and any attempts to start a policy - * instance would need to take a reference on the module, and this is - * not possible once we have reached the point where the exit() - * handler is called. - * - During service registration and unregistration, as service setup - * and cleanup, and policy registration, unregistration and policy - * instance starting, are serialized by \e nrs_core::nrs_mutex, so - * as long as users adhere to the convention of registering policies - * in init() and unregistering them in module exit() functions, there - * should not be a race between these operations. - * - During any policy-specific lprocfs operations, because a reference - * is held by the kernel on a proc entry that has been entered by a - * syscall, so as long as proc entries are removed during unregistration time, - * then unregistration and lprocfs operations will be properly - * serialized. - */ - struct module *pd_owner; - /** - * Bitmask of \e nrs_policy_flags - */ - unsigned pd_flags; - /** - * # of references on this descriptor - */ - atomic_t pd_refs; -}; - -/** - * NRS policy state - * - * Policies transition from one state to the other during their lifetime - */ -enum ptlrpc_nrs_pol_state { - /** - * Not a valid policy state. - */ - NRS_POL_STATE_INVALID, - /** - * Policies are at this state either at the start of their life, or - * transition here when the user selects a different policy to act - * as the primary one. - */ - NRS_POL_STATE_STOPPED, - /** - * Policy is progress of stopping - */ - NRS_POL_STATE_STOPPING, - /** - * Policy is in progress of starting - */ - NRS_POL_STATE_STARTING, - /** - * A policy is in this state in two cases: - * - it is the fallback policy, which is always in this state. - * - it has been activated by the user; i.e. it is the primary policy, - */ - NRS_POL_STATE_STARTED, -}; - -/** - * NRS policy information - * - * Used for obtaining information for the status of a policy via lprocfs - */ -struct ptlrpc_nrs_pol_info { - /** - * Policy name - */ - char pi_name[NRS_POL_NAME_MAX]; - /** - * Current policy state - */ - enum ptlrpc_nrs_pol_state pi_state; - /** - * # RPCs enqueued for later dispatching by the policy - */ - long pi_req_queued; - /** - * # RPCs started for dispatch by the policy - */ - long pi_req_started; - /** - * Is this a fallback policy? - */ - unsigned pi_fallback:1; -}; - -/** - * NRS policy - * - * There is one instance of this for each policy in each NRS head of each - * PTLRPC service partition. - */ -struct ptlrpc_nrs_policy { - /** - * Linkage into the NRS head's list of policies, - * ptlrpc_nrs:nrs_policy_list - */ - struct list_head pol_list; - /** - * Linkage into the NRS head's list of policies with enqueued - * requests ptlrpc_nrs:nrs_policy_queued - */ - struct list_head pol_list_queued; - /** - * Current state of this policy - */ - enum ptlrpc_nrs_pol_state pol_state; - /** - * Bitmask of nrs_policy_flags - */ - unsigned pol_flags; - /** - * # RPCs enqueued for later dispatching by the policy - */ - long pol_req_queued; - /** - * # RPCs started for dispatch by the policy - */ - long pol_req_started; - /** - * Usage Reference count taken on the policy instance - */ - long pol_ref; - /** - * The NRS head this policy has been created at - */ - struct ptlrpc_nrs *pol_nrs; - /** - * Private policy data; varies by policy type - */ - void *pol_private; - /** - * Policy descriptor for this policy instance. - */ - struct ptlrpc_nrs_pol_desc *pol_desc; -}; - -/** - * NRS resource - * - * Resources are embedded into two types of NRS entities: - * - Inside NRS policies, in the policy's private data in - * ptlrpc_nrs_policy::pol_private - * - In objects that act as prime-level scheduling entities in different NRS - * policies; e.g. on a policy that performs round robin or similar order - * scheduling across client NIDs, there would be one NRS resource per unique - * client NID. On a policy which performs round robin scheduling across - * backend filesystem objects, there would be one resource associated with - * each of the backend filesystem objects partaking in the scheduling - * performed by the policy. - * - * NRS resources share a parent-child relationship, in which resources embedded - * in policy instances are the parent entities, with all scheduling entities - * a policy schedules across being the children, thus forming a simple resource - * hierarchy. This hierarchy may be extended with one or more levels in the - * future if the ability to have more than one primary policy is added. - * - * Upon request initialization, references to the then active NRS policies are - * taken and used to later handle the dispatching of the request with one of - * these policies. - * - * \see nrs_resource_get_safe() - * \see ptlrpc_nrs_req_add() - */ -struct ptlrpc_nrs_resource { - /** - * This NRS resource's parent; is NULL for resources embedded in NRS - * policy instances; i.e. those are top-level ones. - */ - struct ptlrpc_nrs_resource *res_parent; - /** - * The policy associated with this resource. - */ - struct ptlrpc_nrs_policy *res_policy; -}; - -enum { - NRS_RES_FALLBACK, - NRS_RES_PRIMARY, - NRS_RES_MAX -}; - -/* \name fifo - * - * FIFO policy - * - * This policy is a logical wrapper around previous, non-NRS functionality. - * It dispatches RPCs in the same order as they arrive from the network. This - * policy is currently used as the fallback policy, and the only enabled policy - * on all NRS heads of all PTLRPC service partitions. - * @{ - */ - -/** - * Private data structure for the FIFO policy - */ -struct nrs_fifo_head { - /** - * Resource object for policy instance. - */ - struct ptlrpc_nrs_resource fh_res; - /** - * List of queued requests. - */ - struct list_head fh_list; - /** - * For debugging purposes. - */ - __u64 fh_sequence; -}; - -struct nrs_fifo_req { - struct list_head fr_list; - __u64 fr_sequence; -}; - -/** @} fifo */ - -/** - * NRS request - * - * Instances of this object exist embedded within ptlrpc_request; the main - * purpose of this object is to hold references to the request's resources - * for the lifetime of the request, and to hold properties that policies use - * use for determining the request's scheduling priority. - */ -struct ptlrpc_nrs_request { - /** - * The request's resource hierarchy. - */ - struct ptlrpc_nrs_resource *nr_res_ptrs[NRS_RES_MAX]; - /** - * Index into ptlrpc_nrs_request::nr_res_ptrs of the resource of the - * policy that was used to enqueue the request. - * - * \see nrs_request_enqueue() - */ - unsigned nr_res_idx; - unsigned nr_initialized:1; - unsigned nr_enqueued:1; - unsigned nr_started:1; - unsigned nr_finalized:1; - - /** - * Policy-specific fields, used for determining a request's scheduling - * priority, and other supporting functionality. - */ - union { - /** - * Fields for the FIFO policy - */ - struct nrs_fifo_req fifo; - } nr_u; - /** - * Externally-registering policies may want to use this to allocate - * their own request properties. - */ - void *ext; -}; - -/** @} nrs */ +#include "lustre_nrs.h" /** * Basic request prioritization operations structure. diff --git a/drivers/staging/lustre/lustre/include/lustre_nrs.h b/drivers/staging/lustre/lustre/include/lustre_nrs.h new file mode 100644 index 000000000000..a5028aaa19cd --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_nrs.h @@ -0,0 +1,717 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2014, Intel Corporation. + * + * Copyright 2012 Xyratex Technology Limited + */ +/* + * + * Network Request Scheduler (NRS) + * + */ + +#ifndef _LUSTRE_NRS_H +#define _LUSTRE_NRS_H + +/** + * \defgroup nrs Network Request Scheduler + * @{ + */ +struct ptlrpc_nrs_policy; +struct ptlrpc_nrs_resource; +struct ptlrpc_nrs_request; + +/** + * NRS control operations. + * + * These are common for all policies. + */ +enum ptlrpc_nrs_ctl { + /** + * Not a valid opcode. + */ + PTLRPC_NRS_CTL_INVALID, + /** + * Activate the policy. + */ + PTLRPC_NRS_CTL_START, + /** + * Reserved for multiple primary policies, which may be a possibility + * in the future. + */ + PTLRPC_NRS_CTL_STOP, + /** + * Policies can start using opcodes from this value and onwards for + * their own purposes; the assigned value itself is arbitrary. + */ + PTLRPC_NRS_CTL_1ST_POL_SPEC = 0x20, +}; + +/** + * NRS policy operations. + * + * These determine the behaviour of a policy, and are called in response to + * NRS core events. + */ +struct ptlrpc_nrs_pol_ops { + /** + * Called during policy registration; this operation is optional. + * + * \param[in,out] policy The policy being initialized + */ + int (*op_policy_init)(struct ptlrpc_nrs_policy *policy); + /** + * Called during policy unregistration; this operation is optional. + * + * \param[in,out] policy The policy being unregistered/finalized + */ + void (*op_policy_fini)(struct ptlrpc_nrs_policy *policy); + /** + * Called when activating a policy via lprocfs; policies allocate and + * initialize their resources here; this operation is optional. + * + * \param[in,out] policy The policy being started + * + * \see nrs_policy_start_locked() + */ + int (*op_policy_start)(struct ptlrpc_nrs_policy *policy); + /** + * Called when deactivating a policy via lprocfs; policies deallocate + * their resources here; this operation is optional + * + * \param[in,out] policy The policy being stopped + * + * \see nrs_policy_stop0() + */ + void (*op_policy_stop)(struct ptlrpc_nrs_policy *policy); + /** + * Used for policy-specific operations; i.e. not generic ones like + * \e PTLRPC_NRS_CTL_START and \e PTLRPC_NRS_CTL_GET_INFO; analogous + * to an ioctl; this operation is optional. + * + * \param[in,out] policy The policy carrying out operation \a opc + * \param[in] opc The command operation being carried out + * \param[in,out] arg An generic buffer for communication between the + * user and the control operation + * + * \retval -ve error + * \retval 0 success + * + * \see ptlrpc_nrs_policy_control() + */ + int (*op_policy_ctl)(struct ptlrpc_nrs_policy *policy, + enum ptlrpc_nrs_ctl opc, void *arg); + + /** + * Called when obtaining references to the resources of the resource + * hierarchy for a request that has arrived for handling at the PTLRPC + * service. Policies should return -ve for requests they do not wish + * to handle. This operation is mandatory. + * + * \param[in,out] policy The policy we're getting resources for. + * \param[in,out] nrq The request we are getting resources for. + * \param[in] parent The parent resource of the resource being + * requested; set to NULL if none. + * \param[out] resp The resource is to be returned here; the + * fallback policy in an NRS head should + * \e always return a non-NULL pointer value. + * \param[in] moving_req When set, signifies that this is an attempt + * to obtain resources for a request being moved + * to the high-priority NRS head by + * ldlm_lock_reorder_req(). + * This implies two things: + * 1. We are under obd_export::exp_rpc_lock and + * so should not sleep. + * 2. We should not perform non-idempotent or can + * skip performing idempotent operations that + * were carried out when resources were first + * taken for the request when it was initialized + * in ptlrpc_nrs_req_initialize(). + * + * \retval 0, +ve The level of the returned resource in the resource + * hierarchy; currently only 0 (for a non-leaf resource) + * and 1 (for a leaf resource) are supported by the + * framework. + * \retval -ve error + * + * \see ptlrpc_nrs_req_initialize() + * \see ptlrpc_nrs_hpreq_add_nolock() + * \see ptlrpc_nrs_req_hp_move() + */ + int (*op_res_get)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq, + const struct ptlrpc_nrs_resource *parent, + struct ptlrpc_nrs_resource **resp, + bool moving_req); + /** + * Called when releasing references taken for resources in the resource + * hierarchy for the request; this operation is optional. + * + * \param[in,out] policy The policy the resource belongs to + * \param[in] res The resource to be freed + * + * \see ptlrpc_nrs_req_finalize() + * \see ptlrpc_nrs_hpreq_add_nolock() + * \see ptlrpc_nrs_req_hp_move() + */ + void (*op_res_put)(struct ptlrpc_nrs_policy *policy, + const struct ptlrpc_nrs_resource *res); + + /** + * Obtains a request for handling from the policy, and optionally + * removes the request from the policy; this operation is mandatory. + * + * \param[in,out] policy The policy to poll + * \param[in] peek When set, signifies that we just want to + * examine the request, and not handle it, so the + * request is not removed from the policy. + * \param[in] force When set, it will force a policy to return a + * request if it has one queued. + * + * \retval NULL No request available for handling + * \retval valid-pointer The request polled for handling + * + * \see ptlrpc_nrs_req_get_nolock() + */ + struct ptlrpc_nrs_request * + (*op_req_get)(struct ptlrpc_nrs_policy *policy, bool peek, + bool force); + /** + * Called when attempting to add a request to a policy for later + * handling; this operation is mandatory. + * + * \param[in,out] policy The policy on which to enqueue \a nrq + * \param[in,out] nrq The request to enqueue + * + * \retval 0 success + * \retval != 0 error + * + * \see ptlrpc_nrs_req_add_nolock() + */ + int (*op_req_enqueue)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); + /** + * Removes a request from the policy's set of pending requests. Normally + * called after a request has been polled successfully from the policy + * for handling; this operation is mandatory. + * + * \param[in,out] policy The policy the request \a nrq belongs to + * \param[in,out] nrq The request to dequeue + * + * \see ptlrpc_nrs_req_del_nolock() + */ + void (*op_req_dequeue)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); + /** + * Called after the request being carried out. Could be used for + * job/resource control; this operation is optional. + * + * \param[in,out] policy The policy which is stopping to handle request + * \a nrq + * \param[in,out] nrq The request + * + * \pre assert_spin_locked(&svcpt->scp_req_lock) + * + * \see ptlrpc_nrs_req_stop_nolock() + */ + void (*op_req_stop)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); + /** + * Registers the policy's lprocfs interface with a PTLRPC service. + * + * \param[in] svc The service + * + * \retval 0 success + * \retval != 0 error + */ + int (*op_lprocfs_init)(struct ptlrpc_service *svc); + /** + * Unegisters the policy's lprocfs interface with a PTLRPC service. + * + * In cases of failed policy registration in + * \e ptlrpc_nrs_policy_register(), this function may be called for a + * service which has not registered the policy successfully, so + * implementations of this method should make sure their operations are + * safe in such cases. + * + * \param[in] svc The service + */ + void (*op_lprocfs_fini)(struct ptlrpc_service *svc); +}; + +/** + * Policy flags + */ +enum nrs_policy_flags { + /** + * Fallback policy, use this flag only on a single supported policy per + * service. The flag cannot be used on policies that use + * \e PTLRPC_NRS_FL_REG_EXTERN + */ + PTLRPC_NRS_FL_FALLBACK = BIT(0), + /** + * Start policy immediately after registering. + */ + PTLRPC_NRS_FL_REG_START = BIT(1), + /** + * This is a policy registering from a module different to the one NRS + * core ships in (currently ptlrpc). + */ + PTLRPC_NRS_FL_REG_EXTERN = BIT(2), +}; + +/** + * NRS queue type. + * + * Denotes whether an NRS instance is for handling normal or high-priority + * RPCs, or whether an operation pertains to one or both of the NRS instances + * in a service. + */ +enum ptlrpc_nrs_queue_type { + PTLRPC_NRS_QUEUE_REG = BIT(0), + PTLRPC_NRS_QUEUE_HP = BIT(1), + PTLRPC_NRS_QUEUE_BOTH = (PTLRPC_NRS_QUEUE_REG | PTLRPC_NRS_QUEUE_HP) +}; + +/** + * NRS head + * + * A PTLRPC service has at least one NRS head instance for handling normal + * priority RPCs, and may optionally have a second NRS head instance for + * handling high-priority RPCs. Each NRS head maintains a list of available + * policies, of which one and only one policy is acting as the fallback policy, + * and optionally a different policy may be acting as the primary policy. For + * all RPCs handled by this NRS head instance, NRS core will first attempt to + * enqueue the RPC using the primary policy (if any). The fallback policy is + * used in the following cases: + * - when there was no primary policy in the + * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED state at the time the request + * was initialized. + * - when the primary policy that was at the + * ptlrpc_nrs_pol_state::PTLRPC_NRS_POL_STATE_STARTED state at the time the + * RPC was initialized, denoted it did not wish, or for some other reason was + * not able to handle the request, by returning a non-valid NRS resource + * reference. + * - when the primary policy that was at the + * ptlrpc_nrs_pol_state::PTLRPC_NRS_POL_STATE_STARTED state at the time the + * RPC was initialized, fails later during the request enqueueing stage. + * + * \see nrs_resource_get_safe() + * \see nrs_request_enqueue() + */ +struct ptlrpc_nrs { + spinlock_t nrs_lock; + /** XXX Possibly replace svcpt->scp_req_lock with another lock here. */ + /** + * List of registered policies + */ + struct list_head nrs_policy_list; + /** + * List of policies with queued requests. Policies that have any + * outstanding requests are queued here, and this list is queried + * in a round-robin manner from NRS core when obtaining a request + * for handling. This ensures that requests from policies that at some + * point transition away from the + * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED state are drained. + */ + struct list_head nrs_policy_queued; + /** + * Service partition for this NRS head + */ + struct ptlrpc_service_part *nrs_svcpt; + /** + * Primary policy, which is the preferred policy for handling RPCs + */ + struct ptlrpc_nrs_policy *nrs_policy_primary; + /** + * Fallback policy, which is the backup policy for handling RPCs + */ + struct ptlrpc_nrs_policy *nrs_policy_fallback; + /** + * This NRS head handles either HP or regular requests + */ + enum ptlrpc_nrs_queue_type nrs_queue_type; + /** + * # queued requests from all policies in this NRS head + */ + unsigned long nrs_req_queued; + /** + * # scheduled requests from all policies in this NRS head + */ + unsigned long nrs_req_started; + /** + * # policies on this NRS + */ + unsigned int nrs_num_pols; + /** + * This NRS head is in progress of starting a policy + */ + unsigned int nrs_policy_starting:1; + /** + * In progress of shutting down the whole NRS head; used during + * unregistration + */ + unsigned int nrs_stopping:1; + /** + * NRS policy is throttling request + */ + unsigned int nrs_throttling:1; +}; + +#define NRS_POL_NAME_MAX 16 +#define NRS_POL_ARG_MAX 16 + +struct ptlrpc_nrs_pol_desc; + +/** + * Service compatibility predicate; this determines whether a policy is adequate + * for handling RPCs of a particular PTLRPC service. + * + * XXX:This should give the same result during policy registration and + * unregistration, and for all partitions of a service; so the result should not + * depend on temporal service or other properties, that may influence the + * result. + */ +typedef bool (*nrs_pol_desc_compat_t)(const struct ptlrpc_service *svc, + const struct ptlrpc_nrs_pol_desc *desc); + +struct ptlrpc_nrs_pol_conf { + /** + * Human-readable policy name + */ + char nc_name[NRS_POL_NAME_MAX]; + /** + * NRS operations for this policy + */ + const struct ptlrpc_nrs_pol_ops *nc_ops; + /** + * Service compatibility predicate + */ + nrs_pol_desc_compat_t nc_compat; + /** + * Set for policies that support a single ptlrpc service, i.e. ones that + * have \a pd_compat set to nrs_policy_compat_one(). The variable value + * depicts the name of the single service that such policies are + * compatible with. + */ + const char *nc_compat_svc_name; + /** + * Owner module for this policy descriptor; policies registering from a + * different module to the one the NRS framework is held within + * (currently ptlrpc), should set this field to THIS_MODULE. + */ + struct module *nc_owner; + /** + * Policy registration flags; a bitmask of \e nrs_policy_flags + */ + unsigned int nc_flags; +}; + +/** + * NRS policy registering descriptor + * + * Is used to hold a description of a policy that can be passed to NRS core in + * order to register the policy with NRS heads in different PTLRPC services. + */ +struct ptlrpc_nrs_pol_desc { + /** + * Human-readable policy name + */ + char pd_name[NRS_POL_NAME_MAX]; + /** + * Link into nrs_core::nrs_policies + */ + struct list_head pd_list; + /** + * NRS operations for this policy + */ + const struct ptlrpc_nrs_pol_ops *pd_ops; + /** + * Service compatibility predicate + */ + nrs_pol_desc_compat_t pd_compat; + /** + * Set for policies that are compatible with only one PTLRPC service. + * + * \see ptlrpc_nrs_pol_conf::nc_compat_svc_name + */ + const char *pd_compat_svc_name; + /** + * Owner module for this policy descriptor. + * + * We need to hold a reference to the module whenever we might make use + * of any of the module's contents, i.e. + * - If one or more instances of the policy are at a state where they + * might be handling a request, i.e. + * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED or + * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPING as we will have to + * call into the policy's ptlrpc_nrs_pol_ops() handlers. A reference + * is taken on the module when + * \e ptlrpc_nrs_pol_desc::pd_refs becomes 1, and released when it + * becomes 0, so that we hold only one reference to the module maximum + * at any time. + * + * We do not need to hold a reference to the module, even though we + * might use code and data from the module, in the following cases: + * - During external policy registration, because this should happen in + * the module's init() function, in which case the module is safe from + * removal because a reference is being held on the module by the + * kernel, and iirc kmod (and I guess module-init-tools also) will + * serialize any racing processes properly anyway. + * - During external policy unregistration, because this should happen + * in a module's exit() function, and any attempts to start a policy + * instance would need to take a reference on the module, and this is + * not possible once we have reached the point where the exit() + * handler is called. + * - During service registration and unregistration, as service setup + * and cleanup, and policy registration, unregistration and policy + * instance starting, are serialized by \e nrs_core::nrs_mutex, so + * as long as users adhere to the convention of registering policies + * in init() and unregistering them in module exit() functions, there + * should not be a race between these operations. + * - During any policy-specific lprocfs operations, because a reference + * is held by the kernel on a proc entry that has been entered by a + * syscall, so as long as proc entries are removed during + * unregistration time, then unregistration and lprocfs operations + * will be properly serialized. + */ + struct module *pd_owner; + /** + * Bitmask of \e nrs_policy_flags + */ + unsigned int pd_flags; + /** + * # of references on this descriptor + */ + atomic_t pd_refs; +}; + +/** + * NRS policy state + * + * Policies transition from one state to the other during their lifetime + */ +enum ptlrpc_nrs_pol_state { + /** + * Not a valid policy state. + */ + NRS_POL_STATE_INVALID, + /** + * Policies are at this state either at the start of their life, or + * transition here when the user selects a different policy to act + * as the primary one. + */ + NRS_POL_STATE_STOPPED, + /** + * Policy is progress of stopping + */ + NRS_POL_STATE_STOPPING, + /** + * Policy is in progress of starting + */ + NRS_POL_STATE_STARTING, + /** + * A policy is in this state in two cases: + * - it is the fallback policy, which is always in this state. + * - it has been activated by the user; i.e. it is the primary policy, + */ + NRS_POL_STATE_STARTED, +}; + +/** + * NRS policy information + * + * Used for obtaining information for the status of a policy via lprocfs + */ +struct ptlrpc_nrs_pol_info { + /** + * Policy name + */ + char pi_name[NRS_POL_NAME_MAX]; + /** + * Policy argument + */ + char pi_arg[NRS_POL_ARG_MAX]; + /** + * Current policy state + */ + enum ptlrpc_nrs_pol_state pi_state; + /** + * # RPCs enqueued for later dispatching by the policy + */ + long pi_req_queued; + /** + * # RPCs started for dispatch by the policy + */ + long pi_req_started; + /** + * Is this a fallback policy? + */ + unsigned pi_fallback:1; +}; + +/** + * NRS policy + * + * There is one instance of this for each policy in each NRS head of each + * PTLRPC service partition. + */ +struct ptlrpc_nrs_policy { + /** + * Linkage into the NRS head's list of policies, + * ptlrpc_nrs:nrs_policy_list + */ + struct list_head pol_list; + /** + * Linkage into the NRS head's list of policies with enqueued + * requests ptlrpc_nrs:nrs_policy_queued + */ + struct list_head pol_list_queued; + /** + * Current state of this policy + */ + enum ptlrpc_nrs_pol_state pol_state; + /** + * Bitmask of nrs_policy_flags + */ + unsigned int pol_flags; + /** + * # RPCs enqueued for later dispatching by the policy + */ + long pol_req_queued; + /** + * # RPCs started for dispatch by the policy + */ + long pol_req_started; + /** + * Usage Reference count taken on the policy instance + */ + long pol_ref; + /** + * Human-readable policy argument + */ + char pol_arg[NRS_POL_ARG_MAX]; + /** + * The NRS head this policy has been created at + */ + struct ptlrpc_nrs *pol_nrs; + /** + * Private policy data; varies by policy type + */ + void *pol_private; + /** + * Policy descriptor for this policy instance. + */ + struct ptlrpc_nrs_pol_desc *pol_desc; +}; + +/** + * NRS resource + * + * Resources are embedded into two types of NRS entities: + * - Inside NRS policies, in the policy's private data in + * ptlrpc_nrs_policy::pol_private + * - In objects that act as prime-level scheduling entities in different NRS + * policies; e.g. on a policy that performs round robin or similar order + * scheduling across client NIDs, there would be one NRS resource per unique + * client NID. On a policy which performs round robin scheduling across + * backend filesystem objects, there would be one resource associated with + * each of the backend filesystem objects partaking in the scheduling + * performed by the policy. + * + * NRS resources share a parent-child relationship, in which resources embedded + * in policy instances are the parent entities, with all scheduling entities + * a policy schedules across being the children, thus forming a simple resource + * hierarchy. This hierarchy may be extended with one or more levels in the + * future if the ability to have more than one primary policy is added. + * + * Upon request initialization, references to the then active NRS policies are + * taken and used to later handle the dispatching of the request with one of + * these policies. + * + * \see nrs_resource_get_safe() + * \see ptlrpc_nrs_req_add() + */ +struct ptlrpc_nrs_resource { + /** + * This NRS resource's parent; is NULL for resources embedded in NRS + * policy instances; i.e. those are top-level ones. + */ + struct ptlrpc_nrs_resource *res_parent; + /** + * The policy associated with this resource. + */ + struct ptlrpc_nrs_policy *res_policy; +}; + +enum { + NRS_RES_FALLBACK, + NRS_RES_PRIMARY, + NRS_RES_MAX +}; + +#include "lustre_nrs_fifo.h" + +/** + * NRS request + * + * Instances of this object exist embedded within ptlrpc_request; the main + * purpose of this object is to hold references to the request's resources + * for the lifetime of the request, and to hold properties that policies use + * use for determining the request's scheduling priority. + **/ +struct ptlrpc_nrs_request { + /** + * The request's resource hierarchy. + */ + struct ptlrpc_nrs_resource *nr_res_ptrs[NRS_RES_MAX]; + /** + * Index into ptlrpc_nrs_request::nr_res_ptrs of the resource of the + * policy that was used to enqueue the request. + * + * \see nrs_request_enqueue() + */ + unsigned int nr_res_idx; + unsigned int nr_initialized:1; + unsigned int nr_enqueued:1; + unsigned int nr_started:1; + unsigned int nr_finalized:1; + + /** + * Policy-specific fields, used for determining a request's scheduling + * priority, and other supporting functionality. + */ + union { + /** + * Fields for the FIFO policy + */ + struct nrs_fifo_req fifo; + } nr_u; + /** + * Externally-registering policies may want to use this to allocate + * their own request properties. + */ + void *ext; +}; + +/** @} nrs */ +#endif diff --git a/drivers/staging/lustre/lustre/include/lustre_nrs_fifo.h b/drivers/staging/lustre/lustre/include/lustre_nrs_fifo.h new file mode 100644 index 000000000000..3b5418eac6c4 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_nrs_fifo.h @@ -0,0 +1,70 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2014, Intel Corporation. + * + * Copyright 2012 Xyratex Technology Limited + */ +/* + * + * Network Request Scheduler (NRS) First-in First-out (FIFO) policy + * + */ + +#ifndef _LUSTRE_NRS_FIFO_H +#define _LUSTRE_NRS_FIFO_H + +/* \name fifo + * + * FIFO policy + * + * This policy is a logical wrapper around previous, non-NRS functionality. + * It dispatches RPCs in the same order as they arrive from the network. This + * policy is currently used as the fallback policy, and the only enabled policy + * on all NRS heads of all PTLRPC service partitions. + * @{ + */ + +/** + * Private data structure for the FIFO policy + */ +struct nrs_fifo_head { + /** + * Resource object for policy instance. + */ + struct ptlrpc_nrs_resource fh_res; + /** + * List of queued requests. + */ + struct list_head fh_list; + /** + * For debugging purposes. + */ + __u64 fh_sequence; +}; + +struct nrs_fifo_req { + struct list_head fr_list; + __u64 fr_sequence; +}; + +/** @} fifo */ +#endif -- cgit v1.2.3 From e57721e7244e64b9e930e8f17a001fa16d5e0b63 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Sun, 2 Oct 2016 22:28:26 -0400 Subject: staging: lustre: quota: remove obsolete quota code Remove the obsolete quotacheck, quotaon and quotaoff, which were retained for the interoperability with old (< 2.4) client and server. Some other obsolete quota code related to LL_IOC_QUOTACTL_18, Q_INVLIDATE and Q_FINVALIDATE are removed as well. Signed-off-by: Niu Yawei Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5975 Reviewed-on: http://review.whamcloud.com/14705 Reviewed-by: Fan Yong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 6 +- .../lustre/lustre/include/lustre/lustre_ioctl.h | 4 +- .../lustre/lustre/include/lustre/lustre_user.h | 13 ++--- .../lustre/lustre/include/lustre_req_layout.h | 3 - drivers/staging/lustre/lustre/include/obd.h | 9 --- drivers/staging/lustre/lustre/include/obd_class.h | 12 ---- .../staging/lustre/lustre/include/obd_support.h | 6 +- drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 2 - drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c | 24 -------- drivers/staging/lustre/lustre/llite/dir.c | 65 ---------------------- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 31 +---------- drivers/staging/lustre/lustre/lov/lov_obd.c | 54 +----------------- drivers/staging/lustre/lustre/mdc/mdc_request.c | 50 ----------------- drivers/staging/lustre/lustre/osc/osc_internal.h | 3 - drivers/staging/lustre/lustre/osc/osc_quota.c | 44 --------------- drivers/staging/lustre/lustre/osc/osc_request.c | 4 -- drivers/staging/lustre/lustre/ptlrpc/layout.c | 15 ----- 17 files changed, 15 insertions(+), 330 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 17feb71ea485..7645ed9a0282 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1406,7 +1406,7 @@ enum ost_cmd { OST_STATFS = 13, OST_SYNC = 16, OST_SET_INFO = 17, - OST_QUOTACHECK = 18, + OST_QUOTACHECK = 18, /* not used since 2.4 */ OST_QUOTACTL = 19, OST_QUOTA_ADJUST_QUNIT = 20, /* not used since 2.4 */ OST_LAST_OPC @@ -1925,7 +1925,7 @@ enum mds_cmd { MDS_SYNC = 44, MDS_DONE_WRITING = 45, /* obsolete since 2.8.0 */ MDS_SET_INFO = 46, - MDS_QUOTACHECK = 47, + MDS_QUOTACHECK = 47, /* not used since 2.4 */ MDS_QUOTACTL = 48, MDS_GETXATTR = 49, MDS_SETXATTR = 50, /* obsolete, now it's MDS_REINT op */ @@ -2889,7 +2889,7 @@ void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size); enum obd_cmd { OBD_PING = 400, OBD_LOG_CANCEL, - OBD_QC_CALLBACK, + OBD_QC_CALLBACK, /* not used since 2.4 */ OBD_IDX_READ, OBD_LAST_OPC }; diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h index f3d7c94c3b50..eb08df33b2db 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h @@ -363,8 +363,8 @@ obd_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len) /* OBD_IOC_LOV_GETSTRIPE 155 LL_IOC_LOV_GETSTRIPE */ /* OBD_IOC_LOV_SETEA 156 LL_IOC_LOV_SETEA */ /* lustre/lustre_user.h 157-159 */ -#define OBD_IOC_QUOTACHECK _IOW('f', 160, int) -#define OBD_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) +/* OBD_IOC_QUOTACHECK _IOW('f', 160, int) */ +/* OBD_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) */ #define OBD_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) /* lustre/lustre_user.h 163-176 */ #define OBD_IOC_CHANGELOG_REG _IOW('f', 177, struct obd_ioctl_data) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 80fecbac1047..856e2f99a8a0 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -557,23 +557,18 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen) #define Q_FINVALIDATE 0x800104 /* deprecated as of 2.4 */ /* these must be explicitly translated into linux Q_* in ll_dir_ioctl */ -#define LUSTRE_Q_QUOTAON 0x800002 /* turn quotas on */ -#define LUSTRE_Q_QUOTAOFF 0x800003 /* turn quotas off */ +#define LUSTRE_Q_QUOTAON 0x800002 /* deprecated as of 2.4 */ +#define LUSTRE_Q_QUOTAOFF 0x800003 /* deprecated as of 2.4 */ #define LUSTRE_Q_GETINFO 0x800005 /* get information about quota files */ #define LUSTRE_Q_SETINFO 0x800006 /* set information about quota files */ #define LUSTRE_Q_GETQUOTA 0x800007 /* get user quota structure */ #define LUSTRE_Q_SETQUOTA 0x800008 /* set user quota structure */ /* lustre-specific control commands */ -#define LUSTRE_Q_INVALIDATE 0x80000b /* invalidate quota data */ -#define LUSTRE_Q_FINVALIDATE 0x80000c /* invalidate filter quota data */ +#define LUSTRE_Q_INVALIDATE 0x80000b /* deprecated as of 2.4 */ +#define LUSTRE_Q_FINVALIDATE 0x80000c /* deprecated as of 2.4 */ #define UGQUOTA 2 /* set both USRQUOTA and GRPQUOTA */ -struct if_quotacheck { - char obd_type[16]; - struct obd_uuid obd_uuid; -}; - #define IDENTITY_DOWNCALL_MAGIC 0x6d6dd629 /* permission */ diff --git a/drivers/staging/lustre/lustre/include/lustre_req_layout.h b/drivers/staging/lustre/lustre/include/lustre_req_layout.h index dd8717eca859..78857b3fdf27 100644 --- a/drivers/staging/lustre/lustre/include/lustre_req_layout.h +++ b/drivers/staging/lustre/lustre/include/lustre_req_layout.h @@ -165,9 +165,7 @@ extern struct req_format RQF_MDS_REINT_LINK; extern struct req_format RQF_MDS_REINT_RENAME; extern struct req_format RQF_MDS_REINT_SETATTR; extern struct req_format RQF_MDS_REINT_SETXATTR; -extern struct req_format RQF_MDS_QUOTACHECK; extern struct req_format RQF_MDS_QUOTACTL; -extern struct req_format RQF_QC_CALLBACK; extern struct req_format RQF_MDS_SWAP_LAYOUTS; /* MDS hsm formats */ extern struct req_format RQF_MDS_HSM_STATE_GET; @@ -180,7 +178,6 @@ extern struct req_format RQF_MDS_HSM_REQUEST; /* OST req_format */ extern struct req_format RQF_OST_CONNECT; extern struct req_format RQF_OST_DISCONNECT; -extern struct req_format RQF_OST_QUOTACHECK; extern struct req_format RQF_OST_QUOTACTL; extern struct req_format RQF_OST_GETATTR; extern struct req_format RQF_OST_SETATTR; diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 8372debbf966..28119011e228 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -345,13 +345,6 @@ struct client_obd { /* also protected by the poorly named _loi_list_lock lock above */ struct osc_async_rc cl_ar; - /* used by quotacheck when the servers are older than 2.4 */ - int cl_qchk_stat; /* quotacheck stat of the peer */ -#define CL_NOT_QUOTACHECKED 1 /* client->cl_qchk_stat init value */ -#if OBD_OCD_VERSION(2, 7, 53, 0) < LUSTRE_VERSION_CODE -#warning "please consider removing quotacheck compatibility code" -#endif - /* sequence manager */ struct lu_client_seq *cl_seq; @@ -930,8 +923,6 @@ struct obd_ops { struct obd_uuid *(*get_uuid)(struct obd_export *exp); /* quota methods */ - int (*quotacheck)(struct obd_device *, struct obd_export *, - struct obd_quotactl *); int (*quotactl)(struct obd_device *, struct obd_export *, struct obd_quotactl *); diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index cb7160e0a99f..8f1d681ababf 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1163,18 +1163,6 @@ static inline int obd_notify_observer(struct obd_device *observer, return rc1 ? rc1 : rc2; } -static inline int obd_quotacheck(struct obd_export *exp, - struct obd_quotactl *oqctl) -{ - int rc; - - EXP_CHECK_DT_OP(exp, quotacheck); - EXP_COUNTER_INCREMENT(exp, quotacheck); - - rc = OBP(exp->exp_obd, quotacheck)(exp->exp_obd, exp, oqctl); - return rc; -} - static inline int obd_quotactl(struct obd_export *exp, struct obd_quotactl *oqctl) { diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 9d2d6f8d7926..1233c3455b6f 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -179,7 +179,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_MDS_STATFS_LCW_SLEEP 0x12a #define OBD_FAIL_MDS_OPEN_CREATE 0x12b #define OBD_FAIL_MDS_OST_SETATTR 0x12c -#define OBD_FAIL_MDS_QUOTACHECK_NET 0x12d +/* OBD_FAIL_MDS_QUOTACHECK_NET 0x12d obsolete since 2.4 */ #define OBD_FAIL_MDS_QUOTACTL_NET 0x12e #define OBD_FAIL_MDS_CLIENT_ADD 0x12f #define OBD_FAIL_MDS_GETXATTR_NET 0x130 @@ -264,7 +264,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_OST_ENOSPC 0x215 #define OBD_FAIL_OST_EROFS 0x216 #define OBD_FAIL_OST_ENOENT 0x217 -#define OBD_FAIL_OST_QUOTACHECK_NET 0x218 +/* OBD_FAIL_OST_QUOTACHECK_NET 0x218 obsolete since 2.4 */ #define OBD_FAIL_OST_QUOTACTL_NET 0x219 #define OBD_FAIL_OST_CHECKSUM_RECEIVE 0x21a #define OBD_FAIL_OST_CHECKSUM_SEND 0x21b @@ -373,7 +373,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_OBD_PING_NET 0x600 #define OBD_FAIL_OBD_LOG_CANCEL_NET 0x601 #define OBD_FAIL_OBD_LOGD_NET 0x602 -#define OBD_FAIL_OBD_QC_CALLBACK_NET 0x603 +/* OBD_FAIL_OBD_QC_CALLBACK_NET 0x603 obsolete since 2.4 */ #define OBD_FAIL_OBD_DQACQ 0x604 #define OBD_FAIL_OBD_LLOG_SETUP 0x605 #define OBD_FAIL_OBD_LOG_CANCEL_REP 0x606 diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 153e990c494e..f3128b671ab3 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -425,8 +425,6 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) goto err_import; } - cli->cl_qchk_stat = CL_NOT_QUOTACHECKED; - return rc; err_import: diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index c32b414c93ba..12647af5a336 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -511,23 +511,6 @@ static inline void ldlm_callback_errmsg(struct ptlrpc_request *req, CWARN("Send reply failed, maybe cause bug 21636.\n"); } -static int ldlm_handle_qc_callback(struct ptlrpc_request *req) -{ - struct obd_quotactl *oqctl; - struct client_obd *cli = &req->rq_export->exp_obd->u.cli; - - oqctl = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL); - if (!oqctl) { - CERROR("Can't unpack obd_quotactl\n"); - return -EPROTO; - } - - oqctl->qc_stat = ptlrpc_status_ntoh(oqctl->qc_stat); - - cli->cl_qchk_stat = oqctl->qc_stat; - return 0; -} - /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */ static int ldlm_callback_handler(struct ptlrpc_request *req) { @@ -577,13 +560,6 @@ static int ldlm_callback_handler(struct ptlrpc_request *req) rc = ldlm_handle_setinfo(req); ldlm_callback_reply(req, rc); return 0; - case OBD_QC_CALLBACK: - req_capsule_set(&req->rq_pill, &RQF_QC_CALLBACK); - if (OBD_FAIL_CHECK(OBD_FAIL_OBD_QC_CALLBACK_NET)) - return 0; - rc = ldlm_handle_qc_callback(req); - ldlm_callback_reply(req, rc); - return 0; default: CERROR("unknown opcode %u\n", lustre_msg_get_opc(req->rq_reqmsg)); diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 360d97f279ea..929c32c6bb10 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -861,10 +861,6 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) int rc = 0; switch (cmd) { - case LUSTRE_Q_INVALIDATE: - case LUSTRE_Q_FINVALIDATE: - case Q_QUOTAON: - case Q_QUOTAOFF: case Q_SETQUOTA: case Q_SETINFO: if (!capable(CFS_CAP_SYS_ADMIN)) @@ -929,10 +925,6 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) QCTL_COPY(oqctl, qctl); rc = obd_quotactl(sbi->ll_md_exp, oqctl); if (rc) { - if (rc != -EALREADY && cmd == Q_QUOTAON) { - oqctl->qc_cmd = Q_QUOTAOFF; - obd_quotactl(sbi->ll_md_exp, oqctl); - } kfree(oqctl); return rc; } @@ -1369,63 +1361,6 @@ out_req: ll_putname(filename); return rc; } - case OBD_IOC_QUOTACHECK: { - struct obd_quotactl *oqctl; - int error = 0; - - if (!capable(CFS_CAP_SYS_ADMIN)) - return -EPERM; - - oqctl = kzalloc(sizeof(*oqctl), GFP_NOFS); - if (!oqctl) - return -ENOMEM; - oqctl->qc_type = arg; - rc = obd_quotacheck(sbi->ll_md_exp, oqctl); - if (rc < 0) { - CDEBUG(D_INFO, "md_quotacheck failed: rc %d\n", rc); - error = rc; - } - - rc = obd_quotacheck(sbi->ll_dt_exp, oqctl); - if (rc < 0) - CDEBUG(D_INFO, "obd_quotacheck failed: rc %d\n", rc); - - kfree(oqctl); - return error ?: rc; - } - case OBD_IOC_POLL_QUOTACHECK: { - struct if_quotacheck *check; - - if (!capable(CFS_CAP_SYS_ADMIN)) - return -EPERM; - - check = kzalloc(sizeof(*check), GFP_NOFS); - if (!check) - return -ENOMEM; - - rc = obd_iocontrol(cmd, sbi->ll_md_exp, 0, (void *)check, - NULL); - if (rc) { - CDEBUG(D_QUOTA, "mdc ioctl %d failed: %d\n", cmd, rc); - if (copy_to_user((void __user *)arg, check, - sizeof(*check))) - CDEBUG(D_QUOTA, "copy_to_user failed\n"); - goto out_poll; - } - - rc = obd_iocontrol(cmd, sbi->ll_dt_exp, 0, (void *)check, - NULL); - if (rc) { - CDEBUG(D_QUOTA, "osc ioctl %d failed: %d\n", cmd, rc); - if (copy_to_user((void __user *)arg, check, - sizeof(*check))) - CDEBUG(D_QUOTA, "copy_to_user failed\n"); - goto out_poll; - } -out_poll: - kfree(check); - return rc; - } case OBD_IOC_QUOTACTL: { struct if_quotactl *qctl; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 7bd7e1585b9c..67969a8d86cc 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1128,9 +1128,7 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, mdc_obd = class_exp2obd(tgt->ltd_exp); mdc_obd->obd_force = obddev->obd_force; err = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg); - if (err == -ENODATA && cmd == OBD_IOC_POLL_QUOTACHECK) { - return err; - } else if (err) { + if (err) { if (tgt->ltd_active) { CERROR("error: iocontrol MDC %s on MDTidx %d cmd %x: err = %d\n", tgt->ltd_uuid.uuid, i, cmd, err); @@ -3243,32 +3241,6 @@ static int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, return rc; } -static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, - struct obd_quotactl *oqctl) -{ - struct obd_device *obd = class_exp2obd(exp); - struct lmv_obd *lmv = &obd->u.lmv; - struct lmv_tgt_desc *tgt; - int rc = 0; - u32 i; - - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - int err; - - tgt = lmv->tgts[i]; - if (!tgt || !tgt->ltd_exp || !tgt->ltd_active) { - CERROR("lmv idx %d inactive\n", i); - return -EIO; - } - - err = obd_quotacheck(tgt->ltd_exp, oqctl); - if (err && !rc) - rc = err; - } - - return rc; -} - static int lmv_merge_attr(struct obd_export *exp, const struct lmv_stripe_md *lsm, struct cl_attr *attr, @@ -3326,7 +3298,6 @@ static struct obd_ops lmv_obd_ops = { .notify = lmv_notify, .get_uuid = lmv_get_uuid, .iocontrol = lmv_iocontrol, - .quotacheck = lmv_quotacheck, .quotactl = lmv_quotactl }; diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 019fe952396b..c2a853cc776d 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1217,8 +1217,6 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, osc_obd->obd_force = obddev->obd_force; err = obd_iocontrol(cmd, lov->lov_tgts[i]->ltd_exp, len, karg, uarg); - if (err == -ENODATA && cmd == OBD_IOC_POLL_QUOTACHECK) - return err; if (err) { if (lov->lov_tgts[i]->ltd_active) { CDEBUG(err == -ENOTTY ? @@ -1355,12 +1353,8 @@ static int lov_quotactl(struct obd_device *obd, struct obd_export *exp, __u64 bhardlimit = 0; int i, rc = 0; - if (oqctl->qc_cmd != LUSTRE_Q_QUOTAON && - oqctl->qc_cmd != LUSTRE_Q_QUOTAOFF && - oqctl->qc_cmd != Q_GETOQUOTA && - oqctl->qc_cmd != Q_INITQUOTA && - oqctl->qc_cmd != LUSTRE_Q_SETQUOTA && - oqctl->qc_cmd != Q_FINVALIDATE) { + if (oqctl->qc_cmd != Q_GETOQUOTA && + oqctl->qc_cmd != LUSTRE_Q_SETQUOTA) { CERROR("bad quota opc %x for lov obd\n", oqctl->qc_cmd); return -EFAULT; } @@ -1407,49 +1401,6 @@ static int lov_quotactl(struct obd_device *obd, struct obd_export *exp, return rc; } -static int lov_quotacheck(struct obd_device *obd, struct obd_export *exp, - struct obd_quotactl *oqctl) -{ - struct lov_obd *lov = &obd->u.lov; - int i, rc = 0; - - obd_getref(obd); - - for (i = 0; i < lov->desc.ld_tgt_count; i++) { - if (!lov->lov_tgts[i]) - continue; - - /* Skip quota check on the administratively disabled OSTs. */ - if (!lov->lov_tgts[i]->ltd_activate) { - CWARN("lov idx %d was administratively disabled, skip quotacheck on it.\n", - i); - continue; - } - - if (!lov->lov_tgts[i]->ltd_active) { - CERROR("lov idx %d inactive\n", i); - rc = -EIO; - goto out; - } - } - - for (i = 0; i < lov->desc.ld_tgt_count; i++) { - int err; - - if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_activate) - continue; - - err = obd_quotacheck(lov->lov_tgts[i]->ltd_exp, oqctl); - if (err && !rc) - rc = err; - } - -out: - obd_putref(obd); - - return rc; -} - static struct obd_ops lov_obd_ops = { .owner = THIS_MODULE, .setup = lov_setup, @@ -1473,7 +1424,6 @@ static struct obd_ops lov_obd_ops = { .getref = lov_getref, .putref = lov_putref, .quotactl = lov_quotactl, - .quotacheck = lov_quotacheck, }; struct kmem_cache *lov_oinfo_slab; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 1d1eaa5238ad..b62b29fee594 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1929,52 +1929,6 @@ static int mdc_ioc_changelog_send(struct obd_device *obd, static int mdc_ioc_hsm_ct_start(struct obd_export *exp, struct lustre_kernelcomm *lk); -static int mdc_quotacheck(struct obd_device *unused, struct obd_export *exp, - struct obd_quotactl *oqctl) -{ - struct client_obd *cli = &exp->exp_obd->u.cli; - struct ptlrpc_request *req; - struct obd_quotactl *body; - int rc; - - req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), - &RQF_MDS_QUOTACHECK, LUSTRE_MDS_VERSION, - MDS_QUOTACHECK); - if (!req) - return -ENOMEM; - - body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL); - *body = *oqctl; - - ptlrpc_request_set_replen(req); - - /* the next poll will find -ENODATA, that means quotacheck is - * going on - */ - cli->cl_qchk_stat = -ENODATA; - rc = ptlrpc_queue_wait(req); - if (rc) - cli->cl_qchk_stat = rc; - ptlrpc_req_finished(req); - return rc; -} - -static int mdc_quota_poll_check(struct obd_export *exp, - struct if_quotacheck *qchk) -{ - struct client_obd *cli = &exp->exp_obd->u.cli; - int rc; - - qchk->obd_uuid = cli->cl_target_uuid; - memcpy(qchk->obd_type, LUSTRE_MDS_NAME, strlen(LUSTRE_MDS_NAME)); - - rc = cli->cl_qchk_stat; - /* the client is not the previous one */ - if (rc == CL_NOT_QUOTACHECKED) - rc = -EINTR; - return rc; -} - static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp, struct obd_quotactl *oqctl) { @@ -2129,9 +2083,6 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, case IOC_OSC_SET_ACTIVE: rc = ptlrpc_set_import_active(imp, data->ioc_offset); goto out; - case OBD_IOC_POLL_QUOTACHECK: - rc = mdc_quota_poll_check(exp, (struct if_quotacheck *)karg); - goto out; case OBD_IOC_PING_TARGET: rc = ptlrpc_obd_ping(obd); goto out; @@ -2794,7 +2745,6 @@ static struct obd_ops mdc_obd_ops = { .process_config = mdc_process_config, .get_uuid = mdc_get_uuid, .quotactl = mdc_quotactl, - .quotacheck = mdc_quotacheck }; static struct md_ops mdc_md_ops = { diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 64684c4a8d51..61bfacb29759 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -190,9 +190,6 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[], int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[]); int osc_quotactl(struct obd_device *unused, struct obd_export *exp, struct obd_quotactl *oqctl); -int osc_quotacheck(struct obd_device *unused, struct obd_export *exp, - struct obd_quotactl *oqctl); -int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk); void osc_inc_unstable_pages(struct ptlrpc_request *req); void osc_dec_unstable_pages(struct ptlrpc_request *req); bool osc_over_unstable_soft_limit(struct client_obd *cli); diff --git a/drivers/staging/lustre/lustre/osc/osc_quota.c b/drivers/staging/lustre/lustre/osc/osc_quota.c index 194d8ede40a2..acdd91a72bd7 100644 --- a/drivers/staging/lustre/lustre/osc/osc_quota.c +++ b/drivers/staging/lustre/lustre/osc/osc_quota.c @@ -281,47 +281,3 @@ int osc_quotactl(struct obd_device *unused, struct obd_export *exp, return rc; } - -int osc_quotacheck(struct obd_device *unused, struct obd_export *exp, - struct obd_quotactl *oqctl) -{ - struct client_obd *cli = &exp->exp_obd->u.cli; - struct ptlrpc_request *req; - struct obd_quotactl *body; - int rc; - - req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), - &RQF_OST_QUOTACHECK, LUSTRE_OST_VERSION, - OST_QUOTACHECK); - if (!req) - return -ENOMEM; - - body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL); - *body = *oqctl; - - ptlrpc_request_set_replen(req); - - /* the next poll will find -ENODATA, that means quotacheck is going on - */ - cli->cl_qchk_stat = -ENODATA; - rc = ptlrpc_queue_wait(req); - if (rc) - cli->cl_qchk_stat = rc; - ptlrpc_req_finished(req); - return rc; -} - -int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk) -{ - struct client_obd *cli = &exp->exp_obd->u.cli; - int rc; - - qchk->obd_uuid = cli->cl_target_uuid; - memcpy(qchk->obd_type, LUSTRE_OST_NAME, strlen(LUSTRE_OST_NAME)); - - rc = cli->cl_qchk_stat; - /* the client is not the previous one */ - if (rc == CL_NOT_QUOTACHECKED) - rc = -EINTR; - return rc; -} diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 2e4d2d5963fc..ab7f82d612e6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2443,9 +2443,6 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, err = ptlrpc_set_import_active(obd->u.cli.cl_import, data->ioc_offset); goto out; - case OBD_IOC_POLL_QUOTACHECK: - err = osc_quota_poll_check(exp, karg); - goto out; case OBD_IOC_PING_TARGET: err = ptlrpc_obd_ping(obd); goto out; @@ -2934,7 +2931,6 @@ static struct obd_ops osc_obd_ops = { .import_event = osc_import_event, .process_config = osc_process_config, .quotactl = osc_quotactl, - .quotacheck = osc_quotacheck, }; extern struct lu_kmem_descr osc_caches[]; diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index 358c124e31ab..f0e044805bc5 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -680,7 +680,6 @@ static struct req_format *req_formats[] = { &RQF_MDS_REINT_RENAME, &RQF_MDS_REINT_SETATTR, &RQF_MDS_REINT_SETXATTR, - &RQF_MDS_QUOTACHECK, &RQF_MDS_QUOTACTL, &RQF_MDS_HSM_PROGRESS, &RQF_MDS_HSM_CT_REGISTER, @@ -690,10 +689,8 @@ static struct req_format *req_formats[] = { &RQF_MDS_HSM_ACTION, &RQF_MDS_HSM_REQUEST, &RQF_MDS_SWAP_LAYOUTS, - &RQF_QC_CALLBACK, &RQF_OST_CONNECT, &RQF_OST_DISCONNECT, - &RQF_OST_QUOTACHECK, &RQF_OST_QUOTACTL, &RQF_OST_GETATTR, &RQF_OST_SETATTR, @@ -1179,14 +1176,6 @@ struct req_format RQF_LOG_CANCEL = DEFINE_REQ_FMT0("OBD_LOG_CANCEL", log_cancel_client, empty); EXPORT_SYMBOL(RQF_LOG_CANCEL); -struct req_format RQF_MDS_QUOTACHECK = - DEFINE_REQ_FMT0("MDS_QUOTACHECK", quotactl_only, empty); -EXPORT_SYMBOL(RQF_MDS_QUOTACHECK); - -struct req_format RQF_OST_QUOTACHECK = - DEFINE_REQ_FMT0("OST_QUOTACHECK", quotactl_only, empty); -EXPORT_SYMBOL(RQF_OST_QUOTACHECK); - struct req_format RQF_MDS_QUOTACTL = DEFINE_REQ_FMT0("MDS_QUOTACTL", quotactl_only, quotactl_only); EXPORT_SYMBOL(RQF_MDS_QUOTACTL); @@ -1195,10 +1184,6 @@ struct req_format RQF_OST_QUOTACTL = DEFINE_REQ_FMT0("OST_QUOTACTL", quotactl_only, quotactl_only); EXPORT_SYMBOL(RQF_OST_QUOTACTL); -struct req_format RQF_QC_CALLBACK = - DEFINE_REQ_FMT0("QC_CALLBACK", quotactl_only, empty); -EXPORT_SYMBOL(RQF_QC_CALLBACK); - struct req_format RQF_MDS_GETSTATUS = DEFINE_REQ_FMT0("MDS_GETSTATUS", mdt_body_only, mdt_body_capa); EXPORT_SYMBOL(RQF_MDS_GETSTATUS); -- cgit v1.2.3 From 0a4bea92409b6846f0da7cb3b463629e8e4b7f92 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:27 -0400 Subject: staging: lustre: obd: remove destroy cookie handling Clients no longer need to track the max and default MDS cookiesizes so remove the obsolete obod o_valid flag OBD_MD_FLCOOKIE, the struct client_obd members cl_{default,max}_mds_cookiesize, the struct obd_trans_info and parameters of this type, the cookiesize parameters from md_init_ea_size(), the files llite/*/{default,max}_cookiesize, and any code that needlessly handled these values. Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6017 Reviewed-on: http://review.whamcloud.com/12922 Reviewed-by: Lai Siyao Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 7 +-- drivers/staging/lustre/lustre/include/lustre_mdc.h | 20 +++---- drivers/staging/lustre/lustre/include/obd.h | 46 +++------------- drivers/staging/lustre/lustre/include/obd_class.h | 31 +++++------ drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 3 +- drivers/staging/lustre/lustre/llite/lcommon_misc.c | 13 ++--- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 23 +++----- .../staging/lustre/lustre/lov/lov_cl_internal.h | 1 - drivers/staging/lustre/lustre/lov/lov_internal.h | 2 - drivers/staging/lustre/lustre/lov/lov_request.c | 1 - drivers/staging/lustre/lustre/mdc/mdc_locks.c | 2 - drivers/staging/lustre/lustre/mdc/mdc_reint.c | 4 -- drivers/staging/lustre/lustre/mdc/mdc_request.c | 15 ++---- .../staging/lustre/lustre/obdecho/echo_client.c | 58 +++++++------------- drivers/staging/lustre/lustre/osc/osc_request.c | 62 +++++----------------- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 4 +- drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 10 ++-- 17 files changed, 79 insertions(+), 223 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 7645ed9a0282..5d2f845599f2 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1664,7 +1664,7 @@ lov_mds_md_max_stripe_count(size_t buf_size, __u32 lmm_magic) #define OBD_MD_FLCKSUM (0x00100000ULL) /* bulk data checksum */ #define OBD_MD_FLQOS (0x00200000ULL) /* quality of service stats */ /*#define OBD_MD_FLOSCOPQ (0x00400000ULL) osc opaque data, never used */ -#define OBD_MD_FLCOOKIE (0x00800000ULL) /* log cancellation cookie */ +/* OBD_MD_FLCOOKIE (0x00800000ULL) obsolete in 2.8 */ #define OBD_MD_FLGROUP (0x01000000ULL) /* group */ #define OBD_MD_FLFID (0x02000000ULL) /* ->ost write inline fid */ #define OBD_MD_FLEPOCH (0x04000000ULL) /* ->ost write with ioepoch */ @@ -2091,7 +2091,7 @@ struct mdt_body { __u32 mbo_eadatasize; __u32 mbo_aclsize; __u32 mbo_max_mdsize; - __u32 mbo_max_cookiesize; + __u32 mbo_unused3; /* was max_cookiesize until 2.8 */ __u32 mbo_uid_h; /* high 32-bits of uid, for FUID */ __u32 mbo_gid_h; /* high 32-bits of gid, for FUID */ __u32 mbo_padding_5; /* also fix lustre_swab_mdt_body */ @@ -3226,7 +3226,8 @@ struct obdo { __u32 o_parent_ver; struct lustre_handle o_handle; /* brw: lock handle to prolong locks */ - struct llog_cookie o_lcookie; /* destroy: unlink cookie from MDS + struct llog_cookie o_lcookie; /* destroy: unlink cookie from MDS, + * obsolete in 2.8, reused in OSP */ __u32 o_uid_h; __u32 o_gid_h; diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index 8fc2d3f2dfd6..92a5c0fe2b67 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -157,15 +157,14 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, } /** - * Update the maximum possible easize and cookiesize. + * Update the maximum possible easize. * - * The values are learned from ptlrpc replies sent by the MDT. The - * default easize and cookiesize is initialized to the minimum value but - * allowed to grow up to a single page in size if required to handle the + * This value is learned from ptlrpc replies sent by the MDT. The + * default easize is initialized to the minimum value but allowed + * to grow up to a single page in size if required to handle the * common case. * - * \see client_obd::cl_default_mds_easize and - * client_obd::cl_default_mds_cookiesize + * \see client_obd::cl_default_mds_easize * * \param[in] exp export for MDC device * \param[in] body body of ptlrpc reply from MDT @@ -176,7 +175,7 @@ static inline void mdc_update_max_ea_from_body(struct obd_export *exp, { if (body->mbo_valid & OBD_MD_FLMODEASIZE) { struct client_obd *cli = &exp->exp_obd->u.cli; - u32 def_cookiesize, def_easize; + u32 def_easize; if (cli->cl_max_mds_easize < body->mbo_max_mdsize) cli->cl_max_mds_easize = body->mbo_max_mdsize; @@ -184,13 +183,6 @@ static inline void mdc_update_max_ea_from_body(struct obd_export *exp, def_easize = min_t(__u32, body->mbo_max_mdsize, OBD_MAX_DEFAULT_EA_SIZE); cli->cl_default_mds_easize = def_easize; - - if (cli->cl_max_mds_cookiesize < body->mbo_max_cookiesize) - cli->cl_max_mds_cookiesize = body->mbo_max_cookiesize; - - def_cookiesize = min_t(__u32, body->mbo_max_cookiesize, - OBD_MAX_DEFAULT_COOKIE_SIZE); - cli->cl_default_mds_cookiesize = def_cookiesize; } } diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 28119011e228..469112174f41 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -204,7 +204,6 @@ enum obd_cl_sem_lock_class { * on the MDS. */ #define OBD_MAX_DEFAULT_EA_SIZE 4096 -#define OBD_MAX_DEFAULT_COOKIE_SIZE 4096 struct mdc_rpc_lock; struct obd_import; @@ -214,7 +213,7 @@ struct client_obd { struct obd_import *cl_import; /* ptlrpc connection state */ size_t cl_conn_count; /* - * Cache maximum and default values for easize and cookiesize. This is + * Cache maximum and default values for easize. This is * strictly a performance optimization to minimize calls to * obd_size_diskmd(). The default values are used to calculate the * initial size of a request buffer. The ptlrpc layer will resize the @@ -235,18 +234,6 @@ struct client_obd { * run-time if a larger observed size is advertised by the MDT. */ u32 cl_max_mds_easize; - /* Default cookie size for llog cookies (see struct llog_cookie). It is - * initialized to zero at mount-time, then it tracks the largest - * observed cookie size advertised by the MDT, up to a maximum value of - * OBD_MAX_DEFAULT_COOKIE_SIZE. Note that llog_cookies are not - * used by clients communicating with MDS versions 2.4.0 and later. - */ - u32 cl_default_mds_cookiesize; - /* Maximum possible cookie size computed at mount-time based on - * the number of OSTs in the filesystem. May be increased at - * run-time if a larger observed size is advertised by the MDT. - */ - u32 cl_max_mds_cookiesize; enum lustre_sec_part cl_sp_me; enum lustre_sec_part cl_sp_to; @@ -447,8 +434,6 @@ struct lmv_obd { int connected; int max_easize; int max_def_easize; - int max_cookiesize; - int max_def_cookiesize; u32 tgts_size; /* size of tgts array */ struct lmv_tgt_desc **tgts; @@ -505,21 +490,6 @@ struct niobuf_local { /* Don't conflict with on-wire flags OBD_BRW_WRITE, etc */ #define N_LOCAL_TEMP_PAGE 0x10000000 -struct obd_trans_info { - __u64 oti_xid; - /* Only used on the server side for tracking acks. */ - struct oti_req_ack_lock { - struct lustre_handle lock; - __u32 mode; - } oti_ack_locks[4]; - void *oti_handle; - struct llog_cookie oti_onecookie; - struct llog_cookie *oti_logcookies; - - /** VBR: versions */ - __u64 oti_pre_version; -}; - /* * Events signalled through obd_notify() upcall-chain. */ @@ -891,24 +861,22 @@ struct obd_ops { struct lov_stripe_md **mem_tgt, struct lov_mds_md *disk_src, int disk_len); int (*create)(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct obd_trans_info *oti); + struct obdo *oa); int (*destroy)(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct obd_trans_info *oti); + struct obdo *oa); int (*setattr)(const struct lu_env *, struct obd_export *exp, - struct obd_info *oinfo, struct obd_trans_info *oti); + struct obd_info *oinfo); int (*getattr)(const struct lu_env *env, struct obd_export *exp, struct obd_info *oinfo); int (*preprw)(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *remote, - int *nr_pages, struct niobuf_local *local, - struct obd_trans_info *oti); + int *nr_pages, struct niobuf_local *local); int (*commitrw)(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *remote, int pages, - struct niobuf_local *local, - struct obd_trans_info *oti, int rc); + struct niobuf_local *local, int rc); int (*init_export)(struct obd_export *exp); int (*destroy_export)(struct obd_export *exp); @@ -1018,7 +986,7 @@ struct md_ops { u64, const char *, const char *, int, int, int, struct ptlrpc_request **); - int (*init_ea_size)(struct obd_export *, u32, u32, u32, u32); + int (*init_ea_size)(struct obd_export *, u32, u32); int (*get_lustre_md)(struct obd_export *, struct ptlrpc_request *, struct obd_export *, struct obd_export *, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 8f1d681ababf..a27dbc8f4e28 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -686,26 +686,26 @@ static inline int obd_free_memmd(struct obd_export *exp, } static inline int obd_create(const struct lu_env *env, struct obd_export *exp, - struct obdo *obdo, struct obd_trans_info *oti) + struct obdo *obdo) { int rc; EXP_CHECK_DT_OP(exp, create); EXP_COUNTER_INCREMENT(exp, create); - rc = OBP(exp->exp_obd, create)(env, exp, obdo, oti); + rc = OBP(exp->exp_obd, create)(env, exp, obdo); return rc; } static inline int obd_destroy(const struct lu_env *env, struct obd_export *exp, - struct obdo *obdo, struct obd_trans_info *oti) + struct obdo *obdo) { int rc; EXP_CHECK_DT_OP(exp, destroy); EXP_COUNTER_INCREMENT(exp, destroy); - rc = OBP(exp->exp_obd, destroy)(env, exp, obdo, oti); + rc = OBP(exp->exp_obd, destroy)(env, exp, obdo); return rc; } @@ -722,15 +722,14 @@ static inline int obd_getattr(const struct lu_env *env, struct obd_export *exp, } static inline int obd_setattr(const struct lu_env *env, struct obd_export *exp, - struct obd_info *oinfo, - struct obd_trans_info *oti) + struct obd_info *oinfo) { int rc; EXP_CHECK_DT_OP(exp, setattr); EXP_COUNTER_INCREMENT(exp, setattr); - rc = OBP(exp->exp_obd, setattr)(env, exp, oinfo, oti); + rc = OBP(exp->exp_obd, setattr)(env, exp, oinfo); return rc; } @@ -1056,8 +1055,7 @@ static inline int obd_preprw(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *remote, int *pages, - struct niobuf_local *local, - struct obd_trans_info *oti) + struct niobuf_local *local) { int rc; @@ -1065,7 +1063,7 @@ static inline int obd_preprw(const struct lu_env *env, int cmd, EXP_COUNTER_INCREMENT(exp, preprw); rc = OBP(exp->exp_obd, preprw)(env, cmd, exp, oa, objcount, obj, remote, - pages, local, oti); + pages, local); return rc; } @@ -1073,14 +1071,13 @@ static inline int obd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *rnb, int pages, - struct niobuf_local *local, - struct obd_trans_info *oti, int rc) + struct niobuf_local *local, int rc) { EXP_CHECK_DT_OP(exp, commitrw); EXP_COUNTER_INCREMENT(exp, commitrw); rc = OBP(exp->exp_obd, commitrw)(env, cmd, exp, oa, objcount, obj, - rnb, pages, local, oti, rc); + rnb, pages, local, rc); return rc; } @@ -1507,14 +1504,12 @@ static inline enum ldlm_mode md_lock_match(struct obd_export *exp, __u64 flags, policy, mode, lockh); } -static inline int md_init_ea_size(struct obd_export *exp, int easize, - int def_asize, int cookiesize, - int def_cookiesize) +static inline int md_init_ea_size(struct obd_export *exp, u32 easize, + u32 def_asize) { EXP_CHECK_MD_OP(exp, init_ea_size); EXP_MD_COUNTER_INCREMENT(exp, init_ea_size); - return MDP(exp->exp_obd, init_ea_size)(exp, easize, def_asize, - cookiesize, def_cookiesize); + return MDP(exp->exp_obd, init_ea_size)(exp, easize, def_asize); } static inline int md_intent_getattr_async(struct obd_export *exp, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index f3128b671ab3..4f9480e5ca5b 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -399,9 +399,8 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) } cli->cl_import = imp; - /* cli->cl_max_mds_{easize,cookiesize} updated by mdc_init_ea_size() */ + /* cli->cl_max_mds_easize updated by mdc_init_ea_size() */ cli->cl_max_mds_easize = sizeof(struct lov_mds_md_v3); - cli->cl_max_mds_cookiesize = sizeof(struct llog_cookie); if (LUSTRE_CFG_BUFLEN(lcfg, 3) > 0) { if (!strcmp(lustre_cfg_string(lcfg, 3), "inactive")) { diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index 07d38e55454b..4562643c2aad 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -49,7 +49,7 @@ int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp) { struct lov_stripe_md lsm = { .lsm_magic = LOV_MAGIC_V3 }; __u32 valsize = sizeof(struct lov_desc); - int rc, easize, def_easize, cookiesize; + int rc, easize, def_easize; struct lov_desc desc; __u16 stripes, def_stripes; @@ -67,16 +67,9 @@ int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp) lsm.lsm_stripe_count = def_stripes; def_easize = obd_size_diskmd(dt_exp, &lsm); - cookiesize = stripes * sizeof(struct llog_cookie); + CDEBUG(D_HA, "updating def/max_easize: %d/%d\n", def_easize, easize); - /* default cookiesize is 0 because from 2.4 server doesn't send - * llog cookies to client. - */ - CDEBUG(D_HA, - "updating def/max_easize: %d/%d def/max_cookiesize: 0/%d\n", - def_easize, easize, cookiesize); - - rc = md_init_ea_size(md_exp, easize, def_easize, cookiesize, 0); + rc = md_init_ea_size(md_exp, easize, def_easize); return rc; } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 67969a8d86cc..75f595820880 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -245,8 +245,7 @@ static int lmv_connect(const struct lu_env *env, return rc; } -static int lmv_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, - u32 cookiesize, u32 def_cookiesize) +static int lmv_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -262,14 +261,7 @@ static int lmv_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, lmv->max_def_easize = def_easize; change = 1; } - if (lmv->max_cookiesize < cookiesize) { - lmv->max_cookiesize = cookiesize; - change = 1; - } - if (lmv->max_def_cookiesize < def_cookiesize) { - lmv->max_def_cookiesize = def_cookiesize; - change = 1; - } + if (change == 0) return 0; @@ -284,8 +276,7 @@ static int lmv_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, continue; } - rc = md_init_ea_size(tgt->ltd_exp, easize, def_easize, - cookiesize, def_cookiesize); + rc = md_init_ea_size(tgt->ltd_exp, easize, def_easize); if (rc) { CERROR("%s: obd_init_ea_size() failed on MDT target %d: rc = %d\n", obd->obd_name, i, rc); @@ -368,8 +359,7 @@ static int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) tgt->ltd_exp = mdc_exp; lmv->desc.ld_active_tgt_count++; - md_init_ea_size(tgt->ltd_exp, lmv->max_easize, lmv->max_def_easize, - lmv->max_cookiesize, lmv->max_def_cookiesize); + md_init_ea_size(tgt->ltd_exp, lmv->max_easize, lmv->max_def_easize); CDEBUG(D_CONFIG, "Connected to %s(%s) successfully (%d)\n", mdc_obd->obd_name, mdc_obd->obd_uuid.uuid, @@ -483,7 +473,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, } else { int easize = sizeof(struct lmv_stripe_md) + lmv->desc.ld_tgt_count * sizeof(struct lu_fid); - lmv_init_ea_size(obd->obd_self_export, easize, 0, 0, 0); + lmv_init_ea_size(obd->obd_self_export, easize, 0); } } @@ -538,7 +528,7 @@ int lmv_check_connect(struct obd_device *obd) class_export_put(lmv->exp); lmv->connected = 1; easize = lmv_mds_md_size(lmv->desc.ld_tgt_count, LMV_MAGIC); - lmv_init_ea_size(obd->obd_self_export, easize, 0, 0, 0); + lmv_init_ea_size(obd->obd_self_export, easize, 0); mutex_unlock(&lmv->lmv_init_mutex); return 0; @@ -1282,7 +1272,6 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg) obd_str2uuid(&lmv->desc.ld_uuid, desc->ld_uuid.uuid); lmv->desc.ld_tgt_count = 0; lmv->desc.ld_active_tgt_count = 0; - lmv->max_cookiesize = 0; lmv->max_def_easize = 0; lmv->max_easize = 0; lmv->lmv_placement = PLACEMENT_CHAR_POLICY; diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 4d2b7d303fea..2b03938f6a63 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -412,7 +412,6 @@ struct lov_io_sub { int sub_refcheck; int sub_refcheck2; int sub_reenter; - void *sub_cookie; }; /** diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 60397a28ef58..bd105d97cc5a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -110,8 +110,6 @@ struct lov_request_set { atomic_t set_completes; atomic_t set_success; atomic_t set_finish_checked; - struct llog_cookie *set_cookies; - int set_cookie_sent; struct list_head set_list; wait_queue_head_t set_waitq; }; diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 42e66d1541a6..c8734a6ea502 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -44,7 +44,6 @@ static void lov_init_set(struct lov_request_set *set) atomic_set(&set->set_completes, 0); atomic_set(&set->set_success, 0); atomic_set(&set->set_finish_checked, 0); - set->set_cookies = NULL; INIT_LIST_HEAD(&set->set_list); atomic_set(&set->set_refcount, 1); init_waitqueue_head(&set->set_waitq); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index f1f6c082fa42..5b3d0ba616a5 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -386,8 +386,6 @@ static struct ptlrpc_request *mdc_intent_unlink_pack(struct obd_export *exp, req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, obddev->u.cli.cl_default_mds_easize); - req_capsule_set_size(&req->rq_pill, &RMF_ACL, RCL_SERVER, - obddev->u.cli.cl_default_mds_cookiesize); ptlrpc_request_set_replen(req); return req; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index 6f62a95bff5b..1847e5a47022 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -288,8 +288,6 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, obd->u.cli.cl_default_mds_easize); - req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_SERVER, - obd->u.cli.cl_default_mds_cookiesize); ptlrpc_request_set_replen(req); *request = req; @@ -398,8 +396,6 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, obd->u.cli.cl_default_mds_easize); - req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_SERVER, - obd->u.cli.cl_default_mds_cookiesize); ptlrpc_request_set_replen(req); rc = mdc_reint(req, obd->u.cli.cl_rpc_lock, LUSTRE_IMP_FULL); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index b62b29fee594..34ccff85ea5b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -787,8 +787,6 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, obd->u.cli.cl_default_mds_easize); - req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_SERVER, - obd->u.cli.cl_default_mds_cookiesize); ptlrpc_request_set_replen(req); @@ -2646,16 +2644,15 @@ err_rpc_lock: return rc; } -/* Initialize the default and maximum LOV EA and cookie sizes. This allows +/* Initialize the default and maximum LOV EA sizes. This allows * us to make MDS RPCs with large enough reply buffers to hold a default - * sized EA and cookie without having to calculate this (via a call into the + * sized EA without having to calculate this (via a call into the * LOV + OSCs) each time we make an RPC. The maximum size is also tracked * but not used to avoid wastefully vmalloc()'ing large reply buffers when * a large number of stripes is possible. If a larger reply buffer is * required it will be reallocated in the ptlrpc layer due to overflow. */ -static int mdc_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, - u32 cookiesize, u32 def_cookiesize) +static int mdc_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize) { struct obd_device *obd = exp->exp_obd; struct client_obd *cli = &obd->u.cli; @@ -2666,12 +2663,6 @@ static int mdc_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, if (cli->cl_default_mds_easize < def_easize) cli->cl_default_mds_easize = def_easize; - if (cli->cl_max_mds_cookiesize < cookiesize) - cli->cl_max_mds_cookiesize = cookiesize; - - if (cli->cl_default_mds_cookiesize < def_cookiesize) - cli->cl_default_mds_cookiesize = def_cookiesize; - return 0; } diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 505582ff4d1e..df6fbed58aa4 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1100,7 +1100,7 @@ out: static u64 last_object_id; static int echo_create_object(const struct lu_env *env, struct echo_device *ed, - struct obdo *oa, struct obd_trans_info *oti) + struct obdo *oa) { struct echo_object *eco; struct echo_client_obd *ec = ed->ed_ec; @@ -1117,7 +1117,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, if (!ostid_id(&oa->o_oi)) ostid_set_id(&oa->o_oi, ++last_object_id); - rc = obd_create(env, ec->ec_exp, oa, oti); + rc = obd_create(env, ec->ec_exp, oa); if (rc != 0) { CERROR("Cannot create objects: rc = %d\n", rc); goto failed; @@ -1137,7 +1137,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, failed: if (created && rc) - obd_destroy(env, ec->ec_exp, oa, oti); + obd_destroy(env, ec->ec_exp, oa); if (rc) CERROR("create object failed with: rc = %d\n", rc); return rc; @@ -1237,8 +1237,7 @@ static int echo_client_page_debug_check(struct page *page, u64 id, static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, struct echo_object *eco, u64 offset, - u64 count, int async, - struct obd_trans_info *oti) + u64 count, int async) { u32 npages; struct brw_page *pga; @@ -1332,8 +1331,7 @@ static int echo_client_prep_commit(const struct lu_env *env, struct obd_export *exp, int rw, struct obdo *oa, struct echo_object *eco, u64 offset, u64 count, - u64 batch, struct obd_trans_info *oti, - int async) + u64 batch, int async) { struct obd_ioobj ioo; struct niobuf_local *lnb; @@ -1378,8 +1376,7 @@ static int echo_client_prep_commit(const struct lu_env *env, ioo.ioo_bufcnt = npages; lpages = npages; - ret = obd_preprw(env, rw, exp, oa, 1, &ioo, rnb, &lpages, - lnb, oti); + ret = obd_preprw(env, rw, exp, oa, 1, &ioo, rnb, &lpages, lnb); if (ret != 0) goto out; LASSERT(lpages == npages); @@ -1411,14 +1408,11 @@ static int echo_client_prep_commit(const struct lu_env *env, rnb[i].rnb_len); } - ret = obd_commitrw(env, rw, exp, oa, 1, &ioo, - rnb, npages, lnb, oti, ret); + ret = obd_commitrw(env, rw, exp, oa, 1, &ioo, rnb, npages, lnb, + ret); if (ret != 0) goto out; - /* Reset oti otherwise it would confuse ldiskfs. */ - memset(oti, 0, sizeof(*oti)); - /* Reuse env context. */ lu_context_exit((struct lu_context *)&env->le_ctx); lu_context_enter((struct lu_context *)&env->le_ctx); @@ -1432,8 +1426,7 @@ out: static int echo_client_brw_ioctl(const struct lu_env *env, int rw, struct obd_export *exp, - struct obd_ioctl_data *data, - struct obd_trans_info *dummy_oti) + struct obd_ioctl_data *data) { struct obd_device *obd = class_exp2obd(exp); struct echo_device *ed = obd2echo_dev(obd); @@ -1470,15 +1463,13 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw, case 1: /* fall through */ case 2: - rc = echo_client_kbrw(ed, rw, oa, - eco, data->ioc_offset, - data->ioc_count, async, dummy_oti); + rc = echo_client_kbrw(ed, rw, oa, eco, data->ioc_offset, + data->ioc_count, async); break; case 3: - rc = echo_client_prep_commit(env, ec->ec_exp, rw, oa, - eco, data->ioc_offset, - data->ioc_count, data->ioc_plen1, - dummy_oti, async); + rc = echo_client_prep_commit(env, ec->ec_exp, rw, oa, eco, + data->ioc_offset, data->ioc_count, + data->ioc_plen1, async); break; default: rc = -EINVAL; @@ -1496,16 +1487,11 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, struct echo_client_obd *ec = ed->ed_ec; struct echo_object *eco; struct obd_ioctl_data *data = karg; - struct obd_trans_info dummy_oti; struct lu_env *env; - struct oti_req_ack_lock *ack_lock; struct obdo *oa; struct lu_fid fid; int rw = OBD_BRW_READ; int rc = 0; - int i; - - memset(&dummy_oti, 0, sizeof(dummy_oti)); oa = &data->ioc_obdo1; if (!(oa->o_valid & OBD_MD_FLGROUP)) { @@ -1535,7 +1521,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, goto out; } - rc = echo_create_object(env, ed, oa, &dummy_oti); + rc = echo_create_object(env, ed, oa); goto out; case OBD_IOC_DESTROY: @@ -1546,7 +1532,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - rc = obd_destroy(env, ec->ec_exp, oa, &dummy_oti); + rc = obd_destroy(env, ec->ec_exp, oa); if (rc == 0) eco->eo_deleted = 1; echo_put_object(eco); @@ -1577,7 +1563,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, .oi_oa = oa, }; - rc = obd_setattr(env, ec->ec_exp, &oinfo, NULL); + rc = obd_setattr(env, ec->ec_exp, &oinfo); echo_put_object(eco); } goto out; @@ -1591,7 +1577,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rw = OBD_BRW_WRITE; /* fall through */ case OBD_IOC_BRW_READ: - rc = echo_client_brw_ioctl(env, rw, exp, data, &dummy_oti); + rc = echo_client_brw_ioctl(env, rw, exp, data); goto out; default: @@ -1604,14 +1590,6 @@ out: lu_env_fini(env); kfree(env); - /* XXX this should be in a helper also called by target_send_reply */ - for (ack_lock = dummy_oti.oti_ack_locks, i = 0; i < 4; - i++, ack_lock++) { - if (!ack_lock->mode) - break; - ldlm_lock_decref(&ack_lock->lock, ack_lock->mode); - } - return rc; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index ab7f82d612e6..64d95c1bb497 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -221,7 +221,7 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp, } static int osc_setattr(const struct lu_env *env, struct obd_export *exp, - struct obd_info *oinfo, struct obd_trans_info *oti) + struct obd_info *oinfo) { struct ptlrpc_request *req; struct ost_body *body; @@ -329,7 +329,7 @@ int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, } static int osc_create(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct obd_trans_info *oti) + struct obdo *oa) { struct ptlrpc_request *req; struct ost_body *body; @@ -358,15 +358,6 @@ static int osc_create(const struct lu_env *env, struct obd_export *exp, ptlrpc_request_set_replen(req); - if ((oa->o_valid & OBD_MD_FLFLAGS) && - oa->o_flags == OBD_FL_DELORPHAN) { - DEBUG_REQ(D_HA, req, - "delorphan from OST integration"); - /* Don't resend the delorphan req */ - req->rq_no_resend = 1; - req->rq_no_delay = 1; - } - rc = ptlrpc_queue_wait(req); if (rc) goto out_req; @@ -383,12 +374,6 @@ static int osc_create(const struct lu_env *env, struct obd_export *exp, oa->o_blksize = cli_brw_size(exp->exp_obd); oa->o_valid |= OBD_MD_FLBLKSZ; - if (oti && oa->o_valid & OBD_MD_FLCOOKIE) { - if (!oti->oti_logcookies) - oti->oti_logcookies = &oti->oti_onecookie; - *oti->oti_logcookies = oa->o_lcookie; - } - CDEBUG(D_HA, "transno: %lld\n", lustre_msg_get_transno(req->rq_repmsg)); out_req: @@ -569,19 +554,8 @@ static int osc_can_send_destroy(struct client_obd *cli) return 0; } -/* Destroy requests can be async always on the client, and we don't even really - * care about the return code since the client cannot do anything at all about - * a destroy failure. - * When the MDS is unlinking a filename, it saves the file objects into a - * recovery llog, and these object records are cancelled when the OST reports - * they were destroyed and sync'd to disk (i.e. transaction committed). - * If the client dies, or the OST is down when the object should be destroyed, - * the records are not cancelled, and when the OST reconnects to the MDS next, - * it will retrieve the llog unlink logs and then sends the log cancellation - * cookies to the MDS after committing destroy transactions. - */ static int osc_destroy(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct obd_trans_info *oti) + struct obdo *oa) { struct client_obd *cli = &exp->exp_obd->u.cli; struct ptlrpc_request *req; @@ -613,32 +587,22 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp, req->rq_request_portal = OST_IO_PORTAL; /* bug 7198 */ ptlrpc_at_set_req_timeout(req); - if (oti && oa->o_valid & OBD_MD_FLCOOKIE) - oa->o_lcookie = *oti->oti_logcookies; body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY); LASSERT(body); lustre_set_wire_obdo(&req->rq_import->imp_connect_data, &body->oa, oa); ptlrpc_request_set_replen(req); - /* If osc_destroy is for destroying the unlink orphan, - * sent from MDT to OST, which should not be blocked here, - * because the process might be triggered by ptlrpcd, and - * it is not good to block ptlrpcd thread (b=16006 - **/ - if (!(oa->o_flags & OBD_FL_DELORPHAN)) { - req->rq_interpret_reply = osc_destroy_interpret; - if (!osc_can_send_destroy(cli)) { - struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, - NULL); - - /* - * Wait until the number of on-going destroy RPCs drops - * under max_rpc_in_flight - */ - l_wait_event_exclusive(cli->cl_destroy_waitq, - osc_can_send_destroy(cli), &lwi); - } + req->rq_interpret_reply = osc_destroy_interpret; + if (!osc_can_send_destroy(cli)) { + struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); + + /* + * Wait until the number of on-going destroy RPCs drops + * under max_rpc_in_flight + */ + l_wait_event_exclusive(cli->cl_destroy_waitq, + osc_can_send_destroy(cli), &lwi); } /* Do not wait for response */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index bca781af854b..1c06b4e8ae88 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1706,7 +1706,7 @@ void lustre_swab_mdt_body(struct mdt_body *b) __swab32s(&b->mbo_eadatasize); __swab32s(&b->mbo_aclsize); __swab32s(&b->mbo_max_mdsize); - __swab32s(&b->mbo_max_cookiesize); + CLASSERT(offsetof(typeof(*b), mbo_unused3)); __swab32s(&b->mbo_uid_h); __swab32s(&b->mbo_gid_h); CLASSERT(offsetof(typeof(*b), mbo_padding_5) != 0); @@ -2103,8 +2103,6 @@ static void dump_obdo(struct obdo *oa) if (valid & OBD_MD_FLHANDLE) CDEBUG(D_RPCTRACE, "obdo: o_handle = %lld\n", oa->o_handle.cookie); - if (valid & OBD_MD_FLCOOKIE) - CDEBUG(D_RPCTRACE, "obdo: o_lcookie = (llog_cookie dumping not yet implemented)\n"); } void dump_ost_body(struct ost_body *ob) diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 09c1025e297a..6c75446a990d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -1245,8 +1245,6 @@ void lustre_assert_wire_constants(void) OBD_MD_FLCKSUM); LASSERTF(OBD_MD_FLQOS == (0x00200000ULL), "found 0x%.16llxULL\n", OBD_MD_FLQOS); - LASSERTF(OBD_MD_FLCOOKIE == (0x00800000ULL), "found 0x%.16llxULL\n", - OBD_MD_FLCOOKIE); LASSERTF(OBD_MD_FLGROUP == (0x01000000ULL), "found 0x%.16llxULL\n", OBD_MD_FLGROUP); LASSERTF(OBD_MD_FLFID == (0x02000000ULL), "found 0x%.16llxULL\n", @@ -1823,10 +1821,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct mdt_body, mbo_max_mdsize)); LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_max_mdsize) == 4, "found %lld\n", (long long)(int)sizeof(((struct mdt_body *)0)->mbo_max_mdsize)); - LASSERTF((int)offsetof(struct mdt_body, mbo_max_cookiesize) == 160, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, mbo_max_cookiesize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_max_cookiesize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->mbo_max_cookiesize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_unused3) == 160, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_unused3)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_unused3) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_unused3)); LASSERTF((int)offsetof(struct mdt_body, mbo_uid_h) == 164, "found %lld\n", (long long)(int)offsetof(struct mdt_body, mbo_uid_h)); LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_uid_h) == 4, "found %lld\n", -- cgit v1.2.3 From f648eed6f32410189f024c73fd86f3c6846c4b6a Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:29 -0400 Subject: staging: lustre: lov: use obd_get_info() to get def/max LOV EA sizes Use obd_get_info() to get the default and maximum LOV EA sizes (along with maximum cookiesize) from LOV. Remove the then unused function obd_size_diskmd() and the unused get info key KEY_LOVDESC. When computing the maximum LOV EA size use the active OST count (ld_active_tgt_count) rather than the OST count (ld_tgt_count). Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/13695 Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 1 - drivers/staging/lustre/lustre/include/obd_class.h | 6 ---- drivers/staging/lustre/lustre/llite/lcommon_misc.c | 36 +++++++++++----------- drivers/staging/lustre/lustre/llite/llite_lib.c | 10 +++++- drivers/staging/lustre/lustre/lov/lov_obd.c | 24 ++++++++------- 5 files changed, 40 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 469112174f41..5fa5838bfe3f 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -667,7 +667,6 @@ enum obd_cleanup_stage { #define KEY_INTERMDS "inter_mds" #define KEY_LAST_ID "last_id" #define KEY_LAST_FID "last_fid" -#define KEY_LOVDESC "lovdesc" #define KEY_MAX_EASIZE "max_easize" #define KEY_DEFAULT_EASIZE "default_easize" #define KEY_MGSSEC "mgssec" diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index a27dbc8f4e28..e6ae4a0b231d 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -628,12 +628,6 @@ static inline int obd_packmd(struct obd_export *exp, return rc; } -static inline int obd_size_diskmd(struct obd_export *exp, - struct lov_stripe_md *mem_src) -{ - return obd_packmd(exp, NULL, mem_src); -} - static inline int obd_free_diskmd(struct obd_export *exp, struct lov_mds_md **disk_tgt) { diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index 4562643c2aad..1558b55363d4 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -47,29 +47,29 @@ */ int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp) { - struct lov_stripe_md lsm = { .lsm_magic = LOV_MAGIC_V3 }; - __u32 valsize = sizeof(struct lov_desc); - int rc, easize, def_easize; - struct lov_desc desc; - __u16 stripes, def_stripes; - - rc = obd_get_info(NULL, dt_exp, sizeof(KEY_LOVDESC), KEY_LOVDESC, - &valsize, &desc); + u32 val_size, max_easize, def_easize; + int rc; + + val_size = sizeof(max_easize); + rc = obd_get_info(NULL, dt_exp, sizeof(KEY_MAX_EASIZE), KEY_MAX_EASIZE, + &val_size, &max_easize); if (rc) return rc; - stripes = min_t(__u32, desc.ld_tgt_count, LOV_MAX_STRIPE_COUNT); - lsm.lsm_stripe_count = stripes; - easize = obd_size_diskmd(dt_exp, &lsm); - - def_stripes = min_t(__u32, desc.ld_default_stripe_count, - LOV_MAX_STRIPE_COUNT); - lsm.lsm_stripe_count = def_stripes; - def_easize = obd_size_diskmd(dt_exp, &lsm); + val_size = sizeof(def_easize); + rc = obd_get_info(NULL, dt_exp, sizeof(KEY_DEFAULT_EASIZE), + KEY_DEFAULT_EASIZE, &val_size, &def_easize); + if (rc) + return rc; - CDEBUG(D_HA, "updating def/max_easize: %d/%d\n", def_easize, easize); + /* + * default cookiesize is 0 because from 2.4 server doesn't send + * llog cookies to client. + */ + CDEBUG(D_HA, "updating def/max_easize: %d/%d\n", + def_easize, max_easize); - rc = md_init_ea_size(md_exp, easize, def_easize); + rc = md_init_ea_size(md_exp, max_easize, def_easize); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index dea103ceec81..fba1499d517b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -560,7 +560,15 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize) { int size, rc; - *lmmsize = obd_size_diskmd(sbi->ll_dt_exp, NULL); + size = sizeof(*lmmsize); + rc = obd_get_info(NULL, sbi->ll_dt_exp, sizeof(KEY_MAX_EASIZE), + KEY_MAX_EASIZE, &size, lmmsize); + if (rc) { + CERROR("%s: cannot get max LOV EA size: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, rc); + return rc; + } + size = sizeof(int); rc = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_MAX_EASIZE), KEY_MAX_EASIZE, &size, lmmsize); diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index c2a853cc776d..473071cdb16c 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1244,28 +1244,30 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp, { struct obd_device *obddev = class_exp2obd(exp); struct lov_obd *lov = &obddev->u.lov; - int rc; + struct lov_desc *ld = &lov->desc; + int rc = 0; if (!vallen || !val) return -EFAULT; obd_getref(obddev); - if (KEY_IS(KEY_LOVDESC)) { - struct lov_desc *desc_ret = val; - *desc_ret = lov->desc; + if (KEY_IS(KEY_MAX_EASIZE)) { + u32 max_stripe_count = min_t(u32, ld->ld_active_tgt_count, + LOV_MAX_STRIPE_COUNT); - rc = 0; - goto out; + *((u32 *)val) = lov_mds_md_size(max_stripe_count, LOV_MAGIC_V3); + } else if (KEY_IS(KEY_DEFAULT_EASIZE)) { + u32 def_stripe_count = min_t(u32, ld->ld_default_stripe_count, + LOV_MAX_STRIPE_COUNT); + + *((u32 *)val) = lov_mds_md_size(def_stripe_count, LOV_MAGIC_V3); } else if (KEY_IS(KEY_TGT_COUNT)) { *((int *)val) = lov->desc.ld_tgt_count; - rc = 0; - goto out; + } else { + rc = -EINVAL; } - rc = -EINVAL; - -out: obd_putref(obddev); return rc; } -- cgit v1.2.3 From 0154672fbecd8d79ffefa659b4e67f59006e0831 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Sun, 2 Oct 2016 22:28:30 -0400 Subject: staging: lustre: ldlm: cancel aged locks for LRUR It doesn't make sense to keep the very aged lock even with the LRUR policy. This patch decreased the default ns_max_age from 10 hours to 65 minutes and changed LRUR policy to cancel very aged locks. Signed-off-by: Niu Yawei Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6529 Reviewed-on: http://review.whamcloud.com/14856 Reviewed-by: Jinshan Xiong Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_dlm.h | 2 +- drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index d03534432624..1c6b7b838c7b 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -59,7 +59,7 @@ struct obd_device; #define OBD_LDLM_DEVICENAME "ldlm" #define LDLM_DEFAULT_LRU_SIZE (100 * num_online_cpus()) -#define LDLM_DEFAULT_MAX_ALIVE (cfs_time_seconds(36000)) +#define LDLM_DEFAULT_MAX_ALIVE (cfs_time_seconds(3900)) /* 65 min */ #define LDLM_DEFAULT_PARALLEL_AST_LIMIT 1024 /** diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 98730a353247..ac1927c54a0f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1182,6 +1182,14 @@ static enum ldlm_policy_res ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, if (count && added >= count) return LDLM_POLICY_KEEP_LOCK; + /* + * Despite of the LV, It doesn't make sense to keep the lock which + * is unused for ns_max_age time. + */ + if (cfs_time_after(cfs_time_current(), + cfs_time_add(lock->l_last_used, ns->ns_max_age))) + return LDLM_POLICY_CANCEL_LOCK; + slv = ldlm_pool_get_slv(pl); lvf = ldlm_pool_get_lvf(pl); la = cfs_duration_sec(cfs_time_sub(cur, lock->l_last_used)); -- cgit v1.2.3 From f7d5215d0afefc9c2b1573fe2980d8e3643857ee Mon Sep 17 00:00:00 2001 From: Vitaly Fertman Date: Sun, 2 Oct 2016 22:28:32 -0400 Subject: staging: lustre: ldlm: interval tree search in ldlm_lock_match() replace the linear search by interval_tree one for granted list in ldlm_lock_match() Signed-off-by: Vitaly Fertman Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5739 Xyratex-bug-id: MRP-2089 Reviewed-on: http://review.whamcloud.com/12294 Reviewed-by: Andreas Dilger Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 249 +++++++++++++++++-------- 1 file changed, 171 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 22b4a52c4711..f2044ecd9505 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1043,88 +1043,173 @@ void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list) } /** - * Search for a lock with given properties in a queue. + * Describe the overlap between two locks. itree_overlap_cb data. + */ +struct lock_match_data { + struct ldlm_lock *lmd_old; + struct ldlm_lock *lmd_lock; + enum ldlm_mode *lmd_mode; + ldlm_policy_data_t *lmd_policy; + __u64 lmd_flags; + int lmd_unref; +}; + +/** + * Check if the given @lock meets the criteria for a match. + * A reference on the lock is taken if matched. * - * \retval a referenced lock or NULL. See the flag descriptions below, in the - * comment above ldlm_lock_match + * \param lock test-against this lock + * \param data parameters */ -static struct ldlm_lock *search_queue(struct list_head *queue, - enum ldlm_mode *mode, - ldlm_policy_data_t *policy, - struct ldlm_lock *old_lock, - __u64 flags, int unref) +static int lock_matches(struct ldlm_lock *lock, struct lock_match_data *data) { - struct ldlm_lock *lock; - struct list_head *tmp; + ldlm_policy_data_t *lpol = &lock->l_policy_data; + enum ldlm_mode match; - list_for_each(tmp, queue) { - enum ldlm_mode match; + if (lock == data->lmd_old) + return INTERVAL_ITER_STOP; - lock = list_entry(tmp, struct ldlm_lock, l_res_link); + /* + * Check if this lock can be matched. + * Used by LU-2919(exclusive open) for open lease lock + */ + if (ldlm_is_excl(lock)) + return INTERVAL_ITER_CONT; - if (lock == old_lock) - break; + /* + * llite sometimes wants to match locks that will be + * canceled when their users drop, but we allow it to match + * if it passes in CBPENDING and the lock still has users. + * this is generally only going to be used by children + * whose parents already hold a lock so forward progress + * can still happen. + */ + if (ldlm_is_cbpending(lock) && + !(data->lmd_flags & LDLM_FL_CBPENDING)) + return INTERVAL_ITER_CONT; - /* Check if this lock can be matched. - * Used by LU-2919(exclusive open) for open lease lock - */ - if (ldlm_is_excl(lock)) - continue; + if (!data->lmd_unref && ldlm_is_cbpending(lock) && + !lock->l_readers && !lock->l_writers) + return INTERVAL_ITER_CONT; - /* llite sometimes wants to match locks that will be - * canceled when their users drop, but we allow it to match - * if it passes in CBPENDING and the lock still has users. - * this is generally only going to be used by children - * whose parents already hold a lock so forward progress - * can still happen. - */ - if (ldlm_is_cbpending(lock) && !(flags & LDLM_FL_CBPENDING)) - continue; - if (!unref && ldlm_is_cbpending(lock) && - lock->l_readers == 0 && lock->l_writers == 0) - continue; + if (!(lock->l_req_mode & *data->lmd_mode)) + return INTERVAL_ITER_CONT; + match = lock->l_req_mode; - if (!(lock->l_req_mode & *mode)) - continue; - match = lock->l_req_mode; - - if (lock->l_resource->lr_type == LDLM_EXTENT && - (lock->l_policy_data.l_extent.start > - policy->l_extent.start || - lock->l_policy_data.l_extent.end < policy->l_extent.end)) - continue; + switch (lock->l_resource->lr_type) { + case LDLM_EXTENT: + if (lpol->l_extent.start > data->lmd_policy->l_extent.start || + lpol->l_extent.end < data->lmd_policy->l_extent.end) + return INTERVAL_ITER_CONT; if (unlikely(match == LCK_GROUP) && - lock->l_resource->lr_type == LDLM_EXTENT && - policy->l_extent.gid != LDLM_GID_ANY && - lock->l_policy_data.l_extent.gid != policy->l_extent.gid) - continue; - - /* We match if we have existing lock with same or wider set + data->lmd_policy->l_extent.gid != LDLM_GID_ANY && + lpol->l_extent.gid != data->lmd_policy->l_extent.gid) + return INTERVAL_ITER_CONT; + break; + case LDLM_IBITS: + /* + * We match if we have existing lock with same or wider set * of bits. */ - if (lock->l_resource->lr_type == LDLM_IBITS && - ((lock->l_policy_data.l_inodebits.bits & - policy->l_inodebits.bits) != - policy->l_inodebits.bits)) - continue; + if ((lpol->l_inodebits.bits & + data->lmd_policy->l_inodebits.bits) != + data->lmd_policy->l_inodebits.bits) + return INTERVAL_ITER_CONT; + break; + default: + break; + } + /* + * We match if we have existing lock with same or wider set + * of bits. + */ + if (!data->lmd_unref && LDLM_HAVE_MASK(lock, GONE)) + return INTERVAL_ITER_CONT; + + if ((data->lmd_flags & LDLM_FL_LOCAL_ONLY) && + !ldlm_is_local(lock)) + return INTERVAL_ITER_CONT; - if (!unref && LDLM_HAVE_MASK(lock, GONE)) + if (data->lmd_flags & LDLM_FL_TEST_LOCK) { + LDLM_LOCK_GET(lock); + ldlm_lock_touch_in_lru(lock); + } else { + ldlm_lock_addref_internal_nolock(lock, match); + } + + *data->lmd_mode = match; + data->lmd_lock = lock; + + return INTERVAL_ITER_STOP; +} + +static unsigned int itree_overlap_cb(struct interval_node *in, void *args) +{ + struct ldlm_interval *node = to_ldlm_interval(in); + struct lock_match_data *data = args; + struct ldlm_lock *lock; + int rc; + + list_for_each_entry(lock, &node->li_group, l_sl_policy) { + rc = lock_matches(lock, data); + if (rc == INTERVAL_ITER_STOP) + return INTERVAL_ITER_STOP; + } + return INTERVAL_ITER_CONT; +} + +/** + * Search for a lock with given parameters in interval trees. + * + * \param res search for a lock in this resource + * \param data parameters + * + * \retval a referenced lock or NULL. + */ +static struct ldlm_lock *search_itree(struct ldlm_resource *res, + struct lock_match_data *data) +{ + struct interval_node_extent ext = { + .start = data->lmd_policy->l_extent.start, + .end = data->lmd_policy->l_extent.end + }; + int idx; + + for (idx = 0; idx < LCK_MODE_NUM; idx++) { + struct ldlm_interval_tree *tree = &res->lr_itree[idx]; + + if (!tree->lit_root) continue; - if ((flags & LDLM_FL_LOCAL_ONLY) && !ldlm_is_local(lock)) + if (!(tree->lit_mode & *data->lmd_mode)) continue; - if (flags & LDLM_FL_TEST_LOCK) { - LDLM_LOCK_GET(lock); - ldlm_lock_touch_in_lru(lock); - } else { - ldlm_lock_addref_internal_nolock(lock, match); - } - *mode = match; - return lock; + interval_search(tree->lit_root, &ext, + itree_overlap_cb, data); } + return data->lmd_lock; +} +/** + * Search for a lock with given properties in a queue. + * + * \param queue search for a lock in this queue + * \param data parameters + * + * \retval a referenced lock or NULL. + */ +static struct ldlm_lock *search_queue(struct list_head *queue, + struct lock_match_data *data) +{ + struct ldlm_lock *lock; + int rc; + + list_for_each_entry(lock, queue, l_res_link) { + rc = lock_matches(lock, data); + if (rc == INTERVAL_ITER_STOP) + return data->lmd_lock; + } return NULL; } @@ -1199,31 +1284,41 @@ enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, enum ldlm_mode mode, struct lustre_handle *lockh, int unref) { + struct lock_match_data data = { + .lmd_old = NULL, + .lmd_lock = NULL, + .lmd_mode = &mode, + .lmd_policy = policy, + .lmd_flags = flags, + .lmd_unref = unref, + }; struct ldlm_resource *res; - struct ldlm_lock *lock, *old_lock = NULL; + struct ldlm_lock *lock; int rc = 0; if (!ns) { - old_lock = ldlm_handle2lock(lockh); - LASSERT(old_lock); + data.lmd_old = ldlm_handle2lock(lockh); + LASSERT(data.lmd_old); - ns = ldlm_lock_to_ns(old_lock); - res_id = &old_lock->l_resource->lr_name; - type = old_lock->l_resource->lr_type; - mode = old_lock->l_req_mode; + ns = ldlm_lock_to_ns(data.lmd_old); + res_id = &data.lmd_old->l_resource->lr_name; + type = data.lmd_old->l_resource->lr_type; + *data.lmd_mode = data.lmd_old->l_req_mode; } res = ldlm_resource_get(ns, NULL, res_id, type, 0); if (IS_ERR(res)) { - LASSERT(!old_lock); + LASSERT(!data.lmd_old); return 0; } LDLM_RESOURCE_ADDREF(res); lock_res(res); - lock = search_queue(&res->lr_granted, &mode, policy, old_lock, - flags, unref); + if (res->lr_type == LDLM_EXTENT) + lock = search_itree(res, &data); + else + lock = search_queue(&res->lr_granted, &data); if (lock) { rc = 1; goto out; @@ -1232,14 +1327,12 @@ enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, rc = 0; goto out; } - lock = search_queue(&res->lr_waiting, &mode, policy, old_lock, - flags, unref); + lock = search_queue(&res->lr_waiting, &data); if (lock) { rc = 1; goto out; } - - out: +out: unlock_res(res); LDLM_RESOURCE_DELREF(res); ldlm_resource_putref(res); @@ -1311,8 +1404,8 @@ enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, (type == LDLM_PLAIN || type == LDLM_IBITS) ? res_id->name[3] : policy->l_extent.end); } - if (old_lock) - LDLM_LOCK_PUT(old_lock); + if (data.lmd_old) + LDLM_LOCK_PUT(data.lmd_old); return rc ? mode : 0; } -- cgit v1.2.3 From 7d870d93badd7f2bfa8a33674ee3b626159b4e9b Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sun, 2 Oct 2016 22:28:33 -0400 Subject: staging: lustre: lov: copy_to_user uses wrong casting With certain version of gcc lov_obd.c failes to compile with the following warning. In function copy_to_user, inlined from lov_iocontrol at lustre/lustre/lov/lov_obd.c:1168: ./arch/x86/include/asm/uaccess.h:735: error: call to __copy_to_user_overflow declared with attribute warning: copy_to_user() buffer size is not probably correct In lov_iocontrol the data was being casted to int instead of the required unsigned long. This patch changes the cast to what is needed for copy_to_user. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6302 Reviewed-on: http://review.whamcloud.com/14613 Reviewed-by: frank zago Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_obd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 473071cdb16c..18cb92d2f2f9 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1085,8 +1085,8 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, /* copy UUID */ if (copy_to_user(data->ioc_pbuf2, obd2cli_tgt(osc_obd), - min((int)data->ioc_plen2, - (int)sizeof(struct obd_uuid)))) + min_t(unsigned long, data->ioc_plen2, + sizeof(struct obd_uuid)))) return -EFAULT; memcpy(&flags, data->ioc_inlbuf1, sizeof(__u32)); @@ -1099,8 +1099,8 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, if (rc) return rc; if (copy_to_user(data->ioc_pbuf1, &stat_buf, - min((int)data->ioc_plen1, - (int)sizeof(stat_buf)))) + min_t(unsigned long, data->ioc_plen1, + sizeof(stat_buf)))) return -EFAULT; break; } -- cgit v1.2.3 From e1f361aca55377a2082a8d72d194988b52915a3b Mon Sep 17 00:00:00 2001 From: Gregoire Pichon Date: Sun, 2 Oct 2016 22:28:34 -0400 Subject: staging: lustre: mdc: add max modify RPCs in flight variable This patch introduces the maximum modify RPCs in flight variable of a mdc client obd device. Its value is set from connection flag and and connection data. It can later be tuned through the max_mod_rpcs_in_flight procfs file. Signed-off-by: Gregoire Pichon Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5319 Reviewed-on: http://review.whamcloud.com/14153 Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: Mike Pershin Reviewed-by: Alex Zhuravlev Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 7 +++ drivers/staging/lustre/lustre/include/obd_class.h | 1 + drivers/staging/lustre/lustre/mdc/lproc_mdc.c | 38 +++++++++++++++ drivers/staging/lustre/lustre/mdc/mdc_request.c | 4 ++ drivers/staging/lustre/lustre/obdclass/genops.c | 57 +++++++++++++++++++++++ drivers/staging/lustre/lustre/ptlrpc/import.c | 11 +++++ 6 files changed, 118 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 5fa5838bfe3f..a97738852dd0 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -318,6 +318,13 @@ struct client_obd { struct mdc_rpc_lock *cl_rpc_lock; struct mdc_rpc_lock *cl_close_lock; + /* modify rpcs in flight + * currently used for metadata only + */ + spinlock_t cl_mod_rpcs_lock; + u16 cl_max_mod_rpcs_in_flight; + + /* mgc datastruct */ atomic_t cl_mgc_refcount; struct obd_export *cl_mgc_mgsexp; diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index e6ae4a0b231d..7d8f0628d38d 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -100,6 +100,7 @@ int obd_get_request_slot(struct client_obd *cli); void obd_put_request_slot(struct client_obd *cli); __u32 obd_get_max_rpcs_in_flight(struct client_obd *cli); int obd_set_max_rpcs_in_flight(struct client_obd *cli, __u32 max); +int obd_set_max_mod_rpcs_in_flight(struct client_obd *cli, u16 max); struct llog_handle; struct llog_rec_hdr; diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index fca9450de57c..5fdee9e7dec1 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -73,6 +73,43 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, } LUSTRE_RW_ATTR(max_rpcs_in_flight); +static ssize_t max_mod_rpcs_in_flight_show(struct kobject *kobj, + struct attribute *attr, + char *buf) +{ + struct obd_device *dev = container_of(kobj, struct obd_device, + obd_kobj); + u16 max; + int len; + + max = dev->u.cli.cl_max_mod_rpcs_in_flight; + len = sprintf(buf, "%hu\n", max); + + return len; +} + +static ssize_t max_mod_rpcs_in_flight_store(struct kobject *kobj, + struct attribute *attr, + const char *buffer, + size_t count) +{ + struct obd_device *dev = container_of(kobj, struct obd_device, + obd_kobj); + u16 val; + int rc; + + rc = kstrtou16(buffer, 10, &val); + if (rc) + return rc; + + rc = obd_set_max_mod_rpcs_in_flight(&dev->u.cli, val); + if (rc) + count = rc; + + return count; +} +LUSTRE_RW_ATTR(max_mod_rpcs_in_flight); + LPROC_SEQ_FOPS_WR_ONLY(mdc, ping); LPROC_SEQ_FOPS_RO_TYPE(mdc, connect_flags); @@ -117,6 +154,7 @@ static struct lprocfs_vars lprocfs_mdc_obd_vars[] = { static struct attribute *mdc_attrs[] = { &lustre_attr_max_rpcs_in_flight.attr, + &lustre_attr_max_mod_rpcs_in_flight.attr, &lustre_attr_max_pages_per_rpc.attr, NULL, }; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 34ccff85ea5b..2d0dd1885321 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2631,8 +2631,12 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg) if (rc) { mdc_cleanup(obd); CERROR("failed to setup llogging subsystems\n"); + return rc; } + spin_lock_init(&cli->cl_mod_rpcs_lock); + cli->cl_max_mod_rpcs_in_flight = OBD_MAX_RIF_DEFAULT - 1; + return rc; err_close_lock: diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index cf8bb2a2f40b..62e66361584a 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -1408,13 +1408,33 @@ EXPORT_SYMBOL(obd_get_max_rpcs_in_flight); int obd_set_max_rpcs_in_flight(struct client_obd *cli, __u32 max) { struct obd_request_slot_waiter *orsw; + const char *typ_name; __u32 old; int diff; + int rc; int i; if (max > OBD_MAX_RIF_MAX || max < 1) return -ERANGE; + typ_name = cli->cl_import->imp_obd->obd_type->typ_name; + if (!strcmp(typ_name, LUSTRE_MDC_NAME)) { + /* + * adjust max_mod_rpcs_in_flight to ensure it is always + * strictly lower that max_rpcs_in_flight + */ + if (max < 2) { + CERROR("%s: cannot set max_rpcs_in_flight to 1 because it must be higher than max_mod_rpcs_in_flight value\n", + cli->cl_import->imp_obd->obd_name); + return -ERANGE; + } + if (max <= cli->cl_max_mod_rpcs_in_flight) { + rc = obd_set_max_mod_rpcs_in_flight(cli, max - 1); + if (rc) + return rc; + } + } + spin_lock(&cli->cl_loi_list_lock); old = cli->cl_max_rpcs_in_flight; cli->cl_max_rpcs_in_flight = max; @@ -1436,3 +1456,40 @@ int obd_set_max_rpcs_in_flight(struct client_obd *cli, __u32 max) return 0; } EXPORT_SYMBOL(obd_set_max_rpcs_in_flight); + +int obd_set_max_mod_rpcs_in_flight(struct client_obd *cli, __u16 max) +{ + struct obd_connect_data *ocd; + u16 maxmodrpcs; + + if (max > OBD_MAX_RIF_MAX || max < 1) + return -ERANGE; + + /* cannot exceed or equal max_rpcs_in_flight */ + if (max >= cli->cl_max_rpcs_in_flight) { + CERROR("%s: can't set max_mod_rpcs_in_flight to a value (%hu) higher or equal to max_rpcs_in_flight value (%u)\n", + cli->cl_import->imp_obd->obd_name, + max, cli->cl_max_rpcs_in_flight); + return -ERANGE; + } + + /* cannot exceed max modify RPCs in flight supported by the server */ + ocd = &cli->cl_import->imp_connect_data; + if (ocd->ocd_connect_flags & OBD_CONNECT_MULTIMODRPCS) + maxmodrpcs = ocd->ocd_maxmodrpcs; + else + maxmodrpcs = 1; + if (max > maxmodrpcs) { + CERROR("%s: can't set max_mod_rpcs_in_flight to a value (%hu) higher than max_mod_rpcs_per_client value (%hu) returned by the server at connection\n", + cli->cl_import->imp_obd->obd_name, + max, maxmodrpcs); + return -ERANGE; + } + + cli->cl_max_mod_rpcs_in_flight = max; + + /* will have to wakeup waiters if max has been increased */ + + return 0; +} +EXPORT_SYMBOL(obd_set_max_mod_rpcs_in_flight); diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 2bdaf2ba2f16..46ba5a40fc8b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -857,6 +857,17 @@ static int ptlrpc_connect_set_flags(struct obd_import *imp, client_adjust_max_dirty(cli); + /* + * Update client max modify RPCs in flight with value returned + * by the server + */ + if (ocd->ocd_connect_flags & OBD_CONNECT_MULTIMODRPCS) + cli->cl_max_mod_rpcs_in_flight = min( + cli->cl_max_mod_rpcs_in_flight, + ocd->ocd_maxmodrpcs); + else + cli->cl_max_mod_rpcs_in_flight = 1; + /* * Reset ns_connect_flags only for initial connect. It might be * changed in while using FS and if we reset it in reconnect -- cgit v1.2.3 From 48a2a12afc54aa1ebfdb1e821fc3dc7893816986 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:35 -0400 Subject: staging: lustre: osc: remove remaining bits for capa support With capa support removed from the OSC layer a few more bits can be cleaned up. Convert the OBD getattr and setattr paths to use struct obdo rather than struct obd_info. Remove the oi_policy, oi_oa, and oi_capa members from struct obd_info. Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3105 Reviewed-on: http://review.whamcloud.com/14640 Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Reviewed-by: James Simmons Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 13 ++----- drivers/staging/lustre/lustre/include/obd_class.h | 17 ++++---- drivers/staging/lustre/lustre/llite/vvp_internal.h | 1 - drivers/staging/lustre/lustre/lov/lov_obd.c | 7 ++-- drivers/staging/lustre/lustre/lov/lov_request.c | 2 - .../staging/lustre/lustre/obdecho/echo_client.c | 12 +----- .../staging/lustre/lustre/osc/osc_cl_internal.h | 1 - drivers/staging/lustre/lustre/osc/osc_internal.h | 6 +-- drivers/staging/lustre/lustre/osc/osc_io.c | 11 ++---- drivers/staging/lustre/lustre/osc/osc_request.c | 45 +++++++++++----------- 10 files changed, 46 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index a97738852dd0..f63336fd801c 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -126,17 +126,10 @@ typedef int (*obd_enqueue_update_f)(void *cookie, int rc); /* obd info for a particular level (lov, osc). */ struct obd_info { - /* Flags used for set request specific flags: - - while lock handling, the flags obtained on the enqueue - request are set here. - - while stats, the flags used for control delay/resend. - - while setattr, the flags used for distinguish punch operation - */ + /* OBD_STATFS_* flags */ __u64 oi_flags; /* lsm data specific for every OSC. */ struct lov_stripe_md *oi_md; - /* obdo data specific for every OSC, if needed at all. */ - struct obdo *oi_oa; /* statfs data specific for every OSC, if needed at all. */ struct obd_statfs *oi_osfs; /* An update callback which is called to update some data on upper @@ -871,9 +864,9 @@ struct obd_ops { int (*destroy)(const struct lu_env *env, struct obd_export *exp, struct obdo *oa); int (*setattr)(const struct lu_env *, struct obd_export *exp, - struct obd_info *oinfo); + struct obdo *oa); int (*getattr)(const struct lu_env *env, struct obd_export *exp, - struct obd_info *oinfo); + struct obdo *oa); int (*preprw)(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *remote, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 7d8f0628d38d..0eaea549dd6f 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -705,26 +705,26 @@ static inline int obd_destroy(const struct lu_env *env, struct obd_export *exp, } static inline int obd_getattr(const struct lu_env *env, struct obd_export *exp, - struct obd_info *oinfo) + struct obdo *oa) { int rc; EXP_CHECK_DT_OP(exp, getattr); EXP_COUNTER_INCREMENT(exp, getattr); - rc = OBP(exp->exp_obd, getattr)(env, exp, oinfo); + rc = OBP(exp->exp_obd, getattr)(env, exp, oa); return rc; } static inline int obd_setattr(const struct lu_env *env, struct obd_export *exp, - struct obd_info *oinfo) + struct obdo *oa) { int rc; EXP_CHECK_DT_OP(exp, setattr); EXP_COUNTER_INCREMENT(exp, setattr); - rc = OBP(exp->exp_obd, setattr)(env, exp, oinfo); + rc = OBP(exp->exp_obd, setattr)(env, exp, oa); return rc; } @@ -991,15 +991,16 @@ static inline int obd_statfs_rqset(struct obd_export *exp, __u32 flags) { struct ptlrpc_request_set *set = NULL; - struct obd_info oinfo = { }; + struct obd_info oinfo = { + .oi_osfs = osfs, + .oi_flags = flags, + }; int rc = 0; - set = ptlrpc_prep_set(); + set = ptlrpc_prep_set(); if (!set) return -ENOMEM; - oinfo.oi_osfs = osfs; - oinfo.oi_flags = flags; rc = obd_statfs_async(exp, &oinfo, max_age, set); if (rc == 0) rc = ptlrpc_set_wait(set); diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index a8e6aeb6aacd..891227c25031 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -44,7 +44,6 @@ enum obd_notify_event; struct inode; struct lov_stripe_md; struct lustre_md; -struct obd_capa; struct obd_device; struct obd_export; struct page; diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 18cb92d2f2f9..653018738995 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1033,7 +1033,10 @@ static int lov_statfs(const struct lu_env *env, struct obd_export *exp, struct obd_statfs *osfs, __u64 max_age, __u32 flags) { struct ptlrpc_request_set *set = NULL; - struct obd_info oinfo = { }; + struct obd_info oinfo = { + .oi_osfs = osfs, + .oi_flags = flags, + }; int rc = 0; /* for obdclass we forbid using obd_statfs_rqset, but prefer using async @@ -1043,8 +1046,6 @@ static int lov_statfs(const struct lu_env *env, struct obd_export *exp, if (!set) return -ENOMEM; - oinfo.oi_osfs = osfs; - oinfo.oi_flags = flags; rc = lov_statfs_async(exp, &oinfo, max_age, set); if (rc == 0) rc = ptlrpc_set_wait(set); diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index c8734a6ea502..d43cc88ae641 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -60,8 +60,6 @@ void lov_finish_set(struct lov_request_set *set) rq_link); list_del_init(&req->rq_link); - if (req->rq_oi.oi_oa) - kmem_cache_free(obdo_cachep, req->rq_oi.oi_oa); kfree(req->rq_oi.oi_osfs); kfree(req); } diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index df6fbed58aa4..d8e3e96b8e54 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1542,11 +1542,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, case OBD_IOC_GETATTR: rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - struct obd_info oinfo = { - .oi_oa = oa, - }; - - rc = obd_getattr(env, ec->ec_exp, &oinfo); + rc = obd_getattr(env, ec->ec_exp, oa); echo_put_object(eco); } goto out; @@ -1559,11 +1555,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - struct obd_info oinfo = { - .oi_oa = oa, - }; - - rc = obd_setattr(env, ec->ec_exp, &oinfo); + rc = obd_setattr(env, ec->ec_exp, oa); echo_put_object(eco); } goto out; diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index 9c8de15c309c..8a554128ed7f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -77,7 +77,6 @@ struct osc_io { /** write osc_lock for this IO, used by osc_extent_find(). */ struct osc_lock *oi_write_osclock; - struct obd_info oi_info; struct obdo oi_oa; struct osc_async_cbargs { bool opc_rpc_sent; diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 61bfacb29759..dc708ea17b29 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -118,13 +118,13 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id, __u64 *flags, void *data, struct lustre_handle *lockh, int unref); -int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, +int osc_setattr_async(struct obd_export *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset); -int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo, +int osc_punch_base(struct obd_export *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset); -int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo, +int osc_sync_base(struct obd_export *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset); diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index b4e062df389f..8eb42757a675 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -484,7 +484,6 @@ static int osc_io_setattr_start(const struct lu_env *env, __u64 size = io->u.ci_setattr.sa_attr.lvb_size; unsigned int ia_valid = io->u.ci_setattr.sa_valid; int result = 0; - struct obd_info oinfo = { }; /* truncate cache dirty pages first */ if (cl_io_is_trunc(io)) @@ -554,16 +553,15 @@ static int osc_io_setattr_start(const struct lu_env *env, oa->o_valid |= OBD_MD_FLFLAGS; } - oinfo.oi_oa = oa; init_completion(&cbargs->opc_sync); if (ia_valid & ATTR_SIZE) result = osc_punch_base(osc_export(cl2osc(obj)), - &oinfo, osc_async_upcall, + oa, osc_async_upcall, cbargs, PTLRPCD_SET); else result = osc_setattr_async(osc_export(cl2osc(obj)), - &oinfo, osc_async_upcall, + oa, osc_async_upcall, cbargs, PTLRPCD_SET); cbargs->opc_rpc_sent = result == 0; } @@ -745,7 +743,6 @@ static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj, { struct osc_io *oio = osc_env_io(env); struct obdo *oa = &oio->oi_oa; - struct obd_info *oinfo = &oio->oi_info; struct lov_oinfo *loi = obj->oo_oinfo; struct osc_async_cbargs *cbargs = &oio->oi_cbarg; int rc = 0; @@ -761,11 +758,9 @@ static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj, obdo_set_parent_fid(oa, fio->fi_fid); - memset(oinfo, 0, sizeof(*oinfo)); - oinfo->oi_oa = oa; init_completion(&cbargs->opc_sync); - rc = osc_sync_base(osc_export(obj), oinfo, osc_async_upcall, cbargs, + rc = osc_sync_base(osc_export(obj), oa, osc_async_upcall, cbargs, PTLRPCD_SET); return rc; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 64d95c1bb497..0985bdae11eb 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -82,7 +82,7 @@ struct osc_setattr_args { }; struct osc_fsync_args { - struct obd_info *fa_oi; + struct obdo *fa_oa; obd_enqueue_update_f fa_upcall; void *fa_cookie; }; @@ -166,19 +166,18 @@ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, } static inline void osc_pack_req_body(struct ptlrpc_request *req, - struct obd_info *oinfo) + struct obdo *oa) { struct ost_body *body; body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY); LASSERT(body); - lustre_set_wire_obdo(&req->rq_import->imp_connect_data, &body->oa, - oinfo->oi_oa); + lustre_set_wire_obdo(&req->rq_import->imp_connect_data, &body->oa, oa); } static int osc_getattr(const struct lu_env *env, struct obd_export *exp, - struct obd_info *oinfo) + struct obdo *oa) { struct ptlrpc_request *req; struct ost_body *body; @@ -194,7 +193,7 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp, return rc; } - osc_pack_req_body(req, oinfo); + osc_pack_req_body(req, oa); ptlrpc_request_set_replen(req); @@ -209,11 +208,11 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp, } CDEBUG(D_INODE, "mode: %o\n", body->oa.o_mode); - lustre_get_wire_obdo(&req->rq_import->imp_connect_data, oinfo->oi_oa, + lustre_get_wire_obdo(&req->rq_import->imp_connect_data, oa, &body->oa); - oinfo->oi_oa->o_blksize = cli_brw_size(exp->exp_obd); - oinfo->oi_oa->o_valid |= OBD_MD_FLBLKSZ; + oa->o_blksize = cli_brw_size(exp->exp_obd); + oa->o_valid |= OBD_MD_FLBLKSZ; out: ptlrpc_req_finished(req); @@ -221,13 +220,13 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp, } static int osc_setattr(const struct lu_env *env, struct obd_export *exp, - struct obd_info *oinfo) + struct obdo *oa) { struct ptlrpc_request *req; struct ost_body *body; int rc; - LASSERT(oinfo->oi_oa->o_valid & OBD_MD_FLGROUP); + LASSERT(oa->o_valid & OBD_MD_FLGROUP); req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SETATTR); if (!req) @@ -239,7 +238,7 @@ static int osc_setattr(const struct lu_env *env, struct obd_export *exp, return rc; } - osc_pack_req_body(req, oinfo); + osc_pack_req_body(req, oa); ptlrpc_request_set_replen(req); @@ -253,7 +252,7 @@ static int osc_setattr(const struct lu_env *env, struct obd_export *exp, goto out; } - lustre_get_wire_obdo(&req->rq_import->imp_connect_data, oinfo->oi_oa, + lustre_get_wire_obdo(&req->rq_import->imp_connect_data, oa, &body->oa); out: @@ -283,7 +282,7 @@ out: return rc; } -int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, +int osc_setattr_async(struct obd_export *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset) { @@ -301,7 +300,7 @@ int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, return rc; } - osc_pack_req_body(req, oinfo); + osc_pack_req_body(req, oa); ptlrpc_request_set_replen(req); @@ -315,7 +314,7 @@ int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, CLASSERT(sizeof(*sa) <= sizeof(req->rq_async_args)); sa = ptlrpc_req_async_args(req); - sa->sa_oa = oinfo->oi_oa; + sa->sa_oa = oa; sa->sa_upcall = upcall; sa->sa_cookie = cookie; @@ -382,7 +381,7 @@ out: return rc; } -int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo, +int osc_punch_base(struct obd_export *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset) { @@ -406,14 +405,14 @@ int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo, body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY); LASSERT(body); lustre_set_wire_obdo(&req->rq_import->imp_connect_data, &body->oa, - oinfo->oi_oa); + oa); ptlrpc_request_set_replen(req); req->rq_interpret_reply = (ptlrpc_interpterer_t)osc_setattr_interpret; CLASSERT(sizeof(*sa) <= sizeof(req->rq_async_args)); sa = ptlrpc_req_async_args(req); - sa->sa_oa = oinfo->oi_oa; + sa->sa_oa = oa; sa->sa_upcall = upcall; sa->sa_cookie = cookie; if (rqset == PTLRPCD_SET) @@ -441,13 +440,13 @@ static int osc_sync_interpret(const struct lu_env *env, goto out; } - *fa->fa_oi->oi_oa = body->oa; + *fa->fa_oa = body->oa; out: rc = fa->fa_upcall(fa->fa_cookie, rc); return rc; } -int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo, +int osc_sync_base(struct obd_export *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset) { @@ -470,14 +469,14 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo, body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY); LASSERT(body); lustre_set_wire_obdo(&req->rq_import->imp_connect_data, &body->oa, - oinfo->oi_oa); + oa); ptlrpc_request_set_replen(req); req->rq_interpret_reply = osc_sync_interpret; CLASSERT(sizeof(*fa) <= sizeof(req->rq_async_args)); fa = ptlrpc_req_async_args(req); - fa->fa_oi = oinfo; + fa->fa_oa = oa; fa->fa_upcall = upcall; fa->fa_cookie = cookie; -- cgit v1.2.3 From e10a431b3fd071bdbdea1ccb7aa2a9581f563deb Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 2 Oct 2016 22:28:36 -0400 Subject: staging: lustre: lov: move LSM to LOV layer Move the definition of struct lov_stripe_md along with supporting functions from obd.h to lov_internal.h. Remove the unused functions obd_packmd() and obd_free_diskmd(). Simplify lov_obd_packmd() according to the reduced use cases and rename it lov_packmd(). Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/13696 Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 77 +---------- drivers/staging/lustre/lustre/include/obd_class.h | 38 ------ .../staging/lustre/lustre/llite/llite_internal.h | 2 - drivers/staging/lustre/lustre/llite/vvp_internal.h | 1 - drivers/staging/lustre/lustre/lmv/lmv_obd.c | 105 --------------- drivers/staging/lustre/lustre/lov/lov_ea.c | 4 +- drivers/staging/lustre/lustre/lov/lov_internal.h | 80 +++++++++++- drivers/staging/lustre/lustre/lov/lov_obd.c | 9 -- drivers/staging/lustre/lustre/lov/lov_pack.c | 145 ++++++--------------- drivers/staging/lustre/lustre/mdc/mdc_request.c | 8 -- drivers/staging/lustre/lustre/osc/osc_request.c | 63 --------- 11 files changed, 118 insertions(+), 414 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f63336fd801c..ebb301250931 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -73,53 +73,7 @@ static inline void loi_init(struct lov_oinfo *loi) { } -/* - * If we are unable to get the maximum object size from the OST in - * ocd_maxbytes using OBD_CONNECT_MAXBYTES, then we fall back to using - * the old maximum object size from ext3. - */ -#define LUSTRE_EXT3_STRIPE_MAXBYTES 0x1fffffff000ULL - -struct lov_stripe_md { - atomic_t lsm_refc; - spinlock_t lsm_lock; - pid_t lsm_lock_owner; /* debugging */ - - /* maximum possible file size, might change as OSTs status changes, - * e.g. disconnected, deactivated - */ - loff_t lsm_maxbytes; - struct ost_id lsm_oi; - __u32 lsm_magic; - __u32 lsm_stripe_size; - __u32 lsm_pattern; /* striping pattern (RAID0, RAID1) */ - __u16 lsm_stripe_count; - __u16 lsm_layout_gen; - char lsm_pool_name[LOV_MAXPOOLNAME + 1]; - struct lov_oinfo *lsm_oinfo[0]; -}; - -static inline bool lsm_is_released(struct lov_stripe_md *lsm) -{ - return !!(lsm->lsm_pattern & LOV_PATTERN_F_RELEASED); -} - -static inline bool lsm_has_objects(struct lov_stripe_md *lsm) -{ - if (!lsm) - return false; - if (lsm_is_released(lsm)) - return false; - return true; -} - -static inline int lov_stripe_md_size(unsigned int stripe_count) -{ - struct lov_stripe_md lsm; - - return sizeof(lsm) + stripe_count * sizeof(lsm.lsm_oinfo[0]); -} - +struct lov_stripe_md; struct obd_info; typedef int (*obd_enqueue_update_f)(void *cookie, int rc); @@ -854,8 +808,6 @@ struct obd_ops { struct obd_statfs *osfs, __u64 max_age, __u32 flags); int (*statfs_async)(struct obd_export *exp, struct obd_info *oinfo, __u64 max_age, struct ptlrpc_request_set *set); - int (*packmd)(struct obd_export *exp, struct lov_mds_md **disk_tgt, - struct lov_stripe_md *mem_src); int (*unpackmd)(struct obd_export *exp, struct lov_stripe_md **mem_tgt, struct lov_mds_md *disk_src, int disk_len); @@ -1033,33 +985,6 @@ struct md_ops { */ }; -struct lsm_operations { - void (*lsm_free)(struct lov_stripe_md *); - void (*lsm_stripe_by_index)(struct lov_stripe_md *, int *, u64 *, - u64 *); - void (*lsm_stripe_by_offset)(struct lov_stripe_md *, int *, u64 *, - u64 *); - int (*lsm_lmm_verify)(struct lov_mds_md *lmm, int lmm_bytes, - __u16 *stripe_count); - int (*lsm_unpackmd)(struct lov_obd *lov, struct lov_stripe_md *lsm, - struct lov_mds_md *lmm); -}; - -extern const struct lsm_operations lsm_v1_ops; -extern const struct lsm_operations lsm_v3_ops; -static inline const struct lsm_operations *lsm_op_find(int magic) -{ - switch (magic) { - case LOV_MAGIC_V1: - return &lsm_v1_ops; - case LOV_MAGIC_V3: - return &lsm_v3_ops; - default: - CERROR("Cannot recognize lsm_magic %08x\n", magic); - return NULL; - } -} - static inline struct md_open_data *obd_mod_alloc(void) { struct md_open_data *mod; diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 0eaea549dd6f..aba96c33c95e 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -609,44 +609,6 @@ obd_process_config(struct obd_device *obd, int datalen, void *data) return rc; } -/* Pack an in-memory MD struct for storage on disk. - * Returns +ve size of packed MD (0 for free), or -ve error. - * - * If @disk_tgt == NULL, MD size is returned (max size if @mem_src == NULL). - * If @*disk_tgt != NULL and @mem_src == NULL, @*disk_tgt will be freed. - * If @*disk_tgt == NULL, it will be allocated - */ -static inline int obd_packmd(struct obd_export *exp, - struct lov_mds_md **disk_tgt, - struct lov_stripe_md *mem_src) -{ - int rc; - - EXP_CHECK_DT_OP(exp, packmd); - EXP_COUNTER_INCREMENT(exp, packmd); - - rc = OBP(exp->exp_obd, packmd)(exp, disk_tgt, mem_src); - return rc; -} - -static inline int obd_free_diskmd(struct obd_export *exp, - struct lov_mds_md **disk_tgt) -{ - LASSERT(disk_tgt); - LASSERT(*disk_tgt); - /* - * LU-2590, for caller's convenience, *disk_tgt could be host - * endianness, it needs swab to LE if necessary, while just - * lov_mds_md header needs it for figuring out how much memory - * needs to be freed. - */ - if ((cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) && - (((*disk_tgt)->lmm_magic == LOV_MAGIC_V1) || - ((*disk_tgt)->lmm_magic == LOV_MAGIC_V3))) - lustre_swab_lov_mds_md(*disk_tgt); - return obd_packmd(exp, disk_tgt, NULL); -} - /* Unpack an MD struct from disk to in-memory format. * Returns +ve size of unpacked MD (0 for free), or -ve error. * diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 675a41a89e3d..80fb862b6d2f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -609,8 +609,6 @@ struct ll_file_data { struct list_head fd_lccs; /* list of ll_cl_context */ }; -struct lov_stripe_md; - extern struct dentry *llite_root; extern struct kset *llite_kset; diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 891227c25031..afed7db1a8d0 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -42,7 +42,6 @@ enum obd_notify_event; struct inode; -struct lov_stripe_md; struct lustre_md; struct obd_device; struct obd_export; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 75f595820880..679cd872045b 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2736,90 +2736,6 @@ static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } -static int lmv_pack_md_v1(const struct lmv_stripe_md *lsm, - struct lmv_mds_md_v1 *lmm1) -{ - int cplen; - int i; - - lmm1->lmv_magic = cpu_to_le32(lsm->lsm_md_magic); - lmm1->lmv_stripe_count = cpu_to_le32(lsm->lsm_md_stripe_count); - lmm1->lmv_master_mdt_index = cpu_to_le32(lsm->lsm_md_master_mdt_index); - lmm1->lmv_hash_type = cpu_to_le32(lsm->lsm_md_hash_type); - cplen = strlcpy(lmm1->lmv_pool_name, lsm->lsm_md_pool_name, - sizeof(lmm1->lmv_pool_name)); - if (cplen >= sizeof(lmm1->lmv_pool_name)) - return -E2BIG; - - for (i = 0; i < lsm->lsm_md_stripe_count; i++) - fid_cpu_to_le(&lmm1->lmv_stripe_fids[i], - &lsm->lsm_md_oinfo[i].lmo_fid); - return 0; -} - -static int -lmv_pack_md(union lmv_mds_md **lmmp, const struct lmv_stripe_md *lsm, - int stripe_count) -{ - int lmm_size = 0, rc = 0; - bool allocated = false; - - LASSERT(lmmp); - - /* Free lmm */ - if (*lmmp && !lsm) { - int stripe_cnt; - - stripe_cnt = lmv_mds_md_stripe_count_get(*lmmp); - lmm_size = lmv_mds_md_size(stripe_cnt, - le32_to_cpu((*lmmp)->lmv_magic)); - if (!lmm_size) - return -EINVAL; - kvfree(*lmmp); - *lmmp = NULL; - return 0; - } - - /* Alloc lmm */ - if (!*lmmp && !lsm) { - lmm_size = lmv_mds_md_size(stripe_count, LMV_MAGIC); - LASSERT(lmm_size > 0); - *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); - if (!*lmmp) - return -ENOMEM; - lmv_mds_md_stripe_count_set(*lmmp, stripe_count); - (*lmmp)->lmv_magic = cpu_to_le32(LMV_MAGIC); - return lmm_size; - } - - /* pack lmm */ - LASSERT(lsm); - lmm_size = lmv_mds_md_size(lsm->lsm_md_stripe_count, - lsm->lsm_md_magic); - if (!*lmmp) { - *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); - if (!*lmmp) - return -ENOMEM; - allocated = true; - } - - switch (lsm->lsm_md_magic) { - case LMV_MAGIC_V1: - rc = lmv_pack_md_v1(lsm, &(*lmmp)->lmv_md_v1); - break; - default: - rc = -EINVAL; - break; - } - - if (rc && allocated) { - kvfree(*lmmp); - *lmmp = NULL; - } - - return lmm_size; -} - static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm, const struct lmv_mds_md_v1 *lmm1) { @@ -2959,26 +2875,6 @@ static int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, (union lmv_mds_md *)lmm, disk_len); } -static int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) -{ - const struct lmv_stripe_md *lmv = (struct lmv_stripe_md *)lsm; - struct obd_device *obd = exp->exp_obd; - struct lmv_obd *lmv_obd = &obd->u.lmv; - int stripe_count; - - if (!lmmp) { - if (lsm) - stripe_count = lmv->lsm_md_stripe_count; - else - stripe_count = lmv_obd->desc.ld_tgt_count; - - return lmv_mds_md_size(stripe_count, LMV_MAGIC_V1); - } - - return lmv_pack_md((union lmv_mds_md **)lmmp, lmv, 0); -} - static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, ldlm_policy_data_t *policy, enum ldlm_mode mode, enum ldlm_cancel_flags flags, void *opaque) @@ -3282,7 +3178,6 @@ static struct obd_ops lmv_obd_ops = { .statfs = lmv_statfs, .get_info = lmv_get_info, .set_info_async = lmv_set_info_async, - .packmd = lmv_packmd, .unpackmd = lmv_unpackmd, .notify = lmv_notify, .get_uuid = lmv_get_uuid, diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c index 63dcd294bfac..d7dc0aa113de 100644 --- a/drivers/staging/lustre/lustre/lov/lov_ea.c +++ b/drivers/staging/lustre/lustre/lov/lov_ea.c @@ -206,7 +206,7 @@ static int lsm_unpackmd_common(struct lov_obd *lov, static void lsm_stripe_by_index_plain(struct lov_stripe_md *lsm, int *stripeno, - u64 *lov_off, u64 *swidth) + loff_t *lov_off, loff_t *swidth) { if (swidth) *swidth = (u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count; @@ -214,7 +214,7 @@ lsm_stripe_by_index_plain(struct lov_stripe_md *lsm, int *stripeno, static void lsm_stripe_by_offset_plain(struct lov_stripe_md *lsm, int *stripeno, - u64 *lov_off, u64 *swidth) + loff_t *lov_off, loff_t *swidth) { if (swidth) *swidth = (u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count; diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index bd105d97cc5a..41e7c5fc374e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -36,6 +36,84 @@ #include "../include/obd_class.h" #include "../include/lustre/lustre_user.h" +/* + * If we are unable to get the maximum object size from the OST in + * ocd_maxbytes using OBD_CONNECT_MAXBYTES, then we fall back to using + * the old maximum object size from ext3. + */ +#define LUSTRE_EXT3_STRIPE_MAXBYTES 0x1fffffff000ULL + +struct lov_stripe_md { + atomic_t lsm_refc; + spinlock_t lsm_lock; + pid_t lsm_lock_owner; /* debugging */ + + /* + * maximum possible file size, might change as OSTs status changes, + * e.g. disconnected, deactivated + */ + loff_t lsm_maxbytes; + struct ost_id lsm_oi; + u32 lsm_magic; + u32 lsm_stripe_size; + u32 lsm_pattern; /* RAID0, RAID1, released, ... */ + u16 lsm_stripe_count; + u16 lsm_layout_gen; + char lsm_pool_name[LOV_MAXPOOLNAME + 1]; + struct lov_oinfo *lsm_oinfo[0]; +}; + +static inline bool lsm_is_released(struct lov_stripe_md *lsm) +{ + return !!(lsm->lsm_pattern & LOV_PATTERN_F_RELEASED); +} + +static inline bool lsm_has_objects(struct lov_stripe_md *lsm) +{ + if (!lsm) + return false; + + if (lsm_is_released(lsm)) + return false; + + return true; +} + +static inline int lov_stripe_md_size(unsigned int stripe_count) +{ + struct lov_stripe_md lsm; + + return sizeof(lsm) + stripe_count * sizeof(lsm.lsm_oinfo[0]); +} + +struct lsm_operations { + void (*lsm_free)(struct lov_stripe_md *); + void (*lsm_stripe_by_index)(struct lov_stripe_md *, int *, loff_t *, + loff_t *); + void (*lsm_stripe_by_offset)(struct lov_stripe_md *, int *, loff_t *, + loff_t *); + int (*lsm_lmm_verify)(struct lov_mds_md *lmm, int lmm_bytes, + u16 *stripe_count); + int (*lsm_unpackmd)(struct lov_obd *lov, struct lov_stripe_md *lsm, + struct lov_mds_md *lmm); +}; + +extern const struct lsm_operations lsm_v1_ops; +extern const struct lsm_operations lsm_v3_ops; + +static inline const struct lsm_operations *lsm_op_find(int magic) +{ + switch (magic) { + case LOV_MAGIC_V1: + return &lsm_v1_ops; + case LOV_MAGIC_V3: + return &lsm_v3_ops; + default: + CERROR("unrecognized lsm_magic %08x\n", magic); + return NULL; + } +} + /* lov_do_div64(a, b) returns a % b, and a = a / b. * The 32-bit code is LOV-specific due to knowing about stripe limits in * order to reduce the divisor to a 32-bit number. If the divisor is @@ -176,8 +254,6 @@ int lov_del_target(struct obd_device *obd, __u32 index, /* lov_pack.c */ ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf, size_t buf_size); -int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmm, - struct lov_stripe_md *lsm); int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm, int lmm_bytes); int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 653018738995..621f66ef1d9b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -971,14 +971,6 @@ out: return rc; } -#define ASSERT_LSM_MAGIC(lsmp) \ -do { \ - LASSERT((lsmp)); \ - LASSERTF(((lsmp)->lsm_magic == LOV_MAGIC_V1 || \ - (lsmp)->lsm_magic == LOV_MAGIC_V3), \ - "%p->lsm_magic=%x\n", (lsmp), (lsmp)->lsm_magic); \ -} while (0) - int lov_statfs_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { struct lov_request_set *lovset = (struct lov_request_set *)data; @@ -1414,7 +1406,6 @@ static struct obd_ops lov_obd_ops = { .disconnect = lov_disconnect, .statfs = lov_statfs, .statfs_async = lov_statfs_async, - .packmd = lov_packmd, .unpackmd = lov_unpackmd, .iocontrol = lov_iocontrol, .get_info = lov_get_info, diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 1156ef986422..17bceadd66f8 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -153,96 +153,6 @@ ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf, return lmm_size; } -/* Pack LOV object metadata for disk storage. It is packed in LE byte - * order and is opaque to the networking layer. - * - * XXX In the future, this will be enhanced to get the EA size from the - * underlying OSC device(s) to get their EA sizes so we can stack - * LOVs properly. For now lov_mds_md_size() just assumes one u64 - * per stripe. - */ -int lov_obd_packmd(struct lov_obd *lov, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) -{ - __u16 stripe_count; - int lmm_size, lmm_magic; - - if (lsm) { - lmm_magic = lsm->lsm_magic; - } else { - if (lmmp && *lmmp) - lmm_magic = le32_to_cpu((*lmmp)->lmm_magic); - else - /* lsm == NULL and lmmp == NULL */ - lmm_magic = LOV_MAGIC; - } - - if ((lmm_magic != LOV_MAGIC_V1) && - (lmm_magic != LOV_MAGIC_V3)) { - CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", - lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); - return -EINVAL; - } - - if (lsm) { - /* If we are just sizing the EA, limit the stripe count - * to the actual number of OSTs in this filesystem. - */ - if (!lmmp) { - stripe_count = lov_get_stripecnt(lov, lmm_magic, - lsm->lsm_stripe_count); - lsm->lsm_stripe_count = stripe_count; - } else if (!lsm_is_released(lsm)) { - stripe_count = lsm->lsm_stripe_count; - } else { - stripe_count = 0; - } - } else { - /* - * To calculate maximum easize by active targets at present, - * which is exactly the maximum easize to be seen by LOV - */ - stripe_count = lov->desc.ld_active_tgt_count; - } - - /* XXX LOV STACKING call into osc for sizes */ - lmm_size = lov_mds_md_size(stripe_count, lmm_magic); - - if (!lmmp) - return lmm_size; - - if (*lmmp && !lsm) { - stripe_count = le16_to_cpu((*lmmp)->lmm_stripe_count); - lmm_size = lov_mds_md_size(stripe_count, lmm_magic); - kvfree(*lmmp); - *lmmp = NULL; - return 0; - } - - if (!*lmmp) { - *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); - if (!*lmmp) - return -ENOMEM; - } - - CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d\n", - lmm_magic, lmm_size); - - if (!lsm) - return lmm_size; - - return lov_lsm_pack(lsm, *lmmp, lmm_size); -} - -int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) -{ - struct obd_device *obd = class_exp2obd(exp); - struct lov_obd *lov = &obd->u.lov; - - return lov_obd_packmd(lov, lmmp, lsm); -} - /* Find the max stripecount we should use */ __u16 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u16 stripe_count) { @@ -393,15 +303,14 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, struct lov_user_md __user *lump) { - /* - * XXX huge struct allocated on stack. - */ /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ - struct lov_obd *lov; struct lov_user_md_v3 lum; - struct lov_mds_md *lmmk = NULL; - int rc, lmmk_size, lmm_size; - int lum_size; + struct lov_mds_md *lmmk; + u32 stripe_count; + ssize_t lmm_size; + size_t lmmk_size; + size_t lum_size; + int rc; mm_segment_t seg; if (!lsm) @@ -414,6 +323,18 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, seg = get_fs(); set_fs(KERNEL_DS); + if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) { + CERROR("bad LSM MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", + lsm->lsm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); + rc = -EIO; + goto out; + } + + if (!lsm_is_released(lsm)) + stripe_count = lsm->lsm_stripe_count; + else + stripe_count = 0; + /* we only need the header part from user space to get lmm_magic and * lmm_stripe_count, (the header part is common to v1 and v3) */ @@ -432,32 +353,40 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, if (lum.lmm_stripe_count && (lum.lmm_stripe_count < lsm->lsm_stripe_count)) { /* Return right size of stripe to user */ - lum.lmm_stripe_count = lsm->lsm_stripe_count; + lum.lmm_stripe_count = stripe_count; rc = copy_to_user(lump, &lum, lum_size); rc = -EOVERFLOW; goto out; } - lov = lu2lov_dev(obj->lo_cl.co_lu.lo_dev)->ld_lov; - rc = lov_obd_packmd(lov, &lmmk, lsm); - if (rc < 0) + lmmk_size = lov_mds_md_size(stripe_count, lsm->lsm_magic); + + + lmmk = libcfs_kvzalloc(lmmk_size, GFP_NOFS); + if (!lmmk) { + rc = -ENOMEM; goto out; - lmmk_size = rc; - lmm_size = rc; - rc = 0; + } + + lmm_size = lov_lsm_pack(lsm, lmmk, lmmk_size); + if (lmm_size < 0) { + rc = lmm_size; + goto out_free; + } /* FIXME: Bug 1185 - copy fields properly when structs change */ /* struct lov_user_md_v3 and struct lov_mds_md_v3 must be the same */ CLASSERT(sizeof(lum) == sizeof(struct lov_mds_md_v3)); CLASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lmmk->lmm_objects[0])); - if ((cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) && - ((lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) || - (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)))) { + if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC && + (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V1) || + lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V3))) { lustre_swab_lov_mds_md(lmmk); lustre_swab_lov_user_md_objects( (struct lov_user_ost_data *)lmmk->lmm_objects, lmmk->lmm_stripe_count); } + if (lum.lmm_magic == LOV_USER_MAGIC) { /* User request for v1, we need skip lmm_pool_name */ if (lmmk->lmm_magic == LOV_MAGIC_V3) { @@ -491,7 +420,7 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, rc = -EFAULT; out_free: - kfree(lmmk); + kvfree(lmmk); out: set_fs(seg); return rc; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 2d0dd1885321..5282c67ab019 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -447,14 +447,6 @@ static int mdc_get_lustre_md(struct obd_export *exp, if (rc < 0) goto out; - if (rc < (typeof(rc))sizeof(*md->lsm)) { - CDEBUG(D_INFO, - "lsm size too small: rc < sizeof (*md->lsm) (%d < %d)\n", - rc, (int)sizeof(*md->lsm)); - rc = -EPROTO; - goto out; - } - } else if (md->body->mbo_valid & OBD_MD_FLDIREA) { int lmvsize; struct lov_mds_md *lmv; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 0985bdae11eb..038f00c37ee7 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -103,68 +103,6 @@ static void osc_release_ppga(struct brw_page **ppga, u32 count); static int brw_interpret(const struct lu_env *env, struct ptlrpc_request *req, void *data, int rc); -/* Unpack OSC object metadata from disk storage (LE byte order). */ -static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int lmm_bytes) -{ - int lsm_size; - struct obd_import *imp = class_exp2cliimp(exp); - - if (lmm) { - if (lmm_bytes < sizeof(*lmm)) { - CERROR("%s: lov_mds_md too small: %d, need %d\n", - exp->exp_obd->obd_name, lmm_bytes, - (int)sizeof(*lmm)); - return -EINVAL; - } - /* XXX LOV_MAGIC etc check? */ - - if (unlikely(ostid_id(&lmm->lmm_oi) == 0)) { - CERROR("%s: zero lmm_object_id: rc = %d\n", - exp->exp_obd->obd_name, -EINVAL); - return -EINVAL; - } - } - - lsm_size = lov_stripe_md_size(1); - if (!lsmp) - return lsm_size; - - if (*lsmp && !lmm) { - kfree((*lsmp)->lsm_oinfo[0]); - kfree(*lsmp); - *lsmp = NULL; - return 0; - } - - if (!*lsmp) { - *lsmp = kzalloc(lsm_size, GFP_NOFS); - if (unlikely(!*lsmp)) - return -ENOMEM; - (*lsmp)->lsm_oinfo[0] = kzalloc(sizeof(struct lov_oinfo), - GFP_NOFS); - if (unlikely(!(*lsmp)->lsm_oinfo[0])) { - kfree(*lsmp); - return -ENOMEM; - } - loi_init((*lsmp)->lsm_oinfo[0]); - } else if (unlikely(ostid_id(&(*lsmp)->lsm_oi) == 0)) { - return -EBADF; - } - - if (lmm) - /* XXX zero *lsmp? */ - ostid_le_to_cpu(&lmm->lmm_oi, &(*lsmp)->lsm_oi); - - if (imp && - (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_MAXBYTES)) - (*lsmp)->lsm_maxbytes = imp->imp_connect_data.ocd_maxbytes; - else - (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; - - return lsm_size; -} - static inline void osc_pack_req_body(struct ptlrpc_request *req, struct obdo *oa) { @@ -2884,7 +2822,6 @@ static struct obd_ops osc_obd_ops = { .disconnect = osc_disconnect, .statfs = osc_statfs, .statfs_async = osc_statfs_async, - .unpackmd = osc_unpackmd, .create = osc_create, .destroy = osc_destroy, .getattr = osc_getattr, -- cgit v1.2.3 From 832bd710656e60816887895f08ed4a6de56a0678 Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Sun, 2 Oct 2016 22:28:37 -0400 Subject: staging: lustre: echo: request pages in batches rather than fetch them one by one. Signed-off-by: Alex Zhuravlev Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5278 Reviewed-on: http://review.whamcloud.com/13612 Reviewed-by: Nathaniel Clark Reviewed-by: Andreas Dilger Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/obdecho/echo_client.c | 38 +++++++++------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index d8e3e96b8e54..c69588cfe814 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1335,7 +1335,7 @@ static int echo_client_prep_commit(const struct lu_env *env, { struct obd_ioobj ioo; struct niobuf_local *lnb; - struct niobuf_remote *rnb; + struct niobuf_remote rnb; u64 off; u64 npages, tot_pages; int i, ret = 0, brw_flags = 0; @@ -1347,9 +1347,7 @@ static int echo_client_prep_commit(const struct lu_env *env, tot_pages = count >> PAGE_SHIFT; lnb = kcalloc(npages, sizeof(struct niobuf_local), GFP_NOFS); - rnb = kcalloc(npages, sizeof(struct niobuf_remote), GFP_NOFS); - - if (!lnb || !rnb) { + if (!lnb) { ret = -ENOMEM; goto out; } @@ -1361,25 +1359,22 @@ static int echo_client_prep_commit(const struct lu_env *env, off = offset; - for (; tot_pages; tot_pages -= npages) { + for (; tot_pages > 0; tot_pages -= npages) { int lpages; if (tot_pages < npages) npages = tot_pages; - for (i = 0; i < npages; i++, off += PAGE_SIZE) { - rnb[i].rnb_offset = off; - rnb[i].rnb_len = PAGE_SIZE; - rnb[i].rnb_flags = brw_flags; - } - - ioo.ioo_bufcnt = npages; + rnb.rnb_offset = off; + rnb.rnb_len = npages * PAGE_SIZE; + rnb.rnb_flags = brw_flags; + ioo.ioo_bufcnt = 1; + off += npages * PAGE_SIZE; lpages = npages; - ret = obd_preprw(env, rw, exp, oa, 1, &ioo, rnb, &lpages, lnb); + ret = obd_preprw(env, rw, exp, oa, 1, &ioo, &rnb, &lpages, lnb); if (ret != 0) goto out; - LASSERT(lpages == npages); for (i = 0; i < lpages; i++) { struct page *page = lnb[i].lnb_page; @@ -1398,17 +1393,17 @@ static int echo_client_prep_commit(const struct lu_env *env, if (rw == OBD_BRW_WRITE) echo_client_page_debug_setup(page, rw, - ostid_id(&oa->o_oi), - rnb[i].rnb_offset, - rnb[i].rnb_len); + ostid_id(&oa->o_oi), + lnb[i].lnb_file_offset, + lnb[i].lnb_len); else echo_client_page_debug_check(page, - ostid_id(&oa->o_oi), - rnb[i].rnb_offset, - rnb[i].rnb_len); + ostid_id(&oa->o_oi), + lnb[i].lnb_file_offset, + lnb[i].lnb_len); } - ret = obd_commitrw(env, rw, exp, oa, 1, &ioo, rnb, npages, lnb, + ret = obd_commitrw(env, rw, exp, oa, 1, &ioo, &rnb, npages, lnb, ret); if (ret != 0) goto out; @@ -1420,7 +1415,6 @@ static int echo_client_prep_commit(const struct lu_env *env, out: kfree(lnb); - kfree(rnb); return ret; } -- cgit v1.2.3 From 84d7238f937f11eced99b37f963b17dc03bfe1bc Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman Date: Mon, 3 Oct 2016 16:53:06 -0700 Subject: staging: lustre: use 'unsigned int' not unsigned Use unsigned int rather than unsigned in header variable declaration for readability. Error found by checkpatch. Signed-off-by: Elizabeth Ferdman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_cl_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 2b03938f6a63..a08e41d7c5d4 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -217,7 +217,7 @@ struct lov_object { union lov_layout_state { struct lov_layout_raid0 { - unsigned lo_nr; + unsigned int lo_nr; /** * When this is true, lov_object::lo_attr contains * valid up to date attributes for a top-level -- cgit v1.2.3 From c802be98d08adfe39795107da73858c088dc55d9 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:46:26 -0300 Subject: staging: wlan-ng: aligned block to open parenthesis Fixed multiple checkpatch warnings by aligning blocks to match open parenthesis. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2sta.c | 80 ++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index e1b4a94292ff..92a7bc5dd804 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -606,8 +606,8 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) hw->ident_nic.minor = le16_to_cpu(hw->ident_nic.minor); netdev_info(wlandev->netdev, "ident: nic h/w: id=0x%02x %d.%d.%d\n", - hw->ident_nic.id, hw->ident_nic.major, - hw->ident_nic.minor, hw->ident_nic.variant); + hw->ident_nic.id, hw->ident_nic.major, + hw->ident_nic.minor, hw->ident_nic.variant); /* Primary f/w identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY, @@ -625,8 +625,8 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) hw->ident_pri_fw.minor = le16_to_cpu(hw->ident_pri_fw.minor); netdev_info(wlandev->netdev, "ident: pri f/w: id=0x%02x %d.%d.%d\n", - hw->ident_pri_fw.id, hw->ident_pri_fw.major, - hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); + hw->ident_pri_fw.id, hw->ident_pri_fw.major, + hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); /* Station (Secondary?) f/w identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY, @@ -639,7 +639,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) if (hw->ident_nic.id < 0x8000) { netdev_err(wlandev->netdev, - "FATAL: Card is not an Intersil Prism2/2.5/3\n"); + "FATAL: Card is not an Intersil Prism2/2.5/3\n"); result = -1; goto failed; } @@ -656,14 +656,14 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) if (hw->ident_sta_fw.id == 0x1f) { netdev_info(wlandev->netdev, - "ident: sta f/w: id=0x%02x %d.%d.%d\n", - hw->ident_sta_fw.id, hw->ident_sta_fw.major, - hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + "ident: sta f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); } else { netdev_info(wlandev->netdev, - "ident: ap f/w: id=0x%02x %d.%d.%d\n", - hw->ident_sta_fw.id, hw->ident_sta_fw.major, - hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + "ident: ap f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); netdev_err(wlandev->netdev, "Unsupported Tertiary AP firmware loaded!\n"); goto failed; } @@ -687,10 +687,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) hw->cap_sup_mfi.top = le16_to_cpu(hw->cap_sup_mfi.top); netdev_info(wlandev->netdev, - "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_sup_mfi.role, hw->cap_sup_mfi.id, - hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom, - hw->cap_sup_mfi.top); + "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_mfi.role, hw->cap_sup_mfi.id, + hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom, + hw->cap_sup_mfi.top); /* Compatibility range, Controller supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE, @@ -711,10 +711,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) hw->cap_sup_cfi.top = le16_to_cpu(hw->cap_sup_cfi.top); netdev_info(wlandev->netdev, - "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_sup_cfi.role, hw->cap_sup_cfi.id, - hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom, - hw->cap_sup_cfi.top); + "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_cfi.role, hw->cap_sup_cfi.id, + hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom, + hw->cap_sup_cfi.top); /* Compatibility range, Primary f/w supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE, @@ -735,10 +735,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) hw->cap_sup_pri.top = le16_to_cpu(hw->cap_sup_pri.top); netdev_info(wlandev->netdev, - "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_sup_pri.role, hw->cap_sup_pri.id, - hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom, - hw->cap_sup_pri.top); + "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_pri.role, hw->cap_sup_pri.id, + hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom, + hw->cap_sup_pri.top); /* Compatibility range, Station f/w supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE, @@ -791,10 +791,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) hw->cap_act_pri_cfi.top = le16_to_cpu(hw->cap_act_pri_cfi.top); netdev_info(wlandev->netdev, - "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id, - hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom, - hw->cap_act_pri_cfi.top); + "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id, + hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom, + hw->cap_act_pri_cfi.top); /* Compatibility range, sta f/w actor, CFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES, @@ -815,10 +815,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) hw->cap_act_sta_cfi.top = le16_to_cpu(hw->cap_act_sta_cfi.top); netdev_info(wlandev->netdev, - "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id, - hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom, - hw->cap_act_sta_cfi.top); + "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id, + hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom, + hw->cap_act_sta_cfi.top); /* Compatibility range, sta f/w actor, MFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES, @@ -839,10 +839,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) hw->cap_act_sta_mfi.top = le16_to_cpu(hw->cap_act_sta_mfi.top); netdev_info(wlandev->netdev, - "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id, - hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom, - hw->cap_act_sta_mfi.top); + "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id, + hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom, + hw->cap_act_sta_mfi.top); /* Serial Number */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, @@ -920,7 +920,7 @@ static int prism2sta_globalsetup(struct wlandevice *wlandev) } static int prism2sta_setmulticast(struct wlandevice *wlandev, - struct net_device *dev) + struct net_device *dev) { int result = 0; struct hfa384x *hw = wlandev->priv; @@ -1064,7 +1064,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, &joinreq, HFA384x_RID_JOINREQUEST_LEN); if (result) { netdev_err(wlandev->netdev, "setconfig(joinreq) failed, result=%d\n", - result); + result); } } @@ -1294,7 +1294,7 @@ void prism2sta_processing_defer(struct work_struct *data) */ if (wlandev->netdev->type == ARPHRD_ETHER) netdev_info(wlandev->netdev, - "linkstatus=DISCONNECTED (unhandled)\n"); + "linkstatus=DISCONNECTED (unhandled)\n"); wlandev->macmode = WLAN_MACMODE_NONE; netif_carrier_off(wlandev->netdev); @@ -1415,7 +1415,7 @@ void prism2sta_processing_defer(struct work_struct *data) default: /* This is bad, IO port problems? */ netdev_warn(wlandev->netdev, - "unknown linkstatus=0x%02x\n", hw->link_status); + "unknown linkstatus=0x%02x\n", hw->link_status); return; } @@ -1785,7 +1785,7 @@ void prism2sta_ev_info(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) break; default: netdev_warn(wlandev->netdev, - "Unknown info type=0x%02x\n", inf->infotype); + "Unknown info type=0x%02x\n", inf->infotype); break; } } -- cgit v1.2.3 From 1230053264ff43b0165ec78d4c6fe3135888e42c Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:46:43 -0300 Subject: staging: wlan-ng: fixed lines over 80 characters Breaks lines over 80 characters that were causing checkpatch issues. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2sta.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 92a7bc5dd804..fd662ffeb268 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -104,7 +104,8 @@ static void prism2sta_reset(struct wlandevice *wlandev); static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep); -static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *msg); +static int prism2sta_mlmerequest(struct wlandevice *wlandev, + struct p80211msg *msg); static int prism2sta_getcardinfo(struct wlandevice *wlandev); static int prism2sta_globalsetup(struct wlandevice *wlandev); static int prism2sta_setmulticast(struct wlandevice *wlandev, @@ -278,7 +279,8 @@ static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, * Call context: * process thread */ -static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *msg) +static int prism2sta_mlmerequest(struct wlandevice *wlandev, + struct p80211msg *msg) { struct hfa384x *hw = wlandev->priv; @@ -1099,7 +1101,8 @@ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, kfree(hw->scanresults); - hw->scanresults = kmemdup(inf, sizeof(struct hfa384x_InfFrame), GFP_ATOMIC); + hw->scanresults = kmemdup(inf, sizeof(struct hfa384x_InfFrame), + GFP_ATOMIC); if (nbss == 0) nbss = -1; -- cgit v1.2.3 From 60f5f3fb78b1410ebe787f067b1372a515d26f38 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:47:05 -0300 Subject: staging: wlan-ng: renames hfa384x_InfFrame to avoid camelcase Renames hfa384x_InfFrame to hfa384x_inf_frame in order to fix a checkpatch error caused by camelcase. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 6 ++--- drivers/staging/wlan-ng/prism2mgmt.h | 3 ++- drivers/staging/wlan-ng/prism2sta.c | 49 ++++++++++++++++++------------------ 3 files changed, 30 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 43c299c3b631..7577f2b66f17 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -774,7 +774,7 @@ union hfa384x_infodata { struct hfa384x_KeyIDChanged keyidchanged; } __packed; -struct hfa384x_InfFrame { +struct hfa384x_inf_frame { u16 framelen; u16 infotype; union hfa384x_infodata info; @@ -862,7 +862,7 @@ struct hfa384x_usb_rxfrm { struct hfa384x_usb_infofrm { u16 type; - struct hfa384x_InfFrame info; + struct hfa384x_inf_frame info; } __packed; struct hfa384x_usb_statusresp { @@ -1370,7 +1370,7 @@ struct hfa384x { struct hfa384x_ChInfoResult results; } channel_info; - struct hfa384x_InfFrame *scanresults; + struct hfa384x_inf_frame *scanresults; struct prism2sta_authlist authlist; /* Authenticated station list. */ unsigned int accessmode; /* Access mode. */ diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index cc1ac7a60dfe..567820fc3735 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -65,7 +65,8 @@ extern int prism2_reset_settletime; u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate); -void prism2sta_ev_info(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf); +void prism2sta_ev_info(struct wlandevice *wlandev, + struct hfa384x_inf_frame *inf); void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status); void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status); void prism2sta_ev_alloc(struct wlandevice *wlandev); diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index fd662ffeb268..2641641e4a07 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -112,25 +112,25 @@ static int prism2sta_setmulticast(struct wlandevice *wlandev, struct net_device *dev); static void prism2sta_inf_handover(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_tallies(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_scanresults(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_authreq(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf); + struct hfa384x_inf_frame *inf); /* * prism2sta_open @@ -964,7 +964,7 @@ exit: * interrupt */ static void prism2sta_inf_handover(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { pr_debug("received infoframe:HANDOVER (unhandled)\n"); } @@ -987,7 +987,7 @@ static void prism2sta_inf_handover(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_tallies(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; u16 *src16; @@ -1033,7 +1033,7 @@ static void prism2sta_inf_tallies(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; int nbss; @@ -1088,7 +1088,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; int nbss; @@ -1101,7 +1101,7 @@ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, kfree(hw->scanresults); - hw->scanresults = kmemdup(inf, sizeof(struct hfa384x_InfFrame), + hw->scanresults = kmemdup(inf, sizeof(struct hfa384x_inf_frame), GFP_ATOMIC); if (nbss == 0) @@ -1130,7 +1130,7 @@ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; unsigned int i, n; @@ -1182,10 +1182,10 @@ void prism2sta_processing_defer(struct work_struct *data) /* First let's process the auth frames */ { struct sk_buff *skb; - struct hfa384x_InfFrame *inf; + struct hfa384x_inf_frame *inf; while ((skb = skb_dequeue(&hw->authq))) { - inf = (struct hfa384x_InfFrame *)skb->data; + inf = (struct hfa384x_inf_frame *)skb->data; prism2sta_inf_authreq_defer(wlandev, inf); } @@ -1443,7 +1443,7 @@ void prism2sta_processing_defer(struct work_struct *data) * interrupt */ static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; @@ -1471,7 +1471,7 @@ static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; struct hfa384x_AssocStatus rec; @@ -1532,7 +1532,7 @@ static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, * */ static void prism2sta_inf_authreq(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; struct sk_buff *skb; @@ -1547,7 +1547,7 @@ static void prism2sta_inf_authreq(struct wlandevice *wlandev, } static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; struct hfa384x_authenticateStation_data rec; @@ -1721,7 +1721,7 @@ static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, - struct hfa384x_InfFrame *inf) + struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; @@ -1745,7 +1745,8 @@ static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, * Call context: * interrupt */ -void prism2sta_ev_info(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) +void prism2sta_ev_info(struct wlandevice *wlandev, + struct hfa384x_inf_frame *inf) { inf->infotype = le16_to_cpu(inf->infotype); /* Dispatch */ -- cgit v1.2.3 From b244edc632b17de4a6638fcafc1c96f9d817b421 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:47:21 -0300 Subject: staging: wlan-ng: renames hfa384x_CommTallies32 to avoid camelcase Fixes a checkpatch warning by renaming the camelcased struct hfa384x_CommTallies32 to hfa384x_comm_tallies_32. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 6 +++--- drivers/staging/wlan-ng/prism2sta.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 7577f2b66f17..e4105e190e84 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -634,7 +634,7 @@ struct hfa384x_CommTallies16 { u16 rxmsginbadmsgfrag; } __packed; -struct hfa384x_CommTallies32 { +struct hfa384x_comm_tallies_32 { u32 txunicastframes; u32 txmulticastframes; u32 txfragments; @@ -763,7 +763,7 @@ struct hfa384x_KeyIDChanged { /*-- Collection of all Inf frames ---------------*/ union hfa384x_infodata { struct hfa384x_CommTallies16 commtallies16; - struct hfa384x_CommTallies32 commtallies32; + struct hfa384x_comm_tallies_32 commtallies32; struct hfa384x_ScanResult scanresult; struct hfa384x_ChInfoResult chinforesult; struct hfa384x_HScanResult hscanresult; @@ -1360,7 +1360,7 @@ struct hfa384x { struct hfa384x_caplevel cap_act_ap_mfi; /* ap f/w to modem interface */ u32 psusercount; /* Power save user count. */ - struct hfa384x_CommTallies32 tallies; /* Communication tallies. */ + struct hfa384x_comm_tallies_32 tallies; /* Communication tallies. */ u8 comment[WLAN_COMMENT_MAX + 1]; /* User comment */ /* Channel Info request results (AP only) */ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 2641641e4a07..73dd3445bde1 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1001,7 +1001,7 @@ static void prism2sta_inf_tallies(struct wlandevice *wlandev, * record length of the info record. */ - cnt = sizeof(struct hfa384x_CommTallies32) / sizeof(u32); + cnt = sizeof(struct hfa384x_comm_tallies_32) / sizeof(u32); if (inf->framelen > 22) { dst = (u32 *)&hw->tallies; src32 = (u32 *)&inf->info.commtallies32; -- cgit v1.2.3 From 040a7bd4ec0011f922fea6f824ec3175911733f8 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:47:38 -0300 Subject: staging: wlan-ng: renames hfa384x_ScanResult to avoid camelcase Renames the camelcased struct hfa384x_ScanResult to hfa384x_scan_result in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- drivers/staging/wlan-ng/prism2sta.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index e4105e190e84..6268703b6dd3 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -671,7 +671,7 @@ struct hfa384x_ScanResultSub { u16 proberesp_rate; } __packed; -struct hfa384x_ScanResult { +struct hfa384x_scan_result { u16 rsvd; u16 scanreason; struct hfa384x_ScanResultSub result[HFA384x_SCANRESULT_MAX]; @@ -764,7 +764,7 @@ struct hfa384x_KeyIDChanged { union hfa384x_infodata { struct hfa384x_CommTallies16 commtallies16; struct hfa384x_comm_tallies_32 commtallies32; - struct hfa384x_ScanResult scanresult; + struct hfa384x_scan_result scanresult; struct hfa384x_ChInfoResult chinforesult; struct hfa384x_HScanResult hscanresult; struct hfa384x_LinkStatus linkstatus; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 73dd3445bde1..ec62bb524de0 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1037,7 +1037,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, { struct hfa384x *hw = wlandev->priv; int nbss; - struct hfa384x_ScanResult *sr = &(inf->info.scanresult); + struct hfa384x_scan_result *sr = &inf->info.scanresult; int i; struct hfa384x_JoinRequest_data joinreq; int result; -- cgit v1.2.3 From de3dc47c9e7cd120d25ef824df3f3ce0e9f1a2b4 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:47:52 -0300 Subject: staging: wlan-ng: renames hfa384x_JoinRequest_data to avoid camelcase Renames the camelcased struct hfa384x_JoinRequest_data to hfa384x_join_request_data in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 6 +++--- drivers/staging/wlan-ng/prism2sta.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 6268703b6dd3..7af07cbc6aae 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -266,7 +266,7 @@ #define HFA384x_RID_DBMCOMMSQUALITY_LEN \ ((u16)sizeof(struct hfa384x_dbmcommsquality)) #define HFA384x_RID_JOINREQUEST_LEN \ - ((u16)sizeof(struct hfa384x_JoinRequest_data)) + ((u16)sizeof(struct hfa384x_join_request_data)) /*-------------------------------------------------------------------- * Information RIDs: Modem Information @@ -415,7 +415,7 @@ struct hfa384x_HostScanRequest_data { } __packed; /*-- Configuration Record: JoinRequest (data portion only) --*/ -struct hfa384x_JoinRequest_data { +struct hfa384x_join_request_data { u8 bssid[WLAN_BSSID_LEN]; u16 channel; } __packed; @@ -1294,7 +1294,7 @@ struct hfa384x { int scanflag; /* to signal scan complete */ int join_ap; /* are we joined to a specific ap */ int join_retries; /* number of join retries till we fail */ - struct hfa384x_JoinRequest_data joinreq; /* join request saved data */ + struct hfa384x_join_request_data joinreq;/* join request saved data */ struct wlandevice *wlandev; /* Timer to allow for the deferred processing of linkstatus messages */ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index ec62bb524de0..c74f48698bc0 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1039,7 +1039,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, int nbss; struct hfa384x_scan_result *sr = &inf->info.scanresult; int i; - struct hfa384x_JoinRequest_data joinreq; + struct hfa384x_join_request_data joinreq; int result; /* Get the number of results, first in bytes, then in results */ @@ -1394,7 +1394,7 @@ void prism2sta_processing_defer(struct work_struct *data) * Disable Transmits, Ignore receives of data frames */ if (hw->join_ap && --hw->join_retries > 0) { - struct hfa384x_JoinRequest_data joinreq; + struct hfa384x_join_request_data joinreq; joinreq = hw->joinreq; /* Send the join request */ -- cgit v1.2.3 From b263dd5e3ea666376e75d62b22f3951592a2c331 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:48:10 -0300 Subject: staging: wlan-ng: renames hfa384x_scanResultSub to avoid camelcase Renames the camelcased struct hfa384x_scanResultSub to hfa384x_scan_result_sub in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- drivers/staging/wlan-ng/prism2sta.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 7af07cbc6aae..e3fae14fc220 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -659,7 +659,7 @@ struct hfa384x_comm_tallies_32 { } __packed; /*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/ -struct hfa384x_ScanResultSub { +struct hfa384x_scan_result_sub { u16 chid; u16 anl; u16 sl; @@ -674,7 +674,7 @@ struct hfa384x_ScanResultSub { struct hfa384x_scan_result { u16 rsvd; u16 scanreason; - struct hfa384x_ScanResultSub result[HFA384x_SCANRESULT_MAX]; + struct hfa384x_scan_result_sub result[HFA384x_SCANRESULT_MAX]; } __packed; /*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index c74f48698bc0..8a9153441d97 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1045,7 +1045,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, /* Get the number of results, first in bytes, then in results */ nbss = (inf->framelen * sizeof(u16)) - sizeof(inf->infotype) - sizeof(inf->info.scanresult.scanreason); - nbss /= sizeof(struct hfa384x_ScanResultSub); + nbss /= sizeof(struct hfa384x_scan_result_sub); /* Print em */ pr_debug("rx scanresults, reason=%d, nbss=%d:\n", -- cgit v1.2.3 From e35baeb07ce8745c6e485d5483923319fb18aef1 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:48:31 -0300 Subject: staging: wlan-ng: renames hfa384x_ChInfoResultSub to avoid camelcase Renames the camelcased struct hfa384x_ChInfoResultSub to hfa384x_ch_info_result_sub in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- drivers/staging/wlan-ng/prism2sta.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index e3fae14fc220..7b6b37375b28 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -678,7 +678,7 @@ struct hfa384x_scan_result { } __packed; /*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ -struct hfa384x_ChInfoResultSub { +struct hfa384x_ch_info_result_sub { u16 chid; u16 anl; u16 pnl; @@ -690,7 +690,7 @@ struct hfa384x_ChInfoResultSub { struct hfa384x_ChInfoResult { u16 scanchannels; - struct hfa384x_ChInfoResultSub result[HFA384x_CHINFORESULT_MAX]; + struct hfa384x_ch_info_result_sub result[HFA384x_CHINFORESULT_MAX]; } __packed; /*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 8a9153441d97..0d2bc69a5b47 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1139,8 +1139,8 @@ static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, le16_to_cpu(inf->info.chinforesult.scanchannels); for (i = 0, n = 0; i < HFA384x_CHINFORESULT_MAX; i++) { - struct hfa384x_ChInfoResultSub *result; - struct hfa384x_ChInfoResultSub *chinforesult; + struct hfa384x_ch_info_result_sub *result; + struct hfa384x_ch_info_result_sub *chinforesult; int chan; if (!(hw->channel_info.results.scanchannels & (1 << i))) -- cgit v1.2.3 From 1889b0db31a0d35ad65604b5f0d57579aa0d6bc4 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:48:46 -0300 Subject: staging: wlan-ng: renames hfa384x_AssocStatus to avoid camelcase Renames the camelcased struct hfa384x_AssocStatus to hfa384x_assoc_status in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- drivers/staging/wlan-ng/prism2sta.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 7b6b37375b28..adbac69b952c 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -733,7 +733,7 @@ struct hfa384x_LinkStatus { #define HFA384x_ASSOCSTATUS_REASSOC ((u16)2) #define HFA384x_ASSOCSTATUS_AUTHFAIL ((u16)5) -struct hfa384x_AssocStatus { +struct hfa384x_assoc_status { u16 assocstatus; u8 sta_addr[ETH_ALEN]; /* old_ap_addr is only valid if assocstatus == 2 */ @@ -768,7 +768,7 @@ union hfa384x_infodata { struct hfa384x_ChInfoResult chinforesult; struct hfa384x_HScanResult hscanresult; struct hfa384x_LinkStatus linkstatus; - struct hfa384x_AssocStatus assocstatus; + struct hfa384x_assoc_status assocstatus; struct hfa384x_AuthRequest authreq; struct hfa384x_PSUserCount psusercnt; struct hfa384x_KeyIDChanged keyidchanged; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 0d2bc69a5b47..b39ef74f2719 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1474,7 +1474,7 @@ static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; - struct hfa384x_AssocStatus rec; + struct hfa384x_assoc_status rec; int i; memcpy(&rec, &inf->info.assocstatus, sizeof(rec)); -- cgit v1.2.3 From 4c976b16551d516f26683faaeba66dc70f38f495 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:49:02 -0300 Subject: staging: wlan-ng: renames hfa384x_authenticateStation_data to avoid camelcase Renames the camelcased struct hfa384x_authenticateStation_data to hfa384x_authenticate_station_data in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 2 +- drivers/staging/wlan-ng/prism2sta.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index adbac69b952c..19d1c0618f07 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -421,7 +421,7 @@ struct hfa384x_join_request_data { } __packed; /*-- Configuration Record: authenticateStation (data portion only) --*/ -struct hfa384x_authenticateStation_data { +struct hfa384x_authenticate_station_data { u8 address[ETH_ALEN]; u16 status; u16 algorithm; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index b39ef74f2719..a838f9a382b0 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1550,7 +1550,7 @@ static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, struct hfa384x_inf_frame *inf) { struct hfa384x *hw = wlandev->priv; - struct hfa384x_authenticateStation_data rec; + struct hfa384x_authenticate_station_data rec; int i, added, result, cnt; u8 *addr; -- cgit v1.2.3 From 1680202c751ab37a20b55ad54dc9a2e40903ee36 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:49:18 -0300 Subject: staging: wlan-ng: renames CQ_currBSS to avoid camelcase Renames the camelcased variable CQ_currBSS to cq_curr_bss in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 2 +- drivers/staging/wlan-ng/prism2sta.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 19d1c0618f07..6acdbcecbfd6 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -455,7 +455,7 @@ struct hfa384x_downloadbuffer { /*-- Information Record: commsquality --*/ struct hfa384x_commsquality { - u16 CQ_currBSS; + u16 cq_curr_bss; u16 ASL_currBSS; u16 ANL_currFC; } __packed; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index a838f9a382b0..bcf213330f6a 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -372,7 +372,7 @@ static int prism2sta_mlmerequest(struct wlandevice *wlandev, qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok; - qualmsg->link.data = le16_to_cpu(hw->qual.CQ_currBSS); + qualmsg->link.data = le16_to_cpu(hw->qual.cq_curr_bss); qualmsg->level.data = le16_to_cpu(hw->qual.ASL_currBSS); qualmsg->noise.data = le16_to_cpu(hw->qual.ANL_currFC); qualmsg->txrate.data = hw->txrate; @@ -1947,7 +1947,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) } pr_debug("commsqual %d %d %d\n", - le16_to_cpu(hw->qual.CQ_currBSS), + le16_to_cpu(hw->qual.cq_curr_bss), le16_to_cpu(hw->qual.ASL_currBSS), le16_to_cpu(hw->qual.ANL_currFC)); } -- cgit v1.2.3 From 0e771659c67f5ee6b969a6515995d61d453b57ff Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:49:32 -0300 Subject: staging: wlan-ng: renames ASL_currBSS to avoid camelcase Renames the camelcased variable ASL_currBSS to asl_curr_bss in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 2 +- drivers/staging/wlan-ng/prism2sta.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 6acdbcecbfd6..e00ebf3308e4 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -456,7 +456,7 @@ struct hfa384x_downloadbuffer { /*-- Information Record: commsquality --*/ struct hfa384x_commsquality { u16 cq_curr_bss; - u16 ASL_currBSS; + u16 asl_curr_bss; u16 ANL_currFC; } __packed; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index bcf213330f6a..e20517db8038 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -373,7 +373,8 @@ static int prism2sta_mlmerequest(struct wlandevice *wlandev, P80211ENUM_msgitem_status_data_ok; qualmsg->link.data = le16_to_cpu(hw->qual.cq_curr_bss); - qualmsg->level.data = le16_to_cpu(hw->qual.ASL_currBSS); + qualmsg->level.data = + le16_to_cpu(hw->qual.asl_curr_bss); qualmsg->noise.data = le16_to_cpu(hw->qual.ANL_currFC); qualmsg->txrate.data = hw->txrate; @@ -1948,7 +1949,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) pr_debug("commsqual %d %d %d\n", le16_to_cpu(hw->qual.cq_curr_bss), - le16_to_cpu(hw->qual.ASL_currBSS), + le16_to_cpu(hw->qual.asl_curr_bss), le16_to_cpu(hw->qual.ANL_currFC)); } -- cgit v1.2.3 From 6b6f94912bb03f2b79853ce6ba2067b75f52784f Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 06:49:47 -0300 Subject: staging: wlan-ng: renames ANL_currFC to avoid camelcase Renames the camelcased variable ANL_currFC to anl_curr_fc in order to fix a checkpatch warning. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 2 +- drivers/staging/wlan-ng/prism2sta.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index e00ebf3308e4..612f928c1c77 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -457,7 +457,7 @@ struct hfa384x_downloadbuffer { struct hfa384x_commsquality { u16 cq_curr_bss; u16 asl_curr_bss; - u16 ANL_currFC; + u16 anl_curr_fc; } __packed; /*-- Information Record: dmbcommsquality --*/ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index e20517db8038..b10c93ed8f92 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -375,7 +375,7 @@ static int prism2sta_mlmerequest(struct wlandevice *wlandev, qualmsg->link.data = le16_to_cpu(hw->qual.cq_curr_bss); qualmsg->level.data = le16_to_cpu(hw->qual.asl_curr_bss); - qualmsg->noise.data = le16_to_cpu(hw->qual.ANL_currFC); + qualmsg->noise.data = le16_to_cpu(hw->qual.anl_curr_fc); qualmsg->txrate.data = hw->txrate; break; @@ -1950,7 +1950,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) pr_debug("commsqual %d %d %d\n", le16_to_cpu(hw->qual.cq_curr_bss), le16_to_cpu(hw->qual.asl_curr_bss), - le16_to_cpu(hw->qual.ANL_currFC)); + le16_to_cpu(hw->qual.anl_curr_fc)); } /* Get the signal rate */ -- cgit v1.2.3 From 10426351723a1da5dab8de8d863d02734b681e48 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Fri, 7 Oct 2016 01:20:23 -0300 Subject: staging: wilc1000: Format block comment. Fix checkpatch warning: WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_spi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index f08cf6d9e1af..572e57d08a11 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -858,7 +858,8 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) /* the SPI to it's initial value. */ if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { /* Read failed. Try with CRC off. This might happen when module - * is removed but chip isn't reset*/ + * is removed but chip isn't reset + */ g_spi.crc_off = 1; dev_err(&spi->dev, "Failed internal read protocol with CRC on, retrying with CRC off...\n"); if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { -- cgit v1.2.3 From 855d198826592e30340487a5a8fc599d8cbcee49 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Fri, 7 Oct 2016 01:20:59 -0300 Subject: staging: wilc1000: Add blank line after variable declarations. Fix checkpath warning: WARNING: Missing a blank line after declarations. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 60d8b055bb2f..fca96d3383e1 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1193,6 +1193,7 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev, u32 i = 0; u32 associatedsta = ~0; u32 inactive_time = 0; + priv = wiphy_priv(wiphy); vif = netdev_priv(dev); -- cgit v1.2.3 From 67f13aa7ea936f5479b5b507eb3d866db942430c Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Fri, 30 Sep 2016 22:39:52 +0000 Subject: staging: android: ion_test: remove extra line per checkpatch.pl Cleanup extra line found by checkpatch.pl Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/ion_test.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/uapi/ion_test.h b/drivers/staging/android/uapi/ion_test.h index ffef06f63133..480242e02f8d 100644 --- a/drivers/staging/android/uapi/ion_test.h +++ b/drivers/staging/android/uapi/ion_test.h @@ -66,5 +66,4 @@ struct ion_test_rw_data { #define ION_IOC_TEST_KERNEL_MAPPING \ _IOW(ION_IOC_MAGIC, 0xf2, struct ion_test_rw_data) - #endif /* _UAPI_LINUX_ION_H */ -- cgit v1.2.3 From 9ab9d4529a612fde4f196d445b7547dd6d6a64ed Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Sat, 8 Oct 2016 22:40:24 -0300 Subject: staging: sm750fb: Replace printk() with pr_info(). Fix checkpatch warning: WARNING: printk() should include KERN_ facility level New checkpatch warning appears after including KERN_ facility level. Fix checkpatch warning: WARNING: Prefer [subsystem eg: netdev]_info([subsystem]dev, ... then dev_info(dev, ... then pr_info(... to printk(KERN_INFO ... Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_help.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_help.c b/drivers/staging/sm750fb/ddk750_help.c index 9637dd30d037..e72a29c8602e 100644 --- a/drivers/staging/sm750fb/ddk750_help.c +++ b/drivers/staging/sm750fb/ddk750_help.c @@ -11,7 +11,7 @@ void ddk750_set_mmio(void __iomem *addr, unsigned short devId, char revId) devId750 = devId; revId750 = revId; if (revId == 0xfe) - printk("found sm750le\n"); + pr_info("found sm750le\n"); } -- cgit v1.2.3 From 67f9dcb155875864ccaf74625a7c702e6d07ab31 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 4 Oct 2016 23:22:36 +0530 Subject: Staging: rtl8192e: rtl_core: Constify rtllib_qos_parameters structures Declare the structure rtllib_qos_parameters as constant as it is only passed as the second argument to the function memcpy. This argument is constant so the fields of rtllib_qos_parameters structure are never modified and hence it can be declared as const. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct rtllib_qos_parameters i@p = {...}; @ok1@ identifier r1.i; position p; expression e1,e2; @@ memcpy(e1,&i@p,e2) @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct rtllib_qos_parameters i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct rtllib_qos_parameters i; File size before: text data bss dec hex filename 30910 496 201 31607 7b77 drivers/staging/rtl8192e/rtl8192e/rtl_core.o File size after: text data bss dec hex filename 30942 464 201 31607 7b77 drivers/staging/rtl8192e/rtl8192e/rtl_core.o Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 4c30eea45f89..f985d88f8726 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -367,7 +367,7 @@ static void _rtl92e_update_cap(struct net_device *dev, u16 cap) } } -static struct rtllib_qos_parameters def_qos_parameters = { +static const struct rtllib_qos_parameters def_qos_parameters = { {cpu_to_le16(3), cpu_to_le16(3), cpu_to_le16(3), cpu_to_le16(3)}, {cpu_to_le16(7), cpu_to_le16(7), cpu_to_le16(7), cpu_to_le16(7)}, {2, 2, 2, 2}, -- cgit v1.2.3 From 340c0469911cb8394d62399d6fcf6f94e30fe2f4 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 6 Oct 2016 23:32:20 +0530 Subject: Staging: rtl8712: remove unused functions Remove the functions sleep_schedulable, down_scanned_network, up_scanned_network and get_free_xmit_queue as they are not used anywhere in the kernel. Functions detected using coccinelle but changes done by hand. Script: @initialize:python@ @@ def display(name,p): print(name,p[0].file) @r1@ identifier func; type T; position p; @@ static T func@p(...) { ... } @r@ identifier r1.func; @@ func @script:python depends on !r@ func << r1.func; p << r1.p; @@ display(func,p) Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/osdep_service.h | 9 --------- drivers/staging/rtl8712/rtl871x_mlme.h | 18 ------------------ drivers/staging/rtl8712/rtl871x_xmit.h | 6 ------ 3 files changed, 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index c9ea50daffff..b8a170978434 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -63,15 +63,6 @@ static inline u32 end_of_queue_search(struct list_head *head, return (head == plist); } -static inline void sleep_schedulable(int ms) -{ - u32 delta; - - delta = msecs_to_jiffies(ms);/*(ms)*/ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(delta); -} - static inline void flush_signals_thread(void) { if (signal_pending(current)) diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index ddaaab058b2f..53a23234c598 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -162,24 +162,6 @@ static inline void clr_fwstate(struct mlme_priv *pmlmepriv, sint state) spin_unlock_irqrestore(&pmlmepriv->lock, irqL); } -static inline void up_scanned_network(struct mlme_priv *pmlmepriv) -{ - unsigned long irqL; - - spin_lock_irqsave(&pmlmepriv->lock, irqL); - pmlmepriv->num_of_scanned++; - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - -static inline void down_scanned_network(struct mlme_priv *pmlmepriv) -{ - unsigned long irqL; - - spin_lock_irqsave(&pmlmepriv->lock, irqL); - pmlmepriv->num_of_scanned--; - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv, sint val) { diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index d899d0c6d3a6..40927277f498 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -261,12 +261,6 @@ struct xmit_priv { uint free_xmitbuf_cnt; }; -static inline struct __queue *get_free_xmit_queue( - struct xmit_priv *pxmitpriv) -{ - return &(pxmitpriv->free_xmit_queue); -} - int r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf); struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv); -- cgit v1.2.3 From c10364e1f4f6cc7e8c3f2e6a3ecb96da8769f10b Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 17:48:21 -0300 Subject: staging: rtl8188eu: core: removes unecessary parenthesis Removes unecessary parenthesis from rtw_led.c file that were causing checkpatch warnings. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_led.c | 68 ++++++++++++++++---------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_led.c b/drivers/staging/rtl8188eu/core/rtw_led.c index 14461cf34037..849f5f30a19a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_led.c +++ b/drivers/staging/rtl8188eu/core/rtw_led.c @@ -30,7 +30,7 @@ void BlinkTimerCallback(unsigned long data) if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped)) return; - schedule_work(&(pLed->BlinkWorkItem)); + schedule_work(&pLed->BlinkWorkItem); } /* */ @@ -72,10 +72,10 @@ void InitLed871x(struct adapter *padapter, struct LED_871x *pLed) ResetLedStatus(pLed); - setup_timer(&(pLed->BlinkTimer), BlinkTimerCallback, + setup_timer(&pLed->BlinkTimer, BlinkTimerCallback, (unsigned long)pLed); - INIT_WORK(&(pLed->BlinkWorkItem), BlinkWorkItemCallback); + INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback); } @@ -85,8 +85,8 @@ void InitLed871x(struct adapter *padapter, struct LED_871x *pLed) /* */ void DeInitLed871x(struct LED_871x *pLed) { - cancel_work_sync(&(pLed->BlinkWorkItem)); - del_timer_sync(&(pLed->BlinkTimer)); + cancel_work_sync(&pLed->BlinkWorkItem); + del_timer_sync(&pLed->BlinkTimer); ResetLedStatus(pLed); } @@ -99,7 +99,7 @@ void DeInitLed871x(struct LED_871x *pLed) static void SwLedBlink1(struct LED_871x *pLed) { struct adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ @@ -247,9 +247,9 @@ static void SwLedBlink1(struct LED_871x *pLed) /* ALPHA, added by chiyoko, 20090106 */ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAction) { - struct led_priv *ledpriv = &(padapter->ledpriv); - struct LED_871x *pLed = &(ledpriv->SwLed0); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct led_priv *ledpriv = &padapter->ledpriv; + struct LED_871x *pLed = &ledpriv->SwLed0; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; switch (LedAction) { case LED_CTL_POWER_ON: @@ -259,11 +259,11 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } @@ -282,11 +282,11 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedNoLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedLinkBlinkInProgress = true; @@ -306,15 +306,15 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct if (IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedNoLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedScanBlinkInProgress = true; @@ -334,11 +334,11 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedNoLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } pLed->bLedBlinkInProgress = true; @@ -356,19 +356,19 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct case LED_CTL_START_WPS_BOTTON: if (!pLed->bLedWPSBlinkInProgress) { if (pLed->bLedNoLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } pLed->bLedWPSBlinkInProgress = true; @@ -383,23 +383,23 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct break; case LED_CTL_STOP_WPS: if (pLed->bLedNoLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } if (pLed->bLedWPSBlinkInProgress) - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); else pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS_STOP; @@ -415,7 +415,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct break; case LED_CTL_STOP_WPS_FAIL: if (pLed->bLedWPSBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } pLed->bLedNoLinkBlinkInProgress = true; @@ -431,23 +431,23 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct pLed->CurrLedState = RTW_LED_OFF; pLed->BlinkingLedState = RTW_LED_OFF; if (pLed->bLedNoLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedWPSBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { - del_timer_sync(&(pLed->BlinkTimer)); + del_timer_sync(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } SwLedOff(padapter, pLed); @@ -475,7 +475,7 @@ void BlinkHandler(struct LED_871x *pLed) void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction) { - struct led_priv *ledpriv = &(padapter->ledpriv); + struct led_priv *ledpriv = &padapter->ledpriv; if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped) || (!padapter->hw_init_completed)) -- cgit v1.2.3 From dd2aa2501c92174bbac2e5a41460b0c00471c9d3 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sat, 8 Oct 2016 17:49:28 -0300 Subject: staging: rtl8188eu: core: fixes tabstop alignment Fixes a tabstop alignment checkpatch issue by removing extra blank spaces. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_led.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_led.c b/drivers/staging/rtl8188eu/core/rtw_led.c index 849f5f30a19a..b613d43e3f74 100644 --- a/drivers/staging/rtl8188eu/core/rtw_led.c +++ b/drivers/staging/rtl8188eu/core/rtw_led.c @@ -326,7 +326,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct pLed->BlinkingLedState = RTW_LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } + } break; case LED_CTL_TX: case LED_CTL_RX: @@ -354,7 +354,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct break; case LED_CTL_START_WPS: /* wait until xinpin finish */ case LED_CTL_START_WPS_BOTTON: - if (!pLed->bLedWPSBlinkInProgress) { + if (!pLed->bLedWPSBlinkInProgress) { if (pLed->bLedNoLinkBlinkInProgress) { del_timer_sync(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; @@ -379,7 +379,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct pLed->BlinkingLedState = RTW_LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } + } break; case LED_CTL_STOP_WPS: if (pLed->bLedNoLinkBlinkInProgress) { -- cgit v1.2.3 From 6f88006826734f661d146098424f467923300552 Mon Sep 17 00:00:00 2001 From: Philipp Hoefflin Date: Mon, 3 Oct 2016 02:57:23 +0200 Subject: staging: ks7010: fix "prohibited space" errors reported by checkpatch Fix all occurences of the following checkpatch errors in ks_hostif.c: - ERROR: space prohibited after that '&' (ctx:WxW) - ERROR: space prohibited after that open parenthesis '(' - ERROR: space prohibited before that close parenthesis ')' Signed-off-by: Philipp Hoefflin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index c57ca581550a..c26d18b108ff 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -23,11 +23,11 @@ /* macro */ #define inc_smeqhead(priv) \ - ( priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE ) + (priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE) #define inc_smeqtail(priv) \ - ( priv->sme_i.qtail = (priv->sme_i.qtail + 1) % SME_EVENT_BUFF_SIZE ) + (priv->sme_i.qtail = (priv->sme_i.qtail + 1) % SME_EVENT_BUFF_SIZE) #define cnt_smeqbody(priv) \ - (((priv->sme_i.qtail + SME_EVENT_BUFF_SIZE) - (priv->sme_i.qhead)) % SME_EVENT_BUFF_SIZE ) + (((priv->sme_i.qtail + SME_EVENT_BUFF_SIZE) - (priv->sme_i.qhead)) % SME_EVENT_BUFF_SIZE) #define KS_WLAN_MEM_FLAG (GFP_ATOMIC) @@ -1244,7 +1244,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) pp->auth_type = cpu_to_le16((uint16_t) TYPE_AUTH); /* no encryption */ } else { if (priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP) { - MichaelMICFunction(&michel_mic, (uint8_t *) priv->wpa.key[0].tx_mic_key, (uint8_t *) & pp->data[0], (int)packet_len, (uint8_t) 0, /* priority */ + MichaelMICFunction(&michel_mic, (uint8_t *) priv->wpa.key[0].tx_mic_key, (uint8_t *) &pp->data[0], (int)packet_len, (uint8_t) 0, /* priority */ (uint8_t *) michel_mic. Result); memcpy(p, michel_mic.Result, 8); -- cgit v1.2.3 From ec9d6dcefc767f6ea79ab7d676be8a88e8a94ee4 Mon Sep 17 00:00:00 2001 From: Philipp Hoefflin Date: Mon, 3 Oct 2016 02:57:24 +0200 Subject: staging: ks7010: use tabs for indentation Fix all occurences of checkpatch "ERROR: code indent should use tabs where possible" errors in ks_hostif.c. Signed-off-by: Philipp Hoefflin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index c26d18b108ff..309c7dc91584 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -23,11 +23,11 @@ /* macro */ #define inc_smeqhead(priv) \ - (priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE) + (priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE) #define inc_smeqtail(priv) \ - (priv->sme_i.qtail = (priv->sme_i.qtail + 1) % SME_EVENT_BUFF_SIZE) + (priv->sme_i.qtail = (priv->sme_i.qtail + 1) % SME_EVENT_BUFF_SIZE) #define cnt_smeqbody(priv) \ - (((priv->sme_i.qtail + SME_EVENT_BUFF_SIZE) - (priv->sme_i.qhead)) % SME_EVENT_BUFF_SIZE) + (((priv->sme_i.qtail + SME_EVENT_BUFF_SIZE) - (priv->sme_i.qhead)) % SME_EVENT_BUFF_SIZE) #define KS_WLAN_MEM_FLAG (GFP_ATOMIC) -- cgit v1.2.3 From 0157403e8a31e8895974ecefa75e8915d01a4535 Mon Sep 17 00:00:00 2001 From: Philipp Hoefflin Date: Mon, 3 Oct 2016 02:57:25 +0200 Subject: staging: ks7010: reformat makro ps_confirm_wait_inc() Reformat the makro ps_confirm_wait_inc() to fix several checkpatch errors and warnings: - ERROR: space required before the open brace '{' - ERROR: space required before the open parenthesis '(' - ERROR: code indent should use tabs where possible - ERROR: space required after that close brace '}' - ERROR: space required before the open parenthesis '(' - WARNING: line over 80 characters - WARNING: please, no spaces at the start of a line Signed-off-by: Philipp Hoefflin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 309c7dc91584..e81e905aab64 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1294,10 +1294,11 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) return result; } -#define ps_confirm_wait_inc(priv) do{if(atomic_read(&priv->psstatus.status) > PS_ACTIVE_SET){ \ - atomic_inc(&priv->psstatus.confirm_wait); \ - /* atomic_set(&priv->psstatus.status, PS_CONF_WAIT);*/ \ - } }while(0) +#define ps_confirm_wait_inc(priv) do { \ + if (atomic_read(&priv->psstatus.status) > PS_ACTIVE_SET) { \ + atomic_inc(&priv->psstatus.confirm_wait); \ + /* atomic_set(&priv->psstatus.status, PS_CONF_WAIT);*/ \ + } } while (0) static void hostif_mib_get_request(struct ks_wlan_private *priv, -- cgit v1.2.3 From 3f64b35e3352f6cc70d6fc59bcd32e8e610d8a06 Mon Sep 17 00:00:00 2001 From: Philipp Hoefflin Date: Mon, 3 Oct 2016 02:57:26 +0200 Subject: staging: ks7010: fix checkpatch "space after #ifdef" error Fix checkpatch "ERROR: exactly one space required after that #ifdef" error in ks_hostif.c. Signed-off-by: Philipp Hoefflin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index e81e905aab64..aff3eae239ab 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -766,7 +766,7 @@ void hostif_sleep_confirm(struct ks_wlan_private *priv) static void hostif_start_confirm(struct ks_wlan_private *priv) { -#ifdef WPS +#ifdef WPS union iwreq_data wrqu; wrqu.data.length = 0; wrqu.data.flags = 0; -- cgit v1.2.3 From 697f9f7f8441dd4595a1653c1b2b4c8177299bf8 Mon Sep 17 00:00:00 2001 From: Muraru Mihaela Date: Mon, 3 Oct 2016 22:28:52 +0300 Subject: Staging: ks7010: add blank line after declaration This patch fixes a coding style WARNING: Missing a blank line after declaration, found by checkpatch.pl. By adding a blank line after declaration of a variable. Signed-off-by: Muraru Mihaela Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks7010_sdio.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 81c46f4d0935..33f3351ae271 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -294,6 +294,7 @@ static int write_to_device(struct ks_wlan_private *priv, unsigned char *buffer, int retval; unsigned char rw_data; struct hostif_hdr *hdr; + hdr = (struct hostif_hdr *)buffer; DPRINTK(4, "size=%d\n", hdr->size); @@ -358,6 +359,7 @@ int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size, { int result = 0; struct hostif_hdr *hdr; + hdr = (struct hostif_hdr *)p; if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) { @@ -1117,6 +1119,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) int ret; struct ks_sdio_card *card; struct ks_wlan_private *priv; + DPRINTK(1, "ks7010_sdio_remove()\n"); card = sdio_get_drvdata(func); @@ -1142,6 +1145,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) /* send stop request to MAC */ { struct hostif_stop_request_t *pp; + pp = kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); -- cgit v1.2.3 From 6b750fac60896949e7e41a667cc63ad777692b09 Mon Sep 17 00:00:00 2001 From: Muraru Mihaela Date: Tue, 4 Oct 2016 23:08:25 +0300 Subject: Staging: ks7010: fix brace coding style issue This is a patch to the ks_wlan_net.c file that fixes up a brace coding style warning found by checkpatch.pl tool, by deleting the unnecessary braces for single statement blocks. Signed-off-by: Muraru Mihaela Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan_net.c | 155 +++++++++++++++++------------------ 1 file changed, 73 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index b2b4fa4c3834..77a77a96ec22 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -88,9 +88,9 @@ int ks_wlan_update_phy_information(struct ks_wlan_private *priv) DPRINTK(4, "in_interrupt = %ld\n", in_interrupt()); - if (priv->dev_state < DEVICE_STATE_READY) { + if (priv->dev_state < DEVICE_STATE_READY) return -1; /* not finished initialize */ - } + if (atomic_read(&update_phyinfo)) return 1; @@ -182,19 +182,18 @@ static int ks_wlan_get_name(struct net_device *dev, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ - if (priv->dev_state < DEVICE_STATE_READY) { + if (priv->dev_state < DEVICE_STATE_READY) strcpy(cwrq, "NOT READY!"); - } else if (priv->reg.phy_type == D_11B_ONLY_MODE) { + else if (priv->reg.phy_type == D_11B_ONLY_MODE) strcpy(cwrq, "IEEE 802.11b"); - } else if (priv->reg.phy_type == D_11G_ONLY_MODE) { + else if (priv->reg.phy_type == D_11G_ONLY_MODE) strcpy(cwrq, "IEEE 802.11g"); - } else { + else strcpy(cwrq, "IEEE 802.11b/g"); - } return 0; } @@ -209,9 +208,8 @@ static int ks_wlan_set_freq(struct net_device *dev, (struct ks_wlan_private *)netdev_priv(dev); int rc = -EINPROGRESS; /* Call commit handler */ - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } /* for SLEEP MODE */ /* If setting by frequency, convert to a channel */ @@ -257,13 +255,13 @@ static int ks_wlan_get_freq(struct net_device *dev, (struct ks_wlan_private *)netdev_priv(dev); int f; - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ - if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { + if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) f = (int)priv->current_ap.channel; - } else + else f = (int)priv->reg.channel; fwrq->m = frequency_list[f - 1] * 100000; fwrq->e = 1; @@ -283,9 +281,9 @@ static int ks_wlan_set_essid(struct net_device *dev, DPRINTK(2, " %d\n", dwrq->flags); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ /* Check if we asked for `any' */ @@ -301,14 +299,14 @@ static int ks_wlan_set_essid(struct net_device *dev, len--; /* Check the size of the string */ - if (len > IW_ESSID_MAX_SIZE) { + if (len > IW_ESSID_MAX_SIZE) return -EINVAL; - } + #else /* Check the size of the string */ - if (dwrq->length > IW_ESSID_MAX_SIZE + 1) { + if (dwrq->length > IW_ESSID_MAX_SIZE + 1) return -E2BIG; - } + #endif /* Set the SSID */ @@ -340,9 +338,9 @@ static int ks_wlan_get_essid(struct net_device *dev, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ /* Note : if dwrq->flags != 0, we should @@ -385,17 +383,17 @@ static int ks_wlan_set_wap(struct net_device *dev, struct iw_request_info *info, DPRINTK(2, "\n"); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ if (priv->reg.operation_mode == MODE_ADHOC || priv->reg.operation_mode == MODE_INFRASTRUCTURE) { memcpy(priv->reg.bssid, (u8 *) & ap_addr->sa_data, ETH_ALEN); - if (is_valid_ether_addr((u8 *) priv->reg.bssid)) { + if (is_valid_ether_addr((u8 *) priv->reg.bssid)) priv->need_commit |= SME_MODE_SET; - } + } else { eth_zero_addr(priv->reg.bssid); return -EOPNOTSUPP; @@ -421,15 +419,14 @@ static int ks_wlan_get_wap(struct net_device *dev, struct iw_request_info *info, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ - if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { + if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) memcpy(awrq->sa_data, &(priv->current_ap.bssid[0]), ETH_ALEN); - } else { + else eth_zero_addr(awrq->sa_data); - } awrq->sa_family = ARPHRD_ETHER; @@ -445,15 +442,14 @@ static int ks_wlan_set_nick(struct net_device *dev, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } /* for SLEEP MODE */ /* Check the size of the string */ - if (dwrq->length > 16 + 1) { + if (dwrq->length > 16 + 1) return -E2BIG; - } + memset(priv->nick, 0, sizeof(priv->nick)); memcpy(priv->nick, extra, dwrq->length); @@ -469,9 +465,9 @@ static int ks_wlan_get_nick(struct net_device *dev, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ strncpy(extra, priv->nick, 16); extra[16] = '\0'; @@ -490,9 +486,9 @@ static int ks_wlan_set_rate(struct net_device *dev, (struct ks_wlan_private *)netdev_priv(dev); int i = 0; - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ if (priv->reg.phy_type == D_11B_ONLY_MODE) { if (vwrq->fixed == 1) { @@ -727,13 +723,13 @@ static int ks_wlan_get_rate(struct net_device *dev, DPRINTK(2, "in_interrupt = %ld update_phyinfo = %d\n", in_interrupt(), atomic_read(&update_phyinfo)); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ - if (!atomic_read(&update_phyinfo)) { + if (!atomic_read(&update_phyinfo)) ks_wlan_update_phy_information(priv); - } + vwrq->value = ((priv->current_rate) & RATE_MASK) * 500000; if (priv->reg.tx_rate == TX_RATE_FIXED) vwrq->fixed = 1; @@ -752,15 +748,15 @@ static int ks_wlan_set_rts(struct net_device *dev, struct iw_request_info *info, (struct ks_wlan_private *)netdev_priv(dev); int rthr = vwrq->value; - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ if (vwrq->disabled) rthr = 2347; - if ((rthr < 0) || (rthr > 2347)) { + if ((rthr < 0) || (rthr > 2347)) return -EINVAL; - } + priv->reg.rts = rthr; priv->need_commit |= SME_RTS; @@ -775,9 +771,9 @@ static int ks_wlan_get_rts(struct net_device *dev, struct iw_request_info *info, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ vwrq->value = priv->reg.rts; vwrq->disabled = (vwrq->value >= 2347); @@ -796,15 +792,15 @@ static int ks_wlan_set_frag(struct net_device *dev, (struct ks_wlan_private *)netdev_priv(dev); int fthr = vwrq->value; - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ if (vwrq->disabled) fthr = 2346; - if ((fthr < 256) || (fthr > 2346)) { + if ((fthr < 256) || (fthr > 2346)) return -EINVAL; - } + fthr &= ~0x1; /* Get an even value - is it really needed ??? */ priv->reg.fragment = fthr; priv->need_commit |= SME_FRAG; @@ -821,9 +817,9 @@ static int ks_wlan_get_frag(struct net_device *dev, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ vwrq->value = priv->reg.fragment; vwrq->disabled = (vwrq->value >= 2346); @@ -843,9 +839,9 @@ static int ks_wlan_set_mode(struct net_device *dev, DPRINTK(2, "mode=%d\n", *uwrq); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ switch (*uwrq) { case IW_MODE_ADHOC: @@ -877,9 +873,8 @@ static int ks_wlan_get_mode(struct net_device *dev, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } /* for SLEEP MODE */ /* If not managed, assume it's ad-hoc */ @@ -913,9 +908,8 @@ static int ks_wlan_set_encode(struct net_device *dev, DPRINTK(2, "flags=%04X\n", dwrq->flags); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } /* for SLEEP MODE */ /* index check */ @@ -959,9 +953,9 @@ static int ks_wlan_set_encode(struct net_device *dev, } /* Send the key to the card */ priv->reg.wep_key[index].size = key.len; - for (i = 0; i < (priv->reg.wep_key[index].size); i++) { + for (i = 0; i < (priv->reg.wep_key[index].size); i++) priv->reg.wep_key[index].val[i] = key.key[i]; - } + priv->need_commit |= (SME_WEP_VAL1 << index); priv->reg.wep_index = index; priv->need_commit |= SME_WEP_INDEX; @@ -973,9 +967,9 @@ static int ks_wlan_set_encode(struct net_device *dev, priv->reg.wep_key[2].size = 0; priv->reg.wep_key[3].size = 0; priv->reg.privacy_invoked = 0x00; - if (priv->reg.authenticate_type == AUTH_TYPE_SHARED_KEY) { + if (priv->reg.authenticate_type == AUTH_TYPE_SHARED_KEY) priv->need_commit |= SME_MODE_SET; - } + priv->reg.authenticate_type = AUTH_TYPE_OPEN_SYSTEM; wep_on_off = WEP_OFF; priv->need_commit |= SME_WEP_FLAG; @@ -997,14 +991,14 @@ static int ks_wlan_set_encode(struct net_device *dev, priv->need_commit |= SME_WEP_FLAG; if (dwrq->flags & IW_ENCODE_OPEN) { - if (priv->reg.authenticate_type == AUTH_TYPE_SHARED_KEY) { + if (priv->reg.authenticate_type == AUTH_TYPE_SHARED_KEY) priv->need_commit |= SME_MODE_SET; - } + priv->reg.authenticate_type = AUTH_TYPE_OPEN_SYSTEM; } else if (dwrq->flags & IW_ENCODE_RESTRICTED) { - if (priv->reg.authenticate_type == AUTH_TYPE_OPEN_SYSTEM) { + if (priv->reg.authenticate_type == AUTH_TYPE_OPEN_SYSTEM) priv->need_commit |= SME_MODE_SET; - } + priv->reg.authenticate_type = AUTH_TYPE_SHARED_KEY; } // return -EINPROGRESS; /* Call commit handler */ @@ -1026,9 +1020,9 @@ static int ks_wlan_get_encode(struct net_device *dev, char zeros[16]; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ dwrq->flags = IW_ENCODE_DISABLED; @@ -1056,9 +1050,8 @@ static int ks_wlan_get_encode(struct net_device *dev, /* Copy the key to the user buffer */ if ((index >= 0) && (index < 4)) dwrq->length = priv->reg.wep_key[index].size; - if (dwrq->length > 16) { + if (dwrq->length > 16) dwrq->length = 0; - } #if 1 /* IW_ENCODE_NOKEY; */ if (dwrq->length) { if ((index >= 0) && (index < 4)) @@ -1086,9 +1079,8 @@ static int ks_wlan_get_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } /* for SLEEP MODE */ /* Not Support */ @@ -1113,9 +1105,8 @@ static int ks_wlan_get_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } /* for SLEEP MODE */ /* Not Support */ @@ -1139,9 +1130,9 @@ static int ks_wlan_get_range(struct net_device *dev, DPRINTK(2, "\n"); - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ dwrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(*range)); @@ -1267,9 +1258,9 @@ static int ks_wlan_set_power(struct net_device *dev, (struct ks_wlan_private *)netdev_priv(dev); short enabled; - if (priv->sleep_mode == SLP_SLEEP) { + if (priv->sleep_mode == SLP_SLEEP) return -EPERM; - } + /* for SLEEP MODE */ enabled = vwrq->disabled ? 0 : 1; if (enabled == 0) { /* 0 */ -- cgit v1.2.3 From 0af454793a247b11b19506fa504ccde63d8372ac Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Thu, 6 Oct 2016 22:50:19 +0200 Subject: staging: ks7010: Remove unnecessary cast sdio functions takes unsigned int as address. No need to cast. Signed-off-by: Pontus Fuchs Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks7010_sdio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 33f3351ae271..1f97161e4945 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -76,10 +76,9 @@ static int ks7010_sdio_write(struct ks_wlan_private *priv, unsigned int address, card = priv->ks_wlan_hw.sdio_card; if (length == 1) /* CMD52 */ - sdio_writeb(card->func, *buffer, (unsigned int)address, &rc); + sdio_writeb(card->func, *buffer, address, &rc); else /* CMD53 */ - rc = sdio_memcpy_toio(card->func, (unsigned int)address, buffer, - length); + rc = sdio_memcpy_toio(card->func, address, buffer, length); if (rc != 0) DPRINTK(1, "sdio error=%d size=%d\n", rc, length); -- cgit v1.2.3 From 7a98abccd28e264a60c55df5b8cf59337ec338ba Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Thu, 6 Oct 2016 22:50:20 +0200 Subject: staging: ks7010: Use printk format specifier for MAC addresses Convert to %pM instead of custom code. Signed-off-by: Pontus Fuchs Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 36 +++++++----------------------------- drivers/staging/ks7010/ks_wlan_net.c | 9 ++------- 2 files changed, 9 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index aff3eae239ab..25c32ab8211d 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -187,13 +187,7 @@ int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info_t *ap_info) memcpy(wrqu.ap_addr.sa_data, &(priv->current_ap.bssid[0]), ETH_ALEN); DPRINTK(3, - "IWEVENT: connect bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", - (unsigned char)wrqu.ap_addr.sa_data[0], - (unsigned char)wrqu.ap_addr.sa_data[1], - (unsigned char)wrqu.ap_addr.sa_data[2], - (unsigned char)wrqu.ap_addr.sa_data[3], - (unsigned char)wrqu.ap_addr.sa_data[4], - (unsigned char)wrqu.ap_addr.sa_data[5]); + "IWEVENT: connect bssid=%pM\n", wrqu.ap_addr.sa_data); wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL); } DPRINTK(4, "\n Link AP\n"); @@ -420,16 +414,11 @@ void hostif_data_indication(struct ks_wlan_private *priv) /* needed parameters: count, keyid, key type, TSC */ sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=" - "%02x:%02x:%02x:%02x:%02x:%02x)", + "%pM)", auth_type - 1, eth_hdr-> h_dest[0] & 0x01 ? "broad" : - "uni", eth_hdr->h_source[0], - eth_hdr->h_source[1], - eth_hdr->h_source[2], - eth_hdr->h_source[3], - eth_hdr->h_source[4], - eth_hdr->h_source[5]); + "uni", eth_hdr->h_source); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = strlen(buf); DPRINTK(4, @@ -560,10 +549,7 @@ void hostif_mib_get_confirm(struct ks_wlan_private *priv) dev->dev_addr[5] = priv->eth_addr[5]; dev->dev_addr[6] = 0x00; dev->dev_addr[7] = 0x00; - printk(KERN_INFO - "ks_wlan: MAC ADDRESS = %02x:%02x:%02x:%02x:%02x:%02x\n", - priv->eth_addr[0], priv->eth_addr[1], priv->eth_addr[2], - priv->eth_addr[3], priv->eth_addr[4], priv->eth_addr[5]); + printk(KERN_INFO "ks_wlan: MAC ADDRESS = %pM\n", priv->eth_addr); break; case DOT11_PRODUCT_VERSION: /* firmware version */ @@ -1184,9 +1170,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) eth = (struct ethhdr *)packet->data; if (memcmp(&priv->eth_addr[0], eth->h_source, ETH_ALEN)) { DPRINTK(1, "invalid mac address !!\n"); - DPRINTK(1, "ethernet->h_source=%02X:%02X:%02X:%02X:%02X:%02X\n", - eth->h_source[0], eth->h_source[1], eth->h_source[2], - eth->h_source[3], eth->h_source[4], eth->h_source[5]); + DPRINTK(1, "ethernet->h_source=%pM\n", eth->h_source); dev_kfree_skb(packet); kfree(pp); return -3; @@ -2217,10 +2201,7 @@ void hostif_sme_mode_setup(struct ks_wlan_private *priv) } else { hostif_infrastructure_set2_request(priv); DPRINTK(2, - "Infra bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", - priv->reg.bssid[0], priv->reg.bssid[1], - priv->reg.bssid[2], priv->reg.bssid[3], - priv->reg.bssid[4], priv->reg.bssid[5]); + "Infra bssid = %pM\n", priv->reg.bssid); } break; case MODE_ADHOC: @@ -2230,10 +2211,7 @@ void hostif_sme_mode_setup(struct ks_wlan_private *priv) } else { hostif_adhoc_set2_request(priv); DPRINTK(2, - "Adhoc bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", - priv->reg.bssid[0], priv->reg.bssid[1], - priv->reg.bssid[2], priv->reg.bssid[3], - priv->reg.bssid[4], priv->reg.bssid[5]); + "Adhoc bssid = %pM\n", priv->reg.bssid); } break; default: diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 77a77a96ec22..b0432fc77c62 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -399,9 +399,7 @@ static int ks_wlan_set_wap(struct net_device *dev, struct iw_request_info *info, return -EOPNOTSUPP; } - DPRINTK(2, "bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", - priv->reg.bssid[0], priv->reg.bssid[1], priv->reg.bssid[2], - priv->reg.bssid[3], priv->reg.bssid[4], priv->reg.bssid[5]); + DPRINTK(2, "bssid = %pM\n", priv->reg.bssid); /* Write it to the card */ if (priv->need_commit) { @@ -3321,10 +3319,7 @@ int ks_wlan_set_mac_address(struct net_device *dev, void *addr) priv->mac_address_valid = 0; hostif_sme_enqueue(priv, SME_MACADDRESS_SET_REQUEST); - netdev_info(dev, - "ks_wlan: MAC ADDRESS = %02x:%02x:%02x:%02x:%02x:%02x\n", - priv->eth_addr[0], priv->eth_addr[1], priv->eth_addr[2], - priv->eth_addr[3], priv->eth_addr[4], priv->eth_addr[5]); + netdev_info(dev, "ks_wlan: MAC ADDRESS = %pM\n", priv->eth_addr); return 0; } -- cgit v1.2.3 From e33c759a1e7c3f73e0059063e9090bcd2df4a66e Mon Sep 17 00:00:00 2001 From: Ebru Akagunduz Date: Fri, 7 Oct 2016 14:17:49 +0300 Subject: staging: ks7010: remove unnecessary else statement This patch removes else statement which is not usefull after a return. Issue found by checkpatch.pl. Signed-off-by: Ebru Akagunduz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index b0432fc77c62..14bb008754d7 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -3412,8 +3412,8 @@ int ks_wlan_open(struct net_device *dev) if (!priv->mac_address_valid) { netdev_err(dev, "ks_wlan : %s Not READY !!\n", dev->name); return -EBUSY; - } else - netif_start_queue(dev); + } + netif_start_queue(dev); return 0; } -- cgit v1.2.3 From 31a86a533a1134e71f3eaae5f027ecf4934f5dca Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Sat, 8 Oct 2016 01:58:11 +0300 Subject: Staging: ks7010: __packed instedad of __attribute__((packed)) Fix a issue found by checkpatch.pl tool: "WARNING: __packed is preferred over __attribute__((packed))". Replace __attribute__((packed)) with __packed. Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 25c32ab8211d..07954ee78d7c 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1927,12 +1927,12 @@ void hostif_sme_set_wep(struct ks_wlan_private *priv, int type) struct wpa_suite_t { unsigned short size; unsigned char suite[4][CIPHER_ID_LEN]; -} __attribute__ ((packed)); +} __packed; struct rsn_mode_t { uint32_t rsn_mode; uint16_t rsn_capability; -} __attribute__ ((packed)); +} __packed; static void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type) @@ -2406,8 +2406,8 @@ void hostif_sme_set_pmksa(struct ks_wlan_private *priv) struct { uint8_t bssid[ETH_ALEN]; uint8_t pmkid[IW_PMKID_LEN]; - } __attribute__ ((packed)) list[PMK_LIST_MAX]; - } __attribute__ ((packed)) pmkcache; + } __packed list[PMK_LIST_MAX]; + } __packed pmkcache; struct pmk_t *pmk; struct list_head *ptr; int i; -- cgit v1.2.3 From c44893aafbd06504d21c64bc7de3621f5cb7c728 Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Sat, 8 Oct 2016 10:22:17 +0300 Subject: Staging: ks7010: Delete unnecessary return statement This is a patch to ks_hostif.c file that fixes up a checkpatch.pl WARNING: void function return statements are not generally useful. The 'return' statement is not useful here, because it is not necessary to be forced the exit of the function. Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 07954ee78d7c..5714cf758831 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1921,7 +1921,6 @@ void hostif_sme_set_wep(struct ks_wlan_private *priv, int type) break; } - return; } struct wpa_suite_t { @@ -2110,7 +2109,6 @@ void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type) break; } - return; } static @@ -2218,7 +2216,6 @@ void hostif_sme_mode_setup(struct ks_wlan_private *priv) break; } - return; } static @@ -2319,7 +2316,6 @@ void hostif_sme_powermgt_set(struct ks_wlan_private *priv) } hostif_power_mngmt_request(priv, mode, wake_up, receiveDTIMs); - return; } static @@ -2337,7 +2333,6 @@ void hostif_sme_sleep_set(struct ks_wlan_private *priv) break; } - return; } static @@ -2395,7 +2390,6 @@ void hostif_sme_set_key(struct ks_wlan_private *priv, int type) &priv->wpa.key[2].rx_seq[0]); break; } - return; } static @@ -2631,7 +2625,6 @@ void hostif_sme_task(unsigned long dev) tasklet_schedule(&priv->sme_task); } } - return; } /* send to Station Management Entity module */ @@ -2715,5 +2708,4 @@ int hostif_init(struct ks_wlan_private *priv) void hostif_exit(struct ks_wlan_private *priv) { tasklet_kill(&priv->sme_task); - return; } -- cgit v1.2.3 From 592c61165b52ef2047aad179fc8bd63bdc5e4770 Mon Sep 17 00:00:00 2001 From: Sabitha George Date: Sun, 9 Oct 2016 11:24:02 +0530 Subject: staging: ks7010: Replace header files This patch replaces inclusion of asm/atomic.h with linux/atomic.h and asm/io.h with linux/io.h to fix checkpatch warning in ks_wlan.h Signed-off-by: Sabitha George Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan.h b/drivers/staging/ks7010/ks_wlan.h index c2cc288ae899..5851714b6359 100644 --- a/drivers/staging/ks7010/ks_wlan.h +++ b/drivers/staging/ks7010/ks_wlan.h @@ -25,13 +25,13 @@ #include /* struct net_device_stats, struct sk_buff */ #include #include -#include /* struct atmic_t */ +#include /* struct atomic_t */ #include /* struct timer_list */ #include #include /* struct completion */ #include -#include +#include #include "ks7010_sdio.h" -- cgit v1.2.3 From 5c065b53ec47eb6ee6551728070c12bd4bdb6b54 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Sun, 9 Oct 2016 00:50:29 -0300 Subject: staging: media: lirc: Format block comments. Fix checkpatch warning: WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/lirc/lirc_sasem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c index 4678ae10b030..920c4a1290f4 100644 --- a/drivers/staging/media/lirc/lirc_sasem.c +++ b/drivers/staging/media/lirc/lirc_sasem.c @@ -103,7 +103,8 @@ struct sasem_context { struct tx_t { unsigned char data_buf[SASEM_DATA_BUF_SZ]; /* user data - * buffer */ + * buffer + */ struct completion finished; /* wait for write to finish */ atomic_t busy; /* write in progress */ int status; /* status of tx completion */ @@ -295,7 +296,8 @@ static int vfd_close(struct inode *inode, struct file *file) if (!context->dev_present && !context->ir_isopen) { /* Device disconnected before close and IR port is * not open. If IR port is open, context will be - * deleted by ir_close. */ + * deleted by ir_close. + */ mutex_unlock(&context->ctx_lock); delete_context(context); return retval; @@ -397,7 +399,8 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, /* Nine 8 byte packets to be sent */ /* NOTE: "\x07\x01\0\0\0\0\0\0" or "\x0c\0\0\0\0\0\0\0" - * will clear the VFD */ + * will clear the VFD + */ for (i = 0; i < 9; i++) { switch (i) { case 0: -- cgit v1.2.3 From 7f140181b47e6cbac398a4aac908a7e29b3af4ee Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 9 Oct 2016 16:05:23 +0530 Subject: Staging: media: radio-bcm2048: constify v4l2_ioctl_ops structure Declare the structure v4l2_ioctl_ops as const as it is only stored in the ioctl_ops field of video_device structure. As this field is of type const struct v4l2_ioctl_ops *, so v4l2_ioctl_ops structures having this property can also be made const. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct v4l2_ioctl_ops i@p = {...}; @ok1@ identifier r1.i; position p; struct video_device s; @@ s.ioctl_ops=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct v4l2_ioctl_ops i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct v4l2_ioctl_ops i; File size before: text data bss dec hex filename 20465 3220 32 23717 5ca5 drivers/staging/media/bcm2048/radio-bcm2048.o File size after: text data bss dec hex filename 21425 2260 32 23717 5ca5 drivers/staging/media/bcm2048/radio-bcm2048.o Signed-off-by: Bhumika Goyal Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/bcm2048/radio-bcm2048.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index ea15cc638097..fe637ce8f4e7 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -2540,7 +2540,7 @@ static int bcm2048_vidioc_s_hw_freq_seek(struct file *file, void *priv, return err; } -static struct v4l2_ioctl_ops bcm2048_ioctl_ops = { +static const struct v4l2_ioctl_ops bcm2048_ioctl_ops = { .vidioc_querycap = bcm2048_vidioc_querycap, .vidioc_g_input = bcm2048_vidioc_g_input, .vidioc_s_input = bcm2048_vidioc_s_input, -- cgit v1.2.3 From b32e807d262ebed54fd8a40345485af4f2b1891a Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Mon, 3 Oct 2016 23:16:43 +0000 Subject: staging: rts5208: xd.h: Alignment fix Change alignment to match open parenthesis Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/xd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/xd.h b/drivers/staging/rts5208/xd.h index 938138c50bb5..d5f10880efb7 100644 --- a/drivers/staging/rts5208/xd.h +++ b/drivers/staging/rts5208/xd.h @@ -179,7 +179,7 @@ int reset_xd_card(struct rtsx_chip *chip); int xd_delay_write(struct rtsx_chip *chip); #endif int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt); + u32 start_sector, u16 sector_cnt); void xd_free_l2p_tbl(struct rtsx_chip *chip); void xd_cleanup_work(struct rtsx_chip *chip); int xd_power_off_card3v3(struct rtsx_chip *chip); -- cgit v1.2.3 From dd67ec811122064b117ba7f270ad466e22b4fc6e Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Mon, 3 Oct 2016 23:17:05 +0000 Subject: staging: rts5208: Alignment fix Coding style checks found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/xd.c | 332 +++++++++++++++++++++++-------------------- 1 file changed, 179 insertions(+), 153 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index 1de02bb98839..8610589ff307 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -97,9 +97,9 @@ static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len) rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_ID); + XD_TRANSFER_START | XD_READ_ID); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); + XD_TRANSFER_END); for (i = 0; i < 4; i++) rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_ADDRESS1 + i), 0, 0); @@ -129,21 +129,23 @@ static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode) rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)addr); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, - 0xFF, (u8)(addr >> 8)); + 0xFF, (u8)(addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3, - 0xFF, (u8)(addr >> 16)); + 0xFF, (u8)(addr >> 16)); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, - xd_card->addr_cycle | XD_CALC_ECC | XD_BA_NO_TRANSFORM); + xd_card->addr_cycle | + XD_CALC_ECC | + XD_BA_NO_TRANSFORM); break; case XD_ERASE_ADDR: rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, (u8)addr); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, - 0xFF, (u8)(addr >> 8)); + 0xFF, (u8)(addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, - 0xFF, (u8)(addr >> 16)); + 0xFF, (u8)(addr >> 16)); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, - (xd_card->addr_cycle - 1) | XD_CALC_ECC | + (xd_card->addr_cycle - 1) | XD_CALC_ECC | XD_BA_NO_TRANSFORM); break; @@ -153,7 +155,7 @@ static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode) } static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr, - u8 *buf, int buf_len) + u8 *buf, int buf_len) { int retval, i; @@ -162,16 +164,16 @@ static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr, xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, - 0xFF, XD_TRANSFER_START | XD_READ_REDUNDANT); + 0xFF, XD_TRANSFER_START | XD_READ_REDUNDANT); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); for (i = 0; i < 6; i++) rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_PAGE_STATUS + i), - 0, 0); + 0, 0); for (i = 0; i < 4; i++) rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_RESERVED0 + i), - 0, 0); + 0, 0); rtsx_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0); retval = rtsx_send_cmd(chip, XD_CARD, 500); @@ -192,7 +194,7 @@ static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr, } static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset, - u8 *buf, int buf_len) + u8 *buf, int buf_len) { int retval, i; @@ -205,7 +207,7 @@ static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset, for (i = 0; i < buf_len; i++) rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i, - 0, 0); + 0, 0); retval = rtsx_send_cmd(chip, 0, 250); if (retval < 0) { @@ -220,7 +222,7 @@ static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset, } static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf, - int buf_len) + int buf_len) { int retval; u8 reg; @@ -235,15 +237,15 @@ static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf, xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); + XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); + XD_TRANSFER_START | XD_READ_PAGES); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); + XD_TRANSFER_END); retval = rtsx_send_cmd(chip, XD_CARD, 250); if (retval == -ETIMEDOUT) { @@ -347,27 +349,27 @@ static void xd_fill_pull_ctl_disable(struct rtsx_chip *chip) { if (CHECK_PID(chip, 0x5208)) { rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); + XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); + XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD); + XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); + MS_D5_PD | MS_D4_PD); } else if (CHECK_PID(chip, 0x5288)) { if (CHECK_BARO_PKG(chip, QFN)) { rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, - 0xFF, 0x55); + 0xFF, 0x55); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, - 0xFF, 0x55); + 0xFF, 0x55); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, - 0xFF, 0x4B); + 0xFF, 0x4B); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, - 0xFF, 0x69); + 0xFF, 0x69); } } } @@ -386,27 +388,27 @@ static void xd_fill_pull_ctl_enable(struct rtsx_chip *chip) { if (CHECK_PID(chip, 0x5208)) { rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); + XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); + XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - XD_WP_PD | XD_CE_PU | XD_CLE_PD | XD_CD_PU); + XD_WP_PD | XD_CE_PU | XD_CLE_PD | XD_CD_PU); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PU | XD_WE_PU | XD_RE_PU | XD_ALE_PD); + XD_RDY_PU | XD_WE_PU | XD_RE_PU | XD_ALE_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); + MS_D5_PD | MS_D4_PD); } else if (CHECK_PID(chip, 0x5288)) { if (CHECK_BARO_PKG(chip, QFN)) { rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, - 0xFF, 0x55); + 0xFF, 0x55); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, - 0xFF, 0x55); + 0xFF, 0x55); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, - 0xFF, 0x53); + 0xFF, 0x53); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, - 0xFF, 0xA9); + 0xFF, 0xA9); } } } @@ -417,31 +419,46 @@ static int xd_pull_ctl_disable(struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5208)) { retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); + XD_D3_PD | + XD_D2_PD | + XD_D1_PD | + XD_D0_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF, - XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); + XD_D7_PD | + XD_D6_PD | + XD_D5_PD | + XD_D4_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF, - XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + XD_WP_PD | + XD_CE_PD | + XD_CLE_PD | + XD_CD_PU); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD); + XD_RDY_PD | + XD_WE_PD | + XD_RE_PD | + XD_ALE_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + MS_INS_PU | + SD_WP_PD | + SD_CD_PU | + SD_CMD_PD); if (retval) { rtsx_trace(chip); return retval; @@ -499,7 +516,7 @@ static int reset_xd(struct rtsx_chip *chip) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF, - XD_PGSTS_NOT_FF); + XD_PGSTS_NOT_FF); if (chip->asic_code) { if (!CHECK_PID(chip, 0x5288)) xd_fill_pull_ctl_disable(chip); @@ -507,12 +524,13 @@ static int reset_xd(struct rtsx_chip *chip) xd_fill_pull_ctl_stage1_barossa(chip); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3) | 0x20); + (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3) | + 0x20); } if (!chip->ft2_fast_mode) rtsx_add_cmd(chip, WRITE_REG_CMD, XD_INIT, - XD_NO_AUTO_PWR_OFF, 0); + XD_NO_AUTO_PWR_OFF, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0); @@ -537,8 +555,9 @@ static int reset_xd(struct rtsx_chip *chip) xd_fill_pull_ctl_enable(chip); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2) | - 0x20); + (FPGA_XD_PULL_CTL_EN1 & + FPGA_XD_PULL_CTL_EN2) | + 0x20); } retval = rtsx_send_cmd(chip, XD_CARD, 100); @@ -571,8 +590,9 @@ static int reset_xd(struct rtsx_chip *chip) xd_fill_pull_ctl_enable(chip); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2) | - 0x20); + (FPGA_XD_PULL_CTL_EN1 & + FPGA_XD_PULL_CTL_EN2) | + 0x20); } } @@ -599,16 +619,17 @@ static int reset_xd(struct rtsx_chip *chip) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF, - XD_TIME_SETUP_STEP * 3 + - XD_TIME_RW_STEP * (2 + i) + XD_TIME_RWN_STEP * i); + XD_TIME_SETUP_STEP * 3 + + XD_TIME_RW_STEP * (2 + i) + XD_TIME_RWN_STEP * i); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF, - XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 + i) + - XD_TIME_RWN_STEP * (3 + i)); + XD_TIME_SETUP_STEP * 3 + + XD_TIME_RW_STEP * (4 + i) + + XD_TIME_RWN_STEP * (3 + i)); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_RESET); + XD_TRANSFER_START | XD_RESET); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); @@ -625,7 +646,7 @@ static int reset_xd(struct rtsx_chip *chip) ptr[0], ptr[1]); if (((ptr[0] & READY_FLAG) != READY_STATE) || - !(ptr[1] & XD_RDY)) + !(ptr[1] & XD_RDY)) continue; retval = xd_read_id(chip, READ_ID, id_buf, 4); @@ -773,7 +794,7 @@ static int reset_xd(struct rtsx_chip *chip) if (redunt[PAGE_STATUS] != XD_GPG) { for (j = 1; j <= 8; j++) { retval = xd_read_redundant(chip, page_addr + j, - redunt, 11); + redunt, 11); if (retval == STATUS_SUCCESS) { if (redunt[PAGE_STATUS] == XD_GPG) break; @@ -786,7 +807,7 @@ static int reset_xd(struct rtsx_chip *chip) /* Check CIS data */ if ((redunt[BLOCK_STATUS] == XD_GBLK) && - (redunt[PARITY] & XD_BA1_ALL0)) { + (redunt[PARITY] & XD_BA1_ALL0)) { u8 buf[10]; page_addr += j; @@ -798,11 +819,11 @@ static int reset_xd(struct rtsx_chip *chip) } if ((buf[0] == 0x01) && (buf[1] == 0x03) && - (buf[2] == 0xD9) - && (buf[3] == 0x01) && (buf[4] == 0xFF) - && (buf[5] == 0x18) && (buf[6] == 0x02) - && (buf[7] == 0xDF) && (buf[8] == 0x01) - && (buf[9] == 0x20)) { + (buf[2] == 0xD9) + && (buf[3] == 0x01) && (buf[4] == 0xFF) + && (buf[5] == 0x18) && (buf[6] == 0x02) + && (buf[7] == 0xDF) && (buf[8] == 0x01) + && (buf[9] == 0x20)) { xd_card->cis_block = (u16)i; } } @@ -957,7 +978,7 @@ static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no) zone = &(xd_card->zone[zone_no]); if ((zone->unused_blk_cnt == 0) || - (zone->set_index == zone->get_index)) { + (zone->set_index == zone->get_index)) { free_zone(zone); dev_dbg(rtsx_dev(chip), "Get unused block fail, no unused block available\n"); return BLK_NOT_FOUND; @@ -982,7 +1003,7 @@ static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no) } static void xd_set_l2p_tbl(struct rtsx_chip *chip, - int zone_no, u16 log_off, u16 phy_off) + int zone_no, u16 log_off, u16 phy_off) { struct xd_info *xd_card = &(chip->xd_card); struct zone_entry *zone; @@ -1023,7 +1044,7 @@ static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off) } retval = xd_init_page(chip, phy_blk, log_off, - 0, xd_card->page_off + 1); + 0, xd_card->page_off + 1); if (retval == STATUS_SUCCESS) break; } @@ -1107,12 +1128,12 @@ static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk) xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, - xd_card->page_off + 1); + xd_card->page_off + 1); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_WRITE_REDUNDANT); + XD_TRANSFER_START | XD_WRITE_REDUNDANT); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); retval = rtsx_send_cmd(chip, XD_CARD, 500); if (retval < 0) { @@ -1153,7 +1174,7 @@ static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, - 0xFF, (u8)(logoff >> 8)); + 0xFF, (u8)(logoff >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)logoff); page_addr = (phy_blk << xd_card->block_shift) + start_page; @@ -1161,15 +1182,15 @@ static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, - XD_BA_TRANSFORM, XD_BA_TRANSFORM); + XD_BA_TRANSFORM, XD_BA_TRANSFORM); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, - 0xFF, (end_page - start_page)); + 0xFF, (end_page - start_page)); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, - 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT); + 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); retval = rtsx_send_cmd(chip, XD_CARD, 500); if (retval < 0) { @@ -1235,11 +1256,11 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, 0); + XD_AUTO_CHK_DATA_STATUS, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); + XD_TRANSFER_START | XD_READ_PAGES); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); retval = rtsx_send_cmd(chip, XD_CARD, 500); if (retval < 0) { @@ -1250,7 +1271,7 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, wait_timeout(100); if (detect_card_cd(chip, - XD_CARD) != STATUS_SUCCESS) { + XD_CARD) != STATUS_SUCCESS) { xd_set_err_code(chip, XD_NO_CARD); rtsx_trace(chip); return STATUS_FAIL; @@ -1261,11 +1282,13 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, || ((reg & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) == (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { rtsx_write_register(chip, - XD_PAGE_STATUS, 0xFF, - XD_BPG); + XD_PAGE_STATUS, + 0xFF, + XD_BPG); rtsx_write_register(chip, - XD_BLOCK_STATUS, 0xFF, - XD_GBLK); + XD_BLOCK_STATUS, + 0xFF, + XD_GBLK); XD_SET_BAD_OLDBLK(xd_card); dev_dbg(rtsx_dev(chip), "old block 0x%x ecc error\n", old_blk); @@ -1287,7 +1310,7 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); retval = rtsx_send_cmd(chip, XD_CARD, 300); if (retval < 0) { @@ -1320,9 +1343,9 @@ static int xd_reset_cmd(struct rtsx_chip *chip) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, - 0xFF, XD_TRANSFER_START | XD_RESET); + 0xFF, XD_TRANSFER_START | XD_RESET); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); @@ -1360,9 +1383,9 @@ static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk) xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_ERASE); + XD_TRANSFER_START | XD_ERASE); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); retval = rtsx_send_cmd(chip, XD_CARD, 250); @@ -1490,7 +1513,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) cur_fst_page_logoff = xd_load_log_block_addr(redunt); if ((cur_fst_page_logoff == 0xFFFF) || - (cur_fst_page_logoff > max_logoff)) { + (cur_fst_page_logoff > max_logoff)) { retval = xd_erase_block(chip, i); if (retval == STATUS_SUCCESS) xd_set_unused_block(chip, i); @@ -1498,7 +1521,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) } if ((zone_no == 0) && (cur_fst_page_logoff == 0) && - (redunt[PAGE_STATUS] != XD_GPG)) + (redunt[PAGE_STATUS] != XD_GPG)) XD_SET_MBR_FAIL(xd_card); if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) { @@ -1524,7 +1547,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) for (m = 0; m < 3; m++) { retval = xd_read_redundant(chip, page_addr, - redunt, 11); + redunt, 11); if (retval == STATUS_SUCCESS) break; } @@ -1598,9 +1621,9 @@ static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd) rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_SET_CMD); + XD_TRANSFER_START | XD_SET_CMD); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); retval = rtsx_send_cmd(chip, XD_CARD, 200); if (retval < 0) { @@ -1612,9 +1635,9 @@ static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd) } static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, - u32 log_blk, u8 start_page, u8 end_page, - u8 *buf, unsigned int *index, - unsigned int *offset) + u32 log_blk, u8 start_page, u8 end_page, + u8 *buf, unsigned int *index, + unsigned int *offset) { struct xd_info *xd_card = &(chip->xd_card); u32 page_addr, new_blk; @@ -1653,22 +1676,23 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); + XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); trans_dma_enable(chip->srb->sc_data_direction, chip, - page_cnt * 512, DMA_512); + page_cnt * 512, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); + XD_TRANSFER_START | XD_READ_PAGES); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END | XD_PPB_EMPTY, XD_TRANSFER_END | XD_PPB_EMPTY); + XD_TRANSFER_END | XD_PPB_EMPTY, + XD_TRANSFER_END | XD_PPB_EMPTY); rtsx_send_cmd_no_wait(chip); retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, - scsi_sg_count(chip->srb), - index, offset, DMA_FROM_DEVICE, - chip->xd_timeout); + scsi_sg_count(chip->srb), + index, offset, DMA_FROM_DEVICE, + chip->xd_timeout); if (retval < 0) { rtsx_clear_xd_error(chip); @@ -1719,7 +1743,7 @@ Fail: } retval = xd_copy_page(chip, phy_blk, new_blk, 0, - xd_card->page_off + 1); + xd_card->page_off + 1); if (retval != STATUS_SUCCESS) { if (!XD_CHK_BAD_NEWBLK(xd_card)) { retval = xd_erase_block(chip, new_blk); @@ -1743,7 +1767,7 @@ Status_Fail: } static int xd_finish_write(struct rtsx_chip *chip, - u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) + u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) { struct xd_info *xd_card = &(chip->xd_card); int retval, zone_no; @@ -1762,7 +1786,7 @@ static int xd_finish_write(struct rtsx_chip *chip, if (old_blk == BLK_NOT_FOUND) { retval = xd_init_page(chip, new_blk, log_off, - page_off, xd_card->page_off + 1); + page_off, xd_card->page_off + 1); if (retval != STATUS_SUCCESS) { retval = xd_erase_block(chip, new_blk); if (retval == STATUS_SUCCESS) @@ -1772,7 +1796,7 @@ static int xd_finish_write(struct rtsx_chip *chip, } } else { retval = xd_copy_page(chip, old_blk, new_blk, - page_off, xd_card->page_off + 1); + page_off, xd_card->page_off + 1); if (retval != STATUS_SUCCESS) { if (!XD_CHK_BAD_NEWBLK(xd_card)) { retval = xd_erase_block(chip, new_blk); @@ -1804,7 +1828,7 @@ static int xd_finish_write(struct rtsx_chip *chip, } static int xd_prepare_write(struct rtsx_chip *chip, - u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) + u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) { int retval; @@ -1823,9 +1847,9 @@ static int xd_prepare_write(struct rtsx_chip *chip, } static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, - u32 new_blk, u32 log_blk, u8 start_page, - u8 end_page, u8 *buf, unsigned int *index, - unsigned int *offset) + u32 new_blk, u32 log_blk, u8 start_page, + u8 end_page, u8 *buf, unsigned int *index, + unsigned int *offset) { struct xd_info *xd_card = &(chip->xd_card); u32 page_addr; @@ -1852,7 +1876,7 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, - 0xFF, (u8)(log_off >> 8)); + 0xFF, (u8)(log_off >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)log_off); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); @@ -1860,23 +1884,23 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, - XD_BA_TRANSFORM); + XD_BA_TRANSFORM); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); trans_dma_enable(chip->srb->sc_data_direction, chip, - page_cnt * 512, DMA_512); + page_cnt * 512, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, - 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES); + 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES); rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); + XD_TRANSFER_END, XD_TRANSFER_END); rtsx_send_cmd_no_wait(chip); retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, - scsi_sg_count(chip->srb), - index, offset, DMA_TO_DEVICE, chip->xd_timeout); + scsi_sg_count(chip->srb), + index, offset, DMA_TO_DEVICE, chip->xd_timeout); if (retval < 0) { rtsx_clear_xd_error(chip); @@ -1944,9 +1968,10 @@ int xd_delay_write(struct rtsx_chip *chip) delay_write->delay_write_flag = 0; retval = xd_finish_write(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->logblock, delay_write->pageoff); + delay_write->old_phyblock, + delay_write->new_phyblock, + delay_write->logblock, + delay_write->pageoff); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1958,7 +1983,7 @@ int xd_delay_write(struct rtsx_chip *chip) #endif int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt) + u32 start_sector, u16 sector_cnt) { struct xd_info *xd_card = &(chip->xd_card); unsigned int lun = SCSI_LUN(srb); @@ -2012,17 +2037,18 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (srb->sc_data_direction == DMA_TO_DEVICE) { #ifdef XD_DELAY_WRITE if (delay_write->delay_write_flag && - (delay_write->logblock == log_blk) && - (start_page > delay_write->pageoff)) { + (delay_write->logblock == log_blk) && + (start_page > delay_write->pageoff)) { delay_write->delay_write_flag = 0; if (delay_write->old_phyblock != BLK_NOT_FOUND) { retval = xd_copy_page(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->pageoff, start_page); + delay_write->old_phyblock, + delay_write->new_phyblock, + delay_write->pageoff, + start_page); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -2039,7 +2065,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, retval = xd_delay_write(chip); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -2047,25 +2073,25 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); new_blk = xd_get_unused_block(chip, zone_no); if ((old_blk == BLK_NOT_FOUND) || - (new_blk == BLK_NOT_FOUND)) { + (new_blk == BLK_NOT_FOUND)) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } retval = xd_prepare_write(chip, old_blk, new_blk, - log_blk, start_page); + log_blk, start_page); if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); + SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; } set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -2078,12 +2104,12 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); + SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; } set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -2092,7 +2118,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); if (old_blk == BLK_NOT_FOUND) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -2116,22 +2142,22 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, page_cnt = end_page - start_page; if (srb->sc_data_direction == DMA_FROM_DEVICE) { retval = xd_read_multiple_pages(chip, old_blk, log_blk, - start_page, end_page, ptr, - &index, &offset); + start_page, end_page, + ptr, &index, &offset); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return STATUS_FAIL; } } else { retval = xd_write_multiple_pages(chip, old_blk, - new_blk, log_blk, - start_page, end_page, ptr, - &index, &offset); + new_blk, log_blk, + start_page, end_page, + ptr, &index, &offset); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -2153,7 +2179,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (retval != STATUS_SUCCESS) { chip->card_fail |= XD_CARD; set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); + SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; } @@ -2163,10 +2189,10 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (old_blk == BLK_NOT_FOUND) { if (srb->sc_data_direction == DMA_FROM_DEVICE) set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); else set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; @@ -2176,7 +2202,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, new_blk = xd_get_unused_block(chip, zone_no); if (new_blk == BLK_NOT_FOUND) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -2186,7 +2212,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, } if ((srb->sc_data_direction == DMA_TO_DEVICE) && - (end_page != (xd_card->page_off + 1))) { + (end_page != (xd_card->page_off + 1))) { #ifdef XD_DELAY_WRITE delay_write->delay_write_flag = 1; delay_write->old_phyblock = old_blk; @@ -2202,11 +2228,11 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, } retval = xd_finish_write(chip, old_blk, new_blk, - log_blk, end_page); + log_blk, end_page); if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); + SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; } -- cgit v1.2.3 From d5549720768759a2c48ca0802c86635c4ee5775e Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Mon, 3 Oct 2016 23:17:26 +0000 Subject: staging: rts5208: Logical continuation fixes Checkpatch detected multiple instances of logical continuation warnings Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/xd.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index 8610589ff307..62962b0713c4 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -819,11 +819,11 @@ static int reset_xd(struct rtsx_chip *chip) } if ((buf[0] == 0x01) && (buf[1] == 0x03) && - (buf[2] == 0xD9) - && (buf[3] == 0x01) && (buf[4] == 0xFF) - && (buf[5] == 0x18) && (buf[6] == 0x02) - && (buf[7] == 0xDF) && (buf[8] == 0x01) - && (buf[9] == 0x20)) { + (buf[2] == 0xD9) && + (buf[3] == 0x01) && (buf[4] == 0xFF) && + (buf[5] == 0x18) && (buf[6] == 0x02) && + (buf[7] == 0xDF) && (buf[8] == 0x01) && + (buf[9] == 0x20)) { xd_card->cis_block = (u16)i; } } @@ -948,8 +948,8 @@ static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) return; } - if ((zone->set_index >= XD_FREE_TABLE_CNT) - || (zone->set_index < 0)) { + if ((zone->set_index >= XD_FREE_TABLE_CNT) || + (zone->set_index < 0)) { free_zone(zone); dev_dbg(rtsx_dev(chip), "Set unused block fail, invalid set_index\n"); return; @@ -1278,8 +1278,8 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, } if (((reg & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) == - (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) - || ((reg & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) == + (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) || + ((reg & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) == (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { rtsx_write_register(chip, XD_PAGE_STATUS, @@ -1723,10 +1723,10 @@ Fail: return retval; } - if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) - == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) - || ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) - == (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { + if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) == + (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) || + ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) == + (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { wait_timeout(100); if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { -- cgit v1.2.3 From 14c42c79fef07619f6b724cf7c4611c8687dfc00 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Mon, 3 Oct 2016 23:18:01 +0000 Subject: staging: rts5208: xd.c: Remove unnecessary parentheses Issues found with checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/xd.c | 64 ++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index 62962b0713c4..a9cd523d27a6 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -37,21 +37,21 @@ static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff, static inline void xd_set_err_code(struct rtsx_chip *chip, u8 err_code) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; xd_card->err_code = err_code; } static inline int xd_check_err_code(struct rtsx_chip *chip, u8 err_code) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; return (xd_card->err_code == err_code); } static int xd_set_init_para(struct rtsx_chip *chip) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int retval; if (chip->asic_code) @@ -70,7 +70,7 @@ static int xd_set_init_para(struct rtsx_chip *chip) static int xd_switch_clock(struct rtsx_chip *chip) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int retval; retval = select_card(chip, XD_CARD); @@ -122,7 +122,7 @@ static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len) static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; switch (mode) { case XD_RW_ADDR: @@ -503,7 +503,7 @@ static int xd_pull_ctl_disable(struct rtsx_chip *chip) static int reset_xd(struct rtsx_chip *chip) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int retval, i, j; u8 *ptr, id_buf[4], redunt[11]; @@ -882,7 +882,7 @@ static u16 xd_load_log_block_addr(u8 *redunt) static int xd_init_l2p_tbl(struct rtsx_chip *chip) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int size, i; dev_dbg(rtsx_dev(chip), "xd_init_l2p_tbl: zone_cnt = %d\n", @@ -931,7 +931,7 @@ static inline void free_zone(struct zone_entry *zone) static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; struct zone_entry *zone; int zone_no; @@ -941,7 +941,7 @@ static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) zone_no, xd_card->zone_cnt); return; } - zone = &(xd_card->zone[zone_no]); + zone = &xd_card->zone[zone_no]; if (zone->free_table == NULL) { if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS) @@ -966,7 +966,7 @@ static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; struct zone_entry *zone; u32 phy_blk; @@ -975,7 +975,7 @@ static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no) zone_no, xd_card->zone_cnt); return BLK_NOT_FOUND; } - zone = &(xd_card->zone[zone_no]); + zone = &xd_card->zone[zone_no]; if ((zone->unused_blk_cnt == 0) || (zone->set_index == zone->get_index)) { @@ -1005,20 +1005,20 @@ static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no) static void xd_set_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off, u16 phy_off) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; struct zone_entry *zone; - zone = &(xd_card->zone[zone_no]); + zone = &xd_card->zone[zone_no]; zone->l2p_table[log_off] = phy_off; } static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; struct zone_entry *zone; int retval; - zone = &(xd_card->zone[zone_no]); + zone = &xd_card->zone[zone_no]; if (zone->l2p_table[log_off] == 0xFFFF) { u32 phy_blk = 0; int i; @@ -1062,7 +1062,7 @@ static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off) int reset_xd_card(struct rtsx_chip *chip) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int retval; memset(xd_card, 0, sizeof(struct xd_info)); @@ -1098,7 +1098,7 @@ int reset_xd_card(struct rtsx_chip *chip) static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int retval; u32 page_addr; u8 reg = 0; @@ -1153,7 +1153,7 @@ static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk) static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff, u8 start_page, u8 end_page) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int retval; u32 page_addr; u8 reg = 0; @@ -1212,7 +1212,7 @@ static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, u8 start_page, u8 end_page) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; u32 old_page, new_page; u8 i, reg = 0; int retval; @@ -1365,7 +1365,7 @@ static int xd_reset_cmd(struct rtsx_chip *chip) static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; u32 page_addr; u8 reg = 0, *ptr; int i, retval; @@ -1426,7 +1426,7 @@ static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk) static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; struct zone_entry *zone; int retval; u32 start, end, i; @@ -1448,7 +1448,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) return STATUS_SUCCESS; } - zone = &(xd_card->zone[zone_no]); + zone = &xd_card->zone[zone_no]; if (zone->l2p_table == NULL) { zone->l2p_table = vmalloc(2000); @@ -1639,7 +1639,7 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, u8 *buf, unsigned int *index, unsigned int *offset) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; u32 page_addr, new_blk; u16 log_off; u8 reg_val, page_cnt; @@ -1769,7 +1769,7 @@ Status_Fail: static int xd_finish_write(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int retval, zone_no; u16 log_off; @@ -1851,7 +1851,7 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, u8 end_page, u8 *buf, unsigned int *index, unsigned int *offset) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; u32 page_addr; int zone_no, retval; u16 log_off; @@ -1954,8 +1954,8 @@ Status_Fail: #ifdef XD_DELAY_WRITE int xd_delay_write(struct rtsx_chip *chip) { - struct xd_info *xd_card = &(chip->xd_card); - struct xd_delay_write_tag *delay_write = &(xd_card->delay_write); + struct xd_info *xd_card = &chip->xd_card; + struct xd_delay_write_tag *delay_write = &xd_card->delay_write; int retval; if (delay_write->delay_write_flag) { @@ -1985,10 +1985,10 @@ int xd_delay_write(struct rtsx_chip *chip) int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; unsigned int lun = SCSI_LUN(srb); #ifdef XD_DELAY_WRITE - struct xd_delay_write_tag *delay_write = &(xd_card->delay_write); + struct xd_delay_write_tag *delay_write = &xd_card->delay_write; #endif int retval, zone_no; unsigned int index = 0, offset = 0; @@ -2250,7 +2250,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, void xd_free_l2p_tbl(struct rtsx_chip *chip) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int i = 0; if (xd_card->zone != NULL) { @@ -2268,7 +2268,7 @@ void xd_free_l2p_tbl(struct rtsx_chip *chip) void xd_cleanup_work(struct rtsx_chip *chip) { #ifdef XD_DELAY_WRITE - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; if (xd_card->delay_write.delay_write_flag) { dev_dbg(rtsx_dev(chip), "xD: delay write\n"); @@ -2323,7 +2323,7 @@ int xd_power_off_card3v3(struct rtsx_chip *chip) int release_xd_card(struct rtsx_chip *chip) { - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; int retval; chip->card_ready &= ~XD_CARD; -- cgit v1.2.3 From daaca111db57da25d8ace698aea3758c7e1755d7 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Mon, 3 Oct 2016 23:18:20 +0000 Subject: staging: rts5208: xd.c: Clean up comparison to NULL Checkpatch recommended changes Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/xd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index a9cd523d27a6..cc400ccc9e79 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -943,7 +943,7 @@ static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) } zone = &xd_card->zone[zone_no]; - if (zone->free_table == NULL) { + if (!zone->free_table) { if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS) return; } @@ -1436,7 +1436,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) dev_dbg(rtsx_dev(chip), "xd_build_l2p_tbl: %d\n", zone_no); - if (xd_card->zone == NULL) { + if (!xd_card->zone) { retval = xd_init_l2p_tbl(chip); if (retval != STATUS_SUCCESS) return retval; @@ -1450,7 +1450,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) zone = &xd_card->zone[zone_no]; - if (zone->l2p_table == NULL) { + if (!zone->l2p_table) { zone->l2p_table = vmalloc(2000); if (!zone->l2p_table) { rtsx_trace(chip); @@ -1459,7 +1459,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) } memset((u8 *)(zone->l2p_table), 0xff, 2000); - if (zone->free_table == NULL) { + if (!zone->free_table) { zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2); if (!zone->free_table) { rtsx_trace(chip); @@ -2253,7 +2253,7 @@ void xd_free_l2p_tbl(struct rtsx_chip *chip) struct xd_info *xd_card = &chip->xd_card; int i = 0; - if (xd_card->zone != NULL) { + if (xd_card->zone) { for (i = 0; i < xd_card->zone_cnt; i++) { vfree(xd_card->zone[i].l2p_table); xd_card->zone[i].l2p_table = NULL; -- cgit v1.2.3 From 40eeb86243de35fd2a613cffdc0397b7d266367a Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Mon, 3 Oct 2016 23:18:38 +0000 Subject: staging: rts5208: xd.c: Fix CamelCase Covert CamelCase as checkpatch suggests Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/xd.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index cc400ccc9e79..66f96dc56765 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -1454,7 +1454,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) zone->l2p_table = vmalloc(2000); if (!zone->l2p_table) { rtsx_trace(chip); - goto Build_Fail; + goto build_fail; } } memset((u8 *)(zone->l2p_table), 0xff, 2000); @@ -1463,7 +1463,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2); if (!zone->free_table) { rtsx_trace(chip); - goto Build_Fail; + goto build_fail; } } memset((u8 *)(zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2); @@ -1604,7 +1604,7 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) return STATUS_SUCCESS; -Build_Fail: +build_fail: vfree(zone->l2p_table); zone->l2p_table = NULL; vfree(zone->free_table); @@ -1646,7 +1646,7 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, int zone_no, retval, i; if (start_page > end_page) - goto Status_Fail; + goto status_fail; page_cnt = end_page - start_page; zone_no = (int)(log_blk / 1000); @@ -1662,7 +1662,7 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { xd_set_err_code(chip, XD_NO_CARD); - goto Status_Fail; + goto status_fail; } } } @@ -1698,16 +1698,16 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, if (retval == -ETIMEDOUT) { xd_set_err_code(chip, XD_TO_ERROR); - goto Status_Fail; + goto status_fail; } else { rtsx_trace(chip); - goto Fail; + goto fail; } } return STATUS_SUCCESS; -Fail: +fail: retval = rtsx_read_register(chip, XD_PAGE_STATUS, ®_val); if (retval) { rtsx_trace(chip); @@ -1731,7 +1731,7 @@ Fail: if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { xd_set_err_code(chip, XD_NO_CARD); - goto Status_Fail; + goto status_fail; } xd_set_err_code(chip, XD_ECC_ERROR); @@ -1739,7 +1739,7 @@ Fail: new_blk = xd_get_unused_block(chip, zone_no); if (new_blk == NO_NEW_BLK) { XD_CLR_BAD_OLDBLK(xd_card); - goto Status_Fail; + goto status_fail; } retval = xd_copy_page(chip, phy_blk, new_blk, 0, @@ -1753,7 +1753,7 @@ Fail: XD_CLR_BAD_NEWBLK(xd_card); } XD_CLR_BAD_OLDBLK(xd_card); - goto Status_Fail; + goto status_fail; } xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); xd_erase_block(chip, phy_blk); @@ -1761,7 +1761,7 @@ Fail: XD_CLR_BAD_OLDBLK(xd_card); } -Status_Fail: +status_fail: rtsx_trace(chip); return STATUS_FAIL; } @@ -1861,7 +1861,7 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, __func__, old_blk, new_blk, log_blk); if (start_page > end_page) - goto Status_Fail; + goto status_fail; page_cnt = end_page - start_page; zone_no = (int)(log_blk / 1000); @@ -1871,7 +1871,7 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, retval = xd_send_cmd(chip, READ1_1); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; rtsx_init_cmd(chip); @@ -1906,10 +1906,10 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, if (retval == -ETIMEDOUT) { xd_set_err_code(chip, XD_TO_ERROR); - goto Status_Fail; + goto status_fail; } else { rtsx_trace(chip); - goto Fail; + goto fail; } } @@ -1935,7 +1935,7 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, return STATUS_SUCCESS; -Fail: +fail: retval = rtsx_read_register(chip, XD_DAT, ®_val); if (retval) { rtsx_trace(chip); @@ -1946,7 +1946,7 @@ Fail: xd_mark_bad_block(chip, new_blk); } -Status_Fail: +status_fail: rtsx_trace(chip); return STATUS_FAIL; } -- cgit v1.2.3 From 6d2117f1a51005a2fa2be65a6e0b9ba82ba564a5 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Mon, 3 Oct 2016 23:18:55 +0000 Subject: staging: rts5208: xd.c: Remove multiple assignments Checkpatch found multiple assignments on one line so move them to their own lines. Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/xd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index 66f96dc56765..85aba05acbc1 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -1489,7 +1489,8 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) dev_dbg(rtsx_dev(chip), "start block 0x%x, end block 0x%x\n", start, end); - zone->set_index = zone->get_index = 0; + zone->set_index = 0; + zone->get_index = 0; zone->unused_blk_cnt = 0; for (i = start; i < end; i++) { -- cgit v1.2.3 From 2e41eb96f99a81e1b941812c7cd767c81d7d7d75 Mon Sep 17 00:00:00 2001 From: Benoit Hiller Date: Sat, 8 Oct 2016 15:49:55 -0400 Subject: staging: dgnc: make find_board_by_major static Fixes the following sparse warning: drivers/staging/dgnc/dgnc_tty.c:933:19: warning: symbol 'find_board_by_major' was not declared. Should it be static? Signed-off-by: Benoit Hiller Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 953d9310fa74..ef9a45bc0b89 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -930,7 +930,7 @@ void dgnc_wakeup_writes(struct channel_t *ch) spin_unlock_irqrestore(&ch->ch_lock, flags); } -struct dgnc_board *find_board_by_major(unsigned int major) +static struct dgnc_board *find_board_by_major(unsigned int major) { int i; -- cgit v1.2.3 From 8ba392d151c5875bf8e580634cc6837b2a029207 Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman Date: Thu, 6 Oct 2016 14:41:18 -0700 Subject: staging: i4l: move open brace to previous line Fix checkpatch error "open brace should be on previous line" since only functions should have their opening brace on a new line. Signed-off-by: Elizabeth Ferdman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/act2000/module.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/i4l/act2000/module.c b/drivers/staging/i4l/act2000/module.c index 99c9c0a1c63e..45dee55335c9 100644 --- a/drivers/staging/i4l/act2000/module.c +++ b/drivers/staging/i4l/act2000/module.c @@ -19,8 +19,7 @@ #include #include -static unsigned short act2000_isa_ports[] = -{ +static unsigned short act2000_isa_ports[] = { 0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380, 0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60, }; -- cgit v1.2.3 From 06e0f0f053243abf7f6daf9f152a64b3fd4b882e Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman Date: Thu, 6 Oct 2016 14:44:28 -0700 Subject: staging: i4l: add blank line after declarations Fix checkpatch error "missing blank line after declarations" to conform to kernel coding style. Signed-off-by: Elizabeth Ferdman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/act2000/act2000_isa.c | 1 + drivers/staging/i4l/act2000/capi.c | 5 +++++ drivers/staging/i4l/act2000/module.c | 3 +++ 3 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/i4l/act2000/act2000_isa.c b/drivers/staging/i4l/act2000/act2000_isa.c index ad7a0391369f..76ff5de65781 100644 --- a/drivers/staging/i4l/act2000/act2000_isa.c +++ b/drivers/staging/i4l/act2000/act2000_isa.c @@ -259,6 +259,7 @@ act2000_isa_receive(act2000_card *card) "act2000_isa_receive: Invalid CAPI msg\n"); { int i; __u8 *p; __u8 *t; __u8 tmp[30]; + for (i = 0, p = (__u8 *)&card->idat.isa.rcvhdr, t = tmp; i < 8; i++) t += sprintf(t, "%02x ", *(p++)); printk(KERN_WARNING "act2000_isa_receive: %s\n", tmp); diff --git a/drivers/staging/i4l/act2000/capi.c b/drivers/staging/i4l/act2000/capi.c index 62f56294853c..66c1e579fc04 100644 --- a/drivers/staging/i4l/act2000/capi.c +++ b/drivers/staging/i4l/act2000/capi.c @@ -506,6 +506,7 @@ static int new_plci(act2000_card *card, __u16 plci) { int i; + for (i = 0; i < ACT2000_BCH; i++) if (card->bch[i].plci == 0x8000) { card->bch[i].plci = plci; @@ -518,6 +519,7 @@ static int find_plci(act2000_card *card, __u16 plci) { int i; + for (i = 0; i < ACT2000_BCH; i++) if (card->bch[i].plci == plci) return i; @@ -528,6 +530,7 @@ static int find_ncci(act2000_card *card, __u16 ncci) { int i; + for (i = 0; i < ACT2000_BCH; i++) if (card->bch[i].ncci == ncci) return i; @@ -538,6 +541,7 @@ static int find_dialing(act2000_card *card, __u16 callref) { int i; + for (i = 0; i < ACT2000_BCH; i++) if ((card->bch[i].callref == callref) && (card->bch[i].fsm_state == ACT2000_STATE_OCALL)) @@ -1088,6 +1092,7 @@ actcapi_debug_msg(struct sk_buff *skb, int direction) int l = msg->hdr.len - 12; int j; char *p = tmp; + for (j = 0; j < l; j++) p += sprintf(p, "%02x ", msg->msg.info_ind.el.display[j]); printk(KERN_DEBUG " D = '%s'\n", tmp); diff --git a/drivers/staging/i4l/act2000/module.c b/drivers/staging/i4l/act2000/module.c index 45dee55335c9..e227c08b4f00 100644 --- a/drivers/staging/i4l/act2000/module.c +++ b/drivers/staging/i4l/act2000/module.c @@ -376,6 +376,7 @@ act2000_command(act2000_card *card, isdn_ctrl *c) } if (card->ptype == ISDN_PTYPE_1TR6) { int i; + chan->eazmask = 0; for (i = 0; i < strlen(c->parm.num); i++) if (isdigit(c->parm.num[i])) @@ -573,6 +574,7 @@ act2000_alloccard(int bus, int port, int irq, char *id) { int i; act2000_card *card; + if (!(card = kzalloc(sizeof(act2000_card), GFP_KERNEL))) { printk(KERN_WARNING "act2000: (%s) Could not allocate card-struct.\n", id); @@ -794,6 +796,7 @@ static void __exit act2000_exit(void) { act2000_card *card = cards; act2000_card *last; + while (card) { unregister_card(card); del_timer_sync(&card->ptimer); -- cgit v1.2.3 From 321c799cd95cafc67fbf955f8a61b49e42b2f9b4 Mon Sep 17 00:00:00 2001 From: Jakub Jedelsky Date: Wed, 5 Oct 2016 00:32:55 +0200 Subject: staging: comedi: Align the * on block comments Block comments should align the * on each line as reported by checkpatch Signed-off-by: Jakub Jedelsky Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidda.c | 4 ++-- drivers/staging/comedi/drivers/mite.c | 2 +- drivers/staging/comedi/drivers/pcl818.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index ccb37d1f0f8e..987414741605 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -248,8 +248,8 @@ static void cb_pcidda_write_caldac(struct comedi_device *dev, cb_pcidda_serial_out(dev, value, num_caldac_bits); /* -* latch stream into appropriate caldac deselect reference dac -*/ + * latch stream into appropriate caldac deselect reference dac + */ cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT; /* deactivate caldacs (one caldac for every two channels) */ for (i = 0; i < max_num_caldacs; i++) diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index b1c0860135d0..05126ba4ba51 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -837,7 +837,7 @@ static int mite_setup(struct comedi_device *dev, struct mite *mite, * of 0x61f and bursts worked. 6281 powered up with register value of * 0x1f and bursts didn't work. The NI windows driver reads the * register, then does a bitwise-or of 0x600 with it and writes it back. - * + * * The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be * written and read back. The bits 0x1f always read as 1. * The rest always read as zero. diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 5aeed44dff70..5b5df0596ad9 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -771,9 +771,9 @@ static int pcl818_ai_cancel(struct comedi_device *dev, s->async->scans_done < cmd->stop_arg)) { if (!devpriv->ai_cmd_canceled) { /* - * Wait for running dma transfer to end, - * do cleanup in interrupt. - */ + * Wait for running dma transfer to end, + * do cleanup in interrupt. + */ devpriv->ai_cmd_canceled = 1; return 0; } -- cgit v1.2.3 From 1af172fa4156ec0ab39e47ebc0883f41802d478c Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 8 Oct 2016 15:58:04 +0530 Subject: Staging: skein: skein_api: Remove useless type conversion Some type conversions like casting a pointer to a pointer of same type, casting to the original type using addressof(&) operator etc. are not needed. Therefore, remove them. Done using coccinelle: @@ type t; t *p; t a; @@ ( - (t)(a) + a | - (t *)(p) + p | - (t *)(&a) + &a ) Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/skein/skein_api.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/skein/skein_api.c b/drivers/staging/skein/skein_api.c index cab26e736111..c6526b6fbfb4 100644 --- a/drivers/staging/skein/skein_api.c +++ b/drivers/staging/skein/skein_api.c @@ -98,19 +98,16 @@ int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len, switch (ctx->skein_size) { case SKEIN_256: ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len, - tree_info, - (const u8 *)key, key_len); + tree_info, key, key_len); break; case SKEIN_512: ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len, - tree_info, - (const u8 *)key, key_len); + tree_info, key, key_len); break; case SKEIN_1024: ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len, - tree_info, - (const u8 *)key, key_len); + tree_info, key, key_len); break; } @@ -152,16 +149,13 @@ int skein_update(struct skein_ctx *ctx, const u8 *msg, switch (ctx->skein_size) { case SKEIN_256: - ret = skein_256_update(&ctx->m.s256, (const u8 *)msg, - msg_byte_cnt); + ret = skein_256_update(&ctx->m.s256, msg, msg_byte_cnt); break; case SKEIN_512: - ret = skein_512_update(&ctx->m.s512, (const u8 *)msg, - msg_byte_cnt); + ret = skein_512_update(&ctx->m.s512, msg, msg_byte_cnt); break; case SKEIN_1024: - ret = skein_1024_update(&ctx->m.s1024, (const u8 *)msg, - msg_byte_cnt); + ret = skein_1024_update(&ctx->m.s1024, msg, msg_byte_cnt); break; } return ret; @@ -211,7 +205,7 @@ int skein_update_bits(struct skein_ctx *ctx, const u8 *msg, /* partial byte bit mask */ mask = (u8)(1u << (7 - (msg_bit_cnt & 7))); /* apply bit padding on final byte (in the buffer) */ - up[length - 1] = (u8)((up[length - 1] & (0 - mask)) | mask); + up[length - 1] = (up[length - 1] & (0 - mask)) | mask; return SKEIN_SUCCESS; } @@ -224,13 +218,13 @@ int skein_final(struct skein_ctx *ctx, u8 *hash) switch (ctx->skein_size) { case SKEIN_256: - ret = skein_256_final(&ctx->m.s256, (u8 *)hash); + ret = skein_256_final(&ctx->m.s256, hash); break; case SKEIN_512: - ret = skein_512_final(&ctx->m.s512, (u8 *)hash); + ret = skein_512_final(&ctx->m.s512, hash); break; case SKEIN_1024: - ret = skein_1024_final(&ctx->m.s1024, (u8 *)hash); + ret = skein_1024_final(&ctx->m.s1024, hash); break; } return ret; -- cgit v1.2.3 From 15fb2af604d602373cd4dafb88143adb03463001 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 8 Oct 2016 15:29:54 +0530 Subject: Staging: emxx_udc: Remove useless type conversion Some type conversions like casting a pointer to a pointer of same type, casting to the original type using addressof(&) operator etc. are not needed. Therefore, remove them. Done using coccinelle: @@ type t; t *p; t a; @@ ( - (t)(a) + a | - (t *)(p) + p | - (t *)(&a) + &a ) Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index c3e298843b43..5d7dc00713f5 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -460,7 +460,7 @@ static void _nbu2ss_ep_in_end( if (length) _nbu2ss_writel(&preg->EP_REGS[num].EP_WRITE, data32); - data = ((((u32)length) << 5) & EPn_DW) | EPn_DEND; + data = (((length) << 5) & EPn_DW) | EPn_DEND; _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data); _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO); @@ -1852,7 +1852,7 @@ static inline void _nbu2ss_ep0_int(struct nbu2ss_udc *udc) status = _nbu2ss_readl(&udc->p_regs->EP0_STATUS); intr = status & EP0_STATUS_RW_BIT; - _nbu2ss_writel(&udc->p_regs->EP0_STATUS, ~(u32)intr); + _nbu2ss_writel(&udc->p_regs->EP0_STATUS, ~intr); status &= (SETUP_INT | EP0_IN_INT | EP0_OUT_INT | STG_END_INT | EP0_OUT_NULL_INT); @@ -2127,7 +2127,7 @@ static inline void _nbu2ss_epn_int(struct nbu2ss_udc *udc, u32 epnum) status = _nbu2ss_readl(&udc->p_regs->EP_REGS[num].EP_STATUS); /* Interrupt Clear */ - _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_STATUS, ~(u32)status); + _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_STATUS, ~status); req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); if (!req) { -- cgit v1.2.3 From 03f705d285ea7cc582f3f86e8a1c73fbd2f261d4 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 9 Oct 2016 13:26:28 +0530 Subject: Staging: emxx_udc: constify usb_ep_ops structure Declare the structure usb_ep_ops as constant as it is only stored in the ops field of a usb_ep structure which is a field of a nbu2ss_ep structure. The ops field is of type const struct usb_ep_ops *, so usb_ep_ops structures having this property can be decalared as const. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct usb_ep_ops i@p = {...}; @ok1@ identifier r1.i; position p; struct nbu2ss_ep s; @@ s.ep.ops=&i@p @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct usb_ep_ops i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct usb_ep_ops i; File size before: text data bss dec hex filename 16007 376 3720 20103 4e87 drivers/staging/emxx_udc/emxx_udc.o File size after: text data bss dec hex filename 16095 280 3720 20095 4e7f drivers/staging/emxx_udc/emxx_udc.o Signed-off-by: Bhumika Goyal Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 5d7dc00713f5..abe2aafc8bd4 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -2938,7 +2938,7 @@ static void nbu2ss_ep_fifo_flush(struct usb_ep *_ep) } /*-------------------------------------------------------------------------*/ -static struct usb_ep_ops nbu2ss_ep_ops = { +static const struct usb_ep_ops nbu2ss_ep_ops = { .enable = nbu2ss_ep_enable, .disable = nbu2ss_ep_disable, -- cgit v1.2.3 From b1e9c8b76cf122e16a80422c84560148ec360f37 Mon Sep 17 00:00:00 2001 From: Harman Kalra Date: Sun, 9 Oct 2016 20:14:05 +0530 Subject: Staging: fbtft: Fixed open parenthesis alignment check This patch resolves all the following CHECKs caught by checkpatch.pl CHECK: Alignment should match open parenthesis Signed-off-by: Harman Kalra Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_ili9325.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index c31e2e051d4a..4ab44791d27c 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -38,18 +38,15 @@ MODULE_PARM_DESC(bt, "Sets the factor used in the step-up circuits"); static unsigned int vc = 0x03; /* Vci1=Vci*0.80 */ module_param(vc, uint, 0); -MODULE_PARM_DESC(vc, -"Sets the ratio factor of Vci to generate the reference voltages Vci1"); +MODULE_PARM_DESC(vc, "Sets the ratio factor of Vci to generate the reference voltages Vci1"); static unsigned int vrh = 0x0d; /* VREG1OUT=Vci*1.85 */ module_param(vrh, uint, 0); -MODULE_PARM_DESC(vrh, -"Set the amplifying rate (1.6 ~ 1.9) of Vci applied to output the VREG1OUT"); +MODULE_PARM_DESC(vrh, "Set the amplifying rate (1.6 ~ 1.9) of Vci applied to output the VREG1OUT"); static unsigned int vdv = 0x12; /* VCOMH amplitude=VREG1OUT*0.98 */ module_param(vdv, uint, 0); -MODULE_PARM_DESC(vdv, -"Select the factor of VREG1OUT to set the amplitude of Vcom"); +MODULE_PARM_DESC(vdv, "Select the factor of VREG1OUT to set the amplitude of Vcom"); static unsigned int vcm = 0x0a; /* VCOMH=VREG1OUT*0.735 */ module_param(vcm, uint, 0); -- cgit v1.2.3 From 9ce7664405bd8919bba46c5f854f42a9a9186cc3 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 7 Oct 2016 19:51:28 +0530 Subject: Staging: fwserial: remove unused function fill_unplug_req The function fill_unplug_req is not used anywhere in the kernel, so remove it. Done using Coccinelle. @r1@ identifier func; type T; @@ static T func(...) { ... } @r@ identifier r1.func; @@ func @delete depends on !r@ identifier r1.func; type r1.T; @@ - static T func(...){...} Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 49c718b91e55..41a49c8194e5 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -1667,12 +1667,6 @@ static inline void fill_plug_rsp_nack(struct fwserial_mgmt_pkt *pkt) pkt->hdr.len = cpu_to_be16(mgmt_pkt_expected_len(pkt->hdr.code)); } -static inline void fill_unplug_req(struct fwserial_mgmt_pkt *pkt) -{ - pkt->hdr.code = cpu_to_be16(FWSC_VIRT_CABLE_UNPLUG); - pkt->hdr.len = cpu_to_be16(mgmt_pkt_expected_len(pkt->hdr.code)); -} - static inline void fill_unplug_rsp_nack(struct fwserial_mgmt_pkt *pkt) { pkt->hdr.code = cpu_to_be16(FWSC_VIRT_CABLE_UNPLUG_RSP | FWSC_RSP_NACK); -- cgit v1.2.3 From 7b518be47dffd1d3c91216f726667d58f1609b96 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:12 +0200 Subject: staging: most: core: remove member add_link This patch removes the unused field add_link of struct most_aim_obj. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 329109c0024f..9c15b63c0864 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -763,7 +763,6 @@ struct most_aim_obj { struct kobject kobj; struct list_head list; struct most_aim *driver; - char add_link[STRING_SIZE]; char remove_link[STRING_SIZE]; }; @@ -984,7 +983,6 @@ static ssize_t store_add_link(struct most_aim_obj *aim_obj, size_t max_len = min_t(size_t, len + 1, STRING_SIZE); strlcpy(buffer, buf, max_len); - strlcpy(aim_obj->add_link, buf, max_len); ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod); if (ret) -- cgit v1.2.3 From 931161b7141eba7c11e023051de96460ffbfe84e Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:13 +0200 Subject: staging: most: core: remove read option from remove_link The attribute "remove_link" returns the latest link that has been removed of a certain channel. Since this piece information isn't particulary useful this patch is going to remove it. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 9c15b63c0864..6507263410bd 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -763,7 +763,6 @@ struct most_aim_obj { struct kobject kobj; struct list_head list; struct most_aim *driver; - char remove_link[STRING_SIZE]; }; #define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj) @@ -1019,13 +1018,6 @@ static ssize_t store_add_link(struct most_aim_obj *aim_obj, static struct most_aim_attribute most_aim_attr_add_link = __ATTR(add_link, S_IRUGO | S_IWUSR, show_add_link, store_add_link); -static ssize_t show_remove_link(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->remove_link); -} - /** * store_remove_link - store function for remove_link attribute * @aim_obj: pointer to AIM object @@ -1049,7 +1041,6 @@ static ssize_t store_remove_link(struct most_aim_obj *aim_obj, size_t max_len = min_t(size_t, len + 1, STRING_SIZE); strlcpy(buffer, buf, max_len); - strlcpy(aim_obj->remove_link, buf, max_len); ret = split_string(buffer, &mdev, &mdev_ch, NULL); if (ret) return ret; @@ -1068,8 +1059,7 @@ static ssize_t store_remove_link(struct most_aim_obj *aim_obj, } static struct most_aim_attribute most_aim_attr_remove_link = - __ATTR(remove_link, S_IRUGO | S_IWUSR, show_remove_link, - store_remove_link); + __ATTR(remove_link, S_IWUSR, NULL, store_remove_link); static struct attribute *most_aim_def_attrs[] = { &most_aim_attr_add_link.attr, -- cgit v1.2.3 From 5d7df3ae4c4d6c7456b8d302ea41fa75c3ccc806 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:14 +0200 Subject: staging: most: core: remove processing of deprecated names The USB HDM does not use the "@" character for channel names anymore. This patch cleans up the code processing such names and adapts the corresponding examples on how to use the properties "add_link" and "remove_link". Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 6507263410bd..835a5871fa6d 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -883,16 +883,16 @@ static ssize_t show_add_link(struct most_aim_obj *aim_obj, * * Examples: * - * Input: "mdev0:ch0@ep_81:my_channel\n" or - * "mdev0:ch0@ep_81:my_channel" + * Input: "mdev0:ch6:my_channel\n" or + * "mdev0:ch6:my_channel" * - * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c -> "my_channel" + * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel" * - * Input: "mdev0:ch0@ep_81\n" - * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c -> "" + * Input: "mdev1:ep81\n" + * Output: *a -> "mdev1", *b -> "ep81", *c -> "" * - * Input: "mdev0:ch0@ep_81" - * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c == NULL + * Input: "mdev1:ep81" + * Output: *a -> "mdev1", *b -> "ep81", *c == NULL */ static int split_string(char *buf, char **a, char **b, char **c) { @@ -960,11 +960,11 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) * Searches for a pair of device and channel and probes the AIM * * Example: - * (1) echo -n -e "mdev0:ch0@ep_81:my_rxchannel\n" >add_link - * (2) echo -n -e "mdev0:ch0@ep_81\n" >add_link + * (1) echo -n -e "mdev0:ch6:my_rxchannel\n" >add_link + * (2) echo -n -e "mdev1:ep81\n" >add_link * * (1) would create the device node /dev/my_rxchannel - * (2) would create the device node /dev/mdev0-ch0@ep_81 + * (2) would create the device node /dev/mdev1-ep81 */ static ssize_t store_add_link(struct most_aim_obj *aim_obj, struct most_aim_attribute *attr, @@ -1026,7 +1026,7 @@ static struct most_aim_attribute most_aim_attr_add_link = * @len: buffer length * * Example: - * echo -n -e "mdev0:ch0@ep_81\n" >remove_link + * echo -n -e "mdev0:ep81\n" >remove_link */ static ssize_t store_remove_link(struct most_aim_obj *aim_obj, struct most_aim_attribute *attr, @@ -1749,9 +1749,6 @@ struct kobject *most_register_interface(struct most_interface *iface) if (!name_suffix) snprintf(channel_name, STRING_SIZE, "ch%d", i); - else if (name_suffix[0] == '@') - snprintf(channel_name, STRING_SIZE, "ch%d%s", i, - name_suffix); else snprintf(channel_name, STRING_SIZE, "%s", name_suffix); -- cgit v1.2.3 From eefb2a845ca944f28ec891d0090cdbaf0e0ee73e Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:15 +0200 Subject: staging: most: core: update examples on how to link channels This patch updates the comments with examples on how to use the "add_link" and "remove_link" properties. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 835a5871fa6d..4c580d1a6a46 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -960,8 +960,8 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) * Searches for a pair of device and channel and probes the AIM * * Example: - * (1) echo -n -e "mdev0:ch6:my_rxchannel\n" >add_link - * (2) echo -n -e "mdev1:ep81\n" >add_link + * (1) echo "mdev0:ch6:my_rxchannel" >add_link + * (2) echo "mdev1:ep81" >add_link * * (1) would create the device node /dev/my_rxchannel * (2) would create the device node /dev/mdev1-ep81 @@ -1026,7 +1026,7 @@ static struct most_aim_attribute most_aim_attr_add_link = * @len: buffer length * * Example: - * echo -n -e "mdev0:ep81\n" >remove_link + * echo "mdev0:ep81" >remove_link */ static ssize_t store_remove_link(struct most_aim_obj *aim_obj, struct most_aim_attribute *attr, -- cgit v1.2.3 From 553a42e51a3be67cf5355024fa6954766c79feb4 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:16 +0200 Subject: staging: most: aim-network: fix startup scenario. In case the networking interface (running on MediaLB) is being started before the MOST network is, it remains disabled even after the MOST network has transitioned to active mode. This patch removes the dependency on the MOST link status to keep the networking queue active and the networking interface working for the case described above. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-network/networking.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 4659a6450c04..5728270a2341 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -67,7 +67,6 @@ struct net_dev_context { struct most_interface *iface; bool channels_opened; bool is_mamac; - unsigned char link_stat; struct net_device *dev; struct net_dev_channel rx; struct net_dev_channel tx; @@ -203,13 +202,10 @@ static int most_nd_open(struct net_device *dev) } nd->channels_opened = true; + netif_wake_queue(dev); - if (nd->is_mamac) { - nd->link_stat = 1; - netif_wake_queue(dev); - } else { + if (!nd->is_mamac) nd->iface->request_netinfo(nd->iface, nd->tx.ch_id); - } return 0; } @@ -561,14 +557,6 @@ void most_deliver_netinfo(struct most_interface *iface, if (mac_addr) ether_addr_copy(dev->dev_addr, mac_addr); - - if (nd->link_stat != link_stat) { - nd->link_stat = link_stat; - if (nd->link_stat) - netif_wake_queue(dev); - else - netif_stop_queue(dev); - } } EXPORT_SYMBOL(most_deliver_netinfo); -- cgit v1.2.3 From 81ad5207862db73e64f6439efa47d259ff4a60a7 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:17 +0200 Subject: staging: most: aim-network: setup mac address before ifup has finished The networking AIM implements a non-standard behavior as it starts the networking interface with an invalid MAC address and changes it by the time a valid one is available. This patch introduces a completion object to set the MAC address of the networking interface before the .ndo_open callback (ifup) of the net_device returns. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-network/networking.c | 36 ++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 5728270a2341..9e1b19b9f64b 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -70,6 +70,7 @@ struct net_dev_context { struct net_device *dev; struct net_dev_channel rx; struct net_dev_channel tx; + struct completion mac_compl; struct list_head list; }; @@ -180,6 +181,7 @@ static int most_nd_set_mac_address(struct net_device *dev, void *p) static int most_nd_open(struct net_device *dev) { struct net_dev_context *nd = dev->ml_priv; + long wait_res; netdev_info(dev, "open net device\n"); @@ -204,8 +206,21 @@ static int most_nd_open(struct net_device *dev) nd->channels_opened = true; netif_wake_queue(dev); - if (!nd->is_mamac) - nd->iface->request_netinfo(nd->iface, nd->tx.ch_id); + if (is_valid_ether_addr(dev->dev_addr)) + return 0; + + nd->iface->request_netinfo(nd->iface, nd->tx.ch_id); + wait_res = wait_for_completion_interruptible_timeout( + &nd->mac_compl, msecs_to_jiffies(5000)); + if (!wait_res) { + netdev_err(dev, "mac timeout\n"); + return -EBUSY; + } + + if (wait_res < 0) { + netdev_warn(dev, "mac waiting interrupted\n"); + return wait_res; + } return 0; } @@ -328,6 +343,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, if (!nd) return -ENOMEM; + init_completion(&nd->mac_compl); nd->iface = iface; spin_lock_irqsave(&list_lock, flags); @@ -544,8 +560,7 @@ void most_deliver_netinfo(struct most_interface *iface, { struct net_dev_context *nd; struct net_device *dev; - - pr_info("Received netinfo from %s\n", iface->description); + const u8 *m = mac_addr; nd = get_net_dev_context(iface); if (!nd) @@ -555,8 +570,17 @@ void most_deliver_netinfo(struct most_interface *iface, if (!dev) return; - if (mac_addr) - ether_addr_copy(dev->dev_addr, mac_addr); + if (m && is_valid_ether_addr(m)) { + if (!is_valid_ether_addr(dev->dev_addr)) { + netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n", + m[0], m[1], m[2], m[3], m[4], m[5]); + ether_addr_copy(dev->dev_addr, m); + complete(&nd->mac_compl); + } else if (!ether_addr_equal(dev->dev_addr, m)) { + netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n", + m[0], m[1], m[2], m[3], m[4], m[5]); + } + } } EXPORT_SYMBOL(most_deliver_netinfo); -- cgit v1.2.3 From 812b55e531541d210e66962200f3a2c1429d3413 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:18 +0200 Subject: staging: most: aim-network: avoid calling netdev_info() This patch removes the needless call of function netdev_info() from function most_nd_setup(). Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-network/networking.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 9e1b19b9f64b..fe0d516cf506 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -211,7 +211,7 @@ static int most_nd_open(struct net_device *dev) nd->iface->request_netinfo(nd->iface, nd->tx.ch_id); wait_res = wait_for_completion_interruptible_timeout( - &nd->mac_compl, msecs_to_jiffies(5000)); + &nd->mac_compl, msecs_to_jiffies(5000)); if (!wait_res) { netdev_err(dev, "mac timeout\n"); return -EBUSY; @@ -288,7 +288,6 @@ static const struct net_device_ops most_nd_ops = { static void most_nd_setup(struct net_device *dev) { - netdev_info(dev, "setup net device\n"); ether_setup(dev); dev->netdev_ops = &most_nd_ops; } -- cgit v1.2.3 From f28e6cd3ac888c705e50e3415ab0bd3950117bdb Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:19 +0200 Subject: staging: most: hdm-usb: remove filtering of networking state In case the networking interface goes down and up again, the USB HDM does not report the state the MOST networking interface controller is in. This might lead to nonfunctional network. Since the networking AIM already takes care of hardware address checking and tracing it can be removed from the HDM USB, which is what this patch is doing. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-usb/hdm_usb.c | 104 ++++++++++----------------------- 1 file changed, 32 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 26c9adb29308..70e58c42a36c 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -97,9 +97,7 @@ struct clear_hold_work { * @cap: channel capabilities * @conf: channel configuration * @dci: direct communication interface of hardware - * @hw_addr: MAC address of hardware * @ep_address: endpoint address table - * @link_stat: link status of hardware * @description: device description * @suffix: suffix for channel name * @channel_lock: synchronize channel access @@ -117,9 +115,7 @@ struct most_dev { struct most_channel_capability *cap; struct most_channel_config *conf; struct most_dci_obj *dci; - u8 hw_addr[6]; u8 *ep_address; - u16 link_stat; char description[MAX_STRING_LEN]; char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN]; spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */ @@ -737,56 +733,6 @@ exit: return 0; } -/** - * hdm_update_netinfo - retrieve latest networking information - * @mdev: device interface - * - * This triggers the USB vendor requests to read the hardware address and - * the current link status of the attached device. - */ -static int hdm_update_netinfo(struct most_dev *mdev) -{ - struct usb_device *usb_device = mdev->usb_device; - struct device *dev = &usb_device->dev; - u16 hi, mi, lo, link; - - if (!is_valid_ether_addr(mdev->hw_addr)) { - if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) { - dev_err(dev, "Vendor request \"hw_addr_hi\" failed\n"); - return -EFAULT; - } - - if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) { - dev_err(dev, "Vendor request \"hw_addr_mid\" failed\n"); - return -EFAULT; - } - - if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) { - dev_err(dev, "Vendor request \"hw_addr_low\" failed\n"); - return -EFAULT; - } - - mutex_lock(&mdev->io_mutex); - mdev->hw_addr[0] = hi >> 8; - mdev->hw_addr[1] = hi; - mdev->hw_addr[2] = mi >> 8; - mdev->hw_addr[3] = mi; - mdev->hw_addr[4] = lo >> 8; - mdev->hw_addr[5] = lo; - mutex_unlock(&mdev->io_mutex); - } - - if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) { - dev_err(dev, "Vendor request \"link status\" failed\n"); - return -EFAULT; - } - - mutex_lock(&mdev->io_mutex); - mdev->link_stat = link; - mutex_unlock(&mdev->io_mutex); - return 0; -} - /** * hdm_request_netinfo - request network information * @iface: pointer to interface @@ -807,7 +753,7 @@ static void hdm_request_netinfo(struct most_interface *iface, int channel) } /** - * link_stat_timer_handler - add work to link_stat work queue + * link_stat_timer_handler - schedule work obtaining mac address and link status * @data: pointer to USB device instance * * The handler runs in interrupt context. That's why we need to defer the @@ -823,33 +769,47 @@ static void link_stat_timer_handler(unsigned long data) } /** - * wq_netinfo - work queue function + * wq_netinfo - work queue function to deliver latest networking information * @wq_obj: object that holds data for our deferred work to do * * This retrieves the network interface status of the USB INIC - * and compares it with the current status. If the status has - * changed, it updates the status of the core. */ static void wq_netinfo(struct work_struct *wq_obj) { struct most_dev *mdev = to_mdev_from_work(wq_obj); - int i, prev_link_stat = mdev->link_stat; - u8 prev_hw_addr[6]; + struct usb_device *usb_device = mdev->usb_device; + struct device *dev = &usb_device->dev; + u16 hi, mi, lo, link; + u8 hw_addr[6]; - for (i = 0; i < 6; i++) - prev_hw_addr[i] = mdev->hw_addr[i]; + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) { + dev_err(dev, "Vendor request 'hw_addr_hi' failed\n"); + return; + } - if (hdm_update_netinfo(mdev) < 0) + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) { + dev_err(dev, "Vendor request 'hw_addr_mid' failed\n"); return; - if (prev_link_stat != mdev->link_stat || - prev_hw_addr[0] != mdev->hw_addr[0] || - prev_hw_addr[1] != mdev->hw_addr[1] || - prev_hw_addr[2] != mdev->hw_addr[2] || - prev_hw_addr[3] != mdev->hw_addr[3] || - prev_hw_addr[4] != mdev->hw_addr[4] || - prev_hw_addr[5] != mdev->hw_addr[5]) - most_deliver_netinfo(&mdev->iface, mdev->link_stat, - &mdev->hw_addr[0]); + } + + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) { + dev_err(dev, "Vendor request 'hw_addr_low' failed\n"); + return; + } + + if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) { + dev_err(dev, "Vendor request 'link status' failed\n"); + return; + } + + hw_addr[0] = hi >> 8; + hw_addr[1] = hi; + hw_addr[2] = mi >> 8; + hw_addr[3] = mi; + hw_addr[4] = lo >> 8; + hw_addr[5] = lo; + + most_deliver_netinfo(&mdev->iface, link, hw_addr); } /** -- cgit v1.2.3 From 02245b607718c8cd9c977f41637c9efff6493375 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:20 +0200 Subject: staging: most: hdm-dim2: remove tracing of mac address This patch removes tracing of the MAC address from the DIM2 HDM as it is already done in the networking AIM. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-dim2/dim2_hdm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 78b2c3dd9bb3..35aee9fbbf02 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -306,14 +306,11 @@ static int deliver_netinfo_thread(void *data) static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo) { u8 *data = mbo->virt_address; - u8 *mac = dev->mac_addrs; pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]); dev->link_state = data[18]; pr_info("NIState: %d\n", dev->link_state); - memcpy(mac, data + 19, 6); - pr_info("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + memcpy(dev->mac_addrs, data + 19, 6); dev->deliver_netinfo++; wake_up_interruptible(&dev->netinfo_waitq); } -- cgit v1.2.3 From 3a542007fdd4e1a387f390eb5b2b0a4ad3c372c7 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 4 Oct 2016 17:10:21 +0200 Subject: staging: most: hdm-usb: fix mbo buffer leak This patch fixes an MBO leak by replacing the proprietary free_anchored_buffers() function with the usb_kill_anchored_urbs() function of the USB subsystem and guarantees that the mbo->complete() completion function is being called for each URB. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-usb/hdm_usb.c | 85 ++++++++++------------------------ 1 file changed, 25 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 70e58c42a36c..1a630e1b9392 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -182,30 +182,6 @@ static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) 5 * HZ); } -/** - * free_anchored_buffers - free device's anchored items - * @mdev: the device - * @channel: channel ID - * @status: status of MBO termination - */ -static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, - enum mbo_status_flags status) -{ - struct mbo *mbo; - struct urb *urb; - - while ((urb = usb_get_from_anchor(&mdev->busy_urbs[channel]))) { - mbo = urb->context; - usb_kill_urb(urb); - if (mbo && mbo->complete) { - mbo->status = status; - mbo->processed_length = 0; - mbo->complete(mbo); - } - usb_free_urb(urb); - } -} - /** * get_stream_frame_size - calculate frame size of current configuration * @cfg: channel configuration @@ -274,7 +250,7 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) cancel_work_sync(&mdev->clear_work[channel].ws); mutex_lock(&mdev->io_mutex); - free_anchored_buffers(mdev, channel, MBO_E_CLOSE); + usb_kill_anchored_urbs(&mdev->busy_urbs[channel]); if (mdev->padding_active[channel]) mdev->padding_active[channel] = false; @@ -373,33 +349,27 @@ static void hdm_write_completion(struct urb *urb) unsigned long flags; spin_lock_irqsave(lock, flags); - if (urb->status == -ENOENT || urb->status == -ECONNRESET || - !mdev->is_channel_healthy[channel]) { - spin_unlock_irqrestore(lock, flags); - return; - } - if (unlikely(urb->status && urb->status != -ESHUTDOWN)) { - mbo->processed_length = 0; + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + if (likely(mdev->is_channel_healthy[channel])) { switch (urb->status) { + case 0: + case -ESHUTDOWN: + mbo->processed_length = urb->actual_length; + mbo->status = MBO_SUCCESS; + break; case -EPIPE: dev_warn(dev, "Broken OUT pipe detected\n"); mdev->is_channel_healthy[channel] = false; - spin_unlock_irqrestore(lock, flags); mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); - return; + break; case -ENODEV: case -EPROTO: mbo->status = MBO_E_CLOSE; break; - default: - mbo->status = MBO_E_INVAL; - break; } - } else { - mbo->status = MBO_SUCCESS; - mbo->processed_length = urb->actual_length; } spin_unlock_irqrestore(lock, flags); @@ -527,40 +497,35 @@ static void hdm_read_completion(struct urb *urb) unsigned long flags; spin_lock_irqsave(lock, flags); - if (urb->status == -ENOENT || urb->status == -ECONNRESET || - !mdev->is_channel_healthy[channel]) { - spin_unlock_irqrestore(lock, flags); - return; - } - if (unlikely(urb->status && urb->status != -ESHUTDOWN)) { - mbo->processed_length = 0; + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + if (likely(mdev->is_channel_healthy[channel])) { switch (urb->status) { + case 0: + case -ESHUTDOWN: + mbo->processed_length = urb->actual_length; + mbo->status = MBO_SUCCESS; + if (mdev->padding_active[channel] && + hdm_remove_padding(mdev, channel, mbo)) { + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + } + break; case -EPIPE: dev_warn(dev, "Broken IN pipe detected\n"); mdev->is_channel_healthy[channel] = false; - spin_unlock_irqrestore(lock, flags); mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); - return; + break; case -ENODEV: case -EPROTO: mbo->status = MBO_E_CLOSE; break; case -EOVERFLOW: dev_warn(dev, "Babble on IN pipe detected\n"); - default: - mbo->status = MBO_E_INVAL; break; } - } else { - mbo->processed_length = urb->actual_length; - mbo->status = MBO_SUCCESS; - if (mdev->padding_active[channel] && - hdm_remove_padding(mdev, channel, mbo)) { - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - } } spin_unlock_irqrestore(lock, flags); @@ -827,7 +792,7 @@ static void wq_clear_halt(struct work_struct *wq_obj) mutex_lock(&mdev->io_mutex); most_stop_enqueue(&mdev->iface, channel); - free_anchored_buffers(mdev, channel, MBO_E_INVAL); + usb_kill_anchored_urbs(&mdev->busy_urbs[channel]); if (usb_clear_halt(mdev->usb_device, pipe)) dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); -- cgit v1.2.3 From bb5cd2e531c03e9b0e4bd42ca682b5a7e845ce76 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:00 +0700 Subject: staging:r8188eu: remove rtw_os_recv_resource_alloc function This simple function does not allocate any resource. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 3 +-- drivers/staging/rtl8188eu/include/recv_osdep.h | 2 -- drivers/staging/rtl8188eu/os_dep/recv_linux.c | 6 ------ 3 files changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index b87cbbbee054..65ae11ed6b7c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -83,8 +83,7 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) list_add_tail(&(precvframe->list), &(precvpriv->free_recv_queue.queue)); - rtw_os_recv_resource_alloc(precvframe); - + precvframe->pkt = NULL; precvframe->len = 0; precvframe->adapter = padapter; diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h index 7550d58f6b5b..9b43a1314bd5 100644 --- a/drivers/staging/rtl8188eu/include/recv_osdep.h +++ b/drivers/staging/rtl8188eu/include/recv_osdep.h @@ -29,8 +29,6 @@ int rtw_recv_indicatepkt(struct adapter *adapter, void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup); -void rtw_os_recv_resource_alloc(struct recv_frame *recvfr); - int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf); void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl); diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c index 103cdb4ed073..b85824ec5354 100644 --- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c @@ -21,12 +21,6 @@ #include #include -/* alloc os related resource in struct recv_frame */ -void rtw_os_recv_resource_alloc(struct recv_frame *precvframe) -{ - precvframe->pkt = NULL; -} - /* alloc os related resource in struct recv_buf */ int rtw_os_recvbuf_resource_alloc(struct adapter *padapter, struct recv_buf *precvbuf) -- cgit v1.2.3 From 4f1ca4d093981abd31eeaf9637df5c03c1b38af5 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:01 +0700 Subject: staging:r8188eu: remove wrappers for rtw_hal_inirp_init function There is no reason to use these wrappers. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/drv_types.h | 1 - drivers/staging/rtl8188eu/os_dep/os_intfs.c | 6 ++---- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 10 ---------- 3 files changed, 2 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 32326fd1dd24..5eb56b1281d2 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -156,7 +156,6 @@ struct adapter { u8 hw_init_completed; void *cmdThread; - void (*intf_start)(struct adapter *adapter); void (*intf_stop)(struct adapter *adapter); struct net_device *pnetdev; struct net_device *pmondev; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 40691f1ec507..8d96e51bd4c7 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -596,8 +596,7 @@ static int _netdev_open(struct net_device *pnetdev) pr_info("can't init mlme_ext_priv\n"); goto netdev_open_error; } - if (padapter->intf_start) - padapter->intf_start(padapter); + rtw_hal_inirp_init(padapter); rtw_led_control(padapter, LED_CTL_NO_LINK); @@ -658,8 +657,7 @@ static int ips_netdrv_open(struct adapter *padapter) goto netdev_open_error; } - if (padapter->intf_start) - padapter->intf_start(padapter); + rtw_hal_inirp_init(padapter); rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); mod_timer(&padapter->mlmepriv.dynamic_chk_timer, diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 68e1e6bbe87f..49963327b0c8 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -141,15 +141,6 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf) } -static void usb_intf_start(struct adapter *padapter) -{ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_start\n")); - - rtw_hal_inirp_init(padapter); - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_start\n")); -} - static void usb_intf_stop(struct adapter *padapter) { RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n")); @@ -366,7 +357,6 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, if (!padapter->HalData) DBG_88E("cant not alloc memory for HAL DATA\n"); - padapter->intf_start = &usb_intf_start; padapter->intf_stop = &usb_intf_stop; /* step read_chip_version */ -- cgit v1.2.3 From b091c6b6ff7940671b41c2e81baca6da3b26cc82 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:02 +0700 Subject: staging:r8188eu: remove pm_netdev_open function netdev_open and ips_netdrv_open are used instead of pm_netdev_open. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_pwrctrl.c | 2 +- drivers/staging/rtl8188eu/include/osdep_intf.h | 3 ++- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 16 ++-------------- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 2 +- 4 files changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index 0b70fe7d3b72..fc6385bc8a54 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -94,7 +94,7 @@ static int rtw_hw_resume(struct adapter *padapter) pwrpriv->bips_processing = true; rtw_reset_drv_sw(padapter); - if (pm_netdev_open(pnetdev, false) != 0) { + if (ips_netdrv_open((struct adapter *)rtw_netdev_priv(pnetdev)) != _SUCCESS) { mutex_unlock(&pwrpriv->mutex_lock); goto error_exit; } diff --git a/drivers/staging/rtl8188eu/include/osdep_intf.h b/drivers/staging/rtl8188eu/include/osdep_intf.h index dbd7dc4f87dd..97d3d8504184 100644 --- a/drivers/staging/rtl8188eu/include/osdep_intf.h +++ b/drivers/staging/rtl8188eu/include/osdep_intf.h @@ -35,7 +35,8 @@ int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname); struct net_device *rtw_init_netdev(struct adapter *padapter); u16 rtw_recv_select_queue(struct sk_buff *skb); -int pm_netdev_open(struct net_device *pnetdev, u8 bnormal); +int netdev_open(struct net_device *pnetdev); +int ips_netdrv_open(struct adapter *padapter); void rtw_ips_dev_unload(struct adapter *padapter); int rtw_ips_pwr_up(struct adapter *padapter); void rtw_ips_pwr_down(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 8d96e51bd4c7..2a1e63de7d15 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -144,7 +144,6 @@ static bool rtw_monitor_enable; module_param_named(monitor_enable, rtw_monitor_enable, bool, 0444); MODULE_PARM_DESC(monitor_enable, "Enable monitor inferface (default: false)"); -static int netdev_open(struct net_device *pnetdev); static int netdev_close(struct net_device *pnetdev); static void loadparam(struct adapter *padapter, struct net_device *pnetdev) @@ -629,7 +628,7 @@ netdev_open_error: return -1; } -static int netdev_open(struct net_device *pnetdev) +int netdev_open(struct net_device *pnetdev) { int ret; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); @@ -641,7 +640,7 @@ static int netdev_open(struct net_device *pnetdev) return ret; } -static int ips_netdrv_open(struct adapter *padapter) +int ips_netdrv_open(struct adapter *padapter) { int status = _SUCCESS; @@ -718,17 +717,6 @@ void rtw_ips_dev_unload(struct adapter *padapter) rtw_hal_deinit(padapter); } -int pm_netdev_open(struct net_device *pnetdev, u8 bnormal) -{ - int status; - - if (bnormal) - status = netdev_open(pnetdev); - else - status = (_SUCCESS == ips_netdrv_open((struct adapter *)rtw_netdev_priv(pnetdev))) ? (0) : (-1); - return status; -} - static int netdev_close(struct net_device *pnetdev) { struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 49963327b0c8..94dac53a48b7 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -285,7 +285,7 @@ static int rtw_resume_process(struct adapter *padapter) pwrpriv->bkeepfwalive = false; pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive); - if (pm_netdev_open(pnetdev, true) != 0) { + if (netdev_open(pnetdev) != 0) { mutex_unlock(&pwrpriv->mutex_lock); goto exit; } -- cgit v1.2.3 From 72e8072a1d5640a60bcf7f2b8d11336fe9f4e256 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:03 +0700 Subject: staging:r8188eu: remove free_recv_buf_queue_cnt member of recv_priv structure This variable does not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c | 1 - drivers/staging/rtl8188eu/hal/usb_halinit.c | 1 - drivers/staging/rtl8188eu/include/rtw_recv.h | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index d0495a16ff79..67a765ae5c28 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -58,7 +58,6 @@ int rtw_hal_init_recv_priv(struct adapter *padapter) precvbuf->adapter = padapter; precvbuf++; } - precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF; skb_queue_head_init(&precvpriv->rx_skb_queue); { int i; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 7692ca495ee5..a09c68fa417a 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1006,7 +1006,6 @@ u32 rtw_hal_inirp_init(struct adapter *Adapter) } precvbuf++; - precvpriv->free_recv_buf_queue_cnt--; } exit: diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index 49d973881a04..a8874a2768c2 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -186,7 +186,6 @@ struct recv_priv { u8 *pallocated_recv_buf; u8 *precv_buf; /* 4 alignment */ struct __queue free_recv_buf_queue; - u32 free_recv_buf_queue_cnt; /* For display the phy informatiom */ u8 is_signal_dbg; /* for debug */ u8 signal_strength_dbg; /* for debug */ -- cgit v1.2.3 From 49cb9d47780b765d27943bc8f3d71230e623b07d Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:04 +0700 Subject: staging:r8188eu: remove skb data alignment in r8188eu driver code (__)netdev_alloc_skb align skb data. Also this function set skb device. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c | 10 +--------- drivers/staging/rtl8188eu/include/rtw_recv.h | 2 -- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 8 +------- 3 files changed, 2 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index 67a765ae5c28..1c7a9a084b49 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -61,23 +61,15 @@ int rtw_hal_init_recv_priv(struct adapter *padapter) skb_queue_head_init(&precvpriv->rx_skb_queue); { int i; - size_t tmpaddr = 0; - size_t alignm = 0; struct sk_buff *pskb = NULL; skb_queue_head_init(&precvpriv->free_recv_skb_queue); for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) { pskb = __netdev_alloc_skb(padapter->pnetdev, - MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, - GFP_KERNEL); + MAX_RECVBUF_SZ, GFP_KERNEL); if (pskb) { kmemleak_not_leak(pskb); - pskb->dev = padapter->pnetdev; - tmpaddr = (size_t)pskb->data; - alignm = tmpaddr & (RECVBUFF_ALIGN_SZ-1); - skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignm)); - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); } diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index a8874a2768c2..c8688639860e 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -139,8 +139,6 @@ struct rx_pkt_attrib { #define SN_EQUAL(a, b) (a == b) #define REORDER_WAIT_TIME (50) /* (ms) */ -#define RECVBUFF_ALIGN_SZ 8 - #define RXDESC_SIZE 24 #define RXDESC_OFFSET RXDESC_SIZE diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index d0d591501b73..b82048229ce4 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -457,8 +457,6 @@ u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *rmem) struct usb_device *pusbd = pdvobj->pusbdev; int err; unsigned int pipe; - size_t tmpaddr = 0; - size_t alignment = 0; u32 ret = _SUCCESS; @@ -483,16 +481,12 @@ u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *rmem) /* re-assign for linux based on skb */ if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) { - precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); + precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ); if (precvbuf->pskb == NULL) { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n")); DBG_88E("#### usb_read_port() alloc_skb fail!#####\n"); return _FAIL; } - - tmpaddr = (size_t)precvbuf->pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); - skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); } else { /* reuse skb */ precvbuf->reuse = false; } -- cgit v1.2.3 From 181e61440dd094e6ab4cdce7acf5e6fd73d84445 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:05 +0700 Subject: staging:r8188eu: change usb_read_port last argument type to (struct *recv_buf) To avoid unnecessary typecasts. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- drivers/staging/rtl8188eu/include/usb_ops_linux.h | 2 +- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index a09c68fa417a..4d0e3f99ac33 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -999,7 +999,7 @@ u32 rtw_hal_inirp_init(struct adapter *Adapter) /* issue Rx irp to receive data */ precvbuf = (struct recv_buf *)precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { - if (usb_read_port(Adapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf) == false) { + if (usb_read_port(Adapter, precvpriv->ff_hwaddr, 0, precvbuf) == false) { RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("usb_rx_init: usb_read_port error\n")); status = _FAIL; goto exit; diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h index 78d9b6e035bf..4fc2e2db2af1 100644 --- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h +++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h @@ -53,7 +53,7 @@ u8 usb_read8(struct adapter *adapter, u32 addr); u16 usb_read16(struct adapter *adapter, u32 addr); u32 usb_read32(struct adapter *adapter, u32 addr); -u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); +u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, struct recv_buf *precvbuf); void usb_read_port_cancel(struct adapter *adapter); int usb_write8(struct adapter *adapter, u32 addr, u8 val); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index b82048229ce4..22777b1ee9ba 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -403,7 +403,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n")); precvbuf->reuse = true; - usb_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); + usb_read_port(adapt, precvpriv->ff_hwaddr, 0, precvbuf); DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__); } else { skb_put(precvbuf->pskb, purb->actual_length); @@ -414,7 +414,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) precvbuf->pskb = NULL; precvbuf->reuse = false; - usb_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); + usb_read_port(adapt, precvpriv->ff_hwaddr, 0, precvbuf); } } else { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete : purb->status(%d) != 0\n", purb->status)); @@ -437,7 +437,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) case -EOVERFLOW: adapt->HalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL; precvbuf->reuse = true; - usb_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); + usb_read_port(adapt, precvpriv->ff_hwaddr, 0, precvbuf); break; case -EINPROGRESS: DBG_88E("ERROR: URB IS IN PROGRESS!\n"); @@ -448,10 +448,9 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) } } -u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *rmem) +u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, struct recv_buf *precvbuf) { struct urb *purb = NULL; - struct recv_buf *precvbuf = (struct recv_buf *)rmem; struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter); struct recv_priv *precvpriv = &adapter->recvpriv; struct usb_device *pusbd = pdvobj->pusbdev; -- cgit v1.2.3 From dbddb97ec1e090d7fd28611233e3b451da991a6c Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:06 +0700 Subject: staging:r8188eu: remove (u32 cnt) argument of usb_read_port function This argument does not used by usb_read_port function. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- drivers/staging/rtl8188eu/include/usb_ops_linux.h | 2 +- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 4d0e3f99ac33..95bbecaeb50f 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -999,7 +999,7 @@ u32 rtw_hal_inirp_init(struct adapter *Adapter) /* issue Rx irp to receive data */ precvbuf = (struct recv_buf *)precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { - if (usb_read_port(Adapter, precvpriv->ff_hwaddr, 0, precvbuf) == false) { + if (usb_read_port(Adapter, precvpriv->ff_hwaddr, precvbuf) == false) { RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("usb_rx_init: usb_read_port error\n")); status = _FAIL; goto exit; diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h index 4fc2e2db2af1..fb586365d2e5 100644 --- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h +++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h @@ -53,7 +53,7 @@ u8 usb_read8(struct adapter *adapter, u32 addr); u16 usb_read16(struct adapter *adapter, u32 addr); u32 usb_read32(struct adapter *adapter, u32 addr); -u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, struct recv_buf *precvbuf); +u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf); void usb_read_port_cancel(struct adapter *adapter); int usb_write8(struct adapter *adapter, u32 addr, u8 val); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 22777b1ee9ba..24d22500532a 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -403,7 +403,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n")); precvbuf->reuse = true; - usb_read_port(adapt, precvpriv->ff_hwaddr, 0, precvbuf); + usb_read_port(adapt, precvpriv->ff_hwaddr, precvbuf); DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__); } else { skb_put(precvbuf->pskb, purb->actual_length); @@ -414,7 +414,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) precvbuf->pskb = NULL; precvbuf->reuse = false; - usb_read_port(adapt, precvpriv->ff_hwaddr, 0, precvbuf); + usb_read_port(adapt, precvpriv->ff_hwaddr, precvbuf); } } else { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete : purb->status(%d) != 0\n", purb->status)); @@ -437,7 +437,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) case -EOVERFLOW: adapt->HalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL; precvbuf->reuse = true; - usb_read_port(adapt, precvpriv->ff_hwaddr, 0, precvbuf); + usb_read_port(adapt, precvpriv->ff_hwaddr, precvbuf); break; case -EINPROGRESS: DBG_88E("ERROR: URB IS IN PROGRESS!\n"); @@ -448,7 +448,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) } } -u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, struct recv_buf *precvbuf) +u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf) { struct urb *purb = NULL; struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter); -- cgit v1.2.3 From cbc63fdc2883f9431ea5239220eaf78a929042e7 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:07 +0700 Subject: staging:r8188eu: remove ff_hwaddr member of recv_priv structure Its value used instead. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 4 +--- drivers/staging/rtl8188eu/include/rtw_recv.h | 1 - drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 6 +++--- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 95bbecaeb50f..dfb78bbdf6c6 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -994,12 +994,10 @@ u32 rtw_hal_inirp_init(struct adapter *Adapter) RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("===> usb_inirp_init\n")); - precvpriv->ff_hwaddr = RECV_BULK_IN_ADDR; - /* issue Rx irp to receive data */ precvbuf = (struct recv_buf *)precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { - if (usb_read_port(Adapter, precvpriv->ff_hwaddr, precvbuf) == false) { + if (usb_read_port(Adapter, RECV_BULK_IN_ADDR, precvbuf) == false) { RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("usb_rx_init: usb_read_port error\n")); status = _FAIL; goto exit; diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index c8688639860e..e871ebbdb95a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -174,7 +174,6 @@ struct recv_priv { u64 rx_drop; u64 last_rx_bytes; - uint ff_hwaddr; u8 rx_pending_cnt; struct tasklet_struct irq_prepare_beacon_tasklet; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 24d22500532a..175c1aeccfe2 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -403,7 +403,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n")); precvbuf->reuse = true; - usb_read_port(adapt, precvpriv->ff_hwaddr, precvbuf); + usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf); DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__); } else { skb_put(precvbuf->pskb, purb->actual_length); @@ -414,7 +414,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) precvbuf->pskb = NULL; precvbuf->reuse = false; - usb_read_port(adapt, precvpriv->ff_hwaddr, precvbuf); + usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf); } } else { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete : purb->status(%d) != 0\n", purb->status)); @@ -437,7 +437,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) case -EOVERFLOW: adapt->HalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL; precvbuf->reuse = true; - usb_read_port(adapt, precvpriv->ff_hwaddr, precvbuf); + usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf); break; case -EINPROGRESS: DBG_88E("ERROR: URB IS IN PROGRESS!\n"); -- cgit v1.2.3 From 30f5687367aa125334969cd9d320c6eb64493451 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:08 +0700 Subject: staging:r8188eu: remove wrappers for LedControl8188eu function There is no reason to use these wrappers. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_cmd.c | 6 +++--- drivers/staging/rtl8188eu/core/rtw_mlme.c | 4 ++-- drivers/staging/rtl8188eu/core/rtw_pwrctrl.c | 2 +- drivers/staging/rtl8188eu/core/rtw_recv.c | 4 ++-- drivers/staging/rtl8188eu/core/rtw_xmit.c | 2 +- drivers/staging/rtl8188eu/hal/rtl8188eu_led.c | 1 - drivers/staging/rtl8188eu/include/rtw_led.h | 8 -------- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 8 ++++---- 8 files changed, 13 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index f1f4788dbd86..36109cec8706 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -308,7 +308,7 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, mod_timer(&pmlmepriv->scan_to_timer, jiffies + msecs_to_jiffies(SCANNING_TIMEOUT)); - rtw_led_control(padapter, LED_CTL_SITE_SURVEY); + LedControl8188eu(padapter, LED_CTL_SITE_SURVEY); pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ } else { @@ -335,7 +335,7 @@ u8 rtw_createbss_cmd(struct adapter *padapter) u8 res = _SUCCESS; - rtw_led_control(padapter, LED_CTL_START_TO_LINK); + LedControl8188eu(padapter, LED_CTL_START_TO_LINK); if (pmlmepriv->assoc_ssid.SsidLength == 0) RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); @@ -379,7 +379,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - rtw_led_control(padapter, LED_CTL_START_TO_LINK); + LedControl8188eu(padapter, LED_CTL_START_TO_LINK); if (pmlmepriv->assoc_ssid.SsidLength == 0) RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n")); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index ee2dcd05010f..032f783b0d83 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -801,7 +801,7 @@ void rtw_indicate_connect(struct adapter *padapter) if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { set_fwstate(pmlmepriv, _FW_LINKED); - rtw_led_control(padapter, LED_CTL_LINK); + LedControl8188eu(padapter, LED_CTL_LINK); rtw_os_indicate_connect(padapter); } @@ -833,7 +833,7 @@ void rtw_indicate_disconnect(struct adapter *padapter) rtw_os_indicate_disconnect(padapter); _clr_fwstate_(pmlmepriv, _FW_LINKED); - rtw_led_control(padapter, LED_CTL_NO_LINK); + LedControl8188eu(padapter, LED_CTL_NO_LINK); rtw_clear_scan_deny(padapter); } diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index fc6385bc8a54..4032121a06f3 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -56,7 +56,7 @@ static int rtw_hw_suspend(struct adapter *padapter) if (check_fwstate(pmlmepriv, _FW_LINKED)) { _clr_fwstate_(pmlmepriv, _FW_LINKED); - rtw_led_control(padapter, LED_CTL_NO_LINK); + LedControl8188eu(padapter, LED_CTL_NO_LINK); rtw_os_indicate_disconnect(padapter); diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 65ae11ed6b7c..1b544e650acf 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -1293,7 +1293,7 @@ static int validate_recv_frame(struct adapter *adapter, retval = _FAIL; /* only data frame return _SUCCESS */ break; case WIFI_DATA_TYPE: /* data */ - rtw_led_control(adapter, LED_CTL_RX); + LedControl8188eu(adapter, LED_CTL_RX); pattrib->qos = (subtype & BIT(7)) ? 1 : 0; retval = validate_recv_data_frame(adapter, precv_frame); if (retval == _FAIL) { @@ -1988,7 +1988,7 @@ static int recv_func_posthandle(struct adapter *padapter, struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; /* DATA FRAME */ - rtw_led_control(padapter, LED_CTL_RX); + LedControl8188eu(padapter, LED_CTL_RX); prframe = decryptor(padapter, prframe); if (prframe == NULL) { diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 0f8b8e0bffdf..2b641f59c504 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -1677,7 +1677,7 @@ s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt) } pxmitframe->pkt = *ppkt; - rtw_led_control(padapter, LED_CTL_TX); + LedControl8188eu(padapter, LED_CTL_TX); pxmitframe->attrib.qsel = pxmitframe->attrib.priority; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index 780666a755ee..fe075ad163c7 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -70,7 +70,6 @@ void rtw_hal_sw_led_init(struct adapter *padapter) struct led_priv *pledpriv = &(padapter->ledpriv); pledpriv->bRegUseLed = true; - pledpriv->LedControlHandler = LedControl8188eu; padapter->HalData->bLedOpenDrain = true; InitLed871x(padapter, &(pledpriv->SwLed0)); diff --git a/drivers/staging/rtl8188eu/include/rtw_led.h b/drivers/staging/rtl8188eu/include/rtw_led.h index f2054ef70358..79f318f94088 100644 --- a/drivers/staging/rtl8188eu/include/rtw_led.h +++ b/drivers/staging/rtl8188eu/include/rtw_led.h @@ -92,17 +92,9 @@ struct led_priv { /* add for led control */ struct LED_871x SwLed0; u8 bRegUseLed; - void (*LedControlHandler)(struct adapter *padapter, - enum LED_CTL_MODE LedAction); /* add for led control */ }; -#define rtw_led_control(adapt, action) \ - do { \ - if ((adapt)->ledpriv.LedControlHandler) \ - (adapt)->ledpriv.LedControlHandler((adapt), (action)); \ - } while (0) - void BlinkTimerCallback(unsigned long data); void BlinkWorkItemCallback(struct work_struct *work); diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 2a1e63de7d15..c933883ed225 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -597,7 +597,7 @@ static int _netdev_open(struct net_device *pnetdev) } rtw_hal_inirp_init(padapter); - rtw_led_control(padapter, LED_CTL_NO_LINK); + LedControl8188eu(padapter, LED_CTL_NO_LINK); padapter->bup = true; } @@ -681,7 +681,7 @@ int rtw_ips_pwr_up(struct adapter *padapter) result = ips_netdrv_open(padapter); - rtw_led_control(padapter, LED_CTL_NO_LINK); + LedControl8188eu(padapter, LED_CTL_NO_LINK); DBG_88E("<=== rtw_ips_pwr_up.............. in %dms\n", jiffies_to_msecs(jiffies - start_time)); @@ -696,7 +696,7 @@ void rtw_ips_pwr_down(struct adapter *padapter) padapter->net_closed = true; - rtw_led_control(padapter, LED_CTL_POWER_OFF); + LedControl8188eu(padapter, LED_CTL_POWER_OFF); rtw_ips_dev_unload(padapter); DBG_88E("<=== rtw_ips_pwr_down..................... in %dms\n", @@ -749,7 +749,7 @@ static int netdev_close(struct net_device *pnetdev) /* s2-4. */ rtw_free_network_queue(padapter, true); /* Close LED */ - rtw_led_control(padapter, LED_CTL_POWER_OFF); + LedControl8188eu(padapter, LED_CTL_POWER_OFF); } RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - drv_close\n")); -- cgit v1.2.3 From f4bf56ac985dcab519d70e37862b4db0df8af170 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:09 +0700 Subject: staging:r8188eu: remove bRegUseLed member of led_priv structure bRegUseLed always is true. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_led.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188eu_led.c | 1 - drivers/staging/rtl8188eu/include/rtw_led.h | 1 - 3 files changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_led.c b/drivers/staging/rtl8188eu/core/rtw_led.c index b613d43e3f74..e6ab1a26f39c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_led.c +++ b/drivers/staging/rtl8188eu/core/rtw_led.c @@ -475,15 +475,10 @@ void BlinkHandler(struct LED_871x *pLed) void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction) { - struct led_priv *ledpriv = &padapter->ledpriv; - if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped) || (!padapter->hw_init_completed)) return; - if (!ledpriv->bRegUseLed) - return; - if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) && (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX || diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index fe075ad163c7..a6d775beb35b 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -69,7 +69,6 @@ void rtw_hal_sw_led_init(struct adapter *padapter) { struct led_priv *pledpriv = &(padapter->ledpriv); - pledpriv->bRegUseLed = true; padapter->HalData->bLedOpenDrain = true; InitLed871x(padapter, &(pledpriv->SwLed0)); diff --git a/drivers/staging/rtl8188eu/include/rtw_led.h b/drivers/staging/rtl8188eu/include/rtw_led.h index 79f318f94088..217ca00ba72b 100644 --- a/drivers/staging/rtl8188eu/include/rtw_led.h +++ b/drivers/staging/rtl8188eu/include/rtw_led.h @@ -91,7 +91,6 @@ void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction); struct led_priv { /* add for led control */ struct LED_871x SwLed0; - u8 bRegUseLed; /* add for led control */ }; -- cgit v1.2.3 From 005aca517055ddeb2a40a43d6fd585e878f1152c Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:10 +0700 Subject: staging:r8188eu: remove bLedStartToLinkBlinkInProgress and bSWLedCtrl members of LED_871x structure These members of LED_871x structure does not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_led.c | 1 - drivers/staging/rtl8188eu/include/rtw_led.h | 3 --- 2 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_led.c b/drivers/staging/rtl8188eu/core/rtw_led.c index e6ab1a26f39c..c1478cff5854 100644 --- a/drivers/staging/rtl8188eu/core/rtw_led.c +++ b/drivers/staging/rtl8188eu/core/rtw_led.c @@ -60,7 +60,6 @@ void ResetLedStatus(struct LED_871x *pLed) pLed->bLedNoLinkBlinkInProgress = false; pLed->bLedLinkBlinkInProgress = false; - pLed->bLedStartToLinkBlinkInProgress = false; pLed->bLedScanBlinkInProgress = false; } diff --git a/drivers/staging/rtl8188eu/include/rtw_led.h b/drivers/staging/rtl8188eu/include/rtw_led.h index 217ca00ba72b..607d1ba56a46 100644 --- a/drivers/staging/rtl8188eu/include/rtw_led.h +++ b/drivers/staging/rtl8188eu/include/rtw_led.h @@ -70,12 +70,9 @@ struct LED_871x { struct timer_list BlinkTimer; /* Timer object for led blinking. */ - u8 bSWLedCtrl; - /* ALPHA, added by chiyoko, 20090106 */ u8 bLedNoLinkBlinkInProgress; u8 bLedLinkBlinkInProgress; - u8 bLedStartToLinkBlinkInProgress; u8 bLedScanBlinkInProgress; struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer to * manipulate H/W to blink LED. */ -- cgit v1.2.3 From ae2d23e0755f68dd46fd80460842dcec8dcc14b7 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:11 +0700 Subject: staging:r8188eu: remove bLedOpenDrain member of hal_data_8188e structure bLedOpenDrain always is true. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188eu_led.c | 18 ++++++------------ drivers/staging/rtl8188eu/include/rtl8188e_hal.h | 2 -- 2 files changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index a6d775beb35b..12879afb992e 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -46,16 +46,12 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed) LedCfg = usb_read8(padapter, REG_LEDCFG2);/* 0x4E */ - if (padapter->HalData->bLedOpenDrain) { - /* Open-drain arrangement for controlling the LED) */ - LedCfg &= 0x90; /* Set to software control. */ - usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3))); - LedCfg = usb_read8(padapter, REG_MAC_PINMUX_CFG); - LedCfg &= 0xFE; - usb_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg); - } else { - usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3) | BIT(5) | BIT(6))); - } + /* Open-drain arrangement for controlling the LED) */ + LedCfg &= 0x90; /* Set to software control. */ + usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3))); + LedCfg = usb_read8(padapter, REG_MAC_PINMUX_CFG); + LedCfg &= 0xFE; + usb_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg); exit: pLed->bLedOn = false; } @@ -69,8 +65,6 @@ void rtw_hal_sw_led_init(struct adapter *padapter) { struct led_priv *pledpriv = &(padapter->ledpriv); - padapter->HalData->bLedOpenDrain = true; - InitLed871x(padapter, &(pledpriv->SwLed0)); } diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 7c81e3f3d12e..19264a247dde 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -270,8 +270,6 @@ struct hal_data_8188e { u8 BluetoothCoexist; u8 ExternalPA; - u8 bLedOpenDrain; /* Open-drain support for controlling the LED.*/ - u8 b1x1RecvCombine; /* for 1T1R receive combining */ u32 AcParam_BE; /* Original parameter for BE, use for EDCA turbo. */ -- cgit v1.2.3 From 1a4a467fa2350aa1103f6224edef521fb1cadbbe Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:12 +0700 Subject: staging:r8188eu: remove ExternalPA member of hal_data_8188e structure ExternalPA always is false. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rf.c | 2 -- drivers/staging/rtl8188eu/include/rtl8188e_hal.h | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c index 2f3edf0f850a..eddd075cec27 100644 --- a/drivers/staging/rtl8188eu/hal/rf.c +++ b/drivers/staging/rtl8188eu/hal/rf.c @@ -61,8 +61,6 @@ void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel) (powerlevel[idx1]<<8) | (powerlevel[idx1]<<16) | (powerlevel[idx1]<<24); - if (tx_agc[idx1] > 0x20 && hal_data->ExternalPA) - tx_agc[idx1] = 0x20; } } else { if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) { diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 19264a247dde..942ce91594e4 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -268,7 +268,6 @@ struct hal_data_8188e { u32 AntennaTxPath; /* Antenna path Tx */ u32 AntennaRxPath; /* Antenna path Rx */ u8 BluetoothCoexist; - u8 ExternalPA; u8 b1x1RecvCombine; /* for 1T1R receive combining */ -- cgit v1.2.3 From 81bd8837458df80e15805ab3e8c573eaa99165b8 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:13 +0700 Subject: staging:r8188eu: remove unused members of hal_data_8188e structure These members of hal_data_8188e structure does not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 3 --- drivers/staging/rtl8188eu/include/rtl8188e_hal.h | 13 ------------- 2 files changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index dfb78bbdf6c6..b1740cf9e3f9 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -562,9 +562,6 @@ static void InitUsbAggregationSetting(struct adapter *Adapter) /* Rx aggregation setting */ usb_AggSettingRxUpdate(Adapter); - - /* 201/12/10 MH Add for USB agg mode dynamic switch. */ - Adapter->HalData->UsbRxHighSpeedMode = false; } static void _InitBeaconParameters(struct adapter *Adapter) diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 942ce91594e4..53c975ac1506 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -265,11 +265,6 @@ struct hal_data_8188e { u32 CCKTxPowerLevelOriginalOffset; u8 CrystalCap; - u32 AntennaTxPath; /* Antenna path Tx */ - u32 AntennaRxPath; /* Antenna path Rx */ - u8 BluetoothCoexist; - - u8 b1x1RecvCombine; /* for 1T1R receive combining */ u32 AcParam_BE; /* Original parameter for BE, use for EDCA turbo. */ @@ -313,14 +308,6 @@ struct hal_data_8188e { u8 OutEpQueueSel; u8 OutEpNumber; - /* Add for USB aggreation mode dynamic shceme. */ - bool UsbRxHighSpeedMode; - - /* 2010/11/22 MH Add for slim combo debug mode selective. */ - /* This is used for fix the drawback of CU TSMC-A/UMC-A cut. - * HW auto suspend ability. Close BT clock. */ - bool SlimComboDbg; - u16 EfuseUsedBytes; /* Auto FSM to Turn On, include clock, isolation, power control -- cgit v1.2.3 From 6f8f444d6c395f25ba159171945b3e1dd104e947 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:14 +0700 Subject: staging:r8188eu: remove Antenna_(Lfet|Right) enumeration items These defintions does not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index b1740cf9e3f9..87e379e6d6ad 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -601,11 +601,6 @@ static void _BBTurnOnBlock(struct adapter *Adapter) phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1); } -enum { - Antenna_Lfet = 1, - Antenna_Right = 2, -}; - static void _InitAntenna_Selection(struct adapter *Adapter) { struct hal_data_8188e *haldata = Adapter->HalData; -- cgit v1.2.3 From ffc2ab44f4d3dd51bd77da960085e3a0de3105e2 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:15 +0700 Subject: staging:r8188eu: remove rf_chip member of hal_data_8188e structure This member is constant. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/phy.c | 13 +------------ drivers/staging/rtl8188eu/hal/usb_halinit.c | 6 ------ drivers/staging/rtl8188eu/include/rtl8188e_hal.h | 1 - 3 files changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 5192ef70bcfc..84ffc01030e0 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -210,13 +210,6 @@ static void phy_set_bw_mode_callback(struct adapter *adapt) u8 reg_bw_opmode; u8 reg_prsr_rsc; - if (hal_data->rf_chip == RF_PSEUDO_11N) - return; - - /* There is no 40MHz mode in RF_8225. */ - if (hal_data->rf_chip == RF_8225) - return; - if (adapt->bDriverStopped) return; @@ -265,8 +258,7 @@ static void phy_set_bw_mode_callback(struct adapter *adapt) } /* Set RF related register */ - if (hal_data->rf_chip == RF_6052) - rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW); + rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW); } void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth, @@ -307,9 +299,6 @@ void rtw_hal_set_chan(struct adapter *adapt, u8 channel) struct hal_data_8188e *hal_data = adapt->HalData; u8 tmpchannel = hal_data->CurrentChannel; - if (hal_data->rf_chip == RF_PSEUDO_11N) - return; - if (channel == 0) channel = 1; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 87e379e6d6ad..71d6ade70554 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1096,18 +1096,12 @@ static void _ReadPROMContent( readAdapterInfo_8188EU(Adapter); } -static void _ReadRFType(struct adapter *Adapter) -{ - Adapter->HalData->rf_chip = RF_6052; -} - void rtw_hal_read_chip_info(struct adapter *Adapter) { unsigned long start = jiffies; MSG_88E("====> %s\n", __func__); - _ReadRFType(Adapter);/* rf_chip -> _InitRFType() */ _ReadPROMContent(Adapter); MSG_88E("<==== %s in %d ms\n", __func__, diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 53c975ac1506..226e89ba132d 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -201,7 +201,6 @@ struct hal_data_8188e { u16 BasicRateSet; /* rf_ctrl */ - u8 rf_chip; u8 NumTotalRFPath; u8 BoardType; -- cgit v1.2.3 From 76fe8b32b4251f18b6fe27e1df5cb33c2aeaa2ac Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:16 +0700 Subject: staging:r8188eu: remove RF_TYPE_8190P enumeration This enumeration does not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h index 0976a761b280..550ad62e7064 100644 --- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h +++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h @@ -99,17 +99,6 @@ enum phy_rate_tx_offset_area { RA_OFFSET_HT_CCK, }; -/* BB/RF related */ -enum RF_TYPE_8190P { - RF_TYPE_MIN, /* 0 */ - RF_8225 = 1, /* 1 11b/g RF for verification only */ - RF_8256 = 2, /* 2 11b/g/n */ - RF_8258 = 3, /* 3 11a/b/g/n RF */ - RF_6052 = 4, /* 4 11b/g/n RF */ - /* TODO: We should remove this psudo PHY RF after we get new RF. */ - RF_PSEUDO_11N = 5, /* 5, It is a temporality RF. */ -}; - struct bb_reg_def { u32 rfintfs; /* set software control: */ /* 0x870~0x877[8 bytes] */ -- cgit v1.2.3 From b39db0b160be36fcef4fe806c9576ffeb7043323 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:17 +0700 Subject: staging:r8188eu: remove NumTotalRFPath member of hal_data_8188e structure NumTotalRFPath is 1 for r8188eu chip. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/phy.c | 11 ++-- drivers/staging/rtl8188eu/hal/rf.c | 20 +++---- drivers/staging/rtl8188eu/hal/rf_cfg.c | 70 ++++------------------- drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c | 51 ++++++++--------- drivers/staging/rtl8188eu/include/rtl8188e_hal.h | 3 - 5 files changed, 49 insertions(+), 106 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 84ffc01030e0..8e0e68586234 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -278,7 +278,6 @@ void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth, static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) { - u8 rf_path; u32 param1, param2; struct hal_data_8188e *hal_data = adapt->HalData; @@ -286,12 +285,10 @@ static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) param1 = RF_CHNLBW; param2 = channel; - for (rf_path = 0; rf_path < hal_data->NumTotalRFPath; rf_path++) { - hal_data->RfRegChnlVal[rf_path] = (hal_data->RfRegChnlVal[rf_path] & - 0xfffffc00) | param2; - phy_set_rf_reg(adapt, (enum rf_radio_path)rf_path, param1, - bRFRegOffsetMask, hal_data->RfRegChnlVal[rf_path]); - } + hal_data->RfRegChnlVal[0] = (hal_data->RfRegChnlVal[0] & + 0xfffffc00) | param2; + phy_set_rf_reg(adapt, 0, param1, + bRFRegOffsetMask, hal_data->RfRegChnlVal[0]); } void rtw_hal_set_chan(struct adapter *adapt, u8 channel) diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c index eddd075cec27..8f8c9de6a9bc 100644 --- a/drivers/staging/rtl8188eu/hal/rf.c +++ b/drivers/staging/rtl8188eu/hal/rf.c @@ -137,17 +137,15 @@ static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm, (powerbase0<<8) | powerbase0; *(ofdmbase+i) = powerbase0; } - for (i = 0; i < adapt->HalData->NumTotalRFPath; i++) { - /* Check HT20 to HT40 diff */ - if (adapt->HalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) - powerlevel[i] = pwr_level_bw20[i]; - else - powerlevel[i] = pwr_level_bw40[i]; - powerbase1 = powerlevel[i]; - powerbase1 = (powerbase1<<24) | (powerbase1<<16) | - (powerbase1<<8) | powerbase1; - *(mcs_base+i) = powerbase1; - } + /* Check HT20 to HT40 diff */ + if (adapt->HalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + powerlevel[0] = pwr_level_bw20[0]; + else + powerlevel[0] = pwr_level_bw40[0]; + powerbase1 = powerlevel[0]; + powerbase1 = (powerbase1<<24) | (powerbase1<<16) | + (powerbase1<<8) | powerbase1; + *mcs_base = powerbase1; } static void get_rx_power_val_by_reg(struct adapter *adapt, u8 channel, u8 index, u32 *powerbase0, u32 *powerbase1, diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index dde64417e66a..9712d7b74345 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -230,79 +230,33 @@ static bool rf6052_conf_para(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; - u8 rfpath; bool rtstatus = true; struct bb_reg_def *pphyreg; - for (rfpath = 0; rfpath < hal_data->NumTotalRFPath; rfpath++) { - pphyreg = &hal_data->PHYRegDef[rfpath]; + pphyreg = &hal_data->PHYRegDef[RF90_PATH_A]; + u4val = phy_query_bb_reg(adapt, pphyreg->rfintfs, BRFSI_RFENV); - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4val = phy_query_bb_reg(adapt, pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4val = phy_query_bb_reg(adapt, pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } + phy_set_bb_reg(adapt, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); - phy_set_bb_reg(adapt, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); + phy_set_bb_reg(adapt, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); - phy_set_bb_reg(adapt, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); + phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2, B3WIREADDREAALENGTH, 0x0); + udelay(1); - phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2, - B3WIREADDREAALENGTH, 0x0); - udelay(1); + phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2, B3WIREDATALENGTH, 0x0); + udelay(1); - phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2, - B3WIREDATALENGTH, 0x0); - udelay(1); + rtstatus = rtl88e_phy_config_rf_with_headerfile(adapt); - switch (rfpath) { - case RF90_PATH_A: - rtstatus = rtl88e_phy_config_rf_with_headerfile(adapt); - break; - case RF90_PATH_B: - rtstatus = rtl88e_phy_config_rf_with_headerfile(adapt); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - phy_set_bb_reg(adapt, pphyreg->rfintfs, - BRFSI_RFENV, u4val); - break; - case RF90_PATH_B: - case RF90_PATH_D: - phy_set_bb_reg(adapt, pphyreg->rfintfs, - BRFSI_RFENV << 16, u4val); - break; - } - - if (!rtstatus) - return false; - } + phy_set_bb_reg(adapt, pphyreg->rfintfs, BRFSI_RFENV, u4val); return rtstatus; } static bool rtl88e_phy_rf6052_config(struct adapter *adapt) { - struct hal_data_8188e *hal_data = adapt->HalData; - - hal_data->NumTotalRFPath = 1; - return rf6052_conf_para(adapt); } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 385bc2f56f2f..edc6b528a7af 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -135,7 +135,6 @@ void rtw_hal_read_chip_version(struct adapter *padapter) dump_chip_info(ChipVersion); pHalData->VersionID = ChipVersion; - pHalData->NumTotalRFPath = 1; } void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet) @@ -470,7 +469,7 @@ void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool Auto { struct hal_data_8188e *pHalData = padapter->HalData; struct txpowerinfo24g pwrInfo24G; - u8 rfPath, ch, group; + u8 ch, group; u8 bIn24G, TxCount; Hal_ReadPowerValueFromPROM_8188E(&pwrInfo24G, PROMContent, AutoLoadFail); @@ -478,34 +477,32 @@ void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool Auto if (!AutoLoadFail) pHalData->bTXPowerDataReadFromEEPORM = true; - for (rfPath = 0; rfPath < pHalData->NumTotalRFPath; rfPath++) { - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - bIn24G = Hal_GetChnlGroup88E(ch, &group); - if (bIn24G) { - pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group]; - if (ch == 14) - pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][4]; - else - pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group]; - } - if (bIn24G) { - DBG_88E("======= Path %d, Channel %d =======\n", rfPath, ch); - DBG_88E("Index24G_CCK_Base[%d][%d] = 0x%x\n", rfPath, ch , pHalData->Index24G_CCK_Base[rfPath][ch]); - DBG_88E("Index24G_BW40_Base[%d][%d] = 0x%x\n", rfPath, ch , pHalData->Index24G_BW40_Base[rfPath][ch]); - } + for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { + bIn24G = Hal_GetChnlGroup88E(ch, &group); + if (bIn24G) { + pHalData->Index24G_CCK_Base[0][ch] = pwrInfo24G.IndexCCK_Base[0][group]; + if (ch == 14) + pHalData->Index24G_BW40_Base[0][ch] = pwrInfo24G.IndexBW40_Base[0][4]; + else + pHalData->Index24G_BW40_Base[0][ch] = pwrInfo24G.IndexBW40_Base[0][group]; } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - pHalData->CCK_24G_Diff[rfPath][TxCount] = pwrInfo24G.CCK_Diff[rfPath][TxCount]; - pHalData->OFDM_24G_Diff[rfPath][TxCount] = pwrInfo24G.OFDM_Diff[rfPath][TxCount]; - pHalData->BW20_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW20_Diff[rfPath][TxCount]; - pHalData->BW40_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW40_Diff[rfPath][TxCount]; - DBG_88E("======= TxCount %d =======\n", TxCount); - DBG_88E("CCK_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->CCK_24G_Diff[rfPath][TxCount]); - DBG_88E("OFDM_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->OFDM_24G_Diff[rfPath][TxCount]); - DBG_88E("BW20_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->BW20_24G_Diff[rfPath][TxCount]); - DBG_88E("BW40_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->BW40_24G_Diff[rfPath][TxCount]); + if (bIn24G) { + DBG_88E("======= Path %d, Channel %d =======\n", 0, ch); + DBG_88E("Index24G_CCK_Base[%d][%d] = 0x%x\n", 0, ch , pHalData->Index24G_CCK_Base[0][ch]); + DBG_88E("Index24G_BW40_Base[%d][%d] = 0x%x\n", 0, ch , pHalData->Index24G_BW40_Base[0][ch]); } } + for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { + pHalData->CCK_24G_Diff[0][TxCount] = pwrInfo24G.CCK_Diff[0][TxCount]; + pHalData->OFDM_24G_Diff[0][TxCount] = pwrInfo24G.OFDM_Diff[0][TxCount]; + pHalData->BW20_24G_Diff[0][TxCount] = pwrInfo24G.BW20_Diff[0][TxCount]; + pHalData->BW40_24G_Diff[0][TxCount] = pwrInfo24G.BW40_Diff[0][TxCount]; + DBG_88E("======= TxCount %d =======\n", TxCount); + DBG_88E("CCK_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->CCK_24G_Diff[0][TxCount]); + DBG_88E("OFDM_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->OFDM_24G_Diff[0][TxCount]); + DBG_88E("BW20_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->BW20_24G_Diff[0][TxCount]); + DBG_88E("BW40_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->BW40_24G_Diff[0][TxCount]); + } /* 2010/10/19 MH Add Regulator recognize for CU. */ if (!AutoLoadFail) { diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 226e89ba132d..9330361da4ad 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -200,9 +200,6 @@ struct hal_data_8188e { u16 BasicRateSet; - /* rf_ctrl */ - u8 NumTotalRFPath; - u8 BoardType; /* EEPROM setting. */ -- cgit v1.2.3 From 85a7dc225d0b687114a045f42880946a9d7f2574 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:18 +0700 Subject: staging:r8188eu: refactor rtl88eu_dm_txpower_tracking_callback_thermalmeter function Remove is2t and rf local variables from this function. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/phy.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 8e0e68586234..126547e06dac 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -393,9 +393,8 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) s8 ofdm_index[2], cck_index = 0; s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0; u32 i = 0, j = 0; - bool is2t = false; - u8 ofdm_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB */ + u8 ofdm_min_index = 6; /* OFDM BB Swing should be less than +3.0dB */ s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = { /* 2.4G, decrease power */ {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11}, @@ -420,11 +419,6 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_T_METER_88E, 0xfc00); - if (is2t) - rf = 2; - else - rf = 1; - if (thermal_val) { /* Query OFDM path A default setting */ ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D; @@ -436,17 +430,6 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) } } - /* Query OFDM path B default setting */ - if (is2t) { - ele_d = phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D; - for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { - if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) { - ofdm_index_old[1] = (u8)i; - break; - } - } - } - /* Query CCK default setting From 0xa24 */ temp_cck = dm_odm->RFCalibrateInfo.RegA24; @@ -465,8 +448,7 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val; dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val; - for (i = 0; i < rf; i++) - dm_odm->RFCalibrateInfo.OFDM_index[i] = ofdm_index_old[i]; + dm_odm->RFCalibrateInfo.OFDM_index[0] = ofdm_index_old[0]; dm_odm->RFCalibrateInfo.CCK_index = cck_index_old; } @@ -525,13 +507,11 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) offset = index_mapping_NUM_88E-1; /* Updating ofdm_index values with new OFDM / CCK offset */ - for (i = 0; i < rf; i++) { - ofdm_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + ofdm_index_mapping[j][offset]; - if (ofdm_index[i] > OFDM_TABLE_SIZE_92D-1) - ofdm_index[i] = OFDM_TABLE_SIZE_92D-1; - else if (ofdm_index[i] < ofdm_min_index) - ofdm_index[i] = ofdm_min_index; - } + ofdm_index[0] = dm_odm->RFCalibrateInfo.OFDM_index[0] + ofdm_index_mapping[j][offset]; + if (ofdm_index[0] > OFDM_TABLE_SIZE_92D-1) + ofdm_index[0] = OFDM_TABLE_SIZE_92D-1; + else if (ofdm_index[0] < ofdm_min_index) + ofdm_index[0] = ofdm_min_index; cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset]; if (cck_index > CCK_TABLE_SIZE-1) -- cgit v1.2.3 From 660d7afff7793a1051830c18e3865156724e605b Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:19 +0700 Subject: staging:r8188eu: remove bTXPowerTrackingInit member of odm_rf_cal structure bTXPowerTrackingInit assigned, but not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/odm.c | 1 - drivers/staging/rtl8188eu/hal/phy.c | 1 - drivers/staging/rtl8188eu/include/odm.h | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index d983a8029f4c..16476e735011 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -991,7 +991,6 @@ void odm_TXPowerTrackingThermalMeterInit(struct odm_dm_struct *pDM_Odm) { pDM_Odm->RFCalibrateInfo.bTXPowerTracking = true; pDM_Odm->RFCalibrateInfo.TXPowercount = 0; - pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = false; if (*(pDM_Odm->mp_mode) != 1) pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true; MSG_88E("pDM_Odm TxPowerTrackControl = %d\n", pDM_Odm->RFCalibrateInfo.TxPowerTrackControl); diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 126547e06dac..109c2d7704ff 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -412,7 +412,6 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) dm_txpwr_track_setpwr(dm_odm); dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++; - dm_odm->RFCalibrateInfo.bTXPowerTrackingInit = true; dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317; diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index 805f52e108b2..0c15e5fd1e2d 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -590,7 +590,6 @@ struct odm_rf_cal { s32 RegEBC; u8 TXPowercount; - bool bTXPowerTrackingInit; bool bTXPowerTracking; u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking * as default */ -- cgit v1.2.3 From 5e88cae5dcda3f58dd09ca8aa6248d3e26dca4b5 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:20 +0700 Subject: staging:r8188eu: remove ANTTEST(ALL|A|B) definitions These defintions does not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/odm.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index 0c15e5fd1e2d..4fb3bb07ceaa 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -80,11 +80,6 @@ #define DM_DIG_FA_TH2_LPS 30 /* 30 lps */ #define RSSI_OFFSET_DIG 0x05; -/* ANT Test */ -#define ANTTESTALL 0x00 /* Ant A or B will be Testing */ -#define ANTTESTA 0x01 /* Ant A will be Testing */ -#define ANTTESTB 0x02 /* Ant B will be testing */ - struct rtw_dig { u8 Dig_Enable_Flag; u8 Dig_Ext_Port_Stage; -- cgit v1.2.3 From 9c0549119008e9c7e6fb887e70b15ee1ed03cbed Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:21 +0700 Subject: staging:r8188eu: remove rtw_endofpktfile function rtw_endofpktfile is one-line function. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_xmit.c | 2 +- drivers/staging/rtl8188eu/include/xmit_osdep.h | 1 - drivers/staging/rtl8188eu/os_dep/xmit_linux.c | 5 ----- 3 files changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 2b641f59c504..ca65f0004e22 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -1064,7 +1064,7 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct frg_inx++; - if (bmcst || rtw_endofpktfile(&pktfile)) { + if (bmcst || pktfile.pkt_len == 0) { pattrib->nr_frags = frg_inx; pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + ((pattrib->nr_frags == 1) ? llc_sz : 0) + diff --git a/drivers/staging/rtl8188eu/include/xmit_osdep.h b/drivers/staging/rtl8188eu/include/xmit_osdep.h index f96ca6af934d..f9b3841cf7fd 100644 --- a/drivers/staging/rtl8188eu/include/xmit_osdep.h +++ b/drivers/staging/rtl8188eu/include/xmit_osdep.h @@ -47,7 +47,6 @@ void rtw_os_xmit_resource_free(struct adapter *padapter, uint rtw_remainder_len(struct pkt_file *pfile); void _rtw_open_pktfile(struct sk_buff *pkt, struct pkt_file *pfile); uint _rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen); -int rtw_endofpktfile(struct pkt_file *pfile); void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt); void rtw_os_xmit_complete(struct adapter *padapter, diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c index 4b1b04e00715..019ded9c2904 100644 --- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c @@ -59,11 +59,6 @@ uint _rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen) return len; } -int rtw_endofpktfile(struct pkt_file *pfile) -{ - return pfile->pkt_len == 0; -} - int rtw_os_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitbuf, u32 alloc_sz) { int i; -- cgit v1.2.3 From 5cd3879757cd75fd26a94a0e970f69d9a57dee58 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:22 +0700 Subject: staging:r8188eu: remove padapter and free_sz arguments of rtw_os_xmit_resource_free function These argumets does not used by rtw_os_xmit_resource_free function. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_xmit.c | 5 ++--- drivers/staging/rtl8188eu/include/xmit_osdep.h | 3 +-- drivers/staging/rtl8188eu/os_dep/xmit_linux.c | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index ca65f0004e22..b60b126b860e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -220,7 +220,6 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) struct adapter *padapter = pxmitpriv->adapter; struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitpriv->pxmit_frame_buf; struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; - u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; u32 num_xmit_extbuf = NR_XMIT_EXTBUFF; if (pxmitpriv->pxmit_frame_buf == NULL) @@ -233,7 +232,7 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) } for (i = 0; i < NR_XMITBUFF; i++) { - rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); + rtw_os_xmit_resource_free(pxmitbuf); pxmitbuf++; } @@ -243,7 +242,7 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) /* free xmit extension buff */ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; for (i = 0; i < num_xmit_extbuf; i++) { - rtw_os_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ)); + rtw_os_xmit_resource_free(pxmitbuf); pxmitbuf++; } diff --git a/drivers/staging/rtl8188eu/include/xmit_osdep.h b/drivers/staging/rtl8188eu/include/xmit_osdep.h index f9b3841cf7fd..959ef4b3066c 100644 --- a/drivers/staging/rtl8188eu/include/xmit_osdep.h +++ b/drivers/staging/rtl8188eu/include/xmit_osdep.h @@ -41,8 +41,7 @@ void rtw_os_xmit_schedule(struct adapter *padapter); int rtw_os_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitbuf, u32 alloc_sz); -void rtw_os_xmit_resource_free(struct adapter *padapter, - struct xmit_buf *pxmitbuf, u32 free_sz); +void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf); uint rtw_remainder_len(struct pkt_file *pfile); void _rtw_open_pktfile(struct sk_buff *pkt, struct pkt_file *pfile); diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c index 019ded9c2904..e097c619ed1b 100644 --- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c @@ -80,8 +80,7 @@ int rtw_os_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitb return _SUCCESS; } -void rtw_os_xmit_resource_free(struct adapter *padapter, - struct xmit_buf *pxmitbuf, u32 free_sz) +void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf) { int i; -- cgit v1.2.3 From 175fa9a7a87af9e46329f80e8fb10968e9bb0ed4 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:23 +0700 Subject: staging:r8188eu: remove unused function declerations rtl8188eu_recv_hdl and rtl8188e_query_rx_phy_status doesn't used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/rtl8188e_recv.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h index 80832a5f0732..0d8bf51c72a9 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h @@ -51,9 +51,7 @@ enum rx_packet_type { }; #define INTERRUPT_MSG_FORMAT_LEN 60 -void rtl8188eu_recv_hdl(struct adapter *padapter, struct recv_buf *precvbuf); void rtl8188eu_recv_tasklet(void *priv); -void rtl8188e_query_rx_phy_status(struct recv_frame *fr, struct phy_stat *phy); void rtl8188e_process_phy_info(struct adapter *padapter, struct recv_frame *prframe); void update_recvframe_phyinfo_88e(struct recv_frame *fra, struct phy_stat *phy); -- cgit v1.2.3 From aaa27e8c4abccc2c8fc3da6e7c092fc4f7a279ed Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:24 +0700 Subject: staging:r8188eu: remove prhdr local variable from rtw_free_stainfo function This variable is unnecessary. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_sta_mgt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c index a71e25294add..941d1a069d20 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c @@ -310,7 +310,6 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */ for (i = 0; i < 16; i++) { struct list_head *phead, *plist; - struct recv_frame *prhdr; struct recv_frame *prframe; struct __queue *ppending_recvframe_queue; struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; @@ -327,8 +326,7 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) plist = phead->next; while (!list_empty(phead)) { - prhdr = container_of(plist, struct recv_frame, list); - prframe = (struct recv_frame *)prhdr; + prframe = container_of(plist, struct recv_frame, list); plist = plist->next; -- cgit v1.2.3 From 63764c7fb6e159a5b2abe782f079bf75661b2489 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:25 +0700 Subject: staging:r8188eu: change type of the precv_buf member of recv_priv structure To avoid unnecessary typecast. To use compiler type checking. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c | 6 +++--- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- drivers/staging/rtl8188eu/include/rtw_recv.h | 2 +- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index 1c7a9a084b49..d3d64fab348f 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -46,10 +46,10 @@ int rtw_hal_init_recv_priv(struct adapter *padapter) goto exit; } - precvpriv->precv_buf = precvpriv->pallocated_recv_buf; + precvpriv->precv_buf = (struct recv_buf *)precvpriv->pallocated_recv_buf; - precvbuf = (struct recv_buf *)precvpriv->precv_buf; + precvbuf = precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf); @@ -86,7 +86,7 @@ void rtw_hal_free_recv_priv(struct adapter *padapter) struct recv_buf *precvbuf; struct recv_priv *precvpriv = &padapter->recvpriv; - precvbuf = (struct recv_buf *)precvpriv->precv_buf; + precvbuf = precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { usb_free_urb(precvbuf->purb); diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 71d6ade70554..3675edb61942 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -987,7 +987,7 @@ u32 rtw_hal_inirp_init(struct adapter *Adapter) ("===> usb_inirp_init\n")); /* issue Rx irp to receive data */ - precvbuf = (struct recv_buf *)precvpriv->precv_buf; + precvbuf = precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { if (usb_read_port(Adapter, RECV_BULK_IN_ADDR, precvbuf) == false) { RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("usb_rx_init: usb_read_port error\n")); diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index e871ebbdb95a..8fa3b8193f6e 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -181,7 +181,7 @@ struct recv_priv { struct sk_buff_head free_recv_skb_queue; struct sk_buff_head rx_skb_queue; u8 *pallocated_recv_buf; - u8 *precv_buf; /* 4 alignment */ + struct recv_buf *precv_buf; /* 4 alignment */ struct __queue free_recv_buf_queue; /* For display the phy informatiom */ u8 is_signal_dbg; /* for debug */ diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 175c1aeccfe2..b87663b8e165 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -521,7 +521,7 @@ void rtw_hal_inirp_deinit(struct adapter *padapter) int i; struct recv_buf *precvbuf; - precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf; + precvbuf = padapter->recvpriv.precv_buf; DBG_88E("%s\n", __func__); -- cgit v1.2.3 From 94b6a662c3169b9e1e408178f5dc16d94a1e9b53 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:26 +0700 Subject: staging:r8188eu: remove pallocated_recv_buf member of the recv_priv structure recv_priv used instead. recv_priv does not changed after assigning and it can be used as kfree argument Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c | 10 +++------- drivers/staging/rtl8188eu/include/rtw_recv.h | 1 - 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index d3d64fab348f..0fc093eb7a77 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -37,18 +37,14 @@ int rtw_hal_init_recv_priv(struct adapter *padapter) /* init recv_buf */ _rtw_init_queue(&precvpriv->free_recv_buf_queue); - precvpriv->pallocated_recv_buf = + precvpriv->precv_buf = kcalloc(NR_RECVBUFF, sizeof(struct recv_buf), GFP_KERNEL); - if (!precvpriv->pallocated_recv_buf) { + if (!precvpriv->precv_buf) { res = _FAIL; RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n")); goto exit; } - - precvpriv->precv_buf = (struct recv_buf *)precvpriv->pallocated_recv_buf; - - precvbuf = precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { @@ -93,7 +89,7 @@ void rtw_hal_free_recv_priv(struct adapter *padapter) precvbuf++; } - kfree(precvpriv->pallocated_recv_buf); + kfree(precvpriv->precv_buf); if (skb_queue_len(&precvpriv->rx_skb_queue)) DBG_88E(KERN_WARNING "rx_skb_queue not empty\n"); diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index 8fa3b8193f6e..e95f4f2c71b3 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -180,7 +180,6 @@ struct recv_priv { struct tasklet_struct recv_tasklet; struct sk_buff_head free_recv_skb_queue; struct sk_buff_head rx_skb_queue; - u8 *pallocated_recv_buf; struct recv_buf *precv_buf; /* 4 alignment */ struct __queue free_recv_buf_queue; /* For display the phy informatiom */ -- cgit v1.2.3 From fd5d86d2f386b3996c50888af97d6ed2df6794f8 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:27 +0700 Subject: staging:r8188eu: remove intf_stop member of adapter structure call usb_intf_stop directly. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/drv_types.h | 1 - drivers/staging/rtl8188eu/include/hal_intf.h | 1 + drivers/staging/rtl8188eu/os_dep/os_intfs.c | 3 +-- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 7 ++----- 4 files changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 5eb56b1281d2..e86419e525d8 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -156,7 +156,6 @@ struct adapter { u8 hw_init_completed; void *cmdThread; - void (*intf_stop)(struct adapter *adapter); struct net_device *pnetdev; struct net_device *pmondev; diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index fa032b0c12ff..e1114a95d442 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -190,6 +190,7 @@ void rtw_hal_set_odm_var(struct adapter *padapter, u32 rtw_hal_inirp_init(struct adapter *padapter); void rtw_hal_inirp_deinit(struct adapter *padapter); +void usb_intf_stop(struct adapter *padapter); s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe); s32 rtw_hal_mgnt_xmit(struct adapter *padapter, diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index c933883ed225..8fc3fadf065f 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -709,8 +709,7 @@ void rtw_ips_dev_unload(struct adapter *padapter) rtw_hal_set_hwreg(padapter, HW_VAR_FIFO_CLEARN_UP, NULL); - if (padapter->intf_stop) - padapter->intf_stop(padapter); + usb_intf_stop(padapter); /* s5. */ if (!padapter->bSurpriseRemoved) diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 94dac53a48b7..c6316ffa64d3 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -141,7 +141,7 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf) } -static void usb_intf_stop(struct adapter *padapter) +void usb_intf_stop(struct adapter *padapter) { RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n")); @@ -174,8 +174,7 @@ static void rtw_dev_unload(struct adapter *padapter) if (padapter->xmitpriv.ack_tx) rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP); /* s3. */ - if (padapter->intf_stop) - padapter->intf_stop(padapter); + usb_intf_stop(padapter); /* s4. */ if (!padapter->pwrctrlpriv.bInternalAutoSuspend) rtw_stop_drv_threads(padapter); @@ -357,8 +356,6 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, if (!padapter->HalData) DBG_88E("cant not alloc memory for HAL DATA\n"); - padapter->intf_stop = &usb_intf_stop; - /* step read_chip_version */ rtw_hal_read_chip_version(padapter); -- cgit v1.2.3 From 437a7b6e116cadfc179db89225bf706bddd50802 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:28 +0700 Subject: staging:r8188eu: remove free_recvframe_cnt member of recv_priv structure Value of free_recvframe_cnt does not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 33 ++-------------------------- drivers/staging/rtl8188eu/include/rtw_recv.h | 1 - 2 files changed, 2 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 1b544e650acf..b5aeb8dd2fb4 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -66,8 +66,6 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) precvpriv->adapter = padapter; - precvpriv->free_recvframe_cnt = NR_RECVFRAME; - precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(struct recv_frame) + RXFRAME_ALIGN_SZ); if (!precvpriv->pallocated_frame_buf) @@ -119,20 +117,11 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv) struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue) { struct recv_frame *hdr; - struct adapter *padapter; - struct recv_priv *precvpriv; hdr = list_first_entry_or_null(&pfree_recv_queue->queue, struct recv_frame, list); - if (hdr) { + if (hdr) list_del_init(&hdr->list); - padapter = hdr->adapter; - if (padapter) { - precvpriv = &padapter->recvpriv; - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt--; - } - } return hdr; } @@ -153,13 +142,8 @@ struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue) int rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_recv_queue) { - struct adapter *padapter; - struct recv_priv *precvpriv; - if (!precvframe) return _FAIL; - padapter = precvframe->adapter; - precvpriv = &padapter->recvpriv; if (precvframe->pkt) { dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */ precvframe->pkt = NULL; @@ -173,29 +157,16 @@ int rtw_free_recvframe(struct recv_frame *precvframe, list_add_tail(&(precvframe->list), get_list_head(pfree_recv_queue)); - if (padapter != NULL) { - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - - spin_unlock_bh(&pfree_recv_queue->lock); + spin_unlock_bh(&pfree_recv_queue->lock); return _SUCCESS; } int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) { - struct adapter *padapter = precvframe->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - list_del_init(&(precvframe->list)); list_add_tail(&(precvframe->list), get_list_head(queue)); - if (padapter != NULL) { - if (queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - return _SUCCESS; } diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index e95f4f2c71b3..40f97288282b 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -166,7 +166,6 @@ struct recv_priv { struct __queue uc_swdec_pending_queue; u8 *pallocated_frame_buf; u8 *precv_frame_buf; - uint free_recvframe_cnt; struct adapter *adapter; u32 bIsAnyNonBEPkts; u64 rx_bytes; -- cgit v1.2.3 From d7689c821d892be8fb8852d3c57d049129f0a2a2 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:29 +0700 Subject: staging:r8188eu: remove rx_pending_cnt member of recv_priv structure Value of this variable does not used. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 2 -- drivers/staging/rtl8188eu/include/rtw_recv.h | 2 -- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 4 ---- 3 files changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index b5aeb8dd2fb4..f046c41dd54d 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -87,8 +87,6 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) precvframe->adapter = padapter; precvframe++; } - precvpriv->rx_pending_cnt = 1; - res = rtw_hal_init_recv_priv(padapter); setup_timer(&precvpriv->signal_stat_timer, diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index 40f97288282b..ffbbbd15542a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -173,8 +173,6 @@ struct recv_priv { u64 rx_drop; u64 last_rx_bytes; - u8 rx_pending_cnt; - struct tasklet_struct irq_prepare_beacon_tasklet; struct tasklet_struct recv_tasklet; struct sk_buff_head free_recv_skb_queue; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index b87663b8e165..9347dcd4f3c2 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -384,8 +384,6 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete!!!\n")); - precvpriv->rx_pending_cnt--; - if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", @@ -490,8 +488,6 @@ u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf) precvbuf->reuse = false; } - precvpriv->rx_pending_cnt++; - purb = precvbuf->purb; /* translate DMA FIFO addr to pipehandle */ -- cgit v1.2.3 From d70c509152292cd4cc741f97ce043e0f65f72689 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:30 +0700 Subject: staging:r8188eu: remove precv_frame_buf member of recv_priv structure precv_frame_buf is used as local variable only in one function. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 4 +--- drivers/staging/rtl8188eu/include/rtw_recv.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index f046c41dd54d..a1b30a5ad568 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -71,9 +71,7 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) if (!precvpriv->pallocated_frame_buf) return _FAIL; - precvpriv->precv_frame_buf = PTR_ALIGN(precvpriv->pallocated_frame_buf, RXFRAME_ALIGN_SZ); - - precvframe = (struct recv_frame *)precvpriv->precv_frame_buf; + precvframe = (struct recv_frame *)PTR_ALIGN(precvpriv->pallocated_frame_buf, RXFRAME_ALIGN_SZ); for (i = 0; i < NR_RECVFRAME; i++) { INIT_LIST_HEAD(&(precvframe->list)); diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index ffbbbd15542a..979961d94c2a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -165,7 +165,6 @@ struct recv_priv { struct __queue recv_pending_queue; struct __queue uc_swdec_pending_queue; u8 *pallocated_frame_buf; - u8 *precv_frame_buf; struct adapter *adapter; u32 bIsAnyNonBEPkts; u64 rx_bytes; -- cgit v1.2.3 From 165601c98f564919d35bb4d1d8416028a5487a57 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:31 +0700 Subject: staging:r8188eu: change poiter type from u8 to void for pallocated_frame_buf member of recv_priv structure pallocated_frame_buf used only to preserve pointer for vfree function. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 2 +- drivers/staging/rtl8188eu/include/rtw_recv.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index a1b30a5ad568..3e6edb63d36b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -71,7 +71,7 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) if (!precvpriv->pallocated_frame_buf) return _FAIL; - precvframe = (struct recv_frame *)PTR_ALIGN(precvpriv->pallocated_frame_buf, RXFRAME_ALIGN_SZ); + precvframe = PTR_ALIGN(precvpriv->pallocated_frame_buf, RXFRAME_ALIGN_SZ); for (i = 0; i < NR_RECVFRAME; i++) { INIT_LIST_HEAD(&(precvframe->list)); diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index 979961d94c2a..052af7b891da 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -164,7 +164,7 @@ struct recv_priv { struct __queue free_recv_queue; struct __queue recv_pending_queue; struct __queue uc_swdec_pending_queue; - u8 *pallocated_frame_buf; + void *pallocated_frame_buf; struct adapter *adapter; u32 bIsAnyNonBEPkts; u64 rx_bytes; -- cgit v1.2.3 From cd30a392493215f3bed649ceac6f0aa53d4e92dd Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:32 +0700 Subject: staging:r8188eu: refactor recvbuf2recvframe function Reduce number of nesting levels. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 31 ++++++++++++------------ 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 9347dcd4f3c2..cc5208212a2a 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -172,22 +172,21 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n")); } - } else { - /* enqueue recvframe to txrtp queue */ - if (pattrib->pkt_rpt_type == TX_REPORT1) { - /* CCX-TXRPT ack for xmit mgmt frames. */ - handle_txrpt_ccx_88e(adapt, precvframe->rx_data); - } else if (pattrib->pkt_rpt_type == TX_REPORT2) { - ODM_RA_TxRPT2Handle_8188E( - &haldata->odmpriv, - precvframe->rx_data, - pattrib->pkt_len, - pattrib->MacIDValidEntry[0], - pattrib->MacIDValidEntry[1] - ); - } else if (pattrib->pkt_rpt_type == HIS_REPORT) { - interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->rx_data); - } + } else if (pattrib->pkt_rpt_type == TX_REPORT1) { + /* CCX-TXRPT ack for xmit mgmt frames. */ + handle_txrpt_ccx_88e(adapt, precvframe->rx_data); + rtw_free_recvframe(precvframe, pfree_recv_queue); + } else if (pattrib->pkt_rpt_type == TX_REPORT2) { + ODM_RA_TxRPT2Handle_8188E( + &haldata->odmpriv, + precvframe->rx_data, + pattrib->pkt_len, + pattrib->MacIDValidEntry[0], + pattrib->MacIDValidEntry[1] + ); + rtw_free_recvframe(precvframe, pfree_recv_queue); + } else if (pattrib->pkt_rpt_type == HIS_REPORT) { + interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->rx_data); rtw_free_recvframe(precvframe, pfree_recv_queue); } pkt_cnt--; -- cgit v1.2.3 From f346d62f33fe7cf320427a9153d1a4bdac1c62a2 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sat, 8 Oct 2016 01:01:33 +0700 Subject: staging:r8188eu: remove unnecessary type cast for update_recvframe_phyinfo_88e argument pphy_status alreay is (struct phy_stat *). Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index cc5208212a2a..34198fe16ca5 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -167,7 +167,7 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) } if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */ if (pattrib->physt) - update_recvframe_phyinfo_88e(precvframe, (struct phy_stat *)pphy_status); + update_recvframe_phyinfo_88e(precvframe, pphy_status); if (rtw_recv_entry(precvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n")); -- cgit v1.2.3 From 5a919c78871d1cd568e8d6ce4844c67c95eccf63 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:18 +0200 Subject: staging: wlan-ng: fix line style warnings in hfa384x_usb.c This patch fix the following checkpatch.pl warnings in hfa384x_usb.c: WARNING: line over 80 characters Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 71 +++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 6a107f8a06e2..395690fd0285 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -153,8 +153,8 @@ enum cmd_mode { static void dbprint_urb(struct urb *urb); #endif -static void -hfa384x_int_rxmonitor(struct wlandevice *wlandev, struct hfa384x_usb_rxfrm *rxfrm); +static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, + struct hfa384x_usb_rxfrm *rxfrm); static void hfa384x_usb_defer(struct work_struct *data); @@ -173,7 +173,8 @@ hfa384x_usbin_txcompl(struct wlandevice *wlandev, union hfa384x_usbin *usbin); static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb); -static void hfa384x_usbin_info(struct wlandevice *wlandev, union hfa384x_usbin *usbin); +static void hfa384x_usbin_info(struct wlandevice *wlandev, + union hfa384x_usbin *usbin); static void hfa384x_usbin_ctlx(struct hfa384x *hw, union hfa384x_usbin *usbin, int urb_status); @@ -193,9 +194,11 @@ static void hfa384x_usbctlx_completion_task(unsigned long data); static void hfa384x_usbctlx_reaper_task(unsigned long data); -static int hfa384x_usbctlx_submit(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); +static int hfa384x_usbctlx_submit(struct hfa384x *hw, + struct hfa384x_usbctlx *ctlx); -static void unlocked_usbctlx_complete(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); +static void unlocked_usbctlx_complete(struct hfa384x *hw, + struct hfa384x_usbctlx *ctlx); struct usbctlx_completor { int (*complete)(struct usbctlx_completor *); @@ -209,7 +212,8 @@ hfa384x_usbctlx_complete_sync(struct hfa384x *hw, static int unlocked_usbctlx_cancel_async(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); -static void hfa384x_cb_status(struct hfa384x *hw, const struct hfa384x_usbctlx *ctlx); +static void hfa384x_cb_status(struct hfa384x *hw, + const struct hfa384x_usbctlx *ctlx); static int usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, @@ -664,12 +668,10 @@ static inline int usbctlx_cmd_completor_fn(struct usbctlx_completor *head) return usbctlx_get_status(complete->cmdresp, complete->result); } -static inline struct usbctlx_completor *init_cmd_completor( - struct usbctlx_cmd_completor - *completor, - const struct hfa384x_usb_statusresp - *cmdresp, - struct hfa384x_cmdresult *result) +static inline struct usbctlx_completor * +init_cmd_completor(struct usbctlx_cmd_completor *completor, + const struct hfa384x_usb_statusresp *cmdresp, + struct hfa384x_cmdresult *result) { completor->head.complete = usbctlx_cmd_completor_fn; completor->cmdresp = cmdresp; @@ -710,13 +712,11 @@ static int usbctlx_rrid_completor_fn(struct usbctlx_completor *head) return 0; } -static inline struct usbctlx_completor *init_rrid_completor( - struct usbctlx_rrid_completor - *completor, - const struct hfa384x_usb_rridresp - *rridresp, - void *riddata, - unsigned int riddatalen) +static inline struct usbctlx_completor * +init_rrid_completor(struct usbctlx_rrid_completor *completor, + const struct hfa384x_usb_rridresp *rridresp, + void *riddata, + unsigned int riddatalen) { completor->head.complete = usbctlx_rrid_completor_fn; completor->rridresp = rridresp; @@ -759,13 +759,11 @@ static int usbctlx_rmem_completor_fn(struct usbctlx_completor *head) return 0; } -static inline struct usbctlx_completor *init_rmem_completor( - struct usbctlx_rmem_completor - *completor, - struct hfa384x_usb_rmemresp - *rmemresp, - void *data, - unsigned int len) +static inline struct usbctlx_completor * +init_rmem_completor(struct usbctlx_rmem_completor *completor, + struct hfa384x_usb_rmemresp *rmemresp, + void *data, + unsigned int len) { completor->head.complete = usbctlx_rmem_completor_fn; completor->rmemresp = rmemresp; @@ -795,7 +793,8 @@ static inline struct usbctlx_completor *init_rmem_completor( * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_cb_status(struct hfa384x *hw, const struct hfa384x_usbctlx *ctlx) +static void hfa384x_cb_status(struct hfa384x *hw, + const struct hfa384x_usbctlx *ctlx) { if (ctlx->usercb) { struct hfa384x_cmdresult cmdresult; @@ -812,7 +811,8 @@ static void hfa384x_cb_status(struct hfa384x *hw, const struct hfa384x_usbctlx * } } -static inline int hfa384x_docmd_wait(struct hfa384x *hw, struct hfa384x_metacmd *cmd) +static inline int hfa384x_docmd_wait(struct hfa384x *hw, + struct hfa384x_metacmd *cmd) { return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); } @@ -1136,7 +1136,8 @@ int hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_corereset(struct hfa384x *hw, int holdtime, int settletime, int genesis) +int hfa384x_corereset(struct hfa384x *hw, int holdtime, + int settletime, int genesis) { int result; @@ -1894,7 +1895,8 @@ int hfa384x_drvr_flashdl_disable(struct hfa384x *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) +int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, + void *buf, u32 len) { int result = 0; u32 dlbufaddr; @@ -2146,7 +2148,8 @@ int hfa384x_drvr_ramdl_enable(struct hfa384x *hw, u32 exeaddr) /* Check that we're not already in a download state */ if (hw->dlstate != HFA384x_DLSTATE_DISABLED) { - netdev_err(hw->wlandev->netdev, "Download state not disabled.\n"); + netdev_err(hw->wlandev->netdev, + "Download state not disabled.\n"); return -EINVAL; } @@ -2847,7 +2850,8 @@ static int unlocked_usbctlx_cancel_async(struct hfa384x *hw, * Call context: * Either, assume interrupt ----------------------------------------------------------------*/ -static void unlocked_usbctlx_complete(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) +static void unlocked_usbctlx_complete(struct hfa384x *hw, + struct hfa384x_usbctlx *ctlx) { /* Timers have been stopped, and ctlx should be in * a terminal state. Retire it from the "active" @@ -3886,7 +3890,8 @@ static void hfa384x_usb_throttlefn(unsigned long data) * Call context: * process or interrupt ----------------------------------------------------------------*/ -static int hfa384x_usbctlx_submit(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) +static int hfa384x_usbctlx_submit(struct hfa384x *hw, + struct hfa384x_usbctlx *ctlx) { unsigned long flags; -- cgit v1.2.3 From d3fcb8a2769a01cff359de693d2864ae2b43dc8f Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:19 +0200 Subject: staging: wlan-ng: fix block comment warnings in hfa384x_usb.c This patch fix the following checkpatch.pl warnings in hfa384x_usb.c: WARNING: Block comments should align the * on each line WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 2370 +++++++++++++++++---------------- 1 file changed, 1213 insertions(+), 1157 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 395690fd0285..1bfea8db3374 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -1,114 +1,114 @@ /* src/prism2/driver/hfa384x_usb.c -* -* Functions that talk to the USB variantof the Intersil hfa384x MAC -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file implements functions that correspond to the prism2/hfa384x -* 802.11 MAC hardware and firmware host interface. -* -* The functions can be considered to represent several levels of -* abstraction. The lowest level functions are simply C-callable wrappers -* around the register accesses. The next higher level represents C-callable -* prism2 API functions that match the Intersil documentation as closely -* as is reasonable. The next higher layer implements common sequences -* of invocations of the API layer (e.g. write to bap, followed by cmd). -* -* Common sequences: -* hfa384x_drvr_xxx Highest level abstractions provided by the -* hfa384x code. They are driver defined wrappers -* for common sequences. These functions generally -* use the services of the lower levels. -* -* hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These -* functions are wrappers for the RID get/set -* sequence. They call copy_[to|from]_bap() and -* cmd_access(). These functions operate on the -* RIDs and buffers without validation. The caller -* is responsible for that. -* -* API wrapper functions: -* hfa384x_cmd_xxx functions that provide access to the f/w commands. -* The function arguments correspond to each command -* argument, even command arguments that get packed -* into single registers. These functions _just_ -* issue the command by setting the cmd/parm regs -* & reading the status/resp regs. Additional -* activities required to fully use a command -* (read/write from/to bap, get/set int status etc.) -* are implemented separately. Think of these as -* C-callable prism2 commands. -* -* Lowest Layer Functions: -* hfa384x_docmd_xxx These functions implement the sequence required -* to issue any prism2 command. Primarily used by the -* hfa384x_cmd_xxx functions. -* -* hfa384x_bap_xxx BAP read/write access functions. -* Note: we usually use BAP0 for non-interrupt context -* and BAP1 for interrupt context. -* -* hfa384x_dl_xxx download related functions. -* -* Driver State Issues: -* Note that there are two pairs of functions that manage the -* 'initialized' and 'running' states of the hw/MAC combo. The four -* functions are create(), destroy(), start(), and stop(). create() -* sets up the data structures required to support the hfa384x_* -* functions and destroy() cleans them up. The start() function gets -* the actual hardware running and enables the interrupts. The stop() -* function shuts the hardware down. The sequence should be: -* create() -* start() -* . -* . Do interesting things w/ the hardware -* . -* stop() -* destroy() -* -* Note that destroy() can be called without calling stop() first. -* -------------------------------------------------------------------- -*/ + * + * Functions that talk to the USB variantof the Intersil hfa384x MAC + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file implements functions that correspond to the prism2/hfa384x + * 802.11 MAC hardware and firmware host interface. + * + * The functions can be considered to represent several levels of + * abstraction. The lowest level functions are simply C-callable wrappers + * around the register accesses. The next higher level represents C-callable + * prism2 API functions that match the Intersil documentation as closely + * as is reasonable. The next higher layer implements common sequences + * of invocations of the API layer (e.g. write to bap, followed by cmd). + * + * Common sequences: + * hfa384x_drvr_xxx Highest level abstractions provided by the + * hfa384x code. They are driver defined wrappers + * for common sequences. These functions generally + * use the services of the lower levels. + * + * hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These + * functions are wrappers for the RID get/set + * sequence. They call copy_[to|from]_bap() and + * cmd_access(). These functions operate on the + * RIDs and buffers without validation. The caller + * is responsible for that. + * + * API wrapper functions: + * hfa384x_cmd_xxx functions that provide access to the f/w commands. + * The function arguments correspond to each command + * argument, even command arguments that get packed + * into single registers. These functions _just_ + * issue the command by setting the cmd/parm regs + * & reading the status/resp regs. Additional + * activities required to fully use a command + * (read/write from/to bap, get/set int status etc.) + * are implemented separately. Think of these as + * C-callable prism2 commands. + * + * Lowest Layer Functions: + * hfa384x_docmd_xxx These functions implement the sequence required + * to issue any prism2 command. Primarily used by the + * hfa384x_cmd_xxx functions. + * + * hfa384x_bap_xxx BAP read/write access functions. + * Note: we usually use BAP0 for non-interrupt context + * and BAP1 for interrupt context. + * + * hfa384x_dl_xxx download related functions. + * + * Driver State Issues: + * Note that there are two pairs of functions that manage the + * 'initialized' and 'running' states of the hw/MAC combo. The four + * functions are create(), destroy(), start(), and stop(). create() + * sets up the data structures required to support the hfa384x_* + * functions and destroy() cleans them up. The start() function gets + * the actual hardware running and enables the interrupts. The stop() + * function shuts the hardware down. The sequence should be: + * create() + * start() + * . + * . Do interesting things w/ the hardware + * . + * stop() + * destroy() + * + * Note that destroy() can be called without calling stop() first. + * -------------------------------------------------------------------- + */ #include #include @@ -311,21 +311,22 @@ void dbprint_urb(struct urb *urb) #endif /*---------------------------------------------------------------- -* submit_rx_urb -* -* Listen for input data on the BULK-IN pipe. If the pipe has -* stalled then schedule it to be reset. -* -* Arguments: -* hw device struct -* memflags memory allocation flags -* -* Returns: -* error code from submission -* -* Call context: -* Any -----------------------------------------------------------------*/ + * submit_rx_urb + * + * Listen for input data on the BULK-IN pipe. If the pipe has + * stalled then schedule it to be reset. + * + * Arguments: + * hw device struct + * memflags memory allocation flags + * + * Returns: + * error code from submission + * + * Call context: + * Any + *---------------------------------------------------------------- + */ static int submit_rx_urb(struct hfa384x *hw, gfp_t memflags) { struct sk_buff *skb; @@ -371,23 +372,24 @@ done: } /*---------------------------------------------------------------- -* submit_tx_urb -* -* Prepares and submits the URB of transmitted data. If the -* submission fails then it will schedule the output pipe to -* be reset. -* -* Arguments: -* hw device struct -* tx_urb URB of data for transmission -* memflags memory allocation flags -* -* Returns: -* error code from submission -* -* Call context: -* Any -----------------------------------------------------------------*/ + * submit_tx_urb + * + * Prepares and submits the URB of transmitted data. If the + * submission fails then it will schedule the output pipe to + * be reset. + * + * Arguments: + * hw device struct + * tx_urb URB of data for transmission + * memflags memory allocation flags + * + * Returns: + * error code from submission + * + * Call context: + * Any + *---------------------------------------------------------------- + */ static int submit_tx_urb(struct hfa384x *hw, struct urb *tx_urb, gfp_t memflags) { struct net_device *netdev = hw->wlandev->netdev; @@ -416,21 +418,22 @@ static int submit_tx_urb(struct hfa384x *hw, struct urb *tx_urb, gfp_t memflags) } /*---------------------------------------------------------------- -* hfa394x_usb_defer -* -* There are some things that the USB stack cannot do while -* in interrupt context, so we arrange this function to run -* in process context. -* -* Arguments: -* hw device structure -* -* Returns: -* nothing -* -* Call context: -* process (by design) -----------------------------------------------------------------*/ + * hfa394x_usb_defer + * + * There are some things that the USB stack cannot do while + * in interrupt context, so we arrange this function to run + * in process context. + * + * Arguments: + * hw device structure + * + * Returns: + * nothing + * + * Call context: + * process (by design) + *---------------------------------------------------------------- + */ static void hfa384x_usb_defer(struct work_struct *data) { struct hfa384x *hw = container_of(data, struct hfa384x, usb_work); @@ -505,26 +508,27 @@ static void hfa384x_usb_defer(struct work_struct *data) } /*---------------------------------------------------------------- -* hfa384x_create -* -* Sets up the struct hfa384x data structure for use. Note this -* does _not_ initialize the actual hardware, just the data structures -* we use to keep track of its state. -* -* Arguments: -* hw device structure -* irq device irq number -* iobase i/o base address for register access -* membase memory base address for register access -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_create + * + * Sets up the struct hfa384x data structure for use. Note this + * does _not_ initialize the actual hardware, just the data structures + * we use to keep track of its state. + * + * Arguments: + * hw device structure + * irq device irq number + * iobase i/o base address for register access + * membase memory base address for register access + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ void hfa384x_create(struct hfa384x *hw, struct usb_device *usb) { memset(hw, 0, sizeof(struct hfa384x)); @@ -575,27 +579,28 @@ void hfa384x_create(struct hfa384x *hw, struct usb_device *usb) } /*---------------------------------------------------------------- -* hfa384x_destroy -* -* Partner to hfa384x_create(). This function cleans up the hw -* structure so that it can be freed by the caller using a simple -* kfree. Currently, this function is just a placeholder. If, at some -* point in the future, an hw in the 'shutdown' state requires a 'deep' -* kfree, this is where it should be done. Note that if this function -* is called on a _running_ hw structure, the drvr_stop() function is -* called. -* -* Arguments: -* hw device structure -* -* Returns: -* nothing, this function is not allowed to fail. -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_destroy + * + * Partner to hfa384x_create(). This function cleans up the hw + * structure so that it can be freed by the caller using a simple + * kfree. Currently, this function is just a placeholder. If, at some + * point in the future, an hw in the 'shutdown' state requires a 'deep' + * kfree, this is where it should be done. Note that if this function + * is called on a _running_ hw structure, the drvr_stop() function is + * called. + * + * Arguments: + * hw device structure + * + * Returns: + * nothing, this function is not allowed to fail. + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ void hfa384x_destroy(struct hfa384x *hw) { struct sk_buff *skb; @@ -649,10 +654,11 @@ usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, } /*---------------------------------------------------------------- -* Completor object: -* This completor must be passed to hfa384x_usbctlx_complete_sync() -* when processing a CTLX that returns a struct hfa384x_cmdresult structure. -----------------------------------------------------------------*/ + * Completor object: + * This completor must be passed to hfa384x_usbctlx_complete_sync() + * when processing a CTLX that returns a struct hfa384x_cmdresult structure. + *---------------------------------------------------------------- + */ struct usbctlx_cmd_completor { struct usbctlx_completor head; @@ -680,10 +686,11 @@ init_cmd_completor(struct usbctlx_cmd_completor *completor, } /*---------------------------------------------------------------- -* Completor object: -* This completor must be passed to hfa384x_usbctlx_complete_sync() -* when processing a CTLX that reads a RID. -----------------------------------------------------------------*/ + * Completor object: + * This completor must be passed to hfa384x_usbctlx_complete_sync() + * when processing a CTLX that reads a RID. + *---------------------------------------------------------------- + */ struct usbctlx_rrid_completor { struct usbctlx_completor head; @@ -726,21 +733,24 @@ init_rrid_completor(struct usbctlx_rrid_completor *completor, } /*---------------------------------------------------------------- -* Completor object: -* Interprets the results of a synchronous RID-write -----------------------------------------------------------------*/ + * Completor object: + * Interprets the results of a synchronous RID-write + *---------------------------------------------------------------- + */ #define init_wrid_completor init_cmd_completor /*---------------------------------------------------------------- -* Completor object: -* Interprets the results of a synchronous memory-write -----------------------------------------------------------------*/ + * Completor object: + * Interprets the results of a synchronous memory-write + *---------------------------------------------------------------- + */ #define init_wmem_completor init_cmd_completor /*---------------------------------------------------------------- -* Completor object: -* Interprets the results of a synchronous memory-read -----------------------------------------------------------------*/ + * Completor object: + * Interprets the results of a synchronous memory-read + *---------------------------------------------------------------- + */ struct usbctlx_rmem_completor { struct usbctlx_completor head; @@ -773,26 +783,27 @@ init_rmem_completor(struct usbctlx_rmem_completor *completor, } /*---------------------------------------------------------------- -* hfa384x_cb_status -* -* Ctlx_complete handler for async CMD type control exchanges. -* mark the hw struct as such. -* -* Note: If the handling is changed here, it should probably be -* changed in docmd as well. -* -* Arguments: -* hw hw struct -* ctlx completed CTLX -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_cb_status + * + * Ctlx_complete handler for async CMD type control exchanges. + * mark the hw struct as such. + * + * Note: If the handling is changed here, it should probably be + * changed in docmd as well. + * + * Arguments: + * hw hw struct + * ctlx completed CTLX + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_cb_status(struct hfa384x *hw, const struct hfa384x_usbctlx *ctlx) { @@ -905,24 +916,25 @@ hfa384x_dowmem_async(struct hfa384x *hw, } /*---------------------------------------------------------------- -* hfa384x_cmd_initialize -* -* Issues the initialize command and sets the hw->state based -* on the result. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_cmd_initialize + * + * Issues the initialize command and sets the hw->state based + * on the result. + * + * Arguments: + * hw device structure + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_cmd_initialize(struct hfa384x *hw) { int result = 0; @@ -950,25 +962,26 @@ int hfa384x_cmd_initialize(struct hfa384x *hw) } /*---------------------------------------------------------------- -* hfa384x_cmd_disable -* -* Issues the disable command to stop communications on one of -* the MACs 'ports'. -* -* Arguments: -* hw device structure -* macport MAC port number (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_cmd_disable + * + * Issues the disable command to stop communications on one of + * the MACs 'ports'. + * + * Arguments: + * hw device structure + * macport MAC port number (host order) + * + * Returns: + * 0 success + * >0 f/w reported failure - f/w status code + * <0 driver reported error (timeout|bad arg) + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport) { struct hfa384x_metacmd cmd; @@ -983,25 +996,26 @@ int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport) } /*---------------------------------------------------------------- -* hfa384x_cmd_enable -* -* Issues the enable command to enable communications on one of -* the MACs 'ports'. -* -* Arguments: -* hw device structure -* macport MAC port number -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_cmd_enable + * + * Issues the enable command to enable communications on one of + * the MACs 'ports'. + * + * Arguments: + * hw device structure + * macport MAC port number + * + * Returns: + * 0 success + * >0 f/w reported failure - f/w status code + * <0 driver reported error (timeout|bad arg) + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport) { struct hfa384x_metacmd cmd; @@ -1016,34 +1030,35 @@ int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport) } /*---------------------------------------------------------------- -* hfa384x_cmd_monitor -* -* Enables the 'monitor mode' of the MAC. Here's the description of -* monitor mode that I've received thus far: -* -* "The "monitor mode" of operation is that the MAC passes all -* frames for which the PLCP checks are correct. All received -* MPDUs are passed to the host with MAC Port = 7, with a -* receive status of good, FCS error, or undecryptable. Passing -* certain MPDUs is a violation of the 802.11 standard, but useful -* for a debugging tool." Normal communication is not possible -* while monitor mode is enabled. -* -* Arguments: -* hw device structure -* enable a code (0x0b|0x0f) that enables/disables -* monitor mode. (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_cmd_monitor + * + * Enables the 'monitor mode' of the MAC. Here's the description of + * monitor mode that I've received thus far: + * + * "The "monitor mode" of operation is that the MAC passes all + * frames for which the PLCP checks are correct. All received + * MPDUs are passed to the host with MAC Port = 7, with a + * receive status of good, FCS error, or undecryptable. Passing + * certain MPDUs is a violation of the 802.11 standard, but useful + * for a debugging tool." Normal communication is not possible + * while monitor mode is enabled. + * + * Arguments: + * hw device structure + * enable a code (0x0b|0x0f) that enables/disables + * monitor mode. (host order) + * + * Returns: + * 0 success + * >0 f/w reported failure - f/w status code + * <0 driver reported error (timeout|bad arg) + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable) { struct hfa384x_metacmd cmd; @@ -1058,43 +1073,44 @@ int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable) } /*---------------------------------------------------------------- -* hfa384x_cmd_download -* -* Sets the controls for the MAC controller code/data download -* process. The arguments set the mode and address associated -* with a download. Note that the aux registers should be enabled -* prior to setting one of the download enable modes. -* -* Arguments: -* hw device structure -* mode 0 - Disable programming and begin code exec -* 1 - Enable volatile mem programming -* 2 - Enable non-volatile mem programming -* 3 - Program non-volatile section from NV download -* buffer. -* (host order) -* lowaddr -* highaddr For mode 1, sets the high & low order bits of -* the "destination address". This address will be -* the execution start address when download is -* subsequently disabled. -* For mode 2, sets the high & low order bits of -* the destination in NV ram. -* For modes 0 & 3, should be zero. (host order) -* NOTE: these are CMD format. -* codelen Length of the data to write in mode 2, -* zero otherwise. (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_cmd_download + * + * Sets the controls for the MAC controller code/data download + * process. The arguments set the mode and address associated + * with a download. Note that the aux registers should be enabled + * prior to setting one of the download enable modes. + * + * Arguments: + * hw device structure + * mode 0 - Disable programming and begin code exec + * 1 - Enable volatile mem programming + * 2 - Enable non-volatile mem programming + * 3 - Program non-volatile section from NV download + * buffer. + * (host order) + * lowaddr + * highaddr For mode 1, sets the high & low order bits of + * the "destination address". This address will be + * the execution start address when download is + * subsequently disabled. + * For mode 2, sets the high & low order bits of + * the destination in NV ram. + * For modes 0 & 3, should be zero. (host order) + * NOTE: these are CMD format. + * codelen Length of the data to write in mode 2, + * zero otherwise. (host order) + * + * Returns: + * 0 success + * >0 f/w reported failure - f/w status code + * <0 driver reported error (timeout|bad arg) + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, u16 highaddr, u16 codelen) { @@ -1114,28 +1130,29 @@ int hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, } /*---------------------------------------------------------------- -* hfa384x_corereset -* -* Perform a reset of the hfa38xx MAC core. We assume that the hw -* structure is in its "created" state. That is, it is initialized -* with proper values. Note that if a reset is done after the -* device has been active for awhile, the caller might have to clean -* up some leftover cruft in the hw structure. -* -* Arguments: -* hw device structure -* holdtime how long (in ms) to hold the reset -* settletime how long (in ms) to wait after releasing -* the reset -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_corereset + * + * Perform a reset of the hfa38xx MAC core. We assume that the hw + * structure is in its "created" state. That is, it is initialized + * with proper values. Note that if a reset is done after the + * device has been active for awhile, the caller might have to clean + * up some leftover cruft in the hw structure. + * + * Arguments: + * hw device structure + * holdtime how long (in ms) to hold the reset + * settletime how long (in ms) to wait after releasing + * the reset + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_corereset(struct hfa384x *hw, int holdtime, int settletime, int genesis) { @@ -1151,29 +1168,30 @@ int hfa384x_corereset(struct hfa384x *hw, int holdtime, } /*---------------------------------------------------------------- -* hfa384x_usbctlx_complete_sync -* -* Waits for a synchronous CTLX object to complete, -* and then handles the response. -* -* Arguments: -* hw device structure -* ctlx CTLX ptr -* completor functor object to decide what to -* do with the CTLX's result. -* -* Returns: -* 0 Success -* -ERESTARTSYS Interrupted by a signal -* -EIO CTLX failed -* -ENODEV Adapter was unplugged -* ??? Result from completor -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_usbctlx_complete_sync + * + * Waits for a synchronous CTLX object to complete, + * and then handles the response. + * + * Arguments: + * hw device structure + * ctlx CTLX ptr + * completor functor object to decide what to + * do with the CTLX's result. + * + * Returns: + * 0 Success + * -ERESTARTSYS Interrupted by a signal + * -EIO CTLX failed + * -ENODEV Adapter was unplugged + * ??? Result from completor + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ static int hfa384x_usbctlx_complete_sync(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx, struct usbctlx_completor *completor) @@ -1258,37 +1276,38 @@ cleanup: } /*---------------------------------------------------------------- -* hfa384x_docmd -* -* Constructs a command CTLX and submits it. -* -* NOTE: Any changes to the 'post-submit' code in this function -* need to be carried over to hfa384x_cbcmd() since the handling -* is virtually identical. -* -* Arguments: -* hw device structure -* mode DOWAIT or DOASYNC -* cmd cmd structure. Includes all arguments and result -* data points. All in host order. in host order -* cmdcb command-specific callback -* usercb user callback for async calls, NULL for DOWAIT calls -* usercb_data user supplied data pointer for async calls, NULL -* for DOASYNC calls -* -* Returns: -* 0 success -* -EIO CTLX failure -* -ERESTARTSYS Awakened on signal -* >0 command indicated error, Status and Resp0-2 are -* in hw structure. -* -* Side effects: -* -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_docmd + * + * Constructs a command CTLX and submits it. + * + * NOTE: Any changes to the 'post-submit' code in this function + * need to be carried over to hfa384x_cbcmd() since the handling + * is virtually identical. + * + * Arguments: + * hw device structure + * mode DOWAIT or DOASYNC + * cmd cmd structure. Includes all arguments and result + * data points. All in host order. in host order + * cmdcb command-specific callback + * usercb user callback for async calls, NULL for DOWAIT calls + * usercb_data user supplied data pointer for async calls, NULL + * for DOASYNC calls + * + * Returns: + * 0 success + * -EIO CTLX failure + * -ERESTARTSYS Awakened on signal + * >0 command indicated error, Status and Resp0-2 are + * in hw structure. + * + * Side effects: + * + * + * Call context: + * process + *---------------------------------------------------------------- + */ static int hfa384x_docmd(struct hfa384x *hw, enum cmd_mode mode, @@ -1342,41 +1361,42 @@ done: } /*---------------------------------------------------------------- -* hfa384x_dorrid -* -* Constructs a read rid CTLX and issues it. -* -* NOTE: Any changes to the 'post-submit' code in this function -* need to be carried over to hfa384x_cbrrid() since the handling -* is virtually identical. -* -* Arguments: -* hw device structure -* mode DOWAIT or DOASYNC -* rid Read RID number (host order) -* riddata Caller supplied buffer that MAC formatted RID.data -* record will be written to for DOWAIT calls. Should -* be NULL for DOASYNC calls. -* riddatalen Buffer length for DOWAIT calls. Zero for DOASYNC calls. -* cmdcb command callback for async calls, NULL for DOWAIT calls -* usercb user callback for async calls, NULL for DOWAIT calls -* usercb_data user supplied data pointer for async calls, NULL -* for DOWAIT calls -* -* Returns: -* 0 success -* -EIO CTLX failure -* -ERESTARTSYS Awakened on signal -* -ENODATA riddatalen != macdatalen -* >0 command indicated error, Status and Resp0-2 are -* in hw structure. -* -* Side effects: -* -* Call context: -* interrupt (DOASYNC) -* process (DOWAIT or DOASYNC) -----------------------------------------------------------------*/ + * hfa384x_dorrid + * + * Constructs a read rid CTLX and issues it. + * + * NOTE: Any changes to the 'post-submit' code in this function + * need to be carried over to hfa384x_cbrrid() since the handling + * is virtually identical. + * + * Arguments: + * hw device structure + * mode DOWAIT or DOASYNC + * rid Read RID number (host order) + * riddata Caller supplied buffer that MAC formatted RID.data + * record will be written to for DOWAIT calls. Should + * be NULL for DOASYNC calls. + * riddatalen Buffer length for DOWAIT calls. Zero for DOASYNC calls. + * cmdcb command callback for async calls, NULL for DOWAIT calls + * usercb user callback for async calls, NULL for DOWAIT calls + * usercb_data user supplied data pointer for async calls, NULL + * for DOWAIT calls + * + * Returns: + * 0 success + * -EIO CTLX failure + * -ERESTARTSYS Awakened on signal + * -ENODATA riddatalen != macdatalen + * >0 command indicated error, Status and Resp0-2 are + * in hw structure. + * + * Side effects: + * + * Call context: + * interrupt (DOASYNC) + * process (DOWAIT or DOASYNC) + *---------------------------------------------------------------- + */ static int hfa384x_dorrid(struct hfa384x *hw, enum cmd_mode mode, @@ -1427,37 +1447,38 @@ done: } /*---------------------------------------------------------------- -* hfa384x_dowrid -* -* Constructs a write rid CTLX and issues it. -* -* NOTE: Any changes to the 'post-submit' code in this function -* need to be carried over to hfa384x_cbwrid() since the handling -* is virtually identical. -* -* Arguments: -* hw device structure -* enum cmd_mode DOWAIT or DOASYNC -* rid RID code -* riddata Data portion of RID formatted for MAC -* riddatalen Length of the data portion in bytes -* cmdcb command callback for async calls, NULL for DOWAIT calls -* usercb user callback for async calls, NULL for DOWAIT calls -* usercb_data user supplied data pointer for async calls -* -* Returns: -* 0 success -* -ETIMEDOUT timed out waiting for register ready or -* command completion -* >0 command indicated error, Status and Resp0-2 are -* in hw structure. -* -* Side effects: -* -* Call context: -* interrupt (DOASYNC) -* process (DOWAIT or DOASYNC) -----------------------------------------------------------------*/ + * hfa384x_dowrid + * + * Constructs a write rid CTLX and issues it. + * + * NOTE: Any changes to the 'post-submit' code in this function + * need to be carried over to hfa384x_cbwrid() since the handling + * is virtually identical. + * + * Arguments: + * hw device structure + * enum cmd_mode DOWAIT or DOASYNC + * rid RID code + * riddata Data portion of RID formatted for MAC + * riddatalen Length of the data portion in bytes + * cmdcb command callback for async calls, NULL for DOWAIT calls + * usercb user callback for async calls, NULL for DOWAIT calls + * usercb_data user supplied data pointer for async calls + * + * Returns: + * 0 success + * -ETIMEDOUT timed out waiting for register ready or + * command completion + * >0 command indicated error, Status and Resp0-2 are + * in hw structure. + * + * Side effects: + * + * Call context: + * interrupt (DOASYNC) + * process (DOWAIT or DOASYNC) + *---------------------------------------------------------------- + */ static int hfa384x_dowrid(struct hfa384x *hw, enum cmd_mode mode, @@ -1513,38 +1534,39 @@ done: } /*---------------------------------------------------------------- -* hfa384x_dormem -* -* Constructs a readmem CTLX and issues it. -* -* NOTE: Any changes to the 'post-submit' code in this function -* need to be carried over to hfa384x_cbrmem() since the handling -* is virtually identical. -* -* Arguments: -* hw device structure -* mode DOWAIT or DOASYNC -* page MAC address space page (CMD format) -* offset MAC address space offset -* data Ptr to data buffer to receive read -* len Length of the data to read (max == 2048) -* cmdcb command callback for async calls, NULL for DOWAIT calls -* usercb user callback for async calls, NULL for DOWAIT calls -* usercb_data user supplied data pointer for async calls -* -* Returns: -* 0 success -* -ETIMEDOUT timed out waiting for register ready or -* command completion -* >0 command indicated error, Status and Resp0-2 are -* in hw structure. -* -* Side effects: -* -* Call context: -* interrupt (DOASYNC) -* process (DOWAIT or DOASYNC) -----------------------------------------------------------------*/ + * hfa384x_dormem + * + * Constructs a readmem CTLX and issues it. + * + * NOTE: Any changes to the 'post-submit' code in this function + * need to be carried over to hfa384x_cbrmem() since the handling + * is virtually identical. + * + * Arguments: + * hw device structure + * mode DOWAIT or DOASYNC + * page MAC address space page (CMD format) + * offset MAC address space offset + * data Ptr to data buffer to receive read + * len Length of the data to read (max == 2048) + * cmdcb command callback for async calls, NULL for DOWAIT calls + * usercb user callback for async calls, NULL for DOWAIT calls + * usercb_data user supplied data pointer for async calls + * + * Returns: + * 0 success + * -ETIMEDOUT timed out waiting for register ready or + * command completion + * >0 command indicated error, Status and Resp0-2 are + * in hw structure. + * + * Side effects: + * + * Call context: + * interrupt (DOASYNC) + * process (DOWAIT or DOASYNC) + *---------------------------------------------------------------- + */ static int hfa384x_dormem(struct hfa384x *hw, enum cmd_mode mode, @@ -1604,38 +1626,39 @@ done: } /*---------------------------------------------------------------- -* hfa384x_dowmem -* -* Constructs a writemem CTLX and issues it. -* -* NOTE: Any changes to the 'post-submit' code in this function -* need to be carried over to hfa384x_cbwmem() since the handling -* is virtually identical. -* -* Arguments: -* hw device structure -* mode DOWAIT or DOASYNC -* page MAC address space page (CMD format) -* offset MAC address space offset -* data Ptr to data buffer containing write data -* len Length of the data to read (max == 2048) -* cmdcb command callback for async calls, NULL for DOWAIT calls -* usercb user callback for async calls, NULL for DOWAIT calls -* usercb_data user supplied data pointer for async calls. -* -* Returns: -* 0 success -* -ETIMEDOUT timed out waiting for register ready or -* command completion -* >0 command indicated error, Status and Resp0-2 are -* in hw structure. -* -* Side effects: -* -* Call context: -* interrupt (DOWAIT) -* process (DOWAIT or DOASYNC) -----------------------------------------------------------------*/ + * hfa384x_dowmem + * + * Constructs a writemem CTLX and issues it. + * + * NOTE: Any changes to the 'post-submit' code in this function + * need to be carried over to hfa384x_cbwmem() since the handling + * is virtually identical. + * + * Arguments: + * hw device structure + * mode DOWAIT or DOASYNC + * page MAC address space page (CMD format) + * offset MAC address space offset + * data Ptr to data buffer containing write data + * len Length of the data to read (max == 2048) + * cmdcb command callback for async calls, NULL for DOWAIT calls + * usercb user callback for async calls, NULL for DOWAIT calls + * usercb_data user supplied data pointer for async calls. + * + * Returns: + * 0 success + * -ETIMEDOUT timed out waiting for register ready or + * command completion + * >0 command indicated error, Status and Resp0-2 are + * in hw structure. + * + * Side effects: + * + * Call context: + * interrupt (DOWAIT) + * process (DOWAIT or DOASYNC) + *---------------------------------------------------------------- + */ static int hfa384x_dowmem(struct hfa384x *hw, enum cmd_mode mode, @@ -1695,27 +1718,28 @@ done: } /*---------------------------------------------------------------- -* hfa384x_drvr_disable -* -* Issues the disable command to stop communications on one of -* the MACs 'ports'. Only macport 0 is valid for stations. -* APs may also disable macports 1-6. Only ports that have been -* previously enabled may be disabled. -* -* Arguments: -* hw device structure -* macport MAC port number (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_disable + * + * Issues the disable command to stop communications on one of + * the MACs 'ports'. Only macport 0 is valid for stations. + * APs may also disable macports 1-6. Only ports that have been + * previously enabled may be disabled. + * + * Arguments: + * hw device structure + * macport MAC port number (host order) + * + * Returns: + * 0 success + * >0 f/w reported failure - f/w status code + * <0 driver reported error (timeout|bad arg) + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_disable(struct hfa384x *hw, u16 macport) { int result = 0; @@ -1733,27 +1757,28 @@ int hfa384x_drvr_disable(struct hfa384x *hw, u16 macport) } /*---------------------------------------------------------------- -* hfa384x_drvr_enable -* -* Issues the enable command to enable communications on one of -* the MACs 'ports'. Only macport 0 is valid for stations. -* APs may also enable macports 1-6. Only ports that are currently -* disabled may be enabled. -* -* Arguments: -* hw device structure -* macport MAC port number -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_enable + * + * Issues the enable command to enable communications on one of + * the MACs 'ports'. Only macport 0 is valid for stations. + * APs may also enable macports 1-6. Only ports that are currently + * disabled may be enabled. + * + * Arguments: + * hw device structure + * macport MAC port number + * + * Returns: + * 0 success + * >0 f/w reported failure - f/w status code + * <0 driver reported error (timeout|bad arg) + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_enable(struct hfa384x *hw, u16 macport) { int result = 0; @@ -1771,26 +1796,27 @@ int hfa384x_drvr_enable(struct hfa384x *hw, u16 macport) } /*---------------------------------------------------------------- -* hfa384x_drvr_flashdl_enable -* -* Begins the flash download state. Checks to see that we're not -* already in a download state and that a port isn't enabled. -* Sets the download state and retrieves the flash download -* buffer location, buffer size, and timeout length. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_flashdl_enable + * + * Begins the flash download state. Checks to see that we're not + * already in a download state and that a port isn't enabled. + * Sets the download state and retrieves the flash download + * buffer location, buffer size, and timeout length. + * + * Arguments: + * hw device structure + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_flashdl_enable(struct hfa384x *hw) { int result = 0; @@ -1832,24 +1858,25 @@ int hfa384x_drvr_flashdl_enable(struct hfa384x *hw) } /*---------------------------------------------------------------- -* hfa384x_drvr_flashdl_disable -* -* Ends the flash download state. Note that this will cause the MAC -* firmware to restart. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_flashdl_disable + * + * Ends the flash download state. Note that this will cause the MAC + * firmware to restart. + * + * Arguments: + * hw device structure + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_flashdl_disable(struct hfa384x *hw) { /* Check that we're already in the download state */ @@ -1867,34 +1894,35 @@ int hfa384x_drvr_flashdl_disable(struct hfa384x *hw) } /*---------------------------------------------------------------- -* hfa384x_drvr_flashdl_write -* -* Performs a FLASH download of a chunk of data. First checks to see -* that we're in the FLASH download state, then sets the download -* mode, uses the aux functions to 1) copy the data to the flash -* buffer, 2) sets the download 'write flash' mode, 3) readback and -* compare. Lather rinse, repeat as many times an necessary to get -* all the given data into flash. -* When all data has been written using this function (possibly -* repeatedly), call drvr_flashdl_disable() to end the download state -* and restart the MAC. -* -* Arguments: -* hw device structure -* daddr Card address to write to. (host order) -* buf Ptr to data to write. -* len Length of data (host order). -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_flashdl_write + * + * Performs a FLASH download of a chunk of data. First checks to see + * that we're in the FLASH download state, then sets the download + * mode, uses the aux functions to 1) copy the data to the flash + * buffer, 2) sets the download 'write flash' mode, 3) readback and + * compare. Lather rinse, repeat as many times an necessary to get + * all the given data into flash. + * When all data has been written using this function (possibly + * repeatedly), call drvr_flashdl_disable() to end the download state + * and restart the MAC. + * + * Arguments: + * hw device structure + * daddr Card address to write to. (host order) + * buf Ptr to data to write. + * len Length of data (host order). + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) { @@ -2010,30 +2038,31 @@ exit_proc: } /*---------------------------------------------------------------- -* hfa384x_drvr_getconfig -* -* Performs the sequence necessary to read a config/info item. -* -* Arguments: -* hw device structure -* rid config/info record id (host order) -* buf host side record buffer. Upon return it will -* contain the body portion of the record (minus the -* RID and len). -* len buffer length (in bytes, should match record length) -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -ENODATA length mismatch between argument and retrieved -* record. -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_getconfig + * + * Performs the sequence necessary to read a config/info item. + * + * Arguments: + * hw device structure + * rid config/info record id (host order) + * buf host side record buffer. Upon return it will + * contain the body portion of the record (minus the + * RID and len). + * len buffer length (in bytes, should match record length) + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * -ENODATA length mismatch between argument and retrieved + * record. + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { return hfa384x_dorrid_wait(hw, rid, buf, len); @@ -2061,7 +2090,8 @@ int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) * * Call context: * process - ----------------------------------------------------------------*/ + *---------------------------------------------------------------- + */ int hfa384x_drvr_setconfig_async(struct hfa384x *hw, u16 rid, @@ -2073,23 +2103,24 @@ hfa384x_drvr_setconfig_async(struct hfa384x *hw, } /*---------------------------------------------------------------- -* hfa384x_drvr_ramdl_disable -* -* Ends the ram download state. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_ramdl_disable + * + * Ends the ram download state. + * + * Arguments: + * hw device structure + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_ramdl_disable(struct hfa384x *hw) { /* Check that we're already in the download state */ @@ -2107,29 +2138,30 @@ int hfa384x_drvr_ramdl_disable(struct hfa384x *hw) } /*---------------------------------------------------------------- -* hfa384x_drvr_ramdl_enable -* -* Begins the ram download state. Checks to see that we're not -* already in a download state and that a port isn't enabled. -* Sets the download state and calls cmd_download with the -* ENABLE_VOLATILE subcommand and the exeaddr argument. -* -* Arguments: -* hw device structure -* exeaddr the card execution address that will be -* jumped to when ramdl_disable() is called -* (host order). -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_ramdl_enable + * + * Begins the ram download state. Checks to see that we're not + * already in a download state and that a port isn't enabled. + * Sets the download state and calls cmd_download with the + * ENABLE_VOLATILE subcommand and the exeaddr argument. + * + * Arguments: + * hw device structure + * exeaddr the card execution address that will be + * jumped to when ramdl_disable() is called + * (host order). + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_ramdl_enable(struct hfa384x *hw, u32 exeaddr) { int result = 0; @@ -2174,31 +2206,32 @@ int hfa384x_drvr_ramdl_enable(struct hfa384x *hw, u32 exeaddr) } /*---------------------------------------------------------------- -* hfa384x_drvr_ramdl_write -* -* Performs a RAM download of a chunk of data. First checks to see -* that we're in the RAM download state, then uses the [read|write]mem USB -* commands to 1) copy the data, 2) readback and compare. The download -* state is unaffected. When all data has been written using -* this function, call drvr_ramdl_disable() to end the download state -* and restart the MAC. -* -* Arguments: -* hw device structure -* daddr Card address to write to. (host order) -* buf Ptr to data to write. -* len Length of data (host order). -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_ramdl_write + * + * Performs a RAM download of a chunk of data. First checks to see + * that we're in the RAM download state, then uses the [read|write]mem USB + * commands to 1) copy the data, 2) readback and compare. The download + * state is unaffected. When all data has been written using + * this function, call drvr_ramdl_disable() to end the download state + * and restart the MAC. + * + * Arguments: + * hw device structure + * daddr Card address to write to. (host order) + * buf Ptr to data to write. + * len Length of data (host order). + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) { int result = 0; @@ -2249,36 +2282,37 @@ int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) } /*---------------------------------------------------------------- -* hfa384x_drvr_readpda -* -* Performs the sequence to read the PDA space. Note there is no -* drvr_writepda() function. Writing a PDA is -* generally implemented by a calling component via calls to -* cmd_download and writing to the flash download buffer via the -* aux regs. -* -* Arguments: -* hw device structure -* buf buffer to store PDA in -* len buffer length -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -ETIMEDOUT timeout waiting for the cmd regs to become -* available, or waiting for the control reg -* to indicate the Aux port is enabled. -* -ENODATA the buffer does NOT contain a valid PDA. -* Either the card PDA is bad, or the auxdata -* reads are giving us garbage. - -* -* Side effects: -* -* Call context: -* process or non-card interrupt. -----------------------------------------------------------------*/ + * hfa384x_drvr_readpda + * + * Performs the sequence to read the PDA space. Note there is no + * drvr_writepda() function. Writing a PDA is + * generally implemented by a calling component via calls to + * cmd_download and writing to the flash download buffer via the + * aux regs. + * + * Arguments: + * hw device structure + * buf buffer to store PDA in + * len buffer length + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * -ETIMEDOUT timeout waiting for the cmd regs to become + * available, or waiting for the control reg + * to indicate the Aux port is enabled. + * -ENODATA the buffer does NOT contain a valid PDA. + * Either the card PDA is bad, or the auxdata + * reads are giving us garbage. + * + * + * Side effects: + * + * Call context: + * process or non-card interrupt. + *---------------------------------------------------------------- + */ int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) { int result = 0; @@ -2369,51 +2403,52 @@ int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) } /*---------------------------------------------------------------- -* hfa384x_drvr_setconfig -* -* Performs the sequence necessary to write a config/info item. -* -* Arguments: -* hw device structure -* rid config/info record id (in host order) -* buf host side record buffer -* len buffer length (in bytes) -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_setconfig + * + * Performs the sequence necessary to write a config/info item. + * + * Arguments: + * hw device structure + * rid config/info record id (in host order) + * buf host side record buffer + * len buffer length (in bytes) + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_setconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { return hfa384x_dowrid_wait(hw, rid, buf, len); } /*---------------------------------------------------------------- -* hfa384x_drvr_start -* -* Issues the MAC initialize command, sets up some data structures, -* and enables the interrupts. After this function completes, the -* low-level stuff should be ready for any/all commands. -* -* Arguments: -* hw device structure -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ - + * hfa384x_drvr_start + * + * Issues the MAC initialize command, sets up some data structures, + * and enables the interrupts. After this function completes, the + * low-level stuff should be ready for any/all commands. + * + * Arguments: + * hw device structure + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_start(struct hfa384x *hw) { int result, result1, result2; @@ -2497,24 +2532,25 @@ done: } /*---------------------------------------------------------------- -* hfa384x_drvr_stop -* -* Shuts down the MAC to the point where it is safe to unload the -* driver. Any subsystem that may be holding a data or function -* ptr into the driver must be cleared/deinitialized. -* -* Arguments: -* hw device structure -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ + * hfa384x_drvr_stop + * + * Shuts down the MAC to the point where it is safe to unload the + * driver. Any subsystem that may be holding a data or function + * ptr into the driver must be cleared/deinitialized. + * + * Arguments: + * hw device structure + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + *---------------------------------------------------------------- + */ int hfa384x_drvr_stop(struct hfa384x *hw) { int i; @@ -2545,26 +2581,27 @@ int hfa384x_drvr_stop(struct hfa384x *hw) } /*---------------------------------------------------------------- -* hfa384x_drvr_txframe -* -* Takes a frame from prism2sta and queues it for transmission. -* -* Arguments: -* hw device structure -* skb packet buffer struct. Contains an 802.11 -* data frame. -* p80211_hdr points to the 802.11 header for the packet. -* Returns: -* 0 Success and more buffs available -* 1 Success but no more buffs -* 2 Allocation failure -* 4 Buffer full or queue busy -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_drvr_txframe + * + * Takes a frame from prism2sta and queues it for transmission. + * + * Arguments: + * hw device structure + * skb packet buffer struct. Contains an 802.11 + * data frame. + * p80211_hdr points to the 802.11 header for the packet. + * Returns: + * 0 Success and more buffs available + * 1 Success but no more buffs + * 2 Allocation failure + * 4 Buffer full or queue busy + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ int hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) @@ -2679,18 +2716,19 @@ void hfa384x_tx_timeout(struct wlandevice *wlandev) } /*---------------------------------------------------------------- -* hfa384x_usbctlx_reaper_task -* -* Tasklet to delete dead CTLX objects -* -* Arguments: -* data ptr to a struct hfa384x -* -* Returns: -* -* Call context: -* Interrupt -----------------------------------------------------------------*/ + * hfa384x_usbctlx_reaper_task + * + * Tasklet to delete dead CTLX objects + * + * Arguments: + * data ptr to a struct hfa384x + * + * Returns: + * + * Call context: + * Interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbctlx_reaper_task(unsigned long data) { struct hfa384x *hw = (struct hfa384x *)data; @@ -2711,19 +2749,20 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) } /*---------------------------------------------------------------- -* hfa384x_usbctlx_completion_task -* -* Tasklet to call completion handlers for returned CTLXs -* -* Arguments: -* data ptr to struct hfa384x -* -* Returns: -* Nothing -* -* Call context: -* Interrupt -----------------------------------------------------------------*/ + * hfa384x_usbctlx_completion_task + * + * Tasklet to call completion handlers for returned CTLXs + * + * Arguments: + * data ptr to struct hfa384x + * + * Returns: + * Nothing + * + * Call context: + * Interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbctlx_completion_task(unsigned long data) { struct hfa384x *hw = (struct hfa384x *)data; @@ -2784,22 +2823,23 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) } /*---------------------------------------------------------------- -* unlocked_usbctlx_cancel_async -* -* Mark the CTLX dead asynchronously, and ensure that the -* next command on the queue is run afterwards. -* -* Arguments: -* hw ptr to the struct hfa384x structure -* ctlx ptr to a CTLX structure -* -* Returns: -* 0 the CTLX's URB is inactive -* -EINPROGRESS the URB is currently being unlinked -* -* Call context: -* Either process or interrupt, but presumably interrupt -----------------------------------------------------------------*/ + * unlocked_usbctlx_cancel_async + * + * Mark the CTLX dead asynchronously, and ensure that the + * next command on the queue is run afterwards. + * + * Arguments: + * hw ptr to the struct hfa384x structure + * ctlx ptr to a CTLX structure + * + * Returns: + * 0 the CTLX's URB is inactive + * -EINPROGRESS the URB is currently being unlinked + * + * Call context: + * Either process or interrupt, but presumably interrupt + *---------------------------------------------------------------- + */ static int unlocked_usbctlx_cancel_async(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) { @@ -2829,27 +2869,28 @@ static int unlocked_usbctlx_cancel_async(struct hfa384x *hw, } /*---------------------------------------------------------------- -* unlocked_usbctlx_complete -* -* A CTLX has completed. It may have been successful, it may not -* have been. At this point, the CTLX should be quiescent. The URBs -* aren't active and the timers should have been stopped. -* -* The CTLX is migrated to the "completing" queue, and the completing -* tasklet is scheduled. -* -* Arguments: -* hw ptr to a struct hfa384x structure -* ctlx ptr to a ctlx structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* Either, assume interrupt -----------------------------------------------------------------*/ + * unlocked_usbctlx_complete + * + * A CTLX has completed. It may have been successful, it may not + * have been. At this point, the CTLX should be quiescent. The URBs + * aren't active and the timers should have been stopped. + * + * The CTLX is migrated to the "completing" queue, and the completing + * tasklet is scheduled. + * + * Arguments: + * hw ptr to a struct hfa384x structure + * ctlx ptr to a ctlx structure + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * Either, assume interrupt + *---------------------------------------------------------------- + */ static void unlocked_usbctlx_complete(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) { @@ -2875,21 +2916,22 @@ static void unlocked_usbctlx_complete(struct hfa384x *hw, } /*---------------------------------------------------------------- -* hfa384x_usbctlxq_run -* -* Checks to see if the head item is running. If not, starts it. -* -* Arguments: -* hw ptr to struct hfa384x -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* any -----------------------------------------------------------------*/ + * hfa384x_usbctlxq_run + * + * Checks to see if the head item is running. If not, starts it. + * + * Arguments: + * hw ptr to struct hfa384x + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * any + *---------------------------------------------------------------- + */ static void hfa384x_usbctlxq_run(struct hfa384x *hw) { unsigned long flags; @@ -2975,21 +3017,22 @@ unlock: } /*---------------------------------------------------------------- -* hfa384x_usbin_callback -* -* Callback for URBs on the BULKIN endpoint. -* -* Arguments: -* urb ptr to the completed urb -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_usbin_callback + * + * Callback for URBs on the BULKIN endpoint. + * + * Arguments: + * urb ptr to the completed urb + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbin_callback(struct urb *urb) { struct wlandevice *wlandev = urb->context; @@ -3151,25 +3194,26 @@ exit: } /*---------------------------------------------------------------- -* hfa384x_usbin_ctlx -* -* We've received a URB containing a Prism2 "response" message. -* This message needs to be matched up with a CTLX on the active -* queue and our state updated accordingly. -* -* Arguments: -* hw ptr to struct hfa384x -* usbin ptr to USB IN packet -* urb_status status of this Bulk-In URB -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_usbin_ctlx + * + * We've received a URB containing a Prism2 "response" message. + * This message needs to be matched up with a CTLX on the active + * queue and our state updated accordingly. + * + * Arguments: + * hw ptr to struct hfa384x + * usbin ptr to USB IN packet + * urb_status status of this Bulk-In URB + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbin_ctlx(struct hfa384x *hw, union hfa384x_usbin *usbin, int urb_status) { @@ -3273,22 +3317,23 @@ unlock: } /*---------------------------------------------------------------- -* hfa384x_usbin_txcompl -* -* At this point we have the results of a previous transmit. -* -* Arguments: -* wlandev wlan device -* usbin ptr to the usb transfer buffer -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_usbin_txcompl + * + * At this point we have the results of a previous transmit. + * + * Arguments: + * wlandev wlan device + * usbin ptr to the usb transfer buffer + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbin_txcompl(struct wlandevice *wlandev, union hfa384x_usbin *usbin) { @@ -3304,22 +3349,23 @@ static void hfa384x_usbin_txcompl(struct wlandevice *wlandev, } /*---------------------------------------------------------------- -* hfa384x_usbin_rx -* -* At this point we have a successful received a rx frame packet. -* -* Arguments: -* wlandev wlan device -* usbin ptr to the usb transfer buffer -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_usbin_rx + * + * At this point we have a successful received a rx frame packet. + * + * Arguments: + * wlandev wlan device + * usbin ptr to the usb transfer buffer + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) { union hfa384x_usbin *usbin = (union hfa384x_usbin *)skb->data; @@ -3400,26 +3446,27 @@ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) } /*---------------------------------------------------------------- -* hfa384x_int_rxmonitor -* -* Helper function for int_rx. Handles monitor frames. -* Note that this function allocates space for the FCS and sets it -* to 0xffffffff. The hfa384x doesn't give us the FCS value but the -* higher layers expect it. 0xffffffff is used as a flag to indicate -* the FCS is bogus. -* -* Arguments: -* wlandev wlan device structure -* rxfrm rx descriptor read from card in int_rx -* -* Returns: -* nothing -* -* Side effects: -* Allocates an skb and passes it up via the PF_PACKET interface. -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_int_rxmonitor + * + * Helper function for int_rx. Handles monitor frames. + * Note that this function allocates space for the FCS and sets it + * to 0xffffffff. The hfa384x doesn't give us the FCS value but the + * higher layers expect it. 0xffffffff is used as a flag to indicate + * the FCS is bogus. + * + * Arguments: + * wlandev wlan device structure + * rxfrm rx descriptor read from card in int_rx + * + * Returns: + * nothing + * + * Side effects: + * Allocates an skb and passes it up via the PF_PACKET interface. + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, struct hfa384x_usb_rxfrm *rxfrm) { @@ -3478,7 +3525,8 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, } /* Copy the 802.11 header to the skb - (ctl frames may be less than a full header) */ + * (ctl frames may be less than a full header) + */ datap = skb_put(skb, hdrlen); memcpy(datap, &(rxdesc->frame_control), hdrlen); @@ -3505,22 +3553,23 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, } /*---------------------------------------------------------------- -* hfa384x_usbin_info -* -* At this point we have a successful received a Prism2 info frame. -* -* Arguments: -* wlandev wlan device -* usbin ptr to the usb transfer buffer -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_usbin_info + * + * At this point we have a successful received a Prism2 info frame. + * + * Arguments: + * wlandev wlan device + * usbin ptr to the usb transfer buffer + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbin_info(struct wlandevice *wlandev, union hfa384x_usbin *usbin) { @@ -3530,21 +3579,22 @@ static void hfa384x_usbin_info(struct wlandevice *wlandev, } /*---------------------------------------------------------------- -* hfa384x_usbout_callback -* -* Callback for URBs on the BULKOUT endpoint. -* -* Arguments: -* urb ptr to the completed urb -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_usbout_callback + * + * Callback for URBs on the BULKOUT endpoint. + * + * Arguments: + * urb ptr to the completed urb + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbout_callback(struct urb *urb) { struct wlandevice *wlandev = urb->context; @@ -3605,21 +3655,22 @@ static void hfa384x_usbout_callback(struct urb *urb) } /*---------------------------------------------------------------- -* hfa384x_ctlxout_callback -* -* Callback for control data on the BULKOUT endpoint. -* -* Arguments: -* urb ptr to the completed urb -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_ctlxout_callback + * + * Callback for control data on the BULKOUT endpoint. + * + * Arguments: + * urb ptr to the completed urb + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_ctlxout_callback(struct urb *urb) { struct hfa384x *hw = urb->context; @@ -3734,23 +3785,24 @@ delresp: } /*---------------------------------------------------------------- -* hfa384x_usbctlx_reqtimerfn -* -* Timer response function for CTLX request timeouts. If this -* function is called, it means that the callback for the OUT -* URB containing a Prism2.x XXX_Request was never called. -* -* Arguments: -* data a ptr to the struct hfa384x -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_usbctlx_reqtimerfn + * + * Timer response function for CTLX request timeouts. If this + * function is called, it means that the callback for the OUT + * URB containing a Prism2.x XXX_Request was never called. + * + * Arguments: + * data a ptr to the struct hfa384x + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) { struct hfa384x *hw = (struct hfa384x *)data; @@ -3792,23 +3844,24 @@ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) } /*---------------------------------------------------------------- -* hfa384x_usbctlx_resptimerfn -* -* Timer response function for CTLX response timeouts. If this -* function is called, it means that the callback for the IN -* URB containing a Prism2.x XXX_Response was never called. -* -* Arguments: -* data a ptr to the struct hfa384x -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * hfa384x_usbctlx_resptimerfn + * + * Timer response function for CTLX response timeouts. If this + * function is called, it means that the callback for the IN + * URB containing a Prism2.x XXX_Response was never called. + * + * Arguments: + * data a ptr to the struct hfa384x + * + * Returns: + * nothing + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usbctlx_resptimerfn(unsigned long data) { struct hfa384x *hw = (struct hfa384x *)data; @@ -3834,20 +3887,21 @@ static void hfa384x_usbctlx_resptimerfn(unsigned long data) } /*---------------------------------------------------------------- -* hfa384x_usb_throttlefn -* -* -* Arguments: -* data ptr to hw -* -* Returns: -* Nothing -* -* Side effects: -* -* Call context: -* Interrupt -----------------------------------------------------------------*/ + * hfa384x_usb_throttlefn + * + * + * Arguments: + * data ptr to hw + * + * Returns: + * Nothing + * + * Side effects: + * + * Call context: + * Interrupt + *---------------------------------------------------------------- + */ static void hfa384x_usb_throttlefn(unsigned long data) { struct hfa384x *hw = (struct hfa384x *)data; @@ -3873,23 +3927,24 @@ static void hfa384x_usb_throttlefn(unsigned long data) } /*---------------------------------------------------------------- -* hfa384x_usbctlx_submit -* -* Called from the doxxx functions to submit a CTLX to the queue -* -* Arguments: -* hw ptr to the hw struct -* ctlx ctlx structure to enqueue -* -* Returns: -* -ENODEV if the adapter is unplugged -* 0 -* -* Side effects: -* -* Call context: -* process or interrupt -----------------------------------------------------------------*/ + * hfa384x_usbctlx_submit + * + * Called from the doxxx functions to submit a CTLX to the queue + * + * Arguments: + * hw ptr to the hw struct + * ctlx ctlx structure to enqueue + * + * Returns: + * -ENODEV if the adapter is unplugged + * 0 + * + * Side effects: + * + * Call context: + * process or interrupt + *---------------------------------------------------------------- + */ static int hfa384x_usbctlx_submit(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) { @@ -3911,21 +3966,22 @@ static int hfa384x_usbctlx_submit(struct hfa384x *hw, } /*---------------------------------------------------------------- -* hfa384x_isgood_pdrcore -* -* Quick check of PDR codes. -* -* Arguments: -* pdrcode PDR code number (host order) -* -* Returns: -* zero not good. -* one is good. -* -* Side effects: -* -* Call context: -----------------------------------------------------------------*/ + * hfa384x_isgood_pdrcore + * + * Quick check of PDR codes. + * + * Arguments: + * pdrcode PDR code number (host order) + * + * Returns: + * zero not good. + * one is good. + * + * Side effects: + * + * Call context: + *---------------------------------------------------------------- + */ static int hfa384x_isgood_pdrcode(u16 pdrcode) { switch (pdrcode) { -- cgit v1.2.3 From b1a57426d0b5d9caa2c5edcc77b24f5d6d7addd9 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:20 +0200 Subject: staging: wlan-ng: fix block comment warnings in p80211conv.c This patch fix the following checkpatch.pl warnings in p80211conv.c: WARNING: Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 318 +++++++++++++++++------------------ 1 file changed, 159 insertions(+), 159 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 0247cbc29145..5c0e65863205 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -1,56 +1,56 @@ /* src/p80211/p80211conv.c -* -* Ether/802.11 conversions and packet buffer routines -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file defines the functions that perform Ethernet to/from -* 802.11 frame conversions. -* -* -------------------------------------------------------------------- -* -*================================================================ -*/ + * + * Ether/802.11 conversions and packet buffer routines + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file defines the functions that perform Ethernet to/from + * 802.11 frame conversions. + * + * -------------------------------------------------------------------- + * + *================================================================ + */ #include #include @@ -79,31 +79,31 @@ static const u8 oui_rfc1042[] = { 0x00, 0x00, 0x00 }; static const u8 oui_8021h[] = { 0x00, 0x00, 0xf8 }; /*---------------------------------------------------------------- -* p80211pb_ether_to_80211 -* -* Uses the contents of the ether frame and the etherconv setting -* to build the elements of the 802.11 frame. -* -* We don't actually set -* up the frame header here. That's the MAC's job. We're only handling -* conversion of DIXII or 802.3+LLC frames to something that works -* with 802.11. -* -* Note -- 802.11 header is NOT part of the skb. Likewise, the 802.11 -* FCS is also not present and will need to be added elsewhere. -* -* Arguments: -* ethconv Conversion type to perform -* skb skbuff containing the ether frame -* p80211_hdr 802.11 header -* -* Returns: -* 0 on success, non-zero otherwise -* -* Call context: -* May be called in interrupt or non-interrupt context -*---------------------------------------------------------------- -*/ + * p80211pb_ether_to_80211 + * + * Uses the contents of the ether frame and the etherconv setting + * to build the elements of the 802.11 frame. + * + * We don't actually set + * up the frame header here. That's the MAC's job. We're only handling + * conversion of DIXII or 802.3+LLC frames to something that works + * with 802.11. + * + * Note -- 802.11 header is NOT part of the skb. Likewise, the 802.11 + * FCS is also not present and will need to be added elsewhere. + * + * Arguments: + * ethconv Conversion type to perform + * skb skbuff containing the ether frame + * p80211_hdr 802.11 header + * + * Returns: + * 0 on success, non-zero otherwise + * + * Call context: + * May be called in interrupt or non-interrupt context + *---------------------------------------------------------------- + */ int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) @@ -255,25 +255,25 @@ static void orinoco_spy_gather(struct wlandevice *wlandev, char *mac, } /*---------------------------------------------------------------- -* p80211pb_80211_to_ether -* -* Uses the contents of a received 802.11 frame and the etherconv -* setting to build an ether frame. -* -* This function extracts the src and dest address from the 802.11 -* frame to use in the construction of the eth frame. -* -* Arguments: -* ethconv Conversion type to perform -* skb Packet buffer containing the 802.11 frame -* -* Returns: -* 0 on success, non-zero otherwise -* -* Call context: -* May be called in interrupt or non-interrupt context -*---------------------------------------------------------------- -*/ + * p80211pb_80211_to_ether + * + * Uses the contents of a received 802.11 frame and the etherconv + * setting to build an ether frame. + * + * This function extracts the src and dest address from the 802.11 + * frame to use in the construction of the eth frame. + * + * Arguments: + * ethconv Conversion type to perform + * skb Packet buffer containing the 802.11 frame + * + * Returns: + * 0 on success, non-zero otherwise + * + * Call context: + * May be called in interrupt or non-interrupt context + *---------------------------------------------------------------- + */ int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv, struct sk_buff *skb) { @@ -508,22 +508,22 @@ int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv, } /*---------------------------------------------------------------- -* p80211_stt_findproto -* -* Searches the 802.1h Selective Translation Table for a given -* protocol. -* -* Arguments: -* proto protocol number (in host order) to search for. -* -* Returns: -* 1 - if the table is empty or a match is found. -* 0 - if the table is non-empty and a match is not found. -* -* Call context: -* May be called in interrupt or non-interrupt context -*---------------------------------------------------------------- -*/ + * p80211_stt_findproto + * + * Searches the 802.1h Selective Translation Table for a given + * protocol. + * + * Arguments: + * proto protocol number (in host order) to search for. + * + * Returns: + * 1 - if the table is empty or a match is found. + * 0 - if the table is non-empty and a match is not found. + * + * Call context: + * May be called in interrupt or non-interrupt context + *---------------------------------------------------------------- + */ int p80211_stt_findproto(u16 proto) { /* Always return found for now. This is the behavior used by the */ @@ -540,21 +540,21 @@ int p80211_stt_findproto(u16 proto) } /*---------------------------------------------------------------- -* p80211skb_rxmeta_detach -* -* Disconnects the frmmeta and rxmeta from an skb. -* -* Arguments: -* wlandev The wlandev this skb belongs to. -* skb The skb we're attaching to. -* -* Returns: -* 0 on success, non-zero otherwise -* -* Call context: -* May be called in interrupt or non-interrupt context -*---------------------------------------------------------------- -*/ + * p80211skb_rxmeta_detach + * + * Disconnects the frmmeta and rxmeta from an skb. + * + * Arguments: + * wlandev The wlandev this skb belongs to. + * skb The skb we're attaching to. + * + * Returns: + * 0 on success, non-zero otherwise + * + * Call context: + * May be called in interrupt or non-interrupt context + *---------------------------------------------------------------- + */ void p80211skb_rxmeta_detach(struct sk_buff *skb) { struct p80211_rxmeta *rxmeta; @@ -584,22 +584,22 @@ void p80211skb_rxmeta_detach(struct sk_buff *skb) } /*---------------------------------------------------------------- -* p80211skb_rxmeta_attach -* -* Allocates a p80211rxmeta structure, initializes it, and attaches -* it to an skb. -* -* Arguments: -* wlandev The wlandev this skb belongs to. -* skb The skb we're attaching to. -* -* Returns: -* 0 on success, non-zero otherwise -* -* Call context: -* May be called in interrupt or non-interrupt context -*---------------------------------------------------------------- -*/ + * p80211skb_rxmeta_attach + * + * Allocates a p80211rxmeta structure, initializes it, and attaches + * it to an skb. + * + * Arguments: + * wlandev The wlandev this skb belongs to. + * skb The skb we're attaching to. + * + * Returns: + * 0 on success, non-zero otherwise + * + * Call context: + * May be called in interrupt or non-interrupt context + *---------------------------------------------------------------- + */ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) { int result = 0; @@ -638,22 +638,22 @@ exit: } /*---------------------------------------------------------------- -* p80211skb_free -* -* Frees an entire p80211skb by checking and freeing the meta struct -* and then freeing the skb. -* -* Arguments: -* wlandev The wlandev this skb belongs to. -* skb The skb we're attaching to. -* -* Returns: -* 0 on success, non-zero otherwise -* -* Call context: -* May be called in interrupt or non-interrupt context -*---------------------------------------------------------------- -*/ + * p80211skb_free + * + * Frees an entire p80211skb by checking and freeing the meta struct + * and then freeing the skb. + * + * Arguments: + * wlandev The wlandev this skb belongs to. + * skb The skb we're attaching to. + * + * Returns: + * 0 on success, non-zero otherwise + * + * Call context: + * May be called in interrupt or non-interrupt context + *---------------------------------------------------------------- + */ void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb) { struct p80211_frmmeta *meta; -- cgit v1.2.3 From 0a6b83e553322a23971b79fde3cf0fd911815038 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:21 +0200 Subject: staging: wlan-ng: fix line style warnings in p80211netdev.c This patch fix the following checkpatch.pl warnings in p80211netdev.c: WARNING: line over 80 characters Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211netdev.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 825a63a7c0e3..78a10af3406b 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -227,7 +227,8 @@ void p80211netdev_rx(struct wlandevice *wlandev, struct sk_buff *skb) * CONV_TO_ETHER_FAILED if conversion failed * CONV_TO_ETHER_SKIPPED if frame is ignored */ -static int p80211_convert_to_ether(struct wlandevice *wlandev, struct sk_buff *skb) +static int p80211_convert_to_ether(struct wlandevice *wlandev, + struct sk_buff *skb) { struct p80211_hdr_a3 *hdr; @@ -459,7 +460,8 @@ static void p80211knetdev_set_multicast_list(struct net_device *dev) #ifdef SIOCETHTOOL -static int p80211netdev_ethtool(struct wlandevice *wlandev, void __user *useraddr) +static int p80211netdev_ethtool(struct wlandevice *wlandev, + void __user *useraddr) { u32 ethcmd; struct ethtool_drvinfo info; @@ -531,7 +533,8 @@ static int p80211netdev_ethtool(struct wlandevice *wlandev, void __user *useradd * Process thread (ioctl caller). TODO: SMP support may require * locks. ----------------------------------------------------------------*/ -static int p80211knetdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static int p80211knetdev_do_ioctl(struct net_device *dev, + struct ifreq *ifr, int cmd) { int result = 0; struct p80211ioctl_req *req = (struct p80211ioctl_req *)ifr; -- cgit v1.2.3 From 84ad1efa7d2b724344e115ea0a0b4d5d7ec45cca Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:22 +0200 Subject: staging: wlan-ng: fix block comment warnings in p80211netdev.c This patch fix the following checkpatch.pl warnings in p80211netdev.c: WARNING: Block comments should align the * on each line WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211netdev.c | 613 +++++++++++++++++---------------- 1 file changed, 314 insertions(+), 299 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 78a10af3406b..fb28d8fc130f 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -1,53 +1,53 @@ /* src/p80211/p80211knetdev.c -* -* Linux Kernel net device interface -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* The functions required for a Linux network device are defined here. -* -* -------------------------------------------------------------------- -*/ + * + * Linux Kernel net device interface + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * The functions required for a Linux network device are defined here. + * + * -------------------------------------------------------------------- + */ #include #include @@ -112,17 +112,18 @@ module_param(wlan_wext_write, int, 0644); MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions"); /*---------------------------------------------------------------- -* p80211knetdev_init -* -* Init method for a Linux netdevice. Called in response to -* register_netdev. -* -* Arguments: -* none -* -* Returns: -* nothing -----------------------------------------------------------------*/ + * p80211knetdev_init + * + * Init method for a Linux netdevice. Called in response to + * register_netdev. + * + * Arguments: + * none + * + * Returns: + * nothing + *---------------------------------------------------------------- + */ static int p80211knetdev_init(struct net_device *netdev) { /* Called in response to register_netdev */ @@ -133,19 +134,20 @@ static int p80211knetdev_init(struct net_device *netdev) } /*---------------------------------------------------------------- -* p80211knetdev_open -* -* Linux netdevice open method. Following a successful call here, -* the device is supposed to be ready for tx and rx. In our -* situation that may not be entirely true due to the state of the -* MAC below. -* -* Arguments: -* netdev Linux network device structure -* -* Returns: -* zero on success, non-zero otherwise -----------------------------------------------------------------*/ + * p80211knetdev_open + * + * Linux netdevice open method. Following a successful call here, + * the device is supposed to be ready for tx and rx. In our + * situation that may not be entirely true due to the state of the + * MAC below. + * + * Arguments: + * netdev Linux network device structure + * + * Returns: + * zero on success, non-zero otherwise + *---------------------------------------------------------------- + */ static int p80211knetdev_open(struct net_device *netdev) { int result = 0; /* success */ @@ -170,17 +172,18 @@ static int p80211knetdev_open(struct net_device *netdev) } /*---------------------------------------------------------------- -* p80211knetdev_stop -* -* Linux netdevice stop (close) method. Following this call, -* no frames should go up or down through this interface. -* -* Arguments: -* netdev Linux network device structure -* -* Returns: -* zero on success, non-zero otherwise -----------------------------------------------------------------*/ + * p80211knetdev_stop + * + * Linux netdevice stop (close) method. Following this call, + * no frames should go up or down through this interface. + * + * Arguments: + * netdev Linux network device structure + * + * Returns: + * zero on success, non-zero otherwise + *---------------------------------------------------------------- + */ static int p80211knetdev_stop(struct net_device *netdev) { int result = 0; @@ -196,18 +199,19 @@ static int p80211knetdev_stop(struct net_device *netdev) } /*---------------------------------------------------------------- -* p80211netdev_rx -* -* Frame receive function called by the mac specific driver. -* -* Arguments: -* wlandev WLAN network device structure -* skb skbuff containing a full 802.11 frame. -* Returns: -* nothing -* Side effects: -* -----------------------------------------------------------------*/ + * p80211netdev_rx + * + * Frame receive function called by the mac specific driver. + * + * Arguments: + * wlandev WLAN network device structure + * skb skbuff containing a full 802.11 frame. + * Returns: + * nothing + * Side effects: + * + *---------------------------------------------------------------- + */ void p80211netdev_rx(struct wlandevice *wlandev, struct sk_buff *skb) { /* Enqueue for post-irq processing */ @@ -300,24 +304,25 @@ static void p80211netdev_rx_bh(unsigned long arg) } /*---------------------------------------------------------------- -* p80211knetdev_hard_start_xmit -* -* Linux netdevice method for transmitting a frame. -* -* Arguments: -* skb Linux sk_buff containing the frame. -* netdev Linux netdevice. -* -* Side effects: -* If the lower layers report that buffers are full. netdev->tbusy -* will be set to prevent higher layers from sending more traffic. -* -* Note: If this function returns non-zero, higher layers retain -* ownership of the skb. -* -* Returns: -* zero on success, non-zero on failure. -----------------------------------------------------------------*/ + * p80211knetdev_hard_start_xmit + * + * Linux netdevice method for transmitting a frame. + * + * Arguments: + * skb Linux sk_buff containing the frame. + * netdev Linux netdevice. + * + * Side effects: + * If the lower layers report that buffers are full. netdev->tbusy + * will be set to prevent higher layers from sending more traffic. + * + * Note: If this function returns non-zero, higher layers retain + * ownership of the skb. + * + * Returns: + * zero on success, non-zero on failure. + *---------------------------------------------------------------- + */ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { @@ -436,17 +441,18 @@ failed: } /*---------------------------------------------------------------- -* p80211knetdev_set_multicast_list -* -* Called from higher layers whenever there's a need to set/clear -* promiscuous mode or rewrite the multicast list. -* -* Arguments: -* none -* -* Returns: -* nothing -----------------------------------------------------------------*/ + * p80211knetdev_set_multicast_list + * + * Called from higher layers whenever there's a need to set/clear + * promiscuous mode or rewrite the multicast list. + * + * Arguments: + * none + * + * Returns: + * nothing + *---------------------------------------------------------------- + */ static void p80211knetdev_set_multicast_list(struct net_device *dev) { struct wlandevice *wlandev = dev->ml_priv; @@ -507,32 +513,33 @@ static int p80211netdev_ethtool(struct wlandevice *wlandev, #endif /*---------------------------------------------------------------- -* p80211knetdev_do_ioctl -* -* Handle an ioctl call on one of our devices. Everything Linux -* ioctl specific is done here. Then we pass the contents of the -* ifr->data to the request message handler. -* -* Arguments: -* dev Linux kernel netdevice -* ifr Our private ioctl request structure, typed for the -* generic struct ifreq so we can use ptr to func -* w/o cast. -* -* Returns: -* zero on success, a negative errno on failure. Possible values: -* -ENETDOWN Device isn't up. -* -EBUSY cmd already in progress -* -ETIME p80211 cmd timed out (MSD may have its own timers) -* -EFAULT memory fault copying msg from user buffer -* -ENOMEM unable to allocate kernel msg buffer -* -ENOSYS bad magic, it the cmd really for us? -* -EintR sleeping on cmd, awakened by signal, cmd cancelled. -* -* Call Context: -* Process thread (ioctl caller). TODO: SMP support may require -* locks. -----------------------------------------------------------------*/ + * p80211knetdev_do_ioctl + * + * Handle an ioctl call on one of our devices. Everything Linux + * ioctl specific is done here. Then we pass the contents of the + * ifr->data to the request message handler. + * + * Arguments: + * dev Linux kernel netdevice + * ifr Our private ioctl request structure, typed for the + * generic struct ifreq so we can use ptr to func + * w/o cast. + * + * Returns: + * zero on success, a negative errno on failure. Possible values: + * -ENETDOWN Device isn't up. + * -EBUSY cmd already in progress + * -ETIME p80211 cmd timed out (MSD may have its own timers) + * -EFAULT memory fault copying msg from user buffer + * -ENOMEM unable to allocate kernel msg buffer + * -ENOSYS bad magic, it the cmd really for us? + * -EintR sleeping on cmd, awakened by signal, cmd cancelled. + * + * Call Context: + * Process thread (ioctl caller). TODO: SMP support may require + * locks. + *---------------------------------------------------------------- + */ static int p80211knetdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { @@ -589,30 +596,31 @@ bail: } /*---------------------------------------------------------------- -* p80211knetdev_set_mac_address -* -* Handles the ioctl for changing the MACAddress of a netdevice -* -* references: linux/netdevice.h and drivers/net/net_init.c -* -* NOTE: [MSM] We only prevent address changes when the netdev is -* up. We don't control anything based on dot11 state. If the -* address is changed on a STA that's currently associated, you -* will probably lose the ability to send and receive data frames. -* Just be aware. Therefore, this should usually only be done -* prior to scan/join/auth/assoc. -* -* Arguments: -* dev netdevice struct -* addr the new MACAddress (a struct) -* -* Returns: -* zero on success, a negative errno on failure. Possible values: -* -EBUSY device is bussy (cmd not possible) -* -and errors returned by: p80211req_dorequest(..) -* -* by: Collin R. Mulliner -----------------------------------------------------------------*/ + * p80211knetdev_set_mac_address + * + * Handles the ioctl for changing the MACAddress of a netdevice + * + * references: linux/netdevice.h and drivers/net/net_init.c + * + * NOTE: [MSM] We only prevent address changes when the netdev is + * up. We don't control anything based on dot11 state. If the + * address is changed on a STA that's currently associated, you + * will probably lose the ability to send and receive data frames. + * Just be aware. Therefore, this should usually only be done + * prior to scan/join/auth/assoc. + * + * Arguments: + * dev netdevice struct + * addr the new MACAddress (a struct) + * + * Returns: + * zero on success, a negative errno on failure. Possible values: + * -EBUSY device is bussy (cmd not possible) + * -and errors returned by: p80211req_dorequest(..) + * + * by: Collin R. Mulliner + *---------------------------------------------------------------- + */ static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *new_addr = addr; @@ -675,7 +683,8 @@ static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr) static int wlan_change_mtu(struct net_device *dev, int new_mtu) { /* 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap) - and another 8 for wep. */ + * and another 8 for wep. + */ if ((new_mtu < 68) || (new_mtu > (2312 - 20 - 8))) return -EINVAL; @@ -698,28 +707,29 @@ static const struct net_device_ops p80211_netdev_ops = { }; /*---------------------------------------------------------------- -* wlan_setup -* -* Roughly matches the functionality of ether_setup. Here -* we set up any members of the wlandevice structure that are common -* to all devices. Additionally, we allocate a linux 'struct device' -* and perform the same setup as ether_setup. -* -* Note: It's important that the caller have setup the wlandev->name -* ptr prior to calling this function. -* -* Arguments: -* wlandev ptr to the wlandev structure for the -* interface. -* physdev ptr to usb device -* Returns: -* zero on success, non-zero otherwise. -* Call Context: -* Should be process thread. We'll assume it might be -* interrupt though. When we add support for statically -* compiled drivers, this function will be called in the -* context of the kernel startup code. -----------------------------------------------------------------*/ + * wlan_setup + * + * Roughly matches the functionality of ether_setup. Here + * we set up any members of the wlandevice structure that are common + * to all devices. Additionally, we allocate a linux 'struct device' + * and perform the same setup as ether_setup. + * + * Note: It's important that the caller have setup the wlandev->name + * ptr prior to calling this function. + * + * Arguments: + * wlandev ptr to the wlandev structure for the + * interface. + * physdev ptr to usb device + * Returns: + * zero on success, non-zero otherwise. + * Call Context: + * Should be process thread. We'll assume it might be + * interrupt though. When we add support for statically + * compiled drivers, this function will be called in the + * context of the kernel startup code. + *---------------------------------------------------------------- + */ int wlan_setup(struct wlandevice *wlandev, struct device *physdev) { int result = 0; @@ -768,24 +778,25 @@ int wlan_setup(struct wlandevice *wlandev, struct device *physdev) } /*---------------------------------------------------------------- -* wlan_unsetup -* -* This function is paired with the wlan_setup routine. It should -* be called after unregister_wlandev. Basically, all it does is -* free the 'struct device' that's associated with the wlandev. -* We do it here because the 'struct device' isn't allocated -* explicitly in the driver code, it's done in wlan_setup. To -* do the free in the driver might seem like 'magic'. -* -* Arguments: -* wlandev ptr to the wlandev structure for the -* interface. -* Call Context: -* Should be process thread. We'll assume it might be -* interrupt though. When we add support for statically -* compiled drivers, this function will be called in the -* context of the kernel startup code. -----------------------------------------------------------------*/ + * wlan_unsetup + * + * This function is paired with the wlan_setup routine. It should + * be called after unregister_wlandev. Basically, all it does is + * free the 'struct device' that's associated with the wlandev. + * We do it here because the 'struct device' isn't allocated + * explicitly in the driver code, it's done in wlan_setup. To + * do the free in the driver might seem like 'magic'. + * + * Arguments: + * wlandev ptr to the wlandev structure for the + * interface. + * Call Context: + * Should be process thread. We'll assume it might be + * interrupt though. When we add support for statically + * compiled drivers, this function will be called in the + * context of the kernel startup code. + *---------------------------------------------------------------- + */ void wlan_unsetup(struct wlandevice *wlandev) { struct wireless_dev *wdev; @@ -802,46 +813,48 @@ void wlan_unsetup(struct wlandevice *wlandev) } /*---------------------------------------------------------------- -* register_wlandev -* -* Roughly matches the functionality of register_netdev. This function -* is called after the driver has successfully probed and set up the -* resources for the device. It's now ready to become a named device -* in the Linux system. -* -* First we allocate a name for the device (if not already set), then -* we call the Linux function register_netdevice. -* -* Arguments: -* wlandev ptr to the wlandev structure for the -* interface. -* Returns: -* zero on success, non-zero otherwise. -* Call Context: -* Can be either interrupt or not. -----------------------------------------------------------------*/ + * register_wlandev + * + * Roughly matches the functionality of register_netdev. This function + * is called after the driver has successfully probed and set up the + * resources for the device. It's now ready to become a named device + * in the Linux system. + * + * First we allocate a name for the device (if not already set), then + * we call the Linux function register_netdevice. + * + * Arguments: + * wlandev ptr to the wlandev structure for the + * interface. + * Returns: + * zero on success, non-zero otherwise. + * Call Context: + * Can be either interrupt or not. + *---------------------------------------------------------------- + */ int register_wlandev(struct wlandevice *wlandev) { return register_netdev(wlandev->netdev); } /*---------------------------------------------------------------- -* unregister_wlandev -* -* Roughly matches the functionality of unregister_netdev. This -* function is called to remove a named device from the system. -* -* First we tell linux that the device should no longer exist. -* Then we remove it from the list of known wlan devices. -* -* Arguments: -* wlandev ptr to the wlandev structure for the -* interface. -* Returns: -* zero on success, non-zero otherwise. -* Call Context: -* Can be either interrupt or not. -----------------------------------------------------------------*/ + * unregister_wlandev + * + * Roughly matches the functionality of unregister_netdev. This + * function is called to remove a named device from the system. + * + * First we tell linux that the device should no longer exist. + * Then we remove it from the list of known wlan devices. + * + * Arguments: + * wlandev ptr to the wlandev structure for the + * interface. + * Returns: + * zero on success, non-zero otherwise. + * Call Context: + * Can be either interrupt or not. + *---------------------------------------------------------------- + */ int unregister_wlandev(struct wlandevice *wlandev) { struct sk_buff *skb; @@ -856,35 +869,36 @@ int unregister_wlandev(struct wlandevice *wlandev) } /*---------------------------------------------------------------- -* p80211netdev_hwremoved -* -* Hardware removed notification. This function should be called -* immediately after an MSD has detected that the underlying hardware -* has been yanked out from under us. The primary things we need -* to do are: -* - Mark the wlandev -* - Prevent any further traffic from the knetdev i/f -* - Prevent any further requests from mgmt i/f -* - If there are any waitq'd mgmt requests or mgmt-frame exchanges, -* shut them down. -* - Call the MSD hwremoved function. -* -* The remainder of the cleanup will be handled by unregister(). -* Our primary goal here is to prevent as much tickling of the MSD -* as possible since the MSD is already in a 'wounded' state. -* -* TODO: As new features are added, this function should be -* updated. -* -* Arguments: -* wlandev WLAN network device structure -* Returns: -* nothing -* Side effects: -* -* Call context: -* Usually interrupt. -----------------------------------------------------------------*/ + * p80211netdev_hwremoved + * + * Hardware removed notification. This function should be called + * immediately after an MSD has detected that the underlying hardware + * has been yanked out from under us. The primary things we need + * to do are: + * - Mark the wlandev + * - Prevent any further traffic from the knetdev i/f + * - Prevent any further requests from mgmt i/f + * - If there are any waitq'd mgmt requests or mgmt-frame exchanges, + * shut them down. + * - Call the MSD hwremoved function. + * + * The remainder of the cleanup will be handled by unregister(). + * Our primary goal here is to prevent as much tickling of the MSD + * as possible since the MSD is already in a 'wounded' state. + * + * TODO: As new features are added, this function should be + * updated. + * + * Arguments: + * wlandev WLAN network device structure + * Returns: + * nothing + * Side effects: + * + * Call context: + * Usually interrupt. + *---------------------------------------------------------------- + */ void p80211netdev_hwremoved(struct wlandevice *wlandev) { wlandev->hwremoved = 1; @@ -895,26 +909,27 @@ void p80211netdev_hwremoved(struct wlandevice *wlandev) } /*---------------------------------------------------------------- -* p80211_rx_typedrop -* -* Classifies the frame, increments the appropriate counter, and -* returns 0|1|2 indicating whether the driver should handle, ignore, or -* drop the frame -* -* Arguments: -* wlandev wlan device structure -* fc frame control field -* -* Returns: -* zero if the frame should be handled by the driver, -* one if the frame should be ignored -* anything else means we drop it. -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ + * p80211_rx_typedrop + * + * Classifies the frame, increments the appropriate counter, and + * returns 0|1|2 indicating whether the driver should handle, ignore, or + * drop the frame + * + * Arguments: + * wlandev wlan device structure + * fc frame control field + * + * Returns: + * zero if the frame should be handled by the driver, + * one if the frame should be ignored + * anything else means we drop it. + * + * Side effects: + * + * Call context: + * interrupt + *---------------------------------------------------------------- + */ static int p80211_rx_typedrop(struct wlandevice *wlandev, u16 fc) { u16 ftype; -- cgit v1.2.3 From 4d43b7916b04aee1c3c7e8ae98cbbc9b045e77d6 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:23 +0200 Subject: staging: wlan-ng: do not return -ENOSYS Fixed coding style issue by replacing ENOSYS with EINVAL. This patch fix the following checkpatch.pl warnings in p80211netdev.c: WARNING: ENOSYS means 'invalid syscall nr' and nothing else Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211netdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index fb28d8fc130f..656033ae3bf0 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -532,7 +532,7 @@ static int p80211netdev_ethtool(struct wlandevice *wlandev, * -ETIME p80211 cmd timed out (MSD may have its own timers) * -EFAULT memory fault copying msg from user buffer * -ENOMEM unable to allocate kernel msg buffer - * -ENOSYS bad magic, it the cmd really for us? + * -EINVAL bad magic, it the cmd really for us? * -EintR sleeping on cmd, awakened by signal, cmd cancelled. * * Call Context: @@ -560,7 +560,7 @@ static int p80211knetdev_do_ioctl(struct net_device *dev, /* Test the magic, assume ifr is good if it's there */ if (req->magic != P80211_IOCTL_MAGIC) { - result = -ENOSYS; + result = -EINVAL; goto bail; } @@ -568,7 +568,7 @@ static int p80211knetdev_do_ioctl(struct net_device *dev, result = 0; goto bail; } else if (cmd != P80211_IFREQ) { - result = -ENOSYS; + result = -EINVAL; goto bail; } -- cgit v1.2.3 From 3aa4ecf7859f2cf9d00bf6ba0b22ff2b98bfdc84 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:24 +0200 Subject: staging: wlan-ng: fix block comment warnings in p80211req.c This patch fix the following checkpatch.pl warnings in p80211req.c: WARNING: Block comments should align the * on each line WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211req.c | 166 ++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index d43e85b5d49b..440dfc180538 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -1,54 +1,54 @@ /* src/p80211/p80211req.c -* -* Request/Indication/MacMgmt interface handling functions -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file contains the functions, types, and macros to support the -* MLME request interface that's implemented via the device ioctls. -* -* -------------------------------------------------------------------- -*/ + * + * Request/Indication/MacMgmt interface handling functions + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file contains the functions, types, and macros to support the + * MLME request interface that's implemented via the device ioctls. + * + * -------------------------------------------------------------------- + */ #include #include @@ -93,21 +93,22 @@ static void p80211req_handle_action(struct wlandevice *wlandev, u32 *data, } /*---------------------------------------------------------------- -* p80211req_dorequest -* -* Handles an MLME request/confirm message. -* -* Arguments: -* wlandev WLAN device struct -* msgbuf Buffer containing a request message -* -* Returns: -* 0 on success, an errno otherwise -* -* Call context: -* Potentially blocks the caller, so it's a good idea to -* not call this function from an interrupt context. -----------------------------------------------------------------*/ + * p80211req_dorequest + * + * Handles an MLME request/confirm message. + * + * Arguments: + * wlandev WLAN device struct + * msgbuf Buffer containing a request message + * + * Returns: + * 0 on success, an errno otherwise + * + * Call context: + * Potentially blocks the caller, so it's a good idea to + * not call this function from an interrupt context. + *---------------------------------------------------------------- + */ int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf) { struct p80211msg *msg = (struct p80211msg *)msgbuf; @@ -147,23 +148,24 @@ int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf) } /*---------------------------------------------------------------- -* p80211req_handlemsg -* -* p80211 message handler. Primarily looks for messages that -* belong to p80211 and then dispatches the appropriate response. -* TODO: we don't do anything yet. Once the linuxMIB is better -* defined we'll need a get/set handler. -* -* Arguments: -* wlandev WLAN device struct -* msg message structure -* -* Returns: -* nothing (any results are set in the status field of the msg) -* -* Call context: -* Process thread -----------------------------------------------------------------*/ + * p80211req_handlemsg + * + * p80211 message handler. Primarily looks for messages that + * belong to p80211 and then dispatches the appropriate response. + * TODO: we don't do anything yet. Once the linuxMIB is better + * defined we'll need a get/set handler. + * + * Arguments: + * wlandev WLAN device struct + * msg message structure + * + * Returns: + * nothing (any results are set in the status field of the msg) + * + * Call context: + * Process thread + *---------------------------------------------------------------- + */ static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *msg) { switch (msg->msgcode) { -- cgit v1.2.3 From c97efa34f4041f60627f82790c77efdb09cdc9b0 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:25 +0200 Subject: staging: wlan-ng: fix line style warnings in p80211req.c This patch fix the following checkpatch.pl warnings in p80211req.c: WARNING: line over 80 characters Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211req.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 440dfc180538..b3b33d2e6447 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -72,7 +72,8 @@ #include "p80211metastruct.h" #include "p80211req.h" -static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *msg); +static void p80211req_handlemsg(struct wlandevice *wlandev, + struct p80211msg *msg); static void p80211req_mibset_mibget(struct wlandevice *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget); @@ -166,7 +167,8 @@ int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf) * Process thread *---------------------------------------------------------------- */ -static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *msg) +static void p80211req_handlemsg(struct wlandevice *wlandev, + struct p80211msg *msg) { switch (msg->msgcode) { -- cgit v1.2.3 From 17d954823d2b04f1f57f955db171b4a62519b500 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:26 +0200 Subject: staging: wlan-ng: fix block comment warnings in p80211wep.c This patch fix the following checkpatch.pl warnings in p80211wep.c: WARNING: Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211wep.c | 90 ++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 23b183738037..59efb354f3e4 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -1,49 +1,49 @@ /* src/p80211/p80211wep.c -* -* WEP encode/decode for P80211. -* -* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -*/ + * + * WEP encode/decode for P80211. + * + * Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + */ /*================================================================*/ /* System Includes */ -- cgit v1.2.3 From 87f26d08cf1328de80359f426cfc0f1d64cfcee4 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:27 +0200 Subject: staging: wlan-ng: fix line style warnings in p80211wep.c This patch fix the following checkpatch.pl warnings in p80211wep.c: WARNING: line over 80 characters Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211wep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 59efb354f3e4..2e33fd7feddc 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -217,8 +217,8 @@ int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override, } /* encrypts in-place. */ -int wep_encrypt(struct wlandevice *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, - u8 *iv, u8 *icv) +int wep_encrypt(struct wlandevice *wlandev, u8 *buf, + u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv) { u32 i, j, k, crc, keylen; u8 s[256], key[64]; -- cgit v1.2.3 From 01fe9c92dff8b0e0f291dc8254e4bd652fa00f0f Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:28 +0200 Subject: staging: wlan-ng: fix block comment warnings in prism2mgmt.c This patch fix the following checkpatch.pl warnings in prism2mgmt.c: WARNING: Block comments should align the * on each line WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mgmt.c | 518 ++++++++++++++++++----------------- 1 file changed, 264 insertions(+), 254 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 170de1c9eac4..90db53dc7196 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -1,61 +1,61 @@ /* src/prism2/driver/prism2mgmt.c -* -* Management request handler functions. -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* The functions in this file handle management requests sent from -* user mode. -* -* Most of these functions have two separate blocks of code that are -* conditional on whether this is a station or an AP. This is used -* to separate out the STA and AP responses to these management primitives. -* It's a choice (good, bad, indifferent?) to have the code in the same -* place so it's clear that the same primitive is implemented in both -* cases but has different behavior. -* -* -------------------------------------------------------------------- -*/ + * + * Management request handler functions. + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * The functions in this file handle management requests sent from + * user mode. + * + * Most of these functions have two separate blocks of code that are + * conditional on whether this is a station or an AP. This is used + * to separate out the STA and AP responses to these management primitives. + * It's a choice (good, bad, indifferent?) to have the code in the same + * place so it's clear that the same primitive is implemented in both + * cases but has different behavior. + * + * -------------------------------------------------------------------- + */ #include #include @@ -90,29 +90,30 @@ (((n)&~BIT(7)) == 22) ? BIT(3) : 0) /*---------------------------------------------------------------- -* prism2mgmt_scan -* -* Initiate a scan for BSSs. -* -* This function corresponds to MLME-scan.request and part of -* MLME-scan.confirm. As far as I can tell in the standard, there -* are no restrictions on when a scan.request may be issued. We have -* to handle in whatever state the driver/MAC happen to be. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -* interrupt -----------------------------------------------------------------*/ + * prism2mgmt_scan + * + * Initiate a scan for BSSs. + * + * This function corresponds to MLME-scan.request and part of + * MLME-scan.confirm. As far as I can tell in the standard, there + * are no restrictions on when a scan.request may be issued. We have + * to handle in whatever state the driver/MAC happen to be. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + * interrupt + *---------------------------------------------------------------- + */ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) { int result = 0; @@ -347,25 +348,26 @@ exit: } /*---------------------------------------------------------------- -* prism2mgmt_scan_results -* -* Retrieve the BSS description for one of the BSSs identified in -* a scan. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -* interrupt -----------------------------------------------------------------*/ + * prism2mgmt_scan_results + * + * Retrieve the BSS description for one of the BSSs identified in + * a scan. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + * interrupt + *---------------------------------------------------------------- + */ int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp) { int result = 0; @@ -507,24 +509,25 @@ exit: } /*---------------------------------------------------------------- -* prism2mgmt_start -* -* Start a BSS. Any station can do this for IBSS, only AP for ESS. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -* interrupt -----------------------------------------------------------------*/ + * prism2mgmt_start + * + * Start a BSS. Any station can do this for IBSS, only AP for ESS. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + * interrupt + *---------------------------------------------------------------- + */ int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) { int result = 0; @@ -689,23 +692,24 @@ done: } /*---------------------------------------------------------------- -* prism2mgmt_readpda -* -* Collect the PDA data and put it in the message. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -----------------------------------------------------------------*/ + * prism2mgmt_readpda + * + * Collect the PDA data and put it in the message. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + *---------------------------------------------------------------- + */ int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp) { struct hfa384x *hw = wlandev->priv; @@ -748,30 +752,31 @@ int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp) } /*---------------------------------------------------------------- -* prism2mgmt_ramdl_state -* -* Establishes the beginning/end of a card RAM download session. -* -* It is expected that the ramdl_write() function will be called -* one or more times between the 'enable' and 'disable' calls to -* this function. -* -* Note: This function should not be called when a mac comm port -* is active. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -----------------------------------------------------------------*/ + * prism2mgmt_ramdl_state + * + * Establishes the beginning/end of a card RAM download session. + * + * It is expected that the ramdl_write() function will be called + * one or more times between the 'enable' and 'disable' calls to + * this function. + * + * Note: This function should not be called when a mac comm port + * is active. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + *---------------------------------------------------------------- + */ int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp) { struct hfa384x *hw = wlandev->priv; @@ -808,25 +813,26 @@ int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp) } /*---------------------------------------------------------------- -* prism2mgmt_ramdl_write -* -* Writes a buffer to the card RAM using the download state. This -* is for writing code to card RAM. To just read or write raw data -* use the aux functions. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -----------------------------------------------------------------*/ + * prism2mgmt_ramdl_write + * + * Writes a buffer to the card RAM using the download state. This + * is for writing code to card RAM. To just read or write raw data + * use the aux functions. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + *---------------------------------------------------------------- + */ int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp) { struct hfa384x *hw = wlandev->priv; @@ -864,30 +870,31 @@ int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp) } /*---------------------------------------------------------------- -* prism2mgmt_flashdl_state -* -* Establishes the beginning/end of a card Flash download session. -* -* It is expected that the flashdl_write() function will be called -* one or more times between the 'enable' and 'disable' calls to -* this function. -* -* Note: This function should not be called when a mac comm port -* is active. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -----------------------------------------------------------------*/ + * prism2mgmt_flashdl_state + * + * Establishes the beginning/end of a card Flash download session. + * + * It is expected that the flashdl_write() function will be called + * one or more times between the 'enable' and 'disable' calls to + * this function. + * + * Note: This function should not be called when a mac comm port + * is active. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + *---------------------------------------------------------------- + */ int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp) { int result = 0; @@ -942,23 +949,24 @@ int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp) } /*---------------------------------------------------------------- -* prism2mgmt_flashdl_write -* -* -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -----------------------------------------------------------------*/ + * prism2mgmt_flashdl_write + * + * + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + *---------------------------------------------------------------- + */ int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp) { struct hfa384x *hw = wlandev->priv; @@ -1001,24 +1009,25 @@ int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp) } /*---------------------------------------------------------------- -* prism2mgmt_autojoin -* -* Associate with an ESS. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -* interrupt -----------------------------------------------------------------*/ + * prism2mgmt_autojoin + * + * Associate with an ESS. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + * interrupt + *---------------------------------------------------------------- + */ int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) { struct hfa384x *hw = wlandev->priv; @@ -1072,24 +1081,25 @@ int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) } /*---------------------------------------------------------------- -* prism2mgmt_wlansniff -* -* Start or stop sniffing. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -* interrupt -----------------------------------------------------------------*/ + * prism2mgmt_wlansniff + * + * Start or stop sniffing. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + * interrupt + *---------------------------------------------------------------- + */ int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp) { int result = 0; -- cgit v1.2.3 From 96da9e643690d0b1b1ca1efddce872d628441ce0 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:29 +0200 Subject: staging: wlan-ng: fix block comment warnings in prism2mib.c This patch fix the following checkpatch.pl warnings in prism2mib.c: WARNING: Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mib.c | 100 ++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 63ab6bc88654..d7792cde2c6a 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -1,54 +1,54 @@ /* src/prism2/driver/prism2mib.c -* -* Management request for mibset/mibget -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* The functions in this file handle the mibset/mibget management -* functions. -* -* -------------------------------------------------------------------- -*/ + * + * Management request for mibset/mibget + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * The functions in this file handle the mibset/mibget management + * functions. + * + * -------------------------------------------------------------------- + */ #include #include -- cgit v1.2.3 From 258ffd7bf1a4c9052c42872a5a30054d2f204736 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:30 +0200 Subject: staging: wlan-ng: fix block comment warnings in prism2sta.c This patch fix the following checkpatch.pl warnings in prism2sta.c: WARNING: Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2sta.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index b10c93ed8f92..b3ae2bb9ae42 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1864,24 +1864,24 @@ void prism2sta_ev_alloc(struct wlandevice *wlandev) } /* -* create_wlan -* -* Called at module init time. This creates the struct wlandevice structure -* and initializes it with relevant bits. -* -* Arguments: -* none -* -* Returns: -* the created struct wlandevice structure. -* -* Side effects: -* also allocates the priv/hw structures. -* -* Call context: -* process thread -* -*/ + * create_wlan + * + * Called at module init time. This creates the struct wlandevice structure + * and initializes it with relevant bits. + * + * Arguments: + * none + * + * Returns: + * the created struct wlandevice structure. + * + * Side effects: + * also allocates the priv/hw structures. + * + * Call context: + * process thread + * + */ static struct wlandevice *create_wlan(void) { struct wlandevice *wlandev = NULL; -- cgit v1.2.3 From 33630b00183d6e1aa0b196e12d5fdb55a44749c1 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:10:32 +0200 Subject: staging: wlan-ng: fix block comment warnings in prism2fw.c This patch fix the following checkpatch.pl warnings in prism2fw.c WARNING: Block comments should align the * on each line WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2fw.c | 485 +++++++++++++++++++------------------ 1 file changed, 248 insertions(+), 237 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 96aa21188669..2454a787b177 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -1,49 +1,49 @@ /* from src/prism2/download/prism2dl.c -* -* utility for downloading prism2 images moved into kernelspace -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -*/ + * + * utility for downloading prism2 images moved into kernelspace + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + */ /*================================================================*/ /* System Includes */ @@ -189,18 +189,19 @@ static int validate_identity(void); /* Function Definitions */ /*---------------------------------------------------------------- -* prism2_fwtry -* -* Try and get firmware into memory -* -* Arguments: -* udev usb device structure -* wlandev wlan device structure -* -* Returns: -* 0 - success -* ~0 - failure -----------------------------------------------------------------*/ + * prism2_fwtry + * + * Try and get firmware into memory + * + * Arguments: + * udev usb device structure + * wlandev wlan device structure + * + * Returns: + * 0 - success + * ~0 - failure + *---------------------------------------------------------------- + */ static int prism2_fwtry(struct usb_device *udev, struct wlandevice *wlandev) { const struct firmware *fw_entry = NULL; @@ -226,18 +227,19 @@ static int prism2_fwtry(struct usb_device *udev, struct wlandevice *wlandev) } /*---------------------------------------------------------------- -* prism2_fwapply -* -* Apply the firmware loaded into memory -* -* Arguments: -* rfptr firmware image in kernel memory -* wlandev device -* -* Returns: -* 0 - success -* ~0 - failure -----------------------------------------------------------------*/ + * prism2_fwapply + * + * Apply the firmware loaded into memory + * + * Arguments: + * rfptr firmware image in kernel memory + * wlandev device + * + * Returns: + * 0 - success + * ~0 - failure + *---------------------------------------------------------------- + */ static int prism2_fwapply(const struct ihex_binrec *rfptr, struct wlandevice *wlandev) { @@ -372,22 +374,23 @@ out: } /*---------------------------------------------------------------- -* crcimage -* -* Adds a CRC16 in the two bytes prior to each block identified by -* an S3 CRC record. Currently, we don't actually do a CRC we just -* insert the value 0xC0DE in hfa384x order. -* -* Arguments: -* fchunk Array of image chunks -* nfchunks Number of image chunks -* s3crc Array of crc records -* ns3crc Number of crc records -* -* Returns: -* 0 success -* ~0 failure -----------------------------------------------------------------*/ + * crcimage + * + * Adds a CRC16 in the two bytes prior to each block identified by + * an S3 CRC record. Currently, we don't actually do a CRC we just + * insert the value 0xC0DE in hfa384x order. + * + * Arguments: + * fchunk Array of image chunks + * nfchunks Number of image chunks + * s3crc Array of crc records + * ns3crc Number of crc records + * + * Returns: + * 0 success + * ~0 failure + *---------------------------------------------------------------- + */ static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks, struct s3crcrec *s3crc, unsigned int ns3crc) { @@ -439,16 +442,17 @@ static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks, } /*---------------------------------------------------------------- -* free_chunks -* -* Clears the chunklist data structures in preparation for a new file. -* -* Arguments: -* none -* -* Returns: -* nothing -----------------------------------------------------------------*/ + * free_chunks + * + * Clears the chunklist data structures in preparation for a new file. + * + * Arguments: + * none + * + * Returns: + * nothing + *---------------------------------------------------------------- + */ static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks) { int i; @@ -462,16 +466,17 @@ static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks) } /*---------------------------------------------------------------- -* free_srecs -* -* Clears the srec data structures in preparation for a new file. -* -* Arguments: -* none -* -* Returns: -* nothing -----------------------------------------------------------------*/ + * free_srecs + * + * Clears the srec data structures in preparation for a new file. + * + * Arguments: + * none + * + * Returns: + * nothing + *---------------------------------------------------------------- + */ static void free_srecs(void) { ns3data = 0; @@ -486,19 +491,20 @@ static void free_srecs(void) } /*---------------------------------------------------------------- -* mkimage -* -* Scans the currently loaded set of S records for data residing -* in contiguous memory regions. Each contiguous region is then -* made into a 'chunk'. This function assumes that we're building -* a new chunk list. Assumes the s3data items are in sorted order. -* -* Arguments: none -* -* Returns: -* 0 - success -* ~0 - failure (probably an errno) -----------------------------------------------------------------*/ + * mkimage + * + * Scans the currently loaded set of S records for data residing + * in contiguous memory regions. Each contiguous region is then + * made into a 'chunk'. This function assumes that we're building + * a new chunk list. Assumes the s3data items are in sorted order. + * + * Arguments: none + * + * Returns: + * 0 - success + * ~0 - failure (probably an errno) + *---------------------------------------------------------------- + */ static int mkimage(struct imgchunk *clist, unsigned int *ccnt) { int result = 0; @@ -577,19 +583,20 @@ static int mkimage(struct imgchunk *clist, unsigned int *ccnt) } /*---------------------------------------------------------------- -* mkpdrlist -* -* Reads a raw PDA and builds an array of pdrec_t structures. -* -* Arguments: -* pda buffer containing raw PDA bytes -* pdrec ptr to an array of pdrec_t's. Will be filled on exit. -* nrec ptr to a variable that will contain the count of PDRs -* -* Returns: -* 0 - success -* ~0 - failure (probably an errno) -----------------------------------------------------------------*/ + * mkpdrlist + * + * Reads a raw PDA and builds an array of pdrec_t structures. + * + * Arguments: + * pda buffer containing raw PDA bytes + * pdrec ptr to an array of pdrec_t's. Will be filled on exit. + * nrec ptr to a variable that will contain the count of PDRs + * + * Returns: + * 0 - success + * ~0 - failure (probably an errno) + *---------------------------------------------------------------- + */ static int mkpdrlist(struct pda *pda) { u16 *pda16 = (u16 *)pda->buf; @@ -644,22 +651,23 @@ static int mkpdrlist(struct pda *pda) } /*---------------------------------------------------------------- -* plugimage -* -* Plugs the given image using the given plug records from the given -* PDA and filename. -* -* Arguments: -* fchunk Array of image chunks -* nfchunks Number of image chunks -* s3plug Array of plug records -* ns3plug Number of plug records -* pda Current pda data -* -* Returns: -* 0 success -* ~0 failure -----------------------------------------------------------------*/ + * plugimage + * + * Plugs the given image using the given plug records from the given + * PDA and filename. + * + * Arguments: + * fchunk Array of image chunks + * nfchunks Number of image chunks + * s3plug Array of plug records + * ns3plug Number of plug records + * pda Current pda data + * + * Returns: + * 0 success + * ~0 failure + *---------------------------------------------------------------- + */ static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, struct s3plugrec *s3plug, unsigned int ns3plug, struct pda *pda) { @@ -749,23 +757,24 @@ static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, } /*---------------------------------------------------------------- -* read_cardpda -* -* Sends the command for the driver to read the pda from the card -* named in the device variable. Upon success, the card pda is -* stored in the "cardpda" variables. Note that the pda structure -* is considered 'well formed' after this function. That means -* that the nrecs is valid, the rec array has been set up, and there's -* a valid PDAEND record in the raw PDA data. -* -* Arguments: -* pda pda structure -* wlandev device -* -* Returns: -* 0 - success -* ~0 - failure (probably an errno) -----------------------------------------------------------------*/ + * read_cardpda + * + * Sends the command for the driver to read the pda from the card + * named in the device variable. Upon success, the card pda is + * stored in the "cardpda" variables. Note that the pda structure + * is considered 'well formed' after this function. That means + * that the nrecs is valid, the rec array has been set up, and there's + * a valid PDAEND record in the raw PDA data. + * + * Arguments: + * pda pda structure + * wlandev device + * + * Returns: + * 0 - success + * ~0 - failure (probably an errno) + *---------------------------------------------------------------- + */ static int read_cardpda(struct pda *pda, struct wlandevice *wlandev) { int result = 0; @@ -802,65 +811,66 @@ static int read_cardpda(struct pda *pda, struct wlandevice *wlandev) } /*---------------------------------------------------------------- -* read_fwfile -* -* Reads the given fw file which should have been compiled from an srec -* file. Each record in the fw file will either be a plain data record, -* a start address record, or other records used for plugging. -* -* Note that data records are expected to be sorted into -* ascending address order in the fw file. -* -* Note also that the start address record, originally an S7 record in -* the srec file, is expected in the fw file to be like a data record but -* with a certain address to make it identifiable. -* -* Here's the SREC format that the fw should have come from: -* S[37]nnaaaaaaaaddd...dddcc -* -* nn - number of bytes starting with the address field -* aaaaaaaa - address in readable (or big endian) format -* dd....dd - 0-245 data bytes (two chars per byte) -* cc - checksum -* -* The S7 record's (there should be only one) address value gets -* converted to an S3 record with address of 0xff400000, with the -* start address being stored as a 4 byte data word. That address is -* the start execution address used for RAM downloads. -* -* The S3 records have a collection of subformats indicated by the -* value of aaaaaaaa: -* 0xff000000 - Plug record, data field format: -* xxxxxxxxaaaaaaaassssssss -* x - PDR code number (little endian) -* a - Address in load image to plug (little endian) -* s - Length of plug data area (little endian) -* -* 0xff100000 - CRC16 generation record, data field format: -* aaaaaaaassssssssbbbbbbbb -* a - Start address for CRC calculation (little endian) -* s - Length of data to calculate over (little endian) -* b - Boolean, true=write crc, false=don't write -* -* 0xff200000 - Info record, data field format: -* ssssttttdd..dd -* s - Size in words (little endian) -* t - Info type (little endian), see #defines and -* struct s3inforec for details about types. -* d - (s - 1) little endian words giving the contents of -* the given info type. -* -* 0xff400000 - Start address record, data field format: -* aaaaaaaa -* a - Address in load image to plug (little endian) -* -* Arguments: -* record firmware image (ihex record structure) in kernel memory -* -* Returns: -* 0 - success -* ~0 - failure (probably an errno) -----------------------------------------------------------------*/ + * read_fwfile + * + * Reads the given fw file which should have been compiled from an srec + * file. Each record in the fw file will either be a plain data record, + * a start address record, or other records used for plugging. + * + * Note that data records are expected to be sorted into + * ascending address order in the fw file. + * + * Note also that the start address record, originally an S7 record in + * the srec file, is expected in the fw file to be like a data record but + * with a certain address to make it identifiable. + * + * Here's the SREC format that the fw should have come from: + * S[37]nnaaaaaaaaddd...dddcc + * + * nn - number of bytes starting with the address field + * aaaaaaaa - address in readable (or big endian) format + * dd....dd - 0-245 data bytes (two chars per byte) + * cc - checksum + * + * The S7 record's (there should be only one) address value gets + * converted to an S3 record with address of 0xff400000, with the + * start address being stored as a 4 byte data word. That address is + * the start execution address used for RAM downloads. + * + * The S3 records have a collection of subformats indicated by the + * value of aaaaaaaa: + * 0xff000000 - Plug record, data field format: + * xxxxxxxxaaaaaaaassssssss + * x - PDR code number (little endian) + * a - Address in load image to plug (little endian) + * s - Length of plug data area (little endian) + * + * 0xff100000 - CRC16 generation record, data field format: + * aaaaaaaassssssssbbbbbbbb + * a - Start address for CRC calculation (little endian) + * s - Length of data to calculate over (little endian) + * b - Boolean, true=write crc, false=don't write + * + * 0xff200000 - Info record, data field format: + * ssssttttdd..dd + * s - Size in words (little endian) + * t - Info type (little endian), see #defines and + * struct s3inforec for details about types. + * d - (s - 1) little endian words giving the contents of + * the given info type. + * + * 0xff400000 - Start address record, data field format: + * aaaaaaaa + * a - Address in load image to plug (little endian) + * + * Arguments: + * record firmware image (ihex record structure) in kernel memory + * + * Returns: + * 0 - success + * ~0 - failure (probably an errno) + *---------------------------------------------------------------- + */ static int read_fwfile(const struct ihex_binrec *record) { int i; @@ -968,20 +978,21 @@ static int read_fwfile(const struct ihex_binrec *record) } /*---------------------------------------------------------------- -* writeimage -* -* Takes the chunks, builds p80211 messages and sends them down -* to the driver for writing to the card. -* -* Arguments: -* wlandev device -* fchunk Array of image chunks -* nfchunks Number of image chunks -* -* Returns: -* 0 success -* ~0 failure -----------------------------------------------------------------*/ + * writeimage + * + * Takes the chunks, builds p80211 messages and sends them down + * to the driver for writing to the card. + * + * Arguments: + * wlandev device + * fchunk Array of image chunks + * nfchunks Number of image chunks + * + * Returns: + * 0 success + * ~0 failure + *---------------------------------------------------------------- + */ static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk, unsigned int nfchunks) { -- cgit v1.2.3 From 173bf7e37f71173f1645161ee849dfdc3d577300 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:13:21 +0200 Subject: staging: wlan-ng: avoid new typedef CTLX_STATE This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef CTLX_STATE Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 3 +-- drivers/staging/wlan-ng/hfa384x_usb.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 612f928c1c77..6337b1da9eaa 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1169,7 +1169,6 @@ enum ctlx_state { CTLX_REQ_COMPLETE, /* OUT URB complete */ CTLX_RESP_COMPLETE /* IN URB received */ }; -typedef enum ctlx_state CTLX_STATE; struct hfa384x_usbctlx; struct hfa384x; @@ -1186,7 +1185,7 @@ struct hfa384x_usbctlx { union hfa384x_usbout outbuf; /* pkt buf for OUT */ union hfa384x_usbin inbuf; /* pkt buf for IN(a copy) */ - CTLX_STATE state; /* Tracks running state */ + enum ctlx_state state; /* Tracks running state */ struct completion done; volatile int reapable; /* Food for the reaper task */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 1bfea8db3374..fbd9dc6b81ee 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -267,7 +267,7 @@ hfa384x_dowmem(struct hfa384x *hw, static int hfa384x_isgood_pdrcode(u16 pdrcode); -static inline const char *ctlxstr(CTLX_STATE s) +static inline const char *ctlxstr(enum ctlx_state s) { static const char * const ctlx_str[] = { "Initial state", -- cgit v1.2.3 From cfea8abf67e57dbe430338895fbb127374672da1 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:29:22 +0200 Subject: staging: wlan-ng: get memory from kernel allocators instead of big static buffer This patch fix the following sparse warnings in prism2fw.c: warning: memset with byte count of 120000 Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2fw.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 2454a787b177..d90b1f47a558 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -124,7 +124,7 @@ struct imgchunk { /* Data records */ static unsigned int ns3data; -static struct s3datarec s3data[S3DATA_MAX]; +static struct s3datarec *s3data; /* Plug records */ static unsigned int ns3plug; @@ -250,7 +250,12 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, /* Initialize the data structures */ ns3data = 0; - memset(s3data, 0, sizeof(s3data)); + s3data = kcalloc(S3DATA_MAX, sizeof(*s3data), GFP_KERNEL); + if (!s3data) { + result = -ENOMEM; + goto out; + } + ns3plug = 0; memset(s3plug, 0, sizeof(s3plug)); ns3crc = 0; @@ -480,7 +485,7 @@ static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks) static void free_srecs(void) { ns3data = 0; - memset(s3data, 0, sizeof(s3data)); + kfree(s3data); ns3plug = 0; memset(s3plug, 0, sizeof(s3plug)); ns3crc = 0; -- cgit v1.2.3 From 4fdaa0d700e4fae4ea99a5b2bb857c4c0e619dfe Mon Sep 17 00:00:00 2001 From: Akshay Mariyanna Date: Mon, 10 Oct 2016 00:42:18 +0530 Subject: staging: ks7010: fix indent style in ks7010_sdio.c This patch fixes the following checkpatch error: ERROR: code indent should use tabs where possible Signed-off-by: Akshay Mariyanna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks7010_sdio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 1f97161e4945..a37cadffe539 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -35,18 +35,18 @@ MODULE_DEVICE_TABLE(sdio, ks7010_sdio_ids); /* macro */ #define inc_txqhead(priv) \ - (priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE) + (priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE) #define inc_txqtail(priv) \ - (priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE) + (priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE) #define cnt_txqbody(priv) \ - (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE) + (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE) #define inc_rxqhead(priv) \ - (priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE) + (priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE) #define inc_rxqtail(priv) \ - (priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE) + (priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE) #define cnt_rxqbody(priv) \ - (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE) + (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE) static int ks7010_sdio_read(struct ks_wlan_private *priv, unsigned int address, unsigned char *buffer, int length) -- cgit v1.2.3 From 71a476e48dbdfc62f510396b645fe75a7ac8647b Mon Sep 17 00:00:00 2001 From: Akshay Mariyanna Date: Mon, 10 Oct 2016 00:42:20 +0530 Subject: staging: ks7010: fix space related style issues in ks7010_sdio.c This fixes the following checkpatch warnings: WARNING: Unnecessary space before function pointer arguments WARNING: unnecessary whitespace before a quoted newline Signed-off-by: Akshay Mariyanna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks7010_sdio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index a37cadffe539..b02980d9bec2 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -254,7 +254,7 @@ int ks_wlan_hw_power_save(struct ks_wlan_private *priv) static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p, unsigned long size, - void (*complete_handler) (void *arg1, void *arg2), + void (*complete_handler)(void *arg1, void *arg2), void *arg1, void *arg2) { struct tx_device_buffer *sp; @@ -353,7 +353,7 @@ static void tx_device_task(void *dev) } int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size, - void (*complete_handler) (void *arg1, void *arg2), + void (*complete_handler)(void *arg1, void *arg2), void *arg1, void *arg2) { int result = 0; @@ -413,7 +413,7 @@ static void ks_wlan_hw_rx(void *dev, uint16_t size) /* receive data */ if (cnt_rxqbody(priv) >= (RX_DEVICE_BUFF_SIZE - 1)) { /* in case of buffer overflow */ - DPRINTK(1, "rx buffer overflow \n"); + DPRINTK(1, "rx buffer overflow\n"); goto error_out; } rx_buffer = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qtail]; -- cgit v1.2.3 From 4ba165e76b9420ddfa0e68d91db18249d86155e1 Mon Sep 17 00:00:00 2001 From: Sabitha George Date: Mon, 10 Oct 2016 12:03:12 +0530 Subject: staging: ks7010: use netdev_* instead of printk() 1. Fixes checkpatch warning on printk usage in ks_hostif.c 2. Dropped "ks_wlan" prefix from the messages 3. Removed the "Memory squeeze,dropping packet" messages Signed-off-by: Sabitha George Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 5714cf758831..1f9f63e6e996 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -465,8 +465,6 @@ void hostif_data_indication(struct ks_wlan_private *priv) skb->dev->last_rx = jiffies; netif_rx(skb); } else { - printk(KERN_WARNING - "ks_wlan: Memory squeeze, dropping packet.\n"); priv->nstats.rx_dropped++; } break; @@ -500,8 +498,6 @@ void hostif_data_indication(struct ks_wlan_private *priv) skb->dev->last_rx = jiffies; netif_rx(skb); } else { - printk(KERN_WARNING - "ks_wlan: Memory squeeze, dropping packet.\n"); priv->nstats.rx_dropped++; } break; @@ -549,7 +545,7 @@ void hostif_mib_get_confirm(struct ks_wlan_private *priv) dev->dev_addr[5] = priv->eth_addr[5]; dev->dev_addr[6] = 0x00; dev->dev_addr[7] = 0x00; - printk(KERN_INFO "ks_wlan: MAC ADDRESS = %pM\n", priv->eth_addr); + netdev_info(dev, "MAC ADDRESS = %pM\n", priv->eth_addr); break; case DOT11_PRODUCT_VERSION: /* firmware version */ @@ -557,8 +553,8 @@ void hostif_mib_get_confirm(struct ks_wlan_private *priv) priv->version_size = priv->rx_size; memcpy(priv->firmware_version, priv->rxp, priv->rx_size); priv->firmware_version[priv->rx_size] = '\0'; - printk(KERN_INFO "ks_wlan: firmware ver. = %s\n", - priv->firmware_version); + netdev_info(dev, "firmware ver. = %s\n", + priv->firmware_version); hostif_sme_enqueue(priv, SME_GET_PRODUCT_VERSION); /* wake_up_interruptible_all(&priv->confirm_wait); */ complete(&priv->confirm_wait); @@ -578,12 +574,12 @@ void hostif_mib_get_confirm(struct ks_wlan_private *priv) } else if (priv->eeprom_sum.type == 1) { if (priv->eeprom_sum.result == 0) { priv->eeprom_checksum = EEPROM_NG; - printk("LOCAL_EEPROM_SUM NG\n"); + netdev_info(dev, "LOCAL_EEPROM_SUM NG\n"); } else if (priv->eeprom_sum.result == 1) { priv->eeprom_checksum = EEPROM_OK; } } else { - printk("LOCAL_EEPROM_SUM error!\n"); + netdev_err(dev, "LOCAL_EEPROM_SUM error!\n"); } break; default: @@ -880,7 +876,7 @@ void hostif_stop_confirm(struct ks_wlan_private *priv) netif_carrier_off(netdev); tmp = FORCE_DISCONNECT & priv->connect_status; priv->connect_status = tmp | DISCONNECT_STATUS; - printk("IWEVENT: disconnect\n"); + netdev_info(netdev, "IWEVENT: disconnect\n"); wrqu0.data.length = 0; wrqu0.data.flags = 0; @@ -890,7 +886,7 @@ void hostif_stop_confirm(struct ks_wlan_private *priv) && (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { eth_zero_addr(wrqu0.ap_addr.sa_data); DPRINTK(3, "IWEVENT: disconnect\n"); - printk("IWEVENT: disconnect\n"); + netdev_info(netdev, "IWEVENT: disconnect\n"); DPRINTK(3, "disconnect :: scan_ind_count=%d\n", priv->scan_ind_count); wireless_send_event(netdev, SIOCGIWAP, &wrqu0, NULL); @@ -1096,7 +1092,7 @@ void hostif_event_check(struct ks_wlan_private *priv) case HIF_AP_SET_CONF: default: //DPRINTK(1, "undefined event[%04X]\n", event); - printk("undefined event[%04X]\n", event); + netdev_err(priv->net_dev, "undefined event[%04X]\n", event); /* wake_up_all(&priv->confirm_wait); */ complete(&priv->confirm_wait); break; @@ -2644,7 +2640,7 @@ void hostif_sme_enqueue(struct ks_wlan_private *priv, unsigned short event) } else { /* in case of buffer overflow */ //DPRINTK(2,"sme queue buffer overflow\n"); - printk("sme queue buffer overflow\n"); + netdev_err(priv->net_dev, "sme queue buffer overflow\n"); } tasklet_schedule(&priv->sme_task); -- cgit v1.2.3 From 3ae3a74736a1532243c278a11d769f0aefe85618 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:26 +0200 Subject: staging: wlan-ng: fix block comments style in p80211conv.h This patch fixes the following checkpatch.pl warning in p80211conv.h: Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.h | 100 +++++++++++++++++------------------ 1 file changed, 50 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h index 8c10357bedf0..ed70d98e5cf1 100644 --- a/drivers/staging/wlan-ng/p80211conv.h +++ b/drivers/staging/wlan-ng/p80211conv.h @@ -1,54 +1,54 @@ /* p80211conv.h -* -* Ether/802.11 conversions and packet buffer routines -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file declares the functions, types and macros that perform -* Ethernet to/from 802.11 frame conversions. -* -* -------------------------------------------------------------------- -*/ + * + * Ether/802.11 conversions and packet buffer routines + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file declares the functions, types and macros that perform + * Ethernet to/from 802.11 frame conversions. + * + * -------------------------------------------------------------------- + */ #ifndef _LINUX_P80211CONV_H #define _LINUX_P80211CONV_H -- cgit v1.2.3 From ed2e0f83944d0c26efed05371af5dbcd2c0a2f28 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:27 +0200 Subject: staging: wlan-ng: fix block comments style in p80211hdr.h This patch fixes the following checkpatch.pl warning in p80211hdr.h: Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211hdr.h | 114 ++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h index 79d9b20b364d..c9b73373f6df 100644 --- a/drivers/staging/wlan-ng/p80211hdr.h +++ b/drivers/staging/wlan-ng/p80211hdr.h @@ -1,61 +1,61 @@ /* p80211hdr.h -* -* Macros, types, and functions for handling 802.11 MAC headers -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file declares the constants and types used in the interface -* between a wlan driver and the user mode utilities. -* -* Note: -* - Constant values are always in HOST byte order. To assign -* values to multi-byte fields they _must_ be converted to -* ieee byte order. To retrieve multi-byte values from incoming -* frames, they must be converted to host order. -* -* All functions declared here are implemented in p80211.c -* -------------------------------------------------------------------- -*/ + * + * Macros, types, and functions for handling 802.11 MAC headers + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file declares the constants and types used in the interface + * between a wlan driver and the user mode utilities. + * + * Note: + * - Constant values are always in HOST byte order. To assign + * values to multi-byte fields they _must_ be converted to + * ieee byte order. To retrieve multi-byte values from incoming + * frames, they must be converted to host order. + * + * All functions declared here are implemented in p80211.c + * -------------------------------------------------------------------- + */ #ifndef _P80211HDR_H #define _P80211HDR_H -- cgit v1.2.3 From 813ea669c3bdc701fb063b2237754c73397897a1 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:28 +0200 Subject: staging: wlan-ng: fix block comments style in p80211ioctl.h This patch fixes the following checkpatch.pl warning in p80211ioctl.h Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211ioctl.h | 120 +++++++++++++++++----------------- 1 file changed, 60 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h index 06c5e36649a7..ab6067e65050 100644 --- a/drivers/staging/wlan-ng/p80211ioctl.h +++ b/drivers/staging/wlan-ng/p80211ioctl.h @@ -1,64 +1,64 @@ /* p80211ioctl.h -* -* Declares constants and types for the p80211 ioctls -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* While this file is called 'ioctl' is purpose goes a little beyond -* that. This file defines the types and contants used to implement -* the p80211 request/confirm/indicate interfaces on Linux. The -* request/confirm interface is, in fact, normally implemented as an -* ioctl. The indicate interface on the other hand, is implemented -* using the Linux 'netlink' interface. -* -* The reason I say that request/confirm is 'normally' implemented -* via ioctl is that we're reserving the right to be able to send -* request commands via the netlink interface. This will be necessary -* if we ever need to send request messages when there aren't any -* wlan network devices present (i.e. sending a message that only p80211 -* cares about. -* -------------------------------------------------------------------- -*/ + * + * Declares constants and types for the p80211 ioctls + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * While this file is called 'ioctl' is purpose goes a little beyond + * that. This file defines the types and contants used to implement + * the p80211 request/confirm/indicate interfaces on Linux. The + * request/confirm interface is, in fact, normally implemented as an + * ioctl. The indicate interface on the other hand, is implemented + * using the Linux 'netlink' interface. + * + * The reason I say that request/confirm is 'normally' implemented + * via ioctl is that we're reserving the right to be able to send + * request commands via the netlink interface. This will be necessary + * if we ever need to send request messages when there aren't any + * wlan network devices present (i.e. sending a message that only p80211 + * cares about. + * -------------------------------------------------------------------- + */ #ifndef _P80211IOCTL_H #define _P80211IOCTL_H -- cgit v1.2.3 From f09fd9bcf6448b54856e8723a00034c55276e0b1 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:29 +0200 Subject: staging: wlan-ng: fix block comments style in p80211metadef.h This patch fixes the following checkpatch.pl warning in p80211metadef.h Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211metadef.h | 88 ++++++++++++++++----------------- 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index b0d3567ca0ad..ea3d9ce222b9 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -1,48 +1,48 @@ /* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. -* -------------------------------------------------------------------- -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -*/ + * -------------------------------------------------------------------- + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + */ #ifndef _P80211MKMETADEF_H #define _P80211MKMETADEF_H -- cgit v1.2.3 From 6b168f0b5d9fc1bf9199c26c235bdbdf2935a48d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:30 +0200 Subject: staging: wlan-ng: fix block comments style in p80211mgmt.h This patch fixes the following checkpatch.pl warning in p80211mgmt.h: Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211mgmt.h | 194 +++++++++++++++++------------------ 1 file changed, 97 insertions(+), 97 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h index 3dd066ac034e..653950fd9843 100644 --- a/drivers/staging/wlan-ng/p80211mgmt.h +++ b/drivers/staging/wlan-ng/p80211mgmt.h @@ -1,101 +1,101 @@ /* p80211mgmt.h -* -* Macros, types, and functions to handle 802.11 mgmt frames -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file declares the constants and types used in the interface -* between a wlan driver and the user mode utilities. -* -* Notes: -* - Constant values are always in HOST byte order. To assign -* values to multi-byte fields they _must_ be converted to -* ieee byte order. To retrieve multi-byte values from incoming -* frames, they must be converted to host order. -* -* - The len member of the frame structure does NOT!!! include -* the MAC CRC. Therefore, the len field on rx'd frames should -* have 4 subtracted from it. -* -* All functions declared here are implemented in p80211.c -* -* The types, macros, and functions defined here are primarily -* used for encoding and decoding management frames. They are -* designed to follow these patterns of use: -* -* DECODE: -* 1) a frame of length len is received into buffer b -* 2) using the hdr structure and macros, we determine the type -* 3) an appropriate mgmt frame structure, mf, is allocated and zeroed -* 4) mf.hdr = b -* mf.buf = b -* mf.len = len -* 5) call mgmt_decode( mf ) -* 6) the frame field pointers in mf are now set. Note that any -* multi-byte frame field values accessed using the frame field -* pointers are in ieee byte order and will have to be converted -* to host order. -* -* ENCODE: -* 1) Library client allocates buffer space for maximum length -* frame of the desired type -* 2) Library client allocates a mgmt frame structure, called mf, -* of the desired type -* 3) Set the following: -* mf.type = -* mf.buf = -* 4) call mgmt_encode( mf ) -* 5) all of the fixed field pointers and fixed length information element -* pointers in mf are now set to their respective locations in the -* allocated space (fortunately, all variable length information elements -* fall at the end of their respective frames). -* 5a) The length field is set to include the last of the fixed and fixed -* length fields. It may have to be updated for optional or variable -* length information elements. -* 6) Optional and variable length information elements are special cases -* and must be handled individually by the client code. -* -------------------------------------------------------------------- -*/ + * + * Macros, types, and functions to handle 802.11 mgmt frames + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file declares the constants and types used in the interface + * between a wlan driver and the user mode utilities. + * + * Notes: + * - Constant values are always in HOST byte order. To assign + * values to multi-byte fields they _must_ be converted to + * ieee byte order. To retrieve multi-byte values from incoming + * frames, they must be converted to host order. + * + * - The len member of the frame structure does NOT!!! include + * the MAC CRC. Therefore, the len field on rx'd frames should + * have 4 subtracted from it. + * + * All functions declared here are implemented in p80211.c + * + * The types, macros, and functions defined here are primarily + * used for encoding and decoding management frames. They are + * designed to follow these patterns of use: + * + * DECODE: + * 1) a frame of length len is received into buffer b + * 2) using the hdr structure and macros, we determine the type + * 3) an appropriate mgmt frame structure, mf, is allocated and zeroed + * 4) mf.hdr = b + * mf.buf = b + * mf.len = len + * 5) call mgmt_decode( mf ) + * 6) the frame field pointers in mf are now set. Note that any + * multi-byte frame field values accessed using the frame field + * pointers are in ieee byte order and will have to be converted + * to host order. + * + * ENCODE: + * 1) Library client allocates buffer space for maximum length + * frame of the desired type + * 2) Library client allocates a mgmt frame structure, called mf, + * of the desired type + * 3) Set the following: + * mf.type = + * mf.buf = + * 4) call mgmt_encode( mf ) + * 5) all of the fixed field pointers and fixed length information element + * pointers in mf are now set to their respective locations in the + * allocated space (fortunately, all variable length information elements + * fall at the end of their respective frames). + * 5a) The length field is set to include the last of the fixed and fixed + * length fields. It may have to be updated for optional or variable + * length information elements. + * 6) Optional and variable length information elements are special cases + * and must be handled individually by the client code. + * -------------------------------------------------------------------- + */ #ifndef _P80211MGMT_H #define _P80211MGMT_H -- cgit v1.2.3 From ea0ebda761c1d22b5feb8335731b3b229f62e1ea Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:31 +0200 Subject: staging: wlan-ng: fix block comments style in p80211msg.h This patch fixes the following checkpatch.pl warning in p80211msg.h Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211msg.h | 90 ++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h index 43d2f971e2cd..40c5cf5997c7 100644 --- a/drivers/staging/wlan-ng/p80211msg.h +++ b/drivers/staging/wlan-ng/p80211msg.h @@ -1,49 +1,49 @@ /* p80211msg.h -* -* Macros, constants, types, and funcs for req and ind messages -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -*/ + * + * Macros, constants, types, and funcs for req and ind messages + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + */ #ifndef _P80211MSG_H #define _P80211MSG_H -- cgit v1.2.3 From 406c39141a1ddd137b470f362a30fa001e15becc Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:32 +0200 Subject: staging: wlan-ng: fix block comments style in p80211netdev.h This patch fixes the following checkpatch.pl warning in p80211netdev.h Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211netdev.h | 100 ++++++++++++++++----------------- 1 file changed, 50 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 1e6a774fc7c5..972e07663914 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -1,54 +1,54 @@ /* p80211netdev.h -* -* WLAN net device structure and functions -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file declares the structure type that represents each wlan -* interface. -* -* -------------------------------------------------------------------- -*/ + * + * WLAN net device structure and functions + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file declares the structure type that represents each wlan + * interface. + * + * -------------------------------------------------------------------- + */ #ifndef _LINUX_P80211NETDEV_H #define _LINUX_P80211NETDEV_H -- cgit v1.2.3 From 1d715f7ec41d2c4464abfaa33ab8373e29045ab1 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:33 +0200 Subject: staging: wlan-ng: fix block comments style in p80211req.h This patch fixes the following checkpatch.pl warning in p80211req.h Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211req.h | 90 ++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h index 8d3054c22a05..6c72f59993e0 100644 --- a/drivers/staging/wlan-ng/p80211req.h +++ b/drivers/staging/wlan-ng/p80211req.h @@ -1,49 +1,49 @@ /* p80211req.h -* -* Request handling functions -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -*/ + * + * Request handling functions + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + */ #ifndef _LINUX_P80211REQ_H #define _LINUX_P80211REQ_H -- cgit v1.2.3 From d2337a50eb9424ebc91065f0e60d7ce4312efc7b Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 9 Oct 2016 17:51:34 +0200 Subject: staging: wlan-ng: fix block comments style in prism2mgmt.h This patch fixes the following checkpatch.pl warning in prism2mgmt.h Block comments should align the * on each line Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mgmt.h | 122 ++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index 567820fc3735..88b979ff68b3 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -1,61 +1,61 @@ /* prism2mgmt.h -* -* Declares the mgmt command handler functions -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file contains the constants and data structures for interaction -* with the hfa384x Wireless LAN (WLAN) Media Access Controller (MAC). -* The hfa384x is a portion of the Harris PRISM(tm) WLAN chipset. -* -* [Implementation and usage notes] -* -* [References] -* CW10 Programmer's Manual v1.5 -* IEEE 802.11 D10.0 -* -* -------------------------------------------------------------------- -*/ + * + * Declares the mgmt command handler functions + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file contains the constants and data structures for interaction + * with the hfa384x Wireless LAN (WLAN) Media Access Controller (MAC). + * The hfa384x is a portion of the Harris PRISM(tm) WLAN chipset. + * + * [Implementation and usage notes] + * + * [References] + * CW10 Programmer's Manual v1.5 + * IEEE 802.11 D10.0 + * + * -------------------------------------------------------------------- + */ #ifndef _PRISM2MGMT_H #define _PRISM2MGMT_H @@ -84,9 +84,11 @@ int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp); int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp); /*--------------------------------------------------------------- -* conversion functions going between wlan message data types and -* Prism2 data types ----------------------------------------------------------------*/ + * conversion functions going between wlan message data types and + * Prism2 data types + *--------------------------------------------------------------- + */ + /* byte area conversion functions*/ void prism2mgmt_bytearea2pstr(u8 *bytearea, struct p80211pstrd *pstr, int len); -- cgit v1.2.3 From f7417a55104cb0ecdf86a1c0ca89b09b4f2c70ec Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Sun, 9 Oct 2016 15:58:39 +0200 Subject: staging: net: netlogic: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: Greg Kroah-Hartman --- drivers/staging/netlogic/xlr_net.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 552a7dcbf50b..cdf01b931296 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -172,29 +172,31 @@ static struct phy_device *xlr_get_phydev(struct xlr_net_priv *priv) /* * Ethtool operation */ -static int xlr_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) +static int xlr_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *ecmd) { struct xlr_net_priv *priv = netdev_priv(ndev); struct phy_device *phydev = xlr_get_phydev(priv); if (!phydev) return -ENODEV; - return phy_ethtool_gset(phydev, ecmd); + return phy_ethtool_ksettings_get(phydev, ecmd); } -static int xlr_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) +static int xlr_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *ecmd) { struct xlr_net_priv *priv = netdev_priv(ndev); struct phy_device *phydev = xlr_get_phydev(priv); if (!phydev) return -ENODEV; - return phy_ethtool_sset(phydev, ecmd); + return phy_ethtool_ksettings_set(phydev, ecmd); } static const struct ethtool_ops xlr_ethtool_ops = { - .get_settings = xlr_get_settings, - .set_settings = xlr_set_settings, + .get_link_ksettings = xlr_get_link_ksettings, + .set_link_ksettings = xlr_set_link_ksettings, }; /* -- cgit v1.2.3 From db0e8e5732c378393968dfa4fa89153b9d515d60 Mon Sep 17 00:00:00 2001 From: Harman Kalra Date: Sun, 9 Oct 2016 21:05:02 +0530 Subject: Staging: i4l: icn: Fixed open brace should be on previous line error This patch resolves the following error caught by checkpatch.pl: ERROR: that open brace { should be on the previous line Signed-off-by: Harman Kalra Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/icn/icn.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index 514bfc2c5b53..3750ba38adc5 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -411,8 +411,7 @@ typedef struct icn_stat { int action; } icn_stat; /* *INDENT-OFF* */ -static icn_stat icn_stat_table[] = -{ +static icn_stat icn_stat_table[] = { {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */ {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */ /* -- cgit v1.2.3 From bdb2a2ff2c8dfb32c4d52a36e29efc649f2205b0 Mon Sep 17 00:00:00 2001 From: Harman Kalra Date: Sun, 9 Oct 2016 21:05:03 +0530 Subject: Staging: i4l: icn: prefer pr_* instead of printk This patch replaces call to printk with appropriate pr_* function thus addressing the following warning generated by the checkpatch script: Prefer [subsystem eg: netdev]_dbg([subsystem]dev, ... then dev_dbg(dev, ... then pr_debug(... to printk(KERN_DEBUG ... Signed-off-by: Harman Kalra Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/icn/icn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/i4l/icn/icn.h b/drivers/staging/i4l/icn/icn.h index f8f2e76d34bf..e273c2795f3c 100644 --- a/drivers/staging/i4l/icn/icn.h +++ b/drivers/staging/i4l/icn/icn.h @@ -54,7 +54,7 @@ typedef struct icn_cdef { /* some useful macros for debugging */ #ifdef ICN_DEBUG_PORT -#define OUTB_P(v, p) {printk(KERN_DEBUG "icn: outb_p(0x%02x,0x%03x)\n", v, p); outb_p(v, p);} +#define OUTB_P(v, p) {pr_debug("icn: outb_p(0x%02x,0x%03x)\n", v, p); outb_p(v, p);} #else #define OUTB_P outb #endif -- cgit v1.2.3 From 5e5a1138ff09dd3d2ad683f6d40f8d2dd08f1559 Mon Sep 17 00:00:00 2001 From: Harman Kalra Date: Sun, 9 Oct 2016 21:05:04 +0530 Subject: Staging: i4l: icn: Fixed open brace should be on previous line error This patch resolves the following error caught by checkpatch.pl: ERROR: that open brace { should be on the previous line Signed-off-by: Harman Kalra Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/icn/icn.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/i4l/icn/icn.h b/drivers/staging/i4l/icn/icn.h index e273c2795f3c..07e2e0196527 100644 --- a/drivers/staging/i4l/icn/icn.h +++ b/drivers/staging/i4l/icn/icn.h @@ -186,8 +186,7 @@ typedef icn_dev *icn_devptr; #ifdef __KERNEL__ static icn_card *cards = (icn_card *) 0; -static u_char chan2bank[] = -{0, 4, 8, 12}; /* for icn_map_channel() */ +static u_char chan2bank[] = {0, 4, 8, 12}; /* for icn_map_channel() */ static icn_dev dev; -- cgit v1.2.3 From 06d1f85e8118d9fb715891652e6dde2afda066b4 Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman Date: Sun, 9 Oct 2016 11:35:54 -0700 Subject: staging: i4l: remove parens around return statement Remove parentheses surrounding return statements. Error found by checkpatch. changes made using coccinelle script: @@ expression e,e1; @@ ( return (e / e1); | return -( e -) ; ) Signed-off-by: Elizabeth Ferdman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/act2000/capi.c | 2 +- drivers/staging/i4l/act2000/module.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/i4l/act2000/capi.c b/drivers/staging/i4l/act2000/capi.c index 66c1e579fc04..61386a78fb91 100644 --- a/drivers/staging/i4l/act2000/capi.c +++ b/drivers/staging/i4l/act2000/capi.c @@ -99,7 +99,7 @@ actcapi_chkhdr(act2000_card *card, actcapi_msghdr *hdr) for (i = 0; i < num_valid_imsg; i++) if ((hdr->cmd.cmd == valid_msg[i].cmd.cmd) && (hdr->cmd.subcmd == valid_msg[i].cmd.subcmd)) { - return (i ? 1 : 2); + return i ? 1 : 2; } return 0; } diff --git a/drivers/staging/i4l/act2000/module.c b/drivers/staging/i4l/act2000/module.c index e227c08b4f00..6aa120319e52 100644 --- a/drivers/staging/i4l/act2000/module.c +++ b/drivers/staging/i4l/act2000/module.c @@ -94,7 +94,7 @@ act2000_find_msn(act2000_card *card, char *msn, int ia5) p = p->next; } if (!ia5) - return (1 << (eaz - '0')); + return 1 << (eaz - '0'); else return eaz; } @@ -110,10 +110,10 @@ act2000_find_eaz(act2000_card *card, char eaz) while (p) { if (p->eaz == eaz) - return (p->msn); + return p->msn; p = p->next; } - return ("\0"); + return "\0"; } /* @@ -292,7 +292,7 @@ act2000_command(act2000_card *card, isdn_ctrl *c) if (ret) return ret; if (card->flags & ACT2000_FLAGS_RUNNING) - return (actcapi_manufacturer_req_msn(card)); + return actcapi_manufacturer_req_msn(card); return 0; case ACT2000_IOCTL_ADDCARD: if (copy_from_user(&cdef, arg, @@ -512,7 +512,7 @@ if_command(isdn_ctrl *c) act2000_card *card = act2000_findcard(c->driver); if (card) - return (act2000_command(card, c)); + return act2000_command(card, c); printk(KERN_ERR "act2000: if_command %d called with invalid driverId %d!\n", c->command, c->driver); @@ -527,7 +527,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) if (card) { if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; - return (len); + return len; } printk(KERN_ERR "act2000: if_writecmd called with invalid driverId!\n"); @@ -542,7 +542,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) if (card) { if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; - return (act2000_readstatus(buf, len, card)); + return act2000_readstatus(buf, len, card); } printk(KERN_ERR "act2000: if_readstatus called with invalid driverId!\n"); @@ -557,7 +557,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) if (card) { if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; - return (act2000_sendbuf(card, channel, ack, skb)); + return act2000_sendbuf(card, channel, ack, skb); } printk(KERN_ERR "act2000: if_sendbuf called with invalid driverId!\n"); @@ -777,7 +777,7 @@ act2000_addcard(int bus, int port, int irq, char *id) failed++; } } - return (added - failed); + return added - failed; } #define DRIVERNAME "IBM Active 2000 ISDN driver" -- cgit v1.2.3 From 0907bb2ca2b0f712743fcf7b0d6448d0ec1848d8 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Sun, 9 Oct 2016 23:24:33 -0300 Subject: staging: media: cxd2099: Format block comments. Fix checkpatch warning: WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/cxd2099/cxd2099.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c index fedeb3c3549e..c72c3f09f175 100644 --- a/drivers/staging/media/cxd2099/cxd2099.c +++ b/drivers/staging/media/cxd2099/cxd2099.c @@ -336,7 +336,8 @@ static int init(struct cxd *ci) break; #endif /* TOSTRT = 8, Mode B (gated clock), falling Edge, - * Serial, POL=HIGH, MSB */ + * Serial, POL=HIGH, MSB + */ status = write_reg(ci, 0x0A, 0xA7); if (status < 0) break; -- cgit v1.2.3 From 98b6594844c956d79ccac581a3f08194241afc59 Mon Sep 17 00:00:00 2001 From: Dilek Uzulmez Date: Sun, 9 Oct 2016 22:27:53 +0300 Subject: Staging: wilc1000: Remove unnecessary 'out of memory' message. This patch fixes checkpatch.pl warning in file host_interface.c WARNING: Possible unnecessary 'out of memory' message Signed-off-by: Dilek Uzulmez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 78f5613e9467..0d16e49a9656 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -2322,10 +2322,8 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, wid.size = 2; wid.val = kmalloc(wid.size, GFP_KERNEL); - if (!wid.val) { - netdev_err(vif->ndev, "Failed to allocate memory\n"); + if (!wid.val) return -ENOMEM; - } wid.val[0] = u8remain_on_chan_flag; wid.val[1] = FALSE_FRMWR_CHANNEL; -- cgit v1.2.3 From 14e6cc71bcf3dcdd9436275721b3ad0d5650e94f Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Mon, 10 Oct 2016 00:38:20 -0300 Subject: staging: wilc1000: Replace printk() with pr_info(). Fix checkpatch warning: WARNING: Prefer [subsystem eg: netdev]_info([subsystem]dev, ... then dev_info(dev, ... then pr_info(... to printk(KERN_INFO ... Replace printk(KERN_INFO...) by pr_info() for more uniform error reporting. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 802bb1d5e207..07260c497db4 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -62,16 +62,16 @@ static ssize_t wilc_debug_level_write(struct file *filp, const char __user *buf, return ret; if (flag > DBG_LEVEL_ALL) { - printk("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(&WILC_DEBUG_LEVEL)); + pr_info("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(&WILC_DEBUG_LEVEL)); return -EINVAL; } atomic_set(&WILC_DEBUG_LEVEL, (int)flag); if (flag == 0) - printk(KERN_INFO "Debug-level disabled\n"); + pr_info("Debug-level disabled\n"); else - printk(KERN_INFO "Debug-level enabled\n"); + pr_info("Debug-level enabled\n"); return count; } -- cgit v1.2.3 From 7343f6215a9d1f90be3ba95a058707ce6cb5980f Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Mon, 10 Oct 2016 11:13:14 +0300 Subject: Staging: wilc1000: Unnecessary 'out of memory' message This patch fixes checkpatch.pl warning in file host_interface.c WARNING : possible unecessary 'out of memory' message. Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0d16e49a9656..ff3d267c2eb0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1722,10 +1722,8 @@ _WPAPtk_end_case_: case PMKSA: pu8keybuf = kmalloc((pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1, GFP_KERNEL); - if (!pu8keybuf) { - netdev_err(vif->ndev, "No buffer to send PMKSA Key\n"); + if (!pu8keybuf) return -ENOMEM; - } pu8keybuf[0] = pstrHostIFkeyAttr->attr.pmkid.numpmkid; -- cgit v1.2.3 From 673ec4e05e2666ac2cbfab823d6fff3733cfcc46 Mon Sep 17 00:00:00 2001 From: Dilek Uzulmez Date: Sun, 9 Oct 2016 22:43:21 +0300 Subject: Staging: rts5208: Remove unnecessary parentheses Problem found using checkpatch.pl CHECK: Unnecessary parentheses around dev->dev_mutex Signed-off-by: Dilek Uzulmez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 5d65a5cdc748..750e2a75912f 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -313,7 +313,7 @@ static int rtsx_suspend(struct pci_dev *pci, pm_message_t state) return 0; /* lock the device pointers */ - mutex_lock(&(dev->dev_mutex)); + mutex_lock(&dev->dev_mutex); chip = dev->chip; @@ -349,7 +349,7 @@ static int rtsx_resume(struct pci_dev *pci) chip = dev->chip; /* lock the device pointers */ - mutex_lock(&(dev->dev_mutex)); + mutex_lock(&dev->dev_mutex); pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); @@ -418,7 +418,7 @@ static int rtsx_control_thread(void *__dev) break; /* lock the device pointers */ - mutex_lock(&(dev->dev_mutex)); + mutex_lock(&dev->dev_mutex); /* if the device has disconnected, we are free to exit */ if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { @@ -536,7 +536,7 @@ static int rtsx_polling_thread(void *__dev) schedule_timeout(msecs_to_jiffies(POLLING_INTERVAL)); /* lock the device pointers */ - mutex_lock(&(dev->dev_mutex)); + mutex_lock(&dev->dev_mutex); /* if the device has disconnected, we are free to exit */ if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { @@ -550,7 +550,7 @@ static int rtsx_polling_thread(void *__dev) mspro_polling_format_status(chip); /* lock the device pointers */ - mutex_lock(&(dev->dev_mutex)); + mutex_lock(&dev->dev_mutex); rtsx_polling_func(chip); @@ -886,7 +886,7 @@ static int rtsx_probe(struct pci_dev *pci, } spin_lock_init(&dev->reg_lock); - mutex_init(&(dev->dev_mutex)); + mutex_init(&dev->dev_mutex); init_completion(&dev->cmnd_ready); init_completion(&dev->control_exit); init_completion(&dev->polling_exit); -- cgit v1.2.3 From 9ae7a47f7f3226c3782418e63f833f8b298266af Mon Sep 17 00:00:00 2001 From: Chase Metzger Date: Sun, 9 Oct 2016 15:26:33 -0700 Subject: drivers: staging: greybus: audio_codec.c: Fixed CHECKS for brace issues Added braces to else statement where checkpatch complained. Signed-off-by: Chase Metzger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_codec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 8a0744b58a32..1bdf84925d22 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -655,8 +655,10 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0); params->state = GBAUDIO_CODEC_STOP; - } else + } else { ret = -EINVAL; + } + if (ret) dev_err_ratelimited(dai->dev, "%s:Error during %s %s stream:%d\n", -- cgit v1.2.3 From 7a29a391ec8e615fab4d37add5708a4cc76421a7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 10 Oct 2016 12:01:41 +0200 Subject: staging: vc04_services: fix debugfs write functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit write functions need to return ssize_t, not int, so fix the functions up for the correct prototype. Cc: Daniel Stone Cc: "Noralf Trønnes" Cc: Pranith Kumar Cc: popcornmix Cc: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c index 7e032130d967..f07cd4448ddf 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c @@ -120,7 +120,7 @@ static int debugfs_log_open(struct inode *inode, struct file *file) return single_open(file, debugfs_log_show, inode->i_private); } -static int debugfs_log_write(struct file *file, +static ssize_t debugfs_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { @@ -229,7 +229,7 @@ static int debugfs_trace_open(struct inode *inode, struct file *file) return single_open(file, debugfs_trace_show, inode->i_private); } -static int debugfs_trace_write(struct file *file, +static ssize_t debugfs_trace_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { -- cgit v1.2.3 From f51bb7a6f548e961eb50e2221e45fcfe2b31ed94 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 10 Oct 2016 12:03:17 +0200 Subject: staging: vc04_services: fix dmac_map/unmap_area prototypes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit You don't define a function prototype on one line as a #define, and then the next declare it as an external C function, without expecting a C compiler to complain loudly. So fix up this mess. Cc: Daniel Stone Cc: "Noralf Trønnes" Cc: Pranith Kumar Cc: popcornmix Cc: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 4cb5bff23728..9ba0e2a7e01e 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -48,9 +48,6 @@ #define dmac_map_area __glue(_CACHE,_dma_map_area) #define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) -extern void dmac_map_area(const void *, size_t, int); -extern void dmac_unmap_area(const void *, size_t, int); - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) #define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) -- cgit v1.2.3 From df044ebfc5bfba6810e3940db458d7fb4572bc6f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 10 Oct 2016 14:23:49 +0200 Subject: staging: vc04_services: don't print pointers directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kernel pointers should be printed with %pK and are not unsigned int big on all architectures. So fix this up to get rid of a bunch of warning messages. Note, there are other assumptions in this code that a pointer fits into an int that need to be fixed up later. Cc: Daniel Stone Cc: "Noralf Trønnes" Cc: Pranith Kumar Cc: popcornmix Cc: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../interface/vchiq_arm/vchiq_2835_arm.c | 12 +- .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 36 ++- .../vc04_services/interface/vchiq_arm/vchiq_core.c | 256 ++++++++------------- .../interface/vchiq_arm/vchiq_kern_lib.c | 9 +- 4 files changed, 124 insertions(+), 189 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 9ba0e2a7e01e..ca1fee35cc73 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -171,8 +171,8 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) } vchiq_log_info(vchiq_arm_log_level, - "vchiq_init - done (slots %x, phys %pad)", - (unsigned int)vchiq_slot_zero, &slot_phys); + "vchiq_init - done (slots %pK, phys %pad)", + vchiq_slot_zero, &slot_phys); vchiq_call_connected_callbacks(); @@ -386,8 +386,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, (num_pages * sizeof(pages[0])), GFP_KERNEL); - vchiq_log_trace(vchiq_arm_log_level, - "create_pagelist - %x", (unsigned int)pagelist); + vchiq_log_trace(vchiq_arm_log_level, "create_pagelist - %pK", + pagelist); if (!pagelist) return -ENOMEM; @@ -511,8 +511,8 @@ free_pagelist(PAGELIST_T *pagelist, int actual) struct page **pages; unsigned int num_pages, i; - vchiq_log_trace(vchiq_arm_log_level, - "free_pagelist - %x, %d", (unsigned int)pagelist, actual); + vchiq_log_trace(vchiq_arm_log_level, "free_pagelist - %pK, %d", + pagelist, actual); num_pages = (pagelist->length + pagelist->offset + PAGE_SIZE - 1) / diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 47df1af2219d..5ec7c96fad33 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -418,8 +418,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) DEBUG_INITIALISE(g_state.local) vchiq_log_trace(vchiq_arm_log_level, - "vchiq_ioctl - instance %x, cmd %s, arg %lx", - (unsigned int)instance, + "vchiq_ioctl - instance %pK, cmd %s, arg %lx", + instance, ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ? ioctl_names[_IOC_NR(cmd)] : "", arg); @@ -713,8 +713,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } vchiq_log_info(vchiq_arm_log_level, - "found bulk_waiter %x for pid %d", - (unsigned int)waiter, current->pid); + "found bulk_waiter %pK for pid %d", waiter, + current->pid); args.userdata = &waiter->bulk_waiter; } status = vchiq_bulk_transfer @@ -743,8 +743,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) list_add(&waiter->list, &instance->bulk_waiter_list); mutex_unlock(&instance->bulk_waiter_list_mutex); vchiq_log_info(vchiq_arm_log_level, - "saved bulk_waiter %x for pid %d", - (unsigned int)waiter, current->pid); + "saved bulk_waiter %pK for pid %d", + waiter, current->pid); if (copy_to_user((void __user *) &(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *) @@ -826,10 +826,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (args.msgbufsize < msglen) { vchiq_log_error( vchiq_arm_log_level, - "header %x: msgbufsize" - " %x < msglen %x", - (unsigned int)header, - args.msgbufsize, + "header %pK: msgbufsize %x < msglen %x", + header, args.msgbufsize, msglen); WARN(1, "invalid message " "size\n"); @@ -980,9 +978,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -EFAULT; } else { vchiq_log_error(vchiq_arm_log_level, - "header %x: bufsize %x < size %x", - (unsigned int)header, args.bufsize, - header->size); + "header %pK: bufsize %x < size %x", + header, args.bufsize, header->size); WARN(1, "invalid size\n"); ret = -EMSGSIZE; } @@ -1284,9 +1281,8 @@ vchiq_release(struct inode *inode, struct file *file) list); list_del(pos); vchiq_log_info(vchiq_arm_log_level, - "bulk_waiter - cleaned up %x " - "for pid %d", - (unsigned int)waiter, waiter->pid); + "bulk_waiter - cleaned up %pK for pid %d", + waiter, waiter->pid); kfree(waiter); } } @@ -1385,9 +1381,8 @@ vchiq_dump_platform_instances(void *dump_context) instance = service->instance; if (instance && !instance->mark) { len = snprintf(buf, sizeof(buf), - "Instance %x: pid %d,%s completions " - "%d/%d", - (unsigned int)instance, instance->pid, + "Instance %pK: pid %d,%s completions %d/%d", + instance, instance->pid, instance->connected ? " connected, " : "", instance->completion_insert - @@ -1415,8 +1410,7 @@ vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service) char buf[80]; int len; - len = snprintf(buf, sizeof(buf), " instance %x", - (unsigned int)service->instance); + len = snprintf(buf, sizeof(buf), " instance %pK", service->instance); if ((service->base.callback == service_callback) && user_service->is_vchi) { diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 7ed32772997d..1254975a57bc 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -380,9 +380,9 @@ make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, void *bulk_userdata) { VCHIQ_STATUS_T status; - vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %x, %x)", + vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %pK, %pK)", service->state->id, service->localport, reason_names[reason], - (unsigned int)header, (unsigned int)bulk_userdata); + header, bulk_userdata); status = service->base.callback(reason, header, service->handle, bulk_userdata); if (status == VCHIQ_ERROR) { @@ -620,8 +620,8 @@ process_free_queue(VCHIQ_STATE_T *state) char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); int data_found = 0; - vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", - state->id, slot_index, (unsigned int)data, + vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%pK %x %x", + state->id, slot_index, data, local->slot_queue_recycle, slot_queue_available); /* Initialise the bitmask for services which have used this @@ -653,16 +653,10 @@ process_free_queue(VCHIQ_STATE_T *state) up(&service_quota->quota_event); else if (count == 0) { vchiq_log_error(vchiq_core_log_level, - "service %d " - "message_use_count=%d " - "(header %x, msgid %x, " - "header->msgid %x, " - "header->size %x)", + "service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)", port, - service_quota-> - message_use_count, - (unsigned int)header, msgid, - header->msgid, + service_quota->message_use_count, + header, msgid, header->msgid, header->size); WARN(1, "invalid message use count\n"); } @@ -684,26 +678,16 @@ process_free_queue(VCHIQ_STATE_T *state) up(&service_quota->quota_event); vchiq_log_trace( vchiq_core_log_level, - "%d: pfq:%d %x@%x - " - "slot_use->%d", + "%d: pfq:%d %x@%pK - slot_use->%d", state->id, port, - header->size, - (unsigned int)header, + header->size, header, count - 1); } else { vchiq_log_error( vchiq_core_log_level, - "service %d " - "slot_use_count" - "=%d (header %x" - ", msgid %x, " - "header->msgid" - " %x, header->" - "size %x)", - port, count, - (unsigned int)header, - msgid, - header->msgid, + "service %d slot_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)", + port, count, header, + msgid, header->msgid, header->size); WARN(1, "bad slot use count\n"); } @@ -715,10 +699,9 @@ process_free_queue(VCHIQ_STATE_T *state) pos += calc_stride(header->size); if (pos > VCHIQ_SLOT_SIZE) { vchiq_log_error(vchiq_core_log_level, - "pfq - pos %x: header %x, msgid %x, " - "header->msgid %x, header->size %x", - pos, (unsigned int)header, msgid, - header->msgid, header->size); + "pfq - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x", + pos, header, msgid, header->msgid, + header->size); WARN(1, "invalid slot position\n"); } } @@ -862,11 +845,9 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int slot_use_count; vchiq_log_info(vchiq_core_log_level, - "%d: qm %s@%x,%x (%d->%d)", - state->id, - msg_type_str(VCHIQ_MSG_TYPE(msgid)), - (unsigned int)header, size, - VCHIQ_MSG_SRCPORT(msgid), + "%d: qm %s@%pK,%x (%d->%d)", + state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), + header, size, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); BUG_ON(!service); @@ -930,10 +911,9 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); } else { vchiq_log_info(vchiq_core_log_level, - "%d: qm %s@%x,%x (%d->%d)", state->id, + "%d: qm %s@%pK,%x (%d->%d)", state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), - (unsigned int)header, size, - VCHIQ_MSG_SRCPORT(msgid), + header, size, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); if (size != 0) { WARN_ON(!((count == 1) && (size == elements[0].size))); @@ -1015,10 +995,9 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int i, pos; vchiq_log_info(vchiq_sync_log_level, - "%d: qms %s@%x,%x (%d->%d)", state->id, + "%d: qms %s@%pK,%x (%d->%d)", state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), - (unsigned int)header, size, - VCHIQ_MSG_SRCPORT(msgid), + header, size, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); for (i = 0, pos = 0; i < (unsigned int)count; @@ -1047,10 +1026,9 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); } else { vchiq_log_info(vchiq_sync_log_level, - "%d: qms %s@%x,%x (%d->%d)", state->id, + "%d: qms %s@%pK,%x (%d->%d)", state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), - (unsigned int)header, size, - VCHIQ_MSG_SRCPORT(msgid), + header, size, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); if (size != 0) { WARN_ON(!((count == 1) && (size == elements[0].size))); @@ -1350,26 +1328,22 @@ resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) "Send Bulk to" : "Recv Bulk from"; if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) vchiq_log_info(SRVTRACE_LEVEL(service), - "%s %c%c%c%c d:%d len:%d %x<->%x", + "%s %c%c%c%c d:%d len:%d %pK<->%pK", header, VCHIQ_FOURCC_AS_4CHARS( service->base.fourcc), - service->remoteport, - bulk->size, - (unsigned int)bulk->data, - (unsigned int)bulk->remote_data); + service->remoteport, bulk->size, + bulk->data, bulk->remote_data); else vchiq_log_info(SRVTRACE_LEVEL(service), "%s %c%c%c%c d:%d ABORTED - tx len:%d," - " rx len:%d %x<->%x", + " rx len:%d %pK<->%pK", header, VCHIQ_FOURCC_AS_4CHARS( service->base.fourcc), service->remoteport, - bulk->size, - bulk->remote_size, - (unsigned int)bulk->data, - (unsigned int)bulk->remote_data); + bulk->size, bulk->remote_size, + bulk->data, bulk->remote_data); } vchiq_complete_bulk(bulk); @@ -1505,9 +1479,8 @@ parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) fourcc = payload->fourcc; vchiq_log_info(vchiq_core_log_level, - "%d: prs OPEN@%x (%d->'%c%c%c%c')", - state->id, (unsigned int)header, - localport, + "%d: prs OPEN@%pK (%d->'%c%c%c%c')", + state->id, header, localport, VCHIQ_FOURCC_AS_4CHARS(fourcc)); service = get_listening_service(state, fourcc); @@ -1678,21 +1651,18 @@ parse_rx_slots(VCHIQ_STATE_T *state) remoteport); if (service) vchiq_log_warning(vchiq_core_log_level, - "%d: prs %s@%x (%d->%d) - " - "found connected service %d", + "%d: prs %s@%pK (%d->%d) - found connected service %d", state->id, msg_type_str(type), - (unsigned int)header, - remoteport, localport, + header, remoteport, localport, service->localport); } if (!service) { vchiq_log_error(vchiq_core_log_level, - "%d: prs %s@%x (%d->%d) - " - "invalid/closed service %d", + "%d: prs %s@%pK (%d->%d) - invalid/closed service %d", state->id, msg_type_str(type), - (unsigned int)header, - remoteport, localport, localport); + header, remoteport, localport, + localport); goto skip_message; } break; @@ -1720,9 +1690,8 @@ parse_rx_slots(VCHIQ_STATE_T *state) if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) > VCHIQ_SLOT_SIZE) { vchiq_log_error(vchiq_core_log_level, - "header %x (msgid %x) - size %x too big for " - "slot", - (unsigned int)header, (unsigned int)msgid, + "header %pK (msgid %x) - size %x too big for slot", + header, (unsigned int)msgid, (unsigned int)size); WARN(1, "oversized for slot\n"); } @@ -1741,9 +1710,9 @@ parse_rx_slots(VCHIQ_STATE_T *state) service->peer_version = payload->version; } vchiq_log_info(vchiq_core_log_level, - "%d: prs OPENACK@%x,%x (%d->%d) v:%d", - state->id, (unsigned int)header, size, - remoteport, localport, service->peer_version); + "%d: prs OPENACK@%pK,%x (%d->%d) v:%d", + state->id, header, size, remoteport, localport, + service->peer_version); if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { service->remoteport = remoteport; @@ -1759,9 +1728,8 @@ parse_rx_slots(VCHIQ_STATE_T *state) WARN_ON(size != 0); /* There should be no data */ vchiq_log_info(vchiq_core_log_level, - "%d: prs CLOSE@%x (%d->%d)", - state->id, (unsigned int)header, - remoteport, localport); + "%d: prs CLOSE@%pK (%d->%d)", + state->id, header, remoteport, localport); mark_service_closing_internal(service, 1); @@ -1777,9 +1745,8 @@ parse_rx_slots(VCHIQ_STATE_T *state) break; case VCHIQ_MSG_DATA: vchiq_log_info(vchiq_core_log_level, - "%d: prs DATA@%x,%x (%d->%d)", - state->id, (unsigned int)header, size, - remoteport, localport); + "%d: prs DATA@%pK,%x (%d->%d)", + state->id, header, size, remoteport, localport); if ((service->remoteport == remoteport) && (service->srvstate == @@ -1802,8 +1769,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) break; case VCHIQ_MSG_CONNECT: vchiq_log_info(vchiq_core_log_level, - "%d: prs CONNECT@%x", - state->id, (unsigned int)header); + "%d: prs CONNECT@%pK", state->id, header); state->version_common = ((VCHIQ_SLOT_ZERO_T *) state->slot_data)->version; up(&state->connect); @@ -1837,12 +1803,10 @@ parse_rx_slots(VCHIQ_STATE_T *state) wmb(); vchiq_log_info(vchiq_core_log_level, - "%d: prs %s@%x (%d->%d) %x@%x", + "%d: prs %s@%pK (%d->%d) %x@%pK", state->id, msg_type_str(type), - (unsigned int)header, - remoteport, localport, - bulk->remote_size, - (unsigned int)bulk->remote_data); + header, remoteport, localport, + bulk->remote_size, bulk->remote_data); queue->remote_insert++; @@ -1895,11 +1859,10 @@ parse_rx_slots(VCHIQ_STATE_T *state) if ((int)(queue->remote_insert - queue->local_insert) >= 0) { vchiq_log_error(vchiq_core_log_level, - "%d: prs %s@%x (%d->%d) " + "%d: prs %s@%pK (%d->%d) " "unexpected (ri=%d,li=%d)", state->id, msg_type_str(type), - (unsigned int)header, - remoteport, localport, + header, remoteport, localport, queue->remote_insert, queue->local_insert); mutex_unlock(&service->bulk_mutex); @@ -1915,11 +1878,10 @@ parse_rx_slots(VCHIQ_STATE_T *state) queue->remote_insert++; vchiq_log_info(vchiq_core_log_level, - "%d: prs %s@%x (%d->%d) %x@%x", + "%d: prs %s@%pK (%d->%d) %x@%pK", state->id, msg_type_str(type), - (unsigned int)header, - remoteport, localport, - bulk->actual, (unsigned int)bulk->data); + header, remoteport, localport, + bulk->actual, bulk->data); vchiq_log_trace(vchiq_core_log_level, "%d: prs:%d %cx li=%x ri=%x p=%x", @@ -1941,14 +1903,14 @@ parse_rx_slots(VCHIQ_STATE_T *state) break; case VCHIQ_MSG_PADDING: vchiq_log_trace(vchiq_core_log_level, - "%d: prs PADDING@%x,%x", - state->id, (unsigned int)header, size); + "%d: prs PADDING@%pK,%x", + state->id, header, size); break; case VCHIQ_MSG_PAUSE: /* If initiated, signal the application thread */ vchiq_log_trace(vchiq_core_log_level, - "%d: prs PAUSE@%x,%x", - state->id, (unsigned int)header, size); + "%d: prs PAUSE@%pK,%x", + state->id, header, size); if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { vchiq_log_error(vchiq_core_log_level, "%d: PAUSE received in state PAUSED", @@ -1971,8 +1933,8 @@ parse_rx_slots(VCHIQ_STATE_T *state) break; case VCHIQ_MSG_RESUME: vchiq_log_trace(vchiq_core_log_level, - "%d: prs RESUME@%x,%x", - state->id, (unsigned int)header, size); + "%d: prs RESUME@%pK,%x", + state->id, header, size); /* Release the slot mutex */ mutex_unlock(&state->slot_mutex); if (state->is_master) @@ -1993,8 +1955,8 @@ parse_rx_slots(VCHIQ_STATE_T *state) default: vchiq_log_error(vchiq_core_log_level, - "%d: prs invalid msgid %x@%x,%x", - state->id, msgid, (unsigned int)header, size); + "%d: prs invalid msgid %x@%pK,%x", + state->id, msgid, header, size); WARN(1, "invalid message\n"); break; } @@ -2159,11 +2121,9 @@ sync_func(void *v) if (!service) { vchiq_log_error(vchiq_sync_log_level, - "%d: sf %s@%x (%d->%d) - " - "invalid/closed service %d", + "%d: sf %s@%pK (%d->%d) - invalid/closed service %d", state->id, msg_type_str(type), - (unsigned int)header, - remoteport, localport, localport); + header, remoteport, localport, localport); release_message_sync(state, header); continue; } @@ -2193,9 +2153,9 @@ sync_func(void *v) service->peer_version = payload->version; } vchiq_log_info(vchiq_sync_log_level, - "%d: sf OPENACK@%x,%x (%d->%d) v:%d", - state->id, (unsigned int)header, size, - remoteport, localport, service->peer_version); + "%d: sf OPENACK@%pK,%x (%d->%d) v:%d", + state->id, header, size, remoteport, localport, + service->peer_version); if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { service->remoteport = remoteport; vchiq_set_service_state(service, @@ -2208,9 +2168,8 @@ sync_func(void *v) case VCHIQ_MSG_DATA: vchiq_log_trace(vchiq_sync_log_level, - "%d: sf DATA@%x,%x (%d->%d)", - state->id, (unsigned int)header, size, - remoteport, localport); + "%d: sf DATA@%pK,%x (%d->%d)", + state->id, header, size, remoteport, localport); if ((service->remoteport == remoteport) && (service->srvstate == @@ -2228,8 +2187,8 @@ sync_func(void *v) default: vchiq_log_error(vchiq_sync_log_level, - "%d: sf unexpected msgid %x@%x,%x", - state->id, msgid, (unsigned int)header, size); + "%d: sf unexpected msgid %x@%pK,%x", + state->id, msgid, header, size); release_message_sync(state, header); break; } @@ -2310,16 +2269,16 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, int i; vchiq_log_warning(vchiq_core_log_level, - "%s: slot_zero = 0x%08lx, is_master = %d", - __func__, (unsigned long)slot_zero, is_master); + "%s: slot_zero = %pK, is_master = %d", + __func__, slot_zero, is_master); /* Check the input configuration */ if (slot_zero->magic != VCHIQ_MAGIC) { vchiq_loud_error_header(); vchiq_loud_error("Invalid VCHIQ magic value found."); - vchiq_loud_error("slot_zero=%x: magic=%x (expected %x)", - (unsigned int)slot_zero, slot_zero->magic, VCHIQ_MAGIC); + vchiq_loud_error("slot_zero=%pK: magic=%x (expected %x)", + slot_zero, slot_zero->magic, VCHIQ_MAGIC); vchiq_loud_error_footer(); return VCHIQ_ERROR; } @@ -2327,10 +2286,8 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, if (slot_zero->version < VCHIQ_VERSION_MIN) { vchiq_loud_error_header(); vchiq_loud_error("Incompatible VCHIQ versions found."); - vchiq_loud_error("slot_zero=%x: VideoCore version=%d " - "(minimum %d)", - (unsigned int)slot_zero, slot_zero->version, - VCHIQ_VERSION_MIN); + vchiq_loud_error("slot_zero=%pK: VideoCore version=%d (minimum %d)", + slot_zero, slot_zero->version, VCHIQ_VERSION_MIN); vchiq_loud_error("Restart with a newer VideoCore image."); vchiq_loud_error_footer(); return VCHIQ_ERROR; @@ -2339,10 +2296,8 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, if (VCHIQ_VERSION < slot_zero->version_min) { vchiq_loud_error_header(); vchiq_loud_error("Incompatible VCHIQ versions found."); - vchiq_loud_error("slot_zero=%x: version=%d (VideoCore " - "minimum %d)", - (unsigned int)slot_zero, VCHIQ_VERSION, - slot_zero->version_min); + vchiq_loud_error("slot_zero=%pK: version=%d (VideoCore minimum %d)", + slot_zero, VCHIQ_VERSION, slot_zero->version_min); vchiq_loud_error("Restart with a newer kernel."); vchiq_loud_error_footer(); return VCHIQ_ERROR; @@ -2354,26 +2309,20 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)) { vchiq_loud_error_header(); if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) - vchiq_loud_error("slot_zero=%x: slot_zero_size=%x " - "(expected %x)", - (unsigned int)slot_zero, - slot_zero->slot_zero_size, - sizeof(VCHIQ_SLOT_ZERO_T)); + vchiq_loud_error("slot_zero=%pK: slot_zero_size=%d (expected %d)", + slot_zero, slot_zero->slot_zero_size, + (int)sizeof(VCHIQ_SLOT_ZERO_T)); if (slot_zero->slot_size != VCHIQ_SLOT_SIZE) - vchiq_loud_error("slot_zero=%x: slot_size=%d " - "(expected %d", - (unsigned int)slot_zero, slot_zero->slot_size, + vchiq_loud_error("slot_zero=%pK: slot_size=%d (expected %d)", + slot_zero, slot_zero->slot_size, VCHIQ_SLOT_SIZE); if (slot_zero->max_slots != VCHIQ_MAX_SLOTS) - vchiq_loud_error("slot_zero=%x: max_slots=%d " - "(expected %d)", - (unsigned int)slot_zero, slot_zero->max_slots, + vchiq_loud_error("slot_zero=%pK: max_slots=%d (expected %d)", + slot_zero, slot_zero->max_slots, VCHIQ_MAX_SLOTS); if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE) - vchiq_loud_error("slot_zero=%x: max_slots_per_side=%d " - "(expected %d)", - (unsigned int)slot_zero, - slot_zero->max_slots_per_side, + vchiq_loud_error("slot_zero=%pK: max_slots_per_side=%d (expected %d)", + slot_zero, slot_zero->max_slots_per_side, VCHIQ_MAX_SLOTS_PER_SIDE); vchiq_loud_error_footer(); return VCHIQ_ERROR; @@ -2750,20 +2699,16 @@ release_service_messages(VCHIQ_SERVICE_T *service) if ((port == service->localport) && (msgid & VCHIQ_MSGID_CLAIMED)) { vchiq_log_info(vchiq_core_log_level, - " fsi - hdr %x", - (unsigned int)header); + " fsi - hdr %pK", header); release_slot(state, slot_info, header, NULL); } pos += calc_stride(header->size); if (pos > VCHIQ_SLOT_SIZE) { vchiq_log_error(vchiq_core_log_level, - "fsi - pos %x: header %x, " - "msgid %x, header->msgid %x, " - "header->size %x", - pos, (unsigned int)header, - msgid, header->msgid, - header->size); + "fsi - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x", + pos, header, msgid, + header->msgid, header->size); WARN(1, "invalid slot position\n"); } } @@ -3335,10 +3280,9 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, wmb(); vchiq_log_info(vchiq_core_log_level, - "%d: bt (%d->%d) %cx %x@%x %x", - state->id, - service->localport, service->remoteport, dir_char, - size, (unsigned int)bulk->data, (unsigned int)userdata); + "%d: bt (%d->%d) %cx %x@%pK %pK", + state->id, service->localport, service->remoteport, dir_char, + size, bulk->data, userdata); /* The slot mutex must be held when the service is being closed, so claim it here to ensure that isn't happening */ @@ -3685,13 +3629,11 @@ vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state) vchiq_dump(dump_context, buf, len + 1); len = snprintf(buf, sizeof(buf), - " tx_pos=%x(@%x), rx_pos=%x(@%x)", + " tx_pos=%x(@%pK), rx_pos=%x(@%pK)", state->local->tx_pos, - (uint32_t)state->tx_data + - (state->local_tx_pos & VCHIQ_SLOT_MASK), + state->tx_data + (state->local_tx_pos & VCHIQ_SLOT_MASK), state->rx_pos, - (uint32_t)state->rx_data + - (state->rx_pos & VCHIQ_SLOT_MASK)); + state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK)); vchiq_dump(dump_context, buf, len + 1); len = snprintf(buf, sizeof(buf), diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c index 25e7011edc50..563642c8664f 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c @@ -155,9 +155,8 @@ VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) list); list_del(pos); vchiq_log_info(vchiq_arm_log_level, - "bulk_waiter - cleaned up %x " - "for pid %d", - (unsigned int)waiter, waiter->pid); + "bulk_waiter - cleaned up %pK for pid %d", + waiter, waiter->pid); kfree(waiter); } kfree(instance); @@ -450,8 +449,8 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, list_add(&waiter->list, &instance->bulk_waiter_list); mutex_unlock(&instance->bulk_waiter_list_mutex); vchiq_log_info(vchiq_arm_log_level, - "saved bulk_waiter %x for pid %d", - (unsigned int)waiter, current->pid); + "saved bulk_waiter %pK for pid %d", + waiter, current->pid); } return status; -- cgit v1.2.3 From 9f8e0562e36693a60a2fd76c7a64184661eaea23 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 7 Oct 2016 10:24:57 -0700 Subject: staging: fbtft: Convert int arrays to s16 These arrays use -1, -2, and -3 as initiators for various types of writes to initialize hardware. No values are used that conflict with using these arrays as s16 instead of int and reducing overall data is good. $ size drivers/staging/fbtft/built-in.o* text data bss dec hex filename 116120 32872 4152 153144 25638 drivers/staging/fbtft/built-in.o.new 116104 36344 6200 158648 26bb8 drivers/staging/fbtft/built-in.o.old Miscellaneous: o Realign some of the arrays to make reading a bit easier Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_ili9481.c | 2 +- drivers/staging/fbtft/fb_ili9486.c | 2 +- drivers/staging/fbtft/fb_s6d02a1.c | 2 +- drivers/staging/fbtft/fb_st7735r.c | 2 +- drivers/staging/fbtft/fbtft-core.c | 2 +- drivers/staging/fbtft/fbtft.h | 4 +- drivers/staging/fbtft/fbtft_device.c | 12 +- drivers/staging/fbtft/flexfb.c | 372 +++++++++++++++++++++++++++++------ 8 files changed, 323 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fbtft/fb_ili9481.c b/drivers/staging/fbtft/fb_ili9481.c index 242adb3859bd..4e75f5abe2f9 100644 --- a/drivers/staging/fbtft/fb_ili9481.c +++ b/drivers/staging/fbtft/fb_ili9481.c @@ -27,7 +27,7 @@ #define WIDTH 320 #define HEIGHT 480 -static int default_init_sequence[] = { +static s16 default_init_sequence[] = { /* SLP_OUT - Sleep out */ -1, MIPI_DCS_EXIT_SLEEP_MODE, -2, 50, diff --git a/drivers/staging/fbtft/fb_ili9486.c b/drivers/staging/fbtft/fb_ili9486.c index fa38d8885f0b..f4b314265f9e 100644 --- a/drivers/staging/fbtft/fb_ili9486.c +++ b/drivers/staging/fbtft/fb_ili9486.c @@ -26,7 +26,7 @@ #define HEIGHT 480 /* this init sequence matches PiScreen */ -static int default_init_sequence[] = { +static s16 default_init_sequence[] = { /* Interface Mode Control */ -1, 0xb0, 0x0, -1, MIPI_DCS_EXIT_SLEEP_MODE, diff --git a/drivers/staging/fbtft/fb_s6d02a1.c b/drivers/staging/fbtft/fb_s6d02a1.c index 774b0ff69e6d..eb712aa0d692 100644 --- a/drivers/staging/fbtft/fb_s6d02a1.c +++ b/drivers/staging/fbtft/fb_s6d02a1.c @@ -24,7 +24,7 @@ #define DRVNAME "fb_s6d02a1" -static int default_init_sequence[] = { +static s16 default_init_sequence[] = { -1, 0xf0, 0x5a, 0x5a, diff --git a/drivers/staging/fbtft/fb_st7735r.c b/drivers/staging/fbtft/fb_st7735r.c index 6670f2bb62ec..710b74bbba97 100644 --- a/drivers/staging/fbtft/fb_st7735r.c +++ b/drivers/staging/fbtft/fb_st7735r.c @@ -25,7 +25,7 @@ #define DEFAULT_GAMMA "0F 1A 0F 18 2F 28 20 22 1F 1B 23 37 00 07 02 10\n" \ "0F 1B 0F 17 33 2C 29 2E 30 30 39 3F 00 07 03 10" -static int default_init_sequence[] = { +static s16 default_init_sequence[] = { -1, MIPI_DCS_SOFT_RESET, -2, 150, /* delay */ diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 587f68aa466c..df4464fc4530 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -660,7 +660,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, unsigned int bpp = display->bpp; unsigned int fps = display->fps; int vmem_size, i; - int *init_sequence = display->init_sequence; + s16 *init_sequence = display->init_sequence; char *gamma = display->gamma; unsigned long *gamma_curves = NULL; diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h index 89c4b5b76ce6..aacdde92cc2e 100644 --- a/drivers/staging/fbtft/fbtft.h +++ b/drivers/staging/fbtft/fbtft.h @@ -124,7 +124,7 @@ struct fbtft_display { unsigned int bpp; unsigned int fps; int txbuflen; - int *init_sequence; + s16 *init_sequence; char *gamma; int gamma_num; int gamma_len; @@ -229,7 +229,7 @@ struct fbtft_par { int led[16]; int aux[16]; } gpio; - int *init_sequence; + s16 *init_sequence; struct { struct mutex lock; unsigned long *curves; diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c index e9211831b6a1..de46f8d988d2 100644 --- a/drivers/staging/fbtft/fbtft_device.c +++ b/drivers/staging/fbtft/fbtft_device.c @@ -96,9 +96,9 @@ static unsigned int buswidth = 8; module_param(buswidth, uint, 0); MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument"); -static int init[FBTFT_MAX_INIT_SEQUENCE]; +static s16 init[FBTFT_MAX_INIT_SEQUENCE]; static int init_num; -module_param_array(init, int, &init_num, 0); +module_param_array(init, short, &init_num, 0); MODULE_PARM_DESC(init, "Init sequence, used with the custom argument"); static unsigned long debug; @@ -131,7 +131,7 @@ static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par, "D0 00 14 15 13 2C 42 43 4E 09 16 14 18 21\n" \ "D0 00 14 15 13 0B 43 55 53 0C 17 14 23 20" -static int cberry28_init_sequence[] = { +static s16 cberry28_init_sequence[] = { /* turn off sleep mode */ -1, MIPI_DCS_EXIT_SLEEP_MODE, -2, 120, @@ -180,7 +180,7 @@ static int cberry28_init_sequence[] = { -3, }; -static int hy28b_init_sequence[] = { +static s16 hy28b_init_sequence[] = { -1, 0x00e7, 0x0010, -1, 0x0000, 0x0001, -1, 0x0001, 0x0100, -1, 0x0002, 0x0700, -1, 0x0003, 0x1030, -1, 0x0004, 0x0000, @@ -211,7 +211,7 @@ static int hy28b_init_sequence[] = { "04 1F 4 7 7 0 7 7 6 0\n" \ "0F 00 1 7 4 0 0 0 6 7" -static int pitft_init_sequence[] = { +static s16 pitft_init_sequence[] = { -1, MIPI_DCS_SOFT_RESET, -2, 5, -1, MIPI_DCS_SET_DISPLAY_OFF, @@ -242,7 +242,7 @@ static int pitft_init_sequence[] = { -3 }; -static int waveshare32b_init_sequence[] = { +static s16 waveshare32b_init_sequence[] = { -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02, -1, 0xCF, 0x00, 0xC1, 0x30, -1, 0xE8, 0x85, 0x00, 0x78, diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c index ce0d254148e4..2dc5f9b6b47e 100644 --- a/drivers/staging/fbtft/flexfb.c +++ b/drivers/staging/fbtft/flexfb.c @@ -38,9 +38,9 @@ static unsigned int height; module_param(height, uint, 0); MODULE_PARM_DESC(height, "Display height"); -static int init[512]; +static s16 init[512]; static int init_num; -module_param_array(init, int, &init_num, 0); +module_param_array(init, short, &init_num, 0); MODULE_PARM_DESC(init, "Init sequence"); static unsigned int setaddrwin; @@ -63,68 +63,316 @@ static bool latched; module_param(latched, bool, 0); MODULE_PARM_DESC(latched, "Use with latched 16-bit databus"); -static int *initp; +static s16 *initp; static int initp_num; /* default init sequences */ -static int st7735r_init[] = { --1, 0x01, -2, 150, -1, 0x11, -2, 500, -1, 0xB1, 0x01, 0x2C, 0x2D, -1, 0xB2, 0x01, 0x2C, 0x2D, -1, 0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, --1, 0xB4, 0x07, -1, 0xC0, 0xA2, 0x02, 0x84, -1, 0xC1, 0xC5, -1, 0xC2, 0x0A, 0x00, -1, 0xC3, 0x8A, 0x2A, -1, 0xC4, 0x8A, 0xEE, -1, 0xC5, 0x0E, --1, 0x20, -1, 0x36, 0xC0, -1, 0x3A, 0x05, -1, 0xE0, 0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10, --1, 0xE1, 0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30, 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10, -1, 0x29, -2, 100, -1, 0x13, -2, 10, -3 }; - -static int ssd1289_init[] = { --1, 0x00, 0x0001, -1, 0x03, 0xA8A4, -1, 0x0C, 0x0000, -1, 0x0D, 0x080C, -1, 0x0E, 0x2B00, -1, 0x1E, 0x00B7, -1, 0x01, 0x2B3F, -1, 0x02, 0x0600, --1, 0x10, 0x0000, -1, 0x11, 0x6070, -1, 0x05, 0x0000, -1, 0x06, 0x0000, -1, 0x16, 0xEF1C, -1, 0x17, 0x0003, -1, 0x07, 0x0233, -1, 0x0B, 0x0000, --1, 0x0F, 0x0000, -1, 0x41, 0x0000, -1, 0x42, 0x0000, -1, 0x48, 0x0000, -1, 0x49, 0x013F, -1, 0x4A, 0x0000, -1, 0x4B, 0x0000, -1, 0x44, 0xEF00, --1, 0x45, 0x0000, -1, 0x46, 0x013F, -1, 0x30, 0x0707, -1, 0x31, 0x0204, -1, 0x32, 0x0204, -1, 0x33, 0x0502, -1, 0x34, 0x0507, -1, 0x35, 0x0204, --1, 0x36, 0x0204, -1, 0x37, 0x0502, -1, 0x3A, 0x0302, -1, 0x3B, 0x0302, -1, 0x23, 0x0000, -1, 0x24, 0x0000, -1, 0x25, 0x8000, -1, 0x4f, 0x0000, --1, 0x4e, 0x0000, -1, 0x22, -3 }; - -static int hx8340bn_init[] = { --1, 0xC1, 0xFF, 0x83, 0x40, -1, 0x11, -2, 150, -1, 0xCA, 0x70, 0x00, 0xD9, -1, 0xB0, 0x01, 0x11, --1, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06, -2, 20, -1, 0xC2, 0x60, 0x71, 0x01, 0x0E, 0x05, 0x02, 0x09, 0x31, 0x0A, --1, 0xC3, 0x67, 0x30, 0x61, 0x17, 0x48, 0x07, 0x05, 0x33, -2, 10, -1, 0xB5, 0x35, 0x20, 0x45, -1, 0xB4, 0x33, 0x25, 0x4C, -2, 10, --1, 0x3A, 0x05, -1, 0x29, -2, 10, -3 }; - -static int ili9225_init[] = { --1, 0x0001, 0x011C, -1, 0x0002, 0x0100, -1, 0x0003, 0x1030, -1, 0x0008, 0x0808, -1, 0x000C, 0x0000, -1, 0x000F, 0x0A01, -1, 0x0020, 0x0000, --1, 0x0021, 0x0000, -2, 50, -1, 0x0010, 0x0A00, -1, 0x0011, 0x1038, -2, 50, -1, 0x0012, 0x1121, -1, 0x0013, 0x004E, -1, 0x0014, 0x676F, --1, 0x0030, 0x0000, -1, 0x0031, 0x00DB, -1, 0x0032, 0x0000, -1, 0x0033, 0x0000, -1, 0x0034, 0x00DB, -1, 0x0035, 0x0000, -1, 0x0036, 0x00AF, --1, 0x0037, 0x0000, -1, 0x0038, 0x00DB, -1, 0x0039, 0x0000, -1, 0x0050, 0x0000, -1, 0x0051, 0x060A, -1, 0x0052, 0x0D0A, -1, 0x0053, 0x0303, --1, 0x0054, 0x0A0D, -1, 0x0055, 0x0A06, -1, 0x0056, 0x0000, -1, 0x0057, 0x0303, -1, 0x0058, 0x0000, -1, 0x0059, 0x0000, -2, 50, --1, 0x0007, 0x1017, -2, 50, -3 }; - -static int ili9320_init[] = { --1, 0x00E5, 0x8000, -1, 0x0000, 0x0001, -1, 0x0001, 0x0100, -1, 0x0002, 0x0700, -1, 0x0003, 0x1030, -1, 0x0004, 0x0000, -1, 0x0008, 0x0202, --1, 0x0009, 0x0000, -1, 0x000A, 0x0000, -1, 0x000C, 0x0000, -1, 0x000D, 0x0000, -1, 0x000F, 0x0000, -1, 0x0010, 0x0000, -1, 0x0011, 0x0007, --1, 0x0012, 0x0000, -1, 0x0013, 0x0000, -2, 200, -1, 0x0010, 0x17B0, -1, 0x0011, 0x0031, -2, 50, -1, 0x0012, 0x0138, -2, 50, -1, 0x0013, 0x1800, --1, 0x0029, 0x0008, -2, 50, -1, 0x0020, 0x0000, -1, 0x0021, 0x0000, -1, 0x0030, 0x0000, -1, 0x0031, 0x0505, -1, 0x0032, 0x0004, --1, 0x0035, 0x0006, -1, 0x0036, 0x0707, -1, 0x0037, 0x0105, -1, 0x0038, 0x0002, -1, 0x0039, 0x0707, -1, 0x003C, 0x0704, -1, 0x003D, 0x0807, --1, 0x0050, 0x0000, -1, 0x0051, 0x00EF, -1, 0x0052, 0x0000, -1, 0x0053, 0x013F, -1, 0x0060, 0x2700, -1, 0x0061, 0x0001, -1, 0x006A, 0x0000, --1, 0x0080, 0x0000, -1, 0x0081, 0x0000, -1, 0x0082, 0x0000, -1, 0x0083, 0x0000, -1, 0x0084, 0x0000, -1, 0x0085, 0x0000, -1, 0x0090, 0x0010, --1, 0x0092, 0x0000, -1, 0x0093, 0x0003, -1, 0x0095, 0x0110, -1, 0x0097, 0x0000, -1, 0x0098, 0x0000, -1, 0x0007, 0x0173, -3 }; - -static int ili9325_init[] = { --1, 0x00E3, 0x3008, -1, 0x00E7, 0x0012, -1, 0x00EF, 0x1231, -1, 0x0001, 0x0100, -1, 0x0002, 0x0700, -1, 0x0003, 0x1030, -1, 0x0004, 0x0000, --1, 0x0008, 0x0207, -1, 0x0009, 0x0000, -1, 0x000A, 0x0000, -1, 0x000C, 0x0000, -1, 0x000D, 0x0000, -1, 0x000F, 0x0000, -1, 0x0010, 0x0000, --1, 0x0011, 0x0007, -1, 0x0012, 0x0000, -1, 0x0013, 0x0000, -2, 200, -1, 0x0010, 0x1690, -1, 0x0011, 0x0223, -2, 50, -1, 0x0012, 0x000D, -2, 50, --1, 0x0013, 0x1200, -1, 0x0029, 0x000A, -1, 0x002B, 0x000C, -2, 50, -1, 0x0020, 0x0000, -1, 0x0021, 0x0000, -1, 0x0030, 0x0000, --1, 0x0031, 0x0506, -1, 0x0032, 0x0104, -1, 0x0035, 0x0207, -1, 0x0036, 0x000F, -1, 0x0037, 0x0306, -1, 0x0038, 0x0102, -1, 0x0039, 0x0707, --1, 0x003C, 0x0702, -1, 0x003D, 0x1604, -1, 0x0050, 0x0000, -1, 0x0051, 0x00EF, -1, 0x0052, 0x0000, -1, 0x0053, 0x013F, -1, 0x0060, 0xA700, --1, 0x0061, 0x0001, -1, 0x006A, 0x0000, -1, 0x0080, 0x0000, -1, 0x0081, 0x0000, -1, 0x0082, 0x0000, -1, 0x0083, 0x0000, -1, 0x0084, 0x0000, --1, 0x0085, 0x0000, -1, 0x0090, 0x0010, -1, 0x0092, 0x0600, -1, 0x0007, 0x0133, -3 }; - -static int ili9341_init[] = { --1, 0x28, -2, 20, -1, 0xCF, 0x00, 0x83, 0x30, -1, 0xED, 0x64, 0x03, 0x12, 0x81, -1, 0xE8, 0x85, 0x01, 0x79, --1, 0xCB, 0x39, 0x2c, 0x00, 0x34, 0x02, -1, 0xF7, 0x20, -1, 0xEA, 0x00, 0x00, -1, 0xC0, 0x26, -1, 0xC1, 0x11, --1, 0xC5, 0x35, 0x3E, -1, 0xC7, 0xBE, -1, 0xB1, 0x00, 0x1B, -1, 0xB6, 0x0a, 0x82, 0x27, 0x00, -1, 0xB7, 0x07, --1, 0x3A, 0x55, -1, 0x36, 0x48, -1, 0x11, -2, 120, -1, 0x29, -2, 20, -3 }; - -static int ssd1351_init[] = { -1, 0xfd, 0x12, -1, 0xfd, 0xb1, -1, 0xae, -1, 0xb3, 0xf1, -1, 0xca, 0x7f, -1, 0xa0, 0x74, - -1, 0x15, 0x00, 0x7f, -1, 0x75, 0x00, 0x7f, -1, 0xa1, 0x00, -1, 0xa2, 0x00, -1, 0xb5, 0x00, - -1, 0xab, 0x01, -1, 0xb1, 0x32, -1, 0xb4, 0xa0, 0xb5, 0x55, -1, 0xbb, 0x17, -1, 0xbe, 0x05, - -1, 0xc1, 0xc8, 0x80, 0xc8, -1, 0xc7, 0x0f, -1, 0xb6, 0x01, -1, 0xa6, -1, 0xaf, -3 }; +static s16 st7735r_init[] = { + -1, 0x01, + -2, 150, + -1, 0x11, + -2, 500, + -1, 0xB1, 0x01, 0x2C, 0x2D, + -1, 0xB2, 0x01, 0x2C, 0x2D, + -1, 0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, + -1, 0xB4, 0x07, + -1, 0xC0, 0xA2, 0x02, 0x84, + -1, 0xC1, 0xC5, + -1, 0xC2, 0x0A, 0x00, + -1, 0xC3, 0x8A, 0x2A, + -1, 0xC4, 0x8A, 0xEE, + -1, 0xC5, 0x0E, + -1, 0x20, + -1, 0x36, 0xC0, + -1, 0x3A, 0x05, + -1, 0xE0, 0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, + 0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10, + -1, 0xE1, 0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, + 0x30, 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10, + -1, 0x29, + -2, 100, + -1, 0x13, + -2, 10, + -3 +}; + +static s16 ssd1289_init[] = { + -1, 0x00, 0x0001, + -1, 0x03, 0xA8A4, + -1, 0x0C, 0x0000, + -1, 0x0D, 0x080C, + -1, 0x0E, 0x2B00, + -1, 0x1E, 0x00B7, + -1, 0x01, 0x2B3F, + -1, 0x02, 0x0600, + -1, 0x10, 0x0000, + -1, 0x11, 0x6070, + -1, 0x05, 0x0000, + -1, 0x06, 0x0000, + -1, 0x16, 0xEF1C, + -1, 0x17, 0x0003, + -1, 0x07, 0x0233, + -1, 0x0B, 0x0000, + -1, 0x0F, 0x0000, + -1, 0x41, 0x0000, + -1, 0x42, 0x0000, + -1, 0x48, 0x0000, + -1, 0x49, 0x013F, + -1, 0x4A, 0x0000, + -1, 0x4B, 0x0000, + -1, 0x44, 0xEF00, + -1, 0x45, 0x0000, + -1, 0x46, 0x013F, + -1, 0x30, 0x0707, + -1, 0x31, 0x0204, + -1, 0x32, 0x0204, + -1, 0x33, 0x0502, + -1, 0x34, 0x0507, + -1, 0x35, 0x0204, + -1, 0x36, 0x0204, + -1, 0x37, 0x0502, + -1, 0x3A, 0x0302, + -1, 0x3B, 0x0302, + -1, 0x23, 0x0000, + -1, 0x24, 0x0000, + -1, 0x25, 0x8000, + -1, 0x4f, 0x0000, + -1, 0x4e, 0x0000, + -1, 0x22, + -3 +}; + +static s16 hx8340bn_init[] = { + -1, 0xC1, 0xFF, 0x83, 0x40, + -1, 0x11, + -2, 150, + -1, 0xCA, 0x70, 0x00, 0xD9, + -1, 0xB0, 0x01, 0x11, + -1, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06, + -2, 20, + -1, 0xC2, 0x60, 0x71, 0x01, 0x0E, 0x05, 0x02, 0x09, 0x31, 0x0A, + -1, 0xC3, 0x67, 0x30, 0x61, 0x17, 0x48, 0x07, 0x05, 0x33, + -2, 10, + -1, 0xB5, 0x35, 0x20, 0x45, + -1, 0xB4, 0x33, 0x25, 0x4C, + -2, 10, + -1, 0x3A, 0x05, + -1, 0x29, + -2, 10, + -3 +}; + +static s16 ili9225_init[] = { + -1, 0x0001, 0x011C, + -1, 0x0002, 0x0100, + -1, 0x0003, 0x1030, + -1, 0x0008, 0x0808, + -1, 0x000C, 0x0000, + -1, 0x000F, 0x0A01, + -1, 0x0020, 0x0000, + -1, 0x0021, 0x0000, + -2, 50, + -1, 0x0010, 0x0A00, + -1, 0x0011, 0x1038, + -2, 50, + -1, 0x0012, 0x1121, + -1, 0x0013, 0x004E, + -1, 0x0014, 0x676F, + -1, 0x0030, 0x0000, + -1, 0x0031, 0x00DB, + -1, 0x0032, 0x0000, + -1, 0x0033, 0x0000, + -1, 0x0034, 0x00DB, + -1, 0x0035, 0x0000, + -1, 0x0036, 0x00AF, + -1, 0x0037, 0x0000, + -1, 0x0038, 0x00DB, + -1, 0x0039, 0x0000, + -1, 0x0050, 0x0000, + -1, 0x0051, 0x060A, + -1, 0x0052, 0x0D0A, + -1, 0x0053, 0x0303, + -1, 0x0054, 0x0A0D, + -1, 0x0055, 0x0A06, + -1, 0x0056, 0x0000, + -1, 0x0057, 0x0303, + -1, 0x0058, 0x0000, + -1, 0x0059, 0x0000, + -2, 50, + -1, 0x0007, 0x1017, + -2, 50, + -3 +}; + +static s16 ili9320_init[] = { + -1, 0x00E5, 0x8000, + -1, 0x0000, 0x0001, + -1, 0x0001, 0x0100, + -1, 0x0002, 0x0700, + -1, 0x0003, 0x1030, + -1, 0x0004, 0x0000, + -1, 0x0008, 0x0202, + -1, 0x0009, 0x0000, + -1, 0x000A, 0x0000, + -1, 0x000C, 0x0000, + -1, 0x000D, 0x0000, + -1, 0x000F, 0x0000, + -1, 0x0010, 0x0000, + -1, 0x0011, 0x0007, + -1, 0x0012, 0x0000, + -1, 0x0013, 0x0000, + -2, 200, + -1, 0x0010, 0x17B0, + -1, 0x0011, 0x0031, + -2, 50, + -1, 0x0012, 0x0138, + -2, 50, + -1, 0x0013, 0x1800, + -1, 0x0029, 0x0008, + -2, 50, + -1, 0x0020, 0x0000, + -1, 0x0021, 0x0000, + -1, 0x0030, 0x0000, + -1, 0x0031, 0x0505, + -1, 0x0032, 0x0004, + -1, 0x0035, 0x0006, + -1, 0x0036, 0x0707, + -1, 0x0037, 0x0105, + -1, 0x0038, 0x0002, + -1, 0x0039, 0x0707, + -1, 0x003C, 0x0704, + -1, 0x003D, 0x0807, + -1, 0x0050, 0x0000, + -1, 0x0051, 0x00EF, + -1, 0x0052, 0x0000, + -1, 0x0053, 0x013F, + -1, 0x0060, 0x2700, + -1, 0x0061, 0x0001, + -1, 0x006A, 0x0000, + -1, 0x0080, 0x0000, + -1, 0x0081, 0x0000, + -1, 0x0082, 0x0000, + -1, 0x0083, 0x0000, + -1, 0x0084, 0x0000, + -1, 0x0085, 0x0000, + -1, 0x0090, 0x0010, + -1, 0x0092, 0x0000, + -1, 0x0093, 0x0003, + -1, 0x0095, 0x0110, + -1, 0x0097, 0x0000, + -1, 0x0098, 0x0000, + -1, 0x0007, 0x0173, + -3 +}; + +static s16 ili9325_init[] = { + -1, 0x00E3, 0x3008, + -1, 0x00E7, 0x0012, + -1, 0x00EF, 0x1231, + -1, 0x0001, 0x0100, + -1, 0x0002, 0x0700, + -1, 0x0003, 0x1030, + -1, 0x0004, 0x0000, + -1, 0x0008, 0x0207, + -1, 0x0009, 0x0000, + -1, 0x000A, 0x0000, + -1, 0x000C, 0x0000, + -1, 0x000D, 0x0000, + -1, 0x000F, 0x0000, + -1, 0x0010, 0x0000, + -1, 0x0011, 0x0007, + -1, 0x0012, 0x0000, + -1, 0x0013, 0x0000, + -2, 200, + -1, 0x0010, 0x1690, + -1, 0x0011, 0x0223, + -2, 50, + -1, 0x0012, 0x000D, + -2, 50, + -1, 0x0013, 0x1200, + -1, 0x0029, 0x000A, + -1, 0x002B, 0x000C, + -2, 50, + -1, 0x0020, 0x0000, + -1, 0x0021, 0x0000, + -1, 0x0030, 0x0000, + -1, 0x0031, 0x0506, + -1, 0x0032, 0x0104, + -1, 0x0035, 0x0207, + -1, 0x0036, 0x000F, + -1, 0x0037, 0x0306, + -1, 0x0038, 0x0102, + -1, 0x0039, 0x0707, + -1, 0x003C, 0x0702, + -1, 0x003D, 0x1604, + -1, 0x0050, 0x0000, + -1, 0x0051, 0x00EF, + -1, 0x0052, 0x0000, + -1, 0x0053, 0x013F, + -1, 0x0060, 0xA700, + -1, 0x0061, 0x0001, + -1, 0x006A, 0x0000, + -1, 0x0080, 0x0000, + -1, 0x0081, 0x0000, + -1, 0x0082, 0x0000, + -1, 0x0083, 0x0000, + -1, 0x0084, 0x0000, + -1, 0x0085, 0x0000, + -1, 0x0090, 0x0010, + -1, 0x0092, 0x0600, + -1, 0x0007, 0x0133, + -3 +}; + +static s16 ili9341_init[] = { + -1, 0x28, + -2, 20, + -1, 0xCF, 0x00, 0x83, 0x30, + -1, 0xED, 0x64, 0x03, 0x12, 0x81, + -1, 0xE8, 0x85, 0x01, 0x79, + -1, 0xCB, 0x39, 0x2c, 0x00, 0x34, 0x02, + -1, 0xF7, 0x20, + -1, 0xEA, 0x00, 0x00, + -1, 0xC0, 0x26, + -1, 0xC1, 0x11, + -1, 0xC5, 0x35, 0x3E, + -1, 0xC7, 0xBE, + -1, 0xB1, 0x00, 0x1B, + -1, 0xB6, 0x0a, 0x82, 0x27, 0x00, + -1, 0xB7, 0x07, + -1, 0x3A, 0x55, + -1, 0x36, 0x48, + -1, 0x11, + -2, 120, + -1, 0x29, + -2, 20, + -3 +}; + +static s16 ssd1351_init[] = { + -1, 0xfd, 0x12, + -1, 0xfd, 0xb1, + -1, 0xae, + -1, 0xb3, 0xf1, + -1, 0xca, 0x7f, + -1, 0xa0, 0x74, + -1, 0x15, 0x00, 0x7f, + -1, 0x75, 0x00, 0x7f, + -1, 0xa1, 0x00, + -1, 0xa2, 0x00, + -1, 0xb5, 0x00, + -1, 0xab, 0x01, + -1, 0xb1, 0x32, + -1, 0xb4, 0xa0, 0xb5, 0x55, + -1, 0xbb, 0x17, + -1, 0xbe, 0x05, + -1, 0xc1, 0xc8, 0x80, 0xc8, + -1, 0xc7, 0x0f, + -1, 0xb6, 0x01, + -1, 0xa6, + -1, 0xaf, + -3 +}; /** * struct flexfb_lcd_controller - Describes the LCD controller properties @@ -142,7 +390,7 @@ struct flexfb_lcd_controller { unsigned int height; unsigned int setaddrwin; unsigned int regwidth; - int *init_seq; + s16 *init_seq; int init_seq_sz; }; -- cgit v1.2.3 From 5cf793714e6f5b345b6799ad4d6df5e049335672 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Oct 2016 01:40:01 -0700 Subject: Staging: fbtft: Fix too many leading tabs warning This is a patch to the fb_agm1264k-fl.c file that fixes up the following issue: WARNING: Too many leading tabs - consider code refactoring Add new function iterate_diffusion_matrix() to refactor a piece of code inside write_vmem(). Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_agm1264k-fl.c | 68 ++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c index 7561385761e9..a6e3af74a904 100644 --- a/drivers/staging/fbtft/fb_agm1264k-fl.c +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -264,6 +264,39 @@ construct_line_bitmap(struct fbtft_par *par, u8 *dest, signed short *src, } } +static void iterate_diffusion_matrix(u32 xres, u32 yres, int x, + int y, signed short *convert_buf, + signed short pixel, signed short error) +{ + u16 i, j; + + /* diffusion matrix row */ + for (i = 0; i < DIFFUSING_MATRIX_WIDTH; ++i) + /* diffusion matrix column */ + for (j = 0; j < DIFFUSING_MATRIX_HEIGHT; ++j) { + signed short *write_pos; + signed char coeff; + + /* skip pixels out of zone */ + if (x + i < 0 || x + i >= xres || y + j >= yres) + continue; + write_pos = &convert_buf[(y + j) * xres + x + i]; + coeff = diffusing_matrix[i][j]; + if (-1 == coeff) + /* pixel itself */ + *write_pos = pixel; + else { + signed short p = *write_pos + error * coeff; + + if (p > WHITE) + p = WHITE; + if (p < BLACK) + p = BLACK; + *write_pos = p; + } + } +} + static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) { u16 *vmem16 = (u16 *)par->info->screen_buffer; @@ -303,7 +336,6 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) signed short error_b = pixel - BLACK; signed short error_w = pixel - WHITE; signed short error; - u16 i, j; /* what color close? */ if (abs(error_b) >= abs(error_w)) { @@ -318,36 +350,10 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) error /= 8; - /* diffusion matrix row */ - for (i = 0; i < DIFFUSING_MATRIX_WIDTH; ++i) - /* diffusion matrix column */ - for (j = 0; j < DIFFUSING_MATRIX_HEIGHT; ++j) { - signed short *write_pos; - signed char coeff; - - /* skip pixels out of zone */ - if (x + i < 0 || - x + i >= par->info->var.xres - || y + j >= par->info->var.yres) - continue; - write_pos = &convert_buf[ - (y + j) * par->info->var.xres + - x + i]; - coeff = diffusing_matrix[i][j]; - if (coeff == -1) - /* pixel itself */ - *write_pos = pixel; - else { - signed short p = *write_pos + - error * coeff; - - if (p > WHITE) - p = WHITE; - if (p < BLACK) - p = BLACK; - *write_pos = p; - } - } + iterate_diffusion_matrix(par->info->var.xres, + par->info->var.yres, + x, y, convert_buf, + pixel, error); } /* 1 string = 2 pages */ -- cgit v1.2.3 From 5c53440daa050909e761ebcce8483b28fb163273 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Sat, 8 Oct 2016 15:37:29 -0600 Subject: staging: comedi: porting NI_GPCT constants from comedi.org module Information pertaining to the NI_GPCT_ARM* registers were added to the comedi.org version of the comedi kernel. This adds this information to the staging-tree version of the comedi kernel. Relevant comments are also copied over. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 08fb26b51a5f..a67ed578af5e 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -1104,18 +1104,19 @@ enum ni_gpct_other_select { enum ni_gpct_arm_source { NI_GPCT_ARM_IMMEDIATE = 0x0, /* - * Start both the counter and the adjacent pared - * counter simultaneously + * Start both the counter and the adjacent paired counter simultaneously */ NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* - * NI doesn't document bits for selecting hardware arm triggers. - * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least - * significant bits (3 bits for 660x or 5 bits for m-series) - * through to the hardware. This will at least allow someone to - * figure out what the bits do later. + * If the NI_GPCT_HW_ARM bit is set, we will pass the least significant + * bits (3 bits for 660x or 5 bits for m-series) through to the + * hardware. To select a hardware trigger, pass the appropriate select + * bit, e.g., + * NI_GPCT_HW_ARM | NI_GPCT_AI_START1_GATE_SELECT or + * NI_GPCT_HW_ARM | NI_GPCT_PFI_GATE_SELECT(pfi_number) */ - NI_GPCT_ARM_UNKNOWN = 0x1000, + NI_GPCT_HW_ARM = 0x1000, + NI_GPCT_ARM_UNKNOWN = NI_GPCT_HW_ARM, /* for backward compatibility */ }; /* digital filtering options for ni 660x for use with INSN_CONFIG_FILTER. */ -- cgit v1.2.3 From cc7a6d6c4614bbf65d57dac31706fb01377d8371 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Sat, 8 Oct 2016 15:38:43 -0600 Subject: staging: comedi: make constants slightly more consistent This makes INSN_CONFIG_DIO_{INPUT,OUTPUT,OPENDRAIN} simply be copies of the already-existing constants COMEDI_INPUT, COMEDI_OUTPUT, and COMEDI_OPENDRAIN. This change also ensures that if a user happens to use, for example, COMEDI_INPUT in place of where INSN_CONFIG_DIO_INPUT, the result will always be the same and also acceptable and correct usage. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index a67ed578af5e..a1c1081906c5 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -244,6 +244,22 @@ enum comedi_subdevice_type { /* configuration instructions */ +/** + * enum comedi_io_direction - COMEDI I/O directions + * @COMEDI_INPUT: Input. + * @COMEDI_OUTPUT: Output. + * @COMEDI_OPENDRAIN: Open-drain (or open-collector) output. + * + * These are used by the %INSN_CONFIG_DIO_QUERY configuration instruction to + * report a direction. They may also be used in other places where a direction + * needs to be specified. + */ +enum comedi_io_direction { + COMEDI_INPUT = 0, + COMEDI_OUTPUT = 1, + COMEDI_OPENDRAIN = 2 +}; + /** * enum configuration_ids - COMEDI configuration instruction codes * @INSN_CONFIG_DIO_INPUT: Configure digital I/O as input. @@ -296,9 +312,9 @@ enum comedi_subdevice_type { * @INSN_CONFIG_PWM_GET_H_BRIDGE: Get PWM H bridge duty cycle and polarity. */ enum configuration_ids { - INSN_CONFIG_DIO_INPUT = 0, - INSN_CONFIG_DIO_OUTPUT = 1, - INSN_CONFIG_DIO_OPENDRAIN = 2, + INSN_CONFIG_DIO_INPUT = COMEDI_INPUT, + INSN_CONFIG_DIO_OUTPUT = COMEDI_OUTPUT, + INSN_CONFIG_DIO_OPENDRAIN = COMEDI_OPENDRAIN, INSN_CONFIG_ANALOG_TRIG = 16, /* INSN_CONFIG_WAVEFORM = 17, */ /* INSN_CONFIG_TRIG = 18, */ @@ -396,22 +412,6 @@ enum comedi_digital_trig_op { COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = 2 }; -/** - * enum comedi_io_direction - COMEDI I/O directions - * @COMEDI_INPUT: Input. - * @COMEDI_OUTPUT: Output. - * @COMEDI_OPENDRAIN: Open-drain (or open-collector) output. - * - * These are used by the %INSN_CONFIG_DIO_QUERY configuration instruction to - * report a direction. They may also be used in other places where a direction - * needs to be specified. - */ -enum comedi_io_direction { - COMEDI_INPUT = 0, - COMEDI_OUTPUT = 1, - COMEDI_OPENDRAIN = 2 -}; - /** * enum comedi_support_level - support level for a COMEDI feature * @COMEDI_UNKNOWN_SUPPORT: Unspecified support for feature. -- cgit v1.2.3 From 1ffe8bdc09f8bfcaad76d71ae68b623c7e03f20f Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Mon, 10 Oct 2016 08:14:19 -0600 Subject: staging: comedi: ni_mio_common: split out ao arming from ni_ao_inttrig AO device arming was previously done as a part of ni_ao_inttrig which is called as a result of the user calling comedi_internal_trigger. For start_src == TRIG_EXT, this does not make very much sense since external triggers should not conceptually need to be software triggered also. This patch splits out the arming functionality to allow arming to specifically and separately be done via the CONFIG_INSN_ARM ioctl command. In order to provide backwards compatibility, this patch also provides automatic arming if ni_ao_inttrig is simply called. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 150 ++++++++++++++++--------- drivers/staging/comedi/drivers/ni_stc.h | 14 +++ 2 files changed, 112 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 0f97d7b611d7..9812508fe8d3 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2729,66 +2729,36 @@ static int ni_ao_insn_write(struct comedi_device *dev, return insn->n; } -static int ni_ao_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - const struct ni_board_struct *board = dev->board_ptr; - struct ni_private *devpriv = dev->private; - unsigned int nbytes; - - switch (data[0]) { - case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: - switch (data[1]) { - case COMEDI_OUTPUT: - nbytes = comedi_samples_to_bytes(s, - board->ao_fifo_depth); - data[2] = 1 + nbytes; - if (devpriv->mite) - data[2] += devpriv->mite->fifo_size; - break; - case COMEDI_INPUT: - data[2] = 0; - break; - default: - return -EINVAL; - } - return 0; - default: - break; - } - - return -EINVAL; -} - -static int ni_ao_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int trig_num) +/* + * Arms the AO device in preparation for a trigger event. + * This function also allocates and prepares a DMA channel (or FIFO if DMA is + * not used). As a part of this preparation, this function preloads the DAC + * registers with the first values of the output stream. This ensures that the + * first clock cycle after the trigger can be used for output. + * + * Note that this function _must_ happen after a user has written data to the + * output buffers via either mmap or write(fileno,...). + */ +static int ni_ao_arm(struct comedi_device *dev, + struct comedi_subdevice *s) { struct ni_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; int ret; int interrupt_b_bits; int i; static const int timeout = 1000; /* - * Require trig_num == cmd->start_arg when cmd->start_src == TRIG_INT. - * For backwards compatibility, also allow trig_num == 0 when - * cmd->start_src != TRIG_INT (i.e. when cmd->start_src == TRIG_EXT); - * in that case, the internal trigger is being used as a pre-trigger - * before the external trigger. + * Prevent ao from doing things like trying to allocate the ao dma + * channel multiple times. */ - if (!(trig_num == cmd->start_arg || - (trig_num == 0 && cmd->start_src != TRIG_INT))) + if (!devpriv->ao_needs_arming) { + dev_dbg(dev->class_dev, "%s: device does not need arming!\n", + __func__); return -EINVAL; + } - /* - * Null trig at beginning prevent ao start trigger from executing more - * than once per command (and doing things like trying to allocate the - * ao dma channel multiple times). - */ - s->async->inttrig = NULL; + devpriv->ao_needs_arming = 0; ni_set_bits(dev, NISTC_INTB_ENA_REG, NISTC_INTB_ENA_AO_FIFO | NISTC_INTB_ENA_AO_ERR, 0); @@ -2840,6 +2810,75 @@ static int ni_ao_inttrig(struct comedi_device *dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); + return 0; +} + +static int ni_ao_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + const struct ni_board_struct *board = dev->board_ptr; + struct ni_private *devpriv = dev->private; + unsigned int nbytes; + + switch (data[0]) { + case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: + switch (data[1]) { + case COMEDI_OUTPUT: + nbytes = comedi_samples_to_bytes(s, + board->ao_fifo_depth); + data[2] = 1 + nbytes; + if (devpriv->mite) + data[2] += devpriv->mite->fifo_size; + break; + case COMEDI_INPUT: + data[2] = 0; + break; + default: + return -EINVAL; + } + return 0; + case INSN_CONFIG_ARM: + return ni_ao_arm(dev, s); + default: + break; + } + + return -EINVAL; +} + +static int ni_ao_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) +{ + struct ni_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + int ret; + + /* + * Require trig_num == cmd->start_arg when cmd->start_src == TRIG_INT. + * For backwards compatibility, also allow trig_num == 0 when + * cmd->start_src != TRIG_INT (i.e. when cmd->start_src == TRIG_EXT); + * in that case, the internal trigger is being used as a pre-trigger + * before the external trigger. + */ + if (!(trig_num == cmd->start_arg || + (trig_num == 0 && cmd->start_src != TRIG_INT))) + return -EINVAL; + + /* + * Null trig at beginning prevent ao start trigger from executing more + * than once per command. + */ + s->async->inttrig = NULL; + + if (devpriv->ao_needs_arming) { + /* only arm this device if it still needs arming */ + ret = ni_ao_arm(dev, s); + if (ret) + return ret; + } + ni_stc_writew(dev, NISTC_AO_CMD2_START1_PULSE | devpriv->ao_cmd2, NISTC_AO_CMD2_REG); @@ -3227,10 +3266,17 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ni_ao_cmd_set_interrupts(dev, s); /* - * arm(ing) and star(ting) happen in ni_ao_inttrig, which _must_ be - * called for ao commands since 1) TRIG_NOW is not supported and 2) DMA - * must be setup and initially written to before arm/start happen. + * arm(ing) must happen later so that DMA can be setup and DACs + * preloaded with the actual output buffer before starting. + * + * start(ing) must happen _after_ arming is completed. Starting can be + * done either via ni_ao_inttrig, or via an external trigger. + * + * **Currently, ni_ao_inttrig will automatically attempt a call to + * ni_ao_arm if the device still needs arming at that point. This + * allows backwards compatibility. */ + devpriv->ao_needs_arming = 1; return 0; } diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h index 1966519cb6e5..f27b545f83eb 100644 --- a/drivers/staging/comedi/drivers/ni_stc.h +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -1053,6 +1053,20 @@ struct ni_private { unsigned int is_67xx:1; unsigned int is_6711:1; unsigned int is_6713:1; + + /* + * Boolean value of whether device needs to be armed. + * + * Currently, only NI AO devices are known to be needing arming, since + * the DAC registers must be preloaded before triggering. + * This variable should only be set true during a command operation + * (e.g ni_ao_cmd) and should then be set false by the arming + * function (e.g. ni_ao_arm). + * + * This variable helps to ensure that multiple DMA allocations are not + * possible. + */ + unsigned int ao_needs_arming:1; }; static const struct comedi_lrange range_ni_E_ao_ext; -- cgit v1.2.3 From efe9bc08bf479b1baacc63554042c5dd11fecd9e Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Tue, 11 Oct 2016 19:43:07 -0300 Subject: staging: sm750fb: Merge ddk750_help.* into ddk750_chip.*. The file ddk750_help.c contained only one function declaration, so it was merged into ddk750_chip.c to simplify the driver. Also, ddk750_help.h was merged into ddk750_chip.h to keep consistency. With these changes a few global variables are removed and the function ddk750_set_mmio is rewritten, so its purpose in the code is clearer. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/Makefile | 2 +- drivers/staging/sm750fb/ddk750.h | 1 - drivers/staging/sm750fb/ddk750_chip.c | 23 +++++++++++------------ drivers/staging/sm750fb/ddk750_chip.h | 10 +++++++++- drivers/staging/sm750fb/ddk750_display.c | 2 +- drivers/staging/sm750fb/ddk750_dvi.c | 2 +- drivers/staging/sm750fb/ddk750_help.c | 17 ----------------- drivers/staging/sm750fb/ddk750_help.h | 21 --------------------- drivers/staging/sm750fb/ddk750_hwi2c.c | 2 +- drivers/staging/sm750fb/ddk750_mode.c | 1 - drivers/staging/sm750fb/ddk750_power.c | 2 +- drivers/staging/sm750fb/ddk750_swi2c.c | 2 +- drivers/staging/sm750fb/sm750_hw.c | 5 ++++- 13 files changed, 30 insertions(+), 60 deletions(-) delete mode 100644 drivers/staging/sm750fb/ddk750_help.c delete mode 100644 drivers/staging/sm750fb/ddk750_help.h (limited to 'drivers') diff --git a/drivers/staging/sm750fb/Makefile b/drivers/staging/sm750fb/Makefile index dcce3f487ed5..4d781f78b95c 100644 --- a/drivers/staging/sm750fb/Makefile +++ b/drivers/staging/sm750fb/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_FB_SM750) += sm750fb.o sm750fb-objs := sm750.o sm750_hw.o sm750_accel.o sm750_cursor.o ddk750_chip.o ddk750_power.o ddk750_mode.o -sm750fb-objs += ddk750_display.o ddk750_help.o ddk750_swi2c.o ddk750_sii164.o ddk750_dvi.o ddk750_hwi2c.o +sm750fb-objs += ddk750_display.o ddk750_swi2c.o ddk750_sii164.o ddk750_dvi.o ddk750_hwi2c.o diff --git a/drivers/staging/sm750fb/ddk750.h b/drivers/staging/sm750fb/ddk750.h index 2c10a08ed964..05669114c4b1 100644 --- a/drivers/staging/sm750fb/ddk750.h +++ b/drivers/staging/sm750fb/ddk750.h @@ -16,7 +16,6 @@ #include "ddk750_chip.h" #include "ddk750_display.h" #include "ddk750_power.h" -#include "ddk750_help.h" #ifdef USE_HW_I2C #include "ddk750_hwi2c.h" #endif diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index c62ebc159236..2b231c28af16 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -1,33 +1,32 @@ #include #include -#include "ddk750_help.h" #include "ddk750_reg.h" #include "ddk750_chip.h" #include "ddk750_power.h" #define MHz(x) ((x) * 1000000) +static logical_chip_type_t chip; + logical_chip_type_t sm750_get_chip_type(void) { - unsigned short physicalID; - char physicalRev; - logical_chip_type_t chip; - - physicalID = devId750; /* either 0x718 or 0x750 */ - physicalRev = revId750; + return chip; +} - if (physicalID == 0x718) +void sm750_set_chip_type(unsigned short devId, char revId) +{ + if (devId == 0x718) chip = SM718; - else if (physicalID == 0x750) { + else if (devId == 0x750) { chip = SM750; /* SM750 and SM750LE are different in their revision ID only. */ - if (physicalRev == SM750LE_REVISION_ID) + if (revId == SM750LE_REVISION_ID) { chip = SM750LE; + pr_info("found sm750le\n"); + } } else chip = SM_UNKNOWN; - - return chip; } static unsigned int get_mxclk_freq(void) diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h index a4ee35917fde..755aab1e5442 100644 --- a/drivers/staging/sm750fb/ddk750_chip.h +++ b/drivers/staging/sm750fb/ddk750_chip.h @@ -6,6 +6,14 @@ #endif #include +#include +#include + +/* software control endianness */ +#define PEEK32(addr) readl(addr + mmio750) +#define POKE32(addr, data) writel(data, addr + mmio750) + +extern void __iomem *mmio750; /* This is all the chips recognized by this library */ typedef enum _logical_chip_type_t { @@ -68,9 +76,9 @@ struct initchip_param { }; logical_chip_type_t sm750_get_chip_type(void); +void sm750_set_chip_type(unsigned short devId, char revId); unsigned int calcPllValue(unsigned int request, struct pll_value *pll); unsigned int formatPllReg(struct pll_value *pPLL); -void ddk750_set_mmio(void __iomem *, unsigned short, char); unsigned int ddk750_getVMSize(void); int ddk750_initHw(struct initchip_param *); diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 4023c476b9e4..aea97361d937 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -1,5 +1,5 @@ #include "ddk750_reg.h" -#include "ddk750_help.h" +#include "ddk750_chip.h" #include "ddk750_display.h" #include "ddk750_power.h" #include "ddk750_dvi.h" diff --git a/drivers/staging/sm750fb/ddk750_dvi.c b/drivers/staging/sm750fb/ddk750_dvi.c index 8252f771ef9e..250c2f478778 100644 --- a/drivers/staging/sm750fb/ddk750_dvi.c +++ b/drivers/staging/sm750fb/ddk750_dvi.c @@ -1,6 +1,6 @@ #define USE_DVICHIP #ifdef USE_DVICHIP -#include "ddk750_help.h" +#include "ddk750_chip.h" #include "ddk750_reg.h" #include "ddk750_dvi.h" #include "ddk750_sii164.h" diff --git a/drivers/staging/sm750fb/ddk750_help.c b/drivers/staging/sm750fb/ddk750_help.c deleted file mode 100644 index e72a29c8602e..000000000000 --- a/drivers/staging/sm750fb/ddk750_help.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "ddk750_help.h" - -void __iomem *mmio750; -char revId750; -unsigned short devId750; - -/* after driver mapped io registers, use this function first */ -void ddk750_set_mmio(void __iomem *addr, unsigned short devId, char revId) -{ - mmio750 = addr; - devId750 = devId; - revId750 = revId; - if (revId == 0xfe) - pr_info("found sm750le\n"); -} - - diff --git a/drivers/staging/sm750fb/ddk750_help.h b/drivers/staging/sm750fb/ddk750_help.h deleted file mode 100644 index 009db9213a73..000000000000 --- a/drivers/staging/sm750fb/ddk750_help.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef DDK750_HELP_H__ -#define DDK750_HELP_H__ -#include "ddk750_chip.h" -#ifndef USE_INTERNAL_REGISTER_ACCESS - -#include -#include -#include - -/* software control endianness */ -#define PEEK32(addr) readl(addr + mmio750) -#define POKE32(addr, data) writel(data, addr + mmio750) - -extern void __iomem *mmio750; -extern char revId750; -extern unsigned short devId750; -#else -/* implement if you want use it*/ -#endif - -#endif diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index d391c127ead7..4ce0fbeba55e 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -1,6 +1,6 @@ #define USE_HW_I2C #ifdef USE_HW_I2C -#include "ddk750_help.h" +#include "ddk750_chip.h" #include "ddk750_reg.h" #include "ddk750_hwi2c.h" #include "ddk750_power.h" diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index 4bbf0c47dc16..496491803a6b 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -1,5 +1,4 @@ -#include "ddk750_help.h" #include "ddk750_reg.h" #include "ddk750_mode.h" #include "ddk750_chip.h" diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 7cc6169f884e..710106e35bcf 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -1,4 +1,4 @@ -#include "ddk750_help.h" +#include "ddk750_chip.h" #include "ddk750_reg.h" #include "ddk750_power.h" diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c index 72a42330e7a1..78bfba0e03e8 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.c +++ b/drivers/staging/sm750fb/ddk750_swi2c.c @@ -10,7 +10,7 @@ * implementation. * *******************************************************************/ -#include "ddk750_help.h" +#include "ddk750_chip.h" #include "ddk750_reg.h" #include "ddk750_swi2c.h" #include "ddk750_power.h" diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 74a97b40a17d..61d2fdc41b52 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -23,6 +23,8 @@ #include "ddk750.h" #include "sm750_accel.h" +void __iomem *mmio750; + int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) { int ret; @@ -59,7 +61,8 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1; sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1; - ddk750_set_mmio(sm750_dev->pvReg, sm750_dev->devid, sm750_dev->revid); + mmio750 = sm750_dev->pvReg; + sm750_set_chip_type(sm750_dev->devid, sm750_dev->revid); sm750_dev->vidmem_start = pci_resource_start(pdev, 0); /* don't use pdev_resource[x].end - resource[x].start to -- cgit v1.2.3 From be704e58328d4c488677c59e04dd9cec2d9515a2 Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman Date: Tue, 11 Oct 2016 19:29:20 -0700 Subject: staging: sm750fb: compress return logic Using Coccinelle script, compress return logic to return a value directly rather than doing an assignment and returning the variable. Remove unnecessary variable declaration by hand. Coccinelle script: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Elizabeth Ferdman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 8770a46c3c67..b094492cc5f0 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1209,7 +1209,6 @@ static struct pci_driver lynxfb_driver = { static int __init lynxfb_init(void) { char *option; - int ret; #ifdef MODULE option = g_option; @@ -1219,8 +1218,7 @@ static int __init lynxfb_init(void) #endif lynxfb_setup(option); - ret = pci_register_driver(&lynxfb_driver); - return ret; + return pci_register_driver(&lynxfb_driver); } module_init(lynxfb_init); -- cgit v1.2.3 From 89e13b4590d004a64961abb66479bb6cc51143f9 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Mon, 10 Oct 2016 16:02:18 +0200 Subject: staging: wlan-ng: Replace data type declaration with variable of same type in cfg80211.c sizeof(var) instead of sizeof(struct XXX) is preferred. Fix it in cfg80211.c file. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 182b2d564627..67c48a8c18af 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -323,7 +323,7 @@ static int prism2_scan(struct wiphy *wiphy, priv->scan_request = request; - memset(&msg1, 0x00, sizeof(struct p80211msg_dot11req_scan)); + memset(&msg1, 0x00, sizeof(msg1)); msg1.msgcode = DIDmsg_dot11req_scan; msg1.bsstype.data = P80211ENUM_bsstype_any; -- cgit v1.2.3 From a567d0d47ffb31d1f8d8c206db998043911fa256 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Mon, 10 Oct 2016 16:02:19 +0200 Subject: staging: wlan-ng: Replace data type declaration with variable of same type in hfa384x_usb.c sizeof(var) instead of sizeof(struct XXX) is preferred. Fix it in hfa384x_usb.c file. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index fbd9dc6b81ee..a83026e74c63 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -531,7 +531,7 @@ static void hfa384x_usb_defer(struct work_struct *data) */ void hfa384x_create(struct hfa384x *hw, struct usb_device *usb) { - memset(hw, 0, sizeof(struct hfa384x)); + memset(hw, 0, sizeof(*hw)); hw->usb = usb; /* set up the endpoints */ -- cgit v1.2.3 From 229dbdc577cf6cf0f0589739b403aa5ef125f8e2 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Mon, 10 Oct 2016 16:02:20 +0200 Subject: staging: wlan-ng: Replace data type declaration with variable of same type in p80211conv.c sizeof(*var) instead of sizeof(struct XXX) is preferred. Fix it in p80211conv.c file. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 5c0e65863205..5080d42245bb 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -615,7 +615,7 @@ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) } /* Allocate the rxmeta */ - rxmeta = kzalloc(sizeof(struct p80211_rxmeta), GFP_ATOMIC); + rxmeta = kzalloc(sizeof(*rxmeta), GFP_ATOMIC); if (!rxmeta) { netdev_err(wlandev->netdev, -- cgit v1.2.3 From ec30aebb0db01375e0594f1b6c2bb9335801a913 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Mon, 10 Oct 2016 16:02:21 +0200 Subject: staging: wlan-ng: Replace data type declaration with variable of same type in p80211netdev.c sizeof(var) instead of sizeof(struct XXX) is preferred. Fix them in p80211netdev.c Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211netdev.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 656033ae3bf0..10dacf86d069 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -342,8 +342,8 @@ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, goto failed; } - memset(&p80211_hdr, 0, sizeof(union p80211_hdr)); - memset(&p80211_wep, 0, sizeof(struct p80211_metawep)); + memset(&p80211_hdr, 0, sizeof(p80211_hdr)); + memset(&p80211_wep, 0, sizeof(p80211_wep)); if (netif_queue_stopped(netdev)) { netdev_dbg(netdev, "called when queue stopped.\n"); @@ -381,8 +381,8 @@ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, goto failed; } /* move the header over */ - memcpy(&p80211_hdr, skb->data, sizeof(union p80211_hdr)); - skb_pull(skb, sizeof(union p80211_hdr)); + memcpy(&p80211_hdr, skb->data, sizeof(p80211_hdr)); + skb_pull(skb, sizeof(p80211_hdr)); } else { if (skb_ether_to_p80211 (wlandev, wlandev->ethconv, skb, &p80211_hdr, @@ -640,9 +640,9 @@ static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr) resultcode = &dot11req.resultcode; /* Set up a dot11req_mibset */ - memset(&dot11req, 0, sizeof(struct p80211msg_dot11req_mibset)); + memset(&dot11req, 0, sizeof(dot11req)); dot11req.msgcode = DIDmsg_dot11req_mibset; - dot11req.msglen = sizeof(struct p80211msg_dot11req_mibset); + dot11req.msglen = sizeof(dot11req); memcpy(dot11req.devname, ((struct wlandevice *)dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1); -- cgit v1.2.3 From 67fafe375a634fa7cd4dc4f710e106c32a406e8a Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Mon, 10 Oct 2016 16:02:22 +0200 Subject: staging: wlan-ng: Replace data type declaration with variable of same type in prism2sta.c sizeof(*var) instead of sizeof(struct XXX) is preferred. Fix them in prism2sta.c file. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2sta.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index b3ae2bb9ae42..351f08d6a5d9 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1102,8 +1102,7 @@ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, kfree(hw->scanresults); - hw->scanresults = kmemdup(inf, sizeof(struct hfa384x_inf_frame), - GFP_ATOMIC); + hw->scanresults = kmemdup(inf, sizeof(*inf), GFP_ATOMIC); if (nbss == 0) nbss = -1; @@ -1888,8 +1887,8 @@ static struct wlandevice *create_wlan(void) struct hfa384x *hw = NULL; /* Alloc our structures */ - wlandev = kzalloc(sizeof(struct wlandevice), GFP_KERNEL); - hw = kzalloc(sizeof(struct hfa384x), GFP_KERNEL); + wlandev = kzalloc(sizeof(*wlandev), GFP_KERNEL); + hw = kzalloc(sizeof(*hw), GFP_KERNEL); if (!wlandev || !hw) { kfree(wlandev); -- cgit v1.2.3 From efffed8e06f85470814c409517ad21163843acf0 Mon Sep 17 00:00:00 2001 From: sayli karnik Date: Mon, 10 Oct 2016 21:53:10 +0530 Subject: staging: wlan-ng: cfg80211: Remove unnecessary parentheses around variables The patch fixes the checkpatch.pl check: CHECK: Unnecessary parentheses around variable Signed-off-by: sayli karnik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 67c48a8c18af..aa0e5a3d4a89 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -375,13 +375,13 @@ static int prism2_scan(struct wiphy *wiphy, ie_buf[0] = WLAN_EID_SSID; ie_buf[1] = msg2.ssid.data.len; ie_len = ie_buf[1] + 2; - memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len); + memcpy(&ie_buf[2], &msg2.ssid.data.data, msg2.ssid.data.len); freq = ieee80211_channel_to_frequency(msg2.dschannel.data, NL80211_BAND_2GHZ); bss = cfg80211_inform_bss(wiphy, ieee80211_get_channel(wiphy, freq), CFG80211_BSS_FTYPE_UNKNOWN, - (const u8 *)&(msg2.bssid.data.data), + (const u8 *)&msg2.bssid.data.data, msg2.timestamp.data, msg2.capinfo.data, msg2.beaconperiod.data, ie_buf, -- cgit v1.2.3 From a88727e7ccbbadd3c55ac4df9a3973020d07b099 Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Wed, 12 Oct 2016 10:18:48 +0300 Subject: Staging: media: omap4iss: Unnecessary KERN_ERR This patch remove unnecessary KERN_ERR in WARN() within iss_csi2.c Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/omap4iss/iss_csi2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index aaca39d751a5..f71d5f2f179f 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -224,7 +224,7 @@ static u16 csi2_ctx_map_format(struct iss_csi2_device *csi2) fmtidx = 3; break; default: - WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n", + WARN(1, "CSI2: pixel format %08x unsupported!\n", fmt->code); return 0; } -- cgit v1.2.3 From 51ea64c98d8f432d8553704faa7765935358580d Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Tue, 11 Oct 2016 11:15:03 +0300 Subject: Staging: media: lirc: Use unsigned int instead unsigned This patch fixes a WARNING: Prefer 'unsigned int' to bare use of 'unsigned', found by checkpatch.pl. By fixing this the types of the parameters become more explicit. Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/lirc/lirc_zilog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 3551aed589c0..34aac3e2eb87 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -1157,8 +1157,8 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n, /* Send the code */ if (ret == 0) { - ret = send_code(tx, (unsigned)command >> 16, - (unsigned)command & 0xFFFF); + ret = send_code(tx, (unsigned int)command >> 16, + (unsigned int)command & 0xFFFF); if (ret == -EPROTO) { mutex_unlock(&ir->ir_lock); mutex_unlock(&tx->client_lock); -- cgit v1.2.3 From 21971f3e0e558db280c9b01d461364e8442d0ef9 Mon Sep 17 00:00:00 2001 From: Varsha Rao Date: Tue, 11 Oct 2016 19:05:46 +0530 Subject: staging: vt6655: Removes the FSF mailing address. This patch fixes the checkpatch issue by removing the Free Software Foundation's mailing address from the sample GPL notice. Because the FSF has changed address in the past, and may change again. Linux already includes a copy of the GPL. Signed-off-by: Varsha Rao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 5 ----- drivers/staging/vt6655/baseband.h | 5 ----- drivers/staging/vt6655/card.c | 4 ---- drivers/staging/vt6655/card.h | 4 ---- drivers/staging/vt6655/channel.c | 4 ---- drivers/staging/vt6655/channel.h | 4 ---- drivers/staging/vt6655/desc.h | 4 ---- drivers/staging/vt6655/device.h | 4 ---- drivers/staging/vt6655/device_cfg.h | 4 ---- drivers/staging/vt6655/device_main.c | 4 ---- drivers/staging/vt6655/dpc.c | 4 ---- drivers/staging/vt6655/dpc.h | 4 ---- drivers/staging/vt6655/key.c | 5 ----- drivers/staging/vt6655/key.h | 5 ----- drivers/staging/vt6655/mac.c | 5 ----- drivers/staging/vt6655/mac.h | 5 ----- drivers/staging/vt6655/power.c | 5 ----- drivers/staging/vt6655/power.h | 4 ---- drivers/staging/vt6655/rf.c | 5 ----- drivers/staging/vt6655/rf.h | 5 ----- drivers/staging/vt6655/rxtx.c | 4 ---- drivers/staging/vt6655/rxtx.h | 4 ---- drivers/staging/vt6655/srom.c | 4 ---- drivers/staging/vt6655/srom.h | 5 ----- drivers/staging/vt6655/tmacro.h | 4 ---- drivers/staging/vt6655/upc.h | 4 ---- 26 files changed, 114 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 7c3ae92d00e4..2696f505910b 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: baseband.c * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index b4e8c43180ec..412537e3fb75 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: baseband.h * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index dbcea4434725..4e0e20cbee0e 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: card.c * Purpose: Provide functions to setup NIC operation mode * Functions: diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 0203c7fd91a2..2f0f893a6971 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: card.h * * Purpose: Provide functions to setup NIC operation mode diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 029a8df4ca1c..ab89956511a0 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: channel.c * */ diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h index 2d613e7f169c..2621dfabff06 100644 --- a/drivers/staging/vt6655/channel.h +++ b/drivers/staging/vt6655/channel.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: channel.h * */ diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index 2d7f6ae89164..2fee6e759ad8 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: desc.h * * Purpose:The header file of descriptor diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 55405e058196..6263c29d51fc 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: device.h * * Purpose: MAC Data structure diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h index b4c9547d3138..0298ea923f97 100644 --- a/drivers/staging/vt6655/device_cfg.h +++ b/drivers/staging/vt6655/device_cfg.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: device_cfg.h * * Purpose: Driver configuration header diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 9b2ec257b9f3..a6f7a4f0dcd5 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: device_main.c * * Purpose: driver entry for initial, open, close, tx and rx. diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 700032e9c477..9b3fa779258a 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: dpc.c * * Purpose: handle dpc rx functions diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h index e80b30816968..6e75fa9c5618 100644 --- a/drivers/staging/vt6655/dpc.h +++ b/drivers/staging/vt6655/dpc.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: dpc.h * * Purpose: diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index e161d5d9aebb..dad9e292d4da 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: key.c * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h index d72719741a56..a5024611af60 100644 --- a/drivers/staging/vt6655/key.h +++ b/drivers/staging/vt6655/key.h @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: key.h * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index d3f4eb2d02af..359b3c3960f8 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: mac.c * * Purpose: MAC routines diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 030f529c339b..d7faaf973c7d 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: mac.h * * Purpose: MAC routines diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 1506b1bb5d55..716d2a80f840 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: power.c * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h index d619c426b941..dfcb0ca8b448 100644 --- a/drivers/staging/vt6655/power.h +++ b/drivers/staging/vt6655/power.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: power.h * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 447882c7a6be..1d00f45385b4 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: rf.c * * Purpose: rf function code diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h index e9c786995506..b6e853784a26 100644 --- a/drivers/staging/vt6655/rf.h +++ b/drivers/staging/vt6655/rf.h @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: rf.h * * Purpose: diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 7e69bc99d60f..6ebab5600ee2 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: rxtx.c * * Purpose: handle WMAC/802.3/802.11 rx & tx functions diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h index 1e30ecb5c63c..89de67115826 100644 --- a/drivers/staging/vt6655/rxtx.h +++ b/drivers/staging/vt6655/rxtx.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: rxtx.h * * Purpose: diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c index ee992772066f..e6d1280a4737 100644 --- a/drivers/staging/vt6655/srom.c +++ b/drivers/staging/vt6655/srom.c @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: srom.c * * Purpose:Implement functions to access eeprom diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h index 531bf0069373..b3215a24ac51 100644 --- a/drivers/staging/vt6655/srom.h +++ b/drivers/staging/vt6655/srom.h @@ -12,11 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * * File: srom.h * * Purpose: Implement functions to access eeprom diff --git a/drivers/staging/vt6655/tmacro.h b/drivers/staging/vt6655/tmacro.h index 597efefc017f..d6a0563ad55c 100644 --- a/drivers/staging/vt6655/tmacro.h +++ b/drivers/staging/vt6655/tmacro.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: tmacro.h * * Purpose: define basic common types and macros diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index 85fe0464cfb3..9806b5989014 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * File: upc.h * * Purpose: Macros to access device -- cgit v1.2.3 From f9d033c8ecef66365d78db31c18eda1be86136bc Mon Sep 17 00:00:00 2001 From: Varsha Rao Date: Wed, 12 Oct 2016 10:06:46 +0530 Subject: staging: vt6655: Adding space around '*' This patch fixes the checkpatch issue by adding space around '*'. Signed-off-by: Varsha Rao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/card.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 4e0e20cbee0e..2e2f96d002e5 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -257,7 +257,7 @@ bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type) BBbWriteEmbedded(priv, 0x88, 0x02); bySlot = C_SLOT_LONG; bySIFS = C_SIFS_BG; - byDIFS = C_SIFS_BG + 2*C_SLOT_LONG; + byDIFS = C_SIFS_BG + 2 * C_SLOT_LONG; byCWMaxMin = 0xA5; } else { /* PK_TYPE_11GA & PK_TYPE_11GB */ MACvSetBBType(priv->PortOffset, BB_TYPE_11G); @@ -285,7 +285,7 @@ bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type) byDIFS = C_SIFS_BG + 2 * C_SLOT_SHORT; } else { bySlot = C_SLOT_LONG; - byDIFS = C_SIFS_BG + 2*C_SLOT_LONG; + byDIFS = C_SIFS_BG + 2 * C_SLOT_LONG; } byCWMaxMin = 0xa4; -- cgit v1.2.3 From 32623b0d28e53f926d962c863ce9a62ddc70f376 Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Tue, 11 Oct 2016 19:54:42 +0300 Subject: Staging: wilc1000: Replace memcpy by ether_addr_copy This patch fixes the following checkpatch.pl warning: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) According to ether_addr_copy() description and functionality, all Ethernet addresses should align to the u16 datatype. Here is the output of pahole for the relevant datastructures: struct del_sta { u8 mac_addr[6]; /* 0 6 */ /* size: 6, cachelines: 1, members: 1 */ /* last cacheline: 6 bytes */ }; struct sta_inactive_t { u8 mac[6]; /* 0 6 */ /* size: 6, cachelines: 1, members: 1 */ /* last cacheline: 6 bytes */ }; Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index ff3d267c2eb0..0c5dea78807d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1930,7 +1930,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, wid.val = kmalloc(wid.size, GFP_KERNEL); stamac = wid.val; - memcpy(stamac, strHostIfStaInactiveT->mac, ETH_ALEN); + ether_addr_copy(stamac, strHostIfStaInactiveT->mac); result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -2166,7 +2166,7 @@ static void Handle_DelStation(struct wilc_vif *vif, pu8CurrByte = wid.val; - memcpy(pu8CurrByte, pstrDelStaParam->mac_addr, ETH_ALEN); + ether_addr_copy(pu8CurrByte, pstrDelStaParam->mac_addr); result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); -- cgit v1.2.3 From 2072763cf08277bd6fef3bcde89966559d65f6fd Mon Sep 17 00:00:00 2001 From: Chase Metzger Date: Tue, 11 Oct 2016 16:22:45 -0700 Subject: drivers: staging: greybus: audio_manager_sysfs.c: Fixed CHECK for brace issue Added braces to else and else if statements where checkpatch complained. Signed-off-by: Chase Metzger Reviewed-by: Vaibhav Agarwal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_manager_sysfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/audio_manager_sysfs.c b/drivers/staging/greybus/audio_manager_sysfs.c index d8bf8591ff9e..376e17cb6cd7 100644 --- a/drivers/staging/greybus/audio_manager_sysfs.c +++ b/drivers/staging/greybus/audio_manager_sysfs.c @@ -71,10 +71,11 @@ static ssize_t manager_sysfs_dump_store( num = gb_audio_manager_dump_module(id); if (num) return num; - } else if (!strncmp("all", buf, 3)) + } else if (!strncmp("all", buf, 3)) { gb_audio_manager_dump_all(); - else + } else { return -EINVAL; + } return count; } -- cgit v1.2.3 From 99a751c74baf90535a232376d81fef957ebad63f Mon Sep 17 00:00:00 2001 From: Sabitha George Date: Mon, 10 Oct 2016 23:23:15 +0530 Subject: staging: ks7010: Replace asm/uaccess.h and asm/atomic.h Replaces inclusion of asm/uaccess.h with linux/uaccess.h and asm/atomic.h with linux/atomic.h in ks_wlan_net.c Signed-off-by: Sabitha George Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 14bb008754d7..cda635a1f20f 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -24,9 +24,9 @@ #include #include #include -#include +#include #include -#include +#include static int wep_on_off; #define WEP_OFF 0 -- cgit v1.2.3 From 96268418f9e27d8b0dde6a6c3837979c30a996aa Mon Sep 17 00:00:00 2001 From: Sabitha George Date: Mon, 10 Oct 2016 23:24:10 +0530 Subject: staging: ks7010: Fixes error "foo * bar should be foo *bar" Fixes checkpatch warning on ks_wlan_net.c: foo * bar should be foo *bar Signed-off-by: Sabitha George Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan_net.c | 64 ++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index cda635a1f20f..84edd3b929b0 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -829,7 +829,7 @@ static int ks_wlan_get_frag(struct net_device *dev, /*------------------------------------------------------------------*/ /* Wireless Handler : set Mode of Operation */ static int ks_wlan_set_mode(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -865,7 +865,7 @@ static int ks_wlan_set_mode(struct net_device *dev, /*------------------------------------------------------------------*/ /* Wireless Handler : get Mode of Operation */ static int ks_wlan_get_mode(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2130,7 +2130,7 @@ static struct iw_statistics *ks_get_wireless_stats(struct net_device *dev) /*------------------------------------------------------------------*/ /* Private handler : set stop request */ static int ks_wlan_set_stop_request(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2196,7 +2196,7 @@ static int ks_wlan_get_firmware_version(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set force disconnect status */ static int ks_wlan_set_detach(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; @@ -2221,7 +2221,7 @@ static int ks_wlan_set_detach(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get force disconnect status */ static int ks_wlan_get_detach(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; @@ -2237,7 +2237,7 @@ static int ks_wlan_get_detach(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get connect status */ static int ks_wlan_get_connect(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; @@ -2254,7 +2254,7 @@ static int ks_wlan_get_connect(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set preamble */ static int ks_wlan_set_preamble(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2279,7 +2279,7 @@ static int ks_wlan_set_preamble(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get preamble */ static int ks_wlan_get_preamble(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2296,7 +2296,7 @@ static int ks_wlan_get_preamble(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set power save mode */ static int ks_wlan_set_powermgt(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2329,7 +2329,7 @@ static int ks_wlan_set_powermgt(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get power save made */ static int ks_wlan_get_powermgt(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2346,7 +2346,7 @@ static int ks_wlan_get_powermgt(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set scan type */ static int ks_wlan_set_scan_type(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2369,7 +2369,7 @@ static int ks_wlan_set_scan_type(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get scan type */ static int ks_wlan_get_scan_type(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2520,7 +2520,7 @@ static int ks_wlan_get_wep_ascii(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set beacon lost count */ static int ks_wlan_set_beacon_lost(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2545,7 +2545,7 @@ static int ks_wlan_set_beacon_lost(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get beacon lost count */ static int ks_wlan_get_beacon_lost(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2562,7 +2562,7 @@ static int ks_wlan_get_beacon_lost(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set phy type */ static int ks_wlan_set_phy_type(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2588,7 +2588,7 @@ static int ks_wlan_set_phy_type(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get phy type */ static int ks_wlan_get_phy_type(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2605,7 +2605,7 @@ static int ks_wlan_get_phy_type(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set cts mode */ static int ks_wlan_set_cts_mode(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2633,7 +2633,7 @@ static int ks_wlan_set_cts_mode(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get cts mode */ static int ks_wlan_get_cts_mode(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2651,7 +2651,7 @@ static int ks_wlan_get_cts_mode(struct net_device *dev, /* Private handler : set sleep mode */ static int ks_wlan_set_sleep_mode(struct net_device *dev, struct iw_request_info *info, - __u32 * uwrq, char *extra) + __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); @@ -2681,7 +2681,7 @@ static int ks_wlan_set_sleep_mode(struct net_device *dev, /* Private handler : get sleep mode */ static int ks_wlan_get_sleep_mode(struct net_device *dev, struct iw_request_info *info, - __u32 * uwrq, char *extra) + __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); @@ -2697,7 +2697,7 @@ static int ks_wlan_get_sleep_mode(struct net_device *dev, /* Private handler : set phy information timer */ static int ks_wlan_set_phy_information_timer(struct net_device *dev, struct iw_request_info *info, - __u32 * uwrq, char *extra) + __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; @@ -2719,7 +2719,7 @@ static int ks_wlan_set_phy_information_timer(struct net_device *dev, /* Private handler : get phy information timer */ static int ks_wlan_get_phy_information_timer(struct net_device *dev, struct iw_request_info *info, - __u32 * uwrq, char *extra) + __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; @@ -2736,7 +2736,7 @@ static int ks_wlan_get_phy_information_timer(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set WPS enable */ static int ks_wlan_set_wps_enable(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2760,7 +2760,7 @@ static int ks_wlan_set_wps_enable(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get WPS enable */ static int ks_wlan_get_wps_enable(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2822,7 +2822,7 @@ static int ks_wlan_set_wps_probe_req(struct net_device *dev, /* Private handler : get WPS probe req */ static int ks_wlan_get_wps_probe_req(struct net_device *dev, struct iw_request_info *info, - __u32 * uwrq, char *extra) + __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; DPRINTK(2, "\n"); @@ -2839,7 +2839,7 @@ static int ks_wlan_get_wps_probe_req(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set tx gain control value */ static int ks_wlan_set_tx_gain(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2866,7 +2866,7 @@ static int ks_wlan_set_tx_gain(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get tx gain control value */ static int ks_wlan_get_tx_gain(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2884,7 +2884,7 @@ static int ks_wlan_get_tx_gain(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set rx gain control value */ static int ks_wlan_set_rx_gain(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2911,7 +2911,7 @@ static int ks_wlan_set_rx_gain(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get rx gain control value */ static int ks_wlan_get_rx_gain(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -2930,7 +2930,7 @@ static int ks_wlan_get_rx_gain(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : set region value */ static int ks_wlan_set_region(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; @@ -2952,7 +2952,7 @@ static int ks_wlan_set_region(struct net_device *dev, /*------------------------------------------------------------------*/ /* Private handler : get eeprom checksum result */ static int ks_wlan_get_eeprom_cksum(struct net_device *dev, - struct iw_request_info *info, __u32 * uwrq, + struct iw_request_info *info, __u32 *uwrq, char *extra) { struct ks_wlan_private *priv = @@ -3079,7 +3079,7 @@ static void print_hif_event(struct net_device *dev, int event) /*------------------------------------------------------------------*/ /* Private handler : get host command history */ static int ks_wlan_hostt(struct net_device *dev, struct iw_request_info *info, - __u32 * uwrq, char *extra) + __u32 *uwrq, char *extra) { int i, event; struct ks_wlan_private *priv = -- cgit v1.2.3 From 4669f6e2758526215adcad27de6e26cde6036c24 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:17 +0000 Subject: staging: rts5208: spi.c: Remove unnecessary parenthesis Style warnings found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/spi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/spi.c b/drivers/staging/rts5208/spi.c index 13c539c83838..5ebcdce80ac2 100644 --- a/drivers/staging/rts5208/spi.c +++ b/drivers/staging/rts5208/spi.c @@ -29,7 +29,7 @@ static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code) { - struct spi_info *spi = &(chip->spi); + struct spi_info *spi = &chip->spi; spi->err_code = err_code; } @@ -57,7 +57,7 @@ static int spi_init(struct rtsx_chip *chip) static int spi_set_init_para(struct rtsx_chip *chip) { - struct spi_info *spi = &(chip->spi); + struct spi_info *spi = &chip->spi; int retval; retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF, @@ -134,7 +134,7 @@ static int sf_polling_status(struct rtsx_chip *chip, int msec) static int sf_enable_write(struct rtsx_chip *chip, u8 ins) { - struct spi_info *spi = &(chip->spi); + struct spi_info *spi = &chip->spi; int retval; if (!spi->write_en) @@ -163,7 +163,7 @@ static int sf_enable_write(struct rtsx_chip *chip, u8 ins) static int sf_disable_write(struct rtsx_chip *chip, u8 ins) { - struct spi_info *spi = &(chip->spi); + struct spi_info *spi = &chip->spi; int retval; if (!spi->write_en) @@ -518,11 +518,11 @@ int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val) int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct spi_info *spi = &(chip->spi); + struct spi_info *spi = &chip->spi; dev_dbg(rtsx_dev(chip), "spi_get_status: err_code = 0x%x\n", spi->err_code); - rtsx_stor_set_xfer_buf(&(spi->err_code), + rtsx_stor_set_xfer_buf(&spi->err_code, min_t(int, scsi_bufflen(srb), 1), srb); scsi_set_resid(srb, scsi_bufflen(srb) - 1); @@ -531,7 +531,7 @@ int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct spi_info *spi = &(chip->spi); + struct spi_info *spi = &chip->spi; spi_set_err_code(chip, SPI_NO_ERR); -- cgit v1.2.3 From 8c3c144bff1bb9163a72c799d4c08190536bc4a8 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:18 +0000 Subject: staging: rts5208: spi.c: Alignment fixes Lining up code with open parantheses found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/spi.c | 130 +++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/spi.c b/drivers/staging/rts5208/spi.c index 5ebcdce80ac2..8b8cd955dfeb 100644 --- a/drivers/staging/rts5208/spi.c +++ b/drivers/staging/rts5208/spi.c @@ -117,9 +117,9 @@ static int sf_polling_status(struct rtsx_chip *chip, int msec) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_POLLING_MODE0); + SPI_TRANSFER0_START | SPI_POLLING_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, msec); if (retval < 0) { @@ -144,11 +144,11 @@ static int sf_enable_write(struct rtsx_chip *chip, u8 ins) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_C_MODE0); + SPI_TRANSFER0_START | SPI_C_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -173,11 +173,11 @@ static int sf_disable_write(struct rtsx_chip *chip, u8 ins) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_C_MODE0); + SPI_TRANSFER0_START | SPI_C_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -191,27 +191,27 @@ static int sf_disable_write(struct rtsx_chip *chip, u8 ins) } static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr, - u16 len) + u16 len) { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8)); if (addr_mode) { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, - (u8)(addr >> 8)); + (u8)(addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, - (u8)(addr >> 16)); + (u8)(addr >> 16)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CADO_MODE0); + SPI_TRANSFER0_START | SPI_CADO_MODE0); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CDO_MODE0); + SPI_TRANSFER0_START | SPI_CDO_MODE0); } rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); } static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr) @@ -222,21 +222,21 @@ static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); if (addr_mode) { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, - (u8)(addr >> 8)); + (u8)(addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, - (u8)(addr >> 16)); + (u8)(addr >> 16)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); + SPI_TRANSFER0_START | SPI_CA_MODE0); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_C_MODE0); + SPI_TRANSFER0_START | SPI_C_MODE0); } rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -322,9 +322,9 @@ static int spi_eeprom_program_enable(struct rtsx_chip *chip) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); + SPI_TRANSFER0_START | SPI_CA_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -358,9 +358,9 @@ int spi_erase_eeprom_chip(struct rtsx_chip *chip) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); + SPI_TRANSFER0_START | SPI_CA_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -402,9 +402,9 @@ int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); + SPI_TRANSFER0_START | SPI_CA_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -442,9 +442,9 @@ int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CADI_MODE0); + SPI_TRANSFER0_START | SPI_CADI_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -497,9 +497,9 @@ int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val) rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); + SPI_TRANSFER0_START | SPI_CA_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -523,7 +523,7 @@ int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) dev_dbg(rtsx_dev(chip), "spi_get_status: err_code = 0x%x\n", spi->err_code); rtsx_stor_set_xfer_buf(&spi->err_code, - min_t(int, scsi_bufflen(srb), 1), srb); + min_t(int, scsi_bufflen(srb), 1), srb); scsi_set_resid(srb, scsi_bufflen(srb) - 1); return STATUS_SUCCESS; @@ -574,37 +574,37 @@ int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); + PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]); if (len == 0) { if (srb->cmnd[9]) { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, - 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0); + 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, - 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0); + 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0); } } else { if (srb->cmnd[9]) { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CADI_MODE0); + SPI_TRANSFER0_START | SPI_CADI_MODE0); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CDI_MODE0); + SPI_TRANSFER0_START | SPI_CDI_MODE0); } } rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval < 0) { @@ -682,38 +682,38 @@ int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (slow_read) { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, - (u8)addr); + (u8)addr); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, - (u8)(addr >> 8)); + (u8)(addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, - (u8)(addr >> 16)); + (u8)(addr >> 16)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, - (u8)addr); + (u8)addr); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, - (u8)(addr >> 8)); + (u8)(addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF, - (u8)(addr >> 16)); + (u8)(addr >> 16)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32); + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32); } rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, - (u8)(pagelen >> 8)); + (u8)(pagelen >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, - (u8)pagelen); + (u8)pagelen); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CADI_MODE0); + SPI_TRANSFER0_START | SPI_CADI_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, - SPI_TRANSFER0_END, SPI_TRANSFER0_END); + SPI_TRANSFER0_END, SPI_TRANSFER0_END); rtsx_send_cmd_no_wait(chip); retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, - DMA_FROM_DEVICE, 10000); + DMA_FROM_DEVICE, 10000); if (retval < 0) { kfree(buf); rtsx_clear_spi_error(chip); @@ -723,7 +723,7 @@ int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) } rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, - TO_XFER_BUF); + TO_XFER_BUF); addr += pagelen; len -= pagelen; @@ -775,14 +775,14 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) } rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, - FROM_XFER_BUF); + FROM_XFER_BUF); rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, - buf[0]); + buf[0]); sf_program(chip, ins, 1, addr, 1); retval = rtsx_send_cmd(chip, 0, 100); @@ -824,14 +824,14 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) while (len) { rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, - FROM_XFER_BUF); + FROM_XFER_BUF); rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, - buf[0]); + buf[0]); if (first_byte) { sf_program(chip, ins, 1, addr, 1); first_byte = 0; @@ -899,10 +899,10 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_send_cmd_no_wait(chip); rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, - &offset, FROM_XFER_BUF); + &offset, FROM_XFER_BUF); retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, - DMA_TO_DEVICE, 100); + DMA_TO_DEVICE, 100); if (retval < 0) { kfree(buf); rtsx_clear_spi_error(chip); @@ -1010,18 +1010,18 @@ int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); + PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1); rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status); rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CDO_MODE0); + SPI_TRANSFER0_START | SPI_CDO_MODE0); rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); + SPI_TRANSFER0_END); retval = rtsx_send_cmd(chip, 0, 100); if (retval != STATUS_SUCCESS) { -- cgit v1.2.3 From e78bff3266c1e187e82b88cbf966f9f654cbf0a3 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:19 +0000 Subject: staging: rts5208: sd.h: Alignment fixes Lining up code with open parenthses found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/sd.h b/drivers/staging/rts5208/sd.h index 60b79280fb5f..55764e16b93a 100644 --- a/drivers/staging/rts5208/sd.h +++ b/drivers/staging/rts5208/sd.h @@ -280,14 +280,15 @@ int reset_sd_card(struct rtsx_chip *chip); int sd_switch_clock(struct rtsx_chip *chip); void sd_stop_seq_mode(struct rtsx_chip *chip); int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt); + u32 start_sector, u16 sector_cnt); void sd_cleanup_work(struct rtsx_chip *chip); int sd_power_off_card3v3(struct rtsx_chip *chip); int release_sd_card(struct rtsx_chip *chip); #ifdef SUPPORT_CPRM int soft_reset_sd_card(struct rtsx_chip *chip); int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, bool special_check); + u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, + bool special_check); int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type); int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip); -- cgit v1.2.3 From 33f2b1216590738466b9433e79774dbdee0a8342 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:20 +0000 Subject: staging: rts5208: sd.c: Remove unnecessary parentheses Cleanup of &(chip->sd_card) to remove parentheses where they are not needed Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 94 ++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index b0bbb36f8988..dd564940b094 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -56,21 +56,21 @@ static u16 REG_SD_DCMPS1_CTL; static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; sd_card->err_code |= err_code; } static inline void sd_clr_err_code(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; sd_card->err_code = 0; } static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; return sd_card->err_code & err_code; } @@ -126,7 +126,7 @@ static int sd_check_data0_status(struct rtsx_chip *chip) static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, u32 arg, u8 rsp_type, u8 *rsp, int rsp_len) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int timeout = 100; u16 reg_addr; @@ -285,7 +285,7 @@ static int sd_read_data(struct rtsx_chip *chip, u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len, int timeout) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int i; @@ -356,7 +356,7 @@ static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len, int timeout) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int i; @@ -424,7 +424,7 @@ static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode, static int sd_check_csd(struct rtsx_chip *chip, char check_wp) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int i; u8 csd_ver, trans_speed; @@ -534,7 +534,7 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp) static int sd_set_sample_push_timing(struct rtsx_chip *chip) { int retval; - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; u8 val = 0; if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) @@ -573,7 +573,7 @@ static int sd_set_sample_push_timing(struct rtsx_chip *chip) static void sd_choose_proper_clock(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; if (CHK_SD_SDR104(sd_card)) { if (chip->asic_code) @@ -637,7 +637,7 @@ static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div) static int sd_set_init_para(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; retval = sd_set_sample_push_timing(chip); @@ -659,7 +659,7 @@ static int sd_set_init_para(struct rtsx_chip *chip) int sd_select_card(struct rtsx_chip *chip, int select) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 cmd_idx, cmd_type; u32 addr; @@ -686,7 +686,7 @@ int sd_select_card(struct rtsx_chip *chip, int select) #ifdef SUPPORT_SD_LOCK static int sd_update_lock_status(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 rsp[5]; @@ -717,7 +717,7 @@ static int sd_update_lock_status(struct rtsx_chip *chip) static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, u8 data_ready, int polling_cnt) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval, i; u8 rsp[5]; @@ -903,7 +903,7 @@ static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir) static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; u16 SD_VP_CTL, SD_DCMPS_CTL; u8 val; int retval; @@ -1060,7 +1060,7 @@ Fail: static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 cmd[5], buf[8]; @@ -1217,7 +1217,7 @@ static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, u8 func_group, u8 func_to_switch, u8 bus_width) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 cmd[5], buf[64]; @@ -1379,7 +1379,7 @@ static int sd_check_switch(struct rtsx_chip *chip, static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int i; u8 func_to_switch = 0; @@ -1611,7 +1611,7 @@ static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 cmd[5]; @@ -1651,7 +1651,7 @@ static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 cmd[5], bus_width; @@ -1691,7 +1691,7 @@ static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; retval = sd_change_phase(chip, sample_point, TUNE_TX); @@ -1730,7 +1730,7 @@ static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 cmd[5], bus_width; @@ -1795,7 +1795,7 @@ static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_dir) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; struct timing_phase_path path[MAX_PHASE + 1]; int i, j, cont_path_cnt; bool new_block; @@ -1913,7 +1913,7 @@ Search_Finish: static int sd_tuning_rx(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int i, j; u32 raw_phase_map[3], phase_map; @@ -1974,7 +1974,7 @@ static int sd_tuning_rx(struct rtsx_chip *chip) static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int i; u32 phase_map; @@ -2039,7 +2039,7 @@ static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) static int sd_tuning_tx(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int i, j; u32 raw_phase_map[3], phase_map; @@ -2193,7 +2193,7 @@ static int mmc_ddr_tuning(struct rtsx_chip *chip) int sd_switch_clock(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; int re_tuning = 0; @@ -2231,7 +2231,7 @@ int sd_switch_clock(struct rtsx_chip *chip) static int sd_prepare_reset(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; if (chip->asic_code) @@ -2478,7 +2478,7 @@ static int sd_dummy_clock(struct rtsx_chip *chip) static int sd_read_lba0(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 cmd[5], bus_width; @@ -2512,7 +2512,7 @@ static int sd_read_lba0(struct rtsx_chip *chip) static int sd_check_wp_state(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u32 val; u16 sd_card_type; @@ -2562,7 +2562,7 @@ static int sd_check_wp_state(struct rtsx_chip *chip) static int reset_sd(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; bool hi_cap_flow = false; int retval, i = 0, j = 0, k = 0; bool sd_dont_switch = false; @@ -2925,7 +2925,7 @@ Status_Fail: static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 buf[8] = {0}, bus_width, *ptr; u16 byte_cnt; @@ -3054,7 +3054,7 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; u8 *ptr, card_type, card_type_mask = 0; @@ -3178,7 +3178,7 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) static int reset_mmc(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval, i = 0, j = 0, k = 0; bool switch_ddr = true; u8 rsp[16]; @@ -3392,7 +3392,7 @@ MMC_UNLOCK_ENTRY: int reset_sd_card(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; sd_init_reg_addr(chip); @@ -3505,7 +3505,7 @@ int reset_sd_card(struct rtsx_chip *chip) static int reset_mmc_only(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; sd_card->sd_type = 0; @@ -3574,7 +3574,7 @@ static int reset_mmc_only(struct rtsx_chip *chip) static int wait_data_buf_ready(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int i, retval; for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) { @@ -3607,7 +3607,7 @@ static int wait_data_buf_ready(struct rtsx_chip *chip) void sd_stop_seq_mode(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; if (sd_card->seq_mode) { @@ -3632,7 +3632,7 @@ void sd_stop_seq_mode(struct rtsx_chip *chip) static inline int sd_auto_tune_clock(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; if (chip->asic_code) { @@ -3681,7 +3681,7 @@ static inline int sd_auto_tune_clock(struct rtsx_chip *chip) int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; u32 data_addr; u8 cfg2; int retval; @@ -4172,7 +4172,7 @@ int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type) int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; unsigned int lun = SCSI_LUN(srb); int len; u8 buf[18] = { @@ -4285,7 +4285,7 @@ static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; unsigned int lun = SCSI_LUN(srb); int retval, rsp_len; u8 cmd_idx, rsp_type; @@ -4420,7 +4420,7 @@ SD_Execute_Cmd_Failed: int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; unsigned int lun = SCSI_LUN(srb); int retval, rsp_len, i; bool read_err = false, cmd13_checkbit = false; @@ -4682,7 +4682,7 @@ SD_Execute_Read_Cmd_Failed: int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; unsigned int lun = SCSI_LUN(srb); int retval, rsp_len, i; bool write_err = false, cmd13_checkbit = false; @@ -5062,7 +5062,7 @@ SD_Execute_Write_Cmd_Failed: int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; unsigned int lun = SCSI_LUN(srb); int count; u16 data_len; @@ -5104,7 +5104,7 @@ int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; unsigned int lun = SCSI_LUN(srb); int retval; @@ -5174,7 +5174,7 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) void sd_cleanup_work(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; if (sd_card->seq_mode) { dev_dbg(rtsx_dev(chip), "SD: stop transmission\n"); @@ -5230,7 +5230,7 @@ int sd_power_off_card3v3(struct rtsx_chip *chip) int release_sd_card(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; int retval; chip->card_ready &= ~SD_CARD; -- cgit v1.2.3 From 20390dc72e94452e3c94e0181e52da63095b968b Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:21 +0000 Subject: staging: rts5208: sd.c: Alignment fixes Lining up with open parenthesis found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 492 ++++++++++++++++++++++--------------------- 1 file changed, 255 insertions(+), 237 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index dd564940b094..6229690cac52 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -124,7 +124,7 @@ static int sd_check_data0_status(struct rtsx_chip *chip) } static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len) + u32 arg, u8 rsp_type, u8 *rsp, int rsp_len) { struct sd_info *sd_card = &chip->sd_card; int retval; @@ -153,11 +153,12 @@ RTY_SEND_CMD: rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, - 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); + 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | SD_STAT_IDLE); + SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | + SD_STAT_IDLE); if (rsp_type == SD_RSP_TYPE_R2) { for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; @@ -238,7 +239,7 @@ RTY_SEND_CMD: if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) { if ((cmd_idx != SEND_RELATIVE_ADDR) && - (cmd_idx != SEND_IF_COND)) { + (cmd_idx != SEND_IF_COND)) { if (cmd_idx != STOP_TRANSMISSION) { if (ptr[1] & 0x80) { rtsx_trace(chip); @@ -308,27 +309,27 @@ static int sd_read_data(struct rtsx_chip *chip, 0xFF, cmd[i]); } rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - (u8)byte_cnt); + (u8)byte_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - (u8)(byte_cnt >> 8)); + (u8)(byte_cnt >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, - (u8)blk_cnt); + (u8)blk_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, - (u8)(blk_cnt >> 8)); + (u8)(blk_cnt >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END| - SD_CHECK_CRC7 | SD_RSP_LEN_6); + SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | + SD_CHECK_CRC7 | SD_RSP_LEN_6); if (trans_mode != SD_TM_AUTO_TUNING) rtsx_add_cmd(chip, WRITE_REG_CMD, - CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); + CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - trans_mode | SD_TRANSFER_START); + trans_mode | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); + SD_TRANSFER_END); retval = rtsx_send_cmd(chip, SD_CARD, timeout); if (retval < 0) { @@ -353,8 +354,8 @@ static int sd_read_data(struct rtsx_chip *chip, } static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode, - u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width, - u8 *buf, int buf_len, int timeout) + u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, + u8 bus_width, u8 *buf, int buf_len, int timeout) { struct sd_info *sd_card = &chip->sd_card; int retval; @@ -389,30 +390,30 @@ static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode, } } rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - (u8)byte_cnt); + (u8)byte_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - (u8)(byte_cnt >> 8)); + (u8)(byte_cnt >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, - (u8)blk_cnt); + (u8)blk_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, - (u8)(blk_cnt >> 8)); + (u8)(blk_cnt >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); + SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | + SD_CHECK_CRC7 | SD_RSP_LEN_6); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - trans_mode | SD_TRANSFER_START); + trans_mode | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); + SD_TRANSFER_END); retval = rtsx_send_cmd(chip, SD_CARD, timeout); if (retval < 0) { if (retval == -ETIMEDOUT) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); } rtsx_trace(chip); @@ -438,7 +439,7 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp) } retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr, - SD_RSP_TYPE_R2, rsp, 16); + SD_RSP_TYPE_R2, rsp, 16); if (retval == STATUS_SUCCESS) break; } @@ -691,7 +692,7 @@ static int sd_update_lock_status(struct rtsx_chip *chip) u8 rsp[5]; retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, rsp, 5); + SD_RSP_TYPE_R1, rsp, 5); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -715,7 +716,7 @@ static int sd_update_lock_status(struct rtsx_chip *chip) #endif static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, - u8 data_ready, int polling_cnt) + u8 data_ready, int polling_cnt) { struct sd_info *sd_card = &chip->sd_card; int retval, i; @@ -723,15 +724,15 @@ static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, for (i = 0; i < polling_cnt; i++) { retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, - 5); + sd_card->sd_addr, SD_RSP_TYPE_R1, + rsp, 5); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; } if (((rsp[3] & 0x1E) == state) && - ((rsp[3] & 0x01) == data_ready)) + ((rsp[3] & 0x01) == data_ready)) return STATUS_SUCCESS; } @@ -746,8 +747,8 @@ static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage) if (voltage == SD_IO_3V3) { if (chip->asic_code) { retval = rtsx_write_phy_register(chip, 0x08, - 0x4FC0 | - chip->phy_voltage); + 0x4FC0 | + chip->phy_voltage); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -763,8 +764,8 @@ static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage) } else if (voltage == SD_IO_1V8) { if (chip->asic_code) { retval = rtsx_write_phy_register(chip, 0x08, - 0x4C40 | - chip->phy_voltage); + 0x4C40 | + chip->phy_voltage); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -800,7 +801,7 @@ static int sd_voltage_switch(struct rtsx_chip *chip) } retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, - NULL, 0); + NULL, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -851,8 +852,8 @@ static int sd_voltage_switch(struct rtsx_chip *chip) (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | SD_DAT1_STATUS | SD_DAT0_STATUS)) { dev_dbg(rtsx_dev(chip), "SD_BUS_STAT: 0x%x\n", stat); - rtsx_write_register(chip, SD_BUS_STAT, - SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); + rtsx_write_register(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | + SD_CLK_FORCE_STOP, 0); rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0); rtsx_trace(chip); return STATUS_FAIL; @@ -992,9 +993,9 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, - DCMPS_CHANGE); + DCMPS_CHANGE); rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, - DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE); + DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE); retval = rtsx_send_cmd(chip, SD_CARD, 100); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -1065,7 +1066,7 @@ static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) u8 cmd[5], buf[8]; retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1078,7 +1079,7 @@ static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) cmd[4] = 0; retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width, - buf, 8, 250); + buf, 8, 250); if (retval != STATUS_SUCCESS) { rtsx_clear_sd_error(chip); rtsx_trace(chip); @@ -1096,7 +1097,7 @@ static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) } static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, - u8 func_to_switch, u8 *buf, int buf_len) + u8 func_to_switch, u8 *buf, int buf_len) { u8 support_mask = 0, query_switch = 0, switch_busy = 0; int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0; @@ -1198,7 +1199,7 @@ static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, if (func_group == SD_FUNC_GROUP_1) { if (!(buf[support_offset] & support_mask) || - ((buf[query_switch_offset] & 0x0F) != query_switch)) { + ((buf[query_switch_offset] & 0x0F) != query_switch)) { rtsx_trace(chip); return STATUS_FAIL; } @@ -1206,7 +1207,7 @@ static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, /* Check 'Busy Status' */ if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) && - ((buf[check_busy_offset] & switch_busy) == switch_busy)) { + ((buf[check_busy_offset] & switch_busy) == switch_busy)) { rtsx_trace(chip); return STATUS_FAIL; } @@ -1214,8 +1215,8 @@ static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, return STATUS_SUCCESS; } -static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, - u8 func_group, u8 func_to_switch, u8 bus_width) +static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, u8 func_group, + u8 func_to_switch, u8 bus_width) { struct sd_info *sd_card = &chip->sd_card; int retval; @@ -1247,7 +1248,7 @@ static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, } retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width, - buf, 64, 250); + buf, 64, 250); if (retval != STATUS_SUCCESS) { rtsx_clear_sd_error(chip); rtsx_trace(chip); @@ -1326,7 +1327,7 @@ static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch) } static int sd_check_switch(struct rtsx_chip *chip, - u8 func_group, u8 func_to_switch, u8 bus_width) + u8 func_group, u8 func_to_switch, u8 bus_width) { int retval; int i; @@ -1340,12 +1341,14 @@ static int sd_check_switch(struct rtsx_chip *chip, } retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group, - func_to_switch, bus_width); + func_to_switch, bus_width); if (retval == STATUS_SUCCESS) { u8 stat; retval = sd_check_switch_mode(chip, SD_SWITCH_MODE, - func_group, func_to_switch, bus_width); + func_group, + func_to_switch, + bus_width); if (retval == STATUS_SUCCESS) { switch_good = true; break; @@ -1364,7 +1367,7 @@ static int sd_check_switch(struct rtsx_chip *chip, } func_to_switch = downgrade_switch_mode(func_group, - func_to_switch); + func_to_switch); wait_timeout(20); } @@ -1385,8 +1388,8 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) u8 func_to_switch = 0; /* Get supported functions */ - retval = sd_check_switch_mode(chip, SD_CHECK_MODE, - NO_ARGUMENT, NO_ARGUMENT, bus_width); + retval = sd_check_switch_mode(chip, SD_CHECK_MODE, NO_ARGUMENT, + NO_ARGUMENT, bus_width); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1446,7 +1449,7 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) if (func_to_switch) { retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch, - bus_width); + bus_width); if (retval != STATUS_SUCCESS) { if (func_to_switch == SDR104_SUPPORT) { sd_card->sd_switch_fail = SDR104_SUPPORT_MASK; @@ -1534,7 +1537,7 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) if (func_to_switch <= CURRENT_LIMIT_800) { retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, - bus_width); + bus_width); if (retval != STATUS_SUCCESS) { if (sd_check_err_code(chip, SD_NO_CARD)) { rtsx_trace(chip); @@ -1596,8 +1599,8 @@ static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) cmd[3] = 0; cmd[4] = 0; - retval = sd_read_data(chip, SD_TM_AUTO_TUNING, - cmd, 5, 0x40, 1, SD_BUS_WIDTH_4, NULL, 0, 100); + retval = sd_read_data(chip, SD_TM_AUTO_TUNING, cmd, 5, 0x40, 1, + SD_BUS_WIDTH_4, NULL, 0, 100); if (retval != STATUS_SUCCESS) { (void)sd_wait_data_idle(chip); @@ -1624,7 +1627,7 @@ static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) dev_dbg(rtsx_dev(chip), "sd ddr tuning rx\n"); retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1636,8 +1639,8 @@ static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) cmd[3] = 0; cmd[4] = 0; - retval = sd_read_data(chip, SD_TM_NORMAL_READ, - cmd, 5, 64, 1, SD_BUS_WIDTH_4, NULL, 0, 100); + retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, + SD_BUS_WIDTH_4, NULL, 0, 100); if (retval != STATUS_SUCCESS) { (void)sd_wait_data_idle(chip); @@ -1676,8 +1679,8 @@ static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) cmd[3] = 0; cmd[4] = 0; - retval = sd_read_data(chip, SD_TM_NORMAL_READ, - cmd, 5, 0x200, 1, bus_width, NULL, 0, 100); + retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 0x200, 1, + bus_width, NULL, 0, 100); if (retval != STATUS_SUCCESS) { (void)sd_wait_data_idle(chip); @@ -1708,11 +1711,11 @@ static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) } retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) { if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) { rtsx_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); + SD_RSP_80CLK_TIMEOUT_EN, 0); rtsx_trace(chip); return STATUS_FAIL; } @@ -1770,8 +1773,8 @@ static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) cmd[3] = 0; cmd[4] = 0; - retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2, - cmd, 5, 16, 1, bus_width, sd_card->raw_csd, 16, 100); + retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2, cmd, 5, 16, 1, + bus_width, sd_card->raw_csd, 16, 100); if (retval != STATUS_SUCCESS) { rtsx_clear_sd_error(chip); rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); @@ -1787,7 +1790,7 @@ static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) } sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); + NULL, 0); return STATUS_SUCCESS; } @@ -1848,7 +1851,7 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, } if ((path[0].start == 0) && - (path[cont_path_cnt - 1].end == MAX_PHASE)) { + (path[cont_path_cnt - 1].end == MAX_PHASE)) { path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1; path[0].len += path[cont_path_cnt - 1].len; path[0].mid = path[0].start + path[0].len / 2; @@ -1992,7 +1995,7 @@ static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { sd_set_err_code(chip, SD_NO_CARD); rtsx_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); + SD_RSP_80CLK_TIMEOUT_EN, 0); rtsx_trace(chip); return STATUS_FAIL; } @@ -2002,10 +2005,10 @@ static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) continue; retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, - 0); + sd_card->sd_addr, SD_RSP_TYPE_R1, + NULL, 0); if ((retval == STATUS_SUCCESS) || - !sd_check_err_code(chip, SD_RSP_TIMEOUT)) + !sd_check_err_code(chip, SD_RSP_TIMEOUT)) phase_map |= 1 << i; } @@ -2131,7 +2134,7 @@ static int sd_ddr_tuning(struct rtsx_chip *chip) } } else { retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase, - TUNE_TX); + TUNE_TX); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -2167,7 +2170,7 @@ static int mmc_ddr_tuning(struct rtsx_chip *chip) } } else { retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase, - TUNE_TX); + TUNE_TX); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -2361,27 +2364,27 @@ int sd_pull_ctl_enable(struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5208)) { rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU); + XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD); + SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD); + XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU); + MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); + MS_D5_PD | MS_D4_PD); } else if (CHECK_PID(chip, 0x5288)) { if (CHECK_BARO_PKG(chip, QFN)) { rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - 0xA8); + 0xA8); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - 0x5A); + 0x5A); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - 0x95); + 0x95); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - 0xAA); + 0xAA); } } @@ -2499,8 +2502,8 @@ static int sd_read_lba0(struct rtsx_chip *chip) bus_width = SD_BUS_WIDTH_1; } - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, - 5, 512, 1, bus_width, NULL, 0, 100); + retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 512, 1, + bus_width, NULL, 0, 100); if (retval != STATUS_SUCCESS) { rtsx_clear_sd_error(chip); rtsx_trace(chip); @@ -2518,8 +2521,8 @@ static int sd_check_wp_state(struct rtsx_chip *chip) u16 sd_card_type; u8 cmd[5], buf[64]; - retval = sd_send_cmd_get_rsp(chip, APP_CMD, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); + retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -2532,12 +2535,12 @@ static int sd_check_wp_state(struct rtsx_chip *chip) cmd[4] = 0; retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, - SD_BUS_WIDTH_4, buf, 64, 250); + SD_BUS_WIDTH_4, buf, 64, 250); if (retval != STATUS_SUCCESS) { rtsx_clear_sd_error(chip); sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); rtsx_trace(chip); return STATUS_FAIL; } @@ -2605,7 +2608,7 @@ Switch_Fail: } retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, - SD_RSP_TYPE_R4, rsp, 5); + SD_RSP_TYPE_R4, rsp, 5); if (retval == STATUS_SUCCESS) { int func_num = (rsp[1] >> 4) & 0x07; @@ -2630,14 +2633,14 @@ Switch_Fail: /* Start Initialization Process of SD Card */ RTY_SD_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, - NULL, 0); + NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; wait_timeout(20); retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA, - SD_RSP_TYPE_R7, rsp, 5); + SD_RSP_TYPE_R7, rsp, 5); if (retval == STATUS_SUCCESS) { if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) { hi_cap_flow = true; @@ -2649,7 +2652,7 @@ RTY_SD_RST: voltage = SUPPORT_VOLTAGE; retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, - SD_RSP_TYPE_R0, NULL, 0); + SD_RSP_TYPE_R0, NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; @@ -2658,7 +2661,7 @@ RTY_SD_RST: do { retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1, - NULL, 0); + NULL, 0); if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { sd_set_err_code(chip, SD_NO_CARD); @@ -2673,7 +2676,7 @@ RTY_SD_RST: } retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, - SD_RSP_TYPE_R3, rsp, 5); + SD_RSP_TYPE_R3, rsp, 5); if (retval != STATUS_SUCCESS) { k++; if (k < 3) @@ -2709,13 +2712,13 @@ RTY_SD_RST: } retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, - NULL, 0); + NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; for (i = 0; i < 3; i++) { retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, - SD_RSP_TYPE_R6, rsp, 5); + SD_RSP_TYPE_R6, rsp, 5); if (retval != STATUS_SUCCESS) goto Status_Fail; @@ -2749,23 +2752,23 @@ SD_UNLOCK_ENTRY: #endif retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; if (support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; @@ -2775,7 +2778,7 @@ SD_UNLOCK_ENTRY: } retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, - NULL, 0); + NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; @@ -2819,12 +2822,12 @@ SD_UNLOCK_ENTRY: if (!support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) goto Status_Fail; } @@ -2867,7 +2870,7 @@ SD_UNLOCK_ENTRY: } sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); if (CHK_SD_DDR50(sd_card)) { retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); @@ -2932,7 +2935,7 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) int len; retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, - 0); + 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return SWITCH_FAIL; @@ -2957,8 +2960,8 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) return SWITCH_ERR; } - retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3, - NULL, 0, byte_cnt, 1, bus_width, buf, len, 100); + retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3, NULL, 0, byte_cnt, 1, + bus_width, buf, len, 100); if (retval != STATUS_SUCCESS) { rtsx_clear_sd_error(chip); rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0); @@ -2980,23 +2983,23 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) if (width == MMC_8BIT_BUS) rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, - 0xFF, 0x08); + 0xFF, 0x08); else rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, - 0xFF, 0x04); + 0xFF, 0x04); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END| - SD_CHECK_CRC7 | SD_RSP_LEN_6); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, SD_CALCULATE_CRC7 | + SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | + SD_CHECK_CRC7 | SD_RSP_LEN_6); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); + PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_NORMAL_READ | SD_TRANSFER_START); + SD_TM_NORMAL_READ | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); + SD_TRANSFER_END); rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0); if (width == MMC_8BIT_BUS) @@ -3024,9 +3027,9 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) arg = 0x03B70200; retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, - SD_RSP_TYPE_R1b, rsp, 5); + SD_RSP_TYPE_R1b, rsp, 5); if ((retval == STATUS_SUCCESS) && - !(rsp[4] & MMC_SWITCH_ERR)) + !(rsp[4] & MMC_SWITCH_ERR)) return SWITCH_SUCCESS; } } else { @@ -3041,9 +3044,9 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) arg = 0x03B70100; retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, - SD_RSP_TYPE_R1b, rsp, 5); + SD_RSP_TYPE_R1b, rsp, 5); if ((retval == STATUS_SUCCESS) && - !(rsp[4] & MMC_SWITCH_ERR)) + !(rsp[4] & MMC_SWITCH_ERR)) return SWITCH_SUCCESS; } } @@ -3065,7 +3068,7 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, - 0x40 | SEND_EXT_CSD); + 0x40 | SEND_EXT_CSD); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0); @@ -3077,14 +3080,14 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END| - SD_CHECK_CRC7 | SD_RSP_LEN_6); + SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | + SD_CHECK_CRC7 | SD_RSP_LEN_6); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); + PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_NORMAL_READ | SD_TRANSFER_START); + SD_TM_NORMAL_READ | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); + SD_TRANSFER_END); rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0); rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0); @@ -3097,7 +3100,7 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) if (retval == -ETIMEDOUT) { rtsx_clear_sd_error(chip); sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); } rtsx_trace(chip); return STATUS_FAIL; @@ -3106,7 +3109,7 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) ptr = rtsx_get_cmd_data(chip); if (ptr[0] & SD_TRANSFER_ERR) { sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); rtsx_trace(chip); return STATUS_FAIL; } @@ -3132,8 +3135,8 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) SET_MMC_26M(sd_card); } - retval = sd_send_cmd_get_rsp(chip, SWITCH, - 0x03B90100, SD_RSP_TYPE_R1b, rsp, 5); + retval = sd_send_cmd_get_rsp(chip, SWITCH, 0x03B90100, + SD_RSP_TYPE_R1b, rsp, 5); if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR)) CLR_MMC_HS(sd_card); } @@ -3201,7 +3204,7 @@ Switch_Fail: RTY_MMC_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, - NULL, 0); + NULL, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3215,11 +3218,11 @@ RTY_MMC_RST: } retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND, - (SUPPORT_VOLTAGE | 0x40000000), - SD_RSP_TYPE_R3, rsp, 5); + (SUPPORT_VOLTAGE | 0x40000000), + SD_RSP_TYPE_R3, rsp, 5); if (retval != STATUS_SUCCESS) { if (sd_check_err_code(chip, SD_BUSY) || - sd_check_err_code(chip, SD_TO_ERR)) { + sd_check_err_code(chip, SD_TO_ERR)) { k++; if (k < 20) { sd_clr_err_code(chip); @@ -3255,7 +3258,7 @@ RTY_MMC_RST: CLR_MMC_SECTOR_MODE(sd_card); retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, - NULL, 0); + NULL, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3263,7 +3266,7 @@ RTY_MMC_RST: sd_card->sd_addr = 0x00100000; retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, - SD_RSP_TYPE_R6, rsp, 5); + SD_RSP_TYPE_R6, rsp, 5); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3284,7 +3287,7 @@ RTY_MMC_RST: } retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, - NULL, 0); + NULL, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3407,7 +3410,7 @@ int reset_sd_card(struct rtsx_chip *chip) } if (chip->ignore_sd && CHK_SDIO_EXIST(chip) && - !CHK_SDIO_IGNORED(chip)) { + !CHK_SDIO_IGNORED(chip)) { if (chip->asic_code) { retval = sd_pull_ctl_enable(chip); if (retval != STATUS_SUCCESS) { @@ -3416,7 +3419,8 @@ int reset_sd_card(struct rtsx_chip *chip) } } else { retval = rtsx_write_register(chip, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, 0); + FPGA_SD_PULL_CTL_BIT | + 0x20, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3587,7 +3591,8 @@ static int wait_data_buf_ready(struct rtsx_chip *chip) sd_card->sd_data_buf_ready = 0; retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); + sd_card->sd_addr, SD_RSP_TYPE_R1, + NULL, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3616,7 +3621,7 @@ void sd_stop_seq_mode(struct rtsx_chip *chip) return; retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); + SD_RSP_TYPE_R1b, NULL, 0); if (retval != STATUS_SUCCESS) sd_set_err_code(chip, SD_STS_ERR); @@ -3679,7 +3684,7 @@ static inline int sd_auto_tune_clock(struct rtsx_chip *chip) } int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, - u16 sector_cnt) + u16 sector_cnt) { struct sd_info *sd_card = &chip->sd_card; u32 data_addr; @@ -3730,20 +3735,20 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, } if (sd_card->seq_mode && - ((sd_card->pre_dir != srb->sc_data_direction) || - ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != - start_sector))) { + ((sd_card->pre_dir != srb->sc_data_direction) || + ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != + start_sector))) { if ((sd_card->pre_sec_cnt < 0x80) && (sd_card->pre_dir == DMA_FROM_DEVICE) && !CHK_SD30_SPEED(sd_card) && !CHK_SD_HS(sd_card) && !CHK_MMC_HS(sd_card)) { sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); } - retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, - 0, SD_RSP_TYPE_R1b, NULL, 0); + retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, + SD_RSP_TYPE_R1b, NULL, 0); if (retval != STATUS_SUCCESS) { chip->rw_need_retry = 1; sd_set_err_code(chip, SD_STS_ERR); @@ -3765,7 +3770,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, && !CHK_SD_HS(sd_card) && !CHK_MMC_HS(sd_card)) { sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); + SD_RSP_TYPE_R1, NULL, 0); } } @@ -3774,21 +3779,21 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, - (u8)sector_cnt); + (u8)sector_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, - (u8)(sector_cnt >> 8)); + (u8)(sector_cnt >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); if (CHK_MMC_8BIT(sd_card)) rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, - 0x03, SD_BUS_WIDTH_8); + 0x03, SD_BUS_WIDTH_8); else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, - 0x03, SD_BUS_WIDTH_4); + 0x03, SD_BUS_WIDTH_4); else rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, - 0x03, SD_BUS_WIDTH_1); + 0x03, SD_BUS_WIDTH_1); if (sd_card->seq_mode) { cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16| @@ -3797,7 +3802,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, - DMA_512); + DMA_512); if (srb->sc_data_direction == DMA_FROM_DEVICE) { rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, @@ -3808,7 +3813,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, } rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); + SD_TRANSFER_END, SD_TRANSFER_END); rtsx_send_cmd_no_wait(chip); } else { @@ -3818,22 +3823,22 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | READ_MULTIPLE_BLOCK); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, - (u8)(data_addr >> 24)); + (u8)(data_addr >> 24)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, - (u8)(data_addr >> 16)); + (u8)(data_addr >> 16)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, - (u8)(data_addr >> 8)); + (u8)(data_addr >> 8)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, - (u8)data_addr); + (u8)data_addr); cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6; rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - cfg2); + cfg2); trans_dma_enable(srb->sc_data_direction, chip, - sector_cnt * 512, DMA_512); + sector_cnt * 512, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START); @@ -3861,7 +3866,8 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, } retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK, - data_addr, SD_RSP_TYPE_R1, NULL, 0); + data_addr, SD_RSP_TYPE_R1, + NULL, 0); if (retval != STATUS_SUCCESS) { chip->rw_need_retry = 1; rtsx_trace(chip); @@ -3874,10 +3880,10 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - cfg2); + cfg2); trans_dma_enable(srb->sc_data_direction, chip, - sector_cnt * 512, DMA_512); + sector_cnt * 512, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); @@ -3891,7 +3897,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, } retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), - scsi_bufflen(srb), scsi_sg_count(srb), + scsi_bufflen(srb), scsi_sg_count(srb), srb->sc_data_direction, chip->sd_timeout); if (retval < 0) { u8 stat = 0; @@ -3916,7 +3922,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, chip->rw_need_retry = 1; retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); + SD_RSP_TYPE_R1b, NULL, 0); if (retval != STATUS_SUCCESS) { sd_set_err_code(chip, SD_STS_ERR); rtsx_trace(chip); @@ -3984,8 +3990,9 @@ int soft_reset_sd_card(struct rtsx_chip *chip) return reset_sd(chip); } -int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, bool special_check) +int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, u32 arg, + u8 rsp_type, u8 *rsp, int rsp_len, + bool special_check) { int retval; int timeout = 100; @@ -4011,11 +4018,11 @@ RTY_SEND_CMD: rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, - 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); + 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); + SD_TRANSFER_END); if (rsp_type == SD_RSP_TYPE_R2) { for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; @@ -4084,7 +4091,7 @@ RTY_SEND_CMD: } if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) || - (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) { + (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) { if ((cmd_idx != STOP_TRANSMISSION) && !special_check) { if (ptr[1] & 0x80) { rtsx_trace(chip); @@ -4206,9 +4213,9 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if ((srb->cmnd[2] != 0x53) || (srb->cmnd[3] != 0x44) || - (srb->cmnd[4] != 0x20) || (srb->cmnd[5] != 0x43) || - (srb->cmnd[6] != 0x61) || (srb->cmnd[7] != 0x72) || - (srb->cmnd[8] != 0x64)) { + (srb->cmnd[4] != 0x20) || (srb->cmnd[5] != 0x43) || + (srb->cmnd[6] != 0x61) || (srb->cmnd[7] != 0x72) || + (srb->cmnd[8] != 0x64)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -4245,7 +4252,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) } static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, - int *rsp_len) + int *rsp_len) { if (!rsp_type || !rsp_len) return STATUS_FAIL; @@ -4339,7 +4346,7 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { if (CHK_MMC_8BIT(sd_card)) { retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, - SD_BUS_WIDTH_8); + SD_BUS_WIDTH_8); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return TRANSPORT_FAILED; @@ -4347,7 +4354,7 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, - SD_BUS_WIDTH_4); + SD_BUS_WIDTH_4); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return TRANSPORT_FAILED; @@ -4372,8 +4379,9 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (acmd) { retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, false); + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Cmd_Failed; @@ -4381,7 +4389,7 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, - sd_card->rsp, rsp_len, false); + sd_card->rsp, rsp_len, false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Cmd_Failed; @@ -4492,7 +4500,8 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (data_len < 512) { retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, - SD_RSP_TYPE_R1, NULL, 0, false); + SD_RSP_TYPE_R1, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Read_Cmd_Failed; @@ -4509,8 +4518,9 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (acmd) { retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, false); + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Read_Cmd_Failed; @@ -4539,7 +4549,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt, - blk_cnt, bus_width, buf, data_len, 2000); + blk_cnt, bus_width, buf, data_len, 2000); if (retval != STATUS_SUCCESS) { read_err = true; kfree(buf); @@ -4558,24 +4568,24 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - 0x02); + 0x02); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - 0x00); + 0x00); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, - 0xFF, (srb->cmnd[7] & 0xFE) >> 1); + 0xFF, (srb->cmnd[7] & 0xFE) >> 1); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, - 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); + 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, - 0x40 | cmd_idx); + 0x40 | cmd_idx); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, - srb->cmnd[3]); + srb->cmnd[3]); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, - srb->cmnd[4]); + srb->cmnd[4]); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, - srb->cmnd[5]); + srb->cmnd[5]); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, - srb->cmnd[6]); + srb->cmnd[6]); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); @@ -4583,13 +4593,14 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); + SD_TRANSFER_END, SD_TRANSFER_END); rtsx_send_cmd_no_wait(chip); retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), - scsi_bufflen(srb), scsi_sg_count(srb), - DMA_FROM_DEVICE, 10000); + scsi_bufflen(srb), + scsi_sg_count(srb), + DMA_FROM_DEVICE, 10000); if (retval < 0) { read_err = true; rtsx_clear_sd_error(chip); @@ -4617,8 +4628,9 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if (send_cmd12) { - retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, - 0, SD_RSP_TYPE_R1b, NULL, 0, false); + retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, + SD_RSP_TYPE_R1b, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Read_Cmd_Failed; @@ -4627,7 +4639,8 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (data_len < 512) { retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, - SD_RSP_TYPE_R1, NULL, 0, false); + SD_RSP_TYPE_R1, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Read_Cmd_Failed; @@ -4651,7 +4664,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) for (i = 0; i < 3; i++) { retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, + sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit); if (retval == STATUS_SUCCESS) @@ -4754,7 +4767,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { if (CHK_MMC_8BIT(sd_card)) { retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, - SD_BUS_WIDTH_8); + SD_BUS_WIDTH_8); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return TRANSPORT_FAILED; @@ -4762,7 +4775,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, - SD_BUS_WIDTH_4); + SD_BUS_WIDTH_4); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return TRANSPORT_FAILED; @@ -4779,7 +4792,8 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (data_len < 512) { retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, - SD_RSP_TYPE_R1, NULL, 0, false); + SD_RSP_TYPE_R1, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Write_Cmd_Failed; @@ -4796,8 +4810,9 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (acmd) { retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, false); + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Write_Cmd_Failed; @@ -4805,7 +4820,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, - sd_card->rsp, rsp_len, false); + sd_card->rsp, rsp_len, false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Write_Cmd_Failed; @@ -4832,7 +4847,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_init_cmd(chip); for (i = 0; i < 256; i++) { rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); + PPBUF_BASE2 + i, 0xFF, buf[i]); } retval = rtsx_send_cmd(chip, 0, 250); if (retval != STATUS_SUCCESS) { @@ -4844,7 +4859,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_init_cmd(chip); for (i = 256; i < data_len; i++) { rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); + PPBUF_BASE2 + i, 0xFF, buf[i]); } retval = rtsx_send_cmd(chip, 0, 250); if (retval != STATUS_SUCCESS) { @@ -4856,7 +4871,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_init_cmd(chip); for (i = 0; i < data_len; i++) { rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); + PPBUF_BASE2 + i, 0xFF, buf[i]); } retval = rtsx_send_cmd(chip, 0, 250); if (retval != STATUS_SUCCESS) { @@ -4871,20 +4886,20 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - srb->cmnd[8] & 0x03); + srb->cmnd[8] & 0x03); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - srb->cmnd[9]); + srb->cmnd[9]); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, - 0x00); + 0x00); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, - 0x01); + 0x01); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); + PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); + SD_TRANSFER_END, SD_TRANSFER_END); retval = rtsx_send_cmd(chip, SD_CARD, 250); } else if (!(data_len & 0x1FF)) { @@ -4893,24 +4908,25 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - 0x02); + 0x02); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - 0x00); + 0x00); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, - 0xFF, (srb->cmnd[7] & 0xFE) >> 1); + 0xFF, (srb->cmnd[7] & 0xFE) >> 1); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, - 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); + 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); + SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); + SD_TRANSFER_END, SD_TRANSFER_END); rtsx_send_cmd_no_wait(chip); retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), - scsi_bufflen(srb), scsi_sg_count(srb), - DMA_TO_DEVICE, 10000); + scsi_bufflen(srb), + scsi_sg_count(srb), + DMA_TO_DEVICE, 10000); } else { rtsx_trace(chip); @@ -4954,8 +4970,9 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if (send_cmd12) { - retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, - 0, SD_RSP_TYPE_R1b, NULL, 0, false); + retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, + SD_RSP_TYPE_R1b, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Write_Cmd_Failed; @@ -4964,7 +4981,8 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (data_len < 512) { retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, - SD_RSP_TYPE_R1, NULL, 0, false); + SD_RSP_TYPE_R1, NULL, 0, + false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto SD_Execute_Write_Cmd_Failed; @@ -4988,9 +5006,9 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) for (i = 0; i < 3; i++) { retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, - cmd13_checkbit); + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, + cmd13_checkbit); if (retval == STATUS_SUCCESS) break; } @@ -5122,9 +5140,9 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if ((srb->cmnd[2] != 0x53) || (srb->cmnd[3] != 0x44) || - (srb->cmnd[4] != 0x20) || (srb->cmnd[5] != 0x43) || - (srb->cmnd[6] != 0x61) || (srb->cmnd[7] != 0x72) || - (srb->cmnd[8] != 0x64)) { + (srb->cmnd[4] != 0x20) || (srb->cmnd[5] != 0x43) || + (srb->cmnd[6] != 0x61) || (srb->cmnd[7] != 0x72) || + (srb->cmnd[8] != 0x64)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; -- cgit v1.2.3 From 7fbe04f1ce6dc727cfd8a00f81748a59f1697b21 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:22 +0000 Subject: staging: rts5208: sd.c: Long line fixes Break up lines over 80 characters Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index 6229690cac52..eb6ccfc363e5 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -969,7 +969,9 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) } udelay(50); retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF, - PHASE_CHANGE | PHASE_NOT_RESET | sample_point); + PHASE_CHANGE | + PHASE_NOT_RESET | + sample_point); if (retval) { rtsx_trace(chip); return retval; @@ -983,7 +985,8 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) } udelay(50); retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF, - PHASE_NOT_RESET | sample_point); + PHASE_NOT_RESET | + sample_point); if (retval) { rtsx_trace(chip); return retval; @@ -2289,31 +2292,36 @@ static int sd_pull_ctl_disable(struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5208)) { retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD); + XD_D3_PD | SD_D7_PD | SD_CLK_PD | + SD_D5_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF, - SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD); + SD_D6_PD | SD_D0_PD | SD_D1_PD | + XD_D5_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF, - SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + SD_D4_PD | XD_CE_PD | XD_CLE_PD | + XD_CD_PU); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); + XD_RDY_PD | SD_D3_PD | SD_D2_PD | + XD_ALE_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + MS_INS_PU | SD_WP_PD | SD_CD_PU | + SD_CMD_PD); if (retval) { rtsx_trace(chip); return retval; -- cgit v1.2.3 From 57a3fcfa6b41927f3874fe305174191243a96b03 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:23 +0000 Subject: staging: rts5208: sd.c: CamelCase fixes Convert camel case lables to all lowercase Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 168 +++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 84 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index eb6ccfc363e5..e3a6dd5c6444 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -1002,18 +1002,18 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) retval = rtsx_send_cmd(chip, SD_CARD, 100); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto Fail; + goto fail; } val = *rtsx_get_cmd_data(chip); if (val & DCMPS_ERROR) { rtsx_trace(chip); - goto Fail; + goto fail; } if ((val & DCMPS_CURRENT_PHASE) != sample_point) { rtsx_trace(chip); - goto Fail; + goto fail; } retval = rtsx_write_register(chip, SD_DCMPS_CTL, @@ -1049,7 +1049,7 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) return STATUS_SUCCESS; -Fail: +fail: rtsx_read_register(chip, SD_VP_CTL, &val); dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val); rtsx_read_register(chip, SD_DCMPS_CTL, &val); @@ -1814,7 +1814,7 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, else final_phase = (u8)chip->sd_default_tx_phase; - goto Search_Finish; + goto search_finish; } cont_path_cnt = 0; @@ -1845,7 +1845,7 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, if (cont_path_cnt == 0) { dev_dbg(rtsx_dev(chip), "No continuous phase path\n"); - goto Search_Finish; + goto search_finish; } else { int idx = cont_path_cnt - 1; @@ -1912,7 +1912,7 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, } } -Search_Finish: +search_finish: dev_dbg(rtsx_dev(chip), "Final chosen phase: %d\n", final_phase); return final_phase; } @@ -2586,7 +2586,7 @@ static int reset_sd(struct rtsx_chip *chip) SET_SD(sd_card); -Switch_Fail: +switch_fail: i = 0; j = 0; @@ -2600,11 +2600,11 @@ Switch_Fail: retval = sd_prepare_reset(chip); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; retval = sd_dummy_clock(chip); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) { int rty_cnt = 0; @@ -2612,7 +2612,7 @@ Switch_Fail: for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) { if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { sd_set_err_code(chip, SD_NO_CARD); - goto Status_Fail; + goto status_fail; } retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, @@ -2624,7 +2624,7 @@ Switch_Fail: dev_dbg(rtsx_dev(chip), "SD_IO card (Function number: %d)!\n", func_num); chip->sd_io = 1; - goto Status_Fail; + goto status_fail; } break; @@ -2643,7 +2643,7 @@ RTY_SD_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; wait_timeout(20); @@ -2662,7 +2662,7 @@ RTY_SD_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; wait_timeout(20); } @@ -2673,14 +2673,14 @@ RTY_SD_RST: if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { sd_set_err_code(chip, SD_NO_CARD); - goto Status_Fail; + goto status_fail; } j++; if (j < 3) goto RTY_SD_RST; else - goto Status_Fail; + goto status_fail; } retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, @@ -2690,7 +2690,7 @@ RTY_SD_RST: if (k < 3) goto RTY_SD_RST; else - goto Status_Fail; + goto status_fail; } i++; @@ -2698,7 +2698,7 @@ RTY_SD_RST: } while (!(rsp[1] & 0x80) && (i < 255)); if (i == 255) - goto Status_Fail; + goto status_fail; if (hi_cap_flow) { if (rsp[1] & 0x40) @@ -2716,19 +2716,19 @@ RTY_SD_RST: if (support_1v8) { retval = sd_voltage_switch(chip); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; } retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; for (i = 0; i < 3; i++) { retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, rsp, 5); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; sd_card->sd_addr = (u32)rsp[1] << 24; sd_card->sd_addr += (u32)rsp[2] << 16; @@ -2739,17 +2739,17 @@ RTY_SD_RST: retval = sd_check_csd(chip, 1); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; retval = sd_select_card(chip, 1); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; #ifdef SUPPORT_SD_LOCK SD_UNLOCK_ENTRY: retval = sd_update_lock_status(chip); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; if (sd_card->sd_lock_status & SD_LOCKED) { sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST); @@ -2762,23 +2762,23 @@ SD_UNLOCK_ENTRY: retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; if (support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; switch_bus_width = SD_BUS_WIDTH_4; } else { @@ -2788,11 +2788,11 @@ SD_UNLOCK_ENTRY: retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; if (!(sd_card->raw_csd[4] & 0x40)) sd_dont_switch = true; @@ -2815,7 +2815,7 @@ SD_UNLOCK_ENTRY: sd_dont_switch = true; try_sdio = false; - goto Switch_Fail; + goto switch_fail; } } else { if (support_1v8) { @@ -2823,7 +2823,7 @@ SD_UNLOCK_ENTRY: sd_dont_switch = true; try_sdio = false; - goto Switch_Fail; + goto switch_fail; } } } @@ -2832,12 +2832,12 @@ SD_UNLOCK_ENTRY: retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; } #ifdef SUPPORT_SD_LOCK @@ -2856,7 +2856,7 @@ SD_UNLOCK_ENTRY: retval = sd_set_init_para(chip); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; if (CHK_SD_DDR50(sd_card)) retval = sd_ddr_tuning(chip); @@ -2865,15 +2865,15 @@ SD_UNLOCK_ENTRY: if (retval != STATUS_SUCCESS) { if (sd20_mode) { - goto Status_Fail; + goto status_fail; } else { retval = sd_init_power(chip); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; try_sdio = false; sd20_mode = true; - goto Switch_Fail; + goto switch_fail; } } @@ -2890,15 +2890,15 @@ SD_UNLOCK_ENTRY: retval = sd_read_lba0(chip); if (retval != STATUS_SUCCESS) { if (sd20_mode) { - goto Status_Fail; + goto status_fail; } else { retval = sd_init_power(chip); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; try_sdio = false; sd20_mode = true; - goto Switch_Fail; + goto switch_fail; } } } @@ -2906,7 +2906,7 @@ SD_UNLOCK_ENTRY: retval = sd_check_wp_state(chip); if (retval != STATUS_SUCCESS) - goto Status_Fail; + goto status_fail; chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; @@ -2929,7 +2929,7 @@ SD_UNLOCK_ENTRY: return STATUS_SUCCESS; -Status_Fail: +status_fail: rtsx_trace(chip); return STATUS_FAIL; } @@ -3201,7 +3201,7 @@ static int reset_mmc(struct rtsx_chip *chip) goto MMC_UNLOCK_ENTRY; #endif -Switch_Fail: +switch_fail: retval = sd_prepare_reset(chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -3330,7 +3330,7 @@ MMC_UNLOCK_ENTRY: } sd_card->mmc_dont_switch_bus = 1; rtsx_trace(chip); - goto Switch_Fail; + goto switch_fail; } } @@ -3356,7 +3356,7 @@ MMC_UNLOCK_ENTRY: switch_ddr = false; rtsx_trace(chip); - goto Switch_Fail; + goto switch_fail; } retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); @@ -3371,7 +3371,7 @@ MMC_UNLOCK_ENTRY: switch_ddr = false; rtsx_trace(chip); - goto Switch_Fail; + goto switch_fail; } } } @@ -4381,7 +4381,7 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = sd_select_card(chip, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Cmd_Failed; + goto sd_execute_cmd_failed; } } @@ -4392,7 +4392,7 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Cmd_Failed; + goto sd_execute_cmd_failed; } } @@ -4400,14 +4400,14 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) sd_card->rsp, rsp_len, false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Cmd_Failed; + goto sd_execute_cmd_failed; } if (standby) { retval = sd_select_card(chip, 1); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Cmd_Failed; + goto sd_execute_cmd_failed; } } @@ -4415,14 +4415,14 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = sd_update_lock_status(chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Cmd_Failed; + goto sd_execute_cmd_failed; } #endif scsi_set_resid(srb, 0); return TRANSPORT_GOOD; -SD_Execute_Cmd_Failed: +sd_execute_cmd_failed: sd_card->pre_cmd_err = 1; set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); release_sd_card(chip); @@ -4512,7 +4512,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } } @@ -4520,7 +4520,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = sd_select_card(chip, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } } @@ -4531,7 +4531,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } } @@ -4563,7 +4563,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) kfree(buf); rtsx_clear_sd_error(chip); rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } min_len = min(data_len, scsi_bufflen(srb)); @@ -4613,25 +4613,25 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) read_err = true; rtsx_clear_sd_error(chip); rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } } else { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } if (standby) { retval = sd_select_card(chip, 1); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } } @@ -4641,7 +4641,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } } @@ -4651,19 +4651,19 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } } @@ -4680,13 +4680,13 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Read_Cmd_Failed; + goto sd_execute_read_cmd_failed; } scsi_set_resid(srb, 0); return TRANSPORT_GOOD; -SD_Execute_Read_Cmd_Failed: +sd_execute_read_cmd_failed: sd_card->pre_cmd_err = 1; set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); if (read_err) @@ -4804,7 +4804,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } @@ -4812,7 +4812,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = sd_select_card(chip, 0); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } @@ -4823,7 +4823,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } @@ -4831,7 +4831,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) sd_card->rsp, rsp_len, false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } if (data_len <= 512) { @@ -4861,7 +4861,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { kfree(buf); rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } rtsx_init_cmd(chip); @@ -4873,7 +4873,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { kfree(buf); rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } else { rtsx_init_cmd(chip); @@ -4885,7 +4885,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { kfree(buf); rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } @@ -4938,14 +4938,14 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } if (retval < 0) { write_err = true; rtsx_clear_sd_error(chip); rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } #ifdef SUPPORT_SD_LOCK @@ -4973,7 +4973,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = sd_select_card(chip, 1); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } @@ -4983,7 +4983,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } @@ -4993,19 +4993,19 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) false); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } @@ -5022,7 +5022,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if (retval != STATUS_SUCCESS) { rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } #ifdef SUPPORT_SD_LOCK @@ -5050,7 +5050,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST); rtsx_trace(chip); - goto SD_Execute_Write_Cmd_Failed; + goto sd_execute_write_cmd_failed; } } @@ -5071,7 +5071,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) scsi_set_resid(srb, 0); return TRANSPORT_GOOD; -SD_Execute_Write_Cmd_Failed: +sd_execute_write_cmd_failed: sd_card->pre_cmd_err = 1; set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); if (write_err) -- cgit v1.2.3 From 3c3776441fec59fa6abd3961fb43ee82039e5566 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:24 +0000 Subject: staging: rts5208: sd.c: Fix logical continuations Checkpatch detected && at the beginning of new lines Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index e3a6dd5c6444..901e6555ca13 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -1404,22 +1404,22 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) for (i = 0; i < 4; i++) { switch ((u8)(chip->sd_speed_prior >> (i*8))) { case SDR104_SUPPORT: - if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK) - && chip->sdr104_en) { + if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK) && + chip->sdr104_en) { func_to_switch = SDR104_SUPPORT; } break; case DDR50_SUPPORT: - if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK) - && chip->ddr50_en) { + if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK) && + chip->ddr50_en) { func_to_switch = DDR50_SUPPORT; } break; case SDR50_SUPPORT: - if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK) - && chip->sdr50_en) { + if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK) && + chip->sdr50_en) { func_to_switch = SDR50_SUPPORT; } break; @@ -3746,11 +3746,11 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, ((sd_card->pre_dir != srb->sc_data_direction) || ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != start_sector))) { - if ((sd_card->pre_sec_cnt < 0x80) - && (sd_card->pre_dir == DMA_FROM_DEVICE) - && !CHK_SD30_SPEED(sd_card) - && !CHK_SD_HS(sd_card) - && !CHK_MMC_HS(sd_card)) { + if ((sd_card->pre_sec_cnt < 0x80) && + (sd_card->pre_dir == DMA_FROM_DEVICE) && + !CHK_SD30_SPEED(sd_card) && + !CHK_SD_HS(sd_card) && + !CHK_MMC_HS(sd_card)) { sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); } @@ -3773,10 +3773,10 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, goto RW_FAIL; } - if ((sd_card->pre_sec_cnt < 0x80) - && !CHK_SD30_SPEED(sd_card) - && !CHK_SD_HS(sd_card) - && !CHK_MMC_HS(sd_card)) { + if ((sd_card->pre_sec_cnt < 0x80) && + !CHK_SD30_SPEED(sd_card) && + !CHK_SD_HS(sd_card) && + !CHK_MMC_HS(sd_card)) { sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); } -- cgit v1.2.3 From fe421a75ec52854746af5a6f99cd24e524c6d18e Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:25 +0000 Subject: staging: rts5208: sd.c: Spacing cleanup Add/remove spaces to make things more readable Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index 901e6555ca13..bdd35b611f27 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -1402,7 +1402,7 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) /* Function Group 1: Access Mode */ for (i = 0; i < 4; i++) { - switch ((u8)(chip->sd_speed_prior >> (i*8))) { + switch ((u8)(chip->sd_speed_prior >> (i * 8))) { case SDR104_SUPPORT: if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK) && chip->sdr104_en) { @@ -1436,7 +1436,6 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) if (func_to_switch) break; - } dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_1: func_to_switch = 0x%02x", func_to_switch); @@ -1502,7 +1501,7 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) func_to_switch = 0xFF; for (i = 0; i < 4; i++) { - switch ((u8)(chip->sd_current_prior >> (i*8))) { + switch ((u8)(chip->sd_current_prior >> (i * 8))) { case CURRENT_LIMIT_800: if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK) func_to_switch = CURRENT_LIMIT_800; @@ -3804,7 +3803,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, 0x03, SD_BUS_WIDTH_1); if (sd_card->seq_mode) { - cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16| + cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); -- cgit v1.2.3 From 5426c164ff83ebe4ffc71bf2bdcc4efd7d4e17a5 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:26 +0000 Subject: staging: rts5208: Alignment fixes Cleaning up checkpatch issues Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_transport.h | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_transport.h b/drivers/staging/rts5208/rtsx_transport.h index 479137398c3d..99740c33f2fb 100644 --- a/drivers/staging/rts5208/rtsx_transport.h +++ b/drivers/staging/rts5208/rtsx_transport.h @@ -30,18 +30,21 @@ #define WAIT_TIME 2000 unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, - unsigned int *offset, enum xfer_buf_dir dir); -void rtsx_stor_set_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb); -void rtsx_stor_get_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb); + unsigned int buflen, + struct scsi_cmnd *srb, + unsigned int *index, + unsigned int *offset, + enum xfer_buf_dir dir); +void rtsx_stor_set_xfer_buf(unsigned char *buffer, unsigned int buflen, + struct scsi_cmnd *srb); +void rtsx_stor_get_xfer_buf(unsigned char *buffer, unsigned int buflen, + struct scsi_cmnd *srb); void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip); #define rtsx_init_cmd(chip) ((chip)->ci = 0) -void rtsx_add_cmd(struct rtsx_chip *chip, - u8 cmd_type, u16 reg_addr, u8 mask, u8 data); +void rtsx_add_cmd(struct rtsx_chip *chip, u8 cmd_type, u16 reg_addr, u8 mask, + u8 data); void rtsx_send_cmd_no_wait(struct rtsx_chip *chip); int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout); @@ -55,11 +58,12 @@ static inline u8 *rtsx_get_cmd_data(struct rtsx_chip *chip) } int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len, - int use_sg, enum dma_data_direction dma_dir, int timeout); + int use_sg, enum dma_data_direction dma_dir, + int timeout); -int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, - void *buf, size_t len, - int use_sg, unsigned int *index, unsigned int *offset, - enum dma_data_direction dma_dir, int timeout); +int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, void *buf, + size_t len, int use_sg, unsigned int *index, + unsigned int *offset, + enum dma_data_direction dma_dir, int timeout); #endif /* __REALTEK_RTSX_TRANSPORT_H */ -- cgit v1.2.3 From c3cca2d1b434143d801592e98c71b9ef63f4f044 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:27 +0000 Subject: staging: rts5208: Unnecessary parentheses cleanup Remove parentheses found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_sys.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_sys.h b/drivers/staging/rts5208/rtsx_sys.h index f49bed9ec76a..817700c0d794 100644 --- a/drivers/staging/rts5208/rtsx_sys.h +++ b/drivers/staging/rts5208/rtsx_sys.h @@ -32,9 +32,9 @@ static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip) { struct rtsx_dev *dev = chip->rtsx; - spin_lock(&(dev->reg_lock)); + spin_lock(&dev->reg_lock); rtsx_enter_ss(chip); - spin_unlock(&(dev->reg_lock)); + spin_unlock(&dev->reg_lock); } static inline void rtsx_reset_detected_cards(struct rtsx_chip *chip, int flag) -- cgit v1.2.3 From ea2030d5ae4bbc05a3cf401542b7bb38bbf99469 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:28 +0000 Subject: staging: rts5208: Alignment fix Fix issue found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_scsi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_scsi.h b/drivers/staging/rts5208/rtsx_scsi.h index 03dd76d6c859..30f3724848fe 100644 --- a/drivers/staging/rts5208/rtsx_scsi.h +++ b/drivers/staging/rts5208/rtsx_scsi.h @@ -136,8 +136,8 @@ void scsi_show_command(struct rtsx_chip *chip); void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type); void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, - u8 sense_key, u32 info, u8 asc, u8 ascq, - u8 sns_key_info0, u16 sns_key_info1); + u8 sense_key, u32 info, u8 asc, u8 ascq, + u8 sns_key_info0, u16 sns_key_info1); int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip); #endif /* __REALTEK_RTSX_SCSI_H */ -- cgit v1.2.3 From 7fb7a2fc40d7a35dcd5949b51d13fde29e2435cd Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:29 +0000 Subject: staging: rts5208: Fix typo in function name Searched the entire kernel for any references to this function and it appears safe to fix the typo Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_scsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index becb4bba166c..f2aab067e84e 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -3100,7 +3100,7 @@ static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) } #ifdef SUPPORT_CPRM -static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +static int sd_extension_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) { unsigned int lun = SCSI_LUN(srb); int result; @@ -3510,7 +3510,7 @@ int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip) case SD_EXECUTE_WRITE: case SD_GET_RSP: case SD_HW_RST: - result = sd_extention_cmnd(srb, chip); + result = sd_extension_cmnd(srb, chip); break; #endif -- cgit v1.2.3 From 3b8cd5aa1751cca738b8c6562d548a65218c9aab Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:30 +0000 Subject: staging: rts5208: Alignment fixes Align to match open parenthesis, found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_scsi.c | 201 ++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 100 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index f2aab067e84e..333d58a6a052 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -354,7 +354,7 @@ void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type) case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD: set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0, - ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1); + ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1); break; case SENSE_TYPE_FORMAT_IN_PROGRESS: @@ -397,7 +397,7 @@ void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type) } void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, - u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0, + u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0, u16 sns_key_info1) { struct sense_data_t *sense = &(chip->sense_buffer[lun]); @@ -444,7 +444,7 @@ static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_FAILED; } else if (sd_card->sd_lock_status & SD_LOCKED) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_READ_FORBIDDEN); + SENSE_TYPE_MEDIA_READ_FORBIDDEN); return TRANSPORT_FAILED; } } @@ -514,7 +514,7 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) #ifdef SUPPORT_MAGIC_GATE if ((chip->mspro_formatter_enable) && - (chip->lun2card[lun] & MS_CARD)) + (chip->lun2card[lun] & MS_CARD)) #else if (chip->mspro_formatter_enable) #endif @@ -603,7 +603,7 @@ static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (prevent) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -621,7 +621,7 @@ static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) sense = &(chip->sense_buffer[lun]); if ((get_lun_card(chip, lun) == MS_CARD) && - ms_card->pro_under_formatting) { + ms_card->pro_under_formatting) { if (ms_card->format_status == FORMAT_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); ms_card->pro_under_formatting = 0; @@ -629,7 +629,7 @@ static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else if (ms_card->format_status == FORMAT_IN_PROGRESS) { /* Logical Unit Not Ready Format in Progress */ set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, - 0, (u16)(ms_card->progress)); + 0, (u16)(ms_card->progress)); } else { /* Format Command Failed */ set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED); @@ -659,7 +659,7 @@ static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) } static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, - int lun, u8 *buf, int buf_len) + int lun, u8 *buf, int buf_len) { struct ms_info *ms_card = &(chip->ms_card); int sys_info_offset; @@ -797,7 +797,7 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) pageCode = srb->cmnd[2] & 0x3f; if ((pageCode == 0x3F) || (pageCode == 0x1C) || - (pageCode == 0x00) || + (pageCode == 0x00) || (pro_formatter_flag && (pageCode == 0x20))) { if (srb->cmnd[0] == MODE_SENSE) { if ((pageCode == 0x3F) || (pageCode == 0x20)) { @@ -896,7 +896,7 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (sd_card->sd_lock_status & SD_LOCKED) { dev_dbg(rtsx_dev(chip), "SD card locked!\n"); set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_READ_FORBIDDEN); + SENSE_TYPE_MEDIA_READ_FORBIDDEN); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -932,7 +932,7 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) * need to judge start_sec at first */ if ((start_sec > get_card_size(chip, lun)) || - ((start_sec + sec_cnt) > get_card_size(chip, lun))) { + ((start_sec + sec_cnt) > get_card_size(chip, lun))) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -947,7 +947,7 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) dev_dbg(rtsx_dev(chip), "read/write fail three times in succession\n"); if (srb->sc_data_direction == DMA_FROM_DEVICE) set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); else set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); @@ -959,7 +959,7 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (check_card_wp(chip, lun)) { dev_dbg(rtsx_dev(chip), "Write protected card!\n"); set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_PROTECT); + SENSE_TYPE_MEDIA_WRITE_PROTECT); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -977,7 +977,7 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); else set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); } retval = TRANSPORT_FAILED; rtsx_trace(chip); @@ -1025,8 +1025,8 @@ static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip) /* Capacity List Length */ if ((buf_len > 12) && chip->mspro_formatter_enable && - (chip->lun2card[lun] & MS_CARD) && - (!card || (card == MS_CARD))) { + (chip->lun2card[lun] & MS_CARD) && + (!card || (card == MS_CARD))) { buf[i++] = 0x10; desc_cnt = 2; } else { @@ -1143,7 +1143,7 @@ static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1153,7 +1153,7 @@ static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1195,7 +1195,7 @@ static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = spi_erase_eeprom_chip(chip); if (retval != STATUS_SUCCESS) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1216,7 +1216,7 @@ static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1247,7 +1247,7 @@ static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (addr < 0xFC00) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1271,7 +1271,7 @@ static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1305,7 +1305,7 @@ static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (addr < 0xFC00) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1333,7 +1333,7 @@ static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1399,7 +1399,7 @@ static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) if ((scsi_bufflen(srb) < buf_len) || !scsi_sglist(srb)) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1541,7 +1541,7 @@ static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) default: set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1556,7 +1556,7 @@ static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_disable_aspm(chip); if (chip->ss_en && - (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + (rtsx_get_stat(chip) == RTSX_STAT_SS)) { rtsx_exit_ss(chip); wait_timeout(100); } @@ -1565,7 +1565,7 @@ static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = rtsx_force_power_on(chip, SSC_PDCTL); if (retval != STATUS_SUCCESS) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1606,7 +1606,7 @@ static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) default: set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1648,14 +1648,15 @@ static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip) dev_dbg(rtsx_dev(chip), "Write to device\n"); retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len, - scsi_sg_count(srb), srb->sc_data_direction, 1000); + scsi_sg_count(srb), srb->sc_data_direction, + 1000); if (retval < 0) { if (srb->sc_data_direction == DMA_FROM_DEVICE) set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); else set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -1699,8 +1700,8 @@ static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) #ifdef SUPPORT_OCP status[8] = 0; - if (CHECK_LUN_MODE(chip, - SD_MS_2LUN) && (chip->lun2card[lun] == MS_CARD)) { + if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && + (chip->lun2card[lun] == MS_CARD)) { oc_now_mask = MS_OC_NOW; oc_ever_mask = MS_OC_EVER; } else { @@ -1804,7 +1805,7 @@ static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (!CHECK_PID(chip, 0x5208)) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1884,7 +1885,7 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip) cmd_type = srb->cmnd[4]; if (cmd_type > 2) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1903,7 +1904,7 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip) value = *(rtsx_get_cmd_data(chip) + idx); if (scsi_bufflen(srb) < 1) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -1971,7 +1972,7 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2039,7 +2040,7 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2050,7 +2051,7 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2090,7 +2091,7 @@ static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = spi_erase_eeprom_chip(chip); if (retval != STATUS_SUCCESS) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2098,13 +2099,13 @@ static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = spi_erase_eeprom_byte(chip, addr); if (retval != STATUS_SUCCESS) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } } else { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2139,7 +2140,7 @@ static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2149,7 +2150,7 @@ static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2204,7 +2205,7 @@ static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2242,7 +2243,7 @@ static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2252,7 +2253,7 @@ static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { vfree(buf); set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2311,7 +2312,7 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_OFF); + LDO3318_PWR_MASK, LDO_OFF); if (retval != STATUS_SUCCESS) { vfree(buf); rtsx_trace(chip); @@ -2321,7 +2322,7 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) wait_timeout(600); retval = rtsx_write_phy_register(chip, 0x08, - 0x4C00 | chip->phy_voltage); + 0x4C00 | chip->phy_voltage); if (retval != STATUS_SUCCESS) { vfree(buf); rtsx_trace(chip); @@ -2329,7 +2330,7 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_ON); + LDO3318_PWR_MASK, LDO_ON); if (retval != STATUS_SUCCESS) { vfree(buf); rtsx_trace(chip); @@ -2352,7 +2353,7 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = rtsx_write_efuse(chip, addr + i, buf[i]); if (retval != STATUS_SUCCESS) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); result = TRANSPORT_FAILED; rtsx_trace(chip); goto Exit; @@ -2370,7 +2371,7 @@ Exit: if (chip->asic_code) { retval = rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_OFF); + LDO3318_PWR_MASK, LDO_OFF); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return TRANSPORT_ERROR; @@ -2385,7 +2386,7 @@ Exit: } retval = rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_ON); + LDO3318_PWR_MASK, LDO_ON); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return TRANSPORT_ERROR; @@ -2425,7 +2426,7 @@ static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (func > func_max) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2439,7 +2440,7 @@ static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = rtsx_read_cfg_seq(chip, func, addr, buf, len); if (retval != STATUS_SUCCESS) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); vfree(buf); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -2484,7 +2485,7 @@ static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (func > func_max) { set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2593,7 +2594,7 @@ static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) default: set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2881,7 +2882,7 @@ static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) default: set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -2927,7 +2928,7 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) || - (srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) || + (srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) || (srb->cmnd[7] != 0x74)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); @@ -2941,7 +2942,7 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) wait_timeout(100); if (!check_card_ready(chip, lun) || - (get_card_size(chip, lun) == 0)) { + (get_card_size(chip, lun) == 0)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -3005,8 +3006,8 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) || - (srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) || - (srb->cmnd[7] != 0x44)) { + (srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) || + (srb->cmnd[7] != 0x44)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -3014,8 +3015,8 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) dev_info_id = srb->cmnd[3]; if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) || - (!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) || - !CHK_MSPRO(ms_card)) { + (!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) || + !CHK_MSPRO(ms_card)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -3208,8 +3209,8 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) switch (key_format) { case KF_GET_LOC_EKB: if ((scsi_bufflen(srb) == 0x41C) && - (srb->cmnd[8] == 0x04) && - (srb->cmnd[9] == 0x1C)) { + (srb->cmnd[8] == 0x04) && + (srb->cmnd[9] == 0x1C)) { retval = mg_get_local_EKB(srb, chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -3218,7 +3219,7 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -3226,8 +3227,8 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) case KF_RSP_CHG: if ((scsi_bufflen(srb) == 0x24) && - (srb->cmnd[8] == 0x00) && - (srb->cmnd[9] == 0x24)) { + (srb->cmnd[8] == 0x00) && + (srb->cmnd[9] == 0x24)) { retval = mg_get_rsp_chg(srb, chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -3236,7 +3237,7 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -3245,12 +3246,12 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) case KF_GET_ICV: ms_card->mg_entry_num = srb->cmnd[5]; if ((scsi_bufflen(srb) == 0x404) && - (srb->cmnd[8] == 0x04) && - (srb->cmnd[9] == 0x04) && - (srb->cmnd[2] == 0x00) && - (srb->cmnd[3] == 0x00) && - (srb->cmnd[4] == 0x00) && - (srb->cmnd[5] < 32)) { + (srb->cmnd[8] == 0x04) && + (srb->cmnd[9] == 0x04) && + (srb->cmnd[2] == 0x00) && + (srb->cmnd[3] == 0x00) && + (srb->cmnd[4] == 0x00) && + (srb->cmnd[5] < 32)) { retval = mg_get_ICV(srb, chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -3259,7 +3260,7 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -3326,8 +3327,8 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) switch (key_format) { case KF_SET_LEAF_ID: if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && - (srb->cmnd[9] == 0x0C)) { + (srb->cmnd[8] == 0x00) && + (srb->cmnd[9] == 0x0C)) { retval = mg_set_leaf_id(srb, chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -3336,7 +3337,7 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -3344,8 +3345,8 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) case KF_CHG_HOST: if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && - (srb->cmnd[9] == 0x0C)) { + (srb->cmnd[8] == 0x00) && + (srb->cmnd[9] == 0x0C)) { retval = mg_chg(srb, chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -3354,7 +3355,7 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -3362,8 +3363,8 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) case KF_RSP_HOST: if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && - (srb->cmnd[9] == 0x0C)) { + (srb->cmnd[8] == 0x00) && + (srb->cmnd[9] == 0x0C)) { retval = mg_rsp(srb, chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -3372,7 +3373,7 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -3381,12 +3382,12 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) case KF_SET_ICV: ms_card->mg_entry_num = srb->cmnd[5]; if ((scsi_bufflen(srb) == 0x404) && - (srb->cmnd[8] == 0x04) && - (srb->cmnd[9] == 0x04) && - (srb->cmnd[2] == 0x00) && - (srb->cmnd[3] == 0x00) && - (srb->cmnd[4] == 0x00) && - (srb->cmnd[5] < 32)) { + (srb->cmnd[8] == 0x04) && + (srb->cmnd[9] == 0x04) && + (srb->cmnd[2] == 0x00) && + (srb->cmnd[3] == 0x00) && + (srb->cmnd[4] == 0x00) && + (srb->cmnd[5] < 32)) { retval = mg_set_ICV(srb, chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); @@ -3395,7 +3396,7 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; } @@ -3427,9 +3428,9 @@ int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip) * REQUEST_SENSE and rs_ppstatus */ if (!((srb->cmnd[0] == VENDOR_CMND) && - (srb->cmnd[1] == SCSI_APP_CMD) && - (srb->cmnd[2] == GET_DEV_STATUS)) && - (srb->cmnd[0] != REQUEST_SENSE)) { + (srb->cmnd[1] == SCSI_APP_CMD) && + (srb->cmnd[2] == GET_DEV_STATUS)) && + (srb->cmnd[0] != REQUEST_SENSE)) { /* Logical Unit Not Ready Format in Progress */ set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0); @@ -3440,12 +3441,12 @@ int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip) #endif if ((get_lun_card(chip, lun) == MS_CARD) && - (ms_card->format_status == FORMAT_IN_PROGRESS)) { + (ms_card->format_status == FORMAT_IN_PROGRESS)) { if ((srb->cmnd[0] != REQUEST_SENSE) && - (srb->cmnd[0] != INQUIRY)) { + (srb->cmnd[0] != INQUIRY)) { /* Logical Unit Not Ready Format in Progress */ set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, - 0, (u16)(ms_card->progress)); + 0, (u16)(ms_card->progress)); rtsx_trace(chip); return TRANSPORT_FAILED; } -- cgit v1.2.3 From 33a1b1cd2e49b7fef41e83e263e095a73f7d3291 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:31 +0000 Subject: staging: rts5208: Remove parentheses Unnecessary parentheses found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_scsi.c | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index 333d58a6a052..ed8d3865072e 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -400,7 +400,7 @@ void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0, u16 sns_key_info1) { - struct sense_data_t *sense = &(chip->sense_buffer[lun]); + struct sense_data_t *sense = &chip->sense_buffer[lun]; sense->err_code = err_code; sense->sense_key = sense_key; @@ -436,7 +436,7 @@ static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip) #ifdef SUPPORT_SD_LOCK if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; if (sd_card->sd_lock_notify) { sd_card->sd_lock_notify = 0; @@ -615,10 +615,10 @@ static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) { struct sense_data_t *sense; unsigned int lun = SCSI_LUN(srb); - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; unsigned char *tmp, *buf; - sense = &(chip->sense_buffer[lun]); + sense = &chip->sense_buffer[lun]; if ((get_lun_card(chip, lun) == MS_CARD) && ms_card->pro_under_formatting) { @@ -661,7 +661,7 @@ static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, int lun, u8 *buf, int buf_len) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; int sys_info_offset; int data_size = buf_len; bool support_format = false; @@ -854,7 +854,7 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) { #ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; #endif unsigned int lun = SCSI_LUN(srb); int retval; @@ -1346,7 +1346,7 @@ static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; unsigned int lun = SCSI_LUN(srb); if (!check_card_ready(chip, lun)) { @@ -1522,9 +1522,9 @@ static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (srb->cmnd[3] == 1) { /* Variable Clock */ - struct xd_info *xd_card = &(chip->xd_card); - struct sd_info *sd_card = &(chip->sd_card); - struct ms_info *ms_card = &(chip->ms_card); + struct xd_info *xd_card = &chip->xd_card; + struct sd_info *sd_card = &chip->sd_card; + struct ms_info *ms_card = &chip->ms_card; switch (srb->cmnd[4]) { case XD_CARD: @@ -1586,9 +1586,9 @@ static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) unsigned int lun = SCSI_LUN(srb); if (srb->cmnd[3] == 1) { - struct xd_info *xd_card = &(chip->xd_card); - struct sd_info *sd_card = &(chip->sd_card); - struct ms_info *ms_card = &(chip->ms_card); + struct xd_info *xd_card = &chip->xd_card; + struct sd_info *sd_card = &chip->sd_card; + struct ms_info *ms_card = &chip->ms_card; u8 tmp; switch (srb->cmnd[4]) { @@ -1668,8 +1668,8 @@ static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip) static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); - struct ms_info *ms_card = &(chip->ms_card); + struct sd_info *sd_card = &chip->sd_card; + struct ms_info *ms_card = &chip->ms_card; int buf_len; unsigned int lun = SCSI_LUN(srb); u8 card = get_lun_card(chip, lun); @@ -2671,7 +2671,7 @@ static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (get_lun_card(chip, lun) == XD_CARD) { rtsx_status[13] = 0x40; } else if (get_lun_card(chip, lun) == SD_CARD) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; rtsx_status[13] = 0x20; if (CHK_SD(sd_card)) { @@ -2687,7 +2687,7 @@ static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_status[13] |= 0x04; } } else if (get_lun_card(chip, lun) == MS_CARD) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; if (CHK_MSPRO(ms_card)) { rtsx_status[13] = 0x38; @@ -2916,7 +2916,7 @@ void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip) static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; unsigned int lun = SCSI_LUN(srb); bool quick_format; int retval; @@ -2987,7 +2987,7 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) #ifdef SUPPORT_PCGL_1P18 static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; unsigned int lun = SCSI_LUN(srb); u8 dev_info_id, data_len; u8 *buf; @@ -3165,7 +3165,7 @@ static int sd_extension_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) #ifdef SUPPORT_MAGIC_GATE static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; unsigned int lun = SCSI_LUN(srb); int retval; u8 key_format; @@ -3278,7 +3278,7 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; unsigned int lun = SCSI_LUN(srb); int retval; u8 key_format; @@ -3416,9 +3416,9 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip) { #ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; #endif - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; unsigned int lun = SCSI_LUN(srb); int result; -- cgit v1.2.3 From 904af7d5b529be94c9b40391af40baeffc5e5101 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:32 +0000 Subject: staging: rts5208: CamelCase fixes Change camel case variables found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_scsi.c | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index ed8d3865072e..9c6d257e41ec 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -754,10 +754,10 @@ static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) { unsigned int lun = SCSI_LUN(srb); - unsigned int dataSize; + unsigned int data_size; int status; bool pro_formatter_flag; - unsigned char pageCode, *buf; + unsigned char page_code, *buf; u8 card = get_lun_card(chip, lun); #ifndef SUPPORT_MAGIC_GATE @@ -770,11 +770,11 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) #endif pro_formatter_flag = false; - dataSize = 8; + data_size = 8; #ifdef SUPPORT_MAGIC_GATE if ((chip->lun2card[lun] & MS_CARD)) { if (!card || (card == MS_CARD)) { - dataSize = 108; + data_size = 108; if (chip->mspro_formatter_enable) pro_formatter_flag = true; } @@ -783,28 +783,28 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (card == MS_CARD) { if (chip->mspro_formatter_enable) { pro_formatter_flag = true; - dataSize = 108; + data_size = 108; } } #endif - buf = kmalloc(dataSize, GFP_KERNEL); + buf = kmalloc(data_size, GFP_KERNEL); if (!buf) { rtsx_trace(chip); return TRANSPORT_ERROR; } - pageCode = srb->cmnd[2] & 0x3f; + page_code = srb->cmnd[2] & 0x3f; - if ((pageCode == 0x3F) || (pageCode == 0x1C) || - (pageCode == 0x00) || - (pro_formatter_flag && (pageCode == 0x20))) { + if ((page_code == 0x3F) || (page_code == 0x1C) || + (page_code == 0x00) || + (pro_formatter_flag && (page_code == 0x20))) { if (srb->cmnd[0] == MODE_SENSE) { - if ((pageCode == 0x3F) || (pageCode == 0x20)) { + if ((page_code == 0x3F) || (page_code == 0x20)) { ms_mode_sense(chip, srb->cmnd[0], - lun, buf, dataSize); + lun, buf, data_size); } else { - dataSize = 4; + data_size = 4; buf[0] = 0x03; buf[1] = 0x00; if (check_card_wp(chip, lun)) @@ -815,11 +815,11 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf[3] = 0x00; } } else { - if ((pageCode == 0x3F) || (pageCode == 0x20)) { + if ((page_code == 0x3F) || (page_code == 0x20)) { ms_mode_sense(chip, srb->cmnd[0], - lun, buf, dataSize); + lun, buf, data_size); } else { - dataSize = 8; + data_size = 8; buf[0] = 0x00; buf[1] = 0x06; buf[2] = 0x00; @@ -842,7 +842,7 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (status == TRANSPORT_GOOD) { unsigned int len = min_t(unsigned int, scsi_bufflen(srb), - dataSize); + data_size); rtsx_stor_set_xfer_buf(buf, len, srb); scsi_set_resid(srb, scsi_bufflen(srb) - len); } @@ -981,7 +981,7 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = TRANSPORT_FAILED; rtsx_trace(chip); - goto Exit; + goto exit; } else { chip->rw_fail_cnt[lun] = 0; retval = TRANSPORT_GOOD; @@ -989,7 +989,7 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) scsi_set_resid(srb, 0); -Exit: +exit: return retval; } @@ -2356,11 +2356,11 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) SENSE_TYPE_MEDIA_WRITE_ERR); result = TRANSPORT_FAILED; rtsx_trace(chip); - goto Exit; + goto exit; } } -Exit: +exit: vfree(buf); retval = card_power_off(chip, SPI_CARD); -- cgit v1.2.3 From f4bfffb9594ea30934fdd4045754aed25cc2ad6f Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:33 +0000 Subject: staging: rts5208: Remove multiple assignment Assign values to variables on their own lines instead of using multiple assignment Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_scsi.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index 9c6d257e41ec..b42c236274c7 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -3022,10 +3022,13 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_FAILED; } - if (dev_info_id == 0x15) - buf_len = data_len = 0x3A; - else - buf_len = data_len = 0x6A; + if (dev_info_id == 0x15) { + buf_len = 0x3A; + data_len = 0x3A; + } else { + buf_len = 0x6A; + data_len = 0x6A; + } buf = kmalloc(buf_len, GFP_KERNEL); if (!buf) { -- cgit v1.2.3 From 44000fe6f173e86474ef909fdc62541d6b756713 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:34 +0000 Subject: staging: rts5208: Add braces to if() Braces should be around every part of the if block and not just the else if Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_scsi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index b42c236274c7..aac3435df32d 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -2896,14 +2896,15 @@ void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip) unsigned int lun = SCSI_LUN(srb); u16 sec_cnt; - if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) + if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) { sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; - else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) { + } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) { sec_cnt = srb->cmnd[4]; if (sec_cnt == 0) sec_cnt = 256; - } else + } else { return; + } if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) { toggle_gpio(chip, LED_GPIO); -- cgit v1.2.3 From 3f19de3681d58135b502230eb01ec764d73be16c Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:35 +0000 Subject: staging: rts5208: Add space around operator Spaces are preferred around operators for readability Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index e725b10ed087..575e5734f2a5 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -149,7 +149,7 @@ static inline void get_current_time(u8 *timeval_buf, int buf_len) getnstimeofday64(&ts64); - tv_usec = ts64.tv_nsec/NSEC_PER_USEC; + tv_usec = ts64.tv_nsec / NSEC_PER_USEC; timeval_buf[0] = (u8)(ts64.tv_sec >> 24); timeval_buf[1] = (u8)(ts64.tv_sec >> 16); -- cgit v1.2.3 From 33f28123af71bab88514d68ab2cdd54cff6dcf3e Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:36 +0000 Subject: staging: rts5208: Alignment fixes Fix alignment issues that checkpatch found Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_chip.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index f36642817c6e..daa8ff2208c1 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -957,12 +957,12 @@ void rtsx_stop_cmd(struct rtsx_chip *chip, int card); int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data); int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data); int rtsx_write_cfg_dw(struct rtsx_chip *chip, - u8 func_no, u16 addr, u32 mask, u32 val); + u8 func_no, u16 addr, u32 mask, u32 val); int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val); int rtsx_write_cfg_seq(struct rtsx_chip *chip, - u8 func, u16 addr, u8 *buf, int len); + u8 func, u16 addr, u8 *buf, int len); int rtsx_read_cfg_seq(struct rtsx_chip *chip, - u8 func, u16 addr, u8 *buf, int len); + u8 func, u16 addr, u8 *buf, int len); int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val); int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val); int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val); -- cgit v1.2.3 From 15794518d7849233aeb015bd99e02b777a68978b Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:37 +0000 Subject: staging: rts5208: Long lines fixes Break up long lines in rtsx_chip.h Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_chip.h | 85 +++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index daa8ff2208c1..fd10ee6a5731 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -285,7 +285,8 @@ struct sense_data_t { #define CARD_INT (XD_INT | MS_INT | SD_INT) #define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT) -#define RTSX_INT (CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | GPIO0_INT | OC_INT) +#define RTSX_INT (CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | \ + GPIO0_INT | OC_INT) #define CARD_EXIST (XD_EXIST | MS_EXIST | SD_EXIST) @@ -393,14 +394,23 @@ struct zone_entry { /* SD card */ #define CHK_SD(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_SD) -#define CHK_SD_HS(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HS)) -#define CHK_SD_SDR50(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR50)) -#define CHK_SD_DDR50(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_DDR50)) -#define CHK_SD_SDR104(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR104)) -#define CHK_SD_HCXC(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HCXC)) -#define CHK_SD_HC(sd_card) (CHK_SD_HCXC(sd_card) && ((sd_card)->capacity <= 0x4000000)) -#define CHK_SD_XC(sd_card) (CHK_SD_HCXC(sd_card) && ((sd_card)->capacity > 0x4000000)) -#define CHK_SD30_SPEED(sd_card) (CHK_SD_SDR50(sd_card) || CHK_SD_DDR50(sd_card) || CHK_SD_SDR104(sd_card)) +#define CHK_SD_HS(sd_card) (CHK_SD(sd_card) && \ + ((sd_card)->sd_type & SD_HS)) +#define CHK_SD_SDR50(sd_card) (CHK_SD(sd_card) && \ + ((sd_card)->sd_type & SD_SDR50)) +#define CHK_SD_DDR50(sd_card) (CHK_SD(sd_card) && \ + ((sd_card)->sd_type & SD_DDR50)) +#define CHK_SD_SDR104(sd_card) (CHK_SD(sd_card) && \ + ((sd_card)->sd_type & SD_SDR104)) +#define CHK_SD_HCXC(sd_card) (CHK_SD(sd_card) && \ + ((sd_card)->sd_type & SD_HCXC)) +#define CHK_SD_HC(sd_card) (CHK_SD_HCXC(sd_card) && \ + ((sd_card)->capacity <= 0x4000000)) +#define CHK_SD_XC(sd_card) (CHK_SD_HCXC(sd_card) && \ + ((sd_card)->capacity > 0x4000000)) +#define CHK_SD30_SPEED(sd_card) (CHK_SD_SDR50(sd_card) || \ + CHK_SD_DDR50(sd_card) || \ + CHK_SD_SDR104(sd_card)) #define SET_SD(sd_card) ((sd_card)->sd_type = TYPE_SD) #define SET_SD_HS(sd_card) ((sd_card)->sd_type |= SD_HS) @@ -416,13 +426,20 @@ struct zone_entry { #define CLR_SD_HCXC(sd_card) ((sd_card)->sd_type &= ~SD_HCXC) /* MMC card */ -#define CHK_MMC(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_MMC) -#define CHK_MMC_26M(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_26M)) -#define CHK_MMC_52M(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_52M)) -#define CHK_MMC_4BIT(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_4BIT)) -#define CHK_MMC_8BIT(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_8BIT)) -#define CHK_MMC_SECTOR_MODE(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_SECTOR_MODE)) -#define CHK_MMC_DDR52(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_DDR52)) +#define CHK_MMC(sd_card) (((sd_card)->sd_type & 0xFF) == \ + TYPE_MMC) +#define CHK_MMC_26M(sd_card) (CHK_MMC(sd_card) && \ + ((sd_card)->sd_type & MMC_26M)) +#define CHK_MMC_52M(sd_card) (CHK_MMC(sd_card) && \ + ((sd_card)->sd_type & MMC_52M)) +#define CHK_MMC_4BIT(sd_card) (CHK_MMC(sd_card) && \ + ((sd_card)->sd_type & MMC_4BIT)) +#define CHK_MMC_8BIT(sd_card) (CHK_MMC(sd_card) && \ + ((sd_card)->sd_type & MMC_8BIT)) +#define CHK_MMC_SECTOR_MODE(sd_card) (CHK_MMC(sd_card) && \ + ((sd_card)->sd_type & MMC_SECTOR_MODE)) +#define CHK_MMC_DDR52(sd_card) (CHK_MMC(sd_card) && \ + ((sd_card)->sd_type & MMC_DDR52)) #define SET_MMC(sd_card) ((sd_card)->sd_type = TYPE_MMC) #define SET_MMC_26M(sd_card) ((sd_card)->sd_type |= MMC_26M) @@ -439,7 +456,8 @@ struct zone_entry { #define CLR_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type &= ~MMC_SECTOR_MODE) #define CLR_MMC_DDR52(sd_card) ((sd_card)->sd_type &= ~MMC_DDR52) -#define CHK_MMC_HS(sd_card) (CHK_MMC_52M(sd_card) && CHK_MMC_26M(sd_card)) +#define CHK_MMC_HS(sd_card) (CHK_MMC_52M(sd_card) && \ + CHK_MMC_26M(sd_card)) #define CLR_MMC_HS(sd_card) \ do { \ CLR_MMC_DDR52(sd_card); \ @@ -450,12 +468,18 @@ do { \ #define SD_SUPPORT_CLASS_TEN 0x01 #define SD_SUPPORT_1V8 0x02 -#define SD_SET_CLASS_TEN(sd_card) ((sd_card)->sd_setting |= SD_SUPPORT_CLASS_TEN) -#define SD_CHK_CLASS_TEN(sd_card) ((sd_card)->sd_setting & SD_SUPPORT_CLASS_TEN) -#define SD_CLR_CLASS_TEN(sd_card) ((sd_card)->sd_setting &= ~SD_SUPPORT_CLASS_TEN) -#define SD_SET_1V8(sd_card) ((sd_card)->sd_setting |= SD_SUPPORT_1V8) -#define SD_CHK_1V8(sd_card) ((sd_card)->sd_setting & SD_SUPPORT_1V8) -#define SD_CLR_1V8(sd_card) ((sd_card)->sd_setting &= ~SD_SUPPORT_1V8) +#define SD_SET_CLASS_TEN(sd_card) ((sd_card)->sd_setting |= \ + SD_SUPPORT_CLASS_TEN) +#define SD_CHK_CLASS_TEN(sd_card) ((sd_card)->sd_setting & \ + SD_SUPPORT_CLASS_TEN) +#define SD_CLR_CLASS_TEN(sd_card) ((sd_card)->sd_setting &= \ + ~SD_SUPPORT_CLASS_TEN) +#define SD_SET_1V8(sd_card) ((sd_card)->sd_setting |= \ + SD_SUPPORT_1V8) +#define SD_CHK_1V8(sd_card) ((sd_card)->sd_setting & \ + SD_SUPPORT_1V8) +#define SD_CLR_1V8(sd_card) ((sd_card)->sd_setting &= \ + ~SD_SUPPORT_1V8) struct sd_info { u16 sd_type; @@ -544,9 +568,12 @@ struct xd_info { #define HG8BIT (MS_HG | MS_8BIT) #define CHK_MSPRO(ms_card) (((ms_card)->ms_type & 0xFF) == TYPE_MSPRO) -#define CHK_HG8BIT(ms_card) (CHK_MSPRO(ms_card) && (((ms_card)->ms_type & HG8BIT) == HG8BIT)) -#define CHK_MSXC(ms_card) (CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_XC)) -#define CHK_MSHG(ms_card) (CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_HG)) +#define CHK_HG8BIT(ms_card) (CHK_MSPRO(ms_card) && \ + (((ms_card)->ms_type & HG8BIT) == HG8BIT)) +#define CHK_MSXC(ms_card) (CHK_MSPRO(ms_card) && \ + ((ms_card)->ms_type & MS_XC)) +#define CHK_MSHG(ms_card) (CHK_MSPRO(ms_card) && \ + ((ms_card)->ms_type & MS_HG)) #define CHK_MS8BIT(ms_card) (((ms_card)->ms_type & MS_8BIT)) #define CHK_MS4BIT(ms_card) (((ms_card)->ms_type & MS_4BIT)) @@ -679,8 +706,10 @@ struct trace_msg_t { #define CLR_SDIO_EXIST(chip) ((chip)->sdio_func_exist &= ~SDIO_EXIST) #define CHK_SDIO_IGNORED(chip) ((chip)->sdio_func_exist & SDIO_IGNORED) -#define SET_SDIO_IGNORED(chip) ((chip)->sdio_func_exist |= SDIO_IGNORED) -#define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= ~SDIO_IGNORED) +#define SET_SDIO_IGNORED(chip) ((chip)->sdio_func_exist |= \ + SDIO_IGNORED) +#define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= \ + ~SDIO_IGNORED) struct rtsx_chip { struct rtsx_dev *rtsx; -- cgit v1.2.3 From 2c6b3b934787eb79257f826d0637d55a02a29c4b Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:38 +0000 Subject: staging: rts5208: Prefer using BIT macro Replace all instances of (1 << x) with BIT(x) to satisfy checkpatch check messages Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_chip.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index fd10ee6a5731..aaf4fae4768c 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -291,18 +291,18 @@ struct sense_data_t { #define CARD_EXIST (XD_EXIST | MS_EXIST | SD_EXIST) /* Bus interrupt enable register */ -#define CMD_DONE_INT_EN (1 << 31) -#define DATA_DONE_INT_EN (1 << 30) -#define TRANS_OK_INT_EN (1 << 29) -#define TRANS_FAIL_INT_EN (1 << 28) -#define XD_INT_EN (1 << 27) -#define MS_INT_EN (1 << 26) -#define SD_INT_EN (1 << 25) -#define GPIO0_INT_EN (1 << 24) -#define OC_INT_EN (1 << 23) +#define CMD_DONE_INT_EN BIT(31) +#define DATA_DONE_INT_EN BIT(30) +#define TRANS_OK_INT_EN BIT(29) +#define TRANS_FAIL_INT_EN BIT(28) +#define XD_INT_EN BIT(27) +#define MS_INT_EN BIT(26) +#define SD_INT_EN BIT(25) +#define GPIO0_INT_EN BIT(24) +#define OC_INT_EN BIT(23) #define DELINK_INT_EN GPIO0_INT_EN -#define MS_OC_INT_EN (1 << 23) -#define SD_OC_INT_EN (1 << 22) +#define MS_OC_INT_EN BIT(23) +#define SD_OC_INT_EN BIT(22) #define READ_REG_CMD 0 #define WRITE_REG_CMD 1 @@ -319,10 +319,10 @@ struct sense_data_t { #define MS_NR 3 #define XD_NR 4 #define SPI_NR 7 -#define SD_CARD (1 << SD_NR) -#define MS_CARD (1 << MS_NR) -#define XD_CARD (1 << XD_NR) -#define SPI_CARD (1 << SPI_NR) +#define SD_CARD BIT(SD_NR) +#define MS_CARD BIT(MS_NR) +#define XD_CARD BIT(XD_NR) +#define SPI_CARD BIT(SPI_NR) #define MAX_ALLOWED_LUN_CNT 8 -- cgit v1.2.3 From 5d2de0d9b778e2b26f108bec1e3e56bd2902c5ab Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:39 +0000 Subject: staging: rts5208: Parenthesis alignment Matching open parenthesis Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_card.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_card.h b/drivers/staging/rts5208/rtsx_card.h index 56df9a431d6d..6e8c7eaafefe 100644 --- a/drivers/staging/rts5208/rtsx_card.h +++ b/drivers/staging/rts5208/rtsx_card.h @@ -1011,9 +1011,9 @@ int switch_normal_clock(struct rtsx_chip *chip, int clk); int enable_card_clock(struct rtsx_chip *chip, u8 card); int disable_card_clock(struct rtsx_chip *chip, u8 card); int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 sec_addr, u16 sec_cnt); + u32 sec_addr, u16 sec_cnt); void trans_dma_enable(enum dma_data_direction dir, - struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size); + struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size); void toggle_gpio(struct rtsx_chip *chip, u8 gpio); void turn_on_led(struct rtsx_chip *chip, u8 gpio); void turn_off_led(struct rtsx_chip *chip, u8 gpio); @@ -1033,7 +1033,7 @@ static inline u32 get_card_size(struct rtsx_chip *chip, unsigned int lun) struct sd_info *sd_card = &(chip->sd_card); if ((get_lun_card(chip, lun) == SD_CARD) && - (sd_card->sd_lock_status & SD_LOCKED)) + (sd_card->sd_lock_status & SD_LOCKED)) return 0; return chip->capacity[lun]; @@ -1073,25 +1073,25 @@ static inline int card_power_off_all(struct rtsx_chip *chip) static inline void rtsx_clear_xd_error(struct rtsx_chip *chip) { rtsx_write_register(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, - XD_STOP | XD_CLR_ERR); + XD_STOP | XD_CLR_ERR); } static inline void rtsx_clear_sd_error(struct rtsx_chip *chip) { rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); + SD_STOP | SD_CLR_ERR); } static inline void rtsx_clear_ms_error(struct rtsx_chip *chip) { rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, - MS_STOP | MS_CLR_ERR); + MS_STOP | MS_CLR_ERR); } static inline void rtsx_clear_spi_error(struct rtsx_chip *chip) { rtsx_write_register(chip, CARD_STOP, SPI_STOP | SPI_CLR_ERR, - SPI_STOP | SPI_CLR_ERR); + SPI_STOP | SPI_CLR_ERR); } #ifdef SUPPORT_SDIO_ASPM -- cgit v1.2.3 From f5becff72881d1249ea81e84d8a709f7eb68a5fd Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:40 +0000 Subject: staging: rts5208: Unecessary parantheses Remove parentheses to stop checkpatch check message Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_card.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_card.h b/drivers/staging/rts5208/rtsx_card.h index 6e8c7eaafefe..aa37705bae39 100644 --- a/drivers/staging/rts5208/rtsx_card.h +++ b/drivers/staging/rts5208/rtsx_card.h @@ -1030,7 +1030,7 @@ u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun); static inline u32 get_card_size(struct rtsx_chip *chip, unsigned int lun) { #ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; if ((get_lun_card(chip, lun) == SD_CARD) && (sd_card->sd_lock_status & SD_LOCKED)) -- cgit v1.2.3 From e379c79baeab4b422b69580ada2a2cb99f918d20 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:41 +0000 Subject: staging: rts5208: Parenthesis alignment Fix alignment to stop checkpath check messages Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_card.c | 42 +++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index 97717744962d..83748fc7f7e7 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -100,9 +100,9 @@ void try_to_switch_sdio_ctrl(struct rtsx_chip *chip) if ((reg1 & 0xC0) && (reg2 & 0xC0)) { chip->sd_int = 1; rtsx_write_register(chip, SDIO_CTRL, 0xFF, - SDIO_BUS_CTRL | SDIO_CD_CTRL); + SDIO_BUS_CTRL | SDIO_CD_CTRL); rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_ON); + LDO3318_PWR_MASK, LDO_ON); } } @@ -133,7 +133,7 @@ void dynamic_configure_sdio_aspm(struct rtsx_chip *chip) if (!chip->sdio_aspm) { dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n"); rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, - 0x30 | (chip->aspm_level[1] << 2)); + 0x30 | (chip->aspm_level[1] << 2)); chip->sdio_aspm = 1; } } else { @@ -300,7 +300,7 @@ static void release_sdio(struct rtsx_chip *chip) { if (chip->sd_io) { rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); + SD_STOP | SD_CLR_ERR); if (chip->chip_insert_with_sdio) { chip->chip_insert_with_sdio = 0; @@ -449,7 +449,7 @@ void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip) #ifdef DISABLE_CARD_INT void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset, - unsigned long *need_release) + unsigned long *need_release) { u8 release_map = 0, reset_map = 0; @@ -502,13 +502,13 @@ void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset, reset_map = 0; if (!(chip->card_exist & XD_CARD) && - (xd_cnt > (DEBOUNCE_CNT-1))) + (xd_cnt > (DEBOUNCE_CNT - 1))) reset_map |= XD_CARD; if (!(chip->card_exist & SD_CARD) && - (sd_cnt > (DEBOUNCE_CNT-1))) + (sd_cnt > (DEBOUNCE_CNT - 1))) reset_map |= SD_CARD; if (!(chip->card_exist & MS_CARD) && - (ms_cnt > (DEBOUNCE_CNT-1))) + (ms_cnt > (DEBOUNCE_CNT - 1))) reset_map |= MS_CARD; } @@ -556,8 +556,10 @@ void rtsx_init_cards(struct rtsx_chip *chip) if (chip->need_release) { if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER)) rtsx_write_register(chip, OCPCLR, - CARD_OC_INT_CLR | CARD_OC_CLR, - CARD_OC_INT_CLR | CARD_OC_CLR); + CARD_OC_INT_CLR | + CARD_OC_CLR, + CARD_OC_INT_CLR | + CARD_OC_CLR); chip->ocp_stat = 0; } #endif @@ -590,9 +592,9 @@ void rtsx_init_cards(struct rtsx_chip *chip) release_xd_card(chip); if (CHECK_PID(chip, 0x5288) && - CHECK_BARO_PKG(chip, QFN)) + CHECK_BARO_PKG(chip, QFN)) rtsx_write_register(chip, HOST_SLEEP_STATE, - 0xC0, 0xC0); + 0xC0, 0xC0); } if (chip->need_release & MS_CARD) { @@ -681,9 +683,9 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); if (sd_vpclk_phase_reset) { rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, - PHASE_NOT_RESET, 0); + PHASE_NOT_RESET, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, - PHASE_NOT_RESET, PHASE_NOT_RESET); + PHASE_NOT_RESET, PHASE_NOT_RESET); } retval = rtsx_send_cmd(chip, 0, WAIT_TIME); @@ -850,7 +852,7 @@ int switch_normal_clock(struct rtsx_chip *chip, int clk) } void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip, - u32 byte_cnt, u8 pack_size) + u32 byte_cnt, u8 pack_size) { if (pack_size > DMA_1024) pack_size = DMA_512; @@ -864,11 +866,11 @@ void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip, if (dir == DMA_FROM_DEVICE) { rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, - 0x03 | DMA_PACK_SIZE_MASK, + 0x03 | DMA_PACK_SIZE_MASK, DMA_DIR_FROM_CARD | DMA_EN | pack_size); } else { rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, - 0x03 | DMA_PACK_SIZE_MASK, + 0x03 | DMA_PACK_SIZE_MASK, DMA_DIR_TO_CARD | DMA_EN | pack_size); } @@ -978,7 +980,7 @@ int card_power_off(struct rtsx_chip *chip, u8 card) } int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 sec_addr, u16 sec_cnt) + u32 sec_addr, u16 sec_cnt) { int retval; unsigned int lun = SCSI_LUN(srb); @@ -1115,7 +1117,7 @@ void turn_on_led(struct rtsx_chip *chip, u8 gpio) { if (CHECK_PID(chip, 0x5288)) rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), - (u8)(1 << gpio)); + (u8)(1 << gpio)); else rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0); } @@ -1126,7 +1128,7 @@ void turn_off_led(struct rtsx_chip *chip, u8 gpio) rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0); else rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), - (u8)(1 << gpio)); + (u8)(1 << gpio)); } int detect_card_cd(struct rtsx_chip *chip, int card) -- cgit v1.2.3 From 117b6038b2bbcedf67c05c04f651864326bc4f26 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:42 +0000 Subject: staging: rts5208: Unnecessary parentheses Remove parentheses found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_card.c | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index 83748fc7f7e7..d7dd504c3255 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -33,11 +33,11 @@ void do_remaining_work(struct rtsx_chip *chip) { - struct sd_info *sd_card = &(chip->sd_card); + struct sd_info *sd_card = &chip->sd_card; #ifdef XD_DELAY_WRITE - struct xd_info *xd_card = &(chip->xd_card); + struct xd_info *xd_card = &chip->xd_card; #endif - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; if (chip->card_ready & SD_CARD) { if (sd_card->seq_mode) { @@ -154,7 +154,7 @@ void do_reset_sd_card(struct rtsx_chip *chip) chip->sd_reset_counter, chip->card2lun[SD_CARD]); if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) { - clear_bit(SD_NR, &(chip->need_reset)); + clear_bit(SD_NR, &chip->need_reset); chip->sd_reset_counter = 0; chip->sd_show_cnt = 0; return; @@ -169,7 +169,7 @@ void do_reset_sd_card(struct rtsx_chip *chip) if (chip->need_release & SD_CARD) return; if (retval == STATUS_SUCCESS) { - clear_bit(SD_NR, &(chip->need_reset)); + clear_bit(SD_NR, &chip->need_reset); chip->sd_reset_counter = 0; chip->sd_show_cnt = 0; chip->card_ready |= SD_CARD; @@ -177,7 +177,7 @@ void do_reset_sd_card(struct rtsx_chip *chip) chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw; } else { if (chip->sd_io || (chip->sd_reset_counter >= MAX_RESET_CNT)) { - clear_bit(SD_NR, &(chip->need_reset)); + clear_bit(SD_NR, &chip->need_reset); chip->sd_reset_counter = 0; chip->sd_show_cnt = 0; } else { @@ -208,7 +208,7 @@ void do_reset_xd_card(struct rtsx_chip *chip) chip->xd_reset_counter, chip->card2lun[XD_CARD]); if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) { - clear_bit(XD_NR, &(chip->need_reset)); + clear_bit(XD_NR, &chip->need_reset); chip->xd_reset_counter = 0; chip->xd_show_cnt = 0; return; @@ -223,14 +223,14 @@ void do_reset_xd_card(struct rtsx_chip *chip) if (chip->need_release & XD_CARD) return; if (retval == STATUS_SUCCESS) { - clear_bit(XD_NR, &(chip->need_reset)); + clear_bit(XD_NR, &chip->need_reset); chip->xd_reset_counter = 0; chip->card_ready |= XD_CARD; chip->card_fail &= ~XD_CARD; chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw; } else { if (chip->xd_reset_counter >= MAX_RESET_CNT) { - clear_bit(XD_NR, &(chip->need_reset)); + clear_bit(XD_NR, &chip->need_reset); chip->xd_reset_counter = 0; chip->xd_show_cnt = 0; } else { @@ -256,7 +256,7 @@ void do_reset_ms_card(struct rtsx_chip *chip) chip->ms_reset_counter, chip->card2lun[MS_CARD]); if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) { - clear_bit(MS_NR, &(chip->need_reset)); + clear_bit(MS_NR, &chip->need_reset); chip->ms_reset_counter = 0; chip->ms_show_cnt = 0; return; @@ -271,14 +271,14 @@ void do_reset_ms_card(struct rtsx_chip *chip) if (chip->need_release & MS_CARD) return; if (retval == STATUS_SUCCESS) { - clear_bit(MS_NR, &(chip->need_reset)); + clear_bit(MS_NR, &chip->need_reset); chip->ms_reset_counter = 0; chip->card_ready |= MS_CARD; chip->card_fail &= ~MS_CARD; chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw; } else { if (chip->ms_reset_counter >= MAX_RESET_CNT) { - clear_bit(MS_NR, &(chip->need_reset)); + clear_bit(MS_NR, &chip->need_reset); chip->ms_reset_counter = 0; chip->ms_show_cnt = 0; } else { @@ -369,7 +369,7 @@ void rtsx_reset_cards(struct rtsx_chip *chip) rtsx_disable_aspm(chip); if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio) - clear_bit(SD_NR, &(chip->need_reset)); + clear_bit(SD_NR, &chip->need_reset); if (chip->need_reset & XD_CARD) { chip->card_exist |= XD_CARD; @@ -381,8 +381,8 @@ void rtsx_reset_cards(struct rtsx_chip *chip) } if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { if (chip->card_exist & XD_CARD) { - clear_bit(SD_NR, &(chip->need_reset)); - clear_bit(MS_NR, &(chip->need_reset)); + clear_bit(SD_NR, &chip->need_reset); + clear_bit(MS_NR, &chip->need_reset); } } if (chip->need_reset & SD_CARD) { @@ -531,23 +531,23 @@ void rtsx_init_cards(struct rtsx_chip *chip) } #ifdef DISABLE_CARD_INT - card_cd_debounce(chip, &(chip->need_reset), &(chip->need_release)); + card_cd_debounce(chip, &chip->need_reset, &chip->need_release); #endif if (chip->need_release) { if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { if (chip->int_reg & XD_EXIST) { - clear_bit(SD_NR, &(chip->need_release)); - clear_bit(MS_NR, &(chip->need_release)); + clear_bit(SD_NR, &chip->need_release); + clear_bit(MS_NR, &chip->need_release); } } if (!(chip->card_exist & SD_CARD) && !chip->sd_io) - clear_bit(SD_NR, &(chip->need_release)); + clear_bit(SD_NR, &chip->need_release); if (!(chip->card_exist & XD_CARD)) - clear_bit(XD_NR, &(chip->need_release)); + clear_bit(XD_NR, &chip->need_release); if (!(chip->card_exist & MS_CARD)) - clear_bit(MS_NR, &(chip->need_release)); + clear_bit(MS_NR, &chip->need_release); dev_dbg(rtsx_dev(chip), "chip->need_release = 0x%x\n", (unsigned int)(chip->need_release)); @@ -569,7 +569,7 @@ void rtsx_init_cards(struct rtsx_chip *chip) } if (chip->need_release & SD_CARD) { - clear_bit(SD_NR, &(chip->need_release)); + clear_bit(SD_NR, &chip->need_release); chip->card_exist &= ~SD_CARD; chip->card_ejected &= ~SD_CARD; chip->card_fail &= ~SD_CARD; @@ -582,7 +582,7 @@ void rtsx_init_cards(struct rtsx_chip *chip) } if (chip->need_release & XD_CARD) { - clear_bit(XD_NR, &(chip->need_release)); + clear_bit(XD_NR, &chip->need_release); chip->card_exist &= ~XD_CARD; chip->card_ejected &= ~XD_CARD; chip->card_fail &= ~XD_CARD; @@ -598,7 +598,7 @@ void rtsx_init_cards(struct rtsx_chip *chip) } if (chip->need_release & MS_CARD) { - clear_bit(MS_NR, &(chip->need_release)); + clear_bit(MS_NR, &chip->need_release); chip->card_exist &= ~MS_CARD; chip->card_ejected &= ~MS_CARD; chip->card_fail &= ~MS_CARD; -- cgit v1.2.3 From 911e84a09af67e03ecefbc88118d9163b7492eb0 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:43 +0000 Subject: staging: rts5208: Spacing Adding space around operator for better readability and to stop checkpatch check messages Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index d7dd504c3255..657d2da70a9c 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -652,7 +652,7 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) return STATUS_FAIL; } - mcu_cnt = (u8)(125/clk + 3); + mcu_cnt = (u8)(125 / clk + 3); if (mcu_cnt > 7) mcu_cnt = 7; -- cgit v1.2.3 From a38e369b31ee7498c63eb3307392020e9250b6f6 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:44 +0000 Subject: staging: rts5208: Comparison to NULL Fix to resolve checkpatch message Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index 657d2da70a9c..a6b7bffc6714 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -986,7 +986,7 @@ int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, unsigned int lun = SCSI_LUN(srb); int i; - if (chip->rw_card[lun] == NULL) { + if (!chip->rw_card[lun]) { rtsx_trace(chip); return STATUS_FAIL; } -- cgit v1.2.3 From 379dfd326906da52e689b51fef4bc66e23e6a9c4 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:45 +0000 Subject: staging: rts5208: rtsx.c: Unnecessary parentheses Remove parentheses found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 750e2a75912f..aa650beddc54 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -485,7 +485,7 @@ SkipForAbort: } if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { - complete(&(dev->notify)); + complete(&dev->notify); rtsx_set_stat(chip, RTSX_STAT_IDLE); } @@ -519,9 +519,9 @@ static int rtsx_polling_thread(void *__dev) { struct rtsx_dev *dev = __dev; struct rtsx_chip *chip = dev->chip; - struct sd_info *sd_card = &(chip->sd_card); - struct xd_info *xd_card = &(chip->xd_card); - struct ms_info *ms_card = &(chip->ms_card); + struct sd_info *sd_card = &chip->sd_card; + struct xd_info *xd_card = &chip->xd_card; + struct ms_info *ms_card = &chip->ms_card; sd_card->cleanup_counter = 0; xd_card->cleanup_counter = 0; @@ -890,7 +890,7 @@ static int rtsx_probe(struct pci_dev *pci, init_completion(&dev->cmnd_ready); init_completion(&dev->control_exit); init_completion(&dev->polling_exit); - init_completion(&(dev->notify)); + init_completion(&dev->notify); init_completion(&dev->scanning_done); init_waitqueue_head(&dev->delay_wait); -- cgit v1.2.3 From c8b07957c4a35acc5df9c4dd342a0bdef19125d6 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:46 +0000 Subject: staging: rts5208: rtsx.c: Alignment Fix to match open parenthesis in order to satisfy checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index aa650beddc54..5d10182ffb81 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -125,7 +125,7 @@ static int slave_configure(struct scsi_device *sdev) /* queue a command */ /* This is always called with scsi_lock(host) held */ static int queuecommand_lck(struct scsi_cmnd *srb, - void (*done)(struct scsi_cmnd *)) + void (*done)(struct scsi_cmnd *)) { struct rtsx_dev *dev = host_to_rtsx(srb->device->host); struct rtsx_chip *chip = dev->chip; @@ -844,7 +844,7 @@ static void rtsx_init_options(struct rtsx_chip *chip) } static int rtsx_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) + const struct pci_device_id *pci_id) { struct Scsi_Host *host; struct rtsx_dev *dev; -- cgit v1.2.3 From cd5491af0d6e2ad3f91597c591e6b60ba98b06f1 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:47 +0000 Subject: staging: rts5208: rtsx.c: Multiple assignments Fix multiple assignments found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 5d10182ffb81..c88200be918a 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -107,8 +107,10 @@ static int slave_configure(struct scsi_device *sdev) * the actual value or the modified one, depending on where the * data comes from. */ - if (sdev->scsi_level < SCSI_2) - sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; + if (sdev->scsi_level < SCSI_2) { + sdev->scsi_level = SCSI_2; + sdev->sdev_target->scsi_level = SCSI_2; + } return 0; } -- cgit v1.2.3 From 7e0ea476edb59f06ed19fac3382dc86606de7c0a Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:48 +0000 Subject: staging: rts5208: rtsx.c: Spacing Add spaces around operator for readability Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index c88200be918a..f611d3d1d8ad 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -122,7 +122,10 @@ static int slave_configure(struct scsi_device *sdev) /* we use this macro to help us write into the buffer */ #undef SPRINTF #define SPRINTF(args...) \ - do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) + do { \ + if (pos < buffer + length) \ + pos += sprintf(pos, ## args); \ + } while (0) /* queue a command */ /* This is always called with scsi_lock(host) held */ -- cgit v1.2.3 From cd4b77586b5bfb1cea8470aa5b44f39e2004e9c8 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:49 +0000 Subject: staging: rts5208: rtsx.c: CamelCase Make camel case labels all lowercase Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index f611d3d1d8ad..efd42de18e13 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -438,7 +438,7 @@ static int rtsx_control_thread(void *__dev) /* has the command aborted ? */ if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { chip->srb->result = DID_ABORT << 16; - goto SkipForAbort; + goto skip_for_abort; } scsi_unlock(host); @@ -485,7 +485,7 @@ static int rtsx_control_thread(void *__dev) else if (chip->srb->result != DID_ABORT << 16) { chip->srb->scsi_done(chip->srb); } else { -SkipForAbort: +skip_for_abort: dev_err(&dev->pci->dev, "scsi command aborted\n"); } @@ -602,7 +602,7 @@ static irqreturn_t rtsx_interrupt(int irq, void *dev_id) dev->trans_result = TRANS_RESULT_FAIL; if (dev->done) complete(dev->done); - goto Exit; + goto exit; } } @@ -624,7 +624,7 @@ static irqreturn_t rtsx_interrupt(int irq, void *dev_id) } } -Exit: +exit: spin_unlock(&dev->reg_lock); return IRQ_HANDLED; } -- cgit v1.2.3 From 8149b9ab570e75726acdc9367bc9aefe1dca76b6 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:50 +0000 Subject: staging: rts5208: rtsx.c: Spacing Remove blank line after opening { Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index efd42de18e13..809d37d243bd 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -536,7 +536,6 @@ static int rtsx_polling_thread(void *__dev) wait_timeout((delay_use + 5) * 1000); for (;;) { - set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(POLLING_INTERVAL)); -- cgit v1.2.3 From 2eb9d8cbb3c3d4458223d3399a2a53a922e37ce8 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:51 +0000 Subject: staging: rts5208: rtsx.c: Alloc sizeof struct Satisfy checkpatch message: Prefer kzalloc(sizeof(*dev->chip)...) over kzalloc(sizeof(struct rtsx_chip)...) Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 809d37d243bd..dafd8fdca1ed 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -883,7 +883,7 @@ static int rtsx_probe(struct pci_dev *pci, dev = host_to_rtsx(host); memset(dev, 0, sizeof(struct rtsx_dev)); - dev->chip = kzalloc(sizeof(struct rtsx_chip), GFP_KERNEL); + dev->chip = kzalloc(sizeof(dev->chip), GFP_KERNEL); if (!dev->chip) { err = -ENOMEM; goto errout; -- cgit v1.2.3 From 8473e5bb5c45aaa169c62ac6393e0bcd9c3c8002 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:52 +0000 Subject: staging: rts5208: ms.h: Parenthesis alignment Fix alignment to match open parenthesis Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/ms.h b/drivers/staging/rts5208/ms.h index d7686399df97..71f98cc03eed 100644 --- a/drivers/staging/rts5208/ms.h +++ b/drivers/staging/rts5208/ms.h @@ -202,9 +202,9 @@ void mspro_polling_format_status(struct rtsx_chip *chip); void mspro_stop_seq_mode(struct rtsx_chip *chip); int reset_ms_card(struct rtsx_chip *chip); int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt); + u32 start_sector, u16 sector_cnt); int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, - int short_data_len, bool quick_format); + int short_data_len, bool quick_format); void ms_free_l2p_tbl(struct rtsx_chip *chip); void ms_cleanup_work(struct rtsx_chip *chip); int ms_power_off_card3v3(struct rtsx_chip *chip); -- cgit v1.2.3 From 9c378f1488e764c589c0fd5c5ff82133c5dcfb43 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:53 +0000 Subject: staging: rts5208: ms.c: Parenthesis alignment Fix checkpatch messages: Alignment should match open parenthesis Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 288 ++++++++++++++++++++++--------------------- 1 file changed, 150 insertions(+), 138 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index f27df0b4cb44..c8ecdf6825ce 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -507,17 +507,17 @@ static int ms_pull_ctl_enable(struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5208)) { rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - MS_D1_PD | MS_D2_PD | MS_CLK_NP | MS_D6_PD); + MS_D1_PD | MS_D2_PD | MS_CLK_NP | MS_D6_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - MS_D3_PD | MS_D0_PD | MS_BS_NP | XD_D4_PD); + MS_D3_PD | MS_D0_PD | MS_BS_NP | XD_D4_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); + XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); + MS_D5_PD | MS_D4_PD); } else if (CHECK_PID(chip, 0x5288)) { if (CHECK_BARO_PKG(chip, QFN)) { rtsx_add_cmd(chip, WRITE_REG_CMD, @@ -665,7 +665,7 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus) for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG, - 6, NO_WAIT_INT); + 6, NO_WAIT_INT); if (retval == STATUS_SUCCESS) break; } @@ -765,7 +765,7 @@ static int ms_confirm_cpu_startup(struct rtsx_chip *chip) for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_read_bytes(chip, GET_INT, 1, - NO_WAIT_INT, &val, 1); + NO_WAIT_INT, &val, 1); if (retval == STATUS_SUCCESS) break; } @@ -861,7 +861,7 @@ static int ms_switch_8bit_bus(struct rtsx_chip *chip) for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, - 1, NO_WAIT_INT); + 1, NO_WAIT_INT); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1061,8 +1061,8 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) return STATUS_FAIL; } retval = ms_transfer_data(chip, MS_TM_AUTO_READ, - PRO_READ_LONG_DATA, 0x40, WAIT_INT, - 0, 0, buf, 64 * 512); + PRO_READ_LONG_DATA, 0x40, WAIT_INT, + 0, 0, buf, 64 * 512); if (retval == STATUS_SUCCESS) break; @@ -1087,7 +1087,7 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) break; retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, - PRO_READ_LONG_DATA, 0, WAIT_INT); + PRO_READ_LONG_DATA, 0, WAIT_INT); if (retval != STATUS_SUCCESS) { kfree(buf); rtsx_trace(chip); @@ -1121,7 +1121,7 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) #ifdef SUPPORT_MSXC if ((buf[cur_addr_off + 8] == 0x10) || - (buf[cur_addr_off + 8] == 0x13)) { + (buf[cur_addr_off + 8] == 0x13)) { #else if (buf[cur_addr_off + 8] == 0x10) { #endif @@ -1264,7 +1264,7 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) if (device_type != 0x00) { if ((device_type == 0x01) || (device_type == 0x02) || - (device_type == 0x03)) { + (device_type == 0x03)) { chip->card_wp |= MS_CARD; } else { rtsx_trace(chip); @@ -1298,7 +1298,7 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) #ifdef SUPPORT_MAGIC_GATE static int mg_set_tpc_para_sub(struct rtsx_chip *chip, - int type, u8 mg_entry_num); + int type, u8 mg_entry_num); #endif static int reset_ms_pro(struct rtsx_chip *chip) @@ -1365,7 +1365,7 @@ Retry: change_power_class = power_class_mode; if (change_power_class) { retval = msxc_change_power(chip, - change_power_class); + change_power_class); if (retval != STATUS_SUCCESS) { change_power_class--; goto Retry; @@ -1418,14 +1418,14 @@ static int ms_read_status_reg(struct rtsx_chip *chip) } static int ms_read_extra_data(struct rtsx_chip *chip, - u16 block_addr, u8 page_num, u8 *buf, int buf_len) + u16 block_addr, u8 page_num, u8 *buf, int buf_len) { struct ms_info *ms_card = &chip->ms_card; int retval, i; u8 val, data[10]; retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 6); + SystemParm, 6); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1488,7 +1488,8 @@ static int ms_read_extra_data(struct rtsx_chip *chip, } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, 6); + MS_EXTRA_SIZE, SystemParm, + 6); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1497,7 +1498,7 @@ static int ms_read_extra_data(struct rtsx_chip *chip, } retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT, - data, MS_EXTRA_SIZE); + data, MS_EXTRA_SIZE); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1512,8 +1513,8 @@ static int ms_read_extra_data(struct rtsx_chip *chip, return STATUS_SUCCESS; } -static int ms_write_extra_data(struct rtsx_chip *chip, - u16 block_addr, u8 page_num, u8 *buf, int buf_len) +static int ms_write_extra_data(struct rtsx_chip *chip, u16 block_addr, + u8 page_num, u8 *buf, int buf_len) { struct ms_info *ms_card = &chip->ms_card; int retval, i; @@ -1525,7 +1526,7 @@ static int ms_write_extra_data(struct rtsx_chip *chip, } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 6 + MS_EXTRA_SIZE); + SystemParm, 6 + MS_EXTRA_SIZE); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1588,7 +1589,7 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) u8 val, data[6]; retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 6); + SystemParm, 6); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1651,7 +1652,7 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) } retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, - 0, NO_WAIT_INT); + 0, NO_WAIT_INT); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1678,7 +1679,7 @@ static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 7); + SystemParm, 7); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1742,7 +1743,7 @@ static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk) u8 val, data[6]; retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 6); + SystemParm, 6); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1844,7 +1845,7 @@ static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, } retval = ms_write_extra_data(chip, phy_blk, i, - extra, MS_EXTRA_SIZE); + extra, MS_EXTRA_SIZE); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1855,7 +1856,7 @@ static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, } static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 start_page, u8 end_page) + u16 log_blk, u8 start_page, u8 end_page) { struct ms_info *ms_card = &chip->ms_card; bool uncorrect_flag = false; @@ -1915,7 +1916,7 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE); retval = ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, 6); + MS_EXTRA_SIZE, SystemParm, 6); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1971,9 +1972,9 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, } retval = ms_transfer_tpc(chip, - MS_TM_NORMAL_READ, - READ_PAGE_DATA, - 0, NO_WAIT_INT); + MS_TM_NORMAL_READ, + READ_PAGE_DATA, + 0, NO_WAIT_INT); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -1981,20 +1982,24 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, if (uncorrect_flag) { ms_set_page_status(log_blk, setPS_NG, - extra, MS_EXTRA_SIZE); + extra, + MS_EXTRA_SIZE); if (i == 0) extra[0] &= 0xEF; ms_write_extra_data(chip, old_blk, i, - extra, MS_EXTRA_SIZE); + extra, + MS_EXTRA_SIZE); dev_dbg(rtsx_dev(chip), "page %d : extra[0] = 0x%x\n", i, extra[0]); MS_SET_BAD_BLOCK_FLG(ms_card); ms_set_page_status(log_blk, setPS_Error, - extra, MS_EXTRA_SIZE); + extra, + MS_EXTRA_SIZE); ms_write_extra_data(chip, new_blk, i, - extra, MS_EXTRA_SIZE); + extra, + MS_EXTRA_SIZE); continue; } @@ -2021,8 +2026,8 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, } } - retval = ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, (6 + MS_EXTRA_SIZE)); + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, (6 + MS_EXTRA_SIZE)); ms_set_err_code(chip, MS_NO_ERROR); @@ -2085,7 +2090,8 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, if (i == 0) { retval = ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, 7); + MS_EXTRA_SIZE, SystemParm, + 7); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -2121,7 +2127,7 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, - NO_WAIT_INT, &val, 1); + NO_WAIT_INT, &val, 1); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -2361,7 +2367,7 @@ RE_SEARCH: } retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG, 1, - NO_WAIT_INT); + NO_WAIT_INT); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -2474,7 +2480,7 @@ static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off) } static void ms_set_l2p_tbl(struct rtsx_chip *chip, - int seg_no, u16 log_off, u16 phy_blk) + int seg_no, u16 log_off, u16 phy_blk) { struct ms_info *ms_card = &chip->ms_card; struct zone_entry *segment; @@ -2530,7 +2536,7 @@ static const unsigned short ms_start_idx[] = {0, 494, 990, 1486, 1982, 2478, 7934}; static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk, - u16 log_off, u8 us1, u8 us2) + u16 log_off, u8 us1, u8 us2) { struct ms_info *ms_card = &chip->ms_card; struct zone_entry *segment; @@ -2646,7 +2652,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) } retval = ms_read_extra_data(chip, phy_blk, 0, - extra, MS_EXTRA_SIZE); + extra, MS_EXTRA_SIZE); if (retval != STATUS_SUCCESS) { dev_dbg(rtsx_dev(chip), "read extra data fail\n"); ms_set_bad_block(chip, phy_blk); @@ -2685,7 +2691,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) } if ((log_blk < ms_start_idx[seg_no]) || - (log_blk >= ms_start_idx[seg_no + 1])) { + (log_blk >= ms_start_idx[seg_no + 1])) { if (!(chip->card_wp & MS_CARD)) { retval = ms_erase_block(chip, phy_blk); if (retval != STATUS_SUCCESS) @@ -2705,7 +2711,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) us1 = extra[0] & 0x10; tmp_blk = segment->l2p_table[idx]; retval = ms_read_extra_data(chip, tmp_blk, 0, - extra, MS_EXTRA_SIZE); + extra, MS_EXTRA_SIZE); if (retval != STATUS_SUCCESS) continue; us2 = extra[0] & 0x10; @@ -2774,7 +2780,8 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) phy_blk = ms_get_unused_block(chip, 0); retval = ms_copy_page(chip, tmp_blk, phy_blk, - log_blk, 0, ms_card->page_off + 1); + log_blk, 0, + ms_card->page_off + 1); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -2861,7 +2868,7 @@ int reset_ms_card(struct rtsx_chip *chip) } static int mspro_set_rw_cmd(struct rtsx_chip *chip, - u32 start_sec, u16 sec_cnt, u8 cmd) + u32 start_sec, u16 sec_cnt, u8 cmd) { int retval, i; u8 data[8]; @@ -2932,8 +2939,8 @@ static inline int ms_auto_tune_clock(struct rtsx_chip *chip) } static int mspro_rw_multi_sector(struct scsi_cmnd *srb, - struct rtsx_chip *chip, u32 start_sector, - u16 sector_cnt) + struct rtsx_chip *chip, u32 start_sector, + u16 sector_cnt) { struct ms_info *ms_card = &chip->ms_card; bool mode_2k = false; @@ -3038,8 +3045,8 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb, } retval = ms_transfer_data(chip, trans_mode, rw_tpc, sector_cnt, - WAIT_INT, mode_2k, scsi_sg_count(srb), - scsi_sglist(srb), scsi_bufflen(srb)); + WAIT_INT, mode_2k, scsi_sg_count(srb), + scsi_sglist(srb), scsi_bufflen(srb)); if (retval != STATUS_SUCCESS) { ms_card->seq_mode = 0; rtsx_read_register(chip, MS_TRANS_CFG, &val); @@ -3076,7 +3083,7 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb, } static int mspro_read_format_progress(struct rtsx_chip *chip, - const int short_data_len) + const int short_data_len) { struct ms_info *ms_card = &chip->ms_card; int retval, i; @@ -3117,7 +3124,7 @@ static int mspro_read_format_progress(struct rtsx_chip *chip, cnt = (u8)short_data_len; retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, - MS_NO_CHECK_INT); + MS_NO_CHECK_INT); if (retval != STATUS_SUCCESS) { ms_card->format_status = FORMAT_FAIL; rtsx_trace(chip); @@ -3125,7 +3132,7 @@ static int mspro_read_format_progress(struct rtsx_chip *chip, } retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT, - data, 8); + data, 8); if (retval != STATUS_SUCCESS) { ms_card->format_status = FORMAT_FAIL; rtsx_trace(chip); @@ -3204,7 +3211,7 @@ void mspro_polling_format_status(struct rtsx_chip *chip) int i; if (ms_card->pro_under_formatting && - (rtsx_get_stat(chip) != RTSX_STAT_SS)) { + (rtsx_get_stat(chip) != RTSX_STAT_SS)) { rtsx_set_stat(chip, RTSX_STAT_RUN); for (i = 0; i < 65535; i++) { @@ -3216,7 +3223,7 @@ void mspro_polling_format_status(struct rtsx_chip *chip) } int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, - int short_data_len, bool quick_format) + int short_data_len, bool quick_format) { struct ms_info *ms_card = &chip->ms_card; int retval, i; @@ -3305,9 +3312,9 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, } static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, - u16 log_blk, u8 start_page, u8 end_page, - u8 *buf, unsigned int *index, - unsigned int *offset) + u16 log_blk, u8 start_page, u8 end_page, + u8 *buf, unsigned int *index, + unsigned int *offset) { struct ms_info *ms_card = &chip->ms_card; int retval, i; @@ -3315,7 +3322,7 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u8 *ptr; retval = ms_read_extra_data(chip, phy_blk, start_page, - extra, MS_EXTRA_SIZE); + extra, MS_EXTRA_SIZE); if (retval == STATUS_SUCCESS) { if ((extra[1] & 0x30) != 0x30) { ms_set_err_code(chip, MS_FLASH_READ_ERROR); @@ -3325,7 +3332,7 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 6); + SystemParm, 6); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3420,7 +3427,7 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, } retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, - &val, 1); + &val, 1); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3441,23 +3448,24 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, - 0xFF, trans_cfg); + 0xFF, trans_cfg); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, RING_BUFFER); + 0x01, RING_BUFFER); trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_READ); + MS_TRANSFER_START | MS_TM_NORMAL_READ); rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); + MS_TRANSFER_END, MS_TRANSFER_END); rtsx_send_cmd_no_wait(chip); - retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, - 512, scsi_sg_count(chip->srb), - index, offset, DMA_FROM_DEVICE, - chip->ms_timeout); + retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512, + scsi_sg_count(chip->srb), + index, offset, + DMA_FROM_DEVICE, + chip->ms_timeout); if (retval < 0) { if (retval == -ETIMEDOUT) { ms_set_err_code(chip, MS_TO_ERROR); @@ -3489,7 +3497,7 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, } static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, - u16 new_blk, u16 log_blk, u8 start_page, + u16 new_blk, u16 log_blk, u8 start_page, u8 end_page, u8 *buf, unsigned int *index, unsigned int *offset) { @@ -3500,7 +3508,7 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, if (!start_page) { retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 7); + SystemParm, 7); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3534,7 +3542,7 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, ms_set_err_code(chip, MS_NO_ERROR); retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, - NO_WAIT_INT); + NO_WAIT_INT); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3542,7 +3550,7 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, (6 + MS_EXTRA_SIZE)); + SystemParm, (6 + MS_EXTRA_SIZE)); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3630,25 +3638,26 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, - 0xFF, WRITE_PAGE_DATA); + 0xFF, WRITE_PAGE_DATA); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, - 0xFF, WAIT_INT); + 0xFF, WAIT_INT); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, RING_BUFFER); + 0x01, RING_BUFFER); trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_WRITE); + MS_TRANSFER_START | MS_TM_NORMAL_WRITE); rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); + MS_TRANSFER_END, MS_TRANSFER_END); rtsx_send_cmd_no_wait(chip); - retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, - 512, scsi_sg_count(chip->srb), - index, offset, DMA_TO_DEVICE, - chip->ms_timeout); + retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512, + scsi_sg_count(chip->srb), + index, offset, + DMA_TO_DEVICE, + chip->ms_timeout); if (retval < 0) { ms_set_err_code(chip, MS_TO_ERROR); rtsx_clear_ms_error(chip); @@ -3677,7 +3686,7 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, if (page_addr == (end_page - 1)) { if (!(val & INT_REG_CED)) { retval = ms_send_cmd(chip, BLOCK_END, - WAIT_INT); + WAIT_INT); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3685,7 +3694,7 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, } retval = ms_read_bytes(chip, GET_INT, 1, - NO_WAIT_INT, &val, 1); + NO_WAIT_INT, &val, 1); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3693,7 +3702,7 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, } if ((page_addr == (end_page - 1)) || - (page_addr == ms_card->page_off)) { + (page_addr == ms_card->page_off)) { if (!(val & INT_REG_CED)) { ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); @@ -3711,13 +3720,13 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, } static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 page_off) + u16 log_blk, u8 page_off) { struct ms_info *ms_card = &chip->ms_card; int retval, seg_no; retval = ms_copy_page(chip, old_blk, new_blk, log_blk, - page_off, ms_card->page_off + 1); + page_off, ms_card->page_off + 1); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3740,13 +3749,13 @@ static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, } static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 start_page) + u16 log_blk, u8 start_page) { int retval; if (start_page) { retval = ms_copy_page(chip, old_blk, new_blk, log_blk, - 0, start_page); + 0, start_page); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; @@ -3772,7 +3781,7 @@ int ms_delay_write(struct rtsx_chip *chip) delay_write->delay_write_flag = 0; retval = ms_finish_write(chip, - delay_write->old_phyblock, + delay_write->old_phyblock, delay_write->new_phyblock, delay_write->logblock, delay_write->pageoff); @@ -3790,13 +3799,13 @@ static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rtsx_chip *chip) { if (srb->sc_data_direction == DMA_FROM_DEVICE) set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); else set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); } static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt) + u32 start_sector, u16 sector_cnt) { struct ms_info *ms_card = &chip->ms_card; unsigned int lun = SCSI_LUN(srb); @@ -3843,16 +3852,17 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (srb->sc_data_direction == DMA_TO_DEVICE) { #ifdef MS_DELAY_WRITE if (delay_write->delay_write_flag && - (delay_write->logblock == log_blk) && - (start_page > delay_write->pageoff)) { + (delay_write->logblock == log_blk) && + (start_page > delay_write->pageoff)) { delay_write->delay_write_flag = 0; retval = ms_copy_page(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, log_blk, - delay_write->pageoff, start_page); + delay_write->old_phyblock, + delay_write->new_phyblock, + log_blk, + delay_write->pageoff, start_page); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -3868,7 +3878,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, retval = ms_delay_write(chip); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -3878,13 +3888,13 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, new_blk = ms_get_unused_block(chip, seg_no); if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } retval = ms_prepare_write(chip, old_blk, new_blk, - log_blk, start_page); + log_blk, start_page); if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { set_sense_type(chip, lun, @@ -3893,7 +3903,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, return STATUS_FAIL; } set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); + SENSE_TYPE_MEDIA_WRITE_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -3906,21 +3916,21 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); + SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; } set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return STATUS_FAIL; } #endif old_blk = ms_get_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no]); + log_blk - ms_start_idx[seg_no]); if (old_blk == 0xFFFF) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return STATUS_FAIL; } @@ -3942,19 +3952,21 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (srb->sc_data_direction == DMA_FROM_DEVICE) { retval = ms_read_multiple_pages(chip, - old_blk, log_blk, start_page, end_page, - ptr, &index, &offset); + old_blk, log_blk, + start_page, end_page, + ptr, &index, &offset); } else { - retval = ms_write_multiple_pages(chip, old_blk, - new_blk, log_blk, start_page, end_page, - ptr, &index, &offset); + retval = ms_write_multiple_pages(chip, old_blk, new_blk, + log_blk, start_page, + end_page, ptr, &index, + &offset); } if (retval != STATUS_SUCCESS) { toggle_gpio(chip, 1); if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); + SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; } @@ -3970,8 +3982,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, ms_set_unused_block(chip, old_blk); ms_set_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no], - new_blk); + log_blk - ms_start_idx[seg_no], + new_blk); } } @@ -3995,14 +4007,14 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (retval != STATUS_SUCCESS) { chip->card_fail |= MS_CARD; set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); + SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; } } old_blk = ms_get_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no]); + log_blk - ms_start_idx[seg_no]); if (old_blk == 0xFFFF) { ms_rw_fail(srb, chip); rtsx_trace(chip); @@ -4034,7 +4046,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, delay_write->pageoff = end_page; #else retval = ms_finish_write(chip, old_blk, new_blk, - log_blk, end_page); + log_blk, end_page); if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { set_sense_type(chip, lun, @@ -4057,17 +4069,17 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, } int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt) + u32 start_sector, u16 sector_cnt) { struct ms_info *ms_card = &chip->ms_card; int retval; if (CHK_MSPRO(ms_card)) retval = mspro_rw_multi_sector(srb, chip, start_sector, - sector_cnt); + sector_cnt); else retval = ms_rw_multi_sector(srb, chip, start_sector, - sector_cnt); + sector_cnt); return retval; } @@ -4189,7 +4201,7 @@ static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num) } static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, - u8 mg_entry_num) + u8 mg_entry_num) { int retval; u8 buf[6]; @@ -4306,7 +4318,7 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, - 3, WAIT_INT, 0, 0, buf + 4, 1536); + 3, WAIT_INT, 0, 0, buf + 4, 1536); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); rtsx_clear_ms_error(chip); @@ -4354,7 +4366,7 @@ int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, - buf, 32); + buf, 32); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); rtsx_trace(chip); @@ -4437,7 +4449,7 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, - buf1, 32); + buf1, 32); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); rtsx_trace(chip); @@ -4560,7 +4572,7 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, - 2, WAIT_INT, 0, 0, buf + 4, 1024); + 2, WAIT_INT, 0, 0, buf + 4, 1024); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_clear_ms_error(chip); @@ -4619,7 +4631,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); else set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); + SENSE_TYPE_MG_WRITE_ERR); } else { set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); } @@ -4634,17 +4646,17 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, - 0xFF, PRO_WRITE_LONG_DATA); + 0xFF, PRO_WRITE_LONG_DATA); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, RING_BUFFER); + 0x01, RING_BUFFER); trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_WRITE); + MS_TRANSFER_START | MS_TM_NORMAL_WRITE); rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); + MS_TRANSFER_END, MS_TRANSFER_END); rtsx_send_cmd_no_wait(chip); @@ -4657,10 +4669,10 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); else set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); + SENSE_TYPE_MG_WRITE_ERR); } else { set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); + SENSE_TYPE_MG_WRITE_ERR); } retval = STATUS_FAIL; rtsx_trace(chip); @@ -4669,7 +4681,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) } #else retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA, - 2, WAIT_INT, 0, 0, buf + 4, 1024); + 2, WAIT_INT, 0, 0, buf + 4, 1024); if ((retval != STATUS_SUCCESS) || check_ms_err(chip)) { rtsx_clear_ms_error(chip); if (ms_card->mg_auth == 0) { @@ -4678,7 +4690,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); else set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); + SENSE_TYPE_MG_WRITE_ERR); } else { set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); } @@ -4706,7 +4718,7 @@ void ms_cleanup_work(struct rtsx_chip *chip) } if (CHK_MSHG(ms_card)) { rtsx_write_register(chip, MS_CFG, - MS_2K_SECTOR_MODE, 0x00); + MS_2K_SECTOR_MODE, 0x00); } } #ifdef MS_DELAY_WRITE -- cgit v1.2.3 From 25ccf0b0a785edb5f20e2da8c5b9f62ecfffd670 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:54 +0000 Subject: staging: rts5208: ms.c: Long Lines Fix long lines detected by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 94 +++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index c8ecdf6825ce..0573d80bc968 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -432,31 +432,36 @@ static int ms_pull_ctl_disable(struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5208)) { retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF, - MS_D1_PD | MS_D2_PD | MS_CLK_PD | MS_D6_PD); + MS_D1_PD | MS_D2_PD | MS_CLK_PD | + MS_D6_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF, - MS_D3_PD | MS_D0_PD | MS_BS_PD | XD_D4_PD); + MS_D3_PD | MS_D0_PD | MS_BS_PD | + XD_D4_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF, - MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + MS_D7_PD | XD_CE_PD | XD_CLE_PD | + XD_CD_PU); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); + XD_RDY_PD | SD_D3_PD | SD_D2_PD | + XD_ALE_PD); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + MS_INS_PU | SD_WP_PD | SD_CD_PU | + SD_CMD_PD); if (retval) { rtsx_trace(chip); return retval; @@ -616,14 +621,20 @@ static int ms_prepare_reset(struct rtsx_chip *chip) if (chip->asic_code) { retval = rtsx_write_register(chip, MS_CFG, 0xFF, - SAMPLE_TIME_RISING | PUSH_TIME_DEFAULT | NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1); + SAMPLE_TIME_RISING | + PUSH_TIME_DEFAULT | + NO_EXTEND_TOGGLE | + MS_BUS_WIDTH_1); if (retval) { rtsx_trace(chip); return retval; } } else { retval = rtsx_write_register(chip, MS_CFG, 0xFF, - SAMPLE_TIME_FALLING | PUSH_TIME_DEFAULT | NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1); + SAMPLE_TIME_FALLING | + PUSH_TIME_DEFAULT | + NO_EXTEND_TOGGLE | + MS_BUS_WIDTH_1); if (retval) { rtsx_trace(chip); return retval; @@ -2375,7 +2386,9 @@ RE_SEARCH: retval = rtsx_write_register(chip, MS_CFG, 0x58 | MS_NO_CHECK_INT, - MS_BUS_WIDTH_4 | PUSH_TIME_ODD | MS_NO_CHECK_INT); + MS_BUS_WIDTH_4 | + PUSH_TIME_ODD | + MS_NO_CHECK_INT); if (retval) { rtsx_trace(chip); return retval; @@ -2999,12 +3012,13 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb, } if (ms_card->seq_mode) { - if ((ms_card->pre_dir != srb->sc_data_direction) - || ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) != start_sector) - || (mode_2k && (ms_card->seq_mode & MODE_512_SEQ)) - || (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ)) - || !(val & MS_INT_BREQ) - || ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) { + if ((ms_card->pre_dir != srb->sc_data_direction) || + ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) != + start_sector) || + (mode_2k && (ms_card->seq_mode & MODE_512_SEQ)) || + (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ)) || + !(val & MS_INT_BREQ) || + ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) { ms_card->seq_mode = 0; ms_card->total_sec_cnt = 0; if (val & MS_INT_BREQ) { @@ -3014,7 +3028,8 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb, return STATUS_FAIL; } - rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); + rtsx_write_register(chip, RBCTL, RB_FLUSH, + RB_FLUSH); } } } @@ -3109,7 +3124,8 @@ static int mspro_read_format_progress(struct rtsx_chip *chip, } if (!(tmp & MS_INT_BREQ)) { - if ((tmp & (MS_INT_CED | MS_INT_BREQ | MS_INT_CMDNK | MS_INT_ERR)) == MS_INT_CED) { + if ((tmp & (MS_INT_CED | MS_INT_BREQ | MS_INT_CMDNK | + MS_INT_ERR)) == MS_INT_CED) { ms_card->format_status = FORMAT_SUCCESS; return STATUS_SUCCESS; } @@ -3396,11 +3412,17 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, if (retval != STATUS_SUCCESS) { if (!(chip->card_wp & MS_CARD)) { reset_ms(chip); - ms_set_page_status(log_blk, setPS_NG, extra, MS_EXTRA_SIZE); - ms_write_extra_data(chip, phy_blk, - page_addr, extra, MS_EXTRA_SIZE); + ms_set_page_status + (log_blk, setPS_NG, + extra, + MS_EXTRA_SIZE); + ms_write_extra_data + (chip, phy_blk, + page_addr, extra, + MS_EXTRA_SIZE); } - ms_set_err_code(chip, MS_FLASH_READ_ERROR); + ms_set_err_code(chip, + MS_FLASH_READ_ERROR); rtsx_trace(chip); return STATUS_FAIL; } @@ -3883,8 +3905,9 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, return STATUS_FAIL; } #endif - old_blk = ms_get_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no]); + old_blk = ms_get_l2p_tbl + (chip, seg_no, + log_blk - ms_start_idx[seg_no]); new_blk = ms_get_unused_block(chip, seg_no); if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) { set_sense_type(chip, lun, @@ -3896,8 +3919,10 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, retval = ms_prepare_write(chip, old_blk, new_blk, log_blk, start_page); if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - set_sense_type(chip, lun, + if (detect_card_cd(chip, MS_CARD) != + STATUS_SUCCESS) { + set_sense_type + (chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; @@ -4048,8 +4073,10 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, retval = ms_finish_write(chip, old_blk, new_blk, log_blk, end_page); if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - set_sense_type(chip, lun, + if (detect_card_cd(chip, MS_CARD) != + STATUS_SUCCESS) { + set_sense_type + (chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); rtsx_trace(chip); return STATUS_FAIL; @@ -4627,7 +4654,8 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { if (ms_card->mg_auth == 0) { if ((buf[5] & 0xC0) != 0) - set_sense_type(chip, lun, + set_sense_type + (chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); else set_sense_type(chip, lun, @@ -4666,7 +4694,9 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_clear_ms_error(chip); if (ms_card->mg_auth == 0) { if ((buf[5] & 0xC0) != 0) - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + set_sense_type + (chip, lun, + SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); else set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); @@ -4686,8 +4716,9 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_clear_ms_error(chip); if (ms_card->mg_auth == 0) { if ((buf[5] & 0xC0) != 0) - set_sense_type(chip, lun, - SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + set_sense_type + (chip, lun, + SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); else set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); @@ -4722,7 +4753,8 @@ void ms_cleanup_work(struct rtsx_chip *chip) } } #ifdef MS_DELAY_WRITE - else if ((!CHK_MSPRO(ms_card)) && ms_card->delay_write.delay_write_flag) { + else if ((!CHK_MSPRO(ms_card)) && + ms_card->delay_write.delay_write_flag) { dev_dbg(rtsx_dev(chip), "MS: delay write\n"); ms_delay_write(chip); ms_card->cleanup_counter = 0; -- cgit v1.2.3 From 36e32ee542ac1981127dcc2f8dcd2a2278097e90 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:55 +0000 Subject: staging: rts5208: ms.c: Multiple assignments Fix check found by checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 0573d80bc968..d9bf3d011ccb 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -2646,7 +2646,8 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) disable_cnt = segment->disable_count; - segment->get_index = segment->set_index = 0; + segment->get_index = 0; + segment->set_index = 0; segment->unused_blk_cnt = 0; for (phy_blk = start; phy_blk < end; phy_blk++) { -- cgit v1.2.3 From a3e7c0928b2de3a169be478fb37a6727a834a853 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:56 +0000 Subject: staging: rts5208: ms.c: Braces fix Add braces to all arms of if statement Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index d9bf3d011ccb..2dd682300288 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -805,9 +805,9 @@ static int ms_confirm_cpu_startup(struct rtsx_chip *chip) } if (val & INT_REG_ERR) { - if (val & INT_REG_CMDNK) + if (val & INT_REG_CMDNK) { chip->card_wp |= (MS_CARD); - else { + } else { rtsx_trace(chip); return STATUS_FAIL; } -- cgit v1.2.3 From d264ceb7796a187777bc23318d35fcc74ac7c6e3 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:57 +0000 Subject: staging: rts5208: CamelCase fix Change label to not use camel case per checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 2dd682300288..28d56c5d1449 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -1328,7 +1328,7 @@ static int reset_ms_pro(struct rtsx_chip *chip) #endif #ifdef XC_POWERCLASS -Retry: +retry: #endif retval = ms_pro_reset_flow(chip, 1); if (retval != STATUS_SUCCESS) { @@ -1379,7 +1379,7 @@ Retry: change_power_class); if (retval != STATUS_SUCCESS) { change_power_class--; - goto Retry; + goto retry; } } } -- cgit v1.2.3 From 7314203b38bb8cfc02ae3e78c4135f2a8a198102 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:58 +0000 Subject: staging: rts5208: rtsx_scsi.h: Long lines Aligning with parenthesis causes lines to go too long, so the parenthesis are on a new line Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_scsi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index aac3435df32d..a95c5de1aa00 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -973,8 +973,9 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { chip->rw_fail_cnt[lun]++; if (srb->sc_data_direction == DMA_FROM_DEVICE) - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + set_sense_type + (chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); else set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); @@ -1981,8 +1982,9 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = rtsx_read_phy_register(chip, addr + i, &val); if (retval != STATUS_SUCCESS) { vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + set_sense_type + (chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); return TRANSPORT_FAILED; } -- cgit v1.2.3 From 7b468a297d7f3a3e2e4e3ee3d2bef5b88ed52cb2 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:56:59 +0000 Subject: staging: rts5208: rtxs_chip.h: Long lines Move comments above long definitions so they don't go over 80 characters Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_chip.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index aaf4fae4768c..4f6e3c1c4621 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -130,16 +130,20 @@ #define PRDCT_REV_LEN 4 /* Product LOT Length */ /* Dynamic flag definitions: used in set_bit() etc. */ -#define RTSX_FLIDX_TRANS_ACTIVE 18 /* 0x00040000 transfer is active */ -#define RTSX_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */ -#define RTSX_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */ +/* 0x00040000 transfer is active */ +#define RTSX_FLIDX_TRANS_ACTIVE 18 +/* 0x00100000 abort is in progress */ +#define RTSX_FLIDX_ABORTING 20 +/* 0x00200000 disconnect in progress */ +#define RTSX_FLIDX_DISCONNECTING 21 #define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \ (1UL << US_FLIDX_DISCONNECTING)) -#define RTSX_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */ -#define RTSX_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI midlayer timed out */ - +/* 0x00400000 device reset in progress */ +#define RTSX_FLIDX_RESETTING 22 +/* 0x00800000 SCSI midlayer timed out */ +#define RTSX_FLIDX_TIMED_OUT 23 #define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */ #define RMB_DISC 0x80 /* The Device is Removable */ #define ANSI_SCSI2 0x02 /* Based on ANSI-SCSI2 */ -- cgit v1.2.3 From 88936fe8530499d1a08d11e357eeae05317dd095 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:57:00 +0000 Subject: staging: rts5208: rtsx_chip.c: Long lines Fix lines that go over 80 characters to stop warnings from checkpatch Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_chip.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c index a10dd6220a7b..3511157a2c78 100644 --- a/drivers/staging/rts5208/rtsx_chip.c +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -114,7 +114,8 @@ static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip) if (chip->asic_code) { retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU); + MS_INS_PU | SD_WP_PU | + SD_CD_PU | SD_CMD_PU); if (retval) { rtsx_trace(chip); return retval; @@ -240,10 +241,10 @@ static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip) return STATUS_FAIL; } } else { - retval = rtsx_write_register(chip, - FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, - 0); + retval = rtsx_write_register + (chip, FPGA_PULL_CTL, + FPGA_SD_PULL_CTL_BIT | 0x20, + 0); if (retval) { rtsx_trace(chip); return retval; @@ -713,7 +714,8 @@ nextcard: if (chip->ft2_fast_mode) { retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF, - MS_PARTIAL_POWER_ON | SD_PARTIAL_POWER_ON); + MS_PARTIAL_POWER_ON | + SD_PARTIAL_POWER_ON); if (retval) { rtsx_trace(chip); return retval; @@ -1567,7 +1569,8 @@ int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, } retval = rtsx_write_register(chip, CFGRWCTL, 0xFF, - 0x80 | mode | ((func_no & 0x03) << 4)); + 0x80 | mode | + ((func_no & 0x03) << 4)); if (retval) { rtsx_trace(chip); return retval; -- cgit v1.2.3 From b41514b1def7047acf7806be9888939278a769c3 Mon Sep 17 00:00:00 2001 From: Wayne Porter Date: Tue, 11 Oct 2016 21:57:01 +0000 Subject: staging: rts5208: rtsx.c: Alignment fix Line goes too long when aligned with parenthesis, so moved to a new line Signed-off-by: Wayne Porter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index dafd8fdca1ed..f3e5efdf0ffc 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -728,9 +728,10 @@ static int rtsx_scan_thread(void *__dev) dev_info(&dev->pci->dev, "%s: waiting for device to settle before scanning\n", CR_DRIVER_NAME); - wait_event_interruptible_timeout(dev->delay_wait, - rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT), - delay_use * HZ); + wait_event_interruptible_timeout + (dev->delay_wait, + rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT), + delay_use * HZ); } /* If the device is still connected, perform the scanning */ -- cgit v1.2.3 From cd7b701f52d27c2278669e4de5c911807be8c10c Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Wed, 12 Oct 2016 14:11:31 -0300 Subject: staging: greybus: camera: Add blank lines after variable declarations. Fix checkpatch warning: WARNING: Missing a blank line after declarations Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/camera.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 491bdd720c0c..d89a329a7b5f 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -289,6 +289,7 @@ static const int gb_camera_configure_streams_validate_response( for (i = 0; i < resp->num_streams; i++) { struct gb_camera_stream_config_response *cfg = &resp->config[i]; + if (cfg->padding) { gcam_err(gcam, "stream #%u padding != 0\n", i); return -EIO; -- cgit v1.2.3 From 9d3318f48ce383cdd261719f4fa95c979bdd7ce4 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Wed, 12 Oct 2016 14:13:01 -0300 Subject: staging: greybus: camera: Replace blank spaces with tabstops. Fix checkpatch warning: WARNING: Statements should start on a tabstop Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index d89a329a7b5f..0c73445737b5 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -1119,7 +1119,7 @@ static ssize_t gb_camera_debugfs_write(struct file *file, char *kbuf; if (len > 1024) - return -EINVAL; + return -EINVAL; kbuf = kmalloc(len + 1, GFP_KERNEL); if (!kbuf) -- cgit v1.2.3 From c4fc2ebcbf762a1fe827931d670452aa27abef00 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Wed, 12 Oct 2016 14:14:14 -0300 Subject: staging: greybus: camera: Use kcalloc for array's memory allocation. Fix checkpatch warning: WARNING: Prefer kcalloc over kzalloc with multiply kcalloc is designed to allocate memory for arrays, its use is preferable than kzalloc in these cases. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 0c73445737b5..1c5b41ae6774 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -797,7 +797,7 @@ static int gb_camera_op_configure_streams(void *priv, unsigned int *nstreams, if (gb_nstreams > GB_CAMERA_MAX_STREAMS) return -EINVAL; - gb_streams = kzalloc(gb_nstreams * sizeof(*gb_streams), GFP_KERNEL); + gb_streams = kcalloc(gb_nstreams, sizeof(*gb_streams), GFP_KERNEL); if (!gb_streams) return -ENOMEM; @@ -938,7 +938,7 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, return ret; /* For each stream to configure parse width, height and format */ - streams = kzalloc(nstreams * sizeof(*streams), GFP_KERNEL); + streams = kcalloc(nstreams, sizeof(*streams), GFP_KERNEL); if (!streams) return -ENOMEM; -- cgit v1.2.3 From cf3ba55dca149b0525063a9c6127d0407e4fe8a8 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Wed, 12 Oct 2016 14:16:34 -0300 Subject: staging: greybus: arche-platform: Format block comments. Fix checkpatch warning: WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/arche-platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index e36ee984485b..a850f6bd84c1 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -455,7 +455,8 @@ retry: goto exit; /* First we want to make sure we power off everything - * and then activate back again */ + * and then activate back again + */ device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); arche_platform_poweroff_seq(arche_pdata); -- cgit v1.2.3 From cb2ec2eff20690397ba65c479074d89eeef11004 Mon Sep 17 00:00:00 2001 From: Chase Metzger Date: Wed, 12 Oct 2016 12:50:14 -0700 Subject: staging: greybus: timesync.c: Fixed WARNING for brace issue Removed a checkpatch warning for braces on single argument if and else statement. Signed-off-by: Chase Metzger Acked-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/timesync.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 2e68af7dea6d..e586627f4bbc 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -807,11 +807,11 @@ static int gb_timesync_schedule(struct gb_timesync_svc *timesync_svc, int state) return -EINVAL; mutex_lock(×ync_svc->mutex); - if (timesync_svc->state != GB_TIMESYNC_STATE_INVALID) { + if (timesync_svc->state != GB_TIMESYNC_STATE_INVALID) gb_timesync_set_state_atomic(timesync_svc, state); - } else { + else ret = -ENODEV; - } + mutex_unlock(×ync_svc->mutex); return ret; } -- cgit v1.2.3 From 4b6588dc2fedff4dc95095f1157e778611e440be Mon Sep 17 00:00:00 2001 From: Alexander Alemayhu Date: Thu, 13 Oct 2016 05:57:20 +0200 Subject: staging: i4l: pcbit: replace some include asm/*.h with linux/*.h Fixes the following checkpatch output: ./pcbit/capi.c:39: WARNING: Use #include instead of ./pcbit/capi.c:40: WARNING: Use #include instead of ./pcbit/callbacks.c:25: WARNING: Use #include instead of ./pcbit/layer2.c:39: WARNING: Use #include instead of ./pcbit/drv.c:34: WARNING: Use #include instead of ./pcbit/drv.c:35: WARNING: Use #include instead of ./pcbit/edss1.c:26: WARNING: Use #include instead of Signed-off-by: Alexander Alemayhu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/pcbit/callbacks.c | 2 +- drivers/staging/i4l/pcbit/capi.c | 4 ++-- drivers/staging/i4l/pcbit/drv.c | 4 ++-- drivers/staging/i4l/pcbit/edss1.c | 2 +- drivers/staging/i4l/pcbit/layer2.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/i4l/pcbit/callbacks.c b/drivers/staging/i4l/pcbit/callbacks.c index efb6d6a3639a..212ab0b229d4 100644 --- a/drivers/staging/i4l/pcbit/callbacks.c +++ b/drivers/staging/i4l/pcbit/callbacks.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include diff --git a/drivers/staging/i4l/pcbit/capi.c b/drivers/staging/i4l/pcbit/capi.c index 373f90feda5a..91f299477d43 100644 --- a/drivers/staging/i4l/pcbit/capi.c +++ b/drivers/staging/i4l/pcbit/capi.c @@ -36,8 +36,8 @@ #include -#include -#include +#include +#include #include diff --git a/drivers/staging/i4l/pcbit/drv.c b/drivers/staging/i4l/pcbit/drv.c index d417df5efb5f..87b852259b89 100644 --- a/drivers/staging/i4l/pcbit/drv.c +++ b/drivers/staging/i4l/pcbit/drv.c @@ -31,8 +31,8 @@ #include #include -#include -#include +#include +#include #include #include "pcbit.h" diff --git a/drivers/staging/i4l/pcbit/edss1.c b/drivers/staging/i4l/pcbit/edss1.c index 6d291d548423..5980d1b5da95 100644 --- a/drivers/staging/i4l/pcbit/edss1.c +++ b/drivers/staging/i4l/pcbit/edss1.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include diff --git a/drivers/staging/i4l/pcbit/layer2.c b/drivers/staging/i4l/pcbit/layer2.c index a136c72547e5..0592bf6ee9c9 100644 --- a/drivers/staging/i4l/pcbit/layer2.c +++ b/drivers/staging/i4l/pcbit/layer2.c @@ -36,7 +36,7 @@ #include -#include +#include #include "pcbit.h" -- cgit v1.2.3 From f4190ce37f083d4b96aca315de383f0ca6140d14 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 12 Oct 2016 17:57:49 +0300 Subject: staging:vt6656:card.c: fix block comments should align the * on each line Block comments should align the * on each line as reported by checkpatch.pl Signed-off-by: Mikhail Golubev Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/card.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 53b469c71dc2..807d3f7af58d 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -610,8 +610,8 @@ u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval) beacon_int = beacon_interval * 1024; /* Next TBTT = - * ((local_current_TSF / beacon_interval) + 1) * beacon_interval - */ + * ((local_current_TSF / beacon_interval) + 1) * beacon_interval + */ if (beacon_int) { do_div(tsf, beacon_int); tsf += 1; -- cgit v1.2.3 From bee80f2926342acc3bca4efa90b26a892fe28ef0 Mon Sep 17 00:00:00 2001 From: Varsha Rao Date: Fri, 14 Oct 2016 00:17:22 +0530 Subject: staging: vt6655: Adding space around '+' This patch fixes the checkpatch issue by adding space around the operator '+'. Signed-off-by: Varsha Rao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/card.h | 2 +- drivers/staging/vt6655/device.h | 12 +- drivers/staging/vt6655/mac.c | 2 +- drivers/staging/vt6655/rf.c | 636 ++++++++++++++++++++-------------------- 4 files changed, 326 insertions(+), 326 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 2f0f893a6971..44420b5a445f 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -46,7 +46,7 @@ #define CB_MAX_CHANNEL_24G 14 #define CB_MAX_CHANNEL_5G 42 -#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G+CB_MAX_CHANNEL_5G) +#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G) typedef enum _CARD_PKT_TYPE { PKT_TYPE_802_11_BCN, diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 6263c29d51fc..3ae40d846a09 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -279,12 +279,12 @@ struct vnt_private { unsigned char byOFDMPwrG; unsigned char byCurPwr; char byCurPwrdBm; - unsigned char abyCCKPwrTbl[CB_MAX_CHANNEL_24G+1]; - unsigned char abyOFDMPwrTbl[CB_MAX_CHANNEL+1]; - char abyCCKDefaultPwr[CB_MAX_CHANNEL_24G+1]; - char abyOFDMDefaultPwr[CB_MAX_CHANNEL+1]; - char abyRegPwr[CB_MAX_CHANNEL+1]; - char abyLocalPwr[CB_MAX_CHANNEL+1]; + unsigned char abyCCKPwrTbl[CB_MAX_CHANNEL_24G + 1]; + unsigned char abyOFDMPwrTbl[CB_MAX_CHANNEL + 1]; + char abyCCKDefaultPwr[CB_MAX_CHANNEL_24G + 1]; + char abyOFDMDefaultPwr[CB_MAX_CHANNEL + 1]; + char abyRegPwr[CB_MAX_CHANNEL + 1]; + char abyLocalPwr[CB_MAX_CHANNEL + 1]; /* BaseBand Loopback Use */ unsigned char byBBCR4d; diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 359b3c3960f8..4aaa99bafcda 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -315,7 +315,7 @@ bool MACbSoftwareReset(struct vnt_private *priv) */ bool MACbSafeSoftwareReset(struct vnt_private *priv) { - unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0+MAC_MAX_CONTEXT_SIZE_PAGE1]; + unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0 + MAC_MAX_CONTEXT_SIZE_PAGE1]; bool bRetVal; /* PATCH.... diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 1d00f45385b4..fa5690dc13da 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -45,359 +45,359 @@ #define AL7230_PWR_IDX_LEN 64 static const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = { - 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x00FFF300+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0F4DC500+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0805B600+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0146C700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x00068800+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0403B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x00DBBA00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0BDFFC00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x00000D00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x00580F00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW + 0x03F79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x01A00200 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x00FFF300 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0005A400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0F4DC500 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0805B600 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0146C700 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x00068800 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0403B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x00DBBA00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x00099B00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0BDFFC00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x00000D00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x00580F00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW }; static const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = { - 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x03F7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 14, Tf = 2412M */ + 0x03F79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x03F79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x03E79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x03E79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x03F7A000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x03F7A000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x03E7A000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x03E7A000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x03F7B000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x03F7B000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x03E7B000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x03E7B000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x03F7C000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x03E7C000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ }; static const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = { - 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 14, Tf = 2412M */ + 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x06666100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ }; static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { - 0x04040900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04041900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04042900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04043900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04044900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04045900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04046900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04047900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04048900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04049900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0404A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0404B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0404C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0404D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0404E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0404F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04050900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04051900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04052900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04053900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04054900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04055900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04056900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04057900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04058900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04059900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0405A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0405B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0405C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0405D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0405E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0405F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04060900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04061900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04062900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04063900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04064900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04065900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04066900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04067900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04068900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04069900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0406A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0406B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0406C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0406D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0406E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0406F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04070900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04071900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04072900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04073900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04074900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04075900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04076900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04077900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04078900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x04079900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0407A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0407B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0407C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0407D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0407E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, - 0x0407F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW + 0x04040900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04041900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04042900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04043900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04044900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04045900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04046900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04047900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04048900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04049900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0404A900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0404B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0404C900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0404D900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0404E900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0404F900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04050900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04051900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04052900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04053900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04054900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04055900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04056900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04057900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04058900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04059900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0405A900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0405B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0405C900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0405D900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0405E900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0405F900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04060900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04061900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04062900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04063900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04064900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04065900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04066900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04067900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04068900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04069900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0406A900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0406B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0406C900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0406D900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0406E900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0406F900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04070900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04071900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04072900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04073900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04074900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04075900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04076900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04077900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04078900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x04079900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0407A900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0407B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0407C900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0407D900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0407E900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, + 0x0407F900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW }; /* 40MHz reference frequency * Need to Pull PLLON(PE3) low when writing channel registers through 3-wire. */ static const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = { - 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ - 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ - 0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 451FE2 */ - 0x3FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 5FDFA3 */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* 11b/g // Need modify for 11a */ + 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ + 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ + 0x841FF200 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 451FE2 */ + 0x3FDFA300 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 5FDFA3 */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* 11b/g // Need modify for 11a */ /* RoberYu:20050113, Rev0.47 Regsiter Setting Guide */ - 0x802B5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 8D1B55 */ - 0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 860207 */ - 0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0xE0000A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: E0600A */ - 0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */ + 0x802B5500 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 8D1B55 */ + 0x56AF3600 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0xCE020700 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 860207 */ + 0x6EBC0800 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0x221BB900 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0xE0000A00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: E0600A */ + 0x08031B00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */ /* RoberYu:20050113, Rev0.47 Regsiter Setting Guide */ - 0x000A3C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 00143C */ - 0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* Need modify for 11a: 12BACF */ + 0x000A3C00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 00143C */ + 0xFFFFFD00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0x00000E00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0x1ABA8F00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* Need modify for 11a: 12BACF */ }; static const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = { - 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */ - 0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */ - 0x5FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */ - 0x67F78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* 11a // Need modify for 11b/g */ - 0x853F5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g, RoberYu:20050113 */ - 0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */ - 0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0xE0600A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */ - 0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */ - 0x00147C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */ - 0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, - 0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* Need modify for 11b/g */ + 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */ + 0x451FE200 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0x5FDFA300 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0x67F78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* 11a // Need modify for 11b/g */ + 0x853F5500 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g, RoberYu:20050113 */ + 0x56AF3600 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0xCE020700 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0x6EBC0800 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0x221BB900 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0xE0600A00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0x08031B00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */ + 0x00147C00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0xFFFFFD00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0x00000E00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, + 0x12BACF00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* Need modify for 11b/g */ }; static const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = { - 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ + 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x0037A000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x0037A000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x0037A000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x0037A000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037B000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037B000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037B000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037B000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */ - 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ - 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ - 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ - 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ - 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ - 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ - 0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ - 0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ + 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ + 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ + 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ + 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ + 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ + 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ + 0x0FF53000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ + 0x0FF53000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */ - 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ - 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ - 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ - 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ - 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ - 0x0FF55000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ - 0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ - 0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ - 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49 */ - 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ - 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ - 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ - 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ - 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ - 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ - 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ - 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ - 0x0FF59000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ - - 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ - 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ - 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ - 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ - 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ - 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ - 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ - 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ - 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ - 0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ - 0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ - 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ - 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ - 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ - 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ - 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ + 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ + 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ + 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ + 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ + 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ + 0x0FF55000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ + 0x0FF56000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ + 0x0FF56000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ + 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49 */ + 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ + 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ + 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ + 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ + 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ + 0x0FF58000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ + 0x0FF58000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ + 0x0FF58000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ + 0x0FF59000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ + + 0x0FF5C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ + 0x0FF5C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ + 0x0FF5C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ + 0x0FF5D000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ + 0x0FF5D000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ + 0x0FF5D000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ + 0x0FF5E000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ + 0x0FF5E000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ + 0x0FF5E000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ + 0x0FF5F000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ + 0x0FF5F000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ + 0x0FF60000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ + 0x0FF60000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ + 0x0FF60000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ + 0x0FF61000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ + 0x0FF61000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ }; static const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = { - 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x1B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x03333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x0B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x1B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x03333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x0B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x1B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x03333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x0B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ 0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */ - 0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ - 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ - 0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ - 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ - 0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ + 0x1D555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ + 0x02AAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ + 0x08000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ + 0x0D555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */ - 0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ - 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ - 0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ - 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ - 0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ - 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ - 0x10000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ - 0x1AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ - 0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ - 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ - 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ - 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ - 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ - 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ - 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ - 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ - 0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ - 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ - 0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ - 0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ - 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ + 0x1D555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ + 0x02AAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ + 0x08000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ + 0x05555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ + 0x10000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ + 0x1AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ + 0x05555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ + 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ + 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ + 0x18000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ + 0x02AAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ + 0x0D555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ + 0x18000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ + 0x02AAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ }; static const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = { - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ - 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ - 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ + 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ + 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ }; /* @@ -436,10 +436,10 @@ static bool s_bAL7230Init(struct vnt_private *priv) /* Calibration */ MACvTimer0MicroSDelay(priv, 150);/* 150us */ /* TXDCOC:active, RCK:disable */ - ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW)); MACvTimer0MicroSDelay(priv, 30);/* 30us */ /* TXDCOC:disable, RCK:active */ - ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW)); MACvTimer0MicroSDelay(priv, 30);/* 30us */ /* TXDCOC:disable, RCK:disable */ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); @@ -550,7 +550,7 @@ static bool RFbAL2230Init(struct vnt_private *priv) MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); /* patch abnormal AL2230 frequency output */ - IFRFbWriteEmbedded(priv, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + IFRFbWriteEmbedded(priv, (0x07168700 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW)); for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]); @@ -560,9 +560,9 @@ static bool RFbAL2230Init(struct vnt_private *priv) MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); MACvTimer0MicroSDelay(priv, 150);/* 150us */ - ret &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x00d80f00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW)); MACvTimer0MicroSDelay(priv, 30);/* 30us */ - ret &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x00780f00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW)); MACvTimer0MicroSDelay(priv, 30);/* 30us */ ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); @@ -850,20 +850,20 @@ bool RFbRawSetPower( case RF_AIROHA: ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); if (rate <= RATE_11M) - ret &= IFRFbWriteEmbedded(priv, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0001B400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); else - ret &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); break; case RF_AL2230S: ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); if (rate <= RATE_11M) { - ret &= IFRFbWriteEmbedded(priv, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - ret &= IFRFbWriteEmbedded(priv, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x040C1400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00299B00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); } else { - ret &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - ret &= IFRFbWriteEmbedded(priv, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00099B00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); } break; -- cgit v1.2.3 From 0a9e0f54b39b5e6431b228bf02a28d9cd20c7dd8 Mon Sep 17 00:00:00 2001 From: Varsha Rao Date: Fri, 14 Oct 2016 00:29:22 +0530 Subject: staging: vt6655: Adding space around '<<' This patch fixes the checkpatch issue by adding space around '<<'. Signed-off-by: Varsha Rao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/rf.c | 638 ++++++++++++++++++++++---------------------- 1 file changed, 319 insertions(+), 319 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index fa5690dc13da..1762c05f2a3e 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -45,359 +45,359 @@ #define AL7230_PWR_IDX_LEN 64 static const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = { - 0x03F79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x01A00200 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x00FFF300 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0005A400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0F4DC500 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0805B600 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0146C700 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x00068800 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0403B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x00DBBA00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x00099B00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0BDFFC00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x00000D00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x00580F00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW + 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x01A00200 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00FFF300 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0F4DC500 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0805B600 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0146C700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00068800 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0403B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00DBBA00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0BDFFC00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00000D00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00580F00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW }; static const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = { - 0x03F79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x03F79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x03E79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x03E79000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x03F7A000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x03F7A000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x03E7A000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x03E7A000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x03F7B000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x03F7B000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x03E7B000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x03E7B000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x03F7C000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x03E7C000 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ + 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x03F7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x03E7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ }; static const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = { - 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x03333100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x06666100 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x06666100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ }; static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { - 0x04040900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04041900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04042900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04043900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04044900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04045900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04046900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04047900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04048900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04049900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0404A900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0404B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0404C900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0404D900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0404E900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0404F900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04050900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04051900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04052900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04053900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04054900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04055900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04056900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04057900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04058900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04059900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0405A900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0405B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0405C900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0405D900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0405E900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0405F900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04060900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04061900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04062900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04063900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04064900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04065900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04066900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04067900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04068900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04069900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0406A900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0406B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0406C900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0406D900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0406E900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0406F900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04070900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04071900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04072900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04073900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04074900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04075900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04076900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04077900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04078900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x04079900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0407A900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0407B900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0407C900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0407D900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0407E900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW, - 0x0407F900 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW + 0x04040900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04041900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04042900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04043900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04044900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04045900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04046900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04047900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04048900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04049900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04050900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04051900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04052900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04053900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04054900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04055900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04056900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04057900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04058900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04059900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04060900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04061900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04062900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04063900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04064900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04065900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04066900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04067900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04068900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04069900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04070900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04071900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04072900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04073900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04074900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04075900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04076900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04077900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04078900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04079900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW }; /* 40MHz reference frequency * Need to Pull PLLON(PE3) low when writing channel registers through 3-wire. */ static const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = { - 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ - 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ - 0x841FF200 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 451FE2 */ - 0x3FDFA300 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 5FDFA3 */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* 11b/g // Need modify for 11a */ + 0x00379000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ + 0x13333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ + 0x841FF200 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11a: 451FE2 */ + 0x3FDFA300 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11a: 5FDFA3 */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* 11b/g // Need modify for 11a */ /* RoberYu:20050113, Rev0.47 Regsiter Setting Guide */ - 0x802B5500 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 8D1B55 */ - 0x56AF3600 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0xCE020700 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 860207 */ - 0x6EBC0800 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0x221BB900 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0xE0000A00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: E0600A */ - 0x08031B00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */ + 0x802B5500 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11a: 8D1B55 */ + 0x56AF3600 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0xCE020700 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11a: 860207 */ + 0x6EBC0800 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0x221BB900 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0xE0000A00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11a: E0600A */ + 0x08031B00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */ /* RoberYu:20050113, Rev0.47 Regsiter Setting Guide */ - 0x000A3C00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11a: 00143C */ - 0xFFFFFD00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0x00000E00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0x1ABA8F00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* Need modify for 11a: 12BACF */ + 0x000A3C00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11a: 00143C */ + 0xFFFFFD00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00000E00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0x1ABA8F00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW /* Need modify for 11a: 12BACF */ }; static const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = { - 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */ - 0x451FE200 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ - 0x5FDFA300 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ - 0x67F78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* 11a // Need modify for 11b/g */ - 0x853F5500 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g, RoberYu:20050113 */ - 0x56AF3600 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0xCE020700 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ - 0x6EBC0800 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0x221BB900 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0xE0600A00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ - 0x08031B00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */ - 0x00147C00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* Need modify for 11b/g */ - 0xFFFFFD00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0x00000E00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, - 0x12BACF00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* Need modify for 11b/g */ + 0x0FF52000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */ + 0x451FE200 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0x5FDFA300 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0x67F78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* 11a // Need modify for 11b/g */ + 0x853F5500 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11b/g, RoberYu:20050113 */ + 0x56AF3600 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0xCE020700 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0x6EBC0800 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0x221BB900 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0xE0600A00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0x08031B00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */ + 0x00147C00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* Need modify for 11b/g */ + 0xFFFFFD00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00000E00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, + 0x12BACF00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW /* Need modify for 11b/g */ }; static const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = { - 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x00379000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x0037A000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x0037A000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x0037A000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x0037A000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037B000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037B000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037B000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037B000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49 */ - 0x0037C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ + 0x00379000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x00379000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x00379000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x00379000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x0037A000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x0037A000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x0037A000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x0037A000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037B000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037B000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037B000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037B000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037C000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49 */ + 0x0037C000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */ - 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ - 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ - 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ - 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ - 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ - 0x0FF52000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ - 0x0FF53000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ - 0x0FF53000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ + 0x0FF52000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ + 0x0FF52000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ + 0x0FF52000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ + 0x0FF52000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ + 0x0FF52000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ + 0x0FF52000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ + 0x0FF53000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ + 0x0FF53000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */ - 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ - 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ - 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ - 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ - 0x0FF54000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ - 0x0FF55000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ - 0x0FF56000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ - 0x0FF56000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ - 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49 */ - 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ - 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ - 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ - 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ - 0x0FF57000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ - 0x0FF58000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ - 0x0FF58000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ - 0x0FF58000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ - 0x0FF59000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ - - 0x0FF5C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ - 0x0FF5C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ - 0x0FF5C000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ - 0x0FF5D000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ - 0x0FF5D000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ - 0x0FF5D000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ - 0x0FF5E000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ - 0x0FF5E000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ - 0x0FF5E000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ - 0x0FF5F000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ - 0x0FF5F000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ - 0x0FF60000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ - 0x0FF60000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ - 0x0FF60000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ - 0x0FF61000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ - 0x0FF61000 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ + 0x0FF54000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ + 0x0FF54000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ + 0x0FF54000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ + 0x0FF54000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ + 0x0FF54000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ + 0x0FF55000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ + 0x0FF56000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ + 0x0FF56000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ + 0x0FF57000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49 */ + 0x0FF57000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ + 0x0FF57000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ + 0x0FF57000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ + 0x0FF57000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ + 0x0FF57000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ + 0x0FF58000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ + 0x0FF58000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ + 0x0FF58000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ + 0x0FF59000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ + + 0x0FF5C000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ + 0x0FF5C000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ + 0x0FF5C000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ + 0x0FF5D000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ + 0x0FF5D000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ + 0x0FF5D000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ + 0x0FF5E000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ + 0x0FF5E000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ + 0x0FF5E000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ + 0x0FF5F000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ + 0x0FF5F000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ + 0x0FF60000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ + 0x0FF60000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ + 0x0FF60000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ + 0x0FF61000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ + 0x0FF61000 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ }; static const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = { - 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x1B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x03333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x0B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x1B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x03333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x0B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x1B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x03333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x0B333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x13333100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ + 0x13333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x1B333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x03333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x0B333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x13333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x1B333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x03333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x0B333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x13333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x1B333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x03333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x0B333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x13333100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x06666100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */ - 0x1D555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ - 0x02AAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ - 0x08000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ - 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ - 0x0D555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ + 0x1D555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ + 0x02AAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ + 0x08000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ + 0x0D555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */ - 0x1D555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ - 0x02AAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ - 0x08000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ - 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ - 0x05555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ - 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ - 0x10000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ - 0x1AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ - 0x05555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ - 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ - 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ - 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ - 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ - 0x0AAAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ - 0x15555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ - 0x00000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ - 0x18000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ - 0x02AAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ - 0x0D555100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ - 0x18000100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ - 0x02AAA100 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ + 0x1D555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ + 0x02AAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ + 0x08000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ + 0x05555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ + 0x10000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ + 0x1AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ + 0x05555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ + 0x0AAAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ + 0x15555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ + 0x00000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ + 0x18000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ + 0x02AAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ + 0x0D555100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ + 0x18000100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ + 0x02AAA100 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ }; static const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = { - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x7FD78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x7FD78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ - 0x67D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ - 0x77D78400 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */ + 0x67D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */ + 0x77D78400 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */ }; /* @@ -436,10 +436,10 @@ static bool s_bAL7230Init(struct vnt_private *priv) /* Calibration */ MACvTimer0MicroSDelay(priv, 150);/* 150us */ /* TXDCOC:active, RCK:disable */ - ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW)); MACvTimer0MicroSDelay(priv, 30);/* 30us */ /* TXDCOC:disable, RCK:active */ - ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00 + (BY_AL7230_REG_LEN<<3) + IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW)); MACvTimer0MicroSDelay(priv, 30);/* 30us */ /* TXDCOC:disable, RCK:disable */ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); @@ -550,7 +550,7 @@ static bool RFbAL2230Init(struct vnt_private *priv) MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); /* patch abnormal AL2230 frequency output */ - IFRFbWriteEmbedded(priv, (0x07168700 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW)); + IFRFbWriteEmbedded(priv, (0x07168700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]); @@ -560,9 +560,9 @@ static bool RFbAL2230Init(struct vnt_private *priv) MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); MACvTimer0MicroSDelay(priv, 150);/* 150us */ - ret &= IFRFbWriteEmbedded(priv, (0x00d80f00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x00d80f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); MACvTimer0MicroSDelay(priv, 30);/* 30us */ - ret &= IFRFbWriteEmbedded(priv, (0x00780f00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x00780f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); MACvTimer0MicroSDelay(priv, 30);/* 30us */ ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); @@ -850,20 +850,20 @@ bool RFbRawSetPower( case RF_AIROHA: ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); if (rate <= RATE_11M) - ret &= IFRFbWriteEmbedded(priv, 0x0001B400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0001B400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); else - ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); break; case RF_AL2230S: ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); if (rate <= RATE_11M) { - ret &= IFRFbWriteEmbedded(priv, 0x040C1400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); - ret &= IFRFbWriteEmbedded(priv, 0x00299B00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x040C1400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00299B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); } else { - ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); - ret &= IFRFbWriteEmbedded(priv, 0x00099B00 + (BY_AL2230_REG_LEN<<3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); } break; -- cgit v1.2.3 From daf60ef9040da94b4a2e5997f4c40257d4a9b8df Mon Sep 17 00:00:00 2001 From: Varsha Rao Date: Fri, 14 Oct 2016 04:29:54 +0530 Subject: Staging: vt6655: Removes unused macros. This patch removes the macros BBvClearFOE and BBvSetFOE. As they are not used anywhere else. Signed-off-by: Varsha Rao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index 412537e3fb75..8a567c9155b4 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -55,12 +55,6 @@ #define TOP_RATE_2M 0x00200000 #define TOP_RATE_1M 0x00100000 -#define BBvClearFOE(dwIoBase) \ - BBbWriteEmbedded(dwIoBase, 0xB1, 0) - -#define BBvSetFOE(dwIoBase) \ - BBbWriteEmbedded(dwIoBase, 0xB1, 0x0C) - unsigned int BBuGetFrameTime( unsigned char byPreambleType, -- cgit v1.2.3 From 42178baf4af085be43aea426ff926914fc202d5b Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Thu, 13 Oct 2016 18:27:31 +0300 Subject: Staging: rtl8188eu: hal: Compress return logic into one line Simplify function returns by merging assignment and return into one command line. Found with Coccinelle @@ expression e, ret; @@ -ret = +return e; -return ret; Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/phy.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 109c2d7704ff..35c91e06cc47 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -40,12 +40,11 @@ static u32 cal_bit_shift(u32 bitmask) u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask) { - u32 return_value = 0, original_value, bit_shift; + u32 original_value, bit_shift; original_value = usb_read32(adapt, regaddr); bit_shift = cal_bit_shift(bitmask); - return_value = (original_value & bitmask) >> bit_shift; - return return_value; + return (original_value & bitmask) >> bit_shift; } void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data) @@ -119,12 +118,11 @@ static void rf_serial_write(struct adapter *adapt, u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path, u32 reg_addr, u32 bit_mask) { - u32 original_value, readback_value, bit_shift; + u32 original_value, bit_shift; original_value = rf_serial_read(adapt, rf_path, reg_addr); bit_shift = cal_bit_shift(bit_mask); - readback_value = (original_value & bit_mask) >> bit_shift; - return readback_value; + return (original_value & bit_mask) >> bit_shift; } void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, -- cgit v1.2.3 From 1cbe7adb9c6d10830494e81f2867858da2fd4c53 Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Thu, 13 Oct 2016 19:45:59 +0300 Subject: Staging: netlogic: Compress return logic into one line Simplify function returns by merging assignment and return into one command line. Found with Coccinelle @@ expression e, ret; @@ -ret = +return e; -return ret; Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/netlogic/xlr_net.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index cdf01b931296..fb0928a4fb97 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -1007,10 +1007,8 @@ static int xlr_net_probe(struct platform_device *pdev) */ adapter = (struct xlr_adapter *) devm_kzalloc(&pdev->dev, sizeof(*adapter), GFP_KERNEL); - if (!adapter) { - err = -ENOMEM; - return err; - } + if (!adapter) + return -ENOMEM; /* * XLR and XLS have 1 and 2 NAE controller respectively -- cgit v1.2.3 From 3b438f2ca9bbf43718b6155bdd9d4841eebb63ab Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Fri, 14 Oct 2016 00:00:51 +0300 Subject: Staging: wilc1000: Compress return logic into one line Simplify function returns by merging assignment and return into one command line. Delete unnecesarry return variable. Found with Coccinelle @@ expression e, ret; @@ -ret = +return e; -return ret Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 4 +--- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 18 +++++------------- 2 files changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 4b51c0ac27ac..622994795222 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -224,9 +224,7 @@ static inline u16 get_asoc_status(u8 *data) u16 asoc_status; asoc_status = data[3]; - asoc_status = (asoc_status << 8) | data[2]; - - return asoc_status; + return (asoc_status << 8) | data[2]; } static inline u16 get_asoc_id(u8 *data) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index fca96d3383e1..f46dcd291d92 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1591,28 +1591,25 @@ static int remain_on_channel(struct wiphy *wiphy, priv->strRemainOnChanParams.u32ListenDuration = duration; priv->strRemainOnChanParams.u32ListenSessionID++; - s32Error = wilc_remain_on_channel(vif, + return wilc_remain_on_channel(vif, priv->strRemainOnChanParams.u32ListenSessionID, duration, chan->hw_value, WILC_WFI_RemainOnChannelExpired, WILC_WFI_RemainOnChannelReady, (void *)priv); - - return s32Error; } static int cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) { - s32 s32Error = 0; struct wilc_priv *priv; struct wilc_vif *vif; priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - s32Error = wilc_listen_state_expired(vif, priv->strRemainOnChanParams.u32ListenSessionID); - return s32Error; + return wilc_listen_state_expired(vif, + priv->strRemainOnChanParams.u32ListenSessionID); } static int mgmt_tx(struct wiphy *wiphy, @@ -1936,12 +1933,10 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE); wilc_set_power_mgmt(vif, 0, 0); - s32Error = wilc_add_beacon(vif, settings->beacon_interval, + return wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, beacon->head_len, (u8 *)beacon->head, beacon->tail_len, (u8 *)beacon->tail); - - return s32Error; } static int change_beacon(struct wiphy *wiphy, struct net_device *dev, @@ -1949,16 +1944,13 @@ static int change_beacon(struct wiphy *wiphy, struct net_device *dev, { struct wilc_priv *priv; struct wilc_vif *vif; - s32 s32Error = 0; priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - s32Error = wilc_add_beacon(vif, 0, 0, beacon->head_len, + return wilc_add_beacon(vif, 0, 0, beacon->head_len, (u8 *)beacon->head, beacon->tail_len, (u8 *)beacon->tail); - - return s32Error; } static int stop_ap(struct wiphy *wiphy, struct net_device *dev) -- cgit v1.2.3 From 3f98afe0b6d6d8d7a72461f9b13da122fe08d20e Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Thu, 13 Oct 2016 19:40:04 -0300 Subject: staging: greybus: audio_codec: Remove useless return statement. Remove return statement that is immediately followed by the function closing bracket. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_codec.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 1bdf84925d22..f8862c6d7102 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -405,7 +405,6 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, params->state = GBAUDIO_CODEC_SHUTDOWN; mutex_unlock(&codec->lock); pm_relax(dai->dev); - return; } static int gbcodec_hw_params(struct snd_pcm_substream *substream, -- cgit v1.2.3 From 3fcb465f1e74ef0cb1edd921c3551170548051e2 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Thu, 13 Oct 2016 19:25:52 -0300 Subject: staging: sm750fb: Replace functions CamelCase naming with underscores. Replace CamelCase function names with underscores to comply with the standard kernel coding style. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 36 +++++++++++++++++----------------- drivers/staging/sm750fb/ddk750_chip.h | 8 ++++---- drivers/staging/sm750fb/ddk750_mode.c | 6 +++--- drivers/staging/sm750fb/ddk750_power.c | 12 ++++++------ drivers/staging/sm750fb/ddk750_power.h | 4 ++-- drivers/staging/sm750fb/sm750_hw.c | 6 +++--- 6 files changed, 36 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 2b231c28af16..a127eb2b4cbc 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -51,7 +51,7 @@ static unsigned int get_mxclk_freq(void) * * Input: Frequency to be set. */ -static void setChipClock(unsigned int frequency) +static void set_chip_clock(unsigned int frequency) { struct pll_value pll; unsigned int ulActualMxClk; @@ -68,19 +68,19 @@ static void setChipClock(unsigned int frequency) pll.clockType = MXCLK_PLL; /* - * Call calcPllValue() to fill the other fields of PLL structure. + * Call calc_pll_value() to fill the other fields of PLL structure. * Sometime, the chip cannot set up the exact clock * required by the User. - * Return value of calcPllValue gives the actual possible clock. + * Return value of calc_pll_value gives the actual possible clock. */ - ulActualMxClk = calcPllValue(frequency, &pll); + ulActualMxClk = calc_pll_value(frequency, &pll); /* Master Clock Control: MXCLK_PLL */ - POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll)); + POKE32(MXCLK_PLL_CTRL, format_pll_reg(&pll)); } } -static void setMemoryClock(unsigned int frequency) +static void set_memory_clock(unsigned int frequency) { unsigned int reg, divisor; @@ -119,7 +119,7 @@ static void setMemoryClock(unsigned int frequency) break; } - setCurrentGate(reg); + set_current_gate(reg); } } @@ -131,7 +131,7 @@ static void setMemoryClock(unsigned int frequency) * NOTE: * The maximum frequency the engine can run is 168MHz. */ -static void setMasterClock(unsigned int frequency) +static void set_master_clock(unsigned int frequency) { unsigned int reg, divisor; @@ -169,11 +169,11 @@ static void setMasterClock(unsigned int frequency) break; } - setCurrentGate(reg); + set_current_gate(reg); } } -unsigned int ddk750_getVMSize(void) +unsigned int ddk750_get_vm_size(void) { unsigned int reg; unsigned int data; @@ -205,18 +205,18 @@ unsigned int ddk750_getVMSize(void) return data; } -int ddk750_initHw(struct initchip_param *pInitParam) +int ddk750_init_hw(struct initchip_param *pInitParam) { unsigned int reg; if (pInitParam->powerMode != 0) pInitParam->powerMode = 0; - setPowerMode(pInitParam->powerMode); + set_power_mode(pInitParam->powerMode); /* Enable display power gate & LOCALMEM power gate*/ reg = PEEK32(CURRENT_GATE); reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM); - setCurrentGate(reg); + set_current_gate(reg); if (sm750_get_chip_type() != SM750LE) { /* set panel pll and graphic mode via mmio_88 */ @@ -232,13 +232,13 @@ int ddk750_initHw(struct initchip_param *pInitParam) } /* Set the Main Chip Clock */ - setChipClock(MHz((unsigned int)pInitParam->chipClock)); + set_chip_clock(MHz((unsigned int)pInitParam->chipClock)); /* Set up memory clock. */ - setMemoryClock(MHz(pInitParam->memClock)); + set_memory_clock(MHz(pInitParam->memClock)); /* Set up master clock */ - setMasterClock(MHz(pInitParam->masterClock)); + set_master_clock(MHz(pInitParam->masterClock)); /* Reset the memory controller. @@ -304,7 +304,7 @@ int ddk750_initHw(struct initchip_param *pInitParam) * M = {1,...,255} * N = {2,...,15} */ -unsigned int calcPllValue(unsigned int request_orig, struct pll_value *pll) +unsigned int calc_pll_value(unsigned int request_orig, struct pll_value *pll) { /* as sm750 register definition, * N located in 2,15 and M located in 1,255 @@ -372,7 +372,7 @@ unsigned int calcPllValue(unsigned int request_orig, struct pll_value *pll) return ret; } -unsigned int formatPllReg(struct pll_value *pPLL) +unsigned int format_pll_reg(struct pll_value *pPLL) { #ifndef VALIDATION_CHIP unsigned int POD = pPLL->POD; diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h index 755aab1e5442..3b731b48bfb5 100644 --- a/drivers/staging/sm750fb/ddk750_chip.h +++ b/drivers/staging/sm750fb/ddk750_chip.h @@ -77,9 +77,9 @@ struct initchip_param { logical_chip_type_t sm750_get_chip_type(void); void sm750_set_chip_type(unsigned short devId, char revId); -unsigned int calcPllValue(unsigned int request, struct pll_value *pll); -unsigned int formatPllReg(struct pll_value *pPLL); -unsigned int ddk750_getVMSize(void); -int ddk750_initHw(struct initchip_param *); +unsigned int calc_pll_value(unsigned int request, struct pll_value *pll); +unsigned int format_pll_reg(struct pll_value *pPLL); +unsigned int ddk750_get_vm_size(void); +int ddk750_init_hw(struct initchip_param *); #endif diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index 496491803a6b..b6af6f31e21c 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -80,7 +80,7 @@ static int programModeRegisters(mode_parameter_t *pModeParam, if (pll->clockType == SECONDARY_PLL) { /* programe secondary pixel clock */ - POKE32(CRT_PLL_CTRL, formatPllReg(pll)); + POKE32(CRT_PLL_CTRL, format_pll_reg(pll)); POKE32(CRT_HORIZONTAL_TOTAL, (((pModeParam->horizontal_total - 1) << CRT_HORIZONTAL_TOTAL_TOTAL_SHIFT) & @@ -130,7 +130,7 @@ static int programModeRegisters(mode_parameter_t *pModeParam, } else if (pll->clockType == PRIMARY_PLL) { unsigned int reserved; - POKE32(PANEL_PLL_CTRL, formatPllReg(pll)); + POKE32(PANEL_PLL_CTRL, format_pll_reg(pll)); reg = ((pModeParam->horizontal_total - 1) << PANEL_HORIZONTAL_TOTAL_TOTAL_SHIFT) & @@ -207,7 +207,7 @@ int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock) pll.inputFreq = DEFAULT_INPUT_CLOCK; pll.clockType = clock; - uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll); + uiActualPixelClk = calc_pll_value(parm->pixel_clock, &pll); if (sm750_get_chip_type() == SM750LE) { /* set graphic mode via IO method */ outb_p(0x88, 0x3d4); diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 710106e35bcf..c9ea464e2a78 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -29,7 +29,7 @@ static unsigned int getPowerMode(void) * SM50x can operate in one of three modes: 0, 1 or Sleep. * On hardware reset, power mode 0 is default. */ -void setPowerMode(unsigned int powerMode) +void set_power_mode(unsigned int powerMode) { unsigned int control_value = 0; @@ -72,7 +72,7 @@ void setPowerMode(unsigned int powerMode) POKE32(POWER_MODE_CTRL, control_value); } -void setCurrentGate(unsigned int gate) +void set_current_gate(unsigned int gate) { unsigned int gate_reg; unsigned int mode; @@ -111,7 +111,7 @@ void enable2DEngine(unsigned int enable) else gate &= ~(CURRENT_GATE_DE | CURRENT_GATE_CSC); - setCurrentGate(gate); + set_current_gate(gate); } void enableDMA(unsigned int enable) @@ -125,7 +125,7 @@ void enableDMA(unsigned int enable) else gate &= ~CURRENT_GATE_DMA; - setCurrentGate(gate); + set_current_gate(gate); } /* @@ -142,7 +142,7 @@ void enableGPIO(unsigned int enable) else gate &= ~CURRENT_GATE_GPIO; - setCurrentGate(gate); + set_current_gate(gate); } /* @@ -159,7 +159,7 @@ void enableI2C(unsigned int enable) else gate &= ~CURRENT_GATE_I2C; - setCurrentGate(gate); + set_current_gate(gate); } diff --git a/drivers/staging/sm750fb/ddk750_power.h b/drivers/staging/sm750fb/ddk750_power.h index 5963691f9a68..ba0b3f5bfd9b 100644 --- a/drivers/staging/sm750fb/ddk750_power.h +++ b/drivers/staging/sm750fb/ddk750_power.h @@ -19,12 +19,12 @@ void ddk750_setDPMS(DPMS_t); /* * This function sets the current power mode */ -void setPowerMode(unsigned int powerMode); +void set_power_mode(unsigned int powerMode); /* * This function sets current gate */ -void setCurrentGate(unsigned int gate); +void set_current_gate(unsigned int gate); /* * This function enable/disable the 2D engine. diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 61d2fdc41b52..d5508ba0e5ff 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -68,9 +68,9 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) /* don't use pdev_resource[x].end - resource[x].start to * calculate the resource size, it's only the maximum available * size but not the actual size, using - * @ddk750_getVMSize function can be safe. + * @ddk750_get_vm_size function can be safe. */ - sm750_dev->vidmem_size = ddk750_getVMSize(); + sm750_dev->vidmem_size = ddk750_get_vm_size(); pr_info("video memory phyAddr = %lx, size = %u bytes\n", sm750_dev->vidmem_start, sm750_dev->vidmem_size); @@ -103,7 +103,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) if (parm->master_clk == 0) parm->master_clk = parm->chip_clk / 3; - ddk750_initHw((struct initchip_param *)&sm750_dev->initParm); + ddk750_init_hw((struct initchip_param *)&sm750_dev->initParm); /* for sm718, open pci burst */ if (sm750_dev->devid == 0x718) { POKE32(SYSTEM_CTRL, -- cgit v1.2.3 From aa1eecdc494290c05e74541b64969c64b192cbc9 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Thu, 13 Oct 2016 19:27:17 -0300 Subject: staging: sm750fb: Remove unnecessary comments. Remove function comments that only restate the function name. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_power.h b/drivers/staging/sm750fb/ddk750_power.h index ba0b3f5bfd9b..7b24f1185989 100644 --- a/drivers/staging/sm750fb/ddk750_power.h +++ b/drivers/staging/sm750fb/ddk750_power.h @@ -15,15 +15,7 @@ DPMS_t; } void ddk750_setDPMS(DPMS_t); - -/* - * This function sets the current power mode - */ void set_power_mode(unsigned int powerMode); - -/* - * This function sets current gate - */ void set_current_gate(unsigned int gate); /* -- cgit v1.2.3 From aa059b30935e812efc7b2e4bfec1d8552d133eed Mon Sep 17 00:00:00 2001 From: Sabitha George Date: Thu, 13 Oct 2016 22:32:20 +0530 Subject: staging: ks7010: Replace __attribute__(aligned(x)) with __aligned(x) Fixes checkpatch.pl warning: __aligned(size) is preferred over __attribute__((aligned(size)) in ks7010_sdio.h Signed-off-by: Sabitha George Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks7010_sdio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks7010_sdio.h b/drivers/staging/ks7010/ks7010_sdio.h index c72064b48bd8..c89e5704c03d 100644 --- a/drivers/staging/ks7010/ks7010_sdio.h +++ b/drivers/staging/ks7010/ks7010_sdio.h @@ -100,7 +100,7 @@ struct hw_info_t { struct ks_sdio_packet { struct ks_sdio_packet *next; u16 nb; - u8 buffer[0] __attribute__ ((aligned(4))); + u8 buffer[0] __aligned(4); }; struct ks_sdio_card { -- cgit v1.2.3 From acefb6450d74417ed7ba4381fa2ea073a30f9244 Mon Sep 17 00:00:00 2001 From: Sabitha George Date: Thu, 13 Oct 2016 22:36:23 +0530 Subject: staging: ks7010: Fixes warning :do not add new typedefs Fixes checkpatch.pl warning: do not add new typedefs in ks_wlan_net.c Signed-off-by: Sabitha George Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan_net.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 84edd3b929b0..7b864c02348b 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -50,10 +50,10 @@ static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, /* A few details needed for WEP (Wireless Equivalent Privacy) */ #define MAX_KEY_SIZE 13 /* 128 (?) bits */ #define MIN_KEY_SIZE 5 /* 40 bits RC4 - WEP */ -typedef struct wep_key_t { +struct wep_key { u16 len; u8 key[16]; /* 40-bit and 104-bit keys */ -} wep_key_t; +}; /* Backward compatibility */ #ifndef IW_ENCODE_NOKEY @@ -899,7 +899,7 @@ static int ks_wlan_set_encode(struct net_device *dev, struct ks_wlan_private *priv = (struct ks_wlan_private *)netdev_priv(dev); - wep_key_t key; + struct wep_key key; int index = (dwrq->flags & IW_ENCODE_INDEX); int current_index = priv->reg.wep_index; int i; -- cgit v1.2.3 From 08f2a14c97133d7b2b3c3c27d1a528a7adac69f1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 13 Oct 2016 11:52:02 +0300 Subject: Staging: lustre: indent an if statement This if statement wasn't intended. Signed-off-by: Dan Carpenter Acked-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/cl_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index cda01b83f281..b4600c449c2d 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -335,7 +335,7 @@ int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, if (obj->co_ops->coo_getstripe) { result = obj->co_ops->coo_getstripe(env, obj, uarg); if (result) - break; + break; } } return result; -- cgit v1.2.3 From 35b1fc2cd7106f51bf318ac4dbc5c72abd5656c1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 1 Oct 2016 21:46:24 +0200 Subject: clk: sunxi: mod0: improve function-level documentation Use the actual function name in the function documentation. Issue detected using Coccinelle (http://coccinelle.lip6.fr/) Signed-off-by: Julia Lawall Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-mod0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index e54266cc1c51..4417ae129ac7 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c @@ -24,7 +24,7 @@ #include "clk-factors.h" /** - * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks + * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks * MOD0 rate is calculated as follows * rate = (parent_rate >> p) / (m + 1); */ -- cgit v1.2.3 From ce0ba283f64e632a088b40a09d74522555275287 Mon Sep 17 00:00:00 2001 From: Lyude Date: Thu, 15 Sep 2016 10:46:35 -0400 Subject: drm/i915/skl: Move per-pipe ddb allocations into crtc states MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First part of cleaning up all of the skl watermark code. This moves the structures for storing the ddb allocations of each pipe into intel_crtc_state, along with moving the structures for storing the current ddb allocations active on hardware into intel_crtc. Changes since v1: - Don't replace alloc->start = alloc->end = 0; Signed-off-by: Lyude Reviewed-by: Maarten Lankhorst Reviewed-by: Paulo Zanoni Cc: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_display.c | 16 ++++++++------- drivers/gpu/drm/i915/intel_drv.h | 8 +++++--- drivers/gpu/drm/i915/intel_pm.c | 40 +++++++++++++++--------------------- 4 files changed, 30 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fe875b27a6bf..ac4287f992f3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1641,7 +1641,6 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1, } struct skl_ddb_allocation { - struct skl_ddb_entry pipe[I915_MAX_PIPES]; struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */ struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES]; }; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 60c699e2c2af..7a68cc327e27 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14246,12 +14246,11 @@ static void skl_update_crtcs(struct drm_atomic_state *state, unsigned int *crtc_vblank_mask) { struct drm_device *dev = state->dev; - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_crtc *crtc; + struct intel_crtc *intel_crtc; struct drm_crtc_state *old_crtc_state; - struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; - struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; + struct intel_crtc_state *cstate; unsigned int updated = 0; bool progress; enum pipe pipe; @@ -14269,12 +14268,14 @@ static void skl_update_crtcs(struct drm_atomic_state *state, for_each_crtc_in_state(state, crtc, old_crtc_state, i) { bool vbl_wait = false; unsigned int cmask = drm_crtc_mask(crtc); - pipe = to_intel_crtc(crtc)->pipe; + + intel_crtc = to_intel_crtc(crtc); + cstate = to_intel_crtc_state(crtc->state); + pipe = intel_crtc->pipe; if (updated & cmask || !crtc->state->active) continue; - if (skl_ddb_allocation_overlaps(state, cur_ddb, new_ddb, - pipe)) + if (skl_ddb_allocation_overlaps(state, intel_crtc)) continue; updated |= cmask; @@ -14285,7 +14286,8 @@ static void skl_update_crtcs(struct drm_atomic_state *state, * then we need to wait for a vblank to pass for the * new ddb allocation to take effect. */ - if (!skl_ddb_allocation_equals(cur_ddb, new_ddb, pipe) && + if (!skl_ddb_entry_equal(&cstate->wm.skl.ddb, + &intel_crtc->hw_ddb) && !crtc->state->active_changed && intel_state->wm_results.dirty_pipes != updated) vbl_wait = true; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5bc115496355..10a0cf2c7e96 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -496,6 +496,7 @@ struct intel_crtc_wm_state { struct { /* gen9+ only needs 1-step wm programming */ struct skl_pipe_wm optimal; + struct skl_ddb_entry ddb; /* cached plane data rate */ unsigned plane_data_rate[I915_MAX_PLANES]; @@ -733,6 +734,9 @@ struct intel_crtc { bool cxsr_allowed; } wm; + /* gen9+: ddb allocation currently being used */ + struct skl_ddb_entry hw_ddb; + int scanline_offset; struct { @@ -1755,9 +1759,7 @@ bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, const struct skl_ddb_allocation *new, enum pipe pipe); bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, - const struct skl_ddb_allocation *old, - const struct skl_ddb_allocation *new, - enum pipe pipe); + struct intel_crtc *intel_crtc); void skl_write_cursor_wm(struct intel_crtc *intel_crtc, const struct skl_wm_values *wm); void skl_write_plane_wm(struct intel_crtc *intel_crtc, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 48b3904c4aeb..66586af84c0a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3062,7 +3062,6 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, struct drm_crtc *for_crtc = cstate->base.crtc; unsigned int pipe_size, ddb_size; int nth_active_pipe; - int pipe = to_intel_crtc(for_crtc)->pipe; if (WARN_ON(!state) || !cstate->base.active) { alloc->start = 0; @@ -3090,7 +3089,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, * we currently hold. */ if (!intel_state->active_pipe_changes) { - *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe]; + *alloc = to_intel_crtc(for_crtc)->hw_ddb; return; } @@ -3358,7 +3357,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, struct drm_plane *plane; struct drm_plane_state *pstate; enum pipe pipe = intel_crtc->pipe; - struct skl_ddb_entry *alloc = &ddb->pipe[pipe]; + struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; uint16_t alloc_size, start, cursor_blocks; uint16_t *minimum = cstate->wm.skl.minimum_blocks; uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; @@ -3374,7 +3373,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, return 0; if (!cstate->base.active) { - ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0; + alloc->start = alloc->end = 0; return 0; } @@ -3901,14 +3900,6 @@ void skl_write_cursor_wm(struct intel_crtc *intel_crtc, &wm->ddb.plane[pipe][PLANE_CURSOR]); } -bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, - const struct skl_ddb_allocation *new, - enum pipe pipe) -{ - return new->pipe[pipe].start == old->pipe[pipe].start && - new->pipe[pipe].end == old->pipe[pipe].end; -} - static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, const struct skl_ddb_entry *b) { @@ -3916,22 +3907,22 @@ static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, } bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, - const struct skl_ddb_allocation *old, - const struct skl_ddb_allocation *new, - enum pipe pipe) + struct intel_crtc *intel_crtc) { - struct drm_device *dev = state->dev; - struct intel_crtc *intel_crtc; - enum pipe otherp; + struct drm_crtc *other_crtc; + struct drm_crtc_state *other_cstate; + struct intel_crtc *other_intel_crtc; + const struct skl_ddb_entry *ddb = + &to_intel_crtc_state(intel_crtc->base.state)->wm.skl.ddb; + int i; - for_each_intel_crtc(dev, intel_crtc) { - otherp = intel_crtc->pipe; + for_each_crtc_in_state(state, other_crtc, other_cstate, i) { + other_intel_crtc = to_intel_crtc(other_crtc); - if (otherp == pipe) + if (other_intel_crtc == intel_crtc) continue; - if (skl_ddb_entries_overlap(&new->pipe[pipe], - &old->pipe[otherp])) + if (skl_ddb_entries_overlap(ddb, &other_intel_crtc->hw_ddb)) return true; } @@ -4096,7 +4087,6 @@ skl_copy_wm_for_pipe(struct skl_wm_values *dst, memcpy(dst->plane_trans[pipe], src->plane_trans[pipe], sizeof(dst->plane_trans[pipe])); - dst->ddb.pipe[pipe] = src->ddb.pipe[pipe]; memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe], sizeof(dst->ddb.y_plane[pipe])); memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], @@ -4204,6 +4194,8 @@ static void skl_update_wm(struct drm_crtc *crtc) skl_copy_wm_for_pipe(hw_vals, results, pipe); + intel_crtc->hw_ddb = cstate->wm.skl.ddb; + mutex_unlock(&dev_priv->wm.wm_mutex); } -- cgit v1.2.3 From b707aa50414633b193da99af5d86acd95c2d9dc4 Mon Sep 17 00:00:00 2001 From: Lyude Date: Thu, 15 Sep 2016 10:56:06 -0400 Subject: drm/i915/skl: Remove linetime from skl_wm_values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Next part of cleaning up the watermark code for skl. This is easy, since it seems that we never actually needed to keep track of the linetime in the skl_wm_values struct anyway. Signed-off-by: Lyude Reviewed-by: Paulo Zanoni Reviewed-by: Maarten Lankhorst Cc: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_display.c | 8 +++++--- drivers/gpu/drm/i915/intel_pm.c | 7 +------ 3 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ac4287f992f3..e56d4a4b63bd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1648,7 +1648,6 @@ struct skl_ddb_allocation { struct skl_wm_values { unsigned dirty_pipes; struct skl_ddb_allocation ddb; - uint32_t wm_linetime[I915_MAX_PIPES]; uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; uint32_t plane_trans[I915_MAX_PIPES][I915_MAX_PLANES]; }; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7a68cc327e27..bdc898ef5b64 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14844,6 +14844,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *intel_cstate = + to_intel_crtc_state(crtc->state); struct intel_crtc_state *old_intel_state = to_intel_crtc_state(old_crtc_state); bool modeset = needs_modeset(crtc->state); @@ -14860,13 +14862,13 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, intel_color_load_luts(crtc->state); } - if (to_intel_crtc_state(crtc->state)->update_pipe) + if (intel_cstate->update_pipe) { intel_update_pipe_config(intel_crtc, old_intel_state); - else if (INTEL_GEN(dev_priv) >= 9) { + } else if (INTEL_GEN(dev_priv) >= 9) { skl_detach_scalers(intel_crtc); I915_WRITE(PIPE_WM_LINETIME(pipe), - dev_priv->wm.skl_hw.wm_linetime[pipe]); + intel_cstate->wm.skl.optimal.linetime); } } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 66586af84c0a..a7d5721ee53b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3845,8 +3845,6 @@ static void skl_compute_wm_results(struct drm_device *dev, temp |= PLANE_WM_EN; r->plane_trans[pipe][PLANE_CURSOR] = temp; - - r->wm_linetime[pipe] = p_wm->linetime; } static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, @@ -4081,7 +4079,6 @@ skl_copy_wm_for_pipe(struct skl_wm_values *dst, struct skl_wm_values *src, enum pipe pipe) { - dst->wm_linetime[pipe] = src->wm_linetime[pipe]; memcpy(dst->plane[pipe], src->plane[pipe], sizeof(dst->plane[pipe])); memcpy(dst->plane_trans[pipe], src->plane_trans[pipe], @@ -4332,8 +4329,6 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) max_level = ilk_wm_max_level(dev_priv); - hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); - for (level = 0; level <= max_level; level++) { for (i = 0; i < intel_num_planes(intel_crtc); i++) hw->plane[pipe][i][level] = @@ -4350,7 +4345,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) hw->dirty_pipes |= drm_crtc_mask(crtc); - active->linetime = hw->wm_linetime[pipe]; + active->linetime = I915_READ(PIPE_WM_LINETIME(pipe)); for (level = 0; level <= max_level; level++) { for (i = 0; i < intel_num_planes(intel_crtc); i++) { -- cgit v1.2.3 From a62163e97bafbc072093ee5645873227f33a43ee Mon Sep 17 00:00:00 2001 From: Lyude Date: Tue, 4 Oct 2016 14:28:20 -0400 Subject: drm/i915/gen9: Make skl_wm_level per-plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having skl_wm_level contain all of the watermarks for each plane is annoying since it prevents us from having any sort of object to represent a single watermark level, something we take advantage of in the next commit to cut down on all of the copy paste code in here. Changes since v1: - Style nitpicks - Fix accidental usage of i vs. PLANE_CURSOR - Split out skl_pipe_wm_active_state simplification into separate patch Signed-off-by: Lyude Reviewed-by: Paulo Zanoni Reviewed-by: Maarten Lankhorst Cc: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 6 +- drivers/gpu/drm/i915/intel_drv.h | 6 +- drivers/gpu/drm/i915/intel_pm.c | 206 +++++++++++++++++++-------------------- 3 files changed, 110 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e56d4a4b63bd..4d1133ffe093 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1653,9 +1653,9 @@ struct skl_wm_values { }; struct skl_wm_level { - bool plane_en[I915_MAX_PLANES]; - uint16_t plane_res_b[I915_MAX_PLANES]; - uint8_t plane_res_l[I915_MAX_PLANES]; + bool plane_en; + uint16_t plane_res_b; + uint8_t plane_res_l; }; /* diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 10a0cf2c7e96..84301d3b8b7f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -468,9 +468,13 @@ struct intel_pipe_wm { bool sprites_scaled; }; -struct skl_pipe_wm { +struct skl_plane_wm { struct skl_wm_level wm[8]; struct skl_wm_level trans_wm; +}; + +struct skl_pipe_wm { + struct skl_plane_wm planes[I915_MAX_PLANES]; uint32_t linetime; }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a7d5721ee53b..a99bbd3dc2ca 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3674,67 +3674,52 @@ static int skl_compute_wm_level(const struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb, struct intel_crtc_state *cstate, + struct intel_plane *intel_plane, int level, struct skl_wm_level *result) { struct drm_atomic_state *state = cstate->base.state; struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); - struct drm_plane *plane; - struct intel_plane *intel_plane; - struct intel_plane_state *intel_pstate; + struct drm_plane *plane = &intel_plane->base; + struct intel_plane_state *intel_pstate = NULL; uint16_t ddb_blocks; enum pipe pipe = intel_crtc->pipe; int ret; + int i = skl_wm_plane_id(intel_plane); + + if (state) + intel_pstate = + intel_atomic_get_existing_plane_state(state, + intel_plane); /* - * We'll only calculate watermarks for planes that are actually - * enabled, so make sure all other planes are set as disabled. + * Note: If we start supporting multiple pending atomic commits against + * the same planes/CRTC's in the future, plane->state will no longer be + * the correct pre-state to use for the calculations here and we'll + * need to change where we get the 'unchanged' plane data from. + * + * For now this is fine because we only allow one queued commit against + * a CRTC. Even if the plane isn't modified by this transaction and we + * don't have a plane lock, we still have the CRTC's lock, so we know + * that no other transactions are racing with us to update it. */ - memset(result, 0, sizeof(*result)); + if (!intel_pstate) + intel_pstate = to_intel_plane_state(plane->state); - for_each_intel_plane_mask(&dev_priv->drm, - intel_plane, - cstate->base.plane_mask) { - int i = skl_wm_plane_id(intel_plane); - - plane = &intel_plane->base; - intel_pstate = NULL; - if (state) - intel_pstate = - intel_atomic_get_existing_plane_state(state, - intel_plane); + WARN_ON(!intel_pstate->base.fb); - /* - * Note: If we start supporting multiple pending atomic commits - * against the same planes/CRTC's in the future, plane->state - * will no longer be the correct pre-state to use for the - * calculations here and we'll need to change where we get the - * 'unchanged' plane data from. - * - * For now this is fine because we only allow one queued commit - * against a CRTC. Even if the plane isn't modified by this - * transaction and we don't have a plane lock, we still have - * the CRTC's lock, so we know that no other transactions are - * racing with us to update it. - */ - if (!intel_pstate) - intel_pstate = to_intel_plane_state(plane->state); + ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); - WARN_ON(!intel_pstate->base.fb); - - ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); - - ret = skl_compute_plane_wm(dev_priv, - cstate, - intel_pstate, - ddb_blocks, - level, - &result->plane_res_b[i], - &result->plane_res_l[i], - &result->plane_en[i]); - if (ret) - return ret; - } + ret = skl_compute_plane_wm(dev_priv, + cstate, + intel_pstate, + ddb_blocks, + level, + &result->plane_res_b, + &result->plane_res_l, + &result->plane_en); + if (ret) + return ret; return 0; } @@ -3755,19 +3740,11 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) static void skl_compute_transition_wm(struct intel_crtc_state *cstate, struct skl_wm_level *trans_wm /* out */) { - struct drm_crtc *crtc = cstate->base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_plane *intel_plane; - if (!cstate->base.active) return; /* Until we know more, just disable transition WMs */ - for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) { - int i = skl_wm_plane_id(intel_plane); - - trans_wm->plane_en[i] = false; - } + trans_wm->plane_en = false; } static int skl_build_pipe_wm(struct intel_crtc_state *cstate, @@ -3776,19 +3753,33 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, { struct drm_device *dev = cstate->base.crtc->dev; const struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_plane *intel_plane; + struct skl_plane_wm *wm; int level, max_level = ilk_wm_max_level(dev_priv); int ret; - for (level = 0; level <= max_level; level++) { - ret = skl_compute_wm_level(dev_priv, ddb, cstate, - level, &pipe_wm->wm[level]); - if (ret) - return ret; + /* + * We'll only calculate watermarks for planes that are actually + * enabled, so make sure all other planes are set as disabled. + */ + memset(pipe_wm->planes, 0, sizeof(pipe_wm->planes)); + + for_each_intel_plane_mask(&dev_priv->drm, + intel_plane, + cstate->base.plane_mask) { + wm = &pipe_wm->planes[skl_wm_plane_id(intel_plane)]; + + for (level = 0; level <= max_level; level++) { + ret = skl_compute_wm_level(dev_priv, ddb, cstate, + intel_plane, level, + &wm->wm[level]); + if (ret) + return ret; + } + skl_compute_transition_wm(cstate, &wm->trans_wm); } pipe_wm->linetime = skl_compute_linetime_wm(cstate); - skl_compute_transition_wm(cstate, &pipe_wm->trans_wm); - return 0; } @@ -3798,50 +3789,55 @@ static void skl_compute_wm_results(struct drm_device *dev, struct intel_crtc *intel_crtc) { int level, max_level = ilk_wm_max_level(to_i915(dev)); + struct skl_plane_wm *plane_wm; enum pipe pipe = intel_crtc->pipe; uint32_t temp; int i; - for (level = 0; level <= max_level; level++) { - for (i = 0; i < intel_num_planes(intel_crtc); i++) { + for (i = 0; i < intel_num_planes(intel_crtc); i++) { + plane_wm = &p_wm->planes[i]; + + for (level = 0; level <= max_level; level++) { temp = 0; - temp |= p_wm->wm[level].plane_res_l[i] << + temp |= plane_wm->wm[level].plane_res_l << PLANE_WM_LINES_SHIFT; - temp |= p_wm->wm[level].plane_res_b[i]; - if (p_wm->wm[level].plane_en[i]) + temp |= plane_wm->wm[level].plane_res_b; + if (plane_wm->wm[level].plane_en) temp |= PLANE_WM_EN; r->plane[pipe][i][level] = temp; } + } + for (level = 0; level <= max_level; level++) { + plane_wm = &p_wm->planes[PLANE_CURSOR]; temp = 0; - - temp |= p_wm->wm[level].plane_res_l[PLANE_CURSOR] << PLANE_WM_LINES_SHIFT; - temp |= p_wm->wm[level].plane_res_b[PLANE_CURSOR]; - - if (p_wm->wm[level].plane_en[PLANE_CURSOR]) + temp |= plane_wm->wm[level].plane_res_l << PLANE_WM_LINES_SHIFT; + temp |= plane_wm->wm[level].plane_res_b; + if (plane_wm->wm[level].plane_en) temp |= PLANE_WM_EN; r->plane[pipe][PLANE_CURSOR][level] = temp; - } /* transition WMs */ for (i = 0; i < intel_num_planes(intel_crtc); i++) { + plane_wm = &p_wm->planes[i]; temp = 0; - temp |= p_wm->trans_wm.plane_res_l[i] << PLANE_WM_LINES_SHIFT; - temp |= p_wm->trans_wm.plane_res_b[i]; - if (p_wm->trans_wm.plane_en[i]) + temp |= plane_wm->trans_wm.plane_res_l << PLANE_WM_LINES_SHIFT; + temp |= plane_wm->trans_wm.plane_res_b; + if (plane_wm->trans_wm.plane_en) temp |= PLANE_WM_EN; r->plane_trans[pipe][i] = temp; } + plane_wm = &p_wm->planes[PLANE_CURSOR]; temp = 0; - temp |= p_wm->trans_wm.plane_res_l[PLANE_CURSOR] << PLANE_WM_LINES_SHIFT; - temp |= p_wm->trans_wm.plane_res_b[PLANE_CURSOR]; - if (p_wm->trans_wm.plane_en[PLANE_CURSOR]) + temp |= plane_wm->trans_wm.plane_res_l << PLANE_WM_LINES_SHIFT; + temp |= plane_wm->trans_wm.plane_res_b; + if (plane_wm->trans_wm.plane_en) temp |= PLANE_WM_EN; r->plane_trans[pipe][PLANE_CURSOR] = temp; @@ -4282,35 +4278,37 @@ static void skl_pipe_wm_active_state(uint32_t val, if (!is_transwm) { if (!is_cursor) { - active->wm[level].plane_en[i] = is_enabled; - active->wm[level].plane_res_b[i] = - val & PLANE_WM_BLOCKS_MASK; - active->wm[level].plane_res_l[i] = - (val >> PLANE_WM_LINES_SHIFT) & - PLANE_WM_LINES_MASK; + active->planes[i].wm[level].plane_en = is_enabled; + active->planes[i].wm[level].plane_res_b = + val & PLANE_WM_BLOCKS_MASK; + active->planes[i].wm[level].plane_res_l = + (val >> PLANE_WM_LINES_SHIFT) & + PLANE_WM_LINES_MASK; } else { - active->wm[level].plane_en[PLANE_CURSOR] = is_enabled; - active->wm[level].plane_res_b[PLANE_CURSOR] = - val & PLANE_WM_BLOCKS_MASK; - active->wm[level].plane_res_l[PLANE_CURSOR] = - (val >> PLANE_WM_LINES_SHIFT) & - PLANE_WM_LINES_MASK; + active->planes[PLANE_CURSOR].wm[level].plane_en = + is_enabled; + active->planes[PLANE_CURSOR].wm[level].plane_res_b = + val & PLANE_WM_BLOCKS_MASK; + active->planes[PLANE_CURSOR].wm[level].plane_res_l = + (val >> PLANE_WM_LINES_SHIFT) & + PLANE_WM_LINES_MASK; } } else { if (!is_cursor) { - active->trans_wm.plane_en[i] = is_enabled; - active->trans_wm.plane_res_b[i] = - val & PLANE_WM_BLOCKS_MASK; - active->trans_wm.plane_res_l[i] = - (val >> PLANE_WM_LINES_SHIFT) & - PLANE_WM_LINES_MASK; + active->planes[i].trans_wm.plane_en = is_enabled; + active->planes[i].trans_wm.plane_res_b = + val & PLANE_WM_BLOCKS_MASK; + active->planes[i].trans_wm.plane_res_l = + (val >> PLANE_WM_LINES_SHIFT) & + PLANE_WM_LINES_MASK; } else { - active->trans_wm.plane_en[PLANE_CURSOR] = is_enabled; - active->trans_wm.plane_res_b[PLANE_CURSOR] = - val & PLANE_WM_BLOCKS_MASK; - active->trans_wm.plane_res_l[PLANE_CURSOR] = - (val >> PLANE_WM_LINES_SHIFT) & - PLANE_WM_LINES_MASK; + active->planes[PLANE_CURSOR].trans_wm.plane_en = + is_enabled; + active->planes[PLANE_CURSOR].trans_wm.plane_res_b = + val & PLANE_WM_BLOCKS_MASK; + active->planes[PLANE_CURSOR].trans_wm.plane_res_l = + (val >> PLANE_WM_LINES_SHIFT) & + PLANE_WM_LINES_MASK; } } } -- cgit v1.2.3 From 1bab7502dde265466fb03124afaada5847065403 Mon Sep 17 00:00:00 2001 From: Lyude Date: Fri, 7 Oct 2016 15:03:07 -0400 Subject: drm/i915/gen9: Cleanup skl_pipe_wm_active_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function is a wreck, let's help it get its life back together and cleanup all of the copy pasta here. Signed-off-by: Lyude Reviewed-by: Maarten Lankhorst Reviewed-by: Paulo Zanoni Cc: Ville Syrjälä --- drivers/gpu/drm/i915/intel_pm.c | 52 +++++++++++------------------------------ 1 file changed, 14 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a99bbd3dc2ca..9ae23384976c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4270,46 +4270,22 @@ static void ilk_optimize_watermarks(struct intel_crtc_state *cstate) static void skl_pipe_wm_active_state(uint32_t val, struct skl_pipe_wm *active, bool is_transwm, - bool is_cursor, int i, int level) { + struct skl_plane_wm *plane_wm = &active->planes[i]; bool is_enabled = (val & PLANE_WM_EN) != 0; if (!is_transwm) { - if (!is_cursor) { - active->planes[i].wm[level].plane_en = is_enabled; - active->planes[i].wm[level].plane_res_b = - val & PLANE_WM_BLOCKS_MASK; - active->planes[i].wm[level].plane_res_l = - (val >> PLANE_WM_LINES_SHIFT) & - PLANE_WM_LINES_MASK; - } else { - active->planes[PLANE_CURSOR].wm[level].plane_en = - is_enabled; - active->planes[PLANE_CURSOR].wm[level].plane_res_b = - val & PLANE_WM_BLOCKS_MASK; - active->planes[PLANE_CURSOR].wm[level].plane_res_l = - (val >> PLANE_WM_LINES_SHIFT) & - PLANE_WM_LINES_MASK; - } + plane_wm->wm[level].plane_en = is_enabled; + plane_wm->wm[level].plane_res_b = val & PLANE_WM_BLOCKS_MASK; + plane_wm->wm[level].plane_res_l = + (val >> PLANE_WM_LINES_SHIFT) & PLANE_WM_LINES_MASK; } else { - if (!is_cursor) { - active->planes[i].trans_wm.plane_en = is_enabled; - active->planes[i].trans_wm.plane_res_b = - val & PLANE_WM_BLOCKS_MASK; - active->planes[i].trans_wm.plane_res_l = - (val >> PLANE_WM_LINES_SHIFT) & - PLANE_WM_LINES_MASK; - } else { - active->planes[PLANE_CURSOR].trans_wm.plane_en = - is_enabled; - active->planes[PLANE_CURSOR].trans_wm.plane_res_b = - val & PLANE_WM_BLOCKS_MASK; - active->planes[PLANE_CURSOR].trans_wm.plane_res_l = - (val >> PLANE_WM_LINES_SHIFT) & - PLANE_WM_LINES_MASK; - } + plane_wm->trans_wm.plane_en = is_enabled; + plane_wm->trans_wm.plane_res_b = val & PLANE_WM_BLOCKS_MASK; + plane_wm->trans_wm.plane_res_l = + (val >> PLANE_WM_LINES_SHIFT) & PLANE_WM_LINES_MASK; } } @@ -4348,20 +4324,20 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) for (level = 0; level <= max_level; level++) { for (i = 0; i < intel_num_planes(intel_crtc); i++) { temp = hw->plane[pipe][i][level]; - skl_pipe_wm_active_state(temp, active, false, - false, i, level); + skl_pipe_wm_active_state(temp, active, false, i, level); } temp = hw->plane[pipe][PLANE_CURSOR][level]; - skl_pipe_wm_active_state(temp, active, false, true, i, level); + skl_pipe_wm_active_state(temp, active, false, PLANE_CURSOR, + level); } for (i = 0; i < intel_num_planes(intel_crtc); i++) { temp = hw->plane_trans[pipe][i]; - skl_pipe_wm_active_state(temp, active, true, false, i, 0); + skl_pipe_wm_active_state(temp, active, true, i, 0); } temp = hw->plane_trans[pipe][PLANE_CURSOR]; - skl_pipe_wm_active_state(temp, active, true, true, i, 0); + skl_pipe_wm_active_state(temp, active, true, PLANE_CURSOR, 0); intel_crtc->wm.active.skl = *active; } -- cgit v1.2.3 From d807ed1c55fb1b2dcfb2bc49385e227f6bee7669 Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Thu, 13 Oct 2016 10:47:08 +0100 Subject: drm: atomic: Clarify documentation around drm_atomic_crtc_needs_modeset Add some additional comments to more explicitly describe the meaning and usage of the three CRTC modeset detection booleans: mode_changed, connectors_changed and active_changed. Suggested-by: Daniel Vetter Signed-off-by: Brian Starkey Acked-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476352028-16701-1-git-send-email-brian.starkey@arm.com --- drivers/gpu/drm/drm_atomic_helper.c | 9 +++++---- include/drm/drm_atomic.h | 11 ++++++++++- include/drm/drm_crtc.h | 5 +++++ 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index c3f83476f996..36f83fe5ec46 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -458,10 +458,11 @@ mode_fixup(struct drm_atomic_state *state) * removed from the crtc. * crtc_state->active_changed is set when crtc_state->active changes, * which is used for dpms. + * See also: drm_atomic_crtc_needs_modeset() * * IMPORTANT: * - * Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a + * Drivers which set ->mode_changed (e.g. in their ->atomic_check hooks if a * plane update can't be done without a full modeset) _must_ call this function * afterwards after that change. It is permitted to call this function multiple * times for the same update, e.g. when the ->atomic_check functions depend upon @@ -510,9 +511,9 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, for_each_connector_in_state(state, connector, connector_state, i) { /* - * This only sets crtc->mode_changed for routing changes, - * drivers must set crtc->mode_changed themselves when connector - * properties need to be updated. + * This only sets crtc->connectors_changed for routing changes, + * drivers must set crtc->connectors_changed themselves when + * connector properties need to be updated. */ ret = update_connector_routing(state, connector, connector_state); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 9701f2dfb784..c52f99415c55 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -365,8 +365,17 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); * * To give drivers flexibility struct &drm_crtc_state has 3 booleans to track * whether the state CRTC changed enough to need a full modeset cycle: - * connectors_changed, mode_changed and active_change. This helper simply + * connectors_changed, mode_changed and active_changed. This helper simply * combines these three to compute the overall need for a modeset for @state. + * + * The atomic helper code sets these booleans, but drivers can and should + * change them appropriately to accurately represent whether a modeset is + * really needed. In general, drivers should avoid full modesets whenever + * possible. + * + * For example if the CRTC mode has changed, and the hardware is able to enact + * the requested mode change without going through a full modeset, the driver + * should clear mode_changed during its ->atomic_check. */ static inline bool drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 0aa292526567..92246619947c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -116,6 +116,11 @@ struct drm_plane_helper_funcs; * never return in a failure from the ->atomic_check callback. Userspace assumes * that a DPMS On will always succeed. In other words: @enable controls resource * assignment, @active controls the actual hardware state. + * + * The three booleans active_changed, connectors_changed and mode_changed are + * intended to indicate whether a full modeset is needed, rather than strictly + * describing what has changed in a commit. + * See also: drm_atomic_crtc_needs_modeset() */ struct drm_crtc_state { struct drm_crtc *crtc; -- cgit v1.2.3 From 0853695c3ba46f97dfc0b5885f7b7e640ca212dd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Oct 2016 13:18:18 +0100 Subject: drm: Add reference counting to drm_atomic_state drm_atomic_state has a complicated single owner model that tracks the single reference from allocation through to destruction on another thread - or perhaps on a local error path. We can simplify this tracking by using reference counting (at a cost of a few more atomics). This is even more beneficial when the lifetime of the state becomes more convoluted than being passed to a single worker thread for the commit. v2: Double check !intel atomic_commit functions for missing gets v3: Update kerneldocs Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Reviewed-by: Eric Engestrom Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161014121833.439-27-chris@chris-wilson.co.uk --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 3 +- drivers/gpu/drm/drm_atomic.c | 25 +++---- drivers/gpu/drm/drm_atomic_helper.c | 98 +++++++--------------------- drivers/gpu/drm/drm_fb_helper.c | 9 +-- drivers/gpu/drm/exynos/exynos_drm_drv.c | 3 +- drivers/gpu/drm/i915/i915_debugfs.c | 5 +- drivers/gpu/drm/i915/intel_display.c | 31 +++++---- drivers/gpu/drm/i915/intel_sprite.c | 4 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 3 +- drivers/gpu/drm/msm/msm_atomic.c | 3 +- drivers/gpu/drm/omapdrm/omap_drv.c | 3 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 3 +- drivers/gpu/drm/sti/sti_drv.c | 3 +- drivers/gpu/drm/tegra/drm.c | 3 +- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 2 - drivers/gpu/drm/vc4/vc4_kms.c | 3 +- include/drm/drm_atomic.h | 31 ++++++++- include/drm/drm_plane.h | 1 - 18 files changed, 102 insertions(+), 131 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 5f484310bee9..9f6222895212 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -464,7 +464,7 @@ atmel_hlcdc_dc_atomic_complete(struct atmel_hlcdc_dc_commit *commit) drm_atomic_helper_cleanup_planes(dev, old_state); - drm_atomic_state_free(old_state); + drm_atomic_state_put(old_state); /* Complete the commit, wake up any waiter. */ spin_lock(&dc->commit.wait.lock); @@ -521,6 +521,7 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev, /* Swap the state, this is the point of no return. */ drm_atomic_helper_swap_state(state, true); + drm_atomic_state_get(state); if (async) queue_work(dc->wq, &commit->work); else diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 23739609427d..5dd70540219c 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -74,6 +74,8 @@ EXPORT_SYMBOL(drm_atomic_state_default_release); int drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) { + kref_init(&state->ref); + /* TODO legacy paths should maybe do a better job about * setting this appropriately? */ @@ -215,22 +217,16 @@ void drm_atomic_state_clear(struct drm_atomic_state *state) EXPORT_SYMBOL(drm_atomic_state_clear); /** - * drm_atomic_state_free - free all memory for an atomic state - * @state: atomic state to deallocate + * __drm_atomic_state_free - free all memory for an atomic state + * @ref: This atomic state to deallocate * * This frees all memory associated with an atomic state, including all the * per-object state for planes, crtcs and connectors. */ -void drm_atomic_state_free(struct drm_atomic_state *state) +void __drm_atomic_state_free(struct kref *ref) { - struct drm_device *dev; - struct drm_mode_config *config; - - if (!state) - return; - - dev = state->dev; - config = &dev->mode_config; + struct drm_atomic_state *state = container_of(ref, typeof(*state), ref); + struct drm_mode_config *config = &state->dev->mode_config; drm_atomic_state_clear(state); @@ -243,7 +239,7 @@ void drm_atomic_state_free(struct drm_atomic_state *state) kfree(state); } } -EXPORT_SYMBOL(drm_atomic_state_free); +EXPORT_SYMBOL(__drm_atomic_state_free); /** * drm_atomic_get_crtc_state - get crtc state @@ -1742,7 +1738,7 @@ retry: if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { /* * Unlike commit, check_only does not clean up state. - * Below we call drm_atomic_state_free for it. + * Below we call drm_atomic_state_put for it. */ ret = drm_atomic_check_only(state); } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { @@ -1775,8 +1771,7 @@ out: goto retry; } - if (ret || arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) - drm_atomic_state_free(state); + drm_atomic_state_put(state); drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 36f83fe5ec46..07b432f43b98 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1208,7 +1208,7 @@ static void commit_tail(struct drm_atomic_state *state) drm_atomic_helper_commit_cleanup_done(state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); } static void commit_work(struct work_struct *work) @@ -1290,6 +1290,7 @@ int drm_atomic_helper_commit(struct drm_device *dev, * make sure work items don't artifically stall on each another. */ + drm_atomic_state_get(state); if (nonblock) queue_work(system_unbound_wq, &state->commit_work); else @@ -1591,7 +1592,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); * * This signals completion of the atomic update @state, including any cleanup * work. If used, it must be called right before calling - * drm_atomic_state_free(). + * drm_atomic_state_put(). * * This is part of the atomic helper support for nonblocking commits, see * drm_atomic_helper_setup_commit() for an overview. @@ -2114,18 +2115,13 @@ retry: state->legacy_cursor_update = true; ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - return 0; fail: if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); @@ -2187,18 +2183,13 @@ retry: goto fail; ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - return 0; fail: if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); @@ -2327,18 +2318,13 @@ retry: goto fail; ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - return 0; fail: if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); @@ -2480,11 +2466,8 @@ int drm_atomic_helper_disable_all(struct drm_device *dev, } err = drm_atomic_commit(state); - free: - if (err < 0) - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return err; } EXPORT_SYMBOL(drm_atomic_helper_disable_all); @@ -2535,7 +2518,7 @@ retry: err = drm_atomic_helper_disable_all(dev, &ctx); if (err < 0) { - drm_atomic_state_free(state); + drm_atomic_state_put(state); state = ERR_PTR(err); goto unlock; } @@ -2624,18 +2607,13 @@ retry: goto fail; ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - return 0; fail: if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); @@ -2684,18 +2662,13 @@ retry: goto fail; ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - return 0; fail: if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); @@ -2744,18 +2717,13 @@ retry: goto fail; ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - return 0; fail: if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); @@ -2828,18 +2796,13 @@ retry: } ret = drm_atomic_nonblocking_commit(state); - if (ret != 0) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - return 0; fail: if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); @@ -2915,19 +2878,14 @@ retry: crtc_state->active = active; ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - return 0; fail: if (ret == -EDEADLK) goto backoff; connector->dpms = old_mode; - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); @@ -3334,7 +3292,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev, free: if (err < 0) { - drm_atomic_state_free(state); + drm_atomic_state_put(state); state = ERR_PTR(err); } @@ -3449,22 +3407,14 @@ retry: goto fail; ret = drm_atomic_commit(state); - if (ret) - goto fail; - - /* Driver takes ownership of state on successful commit. */ - - drm_property_unreference_blob(blob); - - return 0; fail: if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); + drm_atomic_state_put(state); drm_property_unreference_blob(blob); - return ret; + backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 03414bde1f15..22d4f0e22101 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -367,9 +367,7 @@ fail: if (ret == -EDEADLK) goto backoff; - if (ret != 0) - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; backoff: @@ -1361,16 +1359,13 @@ retry: info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; - fail: drm_atomic_clean_old_fb(dev, plane_mask, ret); if (ret == -EDEADLK) goto backoff; - if (ret != 0) - drm_atomic_state_free(state); - + drm_atomic_state_put(state); return ret; backoff: diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index def78c8c1780..4a21a745c373 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -69,7 +69,7 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit) drm_atomic_helper_cleanup_planes(dev, state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); spin_lock(&priv->lock); priv->pending &= ~commit->crtcs; @@ -254,6 +254,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, drm_atomic_helper_swap_state(state, true); + drm_atomic_state_get(state); if (nonblock) schedule_work(&commit->work); else diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 27b0e34dadec..6c7bb87f764e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3941,10 +3941,9 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv, ret = drm_atomic_commit(state); out: - drm_modeset_unlock_all(dev); WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret); - if (ret) - drm_atomic_state_free(state); + drm_modeset_unlock_all(dev); + drm_atomic_state_put(state); } static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ad8d712ae84c..a12e093c54cf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3582,7 +3582,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv) return; err: - drm_atomic_state_free(state); + drm_atomic_state_put(state); } void intel_finish_reset(struct drm_i915_private *dev_priv) @@ -3643,6 +3643,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) intel_hpd_init(dev_priv); } + if (state) + drm_atomic_state_put(state); drm_modeset_drop_locks(ctx); drm_modeset_acquire_fini(ctx); mutex_unlock(&dev->mode_config.mutex); @@ -6882,7 +6884,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) dev_priv->display.crtc_disable(crtc_state, state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", crtc->base.id, crtc->name); @@ -11249,8 +11251,8 @@ found: return true; fail: - drm_atomic_state_free(state); - drm_atomic_state_free(restore_state); + drm_atomic_state_put(state); + drm_atomic_state_put(restore_state); restore_state = state = NULL; if (ret == -EDEADLK) { @@ -11279,10 +11281,9 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, return; ret = drm_atomic_commit(state); - if (ret) { + if (ret) DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret); - drm_atomic_state_free(state); - } + drm_atomic_state_put(state); } static int i9xx_pll_refclk(struct drm_device *dev, @@ -12350,8 +12351,7 @@ retry: goto retry; } - if (ret) - drm_atomic_state_free(state); + drm_atomic_state_put(state); if (ret == 0 && event) { spin_lock_irq(&dev->event_lock); @@ -14437,7 +14437,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_commit_cleanup_done(state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); /* As one of the primary mmio accessors, KMS has a high likelihood * of triggering bugs in unclaimed access. After we finish @@ -14520,6 +14520,7 @@ static int intel_atomic_commit(struct drm_device *dev, intel_shared_dpll_commit(state); intel_atomic_track_fbs(state); + drm_atomic_state_get(state); if (nonblock) queue_work(system_unbound_wq, &state->commit_work); else @@ -14561,9 +14562,8 @@ retry: goto retry; } - if (ret) out: - drm_atomic_state_free(state); + drm_atomic_state_put(state); } /* @@ -16305,8 +16305,8 @@ retry: dev_priv->display.optimize_watermarks(cs); } - drm_atomic_state_free(state); fail: + drm_atomic_state_put(state); drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); } @@ -16943,10 +16943,9 @@ void intel_display_resume(struct drm_device *dev) drm_modeset_acquire_fini(&ctx); mutex_unlock(&dev->mode_config.mutex); - if (ret) { + if (ret) DRM_ERROR("Restoring old state failed with %i\n", ret); - drm_atomic_state_free(state); - } + drm_atomic_state_put(state); } void intel_modeset_gem_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 73a521fdf1bd..be3e04623e2a 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -987,9 +987,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, drm_modeset_backoff(&ctx); } - if (ret) - drm_atomic_state_free(state); - + drm_atomic_state_put(state); out: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index cf83f6507ec8..db61aa5f32ef 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -83,7 +83,7 @@ static void mtk_atomic_complete(struct mtk_drm_private *private, drm_atomic_helper_wait_for_vblanks(drm, state); drm_atomic_helper_cleanup_planes(drm, state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); } static void mtk_atomic_work(struct work_struct *work) @@ -110,6 +110,7 @@ static int mtk_atomic_commit(struct drm_device *drm, drm_atomic_helper_swap_state(state, true); + drm_atomic_state_get(state); if (async) mtk_atomic_schedule(private, state); else diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 73bae382eac3..db193f835298 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -141,7 +141,7 @@ static void complete_commit(struct msm_commit *c, bool async) kms->funcs->complete_commit(kms, state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); commit_destroy(c); } @@ -256,6 +256,7 @@ int msm_atomic_commit(struct drm_device *dev, * current layout. */ + drm_atomic_state_get(state); if (nonblock) { queue_work(priv->atomic_wq, &c->work); return 0; diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index e1cfba51cff6..1735c7accf72 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -105,7 +105,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) dispc_runtime_put(); - drm_atomic_state_free(old_state); + drm_atomic_state_put(old_state); /* Complete the commit, wake up any waiter. */ spin_lock(&priv->commit.lock); @@ -176,6 +176,7 @@ static int omap_atomic_commit(struct drm_device *dev, /* Swap the state, this is the point of no return. */ drm_atomic_helper_swap_state(state, true); + drm_atomic_state_get(state); if (nonblock) schedule_work(&commit->work); else diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index bd9c3bb9252c..c76ed9ee6a01 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -264,7 +264,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit) drm_atomic_helper_cleanup_planes(dev, old_state); - drm_atomic_state_free(old_state); + drm_atomic_state_put(old_state); /* Complete the commit, wake up any waiter. */ spin_lock(&rcdu->commit.wait.lock); @@ -330,6 +330,7 @@ static int rcar_du_atomic_commit(struct drm_device *dev, /* Swap the state, this is the point of no return. */ drm_atomic_helper_swap_state(state, true); + drm_atomic_state_get(state); if (nonblock) schedule_work(&commit->work); else diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 2784919a7366..7087499969bc 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -184,7 +184,7 @@ static void sti_atomic_complete(struct sti_private *private, drm_atomic_helper_wait_for_vblanks(drm, state); drm_atomic_helper_cleanup_planes(drm, state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); } static void sti_atomic_work(struct work_struct *work) @@ -217,6 +217,7 @@ static int sti_atomic_commit(struct drm_device *drm, drm_atomic_helper_swap_state(state, true); + drm_atomic_state_get(state); if (nonblock) sti_atomic_schedule(private, state); else diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 8ab47b502d83..a9630c2d6cb3 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -63,7 +63,7 @@ static void tegra_atomic_complete(struct tegra_drm *tegra, drm_atomic_helper_wait_for_vblanks(drm, state); drm_atomic_helper_cleanup_planes(drm, state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); } static void tegra_atomic_work(struct work_struct *work) @@ -96,6 +96,7 @@ static int tegra_atomic_commit(struct drm_device *drm, drm_atomic_helper_swap_state(state, true); + drm_atomic_state_get(state); if (nonblock) tegra_atomic_schedule(tegra, state); else diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index a694977c32f4..147fb28287ae 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -143,8 +143,6 @@ static int tilcdc_commit(struct drm_device *dev, drm_atomic_helper_cleanup_planes(dev, state); - drm_atomic_state_free(state); - return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index c1f65c6c8e60..f31f72af8551 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -61,7 +61,7 @@ vc4_atomic_complete_commit(struct vc4_commit *c) drm_atomic_helper_cleanup_planes(dev, state); - drm_atomic_state_free(state); + drm_atomic_state_put(state); up(&vc4->async_modeset); @@ -173,6 +173,7 @@ static int vc4_atomic_commit(struct drm_device *dev, * current layout. */ + drm_atomic_state_get(state); if (nonblock) { vc4_queue_seqno_cb(dev, &c->cb, wait_seqno, vc4_atomic_complete_commit_seqno_cb); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index c52f99415c55..fc8af53b18aa 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -153,6 +153,7 @@ struct __drm_connnectors_state { /** * struct drm_atomic_state - the global state object for atomic updates + * @ref: count of all references to this state (will not be freed until zero) * @dev: parent DRM device * @allow_modeset: allow full modeset * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics @@ -164,6 +165,8 @@ struct __drm_connnectors_state { * @acquire_ctx: acquire context for this atomic modeset state update */ struct drm_atomic_state { + struct kref ref; + struct drm_device *dev; bool allow_modeset : 1; bool legacy_cursor_update : 1; @@ -193,7 +196,33 @@ static inline void drm_crtc_commit_get(struct drm_crtc_commit *commit) struct drm_atomic_state * __must_check drm_atomic_state_alloc(struct drm_device *dev); void drm_atomic_state_clear(struct drm_atomic_state *state); -void drm_atomic_state_free(struct drm_atomic_state *state); + +/** + * drm_atomic_state_get - acquire a reference to the atomic state + * @state: The atomic state + * + * Returns a new reference to the @state + */ +static inline struct drm_atomic_state * +drm_atomic_state_get(struct drm_atomic_state *state) +{ + kref_get(&state->ref); + return state; +} + +void __drm_atomic_state_free(struct kref *ref); + +/** + * drm_atomic_state_put - release a reference to the atomic state + * @state: The atomic state + * + * This releases a reference to @state which is freed after removing the + * final reference. No locking required and callable from any context. + */ +static inline void drm_atomic_state_put(struct drm_atomic_state *state) +{ + kref_put(&state->ref, __drm_atomic_state_free); +} int __must_check drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 43cf193e54d6..02353904cdba 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -88,7 +88,6 @@ struct drm_plane_state { struct drm_atomic_state *state; }; - /** * struct drm_plane_funcs - driver plane control functions */ -- cgit v1.2.3 From 49521b13cbc02aff9ac1fff8d425055cc86cef08 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 14 Oct 2016 15:22:22 +0200 Subject: drivers/gpu/vga: allocate vga_arb_write() buffer on stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Size of kmalloc() in vga_arb_write() is controlled by user. Too large kmalloc() size triggers WARNING message on console. Allocate the buffer on stack to avoid the WARNING. The string must be small (e.g "target PCI:domain:bus:dev.fn"). Signed-off-by: Dmitry Vyukov Reviewed-by: Ville Syrjälä Cc: Dave Airlie Cc: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Cc: syzkaller@googlegroups.com Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476451342-146510-1-git-send-email-dvyukov@google.com --- drivers/gpu/vga/vgaarb.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index 1887f199ccb7..77657a8c0cd4 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c @@ -1022,21 +1022,16 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf, unsigned int io_state; - char *kbuf, *curr_pos; + char kbuf[64], *curr_pos; size_t remaining = count; int ret_val; int i; - - kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; - - if (copy_from_user(kbuf, buf, count)) { - kfree(kbuf); + if (count >= sizeof(kbuf)) + return -EINVAL; + if (copy_from_user(kbuf, buf, count)) return -EFAULT; - } curr_pos = kbuf; kbuf[count] = '\0'; /* Just to make sure... */ @@ -1259,11 +1254,9 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf, goto done; } /* If we got here, the message written is not part of the protocol! */ - kfree(kbuf); return -EPROTO; done: - kfree(kbuf); return ret_val; } -- cgit v1.2.3 From 603311ba979fa5bbbf6a8961e5f7a27deafce1b4 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 5 Oct 2016 14:35:01 -0700 Subject: soc: renesas: rcar-sysc: add R8A7743 support Add support for RZ/G1M (R8A7743) SoC power areas to the R-Car SYSC driver. Based on the original (and large) patch by Dmitry Shifrin . Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- .../bindings/power/renesas,rcar-sysc.txt | 7 +++-- drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/r8a7743-sysc.c | 32 ++++++++++++++++++++++ drivers/soc/renesas/rcar-sysc.c | 3 ++ drivers/soc/renesas/rcar-sysc.h | 1 + 5 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 drivers/soc/renesas/r8a7743-sysc.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt index 0725fb37a973..c16ec1866ac4 100644 --- a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt +++ b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt @@ -1,12 +1,13 @@ -DT bindings for the Renesas R-Car System Controller +DT bindings for the Renesas R-Car (RZ/G) System Controller == System Controller Node == -The R-Car System Controller provides power management for the CPU cores and -various coprocessors. +The R-Car (RZ/G) System Controller provides power management for the CPU cores +and various coprocessors. Required properties: - compatible: Must contain exactly one of the following: + - "renesas,r8a7743-sysc" (RZ/G1M) - "renesas,r8a7779-sysc" (R-Car H1) - "renesas,r8a7790-sysc" (R-Car H2) - "renesas,r8a7791-sysc" (R-Car M2-W) diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 623039c3514c..9e0bb329594c 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o diff --git a/drivers/soc/renesas/r8a7743-sysc.c b/drivers/soc/renesas/r8a7743-sysc.c new file mode 100644 index 000000000000..9583a327d90c --- /dev/null +++ b/drivers/soc/renesas/r8a7743-sysc.c @@ -0,0 +1,32 @@ +/* + * Renesas RZ/G1M System Controller + * + * Copyright (C) 2016 Cogent Embedded Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; of the License. + */ + +#include +#include + +#include + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a7743_areas[] __initconst = { + { "always-on", 0, 0, R8A7743_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca15-scu", 0x180, 0, R8A7743_PD_CA15_SCU, R8A7743_PD_ALWAYS_ON, + PD_SCU }, + { "ca15-cpu0", 0x40, 0, R8A7743_PD_CA15_CPU0, R8A7743_PD_CA15_SCU, + PD_CPU_NOCR }, + { "ca15-cpu1", 0x40, 1, R8A7743_PD_CA15_CPU1, R8A7743_PD_CA15_SCU, + PD_CPU_NOCR }, + { "sgx", 0xc0, 0, R8A7743_PD_SGX, R8A7743_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a7743_sysc_info __initconst = { + .areas = r8a7743_areas, + .num_areas = ARRAY_SIZE(r8a7743_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 65c8e1eb90c0..71acd45b13f0 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -275,6 +275,9 @@ finalize: } static const struct of_device_id rcar_sysc_matches[] = { +#ifdef CONFIG_ARCH_R8A7743 + { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info }, +#endif #ifdef CONFIG_ARCH_R8A7779 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info }, #endif diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index 77dbe861473f..8ab9ca8a825a 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -50,6 +50,7 @@ struct rcar_sysc_info { unsigned int num_areas; }; +extern const struct rcar_sysc_info r8a7743_sysc_info; extern const struct rcar_sysc_info r8a7779_sysc_info; extern const struct rcar_sysc_info r8a7790_sysc_info; extern const struct rcar_sysc_info r8a7791_sysc_info; -- cgit v1.2.3 From d0af1bd5f6f44971bea2e45acfe07de629734a3e Mon Sep 17 00:00:00 2001 From: Pankaj Bharadiya Date: Sun, 16 Oct 2016 15:29:14 +0530 Subject: staging: greybus: audio: Rename cport with intf_id gb_audio_manager_module_descriptor's cport field is actually used to manage and pass interface id to user space. Thus rename gb_audio_manager_module_descriptor's 'cport' field and few other things to avoid confusion. Signed-off-by: Pankaj Bharadiya Reviewed-by: Vaibhav Agarwal Acked-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_manager.h | 2 +- drivers/staging/greybus/audio_manager_module.c | 20 ++++++++++---------- drivers/staging/greybus/audio_manager_sysfs.c | 4 ++-- drivers/staging/greybus/audio_module.c | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/audio_manager.h b/drivers/staging/greybus/audio_manager.h index c4ca09754a6a..056088eb12fe 100644 --- a/drivers/staging/greybus/audio_manager.h +++ b/drivers/staging/greybus/audio_manager.h @@ -21,7 +21,7 @@ struct gb_audio_manager_module_descriptor { int slot; int vid; int pid; - int cport; + int intf_id; unsigned int ip_devices; unsigned int op_devices; }; diff --git a/drivers/staging/greybus/audio_manager_module.c b/drivers/staging/greybus/audio_manager_module.c index a10e96ad79c1..2bf40a90368d 100644 --- a/drivers/staging/greybus/audio_manager_module.c +++ b/drivers/staging/greybus/audio_manager_module.c @@ -111,16 +111,16 @@ static ssize_t gb_audio_module_pid_show( static struct gb_audio_manager_module_attribute gb_audio_module_pid_attribute = __ATTR(pid, 0664, gb_audio_module_pid_show, NULL); -static ssize_t gb_audio_module_cport_show( +static ssize_t gb_audio_module_intf_id_show( struct gb_audio_manager_module *module, struct gb_audio_manager_module_attribute *attr, char *buf) { - return sprintf(buf, "%d", module->desc.cport); + return sprintf(buf, "%d", module->desc.intf_id); } static struct gb_audio_manager_module_attribute - gb_audio_module_cport_attribute = - __ATTR(cport, 0664, gb_audio_module_cport_show, NULL); + gb_audio_module_intf_id_attribute = + __ATTR(intf_id, 0664, gb_audio_module_intf_id_show, NULL); static ssize_t gb_audio_module_ip_devices_show( struct gb_audio_manager_module *module, @@ -149,7 +149,7 @@ static struct attribute *gb_audio_module_default_attrs[] = { &gb_audio_module_slot_attribute.attr, &gb_audio_module_vid_attribute.attr, &gb_audio_module_pid_attribute.attr, - &gb_audio_module_cport_attribute.attr, + &gb_audio_module_intf_id_attribute.attr, &gb_audio_module_ip_devices_attribute.attr, &gb_audio_module_op_devices_attribute.attr, NULL, /* need to NULL terminate the list of attributes */ @@ -167,7 +167,7 @@ static void send_add_uevent(struct gb_audio_manager_module *module) char slot_string[64]; char vid_string[64]; char pid_string[64]; - char cport_string[64]; + char intf_id_string[64]; char ip_devices_string[64]; char op_devices_string[64]; @@ -176,7 +176,7 @@ static void send_add_uevent(struct gb_audio_manager_module *module) slot_string, vid_string, pid_string, - cport_string, + intf_id_string, ip_devices_string, op_devices_string, NULL @@ -186,7 +186,7 @@ static void send_add_uevent(struct gb_audio_manager_module *module) snprintf(slot_string, 64, "SLOT=%d", module->desc.slot); snprintf(vid_string, 64, "VID=%d", module->desc.vid); snprintf(pid_string, 64, "PID=%d", module->desc.pid); - snprintf(cport_string, 64, "CPORT=%d", module->desc.cport); + snprintf(intf_id_string, 64, "INTF_ID=%d", module->desc.intf_id); snprintf(ip_devices_string, 64, "I/P DEVICES=0x%X", module->desc.ip_devices); snprintf(op_devices_string, 64, "O/P DEVICES=0x%X", @@ -246,13 +246,13 @@ int gb_audio_manager_module_create( void gb_audio_manager_module_dump(struct gb_audio_manager_module *module) { - pr_info("audio module #%d name=%s slot=%d vid=%d pid=%d cport=%d i/p devices=0x%X o/p devices=0x%X\n", + pr_info("audio module #%d name=%s slot=%d vid=%d pid=%d intf_id=%d i/p devices=0x%X o/p devices=0x%X\n", module->id, module->desc.name, module->desc.slot, module->desc.vid, module->desc.pid, - module->desc.cport, + module->desc.intf_id, module->desc.ip_devices, module->desc.op_devices); } diff --git a/drivers/staging/greybus/audio_manager_sysfs.c b/drivers/staging/greybus/audio_manager_sysfs.c index 376e17cb6cd7..fc0aca6fe912 100644 --- a/drivers/staging/greybus/audio_manager_sysfs.c +++ b/drivers/staging/greybus/audio_manager_sysfs.c @@ -20,10 +20,10 @@ static ssize_t manager_sysfs_add_store( int num = sscanf(buf, "name=%" GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "s " - "slot=%d vid=%d pid=%d cport=%d i/p devices=0x%X" + "slot=%d vid=%d pid=%d intf_id=%d i/p devices=0x%X" "o/p devices=0x%X", desc.name, &desc.slot, &desc.vid, &desc.pid, - &desc.cport, &desc.ip_devices, &desc.op_devices); + &desc.intf_id, &desc.ip_devices, &desc.op_devices); if (num != 7) return -EINVAL; diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index ae1c0fa85752..45b2519322c3 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -348,7 +348,7 @@ static int gb_audio_probe(struct gb_bundle *bundle, desc.slot = 1; /* todo */ desc.vid = 2; /* todo */ desc.pid = 3; /* todo */ - desc.cport = gbmodule->dev_id; + desc.intf_id = gbmodule->dev_id; desc.op_devices = gbmodule->op_devices; desc.ip_devices = gbmodule->ip_devices; gbmodule->manager_id = gb_audio_manager_add(&desc); -- cgit v1.2.3 From 9edae49285051dc9312392df0d07c85f236a4d4b Mon Sep 17 00:00:00 2001 From: sayli karnik Date: Sun, 16 Oct 2016 14:19:48 +0530 Subject: staging: greybus: es2: Use kmemdup instead of kmalloc and memcpy This patch replaces kmalloc and memcpy with kmemdup for duplication of memory. Signed-off-by: sayli karnik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/es2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 071bb1cfd3ae..8eabc713a26d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -175,10 +175,9 @@ static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) u8 *data; int retval; - data = kmalloc(size, GFP_KERNEL); + data = kmemdup(req, size, GFP_KERNEL); if (!data) return -ENOMEM; - memcpy(data, req, size); retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), cmd, -- cgit v1.2.3 From 4d79f43191305b8382ae90147a34487b347b0509 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 15 Oct 2016 12:28:01 +0530 Subject: Staging: greybus: uart: constify tty_port_operations structure Declare tty_port_operations structure as const as it is only stored in the ops field of a tty_port structure which is a field of a gb_tty structure. The ops field is of type const struct tty_port_operations *, so tty_port_operations structures having this property can be declared as const. Done using Coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct tty_port_operations i@p = {...}; @ok1@ identifier r1.i; position p; struct gb_tty q; @@ q.port.ops=&i@p @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct tty_port_operations i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct tty_port_operations i; File size before: text data bss dec hex filename 7646 512 56 8214 2016 drivers/staging/greybus/uart.o File size after: text data bss dec hex filename 7710 448 56 8214 2016 drivers/staging/greybus/uart.o Signed-off-by: Bhumika Goyal Acked-by: Johan Hovold Reviewed-by: David Lin Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 5ee7954bd9f9..8162886bcaed 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -832,7 +832,7 @@ static const struct tty_operations gb_ops = { .tiocmset = gb_tty_tiocmset, }; -static struct tty_port_operations gb_port_ops = { +static const struct tty_port_operations gb_port_ops = { .dtr_rts = gb_tty_dtr_rts, .activate = gb_tty_port_activate, .shutdown = gb_tty_port_shutdown, -- cgit v1.2.3 From 2328ed663b3a34123df2c794f95505d332dc5284 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 15 Oct 2016 11:43:48 +0530 Subject: Staging: android: ion: constify dma_buf_ops structure The dma_buf_ops structure is stored in the ops field of a dma_buf_export_info structure and also used as a condition inside the if() statement. The if condition does not modify its value and the ops field is of type const struct *dma_buf_ops, so dma_buf_ops structures having this property can be declared as const. File size before: text data bss dec hex filename 14471 819 224 15514 3c9a drivers/staging/android/ion/ion.o File size after: text data bss dec hex filename 14599 707 224 15530 3caa drivers/staging/android/ion/ion.o Signed-off-by: Bhumika Goyal Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 396ded52ab70..45eceea449e4 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1013,7 +1013,7 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, return 0; } -static struct dma_buf_ops dma_buf_ops = { +static const struct dma_buf_ops dma_buf_ops = { .map_dma_buf = ion_map_dma_buf, .unmap_dma_buf = ion_unmap_dma_buf, .mmap = ion_mmap, -- cgit v1.2.3 From 6aab2d7eacb078d2ad9b6ca5245521a7886e5d29 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Fri, 14 Oct 2016 21:32:03 -0300 Subject: staging: sm750fb: Add const qualifier to struct declaration. Const qualifier added to struct declaration to avoid data overwrite during runtime and improve security. Signed-off-by: Elise Lennion Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index b094492cc5f0..0663ec00206b 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1188,7 +1188,7 @@ static int __init lynxfb_setup(char *options) return 0; } -static struct pci_device_id smi_pci_table[] = { +static const struct pci_device_id smi_pci_table[] = { { PCI_DEVICE(0x126f, 0x0750), }, {0,} }; -- cgit v1.2.3 From d44e0e5ddc3ec4c7387a4044ede659781babc329 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Fri, 14 Oct 2016 21:35:13 -0300 Subject: staging: dgnc: Add const qualifier to struct declaration. Const qualifier added to struct declaration to avoid data overwrite during runtime and improve security. Signed-off-by: Elise Lennion Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_driver.c | 2 +- drivers/staging/dgnc/dgnc_tty.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index fd372d3afa46..6576674e75b0 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -93,7 +93,7 @@ struct board_id { unsigned int is_pci_express; }; -static struct board_id dgnc_ids[] = { +static const struct board_id dgnc_ids[] = { { PCI_DEVICE_CLASSIC_4_PCI_NAME, 4, 0 }, { PCI_DEVICE_CLASSIC_4_422_PCI_NAME, 4, 0 }, { PCI_DEVICE_CLASSIC_8_PCI_NAME, 8, 0 }, diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index ef9a45bc0b89..cf8aefdc9534 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -50,7 +50,7 @@ static unsigned char *dgnc_TmpWriteBuf; /* * Default transparent print information. */ -static struct digi_t dgnc_digi_init = { +static const struct digi_t dgnc_digi_init = { .digi_flags = DIGI_COOK, /* Flags */ .digi_maxcps = 100, /* Max CPS */ .digi_maxchar = 50, /* Max chars in print queue */ -- cgit v1.2.3 From e2aefba617e37b27537ca5e09e0e05088fa70b2c Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 14 Oct 2016 11:58:08 +0300 Subject: staging:vt6656:baseband.h: fix function definition argument without identifier name issue Function definitions arguments should also have an identifier name as reported by checkpatch.pl. Signed-off-by: Mikhail Golubev Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/baseband.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h index 7cc13874f8f1..fe1c25c64cca 100644 --- a/drivers/staging/vt6656/baseband.h +++ b/drivers/staging/vt6656/baseband.h @@ -86,15 +86,15 @@ struct vnt_phy_field { unsigned int vnt_get_frame_time(u8 preamble_type, u8 pkt_type, unsigned int frame_length, u16 tx_rate); -void vnt_get_phy_field(struct vnt_private *, u32 frame_length, - u16 tx_rate, u8 pkt_type, struct vnt_phy_field *); - -void vnt_set_short_slot_time(struct vnt_private *); -void vnt_set_vga_gain_offset(struct vnt_private *, u8); -void vnt_set_antenna_mode(struct vnt_private *, u8); -int vnt_vt3184_init(struct vnt_private *); -void vnt_set_deep_sleep(struct vnt_private *); -void vnt_exit_deep_sleep(struct vnt_private *); -void vnt_update_pre_ed_threshold(struct vnt_private *, int scanning); +void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length, + u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy); + +void vnt_set_short_slot_time(struct vnt_private *priv); +void vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data); +void vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode); +int vnt_vt3184_init(struct vnt_private *priv); +void vnt_set_deep_sleep(struct vnt_private *priv); +void vnt_exit_deep_sleep(struct vnt_private *priv); +void vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning); #endif /* __BASEBAND_H__ */ -- cgit v1.2.3 From ae719092fe1b7e147ab428903475b4b46ff79389 Mon Sep 17 00:00:00 2001 From: Laurent Navet Date: Sat, 15 Oct 2016 11:50:11 +0200 Subject: staging: unisys: visorbus: add missing include this removes lots of sparse warnings : warning: symbol 'visorchannel_destroy' was not declared. Should it be static? warning: symbol 'visorchannel_get_physaddr' was not declared. Should it be static? warning: symbol 'visorchannel_get_nbytes' was not declared. Should it be static? warning: symbol 'visorchannel_uuid_id' was not declared. Should it be static? warning: symbol 'visorchannel_id' was not declared. Should it be static? warning: symbol 'visorchannel_zoneid' was not declared. Should it be static? warning: symbol 'visorchannel_get_clientpartition' was not declared. Should it be static? warning: symbol 'visorchannel_set_clientpartition' was not declared. Should it be static? warning: symbol 'visorchannel_read' was not declared. Should it be static? warning: symbol 'visorchannel_write' was not declared. Should it be static? warning: symbol 'visorchannel_get_header' was not declared. Should it be static? warning: symbol 'visorchannel_create' was not declared. Should it be static? warning: symbol 'visorchannel_create_with_lock' was not declared. Should it be static? Signed-off-by: Laurent Navet Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchannel.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 300a65dc5c6c..a1381eb81674 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -23,6 +23,7 @@ #include #include "visorbus.h" +#include "visorbus_private.h" #include "controlvmchannel.h" #define MYDRVNAME "visorchannel" -- cgit v1.2.3 From ee705c3b938531992affc01d16bc32ccd5ee968c Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Sun, 16 Oct 2016 00:55:22 +0300 Subject: Staging: vt6656: Make a read-only structure This patch add const qualifier at the declaration of the structure. The structure become a read-only data, this increase the security. Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 0594828bdabf..fe84da363fbd 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -85,7 +85,7 @@ MODULE_PARM_DESC(tx_buffers, "Number of receive usb tx buffers"); * Static vars definitions */ -static struct usb_device_id vt6656_table[] = { +static const struct usb_device_id vt6656_table[] = { {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)}, {} }; -- cgit v1.2.3 From 68a30a63516bcfdf0917bc5acb56150ea7f059ab Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Sat, 15 Oct 2016 19:26:26 -0300 Subject: staging: wilc1000: Remove unnecessary extern variables. Extern variables and functions used in only one file were removed from .h files, and made static in the .c files they're used. Extern variable wilc_initialized was declared and never used, so it was removed. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 1 - drivers/staging/wilc1000/linux_wlan.c | 6 ++++-- drivers/staging/wilc1000/wilc_sdio.c | 3 ++- drivers/staging/wilc1000/wilc_spi.c | 3 ++- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 5 ----- drivers/staging/wilc1000/wilc_wlan.h | 6 ------ 6 files changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index ddfea29df2a7..f36d3b5a0370 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -367,7 +367,6 @@ extern u8 wilc_connected_ssid[6]; extern u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN]; extern int wilc_connecting; -extern u8 wilc_initialized; extern struct timer_list wilc_during_ip_timer; #endif diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 6370a5efe343..42bb86bdb7c2 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -37,6 +37,8 @@ static void linux_wlan_tx_complete(void *priv, int status); static int mac_init_fn(struct net_device *ndev); static struct net_device_stats *mac_stats(struct net_device *dev); static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd); +static int wilc_mac_open(struct net_device *ndev); +static int wilc_mac_close(struct net_device *ndev); static void wilc_set_multicast_list(struct net_device *dev); bool wilc_enable_ps = true; @@ -847,7 +849,7 @@ static int mac_init_fn(struct net_device *ndev) return 0; } -int wilc_mac_open(struct net_device *ndev) +static int wilc_mac_open(struct net_device *ndev) { struct wilc_vif *vif; @@ -1038,7 +1040,7 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) return 0; } -int wilc_mac_close(struct net_device *ndev) +static int wilc_mac_close(struct net_device *ndev) { struct wilc_priv *priv; struct wilc_vif *vif; diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 39b73fb27398..3ad7cec4662d 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -39,6 +39,7 @@ struct wilc_sdio { }; static struct wilc_sdio g_sdio; +static const struct wilc_hif_func wilc_hif_sdio; static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data); static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data); @@ -1100,7 +1101,7 @@ static int sdio_sync_ext(struct wilc *wilc, int nint) * ********************************************/ -const struct wilc_hif_func wilc_hif_sdio = { +static const struct wilc_hif_func wilc_hif_sdio = { .hif_init = sdio_init, .hif_deinit = sdio_deinit, .hif_read_reg = sdio_read_reg, diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 572e57d08a11..55d53c3a95df 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -30,6 +30,7 @@ struct wilc_spi { }; static struct wilc_spi g_spi; +static const struct wilc_hif_func wilc_hif_spi; static int wilc_spi_read(struct wilc *wilc, u32, u8 *, u32); static int wilc_spi_write(struct wilc *wilc, u32, u8 *, u32); @@ -1134,7 +1135,7 @@ static int wilc_spi_sync_ext(struct wilc *wilc, int nint) * Global spi HIF function table * ********************************************/ -const struct wilc_hif_func wilc_hif_spi = { +static const struct wilc_hif_func wilc_hif_spi = { .hif_init = wilc_spi_init, .hif_deinit = _wilc_spi_deinit, .hif_read_reg = wilc_spi_read_reg, diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index f46dcd291d92..c1a24f7bc85f 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -90,17 +90,12 @@ static const struct wiphy_wowlan_support wowlan_support = { #define IS_MGMT_STATUS_SUCCES 0x040 #define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) -extern int wilc_mac_open(struct net_device *ndev); -extern int wilc_mac_close(struct net_device *ndev); - static struct network_info last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; static u32 last_scanned_cnt; struct timer_list wilc_during_ip_timer; static struct timer_list hAgingTimer; static u8 op_ifcs; -u8 wilc_initialized = 1; - #define CHAN2G(_channel, _freq, _flags) { \ .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index de6c4ddbf45a..11365efcc5d0 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -248,9 +248,6 @@ struct wilc_hif_func { void (*disable_interrupt)(struct wilc *nic); }; -extern const struct wilc_hif_func wilc_hif_spi; -extern const struct wilc_hif_func wilc_hif_sdio; - /******************************************** * * Configuration Structure @@ -297,9 +294,6 @@ void wilc_enable_tcp_ack_filter(bool value); int wilc_wlan_get_num_conn_ifcs(struct wilc *); int wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); -int wilc_mac_open(struct net_device *ndev); -int wilc_mac_close(struct net_device *ndev); - void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size); void host_wakeup_notify(struct wilc *wilc); void host_sleep_notify(struct wilc *wilc); -- cgit v1.2.3 From ab1effc09519f3bb4b84dd6d8276cedf07b17a1b Mon Sep 17 00:00:00 2001 From: Sabitha George Date: Sun, 16 Oct 2016 21:42:44 +0530 Subject: staging: ks7010: Add blank line after declarations Fixes checkpatch.pl warning :Missing a blank line after declarations Signed-off-by: Sabitha George Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 1f9f63e6e996..ad840f9f4b77 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -750,6 +750,7 @@ void hostif_start_confirm(struct ks_wlan_private *priv) { #ifdef WPS union iwreq_data wrqu; + wrqu.data.length = 0; wrqu.data.flags = 0; wrqu.ap_addr.sa_family = ARPHRD_ETHER; @@ -771,6 +772,7 @@ void hostif_connect_indication(struct ks_wlan_private *priv) unsigned int old_status = priv->connect_status; struct net_device *netdev = priv->net_dev; union iwreq_data wrqu0; + connect_code = get_WORD(priv); switch (connect_code) { @@ -910,6 +912,7 @@ static void hostif_infrastructure_set_confirm(struct ks_wlan_private *priv) { uint16_t result_code; + DPRINTK(3, "\n"); result_code = get_WORD(priv); DPRINTK(3, "result code = %d\n", result_code); @@ -975,6 +978,7 @@ void hostif_bss_scan_confirm(struct ks_wlan_private *priv) unsigned int result_code; struct net_device *dev = priv->net_dev; union iwreq_data wrqu; + result_code = get_DWORD(priv); DPRINTK(2, "result=%d :: scan_ind_count=%d\n", result_code, priv->scan_ind_count); @@ -1872,6 +1876,7 @@ static void hostif_sme_set_wep(struct ks_wlan_private *priv, int type) { uint32_t val; + switch (type) { case SME_WEP_INDEX_REQUEST: val = cpu_to_le32((uint32_t) (priv->reg.wep_index)); @@ -2335,6 +2340,7 @@ static void hostif_sme_set_key(struct ks_wlan_private *priv, int type) { uint32_t val; + switch (type) { case SME_SET_FLAG: val = cpu_to_le32((uint32_t) (priv->reg.privacy_invoked)); -- cgit v1.2.3 From bd46a80110dcc5c0216ee25acd8b1303ab23455f Mon Sep 17 00:00:00 2001 From: Sabitha George Date: Sun, 16 Oct 2016 21:44:26 +0530 Subject: staging: ks7010: Remove braces around single statement blocks Fixes checkpatch warning: braces{} are not necessary for single statment blocks Signed-off-by: Sabitha George Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index ad840f9f4b77..cbf49c951514 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -97,11 +97,10 @@ int ks_wlan_do_power_save(struct ks_wlan_private *priv) { DPRINTK(4, "psstatus.status=%d\n", atomic_read(&priv->psstatus.status)); - if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { + if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) hostif_sme_enqueue(priv, SME_POW_MNGMT_REQUEST); - } else { + else priv->dev_state = DEVICE_STATE_READY; - } return 0; } @@ -687,15 +686,13 @@ void hostif_mib_set_confirm(struct ks_wlan_private *priv) break; case DOT11_GMK1_TSC: DPRINTK(2, "DOT11_GMK1_TSC:mib_status=%d\n", (int)mib_status); - if (atomic_read(&priv->psstatus.snooze_guard)) { + if (atomic_read(&priv->psstatus.snooze_guard)) atomic_set(&priv->psstatus.snooze_guard, 0); - } break; case DOT11_GMK2_TSC: DPRINTK(2, "DOT11_GMK2_TSC:mib_status=%d\n", (int)mib_status); - if (atomic_read(&priv->psstatus.snooze_guard)) { + if (atomic_read(&priv->psstatus.snooze_guard)) atomic_set(&priv->psstatus.snooze_guard, 0); - } break; case LOCAL_PMK: DPRINTK(2, "LOCAL_PMK:mib_status=%d\n", (int)mib_status); @@ -2436,9 +2433,8 @@ void hostif_sme_execute(struct ks_wlan_private *priv, int event) DPRINTK(3, "event=%d\n", event); switch (event) { case SME_START: - if (priv->dev_state == DEVICE_STATE_BOOT) { + if (priv->dev_state == DEVICE_STATE_BOOT) hostif_mib_get_request(priv, DOT11_MAC_ADDRESS); - } break; case SME_MULTICAST_REQUEST: hostif_sme_multicast_set(priv); @@ -2483,14 +2479,12 @@ void hostif_sme_execute(struct ks_wlan_private *priv, int event) } break; case SME_GET_MAC_ADDRESS: - if (priv->dev_state == DEVICE_STATE_BOOT) { + if (priv->dev_state == DEVICE_STATE_BOOT) hostif_mib_get_request(priv, DOT11_PRODUCT_VERSION); - } break; case SME_GET_PRODUCT_VERSION: - if (priv->dev_state == DEVICE_STATE_BOOT) { + if (priv->dev_state == DEVICE_STATE_BOOT) priv->dev_state = DEVICE_STATE_PREINIT; - } break; case SME_STOP_REQUEST: hostif_stop_request(priv); @@ -2569,9 +2563,8 @@ void hostif_sme_execute(struct ks_wlan_private *priv, int event) /* for power save */ atomic_set(&priv->psstatus.snooze_guard, 0); atomic_set(&priv->psstatus.confirm_wait, 0); - if (priv->dev_state == DEVICE_STATE_PREINIT) { + if (priv->dev_state == DEVICE_STATE_PREINIT) priv->dev_state = DEVICE_STATE_INIT; - } /* wake_up_interruptible_all(&priv->confirm_wait); */ complete(&priv->confirm_wait); break; -- cgit v1.2.3 From a2d1e4285542bbe9f2851baed47b7f5c7eccba50 Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Sun, 16 Oct 2016 01:41:14 +0300 Subject: Staging: unisys: visorbus: Make a read-only structure This patch add const qualifier at the declaration of the structure. The structure become a read-only data, this increase the security. Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 59871495ea85..8e67c1754f05 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1317,7 +1317,7 @@ static struct attribute *visorchipset_install_attrs[] = { NULL }; -static struct attribute_group visorchipset_install_group = { +static const struct attribute_group visorchipset_install_group = { .name = "install", .attrs = visorchipset_install_attrs }; -- cgit v1.2.3 From ce439c425b4e3f93e366939837127fcfd7d013e2 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Mon, 17 Oct 2016 00:18:58 -0200 Subject: staging: vt6656: Compress return logic into one line. Compress the return logic into one line avoids unnecessary variable declarations. In this case it also makes it easier to understand the function. Coccinelle was used to find this return statement. However, additional compressions were done to make the function clearer. Semantic patch: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/card.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 807d3f7af58d..0e5a99375099 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -501,16 +501,7 @@ u8 vnt_get_pkt_type(struct vnt_private *priv) */ u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) { - u64 tsf_offset = 0; - u16 rx_bcn_offset; - - rx_bcn_offset = cw_rxbcntsf_off[rx_rate % MAX_RATE]; - - tsf2 += (u64)rx_bcn_offset; - - tsf_offset = tsf1 - tsf2; - - return tsf_offset; + return tsf1 - tsf2 - (u64)cw_rxbcntsf_off[rx_rate % MAX_RATE]; } /* -- cgit v1.2.3 From dcb9360e66289d6336f8dbd483babf39ac8e73a5 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Mon, 17 Oct 2016 00:17:20 -0200 Subject: staging: xgifb: Compress return logic into one line. Simplify return logic to avoid unnecessary variable assignments. Coccinelle was used with this semantic patch: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index d8010c5c1a70..f4bcb15625ce 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1682,13 +1682,11 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, } if (pVBInfo->TVInfo & TVSetYPbPr750p) { - tempal = XGI_YPbPr750pVCLK; - return tempal; + return XGI_YPbPr750pVCLK; } if (pVBInfo->TVInfo & TVSetYPbPr525p) { - tempal = YPbPr525pVCLK; - return tempal; + return YPbPr525pVCLK; } tempal = NTSC1024VCLK; @@ -1705,8 +1703,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, } /* {End of VB} */ inb((pVBInfo->P3ca + 0x02)); - tempal = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; - return tempal; + return XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; } static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0, -- cgit v1.2.3 From a98753b7e94c867361228c59edf9be195d1dfd84 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Mon, 17 Oct 2016 00:15:47 -0200 Subject: staging: rtl8192e: Compress return logic into one line. Simplify return logic to avoid unnecessary variable assignments. Coccinelle was used with this semantic patch: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c index 9aaa85526eb8..bbe399010be1 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c @@ -202,7 +202,5 @@ bool rtl92e_init_fw(struct net_device *dev) download_firmware_fail: netdev_err(dev, "%s: Failed to initialize firmware.\n", __func__); - rt_status = false; - return rt_status; - + return false; } -- cgit v1.2.3 From 00162ea2e4cc65e454b8b70f2964e431085414fe Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman Date: Sun, 16 Oct 2016 23:46:30 -0700 Subject: staging: rtl8188eu: core: constify local structure Constify the static struct RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE. The only other instance was one of its properties being assigned to a variable: Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; Therefore this is a good candidate for constification. Running size did not show any difference: Before/After: text data bss dec hex filename 44122 408 2974 47504 b990 Lastly, break up the long line to fix the checkpatch warning and conform to kernel coding style. Signed-off-by: Elizabeth Ferdman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index fb13df586441..c94700cf5664 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -133,7 +133,9 @@ static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */ }; -static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the combination for max channel numbers */ +static const struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = { + 0x03 +}; /* use the combination for max channel numbers */ /* * Search the @param channel_num in given @param channel_set -- cgit v1.2.3 From 26f64a6ba149949f40c04502f81b1011d9d9184f Mon Sep 17 00:00:00 2001 From: Varsha Rao Date: Sat, 15 Oct 2016 16:02:58 +0530 Subject: Staging: vt6655: Replace dwIoBase by iobase In this patch dwIoBase is renamed as iobase. This is done to fix the checkpatch issue of CamelCase. Signed-off-by: Varsha Rao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 52 +++--- drivers/staging/vt6655/card.c | 30 ++-- drivers/staging/vt6655/mac.h | 322 +++++++++++++++++++------------------- drivers/staging/vt6655/rf.c | 64 ++++---- drivers/staging/vt6655/srom.c | 32 ++-- drivers/staging/vt6655/srom.h | 6 +- 6 files changed, 253 insertions(+), 253 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 2696f505910b..44dfa5421374 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1911,7 +1911,7 @@ void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length, * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * byBBAddr - address of register in Baseband * Out: * pbyData - data read @@ -1922,24 +1922,24 @@ void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length, bool BBbReadEmbedded(struct vnt_private *priv, unsigned char byBBAddr, unsigned char *pbyData) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; unsigned short ww; unsigned char byValue; /* BB reg offset */ - VNSvOutPortB(dwIoBase + MAC_REG_BBREGADR, byBBAddr); + VNSvOutPortB(iobase + MAC_REG_BBREGADR, byBBAddr); /* turn on REGR */ - MACvRegBitsOn(dwIoBase, MAC_REG_BBREGCTL, BBREGCTL_REGR); + MACvRegBitsOn(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGR); /* W_MAX_TIMEOUT is the timeout period */ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - VNSvInPortB(dwIoBase + MAC_REG_BBREGCTL, &byValue); + VNSvInPortB(iobase + MAC_REG_BBREGCTL, &byValue); if (byValue & BBREGCTL_DONE) break; } /* get BB data */ - VNSvInPortB(dwIoBase + MAC_REG_BBREGDATA, pbyData); + VNSvInPortB(iobase + MAC_REG_BBREGDATA, pbyData); if (ww == W_MAX_TIMEOUT) { pr_debug(" DBG_PORT80(0x30)\n"); @@ -1953,7 +1953,7 @@ bool BBbReadEmbedded(struct vnt_private *priv, * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * byBBAddr - address of register in Baseband * byData - data to write * Out: @@ -1965,20 +1965,20 @@ bool BBbReadEmbedded(struct vnt_private *priv, bool BBbWriteEmbedded(struct vnt_private *priv, unsigned char byBBAddr, unsigned char byData) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; unsigned short ww; unsigned char byValue; /* BB reg offset */ - VNSvOutPortB(dwIoBase + MAC_REG_BBREGADR, byBBAddr); + VNSvOutPortB(iobase + MAC_REG_BBREGADR, byBBAddr); /* set BB data */ - VNSvOutPortB(dwIoBase + MAC_REG_BBREGDATA, byData); + VNSvOutPortB(iobase + MAC_REG_BBREGDATA, byData); /* turn on BBREGCTL_REGW */ - MACvRegBitsOn(dwIoBase, MAC_REG_BBREGCTL, BBREGCTL_REGW); + MACvRegBitsOn(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGW); /* W_MAX_TIMEOUT is the timeout period */ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - VNSvInPortB(dwIoBase + MAC_REG_BBREGCTL, &byValue); + VNSvInPortB(iobase + MAC_REG_BBREGCTL, &byValue); if (byValue & BBREGCTL_DONE) break; } @@ -1995,7 +1995,7 @@ bool BBbWriteEmbedded(struct vnt_private *priv, * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * byRevId - Revision ID * byRFType - RF type * Out: @@ -2009,7 +2009,7 @@ bool BBbVT3253Init(struct vnt_private *priv) { bool bResult = true; int ii; - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; unsigned char byRFType = priv->byRFType; unsigned char byLocalID = priv->byLocalID; @@ -2031,8 +2031,8 @@ bool BBbVT3253Init(struct vnt_private *priv) byVT3253B0_AGC4_RFMD2959[ii][0], byVT3253B0_AGC4_RFMD2959[ii][1]); - VNSvOutPortD(dwIoBase + MAC_REG_ITRTMSET, 0x23); - MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT(0)); + VNSvOutPortD(iobase + MAC_REG_ITRTMSET, 0x23); + MACvRegBitsOn(iobase, MAC_REG_PAPEDELAY, BIT(0)); } priv->abyBBVGA[0] = 0x18; priv->abyBBVGA[1] = 0x0A; @@ -2071,8 +2071,8 @@ bool BBbVT3253Init(struct vnt_private *priv) byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]); - VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23); - MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT(0)); + VNSvOutPortB(iobase + MAC_REG_ITRTMSET, 0x23); + MACvRegBitsOn(iobase, MAC_REG_PAPEDELAY, BIT(0)); priv->abyBBVGA[0] = 0x14; priv->abyBBVGA[1] = 0x0A; @@ -2093,7 +2093,7 @@ bool BBbVT3253Init(struct vnt_private *priv) * 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) */ - /*bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41);*/ + /*bResult &= BBbWriteEmbedded(iobase,0x09,0x41);*/ /* Init ANT B select, * RX Config CR10 = 0x28->0x2A, @@ -2101,7 +2101,7 @@ bool BBbVT3253Init(struct vnt_private *priv) * make the ANT_A, ANT_B inverted) */ - /*bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28);*/ + /*bResult &= BBbWriteEmbedded(iobase,0x0a,0x28);*/ /* Select VC1/VC2, CR215 = 0x02->0x06 */ bResult &= BBbWriteEmbedded(priv, 0xd7, 0x06); @@ -2149,7 +2149,7 @@ bool BBbVT3253Init(struct vnt_private *priv) priv->ldBmThreshold[2] = 0; priv->ldBmThreshold[3] = 0; /* Fix VT3226 DFC system timing issue */ - MACvSetRFLE_LatchBase(dwIoBase); + MACvSetRFLE_LatchBase(iobase); /* {{ RobertYu: 20050104 */ } else if (byRFType == RF_AIROHA7230) { for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) @@ -2161,11 +2161,11 @@ bool BBbVT3253Init(struct vnt_private *priv) /* Init ANT B select,TX Config CR09 = 0x61->0x45, * 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) */ - /*bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41);*/ + /*bResult &= BBbWriteEmbedded(iobase,0x09,0x41);*/ /* Init ANT B select,RX Config CR10 = 0x28->0x2A, * 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) */ - /*bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28);*/ + /*bResult &= BBbWriteEmbedded(iobase,0x0a,0x28);*/ /* Select VC1/VC2, CR215 = 0x02->0x06 */ bResult &= BBbWriteEmbedded(priv, 0xd7, 0x06); /* }} */ @@ -2253,7 +2253,7 @@ void BBvSetVGAGainOffset(struct vnt_private *priv, unsigned char byData) * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * Out: * none * @@ -2274,7 +2274,7 @@ BBvSoftwareReset(struct vnt_private *priv) * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * Out: * none * @@ -2296,7 +2296,7 @@ BBvPowerSaveModeON(struct vnt_private *priv) * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * Out: * none * diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 2e2f96d002e5..928c336f9d83 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -32,7 +32,7 @@ * * Revision History: * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. - * 08-26-2003 Kyle Hsu: Modify the defination type of dwIoBase. + * 08-26-2003 Kyle Hsu: Modify the defination type of iobase. * 09-01-2003 Bryan YC Fan: Add vUpdateIFS(). * */ @@ -934,20 +934,20 @@ u64 CARDqGetTSFOffset(unsigned char byRxRate, u64 qwTSF1, u64 qwTSF2) */ bool CARDbGetCurrentTSF(struct vnt_private *priv, u64 *pqwCurrTSF) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; unsigned short ww; unsigned char byData; - MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD); + MACvRegBitsOn(iobase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD); for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - VNSvInPortB(dwIoBase + MAC_REG_TFTCTL, &byData); + VNSvInPortB(iobase + MAC_REG_TFTCTL, &byData); if (!(byData & TFTCTL_TSFCNTRRD)) break; } if (ww == W_MAX_TIMEOUT) return false; - VNSvInPortD(dwIoBase + MAC_REG_TSFCNTR, (u32 *)pqwCurrTSF); - VNSvInPortD(dwIoBase + MAC_REG_TSFCNTR + 4, (u32 *)pqwCurrTSF + 1); + VNSvInPortD(iobase + MAC_REG_TSFCNTR, (u32 *)pqwCurrTSF); + VNSvInPortD(iobase + MAC_REG_TSFCNTR + 4, (u32 *)pqwCurrTSF + 1); return true; } @@ -985,7 +985,7 @@ u64 CARDqGetNextTBTT(u64 qwTSF, unsigned short wBeaconInterval) * * Parameters: * In: - * dwIoBase - IO Base + * iobase - IO Base * wBeaconInterval - Beacon Interval * Out: * none @@ -995,16 +995,16 @@ u64 CARDqGetNextTBTT(u64 qwTSF, unsigned short wBeaconInterval) void CARDvSetFirstNextTBTT(struct vnt_private *priv, unsigned short wBeaconInterval) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; u64 qwNextTBTT = 0; CARDbGetCurrentTSF(priv, &qwNextTBTT); /* Get Local TSF counter */ qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval); /* Set NextTBTT */ - VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, (u32)qwNextTBTT); - VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, (u32)(qwNextTBTT >> 32)); - MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); + VNSvOutPortD(iobase + MAC_REG_NEXTTBTT, (u32)qwNextTBTT); + VNSvOutPortD(iobase + MAC_REG_NEXTTBTT + 4, (u32)(qwNextTBTT >> 32)); + MACvRegBitsOn(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); } /* @@ -1024,12 +1024,12 @@ void CARDvSetFirstNextTBTT(struct vnt_private *priv, void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF, unsigned short wBeaconInterval) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; qwTSF = CARDqGetNextTBTT(qwTSF, wBeaconInterval); /* Set NextTBTT */ - VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, (u32)qwTSF); - VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, (u32)(qwTSF >> 32)); - MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); + VNSvOutPortD(iobase + MAC_REG_NEXTTBTT, (u32)qwTSF); + VNSvOutPortD(iobase + MAC_REG_NEXTTBTT + 4, (u32)(qwTSF >> 32)); + MACvRegBitsOn(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); pr_debug("Card:Update Next TBTT[%8llx]\n", qwTSF); } diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index d7faaf973c7d..33b758cb79d4 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -549,341 +549,341 @@ /*--------------------- Export Macros ------------------------------*/ -#define MACvRegBitsOn(dwIoBase, byRegOfs, byBits) \ +#define MACvRegBitsOn(iobase, byRegOfs, byBits) \ do { \ unsigned char byData; \ - VNSvInPortB(dwIoBase + byRegOfs, &byData); \ - VNSvOutPortB(dwIoBase + byRegOfs, byData | (byBits)); \ + VNSvInPortB(iobase + byRegOfs, &byData); \ + VNSvOutPortB(iobase + byRegOfs, byData | (byBits)); \ } while (0) -#define MACvWordRegBitsOn(dwIoBase, byRegOfs, wBits) \ +#define MACvWordRegBitsOn(iobase, byRegOfs, wBits) \ do { \ unsigned short wData; \ - VNSvInPortW(dwIoBase + byRegOfs, &wData); \ - VNSvOutPortW(dwIoBase + byRegOfs, wData | (wBits)); \ + VNSvInPortW(iobase + byRegOfs, &wData); \ + VNSvOutPortW(iobase + byRegOfs, wData | (wBits)); \ } while (0) -#define MACvDWordRegBitsOn(dwIoBase, byRegOfs, dwBits) \ +#define MACvDWordRegBitsOn(iobase, byRegOfs, dwBits) \ do { \ unsigned long dwData; \ - VNSvInPortD(dwIoBase + byRegOfs, &dwData); \ - VNSvOutPortD(dwIoBase + byRegOfs, dwData | (dwBits)); \ + VNSvInPortD(iobase + byRegOfs, &dwData); \ + VNSvOutPortD(iobase + byRegOfs, dwData | (dwBits)); \ } while (0) -#define MACvRegBitsOnEx(dwIoBase, byRegOfs, byMask, byBits) \ +#define MACvRegBitsOnEx(iobase, byRegOfs, byMask, byBits) \ do { \ unsigned char byData; \ - VNSvInPortB(dwIoBase + byRegOfs, &byData); \ + VNSvInPortB(iobase + byRegOfs, &byData); \ byData &= byMask; \ - VNSvOutPortB(dwIoBase + byRegOfs, byData | (byBits)); \ + VNSvOutPortB(iobase + byRegOfs, byData | (byBits)); \ } while (0) -#define MACvRegBitsOff(dwIoBase, byRegOfs, byBits) \ +#define MACvRegBitsOff(iobase, byRegOfs, byBits) \ do { \ unsigned char byData; \ - VNSvInPortB(dwIoBase + byRegOfs, &byData); \ - VNSvOutPortB(dwIoBase + byRegOfs, byData & ~(byBits)); \ + VNSvInPortB(iobase + byRegOfs, &byData); \ + VNSvOutPortB(iobase + byRegOfs, byData & ~(byBits)); \ } while (0) -#define MACvWordRegBitsOff(dwIoBase, byRegOfs, wBits) \ +#define MACvWordRegBitsOff(iobase, byRegOfs, wBits) \ do { \ unsigned short wData; \ - VNSvInPortW(dwIoBase + byRegOfs, &wData); \ - VNSvOutPortW(dwIoBase + byRegOfs, wData & ~(wBits)); \ + VNSvInPortW(iobase + byRegOfs, &wData); \ + VNSvOutPortW(iobase + byRegOfs, wData & ~(wBits)); \ } while (0) -#define MACvDWordRegBitsOff(dwIoBase, byRegOfs, dwBits) \ +#define MACvDWordRegBitsOff(iobase, byRegOfs, dwBits) \ do { \ unsigned long dwData; \ - VNSvInPortD(dwIoBase + byRegOfs, &dwData); \ - VNSvOutPortD(dwIoBase + byRegOfs, dwData & ~(dwBits)); \ + VNSvInPortD(iobase + byRegOfs, &dwData); \ + VNSvOutPortD(iobase + byRegOfs, dwData & ~(dwBits)); \ } while (0) -#define MACvGetCurrRx0DescAddr(dwIoBase, pdwCurrDescAddr) \ - VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0, \ +#define MACvGetCurrRx0DescAddr(iobase, pdwCurrDescAddr) \ + VNSvInPortD(iobase + MAC_REG_RXDMAPTR0, \ (unsigned long *)pdwCurrDescAddr) -#define MACvGetCurrRx1DescAddr(dwIoBase, pdwCurrDescAddr) \ - VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1, \ +#define MACvGetCurrRx1DescAddr(iobase, pdwCurrDescAddr) \ + VNSvInPortD(iobase + MAC_REG_RXDMAPTR1, \ (unsigned long *)pdwCurrDescAddr) -#define MACvGetCurrTx0DescAddr(dwIoBase, pdwCurrDescAddr) \ - VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0, \ +#define MACvGetCurrTx0DescAddr(iobase, pdwCurrDescAddr) \ + VNSvInPortD(iobase + MAC_REG_TXDMAPTR0, \ (unsigned long *)pdwCurrDescAddr) -#define MACvGetCurrAC0DescAddr(dwIoBase, pdwCurrDescAddr) \ - VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR, \ +#define MACvGetCurrAC0DescAddr(iobase, pdwCurrDescAddr) \ + VNSvInPortD(iobase + MAC_REG_AC0DMAPTR, \ (unsigned long *)pdwCurrDescAddr) -#define MACvGetCurrSyncDescAddr(dwIoBase, pdwCurrDescAddr) \ - VNSvInPortD(dwIoBase + MAC_REG_SYNCDMAPTR, \ +#define MACvGetCurrSyncDescAddr(iobase, pdwCurrDescAddr) \ + VNSvInPortD(iobase + MAC_REG_SYNCDMAPTR, \ (unsigned long *)pdwCurrDescAddr) -#define MACvGetCurrATIMDescAddr(dwIoBase, pdwCurrDescAddr) \ - VNSvInPortD(dwIoBase + MAC_REG_ATIMDMAPTR, \ +#define MACvGetCurrATIMDescAddr(iobase, pdwCurrDescAddr) \ + VNSvInPortD(iobase + MAC_REG_ATIMDMAPTR, \ (unsigned long *)pdwCurrDescAddr) /* set the chip with current BCN tx descriptor address */ -#define MACvSetCurrBCNTxDescAddr(dwIoBase, dwCurrDescAddr) \ - VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, \ +#define MACvSetCurrBCNTxDescAddr(iobase, dwCurrDescAddr) \ + VNSvOutPortD(iobase + MAC_REG_BCNDMAPTR, \ dwCurrDescAddr) /* set the chip with current BCN length */ -#define MACvSetCurrBCNLength(dwIoBase, wCurrBCNLength) \ - VNSvOutPortW(dwIoBase + MAC_REG_BCNDMACTL+2, \ +#define MACvSetCurrBCNLength(iobase, wCurrBCNLength) \ + VNSvOutPortW(iobase + MAC_REG_BCNDMACTL+2, \ wCurrBCNLength) -#define MACvReadBSSIDAddress(dwIoBase, pbyEtherAddr) \ +#define MACvReadBSSIDAddress(iobase, pbyEtherAddr) \ do { \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ - VNSvInPortB(dwIoBase + MAC_REG_BSSID0, \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 1); \ + VNSvInPortB(iobase + MAC_REG_BSSID0, \ (unsigned char *)pbyEtherAddr); \ - VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 1, \ + VNSvInPortB(iobase + MAC_REG_BSSID0 + 1, \ pbyEtherAddr + 1); \ - VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 2, \ + VNSvInPortB(iobase + MAC_REG_BSSID0 + 2, \ pbyEtherAddr + 2); \ - VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 3, \ + VNSvInPortB(iobase + MAC_REG_BSSID0 + 3, \ pbyEtherAddr + 3); \ - VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 4, \ + VNSvInPortB(iobase + MAC_REG_BSSID0 + 4, \ pbyEtherAddr + 4); \ - VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 5, \ + VNSvInPortB(iobase + MAC_REG_BSSID0 + 5, \ pbyEtherAddr + 5); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 0); \ } while (0) -#define MACvWriteBSSIDAddress(dwIoBase, pbyEtherAddr) \ +#define MACvWriteBSSIDAddress(iobase, pbyEtherAddr) \ do { \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ - VNSvOutPortB(dwIoBase + MAC_REG_BSSID0, \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 1); \ + VNSvOutPortB(iobase + MAC_REG_BSSID0, \ *(pbyEtherAddr)); \ - VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 1, \ + VNSvOutPortB(iobase + MAC_REG_BSSID0 + 1, \ *(pbyEtherAddr + 1)); \ - VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 2, \ + VNSvOutPortB(iobase + MAC_REG_BSSID0 + 2, \ *(pbyEtherAddr + 2)); \ - VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 3, \ + VNSvOutPortB(iobase + MAC_REG_BSSID0 + 3, \ *(pbyEtherAddr + 3)); \ - VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 4, \ + VNSvOutPortB(iobase + MAC_REG_BSSID0 + 4, \ *(pbyEtherAddr + 4)); \ - VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 5, \ + VNSvOutPortB(iobase + MAC_REG_BSSID0 + 5, \ *(pbyEtherAddr + 5)); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 0); \ } while (0) -#define MACvReadEtherAddress(dwIoBase, pbyEtherAddr) \ +#define MACvReadEtherAddress(iobase, pbyEtherAddr) \ do { \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ - VNSvInPortB(dwIoBase + MAC_REG_PAR0, \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 1); \ + VNSvInPortB(iobase + MAC_REG_PAR0, \ (unsigned char *)pbyEtherAddr); \ - VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 1, \ + VNSvInPortB(iobase + MAC_REG_PAR0 + 1, \ pbyEtherAddr + 1); \ - VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 2, \ + VNSvInPortB(iobase + MAC_REG_PAR0 + 2, \ pbyEtherAddr + 2); \ - VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 3, \ + VNSvInPortB(iobase + MAC_REG_PAR0 + 3, \ pbyEtherAddr + 3); \ - VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 4, \ + VNSvInPortB(iobase + MAC_REG_PAR0 + 4, \ pbyEtherAddr + 4); \ - VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 5, \ + VNSvInPortB(iobase + MAC_REG_PAR0 + 5, \ pbyEtherAddr + 5); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 0); \ } while (0) -#define MACvWriteEtherAddress(dwIoBase, pbyEtherAddr) \ +#define MACvWriteEtherAddress(iobase, pbyEtherAddr) \ do { \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAR0, \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 1); \ + VNSvOutPortB(iobase + MAC_REG_PAR0, \ *pbyEtherAddr); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 1, \ + VNSvOutPortB(iobase + MAC_REG_PAR0 + 1, \ *(pbyEtherAddr + 1)); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 2, \ + VNSvOutPortB(iobase + MAC_REG_PAR0 + 2, \ *(pbyEtherAddr + 2)); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 3, \ + VNSvOutPortB(iobase + MAC_REG_PAR0 + 3, \ *(pbyEtherAddr + 3)); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 4, \ + VNSvOutPortB(iobase + MAC_REG_PAR0 + 4, \ *(pbyEtherAddr + 4)); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 5, \ + VNSvOutPortB(iobase + MAC_REG_PAR0 + 5, \ *(pbyEtherAddr + 5)); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 0); \ } while (0) -#define MACvClearISR(dwIoBase) \ - VNSvOutPortD(dwIoBase + MAC_REG_ISR, IMR_MASK_VALUE) +#define MACvClearISR(iobase) \ + VNSvOutPortD(iobase + MAC_REG_ISR, IMR_MASK_VALUE) -#define MACvStart(dwIoBase) \ - VNSvOutPortB(dwIoBase + MAC_REG_HOSTCR, \ +#define MACvStart(iobase) \ + VNSvOutPortB(iobase + MAC_REG_HOSTCR, \ (HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON)) -#define MACvRx0PerPktMode(dwIoBase) \ - VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, RX_PERPKT) +#define MACvRx0PerPktMode(iobase) \ + VNSvOutPortD(iobase + MAC_REG_RXDMACTL0, RX_PERPKT) -#define MACvRx0BufferFillMode(dwIoBase) \ - VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, RX_PERPKTCLR) +#define MACvRx0BufferFillMode(iobase) \ + VNSvOutPortD(iobase + MAC_REG_RXDMACTL0, RX_PERPKTCLR) -#define MACvRx1PerPktMode(dwIoBase) \ - VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, RX_PERPKT) +#define MACvRx1PerPktMode(iobase) \ + VNSvOutPortD(iobase + MAC_REG_RXDMACTL1, RX_PERPKT) -#define MACvRx1BufferFillMode(dwIoBase) \ - VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, RX_PERPKTCLR) +#define MACvRx1BufferFillMode(iobase) \ + VNSvOutPortD(iobase + MAC_REG_RXDMACTL1, RX_PERPKTCLR) -#define MACvRxOn(dwIoBase) \ - MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_RXON) +#define MACvRxOn(iobase) \ + MACvRegBitsOn(iobase, MAC_REG_HOSTCR, HOSTCR_RXON) -#define MACvReceive0(dwIoBase) \ +#define MACvReceive0(iobase) \ do { \ unsigned long dwData; \ - VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL0, &dwData); \ + VNSvInPortD(iobase + MAC_REG_RXDMACTL0, &dwData); \ if (dwData & DMACTL_RUN) \ - VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_WAKE); \ + VNSvOutPortD(iobase + MAC_REG_RXDMACTL0, DMACTL_WAKE); \ else \ - VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN); \ + VNSvOutPortD(iobase + MAC_REG_RXDMACTL0, DMACTL_RUN); \ } while (0) -#define MACvReceive1(dwIoBase) \ +#define MACvReceive1(iobase) \ do { \ unsigned long dwData; \ - VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL1, &dwData); \ + VNSvInPortD(iobase + MAC_REG_RXDMACTL1, &dwData); \ if (dwData & DMACTL_RUN) \ - VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_WAKE); \ + VNSvOutPortD(iobase + MAC_REG_RXDMACTL1, DMACTL_WAKE); \ else \ - VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_RUN); \ + VNSvOutPortD(iobase + MAC_REG_RXDMACTL1, DMACTL_RUN); \ } while (0) -#define MACvTxOn(dwIoBase) \ - MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_TXON) +#define MACvTxOn(iobase) \ + MACvRegBitsOn(iobase, MAC_REG_HOSTCR, HOSTCR_TXON) -#define MACvTransmit0(dwIoBase) \ +#define MACvTransmit0(iobase) \ do { \ unsigned long dwData; \ - VNSvInPortD(dwIoBase + MAC_REG_TXDMACTL0, &dwData); \ + VNSvInPortD(iobase + MAC_REG_TXDMACTL0, &dwData); \ if (dwData & DMACTL_RUN) \ - VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_WAKE); \ + VNSvOutPortD(iobase + MAC_REG_TXDMACTL0, DMACTL_WAKE); \ else \ - VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_RUN); \ + VNSvOutPortD(iobase + MAC_REG_TXDMACTL0, DMACTL_RUN); \ } while (0) -#define MACvTransmitAC0(dwIoBase) \ +#define MACvTransmitAC0(iobase) \ do { \ unsigned long dwData; \ - VNSvInPortD(dwIoBase + MAC_REG_AC0DMACTL, &dwData); \ + VNSvInPortD(iobase + MAC_REG_AC0DMACTL, &dwData); \ if (dwData & DMACTL_RUN) \ - VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_WAKE); \ + VNSvOutPortD(iobase + MAC_REG_AC0DMACTL, DMACTL_WAKE); \ else \ - VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN); \ + VNSvOutPortD(iobase + MAC_REG_AC0DMACTL, DMACTL_RUN); \ } while (0) -#define MACvTransmitSYNC(dwIoBase) \ +#define MACvTransmitSYNC(iobase) \ do { \ unsigned long dwData; \ - VNSvInPortD(dwIoBase + MAC_REG_SYNCDMACTL, &dwData); \ + VNSvInPortD(iobase + MAC_REG_SYNCDMACTL, &dwData); \ if (dwData & DMACTL_RUN) \ - VNSvOutPortD(dwIoBase + MAC_REG_SYNCDMACTL, DMACTL_WAKE); \ + VNSvOutPortD(iobase + MAC_REG_SYNCDMACTL, DMACTL_WAKE); \ else \ - VNSvOutPortD(dwIoBase + MAC_REG_SYNCDMACTL, DMACTL_RUN); \ + VNSvOutPortD(iobase + MAC_REG_SYNCDMACTL, DMACTL_RUN); \ } while (0) -#define MACvTransmitATIM(dwIoBase) \ +#define MACvTransmitATIM(iobase) \ do { \ unsigned long dwData; \ - VNSvInPortD(dwIoBase + MAC_REG_ATIMDMACTL, &dwData); \ + VNSvInPortD(iobase + MAC_REG_ATIMDMACTL, &dwData); \ if (dwData & DMACTL_RUN) \ - VNSvOutPortD(dwIoBase + MAC_REG_ATIMDMACTL, DMACTL_WAKE); \ + VNSvOutPortD(iobase + MAC_REG_ATIMDMACTL, DMACTL_WAKE); \ else \ - VNSvOutPortD(dwIoBase + MAC_REG_ATIMDMACTL, DMACTL_RUN); \ + VNSvOutPortD(iobase + MAC_REG_ATIMDMACTL, DMACTL_RUN); \ } while (0) -#define MACvTransmitBCN(dwIoBase) \ - VNSvOutPortB(dwIoBase + MAC_REG_BCNDMACTL, BEACON_READY) +#define MACvTransmitBCN(iobase) \ + VNSvOutPortB(iobase + MAC_REG_BCNDMACTL, BEACON_READY) -#define MACvClearStckDS(dwIoBase) \ +#define MACvClearStckDS(iobase) \ do { \ unsigned char byOrgValue; \ - VNSvInPortB(dwIoBase + MAC_REG_STICKHW, &byOrgValue); \ + VNSvInPortB(iobase + MAC_REG_STICKHW, &byOrgValue); \ byOrgValue = byOrgValue & 0xFC; \ - VNSvOutPortB(dwIoBase + MAC_REG_STICKHW, byOrgValue); \ + VNSvOutPortB(iobase + MAC_REG_STICKHW, byOrgValue); \ } while (0) -#define MACvReadISR(dwIoBase, pdwValue) \ - VNSvInPortD(dwIoBase + MAC_REG_ISR, pdwValue) +#define MACvReadISR(iobase, pdwValue) \ + VNSvInPortD(iobase + MAC_REG_ISR, pdwValue) -#define MACvWriteISR(dwIoBase, dwValue) \ - VNSvOutPortD(dwIoBase + MAC_REG_ISR, dwValue) +#define MACvWriteISR(iobase, dwValue) \ + VNSvOutPortD(iobase + MAC_REG_ISR, dwValue) -#define MACvIntEnable(dwIoBase, dwMask) \ - VNSvOutPortD(dwIoBase + MAC_REG_IMR, dwMask) +#define MACvIntEnable(iobase, dwMask) \ + VNSvOutPortD(iobase + MAC_REG_IMR, dwMask) -#define MACvIntDisable(dwIoBase) \ - VNSvOutPortD(dwIoBase + MAC_REG_IMR, 0) +#define MACvIntDisable(iobase) \ + VNSvOutPortD(iobase + MAC_REG_IMR, 0) -#define MACvSelectPage0(dwIoBase) \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0) +#define MACvSelectPage0(iobase) \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 0) -#define MACvSelectPage1(dwIoBase) \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1) +#define MACvSelectPage1(iobase) \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 1) -#define MACvReadMIBCounter(dwIoBase, pdwCounter) \ - VNSvInPortD(dwIoBase + MAC_REG_MIBCNTR, pdwCounter) +#define MACvReadMIBCounter(iobase, pdwCounter) \ + VNSvInPortD(iobase + MAC_REG_MIBCNTR, pdwCounter) -#define MACvPwrEvntDisable(dwIoBase) \ - VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPEN0, 0x0000) +#define MACvPwrEvntDisable(iobase) \ + VNSvOutPortW(iobase + MAC_REG_WAKEUPEN0, 0x0000) -#define MACvEnableProtectMD(dwIoBase) \ +#define MACvEnableProtectMD(iobase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ + VNSvInPortD(iobase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue | EnCFG_ProtectMd; \ - VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ + VNSvOutPortD(iobase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) -#define MACvDisableProtectMD(dwIoBase) \ +#define MACvDisableProtectMD(iobase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ + VNSvInPortD(iobase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_ProtectMd; \ - VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ + VNSvOutPortD(iobase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) -#define MACvEnableBarkerPreambleMd(dwIoBase) \ +#define MACvEnableBarkerPreambleMd(iobase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ + VNSvInPortD(iobase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue | EnCFG_BarkerPream; \ - VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ + VNSvOutPortD(iobase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) -#define MACvDisableBarkerPreambleMd(dwIoBase) \ +#define MACvDisableBarkerPreambleMd(iobase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ + VNSvInPortD(iobase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_BarkerPream; \ - VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ + VNSvOutPortD(iobase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) -#define MACvSetBBType(dwIoBase, byTyp) \ +#define MACvSetBBType(iobase, byTyp) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ + VNSvInPortD(iobase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_BBType_MASK; \ dwOrgValue = dwOrgValue | (unsigned long)byTyp; \ - VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ + VNSvOutPortD(iobase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) -#define MACvReadATIMW(dwIoBase, pwCounter) \ - VNSvInPortW(dwIoBase + MAC_REG_AIDATIM, pwCounter) +#define MACvReadATIMW(iobase, pwCounter) \ + VNSvInPortW(iobase + MAC_REG_AIDATIM, pwCounter) -#define MACvWriteATIMW(dwIoBase, wCounter) \ - VNSvOutPortW(dwIoBase + MAC_REG_AIDATIM, wCounter) +#define MACvWriteATIMW(iobase, wCounter) \ + VNSvOutPortW(iobase + MAC_REG_AIDATIM, wCounter) -#define MACvWriteCRC16_128(dwIoBase, byRegOfs, wCRC) \ +#define MACvWriteCRC16_128(iobase, byRegOfs, wCRC) \ do { \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ - VNSvOutPortW(dwIoBase + byRegOfs, wCRC); \ - VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 1); \ + VNSvOutPortW(iobase + byRegOfs, wCRC); \ + VNSvOutPortB(iobase + MAC_REG_PAGE1SEL, 0); \ } while (0) -#define MACvGPIOIn(dwIoBase, pbyValue) \ - VNSvInPortB(dwIoBase + MAC_REG_GPIOCTL1, pbyValue) +#define MACvGPIOIn(iobase, pbyValue) \ + VNSvInPortB(iobase + MAC_REG_GPIOCTL1, pbyValue) -#define MACvSetRFLE_LatchBase(dwIoBase) \ - MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT) +#define MACvSetRFLE_LatchBase(iobase) \ + MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT) bool MACbIsRegBitsOn(struct vnt_private *, unsigned char byRegOfs, unsigned char byTestBits); diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 1762c05f2a3e..431a5d45bc53 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -405,7 +405,7 @@ static const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = { * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * Out: * none * @@ -414,16 +414,16 @@ static const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = { */ static bool s_bAL7230Init(struct vnt_private *priv) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; int ii; bool ret; ret = true; /* 3-wire control for normal mode */ - VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0); + VNSvOutPortB(iobase + MAC_REG_SOFTPWRCTL, 0); - MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI | + MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI | SOFTPWRCTL_TXPEINV)); BBvPowerSaveModeOFF(priv); /* RobertYu:20050106, have DC value for Calibration */ @@ -431,7 +431,7 @@ static bool s_bAL7230Init(struct vnt_private *priv) ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[ii]); /* PLL On */ - MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); /* Calibration */ MACvTimer0MicroSDelay(priv, 150);/* 150us */ @@ -444,7 +444,7 @@ static bool s_bAL7230Init(struct vnt_private *priv) /* TXDCOC:disable, RCK:disable */ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); - MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | + MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPECTI | SOFTPWRCTL_TXPEINV)); @@ -453,7 +453,7 @@ static bool s_bAL7230Init(struct vnt_private *priv) /* PE1: TX_ON, PE2: RX_ON, PE3: PLLON */ /* 3-wire control for power saving mode */ - VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */ + VNSvOutPortB(iobase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */ return ret; } @@ -463,26 +463,26 @@ static bool s_bAL7230Init(struct vnt_private *priv) */ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byChannel) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; bool ret; ret = true; /* PLLON Off */ - MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + MACvWordRegBitsOff(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable0[byChannel - 1]); ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable1[byChannel - 1]); ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable2[byChannel - 1]); /* PLLOn On */ - MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); /* Set Channel[7] = 0 to tell H/W channel is changing now. */ - VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); + VNSvOutPortB(iobase + MAC_REG_CHANNEL, (byChannel & 0x7F)); MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL7230); /* Set Channel[7] = 1 to tell H/W channel change is done. */ - VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); + VNSvOutPortB(iobase + MAC_REG_CHANNEL, (byChannel | 0x80)); return ret; } @@ -492,7 +492,7 @@ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byCha * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * dwData - data to write * Out: * none @@ -502,15 +502,15 @@ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byCha */ bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; unsigned short ww; unsigned long dwValue; - VNSvOutPortD(dwIoBase + MAC_REG_IFREGCTL, dwData); + VNSvOutPortD(iobase + MAC_REG_IFREGCTL, dwData); /* W_MAX_TIMEOUT is the timeout period */ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - VNSvInPortD(dwIoBase + MAC_REG_IFREGCTL, &dwValue); + VNSvInPortD(iobase + MAC_REG_IFREGCTL, &dwValue); if (dwValue & IFREGCTL_DONE) break; } @@ -526,7 +526,7 @@ bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData) * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * Out: * none * @@ -535,19 +535,19 @@ bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData) */ static bool RFbAL2230Init(struct vnt_private *priv) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; int ii; bool ret; ret = true; /* 3-wire control for normal mode */ - VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0); + VNSvOutPortB(iobase + MAC_REG_SOFTPWRCTL, 0); - MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI | + MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI | SOFTPWRCTL_TXPEINV)); /* PLL Off */ - MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + MACvWordRegBitsOff(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); /* patch abnormal AL2230 frequency output */ IFRFbWriteEmbedded(priv, (0x07168700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); @@ -557,7 +557,7 @@ static bool RFbAL2230Init(struct vnt_private *priv) MACvTimer0MicroSDelay(priv, 30); /* delay 30 us */ /* PLL On */ - MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); MACvTimer0MicroSDelay(priv, 150);/* 150us */ ret &= IFRFbWriteEmbedded(priv, (0x00d80f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); @@ -566,20 +566,20 @@ static bool RFbAL2230Init(struct vnt_private *priv) MACvTimer0MicroSDelay(priv, 30);/* 30us */ ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); - MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | + MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPECTI | SOFTPWRCTL_TXPEINV)); /* 3-wire control for power saving mode */ - VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */ + VNSvOutPortB(iobase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */ return ret; } static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byChannel) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; bool ret; ret = true; @@ -588,10 +588,10 @@ static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byCha ret &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable1[byChannel - 1]); /* Set Channel[7] = 0 to tell H/W channel is changing now. */ - VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); + VNSvOutPortB(iobase + MAC_REG_CHANNEL, (byChannel & 0x7F)); MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL2230); /* Set Channel[7] = 1 to tell H/W channel change is done. */ - VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); + VNSvOutPortB(iobase + MAC_REG_CHANNEL, (byChannel | 0x80)); return ret; } @@ -676,7 +676,7 @@ bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * uChannel - channel number * bySleepCnt - SleepProgSyn count * @@ -686,12 +686,12 @@ bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, u16 uChannel) { - void __iomem *dwIoBase = priv->PortOffset; + void __iomem *iobase = priv->PortOffset; int ii; unsigned char byInitCount = 0; unsigned char bySleepCount = 0; - VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, 0); + VNSvOutPortW(iobase + MAC_REG_MISCFFNDEX, 0); switch (byRFType) { case RF_AIROHA: case RF_AL2230S: @@ -753,7 +753,7 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * dwRFPowerTable - RF Tx Power Setting * Out: * none @@ -825,7 +825,7 @@ bool RFbSetPower( * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * dwRFPowerTable - RF Tx Power Setting * Out: * none diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c index e6d1280a4737..635f271595f6 100644 --- a/drivers/staging/vt6655/srom.c +++ b/drivers/staging/vt6655/srom.c @@ -60,7 +60,7 @@ * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * byContntOffset - address of EEPROM * Out: * none @@ -68,7 +68,7 @@ * Return Value: data read * */ -unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, +unsigned char SROMbyReadEmbedded(void __iomem *iobase, unsigned char byContntOffset) { unsigned short wDelay, wNoACK; @@ -77,18 +77,18 @@ unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, unsigned char byOrg; byData = 0xFF; - VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg); + VNSvInPortB(iobase + MAC_REG_I2MCFG, &byOrg); /* turn off hardware retry for getting NACK */ - VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg & (~I2MCFG_NORETRY))); + VNSvOutPortB(iobase + MAC_REG_I2MCFG, (byOrg & (~I2MCFG_NORETRY))); for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) { - VNSvOutPortB(dwIoBase + MAC_REG_I2MTGID, EEP_I2C_DEV_ID); - VNSvOutPortB(dwIoBase + MAC_REG_I2MTGAD, byContntOffset); + VNSvOutPortB(iobase + MAC_REG_I2MTGID, EEP_I2C_DEV_ID); + VNSvOutPortB(iobase + MAC_REG_I2MTGAD, byContntOffset); /* issue read command */ - VNSvOutPortB(dwIoBase + MAC_REG_I2MCSR, I2MCSR_EEMR); + VNSvOutPortB(iobase + MAC_REG_I2MCSR, I2MCSR_EEMR); /* wait DONE be set */ for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) { - VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait); + VNSvInPortB(iobase + MAC_REG_I2MCSR, &byWait); if (byWait & (I2MCSR_DONE | I2MCSR_NACK)) break; PCAvDelayByIO(CB_DELAY_LOOP_WAIT); @@ -98,8 +98,8 @@ unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, break; } } - VNSvInPortB(dwIoBase + MAC_REG_I2MDIPT, &byData); - VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg); + VNSvInPortB(iobase + MAC_REG_I2MDIPT, &byData); + VNSvOutPortB(iobase + MAC_REG_I2MCFG, byOrg); return byData; } @@ -108,20 +108,20 @@ unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * Out: * pbyEepromRegs - EEPROM content Buffer * * Return Value: none * */ -void SROMvReadAllContents(void __iomem *dwIoBase, unsigned char *pbyEepromRegs) +void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs) { int ii; /* ii = Rom Address */ for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) { - *pbyEepromRegs = SROMbyReadEmbedded(dwIoBase, + *pbyEepromRegs = SROMbyReadEmbedded(iobase, (unsigned char)ii); pbyEepromRegs++; } @@ -132,21 +132,21 @@ void SROMvReadAllContents(void __iomem *dwIoBase, unsigned char *pbyEepromRegs) * * Parameters: * In: - * dwIoBase - I/O base address + * iobase - I/O base address * Out: * pbyEtherAddress - Ethernet Address buffer * * Return Value: none * */ -void SROMvReadEtherAddress(void __iomem *dwIoBase, +void SROMvReadEtherAddress(void __iomem *iobase, unsigned char *pbyEtherAddress) { unsigned char ii; /* ii = Rom Address */ for (ii = 0; ii < ETH_ALEN; ii++) { - *pbyEtherAddress = SROMbyReadEmbedded(dwIoBase, ii); + *pbyEtherAddress = SROMbyReadEmbedded(iobase, ii); pbyEtherAddress++; } } diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h index b3215a24ac51..6e03ab6dfa9d 100644 --- a/drivers/staging/vt6655/srom.h +++ b/drivers/staging/vt6655/srom.h @@ -85,12 +85,12 @@ /*--------------------- Export Functions --------------------------*/ -unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, +unsigned char SROMbyReadEmbedded(void __iomem *iobase, unsigned char byContntOffset); -void SROMvReadAllContents(void __iomem *dwIoBase, unsigned char *pbyEepromRegs); +void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs); -void SROMvReadEtherAddress(void __iomem *dwIoBase, +void SROMvReadEtherAddress(void __iomem *iobase, unsigned char *pbyEtherAddress); #endif /* __EEPROM_H__*/ -- cgit v1.2.3 From 761d0efee839cf8cf0710f61f43f77026e5a77d8 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 5 Oct 2016 09:33:27 +0200 Subject: firmware: arm_scpi: add command indirection to support legacy commands Since the legacy SCPI and the SCPI v1.0 differ in the command values, it's better to create some sort of command indirection in the driver to avoid repeated version check at multiple places. This patch adds the indirection command table to allow different values of the command across SCPI versions. [narmstrong@baylibre.com: added cmd check in scpi_send_message] Signed-off-by: Neil Armstrong Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 71 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index ce2bc2a38101..9e9b022450eb 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -99,6 +99,7 @@ enum scpi_error_codes { SCPI_ERR_MAX }; +/* SCPI Standard commands */ enum scpi_std_cmd { SCPI_CMD_INVALID = 0x00, SCPI_CMD_SCPI_READY = 0x01, @@ -132,6 +133,38 @@ enum scpi_std_cmd { SCPI_CMD_COUNT }; +/* List of all commands used by this driver, used as indices */ +enum scpi_drv_cmds { + CMD_SCPI_CAPABILITIES = 0, + CMD_GET_CLOCK_INFO, + CMD_GET_CLOCK_VALUE, + CMD_SET_CLOCK_VALUE, + CMD_GET_DVFS, + CMD_SET_DVFS, + CMD_GET_DVFS_INFO, + CMD_SENSOR_CAPABILITIES, + CMD_SENSOR_INFO, + CMD_SENSOR_VALUE, + CMD_SET_DEVICE_PWR_STATE, + CMD_GET_DEVICE_PWR_STATE, + CMD_MAX_COUNT, +}; + +static int scpi_std_commands[CMD_MAX_COUNT] = { + SCPI_CMD_SCPI_CAPABILITIES, + SCPI_CMD_GET_CLOCK_INFO, + SCPI_CMD_GET_CLOCK_VALUE, + SCPI_CMD_SET_CLOCK_VALUE, + SCPI_CMD_GET_DVFS, + SCPI_CMD_SET_DVFS, + SCPI_CMD_GET_DVFS_INFO, + SCPI_CMD_SENSOR_CAPABILITIES, + SCPI_CMD_SENSOR_INFO, + SCPI_CMD_SENSOR_VALUE, + SCPI_CMD_SET_DEVICE_PWR_STATE, + SCPI_CMD_GET_DEVICE_PWR_STATE, +}; + struct scpi_xfer { u32 slot; /* has to be first element */ u32 cmd; @@ -161,6 +194,7 @@ struct scpi_drvinfo { u32 protocol_version; u32 firmware_version; int num_chans; + int *commands; atomic_t next_chan; struct scpi_ops *scpi_ops; struct scpi_chan *channels; @@ -344,14 +378,20 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch) mutex_unlock(&ch->xfers_lock); } -static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len, +static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len, void *rx_buf, unsigned int rx_len) { int ret; u8 chan; + u8 cmd; struct scpi_xfer *msg; struct scpi_chan *scpi_chan; + if (scpi_info->commands[idx] < 0) + return -EOPNOTSUPP; + + cmd = scpi_info->commands[idx]; + chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans; scpi_chan = scpi_info->channels + chan; @@ -397,7 +437,7 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max) struct clk_get_info clk; __le16 le_clk_id = cpu_to_le16(clk_id); - ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id, + ret = scpi_send_message(CMD_GET_CLOCK_INFO, &le_clk_id, sizeof(le_clk_id), &clk, sizeof(clk)); if (!ret) { *min = le32_to_cpu(clk.min_rate); @@ -412,8 +452,9 @@ static unsigned long scpi_clk_get_val(u16 clk_id) struct clk_get_value clk; __le16 le_clk_id = cpu_to_le16(clk_id); - ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id, + ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id, sizeof(le_clk_id), &clk, sizeof(clk)); + return ret ? ret : le32_to_cpu(clk.rate); } @@ -425,7 +466,7 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate) .rate = cpu_to_le32(rate) }; - return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk), + return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk), &stat, sizeof(stat)); } @@ -434,8 +475,9 @@ static int scpi_dvfs_get_idx(u8 domain) int ret; u8 dvfs_idx; - ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain), + ret = scpi_send_message(CMD_GET_DVFS, &domain, sizeof(domain), &dvfs_idx, sizeof(dvfs_idx)); + return ret ? ret : dvfs_idx; } @@ -444,7 +486,7 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index) int stat; struct dvfs_set dvfs = {domain, index}; - return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs), + return scpi_send_message(CMD_SET_DVFS, &dvfs, sizeof(dvfs), &stat, sizeof(stat)); } @@ -468,9 +510,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain) if (scpi_info->dvfs[domain]) /* data already populated */ return scpi_info->dvfs[domain]; - ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain), + ret = scpi_send_message(CMD_GET_DVFS_INFO, &domain, sizeof(domain), &buf, sizeof(buf)); - if (ret) return ERR_PTR(ret); @@ -503,7 +544,7 @@ static int scpi_sensor_get_capability(u16 *sensors) struct sensor_capabilities cap_buf; int ret; - ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf, + ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf, sizeof(cap_buf)); if (!ret) *sensors = le16_to_cpu(cap_buf.sensors); @@ -517,7 +558,7 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info) struct _scpi_sensor_info _info; int ret; - ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id), + ret = scpi_send_message(CMD_SENSOR_INFO, &id, sizeof(id), &_info, sizeof(_info)); if (!ret) { memcpy(info, &_info, sizeof(*info)); @@ -533,7 +574,7 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val) struct sensor_value buf; int ret; - ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id), + ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id), &buf, sizeof(buf)); if (!ret) *val = (u64)le32_to_cpu(buf.hi_val) << 32 | @@ -548,7 +589,7 @@ static int scpi_device_get_power_state(u16 dev_id) u8 pstate; __le16 id = cpu_to_le16(dev_id); - ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id, + ret = scpi_send_message(CMD_GET_DEVICE_PWR_STATE, &id, sizeof(id), &pstate, sizeof(pstate)); return ret ? ret : pstate; } @@ -561,7 +602,7 @@ static int scpi_device_set_power_state(u16 dev_id, u8 pstate) .pstate = pstate, }; - return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set, + return scpi_send_message(CMD_SET_DEVICE_PWR_STATE, &dev_set, sizeof(dev_set), &stat, sizeof(stat)); } @@ -591,7 +632,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info) int ret; struct scp_capabilities caps; - ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0, + ret = scpi_send_message(CMD_SCPI_CAPABILITIES, NULL, 0, &caps, sizeof(caps)); if (!ret) { info->protocol_version = le32_to_cpu(caps.protocol_version); @@ -755,6 +796,8 @@ err: scpi_info->channels = scpi_chan; scpi_info->num_chans = count; + scpi_info->commands = scpi_std_commands; + platform_set_drvdata(pdev, scpi_info); ret = scpi_init_versions(scpi_info); -- cgit v1.2.3 From 862372bc8fefb7bdc243dd120448b970244c8185 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 12 Oct 2016 14:44:47 +0300 Subject: drm/i915: GMBUS don't need no forcewake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GMBUS is part of the display engine, and thus has no need for forcewake. Let's not bother trying to grab it then. I don't recall if the display engine suffers from system hangs due to multiple accesses to the same "cacheline" in mmio space. I hope not since we're no longer protected by the uncore lock since commit 4e6c2d58ba86 ("drm/i915: Take forcewake once for the entire GMBUS transaction") Cc: Chris Wilson Cc: David Weinehall Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1476272687-15070-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_i2c.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index d04185e1edd6..83f260bb4eef 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -467,13 +467,9 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) struct intel_gmbus, adapter); struct drm_i915_private *dev_priv = bus->dev_priv; - const unsigned int fw = - intel_uncore_forcewake_for_reg(dev_priv, GMBUS0, - FW_REG_READ | FW_REG_WRITE); int i = 0, inc, try = 0; int ret = 0; - intel_uncore_forcewake_get(dev_priv, fw); retry: I915_WRITE_FW(GMBUS0, bus->reg0); @@ -575,7 +571,6 @@ timeout: ret = -EAGAIN; out: - intel_uncore_forcewake_put(dev_priv, fw); return ret; } -- cgit v1.2.3 From 65f2130cbdebe921a6ed1c82b81e3c366a5eca8b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 14 Oct 2016 20:02:53 +0300 Subject: drm/i915: Extract intel_crtc_pch_transcoder() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the code to determine which PCH transcoder we're using to a small helper. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1476464574-32230-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 21 ++++++++++++++------- drivers/gpu/drm/i915/intel_drv.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bdc898ef5b64..9395878abc56 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1926,6 +1926,18 @@ void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) I915_WRITE(TRANS_CHICKEN2(PIPE_A), val); } +enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + WARN_ON(!crtc->config->has_pch_encoder); + + if (HAS_PCH_LPT(dev_priv)) + return TRANSCODER_A; + else + return (enum transcoder) crtc->pipe; +} + /** * intel_enable_pipe - enable a pipe, asserting requirements * @crtc: crtc responsible for the pipe @@ -1939,7 +1951,6 @@ static void intel_enable_pipe(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = to_i915(dev); enum pipe pipe = crtc->pipe; enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; - enum pipe pch_transcoder; i915_reg_t reg; u32 val; @@ -1949,11 +1960,6 @@ static void intel_enable_pipe(struct intel_crtc *crtc) assert_cursor_disabled(dev_priv, pipe); assert_sprites_disabled(dev_priv, pipe); - if (HAS_PCH_LPT(dev_priv)) - pch_transcoder = TRANSCODER_A; - else - pch_transcoder = pipe; - /* * A pipe without a PLL won't actually be able to drive bits from * a plane. On ILK+ the pipe PLLs are integrated, so we don't @@ -1967,7 +1973,8 @@ static void intel_enable_pipe(struct intel_crtc *crtc) } else { if (crtc->config->has_pch_encoder) { /* if driving the PCH, we need FDI enabled */ - assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder); + assert_fdi_rx_pll_enabled(dev_priv, + (enum pipe) intel_crtc_pch_transcoder(crtc)); assert_fdi_tx_pll_enabled(dev_priv, (enum pipe) cpu_transcoder); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 84301d3b8b7f..4388807f8fc8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1191,6 +1191,7 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv); void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); /* intel_display.c */ +enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc); void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco); void intel_update_rawclk(struct drm_i915_private *dev_priv); int vlv_get_cck_clock(struct drm_i915_private *dev_priv, -- cgit v1.2.3 From bfd02b3c557caa083be0d55a3164ede706a446e1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 14 Oct 2016 20:02:54 +0300 Subject: drm/i915: Suppress underruns during DP link retraining MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DP link retraining causes (spurious?) underruns. We can't really avoid them, except perhaps by doing a full modeset (which has its own underrun suppression anyway). So let's just hide them. MST still has its own logic for retrainin, but a bigger hpd handling cleanup/unification is needed there anyway, so let's leave that be for now. References: https://bugs.freedesktop.org/show_bug.cgi?id=98251 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1476464574-32230-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_dp.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bc03f61d94f1..780691a34133 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3987,6 +3987,31 @@ go_again: return -EINVAL; } +static void +intel_dp_retrain_link(struct intel_dp *intel_dp) +{ + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); + + /* Suppress underruns caused by re-training */ + intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); + if (crtc->config->has_pch_encoder) + intel_set_pch_fifo_underrun_reporting(dev_priv, + intel_crtc_pch_transcoder(crtc), false); + + intel_dp_start_link_train(intel_dp); + intel_dp_stop_link_train(intel_dp); + + /* Keep underrun reporting disabled until things are stable */ + intel_wait_for_vblank(&dev_priv->drm, crtc->pipe); + + intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true); + if (crtc->config->has_pch_encoder) + intel_set_pch_fifo_underrun_reporting(dev_priv, + intel_crtc_pch_transcoder(crtc), true); +} + static void intel_dp_check_link_status(struct intel_dp *intel_dp) { @@ -4012,8 +4037,8 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", intel_encoder->base.name); - intel_dp_start_link_train(intel_dp); - intel_dp_stop_link_train(intel_dp); + + intel_dp_retrain_link(intel_dp); } } -- cgit v1.2.3 From 6dffd431e2296cda08e7e4f0242e02df1d1698cd Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Mon, 17 Oct 2016 17:34:38 +0530 Subject: drm: Add aspect ratio parsing in DRM layer Current DRM layer functions don't parse aspect ratio information while converting a user mode->kernel mode or vice versa. This causes modeset to pick mode with wrong aspect ratio, eventually causing failures in HDMI compliance test cases, due to wrong VIC. This patch adds aspect ratio information in DRM's mode conversion and mode comparision functions, to make sure kernel picks mode with right aspect ratio (as per the VIC). V2: Addressed review comments from Sean: - Fix spellings/typo - No need to handle aspect ratio none - Add a break, for default case too V3: Rebase V4: Added r-b from Jose Signed-off-by: Shashank Sharma Signed-off-by: Lin, Jia Signed-off-by: Akashdeep Sharma Reviewed-by: Jim Bride Reviewed-by: Jose Abreu Cc: Daniel Vetter Cc: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476705880-15600-3-git-send-email-shashank.sharma@intel.com --- drivers/gpu/drm/drm_modes.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 53f07ac7c174..fde927a6cc5d 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -997,6 +997,7 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, mode1->vsync_end == mode2->vsync_end && mode1->vtotal == mode2->vtotal && mode1->vscan == mode2->vscan && + mode1->picture_aspect_ratio == mode2->picture_aspect_ratio && (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) == (mode2->flags & ~DRM_MODE_FLAG_3D_MASK)) return true; @@ -1499,6 +1500,21 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, out->vrefresh = in->vrefresh; out->flags = in->flags; out->type = in->type; + out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK; + + switch (in->picture_aspect_ratio) { + case HDMI_PICTURE_ASPECT_4_3: + out->flags |= DRM_MODE_FLAG_PIC_AR_4_3; + break; + case HDMI_PICTURE_ASPECT_16_9: + out->flags |= DRM_MODE_FLAG_PIC_AR_16_9; + break; + case HDMI_PICTURE_ASPECT_RESERVED: + default: + out->flags |= DRM_MODE_FLAG_PIC_AR_NONE; + break; + } + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; } @@ -1544,6 +1560,21 @@ int drm_mode_convert_umode(struct drm_display_mode *out, strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; + /* Clearing picture aspect ratio bits from out flags */ + out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK; + + switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) { + case DRM_MODE_FLAG_PIC_AR_4_3: + out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_4_3; + break; + case DRM_MODE_FLAG_PIC_AR_16_9: + out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_16_9; + break; + default: + out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE; + break; + } + out->status = drm_mode_validate_basic(out); if (out->status != MODE_OK) goto out; -- cgit v1.2.3 From a6e78b3e1406575323b30b65890ee3c29930fb27 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Mon, 17 Oct 2016 17:34:39 +0530 Subject: video: Add new aspect ratios for HDMI 2.0 HDMI 2.0/CEA-861-F introduces two new aspect ratios: - 64:27 - 256:135 This patch adds enumeration for the new aspect ratios in the existing aspect ratio list. V2: rebase V3: rebase V4: Added r-b from Jose, Ack by Tomi Signed-off-by: Shashank Sharma Reviewed-by: Sean Paul Reviewed-by: Jose Abreu Acked-by: Tomi Valkeinen Cc: Daniel Vetter Cc: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476705880-15600-4-git-send-email-shashank.sharma@intel.com --- drivers/video/hdmi.c | 4 ++++ include/linux/hdmi.h | 2 ++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index 162689227a23..1cf907ecded4 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -533,6 +533,10 @@ hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect) return "4:3"; case HDMI_PICTURE_ASPECT_16_9: return "16:9"; + case HDMI_PICTURE_ASPECT_64_27: + return "64:27"; + case HDMI_PICTURE_ASPECT_256_135: + return "256:135"; case HDMI_PICTURE_ASPECT_RESERVED: return "Reserved"; } diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index e9744202fa29..edbb4fc674ed 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -78,6 +78,8 @@ enum hdmi_picture_aspect { HDMI_PICTURE_ASPECT_NONE, HDMI_PICTURE_ASPECT_4_3, HDMI_PICTURE_ASPECT_16_9, + HDMI_PICTURE_ASPECT_64_27, + HDMI_PICTURE_ASPECT_256_135, HDMI_PICTURE_ASPECT_RESERVED, }; -- cgit v1.2.3 From a68362fe3e84fcbedd49939aa200519aa5410135 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Mon, 17 Oct 2016 17:34:40 +0530 Subject: drm: Add and handle new aspect ratios in DRM layer HDMI 2.0/CEA-861-F introduces two new aspect ratios: - 64:27 - 256:135 This patch: - Adds new DRM flags for to represent these new aspect ratios. - Adds new cases to handle these aspect ratios while converting from user->kernel mode or vise versa. V2: Rebase V3: Align macro for DRM_MODE_PICTURE_ASPECT_256_135 (Jim Bride) V4: Added r-b from Jose. Signed-off-by: Shashank Sharma Reviewed-by: Sean Paul Reviewed-by: Jose Abreu Cc: Daniel Vetter Cc: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476705880-15600-5-git-send-email-shashank.sharma@intel.com --- drivers/gpu/drm/drm_modes.c | 12 ++++++++++++ include/uapi/drm/drm_mode.h | 6 ++++++ 2 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index fde927a6cc5d..173b7d335834 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1509,6 +1509,12 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, case HDMI_PICTURE_ASPECT_16_9: out->flags |= DRM_MODE_FLAG_PIC_AR_16_9; break; + case HDMI_PICTURE_ASPECT_64_27: + out->flags |= DRM_MODE_FLAG_PIC_AR_64_27; + break; + case DRM_MODE_PICTURE_ASPECT_256_135: + out->flags |= DRM_MODE_FLAG_PIC_AR_256_135; + break; case HDMI_PICTURE_ASPECT_RESERVED: default: out->flags |= DRM_MODE_FLAG_PIC_AR_NONE; @@ -1570,6 +1576,12 @@ int drm_mode_convert_umode(struct drm_display_mode *out, case DRM_MODE_FLAG_PIC_AR_16_9: out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_16_9; break; + case DRM_MODE_FLAG_PIC_AR_64_27: + out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_64_27; + break; + case DRM_MODE_FLAG_PIC_AR_256_135: + out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_256_135; + break; default: out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE; break; diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 5c142b1387ac..084b50a02dc5 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -81,6 +81,8 @@ extern "C" { #define DRM_MODE_PICTURE_ASPECT_NONE 0 #define DRM_MODE_PICTURE_ASPECT_4_3 1 #define DRM_MODE_PICTURE_ASPECT_16_9 2 +#define DRM_MODE_PICTURE_ASPECT_64_27 3 +#define DRM_MODE_PICTURE_ASPECT_256_135 4 /* Aspect ratio flag bitmask (4 bits 22:19) */ #define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) @@ -90,6 +92,10 @@ extern "C" { (DRM_MODE_PICTURE_ASPECT_4_3<<19) #define DRM_MODE_FLAG_PIC_AR_16_9 \ (DRM_MODE_PICTURE_ASPECT_16_9<<19) +#define DRM_MODE_FLAG_PIC_AR_64_27 \ + (DRM_MODE_PICTURE_ASPECT_64_27<<19) +#define DRM_MODE_FLAG_PIC_AR_256_135 \ + (DRM_MODE_PICTURE_ASPECT_256_135<<19) /* DPMS flags */ /* bit compatible with the xorg definitions. */ -- cgit v1.2.3 From f14f368670541bfa217573194027a58f2206e250 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 17 Oct 2016 09:35:12 +0100 Subject: drm/edid: Rename local variable block to edid The "block" variable points to the entire edid, not individual blocks despite it being named such. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161017083514.21772-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_edid.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ec77bd3e1f08..3b4ac28f509e 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1282,20 +1282,20 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, void *data) { int i, j = 0, valid_extensions = 0; - u8 *block, *new; + u8 *edid, *new; bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS); - if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) + if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) return NULL; /* base block fetch */ for (i = 0; i < 4; i++) { - if (get_edid_block(data, block, 0, EDID_LENGTH)) + if (get_edid_block(data, edid, 0, EDID_LENGTH)) goto out; - if (drm_edid_block_valid(block, 0, print_bad_edid, + if (drm_edid_block_valid(edid, 0, print_bad_edid, &connector->edid_corrupt)) break; - if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { + if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) { connector->null_edid_counter++; goto carp; } @@ -1304,21 +1304,21 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, goto carp; /* if there's no extensions, we're done */ - if (block[0x7e] == 0) - return (struct edid *)block; + if (edid[0x7e] == 0) + return (struct edid *)edid; - new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); + new = krealloc(edid, (edid[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); if (!new) goto out; - block = new; + edid = new; - for (j = 1; j <= block[0x7e]; j++) { + for (j = 1; j <= edid[0x7e]; j++) { for (i = 0; i < 4; i++) { if (get_edid_block(data, - block + (valid_extensions + 1) * EDID_LENGTH, + edid + (valid_extensions + 1) * EDID_LENGTH, j, EDID_LENGTH)) goto out; - if (drm_edid_block_valid(block + (valid_extensions + 1) + if (drm_edid_block_valid(edid + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid, NULL)) { @@ -1336,16 +1336,16 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, } } - if (valid_extensions != block[0x7e]) { - block[EDID_LENGTH-1] += block[0x7e] - valid_extensions; - block[0x7e] = valid_extensions; - new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); + if (valid_extensions != edid[0x7e]) { + edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions; + edid[0x7e] = valid_extensions; + new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); if (!new) goto out; - block = new; + edid = new; } - return (struct edid *)block; + return (struct edid *)edid; carp: if (print_bad_edid) { @@ -1355,7 +1355,7 @@ carp: connector->bad_edid_counter++; out: - kfree(block); + kfree(edid); return NULL; } EXPORT_SYMBOL_GPL(drm_do_get_edid); -- cgit v1.2.3 From a28187ccab9410cad20e8808f00cfc07f99649c3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 17 Oct 2016 09:35:13 +0100 Subject: drm/edid: Use block local to refer to the block Now that we have the name "block" free once more, we can use it to point to the start of a block within the edid. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161017083514.21772-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_edid.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3b4ac28f509e..95de47ba1e77 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1313,15 +1313,13 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, edid = new; for (j = 1; j <= edid[0x7e]; j++) { + u8 *block = edid + (valid_extensions + 1) * EDID_LENGTH; + for (i = 0; i < 4; i++) { - if (get_edid_block(data, - edid + (valid_extensions + 1) * EDID_LENGTH, - j, EDID_LENGTH)) + if (get_edid_block(data, block, j, EDID_LENGTH)) goto out; - if (drm_edid_block_valid(edid + (valid_extensions + 1) - * EDID_LENGTH, j, - print_bad_edid, - NULL)) { + if (drm_edid_block_valid(block, j, + print_bad_edid, NULL)) { valid_extensions++; break; } -- cgit v1.2.3 From 801f33be8e902d8cea75cb7ac056d07c4fdd25f8 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 23 Sep 2016 14:09:07 +0100 Subject: drivers: cci: add missing CCI port availability firmware check The CCI ports programming interface is available to the kernel only when booted in secure mode (or when firmware enables non-secure access to override CCI ports control). In both cases, firmware reports the CCI ports availability through the device tree CCI ports nodes, which must be parsed and their status checked by the kernel probing path. This check is currently missing and may cause the kernel to erroneously believe it is free to take control of CCI ports where in practice CCI ports control is forbidden. Add the missing CCI port availability check to the CCI driver in order to guarantee sane CCI usage. Cc: Liviu Dudau Cc: Suzuki K Poulose Cc: Marc Zyngier Acked-by: Nicolas Pitre Signed-off-by: Lorenzo Pieralisi Signed-off-by: Sudeep Holla --- drivers/bus/arm-cci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c index 890082315054..231633328dfa 100644 --- a/drivers/bus/arm-cci.c +++ b/drivers/bus/arm-cci.c @@ -2190,6 +2190,9 @@ static int cci_probe_ports(struct device_node *np) if (!of_match_node(arm_cci_ctrl_if_matches, cp)) continue; + if (!of_device_is_available(cp)) + continue; + i = nb_ace + nb_ace_lite; if (i >= nb_cci_ports) @@ -2232,6 +2235,13 @@ static int cci_probe_ports(struct device_node *np) ports[i].dn = cp; } + /* + * If there is no CCI port that is under kernel control + * return early and report probe status. + */ + if (!nb_ace && !nb_ace_lite) + return -ENODEV; + /* initialize a stashed array of ACE ports to speed-up look-up */ cci_ace_init_ports(); -- cgit v1.2.3 From cf8fe97cad4a248bc7baaf39ecde2aece72f8618 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 14 Sep 2016 18:45:47 +0200 Subject: clk: renesas: r8a7796: Add SYS-DMAC clocks Signed-off-by: Ulrich Hecht Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index eb347ed265f2..d94a870de746 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -109,6 +109,9 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { + DEF_MOD("sys-dmac2", 217, R8A7796_CLK_S0D3), + DEF_MOD("sys-dmac1", 218, R8A7796_CLK_S0D3), + DEF_MOD("sys-dmac0", 219, R8A7796_CLK_S0D3), DEF_MOD("cmt3", 300, R8A7796_CLK_R), DEF_MOD("cmt2", 301, R8A7796_CLK_R), DEF_MOD("cmt1", 302, R8A7796_CLK_R), -- cgit v1.2.3 From 951456c37df6d778dc0ce42357417cba440cba87 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 14 Sep 2016 18:46:46 +0200 Subject: clk: renesas: r8a7796: Add SCIF clocks Signed-off-by: Ulrich Hecht Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index d94a870de746..37c1e43904ee 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -109,6 +109,11 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { + DEF_MOD("scif5", 202, R8A7796_CLK_S3D4), + DEF_MOD("scif4", 203, R8A7796_CLK_S3D4), + DEF_MOD("scif3", 204, R8A7796_CLK_S3D4), + DEF_MOD("scif1", 206, R8A7796_CLK_S3D4), + DEF_MOD("scif0", 207, R8A7796_CLK_S3D4), DEF_MOD("sys-dmac2", 217, R8A7796_CLK_S0D3), DEF_MOD("sys-dmac1", 218, R8A7796_CLK_S0D3), DEF_MOD("sys-dmac0", 219, R8A7796_CLK_S0D3), -- cgit v1.2.3 From 28aa831949d62711a44d97d692811e767a35b59e Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 14 Sep 2016 18:47:13 +0200 Subject: clk: renesas: r8a7796: Add HSCIF clocks Signed-off-by: Ulrich Hecht Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index 37c1e43904ee..cac1ad7ba1a8 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -128,6 +128,11 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("sdif0", 314, R8A7796_CLK_SD0), DEF_MOD("rwdt0", 402, R8A7796_CLK_R), DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1), + DEF_MOD("hscif4", 516, R8A7796_CLK_S3D1), + DEF_MOD("hscif3", 517, R8A7796_CLK_S3D1), + DEF_MOD("hscif2", 518, R8A7796_CLK_S3D1), + DEF_MOD("hscif1", 519, R8A7796_CLK_S3D1), + DEF_MOD("hscif0", 520, R8A7796_CLK_S3D1), DEF_MOD("thermal", 522, R8A7796_CLK_CP), DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6), DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4), -- cgit v1.2.3 From 878f8baa02d4948637c1e0b41a6055b22eb1f4a5 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 14 Sep 2016 18:46:07 +0200 Subject: clk: renesas: r8a7796: Add I2C clocks Signed-off-by: Ulrich Hecht Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index cac1ad7ba1a8..f0302fba948e 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -143,6 +143,13 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("gpio2", 910, R8A7796_CLK_S3D4), DEF_MOD("gpio1", 911, R8A7796_CLK_S3D4), DEF_MOD("gpio0", 912, R8A7796_CLK_S3D4), + DEF_MOD("i2c6", 918, R8A7796_CLK_S0D6), + DEF_MOD("i2c5", 919, R8A7796_CLK_S0D6), + DEF_MOD("i2c4", 927, R8A7796_CLK_S0D6), + DEF_MOD("i2c3", 928, R8A7796_CLK_S0D6), + DEF_MOD("i2c2", 929, R8A7796_CLK_S3D2), + DEF_MOD("i2c1", 930, R8A7796_CLK_S3D2), + DEF_MOD("i2c0", 931, R8A7796_CLK_S3D2), }; static const unsigned int r8a7796_crit_mod_clks[] __initconst = { -- cgit v1.2.3 From c1b5371b72644907a9b81a7cd8eabb32f04466d1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Sep 2016 16:31:41 +0200 Subject: clk: renesas: cpg-mssr: Always use readl()/writel() The Renesas CPG/MSSR driver core uses a mix of clk_readl()/clk_writel() and readl()/writel() to access the clock registers. Settle on the generic readl()/writel(). Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd --- drivers/clk/renesas/renesas-cpg-mssr.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index e1365e7491ae..a1d5b7431ec4 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -146,12 +146,12 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) enable ? "ON" : "OFF"); spin_lock_irqsave(&priv->mstp_lock, flags); - value = clk_readl(priv->base + SMSTPCR(reg)); + value = readl(priv->base + SMSTPCR(reg)); if (enable) value &= ~bitmask; else value |= bitmask; - clk_writel(value, priv->base + SMSTPCR(reg)); + writel(value, priv->base + SMSTPCR(reg)); spin_unlock_irqrestore(&priv->mstp_lock, flags); @@ -159,8 +159,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) return 0; for (i = 1000; i > 0; --i) { - if (!(clk_readl(priv->base + MSTPSR(reg)) & - bitmask)) + if (!(readl(priv->base + MSTPSR(reg)) & bitmask)) break; cpu_relax(); } @@ -190,7 +189,7 @@ static int cpg_mstp_clock_is_enabled(struct clk_hw *hw) struct cpg_mssr_priv *priv = clock->priv; u32 value; - value = clk_readl(priv->base + MSTPSR(clock->index / 32)); + value = readl(priv->base + MSTPSR(clock->index / 32)); return !(value & BIT(clock->index % 32)); } -- cgit v1.2.3 From 30ad3cf00e94f4a77775d851de15549099f0224e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Sep 2016 16:47:59 +0200 Subject: clk: renesas: rcar-gen3-cpg: Always use readl()/writel() The R-Car Gen3 CPG/MSSR driver uses a mix of clk_readl()/clk_writel() and readl()/writel() to access the clock registers. Settle on the generic readl()/writel(). Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd --- drivers/clk/renesas/rcar-gen3-cpg.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index bb4f2f9a8c2f..28ddb71545b8 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -98,7 +98,7 @@ static int cpg_sd_clock_enable(struct clk_hw *hw) u32 val, sd_fc; unsigned int i; - val = clk_readl(clock->reg); + val = readl(clock->reg); sd_fc = val & CPG_SD_FC_MASK; for (i = 0; i < clock->div_num; i++) @@ -111,7 +111,7 @@ static int cpg_sd_clock_enable(struct clk_hw *hw) val &= ~(CPG_SD_STP_MASK); val |= clock->div_table[i].val & CPG_SD_STP_MASK; - clk_writel(val, clock->reg); + writel(val, clock->reg); return 0; } @@ -120,14 +120,14 @@ static void cpg_sd_clock_disable(struct clk_hw *hw) { struct sd_clock *clock = to_sd_clock(hw); - clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg); + writel(readl(clock->reg) | CPG_SD_STP_MASK, clock->reg); } static int cpg_sd_clock_is_enabled(struct clk_hw *hw) { struct sd_clock *clock = to_sd_clock(hw); - return !(clk_readl(clock->reg) & CPG_SD_STP_MASK); + return !(readl(clock->reg) & CPG_SD_STP_MASK); } static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, @@ -138,7 +138,7 @@ static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, u32 val, sd_fc; unsigned int i; - val = clk_readl(clock->reg); + val = readl(clock->reg); sd_fc = val & CPG_SD_FC_MASK; for (i = 0; i < clock->div_num; i++) @@ -189,10 +189,10 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, if (i >= clock->div_num) return -EINVAL; - val = clk_readl(clock->reg); + val = readl(clock->reg); val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); - clk_writel(val, clock->reg); + writel(val, clock->reg); return 0; } -- cgit v1.2.3 From 02609a2335fd21c34288ef2ab532a0c2e9f20b6a Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 14 Sep 2016 18:46:08 +0200 Subject: pinctrl: sh-pfc: r8a7796: Add I2C pin support Signed-off-by: Ulrich Hecht Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 77 ++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index dc9b671ccf2e..42db74581d49 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1490,6 +1490,57 @@ static const struct sh_pfc_pin pinmux_pins[] = { PINMUX_GPIO_GP_ALL(), }; +/* - I2C -------------------------------------------------------------------- */ +static const unsigned int i2c1_a_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 10), +}; +static const unsigned int i2c1_a_mux[] = { + SDA1_A_MARK, SCL1_A_MARK, +}; +static const unsigned int i2c1_b_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 23), +}; +static const unsigned int i2c1_b_mux[] = { + SDA1_B_MARK, SCL1_B_MARK, +}; +static const unsigned int i2c2_a_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 4), +}; +static const unsigned int i2c2_a_mux[] = { + SDA2_A_MARK, SCL2_A_MARK, +}; +static const unsigned int i2c2_b_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 12), +}; +static const unsigned int i2c2_b_mux[] = { + SDA2_B_MARK, SCL2_B_MARK, +}; +static const unsigned int i2c6_a_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(1, 8), RCAR_GP_PIN(1, 11), +}; +static const unsigned int i2c6_a_mux[] = { + SDA6_A_MARK, SCL6_A_MARK, +}; +static const unsigned int i2c6_b_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25), +}; +static const unsigned int i2c6_b_mux[] = { + SDA6_B_MARK, SCL6_B_MARK, +}; +static const unsigned int i2c6_c_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), +}; +static const unsigned int i2c6_c_mux[] = { + SDA6_C_MARK, SCL6_C_MARK, +}; + /* - SCIF0 ------------------------------------------------------------------ */ static const unsigned int scif0_data_pins[] = { /* RX, TX */ @@ -1912,6 +1963,13 @@ static const unsigned int sdhi3_ds_mux[] = { }; static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(i2c1_a), + SH_PFC_PIN_GROUP(i2c1_b), + SH_PFC_PIN_GROUP(i2c2_a), + SH_PFC_PIN_GROUP(i2c2_b), + SH_PFC_PIN_GROUP(i2c6_a), + SH_PFC_PIN_GROUP(i2c6_b), + SH_PFC_PIN_GROUP(i2c6_c), SH_PFC_PIN_GROUP(scif0_data), SH_PFC_PIN_GROUP(scif0_clk), SH_PFC_PIN_GROUP(scif0_ctrl), @@ -1969,6 +2027,22 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(sdhi3_ds), }; +static const char * const i2c1_groups[] = { + "i2c1_a", + "i2c1_b", +}; + +static const char * const i2c2_groups[] = { + "i2c2_a", + "i2c2_b", +}; + +static const char * const i2c6_groups[] = { + "i2c6_a", + "i2c6_b", + "i2c6_c", +}; + static const char * const scif0_groups[] = { "scif0_data", "scif0_clk", @@ -2058,6 +2132,9 @@ static const char * const sdhi3_groups[] = { }; static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(i2c1), + SH_PFC_FUNCTION(i2c2), + SH_PFC_FUNCTION(i2c6), SH_PFC_FUNCTION(scif0), SH_PFC_FUNCTION(scif1), SH_PFC_FUNCTION(scif2), -- cgit v1.2.3 From fb0828316bf655d26c74321240bbf83b2a1d89ad Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Thu, 13 Oct 2016 10:29:14 +0100 Subject: pinctrl: sh-pfc: r8a7796: Add DRIF support This patch adds DRIF[0-3] pinmux support for r8a7796 SoC. Signed-off-by: Ramesh Shanmugasundaram Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 291 +++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 42db74581d49..dd23198492b5 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1490,6 +1490,221 @@ static const struct sh_pfc_pin pinmux_pins[] = { PINMUX_GPIO_GP_ALL(), }; +/* - DRIF0 --------------------------------------------------------------- */ +static const unsigned int drif0_ctrl_a_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9), +}; +static const unsigned int drif0_ctrl_a_mux[] = { + RIF0_CLK_A_MARK, RIF0_SYNC_A_MARK, +}; +static const unsigned int drif0_data0_a_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 10), +}; +static const unsigned int drif0_data0_a_mux[] = { + RIF0_D0_A_MARK, +}; +static const unsigned int drif0_data1_a_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 7), +}; +static const unsigned int drif0_data1_a_mux[] = { + RIF0_D1_A_MARK, +}; +static const unsigned int drif0_ctrl_b_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 4), +}; +static const unsigned int drif0_ctrl_b_mux[] = { + RIF0_CLK_B_MARK, RIF0_SYNC_B_MARK, +}; +static const unsigned int drif0_data0_b_pins[] = { + /* D0 */ + RCAR_GP_PIN(5, 1), +}; +static const unsigned int drif0_data0_b_mux[] = { + RIF0_D0_B_MARK, +}; +static const unsigned int drif0_data1_b_pins[] = { + /* D1 */ + RCAR_GP_PIN(5, 2), +}; +static const unsigned int drif0_data1_b_mux[] = { + RIF0_D1_B_MARK, +}; +static const unsigned int drif0_ctrl_c_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(5, 12), RCAR_GP_PIN(5, 15), +}; +static const unsigned int drif0_ctrl_c_mux[] = { + RIF0_CLK_C_MARK, RIF0_SYNC_C_MARK, +}; +static const unsigned int drif0_data0_c_pins[] = { + /* D0 */ + RCAR_GP_PIN(5, 13), +}; +static const unsigned int drif0_data0_c_mux[] = { + RIF0_D0_C_MARK, +}; +static const unsigned int drif0_data1_c_pins[] = { + /* D1 */ + RCAR_GP_PIN(5, 14), +}; +static const unsigned int drif0_data1_c_mux[] = { + RIF0_D1_C_MARK, +}; +/* - DRIF1 --------------------------------------------------------------- */ +static const unsigned int drif1_ctrl_a_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 18), +}; +static const unsigned int drif1_ctrl_a_mux[] = { + RIF1_CLK_A_MARK, RIF1_SYNC_A_MARK, +}; +static const unsigned int drif1_data0_a_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 19), +}; +static const unsigned int drif1_data0_a_mux[] = { + RIF1_D0_A_MARK, +}; +static const unsigned int drif1_data1_a_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 20), +}; +static const unsigned int drif1_data1_a_mux[] = { + RIF1_D1_A_MARK, +}; +static const unsigned int drif1_ctrl_b_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 3), +}; +static const unsigned int drif1_ctrl_b_mux[] = { + RIF1_CLK_B_MARK, RIF1_SYNC_B_MARK, +}; +static const unsigned int drif1_data0_b_pins[] = { + /* D0 */ + RCAR_GP_PIN(5, 7), +}; +static const unsigned int drif1_data0_b_mux[] = { + RIF1_D0_B_MARK, +}; +static const unsigned int drif1_data1_b_pins[] = { + /* D1 */ + RCAR_GP_PIN(5, 8), +}; +static const unsigned int drif1_data1_b_mux[] = { + RIF1_D1_B_MARK, +}; +static const unsigned int drif1_ctrl_c_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 11), +}; +static const unsigned int drif1_ctrl_c_mux[] = { + RIF1_CLK_C_MARK, RIF1_SYNC_C_MARK, +}; +static const unsigned int drif1_data0_c_pins[] = { + /* D0 */ + RCAR_GP_PIN(5, 6), +}; +static const unsigned int drif1_data0_c_mux[] = { + RIF1_D0_C_MARK, +}; +static const unsigned int drif1_data1_c_pins[] = { + /* D1 */ + RCAR_GP_PIN(5, 10), +}; +static const unsigned int drif1_data1_c_mux[] = { + RIF1_D1_C_MARK, +}; +/* - DRIF2 --------------------------------------------------------------- */ +static const unsigned int drif2_ctrl_a_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9), +}; +static const unsigned int drif2_ctrl_a_mux[] = { + RIF2_CLK_A_MARK, RIF2_SYNC_A_MARK, +}; +static const unsigned int drif2_data0_a_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 7), +}; +static const unsigned int drif2_data0_a_mux[] = { + RIF2_D0_A_MARK, +}; +static const unsigned int drif2_data1_a_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 10), +}; +static const unsigned int drif2_data1_a_mux[] = { + RIF2_D1_A_MARK, +}; +static const unsigned int drif2_ctrl_b_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 26), RCAR_GP_PIN(6, 27), +}; +static const unsigned int drif2_ctrl_b_mux[] = { + RIF2_CLK_B_MARK, RIF2_SYNC_B_MARK, +}; +static const unsigned int drif2_data0_b_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 30), +}; +static const unsigned int drif2_data0_b_mux[] = { + RIF2_D0_B_MARK, +}; +static const unsigned int drif2_data1_b_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 31), +}; +static const unsigned int drif2_data1_b_mux[] = { + RIF2_D1_B_MARK, +}; +/* - DRIF3 --------------------------------------------------------------- */ +static const unsigned int drif3_ctrl_a_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 18), +}; +static const unsigned int drif3_ctrl_a_mux[] = { + RIF3_CLK_A_MARK, RIF3_SYNC_A_MARK, +}; +static const unsigned int drif3_data0_a_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 19), +}; +static const unsigned int drif3_data0_a_mux[] = { + RIF3_D0_A_MARK, +}; +static const unsigned int drif3_data1_a_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 20), +}; +static const unsigned int drif3_data1_a_mux[] = { + RIF3_D1_A_MARK, +}; +static const unsigned int drif3_ctrl_b_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 24), RCAR_GP_PIN(6, 25), +}; +static const unsigned int drif3_ctrl_b_mux[] = { + RIF3_CLK_B_MARK, RIF3_SYNC_B_MARK, +}; +static const unsigned int drif3_data0_b_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 28), +}; +static const unsigned int drif3_data0_b_mux[] = { + RIF3_D0_B_MARK, +}; +static const unsigned int drif3_data1_b_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 29), +}; +static const unsigned int drif3_data1_b_mux[] = { + RIF3_D1_B_MARK, +}; + /* - I2C -------------------------------------------------------------------- */ static const unsigned int i2c1_a_pins[] = { /* SDA, SCL */ @@ -1963,6 +2178,36 @@ static const unsigned int sdhi3_ds_mux[] = { }; static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(drif0_ctrl_a), + SH_PFC_PIN_GROUP(drif0_data0_a), + SH_PFC_PIN_GROUP(drif0_data1_a), + SH_PFC_PIN_GROUP(drif0_ctrl_b), + SH_PFC_PIN_GROUP(drif0_data0_b), + SH_PFC_PIN_GROUP(drif0_data1_b), + SH_PFC_PIN_GROUP(drif0_ctrl_c), + SH_PFC_PIN_GROUP(drif0_data0_c), + SH_PFC_PIN_GROUP(drif0_data1_c), + SH_PFC_PIN_GROUP(drif1_ctrl_a), + SH_PFC_PIN_GROUP(drif1_data0_a), + SH_PFC_PIN_GROUP(drif1_data1_a), + SH_PFC_PIN_GROUP(drif1_ctrl_b), + SH_PFC_PIN_GROUP(drif1_data0_b), + SH_PFC_PIN_GROUP(drif1_data1_b), + SH_PFC_PIN_GROUP(drif1_ctrl_c), + SH_PFC_PIN_GROUP(drif1_data0_c), + SH_PFC_PIN_GROUP(drif1_data1_c), + SH_PFC_PIN_GROUP(drif2_ctrl_a), + SH_PFC_PIN_GROUP(drif2_data0_a), + SH_PFC_PIN_GROUP(drif2_data1_a), + SH_PFC_PIN_GROUP(drif2_ctrl_b), + SH_PFC_PIN_GROUP(drif2_data0_b), + SH_PFC_PIN_GROUP(drif2_data1_b), + SH_PFC_PIN_GROUP(drif3_ctrl_a), + SH_PFC_PIN_GROUP(drif3_data0_a), + SH_PFC_PIN_GROUP(drif3_data1_a), + SH_PFC_PIN_GROUP(drif3_ctrl_b), + SH_PFC_PIN_GROUP(drif3_data0_b), + SH_PFC_PIN_GROUP(drif3_data1_b), SH_PFC_PIN_GROUP(i2c1_a), SH_PFC_PIN_GROUP(i2c1_b), SH_PFC_PIN_GROUP(i2c2_a), @@ -2027,6 +2272,48 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(sdhi3_ds), }; +static const char * const drif0_groups[] = { + "drif0_ctrl_a", + "drif0_data0_a", + "drif0_data1_a", + "drif0_ctrl_b", + "drif0_data0_b", + "drif0_data1_b", + "drif0_ctrl_c", + "drif0_data0_c", + "drif0_data1_c", +}; + +static const char * const drif1_groups[] = { + "drif1_ctrl_a", + "drif1_data0_a", + "drif1_data1_a", + "drif1_ctrl_b", + "drif1_data0_b", + "drif1_data1_b", + "drif1_ctrl_c", + "drif1_data0_c", + "drif1_data1_c", +}; + +static const char * const drif2_groups[] = { + "drif2_ctrl_a", + "drif2_data0_a", + "drif2_data1_a", + "drif2_ctrl_b", + "drif2_data0_b", + "drif2_data1_b", +}; + +static const char * const drif3_groups[] = { + "drif3_ctrl_a", + "drif3_data0_a", + "drif3_data1_a", + "drif3_ctrl_b", + "drif3_data0_b", + "drif3_data1_b", +}; + static const char * const i2c1_groups[] = { "i2c1_a", "i2c1_b", @@ -2132,6 +2419,10 @@ static const char * const sdhi3_groups[] = { }; static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(drif0), + SH_PFC_FUNCTION(drif1), + SH_PFC_FUNCTION(drif2), + SH_PFC_FUNCTION(drif3), SH_PFC_FUNCTION(i2c1), SH_PFC_FUNCTION(i2c2), SH_PFC_FUNCTION(i2c6), -- cgit v1.2.3 From a7f7b44beadbec60e78d360944e926d5cba7f2d4 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 17 Oct 2016 09:22:04 +0200 Subject: net: hip04: Remove superfluous ether_setup after alloc_etherdev There is no need to call ether_setup after alloc_ethdev since it was already called there. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hip04_eth.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index 3c99ca420f57..854befde0a08 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -897,7 +897,6 @@ static int hip04_mac_probe(struct platform_device *pdev) INIT_WORK(&priv->tx_timeout_task, hip04_tx_timeout_task); - ether_setup(ndev); ndev->netdev_ops = &hip04_netdev_ops; ndev->ethtool_ops = &hip04_ethtool_ops; ndev->watchdog_timeo = TX_TIMEOUT; -- cgit v1.2.3 From 865afb11949e5bf4bb32d9a2aa9867c1ac4d8da0 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 11 Oct 2016 16:15:04 -0700 Subject: drm/fb-helper: reject any changes to the fbdev The current fbdev emulation does not allow to push back changes in width, height or depth to KMS, hence reject any changes with an error. This makes sure that fbdev ioctl's fail properly and user space does not assume that changes succeeded. Signed-off-by: Stefan Agner Reviewed-by: Tomi Valkeinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161011231504.17688-1-stefan@agner.ch --- drivers/gpu/drm/drm_fb_helper.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 22d4f0e22101..8fffac8c5c75 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1209,11 +1209,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, if (var->pixclock != 0 || in_dbg_master()) return -EINVAL; - /* Need to resize the fb object !!! */ - if (var->bits_per_pixel > fb->bits_per_pixel || - var->xres > fb->width || var->yres > fb->height || - var->xres_virtual > fb->width || var->yres_virtual > fb->height) { - DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb " + /* + * Changes struct fb_var_screeninfo are currently not pushed back + * to KMS, hence fail if different settings are requested. + */ + if (var->bits_per_pixel != fb->bits_per_pixel || + var->xres != fb->width || var->yres != fb->height || + var->xres_virtual != fb->width || var->yres_virtual != fb->height) { + DRM_DEBUG("fb userspace requested width/height/bpp different than current fb " "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel, var->xres_virtual, var->yres_virtual, -- cgit v1.2.3 From 9edbf1fa600a2ef17c7553c2103d0055d0320d15 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Thu, 6 Oct 2016 17:21:06 +0200 Subject: drm: Add API for capturing frame CRCs Adds files and directories to debugfs for controlling and reading frame CRCs, per CRTC: dri/0/crtc-0/crc dri/0/crtc-0/crc/control dri/0/crtc-0/crc/data Drivers can implement the set_crc_source callback() in drm_crtc_funcs to start and stop generating frame CRCs and can add entries to the output by calling drm_crtc_add_crc_entry. v2: - Lots of good fixes suggested by Thierry. - Added documentation. - Changed the debugfs layout. - Moved to allocate the entries circular queue once when frame generation gets enabled for the first time. v3: - Use the control file just to select the source, and start and stop capture when the data file is opened and closed, respectively. - Make variable the number of CRC values per entry, per source. - Allocate entries queue each time we start capturing as now there isn't a fixed number of CRC values per entry. - Store the frame counter in the data file as a 8-digit hex number. - For sources that cannot provide useful frame numbers, place XXXXXXXX in the frame field. v4: - Build only if CONFIG_DEBUG_FS is enabled. - Use memdup_user_nul. - Consolidate calculation of the size of an entry in a helper. - Add 0x prefix to hex numbers in the data file. - Remove unnecessary snprintf and strlen usage in read callback. v5: - Made the crcs array in drm_crtc_crc_entry fixed-size - Lots of other smaller improvements suggested by Emil Velikov v7: - Move definition of drm_debugfs_crtc_crc_add to drm_internal.h v8: - Call debugfs_remove_recursive when we fail to create the minor device v9: - Register the debugfs directory for a crtc from drm_crtc_register_all() v10: - Don't let debugfs failures interrupt CRTC registration (Emil Velikov) v11: - Remove extra brace that broke compilation. Sorry! Signed-off-by: Tomeu Vizoso Reviewed-by: Emil Velikov Acked-by: Benjamin Gaignard Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1475767268-14379-3-git-send-email-tomeu.vizoso@collabora.com --- Documentation/gpu/drm-uapi.rst | 6 + drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_crtc.c | 34 +++- drivers/gpu/drm/drm_debugfs.c | 34 +++- drivers/gpu/drm/drm_debugfs_crc.c | 351 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_internal.h | 16 ++ include/drm/drm_crtc.h | 41 +++++ include/drm/drm_debugfs_crc.h | 73 ++++++++ 8 files changed, 555 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/drm_debugfs_crc.c create mode 100644 include/drm/drm_debugfs_crc.h (limited to 'drivers') diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 1ba301cebe16..de3ac9f90f8f 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -216,3 +216,9 @@ interfaces. Especially since all hardware-acceleration interfaces to userspace are driver specific for efficiency and other reasons these interfaces can be rather substantial. Hence every driver has its own chapter. + +Testing and validation +====================== + +.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c + :doc: CRC ABI diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 25c720454017..74579d2e796e 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -9,7 +9,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm_scatter.o drm_pci.o \ drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ - drm_info.o drm_debugfs.o drm_encoder_slave.o \ + drm_info.o drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o \ drm_rect.o drm_vma_manager.o drm_flip_work.o \ drm_modeset_lock.o drm_atomic.o drm_bridge.o \ @@ -23,6 +23,7 @@ drm-$(CONFIG_PCI) += ati_pcigart.o drm-$(CONFIG_DRM_PANEL) += drm_panel.o drm-$(CONFIG_OF) += drm_of.o drm-$(CONFIG_AGP) += drm_agpsupport.o +drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 2d7bedf28647..60403bf7a4ff 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -122,6 +122,10 @@ static int drm_crtc_register_all(struct drm_device *dev) int ret = 0; drm_for_each_crtc(crtc, dev) { + if (drm_debugfs_crtc_add(crtc)) + DRM_ERROR("Failed to initialize debugfs entry for CRTC '%s'.\n", + crtc->name); + if (crtc->funcs->late_register) ret = crtc->funcs->late_register(crtc); if (ret) @@ -138,9 +142,29 @@ static void drm_crtc_unregister_all(struct drm_device *dev) drm_for_each_crtc(crtc, dev) { if (crtc->funcs->early_unregister) crtc->funcs->early_unregister(crtc); + drm_debugfs_crtc_remove(crtc); } } +static int drm_crtc_crc_init(struct drm_crtc *crtc) +{ +#ifdef CONFIG_DEBUG_FS + spin_lock_init(&crtc->crc.lock); + init_waitqueue_head(&crtc->crc.wq); + crtc->crc.source = kstrdup("auto", GFP_KERNEL); + if (!crtc->crc.source) + return -ENOMEM; +#endif + return 0; +} + +static void drm_crtc_crc_fini(struct drm_crtc *crtc) +{ +#ifdef CONFIG_DEBUG_FS + kfree(crtc->crc.source); +#endif +} + /** * drm_crtc_init_with_planes - Initialise a new CRTC object with * specified primary and cursor planes. @@ -210,6 +234,12 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, if (cursor) cursor->possible_crtcs = 1 << drm_crtc_index(crtc); + ret = drm_crtc_crc_init(crtc); + if (ret) { + drm_mode_object_unregister(dev, &crtc->base); + return ret; + } + if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { drm_object_attach_property(&crtc->base, config->prop_active, 0); drm_object_attach_property(&crtc->base, config->prop_mode_id, 0); @@ -236,6 +266,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) * the indices on the drm_crtc after us in the crtc_list. */ + drm_crtc_crc_fini(crtc); + kfree(crtc->gamma_store); crtc->gamma_store = NULL; diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index fa10cef2ba37..8ea72d821525 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -415,5 +415,37 @@ void drm_debugfs_connector_remove(struct drm_connector *connector) connector->debugfs_entry = NULL; } -#endif /* CONFIG_DEBUG_FS */ +int drm_debugfs_crtc_add(struct drm_crtc *crtc) +{ + struct drm_minor *minor = crtc->dev->primary; + struct dentry *root; + char *name; + + name = kasprintf(GFP_KERNEL, "crtc-%d", crtc->index); + if (!name) + return -ENOMEM; + + root = debugfs_create_dir(name, minor->debugfs_root); + kfree(name); + if (!root) + return -ENOMEM; + + crtc->debugfs_entry = root; + + if (drm_debugfs_crtc_crc_add(crtc)) + goto error; + return 0; + +error: + drm_debugfs_crtc_remove(crtc); + return -ENOMEM; +} + +void drm_debugfs_crtc_remove(struct drm_crtc *crtc) +{ + debugfs_remove_recursive(crtc->debugfs_entry); + crtc->debugfs_entry = NULL; +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c new file mode 100644 index 000000000000..4129405d17c0 --- /dev/null +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -0,0 +1,351 @@ +/* + * Copyright © 2008 Intel Corporation + * Copyright © 2016 Collabora Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Based on code from the i915 driver. + * Original author: Damien Lespiau + * + */ + +#include +#include +#include +#include + +/** + * DOC: CRC ABI + * + * DRM device drivers can provide to userspace CRC information of each frame as + * it reached a given hardware component (a "source"). + * + * Userspace can control generation of CRCs in a given CRTC by writing to the + * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC. + * Accepted values are source names (which are driver-specific) and the "auto" + * keyword, which will let the driver select a default source of frame CRCs + * for this CRTC. + * + * Once frame CRC generation is enabled, userspace can capture them by reading + * the dri/0/crtc-N/crc/data file. Each line in that file contains the frame + * number in the first field and then a number of unsigned integer fields + * containing the CRC data. Fields are separated by a single space and the number + * of CRC fields is source-specific. + * + * Note that though in some cases the CRC is computed in a specified way and on + * the frame contents as supplied by userspace (eDP 1.3), in general the CRC + * computation is performed in an unspecified way and on frame contents that have + * been already processed in also an unspecified way and thus userspace cannot + * rely on being able to generate matching CRC values for the frame contents that + * it submits. In this general case, the maximum userspace can do is to compare + * the reported CRCs of frames that should have the same contents. + */ + +static int crc_control_show(struct seq_file *m, void *data) +{ + struct drm_crtc *crtc = m->private; + + seq_printf(m, "%s\n", crtc->crc.source); + + return 0; +} + +static int crc_control_open(struct inode *inode, struct file *file) +{ + struct drm_crtc *crtc = inode->i_private; + + return single_open(file, crc_control_show, crtc); +} + +static ssize_t crc_control_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct drm_crtc *crtc = m->private; + struct drm_crtc_crc *crc = &crtc->crc; + char *source; + + if (len == 0) + return 0; + + if (len > PAGE_SIZE - 1) { + DRM_DEBUG_KMS("Expected < %lu bytes into crtc crc control\n", + PAGE_SIZE); + return -E2BIG; + } + + source = memdup_user_nul(ubuf, len); + if (IS_ERR(source)) + return PTR_ERR(source); + + if (source[len] == '\n') + source[len] = '\0'; + + spin_lock_irq(&crc->lock); + + if (crc->opened) { + spin_unlock_irq(&crc->lock); + kfree(source); + return -EBUSY; + } + + kfree(crc->source); + crc->source = source; + + spin_unlock_irq(&crc->lock); + + *offp += len; + return len; +} + +const struct file_operations drm_crtc_crc_control_fops = { + .owner = THIS_MODULE, + .open = crc_control_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = crc_control_write +}; + +static int crtc_crc_open(struct inode *inode, struct file *filep) +{ + struct drm_crtc *crtc = inode->i_private; + struct drm_crtc_crc *crc = &crtc->crc; + struct drm_crtc_crc_entry *entries = NULL; + size_t values_cnt; + int ret; + + if (crc->opened) + return -EBUSY; + + ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt); + if (ret) + return ret; + + if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) { + ret = -EINVAL; + goto err_disable; + } + + if (WARN_ON(values_cnt == 0)) { + ret = -EINVAL; + goto err_disable; + } + + entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL); + if (!entries) { + ret = -ENOMEM; + goto err_disable; + } + + spin_lock_irq(&crc->lock); + crc->entries = entries; + crc->values_cnt = values_cnt; + crc->opened = true; + spin_unlock_irq(&crc->lock); + + return 0; + +err_disable: + crtc->funcs->set_crc_source(crtc, NULL, &values_cnt); + return ret; +} + +static int crtc_crc_release(struct inode *inode, struct file *filep) +{ + struct drm_crtc *crtc = filep->f_inode->i_private; + struct drm_crtc_crc *crc = &crtc->crc; + size_t values_cnt; + + spin_lock_irq(&crc->lock); + kfree(crc->entries); + crc->entries = NULL; + crc->head = 0; + crc->tail = 0; + crc->values_cnt = 0; + crc->opened = false; + spin_unlock_irq(&crc->lock); + + crtc->funcs->set_crc_source(crtc, NULL, &values_cnt); + + return 0; +} + +static int crtc_crc_data_count(struct drm_crtc_crc *crc) +{ + assert_spin_locked(&crc->lock); + return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR); +} + +/* + * 1 frame field of 10 chars plus a number of CRC fields of 10 chars each, space + * separated, with a newline at the end and null-terminated. + */ +#define LINE_LEN(values_cnt) (10 + 11 * values_cnt + 1 + 1) +#define MAX_LINE_LEN (LINE_LEN(DRM_MAX_CRC_NR)) + +static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf, + size_t count, loff_t *pos) +{ + struct drm_crtc *crtc = filep->f_inode->i_private; + struct drm_crtc_crc *crc = &crtc->crc; + struct drm_crtc_crc_entry *entry; + char buf[MAX_LINE_LEN]; + int ret, i; + + spin_lock_irq(&crc->lock); + + if (!crc->source) { + spin_unlock_irq(&crc->lock); + return 0; + } + + /* Nothing to read? */ + while (crtc_crc_data_count(crc) == 0) { + if (filep->f_flags & O_NONBLOCK) { + spin_unlock_irq(&crc->lock); + return -EAGAIN; + } + + ret = wait_event_interruptible_lock_irq(crc->wq, + crtc_crc_data_count(crc), + crc->lock); + if (ret) { + spin_unlock_irq(&crc->lock); + return ret; + } + } + + /* We know we have an entry to be read */ + entry = &crc->entries[crc->tail]; + + if (count < LINE_LEN(crc->values_cnt)) { + spin_unlock_irq(&crc->lock); + return -EINVAL; + } + + BUILD_BUG_ON_NOT_POWER_OF_2(DRM_CRC_ENTRIES_NR); + crc->tail = (crc->tail + 1) & (DRM_CRC_ENTRIES_NR - 1); + + spin_unlock_irq(&crc->lock); + + if (entry->has_frame_counter) + sprintf(buf, "0x%08x", entry->frame); + else + sprintf(buf, "XXXXXXXXXX"); + + for (i = 0; i < crc->values_cnt; i++) + sprintf(buf + 10 + i * 11, " 0x%08x", entry->crcs[i]); + sprintf(buf + 10 + crc->values_cnt * 11, "\n"); + + if (copy_to_user(user_buf, buf, LINE_LEN(crc->values_cnt))) + return -EFAULT; + + return LINE_LEN(crc->values_cnt); +} + +const struct file_operations drm_crtc_crc_data_fops = { + .owner = THIS_MODULE, + .open = crtc_crc_open, + .read = crtc_crc_read, + .release = crtc_crc_release, +}; + +/** + * drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs + * @crtc: CRTC to whom the frames will belong + * + * Adds files to debugfs directory that allows userspace to control the + * generation of frame CRCs and to read them. + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) +{ + struct dentry *crc_ent, *ent; + + if (!crtc->funcs->set_crc_source) + return 0; + + crc_ent = debugfs_create_dir("crc", crtc->debugfs_entry); + if (!crc_ent) + return -ENOMEM; + + ent = debugfs_create_file("control", S_IRUGO, crc_ent, crtc, + &drm_crtc_crc_control_fops); + if (!ent) + goto error; + + ent = debugfs_create_file("data", S_IRUGO, crc_ent, crtc, + &drm_crtc_crc_data_fops); + if (!ent) + goto error; + + return 0; + +error: + debugfs_remove_recursive(crc_ent); + + return -ENOMEM; +} + +/** + * drm_crtc_add_crc_entry - Add entry with CRC information for a frame + * @crtc: CRTC to which the frame belongs + * @has_frame: whether this entry has a frame number to go with + * @frame: number of the frame these CRCs are about + * @crcs: array of CRC values, with length matching #drm_crtc_crc.values_cnt + * + * For each frame, the driver polls the source of CRCs for new data and calls + * this function to add them to the buffer from where userspace reads. + */ +int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, + uint32_t frame, uint32_t *crcs) +{ + struct drm_crtc_crc *crc = &crtc->crc; + struct drm_crtc_crc_entry *entry; + int head, tail; + + assert_spin_locked(&crc->lock); + + /* Caller may not have noticed yet that userspace has stopped reading */ + if (!crc->opened) + return -EINVAL; + + head = crc->head; + tail = crc->tail; + + if (CIRC_SPACE(head, tail, DRM_CRC_ENTRIES_NR) < 1) { + DRM_ERROR("Overflow of CRC buffer, userspace reads too slow.\n"); + return -ENOBUFS; + } + + entry = &crc->entries[head]; + entry->frame = frame; + entry->has_frame_counter = has_frame; + memcpy(&entry->crcs, crcs, sizeof(*crcs) * crc->values_cnt); + + head = (head + 1) & (DRM_CRC_ENTRIES_NR - 1); + crc->head = head; + + return 0; +} +EXPORT_SYMBOL_GPL(drm_crtc_add_crc_entry); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index e66af289a016..abd209863ef4 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -100,6 +100,9 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, int drm_debugfs_cleanup(struct drm_minor *minor); int drm_debugfs_connector_add(struct drm_connector *connector); void drm_debugfs_connector_remove(struct drm_connector *connector); +int drm_debugfs_crtc_add(struct drm_crtc *crtc); +void drm_debugfs_crtc_remove(struct drm_crtc *crtc); +int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc); #else static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, struct dentry *root) @@ -119,4 +122,17 @@ static inline int drm_debugfs_connector_add(struct drm_connector *connector) static inline void drm_debugfs_connector_remove(struct drm_connector *connector) { } + +static inline int drm_debugfs_crtc_add(struct drm_crtc *crtc) +{ + return 0; +} +static inline void drm_debugfs_crtc_remove(struct drm_crtc *crtc) +{ +} + +static inline int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) +{ + return 0; +} #endif diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 4633915cb51b..284c1b3aec10 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -47,6 +47,7 @@ #include #include #include +#include struct drm_device; struct drm_mode_set; @@ -569,6 +570,30 @@ struct drm_crtc_funcs { * before data structures are torndown. */ void (*early_unregister)(struct drm_crtc *crtc); + + /** + * @set_crc_source: + * + * Changes the source of CRC checksums of frames at the request of + * userspace, typically for testing purposes. The sources available are + * specific of each driver and a %NULL value indicates that CRC + * generation is to be switched off. + * + * When CRC generation is enabled, the driver should call + * drm_crtc_add_crc_entry() at each frame, providing any information + * that characterizes the frame contents in the crcN arguments, as + * provided from the configured source. Drivers must accept a "auto" + * source name that will select a default source for this CRTC. + * + * This callback is optional if the driver does not support any CRC + * generation functionality. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ + int (*set_crc_source)(struct drm_crtc *crtc, const char *source, + size_t *values_cnt); }; /** @@ -685,6 +710,22 @@ struct drm_crtc { * context. */ struct drm_modeset_acquire_ctx *acquire_ctx; + +#ifdef CONFIG_DEBUG_FS + /** + * @debugfs_entry: + * + * Debugfs directory for this CRTC. + */ + struct dentry *debugfs_entry; + + /** + * @crc: + * + * Configuration settings of CRC capture. + */ + struct drm_crtc_crc crc; +#endif }; /** diff --git a/include/drm/drm_debugfs_crc.h b/include/drm/drm_debugfs_crc.h new file mode 100644 index 000000000000..7d63b1d4adb9 --- /dev/null +++ b/include/drm/drm_debugfs_crc.h @@ -0,0 +1,73 @@ +/* + * Copyright © 2016 Collabora Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __DRM_DEBUGFS_CRC_H__ +#define __DRM_DEBUGFS_CRC_H__ + +#define DRM_MAX_CRC_NR 10 + +/** + * struct drm_crtc_crc_entry - entry describing a frame's content + * @has_frame_counter: whether the source was able to provide a frame number + * @frame: number of the frame this CRC is about, if @has_frame_counter is true + * @crc: array of values that characterize the frame + */ +struct drm_crtc_crc_entry { + bool has_frame_counter; + uint32_t frame; + uint32_t crcs[DRM_MAX_CRC_NR]; +}; + +#define DRM_CRC_ENTRIES_NR 128 + +/** + * struct drm_crtc_crc - data supporting CRC capture on a given CRTC + * @lock: protects the fields in this struct + * @source: name of the currently configured source of CRCs + * @opened: whether userspace has opened the data file for reading + * @entries: array of entries, with size of %DRM_CRC_ENTRIES_NR + * @head: head of circular queue + * @tail: tail of circular queue + * @values_cnt: number of CRC values per entry, up to %DRM_MAX_CRC_NR + * @wq: workqueue used to synchronize reading and writing + */ +struct drm_crtc_crc { + spinlock_t lock; + const char *source; + bool opened; + struct drm_crtc_crc_entry *entries; + int head, tail; + size_t values_cnt; + wait_queue_head_t wq; +}; + +#if defined(CONFIG_DEBUG_FS) +int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, + uint32_t frame, uint32_t *crcs); +#else +static inline int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, + uint32_t frame, uint32_t *crcs) +{ + return -EINVAL; +} +#endif /* defined(CONFIG_DEBUG_FS) */ + +#endif /* __DRM_DEBUGFS_CRC_H__ */ -- cgit v1.2.3 From dc30c35be720aa7c62bd9fa4d506be2d686e9165 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 16 Oct 2016 19:56:49 +0200 Subject: net: dsa: mv88e6xxx: Implement interrupt support. The switch can have up to two interrupt controllers. One of these contains the interrupts from the integrated PHYs, so is useful to export. The Marvell PHY driver can then be used in interrupt mode, rather than polling, speeding up PHY handling and reducing load on the MDIO bus. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- .../devicetree/bindings/net/dsa/marvell.txt | 21 +- drivers/net/dsa/mv88e6xxx/chip.c | 248 ++++++++++++++++++++- drivers/net/dsa/mv88e6xxx/global2.c | 139 +++++++++++- drivers/net/dsa/mv88e6xxx/global2.h | 11 + drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 31 +++ 5 files changed, 438 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt index 7629189398aa..32025eb4b31b 100644 --- a/Documentation/devicetree/bindings/net/dsa/marvell.txt +++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt @@ -20,16 +20,35 @@ Required properties: Optional properties: - reset-gpios : Should be a gpio specifier for a reset line - +- interrupt-parent : Parent interrupt controller +- interrupts : Interrupt from the switch +- interrupt-controller : Indicates the switch is itself an interrupt + controller. This is used for the PHY interrupts. +#interrupt-cells = <2> : Controller uses two cells, number and flag +- mdio : container of PHY and devices on the switches MDIO + bus Example: mdio { #address-cells = <1>; #size-cells = <0>; + interrupt-parent = <&gpio0>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <2>; switch0: switch@0 { compatible = "marvell,mv88e6085"; reg = <0>; reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>; }; + mdio { + #address-cells = <1>; + #size-cells = <0>; + switch1phy0: switch1phy0@0 { + reg = <0>; + interrupt-parent = <&switch0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; }; diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 883fd9809dd2..ac032977b16c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -18,11 +18,15 @@ #include #include #include +#include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -323,6 +327,164 @@ static int mv88e6xxx_serdes_write(struct mv88e6xxx_chip *chip, int reg, u16 val) reg, val); } +static void mv88e6xxx_g1_irq_mask(struct irq_data *d) +{ + struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); + unsigned int n = d->hwirq; + + chip->g1_irq.masked |= (1 << n); +} + +static void mv88e6xxx_g1_irq_unmask(struct irq_data *d) +{ + struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); + unsigned int n = d->hwirq; + + chip->g1_irq.masked &= ~(1 << n); +} + +static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id) +{ + struct mv88e6xxx_chip *chip = dev_id; + unsigned int nhandled = 0; + unsigned int sub_irq; + unsigned int n; + u16 reg; + int err; + + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, ®); + mutex_unlock(&chip->reg_lock); + + if (err) + goto out; + + for (n = 0; n < chip->g1_irq.nirqs; ++n) { + if (reg & (1 << n)) { + sub_irq = irq_find_mapping(chip->g1_irq.domain, n); + handle_nested_irq(sub_irq); + ++nhandled; + } + } +out: + return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); +} + +static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d) +{ + struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); + + mutex_lock(&chip->reg_lock); +} + +static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d) +{ + struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); + u16 mask = GENMASK(chip->g1_irq.nirqs, 0); + u16 reg; + int err; + + err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, ®); + if (err) + goto out; + + reg &= ~mask; + reg |= (~chip->g1_irq.masked & mask); + + err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg); + if (err) + goto out; + +out: + mutex_unlock(&chip->reg_lock); +} + +static struct irq_chip mv88e6xxx_g1_irq_chip = { + .name = "mv88e6xxx-g1", + .irq_mask = mv88e6xxx_g1_irq_mask, + .irq_unmask = mv88e6xxx_g1_irq_unmask, + .irq_bus_lock = mv88e6xxx_g1_irq_bus_lock, + .irq_bus_sync_unlock = mv88e6xxx_g1_irq_bus_sync_unlock, +}; + +static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d, + unsigned int irq, + irq_hw_number_t hwirq) +{ + struct mv88e6xxx_chip *chip = d->host_data; + + irq_set_chip_data(irq, d->host_data); + irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq); + irq_set_noprobe(irq); + + return 0; +} + +static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = { + .map = mv88e6xxx_g1_irq_domain_map, + .xlate = irq_domain_xlate_twocell, +}; + +static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip) +{ + int irq, virq; + + for (irq = 0; irq < 16; irq++) { + virq = irq_find_mapping(chip->g2_irq.domain, irq); + irq_dispose_mapping(virq); + } + + irq_domain_remove(chip->g2_irq.domain); +} + +static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip) +{ + int err, irq; + u16 reg; + + chip->g1_irq.nirqs = chip->info->g1_irqs; + chip->g1_irq.domain = irq_domain_add_simple( + NULL, chip->g1_irq.nirqs, 0, + &mv88e6xxx_g1_irq_domain_ops, chip); + if (!chip->g1_irq.domain) + return -ENOMEM; + + for (irq = 0; irq < chip->g1_irq.nirqs; irq++) + irq_create_mapping(chip->g1_irq.domain, irq); + + chip->g1_irq.chip = mv88e6xxx_g1_irq_chip; + chip->g1_irq.masked = ~0; + + err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, ®); + if (err) + goto out; + + reg &= ~GENMASK(chip->g1_irq.nirqs, 0); + + err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg); + if (err) + goto out; + + /* Reading the interrupt status clears (most of) them */ + err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, ®); + if (err) + goto out; + + err = request_threaded_irq(chip->irq, NULL, + mv88e6xxx_g1_irq_thread_fn, + IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + dev_name(chip->dev), chip); + if (err) + goto out; + + return 0; + +out: + mv88e6xxx_g1_irq_free(chip); + + return err; +} + int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask) { int i; @@ -2770,7 +2932,11 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) /* Enable the PHY Polling Unit if present, don't discard any packets, * and mask all interrupt sources. */ - reg = 0; + err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, ®); + if (err < 0) + return err; + + reg &= ~GLOBAL_CONTROL_PPU_ENABLE; if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU) || mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU_ACTIVE)) reg |= GLOBAL_CONTROL_PPU_ENABLE; @@ -2875,10 +3041,6 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) mutex_lock(&chip->reg_lock); - err = mv88e6xxx_switch_reset(chip); - if (err) - goto unlock; - /* Setup Switch Port Registers */ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { err = mv88e6xxx_setup_port(chip, i); @@ -3326,6 +3488,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 8, .flags = MV88E6XXX_FLAGS_FAMILY_6097, .ops = &mv88e6085_ops, }, @@ -3339,6 +3502,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 8, .flags = MV88E6XXX_FLAGS_FAMILY_6095, .ops = &mv88e6095_ops, }, @@ -3352,6 +3516,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6165, .ops = &mv88e6123_ops, }, @@ -3365,6 +3530,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6185, .ops = &mv88e6131_ops, }, @@ -3378,6 +3544,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6165, .ops = &mv88e6161_ops, }, @@ -3391,6 +3558,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6165, .ops = &mv88e6165_ops, }, @@ -3404,6 +3572,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6351, .ops = &mv88e6171_ops, }, @@ -3417,6 +3586,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6352, .ops = &mv88e6172_ops, }, @@ -3430,6 +3600,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6351, .ops = &mv88e6175_ops, }, @@ -3443,6 +3614,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6352, .ops = &mv88e6176_ops, }, @@ -3456,6 +3628,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 8, .flags = MV88E6XXX_FLAGS_FAMILY_6185, .ops = &mv88e6185_ops, }, @@ -3469,6 +3642,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6352, .ops = &mv88e6240_ops, }, @@ -3482,6 +3656,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 8, .flags = MV88E6XXX_FLAGS_FAMILY_6320, .ops = &mv88e6320_ops, }, @@ -3495,6 +3670,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 8, .flags = MV88E6XXX_FLAGS_FAMILY_6320, .ops = &mv88e6321_ops, }, @@ -3508,6 +3684,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6351, .ops = &mv88e6350_ops, }, @@ -3521,6 +3698,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6351, .ops = &mv88e6351_ops, }, @@ -3534,6 +3712,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x10, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6352, .ops = &mv88e6352_ops, }, @@ -3667,6 +3846,12 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev, if (err) goto free; + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_switch_reset(chip); + mutex_unlock(&chip->reg_lock); + if (err) + goto free; + mv88e6xxx_phy_init(chip); err = mv88e6xxx_mdio_register(chip, NULL); @@ -3837,17 +4022,56 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) !of_property_read_u32(np, "eeprom-length", &eeprom_len)) chip->eeprom_len = eeprom_len; + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_switch_reset(chip); + mutex_unlock(&chip->reg_lock); + if (err) + goto out; + + chip->irq = of_irq_get(np, 0); + if (chip->irq == -EPROBE_DEFER) { + err = chip->irq; + goto out; + } + + if (chip->irq > 0) { + /* Has to be performed before the MDIO bus is created, + * because the PHYs will link there interrupts to these + * interrupt controllers + */ + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_g1_irq_setup(chip); + mutex_unlock(&chip->reg_lock); + + if (err) + goto out; + + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) { + err = mv88e6xxx_g2_irq_setup(chip); + if (err) + goto out_g1_irq; + } + } + err = mv88e6xxx_mdio_register(chip, np); if (err) - return err; + goto out_g2_irq; err = mv88e6xxx_register_switch(chip, np); - if (err) { - mv88e6xxx_mdio_unregister(chip); - return err; - } + if (err) + goto out_mdio; return 0; + +out_mdio: + mv88e6xxx_mdio_unregister(chip); +out_g2_irq: + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) + mv88e6xxx_g2_irq_free(chip); +out_g1_irq: + mv88e6xxx_g1_irq_free(chip); +out: + return err; } static void mv88e6xxx_remove(struct mdio_device *mdiodev) @@ -3858,6 +4082,10 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) mv88e6xxx_phy_destroy(chip); mv88e6xxx_unregister_switch(chip); mv88e6xxx_mdio_unregister(chip); + + if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) + mv88e6xxx_g2_irq_free(chip); + mv88e6xxx_g1_irq_free(chip); } static const struct of_device_id mv88e6xxx_of_match[] = { diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index cf686e7506a9..1a0b13521d13 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -1,5 +1,6 @@ /* - * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C) + * Marvell 88E6xxx Switch Global 2 Registers support (device address + * 0x1C) * * Copyright (c) 2008 Marvell Semiconductor * @@ -11,6 +12,7 @@ * (at your option) any later version. */ +#include #include "mv88e6xxx.h" #include "global2.h" @@ -417,6 +419,141 @@ int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg, return mv88e6xxx_g2_smi_phy_cmd(chip, cmd); } +static void mv88e6xxx_g2_irq_mask(struct irq_data *d) +{ + struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); + unsigned int n = d->hwirq; + + chip->g2_irq.masked |= (1 << n); +} + +static void mv88e6xxx_g2_irq_unmask(struct irq_data *d) +{ + struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); + unsigned int n = d->hwirq; + + chip->g2_irq.masked &= ~(1 << n); +} + +static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id) +{ + struct mv88e6xxx_chip *chip = dev_id; + unsigned int nhandled = 0; + unsigned int sub_irq; + unsigned int n; + int err; + u16 reg; + + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, ®); + mutex_unlock(&chip->reg_lock); + if (err) + goto out; + + for (n = 0; n < 16; ++n) { + if (reg & (1 << n)) { + sub_irq = irq_find_mapping(chip->g2_irq.domain, n); + handle_nested_irq(sub_irq); + ++nhandled; + } + } +out: + return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); +} + +static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d) +{ + struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); + + mutex_lock(&chip->reg_lock); +} + +static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d) +{ + struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); + + mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked); + + mutex_unlock(&chip->reg_lock); +} + +static struct irq_chip mv88e6xxx_g2_irq_chip = { + .name = "mv88e6xxx-g2", + .irq_mask = mv88e6xxx_g2_irq_mask, + .irq_unmask = mv88e6xxx_g2_irq_unmask, + .irq_bus_lock = mv88e6xxx_g2_irq_bus_lock, + .irq_bus_sync_unlock = mv88e6xxx_g2_irq_bus_sync_unlock, +}; + +static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d, + unsigned int irq, + irq_hw_number_t hwirq) +{ + struct mv88e6xxx_chip *chip = d->host_data; + + irq_set_chip_data(irq, d->host_data); + irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq); + irq_set_noprobe(irq); + + return 0; +} + +static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = { + .map = mv88e6xxx_g2_irq_domain_map, + .xlate = irq_domain_xlate_twocell, +}; + +void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip) +{ + int irq, virq; + + for (irq = 0; irq < 16; irq++) { + virq = irq_find_mapping(chip->g2_irq.domain, irq); + irq_dispose_mapping(virq); + } + + irq_domain_remove(chip->g2_irq.domain); +} + +int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) +{ + int device_irq; + int err, irq; + + if (!chip->dev->of_node) + return -EINVAL; + + chip->g2_irq.domain = irq_domain_add_simple( + chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip); + if (!chip->g2_irq.domain) + return -ENOMEM; + + for (irq = 0; irq < 16; irq++) + irq_create_mapping(chip->g2_irq.domain, irq); + + chip->g2_irq.chip = mv88e6xxx_g2_irq_chip; + chip->g2_irq.masked = ~0; + + device_irq = irq_find_mapping(chip->g1_irq.domain, + GLOBAL_STATUS_IRQ_DEVICE); + if (device_irq < 0) { + err = device_irq; + goto out; + } + + err = devm_request_threaded_irq(chip->dev, device_irq, NULL, + mv88e6xxx_g2_irq_thread_fn, + IRQF_ONESHOT, "mv88e6xxx-g1", chip); + if (err) + goto out; + + return 0; +out: + mv88e6xxx_g2_irq_free(chip); + + return err; +} + int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) { u16 reg; diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index c4bb9035ee3a..1eb3ddd21551 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -33,6 +33,8 @@ int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip, int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, struct ethtool_eeprom *eeprom, u8 *data); int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip); +int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip); +void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip); #else /* !CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */ @@ -83,6 +85,15 @@ static inline int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) return -EOPNOTSUPP; } +static inline int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) +{ + return -EOPNOTSUPP; +} + +static inline void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip) +{ +} + #endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */ #endif /* _MV88E6XXX_GLOBAL2_H */ diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index e572121c196e..6f48e5886b2a 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -13,6 +13,7 @@ #define __MV88E6XXX_H #include +#include #include #ifndef UINT64_MAX @@ -167,6 +168,15 @@ #define GLOBAL_STATUS_PPU_INITIALIZING (0x1 << 14) #define GLOBAL_STATUS_PPU_DISABLED (0x2 << 14) #define GLOBAL_STATUS_PPU_POLLING (0x3 << 14) +#define GLOBAL_STATUS_IRQ_AVB 8 +#define GLOBAL_STATUS_IRQ_DEVICE 7 +#define GLOBAL_STATUS_IRQ_STATS 6 +#define GLOBAL_STATUS_IRQ_VTU_PROBLEM 5 +#define GLOBAL_STATUS_IRQ_VTU_DONE 4 +#define GLOBAL_STATUS_IRQ_ATU_PROBLEM 3 +#define GLOBAL_STATUS_IRQ_ATU_DONE 2 +#define GLOBAL_STATUS_IRQ_TCAM_DONE 1 +#define GLOBAL_STATUS_IRQ_EEPROM_DONE 0 #define GLOBAL_MAC_01 0x01 #define GLOBAL_MAC_23 0x02 #define GLOBAL_MAC_45 0x03 @@ -417,6 +427,7 @@ enum mv88e6xxx_cap { * The device contains a second set of global 16-bit registers. */ MV88E6XXX_CAP_GLOBAL2, + MV88E6XXX_CAP_G2_INT, /* (0x00) Interrupt Status */ MV88E6XXX_CAP_G2_MGMT_EN_2X, /* (0x02) MGMT Enable Register 2x */ MV88E6XXX_CAP_G2_MGMT_EN_0X, /* (0x03) MGMT Enable Register 0x */ MV88E6XXX_CAP_G2_IRL_CMD, /* (0x09) Ingress Rate Command */ @@ -464,6 +475,7 @@ enum mv88e6xxx_cap { #define MV88E6XXX_FLAG_G1_VTU_FID BIT_ULL(MV88E6XXX_CAP_G1_VTU_FID) #define MV88E6XXX_FLAG_GLOBAL2 BIT_ULL(MV88E6XXX_CAP_GLOBAL2) +#define MV88E6XXX_FLAG_G2_INT BIT_ULL(MV88E6XXX_CAP_G2_INT) #define MV88E6XXX_FLAG_G2_MGMT_EN_2X BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_2X) #define MV88E6XXX_FLAG_G2_MGMT_EN_0X BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_0X) #define MV88E6XXX_FLAG_G2_IRL_CMD BIT_ULL(MV88E6XXX_CAP_G2_IRL_CMD) @@ -524,6 +536,7 @@ enum mv88e6xxx_cap { (MV88E6XXX_FLAG_G1_ATU_FID | \ MV88E6XXX_FLAG_G1_VTU_FID | \ MV88E6XXX_FLAG_GLOBAL2 | \ + MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_POT | \ @@ -536,6 +549,7 @@ enum mv88e6xxx_cap { #define MV88E6XXX_FLAGS_FAMILY_6185 \ (MV88E6XXX_FLAG_GLOBAL2 | \ + MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAGS_MULTI_CHIP | \ MV88E6XXX_FLAG_PPU | \ @@ -561,6 +575,7 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_G1_ATU_FID | \ MV88E6XXX_FLAG_G1_VTU_FID | \ MV88E6XXX_FLAG_GLOBAL2 | \ + MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_POT | \ @@ -578,6 +593,7 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_G1_ATU_FID | \ MV88E6XXX_FLAG_G1_VTU_FID | \ MV88E6XXX_FLAG_GLOBAL2 | \ + MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_POT | \ @@ -602,6 +618,7 @@ struct mv88e6xxx_info { unsigned int port_base_addr; unsigned int global1_addr; unsigned int age_time_coeff; + unsigned int g1_irqs; unsigned long long flags; const struct mv88e6xxx_ops *ops; }; @@ -628,6 +645,13 @@ struct mv88e6xxx_priv_port { struct net_device *bridge_dev; }; +struct mv88e6xxx_irq { + u16 masked; + struct irq_chip chip; + struct irq_domain *domain; + unsigned int nirqs; +}; + struct mv88e6xxx_chip { const struct mv88e6xxx_info *info; @@ -677,6 +701,13 @@ struct mv88e6xxx_chip { /* And the MDIO bus itself */ struct mii_bus *mdio_bus; + + /* There can be two interrupt controllers, which are chained + * off a GPIO as interrupt source + */ + struct mv88e6xxx_irq g1_irq; + struct mv88e6xxx_irq g2_irq; + int irq; }; struct mv88e6xxx_bus_ops { -- cgit v1.2.3 From c974bdbc3e7734e72d6347afc49f806342578e75 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 16 Oct 2016 19:56:50 +0200 Subject: net: phy: Use threaded IRQ, to allow IRQ from sleeping devices The interrupt lines from PHYs maybe connected to I2C bus expanders, or from switches on MDIO busses. Such interrupts are sourced from devices which sleep, so use threaded interrupts. Threaded interrupts require that the interrupt requester also uses the threaded API. Change the phylib to use the threaded API, which is backwards compatible with none-threaded IRQs. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index f424b867f73e..25f2b296aaba 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -739,10 +739,10 @@ phy_err: int phy_start_interrupts(struct phy_device *phydev) { atomic_set(&phydev->irq_disable, 0); - if (request_irq(phydev->irq, phy_interrupt, - IRQF_SHARED, - "phy_interrupt", - phydev) < 0) { + if (request_threaded_irq(phydev->irq, NULL, phy_interrupt, + IRQF_ONESHOT | IRQF_SHARED, + "phy_interrupt", + phydev) < 0) { pr_warn("%s: Can't get IRQ %d (PHY)\n", phydev->mdio.bus->name, phydev->irq); phydev->irq = PHY_POLL; -- cgit v1.2.3 From 664fcf123a30edf16b47d2ce1f610d654ba917b2 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 16 Oct 2016 19:56:51 +0200 Subject: net: phy: Threaded interrupts allow some simplification The PHY interrupts are now handled in a threaded interrupt handler, which can sleep. The work queue is no longer needed, phy_change() can be called directly. phy_mac_interrupt() still needs to be safe to call in interrupt context, so keep the work queue, and use a helper to call phy_change(). Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 45 +++++++++++++++++++++++++------------------- drivers/net/phy/phy_device.c | 2 +- include/linux/phy.h | 5 +++-- 3 files changed, 30 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 25f2b296aaba..bb673c63c85c 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -664,7 +664,7 @@ static void phy_error(struct phy_device *phydev) * @phy_dat: phy_device pointer * * Description: When a PHY interrupt occurs, the handler disables - * interrupts, and schedules a work task to clear the interrupt. + * interrupts, and uses phy_change to handle the interrupt. */ static irqreturn_t phy_interrupt(int irq, void *phy_dat) { @@ -673,15 +673,10 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) if (PHY_HALTED == phydev->state) return IRQ_NONE; /* It can't be ours. */ - /* The MDIO bus is not allowed to be written in interrupt - * context, so we need to disable the irq here. A work - * queue will write the PHY to disable and clear the - * interrupt, and then reenable the irq line. - */ disable_irq_nosync(irq); atomic_inc(&phydev->irq_disable); - queue_work(system_power_efficient_wq, &phydev->phy_queue); + phy_change(phydev); return IRQ_HANDLED; } @@ -766,12 +761,6 @@ int phy_stop_interrupts(struct phy_device *phydev) free_irq(phydev->irq, phydev); - /* Cannot call flush_scheduled_work() here as desired because - * of rtnl_lock(), but we do not really care about what would - * be done, except from enable_irq(), so cancel any work - * possibly pending and take care of the matter below. - */ - cancel_work_sync(&phydev->phy_queue); /* If work indeed has been cancelled, disable_irq() will have * been left unbalanced from phy_interrupt() and enable_irq() * has to be called so that other devices on the line work. @@ -784,14 +773,11 @@ int phy_stop_interrupts(struct phy_device *phydev) EXPORT_SYMBOL(phy_stop_interrupts); /** - * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes - * @work: work_struct that describes the work to be done + * phy_change - Called by the phy_interrupt to handle PHY changes + * @phydev: phy_device struct that interrupted */ -void phy_change(struct work_struct *work) +void phy_change(struct phy_device *phydev) { - struct phy_device *phydev = - container_of(work, struct phy_device, phy_queue); - if (phy_interrupt_is_valid(phydev)) { if (phydev->drv->did_interrupt && !phydev->drv->did_interrupt(phydev)) @@ -832,6 +818,18 @@ phy_err: phy_error(phydev); } +/** + * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes + * @work: work_struct that describes the work to be done + */ +void phy_change_work(struct work_struct *work) +{ + struct phy_device *phydev = + container_of(work, struct phy_device, phy_queue); + + phy_change(phydev); +} + /** * phy_stop - Bring down the PHY link, and stop checking the status * @phydev: target phy_device struct @@ -1116,6 +1114,15 @@ void phy_state_machine(struct work_struct *work) PHY_STATE_TIME * HZ); } +/** + * phy_mac_interrupt - MAC says the link has changed + * @phydev: phy_device struct with changed link + * @new_link: Link is Up/Down. + * + * Description: The MAC layer is able indicate there has been a change + * in the PHY link status. Set the new link status, and trigger the + * state machine, work a work queue. + */ void phy_mac_interrupt(struct phy_device *phydev, int new_link) { phydev->link = new_link; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e977ba931878..ac440a815353 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -347,7 +347,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, mutex_init(&dev->lock); INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); - INIT_WORK(&dev->phy_queue, phy_change); + INIT_WORK(&dev->phy_queue, phy_change_work); /* Request the appropriate module unconditionally; don't * bother trying to do so only if it isn't already loaded, diff --git a/include/linux/phy.h b/include/linux/phy.h index e25f1830fbcf..c47378c93607 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -343,7 +343,7 @@ struct phy_c45_device_ids { * giving up on the current attempt at acquiring a link * irq: IRQ number of the PHY's interrupt (-1 if none) * phy_timer: The timer for handling the state machine - * phy_queue: A work_queue for the interrupt + * phy_queue: A work_queue for the phy_mac_interrupt * attached_dev: The attached enet driver's device instance ptr * adjust_link: Callback for the enet controller to respond to * changes in the link state. @@ -802,7 +802,8 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner); int phy_drivers_register(struct phy_driver *new_driver, int n, struct module *owner); void phy_state_machine(struct work_struct *work); -void phy_change(struct work_struct *work); +void phy_change(struct phy_device *phydev); +void phy_change_work(struct work_struct *work); void phy_mac_interrupt(struct phy_device *phydev, int new_link); void phy_start_machine(struct phy_device *phydev); void phy_stop_machine(struct phy_device *phydev); -- cgit v1.2.3 From ae0219cb441cf5f471feb90961b1e93a91ba6db6 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 16 Oct 2016 19:56:52 +0200 Subject: net: phy: Use phy name when requesting the interrupt Using the fixed name "phy_interrupt" is not very informative in /proc/interrupts when there are a lot of phys, e.g. a device with an Ethernet switch. So when requesting the interrupt, use the name of the phy. Signed-off-by: Andrew Lunn Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index bb673c63c85c..96bf03352bb8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -736,8 +736,7 @@ int phy_start_interrupts(struct phy_device *phydev) atomic_set(&phydev->irq_disable, 0); if (request_threaded_irq(phydev->irq, NULL, phy_interrupt, IRQF_ONESHOT | IRQF_SHARED, - "phy_interrupt", - phydev) < 0) { + phydev_name(phydev), phydev) < 0) { pr_warn("%s: Can't get IRQ %d (PHY)\n", phydev->mdio.bus->name, phydev->irq); phydev->irq = PHY_POLL; -- cgit v1.2.3 From bc4725d9029e2c8205fbaf1105e193d1c4e463bb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 3 Oct 2016 13:03:38 +0200 Subject: clk: renesas: cpg-mssr: Fix inverted debug check The intention was to enable the checks if debugging is enabled, not disabled. Fixes: f793d1e51705b276 ("clk: shmobile: Add new CPG/MSSR driver core") Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index a1d5b7431ec4..057bb8759e38 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -33,9 +33,9 @@ #include "clk-div6.h" #ifdef DEBUG -#define WARN_DEBUG(x) do { } while (0) -#else #define WARN_DEBUG(x) WARN_ON(x) +#else +#define WARN_DEBUG(x) do { } while (0) #endif -- cgit v1.2.3 From 396a3529800af0817c6af2eb65c542588a1f7fb7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 19 Sep 2016 10:43:17 +0200 Subject: pinctrl: bcm2835: add pull defines to dt bindings Also delete (unused) private enum from driver. The pull defines can be used instead if needed. Signed-off-by: Gerd Hoffmann Signed-off-by: Eric Anholt Acked-by: Linus Walleij Acked-by: Stefan Wahren --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 6 ------ include/dt-bindings/pinctrl/bcm2835.h | 5 +++++ 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index fa77165fab2c..4cf612bcfdfa 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -76,12 +76,6 @@ enum bcm2835_pinconf_param { BCM2835_PINCONF_PARAM_PULL, }; -enum bcm2835_pinconf_pull { - BCM2835_PINCONFIG_PULL_NONE, - BCM2835_PINCONFIG_PULL_DOWN, - BCM2835_PINCONFIG_PULL_UP, -}; - #define BCM2835_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_)) #define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16) #define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff) diff --git a/include/dt-bindings/pinctrl/bcm2835.h b/include/dt-bindings/pinctrl/bcm2835.h index 6f0bc37af39c..e4e4fdf5d38f 100644 --- a/include/dt-bindings/pinctrl/bcm2835.h +++ b/include/dt-bindings/pinctrl/bcm2835.h @@ -24,4 +24,9 @@ #define BCM2835_FSEL_ALT2 6 #define BCM2835_FSEL_ALT3 7 +/* brcm,pull property */ +#define BCM2835_PUD_OFF 0 +#define BCM2835_PUD_DOWN 1 +#define BCM2835_PUD_UP 2 + #endif /* __DT_BINDINGS_PINCTRL_BCM2835_H__ */ -- cgit v1.2.3 From b2cdeb19f16ad984eb5bb9193f793d05a8101511 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 13 Oct 2016 11:54:31 +0300 Subject: drm/vc4: Fix a couple error codes in vc4_cl_lookup_bos() If the allocation fails the current code returns success. If copy_from_user() fails it returns the number of bytes remaining instead of -EFAULT. Fixes: d5b1a78a772f ("drm/vc4: Add support for drawing 3D frames.") Signed-off-by: Dan Carpenter Reviewed-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_gem.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 47a095f392f8..303f23c96220 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -544,14 +544,15 @@ vc4_cl_lookup_bos(struct drm_device *dev, handles = drm_malloc_ab(exec->bo_count, sizeof(uint32_t)); if (!handles) { + ret = -ENOMEM; DRM_ERROR("Failed to allocate incoming GEM handles\n"); goto fail; } - ret = copy_from_user(handles, - (void __user *)(uintptr_t)args->bo_handles, - exec->bo_count * sizeof(uint32_t)); - if (ret) { + if (copy_from_user(handles, + (void __user *)(uintptr_t)args->bo_handles, + exec->bo_count * sizeof(uint32_t))) { + ret = -EFAULT; DRM_ERROR("Failed to copy in GEM handles\n"); goto fail; } -- cgit v1.2.3 From b156b7f2169bb4d963a2432ff03319fe7d64b823 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 13:19:37 -0300 Subject: mtd: nand: omap2: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/mtd/nand/omap2_nand.ko | grep alias alias: platform:omap2-nand After this patch: $ modinfo drivers/mtd/nand/omap2_nand.ko | grep alias alias: platform:omap2-nand alias: of:N*T*Cti,omap2-nandC* alias: of:N*T*Cti,omap2-nand Signed-off-by: Javier Martinez Canillas Signed-off-by: Boris Brezillon --- drivers/mtd/nand/omap2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 5513bfd9cdc9..0934c3b3f70e 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -2197,6 +2197,7 @@ static const struct of_device_id omap_nand_ids[] = { { .compatible = "ti,omap2-nand", }, {}, }; +MODULE_DEVICE_TABLE(of, omap_nand_ids); static struct platform_driver omap_nand_driver = { .probe = omap_nand_probe, -- cgit v1.2.3 From ea939008c2d7cade2cbedea5dcbd689e4415f3ed Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 17 Oct 2016 16:30:57 +0200 Subject: fjes: fix format string for trace output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit phys_addr_t may be wider than a pointer and has to be printed using the special %pap format string, as pointed out by this new warning. arch/x86/include/../../../drivers/net/fjes/fjes_trace.h: In function ‘trace_raw_output_fjes_hw_start_debug_req’: arch/x86/include/../../../drivers/net/fjes/fjes_trace.h:212:563: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] Note that this has to pass the address by reference instead of casting it to a different type. Fixes: b6ba737d0b29 ("fjes: ethtool -w and -W support for fjes driver") Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fjes/fjes_trace.h b/drivers/net/fjes/fjes_trace.h index 22e8f1a4f9ee..cca01a1b3d64 100644 --- a/drivers/net/fjes/fjes_trace.h +++ b/drivers/net/fjes/fjes_trace.h @@ -222,8 +222,8 @@ TRACE_EVENT(fjes_hw_start_debug_req, __entry->mode = req_buf->start_trace.mode; __entry->buffer = req_buf->start_trace.buffer[0]; ), - TP_printk("req_buf=[length=%d, mode=%d, buffer=%p]", - __entry->length, __entry->mode, (void *)__entry->buffer) + TP_printk("req_buf=[length=%d, mode=%d, buffer=%pap]", + __entry->length, __entry->mode, &__entry->buffer) ); TRACE_EVENT(fjes_hw_start_debug, -- cgit v1.2.3 From ca8eddc2759c949940720b5dc347e93bc981f5f2 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 17 Oct 2016 15:31:58 +0000 Subject: net: ethernet: nb8800: fix error return code in nb8800_open() Fix to return error code -ENODEV from the of_phy_connect() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Mans Rullgard Signed-off-by: David S. Miller --- drivers/net/ethernet/aurora/nb8800.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c index 453dc0967125..99c40552ea90 100644 --- a/drivers/net/ethernet/aurora/nb8800.c +++ b/drivers/net/ethernet/aurora/nb8800.c @@ -975,8 +975,10 @@ static int nb8800_open(struct net_device *dev) phydev = of_phy_connect(dev, priv->phy_node, nb8800_link_reconfigure, 0, priv->phy_mode); - if (!phydev) + if (!phydev) { + err = -ENODEV; goto err_free_irq; + } nb8800_pause_adv(dev); -- cgit v1.2.3 From 3f3177bb680fc08300e6f2341f44755ff90a358a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 17 Oct 2016 15:19:56 +0000 Subject: fsl/fman: fix error return code in mac_probe() Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function. Fixes: 3933961682a3 ("fsl/fman: Add FMan MAC driver") Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fman/mac.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index 8fe6b3e253fa..cc5d07cfe535 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -879,13 +879,17 @@ static int mac_probe(struct platform_device *_of_dev) priv->fixed_link = kzalloc(sizeof(*priv->fixed_link), GFP_KERNEL); - if (!priv->fixed_link) + if (!priv->fixed_link) { + err = -ENOMEM; goto _return_dev_set_drvdata; + } priv->phy_node = of_node_get(mac_node); phy = of_phy_find_device(priv->phy_node); - if (!phy) + if (!phy) { + err = -EINVAL; goto _return_dev_set_drvdata; + } priv->fixed_link->link = phy->link; priv->fixed_link->speed = phy->speed; -- cgit v1.2.3 From 29676833df1d9207cb665fe9869f6778a96045b9 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 28 Sep 2016 16:30:56 +0100 Subject: power: reset: Add Intel PIIX4 poweroff driver Add a driver which allows powering off the system via an Intel PIIX4 southbridge, by entering the PIIX4 SOff state. This is useful on the MIPS Malta development board, where it will power down the FPGA based board until its ON/NMI button is pressed, or the QEMU implementation of the MIPS Malta board where it will cause QEMU to exit. Signed-off-by: Paul Burton Cc: Sebastian Reichel Cc: Dmitry Eremin-Solenikov Cc: David Woodhouse Cc: linux-pm@vger.kernel.org Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 10 ++++ drivers/power/reset/Makefile | 1 + drivers/power/reset/piix4-poweroff.c | 113 +++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 drivers/power/reset/piix4-poweroff.c (limited to 'drivers') diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index c74c3f67b8da..abeb77217a21 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -104,6 +104,16 @@ config POWER_RESET_MSM help Power off and restart support for Qualcomm boards. +config POWER_RESET_PIIX4_POWEROFF + tristate "Intel PIIX4 power-off driver" + depends on PCI + depends on MIPS || COMPILE_TEST + help + This driver supports powering off a system using the Intel PIIX4 + southbridge, for example the MIPS Malta development board. The + southbridge SOff state is entered in response to a request to + power off the system. + config POWER_RESET_LTC2952 bool "LTC2952 PowerPath power-off driver" depends on OF_GPIO diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 1be307c7fc25..11dae3b56ff9 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o +obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o diff --git a/drivers/power/reset/piix4-poweroff.c b/drivers/power/reset/piix4-poweroff.c new file mode 100644 index 000000000000..bacfc95783f0 --- /dev/null +++ b/drivers/power/reset/piix4-poweroff.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2016 Imagination Technologies + * Author: Paul Burton + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include + +static struct pci_dev *pm_dev; +static resource_size_t io_offset; + +enum piix4_pm_io_reg { + PIIX4_FUNC3IO_PMSTS = 0x00, +#define PIIX4_FUNC3IO_PMSTS_PWRBTN_STS BIT(8) + PIIX4_FUNC3IO_PMCNTRL = 0x04, +#define PIIX4_FUNC3IO_PMCNTRL_SUS_EN BIT(13) +#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF (0x0 << 10) +}; + +#define PIIX4_SUSPEND_MAGIC 0x00120002 + +static const int piix4_pm_io_region = PCI_BRIDGE_RESOURCES; + +static void piix4_poweroff(void) +{ + int spec_devid; + u16 sts; + + /* Ensure the power button status is clear */ + while (1) { + sts = inw(io_offset + PIIX4_FUNC3IO_PMSTS); + if (!(sts & PIIX4_FUNC3IO_PMSTS_PWRBTN_STS)) + break; + outw(sts, io_offset + PIIX4_FUNC3IO_PMSTS); + } + + /* Enable entry to suspend */ + outw(PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF | PIIX4_FUNC3IO_PMCNTRL_SUS_EN, + io_offset + PIIX4_FUNC3IO_PMCNTRL); + + /* If the special cycle occurs too soon this doesn't work... */ + mdelay(10); + + /* + * The PIIX4 will enter the suspend state only after seeing a special + * cycle with the correct magic data on the PCI bus. Generate that + * cycle now. + */ + spec_devid = PCI_DEVID(0, PCI_DEVFN(0x1f, 0x7)); + pci_bus_write_config_dword(pm_dev->bus, spec_devid, 0, + PIIX4_SUSPEND_MAGIC); + + /* Give the system some time to power down, then error */ + mdelay(1000); + pr_emerg("Unable to poweroff system\n"); +} + +static int piix4_poweroff_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + int res; + + if (pm_dev) + return -EINVAL; + + /* Request access to the PIIX4 PM IO registers */ + res = pci_request_region(dev, piix4_pm_io_region, + "PIIX4 PM IO registers"); + if (res) { + dev_err(&dev->dev, "failed to request PM IO registers: %d\n", + res); + return res; + } + + pm_dev = dev; + io_offset = pci_resource_start(dev, piix4_pm_io_region); + pm_power_off = piix4_poweroff; + + return 0; +} + +static void piix4_poweroff_remove(struct pci_dev *dev) +{ + if (pm_power_off == piix4_poweroff) + pm_power_off = NULL; + + pci_release_region(dev, piix4_pm_io_region); + pm_dev = NULL; +} + +static const struct pci_device_id piix4_poweroff_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) }, + { 0 }, +}; + +static struct pci_driver piix4_poweroff_driver = { + .name = "piix4-poweroff", + .id_table = piix4_poweroff_ids, + .probe = piix4_poweroff_probe, + .remove = piix4_poweroff_remove, +}; + +module_pci_driver(piix4_poweroff_driver); +MODULE_AUTHOR("Paul Burton "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 1140f9ed051011e06a2a15c73efe57ac0b0cdc8d Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 18 Oct 2016 09:40:07 +0800 Subject: drm/i915/gvt: Fix build failure after intel_engine_cs change Change GVT-g code reference for intel_engine_cs from static array to allocated pointer after commit 3b3f1650b1ca ("drm/i915: Allocate intel_engine_cs structure only for the enabled engines"). Signed-off-by: Zhenyu Wang Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161018014007.29369-1-zhenyuw@linux.intel.com --- drivers/gpu/drm/i915/gvt/execlist.c | 2 +- drivers/gpu/drm/i915/gvt/handlers.c | 2 +- drivers/gpu/drm/i915/gvt/scheduler.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 4a00ee7ff020..c50a3d1a5131 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -39,7 +39,7 @@ #define _EL_OFFSET_STATUS_PTR 0x3A0 #define execlist_ring_mmio(gvt, ring_id, offset) \ - (gvt->dev_priv->engine[ring_id].mmio_base + (offset)) + (gvt->dev_priv->engine[ring_id]->mmio_base + (offset)) #define valid_context(ctx) ((ctx)->valid) #define same_context(a, b) (((a)->context_id == (b)->context_id) && \ diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index d59a934b6e32..e8ec403b75a1 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -134,7 +134,7 @@ static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg) reg &= ~GENMASK(11, 0); for (i = 0; i < I915_NUM_ENGINES; i++) { - if (gvt->dev_priv->engine[i].mmio_base == reg) + if (gvt->dev_priv->engine[i]->mmio_base == reg) return i; } return -1; diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 732672b7d22b..b15cdf5978a9 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -68,7 +68,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) workload->ctx_desc.lrca); context_page_num = intel_lr_context_size( - &gvt->dev_priv->engine[ring_id]); + gvt->dev_priv->engine[ring_id]); context_page_num = context_page_num >> PAGE_SHIFT; @@ -171,7 +171,7 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) shadow_ctx->desc_template = workload->ctx_desc.addressing_mode << GEN8_CTX_ADDRESSING_MODE_SHIFT; - workload->req = i915_gem_request_alloc(&dev_priv->engine[ring_id], + workload->req = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); if (IS_ERR_OR_NULL(workload->req)) { gvt_err("fail to allocate gem request\n"); @@ -298,7 +298,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload) workload->ctx_desc.lrca); context_page_num = intel_lr_context_size( - &gvt->dev_priv->engine[ring_id]); + gvt->dev_priv->engine[ring_id]); context_page_num = context_page_num >> PAGE_SHIFT; -- cgit v1.2.3 From a758c9b93f5c4e826b3c0849c96c630b1cce8f8d Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Mon, 19 Sep 2016 21:12:12 +0200 Subject: clk: pxa25x: OSTIMER0 clocks from the main oscillator The OSTIMER0 clock ticks at the main oscillator rate, not the 32kHz oscillator rate. Ensure that it is parented to the main oscillator. Signed-off-by: Russell King Acked-by: Stephen Boyd Tested-by: Robert Jarzmik Signed-off-by: Robert Jarzmik --- drivers/clk/pxa/clk-pxa25x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c index a98b98e2a9e4..56b0a6027e38 100644 --- a/drivers/clk/pxa/clk-pxa25x.c +++ b/drivers/clk/pxa/clk-pxa25x.c @@ -230,7 +230,7 @@ static struct dummy_clk dummy_clks[] __initdata = { DUMMY_CLK("GPIO11_CLK", NULL, "osc_3_6864mhz"), DUMMY_CLK("GPIO12_CLK", NULL, "osc_32_768khz"), DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"), - DUMMY_CLK("OSTIMER0", NULL, "osc_32_768khz"), + DUMMY_CLK("OSTIMER0", NULL, "osc_3_6864mhz"), DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"), }; -- cgit v1.2.3 From f4e14edf25661f32c9e7323d8a482b8632a6f47f Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 19 Sep 2016 21:12:13 +0200 Subject: ARM: sa11x0/pxa: acquire timer rate from the clock rate As both pxa and sa1100 provide a clock to the timer, the rate can be inferred from the clock rather than hard encoded in a functional call. This patch changes the pxa timer to have a mandatory clock which is used as the timer rate. Signed-off-by: Robert Jarzmik Acked-by: Daniel Lezcano Acked-by: Russell King --- arch/arm/mach-pxa/generic.c | 3 +-- arch/arm/mach-sa1100/generic.c | 2 +- drivers/clocksource/pxa_timer.c | 11 +++++------ include/clocksource/pxa.h | 3 +-- 4 files changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index ec510ecf8370..2a9297991d74 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -69,8 +69,7 @@ void __init pxa_timer_init(void) pxa27x_clocks_init(); if (cpu_is_pxa3xx()) pxa3xx_clocks_init(); - pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000), - get_clock_tick_rate()); + pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000)); } /* diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 3e09beddb6e8..2eb00691b07d 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -378,7 +378,7 @@ void __init sa1100_map_io(void) void __init sa1100_timer_init(void) { - pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000), 3686400); + pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000)); } static struct resource irq_resource = diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c index 3e1cb512f3ce..9cae38eebec2 100644 --- a/drivers/clocksource/pxa_timer.c +++ b/drivers/clocksource/pxa_timer.c @@ -220,17 +220,16 @@ CLOCKSOURCE_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init); /* * Legacy timer init for non device-tree boards. */ -void __init pxa_timer_nodt_init(int irq, void __iomem *base, - unsigned long clock_tick_rate) +void __init pxa_timer_nodt_init(int irq, void __iomem *base) { struct clk *clk; timer_base = base; clk = clk_get(NULL, "OSTIMER0"); - if (clk && !IS_ERR(clk)) + if (clk && !IS_ERR(clk)) { clk_prepare_enable(clk); - else + pxa_timer_common_init(irq, clk_get_rate(clk)); + } else { pr_crit("%s: unable to get clk\n", __func__); - - pxa_timer_common_init(irq, clock_tick_rate); + } } diff --git a/include/clocksource/pxa.h b/include/clocksource/pxa.h index 1efbe5a66958..a9a0f03024a4 100644 --- a/include/clocksource/pxa.h +++ b/include/clocksource/pxa.h @@ -12,7 +12,6 @@ #ifndef _CLOCKSOURCE_PXA_H #define _CLOCKSOURCE_PXA_H -extern void pxa_timer_nodt_init(int irq, void __iomem *base, - unsigned long clock_tick_rate); +extern void pxa_timer_nodt_init(int irq, void __iomem *base); #endif -- cgit v1.2.3 From 6924089c488e9deab2ecc43a263a09a2d8a3f4cb Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 19 Sep 2016 21:12:14 +0200 Subject: watchdog: sa11x0/pxa: get rid of get_clock_tick_rate The OS timer rate used for the watchdog can now be fetched from the standard clock API. This will remove the last user of get_clock_tick_rate() in both pxa and sa11x0 architectures. Signed-off-by: Robert Jarzmik Acked-by: Daniel Lezcano Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Acked-by: Russell King Acked-by: Wim Van Sebroeck --- drivers/watchdog/sa1100_wdt.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index e1d39a1e9628..8965e3f536c3 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -155,12 +156,27 @@ static struct miscdevice sa1100dog_miscdev = { }; static int margin __initdata = 60; /* (secs) Default is 1 minute */ +static struct clk *clk; static int __init sa1100dog_init(void) { int ret; - oscr_freq = get_clock_tick_rate(); + clk = clk_get(NULL, "OSTIMER0"); + if (IS_ERR(clk)) { + pr_err("SA1100/PXA2xx Watchdog Timer: clock not found: %d\n", + (int) PTR_ERR(clk)); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("SA1100/PXA2xx Watchdog Timer: clock failed to prepare+enable: %d\n", + ret); + goto err; + } + + oscr_freq = clk_get_rate(clk); /* * Read the reset status, and save it for later. If @@ -176,11 +192,17 @@ static int __init sa1100dog_init(void) pr_info("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", margin); return ret; +err: + clk_disable_unprepare(clk); + clk_put(clk); + return ret; } static void __exit sa1100dog_exit(void) { misc_deregister(&sa1100dog_miscdev); + clk_disable_unprepare(clk); + clk_put(clk); } module_init(sa1100dog_init); -- cgit v1.2.3 From cff52e5fc4cfc978b7df898dc14a0492c7ef0ae8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 18 Oct 2016 00:13:39 +0200 Subject: drm: avoid uninitialized timestamp use in wait_vblank gcc warns about the timestamp in drm_wait_vblank being possibly used without an initialization: drivers/gpu/drm/drm_irq.c: In function 'drm_crtc_send_vblank_event': drivers/gpu/drm/drm_irq.c:992:24: error: 'now.tv_usec' may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/gpu/drm/drm_irq.c:1069:17: note: 'now.tv_usec' was declared here drivers/gpu/drm/drm_irq.c:991:23: error: 'now.tv_sec' may be used uninitialized in this function [-Werror=maybe-uninitialized] This can happen if drm_vblank_count_and_time() returns 0 in its error path. To sanitize the error case, I'm changing that function to return a zero timestamp when it fails. Fixes: e6ae8687a87b ("drm: idiot-proof vblank") Reviewed-by: David Herrmann Cc: Rob Clark Cc: Daniel Vetter Signed-off-by: Arnd Bergmann Reviewed-by: Mario Kleiner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161017221355.1861551-6-arnd@arndb.de --- drivers/gpu/drm/drm_irq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index b969a64a1514..48a6167f5e7b 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -952,8 +952,10 @@ static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, u32 vblank_count; unsigned int seq; - if (WARN_ON(pipe >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) { + *vblanktime = (struct timeval) { 0 }; return 0; + } do { seq = read_seqbegin(&vblank->seqlock); -- cgit v1.2.3 From 056996b95686324fdc00e72f8cea01be2356ef62 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Mon, 17 Oct 2016 21:34:37 +0530 Subject: drm: Helper for lspcon in drm_dp_dual_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds lspcon support in dp_dual_mode helper. lspcon is essentially a dp->hdmi dongle with dual personality. LS mode: It works as a passive dongle, by level shifting DP++ signals to HDMI signals, in LS mode. PCON mode: It works as a protocol converter active dongle in pcon mode, by converting DP++ outputs to HDMI 2.0 outputs. This patch adds support for lspcon detection and mode set switch operations, as a dp dual mode dongle. v2: Addressed review comments from Ville - add adaptor id for lspcon devices (0x08), use it to identify lspcon - change function names old: drm_lspcon_get_current_mode/drm_lspcon_change_mode new: drm_lspcon_get_mode/drm_lspcon_set_mode - change drm_lspcon_get_mode type to int, to match drm_dp_dual_mode_get_tmds_output - change 'err' to 'ret' to match the rest of the functions - remove pointless typecasting during call to dual_mode_read - fix the but while setting value of data, while writing lspcon mode - fix indentation - change mdelay(10) -> msleep(10) - return ETIMEDOUT instead of EFAULT, when lspcon mode change times out - Add an empty line to separate std regs macros and lspcon regs macros Indent bit definition v3: Addressed review comments from Rodrigo - change macro name from DP_DUAL_MODE_TYPE_LSPCON to DP_DUAL_MODE_TYPE_HAS_DPCD for better readability - change macro name from DP_DUAL_MODE_LSPCON_MODE_PCON to DP_DUAL_MODE_LSPCON_MODE_PCON for better readability - add comment for MCA specific offsets like 0x40 and 0x41 - remove DP_DUAL_MODE_REV_TYPE2 check while checking lspcon adapter id v4: Addressed review comments from Ville - Fixed indentation at few places - s/current_mode/mode - s/reqd_mode/mode - remove unnecessary void* cast - remove drm_edid.h from includes - Add a comment for _HAS_DPCD - Fix enum description, for lspcon_mode. v5: Rebase v6: Rebase Signed-off-by: Shashank Sharma Reviewed-by: Rodrigo Vivi Acked-by: Dave Airlie Acked-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476720277-16298-1-git-send-email-shashank.sharma@intel.com --- drivers/gpu/drm/drm_dp_dual_mode_helper.c | 103 ++++++++++++++++++++++++++++++ include/drm/drm_dp_dual_mode_helper.h | 26 ++++++++ 2 files changed, 129 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c index a7b2a751f6fe..a7aeb1ec852c 100644 --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c @@ -148,6 +148,14 @@ static bool is_type2_adaptor(uint8_t adaptor_id) DP_DUAL_MODE_REV_TYPE2); } +bool is_lspcon_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN], + const uint8_t adaptor_id) +{ + return is_hdmi_adaptor(hdmi_id) && + (adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 | + DP_DUAL_MODE_TYPE_HAS_DPCD)); +} + /** * drm_dp_dual_mode_detect - Identify the DP dual mode adaptor * @adapter: I2C adapter for the DDC bus @@ -203,6 +211,8 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter) ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID, &adaptor_id, sizeof(adaptor_id)); if (ret == 0) { + if (is_lspcon_adaptor(hdmi_id, adaptor_id)) + return DRM_DP_DUAL_MODE_LSPCON; if (is_type2_adaptor(adaptor_id)) { if (is_hdmi_adaptor(hdmi_id)) return DRM_DP_DUAL_MODE_TYPE2_HDMI; @@ -364,3 +374,96 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type) } } EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name); + +/** + * drm_lspcon_get_mode: Get LSPCON's current mode of operation by + * by reading offset (0x80, 0x41) + * @i2c_adapter: I2C-over-aux adapter + * @current_mode: out vaiable, current lspcon mode of operation + * + * Returns: + * 0 on success, sets the current_mode value to appropriate mode + * -error on failure + */ +int drm_lspcon_get_mode(struct i2c_adapter *adapter, + enum drm_lspcon_mode *mode) +{ + u8 data; + int ret = 0; + + if (!mode) { + DRM_ERROR("NULL input\n"); + return -EINVAL; + } + + /* Read Status: i2c over aux */ + ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_CURRENT_MODE, + &data, sizeof(data)); + if (ret < 0) { + DRM_ERROR("LSPCON read(0x80, 0x41) failed\n"); + return -EFAULT; + } + + if (data & DP_DUAL_MODE_LSPCON_MODE_PCON) + *mode = DRM_LSPCON_MODE_PCON; + else + *mode = DRM_LSPCON_MODE_LS; + return 0; +} +EXPORT_SYMBOL(drm_lspcon_get_mode); + +/** + * drm_lspcon_change_mode: Change LSPCON's mode of operation by + * by writing offset (0x80, 0x40) + * @i2c_adapter: I2C-over-aux adapter + * @reqd_mode: required mode of operation + * + * Returns: + * 0 on success, -error on failure/timeout + */ +int drm_lspcon_set_mode(struct i2c_adapter *adapter, + enum drm_lspcon_mode mode) +{ + u8 data = 0; + int ret; + int time_out = 200; + enum drm_lspcon_mode current_mode; + + if (mode == DRM_LSPCON_MODE_PCON) + data = DP_DUAL_MODE_LSPCON_MODE_PCON; + + /* Change mode */ + ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_LSPCON_MODE_CHANGE, + &data, sizeof(data)); + if (ret < 0) { + DRM_ERROR("LSPCON mode change failed\n"); + return ret; + } + + /* + * Confirm mode change by reading the status bit. + * Sometimes, it takes a while to change the mode, + * so wait and retry until time out or done. + */ + do { + ret = drm_lspcon_get_mode(adapter, ¤t_mode); + if (ret) { + DRM_ERROR("can't confirm LSPCON mode change\n"); + return ret; + } else { + if (current_mode != mode) { + msleep(10); + time_out -= 10; + } else { + DRM_DEBUG_KMS("LSPCON mode changed to %s\n", + mode == DRM_LSPCON_MODE_LS ? + "LS" : "PCON"); + return 0; + } + } + } while (time_out); + + DRM_ERROR("LSPCON mode change timed out\n"); + return -ETIMEDOUT; +} +EXPORT_SYMBOL(drm_lspcon_set_mode); diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h index e8a9dfd0e055..55677704add8 100644 --- a/include/drm/drm_dp_dual_mode_helper.h +++ b/include/drm/drm_dp_dual_mode_helper.h @@ -40,6 +40,8 @@ #define DP_DUAL_MODE_REV_TYPE2 0x00 #define DP_DUAL_MODE_TYPE_MASK 0xf0 #define DP_DUAL_MODE_TYPE_TYPE2 0xa0 +/* This field is marked reserved in dual mode spec, used in LSPCON */ +#define DP_DUAL_MODE_TYPE_HAS_DPCD 0x08 #define DP_DUAL_MODE_IEEE_OUI 0x11 /* 11-13*/ #define DP_DUAL_IEEE_OUI_LEN 3 #define DP_DUAL_DEVICE_ID 0x14 /* 14-19 */ @@ -55,6 +57,11 @@ #define DP_DUAL_MODE_CEC_ENABLE 0x01 #define DP_DUAL_MODE_I2C_SPEED_CTRL 0x22 +/* LSPCON specific registers, defined by MCA */ +#define DP_DUAL_MODE_LSPCON_MODE_CHANGE 0x40 +#define DP_DUAL_MODE_LSPCON_CURRENT_MODE 0x41 +#define DP_DUAL_MODE_LSPCON_MODE_PCON 0x1 + struct i2c_adapter; ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter, @@ -62,6 +69,19 @@ ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter, ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter, u8 offset, const void *buffer, size_t size); +/** +* enum drm_lspcon_mode +* @lspcon_mode_ls: Level shifter mode of LSPCON +* which drives DP++ to HDMI 1.4 conversion. +* @lspcon_mode_pcon: Protocol converter mode of LSPCON +* which drives DP++ to HDMI 2.0 active conversion. +*/ +enum drm_lspcon_mode { + DRM_LSPCON_MODE_INVALID, + DRM_LSPCON_MODE_LS, + DRM_LSPCON_MODE_PCON, +}; + /** * enum drm_dp_dual_mode_type - Type of the DP dual mode adaptor * @DRM_DP_DUAL_MODE_NONE: No DP dual mode adaptor @@ -70,6 +90,7 @@ ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter, * @DRM_DP_DUAL_MODE_TYPE1_HDMI: Type 1 HDMI adaptor * @DRM_DP_DUAL_MODE_TYPE2_DVI: Type 2 DVI adaptor * @DRM_DP_DUAL_MODE_TYPE2_HDMI: Type 2 HDMI adaptor + * @DRM_DP_DUAL_MODE_TYPE2_LSPCON: Level shifter /protocol converter */ enum drm_dp_dual_mode_type { DRM_DP_DUAL_MODE_NONE, @@ -78,6 +99,7 @@ enum drm_dp_dual_mode_type { DRM_DP_DUAL_MODE_TYPE1_HDMI, DRM_DP_DUAL_MODE_TYPE2_DVI, DRM_DP_DUAL_MODE_TYPE2_HDMI, + DRM_DP_DUAL_MODE_LSPCON, }; enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter); @@ -89,4 +111,8 @@ int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type, struct i2c_adapter *adapter, bool enable); const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type); +int drm_lspcon_get_mode(struct i2c_adapter *adapter, + enum drm_lspcon_mode *current_mode); +int drm_lspcon_set_mode(struct i2c_adapter *adapter, + enum drm_lspcon_mode reqd_mode); #endif -- cgit v1.2.3 From dbe9e61b8e4306df24b3e8370a62f7954a81ff5d Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 14 Oct 2016 19:56:49 +0530 Subject: drm/i915: Add lspcon support for I915 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new file, to accommodate lspcon support for I915 driver. These functions probe, detect, initialize and configure an on-board lspcon device during the driver init time. Also, this patch adds a small structure for lspcon device, which will provide the runtime status of the device. V2: addressed ville's review comments - Clean the leftover macros from previous patch set V3: Rebase V4: addressed ville's review comments - make internal functions static - remove lspcon_detect_identifier, make it inline with lspcon_probe - remove is_lspcon_active function - remove force check while setting a lspcon mode V5: Rebase V6: Pass dev_priv to IS_GEN9 check Signed-off-by: Shashank Sharma Signed-off-by: Akashdeep Sharma Reviewed-by: Rodrigo Vivi Acked-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476455212-27893-3-git-send-email-shashank.sharma@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/intel_drv.h | 9 +++ drivers/gpu/drm/i915/intel_lspcon.c | 128 ++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 drivers/gpu/drm/i915/intel_lspcon.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 8790ae4fb171..612340097f4b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -101,6 +101,7 @@ i915-y += dvo_ch7017.o \ intel_dvo.o \ intel_hdmi.o \ intel_i2c.o \ + intel_lspcon.o \ intel_lvds.o \ intel_panel.o \ intel_sdvo.o \ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4388807f8fc8..ab1e6213df3d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -961,12 +961,19 @@ struct intel_dp { bool compliance_test_active; }; +struct intel_lspcon { + bool active; + enum drm_lspcon_mode mode; + struct drm_dp_aux *aux; +}; + struct intel_digital_port { struct intel_encoder base; enum port port; u32 saved_port_bits; struct intel_dp dp; struct intel_hdmi hdmi; + struct intel_lspcon lspcon; enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool); bool release_cl2_override; uint8_t max_lanes; @@ -1848,4 +1855,6 @@ int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state); void intel_color_set_csc(struct drm_crtc_state *crtc_state); void intel_color_load_luts(struct drm_crtc_state *crtc_state); +/* intel_lspcon.c */ +bool lspcon_init(struct intel_digital_port *intel_dig_port); #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c new file mode 100644 index 000000000000..628ae6fbdcb1 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -0,0 +1,128 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * + */ +#include +#include +#include +#include "intel_drv.h" + +enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) +{ + enum drm_lspcon_mode current_mode = DRM_LSPCON_MODE_INVALID; + struct i2c_adapter *adapter = &lspcon->aux->ddc; + + if (drm_lspcon_get_mode(adapter, ¤t_mode)) + DRM_ERROR("Error reading LSPCON mode\n"); + else + DRM_DEBUG_KMS("Current LSPCON mode %s\n", + current_mode == DRM_LSPCON_MODE_PCON ? "PCON" : "LS"); + return current_mode; +} + +static int lspcon_change_mode(struct intel_lspcon *lspcon, + enum drm_lspcon_mode mode, bool force) +{ + int err; + enum drm_lspcon_mode current_mode; + struct i2c_adapter *adapter = &lspcon->aux->ddc; + + err = drm_lspcon_get_mode(adapter, ¤t_mode); + if (err) { + DRM_ERROR("Error reading LSPCON mode\n"); + return err; + } + + if (current_mode == mode) { + DRM_DEBUG_KMS("Current mode = desired LSPCON mode\n"); + return 0; + } + + err = drm_lspcon_set_mode(adapter, mode); + if (err < 0) { + DRM_ERROR("LSPCON mode change failed\n"); + return err; + } + + lspcon->mode = mode; + DRM_DEBUG_KMS("LSPCON mode changed done\n"); + return 0; +} + +static bool lspcon_probe(struct intel_lspcon *lspcon) +{ + enum drm_dp_dual_mode_type adaptor_type; + struct i2c_adapter *adapter = &lspcon->aux->ddc; + + /* Lets probe the adaptor and check its type */ + adaptor_type = drm_dp_dual_mode_detect(adapter); + if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) { + DRM_DEBUG_KMS("No LSPCON detected, found %s\n", + drm_dp_get_dual_mode_type_name(adaptor_type)); + return false; + } + + /* Yay ... got a LSPCON device */ + DRM_DEBUG_KMS("LSPCON detected\n"); + lspcon->mode = lspcon_get_current_mode(lspcon); + lspcon->active = true; + return true; +} + +bool lspcon_init(struct intel_digital_port *intel_dig_port) +{ + struct intel_dp *dp = &intel_dig_port->dp; + struct intel_lspcon *lspcon = &intel_dig_port->lspcon; + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + if (!IS_GEN9(dev_priv)) { + DRM_ERROR("LSPCON is supported on GEN9 only\n"); + return false; + } + + lspcon->active = false; + lspcon->mode = DRM_LSPCON_MODE_INVALID; + lspcon->aux = &dp->aux; + + if (!lspcon_probe(lspcon)) { + DRM_ERROR("Failed to probe lspcon\n"); + return false; + } + + /* + * In the SW state machine, lets Put LSPCON in PCON mode only. + * In this way, it will work with both HDMI 1.4 sinks as well as HDMI + * 2.0 sinks. + */ + if (lspcon->active && lspcon->mode != DRM_LSPCON_MODE_PCON) { + if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON, + true) < 0) { + DRM_ERROR("LSPCON mode change to PCON failed\n"); + return false; + } + } + + DRM_DEBUG_KMS("Success: LSPCON init\n"); + return true; +} -- cgit v1.2.3 From 6389dd83768485a251dc0c5252dbc9a96f86ca53 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 14 Oct 2016 19:56:50 +0530 Subject: drm/i915: Parse VBT data for lspcon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many GEN9 boards come with on-board lspcon cards. Fot these boards, VBT configuration should properly point out if a particular port contains lspcon device, so that driver can initialize it properly. This patch adds a utility function, which checks the VBT flag for lspcon bit, and tells us if a port is configured to have a lspcon device or not. V2: Fixed review comments from Ville - Do not forget PORT_D while checking lspcon for GEN9 V3: Addressed review comments from Rodrigo - Create a HAS_LSPCON() macro for better use case handling. - Do not dump warnings for non-gen-9 platforms, it will be noise. V4: Rebase V5: Rebase V6: Pass dev_priv to HAS_LSPCON() macro Signed-off-by: Shashank Sharma Reviewed-by: Rodrigo Vivi Acked-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476455212-27893-4-git-send-email-shashank.sharma@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 5 ++++ drivers/gpu/drm/i915/intel_bios.c | 49 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4d1133ffe093..8a1020f6c9cc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2862,6 +2862,8 @@ struct drm_i915_cmd_table { #define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.has_gmch_display) +#define HAS_LSPCON(dev_priv) (IS_GEN9(dev_priv)) + /* DPF == dynamic parity feature */ #define HAS_L3_DPF(dev_priv) ((dev_priv)->info.has_l3_dpf) #define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \ @@ -3629,6 +3631,9 @@ bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum por bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port); bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, enum port port); +bool intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv, + enum port port); + /* intel_opregion.c */ #ifdef CONFIG_ACPI diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 83667e8cdd6b..32e1def6a9ef 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1763,3 +1763,52 @@ intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, return false; } + +/** + * intel_bios_is_lspcon_present - if LSPCON is attached on %port + * @dev_priv: i915 device instance + * @port: port to check + * + * Return true if LSPCON is present on this port + */ +bool +intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv, + enum port port) +{ + int i; + + if (!HAS_LSPCON(dev_priv)) + return false; + + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { + if (!dev_priv->vbt.child_dev[i].common.lspcon) + continue; + + switch (dev_priv->vbt.child_dev[i].common.dvo_port) { + case DVO_PORT_DPA: + case DVO_PORT_HDMIA: + if (port == PORT_A) + return true; + break; + case DVO_PORT_DPB: + case DVO_PORT_HDMIB: + if (port == PORT_B) + return true; + break; + case DVO_PORT_DPC: + case DVO_PORT_HDMIC: + if (port == PORT_C) + return true; + break; + case DVO_PORT_DPD: + case DVO_PORT_HDMID: + if (port == PORT_D) + return true; + break; + default: + break; + } + } + + return false; +} -- cgit v1.2.3 From ff66212415e3240cb4f79a09b00a03dd56d48b16 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 14 Oct 2016 19:56:51 +0530 Subject: drm/i915: Enable lspcon initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds initialization code for lspcon. What we are doing here is: - Check if lspcon is configured in VBT for this port - If lspcon is configured, initialize it and configure it as DP port. V2: Addressed Ville's review comments: - Not adding AVI IF functions for LSPCON display now. This part will be added once the dig_port level AVI-IF series gets merged. V3: Rebase V4: Rebase V5: Rebase V6: Rebase Signed-off-by: Shashank Sharma Reviewed-by: Rodrigo Vivi Acked-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476455212-27893-5-git-send-email-shashank.sharma@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index a76afd7a6616..7f7741c1406d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2438,7 +2438,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) struct intel_digital_port *intel_dig_port; struct intel_encoder *intel_encoder; struct drm_encoder *encoder; - bool init_hdmi, init_dp; + bool init_hdmi, init_dp, init_lspcon = false; int max_lanes; if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) { @@ -2470,6 +2470,19 @@ void intel_ddi_init(struct drm_device *dev, enum port port) init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || dev_priv->vbt.ddi_port_info[port].supports_hdmi); init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; + + if (intel_bios_is_lspcon_present(dev_priv, port)) { + /* + * Lspcon device needs to be driven with DP connector + * with special detection sequence. So make sure DP + * is initialized before lspcon. + */ + init_dp = true; + init_lspcon = true; + init_hdmi = false; + DRM_DEBUG_KMS("VBT says port %c has lspcon\n", port_name(port)); + } + if (!init_dp && !init_hdmi) { DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, respect it\n", port_name(port)); @@ -2546,6 +2559,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port) goto err; } + if (init_lspcon) { + if (lspcon_init(intel_dig_port)) + /* TODO: handle hdmi info frame part */ + DRM_DEBUG_KMS("LSPCON init success on port %c\n", + port_name(port)); + else + /* + * LSPCON init faied, but DP init was success, so + * lets try to drive as DP++ port. + */ + DRM_ERROR("LSPCON init failed on port %c\n", + port_name(port)); + } + return; err: -- cgit v1.2.3 From 910530c0630541aa5d2f20ea15f3108bfe2c1693 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 14 Oct 2016 19:56:52 +0530 Subject: drm/i915: Add lspcon resume function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per the software design, we are driving lspcon in PCON mode. But while resuming from suspend, lspcon can go in LS mode (which is its default operating mode on power on) This patch adds a resume function for lspcon, which makes sure its operating in PCON mode, post resume. V2: Address review comments from Imre - move lspcon_resume call to encoder->reset() - use early returns Signed-off-by: Shashank Sharma Reviewed-by: Imre Deak Acked-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476455212-27893-6-git-send-email-shashank.sharma@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 7 ++++++- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_lspcon.c | 8 ++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 780691a34133..88f3b745a326 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4780,11 +4780,16 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp) void intel_dp_encoder_reset(struct drm_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->dev); - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct intel_lspcon *lspcon = &intel_dig_port->lspcon; + struct intel_dp *intel_dp = &intel_dig_port->dp; if (!HAS_DDI(dev_priv)) intel_dp->DP = I915_READ(intel_dp->output_reg); + if (IS_GEN9(dev_priv) && lspcon->active) + lspcon_resume(lspcon); + if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP) return; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ab1e6213df3d..5760420ace61 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1857,4 +1857,5 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state); /* intel_lspcon.c */ bool lspcon_init(struct intel_digital_port *intel_dig_port); +void lspcon_resume(struct intel_lspcon *lspcon); #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 628ae6fbdcb1..d606f1a8f3b6 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -89,6 +89,14 @@ static bool lspcon_probe(struct intel_lspcon *lspcon) return true; } +void lspcon_resume(struct intel_lspcon *lspcon) +{ + if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON, true)) + DRM_ERROR("LSPCON resume failed\n"); + else + DRM_DEBUG_KMS("LSPCON resume success\n"); +} + bool lspcon_init(struct intel_digital_port *intel_dig_port) { struct intel_dp *dp = &intel_dig_port->dp; -- cgit v1.2.3 From 84770cc24f3a51c05055665feeac1dcf22119d69 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:09 +0300 Subject: drm: Centralize format information Various pieces of information about DRM formats (number of planes, color depth, chroma subsampling, ...) are scattered across different helper functions in the DRM core. Callers of those functions often need to access more than a single parameter of the format, leading to inefficiencies due to multiple lookups. Centralize all format information in a data structure and create a function to look up information based on the format 4CC. Signed-off-by: Laurent Pinchart Reviewed-by: Daniel Vetter Reviewed-by: Eric Engestrom Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-2-git-send-email-laurent.pinchart@ideasonboard.com --- Documentation/gpu/drm-kms.rst | 3 ++ drivers/gpu/drm/drm_fourcc.c | 84 +++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_fourcc.h | 21 +++++++++++ 3 files changed, 108 insertions(+) (limited to 'drivers') diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 53b872c105d2..cb0d3537b705 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -63,6 +63,9 @@ Frame Buffer Functions Reference DRM Format Handling =================== +.. kernel-doc:: include/drm/drm_fourcc.h + :internal: + .. kernel-doc:: drivers/gpu/drm/drm_fourcc.c :export: diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 29c56b4331e0..39f09c564111 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -102,6 +102,90 @@ char *drm_get_format_name(uint32_t format) } EXPORT_SYMBOL(drm_get_format_name); +/** + * drm_format_info - query information for a given format + * @format: pixel format (DRM_FORMAT_*) + * + * Returns: + * The instance of struct drm_format_info that describes the pixel format, or + * NULL if the format is unsupported. + */ +const struct drm_format_info *drm_format_info(u32 format) +{ + static const struct drm_format_info formats[] = { + { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 }, + { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 }, + { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 }, + { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 }, + { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 }, + { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 }, + { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 }, + { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 }, + { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + }; + + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (formats[i].format == format) + return &formats[i]; + } + + return NULL; +} +EXPORT_SYMBOL(drm_format_info); + /** * drm_fb_get_bpp_depth - get the bpp/depth values for format * @format: pixel format (DRM_FORMAT_*) diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 30c30fa87ee8..135fef050ee6 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -25,6 +25,27 @@ #include #include +/** + * struct drm_format_info - information about a DRM format + * @format: 4CC format identifier (DRM_FORMAT_*) + * @depth: Color depth (number of bits per pixel excluding padding bits), + * valid for a subset of RGB formats only. This is a legacy field, do not + * use in new code and set to 0 for new formats. + * @num_planes: Number of color planes (1 to 3) + * @cpp: Number of bytes per pixel (per plane) + * @hsub: Horizontal chroma subsampling factor + * @vsub: Vertical chroma subsampling factor + */ +struct drm_format_info { + u32 format; + u8 depth; + u8 num_planes; + u8 cpp[3]; + u8 hsub; + u8 vsub; +}; + +const struct drm_format_info *drm_format_info(u32 format); uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); int drm_format_num_planes(uint32_t format); -- cgit v1.2.3 From 86c238aa51c219b8ba1a0e6a86c2676d856f90d5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:10 +0300 Subject: drm: Implement the drm_format_*() helpers as drm_format_info() wrappers Turn the drm_format_*() helpers into wrappers around the drm_format_info lookup function to centralize all format information in a single place. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen Reviewed-by: Daniel Vetter Reviewed-by: Eric Engestrom Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-3-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_fourcc.c | 186 +++++++++---------------------------------- 1 file changed, 37 insertions(+), 149 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 39f09c564111..23d4b82ec17c 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -198,69 +198,22 @@ EXPORT_SYMBOL(drm_format_info); void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp) { - char *format_name; - - switch (format) { - case DRM_FORMAT_C8: - case DRM_FORMAT_RGB332: - case DRM_FORMAT_BGR233: - *depth = 8; - *bpp = 8; - break; - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_XBGR1555: - case DRM_FORMAT_RGBX5551: - case DRM_FORMAT_BGRX5551: - case DRM_FORMAT_ARGB1555: - case DRM_FORMAT_ABGR1555: - case DRM_FORMAT_RGBA5551: - case DRM_FORMAT_BGRA5551: - *depth = 15; - *bpp = 16; - break; - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - *depth = 16; - *bpp = 16; - break; - case DRM_FORMAT_RGB888: - case DRM_FORMAT_BGR888: - *depth = 24; - *bpp = 24; - break; - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_RGBX8888: - case DRM_FORMAT_BGRX8888: - *depth = 24; - *bpp = 32; - break; - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRX1010102: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_BGRA1010102: - *depth = 30; - *bpp = 32; - break; - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_BGRA8888: - *depth = 32; - *bpp = 32; - break; - default: - format_name = drm_get_format_name(format); + const struct drm_format_info *info; + + info = drm_format_info(format); + if (!info || !info->depth) { + char *format_name = drm_get_format_name(format); + DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name); kfree(format_name); + *depth = 0; *bpp = 0; - break; + return; } + + *depth = info->depth; + *bpp = info->cpp[0] * 8; } EXPORT_SYMBOL(drm_fb_get_bpp_depth); @@ -273,28 +226,10 @@ EXPORT_SYMBOL(drm_fb_get_bpp_depth); */ int drm_format_num_planes(uint32_t format) { - switch (format) { - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - return 3; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_NV24: - case DRM_FORMAT_NV42: - return 2; - default: - return 1; - } + const struct drm_format_info *info; + + info = drm_format_info(format); + return info ? info->num_planes : 1; } EXPORT_SYMBOL(drm_format_num_planes); @@ -308,40 +243,13 @@ EXPORT_SYMBOL(drm_format_num_planes); */ int drm_format_plane_cpp(uint32_t format, int plane) { - unsigned int depth; - int bpp; + const struct drm_format_info *info; - if (plane >= drm_format_num_planes(format)) + info = drm_format_info(format); + if (!info || plane >= info->num_planes) return 0; - switch (format) { - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - return 2; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_NV24: - case DRM_FORMAT_NV42: - return plane ? 2 : 1; - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - return 1; - default: - drm_fb_get_bpp_depth(format, &depth, &bpp); - return bpp >> 3; - } + return info->cpp[plane]; } EXPORT_SYMBOL(drm_format_plane_cpp); @@ -355,28 +263,10 @@ EXPORT_SYMBOL(drm_format_plane_cpp); */ int drm_format_horz_chroma_subsampling(uint32_t format) { - switch (format) { - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - return 4; - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - return 2; - default: - return 1; - } + const struct drm_format_info *info; + + info = drm_format_info(format); + return info ? info->hsub : 1; } EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); @@ -390,18 +280,10 @@ EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); */ int drm_format_vert_chroma_subsampling(uint32_t format) { - switch (format) { - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - return 4; - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - return 2; - default: - return 1; - } + const struct drm_format_info *info; + + info = drm_format_info(format); + return info ? info->vsub : 1; } EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); @@ -416,13 +298,16 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); */ int drm_format_plane_width(int width, uint32_t format, int plane) { - if (plane >= drm_format_num_planes(format)) + const struct drm_format_info *info; + + info = drm_format_info(format); + if (!info || plane >= info->num_planes) return 0; if (plane == 0) return width; - return width / drm_format_horz_chroma_subsampling(format); + return width / info->hsub; } EXPORT_SYMBOL(drm_format_plane_width); @@ -437,12 +322,15 @@ EXPORT_SYMBOL(drm_format_plane_width); */ int drm_format_plane_height(int height, uint32_t format, int plane) { - if (plane >= drm_format_num_planes(format)) + const struct drm_format_info *info; + + info = drm_format_info(format); + if (!info || plane >= info->num_planes) return 0; if (plane == 0) return height; - return height / drm_format_vert_chroma_subsampling(format); + return height / info->vsub; } EXPORT_SYMBOL(drm_format_plane_height); -- cgit v1.2.3 From d549349007ed66af325c1363c0e4f8bb7a518c0d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:11 +0300 Subject: drm: Use drm_format_info() in DRM core code Replace calls to the drm_format_*() helper functions with direct use of the drm_format_info structure. This improves efficiency by removing duplicate lookups. Signed-off-by: Laurent Pinchart Reviewed-by: Daniel Vetter Reviewed-by: Eric Engestrom Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-4-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_fb_cma_helper.c | 23 ++++---- drivers/gpu/drm/drm_framebuffer.c | 102 +++++------------------------------- 2 files changed, 25 insertions(+), 100 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 1fd6eac1400c..fac4f06f8485 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -176,20 +176,20 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, const struct drm_framebuffer_funcs *funcs) { + const struct drm_format_info *info; struct drm_fb_cma *fb_cma; struct drm_gem_cma_object *objs[4]; struct drm_gem_object *obj; - unsigned int hsub; - unsigned int vsub; int ret; int i; - hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); - vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); + info = drm_format_info(mode_cmd->pixel_format); + if (!info) + return ERR_PTR(-EINVAL); - for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) { - unsigned int width = mode_cmd->width / (i ? hsub : 1); - unsigned int height = mode_cmd->height / (i ? vsub : 1); + for (i = 0; i < info->num_planes; i++) { + unsigned int width = mode_cmd->width / (i ? info->hsub : 1); + unsigned int height = mode_cmd->height / (i ? info->vsub : 1); unsigned int min_size; obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); @@ -200,7 +200,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, } min_size = (height - 1) * mode_cmd->pitches[i] - + width * drm_format_plane_cpp(mode_cmd->pixel_format, i) + + width * info->cpp[i] + mode_cmd->offsets[i]; if (obj->size < min_size) { @@ -269,12 +269,15 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) { struct drm_fb_cma *fb_cma = to_fb_cma(fb); - int i, n = drm_format_num_planes(fb->pixel_format); + const struct drm_format_info *info; + int i; seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, (char *)&fb->pixel_format); - for (i = 0; i < n; i++) { + info = drm_format_info(fb->pixel_format); + + for (i = 0; i < info->num_planes; i++) { seq_printf(m, " %d: offset=%d pitch=%d, obj: ", i, fb->offsets[i], fb->pitches[i]); drm_gem_cma_describe(fb_cma->obj[i], m); diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 398efd67cb93..386977df72ce 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -126,111 +126,33 @@ int drm_mode_addfb(struct drm_device *dev, return 0; } -static int format_check(const struct drm_mode_fb_cmd2 *r) -{ - uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; - char *format_name; - - switch (format) { - case DRM_FORMAT_C8: - case DRM_FORMAT_RGB332: - case DRM_FORMAT_BGR233: - case DRM_FORMAT_XRGB4444: - case DRM_FORMAT_XBGR4444: - case DRM_FORMAT_RGBX4444: - case DRM_FORMAT_BGRX4444: - case DRM_FORMAT_ARGB4444: - case DRM_FORMAT_ABGR4444: - case DRM_FORMAT_RGBA4444: - case DRM_FORMAT_BGRA4444: - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_XBGR1555: - case DRM_FORMAT_RGBX5551: - case DRM_FORMAT_BGRX5551: - case DRM_FORMAT_ARGB1555: - case DRM_FORMAT_ABGR1555: - case DRM_FORMAT_RGBA5551: - case DRM_FORMAT_BGRA5551: - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - case DRM_FORMAT_RGB888: - case DRM_FORMAT_BGR888: - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_RGBX8888: - case DRM_FORMAT_BGRX8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_BGRA8888: - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRX1010102: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_BGRA1010102: - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_AYUV: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_NV24: - case DRM_FORMAT_NV42: - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - return 0; - default: - format_name = drm_get_format_name(r->pixel_format); - DRM_DEBUG_KMS("invalid pixel format %s\n", format_name); - kfree(format_name); - return -EINVAL; - } -} - static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) { - int ret, hsub, vsub, num_planes, i; + const struct drm_format_info *info; + int i; - ret = format_check(r); - if (ret) { + info = drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); + if (!info) { char *format_name = drm_get_format_name(r->pixel_format); DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name); kfree(format_name); - return ret; + return -EINVAL; } - hsub = drm_format_horz_chroma_subsampling(r->pixel_format); - vsub = drm_format_vert_chroma_subsampling(r->pixel_format); - num_planes = drm_format_num_planes(r->pixel_format); - - if (r->width == 0 || r->width % hsub) { + if (r->width == 0 || r->width % info->hsub) { DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); return -EINVAL; } - if (r->height == 0 || r->height % vsub) { + if (r->height == 0 || r->height % info->vsub) { DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); return -EINVAL; } - for (i = 0; i < num_planes; i++) { - unsigned int width = r->width / (i != 0 ? hsub : 1); - unsigned int height = r->height / (i != 0 ? vsub : 1); - unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i); + for (i = 0; i < info->num_planes; i++) { + unsigned int width = r->width / (i != 0 ? info->hsub : 1); + unsigned int height = r->height / (i != 0 ? info->vsub : 1); + unsigned int cpp = info->cpp[i]; if (!r->handles[i]) { DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); @@ -273,7 +195,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) } } - for (i = num_planes; i < 4; i++) { + for (i = info->num_planes; i < 4; i++) { if (r->modifier[i]) { DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i); return -EINVAL; -- cgit v1.2.3 From 333d2da5b7cf8046aee88c0412170be5f6f1ed55 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:12 +0300 Subject: drm: WARN when calling drm_format_info() for an unsupported format The format helpers have historically treated unsupported formats as part of the default case, returning values that are likely wrong. We can't change this behaviour now without risking breaking drivers in difficult to detect ways, but we can WARN on unsupported formats to catch faulty callers. The only exception is the framebuffer_check() function that calls drm_format_info() to validate the format passed from userspace. This is a valid use case that shouldn't generate a warning. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-5-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_fourcc.c | 32 ++++++++++++++++++++++++-------- drivers/gpu/drm/drm_framebuffer.c | 2 +- include/drm/drm_fourcc.h | 1 + 3 files changed, 26 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 23d4b82ec17c..523ed916a1c0 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -102,15 +102,11 @@ char *drm_get_format_name(uint32_t format) } EXPORT_SYMBOL(drm_get_format_name); -/** - * drm_format_info - query information for a given format - * @format: pixel format (DRM_FORMAT_*) - * - * Returns: - * The instance of struct drm_format_info that describes the pixel format, or - * NULL if the format is unsupported. +/* + * Internal function to query information for a given format. See + * drm_format_info() for the public API. */ -const struct drm_format_info *drm_format_info(u32 format) +const struct drm_format_info *__drm_format_info(u32 format) { static const struct drm_format_info formats[] = { { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, @@ -184,6 +180,26 @@ const struct drm_format_info *drm_format_info(u32 format) return NULL; } + +/** + * drm_format_info - query information for a given format + * @format: pixel format (DRM_FORMAT_*) + * + * The caller should only pass a supported pixel format to this function. + * Unsupported pixel formats will generate a warning in the kernel log. + * + * Returns: + * The instance of struct drm_format_info that describes the pixel format, or + * NULL if the format is unsupported. + */ +const struct drm_format_info *drm_format_info(u32 format) +{ + const struct drm_format_info *info; + + info = __drm_format_info(format); + WARN_ON(!info); + return info; +} EXPORT_SYMBOL(drm_format_info); /** diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 386977df72ce..49fd7db758e0 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -131,7 +131,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) const struct drm_format_info *info; int i; - info = drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); + info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); if (!info) { char *format_name = drm_get_format_name(r->pixel_format); DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name); diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 135fef050ee6..f73f97afd1e2 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -45,6 +45,7 @@ struct drm_format_info { u8 vsub; }; +const struct drm_format_info *__drm_format_info(u32 format); const struct drm_format_info *drm_format_info(u32 format); uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); -- cgit v1.2.3 From ba0891d1120389ad44c4f4e6d0b71f5fbcc23163 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:13 +0300 Subject: drm: hdlcd: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API. Signed-off-by: Laurent Pinchart Acked-by: Liviu Dudau Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-6-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/arm/hdlcd_crtc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 48019ae22ddb..bbaa55add2d2 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -223,14 +223,12 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, { struct hdlcd_drm_private *hdlcd; struct drm_gem_cma_object *gem; - unsigned int depth, bpp; u32 src_w, src_h, dest_w, dest_h; dma_addr_t scanout_start; if (!plane->state->fb) return; - drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp); src_w = plane->state->src_w >> 16; src_h = plane->state->src_h >> 16; dest_w = plane->state->crtc_w; @@ -238,7 +236,8 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); scanout_start = gem->paddr + plane->state->fb->offsets[0] + plane->state->crtc_y * plane->state->fb->pitches[0] + - plane->state->crtc_x * bpp / 8; + plane->state->crtc_x * + drm_format_plane_cpp(plane->state->fb->pixel_format, 0); hdlcd = plane->dev->dev_private; hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]); -- cgit v1.2.3 From 59f11a43237fe08de8572b5be5d961d262ae770d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:14 +0300 Subject: drm: tilcdc: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API. In the tilcdc_crtc_mode_set() function compute the hardware register value directly from the pixel format instead of computing the number of bits per pixels first. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-7-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 18 ++++++++---------- drivers/gpu/drm/tilcdc/tilcdc_plane.c | 7 ++++--- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 52ebe8fc1784..822531ebd4b0 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -72,16 +72,14 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_gem_cma_object *gem; - unsigned int depth, bpp; dma_addr_t start, end; u64 dma_base_and_ceiling; - drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); gem = drm_fb_cma_get_gem_obj(fb, 0); start = gem->paddr + fb->offsets[0] + crtc->y * fb->pitches[0] + - crtc->x * bpp / 8; + crtc->x * drm_format_plane_cpp(fb->pixel_format, 0); end = start + (crtc->mode.vdisplay * fb->pitches[0]); @@ -461,16 +459,16 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) if (info->tft_alt_mode) reg |= LCDC_TFT_ALT_ENABLE; if (priv->rev == 2) { - unsigned int depth, bpp; - - drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); - switch (bpp) { - case 16: + switch (fb->pixel_format) { + case DRM_FORMAT_BGR565: + case DRM_FORMAT_RGB565: break; - case 32: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_XRGB8888: reg |= LCDC_V2_TFT_24BPP_UNPACK; /* fallthrough */ - case 24: + case DRM_FORMAT_BGR888: + case DRM_FORMAT_RGB888: reg |= LCDC_V2_TFT_24BPP_MODE; break; default: diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index 74c65fa859b2..8a6a50d74aff 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c @@ -39,7 +39,7 @@ static int tilcdc_plane_atomic_check(struct drm_plane *plane, { struct drm_crtc_state *crtc_state; struct drm_plane_state *old_state = plane->state; - unsigned int depth, bpp; + unsigned int pitch; if (!state->crtc) return 0; @@ -68,8 +68,9 @@ static int tilcdc_plane_atomic_check(struct drm_plane *plane, return -EINVAL; } - drm_fb_get_bpp_depth(state->fb->pixel_format, &depth, &bpp); - if (state->fb->pitches[0] != crtc_state->mode.hdisplay * bpp / 8) { + pitch = crtc_state->mode.hdisplay * + drm_format_plane_cpp(state->fb->pixel_format, 0); + if (state->fb->pitches[0] != pitch) { dev_err(plane->dev->dev, "Invalid pitch: fb and crtc widths must be the same"); return -EINVAL; -- cgit v1.2.3 From b7f9745cda2f905403cf0c8ce326e70ee9f8b633 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:15 +0300 Subject: drm: cirrus: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() The driver doesn't need the color depth, only the number of bits per pixel. Use the right API. Signed-off-by: Laurent Pinchart Reviewed-by: Daniel Vetter Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-8-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 6 +++--- drivers/gpu/drm/cirrus/cirrus_main.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index daecf1ad76a4..3a6309d7d8e4 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -138,12 +138,12 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev, { struct drm_device *dev = afbdev->helper.dev; struct cirrus_device *cdev = dev->dev_private; - u32 bpp, depth; + u32 bpp; u32 size; struct drm_gem_object *gobj; - int ret = 0; - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8; if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, bpp, mode_cmd->pitches[0])) diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index 76bcb43e7c06..2c3c0d4072ce 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c @@ -52,10 +52,10 @@ cirrus_user_framebuffer_create(struct drm_device *dev, struct cirrus_device *cdev = dev->dev_private; struct drm_gem_object *obj; struct cirrus_framebuffer *cirrus_fb; + u32 bpp; int ret; - u32 bpp, depth; - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8; if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, bpp, mode_cmd->pitches[0])) -- cgit v1.2.3 From e0f9a4ab49a107c011f3bda401f747fbb5f29e7a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:16 +0300 Subject: drm: gma500: Replace drm_fb_get_bpp_depth() with drm_format_info() The driver uses drm_fb_get_bpp_depth() to check whether it can support the format requested by userspace when creating a framebuffer. This isn't the right API, as it doesn't differentiate between RGB formats other than on a depth and bpp basis. Fixing this requires non trivial changes to the drivers internals. As a first step, replace usage of the drm_fb_get_bpp_depth() function with an equivalent check based on drm_format_info(). This is part of a wider effort to remove usage of the drm_fb_get_bpp_depth() function in drivers. Signed-off-by: Laurent Pinchart Reviewed-by: Daniel Vetter Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-9-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/gma500/framebuffer.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index aee2f9733457..97daf23f3fef 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -236,22 +236,20 @@ static int psb_framebuffer_init(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, struct gtt_range *gt) { - u32 bpp, depth; + const struct drm_format_info *info; int ret; - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + /* + * Reject unknown formats, YUV formats, and formats with more than + * 4 bytes per pixel. + */ + info = drm_format_info(mode_cmd->pixel_format); + if (!info || !info->depth || info->cpp[0] > 4) + return -EINVAL; if (mode_cmd->pitches[0] & 63) return -EINVAL; - switch (bpp) { - case 8: - case 16: - case 24: - case 32: - break; - default: - return -EINVAL; - } + drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); fb->gtt = gt; ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); -- cgit v1.2.3 From 8e911ab770f7bbc8bb5fab0ce6ebd8d1a7188998 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:17 +0300 Subject: drm: amdgpu: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API. Signed-off-by: Laurent Pinchart Reviewed-by: Daniel Vetter Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-10-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 14 +++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 9fb8aa4d6bae..8d01aa24d68a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -90,12 +90,12 @@ static struct fb_ops amdgpufb_ops = { }; -int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tiled) +int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int cpp, bool tiled) { int aligned = width; int pitch_mask = 0; - switch (bpp / 8) { + switch (cpp) { case 1: pitch_mask = 255; break; @@ -110,7 +110,7 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile aligned += pitch_mask; aligned &= ~pitch_mask; - return aligned; + return aligned * cpp; } static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj) @@ -139,13 +139,13 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, int ret; int aligned_size, size; int height = mode_cmd->height; - u32 bpp, depth; + u32 cpp; - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0); /* need to align pitch with crtc limits */ - mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, bpp, - fb_tiled) * ((bpp + 1) / 8); + mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp, + fb_tiled); height = ALIGN(mode_cmd->height, 8); size = mode_cmd->pitches[0] * height; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index e0171c75b60c..3ad0bf6ce3e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -702,7 +702,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, uint32_t handle; int r; - args->pitch = amdgpu_align_pitch(adev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); + args->pitch = amdgpu_align_pitch(adev, args->width, + DIV_ROUND_UP(args->bpp, 8), 0); args->size = (u64)args->pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE); -- cgit v1.2.3 From 802aaf7642f57aa2eadbff8ee38dbd976e8bd0f4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:18 +0300 Subject: drm: radeon: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API. Signed-off-by: Laurent Pinchart Reviewed-by: Daniel Vetter Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-11-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/radeon/radeon_fb.c | 20 ++++++++++---------- drivers/gpu/drm/radeon/radeon_gem.c | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 0daad446d2c7..f65f29911dca 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -89,13 +89,13 @@ static struct fb_ops radeonfb_ops = { }; -int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) +int radeon_align_pitch(struct radeon_device *rdev, int width, int cpp, bool tiled) { int aligned = width; int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; int pitch_mask = 0; - switch (bpp / 8) { + switch (cpp) { case 1: pitch_mask = align_large ? 255 : 127; break; @@ -110,7 +110,7 @@ int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tile aligned += pitch_mask; aligned &= ~pitch_mask; - return aligned; + return aligned * cpp; } static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) @@ -139,13 +139,13 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, int ret; int aligned_size, size; int height = mode_cmd->height; - u32 bpp, depth; + u32 cpp; - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0); /* need to align pitch with crtc limits */ - mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp, - fb_tiled) * ((bpp + 1) / 8); + mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp, + fb_tiled); if (rdev->family >= CHIP_R600) height = ALIGN(mode_cmd->height, 8); @@ -165,11 +165,11 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, tiling_flags = RADEON_TILING_MACRO; #ifdef __BIG_ENDIAN - switch (bpp) { - case 32: + switch (cpp) { + case 4: tiling_flags |= RADEON_TILING_SWAP_32BIT; break; - case 16: + case 2: tiling_flags |= RADEON_TILING_SWAP_16BIT; default: break; diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index deb9511725c9..0bcffd8a7bd3 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -745,7 +745,8 @@ int radeon_mode_dumb_create(struct drm_file *file_priv, uint32_t handle; int r; - args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); + args->pitch = radeon_align_pitch(rdev, args->width, + DIV_ROUND_UP(args->bpp, 8), 0); args->size = args->pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE); -- cgit v1.2.3 From 6c5d064a2dd9ecda0716f66b0586349179036ca4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:19 +0300 Subject: drm: vmwgfx: Replace drm_fb_get_bpp_depth() with drm_format_info() The driver is the last users of the drm_fb_get_bpp_depth() function. It should ideally be converted to use struct drm_mode_fb_cmd2 instead of the legacy struct drm_mode_fb_cmd internally, but that will require broad changes across the code base. As a first step, replace drm_fb_get_bpp_depth() with drm_format_info() in order to stop exporting the function to drivers. The new DRM_ERROR() message comes from the vmw_create_dmabuf_proxy(), vmw_kms_new_framebuffer_surface() and vmw_kms_new_framebuffer_dmabuf() functions that currently print an error if the pixel format is unsupported. Signed-off-by: Laurent Pinchart Reviewed-by: Sinclair Yeh Reviewed-by: Daniel Vetter Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-12-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index bf28ccc150df..c965514b82be 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -980,14 +980,22 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, struct vmw_dma_buffer *bo = NULL; struct ttm_base_object *user_obj; struct drm_mode_fb_cmd mode_cmd; + const struct drm_format_info *info; int ret; + info = drm_format_info(mode_cmd2->pixel_format); + if (!info || !info->depth) { + DRM_ERROR("Unsupported framebuffer format %s\n", + drm_get_format_name(mode_cmd2->pixel_format)); + return ERR_PTR(-EINVAL); + } + mode_cmd.width = mode_cmd2->width; mode_cmd.height = mode_cmd2->height; mode_cmd.pitch = mode_cmd2->pitches[0]; mode_cmd.handle = mode_cmd2->handles[0]; - drm_fb_get_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth, - &mode_cmd.bpp); + mode_cmd.depth = info->depth; + mode_cmd.bpp = info->cpp[0] * 8; /** * This code should be conditioned on Screen Objects not being used. -- cgit v1.2.3 From 7ccf281fb1f9e72a18fd0eafefb321f83247e26a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:20 +0300 Subject: drm/arm: mali-dp: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() The driver doesn't need the color depth, only the number of bits per pixel. Use the right API. Signed-off-by: Laurent Pinchart Reviewed-by: Daniel Vetter Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-13-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/arm/malidp_hw.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index a6132f1d58c1..be815d0cc772 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -198,9 +198,6 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode * static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt) { - unsigned int depth; - int bpp; - /* RGB888 or BGR888 can't be rotated */ if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888)) return -EINVAL; @@ -210,9 +207,7 @@ static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 * worth of pixel data. Required size is then: * size = rotated_width * (bpp / 8) * 8; */ - drm_fb_get_bpp_depth(fmt, &depth, &bpp); - - return w * bpp; + return w * drm_format_plane_cpp(fmt, 0) * 8; } static int malidp550_query_hw(struct malidp_hw_device *hwdev) -- cgit v1.2.3 From 488546fc4d246698d4db9c46f7ec06c4839a18e1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 18 Oct 2016 01:41:21 +0300 Subject: drm: Don't export the drm_fb_get_bpp_depth() function The function is only used by the drm_helper_mode_fill_fb_struct() core function to fill the drm_framebuffer bpp and depth fields, used by drivers that haven't been converted to use pixel formats directly yet. It should not be used by new drivers, so inline it in its only caller. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476744081-24485-14-git-send-email-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_fourcc.c | 31 ------------------------------- drivers/gpu/drm/drm_modeset_helper.c | 17 +++++++++++++++-- include/drm/drm_fourcc.h | 1 - 3 files changed, 15 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 523ed916a1c0..cbb8b77c363c 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -202,37 +202,6 @@ const struct drm_format_info *drm_format_info(u32 format) } EXPORT_SYMBOL(drm_format_info); -/** - * drm_fb_get_bpp_depth - get the bpp/depth values for format - * @format: pixel format (DRM_FORMAT_*) - * @depth: storage for the depth value - * @bpp: storage for the bpp value - * - * This only supports RGB formats here for compat with code that doesn't use - * pixel formats directly yet. - */ -void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, - int *bpp) -{ - const struct drm_format_info *info; - - info = drm_format_info(format); - if (!info || !info->depth) { - char *format_name = drm_get_format_name(format); - - DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name); - kfree(format_name); - - *depth = 0; - *bpp = 0; - return; - } - - *depth = info->depth; - *bpp = info->cpp[0] * 8; -} -EXPORT_SYMBOL(drm_fb_get_bpp_depth); - /** * drm_format_num_planes - get the number of planes for format * @format: pixel format (DRM_FORMAT_*) diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 1d45738f8f98..2544dfe7354c 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -70,8 +70,23 @@ EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, const struct drm_mode_fb_cmd2 *mode_cmd) { + const struct drm_format_info *info; int i; + info = drm_format_info(mode_cmd->pixel_format); + if (!info || !info->depth) { + char *format_name = drm_get_format_name(mode_cmd->pixel_format); + + DRM_DEBUG_KMS("non-RGB pixel format %s\n", format_name); + kfree(format_name); + + fb->depth = 0; + fb->bits_per_pixel = 0; + } else { + fb->depth = info->depth; + fb->bits_per_pixel = info->cpp[0] * 8; + } + fb->width = mode_cmd->width; fb->height = mode_cmd->height; for (i = 0; i < 4; i++) { @@ -79,8 +94,6 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, fb->offsets[i] = mode_cmd->offsets[i]; fb->modifier[i] = mode_cmd->modifier[i]; } - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, - &fb->bits_per_pixel); fb->pixel_format = mode_cmd->pixel_format; fb->flags = mode_cmd->flags; } diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index f73f97afd1e2..dc0aafab9ffd 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -48,7 +48,6 @@ struct drm_format_info { const struct drm_format_info *__drm_format_info(u32 format); const struct drm_format_info *drm_format_info(u32 format); uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); -void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); int drm_format_num_planes(uint32_t format); int drm_format_plane_cpp(uint32_t format, int plane); int drm_format_horz_chroma_subsampling(uint32_t format); -- cgit v1.2.3 From 21e33021a7cfa3a9e402a58cd44fd781d97466f2 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Fri, 14 Oct 2016 16:47:05 -0700 Subject: drm/i915/guc: Sanitory checks for platform that dont have GuC i915.enable_guc_loading/submission=2 forces the usage of GuC. For platforms that do not have a GuC, asking the kernel to use a GuC should not result in an error state. Do extra checks to see if the platform even has a GuC or not, regardless of the kernel parameter. v2: Based on Rodrigo's patch and Paulo's suggestion(Paulo, Rodrigo) v3: Correct the Indentation(Jani, Paulo) v4: Added the blank line(Jani, Paulo) v5 (from Paulo): Remove the extra blank line. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97573 Cc: Rodrigo Vivi Cc: Zanoni Paulo Cc: Jani Nikula Reviewed-by: Paulo Zanoni Signed-off-by: Anusha Srivatsa Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1476488825-5673-1-git-send-email-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/intel_guc_loader.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 678b51a24a23..3c8eaae13732 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -719,11 +719,16 @@ void intel_guc_init(struct drm_device *dev) struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; const char *fw_path; - /* A negative value means "use platform default" */ - if (i915.enable_guc_loading < 0) - i915.enable_guc_loading = HAS_GUC_UCODE(dev); - if (i915.enable_guc_submission < 0) - i915.enable_guc_submission = HAS_GUC_SCHED(dev); + if (!HAS_GUC(dev)) { + i915.enable_guc_loading = 0; + i915.enable_guc_submission = 0; + } else { + /* A negative value means "use platform default" */ + if (i915.enable_guc_loading < 0) + i915.enable_guc_loading = HAS_GUC_UCODE(dev); + if (i915.enable_guc_submission < 0) + i915.enable_guc_submission = HAS_GUC_SCHED(dev); + } if (!HAS_GUC_UCODE(dev)) { fw_path = NULL; -- cgit v1.2.3 From ee3d532fcb64872bc20be0ee58f7afdb9fa82abe Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 11 Oct 2016 15:25:38 -0300 Subject: drm/i915/gen9: unconditionally apply the memory bandwidth WA Mahesh Kumar is already working on a proper implementation for the workaround, but while we still don't have it, let's just unconditionally apply the workaround for everybody and we hope we can close all those numerous bugzilla tickets. Also, I'm not sure how easy it will be to backport the final implementation to the stable Kernels, and this patch here is probably easier to backport. At the present moment I still don't have confirmation that this patch fixes any of the bugs listed below, but we should definitely try testing all of them again. v2: s/intel_needs_memory_bw_wa/skl_needs_memory_bw_wa/ (Lyude). v3: Rebase (dev -> dev_priv change on ilk_wm_max_level). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94337 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94605 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94884 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=95010 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96226 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96828 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97450 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97830 Cc: stable@vger.kernel.org Cc: Mahesh Kumar Cc: Lyude Cc: Dhinakaran Pandiyan Signed-off-by: Paulo Zanoni Reviewed-by: Lyude Link: http://patchwork.freedesktop.org/patch/msgid/1476210338-9797-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 49 ++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9ae23384976c..8b528b279aaa 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2883,6 +2883,21 @@ skl_wm_plane_id(const struct intel_plane *plane) } } +/* + * FIXME: We still don't have the proper code detect if we need to apply the WA, + * so assume we'll always need it in order to avoid underruns. + */ +static bool skl_needs_memory_bw_wa(struct intel_atomic_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + + if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) || + IS_KABYLAKE(dev_priv)) + return true; + + return false; +} + static bool intel_has_sagv(struct drm_i915_private *dev_priv) { @@ -3003,9 +3018,10 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) struct drm_device *dev = state->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_atomic_state *intel_state = to_intel_atomic_state(state); - struct drm_crtc *crtc; + struct intel_crtc *crtc; + struct intel_plane *plane; enum pipe pipe; - int level, plane; + int level, id, latency; if (!intel_has_sagv(dev_priv)) return false; @@ -3023,27 +3039,36 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) /* Since we're now guaranteed to only have one active CRTC... */ pipe = ffs(intel_state->active_crtcs) - 1; - crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); - if (crtc->state->mode.flags & DRM_MODE_FLAG_INTERLACE) + if (crtc->base.state->mode.flags & DRM_MODE_FLAG_INTERLACE) return false; - for_each_plane(dev_priv, pipe, plane) { + for_each_intel_plane_on_crtc(dev, crtc, plane) { + id = skl_wm_plane_id(plane); + /* Skip this plane if it's not enabled */ - if (intel_state->wm_results.plane[pipe][plane][0] == 0) + if (intel_state->wm_results.plane[pipe][id][0] == 0) continue; /* Find the highest enabled wm level for this plane */ for (level = ilk_wm_max_level(dev_priv); - intel_state->wm_results.plane[pipe][plane][level] == 0; --level) + intel_state->wm_results.plane[pipe][id][level] == 0; --level) { } + latency = dev_priv->wm.skl_latency[level]; + + if (skl_needs_memory_bw_wa(intel_state) && + plane->base.state->fb->modifier[0] == + I915_FORMAT_MOD_X_TILED) + latency += 15; + /* * If any of the planes on this pipe don't enable wm levels * that incur memory latencies higher then 30µs we can't enable * the SAGV */ - if (dev_priv->wm.skl_latency[level] < SKL_SAGV_BLOCK_TIME) + if (latency < SKL_SAGV_BLOCK_TIME) return false; } @@ -3558,12 +3583,18 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t width = 0, height = 0; uint32_t plane_pixel_rate; uint32_t y_tile_minimum, y_min_scanlines; + struct intel_atomic_state *state = + to_intel_atomic_state(cstate->base.state); + bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state); if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { *enabled = false; return 0; } + if (apply_memory_bw_wa && fb->modifier[0] == I915_FORMAT_MOD_X_TILED) + latency += 15; + width = drm_rect_width(&intel_pstate->base.src) >> 16; height = drm_rect_height(&intel_pstate->base.src) >> 16; @@ -3616,6 +3647,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, plane_blocks_per_line); y_tile_minimum = plane_blocks_per_line * y_min_scanlines; + if (apply_memory_bw_wa) + y_tile_minimum *= 2; if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { -- cgit v1.2.3 From c89cadd50b0117477935404e0054a35251cfa654 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 10 Oct 2016 17:30:59 -0300 Subject: drm/i915/gen9: look for adjusted_mode in the SAGV check for interlaced We want to look at the mode that we're actually going to set. All the other display checks for interlaced flags also look at adjusted_mode. Cc: Lyude Signed-off-by: Paulo Zanoni Reviewed-by: Lyude Link: http://patchwork.freedesktop.org/patch/msgid/1476131459-23763-2-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8b528b279aaa..105540996616 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3041,7 +3041,7 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) pipe = ffs(intel_state->active_crtcs) - 1; crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); - if (crtc->base.state->mode.flags & DRM_MODE_FLAG_INTERLACE) + if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) return false; for_each_intel_plane_on_crtc(dev, crtc, plane) { -- cgit v1.2.3 From cfd7e3a20251b9ac95651d64556f87f86128a966 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 7 Oct 2016 17:28:57 -0300 Subject: drm/i915/gen9: fix watermarks when using the pipe scaler Luckily, the necessary adjustments for when we're using the scaler are exactly the same as the ones needed on ILK+, so just reuse the function we already have. v2: Invert the patch order so stable backports get easier. Cc: stable@vger.kernel.org Signed-off-by: Paulo Zanoni Reviewed-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1475872138-16194-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 105540996616..b6c665bebebc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3498,12 +3498,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, return 0; } -static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config) -{ - /* TODO: Take into account the scalers once we support them */ - return config->base.adjusted_mode.crtc_clock; -} - /* * The max latency should be 257 (max the punit can code is 255 and we add 2us * for the read latency) and cpp should always be <= 8, so that @@ -3554,7 +3548,7 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst * Adjusted plane pixel rate is just the pipe's adjusted pixel rate * with additional adjustments for plane-specific scaling. */ - adjusted_pixel_rate = skl_pipe_pixel_rate(cstate); + adjusted_pixel_rate = ilk_pipe_pixel_rate(cstate); downscale_amount = skl_plane_downscale_amount(pstate); pixel_rate = adjusted_pixel_rate * downscale_amount >> 16; @@ -3763,11 +3757,11 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) if (!cstate->base.active) return 0; - if (WARN_ON(skl_pipe_pixel_rate(cstate) == 0)) + if (WARN_ON(ilk_pipe_pixel_rate(cstate) == 0)) return 0; return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000, - skl_pipe_pixel_rate(cstate)); + ilk_pipe_pixel_rate(cstate)); } static void skl_compute_transition_wm(struct intel_crtc_state *cstate, -- cgit v1.2.3 From 30d1b5fe8c7206e6e5e5e51e0ff09ef21a77d78e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 7 Oct 2016 17:28:58 -0300 Subject: drm/i915/gen9: don't call ilk_pipe_pixel_rate() twice on the same function We used to call skl_pipe_pixel_rate(), which used to be a single one-line return, but now we're calling ilk_pipe_pixel_rate() which is not as simple, so it's better to just call it once and store the computed value for reuse. Signed-off-by: Paulo Zanoni Reviewed-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1475872138-16194-2-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b6c665bebebc..48d2b71d5e11 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3754,14 +3754,18 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, static uint32_t skl_compute_linetime_wm(struct intel_crtc_state *cstate) { + uint32_t pixel_rate; + if (!cstate->base.active) return 0; - if (WARN_ON(ilk_pipe_pixel_rate(cstate) == 0)) + pixel_rate = ilk_pipe_pixel_rate(cstate); + + if (WARN_ON(pixel_rate == 0)) return 0; return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000, - ilk_pipe_pixel_rate(cstate)); + pixel_rate); } static void skl_compute_transition_wm(struct intel_crtc_state *cstate, -- cgit v1.2.3 From 3ef7f228931a7ac1e4150b4dfc8d58586815f281 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 18 Oct 2016 13:02:48 +0100 Subject: drm/i915: Bump object bookkeeping to u64 from size_t Internally we allow for using more objects than a single process can allocate, i.e. we allow for a 64bit GPU address space even on a 32bit system. Using size_t may oveerflow. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161018120251.25043-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 515c206ba653..dc057c770146 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -392,7 +392,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data) if (ret) return ret; - seq_printf(m, "%u objects, %zu bytes\n", + seq_printf(m, "%u objects, %llu bytes\n", dev_priv->mm.object_count, dev_priv->mm.object_memory); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8a1020f6c9cc..cabcd06c84bd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1389,7 +1389,7 @@ struct i915_gem_mm { /* accounting, useful for userland debugging */ spinlock_t object_stat_lock; - size_t object_memory; + u64 object_memory; u32 object_count; }; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fe92e28ea0a8..838dc159a2d1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -82,7 +82,7 @@ remove_mappable_node(struct drm_mm_node *node) /* some bookkeeping */ static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, - size_t size) + u64 size) { spin_lock(&dev_priv->mm.object_stat_lock); dev_priv->mm.object_count++; @@ -91,7 +91,7 @@ static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, } static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, - size_t size) + u64 size) { spin_lock(&dev_priv->mm.object_stat_lock); dev_priv->mm.object_count--; -- cgit v1.2.3 From b4bcbe2a90a1127a6dad72fbda27e77705d9e0f4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 18 Oct 2016 13:02:49 +0100 Subject: drm/i915: Document our internal limit on object size In many places, we try to count pages using a 32 bit integer. That implies if we are asked to create an object larger than 43bits, we will subtly crash much later. Catch this on the boundary, and add a warning to remind ourselves later on our exabyte systems. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161018120251.25043-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index cabcd06c84bd..33c44c631bab 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3107,7 +3107,7 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj); void i915_gem_object_init(struct drm_i915_gem_object *obj, const struct drm_i915_gem_object_ops *ops); struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev, - size_t size); + u64 size); struct drm_i915_gem_object *i915_gem_object_create_from_data( struct drm_device *dev, const void *data, size_t size); void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 838dc159a2d1..6165a3b0e3a4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4131,14 +4131,29 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = { .put_pages = i915_gem_object_put_pages_gtt, }; -struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev, - size_t size) +/* Note we don't consider signbits :| */ +#define overflows_type(x, T) \ + (sizeof(x) > sizeof(T) && (x) >> (sizeof(T) * BITS_PER_BYTE)) + +struct drm_i915_gem_object * +i915_gem_object_create(struct drm_device *dev, u64 size) { struct drm_i915_gem_object *obj; struct address_space *mapping; gfp_t mask; int ret; + /* There is a prevalence of the assumption that we fit the object's + * page count inside a 32bit _signed_ variable. Let's document this and + * catch if we ever need to fix it. In the meantime, if you do spot + * such a local variable, please consider fixing! + */ + if (WARN_ON(size >> PAGE_SHIFT > INT_MAX)) + return ERR_PTR(-E2BIG); + + if (overflows_type(size, obj->base.size)) + return ERR_PTR(-E2BIG); + obj = i915_gem_object_alloc(dev); if (obj == NULL) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From 4ff340f0617d02ab67a087977883ef8eff36bd68 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 18 Oct 2016 13:02:50 +0100 Subject: drm/i915: Limit the scattergather coalescing to 32bits The scattergather list uses a 32bit size counter, we should avoid exceeding it. v2: Also we should use unsigned int to match sg->length. Fixes: 871dfbd67d4e ("drm/i915: Allow compaction upto SWIOTLB max segment size") Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161018120251.25043-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6165a3b0e3a4..9bb72e503a30 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2205,7 +2205,7 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) return 0; } -static unsigned long swiotlb_max_size(void) +static unsigned int swiotlb_max_size(void) { #if IS_ENABLED(CONFIG_SWIOTLB) return rounddown(swiotlb_nr_tbl() << IO_TLB_SHIFT, PAGE_SIZE); @@ -2225,7 +2225,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) struct sgt_iter sgt_iter; struct page *page; unsigned long last_pfn = 0; /* suppress gcc warning */ - unsigned long max_segment; + unsigned int max_segment; int ret; gfp_t gfp; @@ -2238,7 +2238,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) max_segment = swiotlb_max_size(); if (!max_segment) - max_segment = obj->base.size; + max_segment = rounddown(UINT_MAX, PAGE_SIZE); st = kmalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) -- cgit v1.2.3 From ebc0808fa2da0548a78e715858024cb81cd732bc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 18 Oct 2016 13:02:51 +0100 Subject: drm/i915: Restrict pagefault disabling to just around copy_from_user() When handling execbuf relocations, we play a delicate dance with pagefault. We first try to access the user pages underneath our struct_mutex. However, if those pages were inside a GEM object, we may trigger a pagefault and deadlock as i915_gem_fault() tries to recursively acquire struct_mutex. Instead, we choose to disable pagefaulting around the copy_from_user whilst inside the struct_mutex and handle the EFAULT by falling back to a copy outside the struct_mutex. We however presumed that disabling pagefaults would be expensive. It is just an operation on the local current task. Cheap enough that we can restrict the disable/enable to the critical section around the copy, and so avoid having to handle the atomic sections within the relocation handling itself. v2: Just illustrate the broken error handling rather than argue why it is safer to ignore it, for now. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161018120251.25043-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 71 +++++++++++++++--------------- 1 file changed, 35 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 1d02e74ce62d..d7a663e6a8b2 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -551,20 +551,6 @@ repeat: return 0; } -static bool object_is_idle(struct drm_i915_gem_object *obj) -{ - unsigned long active = i915_gem_object_get_active(obj); - int idx; - - for_each_active(active, idx) { - if (!i915_gem_active_is_idle(&obj->last_read[idx], - &obj->base.dev->struct_mutex)) - return false; - } - - return true; -} - static int i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, struct eb_vmas *eb, @@ -648,10 +634,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, return -EINVAL; } - /* We can't wait for rendering with pagefaults disabled */ - if (pagefault_disabled() && !object_is_idle(obj)) - return -EFAULT; - ret = relocate_entry(obj, reloc, cache, target_offset); if (ret) return ret; @@ -678,12 +660,23 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma, remain = entry->relocation_count; while (remain) { struct drm_i915_gem_relocation_entry *r = stack_reloc; - int count = remain; - if (count > ARRAY_SIZE(stack_reloc)) - count = ARRAY_SIZE(stack_reloc); + unsigned long unwritten; + unsigned int count; + + count = min_t(unsigned int, remain, ARRAY_SIZE(stack_reloc)); remain -= count; - if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0]))) { + /* This is the fast path and we cannot handle a pagefault + * whilst holding the struct mutex lest the user pass in the + * relocations contained within a mmaped bo. For in such a case + * we, the page fault handler would call i915_gem_fault() and + * we would try to acquire the struct mutex again. Obviously + * this is bad and so lockdep complains vehemently. + */ + pagefault_disable(); + unwritten = __copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0])); + pagefault_enable(); + if (unlikely(unwritten)) { ret = -EFAULT; goto out; } @@ -695,11 +688,26 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma, if (ret) goto out; - if (r->presumed_offset != offset && - __put_user(r->presumed_offset, - &user_relocs->presumed_offset)) { - ret = -EFAULT; - goto out; + if (r->presumed_offset != offset) { + pagefault_disable(); + unwritten = __put_user(r->presumed_offset, + &user_relocs->presumed_offset); + pagefault_enable(); + if (unlikely(unwritten)) { + /* Note that reporting an error now + * leaves everything in an inconsistent + * state as we have *already* changed + * the relocation value inside the + * object. As we have not changed the + * reloc.presumed_offset or will not + * change the execobject.offset, on the + * call we may not rewrite the value + * inside the object, leaving it + * dangling and causing a GPU hang. + */ + ret = -EFAULT; + goto out; + } } user_relocs++; @@ -739,20 +747,11 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb) struct i915_vma *vma; int ret = 0; - /* This is the fast path and we cannot handle a pagefault whilst - * holding the struct mutex lest the user pass in the relocations - * contained within a mmaped bo. For in such a case we, the page - * fault handler would call i915_gem_fault() and we would try to - * acquire the struct mutex again. Obviously this is bad and so - * lockdep complains vehemently. - */ - pagefault_disable(); list_for_each_entry(vma, &eb->vmas, exec_list) { ret = i915_gem_execbuffer_relocate_vma(vma, eb); if (ret) break; } - pagefault_enable(); return ret; } -- cgit v1.2.3 From bb6869b2147817385e0261f928b942f466f74a63 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Tue, 18 Oct 2016 10:39:06 +0100 Subject: remoteproc: st_slim_rproc: add a slimcore rproc driver slim core is used as a basis for many IPs in the STi chipsets such as fdma and demux. To avoid duplicating the elf loading code in each device driver a slim rproc driver has been created. This driver is designed to be used by other device drivers such as fdma, or demux whose IP is based around a slim core. The device driver can call slim_rproc_alloc() to allocate a slim rproc and slim_rproc_put() when finished. This driver takes care of ioremapping the slim registers (dmem, imem, slimcore, peripherals), whose offsets and sizes can change between IP's. It also obtains and enables any clocks used by the device. This approach avoids having a double mapping of the registers as slim_rproc does not register its own platform device. It also maps well to device tree abstraction as it allows us to have one dt node for the whole device. All of the generic rproc elf loading code can be reused, and we provide start() stop() hooks to start and stop the slim core once the firmware has been loaded. This has been tested successfully with fdma driver. Signed-off-by: Peter Griffin Signed-off-by: Vinod Koul --- drivers/remoteproc/Kconfig | 7 +- drivers/remoteproc/Makefile | 1 + drivers/remoteproc/st_slim_rproc.c | 364 +++++++++++++++++++++++++++++++ include/linux/remoteproc/st_slim_rproc.h | 58 +++++ 4 files changed, 428 insertions(+), 2 deletions(-) create mode 100644 drivers/remoteproc/st_slim_rproc.c create mode 100644 include/linux/remoteproc/st_slim_rproc.h (limited to 'drivers') diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f396bfef5d42..9270c8e596f7 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -58,7 +58,6 @@ config DA8XX_REMOTEPROC tristate "DA8xx/OMAP-L13x remoteproc support" depends on ARCH_DAVINCI_DA8XX select CMA if MMU - select REMOTEPROC select RPMSG_VIRTIO help Say y here to support DA8xx/OMAP-L13x remote processors via the @@ -99,10 +98,10 @@ config QCOM_WCNSS_PIL tristate "Qualcomm WCNSS Peripheral Image Loader" depends on OF && ARCH_QCOM depends on QCOM_SMEM + depends on REMOTEPROC select QCOM_MDT_LOADER select QCOM_SCM select QCOM_WCNSS_IRIS - select REMOTEPROC help Say y here to support the Peripheral Image Loader for the Qualcomm Wireless Connectivity Subsystem. @@ -116,4 +115,8 @@ config ST_REMOTEPROC processor framework. This can be either built-in or a loadable module. +config ST_SLIM_REMOTEPROC + tristate + select REMOTEPROC + endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 6dfb62ed643f..924f0cb25470 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_QCOM_Q6V5_PIL) += qcom_q6v5_pil.o obj-$(CONFIG_QCOM_WCNSS_IRIS) += qcom_wcnss_iris.o obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss.o obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o +obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c new file mode 100644 index 000000000000..1484e9717946 --- /dev/null +++ b/drivers/remoteproc/st_slim_rproc.c @@ -0,0 +1,364 @@ +/* + * SLIM core rproc driver + * + * Copyright (C) 2016 STMicroelectronics + * + * Author: Peter Griffin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "remoteproc_internal.h" + +/* SLIM core registers */ +#define SLIM_ID_OFST 0x0 +#define SLIM_VER_OFST 0x4 + +#define SLIM_EN_OFST 0x8 +#define SLIM_EN_RUN BIT(0) + +#define SLIM_CLK_GATE_OFST 0xC +#define SLIM_CLK_GATE_DIS BIT(0) +#define SLIM_CLK_GATE_RESET BIT(2) + +#define SLIM_SLIM_PC_OFST 0x20 + +/* DMEM registers */ +#define SLIM_REV_ID_OFST 0x0 +#define SLIM_REV_ID_MIN_MASK GENMASK(15, 8) +#define SLIM_REV_ID_MIN(id) ((id & SLIM_REV_ID_MIN_MASK) >> 8) +#define SLIM_REV_ID_MAJ_MASK GENMASK(23, 16) +#define SLIM_REV_ID_MAJ(id) ((id & SLIM_REV_ID_MAJ_MASK) >> 16) + + +/* peripherals registers */ +#define SLIM_STBUS_SYNC_OFST 0xF88 +#define SLIM_STBUS_SYNC_DIS BIT(0) + +#define SLIM_INT_SET_OFST 0xFD4 +#define SLIM_INT_CLR_OFST 0xFD8 +#define SLIM_INT_MASK_OFST 0xFDC + +#define SLIM_CMD_CLR_OFST 0xFC8 +#define SLIM_CMD_MASK_OFST 0xFCC + +static const char *mem_names[ST_SLIM_MEM_MAX] = { + [ST_SLIM_DMEM] = "dmem", + [ST_SLIM_IMEM] = "imem", +}; + +static int slim_clk_get(struct st_slim_rproc *slim_rproc, struct device *dev) +{ + int clk, err; + + for (clk = 0; clk < ST_SLIM_MAX_CLK; clk++) { + slim_rproc->clks[clk] = of_clk_get(dev->of_node, clk); + if (IS_ERR(slim_rproc->clks[clk])) { + err = PTR_ERR(slim_rproc->clks[clk]); + if (err == -EPROBE_DEFER) + goto err_put_clks; + slim_rproc->clks[clk] = NULL; + break; + } + } + + return 0; + +err_put_clks: + while (--clk >= 0) + clk_put(slim_rproc->clks[clk]); + + return err; +} + +static void slim_clk_disable(struct st_slim_rproc *slim_rproc) +{ + int clk; + + for (clk = 0; clk < ST_SLIM_MAX_CLK && slim_rproc->clks[clk]; clk++) + clk_disable_unprepare(slim_rproc->clks[clk]); +} + +static int slim_clk_enable(struct st_slim_rproc *slim_rproc) +{ + int clk, ret; + + for (clk = 0; clk < ST_SLIM_MAX_CLK && slim_rproc->clks[clk]; clk++) { + ret = clk_prepare_enable(slim_rproc->clks[clk]); + if (ret) + goto err_disable_clks; + } + + return 0; + +err_disable_clks: + while (--clk >= 0) + clk_disable_unprepare(slim_rproc->clks[clk]); + + return ret; +} + +/* + * Remoteproc slim specific device handlers + */ +static int slim_rproc_start(struct rproc *rproc) +{ + struct device *dev = &rproc->dev; + struct st_slim_rproc *slim_rproc = rproc->priv; + unsigned long hw_id, hw_ver, fw_rev; + u32 val; + + /* disable CPU pipeline clock & reset CPU pipeline */ + val = SLIM_CLK_GATE_DIS | SLIM_CLK_GATE_RESET; + writel(val, slim_rproc->slimcore + SLIM_CLK_GATE_OFST); + + /* disable SLIM core STBus sync */ + writel(SLIM_STBUS_SYNC_DIS, slim_rproc->peri + SLIM_STBUS_SYNC_OFST); + + /* enable cpu pipeline clock */ + writel(!SLIM_CLK_GATE_DIS, + slim_rproc->slimcore + SLIM_CLK_GATE_OFST); + + /* clear int & cmd mailbox */ + writel(~0U, slim_rproc->peri + SLIM_INT_CLR_OFST); + writel(~0U, slim_rproc->peri + SLIM_CMD_CLR_OFST); + + /* enable all channels cmd & int */ + writel(~0U, slim_rproc->peri + SLIM_INT_MASK_OFST); + writel(~0U, slim_rproc->peri + SLIM_CMD_MASK_OFST); + + /* enable cpu */ + writel(SLIM_EN_RUN, slim_rproc->slimcore + SLIM_EN_OFST); + + hw_id = readl_relaxed(slim_rproc->slimcore + SLIM_ID_OFST); + hw_ver = readl_relaxed(slim_rproc->slimcore + SLIM_VER_OFST); + + fw_rev = readl(slim_rproc->mem[ST_SLIM_DMEM].cpu_addr + + SLIM_REV_ID_OFST); + + dev_info(dev, "fw rev:%ld.%ld on SLIM %ld.%ld\n", + SLIM_REV_ID_MAJ(fw_rev), SLIM_REV_ID_MIN(fw_rev), + hw_id, hw_ver); + + return 0; +} + +static int slim_rproc_stop(struct rproc *rproc) +{ + struct st_slim_rproc *slim_rproc = rproc->priv; + u32 val; + + /* mask all (cmd & int) channels */ + writel(0UL, slim_rproc->peri + SLIM_INT_MASK_OFST); + writel(0UL, slim_rproc->peri + SLIM_CMD_MASK_OFST); + + /* disable cpu pipeline clock */ + writel(SLIM_CLK_GATE_DIS, slim_rproc->slimcore + SLIM_CLK_GATE_OFST); + + writel(!SLIM_EN_RUN, slim_rproc->slimcore + SLIM_EN_OFST); + + val = readl(slim_rproc->slimcore + SLIM_EN_OFST); + if (val & SLIM_EN_RUN) + dev_warn(&rproc->dev, "Failed to disable SLIM"); + + dev_dbg(&rproc->dev, "slim stopped\n"); + + return 0; +} + +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len) +{ + struct st_slim_rproc *slim_rproc = rproc->priv; + void *va = NULL; + int i; + + for (i = 0; i < ST_SLIM_MEM_MAX; i++) { + if (da != slim_rproc->mem[i].bus_addr) + continue; + + if (len <= slim_rproc->mem[i].size) { + /* __force to make sparse happy with type conversion */ + va = (__force void *)slim_rproc->mem[i].cpu_addr; + break; + } + } + + dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va); + + return va; +} + +static struct rproc_ops slim_rproc_ops = { + .start = slim_rproc_start, + .stop = slim_rproc_stop, + .da_to_va = slim_rproc_da_to_va, +}; + +/* + * Firmware handler operations: sanity, boot address, load ... + */ + +static struct resource_table empty_rsc_tbl = { + .ver = 1, + .num = 0, +}; + +static struct resource_table *slim_rproc_find_rsc_table(struct rproc *rproc, + const struct firmware *fw, + int *tablesz) +{ + *tablesz = sizeof(empty_rsc_tbl); + return &empty_rsc_tbl; +} + +static struct rproc_fw_ops slim_rproc_fw_ops = { + .find_rsc_table = slim_rproc_find_rsc_table, +}; + +/** + * st_slim_rproc_alloc() - allocate and initialise slim rproc + * @pdev: Pointer to the platform_device struct + * @fw_name: Name of firmware for rproc to use + * + * Function for allocating and initialising a slim rproc for use by + * device drivers whose IP is based around the SLIM core. It + * obtains and enables any clocks required by the SLIM core and also + * ioremaps the various IO. + * + * Returns st_slim_rproc pointer or PTR_ERR() on error. + */ + +struct st_slim_rproc *st_slim_rproc_alloc(struct platform_device *pdev, + char *fw_name) +{ + struct device *dev = &pdev->dev; + struct st_slim_rproc *slim_rproc; + struct device_node *np = dev->of_node; + struct rproc *rproc; + struct resource *res; + int err, i; + const struct rproc_fw_ops *elf_ops; + + if (!fw_name) + return ERR_PTR(-EINVAL); + + if (!of_device_is_compatible(np, "st,slim-rproc")) + return ERR_PTR(-EINVAL); + + rproc = rproc_alloc(dev, np->name, &slim_rproc_ops, + fw_name, sizeof(*slim_rproc)); + if (!rproc) + return ERR_PTR(-ENOMEM); + + rproc->has_iommu = false; + + slim_rproc = rproc->priv; + slim_rproc->rproc = rproc; + + elf_ops = rproc->fw_ops; + /* Use some generic elf ops */ + slim_rproc_fw_ops.load = elf_ops->load; + slim_rproc_fw_ops.sanity_check = elf_ops->sanity_check; + + rproc->fw_ops = &slim_rproc_fw_ops; + + /* get imem and dmem */ + for (i = 0; i < ARRAY_SIZE(mem_names); i++) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + mem_names[i]); + + slim_rproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(slim_rproc->mem[i].cpu_addr)) { + dev_err(&pdev->dev, "devm_ioremap_resource failed\n"); + err = PTR_ERR(slim_rproc->mem[i].cpu_addr); + goto err; + } + slim_rproc->mem[i].bus_addr = res->start; + slim_rproc->mem[i].size = resource_size(res); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimcore"); + slim_rproc->slimcore = devm_ioremap_resource(dev, res); + if (IS_ERR(slim_rproc->slimcore)) { + dev_err(&pdev->dev, "failed to ioremap slimcore IO\n"); + err = PTR_ERR(slim_rproc->slimcore); + goto err; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "peripherals"); + slim_rproc->peri = devm_ioremap_resource(dev, res); + if (IS_ERR(slim_rproc->peri)) { + dev_err(&pdev->dev, "failed to ioremap peripherals IO\n"); + err = PTR_ERR(slim_rproc->peri); + goto err; + } + + err = slim_clk_get(slim_rproc, dev); + if (err) + goto err; + + err = slim_clk_enable(slim_rproc); + if (err) { + dev_err(dev, "Failed to enable clocks\n"); + goto err_clk_put; + } + + /* Register as a remoteproc device */ + err = rproc_add(rproc); + if (err) { + dev_err(dev, "registration of slim remoteproc failed\n"); + goto err_clk_dis; + } + + return slim_rproc; + +err_clk_dis: + slim_clk_disable(slim_rproc); +err_clk_put: + for (i = 0; i < ST_SLIM_MAX_CLK && slim_rproc->clks[i]; i++) + clk_put(slim_rproc->clks[i]); +err: + rproc_put(rproc); + return ERR_PTR(err); +} +EXPORT_SYMBOL(st_slim_rproc_alloc); + +/** + * st_slim_rproc_put() - put slim rproc resources + * @slim_rproc: Pointer to the st_slim_rproc struct + * + * Function for calling respective _put() functions on slim_rproc resources. + * + */ +void st_slim_rproc_put(struct st_slim_rproc *slim_rproc) +{ + int clk; + + if (!slim_rproc) + return; + + slim_clk_disable(slim_rproc); + + for (clk = 0; clk < ST_SLIM_MAX_CLK && slim_rproc->clks[clk]; clk++) + clk_put(slim_rproc->clks[clk]); + + rproc_del(slim_rproc->rproc); + rproc_put(slim_rproc->rproc); +} +EXPORT_SYMBOL(st_slim_rproc_put); + +MODULE_AUTHOR("Peter Griffin "); +MODULE_DESCRIPTION("STMicroelectronics SLIM core rproc driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/remoteproc/st_slim_rproc.h b/include/linux/remoteproc/st_slim_rproc.h new file mode 100644 index 000000000000..4155556fa4b2 --- /dev/null +++ b/include/linux/remoteproc/st_slim_rproc.h @@ -0,0 +1,58 @@ +/* + * SLIM core rproc driver header + * + * Copyright (C) 2016 STMicroelectronics + * + * Author: Peter Griffin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef _ST_REMOTEPROC_SLIM_H +#define _ST_REMOTEPROC_SLIM_H + +#define ST_SLIM_MEM_MAX 2 +#define ST_SLIM_MAX_CLK 4 + +enum { + ST_SLIM_DMEM, + ST_SLIM_IMEM, +}; + +/** + * struct st_slim_mem - slim internal memory structure + * @cpu_addr: MPU virtual address of the memory region + * @bus_addr: Bus address used to access the memory region + * @size: Size of the memory region + */ +struct st_slim_mem { + void __iomem *cpu_addr; + phys_addr_t bus_addr; + size_t size; +}; + +/** + * struct st_slim_rproc - SLIM slim core + * @rproc: rproc handle + * @mem: slim memory information + * @slimcore: slim slimcore regs + * @peri: slim peripheral regs + * @clks: slim clocks + */ +struct st_slim_rproc { + struct rproc *rproc; + struct st_slim_mem mem[ST_SLIM_MEM_MAX]; + void __iomem *slimcore; + void __iomem *peri; + + /* st_slim_rproc private */ + struct clk *clks[ST_SLIM_MAX_CLK]; +}; + +struct st_slim_rproc *st_slim_rproc_alloc(struct platform_device *pdev, + char *fw_name); +void st_slim_rproc_put(struct st_slim_rproc *slim_rproc); + +#endif -- cgit v1.2.3 From e41ddbc00e79f06fb6cb2e09e6199ca7b557c457 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Tue, 18 Oct 2016 10:39:08 +0100 Subject: remoteproc: Update Kconfig setup to 'depends on REMOTEPROC' Make REMOTEPROC core a selectable kconfig option, and update remoteproc client drivers to 'depends on' the core. This avoids some nasty Kconfig recursive dependency issues. Also when using menuconfig client drivers will be hidden until the core has been enabled. Documentation/kbuild/kconfig-language.txt: Note: select should be used with care. select will force a symbol to a value without visiting the dependencies. By abusing select you are able to select a symbol FOO even if FOO depends on BAR that is not set. In general use select only for non-visible symbols (no prompts anywhere) and for symbols with no dependencies. That will limit the usefulness but on the other hand avoid the illegal configurations all over. Signed-off-by: Peter Griffin Signed-off-by: Vinod Koul --- drivers/remoteproc/Kconfig | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 9270c8e596f7..14d5d2d43a38 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -1,20 +1,21 @@ menu "Remoteproc drivers" -# REMOTEPROC gets selected by whoever wants it config REMOTEPROC - tristate + tristate "Support for Remote Processor subsystem" depends on HAS_DMA select CRC32 select FW_LOADER select VIRTIO select VIRTUALIZATION +if REMOTEPROC + config OMAP_REMOTEPROC tristate "OMAP remoteproc support" depends on HAS_DMA depends on ARCH_OMAP4 || SOC_OMAP5 depends on OMAP_IOMMU - select REMOTEPROC + depends on REMOTEPROC select MAILBOX select OMAP2PLUS_MBOX select RPMSG_VIRTIO @@ -34,7 +35,7 @@ config OMAP_REMOTEPROC config STE_MODEM_RPROC tristate "STE-Modem remoteproc support" depends on HAS_DMA - select REMOTEPROC + depends on REMOTEPROC default n help Say y or m here to support STE-Modem shared memory driver. @@ -44,7 +45,7 @@ config STE_MODEM_RPROC config WKUP_M3_RPROC tristate "AMx3xx Wakeup M3 remoteproc support" depends on SOC_AM33XX || SOC_AM43XX - select REMOTEPROC + depends on REMOTEPROC help Say y here to support Wakeup M3 remote processor on TI AM33xx and AM43xx family of SoCs. @@ -57,6 +58,7 @@ config WKUP_M3_RPROC config DA8XX_REMOTEPROC tristate "DA8xx/OMAP-L13x remoteproc support" depends on ARCH_DAVINCI_DA8XX + depends on REMOTEPROC select CMA if MMU select RPMSG_VIRTIO help @@ -83,9 +85,9 @@ config QCOM_Q6V5_PIL tristate "Qualcomm Hexagon V5 Peripherial Image Loader" depends on OF && ARCH_QCOM depends on QCOM_SMEM + depends on REMOTEPROC select MFD_SYSCON select QCOM_MDT_LOADER - select REMOTEPROC help Say y here to support the Qualcomm Peripherial Image Loader for the Hexagon V5 based remote processors. @@ -109,7 +111,7 @@ config QCOM_WCNSS_PIL config ST_REMOTEPROC tristate "ST remoteproc support" depends on ARCH_STI - select REMOTEPROC + depends on REMOTEPROC help Say y here to support ST's adjunct processors via the remote processor framework. @@ -117,6 +119,8 @@ config ST_REMOTEPROC config ST_SLIM_REMOTEPROC tristate - select REMOTEPROC + depends on REMOTEPROC + +endif # REMOTEPROC endmenu -- cgit v1.2.3 From 812ab065ea95f42a51fee4d40e436468199bb87d Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Tue, 18 Oct 2016 10:39:10 +0100 Subject: dmaengine: st_fdma: Add STMicroelectronics FDMA driver header file This header file will also be used by the dma xbar driver in the future. Signed-off-by: Ludovic Barre Signed-off-by: Peter Griffin Signed-off-by: Vinod Koul --- drivers/dma/st_fdma.h | 249 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 drivers/dma/st_fdma.h (limited to 'drivers') diff --git a/drivers/dma/st_fdma.h b/drivers/dma/st_fdma.h new file mode 100644 index 000000000000..c58e00d4ab37 --- /dev/null +++ b/drivers/dma/st_fdma.h @@ -0,0 +1,249 @@ +/* + * DMA driver header for STMicroelectronics STi FDMA controller + * + * Copyright (C) 2014 STMicroelectronics + * + * Author: Ludovic Barre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __DMA_ST_FDMA_H +#define __DMA_ST_FDMA_H + +#include +#include +#include +#include +#include "virt-dma.h" + +#define ST_FDMA_NR_DREQS 32 +#define FW_NAME_SIZE 30 +#define DRIVER_NAME "st-fdma" + +/** + * struct st_fdma_generic_node - Free running/paced generic node + * + * @length: Length in bytes of a line in a 2D mem to mem + * @sstride: Stride, in bytes, between source lines in a 2D data move + * @dstride: Stride, in bytes, between destination lines in a 2D data move + */ +struct st_fdma_generic_node { + u32 length; + u32 sstride; + u32 dstride; +}; + +/** + * struct st_fdma_hw_node - Node structure used by fdma hw + * + * @next: Pointer to next node + * @control: Transfer Control Parameters + * @nbytes: Number of Bytes to read + * @saddr: Source address + * @daddr: Destination address + * + * @generic: generic node for free running/paced transfert type + * 2 others transfert type are possible, but not yet implemented + * + * The NODE structures must be aligned to a 32 byte boundary + */ +struct st_fdma_hw_node { + u32 next; + u32 control; + u32 nbytes; + u32 saddr; + u32 daddr; + union { + struct st_fdma_generic_node generic; + }; +} __aligned(32); + +/* + * node control parameters + */ +#define FDMA_NODE_CTRL_REQ_MAP_MASK GENMASK(4, 0) +#define FDMA_NODE_CTRL_REQ_MAP_FREE_RUN 0x0 +#define FDMA_NODE_CTRL_REQ_MAP_DREQ(n) ((n)&FDMA_NODE_CTRL_REQ_MAP_MASK) +#define FDMA_NODE_CTRL_REQ_MAP_EXT FDMA_NODE_CTRL_REQ_MAP_MASK +#define FDMA_NODE_CTRL_SRC_MASK GENMASK(6, 5) +#define FDMA_NODE_CTRL_SRC_STATIC BIT(5) +#define FDMA_NODE_CTRL_SRC_INCR BIT(6) +#define FDMA_NODE_CTRL_DST_MASK GENMASK(8, 7) +#define FDMA_NODE_CTRL_DST_STATIC BIT(7) +#define FDMA_NODE_CTRL_DST_INCR BIT(8) +#define FDMA_NODE_CTRL_SECURE BIT(15) +#define FDMA_NODE_CTRL_PAUSE_EON BIT(30) +#define FDMA_NODE_CTRL_INT_EON BIT(31) + +/** + * struct st_fdma_sw_node - descriptor structure for link list + * + * @pdesc: Physical address of desc + * @node: link used for putting this into a channel queue + */ +struct st_fdma_sw_node { + dma_addr_t pdesc; + struct st_fdma_hw_node *desc; +}; + +#define NAME_SZ 10 + +struct st_fdma_driverdata { + u32 id; + char name[NAME_SZ]; +}; + +struct st_fdma_desc { + struct virt_dma_desc vdesc; + struct st_fdma_chan *fchan; + bool iscyclic; + unsigned int n_nodes; + struct st_fdma_sw_node node[]; +}; + +enum st_fdma_type { + ST_FDMA_TYPE_FREE_RUN, + ST_FDMA_TYPE_PACED, +}; + +struct st_fdma_cfg { + struct device_node *of_node; + enum st_fdma_type type; + dma_addr_t dev_addr; + enum dma_transfer_direction dir; + int req_line; /* request line */ + long req_ctrl; /* Request control */ +}; + +struct st_fdma_chan { + struct st_fdma_dev *fdev; + struct dma_pool *node_pool; + struct dma_slave_config scfg; + struct st_fdma_cfg cfg; + + int dreq_line; + + struct virt_dma_chan vchan; + struct st_fdma_desc *fdesc; + enum dma_status status; +}; + +struct st_fdma_dev { + struct device *dev; + const struct st_fdma_driverdata *drvdata; + struct dma_device dma_device; + + struct st_slim_rproc *slim_rproc; + + int irq; + + struct st_fdma_chan *chans; + + spinlock_t dreq_lock; + unsigned long dreq_mask; + + u32 nr_channels; + char fw_name[FW_NAME_SIZE]; +}; + +/* Peripheral Registers*/ + +#define FDMA_CMD_STA_OFST 0xFC0 +#define FDMA_CMD_SET_OFST 0xFC4 +#define FDMA_CMD_CLR_OFST 0xFC8 +#define FDMA_CMD_MASK_OFST 0xFCC +#define FDMA_CMD_START(ch) (0x1 << (ch << 1)) +#define FDMA_CMD_PAUSE(ch) (0x2 << (ch << 1)) +#define FDMA_CMD_FLUSH(ch) (0x3 << (ch << 1)) + +#define FDMA_INT_STA_OFST 0xFD0 +#define FDMA_INT_STA_CH 0x1 +#define FDMA_INT_STA_ERR 0x2 + +#define FDMA_INT_SET_OFST 0xFD4 +#define FDMA_INT_CLR_OFST 0xFD8 +#define FDMA_INT_MASK_OFST 0xFDC + +#define fdma_read(fdev, name) \ + readl((fdev)->slim_rproc->peri + name) + +#define fdma_write(fdev, val, name) \ + writel((val), (fdev)->slim_rproc->peri + name) + +/* fchan interface (dmem) */ +#define FDMA_CH_CMD_OFST 0x200 +#define FDMA_CH_CMD_STA_MASK GENMASK(1, 0) +#define FDMA_CH_CMD_STA_IDLE (0x0) +#define FDMA_CH_CMD_STA_START (0x1) +#define FDMA_CH_CMD_STA_RUNNING (0x2) +#define FDMA_CH_CMD_STA_PAUSED (0x3) +#define FDMA_CH_CMD_ERR_MASK GENMASK(4, 2) +#define FDMA_CH_CMD_ERR_INT (0x0 << 2) +#define FDMA_CH_CMD_ERR_NAND (0x1 << 2) +#define FDMA_CH_CMD_ERR_MCHI (0x2 << 2) +#define FDMA_CH_CMD_DATA_MASK GENMASK(31, 5) +#define fchan_read(fchan, name) \ + readl((fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + + (fchan)->vchan.chan.chan_id * 0x4 \ + + name) + +#define fchan_write(fchan, val, name) \ + writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + + (fchan)->vchan.chan.chan_id * 0x4 \ + + name) + +/* req interface */ +#define FDMA_REQ_CTRL_OFST 0x240 +#define dreq_write(fchan, val, name) \ + writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + + fchan->dreq_line * 0x04 \ + + name) +/* node interface */ +#define FDMA_NODE_SZ 128 +#define FDMA_PTRN_OFST 0x800 +#define FDMA_CNTN_OFST 0x808 +#define FDMA_SADDRN_OFST 0x80c +#define FDMA_DADDRN_OFST 0x810 +#define fnode_read(fchan, name) \ + readl((fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + + (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \ + + name) + +#define fnode_write(fchan, val, name) \ + writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + + (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \ + + name) + +/* + * request control bits + */ +#define FDMA_REQ_CTRL_NUM_OPS_MASK GENMASK(31, 24) +#define FDMA_REQ_CTRL_NUM_OPS(n) (FDMA_REQ_CTRL_NUM_OPS_MASK & \ + ((n) << 24)) +#define FDMA_REQ_CTRL_INITIATOR_MASK BIT(22) +#define FDMA_REQ_CTRL_INIT0 (0x0 << 22) +#define FDMA_REQ_CTRL_INIT1 (0x1 << 22) +#define FDMA_REQ_CTRL_INC_ADDR_ON BIT(21) +#define FDMA_REQ_CTRL_DATA_SWAP_ON BIT(17) +#define FDMA_REQ_CTRL_WNR BIT(14) +#define FDMA_REQ_CTRL_OPCODE_MASK GENMASK(7, 4) +#define FDMA_REQ_CTRL_OPCODE_LD_ST1 (0x0 << 4) +#define FDMA_REQ_CTRL_OPCODE_LD_ST2 (0x1 << 4) +#define FDMA_REQ_CTRL_OPCODE_LD_ST4 (0x2 << 4) +#define FDMA_REQ_CTRL_OPCODE_LD_ST8 (0x3 << 4) +#define FDMA_REQ_CTRL_OPCODE_LD_ST16 (0x4 << 4) +#define FDMA_REQ_CTRL_OPCODE_LD_ST32 (0x5 << 4) +#define FDMA_REQ_CTRL_OPCODE_LD_ST64 (0x6 << 4) +#define FDMA_REQ_CTRL_HOLDOFF_MASK GENMASK(2, 0) +#define FDMA_REQ_CTRL_HOLDOFF(n) ((n) & FDMA_REQ_CTRL_HOLDOFF_MASK) + +/* bits used by client to configure request control */ +#define FDMA_REQ_CTRL_CFG_MASK (FDMA_REQ_CTRL_HOLDOFF_MASK | \ + FDMA_REQ_CTRL_DATA_SWAP_ON | \ + FDMA_REQ_CTRL_INC_ADDR_ON | \ + FDMA_REQ_CTRL_INITIATOR_MASK) + +#endif /* __DMA_ST_FDMA_H */ -- cgit v1.2.3 From 6b4cd727eaf15ed225b9a3a96ec1d64761ee728a Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Tue, 18 Oct 2016 10:39:11 +0100 Subject: dmaengine: st_fdma: Add STMicroelectronics FDMA engine driver support This patch adds support for the Flexible Direct Memory Access (FDMA) core driver. The FDMA is a slim core CPU with a dedicated firmware. It is a general purpose DMA controller capable of supporting 16 independent DMA channels. Data moves maybe from memory to memory or between memory and paced latency critical real time targets and it is found on al STi based chipsets. Signed-off-by: Ludovic Barre Signed-off-by: Peter Griffin Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 13 + drivers/dma/Makefile | 1 + drivers/dma/st_fdma.c | 899 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 913 insertions(+) create mode 100644 drivers/dma/st_fdma.c (limited to 'drivers') diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index af63a6bcf564..661f21791fee 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -435,6 +435,19 @@ config STE_DMA40 help Support for ST-Ericsson DMA40 controller +config ST_FDMA + tristate "ST FDMA dmaengine support" + depends on ARCH_STI + select ST_SLIM_REMOTEPROC + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Enable support for ST FDMA controller. + It supports 16 independent DMA channels, accepts up to 32 DMA requests + + Say Y here if you have such a chipset. + If unsure, say N. + config STM32_DMA bool "STMicroelectronics STM32 DMA support" depends on ARCH_STM32 || COMPILE_TEST diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index e4dc9cac7ee8..a4fa3360e609 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o obj-$(CONFIG_TI_EDMA) += edma.o obj-$(CONFIG_XGENE_DMA) += xgene-dma.o obj-$(CONFIG_ZX_DMA) += zx296702_dma.o +obj-$(CONFIG_ST_FDMA) += st_fdma.o obj-y += qcom/ obj-y += xilinx/ diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c new file mode 100644 index 000000000000..515e1d4c43e8 --- /dev/null +++ b/drivers/dma/st_fdma.c @@ -0,0 +1,899 @@ +/* + * DMA driver for STMicroelectronics STi FDMA controller + * + * Copyright (C) 2014 STMicroelectronics + * + * Author: Ludovic Barre + * Peter Griffin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "st_fdma.h" + +static inline struct st_fdma_chan *to_st_fdma_chan(struct dma_chan *c) +{ + return container_of(c, struct st_fdma_chan, vchan.chan); +} + +static struct st_fdma_desc *to_st_fdma_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct st_fdma_desc, vdesc); +} + +static int st_fdma_dreq_get(struct st_fdma_chan *fchan) +{ + struct st_fdma_dev *fdev = fchan->fdev; + u32 req_line_cfg = fchan->cfg.req_line; + u32 dreq_line; + int try = 0; + + /* + * dreq_mask is shared for n channels of fdma, so all accesses must be + * atomic. if the dreq_mask is changed between ffz and set_bit, + * we retry + */ + do { + if (fdev->dreq_mask == ~0L) { + dev_err(fdev->dev, "No req lines available\n"); + return -EINVAL; + } + + if (try || req_line_cfg >= ST_FDMA_NR_DREQS) { + dev_err(fdev->dev, "Invalid or used req line\n"); + return -EINVAL; + } else { + dreq_line = req_line_cfg; + } + + try++; + } while (test_and_set_bit(dreq_line, &fdev->dreq_mask)); + + dev_dbg(fdev->dev, "get dreq_line:%d mask:%#lx\n", + dreq_line, fdev->dreq_mask); + + return dreq_line; +} + +static void st_fdma_dreq_put(struct st_fdma_chan *fchan) +{ + struct st_fdma_dev *fdev = fchan->fdev; + + dev_dbg(fdev->dev, "put dreq_line:%#x\n", fchan->dreq_line); + clear_bit(fchan->dreq_line, &fdev->dreq_mask); +} + +static void st_fdma_xfer_desc(struct st_fdma_chan *fchan) +{ + struct virt_dma_desc *vdesc; + unsigned long nbytes, ch_cmd, cmd; + + vdesc = vchan_next_desc(&fchan->vchan); + if (!vdesc) + return; + + fchan->fdesc = to_st_fdma_desc(vdesc); + nbytes = fchan->fdesc->node[0].desc->nbytes; + cmd = FDMA_CMD_START(fchan->vchan.chan.chan_id); + ch_cmd = fchan->fdesc->node[0].pdesc | FDMA_CH_CMD_STA_START; + + /* start the channel for the descriptor */ + fnode_write(fchan, nbytes, FDMA_CNTN_OFST); + fchan_write(fchan, ch_cmd, FDMA_CH_CMD_OFST); + writel(cmd, + fchan->fdev->slim_rproc->peri + FDMA_CMD_SET_OFST); + + dev_dbg(fchan->fdev->dev, "start chan:%d\n", fchan->vchan.chan.chan_id); +} + +static void st_fdma_ch_sta_update(struct st_fdma_chan *fchan, + unsigned long int_sta) +{ + unsigned long ch_sta, ch_err; + int ch_id = fchan->vchan.chan.chan_id; + struct st_fdma_dev *fdev = fchan->fdev; + + ch_sta = fchan_read(fchan, FDMA_CH_CMD_OFST); + ch_err = ch_sta & FDMA_CH_CMD_ERR_MASK; + ch_sta &= FDMA_CH_CMD_STA_MASK; + + if (int_sta & FDMA_INT_STA_ERR) { + dev_warn(fdev->dev, "chan:%d, error:%ld\n", ch_id, ch_err); + fchan->status = DMA_ERROR; + return; + } + + switch (ch_sta) { + case FDMA_CH_CMD_STA_PAUSED: + fchan->status = DMA_PAUSED; + break; + + case FDMA_CH_CMD_STA_RUNNING: + fchan->status = DMA_IN_PROGRESS; + break; + } +} + +static irqreturn_t st_fdma_irq_handler(int irq, void *dev_id) +{ + struct st_fdma_dev *fdev = dev_id; + irqreturn_t ret = IRQ_NONE; + struct st_fdma_chan *fchan = &fdev->chans[0]; + unsigned long int_sta, clr; + + int_sta = fdma_read(fdev, FDMA_INT_STA_OFST); + clr = int_sta; + + for (; int_sta != 0 ; int_sta >>= 2, fchan++) { + if (!(int_sta & (FDMA_INT_STA_CH | FDMA_INT_STA_ERR))) + continue; + + spin_lock(&fchan->vchan.lock); + st_fdma_ch_sta_update(fchan, int_sta); + + if (fchan->fdesc) { + if (!fchan->fdesc->iscyclic) { + list_del(&fchan->fdesc->vdesc.node); + vchan_cookie_complete(&fchan->fdesc->vdesc); + fchan->fdesc = NULL; + fchan->status = DMA_COMPLETE; + } else { + vchan_cyclic_callback(&fchan->fdesc->vdesc); + } + + /* Start the next descriptor (if available) */ + if (!fchan->fdesc) + st_fdma_xfer_desc(fchan); + } + + spin_unlock(&fchan->vchan.lock); + ret = IRQ_HANDLED; + } + + fdma_write(fdev, clr, FDMA_INT_CLR_OFST); + + return ret; +} + +static struct dma_chan *st_fdma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct st_fdma_dev *fdev = ofdma->of_dma_data; + struct dma_chan *chan; + struct st_fdma_chan *fchan; + int ret; + + if (dma_spec->args_count < 1) + return ERR_PTR(-EINVAL); + + if (fdev->dma_device.dev->of_node != dma_spec->np) + return ERR_PTR(-EINVAL); + + ret = rproc_boot(fdev->slim_rproc->rproc); + if (ret == -ENOENT) + return ERR_PTR(-EPROBE_DEFER); + else if (ret) + return ERR_PTR(ret); + + chan = dma_get_any_slave_channel(&fdev->dma_device); + if (!chan) + goto err_chan; + + fchan = to_st_fdma_chan(chan); + + fchan->cfg.of_node = dma_spec->np; + fchan->cfg.req_line = dma_spec->args[0]; + fchan->cfg.req_ctrl = 0; + fchan->cfg.type = ST_FDMA_TYPE_FREE_RUN; + + if (dma_spec->args_count > 1) + fchan->cfg.req_ctrl = dma_spec->args[1] + & FDMA_REQ_CTRL_CFG_MASK; + + if (dma_spec->args_count > 2) + fchan->cfg.type = dma_spec->args[2]; + + if (fchan->cfg.type == ST_FDMA_TYPE_FREE_RUN) { + fchan->dreq_line = 0; + } else { + fchan->dreq_line = st_fdma_dreq_get(fchan); + if (IS_ERR_VALUE(fchan->dreq_line)) { + chan = ERR_PTR(fchan->dreq_line); + goto err_chan; + } + } + + dev_dbg(fdev->dev, "xlate req_line:%d type:%d req_ctrl:%#lx\n", + fchan->cfg.req_line, fchan->cfg.type, fchan->cfg.req_ctrl); + + return chan; + +err_chan: + rproc_shutdown(fdev->slim_rproc->rproc); + return chan; + +} + +static void st_fdma_free_desc(struct virt_dma_desc *vdesc) +{ + struct st_fdma_desc *fdesc; + int i; + + fdesc = to_st_fdma_desc(vdesc); + for (i = 0; i < fdesc->n_nodes; i++) + dma_pool_free(fdesc->fchan->node_pool, fdesc->node[i].desc, + fdesc->node[i].pdesc); + kfree(fdesc); +} + +static struct st_fdma_desc *st_fdma_alloc_desc(struct st_fdma_chan *fchan, + int sg_len) +{ + struct st_fdma_desc *fdesc; + int i; + + fdesc = kzalloc(sizeof(*fdesc) + + sizeof(struct st_fdma_sw_node) * sg_len, GFP_NOWAIT); + if (!fdesc) + return NULL; + + fdesc->fchan = fchan; + fdesc->n_nodes = sg_len; + for (i = 0; i < sg_len; i++) { + fdesc->node[i].desc = dma_pool_alloc(fchan->node_pool, + GFP_NOWAIT, &fdesc->node[i].pdesc); + if (!fdesc->node[i].desc) + goto err; + } + return fdesc; + +err: + while (--i >= 0) + dma_pool_free(fchan->node_pool, fdesc->node[i].desc, + fdesc->node[i].pdesc); + kfree(fdesc); + return NULL; +} + +static int st_fdma_alloc_chan_res(struct dma_chan *chan) +{ + struct st_fdma_chan *fchan = to_st_fdma_chan(chan); + + /* Create the dma pool for descriptor allocation */ + fchan->node_pool = dma_pool_create(dev_name(&chan->dev->device), + fchan->fdev->dev, + sizeof(struct st_fdma_hw_node), + __alignof__(struct st_fdma_hw_node), + 0); + + if (!fchan->node_pool) { + dev_err(fchan->fdev->dev, "unable to allocate desc pool\n"); + return -ENOMEM; + } + + dev_dbg(fchan->fdev->dev, "alloc ch_id:%d type:%d\n", + fchan->vchan.chan.chan_id, fchan->cfg.type); + + return 0; +} + +static void st_fdma_free_chan_res(struct dma_chan *chan) +{ + struct st_fdma_chan *fchan = to_st_fdma_chan(chan); + struct rproc *rproc = fchan->fdev->slim_rproc->rproc; + unsigned long flags; + + LIST_HEAD(head); + + dev_dbg(fchan->fdev->dev, "%s: freeing chan:%d\n", + __func__, fchan->vchan.chan.chan_id); + + if (fchan->cfg.type != ST_FDMA_TYPE_FREE_RUN) + st_fdma_dreq_put(fchan); + + spin_lock_irqsave(&fchan->vchan.lock, flags); + fchan->fdesc = NULL; + spin_unlock_irqrestore(&fchan->vchan.lock, flags); + + dma_pool_destroy(fchan->node_pool); + fchan->node_pool = NULL; + memset(&fchan->cfg, 0, sizeof(struct st_fdma_cfg)); + + rproc_shutdown(rproc); +} + +static struct dma_async_tx_descriptor *st_fdma_prep_dma_memcpy( + struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, + size_t len, unsigned long flags) +{ + struct st_fdma_chan *fchan; + struct st_fdma_desc *fdesc; + struct st_fdma_hw_node *hw_node; + + if (!len) + return NULL; + + fchan = to_st_fdma_chan(chan); + + /* We only require a single descriptor */ + fdesc = st_fdma_alloc_desc(fchan, 1); + if (!fdesc) { + dev_err(fchan->fdev->dev, "no memory for desc\n"); + return NULL; + } + + hw_node = fdesc->node[0].desc; + hw_node->next = 0; + hw_node->control = FDMA_NODE_CTRL_REQ_MAP_FREE_RUN; + hw_node->control |= FDMA_NODE_CTRL_SRC_INCR; + hw_node->control |= FDMA_NODE_CTRL_DST_INCR; + hw_node->control |= FDMA_NODE_CTRL_INT_EON; + hw_node->nbytes = len; + hw_node->saddr = src; + hw_node->daddr = dst; + hw_node->generic.length = len; + hw_node->generic.sstride = 0; + hw_node->generic.dstride = 0; + + return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags); +} + +static int config_reqctrl(struct st_fdma_chan *fchan, + enum dma_transfer_direction direction) +{ + u32 maxburst = 0, addr = 0; + enum dma_slave_buswidth width; + int ch_id = fchan->vchan.chan.chan_id; + struct st_fdma_dev *fdev = fchan->fdev; + + switch (direction) { + + case DMA_DEV_TO_MEM: + fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_WNR; + maxburst = fchan->scfg.src_maxburst; + width = fchan->scfg.src_addr_width; + addr = fchan->scfg.src_addr; + break; + + case DMA_MEM_TO_DEV: + fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_WNR; + maxburst = fchan->scfg.dst_maxburst; + width = fchan->scfg.dst_addr_width; + addr = fchan->scfg.dst_addr; + break; + + default: + return -EINVAL; + } + + fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_OPCODE_MASK; + + switch (width) { + + case DMA_SLAVE_BUSWIDTH_1_BYTE: + fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST1; + break; + + case DMA_SLAVE_BUSWIDTH_2_BYTES: + fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST2; + break; + + case DMA_SLAVE_BUSWIDTH_4_BYTES: + fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST4; + break; + + case DMA_SLAVE_BUSWIDTH_8_BYTES: + fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST8; + break; + + default: + return -EINVAL; + } + + fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_NUM_OPS_MASK; + fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_NUM_OPS(maxburst-1); + dreq_write(fchan, fchan->cfg.req_ctrl, FDMA_REQ_CTRL_OFST); + + fchan->cfg.dev_addr = addr; + fchan->cfg.dir = direction; + + dev_dbg(fdev->dev, "chan:%d config_reqctrl:%#x req_ctrl:%#lx\n", + ch_id, addr, fchan->cfg.req_ctrl); + + return 0; +} + +static void fill_hw_node(struct st_fdma_hw_node *hw_node, + struct st_fdma_chan *fchan, + enum dma_transfer_direction direction) +{ + if (direction == DMA_MEM_TO_DEV) { + hw_node->control |= FDMA_NODE_CTRL_SRC_INCR; + hw_node->control |= FDMA_NODE_CTRL_DST_STATIC; + hw_node->daddr = fchan->cfg.dev_addr; + } else { + hw_node->control |= FDMA_NODE_CTRL_SRC_STATIC; + hw_node->control |= FDMA_NODE_CTRL_DST_INCR; + hw_node->saddr = fchan->cfg.dev_addr; + } + + hw_node->generic.sstride = 0; + hw_node->generic.dstride = 0; +} + +static inline struct st_fdma_chan *st_fdma_prep_common(struct dma_chan *chan, + size_t len, enum dma_transfer_direction direction) +{ + struct st_fdma_chan *fchan; + + if (!chan || !len) + return NULL; + + fchan = to_st_fdma_chan(chan); + + if (!is_slave_direction(direction)) { + dev_err(fchan->fdev->dev, "bad direction?\n"); + return NULL; + } + + return fchan; +} + +static struct dma_async_tx_descriptor *st_fdma_prep_dma_cyclic( + struct dma_chan *chan, dma_addr_t buf_addr, size_t len, + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags) +{ + struct st_fdma_chan *fchan; + struct st_fdma_desc *fdesc; + int sg_len, i; + + fchan = st_fdma_prep_common(chan, len, direction); + if (!fchan) + return NULL; + + if (!period_len) + return NULL; + + if (config_reqctrl(fchan, direction)) { + dev_err(fchan->fdev->dev, "bad width or direction\n"); + return NULL; + } + + /* the buffer length must be a multiple of period_len */ + if (len % period_len != 0) { + dev_err(fchan->fdev->dev, "len is not multiple of period\n"); + return NULL; + } + + sg_len = len / period_len; + fdesc = st_fdma_alloc_desc(fchan, sg_len); + if (!fdesc) { + dev_err(fchan->fdev->dev, "no memory for desc\n"); + return NULL; + } + + fdesc->iscyclic = true; + + for (i = 0; i < sg_len; i++) { + struct st_fdma_hw_node *hw_node = fdesc->node[i].desc; + + hw_node->next = fdesc->node[(i + 1) % sg_len].pdesc; + + hw_node->control = + FDMA_NODE_CTRL_REQ_MAP_DREQ(fchan->dreq_line); + hw_node->control |= FDMA_NODE_CTRL_INT_EON; + + fill_hw_node(hw_node, fchan, direction); + + if (direction == DMA_MEM_TO_DEV) + hw_node->saddr = buf_addr + (i * period_len); + else + hw_node->daddr = buf_addr + (i * period_len); + + hw_node->nbytes = period_len; + hw_node->generic.length = period_len; + } + + return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags); +} + +static struct dma_async_tx_descriptor *st_fdma_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + struct st_fdma_chan *fchan; + struct st_fdma_desc *fdesc; + struct st_fdma_hw_node *hw_node; + struct scatterlist *sg; + int i; + + fchan = st_fdma_prep_common(chan, sg_len, direction); + if (!fchan) + return NULL; + + if (!sgl) + return NULL; + + fdesc = st_fdma_alloc_desc(fchan, sg_len); + if (!fdesc) { + dev_err(fchan->fdev->dev, "no memory for desc\n"); + return NULL; + } + + fdesc->iscyclic = false; + + for_each_sg(sgl, sg, sg_len, i) { + hw_node = fdesc->node[i].desc; + + hw_node->next = fdesc->node[(i + 1) % sg_len].pdesc; + hw_node->control = FDMA_NODE_CTRL_REQ_MAP_DREQ(fchan->dreq_line); + + fill_hw_node(hw_node, fchan, direction); + + if (direction == DMA_MEM_TO_DEV) + hw_node->saddr = sg_dma_address(sg); + else + hw_node->daddr = sg_dma_address(sg); + + hw_node->nbytes = sg_dma_len(sg); + hw_node->generic.length = sg_dma_len(sg); + } + + /* interrupt at end of last node */ + hw_node->control |= FDMA_NODE_CTRL_INT_EON; + + return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags); +} + +static size_t st_fdma_desc_residue(struct st_fdma_chan *fchan, + struct virt_dma_desc *vdesc, + bool in_progress) +{ + struct st_fdma_desc *fdesc = fchan->fdesc; + size_t residue = 0; + dma_addr_t cur_addr = 0; + int i; + + if (in_progress) { + cur_addr = fchan_read(fchan, FDMA_CH_CMD_OFST); + cur_addr &= FDMA_CH_CMD_DATA_MASK; + } + + for (i = fchan->fdesc->n_nodes - 1 ; i >= 0; i--) { + if (cur_addr == fdesc->node[i].pdesc) { + residue += fnode_read(fchan, FDMA_CNTN_OFST); + break; + } + residue += fdesc->node[i].desc->nbytes; + } + + return residue; +} + +static enum dma_status st_fdma_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct st_fdma_chan *fchan = to_st_fdma_chan(chan); + struct virt_dma_desc *vd; + enum dma_status ret; + unsigned long flags; + + ret = dma_cookie_status(chan, cookie, txstate); + if (ret == DMA_COMPLETE || !txstate) + return ret; + + spin_lock_irqsave(&fchan->vchan.lock, flags); + vd = vchan_find_desc(&fchan->vchan, cookie); + if (fchan->fdesc && cookie == fchan->fdesc->vdesc.tx.cookie) + txstate->residue = st_fdma_desc_residue(fchan, vd, true); + else if (vd) + txstate->residue = st_fdma_desc_residue(fchan, vd, false); + else + txstate->residue = 0; + + spin_unlock_irqrestore(&fchan->vchan.lock, flags); + + return ret; +} + +static void st_fdma_issue_pending(struct dma_chan *chan) +{ + struct st_fdma_chan *fchan = to_st_fdma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&fchan->vchan.lock, flags); + + if (vchan_issue_pending(&fchan->vchan) && !fchan->fdesc) + st_fdma_xfer_desc(fchan); + + spin_unlock_irqrestore(&fchan->vchan.lock, flags); +} + +static int st_fdma_pause(struct dma_chan *chan) +{ + unsigned long flags; + LIST_HEAD(head); + struct st_fdma_chan *fchan = to_st_fdma_chan(chan); + int ch_id = fchan->vchan.chan.chan_id; + unsigned long cmd = FDMA_CMD_PAUSE(ch_id); + + dev_dbg(fchan->fdev->dev, "pause chan:%d\n", ch_id); + + spin_lock_irqsave(&fchan->vchan.lock, flags); + if (fchan->fdesc) + fdma_write(fchan->fdev, cmd, FDMA_CMD_SET_OFST); + spin_unlock_irqrestore(&fchan->vchan.lock, flags); + + return 0; +} + +static int st_fdma_resume(struct dma_chan *chan) +{ + unsigned long flags; + unsigned long val; + struct st_fdma_chan *fchan = to_st_fdma_chan(chan); + int ch_id = fchan->vchan.chan.chan_id; + + dev_dbg(fchan->fdev->dev, "resume chan:%d\n", ch_id); + + spin_lock_irqsave(&fchan->vchan.lock, flags); + if (fchan->fdesc) { + val = fchan_read(fchan, FDMA_CH_CMD_OFST); + val &= FDMA_CH_CMD_DATA_MASK; + fchan_write(fchan, val, FDMA_CH_CMD_OFST); + } + spin_unlock_irqrestore(&fchan->vchan.lock, flags); + + return 0; +} + +static int st_fdma_terminate_all(struct dma_chan *chan) +{ + unsigned long flags; + LIST_HEAD(head); + struct st_fdma_chan *fchan = to_st_fdma_chan(chan); + int ch_id = fchan->vchan.chan.chan_id; + unsigned long cmd = FDMA_CMD_PAUSE(ch_id); + + dev_dbg(fchan->fdev->dev, "terminate chan:%d\n", ch_id); + + spin_lock_irqsave(&fchan->vchan.lock, flags); + fdma_write(fchan->fdev, cmd, FDMA_CMD_SET_OFST); + fchan->fdesc = NULL; + vchan_get_all_descriptors(&fchan->vchan, &head); + spin_unlock_irqrestore(&fchan->vchan.lock, flags); + vchan_dma_desc_free_list(&fchan->vchan, &head); + + return 0; +} + +static int st_fdma_slave_config(struct dma_chan *chan, + struct dma_slave_config *slave_cfg) +{ + struct st_fdma_chan *fchan = to_st_fdma_chan(chan); + + memcpy(&fchan->scfg, slave_cfg, sizeof(fchan->scfg)); + return 0; +} + +static const struct st_fdma_driverdata fdma_mpe31_stih407_11 = { + .name = "STiH407", + .id = 0, +}; + +static const struct st_fdma_driverdata fdma_mpe31_stih407_12 = { + .name = "STiH407", + .id = 1, +}; + +static const struct st_fdma_driverdata fdma_mpe31_stih407_13 = { + .name = "STiH407", + .id = 2, +}; + +static const struct of_device_id st_fdma_match[] = { + { .compatible = "st,stih407-fdma-mpe31-11" + , .data = &fdma_mpe31_stih407_11 }, + { .compatible = "st,stih407-fdma-mpe31-12" + , .data = &fdma_mpe31_stih407_12 }, + { .compatible = "st,stih407-fdma-mpe31-13" + , .data = &fdma_mpe31_stih407_13 }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_fdma_match); + +static int st_fdma_parse_dt(struct platform_device *pdev, + const struct st_fdma_driverdata *drvdata, + struct st_fdma_dev *fdev) +{ + struct device_node *np = pdev->dev.of_node; + int ret; + + if (!np) + goto err; + + ret = of_property_read_u32(np, "dma-channels", &fdev->nr_channels); + if (ret) + goto err; + + snprintf(fdev->fw_name, FW_NAME_SIZE, "fdma_%s_%d.elf", + drvdata->name, drvdata->id); + +err: + return ret; +} +#define FDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) + +static void st_fdma_free(struct st_fdma_dev *fdev) +{ + struct st_fdma_chan *fchan; + int i; + + for (i = 0; i < fdev->nr_channels; i++) { + fchan = &fdev->chans[i]; + list_del(&fchan->vchan.chan.device_node); + tasklet_kill(&fchan->vchan.task); + } +} + +static int st_fdma_probe(struct platform_device *pdev) +{ + struct st_fdma_dev *fdev; + const struct of_device_id *match; + struct device_node *np = pdev->dev.of_node; + const struct st_fdma_driverdata *drvdata; + int ret, i; + + match = of_match_device((st_fdma_match), &pdev->dev); + if (!match || !match->data) { + dev_err(&pdev->dev, "No device match found\n"); + return -ENODEV; + } + + drvdata = match->data; + + fdev = devm_kzalloc(&pdev->dev, sizeof(*fdev), GFP_KERNEL); + if (!fdev) + return -ENOMEM; + + ret = st_fdma_parse_dt(pdev, drvdata, fdev); + if (ret) { + dev_err(&pdev->dev, "unable to find platform data\n"); + goto err; + } + + fdev->chans = devm_kcalloc(&pdev->dev, fdev->nr_channels, + sizeof(struct st_fdma_chan), GFP_KERNEL); + if (!fdev->chans) + return -ENOMEM; + + fdev->dev = &pdev->dev; + fdev->drvdata = drvdata; + platform_set_drvdata(pdev, fdev); + + fdev->irq = platform_get_irq(pdev, 0); + if (fdev->irq < 0) { + dev_err(&pdev->dev, "Failed to get irq resource\n"); + return -EINVAL; + } + + ret = devm_request_irq(&pdev->dev, fdev->irq, st_fdma_irq_handler, 0, + dev_name(&pdev->dev), fdev); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq (%d)\n", ret); + goto err; + } + + fdev->slim_rproc = st_slim_rproc_alloc(pdev, fdev->fw_name); + if (!fdev->slim_rproc) { + ret = PTR_ERR(fdev->slim_rproc); + dev_err(&pdev->dev, "slim_rproc_alloc failed (%d)\n", ret); + goto err; + } + + /* Initialise list of FDMA channels */ + INIT_LIST_HEAD(&fdev->dma_device.channels); + for (i = 0; i < fdev->nr_channels; i++) { + struct st_fdma_chan *fchan = &fdev->chans[i]; + + fchan->fdev = fdev; + fchan->vchan.desc_free = st_fdma_free_desc; + vchan_init(&fchan->vchan, &fdev->dma_device); + } + + /* Initialise the FDMA dreq (reserve 0 & 31 for FDMA use) */ + fdev->dreq_mask = BIT(0) | BIT(31); + + dma_cap_set(DMA_SLAVE, fdev->dma_device.cap_mask); + dma_cap_set(DMA_CYCLIC, fdev->dma_device.cap_mask); + dma_cap_set(DMA_MEMCPY, fdev->dma_device.cap_mask); + + fdev->dma_device.dev = &pdev->dev; + fdev->dma_device.device_alloc_chan_resources = st_fdma_alloc_chan_res; + fdev->dma_device.device_free_chan_resources = st_fdma_free_chan_res; + fdev->dma_device.device_prep_dma_cyclic = st_fdma_prep_dma_cyclic; + fdev->dma_device.device_prep_slave_sg = st_fdma_prep_slave_sg; + fdev->dma_device.device_prep_dma_memcpy = st_fdma_prep_dma_memcpy; + fdev->dma_device.device_tx_status = st_fdma_tx_status; + fdev->dma_device.device_issue_pending = st_fdma_issue_pending; + fdev->dma_device.device_terminate_all = st_fdma_terminate_all; + fdev->dma_device.device_config = st_fdma_slave_config; + fdev->dma_device.device_pause = st_fdma_pause; + fdev->dma_device.device_resume = st_fdma_resume; + + fdev->dma_device.src_addr_widths = FDMA_DMA_BUSWIDTHS; + fdev->dma_device.dst_addr_widths = FDMA_DMA_BUSWIDTHS; + fdev->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + fdev->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + + ret = dma_async_device_register(&fdev->dma_device); + if (ret) { + dev_err(&pdev->dev, + "Failed to register DMA device (%d)\n", ret); + goto err_rproc; + } + + ret = of_dma_controller_register(np, st_fdma_of_xlate, fdev); + if (ret) { + dev_err(&pdev->dev, + "Failed to register controller (%d)\n", ret); + goto err_dma_dev; + } + + dev_info(&pdev->dev, "ST FDMA engine driver, irq:%d\n", fdev->irq); + + return 0; + +err_dma_dev: + dma_async_device_unregister(&fdev->dma_device); +err_rproc: + st_fdma_free(fdev); + st_slim_rproc_put(fdev->slim_rproc); +err: + return ret; +} + +static int st_fdma_remove(struct platform_device *pdev) +{ + struct st_fdma_dev *fdev = platform_get_drvdata(pdev); + + devm_free_irq(&pdev->dev, fdev->irq, fdev); + st_slim_rproc_put(fdev->slim_rproc); + of_dma_controller_free(pdev->dev.of_node); + dma_async_device_unregister(&fdev->dma_device); + + return 0; +} + +static struct platform_driver st_fdma_platform_driver = { + .driver = { + .name = DRIVER_NAME, + .of_match_table = st_fdma_match, + }, + .probe = st_fdma_probe, + .remove = st_fdma_remove, +}; +module_platform_driver(st_fdma_platform_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver"); +MODULE_AUTHOR("Ludovic.barre "); +MODULE_AUTHOR("Peter Griffin "); +MODULE_ALIAS("platform: " DRIVER_NAME); -- cgit v1.2.3 From ed838fe937dbcdcf7c0444a5b62edfec6ecd753c Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Tue, 18 Oct 2016 16:50:18 +0530 Subject: net: phy: dp83867: add support for MAC impedance configuration Add support for programmable MAC impedance configuration Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/phy/dp83867.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 91177a4a32ad..1b639242f9e2 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -33,6 +33,7 @@ /* Extended Registers */ #define DP83867_RGMIICTL 0x0032 #define DP83867_RGMIIDCTL 0x0086 +#define DP83867_IO_MUX_CFG 0x0170 #define DP83867_SW_RESET BIT(15) #define DP83867_SW_RESTART BIT(14) @@ -62,10 +63,17 @@ /* RGMIIDCTL bits */ #define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4 +/* IO_MUX_CFG bits */ +#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL 0x1f + +#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 +#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f + struct dp83867_private { int rx_id_delay; int tx_id_delay; int fifo_depth; + int io_impedance; }; static int dp83867_ack_interrupt(struct phy_device *phydev) @@ -111,6 +119,14 @@ static int dp83867_of_init(struct phy_device *phydev) if (!of_node) return -ENODEV; + dp83867->io_impedance = -EINVAL; + + /* Optional configuration */ + if (of_property_read_bool(of_node, "ti,max-output-impedance")) + dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; + else if (of_property_read_bool(of_node, "ti,min-output-impedance")) + dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN; + ret = of_property_read_u32(of_node, "ti,rx-internal-delay", &dp83867->rx_id_delay); if (ret) @@ -184,6 +200,18 @@ static int dp83867_config_init(struct phy_device *phydev) phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL, DP83867_DEVADDR, delay); + + if (dp83867->io_impedance >= 0) { + val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR); + + val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; + val |= dp83867->io_impedance & + DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; + + phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, val); + } } return 0; -- cgit v1.2.3 From 556195f492a15f27f2389acf6e99ae8e5a1bf3d9 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Tue, 18 Oct 2016 08:46:32 +0200 Subject: Revert "dmaengine: pxa_dma: add support for legacy transition" This reverts commit c91134d9194478144ba579ca6efeddf628055650. The conversion of the pxa architecture is now finished for all drivers, so this functions has fullfilled its purpose and can now be removed. Signed-off-by: Robert Jarzmik Acked-by: Arnd Bergmann Signed-off-by: Vinod Koul --- drivers/dma/pxa_dma.c | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index 3f56f9ca4482..b53fb618bbf6 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -413,15 +413,6 @@ static inline void pxad_init_debugfs(struct pxad_device *pdev) {} static inline void pxad_cleanup_debugfs(struct pxad_device *pdev) {} #endif -/* - * In the transition phase where legacy pxa handling is done at the same time as - * mmp_dma, the DMA physical channel split between the 2 DMA providers is done - * through legacy_reserved. Legacy code reserves DMA channels by settings - * corresponding bits in legacy_reserved. - */ -static u32 legacy_reserved; -static u32 legacy_unavailable; - static struct pxad_phy *lookup_phy(struct pxad_chan *pchan) { int prio, i; @@ -442,14 +433,10 @@ static struct pxad_phy *lookup_phy(struct pxad_chan *pchan) for (i = 0; i < pdev->nr_chans; i++) { if (prio != (i & 0xf) >> 2) continue; - if ((i < 32) && (legacy_reserved & BIT(i))) - continue; phy = &pdev->phys[i]; if (!phy->vchan) { phy->vchan = pchan; found = phy; - if (i < 32) - legacy_unavailable |= BIT(i); goto out_unlock; } } @@ -469,7 +456,6 @@ static void pxad_free_phy(struct pxad_chan *chan) struct pxad_device *pdev = to_pxad_dev(chan->vc.chan.device); unsigned long flags; u32 reg; - int i; dev_dbg(&chan->vc.chan.dev->device, "%s(): freeing\n", __func__); @@ -483,9 +469,6 @@ static void pxad_free_phy(struct pxad_chan *chan) } spin_lock_irqsave(&pdev->phy_lock, flags); - for (i = 0; i < 32; i++) - if (chan->phy == &pdev->phys[i]) - legacy_unavailable &= ~BIT(i); chan->phy->vchan = NULL; chan->phy = NULL; spin_unlock_irqrestore(&pdev->phy_lock, flags); @@ -739,8 +722,6 @@ static irqreturn_t pxad_int_handler(int irq, void *dev_id) i = __ffs(dint); dint &= (dint - 1); phy = &pdev->phys[i]; - if ((i < 32) && (legacy_reserved & BIT(i))) - continue; if (pxad_chan_handler(irq, phy) == IRQ_HANDLED) ret = IRQ_HANDLED; } @@ -1522,15 +1503,6 @@ bool pxad_filter_fn(struct dma_chan *chan, void *param) } EXPORT_SYMBOL_GPL(pxad_filter_fn); -int pxad_toggle_reserved_channel(int legacy_channel) -{ - if (legacy_unavailable & (BIT(legacy_channel))) - return -EBUSY; - legacy_reserved ^= BIT(legacy_channel); - return 0; -} -EXPORT_SYMBOL_GPL(pxad_toggle_reserved_channel); - module_platform_driver(pxad_driver); MODULE_DESCRIPTION("Marvell PXA Peripheral DMA Driver"); -- cgit v1.2.3 From 9934075471dcc6de9bdce1f3c1e16f1afbd711a8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 14 Oct 2016 10:30:47 +0530 Subject: dmaengine: omap-dma: add support for pause of non-cyclic transfers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This DMA driver is used by 8250-omap on DRA7-evm. There is one requirement that is to pause a transfer. This is currently used on the RX side. It is possible that the UART HW aborted the RX (UART's RX-timeout) but the DMA controller starts the transfer shortly after. Before we can manually purge the FIFO we need to pause the transfer, check how many bytes it already received and terminate the transfer without it making any progress. From testing on the TX side it seems that it is possible that we invoke pause once the transfer has completed which is indicated by the missing CCR_ENABLE bit but before the interrupt has been noticed. In that case the interrupt will come even after disabling it. The AM572x manual says that we have to wait for the CCR_RD_ACTIVE & CCR_WR_ACTIVE bits to be gone before programming it again here is the drain loop. Also it looks like without the drain the TX-transfer makes sometimes progress. One note: The pause + resume combo is broken because after resume the the complete transfer will be programmed again. That means the already transferred bytes (until the pause event) will be sent again. This is currently not important for my UART user because it does only pause + terminate. v3…v4: - update subject line. v2…v3: - rephrase the comment based on Russell's information / feedback. v1…v2: - move the drain loop into omap_dma_drain_chan() instead of having it twice. - allow pause only for DMA_DEV_TO_MEM transfers if non-cyclic. Add a comment why DMA_MEM_TO_DEV not allowed. - clear pause on terminate_all. Otherwise pause() + terminate_all() will keep the pause bit set and we can't pause the following transfer. Signed-off-by: Sebastian Andrzej Siewior [vigneshr@ti.com: drain channel only when buffering is on, rebase to v4.8] Signed-off-by: Vignesh R Acked-by: Peter Ujfalusi Signed-off-by: Vinod Koul --- drivers/dma/omap-dma.c | 124 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 7ca27d4b1c54..fd6b9e6834ad 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -422,7 +422,30 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) c->running = true; } -static void omap_dma_stop(struct omap_chan *c) +static void omap_dma_drain_chan(struct omap_chan *c) +{ + int i; + u32 val; + + /* Wait for sDMA FIFO to drain */ + for (i = 0; ; i++) { + val = omap_dma_chan_read(c, CCR); + if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))) + break; + + if (i > 100) + break; + + udelay(5); + } + + if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)) + dev_err(c->vc.chan.device->dev, + "DMA drain did not complete on lch %d\n", + c->dma_ch); +} + +static int omap_dma_stop(struct omap_chan *c) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); uint32_t val; @@ -435,7 +458,6 @@ static void omap_dma_stop(struct omap_chan *c) val = omap_dma_chan_read(c, CCR); if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) { uint32_t sysconfig; - unsigned i; sysconfig = omap_dma_glbl_read(od, OCP_SYSCONFIG); val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK; @@ -446,27 +468,19 @@ static void omap_dma_stop(struct omap_chan *c) val &= ~CCR_ENABLE; omap_dma_chan_write(c, CCR, val); - /* Wait for sDMA FIFO to drain */ - for (i = 0; ; i++) { - val = omap_dma_chan_read(c, CCR); - if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))) - break; - - if (i > 100) - break; - - udelay(5); - } - - if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)) - dev_err(c->vc.chan.device->dev, - "DMA drain did not complete on lch %d\n", - c->dma_ch); + if (!(c->ccr & CCR_BUFFERING_DISABLE)) + omap_dma_drain_chan(c); omap_dma_glbl_write(od, OCP_SYSCONFIG, sysconfig); } else { + if (!(val & CCR_ENABLE)) + return -EINVAL; + val &= ~CCR_ENABLE; omap_dma_chan_write(c, CCR, val); + + if (!(c->ccr & CCR_BUFFERING_DISABLE)) + omap_dma_drain_chan(c); } mb(); @@ -481,8 +495,8 @@ static void omap_dma_stop(struct omap_chan *c) omap_dma_chan_write(c, CLNK_CTRL, val); } - c->running = false; + return 0; } static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d) @@ -836,6 +850,8 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan, } else { txstate->residue = 0; } + if (ret == DMA_IN_PROGRESS && c->paused) + ret = DMA_PAUSED; spin_unlock_irqrestore(&c->vc.lock, flags); return ret; @@ -1247,10 +1263,8 @@ static int omap_dma_terminate_all(struct dma_chan *chan) omap_dma_stop(c); } - if (c->cyclic) { - c->cyclic = false; - c->paused = false; - } + c->cyclic = false; + c->paused = false; vchan_get_all_descriptors(&c->vc, &head); spin_unlock_irqrestore(&c->vc.lock, flags); @@ -1269,28 +1283,66 @@ static void omap_dma_synchronize(struct dma_chan *chan) static int omap_dma_pause(struct dma_chan *chan) { struct omap_chan *c = to_omap_dma_chan(chan); + struct omap_dmadev *od = to_omap_dma_dev(chan->device); + unsigned long flags; + int ret = -EINVAL; + bool can_pause; - /* Pause/Resume only allowed with cyclic mode */ - if (!c->cyclic) - return -EINVAL; + spin_lock_irqsave(&od->irq_lock, flags); - if (!c->paused) { - omap_dma_stop(c); - c->paused = true; + if (!c->desc) + goto out; + + if (c->cyclic) + can_pause = true; + + /* + * We do not allow DMA_MEM_TO_DEV transfers to be paused. + * From the AM572x TRM, 16.1.4.18 Disabling a Channel During Transfer: + * "When a channel is disabled during a transfer, the channel undergoes + * an abort, unless it is hardware-source-synchronized …". + * A source-synchronised channel is one where the fetching of data is + * under control of the device. In other words, a device-to-memory + * transfer. So, a destination-synchronised channel (which would be a + * memory-to-device transfer) undergoes an abort if the the CCR_ENABLE + * bit is cleared. + * From 16.1.4.20.4.6.2 Abort: "If an abort trigger occurs, the channel + * aborts immediately after completion of current read/write + * transactions and then the FIFO is cleaned up." The term "cleaned up" + * is not defined. TI recommends to check that RD_ACTIVE and WR_ACTIVE + * are both clear _before_ disabling the channel, otherwise data loss + * will occur. + * The problem is that if the channel is active, then device activity + * can result in DMA activity starting between reading those as both + * clear and the write to DMA_CCR to clear the enable bit hitting the + * hardware. If the DMA hardware can't drain the data in its FIFO to the + * destination, then data loss "might" occur (say if we write to an UART + * and the UART is not accepting any further data). + */ + else if (c->desc->dir == DMA_DEV_TO_MEM) + can_pause = true; + + if (can_pause && !c->paused) { + ret = omap_dma_stop(c); + if (!ret) + c->paused = true; } +out: + spin_unlock_irqrestore(&od->irq_lock, flags); - return 0; + return ret; } static int omap_dma_resume(struct dma_chan *chan) { struct omap_chan *c = to_omap_dma_chan(chan); + struct omap_dmadev *od = to_omap_dma_dev(chan->device); + unsigned long flags; + int ret = -EINVAL; - /* Pause/Resume only allowed with cyclic mode */ - if (!c->cyclic) - return -EINVAL; + spin_lock_irqsave(&od->irq_lock, flags); - if (c->paused) { + if (c->paused && c->desc) { mb(); /* Restore channel link register */ @@ -1298,9 +1350,11 @@ static int omap_dma_resume(struct dma_chan *chan) omap_dma_start(c, c->desc); c->paused = false; + ret = 0; } + spin_unlock_irqrestore(&od->irq_lock, flags); - return 0; + return ret; } static int omap_dma_chan_init(struct omap_dmadev *od) -- cgit v1.2.3 From 7dcec7577ddbc5677deb5204a8cb8837c32a68cf Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Thu, 6 Oct 2016 15:33:14 -0400 Subject: dmaengine: qcom_hidma: prevent disable in error When an error is observed, we try to disable the channel and prevent further accesses from the client. Depending on the type of error, transitioning into disabled state might not be possible. Adding a check to make sure that HW is in enabled/running state before the disable transition happens. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma_ll.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index 3224f24c577b..c3a66c9b0ab7 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -564,19 +564,8 @@ int hidma_ll_disable(struct hidma_lldev *lldev) u32 val; int ret; - val = readl(lldev->evca + HIDMA_EVCA_CTRLSTS_REG); - lldev->evch_state = HIDMA_CH_STATE(val); - val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG); - lldev->trch_state = HIDMA_CH_STATE(val); - - /* already suspended by this OS */ - if ((lldev->trch_state == HIDMA_CH_SUSPENDED) || - (lldev->evch_state == HIDMA_CH_SUSPENDED)) - return 0; - - /* already stopped by the manager */ - if ((lldev->trch_state == HIDMA_CH_STOPPED) || - (lldev->evch_state == HIDMA_CH_STOPPED)) + /* The channel needs to be in working state */ + if (!hidma_ll_isenabled(lldev)) return 0; val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG); -- cgit v1.2.3 From 10714dd37aa7ebb165677b9a793448950ff366ad Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Oct 2016 15:33:12 +0100 Subject: efi: Remove unused include of Signed-off-by: Wei Yongjun Signed-off-by: Matt Fleming Cc: Ard Biesheuvel Cc: Ivan Khoronzhuk Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20161018143318.15673-3-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/test/efi_test.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index f61bb52be318..ae51268737cc 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c @@ -8,7 +8,6 @@ * */ -#include #include #include #include -- cgit v1.2.3 From 0709a008c9fadc176500ece7395b8b5b8de143e3 Mon Sep 17 00:00:00 2001 From: Yisheng Xie Date: Tue, 18 Oct 2016 15:33:13 +0100 Subject: efi/arm*: Fix efi_init() error handling There's an early memmap() leak in the efi_init() error path, fix it. Signed-off-by: Yisheng Xie Signed-off-by: Matt Fleming Cc: Ard Biesheuvel Cc: Catalin Marinas Cc: Linus Torvalds Cc: Mark Rutland Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20161018143318.15673-4-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/arm-init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 8efe13075c92..f853ad2c4ca0 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -244,8 +244,10 @@ void __init efi_init(void) "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", efi.memmap.desc_version); - if (uefi_init() < 0) + if (uefi_init() < 0) { + efi_memmap_unmap(); return; + } reserve_regions(); efi_memattr_init(); -- cgit v1.2.3 From 46b9b7135332d1e2c54e853108a5088ab28f2165 Mon Sep 17 00:00:00 2001 From: Ivan Hu Date: Tue, 18 Oct 2016 15:33:14 +0100 Subject: efi/efi_test: Fix uninitialized variable 'datasize' Fix minor issue found by CoverityScan: CID 1358931 (#1 of 1): Uninitialized scalar variable (UNINIT)9. uninit_use: Using uninitialized value datasize. 199 prev_datasize = datasize; 200 status = efi.get_variable(name, vd, at, dz, data); Signed-off-by: Ivan Hu Signed-off-by: Matt Fleming Cc: Ard Biesheuvel Cc: Ivan Khoronzhuk Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20161018143318.15673-5-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/test/efi_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index ae51268737cc..348efc9cf59f 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c @@ -155,7 +155,7 @@ static long efi_runtime_get_variable(unsigned long arg) { struct efi_getvariable __user *getvariable_user; struct efi_getvariable getvariable; - unsigned long datasize, prev_datasize, *dz; + unsigned long datasize = 0, prev_datasize, *dz; efi_guid_t vendor_guid, *vd = NULL; efi_status_t status; efi_char16_t *name = NULL; -- cgit v1.2.3 From 9c30a2199311df9a1f25d0586c96dfbb7e876cdf Mon Sep 17 00:00:00 2001 From: Ivan Hu Date: Tue, 18 Oct 2016 15:33:15 +0100 Subject: efi/efi_test: Fix uninitialized variable 'rv' Fix minor issue found by CoverityScan: 520 kfree(name); CID 1358932 (#1 of 1): Uninitialized scalar variable (UNINIT)17. uninit_use: Using uninitialized value rv. 521 return rv; 522} Signed-off-by: Ivan Hu Signed-off-by: Matt Fleming Cc: Ard Biesheuvel Cc: Ivan Khoronzhuk Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20161018143318.15673-6-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/test/efi_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index 348efc9cf59f..bb26e12b0cfd 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c @@ -428,7 +428,7 @@ static long efi_runtime_get_nextvariablename(unsigned long arg) efi_guid_t *vd = NULL; efi_guid_t vendor_guid; efi_char16_t *name = NULL; - int rv; + int rv = 0; getnextvariablename_user = (struct efi_getnextvariablename __user *)arg; -- cgit v1.2.3 From c208ed916e587048ba6b69840d08324100d7d325 Mon Sep 17 00:00:00 2001 From: Ivan Hu Date: Tue, 18 Oct 2016 15:33:16 +0100 Subject: efi/efi_test: Use memdup_user() as a cleanup Fix coccicheck warning which recommends to use memdup_user(). This patch fixes the following coccicheck warnings: drivers/firmware/efi/test/efi_test.c:269:8-15: WARNING opportunity for memdup_user Signed-off-by: Ivan Hu Signed-off-by: Matt Fleming Cc: Ard Biesheuvel Cc: Ivan Khoronzhuk Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20161018143318.15673-7-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/test/efi_test.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index bb26e12b0cfd..8cd578f62059 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c @@ -265,14 +265,10 @@ static long efi_runtime_set_variable(unsigned long arg) return rv; } - data = kmalloc(setvariable.data_size, GFP_KERNEL); - if (!data) { + data = memdup_user(setvariable.data, setvariable.data_size); + if (IS_ERR(data)) { kfree(name); - return -ENOMEM; - } - if (copy_from_user(data, setvariable.data, setvariable.data_size)) { - rv = -EFAULT; - goto out; + return PTR_ERR(data); } status = efi.set_variable(name, &vendor_guid, -- cgit v1.2.3 From 753375a881caa01112b7cec2c796749154e0bb23 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 18 Oct 2016 15:33:17 +0100 Subject: efifb: Show framebuffer layout as device attributes Userland sometimes needs to know what the framebuffer configuration was when the firmware was running. This enables us to render localized status strings during firmware updates using the data from the ACPI BGRT table and the protocol described at the url below: https://msdn.microsoft.com/en-us/windows/hardware/drivers/bringup/boot-screen-components This patch also fixes up efifb's printk() usage to use pr_warn() / pr_info() / pr_err() instead. Tested-by: Ard Biesheuvel Signed-off-by: Peter Jones Signed-off-by: Ard Biesheuvel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20161018143318.15673-8-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/video/fbdev/efifb.c | 59 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index 37a37c4d04cb..8c4dc1e1f94f 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c @@ -118,6 +118,31 @@ static inline bool fb_base_is_valid(void) return false; } +#define efifb_attr_decl(name, fmt) \ +static ssize_t name##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + return sprintf(buf, fmt "\n", (screen_info.lfb_##name)); \ +} \ +static DEVICE_ATTR_RO(name) + +efifb_attr_decl(base, "0x%x"); +efifb_attr_decl(linelength, "%u"); +efifb_attr_decl(height, "%u"); +efifb_attr_decl(width, "%u"); +efifb_attr_decl(depth, "%u"); + +static struct attribute *efifb_attrs[] = { + &dev_attr_base.attr, + &dev_attr_linelength.attr, + &dev_attr_width.attr, + &dev_attr_height.attr, + &dev_attr_depth.attr, + NULL +}; +ATTRIBUTE_GROUPS(efifb); + static int efifb_probe(struct platform_device *dev) { struct fb_info *info; @@ -205,14 +230,13 @@ static int efifb_probe(struct platform_device *dev) } else { /* We cannot make this fatal. Sometimes this comes from magic spaces our resource handlers simply don't know about */ - printk(KERN_WARNING - "efifb: cannot reserve video memory at 0x%lx\n", + pr_warn("efifb: cannot reserve video memory at 0x%lx\n", efifb_fix.smem_start); } info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); if (!info) { - printk(KERN_ERR "efifb: cannot allocate framebuffer\n"); + pr_err("efifb: cannot allocate framebuffer\n"); err = -ENOMEM; goto err_release_mem; } @@ -230,16 +254,15 @@ static int efifb_probe(struct platform_device *dev) info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len); if (!info->screen_base) { - printk(KERN_ERR "efifb: abort, cannot ioremap video memory " - "0x%x @ 0x%lx\n", + pr_err("efifb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n", efifb_fix.smem_len, efifb_fix.smem_start); err = -EIO; goto err_release_fb; } - printk(KERN_INFO "efifb: framebuffer at 0x%lx, using %dk, total %dk\n", + pr_info("efifb: framebuffer at 0x%lx, using %dk, total %dk\n", efifb_fix.smem_start, size_remap/1024, size_total/1024); - printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n", + pr_info("efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n", efifb_defined.xres, efifb_defined.yres, efifb_defined.bits_per_pixel, efifb_fix.line_length, screen_info.pages); @@ -247,7 +270,7 @@ static int efifb_probe(struct platform_device *dev) efifb_defined.xres_virtual = efifb_defined.xres; efifb_defined.yres_virtual = efifb_fix.smem_len / efifb_fix.line_length; - printk(KERN_INFO "efifb: scrolling: redraw\n"); + pr_info("efifb: scrolling: redraw\n"); efifb_defined.yres_virtual = efifb_defined.yres; /* some dummy values for timing to make fbset happy */ @@ -265,7 +288,7 @@ static int efifb_probe(struct platform_device *dev) efifb_defined.transp.offset = screen_info.rsvd_pos; efifb_defined.transp.length = screen_info.rsvd_size; - printk(KERN_INFO "efifb: %s: " + pr_info("efifb: %s: " "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", "Truecolor", screen_info.rsvd_size, @@ -285,12 +308,19 @@ static int efifb_probe(struct platform_device *dev) info->fix = efifb_fix; info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE; - if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) { - printk(KERN_ERR "efifb: cannot allocate colormap\n"); + err = sysfs_create_groups(&dev->dev.kobj, efifb_groups); + if (err) { + pr_err("efifb: cannot add sysfs attrs\n"); goto err_unmap; } - if ((err = register_framebuffer(info)) < 0) { - printk(KERN_ERR "efifb: cannot register framebuffer\n"); + err = fb_alloc_cmap(&info->cmap, 256, 0); + if (err < 0) { + pr_err("efifb: cannot allocate colormap\n"); + goto err_groups; + } + err = register_framebuffer(info); + if (err < 0) { + pr_err("efifb: cannot register framebuffer\n"); goto err_fb_dealoc; } fb_info(info, "%s frame buffer device\n", info->fix.id); @@ -298,6 +328,8 @@ static int efifb_probe(struct platform_device *dev) err_fb_dealoc: fb_dealloc_cmap(&info->cmap); +err_groups: + sysfs_remove_groups(&dev->dev.kobj, efifb_groups); err_unmap: iounmap(info->screen_base); err_release_fb: @@ -313,6 +345,7 @@ static int efifb_remove(struct platform_device *pdev) struct fb_info *info = platform_get_drvdata(pdev); unregister_framebuffer(info); + sysfs_remove_groups(&pdev->dev.kobj, efifb_groups); framebuffer_release(info); return 0; -- cgit v1.2.3 From a75dcb5848359f488c32c0aef8711d9bd37a77b8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Oct 2016 15:33:18 +0100 Subject: efi/efivar_ssdt_load: Don't return success on allocation failure We should return -ENOMEM here, instead of success. Signed-off-by: Dan Carpenter Signed-off-by: Ard Biesheuvel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Fixes: 475fb4e8b2f4 ("efi / ACPI: load SSTDs from EFI variables") Link: http://lkml.kernel.org/r/20161018143318.15673-9-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/efi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 1ac199cd75e7..a4944e22f294 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -259,8 +259,10 @@ static __init int efivar_ssdt_load(void) } data = kmalloc(size, GFP_KERNEL); - if (!data) + if (!data) { + ret = -ENOMEM; goto free_entry; + } ret = efivar_entry_get(entry, NULL, &size, data); if (ret) { -- cgit v1.2.3 From 67bef942801842ce7486a23dd3940e320f217319 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:03 -0400 Subject: ethernet/atheros: use core min/max MTU checking atl2: min_mtu 40, max_mtu 1504 - Remove a few redundant defines that already have equivalents in if_ether.h. atl1: min_mtu 42, max_mtu 10218 atl1e: min_mtu 42, max_mtu 8170 atl1c: min_mtu 42, max_mtu 6122/1500 - GbE hardware gets a max_mtu of 6122, slower hardware gets 1500. alx: min_mtu 34, max_mtu 9256 - Not so sure that minimum MTU number is really what was intended, but that's what the math actually makes it out to be, due to max_frame manipulations and comparison in alx_change_mtu, rather than just comparing new_mtu. (I think 68 was the intended min_mtu value). CC: netdev@vger.kernel.org CC: Jay Cliburn CC: Chris Snook Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/hw.h | 1 - drivers/net/ethernet/atheros/alx/main.c | 10 ++---- drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 41 ++++++++++++++++--------- drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 12 +++----- drivers/net/ethernet/atheros/atlx/atl1.c | 15 ++++----- drivers/net/ethernet/atheros/atlx/atl2.c | 16 +++++----- drivers/net/ethernet/atheros/atlx/atl2.h | 3 -- 7 files changed, 47 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/atheros/alx/hw.h b/drivers/net/ethernet/atheros/alx/hw.h index 0191477ace51..e42d7e0947eb 100644 --- a/drivers/net/ethernet/atheros/alx/hw.h +++ b/drivers/net/ethernet/atheros/alx/hw.h @@ -351,7 +351,6 @@ struct alx_rrd { #define ALX_MAX_JUMBO_PKT_SIZE (9*1024) #define ALX_MAX_TSO_PKT_SIZE (7*1024) #define ALX_MAX_FRAME_SIZE ALX_MAX_JUMBO_PKT_SIZE -#define ALX_MIN_FRAME_SIZE (ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) #define ALX_MAX_RX_QUEUES 8 #define ALX_MAX_TX_QUEUES 4 diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index c0f84b73574d..eccbacd96201 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -892,6 +892,9 @@ static int alx_init_sw(struct alx_priv *alx) hw->smb_timer = 400; hw->mtu = alx->dev->mtu; alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu); + /* MTU range: 34 - 9256 */ + alx->dev->min_mtu = 34; + alx->dev->max_mtu = ALX_MAX_FRAME_LEN(ALX_MAX_FRAME_SIZE); alx->tx_ringsz = 256; alx->rx_ringsz = 512; hw->imt = 200; @@ -994,13 +997,6 @@ static int alx_change_mtu(struct net_device *netdev, int mtu) struct alx_priv *alx = netdev_priv(netdev); int max_frame = ALX_MAX_FRAME_LEN(mtu); - if ((max_frame < ALX_MIN_FRAME_SIZE) || - (max_frame > ALX_MAX_FRAME_SIZE)) - return -EINVAL; - - if (netdev->mtu == mtu) - return 0; - netdev->mtu = mtu; alx->hw.mtu = mtu; alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE); diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index a3200ea6d765..773d3b7d8dd5 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -519,6 +519,26 @@ static int atl1c_set_features(struct net_device *netdev, return 0; } +static void atl1c_set_max_mtu(struct net_device *netdev) +{ + struct atl1c_adapter *adapter = netdev_priv(netdev); + struct atl1c_hw *hw = &adapter->hw; + + switch (hw->nic_type) { + /* These (GbE) devices support jumbo packets, max_mtu 6122 */ + case athr_l1c: + case athr_l1d: + case athr_l1d_2: + netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); + break; + /* The 10/100 devices don't support jumbo packets, max_mtu 1500 */ + default: + netdev->max_mtu = ETH_DATA_LEN; + break; + } +} + /** * atl1c_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure @@ -529,22 +549,9 @@ static int atl1c_set_features(struct net_device *netdev, static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) { struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - int old_mtu = netdev->mtu; - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - - /* Fast Ethernet controller doesn't support jumbo packet */ - if (((hw->nic_type == athr_l2c || - hw->nic_type == athr_l2c_b || - hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) || - max_frame < ETH_ZLEN + ETH_FCS_LEN || - max_frame > MAX_JUMBO_FRAME_SIZE) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); - return -EINVAL; - } + /* set MTU */ - if (old_mtu != new_mtu && netif_running(netdev)) { + if (netif_running(netdev)) { while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) msleep(1); netdev->mtu = new_mtu; @@ -2511,6 +2518,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) netdev->netdev_ops = &atl1c_netdev_ops; netdev->watchdog_timeo = AT_TX_WATCHDOG; + netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN); atl1c_set_ethtool_ops(netdev); /* TODO: add when ready */ @@ -2613,6 +2621,9 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_err(&pdev->dev, "net device private data init failed\n"); goto err_sw_init; } + /* set max MTU */ + atl1c_set_max_mtu(netdev); + atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); /* Init GPHY as early as possible due to power saving issue */ diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 974713b19ab6..e96091b652a7 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -439,16 +439,10 @@ static int atl1e_set_features(struct net_device *netdev, static int atl1e_change_mtu(struct net_device *netdev, int new_mtu) { struct atl1e_adapter *adapter = netdev_priv(netdev); - int old_mtu = netdev->mtu; int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - netdev_warn(adapter->netdev, "invalid MTU setting\n"); - return -EINVAL; - } /* set MTU */ - if (old_mtu != new_mtu && netif_running(netdev)) { + if (netif_running(netdev)) { while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) msleep(1); netdev->mtu = new_mtu; @@ -2272,6 +2266,10 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) netdev->netdev_ops = &atl1e_netdev_ops; netdev->watchdog_timeo = AT_TX_WATCHDOG; + /* MTU range: 42 - 8170 */ + netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN); + netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); atl1e_set_ethtool_ops(netdev); netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO | diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index 529bca718334..9aede18aa70f 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -2701,23 +2701,15 @@ static void atl1_reset_dev_task(struct work_struct *work) static int atl1_change_mtu(struct net_device *netdev, int new_mtu) { struct atl1_adapter *adapter = netdev_priv(netdev); - int old_mtu = netdev->mtu; int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); - return -EINVAL; - } - adapter->hw.max_frame_size = max_frame; adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3; adapter->rx_buffer_len = (max_frame + 7) & ~7; adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8; netdev->mtu = new_mtu; - if ((old_mtu != new_mtu) && netif_running(netdev)) { + if (netif_running(netdev)) { atl1_down(adapter); atl1_up(adapter); } @@ -3031,6 +3023,11 @@ static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* is this valid? see atl1_setup_mac_ctrl() */ netdev->features |= NETIF_F_RXCSUM; + /* MTU range: 42 - 10218 */ + netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN); + netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); + /* * patch for some L1 of old version, * the final version of L1 may not need these diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 2ff465848b65..6911394115b2 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -253,7 +253,7 @@ static int atl2_configure(struct atl2_adapter *adapter) /* set MTU */ ATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu + - ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE); + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); /* 1590 */ ATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177); @@ -925,15 +925,11 @@ static int atl2_change_mtu(struct net_device *netdev, int new_mtu) struct atl2_adapter *adapter = netdev_priv(netdev); struct atl2_hw *hw = &adapter->hw; - if ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE))) - return -EINVAL; - /* set MTU */ - if (hw->max_frame_size != new_mtu) { - netdev->mtu = new_mtu; - ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ENET_HEADER_SIZE + - VLAN_SIZE + ETHERNET_FCS_SIZE); - } + netdev->mtu = new_mtu; + hw->max_frame_size = new_mtu; + ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ETH_HLEN + + VLAN_HLEN + ETH_FCS_LEN); return 0; } @@ -1398,6 +1394,8 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->netdev_ops = &atl2_netdev_ops; netdev->ethtool_ops = &atl2_ethtool_ops; netdev->watchdog_timeo = 5 * HZ; + netdev->min_mtu = 40; + netdev->max_mtu = ETH_DATA_LEN + VLAN_HLEN; strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); netdev->mem_start = mmio_start; diff --git a/drivers/net/ethernet/atheros/atlx/atl2.h b/drivers/net/ethernet/atheros/atlx/atl2.h index 2f27d4c4c3ad..c64a6bdfa7ae 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.h +++ b/drivers/net/ethernet/atheros/atlx/atl2.h @@ -228,12 +228,9 @@ static void atl2_force_ps(struct atl2_hw *hw); #define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x000F /* Everything */ /* The size (in bytes) of a ethernet packet */ -#define ENET_HEADER_SIZE 14 #define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */ #define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */ -#define ETHERNET_FCS_SIZE 4 #define MAX_JUMBO_FRAME_SIZE 0x2000 -#define VLAN_SIZE 4 struct tx_pkt_header { unsigned pkt_size:11; -- cgit v1.2.3 From e1c6dccaf3af291488fbad155d7ee6bc29db262a Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:04 -0400 Subject: ethernet/broadcom: use core min/max MTU checking tg3: min_mtu 60, max_mtu 9000/1500 bnxt: min_mtu 60, max_mtu 9000 bnx2x: min_mtu 46, max_mtu 9600 - Fix up ETH_OVREHEAD -> ETH_OVERHEAD while we're in here, remove duplicated defines from bnx2x_link.c. bnx2: min_mtu 46, max_mtu 9000 - Use more standard ETH_* defines while we're at it. bcm63xx_enet: min_mtu 46, max_mtu 2028 - compute_hw_mtu was made largely pointless, and thus merged back into bcm_enet_change_mtu. b44: min_mtu 60, max_mtu 1500 CC: netdev@vger.kernel.org CC: Michael Chan CC: Sony Chacko CC: Ariel Elior CC: Dept-HSGLinuxNICDev@qlogic.com CC: Siva Reddy Kallam CC: Prashant Sreedharan Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/b44.c | 9 +++--- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 35 ++++++++---------------- drivers/net/ethernet/broadcom/bnx2.c | 16 +++++------ drivers/net/ethernet/broadcom/bnx2.h | 6 ++-- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 6 ++-- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 8 +----- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 22 ++++++--------- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 7 +++-- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 7 +++-- drivers/net/ethernet/broadcom/tg3.c | 9 +++--- 10 files changed, 51 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 17aa33c5567d..1df3048a3cdb 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -59,8 +59,8 @@ #define B44_TX_TIMEOUT (5 * HZ) /* hardware minimum and maximum for a single frame's data payload */ -#define B44_MIN_MTU 60 -#define B44_MAX_MTU 1500 +#define B44_MIN_MTU ETH_ZLEN +#define B44_MAX_MTU ETH_DATA_LEN #define B44_RX_RING_SIZE 512 #define B44_DEF_RX_RING_PENDING 200 @@ -1064,9 +1064,6 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu) { struct b44 *bp = netdev_priv(dev); - if (new_mtu < B44_MIN_MTU || new_mtu > B44_MAX_MTU) - return -EINVAL; - if (!netif_running(dev)) { /* We'll just catch it later when the * device is up'd. @@ -2377,6 +2374,8 @@ static int b44_init_one(struct ssb_device *sdev, dev->netdev_ops = &b44_netdev_ops; netif_napi_add(dev, &bp->napi, b44_poll, 64); dev->watchdog_timeo = B44_TX_TIMEOUT; + dev->min_mtu = B44_MIN_MTU; + dev->max_mtu = B44_MAX_MTU; dev->irq = sdev->irq; dev->ethtool_ops = &b44_ethtool_ops; diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index ae364c74baf3..7e513cacb57a 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1622,20 +1622,19 @@ static int bcm_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } /* - * calculate actual hardware mtu + * adjust mtu, can't be called while device is running */ -static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu) +static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu) { - int actual_mtu; + struct bcm_enet_priv *priv = netdev_priv(dev); + int actual_mtu = new_mtu; - actual_mtu = mtu; + if (netif_running(dev)) + return -EBUSY; /* add ethernet header + vlan tag size */ actual_mtu += VLAN_ETH_HLEN; - if (actual_mtu < 64 || actual_mtu > BCMENET_MAX_MTU) - return -EINVAL; - /* * setup maximum size before we get overflow mark in * descriptor, note that this will not prevent reception of @@ -1650,22 +1649,7 @@ static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu) */ priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN, priv->dma_maxburst * 4); - return 0; -} -/* - * adjust mtu, can't be called while device is running - */ -static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu) -{ - int ret; - - if (netif_running(dev)) - return -EBUSY; - - ret = compute_hw_mtu(netdev_priv(dev), new_mtu); - if (ret) - return ret; dev->mtu = new_mtu; return 0; } @@ -1755,7 +1739,7 @@ static int bcm_enet_probe(struct platform_device *pdev) priv->enet_is_sw = false; priv->dma_maxburst = BCMENET_DMA_MAXBURST; - ret = compute_hw_mtu(priv, dev->mtu); + ret = bcm_enet_change_mtu(dev, dev->mtu); if (ret) goto out; @@ -1888,6 +1872,9 @@ static int bcm_enet_probe(struct platform_device *pdev) netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16); dev->ethtool_ops = &bcm_enet_ethtool_ops; + /* MTU range: 46 - 2028 */ + dev->min_mtu = ETH_ZLEN - ETH_HLEN; + dev->max_mtu = BCMENET_MAX_MTU - VLAN_ETH_HLEN; SET_NETDEV_DEV(dev, &pdev->dev); ret = register_netdev(dev); @@ -2742,7 +2729,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev) priv->dma_chan_width = pd->dma_chan_width; } - ret = compute_hw_mtu(priv, dev->mtu); + ret = bcm_enet_change_mtu(dev, dev->mtu); if (ret) goto out; diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 27f11a5d5fe2..2a5df3f71e9f 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -2298,7 +2298,7 @@ bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy) if (BNX2_CHIP(bp) == BNX2_CHIP_5706) BNX2_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300); - if (bp->dev->mtu > 1500) { + if (bp->dev->mtu > ETH_DATA_LEN) { u32 val; /* Set extended packet length bit */ @@ -2352,7 +2352,7 @@ bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy) bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val); } - if (bp->dev->mtu > 1500) { + if (bp->dev->mtu > ETH_DATA_LEN) { /* Set extended packet length bit */ bnx2_write_phy(bp, 0x18, 0x7); bnx2_read_phy(bp, 0x18, &val); @@ -4985,12 +4985,12 @@ bnx2_init_chip(struct bnx2 *bp) /* Program the MTU. Also include 4 bytes for CRC32. */ mtu = bp->dev->mtu; val = mtu + ETH_HLEN + ETH_FCS_LEN; - if (val > (MAX_ETHERNET_PACKET_SIZE + 4)) + if (val > (MAX_ETHERNET_PACKET_SIZE + ETH_HLEN + 4)) val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA; BNX2_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val); - if (mtu < 1500) - mtu = 1500; + if (mtu < ETH_DATA_LEN) + mtu = ETH_DATA_LEN; bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG, BNX2_RBUF_CONFIG_VAL(mtu)); bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG2, BNX2_RBUF_CONFIG2_VAL(mtu)); @@ -7896,10 +7896,6 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu) { struct bnx2 *bp = netdev_priv(dev); - if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) || - ((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE)) - return -EINVAL; - dev->mtu = new_mtu; return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size, false); @@ -8589,6 +8585,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; dev->features |= dev->hw_features; dev->priv_flags |= IFF_UNICAST_FLT; + dev->min_mtu = MIN_ETHERNET_PACKET_SIZE; + dev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE; if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)) dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h index 380234d72b95..a09ec47461c9 100644 --- a/drivers/net/ethernet/broadcom/bnx2.h +++ b/drivers/net/ethernet/broadcom/bnx2.h @@ -6530,9 +6530,9 @@ struct l2_fhdr { #define MII_BNX2_AER_AER_AN_MMD 0x3800 #define MII_BNX2_BLK_ADDR_COMBO_IEEEB0 0xffe0 -#define MIN_ETHERNET_PACKET_SIZE 60 -#define MAX_ETHERNET_PACKET_SIZE 1514 -#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014 +#define MIN_ETHERNET_PACKET_SIZE (ETH_ZLEN - ETH_HLEN) +#define MAX_ETHERNET_PACKET_SIZE ETH_DATA_LEN +#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9000 #define BNX2_RX_COPY_THRESH 128 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 7dd7490fdac1..0a23034bbe3f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1396,9 +1396,9 @@ struct bnx2x { int tx_ring_size; /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */ -#define ETH_OVREHEAD (ETH_HLEN + 8 + 8) -#define ETH_MIN_PACKET_SIZE 60 -#define ETH_MAX_PACKET_SIZE 1500 +#define ETH_OVERHEAD (ETH_HLEN + 8 + 8) +#define ETH_MIN_PACKET_SIZE (ETH_ZLEN - ETH_HLEN) +#define ETH_MAX_PACKET_SIZE ETH_DATA_LEN #define ETH_MAX_JUMBO_PACKET_SIZE 9600 /* TCP with Timestamp Option (32) + IPv6 (40) */ #define ETH_MAX_TPA_HEADER_SIZE 72 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 0a9108cd4c45..ed42c1009685 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2023,7 +2023,7 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp) mtu = bp->dev->mtu; fp->rx_buf_size = BNX2X_FW_RX_ALIGN_START + IP_HEADER_ALIGNMENT_PADDING + - ETH_OVREHEAD + + ETH_OVERHEAD + mtu + BNX2X_FW_RX_ALIGN_END; /* Note : rx_buf_size doesn't take into account NET_SKB_PAD */ @@ -4855,12 +4855,6 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu) return -EAGAIN; } - if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) || - ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) { - BNX2X_ERR("Can't support requested MTU size\n"); - return -EINVAL; - } - /* This does not race with packet allocation * because the actual alloc size is * only updated as part of load diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 1fb80100e5e7..05356efdbf93 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -34,12 +34,6 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy, u8 dev_addr, u16 addr, u8 byte_cnt, u8 *o_buf, u8); /********************************************************/ -#define ETH_HLEN 14 -/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */ -#define ETH_OVREHEAD (ETH_HLEN + 8 + 8) -#define ETH_MIN_PACKET_SIZE 60 -#define ETH_MAX_PACKET_SIZE 1500 -#define ETH_MAX_JUMBO_PACKET_SIZE 9600 #define MDIO_ACCESS_TIMEOUT 1000 #define WC_LANE_MAX 4 #define I2C_SWITCH_WIDTH 2 @@ -1917,7 +1911,7 @@ static int bnx2x_emac_enable(struct link_params *params, /* Enable emac for jumbo packets */ EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE, (EMAC_RX_MTU_SIZE_JUMBO_ENA | - (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD))); + (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD))); /* Strip CRC */ REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1); @@ -2314,19 +2308,19 @@ static int bnx2x_bmac1_enable(struct link_params *params, REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2); /* Set rx mtu */ - wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD; + wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD; wb_data[1] = 0; REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2); bnx2x_update_pfc_bmac1(params, vars); /* Set tx mtu */ - wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD; + wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD; wb_data[1] = 0; REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE, wb_data, 2); /* Set cnt max size */ - wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD; + wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD; wb_data[1] = 0; REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2); @@ -2384,18 +2378,18 @@ static int bnx2x_bmac2_enable(struct link_params *params, udelay(30); /* Set RX MTU */ - wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD; + wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD; wb_data[1] = 0; REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE, wb_data, 2); udelay(30); /* Set TX MTU */ - wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD; + wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD; wb_data[1] = 0; REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE, wb_data, 2); udelay(30); /* Set cnt max size */ - wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD - 2; + wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD - 2; wb_data[1] = 0; REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2); udelay(30); @@ -2516,7 +2510,7 @@ static int bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl, } else { u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE + - ETH_OVREHEAD)/16; + ETH_OVERHEAD)/16; REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0); /* Update threshold */ REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 20fe6a8c35c1..67b6180bdbf6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12080,8 +12080,7 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp) mtu_size, mtu); /* if valid: update device mtu */ - if (((mtu_size + ETH_HLEN) >= - ETH_MIN_PACKET_SIZE) && + if ((mtu_size >= ETH_MIN_PACKET_SIZE) && (mtu_size <= ETH_MAX_JUMBO_PACKET_SIZE)) bp->dev->mtu = mtu_size; @@ -13315,6 +13314,10 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, dev->dcbnl_ops = &bnx2x_dcbnl_ops; #endif + /* MTU range, 46 - 9600 */ + dev->min_mtu = ETH_MIN_PACKET_SIZE; + dev->max_mtu = ETH_MAX_JUMBO_PACKET_SIZE; + /* get_port_hwinfo() will set prtad and mmds properly */ bp->mdio.prtad = MDIO_PRTAD_NONE; bp->mdio.mmds = 0; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index a9f9f3738022..a042da1ff4b9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6290,9 +6290,6 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu) { struct bnxt *bp = netdev_priv(dev); - if (new_mtu < 60 || new_mtu > 9500) - return -EINVAL; - if (netif_running(dev)) bnxt_close_nic(bp, false, false); @@ -6870,6 +6867,10 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->features |= dev->hw_features | NETIF_F_HIGHDMA; dev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 60 - 9500 */ + dev->min_mtu = ETH_ZLEN; + dev->max_mtu = 9500; + #ifdef CONFIG_BNXT_SRIOV init_waitqueue_head(&bp->sriov_cfg_wait); #endif diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index a927a730da10..185e9e047aa9 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -124,7 +124,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define TG3_TX_TIMEOUT (5 * HZ) /* hardware minimum and maximum for a single frame's data payload */ -#define TG3_MIN_MTU 60 +#define TG3_MIN_MTU ETH_ZLEN #define TG3_MAX_MTU(tp) \ (tg3_flag(tp, JUMBO_CAPABLE) ? 9000 : 1500) @@ -14199,9 +14199,6 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) int err; bool reset_phy = false; - if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) - return -EINVAL; - if (!netif_running(dev)) { /* We'll just catch it later when the * device is up'd. @@ -17799,6 +17796,10 @@ static int tg3_init_one(struct pci_dev *pdev, dev->hw_features |= features; dev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 60 - 9000 or 1500, depending on hardware */ + dev->min_mtu = TG3_MIN_MTU; + dev->max_mtu = TG3_MAX_MTU(tp); + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A1 && !tg3_flag(tp, TSO_CAPABLE) && !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { -- cgit v1.2.3 From 91c527a55664ddf4bee26673a35f91748dae4142 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:05 -0400 Subject: ethernet/intel: use core min/max MTU checking e100: min_mtu 68, max_mtu 1500 - remove e100_change_mtu entirely, is identical to old eth_change_mtu, and no longer serves a purpose. No need to set min_mtu or max_mtu explicitly, as ether_setup() will already set them to 68 and 1500. e1000: min_mtu 46, max_mtu 16110 e1000e: min_mtu 68, max_mtu varies based on adapter fm10k: min_mtu 68, max_mtu 15342 - remove fm10k_change_mtu entirely, does nothing now i40e: min_mtu 68, max_mtu 9706 i40evf: min_mtu 68, max_mtu 9706 igb: min_mtu 68, max_mtu 9216 - There are two different "max" frame sizes claimed and both checked in the driver, the larger value wasn't relevant though, so I've set max_mtu to the smaller of the two values here to retain identical behavior. igbvf: min_mtu 68, max_mtu 9216 - Same issue as igb duplicated ixgb: min_mtu 68, max_mtu 16114 - Also remove pointless old == new check, as that's done in dev_set_mtu ixgbe: min_mtu 68, max_mtu 9710 ixgbevf: min_mtu 68, max_mtu dependent on hardware/firmware - Some hw can only handle up to max_mtu 1504 on a vf, others 9710 CC: netdev@vger.kernel.org CC: intel-wired-lan@lists.osuosl.org CC: Jeff Kirsher Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/e100.c | 9 ------- drivers/net/ethernet/intel/e1000/e1000_main.c | 12 ++++----- drivers/net/ethernet/intel/e1000e/netdev.c | 14 +++++----- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 15 +++-------- drivers/net/ethernet/intel/i40e/i40e_main.c | 10 +++---- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 8 +++--- drivers/net/ethernet/intel/igb/e1000_defines.h | 3 ++- drivers/net/ethernet/intel/igb/igb_main.c | 15 +++-------- drivers/net/ethernet/intel/igbvf/defines.h | 3 ++- drivers/net/ethernet/intel/igbvf/netdev.c | 14 +++------- drivers/net/ethernet/intel/ixgb/ixgb_main.c | 16 +++-------- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 11 ++++---- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 33 ++++++++++++----------- 13 files changed, 62 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 068789e694c9..25c6dfd500b4 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -2286,14 +2286,6 @@ static int e100_set_mac_address(struct net_device *netdev, void *p) return 0; } -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - static int e100_asf(struct nic *nic) { /* ASF can be enabled from eeprom */ @@ -2834,7 +2826,6 @@ static const struct net_device_ops e100_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_rx_mode = e100_set_multicast_list, .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, .ndo_do_ioctl = e100_do_ioctl, .ndo_tx_timeout = e100_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index f42129d09e2c..33076fa98002 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -1085,6 +1085,10 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->subsystem_vendor_id != PCI_VENDOR_ID_VMWARE) netdev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 46 - 16110 */ + netdev->min_mtu = ETH_ZLEN - ETH_HLEN; + netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN); + adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); /* initialize eeprom parameters */ @@ -3549,13 +3553,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - - if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - e_err(probe, "Invalid MTU setting\n"); - return -EINVAL; - } + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; /* Adapter-specific max frame size limits. */ switch (hw->mac_type) { diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 7017281ba2dc..8759d9236930 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5974,19 +5974,12 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) int max_frame = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; /* Jumbo frame support */ - if ((max_frame > (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)) && + if ((new_mtu > ETH_DATA_LEN) && !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { e_err("Jumbo Frames not supported.\n"); return -EINVAL; } - /* Supported frame sizes */ - if ((new_mtu < (VLAN_ETH_ZLEN + ETH_FCS_LEN)) || - (max_frame > adapter->max_hw_frame_size)) { - e_err("Unsupported MTU setting\n"); - return -EINVAL; - } - /* Jumbo frame workaround on 82579 and newer requires CRC be stripped */ if ((adapter->hw.mac.type >= e1000_pch2lan) && !(adapter->flags2 & FLAG2_CRC_STRIPPING) && @@ -7187,6 +7180,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->vlan_features |= NETIF_F_HIGHDMA; } + /* MTU range: 68 - max_hw_frame_size */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = adapter->max_hw_frame_size - + (VLAN_ETH_HLEN + ETH_FCS_LEN); + if (e1000e_enable_mng_pass_thru(&adapter->hw)) adapter->flags |= FLAG_MNG_PT_ENABLED; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 05629381be6b..bc5ef6eb3dd6 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -706,16 +706,6 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev) return err; } -static int fm10k_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < 68 || new_mtu > FM10K_MAX_JUMBO_FRAME_SIZE) - return -EINVAL; - - dev->mtu = new_mtu; - - return 0; -} - /** * fm10k_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure @@ -1405,7 +1395,6 @@ static const struct net_device_ops fm10k_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_start_xmit = fm10k_xmit_frame, .ndo_set_mac_address = fm10k_set_mac, - .ndo_change_mtu = fm10k_change_mtu, .ndo_tx_timeout = fm10k_tx_timeout, .ndo_vlan_rx_add_vid = fm10k_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = fm10k_vlan_rx_kill_vid, @@ -1490,5 +1479,9 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info) dev->hw_features |= hw_features; + /* MTU range: 68 - 15342 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = FM10K_MAX_JUMBO_FRAME_SIZE; + return dev; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index ac1faee2a5b8..83edbe8e3618 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2239,13 +2239,8 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) static int i40e_change_mtu(struct net_device *netdev, int new_mtu) { struct i40e_netdev_priv *np = netdev_priv(netdev); - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; struct i40e_vsi *vsi = np->vsi; - /* MTU < 68 is an error and causes problems on some kernels */ - if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER)) - return -EINVAL; - netdev_info(netdev, "changing MTU from %d to %d\n", netdev->mtu, new_mtu); netdev->mtu = new_mtu; @@ -9220,6 +9215,11 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) i40e_fcoe_config_netdev(netdev, vsi); #endif + /* MTU range: 68 - 9706 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = I40E_MAX_RXBUFFER - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); + return 0; } diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 14372810fc27..777eb29e4ff7 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2133,10 +2133,6 @@ static struct net_device_stats *i40evf_get_stats(struct net_device *netdev) static int i40evf_change_mtu(struct net_device *netdev, int new_mtu) { struct i40evf_adapter *adapter = netdev_priv(netdev); - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - - if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER)) - return -EINVAL; netdev->mtu = new_mtu; adapter->flags |= I40EVF_FLAG_RESET_NEEDED; @@ -2424,6 +2420,10 @@ static void i40evf_init_task(struct work_struct *work) i40evf_set_ethtool_ops(netdev); netdev->watchdog_timeo = 5 * HZ; + /* MTU range: 68 - 9710 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = I40E_MAX_RXBUFFER - (ETH_HLEN + ETH_FCS_LEN); + if (!is_valid_ether_addr(adapter->hw.mac.addr)) { dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n", adapter->hw.mac.addr); diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index 2688180a7acd..8aee314332a8 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -357,7 +357,8 @@ #define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ /* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */ -#define MAX_JUMBO_FRAME_SIZE 0x2600 +#define MAX_JUMBO_FRAME_SIZE 0x2600 +#define MAX_STD_JUMBO_FRAME_SIZE 9216 /* PBA constants */ #define E1000_PBA_34K 0x0022 diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index edc9a6ac5169..4feca69e5833 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2468,6 +2468,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 68 - 9216 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; + adapter->en_mng_pt = igb_enable_mng_pass_thru(hw); /* before reading the NVM, reset the controller to put the device in a @@ -5408,17 +5412,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) struct pci_dev *pdev = adapter->pdev; int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { - dev_err(&pdev->dev, "Invalid MTU setting\n"); - return -EINVAL; - } - -#define MAX_STD_JUMBO_FRAME_SIZE 9238 - if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { - dev_err(&pdev->dev, "MTU > 9216 not supported.\n"); - return -EINVAL; - } - /* adjust max frame to be at least the size of a standard frame */ if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN)) max_frame = ETH_FRAME_LEN + ETH_FCS_LEN; diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h index ee1ef08d7fc4..f1789d192e24 100644 --- a/drivers/net/ethernet/intel/igbvf/defines.h +++ b/drivers/net/ethernet/intel/igbvf/defines.h @@ -85,7 +85,8 @@ #define E1000_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */ #define E1000_TXD_STAT_DD 0x00000001 /* Desc Done */ -#define MAX_JUMBO_FRAME_SIZE 0x3F00 +#define MAX_JUMBO_FRAME_SIZE 0x3F00 +#define MAX_STD_JUMBO_FRAME_SIZE 9216 /* 802.1q VLAN Packet Size */ #define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 12bb877df860..810fcf7aa2c6 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -2356,16 +2356,6 @@ static int igbvf_change_mtu(struct net_device *netdev, int new_mtu) struct igbvf_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - if (new_mtu < 68 || new_mtu > INT_MAX - ETH_HLEN - ETH_FCS_LEN || - max_frame > MAX_JUMBO_FRAME_SIZE) - return -EINVAL; - -#define MAX_STD_JUMBO_FRAME_SIZE 9234 - if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { - dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n"); - return -EINVAL; - } - while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state)) usleep_range(1000, 2000); /* igbvf_down has a dependency on max_frame_size */ @@ -2786,6 +2776,10 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; + /* MTU range: 68 - 9216 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; + /*reset the controller to put the device in a known good state */ err = hw->mac.ops.reset_hw(hw); if (err) { diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index 31f91459312f..5826b1ddedcf 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -487,6 +487,10 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->vlan_features |= NETIF_F_HIGHDMA; } + /* MTU range: 68 - 16114 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = IXGB_MAX_JUMBO_FRAME_SIZE - ETH_HLEN; + /* make sure the EEPROM is good */ if (!ixgb_validate_eeprom_checksum(&adapter->hw)) { @@ -1619,18 +1623,6 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu) { struct ixgb_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH; - int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH; - - /* MTU < 68 is an error for IPv4 traffic, just don't allow it */ - if ((new_mtu < 68) || - (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) { - netif_err(adapter, probe, adapter->netdev, - "Invalid MTU setting %d\n", new_mtu); - return -EINVAL; - } - - if (old_max_frame == max_frame) - return 0; if (netif_running(netdev)) ixgb_down(adapter, true); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 784b0b98ab2f..7dfde209b0e0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6049,11 +6049,6 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter) static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - - /* MTU < 68 is an error and causes problems on some kernels */ - if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) - return -EINVAL; /* * For 82599EB we cannot allow legacy VFs to enable their receive @@ -6062,7 +6057,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) */ if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) && (adapter->hw.mac.type == ixgbe_mac_82599EB) && - (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN))) + (new_mtu > ETH_DATA_LEN)) e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n"); e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu); @@ -9608,6 +9603,10 @@ skip_sriov: netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; + /* MTU range: 68 - 9710 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN); + #ifdef CONFIG_IXGBE_DCB if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE) netdev->dcbnl_ops = &dcbnl_ops; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 7eaac3234049..d2775f032f74 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3742,24 +3742,8 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu) struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE; int ret; - switch (adapter->hw.api_version) { - case ixgbe_mbox_api_11: - case ixgbe_mbox_api_12: - max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE; - break; - default: - if (adapter->hw.mac.type != ixgbe_mac_82599_vf) - max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE; - break; - } - - /* MTU < 68 is an error and causes problems on some kernels */ - if ((new_mtu < 68) || (max_frame > max_possible_frame)) - return -EINVAL; - spin_lock_bh(&adapter->mbx_lock); /* notify the PF of our intent to use this size of frame */ ret = hw->mac.ops.set_rlpml(hw, max_frame); @@ -4104,6 +4088,23 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 68 - 1504 or 9710 */ + netdev->min_mtu = ETH_MIN_MTU; + switch (adapter->hw.api_version) { + case ixgbe_mbox_api_11: + case ixgbe_mbox_api_12: + netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN); + break; + default: + if (adapter->hw.mac.type != ixgbe_mac_82599_vf) + netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN); + else + netdev->max_mtu = ETH_DATA_LEN + ETH_FCS_LEN; + break; + } + if (IXGBE_REMOVED(hw->hw_addr)) { err = -EIO; goto err_sw_init; -- cgit v1.2.3 From 5777987e0f4bf83c874b538d6be4029f4597878a Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:06 -0400 Subject: ethernet/marvell: use core min/max MTU checking mvneta: min_mtu 68, max_mtu 9676 - mtu validation routine mostly did range check, merge back into mvneta_change_mtu for simplicity mvpp2: min_mtu 68, max_mtu 9676 - mtu validation routine mostly did range check, merge back into mvpp2_change_mtu for simplicity pxa168_eth: min_mtu 68, max_mtu 9500 skge: min_mtu 60, max_mtu 9000 sky2: min_mtu 68, max_mtu 1500 or 9000, depending on hw CC: netdev@vger.kernel.org CC: Mirko Lindner CC: Stephen Hemminger CC: Thomas Petazzoni Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 36 +++++++++---------------------- drivers/net/ethernet/marvell/mvpp2.c | 36 ++++++++----------------------- drivers/net/ethernet/marvell/pxa168_eth.c | 7 +++--- drivers/net/ethernet/marvell/skge.c | 7 +++--- drivers/net/ethernet/marvell/sky2.c | 18 +++++++--------- 5 files changed, 35 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 5cb07c2017bf..b85819ea8eea 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3024,29 +3024,6 @@ static void mvneta_stop_dev(struct mvneta_port *pp) mvneta_rx_reset(pp); } -/* Return positive if MTU is valid */ -static int mvneta_check_mtu_valid(struct net_device *dev, int mtu) -{ - if (mtu < 68) { - netdev_err(dev, "cannot change mtu to less than 68\n"); - return -EINVAL; - } - - /* 9676 == 9700 - 20 and rounding to 8 */ - if (mtu > 9676) { - netdev_info(dev, "Illegal MTU value %d, round to 9676\n", mtu); - mtu = 9676; - } - - if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) { - netdev_info(dev, "Illegal MTU value %d, rounding to %d\n", - mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8)); - mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8); - } - - return mtu; -} - static void mvneta_percpu_enable(void *arg) { struct mvneta_port *pp = arg; @@ -3067,9 +3044,11 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) struct mvneta_port *pp = netdev_priv(dev); int ret; - mtu = mvneta_check_mtu_valid(dev, mtu); - if (mtu < 0) - return -EINVAL; + if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) { + netdev_info(dev, "Illegal MTU value %d, rounding to %d\n", + mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8)); + mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8); + } dev->mtu = mtu; @@ -4154,6 +4133,11 @@ static int mvneta_probe(struct platform_device *pdev) dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE; dev->gso_max_segs = MVNETA_MAX_TSO_SEGS; + /* MTU range: 68 - 9676 */ + dev->min_mtu = ETH_MIN_MTU; + /* 9676 == 9700 - 20 and rounding to 8 */ + dev->max_mtu = 9676; + err = register_netdev(dev); if (err < 0) { dev_err(&pdev->dev, "failed to register\n"); diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index 60227a3452a4..c8bf155cad94 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -5453,29 +5453,6 @@ static void mvpp2_stop_dev(struct mvpp2_port *port) phy_stop(ndev->phydev); } -/* Return positive if MTU is valid */ -static inline int mvpp2_check_mtu_valid(struct net_device *dev, int mtu) -{ - if (mtu < 68) { - netdev_err(dev, "cannot change mtu to less than 68\n"); - return -EINVAL; - } - - /* 9676 == 9700 - 20 and rounding to 8 */ - if (mtu > 9676) { - netdev_info(dev, "illegal MTU value %d, round to 9676\n", mtu); - mtu = 9676; - } - - if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) { - netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu, - ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8)); - mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8); - } - - return mtu; -} - static int mvpp2_check_ringparam_valid(struct net_device *dev, struct ethtool_ringparam *ring) { @@ -5717,10 +5694,10 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu) struct mvpp2_port *port = netdev_priv(dev); int err; - mtu = mvpp2_check_mtu_valid(dev, mtu); - if (mtu < 0) { - err = mtu; - goto error; + if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) { + netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu, + ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8)); + mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8); } if (!netif_running(dev)) { @@ -6212,6 +6189,11 @@ static int mvpp2_port_probe(struct platform_device *pdev, dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO; dev->vlan_features |= features; + /* MTU range: 68 - 9676 */ + dev->min_mtu = ETH_MIN_MTU; + /* 9676 == 9700 - 20 and rounding to 8 */ + dev->max_mtu = 9676; + err = register_netdev(dev); if (err < 0) { dev_err(&pdev->dev, "failed to register netdev\n"); diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 5d5000c8edf1..b78a838f306c 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1209,9 +1209,6 @@ static int pxa168_eth_change_mtu(struct net_device *dev, int mtu) int retval; struct pxa168_eth_private *pep = netdev_priv(dev); - if ((mtu > 9500) || (mtu < 68)) - return -EINVAL; - dev->mtu = mtu; retval = set_port_config_ext(pep); @@ -1459,6 +1456,10 @@ static int pxa168_eth_probe(struct platform_device *pdev) dev->base_addr = 0; dev->ethtool_ops = &pxa168_ethtool_ops; + /* MTU range: 68 - 9500 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = 9500; + INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task); if (pdev->dev.of_node) diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 7173836fe361..9c4b722c3fdd 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -2900,9 +2900,6 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu) { int err; - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) - return -EINVAL; - if (!netif_running(dev)) { dev->mtu = new_mtu; return 0; @@ -3857,6 +3854,10 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, dev->watchdog_timeo = TX_WATCHDOG; dev->irq = hw->pdev->irq; + /* MTU range: 60 - 9000 */ + dev->min_mtu = ETH_ZLEN; + dev->max_mtu = ETH_JUMBO_MTU; + if (highmem) dev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index f05ea56dcff2..aa60f4dcddd8 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -2398,16 +2398,6 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) u16 ctl, mode; u32 imask; - /* MTU size outside the spec */ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) - return -EINVAL; - - /* MTU > 1500 on yukon FE and FE+ not allowed */ - if (new_mtu > ETH_DATA_LEN && - (hw->chip_id == CHIP_ID_YUKON_FE || - hw->chip_id == CHIP_ID_YUKON_FE_P)) - return -EINVAL; - if (!netif_running(dev)) { dev->mtu = new_mtu; netdev_update_features(dev); @@ -4808,6 +4798,14 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port, dev->features |= dev->hw_features; + /* MTU range: 60 - 1500 or 9000 */ + dev->min_mtu = ETH_ZLEN; + if (hw->chip_id == CHIP_ID_YUKON_FE || + hw->chip_id == CHIP_ID_YUKON_FE_P) + dev->max_mtu = ETH_DATA_LEN; + else + dev->max_mtu = ETH_JUMBO_MTU; + /* try to get mac address in the following order: * 1) from device tree data * 2) from internal registers set by bootloader -- cgit v1.2.3 From b80f71f5816fce2da8a0df22719f106c0a3d8dc7 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:07 -0400 Subject: ethernet/mellanox: use core min/max MTU checking mlx4: min_mtu 46, max_mtu depends on hardware mlx5: min_mtu 68, max_mtu depends on hardware CC: netdev@vger.kernel.org CC: Tariq Toukan CC: Saeed Mahameed Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 8 ++++---- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 24 ++++++----------------- 2 files changed, 10 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 7e703bed7b82..bf35ac4c1c61 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2205,10 +2205,6 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) en_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n", dev->mtu, new_mtu); - if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) { - en_err(priv, "Bad MTU size:%d.\n", new_mtu); - return -EPERM; - } if (priv->xdp_ring_num && MLX4_EN_EFF_MTU(new_mtu) > FRAG_SZ0) { en_err(priv, "MTU size:%d requires frags but XDP running\n", new_mtu); @@ -3288,6 +3284,10 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM; } + /* MTU range: 46 - hw-specific max */ + dev->min_mtu = MLX4_EN_MIN_MTU; + dev->max_mtu = priv->max_mtu; + mdev->pndev[port] = dev; mdev->upper[port] = NULL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 7eaf38020a8f..03183eba7003 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2851,31 +2851,13 @@ static int mlx5e_set_features(struct net_device *netdev, return err ? -EINVAL : 0; } -#define MXL5_HW_MIN_MTU 64 -#define MXL5E_MIN_MTU (MXL5_HW_MIN_MTU + ETH_FCS_LEN) - static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu) { struct mlx5e_priv *priv = netdev_priv(netdev); - struct mlx5_core_dev *mdev = priv->mdev; bool was_opened; - u16 max_mtu; - u16 min_mtu; int err = 0; bool reset; - mlx5_query_port_max_mtu(mdev, &max_mtu, 1); - - max_mtu = MLX5E_HW2SW_MTU(max_mtu); - min_mtu = MLX5E_HW2SW_MTU(MXL5E_MIN_MTU); - - if (new_mtu > max_mtu || new_mtu < min_mtu) { - netdev_err(netdev, - "%s: Bad MTU (%d), valid range is: [%d..%d]\n", - __func__, new_mtu, min_mtu, max_mtu); - return -EINVAL; - } - mutex_lock(&priv->state_lock); reset = !priv->params.lro_en && @@ -3835,6 +3817,7 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev) { const struct mlx5e_profile *profile; struct mlx5e_priv *priv; + u16 max_mtu; int err; priv = netdev_priv(netdev); @@ -3865,6 +3848,11 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev) mlx5e_init_l2_addr(priv); + /* MTU range: 68 - hw-specific max */ + netdev->min_mtu = ETH_MIN_MTU; + mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1); + netdev->max_mtu = MLX5E_HW2SW_MTU(max_mtu); + mlx5e_set_dev_port_mtu(netdev); if (profile->enable) -- cgit v1.2.3 From caff2a87f60ab15ce872e65d577d7577c9121026 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:08 -0400 Subject: ethernet/qlogic: use core min/max MTU checking qede: min_mtu 46, max_mtu 9600 - Put define for max in qede.h qlcnic: min_mtu 68, max_mtu 9600 CC: netdev@vger.kernel.org CC Dept-GELinuxNICDev@qlogic.com CC: Yuval Mintz CC: Ariel Elior Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede.h | 5 +++-- drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 8 -------- drivers/net/ethernet/qlogic/qede/qede_main.c | 4 ++++ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 6 ------ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 4 ++++ 5 files changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index f50e5270ad30..9135b9d37dfa 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -362,8 +362,9 @@ void qede_recycle_rx_bd_ring(struct qede_rx_queue *rxq, struct qede_dev *edev, #define NUM_TX_BDS_MIN 128 #define NUM_TX_BDS_DEF NUM_TX_BDS_MAX -#define QEDE_MIN_PKT_LEN 64 -#define QEDE_RX_HDR_SIZE 256 +#define QEDE_MIN_PKT_LEN 64 +#define QEDE_RX_HDR_SIZE 256 +#define QEDE_MAX_JUMBO_PACKET_SIZE 9600 #define for_each_queue(i) for (i = 0; i < edev->num_queues; i++) #endif /* _QEDE_H_ */ diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index 25a9b293ee8f..b7dbb4493a64 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -723,19 +723,11 @@ static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args) } /* Netdevice NDOs */ -#define ETH_MAX_JUMBO_PACKET_SIZE 9600 -#define ETH_MIN_PACKET_SIZE 60 int qede_change_mtu(struct net_device *ndev, int new_mtu) { struct qede_dev *edev = netdev_priv(ndev); union qede_reload_args args; - if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) || - ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) { - DP_ERR(edev, "Can't support requested MTU size\n"); - return -EINVAL; - } - DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), "Configuring MTU size of %d\n", new_mtu); diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 0e483afc2b87..4f298656bf47 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -2391,6 +2391,10 @@ static void qede_init_ndev(struct qede_dev *edev) ndev->hw_features = hw_features; + /* MTU range: 46 - 9600 */ + ndev->min_mtu = ETH_ZLEN - ETH_HLEN; + ndev->max_mtu = QEDE_MAX_JUMBO_PACKET_SIZE; + /* Set network device HW mac */ ether_addr_copy(edev->ndev->dev_addr, edev->dev_info.common.hw_mac); } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 509b596cf1e8..838cc0ceafd8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -1024,12 +1024,6 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu) struct qlcnic_adapter *adapter = netdev_priv(netdev); int rc = 0; - if (mtu < P3P_MIN_MTU || mtu > P3P_MAX_MTU) { - dev_err(&adapter->netdev->dev, "%d bytes < mtu < %d bytes" - " not supported\n", P3P_MAX_MTU, P3P_MIN_MTU); - return -EINVAL; - } - rc = qlcnic_fw_cmd_set_mtu(adapter, mtu); if (!rc) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 3ae3968b0edf..4c0cce962585 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2342,6 +2342,10 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, netdev->priv_flags |= IFF_UNICAST_FLT; netdev->irq = adapter->msix_entries[0].vector; + /* MTU range: 68 - 9600 */ + netdev->min_mtu = P3P_MIN_MTU; + netdev->max_mtu = P3P_MAX_MTU; + err = qlcnic_set_real_num_queues(adapter, adapter->drv_tx_rings, adapter->drv_sds_rings); if (err) -- cgit v1.2.3 From c7315a95c2a3c8a5a5e31c72755d7505e92f0872 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:09 -0400 Subject: ethernet/realtek: use core min/max MTU checking 8139cp: min_mtu 60, max_mtu 4096 8139too: min_mtu 68, max_mtu 1770 r8169: min_mtu 60, max_mtu depends on chipset, 1500 to 9k-ish CC: netdev@vger.kernel.org CC: Realtek linux nic maintainers Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/8139cp.c | 8 ++++---- drivers/net/ethernet/realtek/8139too.c | 13 ++++--------- drivers/net/ethernet/realtek/r8169.c | 8 ++++---- 3 files changed, 12 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 5297bf77211c..b7c89ebcf4a2 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -1277,10 +1277,6 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu) { struct cp_private *cp = netdev_priv(dev); - /* check for invalid MTU, according to hardware limits */ - if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU) - return -EINVAL; - /* if network interface not up, no need for complexity */ if (!netif_running(dev)) { dev->mtu = new_mtu; @@ -2010,6 +2006,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | NETIF_F_HIGHDMA; + /* MTU range: 60 - 4096 */ + dev->min_mtu = CP_MIN_MTU; + dev->max_mtu = CP_MAX_MTU; + rc = register_netdev(dev); if (rc) goto err_out_iomap; diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index da4c2d8a4173..9bc047ac883b 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c @@ -924,19 +924,10 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur return 0; } -static int rtl8139_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < 68 || new_mtu > MAX_ETH_DATA_SIZE) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static const struct net_device_ops rtl8139_netdev_ops = { .ndo_open = rtl8139_open, .ndo_stop = rtl8139_close, .ndo_get_stats64 = rtl8139_get_stats64, - .ndo_change_mtu = rtl8139_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = rtl8139_set_mac_address, .ndo_start_xmit = rtl8139_start_xmit, @@ -1022,6 +1013,10 @@ static int rtl8139_init_one(struct pci_dev *pdev, dev->hw_features |= NETIF_F_RXALL; dev->hw_features |= NETIF_F_RXFCS; + /* MTU range: 68 - 1770 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = MAX_ETH_DATA_SIZE; + /* tp zeroed and aligned in alloc_etherdev */ tp = netdev_priv(dev); diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e55638c7505a..b698ea544bfc 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -6673,10 +6673,6 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) { struct rtl8169_private *tp = netdev_priv(dev); - if (new_mtu < ETH_ZLEN || - new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max) - return -EINVAL; - if (new_mtu > ETH_DATA_LEN) rtl_hw_jumbo_enable(tp); else @@ -8430,6 +8426,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->hw_features |= NETIF_F_RXALL; dev->hw_features |= NETIF_F_RXFCS; + /* MTU range: 60 - hw-specific max */ + dev->min_mtu = ETH_ZLEN; + dev->max_mtu = rtl_chip_infos[chipset].jumbo_max; + tp->hw_start = cfg->hw_start; tp->event_slow = cfg->event_slow; -- cgit v1.2.3 From 540bfe30dc3f0b365c3a859eecad66ef468e167c Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:10 -0400 Subject: ethernet/sun: use core min/max MTU checking cassini: min_mtu 60, max_mtu 9000 niu: min_mtu 68, max_mtu 9216 sungem: min_mtu 68, max_mtu 1500 (comments say jumbo mode is broken) sunvnet: min_mtu 68, max_mtu 65535 - removed sunvnet_change_mut_common as it does nothing now CC: netdev@vger.kernel.org Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/cassini.c | 7 ++++--- drivers/net/ethernet/sun/ldmvsw.c | 5 ++++- drivers/net/ethernet/sun/niu.c | 7 ++++--- drivers/net/ethernet/sun/sungem.c | 11 ++++++----- drivers/net/ethernet/sun/sunvnet.c | 5 ++++- drivers/net/ethernet/sun/sunvnet_common.c | 10 ---------- drivers/net/ethernet/sun/sunvnet_common.h | 3 ++- 7 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index 062bce9acde6..e9e5ef241c6f 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -3863,9 +3863,6 @@ static int cas_change_mtu(struct net_device *dev, int new_mtu) { struct cas *cp = netdev_priv(dev); - if (new_mtu < CAS_MIN_MTU || new_mtu > CAS_MAX_MTU) - return -EINVAL; - dev->mtu = new_mtu; if (!netif_running(dev) || !netif_device_present(dev)) return 0; @@ -5115,6 +5112,10 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; + /* MTU range: 60 - varies or 9000 */ + dev->min_mtu = CAS_MIN_MTU; + dev->max_mtu = CAS_MAX_MTU; + if (register_netdev(dev)) { dev_err(&pdev->dev, "Cannot register net device, aborting\n"); goto err_out_free_consistent; diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c index 0ac449acaf5b..335b87660638 100644 --- a/drivers/net/ethernet/sun/ldmvsw.c +++ b/drivers/net/ethernet/sun/ldmvsw.c @@ -139,7 +139,6 @@ static const struct net_device_ops vsw_ops = { .ndo_set_mac_address = sunvnet_set_mac_addr_common, .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = sunvnet_tx_timeout_common, - .ndo_change_mtu = sunvnet_change_mtu_common, .ndo_start_xmit = vsw_start_xmit, .ndo_select_queue = vsw_select_queue, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -239,6 +238,10 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[], NETIF_F_HW_CSUM | NETIF_F_SG; dev->features = dev->hw_features; + /* MTU range: 68 - 65535 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = VNET_MAX_MTU; + SET_NETDEV_DEV(dev, &vdev->dev); return dev; diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index a2371aa14a49..f90d1af6d390 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -6754,9 +6754,6 @@ static int niu_change_mtu(struct net_device *dev, int new_mtu) struct niu *np = netdev_priv(dev); int err, orig_jumbo, new_jumbo; - if (new_mtu < 68 || new_mtu > NIU_MAX_MTU) - return -EINVAL; - orig_jumbo = (dev->mtu > ETH_DATA_LEN); new_jumbo = (new_mtu > ETH_DATA_LEN); @@ -9823,6 +9820,10 @@ static int niu_pci_init_one(struct pci_dev *pdev, dev->irq = pdev->irq; + /* MTU range: 68 - 9216 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = NIU_MAX_MTU; + niu_assign_netdev_ops(dev); err = niu_get_invariants(np); diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index d6ad0fbd054e..66ecf0fcc330 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -2476,9 +2476,9 @@ static void gem_set_multicast(struct net_device *dev) } /* Jumbo-grams don't seem to work :-( */ -#define GEM_MIN_MTU 68 +#define GEM_MIN_MTU ETH_MIN_MTU #if 1 -#define GEM_MAX_MTU 1500 +#define GEM_MAX_MTU ETH_DATA_LEN #else #define GEM_MAX_MTU 9000 #endif @@ -2487,9 +2487,6 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu) { struct gem *gp = netdev_priv(dev); - if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU) - return -EINVAL; - dev->mtu = new_mtu; /* We'll just catch it later when the device is up'd or resumed */ @@ -2977,6 +2974,10 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; + /* MTU range: 68 - 1500 (Jumbo mode is broken) */ + dev->min_mtu = GEM_MIN_MTU; + dev->max_mtu = GEM_MAX_MTU; + /* Register with kernel */ if (register_netdev(dev)) { pr_err("Cannot register net device, aborting\n"); diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index a2f9b47de187..5356a7074796 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -159,7 +159,6 @@ static const struct net_device_ops vnet_ops = { .ndo_set_mac_address = sunvnet_set_mac_addr_common, .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = sunvnet_tx_timeout_common, - .ndo_change_mtu = sunvnet_change_mtu_common, .ndo_start_xmit = vnet_start_xmit, .ndo_select_queue = vnet_select_queue, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -202,6 +201,10 @@ static struct vnet *vnet_new(const u64 *local_mac, NETIF_F_HW_CSUM | NETIF_F_SG; dev->features = dev->hw_features; + /* MTU range: 68 - 65535 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = VNET_MAX_MTU; + SET_NETDEV_DEV(dev, &vdev->dev); err = register_netdev(dev); diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index 904a5a12a85d..58efe69b7ba7 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -1583,16 +1583,6 @@ void sunvnet_set_rx_mode_common(struct net_device *dev, struct vnet *vp) } EXPORT_SYMBOL_GPL(sunvnet_set_rx_mode_common); -int sunvnet_change_mtu_common(struct net_device *dev, int new_mtu) -{ - if (new_mtu < 68 || new_mtu > 65535) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} -EXPORT_SYMBOL_GPL(sunvnet_change_mtu_common); - int sunvnet_set_mac_addr_common(struct net_device *dev, void *p) { return -EINVAL; diff --git a/drivers/net/ethernet/sun/sunvnet_common.h b/drivers/net/ethernet/sun/sunvnet_common.h index bd36528af972..ce5c824128a3 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.h +++ b/drivers/net/ethernet/sun/sunvnet_common.h @@ -15,6 +15,8 @@ #define VNET_MINTSO 2048 /* VIO protocol's minimum TSO len */ #define VNET_MAXTSO 65535 /* VIO protocol's maximum TSO len */ +#define VNET_MAX_MTU 65535 + /* VNET packets are sent in buffers with the first 6 bytes skipped * so that after the ethernet header the IPv4/IPv6 headers are aligned * properly. @@ -125,7 +127,6 @@ int sunvnet_close_common(struct net_device *dev); void sunvnet_set_rx_mode_common(struct net_device *dev, struct vnet *vp); int sunvnet_set_mac_addr_common(struct net_device *dev, void *p); void sunvnet_tx_timeout_common(struct net_device *dev); -int sunvnet_change_mtu_common(struct net_device *dev, int new_mtu); int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, struct vnet_port *(*vnet_tx_port) (struct sk_buff *, struct net_device *)); -- cgit v1.2.3 From f7ad72bfceb95e6607e0f0d7b7dbfb551865610a Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:11 -0400 Subject: ethernet/dlink: use core min/max MTU checking dl2k: min_mtu 68, max_mtu 1536 or 8000, depending on hardware - Removed change_mtu, does nothing productive anymore sundance: min_mtu 68, max_mtu 8191 CC: netdev@vger.kernel.org CC: Denis Kirjanov Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/dlink/dl2k.c | 22 ++++------------------ drivers/net/ethernet/dlink/sundance.c | 6 ++++-- 2 files changed, 8 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c index 78f144696d6b..8c95a8a81e3c 100644 --- a/drivers/net/ethernet/dlink/dl2k.c +++ b/drivers/net/ethernet/dlink/dl2k.c @@ -76,7 +76,6 @@ static void rio_free_tx (struct net_device *dev, int irq); static void tx_error (struct net_device *dev, int tx_status); static int receive_packet (struct net_device *dev); static void rio_error (struct net_device *dev, int int_status); -static int change_mtu (struct net_device *dev, int new_mtu); static void set_multicast (struct net_device *dev); static struct net_device_stats *get_stats (struct net_device *dev); static int clear_stats (struct net_device *dev); @@ -106,7 +105,6 @@ static const struct net_device_ops netdev_ops = { .ndo_set_rx_mode = set_multicast, .ndo_do_ioctl = rio_ioctl, .ndo_tx_timeout = rio_tx_timeout, - .ndo_change_mtu = change_mtu, }; static int @@ -230,6 +228,10 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) #if 0 dev->features = NETIF_F_IP_CSUM; #endif + /* MTU range: 68 - 1536 or 8000 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = np->jumbo ? MAX_JUMBO : PACKET_SIZE; + pci_set_drvdata (pdev, dev); ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma); @@ -1198,22 +1200,6 @@ clear_stats (struct net_device *dev) return 0; } - -static int -change_mtu (struct net_device *dev, int new_mtu) -{ - struct netdev_private *np = netdev_priv(dev); - int max = (np->jumbo) ? MAX_JUMBO : 1536; - - if ((new_mtu < 68) || (new_mtu > max)) { - return -EINVAL; - } - - dev->mtu = new_mtu; - - return 0; -} - static void set_multicast (struct net_device *dev) { diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index 79d80090eac8..eab36acfc0d1 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c @@ -580,6 +580,10 @@ static int sundance_probe1(struct pci_dev *pdev, dev->ethtool_ops = ðtool_ops; dev->watchdog_timeo = TX_TIMEOUT; + /* MTU range: 68 - 8191 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = 8191; + pci_set_drvdata(pdev, dev); i = register_netdev(dev); @@ -713,8 +717,6 @@ err_out_netdev: static int change_mtu(struct net_device *dev, int new_mtu) { - if ((new_mtu < 68) || (new_mtu > 8191)) /* Set by RxDMAFrameLen */ - return -EINVAL; if (netif_running(dev)) return -EBUSY; dev->mtu = new_mtu; -- cgit v1.2.3 From 18c310fb9583a9c69b0316b7907759017f2e152a Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:12 -0400 Subject: ethernet/neterion: use core min/max MTU checking s2io: min_mtu 46, max_mtu 9600 vxge: min_mtu 68, max_mtu 9600 CC: netdev@vger.kernel.org CC: Jon Mason Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/neterion/s2io.c | 9 ++++----- drivers/net/ethernet/neterion/vxge/vxge-config.h | 2 +- drivers/net/ethernet/neterion/vxge/vxge-main.c | 9 ++++----- 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index eaa37c079a7c..564f682fa4dc 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -6678,11 +6678,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) struct s2io_nic *sp = netdev_priv(dev); int ret = 0; - if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) { - DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", dev->name); - return -EPERM; - } - dev->mtu = new_mtu; if (netif_running(dev)) { s2io_stop_all_tx_queue(sp); @@ -8019,6 +8014,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET; } + /* MTU range: 46 - 9600 */ + dev->min_mtu = MIN_MTU; + dev->max_mtu = S2IO_JUMBO_SIZE; + /* store mac addresses from CAM to s2io_nic structure */ do_s2io_store_unicast_mc(sp); diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.h b/drivers/net/ethernet/neterion/vxge/vxge-config.h index 6ce4412fcc1a..cfa970417f81 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-config.h +++ b/drivers/net/ethernet/neterion/vxge/vxge-config.h @@ -27,7 +27,7 @@ (((size) - (((u64)adrs) & ((size)-1))) & ((size)-1)) #endif -#define VXGE_HW_MIN_MTU 68 +#define VXGE_HW_MIN_MTU ETH_MIN_MTU #define VXGE_HW_MAX_MTU 9600 #define VXGE_HW_DEFAULT_MTU 1500 diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index e0993eba5df3..e07b936f64ec 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -3074,11 +3074,6 @@ static int vxge_change_mtu(struct net_device *dev, int new_mtu) vxge_debug_entryexit(vdev->level_trace, "%s:%d", __func__, __LINE__); - if ((new_mtu < VXGE_HW_MIN_MTU) || (new_mtu > VXGE_HW_MAX_MTU)) { - vxge_debug_init(vdev->level_err, - "%s: mtu size is invalid", dev->name); - return -EPERM; - } /* check if device is down already */ if (unlikely(!is_vxge_card_up(vdev))) { @@ -3462,6 +3457,10 @@ static int vxge_device_register(struct __vxge_hw_device *hldev, "%s : using High DMA", __func__); } + /* MTU range: 68 - 9600 */ + ndev->min_mtu = VXGE_HW_MIN_MTU; + ndev->max_mtu = VXGE_HW_MAX_MTU; + ret = register_netdev(ndev); if (ret) { vxge_debug_init(vxge_hw_device_trace_level_get(hldev), -- cgit v1.2.3 From 109cc16526c6d5551f7735683f7985b2b0300bb5 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:13 -0400 Subject: ethernet/cavium: use core min/max MTU checking liquidio: min_mtu 68, max_mtu 16000 thunder: min_mtu 64, max_mtu 9200 CC: netdev@vger.kernel.org CC: Sunil Goutham CC: Robert Richter CC: Derek Chickles CC: Satanand Burla CC: Felix Manlunas CC: Raghu Vatsavayi Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/liquidio/lio_main.c | 15 ++++----------- drivers/net/ethernet/cavium/liquidio/octeon_network.h | 2 +- drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 13 +++---------- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 10 ++++------ 4 files changed, 12 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index afc6f9dc8119..71d01a77896d 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -2868,17 +2868,6 @@ static int liquidio_change_mtu(struct net_device *netdev, int new_mtu) struct octnic_ctrl_pkt nctrl; int ret = 0; - /* Limit the MTU to make sure the ethernet packets are between 68 bytes - * and 16000 bytes - */ - if ((new_mtu < LIO_MIN_MTU_SIZE) || - (new_mtu > LIO_MAX_MTU_SIZE)) { - dev_err(&oct->pci_dev->dev, "Invalid MTU: %d\n", new_mtu); - dev_err(&oct->pci_dev->dev, "Valid range %d and %d\n", - LIO_MIN_MTU_SIZE, LIO_MAX_MTU_SIZE); - return -EINVAL; - } - memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); nctrl.ncmd.u64 = 0; @@ -3891,6 +3880,10 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) netdev->hw_features = netdev->hw_features & ~NETIF_F_HW_VLAN_CTAG_RX; + /* MTU range: 68 - 16000 */ + netdev->min_mtu = LIO_MIN_MTU_SIZE; + netdev->max_mtu = LIO_MAX_MTU_SIZE; + /* Point to the properties for octeon device to which this * interface belongs. */ diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h b/drivers/net/ethernet/cavium/liquidio/octeon_network.h index e5d1debd05ad..54b966596323 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h @@ -29,7 +29,7 @@ #include #define LIO_MAX_MTU_SIZE (OCTNET_MAX_FRM_SIZE - OCTNET_FRM_HEADER_SIZE) -#define LIO_MIN_MTU_SIZE 68 +#define LIO_MIN_MTU_SIZE ETH_MIN_MTU struct oct_nic_stats_resp { u64 rh; diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c index 4ab404f45b21..16e12c45904b 100644 --- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c @@ -645,16 +645,6 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu) struct octeon_mgmt *p = netdev_priv(netdev); int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM; - /* Limit the MTU to make sure the ethernet packets are between - * 64 bytes and 16383 bytes. - */ - if (size_without_fcs < 64 || size_without_fcs > 16383) { - dev_warn(p->dev, "MTU must be between %d and %d.\n", - 64 - OCTEON_MGMT_RX_HEADROOM, - 16383 - OCTEON_MGMT_RX_HEADROOM); - return -EINVAL; - } - netdev->mtu = new_mtu; cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs); @@ -1491,6 +1481,9 @@ static int octeon_mgmt_probe(struct platform_device *pdev) netdev->netdev_ops = &octeon_mgmt_ops; netdev->ethtool_ops = &octeon_mgmt_ethtool_ops; + netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM; + netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM; + mac = of_get_mac_address(pdev->dev.of_node); if (mac) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 45a13f718863..b192712c93b7 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -1312,12 +1312,6 @@ static int nicvf_change_mtu(struct net_device *netdev, int new_mtu) { struct nicvf *nic = netdev_priv(netdev); - if (new_mtu > NIC_HW_MAX_FRS) - return -EINVAL; - - if (new_mtu < NIC_HW_MIN_FRS) - return -EINVAL; - if (nicvf_update_hw_max_frs(nic, new_mtu)) return -EINVAL; netdev->mtu = new_mtu; @@ -1630,6 +1624,10 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->netdev_ops = &nicvf_netdev_ops; netdev->watchdog_timeo = NICVF_TX_TIMEOUT; + /* MTU range: 64 - 9200 */ + netdev->min_mtu = NIC_HW_MIN_FRS; + netdev->max_mtu = NIC_HW_MAX_FRS; + INIT_WORK(&nic->reset_task, nicvf_reset_task); err = register_netdev(netdev); -- cgit v1.2.3 From 3d5d96acfeb9ddab99e0216109cbc034a65fd490 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:14 -0400 Subject: ethernet/ibm: use core min/max MTU checking ehea: min_mtu 68, max_mtu 9022 - remove ehea_change_mtu, it's now redundant emac: min_mtu 46, max_mtu 1500 or whatever gets read from OF CC: netdev@vger.kernel.org CC: Douglas Miller Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ehea/ehea_main.c | 13 ++++--------- drivers/net/ethernet/ibm/emac/core.c | 9 +++++---- 2 files changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 54efa9a5167b..e9719ba450d7 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -1981,14 +1981,6 @@ out: ehea_update_bcmc_registrations(); } -static int ehea_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > EHEA_MAX_PACKET_SIZE)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe) { swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC; @@ -2968,7 +2960,6 @@ static const struct net_device_ops ehea_netdev_ops = { .ndo_set_mac_address = ehea_set_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_set_rx_mode = ehea_set_multicast_list, - .ndo_change_mtu = ehea_change_mtu, .ndo_vlan_rx_add_vid = ehea_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = ehea_vlan_rx_kill_vid, .ndo_tx_timeout = ehea_tx_watchdog, @@ -3041,6 +3032,10 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, NETIF_F_IP_CSUM; dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT; + /* MTU range: 68 - 9022 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = EHEA_MAX_PACKET_SIZE; + INIT_WORK(&port->reset_task, ehea_reset_port); INIT_DELAYED_WORK(&port->stats_work, ehea_update_stats); diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 5d804a544674..52a69c925965 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -1099,9 +1099,6 @@ static int emac_change_mtu(struct net_device *ndev, int new_mtu) struct emac_instance *dev = netdev_priv(ndev); int ret = 0; - if (new_mtu < EMAC_MIN_MTU || new_mtu > dev->max_mtu) - return -EINVAL; - DBG(dev, "change_mtu(%d)" NL, new_mtu); if (netif_running(ndev)) { @@ -2564,7 +2561,7 @@ static int emac_init_config(struct emac_instance *dev) if (emac_read_uint_prop(np, "cell-index", &dev->cell_index, 1)) return -ENXIO; if (emac_read_uint_prop(np, "max-frame-size", &dev->max_mtu, 0)) - dev->max_mtu = 1500; + dev->max_mtu = ETH_DATA_LEN; if (emac_read_uint_prop(np, "rx-fifo-size", &dev->rx_fifo_size, 0)) dev->rx_fifo_size = 2048; if (emac_read_uint_prop(np, "tx-fifo-size", &dev->tx_fifo_size, 0)) @@ -2890,6 +2887,10 @@ static int emac_probe(struct platform_device *ofdev) ndev->netdev_ops = &emac_netdev_ops; ndev->ethtool_ops = &emac_ethtool_ops; + /* MTU range: 46 - 1500 or whatever is in OF */ + ndev->min_mtu = EMAC_MIN_MTU; + ndev->max_mtu = dev->max_mtu; + netif_carrier_off(ndev); err = register_netdev(ndev); -- cgit v1.2.3 From f58f0817d78a8418f1f33a30be09fcb34184cc94 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:15 -0400 Subject: ethernet/tile: use core min/max MTU checking tilegx: min_mtu 68, max_mtu 1500 or 9000, depending on modparam - remove tile_net_change_mtu now that it is fully redundant tilepro: min_mtu 68, max_mtu 1500 - hardware supports jumbo packets up to 10226, but it's not implemented or tested yet, according to code comments CC: netdev@vger.kernel.org CC: Chris Metcalf Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/tile/tilegx.c | 21 ++++++++------------- drivers/net/ethernet/tile/tilepro.c | 27 +++++---------------------- 2 files changed, 13 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 11213a38c795..0aaf975bb347 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -59,6 +59,9 @@ /* Maximum number of packets to handle per "poll". */ #define TILE_NET_WEIGHT 64 +/* Maximum Jumbo Packet MTU */ +#define TILE_JUMBO_MAX_MTU 9000 + /* Number of entries in each iqueue. */ #define IQUEUE_ENTRIES 512 @@ -2101,17 +2104,6 @@ static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return -EOPNOTSUPP; } -/* Change the MTU. */ -static int tile_net_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < 68) - return -EINVAL; - if (new_mtu > ((jumbo_num != 0) ? 9000 : 1500)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - /* Change the Ethernet address of the NIC. * * The hypervisor driver does not support changing MAC address. However, @@ -2154,7 +2146,6 @@ static const struct net_device_ops tile_net_ops = { .ndo_start_xmit = tile_net_tx, .ndo_select_queue = tile_net_select_queue, .ndo_do_ioctl = tile_net_ioctl, - .ndo_change_mtu = tile_net_change_mtu, .ndo_tx_timeout = tile_net_tx_timeout, .ndo_set_mac_address = tile_net_set_mac_address, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2174,7 +2165,11 @@ static void tile_net_setup(struct net_device *dev) ether_setup(dev); dev->netdev_ops = &tile_net_ops; dev->watchdog_timeo = TILE_NET_TIMEOUT; - dev->mtu = 1500; + + /* MTU range: 68 - 1500 or 9000 */ + dev->mtu = ETH_DATA_LEN; + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = jumbo_num ? TILE_JUMBO_MAX_MTU : ETH_DATA_LEN; features |= NETIF_F_HW_CSUM; features |= NETIF_F_SG; diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c index 4ef605a90247..0a3b7dafa3ba 100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c @@ -87,7 +87,7 @@ /* This should be 1500 if "jumbo" is not set in LIPP. */ /* This should be at most 10226 (10240 - 14) if "jumbo" is set in LIPP. */ /* ISSUE: This has not been thoroughly tested (except at 1500). */ -#define TILE_NET_MTU 1500 +#define TILE_NET_MTU ETH_DATA_LEN /* HACK: Define this to verify incoming packets. */ /* #define TILE_NET_VERIFY_INGRESS */ @@ -2095,26 +2095,6 @@ static struct rtnl_link_stats64 *tile_net_get_stats64(struct net_device *dev, } -/* - * Change the "mtu". - * - * The "change_mtu" method is usually not needed. - * If you need it, it must be like this. - */ -static int tile_net_change_mtu(struct net_device *dev, int new_mtu) -{ - PDEBUG("tile_net_change_mtu()\n"); - - /* Check ranges. */ - if ((new_mtu < 68) || (new_mtu > 1500)) - return -EINVAL; - - /* Accept the value. */ - dev->mtu = new_mtu; - - return 0; -} - /* * Change the Ethernet Address of the NIC. @@ -2229,7 +2209,6 @@ static const struct net_device_ops tile_net_ops = { .ndo_start_xmit = tile_net_tx, .ndo_do_ioctl = tile_net_ioctl, .ndo_get_stats64 = tile_net_get_stats64, - .ndo_change_mtu = tile_net_change_mtu, .ndo_tx_timeout = tile_net_tx_timeout, .ndo_set_mac_address = tile_net_set_mac_address, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2252,7 +2231,11 @@ static void tile_net_setup(struct net_device *dev) dev->netdev_ops = &tile_net_ops; dev->watchdog_timeo = TILE_NET_TIMEOUT; dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN; + + /* MTU range: 68 - 1500 */ dev->mtu = TILE_NET_MTU; + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = TILE_NET_MTU; features |= NETIF_F_HW_CSUM; features |= NETIF_F_SG; -- cgit v1.2.3 From 1281a2c7b814cf5ccdafa49c1410dd5092da0542 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:16 -0400 Subject: ethernet/toshiba: use core min/max MTU checking gelic_net: min_mtu 64, max_mtu 1518 - remove gelic_net_change_mtu now that it is redundant spidernet: min_Mtu 64, max_mtu 2294 - remove spiter_net_change_mtu now that it is redundant CC: netdev@vger.kernel.org CC: Geoff Levand CC: Ishizaki Kou Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/toshiba/ps3_gelic_net.c | 23 ++++------------------ drivers/net/ethernet/toshiba/ps3_gelic_net.h | 1 - drivers/net/ethernet/toshiba/ps3_gelic_wireless.c | 1 - drivers/net/ethernet/toshiba/spider_net.c | 24 ++++------------------- 4 files changed, 8 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c index 272f2b1cb7ad..345316c749e7 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c @@ -1114,24 +1114,6 @@ static int gelic_net_poll(struct napi_struct *napi, int budget) } return packets_done; } -/** - * gelic_net_change_mtu - changes the MTU of an interface - * @netdev: interface device structure - * @new_mtu: new MTU value - * - * returns 0 on success, <0 on failure - */ -int gelic_net_change_mtu(struct net_device *netdev, int new_mtu) -{ - /* no need to re-alloc skbs or so -- the max mtu is about 2.3k - * and mtu is outbound only anyway */ - if ((new_mtu < GELIC_NET_MIN_MTU) || - (new_mtu > GELIC_NET_MAX_MTU)) { - return -EINVAL; - } - netdev->mtu = new_mtu; - return 0; -} /** * gelic_card_interrupt - event handler for gelic_net @@ -1446,7 +1428,6 @@ static const struct net_device_ops gelic_netdevice_ops = { .ndo_stop = gelic_net_stop, .ndo_start_xmit = gelic_net_xmit, .ndo_set_rx_mode = gelic_net_set_multi, - .ndo_change_mtu = gelic_net_change_mtu, .ndo_tx_timeout = gelic_net_tx_timeout, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -1513,6 +1494,10 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card) netdev->features |= NETIF_F_VLAN_CHALLENGED; } + /* MTU range: 64 - 1518 */ + netdev->min_mtu = GELIC_NET_MIN_MTU; + netdev->max_mtu = GELIC_NET_MAX_MTU; + status = register_netdev(netdev); if (status) { dev_err(ctodev(card), "%s:Couldn't register %s %d\n", diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h index 8505196be9f5..003d0452d9cb 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.h +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h @@ -373,7 +373,6 @@ int gelic_net_stop(struct net_device *netdev); int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev); void gelic_net_set_multi(struct net_device *netdev); void gelic_net_tx_timeout(struct net_device *netdev); -int gelic_net_change_mtu(struct net_device *netdev, int new_mtu); int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card); /* shared ethtool ops */ diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c index 446ea580ad42..b3abd02dc949 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c @@ -2558,7 +2558,6 @@ static const struct net_device_ops gelic_wl_netdevice_ops = { .ndo_stop = gelic_wl_stop, .ndo_start_xmit = gelic_net_xmit, .ndo_set_rx_mode = gelic_net_set_multi, - .ndo_change_mtu = gelic_net_change_mtu, .ndo_tx_timeout = gelic_net_tx_timeout, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c index 36a6e8b54d94..cb341dfe65ad 100644 --- a/drivers/net/ethernet/toshiba/spider_net.c +++ b/drivers/net/ethernet/toshiba/spider_net.c @@ -1278,25 +1278,6 @@ static int spider_net_poll(struct napi_struct *napi, int budget) return packets_done; } -/** - * spider_net_change_mtu - changes the MTU of an interface - * @netdev: interface device structure - * @new_mtu: new MTU value - * - * returns 0 on success, <0 on failure - */ -static int -spider_net_change_mtu(struct net_device *netdev, int new_mtu) -{ - /* no need to re-alloc skbs or so -- the max mtu is about 2.3k - * and mtu is outbound only anyway */ - if ( (new_mtu < SPIDER_NET_MIN_MTU ) || - (new_mtu > SPIDER_NET_MAX_MTU) ) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - /** * spider_net_set_mac - sets the MAC of an interface * @netdev: interface device structure @@ -2229,7 +2210,6 @@ static const struct net_device_ops spider_net_ops = { .ndo_start_xmit = spider_net_xmit, .ndo_set_rx_mode = spider_net_set_multi, .ndo_set_mac_address = spider_net_set_mac, - .ndo_change_mtu = spider_net_change_mtu, .ndo_do_ioctl = spider_net_do_ioctl, .ndo_tx_timeout = spider_net_tx_timeout, .ndo_validate_addr = eth_validate_addr, @@ -2299,6 +2279,10 @@ spider_net_setup_netdev(struct spider_net_card *card) /* some time: NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | * NETIF_F_HW_VLAN_CTAG_FILTER */ + /* MTU range: 64 - 2294 */ + netdev->min_mtu = SPIDER_NET_MIN_MTU; + netdev->max_mtu = SPIDER_NET_MAX_MTU; + netdev->irq = card->pdev->irq; card->num_rx_ints = 0; card->ignore_rx_ramfull = 0; -- cgit v1.2.3 From 44770e1180decf9b483d9b537fdad385a4fbf462 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 17 Oct 2016 15:54:17 -0400 Subject: ethernet: use core min/max MTU checking et131x: min_mtu 64, max_mtu 9216 altera_tse: min_mtu 64, max_mtu 1500 amd8111e: min_mtu 60, max_mtu 9000 bnad: min_mtu 46, max_mtu 9000 macb: min_mtu 68, max_mtu 1500 or 10240 depending on hardware capability xgmac: min_mtu 46, max_mtu 9000 cxgb2: min_mtu 68, max_mtu 9582 (pm3393) or 9600 (vsc7326) enic: min_mtu 68, max_mtu 9000 gianfar: min_mtu 50, max_mu 9586 hns_enet: min_mtu 68, max_mtu 9578 (v1) or 9706 (v2) ksz884x: min_mtu 60, max_mtu 1894 myri10ge: min_mtu 68, max_mtu 9000 natsemi: min_mtu 64, max_mtu 2024 nfp: min_mtu 68, max_mtu hardware-specific forcedeth: min_mtu 64, max_mtu 1500 or 9100, depending on hardware pch_gbe: min_mtu 46, max_mtu 10300 pasemi_mac: min_mtu 64, max_mtu 9000 qcaspi: min_mtu 46, max_mtu 1500 - remove qcaspi_netdev_change_mtu as it is now redundant rocker: min_mtu 68, max_mtu 9000 sxgbe: min_mtu 68, max_mtu 9000 stmmac: min_mtu 46, max_mtu depends on hardware tehuti: min_mtu 60, max_mtu 16384 - driver had no max mtu checking, but product docs say 16k jumbo packets are supported by the hardware netcp: min_mtu 68, max_mtu 9486 - remove netcp_ndo_change_mtu as it is now redundant via-velocity: min_mtu 64, max_mtu 9000 octeon: min_mtu 46, max_mtu 65370 CC: netdev@vger.kernel.org CC: Mark Einon CC: Vince Bridgers CC: Rasesh Mody CC: Nicolas Ferre CC: Santosh Raspatur CC: Hariprasad S CC: Christian Benvenuti CC: Sujith Sankar CC: Govindarajulu Varadarajan <_govind@gmx.com> CC: Neel Patel CC: Claudiu Manoil CC: Yisen Zhuang CC: Salil Mehta CC: Hyong-Youb Kim CC: Jakub Kicinski CC: Olof Johansson CC: Jiri Pirko CC: Byungho An CC: Girish K S CC: Vipul Pandya CC: Giuseppe Cavallaro CC: Alexandre Torgue CC: Andy Gospodarek CC: Wingman Kwok CC: Murali Karicheri CC: Francois Romieu Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/agere/et131x.c | 7 +++-- drivers/net/ethernet/altera/altera_tse.h | 1 - drivers/net/ethernet/altera/altera_tse_main.c | 14 ++------- drivers/net/ethernet/amd/amd8111e.c | 5 ++-- drivers/net/ethernet/brocade/bna/bnad.c | 7 +++-- drivers/net/ethernet/cadence/macb.c | 19 ++++++------- drivers/net/ethernet/calxeda/xgmac.c | 20 ++++--------- drivers/net/ethernet/chelsio/cxgb/common.h | 5 ++++ drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 18 ++++++++++-- drivers/net/ethernet/chelsio/cxgb/pm3393.c | 8 +----- drivers/net/ethernet/chelsio/cxgb/vsc7326.c | 5 ---- drivers/net/ethernet/cisco/enic/enic_main.c | 7 +++-- drivers/net/ethernet/cisco/enic/enic_res.h | 2 +- drivers/net/ethernet/freescale/gianfar.c | 9 ++---- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 3 +- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 11 +++++--- drivers/net/ethernet/micrel/ksz884x.c | 33 +++++++++++----------- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 20 +++++++------ drivers/net/ethernet/natsemi/natsemi.c | 7 +++-- .../net/ethernet/netronome/nfp/nfp_net_common.c | 10 +++---- drivers/net/ethernet/nvidia/forcedeth.c | 9 +++--- .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 13 ++++----- drivers/net/ethernet/pasemi/pasemi_mac.c | 12 ++++---- drivers/net/ethernet/qualcomm/qca_framing.h | 6 ++-- drivers/net/ethernet/qualcomm/qca_spi.c | 16 +++-------- drivers/net/ethernet/rocker/rocker_main.c | 12 ++++---- drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 17 +++-------- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 25 ++++++---------- drivers/net/ethernet/tehuti/tehuti.c | 14 +++------ drivers/net/ethernet/tehuti/tehuti.h | 3 ++ drivers/net/ethernet/ti/netcp_core.c | 20 +++---------- drivers/net/ethernet/via/via-velocity.c | 11 +++----- drivers/staging/octeon/ethernet.c | 22 +++++++-------- 33 files changed, 169 insertions(+), 222 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c index 906683851c7d..831bab352f8e 100644 --- a/drivers/net/ethernet/agere/et131x.c +++ b/drivers/net/ethernet/agere/et131x.c @@ -176,6 +176,8 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere S #define NUM_FBRS 2 #define MAX_PACKETS_HANDLED 256 +#define ET131X_MIN_MTU 64 +#define ET131X_MAX_MTU 9216 #define ALCATEL_MULTICAST_PKT 0x01000000 #define ALCATEL_BROADCAST_PKT 0x02000000 @@ -3869,9 +3871,6 @@ static int et131x_change_mtu(struct net_device *netdev, int new_mtu) int result = 0; struct et131x_adapter *adapter = netdev_priv(netdev); - if (new_mtu < 64 || new_mtu > 9216) - return -EINVAL; - et131x_disable_txrx(netdev); netdev->mtu = new_mtu; @@ -3958,6 +3957,8 @@ static int et131x_pci_setup(struct pci_dev *pdev, netdev->watchdog_timeo = ET131X_TX_TIMEOUT; netdev->netdev_ops = &et131x_netdev_ops; + netdev->min_mtu = ET131X_MIN_MTU; + netdev->max_mtu = ET131X_MAX_MTU; SET_NETDEV_DEV(netdev, &pdev->dev); netdev->ethtool_ops = &et131x_ethtool_ops; diff --git a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h index e0052003d16f..9b640c8fbc28 100644 --- a/drivers/net/ethernet/altera/altera_tse.h +++ b/drivers/net/ethernet/altera/altera_tse.h @@ -443,7 +443,6 @@ struct altera_tse_private { /* RX/TX MAC FIFO configs */ u32 tx_fifo_depth; u32 rx_fifo_depth; - u32 max_mtu; /* Hash filter settings */ u32 hash_filter; diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index bda31f308cc2..cc9787e33acf 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -994,20 +994,11 @@ static void tse_set_mac(struct altera_tse_private *priv, bool enable) */ static int tse_change_mtu(struct net_device *dev, int new_mtu) { - struct altera_tse_private *priv = netdev_priv(dev); - unsigned int max_mtu = priv->max_mtu; - unsigned int min_mtu = ETH_ZLEN + ETH_FCS_LEN; - if (netif_running(dev)) { netdev_err(dev, "must be stopped to change its MTU\n"); return -EBUSY; } - if ((new_mtu < min_mtu) || (new_mtu > max_mtu)) { - netdev_err(dev, "invalid MTU, max MTU is: %u\n", max_mtu); - return -EINVAL; - } - dev->mtu = new_mtu; netdev_update_features(dev); @@ -1446,15 +1437,16 @@ static int altera_tse_probe(struct platform_device *pdev) of_property_read_bool(pdev->dev.of_node, "altr,has-supplementary-unicast"); + priv->dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN; /* Max MTU is 1500, ETH_DATA_LEN */ - priv->max_mtu = ETH_DATA_LEN; + priv->dev->max_mtu = ETH_DATA_LEN; /* Get the max mtu from the device tree. Note that the * "max-frame-size" parameter is actually max mtu. Definition * in the ePAPR v1.1 spec and usage differ, so go with usage. */ of_property_read_u32(pdev->dev.of_node, "max-frame-size", - &priv->max_mtu); + &priv->dev->max_mtu); /* The DMA buffer size already accounts for an alignment bias * to avoid unaligned access exceptions for the NIOS processor, diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index f92cc97151ec..84b4ffbd084a 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -1556,9 +1556,6 @@ static int amd8111e_change_mtu(struct net_device *dev, int new_mtu) struct amd8111e_priv *lp = netdev_priv(dev); int err; - if ((new_mtu < AMD8111E_MIN_MTU) || (new_mtu > AMD8111E_MAX_MTU)) - return -EINVAL; - if (!netif_running(dev)) { /* new_mtu will be used * when device starts netxt time @@ -1874,6 +1871,8 @@ static int amd8111e_probe_one(struct pci_dev *pdev, dev->ethtool_ops = &ops; dev->irq =pdev->irq; dev->watchdog_timeo = AMD8111E_TX_TIMEOUT; + dev->min_mtu = AMD8111E_MIN_MTU; + dev->max_mtu = AMD8111E_MAX_MTU; netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32); #if AMD8111E_VLAN_TAG_USED diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index f9df4b5ae90e..b200a783443e 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -3296,9 +3296,6 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu) struct bnad *bnad = netdev_priv(netdev); u32 rx_count = 0, frame, new_frame; - if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU) - return -EINVAL; - mutex_lock(&bnad->conf_mutex); mtu = netdev->mtu; @@ -3465,6 +3462,10 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac) netdev->mem_start = bnad->mmio_start; netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1; + /* MTU range: 46 - 9000 */ + netdev->min_mtu = ETH_ZLEN - ETH_HLEN; + netdev->max_mtu = BNAD_JUMBO_MTU; + netdev->netdev_ops = &bnad_netdev_ops; bnad_set_ethtool_ops(netdev); } diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 20e72044b765..e83781ad4477 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -56,7 +56,7 @@ #define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1)) #define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1)) -#define GEM_MTU_MIN_SIZE 68 +#define GEM_MTU_MIN_SIZE ETH_MIN_MTU #define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0) #define MACB_WOL_ENABLED (0x1 << 1) @@ -1986,19 +1986,9 @@ static int macb_close(struct net_device *dev) static int macb_change_mtu(struct net_device *dev, int new_mtu) { - struct macb *bp = netdev_priv(dev); - u32 max_mtu; - if (netif_running(dev)) return -EBUSY; - max_mtu = ETH_DATA_LEN; - if (bp->caps & MACB_CAPS_JUMBO) - max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN; - - if ((new_mtu > max_mtu) || (new_mtu < GEM_MTU_MIN_SIZE)) - return -EINVAL; - dev->mtu = new_mtu; return 0; @@ -3027,6 +3017,13 @@ static int macb_probe(struct platform_device *pdev) goto err_out_free_netdev; } + /* MTU range: 68 - 1500 or 10240 */ + dev->min_mtu = GEM_MTU_MIN_SIZE; + if (bp->caps & MACB_CAPS_JUMBO) + dev->max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN; + else + dev->max_mtu = ETH_DATA_LEN; + mac = of_get_mac_address(np); if (mac) ether_addr_copy(bp->dev->dev_addr, mac); diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 63efa0dc45ba..6e723662ee69 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -394,7 +394,7 @@ struct xgmac_priv { }; /* XGMAC Configuration Settings */ -#define MAX_MTU 9000 +#define XGMAC_MAX_MTU 9000 #define PAUSE_TIME 0x400 #define DMA_RX_RING_SZ 256 @@ -1360,20 +1360,6 @@ out: */ static int xgmac_change_mtu(struct net_device *dev, int new_mtu) { - struct xgmac_priv *priv = netdev_priv(dev); - int old_mtu; - - if ((new_mtu < 46) || (new_mtu > MAX_MTU)) { - netdev_err(priv->dev, "invalid MTU, max MTU is: %d\n", MAX_MTU); - return -EINVAL; - } - - old_mtu = dev->mtu; - - /* return early if the buffer sizes will not change */ - if (old_mtu == new_mtu) - return 0; - /* Stop everything, get ready to change the MTU */ if (!netif_running(dev)) return 0; @@ -1804,6 +1790,10 @@ static int xgmac_probe(struct platform_device *pdev) ndev->features |= ndev->hw_features; ndev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 46 - 9000 */ + ndev->min_mtu = ETH_ZLEN - ETH_HLEN; + ndev->max_mtu = XGMAC_MAX_MTU; + /* Get the MAC address */ xgmac_get_mac_addr(priv->base, ndev->dev_addr, 0); if (!is_valid_ether_addr(ndev->dev_addr)) diff --git a/drivers/net/ethernet/chelsio/cxgb/common.h b/drivers/net/ethernet/chelsio/cxgb/common.h index 53b1f9478383..6916c62f2487 100644 --- a/drivers/net/ethernet/chelsio/cxgb/common.h +++ b/drivers/net/ethernet/chelsio/cxgb/common.h @@ -85,6 +85,11 @@ struct t1_rx_mode { #define SPEED_INVALID 0xffff #define DUPLEX_INVALID 0xff +/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */ +#define PM3393_MAX_FRAME_SIZE 9600 + +#define VSC7326_MAX_MTU 9600 + enum { CHBT_BOARD_N110, CHBT_BOARD_N210, diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c index f5f1b0b51ebd..81d1d0bc7553 100644 --- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c +++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c @@ -825,8 +825,6 @@ static int t1_change_mtu(struct net_device *dev, int new_mtu) if (!mac->ops->set_mtu) return -EOPNOTSUPP; - if (new_mtu < 68) - return -EINVAL; if ((ret = mac->ops->set_mtu(mac, new_mtu))) return ret; dev->mtu = new_mtu; @@ -1101,6 +1099,22 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netif_napi_add(netdev, &adapter->napi, t1_poll, 64); netdev->ethtool_ops = &t1_ethtool_ops; + + switch (bi->board) { + case CHBT_BOARD_CHT110: + case CHBT_BOARD_N110: + case CHBT_BOARD_N210: + case CHBT_BOARD_CHT210: + netdev->max_mtu = PM3393_MAX_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN); + break; + case CHBT_BOARD_CHN204: + netdev->max_mtu = VSC7326_MAX_MTU; + break; + default: + netdev->max_mtu = ETH_DATA_LEN; + break; + } } if (t1_init_sw_modules(adapter, bi) < 0) { diff --git a/drivers/net/ethernet/chelsio/cxgb/pm3393.c b/drivers/net/ethernet/chelsio/cxgb/pm3393.c index eb462d7db427..c27908e66f5e 100644 --- a/drivers/net/ethernet/chelsio/cxgb/pm3393.c +++ b/drivers/net/ethernet/chelsio/cxgb/pm3393.c @@ -47,9 +47,6 @@ #define OFFSET(REG_ADDR) ((REG_ADDR) << 2) -/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */ -#define MAX_FRAME_SIZE 9600 - #define IPG 12 #define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \ SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \ @@ -331,10 +328,7 @@ static int pm3393_set_mtu(struct cmac *cmac, int mtu) { int enabled = cmac->instance->enabled; - /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */ - mtu += 14 + 4; - if (mtu > MAX_FRAME_SIZE) - return -EINVAL; + mtu += ETH_HLEN + ETH_FCS_LEN; /* Disable Rx/Tx MAC before configuring it. */ if (enabled) diff --git a/drivers/net/ethernet/chelsio/cxgb/vsc7326.c b/drivers/net/ethernet/chelsio/cxgb/vsc7326.c index 6f30b6f78553..bdc895bd2a46 100644 --- a/drivers/net/ethernet/chelsio/cxgb/vsc7326.c +++ b/drivers/net/ethernet/chelsio/cxgb/vsc7326.c @@ -11,8 +11,6 @@ /* 30 minutes for full statistics update */ #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS) -#define MAX_MTU 9600 - /* The egress WM value 0x01a01fff should be used only when the * interface is down (MAC port disabled). This is a workaround * for disabling the T2/MAC flow-control. When the interface is @@ -452,9 +450,6 @@ static int mac_set_mtu(struct cmac *mac, int mtu) { int port = mac->instance->index; - if (mtu > MAX_MTU) - return -EINVAL; - /* max_len includes header and FCS */ vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4); return 0; diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 48f82ab6c25b..f514faf8b709 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1843,9 +1843,6 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu) struct enic *enic = netdev_priv(netdev); int running = netif_running(netdev); - if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU) - return -EINVAL; - if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) return -EOPNOTSUPP; @@ -2751,6 +2748,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 68 - 9000 */ + netdev->min_mtu = ENIC_MIN_MTU; + netdev->max_mtu = ENIC_MAX_MTU; + err = register_netdev(netdev); if (err) { dev_err(dev, "Cannot register net device, aborting\n"); diff --git a/drivers/net/ethernet/cisco/enic/enic_res.h b/drivers/net/ethernet/cisco/enic/enic_res.h index 69f60afd6577..81f98a8b60e9 100644 --- a/drivers/net/ethernet/cisco/enic/enic_res.h +++ b/drivers/net/ethernet/cisco/enic/enic_res.h @@ -30,7 +30,7 @@ #define ENIC_MIN_RQ_DESCS 64 #define ENIC_MAX_RQ_DESCS 4096 -#define ENIC_MIN_MTU 68 +#define ENIC_MIN_MTU ETH_MIN_MTU #define ENIC_MAX_MTU 9000 #define ENIC_MULTICAST_PERFECT_FILTERS 32 diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 4b4f5bc0e279..409210413f5d 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1338,7 +1338,10 @@ static int gfar_probe(struct platform_device *ofdev) /* Fill in the dev structure */ dev->watchdog_timeo = TX_TIMEOUT; + /* MTU range: 50 - 9586 */ dev->mtu = 1500; + dev->min_mtu = 50; + dev->max_mtu = GFAR_JUMBO_FRAME_SIZE - ETH_HLEN; dev->netdev_ops = &gfar_netdev_ops; dev->ethtool_ops = &gfar_ethtool_ops; @@ -2592,12 +2595,6 @@ static int gfar_set_mac_address(struct net_device *dev) static int gfar_change_mtu(struct net_device *dev, int new_mtu) { struct gfar_private *priv = netdev_priv(dev); - int frame_size = new_mtu + ETH_HLEN; - - if ((frame_size < 64) || (frame_size > GFAR_JUMBO_FRAME_SIZE)) { - netif_err(priv, drv, dev, "Invalid MTU setting\n"); - return -EINVAL; - } while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state)) cpu_relax(); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 22e141005cd9..d8e99416ab24 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -446,8 +446,7 @@ int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu) if (mac_cb->mac_type == HNAE_PORT_DEBUG) max_frm = MAC_MAX_MTU_DBG; - if ((new_mtu < MAC_MIN_MTU) || (new_frm > max_frm) || - (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size)) + if (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size) return -EINVAL; if (!drv->config_max_frame_length) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 059aaeda46b1..a7208673116c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -22,6 +22,7 @@ #include "hnae.h" #include "hns_enet.h" +#include "hns_dsaf_mac.h" #define NIC_MAX_Q_PER_VF 16 #define HNS_NIC_TX_TIMEOUT (5 * HZ) @@ -1405,10 +1406,6 @@ static int hns_nic_change_mtu(struct net_device *ndev, int new_mtu) struct hnae_handle *h = priv->ae_handle; int ret; - /* MTU < 68 is an error and causes problems on some kernels */ - if (new_mtu < 68) - return -EINVAL; - if (!h->dev->ops->set_mtu) return -ENOTSUPP; @@ -1953,14 +1950,20 @@ static int hns_nic_dev_probe(struct platform_device *pdev) NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; ndev->vlan_features |= NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO; + /* MTU range: 68 - 9578 (v1) or 9706 (v2) */ + ndev->min_mtu = MAC_MIN_MTU; switch (priv->enet_ver) { case AE_VERSION_2: ndev->features |= NETIF_F_TSO | NETIF_F_TSO6; ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6; + ndev->max_mtu = MAC_MAX_MTU_V2 - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); break; default: + ndev->max_mtu = MAC_MAX_MTU - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); break; } diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 280e761d3a97..97f6ef1fa7d0 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -5807,24 +5807,19 @@ static int netdev_change_mtu(struct net_device *dev, int new_mtu) if (hw->dev_count > 1) if (dev != hw_priv->dev) return 0; - if (new_mtu < 60) - return -EINVAL; - if (dev->mtu != new_mtu) { - hw_mtu = new_mtu + ETHERNET_HEADER_SIZE + 4; - if (hw_mtu > MAX_RX_BUF_SIZE) - return -EINVAL; - if (hw_mtu > REGULAR_RX_BUF_SIZE) { - hw->features |= RX_HUGE_FRAME; - hw_mtu = MAX_RX_BUF_SIZE; - } else { - hw->features &= ~RX_HUGE_FRAME; - hw_mtu = REGULAR_RX_BUF_SIZE; - } - hw_mtu = (hw_mtu + 3) & ~3; - hw_priv->mtu = hw_mtu; - dev->mtu = new_mtu; + hw_mtu = new_mtu + ETHERNET_HEADER_SIZE + 4; + if (hw_mtu > REGULAR_RX_BUF_SIZE) { + hw->features |= RX_HUGE_FRAME; + hw_mtu = MAX_RX_BUF_SIZE; + } else { + hw->features &= ~RX_HUGE_FRAME; + hw_mtu = REGULAR_RX_BUF_SIZE; } + hw_mtu = (hw_mtu + 3) & ~3; + hw_priv->mtu = hw_mtu; + dev->mtu = new_mtu; + return 0; } @@ -7099,6 +7094,12 @@ static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id) dev->netdev_ops = &netdev_ops; dev->ethtool_ops = &netdev_ethtool_ops; + + /* MTU range: 60 - 1894 */ + dev->min_mtu = ETH_ZLEN; + dev->max_mtu = MAX_RX_BUF_SIZE - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); + if (register_netdev(dev)) goto pcidev_init_reg_err; port_set_power_saving(port, true); diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 6d1a956e3f77..5ae3f175cc23 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -3232,10 +3232,6 @@ static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) struct myri10ge_priv *mgp = netdev_priv(dev); int error = 0; - if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) { - netdev_err(dev, "new mtu (%d) is not valid\n", new_mtu); - return -EINVAL; - } netdev_info(dev, "changing mtu from %d to %d\n", dev->mtu, new_mtu); if (mgp->running) { /* if we change the mtu on an active device, we must @@ -4086,13 +4082,19 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) myri10ge_setup_dca(mgp); #endif pci_set_drvdata(pdev, mgp); - if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU) - myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; - if ((myri10ge_initial_mtu + ETH_HLEN) < 68) - myri10ge_initial_mtu = 68; - netdev->netdev_ops = &myri10ge_netdev_ops; + /* MTU range: 68 - 9000 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; + + if (myri10ge_initial_mtu > netdev->max_mtu) + myri10ge_initial_mtu = netdev->max_mtu; + if (myri10ge_initial_mtu < netdev->min_mtu) + myri10ge_initial_mtu = netdev->min_mtu; + netdev->mtu = myri10ge_initial_mtu; + + netdev->netdev_ops = &myri10ge_netdev_ops; netdev->hw_features = mgp->features | NETIF_F_RXCSUM; /* fake NETIF_F_HW_VLAN_CTAG_RX for good GRO performance */ diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index ed89029ff75b..22b0821c1da0 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c @@ -929,6 +929,10 @@ static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent) dev->ethtool_ops = ðtool_ops; + /* MTU range: 64 - 2024 */ + dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN; + dev->max_mtu = NATSEMI_RX_LIMIT - NATSEMI_HEADERS; + if (mtu) dev->mtu = mtu; @@ -2526,9 +2530,6 @@ static void __set_rx_mode(struct net_device *dev) static int natsemi_change_mtu(struct net_device *dev, int new_mtu) { - if (new_mtu < 64 || new_mtu > NATSEMI_RX_LIMIT-NATSEMI_HEADERS) - return -EINVAL; - dev->mtu = new_mtu; /* synchronized against open : rtnl_lock() held by caller */ diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index aee3fd2b6538..d365760fa75b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2278,11 +2278,6 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) struct nfp_net_rx_ring *tmp_rings; int err; - if (new_mtu < 68 || new_mtu > nn->max_mtu) { - nn_err(nn, "New MTU (%d) is not valid\n", new_mtu); - return -EINVAL; - } - old_mtu = netdev->mtu; old_fl_bufsz = nn->fl_bufsz; new_fl_bufsz = NFP_NET_MAX_PREPEND + ETH_HLEN + VLAN_HLEN * 2 + new_mtu; @@ -2930,6 +2925,11 @@ int nfp_net_netdev_init(struct net_device *netdev) ether_setup(netdev); netdev->netdev_ops = &nfp_net_netdev_ops; netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000); + + /* MTU range: 68 - hw-specific max */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = nn->max_mtu; + netif_carrier_off(netdev); nfp_net_set_ethtool_ops(netdev); diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 9b0d7f463ff3..3913f07279d2 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -3008,17 +3008,12 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) struct fe_priv *np = netdev_priv(dev); int old_mtu; - if (new_mtu < 64 || new_mtu > np->pkt_limit) - return -EINVAL; - old_mtu = dev->mtu; dev->mtu = new_mtu; /* return early if the buffer sizes will not change */ if (old_mtu <= ETH_DATA_LEN && new_mtu <= ETH_DATA_LEN) return 0; - if (old_mtu == new_mtu) - return 0; /* synchronized against open : rtnl_lock() held by caller */ if (netif_running(dev)) { @@ -5719,6 +5714,10 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) /* Add loopback capability to the device. */ dev->hw_features |= NETIF_F_LOOPBACK; + /* MTU range: 64 - 1500 or 9100 */ + dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN; + dev->max_mtu = np->pkt_limit; + np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG; if ((id->driver_data & DEV_HAS_PAUSEFRAME_TX_V1) || (id->driver_data & DEV_HAS_PAUSEFRAME_TX_V2) || diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 3cd87a41ac92..d461f419948e 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -2260,16 +2260,10 @@ static int pch_gbe_set_mac(struct net_device *netdev, void *addr) static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu) { struct pch_gbe_adapter *adapter = netdev_priv(netdev); - int max_frame; + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; unsigned long old_rx_buffer_len = adapter->rx_buffer_len; int err; - max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || - (max_frame > PCH_GBE_MAX_JUMBO_FRAME_SIZE)) { - netdev_err(netdev, "Invalid MTU setting\n"); - return -EINVAL; - } if (max_frame <= PCH_GBE_FRAME_SIZE_2048) adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_2048; else if (max_frame <= PCH_GBE_FRAME_SIZE_4096) @@ -2633,6 +2627,11 @@ static int pch_gbe_probe(struct pci_dev *pdev, netdev->features = netdev->hw_features; pch_gbe_set_ethtool_ops(netdev); + /* MTU range: 46 - 10300 */ + netdev->min_mtu = ETH_ZLEN - ETH_HLEN; + netdev->max_mtu = PCH_GBE_MAX_JUMBO_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN); + pch_gbe_mac_load_mac_addr(&adapter->hw); pch_gbe_mac_reset_hw(&adapter->hw); diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index 2f4a837f0d6a..badfa1d562a4 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -53,7 +53,7 @@ * - Multiqueue RX/TX */ -#define PE_MIN_MTU 64 +#define PE_MIN_MTU (ETH_ZLEN + ETH_HLEN) #define PE_MAX_MTU 9000 #define PE_DEF_MTU ETH_DATA_LEN @@ -1611,9 +1611,6 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) int running; int ret = 0; - if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU) - return -EINVAL; - running = netif_running(dev); if (running) { @@ -1635,7 +1632,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) } /* Setup checksum channels if large MTU and none already allocated */ - if (new_mtu > 1500 && !mac->num_cs) { + if (new_mtu > PE_DEF_MTU && !mac->num_cs) { pasemi_mac_setup_csrings(mac); if (!mac->num_cs) { ret = -ENOMEM; @@ -1757,6 +1754,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev->netdev_ops = &pasemi_netdev_ops; dev->mtu = PE_DEF_MTU; + + /* MTU range: 64 - 9000 */ + dev->min_mtu = PE_MIN_MTU; + dev->max_mtu = PE_MAX_MTU; + /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; diff --git a/drivers/net/ethernet/qualcomm/qca_framing.h b/drivers/net/ethernet/qualcomm/qca_framing.h index 5d965959c978..d5e795dcdf47 100644 --- a/drivers/net/ethernet/qualcomm/qca_framing.h +++ b/drivers/net/ethernet/qualcomm/qca_framing.h @@ -43,9 +43,9 @@ /* Frame length is invalid */ #define QCAFRM_INVFRAME (QCAFRM_ERR_BASE - 4) -/* Min/Max Ethernet MTU */ -#define QCAFRM_ETHMINMTU 46 -#define QCAFRM_ETHMAXMTU 1500 +/* Min/Max Ethernet MTU: 46/1500 */ +#define QCAFRM_ETHMINMTU (ETH_ZLEN - ETH_HLEN) +#define QCAFRM_ETHMAXMTU ETH_DATA_LEN /* Min/Max frame lengths */ #define QCAFRM_ETHMINLEN (QCAFRM_ETHMINMTU + ETH_HLEN) diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 6e2add979471..513e6c74e199 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -780,24 +780,12 @@ qcaspi_netdev_uninit(struct net_device *dev) dev_kfree_skb(qca->rx_skb); } -static int -qcaspi_netdev_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < QCAFRM_ETHMINMTU) || (new_mtu > QCAFRM_ETHMAXMTU)) - return -EINVAL; - - dev->mtu = new_mtu; - - return 0; -} - static const struct net_device_ops qcaspi_netdev_ops = { .ndo_init = qcaspi_netdev_init, .ndo_uninit = qcaspi_netdev_uninit, .ndo_open = qcaspi_netdev_open, .ndo_stop = qcaspi_netdev_close, .ndo_start_xmit = qcaspi_netdev_xmit, - .ndo_change_mtu = qcaspi_netdev_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_tx_timeout = qcaspi_netdev_tx_timeout, .ndo_validate_addr = eth_validate_addr, @@ -814,6 +802,10 @@ qcaspi_netdev_setup(struct net_device *dev) dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->tx_queue_len = 100; + /* MTU range: 46 - 1500 */ + dev->min_mtu = QCAFRM_ETHMINMTU; + dev->max_mtu = QCAFRM_ETHMAXMTU; + qca = netdev_priv(dev); memset(qca, 0, sizeof(struct qcaspi)); diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 5424fb341613..9b64f369076d 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -1953,12 +1953,6 @@ static int rocker_port_change_mtu(struct net_device *dev, int new_mtu) int running = netif_running(dev); int err; -#define ROCKER_PORT_MIN_MTU 68 -#define ROCKER_PORT_MAX_MTU 9000 - - if (new_mtu < ROCKER_PORT_MIN_MTU || new_mtu > ROCKER_PORT_MAX_MTU) - return -EINVAL; - if (running) rocker_port_stop(dev); @@ -2536,6 +2530,8 @@ static void rocker_port_dev_addr_init(struct rocker_port *rocker_port) } } +#define ROCKER_PORT_MIN_MTU ETH_MIN_MTU +#define ROCKER_PORT_MAX_MTU 9000 static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) { const struct pci_dev *pdev = rocker->pdev; @@ -2570,6 +2566,10 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_SG; + /* MTU range: 68 - 9000 */ + dev->min_mtu = ROCKER_PORT_MIN_MTU; + dev->max_mtu = ROCKER_PORT_MAX_MTU; + err = rocker_world_port_pre_init(rocker_port); if (err) { dev_err(&pdev->dev, "port world pre-init failed\n"); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index ea44a2456ce1..5dbe40640da6 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c @@ -1820,19 +1820,6 @@ static int sxgbe_set_features(struct net_device *dev, */ static int sxgbe_change_mtu(struct net_device *dev, int new_mtu) { - /* RFC 791, page 25, "Every internet module must be able to forward - * a datagram of 68 octets without further fragmentation." - */ - if (new_mtu < MIN_MTU || (new_mtu > MAX_MTU)) { - netdev_err(dev, "invalid MTU, MTU should be in between %d and %d\n", - MIN_MTU, MAX_MTU); - return -EINVAL; - } - - /* Return if the buffer sizes will not change */ - if (dev->mtu == new_mtu) - return 0; - dev->mtu = new_mtu; if (!netif_running(dev)) @@ -2144,6 +2131,10 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, /* assign filtering support */ ndev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 68 - 9000 */ + ndev->min_mtu = MIN_MTU; + ndev->max_mtu = MAX_MTU; + priv->msg_enable = netif_msg_init(debug, default_msg_level); /* Enable TCP segmentation offload for all DMA channels */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index da0b80a1917a..fa4a82f4656f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2715,27 +2715,11 @@ static void stmmac_set_rx_mode(struct net_device *dev) */ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) { - struct stmmac_priv *priv = netdev_priv(dev); - int max_mtu; - if (netif_running(dev)) { pr_err("%s: must be stopped to change its MTU\n", dev->name); return -EBUSY; } - if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00)) - max_mtu = JUMBO_LEN; - else - max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN); - - if (priv->plat->maxmtu < max_mtu) - max_mtu = priv->plat->maxmtu; - - if ((new_mtu < 46) || (new_mtu > max_mtu)) { - pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu); - return -EINVAL; - } - dev->mtu = new_mtu; netdev_update_features(dev); @@ -3317,6 +3301,15 @@ int stmmac_dvr_probe(struct device *device, #endif priv->msg_enable = netif_msg_init(debug, default_msg_level); + /* MTU range: 46 - hw-specific max */ + ndev->min_mtu = ETH_ZLEN - ETH_HLEN; + if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00)) + ndev->max_mtu = JUMBO_LEN; + else + ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN); + if (priv->plat->maxmtu < ndev->max_mtu) + ndev->max_mtu = priv->plat->maxmtu; + if (flow_ctrl) priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index 7108c68f16d3..baa3e4a5731c 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -761,16 +761,6 @@ static int bdx_change_mtu(struct net_device *ndev, int new_mtu) { ENTER; - if (new_mtu == ndev->mtu) - RET(0); - - /* enforce minimum frame size */ - if (new_mtu < ETH_ZLEN) { - netdev_err(ndev, "mtu %d is less then minimal %d\n", - new_mtu, ETH_ZLEN); - RET(-EINVAL); - } - ndev->mtu = new_mtu; if (netif_running(ndev)) { bdx_close(ndev); @@ -2057,6 +2047,10 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef BDX_LLTX ndev->features |= NETIF_F_LLTX; #endif + /* MTU range: 60 - 16384 */ + ndev->min_mtu = ETH_ZLEN; + ndev->max_mtu = BDX_MAX_MTU; + spin_lock_init(&priv->tx_lock); /*bdx_hw_reset(priv); */ diff --git a/drivers/net/ethernet/tehuti/tehuti.h b/drivers/net/ethernet/tehuti/tehuti.h index 709ebd6e28b4..8e7b4c9abf21 100644 --- a/drivers/net/ethernet/tehuti/tehuti.h +++ b/drivers/net/ethernet/tehuti/tehuti.h @@ -74,6 +74,9 @@ * ifcontig eth1 txqueuelen 3000 - to change it at runtime */ #define BDX_NDEV_TXQ_LEN 3000 +/* Max MTU for Jumbo Frame mode, per tehutinetworks.net Features FAQ is 16k */ +#define BDX_MAX_MTU (16 * 1024) + #define FIFO_SIZE 4096 #define FIFO_EXTRA_SPACE 1024 diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 32516661f180..11609d5467fc 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1766,21 +1766,6 @@ out: return (ret == 0) ? 0 : err; } -static int netcp_ndo_change_mtu(struct net_device *ndev, int new_mtu) -{ - struct netcp_intf *netcp = netdev_priv(ndev); - - /* MTU < 68 is an error for IPv4 traffic */ - if ((new_mtu < 68) || - (new_mtu > (NETCP_MAX_FRAME_SIZE - ETH_HLEN - ETH_FCS_LEN))) { - dev_err(netcp->ndev_dev, "Invalid mtu size = %d\n", new_mtu); - return -EINVAL; - } - - ndev->mtu = new_mtu; - return 0; -} - static void netcp_ndo_tx_timeout(struct net_device *ndev) { struct netcp_intf *netcp = netdev_priv(ndev); @@ -1886,7 +1871,6 @@ static const struct net_device_ops netcp_netdev_ops = { .ndo_start_xmit = netcp_ndo_start_xmit, .ndo_set_rx_mode = netcp_set_rx_mode, .ndo_do_ioctl = netcp_ndo_ioctl, - .ndo_change_mtu = netcp_ndo_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_vlan_rx_add_vid = netcp_rx_add_vid, @@ -1923,6 +1907,10 @@ static int netcp_create_interface(struct netcp_device *netcp_device, ndev->hw_features = ndev->features; ndev->vlan_features |= NETIF_F_SG; + /* MTU range: 68 - 9486 */ + ndev->min_mtu = ETH_MIN_MTU; + ndev->max_mtu = NETCP_MAX_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN); + netcp = netdev_priv(ndev); spin_lock_init(&netcp->lock); INIT_LIST_HEAD(&netcp->module_head); diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index 908e72e18ef7..4716e60e2ccb 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -2284,13 +2284,6 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) struct velocity_info *vptr = netdev_priv(dev); int ret = 0; - if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) { - VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n", - vptr->netdev->name); - ret = -EINVAL; - goto out_0; - } - if (!netif_running(dev)) { dev->mtu = new_mtu; goto out_0; @@ -2864,6 +2857,10 @@ static int velocity_probe(struct device *dev, int irq, NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_IP_CSUM; + /* MTU range: 64 - 9000 */ + netdev->min_mtu = VELOCITY_MIN_MTU; + netdev->max_mtu = VELOCITY_MAX_MTU; + ret = register_netdev(netdev); if (ret < 0) goto err_iounmap; diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index d02e3e31ed29..8130dfe89745 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -259,17 +259,6 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) #endif int mtu_overhead = ETH_HLEN + ETH_FCS_LEN + vlan_bytes; - /* - * Limit the MTU to make sure the ethernet packets are between - * 64 bytes and 65535 bytes. - */ - if ((new_mtu + mtu_overhead < VLAN_ETH_ZLEN) || - (new_mtu + mtu_overhead > OCTEON_MAX_MTU)) { - pr_err("MTU must be between %d and %d.\n", - VLAN_ETH_ZLEN - mtu_overhead, - OCTEON_MAX_MTU - mtu_overhead); - return -EINVAL; - } dev->mtu = new_mtu; if ((interface < 2) && @@ -457,7 +446,7 @@ int cvm_oct_common_init(struct net_device *dev) dev->ethtool_ops = &cvm_oct_ethtool_ops; cvm_oct_set_mac_filter(dev); - dev->netdev_ops->ndo_change_mtu(dev, dev->mtu); + dev_set_mtu(dev, dev->mtu); /* * Zero out stats for port so we won't mistakenly show @@ -685,6 +674,11 @@ static int cvm_oct_probe(struct platform_device *pdev) int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; int qos; struct device_node *pip; + int mtu_overhead = ETH_HLEN + ETH_FCS_LEN; + +#if IS_ENABLED(CONFIG_VLAN_8021Q) + mtu_overhead += VLAN_HLEN; +#endif octeon_mdiobus_force_mod_depencency(); @@ -783,6 +777,8 @@ static int cvm_oct_probe(struct platform_device *pdev) strcpy(dev->name, "pow%d"); for (qos = 0; qos < 16; qos++) skb_queue_head_init(&priv->tx_free_list[qos]); + dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead; + dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead; if (register_netdev(dev) < 0) { pr_err("Failed to register ethernet device for POW\n"); @@ -836,6 +832,8 @@ static int cvm_oct_probe(struct platform_device *pdev) for (qos = 0; qos < cvmx_pko_get_num_queues(port); qos++) cvmx_fau_atomic_write32(priv->fau + qos * 4, 0); + dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead; + dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead; switch (priv->imode) { /* These types don't support ports to IPD/PKO */ -- cgit v1.2.3 From b3208b2024c9089106df52ae25ebf39068d6f9fc Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 17 Oct 2016 19:15:45 -0700 Subject: net: bonding: Flip to the new dev walk API Convert alb_send_learning_packets and bond_has_this_ip to use the new netdev_walk_all_upper_dev_rcu API. In both cases this is just a code conversion; no functional change is intended. v2 - removed typecast of data and simplified bond_upper_dev_walk Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 82 ++++++++++++++++++++++++++--------------- drivers/net/bonding/bond_main.c | 17 +++++---- 2 files changed, 61 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 551f0f8dead3..c80b023092dd 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -950,13 +950,61 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], dev_queue_xmit(skb); } +struct alb_walk_data { + struct bonding *bond; + struct slave *slave; + u8 *mac_addr; + bool strict_match; +}; + +static int alb_upper_dev_walk(struct net_device *upper, void *_data) +{ + struct alb_walk_data *data = _data; + bool strict_match = data->strict_match; + struct bonding *bond = data->bond; + struct slave *slave = data->slave; + u8 *mac_addr = data->mac_addr; + struct bond_vlan_tag *tags; + + if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) { + if (strict_match && + ether_addr_equal_64bits(mac_addr, + upper->dev_addr)) { + alb_send_lp_vid(slave, mac_addr, + vlan_dev_vlan_proto(upper), + vlan_dev_vlan_id(upper)); + } else if (!strict_match) { + alb_send_lp_vid(slave, upper->dev_addr, + vlan_dev_vlan_proto(upper), + vlan_dev_vlan_id(upper)); + } + } + + /* If this is a macvlan device, then only send updates + * when strict_match is turned off. + */ + if (netif_is_macvlan(upper) && !strict_match) { + tags = bond_verify_device_path(bond->dev, upper, 0); + if (IS_ERR_OR_NULL(tags)) + BUG(); + alb_send_lp_vid(slave, upper->dev_addr, + tags[0].vlan_proto, tags[0].vlan_id); + kfree(tags); + } + + return 0; +} + static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], bool strict_match) { struct bonding *bond = bond_get_bond_by_slave(slave); - struct net_device *upper; - struct list_head *iter; - struct bond_vlan_tag *tags; + struct alb_walk_data data = { + .strict_match = strict_match, + .mac_addr = mac_addr, + .slave = slave, + .bond = bond, + }; /* send untagged */ alb_send_lp_vid(slave, mac_addr, 0, 0); @@ -965,33 +1013,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], * for that device. */ rcu_read_lock(); - netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { - if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) { - if (strict_match && - ether_addr_equal_64bits(mac_addr, - upper->dev_addr)) { - alb_send_lp_vid(slave, mac_addr, - vlan_dev_vlan_proto(upper), - vlan_dev_vlan_id(upper)); - } else if (!strict_match) { - alb_send_lp_vid(slave, upper->dev_addr, - vlan_dev_vlan_proto(upper), - vlan_dev_vlan_id(upper)); - } - } - - /* If this is a macvlan device, then only send updates - * when strict_match is turned off. - */ - if (netif_is_macvlan(upper) && !strict_match) { - tags = bond_verify_device_path(bond->dev, upper, 0); - if (IS_ERR_OR_NULL(tags)) - BUG(); - alb_send_lp_vid(slave, upper->dev_addr, - tags[0].vlan_proto, tags[0].vlan_id); - kfree(tags); - } - } + netdev_walk_all_upper_dev_rcu(bond->dev, alb_upper_dev_walk, &data); rcu_read_unlock(); } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5fa36ebc0640..c9944d86d045 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2270,22 +2270,23 @@ re_arm: } } +static int bond_upper_dev_walk(struct net_device *upper, void *data) +{ + __be32 ip = *((__be32 *)data); + + return ip == bond_confirm_addr(upper, 0, ip); +} + static bool bond_has_this_ip(struct bonding *bond, __be32 ip) { - struct net_device *upper; - struct list_head *iter; bool ret = false; if (ip == bond_confirm_addr(bond->dev, 0, ip)) return true; rcu_read_lock(); - netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { - if (ip == bond_confirm_addr(upper, 0, ip)) { - ret = true; - break; - } - } + if (netdev_walk_all_upper_dev_rcu(bond->dev, bond_upper_dev_walk, &ip)) + ret = true; rcu_read_unlock(); return ret; -- cgit v1.2.3 From 453d39329ad03f9f6d93ec6d0d57bf7a1e2a20c7 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 17 Oct 2016 19:15:46 -0700 Subject: IB/core: Flip to the new dev walk API Convert rdma_is_upper_dev_rcu, handle_netdev_upper and ipoib_get_net_dev_match_addr to the new upper device walk API. This is just a code conversion; no functional change is intended. v2 - removed typecast of data Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/infiniband/core/core_priv.h | 9 +------ drivers/infiniband/core/roce_gid_mgmt.c | 42 ++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index 19d499dcab76..0c0bea091de8 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -127,14 +127,7 @@ void ib_cache_release_one(struct ib_device *device); static inline bool rdma_is_upper_dev_rcu(struct net_device *dev, struct net_device *upper) { - struct net_device *_upper = NULL; - struct list_head *iter; - - netdev_for_each_all_upper_dev_rcu(dev, _upper, iter) - if (_upper == upper) - break; - - return _upper == upper; + return netdev_has_upper_dev_all_rcu(dev, upper); } int addr_init(void); diff --git a/drivers/infiniband/core/roce_gid_mgmt.c b/drivers/infiniband/core/roce_gid_mgmt.c index 06556c34606d..3a64a0881882 100644 --- a/drivers/infiniband/core/roce_gid_mgmt.c +++ b/drivers/infiniband/core/roce_gid_mgmt.c @@ -437,6 +437,28 @@ static void callback_for_addr_gid_device_scan(struct ib_device *device, &parsed->gid_attr); } +struct upper_list { + struct list_head list; + struct net_device *upper; +}; + +static int netdev_upper_walk(struct net_device *upper, void *data) +{ + struct upper_list *entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + struct list_head *upper_list = data; + + if (!entry) { + pr_info("roce_gid_mgmt: couldn't allocate entry to delete ndev\n"); + return 0; + } + + list_add_tail(&entry->list, upper_list); + dev_hold(upper); + entry->upper = upper; + + return 0; +} + static void handle_netdev_upper(struct ib_device *ib_dev, u8 port, void *cookie, void (*handle_netdev)(struct ib_device *ib_dev, @@ -444,30 +466,12 @@ static void handle_netdev_upper(struct ib_device *ib_dev, u8 port, struct net_device *ndev)) { struct net_device *ndev = (struct net_device *)cookie; - struct upper_list { - struct list_head list; - struct net_device *upper; - }; - struct net_device *upper; - struct list_head *iter; struct upper_list *upper_iter; struct upper_list *upper_temp; LIST_HEAD(upper_list); rcu_read_lock(); - netdev_for_each_all_upper_dev_rcu(ndev, upper, iter) { - struct upper_list *entry = kmalloc(sizeof(*entry), - GFP_ATOMIC); - - if (!entry) { - pr_info("roce_gid_mgmt: couldn't allocate entry to delete ndev\n"); - continue; - } - - list_add_tail(&entry->list, &upper_list); - dev_hold(upper); - entry->upper = upper; - } + netdev_walk_all_upper_dev_rcu(ndev, netdev_upper_walk, &upper_list); rcu_read_unlock(); handle_netdev(ib_dev, port, ndev); -- cgit v1.2.3 From e0e79c8e74b08976d9b45e52b704b9228c6965c7 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 17 Oct 2016 19:15:47 -0700 Subject: IB/ipoib: Flip to new dev walk API Convert ipoib_get_net_dev_match_addr to the new upper device walk API. This is just a code conversion; no functional change is intended. v2 - removed typecast of data Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 37 +++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 5636fc3da6b8..cc059218c962 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -292,6 +292,25 @@ static struct net_device *ipoib_get_master_net_dev(struct net_device *dev) return dev; } +struct ipoib_walk_data { + const struct sockaddr *addr; + struct net_device *result; +}; + +static int ipoib_upper_walk(struct net_device *upper, void *_data) +{ + struct ipoib_walk_data *data = _data; + int ret = 0; + + if (ipoib_is_dev_match_addr_rcu(data->addr, upper)) { + dev_hold(upper); + data->result = upper; + ret = 1; + } + + return ret; +} + /** * Find a net_device matching the given address, which is an upper device of * the given net_device. @@ -304,27 +323,21 @@ static struct net_device *ipoib_get_master_net_dev(struct net_device *dev) static struct net_device *ipoib_get_net_dev_match_addr( const struct sockaddr *addr, struct net_device *dev) { - struct net_device *upper, - *result = NULL; - struct list_head *iter; + struct ipoib_walk_data data = { + .addr = addr, + }; rcu_read_lock(); if (ipoib_is_dev_match_addr_rcu(addr, dev)) { dev_hold(dev); - result = dev; + data.result = dev; goto out; } - netdev_for_each_all_upper_dev_rcu(dev, upper, iter) { - if (ipoib_is_dev_match_addr_rcu(addr, upper)) { - dev_hold(upper); - result = upper; - break; - } - } + netdev_walk_all_upper_dev_rcu(dev, ipoib_upper_walk, &data); out: rcu_read_unlock(); - return result; + return data.result; } /* returns the number of IPoIB netdevs on top a given ipoib device matching a -- cgit v1.2.3 From 1cd127fc7d3a6d6a0fc9f9cca47ca3a16ee79679 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 17 Oct 2016 19:15:48 -0700 Subject: ixgbe: Flip to the new dev walk API Convert ixgbe users to new dev walk API. This is just a code conversion; no functional change is intended. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 132 ++++++++++++++++---------- 1 file changed, 82 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 7dfde209b0e0..cbd2cfa1b154 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -5012,24 +5012,23 @@ fwd_queue_err: return err; } -static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter) +static int ixgbe_upper_dev_walk(struct net_device *upper, void *data) { - struct net_device *upper; - struct list_head *iter; - int err; - - netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) { - if (netif_is_macvlan(upper)) { - struct macvlan_dev *dfwd = netdev_priv(upper); - struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv; + if (netif_is_macvlan(upper)) { + struct macvlan_dev *dfwd = netdev_priv(upper); + struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv; - if (dfwd->fwd_priv) { - err = ixgbe_fwd_ring_up(upper, vadapter); - if (err) - continue; - } - } + if (dfwd->fwd_priv) + ixgbe_fwd_ring_up(upper, vadapter); } + + return 0; +} + +static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter) +{ + netdev_walk_all_upper_dev_rcu(adapter->netdev, + ixgbe_upper_dev_walk, NULL); } static void ixgbe_configure(struct ixgbe_adapter *adapter) @@ -5448,12 +5447,25 @@ static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter) spin_unlock(&adapter->fdir_perfect_lock); } +static int ixgbe_disable_macvlan(struct net_device *upper, void *data) +{ + if (netif_is_macvlan(upper)) { + struct macvlan_dev *vlan = netdev_priv(upper); + + if (vlan->fwd_priv) { + netif_tx_stop_all_queues(upper); + netif_carrier_off(upper); + netif_tx_disable(upper); + } + } + + return 0; +} + void ixgbe_down(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; - struct net_device *upper; - struct list_head *iter; int i; /* signal that we are down to the interrupt handler */ @@ -5477,17 +5489,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_tx_disable(netdev); /* disable any upper devices */ - netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) { - if (netif_is_macvlan(upper)) { - struct macvlan_dev *vlan = netdev_priv(upper); - - if (vlan->fwd_priv) { - netif_tx_stop_all_queues(upper); - netif_carrier_off(upper); - netif_tx_disable(upper); - } - } - } + netdev_walk_all_upper_dev_rcu(adapter->netdev, + ixgbe_disable_macvlan, NULL); ixgbe_irq_disable(adapter); @@ -6723,6 +6726,18 @@ static void ixgbe_update_default_up(struct ixgbe_adapter *adapter) #endif } +static int ixgbe_enable_macvlan(struct net_device *upper, void *data) +{ + if (netif_is_macvlan(upper)) { + struct macvlan_dev *vlan = netdev_priv(upper); + + if (vlan->fwd_priv) + netif_tx_wake_all_queues(upper); + } + + return 0; +} + /** * ixgbe_watchdog_link_is_up - update netif_carrier status and * print link up message @@ -6732,8 +6747,6 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; - struct net_device *upper; - struct list_head *iter; u32 link_speed = adapter->link_speed; const char *speed_str; bool flow_rx, flow_tx; @@ -6804,14 +6817,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) /* enable any upper devices */ rtnl_lock(); - netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) { - if (netif_is_macvlan(upper)) { - struct macvlan_dev *vlan = netdev_priv(upper); - - if (vlan->fwd_priv) - netif_tx_wake_all_queues(upper); - } - } + netdev_walk_all_upper_dev_rcu(adapter->netdev, + ixgbe_enable_macvlan, NULL); rtnl_unlock(); /* update the default user priority for VFs */ @@ -8345,12 +8352,38 @@ static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter, } #ifdef CONFIG_NET_CLS_ACT +struct upper_walk_data { + struct ixgbe_adapter *adapter; + u64 action; + int ifindex; + u8 queue; +}; + +static int get_macvlan_queue(struct net_device *upper, void *_data) +{ + if (netif_is_macvlan(upper)) { + struct macvlan_dev *dfwd = netdev_priv(upper); + struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv; + struct upper_walk_data *data = _data; + struct ixgbe_adapter *adapter = data->adapter; + int ifindex = data->ifindex; + + if (vadapter && vadapter->netdev->ifindex == ifindex) { + data->queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx; + data->action = data->queue; + return 1; + } + } + + return 0; +} + static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex, u8 *queue, u64 *action) { unsigned int num_vfs = adapter->num_vfs, vf; + struct upper_walk_data data; struct net_device *upper; - struct list_head *iter; /* redirect to a SRIOV VF */ for (vf = 0; vf < num_vfs; ++vf) { @@ -8368,17 +8401,16 @@ static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex, } /* redirect to a offloaded macvlan netdev */ - netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) { - if (netif_is_macvlan(upper)) { - struct macvlan_dev *dfwd = netdev_priv(upper); - struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv; - - if (vadapter && vadapter->netdev->ifindex == ifindex) { - *queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx; - *action = *queue; - return 0; - } - } + data.adapter = adapter; + data.ifindex = ifindex; + data.action = 0; + data.queue = 0; + if (netdev_walk_all_upper_dev_rcu(adapter->netdev, + get_macvlan_queue, &data)) { + *action = data.action; + *queue = data.queue; + + return 0; } return -EINVAL; -- cgit v1.2.3 From dd82364c3ab93a96bb1e45d22106a4b1ea4bef39 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 17 Oct 2016 19:15:49 -0700 Subject: mlxsw: Flip to the new dev walk API Convert mlxsw users to new dev walk API. This is just a code conversion; no functional change is intended. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 37 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 43a5eddc2c11..99805fd3d110 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3092,19 +3092,30 @@ static bool mlxsw_sp_port_dev_check(const struct net_device *dev) return dev->netdev_ops == &mlxsw_sp_port_netdev_ops; } +static int mlxsw_lower_dev_walk(struct net_device *lower_dev, void *data) +{ + struct mlxsw_sp_port **port = data; + int ret = 0; + + if (mlxsw_sp_port_dev_check(lower_dev)) { + *port = netdev_priv(lower_dev); + ret = 1; + } + + return ret; +} + static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev) { - struct net_device *lower_dev; - struct list_head *iter; + struct mlxsw_sp_port *port; if (mlxsw_sp_port_dev_check(dev)) return netdev_priv(dev); - netdev_for_each_all_lower_dev(dev, lower_dev, iter) { - if (mlxsw_sp_port_dev_check(lower_dev)) - return netdev_priv(lower_dev); - } - return NULL; + port = NULL; + netdev_walk_all_lower_dev(dev, mlxsw_lower_dev_walk, &port); + + return port; } static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev) @@ -3117,17 +3128,15 @@ static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev) static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev) { - struct net_device *lower_dev; - struct list_head *iter; + struct mlxsw_sp_port *port; if (mlxsw_sp_port_dev_check(dev)) return netdev_priv(dev); - netdev_for_each_all_lower_dev_rcu(dev, lower_dev, iter) { - if (mlxsw_sp_port_dev_check(lower_dev)) - return netdev_priv(lower_dev); - } - return NULL; + port = NULL; + netdev_walk_all_lower_dev_rcu(dev, mlxsw_lower_dev_walk, &port); + + return port; } struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev) -- cgit v1.2.3 From cf2d67408b2f9a840f27d25a0219070b5b5deec4 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 17 Oct 2016 19:15:50 -0700 Subject: rocker: Flip to the new dev walk API Convert rocker to the new dev walk API. This is just a code conversion; no functional change is intended. v2 - removed typecast of data Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker_main.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 9b64f369076d..2e81b702a927 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2839,20 +2839,37 @@ static bool rocker_port_dev_check_under(const struct net_device *dev, return true; } +struct rocker_walk_data { + struct rocker *rocker; + struct rocker_port *port; +}; + +static int rocker_lower_dev_walk(struct net_device *lower_dev, void *_data) +{ + struct rocker_walk_data *data = _data; + int ret = 0; + + if (rocker_port_dev_check_under(lower_dev, data->rocker)) { + data->port = netdev_priv(lower_dev); + ret = 1; + } + + return ret; +} + struct rocker_port *rocker_port_dev_lower_find(struct net_device *dev, struct rocker *rocker) { - struct net_device *lower_dev; - struct list_head *iter; + struct rocker_walk_data data; if (rocker_port_dev_check_under(dev, rocker)) return netdev_priv(dev); - netdev_for_each_all_lower_dev(dev, lower_dev, iter) { - if (rocker_port_dev_check_under(lower_dev, rocker)) - return netdev_priv(lower_dev); - } - return NULL; + data.rocker = rocker; + data.port = NULL; + netdev_walk_all_lower_dev(dev, rocker_lower_dev_walk, &data); + + return data.port; } static int rocker_netdevice_event(struct notifier_block *unused, -- cgit v1.2.3 From 0e0f27dd65dd7403d41d72a8efafe388bbb36f84 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 17 Oct 2016 10:49:52 -0500 Subject: skge: Rename LED_OFF and LED_ON in marvel skge driver to avoid conflicts with leds namespace Adding led support for phy causes namespace conflicts for some phy drivers. The marvel skge driver declared an enum for representing the states of Link LED Register. The enum contained constant LED_OFF which conflicted with declartation found in linux/leds.h. LED_OFF changed to LED_REG_OFF Also changed LED_ON to LED_REG_ON to avoid possible future conflict and for consistency. Signed-off-by: Zach Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/skge.c | 6 +++--- drivers/net/ethernet/marvell/skge.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 9c4b722c3fdd..9146a514fb33 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -1048,7 +1048,7 @@ static const char *skge_pause(enum pause_status status) static void skge_link_up(struct skge_port *skge) { skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), - LED_BLK_OFF|LED_SYNC_OFF|LED_ON); + LED_BLK_OFF|LED_SYNC_OFF|LED_REG_ON); netif_carrier_on(skge->netdev); netif_wake_queue(skge->netdev); @@ -1062,7 +1062,7 @@ static void skge_link_up(struct skge_port *skge) static void skge_link_down(struct skge_port *skge) { - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); + skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_REG_OFF); netif_carrier_off(skge->netdev); netif_stop_queue(skge->netdev); @@ -2668,7 +2668,7 @@ static int skge_down(struct net_device *dev) if (hw->ports == 1) free_irq(hw->pdev->irq, hw); - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); + skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_REG_OFF); if (is_genesis(hw)) genesis_stop(skge); else diff --git a/drivers/net/ethernet/marvell/skge.h b/drivers/net/ethernet/marvell/skge.h index a2eb34115844..3ea151ff9c43 100644 --- a/drivers/net/ethernet/marvell/skge.h +++ b/drivers/net/ethernet/marvell/skge.h @@ -662,8 +662,8 @@ enum { LED_BLK_OFF = 1<<4, /* Link LED Blinking Off */ LED_SYNC_ON = 1<<3, /* Use Sync Wire to switch LED */ LED_SYNC_OFF = 1<<2, /* Disable Sync Wire Input */ - LED_ON = 1<<1, /* switch LED on */ - LED_OFF = 1<<0, /* switch LED off */ + LED_REG_ON = 1<<1, /* switch LED on */ + LED_REG_OFF = 1<<0, /* switch LED off */ }; /* Receive GMAC FIFO (YUKON) */ -- cgit v1.2.3 From 61a179657f1d00e45697de20067d5d7b3724eb91 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 17 Oct 2016 10:49:53 -0500 Subject: net: phy: Encapsulate actions performed during link state changes into function phy_adjust_link During phy state machine state transitions some set of actions should occur whenever the link state changes. These actions should be encapsulated into a single function This patch adds the phy_adjust_link function, which is called whenever phydev->adjust_link would have been called before. Actions that should occur whenever the phy link is adjusted can now be added to the phy_adjust_link function. Signed-off-by: Zach Brown Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 96bf03352bb8..8b7659e94057 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -908,6 +908,11 @@ void phy_start(struct phy_device *phydev) } EXPORT_SYMBOL(phy_start); +static void phy_adjust_link(struct phy_device *phydev) +{ + phydev->adjust_link(phydev->attached_dev); +} + /** * phy_state_machine - Handle the state machine * @work: work_struct that describes the work to be done @@ -950,7 +955,7 @@ void phy_state_machine(struct work_struct *work) if (!phydev->link) { phydev->state = PHY_NOLINK; netif_carrier_off(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); + phy_adjust_link(phydev); break; } @@ -963,7 +968,7 @@ void phy_state_machine(struct work_struct *work) if (err > 0) { phydev->state = PHY_RUNNING; netif_carrier_on(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); + phy_adjust_link(phydev); } else if (0 == phydev->link_timeout--) needs_aneg = true; @@ -990,7 +995,7 @@ void phy_state_machine(struct work_struct *work) } phydev->state = PHY_RUNNING; netif_carrier_on(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); + phy_adjust_link(phydev); } break; case PHY_FORCING: @@ -1006,7 +1011,7 @@ void phy_state_machine(struct work_struct *work) needs_aneg = true; } - phydev->adjust_link(phydev->attached_dev); + phy_adjust_link(phydev); break; case PHY_RUNNING: /* Only register a CHANGE if we are polling and link changed @@ -1035,7 +1040,7 @@ void phy_state_machine(struct work_struct *work) netif_carrier_off(phydev->attached_dev); } - phydev->adjust_link(phydev->attached_dev); + phy_adjust_link(phydev); if (phy_interrupt_is_valid(phydev)) err = phy_config_interrupt(phydev, @@ -1045,7 +1050,7 @@ void phy_state_machine(struct work_struct *work) if (phydev->link) { phydev->link = 0; netif_carrier_off(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); + phy_adjust_link(phydev); do_suspend = true; } break; @@ -1069,7 +1074,7 @@ void phy_state_machine(struct work_struct *work) } else { phydev->state = PHY_NOLINK; } - phydev->adjust_link(phydev->attached_dev); + phy_adjust_link(phydev); } else { phydev->state = PHY_AN; phydev->link_timeout = PHY_AN_TIMEOUT; @@ -1085,7 +1090,7 @@ void phy_state_machine(struct work_struct *work) } else { phydev->state = PHY_NOLINK; } - phydev->adjust_link(phydev->attached_dev); + phy_adjust_link(phydev); } break; } -- cgit v1.2.3 From 1f9127caece42514a47011326b83ad93d95cd5d7 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 17 Oct 2016 10:49:54 -0500 Subject: net: phy: Create phy_supported_speeds function which lists speeds currently supported by a phydevice phy_supported_speeds provides a means to get a list of all the speeds a phy device currently supports. Signed-off-by: Zach Brown Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/phy.h | 15 +++++++++++++++ 2 files changed, 50 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 8b7659e94057..ee3c793124c7 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -260,6 +260,41 @@ static inline unsigned int phy_find_valid(unsigned int idx, u32 features) return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1; } +/** + * phy_supported_speeds - return all speeds currently supported by a phy device + * @phy: The phy device to return supported speeds of. + * @speeds: buffer to store supported speeds in. + * @size: size of speeds buffer. + * + * Description: Returns the number of supported speeds, and fills the speeds + * buffer with the supported speeds. If speeds buffer is too small to contain + * all currently supported speeds, will return as many speeds as can fit. + */ +unsigned int phy_supported_speeds(struct phy_device *phy, + unsigned int *speeds, + unsigned int size) +{ + unsigned int count = 0; + unsigned int idx = 0; + + while (idx < MAX_NUM_SETTINGS && count < size) { + idx = phy_find_valid(idx, phy->supported); + + if (!(settings[idx].setting & phy->supported)) + break; + + /* Assumes settings are grouped by speed */ + if ((count == 0) || + (speeds[count - 1] != settings[idx].speed)) { + speeds[count] = settings[idx].speed; + count++; + } + idx++; + } + + return count; +} + /** * phy_check_valid - check if there is a valid PHY setting which matches * speed, duplex, and feature mask diff --git a/include/linux/phy.h b/include/linux/phy.h index c47378c93607..4b6c246c63bb 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -84,6 +84,21 @@ typedef enum { PHY_INTERFACE_MODE_MAX, } phy_interface_t; +/** + * phy_supported_speeds - return all speeds currently supported by a phy device + * @phy: The phy device to return supported speeds of. + * @speeds: buffer to store supported speeds in. + * @size: size of speeds buffer. + * + * Description: Returns the number of supported speeds, and + * fills the speeds * buffer with the supported speeds. If speeds buffer is + * too small to contain * all currently supported speeds, will return as + * many speeds as can fit. + */ +unsigned int phy_supported_speeds(struct phy_device *phy, + unsigned int *speeds, + unsigned int size); + /** * It maps 'enum phy_interface_t' found in include/linux/phy.h * into the device tree binding of 'phy-mode', so that Ethernet -- cgit v1.2.3 From 2e0bc452f4721520502575362a9cd3c1248d2337 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 17 Oct 2016 10:49:55 -0500 Subject: net: phy: leds: add support for led triggers on phy link state change Create an option CONFIG_LED_TRIGGER_PHY (default n), which will create a set of led triggers for each instantiated PHY device. There is one LED trigger per link-speed, per-phy. The triggers are registered during phy_attach and unregistered during phy_detach. This allows for a user to configure their system to allow a set of LEDs not controlled by the phy to represent link state changes on the phy. LEDS controlled by the phy are unaffected. For example, we have a board where some of the leds in the RJ45 socket are controlled by the phy, but others are not. Using the triggers provided by this patch the leds not controlled by the phy can be configured to show the current speed of the ethernet connection. The leds controlled by the phy are unaffected. Signed-off-by: Josh Cartwright Signed-off-by: Nathan Sullivan Signed-off-by: Zach Brown Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 13 ++++ drivers/net/phy/Makefile | 1 + drivers/net/phy/phy.c | 1 + drivers/net/phy/phy_device.c | 5 ++ drivers/net/phy/phy_led_triggers.c | 136 +++++++++++++++++++++++++++++++++++++ include/linux/phy.h | 7 ++ include/linux/phy_led_triggers.h | 51 ++++++++++++++ 7 files changed, 214 insertions(+) create mode 100644 drivers/net/phy/phy_led_triggers.c create mode 100644 include/linux/phy_led_triggers.h (limited to 'drivers') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 2651c8d8de2f..45f68eaf9b79 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -15,6 +15,19 @@ if PHYLIB config SWPHY bool +config LED_TRIGGER_PHY + bool "Support LED triggers for tracking link state" + depends on LEDS_TRIGGERS + ---help--- + Adds support for a set of LED trigger events per-PHY. Link + state change will trigger the events, for consumption by an + LED class driver. There are triggers for each link speed currently + supported by the phy, and are of the form: + :: + + Where speed is in the form: + Mbps or Gbps + comment "MDIO bus device drivers" config MDIO_BCM_IPROC diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index e58667d111e7..86d12cd3fbf0 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -2,6 +2,7 @@ libphy-y := phy.o phy_device.o mdio_bus.o mdio_device.o libphy-$(CONFIG_SWPHY) += swphy.o +libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_led_triggers.o obj-$(CONFIG_PHYLIB) += libphy.o diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index ee3c793124c7..2f94c60d4939 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -946,6 +946,7 @@ EXPORT_SYMBOL(phy_start); static void phy_adjust_link(struct phy_device *phydev) { phydev->adjust_link(phydev->attached_dev); + phy_led_trigger_change_speed(phydev); } /** diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index ac440a815353..49a1c988d29c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -916,6 +917,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, else phy_resume(phydev); + phy_led_triggers_register(phydev); + return err; error: @@ -989,6 +992,8 @@ void phy_detach(struct phy_device *phydev) } } + phy_led_triggers_unregister(phydev); + /* * The phydev might go away on the put_device() below, so avoid * a use-after-free bug by reading the underlying bus first. diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c new file mode 100644 index 000000000000..cda600a1b766 --- /dev/null +++ b/drivers/net/phy/phy_led_triggers.c @@ -0,0 +1,136 @@ +/* Copyright (C) 2016 National Instruments Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include + +static struct phy_led_trigger *phy_speed_to_led_trigger(struct phy_device *phy, + unsigned int speed) +{ + unsigned int i; + + for (i = 0; i < phy->phy_num_led_triggers; i++) { + if (phy->phy_led_triggers[i].speed == speed) + return &phy->phy_led_triggers[i]; + } + return NULL; +} + +void phy_led_trigger_change_speed(struct phy_device *phy) +{ + struct phy_led_trigger *plt; + + if (!phy->link) + goto out_change_speed; + + if (phy->speed == 0) + return; + + plt = phy_speed_to_led_trigger(phy, phy->speed); + if (!plt) { + netdev_alert(phy->attached_dev, + "No phy led trigger registered for speed(%d)\n", + phy->speed); + goto out_change_speed; + } + + if (plt != phy->last_triggered) { + led_trigger_event(&phy->last_triggered->trigger, LED_OFF); + led_trigger_event(&plt->trigger, LED_FULL); + phy->last_triggered = plt; + } + return; + +out_change_speed: + if (phy->last_triggered) { + led_trigger_event(&phy->last_triggered->trigger, + LED_OFF); + phy->last_triggered = NULL; + } +} +EXPORT_SYMBOL_GPL(phy_led_trigger_change_speed); + +static int phy_led_trigger_register(struct phy_device *phy, + struct phy_led_trigger *plt, + unsigned int speed) +{ + char name_suffix[PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE]; + + plt->speed = speed; + + if (speed < SPEED_1000) + snprintf(name_suffix, sizeof(name_suffix), "%dMbps", speed); + else if (speed == SPEED_2500) + snprintf(name_suffix, sizeof(name_suffix), "2.5Gbps"); + else + snprintf(name_suffix, sizeof(name_suffix), "%dGbps", + DIV_ROUND_CLOSEST(speed, 1000)); + + snprintf(plt->name, sizeof(plt->name), PHY_ID_FMT ":%s", + phy->mdio.bus->id, phy->mdio.addr, name_suffix); + plt->trigger.name = plt->name; + + return led_trigger_register(&plt->trigger); +} + +static void phy_led_trigger_unregister(struct phy_led_trigger *plt) +{ + led_trigger_unregister(&plt->trigger); +} + +int phy_led_triggers_register(struct phy_device *phy) +{ + int i, err; + unsigned int speeds[50]; + + phy->phy_num_led_triggers = phy_supported_speeds(phy, speeds, + ARRAY_SIZE(speeds)); + if (!phy->phy_num_led_triggers) + return 0; + + phy->phy_led_triggers = devm_kzalloc(&phy->mdio.dev, + sizeof(struct phy_led_trigger) * + phy->phy_num_led_triggers, + GFP_KERNEL); + if (!phy->phy_led_triggers) + return -ENOMEM; + + for (i = 0; i < phy->phy_num_led_triggers; i++) { + err = phy_led_trigger_register(phy, &phy->phy_led_triggers[i], + speeds[i]); + if (err) + goto out_unreg; + } + + phy->last_triggered = NULL; + phy_led_trigger_change_speed(phy); + + return 0; +out_unreg: + while (i--) + phy_led_trigger_unregister(&phy->phy_led_triggers[i]); + devm_kfree(&phy->mdio.dev, phy->phy_led_triggers); + return err; +} +EXPORT_SYMBOL_GPL(phy_led_triggers_register); + +void phy_led_triggers_unregister(struct phy_device *phy) +{ + int i; + + for (i = 0; i < phy->phy_num_led_triggers; i++) + phy_led_trigger_unregister(&phy->phy_led_triggers[i]); + + devm_kfree(&phy->mdio.dev, phy->phy_led_triggers); +} +EXPORT_SYMBOL_GPL(phy_led_triggers_unregister); diff --git a/include/linux/phy.h b/include/linux/phy.h index 4b6c246c63bb..e7e1fd382564 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -420,6 +421,12 @@ struct phy_device { int link_timeout; +#ifdef CONFIG_LED_TRIGGER_PHY + struct phy_led_trigger *phy_led_triggers; + unsigned int phy_num_led_triggers; + struct phy_led_trigger *last_triggered; +#endif + /* * Interrupt number for this PHY * -1 means no interrupt diff --git a/include/linux/phy_led_triggers.h b/include/linux/phy_led_triggers.h new file mode 100644 index 000000000000..a2daea0a37d2 --- /dev/null +++ b/include/linux/phy_led_triggers.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2016 National Instruments Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __PHY_LED_TRIGGERS +#define __PHY_LED_TRIGGERS + +struct phy_device; + +#ifdef CONFIG_LED_TRIGGER_PHY + +#include + +#define PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE 10 +#define PHY_MII_BUS_ID_SIZE (20 - 3) + +#define PHY_LINK_LED_TRIGGER_NAME_SIZE (PHY_MII_BUS_ID_SIZE + \ + FIELD_SIZEOF(struct mdio_device, addr)+\ + PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE) + +struct phy_led_trigger { + struct led_trigger trigger; + char name[PHY_LINK_LED_TRIGGER_NAME_SIZE]; + unsigned int speed; +}; + + +extern int phy_led_triggers_register(struct phy_device *phy); +extern void phy_led_triggers_unregister(struct phy_device *phy); +extern void phy_led_trigger_change_speed(struct phy_device *phy); + +#else + +static inline int phy_led_triggers_register(struct phy_device *phy) +{ + return 0; +} +static inline void phy_led_triggers_unregister(struct phy_device *phy) { } +static inline void phy_led_trigger_change_speed(struct phy_device *phy) { } + +#endif + +#endif -- cgit v1.2.3 From cd94e519dc5d82e2b8a0c93ebf09152727af5150 Mon Sep 17 00:00:00 2001 From: Bert Kenward Date: Tue, 18 Oct 2016 17:47:45 +0100 Subject: ethernet/sfc: use core min/max MTU checking Fixes: 61e84623ace3 ("net: centralize net_device min/max MTU checking") Signed-off-by: Bert Kenward Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 3cf3557106c2..b626da6e80a5 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2263,18 +2263,6 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) rc = efx_check_disabled(efx); if (rc) return rc; - if (new_mtu > EFX_MAX_MTU) { - netif_err(efx, drv, efx->net_dev, - "Requested MTU of %d too big (max: %d)\n", - new_mtu, EFX_MAX_MTU); - return -EINVAL; - } - if (new_mtu < EFX_MIN_MTU) { - netif_err(efx, drv, efx->net_dev, - "Requested MTU of %d too small (min: %d)\n", - new_mtu, EFX_MIN_MTU); - return -EINVAL; - } netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); @@ -2478,6 +2466,8 @@ static int efx_register_netdev(struct efx_nic *efx) net_dev->priv_flags |= IFF_UNICAST_FLT; net_dev->ethtool_ops = &efx_ethtool_ops; net_dev->gso_max_segs = EFX_TSO_MAX_SEGS; + net_dev->min_mtu = EFX_MIN_MTU; + net_dev->max_mtu = EFX_MAX_MTU; rtnl_lock(); -- cgit v1.2.3 From d09d747ae4c25a89aa04c0881ea52e90a09bedfd Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 17 Oct 2016 21:45:30 +0200 Subject: net: smc91x: isolate u16 writes alignment workaround Writes to u16 has a special handling on 3 PXA platforms, where the hardware wiring forces these writes to be u32 aligned. This patch isolates this handling for PXA platforms as before, but enables this "workaround" to be set up dynamically, which will be the case in device-tree build types. This patch was tested on 2 PXA platforms : mainstone, which relies on the workaround, and lubbock, which doesn't. Signed-off-by: Robert Jarzmik Signed-off-by: David S. Miller --- arch/mn10300/unit-asb2303/include/unit/smc91111.h | 2 +- drivers/net/ethernet/smsc/smc91x.c | 3 +- drivers/net/ethernet/smsc/smc91x.h | 82 ++++++++++++----------- 3 files changed, 47 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/arch/mn10300/unit-asb2303/include/unit/smc91111.h b/arch/mn10300/unit-asb2303/include/unit/smc91111.h index dd456e9c513f..dd4e2946438e 100644 --- a/arch/mn10300/unit-asb2303/include/unit/smc91111.h +++ b/arch/mn10300/unit-asb2303/include/unit/smc91111.h @@ -30,7 +30,7 @@ #if SMC_CAN_USE_16BIT #define SMC_inw(a, r) inw((unsigned long) ((a) + (r))) -#define SMC_outw(v, a, r) outw(v, (unsigned long) ((a) + (r))) +#define SMC_outw(lp, v, a, r) outw(v, (unsigned long) ((a) + (r))) #define SMC_insw(a, r, p, l) insw((unsigned long) ((a) + (r)), (p), (l)) #define SMC_outsw(a, r, p, l) outsw((unsigned long) ((a) + (r)), (p), (l)) #endif diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 9b4780f87863..705d99b2d947 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -602,7 +602,8 @@ static void smc_hardware_send_pkt(unsigned long data) SMC_PUSH_DATA(lp, buf, len & ~1); /* Send final ctl word with the last byte if there is one */ - SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp)); + SMC_outw(lp, ((len & 1) ? (0x2000 | buf[len - 1]) : 0), ioaddr, + DATA_REG(lp)); /* * If THROTTLE_TX_PKTS is set, we stop the queue here. This will diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index ea8465467469..45e6b81a6a92 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -63,8 +63,6 @@ #if defined(CONFIG_ARM) -#include - /* Now the bus width is specified in the platform data * pretend here to support all I/O access types */ @@ -86,11 +84,11 @@ #define SMC_inl(a, r) readl((a) + (r)) #define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outw(v, a, r) \ +#define SMC_outw(lp, v, a, r) \ do { \ unsigned int __v = v, __smc_r = r; \ if (SMC_16BIT(lp)) \ - __SMC_outw(__v, a, __smc_r); \ + __SMC_outw(lp, __v, a, __smc_r); \ else if (SMC_8BIT(lp)) \ SMC_outw_b(__v, a, __smc_r); \ else \ @@ -107,10 +105,10 @@ #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_align4(u16 val, void __iomem *ioaddr, int reg, + bool use_align4_workaround) { - if ((machine_is_mainstone() || machine_is_stargate2() || - machine_is_pxa_idp()) && reg & 2) { + if (use_align4_workaround) { unsigned int v = val << 16; v |= readl(ioaddr + (reg & ~2)) & 0xffff; writel(v, ioaddr + (reg & ~2)); @@ -119,6 +117,12 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) } } +#define __SMC_outw(lp, v, a, r) \ + _SMC_outw_align4((v), (a), (r), \ + IS_BUILTIN(CONFIG_ARCH_PXA) && ((r) & 2) && \ + (lp)->cfg.pxa_u16_align4) + + #elif defined(CONFIG_SH_SH4202_MICRODEV) #define SMC_CAN_USE_8BIT 0 @@ -129,7 +133,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_inw(a, r) inw((a) + (r) - 0xa0000000) #define SMC_inl(a, r) inl((a) + (r) - 0xa0000000) #define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000) -#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000) +#define SMC_outw(lp, v, a, r) outw(v, (a) + (r) - 0xa0000000) #define SMC_outl(v, a, r) outl(v, (a) + (r) - 0xa0000000) #define SMC_insl(a, r, p, l) insl((a) + (r) - 0xa0000000, p, l) #define SMC_outsl(a, r, p, l) outsl((a) + (r) - 0xa0000000, p, l) @@ -147,7 +151,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_inb(a, r) inb(((u32)a) + (r)) #define SMC_inw(a, r) inw(((u32)a) + (r)) #define SMC_outb(v, a, r) outb(v, ((u32)a) + (r)) -#define SMC_outw(v, a, r) outw(v, ((u32)a) + (r)) +#define SMC_outw(lp, v, a, r) outw(v, ((u32)a) + (r)) #define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l) #define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l) @@ -175,7 +179,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_inw(a, r) readw((a) + (r)) #define SMC_inl(a, r) readl((a) + (r)) #define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outw(lp, v, a, r) writew(v, (a) + (r)) #define SMC_outl(v, a, r) writel(v, (a) + (r)) #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) @@ -207,7 +211,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) } #define SMC_inw(a, r) _swapw(readw((a) + (r))) -#define SMC_outw(v, a, r) writew(_swapw(v), (a) + (r)) +#define SMC_outw(lp, v, a, r) writew(_swapw(v), (a) + (r)) #define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l) #define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l) @@ -241,7 +245,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) #define SMC_inw(a, r) ioread16((a) + (r)) #define SMC_inl(a, r) ioread32((a) + (r)) #define SMC_outb(v, a, r) iowrite8(v, (a) + (r)) -#define SMC_outw(v, a, r) iowrite16(v, (a) + (r)) +#define SMC_outw(lp, v, a, r) iowrite16(v, (a) + (r)) #define SMC_outl(v, a, r) iowrite32(v, (a) + (r)) #define SMC_insw(a, r, p, l) ioread16_rep((a) + (r), p, l) #define SMC_outsw(a, r, p, l) iowrite16_rep((a) + (r), p, l) @@ -303,6 +307,8 @@ struct smc_local { /* the low address lines on some platforms aren't connected... */ int io_shift; + /* on some platforms a u16 write must be 4-bytes aligned */ + bool half_word_align4; struct smc91x_platdata cfg; }; @@ -457,7 +463,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma, #if ! SMC_CAN_USE_16BIT -#define SMC_outw(x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg) +#define SMC_outw(lp, 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() @@ -909,7 +915,7 @@ static const char * chip_ids[ 16 ] = { else if (SMC_8BIT(lp)) \ SMC_outb(x, ioaddr, PN_REG(lp)); \ else \ - SMC_outw(x, ioaddr, PN_REG(lp)); \ + SMC_outw(lp, x, ioaddr, PN_REG(lp)); \ } while (0) #define SMC_GET_AR(lp) \ @@ -937,7 +943,7 @@ static const char * chip_ids[ 16 ] = { int __mask; \ local_irq_save(__flags); \ __mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \ - SMC_outw(__mask | (x), ioaddr, INT_REG(lp)); \ + SMC_outw(lp, __mask | (x), ioaddr, INT_REG(lp)); \ local_irq_restore(__flags); \ } \ } while (0) @@ -951,7 +957,7 @@ static const char * chip_ids[ 16 ] = { if (SMC_8BIT(lp)) \ SMC_outb(x, ioaddr, IM_REG(lp)); \ else \ - SMC_outw((x) << 8, ioaddr, INT_REG(lp)); \ + SMC_outw(lp, (x) << 8, ioaddr, INT_REG(lp)); \ } while (0) #define SMC_CURRENT_BANK(lp) SMC_inw(ioaddr, BANK_SELECT) @@ -961,22 +967,22 @@ static const char * chip_ids[ 16 ] = { if (SMC_MUST_ALIGN_WRITE(lp)) \ SMC_outl((x)<<16, ioaddr, 12< Date: Mon, 17 Oct 2016 21:45:31 +0200 Subject: net: smc91x: take into account half-word workaround For device-tree builds, platforms such as mainstone, idp and stargate2 must have their u16 writes all aligned on 32 bit boundaries. This is already enabled in platform data builds, and this patch adds it to device-tree builds. Signed-off-by: Robert Jarzmik Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smc91x.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 705d99b2d947..65077c77082a 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -2326,6 +2326,8 @@ static int smc_drv_probe(struct platform_device *pdev) if (!device_property_read_u32(&pdev->dev, "reg-shift", &val)) lp->io_shift = val; + lp->cfg.pxa_u16_align4 = + device_property_read_bool(&pdev->dev, "pxa-u16-align4"); } #endif -- cgit v1.2.3 From d248cafc892e5d5a44a84553dada18fcc470bf27 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Tue, 18 Oct 2016 11:41:48 +0800 Subject: r8152: add new products of Lenovo Add the following four products of Lenovo and sort the order of the list. VID PID 0x17ef 0x3062 0x17ef 0x3069 0x17ef 0x720c 0x17ef 0x7214 Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 28 ++++++++++++++++++++++++++++ drivers/net/usb/r8152.c | 6 +++++- 2 files changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index c47ec0a04c8e..45e5e4332a28 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -687,6 +687,20 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* ThinkPad USB-C Dock (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + +/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM, @@ -694,6 +708,20 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + +/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2886946ca371..8d6e13c689e0 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -4411,8 +4411,12 @@ static struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)}, {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)}, - {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3069)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, {} }; -- cgit v1.2.3 From aa0938c6d77d84d9ab72c5674c9624dddc345095 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Oct 2016 15:53:37 +0000 Subject: net: dsa: mv88e6xxx: fix non static symbol warning Fixes the following sparse warning: drivers/net/dsa/mv88e6xxx/chip.c:2866:5: warning: symbol 'mv88e6xxx_g1_set_switch_mac' was not declared. Should it be static? Signed-off-by: Wei Yongjun Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index ac032977b16c..157360f25069 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2863,7 +2863,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) return mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, 0x0000); } -int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr) +static int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr) { int err; -- cgit v1.2.3 From 4251e7475d4b2ac0d9ad039439ad0650921b1d27 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Oct 2016 15:54:50 +0000 Subject: qed: Remove useless set memory to zero use memset() The memory return by kzalloc() has already be set to zero, so remove useless memset(0). Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_roce.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c index 76831a398bed..b11beb559981 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_roce.c +++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c @@ -2747,7 +2747,6 @@ static int qed_roce_ll2_start(struct qed_dev *cdev, DP_ERR(cdev, "qed roce ll2 start: failed memory allocation\n"); return -ENOMEM; } - memset(roce_ll2, 0, sizeof(*roce_ll2)); roce_ll2->handle = QED_LL2_UNUSED_HANDLE; roce_ll2->cbs = params->cbs; roce_ll2->cb_cookie = params->cb_cookie; -- cgit v1.2.3 From 0f57dc6ae1ff0c702450083176b657ba37c07363 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Mon, 17 Oct 2016 16:48:58 +0100 Subject: remoteproc: Keep local copy of firmware name Storage of the firmware name was inconsistent, either storing a pointer to a name stored with unknown ownership, or a variable length tacked onto the end of the struct proc allocated in rproc_alloc. In preparation for allowing the firmware of an already allocated struct rproc to be changed, instead always keep a locally maintained copy of the firmware name. Signed-off-by: Matt Redfearn Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 31 ++++++++++++++++--------------- include/linux/remoteproc.h | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index c6bfb3496684..ccc2a73e94dd 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1273,6 +1273,7 @@ static void rproc_type_release(struct device *dev) if (rproc->index >= 0) ida_simple_remove(&rproc_dev_index, rproc->index); + kfree(rproc->firmware); kfree(rproc); } @@ -1310,31 +1311,31 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, { struct rproc *rproc; char *p, *template = "rproc-%s-fw"; - int name_len = 0; + int name_len; if (!dev || !name || !ops) return NULL; - if (!firmware) + if (!firmware) { /* - * Make room for default firmware name (minus %s plus '\0'). * If the caller didn't pass in a firmware name then - * construct a default name. We're already glomming 'len' - * bytes onto the end of the struct rproc allocation, so do - * a few more for the default firmware name (but only if - * the caller doesn't pass one). + * construct a default name. */ name_len = strlen(name) + strlen(template) - 2 + 1; - - rproc = kzalloc(sizeof(*rproc) + len + name_len, GFP_KERNEL); - if (!rproc) - return NULL; - - if (!firmware) { - p = (char *)rproc + sizeof(struct rproc) + len; + p = kmalloc(name_len, GFP_KERNEL); + if (!p) + return NULL; snprintf(p, name_len, template, name); } else { - p = (char *)firmware; + p = kstrdup(firmware, GFP_KERNEL); + if (!p) + return NULL; + } + + rproc = kzalloc(sizeof(struct rproc) + len, GFP_KERNEL); + if (!rproc) { + kfree(p); + return NULL; } rproc->firmware = p; diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 930023b7c825..940e4cf2ac48 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -415,7 +415,7 @@ struct rproc { struct list_head node; struct iommu_domain *domain; const char *name; - const char *firmware; + char *firmware; void *priv; const struct rproc_ops *ops; struct device dev; -- cgit v1.2.3 From 3227c876fb9a50fd7169fe265f236acce9ac2d2f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 18 Oct 2016 18:24:19 -0300 Subject: remoteproc: qcom: q6v5_pil: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/remoteproc/qcom_q6v5_pil.ko | grep alias $ After this patch: $ modinfo drivers/remoteproc/qcom_q6v5_pil.ko | grep alias alias: of:N*T*Cqcom,q6v5-pilC* alias: of:N*T*Cqcom,q6v5-pil Signed-off-by: Javier Martinez Canillas Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 2e0caaaa766a..b08989b48df7 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -894,6 +894,7 @@ static const struct of_device_id q6v5_of_match[] = { { .compatible = "qcom,q6v5-pil", }, { }, }; +MODULE_DEVICE_TABLE(of, q6v5_of_match); static struct platform_driver q6v5_driver = { .probe = q6v5_probe, -- cgit v1.2.3 From 4958aabb0c499b6c86bc830b8a769455b847fa26 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 18 Oct 2016 18:24:20 -0300 Subject: remoteproc: qcom: wcnss: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/remoteproc/qcom_wcnss.ko | grep alias $ After this patch: $ modinfo drivers/remoteproc/qcom_wcnss.ko | grep alias alias: of:N*T*Cqcom,pronto-v2-pilC* alias: of:N*T*Cqcom,pronto-v2-pil alias: of:N*T*Cqcom,pronto-v1-pilC* alias: of:N*T*Cqcom,pronto-v1-pil alias: of:N*T*Cqcom,riva-pilC* alias: of:N*T*Cqcom,riva-pil Signed-off-by: Javier Martinez Canillas Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_wcnss.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index f5cedeaafba1..e5d9de94c1db 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -609,6 +609,7 @@ static const struct of_device_id wcnss_of_match[] = { { .compatible = "qcom,pronto-v2-pil", &pronto_v2_data }, { }, }; +MODULE_DEVICE_TABLE(of, wcnss_of_match); static struct platform_driver wcnss_driver = { .probe = wcnss_probe, -- cgit v1.2.3 From af148e458d0a175c41f41664cdb97e0d251b9e69 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 18 Oct 2016 18:24:21 -0300 Subject: remoteproc: qcom: wcnss_iris: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/remoteproc/qcom_wcnss_iris.ko | grep alias $ After this patch: $ modinfo drivers/remoteproc/qcom_wcnss_iris.ko | grep alias alias: of:N*T*Cqcom,wcn3680C* alias: of:N*T*Cqcom,wcn3680 alias: of:N*T*Cqcom,wcn3660C* alias: of:N*T*Cqcom,wcn3660 alias: of:N*T*Cqcom,wcn3620C* alias: of:N*T*Cqcom,wcn3620 Signed-off-by: Javier Martinez Canillas Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_wcnss_iris.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/remoteproc/qcom_wcnss_iris.c b/drivers/remoteproc/qcom_wcnss_iris.c index f0ca24a8dd0b..07ef653cfbdf 100644 --- a/drivers/remoteproc/qcom_wcnss_iris.c +++ b/drivers/remoteproc/qcom_wcnss_iris.c @@ -173,6 +173,7 @@ static const struct of_device_id iris_of_match[] = { { .compatible = "qcom,wcn3680", .data = &wcn3680_data }, {} }; +MODULE_DEVICE_TABLE(of, iris_of_match); static struct platform_driver wcnss_driver = { .probe = qcom_iris_probe, -- cgit v1.2.3 From 89d9475610771b5e5fe1879075f0fc9ba6e3755f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 15:40:34 +0900 Subject: sd: Implement support for ZBC devices Implement ZBC support functions to setup zoned disks, both host-managed and host-aware models. Only zoned disks that satisfy the following conditions are supported: 1) All zones are the same size, with the exception of an eventual last smaller runt zone. 2) For host-managed disks, reads are unrestricted (reads are not failed due to zone or write pointer alignement constraints). Zoned disks that do not satisfy these 2 conditions are setup with a capacity of 0 to prevent their use. The function sd_zbc_read_zones, called from sd_revalidate_disk, checks that the device satisfies the above two constraints. This function may also change the disk capacity previously set by sd_read_capacity for devices reporting only the capacity of conventional zones at the beginning of the LBA range (i.e. devices reporting rc_basis set to 0). The capacity message output was moved out of sd_read_capacity into a new function sd_print_capacity to include this eventual capacity change by sd_zbc_read_zones. This new function also includes a call to sd_zbc_print_zones to display the number of zones and zone size of the device. Signed-off-by: Hannes Reinecke [Damien: * Removed zone cache support * Removed mapping of discard to reset write pointer command * Modified sd_zbc_read_zones to include checks that the device satisfies the kernel constraints * Implemeted REPORT ZONES setup and post-processing based on code from Shaun Tancheff * Removed confusing use of 512B sector units in functions interface] Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Reviewed-by: Shaun Tancheff Tested-by: Shaun Tancheff Acked-by: Martin K. Petersen Signed-off-by: Jens Axboe --- drivers/scsi/Makefile | 1 + drivers/scsi/sd.c | 148 ++++++++--- drivers/scsi/sd.h | 70 +++++ drivers/scsi/sd_zbc.c | 642 ++++++++++++++++++++++++++++++++++++++++++++++ include/scsi/scsi_proto.h | 17 ++ 5 files changed, 843 insertions(+), 35 deletions(-) create mode 100644 drivers/scsi/sd_zbc.c (limited to 'drivers') diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 38d938d7fe67..1520596f54a6 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -173,6 +173,7 @@ hv_storvsc-y := storvsc_drv.o sd_mod-objs := sd.o sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o +sd_mod-$(CONFIG_BLK_DEV_ZONED) += sd_zbc.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 51e56296f465..b9618ffca829 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -93,6 +93,7 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR); MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); +MODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC); #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) #define SD_MINORS 16 @@ -163,7 +164,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr, static const char temp[] = "temporary "; int len; - if (sdp->type != TYPE_DISK) + if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) /* no cache control on RBC devices; theoretically they * can do it, but there's probably so many exceptions * it's not worth the risk */ @@ -262,7 +263,7 @@ allow_restart_store(struct device *dev, struct device_attribute *attr, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (sdp->type != TYPE_DISK) + if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) return -EINVAL; sdp->allow_restart = simple_strtoul(buf, NULL, 10); @@ -392,6 +393,11 @@ provisioning_mode_store(struct device *dev, struct device_attribute *attr, if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (sd_is_zoned(sdkp)) { + sd_config_discard(sdkp, SD_LBP_DISABLE); + return count; + } + if (sdp->type != TYPE_DISK) return -EINVAL; @@ -459,7 +465,7 @@ max_write_same_blocks_store(struct device *dev, struct device_attribute *attr, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (sdp->type != TYPE_DISK) + if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) return -EINVAL; err = kstrtoul(buf, 10, &max); @@ -844,6 +850,12 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd) BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size); + if (sd_is_zoned(sdkp)) { + ret = sd_zbc_setup_write_cmnd(cmd); + if (ret != BLKPREP_OK) + return ret; + } + sector >>= ilog2(sdp->sector_size) - 9; nr_sectors >>= ilog2(sdp->sector_size) - 9; @@ -901,19 +913,25 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) struct request *rq = SCpnt->request; struct scsi_device *sdp = SCpnt->device; struct gendisk *disk = rq->rq_disk; - struct scsi_disk *sdkp; + struct scsi_disk *sdkp = scsi_disk(disk); sector_t block = blk_rq_pos(rq); sector_t threshold; unsigned int this_count = blk_rq_sectors(rq); unsigned int dif, dix; + bool zoned_write = sd_is_zoned(sdkp) && rq_data_dir(rq) == WRITE; int ret; unsigned char protect; + if (zoned_write) { + ret = sd_zbc_setup_write_cmnd(SCpnt); + if (ret != BLKPREP_OK) + return ret; + } + ret = scsi_init_io(SCpnt); if (ret != BLKPREP_OK) goto out; SCpnt = rq->special; - sdkp = scsi_disk(disk); /* from here on until we're complete, any goto out * is used for a killable error condition */ @@ -1132,6 +1150,9 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) */ ret = BLKPREP_OK; out: + if (zoned_write && ret != BLKPREP_OK) + sd_zbc_cancel_write_cmnd(SCpnt); + return ret; } @@ -1149,6 +1170,10 @@ static int sd_init_command(struct scsi_cmnd *cmd) case REQ_OP_READ: case REQ_OP_WRITE: return sd_setup_read_write_cmnd(cmd); + case REQ_OP_ZONE_REPORT: + return sd_zbc_setup_report_cmnd(cmd); + case REQ_OP_ZONE_RESET: + return sd_zbc_setup_reset_cmnd(cmd); default: BUG(); } @@ -1780,7 +1805,10 @@ static int sd_done(struct scsi_cmnd *SCpnt) unsigned char op = SCpnt->cmnd[0]; unsigned char unmap = SCpnt->cmnd[1] & 8; - if (req_op(req) == REQ_OP_DISCARD || req_op(req) == REQ_OP_WRITE_SAME) { + switch (req_op(req)) { + case REQ_OP_DISCARD: + case REQ_OP_WRITE_SAME: + case REQ_OP_ZONE_RESET: if (!result) { good_bytes = blk_rq_bytes(req); scsi_set_resid(SCpnt, 0); @@ -1788,6 +1816,17 @@ static int sd_done(struct scsi_cmnd *SCpnt) good_bytes = 0; scsi_set_resid(SCpnt, blk_rq_bytes(req)); } + break; + case REQ_OP_ZONE_REPORT: + if (!result) { + good_bytes = scsi_bufflen(SCpnt) + - scsi_get_resid(SCpnt); + scsi_set_resid(SCpnt, 0); + } else { + good_bytes = 0; + scsi_set_resid(SCpnt, blk_rq_bytes(req)); + } + break; } if (result) { @@ -1848,7 +1887,11 @@ static int sd_done(struct scsi_cmnd *SCpnt) default: break; } + out: + if (sd_is_zoned(sdkp)) + sd_zbc_complete(SCpnt, good_bytes, &sshdr); + SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, "sd_done: completed %d of %d bytes\n", good_bytes, scsi_bufflen(SCpnt))); @@ -1983,7 +2026,6 @@ sd_spinup_disk(struct scsi_disk *sdkp) } } - /* * Determine whether disk supports Data Integrity Field. */ @@ -2133,6 +2175,9 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, /* Logical blocks per physical block exponent */ sdkp->physical_block_size = (1 << (buffer[13] & 0xf)) * sector_size; + /* RC basis */ + sdkp->rc_basis = (buffer[12] >> 4) & 0x3; + /* Lowest aligned logical block */ alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size; blk_queue_alignment_offset(sdp->request_queue, alignment); @@ -2242,7 +2287,6 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) { int sector_size; struct scsi_device *sdp = sdkp->device; - sector_t old_capacity = sdkp->capacity; if (sd_try_rc16_first(sdp)) { sector_size = read_capacity_16(sdkp, sdp, buffer); @@ -2323,35 +2367,44 @@ got_data: sector_size = 512; } blk_queue_logical_block_size(sdp->request_queue, sector_size); + blk_queue_physical_block_size(sdp->request_queue, + sdkp->physical_block_size); + sdkp->device->sector_size = sector_size; - { - char cap_str_2[10], cap_str_10[10]; + if (sdkp->capacity > 0xffffffff) + sdp->use_16_for_rw = 1; - string_get_size(sdkp->capacity, sector_size, - STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); - string_get_size(sdkp->capacity, sector_size, - STRING_UNITS_10, cap_str_10, - sizeof(cap_str_10)); +} - if (sdkp->first_scan || old_capacity != sdkp->capacity) { - sd_printk(KERN_NOTICE, sdkp, - "%llu %d-byte logical blocks: (%s/%s)\n", - (unsigned long long)sdkp->capacity, - sector_size, cap_str_10, cap_str_2); +/* + * Print disk capacity + */ +static void +sd_print_capacity(struct scsi_disk *sdkp, + sector_t old_capacity) +{ + int sector_size = sdkp->device->sector_size; + char cap_str_2[10], cap_str_10[10]; - if (sdkp->physical_block_size != sector_size) - sd_printk(KERN_NOTICE, sdkp, - "%u-byte physical blocks\n", - sdkp->physical_block_size); - } - } + string_get_size(sdkp->capacity, sector_size, + STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); + string_get_size(sdkp->capacity, sector_size, + STRING_UNITS_10, cap_str_10, + sizeof(cap_str_10)); - if (sdkp->capacity > 0xffffffff) - sdp->use_16_for_rw = 1; + if (sdkp->first_scan || old_capacity != sdkp->capacity) { + sd_printk(KERN_NOTICE, sdkp, + "%llu %d-byte logical blocks: (%s/%s)\n", + (unsigned long long)sdkp->capacity, + sector_size, cap_str_10, cap_str_2); - blk_queue_physical_block_size(sdp->request_queue, - sdkp->physical_block_size); - sdkp->device->sector_size = sector_size; + if (sdkp->physical_block_size != sector_size) + sd_printk(KERN_NOTICE, sdkp, + "%u-byte physical blocks\n", + sdkp->physical_block_size); + + sd_zbc_print_zones(sdkp); + } } /* called with buffer of length 512 */ @@ -2613,7 +2666,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) struct scsi_mode_data data; struct scsi_sense_hdr sshdr; - if (sdp->type != TYPE_DISK) + if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) return; if (sdkp->protection_type == 0) @@ -2720,6 +2773,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) */ static void sd_read_block_characteristics(struct scsi_disk *sdkp) { + struct request_queue *q = sdkp->disk->queue; unsigned char *buffer; u16 rot; const int vpd_len = 64; @@ -2734,10 +2788,21 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) rot = get_unaligned_be16(&buffer[4]); if (rot == 1) { - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sdkp->disk->queue); - queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, sdkp->disk->queue); + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); + queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q); } + sdkp->zoned = (buffer[8] >> 4) & 3; + if (sdkp->zoned == 1) + q->limits.zoned = BLK_ZONED_HA; + else if (sdkp->device->type == TYPE_ZBC) + q->limits.zoned = BLK_ZONED_HM; + else + q->limits.zoned = BLK_ZONED_NONE; + if (blk_queue_is_zoned(q) && sdkp->first_scan) + sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n", + q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware"); + out: kfree(buffer); } @@ -2809,6 +2874,7 @@ static int sd_revalidate_disk(struct gendisk *disk) struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; struct request_queue *q = sdkp->disk->queue; + sector_t old_capacity = sdkp->capacity; unsigned char *buffer; unsigned int dev_max, rw_max; @@ -2842,8 +2908,11 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_block_provisioning(sdkp); sd_read_block_limits(sdkp); sd_read_block_characteristics(sdkp); + sd_zbc_read_zones(sdkp, buffer); } + sd_print_capacity(sdkp, old_capacity); + sd_read_write_protect_flag(sdkp, buffer); sd_read_cache_type(sdkp, buffer); sd_read_app_tag_own(sdkp, buffer); @@ -3041,9 +3110,16 @@ static int sd_probe(struct device *dev) scsi_autopm_get_device(sdp); error = -ENODEV; - if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC) + if (sdp->type != TYPE_DISK && + sdp->type != TYPE_ZBC && + sdp->type != TYPE_MOD && + sdp->type != TYPE_RBC) goto out; +#ifndef CONFIG_BLK_DEV_ZONED + if (sdp->type == TYPE_ZBC) + goto out; +#endif SCSI_LOG_HLQUEUE(3, sdev_printk(KERN_INFO, sdp, "sd_probe\n")); @@ -3147,6 +3223,8 @@ static int sd_remove(struct device *dev) del_gendisk(sdkp->disk); sd_shutdown(dev); + sd_zbc_remove(sdkp); + blk_register_region(devt, SD_MINORS, NULL, sd_default_probe, NULL, NULL); diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index c8d986368da9..4dac35e96a75 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -64,6 +64,15 @@ struct scsi_disk { struct scsi_device *device; struct device dev; struct gendisk *disk; +#ifdef CONFIG_BLK_DEV_ZONED + unsigned int nr_zones; + unsigned int zone_blocks; + unsigned int zone_shift; + unsigned long *zones_wlock; + unsigned int zones_optimal_open; + unsigned int zones_optimal_nonseq; + unsigned int zones_max_open; +#endif atomic_t openers; sector_t capacity; /* size in logical blocks */ u32 max_xfer_blocks; @@ -94,6 +103,9 @@ struct scsi_disk { unsigned lbpvpd : 1; unsigned ws10 : 1; unsigned ws16 : 1; + unsigned rc_basis: 2; + unsigned zoned: 2; + unsigned urswrz : 1; }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) @@ -156,6 +168,11 @@ static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t b return blocks * sdev->sector_size; } +static inline sector_t sectors_to_logical(struct scsi_device *sdev, sector_t sector) +{ + return sector >> (ilog2(sdev->sector_size) - 9); +} + /* * Look up the DIX operation based on whether the command is read or * write and whether dix and dif are enabled. @@ -239,4 +256,57 @@ static inline void sd_dif_complete(struct scsi_cmnd *cmd, unsigned int a) #endif /* CONFIG_BLK_DEV_INTEGRITY */ +static inline int sd_is_zoned(struct scsi_disk *sdkp) +{ + return sdkp->zoned == 1 || sdkp->device->type == TYPE_ZBC; +} + +#ifdef CONFIG_BLK_DEV_ZONED + +extern int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer); +extern void sd_zbc_remove(struct scsi_disk *sdkp); +extern void sd_zbc_print_zones(struct scsi_disk *sdkp); +extern int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd); +extern void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd); +extern int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd); +extern int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd); +extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes, + struct scsi_sense_hdr *sshdr); + +#else /* CONFIG_BLK_DEV_ZONED */ + +static inline int sd_zbc_read_zones(struct scsi_disk *sdkp, + unsigned char *buf) +{ + return 0; +} + +static inline void sd_zbc_remove(struct scsi_disk *sdkp) {} + +static inline void sd_zbc_print_zones(struct scsi_disk *sdkp) {} + +static inline int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd) +{ + /* Let the drive fail requests */ + return BLKPREP_OK; +} + +static inline void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd) {} + +static inline int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd) +{ + return BLKPREP_INVALID; +} + +static inline int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd) +{ + return BLKPREP_INVALID; +} + +static inline void sd_zbc_complete(struct scsi_cmnd *cmd, + unsigned int good_bytes, + struct scsi_sense_hdr *sshdr) {} + +#endif /* CONFIG_BLK_DEV_ZONED */ + #endif /* _SCSI_DISK_H */ diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c new file mode 100644 index 000000000000..16d3fa62d8ac --- /dev/null +++ b/drivers/scsi/sd_zbc.c @@ -0,0 +1,642 @@ +/* + * SCSI Zoned Block commands + * + * Copyright (C) 2014-2015 SUSE Linux GmbH + * Written by: Hannes Reinecke + * Modified by: Damien Le Moal + * Modified by: Shaun Tancheff + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sd.h" +#include "scsi_priv.h" + +enum zbc_zone_type { + ZBC_ZONE_TYPE_CONV = 0x1, + ZBC_ZONE_TYPE_SEQWRITE_REQ, + ZBC_ZONE_TYPE_SEQWRITE_PREF, + ZBC_ZONE_TYPE_RESERVED, +}; + +enum zbc_zone_cond { + ZBC_ZONE_COND_NO_WP, + ZBC_ZONE_COND_EMPTY, + ZBC_ZONE_COND_IMP_OPEN, + ZBC_ZONE_COND_EXP_OPEN, + ZBC_ZONE_COND_CLOSED, + ZBC_ZONE_COND_READONLY = 0xd, + ZBC_ZONE_COND_FULL, + ZBC_ZONE_COND_OFFLINE, +}; + +/** + * Convert a zone descriptor to a zone struct. + */ +static void sd_zbc_parse_report(struct scsi_disk *sdkp, + u8 *buf, + struct blk_zone *zone) +{ + struct scsi_device *sdp = sdkp->device; + + memset(zone, 0, sizeof(struct blk_zone)); + + zone->type = buf[0] & 0x0f; + zone->cond = (buf[1] >> 4) & 0xf; + if (buf[1] & 0x01) + zone->reset = 1; + if (buf[1] & 0x02) + zone->non_seq = 1; + + zone->len = logical_to_sectors(sdp, get_unaligned_be64(&buf[8])); + zone->start = logical_to_sectors(sdp, get_unaligned_be64(&buf[16])); + zone->wp = logical_to_sectors(sdp, get_unaligned_be64(&buf[24])); + if (zone->type != ZBC_ZONE_TYPE_CONV && + zone->cond == ZBC_ZONE_COND_FULL) + zone->wp = zone->start + zone->len; +} + +/** + * Issue a REPORT ZONES scsi command. + */ +static int sd_zbc_report_zones(struct scsi_disk *sdkp, unsigned char *buf, + unsigned int buflen, sector_t lba) +{ + struct scsi_device *sdp = sdkp->device; + const int timeout = sdp->request_queue->rq_timeout; + struct scsi_sense_hdr sshdr; + unsigned char cmd[16]; + unsigned int rep_len; + int result; + + memset(cmd, 0, 16); + cmd[0] = ZBC_IN; + cmd[1] = ZI_REPORT_ZONES; + put_unaligned_be64(lba, &cmd[2]); + put_unaligned_be32(buflen, &cmd[10]); + memset(buf, 0, buflen); + + result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, + buf, buflen, &sshdr, + timeout, SD_MAX_RETRIES, NULL); + if (result) { + sd_printk(KERN_ERR, sdkp, + "REPORT ZONES lba %llu failed with %d/%d\n", + (unsigned long long)lba, + host_byte(result), driver_byte(result)); + return -EIO; + } + + rep_len = get_unaligned_be32(&buf[0]); + if (rep_len < 64) { + sd_printk(KERN_ERR, sdkp, + "REPORT ZONES report invalid length %u\n", + rep_len); + return -EIO; + } + + return 0; +} + +int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd) +{ + struct request *rq = cmd->request; + struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); + sector_t lba, sector = blk_rq_pos(rq); + unsigned int nr_bytes = blk_rq_bytes(rq); + int ret; + + WARN_ON(nr_bytes == 0); + + if (!sd_is_zoned(sdkp)) + /* Not a zoned device */ + return BLKPREP_KILL; + + ret = scsi_init_io(cmd); + if (ret != BLKPREP_OK) + return ret; + + cmd->cmd_len = 16; + memset(cmd->cmnd, 0, cmd->cmd_len); + cmd->cmnd[0] = ZBC_IN; + cmd->cmnd[1] = ZI_REPORT_ZONES; + lba = sectors_to_logical(sdkp->device, sector); + put_unaligned_be64(lba, &cmd->cmnd[2]); + put_unaligned_be32(nr_bytes, &cmd->cmnd[10]); + /* Do partial report for speeding things up */ + cmd->cmnd[14] = ZBC_REPORT_ZONE_PARTIAL; + + cmd->sc_data_direction = DMA_FROM_DEVICE; + cmd->sdb.length = nr_bytes; + cmd->transfersize = sdkp->device->sector_size; + cmd->allowed = 0; + + /* + * Report may return less bytes than requested. Make sure + * to report completion on the entire initial request. + */ + rq->__data_len = nr_bytes; + + return BLKPREP_OK; +} + +static void sd_zbc_report_zones_complete(struct scsi_cmnd *scmd, + unsigned int good_bytes) +{ + struct request *rq = scmd->request; + struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); + struct sg_mapping_iter miter; + struct blk_zone_report_hdr hdr; + struct blk_zone zone; + unsigned int offset, bytes = 0; + unsigned long flags; + u8 *buf; + + if (good_bytes < 64) + return; + + memset(&hdr, 0, sizeof(struct blk_zone_report_hdr)); + + sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd), + SG_MITER_TO_SG | SG_MITER_ATOMIC); + + local_irq_save(flags); + while (sg_miter_next(&miter) && bytes < good_bytes) { + + buf = miter.addr; + offset = 0; + + if (bytes == 0) { + /* Set the report header */ + hdr.nr_zones = min_t(unsigned int, + (good_bytes - 64) / 64, + get_unaligned_be32(&buf[0]) / 64); + memcpy(buf, &hdr, sizeof(struct blk_zone_report_hdr)); + offset += 64; + bytes += 64; + } + + /* Parse zone descriptors */ + while (offset < miter.length && hdr.nr_zones) { + WARN_ON(offset > miter.length); + buf = miter.addr + offset; + sd_zbc_parse_report(sdkp, buf, &zone); + memcpy(buf, &zone, sizeof(struct blk_zone)); + offset += 64; + bytes += 64; + hdr.nr_zones--; + } + + if (!hdr.nr_zones) + break; + + } + sg_miter_stop(&miter); + local_irq_restore(flags); +} + +static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp) +{ + return logical_to_sectors(sdkp->device, sdkp->zone_blocks); +} + +static inline unsigned int sd_zbc_zone_no(struct scsi_disk *sdkp, + sector_t sector) +{ + return sectors_to_logical(sdkp->device, sector) >> sdkp->zone_shift; +} + +int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd) +{ + struct request *rq = cmd->request; + struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); + sector_t sector = blk_rq_pos(rq); + sector_t block = sectors_to_logical(sdkp->device, sector); + unsigned int zno = block >> sdkp->zone_shift; + + if (!sd_is_zoned(sdkp)) + /* Not a zoned device */ + return BLKPREP_KILL; + + if (sdkp->device->changed) + return BLKPREP_KILL; + + if (sector & (sd_zbc_zone_sectors(sdkp) - 1)) + /* Unaligned request */ + return BLKPREP_KILL; + + /* Do not allow concurrent reset and writes */ + if (sdkp->zones_wlock && + test_and_set_bit(zno, sdkp->zones_wlock)) + return BLKPREP_DEFER; + + cmd->cmd_len = 16; + memset(cmd->cmnd, 0, cmd->cmd_len); + cmd->cmnd[0] = ZBC_OUT; + cmd->cmnd[1] = ZO_RESET_WRITE_POINTER; + put_unaligned_be64(block, &cmd->cmnd[2]); + + rq->timeout = SD_TIMEOUT; + cmd->sc_data_direction = DMA_NONE; + cmd->transfersize = 0; + cmd->allowed = 0; + + return BLKPREP_OK; +} + +int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd) +{ + struct request *rq = cmd->request; + struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); + sector_t sector = blk_rq_pos(rq); + sector_t zone_sectors = sd_zbc_zone_sectors(sdkp); + unsigned int zno = sd_zbc_zone_no(sdkp, sector); + + /* + * Note: Checks of the alignment of the write command on + * logical blocks is done in sd.c + */ + + /* Do not allow zone boundaries crossing on host-managed drives */ + if (blk_queue_zoned_model(sdkp->disk->queue) == BLK_ZONED_HM && + (sector & (zone_sectors - 1)) + blk_rq_sectors(rq) > zone_sectors) + return BLKPREP_KILL; + + /* + * Do not issue more than one write at a time per + * zone. This solves write ordering problems due to + * the unlocking of the request queue in the dispatch + * path in the non scsi-mq case. For scsi-mq, this + * also avoids potential write reordering when multiple + * threads running on different CPUs write to the same + * zone (with a synchronized sequential pattern). + */ + if (sdkp->zones_wlock && + test_and_set_bit(zno, sdkp->zones_wlock)) + return BLKPREP_DEFER; + + return BLKPREP_OK; +} + +static void sd_zbc_unlock_zone(struct request *rq) +{ + struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); + + if (sdkp->zones_wlock) { + unsigned int zno = sd_zbc_zone_no(sdkp, blk_rq_pos(rq)); + WARN_ON_ONCE(!test_bit(zno, sdkp->zones_wlock)); + clear_bit_unlock(zno, sdkp->zones_wlock); + smp_mb__after_atomic(); + } +} + +void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd) +{ + sd_zbc_unlock_zone(cmd->request); +} + +void sd_zbc_complete(struct scsi_cmnd *cmd, + unsigned int good_bytes, + struct scsi_sense_hdr *sshdr) +{ + int result = cmd->result; + struct request *rq = cmd->request; + + switch (req_op(rq)) { + case REQ_OP_WRITE: + case REQ_OP_WRITE_SAME: + case REQ_OP_ZONE_RESET: + + /* Unlock the zone */ + sd_zbc_unlock_zone(rq); + + if (!result || + sshdr->sense_key != ILLEGAL_REQUEST) + break; + + switch (sshdr->asc) { + case 0x24: + /* + * INVALID FIELD IN CDB error: For a zone reset, + * this means that a reset of a conventional + * zone was attempted. Nothing to worry about in + * this case, so be quiet about the error. + */ + if (req_op(rq) == REQ_OP_ZONE_RESET) + rq->cmd_flags |= REQ_QUIET; + break; + case 0x21: + /* + * INVALID ADDRESS FOR WRITE error: It is unlikely that + * retrying write requests failed with any kind of + * alignement error will result in success. So don't. + */ + cmd->allowed = 0; + break; + } + + break; + + case REQ_OP_ZONE_REPORT: + + if (!result) + sd_zbc_report_zones_complete(cmd, good_bytes); + break; + + } +} + +/** + * Read zoned block device characteristics (VPD page B6). + */ +static int sd_zbc_read_zoned_characteristics(struct scsi_disk *sdkp, + unsigned char *buf) +{ + + if (scsi_get_vpd_page(sdkp->device, 0xb6, buf, 64)) { + sd_printk(KERN_NOTICE, sdkp, + "Unconstrained-read check failed\n"); + return -ENODEV; + } + + if (sdkp->device->type != TYPE_ZBC) { + /* Host-aware */ + sdkp->urswrz = 1; + sdkp->zones_optimal_open = get_unaligned_be64(&buf[8]); + sdkp->zones_optimal_nonseq = get_unaligned_be64(&buf[12]); + sdkp->zones_max_open = 0; + } else { + /* Host-managed */ + sdkp->urswrz = buf[4] & 1; + sdkp->zones_optimal_open = 0; + sdkp->zones_optimal_nonseq = 0; + sdkp->zones_max_open = get_unaligned_be64(&buf[16]); + } + + return 0; +} + +/** + * Check reported capacity. + */ +static int sd_zbc_check_capacity(struct scsi_disk *sdkp, + unsigned char *buf) +{ + sector_t lba; + int ret; + + if (sdkp->rc_basis != 0) + return 0; + + /* Do a report zone to get the maximum LBA to check capacity */ + ret = sd_zbc_report_zones(sdkp, buf, SD_BUF_SIZE, 0); + if (ret) + return ret; + + /* The max_lba field is the capacity of this device */ + lba = get_unaligned_be64(&buf[8]); + if (lba + 1 == sdkp->capacity) + return 0; + + if (sdkp->first_scan) + sd_printk(KERN_WARNING, sdkp, + "Changing capacity from %llu to max LBA+1 %llu\n", + (unsigned long long)sdkp->capacity, + (unsigned long long)lba + 1); + sdkp->capacity = lba + 1; + + return 0; +} + +#define SD_ZBC_BUF_SIZE 131072 + +static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) +{ + u64 zone_blocks; + sector_t block = 0; + unsigned char *buf; + unsigned char *rec; + unsigned int buf_len; + unsigned int list_length; + int ret; + u8 same; + + sdkp->zone_blocks = 0; + + /* Get a buffer */ + buf = kmalloc(SD_ZBC_BUF_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* Do a report zone to get the same field */ + ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0); + if (ret) + goto out; + + same = buf[4] & 0x0f; + if (same > 0) { + rec = &buf[64]; + zone_blocks = get_unaligned_be64(&rec[8]); + goto out; + } + + /* + * Check the size of all zones: all zones must be of + * equal size, except the last zone which can be smaller + * than other zones. + */ + do { + + /* Parse REPORT ZONES header */ + list_length = get_unaligned_be32(&buf[0]) + 64; + rec = buf + 64; + if (list_length < SD_ZBC_BUF_SIZE) + buf_len = list_length; + else + buf_len = SD_ZBC_BUF_SIZE; + + /* Parse zone descriptors */ + while (rec < buf + buf_len) { + zone_blocks = get_unaligned_be64(&rec[8]); + if (sdkp->zone_blocks == 0) { + sdkp->zone_blocks = zone_blocks; + } else if (zone_blocks != sdkp->zone_blocks && + (block + zone_blocks < sdkp->capacity + || zone_blocks > sdkp->zone_blocks)) { + zone_blocks = 0; + goto out; + } + block += zone_blocks; + rec += 64; + } + + if (block < sdkp->capacity) { + ret = sd_zbc_report_zones(sdkp, buf, + SD_ZBC_BUF_SIZE, block); + if (ret) + return ret; + } + + } while (block < sdkp->capacity); + + zone_blocks = sdkp->zone_blocks; + +out: + kfree(buf); + + if (!zone_blocks) { + if (sdkp->first_scan) + sd_printk(KERN_NOTICE, sdkp, + "Devices with non constant zone " + "size are not supported\n"); + return -ENODEV; + } + + if (!is_power_of_2(zone_blocks)) { + if (sdkp->first_scan) + sd_printk(KERN_NOTICE, sdkp, + "Devices with non power of 2 zone " + "size are not supported\n"); + return -ENODEV; + } + + if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) { + if (sdkp->first_scan) + sd_printk(KERN_NOTICE, sdkp, + "Zone size too large\n"); + return -ENODEV; + } + + sdkp->zone_blocks = zone_blocks; + + return 0; +} + +static int sd_zbc_setup(struct scsi_disk *sdkp) +{ + + /* chunk_sectors indicates the zone size */ + blk_queue_chunk_sectors(sdkp->disk->queue, + logical_to_sectors(sdkp->device, sdkp->zone_blocks)); + sdkp->zone_shift = ilog2(sdkp->zone_blocks); + sdkp->nr_zones = sdkp->capacity >> sdkp->zone_shift; + if (sdkp->capacity & (sdkp->zone_blocks - 1)) + sdkp->nr_zones++; + + if (!sdkp->zones_wlock) { + sdkp->zones_wlock = kcalloc(BITS_TO_LONGS(sdkp->nr_zones), + sizeof(unsigned long), + GFP_KERNEL); + if (!sdkp->zones_wlock) + return -ENOMEM; + } + + return 0; +} + +int sd_zbc_read_zones(struct scsi_disk *sdkp, + unsigned char *buf) +{ + sector_t capacity; + int ret = 0; + + if (!sd_is_zoned(sdkp)) + /* + * Device managed or normal SCSI disk, + * no special handling required + */ + return 0; + + + /* Get zoned block device characteristics */ + ret = sd_zbc_read_zoned_characteristics(sdkp, buf); + if (ret) + goto err; + + /* + * Check for unconstrained reads: host-managed devices with + * constrained reads (drives failing read after write pointer) + * are not supported. + */ + if (!sdkp->urswrz) { + if (sdkp->first_scan) + sd_printk(KERN_NOTICE, sdkp, + "constrained reads devices are not supported\n"); + ret = -ENODEV; + goto err; + } + + /* Check capacity */ + ret = sd_zbc_check_capacity(sdkp, buf); + if (ret) + goto err; + capacity = logical_to_sectors(sdkp->device, sdkp->capacity); + + /* + * Check zone size: only devices with a constant zone size (except + * an eventual last runt zone) that is a power of 2 are supported. + */ + ret = sd_zbc_check_zone_size(sdkp); + if (ret) + goto err; + + /* The drive satisfies the kernel restrictions: set it up */ + ret = sd_zbc_setup(sdkp); + if (ret) + goto err; + + return 0; + +err: + sdkp->capacity = 0; + + return ret; +} + +void sd_zbc_remove(struct scsi_disk *sdkp) +{ + kfree(sdkp->zones_wlock); + sdkp->zones_wlock = NULL; +} + +void sd_zbc_print_zones(struct scsi_disk *sdkp) +{ + if (!sd_is_zoned(sdkp) || !sdkp->capacity) + return; + + if (sdkp->capacity & (sdkp->zone_blocks - 1)) + sd_printk(KERN_NOTICE, sdkp, + "%u zones of %u logical blocks + 1 runt zone\n", + sdkp->nr_zones - 1, + sdkp->zone_blocks); + else + sd_printk(KERN_NOTICE, sdkp, + "%u zones of %u logical blocks\n", + sdkp->nr_zones, + sdkp->zone_blocks); +} diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h index d1defd1ebd95..6ba66e01f6df 100644 --- a/include/scsi/scsi_proto.h +++ b/include/scsi/scsi_proto.h @@ -299,4 +299,21 @@ struct scsi_lun { #define SCSI_ACCESS_STATE_MASK 0x0f #define SCSI_ACCESS_STATE_PREFERRED 0x80 +/* Reporting options for REPORT ZONES */ +enum zbc_zone_reporting_options { + ZBC_ZONE_REPORTING_OPTION_ALL = 0, + ZBC_ZONE_REPORTING_OPTION_EMPTY, + ZBC_ZONE_REPORTING_OPTION_IMPLICIT_OPEN, + ZBC_ZONE_REPORTING_OPTION_EXPLICIT_OPEN, + ZBC_ZONE_REPORTING_OPTION_CLOSED, + ZBC_ZONE_REPORTING_OPTION_FULL, + ZBC_ZONE_REPORTING_OPTION_READONLY, + ZBC_ZONE_REPORTING_OPTION_OFFLINE, + ZBC_ZONE_REPORTING_OPTION_NEED_RESET_WP = 0x10, + ZBC_ZONE_REPORTING_OPTION_NON_SEQWRITE, + ZBC_ZONE_REPORTING_OPTION_NON_WP = 0x3f, +}; + +#define ZBC_REPORT_ZONE_PARTIAL 0x80 + #endif /* _SCSI_PROTO_H_ */ -- cgit v1.2.3 From 32c52eff6a27798706487e042fae7bac6dd73576 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 1 Oct 2016 21:46:25 +0200 Subject: power: supply: improve function-level documentation In drivers/power/supply/ab8500_fg.c, fix two typos and adjust the function name in two cases to correspond to the names of the defined functions. In drivers/power/supply/power_supply_core.c, change two variable names to the names of the corresponding parameters. Issue detected using Coccinelle (http://coccinelle.lip6.fr/) Signed-off-by: Julia Lawall Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_fg.c | 8 ++++---- drivers/power/supply/power_supply_core.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 2199f673118c..c569f82a0071 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -1900,7 +1900,7 @@ static void ab8500_fg_low_bat_work(struct work_struct *work) * ab8500_fg_battok_calc - calculate the bit pattern corresponding * to the target voltage. * @di: pointer to the ab8500_fg structure - * @target target voltage + * @target: target voltage * * Returns bit pattern closest to the target voltage * valid return values are 0-14. (0-BATT_OK_MAX_NR_INCREMENTS) @@ -2391,7 +2391,7 @@ static void ab8500_fg_external_power_changed(struct power_supply *psy) } /** - * abab8500_fg_reinit_work() - work to reset the FG algorithm + * ab8500_fg_reinit_work() - work to reset the FG algorithm * @work: pointer to the work_struct structure * * Used to reset the current battery capacity to be able to @@ -2528,7 +2528,7 @@ static struct kobj_type ab8500_fg_ktype = { }; /** - * ab8500_chargalg_sysfs_exit() - de-init of sysfs entry + * ab8500_fg_sysfs_exit() - de-init of sysfs entry * @di: pointer to the struct ab8500_chargalg * * This function removes the entry in sysfs. @@ -2539,7 +2539,7 @@ static void ab8500_fg_sysfs_exit(struct ab8500_fg *di) } /** - * ab8500_chargalg_sysfs_init() - init of sysfs entry + * ab8500_fg_sysfs_init() - init of sysfs entry * @di: pointer to the struct ab8500_chargalg * * This function adds an entry in sysfs. diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index a74d8ca383a1..1e0960b646e8 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -413,7 +413,7 @@ static int power_supply_match_device_node(struct device *dev, const void *data) /** * power_supply_get_by_phandle() - Search for a power supply and returns its ref * @np: Pointer to device node holding phandle property - * @phandle_name: Name of property holding a power supply name + * @property: Name of property holding a power supply name * * If power supply was found, it increases reference count for the * internal power supply's device. The user should power_supply_put() @@ -458,7 +458,7 @@ static void devm_power_supply_put(struct device *dev, void *res) * devm_power_supply_get_by_phandle() - Resource managed version of * power_supply_get_by_phandle() * @dev: Pointer to device holding phandle property - * @phandle_name: Name of property holding a power supply phandle + * @property: Name of property holding a power supply phandle * * Return: On success returns a reference to a power supply with * matching name equals to value under @property, NULL or ERR_PTR otherwise. -- cgit v1.2.3 From 950b6c2d110e8df65b9d2704cc7039f3d0d9f7b2 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 30 Sep 2016 21:45:30 -0700 Subject: power: supply: bq27xxx_battery: don't update poll_interval param if same To avoid canceling the delayed workqueue needlessly, and scheduling an immediate polling. Check if the new poll_interval value is different than the previous setting. Cc: Tony Lindgren Cc: Sebastian Reichel Signed-off-by: Matt Ranostay Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq27xxx_battery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index 3b0dbc689d72..0c343a0c941e 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -397,10 +397,11 @@ static LIST_HEAD(bq27xxx_battery_devices); static int poll_interval_param_set(const char *val, const struct kernel_param *kp) { struct bq27xxx_device_info *di; + unsigned int prev_val = *(unsigned int *) kp->arg; int ret; ret = param_set_uint(val, kp); - if (ret < 0) + if (ret < 0 || prev_val == *(unsigned int *) kp->arg) return ret; mutex_lock(&bq27xxx_list_lock); -- cgit v1.2.3 From 14d60bdd1ef58e3e0913f049c88daeed91a43387 Mon Sep 17 00:00:00 2001 From: Liu Xiang Date: Wed, 21 Sep 2016 22:17:34 +0800 Subject: power: supply: max17040: Change register transaction length from 8 bits to 16 bits According to the datasheet, MAX17040 has six 16-bit registers. Register reads and writes are only valid if all 16 bits are transferred. Any write command that is terminated early is ignored. So it's better to change register transacton length from 8 bits to 16 bits. Signed-off-by: Liu Xiang Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17040_battery.c | 52 +++++++++++++-------------------- 1 file changed, 20 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index 8689c80202b5..e7c3649b31a0 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c @@ -21,18 +21,13 @@ #include #include -#define MAX17040_VCELL_MSB 0x02 -#define MAX17040_VCELL_LSB 0x03 -#define MAX17040_SOC_MSB 0x04 -#define MAX17040_SOC_LSB 0x05 -#define MAX17040_MODE_MSB 0x06 -#define MAX17040_MODE_LSB 0x07 -#define MAX17040_VER_MSB 0x08 -#define MAX17040_VER_LSB 0x09 -#define MAX17040_RCOMP_MSB 0x0C -#define MAX17040_RCOMP_LSB 0x0D -#define MAX17040_CMD_MSB 0xFE -#define MAX17040_CMD_LSB 0xFF +#define MAX17040_VCELL 0x02 +#define MAX17040_SOC 0x04 +#define MAX17040_MODE 0x06 +#define MAX17040_VER 0x08 +#define MAX17040_RCOMP 0x0C +#define MAX17040_CMD 0xFE + #define MAX17040_DELAY 1000 #define MAX17040_BATTERY_FULL 95 @@ -78,11 +73,11 @@ static int max17040_get_property(struct power_supply *psy, return 0; } -static int max17040_write_reg(struct i2c_client *client, int reg, u8 value) +static int max17040_write_reg(struct i2c_client *client, int reg, u16 value) { int ret; - ret = i2c_smbus_write_byte_data(client, reg, value); + ret = i2c_smbus_write_word_swapped(client, reg, value); if (ret < 0) dev_err(&client->dev, "%s: err %d\n", __func__, ret); @@ -94,7 +89,7 @@ static int max17040_read_reg(struct i2c_client *client, int reg) { int ret; - ret = i2c_smbus_read_byte_data(client, reg); + ret = i2c_smbus_read_word_swapped(client, reg); if (ret < 0) dev_err(&client->dev, "%s: err %d\n", __func__, ret); @@ -104,43 +99,36 @@ static int max17040_read_reg(struct i2c_client *client, int reg) static void max17040_reset(struct i2c_client *client) { - max17040_write_reg(client, MAX17040_CMD_MSB, 0x54); - max17040_write_reg(client, MAX17040_CMD_LSB, 0x00); + max17040_write_reg(client, MAX17040_CMD, 0x0054); } static void max17040_get_vcell(struct i2c_client *client) { struct max17040_chip *chip = i2c_get_clientdata(client); - u8 msb; - u8 lsb; + u16 vcell; - msb = max17040_read_reg(client, MAX17040_VCELL_MSB); - lsb = max17040_read_reg(client, MAX17040_VCELL_LSB); + vcell = max17040_read_reg(client, MAX17040_VCELL); - chip->vcell = (msb << 4) + (lsb >> 4); + chip->vcell = vcell; } static void max17040_get_soc(struct i2c_client *client) { struct max17040_chip *chip = i2c_get_clientdata(client); - u8 msb; - u8 lsb; + u16 soc; - msb = max17040_read_reg(client, MAX17040_SOC_MSB); - lsb = max17040_read_reg(client, MAX17040_SOC_LSB); + soc = max17040_read_reg(client, MAX17040_SOC); - chip->soc = msb; + chip->soc = (soc >> 8); } static void max17040_get_version(struct i2c_client *client) { - u8 msb; - u8 lsb; + u16 version; - msb = max17040_read_reg(client, MAX17040_VER_MSB); - lsb = max17040_read_reg(client, MAX17040_VER_LSB); + version = max17040_read_reg(client, MAX17040_VER); - dev_info(&client->dev, "MAX17040 Fuel-Gauge Ver %d%d\n", msb, lsb); + dev_info(&client->dev, "MAX17040 Fuel-Gauge Ver 0x%x\n", version); } static void max17040_get_online(struct i2c_client *client) -- cgit v1.2.3 From a5a8539927b840502d706c8c56423d203437d9c6 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 16:13:35 -0300 Subject: power: supply: max8997_charger: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/power/supply/max8997_charger.ko | grep alias $ After this patch: $ modinfo drivers/power/supply/max8997_charger.ko | grep alias alias: platform:max8997-battery Signed-off-by: Javier Martinez Canillas Signed-off-by: Sebastian Reichel --- drivers/power/supply/max8997_charger.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c index 0b2eab571528..290ddc12b040 100644 --- a/drivers/power/supply/max8997_charger.c +++ b/drivers/power/supply/max8997_charger.c @@ -184,6 +184,7 @@ static const struct platform_device_id max8997_battery_id[] = { { "max8997-battery", 0 }, { } }; +MODULE_DEVICE_TABLE(platform, max8997_battery_id); static struct platform_driver max8997_battery_driver = { .driver = { -- cgit v1.2.3 From 99e33fbdffc6d98ff8966b6a13a8fa53253a2974 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 16:13:36 -0300 Subject: power: supply: axp288_fuel_gauge: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/power/supply/axp288_fuel_gauge.ko | grep alias $ After this patch: $ modinfo drivers/power/supply/axp288_fuel_gauge.ko | grep alias alias: platform:axp288_fuel_gauge Signed-off-by: Javier Martinez Canillas Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_fuel_gauge.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c index 5bdde692f724..539eb41504bb 100644 --- a/drivers/power/supply/axp288_fuel_gauge.c +++ b/drivers/power/supply/axp288_fuel_gauge.c @@ -1120,6 +1120,7 @@ static const struct platform_device_id axp288_fg_id_table[] = { { .name = DEV_NAME }, {}, }; +MODULE_DEVICE_TABLE(platform, axp288_fg_id_table); static int axp288_fuel_gauge_remove(struct platform_device *pdev) { -- cgit v1.2.3 From 991de440363d294bee06bfaf484a3843f3f3fd81 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 15:36:12 -0300 Subject: power: reset: at91-reset: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/power/reset/at91-reset.ko | grep alias $ After this patch: $ modinfo drivers/power/reset/at91-reset.ko | grep alias alias: of:N*T*Catmel,sama5d3-rstcC* alias: of:N*T*Catmel,sama5d3-rstc alias: of:N*T*Catmel,at91sam9g45-rstcC* alias: of:N*T*Catmel,at91sam9g45-rstc alias: of:N*T*Catmel,at91sam9260-rstcC* alias: of:N*T*Catmel,at91sam9260-rstc alias: platform:at91-sam9g45-reset alias: platform:at91-sam9260-reset Signed-off-by: Javier Martinez Canillas Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 1b5d450586d1..568580cf0655 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -175,6 +175,7 @@ static const struct of_device_id at91_reset_of_match[] = { { .compatible = "atmel,sama5d3-rstc", .data = sama5d3_restart }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, at91_reset_of_match); static struct notifier_block at91_restart_nb = { .priority = 192, @@ -242,6 +243,7 @@ static const struct platform_device_id at91_reset_plat_match[] = { { "at91-sam9g45-reset", (unsigned long)at91sam9g45_restart }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(platform, at91_reset_plat_match); static struct platform_driver at91_reset_driver = { .remove = __exit_p(at91_reset_remove), -- cgit v1.2.3 From c9ba9b77631d7bb81c953b83e17f6924380c09e1 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 15:36:13 -0300 Subject: power: reset: at91-poweroff: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/power/reset/at91-poweroff.ko | grep alias $ After this patch: $ modinfo drivers/power/reset/at91-poweroff.ko | grep alias alias: of:N*T*Catmel,at91sam9x5-shdwcC* alias: of:N*T*Catmel,at91sam9x5-shdwc alias: of:N*T*Catmel,at91sam9rl-shdwcC* alias: of:N*T*Catmel,at91sam9rl-shdwc alias: of:N*T*Catmel,at91sam9260-shdwcC* alias: of:N*T*Catmel,at91sam9260-shdwc Signed-off-by: Javier Martinez Canillas Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-poweroff.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c index e9e24df35f26..a85dd4d233af 100644 --- a/drivers/power/reset/at91-poweroff.c +++ b/drivers/power/reset/at91-poweroff.c @@ -169,6 +169,7 @@ static const struct of_device_id at91_poweroff_of_match[] = { { .compatible = "atmel,at91sam9x5-shdwc", }, { /*sentinel*/ } }; +MODULE_DEVICE_TABLE(of, at91_poweroff_of_match); static struct platform_driver at91_poweroff_driver = { .remove = __exit_p(at91_poweroff_remove), -- cgit v1.2.3 From 0a27aa9c316ea36c299bfe552da8297e15d16fd4 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 15:36:14 -0300 Subject: power: reset: syscon-reboot-mode: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/power/reset/syscon-reboot-mode.ko | grep alias $ After this patch: $ modinfo drivers/power/reset/syscon-reboot-mode.ko | grep alias alias: of:N*T*Csyscon-reboot-modeC* alias: of:N*T*Csyscon-reboot-mode Signed-off-by: Javier Martinez Canillas Signed-off-by: Sebastian Reichel --- drivers/power/reset/syscon-reboot-mode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/power/reset/syscon-reboot-mode.c b/drivers/power/reset/syscon-reboot-mode.c index 1ecb51d67149..c8c371b285b1 100644 --- a/drivers/power/reset/syscon-reboot-mode.c +++ b/drivers/power/reset/syscon-reboot-mode.c @@ -74,6 +74,7 @@ static const struct of_device_id syscon_reboot_mode_of_match[] = { { .compatible = "syscon-reboot-mode" }, {} }; +MODULE_DEVICE_TABLE(of, syscon_reboot_mode_of_match); static struct platform_driver syscon_reboot_mode_driver = { .probe = syscon_reboot_mode_probe, -- cgit v1.2.3 From 93f7c27b4dc56f144b954424031baae0f6a0e808 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 15:36:15 -0300 Subject: power: reset: zx-reboot: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/power/reset/zx-reboot.ko | grep alias $ After this patch: $ modinfo drivers/power/reset/zx-reboot.ko | grep alias alias: of:N*T*Czte,sysctrlC* alias: of:N*T*Czte,sysctrl Signed-off-by: Javier Martinez Canillas Signed-off-by: Sebastian Reichel --- drivers/power/reset/zx-reboot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/power/reset/zx-reboot.c b/drivers/power/reset/zx-reboot.c index b0b1eb3a78c2..7549c7f74a3c 100644 --- a/drivers/power/reset/zx-reboot.c +++ b/drivers/power/reset/zx-reboot.c @@ -72,6 +72,7 @@ static const struct of_device_id zx_reboot_of_match[] = { { .compatible = "zte,sysctrl" }, {} }; +MODULE_DEVICE_TABLE(of, zx_reboot_of_match); static struct platform_driver zx_reboot_driver = { .probe = zx_reboot_probe, -- cgit v1.2.3 From 44fccac4ff17371054f795f89e23f0b60bb516c1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 14 Oct 2016 10:33:28 +0300 Subject: power: supply: lp8788: remove an unneeded NULL check We checked that "pdata->chg_params" is non-NULL earlier in this function so when we add "i" to it, it's still non-NULL. Signed-off-by: Dan Carpenter Acked-by: Milo Kim Signed-off-by: Sebastian Reichel --- drivers/power/supply/lp8788-charger.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/power/supply/lp8788-charger.c b/drivers/power/supply/lp8788-charger.c index 7321b727d484..509e2b341bd6 100644 --- a/drivers/power/supply/lp8788-charger.c +++ b/drivers/power/supply/lp8788-charger.c @@ -384,9 +384,6 @@ static int lp8788_update_charger_params(struct platform_device *pdev, for (i = 0; i < pdata->num_chg_params; i++) { param = pdata->chg_params + i; - if (!param) - continue; - if (lp8788_is_valid_charger_register(param->addr)) { ret = lp8788_write_byte(lp, param->addr, param->val); if (ret) -- cgit v1.2.3 From b9a1b7179cde240abf67a613f2a67be7c56cc59f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 18 Oct 2016 17:16:23 +0200 Subject: i915: don't call drm_atomic_state_put on invalid pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The introduction of reference counting on the state structures caused sanitize_watermarks() in i915 to break in the error handling case, as pointed out by gcc -Wmaybe-uninitialized drivers/gpu/drm/i915/intel_display.c: In function ‘intel_modeset_init’: include/drm/drm_atomic.h:224:2: error: ‘state’ may be used uninitialized in this function [-Werror=maybe-uninitialized] This changes the function back to only drop the reference count when it was successfully allocated first. Fixes: 0853695c3ba4 ("drm: Add reference counting to drm_atomic_state") Cc: Chris Wilson Cc: Daniel Vetter Signed-off-by: Arnd Bergmann Reviewed-by: Eric Engestrom Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161018151652.2690201-1-arnd@arndb.de --- drivers/gpu/drm/i915/intel_display.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a12e093c54cf..1e3b5eebd2a2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -16294,7 +16294,7 @@ retry: * BIOS-programmed watermarks untouched and hope for the best. */ WARN(true, "Could not determine valid watermarks for inherited state\n"); - goto fail; + goto put_state; } /* Write calculated watermark values back */ @@ -16305,8 +16305,9 @@ retry: dev_priv->display.optimize_watermarks(cs); } -fail: +put_state: drm_atomic_state_put(state); +fail: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); } -- cgit v1.2.3 From fb80016af071b3baedb8c2f327ae599f8ab107dc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 18 Oct 2016 13:57:19 -0700 Subject: gpu: Remove depends on RESET_CONTROLLER when not a provider These GPU drivers only depend on the RESET_CONTROLLER config option to fix build issues that existed when there weren't stub reset APIs for reset controller consumers. Given that these drivers aren't providing any reset controllers themselves, they don't actually depend on the API to build (just to function) so they don't need to depend on it. Remove the dependency to fix recursive build errors like the following: drivers/usb/Kconfig:39:error: recursive dependency detected! drivers/usb/Kconfig:39: symbol USB is selected by MOUSE_APPLETOUCH drivers/input/mouse/Kconfig:187: symbol MOUSE_APPLETOUCH depends on INPUT drivers/input/Kconfig:8: symbol INPUT is selected by VT drivers/tty/Kconfig:12: symbol VT is selected by FB_STI drivers/video/fbdev/Kconfig:674: symbol FB_STI depends on FB drivers/video/fbdev/Kconfig:5: symbol FB is selected by DRM_KMS_FB_HELPER drivers/gpu/drm/Kconfig:42: symbol DRM_KMS_FB_HELPER is selected by DRM_KMS_CMA_HELPER drivers/gpu/drm/Kconfig:98: symbol DRM_KMS_CMA_HELPER is selected by DRM_IMX drivers/gpu/drm/imx/Kconfig:1: symbol DRM_IMX depends on IMX_IPUV3_CORE drivers/gpu/ipu-v3/Kconfig:1: symbol IMX_IPUV3_CORE depends on RESET_CONTROLLER drivers/reset/Kconfig:4: symbol RESET_CONTROLLER is selected by USB_CHIPIDEA drivers/usb/chipidea/Kconfig:1: symbol USB_CHIPIDEA depends on USB_EHCI_HCD drivers/usb/host/Kconfig:84: symbol USB_EHCI_HCD depends on USB Cc: Arnd Bergmann Cc: Cc: Heiko Stuebner Cc: Mark Yao Acked-by: Philipp Zabel Acked-by: robdclark@gmail.com Signed-off-by: Stephen Boyd Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161018205719.20575-1-stephen.boyd@linaro.org --- drivers/gpu/drm/rockchip/Kconfig | 1 - drivers/gpu/drm/tegra/Kconfig | 1 - drivers/gpu/ipu-v3/Kconfig | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 3c58669a06ce..6f7f9c59f05b 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -1,7 +1,6 @@ config DRM_ROCKCHIP tristate "DRM Support for Rockchip" depends on DRM && ROCKCHIP_IOMMU - depends on RESET_CONTROLLER select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index 63ebb154b9b5..bbf5a4b7e0b6 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig @@ -3,7 +3,6 @@ config DRM_TEGRA depends on ARCH_TEGRA || (ARM && COMPILE_TEST) depends on COMMON_CLK depends on DRM - depends on RESET_CONTROLLER select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL diff --git a/drivers/gpu/ipu-v3/Kconfig b/drivers/gpu/ipu-v3/Kconfig index aefdff95356d..08766c6e7856 100644 --- a/drivers/gpu/ipu-v3/Kconfig +++ b/drivers/gpu/ipu-v3/Kconfig @@ -1,7 +1,6 @@ config IMX_IPUV3_CORE tristate "IPUv3 core support" depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM - depends on RESET_CONTROLLER select GENERIC_IRQ_CHIP help Choose this if you have a i.MX5/6 system and want to use the Image -- cgit v1.2.3 From 0525a062df00ff728919a752d2204b943cf76bd4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Oct 2016 14:27:07 +0100 Subject: drm/i915: Emit telltales for extra levels of debug upon initialisation After printing our welcome message to the user, also include supplementary details on what debugging is enabled (useful for us to sanity check what extra safeguards are on for any random kernel). Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161014132707.29039-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld drm.primary->index); + if (IS_ENABLED(CONFIG_DRM_I915_DEBUG)) + DRM_INFO("DRM_I915_DEBUG enabled\n"); + if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) + DRM_INFO("DRM_I915_DEBUG_GEM enabled\n"); intel_runtime_pm_put(dev_priv); -- cgit v1.2.3 From 6a6af3d04435adfdaab363624ec569a9b5d3973c Mon Sep 17 00:00:00 2001 From: Gabriele Mazzotta Date: Tue, 4 Oct 2016 00:50:28 +0200 Subject: rtc: cmos: Reject unsupported alarm values Some platforms allows to specify the month and day of the month in which an alarm should go off, some others the day of the month and some others just the time. Currently any given value is accepted by the driver and only the supported fields are used to program the hardware. As consequence, alarms are potentially programmed to go off in the wrong moment. Fix this by rejecting any unsupported value. Signed-off-by: Gabriele Mazzotta Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index dd3d59806ffa..903a82ae83f0 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -325,14 +325,86 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) cmos_checkintr(cmos, rtc_control); } +static int cmos_validate_alarm(struct device *dev, struct rtc_wkalrm *t) +{ + struct cmos_rtc *cmos = dev_get_drvdata(dev); + struct rtc_time now; + + cmos_read_time(dev, &now); + + if (!cmos->day_alrm) { + time64_t t_max_date; + time64_t t_alrm; + + t_max_date = rtc_tm_to_time64(&now); + t_max_date += 24 * 60 * 60 - 1; + t_alrm = rtc_tm_to_time64(&t->time); + if (t_alrm > t_max_date) { + dev_err(dev, + "Alarms can be up to one day in the future\n"); + return -EINVAL; + } + } else if (!cmos->mon_alrm) { + struct rtc_time max_date = now; + time64_t t_max_date; + time64_t t_alrm; + int max_mday; + + if (max_date.tm_mon == 11) { + max_date.tm_mon = 0; + max_date.tm_year += 1; + } else { + max_date.tm_mon += 1; + } + max_mday = rtc_month_days(max_date.tm_mon, max_date.tm_year); + if (max_date.tm_mday > max_mday) + max_date.tm_mday = max_mday; + + t_max_date = rtc_tm_to_time64(&max_date); + t_max_date -= 1; + t_alrm = rtc_tm_to_time64(&t->time); + if (t_alrm > t_max_date) { + dev_err(dev, + "Alarms can be up to one month in the future\n"); + return -EINVAL; + } + } else { + struct rtc_time max_date = now; + time64_t t_max_date; + time64_t t_alrm; + int max_mday; + + max_date.tm_year += 1; + max_mday = rtc_month_days(max_date.tm_mon, max_date.tm_year); + if (max_date.tm_mday > max_mday) + max_date.tm_mday = max_mday; + + t_max_date = rtc_tm_to_time64(&max_date); + t_max_date -= 1; + t_alrm = rtc_tm_to_time64(&t->time); + if (t_alrm > t_max_date) { + dev_err(dev, + "Alarms can be up to one year in the future\n"); + return -EINVAL; + } + } + + return 0; +} + static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) { struct cmos_rtc *cmos = dev_get_drvdata(dev); unsigned char mon, mday, hrs, min, sec, rtc_control; + int ret; if (!is_valid_irq(cmos->irq)) return -EIO; + ret = cmos_validate_alarm(dev, t); + if (ret < 0) + return ret; + mon = t->time.tm_mon + 1; mday = t->time.tm_mday; hrs = t->time.tm_hour; -- cgit v1.2.3 From 290cd0f07f0c55f4071aee47b5d4cc3c83da588c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 12 Oct 2016 15:30:53 +0200 Subject: rtc: cmos: don't refer to asm-generic/rtc.h That header has been gone for a while. I've fixed up the Kconfig comment, but the one in rtc-cmos.c doesn't make any sense to me even looking at its history. Signed-off-by: Christoph Hellwig Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 4 ++-- drivers/rtc/rtc-cmos.c | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e859d148aba9..4cbea34e6003 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -820,8 +820,8 @@ config RTC_DRV_RV3029_HWMON comment "Platform RTC drivers" -# this 'CMOS' RTC driver is arch dependent because -# requires defining CMOS_READ/CMOS_WRITE, and a +# this 'CMOS' RTC driver is arch dependent because it requires +# defining CMOS_READ/CMOS_WRITE, and a # global rtc_lock ... it's not yet just another platform_device. config RTC_DRV_CMOS diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 903a82ae83f0..390172bac39b 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -772,9 +772,6 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) spin_unlock_irq(&rtc_lock); - /* FIXME: - * doesn't know 12-hour mode either. - */ if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) { dev_warn(dev, "only 24-hr supported\n"); retval = -ENXIO; -- cgit v1.2.3 From 341ca402e42b3c4a8b34341a35f82ff9f7bf8664 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Sun, 18 Sep 2016 14:51:59 +0300 Subject: iwlwifi: mvm: update txq metadata to current owner When a TXQ's owner is changed, the FW is indeed notified, but the driver doesn't update the current metadata to reflect the owner change. Fix that. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index fc771885e383..a65030f4019d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -875,12 +875,17 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue) cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd); - if (ret) + if (ret) { IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n", queue, ret); - else - IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n", - queue, tid); + return; + } + + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[queue].txq_tid = tid; + spin_unlock_bh(&mvm->queue_info_lock); + IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n", + queue, tid); } static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue) -- cgit v1.2.3 From 56214749e0b46eeac6795551f187c0f9443918f2 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Thu, 22 Sep 2016 15:14:08 +0300 Subject: iwlwifi: mvm: fix reserved txq freeing If a TXQ's marking as a reserved queue is removed, when removing the STA the driver might try to access out of bounds memory. Make sure the reserved queue is freed only if it is still reserved. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index a65030f4019d..c9dcb70cb525 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1494,12 +1494,15 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, ret = iwl_mvm_drain_sta(mvm, mvm_sta, false); /* If DQA is supported - the queues can be disabled now */ - if (iwl_mvm_is_dqa_supported(mvm)) { + if (iwl_mvm_is_dqa_supported(mvm)) + iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta); + + /* If there is a TXQ still marked as reserved - free it */ + if (iwl_mvm_is_dqa_supported(mvm) && + mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) { u8 reserved_txq = mvm_sta->reserved_queue; enum iwl_mvm_queue_status *status; - iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta); - /* * If no traffic has gone through the reserved TXQ - it * is still marked as IWL_MVM_QUEUE_RESERVED, and -- cgit v1.2.3 From 737847aa2c22ea41ce38950bff800d2f7dd05a03 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 27 Sep 2016 15:17:29 +0300 Subject: iwlwifi: mvm: support MONITOR vif in DQA mode In DQA mode the TXQs are allocated on demand, so make sure the sniffer STA tfd_queue_msk isn't set. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 6b962d6b067a..9a9120319510 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -899,9 +899,11 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action); - for (i = 0; i < IEEE80211_NUM_ACS; i++) - if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) - tfd_queue_msk |= BIT(vif->hw_queue[i]); + if (!iwl_mvm_is_dqa_supported(mvm)) { + for (i = 0; i < IEEE80211_NUM_ACS; i++) + if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) + tfd_queue_msk |= BIT(vif->hw_queue[i]); + } cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC | MAC_FILTER_IN_CONTROL_AND_MGMT | -- cgit v1.2.3 From ad5de73734031c07eb8c7cdb7c7d63d3630bb202 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 27 Sep 2016 16:01:10 +0300 Subject: iwlwifi: mvm: fix dqa deferred frames marking When a STA has deferred traffic to TX, an appropriate bit is turned on in %deferred_tx_frames to indicate deferred traffic. This marking is never turned off, resulting in iterating over TIDs with no deferred traffic. Although this didn't cause any failures/errors/bugs, there is still no point of iterating over these TIDs when not needed. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index c9dcb70cb525..5ec1b96b9593 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1015,6 +1015,7 @@ static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm, local_bh_disable(); spin_lock(&mvmsta->lock); skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx); + mvmsta->deferred_traffic_tid_map &= ~BIT(tid); spin_unlock(&mvmsta->lock); while ((skb = __skb_dequeue(&deferred_tx))) -- cgit v1.2.3 From 65e254821cee1a63f3f6d23270e90b33432b2bef Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2016 14:24:22 +0200 Subject: iwlwifi: mvm: use firmware station PM notification for AP_LINK_PS When using RSS on 9000 series devices, we can't rely on processing the received frames for station powersave handling, since they could be processed on different CPUs and out of order. In order to still manage the powersave of stations, the firmware sends a notification on sleep->wake, wake->sleep and - for U-APSD - frames received with PM while already sleeping (with the TID.) With this, the driver can set AP_LINK_PS, which is required for real parallel RX. In addition, this requires checking for PS-Poll frames and calling ieee80211_sta_pspoll() appropriately. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 26 ++++++++ .../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 9 ++- drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 70 ++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 + drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 13 ++++ drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 1 + 9 files changed, 119 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index ceec5ca2b1ab..1ad0ec180d5d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -293,6 +293,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * is supported. * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan + * @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT @@ -342,6 +343,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, + IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38, IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h index acc5cd53e4ba..b530fa47d68a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h @@ -474,4 +474,30 @@ struct iwl_mvm_internal_rxq_notif { u8 data[]; } __packed; +/** + * enum iwl_mvm_pm_event - type of station PM event + * @IWL_MVM_PM_EVENT_AWAKE: station woke up + * @IWL_MVM_PM_EVENT_ASLEEP: station went to sleep + * @IWL_MVM_PM_EVENT_UAPSD: station sent uAPSD trigger + * @IWL_MVM_PM_EVENT_PS_POLL: station sent PS-Poll + */ +enum iwl_mvm_pm_event { + IWL_MVM_PM_EVENT_AWAKE, + IWL_MVM_PM_EVENT_ASLEEP, + IWL_MVM_PM_EVENT_UAPSD, + IWL_MVM_PM_EVENT_PS_POLL, +}; /* PEER_PM_NTFY_API_E_VER_1 */ + +/** + * struct iwl_mvm_pm_state_notification - station PM state notification + * @sta_id: station ID of the station changing state + * @type: the new powersave state, see IWL_MVM_PM_EVENT_ above + */ +struct iwl_mvm_pm_state_notification { + u8 sta_id; + u8 type; + /* private: */ + u16 reserved; +} __packed; /* PEER_PM_NTFY_API_S_VER_1 */ + #endif /* __fw_api_rx_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h index 6c8e3ca79323..3b5150e9975d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h @@ -179,7 +179,7 @@ enum iwl_sta_key_flag { * enum iwl_sta_modify_flag - indicate to the fw what flag are being changed * @STA_MODIFY_QUEUE_REMOVAL: this command removes a queue * @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx - * @STA_MODIFY_TX_RATE: unused + * @STA_MODIFY_UAPSD_ACS: this command modifies %uapsd_trigger_acs * @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid * @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid * @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count @@ -189,7 +189,7 @@ enum iwl_sta_key_flag { enum iwl_sta_modify_flag { STA_MODIFY_QUEUE_REMOVAL = BIT(0), STA_MODIFY_TID_DISABLE_TX = BIT(1), - STA_MODIFY_TX_RATE = BIT(2), + STA_MODIFY_UAPSD_ACS = BIT(2), STA_MODIFY_ADD_BA_TID = BIT(3), STA_MODIFY_REMOVE_BA_TID = BIT(4), STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5), @@ -353,6 +353,8 @@ struct iwl_mvm_add_sta_cmd_v7 { * @beamform_flags: beam forming controls * @tfd_queue_msk: tfd queues used by this station * @rx_ba_window: aggregation window size + * @scd_queue_bank: queue bank in used. Each bank contains 32 queues. 0 means + * that the queues used by this station are in the first 32. * * The device contains an internal table of per-station information, with info * on security keys, aggregation parameters, and Tx rates for initial Tx @@ -382,7 +384,8 @@ struct iwl_mvm_add_sta_cmd { __le16 beamform_flags; __le32 tfd_queue_msk; __le16 rx_ba_window; - __le16 reserved; + u8 scd_queue_bank; + u8 uapsd_trigger_acs; } __packed; /* ADD_STA_CMD_API_S_VER_8 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 97633690f3d5..ae12badc0c2a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -332,6 +332,7 @@ enum iwl_data_path_subcmd_ids { DQA_ENABLE_CMD = 0x0, UPDATE_MU_GROUPS_CMD = 0x1, TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2, + STA_PM_NOTIF = 0xFD, MU_GROUP_MGMT_NOTIF = 0xFE, RX_QUEUES_NOTIFICATION = 0xFF, }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 318efd814037..9eeb2c36bbc1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -445,6 +445,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); if (iwl_mvm_has_new_rx_api(mvm)) ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); + if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF)) + ieee80211_hw_set(hw, AP_LINK_PS); if (mvm->trans->num_rx_queues > 1) ieee80211_hw_set(hw, USES_RSS); @@ -2318,10 +2320,9 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw, tids, more_data, true); } -static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) +static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); @@ -2374,6 +2375,67 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, spin_unlock_bh(&mvmsta->lock); } +static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + __iwl_mvm_mac_sta_notify(hw, cmd, sta); +} + +void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_mvm_pm_state_notification *notif = (void *)pkt->data; + struct ieee80211_sta *sta; + struct iwl_mvm_sta *mvmsta; + bool sleeping = (notif->type != IWL_MVM_PM_EVENT_AWAKE); + + if (WARN_ON(notif->sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))) + return; + + rcu_read_lock(); + sta = mvm->fw_id_to_mac_id[notif->sta_id]; + if (WARN_ON(IS_ERR_OR_NULL(sta))) { + rcu_read_unlock(); + return; + } + + mvmsta = iwl_mvm_sta_from_mac80211(sta); + + if (!mvmsta->vif || + mvmsta->vif->type != NL80211_IFTYPE_AP) { + rcu_read_unlock(); + return; + } + + if (mvmsta->sleeping != sleeping) { + mvmsta->sleeping = sleeping; + __iwl_mvm_mac_sta_notify(mvm->hw, + sleeping ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE, + sta); + ieee80211_sta_ps_transition(sta, sleeping); + } + + if (sleeping) { + switch (notif->type) { + case IWL_MVM_PM_EVENT_AWAKE: + case IWL_MVM_PM_EVENT_ASLEEP: + break; + case IWL_MVM_PM_EVENT_UAPSD: + ieee80211_sta_uapsd_trigger(sta, IEEE80211_NUM_TIDS); + break; + case IWL_MVM_PM_EVENT_PS_POLL: + ieee80211_sta_pspoll(sta); + break; + default: + break; + } + } + + rcu_read_unlock(); +} + static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index d17cbf603f7c..726ba48da15d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1418,6 +1418,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_window_status_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 05fe6dd1a2c8..e86986f5c40d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -306,6 +306,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { iwl_mvm_rx_stored_beacon_notif, RX_HANDLER_SYNC), RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF, iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC), + RX_HANDLER_GRP(DATA_PATH_GROUP, STA_PM_NOTIF, + iwl_mvm_sta_pm_notif, RX_HANDLER_SYNC), }; #undef RX_HANDLER #undef RX_HANDLER_GRP @@ -452,6 +454,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = { static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { HCMD_NAME(UPDATE_MU_GROUPS_CMD), HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), + HCMD_NAME(STA_PM_NOTIF), HCMD_NAME(MU_GROUP_MGMT_NOTIF), HCMD_NAME(RX_QUEUES_NOTIFICATION), }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 5ec1b96b9593..82ee786bba63 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -203,6 +203,19 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, add_sta_cmd.station_flags |= cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); + if (sta->wme) { + add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS; + + if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) + add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BK); + if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) + add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BE); + if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) + add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VI); + if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) + add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VO); + } + status = ADD_STA_SUCCESS; ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, iwl_mvm_add_sta_cmd_size(mvm), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index e068d5355865..b45c7b9937c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -436,6 +436,7 @@ struct iwl_mvm_sta { bool disable_tx; bool tlc_amsdu; + bool sleeping; u8 agg_tids; u8 sleep_tx_count; u8 avg_energy; -- cgit v1.2.3 From 64fa3aff89785b5a924ce3934f6595c35b4dffee Mon Sep 17 00:00:00 2001 From: Sharon Dvir Date: Wed, 17 Aug 2016 15:35:09 +0300 Subject: iwlwifi: pcie: give a meaningful name to interrupt request Instead of passing DRV_NAME pass a string that represents the reason for the interrupt. Signed-off-by: Sharon Dvir Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 29 ++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index ae95533e587d..b10e3633df1a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1598,6 +1598,29 @@ static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans) } } +static const char *queue_name(struct device *dev, + struct iwl_trans_pcie *trans_p, int i) +{ + if (trans_p->shared_vec_mask) { + int vec = trans_p->shared_vec_mask & + IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0; + + if (i == 0) + return DRV_NAME ": shared IRQ"; + + return devm_kasprintf(dev, GFP_KERNEL, + DRV_NAME ": queue %d", i + vec); + } + if (i == 0) + return DRV_NAME ": default queue"; + + if (i == trans_p->alloc_vecs - 1) + return DRV_NAME ": exception"; + + return devm_kasprintf(dev, GFP_KERNEL, + DRV_NAME ": queue %d", i); +} + static int iwl_pcie_init_msix_handler(struct pci_dev *pdev, struct iwl_trans_pcie *trans_pcie) { @@ -1606,6 +1629,10 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev, for (i = 0; i < trans_pcie->alloc_vecs; i++) { int ret; struct msix_entry *msix_entry; + const char *qname = queue_name(&pdev->dev, trans_pcie, i); + + if (!qname) + return -ENOMEM; msix_entry = &trans_pcie->msix_entries[i]; ret = devm_request_threaded_irq(&pdev->dev, @@ -1615,7 +1642,7 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev, iwl_pcie_irq_msix_handler : iwl_pcie_irq_rx_msix_handler, IRQF_SHARED, - DRV_NAME, + qname, msix_entry); if (ret) { IWL_ERR(trans_pcie->trans, -- cgit v1.2.3 From 19c52f460f6d84af8225d8a769d66871dc5ed65b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 9 Oct 2016 15:43:24 +0300 Subject: iwlwifi: mvm: tell the firmware about the AID of the peer When a peer associates, the firmware will soon want to know its AID to be able to compute the TIM IE by itself. In DQA, the firmware has all the information it needs to update the TIM internally. The only missing part is the AID. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 82ee786bba63..636c8b03e318 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -202,6 +202,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT); add_sta_cmd.station_flags |= cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); + add_sta_cmd.assoc_id = cpu_to_le16(sta->aid); if (sta->wme) { add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS; -- cgit v1.2.3 From 8236f7db272484093fb02ce72a40e7224a5c29d4 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 6 Oct 2016 16:42:32 +0300 Subject: iwlwifi: mvm: assign cab queue to the correct station Currently when configuring the cab queue the scheduler is configured without station id - which results in station id 0. In DQA mode this causes firmware to assert later on when the actual station 0 is added with an empty tfd_queue_mask. Fix that by configuring the queue to the broadcast station. This is a bit trickier since the queue should not be included in the tfd_queue_mask of the ADD_STA since it is a multicast queue, and the tfd_queue_mask is only unicast queue. As a result the queue should be enabled only after the broadcast station is added. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 16 +++++++--------- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 9a9120319510..4a0874e40731 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -499,23 +499,21 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) if (ret) return ret; + /* If DQA is supported - queues will be enabled when needed */ + if (iwl_mvm_is_dqa_supported(mvm)) + return 0; + switch (vif->type) { case NL80211_IFTYPE_P2P_DEVICE: - if (!iwl_mvm_is_dqa_supported(mvm)) - iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, - IWL_MVM_OFFCHANNEL_QUEUE, - IWL_MVM_TX_FIFO_VO, 0, - wdg_timeout); + iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, + IWL_MVM_OFFCHANNEL_QUEUE, + IWL_MVM_TX_FIFO_VO, 0, wdg_timeout); break; case NL80211_IFTYPE_AP: iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue, IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); /* fall through */ default: - /* If DQA is supported - queues will be enabled when needed */ - if (iwl_mvm_is_dqa_supported(mvm)) - break; - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], vif->hw_queue[ac], diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 9eeb2c36bbc1..4f8c1347aa23 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -2099,6 +2099,22 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, if (ret) goto out_unbind; + /* enable the multicast queue, now that we have a station for it */ + if (iwl_mvm_is_dqa_supported(mvm)) { + unsigned int wdg_timeout = + iwl_mvm_get_wd_timeout(mvm, vif, false, false); + struct iwl_trans_txq_scd_cfg cfg = { + .fifo = IWL_MVM_TX_FIFO_MCAST, + .sta_id = mvmvif->bcast_sta.sta_id, + .tid = IWL_MAX_TID_COUNT, + .aggregate = false, + .frame_limit = IWL_FRAME_LIMIT, + }; + + iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, + &cfg, wdg_timeout); + } + /* must be set before quota calculations */ mvmvif->ap_ibss_active = true; -- cgit v1.2.3 From b610393a66c7b8936f2435c33ee032b23581ed4e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 18 Oct 2016 14:21:50 +0300 Subject: drm: make is_lspcon_adaptor static Fixes sparse warning: drivers/gpu/drm/drm_dp_dual_mode_helper.c:151:6: warning: symbol 'is_lspcon_adaptor' was not declared. Should it be static? Fixes: 056996b95686 ("drm: Helper for lspcon in drm_dp_dual_mode") Cc: Rodrigo Vivi Cc: Shashank Sharma Cc: Reviewed-by: Shashank Sharma Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476789711-19697-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/drm_dp_dual_mode_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c index a7aeb1ec852c..2624e266abbd 100644 --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c @@ -148,8 +148,8 @@ static bool is_type2_adaptor(uint8_t adaptor_id) DP_DUAL_MODE_REV_TYPE2); } -bool is_lspcon_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN], - const uint8_t adaptor_id) +static bool is_lspcon_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN], + const uint8_t adaptor_id) { return is_hdmi_adaptor(hdmi_id) && (adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 | -- cgit v1.2.3 From 1dc16aac8a537942f47c6df14e7165bbaac26907 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 18 Oct 2016 14:21:51 +0300 Subject: drm/i915: make lspcon_get_current_mode static Fixes sparse warning: drivers/gpu/drm/i915/intel_lspcon.c:30:22: warning: symbol 'lspcon_get_current_mode' was not declared. Should it be static? Fixes: dbe9e61b8e43 ("drm/i915: Add lspcon support for I915 driver") Cc: Rodrigo Vivi Cc: Shashank Sharma Reviewed-by: Shashank Sharma Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476789711-19697-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_lspcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index d606f1a8f3b6..632149c6b3ad 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -27,7 +27,7 @@ #include #include "intel_drv.h" -enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) +static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) { enum drm_lspcon_mode current_mode = DRM_LSPCON_MODE_INVALID; struct i2c_adapter *adapter = &lspcon->aux->ddc; -- cgit v1.2.3 From a17b9e4c9c5e9c4da4385908af0377af11529266 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 18 Oct 2016 13:42:09 +0800 Subject: clk: sunxi-ng: sun6i-a31: Force AHB1 clock to use PLL6 as parent On the A31, the DMA engine only works if AHB1 is clocked from PLL6. In addition, the hstimer is clocked from AHB1, and if AHB1 is clocked from the CPU clock, and cpufreq is working, we get an unstable timer. Force the AHB1 clock to use PLL6 as its parent. Previously this was done in the device tree with the assigned-clocks and assigned-clocks-parent bindings. However with this new monolithic driver, the system critical clocks aren't exported through the device tree. The alternative is to force this setting in the driver before the clocks are registered. This is also done in newer versions of mainline U-boot. But people still using an older version, or even the vendor version, can still hit this issue. Hence the need to do it in the kernel as well. Reported-by: Hans de Goede Reported-by: Maxime Ripard Fixes: c6e6c96d8fa6 ("clk: sunxi-ng: Add A31/A31s clocks") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 79596463e0d9..4a82a49cff5e 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -191,6 +191,8 @@ static struct clk_div_table axi_div_table[] = { static SUNXI_CCU_DIV_TABLE(axi_clk, "axi", "cpu", 0x050, 0, 3, axi_div_table, 0); +#define SUN6I_A31_AHB1_REG 0x054 + static const char * const ahb1_parents[] = { "osc32k", "osc24M", "axi", "pll-periph" }; @@ -1230,6 +1232,16 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) val &= BIT(16); writel(val, reg + SUN6I_A31_PLL_MIPI_REG); + /* Force AHB1 to PLL6 / 3 */ + val = readl(reg + SUN6I_A31_AHB1_REG); + /* set PLL6 pre-div = 3 */ + val &= ~GENMASK(7, 6); + val |= 0x2 << 6; + /* select PLL6 / pre-div */ + val &= ~GENMASK(13, 12); + val |= 0x3 << 12; + writel(val, reg + SUN6I_A31_AHB1_REG); + sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc); ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, -- cgit v1.2.3 From f3fe4e93dd6346c01fd4070ae02ec746fbae73bb Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 18 Oct 2016 23:12:11 +0300 Subject: mac80211: add a HW flag for supporting HW TX fragmentation Currently mac80211 determines whether HW does fragmentation by checking whether the set_frag_threshold callback is set or not. However, some drivers may want to set the HW fragmentation capability depending on HW generation. Allow this by checking a HW flag instead of checking the callback. Signed-off-by: Sara Sharon [added the flag to ath10k and wlcore] Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath10k/mac.c | 1 + drivers/net/wireless/ti/wlcore/main.c | 1 + include/net/mac80211.h | 10 ++++++++-- net/mac80211/debugfs.c | 1 + net/mac80211/main.c | 4 ++++ net/mac80211/tx.c | 4 ++-- net/mac80211/wpa.c | 2 +- 7 files changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 76297d69f1ed..e322b6df0ebc 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -7881,6 +7881,7 @@ int ath10k_mac_register(struct ath10k *ar) ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF); ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA); ieee80211_hw_set(ar->hw, QUEUE_CONTROL); + ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 471521a0db7b..9f39c6cf98fb 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -6086,6 +6086,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) ieee80211_hw_set(wl->hw, SUPPORTS_DYNAMIC_PS); ieee80211_hw_set(wl->hw, SIGNAL_DBM); ieee80211_hw_set(wl->hw, SUPPORTS_PS); + ieee80211_hw_set(wl->hw, SUPPORTS_TX_FRAG); wl->hw->wiphy->cipher_suites = cipher_suites; wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f3dbadafe16e..a1a27021f452 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2025,6 +2025,10 @@ struct ieee80211_txq { * drivers, mac80211 packet loss mechanism will not be triggered and driver * is completely depending on firmware event for station kickout. * + * @IEEE80211_HW_SUPPORTS_TX_FRAG: Hardware does fragmentation by itself. + * The stack will not do fragmentation. + * The callback for @set_frag_threshold should be set as well. + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2066,6 +2070,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_TX_AMSDU, IEEE80211_HW_TX_FRAG_LIST, IEEE80211_HW_REPORTS_LOW_ACK, + IEEE80211_HW_SUPPORTS_TX_FRAG, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS @@ -3093,8 +3098,9 @@ enum ieee80211_reconfig_type { * The callback must be atomic. * * @set_frag_threshold: Configuration of fragmentation threshold. Assign this - * if the device does fragmentation by itself; if this callback is - * implemented then the stack will not do fragmentation. + * if the device does fragmentation by itself. Note that to prevent the + * stack from doing fragmentation IEEE80211_HW_SUPPORTS_TX_FRAG + * should be set as well. * The callback can sleep. * * @set_rts_threshold: Configuration of RTS threshold (if device needs it) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index f56e2f487d09..e02ba42ca827 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -210,6 +210,7 @@ static const char *hw_flag_names[] = { FLAG(TX_AMSDU), FLAG(TX_FRAG_LIST), FLAG(REPORTS_LOW_ACK), + FLAG(SUPPORTS_TX_FRAG), #undef FLAG }; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1075ac24c8c5..0d9163c16dda 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -821,6 +821,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) !local->ops->tdls_recv_channel_switch)) return -EOPNOTSUPP; + if (WARN_ON(ieee80211_hw_check(hw, SUPPORTS_TX_FRAG) && + !local->ops->set_frag_threshold)) + return -EINVAL; + if (WARN_ON(local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN) && (!local->ops->start_nan || !local->ops->stop_nan))) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 772e36909fa3..62ccaf6f585d 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -934,7 +934,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) if (info->flags & IEEE80211_TX_CTL_DONTFRAG) return TX_CONTINUE; - if (tx->local->ops->set_frag_threshold) + if (ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG)) return TX_CONTINUE; /* @@ -2800,7 +2800,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) /* fast-xmit doesn't handle fragmentation at all */ if (local->hw.wiphy->frag_threshold != (u32)-1 && - !local->ops->set_frag_threshold) + !ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG)) goto out; rcu_read_lock(); diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index b48c1e13e281..c24934544f9c 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -57,7 +57,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) if (info->control.hw_key && (info->flags & IEEE80211_TX_CTL_DONTFRAG || - tx->local->ops->set_frag_threshold) && + ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG)) && !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { /* hwaccel - with no need for SW-generated MMIC */ return TX_CONTINUE; -- cgit v1.2.3 From 20f4d69243785167449e6e765ce9f2a7b097ac45 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Thu, 29 Sep 2016 13:43:21 -0700 Subject: EDAC, {sb,skx}_edac: Use Intel model macros instead of open-coding them We now have symbolic names for a bunch of Intel CPU models via asm/intel-family.h. The original conversion missed the EDAC drivers. Convert them. Signed-off-by: Dave Hansen Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/20160929204321.9FAE5F84@viggo.jf.intel.com [ Remove comment, macro name is descriptive enough. ] Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 13 +++++++------ drivers/edac/skx_edac.c | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 54775221a01f..843ac6c351fd 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -3365,12 +3366,12 @@ fail0: { X86_VENDOR_INTEL, 6, model, 0, (unsigned long)&table } static const struct x86_cpu_id sbridge_cpuids[] = { - ICPU(0x2d, pci_dev_descr_sbridge_table), /* SANDY_BRIDGE */ - ICPU(0x3e, pci_dev_descr_ibridge_table), /* IVY_BRIDGE */ - ICPU(0x3f, pci_dev_descr_haswell_table), /* HASWELL */ - ICPU(0x4f, pci_dev_descr_broadwell_table), /* BROADWELL */ - ICPU(0x56, pci_dev_descr_broadwell_table), /* BROADWELL-DE */ - ICPU(0x57, pci_dev_descr_knl_table), /* KNIGHTS_LANDING */ + ICPU(INTEL_FAM6_SANDYBRIDGE_X, pci_dev_descr_sbridge_table), + ICPU(INTEL_FAM6_IVYBRIDGE_X, pci_dev_descr_ibridge_table), + ICPU(INTEL_FAM6_HASWELL_X, pci_dev_descr_haswell_table), + ICPU(INTEL_FAM6_BROADWELL_X, pci_dev_descr_broadwell_table), + ICPU(INTEL_FAM6_BROADWELL_XEON_D, pci_dev_descr_broadwell_table), + ICPU(INTEL_FAM6_XEON_PHI_KNL, pci_dev_descr_knl_table), { } }; MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids); diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index 0ff4878c2aa1..f3b3d3be1e84 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -263,7 +264,7 @@ fail: } const struct x86_cpu_id skx_cpuids[] = { - { X86_VENDOR_INTEL, 6, 0x55, 0, 0 }, /* Skylake */ + { X86_VENDOR_INTEL, 6, INTEL_FAM6_SKYLAKE_X, 0, 0 }, { } }; MODULE_DEVICE_TABLE(x86cpu, skx_cpuids); -- cgit v1.2.3 From 9a9260ca926c6e7b6bcfd3c93a1820d86565ff4f Mon Sep 17 00:00:00 2001 From: Piotr Luc Date: Thu, 13 Oct 2016 17:30:59 +0200 Subject: EDAC, sb_edac: Add Knights Mill support Add Knights Mill (KNM) to the list of CPU models supported by sb_edac. Signed-off-by: Piotr Luc Reviewed-by: Dave Hansen Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/20161013153105.2517-6-piotr.luc@intel.com Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 843ac6c351fd..c1ad0eb7d5dd 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -3372,6 +3372,7 @@ static const struct x86_cpu_id sbridge_cpuids[] = { ICPU(INTEL_FAM6_BROADWELL_X, pci_dev_descr_broadwell_table), ICPU(INTEL_FAM6_BROADWELL_XEON_D, pci_dev_descr_broadwell_table), ICPU(INTEL_FAM6_XEON_PHI_KNL, pci_dev_descr_knl_table), + ICPU(INTEL_FAM6_XEON_PHI_KNM, pci_dev_descr_knl_table), { } }; MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids); -- cgit v1.2.3 From 40fa60c8af68640a582f798d26127f02ba122907 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:39 +0100 Subject: drm/i915: Catch premature unpinning of pages Try to catch the violation of unpinning the backing storage whilst still bound to the GPU. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161019101147.17342-5-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 33c44c631bab..6c8a104b42ed 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3181,14 +3181,15 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n) static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { - BUG_ON(obj->pages == NULL); + GEM_BUG_ON(obj->pages == NULL); obj->pages_pin_count++; } static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) { - BUG_ON(obj->pages_pin_count == 0); + GEM_BUG_ON(obj->pages_pin_count == 0); obj->pages_pin_count--; + GEM_BUG_ON(obj->pages_pin_count < obj->bind_count); } enum i915_map_type { -- cgit v1.2.3 From e3f56b2953ec8160629295bc2be0c8d3b8f4d1d3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 18 Oct 2016 14:28:35 +0300 Subject: drm: fix sparse warnings on undeclared symbols in crc debugfs Fixes sparse warnings: drivers/gpu/drm/drm_debugfs_crc.c:118:30: warning: symbol 'drm_crtc_crc_control_fops' was not declared. Should it be static? drivers/gpu/drm/drm_debugfs_crc.c:264:30: warning: symbol 'drm_crtc_crc_data_fops' was not declared. Should it be static? drivers/gpu/drm/drm_debugfs_crc.c:281:5: warning: symbol 'drm_debugfs_crtc_crc_add' was not declared. Should it be static? Fixes: 9edbf1fa600a ("drm: Add API for capturing frame CRCs") Cc: Benjamin Gaignard Cc: Daniel Vetter Cc: Emil Velikov Cc: Tomeu Vizoso Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476790115-28665-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/drm_debugfs_crc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index 4129405d17c0..00e771fb7df2 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -30,6 +30,7 @@ #include #include #include +#include "drm_internal.h" /** * DOC: CRC ABI @@ -115,7 +116,7 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf, return len; } -const struct file_operations drm_crtc_crc_control_fops = { +static const struct file_operations drm_crtc_crc_control_fops = { .owner = THIS_MODULE, .open = crc_control_open, .read = seq_read, @@ -261,7 +262,7 @@ static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf, return LINE_LEN(crc->values_cnt); } -const struct file_operations drm_crtc_crc_data_fops = { +static const struct file_operations drm_crtc_crc_data_fops = { .owner = THIS_MODULE, .open = crtc_crc_open, .read = crtc_crc_read, -- cgit v1.2.3 From 0f9cdd743f7f8d470fff51b11250f02fc554cf1b Mon Sep 17 00:00:00 2001 From: Gustaf Lindström Date: Tue, 4 Oct 2016 17:29:21 +0200 Subject: drm/panel: simple: Add support for Sharp LQ150X1LG11 panels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Sharp 15" LQ150X1LG11 panel is an XGA TFT LCD panel. The simple-panel driver is used to get support for essential functionality of the panel. Signed-off-by: Gustaf Lindström Signed-off-by: Peter Rosin [treding@nvidia.com: change .bpc from 8 to 6] Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 113db3c4a633..76f0ef7e5b7c 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1420,6 +1420,30 @@ static const struct panel_desc sharp_lq123p1jx31 = { }, }; +static const struct drm_display_mode sharp_lq150x1lg11_mode = { + .clock = 71100, + .hdisplay = 1024, + .hsync_start = 1024 + 168, + .hsync_end = 1024 + 168 + 64, + .htotal = 1024 + 168 + 64 + 88, + .vdisplay = 768, + .vsync_start = 768 + 37, + .vsync_end = 768 + 37 + 2, + .vtotal = 768 + 37 + 2 + 8, + .vrefresh = 60, +}; + +static const struct panel_desc sharp_lq150x1lg11 = { + .modes = &sharp_lq150x1lg11_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 304, + .height = 228, + }, + .bus_format = MEDIA_BUS_FMT_RGB565_1X16, +}; + static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = { .clock = 33300, .hdisplay = 800, @@ -1682,6 +1706,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "sharp,lq123p1jx31", .data = &sharp_lq123p1jx31, + }, { + .compatible = "sharp,lq150x1lg11", + .data = &sharp_lq150x1lg11, }, { .compatible = "shelly,sca07010-bfn-lnn", .data = &shelly_sca07010_bfn_lnn, -- cgit v1.2.3 From 7ee933a1d5c47521c2b2842e5d6d29e643fd2e4a Mon Sep 17 00:00:00 2001 From: Haixia Shi Date: Tue, 11 Oct 2016 14:59:16 -0700 Subject: drm/panel: simple: Add support for AUO T215HVN01 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AUO T215HVN01 is a 21.5" FHD (1920x1080) color TFT LCD panel. This panel is used on the Acer Chromebase 21.5-inch All-in-One (DC221HQ). Link to spec: http://www.udmgroup.com/ftp/T215HVN01.0.pdf v2: fix alphabetical order v3: remove minor revision suffix ".0" and add link to spec v4: add dt-binding documentation Signed-off-by: Haixia Shi Tested-by: Haixia Shi Reviewed-by: Stéphane Marchesin Cc: Emil Velikov Cc: Thierry Reding Cc: David Airlie Cc: Rob Herring Cc: Mark Rutland Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Acked-by: Rob Herring Signed-off-by: Thierry Reding --- .../bindings/display/panel/auo,t215hvn01.txt | 7 +++++ drivers/gpu/drm/panel/panel-simple.c | 30 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt b/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt new file mode 100644 index 000000000000..cbd9da3f03b1 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt @@ -0,0 +1,7 @@ +AU Optronics Corporation 21.5" FHD (1920x1080) color TFT LCD panel + +Required properties: +- compatible: should be "auo,t215hvn01" + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 76f0ef7e5b7c..140a0bc01395 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -555,6 +555,33 @@ static const struct panel_desc auo_b133htn01 = { }, }; +static const struct drm_display_mode auo_t215hvn01_mode = { + .clock = 148800, + .hdisplay = 1920, + .hsync_start = 1920 + 88, + .hsync_end = 1920 + 88 + 44, + .htotal = 1920 + 88 + 44 + 148, + .vdisplay = 1080, + .vsync_start = 1080 + 4, + .vsync_end = 1080 + 4 + 5, + .vtotal = 1080 + 4 + 5 + 36, + .vrefresh = 60, +}; + +static const struct panel_desc auo_t215hvn01 = { + .modes = &auo_t215hvn01_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 430, + .height = 270, + }, + .delay = { + .disable = 5, + .unprepare = 1000, + } +}; + static const struct drm_display_mode avic_tm070ddh03_mode = { .clock = 51200, .hdisplay = 1024, @@ -1598,6 +1625,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "auo,b133xtn01", .data = &auo_b133xtn01, + }, { + .compatible = "auo,t215hvn01", + .data = &auo_t215hvn01, }, { .compatible = "avic,tm070ddh03", .data = &avic_tm070ddh03, -- cgit v1.2.3 From 05ec0e4501f7f05ef610070294fcc806ccbbb981 Mon Sep 17 00:00:00 2001 From: Fabien Lahoudere Date: Mon, 17 Oct 2016 11:38:01 +0200 Subject: drm/panel: simple: Add NVD9128 as a simple panel Add New Vision Display 7.0" 800 RGB x 480 TFT LCD panel Signed-off-by: Fabien Lahoudere Acked-by: Rob Herring Signed-off-by: Thierry Reding --- .../devicetree/bindings/display/panel/nvd,9128.txt | 7 ++++++ .../devicetree/bindings/vendor-prefixes.txt | 1 + drivers/gpu/drm/panel/panel-simple.c | 26 ++++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/nvd,9128.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/panel/nvd,9128.txt b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt new file mode 100644 index 000000000000..17bcd017c678 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt @@ -0,0 +1,7 @@ +New Vision Display 7.0" 800 RGB x 480 TFT LCD panel + +Required properties: +- compatible: should be "nvd,9128" + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index f0a48ea78659..d9c51d7f4aac 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -187,6 +187,7 @@ netgear NETGEAR netlogic Broadcom Corporation (formerly NetLogic Microsystems) netxeon Shenzhen Netxeon Technology CO., LTD newhaven Newhaven Display International +nvd New Vision Display nintendo Nintendo nokia Nokia nuvoton Nuvoton Technology Corporation diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 140a0bc01395..659c75941b45 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1191,6 +1191,29 @@ static const struct panel_desc nec_nl4827hc19_05b = { .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE, }; +static const struct drm_display_mode nvd_9128_mode = { + .clock = 29500, + .hdisplay = 800, + .hsync_start = 800 + 130, + .hsync_end = 800 + 130 + 98, + .htotal = 800 + 0 + 130 + 98, + .vdisplay = 480, + .vsync_start = 480 + 10, + .vsync_end = 480 + 10 + 50, + .vtotal = 480 + 0 + 10 + 50, +}; + +static const struct panel_desc nvd_9128 = { + .modes = &nvd_9128_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 156, + .height = 88, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, +}; + static const struct display_timing okaya_rs800480t_7x0gp_timing = { .pixelclock = { 30000000, 30000000, 40000000 }, .hactive = { 800, 800, 800 }, @@ -1706,6 +1729,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "nec,nl4827hc19-05b", .data = &nec_nl4827hc19_05b, + }, { + .compatible = "nvd,9128", + .data = &nvd_9128, }, { .compatible = "okaya,rs800480t-7x0gp", .data = &okaya_rs800480t_7x0gp, -- cgit v1.2.3 From 919b742fb5f4c14a5b171430cd8bdbef75926ad5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 19 Oct 2016 14:09:10 +0200 Subject: dmaengine: st_fdma: fix uninitialized variable access The newly added st_fdma driver introduces a build warning for allmodconfig when we add '-Wmaybe-uninitialized': drivers/dma/st_fdma.c: In function 'st_fdma_probe': drivers/dma/st_fdma.c:777:5: error: 'ret' may be used uninitialized in this function [-Werror=maybe-uninitialized] The warning is correct, though this can't happen in practice as the check is redundant (we don't get to this function if the pointer is NULL). Even if the function were called with a NULL of_node, the check is not needed because of_property_read_u32 can deal with a NULL argument by returning an error. Removing the unnecessary code simplifies the function and avoids the condition that we get the warning for. Fixes: 6b4cd727eaf1 ("dmaengine: st_fdma: Add STMicroelectronics FDMA engine driver support") Signed-off-by: Arnd Bergmann Acked-by: Peter Griffin Signed-off-by: Vinod Koul --- drivers/dma/st_fdma.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c index 515e1d4c43e8..232d3547a6a3 100644 --- a/drivers/dma/st_fdma.c +++ b/drivers/dma/st_fdma.c @@ -720,21 +720,11 @@ static int st_fdma_parse_dt(struct platform_device *pdev, const struct st_fdma_driverdata *drvdata, struct st_fdma_dev *fdev) { - struct device_node *np = pdev->dev.of_node; - int ret; - - if (!np) - goto err; - - ret = of_property_read_u32(np, "dma-channels", &fdev->nr_channels); - if (ret) - goto err; - snprintf(fdev->fw_name, FW_NAME_SIZE, "fdma_%s_%d.elf", drvdata->name, drvdata->id); -err: - return ret; + return of_property_read_u32(pdev->dev.of_node, "dma-channels", + &fdev->nr_channels); } #define FDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ -- cgit v1.2.3 From 0741b819246029a7e53b8edcc5693debd7c00c8f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 19 Oct 2016 12:05:53 +0100 Subject: dmaengine: omap-dma: initialize can_pause to false can_pause is not initialized so it contains garbage. Fix this by setting it to false. Found using static analysis with cppcheck. Signed-off-by: Colin Ian King Signed-off-by: Vinod Koul --- drivers/dma/omap-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index fd6b9e6834ad..15eb8024666b 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -1286,7 +1286,7 @@ static int omap_dma_pause(struct dma_chan *chan) struct omap_dmadev *od = to_omap_dma_dev(chan->device); unsigned long flags; int ret = -EINVAL; - bool can_pause; + bool can_pause = false; spin_lock_irqsave(&od->irq_lock, flags); -- cgit v1.2.3 From b5b809532e7b070374d98c90f8f423c63f3655f5 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Thu, 6 Oct 2016 18:21:29 -0400 Subject: dmaengine: qcom_hidma: remove useless debugfs file removal Since 'commit acc29fb8f792 ("debugfs: ->d_parent is never NULL or negative")', HIDMA object removal is no longer working. This is due to redundant debugfs remove call in hidma_debug_uninit. debugfs_remove_recursive(dmadev->debugfs); debugfs_remove_recursive(dmadev->stats); The first remove is for the directory. Second remove is for the file under the directory. The directory remove makes file remove invalid. Unable to handle kernel NULL pointer dereference at virtual address [] down_write+0x18/0x68 [] debugfs_remove_recursive+0x50/0x1c0 [] hidma_debug_uninit+0x20/0x30 [] hidma_remove+0x48/0x98 [] platform_drv_remove+0x24/0x68 [] __device_release_driver+0x80/0x118 [] device_release_driver+0x24/0x38 [] unbind_store+0xe8/0x110 [] drv_attr_store+0x20/0x30 [] sysfs_kf_write+0x48/0x58 [] kernfs_fop_write+0xb0/0x1d8 [] __vfs_write+0x1c/0x110 [] vfs_write+0xa0/0x1b8 [] SyS_write+0x44/0xa0 [] el0_svc_naked+0x24/0x28 Removing the second line. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma_dbg.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c index fa827e5ffd68..3d83b9962220 100644 --- a/drivers/dma/qcom/hidma_dbg.c +++ b/drivers/dma/qcom/hidma_dbg.c @@ -164,7 +164,6 @@ static const struct file_operations hidma_dma_fops = { void hidma_debug_uninit(struct hidma_dev *dmadev) { debugfs_remove_recursive(dmadev->debugfs); - debugfs_remove_recursive(dmadev->stats); } int hidma_debug_init(struct hidma_dev *dmadev) -- cgit v1.2.3 From 5282c181662c4cef4823cc16b4641d147c52144f Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Fri, 7 Oct 2016 01:25:08 -0400 Subject: of: irq: make of_msi_configure accessible from modules The of_msi_configure routine is only accessible by the built-in kernel drivers. Export this function so that modules can use it too. This function is useful for configuring MSI on child device tree nodes on hierarchical objects. Acked-by: Rob Herring Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/of/irq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 393fea85eb4e..3fda9a32defb 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -697,3 +697,4 @@ void of_msi_configure(struct device *dev, struct device_node *np) dev_set_msi_domain(dev, of_msi_get_domain(dev, np, DOMAIN_BUS_PLATFORM_MSI)); } +EXPORT_SYMBOL_GPL(of_msi_configure); -- cgit v1.2.3 From 9da0be80be6e7855385ec519c7c13576dfed84c0 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Fri, 7 Oct 2016 01:25:09 -0400 Subject: dmaengine: qcom_hidma: configure DMA and MSI for OF Configure the DMA bindings for the device tree based firmware. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma_mgmt.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c index 82f36e466083..185d29c77c22 100644 --- a/drivers/dma/qcom/hidma_mgmt.c +++ b/drivers/dma/qcom/hidma_mgmt.c @@ -375,8 +375,15 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np) ret = PTR_ERR(new_pdev); goto out; } + of_node_get(child); + new_pdev->dev.of_node = child; of_dma_configure(&new_pdev->dev, child); - + /* + * It is assumed that calling of_msi_configure is safe on + * platforms with or without MSI support. + */ + of_msi_configure(&new_pdev->dev, child); + of_node_put(child); kfree(res); res = NULL; } -- cgit v1.2.3 From d3eab504d44803147d94de8f8e1baf3f6f5645f1 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Fri, 7 Oct 2016 01:25:12 -0400 Subject: dmaengine: qcom_hidma: add a common API to setup the interrupt Introducing the hidma_ll_setup_irq function to set up the interrupt type externally from the OS interface. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma.h | 2 ++ drivers/dma/qcom/hidma_ll.c | 27 +++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h index e52e20716303..de6176497524 100644 --- a/drivers/dma/qcom/hidma.h +++ b/drivers/dma/qcom/hidma.h @@ -46,6 +46,7 @@ struct hidma_tre { }; struct hidma_lldev { + bool msi_support; /* flag indicating MSI support */ bool initialized; /* initialized flag */ u8 trch_state; /* trch_state of the device */ u8 evch_state; /* evch_state of the device */ @@ -145,6 +146,7 @@ int hidma_ll_disable(struct hidma_lldev *lldev); int hidma_ll_enable(struct hidma_lldev *llhndl); void hidma_ll_set_transfer_params(struct hidma_lldev *llhndl, u32 tre_ch, dma_addr_t src, dma_addr_t dest, u32 len, u32 flags); +void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi); int hidma_ll_setup(struct hidma_lldev *lldev); struct hidma_lldev *hidma_ll_init(struct device *dev, u32 max_channels, void __iomem *trca, void __iomem *evca, diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index c3a66c9b0ab7..132d29eb9a63 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -680,17 +680,36 @@ int hidma_ll_setup(struct hidma_lldev *lldev) writel(HIDMA_EVRE_SIZE * nr_tres, lldev->evca + HIDMA_EVCA_RING_LEN_REG); - /* support IRQ only for now */ + /* configure interrupts */ + hidma_ll_setup_irq(lldev, lldev->msi_support); + + rc = hidma_ll_enable(lldev); + if (rc) + return rc; + + return rc; +} + +void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi) +{ + u32 val; + + lldev->msi_support = msi; + + /* disable interrupts again after reset */ + writel(0, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG); + writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG); + + /* support IRQ by default */ val = readl(lldev->evca + HIDMA_EVCA_INTCTRL_REG); val &= ~0xF; - val |= 0x1; + if (!lldev->msi_support) + val = val | 0x1; writel(val, lldev->evca + HIDMA_EVCA_INTCTRL_REG); /* clear all pending interrupts and enable them */ writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG); writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG); - - return hidma_ll_enable(lldev); } struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres, -- cgit v1.2.3 From fc737969f645c1cbb1d167604eb7082fe18809c4 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Fri, 7 Oct 2016 01:25:14 -0400 Subject: dmaengine: qcom_hidma: break completion processing on error We try to consume as much successful transfers as possible. Now that we support MSI interrupts, an error interrupt might be observed by another processor while we are finishing the successful ones. Try to abort successful processing if this is the case. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma_ll.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index 132d29eb9a63..e605c9096545 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -291,6 +291,13 @@ static int hidma_handle_tre_completion(struct hidma_lldev *lldev) evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG); num_completed++; + + /* + * An error interrupt might have arrived while we are processing + * the completed interrupt. + */ + if (!hidma_ll_isenabled(lldev)) + break; } if (num_completed) { -- cgit v1.2.3 From 3134e9bdbe9c81a943b2c027a78433d4b0cf50dc Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 19 Oct 2016 11:24:57 +0200 Subject: net: fs_enet: Use net_device_stats from struct net_device Instead of using a private copy of struct net_device_stats in struct fs_enet_private, use stats from struct net_device. Also remove the now unnecessary .ndo_get_stats function. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- .../net/ethernet/freescale/fs_enet/fs_enet-main.c | 43 +++++++++------------- drivers/net/ethernet/freescale/fs_enet/fs_enet.h | 1 - 2 files changed, 18 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 925d1bca6a26..44f50e168703 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -118,22 +118,22 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) { if (sc & BD_ENET_TX_HB) /* No heartbeat */ - fep->stats.tx_heartbeat_errors++; + dev->stats.tx_heartbeat_errors++; if (sc & BD_ENET_TX_LC) /* Late collision */ - fep->stats.tx_window_errors++; + dev->stats.tx_window_errors++; if (sc & BD_ENET_TX_RL) /* Retrans limit */ - fep->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; if (sc & BD_ENET_TX_UN) /* Underrun */ - fep->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; if (sc & BD_ENET_TX_CSL) /* Carrier lost */ - fep->stats.tx_carrier_errors++; + dev->stats.tx_carrier_errors++; if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) { - fep->stats.tx_errors++; + dev->stats.tx_errors++; do_restart = 1; } } else - fep->stats.tx_packets++; + dev->stats.tx_packets++; if (sc & BD_ENET_TX_READY) { dev_warn(fep->dev, @@ -145,7 +145,7 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) * but we eventually sent the packet OK. */ if (sc & BD_ENET_TX_DEF) - fep->stats.collisions++; + dev->stats.collisions++; /* unmap */ if (fep->mapped_as_page[dirtyidx]) @@ -212,19 +212,19 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) */ if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL | BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) { - fep->stats.rx_errors++; + dev->stats.rx_errors++; /* Frame too long or too short. */ if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) - fep->stats.rx_length_errors++; + dev->stats.rx_length_errors++; /* Frame alignment */ if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL)) - fep->stats.rx_frame_errors++; + dev->stats.rx_frame_errors++; /* CRC Error */ if (sc & BD_ENET_RX_CR) - fep->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; /* FIFO overrun */ if (sc & BD_ENET_RX_OV) - fep->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; skbn = fep->rx_skbuff[curidx]; } else { @@ -233,9 +233,9 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) /* * Process the incoming frame. */ - fep->stats.rx_packets++; + dev->stats.rx_packets++; pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */ - fep->stats.rx_bytes += pkt_len + 4; + dev->stats.rx_bytes += pkt_len + 4; if (pkt_len <= fpi->rx_copybreak) { /* +2 to make IP header L1 cache aligned */ @@ -277,7 +277,7 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) received++; netif_receive_skb(skb); } else { - fep->stats.rx_dropped++; + dev->stats.rx_dropped++; skbn = skb; } } @@ -543,7 +543,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) curidx = bdp - fep->tx_bd_base; len = skb->len; - fep->stats.tx_bytes += len; + dev->stats.tx_bytes += len; if (nr_frags) len -= skb->data_len; fep->tx_free -= nr_frags + 1; @@ -619,7 +619,7 @@ static void fs_timeout(struct net_device *dev) unsigned long flags; int wake = 0; - fep->stats.tx_errors++; + dev->stats.tx_errors++; spin_lock_irqsave(&fep->lock, flags); @@ -774,12 +774,6 @@ static int fs_enet_close(struct net_device *dev) return 0; } -static struct net_device_stats *fs_enet_get_stats(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - return &fep->stats; -} - /*************************************************************************/ static void fs_get_drvinfo(struct net_device *dev, @@ -905,7 +899,6 @@ extern void fs_mii_disconnect(struct net_device *dev); static const struct net_device_ops fs_enet_netdev_ops = { .ndo_open = fs_enet_open, .ndo_stop = fs_enet_close, - .ndo_get_stats = fs_enet_get_stats, .ndo_start_xmit = fs_enet_start_xmit, .ndo_tx_timeout = fs_timeout, .ndo_set_rx_mode = fs_set_multicast_list, diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h index fee24c822fad..5ce516c8a62a 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h @@ -137,7 +137,6 @@ struct fs_enet_private { cbd_t __iomem *cur_rx; cbd_t __iomem *cur_tx; int tx_free; - struct net_device_stats stats; struct timer_list phy_timer_list; const struct phy_info *phy; u32 msg_enable; -- cgit v1.2.3 From 1b7794163ab35a06b32b04ff558819ebb684b1c2 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 16 Oct 2016 13:25:47 +0100 Subject: dmaengine: ioatdma: loop for number elements in array chanerr_str Just iterate over the number of elements in array chanerr_str rather than for all 32 bits. This removes the need for a NULL chanerr_str[i] check which could possibly overrun if the upper bits (28..31) of chanerr are set and 27th bit in chanerr is zero. This simplifies the code by removing an if statement and a break. Signed-off-by: Colin Ian King Signed-off-by: Vinod Koul --- drivers/dma/ioat/dma.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 49386ce04bf5..42ff3073d89d 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -66,7 +66,6 @@ static char *chanerr_str[] = { "Result Guard Tag verification Error", "Result Application Tag verification Error", "Result Reference Tag verification Error", - NULL }; static void ioat_eh(struct ioatdma_chan *ioat_chan); @@ -75,13 +74,10 @@ static void ioat_print_chanerrs(struct ioatdma_chan *ioat_chan, u32 chanerr) { int i; - for (i = 0; i < 32; i++) { + for (i = 0; i < ARRAY_SIZE(chanerr_str); i++) { if ((chanerr >> i) & 1) { - if (chanerr_str[i]) { - dev_err(to_dev(ioat_chan), "Err(%d): %s\n", - i, chanerr_str[i]); - } else - break; + dev_err(to_dev(ioat_chan), "Err(%d): %s\n", + i, chanerr_str[i]); } } } -- cgit v1.2.3 From 613a308159e5dd569d4d480ff0387628724926ca Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Oct 2016 15:08:04 +0300 Subject: drm: Fix LSPCON kernel-doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix warnings on building htmldocs. v2: whitespace around '/' (Ville) Fixes: 056996b95686 ("drm: Helper for lspcon in drm_dp_dual_mode") Cc: Rodrigo Vivi Cc: Shashank Sharma Cc: Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1476878884-2370-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/drm_dp_dual_mode_helper.c | 14 +++++++------- include/drm/drm_dp_dual_mode_helper.h | 15 ++++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c index 2624e266abbd..488355bdafb9 100644 --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c @@ -377,9 +377,9 @@ EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name); /** * drm_lspcon_get_mode: Get LSPCON's current mode of operation by - * by reading offset (0x80, 0x41) - * @i2c_adapter: I2C-over-aux adapter - * @current_mode: out vaiable, current lspcon mode of operation + * reading offset (0x80, 0x41) + * @adapter: I2C-over-aux adapter + * @mode: current lspcon mode of operation output variable * * Returns: * 0 on success, sets the current_mode value to appropriate mode @@ -413,10 +413,10 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter, EXPORT_SYMBOL(drm_lspcon_get_mode); /** - * drm_lspcon_change_mode: Change LSPCON's mode of operation by - * by writing offset (0x80, 0x40) - * @i2c_adapter: I2C-over-aux adapter - * @reqd_mode: required mode of operation + * drm_lspcon_set_mode: Change LSPCON's mode of operation by + * writing offset (0x80, 0x40) + * @adapter: I2C-over-aux adapter + * @mode: required mode of operation * * Returns: * 0 on success, -error on failure/timeout diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h index 55677704add8..4c42db81fcb4 100644 --- a/include/drm/drm_dp_dual_mode_helper.h +++ b/include/drm/drm_dp_dual_mode_helper.h @@ -70,12 +70,13 @@ ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter, u8 offset, const void *buffer, size_t size); /** -* enum drm_lspcon_mode -* @lspcon_mode_ls: Level shifter mode of LSPCON -* which drives DP++ to HDMI 1.4 conversion. -* @lspcon_mode_pcon: Protocol converter mode of LSPCON -* which drives DP++ to HDMI 2.0 active conversion. -*/ + * enum drm_lspcon_mode + * @DRM_LSPCON_MODE_INVALID: No LSPCON. + * @DRM_LSPCON_MODE_LS: Level shifter mode of LSPCON + * which drives DP++ to HDMI 1.4 conversion. + * @DRM_LSPCON_MODE_PCON: Protocol converter mode of LSPCON + * which drives DP++ to HDMI 2.0 active conversion. + */ enum drm_lspcon_mode { DRM_LSPCON_MODE_INVALID, DRM_LSPCON_MODE_LS, @@ -90,7 +91,7 @@ enum drm_lspcon_mode { * @DRM_DP_DUAL_MODE_TYPE1_HDMI: Type 1 HDMI adaptor * @DRM_DP_DUAL_MODE_TYPE2_DVI: Type 2 DVI adaptor * @DRM_DP_DUAL_MODE_TYPE2_HDMI: Type 2 HDMI adaptor - * @DRM_DP_DUAL_MODE_TYPE2_LSPCON: Level shifter /protocol converter + * @DRM_DP_DUAL_MODE_LSPCON: Level shifter / protocol converter */ enum drm_dp_dual_mode_type { DRM_DP_DUAL_MODE_NONE, -- cgit v1.2.3 From 8d7c22ac0c036978a072b7e13c607b5402c474e0 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 19 Oct 2016 08:19:44 -0600 Subject: libnvdimm: use generic iostat interfaces nd_iostat_start() and nd_iostat_end() implement the same functionality that generic_start_io_acct() and generic_end_io_acct() already provide. Change nd_iostat_start() and nd_iostat_end() to call the generic iostat interfaces. There is no change in the nd interfaces. Signed-off-by: Toshi Kani Cc: Andrew Morton Cc: Alexander Viro Cc: Dave Chinner Cc: Ross Zwisler Signed-off-by: Dan Williams --- drivers/nvdimm/core.c | 29 ----------------------------- drivers/nvdimm/nd.h | 11 +++++++++-- 2 files changed, 9 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index 7ceba08774b6..9303cfeb8bee 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c @@ -317,35 +317,6 @@ ssize_t nd_sector_size_store(struct device *dev, const char *buf, } } -void __nd_iostat_start(struct bio *bio, unsigned long *start) -{ - struct gendisk *disk = bio->bi_bdev->bd_disk; - const int rw = bio_data_dir(bio); - int cpu = part_stat_lock(); - - *start = jiffies; - part_round_stats(cpu, &disk->part0); - part_stat_inc(cpu, &disk->part0, ios[rw]); - part_stat_add(cpu, &disk->part0, sectors[rw], bio_sectors(bio)); - part_inc_in_flight(&disk->part0, rw); - part_stat_unlock(); -} -EXPORT_SYMBOL(__nd_iostat_start); - -void nd_iostat_end(struct bio *bio, unsigned long start) -{ - struct gendisk *disk = bio->bi_bdev->bd_disk; - unsigned long duration = jiffies - start; - const int rw = bio_data_dir(bio); - int cpu = part_stat_lock(); - - part_stat_add(cpu, &disk->part0, ticks[rw], duration); - part_round_stats(cpu, &disk->part0); - part_dec_in_flight(&disk->part0, rw); - part_stat_unlock(); -} -EXPORT_SYMBOL(nd_iostat_end); - static ssize_t commands_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index d3b2fca8deec..065abf1b8f32 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -377,10 +377,17 @@ static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) if (!blk_queue_io_stat(disk->queue)) return false; - __nd_iostat_start(bio, start); + *start = jiffies; + generic_start_io_acct(bio_data_dir(bio), + bio_sectors(bio), &disk->part0); return true; } -void nd_iostat_end(struct bio *bio, unsigned long start); +static inline void nd_iostat_end(struct bio *bio, unsigned long start) +{ + struct gendisk *disk = bio->bi_bdev->bd_disk; + + generic_end_io_acct(bio_data_dir(bio), &disk->part0, start); +} static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, unsigned int len) { -- cgit v1.2.3 From 42237e393f64d619ed56e17fbf8fd27526485695 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 15 Oct 2016 15:33:52 -0700 Subject: libnvdimm: allow a platform to force enable label support Platforms like QEMU-KVM implement an NFIT table and label DSMs. However, since that environment does not define an aliased configuration, the labels are currently ignored and the kernel registers a single full-sized pmem-namespace per region. Now that the kernel supports sub-divisions of pmem regions the labels have a purpose. Arrange for the labels to be honored when we find an existing / valid namespace index block. Cc: Cc: Haozhong Zhang Cc: Xiao Guangrong Signed-off-by: Dan Williams --- drivers/nvdimm/dimm.c | 2 ++ drivers/nvdimm/dimm_devs.c | 7 +++++++ drivers/nvdimm/nd.h | 1 + 3 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c index 619834e144d1..ee0b412827bf 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c @@ -64,6 +64,8 @@ static int nvdimm_probe(struct device *dev) nd_label_copy(ndd, to_next_namespace_index(ndd), to_current_namespace_index(ndd)); rc = nd_label_reserve_dpa(ndd); + if (ndd->ns_current >= 0) + nvdimm_set_aliasing(dev); nvdimm_bus_unlock(dev); if (rc) diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index d614493ad5ac..0eedc49e0d47 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -184,6 +184,13 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, return rc; } +void nvdimm_set_aliasing(struct device *dev) +{ + struct nvdimm *nvdimm = to_nvdimm(dev); + + nvdimm->flags |= NDD_ALIASING; +} + static void nvdimm_release(struct device *dev) { struct nvdimm *nvdimm = to_nvdimm(dev); diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 065abf1b8f32..35dd75057e16 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -238,6 +238,7 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, void *buf, size_t len); long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, unsigned int len); +void nvdimm_set_aliasing(struct device *dev); struct nd_btt *to_nd_btt(struct device *dev); struct nd_gen_sb { -- cgit v1.2.3 From e687cd19f1cb9d3bbb16146fe7a8740cf836e481 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 19 Oct 2016 13:23:50 +0000 Subject: dmaengine: st_fdma: Fix the error return code in st_fdma_probe() In case of error, the function st_slim_rproc_alloc() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Signed-off-by: Wei Yongjun Acked-by: Peter Griffin Signed-off-by: Vinod Koul --- drivers/dma/st_fdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c index 232d3547a6a3..bfb79bd0c6de 100644 --- a/drivers/dma/st_fdma.c +++ b/drivers/dma/st_fdma.c @@ -792,7 +792,7 @@ static int st_fdma_probe(struct platform_device *pdev) } fdev->slim_rproc = st_slim_rproc_alloc(pdev, fdev->fw_name); - if (!fdev->slim_rproc) { + if (IS_ERR(fdev->slim_rproc)) { ret = PTR_ERR(fdev->slim_rproc); dev_err(&pdev->dev, "slim_rproc_alloc failed (%d)\n", ret); goto err; -- cgit v1.2.3 From 2facc6dacc64f14efc6fb81e2019f48e992166e2 Mon Sep 17 00:00:00 2001 From: Tang Yuantian Date: Sun, 9 Oct 2016 16:51:04 +0800 Subject: ahci: qoriq: added ls1046a platform support Ls1046a is a new introduced soc which supports ATA3.0. Signed-off-by: Tang Yuantian Signed-off-by: Tejun Heo --- drivers/ata/ahci_qoriq.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index 1eba8dff875e..9884c8c6e934 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -46,11 +46,13 @@ #define LS1021A_AXICC_ADDR 0xC0 #define SATA_ECC_DISABLE 0x00020000 +#define LS1046A_SATA_ECC_DIS 0x80000000 enum ahci_qoriq_type { AHCI_LS1021A, AHCI_LS1043A, AHCI_LS2080A, + AHCI_LS1046A, }; struct ahci_qoriq_priv { @@ -63,6 +65,7 @@ static const struct of_device_id ahci_qoriq_of_match[] = { { .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A}, { .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A}, { .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A}, + { .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A}, {}, }; MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match); @@ -175,6 +178,13 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv) writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); break; + + case AHCI_LS1046A: + writel(LS1046A_SATA_ECC_DIS, qpriv->ecc_addr); + writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); + writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); + writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); + break; } return 0; @@ -204,9 +214,9 @@ static int ahci_qoriq_probe(struct platform_device *pdev) qoriq_priv->type = (enum ahci_qoriq_type)of_id->data; - if (qoriq_priv->type == AHCI_LS1021A) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "sata-ecc"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "sata-ecc"); + if (res) { qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res); if (IS_ERR(qoriq_priv->ecc_addr)) return PTR_ERR(qoriq_priv->ecc_addr); -- cgit v1.2.3 From 8e061784b51ec4a4efed0deaafb5bd9725bf5b06 Mon Sep 17 00:00:00 2001 From: Adam Manzanares Date: Mon, 17 Oct 2016 11:27:29 -0700 Subject: ata: Enabling ATA Command Priorities This patch checks to see if an ATA device supports NCQ command priorities. If so and the user has specified an iocontext that indicates IO_PRIO_CLASS_RT then we build a tf with a high priority command. This is done to improve the tail latency of commands that are high priority by passing priority to the device. tj: Removed trivial ata_ncq_prio_enabled() and open-coded the test. Signed-off-by: Adam Manzanares Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 35 ++++++++++++++++++++++++++++++++++- drivers/ata/libata-scsi.c | 6 +++++- drivers/ata/libata.h | 2 +- include/linux/ata.h | 6 ++++++ include/linux/libata.h | 3 +++ 5 files changed, 49 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 223a770f78f3..8346faf63337 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -739,6 +739,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) * @n_block: Number of blocks * @tf_flags: RW/FUA etc... * @tag: tag + * @class: IO priority class * * LOCKING: * None. @@ -753,7 +754,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) */ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, - unsigned int tag) + unsigned int tag, int class) { tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->flags |= tf_flags; @@ -785,6 +786,12 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, tf->device = ATA_LBA; if (tf->flags & ATA_TFLAG_FUA) tf->device |= 1 << 7; + + if (dev->flags & ATA_DFLAG_NCQ_PRIO) { + if (class == IOPRIO_CLASS_RT) + tf->hob_nsect |= ATA_PRIO_HIGH << + ATA_SHIFT_PRIO; + } } else if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; @@ -2156,6 +2163,30 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev) } } +static void ata_dev_config_ncq_prio(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + unsigned int err_mask; + + err_mask = ata_read_log_page(dev, + ATA_LOG_SATA_ID_DEV_DATA, + ATA_LOG_SATA_SETTINGS, + ap->sector_buf, + 1); + if (err_mask) { + ata_dev_dbg(dev, + "failed to get Identify Device data, Emask 0x%x\n", + err_mask); + return; + } + + if (ap->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET] & BIT(3)) + dev->flags |= ATA_DFLAG_NCQ_PRIO; + else + ata_dev_dbg(dev, "SATA page does not support priority\n"); + +} + static int ata_dev_config_ncq(struct ata_device *dev, char *desc, size_t desc_sz) { @@ -2205,6 +2236,8 @@ static int ata_dev_config_ncq(struct ata_device *dev, ata_dev_config_ncq_send_recv(dev); if (ata_id_has_ncq_non_data(dev->id)) ata_dev_config_ncq_non_data(dev); + if (ata_id_has_ncq_prio(dev->id)) + ata_dev_config_ncq_prio(dev); } return 0; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9cceb4a875a5..2bccc3c7de48 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -50,6 +50,7 @@ #include #include #include +#include #include "libata.h" #include "libata-transport.h" @@ -1755,6 +1756,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) { struct scsi_cmnd *scmd = qc->scsicmd; const u8 *cdb = scmd->cmnd; + struct request *rq = scmd->request; + int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq)); unsigned int tf_flags = 0; u64 block; u32 n_block; @@ -1821,7 +1824,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) qc->nbytes = n_block * scmd->device->sector_size; rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, - qc->tag); + qc->tag, class); + if (likely(rc == 0)) return 0; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 3b301a48007c..8f3a5596dd67 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -66,7 +66,7 @@ extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, - unsigned int tag); + unsigned int tag, int class); extern u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev); extern unsigned ata_exec_internal(struct ata_device *dev, diff --git a/include/linux/ata.h b/include/linux/ata.h index fdb180367ba1..af6859b3a93d 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -348,6 +348,7 @@ enum { ATA_LOG_DEVSLP_DETO = 0x01, ATA_LOG_DEVSLP_VALID = 0x07, ATA_LOG_DEVSLP_VALID_MASK = 0x80, + ATA_LOG_NCQ_PRIO_OFFSET = 0x09, /* NCQ send and receive log */ ATA_LOG_NCQ_SEND_RECV_SUBCMDS_OFFSET = 0x00, @@ -940,6 +941,11 @@ static inline bool ata_id_has_ncq_non_data(const u16 *id) return id[ATA_ID_SATA_CAPABILITY_2] & BIT(5); } +static inline bool ata_id_has_ncq_prio(const u16 *id) +{ + return id[ATA_ID_SATA_CAPABILITY] & BIT(12); +} + static inline bool ata_id_has_trim(const u16 *id) { if (ata_id_major_version(id) >= 7 && diff --git a/include/linux/libata.h b/include/linux/libata.h index 616eef4d81ea..90b69a6293a3 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -166,6 +166,7 @@ enum { ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */ ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */ ATA_DFLAG_NCQ_SEND_RECV = (1 << 19), /* device supports NCQ SEND and RECV */ + ATA_DFLAG_NCQ_PRIO = (1 << 20), /* device supports NCQ priority */ ATA_DFLAG_INIT_MASK = (1 << 24) - 1, ATA_DFLAG_DETACH = (1 << 24), @@ -342,7 +343,9 @@ enum { ATA_SHIFT_PIO = 0, ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_NR_PIO_MODES, ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES, + ATA_SHIFT_PRIO = 6, + ATA_PRIO_HIGH = 2, /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, -- cgit v1.2.3 From 84f95243b5439a20c33837075b88926bfa00c4ec Mon Sep 17 00:00:00 2001 From: Adam Manzanares Date: Mon, 17 Oct 2016 11:27:30 -0700 Subject: ata: ATA Command Priority Disabled By Default Add a sysfs entry to turn on priority information being passed to a ATA device. By default this feature is turned off. This patch depends on ata: Enabling ATA Command Priorities tj: Renamed ncq_prio_on to ncq_prio_enable and removed trivial ata_ncq_prio_on() and open-coded the test. Signed-off-by: Adam Manzanares Signed-off-by: Tejun Heo --- drivers/ata/libahci.c | 1 + drivers/ata/libata-core.c | 3 ++- drivers/ata/libata-scsi.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 2 ++ 4 files changed, 73 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 0d028ead99e8..ee7db3119b18 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -140,6 +140,7 @@ EXPORT_SYMBOL_GPL(ahci_shost_attrs); struct device_attribute *ahci_sdev_attrs[] = { &dev_attr_sw_activity, &dev_attr_unload_heads, + &dev_attr_ncq_prio_enable, NULL }; EXPORT_SYMBOL_GPL(ahci_sdev_attrs); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 8346faf63337..b294339159a4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -787,7 +787,8 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, if (tf->flags & ATA_TFLAG_FUA) tf->device |= 1 << 7; - if (dev->flags & ATA_DFLAG_NCQ_PRIO) { + if ((dev->flags & ATA_DFLAG_NCQ_PRIO) && + (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE)) { if (class == IOPRIO_CLASS_RT) tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2bccc3c7de48..87597a3f6149 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -271,6 +271,73 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, ata_scsi_park_show, ata_scsi_park_store); EXPORT_SYMBOL_GPL(dev_attr_unload_heads); +static ssize_t ata_ncq_prio_enable_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(device); + struct ata_port *ap; + struct ata_device *dev; + bool ncq_prio_enable; + int rc = 0; + + ap = ata_shost_to_port(sdev->host); + + spin_lock_irq(ap->lock); + dev = ata_scsi_find_dev(ap, sdev); + if (!dev) { + rc = -ENODEV; + goto unlock; + } + + ncq_prio_enable = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE; + +unlock: + spin_unlock_irq(ap->lock); + + return rc ? rc : snprintf(buf, 20, "%u\n", ncq_prio_enable); +} + +static ssize_t ata_ncq_prio_enable_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct scsi_device *sdev = to_scsi_device(device); + struct ata_port *ap; + struct ata_device *dev; + long int input; + unsigned long flags; + int rc; + + rc = kstrtol(buf, 10, &input); + if (rc) + return rc; + if ((input < 0) || (input > 1)) + return -EINVAL; + + ap = ata_shost_to_port(sdev->host); + + spin_lock_irqsave(ap->lock, flags); + dev = ata_scsi_find_dev(ap, sdev); + if (unlikely(!dev)) { + rc = -ENODEV; + goto unlock; + } + + if (input) + dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLE; + else + dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; + +unlock: + spin_unlock_irqrestore(ap->lock, flags); + + return rc ? rc : len; +} + +DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR, + ata_ncq_prio_enable_show, ata_ncq_prio_enable_store); +EXPORT_SYMBOL_GPL(dev_attr_ncq_prio_enable); + void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) { @@ -402,6 +469,7 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity); struct device_attribute *ata_common_sdev_attrs[] = { &dev_attr_unload_heads, + &dev_attr_ncq_prio_enable, NULL }; EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); diff --git a/include/linux/libata.h b/include/linux/libata.h index 90b69a6293a3..c170be548b7f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -167,6 +167,7 @@ enum { ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */ ATA_DFLAG_NCQ_SEND_RECV = (1 << 19), /* device supports NCQ SEND and RECV */ ATA_DFLAG_NCQ_PRIO = (1 << 20), /* device supports NCQ priority */ + ATA_DFLAG_NCQ_PRIO_ENABLE = (1 << 21), /* Priority cmds sent to dev */ ATA_DFLAG_INIT_MASK = (1 << 24) - 1, ATA_DFLAG_DETACH = (1 << 24), @@ -545,6 +546,7 @@ typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes) extern struct device_attribute dev_attr_link_power_management_policy; extern struct device_attribute dev_attr_unload_heads; +extern struct device_attribute dev_attr_ncq_prio_enable; extern struct device_attribute dev_attr_em_message_type; extern struct device_attribute dev_attr_em_message; extern struct device_attribute dev_attr_sw_activity; -- cgit v1.2.3 From 38fac8bffca212e932f306c4a27e5b35d3c29419 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 19:05:26 +0100 Subject: drm/i915: STOP_MACHINE is no more, stop selecting it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The STOP_MACHINE kconfig symbol was removed upstream after making stop_machine() always work, commit 86fffe4a61dd ("kernel: remove stop_machine() Kconfig dependency"), and was removed from i915's Kconfig in commit 21fabbebff0e ("drm/i915: Remove select to deleted STOP_MACHINE from Kconfig"). However, I accidentally reintroduced the select when rebasing an older commit that also was dependent upon a working stop_machine. Fixes: 9f267eb8d2ea ("drm/i915: Stop the machine whilst capturing...") Reported-by: Valentin Rothberg Signed-off-by: Chris Wilson Cc: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161019180635.27459-1-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 6aedc96aa412..1c1b19ccb92f 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -4,7 +4,6 @@ config DRM_I915 depends on X86 && PCI select INTEL_GTT select INTERVAL_TREE - select STOP_MACHINE # we need shmfs for the swappable backing store, and in particular # the shmem_readpage() which depends upon tmpfs select SHMEM -- cgit v1.2.3 From 0f6e87613c3234c6350aaa971bd9434d29405302 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 19 Oct 2016 13:47:52 +0000 Subject: net: arc_emac: use dev_kfree_skb_any instead of dev_kfree_skb Replace dev_kfree_skb with dev_kfree_skb_any in arc_emac_tx() which can be called from hard irq context (netpoll) and from other contexts. arc_emac_tx() only frees skbs that it has dropped. This is detected by Coccinelle semantic patch. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/arc/emac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index b0da9693f28a..95d8b3ea7bc3 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -633,7 +633,7 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) if (unlikely(dma_mapping_error(&ndev->dev, addr))) { stats->tx_dropped++; stats->tx_errors++; - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr); -- cgit v1.2.3 From b410d13e10db86832026f6ef1a9a7b4ae1c48c19 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 19 Oct 2016 09:56:57 -0500 Subject: net: macb: Use variables with defaults for tx/rx ring sizes instead of hardcoded values The macb driver hardcoded the tx/rx ring sizes. This made it impossible to change the sizes at run time. Add tx_ring_size, and rx_ring_size variables to macb object, which are initilized with default vales during macb_init. Change all references to RX_RING_SIZE and TX_RING_SIZE to their respective replacements. Signed-off-by: Zach Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 114 ++++++++++++++++++++---------------- drivers/net/ethernet/cadence/macb.h | 3 + 2 files changed, 65 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index e83781ad4477..644975da2857 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -37,14 +37,16 @@ #define MACB_RX_BUFFER_SIZE 128 #define RX_BUFFER_MULTIPLE 64 /* bytes */ -#define RX_RING_SIZE 512 /* must be power of 2 */ -#define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE) +#define DEFAULT_RX_RING_SIZE 512 /* must be power of 2 */ +#define RX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \ + * (bp)->rx_ring_size) -#define TX_RING_SIZE 128 /* must be power of 2 */ -#define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE) +#define DEFAULT_TX_RING_SIZE 512 /* must be power of 2 */ +#define TX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \ + * (bp)->tx_ring_size) /* level of occupied TX descriptors under which we wake up TX process */ -#define MACB_TX_WAKEUP_THRESH (3 * TX_RING_SIZE / 4) +#define MACB_TX_WAKEUP_THRESH(bp) (3 * (bp)->tx_ring_size / 4) #define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \ | MACB_BIT(ISR_ROVR)) @@ -67,45 +69,47 @@ #define MACB_HALT_TIMEOUT 1230 /* Ring buffer accessors */ -static unsigned int macb_tx_ring_wrap(unsigned int index) +static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index) { - return index & (TX_RING_SIZE - 1); + return index & (bp->tx_ring_size - 1); } static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue, unsigned int index) { - return &queue->tx_ring[macb_tx_ring_wrap(index)]; + return &queue->tx_ring[macb_tx_ring_wrap(queue->bp, index)]; } static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue, unsigned int index) { - return &queue->tx_skb[macb_tx_ring_wrap(index)]; + return &queue->tx_skb[macb_tx_ring_wrap(queue->bp, index)]; } static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index) { dma_addr_t offset; - offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc); + offset = macb_tx_ring_wrap(queue->bp, index) * + sizeof(struct macb_dma_desc); return queue->tx_ring_dma + offset; } -static unsigned int macb_rx_ring_wrap(unsigned int index) +static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index) { - return index & (RX_RING_SIZE - 1); + return index & (bp->rx_ring_size - 1); } static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index) { - return &bp->rx_ring[macb_rx_ring_wrap(index)]; + return &bp->rx_ring[macb_rx_ring_wrap(bp, index)]; } static void *macb_rx_buffer(struct macb *bp, unsigned int index) { - return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index); + return bp->rx_buffers + bp->rx_buffer_size * + macb_rx_ring_wrap(bp, index); } /* I/O accessors */ @@ -608,7 +612,8 @@ static void macb_tx_error_task(struct work_struct *work) */ if (!(ctrl & MACB_BIT(TX_BUF_EXHAUSTED))) { netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n", - macb_tx_ring_wrap(tail), skb->data); + macb_tx_ring_wrap(bp, tail), + skb->data); bp->stats.tx_packets++; bp->stats.tx_bytes += skb->len; } @@ -700,7 +705,8 @@ static void macb_tx_interrupt(struct macb_queue *queue) /* First, update TX stats if needed */ if (skb) { netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n", - macb_tx_ring_wrap(tail), skb->data); + macb_tx_ring_wrap(bp, tail), + skb->data); bp->stats.tx_packets++; bp->stats.tx_bytes += skb->len; } @@ -720,7 +726,7 @@ static void macb_tx_interrupt(struct macb_queue *queue) queue->tx_tail = tail; if (__netif_subqueue_stopped(bp->dev, queue_index) && CIRC_CNT(queue->tx_head, queue->tx_tail, - TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH) + bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp)) netif_wake_subqueue(bp->dev, queue_index); } @@ -731,8 +737,8 @@ static void gem_rx_refill(struct macb *bp) dma_addr_t paddr; while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, - RX_RING_SIZE) > 0) { - entry = macb_rx_ring_wrap(bp->rx_prepared_head); + bp->rx_ring_size) > 0) { + entry = macb_rx_ring_wrap(bp, bp->rx_prepared_head); /* Make hw descriptor updates visible to CPU */ rmb(); @@ -759,7 +765,7 @@ static void gem_rx_refill(struct macb *bp) bp->rx_skbuff[entry] = skb; - if (entry == RX_RING_SIZE - 1) + if (entry == bp->rx_ring_size - 1) paddr |= MACB_BIT(RX_WRAP); macb_set_addr(&(bp->rx_ring[entry]), paddr); bp->rx_ring[entry].ctrl = 0; @@ -813,7 +819,7 @@ static int gem_rx(struct macb *bp, int budget) dma_addr_t addr; bool rxused; - entry = macb_rx_ring_wrap(bp->rx_tail); + entry = macb_rx_ring_wrap(bp, bp->rx_tail); desc = &bp->rx_ring[entry]; /* Make hw descriptor updates visible to CPU */ @@ -895,8 +901,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, len = desc->ctrl & bp->rx_frm_len_mask; netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n", - macb_rx_ring_wrap(first_frag), - macb_rx_ring_wrap(last_frag), len); + macb_rx_ring_wrap(bp, first_frag), + macb_rx_ring_wrap(bp, last_frag), len); /* The ethernet header starts NET_IP_ALIGN bytes into the * first buffer. Since the header is 14 bytes, this makes the @@ -969,12 +975,12 @@ static inline void macb_init_rx_ring(struct macb *bp) int i; addr = bp->rx_buffers_dma; - for (i = 0; i < RX_RING_SIZE; i++) { + for (i = 0; i < bp->rx_ring_size; i++) { bp->rx_ring[i].addr = addr; bp->rx_ring[i].ctrl = 0; addr += bp->rx_buffer_size; } - bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); + bp->rx_ring[bp->rx_ring_size - 1].addr |= MACB_BIT(RX_WRAP); } static int macb_rx(struct macb *bp, int budget) @@ -1228,7 +1234,7 @@ static unsigned int macb_tx_map(struct macb *bp, offset = 0; while (len) { size = min(len, bp->max_tx_length); - entry = macb_tx_ring_wrap(tx_head); + entry = macb_tx_ring_wrap(bp, tx_head); tx_skb = &queue->tx_skb[entry]; mapping = dma_map_single(&bp->pdev->dev, @@ -1257,7 +1263,7 @@ static unsigned int macb_tx_map(struct macb *bp, offset = 0; while (len) { size = min(len, bp->max_tx_length); - entry = macb_tx_ring_wrap(tx_head); + entry = macb_tx_ring_wrap(bp, tx_head); tx_skb = &queue->tx_skb[entry]; mapping = skb_frag_dma_map(&bp->pdev->dev, frag, @@ -1295,14 +1301,14 @@ static unsigned int macb_tx_map(struct macb *bp, * to set the end of TX queue */ i = tx_head; - entry = macb_tx_ring_wrap(i); + entry = macb_tx_ring_wrap(bp, i); ctrl = MACB_BIT(TX_USED); desc = &queue->tx_ring[entry]; desc->ctrl = ctrl; do { i--; - entry = macb_tx_ring_wrap(i); + entry = macb_tx_ring_wrap(bp, i); tx_skb = &queue->tx_skb[entry]; desc = &queue->tx_ring[entry]; @@ -1311,7 +1317,7 @@ static unsigned int macb_tx_map(struct macb *bp, ctrl |= MACB_BIT(TX_LAST); eof = 0; } - if (unlikely(entry == (TX_RING_SIZE - 1))) + if (unlikely(entry == (bp->tx_ring_size - 1))) ctrl |= MACB_BIT(TX_WRAP); /* Set TX buffer descriptor */ @@ -1388,7 +1394,8 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&bp->lock, flags); /* This is a hard error, log it. */ - if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < count) { + if (CIRC_SPACE(queue->tx_head, queue->tx_tail, + bp->tx_ring_size) < count) { netif_stop_subqueue(dev, queue_index); spin_unlock_irqrestore(&bp->lock, flags); netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n", @@ -1414,7 +1421,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); - if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < 1) + if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1) netif_stop_subqueue(dev, queue_index); unlock: @@ -1453,7 +1460,7 @@ static void gem_free_rx_buffers(struct macb *bp) if (!bp->rx_skbuff) return; - for (i = 0; i < RX_RING_SIZE; i++) { + for (i = 0; i < bp->rx_ring_size; i++) { skb = bp->rx_skbuff[i]; if (!skb) @@ -1478,7 +1485,7 @@ static void macb_free_rx_buffers(struct macb *bp) { if (bp->rx_buffers) { dma_free_coherent(&bp->pdev->dev, - RX_RING_SIZE * bp->rx_buffer_size, + bp->rx_ring_size * bp->rx_buffer_size, bp->rx_buffers, bp->rx_buffers_dma); bp->rx_buffers = NULL; } @@ -1491,7 +1498,7 @@ static void macb_free_consistent(struct macb *bp) bp->macbgem_ops.mog_free_rx_buffers(bp); if (bp->rx_ring) { - dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES, + dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES(bp), bp->rx_ring, bp->rx_ring_dma); bp->rx_ring = NULL; } @@ -1500,7 +1507,7 @@ static void macb_free_consistent(struct macb *bp) kfree(queue->tx_skb); queue->tx_skb = NULL; if (queue->tx_ring) { - dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES, + dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES(bp), queue->tx_ring, queue->tx_ring_dma); queue->tx_ring = NULL; } @@ -1511,14 +1518,14 @@ static int gem_alloc_rx_buffers(struct macb *bp) { int size; - size = RX_RING_SIZE * sizeof(struct sk_buff *); + size = bp->rx_ring_size * sizeof(struct sk_buff *); bp->rx_skbuff = kzalloc(size, GFP_KERNEL); if (!bp->rx_skbuff) return -ENOMEM; - - netdev_dbg(bp->dev, - "Allocated %d RX struct sk_buff entries at %p\n", - RX_RING_SIZE, bp->rx_skbuff); + else + netdev_dbg(bp->dev, + "Allocated %d RX struct sk_buff entries at %p\n", + bp->rx_ring_size, bp->rx_skbuff); return 0; } @@ -1526,7 +1533,7 @@ static int macb_alloc_rx_buffers(struct macb *bp) { int size; - size = RX_RING_SIZE * bp->rx_buffer_size; + size = bp->rx_ring_size * bp->rx_buffer_size; bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size, &bp->rx_buffers_dma, GFP_KERNEL); if (!bp->rx_buffers) @@ -1545,7 +1552,7 @@ static int macb_alloc_consistent(struct macb *bp) int size; for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { - size = TX_RING_BYTES; + size = TX_RING_BYTES(bp); queue->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size, &queue->tx_ring_dma, GFP_KERNEL); @@ -1556,13 +1563,13 @@ static int macb_alloc_consistent(struct macb *bp) q, size, (unsigned long)queue->tx_ring_dma, queue->tx_ring); - size = TX_RING_SIZE * sizeof(struct macb_tx_skb); + size = bp->tx_ring_size * sizeof(struct macb_tx_skb); queue->tx_skb = kmalloc(size, GFP_KERNEL); if (!queue->tx_skb) goto out_err; } - size = RX_RING_BYTES; + size = RX_RING_BYTES(bp); bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size, &bp->rx_ring_dma, GFP_KERNEL); if (!bp->rx_ring) @@ -1588,11 +1595,11 @@ static void gem_init_rings(struct macb *bp) int i; for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { - for (i = 0; i < TX_RING_SIZE; i++) { - macb_set_addr(&(queue->tx_ring[i]), 0); + for (i = 0; i < bp->tx_ring_size; i++) { + queue->tx_ring[i].addr = 0; queue->tx_ring[i].ctrl = MACB_BIT(TX_USED); } - queue->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP); + queue->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP); queue->tx_head = 0; queue->tx_tail = 0; } @@ -1609,13 +1616,13 @@ static void macb_init_rings(struct macb *bp) macb_init_rx_ring(bp); - for (i = 0; i < TX_RING_SIZE; i++) { + for (i = 0; i < bp->tx_ring_size; i++) { bp->queues[0].tx_ring[i].addr = 0; bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED); } bp->queues[0].tx_head = 0; bp->queues[0].tx_tail = 0; - bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP); + bp->queues[0].tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP); bp->rx_tail = 0; } @@ -2148,8 +2155,8 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs, regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1)) | MACB_GREGS_VERSION; - tail = macb_tx_ring_wrap(bp->queues[0].tx_tail); - head = macb_tx_ring_wrap(bp->queues[0].tx_head); + tail = macb_tx_ring_wrap(bp, bp->queues[0].tx_tail); + head = macb_tx_ring_wrap(bp, bp->queues[0].tx_head); regs_buff[0] = macb_readl(bp, NCR); regs_buff[1] = macb_or_gem_readl(bp, NCFGR); @@ -2419,6 +2426,9 @@ static int macb_init(struct platform_device *pdev) int err; u32 val; + bp->tx_ring_size = DEFAULT_TX_RING_SIZE; + bp->rx_ring_size = DEFAULT_RX_RING_SIZE; + /* set the queue register mapping once for all: queue0 has a special * register mapping but we don't want to test the queue index then * compute the corresponding register offset at run time. diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 8bed4b52fef5..1216950c97d1 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -811,6 +811,9 @@ struct macb { void *rx_buffers; size_t rx_buffer_size; + unsigned int rx_ring_size; + unsigned int tx_ring_size; + unsigned int num_queues; unsigned int queue_mask; struct macb_queue queues[MACB_MAX_QUEUES]; -- cgit v1.2.3 From 8441bb33beaf58a67a7664dddede68c5860acf74 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 19 Oct 2016 09:56:58 -0500 Subject: net: macb: Add ethtool get_ringparam and set_ringparam functionality Some applications want to tune the size of the macb rx/tx ring buffers. The ethtool set_ringparam function is the standard way of doing it. Signed-off-by: Zach Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 644975da2857..e1847ce6308d 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -37,11 +37,16 @@ #define MACB_RX_BUFFER_SIZE 128 #define RX_BUFFER_MULTIPLE 64 /* bytes */ + #define DEFAULT_RX_RING_SIZE 512 /* must be power of 2 */ +#define MIN_RX_RING_SIZE 64 +#define MAX_RX_RING_SIZE 8192 #define RX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \ * (bp)->rx_ring_size) #define DEFAULT_TX_RING_SIZE 512 /* must be power of 2 */ +#define MIN_TX_RING_SIZE 64 +#define MAX_TX_RING_SIZE 4096 #define TX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \ * (bp)->tx_ring_size) @@ -2211,6 +2216,56 @@ static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) return 0; } +static void macb_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct macb *bp = netdev_priv(netdev); + + ring->rx_max_pending = MAX_RX_RING_SIZE; + ring->tx_max_pending = MAX_TX_RING_SIZE; + + ring->rx_pending = bp->rx_ring_size; + ring->tx_pending = bp->tx_ring_size; +} + +static int macb_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct macb *bp = netdev_priv(netdev); + u32 new_rx_size, new_tx_size; + unsigned int reset = 0; + + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + + new_rx_size = clamp_t(u32, ring->rx_pending, + MIN_RX_RING_SIZE, MAX_RX_RING_SIZE); + new_rx_size = roundup_pow_of_two(new_rx_size); + + new_tx_size = clamp_t(u32, ring->tx_pending, + MIN_TX_RING_SIZE, MAX_TX_RING_SIZE); + new_tx_size = roundup_pow_of_two(new_tx_size); + + if ((new_tx_size == bp->tx_ring_size) && + (new_rx_size == bp->rx_ring_size)) { + /* nothing to do */ + return 0; + } + + if (netif_running(bp->dev)) { + reset = 1; + macb_close(bp->dev); + } + + bp->rx_ring_size = new_rx_size; + bp->tx_ring_size = new_tx_size; + + if (reset) + macb_open(bp->dev); + + return 0; +} + static const struct ethtool_ops macb_ethtool_ops = { .get_regs_len = macb_get_regs_len, .get_regs = macb_get_regs, @@ -2220,6 +2275,8 @@ static const struct ethtool_ops macb_ethtool_ops = { .set_wol = macb_set_wol, .get_link_ksettings = phy_ethtool_get_link_ksettings, .set_link_ksettings = phy_ethtool_set_link_ksettings, + .get_ringparam = macb_get_ringparam, + .set_ringparam = macb_set_ringparam, }; static const struct ethtool_ops gem_ethtool_ops = { @@ -2232,6 +2289,8 @@ static const struct ethtool_ops gem_ethtool_ops = { .get_sset_count = gem_get_sset_count, .get_link_ksettings = phy_ethtool_get_link_ksettings, .set_link_ksettings = phy_ethtool_set_link_ksettings, + .get_ringparam = macb_get_ringparam, + .set_ringparam = macb_set_ringparam, }; static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -- cgit v1.2.3 From d8c0fafcbd68eb3506fec3638e7d77a1a55b1121 Mon Sep 17 00:00:00 2001 From: "cpaul@redhat.com" Date: Tue, 18 Oct 2016 16:09:49 -0200 Subject: drm/i915/gen9: Get rid of redundant watermark values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we've make skl_wm_levels make a little more sense, we can remove all of the redundant wm information. Up until now we'd been storing two copies of all of the skl watermarks: one being the skl_pipe_wm structs, the other being the global wm struct in drm_i915_private containing the raw register values. This is confusing and problematic, since it means we're prone to accidentally letting the two copies go out of sync. So, get rid of all of the functions responsible for computing the register values and just use a single helper, skl_write_wm_level(), to convert and write the new watermarks on the fly. Changes since v1: - Fixup skl_write_wm_level() - Fixup skl_wm_level_from_reg_val() - Don't forget to copy *active to intel_crtc->wm.active.skl Changes since v2: - Fix usage of wrong cstate Changes since v3 (by Paulo): - Rebase Reviewed-by: Maarten Lankhorst Reviewed-by: Paulo Zanoni (v2) Cc: Ville Syrjälä Cc: Matt Roper Cc: Paulo Zanoni Signed-off-by: Lyude Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1476814189-6062-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 - drivers/gpu/drm/i915/intel_display.c | 14 ++- drivers/gpu/drm/i915/intel_drv.h | 6 +- drivers/gpu/drm/i915/intel_pm.c | 203 ++++++++++++----------------------- drivers/gpu/drm/i915/intel_sprite.c | 8 +- 5 files changed, 90 insertions(+), 143 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6c8a104b42ed..b339c916f7a9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1648,8 +1648,6 @@ struct skl_ddb_allocation { struct skl_wm_values { unsigned dirty_pipes; struct skl_ddb_allocation ddb; - uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; - uint32_t plane_trans[I915_MAX_PIPES][I915_MAX_PLANES]; }; struct skl_wm_level { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9395878abc56..0e18cf479328 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3385,6 +3385,8 @@ static void skylake_update_primary_plane(struct drm_plane *plane, struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_framebuffer *fb = plane_state->base.fb; const struct skl_wm_values *wm = &dev_priv->wm.skl_results; + const struct skl_plane_wm *p_wm = + &crtc_state->wm.skl.optimal.planes[0]; int pipe = intel_crtc->pipe; u32 plane_ctl; unsigned int rotation = plane_state->base.rotation; @@ -3421,7 +3423,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane, intel_crtc->adjusted_y = src_y; if (wm->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) - skl_write_plane_wm(intel_crtc, wm, 0); + skl_write_plane_wm(intel_crtc, p_wm, &wm->ddb, 0); I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); I915_WRITE(PLANE_OFFSET(pipe, 0), (src_y << 16) | src_x); @@ -3455,6 +3457,8 @@ static void skylake_disable_primary_plane(struct drm_plane *primary, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + const struct skl_plane_wm *p_wm = &cstate->wm.skl.optimal.planes[0]; int pipe = intel_crtc->pipe; /* @@ -3462,7 +3466,8 @@ static void skylake_disable_primary_plane(struct drm_plane *primary, * plane's visiblity isn't actually changing neither is its watermarks. */ if (!crtc->primary->state->visible) - skl_write_plane_wm(intel_crtc, &dev_priv->wm.skl_results, 0); + skl_write_plane_wm(intel_crtc, p_wm, + &dev_priv->wm.skl_results.ddb, 0); I915_WRITE(PLANE_CTL(pipe, 0), 0); I915_WRITE(PLANE_SURF(pipe, 0), 0); @@ -10833,12 +10838,15 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); const struct skl_wm_values *wm = &dev_priv->wm.skl_results; + const struct skl_plane_wm *p_wm = + &cstate->wm.skl.optimal.planes[PLANE_CURSOR]; int pipe = intel_crtc->pipe; uint32_t cntl = 0; if (INTEL_GEN(dev_priv) >= 9 && wm->dirty_pipes & drm_crtc_mask(crtc)) - skl_write_cursor_wm(intel_crtc, wm); + skl_write_cursor_wm(intel_crtc, p_wm, &wm->ddb); if (plane_state && plane_state->base.visible) { cntl = MCURSOR_GAMMA_ENABLE; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5760420ace61..a158d7e7edae 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1773,9 +1773,11 @@ bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, struct intel_crtc *intel_crtc); void skl_write_cursor_wm(struct intel_crtc *intel_crtc, - const struct skl_wm_values *wm); + const struct skl_plane_wm *wm, + const struct skl_ddb_allocation *ddb); void skl_write_plane_wm(struct intel_crtc *intel_crtc, - const struct skl_wm_values *wm, + const struct skl_plane_wm *wm, + const struct skl_ddb_allocation *ddb, int plane); uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); bool ilk_disable_lp_wm(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 48d2b71d5e11..84e3272e5136 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3020,8 +3020,10 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct intel_crtc *crtc; struct intel_plane *plane; + struct intel_crtc_state *cstate; + struct skl_plane_wm *wm; enum pipe pipe; - int level, id, latency; + int level, latency; if (!intel_has_sagv(dev_priv)) return false; @@ -3040,20 +3042,21 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) /* Since we're now guaranteed to only have one active CRTC... */ pipe = ffs(intel_state->active_crtcs) - 1; crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + cstate = to_intel_crtc_state(crtc->base.state); if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) return false; for_each_intel_plane_on_crtc(dev, crtc, plane) { - id = skl_wm_plane_id(plane); + wm = &cstate->wm.skl.optimal.planes[skl_wm_plane_id(plane)]; /* Skip this plane if it's not enabled */ - if (intel_state->wm_results.plane[pipe][id][0] == 0) + if (!wm->wm[0].plane_en) continue; /* Find the highest enabled wm level for this plane */ for (level = ilk_wm_max_level(dev_priv); - intel_state->wm_results.plane[pipe][id][level] == 0; --level) + !wm->wm[level].plane_en; --level) { } latency = dev_priv->wm.skl_latency[level]; @@ -3814,66 +3817,6 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, return 0; } -static void skl_compute_wm_results(struct drm_device *dev, - struct skl_pipe_wm *p_wm, - struct skl_wm_values *r, - struct intel_crtc *intel_crtc) -{ - int level, max_level = ilk_wm_max_level(to_i915(dev)); - struct skl_plane_wm *plane_wm; - enum pipe pipe = intel_crtc->pipe; - uint32_t temp; - int i; - - for (i = 0; i < intel_num_planes(intel_crtc); i++) { - plane_wm = &p_wm->planes[i]; - - for (level = 0; level <= max_level; level++) { - temp = 0; - - temp |= plane_wm->wm[level].plane_res_l << - PLANE_WM_LINES_SHIFT; - temp |= plane_wm->wm[level].plane_res_b; - if (plane_wm->wm[level].plane_en) - temp |= PLANE_WM_EN; - - r->plane[pipe][i][level] = temp; - } - } - - for (level = 0; level <= max_level; level++) { - plane_wm = &p_wm->planes[PLANE_CURSOR]; - temp = 0; - temp |= plane_wm->wm[level].plane_res_l << PLANE_WM_LINES_SHIFT; - temp |= plane_wm->wm[level].plane_res_b; - if (plane_wm->wm[level].plane_en) - temp |= PLANE_WM_EN; - - r->plane[pipe][PLANE_CURSOR][level] = temp; - } - - /* transition WMs */ - for (i = 0; i < intel_num_planes(intel_crtc); i++) { - plane_wm = &p_wm->planes[i]; - temp = 0; - temp |= plane_wm->trans_wm.plane_res_l << PLANE_WM_LINES_SHIFT; - temp |= plane_wm->trans_wm.plane_res_b; - if (plane_wm->trans_wm.plane_en) - temp |= PLANE_WM_EN; - - r->plane_trans[pipe][i] = temp; - } - - plane_wm = &p_wm->planes[PLANE_CURSOR]; - temp = 0; - temp |= plane_wm->trans_wm.plane_res_l << PLANE_WM_LINES_SHIFT; - temp |= plane_wm->trans_wm.plane_res_b; - if (plane_wm->trans_wm.plane_en) - temp |= PLANE_WM_EN; - - r->plane_trans[pipe][PLANE_CURSOR] = temp; -} - static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, i915_reg_t reg, const struct skl_ddb_entry *entry) @@ -3884,8 +3827,24 @@ static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, I915_WRITE(reg, 0); } +static void skl_write_wm_level(struct drm_i915_private *dev_priv, + i915_reg_t reg, + const struct skl_wm_level *level) +{ + uint32_t val = 0; + + if (level->plane_en) { + val |= PLANE_WM_EN; + val |= level->plane_res_b; + val |= level->plane_res_l << PLANE_WM_LINES_SHIFT; + } + + I915_WRITE(reg, val); +} + void skl_write_plane_wm(struct intel_crtc *intel_crtc, - const struct skl_wm_values *wm, + const struct skl_plane_wm *wm, + const struct skl_ddb_allocation *ddb, int plane) { struct drm_crtc *crtc = &intel_crtc->base; @@ -3895,19 +3854,21 @@ void skl_write_plane_wm(struct intel_crtc *intel_crtc, enum pipe pipe = intel_crtc->pipe; for (level = 0; level <= max_level; level++) { - I915_WRITE(PLANE_WM(pipe, plane, level), - wm->plane[pipe][plane][level]); + skl_write_wm_level(dev_priv, PLANE_WM(pipe, plane, level), + &wm->wm[level]); } - I915_WRITE(PLANE_WM_TRANS(pipe, plane), wm->plane_trans[pipe][plane]); + skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane), + &wm->trans_wm); skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane), - &wm->ddb.plane[pipe][plane]); + &ddb->plane[pipe][plane]); skl_ddb_entry_write(dev_priv, PLANE_NV12_BUF_CFG(pipe, plane), - &wm->ddb.y_plane[pipe][plane]); + &ddb->y_plane[pipe][plane]); } void skl_write_cursor_wm(struct intel_crtc *intel_crtc, - const struct skl_wm_values *wm) + const struct skl_plane_wm *wm, + const struct skl_ddb_allocation *ddb) { struct drm_crtc *crtc = &intel_crtc->base; struct drm_device *dev = crtc->dev; @@ -3916,13 +3877,13 @@ void skl_write_cursor_wm(struct intel_crtc *intel_crtc, enum pipe pipe = intel_crtc->pipe; for (level = 0; level <= max_level; level++) { - I915_WRITE(CUR_WM(pipe, level), - wm->plane[pipe][PLANE_CURSOR][level]); + skl_write_wm_level(dev_priv, CUR_WM(pipe, level), + &wm->wm[level]); } - I915_WRITE(CUR_WM_TRANS(pipe), wm->plane_trans[pipe][PLANE_CURSOR]); + skl_write_wm_level(dev_priv, CUR_WM_TRANS(pipe), &wm->trans_wm); skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe), - &wm->ddb.plane[pipe][PLANE_CURSOR]); + &ddb->plane[pipe][PLANE_CURSOR]); } static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, @@ -4106,11 +4067,6 @@ skl_copy_wm_for_pipe(struct skl_wm_values *dst, struct skl_wm_values *src, enum pipe pipe) { - memcpy(dst->plane[pipe], src->plane[pipe], - sizeof(dst->plane[pipe])); - memcpy(dst->plane_trans[pipe], src->plane_trans[pipe], - sizeof(dst->plane_trans[pipe])); - memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe], sizeof(dst->ddb.y_plane[pipe])); memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], @@ -4159,7 +4115,6 @@ skl_compute_wm(struct drm_atomic_state *state) * no suitable watermark values can be found. */ for_each_crtc_in_state(state, crtc, cstate, i) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate); @@ -4177,7 +4132,6 @@ skl_compute_wm(struct drm_atomic_state *state) continue; intel_cstate->update_wm_pre = true; - skl_compute_wm_results(crtc->dev, pipe_wm, results, intel_crtc); } return 0; @@ -4211,9 +4165,11 @@ static void skl_update_wm(struct drm_crtc *crtc) int plane; for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) - skl_write_plane_wm(intel_crtc, results, plane); + skl_write_plane_wm(intel_crtc, &pipe_wm->planes[plane], + &results->ddb, plane); - skl_write_cursor_wm(intel_crtc, results); + skl_write_cursor_wm(intel_crtc, &pipe_wm->planes[PLANE_CURSOR], + &results->ddb); } skl_copy_wm_for_pipe(hw_vals, results, pipe); @@ -4298,26 +4254,13 @@ static void ilk_optimize_watermarks(struct intel_crtc_state *cstate) mutex_unlock(&dev_priv->wm.wm_mutex); } -static void skl_pipe_wm_active_state(uint32_t val, - struct skl_pipe_wm *active, - bool is_transwm, - int i, - int level) +static inline void skl_wm_level_from_reg_val(uint32_t val, + struct skl_wm_level *level) { - struct skl_plane_wm *plane_wm = &active->planes[i]; - bool is_enabled = (val & PLANE_WM_EN) != 0; - - if (!is_transwm) { - plane_wm->wm[level].plane_en = is_enabled; - plane_wm->wm[level].plane_res_b = val & PLANE_WM_BLOCKS_MASK; - plane_wm->wm[level].plane_res_l = - (val >> PLANE_WM_LINES_SHIFT) & PLANE_WM_LINES_MASK; - } else { - plane_wm->trans_wm.plane_en = is_enabled; - plane_wm->trans_wm.plane_res_b = val & PLANE_WM_BLOCKS_MASK; - plane_wm->trans_wm.plane_res_l = - (val >> PLANE_WM_LINES_SHIFT) & PLANE_WM_LINES_MASK; - } + level->plane_en = val & PLANE_WM_EN; + level->plane_res_b = val & PLANE_WM_BLOCKS_MASK; + level->plane_res_l = (val >> PLANE_WM_LINES_SHIFT) & + PLANE_WM_LINES_MASK; } static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) @@ -4327,49 +4270,41 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) struct skl_wm_values *hw = &dev_priv->wm.skl_hw; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct intel_plane *intel_plane; struct skl_pipe_wm *active = &cstate->wm.skl.optimal; + struct skl_plane_wm *wm; enum pipe pipe = intel_crtc->pipe; - int level, i, max_level; - uint32_t temp; + int level, id, max_level; + uint32_t val; max_level = ilk_wm_max_level(dev_priv); - for (level = 0; level <= max_level; level++) { - for (i = 0; i < intel_num_planes(intel_crtc); i++) - hw->plane[pipe][i][level] = - I915_READ(PLANE_WM(pipe, i, level)); - hw->plane[pipe][PLANE_CURSOR][level] = I915_READ(CUR_WM(pipe, level)); - } - - for (i = 0; i < intel_num_planes(intel_crtc); i++) - hw->plane_trans[pipe][i] = I915_READ(PLANE_WM_TRANS(pipe, i)); - hw->plane_trans[pipe][PLANE_CURSOR] = I915_READ(CUR_WM_TRANS(pipe)); - - if (!intel_crtc->active) - return; - - hw->dirty_pipes |= drm_crtc_mask(crtc); + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + id = skl_wm_plane_id(intel_plane); + wm = &cstate->wm.skl.optimal.planes[id]; - active->linetime = I915_READ(PIPE_WM_LINETIME(pipe)); + for (level = 0; level <= max_level; level++) { + if (id != PLANE_CURSOR) + val = I915_READ(PLANE_WM(pipe, id, level)); + else + val = I915_READ(CUR_WM(pipe, level)); - for (level = 0; level <= max_level; level++) { - for (i = 0; i < intel_num_planes(intel_crtc); i++) { - temp = hw->plane[pipe][i][level]; - skl_pipe_wm_active_state(temp, active, false, i, level); + skl_wm_level_from_reg_val(val, &wm->wm[level]); } - temp = hw->plane[pipe][PLANE_CURSOR][level]; - skl_pipe_wm_active_state(temp, active, false, PLANE_CURSOR, - level); - } - for (i = 0; i < intel_num_planes(intel_crtc); i++) { - temp = hw->plane_trans[pipe][i]; - skl_pipe_wm_active_state(temp, active, true, i, 0); + if (id != PLANE_CURSOR) + val = I915_READ(PLANE_WM_TRANS(pipe, id)); + else + val = I915_READ(CUR_WM_TRANS(pipe)); + + skl_wm_level_from_reg_val(val, &wm->trans_wm); } - temp = hw->plane_trans[pipe][PLANE_CURSOR]; - skl_pipe_wm_active_state(temp, active, true, PLANE_CURSOR, 0); + if (!intel_crtc->active) + return; + hw->dirty_pipes |= drm_crtc_mask(crtc); + active->linetime = I915_READ(PIPE_WM_LINETIME(pipe)); intel_crtc->wm.active.skl = *active; } diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index c7d9a20e370d..e7d2cff8569d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -208,6 +208,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); const int pipe = intel_plane->pipe; const int plane = intel_plane->plane + 1; + const struct skl_plane_wm *p_wm = + &crtc_state->wm.skl.optimal.planes[plane]; u32 plane_ctl; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 surf_addr = plane_state->main.offset; @@ -232,7 +234,7 @@ skl_update_plane(struct drm_plane *drm_plane, plane_ctl |= skl_plane_ctl_rotation(rotation); if (wm->dirty_pipes & drm_crtc_mask(crtc)) - skl_write_plane_wm(intel_crtc, wm, plane); + skl_write_plane_wm(intel_crtc, p_wm, &wm->ddb, plane); if (key->flags) { I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value); @@ -289,6 +291,7 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) struct drm_device *dev = dplane->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *intel_plane = to_intel_plane(dplane); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); const int pipe = intel_plane->pipe; const int plane = intel_plane->plane + 1; @@ -298,7 +301,8 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) */ if (!dplane->state->visible) skl_write_plane_wm(to_intel_crtc(crtc), - &dev_priv->wm.skl_results, plane); + &cstate->wm.skl.optimal.planes[plane], + &dev_priv->wm.skl_results.ddb, plane); I915_WRITE(PLANE_CTL(pipe, plane), 0); -- cgit v1.2.3 From 413fc530c5b2fbf8c5ff926aaa18d7597463c055 Mon Sep 17 00:00:00 2001 From: "cpaul@redhat.com" Date: Fri, 14 Oct 2016 17:31:54 -0400 Subject: drm/i915/gen9: Add ddb changes to atomic debug output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finally, add some debugging output for ddb changes in the atomic debug output. This makes it a lot easier to spot bugs from incorrect ddb allocations. Signed-off-by: Lyude Reviewed-by: Maarten Lankhorst Reviewed-by: Paulo Zanoni Cc: Ville Syrjälä Cc: Matt Roper Cc: Paulo Zanoni Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1476480722-13015-7-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_pm.c | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 84e3272e5136..26c49bd00fc2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4073,6 +4073,58 @@ skl_copy_wm_for_pipe(struct skl_wm_values *dst, sizeof(dst->ddb.plane[pipe])); } +static void +skl_print_wm_changes(const struct drm_atomic_state *state) +{ + const struct drm_device *dev = state->dev; + const struct drm_i915_private *dev_priv = to_i915(dev); + const struct intel_atomic_state *intel_state = + to_intel_atomic_state(state); + const struct drm_crtc *crtc; + const struct drm_crtc_state *cstate; + const struct drm_plane *plane; + const struct intel_plane *intel_plane; + const struct drm_plane_state *pstate; + const struct skl_ddb_allocation *old_ddb = &dev_priv->wm.skl_hw.ddb; + const struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; + enum pipe pipe; + int id; + int i, j; + + for_each_crtc_in_state(state, crtc, cstate, i) { + pipe = to_intel_crtc(crtc)->pipe; + + for_each_plane_in_state(state, plane, pstate, j) { + const struct skl_ddb_entry *old, *new; + + intel_plane = to_intel_plane(plane); + id = skl_wm_plane_id(intel_plane); + old = &old_ddb->plane[pipe][id]; + new = &new_ddb->plane[pipe][id]; + + if (intel_plane->pipe != pipe) + continue; + + if (skl_ddb_entry_equal(old, new)) + continue; + + if (id != PLANE_CURSOR) { + DRM_DEBUG_ATOMIC("[PLANE:%d:plane %d%c] ddb (%d - %d) -> (%d - %d)\n", + plane->base.id, id + 1, + pipe_name(pipe), + old->start, old->end, + new->start, new->end); + } else { + DRM_DEBUG_ATOMIC("[PLANE:%d:cursor %c] ddb (%d - %d) -> (%d - %d)\n", + plane->base.id, + pipe_name(pipe), + old->start, old->end, + new->start, new->end); + } + } + } +} + static int skl_compute_wm(struct drm_atomic_state *state) { @@ -4134,6 +4186,8 @@ skl_compute_wm(struct drm_atomic_state *state) intel_cstate->update_wm_pre = true; } + skl_print_wm_changes(state); + return 0; } -- cgit v1.2.3 From bf9d99ad17ff3d85dc8c807063f76560587d983a Mon Sep 17 00:00:00 2001 From: "cpaul@redhat.com" Date: Fri, 14 Oct 2016 17:31:55 -0400 Subject: drm/i915/gen9: Make skl_pipe_wm_get_hw_state() reusable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's not much of a reason this should have the locations to read out the hardware state hardcoded, so allow the caller to specify the location and add this function to intel_drv.h. As well, we're going to need this function to be reusable for the next patch. Changes since v1: - Fix accidental behavior change in the code that Paulo pointed out Signed-off-by: Lyude Cc: Maarten Lankhorst Cc: Ville Syrjälä Cc: Matt Roper Cc: Paulo Zanoni Reviewed-by: Paulo Zanoni Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1476480722-13015-8-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 28 ++++++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a158d7e7edae..925df51f67f1 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1764,6 +1764,8 @@ void ilk_wm_get_hw_state(struct drm_device *dev); void skl_wm_get_hw_state(struct drm_device *dev); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb /* out */); +void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc, + struct skl_pipe_wm *out); bool intel_can_enable_sagv(struct drm_atomic_state *state); int intel_enable_sagv(struct drm_i915_private *dev_priv); int intel_disable_sagv(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 26c49bd00fc2..65277122a279 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4317,15 +4317,13 @@ static inline void skl_wm_level_from_reg_val(uint32_t val, PLANE_WM_LINES_MASK; } -static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) +void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc, + struct skl_pipe_wm *out) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct skl_wm_values *hw = &dev_priv->wm.skl_hw; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); struct intel_plane *intel_plane; - struct skl_pipe_wm *active = &cstate->wm.skl.optimal; struct skl_plane_wm *wm; enum pipe pipe = intel_crtc->pipe; int level, id, max_level; @@ -4335,7 +4333,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { id = skl_wm_plane_id(intel_plane); - wm = &cstate->wm.skl.optimal.planes[id]; + wm = &out->planes[id]; for (level = 0; level <= max_level; level++) { if (id != PLANE_CURSOR) @@ -4357,20 +4355,30 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) if (!intel_crtc->active) return; - hw->dirty_pipes |= drm_crtc_mask(crtc); - active->linetime = I915_READ(PIPE_WM_LINETIME(pipe)); - intel_crtc->wm.active.skl = *active; + out->linetime = I915_READ(PIPE_WM_LINETIME(pipe)); } void skl_wm_get_hw_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct skl_wm_values *hw = &dev_priv->wm.skl_hw; struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb; struct drm_crtc *crtc; + struct intel_crtc *intel_crtc; + struct intel_crtc_state *cstate; skl_ddb_get_hw_state(dev_priv, ddb); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - skl_pipe_wm_get_hw_state(crtc); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + intel_crtc = to_intel_crtc(crtc); + cstate = to_intel_crtc_state(crtc->state); + + skl_pipe_wm_get_hw_state(crtc, &cstate->wm.skl.optimal); + + if (intel_crtc->active) { + hw->dirty_pipes |= drm_crtc_mask(crtc); + intel_crtc->wm.active.skl = cstate->wm.skl.optimal; + } + } if (dev_priv->active_crtcs) { /* Fully recompute DDB on first atomic commit */ -- cgit v1.2.3 From 45ece23016ccd86a4629c9f74e22f0c06afa88f5 Mon Sep 17 00:00:00 2001 From: "cpaul@redhat.com" Date: Fri, 14 Oct 2016 17:31:56 -0400 Subject: drm/i915/gen9: Add skl_wm_level_equals() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Helper we're going to be using for implementing verification of the wm levels in skl_verify_wm_level(). Signed-off-by: Lyude Reviewed-by: Paulo Zanoni Cc: Maarten Lankhorst Cc: Ville Syrjälä Cc: Matt Roper Cc: Paulo Zanoni Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1476480722-13015-9-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 925df51f67f1..c06a33e0ff19 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1769,6 +1769,8 @@ void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc, bool intel_can_enable_sagv(struct drm_atomic_state *state); int intel_enable_sagv(struct drm_i915_private *dev_priv); int intel_disable_sagv(struct drm_i915_private *dev_priv); +bool skl_wm_level_equals(const struct skl_wm_level *l1, + const struct skl_wm_level *l2); bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, const struct skl_ddb_allocation *new, enum pipe pipe); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 65277122a279..0a9e7f2045d4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3886,6 +3886,20 @@ void skl_write_cursor_wm(struct intel_crtc *intel_crtc, &ddb->plane[pipe][PLANE_CURSOR]); } +bool skl_wm_level_equals(const struct skl_wm_level *l1, + const struct skl_wm_level *l2) +{ + if (l1->plane_en != l2->plane_en) + return false; + + /* If both planes aren't enabled, the rest shouldn't matter */ + if (!l1->plane_en) + return true; + + return (l1->plane_res_l == l2->plane_res_l && + l1->plane_res_b == l2->plane_res_b); +} + static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, const struct skl_ddb_entry *b) { -- cgit v1.2.3 From 3de8a14c288c1f83b9cd4bf24bb4fe6d0c22635b Mon Sep 17 00:00:00 2001 From: "cpaul@redhat.com" Date: Fri, 14 Oct 2016 17:31:57 -0400 Subject: drm/i915/gen9: Actually verify WM levels in verify_wm_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Paulo Zanoni for indirectly pointing this out. Looks like we never actually added any code for checking whether or not we actually wrote watermark levels properly. Let's fix that. Changes since v1: - Use %u instead of %d when printing WM state mismatches Signed-off-by: Lyude Reviewed-by: Paulo Zanoni Cc: Maarten Lankhorst Cc: Ville Syrjälä Cc: Matt Roper Cc: Paulo Zanoni Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1476480722-13015-10-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_display.c | 100 +++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0e18cf479328..0c97116c49b9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13462,30 +13462,66 @@ static void verify_wm_state(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct skl_ddb_allocation hw_ddb, *sw_ddb; - struct skl_ddb_entry *hw_entry, *sw_entry; + struct skl_pipe_wm hw_wm, *sw_wm; + struct skl_plane_wm *hw_plane_wm, *sw_plane_wm; + struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); const enum pipe pipe = intel_crtc->pipe; - int plane; + int plane, level, max_level = ilk_wm_max_level(dev_priv); if (INTEL_INFO(dev)->gen < 9 || !new_state->active) return; + skl_pipe_wm_get_hw_state(crtc, &hw_wm); + sw_wm = &intel_crtc->wm.active.skl; + skl_ddb_get_hw_state(dev_priv, &hw_ddb); sw_ddb = &dev_priv->wm.skl_hw.ddb; /* planes */ for_each_plane(dev_priv, pipe, plane) { - hw_entry = &hw_ddb.plane[pipe][plane]; - sw_entry = &sw_ddb->plane[pipe][plane]; + hw_plane_wm = &hw_wm.planes[plane]; + sw_plane_wm = &sw_wm->planes[plane]; - if (skl_ddb_entry_equal(hw_entry, sw_entry)) - continue; + /* Watermarks */ + for (level = 0; level <= max_level; level++) { + if (skl_wm_level_equals(&hw_plane_wm->wm[level], + &sw_plane_wm->wm[level])) + continue; + + DRM_ERROR("mismatch in WM pipe %c plane %d level %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + pipe_name(pipe), plane + 1, level, + sw_plane_wm->wm[level].plane_en, + sw_plane_wm->wm[level].plane_res_b, + sw_plane_wm->wm[level].plane_res_l, + hw_plane_wm->wm[level].plane_en, + hw_plane_wm->wm[level].plane_res_b, + hw_plane_wm->wm[level].plane_res_l); + } - DRM_ERROR("mismatch in DDB state pipe %c plane %d " - "(expected (%u,%u), found (%u,%u))\n", - pipe_name(pipe), plane + 1, - sw_entry->start, sw_entry->end, - hw_entry->start, hw_entry->end); + if (!skl_wm_level_equals(&hw_plane_wm->trans_wm, + &sw_plane_wm->trans_wm)) { + DRM_ERROR("mismatch in trans WM pipe %c plane %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + pipe_name(pipe), plane + 1, + sw_plane_wm->trans_wm.plane_en, + sw_plane_wm->trans_wm.plane_res_b, + sw_plane_wm->trans_wm.plane_res_l, + hw_plane_wm->trans_wm.plane_en, + hw_plane_wm->trans_wm.plane_res_b, + hw_plane_wm->trans_wm.plane_res_l); + } + + /* DDB */ + hw_ddb_entry = &hw_ddb.plane[pipe][plane]; + sw_ddb_entry = &sw_ddb->plane[pipe][plane]; + + if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { + DRM_ERROR("mismatch in DDB state pipe %c plane %d " + "(expected (%u,%u), found (%u,%u))\n", + pipe_name(pipe), plane + 1, + sw_ddb_entry->start, sw_ddb_entry->end, + hw_ddb_entry->start, hw_ddb_entry->end); + } } /* @@ -13495,15 +13531,47 @@ static void verify_wm_state(struct drm_crtc *crtc, * once the plane becomes visible, we can skip this check */ if (intel_crtc->cursor_addr) { - hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR]; - sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR]; + hw_plane_wm = &hw_wm.planes[PLANE_CURSOR]; + sw_plane_wm = &sw_wm->planes[PLANE_CURSOR]; + + /* Watermarks */ + for (level = 0; level <= max_level; level++) { + if (skl_wm_level_equals(&hw_plane_wm->wm[level], + &sw_plane_wm->wm[level])) + continue; + + DRM_ERROR("mismatch in WM pipe %c cursor level %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + pipe_name(pipe), level, + sw_plane_wm->wm[level].plane_en, + sw_plane_wm->wm[level].plane_res_b, + sw_plane_wm->wm[level].plane_res_l, + hw_plane_wm->wm[level].plane_en, + hw_plane_wm->wm[level].plane_res_b, + hw_plane_wm->wm[level].plane_res_l); + } + + if (!skl_wm_level_equals(&hw_plane_wm->trans_wm, + &sw_plane_wm->trans_wm)) { + DRM_ERROR("mismatch in trans WM pipe %c cursor (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + pipe_name(pipe), + sw_plane_wm->trans_wm.plane_en, + sw_plane_wm->trans_wm.plane_res_b, + sw_plane_wm->trans_wm.plane_res_l, + hw_plane_wm->trans_wm.plane_en, + hw_plane_wm->trans_wm.plane_res_b, + hw_plane_wm->trans_wm.plane_res_l); + } + + /* DDB */ + hw_ddb_entry = &hw_ddb.plane[pipe][PLANE_CURSOR]; + sw_ddb_entry = &sw_ddb->plane[pipe][PLANE_CURSOR]; - if (!skl_ddb_entry_equal(hw_entry, sw_entry)) { + if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { DRM_ERROR("mismatch in DDB state pipe %c cursor " "(expected (%u,%u), found (%u,%u))\n", pipe_name(pipe), - sw_entry->start, sw_entry->end, - hw_entry->start, hw_entry->end); + sw_ddb_entry->start, sw_ddb_entry->end, + hw_ddb_entry->start, hw_ddb_entry->end); } } } -- cgit v1.2.3 From faccd9941b17eb569db9b4e471c55aebdc93fe06 Mon Sep 17 00:00:00 2001 From: "cpaul@redhat.com" Date: Fri, 14 Oct 2016 17:31:58 -0400 Subject: drm/i915/gen9: Don't wrap strings in verify_wm_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrapping strings is against the guidelines in Documentation/CodingStyle, chapter 2. Signed-off-by: Lyude Reviewed-by: Paulo Zanoni Cc: Maarten Lankhorst Cc: Ville Syrjälä Cc: Matt Roper Cc: Paulo Zanoni Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1476480722-13015-11-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_display.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0c97116c49b9..6ccedf2af98e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13516,8 +13516,7 @@ static void verify_wm_state(struct drm_crtc *crtc, sw_ddb_entry = &sw_ddb->plane[pipe][plane]; if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { - DRM_ERROR("mismatch in DDB state pipe %c plane %d " - "(expected (%u,%u), found (%u,%u))\n", + DRM_ERROR("mismatch in DDB state pipe %c plane %d (expected (%u,%u), found (%u,%u))\n", pipe_name(pipe), plane + 1, sw_ddb_entry->start, sw_ddb_entry->end, hw_ddb_entry->start, hw_ddb_entry->end); @@ -13567,8 +13566,7 @@ static void verify_wm_state(struct drm_crtc *crtc, sw_ddb_entry = &sw_ddb->plane[pipe][PLANE_CURSOR]; if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { - DRM_ERROR("mismatch in DDB state pipe %c cursor " - "(expected (%u,%u), found (%u,%u))\n", + DRM_ERROR("mismatch in DDB state pipe %c cursor (expected (%u,%u), found (%u,%u))\n", pipe_name(pipe), sw_ddb_entry->start, sw_ddb_entry->end, hw_ddb_entry->start, hw_ddb_entry->end); -- cgit v1.2.3 From 41b9bb1b3be4cf6b9c28bbe1223744de48bf25c0 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 19 Oct 2016 17:32:19 -0700 Subject: drm/fb_cma_helper: do not free fbdev if there is none If fbdev emulation is not in use (or not built-in), fb_helper.fbdev is NULL. Don't call calling drm_fbdev_cma_defio_fini in this case. Signed-off-by: Stefan Agner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161020003221.2941-2-stefan@agner.ch --- drivers/gpu/drm/drm_fb_cma_helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index fac4f06f8485..4c6664407bfb 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -560,7 +560,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init); void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma) { drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper); - drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev); + if (fbdev_cma->fb_helper.fbdev) + drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev); drm_fb_helper_release_fbi(&fbdev_cma->fb_helper); if (fbdev_cma->fb) { -- cgit v1.2.3 From 7fb71c8f4f45afe73d307181be87c877447d0e47 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 12:37:43 +0100 Subject: drm/i915: Handle early failure during intel_get_load_detect_pipe In the error path, we have to be ready to handle an error before either the state or restore_state have been allocated. [ 397.001342] BUG: unable to handle kernel NULL pointer dereference at (null) [ 397.001419] IP: [] intel_get_load_detect_pipe+0xe4/0x610 [i915] [ 397.001502] PGD 136a2a067 [ 397.001523] PUD 134b5f067 [ 397.001546] PMD 0 [ 397.001569] Oops: 0002 [#1] PREEMPT SMP [ 397.001599] Modules linked in: snd_hda_intel i915 cdc_ncm usbnet mii x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic snd_hda_codec snd_hwdep snd_hda_core snd_pcm lpc_ich mei_me mei sdhci_pci sdhci mmc_core e1000e ptp pps_core [last unloaded: i915] [ 397.001902] CPU: 1 PID: 9287 Comm: kms_force_conne Tainted: G U 4.9.0-rc1-CI-CI_DRM_1730+ #1 [ 397.001965] Hardware name: LENOVO 2356GCG/2356GCG, BIOS G7ET31WW (1.13 ) 07/02/2012 [ 397.002017] task: ffff880138c38040 task.stack: ffffc900083e4000 [ 397.002057] RIP: 0010:[] [] intel_get_load_detect_pipe+0xe4/0x610 [i915] [ 397.002153] RSP: 0018:ffffc900083e7ae8 EFLAGS: 00010286 [ 397.002191] RAX: 00000000ffffffdd RBX: ffffc900083e7bc8 RCX: 0000000000000006 [ 397.002239] RDX: 0000000000000006 RSI: ffff880138c388b8 RDI: ffffc900083e79e0 [ 397.002287] RBP: ffffc900083e7b78 R08: 0000000000000000 R09: 0000000000000000 [ 397.002335] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 397.002386] R13: ffff8801305e1158 R14: 00000000ffffffdd R15: 0000000000000000 [ 397.002434] FS: 00007fea1b03c740(0000) GS:ffff88013e240000(0000) knlGS:0000000000000000 [ 397.002488] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 397.002528] CR2: 0000000000000000 CR3: 00000001361da000 CR4: 00000000001406e0 [ 397.002576] Stack: [ 397.002592] ffff88013046f180 0000000000000000 ffffc900083e7bc0 0000000000000000 [ 397.002655] 0000000000000000 ffff8801306bd038 ffff88012e980000 ffffc90000000001 [ 397.002718] ffffc90000000000 ffff880136b8ca88 ffff88012e980890 ffff88012e980540 [ 397.002780] Call Trace: [ 397.002828] [] intel_crt_detect+0x3c4/0x8f0 [i915] [ 397.002876] [] ? vprintk_default+0x1a/0x20 [ 397.002918] [] ? printk+0x43/0x4b [ 397.002956] [] drm_helper_probe_single_connector_modes+0x406/0x4f0 [ 397.003014] [] ? mutex_unlock+0x9/0x10 [ 397.003054] [] drm_mode_getconnector+0x33c/0x3c0 [ 397.003099] [] ? debug_lockdep_rcu_enabled+0x1d/0x20 [ 397.003147] [] ? __might_fault+0x3e/0x90 [ 397.003191] [] drm_ioctl+0x1f6/0x480 [ 397.003231] [] ? drm_mode_connector_property_set_ioctl+0x30/0x30 [ 397.003285] [] do_vfs_ioctl+0x8e/0x690 [ 397.003324] [] ? task_work_run+0x8c/0xb0 [ 397.003366] [] ? trace_hardirqs_on_caller+0x122/0x1b0 [ 397.003412] [] SyS_ioctl+0x3c/0x70 [ 397.003451] [] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 397.003496] Code: 85 c0 41 89 c6 75 57 49 8b 85 f0 00 00 00 48 89 de 45 31 ff 48 8d 78 20 e8 1a 89 13 e1 45 31 c9 85 c0 41 89 c6 0f 84 2f 01 00 00 41 83 29 01 74 53 f0 41 83 2f 01 74 2d 41 83 fe dd 75 35 48 [ 397.003837] RIP [] intel_get_load_detect_pipe+0xe4/0x610 [i915] [ 397.003921] RSP [ 397.003947] CR2: 0000000000000000 Testcase: igt/kms_force_connector_basic/force-load-detect # ivb-3720m Fixes: 0853695c3ba4 ("drm: Add reference counting to drm_atomic_state" Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161019113743.19847-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_display.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1e3b5eebd2a2..e11896cd2015 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11251,9 +11251,14 @@ found: return true; fail: - drm_atomic_state_put(state); - drm_atomic_state_put(restore_state); - restore_state = state = NULL; + if (state) { + drm_atomic_state_put(state); + state = NULL; + } + if (restore_state) { + drm_atomic_state_put(restore_state); + restore_state = NULL; + } if (ret == -EDEADLK) { drm_modeset_backoff(ctx); -- cgit v1.2.3 From 8de82280e3f5c4569505f475ce1a0b9ccfbd8de8 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:37 -0700 Subject: HID: wacom: Update vendor-defined usage names to better match standards Our loose use of "pen" and "digitizer" in the naming of several of our vendor-defined usages may be a source of confusion given that the terms have specific meaning within the HID specification. "Pen" specifically refers to "an integrated display that allows the use of a stylus" (e.g. something like a tablet PC or Cintiq) wheras "Digitizer" is a better fit for opaque tablets like an Intuos. While we're at it, go ahead and rename the definitions to make them more distinct and better match up with the convention used by HID (e.g. the use of '_UP_' for usage pages) and make them more distinct. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 12 ++++++------ drivers/hid/wacom_wac.c | 2 +- drivers/hid/wacom_wac.h | 17 +++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 5e7a5648e708..773fa114b216 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -159,18 +159,18 @@ static void wacom_feature_mapping(struct hid_device *hdev, case HID_UP_DIGITIZER: if (field->report->id == 0x0B && - (field->application == WACOM_G9_DIGITIZER || - field->application == WACOM_G11_DIGITIZER)) { + (field->application == WACOM_HID_G9_PEN || + field->application == WACOM_HID_G11_PEN)) { wacom->wacom_wac.mode_report = field->report->id; wacom->wacom_wac.mode_value = 0; } break; - case WACOM_G9_PAGE: - case WACOM_G11_PAGE: + case WACOM_HID_UP_G9: + case WACOM_HID_UP_G11: if (field->report->id == 0x03 && - (field->application == WACOM_G9_TOUCHSCREEN || - field->application == WACOM_G11_TOUCHSCREEN)) { + (field->application == WACOM_HID_G9_TOUCHSCREEN || + field->application == WACOM_HID_G11_TOUCHSCREEN)) { wacom->wacom_wac.mode_report = field->report->id; wacom->wacom_wac.mode_value = 0; } diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 1cb79925730d..3038954b8c41 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2448,7 +2448,7 @@ void wacom_setup_device_quirks(struct wacom *wacom) /* * Raw Wacom-mode pen and touch events both come from interface * 0, whose HID descriptor has an application usage of 0xFF0D - * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back + * (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back * out through the HID_GENERIC device created for interface 1, * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH. */ diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 324c40b0c119..f58bbd18209c 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -84,20 +84,21 @@ #define WACOM_DEVICETYPE_WL_MONITOR 0x0008 #define WACOM_DEVICETYPE_DIRECT 0x0010 -#define WACOM_VENDORDEFINED_PEN 0xff0d0001 -#define WACOM_G9_PAGE 0xff090000 -#define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02) -#define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11) -#define WACOM_G11_PAGE 0xff110000 -#define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02) -#define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11) +#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_UP_G9 0xff090000 +#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) +#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) +#define WACOM_HID_UP_G11 0xff110000 +#define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02) +#define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11) #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \ ((f)->application == HID_DG_PEN) || \ ((f)->application == HID_DG_DIGITIZER) || \ - ((f)->application == WACOM_VENDORDEFINED_PEN)) + ((f)->application == WACOM_HID_WD_DIGITIZER)) #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ ((f)->application == HID_DG_TOUCHSCREEN)) -- cgit v1.2.3 From 1b18b75c7e2452fc6f4cd1bb701efc4438532a07 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:38 -0700 Subject: HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields We've defined several new usages (e.g. WACOM_G9_PEN and WACOM_G9_TOUCHSCREEN) which aren't checked by the WACOM_PEN_FIELD and WACOM_FINGER_FIELD macros but probably should be. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index f58bbd18209c..d2629c81c51a 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -98,10 +98,14 @@ ((f)->physical == HID_DG_PEN) || \ ((f)->application == HID_DG_PEN) || \ ((f)->application == HID_DG_DIGITIZER) || \ - ((f)->application == WACOM_HID_WD_DIGITIZER)) + ((f)->application == WACOM_HID_WD_DIGITIZER) || \ + ((f)->application == WACOM_HID_G9_PEN) || \ + ((f)->application == WACOM_HID_G11_PEN)) #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ - ((f)->application == HID_DG_TOUCHSCREEN)) + ((f)->application == HID_DG_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_G11_TOUCHSCREEN)) enum { PENPARTNER = 0, -- cgit v1.2.3 From 49005b9fd05249d537363ff86cb41f07f48c847a Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:39 -0700 Subject: HID: wacom: Refactor button-to-key translation into function This just centralizes the logic used in both wacom_setup_numbered_buttons and wacom_report_numbered_buttons so that they don't drift out of sync. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 3038954b8c41..8071c18bf9c2 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2769,17 +2769,29 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, return 0; } +static int wacom_numbered_button_to_key(int n) +{ + if (n < 10) + return BTN_0 + n; + else if (n < 16) + return BTN_A + (n-10); + else if (n < 18) + return BTN_BASE + (n-16); + else + return 0; +} + static void wacom_setup_numbered_buttons(struct input_dev *input_dev, int button_count) { int i; - for (i = 0; i < button_count && i < 10; i++) - __set_bit(BTN_0 + i, input_dev->keybit); - for (i = 10; i < button_count && i < 16; i++) - __set_bit(BTN_A + (i-10), input_dev->keybit); - for (i = 16; i < button_count && i < 18; i++) - __set_bit(BTN_BASE + (i-16), input_dev->keybit); + for (i = 0; i < button_count; i++) { + int key = wacom_numbered_button_to_key(i); + + if (key) + __set_bit(key, input_dev->keybit); + } } static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group) @@ -2881,12 +2893,12 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev, for (i = 0; i < wacom->led.count; i++) wacom_update_led(wacom, button_count, mask, i); - for (i = 0; i < button_count && i < 10; i++) - input_report_key(input_dev, BTN_0 + i, mask & (1 << i)); - for (i = 10; i < button_count && i < 16; i++) - input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i)); - for (i = 16; i < button_count && i < 18; i++) - input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i)); + for (i = 0; i < button_count; i++) { + int key = wacom_numbered_button_to_key(i); + + if (key) + input_report_key(input_dev, key, mask & (1 << i)); + } } int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, -- cgit v1.2.3 From 6005a13c90a31501f3c21797b567e845c7098f25 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:40 -0700 Subject: HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 ISDv4 devices have long supported reporting data from each of two barrel switches, but HID_DG_BARRELSWITCH2 itself was only recently standardized. Prior to its adoption, ISDv4 devices would associate the bit indicating the state of the second barrel switch with the "Undefined" 0x000D0000 usage. Although most such devices have explicit support, a few use the HID_GENERIC codepath which ignores the "Undefined" usage. This patch adds code which detects the presence of a pre-standard second barrel switch and corrects the usage value so that the HID_GENERIC code will declare its presence and report its state. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 773fa114b216..033cc032f45c 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -240,6 +240,30 @@ static void wacom_usage_mapping(struct hid_device *hdev, features->touch_max = 1; } + /* + * ISDv4 devices which predate HID's adoption of the + * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its + * position instead. We can accurately detect if a + * usage with that value should be HID_DG_BARRELSWITCH2 + * based on the surrounding usages, which have remained + * constant across generations. + */ + if (features->type == HID_GENERIC && + usage->hid == 0x000D0000 && + field->application == HID_DG_PEN && + field->physical == HID_DG_STYLUS) { + int i = usage->usage_index; + + if (i-4 >= 0 && i+1 < field->maxusage && + field->usage[i-4].hid == HID_DG_TIPSWITCH && + field->usage[i-3].hid == HID_DG_BARRELSWITCH && + field->usage[i-2].hid == HID_DG_ERASER && + field->usage[i-1].hid == HID_DG_INVERT && + field->usage[i+1].hid == HID_DG_INRANGE) { + usage->hid = HID_DG_BARRELSWITCH2; + } + } + switch (usage->hid) { case HID_GD_X: features->x_max = field->logical_maximum; -- cgit v1.2.3 From f2209d4aefac246772152c5294af49f2800f646b Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:41 -0700 Subject: HID: wacom: generic: Strip off excessive name prefixing The product name received from the string descriptor in the new MobileStudio Pro line of tablets begins with "Wacom", which leads to unnecessary visual noise in the device name when appended to the vendor name which also includes "Wacom". Look for and fix cases like this. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 033cc032f45c..7b9bff2fad94 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1940,6 +1940,19 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) /* shift everything including the terminator */ memmove(gap, gap+1, strlen(gap)); } + + /* strip off excessive prefixing */ + if (strstr(name, "Wacom Co.,Ltd. Wacom ") == name) { + int n = strlen(name); + int x = strlen("Wacom Co.,Ltd. "); + memmove(name, name+x, n-x+1); + } + if (strstr(name, "Wacom Co., Ltd. Wacom ") == name) { + int n = strlen(name); + int x = strlen("Wacom Co., Ltd. "); + memmove(name, name+x, n-x+1); + } + /* get rid of trailing whitespace */ if (name[strlen(name)-1] == ' ') name[strlen(name)-1] = '\0'; -- cgit v1.2.3 From 50066a042da5457ae5b6397425f0a7ca556231e3 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:42 -0700 Subject: HID: wacom: generic: Add support for height, tilt, and twist usages The HID standard defines usages that allow digitizers to report the pen's height, tilt, and rotation and which are used by Wacom's new "MobileStudio Pro" devices. Note that 'hidinput_calc_abs_res' expects ABS_Z (historically used by our driver to report twist) to have linear units. To ensure it calculates a resolution with the actually-angular units provided in the HID descriptor we nedd to lie and tell it we're calculating it for the (rotational) ABS_RZ axis instead. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 28 ++++++++++++++++++++++++++-- include/linux/hid.h | 3 +++ 2 files changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 8071c18bf9c2..3f4ba53192c0 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1440,6 +1440,11 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, { int fmin = field->logical_minimum; int fmax = field->logical_maximum; + int resolution_code = code; + + if (usage->hid == HID_DG_TWIST) { + resolution_code = ABS_RZ; + } usage->type = type; usage->code = code; @@ -1450,7 +1455,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, case EV_ABS: input_set_abs_params(input, code, fmin, fmax, fuzz, 0); input_abs_set_res(input, code, - hidinput_calc_abs_res(field, code)); + hidinput_calc_abs_res(field, resolution_code)); break; case EV_KEY: input_set_capability(input, EV_KEY, code); @@ -1475,6 +1480,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, case HID_GD_Y: wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4); break; + case HID_GD_Z: + wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0); + break; case HID_DG_TIPPRESSURE: wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0); break; @@ -1485,6 +1493,15 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_RUBBER, 0); break; + case HID_DG_TILT_X: + wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0); + break; + case HID_DG_TILT_Y: + wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0); + break; + case HID_DG_TWIST: + wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0); + break; case HID_DG_ERASER: case HID_DG_TIPSWITCH: wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0); @@ -1508,8 +1525,15 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->pen_input; - /* checking which Tool / tip switch to send */ switch (usage->hid) { + case HID_GD_Z: + /* + * HID_GD_Z "should increase as the control's position is + * moved from high to low", while ABS_DISTANCE instead + * increases in value as the tool moves from low to high. + */ + value = field->logical_maximum - value; + break; case HID_DG_INRANGE: wacom_wac->hid_data.inrange_state = value; return 0; diff --git a/include/linux/hid.h b/include/linux/hid.h index b2ec82712baa..e712101a1670 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -232,6 +232,9 @@ struct hid_item { #define HID_DG_TABLETFUNCTIONKEY 0x000d0039 #define HID_DG_PROGRAMCHANGEKEY 0x000d003a #define HID_DG_INVERT 0x000d003c +#define HID_DG_TILT_X 0x000d003d +#define HID_DG_TILT_Y 0x000d003e +#define HID_DG_TWIST 0x000d0041 #define HID_DG_TIPSWITCH 0x000d0042 #define HID_DG_TIPSWITCH2 0x000d0043 #define HID_DG_BARRELSWITCH 0x000d0044 -- cgit v1.2.3 From c9c095874ab4446be6dec6755d8f68862fdeae48 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:43 -0700 Subject: HID: wacom: generic: Support and use 'Custom HID' mode and usages Wacom's new "MobileStudio Pro" tablets are the first devices in their branded product line-up to include a usable HID descriptor for the pen interface. Like prior branded products, the device can operate in one of two modes: 'Standard HID', and 'Wacom Custom HID'. Although the first mode is usable by the HID_GENERIC codepath as-is (huzzah!), it is subject to some restrictions -- most notably pressure being limited to 2048 levels instead of 8192. To ensure tablets that include support for Custom HID mode work optimally, we add support for its usages and switch the device to Custom HID mode if possible. The usages defined for Custom HID mode are often numerically similar to their standard HID equivalents, allowing us to write a simple translation function that takes arbitrary HID usages as input and which returns the corresponding standard HID usage as output (if one exists). Switching on this translated usage instead of the actual usage allows the existing cases to apply to both modes of operation without having to explicitly define every Custom HID usage. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 5 +++++ drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 3 +++ 3 files changed, 39 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 7b9bff2fad94..b2e2471bbef6 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -166,6 +166,11 @@ static void wacom_feature_mapping(struct hid_device *hdev, } break; + case WACOM_HID_WD_DATAMODE: + wacom->wacom_wac.mode_report = field->report->id; + wacom->wacom_wac.mode_value = 2; + break; + case WACOM_HID_UP_G9: case WACOM_HID_UP_G11: if (field->report->id == 0x03 && diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 3f4ba53192c0..6c2f0e4baf7d 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1435,14 +1435,35 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) return 0; } +static int wacom_equivalent_usage(int usage) +{ + if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) { + int subpage = (usage & 0xFF00) << 8; + int subusage = (usage & 0xFF); + + if (subpage == WACOM_HID_SP_DIGITIZER || + subpage == WACOM_HID_SP_DIGITIZERINFO) { + return usage; + } + + if (subpage == HID_UP_UNDEFINED) + subpage = HID_UP_DIGITIZER; + + return subpage | subusage; + } + + return usage; +} + static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, struct hid_field *field, __u8 type, __u16 code, int fuzz) { int fmin = field->logical_minimum; int fmax = field->logical_maximum; + unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); int resolution_code = code; - if (usage->hid == HID_DG_TWIST) { + if (equivalent_usage == HID_DG_TWIST) { resolution_code = ABS_RZ; } @@ -1472,8 +1493,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->pen_input; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_X: wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); break; @@ -1524,8 +1546,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->pen_input; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_Z: /* * HID_GD_Z "should increase as the control's position is @@ -1597,8 +1620,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->touch_input; unsigned touch_max = wacom_wac->features.touch_max; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_X: if (touch_max == 1) wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); @@ -1673,8 +1697,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_X: wacom_wac->hid_data.x = value; break; @@ -1697,7 +1722,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev, if (usage->usage_index + 1 == field->report_count) { - if (usage->hid == wacom_wac->hid_data.last_slot_field) + if (equivalent_usage == wacom_wac->hid_data.last_slot_field) wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); } diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index d2629c81c51a..ba914bad971f 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -85,7 +85,10 @@ #define WACOM_DEVICETYPE_DIRECT 0x0010 #define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_SP_DIGITIZER 0x000d0000 +#define WACOM_HID_SP_DIGITIZERINFO 0x00100000 #define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) #define WACOM_HID_UP_G9 0xff090000 #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) #define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) -- cgit v1.2.3 From b5c921e6c3916cdadd6e605d792f811abf7a5f82 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:44 -0700 Subject: HID: wacom: generic: Add support for vendor-defined "Distance" usage The vendor-defined 0xFF0D01032 ("Distance") usage is nearly equivalent to HID_GD_Z, except that the axis direction is inverted. Unlike HID_GD_Z which increases in value as the pen-to-surface distance is decreased, this usage decreases. Treat this usage as a special case to ensure we don't invert the scale to be ABS_DISTANCE compatible like we do for HID_GD_Z. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 4 +++- drivers/hid/wacom_wac.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 6c2f0e4baf7d..f78ad77d9ed7 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1442,7 +1442,8 @@ static int wacom_equivalent_usage(int usage) int subusage = (usage & 0xFF); if (subpage == WACOM_HID_SP_DIGITIZER || - subpage == WACOM_HID_SP_DIGITIZERINFO) { + subpage == WACOM_HID_SP_DIGITIZERINFO || + usage == WACOM_HID_WD_DISTANCE) { return usage; } @@ -1502,6 +1503,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, case HID_GD_Y: wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4); break; + case WACOM_HID_WD_DISTANCE: case HID_GD_Z: wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0); break; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index ba914bad971f..63a5a2586707 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -88,6 +88,7 @@ #define WACOM_HID_SP_DIGITIZER 0x000d0000 #define WACOM_HID_SP_DIGITIZERINFO 0x00100000 #define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) #define WACOM_HID_UP_G9 0xff090000 #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) -- cgit v1.2.3 From 929d6d5d22761fca1100e519cebe66f0fb11828d Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:45 -0700 Subject: HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage The airbrush fingerwheel does not have a usage that corresponds cleanly with a standard HID usage, so we add explicit support for it via its vendor-defined usage. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 3 +++ drivers/hid/wacom_wac.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index f78ad77d9ed7..81467c982734 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1539,6 +1539,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, case HID_DG_TOOLSERIALNUMBER: wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0); break; + case WACOM_HID_WD_FINGERWHEEL: + wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); + break; } } diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 63a5a2586707..544755929c2f 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -89,6 +89,7 @@ #define WACOM_HID_SP_DIGITIZERINFO 0x00100000 #define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) #define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) #define WACOM_HID_UP_G9 0xff090000 #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) -- cgit v1.2.3 From 61ce346a21a74cc106e76bbaf6a2319d1d74fa6d Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:46 -0700 Subject: HID: wacom: generic: Add support for vendor-defined "Sense" usage Wacom's professional tablets beginning with the Intuos4 are capable of reporting an intermediate degree of proximity where the pen is no longer close enough to communicate with ("in prox"), but still close enough to be sensed ("in range"). This additional state is particularly useful for performing palm rejection as it allows the driver to disable the touch sensor while the pen is a greater distance from the tablet. Like other professional tablets, the new MobileStudio Pro also reports this intermeidate "in range" proximity state. Its descriptor assigns usage 0xff0d0036 to this bit. Normally 'wacom_equivalent_usage' would translate this to the standard HID "Quality" usage, but since this has a different meaning we have it explicitly ignore the usage and define it ourselves as "Sense" (since "In Range" is already defined by the HID standard and interpreted by our driver as meaning "in prox"). Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 26 +++++++++++++++++++++++--- drivers/hid/wacom_wac.h | 3 +++ 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 81467c982734..c0d75aee91e5 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1443,6 +1443,7 @@ static int wacom_equivalent_usage(int usage) if (subpage == WACOM_HID_SP_DIGITIZER || subpage == WACOM_HID_SP_DIGITIZERINFO || + usage == WACOM_HID_WD_SENSE || usage == WACOM_HID_WD_DISTANCE) { return usage; } @@ -1493,6 +1494,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_features *features = &wacom_wac->features; struct input_dev *input = wacom_wac->pen_input; unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); @@ -1539,6 +1541,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, case HID_DG_TOOLSERIALNUMBER: wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0); break; + case WACOM_HID_WD_SENSE: + features->quirks |= WACOM_QUIRK_SENSE; + wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0); + break; case WACOM_HID_WD_FINGERWHEEL: wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); break; @@ -1550,6 +1556,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_features *features = &wacom_wac->features; struct input_dev *input = wacom_wac->pen_input; unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); @@ -1564,6 +1571,8 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, break; case HID_DG_INRANGE: wacom_wac->hid_data.inrange_state = value; + if (!(features->quirks & WACOM_QUIRK_SENSE)) + wacom_wac->hid_data.sense_state = value; return 0; case HID_DG_INVERT: wacom_wac->hid_data.invert_state = value; @@ -1572,6 +1581,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, case HID_DG_TIPSWITCH: wacom_wac->hid_data.tipswitch |= value; return 0; + case WACOM_HID_WD_SENSE: + wacom_wac->hid_data.sense_state = value; + return 0; } /* send pen events only when touch is up or forced out @@ -1580,6 +1592,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, if (!usage->type || delay_pen_events(wacom_wac)) return 0; + /* send pen events only when the pen is in/entering/leaving proximity */ + if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0]) + return 0; + input_event(input, usage->type, usage->code, value); return 0; @@ -1598,16 +1614,17 @@ static void wacom_wac_pen_report(struct hid_device *hdev, struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->pen_input; bool prox = wacom_wac->hid_data.inrange_state; + bool range = wacom_wac->hid_data.sense_state; - if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */ + if (!wacom_wac->tool[0] && prox) /* first in prox */ /* Going into proximity select tool */ wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; /* keep pen state for touch events */ - wacom_wac->shared->stylus_in_proximity = prox; + wacom_wac->shared->stylus_in_proximity = range; - if (!delay_pen_events(wacom_wac)) { + if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) { input_report_key(input, BTN_TOUCH, wacom_wac->hid_data.tipswitch); input_report_key(input, wacom_wac->tool[0], prox); @@ -1616,6 +1633,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev, input_sync(input); } + + if (!prox) + wacom_wac->tool[0] = 0; } static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 544755929c2f..c27b7b40092e 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -74,6 +74,7 @@ /* device quirks */ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 +#define WACOM_QUIRK_SENSE 0x0002 #define WACOM_QUIRK_BATTERY 0x0008 /* device types */ @@ -88,6 +89,7 @@ #define WACOM_HID_SP_DIGITIZER 0x000d0000 #define WACOM_HID_SP_DIGITIZERINFO 0x00100000 #define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) #define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) #define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) @@ -212,6 +214,7 @@ struct wacom_shared { struct hid_data { __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ __s16 inputmode_index; /* InputMode HID feature index in the report */ + bool sense_state; bool inrange_state; bool invert_state; bool tipswitch; -- cgit v1.2.3 From 82527da319ee41e1e896f6c1290c83ecbc892a69 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:47 -0700 Subject: HID: wacom: Read and internally use corrected Intuos tool IDs The 'wacom_intuos_inout' function incorrectly assmebles tool IDs from the proximity report, shifting the higher values of the ID four bits farther than intended. This problem was not detected until too late, but has not caused any issues since the incorrect IDs still fit in a 32-bit integer and userspace programs have not required the value to match the hardware (just that the values are unique and constant). The tool IDs reported by the new MobileStudio Pro (or any future HID_GENERIC device that supports them) do not suffer from the same assembly issue, however. In order for 'wacom_intuos_get_tool_type' to work for with both codepaths, we correct this issue internally and have 'wacom_intuos_general' only mangle the ID when it is posted to userspace. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index c0d75aee91e5..df9d866b9b3f 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -588,6 +588,11 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) return 1; } +static int wacom_intuos_id_mangle(int tool_id) +{ + return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF); +} + static int wacom_intuos_get_tool_type(int tool_id) { int tool_type; @@ -595,7 +600,7 @@ static int wacom_intuos_get_tool_type(int tool_id) switch (tool_id) { case 0x812: /* Inking pen */ case 0x801: /* Intuos3 Inking pen */ - case 0x120802: /* Intuos4/5 Inking Pen */ + case 0x12802: /* Intuos4/5 Inking Pen */ case 0x012: tool_type = BTN_TOOL_PENCIL; break; @@ -610,11 +615,11 @@ static int wacom_intuos_get_tool_type(int tool_id) case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ case 0x8e2: /* IntuosHT2 pen */ case 0x022: - case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */ - case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */ - case 0x160802: /* Cintiq 13HD Pro Pen */ - case 0x180802: /* DTH2242 Pen */ - case 0x100802: /* Intuos4/5 13HD/24HD General Pen */ + case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */ + case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */ + case 0x16802: /* Cintiq 13HD Pro Pen */ + case 0x18802: /* DTH2242 Pen */ + case 0x10802: /* Intuos4/5 13HD/24HD General Pen */ tool_type = BTN_TOOL_PEN; break; @@ -648,12 +653,12 @@ static int wacom_intuos_get_tool_type(int tool_id) case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */ case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */ case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ - case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */ - case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ - case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */ - case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */ - case 0x18080a: /* DTH2242 Eraser */ - case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */ + case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */ + case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ + case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */ + case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */ + case 0x1880a: /* DTH2242 Eraser */ + case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */ tool_type = BTN_TOOL_RUBBER; break; @@ -662,7 +667,7 @@ static int wacom_intuos_get_tool_type(int tool_id) case 0x112: case 0x913: /* Intuos3 Airbrush */ case 0x902: /* Intuos4/5 13HD/24HD Airbrush */ - case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */ + case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */ tool_type = BTN_TOOL_AIRBRUSH; break; @@ -693,7 +698,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) (data[6] << 4) + (data[7] >> 4); wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) | - ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12); + ((data[7] & 0x0f) << 16) | ((data[8] & 0xf0) << 8); wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]); @@ -923,7 +928,7 @@ static int wacom_intuos_general(struct wacom_wac *wacom) * don't report events for invalid data */ /* older I4 styli don't work with new Cintiqs */ - if ((!((wacom->id[idx] >> 20) & 0x01) && + if ((!((wacom->id[idx] >> 16) & 0x01) && (features->type == WACOM_21UX2)) || /* Only large Intuos support Lense Cursor */ (wacom->tool[idx] == BTN_TOOL_LENS && @@ -1059,7 +1064,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom) break; } - input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */ + input_report_abs(input, ABS_MISC, + wacom_intuos_id_mangle(wacom->id[idx])); /* report tool id */ input_report_key(input, wacom->tool[idx], 1); input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); wacom->reporting_data = true; -- cgit v1.2.3 From f85c9dc678a5e17f49805035f5b327ed134c4237 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:48 -0700 Subject: HID: wacom: generic: Support tool ID and additional tool types Devices following the new Custom HID mode specification (as well as even some recent component sensors which use the same standard HID usage) are capable of reporting tool ID information that we need to relay to userspace. This patch adds support for reading and relaying the tool type information, which is (unfortunately) split across two usages. We also advertise the existence of tool types beyond BTN_TOOL_PEN that might be available. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- drivers/hid/wacom_wac.h | 4 ++- 2 files changed, 71 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index df9d866b9b3f..85e1ad102cdc 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1450,6 +1450,8 @@ static int wacom_equivalent_usage(int usage) if (subpage == WACOM_HID_SP_DIGITIZER || subpage == WACOM_HID_SP_DIGITIZERINFO || usage == WACOM_HID_WD_SENSE || + usage == WACOM_HID_WD_SERIALHI || + usage == WACOM_HID_WD_TOOLTYPE || usage == WACOM_HID_WD_DISTANCE) { return usage; } @@ -1551,6 +1553,17 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, features->quirks |= WACOM_QUIRK_SENSE; wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0); break; + case WACOM_HID_WD_SERIALHI: + wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0); + set_bit(EV_KEY, input->evbit); + input_set_capability(input, EV_KEY, BTN_TOOL_PEN); + input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER); + input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH); + input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL); + input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH); + input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE); + input_set_capability(input, EV_KEY, BTN_TOOL_LENS); + break; case WACOM_HID_WD_FINGERWHEEL: wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); break; @@ -1587,9 +1600,35 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, case HID_DG_TIPSWITCH: wacom_wac->hid_data.tipswitch |= value; return 0; + case HID_DG_TOOLSERIALNUMBER: + wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFF); + wacom_wac->serial[0] |= value; + return 0; case WACOM_HID_WD_SENSE: wacom_wac->hid_data.sense_state = value; return 0; + case WACOM_HID_WD_SERIALHI: + wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF); + wacom_wac->serial[0] |= ((__u64)value) << 32; + /* + * Non-USI EMR devices may contain additional tool type + * information here. See WACOM_HID_WD_TOOLTYPE case for + * more details. + */ + if (value >> 20 == 1) { + wacom_wac->id[0] |= value & 0xFFFFF; + } + return 0; + case WACOM_HID_WD_TOOLTYPE: + /* + * Some devices (MobileStudio Pro, and possibly later + * devices as well) do not return the complete tool + * type in their WACOM_HID_WD_TOOLTYPE usage. Use a + * bitwise OR so the complete value can be built + * up over time :( + */ + wacom_wac->id[0] |= value; + return 0; } /* send pen events only when touch is up or forced out @@ -1622,26 +1661,51 @@ static void wacom_wac_pen_report(struct hid_device *hdev, bool prox = wacom_wac->hid_data.inrange_state; bool range = wacom_wac->hid_data.sense_state; - if (!wacom_wac->tool[0] && prox) /* first in prox */ + if (!wacom_wac->tool[0] && prox) { /* first in prox */ /* Going into proximity select tool */ - wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ? - BTN_TOOL_RUBBER : BTN_TOOL_PEN; + if (wacom_wac->hid_data.invert_state) + wacom_wac->tool[0] = BTN_TOOL_RUBBER; + else if (wacom_wac->id[0]) + wacom_wac->tool[0] = wacom_intuos_get_tool_type(wacom_wac->id[0]); + else + wacom_wac->tool[0] = BTN_TOOL_PEN; + } /* keep pen state for touch events */ wacom_wac->shared->stylus_in_proximity = range; if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) { + int id = wacom_wac->id[0]; + + /* + * Non-USI EMR tools should have their IDs mangled to + * match the legacy behavior of wacom_intuos_general + */ + if (wacom_wac->serial[0] >> 52 == 1) + id = wacom_intuos_id_mangle(id); + + /* + * To ensure compatibility with xf86-input-wacom, we should + * report the BTN_TOOL_* event prior to the ABS_MISC or + * MSC_SERIAL events. + */ input_report_key(input, BTN_TOUCH, wacom_wac->hid_data.tipswitch); input_report_key(input, wacom_wac->tool[0], prox); + if (wacom_wac->serial[0]) { + input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]); + input_report_abs(input, ABS_MISC, id); + } wacom_wac->hid_data.tipswitch = false; input_sync(input); } - if (!prox) + if (!prox) { wacom_wac->tool[0] = 0; + wacom_wac->id[0] = 0; + } } static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index c27b7b40092e..83ddb2a062a1 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -90,6 +90,8 @@ #define WACOM_HID_SP_DIGITIZERINFO 0x00100000 #define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) #define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) +#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) +#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77) #define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) #define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) @@ -247,7 +249,7 @@ struct wacom_wac { unsigned char data[WACOM_PKGLEN_MAX]; int tool[2]; int id[2]; - __u32 serial[2]; + __u64 serial[2]; bool reporting_data; struct wacom_features features; struct wacom_shared *shared; -- cgit v1.2.3 From e779ef23104869d74f56fbd199a90e76699eb699 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:49 -0700 Subject: HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Many of Wacom's display tablets include an "outbound" area where pen digitizing is possible but outside of the display area. To ensure that pen coordinates are mapped to the correct on-screen location, the driver sets the minimum and maximum axis values of X and Y to those coordinates which coincide with the screen edge. These values are simply the hardware minimum/maximum plus/minus the outbound size for a particular edge. When outbound support was added/updated in ac414da, fa77034, and ecd618d, we decided to have the wacom_features structs store the desired minimum and maximum values directly. In hindsight, this was perhaps not the best choice since it has allowed minor errors to crop up unnoticed. Some tablets have had their coordinates over-corrected (e.g. most of the devices "fixed" in ecd618d were already adjusted in ac414da), while others never had a correction applied (e.g. the ISDv5 325, whose declared maximum the hardware maximum instead of the outbound maximum). A less error-prone method of handling the outbound is to let the driver calculate the correct minimum/maximum values by providing it with both the actual hardware maximums and the size of the outbound on each edge. These values are more easy to verify as correct since the values can be trivially compared against specifications. This patch reverts the declared maximum values to the actual hardware maximums, e.g. as declared prior to ac414da (values for these and other display tablets that were subsuquently introduced have been verified against specs). Per-edge outbound sizes are stored in the wacom_features struct as offset_{left,right,top,bottom} and used in combination with the hardware ranges to calculate effective axis ranges for ABS_X and ABS_Y. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 62 ++++++++++++++++++++++++++++++++----------------- drivers/hid/wacom_wac.h | 6 +++-- 2 files changed, 45 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 85e1ad102cdc..5046071f2e9e 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2674,10 +2674,12 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(ABS_MISC, input_dev->absbit); - input_set_abs_params(input_dev, ABS_X, features->x_min, - features->x_max, features->x_fuzz, 0); - input_set_abs_params(input_dev, ABS_Y, features->y_min, - features->y_max, features->y_fuzz, 0); + input_set_abs_params(input_dev, ABS_X, 0 + features->offset_left, + features->x_max - features->offset_right, + features->x_fuzz, 0); + input_set_abs_params(input_dev, ABS_Y, 0 + features->offset_top, + features->y_max - features->offset_bottom, + features->y_fuzz, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, features->pressure_fuzz, 0); @@ -3389,26 +3391,30 @@ static const struct wacom_features wacom_features_0x317 = INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0xF4 = - { "Wacom Cintiq 24HD", 104080, 65200, 2047, 63, + { "Wacom Cintiq 24HD", 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0xF8 = - { "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */ + { "Wacom Cintiq 24HD touch", 104480, 65600, 2047, 63, /* Pen */ WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; static const struct wacom_features wacom_features_0xF6 = { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x32A = - { "Wacom Cintiq 27QHD", 119740, 67520, 2047, 63, + { "Wacom Cintiq 27QHD", 120140, 67920, 2047, 63, WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0x32B = - { "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63, + { "Wacom Cintiq 27QHD touch", 120140, 67920, 2047, 63, WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C }; static const struct wacom_features wacom_features_0x32C = { "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT, @@ -3423,13 +3429,15 @@ static const struct wacom_features wacom_features_0xC6 = { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 }; static const struct wacom_features wacom_features_0x304 = - { "Wacom Cintiq 13HD", 59152, 33448, 1023, 63, + { "Wacom Cintiq 13HD", 59552, 33848, 1023, 63, WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0x333 = - { "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63, + { "Wacom Cintiq 13HD touch", 59552, 33848, 2047, 63, WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 }; static const struct wacom_features wacom_features_0x335 = { "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */ @@ -3446,42 +3454,50 @@ static const struct wacom_features wacom_features_0xF0 = { "Wacom DTU1631", 34623, 19553, 511, 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xFB = - { "Wacom DTU1031", 21896, 13760, 511, 0, + { "Wacom DTU1031", 22096, 13960, 511, 0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, + WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_0x32F = - { "Wacom DTU1031X", 22472, 12728, 511, 0, + { "Wacom DTU1031X", 22672, 12928, 511, 0, DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0, + WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_0x336 = - { "Wacom DTU1141", 23472, 13203, 1023, 0, + { "Wacom DTU1141", 23672, 13403, 1023, 0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, + WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_0x57 = - { "Wacom DTK2241", 95640, 54060, 2047, 63, + { "Wacom DTK2241", 95840, 54260, 2047, 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0x59 = /* Pen */ - { "Wacom DTH2242", 95640, 54060, 2047, 63, + { "Wacom DTH2242", 95840, 54260, 2047, 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; static const struct wacom_features wacom_features_0x5D = /* Touch */ { "Wacom DTH2242", .type = WACOM_24HDT, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0xCC = - { "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63, + { "Wacom Cintiq 21UX2", 87200, 65600, 2047, 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0xFA = - { "Wacom Cintiq 22HD", 95440, 53860, 2047, 63, + { "Wacom Cintiq 22HD", 95840, 54260, 2047, 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0x5B = - { "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63, + { "Wacom Cintiq 22HDT", 95840, 54260, 2047, 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; static const struct wacom_features wacom_features_0x5E = { "Wacom Cintiq 22HDT", .type = WACOM_24HDT, @@ -3625,18 +3641,20 @@ static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x307 = - { "Wacom ISDv5 307", 59152, 33448, 2047, 63, + { "Wacom ISDv5 307", 59552, 33848, 2047, 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; static const struct wacom_features wacom_features_0x309 = { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x30A = - { "Wacom ISDv5 30A", 59152, 33448, 2047, 63, + { "Wacom ISDv5 30A", 59552, 33848, 2047, 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C }; static const struct wacom_features wacom_features_0x30C = { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */ @@ -3652,6 +3670,7 @@ static const struct wacom_features wacom_features_0x325 = { "Wacom ISDv5 325", 59552, 33848, 2047, 63, CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 }; static const struct wacom_features wacom_features_0x326 = /* Touch */ { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM, @@ -3681,8 +3700,9 @@ static const struct wacom_features wacom_features_0x33E = INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x343 = - { "Wacom DTK1651", 34616, 19559, 1023, 0, + { "Wacom DTK1651", 34816, 19759, 1023, 0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, + WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_HID_ANY_ID = diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 83ddb2a062a1..5c5c6891b832 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -181,8 +181,10 @@ struct wacom_features { int x_resolution; int y_resolution; int numbered_buttons; - int x_min; - int y_min; + int offset_left; + int offset_right; + int offset_top; + int offset_bottom; int device_type; int x_phy; int y_phy; -- cgit v1.2.3 From 345857bb493fbff15632a6bdf04713163ccd6fe6 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:50 -0700 Subject: HID: wacom: generic: Add support for sensor offsets Many of Wacom's display tablets include an "outbound" area where pen digitizing is possible but outside of the display area. To accommodate such sensors in the HID_GENERIC codepath, we add support for the necessary vendor-defined HID feature usages and adjust the min/max values of the X and Y axes accordingly, similar to what is done in the non-generic codepath. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 38 ++++++++++++++++++++++++++++++-------- drivers/hid/wacom_wac.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/hid/wacom_wac.h | 4 ++++ 3 files changed, 74 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index b2e2471bbef6..b9779bcbd140 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, struct hid_data *hid_data = &wacom->wacom_wac.hid_data; u8 *data; int ret; + int n; switch (usage->hid) { case HID_DG_CONTACTMAX: @@ -180,6 +181,27 @@ static void wacom_feature_mapping(struct hid_device *hdev, wacom->wacom_wac.mode_value = 0; } break; + case WACOM_HID_WD_OFFSETLEFT: + case WACOM_HID_WD_OFFSETTOP: + case WACOM_HID_WD_OFFSETRIGHT: + case WACOM_HID_WD_OFFSETBOTTOM: + /* read manually */ + n = hid_report_len(field->report); + data = hid_alloc_report_buf(field->report, GFP_KERNEL); + if (!data) + break; + data[0] = field->report->id; + ret = wacom_get_report(hdev, HID_FEATURE_REPORT, + data, n, WAC_CMD_RETRIES); + if (ret == n) { + ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, + data, n, 0); + } else { + hid_warn(hdev, "%s: could not retrieve sensor offsets\n", + __func__); + } + kfree(data); + break; } } @@ -718,11 +740,6 @@ static int wacom_add_shared_data(struct hid_device *hdev) return retval; } - if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) - wacom_wac->shared->touch = hdev; - else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) - wacom_wac->shared->pen = hdev; - out: mutex_unlock(&wacom_udev_list_lock); return retval; @@ -2019,6 +2036,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) if (error) goto fail; + error = wacom_add_shared_data(hdev); + if (error) + goto fail; + /* * Bamboo Pad has a generic hid handling for the Pen, and we switch it * into debug mode for the touch part. @@ -2059,9 +2080,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) wacom_update_name(wacom, wireless ? " (WL)" : ""); - error = wacom_add_shared_data(hdev); - if (error) - goto fail; + if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) + wacom_wac->shared->touch = hdev; + else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) + wacom_wac->shared->pen = hdev; if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) && (features->quirks & WACOM_QUIRK_BATTERY)) { diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 5046071f2e9e..3bb6dd6e4eea 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1468,6 +1468,9 @@ static int wacom_equivalent_usage(int usage) static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, struct hid_field *field, __u8 type, __u16 code, int fuzz) { + struct wacom *wacom = input_get_drvdata(input); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_features *features = &wacom_wac->features; int fmin = field->logical_minimum; int fmax = field->logical_maximum; unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); @@ -1477,6 +1480,15 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, resolution_code = ABS_RZ; } + if (equivalent_usage == HID_GD_X) { + fmin += features->offset_left; + fmax -= features->offset_right; + } + if (equivalent_usage == HID_GD_Y) { + fmin += features->offset_top; + fmax -= features->offset_bottom; + } + usage->type = type; usage->code = code; @@ -1629,6 +1641,34 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, */ wacom_wac->id[0] |= value; return 0; + case WACOM_HID_WD_OFFSETLEFT: + if (features->offset_left && value != features->offset_left) + hid_warn(hdev, "%s: overriding exising left offset " + "%d -> %d\n", __func__, value, + features->offset_left); + features->offset_left = value; + return 0; + case WACOM_HID_WD_OFFSETRIGHT: + if (features->offset_right && value != features->offset_right) + hid_warn(hdev, "%s: overriding exising right offset " + "%d -> %d\n", __func__, value, + features->offset_right); + features->offset_right = value; + return 0; + case WACOM_HID_WD_OFFSETTOP: + if (features->offset_top && value != features->offset_top) + hid_warn(hdev, "%s: overriding exising top offset " + "%d -> %d\n", __func__, value, + features->offset_top); + features->offset_top = value; + return 0; + case WACOM_HID_WD_OFFSETBOTTOM: + if (features->offset_bottom && value != features->offset_bottom) + hid_warn(hdev, "%s: overriding exising bottom offset " + "%d -> %d\n", __func__, value, + features->offset_bottom); + features->offset_bottom = value; + return 0; } /* send pen events only when touch is up or forced out diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 5c5c6891b832..b4c3c6425b85 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -94,6 +94,10 @@ #define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77) #define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) #define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) +#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30) +#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31) +#define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32) +#define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33) #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) #define WACOM_HID_UP_G9 0xff090000 #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) -- cgit v1.2.3 From 5922e613256f159f8d53d99b17379f362e544541 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:51 -0700 Subject: HID: wacom: generic: Introduce pad support As with usages for the pen, the Custom HID specificiation includes usages for the pad. Here we add functions to map and handle most of the pad usages present on the MobileStudio Pro. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 143 ++++++++++++++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 19 +++++++ 2 files changed, 146 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 3bb6dd6e4eea..70de1fa930cc 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)"); static void wacom_report_numbered_buttons(struct input_dev *input_dev, int button_count, int mask); +static int wacom_numbered_button_to_key(int n); + /* * Percent of battery capacity for Graphire. * 8th value means AC online and show 100% capacity. @@ -1447,12 +1449,16 @@ static int wacom_equivalent_usage(int usage) int subpage = (usage & 0xFF00) << 8; int subusage = (usage & 0xFF); - if (subpage == WACOM_HID_SP_DIGITIZER || + if (subpage == WACOM_HID_SP_PAD || + subpage == WACOM_HID_SP_BUTTON || + subpage == WACOM_HID_SP_DIGITIZER || subpage == WACOM_HID_SP_DIGITIZERINFO || usage == WACOM_HID_WD_SENSE || usage == WACOM_HID_WD_SERIALHI || usage == WACOM_HID_WD_TOOLTYPE || - usage == WACOM_HID_WD_DISTANCE) { + usage == WACOM_HID_WD_DISTANCE || + usage == WACOM_HID_WD_TOUCHRING || + usage == WACOM_HID_WD_TOUCHRINGSTATUS) { return usage; } @@ -1509,6 +1515,98 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, } } +static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_features *features = &wacom_wac->features; + struct input_dev *input = wacom_wac->pad_input; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); + + switch (equivalent_usage) { + case WACOM_HID_WD_ACCELEROMETER_X: + __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); + wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0); + break; + case WACOM_HID_WD_ACCELEROMETER_Y: + __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); + wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 0); + break; + case WACOM_HID_WD_ACCELEROMETER_Z: + __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); + wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0); + break; + case WACOM_HID_WD_BUTTONHOME: + case WACOM_HID_WD_BUTTONUP: + case WACOM_HID_WD_BUTTONDOWN: + case WACOM_HID_WD_BUTTONLEFT: + case WACOM_HID_WD_BUTTONRIGHT: + wacom_map_usage(input, usage, field, EV_KEY, + wacom_numbered_button_to_key(features->numbered_buttons), + 0); + features->numbered_buttons++; + break; + case WACOM_HID_WD_TOUCHRING: + wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); + break; + } + + switch (equivalent_usage & 0xfffffff0) { + case WACOM_HID_WD_EXPRESSKEY00: + wacom_map_usage(input, usage, field, EV_KEY, + wacom_numbered_button_to_key(features->numbered_buttons), + 0); + features->numbered_buttons++; + break; + } +} + +static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field, + struct hid_usage *usage, __s32 value) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct input_dev *input = wacom_wac->pad_input; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); + + if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) { + wacom_wac->hid_data.inrange_state |= value; + } + + if (equivalent_usage != WACOM_HID_WD_TOUCHRINGSTATUS) + input_event(input, usage->type, usage->code, value); + + return 0; +} + +static void wacom_wac_pad_pre_report(struct hid_device *hdev, + struct hid_report *report) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + + wacom_wac->hid_data.inrange_state = 0; +} + +static void wacom_wac_pad_report(struct hid_device *hdev, + struct hid_report *report) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct input_dev *input = wacom_wac->pad_input; + bool active = wacom_wac->hid_data.inrange_state != 0; + + /* + * don't report prox for events like accelerometer + * or battery status + */ + if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) + input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0); + + input_sync(input); +} + static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage) { @@ -1946,10 +2044,11 @@ void wacom_wac_usage_mapping(struct hid_device *hdev, /* currently, only direct devices have proper hid report descriptors */ features->device_type |= WACOM_DEVICETYPE_DIRECT; - if (WACOM_PEN_FIELD(field)) + if (WACOM_PAD_FIELD(field)) + return wacom_wac_pad_usage_mapping(hdev, field, usage); + else if (WACOM_PEN_FIELD(field)) return wacom_wac_pen_usage_mapping(hdev, field, usage); - - if (WACOM_FINGER_FIELD(field)) + else if (WACOM_FINGER_FIELD(field)) return wacom_wac_finger_usage_mapping(hdev, field, usage); } @@ -1961,10 +2060,11 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field, if (wacom->wacom_wac.features.type != HID_GENERIC) return 0; - if (WACOM_PEN_FIELD(field)) + if (WACOM_PAD_FIELD(field)) + return wacom_wac_pad_event(hdev, field, usage, value); + else if (WACOM_PEN_FIELD(field)) return wacom_wac_pen_event(hdev, field, usage, value); - - if (WACOM_FINGER_FIELD(field)) + else if (WACOM_FINGER_FIELD(field)) return wacom_wac_finger_event(hdev, field, usage, value); return 0; @@ -1998,18 +2098,20 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) if (wacom_wac->features.type != HID_GENERIC) return; - if (WACOM_PEN_FIELD(field)) + if (WACOM_PAD_FIELD(field)) + wacom_wac_pad_pre_report(hdev, report); + else if (WACOM_PEN_FIELD(field)) wacom_wac_pen_pre_report(hdev, report); - - if (WACOM_FINGER_FIELD(field)) + else if (WACOM_FINGER_FIELD(field)) wacom_wac_finger_pre_report(hdev, report); wacom_report_events(hdev, report); - if (WACOM_PEN_FIELD(field)) + if (WACOM_PAD_FIELD(field)) + return wacom_wac_pad_report(hdev, report); + else if (WACOM_PEN_FIELD(field)) return wacom_wac_pen_report(hdev, report); - - if (WACOM_FINGER_FIELD(field)) + else if (WACOM_FINGER_FIELD(field)) return wacom_wac_finger_report(hdev, report); } @@ -2583,6 +2685,8 @@ void wacom_setup_device_quirks(struct wacom *wacom) struct wacom_features *features = &wacom->wacom_wac.features; /* The pen and pad share the same interface on most devices */ + if (features->numbered_buttons > 0) + features->device_type |= WACOM_DEVICETYPE_PAD; if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 || features->type == DTUS || (features->type >= INTUOS3S && features->type <= WACOM_MO)) { @@ -3104,8 +3208,12 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, __set_bit(ABS_MISC, input_dev->absbit); /* kept for making legacy xf86-input-wacom accepting the pad */ - input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0); + if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X].minimum || + input_dev->absinfo[ABS_X].maximum))) + input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0); + if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y].minimum || + input_dev->absinfo[ABS_Y].maximum))) + input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0); /* kept for making udev and libwacom accepting the pad */ __set_bit(BTN_STYLUS, input_dev->keybit); @@ -3225,6 +3333,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); break; + case HID_GENERIC: + break; + default: /* no pad supported */ return -ENODEV; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index b4c3c6425b85..1f7c4a86d91b 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -86,19 +86,34 @@ #define WACOM_DEVICETYPE_DIRECT 0x0010 #define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_SP_PAD 0x00040000 +#define WACOM_HID_SP_BUTTON 0x00090000 #define WACOM_HID_SP_DIGITIZER 0x000d0000 #define WACOM_HID_SP_DIGITIZERINFO 0x00100000 #define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) #define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) +#define WACOM_HID_WD_DIGITIZERFNKEYS (WACOM_HID_UP_WACOMDIGITIZER | 0x39) #define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) #define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77) #define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138) +#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139) +#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401) +#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402) +#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) +#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) +#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990) +#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991) +#define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992) +#define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993) +#define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994) #define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) #define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30) #define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31) #define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32) #define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33) #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) +#define WACOM_HID_WD_DIGITIZERINFO (WACOM_HID_UP_WACOMDIGITIZER | 0x1013) #define WACOM_HID_UP_G9 0xff090000 #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) #define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) @@ -106,6 +121,10 @@ #define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02) #define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11) +#define WACOM_PAD_FIELD(f) (((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \ + ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \ + ((f)->physical == WACOM_HID_WD_DIGITIZERINFO)) + #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \ -- cgit v1.2.3 From 93aab7fa4f8091d8fe2aed7e79a650fc1c084512 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:52 -0700 Subject: HID: wacom: generic: Add support for battery status on pen and pad interfaces Adds support for usages that may appear on the pen or pad interface which report the state of the tablet battery. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 41 ++++++++++++++++++++++++++++++++++++++++- drivers/hid/wacom_wac.h | 6 ++++++ include/linux/hid.h | 1 + 3 files changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 70de1fa930cc..f3edecf52c06 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1525,6 +1525,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); switch (equivalent_usage) { + case WACOM_HID_WD_BATTERY_LEVEL: + case WACOM_HID_WD_BATTERY_CHARGING: + features->quirks |= WACOM_QUIRK_BATTERY; + break; case WACOM_HID_WD_ACCELEROMETER_X: __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0); @@ -1574,8 +1578,25 @@ static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field, wacom_wac->hid_data.inrange_state |= value; } - if (equivalent_usage != WACOM_HID_WD_TOUCHRINGSTATUS) + switch (equivalent_usage) { + case WACOM_HID_WD_BATTERY_LEVEL: + wacom_wac->hid_data.battery_capacity = value; + wacom_wac->hid_data.bat_connected = 1; + return 0; + + case WACOM_HID_WD_BATTERY_CHARGING: + wacom_wac->hid_data.bat_charging = value; + wacom_wac->hid_data.ps_connected = value; + wacom_wac->hid_data.bat_connected = 1; + return 0; + + case WACOM_HID_WD_TOUCHRINGSTATUS: + return 0; + + default: input_event(input, usage->type, usage->code, value); + break; + } return 0; } @@ -1594,6 +1615,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_features *features = &wacom_wac->features; struct input_dev *input = wacom_wac->pad_input; bool active = wacom_wac->hid_data.inrange_state != 0; @@ -1604,6 +1626,16 @@ static void wacom_wac_pad_report(struct hid_device *hdev, if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0); + if (features->quirks & WACOM_QUIRK_BATTERY) { + int capacity = wacom_wac->hid_data.battery_capacity; + bool charging = wacom_wac->hid_data.bat_charging; + bool connected = wacom_wac->hid_data.bat_connected; + bool powered = wacom_wac->hid_data.ps_connected; + + wacom_notify_battery(wacom_wac, capacity, charging, + connected, powered); + } + input_sync(input); } @@ -1633,6 +1665,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, case HID_DG_INRANGE: wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0); break; + case HID_DG_BATTERYSTRENGTH: + features->quirks |= WACOM_QUIRK_BATTERY; + break; case HID_DG_INVERT: wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_RUBBER, 0); @@ -1703,6 +1738,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, if (!(features->quirks & WACOM_QUIRK_SENSE)) wacom_wac->hid_data.sense_state = value; return 0; + case HID_DG_BATTERYSTRENGTH: + wacom_wac->hid_data.battery_capacity = value; + wacom_wac->hid_data.bat_connected = 1; + break; case HID_DG_INVERT: wacom_wac->hid_data.invert_state = value; return 0; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 1f7c4a86d91b..7418c9715d31 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -101,6 +101,8 @@ #define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401) #define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402) #define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) +#define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404) +#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b) #define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) #define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990) #define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991) @@ -257,6 +259,10 @@ struct hid_data { int last_slot_field; int num_expected; int num_received; + int battery_capacity; + int bat_charging; + int bat_connected; + int ps_connected; }; struct wacom_remote_data { diff --git a/include/linux/hid.h b/include/linux/hid.h index e712101a1670..3baa2f962e48 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -231,6 +231,7 @@ struct hid_item { #define HID_DG_TAP 0x000d0035 #define HID_DG_TABLETFUNCTIONKEY 0x000d0039 #define HID_DG_PROGRAMCHANGEKEY 0x000d003a +#define HID_DG_BATTERYSTRENGTH 0x000d003b #define HID_DG_INVERT 0x000d003c #define HID_DG_TILT_X 0x000d003d #define HID_DG_TILT_Y 0x000d003e -- cgit v1.2.3 From bf78adcb6dc681624015a4390f0e5f656cb0270b Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:53 -0700 Subject: HID: wacom: generic: Extend pad support The HID specification that the MobileStudio Pro follows includes usages for several values that would be good to support so that future devices "just work" out of the box. Extend the HID_GENERIC pad codepath to handle these usages. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 15 +++++++++++++++ drivers/hid/wacom_wac.h | 5 +++++ 2 files changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index f3edecf52c06..0723ba8906fa 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1457,6 +1457,8 @@ static int wacom_equivalent_usage(int usage) usage == WACOM_HID_WD_SERIALHI || usage == WACOM_HID_WD_TOOLTYPE || usage == WACOM_HID_WD_DISTANCE || + usage == WACOM_HID_WD_TOUCHSTRIP || + usage == WACOM_HID_WD_TOUCHSTRIP2 || usage == WACOM_HID_WD_TOUCHRING || usage == WACOM_HID_WD_TOUCHRINGSTATUS) { return usage; @@ -1512,6 +1514,9 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, case EV_MSC: input_set_capability(input, EV_MSC, code); break; + case EV_SW: + input_set_capability(input, EV_SW, code); + break; } } @@ -1546,11 +1551,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, case WACOM_HID_WD_BUTTONDOWN: case WACOM_HID_WD_BUTTONLEFT: case WACOM_HID_WD_BUTTONRIGHT: + case WACOM_HID_WD_BUTTONCENTER: wacom_map_usage(input, usage, field, EV_KEY, wacom_numbered_button_to_key(features->numbered_buttons), 0); features->numbered_buttons++; break; + case WACOM_HID_WD_TOUCHONOFF: + wacom_map_usage(input, usage, field, EV_SW, SW_MUTE_DEVICE, 0); + break; + case WACOM_HID_WD_TOUCHSTRIP: + wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0); + break; + case WACOM_HID_WD_TOUCHSTRIP2: + wacom_map_usage(input, usage, field, EV_ABS, ABS_RY, 0); + break; case WACOM_HID_WD_TOUCHRING: wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); break; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 7418c9715d31..a54a3017a23f 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -96,6 +96,8 @@ #define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) #define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77) #define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_TOUCHSTRIP (WACOM_HID_UP_WACOMDIGITIZER | 0x0136) +#define WACOM_HID_WD_TOUCHSTRIP2 (WACOM_HID_UP_WACOMDIGITIZER | 0x0137) #define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138) #define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139) #define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401) @@ -104,11 +106,14 @@ #define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404) #define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b) #define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) +#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950) #define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990) #define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991) #define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992) #define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993) #define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994) +#define WACOM_HID_WD_BUTTONCENTER (WACOM_HID_UP_WACOMDIGITIZER | 0x0995) +#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0996) #define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) #define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30) #define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31) -- cgit v1.2.3 From c0bf57411b6b03dd72d4d20f362ba1ca72244834 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 19 Oct 2016 18:03:54 -0700 Subject: HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res The "Steering" usage (HID_UP_SIMULATION | 0xc8) is defined in HUT 1.12 as follows: "A steering wheel is a single degree-of-freedom device that rotates about an axis. The zero position is always the neutral or 'straight ahead' position, with positive values turning clockwise and negative values turning counterclockwise. If the Coordinate Values Wrap attribute is set, the steering wheel can be turned past 360 degrees." The hidinput_configure_usage function canonically maps this usage to the ABS_WHEEL axis, but hidinput_calc_abs_res does not recognize this axis as one for which it can calculate a resolution. This effectively prevents wheels from being assigned a proper resolution that userspace can use to determine the precise angle of input. This commit adds ABS_WHEEL as a rotational axis to hidinput_calc_abs_res. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-input.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index fb9ace1cef8b..c4e935b5fe74 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) case ABS_RX: case ABS_RY: case ABS_RZ: + case ABS_WHEEL: case ABS_TILT_X: case ABS_TILT_Y: if (field->unit == 0x14) { /* If degrees */ -- cgit v1.2.3 From feddf6e866c9cdbdec45b09f0a9566ea538a0da3 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Thu, 20 Oct 2016 17:15:03 +0800 Subject: drm/i915/gvt: clean up intel_gvt.h as interface for i915 core i915 core should only call functions and structures exposed through intel_gvt.h. Remove internal gvt.h and i915_pvinfo.h. Change for internal intel_gvt structure as private handler which not requires to expose gvt internal structure for i915 core. v2: Fix per Chris's comment - carefully handle dev_priv->gvt assignment - add necessary bracket for macro helper - forward declartion struct intel_gvt - keep free operation within same file handling alloc v3: fix use after free and remove intel_gvt.initialized v4: change to_gvt() to an inline Reviewed-by: Chris Wilson Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/aperture_gm.c | 1 + drivers/gpu/drm/i915/gvt/cfg_space.c | 1 + drivers/gpu/drm/i915/gvt/cmd_parser.c | 2 ++ drivers/gpu/drm/i915/gvt/display.c | 1 + drivers/gpu/drm/i915/gvt/edid.c | 1 + drivers/gpu/drm/i915/gvt/execlist.c | 1 + drivers/gpu/drm/i915/gvt/firmware.c | 2 ++ drivers/gpu/drm/i915/gvt/gtt.c | 2 ++ drivers/gpu/drm/i915/gvt/gvt.c | 19 +++++++++++++------ drivers/gpu/drm/i915/gvt/gvt.h | 7 +++++-- drivers/gpu/drm/i915/gvt/handlers.c | 2 ++ drivers/gpu/drm/i915/gvt/interrupt.c | 1 + drivers/gpu/drm/i915/gvt/mmio.c | 1 + drivers/gpu/drm/i915/gvt/opregion.c | 1 + drivers/gpu/drm/i915/gvt/render.c | 1 + drivers/gpu/drm/i915/gvt/sched_policy.c | 1 + drivers/gpu/drm/i915/gvt/scheduler.c | 5 +++-- drivers/gpu/drm/i915/gvt/vgpu.c | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/intel_gvt.h | 3 +-- 20 files changed, 44 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index e0211f83bd93..db503c164b2f 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -35,6 +35,7 @@ */ #include "i915_drv.h" +#include "gvt.h" #define MB_TO_BYTES(mb) ((mb) << 20ULL) #define BYTES_TO_MB(b) ((b) >> 20ULL) diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index 16360e449ed0..4c687740f5f1 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -32,6 +32,7 @@ */ #include "i915_drv.h" +#include "gvt.h" enum { INTEL_GVT_PCI_BAR_GTTMMIO = 0, diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 5808ee7c1935..5b4658ff4d8a 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -36,6 +36,8 @@ #include #include "i915_drv.h" +#include "gvt.h" +#include "i915_pvinfo.h" #include "trace.h" #define INVALID_OP (~0U) diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 534000b91681..d8908d4cd09a 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -33,6 +33,7 @@ */ #include "i915_drv.h" +#include "gvt.h" static int get_edp_pipe(struct intel_vgpu *vgpu) { diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c index a07e4276126c..7e1da1c563ca 100644 --- a/drivers/gpu/drm/i915/gvt/edid.c +++ b/drivers/gpu/drm/i915/gvt/edid.c @@ -33,6 +33,7 @@ */ #include "i915_drv.h" +#include "gvt.h" #define GMBUS1_TOTAL_BYTES_SHIFT 16 #define GMBUS1_TOTAL_BYTES_MASK 0x1ff diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index c50a3d1a5131..b87b4f5e4c8f 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -33,6 +33,7 @@ */ #include "i915_drv.h" +#include "gvt.h" #define _EL_OFFSET_STATUS 0x234 #define _EL_OFFSET_STATUS_BUF 0x370 diff --git a/drivers/gpu/drm/i915/gvt/firmware.c b/drivers/gpu/drm/i915/gvt/firmware.c index 4578a4d69a09..d068a524a699 100644 --- a/drivers/gpu/drm/i915/gvt/firmware.c +++ b/drivers/gpu/drm/i915/gvt/firmware.c @@ -32,6 +32,8 @@ #include #include "i915_drv.h" +#include "gvt.h" +#include "i915_pvinfo.h" #define FIRMWARE_VERSION (0x0) diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 29de179920e8..0722d1e61fce 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -34,6 +34,8 @@ */ #include "i915_drv.h" +#include "gvt.h" +#include "i915_pvinfo.h" #include "trace.h" static bool enable_out_of_sync = false; diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index e72e26c61a15..31b59d40f3fb 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -35,6 +35,7 @@ #include #include "i915_drv.h" +#include "gvt.h" struct intel_gvt_host intel_gvt_host; @@ -173,9 +174,9 @@ static int init_service_thread(struct intel_gvt *gvt) */ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) { - struct intel_gvt *gvt = &dev_priv->gvt; + struct intel_gvt *gvt = to_gvt(dev_priv); - if (WARN_ON(!gvt->initialized)) + if (WARN_ON(!gvt)) return; clean_service_thread(gvt); @@ -188,7 +189,8 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) intel_gvt_clean_mmio_info(gvt); intel_gvt_free_firmware(gvt); - gvt->initialized = false; + kfree(dev_priv->gvt); + dev_priv->gvt = NULL; } /** @@ -204,7 +206,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) */ int intel_gvt_init_device(struct drm_i915_private *dev_priv) { - struct intel_gvt *gvt = &dev_priv->gvt; + struct intel_gvt *gvt; int ret; /* @@ -214,9 +216,13 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) if (WARN_ON(!intel_gvt_host.initialized)) return -EINVAL; - if (WARN_ON(gvt->initialized)) + if (WARN_ON(dev_priv->gvt)) return -EEXIST; + gvt = kzalloc(sizeof(struct intel_gvt), GFP_KERNEL); + if (!gvt) + return -ENOMEM; + gvt_dbg_core("init gvt device\n"); mutex_init(&gvt->lock); @@ -261,7 +267,7 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) goto out_clean_cmd_parser; gvt_dbg_core("gvt device creation is done\n"); - gvt->initialized = true; + dev_priv->gvt = gvt; return 0; out_clean_cmd_parser: @@ -280,5 +286,6 @@ out_free_firmware: intel_gvt_free_firmware(gvt); out_clean_mmio_info: intel_gvt_clean_mmio_info(gvt); + kfree(gvt); return ret; } diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 1564554b7459..15c595e0a63b 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -192,8 +192,6 @@ struct intel_gvt_opregion { struct intel_gvt { struct mutex lock; - bool initialized; - struct drm_i915_private *dev_priv; struct idr vgpu_idr; /* vGPU IDR pool */ @@ -213,6 +211,11 @@ struct intel_gvt { unsigned long service_request; }; +static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915) +{ + return i915->gvt; +} + enum { INTEL_GVT_REQUEST_EMULATE_VBLANK = 0, }; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index e8ec403b75a1..b21115fecf86 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -37,6 +37,8 @@ */ #include "i915_drv.h" +#include "gvt.h" +#include "i915_pvinfo.h" /* XXX FIXME i915 has changed PP_XXX definition */ #define PCH_PP_STATUS _MMIO(0xc7200) diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c index 84d7174d0081..e43ef7228557 100644 --- a/drivers/gpu/drm/i915/gvt/interrupt.c +++ b/drivers/gpu/drm/i915/gvt/interrupt.c @@ -30,6 +30,7 @@ */ #include "i915_drv.h" +#include "gvt.h" /* common offset among interrupt control registers */ #define regbase_to_isr(base) (base) diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index ce3af95d049f..585b01f63254 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -34,6 +34,7 @@ */ #include "i915_drv.h" +#include "gvt.h" /** * intel_vgpu_gpa_to_mmio_offset - translate a GPA to MMIO offset diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c index 46cc2407a0a2..53ac81f63c64 100644 --- a/drivers/gpu/drm/i915/gvt/opregion.c +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -23,6 +23,7 @@ #include #include "i915_drv.h" +#include "gvt.h" static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa) { diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index f54ab8540b12..feebb65ba641 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -34,6 +34,7 @@ */ #include "i915_drv.h" +#include "gvt.h" struct render_mmio { int ring_id; diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index c607354c3798..278db0c180fc 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -32,6 +32,7 @@ */ #include "i915_drv.h" +#include "gvt.h" static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu) { diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index b15cdf5978a9..01d23ad03637 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -33,10 +33,11 @@ * */ -#include "i915_drv.h" - #include +#include "i915_drv.h" +#include "gvt.h" + #define RING_CTX_OFF(x) \ offsetof(struct execlist_ring_context, x) diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index e5e0a72336c8..9401436d721f 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -32,6 +32,8 @@ */ #include "i915_drv.h" +#include "gvt.h" +#include "i915_pvinfo.h" static void clean_vgpu_mmio(struct intel_vgpu *vgpu) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4d1133ffe093..5024ad91d132 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1778,7 +1778,7 @@ struct drm_i915_private { struct i915_virtual_gpu vgpu; - struct intel_gvt gvt; + struct intel_gvt *gvt; struct intel_guc guc; @@ -2992,7 +2992,7 @@ int intel_wait_for_register_fw(struct drm_i915_private *dev_priv, static inline bool intel_gvt_active(struct drm_i915_private *dev_priv) { - return dev_priv->gvt.initialized; + return dev_priv->gvt; } static inline bool intel_vgpu_active(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_gvt.h b/drivers/gpu/drm/i915/intel_gvt.h index 0f00105f4c5d..25df2d65b985 100644 --- a/drivers/gpu/drm/i915/intel_gvt.h +++ b/drivers/gpu/drm/i915/intel_gvt.h @@ -24,8 +24,7 @@ #ifndef _INTEL_GVT_H_ #define _INTEL_GVT_H_ -#include "i915_pvinfo.h" -#include "gvt/gvt.h" +struct intel_gvt; #ifdef CONFIG_DRM_I915_GVT int intel_gvt_init(struct drm_i915_private *dev_priv); -- cgit v1.2.3 From bbc3693351fcf4ab74b0913e15189362588cd34f Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 19 Oct 2016 12:36:56 +0800 Subject: drm/i915/gvt: Fix warning on obsolete function usage Don't use obsolete drm_gem_object_unreference() but switch to i915_gem_object_put(). Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index b87b4f5e4c8f..983bf863bc1f 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -499,7 +499,7 @@ static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb, list) { - drm_gem_object_unreference(&(entry_obj->obj->base)); + i915_gem_object_put(entry_obj->obj); kvfree(entry_obj->va); list_del(&entry_obj->list); kfree(entry_obj); @@ -512,7 +512,7 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) if (wa_ctx->indirect_ctx.size == 0) return; - drm_gem_object_unreference(&(wa_ctx->indirect_ctx.obj->base)); + i915_gem_object_put(wa_ctx->indirect_ctx.obj); kvfree(wa_ctx->indirect_ctx.shadow_va); } -- cgit v1.2.3 From 22681c7bc79aefbb8e1c459474ac668a9493b577 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 19 Oct 2016 14:40:59 +0800 Subject: Documentation/gpu: Add section for Intel GVT-g host support Update with brief overview and reference for more detailed arch design documents. Add new section for Intel GVT-g host support. Signed-off-by: Zhenyu Wang --- Documentation/gpu/i915.rst | 9 +++++++++ drivers/gpu/drm/i915/intel_gvt.c | 8 ++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index 87aaffc22920..95ce77ff4342 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -49,6 +49,15 @@ Intel GVT-g Guest Support(vGPU) .. kernel-doc:: drivers/gpu/drm/i915/i915_vgpu.c :internal: +Intel GVT-g Host Support(vGPU device model) +------------------------------------------- + +.. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c + :doc: Intel GVT-g host support + +.. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c + :internal: + Display Hardware Handling ========================= diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index 8e8596da89b1..290384e86c63 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -31,8 +31,12 @@ * GPU among multiple virtual machines on a time-sharing basis. Each * virtual machine is presented a virtual GPU (vGPU), which has equivalent * features as the underlying physical GPU (pGPU), so i915 driver can run - * seamlessly in a virtual machine. This file provides the englightments - * of GVT and the necessary components used by GVT in i915 driver. + * seamlessly in a virtual machine. + * + * To virtualize GPU resources GVT-g driver depends on hypervisor technology + * e.g KVM/VFIO/mdev, Xen, etc. to provide resource access trapping capability + * and be virtualized within GVT-g device module. More architectural design + * doc is available on https://01.org/group/2230/documentation-list. */ static bool is_supported_device(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From 75ea10da063f96d81828316cc25a896ae523c826 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:37 +0100 Subject: drm/i915/gvt: Add runtime pm around fences Manipulating the fence_list requires the runtime wakelock, as does writing to the fence registers. Acquire a wakelock for the former, and assert that the device is awake for the latter. Signed-off-by: Chris Wilson Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/aperture_gm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index db503c164b2f..0d41ebc4aea6 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -145,6 +145,8 @@ void intel_vgpu_write_fence(struct intel_vgpu *vgpu, struct drm_i915_fence_reg *reg; i915_reg_t fence_reg_lo, fence_reg_hi; + assert_rpm_wakelock_held(dev_priv); + if (WARN_ON(fence > vgpu_fence_sz(vgpu))) return; @@ -173,6 +175,8 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu) if (WARN_ON(!vgpu_fence_sz(vgpu))) return; + intel_runtime_pm_get(dev_priv); + mutex_lock(&dev_priv->drm.struct_mutex); for (i = 0; i < vgpu_fence_sz(vgpu); i++) { reg = vgpu->fence.regs[i]; @@ -181,6 +185,8 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu) &dev_priv->mm.fence_list); } mutex_unlock(&dev_priv->drm.struct_mutex); + + intel_runtime_pm_put(dev_priv); } static int alloc_vgpu_fence(struct intel_vgpu *vgpu) @@ -191,6 +197,8 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu) int i; struct list_head *pos, *q; + intel_runtime_pm_get(dev_priv); + /* Request fences from host */ mutex_lock(&dev_priv->drm.struct_mutex); i = 0; @@ -208,6 +216,7 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu) goto out_free_fence; mutex_unlock(&dev_priv->drm.struct_mutex); + intel_runtime_pm_put(dev_priv); return 0; out_free_fence: /* Return fences to host, if fail */ @@ -219,6 +228,7 @@ out_free_fence: &dev_priv->mm.fence_list); } mutex_unlock(&dev_priv->drm.struct_mutex); + intel_runtime_pm_put(dev_priv); return -ENOSPC; } -- cgit v1.2.3 From 894cf7d156346986946cc573dc8c251804dc8321 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:38 +0100 Subject: drm/i915/gvt: i915_gem_object_create() returns an error pointer On failure from i915_gem_object_create(), we need to check for an error pointer not NULL. Signed-off-by: Chris Wilson Reviewed-by: Zhenyu Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 48 ++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 5b4658ff4d8a..d942da9a0c8a 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1640,16 +1640,19 @@ static int perform_bb_shadow(struct parser_exec_state *s) if (entry_obj == NULL) return -ENOMEM; - entry_obj->obj = i915_gem_object_create(&(s->vgpu->gvt->dev_priv->drm), - round_up(bb_size, PAGE_SIZE)); - if (entry_obj->obj == NULL) - return -ENOMEM; + entry_obj->obj = + i915_gem_object_create(&(s->vgpu->gvt->dev_priv->drm), + roundup(bb_size, PAGE_SIZE)); + if (IS_ERR(entry_obj->obj)) { + ret = PTR_ERR(entry_obj->obj); + goto free_entry; + } entry_obj->len = bb_size; INIT_LIST_HEAD(&entry_obj->list); ret = i915_gem_object_get_pages(entry_obj->obj); if (ret) - return ret; + goto put_obj; i915_gem_object_pin_pages(entry_obj->obj); @@ -1675,7 +1678,7 @@ static int perform_bb_shadow(struct parser_exec_state *s) gma, gma + bb_size, dst); if (ret) { gvt_err("fail to copy guest ring buffer\n"); - return ret; + goto unmap_src; } list_add(&entry_obj->list, &s->workload->shadow_bb); @@ -1696,7 +1699,10 @@ unmap_src: vunmap(dst); unpin_src: i915_gem_object_unpin_pages(entry_obj->obj); - +put_obj: + i915_gem_object_put(entry_obj->obj); +free_entry: + kfree(entry_obj); return ret; } @@ -2709,31 +2715,31 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) struct drm_device *dev = &wa_ctx->workload->vgpu->gvt->dev_priv->drm; int ctx_size = wa_ctx->indirect_ctx.size; unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma; + struct drm_i915_gem_object *obj; int ret = 0; void *dest = NULL; - wa_ctx->indirect_ctx.obj = i915_gem_object_create(dev, - round_up(ctx_size + CACHELINE_BYTES, PAGE_SIZE)); - if (wa_ctx->indirect_ctx.obj == NULL) - return -ENOMEM; + obj = i915_gem_object_create(dev, + roundup(ctx_size + CACHELINE_BYTES, + PAGE_SIZE)); + if (IS_ERR(obj)) + return PTR_ERR(obj); - ret = i915_gem_object_get_pages(wa_ctx->indirect_ctx.obj); + ret = i915_gem_object_get_pages(obj); if (ret) - return ret; + goto put_obj; - i915_gem_object_pin_pages(wa_ctx->indirect_ctx.obj); + i915_gem_object_pin_pages(obj); /* get the va of the shadow batch buffer */ - dest = (void *)vmap_batch(wa_ctx->indirect_ctx.obj, 0, - ctx_size + CACHELINE_BYTES); + dest = (void *)vmap_batch(obj, 0, ctx_size + CACHELINE_BYTES); if (!dest) { gvt_err("failed to vmap shadow indirect ctx\n"); ret = -ENOMEM; goto unpin_src; } - ret = i915_gem_object_set_to_cpu_domain(wa_ctx->indirect_ctx.obj, - false); + ret = i915_gem_object_set_to_cpu_domain(obj, false); if (ret) { gvt_err("failed to set shadow indirect ctx to CPU\n"); goto unmap_src; @@ -2748,16 +2754,18 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) guest_gma, guest_gma + ctx_size, dest); if (ret) { gvt_err("fail to copy guest indirect ctx\n"); - return ret; + goto unmap_src; } + wa_ctx->indirect_ctx.obj = obj; return 0; unmap_src: vunmap(dest); unpin_src: i915_gem_object_unpin_pages(wa_ctx->indirect_ctx.obj); - +put_obj: + i915_gem_object_put(wa_ctx->indirect_ctx.obj); return ret; } -- cgit v1.2.3 From b6d891429d29f4ff7cacbaa5c4bb1511797a4bce Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:40 +0100 Subject: drm/i915/gvt: Use the returned VMA to provide the virtual address The purpose of returning the just-pinned VMA is so that we can use the information within, like its address. Also it should be tracked and used as the cookie to unpin... Signed-off-by: Chris Wilson Reviewed-by: Zhenyu Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 983bf863bc1f..f865ce0c7727 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -386,8 +386,6 @@ static int set_gma_to_bb_cmd(struct intel_shadow_bb_entry *entry_obj, static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) { int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd; - struct i915_vma *vma; - unsigned long gma; /* pin the gem object to ggtt */ if (!list_empty(&workload->shadow_bb)) { @@ -399,8 +397,10 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb, list) { + struct i915_vma *vma; + vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, - 0, 0); + 4, 0); if (IS_ERR(vma)) { gvt_err("Cannot pin\n"); return; @@ -408,9 +408,9 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) i915_gem_object_unpin_pages(entry_obj->obj); /* update the relocate gma with shadow batch buffer*/ - gma = i915_gem_object_ggtt_offset(entry_obj->obj, NULL); - WARN_ON(!IS_ALIGNED(gma, 4)); - set_gma_to_bb_cmd(entry_obj, gma, gmadr_bytes); + set_gma_to_bb_cmd(entry_obj, + i915_ggtt_offset(vma), + gmadr_bytes); } } } @@ -442,7 +442,6 @@ static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) { struct i915_vma *vma; - unsigned long gma; unsigned char *per_ctx_va = (unsigned char *)wa_ctx->indirect_ctx.shadow_va + wa_ctx->indirect_ctx.size; @@ -450,16 +449,15 @@ static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) if (wa_ctx->indirect_ctx.size == 0) return; - vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL, 0, 0, 0); + vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL, + 0, CACHELINE_BYTES, 0); if (IS_ERR(vma)) { gvt_err("Cannot pin indirect ctx obj\n"); return; } i915_gem_object_unpin_pages(wa_ctx->indirect_ctx.obj); - gma = i915_gem_object_ggtt_offset(wa_ctx->indirect_ctx.obj, NULL); - WARN_ON(!IS_ALIGNED(gma, CACHELINE_BYTES)); - wa_ctx->indirect_ctx.shadow_gma = gma; + wa_ctx->indirect_ctx.shadow_gma = i915_ggtt_offset(vma); wa_ctx->per_ctx.shadow_gma = *((unsigned int *)per_ctx_va + 1); memset(per_ctx_va, 0, CACHELINE_BYTES); -- cgit v1.2.3 From eeacd86efa53e6328c63b79d1999a7d214972278 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:41 +0100 Subject: drm/i915/gvt: Remove dangerous unpin of backing storage of bound GPU object Unpinning the pages prior to the object being release from the GPU may allow the GPU to read and write into system pages (i.e. use after free by the hw). Signed-off-by: Chris Wilson Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index f865ce0c7727..5534336814f0 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -405,7 +405,11 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) gvt_err("Cannot pin\n"); return; } - i915_gem_object_unpin_pages(entry_obj->obj); + + /* FIXME: we are not tracking our pinned VMA leaving it + * up to the core to fix up the stray pin_count upon + * free. + */ /* update the relocate gma with shadow batch buffer*/ set_gma_to_bb_cmd(entry_obj, @@ -455,7 +459,11 @@ static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) gvt_err("Cannot pin indirect ctx obj\n"); return; } - i915_gem_object_unpin_pages(wa_ctx->indirect_ctx.obj); + + /* FIXME: we are not tracking our pinned VMA leaving it + * up to the core to fix up the stray pin_count upon + * free. + */ wa_ctx->indirect_ctx.shadow_gma = i915_ggtt_offset(vma); -- cgit v1.2.3 From 0eb742d7af224481ab7abb7b38bd7166e47661e2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 20 Oct 2016 17:29:36 +0800 Subject: drm/i915/gvt: Hold a reference on the request The workload took a pointer to the request, and even waited upon, without holding a reference on the request. Take that reference explicitly and fix up the error path following request allocation that missed flushing the request. v2: [zhenyuw] - drop request put in error path for dispatch, as main thread caller will handle it identically to a real request. Signed-off-by: Chris Wilson Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/scheduler.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 01d23ad03637..3c2d8e9b2d3f 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -164,6 +164,7 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) int ring_id = workload->ring_id; struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; + struct drm_i915_gem_request *rq; int ret; gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n", @@ -172,17 +173,16 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) shadow_ctx->desc_template = workload->ctx_desc.addressing_mode << GEN8_CTX_ADDRESSING_MODE_SHIFT; - workload->req = i915_gem_request_alloc(dev_priv->engine[ring_id], - shadow_ctx); - if (IS_ERR_OR_NULL(workload->req)) { + rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); + if (IS_ERR(rq)) { gvt_err("fail to allocate gem request\n"); - workload->status = PTR_ERR(workload->req); - workload->req = NULL; + workload->status = PTR_ERR(rq); return workload->status; } - gvt_dbg_sched("ring id %d get i915 gem request %p\n", - ring_id, workload->req); + gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq); + + workload->req = i915_gem_request_get(rq); mutex_lock(&gvt->lock); @@ -209,16 +209,15 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) gvt_dbg_sched("ring id %d submit workload to i915 %p\n", ring_id, workload->req); - i915_add_request_no_flush(workload->req); - + i915_add_request_no_flush(rq); workload->dispatched = true; return 0; err: workload->status = ret; - if (workload->req) - workload->req = NULL; mutex_unlock(&gvt->lock); + + i915_add_request_no_flush(rq); return ret; } @@ -459,6 +458,8 @@ complete: complete_current_workload(gvt, ring_id); + i915_gem_request_put(fetch_and_zero(&workload->req)); + if (need_force_wake) intel_uncore_forcewake_put(gvt->dev_priv, FORCEWAKE_ALL); -- cgit v1.2.3 From f460c251ea37836c57584a18981820fbde809d1d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:43 +0100 Subject: drm/i915/gvt: Stop checking for impossible interrupts from a kthread The kthread will not be interrupted, don't even bother checking. Signed-off-by: Chris Wilson Reviewed-by: Zhenyu Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/scheduler.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 3c2d8e9b2d3f..9c508c307ff0 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -423,12 +423,7 @@ static int workload_thread(void *priv) /* * Always take i915 big lock first */ - ret = i915_mutex_lock_interruptible(&gvt->dev_priv->drm); - if (ret < 0) { - gvt_err("i915 submission is not available, retry\n"); - schedule_timeout(1); - continue; - } + mutex_lock(&gvt->dev_priv->drm.struct_mutex); gvt_dbg_sched("ring id %d will dispatch workload %p\n", workload->ring_id, workload); @@ -447,7 +442,7 @@ static int workload_thread(void *priv) workload->ring_id, workload); workload->status = i915_wait_request(workload->req, - I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, + I915_WAIT_LOCKED, NULL, NULL); if (workload->status != 0) gvt_err("fail to wait workload, skip\n"); -- cgit v1.2.3 From 66bbc3b2b16b4d15de0bd737147538bcf4d355b6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:44 +0100 Subject: drm/i915/gvt: Stop waiting whilst holding struct_mutex For whatever reason, the gvt scheduler runs synchronously. At the very least, lets run synchronously without holding the struct_mutex. v2: cut'n'paste mutex_lock instead of unlock. Replace long hold of struct_mutex with a mutex to serialise the worker threads. Signed-off-by: Chris Wilson Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/scheduler.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 9c508c307ff0..12f825512e9b 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -390,6 +390,8 @@ struct workload_thread_param { int ring_id; }; +static DEFINE_MUTEX(scheduler_mutex); + static int workload_thread(void *priv) { struct workload_thread_param *p = (struct workload_thread_param *)priv; @@ -414,17 +416,14 @@ static int workload_thread(void *priv) if (kthread_should_stop()) break; + mutex_lock(&scheduler_mutex); + gvt_dbg_sched("ring id %d next workload %p vgpu %d\n", workload->ring_id, workload, workload->vgpu->id); intel_runtime_pm_get(gvt->dev_priv); - /* - * Always take i915 big lock first - */ - mutex_lock(&gvt->dev_priv->drm.struct_mutex); - gvt_dbg_sched("ring id %d will dispatch workload %p\n", workload->ring_id, workload); @@ -432,7 +431,10 @@ static int workload_thread(void *priv) intel_uncore_forcewake_get(gvt->dev_priv, FORCEWAKE_ALL); + mutex_lock(&gvt->dev_priv->drm.struct_mutex); ret = dispatch_workload(workload); + mutex_unlock(&gvt->dev_priv->drm.struct_mutex); + if (ret) { gvt_err("fail to dispatch workload, skip\n"); goto complete; @@ -442,8 +444,7 @@ static int workload_thread(void *priv) workload->ring_id, workload); workload->status = i915_wait_request(workload->req, - I915_WAIT_LOCKED, - NULL, NULL); + 0, NULL, NULL); if (workload->status != 0) gvt_err("fail to wait workload, skip\n"); @@ -451,7 +452,9 @@ complete: gvt_dbg_sched("will complete workload %p\n, status: %d\n", workload, workload->status); + mutex_lock(&gvt->dev_priv->drm.struct_mutex); complete_current_workload(gvt, ring_id); + mutex_unlock(&gvt->dev_priv->drm.struct_mutex); i915_gem_request_put(fetch_and_zero(&workload->req)); @@ -459,9 +462,10 @@ complete: intel_uncore_forcewake_put(gvt->dev_priv, FORCEWAKE_ALL); - mutex_unlock(&gvt->dev_priv->drm.struct_mutex); - intel_runtime_pm_put(gvt->dev_priv); + + mutex_unlock(&scheduler_mutex); + } return 0; } -- cgit v1.2.3 From bcd0aeded478f1ed6dfbbeafc3e2581c4021a99c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:45 +0100 Subject: drm/i915/gvt: Use common mapping routines for indirect_ctx object We have the ability to map an object, so use it rather than opencode it badly. Signed-off-by: Chris Wilson Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 28 +++++++++------------------- drivers/gpu/drm/i915/gvt/execlist.c | 2 +- 2 files changed, 10 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index d942da9a0c8a..153943a9411e 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -2717,7 +2717,7 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma; struct drm_i915_gem_object *obj; int ret = 0; - void *dest = NULL; + void *map; obj = i915_gem_object_create(dev, roundup(ctx_size + CACHELINE_BYTES, @@ -2725,18 +2725,12 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) if (IS_ERR(obj)) return PTR_ERR(obj); - ret = i915_gem_object_get_pages(obj); - if (ret) - goto put_obj; - - i915_gem_object_pin_pages(obj); - /* get the va of the shadow batch buffer */ - dest = (void *)vmap_batch(obj, 0, ctx_size + CACHELINE_BYTES); - if (!dest) { + map = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(map)) { gvt_err("failed to vmap shadow indirect ctx\n"); - ret = -ENOMEM; - goto unpin_src; + ret = PTR_ERR(map); + goto put_obj; } ret = i915_gem_object_set_to_cpu_domain(obj, false); @@ -2745,25 +2739,21 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) goto unmap_src; } - wa_ctx->indirect_ctx.shadow_va = dest; - - memset(dest, 0, round_up(ctx_size + CACHELINE_BYTES, PAGE_SIZE)); - ret = copy_gma_to_hva(wa_ctx->workload->vgpu, wa_ctx->workload->vgpu->gtt.ggtt_mm, - guest_gma, guest_gma + ctx_size, dest); + guest_gma, guest_gma + ctx_size, + map); if (ret) { gvt_err("fail to copy guest indirect ctx\n"); goto unmap_src; } wa_ctx->indirect_ctx.obj = obj; + wa_ctx->indirect_ctx.shadow_va = map; return 0; unmap_src: - vunmap(dest); -unpin_src: - i915_gem_object_unpin_pages(wa_ctx->indirect_ctx.obj); + i915_gem_object_unpin_map(obj); put_obj: i915_gem_object_put(wa_ctx->indirect_ctx.obj); return ret; diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 5534336814f0..88430ca23504 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -518,8 +518,8 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) if (wa_ctx->indirect_ctx.size == 0) return; + i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj); i915_gem_object_put(wa_ctx->indirect_ctx.obj); - kvfree(wa_ctx->indirect_ctx.shadow_va); } static int complete_execlist_workload(struct intel_vgpu_workload *workload) -- cgit v1.2.3 From a28615041ea2d1645143b868cd5ea65e9cf28381 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:46 +0100 Subject: drm/i915/gvt: Use common mapping routines for shadow_bb object We have the ability to map an object, so use it rather than opencode it badly. Note that the object remains permanently pinned, this is poor practise. Signed-off-by: Chris Wilson Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 21 ++++++--------------- drivers/gpu/drm/i915/gvt/execlist.c | 2 +- 2 files changed, 7 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 153943a9411e..ff719e77a594 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1650,18 +1650,10 @@ static int perform_bb_shadow(struct parser_exec_state *s) entry_obj->len = bb_size; INIT_LIST_HEAD(&entry_obj->list); - ret = i915_gem_object_get_pages(entry_obj->obj); - if (ret) + dst = i915_gem_object_pin_map(entry_obj->obj, I915_MAP_WB); + if (IS_ERR(dst)) { + ret = PTR_ERR(dst); goto put_obj; - - i915_gem_object_pin_pages(entry_obj->obj); - - /* get the va of the shadow batch buffer */ - dst = (void *)vmap_batch(entry_obj->obj, 0, bb_size); - if (!dst) { - gvt_err("failed to vmap shadow batch\n"); - ret = -ENOMEM; - goto unpin_src; } ret = i915_gem_object_set_to_cpu_domain(entry_obj->obj, false); @@ -1675,7 +1667,8 @@ static int perform_bb_shadow(struct parser_exec_state *s) /* copy batch buffer to shadow batch buffer*/ ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, - gma, gma + bb_size, dst); + gma, gma + bb_size, + dst); if (ret) { gvt_err("fail to copy guest ring buffer\n"); goto unmap_src; @@ -1696,9 +1689,7 @@ static int perform_bb_shadow(struct parser_exec_state *s) return 0; unmap_src: - vunmap(dst); -unpin_src: - i915_gem_object_unpin_pages(entry_obj->obj); + i915_gem_object_unpin_map(entry_obj->obj); put_obj: i915_gem_object_put(entry_obj->obj); free_entry: diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 88430ca23504..d4bd29306d84 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -505,8 +505,8 @@ static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb, list) { + i915_gem_object_unpin_map(entry_obj->obj); i915_gem_object_put(entry_obj->obj); - kvfree(entry_obj->va); list_del(&entry_obj->list); kfree(entry_obj); } -- cgit v1.2.3 From 3eec872207cc8230bc98cffa8895173e4effacb2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 11:11:47 +0100 Subject: drm/i915/gvt: Remove defunct vmap_batch() This code was removed from i915_cmd_parser.c but still an obsolete version wound up being duplicated into gvt/cmd_parser.c. Good riddance. Signed-off-by: Chris Wilson Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 38 ----------------------------------- 1 file changed, 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index ff719e77a594..0d322e035d9f 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1583,44 +1583,6 @@ static uint32_t find_bb_size(struct parser_exec_state *s) return bb_size; } -static u32 *vmap_batch(struct drm_i915_gem_object *obj, - unsigned int start, unsigned int len) -{ - int i; - void *addr = NULL; - struct sg_page_iter sg_iter; - int first_page = start >> PAGE_SHIFT; - int last_page = (len + start + 4095) >> PAGE_SHIFT; - int npages = last_page - first_page; - struct page **pages; - - pages = drm_malloc_ab(npages, sizeof(*pages)); - if (pages == NULL) { - DRM_DEBUG_DRIVER("Failed to get space for pages\n"); - goto finish; - } - - i = 0; - for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, - first_page) { - pages[i++] = sg_page_iter_page(&sg_iter); - if (i == npages) - break; - } - - addr = vmap(pages, i, 0, PAGE_KERNEL); - if (addr == NULL) { - DRM_DEBUG_DRIVER("Failed to vmap pages\n"); - goto finish; - } - -finish: - if (pages) - drm_free_large(pages); - return (u32 *)addr; -} - - static int perform_bb_shadow(struct parser_exec_state *s) { struct intel_shadow_bb_entry *entry_obj; -- cgit v1.2.3 From 0fac21e7e978f8556d3f9bb1b2fadfc722bfe992 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Thu, 20 Oct 2016 13:30:33 +0800 Subject: drm/i915/gvt: properly access enabled intel_engine_cs Switch to use new for_each_engine() helper to properly access enabled intel_engine_cs as i915 core has changed that to be dynamic managed. At GVT-g init time would still depend on ring mask to determine engine list as it's earlier. Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 5 +++-- drivers/gpu/drm/i915/gvt/handlers.c | 11 ++++++----- drivers/gpu/drm/i915/gvt/sched_policy.c | 12 +++++++----- drivers/gpu/drm/i915/gvt/scheduler.c | 4 ++++ 4 files changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index d4bd29306d84..0e9b340897e3 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -817,10 +817,11 @@ void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu) int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) { - int i; + enum intel_engine_id i; + struct intel_engine_cs *engine; /* each ring has a virtual execlist engine */ - for (i = 0; i < I915_NUM_ENGINES; i++) { + for_each_engine(engine, vgpu->gvt->dev_priv, i) { init_vgpu_execlist(vgpu, i); INIT_LIST_HEAD(&vgpu->workload_q_head[i]); } diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index b21115fecf86..3e74fb3d4aa9 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -132,12 +132,13 @@ static int new_mmio_info(struct intel_gvt *gvt, static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg) { - int i; + enum intel_engine_id id; + struct intel_engine_cs *engine; reg &= ~GENMASK(11, 0); - for (i = 0; i < I915_NUM_ENGINES; i++) { - if (gvt->dev_priv->engine[i]->mmio_base == reg) - return i; + for_each_engine(engine, gvt->dev_priv, id) { + if (engine->mmio_base == reg) + return id; } return -1; } @@ -1306,7 +1307,7 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, u32 data = *(u32 *)p_data; int ret; - if (WARN_ON(ring_id < 0)) + if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1)) return -EINVAL; execlist = &vgpu->execlist[ring_id]; diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index 278db0c180fc..b605ac6137eb 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -37,9 +37,10 @@ static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu) { struct intel_vgpu_execlist *execlist; - int i; + enum intel_engine_id i; + struct intel_engine_cs *engine; - for (i = 0; i < I915_NUM_ENGINES; i++) { + for_each_engine(engine, vgpu->gvt->dev_priv, i) { execlist = &vgpu->execlist[i]; if (!list_empty(workload_q_head(vgpu, i))) return true; @@ -51,7 +52,8 @@ static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu) static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) { struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; - int i; + enum intel_engine_id i; + struct intel_engine_cs *engine; /* no target to schedule */ if (!scheduler->next_vgpu) @@ -67,7 +69,7 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) scheduler->need_reschedule = true; /* still have uncompleted workload? */ - for (i = 0; i < I915_NUM_ENGINES; i++) { + for_each_engine(engine, gvt->dev_priv, i) { if (scheduler->current_workload[i]) { gvt_dbg_sched("still have running workload\n"); return; @@ -84,7 +86,7 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) scheduler->need_reschedule = false; /* wake up workload dispatch thread */ - for (i = 0; i < I915_NUM_ENGINES; i++) + for_each_engine(engine, gvt->dev_priv, i) wake_up(&scheduler->waitq[i]); } diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 12f825512e9b..a6ba60141ff4 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -510,6 +510,10 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt) init_waitqueue_head(&scheduler->workload_complete_wq); for (i = 0; i < I915_NUM_ENGINES; i++) { + /* check ring mask at init time */ + if (!HAS_ENGINE(gvt->dev_priv, i)) + continue; + init_waitqueue_head(&scheduler->waitq[i]); param = kzalloc(sizeof(*param), GFP_KERNEL); -- cgit v1.2.3 From 321927db98320f0121adc50a8325f23e08735c34 Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Thu, 20 Oct 2016 14:08:46 +0800 Subject: drm/i915/gvt: fix sparse warnings on different address spaces Add proper __iomem annotation for pointers obtained via ioremap(). Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/firmware.c | 8 +++++--- drivers/gpu/drm/i915/gvt/gtt.c | 4 ++-- drivers/gpu/drm/i915/gvt/gvt.h | 2 +- drivers/gpu/drm/i915/gvt/opregion.c | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/firmware.c b/drivers/gpu/drm/i915/gvt/firmware.c index d068a524a699..2fae2a2ca96f 100644 --- a/drivers/gpu/drm/i915/gvt/firmware.c +++ b/drivers/gpu/drm/i915/gvt/firmware.c @@ -51,7 +51,7 @@ struct gvt_firmware_header { #define RD(offset) (readl(mmio + offset.reg)) #define WR(v, offset) (writel(v, mmio + offset.reg)) -static void bdw_forcewake_get(void *mmio) +static void bdw_forcewake_get(void __iomem *mmio) { WR(_MASKED_BIT_DISABLE(0xffff), FORCEWAKE_MT); @@ -91,7 +91,8 @@ static struct bin_attribute firmware_attr = { .mmap = NULL, }; -static int expose_firmware_sysfs(struct intel_gvt *gvt, void *mmio) +static int expose_firmware_sysfs(struct intel_gvt *gvt, + void __iomem *mmio) { struct intel_gvt_device_info *info = &gvt->device_info; struct pci_dev *pdev = gvt->dev_priv->drm.pdev; @@ -234,7 +235,8 @@ int intel_gvt_load_firmware(struct intel_gvt *gvt) struct gvt_firmware_header *h; const struct firmware *fw; char *path; - void *mmio, *mem; + void __iomem *mmio; + void *mem; int ret; path = kmalloc(PATH_MAX, GFP_KERNEL); diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 0722d1e61fce..a8c2405f6f3e 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -269,7 +269,7 @@ static inline int get_pse_type(int type) static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index) { - void *addr = (u64 *)dev_priv->ggtt.gsm + index; + void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index; u64 pte; #ifdef readq @@ -284,7 +284,7 @@ static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index) static void write_pte64(struct drm_i915_private *dev_priv, unsigned long index, u64 pte) { - void *addr = (u64 *)dev_priv->ggtt.gsm + index; + void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index; #ifdef writeq writeq(pte, addr); diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 15c595e0a63b..11df62b542b1 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -186,7 +186,7 @@ struct intel_gvt_firmware { }; struct intel_gvt_opregion { - void *opregion_va; + void __iomem *opregion_va; u32 opregion_pa; }; diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c index 53ac81f63c64..973c8a9d0b15 100644 --- a/drivers/gpu/drm/i915/gvt/opregion.c +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -27,7 +27,7 @@ static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa) { - void *host_va = vgpu->gvt->opregion.opregion_va; + void __iomem *host_va = vgpu->gvt->opregion.opregion_va; u8 *buf; int i; -- cgit v1.2.3 From 999ccb4017c2c818afae18a90060385ec1db903b Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Thu, 20 Oct 2016 14:08:47 +0800 Subject: drm/i915/gvt: mark symbols static where possible Mark all local functions & variables as static. Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 6 +++--- drivers/gpu/drm/i915/gvt/display.c | 2 +- drivers/gpu/drm/i915/gvt/execlist.c | 2 +- drivers/gpu/drm/i915/gvt/gtt.c | 8 ++++---- drivers/gpu/drm/i915/gvt/interrupt.c | 2 +- drivers/gpu/drm/i915/gvt/sched_policy.c | 2 +- drivers/gpu/drm/i915/gvt/scheduler.c | 3 ++- 7 files changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 0d322e035d9f..aafb57e26288 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -480,8 +480,8 @@ struct parser_exec_state { #define gmadr_dw_number(s) \ (s->vgpu->gvt->device_info.gmadr_bytes_in_cmd >> 2) -unsigned long bypass_scan_mask = 0; -bool bypass_batch_buffer_scan = true; +static unsigned long bypass_scan_mask = 0; +static bool bypass_batch_buffer_scan = true; /* ring ALL, type = 0 */ static struct sub_op_bits sub_op_mi[] = { @@ -960,7 +960,7 @@ struct cmd_interrupt_event { int mi_user_interrupt; }; -struct cmd_interrupt_event cmd_interrupt_events[] = { +static struct cmd_interrupt_event cmd_interrupt_events[] = { [RCS] = { .pipe_control_notify = RCS_PIPE_CONTROL, .mi_flush_dw = INTEL_GVT_EVENT_RESERVED, diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index d8908d4cd09a..c0c884aeb30e 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -120,7 +120,7 @@ static unsigned char virtual_dp_monitor_edid[] = { #define DPCD_HEADER_SIZE 0xb -u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { +static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { 0x11, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 0e9b340897e3..d251ca5d173c 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -623,7 +623,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload) (list_empty(q) ? NULL : container_of(q->prev, \ struct intel_vgpu_workload, list)) -bool submit_context(struct intel_vgpu *vgpu, int ring_id, +static bool submit_context(struct intel_vgpu *vgpu, int ring_id, struct execlist_ctx_descriptor_format *desc, bool emulate_schedule_in) { diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index a8c2405f6f3e..d3230bea7e41 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1921,7 +1921,7 @@ int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, return ret; } -bool intel_gvt_create_scratch_page(struct intel_vgpu *vgpu) +static bool create_scratch_page(struct intel_vgpu *vgpu) { struct intel_vgpu_gtt *gtt = &vgpu->gtt; void *p; @@ -1955,7 +1955,7 @@ bool intel_gvt_create_scratch_page(struct intel_vgpu *vgpu) return 0; } -void intel_gvt_release_scratch_page(struct intel_vgpu *vgpu) +static void release_scratch_page(struct intel_vgpu *vgpu) { if (vgpu->gtt.scratch_page != NULL) { __free_page(vgpu->gtt.scratch_page); @@ -1995,7 +1995,7 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) gtt->ggtt_mm = ggtt_mm; - intel_gvt_create_scratch_page(vgpu); + create_scratch_page(vgpu); return 0; } @@ -2015,7 +2015,7 @@ void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu) struct intel_vgpu_mm *mm; ppgtt_free_all_shadow_page(vgpu); - intel_gvt_release_scratch_page(vgpu); + release_scratch_page(vgpu); list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) { mm = container_of(pos, struct intel_vgpu_mm, list); diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c index e43ef7228557..f7be02ac4be1 100644 --- a/drivers/gpu/drm/i915/gvt/interrupt.c +++ b/drivers/gpu/drm/i915/gvt/interrupt.c @@ -50,7 +50,7 @@ static void update_upstream_irq(struct intel_vgpu *vgpu, struct intel_gvt_irq_info *info); -const char * const irq_name[INTEL_GVT_EVENT_MAX] = { +static const char * const irq_name[INTEL_GVT_EVENT_MAX] = { [RCS_MI_USER_INTERRUPT] = "Render CS MI USER INTERRUPT", [RCS_DEBUG] = "Render EU debug from SVG", [RCS_MMIO_SYNC_FLUSH] = "Render MMIO sync flush status", diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index b605ac6137eb..1df6a5460f3e 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -236,7 +236,7 @@ static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu) list_del_init(&vgpu_data->list); } -struct intel_gvt_sched_policy_ops tbs_schedule_ops = { +static struct intel_gvt_sched_policy_ops tbs_schedule_ops = { .init = tbs_sched_init, .clean = tbs_sched_clean, .init_vgpu = tbs_sched_init_vgpu, diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index a6ba60141ff4..e96eaeebeb0a 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -41,7 +41,8 @@ #define RING_CTX_OFF(x) \ offsetof(struct execlist_ring_context, x) -void set_context_pdp_root_pointer(struct execlist_ring_context *ring_context, +static void set_context_pdp_root_pointer( + struct execlist_ring_context *ring_context, u32 pdp[8]) { struct execlist_mmio_pair *pdp_pair = &ring_context->pdp3_UDW; -- cgit v1.2.3 From 76a79d59ada00fa22e5f8cd94b36296f395c3406 Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Thu, 20 Oct 2016 14:08:48 +0800 Subject: drm/i915/gvt: fix spare warnings on odd constant _Bool cast The function return values should has type int if it return a integer value. Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 2 +- drivers/gpu/drm/i915/gvt/gtt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index d251ca5d173c..c1f6019d8895 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -623,7 +623,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload) (list_empty(q) ? NULL : container_of(q->prev, \ struct intel_vgpu_workload, list)) -static bool submit_context(struct intel_vgpu *vgpu, int ring_id, +static int submit_context(struct intel_vgpu *vgpu, int ring_id, struct execlist_ctx_descriptor_format *desc, bool emulate_schedule_in) { diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index d3230bea7e41..ca1572070792 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1921,7 +1921,7 @@ int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, return ret; } -static bool create_scratch_page(struct intel_vgpu *vgpu) +static int create_scratch_page(struct intel_vgpu *vgpu) { struct intel_vgpu_gtt *gtt = &vgpu->gtt; void *p; -- cgit v1.2.3 From 19e6393fb5366a89705a62b3276ce42e990d12ce Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Thu, 20 Oct 2016 14:08:49 +0800 Subject: drm/i915/gvt: do not ignore return value of create_scratch_page Function create_scratch_page() may fail in some cases. Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gtt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index ca1572070792..2cc761328569 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1995,8 +1995,7 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) gtt->ggtt_mm = ggtt_mm; - create_scratch_page(vgpu); - return 0; + return create_scratch_page(vgpu); } /** -- cgit v1.2.3 From 64933513e4610c90d84104a4988a328c934a3e7b Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 14 Sep 2016 14:27:53 +0100 Subject: reset: sti: Remove STiH415/6 reset support Support for STiH415/6 SoCs is being removed from the kernel because the platforms are obsolete. This patch removes the reset drivers for these SoC's. Signed-off-by: Peter Griffin Signed-off-by: Philipp Zabel --- arch/arm/mach-sti/Kconfig | 2 - drivers/reset/sti/Kconfig | 8 --- drivers/reset/sti/Makefile | 2 - drivers/reset/sti/reset-stih415.c | 112 ----------------------------- drivers/reset/sti/reset-stih416.c | 143 -------------------------------------- 5 files changed, 267 deletions(-) delete mode 100644 drivers/reset/sti/reset-stih415.c delete mode 100644 drivers/reset/sti/reset-stih416.c (limited to 'drivers') diff --git a/arch/arm/mach-sti/Kconfig b/arch/arm/mach-sti/Kconfig index 119e1108b1f8..f8eeeffddaff 100644 --- a/arch/arm/mach-sti/Kconfig +++ b/arch/arm/mach-sti/Kconfig @@ -28,7 +28,6 @@ if ARCH_STI config SOC_STIH415 bool "STiH415 STMicroelectronics Consumer Electronics family" default y - select STIH415_RESET help This enables support for STMicroelectronics Digital Consumer Electronics family StiH415 parts, primarily targeted at set-top-box @@ -38,7 +37,6 @@ config SOC_STIH415 config SOC_STIH416 bool "STiH416 STMicroelectronics Consumer Electronics family" default y - select STIH416_RESET help This enables support for STMicroelectronics Digital Consumer Electronics family StiH416 parts, primarily targeted at set-top-box diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig index 613178553612..71592b5bfd14 100644 --- a/drivers/reset/sti/Kconfig +++ b/drivers/reset/sti/Kconfig @@ -3,14 +3,6 @@ if ARCH_STI config STI_RESET_SYSCFG bool -config STIH415_RESET - bool - select STI_RESET_SYSCFG - -config STIH416_RESET - bool - select STI_RESET_SYSCFG - config STIH407_RESET bool select STI_RESET_SYSCFG diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile index dc85dfbe56a9..f9d82411f29e 100644 --- a/drivers/reset/sti/Makefile +++ b/drivers/reset/sti/Makefile @@ -1,5 +1,3 @@ obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o -obj-$(CONFIG_STIH415_RESET) += reset-stih415.o -obj-$(CONFIG_STIH416_RESET) += reset-stih416.o obj-$(CONFIG_STIH407_RESET) += reset-stih407.o diff --git a/drivers/reset/sti/reset-stih415.c b/drivers/reset/sti/reset-stih415.c deleted file mode 100644 index 6f220cdbef46..000000000000 --- a/drivers/reset/sti/reset-stih415.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2013 STMicroelectronics (R&D) Limited - * Author: Stephen Gallimore - * Author: Srinivas Kandagatla - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#include -#include -#include -#include - -#include - -#include "reset-syscfg.h" - -/* - * STiH415 Peripheral powerdown definitions. - */ -static const char stih415_front[] = "st,stih415-front-syscfg"; -static const char stih415_rear[] = "st,stih415-rear-syscfg"; -static const char stih415_sbc[] = "st,stih415-sbc-syscfg"; -static const char stih415_lpm[] = "st,stih415-lpm-syscfg"; - -#define STIH415_PDN_FRONT(_bit) \ - _SYSCFG_RST_CH(stih415_front, SYSCFG_114, _bit, SYSSTAT_187, _bit) - -#define STIH415_PDN_REAR(_cntl, _stat) \ - _SYSCFG_RST_CH(stih415_rear, SYSCFG_336, _cntl, SYSSTAT_384, _stat) - -#define STIH415_SRST_REAR(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih415_rear, _reg, _bit) - -#define STIH415_SRST_SBC(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih415_sbc, _reg, _bit) - -#define STIH415_SRST_FRONT(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih415_front, _reg, _bit) - -#define STIH415_SRST_LPM(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih415_lpm, _reg, _bit) - -#define SYSCFG_114 0x38 /* Powerdown request EMI/NAND/Keyscan */ -#define SYSSTAT_187 0x15c /* Powerdown status EMI/NAND/Keyscan */ - -#define SYSCFG_336 0x90 /* Powerdown request USB/SATA/PCIe */ -#define SYSSTAT_384 0x150 /* Powerdown status USB/SATA/PCIe */ - -#define SYSCFG_376 0x130 /* Reset generator 0 control 0 */ -#define SYSCFG_166 0x108 /* Softreset Ethernet 0 */ -#define SYSCFG_31 0x7c /* Softreset Ethernet 1 */ -#define LPM_SYSCFG_1 0x4 /* Softreset IRB */ - -static const struct syscfg_reset_channel_data stih415_powerdowns[] = { - [STIH415_EMISS_POWERDOWN] = STIH415_PDN_FRONT(0), - [STIH415_NAND_POWERDOWN] = STIH415_PDN_FRONT(1), - [STIH415_KEYSCAN_POWERDOWN] = STIH415_PDN_FRONT(2), - [STIH415_USB0_POWERDOWN] = STIH415_PDN_REAR(0, 0), - [STIH415_USB1_POWERDOWN] = STIH415_PDN_REAR(1, 1), - [STIH415_USB2_POWERDOWN] = STIH415_PDN_REAR(2, 2), - [STIH415_SATA0_POWERDOWN] = STIH415_PDN_REAR(3, 3), - [STIH415_SATA1_POWERDOWN] = STIH415_PDN_REAR(4, 4), - [STIH415_PCIE_POWERDOWN] = STIH415_PDN_REAR(5, 8), -}; - -static const struct syscfg_reset_channel_data stih415_softresets[] = { - [STIH415_ETH0_SOFTRESET] = STIH415_SRST_FRONT(SYSCFG_166, 0), - [STIH415_ETH1_SOFTRESET] = STIH415_SRST_SBC(SYSCFG_31, 0), - [STIH415_IRB_SOFTRESET] = STIH415_SRST_LPM(LPM_SYSCFG_1, 6), - [STIH415_USB0_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 9), - [STIH415_USB1_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 10), - [STIH415_USB2_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 11), - [STIH415_KEYSCAN_SOFTRESET] = STIH415_SRST_LPM(LPM_SYSCFG_1, 8), -}; - -static struct syscfg_reset_controller_data stih415_powerdown_controller = { - .wait_for_ack = true, - .nr_channels = ARRAY_SIZE(stih415_powerdowns), - .channels = stih415_powerdowns, -}; - -static struct syscfg_reset_controller_data stih415_softreset_controller = { - .wait_for_ack = false, - .active_low = true, - .nr_channels = ARRAY_SIZE(stih415_softresets), - .channels = stih415_softresets, -}; - -static const struct of_device_id stih415_reset_match[] = { - { .compatible = "st,stih415-powerdown", - .data = &stih415_powerdown_controller, }, - { .compatible = "st,stih415-softreset", - .data = &stih415_softreset_controller, }, - {}, -}; - -static struct platform_driver stih415_reset_driver = { - .probe = syscfg_reset_probe, - .driver = { - .name = "reset-stih415", - .of_match_table = stih415_reset_match, - }, -}; - -static int __init stih415_reset_init(void) -{ - return platform_driver_register(&stih415_reset_driver); -} -arch_initcall(stih415_reset_init); diff --git a/drivers/reset/sti/reset-stih416.c b/drivers/reset/sti/reset-stih416.c deleted file mode 100644 index c581d606ef0f..000000000000 --- a/drivers/reset/sti/reset-stih416.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2013 STMicroelectronics (R&D) Limited - * Author: Stephen Gallimore - * Author: Srinivas Kandagatla - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#include -#include -#include -#include - -#include - -#include "reset-syscfg.h" - -/* - * STiH416 Peripheral powerdown definitions. - */ -static const char stih416_front[] = "st,stih416-front-syscfg"; -static const char stih416_rear[] = "st,stih416-rear-syscfg"; -static const char stih416_sbc[] = "st,stih416-sbc-syscfg"; -static const char stih416_lpm[] = "st,stih416-lpm-syscfg"; -static const char stih416_cpu[] = "st,stih416-cpu-syscfg"; - -#define STIH416_PDN_FRONT(_bit) \ - _SYSCFG_RST_CH(stih416_front, SYSCFG_1500, _bit, SYSSTAT_1578, _bit) - -#define STIH416_PDN_REAR(_cntl, _stat) \ - _SYSCFG_RST_CH(stih416_rear, SYSCFG_2525, _cntl, SYSSTAT_2583, _stat) - -#define SYSCFG_1500 0x7d0 /* Powerdown request EMI/NAND/Keyscan */ -#define SYSSTAT_1578 0x908 /* Powerdown status EMI/NAND/Keyscan */ - -#define SYSCFG_2525 0x834 /* Powerdown request USB/SATA/PCIe */ -#define SYSSTAT_2583 0x91c /* Powerdown status USB/SATA/PCIe */ - -#define SYSCFG_2552 0x8A0 /* Reset Generator control 0 */ -#define SYSCFG_1539 0x86c /* Softreset Ethernet 0 */ -#define SYSCFG_510 0x7f8 /* Softreset Ethernet 1 */ -#define LPM_SYSCFG_1 0x4 /* Softreset IRB */ -#define SYSCFG_2553 0x8a4 /* Softreset SATA0/1, PCIE0/1 */ -#define SYSCFG_7563 0x8cc /* MPE softresets 0 */ -#define SYSCFG_7564 0x8d0 /* MPE softresets 1 */ - -#define STIH416_SRST_CPU(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih416_cpu, _reg, _bit) - -#define STIH416_SRST_FRONT(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih416_front, _reg, _bit) - -#define STIH416_SRST_REAR(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih416_rear, _reg, _bit) - -#define STIH416_SRST_LPM(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih416_lpm, _reg, _bit) - -#define STIH416_SRST_SBC(_reg, _bit) \ - _SYSCFG_RST_CH_NO_ACK(stih416_sbc, _reg, _bit) - -static const struct syscfg_reset_channel_data stih416_powerdowns[] = { - [STIH416_EMISS_POWERDOWN] = STIH416_PDN_FRONT(0), - [STIH416_NAND_POWERDOWN] = STIH416_PDN_FRONT(1), - [STIH416_KEYSCAN_POWERDOWN] = STIH416_PDN_FRONT(2), - [STIH416_USB0_POWERDOWN] = STIH416_PDN_REAR(0, 0), - [STIH416_USB1_POWERDOWN] = STIH416_PDN_REAR(1, 1), - [STIH416_USB2_POWERDOWN] = STIH416_PDN_REAR(2, 2), - [STIH416_USB3_POWERDOWN] = STIH416_PDN_REAR(6, 5), - [STIH416_SATA0_POWERDOWN] = STIH416_PDN_REAR(3, 3), - [STIH416_SATA1_POWERDOWN] = STIH416_PDN_REAR(4, 4), - [STIH416_PCIE0_POWERDOWN] = STIH416_PDN_REAR(7, 9), - [STIH416_PCIE1_POWERDOWN] = STIH416_PDN_REAR(5, 8), -}; - -static const struct syscfg_reset_channel_data stih416_softresets[] = { - [STIH416_ETH0_SOFTRESET] = STIH416_SRST_FRONT(SYSCFG_1539, 0), - [STIH416_ETH1_SOFTRESET] = STIH416_SRST_SBC(SYSCFG_510, 0), - [STIH416_IRB_SOFTRESET] = STIH416_SRST_LPM(LPM_SYSCFG_1, 6), - [STIH416_USB0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 9), - [STIH416_USB1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 10), - [STIH416_USB2_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 11), - [STIH416_USB3_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 28), - [STIH416_SATA0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 7), - [STIH416_SATA1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 3), - [STIH416_PCIE0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 15), - [STIH416_PCIE1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 2), - [STIH416_AUD_DAC_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 14), - [STIH416_HDTVOUT_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 5), - [STIH416_VTAC_M_RX_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 25), - [STIH416_VTAC_A_RX_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 26), - [STIH416_SYNC_HD_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 5), - [STIH416_SYNC_SD_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 6), - [STIH416_BLITTER_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 10), - [STIH416_GPU_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 11), - [STIH416_VTAC_M_TX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 18), - [STIH416_VTAC_A_TX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 19), - [STIH416_VTG_AUX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 21), - [STIH416_JPEG_DEC_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 23), - [STIH416_HVA_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 2), - [STIH416_COMPO_M_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 3), - [STIH416_COMPO_A_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 4), - [STIH416_VP8_DEC_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 10), - [STIH416_VTG_MAIN_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 16), - [STIH416_KEYSCAN_SOFTRESET] = STIH416_SRST_LPM(LPM_SYSCFG_1, 8), -}; - -static struct syscfg_reset_controller_data stih416_powerdown_controller = { - .wait_for_ack = true, - .nr_channels = ARRAY_SIZE(stih416_powerdowns), - .channels = stih416_powerdowns, -}; - -static struct syscfg_reset_controller_data stih416_softreset_controller = { - .wait_for_ack = false, - .active_low = true, - .nr_channels = ARRAY_SIZE(stih416_softresets), - .channels = stih416_softresets, -}; - -static const struct of_device_id stih416_reset_match[] = { - { .compatible = "st,stih416-powerdown", - .data = &stih416_powerdown_controller, }, - { .compatible = "st,stih416-softreset", - .data = &stih416_softreset_controller, }, - {}, -}; - -static struct platform_driver stih416_reset_driver = { - .probe = syscfg_reset_probe, - .driver = { - .name = "reset-stih416", - .of_match_table = stih416_reset_match, - }, -}; - -static int __init stih416_reset_init(void) -{ - return platform_driver_register(&stih416_reset_driver); -} -arch_initcall(stih416_reset_init); -- cgit v1.2.3 From a68262bb1e0cd21870a404a7b6323500e9b5c004 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 5 Oct 2016 17:27:08 +0200 Subject: reset: oxnas: Add OX820 support In order to support the Oxford Semiconductor OX820 SoC, add a new compatible string. Signed-off-by: Neil Armstrong Signed-off-by: Philipp Zabel --- drivers/reset/reset-oxnas.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c index 944980572f79..0d9036dea010 100644 --- a/drivers/reset/reset-oxnas.c +++ b/drivers/reset/reset-oxnas.c @@ -80,6 +80,7 @@ static const struct reset_control_ops oxnas_reset_ops = { static const struct of_device_id oxnas_reset_dt_ids[] = { { .compatible = "oxsemi,ox810se-reset", }, + { .compatible = "oxsemi,ox820-reset", }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids); -- cgit v1.2.3 From ecc2d430fadfba408b1d453d82128a696fa73fe0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 16 Sep 2016 13:03:47 +0000 Subject: memory: atmel-ebi: fix return value check in at91_ebi_dev_disable() Fix the retrn value check which testing the wrong variable in at91_ebi_dev_disable(). Signed-off-by: Wei Yongjun Signed-off-by: Alexandre Belloni --- drivers/memory/atmel-ebi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c index b5ed3bd082b5..047d6fcdcec2 100644 --- a/drivers/memory/atmel-ebi.c +++ b/drivers/memory/atmel-ebi.c @@ -657,7 +657,7 @@ static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np) return -ENOMEM; newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL); - if (!newprop->name) + if (!newprop->value) return -ENOMEM; newprop->length = sizeof("disabled"); -- cgit v1.2.3 From af692400608857f7d7c3189c150c0b1d6b0ffad0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 16 Sep 2016 13:05:10 +0000 Subject: memory: atmel-sdramc: use builtin_platform_driver to simplify the code Use the builtin_platform_driver() macro to make the code simpler. Signed-off-by: Wei Yongjun Signed-off-by: Alexandre Belloni --- drivers/memory/atmel-sdramc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/memory/atmel-sdramc.c b/drivers/memory/atmel-sdramc.c index 12080b05e3e6..b418b39af180 100644 --- a/drivers/memory/atmel-sdramc.c +++ b/drivers/memory/atmel-sdramc.c @@ -85,8 +85,4 @@ static struct platform_driver atmel_ramc_driver = { }, }; -static int __init atmel_ramc_init(void) -{ - return platform_driver_register(&atmel_ramc_driver); -} -device_initcall(atmel_ramc_init); +builtin_platform_driver(atmel_ramc_driver); -- cgit v1.2.3 From eaa14c24864ecfc60fb591f3b20747af7c67d446 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Oct 2016 13:52:03 +0100 Subject: drm/i915: Stop reporting error details in dmesg as well as the error-state As we already capture all the information from the registers into the error-state, also dumping that to dmesg just generates noise that upsets CI and users alike (and doesn't provide us with any more information). Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161019125203.28851-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_irq.c | 86 ++++++----------------------------------- 1 file changed, 11 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b4a99dd54e6b..23315e5461bf 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2578,90 +2578,26 @@ i915_err_print_instdone(struct drm_i915_private *dev_priv, slice, subslice, instdone->row[slice][subslice]); } -static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) +static void i915_clear_error_registers(struct drm_i915_private *dev_priv) { - struct intel_instdone instdone; - u32 eir = I915_READ(EIR); - int pipe; - - if (!eir) - return; - - pr_err("render error detected, EIR: 0x%08x\n", eir); - - intel_engine_get_instdone(dev_priv->engine[RCS], &instdone); - - if (IS_G4X(dev_priv)) { - if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) { - u32 ipeir = I915_READ(IPEIR_I965); - - pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965)); - pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965)); - i915_err_print_instdone(dev_priv, &instdone); - pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS)); - pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965)); - I915_WRITE(IPEIR_I965, ipeir); - POSTING_READ(IPEIR_I965); - } - if (eir & GM45_ERROR_PAGE_TABLE) { - u32 pgtbl_err = I915_READ(PGTBL_ER); - pr_err("page table error\n"); - pr_err(" PGTBL_ER: 0x%08x\n", pgtbl_err); - I915_WRITE(PGTBL_ER, pgtbl_err); - POSTING_READ(PGTBL_ER); - } - } + u32 eir; - if (!IS_GEN2(dev_priv)) { - if (eir & I915_ERROR_PAGE_TABLE) { - u32 pgtbl_err = I915_READ(PGTBL_ER); - pr_err("page table error\n"); - pr_err(" PGTBL_ER: 0x%08x\n", pgtbl_err); - I915_WRITE(PGTBL_ER, pgtbl_err); - POSTING_READ(PGTBL_ER); - } - } + if (!IS_GEN2(dev_priv)) + I915_WRITE(PGTBL_ER, I915_READ(PGTBL_ER)); - if (eir & I915_ERROR_MEMORY_REFRESH) { - pr_err("memory refresh error:\n"); - for_each_pipe(dev_priv, pipe) - pr_err("pipe %c stat: 0x%08x\n", - pipe_name(pipe), I915_READ(PIPESTAT(pipe))); - /* pipestat has already been acked */ - } - if (eir & I915_ERROR_INSTRUCTION) { - pr_err("instruction error\n"); - pr_err(" INSTPM: 0x%08x\n", I915_READ(INSTPM)); - i915_err_print_instdone(dev_priv, &instdone); - if (INTEL_GEN(dev_priv) < 4) { - u32 ipeir = I915_READ(IPEIR); - - pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR)); - pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR)); - pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD)); - I915_WRITE(IPEIR, ipeir); - POSTING_READ(IPEIR); - } else { - u32 ipeir = I915_READ(IPEIR_I965); - - pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965)); - pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965)); - pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS)); - pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965)); - I915_WRITE(IPEIR_I965, ipeir); - POSTING_READ(IPEIR_I965); - } - } + if (INTEL_GEN(dev_priv) < 4) + I915_WRITE(IPEIR, I915_READ(IPEIR)); + else + I915_WRITE(IPEIR_I965, I915_READ(IPEIR_I965)); - I915_WRITE(EIR, eir); - POSTING_READ(EIR); + I915_WRITE(EIR, I915_READ(EIR)); eir = I915_READ(EIR); if (eir) { /* * some errors might have become stuck, * mask them. */ - DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir); + DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir); I915_WRITE(EMR, I915_READ(EMR) | eir); I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); } @@ -2690,7 +2626,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv, va_end(args); i915_capture_error_state(dev_priv, engine_mask, error_msg); - i915_report_and_clear_eir(dev_priv); + i915_clear_error_registers(dev_priv); if (!engine_mask) return; -- cgit v1.2.3 From 181c9bfe4b37a36075c91b9e16ce8c99ed0d9b7b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 18 Oct 2016 12:13:15 +0200 Subject: drm/imx: ipuv3-plane: request modeset if plane offsets changed If the framebuffer pixel format is planar YUV and unchanged, but the U or V plane offsets change, do not return an error, but request a modeset instead. Signed-off-by: Philipp Zabel Acked-by: Liu Ying --- drivers/gpu/drm/imx/ipuv3-plane.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index d5864ed4d772..737f085eafac 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -356,13 +356,11 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) return -EINVAL; - if (old_fb && - (old_fb->pixel_format == DRM_FORMAT_YUV420 || - old_fb->pixel_format == DRM_FORMAT_YVU420)) { + if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { old_ubo = drm_plane_state_to_ubo(old_state); old_vbo = drm_plane_state_to_vbo(old_state); if (ubo != old_ubo || vbo != old_vbo) - return -EINVAL; + crtc_state->mode_changed = true; } if (fb->pitches[1] != fb->pitches[2]) -- cgit v1.2.3 From 3fd8b292ae6b99e3e6e96df3e470b25b100741a8 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 18 Oct 2016 11:40:25 +0200 Subject: drm/imx: ipuv3-plane: merge ipu_plane_atomic_set_base into atomic_update ipu_plane_atomic_set_base is called from ipu_plane_atomic_update in two different places, depending on whether drm_atomic_crtc_needs_modeset is true. Also depending on the same condition, this function does two different things. This patch removes the indirection by merging the relevant parts into ipu_plane_atomic_update, making the actual code flow more obvious as a result. Also remove the duplicate planar format comment, which is already found in ipu_plane_atomic_check. Signed-off-by: Philipp Zabel Acked-by: Liu Ying --- drivers/gpu/drm/imx/ipuv3-plane.c | 97 ++++++++++++++------------------------- 1 file changed, 34 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 737f085eafac..32871bed5dcc 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -103,62 +103,6 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) (state->src_x >> 16) / 2 - eba; } -static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane) -{ - struct drm_plane *plane = &ipu_plane->base; - struct drm_plane_state *state = plane->state; - struct drm_crtc_state *crtc_state = state->crtc->state; - struct drm_framebuffer *fb = state->fb; - unsigned long eba, ubo, vbo; - int active; - - eba = drm_plane_state_to_eba(state); - - switch (fb->pixel_format) { - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - break; - - /* - * Multiplanar formats have to meet the following restrictions: - * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO - * - EBA, UBO and VBO are a multiple of 8 - * - UBO and VBO are unsigned and not larger than 0xfffff8 - * - Only EBA may be changed while scanout is active - * - The strides of U and V planes must be identical. - */ - ubo = drm_plane_state_to_ubo(state); - vbo = drm_plane_state_to_vbo(state); - - if (fb->pixel_format == DRM_FORMAT_YUV420) - ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, - fb->pitches[1], ubo, vbo); - else - ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, - fb->pitches[1], vbo, ubo); - - dev_dbg(ipu_plane->base.dev->dev, - "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, - state->src_x >> 16, state->src_y >> 16); - break; - default: - dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", - eba, state->src_x >> 16, state->src_y >> 16); - - break; - } - - if (!drm_atomic_crtc_needs_modeset(crtc_state)) { - active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); - ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); - } else { - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); - } -} - void ipu_plane_put_resources(struct ipu_plane *ipu_plane) { if (!IS_ERR_OR_NULL(ipu_plane->dp)) @@ -397,15 +341,19 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, { struct ipu_plane *ipu_plane = to_ipu_plane(plane); struct drm_plane_state *state = plane->state; + struct drm_crtc_state *crtc_state = state->crtc->state; + struct drm_framebuffer *fb = state->fb; + unsigned long eba, ubo, vbo; enum ipu_color_space ics; + int active; - if (old_state->fb) { - struct drm_crtc_state *crtc_state = state->crtc->state; + eba = drm_plane_state_to_eba(state); - if (!drm_atomic_crtc_needs_modeset(crtc_state)) { - ipu_plane_atomic_set_base(ipu_plane); - return; - } + if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { + active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); + ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); + return; } switch (ipu_plane->dp_flow) { @@ -449,7 +397,30 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]); - ipu_plane_atomic_set_base(ipu_plane); + switch (fb->pixel_format) { + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + ubo = drm_plane_state_to_ubo(state); + vbo = drm_plane_state_to_vbo(state); + + if (fb->pixel_format == DRM_FORMAT_YUV420) + ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, + fb->pitches[1], ubo, vbo); + else + ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, + fb->pitches[1], vbo, ubo); + + dev_dbg(ipu_plane->base.dev->dev, + "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, + state->src_x >> 16, state->src_y >> 16); + break; + default: + dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", + eba, state->src_x >> 16, state->src_y >> 16); + break; + } + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); ipu_plane_enable(ipu_plane); } -- cgit v1.2.3 From f2fa3536b211a420a668a239b93c6cfb7978d2ce Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 18 Oct 2016 12:26:19 +0200 Subject: drm/imx: ipuv3-plane: let drm_plane_state_to_ubo/vbo handle chroma subsampling other than 4:2:0 To support 4:2:2 or 4:4:4 chroma subsampling, divide the x/y offsets in drm_plane_state_to_ubo/vbo only if necessary for the given pixel format. Signed-off-by: Philipp Zabel Acked-by: Liu Ying --- drivers/gpu/drm/imx/ipuv3-plane.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 32871bed5dcc..52784cb6bee4 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -64,13 +64,14 @@ drm_plane_state_to_eba(struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; struct drm_gem_cma_object *cma_obj; + int x = state->src_x >> 16; + int y = state->src_y >> 16; cma_obj = drm_fb_cma_get_gem_obj(fb, 0); BUG_ON(!cma_obj); - return cma_obj->paddr + fb->offsets[0] + - fb->pitches[0] * (state->src_y >> 16) + - (fb->bits_per_pixel >> 3) * (state->src_x >> 16); + return cma_obj->paddr + fb->offsets[0] + fb->pitches[0] * y + + drm_format_plane_cpp(fb->pixel_format, 0) * x; } static inline unsigned long @@ -79,13 +80,17 @@ drm_plane_state_to_ubo(struct drm_plane_state *state) struct drm_framebuffer *fb = state->fb; struct drm_gem_cma_object *cma_obj; unsigned long eba = drm_plane_state_to_eba(state); + int x = state->src_x >> 16; + int y = state->src_y >> 16; cma_obj = drm_fb_cma_get_gem_obj(fb, 1); BUG_ON(!cma_obj); - return cma_obj->paddr + fb->offsets[1] + - fb->pitches[1] * (state->src_y >> 16) / 2 + - (state->src_x >> 16) / 2 - eba; + x /= drm_format_horz_chroma_subsampling(fb->pixel_format); + y /= drm_format_vert_chroma_subsampling(fb->pixel_format); + + return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + + drm_format_plane_cpp(fb->pixel_format, 1) * x - eba; } static inline unsigned long @@ -94,13 +99,17 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) struct drm_framebuffer *fb = state->fb; struct drm_gem_cma_object *cma_obj; unsigned long eba = drm_plane_state_to_eba(state); + int x = state->src_x >> 16; + int y = state->src_y >> 16; cma_obj = drm_fb_cma_get_gem_obj(fb, 2); BUG_ON(!cma_obj); - return cma_obj->paddr + fb->offsets[2] + - fb->pitches[2] * (state->src_y >> 16) / 2 + - (state->src_x >> 16) / 2 - eba; + x /= drm_format_horz_chroma_subsampling(fb->pixel_format); + y /= drm_format_vert_chroma_subsampling(fb->pixel_format); + + return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + + drm_format_plane_cpp(fb->pixel_format, 2) * x - eba; } void ipu_plane_put_resources(struct ipu_plane *ipu_plane) -- cgit v1.2.3 From 9c24d680de0d7b68ac4c07cc685d9dbf83751a1d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 18 Oct 2016 13:33:31 +0200 Subject: gpu: ipu-cpmem: remove unused ipu_cpmem_set_yuv_planar function ipu_cpmem_set_yuv_planar_full is only used directly, remove the wrapper. Suggested-by: Liu Ying Signed-off-by: Philipp Zabel Acked-by: Liu Ying --- drivers/gpu/ipu-v3/ipu-cpmem.c | 36 ------------------------------------ include/video/imx-ipu-v3.h | 2 -- 2 files changed, 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c index fcb7dc86167b..f3ca1d6c02d0 100644 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c @@ -417,42 +417,6 @@ void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch, } EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full); -void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch, - u32 pixel_format, int stride, int height) -{ - int fourcc, u_offset, v_offset; - int uv_stride = 0; - - fourcc = v4l2_pix_fmt_to_drm_fourcc(pixel_format); - switch (fourcc) { - case DRM_FORMAT_YUV420: - uv_stride = stride / 2; - u_offset = stride * height; - v_offset = u_offset + (uv_stride * height / 2); - break; - case DRM_FORMAT_YVU420: - uv_stride = stride / 2; - v_offset = stride * height; - u_offset = v_offset + (uv_stride * height / 2); - break; - case DRM_FORMAT_YUV422: - uv_stride = stride / 2; - u_offset = stride * height; - v_offset = u_offset + (uv_stride * height); - break; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV16: - uv_stride = stride; - u_offset = stride * height; - v_offset = 0; - break; - default: - return; - } - ipu_cpmem_set_yuv_planar_full(ch, uv_stride, u_offset, v_offset); -} -EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); - static const struct ipu_rgb def_xrgb_32 = { .red = { .offset = 16, .length = 8, }, .green = { .offset = 8, .length = 8, }, diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index 173073eb6aaf..cc8174c14df8 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h @@ -247,8 +247,6 @@ void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch, unsigned int uv_stride, unsigned int u_offset, unsigned int v_offset); -void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch, - u32 pixel_format, int stride, int height); int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc); int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image); void ipu_cpmem_dump(struct ipuv3_channel *ch); -- cgit v1.2.3 From c9d508c2df04af001c62e4fe86593aabe42ae718 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 18 Oct 2016 13:36:33 +0200 Subject: gpu: ipu-v3: add YUV 4:4:4 support The IDMAC does support reading and writing DRM_FORMAT_YUV444 and DRM_FORMAT_YVU444. Signed-off-by: Philipp Zabel Acked-by: Liu Ying --- drivers/gpu/ipu-v3/ipu-common.c | 2 ++ drivers/gpu/ipu-v3/ipu-cpmem.c | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index b9539f7c5e9a..b7d7bd6e3d60 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -88,6 +88,8 @@ enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc) case DRM_FORMAT_YVU420: case DRM_FORMAT_YUV422: case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: case DRM_FORMAT_NV12: case DRM_FORMAT_NV21: case DRM_FORMAT_NV16: diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c index f3ca1d6c02d0..4b2b67113d92 100644 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c @@ -554,6 +554,13 @@ int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc) /* burst size */ ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31); break; + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: + /* pix format */ + ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0); + /* burst size */ + ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31); + break; case DRM_FORMAT_NV12: /* pix format */ ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4); -- cgit v1.2.3 From eae13c9337e2bba0f59b1723114e73be18499c5b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 18 Oct 2016 12:31:40 +0200 Subject: drm/imx: ipuv3-plane: add support for YUV 4:2:2 and 4:4:4, NV12, and NV16 formats Hook up support for DRM_FORMAT_YUV422, DRM_FORMAT_YVU422, DRM_FORMAT_YUV444, DRM_FORMAT_YVU444, DRM_FORMAT_NV12, and DRM_FORMAT_NV16. Signed-off-by: Philipp Zabel Acked-by: Liu Ying --- drivers/gpu/drm/imx/ipuv3-plane.c | 60 ++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 52784cb6bee4..6a97e396fce3 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -50,6 +50,12 @@ static const uint32_t ipu_plane_formats[] = { DRM_FORMAT_YVYU, DRM_FORMAT_YUV420, DRM_FORMAT_YVU420, + DRM_FORMAT_YUV422, + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, + DRM_FORMAT_NV12, + DRM_FORMAT_NV16, DRM_FORMAT_RGB565, }; @@ -292,6 +298,10 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, switch (fb->pixel_format) { case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: /* * Multiplanar formats have to meet the following restrictions: * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO @@ -300,25 +310,34 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, * - Only EBA may be changed while scanout is active * - The strides of U and V planes must be identical. */ - ubo = drm_plane_state_to_ubo(state); vbo = drm_plane_state_to_vbo(state); - if ((ubo & 0x7) || (vbo & 0x7)) - return -EINVAL; - - if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) + if (vbo & 0x7 || vbo > 0xfffff8) return -EINVAL; if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { - old_ubo = drm_plane_state_to_ubo(old_state); old_vbo = drm_plane_state_to_vbo(old_state); - if (ubo != old_ubo || vbo != old_vbo) + if (vbo != old_vbo) crtc_state->mode_changed = true; } if (fb->pitches[1] != fb->pitches[2]) return -EINVAL; + /* fall-through */ + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + ubo = drm_plane_state_to_ubo(state); + + if (ubo & 0x7 || ubo > 0xfffff8) + return -EINVAL; + + if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { + old_ubo = drm_plane_state_to_ubo(old_state); + if (ubo != old_ubo) + crtc_state->mode_changed = true; + } + if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) return -EINVAL; @@ -409,20 +428,35 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, switch (fb->pixel_format) { case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: ubo = drm_plane_state_to_ubo(state); vbo = drm_plane_state_to_vbo(state); + if (fb->pixel_format == DRM_FORMAT_YVU420 || + fb->pixel_format == DRM_FORMAT_YVU422 || + fb->pixel_format == DRM_FORMAT_YVU444) + swap(ubo, vbo); - if (fb->pixel_format == DRM_FORMAT_YUV420) - ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, - fb->pitches[1], ubo, vbo); - else - ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, - fb->pitches[1], vbo, ubo); + ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, + fb->pitches[1], ubo, vbo); dev_dbg(ipu_plane->base.dev->dev, "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, state->src_x >> 16, state->src_y >> 16); break; + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + ubo = drm_plane_state_to_ubo(state); + + ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, + fb->pitches[1], ubo, ubo); + + dev_dbg(ipu_plane->base.dev->dev, + "phy = %lu %lu, x = %d, y = %d", eba, ubo, + state->src_x >> 16, state->src_y >> 16); + break; default: dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", eba, state->src_x >> 16, state->src_y >> 16); -- cgit v1.2.3 From a92d81456c08ea6917a7630718837f0a01cbd0d0 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 29 Aug 2016 08:32:03 +0200 Subject: gpu: ipu-v3: initially clear all interrupts If we want to stop resetting the IPU in the future, masking all interrupts before registering the irq handlers will not be enough to avoid spurious interrupts. We also have to clear them. Signed-off-by: Philipp Zabel Acked-by: Liu Ying --- drivers/gpu/ipu-v3/ipu-common.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index b7d7bd6e3d60..97218af4fe75 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -1286,8 +1286,11 @@ static int ipu_irq_init(struct ipu_soc *ipu) return ret; } - for (i = 0; i < IPU_NUM_IRQS; i += 32) + /* Mask and clear all interrupts */ + for (i = 0; i < IPU_NUM_IRQS; i += 32) { ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32)); + ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32)); + } for (i = 0; i < IPU_NUM_IRQS; i += 32) { gc = irq_get_domain_generic_chip(ipu->domain, i); -- cgit v1.2.3 From eafc4894d0a6a773970b40dd092dbc0771ed39b5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Oct 2016 14:44:28 +0100 Subject: drm/i915: Add a sunset clause to GPU hang logging If the kernel is old, more than a few releases old, chances are that the user is using an old kernel for a good reason, despite there being GPU hangs. After 180days since driver release stop suggesting that they should send those reports upstream. [Since Daniel acked this I expect he will pick up the dim patch to automatically update the DRIVER_TIMESTAMP everytime we tag a new release.] Signed-off-by: Chris Wilson Cc: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161014134428.29582-1-chris@chris-wilson.co.uk Acked-by: Daniel Vetter Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b339c916f7a9..c278c5af6174 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -71,6 +71,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" #define DRIVER_DATE "20161010" +#define DRIVER_TIMESTAMP 1476452087 #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index a8ce358850d1..242b9a927899 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1541,6 +1541,8 @@ static int capture(void *data) return 0; } +#define DAY_AS_SECONDS(x) (24 * 60 * 60 * (x)) + /** * i915_capture_error_state - capture an error record for later analysis * @dev: drm device @@ -1593,7 +1595,8 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, return; } - if (!warned) { + if (!warned && + ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) { DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n"); DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n"); DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n"); -- cgit v1.2.3 From 4e647d960c510e0d5cd700058fb8ddd529c390ee Mon Sep 17 00:00:00 2001 From: Adam Manzanares Date: Wed, 19 Oct 2016 20:40:19 -0700 Subject: ata: set ncq_prio_enabled iff device has support We previously had a check to see if the device has support for prioritized ncq commands and a check to see if a device flag is set, through a sysfs variable, in order to send a prioritized command. This patch only allows the sysfs variable to be set if the device supports prioritized commands enabling one check in ata_build_rw_tf in order to determine whether or not to send a prioritized command. This patch depends on ata: ATA Command Priority Disabled By Default tj: Minor subject and formatting updates. Signed-off-by: Adam Manzanares Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 3 +-- drivers/ata/libata-scsi.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b294339159a4..43842fdcdc87 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -787,8 +787,7 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, if (tf->flags & ATA_TFLAG_FUA) tf->device |= 1 << 7; - if ((dev->flags & ATA_DFLAG_NCQ_PRIO) && - (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE)) { + if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE) { if (class == IOPRIO_CLASS_RT) tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 87597a3f6149..49c09d876358 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -323,10 +323,16 @@ static ssize_t ata_ncq_prio_enable_store(struct device *device, goto unlock; } - if (input) + if (input) { + if (!(dev->flags & ATA_DFLAG_NCQ_PRIO)) { + rc = -EOPNOTSUPP; + goto unlock; + } + dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLE; - else + } else { dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; + } unlock: spin_unlock_irqrestore(ap->lock, flags); -- cgit v1.2.3 From 25c07e2c5ec80a1c7390b41e2b03ca3d0e31fc01 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Wed, 19 Oct 2016 23:23:50 +0200 Subject: net: smc91x: fix neponset breakage by pxa u16 writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patch isolating the u16 writes for pxa assumed all machine_is_*() calls were removed, and therefore removed the mach-types.h include which provided them. Unfortunately 2 machine_is_*() remained in smc91x.c file including smc91x.h from which the include was removed, triggering the error: drivers/net/ethernet/smsc/smc91x.c: In function ‘smc_drv_probe’: drivers/net/ethernet/smsc/smc91x.c:2380:2: error: implicit declaration of function ‘machine_is_assabet’ [-Werror=implicit-function-declaration] if (machine_is_assabet() && machine_has_neponset()) This adds back the wrongly removed include. Fixes: d09d747ae4c2 ("net: smc91x: isolate u16 writes alignment workaround") Signed-off-by: Robert Jarzmik Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smc91x.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 45e6b81a6a92..08b17adf0a65 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -63,6 +63,8 @@ #if defined(CONFIG_ARM) +#include + /* Now the bus width is specified in the platform data * pretend here to support all I/O access types */ -- cgit v1.2.3 From b3e0b2dba870cc2f1d614a0f04459c18d8bf71a3 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 20 Oct 2016 11:43:38 +0800 Subject: drm/sun4i: sun6i-drc: Support DRC on A31 and A31s The A31 and A31s also have the DRC as part of the display pipeline. As we know virtually nothing about them, just add compatible strings for both SoCs to the stub driver. Signed-off-by: Chen-Yu Tsai Acked-by: Rob Herring Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 2 ++ drivers/gpu/drm/sun4i/sun6i_drc.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index b95696d748c7..5368961cd727 100644 --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt @@ -64,6 +64,8 @@ adaptive backlight control. Required properties: - compatible: value must be one of: + * allwinner,sun6i-a31-drc + * allwinner,sun6i-a31s-drc * allwinner,sun8i-a33-drc - reg: base address and size of the memory-mapped region. - interrupts: interrupt associated to this IP diff --git a/drivers/gpu/drm/sun4i/sun6i_drc.c b/drivers/gpu/drm/sun4i/sun6i_drc.c index bf6d846d8132..6ef707c5a719 100644 --- a/drivers/gpu/drm/sun4i/sun6i_drc.c +++ b/drivers/gpu/drm/sun4i/sun6i_drc.c @@ -98,6 +98,8 @@ static int sun6i_drc_remove(struct platform_device *pdev) } static const struct of_device_id sun6i_drc_of_table[] = { + { .compatible = "allwinner,sun6i-a31-drc" }, + { .compatible = "allwinner,sun6i-a31s-drc" }, { .compatible = "allwinner,sun8i-a33-drc" }, { } }; -- cgit v1.2.3 From 91ea2f29cba6a7fe035ea232e4f981211a9fce5d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 20 Oct 2016 11:43:39 +0800 Subject: drm/sun4i: tcon: Move SoC specific quirks to a DT matched data structure We already have some differences between the 2 supported SoCs. More will be added as we support other SoCs. To avoid bloating the probe function with even more conditionals, move the quirks to a separate data structure that's tied to the compatible string. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 33 ++++++++++++++++++--------------- drivers/gpu/drm/sun4i/sun4i_tcon.h | 11 +++++++---- 2 files changed, 25 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index cadacb517f95..7658f0337e0b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -62,7 +63,7 @@ void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel) return; } - WARN_ON(!tcon->has_channel_1); + WARN_ON(!tcon->quirks->has_channel_1); regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, SUN4I_TCON1_CTL_TCON_ENABLE, 0); clk_disable_unprepare(tcon->sclk1); @@ -80,7 +81,7 @@ void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel) return; } - WARN_ON(!tcon->has_channel_1); + WARN_ON(!tcon->quirks->has_channel_1); regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, SUN4I_TCON1_CTL_TCON_ENABLE, SUN4I_TCON1_CTL_TCON_ENABLE); @@ -202,7 +203,7 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, u8 clk_delay; u32 val; - WARN_ON(!tcon->has_channel_1); + WARN_ON(!tcon->quirks->has_channel_1); /* Adjust clock delay */ clk_delay = sun4i_tcon_get_clk_delay(mode, 1); @@ -266,7 +267,7 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, /* * FIXME: Undocumented bits */ - if (tcon->has_mux) + if (tcon->quirks->has_unknown_mux) regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, 1); } EXPORT_SYMBOL(sun4i_tcon1_mode_set); @@ -327,7 +328,7 @@ static int sun4i_tcon_init_clocks(struct device *dev, return PTR_ERR(tcon->sclk0); } - if (tcon->has_channel_1) { + if (tcon->quirks->has_channel_1) { tcon->sclk1 = devm_clk_get(dev, "tcon-ch1"); if (IS_ERR(tcon->sclk1)) { dev_err(dev, "Couldn't get the TCON channel 1 clock\n"); @@ -487,14 +488,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, drv->tcon = tcon; tcon->drm = drm; tcon->dev = dev; - - if (of_device_is_compatible(dev->of_node, "allwinner,sun5i-a13-tcon")) { - tcon->has_mux = true; - tcon->has_channel_1 = true; - } else { - tcon->has_mux = false; - tcon->has_channel_1 = false; - } + tcon->quirks = of_device_get_match_data(dev); tcon->lcd_rst = devm_reset_control_get(dev, "lcd"); if (IS_ERR(tcon->lcd_rst)) { @@ -588,9 +582,18 @@ static int sun4i_tcon_remove(struct platform_device *pdev) return 0; } +static const struct sun4i_tcon_quirks sun5i_a13_quirks = { + .has_unknown_mux = true, + .has_channel_1 = true, +}; + +static const struct sun4i_tcon_quirks sun8i_a33_quirks = { + /* nothing is supported */ +}; + static const struct of_device_id sun4i_tcon_of_table[] = { - { .compatible = "allwinner,sun5i-a13-tcon" }, - { .compatible = "allwinner,sun8i-a33-tcon" }, + { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks }, + { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, { } }; MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table); diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index 12bd48925f4d..166064bafe2e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -142,6 +142,11 @@ #define SUN4I_TCON_MAX_CHANNELS 2 +struct sun4i_tcon_quirks { + bool has_unknown_mux; /* sun5i has undocumented mux */ + bool has_channel_1; /* a33 does not have channel 1 */ +}; + struct sun4i_tcon { struct device *dev; struct drm_device *drm; @@ -160,12 +165,10 @@ struct sun4i_tcon { /* Reset control */ struct reset_control *lcd_rst; - /* Platform adjustments */ - bool has_mux; - struct drm_panel *panel; - bool has_channel_1; + /* Platform adjustments */ + const struct sun4i_tcon_quirks *quirks; }; struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node); -- cgit v1.2.3 From 93a5ec14da24a8abbac5bcb953b45cc7a5d0198a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 20 Oct 2016 11:43:40 +0800 Subject: drm/sun4i: Add compatible string for A31/A31s TCON (timing controller) The A31 TCON has mux controls for how TCON outputs are routed to the HDMI and MIPI DSI blocks. Since the A31s does not have MIPI DSI, it only has a mux for the HDMI controller input. This patch only adds support for the compatible strings. Actual support for the mux controls should be added with HDMI and MIPI DSI support. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 4 +++- drivers/gpu/drm/sun4i/sun4i_drv.c | 2 ++ drivers/gpu/drm/sun4i/sun4i_tcon.c | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index 5368961cd727..15fdca8909f2 100644 --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt @@ -28,6 +28,8 @@ The TCON acts as a timing controller for RGB, LVDS and TV interfaces. Required properties: - compatible: value must be either: * allwinner,sun5i-a13-tcon + * allwinner,sun6i-a31-tcon + * allwinner,sun6i-a31s-tcon * allwinner,sun8i-a33-tcon - reg: base address and size of memory-mapped region - interrupts: interrupt associated to this IP @@ -50,7 +52,7 @@ Required properties: second the block connected to the TCON channel 1 (usually the TV encoder) -On the A13, there is one more clock required: +On SoCs other than the A33, there is one more clock required: - 'tcon-ch1': The clock driving the TCON channel 1 DRC diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 0da9862ad8ed..a15c231fbd59 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -207,6 +207,8 @@ static bool sun4i_drv_node_is_frontend(struct device_node *node) static bool sun4i_drv_node_is_tcon(struct device_node *node) { return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") || + of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") || + of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") || of_device_is_compatible(node, "allwinner,sun8i-a33-tcon"); } diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 7658f0337e0b..c6afb2448655 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -587,12 +587,22 @@ static const struct sun4i_tcon_quirks sun5i_a13_quirks = { .has_channel_1 = true, }; +static const struct sun4i_tcon_quirks sun6i_a31_quirks = { + .has_channel_1 = true, +}; + +static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { + .has_channel_1 = true, +}; + static const struct sun4i_tcon_quirks sun8i_a33_quirks = { /* nothing is supported */ }; static const struct of_device_id sun4i_tcon_of_table[] = { { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks }, + { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks }, + { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks }, { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, { } }; -- cgit v1.2.3 From 49c440e87cd6f547f93d0dc53571ae0e11d9ec8f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 20 Oct 2016 11:43:41 +0800 Subject: drm/sun4i: Add compatible strings for A31/A31s display pipelines The A31's display pipeline has 2 frontends, 2 backends, and 2 TCONs. It also has new display enhancement blocks, such as the DRC (Dynamic Range Controller), the DEU (Display Enhancement Unit), and the CMU (Color Management Unit). It supports HDMI, MIPI DSI, and 2 LCD/LVDS channels. The A31s display pipeline is almost the same, just without MIPI DSI. Only the TCON seems to be different, due to the missing mux for MIPI DSI. Add compatible strings for both of them. Signed-off-by: Chen-Yu Tsai Acked-by: Rob Herring Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 4 ++++ drivers/gpu/drm/sun4i/sun4i_backend.c | 1 + drivers/gpu/drm/sun4i/sun4i_drv.c | 3 +++ 3 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index 15fdca8909f2..b82c00449468 100644 --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt @@ -91,6 +91,7 @@ system. Required properties: - compatible: value must be one of: * allwinner,sun5i-a13-display-backend + * allwinner,sun6i-a31-display-backend * allwinner,sun8i-a33-display-backend - reg: base address and size of the memory-mapped region. - clocks: phandles to the clocks feeding the frontend and backend @@ -121,6 +122,7 @@ deinterlacing and color space conversion. Required properties: - compatible: value must be one of: * allwinner,sun5i-a13-display-frontend + * allwinner,sun6i-a31-display-frontend * allwinner,sun8i-a33-display-frontend - reg: base address and size of the memory-mapped region. - interrupts: interrupt associated to this IP @@ -146,6 +148,8 @@ extra node. Required properties: - compatible: value must be one of: * allwinner,sun5i-a13-display-engine + * allwinner,sun6i-a31-display-engine + * allwinner,sun6i-a31s-display-engine * allwinner,sun8i-a33-display-engine - allwinner,pipelines: list of phandle to the display engine diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 32c0584e3c35..6e6c59a661b6 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -408,6 +408,7 @@ static int sun4i_backend_remove(struct platform_device *pdev) static const struct of_device_id sun4i_backend_of_table[] = { { .compatible = "allwinner,sun5i-a13-display-backend" }, + { .compatible = "allwinner,sun6i-a31-display-backend" }, { .compatible = "allwinner,sun8i-a33-display-backend" }, { } }; diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index a15c231fbd59..fa6568e1822a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -201,6 +201,7 @@ static const struct component_master_ops sun4i_drv_master_ops = { static bool sun4i_drv_node_is_frontend(struct device_node *node) { return of_device_is_compatible(node, "allwinner,sun5i-a13-display-frontend") || + of_device_is_compatible(node, "allwinner,sun6i-a31-display-frontend") || of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend"); } @@ -324,6 +325,8 @@ static int sun4i_drv_remove(struct platform_device *pdev) static const struct of_device_id sun4i_drv_of_table[] = { { .compatible = "allwinner,sun5i-a13-display-engine" }, + { .compatible = "allwinner,sun6i-a31-display-engine" }, + { .compatible = "allwinner,sun6i-a31s-display-engine" }, { .compatible = "allwinner,sun8i-a33-display-engine" }, { } }; -- cgit v1.2.3 From a501a14e38cc4d8e9c91bb508cdca7032d53f717 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Sep 2016 10:05:32 +0200 Subject: clk: sunxi-ng: Rename the internal structures Rename the structures meant to be embedded in other structures to make it consistent with the mux structure name Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai --- drivers/clk/sunxi-ng/ccu_div.h | 6 +++--- drivers/clk/sunxi-ng/ccu_frac.c | 12 ++++++------ drivers/clk/sunxi-ng/ccu_frac.h | 14 +++++++------- drivers/clk/sunxi-ng/ccu_mp.h | 4 ++-- drivers/clk/sunxi-ng/ccu_mult.h | 4 ++-- drivers/clk/sunxi-ng/ccu_nk.h | 4 ++-- drivers/clk/sunxi-ng/ccu_nkm.h | 6 +++--- drivers/clk/sunxi-ng/ccu_nkmp.h | 8 ++++---- drivers/clk/sunxi-ng/ccu_nm.h | 6 +++--- 9 files changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h index 34c338832c0d..06540f7cf41c 100644 --- a/drivers/clk/sunxi-ng/ccu_div.h +++ b/drivers/clk/sunxi-ng/ccu_div.h @@ -20,7 +20,7 @@ #include "ccu_mux.h" /** - * struct _ccu_div - Internal divider description + * struct ccu_div_internal - Internal divider description * @shift: Bit offset of the divider in its register * @width: Width of the divider field in its register * @max: Maximum value allowed for that divider. This is the @@ -36,7 +36,7 @@ * It is basically a wrapper around the clk_divider functions * arguments. */ -struct _ccu_div { +struct ccu_div_internal { u8 shift; u8 width; @@ -78,7 +78,7 @@ struct _ccu_div { struct ccu_div { u32 enable; - struct _ccu_div div; + struct ccu_div_internal div; struct ccu_mux_internal mux; struct ccu_common common; }; diff --git a/drivers/clk/sunxi-ng/ccu_frac.c b/drivers/clk/sunxi-ng/ccu_frac.c index 5c4b10cd15b5..8b5eb7756bf7 100644 --- a/drivers/clk/sunxi-ng/ccu_frac.c +++ b/drivers/clk/sunxi-ng/ccu_frac.c @@ -14,7 +14,7 @@ #include "ccu_frac.h" bool ccu_frac_helper_is_enabled(struct ccu_common *common, - struct _ccu_frac *cf) + struct ccu_frac_internal *cf) { if (!(common->features & CCU_FEATURE_FRACTIONAL)) return false; @@ -23,7 +23,7 @@ bool ccu_frac_helper_is_enabled(struct ccu_common *common, } void ccu_frac_helper_enable(struct ccu_common *common, - struct _ccu_frac *cf) + struct ccu_frac_internal *cf) { unsigned long flags; u32 reg; @@ -38,7 +38,7 @@ void ccu_frac_helper_enable(struct ccu_common *common, } void ccu_frac_helper_disable(struct ccu_common *common, - struct _ccu_frac *cf) + struct ccu_frac_internal *cf) { unsigned long flags; u32 reg; @@ -53,7 +53,7 @@ void ccu_frac_helper_disable(struct ccu_common *common, } bool ccu_frac_helper_has_rate(struct ccu_common *common, - struct _ccu_frac *cf, + struct ccu_frac_internal *cf, unsigned long rate) { if (!(common->features & CCU_FEATURE_FRACTIONAL)) @@ -63,7 +63,7 @@ bool ccu_frac_helper_has_rate(struct ccu_common *common, } unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, - struct _ccu_frac *cf) + struct ccu_frac_internal *cf) { u32 reg; @@ -84,7 +84,7 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, } int ccu_frac_helper_set_rate(struct ccu_common *common, - struct _ccu_frac *cf, + struct ccu_frac_internal *cf, unsigned long rate) { unsigned long flags; diff --git a/drivers/clk/sunxi-ng/ccu_frac.h b/drivers/clk/sunxi-ng/ccu_frac.h index e4c670b1cdfe..7b1ee380156f 100644 --- a/drivers/clk/sunxi-ng/ccu_frac.h +++ b/drivers/clk/sunxi-ng/ccu_frac.h @@ -18,7 +18,7 @@ #include "ccu_common.h" -struct _ccu_frac { +struct ccu_frac_internal { u32 enable; u32 select; @@ -33,21 +33,21 @@ struct _ccu_frac { } bool ccu_frac_helper_is_enabled(struct ccu_common *common, - struct _ccu_frac *cf); + struct ccu_frac_internal *cf); void ccu_frac_helper_enable(struct ccu_common *common, - struct _ccu_frac *cf); + struct ccu_frac_internal *cf); void ccu_frac_helper_disable(struct ccu_common *common, - struct _ccu_frac *cf); + struct ccu_frac_internal *cf); bool ccu_frac_helper_has_rate(struct ccu_common *common, - struct _ccu_frac *cf, + struct ccu_frac_internal *cf, unsigned long rate); unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, - struct _ccu_frac *cf); + struct ccu_frac_internal *cf); int ccu_frac_helper_set_rate(struct ccu_common *common, - struct _ccu_frac *cf, + struct ccu_frac_internal *cf, unsigned long rate); #endif /* _CCU_FRAC_H_ */ diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h index edf9215ea8cc..915625e97d98 100644 --- a/drivers/clk/sunxi-ng/ccu_mp.h +++ b/drivers/clk/sunxi-ng/ccu_mp.h @@ -29,8 +29,8 @@ struct ccu_mp { u32 enable; - struct _ccu_div m; - struct _ccu_div p; + struct ccu_div_internal m; + struct ccu_div_internal p; struct ccu_mux_internal mux; struct ccu_common common; }; diff --git a/drivers/clk/sunxi-ng/ccu_mult.h b/drivers/clk/sunxi-ng/ccu_mult.h index 5d2c8dc14073..113780b7558e 100644 --- a/drivers/clk/sunxi-ng/ccu_mult.h +++ b/drivers/clk/sunxi-ng/ccu_mult.h @@ -4,7 +4,7 @@ #include "ccu_common.h" #include "ccu_mux.h" -struct _ccu_mult { +struct ccu_mult_internal { u8 shift; u8 width; }; @@ -18,7 +18,7 @@ struct _ccu_mult { struct ccu_mult { u32 enable; - struct _ccu_mult mult; + struct ccu_mult_internal mult; struct ccu_mux_internal mux; struct ccu_common common; }; diff --git a/drivers/clk/sunxi-ng/ccu_nk.h b/drivers/clk/sunxi-ng/ccu_nk.h index 4b52da0c29fe..437836b80696 100644 --- a/drivers/clk/sunxi-ng/ccu_nk.h +++ b/drivers/clk/sunxi-ng/ccu_nk.h @@ -30,8 +30,8 @@ struct ccu_nk { u32 enable; u32 lock; - struct _ccu_mult n; - struct _ccu_mult k; + struct ccu_mult_internal n; + struct ccu_mult_internal k; unsigned int fixed_post_div; diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h index 35493fddd8ab..34580894f4d1 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.h +++ b/drivers/clk/sunxi-ng/ccu_nkm.h @@ -29,9 +29,9 @@ struct ccu_nkm { u32 enable; u32 lock; - struct _ccu_mult n; - struct _ccu_mult k; - struct _ccu_div m; + struct ccu_mult_internal n; + struct ccu_mult_internal k; + struct ccu_div_internal m; struct ccu_mux_internal mux; struct ccu_common common; diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.h b/drivers/clk/sunxi-ng/ccu_nkmp.h index 5adb0c92a614..a82facbc6144 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.h +++ b/drivers/clk/sunxi-ng/ccu_nkmp.h @@ -29,10 +29,10 @@ struct ccu_nkmp { u32 enable; u32 lock; - struct _ccu_mult n; - struct _ccu_mult k; - struct _ccu_div m; - struct _ccu_div p; + struct ccu_mult_internal n; + struct ccu_mult_internal k; + struct ccu_div_internal m; + struct ccu_div_internal p; struct ccu_common common; }; diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h index 0b7bcd33a2df..e87fd186da78 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.h +++ b/drivers/clk/sunxi-ng/ccu_nm.h @@ -30,9 +30,9 @@ struct ccu_nm { u32 enable; u32 lock; - struct _ccu_mult n; - struct _ccu_div m; - struct _ccu_frac frac; + struct ccu_mult_internal n; + struct ccu_div_internal m; + struct ccu_frac_internal frac; struct ccu_common common; }; -- cgit v1.2.3 From 01e5943ac16b1529821cceea36e929f7ea51c854 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 20 Oct 2016 10:28:27 +0200 Subject: net: fec: drop check for clk==NULL before calling clk_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clk_prepare, clk_enable and their counterparts (at least the common clk ones, but also most others) do check for the clk being NULL anyhow (and return 0 then), so there is no gain when the caller checks, too. Signed-off-by: Uwe Kleine-König Acked-by: Fugang Duan Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 4ce8179aa4ff..43b2839a3d11 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1841,11 +1841,11 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) ret = clk_prepare_enable(fep->clk_ahb); if (ret) return ret; - if (fep->clk_enet_out) { - ret = clk_prepare_enable(fep->clk_enet_out); - if (ret) - goto failed_clk_enet_out; - } + + ret = clk_prepare_enable(fep->clk_enet_out); + if (ret) + goto failed_clk_enet_out; + if (fep->clk_ptp) { mutex_lock(&fep->ptp_clk_mutex); ret = clk_prepare_enable(fep->clk_ptp); @@ -1857,23 +1857,20 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) } mutex_unlock(&fep->ptp_clk_mutex); } - if (fep->clk_ref) { - ret = clk_prepare_enable(fep->clk_ref); - if (ret) - goto failed_clk_ref; - } + + ret = clk_prepare_enable(fep->clk_ref); + if (ret) + goto failed_clk_ref; } else { clk_disable_unprepare(fep->clk_ahb); - if (fep->clk_enet_out) - clk_disable_unprepare(fep->clk_enet_out); + clk_disable_unprepare(fep->clk_enet_out); if (fep->clk_ptp) { mutex_lock(&fep->ptp_clk_mutex); clk_disable_unprepare(fep->clk_ptp); fep->ptp_clk_on = false; mutex_unlock(&fep->ptp_clk_mutex); } - if (fep->clk_ref) - clk_disable_unprepare(fep->clk_ref); + clk_disable_unprepare(fep->clk_ref); } return 0; -- cgit v1.2.3 From 547412fe08239366f867aea4cc9c8e6816302c1d Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Thu, 20 Oct 2016 16:30:31 +0800 Subject: net: phy: aquantia: add PHY ID of AQR106 and AQR107 The AQR106 and AQR107 can use the existing driver. Signed-off-by: Shaohui Xie Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 09b0b0aa8d68..e8ae50e1255e 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -21,6 +21,8 @@ #define PHY_ID_AQ1202 0x03a1b445 #define PHY_ID_AQ2104 0x03a1b460 #define PHY_ID_AQR105 0x03a1b4a2 +#define PHY_ID_AQR106 0x03a1b4d0 +#define PHY_ID_AQR107 0x03a1b4e0 #define PHY_ID_AQR405 0x03a1b4b0 #define PHY_AQUANTIA_FEATURES (SUPPORTED_10000baseT_Full | \ @@ -153,6 +155,30 @@ static struct phy_driver aquantia_driver[] = { .ack_interrupt = aquantia_ack_interrupt, .read_status = aquantia_read_status, }, +{ + .phy_id = PHY_ID_AQR106, + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQR106", + .features = PHY_AQUANTIA_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, + .config_intr = aquantia_config_intr, + .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, +}, +{ + .phy_id = PHY_ID_AQR107, + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQR107", + .features = PHY_AQUANTIA_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, + .config_intr = aquantia_config_intr, + .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, +}, { .phy_id = PHY_ID_AQR405, .phy_id_mask = 0xfffffff0, @@ -173,6 +199,8 @@ static struct mdio_device_id __maybe_unused aquantia_tbl[] = { { PHY_ID_AQ1202, 0xfffffff0 }, { PHY_ID_AQ2104, 0xfffffff0 }, { PHY_ID_AQR105, 0xfffffff0 }, + { PHY_ID_AQR106, 0xfffffff0 }, + { PHY_ID_AQR107, 0xfffffff0 }, { PHY_ID_AQR405, 0xfffffff0 }, { } }; -- cgit v1.2.3 From d80f45ffd8847891554f00e19fc9bc95ee720976 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 20 Oct 2016 16:59:49 +0000 Subject: dwc_eth_qos: use dev_kfree_skb_any instead of dev_kfree_skb Replace dev_kfree_skb with dev_kfree_skb_any in dwceqos_start_xmit() which can be called from hard irq context (netpoll) and from other contexts. dwceqos_start_xmit() only frees skbs that it has dropped. This is detected by Coccinelle semantic patch. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/synopsys/dwc_eth_qos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c b/drivers/net/ethernet/synopsys/dwc_eth_qos.c index 0d0053128542..eaa51ce8bd6d 100644 --- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c +++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c @@ -2211,7 +2211,7 @@ static int dwceqos_start_xmit(struct sk_buff *skb, struct net_device *ndev) tx_error: dwceqos_tx_rollback(lp, &trans); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return 0; } -- cgit v1.2.3 From 81ad2b7de6dd352802f9979910343d4867e1ac94 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 20 Oct 2016 17:00:32 +0000 Subject: net: ethernet: mediatek: use dev_kfree_skb_any instead of dev_kfree_skb Replace dev_kfree_skb with dev_kfree_skb_any in mtk_start_xmit() which can be called from hard irq context (netpoll) and from other contexts. mtk_start_xmit() only frees skbs that it has dropped. This is detected by Coccinelle semantic patch. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 8f80e618ae59..d71627417ea7 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -843,7 +843,7 @@ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) drop: spin_unlock(ð->page_lock); stats->tx_dropped++; - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } -- cgit v1.2.3 From 1a61a8f1776758acb5111785c8a1688394fa3a60 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 20 Oct 2016 17:01:56 +0000 Subject: myri10ge: fix typo in parameter description Fix typo in parameter description. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 5ae3f175cc23..e506ca876d0d 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -289,7 +289,7 @@ static char *myri10ge_fw_names[MYRI10GE_MAX_BOARDS] = {[0 ... (MYRI10GE_MAX_BOARDS - 1)] = NULL }; module_param_array_named(myri10ge_fw_names, myri10ge_fw_names, charp, NULL, 0444); -MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image names per board"); +MODULE_PARM_DESC(myri10ge_fw_names, "Firmware image names per board"); static int myri10ge_ecrc_enable = 1; module_param(myri10ge_ecrc_enable, int, S_IRUGO); -- cgit v1.2.3 From d894be57ca92c8a8819ab544d550809e8731137b Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 20 Oct 2016 13:55:16 -0400 Subject: ethernet: use net core MTU range checking in more drivers Somehow, I missed a healthy number of ethernet drivers in the last pass. Most of these drivers either were in need of an updated max_mtu to make jumbo frames possible to enable again. In a few cases, also setting a different min_mtu to match previous lower bounds. There are also a few drivers that had no upper bounds checking, so they're getting a brand new ETH_MAX_MTU that is identical to IP_MAX_MTU, but accessible by includes all ethernet and ethernet-like drivers all have already. acenic: - min_mtu = 0, max_mtu = 9000 amazon/ena: - min_mtu = 128, max_mtu = adapter->max_mtu amd/xgbe: - min_mtu = 0, max_mtu = 9000 sb1250: - min_mtu = 0, max_mtu = 1518 cxgb3: - min_mtu = 81, max_mtu = 65535 cxgb4: - min_mtu = 81, max_mtu = 9600 cxgb4vf: - min_mtu = 81, max_mtu = 65535 benet: - min_mtu = 256, max_mtu = 9000 ibmveth: - min_mtu = 68, max_mtu = 65535 ibmvnic: - min_mtu = adapter->min_mtu, max_mtu = adapter->max_mtu - remove now redundant ibmvnic_change_mtu jme: - min_mtu = 1280, max_mtu = 9202 mv643xx_eth: - min_mtu = 64, max_mtu = 9500 mlxsw: - min_mtu = 0, max_mtu = 65535 - Basically bypassing the core checks, and instead relying on dynamic checks in the respective switch drivers' ndo_change_mtu functions ns83820: - min_mtu = 0 - remove redundant ns83820_change_mtu, only checked for mtu > 1500 netxen: - min_mtu = 0, max_mtu = 8000 (P2), max_mtu = 9600 (P3) qlge: - min_mtu = 1500, max_mtu = 9000 - driver only supports setting mtu to 1500 or 9000, so the core check only rules out < 1500 and > 9000, qlge_change_mtu still needs to check that the value is 1500 or 9000 qualcomm/emac: - min_mtu = 46, max_mtu = 9194 xilinx_axienet: - min_mtu = 64, max_mtu = 9000 Fixes: 61e84623ace3 ("net: centralize net_device min/max MTU checking") CC: netdev@vger.kernel.org CC: Jes Sorensen CC: Netanel Belgazal CC: Tom Lendacky CC: Santosh Raspatur CC: Hariprasad S CC: Sathya Perla CC: Ajit Khaparde CC: Sriharsha Basavapatna CC: Somnath Kotur CC: Thomas Falcon CC: John Allen CC: Guo-Fu Tseng CC: Sebastian Hesselbarth CC: Jiri Pirko CC: Ido Schimmel CC: Manish Chopra CC: Sony Chacko CC: Rajesh Borundia CC: Timur Tabi CC: Anirudha Sarangi CC: John Linn Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/alteon/acenic.c | 5 ++--- drivers/net/ethernet/amazon/ena/ena_netdev.c | 9 ++------- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 5 ----- drivers/net/ethernet/amd/xgbe/xgbe-main.c | 2 ++ drivers/net/ethernet/broadcom/sb1250-mac.c | 12 ++---------- drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 4 ++-- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 6 ++++-- .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 6 ++---- drivers/net/ethernet/emulex/benet/be_main.c | 22 ++++------------------ drivers/net/ethernet/ibm/ibmveth.c | 6 +++--- drivers/net/ethernet/ibm/ibmvnic.c | 16 ++++------------ drivers/net/ethernet/jme.c | 12 ++++-------- drivers/net/ethernet/marvell/mv643xx_eth.c | 7 ++++--- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 3 +++ drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 3 +++ drivers/net/ethernet/natsemi/ns83820.c | 11 ++--------- drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | 12 ------------ .../net/ethernet/qlogic/netxen/netxen_nic_main.c | 7 +++++++ drivers/net/ethernet/qlogic/qlge/qlge_main.c | 7 +++++++ drivers/net/ethernet/qualcomm/emac/emac.c | 13 ++++++------- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 7 ++++--- include/uapi/linux/if_ether.h | 1 + 22 files changed, 68 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index b90a26b13fdf..a5c1e290677a 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -474,6 +474,8 @@ static int acenic_probe_one(struct pci_dev *pdev, dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; dev->watchdog_timeo = 5*HZ; + dev->min_mtu = 0; + dev->max_mtu = ACE_JUMBO_MTU; dev->netdev_ops = &ace_netdev_ops; dev->ethtool_ops = &ace_ethtool_ops; @@ -2548,9 +2550,6 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu) struct ace_private *ap = netdev_priv(dev); struct ace_regs __iomem *regs = ap->regs; - if (new_mtu > ACE_JUMBO_MTU) - return -EINVAL; - writel(new_mtu + ETH_HLEN + 4, ®s->IfMtu); dev->mtu = new_mtu; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index bfeaec5bd7b9..2a55ab00686a 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -103,13 +103,6 @@ static int ena_change_mtu(struct net_device *dev, int new_mtu) struct ena_adapter *adapter = netdev_priv(dev); int ret; - if ((new_mtu > adapter->max_mtu) || (new_mtu < ENA_MIN_MTU)) { - netif_err(adapter, drv, dev, - "Invalid MTU setting. new_mtu: %d\n", new_mtu); - - return -EINVAL; - } - ret = ena_com_set_dev_mtu(adapter->ena_dev, new_mtu); if (!ret) { netif_dbg(adapter, drv, dev, "set MTU to %d\n", new_mtu); @@ -2755,6 +2748,8 @@ static void ena_set_conf_feat_params(struct ena_adapter *adapter, ena_set_dev_offloads(feat, netdev); adapter->max_mtu = feat->dev_attr.max_mtu; + netdev->max_mtu = adapter->max_mtu; + netdev->min_mtu = ENA_MIN_MTU; } static int ena_rss_init_default(struct ena_adapter *adapter) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 7f9216db026f..c4e668208e04 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -257,11 +257,6 @@ static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu) { unsigned int rx_buf_size; - if (mtu > XGMAC_JUMBO_PACKET_MTU) { - netdev_alert(netdev, "MTU exceeds maximum supported value\n"); - return -EINVAL; - } - rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; rx_buf_size = clamp_val(rx_buf_size, XGBE_RX_MIN_BUF_SIZE, PAGE_SIZE); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 9de078819aa6..667e1209a2f5 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -738,6 +738,8 @@ static int xgbe_probe(struct platform_device *pdev) pdata->netdev_features = netdev->features; netdev->priv_flags |= IFF_UNICAST_FLT; + netdev->min_mtu = 0; + netdev->max_mtu = XGMAC_JUMBO_PACKET_MTU; /* Use default watchdog timeout */ netdev->watchdog_timeo = 0; diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index f1b81187a201..cb312e4c89f4 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -2147,15 +2147,6 @@ static void sbmac_setmulti(struct sbmac_softc *sc) } } -static int sb1250_change_mtu(struct net_device *_dev, int new_mtu) -{ - if (new_mtu > ENET_PACKET_SIZE) - return -EINVAL; - _dev->mtu = new_mtu; - pr_info("changing the mtu to %d\n", new_mtu); - return 0; -} - static const struct net_device_ops sbmac_netdev_ops = { .ndo_open = sbmac_open, .ndo_stop = sbmac_close, @@ -2163,7 +2154,6 @@ static const struct net_device_ops sbmac_netdev_ops = { .ndo_set_rx_mode = sbmac_set_rx_mode, .ndo_tx_timeout = sbmac_tx_timeout, .ndo_do_ioctl = sbmac_mii_ioctl, - .ndo_change_mtu = sb1250_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2229,6 +2219,8 @@ static int sbmac_init(struct platform_device *pldev, long long base) dev->netdev_ops = &sbmac_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; + dev->max_mtu = 0; + dev->max_mtu = ENET_PACKET_SIZE; netif_napi_add(dev, &sc->napi, sbmac_poll, 16); diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 43da891fab97..092b3c16440b 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -2531,8 +2531,6 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu) struct adapter *adapter = pi->adapter; int ret; - if (new_mtu < 81) /* accommodate SACK */ - return -EINVAL; if ((ret = t3_mac_set_mtu(&pi->mac, new_mtu))) return ret; dev->mtu = new_mtu; @@ -3295,6 +3293,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->netdev_ops = &cxgb_netdev_ops; netdev->ethtool_ops = &cxgb_ethtool_ops; + netdev->min_mtu = 81; + netdev->max_mtu = ETH_MAX_MTU; } pci_set_drvdata(pdev, adapter); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index f320497368f4..b0bb23f95beb 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2502,8 +2502,6 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu) int ret; struct port_info *pi = netdev_priv(dev); - if (new_mtu < 81 || new_mtu > MAX_MTU) /* accommodate SACK */ - return -EINVAL; ret = t4_set_rxmode(pi->adapter, pi->adapter->pf, pi->viid, new_mtu, -1, -1, -1, -1, true); if (!ret) @@ -4803,6 +4801,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->priv_flags |= IFF_UNICAST_FLT; + /* MTU range: 81 - 9600 */ + netdev->min_mtu = 81; + netdev->max_mtu = MAX_MTU; + netdev->netdev_ops = &cxgb4_netdev_ops; #ifdef CONFIG_CHELSIO_T4_DCB netdev->dcbnl_ops = &cxgb4_dcb_ops; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 100b2cc064a3..5d4da0e8acaa 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -1108,10 +1108,6 @@ static int cxgb4vf_change_mtu(struct net_device *dev, int new_mtu) int ret; struct port_info *pi = netdev_priv(dev); - /* accommodate SACK */ - if (new_mtu < 81) - return -EINVAL; - ret = t4vf_set_rxmode(pi->adapter, pi->viid, new_mtu, -1, -1, -1, -1, true); if (!ret) @@ -2966,6 +2962,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_HIGHDMA; netdev->priv_flags |= IFF_UNICAST_FLT; + netdev->min_mtu = 81; + netdev->max_mtu = ETH_MAX_MTU; netdev->netdev_ops = &cxgb4vf_netdev_ops; netdev->ethtool_ops = &cxgb4vf_ethtool_ops; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index cece8a08edca..3f6152cc648c 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1406,23 +1406,6 @@ drop: return NETDEV_TX_OK; } -static int be_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct be_adapter *adapter = netdev_priv(netdev); - struct device *dev = &adapter->pdev->dev; - - if (new_mtu < BE_MIN_MTU || new_mtu > BE_MAX_MTU) { - dev_info(dev, "MTU must be between %d and %d bytes\n", - BE_MIN_MTU, BE_MAX_MTU); - return -EINVAL; - } - - dev_info(dev, "MTU changed from %d to %d bytes\n", - netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - return 0; -} - static inline bool be_in_all_promisc(struct be_adapter *adapter) { return (adapter->if_flags & BE_IF_FLAGS_ALL_PROMISCUOUS) == @@ -5216,7 +5199,6 @@ static const struct net_device_ops be_netdev_ops = { .ndo_start_xmit = be_xmit, .ndo_set_rx_mode = be_set_rx_mode, .ndo_set_mac_address = be_mac_addr_set, - .ndo_change_mtu = be_change_mtu, .ndo_get_stats64 = be_get_stats64, .ndo_validate_addr = eth_validate_addr, .ndo_vlan_rx_add_vid = be_vlan_add_vid, @@ -5266,6 +5248,10 @@ static void be_netdev_init(struct net_device *netdev) netdev->netdev_ops = &be_netdev_ops; netdev->ethtool_ops = &be_ethtool_ops; + + /* MTU range: 256 - 9000 */ + netdev->min_mtu = BE_MIN_MTU; + netdev->max_mtu = BE_MAX_MTU; } static void be_cleanup(struct be_adapter *adapter) diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index ebe60719e489..29c05d0d79a9 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1349,9 +1349,6 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) int i, rc; int need_restart = 0; - if (new_mtu < IBMVETH_MIN_MTU) - return -EINVAL; - for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size) break; @@ -1551,6 +1548,9 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) netdev->hw_features |= NETIF_F_TSO; } + netdev->min_mtu = IBMVETH_MIN_MTU; + netdev->min_mtu = ETH_MAX_MTU; + memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN); if (firmware_has_feature(FW_FEATURE_CMO)) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index bfe17d9c022d..657206be7ba9 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -902,17 +902,6 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p) return 0; } -static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct ibmvnic_adapter *adapter = netdev_priv(netdev); - - if (new_mtu > adapter->req_mtu || new_mtu < adapter->min_mtu) - return -EINVAL; - - netdev->mtu = new_mtu; - return 0; -} - static void ibmvnic_tx_timeout(struct net_device *dev) { struct ibmvnic_adapter *adapter = netdev_priv(dev); @@ -1029,7 +1018,6 @@ static const struct net_device_ops ibmvnic_netdev_ops = { .ndo_set_rx_mode = ibmvnic_set_multi, .ndo_set_mac_address = ibmvnic_set_mac, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = ibmvnic_change_mtu, .ndo_tx_timeout = ibmvnic_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ibmvnic_netpoll_controller, @@ -2638,10 +2626,12 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq, break; case MIN_MTU: adapter->min_mtu = be64_to_cpu(crq->query_capability.number); + netdev->min_mtu = adapter->min_mtu; netdev_dbg(netdev, "min_mtu = %lld\n", adapter->min_mtu); break; case MAX_MTU: adapter->max_mtu = be64_to_cpu(crq->query_capability.number); + netdev->max_mtu = adapter->max_mtu; netdev_dbg(netdev, "max_mtu = %lld\n", adapter->max_mtu); break; case MAX_MULTICAST_FILTERS: @@ -3654,6 +3644,8 @@ static void handle_crq_init_rsp(struct work_struct *work) goto task_failed; netdev->real_num_tx_queues = adapter->req_tx_queues; + netdev->min_mtu = adapter->min_mtu; + netdev->max_mtu = adapter->max_mtu; if (adapter->failover) { adapter->failover = false; diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 836ebd8ee768..f9fcab54783c 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -2357,14 +2357,6 @@ jme_change_mtu(struct net_device *netdev, int new_mtu) { struct jme_adapter *jme = netdev_priv(netdev); - if (new_mtu == jme->old_mtu) - return 0; - - if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) || - ((new_mtu) < IPV6_MIN_MTU)) - return -EINVAL; - - netdev->mtu = new_mtu; netdev_update_features(netdev); @@ -3063,6 +3055,10 @@ jme_init_one(struct pci_dev *pdev, if (using_dac) netdev->features |= NETIF_F_HIGHDMA; + /* MTU range: 1280 - 9202*/ + netdev->min_mtu = IPV6_MIN_MTU; + netdev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE - ETH_HLEN; + SET_NETDEV_DEV(netdev, &pdev->dev); pci_set_drvdata(pdev, netdev); diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 18e6bb6e3867..68675d83bdc5 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2585,9 +2585,6 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu) { struct mv643xx_eth_private *mp = netdev_priv(dev); - if (new_mtu < 64 || new_mtu > 9500) - return -EINVAL; - dev->mtu = new_mtu; mv643xx_eth_recalc_skb_size(mp); tx_set_rate(mp, 1000000000, 16777216); @@ -3206,6 +3203,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev->priv_flags |= IFF_UNICAST_FLT; dev->gso_max_segs = MV643XX_MAX_TSO_SEGS; + /* MTU range: 64 - 9500 */ + dev->min_mtu = 64; + dev->max_mtu = 9500; + SET_NETDEV_DEV(dev, &pdev->dev); if (mp->shared->win_protect) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 99805fd3d110..6d8cb22579ee 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2284,6 +2284,9 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC; dev->hw_features |= NETIF_F_HW_TC; + dev->min_mtu = 0; + dev->max_mtu = ETH_MAX_MTU; + /* Each packet needs to have a Tx header (metadata) on top all other * headers. */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index c0c23e2f3275..66af63d99b8b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -994,6 +994,9 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG | NETIF_F_VLAN_CHALLENGED; + dev->min_mtu = 0; + dev->max_mtu = ETH_MAX_MTU; + /* Each packet needs to have a Tx header (metadata) on top all other * headers. */ diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 569ade6cf85c..a34631ed741d 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -1679,14 +1679,6 @@ static void ns83820_getmac(struct ns83820 *dev, u8 *mac) } } -static int ns83820_change_mtu(struct net_device *ndev, int new_mtu) -{ - if (new_mtu > RX_BUF_SIZE) - return -EINVAL; - ndev->mtu = new_mtu; - return 0; -} - static void ns83820_set_multicast(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); @@ -1933,7 +1925,6 @@ static const struct net_device_ops netdev_ops = { .ndo_stop = ns83820_stop, .ndo_start_xmit = ns83820_hard_start_xmit, .ndo_get_stats = ns83820_get_stats, - .ndo_change_mtu = ns83820_change_mtu, .ndo_set_rx_mode = ns83820_set_multicast, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, @@ -2190,6 +2181,8 @@ static int ns83820_init_one(struct pci_dev *pci_dev, ndev->features |= NETIF_F_SG; ndev->features |= NETIF_F_IP_CSUM; + ndev->min_mtu = 0; + #ifdef NS83820_VLAN_ACCEL_SUPPORT /* We also support hardware vlan acceleration */ ndev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index 2b10f1bcd151..a996801d442d 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c @@ -987,20 +987,8 @@ int netxen_send_lro_cleanup(struct netxen_adapter *adapter) int netxen_nic_change_mtu(struct net_device *netdev, int mtu) { struct netxen_adapter *adapter = netdev_priv(netdev); - int max_mtu; int rc = 0; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - max_mtu = P3_MAX_MTU; - else - max_mtu = P2_MAX_MTU; - - if (mtu > max_mtu) { - printk(KERN_ERR "%s: mtu > %d bytes unsupported\n", - netdev->name, max_mtu); - return -EINVAL; - } - if (adapter->set_mtu) rc = adapter->set_mtu(adapter, mtu); diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 7a0281a36c28..561fb94c7267 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1572,6 +1572,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->physical_port = i; } + /* MTU range: 0 - 8000 (P2) or 9600 (P3) */ + netdev->min_mtu = 0; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netdev->max_mtu = P3_MAX_MTU; + else + netdev->max_mtu = P2_MAX_MTU; + netxen_nic_clear_stats(adapter); err = netxen_setup_intr(adapter); diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index fd4a8e473f11..1409412ab39d 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -4788,6 +4788,13 @@ static int qlge_probe(struct pci_dev *pdev, ndev->ethtool_ops = &qlge_ethtool_ops; ndev->watchdog_timeo = 10 * HZ; + /* MTU range: this driver only supports 1500 or 9000, so this only + * filters out values above or below, and we'll rely on + * qlge_change_mtu to make sure only 1500 or 9000 are allowed + */ + ndev->min_mtu = ETH_DATA_LEN; + ndev->max_mtu = 9000; + err = register_netdev(ndev); if (err) { dev_err(&pdev->dev, "net device registration failed.\n"); diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 9bf3b2b82e95..e4e1925d18a4 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -239,15 +239,8 @@ static void emac_rx_mode_set(struct net_device *netdev) /* Change the Maximum Transfer Unit (MTU) */ static int emac_change_mtu(struct net_device *netdev, int new_mtu) { - unsigned int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; struct emac_adapter *adpt = netdev_priv(netdev); - if ((max_frame < EMAC_MIN_ETH_FRAME_SIZE) || - (max_frame > EMAC_MAX_ETH_FRAME_SIZE)) { - netdev_err(adpt->netdev, "error: invalid MTU setting\n"); - return -EINVAL; - } - netif_info(adpt, hw, adpt->netdev, "changing MTU from %d to %d\n", netdev->mtu, new_mtu); @@ -679,6 +672,12 @@ static int emac_probe(struct platform_device *pdev) netdev->vlan_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6; + /* MTU range: 46 - 9194 */ + netdev->min_mtu = EMAC_MIN_ETH_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); + netdev->max_mtu = EMAC_MAX_ETH_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); + INIT_WORK(&adpt->work_thread, emac_work_thread); /* Initialize queues */ diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index c688d68c39aa..c9c8a3be9f1b 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1034,9 +1034,6 @@ static int axienet_change_mtu(struct net_device *ndev, int new_mtu) XAE_TRL_SIZE) > lp->rxmem) return -EINVAL; - if ((new_mtu > XAE_JUMBO_MTU) || (new_mtu < 64)) - return -EINVAL; - ndev->mtu = new_mtu; return 0; @@ -1475,6 +1472,10 @@ static int axienet_probe(struct platform_device *pdev) ndev->netdev_ops = &axienet_netdev_ops; ndev->ethtool_ops = &axienet_ethtool_ops; + /* MTU range: 64 - 9000 */ + ndev->min_mtu = 64; + ndev->max_mtu = XAE_JUMBO_MTU; + lp = netdev_priv(ndev); lp->ndev = ndev; lp->dev = &pdev->dev; diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index 864d6f2b2cb0..3e5185e9ef03 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -36,6 +36,7 @@ #define ETH_FCS_LEN 4 /* Octets in the FCS */ #define ETH_MIN_MTU 68 /* Min IPv4 MTU per RFC791 */ +#define ETH_MAX_MTU 0xFFFFU /* 65535, same as IP_MAX_MTU */ /* * These are the defined Ethernet Protocol ID's. -- cgit v1.2.3 From f77f0aee4da4beff5042b49913e856539f23adff Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 20 Oct 2016 13:55:17 -0400 Subject: net: use core MTU range checking in USB NIC drivers usbnet: - Remove stale new_mtu <= 0 check in usbnet.c - Set min_mtu = 0, max_mtu = 65535 (sub-drivers must set their own max_mtu and/or min_mtu as needed) r8152: - Set appropriate max_mtu for different variants (1500 or 9194) lan78xx: - Set max_mtu = 9000 asix_driver: - max_mtu = 16384 for ax88178 variant ax88179: - max_mtu = 4088 cdc_ncm: - max_mtu from hardware cdc-phonet: - min_mtu = 6, max_mtu = 65541 sierra_net: - max_mtu = 1500, call usbnet_change_mtu directly - sierra_net_change_mtu checked for MTU > 1500, then called usbnet_change_mtu, but if we set max_mtu to let the network core handle the range check, then we can simply call usbnet_change_mtu directly smsc75xx: - max_mtu = 9000 CC: netdev@vger.kernel.org CC: Woojung Huh CC: Microchip Linux Driver Support CC: Hayes Wang CC: Oliver Neukum CC: Steve Glendinning Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/usb/asix_devices.c | 4 +--- drivers/net/usb/ax88179_178a.c | 4 +--- drivers/net/usb/cdc-phonet.c | 12 ++---------- drivers/net/usb/cdc_ncm.c | 5 +---- drivers/net/usb/lan78xx.c | 8 +++----- drivers/net/usb/r8152.c | 15 ++++++++++++--- drivers/net/usb/sierra_net.c | 13 ++----------- drivers/net/usb/smsc75xx.c | 4 +--- drivers/net/usb/usbnet.c | 4 ++-- 9 files changed, 25 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index cce24950a0ab..7363cc5dd1bf 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -1026,9 +1026,6 @@ static int ax88178_change_mtu(struct net_device *net, int new_mtu) netdev_dbg(dev->net, "ax88178_change_mtu() new_mtu=%d\n", new_mtu); - if (new_mtu <= 0 || ll_mtu > 16384) - return -EINVAL; - if ((ll_mtu % dev->maxpacket) == 0) return -EDOM; @@ -1081,6 +1078,7 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->netdev_ops = &ax88178_netdev_ops; dev->net->ethtool_ops = &ax88178_ethtool_ops; + dev->net->max_mtu = 16384 - (dev->net->hard_header_len + 4); /* Blink LEDS so users know driver saw dongle */ asix_sw_reset(dev, 0, 0); diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index e6338c16081a..36c70d6f7363 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -907,9 +907,6 @@ static int ax88179_change_mtu(struct net_device *net, int new_mtu) struct usbnet *dev = netdev_priv(net); u16 tmp16; - if (new_mtu <= 0 || new_mtu > 4088) - return -EINVAL; - net->mtu = new_mtu; dev->hard_mtu = net->mtu + net->hard_header_len; @@ -1266,6 +1263,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->netdev_ops = &ax88179_netdev_ops; dev->net->ethtool_ops = &ax88179_ethtool_ops; dev->net->needed_headroom = 8; + dev->net->max_mtu = 4088; /* Initialize MII structure */ dev->mii.dev = dev->net; diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index ff2270ead2e6..eb52de8205f0 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -276,21 +276,11 @@ static int usbpn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -ENOIOCTLCMD; } -static int usbpn_set_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU)) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - static const struct net_device_ops usbpn_ops = { .ndo_open = usbpn_open, .ndo_stop = usbpn_close, .ndo_start_xmit = usbpn_xmit, .ndo_do_ioctl = usbpn_ioctl, - .ndo_change_mtu = usbpn_set_mtu, }; static void usbpn_setup(struct net_device *dev) @@ -301,6 +291,8 @@ static void usbpn_setup(struct net_device *dev) dev->type = ARPHRD_PHONET; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->mtu = PHONET_MAX_MTU; + dev->min_mtu = PHONET_MIN_MTU; + dev->max_mtu = PHONET_MAX_MTU; dev->hard_header_len = 1; dev->dev_addr[0] = PN_MEDIA_USB; dev->addr_len = 1; diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 877c9516e781..7141817946f0 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -740,10 +740,6 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx) int cdc_ncm_change_mtu(struct net_device *net, int new_mtu) { struct usbnet *dev = netdev_priv(net); - int maxmtu = cdc_ncm_max_dgram_size(dev) - cdc_ncm_eth_hlen(dev); - - if (new_mtu <= 0 || new_mtu > maxmtu) - return -EINVAL; net->mtu = new_mtu; cdc_ncm_set_dgram_size(dev, new_mtu + cdc_ncm_eth_hlen(dev)); @@ -909,6 +905,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ /* must handle MTU changes */ dev->net->netdev_ops = &cdc_ncm_netdev_ops; + dev->net->max_mtu = cdc_ncm_max_dgram_size(dev) - cdc_ncm_eth_hlen(dev); return 0; diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 13f033cebf2d..c4e748e92db4 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1980,11 +1980,6 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu) int old_rx_urb_size = dev->rx_urb_size; int ret; - if (new_mtu > MAX_SINGLE_PACKET_SIZE) - return -EINVAL; - - if (new_mtu <= 0) - return -EINVAL; /* no second zero-length packet read wanted after mtu-sized packets */ if ((ll_mtu % dev->maxpacket) == 0) return -EDOM; @@ -3388,6 +3383,9 @@ static int lan78xx_probe(struct usb_interface *intf, if (netdev->mtu > (dev->hard_mtu - netdev->hard_header_len)) netdev->mtu = dev->hard_mtu - netdev->hard_header_len; + /* MTU range: 68 - 9000 */ + netdev->max_mtu = MAX_SINGLE_PACKET_SIZE; + dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0; dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1; dev->ep_intr = (intf->cur_altsetting)->endpoint + 2; diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 8d6e13c689e0..4213c28eeb43 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -4119,9 +4119,6 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu) break; } - if (new_mtu < 68 || new_mtu > RTL8153_MAX_MTU) - return -EINVAL; - ret = usb_autopm_get_interface(tp->intf); if (ret < 0) return ret; @@ -4311,6 +4308,18 @@ static int rtl8152_probe(struct usb_interface *intf, netdev->ethtool_ops = &ops; netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE); + /* MTU range: 68 - 1500 or 9194 */ + netdev->min_mtu = ETH_MIN_MTU; + switch (tp->version) { + case RTL_VER_01: + case RTL_VER_02: + netdev->max_mtu = ETH_DATA_LEN; + break; + default: + netdev->max_mtu = RTL8153_MAX_MTU; + break; + } + tp->mii.dev = netdev; tp->mii.mdio_read = read_mii_word; tp->mii.mdio_write = write_mii_word; diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index a251588762ec..12071f1582df 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -165,7 +165,6 @@ struct lsi_umts { /* Forward definitions */ static void sierra_sync_timer(unsigned long syncdata); -static int sierra_net_change_mtu(struct net_device *net, int new_mtu); /* Our own net device operations structure */ static const struct net_device_ops sierra_net_device_ops = { @@ -173,7 +172,7 @@ static const struct net_device_ops sierra_net_device_ops = { .ndo_stop = usbnet_stop, .ndo_start_xmit = usbnet_start_xmit, .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_change_mtu = sierra_net_change_mtu, + .ndo_change_mtu = usbnet_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; @@ -622,15 +621,6 @@ static const struct ethtool_ops sierra_net_ethtool_ops = { .nway_reset = usbnet_nway_reset, }; -/* MTU can not be more than 1500 bytes, enforce it. */ -static int sierra_net_change_mtu(struct net_device *net, int new_mtu) -{ - if (new_mtu > SIERRA_NET_MAX_SUPPORTED_MTU) - return -EINVAL; - - return usbnet_change_mtu(net, new_mtu); -} - static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) { int result = 0; @@ -720,6 +710,7 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->hard_header_len += SIERRA_NET_HIP_EXT_HDR_LEN; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; + dev->net->max_mtu = SIERRA_NET_MAX_SUPPORTED_MTU; /* Set up the netdev */ dev->net->flags |= IFF_NOARP; diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 9af9799935db..0b17b40d7a4f 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -925,9 +925,6 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu) struct usbnet *dev = netdev_priv(netdev); int ret; - if (new_mtu > MAX_SINGLE_PACKET_SIZE) - return -EINVAL; - ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN); if (ret < 0) { netdev_warn(dev->net, "Failed to set mac rx frame length\n"); @@ -1448,6 +1445,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->flags |= IFF_MULTICAST; dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; + dev->net->max_mtu = MAX_SINGLE_PACKET_SIZE; return 0; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index d5071e364d40..3de65ea6531a 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -384,8 +384,6 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu) int old_hard_mtu = dev->hard_mtu; int old_rx_urb_size = dev->rx_urb_size; - if (new_mtu <= 0) - return -EINVAL; // no second zero-length packet read wanted after mtu-sized packets if ((ll_mtu % dev->maxpacket) == 0) return -EDOM; @@ -1669,6 +1667,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) * bind() should set rx_urb_size in that case. */ dev->hard_mtu = net->mtu + net->hard_header_len; + net->min_mtu = 0; + net->max_mtu = ETH_MAX_MTU; net->netdev_ops = &usbnet_netdev_ops; net->watchdog_timeo = TX_TIMEOUT_JIFFIES; -- cgit v1.2.3 From 9c22b4a34eddbaa5b5243c8cd27e31aa36e676e1 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 20 Oct 2016 13:55:18 -0400 Subject: net: use core MTU range checking in wireless drivers - set max_mtu in wil6210 driver - set max_mtu in atmel driver - set min/max_mtu in cisco airo driver, remove airo_change_mtu - set min/max_mtu in ipw2100/ipw2200 drivers, remove libipw_change_mtu - set min/max_mtu in p80211netdev, remove wlan_change_mtu - set min/max_mtu in net/mac80211/iface.c and remove ieee80211_change_mtu - set min/max_mtu in wimax/i2400m and remove i2400m_change_mtu - set min/max_mtu in intersil/hostap and remove prism2_change_mtu - set min/max_mtu in intersil/orinoco - set min/max_mtu in tty/n_gsm and remove gsm_change_mtu CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: Maya Erez CC: Simon Kelley CC: Stanislav Yakovlev CC: Johannes Berg CC: Inaky Perez-Gonzalez Signed-off-by: Jarod Wilson Acked-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/netdev.c | 22 ++-------------------- drivers/net/wireless/ath/wil6210/netdev.c | 17 +---------------- drivers/net/wireless/atmel/atmel.c | 13 ++++--------- drivers/net/wireless/cisco/airo.c | 14 +++----------- drivers/net/wireless/intel/ipw2x00/ipw2100.c | 3 ++- drivers/net/wireless/intel/ipw2x00/ipw2200.c | 8 ++++++-- drivers/net/wireless/intel/ipw2x00/libipw.h | 1 - drivers/net/wireless/intel/ipw2x00/libipw_module.c | 9 --------- drivers/net/wireless/intersil/hostap/hostap_main.c | 15 ++------------- drivers/net/wireless/intersil/orinoco/main.c | 6 +++--- drivers/staging/wlan-ng/p80211netdev.c | 18 +++++------------- drivers/tty/n_gsm.c | 12 ++---------- net/mac80211/iface.c | 15 ++++----------- 13 files changed, 34 insertions(+), 119 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index bb74f4b9a02f..7f64e74d746b 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -394,25 +394,6 @@ drop: } -static -int i2400m_change_mtu(struct net_device *net_dev, int new_mtu) -{ - int result; - struct i2400m *i2400m = net_dev_to_i2400m(net_dev); - struct device *dev = i2400m_dev(i2400m); - - if (new_mtu >= I2400M_MAX_MTU) { - dev_err(dev, "Cannot change MTU to %d (max is %d)\n", - new_mtu, I2400M_MAX_MTU); - result = -EINVAL; - } else { - net_dev->mtu = new_mtu; - result = 0; - } - return result; -} - - static void i2400m_tx_timeout(struct net_device *net_dev) { @@ -590,7 +571,6 @@ static const struct net_device_ops i2400m_netdev_ops = { .ndo_stop = i2400m_stop, .ndo_start_xmit = i2400m_hard_start_xmit, .ndo_tx_timeout = i2400m_tx_timeout, - .ndo_change_mtu = i2400m_change_mtu, }; static void i2400m_get_drvinfo(struct net_device *net_dev, @@ -621,6 +601,8 @@ void i2400m_netdev_setup(struct net_device *net_dev) d_fnstart(3, NULL, "(net_dev %p)\n", net_dev); ether_setup(net_dev); net_dev->mtu = I2400M_MAX_MTU; + net_dev->min_mtu = 0; + net_dev->max_mtu = I2400M_MAX_MTU; net_dev->tx_queue_len = I2400M_TX_QLEN; net_dev->features = NETIF_F_VLAN_CHALLENGED diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 61de5e9f8ef0..d18372cdc8ca 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -41,21 +41,6 @@ static int wil_stop(struct net_device *ndev) return wil_down(wil); } -static int wil_change_mtu(struct net_device *ndev, int new_mtu) -{ - struct wil6210_priv *wil = ndev_to_wil(ndev); - - if (new_mtu < 68 || new_mtu > mtu_max) { - wil_err(wil, "invalid MTU %d\n", new_mtu); - return -EINVAL; - } - - wil_dbg_misc(wil, "change MTU %d -> %d\n", ndev->mtu, new_mtu); - ndev->mtu = new_mtu; - - return 0; -} - static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) { struct wil6210_priv *wil = ndev_to_wil(ndev); @@ -69,7 +54,6 @@ static const struct net_device_ops wil_netdev_ops = { .ndo_start_xmit = wil_start_xmit, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = wil_change_mtu, .ndo_do_ioctl = wil_do_ioctl, }; @@ -126,6 +110,7 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) static void wil_dev_setup(struct net_device *dev) { ether_setup(dev); + dev->max_mtu = mtu_max; dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; } diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c index bf2e9a083c0c..eb92d5ab7a27 100644 --- a/drivers/net/wireless/atmel/atmel.c +++ b/drivers/net/wireless/atmel/atmel.c @@ -1295,14 +1295,6 @@ static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev) return &priv->wstats; } -static int atmel_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 2312)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static int atmel_set_mac_address(struct net_device *dev, void *p) { struct sockaddr *addr = p; @@ -1506,7 +1498,6 @@ static const struct file_operations atmel_proc_fops = { static const struct net_device_ops atmel_netdev_ops = { .ndo_open = atmel_open, .ndo_stop = atmel_close, - .ndo_change_mtu = atmel_change_mtu, .ndo_set_mac_address = atmel_set_mac_address, .ndo_start_xmit = start_tx, .ndo_do_ioctl = atmel_ioctl, @@ -1600,6 +1591,10 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, dev->irq = irq; dev->base_addr = port; + /* MTU range: 68 - 2312 */ + dev->min_mtu = 68; + dev->max_mtu = MAX_WIRELESS_BODY - ETH_FCS_LEN; + SET_NETDEV_DEV(dev, sys_dev); if ((rc = request_irq(dev->irq, service_interrupt, IRQF_SHARED, dev->name, dev))) { diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index 69b826d229c5..4b040451a9b8 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -2329,14 +2329,6 @@ static int airo_set_mac_address(struct net_device *dev, void *p) return 0; } -static int airo_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 2400)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static LIST_HEAD(airo_devices); static void add_airo_dev(struct airo_info *ai) @@ -2656,7 +2648,6 @@ static const struct net_device_ops airo11_netdev_ops = { .ndo_get_stats = airo_get_stats, .ndo_set_mac_address = airo_set_mac_address, .ndo_do_ioctl = airo_ioctl, - .ndo_change_mtu = airo_change_mtu, }; static void wifi_setup(struct net_device *dev) @@ -2668,6 +2659,8 @@ static void wifi_setup(struct net_device *dev) dev->type = ARPHRD_IEEE80211; dev->hard_header_len = ETH_HLEN; dev->mtu = AIRO_DEF_MTU; + dev->min_mtu = 68; + dev->max_mtu = MIC_MSGLEN_MAX; dev->addr_len = ETH_ALEN; dev->tx_queue_len = 100; @@ -2754,7 +2747,6 @@ static const struct net_device_ops airo_netdev_ops = { .ndo_set_rx_mode = airo_set_multicast_list, .ndo_set_mac_address = airo_set_mac_address, .ndo_do_ioctl = airo_ioctl, - .ndo_change_mtu = airo_change_mtu, .ndo_validate_addr = eth_validate_addr, }; @@ -2766,7 +2758,6 @@ static const struct net_device_ops mpi_netdev_ops = { .ndo_set_rx_mode = airo_set_multicast_list, .ndo_set_mac_address = airo_set_mac_address, .ndo_do_ioctl = airo_ioctl, - .ndo_change_mtu = airo_change_mtu, .ndo_validate_addr = eth_validate_addr, }; @@ -2822,6 +2813,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, dev->irq = irq; dev->base_addr = port; dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->max_mtu = MIC_MSGLEN_MAX; SET_NETDEV_DEV(dev, dmdev); diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index bfa542c8d6f1..64176090b196 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -6035,7 +6035,6 @@ static const struct net_device_ops ipw2100_netdev_ops = { .ndo_open = ipw2100_open, .ndo_stop = ipw2100_close, .ndo_start_xmit = libipw_xmit, - .ndo_change_mtu = libipw_change_mtu, .ndo_tx_timeout = ipw2100_tx_timeout, .ndo_set_mac_address = ipw2100_set_address, .ndo_validate_addr = eth_validate_addr, @@ -6071,6 +6070,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, dev->wireless_data = &priv->wireless_data; dev->watchdog_timeo = 3 * HZ; dev->irq = 0; + dev->min_mtu = 68; + dev->max_mtu = LIBIPW_DATA_LEN; /* NOTE: We don't use the wireless_handlers hook * in dev as the system will start throwing WX requests diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c index bfd68612a535..ef9af8a29cad 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -11561,7 +11561,6 @@ static const struct net_device_ops ipw_prom_netdev_ops = { .ndo_open = ipw_prom_open, .ndo_stop = ipw_prom_stop, .ndo_start_xmit = ipw_prom_hard_start_xmit, - .ndo_change_mtu = libipw_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; @@ -11587,6 +11586,9 @@ static int ipw_prom_alloc(struct ipw_priv *priv) priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops; + priv->prom_net_dev->min_mtu = 68; + priv->prom_net_dev->max_mtu = LIBIPW_DATA_LEN; + priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR; SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev); @@ -11619,7 +11621,6 @@ static const struct net_device_ops ipw_netdev_ops = { .ndo_set_rx_mode = ipw_net_set_multicast_list, .ndo_set_mac_address = ipw_net_set_mac_address, .ndo_start_xmit = libipw_xmit, - .ndo_change_mtu = libipw_change_mtu, .ndo_validate_addr = eth_validate_addr, }; @@ -11729,6 +11730,9 @@ static int ipw_pci_probe(struct pci_dev *pdev, net_dev->wireless_handlers = &ipw_wx_handler_def; net_dev->ethtool_ops = &ipw_ethtool_ops; + net_dev->min_mtu = 68; + net_dev->max_mtu = LIBIPW_DATA_LEN; + err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group); if (err) { IPW_ERROR("failed to create sysfs device attributes\n"); diff --git a/drivers/net/wireless/intel/ipw2x00/libipw.h b/drivers/net/wireless/intel/ipw2x00/libipw.h index b0571618c2ed..b51355134e04 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw.h +++ b/drivers/net/wireless/intel/ipw2x00/libipw.h @@ -948,7 +948,6 @@ static inline int libipw_is_cck_rate(u8 rate) /* libipw.c */ void free_libipw(struct net_device *dev, int monitor); struct net_device *alloc_libipw(int sizeof_priv, int monitor); -int libipw_change_mtu(struct net_device *dev, int new_mtu); void libipw_networks_age(struct libipw_device *ieee, unsigned long age_secs); diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_module.c b/drivers/net/wireless/intel/ipw2x00/libipw_module.c index 60f28740f6af..2332075565f2 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_module.c @@ -118,15 +118,6 @@ static void libipw_networks_initialize(struct libipw_device *ieee) &ieee->network_free_list); } -int libipw_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} -EXPORT_SYMBOL(libipw_change_mtu); - struct net_device *alloc_libipw(int sizeof_priv, int monitor) { struct libipw_device *ieee; diff --git a/drivers/net/wireless/intersil/hostap/hostap_main.c b/drivers/net/wireless/intersil/hostap/hostap_main.c index 80d4228ba754..1a16b8cb366e 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_main.c +++ b/drivers/net/wireless/intersil/hostap/hostap_main.c @@ -765,16 +765,6 @@ static void hostap_set_multicast_list(struct net_device *dev) } -static int prism2_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - - static void prism2_tx_timeout(struct net_device *dev) { struct hostap_interface *iface; @@ -813,7 +803,6 @@ static const struct net_device_ops hostap_netdev_ops = { .ndo_do_ioctl = hostap_ioctl, .ndo_set_mac_address = prism2_set_mac_address, .ndo_set_rx_mode = hostap_set_multicast_list, - .ndo_change_mtu = prism2_change_mtu, .ndo_tx_timeout = prism2_tx_timeout, .ndo_validate_addr = eth_validate_addr, }; @@ -826,7 +815,6 @@ static const struct net_device_ops hostap_mgmt_netdev_ops = { .ndo_do_ioctl = hostap_ioctl, .ndo_set_mac_address = prism2_set_mac_address, .ndo_set_rx_mode = hostap_set_multicast_list, - .ndo_change_mtu = prism2_change_mtu, .ndo_tx_timeout = prism2_tx_timeout, .ndo_validate_addr = eth_validate_addr, }; @@ -839,7 +827,6 @@ static const struct net_device_ops hostap_master_ops = { .ndo_do_ioctl = hostap_ioctl, .ndo_set_mac_address = prism2_set_mac_address, .ndo_set_rx_mode = hostap_set_multicast_list, - .ndo_change_mtu = prism2_change_mtu, .ndo_tx_timeout = prism2_tx_timeout, .ndo_validate_addr = eth_validate_addr, }; @@ -851,6 +838,8 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local, iface = netdev_priv(dev); ether_setup(dev); + dev->min_mtu = PRISM2_MIN_MTU; + dev->max_mtu = PRISM2_MAX_MTU; dev->priv_flags &= ~IFF_TX_SKB_SHARING; /* kernel callbacks */ diff --git a/drivers/net/wireless/intersil/orinoco/main.c b/drivers/net/wireless/intersil/orinoco/main.c index 7afe2004e930..9d96b7c928f7 100644 --- a/drivers/net/wireless/intersil/orinoco/main.c +++ b/drivers/net/wireless/intersil/orinoco/main.c @@ -322,9 +322,6 @@ int orinoco_change_mtu(struct net_device *dev, int new_mtu) { struct orinoco_private *priv = ndev_priv(dev); - if ((new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU)) - return -EINVAL; - /* MTU + encapsulation + header length */ if ((new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) > (priv->nicbuf_size - ETH_HLEN)) @@ -2288,6 +2285,9 @@ int orinoco_if_add(struct orinoco_private *priv, dev->base_addr = base_addr; dev->irq = irq; + dev->min_mtu = ORINOCO_MIN_MTU; + dev->max_mtu = ORINOCO_MAX_MTU; + SET_NETDEV_DEV(dev, priv->dev); ret = register_netdev(dev); if (ret) diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 825a63a7c0e3..4762d38a720e 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -669,18 +669,6 @@ static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr) return result; } -static int wlan_change_mtu(struct net_device *dev, int new_mtu) -{ - /* 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap) - and another 8 for wep. */ - if ((new_mtu < 68) || (new_mtu > (2312 - 20 - 8))) - return -EINVAL; - - dev->mtu = new_mtu; - - return 0; -} - static const struct net_device_ops p80211_netdev_ops = { .ndo_init = p80211knetdev_init, .ndo_open = p80211knetdev_open, @@ -690,7 +678,6 @@ static const struct net_device_ops p80211_netdev_ops = { .ndo_do_ioctl = p80211knetdev_do_ioctl, .ndo_set_mac_address = p80211knetdev_set_mac_address, .ndo_tx_timeout = p80211knetdev_tx_timeout, - .ndo_change_mtu = wlan_change_mtu, .ndo_validate_addr = eth_validate_addr, }; @@ -756,6 +743,11 @@ int wlan_setup(struct wlandevice *wlandev, struct device *physdev) wdev->wiphy = wiphy; wdev->iftype = NL80211_IFTYPE_STATION; netdev->ieee80211_ptr = wdev; + netdev->min_mtu = 68; + /* 2312 is max 802.11 payload, 20 is overhead, + * (ether + llc + snap) and another 8 for wep. + */ + netdev->max_mtu = (2312 - 20 - 8); netif_stop_queue(netdev); netif_carrier_off(netdev); diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 54cab59e20ed..f3932baed07d 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2711,15 +2711,6 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci, return; } -static int gsm_change_mtu(struct net_device *net, int new_mtu) -{ - struct gsm_mux_net *mux_net = netdev_priv(net); - if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu)) - return -EINVAL; - net->mtu = new_mtu; - return 0; -} - static void gsm_mux_net_init(struct net_device *net) { static const struct net_device_ops gsm_netdev_ops = { @@ -2728,7 +2719,6 @@ static void gsm_mux_net_init(struct net_device *net) .ndo_start_xmit = gsm_mux_net_start_xmit, .ndo_tx_timeout = gsm_mux_net_tx_timeout, .ndo_get_stats = gsm_mux_net_get_stats, - .ndo_change_mtu = gsm_change_mtu, }; net->netdev_ops = &gsm_netdev_ops; @@ -2787,6 +2777,8 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc) return -ENOMEM; } net->mtu = dlci->gsm->mtu; + net->min_mtu = 8; + net->max_mtu = dlci->gsm->mtu; mux_net = netdev_priv(net); mux_net->dlci = dlci; kref_init(&mux_net->ref); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 638ec0759078..73e6a8fd2845 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -150,15 +150,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) ieee80211_hw_config(local, change); } -static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr, bool check_dup) { @@ -1166,7 +1157,6 @@ static const struct net_device_ops ieee80211_dataif_ops = { .ndo_uninit = ieee80211_uninit, .ndo_start_xmit = ieee80211_subif_start_xmit, .ndo_set_rx_mode = ieee80211_set_multicast_list, - .ndo_change_mtu = ieee80211_change_mtu, .ndo_set_mac_address = ieee80211_change_mac, .ndo_select_queue = ieee80211_netdev_select_queue, .ndo_get_stats64 = ieee80211_get_stats64, @@ -1200,7 +1190,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = { .ndo_uninit = ieee80211_uninit, .ndo_start_xmit = ieee80211_monitor_start_xmit, .ndo_set_rx_mode = ieee80211_set_multicast_list, - .ndo_change_mtu = ieee80211_change_mtu, .ndo_set_mac_address = ieee80211_change_mac, .ndo_select_queue = ieee80211_monitor_select_queue, .ndo_get_stats64 = ieee80211_get_stats64, @@ -1884,6 +1873,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops); + /* MTU range: 256 - 2304 */ + ndev->min_mtu = 256; + ndev->max_mtu = IEEE80211_MAX_DATA_LEN; + ret = register_netdevice(ndev); if (ret) { ieee80211_if_free(ndev); -- cgit v1.2.3 From 8b6b4135e4fb2b537f33b811c13f77bee25ca8d3 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 20 Oct 2016 13:55:19 -0400 Subject: net: use core MTU range checking in WAN drivers - set min/max_mtu in all hdlc drivers, remove hdlc_change_mtu - sent max_mtu in lec driver, remove lec_change_mtu - set min/max_mtu in x25_asy driver CC: netdev@vger.kernel.org CC: Krzysztof Halasa CC: Krzysztof Halasa CC: Jan "Yenya" Kasprzak CC: Francois Romieu CC: Kevin Curtis CC: Zhao Qiang Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/char/pcmcia/synclink_cs.c | 1 - drivers/net/wan/c101.c | 1 - drivers/net/wan/cosa.c | 1 - drivers/net/wan/dscc4.c | 1 - drivers/net/wan/farsync.c | 1 - drivers/net/wan/fsl_ucc_hdlc.c | 1 - drivers/net/wan/hdlc.c | 11 ++--------- drivers/net/wan/hdlc_fr.c | 3 ++- drivers/net/wan/hostess_sv11.c | 1 - drivers/net/wan/ixp4xx_hss.c | 1 - drivers/net/wan/lmc/lmc_main.c | 1 - drivers/net/wan/n2.c | 1 - drivers/net/wan/pc300too.c | 1 - drivers/net/wan/pci200syn.c | 1 - drivers/net/wan/sealevel.c | 1 - drivers/net/wan/wanxl.c | 1 - drivers/net/wan/x25_asy.c | 5 ++--- drivers/tty/synclink.c | 1 - drivers/tty/synclink_gt.c | 1 - drivers/tty/synclinkmp.c | 1 - include/linux/hdlc.h | 2 -- net/atm/lec.c | 11 +---------- 22 files changed, 7 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index d28922df01d7..a7dd5f4f2c5a 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -4248,7 +4248,6 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size) static const struct net_device_ops hdlcdev_ops = { .ndo_open = hdlcdev_open, .ndo_stop = hdlcdev_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = hdlcdev_ioctl, .ndo_tx_timeout = hdlcdev_tx_timeout, diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index 09a50751763b..2371e078afbb 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -302,7 +302,6 @@ static void c101_destroy_card(card_t *card) static const struct net_device_ops c101_ops = { .ndo_open = c101_open, .ndo_stop = c101_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = c101_ioctl, }; diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index b87fe0a01c69..087eb266601f 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -432,7 +432,6 @@ module_exit(cosa_exit); static const struct net_device_ops cosa_ops = { .ndo_open = cosa_net_open, .ndo_stop = cosa_net_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = cosa_net_ioctl, .ndo_tx_timeout = cosa_net_timeout, diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 629225980463..7351e5440ed7 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -887,7 +887,6 @@ static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz) static const struct net_device_ops dscc4_ops = { .ndo_open = dscc4_open, .ndo_stop = dscc4_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = dscc4_ioctl, .ndo_tx_timeout = dscc4_tx_timeout, diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 3c9cbf908ec7..03696d35ee9c 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -2394,7 +2394,6 @@ fst_init_card(struct fst_card_info *card) static const struct net_device_ops fst_ops = { .ndo_open = fst_open, .ndo_stop = fst_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = fst_ioctl, .ndo_tx_timeout = fst_tx_timeout, diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 65647533b401..e38ce4da3efb 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -992,7 +992,6 @@ static const struct dev_pm_ops uhdlc_pm_ops = { static const struct net_device_ops uhdlc_ops = { .ndo_open = uhdlc_open, .ndo_stop = uhdlc_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = uhdlc_ioctl, }; diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index 9bd4aa8083ce..7221a53b8b14 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -46,14 +46,6 @@ static const char* version = "HDLC support module revision 1.22"; static struct hdlc_proto *first_proto; -int hdlc_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) { @@ -237,6 +229,8 @@ static void hdlc_setup_dev(struct net_device *dev) dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->priv_flags = IFF_WAN_HDLC; dev->mtu = HDLC_MAX_MTU; + dev->min_mtu = 68; + dev->max_mtu = HDLC_MAX_MTU; dev->type = ARPHRD_RAWHDLC; dev->hard_header_len = 16; dev->addr_len = 0; @@ -353,7 +347,6 @@ MODULE_AUTHOR("Krzysztof Halasa "); MODULE_DESCRIPTION("HDLC support module"); MODULE_LICENSE("GPL v2"); -EXPORT_SYMBOL(hdlc_change_mtu); EXPORT_SYMBOL(hdlc_start_xmit); EXPORT_SYMBOL(hdlc_open); EXPORT_SYMBOL(hdlc_close); diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index b6e0cfb095d3..eb915281197e 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1053,7 +1053,6 @@ static void pvc_setup(struct net_device *dev) static const struct net_device_ops pvc_ops = { .ndo_open = pvc_open, .ndo_stop = pvc_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = pvc_xmit, .ndo_do_ioctl = pvc_ioctl, }; @@ -1096,6 +1095,8 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) } dev->netdev_ops = &pvc_ops; dev->mtu = HDLC_MAX_MTU; + dev->min_mtu = 68; + dev->max_mtu = HDLC_MAX_MTU; dev->priv_flags |= IFF_NO_QUEUE; dev->ml_priv = pvc; diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c index 3d741663fd67..dd6bb3364ad2 100644 --- a/drivers/net/wan/hostess_sv11.c +++ b/drivers/net/wan/hostess_sv11.c @@ -180,7 +180,6 @@ static int hostess_attach(struct net_device *dev, unsigned short encoding, static const struct net_device_ops hostess_ops = { .ndo_open = hostess_open, .ndo_stop = hostess_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = hostess_ioctl, }; diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index e7bbdb7af53a..6a505c26a3e7 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -1321,7 +1321,6 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static const struct net_device_ops hss_hdlc_ops = { .ndo_open = hss_hdlc_open, .ndo_stop = hss_hdlc_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = hss_hdlc_ioctl, }; diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 299140c04556..001b7796740d 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -808,7 +808,6 @@ static int lmc_attach(struct net_device *dev, unsigned short encoding, static const struct net_device_ops lmc_ops = { .ndo_open = lmc_open, .ndo_stop = lmc_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = lmc_ioctl, .ndo_tx_timeout = lmc_driver_timeout, diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index 315bf09d6a20..c8f4517db3a0 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -330,7 +330,6 @@ static void n2_destroy_card(card_t *card) static const struct net_device_ops n2_ops = { .ndo_open = n2_open, .ndo_stop = n2_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = n2_ioctl, }; diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index db363856e0b5..e1dd1ec18d64 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -291,7 +291,6 @@ static void pc300_pci_remove_one(struct pci_dev *pdev) static const struct net_device_ops pc300_ops = { .ndo_open = pc300_open, .ndo_stop = pc300_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = pc300_ioctl, }; diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index e8455621390e..4e437c599e9a 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -270,7 +270,6 @@ static void pci200_pci_remove_one(struct pci_dev *pdev) static const struct net_device_ops pci200_ops = { .ndo_open = pci200_open, .ndo_stop = pci200_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = pci200_ioctl, }; diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c index 27860b4f5908..fbb5aa2c4d8f 100644 --- a/drivers/net/wan/sealevel.c +++ b/drivers/net/wan/sealevel.c @@ -174,7 +174,6 @@ static int sealevel_attach(struct net_device *dev, unsigned short encoding, static const struct net_device_ops sealevel_ops = { .ndo_open = sealevel_open, .ndo_stop = sealevel_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = sealevel_ioctl, }; diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index a20d688d2595..0c7317520ed3 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -551,7 +551,6 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) static const struct net_device_ops wanxl_ops = { .ndo_open = wanxl_open, .ndo_stop = wanxl_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = wanxl_ioctl, .ndo_get_stats = wanxl_get_stats, diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 1bc5e93d2a34..878b05d06fc7 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -124,9 +124,6 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu) unsigned char *xbuff, *rbuff; int len; - if (newmtu > 65534) - return -EINVAL; - len = 2 * newmtu; xbuff = kmalloc(len + 4, GFP_ATOMIC); rbuff = kmalloc(len + 4, GFP_ATOMIC); @@ -751,6 +748,8 @@ static void x25_asy_setup(struct net_device *dev) */ dev->mtu = SL_MTU; + dev->min_mtu = 0; + dev->max_mtu = 65534; dev->netdev_ops = &x25_asy_netdev_ops; dev->watchdog_timeo = HZ*20; dev->hard_header_len = 0; diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index c13e27ecb0b7..415885c56435 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -7973,7 +7973,6 @@ static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size) static const struct net_device_ops hdlcdev_ops = { .ndo_open = hdlcdev_open, .ndo_stop = hdlcdev_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = hdlcdev_ioctl, .ndo_tx_timeout = hdlcdev_tx_timeout, diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 7aca2d4670e4..8267bcf2405e 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -1768,7 +1768,6 @@ static void hdlcdev_rx(struct slgt_info *info, char *buf, int size) static const struct net_device_ops hdlcdev_ops = { .ndo_open = hdlcdev_open, .ndo_stop = hdlcdev_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = hdlcdev_ioctl, .ndo_tx_timeout = hdlcdev_tx_timeout, diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index dec156586de1..d66620f7eaa3 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -1887,7 +1887,6 @@ static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size) static const struct net_device_ops hdlcdev_ops = { .ndo_open = hdlcdev_open, .ndo_stop = hdlcdev_close, - .ndo_change_mtu = hdlc_change_mtu, .ndo_start_xmit = hdlc_start_xmit, .ndo_do_ioctl = hdlcdev_ioctl, .ndo_tx_timeout = hdlcdev_tx_timeout, diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h index e31bcd4c7859..97585d9679f3 100644 --- a/include/linux/hdlc.h +++ b/include/linux/hdlc.h @@ -93,8 +93,6 @@ static __inline__ void debug_frame(const struct sk_buff *skb) int hdlc_open(struct net_device *dev); /* Must be called by hardware driver when HDLC device is being closed */ void hdlc_close(struct net_device *dev); -/* May be used by hardware driver */ -int hdlc_change_mtu(struct net_device *dev, int new_mtu); /* Must be pointed to by hw driver's dev->netdev_ops->ndo_start_xmit */ netdev_tx_t hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev); diff --git a/net/atm/lec.c b/net/atm/lec.c index 5d2693826afb..779b3fa6052d 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -544,15 +544,6 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, return 0; } -/* shamelessly stolen from drivers/net/net_init.c */ -static int lec_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 18190)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static void lec_set_multicast_list(struct net_device *dev) { /* @@ -565,7 +556,6 @@ static const struct net_device_ops lec_netdev_ops = { .ndo_open = lec_open, .ndo_stop = lec_close, .ndo_start_xmit = lec_start_xmit, - .ndo_change_mtu = lec_change_mtu, .ndo_tx_timeout = lec_tx_timeout, .ndo_set_rx_mode = lec_set_multicast_list, }; @@ -742,6 +732,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) if (!dev_lec[i]) return -ENOMEM; dev_lec[i]->netdev_ops = &lec_netdev_ops; + dev_lec[i]->max_mtu = 18190; snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i); if (register_netdev(dev_lec[i])) { free_netdev(dev_lec[i]); -- cgit v1.2.3 From 91572088e3fdbf4fe31cf397926d8b890fdb3237 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 20 Oct 2016 13:55:20 -0400 Subject: net: use core MTU range checking in core net infra geneve: - Merge __geneve_change_mtu back into geneve_change_mtu, set max_mtu - This one isn't quite as straight-forward as others, could use some closer inspection and testing macvlan: - set min/max_mtu tun: - set min/max_mtu, remove tun_net_change_mtu vxlan: - Merge __vxlan_change_mtu back into vxlan_change_mtu - Set max_mtu to IP_MAX_MTU and retain dynamic MTU range checks in change_mtu function - This one is also not as straight-forward and could use closer inspection and testing from vxlan folks bridge: - set max_mtu of IP_MAX_MTU and retain dynamic MTU range checks in change_mtu function openvswitch: - set min/max_mtu, remove internal_dev_change_mtu - note: max_mtu wasn't checked previously, it's been set to 65535, which is the largest possible size supported sch_teql: - set min/max_mtu (note: max_mtu previously unchecked, used max of 65535) macsec: - min_mtu = 0, max_mtu = 65535 macvlan: - min_mtu = 0, max_mtu = 65535 ntb_netdev: - min_mtu = 0, max_mtu = 65535 veth: - min_mtu = 68, max_mtu = 65535 8021q: - min_mtu = 0, max_mtu = 65535 CC: netdev@vger.kernel.org CC: Nicolas Dichtel CC: Hannes Frederic Sowa CC: Tom Herbert CC: Daniel Borkmann CC: Alexander Duyck CC: Paolo Abeni CC: Jiri Benc CC: WANG Cong CC: Roopa Prabhu CC: Pravin B Shelar CC: Sabrina Dubroca CC: Patrick McHardy CC: Stephen Hemminger CC: Pravin Shelar CC: Maxim Krasnyansky Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/geneve.c | 48 +++++++++++---------------- drivers/net/macsec.c | 2 ++ drivers/net/macvlan.c | 8 ++++- drivers/net/ntb_netdev.c | 3 ++ drivers/net/tun.c | 20 ++++------- drivers/net/veth.c | 17 ++-------- drivers/net/vxlan.c | 64 +++++++++++++++++++----------------- net/8021q/vlan_dev.c | 3 ++ net/bridge/br_device.c | 3 +- net/openvswitch/vport-internal_dev.c | 10 ------ net/sched/sch_teql.c | 5 ++- 11 files changed, 81 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 3c20e87bb761..752bcaa852e4 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1034,39 +1034,18 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) return geneve_xmit_skb(skb, dev, info); } -static int __geneve_change_mtu(struct net_device *dev, int new_mtu, bool strict) +static int geneve_change_mtu(struct net_device *dev, int new_mtu) { - struct geneve_dev *geneve = netdev_priv(dev); - /* The max_mtu calculation does not take account of GENEVE - * options, to avoid excluding potentially valid - * configurations. + /* Only possible if called internally, ndo_change_mtu path's new_mtu + * is guaranteed to be between dev->min_mtu and dev->max_mtu. */ - int max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - dev->hard_header_len; - - if (geneve->remote.sa.sa_family == AF_INET6) - max_mtu -= sizeof(struct ipv6hdr); - else - max_mtu -= sizeof(struct iphdr); - - if (new_mtu < 68) - return -EINVAL; - - if (new_mtu > max_mtu) { - if (strict) - return -EINVAL; - - new_mtu = max_mtu; - } + if (new_mtu > dev->max_mtu) + new_mtu = dev->max_mtu; dev->mtu = new_mtu; return 0; } -static int geneve_change_mtu(struct net_device *dev, int new_mtu) -{ - return __geneve_change_mtu(dev, new_mtu, true); -} - static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct ip_tunnel_info *info = skb_tunnel_info(skb); @@ -1170,6 +1149,14 @@ static void geneve_setup(struct net_device *dev) dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM; dev->hw_features |= NETIF_F_GSO_SOFTWARE; + /* MTU range: 68 - (something less than 65535) */ + dev->min_mtu = ETH_MIN_MTU; + /* The max_mtu calculation does not take account of GENEVE + * options, to avoid excluding potentially valid + * configurations. This will be further reduced by IPvX hdr size. + */ + dev->max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - dev->hard_header_len; + netif_keep_dst(dev); dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; @@ -1285,10 +1272,13 @@ static int geneve_configure(struct net *net, struct net_device *dev, /* make enough headroom for basic scenario */ encap_len = GENEVE_BASE_HLEN + ETH_HLEN; - if (remote->sa.sa_family == AF_INET) + if (remote->sa.sa_family == AF_INET) { encap_len += sizeof(struct iphdr); - else + dev->max_mtu -= sizeof(struct iphdr); + } else { encap_len += sizeof(struct ipv6hdr); + dev->max_mtu -= sizeof(struct ipv6hdr); + } dev->needed_headroom = encap_len + ETH_HLEN; if (metadata) { @@ -1488,7 +1478,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, /* openvswitch users expect packet sizes to be unrestricted, * so set the largest MTU we can. */ - err = __geneve_change_mtu(dev, IP_MAX_MTU, false); + err = geneve_change_mtu(dev, IP_MAX_MTU); if (err) goto err; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 3ea47f28e143..1a134cb2d52c 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2970,6 +2970,8 @@ static void macsec_free_netdev(struct net_device *dev) static void macsec_setup(struct net_device *dev) { ether_setup(dev); + dev->min_mtu = 0; + dev->max_mtu = ETH_MAX_MTU; dev->priv_flags |= IFF_NO_QUEUE; dev->netdev_ops = &macsec_netdev_ops; dev->destructor = macsec_free_netdev; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 3234fcdea317..a0644158647a 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -777,7 +777,7 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu) { struct macvlan_dev *vlan = netdev_priv(dev); - if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu) + if (vlan->lowerdev->mtu < new_mtu) return -EINVAL; dev->mtu = new_mtu; return 0; @@ -1085,6 +1085,8 @@ void macvlan_common_setup(struct net_device *dev) { ether_setup(dev); + dev->min_mtu = 0; + dev->max_mtu = ETH_MAX_MTU; dev->priv_flags &= ~IFF_TX_SKB_SHARING; netif_keep_dst(dev); dev->priv_flags |= IFF_UNICAST_FLT; @@ -1297,6 +1299,10 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, else if (dev->mtu > lowerdev->mtu) return -EINVAL; + /* MTU range: 68 - lowerdev->max_mtu */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = lowerdev->max_mtu; + if (!tb[IFLA_ADDRESS]) eth_hw_addr_random(dev); diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index a9acf7156855..36877ba65516 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -433,6 +433,9 @@ static int ntb_netdev_probe(struct device *client_dev) ndev->netdev_ops = &ntb_netdev_ops; ndev->ethtool_ops = &ntb_ethtool_ops; + ndev->min_mtu = 0; + ndev->max_mtu = ETH_MAX_MTU; + dev->qp = ntb_transport_create_queue(ndev, client_dev, &ntb_netdev_handlers); if (!dev->qp) { diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 8093e39ae263..93285687cf13 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -925,18 +925,6 @@ static void tun_net_mclist(struct net_device *dev) */ } -#define MIN_MTU 68 -#define MAX_MTU 65535 - -static int -tun_net_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static netdev_features_t tun_net_fix_features(struct net_device *dev, netdev_features_t features) { @@ -1014,7 +1002,6 @@ static const struct net_device_ops tun_netdev_ops = { .ndo_open = tun_net_open, .ndo_stop = tun_net_close, .ndo_start_xmit = tun_net_xmit, - .ndo_change_mtu = tun_net_change_mtu, .ndo_fix_features = tun_net_fix_features, .ndo_select_queue = tun_select_queue, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1029,7 +1016,6 @@ static const struct net_device_ops tap_netdev_ops = { .ndo_open = tun_net_open, .ndo_stop = tun_net_close, .ndo_start_xmit = tun_net_xmit, - .ndo_change_mtu = tun_net_change_mtu, .ndo_fix_features = tun_net_fix_features, .ndo_set_rx_mode = tun_net_mclist, .ndo_set_mac_address = eth_mac_addr, @@ -1062,6 +1048,9 @@ static void tun_flow_uninit(struct tun_struct *tun) tun_flow_flush(tun); } +#define MIN_MTU 68 +#define MAX_MTU 65535 + /* Initialize net device. */ static void tun_net_init(struct net_device *dev) { @@ -1092,6 +1081,9 @@ static void tun_net_init(struct net_device *dev) break; } + + dev->min_mtu = MIN_MTU; + dev->max_mtu = MAX_MTU - dev->hard_header_len; } /* Character device part */ diff --git a/drivers/net/veth.c b/drivers/net/veth.c index fbc853e64531..0520952aa096 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -23,9 +23,6 @@ #define DRV_NAME "veth" #define DRV_VERSION "1.0" -#define MIN_MTU 68 /* Min L3 MTU */ -#define MAX_MTU 65535 /* Max L3 MTU (arbitrary) */ - struct pcpu_vstats { u64 packets; u64 bytes; @@ -216,17 +213,9 @@ static int veth_close(struct net_device *dev) return 0; } -static int is_valid_veth_mtu(int new_mtu) +static int is_valid_veth_mtu(int mtu) { - return new_mtu >= MIN_MTU && new_mtu <= MAX_MTU; -} - -static int veth_change_mtu(struct net_device *dev, int new_mtu) -{ - if (!is_valid_veth_mtu(new_mtu)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; + return mtu >= ETH_MIN_MTU && mtu <= ETH_MAX_MTU; } static int veth_dev_init(struct net_device *dev) @@ -300,7 +289,6 @@ static const struct net_device_ops veth_netdev_ops = { .ndo_open = veth_open, .ndo_stop = veth_close, .ndo_start_xmit = veth_xmit, - .ndo_change_mtu = veth_change_mtu, .ndo_get_stats64 = veth_get_stats64, .ndo_set_rx_mode = veth_set_multicast_list, .ndo_set_mac_address = eth_mac_addr, @@ -337,6 +325,7 @@ static void veth_setup(struct net_device *dev) NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX); dev->destructor = veth_dev_free; + dev->max_mtu = ETH_MAX_MTU; dev->hw_features = VETH_FEATURES; dev->hw_enc_features = VETH_FEATURES; diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index e7d16687538b..c0170b6956bb 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2367,43 +2367,31 @@ static void vxlan_set_multicast_list(struct net_device *dev) { } -static int __vxlan_change_mtu(struct net_device *dev, - struct net_device *lowerdev, - struct vxlan_rdst *dst, int new_mtu, bool strict) +static int vxlan_change_mtu(struct net_device *dev, int new_mtu) { - int max_mtu = IP_MAX_MTU; - - if (lowerdev) - max_mtu = lowerdev->mtu; + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_rdst *dst = &vxlan->default_dst; + struct net_device *lowerdev = __dev_get_by_index(vxlan->net, + dst->remote_ifindex); + bool use_ipv6 = false; if (dst->remote_ip.sa.sa_family == AF_INET6) - max_mtu -= VXLAN6_HEADROOM; - else - max_mtu -= VXLAN_HEADROOM; - - if (new_mtu < 68) - return -EINVAL; + use_ipv6 = true; - if (new_mtu > max_mtu) { - if (strict) + /* This check is different than dev->max_mtu, because it looks at + * the lowerdev->mtu, rather than the static dev->max_mtu + */ + if (lowerdev) { + int max_mtu = lowerdev->mtu - + (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); + if (new_mtu > max_mtu) return -EINVAL; - - new_mtu = max_mtu; } dev->mtu = new_mtu; return 0; } -static int vxlan_change_mtu(struct net_device *dev, int new_mtu) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_rdst *dst = &vxlan->default_dst; - struct net_device *lowerdev = __dev_get_by_index(vxlan->net, - dst->remote_ifindex); - return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true); -} - static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct vxlan_dev *vxlan = netdev_priv(dev); @@ -2795,6 +2783,10 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, vxlan_ether_setup(dev); } + /* MTU range: 68 - 65535 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = ETH_MAX_MTU; + vxlan->net = src_net; dst->remote_vni = conf->vni; @@ -2838,7 +2830,8 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, #endif if (!conf->mtu) - dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); + dev->mtu = lowerdev->mtu - + (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); needed_headroom = lowerdev->hard_header_len; } else if (vxlan_addr_multicast(&dst->remote_ip)) { @@ -2847,9 +2840,20 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, } if (conf->mtu) { - err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false); - if (err) - return err; + int max_mtu = ETH_MAX_MTU; + + if (lowerdev) + max_mtu = lowerdev->mtu; + + max_mtu -= (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); + + if (conf->mtu < dev->min_mtu || conf->mtu > dev->max_mtu) + return -EINVAL; + + dev->mtu = conf->mtu; + + if (conf->mtu > max_mtu) + dev->mtu = max_mtu; } if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index fbfacd51aa34..10da6c588bf8 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -826,5 +826,8 @@ void vlan_setup(struct net_device *dev) dev->destructor = vlan_dev_free; dev->ethtool_ops = &vlan_ethtool_ops; + dev->min_mtu = 0; + dev->max_mtu = ETH_MAX_MTU; + eth_zero_addr(dev->broadcast); } diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 89a687f3c0a3..c08e02b67818 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -185,7 +185,7 @@ static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev, static int br_change_mtu(struct net_device *dev, int new_mtu) { struct net_bridge *br = netdev_priv(dev); - if (new_mtu < 68 || new_mtu > br_min_mtu(br)) + if (new_mtu > br_min_mtu(br)) return -EINVAL; dev->mtu = new_mtu; @@ -410,6 +410,7 @@ void br_dev_setup(struct net_device *dev) br->bridge_hello_time = br->hello_time = 2 * HZ; br->bridge_forward_delay = br->forward_delay = 15 * HZ; br->ageing_time = BR_DEFAULT_AGEING_TIME; + dev->max_mtu = ETH_MAX_MTU; br_netfilter_rtable_init(br); br_stp_timer_init(br); diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index e7da29021b38..d5d6caecd072 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -89,15 +89,6 @@ static const struct ethtool_ops internal_dev_ethtool_ops = { .get_link = ethtool_op_get_link, }; -static int internal_dev_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < 68) - return -EINVAL; - - netdev->mtu = new_mtu; - return 0; -} - static void internal_dev_destructor(struct net_device *dev) { struct vport *vport = ovs_internal_dev_get_vport(dev); @@ -148,7 +139,6 @@ static const struct net_device_ops internal_dev_netdev_ops = { .ndo_stop = internal_dev_stop, .ndo_start_xmit = internal_dev_xmit, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = internal_dev_change_mtu, .ndo_get_stats64 = internal_get_stats, .ndo_set_rx_headroom = internal_set_rx_headroom, }; diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 2cd9b4478b92..b0196366d58d 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -418,9 +418,6 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu) struct teql_master *m = netdev_priv(dev); struct Qdisc *q; - if (new_mtu < 68) - return -EINVAL; - q = m->slaves; if (q) { do { @@ -460,6 +457,8 @@ static __init void teql_master_setup(struct net_device *dev) dev->netdev_ops = &teql_netdev_ops; dev->type = ARPHRD_VOID; dev->mtu = 1500; + dev->min_mtu = 68; + dev->max_mtu = 65535; dev->tx_queue_len = 100; dev->flags = IFF_NOARP; dev->hard_header_len = LL_MAX_HEADER; -- cgit v1.2.3 From d0c2c9973ecd267307543526ae93855e3a3e4b23 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 20 Oct 2016 13:55:21 -0400 Subject: net: use core MTU range checking in virt drivers hyperv_net: - set min/max_mtu, per Haiyang, after rndis_filter_device_add virtio_net: - set min/max_mtu - remove virtnet_change_mtu vmxnet3: - set min/max_mtu xen-netback: - min_mtu = 0, max_mtu = 65517 xen-netfront: - min_mtu = 0, max_mtu = 65535 unisys/visor: - clean up defines a little to not clash with network core or add redundat definitions CC: netdev@vger.kernel.org CC: virtualization@lists.linux-foundation.org CC: "K. Y. Srinivasan" CC: Haiyang Zhang CC: "Michael S. Tsirkin" CC: Shrikrishna Khare CC: "VMware, Inc." CC: Wei Liu CC: Paul Durrant CC: David Kershner Signed-off-by: Jarod Wilson Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 4 ++-- drivers/net/hyperv/netvsc_drv.c | 14 +++++++------- drivers/net/virtio_net.c | 23 ++++++++++------------- drivers/net/vmxnet3/vmxnet3_drv.c | 7 ++++--- drivers/net/xen-netback/interface.c | 5 ++++- drivers/net/xen-netfront.c | 2 ++ drivers/staging/unisys/include/iochannel.h | 10 ++++------ drivers/staging/unisys/visornic/visornic_main.c | 4 ++-- 8 files changed, 35 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index f4fbcb5aa24a..3958adade7eb 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -606,8 +606,8 @@ struct nvsp_message { } __packed; -#define NETVSC_MTU 65536 -#define NETVSC_MTU_MIN 68 +#define NETVSC_MTU 65535 +#define NETVSC_MTU_MIN ETH_MIN_MTU #define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */ #define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */ diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index f0919bd3a563..3b28cf127f9d 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -872,19 +872,12 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) struct netvsc_device *nvdev = ndevctx->nvdev; struct hv_device *hdev = ndevctx->device_ctx; struct netvsc_device_info device_info; - int limit = ETH_DATA_LEN; u32 num_chn; int ret = 0; if (ndevctx->start_remove || !nvdev || nvdev->destroy) return -ENODEV; - if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) - limit = NETVSC_MTU - ETH_HLEN; - - if (mtu < NETVSC_MTU_MIN || mtu > limit) - return -EINVAL; - ret = netvsc_close(ndev); if (ret) goto out; @@ -1402,6 +1395,13 @@ static int netvsc_probe(struct hv_device *dev, netif_set_real_num_tx_queues(net, nvdev->num_chn); netif_set_real_num_rx_queues(net, nvdev->num_chn); + /* MTU range: 68 - 1500 or 65521 */ + net->min_mtu = NETVSC_MTU_MIN; + if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) + net->max_mtu = NETVSC_MTU - ETH_HLEN; + else + net->max_mtu = ETH_DATA_LEN; + ret = register_netdev(net); if (ret != 0) { pr_err("Unable to register netdev.\n"); diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index fad84f3f4109..720809f82a0e 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1419,17 +1419,6 @@ static const struct ethtool_ops virtnet_ethtool_ops = { .set_settings = virtnet_set_settings, }; -#define MIN_MTU 68 -#define MAX_MTU 65535 - -static int virtnet_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < MIN_MTU || new_mtu > MAX_MTU) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static const struct net_device_ops virtnet_netdev = { .ndo_open = virtnet_open, .ndo_stop = virtnet_close, @@ -1437,7 +1426,6 @@ static const struct net_device_ops virtnet_netdev = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = virtnet_set_mac_address, .ndo_set_rx_mode = virtnet_set_rx_mode, - .ndo_change_mtu = virtnet_change_mtu, .ndo_get_stats64 = virtnet_stats, .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid, @@ -1748,6 +1736,9 @@ static bool virtnet_validate_features(struct virtio_device *vdev) return true; } +#define MIN_MTU ETH_MIN_MTU +#define MAX_MTU ETH_MAX_MTU + static int virtnet_probe(struct virtio_device *vdev) { int i, err; @@ -1821,6 +1812,10 @@ static int virtnet_probe(struct virtio_device *vdev) dev->vlan_features = dev->features; + /* MTU range: 68 - 65535 */ + dev->min_mtu = MIN_MTU; + dev->max_mtu = MAX_MTU; + /* Configuration may specify what MAC to use. Otherwise random. */ if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) virtio_cread_bytes(vdev, @@ -1875,8 +1870,10 @@ static int virtnet_probe(struct virtio_device *vdev) mtu = virtio_cread16(vdev, offsetof(struct virtio_net_config, mtu)); - if (virtnet_change_mtu(dev, mtu)) + if (mtu < dev->min_mtu || mtu > dev->max_mtu) __virtio_clear_bit(vdev, VIRTIO_NET_F_MTU); + else + dev->mtu = mtu; } if (vi->any_header_sg) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index b5554f2ebee4..0c36de121eb0 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2969,9 +2969,6 @@ vmxnet3_change_mtu(struct net_device *netdev, int new_mtu) struct vmxnet3_adapter *adapter = netdev_priv(netdev); int err = 0; - if (new_mtu < VMXNET3_MIN_MTU || new_mtu > VMXNET3_MAX_MTU) - return -EINVAL; - netdev->mtu = new_mtu; /* @@ -3428,6 +3425,10 @@ vmxnet3_probe_device(struct pci_dev *pdev, vmxnet3_set_ethtool_ops(netdev); netdev->watchdog_timeo = 5 * HZ; + /* MTU range: 60 - 9000 */ + netdev->min_mtu = VMXNET3_MIN_MTU; + netdev->max_mtu = VMXNET3_MAX_MTU; + INIT_WORK(&adapter->work, vmxnet3_reset_work); set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 74dc2bf71428..e30ffd29b7e9 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -302,7 +302,7 @@ static int xenvif_close(struct net_device *dev) static int xenvif_change_mtu(struct net_device *dev, int mtu) { struct xenvif *vif = netdev_priv(dev); - int max = vif->can_sg ? 65535 - VLAN_ETH_HLEN : ETH_DATA_LEN; + int max = vif->can_sg ? ETH_MAX_MTU - VLAN_ETH_HLEN : ETH_DATA_LEN; if (mtu > max) return -EINVAL; @@ -471,6 +471,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, dev->tx_queue_len = XENVIF_QUEUE_LENGTH; + dev->min_mtu = 0; + dev->max_mtu = ETH_MAX_MTU - VLAN_ETH_HLEN; + /* * Initialise a dummy MAC address. We choose the numerically * largest non-broadcast address to prevent the address getting diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index e17879dd5d5a..7d616b003e89 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1329,6 +1329,8 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) netdev->features |= netdev->hw_features; netdev->ethtool_ops = &xennet_ethtool_ops; + netdev->min_mtu = 0; + netdev->max_mtu = XEN_NETIF_MAX_TX_SIZE; SET_NETDEV_DEV(netdev, &dev->dev); np->netdev = netdev; diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index cba4433bcd51..9081b3f8779c 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -113,12 +113,10 @@ enum net_types { }; -#define ETH_HEADER_SIZE 14 /* size of ethernet header */ - #define ETH_MIN_DATA_SIZE 46 /* minimum eth data size */ -#define ETH_MIN_PACKET_SIZE (ETH_HEADER_SIZE + ETH_MIN_DATA_SIZE) +#define ETH_MIN_PACKET_SIZE (ETH_HLEN + ETH_MIN_DATA_SIZE) -#define ETH_MAX_MTU 16384 /* maximum data size */ +#define VISOR_ETH_MAX_MTU 16384 /* maximum data size */ #ifndef MAX_MACADDR_LEN #define MAX_MACADDR_LEN 6 /* number of bytes in MAC address */ @@ -288,7 +286,7 @@ struct net_pkt_xmt { int len; /* full length of data in the packet */ int num_frags; /* number of fragments in frags containing data */ struct phys_info frags[MAX_PHYS_INFO]; /* physical page information */ - char ethhdr[ETH_HEADER_SIZE]; /* the ethernet header */ + char ethhdr[ETH_HLEN]; /* the ethernet header */ struct { /* these are needed for csum at uisnic end */ u8 valid; /* 1 = struct is valid - else ignore */ @@ -323,7 +321,7 @@ struct net_pkt_xmtdone { */ #define RCVPOST_BUF_SIZE 4032 #define MAX_NET_RCV_CHAIN \ - ((ETH_MAX_MTU + ETH_HEADER_SIZE + RCVPOST_BUF_SIZE - 1) \ + ((VISOR_ETH_MAX_MTU + ETH_HLEN + RCVPOST_BUF_SIZE - 1) \ / RCVPOST_BUF_SIZE) struct net_pkt_rcvpost { diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 136700756485..f8a584bf4a77 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -791,7 +791,7 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) * pointing to */ firstfraglen = skb->len - skb->data_len; - if (firstfraglen < ETH_HEADER_SIZE) { + if (firstfraglen < ETH_HLEN) { spin_unlock_irqrestore(&devdata->priv_lock, flags); devdata->busy_cnt++; dev_err(&netdev->dev, @@ -864,7 +864,7 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) /* copy ethernet header from first frag into ocmdrsp * - everything else will be pass in frags & DMA'ed */ - memcpy(cmdrsp->net.xmt.ethhdr, skb->data, ETH_HEADER_SIZE); + memcpy(cmdrsp->net.xmt.ethhdr, skb->data, ETH_HLEN); /* copy frags info - from skb->data we need to only provide access * beyond eth header */ -- cgit v1.2.3 From b3e3893e1253692c3d2b8e8ebd5a26183ed30443 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 20 Oct 2016 13:55:22 -0400 Subject: net: use core MTU range checking in misc drivers firewire-net: - set min/max_mtu - remove fwnet_change_mtu nes: - set max_mtu - clean up nes_netdev_change_mtu xpnet: - set min/max_mtu - remove xpnet_dev_change_mtu hippi: - set min/max_mtu - remove hippi_change_mtu batman-adv: - set max_mtu - remove batadv_interface_change_mtu - initialization is a little async, not 100% certain that max_mtu is set in the optimal place, don't have hardware to test with rionet: - set min/max_mtu - remove rionet_change_mtu slip: - set min/max_mtu - streamline sl_change_mtu um/net_kern: - remove pointless ndo_change_mtu hsi/clients/ssi_protocol: - use core MTU range checking - remove now redundant ssip_pn_set_mtu ipoib: - set a default max MTU value - Note: ipoib's actual max MTU can vary, depending on if the device is in connected mode or not, so we'll just set the max_mtu value to the max possible, and let the ndo_change_mtu function continue to validate any new MTU change requests with checks for CM or not. Note that ipoib has no min_mtu set, and thus, the network core's mtu > 0 check is the only lower bounds here. mptlan: - use net core MTU range checking - remove now redundant mpt_lan_change_mtu fddi: - min_mtu = 21, max_mtu = 4470 - remove now redundant fddi_change_mtu (including export) fjes: - min_mtu = 8192, max_mtu = 65536 - The max_mtu value is actually one over IP_MAX_MTU here, but the idea is to get past the core net MTU range checks so fjes_change_mtu can validate a new MTU against what it supports (see fjes_support_mtu in fjes_hw.c) hsr: - min_mtu = 0 (calls ether_setup, max_mtu is 1500) f_phonet: - min_mtu = 6, max_mtu = 65541 u_ether: - min_mtu = 14, max_mtu = 15412 phonet/pep-gprs: - min_mtu = 576, max_mtu = 65530 - remove redundant gprs_set_mtu CC: netdev@vger.kernel.org CC: linux-rdma@vger.kernel.org CC: Stefan Richter CC: Faisal Latif CC: linux-rdma@vger.kernel.org CC: Cliff Whickman CC: Robin Holt CC: Jes Sorensen CC: Marek Lindner CC: Simon Wunderlich CC: Antonio Quartulli CC: Sathya Prakash CC: Chaitra P B CC: Suganath Prabu Subramani CC: MPT-FusionLinux.pdl@broadcom.com CC: Sebastian Reichel CC: Felipe Balbi CC: Arvid Brodin CC: Remi Denis-Courmont Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- arch/um/drivers/net_kern.c | 8 -------- drivers/firewire/net.c | 18 ++++-------------- drivers/hsi/clients/ssi_protocol.c | 14 ++++---------- drivers/infiniband/hw/nes/nes.c | 1 - drivers/infiniband/hw/nes/nes.h | 4 ++-- drivers/infiniband/hw/nes/nes_nic.c | 10 +++------- drivers/infiniband/ulp/ipoib/ipoib_main.c | 1 + drivers/message/fusion/mptlan.c | 15 ++++----------- drivers/misc/sgi-xp/xpnet.c | 21 ++++----------------- drivers/net/fddi/skfp/skfddi.c | 1 - drivers/net/fjes/fjes_main.c | 2 ++ drivers/net/hippi/rrunner.c | 1 - drivers/net/rionet.c | 15 +++------------ drivers/net/slip/slip.c | 11 +++++------ drivers/usb/gadget/function/f_phonet.c | 11 ++--------- drivers/usb/gadget/function/u_ether.c | 14 ++++---------- include/linux/fddidevice.h | 1 - include/linux/hippidevice.h | 1 - net/802/fddi.c | 11 ++--------- net/802/hippi.c | 14 ++------------ net/batman-adv/soft-interface.c | 13 +------------ net/hsr/hsr_device.c | 1 + net/phonet/pep-gprs.c | 12 ++---------- 23 files changed, 46 insertions(+), 154 deletions(-) (limited to 'drivers') diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 2cd5b6874c7b..1669240c7a25 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -256,13 +256,6 @@ static void uml_net_tx_timeout(struct net_device *dev) netif_wake_queue(dev); } -static int uml_net_change_mtu(struct net_device *dev, int new_mtu) -{ - dev->mtu = new_mtu; - - return 0; -} - #ifdef CONFIG_NET_POLL_CONTROLLER static void uml_net_poll_controller(struct net_device *dev) { @@ -374,7 +367,6 @@ static const struct net_device_ops uml_netdev_ops = { .ndo_set_rx_mode = uml_net_set_multicast_list, .ndo_tx_timeout = uml_net_tx_timeout, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = uml_net_change_mtu, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = uml_net_poll_controller, diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 309311b1faae..8430222151fc 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -1349,15 +1349,6 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net) return NETDEV_TX_OK; } -static int fwnet_change_mtu(struct net_device *net, int new_mtu) -{ - if (new_mtu < 68) - return -EINVAL; - - net->mtu = new_mtu; - return 0; -} - static const struct ethtool_ops fwnet_ethtool_ops = { .get_link = ethtool_op_get_link, }; @@ -1366,7 +1357,6 @@ static const struct net_device_ops fwnet_netdev_ops = { .ndo_open = fwnet_open, .ndo_stop = fwnet_stop, .ndo_start_xmit = fwnet_tx, - .ndo_change_mtu = fwnet_change_mtu, }; static void fwnet_init_dev(struct net_device *net) @@ -1435,7 +1425,6 @@ static int fwnet_probe(struct fw_unit *unit, struct net_device *net; bool allocated_netdev = false; struct fwnet_device *dev; - unsigned max_mtu; int ret; union fwnet_hwaddr *ha; @@ -1478,9 +1467,10 @@ static int fwnet_probe(struct fw_unit *unit, * Use the RFC 2734 default 1500 octets or the maximum payload * as initial MTU */ - max_mtu = (1 << (card->max_receive + 1)) - - sizeof(struct rfc2734_header) - IEEE1394_GASP_HDR_SIZE; - net->mtu = min(1500U, max_mtu); + net->max_mtu = (1 << (card->max_receive + 1)) + - sizeof(struct rfc2734_header) - IEEE1394_GASP_HDR_SIZE; + net->mtu = min(1500U, net->max_mtu); + net->min_mtu = ETH_MIN_MTU; /* Set our hardware address while we're at it */ ha = (union fwnet_hwaddr *)net->dev_addr; diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index 6031cd146556..7ef819680acd 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -960,15 +960,6 @@ static int ssip_pn_stop(struct net_device *dev) return 0; } -static int ssip_pn_set_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu > SSIP_MAX_MTU || new_mtu < PHONET_MIN_MTU) - return -EINVAL; - dev->mtu = new_mtu; - - return 0; -} - static void ssip_xmit_work(struct work_struct *work) { struct ssi_protocol *ssi = @@ -1060,7 +1051,6 @@ static const struct net_device_ops ssip_pn_ops = { .ndo_open = ssip_pn_open, .ndo_stop = ssip_pn_stop, .ndo_start_xmit = ssip_pn_xmit, - .ndo_change_mtu = ssip_pn_set_mtu, }; static void ssip_pn_setup(struct net_device *dev) @@ -1136,6 +1126,10 @@ static int ssi_protocol_probe(struct device *dev) goto out1; } + /* MTU range: 6 - 65535 */ + ssi->netdev->min_mtu = PHONET_MIN_MTU; + ssi->netdev->max_mtu = SSIP_MAX_MTU; + SET_NETDEV_DEV(ssi->netdev, dev); netif_carrier_off(ssi->netdev); err = register_netdev(ssi->netdev); diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 35cbb17bec12..2baa45a8e401 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -65,7 +65,6 @@ MODULE_DESCRIPTION("NetEffect RNIC Low-level iWARP Driver"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(DRV_VERSION); -int max_mtu = 9000; int interrupt_mod_interval = 0; /* Interoperability */ diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index e7430c9254d3..85acd0843b50 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -83,6 +83,8 @@ #define NES_FIRST_QPN 64 #define NES_SW_CONTEXT_ALIGN 1024 +#define NES_MAX_MTU 9000 + #define NES_NIC_MAX_NICS 16 #define NES_MAX_ARP_TABLE_SIZE 4096 @@ -169,8 +171,6 @@ do { \ #include "nes_cm.h" #include "nes_mgt.h" -extern int max_mtu; -#define max_frame_len (max_mtu+ETH_HLEN) extern int interrupt_mod_interval; extern int nes_if_count; extern int mpa_version; diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 2b27d1351cf7..7f8597d6738b 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -981,20 +981,16 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu) { struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; - int ret = 0; u8 jumbomode = 0; u32 nic_active; u32 nic_active_bit; u32 uc_all_active; u32 mc_all_active; - if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu)) - return -EINVAL; - netdev->mtu = new_mtu; nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN; - if (netdev->mtu > 1500) { + if (netdev->mtu > ETH_DATA_LEN) { jumbomode=1; } nes_nic_init_timer_defaults(nesdev, jumbomode); @@ -1020,7 +1016,7 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu) nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); } - return ret; + return 0; } @@ -1658,7 +1654,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, netdev->watchdog_timeo = NES_TX_TIMEOUT; netdev->irq = nesdev->pcidev->irq; - netdev->mtu = ETH_DATA_LEN; + netdev->max_mtu = NES_MAX_MTU; netdev->hard_header_len = ETH_HLEN; netdev->addr_len = ETH_ALEN; netdev->type = ARPHRD_ETHER; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index cc059218c962..ae5d7cd100a5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -2017,6 +2017,7 @@ static struct net_device *ipoib_add_port(const char *format, /* MTU will be reset when mcast join happens */ priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu); priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu; + priv->dev->max_mtu = IPOIB_CM_MTU; priv->dev->neigh_priv_len = sizeof(struct ipoib_neigh); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 6955c9e22d57..55dd71bbdc2a 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -548,16 +548,6 @@ mpt_lan_close(struct net_device *dev) return 0; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < MPT_LAN_MIN_MTU) || (new_mtu > MPT_LAN_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* Tx timeout handler. */ static void @@ -1304,7 +1294,6 @@ static const struct net_device_ops mpt_netdev_ops = { .ndo_open = mpt_lan_open, .ndo_stop = mpt_lan_close, .ndo_start_xmit = mpt_lan_sdu_send, - .ndo_change_mtu = mpt_lan_change_mtu, .ndo_tx_timeout = mpt_lan_tx_timeout, }; @@ -1375,6 +1364,10 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) dev->netdev_ops = &mpt_netdev_ops; dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT; + /* MTU range: 96 - 65280 */ + dev->min_mtu = MPT_LAN_MIN_MTU; + dev->max_mtu = MPT_LAN_MAX_MTU; + dlprintk((KERN_INFO MYNAM ": Finished registering dev " "and setting initial values\n")); diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 557f9782c53c..0c26eaf5f62b 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -118,6 +118,8 @@ static DEFINE_SPINLOCK(xpnet_broadcast_lock); * now, the default is 64KB. */ #define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES) +/* 68 comes from min TCP+IP+MAC header */ +#define XPNET_MIN_MTU 68 /* 32KB has been determined to be the ideal */ #define XPNET_DEF_MTU (0x8000UL) @@ -330,22 +332,6 @@ xpnet_dev_stop(struct net_device *dev) return 0; } -static int -xpnet_dev_change_mtu(struct net_device *dev, int new_mtu) -{ - /* 68 comes from min TCP+IP+MAC header */ - if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) { - dev_err(xpnet, "ifconfig %s mtu %d failed; value must be " - "between 68 and %ld\n", dev->name, new_mtu, - XPNET_MAX_MTU); - return -EINVAL; - } - - dev->mtu = new_mtu; - dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu); - return 0; -} - /* * Notification that the other end has received the message and * DMA'd the skb information. At this point, they are done with @@ -519,7 +505,6 @@ static const struct net_device_ops xpnet_netdev_ops = { .ndo_open = xpnet_dev_open, .ndo_stop = xpnet_dev_stop, .ndo_start_xmit = xpnet_dev_hard_start_xmit, - .ndo_change_mtu = xpnet_dev_change_mtu, .ndo_tx_timeout = xpnet_dev_tx_timeout, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -555,6 +540,8 @@ xpnet_init(void) xpnet_device->netdev_ops = &xpnet_netdev_ops; xpnet_device->mtu = XPNET_DEF_MTU; + xpnet_device->min_mtu = XPNET_MIN_MTU; + xpnet_device->max_mtu = XPNET_MAX_MTU; /* * Multicast assumes the LSB of the first octet is set for multicast diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c index 51acc6d86e91..3a639180e4a0 100644 --- a/drivers/net/fddi/skfp/skfddi.c +++ b/drivers/net/fddi/skfp/skfddi.c @@ -166,7 +166,6 @@ static const struct net_device_ops skfp_netdev_ops = { .ndo_stop = skfp_close, .ndo_start_xmit = skfp_send_pkt, .ndo_get_stats = skfp_ctl_get_stats, - .ndo_change_mtu = fddi_change_mtu, .ndo_set_rx_mode = skfp_ctl_set_multicast_list, .ndo_set_mac_address = skfp_ctl_set_mac_address, .ndo_do_ioctl = skfp_ioctl, diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index f36eb4ad40b7..b77e4ecf3cf2 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -1316,6 +1316,8 @@ static void fjes_netdev_setup(struct net_device *netdev) netdev->netdev_ops = &fjes_netdev_ops; fjes_set_ethtool_ops(netdev); netdev->mtu = fjes_support_mtu[3]; + netdev->min_mtu = fjes_support_mtu[0]; + netdev->max_mtu = fjes_support_mtu[3]; netdev->flags |= IFF_BROADCAST; netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER; } diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index 95c0b45a68fb..f5a9728b89f3 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c @@ -68,7 +68,6 @@ static const struct net_device_ops rr_netdev_ops = { .ndo_stop = rr_close, .ndo_do_ioctl = rr_ioctl, .ndo_start_xmit = rr_start_xmit, - .ndo_change_mtu = hippi_change_mtu, .ndo_set_mac_address = hippi_mac_addr, }; diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index a31f4610b493..300bb1479b3a 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -466,17 +466,6 @@ static void rionet_set_msglevel(struct net_device *ndev, u32 value) rnet->msg_enable = value; } -static int rionet_change_mtu(struct net_device *ndev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > RIONET_MAX_MTU)) { - printk(KERN_ERR "%s: Invalid MTU size %d\n", - ndev->name, new_mtu); - return -EINVAL; - } - ndev->mtu = new_mtu; - return 0; -} - static const struct ethtool_ops rionet_ethtool_ops = { .get_drvinfo = rionet_get_drvinfo, .get_msglevel = rionet_get_msglevel, @@ -488,7 +477,6 @@ static const struct net_device_ops rionet_netdev_ops = { .ndo_open = rionet_open, .ndo_stop = rionet_close, .ndo_start_xmit = rionet_start_xmit, - .ndo_change_mtu = rionet_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, }; @@ -525,6 +513,9 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) ndev->netdev_ops = &rionet_netdev_ops; ndev->mtu = RIONET_MAX_MTU; + /* MTU range: 68 - 4082 */ + ndev->min_mtu = ETH_MIN_MTU; + ndev->max_mtu = RIONET_MAX_MTU; ndev->features = NETIF_F_LLTX; SET_NETDEV_DEV(ndev, &mport->dev); ndev->ethtool_ops = &rionet_ethtool_ops; diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 9ed6d1c1ee45..7e933d8ff811 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -561,12 +561,7 @@ static int sl_change_mtu(struct net_device *dev, int new_mtu) { struct slip *sl = netdev_priv(dev); - if (new_mtu < 68 || new_mtu > 65534) - return -EINVAL; - - if (new_mtu != dev->mtu) - return sl_realloc_bufs(sl, new_mtu); - return 0; + return sl_realloc_bufs(sl, new_mtu); } /* Netdevice get statistics request */ @@ -663,6 +658,10 @@ static void sl_setup(struct net_device *dev) dev->addr_len = 0; dev->tx_queue_len = 10; + /* MTU range: 68 - 65534 */ + dev->min_mtu = 68; + dev->max_mtu = 65534; + /* New-style flags. */ dev->flags = IFF_NOARP|IFF_POINTOPOINT|IFF_MULTICAST; } diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c index 0473d619d5bf..b4058f0000e4 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -261,19 +261,10 @@ out: return NETDEV_TX_OK; } -static int pn_net_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static const struct net_device_ops pn_netdev_ops = { .ndo_open = pn_net_open, .ndo_stop = pn_net_close, .ndo_start_xmit = pn_net_xmit, - .ndo_change_mtu = pn_net_mtu, }; static void pn_net_setup(struct net_device *dev) @@ -282,6 +273,8 @@ static void pn_net_setup(struct net_device *dev) dev->type = ARPHRD_PHONET; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->mtu = PHONET_DEV_MTU; + dev->min_mtu = PHONET_MIN_MTU; + dev->max_mtu = PHONET_MAX_MTU; dev->hard_header_len = 1; dev->dev_addr[0] = PN_MEDIA_USB; dev->addr_len = 1; diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 9c8c9ed1dc9e..39a6df1e2ded 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -142,15 +142,6 @@ static inline int qlen(struct usb_gadget *gadget, unsigned qmult) /* NETWORK DRIVER HOOKUP (to the layer above this driver) */ -static int ueth_change_mtu(struct net_device *net, int new_mtu) -{ - if (new_mtu <= ETH_HLEN || new_mtu > GETHER_MAX_ETH_FRAME_LEN) - return -ERANGE; - net->mtu = new_mtu; - - return 0; -} - static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) { struct eth_dev *dev = netdev_priv(net); @@ -736,7 +727,6 @@ static const struct net_device_ops eth_netdev_ops = { .ndo_open = eth_open, .ndo_stop = eth_stop, .ndo_start_xmit = eth_start_xmit, - .ndo_change_mtu = ueth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; @@ -799,6 +789,10 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, net->ethtool_ops = &ops; + /* MTU range: 14 - 15412 */ + net->min_mtu = ETH_HLEN; + net->max_mtu = GETHER_MAX_ETH_FRAME_LEN; + dev->gadget = g; SET_NETDEV_DEV(net, &g->dev); SET_NETDEV_DEVTYPE(net, &gadget_type); diff --git a/include/linux/fddidevice.h b/include/linux/fddidevice.h index 9a79f0106da1..32c22cfb238b 100644 --- a/include/linux/fddidevice.h +++ b/include/linux/fddidevice.h @@ -26,7 +26,6 @@ #ifdef __KERNEL__ __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev); -int fddi_change_mtu(struct net_device *dev, int new_mtu); struct net_device *alloc_fddidev(int sizeof_priv); #endif diff --git a/include/linux/hippidevice.h b/include/linux/hippidevice.h index 8ec23fb0b412..402f99e328d4 100644 --- a/include/linux/hippidevice.h +++ b/include/linux/hippidevice.h @@ -32,7 +32,6 @@ struct hippi_cb { }; __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev); -int hippi_change_mtu(struct net_device *dev, int new_mtu); int hippi_mac_addr(struct net_device *dev, void *p); int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p); struct net_device *alloc_hippi_dev(int sizeof_priv); diff --git a/net/802/fddi.c b/net/802/fddi.c index 7d3a0af954e8..6356623fc238 100644 --- a/net/802/fddi.c +++ b/net/802/fddi.c @@ -141,15 +141,6 @@ __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev) EXPORT_SYMBOL(fddi_type_trans); -int fddi_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} -EXPORT_SYMBOL(fddi_change_mtu); - static const struct header_ops fddi_header_ops = { .create = fddi_header, }; @@ -161,6 +152,8 @@ static void fddi_setup(struct net_device *dev) dev->type = ARPHRD_FDDI; dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */ dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */ + dev->min_mtu = FDDI_K_SNAP_HLEN; + dev->max_mtu = FDDI_K_SNAP_DLEN; dev->addr_len = FDDI_K_ALEN; dev->tx_queue_len = 100; /* Long queues on FDDI */ dev->flags = IFF_BROADCAST | IFF_MULTICAST; diff --git a/net/802/hippi.c b/net/802/hippi.c index ade1a52cdcff..5e4427beab2b 100644 --- a/net/802/hippi.c +++ b/net/802/hippi.c @@ -116,18 +116,6 @@ __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev) EXPORT_SYMBOL(hippi_type_trans); -int hippi_change_mtu(struct net_device *dev, int new_mtu) -{ - /* - * HIPPI's got these nice large MTUs. - */ - if ((new_mtu < 68) || (new_mtu > 65280)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} -EXPORT_SYMBOL(hippi_change_mtu); - /* * For HIPPI we will actually use the lower 4 bytes of the hardware * address as the I-FIELD rather than the actual hardware address. @@ -174,6 +162,8 @@ static void hippi_setup(struct net_device *dev) dev->type = ARPHRD_HIPPI; dev->hard_header_len = HIPPI_HLEN; dev->mtu = 65280; + dev->min_mtu = 68; + dev->max_mtu = 65280; dev->addr_len = HIPPI_ALEN; dev->tx_queue_len = 25 /* 5 */; memset(dev->broadcast, 0xFF, HIPPI_ALEN); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 49e16b6e0ba3..112679d64be5 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -158,17 +158,6 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) return 0; } -static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu) -{ - /* check ranges */ - if ((new_mtu < 68) || (new_mtu > batadv_hardif_min_mtu(dev))) - return -EINVAL; - - dev->mtu = new_mtu; - - return 0; -} - /** * batadv_interface_set_rx_mode - set the rx mode of a device * @dev: registered network device to modify @@ -920,7 +909,6 @@ static const struct net_device_ops batadv_netdev_ops = { .ndo_vlan_rx_add_vid = batadv_interface_add_vid, .ndo_vlan_rx_kill_vid = batadv_interface_kill_vid, .ndo_set_mac_address = batadv_interface_set_mac_addr, - .ndo_change_mtu = batadv_interface_change_mtu, .ndo_set_rx_mode = batadv_interface_set_rx_mode, .ndo_start_xmit = batadv_interface_tx, .ndo_validate_addr = eth_validate_addr, @@ -987,6 +975,7 @@ struct net_device *batadv_softif_create(struct net *net, const char *name) dev_net_set(soft_iface, net); soft_iface->rtnl_link_ops = &batadv_link_ops; + soft_iface->max_mtu = batadv_hardif_min_mtu(soft_iface); ret = register_netdevice(soft_iface); if (ret < 0) { diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 16737cd8dae8..fc65b145f6e7 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -398,6 +398,7 @@ void hsr_dev_setup(struct net_device *dev) random_ether_addr(dev->dev_addr); ether_setup(dev); + dev->min_mtu = 0; dev->header_ops = &hsr_header_ops; dev->netdev_ops = &hsr_device_ops; SET_NETDEV_DEVTYPE(dev, &hsr_type); diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index fa8237fdc57b..21c28b51be94 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c @@ -217,20 +217,10 @@ static netdev_tx_t gprs_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int gprs_set_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 576) || (new_mtu > (PHONET_MAX_MTU - 11))) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - static const struct net_device_ops gprs_netdev_ops = { .ndo_open = gprs_open, .ndo_stop = gprs_close, .ndo_start_xmit = gprs_xmit, - .ndo_change_mtu = gprs_set_mtu, }; static void gprs_setup(struct net_device *dev) @@ -239,6 +229,8 @@ static void gprs_setup(struct net_device *dev) dev->type = ARPHRD_PHONET_PIPE; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->mtu = GPRS_DEFAULT_MTU; + dev->min_mtu = 576; + dev->max_mtu = (PHONET_MAX_MTU - 11); dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 10; -- cgit v1.2.3 From 46b3ef4cdf6f84c35eeacfd4c19839e0067fcfdd Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 20 Oct 2016 13:55:23 -0400 Subject: s390/net: use net core MTU range checking ctcm: - min_mtu = 576, max_mtu = 65527 netiucv: - min_mtu = 576, max_mtu = 65535 qeth: - min_mtu = 64, max_mtu = 65535 CC: netdev@vger.kernel.org CC: linux-s390@vger.kernel.org CC: Ursula Braun Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/s390/net/ctcm_main.c | 5 ++--- drivers/s390/net/netiucv.c | 24 ++---------------------- drivers/s390/net/qeth_core_main.c | 4 ---- drivers/s390/net/qeth_l2_main.c | 2 ++ drivers/s390/net/qeth_l3_main.c | 2 ++ 5 files changed, 8 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index ad17fc5883f6..ac65f12bcd43 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1032,9 +1032,6 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu) struct ctcm_priv *priv; int max_bufsize; - if (new_mtu < 576 || new_mtu > 65527) - return -EINVAL; - priv = dev->ml_priv; max_bufsize = priv->channel[CTCM_READ]->max_bufsize; @@ -1123,6 +1120,8 @@ void static ctcm_dev_setup(struct net_device *dev) dev->type = ARPHRD_SLIP; dev->tx_queue_len = 100; dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->min_mtu = 576; + dev->max_mtu = 65527; } /* diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 2f0f3918172a..2981024a2438 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1428,27 +1428,6 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev) return &priv->stats; } -/** - * netiucv_change_mtu - * @dev: Pointer to interface struct. - * @new_mtu: The new MTU to use for this interface. - * - * Sets MTU of an interface. - * - * Returns 0 on success, -EINVAL if MTU is out of valid range. - * (valid range is 576 .. NETIUCV_MTU_MAX). - */ -static int netiucv_change_mtu(struct net_device * dev, int new_mtu) -{ - IUCV_DBF_TEXT(trace, 3, __func__); - if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) { - IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n"); - return -EINVAL; - } - dev->mtu = new_mtu; - return 0; -} - /* * attributes in sysfs */ @@ -1986,12 +1965,13 @@ static const struct net_device_ops netiucv_netdev_ops = { .ndo_stop = netiucv_close, .ndo_get_stats = netiucv_stats, .ndo_start_xmit = netiucv_tx, - .ndo_change_mtu = netiucv_change_mtu, }; static void netiucv_setup_netdevice(struct net_device *dev) { dev->mtu = NETIUCV_MTU_DEFAULT; + dev->min_mtu = 576; + dev->max_mtu = NETIUCV_MTU_MAX; dev->destructor = netiucv_free_netdevice; dev->hard_header_len = NETIUCV_HDRLEN; dev->addr_len = 0; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 20cf29613043..e33558313834 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4202,10 +4202,6 @@ int qeth_change_mtu(struct net_device *dev, int new_mtu) sprintf(dbf_text, "%8x", new_mtu); QETH_CARD_TEXT(card, 4, dbf_text); - if (new_mtu < 64) - return -EINVAL; - if (new_mtu > 65535) - return -EINVAL; if ((!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) && (!qeth_mtu_is_valid(card, new_mtu))) return -EINVAL; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index bb27058fa9f0..9c921c2833f1 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1107,6 +1107,8 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) card->dev->ml_priv = card; card->dev->watchdog_timeo = QETH_TX_TIMEOUT; card->dev->mtu = card->info.initial_mtu; + card->dev->min_mtu = 64; + card->dev->max_mtu = ETH_MAX_MTU; card->dev->netdev_ops = &qeth_l2_netdev_ops; card->dev->ethtool_ops = (card->info.type != QETH_CARD_TYPE_OSN) ? diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 272d9e7419be..ac37d050e765 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -3140,6 +3140,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) card->dev->ml_priv = card; card->dev->watchdog_timeo = QETH_TX_TIMEOUT; card->dev->mtu = card->info.initial_mtu; + card->dev->min_mtu = 64; + card->dev->max_mtu = ETH_MAX_MTU; card->dev->ethtool_ops = &qeth_l3_ethtool_ops; card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | -- cgit v1.2.3 From 0a91877cf2ee78a2a57d65b42f14eefc54dc4455 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 30 Sep 2016 11:05:56 -0700 Subject: drm/i915: Move down skl/kbl ddi iboost and n_edp_entires fixup No functional change. Only moving this fixup block out of ddi_translation definitions so we can split skl and kbl cleanly. v2: Remove useless comment. (Ville) Cc: Manasi Navare Signed-off-by: Rodrigo Vivi Reviewed-by: Manasi Navare Link: http://patchwork.freedesktop.org/patch/msgid/1475258757-29540-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 7f7741c1406d..e74c2fc360f1 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -436,15 +436,6 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) skl_get_buf_trans_dp(dev_priv, &n_dp_entries); ddi_translations_edp = skl_get_buf_trans_edp(dev_priv, &n_edp_entries); - - /* If we're boosting the current, set bit 31 of trans1 */ - if (dev_priv->vbt.ddi_port_info[port].dp_boost_level) - iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; - - if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP && - port != PORT_A && port != PORT_E && - n_edp_entries > 9)) - n_edp_entries = 9; } else if (IS_BROADWELL(dev_priv)) { ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; @@ -464,6 +455,17 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); } + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { + /* If we're boosting the current, set bit 31 of trans1 */ + if (dev_priv->vbt.ddi_port_info[port].dp_boost_level) + iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; + + if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP && + port != PORT_A && port != PORT_E && + n_edp_entries > 9)) + n_edp_entries = 9; + } + switch (encoder->type) { case INTEL_OUTPUT_EDP: ddi_translations = ddi_translations_edp; -- cgit v1.2.3 From 0fdd491861e1269dc18017774fc50c3a3b54f3eb Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 18 Oct 2016 08:57:36 -0700 Subject: drm/i915: KBL - Recommended buffer translation programming for DisplayPort According to spec: "KBL re-uses SKL values, except where specific KBL values are listed." And recently spec has changed adding different table for Display Port only. But for all SKUs (H,S,U,Y) we have slightly different values. v2: Fix wrong condition spotted by Jani. v3: Fix 7th entry of KBL H and S table - by Manasi. Cc: Jani Nikula Cc: Manasi Navare Signed-off-by: Rodrigo Vivi Reviewed-by: Manasi Navare Link: http://patchwork.freedesktop.org/patch/msgid/1476806256-13318-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 88 +++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index e74c2fc360f1..fb18d699ce10 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -167,8 +167,47 @@ static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { { 0x80005012, 0x000000C0, 0x3 }, }; +/* Kabylake H and S */ +static const struct ddi_buf_trans kbl_ddi_translations_dp[] = { + { 0x00002016, 0x000000A0, 0x0 }, + { 0x00005012, 0x0000009B, 0x0 }, + { 0x00007011, 0x00000088, 0x0 }, + { 0x80009010, 0x000000C0, 0x1 }, + { 0x00002016, 0x0000009B, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x80007011, 0x000000C0, 0x1 }, + { 0x00002016, 0x00000097, 0x0 }, + { 0x80005012, 0x000000C0, 0x1 }, +}; + +/* Kabylake U */ +static const struct ddi_buf_trans kbl_u_ddi_translations_dp[] = { + { 0x0000201B, 0x000000A1, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x80007011, 0x000000CD, 0x3 }, + { 0x80009010, 0x000000C0, 0x3 }, + { 0x0000201B, 0x0000009D, 0x0 }, + { 0x80005012, 0x000000C0, 0x3 }, + { 0x80007011, 0x000000C0, 0x3 }, + { 0x00002016, 0x0000004F, 0x0 }, + { 0x80005012, 0x000000C0, 0x3 }, +}; + +/* Kabylake Y */ +static const struct ddi_buf_trans kbl_y_ddi_translations_dp[] = { + { 0x00001017, 0x000000A1, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x80007011, 0x000000CD, 0x3 }, + { 0x8000800F, 0x000000C0, 0x3 }, + { 0x00001017, 0x0000009D, 0x0 }, + { 0x80005012, 0x000000C0, 0x3 }, + { 0x80007011, 0x000000C0, 0x3 }, + { 0x00001017, 0x0000004C, 0x0 }, + { 0x80005012, 0x000000C0, 0x3 }, +}; + /* - * Skylake H and S + * Skylake/Kabylake H and S * eDP 1.4 low vswing translation parameters */ static const struct ddi_buf_trans skl_ddi_translations_edp[] = { @@ -185,7 +224,7 @@ static const struct ddi_buf_trans skl_ddi_translations_edp[] = { }; /* - * Skylake U + * Skylake/Kabylake U * eDP 1.4 low vswing translation parameters */ static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { @@ -202,7 +241,7 @@ static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { }; /* - * Skylake Y + * Skylake/Kabylake Y * eDP 1.4 low vswing translation parameters */ static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = { @@ -218,7 +257,7 @@ static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = { { 0x00000018, 0x0000008A, 0x0 }, }; -/* Skylake U, H and S */ +/* Skylake/Kabylake U, H and S */ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { { 0x00000018, 0x000000AC, 0x0 }, { 0x00005012, 0x0000009D, 0x0 }, @@ -233,7 +272,7 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { { 0x80000018, 0x000000C0, 0x1 }, }; -/* Skylake Y */ +/* Skylake/Kabylake Y */ static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = { { 0x00000018, 0x000000A1, 0x0 }, { 0x00005012, 0x000000DF, 0x0 }, @@ -334,10 +373,10 @@ bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) static const struct ddi_buf_trans * skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) { - if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) { + if (IS_SKL_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); return skl_y_ddi_translations_dp; - } else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv)) { + } else if (IS_SKL_ULT(dev_priv)) { *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); return skl_u_ddi_translations_dp; } else { @@ -346,6 +385,21 @@ skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) } } +static const struct ddi_buf_trans * +kbl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) +{ + if (IS_KBL_ULX(dev_priv)) { + *n_entries = ARRAY_SIZE(kbl_y_ddi_translations_dp); + return kbl_y_ddi_translations_dp; + } else if (IS_KBL_ULT(dev_priv)) { + *n_entries = ARRAY_SIZE(kbl_u_ddi_translations_dp); + return kbl_u_ddi_translations_dp; + } else { + *n_entries = ARRAY_SIZE(kbl_ddi_translations_dp); + return kbl_ddi_translations_dp; + } +} + static const struct ddi_buf_trans * skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) { @@ -362,7 +416,10 @@ skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) } } - return skl_get_buf_trans_dp(dev_priv, n_entries); + if (IS_KABYLAKE(dev_priv)) + return kbl_get_buf_trans_dp(dev_priv, n_entries); + else + return skl_get_buf_trans_dp(dev_priv, n_entries); } static const struct ddi_buf_trans * @@ -430,7 +487,13 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) if (IS_BROXTON(dev_priv)) return; - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { + if (IS_KABYLAKE(dev_priv)) { + ddi_translations_fdi = NULL; + ddi_translations_dp = + kbl_get_buf_trans_dp(dev_priv, &n_dp_entries); + ddi_translations_edp = + skl_get_buf_trans_edp(dev_priv, &n_edp_entries); + } else if (IS_SKYLAKE(dev_priv)) { ddi_translations_fdi = NULL; ddi_translations_dp = skl_get_buf_trans_dp(dev_priv, &n_dp_entries); @@ -1436,7 +1499,12 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder, u32 level) if (dp_iboost) { iboost = dp_iboost; } else { - ddi_translations = skl_get_buf_trans_dp(dev_priv, &n_entries); + if (IS_KABYLAKE(dev_priv)) + ddi_translations = kbl_get_buf_trans_dp(dev_priv, + &n_entries); + else + ddi_translations = skl_get_buf_trans_dp(dev_priv, + &n_entries); iboost = ddi_translations[level].i_boost; } } else if (type == INTEL_OUTPUT_EDP) { -- cgit v1.2.3 From 3a993ab603c79896b834cb082648a8e57757b22c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 18 Oct 2016 03:02:24 +0800 Subject: ACPICA: Update an info message during table load phase ACPICA commit 1d435008fd9ea34768df8862de9cb6fff69650f6 Only emit an extra newline for acpiexec. Link: https://github.com/acpica/acpica/commit/1d435008 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbxfload.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 5569f637f669..2599e8314d94 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -239,7 +239,7 @@ acpi_status acpi_tb_load_namespace(void) } if (!tables_failed) { - ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded\n", tables_loaded)); + ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded", tables_loaded)); } else { ACPI_ERROR((AE_INFO, "%u table load failures, %u successful", @@ -250,6 +250,10 @@ acpi_status acpi_tb_load_namespace(void) status = AE_CTRL_TERMINATE; } +#ifdef ACPI_APPLICATION + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "\n")); +#endif + unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); -- cgit v1.2.3 From cacf54750a4204a2d2e49fadce56ef9c739e6b9f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 18 Oct 2016 03:03:19 +0800 Subject: ACPICA: Increase loop limit for AE_AML_INFINITE_LOOP exception ACPICA commit 9f83b34cb172549c20f18663bc7460fb4145a75b increase loop limit to accomodate faster processors. From 64k loops max to 1 million. Link: https://github.com/acpica/acpica/commit/9f83b34c Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 2 +- include/acpi/acconfig.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 750fa824d42c..17f7bb8f9d93 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -242,7 +242,7 @@ ACPI_GLOBAL(struct acpi_thread_state *, acpi_gbl_current_walk_list); /* Maximum number of While() loop iterations before forced abort */ -ACPI_GLOBAL(u16, acpi_gbl_max_loop_iterations); +ACPI_GLOBAL(u32, acpi_gbl_max_loop_iterations); /* Control method single step flag */ diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 12c2882bf647..d25da936750e 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -146,7 +146,7 @@ /* Maximum number of While() loops before abort */ -#define ACPI_MAX_LOOP_COUNT 0xFFFF +#define ACPI_MAX_LOOP_COUNT 0x000FFFFF /****************************************************************************** * -- cgit v1.2.3 From a335e95590acee89e75a21849d943f085c6269b5 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 18 Oct 2016 03:03:39 +0800 Subject: ACPICA: Disassembler: Fix for Divide() support, new support for test suite ACPICA commit 4b367408659af08fd44839866ec301285284e6f4 Fixes a problem with complex expressions where an illegal mix of legacy ASL and ASL+ could be emitted. Adds new support for ASLTS that disables some disassembler optimizations could be changed during a conversion to ASL+. These expressions are now emitted in legacy ASL instead of ASL+. Link: https://github.com/acpica/acpica/commit/4b367408 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 1 + drivers/acpi/acpica/aclocal.h | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 17f7bb8f9d93..b549e6d048bd 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -318,6 +318,7 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_cstyle_disassembly, TRUE); ACPI_INIT_GLOBAL(u8, acpi_gbl_force_aml_disassembly, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_dm_opt_verbose, TRUE); ACPI_INIT_GLOBAL(u8, acpi_gbl_dm_emit_external_opcodes, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_do_disassembler_optimizations, TRUE); ACPI_GLOBAL(u8, acpi_gbl_dm_opt_disasm); ACPI_GLOBAL(u8, acpi_gbl_dm_opt_listing); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index dff1207a6078..792660054992 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -765,7 +765,7 @@ union acpi_parse_value { union acpi_parse_value value; /* Value or args associated with the opcode */\ u8 arg_list_length; /* Number of elements in the arg list */\ ACPI_DISASM_ONLY_MEMBERS (\ - u8 disasm_flags; /* Used during AML disassembly */\ + u16 disasm_flags; /* Used during AML disassembly */\ u8 disasm_opcode; /* Subtype used for disassembly */\ char *operator_symbol;/* Used for C-style operator name strings */\ char aml_op_name[16]) /* Op name (debug only) */ @@ -868,14 +868,15 @@ struct acpi_parse_state { /* Parse object disasm_flags */ -#define ACPI_PARSEOP_IGNORE 0x01 -#define ACPI_PARSEOP_PARAMETER_LIST 0x02 -#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04 -#define ACPI_PARSEOP_PREDEFINED_CHECKED 0x08 -#define ACPI_PARSEOP_CLOSING_PAREN 0x10 -#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT 0x20 -#define ACPI_PARSEOP_ASSIGNMENT 0x40 -#define ACPI_PARSEOP_ELSEIF 0x80 +#define ACPI_PARSEOP_IGNORE 0x0001 +#define ACPI_PARSEOP_PARAMETER_LIST 0x0002 +#define ACPI_PARSEOP_EMPTY_TERMLIST 0x0004 +#define ACPI_PARSEOP_PREDEFINED_CHECKED 0x0008 +#define ACPI_PARSEOP_CLOSING_PAREN 0x0010 +#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT 0x0020 +#define ACPI_PARSEOP_ASSIGNMENT 0x0040 +#define ACPI_PARSEOP_ELSEIF 0x0080 +#define ACPI_PARSEOP_LEGACY_ASL_ONLY 0x0100 /***************************************************************************** * -- cgit v1.2.3 From 066118ffe94bc38d405edaf4dbc039f00dec6e7b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 18 Oct 2016 03:03:57 +0800 Subject: ACPICA: Move acpi_gbl_max_loop_iterations to the public globals file ACPICA commit eb8b2194200867dec9ba38e5ab98b5b8ef262945 Moved to acpixf.h with the rest of the configuration globals. Link: https://github.com/acpica/acpica/commit/eb8b2194 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 4 ---- include/acpi/acpixf.h | 7 +++++++ 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index b549e6d048bd..edbb42e251a6 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -240,10 +240,6 @@ ACPI_INIT_GLOBAL(u32, acpi_gbl_nesting_level, 0); ACPI_GLOBAL(struct acpi_thread_state *, acpi_gbl_current_walk_list); -/* Maximum number of While() loop iterations before forced abort */ - -ACPI_GLOBAL(u32, acpi_gbl_max_loop_iterations); - /* Control method single step flag */ ACPI_GLOBAL(u8, acpi_gbl_cm_single_step); diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index c7b3a132dbe7..07ab21ea47c8 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -258,6 +258,13 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_osi_data, 0); */ ACPI_INIT_GLOBAL(u8, acpi_gbl_reduced_hardware, FALSE); +/* + * Maximum number of While() loop iterations before forced method abort. + * This mechanism is intended to prevent infinite loops during interpreter + * execution within a host kernel. + */ +ACPI_INIT_GLOBAL(u32, acpi_gbl_max_loop_iterations, ACPI_MAX_LOOP_COUNT); + /* * This mechanism is used to trace a specified AML method. The method is * traced each time it is executed. -- cgit v1.2.3 From 69eb4d0190eab9e32fccbe1ec64dec1cfa7fb01a Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 16 Sep 2016 12:08:51 +0200 Subject: hwrng: omap - Switch to non-obsolete read API implementation The ".data_present" and ".data_read" operations are marked as OBSOLETE in the hwrng API. We have to use the ".read" operation instead. It makes the driver simpler and moves the busy loop, that waits until enough data is generated, to the read function. We simplify this step by only checking the status of the engine, if there is data, we copy the data to the output buffer and the amout of copied data is returned to the caller, otherwise zero is returned. The hwrng core will re-call the read operation as many times as required until enough data has been copied. Signed-off-by: Romain Perier Signed-off-by: Herbert Xu --- drivers/char/hw_random/omap-rng.c | 41 ++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index f5c26a5f6875..6ba0794e1c5a 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -140,41 +140,35 @@ static inline void omap_rng_write(struct omap_rng_dev *priv, u16 reg, __raw_writel(val, priv->base + priv->pdata->regs[reg]); } -static int omap_rng_data_present(struct hwrng *rng, int wait) + +static int omap_rng_do_read(struct hwrng *rng, void *data, size_t max, + bool wait) { struct omap_rng_dev *priv; - int data, i; + int i, present; priv = (struct omap_rng_dev *)rng->priv; + if (max < priv->pdata->data_size) + return 0; + for (i = 0; i < 20; i++) { - data = priv->pdata->data_present(priv); - if (data || !wait) + present = priv->pdata->data_present(priv); + if (present || !wait) break; - /* RNG produces data fast enough (2+ MBit/sec, even - * during "rngtest" loads, that these delays don't - * seem to trigger. We *could* use the RNG IRQ, but - * that'd be higher overhead ... so why bother? - */ + udelay(10); } - return data; -} - -static int omap_rng_data_read(struct hwrng *rng, u32 *data) -{ - struct omap_rng_dev *priv; - u32 data_size, i; - - priv = (struct omap_rng_dev *)rng->priv; - data_size = priv->pdata->data_size; + if (!present) + return 0; - for (i = 0; i < data_size / sizeof(u32); i++) - data[i] = omap_rng_read(priv, RNG_OUTPUT_L_REG + i); + memcpy_fromio(data, priv->base + priv->pdata->regs[RNG_OUTPUT_L_REG], + priv->pdata->data_size); if (priv->pdata->regs[RNG_INTACK_REG]) omap_rng_write(priv, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK); - return data_size; + + return priv->pdata->data_size; } static int omap_rng_init(struct hwrng *rng) @@ -195,8 +189,7 @@ static void omap_rng_cleanup(struct hwrng *rng) static struct hwrng omap_rng_ops = { .name = "omap", - .data_present = omap_rng_data_present, - .data_read = omap_rng_data_read, + .read = omap_rng_do_read, .init = omap_rng_init, .cleanup = omap_rng_cleanup, }; -- cgit v1.2.3 From b23d2d92ce34a487436dba8549a302729c5a40a2 Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 16 Sep 2016 12:08:52 +0200 Subject: hwrng: omap - Remove global definition of hwrng The omap-rng driver currently assumes that there will only ever be a single instance of an RNG device. For this reason, there is a statically allocated struct hwrng, with a fixed name. However, registering two struct hwrng with the same isn't accepted by the RNG framework, so we need to switch to a dynamically allocated struct hwrng, each using a different name. Then, we define the name of this hwrng to "dev_name(dev)", so the name of the data structure is unique per device. Signed-off-by: Romain Perier Signed-off-by: Herbert Xu --- drivers/char/hw_random/omap-rng.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 6ba0794e1c5a..e4f71c8147f9 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -127,6 +127,7 @@ struct omap_rng_dev { void __iomem *base; struct device *dev; const struct omap_rng_pdata *pdata; + struct hwrng rng; }; static inline u32 omap_rng_read(struct omap_rng_dev *priv, u16 reg) @@ -187,12 +188,6 @@ static void omap_rng_cleanup(struct hwrng *rng) priv->pdata->cleanup(priv); } -static struct hwrng omap_rng_ops = { - .name = "omap", - .read = omap_rng_do_read, - .init = omap_rng_init, - .cleanup = omap_rng_cleanup, -}; static inline u32 omap2_rng_data_present(struct omap_rng_dev *priv) { @@ -365,7 +360,11 @@ static int omap_rng_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - omap_rng_ops.priv = (unsigned long)priv; + priv->rng.read = omap_rng_do_read; + priv->rng.init = omap_rng_init; + priv->rng.cleanup = omap_rng_cleanup; + + priv->rng.priv = (unsigned long)priv; platform_set_drvdata(pdev, priv); priv->dev = dev; @@ -376,6 +375,12 @@ static int omap_rng_probe(struct platform_device *pdev) goto err_ioremap; } + priv->rng.name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); + if (!priv->rng.name) { + ret = -ENOMEM; + goto err_ioremap; + } + pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { @@ -389,7 +394,7 @@ static int omap_rng_probe(struct platform_device *pdev) if (ret) goto err_ioremap; - ret = hwrng_register(&omap_rng_ops); + ret = hwrng_register(&priv->rng); if (ret) goto err_register; @@ -410,7 +415,7 @@ static int omap_rng_remove(struct platform_device *pdev) { struct omap_rng_dev *priv = platform_get_drvdata(pdev); - hwrng_unregister(&omap_rng_ops); + hwrng_unregister(&priv->rng); priv->pdata->cleanup(priv); -- cgit v1.2.3 From e54feeb0db9c6fc5d6b75cc045c9e4578534ec2e Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 16 Sep 2016 12:08:53 +0200 Subject: hwrng: omap - Add support for 128-bit output of data So far, this driver only supports up to 64 bits of output data generated by an RNG. Some IP blocks, like the SafeXcel IP-76 supports up to 128 bits of output data. This commits renames registers descriptions OUTPUT_L_REG and OUTPUT_H_REG to OUTPUT_0_REG and OUPUT_1_REG, respectively. It also adds two new values to the enumeration of existing registers: OUTPUT_2_REG and OUTPUT_3_REG. Signed-off-by: Romain Perier Signed-off-by: Herbert Xu --- drivers/char/hw_random/omap-rng.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index e4f71c8147f9..6c18540c8b43 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -65,8 +65,10 @@ #define OMAP4_RNG_OUTPUT_SIZE 0x8 enum { - RNG_OUTPUT_L_REG = 0, - RNG_OUTPUT_H_REG, + RNG_OUTPUT_0_REG = 0, + RNG_OUTPUT_1_REG, + RNG_OUTPUT_2_REG, + RNG_OUTPUT_3_REG, RNG_STATUS_REG, RNG_INTMASK_REG, RNG_INTACK_REG, @@ -82,7 +84,7 @@ enum { }; static const u16 reg_map_omap2[] = { - [RNG_OUTPUT_L_REG] = 0x0, + [RNG_OUTPUT_0_REG] = 0x0, [RNG_STATUS_REG] = 0x4, [RNG_CONFIG_REG] = 0x28, [RNG_REV_REG] = 0x3c, @@ -90,8 +92,8 @@ static const u16 reg_map_omap2[] = { }; static const u16 reg_map_omap4[] = { - [RNG_OUTPUT_L_REG] = 0x0, - [RNG_OUTPUT_H_REG] = 0x4, + [RNG_OUTPUT_0_REG] = 0x0, + [RNG_OUTPUT_1_REG] = 0x4, [RNG_STATUS_REG] = 0x8, [RNG_INTMASK_REG] = 0xc, [RNG_INTACK_REG] = 0x10, @@ -163,7 +165,7 @@ static int omap_rng_do_read(struct hwrng *rng, void *data, size_t max, if (!present) return 0; - memcpy_fromio(data, priv->base + priv->pdata->regs[RNG_OUTPUT_L_REG], + memcpy_fromio(data, priv->base + priv->pdata->regs[RNG_OUTPUT_0_REG], priv->pdata->data_size); if (priv->pdata->regs[RNG_INTACK_REG]) -- cgit v1.2.3 From f0d5a11200ca7071273d4b55b3c1d2a6f24f567b Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 16 Sep 2016 12:08:54 +0200 Subject: hwrng: omap - Don't prefix the probe message with OMAP So far, this driver was only used for OMAP SoCs. However, if a device variant is added for an IP block that has nothing to do with the OMAP platform, the message "OMAP Random Number Generator Ver" is displayed anyway. Instead of hardcoding "OMAP" into this message, we decide to only display "Random Number Generator". As dev_info is already pre-pending the message with the name of the device, we have enough informations. Signed-off-by: Romain Perier Signed-off-by: Herbert Xu --- drivers/char/hw_random/omap-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 6c18540c8b43..c64a0990feb7 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -400,7 +400,7 @@ static int omap_rng_probe(struct platform_device *pdev) if (ret) goto err_register; - dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", + dev_info(&pdev->dev, "Random Number Generator ver. %02x\n", omap_rng_read(priv, RNG_REV_REG)); return 0; -- cgit v1.2.3 From 383212425c926f3648fd760b2b674f1b7fac0d1d Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 16 Sep 2016 12:08:55 +0200 Subject: hwrng: omap - Add device variant for SafeXcel IP-76 found in Armada 8K This commits adds a device variant for Safexcel,EIP76 found in Marvell Armada 8k. It defines registers mapping with the good offset and add a specific initialization function. Signed-off-by: Romain Perier Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 2 +- drivers/char/hw_random/omap-rng.c | 86 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 200dab5136a7..ceff2fc524b1 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -168,7 +168,7 @@ config HW_RANDOM_IXP4XX config HW_RANDOM_OMAP tristate "OMAP Random Number Generator support" - depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS + depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index c64a0990feb7..3ad86fdf954e 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -63,6 +64,7 @@ #define OMAP2_RNG_OUTPUT_SIZE 0x4 #define OMAP4_RNG_OUTPUT_SIZE 0x8 +#define EIP76_RNG_OUTPUT_SIZE 0x10 enum { RNG_OUTPUT_0_REG = 0, @@ -108,6 +110,23 @@ static const u16 reg_map_omap4[] = { [RNG_SYSCONFIG_REG] = 0x1FE4, }; +static const u16 reg_map_eip76[] = { + [RNG_OUTPUT_0_REG] = 0x0, + [RNG_OUTPUT_1_REG] = 0x4, + [RNG_OUTPUT_2_REG] = 0x8, + [RNG_OUTPUT_3_REG] = 0xc, + [RNG_STATUS_REG] = 0x10, + [RNG_INTACK_REG] = 0x10, + [RNG_CONTROL_REG] = 0x14, + [RNG_CONFIG_REG] = 0x18, + [RNG_ALARMCNT_REG] = 0x1c, + [RNG_FROENABLE_REG] = 0x20, + [RNG_FRODETUNE_REG] = 0x24, + [RNG_ALARMMASK_REG] = 0x28, + [RNG_ALARMSTOP_REG] = 0x2c, + [RNG_REV_REG] = 0x7c, +}; + struct omap_rng_dev; /** * struct omap_rng_pdata - RNG IP block-specific data @@ -130,6 +149,7 @@ struct omap_rng_dev { struct device *dev; const struct omap_rng_pdata *pdata; struct hwrng rng; + struct clk *clk; }; static inline u32 omap_rng_read(struct omap_rng_dev *priv, u16 reg) @@ -221,6 +241,38 @@ static inline u32 omap4_rng_data_present(struct omap_rng_dev *priv) return omap_rng_read(priv, RNG_STATUS_REG) & RNG_REG_STATUS_RDY; } +static int eip76_rng_init(struct omap_rng_dev *priv) +{ + u32 val; + + /* Return if RNG is already running. */ + if (omap_rng_read(priv, RNG_CONTROL_REG) & RNG_CONTROL_ENABLE_TRNG_MASK) + return 0; + + /* Number of 512 bit blocks of raw Noise Source output data that must + * be processed by either the Conditioning Function or the + * SP 800-90 DRBG ‘BC_DF’ functionality to yield a ‘full entropy’ + * output value. + */ + val = 0x5 << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; + + /* Number of FRO samples that are XOR-ed together into one bit to be + * shifted into the main shift register + */ + val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT; + omap_rng_write(priv, RNG_CONFIG_REG, val); + + /* Enable all available FROs */ + omap_rng_write(priv, RNG_FRODETUNE_REG, 0x0); + omap_rng_write(priv, RNG_FROENABLE_REG, RNG_REG_FROENABLE_MASK); + + /* Enable TRNG */ + val = RNG_CONTROL_ENABLE_TRNG_MASK; + omap_rng_write(priv, RNG_CONTROL_REG, val); + + return 0; +} + static int omap4_rng_init(struct omap_rng_dev *priv) { u32 val; @@ -290,6 +342,14 @@ static struct omap_rng_pdata omap4_rng_pdata = { .cleanup = omap4_rng_cleanup, }; +static struct omap_rng_pdata eip76_rng_pdata = { + .regs = (u16 *)reg_map_eip76, + .data_size = EIP76_RNG_OUTPUT_SIZE, + .data_present = omap4_rng_data_present, + .init = eip76_rng_init, + .cleanup = omap4_rng_cleanup, +}; + static const struct of_device_id omap_rng_of_match[] = { { .compatible = "ti,omap2-rng", @@ -299,6 +359,10 @@ static const struct of_device_id omap_rng_of_match[] = { .compatible = "ti,omap4-rng", .data = &omap4_rng_pdata, }, + { + .compatible = "inside-secure,safexcel-eip76", + .data = &eip76_rng_pdata, + }, {}, }; MODULE_DEVICE_TABLE(of, omap_rng_of_match); @@ -317,7 +381,8 @@ static int of_get_omap_rng_device_details(struct omap_rng_dev *priv, } priv->pdata = match->data; - if (of_device_is_compatible(dev->of_node, "ti,omap4-rng")) { + if (of_device_is_compatible(dev->of_node, "ti,omap4-rng") || + of_device_is_compatible(dev->of_node, "inside-secure,safexcel-eip76")) { irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "%s: error getting IRQ resource - %d\n", @@ -333,6 +398,16 @@ static int of_get_omap_rng_device_details(struct omap_rng_dev *priv, return err; } omap_rng_write(priv, RNG_INTMASK_REG, RNG_SHUTDOWN_OFLO_MASK); + + priv->clk = of_clk_get(pdev->dev.of_node, 0); + if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (!IS_ERR(priv->clk)) { + err = clk_prepare_enable(priv->clk); + if (err) + dev_err(&pdev->dev, "unable to enable the clk, " + "err = %d\n", err); + } } return 0; } @@ -394,7 +469,7 @@ static int omap_rng_probe(struct platform_device *pdev) ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) : get_omap_rng_device_details(priv); if (ret) - goto err_ioremap; + goto err_register; ret = hwrng_register(&priv->rng); if (ret) @@ -407,7 +482,11 @@ static int omap_rng_probe(struct platform_device *pdev) err_register: priv->base = NULL; + pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); + + if (!IS_ERR(priv->clk)) + clk_disable_unprepare(priv->clk); err_ioremap: dev_err(dev, "initialization failed.\n"); return ret; @@ -424,6 +503,9 @@ static int omap_rng_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); + if (!IS_ERR(priv->clk)) + clk_disable_unprepare(priv->clk); + return 0; } -- cgit v1.2.3 From f709dc86bc4f9d8c320ceb9a12ac304756129dd5 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Thu, 29 Sep 2016 18:46:57 +0200 Subject: crypto: atmel-aes - fix compiler error when VERBOSE_DEBUG is defined This patch fixes a compiler error when VERBOSE_DEBUG is defined. Indeed, in atmel_aes_write(), the 3rd argument of atmel_aes_reg_name() was missing. Signed-off-by: Cyrille Pitchen Reported-by: Levent Demir Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index e3d40a8dfffb..1d9e7bd3f377 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -317,7 +317,7 @@ static inline void atmel_aes_write(struct atmel_aes_dev *dd, char tmp[16]; dev_vdbg(dd->dev, "write 0x%08x into %s\n", value, - atmel_aes_reg_name(offset, tmp)); + atmel_aes_reg_name(offset, tmp, sizeof(tmp))); } #endif /* VERBOSE_DEBUG */ -- cgit v1.2.3 From d52db5188a87dcdf8e5bf024f45543b362a1a85f Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Mon, 3 Oct 2016 14:33:16 +0200 Subject: crypto: atmel-aes - add support to the XTS mode This patch adds the xts(aes) algorithm, which is supported from hardware version 0x500 and above (sama5d2x). Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes-regs.h | 4 + drivers/crypto/atmel-aes.c | 185 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 183 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h index 6c2951bb70b1..0ec04407b533 100644 --- a/drivers/crypto/atmel-aes-regs.h +++ b/drivers/crypto/atmel-aes-regs.h @@ -28,6 +28,7 @@ #define AES_MR_OPMOD_CFB (0x3 << 12) #define AES_MR_OPMOD_CTR (0x4 << 12) #define AES_MR_OPMOD_GCM (0x5 << 12) +#define AES_MR_OPMOD_XTS (0x6 << 12) #define AES_MR_LOD (0x1 << 15) #define AES_MR_CFBS_MASK (0x7 << 16) #define AES_MR_CFBS_128b (0x0 << 16) @@ -67,6 +68,9 @@ #define AES_CTRR 0x98 #define AES_GCMHR(x) (0x9c + ((x) * 0x04)) +#define AES_TWR(x) (0xc0 + ((x) * 0x04)) +#define AES_ALPHAR(x) (0xd0 + ((x) * 0x04)) + #define AES_HW_VERSION 0xFC #endif /* __ATMEL_AES_REGS_H__ */ diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 1d9e7bd3f377..6b656f4a9378 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,7 @@ #define AES_FLAGS_CFB8 (AES_MR_OPMOD_CFB | AES_MR_CFBS_8b) #define AES_FLAGS_CTR AES_MR_OPMOD_CTR #define AES_FLAGS_GCM AES_MR_OPMOD_GCM +#define AES_FLAGS_XTS AES_MR_OPMOD_XTS #define AES_FLAGS_MODE_MASK (AES_FLAGS_OPMODE_MASK | \ AES_FLAGS_ENCRYPT | \ @@ -89,6 +91,7 @@ struct atmel_aes_caps { bool has_cfb64; bool has_ctr32; bool has_gcm; + bool has_xts; u32 max_burst_size; }; @@ -135,6 +138,12 @@ struct atmel_aes_gcm_ctx { atmel_aes_fn_t ghash_resume; }; +struct atmel_aes_xts_ctx { + struct atmel_aes_base_ctx base; + + u32 key2[AES_KEYSIZE_256 / sizeof(u32)]; +}; + struct atmel_aes_reqctx { unsigned long mode; }; @@ -282,6 +291,20 @@ static const char *atmel_aes_reg_name(u32 offset, char *tmp, size_t sz) snprintf(tmp, sz, "GCMHR[%u]", (offset - AES_GCMHR(0)) >> 2); break; + case AES_TWR(0): + case AES_TWR(1): + case AES_TWR(2): + case AES_TWR(3): + snprintf(tmp, sz, "TWR[%u]", (offset - AES_TWR(0)) >> 2); + break; + + case AES_ALPHAR(0): + case AES_ALPHAR(1): + case AES_ALPHAR(2): + case AES_ALPHAR(3): + snprintf(tmp, sz, "ALPHAR[%u]", (offset - AES_ALPHAR(0)) >> 2); + break; + default: snprintf(tmp, sz, "0x%02x", offset); break; @@ -453,15 +476,15 @@ static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err) return err; } -static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma, - const u32 *iv) +static void atmel_aes_write_ctrl_key(struct atmel_aes_dev *dd, bool use_dma, + const u32 *iv, const u32 *key, int keylen) { u32 valmr = 0; /* MR register must be set before IV registers */ - if (dd->ctx->keylen == AES_KEYSIZE_128) + if (keylen == AES_KEYSIZE_128) valmr |= AES_MR_KEYSIZE_128; - else if (dd->ctx->keylen == AES_KEYSIZE_192) + else if (keylen == AES_KEYSIZE_192) valmr |= AES_MR_KEYSIZE_192; else valmr |= AES_MR_KEYSIZE_256; @@ -478,13 +501,19 @@ static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma, atmel_aes_write(dd, AES_MR, valmr); - atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key, - SIZE_IN_WORDS(dd->ctx->keylen)); + atmel_aes_write_n(dd, AES_KEYWR(0), key, SIZE_IN_WORDS(keylen)); if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB) atmel_aes_write_block(dd, AES_IVR(0), iv); } +static inline void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma, + const u32 *iv) + +{ + atmel_aes_write_ctrl_key(dd, use_dma, iv, + dd->ctx->key, dd->ctx->keylen); +} /* CPU transfer */ @@ -1769,6 +1798,137 @@ static struct aead_alg aes_gcm_alg = { }; +/* xts functions */ + +static inline struct atmel_aes_xts_ctx * +atmel_aes_xts_ctx_cast(struct atmel_aes_base_ctx *ctx) +{ + return container_of(ctx, struct atmel_aes_xts_ctx, base); +} + +static int atmel_aes_xts_process_data(struct atmel_aes_dev *dd); + +static int atmel_aes_xts_start(struct atmel_aes_dev *dd) +{ + struct atmel_aes_xts_ctx *ctx = atmel_aes_xts_ctx_cast(dd->ctx); + struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq); + struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req); + unsigned long flags; + int err; + + atmel_aes_set_mode(dd, rctx); + + err = atmel_aes_hw_init(dd); + if (err) + return atmel_aes_complete(dd, err); + + /* Compute the tweak value from req->info with ecb(aes). */ + flags = dd->flags; + dd->flags &= ~AES_FLAGS_MODE_MASK; + dd->flags |= (AES_FLAGS_ECB | AES_FLAGS_ENCRYPT); + atmel_aes_write_ctrl_key(dd, false, NULL, + ctx->key2, ctx->base.keylen); + dd->flags = flags; + + atmel_aes_write_block(dd, AES_IDATAR(0), req->info); + return atmel_aes_wait_for_data_ready(dd, atmel_aes_xts_process_data); +} + +static int atmel_aes_xts_process_data(struct atmel_aes_dev *dd) +{ + struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq); + bool use_dma = (req->nbytes >= ATMEL_AES_DMA_THRESHOLD); + u32 tweak[AES_BLOCK_SIZE / sizeof(u32)]; + static const u32 one[AES_BLOCK_SIZE / sizeof(u32)] = {cpu_to_le32(1), }; + u8 *tweak_bytes = (u8 *)tweak; + int i; + + /* Read the computed ciphered tweak value. */ + atmel_aes_read_block(dd, AES_ODATAR(0), tweak); + /* + * Hardware quirk: + * the order of the ciphered tweak bytes need to be reversed before + * writing them into the ODATARx registers. + */ + for (i = 0; i < AES_BLOCK_SIZE/2; ++i) { + u8 tmp = tweak_bytes[AES_BLOCK_SIZE - 1 - i]; + + tweak_bytes[AES_BLOCK_SIZE - 1 - i] = tweak_bytes[i]; + tweak_bytes[i] = tmp; + } + + /* Process the data. */ + atmel_aes_write_ctrl(dd, use_dma, NULL); + atmel_aes_write_block(dd, AES_TWR(0), tweak); + atmel_aes_write_block(dd, AES_ALPHAR(0), one); + if (use_dma) + return atmel_aes_dma_start(dd, req->src, req->dst, req->nbytes, + atmel_aes_transfer_complete); + + return atmel_aes_cpu_start(dd, req->src, req->dst, req->nbytes, + atmel_aes_transfer_complete); +} + +static int atmel_aes_xts_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct atmel_aes_xts_ctx *ctx = crypto_ablkcipher_ctx(tfm); + int err; + + err = xts_check_key(crypto_ablkcipher_tfm(tfm), key, keylen); + if (err) + return err; + + memcpy(ctx->base.key, key, keylen/2); + memcpy(ctx->key2, key + keylen/2, keylen/2); + ctx->base.keylen = keylen/2; + + return 0; +} + +static int atmel_aes_xts_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, AES_FLAGS_XTS | AES_FLAGS_ENCRYPT); +} + +static int atmel_aes_xts_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, AES_FLAGS_XTS); +} + +static int atmel_aes_xts_cra_init(struct crypto_tfm *tfm) +{ + struct atmel_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm); + + tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_aes_reqctx); + ctx->base.start = atmel_aes_xts_start; + + return 0; +} + +static struct crypto_alg aes_xts_alg = { + .cra_name = "xts(aes)", + .cra_driver_name = "atmel-xts-aes", + .cra_priority = ATMEL_AES_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_xts_ctx), + .cra_alignmask = 0xf, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_xts_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2 * AES_MIN_KEY_SIZE, + .max_keysize = 2 * AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_xts_setkey, + .encrypt = atmel_aes_xts_encrypt, + .decrypt = atmel_aes_xts_decrypt, + } +}; + + /* Probe functions */ static int atmel_aes_buff_init(struct atmel_aes_dev *dd) @@ -1877,6 +2037,9 @@ static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd) { int i; + if (dd->caps.has_xts) + crypto_unregister_alg(&aes_xts_alg); + if (dd->caps.has_gcm) crypto_unregister_aead(&aes_gcm_alg); @@ -1909,8 +2072,16 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd) goto err_aes_gcm_alg; } + if (dd->caps.has_xts) { + err = crypto_register_alg(&aes_xts_alg); + if (err) + goto err_aes_xts_alg; + } + return 0; +err_aes_xts_alg: + crypto_unregister_aead(&aes_gcm_alg); err_aes_gcm_alg: crypto_unregister_alg(&aes_cfb64_alg); err_aes_cfb64_alg: @@ -1928,6 +2099,7 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd) dd->caps.has_cfb64 = 0; dd->caps.has_ctr32 = 0; dd->caps.has_gcm = 0; + dd->caps.has_xts = 0; dd->caps.max_burst_size = 1; /* keep only major version number */ @@ -1937,6 +2109,7 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd) dd->caps.has_cfb64 = 1; dd->caps.has_ctr32 = 1; dd->caps.has_gcm = 1; + dd->caps.has_xts = 1; dd->caps.max_burst_size = 4; break; case 0x200: -- cgit v1.2.3 From 0c99620f0ac13a51f2f78cf62e6b551a09f8b1f1 Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Wed, 5 Oct 2016 09:56:32 +0200 Subject: crypto: marvell - Use an unique pool to copy results of requests So far, we used a dedicated dma pool to copy the result of outer IV for cipher requests. Instead of using a dma pool per outer data, we prefer use the op dma pool that contains all part of the request from the SRAM. Then, the outer data that is likely to be used by the 'complete' operation, is copied later. In this way, any type of result can be retrieved by DMA for cipher or ahash requests. Signed-off-by: Romain Perier Acked-by: Boris Brezillon Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa.c | 4 ---- drivers/crypto/marvell/cesa.h | 5 ++--- drivers/crypto/marvell/cipher.c | 8 +++++--- drivers/crypto/marvell/tdma.c | 33 +++++++++++++++++++-------------- 4 files changed, 26 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c index 37dadb2a4feb..6e7a5c77a00a 100644 --- a/drivers/crypto/marvell/cesa.c +++ b/drivers/crypto/marvell/cesa.c @@ -375,10 +375,6 @@ static int mv_cesa_dev_dma_init(struct mv_cesa_dev *cesa) if (!dma->padding_pool) return -ENOMEM; - dma->iv_pool = dmam_pool_create("cesa_iv", dev, 16, 1, 0); - if (!dma->iv_pool) - return -ENOMEM; - cesa->dma = dma; return 0; diff --git a/drivers/crypto/marvell/cesa.h b/drivers/crypto/marvell/cesa.h index e423d33decd4..a768da7138a1 100644 --- a/drivers/crypto/marvell/cesa.h +++ b/drivers/crypto/marvell/cesa.h @@ -277,7 +277,7 @@ struct mv_cesa_op_ctx { #define CESA_TDMA_DUMMY 0 #define CESA_TDMA_DATA 1 #define CESA_TDMA_OP 2 -#define CESA_TDMA_IV 3 +#define CESA_TDMA_RESULT 3 /** * struct mv_cesa_tdma_desc - TDMA descriptor @@ -393,7 +393,6 @@ struct mv_cesa_dev_dma { struct dma_pool *op_pool; struct dma_pool *cache_pool; struct dma_pool *padding_pool; - struct dma_pool *iv_pool; }; /** @@ -839,7 +838,7 @@ mv_cesa_tdma_desc_iter_init(struct mv_cesa_tdma_chain *chain) memset(chain, 0, sizeof(*chain)); } -int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src, +int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src, u32 size, u32 flags, gfp_t gfp_flags); struct mv_cesa_op_ctx *mv_cesa_dma_add_op(struct mv_cesa_tdma_chain *chain, diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c index d19dc9614e6e..098871a22a54 100644 --- a/drivers/crypto/marvell/cipher.c +++ b/drivers/crypto/marvell/cipher.c @@ -212,7 +212,8 @@ mv_cesa_ablkcipher_complete(struct crypto_async_request *req) struct mv_cesa_req *basereq; basereq = &creq->base; - memcpy(ablkreq->info, basereq->chain.last->data, ivsize); + memcpy(ablkreq->info, basereq->chain.last->op->ctx.blkcipher.iv, + ivsize); } else { memcpy_fromio(ablkreq->info, engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET, @@ -373,8 +374,9 @@ static int mv_cesa_ablkcipher_dma_req_init(struct ablkcipher_request *req, /* Add output data for IV */ ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req)); - ret = mv_cesa_dma_add_iv_op(&basereq->chain, CESA_SA_CRYPT_IV_SRAM_OFFSET, - ivsize, CESA_TDMA_SRC_IN_SRAM, flags); + ret = mv_cesa_dma_add_result_op(&basereq->chain, CESA_SA_CFG_SRAM_OFFSET, + CESA_SA_DATA_SRAM_OFFSET, + CESA_TDMA_SRC_IN_SRAM, flags); if (ret) goto err_free_tdma; diff --git a/drivers/crypto/marvell/tdma.c b/drivers/crypto/marvell/tdma.c index 9fd7a5fbaa1b..4416b88eca70 100644 --- a/drivers/crypto/marvell/tdma.c +++ b/drivers/crypto/marvell/tdma.c @@ -69,9 +69,6 @@ void mv_cesa_dma_cleanup(struct mv_cesa_req *dreq) if (type == CESA_TDMA_OP) dma_pool_free(cesa_dev->dma->op_pool, tdma->op, le32_to_cpu(tdma->src)); - else if (type == CESA_TDMA_IV) - dma_pool_free(cesa_dev->dma->iv_pool, tdma->data, - le32_to_cpu(tdma->dst)); tdma = tdma->next; dma_pool_free(cesa_dev->dma->tdma_desc_pool, old_tdma, @@ -209,29 +206,37 @@ mv_cesa_dma_add_desc(struct mv_cesa_tdma_chain *chain, gfp_t flags) return new_tdma; } -int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src, +int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src, u32 size, u32 flags, gfp_t gfp_flags) { - - struct mv_cesa_tdma_desc *tdma; - u8 *iv; - dma_addr_t dma_handle; + struct mv_cesa_tdma_desc *tdma, *op_desc; tdma = mv_cesa_dma_add_desc(chain, gfp_flags); if (IS_ERR(tdma)) return PTR_ERR(tdma); - iv = dma_pool_alloc(cesa_dev->dma->iv_pool, gfp_flags, &dma_handle); - if (!iv) - return -ENOMEM; + /* We re-use an existing op_desc object to retrieve the context + * and result instead of allocating a new one. + * There is at least one object of this type in a CESA crypto + * req, just pick the first one in the chain. + */ + for (op_desc = chain->first; op_desc; op_desc = op_desc->next) { + u32 type = op_desc->flags & CESA_TDMA_TYPE_MSK; + + if (type == CESA_TDMA_OP) + break; + } + + if (!op_desc) + return -EIO; tdma->byte_cnt = cpu_to_le32(size | BIT(31)); tdma->src = src; - tdma->dst = cpu_to_le32(dma_handle); - tdma->data = iv; + tdma->dst = op_desc->src; + tdma->op = op_desc->op; flags &= (CESA_TDMA_DST_IN_SRAM | CESA_TDMA_SRC_IN_SRAM); - tdma->flags = flags | CESA_TDMA_IV; + tdma->flags = flags | CESA_TDMA_RESULT; return 0; } -- cgit v1.2.3 From f34dad1721642989336283c9e6c3b8f6b23fa67c Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Wed, 5 Oct 2016 09:56:33 +0200 Subject: crypto: marvell - Don't break chain for computable last ahash requests Currently, the driver breaks chain for all kind of hash requests in order to don't override intermediate states of partial ahash updates. However, some final ahash requests can be directly processed by the engine, and so without intermediate state. This is typically the case for most for the HMAC requests processed via IPSec. This commits adds a TDMA descriptor to copy context for these of requests into the "op" dma pool, then it allow to chain these requests at the DMA level. The 'complete' operation is also updated to retrieve the MAC digest from the right location. Signed-off-by: Romain Perier Acked-by: Boris Brezillon Signed-off-by: Herbert Xu --- drivers/crypto/marvell/hash.c | 65 ++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c index 9f284682c091..2a9260559654 100644 --- a/drivers/crypto/marvell/hash.c +++ b/drivers/crypto/marvell/hash.c @@ -312,24 +312,40 @@ static void mv_cesa_ahash_complete(struct crypto_async_request *req) int i; digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq)); - for (i = 0; i < digsize / 4; i++) - creq->state[i] = readl_relaxed(engine->regs + CESA_IVDIG(i)); - if (creq->last_req) { + if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ && + (creq->base.chain.last->flags & CESA_TDMA_TYPE_MSK) == CESA_TDMA_RESULT) { + __le32 *data = NULL; + /* - * Hardware's MD5 digest is in little endian format, but - * SHA in big endian format + * Result is already in the correct endianess when the SA is + * used */ - if (creq->algo_le) { - __le32 *result = (void *)ahashreq->result; + data = creq->base.chain.last->op->ctx.hash.hash; + for (i = 0; i < digsize / 4; i++) + creq->state[i] = cpu_to_le32(data[i]); - for (i = 0; i < digsize / 4; i++) - result[i] = cpu_to_le32(creq->state[i]); - } else { - __be32 *result = (void *)ahashreq->result; + memcpy(ahashreq->result, data, digsize); + } else { + for (i = 0; i < digsize / 4; i++) + creq->state[i] = readl_relaxed(engine->regs + + CESA_IVDIG(i)); + if (creq->last_req) { + /* + * Hardware's MD5 digest is in little endian format, but + * SHA in big endian format + */ + if (creq->algo_le) { + __le32 *result = (void *)ahashreq->result; + + for (i = 0; i < digsize / 4; i++) + result[i] = cpu_to_le32(creq->state[i]); + } else { + __be32 *result = (void *)ahashreq->result; - for (i = 0; i < digsize / 4; i++) - result[i] = cpu_to_be32(creq->state[i]); + for (i = 0; i < digsize / 4; i++) + result[i] = cpu_to_be32(creq->state[i]); + } } } @@ -504,6 +520,12 @@ mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain, CESA_SA_DESC_CFG_LAST_FRAG, CESA_SA_DESC_CFG_FRAG_MSK); + ret = mv_cesa_dma_add_result_op(chain, + CESA_SA_CFG_SRAM_OFFSET, + CESA_SA_DATA_SRAM_OFFSET, + CESA_TDMA_SRC_IN_SRAM, flags); + if (ret) + return ERR_PTR(-ENOMEM); return op; } @@ -564,6 +586,7 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req) struct mv_cesa_op_ctx *op = NULL; unsigned int frag_len; int ret; + u32 type; basereq->chain.first = NULL; basereq->chain.last = NULL; @@ -635,7 +658,15 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req) goto err_free_tdma; } - if (op) { + /* + * If results are copied via DMA, this means that this + * request can be directly processed by the engine, + * without partial updates. So we can chain it at the + * DMA level with other requests. + */ + type = basereq->chain.last->flags & CESA_TDMA_TYPE_MSK; + + if (op && type != CESA_TDMA_RESULT) { /* Add dummy desc to wait for crypto operation end */ ret = mv_cesa_dma_add_dummy_end(&basereq->chain, flags); if (ret) @@ -648,8 +679,10 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req) else creq->cache_ptr = 0; - basereq->chain.last->flags |= (CESA_TDMA_END_OF_REQ | - CESA_TDMA_BREAK_CHAIN); + basereq->chain.last->flags |= CESA_TDMA_END_OF_REQ; + + if (type != CESA_TDMA_RESULT) + basereq->chain.last->flags |= CESA_TDMA_BREAK_CHAIN; return 0; -- cgit v1.2.3 From 4c36941aee7f9bb3a1183ba89aa15b86622c8668 Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Fri, 7 Oct 2016 22:36:20 +0200 Subject: crypto: crypto4xx - Fix size used in dma_free_coherent() The size used in 'dma_free_coherent()' looks un-initialized here. ctx->sa_len is set a few lines below and is apparently not set by the caller. So use 'size' as in the corresponding 'dma_alloc_coherent()' a few lines above. This has been spotted with coccinelle, using the following script: //////////////////// @r@ expression x0, x1, y0, y1, z0, z1, t0, t1, ret; @@ * ret = dma_alloc_coherent(x0, y0, z0, t0); ... * dma_free_coherent(x1, y1, ret, t1); @script:python@ y0 << r.y0; y1 << r.y1; @@ if y1.find(y0) == -1: print "WARNING: sizes look different: '%s' vs '%s'" % (y0, y1) //////////////////// Signed-off-by: Christophe JAILLET Signed-off-by: Herbert Xu --- drivers/crypto/amcc/crypto4xx_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index dae1e39139e9..d10b4ae5e0da 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -135,8 +135,7 @@ int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size) ctx->sa_out = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4, &ctx->sa_out_dma_addr, GFP_ATOMIC); if (ctx->sa_out == NULL) { - dma_free_coherent(ctx->dev->core_dev->device, - ctx->sa_len * 4, + dma_free_coherent(ctx->dev->core_dev->device, size * 4, ctx->sa_in, ctx->sa_in_dma_addr); return -ENOMEM; } -- cgit v1.2.3 From 3cf799680d2612a21d50ed554848dd37241672c8 Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Wed, 12 Oct 2016 08:47:03 -0500 Subject: crypto: ccp - change type of struct member lsb to signed The lsb field uses a value of -1 to indicate that it is unassigned. Therefore type must be a signed int. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index da5f4a678083..5afaa53672b3 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -278,7 +278,7 @@ struct ccp_cmd_queue { /* Private LSB that is assigned to this queue, or -1 if none. * Bitmap for my private LSB, unused otherwise */ - unsigned int lsb; + int lsb; DECLARE_BITMAP(lsbmap, PLSB_MAP_SIZE); /* Queue processing thread */ -- cgit v1.2.3 From c699995663b40d61afcc14ca27f0106f13151772 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 10 Sep 2016 09:55:49 +0800 Subject: pwm: meson: Add missing spin_lock_init() The driver uses the spin_lock but does not initialize it. Fix it. Signed-off-by: Axel Lin Acked-by: Neil Armstrong Signed-off-by: Thierry Reding --- drivers/pwm/pwm-meson.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 381871b2bb46..9d5bd7d5c610 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -474,6 +474,7 @@ static int meson_pwm_probe(struct platform_device *pdev) if (IS_ERR(meson->base)) return PTR_ERR(meson->base); + spin_lock_init(&meson->lock); meson->chip.dev = &pdev->dev; meson->chip.ops = &meson_pwm_ops; meson->chip.base = -1; -- cgit v1.2.3 From 58d5b693637d9963018bcb92fecf858e6899ed49 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 19 Oct 2016 16:49:59 -0300 Subject: pwm: meson: Remove unneeded platform MODULE_ALIAS The Amlogic Meson is a DT-only platform, which means the devices are registered via OF and not using the legacy platform devices support. So there's no need to have a MODULE_ALIAS("platform:meson-pwm") since the reported uevent MODALIAS to user-space will always be the OF one. Signed-off-by: Javier Martinez Canillas Acked-by: Kevin Hilman Signed-off-by: Thierry Reding --- drivers/pwm/pwm-meson.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 381871b2bb46..5678092cad4b 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -523,7 +523,6 @@ static struct platform_driver meson_pwm_driver = { }; module_platform_driver(meson_pwm_driver); -MODULE_ALIAS("platform:meson-pwm"); MODULE_DESCRIPTION("Amlogic Meson PWM Generator driver"); MODULE_AUTHOR("Neil Armstrong "); MODULE_LICENSE("Dual BSD/GPL"); -- cgit v1.2.3 From 5c1c63f6345b9e1600875f3122166c0af434158e Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Fri, 21 Oct 2016 12:03:40 +0800 Subject: clk: rockchip: add 533.25MHz to rk3399 clock rates table We need to get the accurate 533.25MHz for the DP display. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 8387c7a40bda..a5a3f412d09a 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -93,6 +93,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0), RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0), + RK3036_PLL_RATE( 533250000, 8, 711, 4, 1, 1, 0), RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), -- cgit v1.2.3 From 8eee6b9dd30d5b20a4c31886057a68bb6a2736c9 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 10 Oct 2016 09:25:24 -0500 Subject: spi: Add Flag to Enable Slave Select with GPIO Chip Select. Some SPI masters require slave selection before the transfer can begin [1]. The SPI framework currently selects the chip using either 1) the internal CS mechanism or 2) the GPIO CS, but not both. This patch adds a new master->flags define to indicate both the GPIO CS and the internal chip select mechanism should be used. Tested On: Altera CycloneV development kit Compile tested for build errors on x86_64 (allyesconfigs) [1] DesignWare dw_apb_ssi Databook, Version 3.20a (page 39) Signed-off-by: Thor Thayer Signed-off-by: Mark Brown --- drivers/spi/spi.c | 9 +++++++-- include/linux/spi/spi.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5787b723b593..cbe15ab5f8a8 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -697,10 +697,15 @@ static void spi_set_cs(struct spi_device *spi, bool enable) if (spi->mode & SPI_CS_HIGH) enable = !enable; - if (gpio_is_valid(spi->cs_gpio)) + if (gpio_is_valid(spi->cs_gpio)) { gpio_set_value(spi->cs_gpio, !enable); - else if (spi->master->set_cs) + /* Some SPI masters need both GPIO CS & slave_select */ + if ((spi->master->flags & SPI_MASTER_GPIO_SS) && + spi->master->set_cs) + spi->master->set_cs(spi, !enable); + } else if (spi->master->set_cs) { spi->master->set_cs(spi, !enable); + } } #ifdef CONFIG_HAS_DMA diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 4b743ac35396..75c6bd0ac605 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -442,6 +442,7 @@ struct spi_master { #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ #define SPI_MASTER_MUST_RX BIT(3) /* requires rx */ #define SPI_MASTER_MUST_TX BIT(4) /* requires tx */ +#define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */ /* * on some hardware transfer / message size may be constrained -- cgit v1.2.3 From b497eb024531b712f9d2c6af0bb55ca558a2674e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 1 Oct 2016 21:07:52 +0200 Subject: spi: fsl-espi: replace of_get_property with of_property_read_u32 of_property_read_u32 is better here than generic of_get_property: - implicit endianness conversion if needed - implicit checking of size of property Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 7451585a080e..1f97cce615d3 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -545,9 +545,8 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, struct spi_master *master; struct mpc8xxx_spi *mpc8xxx_spi; struct device_node *nc; - const __be32 *prop; - u32 regval, csmode; - int i, len, ret; + u32 regval, csmode, cs, prop; + int ret; master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi)); if (!master) @@ -599,29 +598,29 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, /* Init eSPI CS mode register */ for_each_available_child_of_node(master->dev.of_node, nc) { /* get chip select */ - prop = of_get_property(nc, "reg", &len); - if (!prop || len < sizeof(*prop)) - continue; - i = be32_to_cpup(prop); - if (i < 0 || i >= pdata->max_chipselect) + ret = of_property_read_u32(nc, "reg", &cs); + if (ret || cs >= pdata->max_chipselect) continue; csmode = CSMODE_INIT_VAL; + /* check if CSBEF is set in device tree */ - prop = of_get_property(nc, "fsl,csbef", &len); - if (prop && len >= sizeof(*prop)) { + ret = of_property_read_u32(nc, "fsl,csbef", &prop); + if (!ret) { csmode &= ~(CSMODE_BEF(0xf)); - csmode |= CSMODE_BEF(be32_to_cpup(prop)); + csmode |= CSMODE_BEF(prop); } + /* check if CSAFT is set in device tree */ - prop = of_get_property(nc, "fsl,csaft", &len); - if (prop && len >= sizeof(*prop)) { + ret = of_property_read_u32(nc, "fsl,csaft", &prop); + if (!ret) { csmode &= ~(CSMODE_AFT(0xf)); - csmode |= CSMODE_AFT(be32_to_cpup(prop)); + csmode |= CSMODE_AFT(prop); } - fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODEx(i), csmode); - dev_info(dev, "cs=%d, init_csmode=0x%x\n", i, csmode); + fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODEx(cs), csmode); + + dev_info(dev, "cs=%u, init_csmode=0x%x\n", cs, csmode); } /* Enable SPI interface */ @@ -660,16 +659,16 @@ static int of_fsl_espi_get_chipselects(struct device *dev) { struct device_node *np = dev->of_node; struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - const u32 *prop; - int len; + u32 num_cs; + int ret; - prop = of_get_property(np, "fsl,espi-num-chipselects", &len); - if (!prop || len < sizeof(*prop)) { + ret = of_property_read_u32(np, "fsl,espi-num-chipselects", &num_cs); + if (ret) { dev_err(dev, "No 'fsl,espi-num-chipselects' property\n"); return -EINVAL; } - pdata->max_chipselect = *prop; + pdata->max_chipselect = num_cs; pdata->cs_control = NULL; return 0; -- cgit v1.2.3 From e4be7053b9d3aa0a97b311ad77528d8b32236590 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 2 Oct 2016 14:22:35 +0200 Subject: spi: fsl-espi: reject MSB-first transfers with word sizes other than 8 or 16 According to the ESPI spec MSB-first transfers are supported for word size 8 and 16 only. Check for this and reject MSB-first transfers with other word sizes. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 1f97cce615d3..65bb70d3bfc4 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -153,6 +153,7 @@ static int fsl_espi_check_message(struct spi_message *m) first = list_first_entry(&m->transfers, struct spi_transfer, transfer_list); + list_for_each_entry(t, &m->transfers, transfer_list) { if (first->bits_per_word != t->bits_per_word || first->speed_hz != t->speed_hz) { @@ -161,6 +162,15 @@ static int fsl_espi_check_message(struct spi_message *m) } } + /* ESPI supports MSB-first transfers for word size 8 / 16 only */ + if (!(m->spi->mode & SPI_LSB_FIRST) && first->bits_per_word != 8 && + first->bits_per_word != 16) { + dev_err(mspi->dev, + "MSB-first transfer not supported for wordsize %u\n", + first->bits_per_word); + return -EINVAL; + } + return 0; } -- cgit v1.2.3 From 923ab15e1a5ce6248601304440e9f30fbf3bb6ab Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 2 Oct 2016 14:22:57 +0200 Subject: spi: fsl-espi: fix handling of word sizes other than 8 bit The code in fsl_espi_tx_buf_lsb and parts of fsl_espi_setup_transfer look very weird and don't reflect the ESPI spec. ESPI stores values with <= 8 bit word size right justified as 8 bit value and values with > 8 bit word size right justified as 16 bit value. Therefore no such shifting is needed. Only case MSB-first with 8 bit word size is correctly handled, and most likely nobody ever used this driver with a different config. On ESPI only the case LSB-first with word size > 8 bit needs a special handling. In this case a little endian 16 bit value has to be written to the TX FIFO what requires a byte swap as the host system is big endian. The same applies to reading from the RX FIFO. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 84 ++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 65bb70d3bfc4..eea5123abb38 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -112,6 +112,32 @@ static inline void fsl_espi_write_reg8(struct mpc8xxx_spi *mspi, int offset, iowrite8(val, mspi->reg_base + offset); } +static void fsl_espi_memcpy_swab(void *to, const void *from, + struct spi_message *m, + struct spi_transfer *t) +{ + unsigned int len = t->len; + + if (!(m->spi->mode & SPI_LSB_FIRST) || t->bits_per_word <= 8) { + memcpy(to, from, len); + return; + } + + /* In case of LSB-first and bits_per_word > 8 byte-swap all words */ + while (len) + if (len >= 4) { + *(u32 *)to = swahb32p(from); + to += 4; + from += 4; + len -= 4; + } else { + *(u16 *)to = swab16p(from); + to += 2; + from += 2; + len -= 2; + } +} + static void fsl_espi_copy_to_buf(struct spi_message *m, struct mpc8xxx_spi *mspi) { @@ -120,7 +146,7 @@ static void fsl_espi_copy_to_buf(struct spi_message *m, list_for_each_entry(t, &m->transfers, transfer_list) { if (t->tx_buf) - memcpy(buf, t->tx_buf, t->len); + fsl_espi_memcpy_swab(buf, t->tx_buf, m, t); else memset(buf, 0, t->len); buf += t->len; @@ -135,7 +161,7 @@ static void fsl_espi_copy_from_buf(struct spi_message *m, list_for_each_entry(t, &m->transfers, transfer_list) { if (t->rx_buf) - memcpy(t->rx_buf, buf, t->len); + fsl_espi_memcpy_swab(t->rx_buf, buf, m, t); buf += t->len; } } @@ -194,27 +220,6 @@ static void fsl_espi_change_mode(struct spi_device *spi) local_irq_restore(flags); } -static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi) -{ - u32 data; - u16 data_h; - u16 data_l; - const u32 *tx = mpc8xxx_spi->tx; - - if (!tx) - return 0; - - data = *tx++ << mpc8xxx_spi->tx_shift; - data_l = data & 0xffff; - data_h = (data >> 16) & 0xffff; - swab16s(&data_l); - swab16s(&data_h); - data = data_h | data_l; - - mpc8xxx_spi->tx = tx; - return data; -} - static void fsl_espi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { @@ -224,23 +229,6 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, u8 pm; struct spi_mpc8xxx_cs *cs = spi->controller_state; - cs->rx_shift = 0; - cs->tx_shift = 0; - cs->get_rx = mpc8xxx_spi_rx_buf_u32; - cs->get_tx = mpc8xxx_spi_tx_buf_u32; - if (bits_per_word <= 8) { - cs->rx_shift = 8 - bits_per_word; - } else { - cs->rx_shift = 16 - bits_per_word; - if (spi->mode & SPI_LSB_FIRST) - cs->get_tx = fsl_espi_tx_buf_lsb; - } - - mpc8xxx_spi->rx_shift = cs->rx_shift; - mpc8xxx_spi->tx_shift = cs->tx_shift; - mpc8xxx_spi->get_rx = cs->get_rx; - mpc8xxx_spi->get_tx = cs->get_tx; - /* mask out bits we are going to set */ cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF)); @@ -271,7 +259,6 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) { struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); - u32 word; int ret; mpc8xxx_spi->len = t->len; @@ -290,8 +277,8 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, SPIM_RNE); /* transmit word */ - word = mpc8xxx_spi->get_tx(mpc8xxx_spi); - fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPITF, word); + fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPITF, *(u32 *)mpc8xxx_spi->tx); + mpc8xxx_spi->tx += 4; /* Won't hang up forever, SPI bus sometimes got lost interrupts... */ ret = wait_for_completion_timeout(&mpc8xxx_spi->done, 2 * HZ); @@ -468,8 +455,10 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) mspi->len -= rx_nr_bytes; - if (mspi->rx) - mspi->get_rx(rx_data, mspi); + if (mspi->rx) { + *(u32 *)mspi->rx = rx_data; + mspi->rx += 4; + } } if (!(events & SPIE_TNF)) { @@ -487,9 +476,8 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) mspi->count -= 1; if (mspi->count) { - u32 word = mspi->get_tx(mspi); - - fsl_espi_write_reg(mspi, ESPI_SPITF, word); + fsl_espi_write_reg(mspi, ESPI_SPITF, *(u32 *)mspi->tx); + mspi->tx += 4; } else { complete(&mspi->done); } -- cgit v1.2.3 From af9e53fef7015e1e4fe3f32b35e839df392bf4d6 Mon Sep 17 00:00:00 2001 From: Vikram N Date: Fri, 30 Sep 2016 19:53:11 +0530 Subject: spi: omap2-mcspi: Fix modifying platform resource data currently during probe the resource data gets modified and device physical address remains valid only during first load. If the module is unloaded and loaded again, the ioremp will be done on a incorrect address as the resource was modified during previous module load. This patch fixes this issue. Signed-off-by: Vikram N Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index d5157b2222ce..3567e1dfd30d 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1391,15 +1391,13 @@ static int omap2_mcspi_probe(struct platform_device *pdev) goto free_master; } - r->start += regs_offset; - r->end += regs_offset; - mcspi->phys = r->start; - mcspi->base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(mcspi->base)) { status = PTR_ERR(mcspi->base); goto free_master; } + mcspi->phys = r->start + regs_offset; + mcspi->base += regs_offset; mcspi->dev = &pdev->dev; -- cgit v1.2.3 From 144235ea752b4d56d66fe03bb6b7fae7e0032404 Mon Sep 17 00:00:00 2001 From: Fabien Lahoudere Date: Thu, 6 Oct 2016 16:44:27 +0200 Subject: spi: spidev: Add device to spidev device tree compatibility list Entries are needed in the spidev ID list to configure configure it from a device tree. Add entry for the following device: - "ge,achc" : GE Healthcare USB Management Controller The USB Management Controller does not expose USB to the host, but acts as an offload engine, communicating with specific USB based data acquisition devices which are connected to it, extracting the required data and providing it to the host via other methods. SPI is used as an out-of-band configuration channel. Signed-off-by: Fabien Lahoudere Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 2e05046f866b..9e2e099baf8c 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -696,6 +696,7 @@ static struct class *spidev_class; static const struct of_device_id spidev_dt_ids[] = { { .compatible = "rohm,dh2228fv" }, { .compatible = "lineartechnology,ltc2488" }, + { .compatible = "ge,achc" }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); -- cgit v1.2.3 From 465418c6064c88d4af555abe0480c417eb47eae3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Hiler Date: Thu, 20 Oct 2016 17:31:00 +0200 Subject: drm/i915/gen9: Remove WaEnableYV12BugFixInHalfSliceChicken7 Dropping WA because it was for early steppings. It is fixed in newer preproduction and all production revisions. v2: add references, updated commit message References: HSD#2126385, HSD#2131381, BSID#0764 Cc: Mika Kuoppala Cc: Chris Wilson Cc: Michal Winiarski Signed-off-by: Arkadiusz Hiler Reviewed-by: Mika Kuoppala Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1476977460-28088-1-git-send-email-arkadiusz.hiler@intel.com --- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e107455b0168..32786ba199b9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -849,10 +849,8 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) */ } - /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */ /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, - GEN9_ENABLE_YV12_BUGFIX | GEN9_ENABLE_GPGPU_PREEMPTION); /* Wa4x4STCOptimizationDisable:skl,bxt,kbl */ -- cgit v1.2.3 From 8f7ce038f1178057733b7e765bf9160a2f9be14b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 11 Oct 2016 20:52:45 +0300 Subject: drm/i915: Respect alternate_aux_channel for all DDI ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VBT provides the platform a way to mix and match the DDI ports vs. AUX channels. Currently we only trust the VBT for DDI E, which has no corresponding AUX channel of its own. However it is possible that some board might use some non-standard DDI vs. AUX port routing even for the other ports. Perhaps for signal routing reasons or something, So let's generalize this and trust the VBT for all ports. For now we'll limit this to DDI platforms, as we trust the VBT a bit more there anyway when it comes to the DDI ports. I've structured the code in a way that would allow us to easily expand this to other platforms as well, by simply filling in the ddi_port_info. v2: Drop whitespace changes, keep MISSING_CASE() for unknown aux ch assignment, include a commit message, include debug message during init Cc: stable@vger.kernel.org Cc: Maarten Maathuis Tested-by: Maarten Maathuis References: https://bugs.freedesktop.org/show_bug.cgi?id=97877 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1476208368-5710-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jim Bride --- drivers/gpu/drm/i915/intel_dp.c | 71 +++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 88f3b745a326..1bd14c49b18b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1109,6 +1109,44 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return ret; } +static enum port intel_aux_port(struct drm_i915_private *dev_priv, + enum port port) +{ + const struct ddi_vbt_port_info *info = + &dev_priv->vbt.ddi_port_info[port]; + enum port aux_port; + + if (!info->alternate_aux_channel) { + DRM_DEBUG_KMS("using AUX %c for port %c (platform default)\n", + port_name(port), port_name(port)); + return port; + } + + switch (info->alternate_aux_channel) { + case DP_AUX_A: + aux_port = PORT_A; + break; + case DP_AUX_B: + aux_port = PORT_B; + break; + case DP_AUX_C: + aux_port = PORT_C; + break; + case DP_AUX_D: + aux_port = PORT_D; + break; + default: + MISSING_CASE(info->alternate_aux_channel); + aux_port = PORT_A; + break; + } + + DRM_DEBUG_KMS("using AUX %c for port %c (VBT)\n", + port_name(aux_port), port_name(port)); + + return aux_port; +} + static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv, enum port port) { @@ -1169,36 +1207,9 @@ static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv, } } -/* - * On SKL we don't have Aux for port E so we rely - * on VBT to set a proper alternate aux channel. - */ -static enum port skl_porte_aux_port(struct drm_i915_private *dev_priv) -{ - const struct ddi_vbt_port_info *info = - &dev_priv->vbt.ddi_port_info[PORT_E]; - - switch (info->alternate_aux_channel) { - case DP_AUX_A: - return PORT_A; - case DP_AUX_B: - return PORT_B; - case DP_AUX_C: - return PORT_C; - case DP_AUX_D: - return PORT_D; - default: - MISSING_CASE(info->alternate_aux_channel); - return PORT_A; - } -} - static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, enum port port) { - if (port == PORT_E) - port = skl_porte_aux_port(dev_priv); - switch (port) { case PORT_A: case PORT_B: @@ -1214,9 +1225,6 @@ static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, enum port port, int index) { - if (port == PORT_E) - port = skl_porte_aux_port(dev_priv); - switch (port) { case PORT_A: case PORT_B: @@ -1254,7 +1262,8 @@ static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv, static void intel_aux_reg_init(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); - enum port port = dp_to_dig_port(intel_dp)->port; + enum port port = intel_aux_port(dev_priv, + dp_to_dig_port(intel_dp)->port); int i; intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port); -- cgit v1.2.3 From e4ab73a13291fc844c9e24d5c347bd95818544d2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 11 Oct 2016 20:52:46 +0300 Subject: drm/i915: Respect alternate_ddc_pin for all DDI ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VBT provides the platform a way to mix and match the DDI ports vs. GMBUS pins. Currently we only trust the VBT for DDI E, which I suppose has no standard GMBUS pin assignment. However, there are machines out there that use a non-standard mapping for the other ports as well. Let's start trusting the VBT on this one for all ports on DDI platforms. I've structured the code such that other platforms could easily start using this as well, by simply filling in the ddi_port_info. IIRC there may be CHV system that might actually need this. v2: Include a commit message, include a debug message during init Cc: stable@vger.kernel.org Cc: Maarten Maathuis Tested-by: Maarten Maathuis Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97877 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1476208368-5710-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jim Bride --- drivers/gpu/drm/i915/intel_hdmi.c | 84 ++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 501334242d38..af8715f31807 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1800,6 +1800,50 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; } +static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv, + enum port port) +{ + const struct ddi_vbt_port_info *info = + &dev_priv->vbt.ddi_port_info[port]; + u8 ddc_pin; + + if (info->alternate_ddc_pin) { + DRM_DEBUG_KMS("Using DDC pin 0x%x for port %c (VBT)\n", + info->alternate_ddc_pin, port_name(port)); + return info->alternate_ddc_pin; + } + + switch (port) { + case PORT_B: + if (IS_BROXTON(dev_priv)) + ddc_pin = GMBUS_PIN_1_BXT; + else + ddc_pin = GMBUS_PIN_DPB; + break; + case PORT_C: + if (IS_BROXTON(dev_priv)) + ddc_pin = GMBUS_PIN_2_BXT; + else + ddc_pin = GMBUS_PIN_DPC; + break; + case PORT_D: + if (IS_CHERRYVIEW(dev_priv)) + ddc_pin = GMBUS_PIN_DPD_CHV; + else + ddc_pin = GMBUS_PIN_DPD; + break; + default: + MISSING_CASE(port); + ddc_pin = GMBUS_PIN_DPB; + break; + } + + DRM_DEBUG_KMS("Using DDC pin 0x%x for port %c (platform default)\n", + ddc_pin, port_name(port)); + + return ddc_pin; +} + void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector) { @@ -1809,7 +1853,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); enum port port = intel_dig_port->port; - uint8_t alternate_ddc_pin; DRM_DEBUG_KMS("Adding HDMI connector on port %c\n", port_name(port)); @@ -1827,12 +1870,10 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, connector->doublescan_allowed = 0; connector->stereo_allowed = 1; + intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port); + switch (port) { case PORT_B: - if (IS_BROXTON(dev_priv)) - intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT; - else - intel_hdmi->ddc_bus = GMBUS_PIN_DPB; /* * On BXT A0/A1, sw needs to activate DDIA HPD logic and * interrupts to check the external panel connection. @@ -1843,46 +1884,17 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_encoder->hpd_pin = HPD_PORT_B; break; case PORT_C: - if (IS_BROXTON(dev_priv)) - intel_hdmi->ddc_bus = GMBUS_PIN_2_BXT; - else - intel_hdmi->ddc_bus = GMBUS_PIN_DPC; intel_encoder->hpd_pin = HPD_PORT_C; break; case PORT_D: - if (WARN_ON(IS_BROXTON(dev_priv))) - intel_hdmi->ddc_bus = GMBUS_PIN_DISABLED; - else if (IS_CHERRYVIEW(dev_priv)) - intel_hdmi->ddc_bus = GMBUS_PIN_DPD_CHV; - else - intel_hdmi->ddc_bus = GMBUS_PIN_DPD; intel_encoder->hpd_pin = HPD_PORT_D; break; case PORT_E: - /* On SKL PORT E doesn't have seperate GMBUS pin - * We rely on VBT to set a proper alternate GMBUS pin. */ - alternate_ddc_pin = - dev_priv->vbt.ddi_port_info[PORT_E].alternate_ddc_pin; - switch (alternate_ddc_pin) { - case DDC_PIN_B: - intel_hdmi->ddc_bus = GMBUS_PIN_DPB; - break; - case DDC_PIN_C: - intel_hdmi->ddc_bus = GMBUS_PIN_DPC; - break; - case DDC_PIN_D: - intel_hdmi->ddc_bus = GMBUS_PIN_DPD; - break; - default: - MISSING_CASE(alternate_ddc_pin); - } intel_encoder->hpd_pin = HPD_PORT_E; break; - case PORT_A: - intel_encoder->hpd_pin = HPD_PORT_A; - /* Internal port only for eDP. */ default: - BUG(); + MISSING_CASE(port); + return; } if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { -- cgit v1.2.3 From 9454fa871edf15c20a0371548b3ec0d6d944a498 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 11 Oct 2016 20:52:47 +0300 Subject: drm/i915: Clean up DDI DDC/AUX CH sanitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we use the AUX and GMBUS assignment from VBT for all ports, let's clean up the sanitization of the port information a bit. Previosuly we only did this for port E, and only complained about a non-standard assignment for the other ports. But as we know that non-standard assignments are a fact of life, let's expand the sanitization to all the ports. v2: Include a commit message, fix up the comments a bit v3: Don't clobber other ports if the current port has no alternate aux ch/ddc pin Cc: stable@vger.kernel.org Cc: Maarten Maathuis Tested-by: Maarten Maathuis References: https://bugs.freedesktop.org/show_bug.cgi?id=97877 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1476208368-5710-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jim Bride (v2) --- drivers/gpu/drm/i915/intel_bios.c | 122 ++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 32e1def6a9ef..5ab646ef8c9f 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1035,6 +1035,77 @@ static u8 translate_iboost(u8 val) return mapping[val]; } +static void sanitize_ddc_pin(struct drm_i915_private *dev_priv, + enum port port) +{ + const struct ddi_vbt_port_info *info = + &dev_priv->vbt.ddi_port_info[port]; + enum port p; + + if (!info->alternate_ddc_pin) + return; + + for_each_port_masked(p, (1 << port) - 1) { + struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p]; + + if (info->alternate_ddc_pin != i->alternate_ddc_pin) + continue; + + DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, " + "disabling port %c DVI/HDMI support\n", + port_name(p), i->alternate_ddc_pin, + port_name(port), port_name(p)); + + /* + * If we have multiple ports supposedly sharing the + * pin, then dvi/hdmi couldn't exist on the shared + * port. Otherwise they share the same ddc bin and + * system couldn't communicate with them separately. + * + * Due to parsing the ports in alphabetical order, + * a higher port will always clobber a lower one. + */ + i->supports_dvi = false; + i->supports_hdmi = false; + i->alternate_ddc_pin = 0; + } +} + +static void sanitize_aux_ch(struct drm_i915_private *dev_priv, + enum port port) +{ + const struct ddi_vbt_port_info *info = + &dev_priv->vbt.ddi_port_info[port]; + enum port p; + + if (!info->alternate_aux_channel) + return; + + for_each_port_masked(p, (1 << port) - 1) { + struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p]; + + if (info->alternate_aux_channel != i->alternate_aux_channel) + continue; + + DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, " + "disabling port %c DP support\n", + port_name(p), i->alternate_aux_channel, + port_name(port), port_name(p)); + + /* + * If we have multiple ports supposedlt sharing the + * aux channel, then DP couldn't exist on the shared + * port. Otherwise they share the same aux channel + * and system couldn't communicate with them separately. + * + * Due to parsing the ports in alphabetical order, + * a higher port will always clobber a lower one. + */ + i->supports_dp = false; + i->alternate_aux_channel = 0; + } +} + static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, const struct bdb_header *bdb) { @@ -1109,54 +1180,15 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); if (is_dvi) { - if (port == PORT_E) { - info->alternate_ddc_pin = ddc_pin; - /* if DDIE share ddc pin with other port, then - * dvi/hdmi couldn't exist on the shared port. - * Otherwise they share the same ddc bin and system - * couldn't communicate with them seperately. */ - if (ddc_pin == DDC_PIN_B) { - dev_priv->vbt.ddi_port_info[PORT_B].supports_dvi = 0; - dev_priv->vbt.ddi_port_info[PORT_B].supports_hdmi = 0; - } else if (ddc_pin == DDC_PIN_C) { - dev_priv->vbt.ddi_port_info[PORT_C].supports_dvi = 0; - dev_priv->vbt.ddi_port_info[PORT_C].supports_hdmi = 0; - } else if (ddc_pin == DDC_PIN_D) { - dev_priv->vbt.ddi_port_info[PORT_D].supports_dvi = 0; - dev_priv->vbt.ddi_port_info[PORT_D].supports_hdmi = 0; - } - } else if (ddc_pin == DDC_PIN_B && port != PORT_B) - DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); - else if (ddc_pin == DDC_PIN_C && port != PORT_C) - DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); - else if (ddc_pin == DDC_PIN_D && port != PORT_D) - DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); + info->alternate_ddc_pin = ddc_pin; + + sanitize_ddc_pin(dev_priv, port); } if (is_dp) { - if (port == PORT_E) { - info->alternate_aux_channel = aux_channel; - /* if DDIE share aux channel with other port, then - * DP couldn't exist on the shared port. Otherwise - * they share the same aux channel and system - * couldn't communicate with them seperately. */ - if (aux_channel == DP_AUX_A) - dev_priv->vbt.ddi_port_info[PORT_A].supports_dp = 0; - else if (aux_channel == DP_AUX_B) - dev_priv->vbt.ddi_port_info[PORT_B].supports_dp = 0; - else if (aux_channel == DP_AUX_C) - dev_priv->vbt.ddi_port_info[PORT_C].supports_dp = 0; - else if (aux_channel == DP_AUX_D) - dev_priv->vbt.ddi_port_info[PORT_D].supports_dp = 0; - } - else if (aux_channel == DP_AUX_A && port != PORT_A) - DRM_DEBUG_KMS("Unexpected AUX channel for port A\n"); - else if (aux_channel == DP_AUX_B && port != PORT_B) - DRM_DEBUG_KMS("Unexpected AUX channel for port B\n"); - else if (aux_channel == DP_AUX_C && port != PORT_C) - DRM_DEBUG_KMS("Unexpected AUX channel for port C\n"); - else if (aux_channel == DP_AUX_D && port != PORT_D) - DRM_DEBUG_KMS("Unexpected AUX channel for port D\n"); + info->alternate_aux_channel = aux_channel; + + sanitize_aux_ch(dev_priv, port); } if (bdb->version >= 158) { -- cgit v1.2.3 From c8a89b08a43e640f5ea5dcc4b59f7cea79c890a2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 11 Oct 2016 20:52:48 +0300 Subject: drm/i915: Fix whitespace issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the poorly indented port parameters to the aux ctl and data reg functions. This was fallout from the s/i915_mmio_reg_t/i915_reg_t/ that happened during the review of commit f0f59a00a1c9 ("drm/i915: Type safe register read/write") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1476208368-5710-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jim Bride --- drivers/gpu/drm/i915/intel_dp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1bd14c49b18b..e03e79f7714a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1148,7 +1148,7 @@ static enum port intel_aux_port(struct drm_i915_private *dev_priv, } static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv, - enum port port) + enum port port) { switch (port) { case PORT_B: @@ -1162,7 +1162,7 @@ static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv, } static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv, - enum port port, int index) + enum port port, int index) { switch (port) { case PORT_B: @@ -1176,7 +1176,7 @@ static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv, } static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv, - enum port port) + enum port port) { switch (port) { case PORT_A: @@ -1192,7 +1192,7 @@ static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv, } static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv, - enum port port, int index) + enum port port, int index) { switch (port) { case PORT_A: @@ -1208,7 +1208,7 @@ static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv, } static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, - enum port port) + enum port port) { switch (port) { case PORT_A: @@ -1223,7 +1223,7 @@ static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, } static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, - enum port port, int index) + enum port port, int index) { switch (port) { case PORT_A: @@ -1238,7 +1238,7 @@ static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, } static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, - enum port port) + enum port port) { if (INTEL_INFO(dev_priv)->gen >= 9) return skl_aux_ctl_reg(dev_priv, port); @@ -1249,7 +1249,7 @@ static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, } static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv, - enum port port, int index) + enum port port, int index) { if (INTEL_INFO(dev_priv)->gen >= 9) return skl_aux_data_reg(dev_priv, port, index); -- cgit v1.2.3 From e5f1b245870d59be0e6cc3b33edf5406a3b59648 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 5 Oct 2016 09:33:12 +0200 Subject: cpuidle: governors: Remove remaining old module code The governor's code use try_module_get() and put_module() to refcount the governor's module. But the governors are not compiled as module. The refcount does not prevent to switch the governor or unload a module as they aren't compiled as modules. The code is pointless, so remove it. Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governor.c | 4 ---- drivers/cpuidle/governors/ladder.c | 2 -- drivers/cpuidle/governors/menu.c | 2 -- include/linux/cpuidle.h | 2 -- 4 files changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c index fb9f511cca23..4e78263e34a4 100644 --- a/drivers/cpuidle/governor.c +++ b/drivers/cpuidle/governor.c @@ -9,7 +9,6 @@ */ #include -#include #include #include "cpuidle.h" @@ -53,14 +52,11 @@ int cpuidle_switch_governor(struct cpuidle_governor *gov) if (cpuidle_curr_governor) { list_for_each_entry(dev, &cpuidle_detected_devices, device_list) cpuidle_disable_device(dev); - module_put(cpuidle_curr_governor->owner); } cpuidle_curr_governor = gov; if (gov) { - if (!try_module_get(cpuidle_curr_governor->owner)) - return -EINVAL; list_for_each_entry(dev, &cpuidle_detected_devices, device_list) cpuidle_enable_device(dev); cpuidle_install_idle_handler(); diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 63bd5a403e22..fe8f08948fcb 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -177,7 +176,6 @@ static struct cpuidle_governor ladder_governor = { .enable = ladder_enable_device, .select = ladder_select_state, .reflect = ladder_reflect, - .owner = THIS_MODULE, }; /** diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 03d38c291de6..d9b5b9398a0f 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -19,7 +19,6 @@ #include #include #include -#include /* * Please note when changing the tuning values: @@ -484,7 +483,6 @@ static struct cpuidle_governor menu_governor = { .enable = menu_enable_device, .select = menu_select, .reflect = menu_reflect, - .owner = THIS_MODULE, }; /** diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index bb31373c3478..15deea449edc 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -235,8 +235,6 @@ struct cpuidle_governor { int (*select) (struct cpuidle_driver *drv, struct cpuidle_device *dev); void (*reflect) (struct cpuidle_device *dev, int index); - - struct module *owner; }; #ifdef CONFIG_CPU_IDLE -- cgit v1.2.3 From f5261402494a4893e7c5c6cd5ab99b8f7589b717 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Mon, 10 Oct 2016 20:44:22 +0800 Subject: PM / AVS: rockchip-io: make the log more consistent When testing SD hotplug automatically, I got bunch of useless log like this: [ 588.357838] mmc0: card 0007 removed [ 589.492664] rockchip-iodomain ff770000.syscon:io-domains: Setting to 3300000 done [ 589.500698] vccio_sd: ramp_delay not set [ 589.504817] rockchip-iodomain ff770000.syscon:io-domains: Setting to 3300000 done [ 589.669705] rockchip-iodomain ff770000.syscon:io-domains: Setting to 3300000 done [ 589.677593] vccio_sd: ramp_delay not set [ 589.681581] rockchip-iodomain ff770000.syscon:io-domains: Setting to 1800000 done [ 590.032820] dwmmc_rockchip ff0c0000.dwmmc: Successfully tuned phase to 140 [ 590.039725] mmc0: new ultra high speed SDR50 SDHC card at address 0007 [ 590.046641] mmcblk0: mmc0:0007 SD32G 29.3 GiB [ 590.052163] mmcblk0: p1 Moreover the code is intent to print the 'uV' for debug but later print it using dev_info. It looks more like to me that it should be the real intention of the code. Anyway, let's mark this verbose log as debug message. Signed-off-by: Shawn Lin Reviewed-by: Heiko Stuebner Acked-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/power/avs/rockchip-io-domain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/power/avs/rockchip-io-domain.c b/drivers/power/avs/rockchip-io-domain.c index 01b6d3f9b8fb..56bce1908be2 100644 --- a/drivers/power/avs/rockchip-io-domain.c +++ b/drivers/power/avs/rockchip-io-domain.c @@ -143,7 +143,7 @@ static int rockchip_iodomain_notify(struct notifier_block *nb, if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) return NOTIFY_BAD; - dev_info(supply->iod->dev, "Setting to %d done\n", uV); + dev_dbg(supply->iod->dev, "Setting to %d done\n", uV); return NOTIFY_OK; } -- cgit v1.2.3 From d4cb3fd9b548b8bfe2a712ec920b9ebabd3547ab Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 19 Oct 2016 22:29:53 +0100 Subject: drm/i915/dp: add lane_count check in intel_dp_check_link_status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently it's entirely possible to go through the link training step without first determining the lane_count, which is silly since we end up doing a bunch of aux transfers of size = 0, as highlighted by WARN_ON(!msg->buffer != !msg->size), and can only ever result in a 'failed to update link training' message. This can be observed during intel_dp_long_pulse where we can do the link training step, but before we have had a chance to set the link params. To avoid this we add an extra check for the lane_count in intel_dp_check_link_status, which should prevent us from doing the link training step prematurely. v2: add WARN_ON_ONCE and FIXME comment (Ville) References: https://bugs.freedesktop.org/show_bug.cgi?id=97344 Cc: Ville Syrjälä Cc: Mika Kahola Signed-off-by: Matthew Auld Link: http://patchwork.freedesktop.org/patch/msgid/1476912593-10019-1-git-send-email-matthew.auld@intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_dp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e03e79f7714a..f30db8f2425e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4041,6 +4041,11 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) if (!to_intel_crtc(intel_encoder->base.crtc)->active) return; + /* FIXME: we need to synchronize this sort of stuff with hardware + * readout */ + if (WARN_ON_ONCE(!intel_dp->lane_count)) + return; + /* if link training is requested we should perform it always */ if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) || (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { -- cgit v1.2.3 From 974f86498ed28d86575cd2327bd83e53abd872da Mon Sep 17 00:00:00 2001 From: "Prakash, Prashanth" Date: Fri, 14 Oct 2016 12:00:23 -0600 Subject: cpufreq / CPPC: Add MODULE_DEVICE_TABLE for cppc_cpufreq driver MODULE_DEVICE_TABLE is added so that CPPC cpufreq module can be automatically loaded when we have a acpi processor device with "ACPI0007" hid. Signed-off-by: Prashanth Prakash Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cppc_cpufreq.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 4852d9efe74e..e82bb3c30b92 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -247,3 +247,10 @@ MODULE_DESCRIPTION("CPUFreq driver based on the ACPI CPPC v5.0+ spec"); MODULE_LICENSE("GPL"); late_initcall(cppc_cpufreq_init); + +static const struct acpi_device_id cppc_acpi_ids[] = { + {ACPI_PROCESSOR_DEVICE_HID, }, + {} +}; + +MODULE_DEVICE_TABLE(acpi, cppc_acpi_ids); -- cgit v1.2.3 From 46dd212a0679872d2ad824e86672e53c1625ab1c Mon Sep 17 00:00:00 2001 From: Paweł Jarosz Date: Fri, 14 Oct 2016 14:16:39 +0200 Subject: clk: rockchip: Use clock ids for cpu and peri clocks on rk3066 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add bindings for ACLK_CPU, HCLK_CPU, PCLK_CPU, ACLK_PERI, HCLK_PERI, PCLK_PERI. We need this to init it's rate at boot time. Signed-off-by: Paweł Jarosz Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3188.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index d0e722a0e8cf..a6d398f4b18f 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -306,14 +306,14 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, RK2928_CLKGATE_CON(0), 2, GFLAGS), - GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, + GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0, RK2928_CLKGATE_CON(0), 3, GFLAGS), GATE(0, "atclk_cpu", "pclk_cpu_pre", 0, RK2928_CLKGATE_CON(0), 6, GFLAGS), - GATE(0, "pclk_cpu", "pclk_cpu_pre", 0, + GATE(PCLK_CPU, "pclk_cpu", "pclk_cpu_pre", 0, RK2928_CLKGATE_CON(0), 5, GFLAGS), - GATE(0, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED, + GATE(HCLK_CPU, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(0), 4, GFLAGS), COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, @@ -323,12 +323,12 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(1), 4, GFLAGS), - GATE(0, "aclk_peri", "aclk_peri_pre", 0, + GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre", 0, RK2928_CLKGATE_CON(2), 1, GFLAGS), - COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0, + COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_pre", 0, RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, RK2928_CLKGATE_CON(2), 2, GFLAGS), - COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0, + COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_pre", 0, RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, RK2928_CLKGATE_CON(2), 3, GFLAGS), -- cgit v1.2.3 From 838de39fc9516470b1410cc068c7f41daec69265 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 20 Oct 2016 12:50:03 -0200 Subject: drm/fence: release fence reference when canceling event If the event gets canceled we also need to put away the fence reference it holds. Signed-off-by: Gustavo Padovan Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476975005-30441-3-git-send-email-gustavo@padovan.org --- drivers/gpu/drm/drm_fops.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index e84faecf5225..8bed5f459182 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -663,6 +663,10 @@ void drm_event_cancel_free(struct drm_device *dev, list_del(&p->pending_link); } spin_unlock_irqrestore(&dev->event_lock, flags); + + if (p->fence) + fence_put(p->fence); + kfree(p); } EXPORT_SYMBOL(drm_event_cancel_free); -- cgit v1.2.3 From 4bee77dc734ccd4119bb750479809ebc82776bef Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 20 Oct 2016 15:44:53 +0900 Subject: PM / OPP: make _of_get_opp_desc_node() a static function Since commit f47b72a15a96 ("PM / OPP: Move CONFIG_OF dependent code in a separate file"), this function is defined and called only in drivers/base/power/opp/of.c . Signed-off-by: Masahiro Yamada Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/of.c | 2 +- drivers/base/power/opp/opp.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c index 5552211e6fcd..6480137bd256 100644 --- a/drivers/base/power/opp/of.c +++ b/drivers/base/power/opp/of.c @@ -198,7 +198,7 @@ void dev_pm_opp_of_remove_table(struct device *dev) EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table); /* Returns opp descriptor node for a device, caller must do of_node_put() */ -struct device_node *_of_get_opp_desc_node(struct device *dev) +static struct device_node *_of_get_opp_desc_node(struct device *dev) { /* * TODO: Support for multiple OPP tables. diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index fabd5ca1a083..96cd30ac6c1d 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -190,7 +190,6 @@ struct opp_table { /* Routines internal to opp core */ struct opp_table *_find_opp_table(struct device *dev); struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table); -struct device_node *_of_get_opp_desc_node(struct device *dev); void _dev_pm_opp_remove_table(struct device *dev, bool remove_all); struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table); int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table); -- cgit v1.2.3 From 349aa92e81bd14552d8d2335aff490f306038603 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 20 Oct 2016 16:12:49 +0900 Subject: PM / OPP: fix debug/error messages in dev_pm_opp_of_get_sharing_cpus() These log messages are wrong because _of_get_opp_desc_node() returns an operating-points-v2 node. Commit a6eed752f5fb ("PM / OPP: passing NULL to PTR_ERR()") fixed static checker warnings, and reworded the messages at the same time (but the latter was not mentioned in the git-log). Restore the correct messages. Signed-off-by: Masahiro Yamada Acked-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/of.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c index 6480137bd256..5b3755e49731 100644 --- a/drivers/base/power/opp/of.c +++ b/drivers/base/power/opp/of.c @@ -562,7 +562,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, /* Get OPP descriptor node */ np = _of_get_opp_desc_node(cpu_dev); if (!np) { - dev_dbg(cpu_dev, "%s: Couldn't find cpu_dev node.\n", __func__); + dev_dbg(cpu_dev, "%s: Couldn't find opp node.\n", __func__); return -ENOENT; } @@ -587,7 +587,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, /* Get OPP descriptor node */ tmp_np = _of_get_opp_desc_node(tcpu_dev); if (!tmp_np) { - dev_err(tcpu_dev, "%s: Couldn't find tcpu_dev node.\n", + dev_err(tcpu_dev, "%s: Couldn't find opp node.\n", __func__); ret = -ENOENT; goto put_cpu_node; -- cgit v1.2.3 From 62006c1702b3b1be0c0726949e0ee0ea2326be9c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 17 Oct 2016 20:16:58 +0200 Subject: PM / Runtime: Remove the exported function pm_children_suspended() The exported function pm_children_suspended() has only one caller, which is the runtime PM internal function, rpm_check_suspend_allowed(). Let's clean-up this code, by removing pm_children_suspended() altogether and instead do the one-liner check directly in rpm_check_suspend_allowed(). Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Signed-off-by: Rafael J. Wysocki --- drivers/base/power/runtime.c | 3 ++- include/linux/pm_runtime.h | 7 ------- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 82a081ea4317..53b427dfc403 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -241,7 +241,8 @@ static int rpm_check_suspend_allowed(struct device *dev) retval = -EACCES; else if (atomic_read(&dev->power.usage_count) > 0) retval = -EAGAIN; - else if (!pm_children_suspended(dev)) + else if (!dev->power.ignore_children && + atomic_read(&dev->power.child_count)) retval = -EBUSY; /* Pending resume requests take precedence over suspends. */ diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 2e14d2667b6c..61ea5666c94c 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -61,12 +61,6 @@ static inline void pm_suspend_ignore_children(struct device *dev, bool enable) dev->power.ignore_children = enable; } -static inline bool pm_children_suspended(struct device *dev) -{ - return dev->power.ignore_children - || !atomic_read(&dev->power.child_count); -} - static inline void pm_runtime_get_noresume(struct device *dev) { atomic_inc(&dev->power.usage_count); @@ -162,7 +156,6 @@ static inline void pm_runtime_allow(struct device *dev) {} static inline void pm_runtime_forbid(struct device *dev) {} static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {} -static inline bool pm_children_suspended(struct device *dev) { return false; } static inline void pm_runtime_get_noresume(struct device *dev) {} static inline void pm_runtime_put_noidle(struct device *dev) {} static inline bool device_run_wake(struct device *dev) { return false; } -- cgit v1.2.3 From 216ef0b6b8c7f041a618913e94da52c3fdf82a99 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 17 Oct 2016 20:16:59 +0200 Subject: PM / Runtime: Clarify comment in rpm_resume() when resuming the parent Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Signed-off-by: Rafael J. Wysocki --- drivers/base/power/runtime.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 53b427dfc403..117db71e84cb 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -713,8 +713,8 @@ static int rpm_resume(struct device *dev, int rpmflags) spin_lock(&parent->power.lock); /* - * We can resume if the parent's runtime PM is disabled or it - * is set to ignore children. + * Resume the parent if it has runtime PM enabled and not been + * set to ignore its children. */ if (!parent->power.disable_depth && !parent->power.ignore_children) { -- cgit v1.2.3 From de1e211ff7b948b286222f592a5168746a7dc5e5 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Sat, 8 Oct 2016 08:55:18 +0100 Subject: drm/virtio: kconfig: Fixup white space. Use tabs instead of spaces. Signed-off-by: Peter Griffin Acked-by: Lee Jones Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1475913318-12275-1-git-send-email-peter.griffin@linaro.org Link: http://patchwork.freedesktop.org/patch/msgid/1476238699-25820-1-git-send-email-jiang.biao2@zte.com.cn --- drivers/gpu/drm/virtio/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/Kconfig b/drivers/gpu/drm/virtio/Kconfig index e1afc3d3f8d9..81d1807ac228 100644 --- a/drivers/gpu/drm/virtio/Kconfig +++ b/drivers/gpu/drm/virtio/Kconfig @@ -1,10 +1,10 @@ config DRM_VIRTIO_GPU tristate "Virtio GPU driver" depends on DRM && VIRTIO - select DRM_KMS_HELPER - select DRM_TTM + select DRM_KMS_HELPER + select DRM_TTM help This is the virtual GPU driver for virtio. It can be used with - QEMU based VMMs (like KVM or Xen). + QEMU based VMMs (like KVM or Xen). If unsure say M. -- cgit v1.2.3 From 30cd85dd6edc86ea8d8589efb813f1fad41ef233 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 19 Oct 2016 15:48:32 -0200 Subject: dma-buf/sync_file: hold reference to fence when creating sync_file fence referencing was out of balance. It was not taking any ref to the fence at creating time, but it was putting a reference when freeing the sync file. This patch fixes the balancing issue by getting a reference for the fence when creating the sync_file. Signed-off-by: Gustavo Padovan Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1476899313-22241-1-git-send-email-gustavo@padovan.org --- drivers/dma-buf/sync_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index b29a9e817320..235f8ac113cc 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -79,7 +79,7 @@ struct sync_file *sync_file_create(struct fence *fence) if (!sync_file) return NULL; - sync_file->fence = fence; + sync_file->fence = fence_get(fence); snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d", fence->ops->get_driver_name(fence), -- cgit v1.2.3 From e8f0a89cd7591c5d4eb7c77833af865b4db356b7 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Wed, 19 Oct 2016 15:53:01 +0200 Subject: hv_netvsc: fix a race between netvsc_send() and netvsc_init_buf() Fix in commit 880988348270 ("hv_netvsc: set nvdev link after populating chn_table") turns out to be incomplete. A crash in netvsc_get_next_send_section() is observed on mtu change when the device is under load. The race I identified is: if we get to netvsc_send() after we set net_device_ctx->nvdev link in netvsc_device_add() but before we finish netvsc_connect_vsp()->netvsc_init_buf() send_section_map is not allocated and we crash. Unfortunately we can't set net_device_ctx->nvdev link after the netvsc_init_buf() call as during the negotiation we need to receive packets and on the receive path we check for it. It would probably be possible to split nvdev into a pair of nvdev_in and nvdev_out links and check them accordingly in get_outbound_net_device()/ get_inbound_net_device() but this looks like an overkill. Check that send_section_map is allocated in netvsc_send(). Signed-off-by: Vitaly Kuznetsov Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 720b5fa9e625..e2bfaac1801d 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -888,6 +888,13 @@ int netvsc_send(struct hv_device *device, if (!net_device) return -ENODEV; + /* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get + * here before the negotiation with the host is finished and + * send_section_map may not be allocated yet. + */ + if (!net_device->send_section_map) + return -EAGAIN; + out_channel = net_device->chn_table[q_idx]; packet->send_buf_index = NETVSC_INVALID_INDEX; -- cgit v1.2.3 From f59dab8d9e8f37f7042ba05bfbab748b1312e73e Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 20 Oct 2016 10:12:42 +0200 Subject: mtd: nand: sunxi: fix support for 512bytes ECC chunks The driver is incorrectly assuming that the ECC block size is always 1k which is not always true. Also take the other cases into account. Signed-off-by: Boris Brezillon Signed-off-by: Maxime Ripard --- drivers/mtd/nand/sunxi_nand.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 8b8470c4e6d0..e40482a65de6 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -145,6 +145,7 @@ #define NFC_ECC_PIPELINE BIT(3) #define NFC_ECC_EXCEPTION BIT(4) #define NFC_ECC_BLOCK_SIZE_MSK BIT(5) +#define NFC_ECC_BLOCK_512 BIT(5) #define NFC_RANDOM_EN BIT(9) #define NFC_RANDOM_DIRECTION BIT(10) #define NFC_ECC_MODE_MSK GENMASK(15, 12) @@ -817,6 +818,9 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION | NFC_ECC_PIPELINE; + if (nand->ecc.size == 512) + ecc_ctl |= NFC_ECC_BLOCK_512; + writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL); } -- cgit v1.2.3 From 6ac18a4859b3a7d55874bed2ebe6d704b7926a10 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 20 Oct 2016 10:12:43 +0200 Subject: mtd: nand: add support for the TC58NVG2S0H chip Add the description of the Toshiba TC58NVG2S0H SLC nand to the nand_ids table so we can use the NAND ECC infos and the ONFI timings. Signed-off-by: Boris Brezillon Signed-off-by: Maxime Ripard --- drivers/mtd/nand/nand_ids.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 2af9869a115e..b3a332f37e14 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -36,6 +36,9 @@ struct nand_flash_dev nand_flash_ids[] = { {"TC58NVG2S0F 4G 3.3V 8-bit", { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} }, SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) }, + {"TC58NVG2S0H 4G 3.3V 8-bit", + { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00} }, + SZ_4K, SZ_512, SZ_256K, 0, 8, 256, NAND_ECC_INFO(8, SZ_512) }, {"TC58NVG3S0F 8G 3.3V 8-bit", { .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} }, SZ_4K, SZ_1K, SZ_256K, 0, 8, 232, NAND_ECC_INFO(4, SZ_512) }, -- cgit v1.2.3 From bd2ef25d921c0d937e4bc4f5a4f98f534424c6aa Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 19:30:46 +0300 Subject: drm: Add drm_rotation_90_or_270() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have intel_rotation_90_or_270() in i915 to check if the rotation is 90 or 270 degrees. Similar checks are elsewhere in drm, so let's move the helper into a central place and use it everwhere. v2: Drop the BIT() Convert all new intel_rotation_90_or_270() calls Deal with superfluous code shuffling Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson (v1) Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1474907460-10717-2-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 4 ++-- drivers/gpu/drm/drm_atomic_helper.c | 2 +- drivers/gpu/drm/drm_crtc.c | 3 +-- drivers/gpu/drm/i915/intel_atomic_plane.c | 3 ++- drivers/gpu/drm/i915/intel_display.c | 16 ++++++++-------- drivers/gpu/drm/i915/intel_drv.h | 6 ------ drivers/gpu/drm/i915/intel_fbc.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 12 ++++++------ drivers/gpu/drm/omapdrm/omap_plane.c | 8 ++------ include/drm/drm_blend.h | 5 +++++ 10 files changed, 28 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 9d4c030672f0..b380179d4013 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -393,7 +393,7 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, if ((state->base.fb->pixel_format == DRM_FORMAT_YUV422 || state->base.fb->pixel_format == DRM_FORMAT_NV61) && - (state->base.rotation & (DRM_ROTATE_90 | DRM_ROTATE_270))) + drm_rotation_90_or_270(state->base.rotation)) cfg |= ATMEL_HLCDC_YUV422ROT; atmel_hlcdc_layer_update_cfg(&plane->layer, @@ -628,7 +628,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, /* * Swap width and size in case of 90 or 270 degrees rotation */ - if (state->base.rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)) { + if (drm_rotation_90_or_270(state->base.rotation)) { tmp = state->crtc_w; state->crtc_w = state->crtc_h; state->crtc_h = tmp; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 07b432f43b98..f9362760bfb2 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2399,7 +2399,7 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, primary_state->crtc_h = vdisplay; primary_state->src_x = set->x << 16; primary_state->src_y = set->y << 16; - if (primary_state->rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)) { + if (drm_rotation_90_or_270(primary_state->rotation)) { primary_state->src_w = vdisplay << 16; primary_state->src_h = hdisplay << 16; } else { diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 60403bf7a4ff..13441e21117c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -727,8 +727,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); if (crtc->state && - crtc->primary->state->rotation & (DRM_ROTATE_90 | - DRM_ROTATE_270)) + drm_rotation_90_or_270(crtc->primary->state->rotation)) swap(hdisplay, vdisplay); return drm_framebuffer_check_src_coords(x << 16, y << 16, diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index b82de3072d4f..c762ae549a1c 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -142,8 +142,9 @@ static int intel_plane_atomic_check(struct drm_plane *plane, intel_state->clip.y2 = crtc_state->base.enable ? crtc_state->pipe_src_h : 0; - if (state->fb && intel_rotation_90_or_270(state->rotation)) { + if (state->fb && drm_rotation_90_or_270(state->rotation)) { char *format_name; + if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e11896cd2015..af18e2cce34b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2139,7 +2139,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, const struct drm_framebuffer *fb, unsigned int rotation) { - if (intel_rotation_90_or_270(rotation)) { + if (drm_rotation_90_or_270(rotation)) { *view = i915_ggtt_view_rotated; view->params.rotated = to_intel_framebuffer(fb)->rot_info; } else { @@ -2260,7 +2260,7 @@ void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane, unsigned int rotation) { - if (intel_rotation_90_or_270(rotation)) + if (drm_rotation_90_or_270(rotation)) return to_intel_framebuffer(fb)->rotated[plane].pitch; else return fb->pitches[plane]; @@ -2296,7 +2296,7 @@ void intel_add_fb_offsets(int *x, int *y, const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb); unsigned int rotation = state->base.rotation; - if (intel_rotation_90_or_270(rotation)) { + if (drm_rotation_90_or_270(rotation)) { *x += intel_fb->rotated[plane].x; *y += intel_fb->rotated[plane].y; } else { @@ -2360,7 +2360,7 @@ static u32 intel_adjust_tile_offset(int *x, int *y, intel_tile_dims(dev_priv, &tile_width, &tile_height, fb->modifier[plane], cpp); - if (intel_rotation_90_or_270(rotation)) { + if (drm_rotation_90_or_270(rotation)) { pitch_tiles = pitch / tile_height; swap(tile_width, tile_height); } else { @@ -2416,7 +2416,7 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv, intel_tile_dims(dev_priv, &tile_width, &tile_height, fb_modifier, cpp); - if (intel_rotation_90_or_270(rotation)) { + if (drm_rotation_90_or_270(rotation)) { pitch_tiles = pitch / tile_height; swap(tile_width, tile_height); } else { @@ -2976,7 +2976,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) int ret; /* Rotate src coordinates to match rotated GTT view */ - if (intel_rotation_90_or_270(rotation)) + if (drm_rotation_90_or_270(rotation)) drm_rect_rotate(&plane_state->base.src, fb->width, fb->height, DRM_ROTATE_270); @@ -3276,7 +3276,7 @@ u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, * The stride is either expressed as a multiple of 64 bytes chunks for * linear buffers or in number of tiles for tiled buffers. */ - if (intel_rotation_90_or_270(rotation)) { + if (drm_rotation_90_or_270(rotation)) { int cpp = drm_format_plane_cpp(fb->pixel_format, plane); stride /= intel_tile_height(dev_priv, fb->modifier[0], cpp); @@ -4666,7 +4666,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, to_intel_crtc(crtc_state->base.crtc); int need_scaling; - need_scaling = intel_rotation_90_or_270(rotation) ? + need_scaling = drm_rotation_90_or_270(rotation) ? (src_h != dst_w || src_w != dst_h): (src_w != dst_w || src_h != dst_h); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8fd16adf069b..c6ae525fe1f5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1284,12 +1284,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, uint64_t fb_modifier, unsigned int cpp); -static inline bool -intel_rotation_90_or_270(unsigned int rotation) -{ - return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270); -} - void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index faa67624e1ed..afc040be1172 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -84,7 +84,7 @@ static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache, { int w, h; - if (intel_rotation_90_or_270(cache->plane.rotation)) { + if (drm_rotation_90_or_270(cache->plane.rotation)) { w = cache->plane.src_h; h = cache->plane.src_w; } else { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2df06b703e3d..1472400ddce3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3151,7 +3151,7 @@ skl_plane_downscale_amount(const struct intel_plane_state *pstate) src_h = drm_rect_height(&pstate->base.src); dst_w = drm_rect_width(&pstate->base.dst); dst_h = drm_rect_height(&pstate->base.dst); - if (intel_rotation_90_or_270(pstate->base.rotation)) + if (drm_rotation_90_or_270(pstate->base.rotation)) swap(dst_w, dst_h); downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING); @@ -3182,7 +3182,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, width = drm_rect_width(&intel_pstate->base.src) >> 16; height = drm_rect_height(&intel_pstate->base.src) >> 16; - if (intel_rotation_90_or_270(pstate->rotation)) + if (drm_rotation_90_or_270(pstate->rotation)) swap(width, height); /* for planar format */ @@ -3282,7 +3282,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, src_w = drm_rect_width(&intel_pstate->base.src) >> 16; src_h = drm_rect_height(&intel_pstate->base.src) >> 16; - if (intel_rotation_90_or_270(pstate->rotation)) + if (drm_rotation_90_or_270(pstate->rotation)) swap(src_w, src_h); /* Halve UV plane width and height for NV12 */ @@ -3296,7 +3296,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, else plane_bpp = drm_format_plane_cpp(fb->pixel_format, 0); - if (intel_rotation_90_or_270(pstate->rotation)) { + if (drm_rotation_90_or_270(pstate->rotation)) { switch (plane_bpp) { case 1: min_scanlines = 32; @@ -3554,7 +3554,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, width = drm_rect_width(&intel_pstate->base.src) >> 16; height = drm_rect_height(&intel_pstate->base.src) >> 16; - if (intel_rotation_90_or_270(pstate->rotation)) + if (drm_rotation_90_or_270(pstate->rotation)) swap(width, height); cpp = drm_format_plane_cpp(fb->pixel_format, 0); @@ -3575,7 +3575,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { uint32_t min_scanlines = 4; uint32_t y_tile_minimum; - if (intel_rotation_90_or_270(pstate->rotation)) { + if (drm_rotation_90_or_270(pstate->rotation)) { int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? drm_format_plane_cpp(fb->pixel_format, 1) : drm_format_plane_cpp(fb->pixel_format, 0); diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 66ac8c40db26..1549e8393056 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -108,16 +108,12 @@ static void omap_plane_atomic_update(struct drm_plane *plane, win.src_x = state->src_x >> 16; win.src_y = state->src_y >> 16; - switch (state->rotation & DRM_ROTATE_MASK) { - case DRM_ROTATE_90: - case DRM_ROTATE_270: + if (drm_rotation_90_or_270(state->rotation)) { win.src_w = state->src_h >> 16; win.src_h = state->src_w >> 16; - break; - default: + } else { win.src_w = state->src_w >> 16; win.src_h = state->src_h >> 16; - break; } /* update scanout: */ diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h index 36baa175de99..bb493410396c 100644 --- a/include/drm/drm_blend.h +++ b/include/drm/drm_blend.h @@ -47,6 +47,11 @@ struct drm_atomic_state; #define DRM_REFLECT_Y BIT(5) #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y) +static inline bool drm_rotation_90_or_270(unsigned int rotation) +{ + return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270); +} + struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, unsigned int supported_rotations); unsigned int drm_rotation_simplify(unsigned int rotation, -- cgit v1.2.3 From 6e0c7c3358d4e8e9917a97348e6f77da88226cbe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 19:30:47 +0300 Subject: drm/atomic: Reject attempts to use multiple rotation angles at once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rotation property should only accept exactly one rotation angle at once. Let's reject attempts to set none or multiple angles. Testcase: igt/kms_rotation_crc/bad-rotation Signed-off-by: Ville Syrjälä Reviewed-by: Joonas Lahtinen Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1474907460-10717-3-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_atomic.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 5dd70540219c..13ce95ee458e 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -706,6 +706,8 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, } else if (property == config->prop_src_h) { state->src_h = val; } else if (property == config->rotation_property) { + if (!is_power_of_2(val & DRM_ROTATE_MASK)) + return -EINVAL; state->rotation = val; } else if (property == plane->zpos_property) { state->zpos = val; -- cgit v1.2.3 From d138dd3c0c70979215f3184cf36f95875e37932e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 19:30:48 +0300 Subject: drm: Add support for optional per-plane rotation property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not all planes on the system may support the same rotations/reflections, so make it possible to create a separate property for each plane. This way userspace gets told exactly which rotations/reflections are possible for each plane. v2: Add drm_plane_create_rotation_property() helper v3: Drop the BIT(), __builtin_ffs(x) - 1, Moar WARNs for bad parameters Deal with superfluous code shuffling Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson (v1) Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1474907460-10717-4-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_atomic.c | 6 ++++-- drivers/gpu/drm/drm_blend.c | 35 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_fb_helper.c | 6 +++++- include/drm/drm_blend.h | 3 +++ include/drm/drm_plane.h | 2 ++ 5 files changed, 49 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 13ce95ee458e..f81706387889 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -705,7 +705,8 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, state->src_w = val; } else if (property == config->prop_src_h) { state->src_h = val; - } else if (property == config->rotation_property) { + } else if (property == config->rotation_property || + property == plane->rotation_property) { if (!is_power_of_2(val & DRM_ROTATE_MASK)) return -EINVAL; state->rotation = val; @@ -765,7 +766,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->src_w; } else if (property == config->prop_src_h) { *val = state->src_h; - } else if (property == config->rotation_property) { + } else if (property == config->rotation_property || + property == plane->rotation_property) { *val = state->rotation; } else if (property == plane->zpos_property) { *val = state->zpos; diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index 85172a977bf3..e52aece30900 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c @@ -162,6 +162,41 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, } EXPORT_SYMBOL(drm_mode_create_rotation_property); +int drm_plane_create_rotation_property(struct drm_plane *plane, + unsigned int rotation, + unsigned int supported_rotations) +{ + static const struct drm_prop_enum_list props[] = { + { __builtin_ffs(DRM_ROTATE_0) - 1, "rotate-0" }, + { __builtin_ffs(DRM_ROTATE_90) - 1, "rotate-90" }, + { __builtin_ffs(DRM_ROTATE_180) - 1, "rotate-180" }, + { __builtin_ffs(DRM_ROTATE_270) - 1, "rotate-270" }, + { __builtin_ffs(DRM_REFLECT_X) - 1, "reflect-x" }, + { __builtin_ffs(DRM_REFLECT_Y) - 1, "reflect-y" }, + }; + struct drm_property *prop; + + WARN_ON((supported_rotations & DRM_ROTATE_MASK) == 0); + WARN_ON(!is_power_of_2(rotation & DRM_ROTATE_MASK)); + WARN_ON(rotation & ~supported_rotations); + + prop = drm_property_create_bitmask(plane->dev, 0, "rotation", + props, ARRAY_SIZE(props), + supported_rotations); + if (!prop) + return -ENOMEM; + + drm_object_attach_property(&plane->base, prop, rotation); + + if (plane->state) + plane->state->rotation = rotation; + + plane->rotation_property = prop; + + return 0; +} +EXPORT_SYMBOL(drm_plane_create_rotation_property); + /** * drm_rotation_simplify() - Try to simplify the rotation * @rotation: Rotation to be simplified diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 8fffac8c5c75..e0d428f9d1cb 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -392,7 +392,11 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) if (plane->type != DRM_PLANE_TYPE_PRIMARY) drm_plane_force_disable(plane); - if (dev->mode_config.rotation_property) { + if (plane->rotation_property) { + drm_mode_plane_set_obj_prop(plane, + plane->rotation_property, + DRM_ROTATE_0); + } else if (dev->mode_config.rotation_property) { drm_mode_plane_set_obj_prop(plane, dev->mode_config.rotation_property, DRM_ROTATE_0); diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h index bb493410396c..fd351924e1c5 100644 --- a/include/drm/drm_blend.h +++ b/include/drm/drm_blend.h @@ -54,6 +54,9 @@ static inline bool drm_rotation_90_or_270(unsigned int rotation) struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, unsigned int supported_rotations); +int drm_plane_create_rotation_property(struct drm_plane *plane, + unsigned int rotation, + unsigned int supported_rotations); unsigned int drm_rotation_simplify(unsigned int rotation, unsigned int supported_rotations); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 02353904cdba..98b39d66eb32 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -385,6 +385,7 @@ enum drm_plane_type { * @type: type of plane (overlay, primary, cursor) * @state: current atomic state for this plane * @zpos_property: zpos property for this plane + * @rotation_property: rotation property for this plane * @helper_private: mid-layer private data */ struct drm_plane { @@ -431,6 +432,7 @@ struct drm_plane { struct drm_plane_state *state; struct drm_property *zpos_property; + struct drm_property *rotation_property; }; #define obj_to_plane(x) container_of(x, struct drm_plane, base) -- cgit v1.2.3 From ea0e1ce20f736ee7e9209fec2f78880a06056890 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 19:30:49 +0300 Subject: drm/arm: Use per-plane rotation property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global mode_config.rotation_property is going away, switch over to per-plane rotation_property. v2: Drop the BIT() Cc: Liviu Dudau Cc: Brian Starkey Cc: Mali DP Maintainers Signed-off-by: Ville Syrjälä Acked-by: Brian Starkey Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1474907460-10717-5-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/arm/malidp_planes.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 82c193e5e0d6..abaca03b9d36 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -254,21 +254,18 @@ int malidp_de_planes_init(struct drm_device *drm) if (ret < 0) goto cleanup; - if (!drm->mode_config.rotation_property) { + /* SMART layer can't be rotated */ + if (id != DE_SMART) { unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 | DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y; - drm->mode_config.rotation_property = - drm_mode_create_rotation_property(drm, flags); + drm_plane_create_rotation_property(&plane->base, + DRM_ROTATE_0, + flags); } - /* SMART layer can't be rotated */ - if (drm->mode_config.rotation_property && (id != DE_SMART)) - drm_object_attach_property(&plane->base.base, - drm->mode_config.rotation_property, - DRM_ROTATE_0); drm_plane_helper_add(&plane->base, &malidp_de_plane_helper_funcs); -- cgit v1.2.3 From 9fe58f017b54e4d3457479c258d7a8466fc1655e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 19:30:50 +0300 Subject: drm/atmel-hlcdc: Use per-plane rotation property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global mode_config.rotation_property is going away, switch over to per-plane rotation_property. v2: Propagate error upwards (Boris) v3: Drop the BIT() Cc: Boris Brezillon Signed-off-by: Ville Syrjälä Acked-by: Boris Brezillon Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1474907460-10717-6-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 37 +++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index b380179d4013..246ed1e33d8a 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -883,9 +883,9 @@ static int atmel_hlcdc_plane_atomic_get_property(struct drm_plane *p, return 0; } -static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, - const struct atmel_hlcdc_layer_desc *desc, - struct atmel_hlcdc_plane_properties *props) +static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc, + struct atmel_hlcdc_plane_properties *props) { struct regmap *regmap = plane->layer.hlcdc->regmap; @@ -902,10 +902,18 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, ATMEL_HLCDC_LAYER_GA_MASK); } - if (desc->layout.xstride && desc->layout.pstride) - drm_object_attach_property(&plane->base.base, - plane->base.dev->mode_config.rotation_property, - DRM_ROTATE_0); + if (desc->layout.xstride && desc->layout.pstride) { + int ret; + + ret = drm_plane_create_rotation_property(&plane->base, + DRM_ROTATE_0, + DRM_ROTATE_0 | + DRM_ROTATE_90 | + DRM_ROTATE_180 | + DRM_ROTATE_270); + if (ret) + return ret; + } if (desc->layout.csc) { /* @@ -925,6 +933,8 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, ATMEL_HLCDC_LAYER_CSC_CFG(&plane->layer, 2), 0x40040890); } + + return 0; } static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { @@ -1036,7 +1046,9 @@ atmel_hlcdc_plane_create(struct drm_device *dev, &atmel_hlcdc_layer_plane_helper_funcs); /* Set default property values*/ - atmel_hlcdc_plane_init_properties(plane, desc, props); + ret = atmel_hlcdc_plane_init_properties(plane, desc, props); + if (ret) + return ERR_PTR(ret); return plane; } @@ -1054,15 +1066,6 @@ atmel_hlcdc_plane_create_properties(struct drm_device *dev) if (!props->alpha) return ERR_PTR(-ENOMEM); - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, - DRM_ROTATE_0 | - DRM_ROTATE_90 | - DRM_ROTATE_180 | - DRM_ROTATE_270); - if (!dev->mode_config.rotation_property) - return ERR_PTR(-ENOMEM); - return props; } -- cgit v1.2.3 From 18391ec0bb4a1ea1ba2b485b8b29ac536d52fa5b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 19:30:51 +0300 Subject: drm/omap: Set rotation property initial value to BIT(DRM_ROTATE_0) insted of 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0 isn't a valid rotation property value, so let's set the initial value of the property to BIT(DRM_ROTATE_0) instead. v2: Drop the BIT() Cc: Tomi Valkeinen Cc: Rob Clark Signed-off-by: Ville Syrjälä Reviewed-by: Tomi Valkeinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1474907460-10717-7-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/omapdrm/omap_drv.c | 6 ++++-- drivers/gpu/drm/omapdrm/omap_plane.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 1735c7accf72..31ec5d0a9576 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -762,12 +762,14 @@ static void dev_lastclose(struct drm_device *dev) */ for (i = 0; i < priv->num_crtcs; i++) { drm_object_property_set_value(&priv->crtcs[i]->base, - dev->mode_config.rotation_property, 0); + dev->mode_config.rotation_property, + DRM_ROTATE_0); } for (i = 0; i < priv->num_planes; i++) { drm_object_property_set_value(&priv->planes[i]->base, - dev->mode_config.rotation_property, 0); + dev->mode_config.rotation_property, + DRM_ROTATE_0); } } diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 1549e8393056..6ddaa5ea4b6b 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -213,7 +213,7 @@ void omap_plane_install_properties(struct drm_plane *plane, if (priv->has_dmm) { struct drm_property *prop = dev->mode_config.rotation_property; - drm_object_attach_property(obj, prop, 0); + drm_object_attach_property(obj, prop, DRM_ROTATE_0); } drm_object_attach_property(obj, priv->zorder_prop, 0); -- cgit v1.2.3 From 0da88db14034e8b309f1c4188123ca1a02f4b354 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 19:30:52 +0300 Subject: drm/omap: Use per-plane rotation property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global mode_config.rotation_property is going away, switch over to per-plane rotation_property. Not sure I got the annoying crtc rotation_property handling right. Might work, or migth not. v2: Drop the BIT() Don't create rotation property twice for each primary plane Cc: Tomi Valkeinen Cc: Rob Clark Signed-off-by: Ville Syrjälä Reviewed-by: Tomi Valkeinen [danvet: Add comment per discussion between Tomi&Ville.] Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1474907460-10717-8-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/omapdrm/omap_crtc.c | 13 ++++----- drivers/gpu/drm/omapdrm/omap_drv.c | 52 +++++++++++++++++------------------- drivers/gpu/drm/omapdrm/omap_plane.c | 14 +++++++--- 3 files changed, 41 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 180f644e861e..16c691dbc372 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -438,13 +438,14 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, } } -static bool omap_crtc_is_plane_prop(struct drm_device *dev, +static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc, struct drm_property *property) { + struct drm_device *dev = crtc->dev; struct omap_drm_private *priv = dev->dev_private; return property == priv->zorder_prop || - property == dev->mode_config.rotation_property; + property == crtc->primary->rotation_property; } static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, @@ -452,9 +453,7 @@ static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t val) { - struct drm_device *dev = crtc->dev; - - if (omap_crtc_is_plane_prop(dev, property)) { + if (omap_crtc_is_plane_prop(crtc, property)) { struct drm_plane_state *plane_state; struct drm_plane *plane = crtc->primary; @@ -479,9 +478,7 @@ static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t *val) { - struct drm_device *dev = crtc->dev; - - if (omap_crtc_is_plane_prop(dev, property)) { + if (omap_crtc_is_plane_prop(crtc, property)) { /* * Delegate property get to the primary plane. The * drm_atomic_plane_get_property() function isn't exported, but diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 31ec5d0a9576..39c5312b466c 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -293,16 +293,6 @@ static int omap_modeset_init_properties(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; - if (priv->has_dmm) { - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, - DRM_ROTATE_0 | DRM_ROTATE_90 | - DRM_ROTATE_180 | DRM_ROTATE_270 | - DRM_REFLECT_X | DRM_REFLECT_Y); - if (!dev->mode_config.rotation_property) - return -ENOMEM; - } - priv->zorder_prop = drm_property_create_range(dev, 0, "zorder", 0, 3); if (!priv->zorder_prop) return -ENOMEM; @@ -753,24 +743,32 @@ static void dev_lastclose(struct drm_device *dev) DBG("lastclose: dev=%p", dev); - if (dev->mode_config.rotation_property) { - /* need to restore default rotation state.. not sure - * if there is a cleaner way to restore properties to - * default state? Maybe a flag that properties should - * automatically be restored to default state on - * lastclose? - */ - for (i = 0; i < priv->num_crtcs; i++) { - drm_object_property_set_value(&priv->crtcs[i]->base, - dev->mode_config.rotation_property, - DRM_ROTATE_0); - } + /* need to restore default rotation state.. not sure + * if there is a cleaner way to restore properties to + * default state? Maybe a flag that properties should + * automatically be restored to default state on + * lastclose? + */ + for (i = 0; i < priv->num_crtcs; i++) { + struct drm_crtc *crtc = priv->crtcs[i]; - for (i = 0; i < priv->num_planes; i++) { - drm_object_property_set_value(&priv->planes[i]->base, - dev->mode_config.rotation_property, - DRM_ROTATE_0); - } + if (!crtc->primary->rotation_property) + continue; + + drm_object_property_set_value(&crtc->base, + crtc->primary->rotation_property, + DRM_ROTATE_0); + } + + for (i = 0; i < priv->num_planes; i++) { + struct drm_plane *plane = priv->planes[i]; + + if (!plane->rotation_property) + continue; + + drm_object_property_set_value(&plane->base, + plane->rotation_property, + DRM_ROTATE_0); } if (priv->fbdev) { diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 6ddaa5ea4b6b..0ffd5b930ec0 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -211,9 +211,17 @@ void omap_plane_install_properties(struct drm_plane *plane, struct omap_drm_private *priv = dev->dev_private; if (priv->has_dmm) { - struct drm_property *prop = dev->mode_config.rotation_property; - - drm_object_attach_property(obj, prop, DRM_ROTATE_0); + if (!plane->rotation_property) + drm_plane_create_rotation_property(plane, + DRM_ROTATE_0, + DRM_ROTATE_0 | DRM_ROTATE_90 | + DRM_ROTATE_180 | DRM_ROTATE_270 | + DRM_REFLECT_X | DRM_REFLECT_Y); + + /* Attach the rotation property also to the crtc object */ + if (plane->rotation_property && obj != &plane->base) + drm_object_attach_property(obj, plane->rotation_property, + DRM_ROTATE_0); } drm_object_attach_property(obj, priv->zorder_prop, 0); -- cgit v1.2.3 From 93ca7e00667063a8dc86f04373e85e89a09efef4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Sep 2016 19:30:56 +0300 Subject: drm/i915: Use the per-plane rotation property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On certain platforms not all planes support the same set of rotations/reflections, so let's use the per-plane property for this. This is already a problem on SKL when we use the legay cursor plane as it only supports 0|180 whereas the universal planes support 0|90|180|270, and it will be a problem on CHV soon. v2: Use drm_plane_create_rotation_property() helper v3: Drop the BIT(), use INTEL_GEN() Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson (v1) Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1474907460-10717-12-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 52 +++++++++++++++--------------------- drivers/gpu/drm/i915/intel_drv.h | 3 --- drivers/gpu/drm/i915/intel_sprite.c | 14 +++++++++- 3 files changed, 34 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index af18e2cce34b..6c5c36eba6cb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14886,6 +14886,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, struct intel_plane *primary = NULL; struct intel_plane_state *state = NULL; const uint32_t *intel_primary_formats; + unsigned int supported_rotations; unsigned int num_formats; int ret; @@ -14958,8 +14959,21 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, if (ret) goto fail; - if (INTEL_INFO(dev)->gen >= 4) - intel_create_rotation_property(dev, primary); + if (INTEL_GEN(dev) >= 9) { + supported_rotations = + DRM_ROTATE_0 | DRM_ROTATE_90 | + DRM_ROTATE_180 | DRM_ROTATE_270; + } else if (INTEL_GEN(dev) >= 4) { + supported_rotations = + DRM_ROTATE_0 | DRM_ROTATE_180; + } else { + supported_rotations = DRM_ROTATE_0; + } + + if (INTEL_GEN(dev) >= 4) + drm_plane_create_rotation_property(&primary->base, + DRM_ROTATE_0, + supported_rotations); drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); @@ -14972,24 +14986,6 @@ fail: return NULL; } -void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane) -{ - if (!dev->mode_config.rotation_property) { - unsigned long flags = DRM_ROTATE_0 | - DRM_ROTATE_180; - - if (INTEL_INFO(dev)->gen >= 9) - flags |= DRM_ROTATE_90 | DRM_ROTATE_270; - - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, flags); - } - if (dev->mode_config.rotation_property) - drm_object_attach_property(&plane->base.base, - dev->mode_config.rotation_property, - plane->base.state->rotation); -} - static int intel_check_cursor_plane(struct drm_plane *plane, struct intel_crtc_state *crtc_state, @@ -15116,17 +15112,11 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, if (ret) goto fail; - if (INTEL_INFO(dev)->gen >= 4) { - if (!dev->mode_config.rotation_property) - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, - DRM_ROTATE_0 | - DRM_ROTATE_180); - if (dev->mode_config.rotation_property) - drm_object_attach_property(&cursor->base.base, - dev->mode_config.rotation_property, - state->base.rotation); - } + if (INTEL_GEN(dev) >= 4) + drm_plane_create_rotation_property(&cursor->base, + DRM_ROTATE_0, + DRM_ROTATE_0 | + DRM_ROTATE_180); if (INTEL_INFO(dev)->gen >=9) state->scaler_id = -1; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c6ae525fe1f5..5145ff264c8e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1284,9 +1284,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, uint64_t fb_modifier, unsigned int cpp); -void intel_create_rotation_property(struct drm_device *dev, - struct intel_plane *plane); - void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, enum pipe pipe); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index be3e04623e2a..3ea6419e18b9 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1044,6 +1044,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) struct intel_plane_state *state = NULL; unsigned long possible_crtcs; const uint32_t *plane_formats; + unsigned int supported_rotations; int num_plane_formats; int ret; @@ -1119,6 +1120,15 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) goto fail; } + if (INTEL_GEN(dev) >= 9) { + supported_rotations = + DRM_ROTATE_0 | DRM_ROTATE_90 | + DRM_ROTATE_180 | DRM_ROTATE_270; + } else { + supported_rotations = + DRM_ROTATE_0 | DRM_ROTATE_180; + } + intel_plane->pipe = pipe; intel_plane->plane = plane; intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); @@ -1141,7 +1151,9 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) if (ret) goto fail; - intel_create_rotation_property(dev, intel_plane); + drm_plane_create_rotation_property(&intel_plane->base, + DRM_ROTATE_0, + supported_rotations); drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); -- cgit v1.2.3 From 8a5bbf327aa16025c78491266a6425807c7fbee0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 21 Oct 2016 15:15:40 +0100 Subject: drm: Use u64 for intermediate dotclock calculations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have reached the era where monitor bandwidths now exceed 31bits in frequency calculations, though as we stored them in kHz units we are safe from overflow in the modelines for some time. [ 48.723720] UBSAN: Undefined behaviour in ../drivers/gpu/drm/drm_modes.c:325:49 [ 48.726943] signed integer overflow: [ 48.728503] 2240 * 1000000 cannot be represented in type 'int' Reported-by: Martin Liška Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98372 Signed-off-by: Chris Wilson Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161021141540.26837-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_modes.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 173b7d335834..f64ac86deb84 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -165,6 +165,7 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, unsigned int vfieldrate, hperiod; int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; int interlace; + u64 tmp; /* allocate the drm_display_mode structure. If failure, we will * return directly @@ -322,8 +323,11 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, drm_mode->vsync_end = drm_mode->vsync_start + vsync; } /* 15/13. Find pixel clock frequency (kHz for xf86) */ - drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod; - drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP; + tmp = drm_mode->htotal; /* perform intermediate calcs in u64 */ + tmp *= HV_FACTOR * 1000; + do_div(tmp, hperiod); + tmp -= drm_mode->clock % CVT_CLOCK_STEP; + drm_mode->clock = tmp; /* 18/16. Find actual vertical frame frequency */ /* ignore - just set the mode flag for interlaced */ if (interlaced) { -- cgit v1.2.3 From 1d29815ef2d2dd0fb1a62494a9c158c0dc49e2c8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 19 Oct 2016 02:53:26 +0200 Subject: cpufreq: intel_pstate: Drop boost_iowait flag The "IOwait boosting" mechanism is only used by the get_target_pstate_use_cpu_load() governor function and the boost_iowait flag in pid_params is always set when that function is in use (and it is never set otherwise). This means that the boost_iowait flag is in fact redundant and may be dropped. For this reason, replace the boost_iowait flag check in intel_pstate_update_util() with an equivalent check against pstate_funcs.get_target_pstate and drop that flag. Signed-off-by: Rafael J. Wysocki Acked-by: Srinivas Pandruvada --- drivers/cpufreq/intel_pstate.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index f535f8123258..16d071a618b7 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -233,7 +233,6 @@ static struct cpudata **all_cpu_data; * @p_gain_pct: PID proportional gain * @i_gain_pct: PID integral gain * @d_gain_pct: PID derivative gain - * @boost_iowait: Whether or not to use iowait boosting. * * Stores per CPU model static PID configuration data. */ @@ -245,7 +244,6 @@ struct pstate_adjust_policy { int p_gain_pct; int d_gain_pct; int i_gain_pct; - bool boost_iowait; }; /** @@ -1043,7 +1041,6 @@ static const struct cpu_defaults silvermont_params = { .p_gain_pct = 14, .d_gain_pct = 0, .i_gain_pct = 4, - .boost_iowait = true, }, .funcs = { .get_max = atom_get_max_pstate, @@ -1065,7 +1062,6 @@ static const struct cpu_defaults airmont_params = { .p_gain_pct = 14, .d_gain_pct = 0, .i_gain_pct = 4, - .boost_iowait = true, }, .funcs = { .get_max = atom_get_max_pstate, @@ -1107,7 +1103,6 @@ static const struct cpu_defaults bxt_params = { .p_gain_pct = 14, .d_gain_pct = 0, .i_gain_pct = 4, - .boost_iowait = true, }, .funcs = { .get_max = core_get_max_pstate, @@ -1347,7 +1342,7 @@ static void intel_pstate_update_util(struct update_util_data *data, u64 time, struct cpudata *cpu = container_of(data, struct cpudata, update_util); u64 delta_ns; - if (pid_params.boost_iowait) { + if (pstate_funcs.get_target_pstate == get_target_pstate_use_cpu_load) { if (flags & SCHED_CPUFREQ_IOWAIT) { cpu->iowait_boost = int_tofp(1); } else if (cpu->iowait_boost) { -- cgit v1.2.3 From 185d82456edaa5a7a8c8827840b8a675c60579c0 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 21 Oct 2016 09:38:20 -0700 Subject: cpufreq: intel_pstate: Remove PID debugfs when not used When target state is calculated using get_target_pstate_use_cpu_load(), PID controller is not used, hence it has no effect on performance. So don't present debugfs entries to tune PID controller. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 16d071a618b7..d46e881ff4d7 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -636,8 +636,10 @@ static void __init intel_pstate_debug_expose_params(void) struct dentry *debugfs_parent; int i = 0; - if (hwp_active) + if (hwp_active || + pstate_funcs.get_target_pstate == get_target_pstate_use_cpu_load) return; + debugfs_parent = debugfs_create_dir("pstate_snb", NULL); if (IS_ERR_OR_NULL(debugfs_parent)) return; -- cgit v1.2.3 From 59d65b73a23cee48e6f3e44686f199d79b7ee854 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Fri, 14 Oct 2016 10:47:49 -0700 Subject: PM / Domains: Make genpd state allocation dynamic Allow PM Domain states to be defined dynamically by the drivers. This removes the limitation on the maximum number of states possible for a domain. Suggested-by: Ulf Hansson Signed-off-by: Lina Iyer Acked-by: Ulf Hansson Reviewed-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-imx/gpc.c | 17 ++++++++++------- drivers/base/power/domain.c | 35 +++++++++++++++++++++++------------ include/linux/pm_domain.h | 5 ++--- 3 files changed, 35 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 0df062d8b2c9..57a410bbb6a2 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -380,13 +380,6 @@ static struct pu_domain imx6q_pu_domain = { .name = "PU", .power_off = imx6q_pm_pu_power_off, .power_on = imx6q_pm_pu_power_on, - .states = { - [0] = { - .power_off_latency_ns = 25000, - .power_on_latency_ns = 2000000, - }, - }, - .state_count = 1, }, }; @@ -430,6 +423,16 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg) if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) return 0; + imx6q_pu_domain.base.states = devm_kzalloc(dev, + sizeof(*imx6q_pu_domain.base.states), + GFP_KERNEL); + if (!imx6q_pu_domain.base.states) + return -ENOMEM; + + imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000; + imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000; + imx6q_pu_domain.base.state_count = 1; + pm_genpd_init(&imx6q_pu_domain.base, NULL, false); return of_genpd_add_provider_onecell(dev->of_node, &imx_gpc_onecell_data); diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index e023066e4215..37ab7f1ef178 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1282,6 +1282,21 @@ out: } EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); +static int genpd_set_default_power_state(struct generic_pm_domain *genpd) +{ + struct genpd_power_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + genpd->states = state; + genpd->state_count = 1; + genpd->free = state; + + return 0; +} + /** * pm_genpd_init - Initialize a generic I/O PM domain object. * @genpd: PM domain object to initialize. @@ -1293,6 +1308,8 @@ EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); int pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off) { + int ret; + if (IS_ERR_OR_NULL(genpd)) return -EINVAL; @@ -1325,19 +1342,12 @@ int pm_genpd_init(struct generic_pm_domain *genpd, genpd->dev_ops.start = pm_clk_resume; } - if (genpd->state_idx >= GENPD_MAX_NUM_STATES) { - pr_warn("Initial state index out of bounds.\n"); - genpd->state_idx = GENPD_MAX_NUM_STATES - 1; - } - - if (genpd->state_count > GENPD_MAX_NUM_STATES) { - pr_warn("Limiting states to %d\n", GENPD_MAX_NUM_STATES); - genpd->state_count = GENPD_MAX_NUM_STATES; - } - /* Use only one "off" state if there were no states declared */ - if (genpd->state_count == 0) - genpd->state_count = 1; + if (genpd->state_count == 0) { + ret = genpd_set_default_power_state(genpd); + if (ret) + return ret; + } mutex_lock(&gpd_list_lock); list_add(&genpd->gpd_list_node, &gpd_list); @@ -1377,6 +1387,7 @@ static int genpd_remove(struct generic_pm_domain *genpd) list_del(&genpd->gpd_list_node); mutex_unlock(&genpd->lock); cancel_work_sync(&genpd->power_off_work); + kfree(genpd->free); pr_debug("%s: removed %s\n", __func__, genpd->name); return 0; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index a09fe5c009c8..de1d8f331b03 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -19,8 +19,6 @@ /* Defines used for the flags field in the struct generic_pm_domain */ #define GENPD_FLAG_PM_CLK (1U << 0) /* PM domain uses PM clk */ -#define GENPD_MAX_NUM_STATES 8 /* Number of possible low power states */ - enum gpd_status { GPD_STATE_ACTIVE = 0, /* PM domain is active */ GPD_STATE_POWER_OFF, /* PM domain is off */ @@ -70,9 +68,10 @@ struct generic_pm_domain { void (*detach_dev)(struct generic_pm_domain *domain, struct device *dev); unsigned int flags; /* Bit field of configs for genpd */ - struct genpd_power_state states[GENPD_MAX_NUM_STATES]; + struct genpd_power_state *states; unsigned int state_count; /* number of states */ unsigned int state_idx; /* state that genpd will go to when off */ + void *free; /* Free the state that was allocated for default */ }; -- cgit v1.2.3 From 30f604283e05d34cb10108c7ba017e5f4fc9d62c Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Fri, 14 Oct 2016 10:47:51 -0700 Subject: PM / Domains: Allow domain power states to be read from DT This patch allows domains to define idle states in the DT. SoC's can define domain idle states in DT using the "domain-idle-states" property of the domain provider. Add API to read the idle states from DT that can be set in the genpd object. This patch is based on the original patch by Marc Titinger. Signed-off-by: Marc Titinger Signed-off-by: Ulf Hansson Signed-off-by: Lina Iyer Reviewed-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 94 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_domain.h | 8 ++++ 2 files changed, 102 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 37ab7f1ef178..9af75ba0472a 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1916,6 +1916,100 @@ out: return ret ? -EPROBE_DEFER : 0; } EXPORT_SYMBOL_GPL(genpd_dev_pm_attach); + +static const struct of_device_id idle_state_match[] = { + { .compatible = "arm,idle-state", }, + { } +}; + +static int genpd_parse_state(struct genpd_power_state *genpd_state, + struct device_node *state_node) +{ + int err; + u32 residency; + u32 entry_latency, exit_latency; + const struct of_device_id *match_id; + + match_id = of_match_node(idle_state_match, state_node); + if (!match_id) + return -EINVAL; + + err = of_property_read_u32(state_node, "entry-latency-us", + &entry_latency); + if (err) { + pr_debug(" * %s missing entry-latency-us property\n", + state_node->full_name); + return -EINVAL; + } + + err = of_property_read_u32(state_node, "exit-latency-us", + &exit_latency); + if (err) { + pr_debug(" * %s missing exit-latency-us property\n", + state_node->full_name); + return -EINVAL; + } + + err = of_property_read_u32(state_node, "min-residency-us", &residency); + if (!err) + genpd_state->residency_ns = 1000 * residency; + + genpd_state->power_on_latency_ns = 1000 * exit_latency; + genpd_state->power_off_latency_ns = 1000 * entry_latency; + + return 0; +} + +/** + * of_genpd_parse_idle_states: Return array of idle states for the genpd. + * + * @dn: The genpd device node + * @states: The pointer to which the state array will be saved. + * @n: The count of elements in the array returned from this function. + * + * Returns the device states parsed from the OF node. The memory for the states + * is allocated by this function and is the responsibility of the caller to + * free the memory after use. + */ +int of_genpd_parse_idle_states(struct device_node *dn, + struct genpd_power_state **states, int *n) +{ + struct genpd_power_state *st; + struct device_node *np; + int i = 0; + int err, ret; + int count; + struct of_phandle_iterator it; + + count = of_count_phandle_with_args(dn, "domain-idle-states", NULL); + if (!count) + return -EINVAL; + + st = kcalloc(count, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + /* Loop over the phandles until all the requested entry is found */ + of_for_each_phandle(&it, err, dn, "domain-idle-states", NULL, 0) { + np = it.node; + ret = genpd_parse_state(&st[i++], np); + if (ret) { + pr_err + ("Parsing idle state node %s failed with err %d\n", + np->full_name, ret); + of_node_put(np); + kfree(st); + return ret; + } + } + + *n = count; + *states = st; + + return 0; +} +EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states); + #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */ diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index f4492eb71701..b4894969fbec 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -205,6 +205,8 @@ extern int of_genpd_add_device(struct of_phandle_args *args, extern int of_genpd_add_subdomain(struct of_phandle_args *parent, struct of_phandle_args *new_subdomain); extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); +extern int of_genpd_parse_idle_states(struct device_node *dn, + struct genpd_power_state **states, int *n); int genpd_dev_pm_attach(struct device *dev); #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */ @@ -234,6 +236,12 @@ static inline int of_genpd_add_subdomain(struct of_phandle_args *parent, return -ENODEV; } +static inline int of_genpd_parse_idle_states(struct device_node *dn, + struct genpd_power_state **states, int *n) +{ + return -ENODEV; +} + static inline int genpd_dev_pm_attach(struct device *dev) { return -ENODEV; -- cgit v1.2.3 From 0c9b694a8a7d4853318c4f2ce315afa2bd3664b6 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Fri, 14 Oct 2016 10:47:52 -0700 Subject: PM / Domains: Save the fwnode in genpd_power_state Save the fwnode for the genpd state in the state node. PM Domain clients may use the fwnode to read in the platform specific domain state properties and associate them with the state. Signed-off-by: Lina Iyer Acked-by: Ulf Hansson Reviewed-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 1 + include/linux/pm_domain.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 9af75ba0472a..1a6073aaca0e 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1956,6 +1956,7 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, genpd_state->power_on_latency_ns = 1000 * exit_latency; genpd_state->power_off_latency_ns = 1000 * entry_latency; + genpd_state->fwnode = &state_node->fwnode; return 0; } diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index b4894969fbec..6a8988166899 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -39,6 +39,7 @@ struct genpd_power_state { s64 power_off_latency_ns; s64 power_on_latency_ns; s64 residency_ns; + struct fwnode_handle *fwnode; }; struct generic_pm_domain { -- cgit v1.2.3 From 35241d12f750d2f1556a9c85f175ce7044716881 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Fri, 14 Oct 2016 10:47:54 -0700 Subject: PM / Domains: Abstract genpd locking Abstract genpd lock/unlock calls, in preparation for domain specific locks added in the following patches. Signed-off-by: Lina Iyer Signed-off-by: Ulf Hansson Reviewed-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 121 +++++++++++++++++++++++++++++--------------- include/linux/pm_domain.h | 5 +- 2 files changed, 85 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 1a6073aaca0e..4194012cdf86 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -39,6 +39,46 @@ static LIST_HEAD(gpd_list); static DEFINE_MUTEX(gpd_list_lock); +struct genpd_lock_ops { + void (*lock)(struct generic_pm_domain *genpd); + void (*lock_nested)(struct generic_pm_domain *genpd, int depth); + int (*lock_interruptible)(struct generic_pm_domain *genpd); + void (*unlock)(struct generic_pm_domain *genpd); +}; + +static void genpd_lock_mtx(struct generic_pm_domain *genpd) +{ + mutex_lock(&genpd->mlock); +} + +static void genpd_lock_nested_mtx(struct generic_pm_domain *genpd, + int depth) +{ + mutex_lock_nested(&genpd->mlock, depth); +} + +static int genpd_lock_interruptible_mtx(struct generic_pm_domain *genpd) +{ + return mutex_lock_interruptible(&genpd->mlock); +} + +static void genpd_unlock_mtx(struct generic_pm_domain *genpd) +{ + return mutex_unlock(&genpd->mlock); +} + +static const struct genpd_lock_ops genpd_mtx_ops = { + .lock = genpd_lock_mtx, + .lock_nested = genpd_lock_nested_mtx, + .lock_interruptible = genpd_lock_interruptible_mtx, + .unlock = genpd_unlock_mtx, +}; + +#define genpd_lock(p) p->lock_ops->lock(p) +#define genpd_lock_nested(p, d) p->lock_ops->lock_nested(p, d) +#define genpd_lock_interruptible(p) p->lock_ops->lock_interruptible(p) +#define genpd_unlock(p) p->lock_ops->unlock(p) + /* * Get the generic PM domain for a particular struct device. * This validates the struct device pointer, the PM domain pointer, @@ -200,9 +240,9 @@ static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) genpd_sd_counter_inc(master); - mutex_lock_nested(&master->lock, depth + 1); + genpd_lock_nested(master, depth + 1); ret = genpd_poweron(master, depth + 1); - mutex_unlock(&master->lock); + genpd_unlock(master); if (ret) { genpd_sd_counter_dec(master); @@ -255,9 +295,9 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, spin_unlock_irq(&dev->power.lock); if (!IS_ERR(genpd)) { - mutex_lock(&genpd->lock); + genpd_lock(genpd); genpd->max_off_time_changed = true; - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); } dev = dev->parent; @@ -354,9 +394,9 @@ static void genpd_power_off_work_fn(struct work_struct *work) genpd = container_of(work, struct generic_pm_domain, power_off_work); - mutex_lock(&genpd->lock); + genpd_lock(genpd); genpd_poweroff(genpd, true); - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); } /** @@ -472,9 +512,9 @@ static int genpd_runtime_suspend(struct device *dev) if (dev->power.irq_safe) return 0; - mutex_lock(&genpd->lock); + genpd_lock(genpd); genpd_poweroff(genpd, false); - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); return 0; } @@ -509,9 +549,9 @@ static int genpd_runtime_resume(struct device *dev) goto out; } - mutex_lock(&genpd->lock); + genpd_lock(genpd); ret = genpd_poweron(genpd, 0); - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); if (ret) return ret; @@ -547,9 +587,9 @@ err_stop: genpd_stop_dev(genpd, dev); err_poweroff: if (!dev->power.irq_safe) { - mutex_lock(&genpd->lock); + genpd_lock(genpd); genpd_poweroff(genpd, 0); - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); } return ret; @@ -732,20 +772,20 @@ static int pm_genpd_prepare(struct device *dev) if (resume_needed(dev, genpd)) pm_runtime_resume(dev); - mutex_lock(&genpd->lock); + genpd_lock(genpd); if (genpd->prepared_count++ == 0) genpd->suspended_count = 0; - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); ret = pm_generic_prepare(dev); if (ret) { - mutex_lock(&genpd->lock); + genpd_lock(genpd); genpd->prepared_count--; - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); } return ret; @@ -936,13 +976,13 @@ static void pm_genpd_complete(struct device *dev) pm_generic_complete(dev); - mutex_lock(&genpd->lock); + genpd_lock(genpd); genpd->prepared_count--; if (!genpd->prepared_count) genpd_queue_power_off_work(genpd); - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); } /** @@ -1071,7 +1111,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, if (IS_ERR(gpd_data)) return PTR_ERR(gpd_data); - mutex_lock(&genpd->lock); + genpd_lock(genpd); if (genpd->prepared_count > 0) { ret = -EAGAIN; @@ -1088,7 +1128,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, list_add_tail(&gpd_data->base.list_node, &genpd->dev_list); out: - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); if (ret) genpd_free_dev_data(dev, gpd_data); @@ -1130,7 +1170,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, gpd_data = to_gpd_data(pdd); dev_pm_qos_remove_notifier(dev, &gpd_data->nb); - mutex_lock(&genpd->lock); + genpd_lock(genpd); if (genpd->prepared_count > 0) { ret = -EAGAIN; @@ -1145,14 +1185,14 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, list_del_init(&pdd->list_node); - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); genpd_free_dev_data(dev, gpd_data); return 0; out: - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); dev_pm_qos_add_notifier(dev, &gpd_data->nb); return ret; @@ -1187,8 +1227,8 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd, if (!link) return -ENOMEM; - mutex_lock(&subdomain->lock); - mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING); + genpd_lock(subdomain); + genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING); if (genpd->status == GPD_STATE_POWER_OFF && subdomain->status != GPD_STATE_POWER_OFF) { @@ -1211,8 +1251,8 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd, genpd_sd_counter_inc(genpd); out: - mutex_unlock(&genpd->lock); - mutex_unlock(&subdomain->lock); + genpd_unlock(genpd); + genpd_unlock(subdomain); if (ret) kfree(link); return ret; @@ -1250,8 +1290,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)) return -EINVAL; - mutex_lock(&subdomain->lock); - mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING); + genpd_lock(subdomain); + genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING); if (!list_empty(&subdomain->master_links) || subdomain->device_count) { pr_warn("%s: unable to remove subdomain %s\n", genpd->name, @@ -1275,8 +1315,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, } out: - mutex_unlock(&genpd->lock); - mutex_unlock(&subdomain->lock); + genpd_unlock(genpd); + genpd_unlock(subdomain); return ret; } @@ -1316,7 +1356,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd, INIT_LIST_HEAD(&genpd->master_links); INIT_LIST_HEAD(&genpd->slave_links); INIT_LIST_HEAD(&genpd->dev_list); - mutex_init(&genpd->lock); + mutex_init(&genpd->mlock); + genpd->lock_ops = &genpd_mtx_ops; genpd->gov = gov; INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn); atomic_set(&genpd->sd_count, 0); @@ -1364,16 +1405,16 @@ static int genpd_remove(struct generic_pm_domain *genpd) if (IS_ERR_OR_NULL(genpd)) return -EINVAL; - mutex_lock(&genpd->lock); + genpd_lock(genpd); if (genpd->has_provider) { - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); pr_err("Provider present, unable to remove %s\n", genpd->name); return -EBUSY; } if (!list_empty(&genpd->master_links) || genpd->device_count) { - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); pr_err("%s: unable to remove %s\n", __func__, genpd->name); return -EBUSY; } @@ -1385,7 +1426,7 @@ static int genpd_remove(struct generic_pm_domain *genpd) } list_del(&genpd->gpd_list_node); - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); cancel_work_sync(&genpd->power_off_work); kfree(genpd->free); pr_debug("%s: removed %s\n", __func__, genpd->name); @@ -1909,9 +1950,9 @@ int genpd_dev_pm_attach(struct device *dev) dev->pm_domain->detach = genpd_dev_pm_detach; dev->pm_domain->sync = genpd_dev_pm_sync; - mutex_lock(&pd->lock); + genpd_lock(pd); ret = genpd_poweron(pd, 0); - mutex_unlock(&pd->lock); + genpd_unlock(pd); out: return ret ? -EPROBE_DEFER : 0; } @@ -2064,7 +2105,7 @@ static int pm_genpd_summary_one(struct seq_file *s, char state[16]; int ret; - ret = mutex_lock_interruptible(&genpd->lock); + ret = genpd_lock_interruptible(genpd); if (ret) return -ERESTARTSYS; @@ -2101,7 +2142,7 @@ static int pm_genpd_summary_one(struct seq_file *s, seq_puts(s, "\n"); exit: - mutex_unlock(&genpd->lock); + genpd_unlock(genpd); return 0; } diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 6a8988166899..811b968eb740 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -42,13 +42,14 @@ struct genpd_power_state { struct fwnode_handle *fwnode; }; +struct genpd_lock_ops; + struct generic_pm_domain { struct dev_pm_domain domain; /* PM domain operations */ struct list_head gpd_list_node; /* Node in the global PM domains list */ struct list_head master_links; /* Links with PM domain as a master */ struct list_head slave_links; /* Links with PM domain as a slave */ struct list_head dev_list; /* List of devices */ - struct mutex lock; struct dev_power_governor *gov; struct work_struct power_off_work; struct fwnode_handle *provider; /* Identity of the domain provider */ @@ -74,6 +75,8 @@ struct generic_pm_domain { unsigned int state_count; /* number of states */ unsigned int state_idx; /* state that genpd will go to when off */ void *free; /* Free the state that was allocated for default */ + const struct genpd_lock_ops *lock_ops; + struct mutex mlock; }; -- cgit v1.2.3 From d716f4798ff8c65ace4a6ab291f9a4ff265df4ba Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Fri, 14 Oct 2016 10:47:55 -0700 Subject: PM / Domains: Support IRQ safe PM domains Generic Power Domains currently support turning on/off only in process context. This prevents the usage of PM domains for domains that could be powered on/off in a context where IRQs are disabled. Many such domains exist today and do not get powered off, when the IRQ safe devices in that domain are powered off, because of this limitation. However, not all domains can operate in IRQ safe contexts. Genpd therefore, has to support both cases where the domain may or may not operate in IRQ safe contexts. Configuring genpd to use an appropriate lock for that domain, would allow domains that have IRQ safe devices to runtime suspend and resume, in atomic context. To achieve domain specific locking, set the domain's ->flag to GENPD_FLAG_IRQ_SAFE while defining the domain. This indicates that genpd should use a spinlock instead of a mutex for locking the domain. Locking is abstracted through genpd_lock() and genpd_unlock() functions that use the flag to determine the appropriate lock to be used for that domain. Domains that have lower latency to suspend and resume and can operate with IRQs disabled may now be able to save power, when the component devices and sub-domains are idle at runtime. The restriction this imposes on the domain hierarchy is that non-IRQ safe domains may not have IRQ-safe subdomains, but IRQ safe domains may have IRQ safe and non-IRQ safe subdomains and devices. Signed-off-by: Lina Iyer Acked-by: Ulf Hansson Reviewed-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 111 ++++++++++++++++++++++++++++++++++++++++---- include/linux/pm_domain.h | 10 +++- 2 files changed, 110 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 4194012cdf86..aac656a889dc 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -74,11 +74,70 @@ static const struct genpd_lock_ops genpd_mtx_ops = { .unlock = genpd_unlock_mtx, }; +static void genpd_lock_spin(struct generic_pm_domain *genpd) + __acquires(&genpd->slock) +{ + unsigned long flags; + + spin_lock_irqsave(&genpd->slock, flags); + genpd->lock_flags = flags; +} + +static void genpd_lock_nested_spin(struct generic_pm_domain *genpd, + int depth) + __acquires(&genpd->slock) +{ + unsigned long flags; + + spin_lock_irqsave_nested(&genpd->slock, flags, depth); + genpd->lock_flags = flags; +} + +static int genpd_lock_interruptible_spin(struct generic_pm_domain *genpd) + __acquires(&genpd->slock) +{ + unsigned long flags; + + spin_lock_irqsave(&genpd->slock, flags); + genpd->lock_flags = flags; + return 0; +} + +static void genpd_unlock_spin(struct generic_pm_domain *genpd) + __releases(&genpd->slock) +{ + spin_unlock_irqrestore(&genpd->slock, genpd->lock_flags); +} + +static const struct genpd_lock_ops genpd_spin_ops = { + .lock = genpd_lock_spin, + .lock_nested = genpd_lock_nested_spin, + .lock_interruptible = genpd_lock_interruptible_spin, + .unlock = genpd_unlock_spin, +}; + #define genpd_lock(p) p->lock_ops->lock(p) #define genpd_lock_nested(p, d) p->lock_ops->lock_nested(p, d) #define genpd_lock_interruptible(p) p->lock_ops->lock_interruptible(p) #define genpd_unlock(p) p->lock_ops->unlock(p) +#define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE) + +static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev, + struct generic_pm_domain *genpd) +{ + bool ret; + + ret = pm_runtime_is_irq_safe(dev) && !genpd_is_irq_safe(genpd); + + /* Warn once for each IRQ safe dev in no sleep domain */ + if (ret) + dev_warn_once(dev, "PM domain %s will not be powered off\n", + genpd->name); + + return ret; +} + /* * Get the generic PM domain for a particular struct device. * This validates the struct device pointer, the PM domain pointer, @@ -343,7 +402,12 @@ static int genpd_poweroff(struct generic_pm_domain *genpd, bool is_async) if (stat > PM_QOS_FLAGS_NONE) return -EBUSY; - if (!pm_runtime_suspended(pdd->dev) || pdd->dev->power.irq_safe) + /* + * Do not allow PM domain to be powered off, when an IRQ safe + * device is part of a non-IRQ safe domain. + */ + if (!pm_runtime_suspended(pdd->dev) || + irq_safe_dev_in_no_sleep_domain(pdd->dev, genpd)) not_suspended++; } @@ -506,10 +570,10 @@ static int genpd_runtime_suspend(struct device *dev) } /* - * If power.irq_safe is set, this routine will be run with interrupts - * off, so it can't use mutexes. + * If power.irq_safe is set, this routine may be run with + * IRQs disabled, so suspend only if the PM domain also is irq_safe. */ - if (dev->power.irq_safe) + if (irq_safe_dev_in_no_sleep_domain(dev, genpd)) return 0; genpd_lock(genpd); @@ -543,8 +607,11 @@ static int genpd_runtime_resume(struct device *dev) if (IS_ERR(genpd)) return -EINVAL; - /* If power.irq_safe, the PM domain is never powered off. */ - if (dev->power.irq_safe) { + /* + * As we don't power off a non IRQ safe domain, which holds + * an IRQ safe device, we don't need to restore power to it. + */ + if (irq_safe_dev_in_no_sleep_domain(dev, genpd)) { timed = false; goto out; } @@ -586,7 +653,8 @@ static int genpd_runtime_resume(struct device *dev) err_stop: genpd_stop_dev(genpd, dev); err_poweroff: - if (!dev->power.irq_safe) { + if (!pm_runtime_is_irq_safe(dev) || + (pm_runtime_is_irq_safe(dev) && genpd_is_irq_safe(genpd))) { genpd_lock(genpd); genpd_poweroff(genpd, 0); genpd_unlock(genpd); @@ -1223,6 +1291,17 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd, || genpd == subdomain) return -EINVAL; + /* + * If the domain can be powered on/off in an IRQ safe + * context, ensure that the subdomain can also be + * powered on/off in that context. + */ + if (!genpd_is_irq_safe(genpd) && genpd_is_irq_safe(subdomain)) { + WARN("Parent %s of subdomain %s must be IRQ safe\n", + genpd->name, subdomain->name); + return -EINVAL; + } + link = kzalloc(sizeof(*link), GFP_KERNEL); if (!link) return -ENOMEM; @@ -1337,6 +1416,17 @@ static int genpd_set_default_power_state(struct generic_pm_domain *genpd) return 0; } +static void genpd_lock_init(struct generic_pm_domain *genpd) +{ + if (genpd->flags & GENPD_FLAG_IRQ_SAFE) { + spin_lock_init(&genpd->slock); + genpd->lock_ops = &genpd_spin_ops; + } else { + mutex_init(&genpd->mlock); + genpd->lock_ops = &genpd_mtx_ops; + } +} + /** * pm_genpd_init - Initialize a generic I/O PM domain object. * @genpd: PM domain object to initialize. @@ -1356,8 +1446,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd, INIT_LIST_HEAD(&genpd->master_links); INIT_LIST_HEAD(&genpd->slave_links); INIT_LIST_HEAD(&genpd->dev_list); - mutex_init(&genpd->mlock); - genpd->lock_ops = &genpd_mtx_ops; + genpd_lock_init(genpd); genpd->gov = gov; INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn); atomic_set(&genpd->sd_count, 0); @@ -2131,7 +2220,9 @@ static int pm_genpd_summary_one(struct seq_file *s, } list_for_each_entry(pm_data, &genpd->dev_list, list_node) { - kobj_path = kobject_get_path(&pm_data->dev->kobj, GFP_KERNEL); + kobj_path = kobject_get_path(&pm_data->dev->kobj, + genpd_is_irq_safe(genpd) ? + GFP_ATOMIC : GFP_KERNEL); if (kobj_path == NULL) continue; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 811b968eb740..81ece61075df 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -15,9 +15,11 @@ #include #include #include +#include /* Defines used for the flags field in the struct generic_pm_domain */ #define GENPD_FLAG_PM_CLK (1U << 0) /* PM domain uses PM clk */ +#define GENPD_FLAG_IRQ_SAFE (1U << 1) /* PM domain operates in atomic */ enum gpd_status { GPD_STATE_ACTIVE = 0, /* PM domain is active */ @@ -76,7 +78,13 @@ struct generic_pm_domain { unsigned int state_idx; /* state that genpd will go to when off */ void *free; /* Free the state that was allocated for default */ const struct genpd_lock_ops *lock_ops; - struct mutex mlock; + union { + struct mutex mlock; + struct { + spinlock_t slock; + unsigned long lock_flags; + }; + }; }; -- cgit v1.2.3 From e2aad66638f995f825e637ef621f45d902c130d1 Mon Sep 17 00:00:00 2001 From: Sangwon Jee Date: Fri, 21 Oct 2016 15:28:59 -0700 Subject: Input: melfas_mip4 - add product_id sysfs attribute Add product_id sysfs attribute and update protocol version to support it. Signed-off-by: Sangwon Jee Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/melfas_mip4.c | 40 +++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 552a3773f79d..8739cb718b4c 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -33,7 +33,7 @@ /***************************************************************** * Protocol - * Version : MIP 4.0 Rev 4.6 + * Version : MIP 4.0 Rev 5.4 *****************************************************************/ /* Address */ @@ -81,6 +81,9 @@ #define MIP4_R1_INFO_IC_HW_CATEGORY 0x77 #define MIP4_R1_INFO_CONTACT_THD_SCR 0x78 #define MIP4_R1_INFO_CONTACT_THD_KEY 0x7A +#define MIP4_R1_INFO_PID 0x7C +#define MIP4_R1_INFO_VID 0x7E +#define MIP4_R1_INFO_SLAVE_ADDR 0x80 #define MIP4_R0_EVENT 0x02 #define MIP4_R1_EVENT_SUPPORTED_FUNC 0x00 @@ -157,6 +160,7 @@ struct mip4_ts { char phys[32]; char product_name[16]; + u16 product_id; char ic_name[4]; unsigned int max_x; @@ -264,6 +268,18 @@ static int mip4_query_device(struct mip4_ts *ts) dev_dbg(&ts->client->dev, "product name: %.*s\n", (int)sizeof(ts->product_name), ts->product_name); + /* Product ID */ + cmd[0] = MIP4_R0_INFO; + cmd[1] = MIP4_R1_INFO_PID; + error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), buf, 2); + if (error) { + dev_warn(&ts->client->dev, + "Failed to retrieve product id: %d\n", error); + } else { + ts->product_id = get_unaligned_le16(&buf[0]); + dev_dbg(&ts->client->dev, "product id: %04X\n", ts->product_id); + } + /* IC name */ cmd[0] = MIP4_R0_INFO; cmd[1] = MIP4_R1_INFO_IC_NAME; @@ -1348,6 +1364,25 @@ static ssize_t mip4_sysfs_read_hw_version(struct device *dev, static DEVICE_ATTR(hw_version, S_IRUGO, mip4_sysfs_read_hw_version, NULL); +static ssize_t mip4_sysfs_read_product_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct mip4_ts *ts = i2c_get_clientdata(client); + size_t count; + + mutex_lock(&ts->input->mutex); + + count = snprintf(buf, PAGE_SIZE, "%04X\n", ts->product_id); + + mutex_unlock(&ts->input->mutex); + + return count; +} + +static DEVICE_ATTR(product_id, S_IRUGO, mip4_sysfs_read_product_id, NULL); + static ssize_t mip4_sysfs_read_ic_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -1371,6 +1406,7 @@ static DEVICE_ATTR(ic_name, S_IRUGO, mip4_sysfs_read_ic_name, NULL); static struct attribute *mip4_attrs[] = { &dev_attr_fw_version.attr, &dev_attr_hw_version.attr, + &dev_attr_product_id.attr, &dev_attr_ic_name.attr, &dev_attr_update_fw.attr, NULL, @@ -1572,6 +1608,6 @@ static struct i2c_driver mip4_driver = { module_i2c_driver(mip4_driver); MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen"); -MODULE_VERSION("2016.09.28"); +MODULE_VERSION("2016.10.20"); MODULE_AUTHOR("Sangwon Jee "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 77b425399f6d5f1b04c58738bc10ca6decb10c9a Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Fri, 21 Oct 2016 15:35:33 -0700 Subject: Input: i8042 - use chassis info to skip selftest on Asus laptops Instead of relying on this model zoo let's skip selftest on all newer Asus laptops (newer as in when they changed "Computer" -> "COMPUTER" in their DMI data). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 74 +---------------------------------- 1 file changed, 1 insertion(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f4bfb4b2d50a..b42787e21d0a 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -517,79 +517,7 @@ static const struct dmi_system_id i8042_dmi_noselftest_table[] = { { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "A455LD"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "K401LB"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "K501LB"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "K501LX"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "R409L"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "V502LX"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "X302LA"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "X450LD"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "X455LAB"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "X455LDB"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "X455LF"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "Z450LA"), + DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ }, }, { } -- cgit v1.2.3 From fbf0296c25ce3ae0816d2f72aaef70e7da9e3a7a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 21 Oct 2016 21:55:31 +0100 Subject: drm/i915: Stop setting SNB min-freq-table 0 on powersave setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The min-freq-table is an array of values that match each CPU frequency to an equivalent GPU frequency. Setting a single value of 0 on init is both illegal (generates an error from the PCU) and nonsensical. Let's see if we survive without that error. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161021205531.8651-1-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_pm.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0a9e7f2045d4..ea01b406d776 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5589,10 +5589,6 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000); I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); - if (ret) - DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); - reset_rps(dev_priv, gen6_set_rps); rc6vids = 0; -- cgit v1.2.3 From 5b560c3a99a0d1a65132ce6f2f5a8505536613e4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 21 Oct 2016 22:22:43 +0300 Subject: drm/msm/mdp5: Use per-plane rotation property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global mode_config.rotation_property is going away, switch over to per-plane rotation_property. v2: Drop the BIT() Cc: Rob Clark Cc: Jilai Wang Cc: Archit Taneja Signed-off-by: Ville Syrjälä Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477077768-4274-2-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 951c002b05df..2653ad893ebc 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -75,15 +75,11 @@ static void mdp5_plane_install_rotation_property(struct drm_device *dev, !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) return; - if (!dev->mode_config.rotation_property) - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, - DRM_ROTATE_0 | DRM_REFLECT_X | DRM_REFLECT_Y); - - if (dev->mode_config.rotation_property) - drm_object_attach_property(&plane->base, - dev->mode_config.rotation_property, - DRM_ROTATE_0); + drm_plane_create_rotation_property(plane, + DRM_ROTATE_0, + DRM_ROTATE_0 | + DRM_REFLECT_X | + DRM_REFLECT_Y); } /* helper to install properties which are common to planes and crtcs */ -- cgit v1.2.3 From 574a37b1bb07499778e6f46b56b6dda18151ad04 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 21 Oct 2016 22:22:44 +0300 Subject: drm/msm/mdp5: Advertize 180 degree rotation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the hardware can apparently do both X and Y reflection, we can advertize also 180 degree rotation as thats just X+Y reflection. v2: Drop the BIT() Cc: Rob Clark Cc: Jilai Wang Cc: Archit Taneja Signed-off-by: Ville Syrjälä Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477077768-4274-3-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 2653ad893ebc..cf50d3ec8d1b 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -78,6 +78,7 @@ static void mdp5_plane_install_rotation_property(struct drm_device *dev, drm_plane_create_rotation_property(plane, DRM_ROTATE_0, DRM_ROTATE_0 | + DRM_ROTATE_180 | DRM_REFLECT_X | DRM_REFLECT_Y); } @@ -285,6 +286,8 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, plane_enabled(old_state), plane_enabled(state)); if (plane_enabled(state)) { + unsigned int rotation; + format = to_mdp_format(msm_framebuffer_format(state->fb)); if (MDP_FORMAT_IS_YUV(format) && !pipe_supports_yuv(mdp5_plane->caps)) { @@ -305,8 +308,13 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, return -EINVAL; } - hflip = !!(state->rotation & DRM_REFLECT_X); - vflip = !!(state->rotation & DRM_REFLECT_Y); + rotation = drm_rotation_simplify(state->rotation, + DRM_ROTATE_0 | + DRM_REFLECT_X | + DRM_REFLECT_Y); + hflip = !!(rotation & DRM_REFLECT_X); + vflip = !!(rotation & DRM_REFLECT_Y); + if ((vflip && !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) || (hflip && !(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP))) { dev_err(plane->dev->dev, @@ -677,6 +685,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, int pe_top[COMP_MAX], pe_bottom[COMP_MAX]; uint32_t hdecm = 0, vdecm = 0; uint32_t pix_format; + unsigned int rotation; bool vflip, hflip; unsigned long flags; int ret; @@ -739,8 +748,12 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, config |= get_scale_config(format, src_h, crtc_h, false); DBG("scale config = %x", config); - hflip = !!(pstate->rotation & DRM_REFLECT_X); - vflip = !!(pstate->rotation & DRM_REFLECT_Y); + rotation = drm_rotation_simplify(pstate->rotation, + DRM_ROTATE_0 | + DRM_REFLECT_X | + DRM_REFLECT_Y); + hflip = !!(rotation & DRM_REFLECT_X); + vflip = !!(rotation & DRM_REFLECT_Y); spin_lock_irqsave(&mdp5_plane->pipe_lock, flags); -- cgit v1.2.3 From 6686df8cf1cf589c54343372e3524bf52cda038e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 21 Oct 2016 22:22:45 +0300 Subject: drm: RIP mode_config->rotation_property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all drivers have been converted over to the per-plane rotation property, we can just nuke the global rotation property. v2: Rebase due to BIT(),__builtin_ffs() & co. Deal with superfluous code shuffling Signed-off-by: Ville Syrjälä Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477077768-4274-4-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_atomic.c | 6 ++---- drivers/gpu/drm/drm_blend.c | 32 ++++---------------------------- drivers/gpu/drm/drm_fb_helper.c | 7 +------ include/drm/drm_blend.h | 2 -- include/drm/drm_crtc.h | 5 ----- 5 files changed, 7 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index f81706387889..1b5a32df9a9a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -705,8 +705,7 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, state->src_w = val; } else if (property == config->prop_src_h) { state->src_h = val; - } else if (property == config->rotation_property || - property == plane->rotation_property) { + } else if (property == plane->rotation_property) { if (!is_power_of_2(val & DRM_ROTATE_MASK)) return -EINVAL; state->rotation = val; @@ -766,8 +765,7 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->src_w; } else if (property == config->prop_src_h) { *val = state->src_h; - } else if (property == config->rotation_property || - property == plane->rotation_property) { + } else if (property == plane->rotation_property) { *val = state->rotation; } else if (property == plane->zpos_property) { *val = state->zpos; diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index e52aece30900..1f2412c7ccfd 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c @@ -89,7 +89,7 @@ * On top of this basic transformation additional properties can be exposed by * the driver: * - * - Rotation is set up with drm_mode_create_rotation_property(). It adds a + * - Rotation is set up with drm_plane_create_rotation_property(). It adds a * rotation and reflection step between the source and destination rectangles. * Without this property the rectangle is only scaled, but not rotated or * reflected. @@ -105,18 +105,12 @@ */ /** - * drm_mode_create_rotation_property - create a new rotation property - * @dev: DRM device + * drm_plane_create_rotation_property - create a new rotation property + * @plane: drm plane + * @rotation: initial value of the rotation property * @supported_rotations: bitmask of supported rotations and reflections * * This creates a new property with the selected support for transformations. - * The resulting property should be stored in @rotation_property in - * &drm_mode_config. It then must be attached to each plane which supports - * rotations using drm_object_attach_property(). - * - * FIXME: Probably better if the rotation property is created on each plane, - * like the zpos property. Otherwise it's not possible to allow different - * rotation modes on different planes. * * Since a rotation by 180° degress is the same as reflecting both along the x * and the y axis the rotation property is somewhat redundant. Drivers can use @@ -144,24 +138,6 @@ * rotation. After reflection, the rotation is applied to the image sampled from * the source rectangle, before scaling it to fit the destination rectangle. */ -struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, - unsigned int supported_rotations) -{ - static const struct drm_prop_enum_list props[] = { - { __builtin_ffs(DRM_ROTATE_0) - 1, "rotate-0" }, - { __builtin_ffs(DRM_ROTATE_90) - 1, "rotate-90" }, - { __builtin_ffs(DRM_ROTATE_180) - 1, "rotate-180" }, - { __builtin_ffs(DRM_ROTATE_270) - 1, "rotate-270" }, - { __builtin_ffs(DRM_REFLECT_X) - 1, "reflect-x" }, - { __builtin_ffs(DRM_REFLECT_Y) - 1, "reflect-y" }, - }; - - return drm_property_create_bitmask(dev, 0, "rotation", - props, ARRAY_SIZE(props), - supported_rotations); -} -EXPORT_SYMBOL(drm_mode_create_rotation_property); - int drm_plane_create_rotation_property(struct drm_plane *plane, unsigned int rotation, unsigned int supported_rotations) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index e0d428f9d1cb..83dbae0fabcf 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -392,15 +392,10 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) if (plane->type != DRM_PLANE_TYPE_PRIMARY) drm_plane_force_disable(plane); - if (plane->rotation_property) { + if (plane->rotation_property) drm_mode_plane_set_obj_prop(plane, plane->rotation_property, DRM_ROTATE_0); - } else if (dev->mode_config.rotation_property) { - drm_mode_plane_set_obj_prop(plane, - dev->mode_config.rotation_property, - DRM_ROTATE_0); - } } for (i = 0; i < fb_helper->crtc_count; i++) { diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h index fd351924e1c5..13221cf9b3eb 100644 --- a/include/drm/drm_blend.h +++ b/include/drm/drm_blend.h @@ -52,8 +52,6 @@ static inline bool drm_rotation_90_or_270(unsigned int rotation) return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270); } -struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, - unsigned int supported_rotations); int drm_plane_create_rotation_property(struct drm_plane *plane, unsigned int rotation, unsigned int supported_rotations); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 284c1b3aec10..bc860cfc67ca 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1155,11 +1155,6 @@ struct drm_mode_config { * CURSOR, PRIMARY and OVERLAY legacy uses of planes. */ struct drm_property *plane_type_property; - /** - * @rotation_property: Optional property for planes or CRTCs to specifiy - * rotation. - */ - struct drm_property *rotation_property; /** * @prop_src_x: Default atomic plane property for the plane source * position in the connected &drm_framebuffer. -- cgit v1.2.3 From 668592492409498afc277da41e84799e1d2255c2 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 20 Oct 2016 10:49:01 +0200 Subject: mtd: nand: Add OX820 NAND Support Add NAND driver to support the Oxford Semiconductor OX820 NAND Controller. This is a simple memory mapped NAND controller with single chip select and software ECC. Acked-by: Rob Herring Signed-off-by: Neil Armstrong Signed-off-by: Boris Brezillon --- .../devicetree/bindings/mtd/oxnas-nand.txt | 41 +++++ drivers/mtd/nand/Kconfig | 5 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/oxnas_nand.c | 195 +++++++++++++++++++++ 4 files changed, 242 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/oxnas-nand.txt create mode 100644 drivers/mtd/nand/oxnas_nand.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/mtd/oxnas-nand.txt b/Documentation/devicetree/bindings/mtd/oxnas-nand.txt new file mode 100644 index 000000000000..56d5c19da41d --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/oxnas-nand.txt @@ -0,0 +1,41 @@ +* Oxford Semiconductor OXNAS NAND Controller + +Please refer to nand.txt for generic information regarding MTD NAND bindings. + +Required properties: + - compatible: "oxsemi,ox820-nand" + - reg: Base address and length for NAND mapped memory. + +Optional Properties: + - clocks: phandle to the NAND gate clock if needed. + - resets: phandle to the NAND reset control if needed. + +Example: + +nandc: nand-controller@41000000 { + compatible = "oxsemi,ox820-nand"; + reg = <0x41000000 0x100000>; + clocks = <&stdclk CLK_820_NAND>; + resets = <&reset RESET_NAND>; + #address-cells = <1>; + #size-cells = <0>; + + nand@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + nand-ecc-mode = "soft"; + nand-ecc-algo = "hamming"; + + partition@0 { + label = "boot"; + reg = <0x00000000 0x00e00000>; + read-only; + }; + + partition@e00000 { + label = "ubi"; + reg = <0x00e00000 0x07200000>; + }; + }; +}; diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 7b7a887b4709..c023125989cf 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -426,6 +426,11 @@ config MTD_NAND_ORION No board specific support is done by this driver, each board must advertise a platform_device for the driver to attach. +config MTD_NAND_OXNAS + tristate "NAND Flash support for Oxford Semiconductor SoC" + help + This enables the NAND flash controller on Oxford Semiconductor SoCs. + config MTD_NAND_FSL_ELBC tristate "NAND support for Freescale eLBC controllers" depends on FSL_SOC diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index cafde6f3d957..05fc054a9472 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o +obj-$(CONFIG_MTD_NAND_OXNAS) += oxnas_nand.o obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o obj-$(CONFIG_MTD_NAND_FSL_IFC) += fsl_ifc_nand.o obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o diff --git a/drivers/mtd/nand/oxnas_nand.c b/drivers/mtd/nand/oxnas_nand.c new file mode 100644 index 000000000000..3e3bf3b364d2 --- /dev/null +++ b/drivers/mtd/nand/oxnas_nand.c @@ -0,0 +1,195 @@ +/* + * Oxford Semiconductor OXNAS NAND driver + + * Copyright (C) 2016 Neil Armstrong + * Heavily based on plat_nand.c : + * Author: Vitaly Wool + * Copyright (C) 2013 Ma Haijun + * Copyright (C) 2012 John Crispin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Nand commands */ +#define OXNAS_NAND_CMD_ALE BIT(18) +#define OXNAS_NAND_CMD_CLE BIT(19) + +#define OXNAS_NAND_MAX_CHIPS 1 + +struct oxnas_nand_ctrl { + struct nand_hw_control base; + void __iomem *io_base; + struct clk *clk; + struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS]; +}; + +static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); + + return readb(oxnas->io_base); +} + +static void oxnas_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); + + ioread8_rep(oxnas->io_base, buf, len); +} + +static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); + + iowrite8_rep(oxnas->io_base, buf, len); +} + +/* Single CS command control */ +static void oxnas_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); + + if (ctrl & NAND_CLE) + writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_CLE); + else if (ctrl & NAND_ALE) + writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_ALE); +} + +/* + * Probe for the NAND device. + */ +static int oxnas_nand_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *nand_np; + struct oxnas_nand_ctrl *oxnas; + struct nand_chip *chip; + struct mtd_info *mtd; + struct resource *res; + int nchips = 0; + int count = 0; + int err = 0; + + /* Allocate memory for the device structure (and zero it) */ + oxnas = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip), + GFP_KERNEL); + if (!oxnas) + return -ENOMEM; + + nand_hw_control_init(&oxnas->base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + oxnas->io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(oxnas->io_base)) + return PTR_ERR(oxnas->io_base); + + oxnas->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(oxnas->clk)) + oxnas->clk = NULL; + + /* Only a single chip node is supported */ + count = of_get_child_count(np); + if (count > 1) + return -EINVAL; + + clk_prepare_enable(oxnas->clk); + device_reset_optional(&pdev->dev); + + for_each_child_of_node(np, nand_np) { + chip = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip), + GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->controller = &oxnas->base; + + nand_set_flash_node(chip, nand_np); + nand_set_controller_data(chip, oxnas); + + mtd = nand_to_mtd(chip); + mtd->dev.parent = &pdev->dev; + mtd->priv = chip; + + chip->cmd_ctrl = oxnas_nand_cmd_ctrl; + chip->read_buf = oxnas_nand_read_buf; + chip->read_byte = oxnas_nand_read_byte; + chip->write_buf = oxnas_nand_write_buf; + chip->chip_delay = 30; + + /* Scan to find existence of the device */ + err = nand_scan(mtd, 1); + if (err) + return err; + + err = mtd_device_register(mtd, NULL, 0); + if (err) { + nand_release(mtd); + return err; + } + + oxnas->chips[nchips] = chip; + ++nchips; + } + + /* Exit if no chips found */ + if (!nchips) + return -ENODEV; + + platform_set_drvdata(pdev, oxnas); + + return 0; +} + +static int oxnas_nand_remove(struct platform_device *pdev) +{ + struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev); + + if (oxnas->chips[0]) + nand_release(nand_to_mtd(oxnas->chips[0])); + + clk_disable_unprepare(oxnas->clk); + + return 0; +} + +static const struct of_device_id oxnas_nand_match[] = { + { .compatible = "oxsemi,ox820-nand" }, + {}, +}; +MODULE_DEVICE_TABLE(of, oxnas_nand_match); + +static struct platform_driver oxnas_nand_driver = { + .probe = oxnas_nand_probe, + .remove = oxnas_nand_remove, + .driver = { + .name = "oxnas_nand", + .of_match_table = oxnas_nand_match, + }, +}; + +module_platform_driver(oxnas_nand_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION("Oxnas NAND driver"); +MODULE_ALIAS("platform:oxnas_nand"); -- cgit v1.2.3 From 240ea9214a6042f3807fd09f149d74ae5700e117 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 14:38:18 +0000 Subject: EDAC, skx_edac: Fix non static symbol warnings Fix the following sparse warnings: drivers/edac/skx_edac.c:266:25: warning: symbol 'skx_cpuids' was not declared. Should it be static? drivers/edac/skx_edac.c:1040:12: warning: symbol 'skx_init' was not declared. Should it be static? Signed-off-by: Wei Yongjun Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1477147098-2842-1-git-send-email-weiyj.lk@gmail.com Signed-off-by: Borislav Petkov --- drivers/edac/skx_edac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index f3b3d3be1e84..9edcb29b3001 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c @@ -263,7 +263,7 @@ fail: return -ENODEV; } -const struct x86_cpu_id skx_cpuids[] = { +static const struct x86_cpu_id skx_cpuids[] = { { X86_VENDOR_INTEL, 6, INTEL_FAM6_SKYLAKE_X, 0, 0 }, { } }; @@ -1037,7 +1037,7 @@ static void skx_remove(void) * search for all the devices we need * check which DIMMs are present. */ -int __init skx_init(void) +static int __init skx_init(void) { const struct x86_cpu_id *id; const struct munit *m; -- cgit v1.2.3 From 90e493d7d51c791a2adc2de962cbd5000f1b7460 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Wed, 19 Oct 2016 14:53:47 -0500 Subject: EDAC, altera: Disable IRQs while injecting SDRAM errors Disable IRQs while injecting SDRAM errors. The RT patches exposed a spinlock deadlock where the spinlock taken for the regmap write deadlocked with the IRQ clear regmap write. Error injection is not normally enabled for ECC but only for testing. Signed-off-by: Thor Thayer Cc: linux-edac Link: http://lkml.kernel.org/r/1476906827-9412-1-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 58d3e2b39b5b..6421cc3c7dc1 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -153,13 +153,17 @@ static ssize_t altr_sdr_mc_err_inject_write(struct file *file, if (count == 3) { edac_printk(KERN_ALERT, EDAC_MC, "Inject Double bit error\n"); + local_irq_disable(); regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset, (read_reg | priv->ue_set_mask)); + local_irq_enable(); } else { edac_printk(KERN_ALERT, EDAC_MC, "Inject Single bit error\n"); + local_irq_disable(); regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset, (read_reg | priv->ce_set_mask)); + local_irq_enable(); } ptemp[0] = 0x5A5A5A5A; -- cgit v1.2.3 From 304887041d953b6692c0d4a9f8fafb252d32e9a0 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 20 Oct 2016 16:28:01 +0000 Subject: platform/x86: Introduce support for Mellanox hotplug driver Enable system support for the Mellanox Technologies hotplug platform driver, which provides support for the next Mellanox basic systems: "msx6710", "msx6720", "msb7700", "msn2700", "msx1410", "msn2410", "msb7800", "msn2740", "msn2100" and also various number of derivative systems from the above basic types. This driver handles hot-plug events for the power suppliers, power cables and fans for the above systems. The Kconfig currently controlling compilation of this code is: driver/platform/x86:config MLX_CPLD_PLATFORM tristate "Mellanox platform hotplug driver support" Signed-off-by: Vadim Pasternak Signed-off-by: Darren Hart --- MAINTAINERS | 7 + drivers/platform/x86/Kconfig | 11 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/mlxcpld-hotplug.c | 515 ++++++++++++++++++++++++++ include/linux/platform_data/mlxcpld-hotplug.h | 99 +++++ 5 files changed, 633 insertions(+) create mode 100644 drivers/platform/x86/mlxcpld-hotplug.c create mode 100644 include/linux/platform_data/mlxcpld-hotplug.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 1cd38a7e0064..3e30399e715f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7881,6 +7881,13 @@ L: platform-driver-x86@vger.kernel.org S: Supported F: arch/x86/platform/mellanox/mlx-platform.c +MELLANOX MLX CPLD HOTPLUG DRIVER +M: Vadim Pasternak +L: platform-driver-x86@vger.kernel.org +S: Supported +F: drivers/platform/x86/mlxcpld-hotplug.c +F: include/linux/platform_data/mlxcpld-hotplug.h + SOFT-ROCE DRIVER (rxe) M: Moni Shoua L: linux-rdma@vger.kernel.org diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b8a21d7b25d4..185376901d9c 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1027,4 +1027,15 @@ config INTEL_TELEMETRY used to get various SoC events and parameters directly via debugfs files. Various tools may use this interface for SoC state monitoring. + +config MLX_CPLD_PLATFORM + tristate "Mellanox platform hotplug driver support" + default n + depends on MLX_PLATFORM + select HWMON + select I2C + ---help--- + This driver handles hot-plug events for the power suppliers, power + cables and fans on the wide range Mellanox IB and Ethernet systems. + endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 2efa86d2a1a7..1f06b6339cf7 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -71,3 +71,4 @@ obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \ intel_telemetry_pltdrv.o \ intel_telemetry_debugfs.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o +obj-$(CONFIG_MLX_CPLD_PLATFORM) += mlxcpld-hotplug.o diff --git a/drivers/platform/x86/mlxcpld-hotplug.c b/drivers/platform/x86/mlxcpld-hotplug.c new file mode 100644 index 000000000000..aff3686b3b37 --- /dev/null +++ b/drivers/platform/x86/mlxcpld-hotplug.c @@ -0,0 +1,515 @@ +/* + * drivers/platform/x86/mlxcpld-hotplug.c + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Vadim Pasternak + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Offset of event and mask registers from status register */ +#define MLXCPLD_HOTPLUG_EVENT_OFF 1 +#define MLXCPLD_HOTPLUG_MASK_OFF 2 +#define MLXCPLD_HOTPLUG_AGGR_MASK_OFF 1 + +#define MLXCPLD_HOTPLUG_ATTRS_NUM 8 + +/** + * enum mlxcpld_hotplug_attr_type - sysfs attributes for hotplug events: + * @MLXCPLD_HOTPLUG_ATTR_TYPE_PSU: power supply unit attribute; + * @MLXCPLD_HOTPLUG_ATTR_TYPE_PWR: power cable attribute; + * @MLXCPLD_HOTPLUG_ATTR_TYPE_FAN: FAN drawer attribute; + */ +enum mlxcpld_hotplug_attr_type { + MLXCPLD_HOTPLUG_ATTR_TYPE_PSU, + MLXCPLD_HOTPLUG_ATTR_TYPE_PWR, + MLXCPLD_HOTPLUG_ATTR_TYPE_FAN, +}; + +/** + * struct mlxcpld_hotplug_priv_data - platform private data: + * @irq: platform interrupt number; + * @pdev: platform device; + * @plat: platform data; + * @hwmon: hwmon device; + * @mlxcpld_hotplug_attr: sysfs attributes array; + * @mlxcpld_hotplug_dev_attr: sysfs sensor device attribute array; + * @group: sysfs attribute group; + * @groups: list of sysfs attribute group for hwmon registration; + * @dwork: delayed work template; + * @lock: spin lock; + * @aggr_cache: last value of aggregation register status; + * @psu_cache: last value of PSU register status; + * @pwr_cache: last value of power register status; + * @fan_cache: last value of FAN register status; + */ +struct mlxcpld_hotplug_priv_data { + int irq; + struct platform_device *pdev; + struct mlxcpld_hotplug_platform_data *plat; + struct device *hwmon; + struct attribute *mlxcpld_hotplug_attr[MLXCPLD_HOTPLUG_ATTRS_NUM + 1]; + struct sensor_device_attribute_2 + mlxcpld_hotplug_dev_attr[MLXCPLD_HOTPLUG_ATTRS_NUM]; + struct attribute_group group; + const struct attribute_group *groups[2]; + struct delayed_work dwork; + spinlock_t lock; + u8 aggr_cache; + u8 psu_cache; + u8 pwr_cache; + u8 fan_cache; +}; + +static ssize_t mlxcpld_hotplug_attr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct mlxcpld_hotplug_priv_data *priv = platform_get_drvdata(pdev); + int index = to_sensor_dev_attr_2(attr)->index; + int nr = to_sensor_dev_attr_2(attr)->nr; + u8 reg_val = 0; + + switch (nr) { + case MLXCPLD_HOTPLUG_ATTR_TYPE_PSU: + /* Bit = 0 : PSU is present. */ + reg_val = !!!(inb(priv->plat->psu_reg_offset) & BIT(index)); + break; + + case MLXCPLD_HOTPLUG_ATTR_TYPE_PWR: + /* Bit = 1 : power cable is attached. */ + reg_val = !!(inb(priv->plat->pwr_reg_offset) & BIT(index % + priv->plat->pwr_count)); + break; + + case MLXCPLD_HOTPLUG_ATTR_TYPE_FAN: + /* Bit = 0 : FAN is present. */ + reg_val = !!!(inb(priv->plat->fan_reg_offset) & BIT(index % + priv->plat->fan_count)); + break; + } + + return sprintf(buf, "%u\n", reg_val); +} + +#define PRIV_ATTR(i) priv->mlxcpld_hotplug_attr[i] +#define PRIV_DEV_ATTR(i) priv->mlxcpld_hotplug_dev_attr[i] +static int mlxcpld_hotplug_attr_init(struct mlxcpld_hotplug_priv_data *priv) +{ + int num_attrs = priv->plat->psu_count + priv->plat->pwr_count + + priv->plat->fan_count; + int i; + + priv->group.attrs = devm_kzalloc(&priv->pdev->dev, num_attrs * + sizeof(struct attribute *), + GFP_KERNEL); + if (!priv->group.attrs) + return -ENOMEM; + + for (i = 0; i < num_attrs; i++) { + PRIV_ATTR(i) = &PRIV_DEV_ATTR(i).dev_attr.attr; + + if (i < priv->plat->psu_count) { + PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev, + GFP_KERNEL, "psu%u", i + 1); + PRIV_DEV_ATTR(i).nr = MLXCPLD_HOTPLUG_ATTR_TYPE_PSU; + } else if (i < priv->plat->psu_count + priv->plat->pwr_count) { + PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev, + GFP_KERNEL, "pwr%u", i % + priv->plat->pwr_count + 1); + PRIV_DEV_ATTR(i).nr = MLXCPLD_HOTPLUG_ATTR_TYPE_PWR; + } else { + PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev, + GFP_KERNEL, "fan%u", i % + priv->plat->fan_count + 1); + PRIV_DEV_ATTR(i).nr = MLXCPLD_HOTPLUG_ATTR_TYPE_FAN; + } + + if (!PRIV_ATTR(i)->name) { + dev_err(&priv->pdev->dev, "Memory allocation failed for sysfs attribute %d.\n", + i + 1); + return -ENOMEM; + } + + PRIV_DEV_ATTR(i).dev_attr.attr.name = PRIV_ATTR(i)->name; + PRIV_DEV_ATTR(i).dev_attr.attr.mode = S_IRUGO; + PRIV_DEV_ATTR(i).dev_attr.show = mlxcpld_hotplug_attr_show; + PRIV_DEV_ATTR(i).index = i; + sysfs_attr_init(&PRIV_DEV_ATTR(i).dev_attr.attr); + } + + priv->group.attrs = priv->mlxcpld_hotplug_attr; + priv->groups[0] = &priv->group; + priv->groups[1] = NULL; + + return 0; +} + +static int mlxcpld_hotplug_device_create(struct device *dev, + struct mlxcpld_hotplug_device *item) +{ + item->adapter = i2c_get_adapter(item->bus); + if (!item->adapter) { + dev_err(dev, "Failed to get adapter for bus %d\n", + item->bus); + return -EFAULT; + } + + item->client = i2c_new_device(item->adapter, &item->brdinfo); + if (!item->client) { + dev_err(dev, "Failed to create client %s at bus %d at addr 0x%02x\n", + item->brdinfo.type, item->bus, item->brdinfo.addr); + i2c_put_adapter(item->adapter); + item->adapter = NULL; + return -EFAULT; + } + + return 0; +} + +static void mlxcpld_hotplug_device_destroy(struct mlxcpld_hotplug_device *item) +{ + if (item->client) { + i2c_unregister_device(item->client); + item->client = NULL; + } + + if (item->adapter) { + i2c_put_adapter(item->adapter); + item->adapter = NULL; + } +} + +static inline void +mlxcpld_hotplug_work_helper(struct device *dev, + struct mlxcpld_hotplug_device *item, u8 is_inverse, + u16 offset, u8 mask, u8 *cache) +{ + u8 val, asserted; + int bit; + + /* Mask event. */ + outb(0, offset + MLXCPLD_HOTPLUG_MASK_OFF); + /* Read status. */ + val = inb(offset) & mask; + asserted = *cache ^ val; + *cache = val; + + /* + * Validate if item related to received signal type is valid. + * It should never happen, excepted the situation when some + * piece of hardware is broken. In such situation just produce + * error message and return. Caller must continue to handle the + * signals from other devices if any. + */ + if (unlikely(!item)) { + dev_err(dev, "False signal is received: register at offset 0x%02x, mask 0x%02x.\n", + offset, mask); + return; + } + + for_each_set_bit(bit, (unsigned long *)&asserted, 8) { + if (val & BIT(bit)) { + if (is_inverse) + mlxcpld_hotplug_device_destroy(item + bit); + else + mlxcpld_hotplug_device_create(dev, item + bit); + } else { + if (is_inverse) + mlxcpld_hotplug_device_create(dev, item + bit); + else + mlxcpld_hotplug_device_destroy(item + bit); + } + } + + /* Acknowledge event. */ + outb(0, offset + MLXCPLD_HOTPLUG_EVENT_OFF); + /* Unmask event. */ + outb(mask, offset + MLXCPLD_HOTPLUG_MASK_OFF); +} + +/* + * mlxcpld_hotplug_work_handler - performs traversing of CPLD interrupt + * registers according to the below hierarchy schema: + * + * Aggregation registers (status/mask) + * PSU registers: *---* + * *-----------------* | | + * |status/event/mask|----->| * | + * *-----------------* | | + * Power registers: | | + * *-----------------* | | + * |status/event/mask|----->| * |---> CPU + * *-----------------* | | + * FAN registers: + * *-----------------* | | + * |status/event/mask|----->| * | + * *-----------------* | | + * *---* + * In case some system changed are detected: FAN in/out, PSU in/out, power + * cable attached/detached, relevant device is created or destroyed. + */ +static void mlxcpld_hotplug_work_handler(struct work_struct *work) +{ + struct mlxcpld_hotplug_priv_data *priv = container_of(work, + struct mlxcpld_hotplug_priv_data, dwork.work); + u8 val, aggr_asserted; + unsigned long flags; + + /* Mask aggregation event. */ + outb(0, priv->plat->top_aggr_offset + MLXCPLD_HOTPLUG_AGGR_MASK_OFF); + /* Read aggregation status. */ + val = inb(priv->plat->top_aggr_offset) & priv->plat->top_aggr_mask; + aggr_asserted = priv->aggr_cache ^ val; + priv->aggr_cache = val; + + /* Handle PSU configuration changes. */ + if (aggr_asserted & priv->plat->top_aggr_psu_mask) + mlxcpld_hotplug_work_helper(&priv->pdev->dev, priv->plat->psu, + 1, priv->plat->psu_reg_offset, + priv->plat->psu_mask, + &priv->psu_cache); + + /* Handle power cable configuration changes. */ + if (aggr_asserted & priv->plat->top_aggr_pwr_mask) + mlxcpld_hotplug_work_helper(&priv->pdev->dev, priv->plat->pwr, + 0, priv->plat->pwr_reg_offset, + priv->plat->pwr_mask, + &priv->pwr_cache); + + /* Handle FAN configuration changes. */ + if (aggr_asserted & priv->plat->top_aggr_fan_mask) + mlxcpld_hotplug_work_helper(&priv->pdev->dev, priv->plat->fan, + 1, priv->plat->fan_reg_offset, + priv->plat->fan_mask, + &priv->fan_cache); + + if (aggr_asserted) { + spin_lock_irqsave(&priv->lock, flags); + + /* + * It is possible, that some signals have been inserted, while + * interrupt has been masked by mlxcpld_hotplug_work_handler. + * In this case such signals will be missed. In order to handle + * these signals delayed work is canceled and work task + * re-scheduled for immediate execution. It allows to handle + * missed signals, if any. In other case work handler just + * validates that no new signals have been received during + * masking. + */ + cancel_delayed_work(&priv->dwork); + schedule_delayed_work(&priv->dwork, 0); + + spin_unlock_irqrestore(&priv->lock, flags); + + return; + } + + /* Unmask aggregation event (no need acknowledge). */ + outb(priv->plat->top_aggr_mask, priv->plat->top_aggr_offset + + MLXCPLD_HOTPLUG_AGGR_MASK_OFF); +} + +static void mlxcpld_hotplug_set_irq(struct mlxcpld_hotplug_priv_data *priv) +{ + /* Clear psu presense event. */ + outb(0, priv->plat->psu_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF); + /* Set psu initial status as mask and unmask psu event. */ + priv->psu_cache = priv->plat->psu_mask; + outb(priv->plat->psu_mask, priv->plat->psu_reg_offset + + MLXCPLD_HOTPLUG_MASK_OFF); + + /* Clear power cable event. */ + outb(0, priv->plat->pwr_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF); + /* Keep power initial status as zero and unmask power event. */ + outb(priv->plat->pwr_mask, priv->plat->pwr_reg_offset + + MLXCPLD_HOTPLUG_MASK_OFF); + + /* Clear fan presense event. */ + outb(0, priv->plat->fan_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF); + /* Set fan initial status as mask and unmask fan event. */ + priv->fan_cache = priv->plat->fan_mask; + outb(priv->plat->fan_mask, priv->plat->fan_reg_offset + + MLXCPLD_HOTPLUG_MASK_OFF); + + /* Keep aggregation initial status as zero and unmask events. */ + outb(priv->plat->top_aggr_mask, priv->plat->top_aggr_offset + + MLXCPLD_HOTPLUG_AGGR_MASK_OFF); + + /* Invoke work handler for initializing hot plug devices setting. */ + mlxcpld_hotplug_work_handler(&priv->dwork.work); + + enable_irq(priv->irq); +} + +static void mlxcpld_hotplug_unset_irq(struct mlxcpld_hotplug_priv_data *priv) +{ + int i; + + disable_irq(priv->irq); + cancel_delayed_work_sync(&priv->dwork); + + /* Mask aggregation event. */ + outb(0, priv->plat->top_aggr_offset + MLXCPLD_HOTPLUG_AGGR_MASK_OFF); + + /* Mask psu presense event. */ + outb(0, priv->plat->psu_reg_offset + MLXCPLD_HOTPLUG_MASK_OFF); + /* Clear psu presense event. */ + outb(0, priv->plat->psu_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF); + + /* Mask power cable event. */ + outb(0, priv->plat->pwr_reg_offset + MLXCPLD_HOTPLUG_MASK_OFF); + /* Clear power cable event. */ + outb(0, priv->plat->pwr_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF); + + /* Mask fan presense event. */ + outb(0, priv->plat->fan_reg_offset + MLXCPLD_HOTPLUG_MASK_OFF); + /* Clear fan presense event. */ + outb(0, priv->plat->fan_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF); + + /* Remove all the attached devices. */ + for (i = 0; i < priv->plat->psu_count; i++) + mlxcpld_hotplug_device_destroy(priv->plat->psu + i); + + for (i = 0; i < priv->plat->pwr_count; i++) + mlxcpld_hotplug_device_destroy(priv->plat->pwr + i); + + for (i = 0; i < priv->plat->fan_count; i++) + mlxcpld_hotplug_device_destroy(priv->plat->fan + i); +} + +static irqreturn_t mlxcpld_hotplug_irq_handler(int irq, void *dev) +{ + struct mlxcpld_hotplug_priv_data *priv = + (struct mlxcpld_hotplug_priv_data *)dev; + + /* Schedule work task for immediate execution.*/ + schedule_delayed_work(&priv->dwork, 0); + + return IRQ_HANDLED; +} + +static int mlxcpld_hotplug_probe(struct platform_device *pdev) +{ + struct mlxcpld_hotplug_platform_data *pdata; + struct mlxcpld_hotplug_priv_data *priv; + int err; + + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { + dev_err(&pdev->dev, "Failed to get platform data.\n"); + return -EINVAL; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->pdev = pdev; + priv->plat = pdata; + + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq < 0) { + dev_err(&pdev->dev, "Failed to get platform irq: %d\n", + priv->irq); + return priv->irq; + } + + err = devm_request_irq(&pdev->dev, priv->irq, + mlxcpld_hotplug_irq_handler, 0, pdev->name, + priv); + if (err) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", err); + return err; + } + disable_irq(priv->irq); + + INIT_DELAYED_WORK(&priv->dwork, mlxcpld_hotplug_work_handler); + spin_lock_init(&priv->lock); + + err = mlxcpld_hotplug_attr_init(priv); + if (err) { + dev_err(&pdev->dev, "Failed to allocate attributes: %d\n", err); + return err; + } + + priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, + "mlxcpld_hotplug", priv, priv->groups); + if (IS_ERR(priv->hwmon)) { + dev_err(&pdev->dev, "Failed to register hwmon device %ld\n", + PTR_ERR(priv->hwmon)); + return PTR_ERR(priv->hwmon); + } + + platform_set_drvdata(pdev, priv); + + /* Perform initial interrupts setup. */ + mlxcpld_hotplug_set_irq(priv); + + return 0; +} + +static int mlxcpld_hotplug_remove(struct platform_device *pdev) +{ + struct mlxcpld_hotplug_priv_data *priv = platform_get_drvdata(pdev); + + /* Clean interrupts setup. */ + mlxcpld_hotplug_unset_irq(priv); + + return 0; +} + +static struct platform_driver mlxcpld_hotplug_driver = { + .driver = { + .name = "mlxcpld-hotplug", + }, + .probe = mlxcpld_hotplug_probe, + .remove = mlxcpld_hotplug_remove, +}; + +module_platform_driver(mlxcpld_hotplug_driver); + +MODULE_AUTHOR("Vadim Pasternak "); +MODULE_DESCRIPTION("Mellanox CPLD hotplug platform driver"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("platform:mlxcpld-hotplug"); diff --git a/include/linux/platform_data/mlxcpld-hotplug.h b/include/linux/platform_data/mlxcpld-hotplug.h new file mode 100644 index 000000000000..e4cfcffaa6f4 --- /dev/null +++ b/include/linux/platform_data/mlxcpld-hotplug.h @@ -0,0 +1,99 @@ +/* + * include/linux/platform_data/mlxcpld-hotplug.h + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Vadim Pasternak + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H +#define __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H + +/** + * struct mlxcpld_hotplug_device - I2C device data: + * @adapter: I2C device adapter; + * @client: I2C device client; + * @brdinfo: device board information; + * @bus: I2C bus, where device is attached; + * + * Structure represents I2C hotplug device static data (board topology) and + * dynamic data (related kernel objects handles). + */ +struct mlxcpld_hotplug_device { + struct i2c_adapter *adapter; + struct i2c_client *client; + struct i2c_board_info brdinfo; + u16 bus; +}; + +/** + * struct mlxcpld_hotplug_platform_data - device platform data: + * @top_aggr_offset: offset of top aggregation interrupt register; + * @top_aggr_mask: top aggregation interrupt common mask; + * @top_aggr_psu_mask: top aggregation interrupt PSU mask; + * @psu_reg_offset: offset of PSU interrupt register; + * @psu_mask: PSU interrupt mask; + * @psu_count: number of equipped replaceable PSUs; + * @psu: pointer to PSU devices data array; + * @top_aggr_pwr_mask: top aggregation interrupt power mask; + * @pwr_reg_offset: offset of power interrupt register + * @pwr_mask: power interrupt mask; + * @pwr_count: number of power sources; + * @pwr: pointer to power devices data array; + * @top_aggr_fan_mask: top aggregation interrupt FAN mask; + * @fan_reg_offset: offset of FAN interrupt register; + * @fan_mask: FAN interrupt mask; + * @fan_count: number of equipped replaceable FANs; + * @fan: pointer to FAN devices data array; + * + * Structure represents board platform data, related to system hotplug events, + * like FAN, PSU, power cable insertion and removing. This data provides the + * number of hot-pluggable devices and hardware description for event handling. + */ +struct mlxcpld_hotplug_platform_data { + u16 top_aggr_offset; + u8 top_aggr_mask; + u8 top_aggr_psu_mask; + u16 psu_reg_offset; + u8 psu_mask; + u8 psu_count; + struct mlxcpld_hotplug_device *psu; + u8 top_aggr_pwr_mask; + u16 pwr_reg_offset; + u8 pwr_mask; + u8 pwr_count; + struct mlxcpld_hotplug_device *pwr; + u8 top_aggr_fan_mask; + u16 fan_reg_offset; + u8 fan_mask; + u8 fan_count; + struct mlxcpld_hotplug_device *fan; +}; + +#endif /* __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H */ -- cgit v1.2.3 From 1a2cfd0070c1f60fbcfced776e8329461303a702 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 5 Oct 2016 17:07:49 +0200 Subject: clk: oxnas: Rename to clk_oxnas_gate Rename clock ops to clk_oxnas_gate in ops and structures. Signed-off-by: Neil Armstrong Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20161005150752.22618-4-narmstrong@baylibre.com --- drivers/clk/clk-oxnas.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c index 47649ac5d399..a76c7fbb90ca 100644 --- a/drivers/clk/clk-oxnas.c +++ b/drivers/clk/clk-oxnas.c @@ -26,7 +26,7 @@ #include /* Standard regmap gate clocks */ -struct clk_oxnas { +struct clk_oxnas_gate { struct clk_hw hw; signed char bit; struct regmap *regmap; @@ -37,14 +37,14 @@ struct clk_oxnas { #define CLK_SET_REGOFFSET 0x2c #define CLK_CLR_REGOFFSET 0x30 -static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw) +static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw) { - return container_of(hw, struct clk_oxnas, hw); + return container_of(hw, struct clk_oxnas_gate, hw); } -static int oxnas_clk_is_enabled(struct clk_hw *hw) +static int oxnas_clk_gate_is_enabled(struct clk_hw *hw) { - struct clk_oxnas *std = to_clk_oxnas(hw); + struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw); int ret; unsigned int val; @@ -55,26 +55,26 @@ static int oxnas_clk_is_enabled(struct clk_hw *hw) return val & BIT(std->bit); } -static int oxnas_clk_enable(struct clk_hw *hw) +static int oxnas_clk_gate_enable(struct clk_hw *hw) { - struct clk_oxnas *std = to_clk_oxnas(hw); + struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw); regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit)); return 0; } -static void oxnas_clk_disable(struct clk_hw *hw) +static void oxnas_clk_gate_disable(struct clk_hw *hw) { - struct clk_oxnas *std = to_clk_oxnas(hw); + struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw); regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit)); } -static const struct clk_ops oxnas_clk_ops = { - .enable = oxnas_clk_enable, - .disable = oxnas_clk_disable, - .is_enabled = oxnas_clk_is_enabled, +static const struct clk_ops oxnas_clk_gate_ops = { + .enable = oxnas_clk_gate_enable, + .disable = oxnas_clk_gate_disable, + .is_enabled = oxnas_clk_gate_is_enabled, }; static const char *const oxnas_clk_parents[] = { @@ -88,7 +88,7 @@ static const char *const eth_parents[] = { #define DECLARE_STD_CLKP(__clk, __parent) \ static const struct clk_init_data clk_##__clk##_init = { \ .name = __stringify(__clk), \ - .ops = &oxnas_clk_ops, \ + .ops = &oxnas_clk_gate_ops, \ .parent_names = __parent, \ .num_parents = ARRAY_SIZE(__parent), \ } @@ -127,7 +127,7 @@ static const struct clk_oxnas_init_data clk_oxnas_init[] = { }; struct clk_oxnas_data { - struct clk_oxnas clk_oxnas[ARRAY_SIZE(clk_oxnas_init)]; + struct clk_oxnas_gate clk_oxnas[ARRAY_SIZE(clk_oxnas_init)]; struct clk_onecell_data onecell_data[ARRAY_SIZE(clk_oxnas_init)]; struct clk *clks[ARRAY_SIZE(clk_oxnas_init)]; }; @@ -150,7 +150,7 @@ static int oxnas_stdclk_probe(struct platform_device *pdev) } for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) { - struct clk_oxnas *_clk; + struct clk_oxnas_gate *_clk; _clk = &clk_oxnas->clk_oxnas[i]; _clk->bit = clk_oxnas_init[i].bit; -- cgit v1.2.3 From 5a9e54a81b5ef6b31ffafc2199c648083bc50248 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 5 Oct 2016 17:07:50 +0200 Subject: clk: oxnas: Refactor to make use of devm_clk_hw_register() Make usage of static tables identified by the OF match table to feed devm_clk_hw_register() and use of_clk_add_hw_provider(). This structure is cleaner and simplifies adding new SoC support while having common probe and gate ops code. Signed-off-by: Neil Armstrong Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20161005150752.22618-5-narmstrong@baylibre.com --- drivers/clk/clk-oxnas.c | 148 +++++++++++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c index a76c7fbb90ca..b1ef3ea990f1 100644 --- a/drivers/clk/clk-oxnas.c +++ b/drivers/clk/clk-oxnas.c @@ -20,18 +20,29 @@ #include #include #include +#include #include #include #include #include +#include + /* Standard regmap gate clocks */ struct clk_oxnas_gate { struct clk_hw hw; - signed char bit; + unsigned int bit; struct regmap *regmap; }; +struct oxnas_stdclk_data { + struct clk_hw_onecell_data *onecell_data; + struct clk_oxnas_gate **gates; + unsigned int ngates; + struct clk_oxnas_pll **plls; + unsigned int nplls; +}; + /* Regmap offsets */ #define CLK_STAT_REGOFFSET 0x24 #define CLK_SET_REGOFFSET 0x2c @@ -77,7 +88,7 @@ static const struct clk_ops oxnas_clk_gate_ops = { .is_enabled = oxnas_clk_gate_is_enabled, }; -static const char *const oxnas_clk_parents[] = { +static const char *const osc_parents[] = { "oscillator", }; @@ -85,63 +96,81 @@ static const char *const eth_parents[] = { "gmacclk", }; -#define DECLARE_STD_CLKP(__clk, __parent) \ -static const struct clk_init_data clk_##__clk##_init = { \ - .name = __stringify(__clk), \ - .ops = &oxnas_clk_gate_ops, \ - .parent_names = __parent, \ - .num_parents = ARRAY_SIZE(__parent), \ +#define OXNAS_GATE(_name, _bit, _parents) \ +struct clk_oxnas_gate _name = { \ + .bit = (_bit), \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &oxnas_clk_gate_ops, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ + }, \ } -#define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents) +static OXNAS_GATE(ox810se_leon, 0, osc_parents); +static OXNAS_GATE(ox810se_dma_sgdma, 1, osc_parents); +static OXNAS_GATE(ox810se_cipher, 2, osc_parents); +static OXNAS_GATE(ox810se_sata, 4, osc_parents); +static OXNAS_GATE(ox810se_audio, 5, osc_parents); +static OXNAS_GATE(ox810se_usbmph, 6, osc_parents); +static OXNAS_GATE(ox810se_etha, 7, eth_parents); +static OXNAS_GATE(ox810se_pciea, 8, osc_parents); +static OXNAS_GATE(ox810se_nand, 9, osc_parents); + +static struct clk_oxnas_gate *ox810se_gates[] = { + &ox810se_leon, + &ox810se_dma_sgdma, + &ox810se_cipher, + &ox810se_sata, + &ox810se_audio, + &ox810se_usbmph, + &ox810se_etha, + &ox810se_pciea, + &ox810se_nand, +}; -/* Hardware Bit - Clock association */ -struct clk_oxnas_init_data { - unsigned long bit; - const struct clk_init_data *clk_init; +static struct clk_hw_onecell_data ox810se_hw_onecell_data = { + .hws = { + [CLK_810_LEON] = &ox810se_leon.hw, + [CLK_810_DMA_SGDMA] = &ox810se_dma_sgdma.hw, + [CLK_810_CIPHER] = &ox810se_cipher.hw, + [CLK_810_SATA] = &ox810se_sata.hw, + [CLK_810_AUDIO] = &ox810se_audio.hw, + [CLK_810_USBMPH] = &ox810se_usbmph.hw, + [CLK_810_ETHA] = &ox810se_etha.hw, + [CLK_810_PCIEA] = &ox810se_pciea.hw, + [CLK_810_NAND] = &ox810se_nand.hw, + }, + .num = ARRAY_SIZE(ox810se_gates), }; -/* Clk init data declaration */ -DECLARE_STD_CLK(leon); -DECLARE_STD_CLK(dma_sgdma); -DECLARE_STD_CLK(cipher); -DECLARE_STD_CLK(sata); -DECLARE_STD_CLK(audio); -DECLARE_STD_CLK(usbmph); -DECLARE_STD_CLKP(etha, eth_parents); -DECLARE_STD_CLK(pciea); -DECLARE_STD_CLK(nand); - -/* Table index is clock indice */ -static const struct clk_oxnas_init_data clk_oxnas_init[] = { - [0] = {0, &clk_leon_init}, - [1] = {1, &clk_dma_sgdma_init}, - [2] = {2, &clk_cipher_init}, - /* Skip & Do not touch to DDR clock */ - [3] = {4, &clk_sata_init}, - [4] = {5, &clk_audio_init}, - [5] = {6, &clk_usbmph_init}, - [6] = {7, &clk_etha_init}, - [7] = {8, &clk_pciea_init}, - [8] = {9, &clk_nand_init}, + +static struct oxnas_stdclk_data ox810se_stdclk_data = { + .onecell_data = &ox810se_hw_onecell_data, + .gates = ox810se_gates, + .ngates = ARRAY_SIZE(ox810se_gates), }; -struct clk_oxnas_data { - struct clk_oxnas_gate clk_oxnas[ARRAY_SIZE(clk_oxnas_init)]; - struct clk_onecell_data onecell_data[ARRAY_SIZE(clk_oxnas_init)]; - struct clk *clks[ARRAY_SIZE(clk_oxnas_init)]; + +static const struct of_device_id oxnas_stdclk_dt_ids[] = { + { .compatible = "oxsemi,ox810se-stdclk", &ox810se_stdclk_data }, + { } }; static int oxnas_stdclk_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct clk_oxnas_data *clk_oxnas; + const struct oxnas_stdclk_data *data; + const struct of_device_id *id; struct regmap *regmap; + int ret; int i; - clk_oxnas = devm_kzalloc(&pdev->dev, sizeof(*clk_oxnas), GFP_KERNEL); - if (!clk_oxnas) - return -ENOMEM; + id = of_match_device(oxnas_stdclk_dt_ids, &pdev->dev); + if (!id) + return -ENODEV; + data = id->data; regmap = syscon_node_to_regmap(of_get_parent(np)); if (IS_ERR(regmap)) { @@ -149,32 +178,23 @@ static int oxnas_stdclk_probe(struct platform_device *pdev) return PTR_ERR(regmap); } - for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) { - struct clk_oxnas_gate *_clk; + for (i = 0 ; i < data->ngates ; ++i) + data->gates[i]->regmap = regmap; - _clk = &clk_oxnas->clk_oxnas[i]; - _clk->bit = clk_oxnas_init[i].bit; - _clk->hw.init = clk_oxnas_init[i].clk_init; - _clk->regmap = regmap; + for (i = 0; i < data->onecell_data->num; i++) { + if (!data->onecell_data->hws[i]) + continue; - clk_oxnas->clks[i] = - devm_clk_register(&pdev->dev, &_clk->hw); - if (WARN_ON(IS_ERR(clk_oxnas->clks[i]))) - return PTR_ERR(clk_oxnas->clks[i]); + ret = devm_clk_hw_register(&pdev->dev, + data->onecell_data->hws[i]); + if (ret) + return ret; } - clk_oxnas->onecell_data->clks = clk_oxnas->clks; - clk_oxnas->onecell_data->clk_num = ARRAY_SIZE(clk_oxnas_init); - - return of_clk_add_provider(np, of_clk_src_onecell_get, - clk_oxnas->onecell_data); + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, + data->onecell_data); } -static const struct of_device_id oxnas_stdclk_dt_ids[] = { - { .compatible = "oxsemi,ox810se-stdclk" }, - { } -}; - static struct platform_driver oxnas_stdclk_driver = { .probe = oxnas_stdclk_probe, .driver = { -- cgit v1.2.3 From 6df4393daf8b7a3f7c395e7858b734e2dc9b116b Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 5 Oct 2016 17:07:51 +0200 Subject: clk: oxnas: Add OX820 Gate clocks Add support for the Oxford Semiconductor OX820 SoC gate clocks along the OX810SE SoC support. This rework on concerns the gate clocks since they are different. Future PLL handling code will be added for OX820. Signed-off-by: Neil Armstrong Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20161005150752.22618-6-narmstrong@baylibre.com --- drivers/clk/clk-oxnas.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c index b1ef3ea990f1..e51e0023fc6e 100644 --- a/drivers/clk/clk-oxnas.c +++ b/drivers/clk/clk-oxnas.c @@ -27,6 +27,7 @@ #include #include +#include /* Standard regmap gate clocks */ struct clk_oxnas_gate { @@ -130,6 +131,38 @@ static struct clk_oxnas_gate *ox810se_gates[] = { &ox810se_nand, }; +static OXNAS_GATE(ox820_leon, 0, osc_parents); +static OXNAS_GATE(ox820_dma_sgdma, 1, osc_parents); +static OXNAS_GATE(ox820_cipher, 2, osc_parents); +static OXNAS_GATE(ox820_sd, 3, osc_parents); +static OXNAS_GATE(ox820_sata, 4, osc_parents); +static OXNAS_GATE(ox820_audio, 5, osc_parents); +static OXNAS_GATE(ox820_usbmph, 6, osc_parents); +static OXNAS_GATE(ox820_etha, 7, eth_parents); +static OXNAS_GATE(ox820_pciea, 8, osc_parents); +static OXNAS_GATE(ox820_nand, 9, osc_parents); +static OXNAS_GATE(ox820_ethb, 10, eth_parents); +static OXNAS_GATE(ox820_pcieb, 11, osc_parents); +static OXNAS_GATE(ox820_ref600, 12, osc_parents); +static OXNAS_GATE(ox820_usbdev, 13, osc_parents); + +static struct clk_oxnas_gate *ox820_gates[] = { + &ox820_leon, + &ox820_dma_sgdma, + &ox820_cipher, + &ox820_sd, + &ox820_sata, + &ox820_audio, + &ox820_usbmph, + &ox820_etha, + &ox820_pciea, + &ox820_nand, + &ox820_etha, + &ox820_pciea, + &ox820_ref600, + &ox820_usbdev, +}; + static struct clk_hw_onecell_data ox810se_hw_onecell_data = { .hws = { [CLK_810_LEON] = &ox810se_leon.hw, @@ -145,6 +178,25 @@ static struct clk_hw_onecell_data ox810se_hw_onecell_data = { .num = ARRAY_SIZE(ox810se_gates), }; +static struct clk_hw_onecell_data ox820_hw_onecell_data = { + .hws = { + [CLK_820_LEON] = &ox820_leon.hw, + [CLK_820_DMA_SGDMA] = &ox820_dma_sgdma.hw, + [CLK_820_CIPHER] = &ox820_cipher.hw, + [CLK_820_SD] = &ox820_sd.hw, + [CLK_820_SATA] = &ox820_sata.hw, + [CLK_820_AUDIO] = &ox820_audio.hw, + [CLK_820_USBMPH] = &ox820_usbmph.hw, + [CLK_820_ETHA] = &ox820_etha.hw, + [CLK_820_PCIEA] = &ox820_pciea.hw, + [CLK_820_NAND] = &ox820_nand.hw, + [CLK_820_ETHB] = &ox820_ethb.hw, + [CLK_820_PCIEB] = &ox820_pcieb.hw, + [CLK_820_REF600] = &ox820_ref600.hw, + [CLK_820_USBDEV] = &ox820_usbdev.hw, + }, + .num = ARRAY_SIZE(ox820_gates), +}; static struct oxnas_stdclk_data ox810se_stdclk_data = { .onecell_data = &ox810se_hw_onecell_data, @@ -152,9 +204,15 @@ static struct oxnas_stdclk_data ox810se_stdclk_data = { .ngates = ARRAY_SIZE(ox810se_gates), }; +static struct oxnas_stdclk_data ox820_stdclk_data = { + .onecell_data = &ox820_hw_onecell_data, + .gates = ox820_gates, + .ngates = ARRAY_SIZE(ox820_gates), +}; static const struct of_device_id oxnas_stdclk_dt_ids[] = { { .compatible = "oxsemi,ox810se-stdclk", &ox810se_stdclk_data }, + { .compatible = "oxsemi,ox820-stdclk", &ox820_stdclk_data }, { } }; -- cgit v1.2.3 From 6572389bcc1121b4e4112632e289a57a1136989d Mon Sep 17 00:00:00 2001 From: sayli karnik Date: Mon, 10 Oct 2016 21:09:17 +0530 Subject: staging: iio: cdc: ad7152: Implement IIO_CHAN_INFO_SAMP_FREQ attribute Attributes that were once privately defined become standard with time and hence a special global define is used. Hence update driver ad7152 to use IIO_CHAN_INFO_SAMP_FREQ which is a global define instead of IIO_DEV_ATTR_SAMP_FREQ. Move functionality from IIO_DEV_ATTR_SAMP_FREQ attribute into IIO_CHAN_INFO_SAMP_FREQ to implement the sampling_frequency attribute. Modify ad7152_read_raw() and ad7152_write_raw() to allow reading and writing the element as well. Also add a lock in the driver's private data. Signed-off-by: sayli karnik Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7152.c | 118 ++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index 928f70085bd1..0203c8103750 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -167,63 +167,12 @@ static const unsigned char ad7152_filter_rate_table[][2] = { {200, 5 + 1}, {50, 20 + 1}, {20, 50 + 1}, {17, 60 + 1}, }; -static ssize_t ad7152_show_filter_rate_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7152_chip_info *chip = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", - ad7152_filter_rate_table[chip->filter_rate_setup][0]); -} - -static ssize_t ad7152_store_filter_rate_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7152_chip_info *chip = iio_priv(indio_dev); - u8 data; - int ret, i; - - ret = kstrtou8(buf, 10, &data); - if (ret < 0) - return ret; - - for (i = 0; i < ARRAY_SIZE(ad7152_filter_rate_table); i++) - if (data >= ad7152_filter_rate_table[i][0]) - break; - - if (i >= ARRAY_SIZE(ad7152_filter_rate_table)) - i = ARRAY_SIZE(ad7152_filter_rate_table) - 1; - - mutex_lock(&indio_dev->mlock); - ret = i2c_smbus_write_byte_data(chip->client, - AD7152_REG_CFG2, AD7152_CFG2_OSR(i)); - if (ret < 0) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - - chip->filter_rate_setup = i; - mutex_unlock(&indio_dev->mlock); - - return len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, - ad7152_show_filter_rate_setup, - ad7152_store_filter_rate_setup); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("200 50 20 17"); static IIO_CONST_ATTR(in_capacitance_scale_available, "0.000061050 0.000030525 0.000015263 0.000007631"); static struct attribute *ad7152_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, @@ -249,6 +198,51 @@ static const int ad7152_scale_table[] = { 30525, 7631, 15263, 61050 }; +/** + * read_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * + * lock must be held + **/ +static int ad7152_read_raw_samp_freq(struct device *dev, int *val) +{ + struct ad7152_chip_info *chip = iio_priv(dev_to_iio_dev(dev)); + + *val = ad7152_filter_rate_table[chip->filter_rate_setup][0]; + + return 0; +} + +/** + * write_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * + * lock must be held + **/ +static int ad7152_write_raw_samp_freq(struct device *dev, int val) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7152_chip_info *chip = iio_priv(indio_dev); + int ret, i; + + for (i = 0; i < ARRAY_SIZE(ad7152_filter_rate_table); i++) + if (val >= ad7152_filter_rate_table[i][0]) + break; + + if (i >= ARRAY_SIZE(ad7152_filter_rate_table)) + i = ARRAY_SIZE(ad7152_filter_rate_table) - 1; + + mutex_lock(&indio_dev->mlock); + ret = i2c_smbus_write_byte_data(chip->client, + AD7152_REG_CFG2, AD7152_CFG2_OSR(i)); + if (ret < 0) { + mutex_unlock(&indio_dev->mlock); + return ret; + } + + chip->filter_rate_setup = i; + mutex_unlock(&indio_dev->mlock); + + return ret; +} static int ad7152_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, @@ -309,6 +303,17 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, if (ret < 0) goto out; + ret = 0; + break; + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) { + ret = -EINVAL; + goto out; + } + ret = ad7152_write_raw_samp_freq(&indio_dev->dev, val); + if (ret < 0) + goto out; + ret = 0; break; default: @@ -406,6 +411,13 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT_PLUS_NANO; break; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = ad7152_read_raw_samp_freq(&indio_dev->dev, val); + if (ret < 0) + goto out; + + ret = IIO_VAL_INT; + break; default: ret = -EINVAL; } @@ -443,6 +455,7 @@ static const struct iio_chan_spec ad7152_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), }, { .type = IIO_CAPACITANCE, .differential = 1, @@ -453,6 +466,7 @@ static const struct iio_chan_spec ad7152_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), }, { .type = IIO_CAPACITANCE, .indexed = 1, @@ -461,6 +475,7 @@ static const struct iio_chan_spec ad7152_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), }, { .type = IIO_CAPACITANCE, .differential = 1, @@ -471,6 +486,7 @@ static const struct iio_chan_spec ad7152_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), } }; -- cgit v1.2.3 From 2296c0623eb741d4985b4fbd5c2c8e48a2795d2a Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Mon, 10 Oct 2016 18:01:31 +0800 Subject: staging: iio: cdc: ad7746: implement IIO_CHAN_INFO_SAMP_FREQ This driver predates the availability of IIO_CHAN_INFO_SAMP_FREQ attribute wherein usage has some advantages like it can be accessed by in-kernel consumers as well as reduces the code size. Therefore, use IIO_CHAN_INFO_SAMP_FREQ to implement the sampling_frequency attribute instead of using IIO_DEVICE_ATTR() macro. Move code from the functions associated with IIO_DEVICE_ATTR() into respective read and write hooks with the mask set to IIO_CHAN_INFO_SAMP_FREQ. Signed-off-by: Eva Rachel Retuya Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 120 ++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 5771d4ee8ef1..f41251ceeacd 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -122,7 +122,8 @@ static const struct iio_chan_spec ad7746_channels[] = { .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_EXT_VIN, }, @@ -132,7 +133,8 @@ static const struct iio_chan_spec ad7746_channels[] = { .channel = 1, .extend_name = "supply", .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_VDD_MON, }, @@ -159,7 +161,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7746_REG_CAP_DATA_HIGH << 8, }, [CIN1_DIFF] = { @@ -171,7 +173,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CAPDIFF }, @@ -182,7 +184,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CIN2, }, @@ -195,7 +197,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CAPDIFF | AD7746_CAPSETUP_CIN2, } @@ -355,101 +357,47 @@ static IIO_DEVICE_ATTR(in_capacitance1_calibscale_calibration, static IIO_DEVICE_ATTR(in_voltage0_calibscale_calibration, S_IWUSR, NULL, ad7746_start_gain_calib, VIN); -static ssize_t ad7746_show_cap_filter_rate_setup(struct device *dev, - struct device_attribute *attr, - char *buf) +static int ad7746_store_cap_filter_rate_setup(struct ad7746_chip_info *chip, + int val) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7746_chip_info *chip = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", ad7746_cap_filter_rate_table[ - (chip->config >> 3) & 0x7][0]); -} - -static ssize_t ad7746_store_cap_filter_rate_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7746_chip_info *chip = iio_priv(indio_dev); - u8 data; - int ret, i; - - ret = kstrtou8(buf, 10, &data); - if (ret < 0) - return ret; + int i; for (i = 0; i < ARRAY_SIZE(ad7746_cap_filter_rate_table); i++) - if (data >= ad7746_cap_filter_rate_table[i][0]) + if (val >= ad7746_cap_filter_rate_table[i][0]) break; if (i >= ARRAY_SIZE(ad7746_cap_filter_rate_table)) i = ARRAY_SIZE(ad7746_cap_filter_rate_table) - 1; - mutex_lock(&indio_dev->mlock); chip->config &= ~AD7746_CONF_CAPFS(0x7); chip->config |= AD7746_CONF_CAPFS(i); - mutex_unlock(&indio_dev->mlock); - return len; + return 0; } -static ssize_t ad7746_show_vt_filter_rate_setup(struct device *dev, - struct device_attribute *attr, - char *buf) +static int ad7746_store_vt_filter_rate_setup(struct ad7746_chip_info *chip, + int val) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7746_chip_info *chip = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", ad7746_vt_filter_rate_table[ - (chip->config >> 6) & 0x3][0]); -} - -static ssize_t ad7746_store_vt_filter_rate_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7746_chip_info *chip = iio_priv(indio_dev); - u8 data; - int ret, i; - - ret = kstrtou8(buf, 10, &data); - if (ret < 0) - return ret; + int i; for (i = 0; i < ARRAY_SIZE(ad7746_vt_filter_rate_table); i++) - if (data >= ad7746_vt_filter_rate_table[i][0]) + if (val >= ad7746_vt_filter_rate_table[i][0]) break; if (i >= ARRAY_SIZE(ad7746_vt_filter_rate_table)) i = ARRAY_SIZE(ad7746_vt_filter_rate_table) - 1; - mutex_lock(&indio_dev->mlock); chip->config &= ~AD7746_CONF_VTFS(0x3); chip->config |= AD7746_CONF_VTFS(i); - mutex_unlock(&indio_dev->mlock); - return len; + return 0; } -static IIO_DEVICE_ATTR(in_capacitance_sampling_frequency, - S_IRUGO | S_IWUSR, ad7746_show_cap_filter_rate_setup, - ad7746_store_cap_filter_rate_setup, 0); - -static IIO_DEVICE_ATTR(in_voltage_sampling_frequency, - S_IRUGO | S_IWUSR, ad7746_show_vt_filter_rate_setup, - ad7746_store_vt_filter_rate_setup, 0); - static IIO_CONST_ATTR(in_voltage_sampling_frequency_available, "50 31 16 8"); static IIO_CONST_ATTR(in_capacitance_sampling_frequency_available, "91 84 50 26 16 13 11 9"); static struct attribute *ad7746_attributes[] = { - &iio_dev_attr_in_capacitance_sampling_frequency.dev_attr.attr, - &iio_dev_attr_in_voltage_sampling_frequency.dev_attr.attr, &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr, @@ -547,6 +495,23 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, ret = 0; break; + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) { + ret = -EINVAL; + goto out; + } + + switch (chan->type) { + case IIO_CAPACITANCE: + ret = ad7746_store_cap_filter_rate_setup(chip, val); + break; + case IIO_VOLTAGE: + ret = ad7746_store_vt_filter_rate_setup(chip, val); + break; + default: + ret = -EINVAL; + } + break; default: ret = -EINVAL; } @@ -666,6 +631,21 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, break; } + break; + case IIO_CHAN_INFO_SAMP_FREQ: + switch (chan->type) { + case IIO_CAPACITANCE: + *val = ad7746_cap_filter_rate_table[ + (chip->config >> 3) & 0x7][0]; + ret = IIO_VAL_INT; + break; + case IIO_VOLTAGE: + *val = ad7746_vt_filter_rate_table[ + (chip->config >> 6) & 0x3][0]; + break; + default: + ret = -EINVAL; + } break; default: ret = -EINVAL; -- cgit v1.2.3 From f08a1508476d4501d32a0e82d28d5734243c4b11 Mon Sep 17 00:00:00 2001 From: sayli karnik Date: Mon, 10 Oct 2016 11:50:48 +0530 Subject: staging: iio: cdc: ad7152: Replace mlock with a local mutex lock mlock is intended to protect only switches between modes. Given this driver doesn't support more than one mode (sysfs polled reads only), replace mlock with a local mutex lock. Signed-off-by: sayli karnik Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7152.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index 0203c8103750..b91b50f345bd 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -89,6 +89,7 @@ struct ad7152_chip_info { */ u8 filter_rate_setup; u8 setup[2]; + struct mutex state_lock; /* protect hardware state */ }; static inline ssize_t ad7152_start_calib(struct device *dev, @@ -115,10 +116,10 @@ static inline ssize_t ad7152_start_calib(struct device *dev, else regval |= AD7152_CONF_CH2EN; - mutex_lock(&indio_dev->mlock); + mutex_lock(&chip->state_lock); ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG, regval); if (ret < 0) { - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&chip->state_lock); return ret; } @@ -126,12 +127,12 @@ static inline ssize_t ad7152_start_calib(struct device *dev, mdelay(20); ret = i2c_smbus_read_byte_data(chip->client, AD7152_REG_CFG); if (ret < 0) { - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&chip->state_lock); return ret; } } while ((ret == regval) && timeout--); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&chip->state_lock); return len; } @@ -230,16 +231,16 @@ static int ad7152_write_raw_samp_freq(struct device *dev, int val) if (i >= ARRAY_SIZE(ad7152_filter_rate_table)) i = ARRAY_SIZE(ad7152_filter_rate_table) - 1; - mutex_lock(&indio_dev->mlock); + mutex_lock(&chip->state_lock); ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG2, AD7152_CFG2_OSR(i)); if (ret < 0) { - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&chip->state_lock); return ret; } chip->filter_rate_setup = i; - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&chip->state_lock); return ret; } @@ -252,7 +253,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, struct ad7152_chip_info *chip = iio_priv(indio_dev); int ret, i; - mutex_lock(&indio_dev->mlock); + mutex_lock(&chip->state_lock); switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: @@ -321,7 +322,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, } out: - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&chip->state_lock); return ret; } @@ -334,7 +335,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, int ret; u8 regval = 0; - mutex_lock(&indio_dev->mlock); + mutex_lock(&chip->state_lock); switch (mask) { case IIO_CHAN_INFO_RAW: @@ -422,7 +423,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, ret = -EINVAL; } out: - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&chip->state_lock); return ret; } @@ -509,6 +510,7 @@ static int ad7152_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); chip->client = client; + mutex_init(&chip->state_lock); /* Establish that the iio_dev is a child of the i2c device */ indio_dev->name = id->name; -- cgit v1.2.3 From 92da01a08deb4678a2b653f65b9e685d90e261c9 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Oct 2016 11:38:19 +0100 Subject: staging:iio:TODO drop outdated entries in this todo. There is still stuff to be done in the remaining drivers but pretty much nothing was left from this original TODO. Sorry Greg, should have been keeping this up to date. Signed-off-by: Jonathan Cameron Acked-by: Greg Kroah-Hartman --- drivers/staging/iio/TODO | 70 +----------------------------------------------- 1 file changed, 1 insertion(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO index 93a896883e37..4922402e2e98 100644 --- a/drivers/staging/iio/TODO +++ b/drivers/staging/iio/TODO @@ -1,76 +1,8 @@ -2009 8/18 - -Core: -1) Get reviews -2) Additional testing -3) Ensure all desirable features present by adding more devices. - Major changes not expected except in response to comments - -Max1363 core: -1) Possibly add sysfs exports of constant useful to userspace. -Would be nice -2) Support hardware generated interrupts -3) Expand device set. Lots of other maxim adc's have very - similar interfaces. - -MXS LRADC driver: -This is a classic MFD device as it combines the following subdevices - - touchscreen controller (input subsystem related device) - - general purpose ADC channels - - battery voltage monitor (power subsystem related device) - - die temperature monitor (thermal management) - -At least the battery voltage and die temperature feature is required in-kernel -by a driver of the SoC's battery charging unit to avoid any damage to the -silicon and the battery. - -TSL2561 -Would be nice -1) Open question of userspace vs kernel space balance when -converting to useful light measurements from device ones. -2) Add sysfs elements necessary to allow device agnostic -unit conversion. - -LIS3L02DQ core - -LIS3L02DQ ring - -KXSD9 -Currently minimal driver, would be nice to add: -1) Support for all chip generated interrupts (events), -basically get support up to level of lis3l02dq driver. - -Ring buffer core - -SCA3000 -Would be nice -1) Testing on devices other than sca3000-e05 - -Trigger core support -1) Discussion of approach. Is it general enough? - -Ring Buffer: -1) Discussion of approach. -There are probably better ways of doing this. The -intention is to allow for more than one software ring -buffer implementation as different users will have -different requirements. This one suits mid range -frequencies (100Hz - 4kHz). -2) Lots of testing - -GPIO trigger -1) Add control over the type of interrupt etc. This will -necessitate a header that is also visible from arch board -files. (avoided at the moment to keep the driver set -contained in staging). +2016 10/09 ADI Drivers: CC the device-drivers-devel@blackfin.uclinux.org mailing list when e-mailing the normal IIO list (see below). -Documentation -1) Lots of cleanup and expansion. -2) Some device require individual docs. - Contact: Jonathan Cameron . Mailing list: linux-iio@vger.kernel.org -- cgit v1.2.3 From 744ef62c2ee6ab71cdae944368983dc59b77dc32 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 10 Oct 2016 03:19:55 -0400 Subject: staging: iio: isl29018: add newlines to improve readability Add newlines to improve code readability in preparation for moving the driver out of staging. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 52bfb1cbe8e0..26bbbb87f743 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -399,6 +399,7 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, write_done: mutex_unlock(&chip->lock); + return ret; } @@ -464,6 +465,7 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, read_done: mutex_unlock(&chip->lock); + return ret; } @@ -726,6 +728,7 @@ static int isl29018_probe(struct i2c_client *client, indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); if (!indio_dev) return -ENOMEM; + chip = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); @@ -765,6 +768,7 @@ static int isl29018_probe(struct i2c_client *client, indio_dev->name = name; indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; + return devm_iio_device_register(&client->dev, indio_dev); } @@ -782,6 +786,7 @@ static int isl29018_suspend(struct device *dev) chip->suspended = true; mutex_unlock(&chip->lock); + return 0; } @@ -797,6 +802,7 @@ static int isl29018_resume(struct device *dev) chip->suspended = false; mutex_unlock(&chip->lock); + return err; } -- cgit v1.2.3 From 8281101c2d69dd784baf8bdd0895b40ff041b756 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 10 Oct 2016 03:19:56 -0400 Subject: staging: iio: isl29018: fix poorly named function isl29035_detect() did not just do chip detection. Move functionality directly into isl29018_chip_init() to avoid naming confusion. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 44 ++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 26bbbb87f743..130f2225a6fc 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -529,30 +529,6 @@ static const struct attribute_group isl29023_group = { .attrs = isl29023_attributes, }; -static int isl29035_detect(struct isl29018_chip *chip) -{ - int status; - unsigned int id; - struct device *dev = regmap_get_device(chip->regmap); - - status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id); - if (status < 0) { - dev_err(dev, - "Error reading ID register with error %d\n", - status); - return status; - } - - id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT; - - if (id != ISL29035_DEVICE_ID) - return -ENODEV; - - /* Clear brownout bit */ - return regmap_update_bits(chip->regmap, ISL29035_REG_DEVICE_ID, - ISL29035_BOUT_MASK, 0); -} - enum { isl29018, isl29023, @@ -565,7 +541,25 @@ static int isl29018_chip_init(struct isl29018_chip *chip) struct device *dev = regmap_get_device(chip->regmap); if (chip->type == isl29035) { - status = isl29035_detect(chip); + unsigned int id; + + status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id); + if (status < 0) { + dev_err(dev, + "Error reading ID register with error %d\n", + status); + return status; + } + + id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT; + + if (id != ISL29035_DEVICE_ID) + return -ENODEV; + + /* Clear brownout bit */ + status = regmap_update_bits(chip->regmap, + ISL29035_REG_DEVICE_ID, + ISL29035_BOUT_MASK, 0); if (status < 0) return status; } -- cgit v1.2.3 From 19a00a9d4c9027b4ce93b7c500da53dcb36ba1b0 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 10 Oct 2016 03:19:57 -0400 Subject: staging: iio: isl29018: fix multiline comment syntax Change multiline comments from: /* line1 * line2 * ... */ to /* * line1 * line2 * ... */ Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 130f2225a6fc..132de8e93bf8 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -564,7 +564,8 @@ static int isl29018_chip_init(struct isl29018_chip *chip) return status; } - /* Code added per Intersil Application Note 1534: + /* + * Code added per Intersil Application Note 1534: * When VDD sinks to approximately 1.8V or below, some of * the part's registers may change their state. When VDD * recovers to 2.25V (or greater), the part may thus be in an @@ -591,7 +592,8 @@ static int isl29018_chip_init(struct isl29018_chip *chip) return status; } - /* See Intersil AN1534 comments above. + /* + * See Intersil AN1534 comments above. * "Operating Mode" (COMMAND1) register is reprogrammed when * data is read from the device. */ @@ -773,7 +775,8 @@ static int isl29018_suspend(struct device *dev) mutex_lock(&chip->lock); - /* Since this driver uses only polling commands, we are by default in + /* + * Since this driver uses only polling commands, we are by default in * auto shutdown (ie, power-down) mode. * So we do not have much to do here. */ -- cgit v1.2.3 From aba1a8d77fe355d1b698e10b97c74974ca8b7438 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 10 Oct 2016 03:19:58 -0400 Subject: staging: iio: isl29018: combine two return statements into one Use the return value from isl29018_set_integration_time() as the return value for isl29018_chip_init() since this is the last piece of work inside that function. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 132de8e93bf8..6b6c761c801d 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -616,12 +616,10 @@ static int isl29018_chip_init(struct isl29018_chip *chip) status = isl29018_set_integration_time(chip, isl29018_int_utimes[chip->type][chip->int_time]); - if (status < 0) { + if (status < 0) dev_err(dev, "Init of isl29018 fails\n"); - return status; - } - return 0; + return status; } static const struct iio_info isl29018_info = { -- cgit v1.2.3 From b2f85b08c9e7d6c5aadc59f762f5dd77a9efd683 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 10 Oct 2016 03:19:59 -0400 Subject: staging: iio: isl29018: remove blank line for consistency Remove blank line between MODULE_DEVICE_TABLE() and its corresponding structure for consistency with the other device table entries. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 6b6c761c801d..917dd8b43e72 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -821,7 +821,6 @@ static const struct i2c_device_id isl29018_id[] = { {"isl29035", isl29035}, {} }; - MODULE_DEVICE_TABLE(i2c, isl29018_id); static const struct of_device_id isl29018_of_match[] = { -- cgit v1.2.3 From bac80fd0cf889d99461e54e4e1ae31392769f635 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 10 Oct 2016 03:20:00 -0400 Subject: staging: iio: isl29018: rename description in Kconfig for consistency Rename description from "ISL 29018" to "Intersil 29018" in Kconfig for consistency with other drivers in mainline. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig index ca8d6e66c899..5e4e77ef7f98 100644 --- a/drivers/staging/iio/light/Kconfig +++ b/drivers/staging/iio/light/Kconfig @@ -4,7 +4,7 @@ menu "Light sensors" config SENSORS_ISL29018 - tristate "ISL 29018 light and proximity sensor" + tristate "Intersil 29018 light and proximity sensor" depends on I2C select REGMAP_I2C default n -- cgit v1.2.3 From dd4ba3fb22233e69f06399ee0aa7ecb11d2b595c Mon Sep 17 00:00:00 2001 From: sayli karnik Date: Tue, 11 Oct 2016 17:07:21 +0530 Subject: iio: bmi160_core: Fix sparse warning due to incorrect type in assignment There is a type mismatch between the buffer which is of type s16 and the samples stored, which are declared as __le16. Fix the following sparse warning: drivers/iio/imu/bmi160/bmi160_core.c:411:26: warning: incorrect type in assignment (different base types) drivers/iio/imu/bmi160/bmi160_core.c:411:26: expected signed short [signed] [short] [explicitly-signed] drivers/iio/imu/bmi160/bmi160_core.c:411:26: got restricted __le16 [addressable] [usertype] sample This is a cosmetic-type patch since it does not alter code behaviour. The le16 is going into a 16bit buf element, and is labelled as IIO_LE in the channel buffer definition. Signed-off-by: sayli karnik Signed-off-by: Jonathan Cameron --- drivers/iio/imu/bmi160/bmi160_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c index e0251b8c1a52..5355507f8fa1 100644 --- a/drivers/iio/imu/bmi160/bmi160_core.c +++ b/drivers/iio/imu/bmi160/bmi160_core.c @@ -398,7 +398,8 @@ static irqreturn_t bmi160_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmi160_data *data = iio_priv(indio_dev); - s16 buf[16]; /* 3 sens x 3 axis x s16 + 3 x s16 pad + 4 x s16 tstamp */ + __le16 buf[16]; + /* 3 sens x 3 axis x __le16 + 3 x __le16 pad + 4 x __le16 tstamp */ int i, ret, j = 0, base = BMI160_REG_DATA_MAGN_XOUT_L; __le16 sample; -- cgit v1.2.3 From 3f5def652f6609dd1981be8283de155f15a3df48 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Fri, 14 Oct 2016 15:43:14 +0200 Subject: iio: ms65611_core: Fixes dereferencing regulator pointer Change in handling of the regulator description means that static checkers correctly assume we could be using dereferenced pointer to the regulator. In reality we will never get the -ENODEV error, as current behavior flow does not predict it, because: If the device tree or board file does not define suitable regulators for the component, it will be substituted by a dummy regulator, or, if regulators are disabled altogether, by stubs. Reported-by: Dan Carpenter Suggested-by: Lars-Peter Clausen Signed-off-by: Crt Mori Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5611_core.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index a74ed1f0c880..6bd53e702667 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -392,17 +392,14 @@ static int ms5611_init(struct iio_dev *indio_dev) /* Enable attached regulator if any. */ st->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd"); - if (!IS_ERR(st->vdd)) { - ret = regulator_enable(st->vdd); - if (ret) { - dev_err(indio_dev->dev.parent, - "failed to enable Vdd supply: %d\n", ret); - return ret; - } - } else { - ret = PTR_ERR(st->vdd); - if (ret != -ENODEV) - return ret; + if (IS_ERR(st->vdd)) + return PTR_ERR(st->vdd); + + ret = regulator_enable(st->vdd); + if (ret) { + dev_err(indio_dev->dev.parent, + "failed to enable Vdd supply: %d\n", ret); + return ret; } ret = ms5611_reset(indio_dev); -- cgit v1.2.3 From b440f1d90ec54fd2586537ea46e958343ad4b151 Mon Sep 17 00:00:00 2001 From: Tomas Novotny Date: Tue, 11 Oct 2016 15:57:40 +0200 Subject: iio: dac: mcp4725: use regulator framework Use a standard framework to get the reference voltage. It is done that way in the iio subsystem and it will simplify extending of the driver. Structure mcp4725_platform_data is left undeleted because it used in the next patch. This change breaks the current users of the driver, but there is no mainline user of struct mcp4725_platform_data. Signed-off-by: Tomas Novotny Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp4725.c | 46 +++++++++++++++++++++++++++++++++-------- include/linux/iio/dac/mcp4725.h | 1 - 2 files changed, 37 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index cca935c06f2b..2b28b1f5b3a2 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -28,10 +29,10 @@ struct mcp4725_data { struct i2c_client *client; - u16 vref_mv; u16 dac_value; bool powerdown; unsigned powerdown_mode; + struct regulator *vdd_reg; }; static int mcp4725_suspend(struct device *dev) @@ -283,13 +284,18 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct mcp4725_data *data = iio_priv(indio_dev); + int ret; switch (mask) { case IIO_CHAN_INFO_RAW: *val = data->dac_value; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = data->vref_mv; + ret = regulator_get_voltage(data->vdd_reg); + if (ret < 0) + return ret; + + *val = ret / 1000; *val2 = 12; return IIO_VAL_FRACTIONAL_LOG2; } @@ -328,12 +334,12 @@ static int mcp4725_probe(struct i2c_client *client, { struct mcp4725_data *data; struct iio_dev *indio_dev; - struct mcp4725_platform_data *platform_data = client->dev.platform_data; + struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev); u8 inbuf[3]; u8 pd; int err; - if (!platform_data || !platform_data->vref_mv) { + if (!pdata) { dev_err(&client->dev, "invalid platform data"); return -EINVAL; } @@ -345,6 +351,14 @@ static int mcp4725_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; + data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); + if (IS_ERR(data->vdd_reg)) + return PTR_ERR(data->vdd_reg); + + err = regulator_enable(data->vdd_reg); + if (err) + return err; + indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->info = &mcp4725_info; @@ -352,25 +366,39 @@ static int mcp4725_probe(struct i2c_client *client, indio_dev->num_channels = 1; indio_dev->modes = INDIO_DIRECT_MODE; - data->vref_mv = platform_data->vref_mv; - /* read current DAC value */ err = i2c_master_recv(client, inbuf, 3); if (err < 0) { dev_err(&client->dev, "failed to read DAC value"); - return err; + goto err_disable_vdd_reg; } pd = (inbuf[0] >> 1) & 0x3; data->powerdown = pd > 0 ? true : false; data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */ data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); - return iio_device_register(indio_dev); + err = iio_device_register(indio_dev); + if (err) + goto err_disable_vdd_reg; + + return 0; + + +err_disable_vdd_reg: + regulator_disable(data->vdd_reg); + + return err; } static int mcp4725_remove(struct i2c_client *client) { - iio_device_unregister(i2c_get_clientdata(client)); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mcp4725_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + regulator_disable(data->vdd_reg); + return 0; } diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h index 91530e6611e9..7c062e8d2a48 100644 --- a/include/linux/iio/dac/mcp4725.h +++ b/include/linux/iio/dac/mcp4725.h @@ -10,7 +10,6 @@ #define IIO_DAC_MCP4725_H_ struct mcp4725_platform_data { - u16 vref_mv; }; #endif /* IIO_DAC_MCP4725_H_ */ -- cgit v1.2.3 From 4d9b0413e29d61e6382b613f4835118504e65e86 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Tue, 11 Oct 2016 12:31:36 -0700 Subject: iio: accel: mma8452: claim direct mode during raw reads Driver was checking for direct mode but not locking it. Use claim/release helper functions to guarantee the device stays in direct mode during raw reads. Signed-off-by: Alison Schofield Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 1c7051581513..7951def89d63 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -459,12 +459,14 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; mutex_lock(&data->lock); ret = mma8452_read(data, buffer); mutex_unlock(&data->lock); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; -- cgit v1.2.3 From 79de2ee469aaef0afb25dde7d65d7fbc91600573 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 15 Oct 2016 15:55:06 +0100 Subject: iio: accel: mma8452: claim direct mode during write raw Driver was checking for direct mode but not locking it. Use claim/release helper functions to guarantee the device stays in direct mode during all write raw operations. Signed-off-by: Alison Schofield Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 60 ++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 7951def89d63..f418c588af6a 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -666,37 +666,46 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, struct mma8452_data *data = iio_priv(indio_dev); int i, ret; - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: i = mma8452_get_samp_freq_index(data, val, val2); - if (i < 0) - return i; - + if (i < 0) { + ret = i; + break; + } data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK; data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT; - return mma8452_change_config(data, MMA8452_CTRL_REG1, - data->ctrl_reg1); + ret = mma8452_change_config(data, MMA8452_CTRL_REG1, + data->ctrl_reg1); + break; case IIO_CHAN_INFO_SCALE: i = mma8452_get_scale_index(data, val, val2); - if (i < 0) - return i; + if (i < 0) { + ret = i; + break; + } data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK; data->data_cfg |= i; - return mma8452_change_config(data, MMA8452_DATA_CFG, - data->data_cfg); + ret = mma8452_change_config(data, MMA8452_DATA_CFG, + data->data_cfg); + break; case IIO_CHAN_INFO_CALIBBIAS: - if (val < -128 || val > 127) - return -EINVAL; + if (val < -128 || val > 127) { + ret = -EINVAL; + break; + } - return mma8452_change_config(data, - MMA8452_OFF_X + chan->scan_index, - val); + ret = mma8452_change_config(data, + MMA8452_OFF_X + chan->scan_index, + val); + break; case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: if (val == 0 && val2 == 0) { @@ -705,23 +714,30 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, data->data_cfg |= MMA8452_DATA_CFG_HPF_MASK; ret = mma8452_set_hp_filter_frequency(data, val, val2); if (ret < 0) - return ret; + break; } - return mma8452_change_config(data, MMA8452_DATA_CFG, + ret = mma8452_change_config(data, MMA8452_DATA_CFG, data->data_cfg); + break; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ret = mma8452_get_odr_index(data); for (i = 0; i < ARRAY_SIZE(mma8452_os_ratio); i++) { - if (mma8452_os_ratio[i][ret] == val) - return mma8452_set_power_mode(data, i); + if (mma8452_os_ratio[i][ret] == val) { + ret = mma8452_set_power_mode(data, i); + break; + } } - + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + + iio_device_release_direct_mode(indio_dev); + return ret; } static int mma8452_read_thresh(struct iio_dev *indio_dev, -- cgit v1.2.3 From ac13980584d1fe2493516e1f6e839f0a3c425280 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Tue, 11 Oct 2016 12:33:12 -0700 Subject: iio: pressure: mpl3115: claim direct mode during raw reads Driver was checking for direct mode but not locking it. Use claim/release helper functions to guarantee the device stays in direct mode during raw reads. Signed-off-by: Alison Schofield Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/mpl3115.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index 6392d7b62841..cc3f84139157 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -82,8 +82,9 @@ static int mpl3115_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (chan->type) { case IIO_PRESSURE: /* in 0.25 pascal / LSB */ @@ -91,32 +92,39 @@ static int mpl3115_read_raw(struct iio_dev *indio_dev, ret = mpl3115_request(data); if (ret < 0) { mutex_unlock(&data->lock); - return ret; + break; } ret = i2c_smbus_read_i2c_block_data(data->client, MPL3115_OUT_PRESS, 3, (u8 *) &tmp); mutex_unlock(&data->lock); if (ret < 0) - return ret; + break; *val = be32_to_cpu(tmp) >> 12; - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; case IIO_TEMP: /* in 0.0625 celsius / LSB */ mutex_lock(&data->lock); ret = mpl3115_request(data); if (ret < 0) { mutex_unlock(&data->lock); - return ret; + break; } ret = i2c_smbus_read_i2c_block_data(data->client, MPL3115_OUT_TEMP, 2, (u8 *) &tmp); mutex_unlock(&data->lock); if (ret < 0) - return ret; + break; *val = sign_extend32(be32_to_cpu(tmp) >> 20, 11); - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_PRESSURE: -- cgit v1.2.3 From a57504144c62404472f3cc6a7bf4ada4508d5ddc Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Mon, 10 Oct 2016 03:20:02 -0400 Subject: staging: iio: isl29018: move out of staging Move ISL29018/ISL29023/ISL29035 driver out of staging into mainline. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 12 + drivers/iio/light/Makefile | 1 + drivers/iio/light/isl29018.c | 847 +++++++++++++++++++++++++++++++++++ drivers/staging/iio/light/Kconfig | 12 - drivers/staging/iio/light/Makefile | 1 - drivers/staging/iio/light/isl29018.c | 847 ----------------------------------- 6 files changed, 860 insertions(+), 860 deletions(-) create mode 100644 drivers/iio/light/isl29018.c delete mode 100644 drivers/staging/iio/light/isl29018.c (limited to 'drivers') diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index ba2e64d7ee58..d01172089828 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -140,6 +140,18 @@ config GP2AP020A00F To compile this driver as a module, choose M here: the module will be called gp2ap020a00f. +config SENSORS_ISL29018 + tristate "Intersil 29018 light and proximity sensor" + depends on I2C + select REGMAP_I2C + default n + help + If you say yes here you get support for ambient light sensing and + proximity infrared sensing from Intersil ISL29018. + This driver will provide the measurements of ambient light intensity + in lux, proximity infrared sensing and normal infrared sensing. + Data from sensor is accessible via sysfs. + config ISL29125 tristate "Intersil ISL29125 digital color light sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index c5768df87a17..15f24c557f5f 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_CM36651) += cm36651.o obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o +obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o obj-$(CONFIG_ISL29125) += isl29125.o obj-$(CONFIG_JSA1212) += jsa1212.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c new file mode 100644 index 000000000000..917dd8b43e72 --- /dev/null +++ b/drivers/iio/light/isl29018.c @@ -0,0 +1,847 @@ +/* + * A iio driver for the light sensor ISL 29018/29023/29035. + * + * IIO driver for monitoring ambient light intensity in luxi, proximity + * sensing and infrared sensing. + * + * Copyright (c) 2010, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ISL29018_CONV_TIME_MS 100 + +#define ISL29018_REG_ADD_COMMAND1 0x00 +#define ISL29018_CMD1_OPMODE_SHIFT 5 +#define ISL29018_CMD1_OPMODE_MASK (7 << ISL29018_CMD1_OPMODE_SHIFT) +#define ISL29018_CMD1_OPMODE_POWER_DOWN 0 +#define ISL29018_CMD1_OPMODE_ALS_ONCE 1 +#define ISL29018_CMD1_OPMODE_IR_ONCE 2 +#define ISL29018_CMD1_OPMODE_PROX_ONCE 3 + +#define ISL29018_REG_ADD_COMMAND2 0x01 +#define ISL29018_CMD2_RESOLUTION_SHIFT 2 +#define ISL29018_CMD2_RESOLUTION_MASK (0x3 << ISL29018_CMD2_RESOLUTION_SHIFT) + +#define ISL29018_CMD2_RANGE_SHIFT 0 +#define ISL29018_CMD2_RANGE_MASK (0x3 << ISL29018_CMD2_RANGE_SHIFT) + +#define ISL29018_CMD2_SCHEME_SHIFT 7 +#define ISL29018_CMD2_SCHEME_MASK (0x1 << ISL29018_CMD2_SCHEME_SHIFT) + +#define ISL29018_REG_ADD_DATA_LSB 0x02 +#define ISL29018_REG_ADD_DATA_MSB 0x03 + +#define ISL29018_REG_TEST 0x08 +#define ISL29018_TEST_SHIFT 0 +#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT) + +#define ISL29035_REG_DEVICE_ID 0x0F +#define ISL29035_DEVICE_ID_SHIFT 0x03 +#define ISL29035_DEVICE_ID_MASK (0x7 << ISL29035_DEVICE_ID_SHIFT) +#define ISL29035_DEVICE_ID 0x5 +#define ISL29035_BOUT_SHIFT 0x07 +#define ISL29035_BOUT_MASK (0x01 << ISL29035_BOUT_SHIFT) + +enum isl29018_int_time { + ISL29018_INT_TIME_16, + ISL29018_INT_TIME_12, + ISL29018_INT_TIME_8, + ISL29018_INT_TIME_4, +}; + +static const unsigned int isl29018_int_utimes[3][4] = { + {90000, 5630, 351, 21}, + {90000, 5600, 352, 22}, + {105000, 6500, 410, 25}, +}; + +static const struct isl29018_scale { + unsigned int scale; + unsigned int uscale; +} isl29018_scales[4][4] = { + { {0, 15258}, {0, 61035}, {0, 244140}, {0, 976562} }, + { {0, 244140}, {0, 976562}, {3, 906250}, {15, 625000} }, + { {3, 906250}, {15, 625000}, {62, 500000}, {250, 0} }, + { {62, 500000}, {250, 0}, {1000, 0}, {4000, 0} } +}; + +struct isl29018_chip { + struct regmap *regmap; + struct mutex lock; + int type; + unsigned int calibscale; + unsigned int ucalibscale; + unsigned int int_time; + struct isl29018_scale scale; + int prox_scheme; + bool suspended; +}; + +static int isl29018_set_integration_time(struct isl29018_chip *chip, + unsigned int utime) +{ + unsigned int i; + int ret; + unsigned int int_time, new_int_time; + + for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) { + if (utime == isl29018_int_utimes[chip->type][i]) { + new_int_time = i; + break; + } + } + + if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type])) + return -EINVAL; + + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_RESOLUTION_MASK, + i << ISL29018_CMD2_RESOLUTION_SHIFT); + if (ret < 0) + return ret; + + /* Keep the same range when integration time changes */ + int_time = chip->int_time; + for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) { + if (chip->scale.scale == isl29018_scales[int_time][i].scale && + chip->scale.uscale == isl29018_scales[int_time][i].uscale) { + chip->scale = isl29018_scales[new_int_time][i]; + break; + } + } + chip->int_time = new_int_time; + + return 0; +} + +static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale) +{ + unsigned int i; + int ret; + struct isl29018_scale new_scale; + + for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) { + if (scale == isl29018_scales[chip->int_time][i].scale && + uscale == isl29018_scales[chip->int_time][i].uscale) { + new_scale = isl29018_scales[chip->int_time][i]; + break; + } + } + + if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time])) + return -EINVAL; + + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_RANGE_MASK, + i << ISL29018_CMD2_RANGE_SHIFT); + if (ret < 0) + return ret; + + chip->scale = new_scale; + + return 0; +} + +static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) +{ + int status; + unsigned int lsb; + unsigned int msb; + struct device *dev = regmap_get_device(chip->regmap); + + /* Set mode */ + status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, + mode << ISL29018_CMD1_OPMODE_SHIFT); + if (status) { + dev_err(dev, + "Error in setting operating mode err %d\n", status); + return status; + } + msleep(ISL29018_CONV_TIME_MS); + status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb); + if (status < 0) { + dev_err(dev, + "Error in reading LSB DATA with err %d\n", status); + return status; + } + + status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb); + if (status < 0) { + dev_err(dev, + "Error in reading MSB DATA with error %d\n", status); + return status; + } + dev_vdbg(dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb); + + return (msb << 8) | lsb; +} + +static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) +{ + int lux_data; + unsigned int data_x_range; + + lux_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_ALS_ONCE); + if (lux_data < 0) + return lux_data; + + data_x_range = lux_data * chip->scale.scale + + lux_data * chip->scale.uscale / 1000000; + *lux = data_x_range * chip->calibscale + + data_x_range * chip->ucalibscale / 1000000; + + return 0; +} + +static int isl29018_read_ir(struct isl29018_chip *chip, int *ir) +{ + int ir_data; + + ir_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_IR_ONCE); + if (ir_data < 0) + return ir_data; + + *ir = ir_data; + + return 0; +} + +static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, + int *near_ir) +{ + int status; + int prox_data = -1; + int ir_data = -1; + struct device *dev = regmap_get_device(chip->regmap); + + /* Do proximity sensing with required scheme */ + status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_SCHEME_MASK, + scheme << ISL29018_CMD2_SCHEME_SHIFT); + if (status) { + dev_err(dev, "Error in setting operating mode\n"); + return status; + } + + prox_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_PROX_ONCE); + if (prox_data < 0) + return prox_data; + + if (scheme == 1) { + *near_ir = prox_data; + return 0; + } + + ir_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_IR_ONCE); + if (ir_data < 0) + return ir_data; + + if (prox_data >= ir_data) + *near_ir = prox_data - ir_data; + else + *near_ir = 0; + + return 0; +} + +static ssize_t in_illuminance_scale_available_show + (struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct isl29018_chip *chip = iio_priv(indio_dev); + unsigned int i; + int len = 0; + + mutex_lock(&chip->lock); + for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) + len += sprintf(buf + len, "%d.%06d ", + isl29018_scales[chip->int_time][i].scale, + isl29018_scales[chip->int_time][i].uscale); + mutex_unlock(&chip->lock); + + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t in_illuminance_integration_time_available_show + (struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct isl29018_chip *chip = iio_priv(indio_dev); + unsigned int i; + int len = 0; + + for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) + len += sprintf(buf + len, "0.%06d ", + isl29018_int_utimes[chip->type][i]); + + buf[len - 1] = '\n'; + + return len; +} + +/* + * From ISL29018 Data Sheet (FN6619.4, Oct 8, 2012) regarding the + * infrared suppression: + * + * Proximity Sensing Scheme: Bit 7. This bit programs the function + * of the proximity detection. Logic 0 of this bit, Scheme 0, makes + * full n (4, 8, 12, 16) bits (unsigned) proximity detection. The range + * of Scheme 0 proximity count is from 0 to 2^n. Logic 1 of this bit, + * Scheme 1, makes n-1 (3, 7, 11, 15) bits (2's complementary) + * proximity_less_ambient detection. The range of Scheme 1 + * proximity count is from -2^(n-1) to 2^(n-1) . The sign bit is extended + * for resolutions less than 16. While Scheme 0 has wider dynamic + * range, Scheme 1 proximity detection is less affected by the + * ambient IR noise variation. + * + * 0 Sensing IR from LED and ambient + * 1 Sensing IR from LED with ambient IR rejection + */ +static ssize_t proximity_on_chip_ambient_infrared_suppression_show + (struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct isl29018_chip *chip = iio_priv(indio_dev); + + /* + * Return the "proximity scheme" i.e. if the chip does on chip + * infrared suppression (1 means perform on chip suppression) + */ + return sprintf(buf, "%d\n", chip->prox_scheme); +} + +static ssize_t proximity_on_chip_ambient_infrared_suppression_store + (struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct isl29018_chip *chip = iio_priv(indio_dev); + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + if (!(val == 0 || val == 1)) + return -EINVAL; + + /* + * Get the "proximity scheme" i.e. if the chip does on chip + * infrared suppression (1 means perform on chip suppression) + */ + mutex_lock(&chip->lock); + chip->prox_scheme = val; + mutex_unlock(&chip->lock); + + return count; +} + +static int isl29018_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct isl29018_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(&chip->lock); + if (chip->suspended) { + ret = -EBUSY; + goto write_done; + } + switch (mask) { + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_LIGHT) { + chip->calibscale = val; + chip->ucalibscale = val2; + ret = 0; + } + break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type == IIO_LIGHT && !val) + ret = isl29018_set_integration_time(chip, val2); + break; + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_LIGHT) + ret = isl29018_set_scale(chip, val, val2); + break; + default: + break; + } + +write_done: + mutex_unlock(&chip->lock); + + return ret; +} + +static int isl29018_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret = -EINVAL; + struct isl29018_chip *chip = iio_priv(indio_dev); + + mutex_lock(&chip->lock); + if (chip->suspended) { + ret = -EBUSY; + goto read_done; + } + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_LIGHT: + ret = isl29018_read_lux(chip, val); + break; + case IIO_INTENSITY: + ret = isl29018_read_ir(chip, val); + break; + case IIO_PROXIMITY: + ret = isl29018_read_proximity_ir(chip, + chip->prox_scheme, + val); + break; + default: + break; + } + if (!ret) + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type == IIO_LIGHT) { + *val = 0; + *val2 = isl29018_int_utimes[chip->type][chip->int_time]; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_LIGHT) { + *val = chip->scale.scale; + *val2 = chip->scale.uscale; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_LIGHT) { + *val = chip->calibscale; + *val2 = chip->ucalibscale; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; + default: + break; + } + +read_done: + mutex_unlock(&chip->lock); + + return ret; +} + +#define ISL29018_LIGHT_CHANNEL { \ + .type = IIO_LIGHT, \ + .indexed = 1, \ + .channel = 0, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | \ + BIT(IIO_CHAN_INFO_CALIBSCALE) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ +} + +#define ISL29018_IR_CHANNEL { \ + .type = IIO_INTENSITY, \ + .modified = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .channel2 = IIO_MOD_LIGHT_IR, \ +} + +#define ISL29018_PROXIMITY_CHANNEL { \ + .type = IIO_PROXIMITY, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +} + +static const struct iio_chan_spec isl29018_channels[] = { + ISL29018_LIGHT_CHANNEL, + ISL29018_IR_CHANNEL, + ISL29018_PROXIMITY_CHANNEL, +}; + +static const struct iio_chan_spec isl29023_channels[] = { + ISL29018_LIGHT_CHANNEL, + ISL29018_IR_CHANNEL, +}; + +static IIO_DEVICE_ATTR_RO(in_illuminance_integration_time_available, 0); +static IIO_DEVICE_ATTR_RO(in_illuminance_scale_available, 0); +static IIO_DEVICE_ATTR_RW(proximity_on_chip_ambient_infrared_suppression, 0); + +#define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) + +static struct attribute *isl29018_attributes[] = { + ISL29018_DEV_ATTR(in_illuminance_scale_available), + ISL29018_DEV_ATTR(in_illuminance_integration_time_available), + ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression), + NULL +}; + +static struct attribute *isl29023_attributes[] = { + ISL29018_DEV_ATTR(in_illuminance_scale_available), + ISL29018_DEV_ATTR(in_illuminance_integration_time_available), + NULL +}; + +static const struct attribute_group isl29018_group = { + .attrs = isl29018_attributes, +}; + +static const struct attribute_group isl29023_group = { + .attrs = isl29023_attributes, +}; + +enum { + isl29018, + isl29023, + isl29035, +}; + +static int isl29018_chip_init(struct isl29018_chip *chip) +{ + int status; + struct device *dev = regmap_get_device(chip->regmap); + + if (chip->type == isl29035) { + unsigned int id; + + status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id); + if (status < 0) { + dev_err(dev, + "Error reading ID register with error %d\n", + status); + return status; + } + + id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT; + + if (id != ISL29035_DEVICE_ID) + return -ENODEV; + + /* Clear brownout bit */ + status = regmap_update_bits(chip->regmap, + ISL29035_REG_DEVICE_ID, + ISL29035_BOUT_MASK, 0); + if (status < 0) + return status; + } + + /* + * Code added per Intersil Application Note 1534: + * When VDD sinks to approximately 1.8V or below, some of + * the part's registers may change their state. When VDD + * recovers to 2.25V (or greater), the part may thus be in an + * unknown mode of operation. The user can return the part to + * a known mode of operation either by (a) setting VDD = 0V for + * 1 second or more and then powering back up with a slew rate + * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX + * conversions, clear the test registers, and then rewrite all + * registers to the desired values. + * ... + * For ISL29011, ISL29018, ISL29021, ISL29023 + * 1. Write 0x00 to register 0x08 (TEST) + * 2. Write 0x00 to register 0x00 (CMD1) + * 3. Rewrite all registers to the desired values + * + * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says + * the same thing EXCEPT the data sheet asks for a 1ms delay after + * writing the CMD1 register. + */ + status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0); + if (status < 0) { + dev_err(dev, "Failed to clear isl29018 TEST reg.(%d)\n", + status); + return status; + } + + /* + * See Intersil AN1534 comments above. + * "Operating Mode" (COMMAND1) register is reprogrammed when + * data is read from the device. + */ + status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0); + if (status < 0) { + dev_err(dev, "Failed to clear isl29018 CMD1 reg.(%d)\n", + status); + return status; + } + + usleep_range(1000, 2000); /* per data sheet, page 10 */ + + /* Set defaults */ + status = isl29018_set_scale(chip, chip->scale.scale, + chip->scale.uscale); + if (status < 0) { + dev_err(dev, "Init of isl29018 fails\n"); + return status; + } + + status = isl29018_set_integration_time(chip, + isl29018_int_utimes[chip->type][chip->int_time]); + if (status < 0) + dev_err(dev, "Init of isl29018 fails\n"); + + return status; +} + +static const struct iio_info isl29018_info = { + .attrs = &isl29018_group, + .driver_module = THIS_MODULE, + .read_raw = isl29018_read_raw, + .write_raw = isl29018_write_raw, +}; + +static const struct iio_info isl29023_info = { + .attrs = &isl29023_group, + .driver_module = THIS_MODULE, + .read_raw = isl29018_read_raw, + .write_raw = isl29018_write_raw, +}; + +static bool isl29018_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ISL29018_REG_ADD_DATA_LSB: + case ISL29018_REG_ADD_DATA_MSB: + case ISL29018_REG_ADD_COMMAND1: + case ISL29018_REG_TEST: + case ISL29035_REG_DEVICE_ID: + return true; + default: + return false; + } +} + +static const struct regmap_config isl29018_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .volatile_reg = isl29018_is_volatile_reg, + .max_register = ISL29018_REG_TEST, + .num_reg_defaults_raw = ISL29018_REG_TEST + 1, + .cache_type = REGCACHE_RBTREE, +}; + +static const struct regmap_config isl29035_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .volatile_reg = isl29018_is_volatile_reg, + .max_register = ISL29035_REG_DEVICE_ID, + .num_reg_defaults_raw = ISL29035_REG_DEVICE_ID + 1, + .cache_type = REGCACHE_RBTREE, +}; + +struct isl29018_chip_info { + const struct iio_chan_spec *channels; + int num_channels; + const struct iio_info *indio_info; + const struct regmap_config *regmap_cfg; +}; + +static const struct isl29018_chip_info isl29018_chip_info_tbl[] = { + [isl29018] = { + .channels = isl29018_channels, + .num_channels = ARRAY_SIZE(isl29018_channels), + .indio_info = &isl29018_info, + .regmap_cfg = &isl29018_regmap_config, + }, + [isl29023] = { + .channels = isl29023_channels, + .num_channels = ARRAY_SIZE(isl29023_channels), + .indio_info = &isl29023_info, + .regmap_cfg = &isl29018_regmap_config, + }, + [isl29035] = { + .channels = isl29023_channels, + .num_channels = ARRAY_SIZE(isl29023_channels), + .indio_info = &isl29023_info, + .regmap_cfg = &isl29035_regmap_config, + }, +}; + +static const char *isl29018_match_acpi_device(struct device *dev, int *data) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + + if (!id) + return NULL; + + *data = (int)id->driver_data; + + return dev_name(dev); +} + +static int isl29018_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct isl29018_chip *chip; + struct iio_dev *indio_dev; + int err; + const char *name = NULL; + int dev_id = 0; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; + + chip = iio_priv(indio_dev); + + i2c_set_clientdata(client, indio_dev); + + if (id) { + name = id->name; + dev_id = id->driver_data; + } + + if (ACPI_HANDLE(&client->dev)) + name = isl29018_match_acpi_device(&client->dev, &dev_id); + + mutex_init(&chip->lock); + + chip->type = dev_id; + chip->calibscale = 1; + chip->ucalibscale = 0; + chip->int_time = ISL29018_INT_TIME_16; + chip->scale = isl29018_scales[chip->int_time][0]; + chip->suspended = false; + + chip->regmap = devm_regmap_init_i2c(client, + isl29018_chip_info_tbl[dev_id].regmap_cfg); + if (IS_ERR(chip->regmap)) { + err = PTR_ERR(chip->regmap); + dev_err(&client->dev, "regmap initialization fails: %d\n", err); + return err; + } + + err = isl29018_chip_init(chip); + if (err) + return err; + + indio_dev->info = isl29018_chip_info_tbl[dev_id].indio_info; + indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels; + indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels; + indio_dev->name = name; + indio_dev->dev.parent = &client->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +#ifdef CONFIG_PM_SLEEP +static int isl29018_suspend(struct device *dev) +{ + struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev)); + + mutex_lock(&chip->lock); + + /* + * Since this driver uses only polling commands, we are by default in + * auto shutdown (ie, power-down) mode. + * So we do not have much to do here. + */ + chip->suspended = true; + + mutex_unlock(&chip->lock); + + return 0; +} + +static int isl29018_resume(struct device *dev) +{ + struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev)); + int err; + + mutex_lock(&chip->lock); + + err = isl29018_chip_init(chip); + if (!err) + chip->suspended = false; + + mutex_unlock(&chip->lock); + + return err; +} + +static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume); +#define ISL29018_PM_OPS (&isl29018_pm_ops) +#else +#define ISL29018_PM_OPS NULL +#endif + +static const struct acpi_device_id isl29018_acpi_match[] = { + {"ISL29018", isl29018}, + {"ISL29023", isl29023}, + {"ISL29035", isl29035}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match); + +static const struct i2c_device_id isl29018_id[] = { + {"isl29018", isl29018}, + {"isl29023", isl29023}, + {"isl29035", isl29035}, + {} +}; +MODULE_DEVICE_TABLE(i2c, isl29018_id); + +static const struct of_device_id isl29018_of_match[] = { + { .compatible = "isil,isl29018", }, + { .compatible = "isil,isl29023", }, + { .compatible = "isil,isl29035", }, + { }, +}; +MODULE_DEVICE_TABLE(of, isl29018_of_match); + +static struct i2c_driver isl29018_driver = { + .driver = { + .name = "isl29018", + .acpi_match_table = ACPI_PTR(isl29018_acpi_match), + .pm = ISL29018_PM_OPS, + .of_match_table = isl29018_of_match, + }, + .probe = isl29018_probe, + .id_table = isl29018_id, +}; +module_i2c_driver(isl29018_driver); + +MODULE_DESCRIPTION("ISL29018 Ambient Light Sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig index 5e4e77ef7f98..dbf22d396ddf 100644 --- a/drivers/staging/iio/light/Kconfig +++ b/drivers/staging/iio/light/Kconfig @@ -3,18 +3,6 @@ # menu "Light sensors" -config SENSORS_ISL29018 - tristate "Intersil 29018 light and proximity sensor" - depends on I2C - select REGMAP_I2C - default n - help - If you say yes here you get support for ambient light sensing and - proximity infrared sensing from Intersil ISL29018. - This driver will provide the measurements of ambient light intensity - in lux, proximity infrared sensing and normal infrared sensing. - Data from sensor is accessible via sysfs. - config SENSORS_ISL29028 tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor" depends on I2C diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile index 9960fdf7c15b..6480856e1682 100644 --- a/drivers/staging/iio/light/Makefile +++ b/drivers/staging/iio/light/Makefile @@ -2,7 +2,6 @@ # Makefile for industrial I/O Light sensors # -obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o obj-$(CONFIG_TSL2583) += tsl2583.o obj-$(CONFIG_TSL2x7x) += tsl2x7x_core.o diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c deleted file mode 100644 index 917dd8b43e72..000000000000 --- a/drivers/staging/iio/light/isl29018.c +++ /dev/null @@ -1,847 +0,0 @@ -/* - * A iio driver for the light sensor ISL 29018/29023/29035. - * - * IIO driver for monitoring ambient light intensity in luxi, proximity - * sensing and infrared sensing. - * - * Copyright (c) 2010, NVIDIA Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ISL29018_CONV_TIME_MS 100 - -#define ISL29018_REG_ADD_COMMAND1 0x00 -#define ISL29018_CMD1_OPMODE_SHIFT 5 -#define ISL29018_CMD1_OPMODE_MASK (7 << ISL29018_CMD1_OPMODE_SHIFT) -#define ISL29018_CMD1_OPMODE_POWER_DOWN 0 -#define ISL29018_CMD1_OPMODE_ALS_ONCE 1 -#define ISL29018_CMD1_OPMODE_IR_ONCE 2 -#define ISL29018_CMD1_OPMODE_PROX_ONCE 3 - -#define ISL29018_REG_ADD_COMMAND2 0x01 -#define ISL29018_CMD2_RESOLUTION_SHIFT 2 -#define ISL29018_CMD2_RESOLUTION_MASK (0x3 << ISL29018_CMD2_RESOLUTION_SHIFT) - -#define ISL29018_CMD2_RANGE_SHIFT 0 -#define ISL29018_CMD2_RANGE_MASK (0x3 << ISL29018_CMD2_RANGE_SHIFT) - -#define ISL29018_CMD2_SCHEME_SHIFT 7 -#define ISL29018_CMD2_SCHEME_MASK (0x1 << ISL29018_CMD2_SCHEME_SHIFT) - -#define ISL29018_REG_ADD_DATA_LSB 0x02 -#define ISL29018_REG_ADD_DATA_MSB 0x03 - -#define ISL29018_REG_TEST 0x08 -#define ISL29018_TEST_SHIFT 0 -#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT) - -#define ISL29035_REG_DEVICE_ID 0x0F -#define ISL29035_DEVICE_ID_SHIFT 0x03 -#define ISL29035_DEVICE_ID_MASK (0x7 << ISL29035_DEVICE_ID_SHIFT) -#define ISL29035_DEVICE_ID 0x5 -#define ISL29035_BOUT_SHIFT 0x07 -#define ISL29035_BOUT_MASK (0x01 << ISL29035_BOUT_SHIFT) - -enum isl29018_int_time { - ISL29018_INT_TIME_16, - ISL29018_INT_TIME_12, - ISL29018_INT_TIME_8, - ISL29018_INT_TIME_4, -}; - -static const unsigned int isl29018_int_utimes[3][4] = { - {90000, 5630, 351, 21}, - {90000, 5600, 352, 22}, - {105000, 6500, 410, 25}, -}; - -static const struct isl29018_scale { - unsigned int scale; - unsigned int uscale; -} isl29018_scales[4][4] = { - { {0, 15258}, {0, 61035}, {0, 244140}, {0, 976562} }, - { {0, 244140}, {0, 976562}, {3, 906250}, {15, 625000} }, - { {3, 906250}, {15, 625000}, {62, 500000}, {250, 0} }, - { {62, 500000}, {250, 0}, {1000, 0}, {4000, 0} } -}; - -struct isl29018_chip { - struct regmap *regmap; - struct mutex lock; - int type; - unsigned int calibscale; - unsigned int ucalibscale; - unsigned int int_time; - struct isl29018_scale scale; - int prox_scheme; - bool suspended; -}; - -static int isl29018_set_integration_time(struct isl29018_chip *chip, - unsigned int utime) -{ - unsigned int i; - int ret; - unsigned int int_time, new_int_time; - - for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) { - if (utime == isl29018_int_utimes[chip->type][i]) { - new_int_time = i; - break; - } - } - - if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type])) - return -EINVAL; - - ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, - ISL29018_CMD2_RESOLUTION_MASK, - i << ISL29018_CMD2_RESOLUTION_SHIFT); - if (ret < 0) - return ret; - - /* Keep the same range when integration time changes */ - int_time = chip->int_time; - for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) { - if (chip->scale.scale == isl29018_scales[int_time][i].scale && - chip->scale.uscale == isl29018_scales[int_time][i].uscale) { - chip->scale = isl29018_scales[new_int_time][i]; - break; - } - } - chip->int_time = new_int_time; - - return 0; -} - -static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale) -{ - unsigned int i; - int ret; - struct isl29018_scale new_scale; - - for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) { - if (scale == isl29018_scales[chip->int_time][i].scale && - uscale == isl29018_scales[chip->int_time][i].uscale) { - new_scale = isl29018_scales[chip->int_time][i]; - break; - } - } - - if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time])) - return -EINVAL; - - ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, - ISL29018_CMD2_RANGE_MASK, - i << ISL29018_CMD2_RANGE_SHIFT); - if (ret < 0) - return ret; - - chip->scale = new_scale; - - return 0; -} - -static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) -{ - int status; - unsigned int lsb; - unsigned int msb; - struct device *dev = regmap_get_device(chip->regmap); - - /* Set mode */ - status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, - mode << ISL29018_CMD1_OPMODE_SHIFT); - if (status) { - dev_err(dev, - "Error in setting operating mode err %d\n", status); - return status; - } - msleep(ISL29018_CONV_TIME_MS); - status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb); - if (status < 0) { - dev_err(dev, - "Error in reading LSB DATA with err %d\n", status); - return status; - } - - status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb); - if (status < 0) { - dev_err(dev, - "Error in reading MSB DATA with error %d\n", status); - return status; - } - dev_vdbg(dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb); - - return (msb << 8) | lsb; -} - -static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) -{ - int lux_data; - unsigned int data_x_range; - - lux_data = isl29018_read_sensor_input(chip, - ISL29018_CMD1_OPMODE_ALS_ONCE); - if (lux_data < 0) - return lux_data; - - data_x_range = lux_data * chip->scale.scale + - lux_data * chip->scale.uscale / 1000000; - *lux = data_x_range * chip->calibscale + - data_x_range * chip->ucalibscale / 1000000; - - return 0; -} - -static int isl29018_read_ir(struct isl29018_chip *chip, int *ir) -{ - int ir_data; - - ir_data = isl29018_read_sensor_input(chip, - ISL29018_CMD1_OPMODE_IR_ONCE); - if (ir_data < 0) - return ir_data; - - *ir = ir_data; - - return 0; -} - -static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, - int *near_ir) -{ - int status; - int prox_data = -1; - int ir_data = -1; - struct device *dev = regmap_get_device(chip->regmap); - - /* Do proximity sensing with required scheme */ - status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, - ISL29018_CMD2_SCHEME_MASK, - scheme << ISL29018_CMD2_SCHEME_SHIFT); - if (status) { - dev_err(dev, "Error in setting operating mode\n"); - return status; - } - - prox_data = isl29018_read_sensor_input(chip, - ISL29018_CMD1_OPMODE_PROX_ONCE); - if (prox_data < 0) - return prox_data; - - if (scheme == 1) { - *near_ir = prox_data; - return 0; - } - - ir_data = isl29018_read_sensor_input(chip, - ISL29018_CMD1_OPMODE_IR_ONCE); - if (ir_data < 0) - return ir_data; - - if (prox_data >= ir_data) - *near_ir = prox_data - ir_data; - else - *near_ir = 0; - - return 0; -} - -static ssize_t in_illuminance_scale_available_show - (struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - unsigned int i; - int len = 0; - - mutex_lock(&chip->lock); - for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) - len += sprintf(buf + len, "%d.%06d ", - isl29018_scales[chip->int_time][i].scale, - isl29018_scales[chip->int_time][i].uscale); - mutex_unlock(&chip->lock); - - buf[len - 1] = '\n'; - - return len; -} - -static ssize_t in_illuminance_integration_time_available_show - (struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - unsigned int i; - int len = 0; - - for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) - len += sprintf(buf + len, "0.%06d ", - isl29018_int_utimes[chip->type][i]); - - buf[len - 1] = '\n'; - - return len; -} - -/* - * From ISL29018 Data Sheet (FN6619.4, Oct 8, 2012) regarding the - * infrared suppression: - * - * Proximity Sensing Scheme: Bit 7. This bit programs the function - * of the proximity detection. Logic 0 of this bit, Scheme 0, makes - * full n (4, 8, 12, 16) bits (unsigned) proximity detection. The range - * of Scheme 0 proximity count is from 0 to 2^n. Logic 1 of this bit, - * Scheme 1, makes n-1 (3, 7, 11, 15) bits (2's complementary) - * proximity_less_ambient detection. The range of Scheme 1 - * proximity count is from -2^(n-1) to 2^(n-1) . The sign bit is extended - * for resolutions less than 16. While Scheme 0 has wider dynamic - * range, Scheme 1 proximity detection is less affected by the - * ambient IR noise variation. - * - * 0 Sensing IR from LED and ambient - * 1 Sensing IR from LED with ambient IR rejection - */ -static ssize_t proximity_on_chip_ambient_infrared_suppression_show - (struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - - /* - * Return the "proximity scheme" i.e. if the chip does on chip - * infrared suppression (1 means perform on chip suppression) - */ - return sprintf(buf, "%d\n", chip->prox_scheme); -} - -static ssize_t proximity_on_chip_ambient_infrared_suppression_store - (struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - int val; - - if (kstrtoint(buf, 10, &val)) - return -EINVAL; - if (!(val == 0 || val == 1)) - return -EINVAL; - - /* - * Get the "proximity scheme" i.e. if the chip does on chip - * infrared suppression (1 means perform on chip suppression) - */ - mutex_lock(&chip->lock); - chip->prox_scheme = val; - mutex_unlock(&chip->lock); - - return count; -} - -static int isl29018_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct isl29018_chip *chip = iio_priv(indio_dev); - int ret = -EINVAL; - - mutex_lock(&chip->lock); - if (chip->suspended) { - ret = -EBUSY; - goto write_done; - } - switch (mask) { - case IIO_CHAN_INFO_CALIBSCALE: - if (chan->type == IIO_LIGHT) { - chip->calibscale = val; - chip->ucalibscale = val2; - ret = 0; - } - break; - case IIO_CHAN_INFO_INT_TIME: - if (chan->type == IIO_LIGHT && !val) - ret = isl29018_set_integration_time(chip, val2); - break; - case IIO_CHAN_INFO_SCALE: - if (chan->type == IIO_LIGHT) - ret = isl29018_set_scale(chip, val, val2); - break; - default: - break; - } - -write_done: - mutex_unlock(&chip->lock); - - return ret; -} - -static int isl29018_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - int ret = -EINVAL; - struct isl29018_chip *chip = iio_priv(indio_dev); - - mutex_lock(&chip->lock); - if (chip->suspended) { - ret = -EBUSY; - goto read_done; - } - switch (mask) { - case IIO_CHAN_INFO_RAW: - case IIO_CHAN_INFO_PROCESSED: - switch (chan->type) { - case IIO_LIGHT: - ret = isl29018_read_lux(chip, val); - break; - case IIO_INTENSITY: - ret = isl29018_read_ir(chip, val); - break; - case IIO_PROXIMITY: - ret = isl29018_read_proximity_ir(chip, - chip->prox_scheme, - val); - break; - default: - break; - } - if (!ret) - ret = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_INT_TIME: - if (chan->type == IIO_LIGHT) { - *val = 0; - *val2 = isl29018_int_utimes[chip->type][chip->int_time]; - ret = IIO_VAL_INT_PLUS_MICRO; - } - break; - case IIO_CHAN_INFO_SCALE: - if (chan->type == IIO_LIGHT) { - *val = chip->scale.scale; - *val2 = chip->scale.uscale; - ret = IIO_VAL_INT_PLUS_MICRO; - } - break; - case IIO_CHAN_INFO_CALIBSCALE: - if (chan->type == IIO_LIGHT) { - *val = chip->calibscale; - *val2 = chip->ucalibscale; - ret = IIO_VAL_INT_PLUS_MICRO; - } - break; - default: - break; - } - -read_done: - mutex_unlock(&chip->lock); - - return ret; -} - -#define ISL29018_LIGHT_CHANNEL { \ - .type = IIO_LIGHT, \ - .indexed = 1, \ - .channel = 0, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | \ - BIT(IIO_CHAN_INFO_CALIBSCALE) | \ - BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_INT_TIME), \ -} - -#define ISL29018_IR_CHANNEL { \ - .type = IIO_INTENSITY, \ - .modified = 1, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .channel2 = IIO_MOD_LIGHT_IR, \ -} - -#define ISL29018_PROXIMITY_CHANNEL { \ - .type = IIO_PROXIMITY, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ -} - -static const struct iio_chan_spec isl29018_channels[] = { - ISL29018_LIGHT_CHANNEL, - ISL29018_IR_CHANNEL, - ISL29018_PROXIMITY_CHANNEL, -}; - -static const struct iio_chan_spec isl29023_channels[] = { - ISL29018_LIGHT_CHANNEL, - ISL29018_IR_CHANNEL, -}; - -static IIO_DEVICE_ATTR_RO(in_illuminance_integration_time_available, 0); -static IIO_DEVICE_ATTR_RO(in_illuminance_scale_available, 0); -static IIO_DEVICE_ATTR_RW(proximity_on_chip_ambient_infrared_suppression, 0); - -#define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) - -static struct attribute *isl29018_attributes[] = { - ISL29018_DEV_ATTR(in_illuminance_scale_available), - ISL29018_DEV_ATTR(in_illuminance_integration_time_available), - ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression), - NULL -}; - -static struct attribute *isl29023_attributes[] = { - ISL29018_DEV_ATTR(in_illuminance_scale_available), - ISL29018_DEV_ATTR(in_illuminance_integration_time_available), - NULL -}; - -static const struct attribute_group isl29018_group = { - .attrs = isl29018_attributes, -}; - -static const struct attribute_group isl29023_group = { - .attrs = isl29023_attributes, -}; - -enum { - isl29018, - isl29023, - isl29035, -}; - -static int isl29018_chip_init(struct isl29018_chip *chip) -{ - int status; - struct device *dev = regmap_get_device(chip->regmap); - - if (chip->type == isl29035) { - unsigned int id; - - status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id); - if (status < 0) { - dev_err(dev, - "Error reading ID register with error %d\n", - status); - return status; - } - - id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT; - - if (id != ISL29035_DEVICE_ID) - return -ENODEV; - - /* Clear brownout bit */ - status = regmap_update_bits(chip->regmap, - ISL29035_REG_DEVICE_ID, - ISL29035_BOUT_MASK, 0); - if (status < 0) - return status; - } - - /* - * Code added per Intersil Application Note 1534: - * When VDD sinks to approximately 1.8V or below, some of - * the part's registers may change their state. When VDD - * recovers to 2.25V (or greater), the part may thus be in an - * unknown mode of operation. The user can return the part to - * a known mode of operation either by (a) setting VDD = 0V for - * 1 second or more and then powering back up with a slew rate - * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX - * conversions, clear the test registers, and then rewrite all - * registers to the desired values. - * ... - * For ISL29011, ISL29018, ISL29021, ISL29023 - * 1. Write 0x00 to register 0x08 (TEST) - * 2. Write 0x00 to register 0x00 (CMD1) - * 3. Rewrite all registers to the desired values - * - * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says - * the same thing EXCEPT the data sheet asks for a 1ms delay after - * writing the CMD1 register. - */ - status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0); - if (status < 0) { - dev_err(dev, "Failed to clear isl29018 TEST reg.(%d)\n", - status); - return status; - } - - /* - * See Intersil AN1534 comments above. - * "Operating Mode" (COMMAND1) register is reprogrammed when - * data is read from the device. - */ - status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0); - if (status < 0) { - dev_err(dev, "Failed to clear isl29018 CMD1 reg.(%d)\n", - status); - return status; - } - - usleep_range(1000, 2000); /* per data sheet, page 10 */ - - /* Set defaults */ - status = isl29018_set_scale(chip, chip->scale.scale, - chip->scale.uscale); - if (status < 0) { - dev_err(dev, "Init of isl29018 fails\n"); - return status; - } - - status = isl29018_set_integration_time(chip, - isl29018_int_utimes[chip->type][chip->int_time]); - if (status < 0) - dev_err(dev, "Init of isl29018 fails\n"); - - return status; -} - -static const struct iio_info isl29018_info = { - .attrs = &isl29018_group, - .driver_module = THIS_MODULE, - .read_raw = isl29018_read_raw, - .write_raw = isl29018_write_raw, -}; - -static const struct iio_info isl29023_info = { - .attrs = &isl29023_group, - .driver_module = THIS_MODULE, - .read_raw = isl29018_read_raw, - .write_raw = isl29018_write_raw, -}; - -static bool isl29018_is_volatile_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case ISL29018_REG_ADD_DATA_LSB: - case ISL29018_REG_ADD_DATA_MSB: - case ISL29018_REG_ADD_COMMAND1: - case ISL29018_REG_TEST: - case ISL29035_REG_DEVICE_ID: - return true; - default: - return false; - } -} - -static const struct regmap_config isl29018_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .volatile_reg = isl29018_is_volatile_reg, - .max_register = ISL29018_REG_TEST, - .num_reg_defaults_raw = ISL29018_REG_TEST + 1, - .cache_type = REGCACHE_RBTREE, -}; - -static const struct regmap_config isl29035_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .volatile_reg = isl29018_is_volatile_reg, - .max_register = ISL29035_REG_DEVICE_ID, - .num_reg_defaults_raw = ISL29035_REG_DEVICE_ID + 1, - .cache_type = REGCACHE_RBTREE, -}; - -struct isl29018_chip_info { - const struct iio_chan_spec *channels; - int num_channels; - const struct iio_info *indio_info; - const struct regmap_config *regmap_cfg; -}; - -static const struct isl29018_chip_info isl29018_chip_info_tbl[] = { - [isl29018] = { - .channels = isl29018_channels, - .num_channels = ARRAY_SIZE(isl29018_channels), - .indio_info = &isl29018_info, - .regmap_cfg = &isl29018_regmap_config, - }, - [isl29023] = { - .channels = isl29023_channels, - .num_channels = ARRAY_SIZE(isl29023_channels), - .indio_info = &isl29023_info, - .regmap_cfg = &isl29018_regmap_config, - }, - [isl29035] = { - .channels = isl29023_channels, - .num_channels = ARRAY_SIZE(isl29023_channels), - .indio_info = &isl29023_info, - .regmap_cfg = &isl29035_regmap_config, - }, -}; - -static const char *isl29018_match_acpi_device(struct device *dev, int *data) -{ - const struct acpi_device_id *id; - - id = acpi_match_device(dev->driver->acpi_match_table, dev); - - if (!id) - return NULL; - - *data = (int)id->driver_data; - - return dev_name(dev); -} - -static int isl29018_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct isl29018_chip *chip; - struct iio_dev *indio_dev; - int err; - const char *name = NULL; - int dev_id = 0; - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); - if (!indio_dev) - return -ENOMEM; - - chip = iio_priv(indio_dev); - - i2c_set_clientdata(client, indio_dev); - - if (id) { - name = id->name; - dev_id = id->driver_data; - } - - if (ACPI_HANDLE(&client->dev)) - name = isl29018_match_acpi_device(&client->dev, &dev_id); - - mutex_init(&chip->lock); - - chip->type = dev_id; - chip->calibscale = 1; - chip->ucalibscale = 0; - chip->int_time = ISL29018_INT_TIME_16; - chip->scale = isl29018_scales[chip->int_time][0]; - chip->suspended = false; - - chip->regmap = devm_regmap_init_i2c(client, - isl29018_chip_info_tbl[dev_id].regmap_cfg); - if (IS_ERR(chip->regmap)) { - err = PTR_ERR(chip->regmap); - dev_err(&client->dev, "regmap initialization fails: %d\n", err); - return err; - } - - err = isl29018_chip_init(chip); - if (err) - return err; - - indio_dev->info = isl29018_chip_info_tbl[dev_id].indio_info; - indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels; - indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels; - indio_dev->name = name; - indio_dev->dev.parent = &client->dev; - indio_dev->modes = INDIO_DIRECT_MODE; - - return devm_iio_device_register(&client->dev, indio_dev); -} - -#ifdef CONFIG_PM_SLEEP -static int isl29018_suspend(struct device *dev) -{ - struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev)); - - mutex_lock(&chip->lock); - - /* - * Since this driver uses only polling commands, we are by default in - * auto shutdown (ie, power-down) mode. - * So we do not have much to do here. - */ - chip->suspended = true; - - mutex_unlock(&chip->lock); - - return 0; -} - -static int isl29018_resume(struct device *dev) -{ - struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev)); - int err; - - mutex_lock(&chip->lock); - - err = isl29018_chip_init(chip); - if (!err) - chip->suspended = false; - - mutex_unlock(&chip->lock); - - return err; -} - -static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume); -#define ISL29018_PM_OPS (&isl29018_pm_ops) -#else -#define ISL29018_PM_OPS NULL -#endif - -static const struct acpi_device_id isl29018_acpi_match[] = { - {"ISL29018", isl29018}, - {"ISL29023", isl29023}, - {"ISL29035", isl29035}, - {}, -}; -MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match); - -static const struct i2c_device_id isl29018_id[] = { - {"isl29018", isl29018}, - {"isl29023", isl29023}, - {"isl29035", isl29035}, - {} -}; -MODULE_DEVICE_TABLE(i2c, isl29018_id); - -static const struct of_device_id isl29018_of_match[] = { - { .compatible = "isil,isl29018", }, - { .compatible = "isil,isl29023", }, - { .compatible = "isil,isl29035", }, - { }, -}; -MODULE_DEVICE_TABLE(of, isl29018_of_match); - -static struct i2c_driver isl29018_driver = { - .driver = { - .name = "isl29018", - .acpi_match_table = ACPI_PTR(isl29018_acpi_match), - .pm = ISL29018_PM_OPS, - .of_match_table = isl29018_of_match, - }, - .probe = isl29018_probe, - .id_table = isl29018_id, -}; -module_i2c_driver(isl29018_driver); - -MODULE_DESCRIPTION("ISL29018 Ambient Light Sensor driver"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e3ef7532a3d2aabec6aaff0b72db42a6ebf03ab6 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:01 +0100 Subject: staging:iio:accel:sca3000 Fix a use before setting of the indio_dev->buffer pointer. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index d1cb9b9cf22b..e5de52d05a5c 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -270,8 +270,8 @@ int sca3000_configure_ring(struct iio_dev *indio_dev) return -ENOMEM; indio_dev->modes |= INDIO_BUFFER_HARDWARE; - indio_dev->buffer->access = &sca3000_ring_access_funcs; + buffer->access = &sca3000_ring_access_funcs; iio_device_attach_buffer(indio_dev, buffer); return 0; -- cgit v1.2.3 From ced5c03d360aeebaac6faa7dd8d6d0a77733ab16 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:02 +0100 Subject: staging:iio:accel:sca3000 merge files into one. In the early days of IIO we were much more inclined to keep the impact of the core IIO elements to the minimum. As time has moved on it has become clear that hardly any builds are done without buffer support and that it adds considerable complexity to the drivers. Hence merge down the buffer and non buffer elements of the sca3000 driver also allowing us to drop the header file used for the interfaces between the two. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/Makefile | 1 - drivers/staging/iio/accel/sca3000.c | 1702 ++++++++++++++++++++++++++++++ drivers/staging/iio/accel/sca3000.h | 279 ----- drivers/staging/iio/accel/sca3000_core.c | 1210 --------------------- drivers/staging/iio/accel/sca3000_ring.c | 350 ------ 5 files changed, 1702 insertions(+), 1840 deletions(-) create mode 100644 drivers/staging/iio/accel/sca3000.c delete mode 100644 drivers/staging/iio/accel/sca3000.h delete mode 100644 drivers/staging/iio/accel/sca3000_core.c delete mode 100644 drivers/staging/iio/accel/sca3000_ring.c (limited to 'drivers') diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index 1810a434a755..1d49b6ab87ab 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -14,5 +14,4 @@ obj-$(CONFIG_ADIS16209) += adis16209.o adis16240-y := adis16240_core.o obj-$(CONFIG_ADIS16240) += adis16240.o -sca3000-y := sca3000_core.o sca3000_ring.o obj-$(CONFIG_SCA3000) += sca3000.o diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c new file mode 100644 index 000000000000..62ab1aef2528 --- /dev/null +++ b/drivers/staging/iio/accel/sca3000.c @@ -0,0 +1,1702 @@ +/* + * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Copyright (c) 2009 Jonathan Cameron + * + * See industrialio/accels/sca3000.h for comments. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../ring_hw.h" + +#define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02) +#define SCA3000_READ_REG(a) ((a) << 2) + +#define SCA3000_REG_ADDR_REVID 0x00 +#define SCA3000_REVID_MAJOR_MASK 0xf0 +#define SCA3000_REVID_MINOR_MASK 0x0f + +#define SCA3000_REG_ADDR_STATUS 0x02 +#define SCA3000_LOCKED 0x20 +#define SCA3000_EEPROM_CS_ERROR 0x02 +#define SCA3000_SPI_FRAME_ERROR 0x01 + +/* All reads done using register decrement so no need to directly access LSBs */ +#define SCA3000_REG_ADDR_X_MSB 0x05 +#define SCA3000_REG_ADDR_Y_MSB 0x07 +#define SCA3000_REG_ADDR_Z_MSB 0x09 + +#define SCA3000_REG_ADDR_RING_OUT 0x0f + +/* Temp read untested - the e05 doesn't have the sensor */ +#define SCA3000_REG_ADDR_TEMP_MSB 0x13 + +#define SCA3000_REG_ADDR_MODE 0x14 +#define SCA3000_MODE_PROT_MASK 0x28 + +#define SCA3000_RING_BUF_ENABLE 0x80 +#define SCA3000_RING_BUF_8BIT 0x40 +/* + * Free fall detection triggers an interrupt if the acceleration + * is below a threshold for equivalent of 25cm drop + */ +#define SCA3000_FREE_FALL_DETECT 0x10 +#define SCA3000_MEAS_MODE_NORMAL 0x00 +#define SCA3000_MEAS_MODE_OP_1 0x01 +#define SCA3000_MEAS_MODE_OP_2 0x02 + +/* + * In motion detection mode the accelerations are band pass filtered + * (approx 1 - 25Hz) and then a programmable threshold used to trigger + * and interrupt. + */ +#define SCA3000_MEAS_MODE_MOT_DET 0x03 + +#define SCA3000_REG_ADDR_BUF_COUNT 0x15 + +#define SCA3000_REG_ADDR_INT_STATUS 0x16 + +#define SCA3000_INT_STATUS_THREE_QUARTERS 0x80 +#define SCA3000_INT_STATUS_HALF 0x40 + +#define SCA3000_INT_STATUS_FREE_FALL 0x08 +#define SCA3000_INT_STATUS_Y_TRIGGER 0x04 +#define SCA3000_INT_STATUS_X_TRIGGER 0x02 +#define SCA3000_INT_STATUS_Z_TRIGGER 0x01 + +/* Used to allow access to multiplexed registers */ +#define SCA3000_REG_ADDR_CTRL_SEL 0x18 +/* Only available for SCA3000-D03 and SCA3000-D01 */ +#define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01 +#define SCA3000_REG_CTRL_SEL_MD_CTRL 0x02 +#define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03 +#define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04 +#define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05 +/* + * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device + * will not function + */ +#define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B +#define SCA3000_OUT_CTRL_PROT_MASK 0xE0 +#define SCA3000_OUT_CTRL_BUF_X_EN 0x10 +#define SCA3000_OUT_CTRL_BUF_Y_EN 0x08 +#define SCA3000_OUT_CTRL_BUF_Z_EN 0x04 +#define SCA3000_OUT_CTRL_BUF_DIV_MASK 0x03 +#define SCA3000_OUT_CTRL_BUF_DIV_4 0x02 +#define SCA3000_OUT_CTRL_BUF_DIV_2 0x01 + +/* + * Control which motion detector interrupts are on. + * For now only OR combinations are supported. + */ +#define SCA3000_MD_CTRL_PROT_MASK 0xC0 +#define SCA3000_MD_CTRL_OR_Y 0x01 +#define SCA3000_MD_CTRL_OR_X 0x02 +#define SCA3000_MD_CTRL_OR_Z 0x04 +/* Currently unsupported */ +#define SCA3000_MD_CTRL_AND_Y 0x08 +#define SCA3000_MD_CTRL_AND_X 0x10 +#define SAC3000_MD_CTRL_AND_Z 0x20 + +/* + * Some control registers of complex access methods requiring this register to + * be used to remove a lock. + */ +#define SCA3000_REG_ADDR_UNLOCK 0x1e + +#define SCA3000_REG_ADDR_INT_MASK 0x21 +#define SCA3000_INT_MASK_PROT_MASK 0x1C + +#define SCA3000_INT_MASK_RING_THREE_QUARTER 0x80 +#define SCA3000_INT_MASK_RING_HALF 0x40 + +#define SCA3000_INT_MASK_ALL_INTS 0x02 +#define SCA3000_INT_MASK_ACTIVE_HIGH 0x01 +#define SCA3000_INT_MASK_ACTIVE_LOW 0x00 + +/* Values of multiplexed registers (write to ctrl_data after select) */ +#define SCA3000_REG_ADDR_CTRL_DATA 0x22 + +/* + * Measurement modes available on some sca3000 series chips. Code assumes others + * may become available in the future. + * + * Bypass - Bypass the low-pass filter in the signal channel so as to increase + * signal bandwidth. + * + * Narrow - Narrow low-pass filtering of the signal channel and half output + * data rate by decimation. + * + * Wide - Widen low-pass filtering of signal channel to increase bandwidth + */ +#define SCA3000_OP_MODE_BYPASS 0x01 +#define SCA3000_OP_MODE_NARROW 0x02 +#define SCA3000_OP_MODE_WIDE 0x04 +#define SCA3000_MAX_TX 6 +#define SCA3000_MAX_RX 2 + +/** + * struct sca3000_state - device instance state information + * @us: the associated spi device + * @info: chip variant information + * @interrupt_handler_ws: event interrupt handler for all events + * @last_timestamp: the timestamp of the last event + * @mo_det_use_count: reference counter for the motion detection unit + * @lock: lock used to protect elements of sca3000_state + * and the underlying device state. + * @bpse: number of bits per scan element + * @tx: dma-able transmit buffer + * @rx: dma-able receive buffer + **/ +struct sca3000_state { + struct spi_device *us; + const struct sca3000_chip_info *info; + struct work_struct interrupt_handler_ws; + s64 last_timestamp; + int mo_det_use_count; + struct mutex lock; + int bpse; + /* Can these share a cacheline ? */ + u8 rx[2] ____cacheline_aligned; + u8 tx[6] ____cacheline_aligned; +}; + +/** + * struct sca3000_chip_info - model dependent parameters + * @scale: scale * 10^-6 + * @temp_output: some devices have temperature sensors. + * @measurement_mode_freq: normal mode sampling frequency + * @option_mode_1: first optional mode. Not all models have one + * @option_mode_1_freq: option mode 1 sampling frequency + * @option_mode_2: second optional mode. Not all chips have one + * @option_mode_2_freq: option mode 2 sampling frequency + * + * This structure is used to hold information about the functionality of a given + * sca3000 variant. + **/ +struct sca3000_chip_info { + unsigned int scale; + bool temp_output; + int measurement_mode_freq; + int option_mode_1; + int option_mode_1_freq; + int option_mode_2; + int option_mode_2_freq; + int mot_det_mult_xz[6]; + int mot_det_mult_y[7]; +}; + +enum sca3000_variant { + d01, + e02, + e04, + e05, +}; + +/* + * Note where option modes are not defined, the chip simply does not + * support any. + * Other chips in the sca3000 series use i2c and are not included here. + * + * Some of these devices are only listed in the family data sheet and + * do not actually appear to be available. + */ +static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = { + [d01] = { + .scale = 7357, + .temp_output = true, + .measurement_mode_freq = 250, + .option_mode_1 = SCA3000_OP_MODE_BYPASS, + .option_mode_1_freq = 250, + .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300}, + .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750}, + }, + [e02] = { + .scale = 9810, + .measurement_mode_freq = 125, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 63, + .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050}, + .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700}, + }, + [e04] = { + .scale = 19620, + .measurement_mode_freq = 100, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 50, + .option_mode_2 = SCA3000_OP_MODE_WIDE, + .option_mode_2_freq = 400, + .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100}, + .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000}, + }, + [e05] = { + .scale = 61313, + .measurement_mode_freq = 200, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 50, + .option_mode_2 = SCA3000_OP_MODE_WIDE, + .option_mode_2_freq = 400, + .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900}, + .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600}, + }, +}; + +static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val) +{ + st->tx[0] = SCA3000_WRITE_REG(address); + st->tx[1] = val; + return spi_write(st->us, st->tx, 2); +} + +static int sca3000_read_data_short(struct sca3000_state *st, + u8 reg_address_high, + int len) +{ + struct spi_transfer xfer[2] = { + { + .len = 1, + .tx_buf = st->tx, + }, { + .len = len, + .rx_buf = st->rx, + } + }; + st->tx[0] = SCA3000_READ_REG(reg_address_high); + + return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); +} + +/** + * sca3000_reg_lock_on() test if the ctrl register lock is on + * + * Lock must be held. + **/ +static int sca3000_reg_lock_on(struct sca3000_state *st) +{ + int ret; + + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1); + if (ret < 0) + return ret; + + return !(st->rx[0] & SCA3000_LOCKED); +} + +/** + * __sca3000_unlock_reg_lock() unlock the control registers + * + * Note the device does not appear to support doing this in a single transfer. + * This should only ever be used as part of ctrl reg read. + * Lock must be held before calling this + **/ +static int __sca3000_unlock_reg_lock(struct sca3000_state *st) +{ + struct spi_transfer xfer[3] = { + { + .len = 2, + .cs_change = 1, + .tx_buf = st->tx, + }, { + .len = 2, + .cs_change = 1, + .tx_buf = st->tx + 2, + }, { + .len = 2, + .tx_buf = st->tx + 4, + }, + }; + st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); + st->tx[1] = 0x00; + st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); + st->tx[3] = 0x50; + st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); + st->tx[5] = 0xA0; + + return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); +} + +/** + * sca3000_write_ctrl_reg() write to a lock protect ctrl register + * @sel: selects which registers we wish to write to + * @val: the value to be written + * + * Certain control registers are protected against overwriting by the lock + * register and use a shared write address. This function allows writing of + * these registers. + * Lock must be held. + **/ +static int sca3000_write_ctrl_reg(struct sca3000_state *st, + u8 sel, + uint8_t val) +{ + int ret; + + ret = sca3000_reg_lock_on(st); + if (ret < 0) + goto error_ret; + if (ret) { + ret = __sca3000_unlock_reg_lock(st); + if (ret) + goto error_ret; + } + + /* Set the control select register */ + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_SEL, sel); + if (ret) + goto error_ret; + + /* Write the actual value into the register */ + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_DATA, val); + +error_ret: + return ret; +} + +/** + * sca3000_read_ctrl_reg() read from lock protected control register. + * + * Lock must be held. + **/ +static int sca3000_read_ctrl_reg(struct sca3000_state *st, + u8 ctrl_reg) +{ + int ret; + + ret = sca3000_reg_lock_on(st); + if (ret < 0) + goto error_ret; + if (ret) { + ret = __sca3000_unlock_reg_lock(st); + if (ret) + goto error_ret; + } + /* Set the control select register */ + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_SEL, ctrl_reg); + if (ret) + goto error_ret; + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_CTRL_DATA, 1); + if (ret) + goto error_ret; + return st->rx[0]; +error_ret: + return ret; +} + +/** + * sca3000_show_rev() - sysfs interface to read the chip revision number + **/ +static ssize_t sca3000_show_rev(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int len = 0, ret; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_REVID, 1); + if (ret < 0) + goto error_ret; + len += sprintf(buf + len, + "major=%d, minor=%d\n", + st->rx[0] & SCA3000_REVID_MAJOR_MASK, + st->rx[0] & SCA3000_REVID_MINOR_MASK); +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +/** + * sca3000_show_available_measurement_modes() display available modes + * + * This is all read from chip specific data in the driver. Not all + * of the sca3000 series support modes other than normal. + **/ +static ssize_t +sca3000_show_available_measurement_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + int len = 0; + + len += sprintf(buf + len, "0 - normal mode"); + switch (st->info->option_mode_1) { + case SCA3000_OP_MODE_NARROW: + len += sprintf(buf + len, ", 1 - narrow mode"); + break; + case SCA3000_OP_MODE_BYPASS: + len += sprintf(buf + len, ", 1 - bypass mode"); + break; + } + switch (st->info->option_mode_2) { + case SCA3000_OP_MODE_WIDE: + len += sprintf(buf + len, ", 2 - wide mode"); + break; + } + /* always supported */ + len += sprintf(buf + len, " 3 - motion detection\n"); + + return len; +} + +/** + * sca3000_show_measurement_mode() sysfs read of current mode + **/ +static ssize_t +sca3000_show_measurement_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + int len = 0, ret; + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + /* mask bottom 2 bits - only ones that are relevant */ + st->rx[0] &= 0x03; + switch (st->rx[0]) { + case SCA3000_MEAS_MODE_NORMAL: + len += sprintf(buf + len, "0 - normal mode\n"); + break; + case SCA3000_MEAS_MODE_MOT_DET: + len += sprintf(buf + len, "3 - motion detection\n"); + break; + case SCA3000_MEAS_MODE_OP_1: + switch (st->info->option_mode_1) { + case SCA3000_OP_MODE_NARROW: + len += sprintf(buf + len, "1 - narrow mode\n"); + break; + case SCA3000_OP_MODE_BYPASS: + len += sprintf(buf + len, "1 - bypass mode\n"); + break; + } + break; + case SCA3000_MEAS_MODE_OP_2: + switch (st->info->option_mode_2) { + case SCA3000_OP_MODE_WIDE: + len += sprintf(buf + len, "2 - wide mode\n"); + break; + } + break; + } + +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +/** + * sca3000_store_measurement_mode() set the current mode + **/ +static ssize_t +sca3000_store_measurement_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + u8 mask = 0x03; + u8 val; + + mutex_lock(&st->lock); + ret = kstrtou8(buf, 10, &val); + if (ret) + goto error_ret; + if (val > 3) { + ret = -EINVAL; + goto error_ret; + } + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + st->rx[0] &= ~mask; + st->rx[0] |= (val & mask); + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, st->rx[0]); + if (ret) + goto error_ret; + mutex_unlock(&st->lock); + + return len; + +error_ret: + mutex_unlock(&st->lock); + + return ret; +} + +/* + * Not even vaguely standard attributes so defined here rather than + * in the relevant IIO core headers + */ +static IIO_DEVICE_ATTR(measurement_mode_available, S_IRUGO, + sca3000_show_available_measurement_modes, + NULL, 0); + +static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR, + sca3000_show_measurement_mode, + sca3000_store_measurement_mode, + 0); + +/* More standard attributes */ + +static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); + +static const struct iio_event_spec sca3000_event = { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; + +#define SCA3000_CHAN(index, mod) \ + { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = mod, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 11, \ + .storagebits = 16, \ + .shift = 5, \ + }, \ + .event_spec = &sca3000_event, \ + .num_event_specs = 1, \ + } + +static const struct iio_chan_spec sca3000_channels[] = { + SCA3000_CHAN(0, IIO_MOD_X), + SCA3000_CHAN(1, IIO_MOD_Y), + SCA3000_CHAN(2, IIO_MOD_Z), +}; + +static const struct iio_chan_spec sca3000_channels_with_temp[] = { + SCA3000_CHAN(0, IIO_MOD_X), + SCA3000_CHAN(1, IIO_MOD_Y), + SCA3000_CHAN(2, IIO_MOD_Z), + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + /* No buffer support */ + .scan_index = -1, + }, +}; + +static u8 sca3000_addresses[3][3] = { + [0] = {SCA3000_REG_ADDR_X_MSB, SCA3000_REG_CTRL_SEL_MD_X_TH, + SCA3000_MD_CTRL_OR_X}, + [1] = {SCA3000_REG_ADDR_Y_MSB, SCA3000_REG_CTRL_SEL_MD_Y_TH, + SCA3000_MD_CTRL_OR_Y}, + [2] = {SCA3000_REG_ADDR_Z_MSB, SCA3000_REG_CTRL_SEL_MD_Z_TH, + SCA3000_MD_CTRL_OR_Z}, +}; + +/** + * __sca3000_get_base_freq() obtain mode specific base frequency + * + * lock must be held + **/ +static inline int __sca3000_get_base_freq(struct sca3000_state *st, + const struct sca3000_chip_info *info, + int *base_freq) +{ + int ret; + + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + switch (0x03 & st->rx[0]) { + case SCA3000_MEAS_MODE_NORMAL: + *base_freq = info->measurement_mode_freq; + break; + case SCA3000_MEAS_MODE_OP_1: + *base_freq = info->option_mode_1_freq; + break; + case SCA3000_MEAS_MODE_OP_2: + *base_freq = info->option_mode_2_freq; + break; + default: + ret = -EINVAL; + } +error_ret: + return ret; +} + +/** + * read_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * + * lock must be held + **/ +static int read_raw_samp_freq(struct sca3000_state *st, int *val) +{ + int ret; + + ret = __sca3000_get_base_freq(st, st->info, val); + if (ret) + return ret; + + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + return ret; + + if (*val > 0) { + ret &= SCA3000_OUT_CTRL_BUF_DIV_MASK; + switch (ret) { + case SCA3000_OUT_CTRL_BUF_DIV_2: + *val /= 2; + break; + case SCA3000_OUT_CTRL_BUF_DIV_4: + *val /= 4; + break; + } + } + + return 0; +} + +/** + * write_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * + * lock must be held + **/ +static int write_raw_samp_freq(struct sca3000_state *st, int val) +{ + int ret, base_freq, ctrlval; + + ret = __sca3000_get_base_freq(st, st->info, &base_freq); + if (ret) + return ret; + + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + return ret; + + ctrlval = ret & ~SCA3000_OUT_CTRL_BUF_DIV_MASK; + + if (val == base_freq / 2) + ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2; + if (val == base_freq / 4) + ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4; + else if (val != base_freq) + return -EINVAL; + + return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, + ctrlval); +} + +static int sca3000_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + u8 address; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&st->lock); + if (chan->type == IIO_ACCEL) { + if (st->mo_det_use_count) { + mutex_unlock(&st->lock); + return -EBUSY; + } + address = sca3000_addresses[chan->address][0]; + ret = sca3000_read_data_short(st, address, 2); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + *val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF; + *val = ((*val) << (sizeof(*val) * 8 - 13)) >> + (sizeof(*val) * 8 - 13); + } else { + /* get the temperature when available */ + ret = sca3000_read_data_short(st, + SCA3000_REG_ADDR_TEMP_MSB, + 2); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + *val = ((st->rx[0] & 0x3F) << 3) | + ((st->rx[1] & 0xE0) >> 5); + } + mutex_unlock(&st->lock); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + if (chan->type == IIO_ACCEL) + *val2 = st->info->scale; + else /* temperature */ + *val2 = 555556; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = -214; + *val2 = 600000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&st->lock); + ret = read_raw_samp_freq(st, val); + mutex_unlock(&st->lock); + return ret ? ret : IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int sca3000_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&st->lock); + ret = write_raw_samp_freq(st, val); + mutex_unlock(&st->lock); + return ret; + default: + return -EINVAL; + } + + return ret; +} + +/** + * sca3000_read_av_freq() sysfs function to get available frequencies + * + * The later modes are only relevant to the ring buffer - and depend on current + * mode. Note that data sheet gives rather wide tolerances for these so integer + * division will give good enough answer and not all chips have them specified + * at all. + **/ +static ssize_t sca3000_read_av_freq(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + int len = 0, ret, val; + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + val = st->rx[0]; + mutex_unlock(&st->lock); + if (ret) + goto error_ret; + + switch (val & 0x03) { + case SCA3000_MEAS_MODE_NORMAL: + len += sprintf(buf + len, "%d %d %d\n", + st->info->measurement_mode_freq, + st->info->measurement_mode_freq / 2, + st->info->measurement_mode_freq / 4); + break; + case SCA3000_MEAS_MODE_OP_1: + len += sprintf(buf + len, "%d %d %d\n", + st->info->option_mode_1_freq, + st->info->option_mode_1_freq / 2, + st->info->option_mode_1_freq / 4); + break; + case SCA3000_MEAS_MODE_OP_2: + len += sprintf(buf + len, "%d %d %d\n", + st->info->option_mode_2_freq, + st->info->option_mode_2_freq / 2, + st->info->option_mode_2_freq / 4); + break; + } + return len; +error_ret: + return ret; +} + +/* + * Should only really be registered if ring buffer support is compiled in. + * Does no harm however and doing it right would add a fair bit of complexity + */ +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); + +/** + * sca3000_read_thresh() - query of a threshold + **/ +static int sca3000_read_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + int ret, i; + struct sca3000_state *st = iio_priv(indio_dev); + int num = chan->channel2; + + mutex_lock(&st->lock); + ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]); + mutex_unlock(&st->lock); + if (ret < 0) + return ret; + *val = 0; + if (num == 1) + for_each_set_bit(i, (unsigned long *)&ret, + ARRAY_SIZE(st->info->mot_det_mult_y)) + *val += st->info->mot_det_mult_y[i]; + else + for_each_set_bit(i, (unsigned long *)&ret, + ARRAY_SIZE(st->info->mot_det_mult_xz)) + *val += st->info->mot_det_mult_xz[i]; + + return IIO_VAL_INT; +} + +/** + * sca3000_write_thresh() control of threshold + **/ +static int sca3000_write_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int num = chan->channel2; + int ret; + int i; + u8 nonlinear = 0; + + if (num == 1) { + i = ARRAY_SIZE(st->info->mot_det_mult_y); + while (i > 0) + if (val >= st->info->mot_det_mult_y[--i]) { + nonlinear |= (1 << i); + val -= st->info->mot_det_mult_y[i]; + } + } else { + i = ARRAY_SIZE(st->info->mot_det_mult_xz); + while (i > 0) + if (val >= st->info->mot_det_mult_xz[--i]) { + nonlinear |= (1 << i); + val -= st->info->mot_det_mult_xz[i]; + } + } + + mutex_lock(&st->lock); + ret = sca3000_write_ctrl_reg(st, sca3000_addresses[num][1], nonlinear); + mutex_unlock(&st->lock); + + return ret; +} + +static struct attribute *sca3000_attributes[] = { + &iio_dev_attr_revision.dev_attr.attr, + &iio_dev_attr_measurement_mode_available.dev_attr.attr, + &iio_dev_attr_measurement_mode.dev_attr.attr, + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group sca3000_attribute_group = { + .attrs = sca3000_attributes, +}; + +/** + * sca3000_ring_int_process() ring specific interrupt handling. + * + * This is only split from the main interrupt handler so as to + * reduce the amount of code if the ring buffer is not enabled. + **/ +static void sca3000_ring_int_process(u8 val, struct iio_buffer *ring) +{ + if (val & (SCA3000_INT_STATUS_THREE_QUARTERS | + SCA3000_INT_STATUS_HALF)) { + ring->stufftoread = true; + wake_up_interruptible(&ring->pollq); + } +} + +/** + * sca3000_event_handler() - handling ring and non ring events + * + * Ring related interrupt handler. Depending on event, push to + * the ring buffer event chrdev or the event one. + * + * This function is complicated by the fact that the devices can signify ring + * and non ring events via the same interrupt line and they can only + * be distinguished via a read of the relevant status register. + **/ +static irqreturn_t sca3000_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct sca3000_state *st = iio_priv(indio_dev); + int ret, val; + s64 last_timestamp = iio_get_time_ns(indio_dev); + + /* + * Could lead if badly timed to an extra read of status reg, + * but ensures no interrupt is missed. + */ + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_STATUS, 1); + val = st->rx[0]; + mutex_unlock(&st->lock); + if (ret) + goto done; + + sca3000_ring_int_process(val, indio_dev->buffer); + + if (val & SCA3000_INT_STATUS_FREE_FALL) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + last_timestamp); + + if (val & SCA3000_INT_STATUS_Y_TRIGGER) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Y, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + last_timestamp); + + if (val & SCA3000_INT_STATUS_X_TRIGGER) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + last_timestamp); + + if (val & SCA3000_INT_STATUS_Z_TRIGGER) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + last_timestamp); + +done: + return IRQ_HANDLED; +} + +/** + * sca3000_read_event_config() what events are enabled + **/ +static int sca3000_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + u8 protect_mask = 0x03; + int num = chan->channel2; + + /* read current value of mode register */ + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + + if ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET) { + ret = 0; + } else { + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); + if (ret < 0) + goto error_ret; + /* only supporting logical or's for now */ + ret = !!(ret & sca3000_addresses[num][2]); + } +error_ret: + mutex_unlock(&st->lock); + + return ret; +} + +/** + * sca3000_query_free_fall_mode() is free fall mode enabled + **/ +static ssize_t sca3000_query_free_fall_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + int val; + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + val = st->rx[0]; + mutex_unlock(&st->lock); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", !!(val & SCA3000_FREE_FALL_DETECT)); +} + +/** + * sca3000_set_free_fall_mode() simple on off control for free fall int + * + * In these chips the free fall detector should send an interrupt if + * the device falls more than 25cm. This has not been tested due + * to fragile wiring. + **/ +static ssize_t sca3000_set_free_fall_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + u8 val; + int ret; + u8 protect_mask = SCA3000_FREE_FALL_DETECT; + + mutex_lock(&st->lock); + ret = kstrtou8(buf, 10, &val); + if (ret) + goto error_ret; + + /* read current value of mode register */ + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + + /* if off and should be on */ + if (val && !(st->rx[0] & protect_mask)) + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + (st->rx[0] | SCA3000_FREE_FALL_DETECT)); + /* if on and should be off */ + else if (!val && (st->rx[0] & protect_mask)) + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + (st->rx[0] & ~protect_mask)); +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +/** + * sca3000_write_event_config() simple on off control for motion detector + * + * This is a per axis control, but enabling any will result in the + * motion detector unit being enabled. + * N.B. enabling motion detector stops normal data acquisition. + * There is a complexity in knowing which mode to return to when + * this mode is disabled. Currently normal mode is assumed. + **/ +static int sca3000_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret, ctrlval; + u8 protect_mask = 0x03; + int num = chan->channel2; + + mutex_lock(&st->lock); + /* + * First read the motion detector config to find out if + * this axis is on + */ + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); + if (ret < 0) + goto exit_point; + ctrlval = ret; + /* if off and should be on */ + if (state && !(ctrlval & sca3000_addresses[num][2])) { + ret = sca3000_write_ctrl_reg(st, + SCA3000_REG_CTRL_SEL_MD_CTRL, + ctrlval | + sca3000_addresses[num][2]); + if (ret) + goto exit_point; + st->mo_det_use_count++; + } else if (!state && (ctrlval & sca3000_addresses[num][2])) { + ret = sca3000_write_ctrl_reg(st, + SCA3000_REG_CTRL_SEL_MD_CTRL, + ctrlval & + ~(sca3000_addresses[num][2])); + if (ret) + goto exit_point; + st->mo_det_use_count--; + } + + /* read current value of mode register */ + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto exit_point; + /* if off and should be on */ + if ((st->mo_det_use_count) && + ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET)) + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + (st->rx[0] & ~protect_mask) + | SCA3000_MEAS_MODE_MOT_DET); + /* if on and should be off */ + else if (!(st->mo_det_use_count) && + ((st->rx[0] & protect_mask) == SCA3000_MEAS_MODE_MOT_DET)) + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + (st->rx[0] & ~protect_mask)); +exit_point: + mutex_unlock(&st->lock); + + return ret; +} + +/* Free fall detector related event attribute */ +static IIO_DEVICE_ATTR_NAMED(accel_xayaz_mag_falling_en, + in_accel_x & y & z_mag_falling_en, + S_IRUGO | S_IWUSR, + sca3000_query_free_fall_mode, + sca3000_set_free_fall_mode, + 0); + +static IIO_CONST_ATTR_NAMED(accel_xayaz_mag_falling_period, + in_accel_x & y & z_mag_falling_period, + "0.226"); + +static struct attribute *sca3000_event_attributes[] = { + &iio_dev_attr_accel_xayaz_mag_falling_en.dev_attr.attr, + &iio_const_attr_accel_xayaz_mag_falling_period.dev_attr.attr, + NULL, +}; + +static struct attribute_group sca3000_event_attribute_group = { + .attrs = sca3000_event_attributes, + .name = "events", +}; + +static int sca3000_read_data(struct sca3000_state *st, + u8 reg_address_high, + u8 **rx_p, + int len) +{ + int ret; + struct spi_transfer xfer[2] = { + { + .len = 1, + .tx_buf = st->tx, + }, { + .len = len, + } + }; + *rx_p = kmalloc(len, GFP_KERNEL); + if (!*rx_p) { + ret = -ENOMEM; + goto error_ret; + } + xfer[1].rx_buf = *rx_p; + st->tx[0] = SCA3000_READ_REG(reg_address_high); + ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); + if (ret) { + dev_err(get_device(&st->us->dev), "problem reading register"); + goto error_free_rx; + } + + return 0; +error_free_rx: + kfree(*rx_p); +error_ret: + return ret; +} + +/** + * sca3000_read_first_n_hw_rb() - main ring access, pulls data from ring + * @r: the ring + * @count: number of samples to try and pull + * @data: output the actual samples pulled from the hw ring + * + * Currently does not provide timestamps. As the hardware doesn't add them they + * can only be inferred approximately from ring buffer events such as 50% full + * and knowledge of when buffer was last emptied. This is left to userspace. + **/ +static int sca3000_read_first_n_hw_rb(struct iio_buffer *r, + size_t count, char __user *buf) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + struct iio_dev *indio_dev = hw_ring->private; + struct sca3000_state *st = iio_priv(indio_dev); + u8 *rx; + int ret, i, num_available, num_read = 0; + int bytes_per_sample = 1; + + if (st->bpse == 11) + bytes_per_sample = 2; + + mutex_lock(&st->lock); + if (count % bytes_per_sample) { + ret = -EINVAL; + goto error_ret; + } + + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_BUF_COUNT, 1); + if (ret) + goto error_ret; + num_available = st->rx[0]; + /* + * num_available is the total number of samples available + * i.e. number of time points * number of channels. + */ + if (count > num_available * bytes_per_sample) + num_read = num_available * bytes_per_sample; + else + num_read = count; + + ret = sca3000_read_data(st, + SCA3000_REG_ADDR_RING_OUT, + &rx, num_read); + if (ret) + goto error_ret; + + for (i = 0; i < num_read / sizeof(u16); i++) + *(((u16 *)rx) + i) = be16_to_cpup((__be16 *)rx + i); + + if (copy_to_user(buf, rx, num_read)) + ret = -EFAULT; + kfree(rx); + r->stufftoread = 0; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : num_read; +} + +static size_t sca3000_ring_buf_data_available(struct iio_buffer *r) +{ + return r->stufftoread ? r->watermark : 0; +} + +/** + * sca3000_query_ring_int() is the hardware ring status interrupt enabled + **/ +static ssize_t sca3000_query_ring_int(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret, val; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + val = st->rx[0]; + mutex_unlock(&st->lock); + if (ret) + return ret; + + return sprintf(buf, "%d\n", !!(val & this_attr->address)); +} + +/** + * sca3000_set_ring_int() set state of ring status interrupt + **/ +static ssize_t sca3000_set_ring_int(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + u8 val; + int ret; + + mutex_lock(&st->lock); + ret = kstrtou8(buf, 10, &val); + if (ret) + goto error_ret; + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + if (ret) + goto error_ret; + if (val) + ret = sca3000_write_reg(st, + SCA3000_REG_ADDR_INT_MASK, + st->rx[0] | this_attr->address); + else + ret = sca3000_write_reg(st, + SCA3000_REG_ADDR_INT_MASK, + st->rx[0] & ~this_attr->address); +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(50_percent, S_IRUGO | S_IWUSR, + sca3000_query_ring_int, + sca3000_set_ring_int, + SCA3000_INT_MASK_RING_HALF); + +static IIO_DEVICE_ATTR(75_percent, S_IRUGO | S_IWUSR, + sca3000_query_ring_int, + sca3000_set_ring_int, + SCA3000_INT_MASK_RING_THREE_QUARTER); + +static ssize_t sca3000_show_buffer_scale(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + + return sprintf(buf, "0.%06d\n", 4 * st->info->scale); +} + +static IIO_DEVICE_ATTR(in_accel_scale, + S_IRUGO, + sca3000_show_buffer_scale, + NULL, + 0); + +/* + * Ring buffer attributes + * This device is a bit unusual in that the sampling frequency and bpse + * only apply to the ring buffer. At all times full rate and accuracy + * is available via direct reading from registers. + */ +static const struct attribute *sca3000_ring_attributes[] = { + &iio_dev_attr_50_percent.dev_attr.attr, + &iio_dev_attr_75_percent.dev_attr.attr, + &iio_dev_attr_in_accel_scale.dev_attr.attr, + NULL, +}; + +static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) +{ + struct iio_buffer *buf; + struct iio_hw_buffer *ring; + + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (!ring) + return NULL; + + ring->private = indio_dev; + buf = &ring->buf; + buf->stufftoread = 0; + buf->length = 64; + buf->attrs = sca3000_ring_attributes; + iio_buffer_init(buf); + + return buf; +} + +static void sca3000_ring_release(struct iio_buffer *r) +{ + kfree(iio_to_hw_buf(r)); +} + +static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { + .read_first_n = &sca3000_read_first_n_hw_rb, + .data_available = sca3000_ring_buf_data_available, + .release = sca3000_ring_release, + + .modes = INDIO_BUFFER_HARDWARE, +}; + +static int sca3000_configure_ring(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer; + + buffer = sca3000_rb_allocate(indio_dev); + if (!buffer) + return -ENOMEM; + indio_dev->modes |= INDIO_BUFFER_HARDWARE; + + buffer->access = &sca3000_ring_access_funcs; + iio_device_attach_buffer(indio_dev, buffer); + + return 0; +} + +static void sca3000_unconfigure_ring(struct iio_dev *indio_dev) +{ + iio_buffer_put(indio_dev->buffer); +} + +static inline +int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + if (state) { + dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n"); + ret = sca3000_write_reg(st, + SCA3000_REG_ADDR_MODE, + (st->rx[0] | SCA3000_RING_BUF_ENABLE)); + } else + ret = sca3000_write_reg(st, + SCA3000_REG_ADDR_MODE, + (st->rx[0] & ~SCA3000_RING_BUF_ENABLE)); +error_ret: + mutex_unlock(&st->lock); + + return ret; +} + +/** + * sca3000_hw_ring_preenable() hw ring buffer preenable function + * + * Very simple enable function as the chip will allows normal reads + * during ring buffer operation so as long as it is indeed running + * before we notify the core, the precise ordering does not matter. + **/ +static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) +{ + return __sca3000_hw_ring_state_set(indio_dev, 1); +} + +static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev) +{ + return __sca3000_hw_ring_state_set(indio_dev, 0); +} + +static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { + .preenable = &sca3000_hw_ring_preenable, + .postdisable = &sca3000_hw_ring_postdisable, +}; + +static void sca3000_register_ring_funcs(struct iio_dev *indio_dev) +{ + indio_dev->setup_ops = &sca3000_ring_setup_ops; +} + +/** + * sca3000_clean_setup() get the device into a predictable state + * + * Devices use flash memory to store many of the register values + * and hence can come up in somewhat unpredictable states. + * Hence reset everything on driver load. + **/ +static int sca3000_clean_setup(struct sca3000_state *st) +{ + int ret; + + mutex_lock(&st->lock); + /* Ensure all interrupts have been acknowledged */ + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_STATUS, 1); + if (ret) + goto error_ret; + + /* Turn off all motion detection channels */ + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); + if (ret < 0) + goto error_ret; + ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL, + ret & SCA3000_MD_CTRL_PROT_MASK); + if (ret) + goto error_ret; + + /* Disable ring buffer */ + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + goto error_ret; + ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, + (ret & SCA3000_OUT_CTRL_PROT_MASK) + | SCA3000_OUT_CTRL_BUF_X_EN + | SCA3000_OUT_CTRL_BUF_Y_EN + | SCA3000_OUT_CTRL_BUF_Z_EN + | SCA3000_OUT_CTRL_BUF_DIV_4); + if (ret) + goto error_ret; + /* Enable interrupts, relevant to mode and set up as active low */ + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + if (ret) + goto error_ret; + ret = sca3000_write_reg(st, + SCA3000_REG_ADDR_INT_MASK, + (ret & SCA3000_INT_MASK_PROT_MASK) + | SCA3000_INT_MASK_ACTIVE_LOW); + if (ret) + goto error_ret; + /* + * Select normal measurement mode, free fall off, ring off + * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5 + * as that occurs in one of the example on the datasheet + */ + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + (st->rx[0] & SCA3000_MODE_PROT_MASK)); + st->bpse = 11; + +error_ret: + mutex_unlock(&st->lock); + return ret; +} + +static const struct iio_info sca3000_info = { + .attrs = &sca3000_attribute_group, + .read_raw = &sca3000_read_raw, + .write_raw = &sca3000_write_raw, + .event_attrs = &sca3000_event_attribute_group, + .read_event_value = &sca3000_read_thresh, + .write_event_value = &sca3000_write_thresh, + .read_event_config = &sca3000_read_event_config, + .write_event_config = &sca3000_write_event_config, + .driver_module = THIS_MODULE, +}; + +static int sca3000_probe(struct spi_device *spi) +{ + int ret; + struct sca3000_state *st; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + st->us = spi; + mutex_init(&st->lock); + st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi) + ->driver_data]; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &sca3000_info; + if (st->info->temp_output) { + indio_dev->channels = sca3000_channels_with_temp; + indio_dev->num_channels = + ARRAY_SIZE(sca3000_channels_with_temp); + } else { + indio_dev->channels = sca3000_channels; + indio_dev->num_channels = ARRAY_SIZE(sca3000_channels); + } + indio_dev->modes = INDIO_DIRECT_MODE; + + sca3000_configure_ring(indio_dev); + ret = iio_device_register(indio_dev); + if (ret < 0) + return ret; + + if (spi->irq) { + ret = request_threaded_irq(spi->irq, + NULL, + &sca3000_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "sca3000", + indio_dev); + if (ret) + goto error_unregister_dev; + } + sca3000_register_ring_funcs(indio_dev); + ret = sca3000_clean_setup(st); + if (ret) + goto error_free_irq; + return 0; + +error_free_irq: + if (spi->irq) + free_irq(spi->irq, indio_dev); +error_unregister_dev: + iio_device_unregister(indio_dev); + return ret; +} + +static int sca3000_stop_all_interrupts(struct sca3000_state *st) +{ + int ret; + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + if (ret) + goto error_ret; + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_INT_MASK, + (st->rx[0] & + ~(SCA3000_INT_MASK_RING_THREE_QUARTER | + SCA3000_INT_MASK_RING_HALF | + SCA3000_INT_MASK_ALL_INTS))); +error_ret: + mutex_unlock(&st->lock); + return ret; +} + +static int sca3000_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct sca3000_state *st = iio_priv(indio_dev); + + /* Must ensure no interrupts can be generated after this! */ + sca3000_stop_all_interrupts(st); + if (spi->irq) + free_irq(spi->irq, indio_dev); + iio_device_unregister(indio_dev); + sca3000_unconfigure_ring(indio_dev); + + return 0; +} + +static const struct spi_device_id sca3000_id[] = { + {"sca3000_d01", d01}, + {"sca3000_e02", e02}, + {"sca3000_e04", e04}, + {"sca3000_e05", e05}, + {} +}; +MODULE_DEVICE_TABLE(spi, sca3000_id); + +static struct spi_driver sca3000_driver = { + .driver = { + .name = "sca3000", + }, + .probe = sca3000_probe, + .remove = sca3000_remove, + .id_table = sca3000_id, +}; +module_spi_driver(sca3000_driver); + +MODULE_AUTHOR("Jonathan Cameron "); +MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h deleted file mode 100644 index 4dcc8575cbe3..000000000000 --- a/drivers/staging/iio/accel/sca3000.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * sca3000.c -- support VTI sca3000 series accelerometers - * via SPI - * - * Copyright (c) 2007 Jonathan Cameron - * - * Partly based upon tle62x0.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Initial mode is direct measurement. - * - * Untested things - * - * Temperature reading (the e05 I'm testing with doesn't have a sensor) - * - * Free fall detection mode - supported but untested as I'm not droping my - * dubious wire rig far enough to test it. - * - * Unsupported as yet - * - * Time stamping of data from ring. Various ideas on how to do this but none - * are remotely simple. Suggestions welcome. - * - * Individual enabling disabling of channels going into ring buffer - * - * Overflow handling (this is signaled for all but 8 bit ring buffer mode.) - * - * Motion detector using AND combinations of signals. - * - * Note: Be very careful about not touching an register bytes marked - * as reserved on the data sheet. They really mean it as changing convents of - * some will cause the device to lock up. - * - * Known issues - on rare occasions the interrupts lock up. Not sure why as yet. - * Can probably alleviate this by reading the interrupt register on start, but - * that is really just brushing the problem under the carpet. - */ -#ifndef _SCA3000 -#define _SCA3000 - -#define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02) -#define SCA3000_READ_REG(a) ((a) << 2) - -#define SCA3000_REG_ADDR_REVID 0x00 -#define SCA3000_REVID_MAJOR_MASK 0xf0 -#define SCA3000_REVID_MINOR_MASK 0x0f - -#define SCA3000_REG_ADDR_STATUS 0x02 -#define SCA3000_LOCKED 0x20 -#define SCA3000_EEPROM_CS_ERROR 0x02 -#define SCA3000_SPI_FRAME_ERROR 0x01 - -/* All reads done using register decrement so no need to directly access LSBs */ -#define SCA3000_REG_ADDR_X_MSB 0x05 -#define SCA3000_REG_ADDR_Y_MSB 0x07 -#define SCA3000_REG_ADDR_Z_MSB 0x09 - -#define SCA3000_REG_ADDR_RING_OUT 0x0f - -/* Temp read untested - the e05 doesn't have the sensor */ -#define SCA3000_REG_ADDR_TEMP_MSB 0x13 - -#define SCA3000_REG_ADDR_MODE 0x14 -#define SCA3000_MODE_PROT_MASK 0x28 - -#define SCA3000_RING_BUF_ENABLE 0x80 -#define SCA3000_RING_BUF_8BIT 0x40 -/* - * Free fall detection triggers an interrupt if the acceleration - * is below a threshold for equivalent of 25cm drop - */ -#define SCA3000_FREE_FALL_DETECT 0x10 -#define SCA3000_MEAS_MODE_NORMAL 0x00 -#define SCA3000_MEAS_MODE_OP_1 0x01 -#define SCA3000_MEAS_MODE_OP_2 0x02 - -/* - * In motion detection mode the accelerations are band pass filtered - * (approx 1 - 25Hz) and then a programmable threshold used to trigger - * and interrupt. - */ -#define SCA3000_MEAS_MODE_MOT_DET 0x03 - -#define SCA3000_REG_ADDR_BUF_COUNT 0x15 - -#define SCA3000_REG_ADDR_INT_STATUS 0x16 - -#define SCA3000_INT_STATUS_THREE_QUARTERS 0x80 -#define SCA3000_INT_STATUS_HALF 0x40 - -#define SCA3000_INT_STATUS_FREE_FALL 0x08 -#define SCA3000_INT_STATUS_Y_TRIGGER 0x04 -#define SCA3000_INT_STATUS_X_TRIGGER 0x02 -#define SCA3000_INT_STATUS_Z_TRIGGER 0x01 - -/* Used to allow access to multiplexed registers */ -#define SCA3000_REG_ADDR_CTRL_SEL 0x18 -/* Only available for SCA3000-D03 and SCA3000-D01 */ -#define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01 -#define SCA3000_REG_CTRL_SEL_MD_CTRL 0x02 -#define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03 -#define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04 -#define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05 -/* - * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device - * will not function - */ -#define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B -#define SCA3000_OUT_CTRL_PROT_MASK 0xE0 -#define SCA3000_OUT_CTRL_BUF_X_EN 0x10 -#define SCA3000_OUT_CTRL_BUF_Y_EN 0x08 -#define SCA3000_OUT_CTRL_BUF_Z_EN 0x04 -#define SCA3000_OUT_CTRL_BUF_DIV_MASK 0x03 -#define SCA3000_OUT_CTRL_BUF_DIV_4 0x02 -#define SCA3000_OUT_CTRL_BUF_DIV_2 0x01 - -/* - * Control which motion detector interrupts are on. - * For now only OR combinations are supported. - */ -#define SCA3000_MD_CTRL_PROT_MASK 0xC0 -#define SCA3000_MD_CTRL_OR_Y 0x01 -#define SCA3000_MD_CTRL_OR_X 0x02 -#define SCA3000_MD_CTRL_OR_Z 0x04 -/* Currently unsupported */ -#define SCA3000_MD_CTRL_AND_Y 0x08 -#define SCA3000_MD_CTRL_AND_X 0x10 -#define SAC3000_MD_CTRL_AND_Z 0x20 - -/* - * Some control registers of complex access methods requiring this register to - * be used to remove a lock. - */ -#define SCA3000_REG_ADDR_UNLOCK 0x1e - -#define SCA3000_REG_ADDR_INT_MASK 0x21 -#define SCA3000_INT_MASK_PROT_MASK 0x1C - -#define SCA3000_INT_MASK_RING_THREE_QUARTER 0x80 -#define SCA3000_INT_MASK_RING_HALF 0x40 - -#define SCA3000_INT_MASK_ALL_INTS 0x02 -#define SCA3000_INT_MASK_ACTIVE_HIGH 0x01 -#define SCA3000_INT_MASK_ACTIVE_LOW 0x00 - -/* Values of multiplexed registers (write to ctrl_data after select) */ -#define SCA3000_REG_ADDR_CTRL_DATA 0x22 - -/* - * Measurement modes available on some sca3000 series chips. Code assumes others - * may become available in the future. - * - * Bypass - Bypass the low-pass filter in the signal channel so as to increase - * signal bandwidth. - * - * Narrow - Narrow low-pass filtering of the signal channel and half output - * data rate by decimation. - * - * Wide - Widen low-pass filtering of signal channel to increase bandwidth - */ -#define SCA3000_OP_MODE_BYPASS 0x01 -#define SCA3000_OP_MODE_NARROW 0x02 -#define SCA3000_OP_MODE_WIDE 0x04 -#define SCA3000_MAX_TX 6 -#define SCA3000_MAX_RX 2 - -/** - * struct sca3000_state - device instance state information - * @us: the associated spi device - * @info: chip variant information - * @interrupt_handler_ws: event interrupt handler for all events - * @last_timestamp: the timestamp of the last event - * @mo_det_use_count: reference counter for the motion detection unit - * @lock: lock used to protect elements of sca3000_state - * and the underlying device state. - * @bpse: number of bits per scan element - * @tx: dma-able transmit buffer - * @rx: dma-able receive buffer - **/ -struct sca3000_state { - struct spi_device *us; - const struct sca3000_chip_info *info; - struct work_struct interrupt_handler_ws; - s64 last_timestamp; - int mo_det_use_count; - struct mutex lock; - int bpse; - /* Can these share a cacheline ? */ - u8 rx[2] ____cacheline_aligned; - u8 tx[6] ____cacheline_aligned; -}; - -/** - * struct sca3000_chip_info - model dependent parameters - * @scale: scale * 10^-6 - * @temp_output: some devices have temperature sensors. - * @measurement_mode_freq: normal mode sampling frequency - * @option_mode_1: first optional mode. Not all models have one - * @option_mode_1_freq: option mode 1 sampling frequency - * @option_mode_2: second optional mode. Not all chips have one - * @option_mode_2_freq: option mode 2 sampling frequency - * - * This structure is used to hold information about the functionality of a given - * sca3000 variant. - **/ -struct sca3000_chip_info { - unsigned int scale; - bool temp_output; - int measurement_mode_freq; - int option_mode_1; - int option_mode_1_freq; - int option_mode_2; - int option_mode_2_freq; - int mot_det_mult_xz[6]; - int mot_det_mult_y[7]; -}; - -int sca3000_read_data_short(struct sca3000_state *st, - u8 reg_address_high, - int len); - -/** - * sca3000_write_reg() write a single register - * @address: address of register on chip - * @val: value to be written to register - * - * The main lock must be held. - **/ -int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val); - -#ifdef CONFIG_IIO_BUFFER -/** - * sca3000_register_ring_funcs() setup the ring state change functions - **/ -void sca3000_register_ring_funcs(struct iio_dev *indio_dev); - -/** - * sca3000_configure_ring() - allocate and configure ring buffer - * @indio_dev: iio-core device whose ring is to be configured - * - * The hardware ring buffer needs far fewer ring buffer functions than - * a software one as a lot of things are handled automatically. - * This function also tells the iio core that our device supports a - * hardware ring buffer mode. - **/ -int sca3000_configure_ring(struct iio_dev *indio_dev); - -/** - * sca3000_unconfigure_ring() - deallocate the ring buffer - * @indio_dev: iio-core device whose ring we are freeing - **/ -void sca3000_unconfigure_ring(struct iio_dev *indio_dev); - -/** - * sca3000_ring_int_process() handles ring related event pushing and escalation - * @val: the event code - **/ -void sca3000_ring_int_process(u8 val, struct iio_buffer *ring); - -#else -static inline void sca3000_register_ring_funcs(struct iio_dev *indio_dev) -{ -} - -static inline -int sca3000_register_ring_access_and_init(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void sca3000_ring_int_process(u8 val, void *ring) -{ -} - -#endif -#endif /* _SCA3000 */ diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c deleted file mode 100644 index 564b36d4f648..000000000000 --- a/drivers/staging/iio/accel/sca3000_core.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* - * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * Copyright (c) 2009 Jonathan Cameron - * - * See industrialio/accels/sca3000.h for comments. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sca3000.h" - -enum sca3000_variant { - d01, - e02, - e04, - e05, -}; - -/* - * Note where option modes are not defined, the chip simply does not - * support any. - * Other chips in the sca3000 series use i2c and are not included here. - * - * Some of these devices are only listed in the family data sheet and - * do not actually appear to be available. - */ -static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = { - [d01] = { - .scale = 7357, - .temp_output = true, - .measurement_mode_freq = 250, - .option_mode_1 = SCA3000_OP_MODE_BYPASS, - .option_mode_1_freq = 250, - .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300}, - .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750}, - }, - [e02] = { - .scale = 9810, - .measurement_mode_freq = 125, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 63, - .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050}, - .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700}, - }, - [e04] = { - .scale = 19620, - .measurement_mode_freq = 100, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 50, - .option_mode_2 = SCA3000_OP_MODE_WIDE, - .option_mode_2_freq = 400, - .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100}, - .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000}, - }, - [e05] = { - .scale = 61313, - .measurement_mode_freq = 200, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 50, - .option_mode_2 = SCA3000_OP_MODE_WIDE, - .option_mode_2_freq = 400, - .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900}, - .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600}, - }, -}; - -int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val) -{ - st->tx[0] = SCA3000_WRITE_REG(address); - st->tx[1] = val; - return spi_write(st->us, st->tx, 2); -} - -int sca3000_read_data_short(struct sca3000_state *st, - u8 reg_address_high, - int len) -{ - struct spi_transfer xfer[2] = { - { - .len = 1, - .tx_buf = st->tx, - }, { - .len = len, - .rx_buf = st->rx, - } - }; - st->tx[0] = SCA3000_READ_REG(reg_address_high); - - return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); -} - -/** - * sca3000_reg_lock_on() test if the ctrl register lock is on - * - * Lock must be held. - **/ -static int sca3000_reg_lock_on(struct sca3000_state *st) -{ - int ret; - - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1); - if (ret < 0) - return ret; - - return !(st->rx[0] & SCA3000_LOCKED); -} - -/** - * __sca3000_unlock_reg_lock() unlock the control registers - * - * Note the device does not appear to support doing this in a single transfer. - * This should only ever be used as part of ctrl reg read. - * Lock must be held before calling this - **/ -static int __sca3000_unlock_reg_lock(struct sca3000_state *st) -{ - struct spi_transfer xfer[3] = { - { - .len = 2, - .cs_change = 1, - .tx_buf = st->tx, - }, { - .len = 2, - .cs_change = 1, - .tx_buf = st->tx + 2, - }, { - .len = 2, - .tx_buf = st->tx + 4, - }, - }; - st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); - st->tx[1] = 0x00; - st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); - st->tx[3] = 0x50; - st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); - st->tx[5] = 0xA0; - - return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); -} - -/** - * sca3000_write_ctrl_reg() write to a lock protect ctrl register - * @sel: selects which registers we wish to write to - * @val: the value to be written - * - * Certain control registers are protected against overwriting by the lock - * register and use a shared write address. This function allows writing of - * these registers. - * Lock must be held. - **/ -static int sca3000_write_ctrl_reg(struct sca3000_state *st, - u8 sel, - uint8_t val) -{ - int ret; - - ret = sca3000_reg_lock_on(st); - if (ret < 0) - goto error_ret; - if (ret) { - ret = __sca3000_unlock_reg_lock(st); - if (ret) - goto error_ret; - } - - /* Set the control select register */ - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_SEL, sel); - if (ret) - goto error_ret; - - /* Write the actual value into the register */ - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_DATA, val); - -error_ret: - return ret; -} - -/** - * sca3000_read_ctrl_reg() read from lock protected control register. - * - * Lock must be held. - **/ -static int sca3000_read_ctrl_reg(struct sca3000_state *st, - u8 ctrl_reg) -{ - int ret; - - ret = sca3000_reg_lock_on(st); - if (ret < 0) - goto error_ret; - if (ret) { - ret = __sca3000_unlock_reg_lock(st); - if (ret) - goto error_ret; - } - /* Set the control select register */ - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_SEL, ctrl_reg); - if (ret) - goto error_ret; - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_CTRL_DATA, 1); - if (ret) - goto error_ret; - return st->rx[0]; -error_ret: - return ret; -} - -/** - * sca3000_show_rev() - sysfs interface to read the chip revision number - **/ -static ssize_t sca3000_show_rev(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int len = 0, ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_REVID, 1); - if (ret < 0) - goto error_ret; - len += sprintf(buf + len, - "major=%d, minor=%d\n", - st->rx[0] & SCA3000_REVID_MAJOR_MASK, - st->rx[0] & SCA3000_REVID_MINOR_MASK); -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - -/** - * sca3000_show_available_measurement_modes() display available modes - * - * This is all read from chip specific data in the driver. Not all - * of the sca3000 series support modes other than normal. - **/ -static ssize_t -sca3000_show_available_measurement_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int len = 0; - - len += sprintf(buf + len, "0 - normal mode"); - switch (st->info->option_mode_1) { - case SCA3000_OP_MODE_NARROW: - len += sprintf(buf + len, ", 1 - narrow mode"); - break; - case SCA3000_OP_MODE_BYPASS: - len += sprintf(buf + len, ", 1 - bypass mode"); - break; - } - switch (st->info->option_mode_2) { - case SCA3000_OP_MODE_WIDE: - len += sprintf(buf + len, ", 2 - wide mode"); - break; - } - /* always supported */ - len += sprintf(buf + len, " 3 - motion detection\n"); - - return len; -} - -/** - * sca3000_show_measurement_mode() sysfs read of current mode - **/ -static ssize_t -sca3000_show_measurement_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int len = 0, ret; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - /* mask bottom 2 bits - only ones that are relevant */ - st->rx[0] &= 0x03; - switch (st->rx[0]) { - case SCA3000_MEAS_MODE_NORMAL: - len += sprintf(buf + len, "0 - normal mode\n"); - break; - case SCA3000_MEAS_MODE_MOT_DET: - len += sprintf(buf + len, "3 - motion detection\n"); - break; - case SCA3000_MEAS_MODE_OP_1: - switch (st->info->option_mode_1) { - case SCA3000_OP_MODE_NARROW: - len += sprintf(buf + len, "1 - narrow mode\n"); - break; - case SCA3000_OP_MODE_BYPASS: - len += sprintf(buf + len, "1 - bypass mode\n"); - break; - } - break; - case SCA3000_MEAS_MODE_OP_2: - switch (st->info->option_mode_2) { - case SCA3000_OP_MODE_WIDE: - len += sprintf(buf + len, "2 - wide mode\n"); - break; - } - break; - } - -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - -/** - * sca3000_store_measurement_mode() set the current mode - **/ -static ssize_t -sca3000_store_measurement_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - u8 mask = 0x03; - u8 val; - - mutex_lock(&st->lock); - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - if (val > 3) { - ret = -EINVAL; - goto error_ret; - } - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - st->rx[0] &= ~mask; - st->rx[0] |= (val & mask); - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, st->rx[0]); - if (ret) - goto error_ret; - mutex_unlock(&st->lock); - - return len; - -error_ret: - mutex_unlock(&st->lock); - - return ret; -} - -/* - * Not even vaguely standard attributes so defined here rather than - * in the relevant IIO core headers - */ -static IIO_DEVICE_ATTR(measurement_mode_available, S_IRUGO, - sca3000_show_available_measurement_modes, - NULL, 0); - -static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR, - sca3000_show_measurement_mode, - sca3000_store_measurement_mode, - 0); - -/* More standard attributes */ - -static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); - -static const struct iio_event_spec sca3000_event = { - .type = IIO_EV_TYPE_MAG, - .dir = IIO_EV_DIR_RISING, - .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), -}; - -#define SCA3000_CHAN(index, mod) \ - { \ - .type = IIO_ACCEL, \ - .modified = 1, \ - .channel2 = mod, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ - .address = index, \ - .scan_index = index, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 11, \ - .storagebits = 16, \ - .shift = 5, \ - }, \ - .event_spec = &sca3000_event, \ - .num_event_specs = 1, \ - } - -static const struct iio_chan_spec sca3000_channels[] = { - SCA3000_CHAN(0, IIO_MOD_X), - SCA3000_CHAN(1, IIO_MOD_Y), - SCA3000_CHAN(2, IIO_MOD_Z), -}; - -static const struct iio_chan_spec sca3000_channels_with_temp[] = { - SCA3000_CHAN(0, IIO_MOD_X), - SCA3000_CHAN(1, IIO_MOD_Y), - SCA3000_CHAN(2, IIO_MOD_Z), - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_OFFSET), - /* No buffer support */ - .scan_index = -1, - }, -}; - -static u8 sca3000_addresses[3][3] = { - [0] = {SCA3000_REG_ADDR_X_MSB, SCA3000_REG_CTRL_SEL_MD_X_TH, - SCA3000_MD_CTRL_OR_X}, - [1] = {SCA3000_REG_ADDR_Y_MSB, SCA3000_REG_CTRL_SEL_MD_Y_TH, - SCA3000_MD_CTRL_OR_Y}, - [2] = {SCA3000_REG_ADDR_Z_MSB, SCA3000_REG_CTRL_SEL_MD_Z_TH, - SCA3000_MD_CTRL_OR_Z}, -}; - -/** - * __sca3000_get_base_freq() obtain mode specific base frequency - * - * lock must be held - **/ -static inline int __sca3000_get_base_freq(struct sca3000_state *st, - const struct sca3000_chip_info *info, - int *base_freq) -{ - int ret; - - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - switch (0x03 & st->rx[0]) { - case SCA3000_MEAS_MODE_NORMAL: - *base_freq = info->measurement_mode_freq; - break; - case SCA3000_MEAS_MODE_OP_1: - *base_freq = info->option_mode_1_freq; - break; - case SCA3000_MEAS_MODE_OP_2: - *base_freq = info->option_mode_2_freq; - break; - default: - ret = -EINVAL; - } -error_ret: - return ret; -} - -/** - * read_raw handler for IIO_CHAN_INFO_SAMP_FREQ - * - * lock must be held - **/ -static int read_raw_samp_freq(struct sca3000_state *st, int *val) -{ - int ret; - - ret = __sca3000_get_base_freq(st, st->info, val); - if (ret) - return ret; - - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - if (ret < 0) - return ret; - - if (*val > 0) { - ret &= SCA3000_OUT_CTRL_BUF_DIV_MASK; - switch (ret) { - case SCA3000_OUT_CTRL_BUF_DIV_2: - *val /= 2; - break; - case SCA3000_OUT_CTRL_BUF_DIV_4: - *val /= 4; - break; - } - } - - return 0; -} - -/** - * write_raw handler for IIO_CHAN_INFO_SAMP_FREQ - * - * lock must be held - **/ -static int write_raw_samp_freq(struct sca3000_state *st, int val) -{ - int ret, base_freq, ctrlval; - - ret = __sca3000_get_base_freq(st, st->info, &base_freq); - if (ret) - return ret; - - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - if (ret < 0) - return ret; - - ctrlval = ret & ~SCA3000_OUT_CTRL_BUF_DIV_MASK; - - if (val == base_freq / 2) - ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2; - if (val == base_freq / 4) - ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4; - else if (val != base_freq) - return -EINVAL; - - return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, - ctrlval); -} - -static int sca3000_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - u8 address; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - mutex_lock(&st->lock); - if (chan->type == IIO_ACCEL) { - if (st->mo_det_use_count) { - mutex_unlock(&st->lock); - return -EBUSY; - } - address = sca3000_addresses[chan->address][0]; - ret = sca3000_read_data_short(st, address, 2); - if (ret < 0) { - mutex_unlock(&st->lock); - return ret; - } - *val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF; - *val = ((*val) << (sizeof(*val) * 8 - 13)) >> - (sizeof(*val) * 8 - 13); - } else { - /* get the temperature when available */ - ret = sca3000_read_data_short(st, - SCA3000_REG_ADDR_TEMP_MSB, - 2); - if (ret < 0) { - mutex_unlock(&st->lock); - return ret; - } - *val = ((st->rx[0] & 0x3F) << 3) | - ((st->rx[1] & 0xE0) >> 5); - } - mutex_unlock(&st->lock); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - *val = 0; - if (chan->type == IIO_ACCEL) - *val2 = st->info->scale; - else /* temperature */ - *val2 = 555556; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OFFSET: - *val = -214; - *val2 = 600000; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_SAMP_FREQ: - mutex_lock(&st->lock); - ret = read_raw_samp_freq(st, val); - mutex_unlock(&st->lock); - return ret ? ret : IIO_VAL_INT; - default: - return -EINVAL; - } -} - -static int sca3000_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - if (val2) - return -EINVAL; - mutex_lock(&st->lock); - ret = write_raw_samp_freq(st, val); - mutex_unlock(&st->lock); - return ret; - default: - return -EINVAL; - } - - return ret; -} - -/** - * sca3000_read_av_freq() sysfs function to get available frequencies - * - * The later modes are only relevant to the ring buffer - and depend on current - * mode. Note that data sheet gives rather wide tolerances for these so integer - * division will give good enough answer and not all chips have them specified - * at all. - **/ -static ssize_t sca3000_read_av_freq(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int len = 0, ret, val; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - val = st->rx[0]; - mutex_unlock(&st->lock); - if (ret) - goto error_ret; - - switch (val & 0x03) { - case SCA3000_MEAS_MODE_NORMAL: - len += sprintf(buf + len, "%d %d %d\n", - st->info->measurement_mode_freq, - st->info->measurement_mode_freq / 2, - st->info->measurement_mode_freq / 4); - break; - case SCA3000_MEAS_MODE_OP_1: - len += sprintf(buf + len, "%d %d %d\n", - st->info->option_mode_1_freq, - st->info->option_mode_1_freq / 2, - st->info->option_mode_1_freq / 4); - break; - case SCA3000_MEAS_MODE_OP_2: - len += sprintf(buf + len, "%d %d %d\n", - st->info->option_mode_2_freq, - st->info->option_mode_2_freq / 2, - st->info->option_mode_2_freq / 4); - break; - } - return len; -error_ret: - return ret; -} - -/* - * Should only really be registered if ring buffer support is compiled in. - * Does no harm however and doing it right would add a fair bit of complexity - */ -static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); - -/** - * sca3000_read_thresh() - query of a threshold - **/ -static int sca3000_read_thresh(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int *val, int *val2) -{ - int ret, i; - struct sca3000_state *st = iio_priv(indio_dev); - int num = chan->channel2; - - mutex_lock(&st->lock); - ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]); - mutex_unlock(&st->lock); - if (ret < 0) - return ret; - *val = 0; - if (num == 1) - for_each_set_bit(i, (unsigned long *)&ret, - ARRAY_SIZE(st->info->mot_det_mult_y)) - *val += st->info->mot_det_mult_y[i]; - else - for_each_set_bit(i, (unsigned long *)&ret, - ARRAY_SIZE(st->info->mot_det_mult_xz)) - *val += st->info->mot_det_mult_xz[i]; - - return IIO_VAL_INT; -} - -/** - * sca3000_write_thresh() control of threshold - **/ -static int sca3000_write_thresh(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int num = chan->channel2; - int ret; - int i; - u8 nonlinear = 0; - - if (num == 1) { - i = ARRAY_SIZE(st->info->mot_det_mult_y); - while (i > 0) - if (val >= st->info->mot_det_mult_y[--i]) { - nonlinear |= (1 << i); - val -= st->info->mot_det_mult_y[i]; - } - } else { - i = ARRAY_SIZE(st->info->mot_det_mult_xz); - while (i > 0) - if (val >= st->info->mot_det_mult_xz[--i]) { - nonlinear |= (1 << i); - val -= st->info->mot_det_mult_xz[i]; - } - } - - mutex_lock(&st->lock); - ret = sca3000_write_ctrl_reg(st, sca3000_addresses[num][1], nonlinear); - mutex_unlock(&st->lock); - - return ret; -} - -static struct attribute *sca3000_attributes[] = { - &iio_dev_attr_revision.dev_attr.attr, - &iio_dev_attr_measurement_mode_available.dev_attr.attr, - &iio_dev_attr_measurement_mode.dev_attr.attr, - &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group sca3000_attribute_group = { - .attrs = sca3000_attributes, -}; - -/** - * sca3000_event_handler() - handling ring and non ring events - * - * Ring related interrupt handler. Depending on event, push to - * the ring buffer event chrdev or the event one. - * - * This function is complicated by the fact that the devices can signify ring - * and non ring events via the same interrupt line and they can only - * be distinguished via a read of the relevant status register. - **/ -static irqreturn_t sca3000_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct sca3000_state *st = iio_priv(indio_dev); - int ret, val; - s64 last_timestamp = iio_get_time_ns(indio_dev); - - /* - * Could lead if badly timed to an extra read of status reg, - * but ensures no interrupt is missed. - */ - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_STATUS, 1); - val = st->rx[0]; - mutex_unlock(&st->lock); - if (ret) - goto done; - - sca3000_ring_int_process(val, indio_dev->buffer); - - if (val & SCA3000_INT_STATUS_FREE_FALL) - iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_X_AND_Y_AND_Z, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_FALLING), - last_timestamp); - - if (val & SCA3000_INT_STATUS_Y_TRIGGER) - iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_Y, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_RISING), - last_timestamp); - - if (val & SCA3000_INT_STATUS_X_TRIGGER) - iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_X, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_RISING), - last_timestamp); - - if (val & SCA3000_INT_STATUS_Z_TRIGGER) - iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_Z, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_RISING), - last_timestamp); - -done: - return IRQ_HANDLED; -} - -/** - * sca3000_read_event_config() what events are enabled - **/ -static int sca3000_read_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - u8 protect_mask = 0x03; - int num = chan->channel2; - - /* read current value of mode register */ - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - - if ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET) { - ret = 0; - } else { - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); - if (ret < 0) - goto error_ret; - /* only supporting logical or's for now */ - ret = !!(ret & sca3000_addresses[num][2]); - } -error_ret: - mutex_unlock(&st->lock); - - return ret; -} - -/** - * sca3000_query_free_fall_mode() is free fall mode enabled - **/ -static ssize_t sca3000_query_free_fall_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int val; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - val = st->rx[0]; - mutex_unlock(&st->lock); - if (ret < 0) - return ret; - return sprintf(buf, "%d\n", !!(val & SCA3000_FREE_FALL_DETECT)); -} - -/** - * sca3000_set_free_fall_mode() simple on off control for free fall int - * - * In these chips the free fall detector should send an interrupt if - * the device falls more than 25cm. This has not been tested due - * to fragile wiring. - **/ -static ssize_t sca3000_set_free_fall_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - u8 val; - int ret; - u8 protect_mask = SCA3000_FREE_FALL_DETECT; - - mutex_lock(&st->lock); - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - - /* read current value of mode register */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - - /* if off and should be on */ - if (val && !(st->rx[0] & protect_mask)) - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] | SCA3000_FREE_FALL_DETECT)); - /* if on and should be off */ - else if (!val && (st->rx[0] & protect_mask)) - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~protect_mask)); -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - -/** - * sca3000_write_event_config() simple on off control for motion detector - * - * This is a per axis control, but enabling any will result in the - * motion detector unit being enabled. - * N.B. enabling motion detector stops normal data acquisition. - * There is a complexity in knowing which mode to return to when - * this mode is disabled. Currently normal mode is assumed. - **/ -static int sca3000_write_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - int state) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret, ctrlval; - u8 protect_mask = 0x03; - int num = chan->channel2; - - mutex_lock(&st->lock); - /* - * First read the motion detector config to find out if - * this axis is on - */ - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); - if (ret < 0) - goto exit_point; - ctrlval = ret; - /* if off and should be on */ - if (state && !(ctrlval & sca3000_addresses[num][2])) { - ret = sca3000_write_ctrl_reg(st, - SCA3000_REG_CTRL_SEL_MD_CTRL, - ctrlval | - sca3000_addresses[num][2]); - if (ret) - goto exit_point; - st->mo_det_use_count++; - } else if (!state && (ctrlval & sca3000_addresses[num][2])) { - ret = sca3000_write_ctrl_reg(st, - SCA3000_REG_CTRL_SEL_MD_CTRL, - ctrlval & - ~(sca3000_addresses[num][2])); - if (ret) - goto exit_point; - st->mo_det_use_count--; - } - - /* read current value of mode register */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto exit_point; - /* if off and should be on */ - if ((st->mo_det_use_count) && - ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET)) - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~protect_mask) - | SCA3000_MEAS_MODE_MOT_DET); - /* if on and should be off */ - else if (!(st->mo_det_use_count) && - ((st->rx[0] & protect_mask) == SCA3000_MEAS_MODE_MOT_DET)) - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~protect_mask)); -exit_point: - mutex_unlock(&st->lock); - - return ret; -} - -/* Free fall detector related event attribute */ -static IIO_DEVICE_ATTR_NAMED(accel_xayaz_mag_falling_en, - in_accel_x & y & z_mag_falling_en, - S_IRUGO | S_IWUSR, - sca3000_query_free_fall_mode, - sca3000_set_free_fall_mode, - 0); - -static IIO_CONST_ATTR_NAMED(accel_xayaz_mag_falling_period, - in_accel_x & y & z_mag_falling_period, - "0.226"); - -static struct attribute *sca3000_event_attributes[] = { - &iio_dev_attr_accel_xayaz_mag_falling_en.dev_attr.attr, - &iio_const_attr_accel_xayaz_mag_falling_period.dev_attr.attr, - NULL, -}; - -static struct attribute_group sca3000_event_attribute_group = { - .attrs = sca3000_event_attributes, - .name = "events", -}; - -/** - * sca3000_clean_setup() get the device into a predictable state - * - * Devices use flash memory to store many of the register values - * and hence can come up in somewhat unpredictable states. - * Hence reset everything on driver load. - **/ -static int sca3000_clean_setup(struct sca3000_state *st) -{ - int ret; - - mutex_lock(&st->lock); - /* Ensure all interrupts have been acknowledged */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_STATUS, 1); - if (ret) - goto error_ret; - - /* Turn off all motion detection channels */ - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); - if (ret < 0) - goto error_ret; - ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL, - ret & SCA3000_MD_CTRL_PROT_MASK); - if (ret) - goto error_ret; - - /* Disable ring buffer */ - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - if (ret < 0) - goto error_ret; - ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, - (ret & SCA3000_OUT_CTRL_PROT_MASK) - | SCA3000_OUT_CTRL_BUF_X_EN - | SCA3000_OUT_CTRL_BUF_Y_EN - | SCA3000_OUT_CTRL_BUF_Z_EN - | SCA3000_OUT_CTRL_BUF_DIV_4); - if (ret) - goto error_ret; - /* Enable interrupts, relevant to mode and set up as active low */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); - if (ret) - goto error_ret; - ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_INT_MASK, - (ret & SCA3000_INT_MASK_PROT_MASK) - | SCA3000_INT_MASK_ACTIVE_LOW); - if (ret) - goto error_ret; - /* - * Select normal measurement mode, free fall off, ring off - * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5 - * as that occurs in one of the example on the datasheet - */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] & SCA3000_MODE_PROT_MASK)); - st->bpse = 11; - -error_ret: - mutex_unlock(&st->lock); - return ret; -} - -static const struct iio_info sca3000_info = { - .attrs = &sca3000_attribute_group, - .read_raw = &sca3000_read_raw, - .write_raw = &sca3000_write_raw, - .event_attrs = &sca3000_event_attribute_group, - .read_event_value = &sca3000_read_thresh, - .write_event_value = &sca3000_write_thresh, - .read_event_config = &sca3000_read_event_config, - .write_event_config = &sca3000_write_event_config, - .driver_module = THIS_MODULE, -}; - -static int sca3000_probe(struct spi_device *spi) -{ - int ret; - struct sca3000_state *st; - struct iio_dev *indio_dev; - - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->lock); - st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi) - ->driver_data]; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &sca3000_info; - if (st->info->temp_output) { - indio_dev->channels = sca3000_channels_with_temp; - indio_dev->num_channels = - ARRAY_SIZE(sca3000_channels_with_temp); - } else { - indio_dev->channels = sca3000_channels; - indio_dev->num_channels = ARRAY_SIZE(sca3000_channels); - } - indio_dev->modes = INDIO_DIRECT_MODE; - - sca3000_configure_ring(indio_dev); - ret = iio_device_register(indio_dev); - if (ret < 0) - return ret; - - if (spi->irq) { - ret = request_threaded_irq(spi->irq, - NULL, - &sca3000_event_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "sca3000", - indio_dev); - if (ret) - goto error_unregister_dev; - } - sca3000_register_ring_funcs(indio_dev); - ret = sca3000_clean_setup(st); - if (ret) - goto error_free_irq; - return 0; - -error_free_irq: - if (spi->irq) - free_irq(spi->irq, indio_dev); -error_unregister_dev: - iio_device_unregister(indio_dev); - return ret; -} - -static int sca3000_stop_all_interrupts(struct sca3000_state *st) -{ - int ret; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); - if (ret) - goto error_ret; - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_INT_MASK, - (st->rx[0] & - ~(SCA3000_INT_MASK_RING_THREE_QUARTER | - SCA3000_INT_MASK_RING_HALF | - SCA3000_INT_MASK_ALL_INTS))); -error_ret: - mutex_unlock(&st->lock); - return ret; -} - -static int sca3000_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct sca3000_state *st = iio_priv(indio_dev); - - /* Must ensure no interrupts can be generated after this! */ - sca3000_stop_all_interrupts(st); - if (spi->irq) - free_irq(spi->irq, indio_dev); - iio_device_unregister(indio_dev); - sca3000_unconfigure_ring(indio_dev); - - return 0; -} - -static const struct spi_device_id sca3000_id[] = { - {"sca3000_d01", d01}, - {"sca3000_e02", e02}, - {"sca3000_e04", e04}, - {"sca3000_e05", e05}, - {} -}; -MODULE_DEVICE_TABLE(spi, sca3000_id); - -static struct spi_driver sca3000_driver = { - .driver = { - .name = "sca3000", - }, - .probe = sca3000_probe, - .remove = sca3000_remove, - .id_table = sca3000_id, -}; -module_spi_driver(sca3000_driver); - -MODULE_AUTHOR("Jonathan Cameron "); -MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c deleted file mode 100644 index e5de52d05a5c..000000000000 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * sca3000_ring.c -- support VTI sca3000 series accelerometers via SPI - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * Copyright (c) 2009 Jonathan Cameron - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "../ring_hw.h" -#include "sca3000.h" - -/* RFC / future work - * - * The internal ring buffer doesn't actually change what it holds depending - * on which signals are enabled etc, merely whether you can read them. - * As such the scan mode selection is somewhat different than for a software - * ring buffer and changing it actually covers any data already in the buffer. - * Currently scan elements aren't configured so it doesn't matter. - */ - -static int sca3000_read_data(struct sca3000_state *st, - u8 reg_address_high, - u8 **rx_p, - int len) -{ - int ret; - struct spi_transfer xfer[2] = { - { - .len = 1, - .tx_buf = st->tx, - }, { - .len = len, - } - }; - *rx_p = kmalloc(len, GFP_KERNEL); - if (!*rx_p) { - ret = -ENOMEM; - goto error_ret; - } - xfer[1].rx_buf = *rx_p; - st->tx[0] = SCA3000_READ_REG(reg_address_high); - ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); - if (ret) { - dev_err(get_device(&st->us->dev), "problem reading register"); - goto error_free_rx; - } - - return 0; -error_free_rx: - kfree(*rx_p); -error_ret: - return ret; -} - -/** - * sca3000_read_first_n_hw_rb() - main ring access, pulls data from ring - * @r: the ring - * @count: number of samples to try and pull - * @data: output the actual samples pulled from the hw ring - * - * Currently does not provide timestamps. As the hardware doesn't add them they - * can only be inferred approximately from ring buffer events such as 50% full - * and knowledge of when buffer was last emptied. This is left to userspace. - **/ -static int sca3000_read_first_n_hw_rb(struct iio_buffer *r, - size_t count, char __user *buf) -{ - struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); - struct iio_dev *indio_dev = hw_ring->private; - struct sca3000_state *st = iio_priv(indio_dev); - u8 *rx; - int ret, i, num_available, num_read = 0; - int bytes_per_sample = 1; - - if (st->bpse == 11) - bytes_per_sample = 2; - - mutex_lock(&st->lock); - if (count % bytes_per_sample) { - ret = -EINVAL; - goto error_ret; - } - - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_BUF_COUNT, 1); - if (ret) - goto error_ret; - num_available = st->rx[0]; - /* - * num_available is the total number of samples available - * i.e. number of time points * number of channels. - */ - if (count > num_available * bytes_per_sample) - num_read = num_available * bytes_per_sample; - else - num_read = count; - - ret = sca3000_read_data(st, - SCA3000_REG_ADDR_RING_OUT, - &rx, num_read); - if (ret) - goto error_ret; - - for (i = 0; i < num_read / sizeof(u16); i++) - *(((u16 *)rx) + i) = be16_to_cpup((__be16 *)rx + i); - - if (copy_to_user(buf, rx, num_read)) - ret = -EFAULT; - kfree(rx); - r->stufftoread = 0; -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : num_read; -} - -static size_t sca3000_ring_buf_data_available(struct iio_buffer *r) -{ - return r->stufftoread ? r->watermark : 0; -} - -/** - * sca3000_query_ring_int() is the hardware ring status interrupt enabled - **/ -static ssize_t sca3000_query_ring_int(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret, val; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); - val = st->rx[0]; - mutex_unlock(&st->lock); - if (ret) - return ret; - - return sprintf(buf, "%d\n", !!(val & this_attr->address)); -} - -/** - * sca3000_set_ring_int() set state of ring status interrupt - **/ -static ssize_t sca3000_set_ring_int(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - u8 val; - int ret; - - mutex_lock(&st->lock); - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); - if (ret) - goto error_ret; - if (val) - ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_INT_MASK, - st->rx[0] | this_attr->address); - else - ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_INT_MASK, - st->rx[0] & ~this_attr->address); -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(50_percent, S_IRUGO | S_IWUSR, - sca3000_query_ring_int, - sca3000_set_ring_int, - SCA3000_INT_MASK_RING_HALF); - -static IIO_DEVICE_ATTR(75_percent, S_IRUGO | S_IWUSR, - sca3000_query_ring_int, - sca3000_set_ring_int, - SCA3000_INT_MASK_RING_THREE_QUARTER); - -static ssize_t sca3000_show_buffer_scale(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - - return sprintf(buf, "0.%06d\n", 4 * st->info->scale); -} - -static IIO_DEVICE_ATTR(in_accel_scale, - S_IRUGO, - sca3000_show_buffer_scale, - NULL, - 0); - -/* - * Ring buffer attributes - * This device is a bit unusual in that the sampling frequency and bpse - * only apply to the ring buffer. At all times full rate and accuracy - * is available via direct reading from registers. - */ -static const struct attribute *sca3000_ring_attributes[] = { - &iio_dev_attr_50_percent.dev_attr.attr, - &iio_dev_attr_75_percent.dev_attr.attr, - &iio_dev_attr_in_accel_scale.dev_attr.attr, - NULL, -}; - -static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) -{ - struct iio_buffer *buf; - struct iio_hw_buffer *ring; - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (!ring) - return NULL; - - ring->private = indio_dev; - buf = &ring->buf; - buf->stufftoread = 0; - buf->length = 64; - buf->attrs = sca3000_ring_attributes; - iio_buffer_init(buf); - - return buf; -} - -static void sca3000_ring_release(struct iio_buffer *r) -{ - kfree(iio_to_hw_buf(r)); -} - -static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { - .read_first_n = &sca3000_read_first_n_hw_rb, - .data_available = sca3000_ring_buf_data_available, - .release = sca3000_ring_release, - - .modes = INDIO_BUFFER_HARDWARE, -}; - -int sca3000_configure_ring(struct iio_dev *indio_dev) -{ - struct iio_buffer *buffer; - - buffer = sca3000_rb_allocate(indio_dev); - if (!buffer) - return -ENOMEM; - indio_dev->modes |= INDIO_BUFFER_HARDWARE; - - - buffer->access = &sca3000_ring_access_funcs; - iio_device_attach_buffer(indio_dev, buffer); - - return 0; -} - -void sca3000_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_buffer_put(indio_dev->buffer); -} - -static inline -int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - if (state) { - dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n"); - ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_MODE, - (st->rx[0] | SCA3000_RING_BUF_ENABLE)); - } else - ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~SCA3000_RING_BUF_ENABLE)); -error_ret: - mutex_unlock(&st->lock); - - return ret; -} - -/** - * sca3000_hw_ring_preenable() hw ring buffer preenable function - * - * Very simple enable function as the chip will allows normal reads - * during ring buffer operation so as long as it is indeed running - * before we notify the core, the precise ordering does not matter. - **/ -static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) -{ - return __sca3000_hw_ring_state_set(indio_dev, 1); -} - -static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev) -{ - return __sca3000_hw_ring_state_set(indio_dev, 0); -} - -static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { - .preenable = &sca3000_hw_ring_preenable, - .postdisable = &sca3000_hw_ring_postdisable, -}; - -void sca3000_register_ring_funcs(struct iio_dev *indio_dev) -{ - indio_dev->setup_ops = &sca3000_ring_setup_ops; -} - -/** - * sca3000_ring_int_process() ring specific interrupt handling. - * - * This is only split from the main interrupt handler so as to - * reduce the amount of code if the ring buffer is not enabled. - **/ -void sca3000_ring_int_process(u8 val, struct iio_buffer *ring) -{ - if (val & (SCA3000_INT_STATUS_THREE_QUARTERS | - SCA3000_INT_STATUS_HALF)) { - ring->stufftoread = true; - wake_up_interruptible(&ring->pollq); - } -} -- cgit v1.2.3 From d1bf1a865fe6b391208efab532b1e6fc912e5bed Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:03 +0100 Subject: staging:iio:accel:sca3000 drop sca3000_register_ring_funcs This was needed when the buffer support was optional. Pointless wrapper now so drop it. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 62ab1aef2528..36a52d02ee0e 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -1504,11 +1504,6 @@ static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { .postdisable = &sca3000_hw_ring_postdisable, }; -static void sca3000_register_ring_funcs(struct iio_dev *indio_dev) -{ - indio_dev->setup_ops = &sca3000_ring_setup_ops; -} - /** * sca3000_clean_setup() get the device into a predictable state * @@ -1631,7 +1626,7 @@ static int sca3000_probe(struct spi_device *spi) if (ret) goto error_unregister_dev; } - sca3000_register_ring_funcs(indio_dev); + indio_dev->setup_ops = &sca3000_ring_setup_ops; ret = sca3000_clean_setup(st); if (ret) goto error_free_irq; -- cgit v1.2.3 From 271a25f6480d51225abc2616df6c96e5979a7ffa Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:04 +0100 Subject: staging:iio:accel:sca3000 Fix clearing of flag + setting of size of scan. Not clearing the stuff_to_read flag can lead to a false flag being set on restarting the buffer if the data was not all read the previous time. The size of the scan is needed to ensure the function iio_buffer_read_first_n_outer actually tries to read the data. This stuff has been broken for some time so not stable material. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 36a52d02ee0e..8af7d83e658d 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -1491,6 +1491,19 @@ error_ret: **/ static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) { + /* + * Set stuff to read to indicate no data present. + * Need for cases where the interrupt had fired at the + * end of a cycle, but the data was never read. + */ + indio_dev->buffer->stufftoread = 0; + /* + * Needed to ensure the core will actually read data + * from the device rather than assuming no channels + * are enabled. + */ + indio_dev->buffer->bytes_per_datum = 6; + return __sca3000_hw_ring_state_set(indio_dev, 1); } -- cgit v1.2.3 From c19a02582b9b9b60cbeddfda2d3958ca36f9afc9 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:05 +0100 Subject: staging:iio:accel:sca3000 Drop custom ABI for watersheds. For now we support only the 50% watershed interrupt and start and stop it as part of the buffer bring up. The 75% case may come back in future. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 111 +++++++++++++----------------------- 1 file changed, 41 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 8af7d83e658d..173e9a69d44f 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -1309,73 +1309,6 @@ static size_t sca3000_ring_buf_data_available(struct iio_buffer *r) return r->stufftoread ? r->watermark : 0; } -/** - * sca3000_query_ring_int() is the hardware ring status interrupt enabled - **/ -static ssize_t sca3000_query_ring_int(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret, val; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); - val = st->rx[0]; - mutex_unlock(&st->lock); - if (ret) - return ret; - - return sprintf(buf, "%d\n", !!(val & this_attr->address)); -} - -/** - * sca3000_set_ring_int() set state of ring status interrupt - **/ -static ssize_t sca3000_set_ring_int(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - u8 val; - int ret; - - mutex_lock(&st->lock); - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); - if (ret) - goto error_ret; - if (val) - ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_INT_MASK, - st->rx[0] | this_attr->address); - else - ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_INT_MASK, - st->rx[0] & ~this_attr->address); -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(50_percent, S_IRUGO | S_IWUSR, - sca3000_query_ring_int, - sca3000_set_ring_int, - SCA3000_INT_MASK_RING_HALF); - -static IIO_DEVICE_ATTR(75_percent, S_IRUGO | S_IWUSR, - sca3000_query_ring_int, - sca3000_set_ring_int, - SCA3000_INT_MASK_RING_THREE_QUARTER); - static ssize_t sca3000_show_buffer_scale(struct device *dev, struct device_attribute *attr, char *buf) @@ -1399,8 +1332,6 @@ static IIO_DEVICE_ATTR(in_accel_scale, * is available via direct reading from registers. */ static const struct attribute *sca3000_ring_attributes[] = { - &iio_dev_attr_50_percent.dev_attr.attr, - &iio_dev_attr_75_percent.dev_attr.attr, &iio_dev_attr_in_accel_scale.dev_attr.attr, NULL, }; @@ -1491,6 +1422,9 @@ error_ret: **/ static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) { + int ret; + struct sca3000_state *st = iio_priv(indio_dev); + /* * Set stuff to read to indicate no data present. * Need for cases where the interrupt had fired at the @@ -1504,12 +1438,49 @@ static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) */ indio_dev->buffer->bytes_per_datum = 6; + mutex_lock(&st->lock); + + /* Enable the 50% full interrupt */ + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + if (ret) + goto error_unlock; + ret = sca3000_write_reg(st, + SCA3000_REG_ADDR_INT_MASK, + st->rx[0] | SCA3000_INT_MASK_RING_HALF); + if (ret) + goto error_unlock; + + mutex_unlock(&st->lock); + return __sca3000_hw_ring_state_set(indio_dev, 1); + +error_unlock: + mutex_unlock(&st->lock); + + return ret; } static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev) { - return __sca3000_hw_ring_state_set(indio_dev, 0); + int ret; + struct sca3000_state *st = iio_priv(indio_dev); + + ret = __sca3000_hw_ring_state_set(indio_dev, 0); + if (ret) + return ret; + + /* Disable the 50% full interrupt */ + mutex_lock(&st->lock); + + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + if (ret) + goto unlock; + ret = sca3000_write_reg(st, + SCA3000_REG_ADDR_INT_MASK, + st->rx[0] & ~SCA3000_INT_MASK_RING_HALF); +unlock: + mutex_unlock(&st->lock); + return ret; } static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { -- cgit v1.2.3 From 152a6a884ae13400bd7c48f011acf81ef5225238 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:06 +0100 Subject: staging:iio:accel:sca3000 move to hybrid hard / soft buffer design. In a similar fashion to other newer drivers (e.g. ti_am335x), instead of using the hardware buffer support in IIO to directly access the hardware fifo, insert a software fifo and feed that from the hardware one when interrupts occur. This gives a simpler structure to the data flows and allows more flexibility over how often data is shipped to userspace etc. This was also the only direct user of the simplistic generalization found in ring_hw.h so that header is removed. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/Kconfig | 3 +- drivers/staging/iio/accel/sca3000.c | 256 ++++++++++-------------------------- drivers/staging/iio/ring_hw.h | 27 ---- 3 files changed, 72 insertions(+), 214 deletions(-) delete mode 100644 drivers/staging/iio/ring_hw.h (limited to 'drivers') diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index 1c994b57c7d2..53389bfdd100 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -52,7 +52,8 @@ config ADIS16240 called adis16240. config SCA3000 - depends on IIO_BUFFER + select IIO_BUFFER + select IIO_KFIFO_BUF depends on SPI tristate "VTI SCA3000 series accelerometers" help diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 173e9a69d44f..f9ab7b3f8e87 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -23,7 +23,7 @@ #include #include #include -#include "../ring_hw.h" +#include #define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02) #define SCA3000_READ_REG(a) ((a) << 2) @@ -173,7 +173,7 @@ struct sca3000_state { struct mutex lock; int bpse; /* Can these share a cacheline ? */ - u8 rx[2] ____cacheline_aligned; + u8 rx[384] ____cacheline_aligned; u8 tx[6] ____cacheline_aligned; }; @@ -572,6 +572,10 @@ static const struct iio_event_spec sca3000_event = { .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }; +/* + * Note the hack in the number of bits to pretend we have 2 more than + * we do in the fifo. + */ #define SCA3000_CHAN(index, mod) \ { \ .type = IIO_ACCEL, \ @@ -584,9 +588,10 @@ static const struct iio_event_spec sca3000_event = { .scan_index = index, \ .scan_type = { \ .sign = 's', \ - .realbits = 11, \ + .realbits = 13, \ .storagebits = 16, \ - .shift = 5, \ + .shift = 3, \ + .endianness = IIO_BE, \ }, \ .event_spec = &sca3000_event, \ .num_event_specs = 1, \ @@ -935,19 +940,71 @@ static const struct attribute_group sca3000_attribute_group = { .attrs = sca3000_attributes, }; +static int sca3000_read_data(struct sca3000_state *st, + u8 reg_address_high, + u8 *rx, + int len) +{ + int ret; + struct spi_transfer xfer[2] = { + { + .len = 1, + .tx_buf = st->tx, + }, { + .len = len, + .rx_buf = rx, + } + }; + + st->tx[0] = SCA3000_READ_REG(reg_address_high); + ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); + if (ret) { + dev_err(get_device(&st->us->dev), "problem reading register"); + return ret; + } + + return 0; +} + /** * sca3000_ring_int_process() ring specific interrupt handling. * * This is only split from the main interrupt handler so as to * reduce the amount of code if the ring buffer is not enabled. **/ -static void sca3000_ring_int_process(u8 val, struct iio_buffer *ring) +static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev) { - if (val & (SCA3000_INT_STATUS_THREE_QUARTERS | - SCA3000_INT_STATUS_HALF)) { - ring->stufftoread = true; - wake_up_interruptible(&ring->pollq); + struct sca3000_state *st = iio_priv(indio_dev); + int ret, i, num_available; + + mutex_lock(&st->lock); + if (val & SCA3000_INT_STATUS_HALF) { + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_BUF_COUNT, + 1); + if (ret) + goto error_ret; + num_available = st->rx[0]; + /* + * num_available is the total number of samples available + * i.e. number of time points * number of channels. + */ + ret = sca3000_read_data(st, SCA3000_REG_ADDR_RING_OUT, st->rx, + num_available * 2); + if (ret) + goto error_ret; + for (i = 0; i < num_available / 3; i++) { + /* + * Dirty hack to cover for 11 bit in fifo, 13 bit + * direct reading. + * + * In theory the bottom two bits are undefined. + * In reality they appear to always be 0. + */ + iio_push_to_buffers(indio_dev, st->rx + i * 3 * 2); + } } +error_ret: + mutex_unlock(&st->lock); } /** @@ -978,7 +1035,7 @@ static irqreturn_t sca3000_event_handler(int irq, void *private) if (ret) goto done; - sca3000_ring_int_process(val, indio_dev->buffer); + sca3000_ring_int_process(val, indio_dev); if (val & SCA3000_INT_STATUS_FREE_FALL) iio_push_event(indio_dev, @@ -1209,183 +1266,23 @@ static struct attribute_group sca3000_event_attribute_group = { .name = "events", }; -static int sca3000_read_data(struct sca3000_state *st, - u8 reg_address_high, - u8 **rx_p, - int len) -{ - int ret; - struct spi_transfer xfer[2] = { - { - .len = 1, - .tx_buf = st->tx, - }, { - .len = len, - } - }; - *rx_p = kmalloc(len, GFP_KERNEL); - if (!*rx_p) { - ret = -ENOMEM; - goto error_ret; - } - xfer[1].rx_buf = *rx_p; - st->tx[0] = SCA3000_READ_REG(reg_address_high); - ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); - if (ret) { - dev_err(get_device(&st->us->dev), "problem reading register"); - goto error_free_rx; - } - - return 0; -error_free_rx: - kfree(*rx_p); -error_ret: - return ret; -} - -/** - * sca3000_read_first_n_hw_rb() - main ring access, pulls data from ring - * @r: the ring - * @count: number of samples to try and pull - * @data: output the actual samples pulled from the hw ring - * - * Currently does not provide timestamps. As the hardware doesn't add them they - * can only be inferred approximately from ring buffer events such as 50% full - * and knowledge of when buffer was last emptied. This is left to userspace. - **/ -static int sca3000_read_first_n_hw_rb(struct iio_buffer *r, - size_t count, char __user *buf) -{ - struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); - struct iio_dev *indio_dev = hw_ring->private; - struct sca3000_state *st = iio_priv(indio_dev); - u8 *rx; - int ret, i, num_available, num_read = 0; - int bytes_per_sample = 1; - - if (st->bpse == 11) - bytes_per_sample = 2; - - mutex_lock(&st->lock); - if (count % bytes_per_sample) { - ret = -EINVAL; - goto error_ret; - } - - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_BUF_COUNT, 1); - if (ret) - goto error_ret; - num_available = st->rx[0]; - /* - * num_available is the total number of samples available - * i.e. number of time points * number of channels. - */ - if (count > num_available * bytes_per_sample) - num_read = num_available * bytes_per_sample; - else - num_read = count; - - ret = sca3000_read_data(st, - SCA3000_REG_ADDR_RING_OUT, - &rx, num_read); - if (ret) - goto error_ret; - - for (i = 0; i < num_read / sizeof(u16); i++) - *(((u16 *)rx) + i) = be16_to_cpup((__be16 *)rx + i); - - if (copy_to_user(buf, rx, num_read)) - ret = -EFAULT; - kfree(rx); - r->stufftoread = 0; -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : num_read; -} - -static size_t sca3000_ring_buf_data_available(struct iio_buffer *r) -{ - return r->stufftoread ? r->watermark : 0; -} - -static ssize_t sca3000_show_buffer_scale(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - - return sprintf(buf, "0.%06d\n", 4 * st->info->scale); -} - -static IIO_DEVICE_ATTR(in_accel_scale, - S_IRUGO, - sca3000_show_buffer_scale, - NULL, - 0); - -/* - * Ring buffer attributes - * This device is a bit unusual in that the sampling frequency and bpse - * only apply to the ring buffer. At all times full rate and accuracy - * is available via direct reading from registers. - */ -static const struct attribute *sca3000_ring_attributes[] = { - &iio_dev_attr_in_accel_scale.dev_attr.attr, - NULL, -}; - -static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) -{ - struct iio_buffer *buf; - struct iio_hw_buffer *ring; - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (!ring) - return NULL; - - ring->private = indio_dev; - buf = &ring->buf; - buf->stufftoread = 0; - buf->length = 64; - buf->attrs = sca3000_ring_attributes; - iio_buffer_init(buf); - - return buf; -} - -static void sca3000_ring_release(struct iio_buffer *r) -{ - kfree(iio_to_hw_buf(r)); -} - -static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { - .read_first_n = &sca3000_read_first_n_hw_rb, - .data_available = sca3000_ring_buf_data_available, - .release = sca3000_ring_release, - - .modes = INDIO_BUFFER_HARDWARE, -}; - static int sca3000_configure_ring(struct iio_dev *indio_dev) { struct iio_buffer *buffer; - buffer = sca3000_rb_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; - indio_dev->modes |= INDIO_BUFFER_HARDWARE; - buffer->access = &sca3000_ring_access_funcs; iio_device_attach_buffer(indio_dev, buffer); + indio_dev->modes |= INDIO_BUFFER_SOFTWARE; return 0; } static void sca3000_unconfigure_ring(struct iio_dev *indio_dev) { - iio_buffer_put(indio_dev->buffer); + iio_kfifo_free(indio_dev->buffer); } static inline @@ -1425,19 +1322,6 @@ static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) int ret; struct sca3000_state *st = iio_priv(indio_dev); - /* - * Set stuff to read to indicate no data present. - * Need for cases where the interrupt had fired at the - * end of a cycle, but the data was never read. - */ - indio_dev->buffer->stufftoread = 0; - /* - * Needed to ensure the core will actually read data - * from the device rather than assuming no channels - * are enabled. - */ - indio_dev->buffer->bytes_per_datum = 6; - mutex_lock(&st->lock); /* Enable the 50% full interrupt */ diff --git a/drivers/staging/iio/ring_hw.h b/drivers/staging/iio/ring_hw.h deleted file mode 100644 index 75bf47bfee78..000000000000 --- a/drivers/staging/iio/ring_hw.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * ring_hw.h - common functionality for iio hardware ring buffers - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * Copyright (c) 2009 Jonathan Cameron - * - */ - -#ifndef _RING_HW_H_ -#define _RING_HW_H_ - -/** - * struct iio_hw_ring_buffer- hardware ring buffer - * @buf: generic ring buffer elements - * @private: device specific data - */ -struct iio_hw_buffer { - struct iio_buffer buf; - void *private; -}; - -#define iio_to_hw_buf(r) container_of(r, struct iio_hw_buffer, buf) - -#endif /* _RING_HW_H_ */ -- cgit v1.2.3 From 2600e12b8ba677f78da745adbe601f411ba43d4a Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:07 +0100 Subject: staging:iio:accel:sca3000 drop some unused variables. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index f9ab7b3f8e87..21428a4a3ec4 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -155,23 +155,19 @@ * struct sca3000_state - device instance state information * @us: the associated spi device * @info: chip variant information - * @interrupt_handler_ws: event interrupt handler for all events * @last_timestamp: the timestamp of the last event * @mo_det_use_count: reference counter for the motion detection unit * @lock: lock used to protect elements of sca3000_state * and the underlying device state. - * @bpse: number of bits per scan element * @tx: dma-able transmit buffer * @rx: dma-able receive buffer **/ struct sca3000_state { struct spi_device *us; const struct sca3000_chip_info *info; - struct work_struct interrupt_handler_ws; s64 last_timestamp; int mo_det_use_count; struct mutex lock; - int bpse; /* Can these share a cacheline ? */ u8 rx[384] ____cacheline_aligned; u8 tx[6] ____cacheline_aligned; @@ -1430,7 +1426,6 @@ static int sca3000_clean_setup(struct sca3000_state *st) goto error_ret; ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, (st->rx[0] & SCA3000_MODE_PROT_MASK)); - st->bpse = 11; error_ret: mutex_unlock(&st->lock); -- cgit v1.2.3 From 45ae5561acf52e82c838ba997dca5afc53ff1b61 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:08 +0100 Subject: staging:iio:accel:sca3000 use a 'fake' channel to handle freefall event registration. This is an approach used in some newer drivers as it exposes the compound channel events to the core rather than hiding their control in sysfs attributes entirely via the driver. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 303 ++++++++++++++++++------------------ 1 file changed, 155 insertions(+), 148 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 21428a4a3ec4..ec8d6f56d14a 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -60,6 +60,7 @@ #define SCA3000_MEAS_MODE_NORMAL 0x00 #define SCA3000_MEAS_MODE_OP_1 0x01 #define SCA3000_MEAS_MODE_OP_2 0x02 +#define SCA3000_MODE_MASK 0x03 /* * In motion detection mode the accelerations are band pass filtered @@ -593,10 +594,25 @@ static const struct iio_event_spec sca3000_event = { .num_event_specs = 1, \ } +static const struct iio_event_spec sca3000_freefall_event_spec = { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD), +}; + static const struct iio_chan_spec sca3000_channels[] = { SCA3000_CHAN(0, IIO_MOD_X), SCA3000_CHAN(1, IIO_MOD_Y), SCA3000_CHAN(2, IIO_MOD_Z), + { + .type = IIO_ACCEL, + .modified = 1, + .channel2 = IIO_MOD_X_AND_Y_AND_Z, + .scan_index = -1, /* Fake channel */ + .event_spec = &sca3000_freefall_event_spec, + .num_event_specs = 1, + }, }; static const struct iio_chan_spec sca3000_channels_with_temp[] = { @@ -611,6 +627,14 @@ static const struct iio_chan_spec sca3000_channels_with_temp[] = { /* No buffer support */ .scan_index = -1, }, + { + .type = IIO_ACCEL, + .modified = 1, + .channel2 = IIO_MOD_X_AND_Y_AND_Z, + .scan_index = -1, /* Fake channel */ + .event_spec = &sca3000_freefall_event_spec, + .num_event_specs = 1, + }, }; static u8 sca3000_addresses[3][3] = { @@ -854,46 +878,54 @@ error_ret: static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); /** - * sca3000_read_thresh() - query of a threshold + * sca3000_read_event_value() - query of a threshold or period **/ -static int sca3000_read_thresh(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int *val, int *val2) +static int sca3000_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { int ret, i; struct sca3000_state *st = iio_priv(indio_dev); int num = chan->channel2; + switch (info) { + case IIO_EV_INFO_VALUE: + mutex_lock(&st->lock); + ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]); + mutex_unlock(&st->lock); + if (ret < 0) + return ret; + *val = 0; + if (num == 1) + for_each_set_bit(i, (unsigned long *)&ret, + ARRAY_SIZE(st->info->mot_det_mult_y)) + *val += st->info->mot_det_mult_y[i]; + else + for_each_set_bit(i, (unsigned long *)&ret, + ARRAY_SIZE(st->info->mot_det_mult_xz)) + *val += st->info->mot_det_mult_xz[i]; - mutex_lock(&st->lock); - ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]); - mutex_unlock(&st->lock); - if (ret < 0) - return ret; - *val = 0; - if (num == 1) - for_each_set_bit(i, (unsigned long *)&ret, - ARRAY_SIZE(st->info->mot_det_mult_y)) - *val += st->info->mot_det_mult_y[i]; - else - for_each_set_bit(i, (unsigned long *)&ret, - ARRAY_SIZE(st->info->mot_det_mult_xz)) - *val += st->info->mot_det_mult_xz[i]; - - return IIO_VAL_INT; + return IIO_VAL_INT; + case IIO_EV_INFO_PERIOD: + *val = 0; + *val2 = 226000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } } /** - * sca3000_write_thresh() control of threshold + * sca3000_write_value() control of threshold and period **/ -static int sca3000_write_thresh(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) +static int sca3000_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct sca3000_state *st = iio_priv(indio_dev); int num = chan->channel2; @@ -901,7 +933,7 @@ static int sca3000_write_thresh(struct iio_dev *indio_dev, int i; u8 nonlinear = 0; - if (num == 1) { + if (num == IIO_MOD_Y) { i = ARRAY_SIZE(st->info->mot_det_mult_y); while (i > 0) if (val >= st->info->mot_det_mult_y[--i]) { @@ -1088,180 +1120,156 @@ static int sca3000_read_event_config(struct iio_dev *indio_dev, /* read current value of mode register */ mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); if (ret) goto error_ret; - if ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET) { - ret = 0; - } else { - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); - if (ret < 0) - goto error_ret; - /* only supporting logical or's for now */ - ret = !!(ret & sca3000_addresses[num][2]); + switch (chan->channel2) { + case IIO_MOD_X_AND_Y_AND_Z: + ret = !!(st->rx[0] & SCA3000_FREE_FALL_DETECT); + break; + case IIO_MOD_X: + case IIO_MOD_Y: + case IIO_MOD_Z: + /* + * Motion detection mode cannot run at the same time as + * acceleration data being read. + */ + if ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET) { + ret = 0; + } else { + ret = sca3000_read_ctrl_reg(st, + SCA3000_REG_CTRL_SEL_MD_CTRL); + if (ret < 0) + goto error_ret; + /* only supporting logical or's for now */ + ret = !!(ret & sca3000_addresses[num][2]); + } + break; + default: + ret = -EINVAL; } + error_ret: mutex_unlock(&st->lock); return ret; } -/** - * sca3000_query_free_fall_mode() is free fall mode enabled - **/ -static ssize_t sca3000_query_free_fall_mode(struct device *dev, - struct device_attribute *attr, - char *buf) +static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state) { - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); - int val; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - val = st->rx[0]; - mutex_unlock(&st->lock); - if (ret < 0) - return ret; - return sprintf(buf, "%d\n", !!(val & SCA3000_FREE_FALL_DETECT)); -} - -/** - * sca3000_set_free_fall_mode() simple on off control for free fall int - * - * In these chips the free fall detector should send an interrupt if - * the device falls more than 25cm. This has not been tested due - * to fragile wiring. - **/ -static ssize_t sca3000_set_free_fall_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - u8 val; int ret; - u8 protect_mask = SCA3000_FREE_FALL_DETECT; - - mutex_lock(&st->lock); - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; /* read current value of mode register */ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); if (ret) - goto error_ret; + return ret; /* if off and should be on */ - if (val && !(st->rx[0] & protect_mask)) - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] | SCA3000_FREE_FALL_DETECT)); + if (state && !(st->rx[0] & SCA3000_FREE_FALL_DETECT)) + return sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + st->rx[0] | SCA3000_FREE_FALL_DETECT); /* if on and should be off */ - else if (!val && (st->rx[0] & protect_mask)) - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~protect_mask)); -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; + else if (!state && (st->rx[0] & SCA3000_FREE_FALL_DETECT)) + return sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + st->rx[0] & ~SCA3000_FREE_FALL_DETECT); + else + return 0; } -/** - * sca3000_write_event_config() simple on off control for motion detector - * - * This is a per axis control, but enabling any will result in the - * motion detector unit being enabled. - * N.B. enabling motion detector stops normal data acquisition. - * There is a complexity in knowing which mode to return to when - * this mode is disabled. Currently normal mode is assumed. - **/ -static int sca3000_write_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - int state) +static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis, + int state) { struct sca3000_state *st = iio_priv(indio_dev); int ret, ctrlval; - u8 protect_mask = 0x03; - int num = chan->channel2; - mutex_lock(&st->lock); /* * First read the motion detector config to find out if * this axis is on */ ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); if (ret < 0) - goto exit_point; + return ret; ctrlval = ret; /* if off and should be on */ - if (state && !(ctrlval & sca3000_addresses[num][2])) { + if (state && !(ctrlval & sca3000_addresses[axis][2])) { ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL, ctrlval | - sca3000_addresses[num][2]); + sca3000_addresses[axis][2]); if (ret) - goto exit_point; + return ret; st->mo_det_use_count++; - } else if (!state && (ctrlval & sca3000_addresses[num][2])) { + } else if (!state && (ctrlval & sca3000_addresses[axis][2])) { ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL, ctrlval & - ~(sca3000_addresses[num][2])); + ~(sca3000_addresses[axis][2])); if (ret) - goto exit_point; + return ret; st->mo_det_use_count--; } /* read current value of mode register */ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); if (ret) - goto exit_point; + return ret; /* if off and should be on */ if ((st->mo_det_use_count) && - ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET)) - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~protect_mask) + ((st->rx[0] & SCA3000_MODE_MASK) != SCA3000_MEAS_MODE_MOT_DET)) + return sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + (st->rx[0] & ~SCA3000_MODE_MASK) | SCA3000_MEAS_MODE_MOT_DET); /* if on and should be off */ else if (!(st->mo_det_use_count) && - ((st->rx[0] & protect_mask) == SCA3000_MEAS_MODE_MOT_DET)) - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~protect_mask)); -exit_point: + ((st->rx[0] & SCA3000_MODE_MASK) == SCA3000_MEAS_MODE_MOT_DET)) + return sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + st->rx[0] & SCA3000_MODE_MASK); + else + return 0; +} + +/** + * sca3000_write_event_config() simple on off control for motion detector + * + * This is a per axis control, but enabling any will result in the + * motion detector unit being enabled. + * N.B. enabling motion detector stops normal data acquisition. + * There is a complexity in knowing which mode to return to when + * this mode is disabled. Currently normal mode is assumed. + **/ +static int sca3000_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + switch (chan->channel2) { + case IIO_MOD_X_AND_Y_AND_Z: + ret = sca3000_freefall_set_state(indio_dev, state); + break; + + case IIO_MOD_X: + case IIO_MOD_Y: + case IIO_MOD_Z: + ret = sca3000_motion_detect_set_state(indio_dev, chan->channel2, + state); + break; + default: + ret = -EINVAL; + break; + } mutex_unlock(&st->lock); return ret; } -/* Free fall detector related event attribute */ -static IIO_DEVICE_ATTR_NAMED(accel_xayaz_mag_falling_en, - in_accel_x & y & z_mag_falling_en, - S_IRUGO | S_IWUSR, - sca3000_query_free_fall_mode, - sca3000_set_free_fall_mode, - 0); - -static IIO_CONST_ATTR_NAMED(accel_xayaz_mag_falling_period, - in_accel_x & y & z_mag_falling_period, - "0.226"); - -static struct attribute *sca3000_event_attributes[] = { - &iio_dev_attr_accel_xayaz_mag_falling_en.dev_attr.attr, - &iio_const_attr_accel_xayaz_mag_falling_period.dev_attr.attr, - NULL, -}; - -static struct attribute_group sca3000_event_attribute_group = { - .attrs = sca3000_event_attributes, - .name = "events", -}; - static int sca3000_configure_ring(struct iio_dev *indio_dev) { struct iio_buffer *buffer; @@ -1436,9 +1444,8 @@ static const struct iio_info sca3000_info = { .attrs = &sca3000_attribute_group, .read_raw = &sca3000_read_raw, .write_raw = &sca3000_write_raw, - .event_attrs = &sca3000_event_attribute_group, - .read_event_value = &sca3000_read_thresh, - .write_event_value = &sca3000_write_thresh, + .read_event_value = &sca3000_read_event_value, + .write_event_value = &sca3000_write_event_value, .read_event_config = &sca3000_read_event_config, .write_event_config = &sca3000_write_event_config, .driver_module = THIS_MODULE, -- cgit v1.2.3 From 9bc11d32b3a47e09904f954a3a17a514779afaec Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:09 +0100 Subject: staging:iio:accel:sca3000 Clean up register defines. Introduce some more masks and generally drive towards consistent naming. Note the small indents used to indicate parts of registers + parts of multiplexed registers. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 328 ++++++++++++++++++------------------ 1 file changed, 165 insertions(+), 163 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index ec8d6f56d14a..86b0f104b592 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -28,111 +28,111 @@ #define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02) #define SCA3000_READ_REG(a) ((a) << 2) -#define SCA3000_REG_ADDR_REVID 0x00 -#define SCA3000_REVID_MAJOR_MASK 0xf0 -#define SCA3000_REVID_MINOR_MASK 0x0f - -#define SCA3000_REG_ADDR_STATUS 0x02 -#define SCA3000_LOCKED 0x20 -#define SCA3000_EEPROM_CS_ERROR 0x02 -#define SCA3000_SPI_FRAME_ERROR 0x01 - +#define SCA3000_REG_REVID_ADDR 0x00 +#define SCA3000_REG_REVID_MAJOR_MASK GENMASK(8, 4) +#define SCA3000_REG_REVID_MINOR_MASK GENMASK(3, 0) + +#define SCA3000_REG_STATUS_ADDR 0x02 +#define SCA3000_LOCKED BIT(5) +#define SCA3000_EEPROM_CS_ERROR BIT(1) +#define SCA3000_SPI_FRAME_ERROR BIT(0) + /* All reads done using register decrement so no need to directly access LSBs */ -#define SCA3000_REG_ADDR_X_MSB 0x05 -#define SCA3000_REG_ADDR_Y_MSB 0x07 -#define SCA3000_REG_ADDR_Z_MSB 0x09 +#define SCA3000_REG_X_MSB_ADDR 0x05 +#define SCA3000_REG_Y_MSB_ADDR 0x07 +#define SCA3000_REG_Z_MSB_ADDR 0x09 -#define SCA3000_REG_ADDR_RING_OUT 0x0f +#define SCA3000_REG_RING_OUT_ADDR 0x0f /* Temp read untested - the e05 doesn't have the sensor */ -#define SCA3000_REG_ADDR_TEMP_MSB 0x13 +#define SCA3000_REG_TEMP_MSB_ADDR 0x13 -#define SCA3000_REG_ADDR_MODE 0x14 -#define SCA3000_MODE_PROT_MASK 0x28 +#define SCA3000_REG_MODE_ADDR 0x14 +#define SCA3000_MODE_PROT_MASK 0x28 +#define SCA3000_REG_MODE_RING_BUF_ENABLE BIT(7) +#define SCA3000_REG_MODE_RING_BUF_8BIT BIT(6) -#define SCA3000_RING_BUF_ENABLE 0x80 -#define SCA3000_RING_BUF_8BIT 0x40 /* * Free fall detection triggers an interrupt if the acceleration * is below a threshold for equivalent of 25cm drop */ -#define SCA3000_FREE_FALL_DETECT 0x10 -#define SCA3000_MEAS_MODE_NORMAL 0x00 -#define SCA3000_MEAS_MODE_OP_1 0x01 -#define SCA3000_MEAS_MODE_OP_2 0x02 -#define SCA3000_MODE_MASK 0x03 +#define SCA3000_REG_MODE_FREE_FALL_DETECT BIT(4) +#define SCA3000_REG_MODE_MEAS_MODE_NORMAL 0x00 +#define SCA3000_REG_MODE_MEAS_MODE_OP_1 0x01 +#define SCA3000_REG_MODE_MEAS_MODE_OP_2 0x02 /* * In motion detection mode the accelerations are band pass filtered * (approx 1 - 25Hz) and then a programmable threshold used to trigger * and interrupt. */ -#define SCA3000_MEAS_MODE_MOT_DET 0x03 - -#define SCA3000_REG_ADDR_BUF_COUNT 0x15 +#define SCA3000_REG_MODE_MEAS_MODE_MOT_DET 0x03 +#define SCA3000_REG_MODE_MODE_MASK 0x03 -#define SCA3000_REG_ADDR_INT_STATUS 0x16 +#define SCA3000_REG_BUF_COUNT_ADDR 0x15 -#define SCA3000_INT_STATUS_THREE_QUARTERS 0x80 -#define SCA3000_INT_STATUS_HALF 0x40 - -#define SCA3000_INT_STATUS_FREE_FALL 0x08 -#define SCA3000_INT_STATUS_Y_TRIGGER 0x04 -#define SCA3000_INT_STATUS_X_TRIGGER 0x02 -#define SCA3000_INT_STATUS_Z_TRIGGER 0x01 +#define SCA3000_REG_INT_STATUS_ADDR 0x16 +#define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7) +#define SCA3000_REG_INT_STATUS_HALF BIT(6) + +#define SCA3000_INT_STATUS_FREE_FALL BIT(3) +#define SCA3000_INT_STATUS_Y_TRIGGER BIT(2) +#define SCA3000_INT_STATUS_X_TRIGGER BIT(1) +#define SCA3000_INT_STATUS_Z_TRIGGER BIT(0) /* Used to allow access to multiplexed registers */ -#define SCA3000_REG_ADDR_CTRL_SEL 0x18 +#define SCA3000_REG_CTRL_SEL_ADDR 0x18 /* Only available for SCA3000-D03 and SCA3000-D01 */ -#define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01 -#define SCA3000_REG_CTRL_SEL_MD_CTRL 0x02 -#define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03 -#define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04 -#define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05 +#define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01 +#define SCA3000_REG_CTRL_SEL_MD_CTRL 0x02 +#define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03 +#define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04 +#define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05 /* * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device * will not function */ -#define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B -#define SCA3000_OUT_CTRL_PROT_MASK 0xE0 -#define SCA3000_OUT_CTRL_BUF_X_EN 0x10 -#define SCA3000_OUT_CTRL_BUF_Y_EN 0x08 -#define SCA3000_OUT_CTRL_BUF_Z_EN 0x04 -#define SCA3000_OUT_CTRL_BUF_DIV_MASK 0x03 -#define SCA3000_OUT_CTRL_BUF_DIV_4 0x02 -#define SCA3000_OUT_CTRL_BUF_DIV_2 0x01 +#define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B + +#define SCA3000_REG_OUT_CTRL_PROT_MASK 0xE0 +#define SCA3000_REG_OUT_CTRL_BUF_X_EN 0x10 +#define SCA3000_REG_OUT_CTRL_BUF_Y_EN 0x08 +#define SCA3000_REG_OUT_CTRL_BUF_Z_EN 0x04 +#define SCA3000_REG_OUT_CTRL_BUF_DIV_MASK 0x03 +#define SCA3000_REG_OUT_CTRL_BUF_DIV_4 0x02 +#define SCA3000_REG_OUT_CTRL_BUF_DIV_2 0x01 + /* * Control which motion detector interrupts are on. * For now only OR combinations are supported. */ -#define SCA3000_MD_CTRL_PROT_MASK 0xC0 -#define SCA3000_MD_CTRL_OR_Y 0x01 -#define SCA3000_MD_CTRL_OR_X 0x02 -#define SCA3000_MD_CTRL_OR_Z 0x04 +#define SCA3000_MD_CTRL_PROT_MASK 0xC0 +#define SCA3000_MD_CTRL_OR_Y BIT(0) +#define SCA3000_MD_CTRL_OR_X BIT(1) +#define SCA3000_MD_CTRL_OR_Z BIT(2) /* Currently unsupported */ -#define SCA3000_MD_CTRL_AND_Y 0x08 -#define SCA3000_MD_CTRL_AND_X 0x10 -#define SAC3000_MD_CTRL_AND_Z 0x20 +#define SCA3000_MD_CTRL_AND_Y BIT(3) +#define SCA3000_MD_CTRL_AND_X BIT(4) +#define SAC3000_MD_CTRL_AND_Z BIT(5) /* * Some control registers of complex access methods requiring this register to * be used to remove a lock. */ -#define SCA3000_REG_ADDR_UNLOCK 0x1e - -#define SCA3000_REG_ADDR_INT_MASK 0x21 -#define SCA3000_INT_MASK_PROT_MASK 0x1C +#define SCA3000_REG_UNLOCK_ADDR 0x1e -#define SCA3000_INT_MASK_RING_THREE_QUARTER 0x80 -#define SCA3000_INT_MASK_RING_HALF 0x40 - -#define SCA3000_INT_MASK_ALL_INTS 0x02 -#define SCA3000_INT_MASK_ACTIVE_HIGH 0x01 -#define SCA3000_INT_MASK_ACTIVE_LOW 0x00 +#define SCA3000_REG_INT_MASK_ADDR 0x21 +#define SCA3000_REG_INT_MASK_PROT_MASK 0x1C + +#define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7) +#define SCA3000_REG_INT_MASK_RING_HALF BIT(6) +#define SCA3000_REG_INT_MASK_ALL_INTS 0x02 +#define SCA3000_REG_INT_MASK_ACTIVE_HIGH 0x01 +#define SCA3000_REG_INT_MASK_ACTIVE_LOW 0x00 /* Values of multiplexed registers (write to ctrl_data after select) */ -#define SCA3000_REG_ADDR_CTRL_DATA 0x22 +#define SCA3000_REG_CTRL_DATA_ADDR 0x22 /* * Measurement modes available on some sca3000 series chips. Code assumes others @@ -146,9 +146,9 @@ * * Wide - Widen low-pass filtering of signal channel to increase bandwidth */ -#define SCA3000_OP_MODE_BYPASS 0x01 -#define SCA3000_OP_MODE_NARROW 0x02 -#define SCA3000_OP_MODE_WIDE 0x04 +#define SCA3000_OP_MODE_BYPASS 0x01 +#define SCA3000_OP_MODE_NARROW 0x02 +#define SCA3000_OP_MODE_WIDE 0x04 #define SCA3000_MAX_TX 6 #define SCA3000_MAX_RX 2 @@ -288,7 +288,7 @@ static int sca3000_reg_lock_on(struct sca3000_state *st) { int ret; - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_STATUS_ADDR, 1); if (ret < 0) return ret; @@ -318,11 +318,11 @@ static int __sca3000_unlock_reg_lock(struct sca3000_state *st) .tx_buf = st->tx + 4, }, }; - st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); + st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); st->tx[1] = 0x00; - st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); + st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); st->tx[3] = 0x50; - st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); + st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); st->tx[5] = 0xA0; return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); @@ -354,12 +354,12 @@ static int sca3000_write_ctrl_reg(struct sca3000_state *st, } /* Set the control select register */ - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_SEL, sel); + ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, sel); if (ret) goto error_ret; /* Write the actual value into the register */ - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_DATA, val); + ret = sca3000_write_reg(st, SCA3000_REG_CTRL_DATA_ADDR, val); error_ret: return ret; @@ -384,10 +384,10 @@ static int sca3000_read_ctrl_reg(struct sca3000_state *st, goto error_ret; } /* Set the control select register */ - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_SEL, ctrl_reg); + ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, ctrl_reg); if (ret) goto error_ret; - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_CTRL_DATA, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_CTRL_DATA_ADDR, 1); if (ret) goto error_ret; return st->rx[0]; @@ -407,13 +407,13 @@ static ssize_t sca3000_show_rev(struct device *dev, struct sca3000_state *st = iio_priv(indio_dev); mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_REVID, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_REVID_ADDR, 1); if (ret < 0) goto error_ret; len += sprintf(buf + len, - "major=%d, minor=%d\n", - st->rx[0] & SCA3000_REVID_MAJOR_MASK, - st->rx[0] & SCA3000_REVID_MINOR_MASK); + "major=%lu, minor=%lu\n", + st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK, + st->rx[0] & SCA3000_REG_REVID_MINOR_MASK); error_ret: mutex_unlock(&st->lock); @@ -468,19 +468,19 @@ sca3000_show_measurement_mode(struct device *dev, int len = 0, ret; mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); if (ret) goto error_ret; /* mask bottom 2 bits - only ones that are relevant */ - st->rx[0] &= 0x03; + st->rx[0] &= SCA3000_REG_MODE_MODE_MASK; switch (st->rx[0]) { - case SCA3000_MEAS_MODE_NORMAL: + case SCA3000_REG_MODE_MEAS_MODE_NORMAL: len += sprintf(buf + len, "0 - normal mode\n"); break; - case SCA3000_MEAS_MODE_MOT_DET: + case SCA3000_REG_MODE_MEAS_MODE_MOT_DET: len += sprintf(buf + len, "3 - motion detection\n"); break; - case SCA3000_MEAS_MODE_OP_1: + case SCA3000_REG_MODE_MEAS_MODE_OP_1: switch (st->info->option_mode_1) { case SCA3000_OP_MODE_NARROW: len += sprintf(buf + len, "1 - narrow mode\n"); @@ -490,7 +490,7 @@ sca3000_show_measurement_mode(struct device *dev, break; } break; - case SCA3000_MEAS_MODE_OP_2: + case SCA3000_REG_MODE_MEAS_MODE_OP_2: switch (st->info->option_mode_2) { case SCA3000_OP_MODE_WIDE: len += sprintf(buf + len, "2 - wide mode\n"); @@ -517,7 +517,6 @@ sca3000_store_measurement_mode(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); int ret; - u8 mask = 0x03; u8 val; mutex_lock(&st->lock); @@ -528,12 +527,12 @@ sca3000_store_measurement_mode(struct device *dev, ret = -EINVAL; goto error_ret; } - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); if (ret) goto error_ret; - st->rx[0] &= ~mask; - st->rx[0] |= (val & mask); - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, st->rx[0]); + st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK; + st->rx[0] |= (val & SCA3000_REG_MODE_MODE_MASK); + ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]); if (ret) goto error_ret; mutex_unlock(&st->lock); @@ -638,11 +637,11 @@ static const struct iio_chan_spec sca3000_channels_with_temp[] = { }; static u8 sca3000_addresses[3][3] = { - [0] = {SCA3000_REG_ADDR_X_MSB, SCA3000_REG_CTRL_SEL_MD_X_TH, + [0] = {SCA3000_REG_X_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_X_TH, SCA3000_MD_CTRL_OR_X}, - [1] = {SCA3000_REG_ADDR_Y_MSB, SCA3000_REG_CTRL_SEL_MD_Y_TH, + [1] = {SCA3000_REG_Y_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Y_TH, SCA3000_MD_CTRL_OR_Y}, - [2] = {SCA3000_REG_ADDR_Z_MSB, SCA3000_REG_CTRL_SEL_MD_Z_TH, + [2] = {SCA3000_REG_Z_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Z_TH, SCA3000_MD_CTRL_OR_Z}, }; @@ -657,17 +656,17 @@ static inline int __sca3000_get_base_freq(struct sca3000_state *st, { int ret; - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); if (ret) goto error_ret; - switch (0x03 & st->rx[0]) { - case SCA3000_MEAS_MODE_NORMAL: + switch (SCA3000_REG_MODE_MODE_MASK & st->rx[0]) { + case SCA3000_REG_MODE_MEAS_MODE_NORMAL: *base_freq = info->measurement_mode_freq; break; - case SCA3000_MEAS_MODE_OP_1: + case SCA3000_REG_MODE_MEAS_MODE_OP_1: *base_freq = info->option_mode_1_freq; break; - case SCA3000_MEAS_MODE_OP_2: + case SCA3000_REG_MODE_MEAS_MODE_OP_2: *base_freq = info->option_mode_2_freq; break; default: @@ -695,12 +694,12 @@ static int read_raw_samp_freq(struct sca3000_state *st, int *val) return ret; if (*val > 0) { - ret &= SCA3000_OUT_CTRL_BUF_DIV_MASK; + ret &= SCA3000_REG_OUT_CTRL_BUF_DIV_MASK; switch (ret) { - case SCA3000_OUT_CTRL_BUF_DIV_2: + case SCA3000_REG_OUT_CTRL_BUF_DIV_2: *val /= 2; break; - case SCA3000_OUT_CTRL_BUF_DIV_4: + case SCA3000_REG_OUT_CTRL_BUF_DIV_4: *val /= 4; break; } @@ -726,12 +725,12 @@ static int write_raw_samp_freq(struct sca3000_state *st, int val) if (ret < 0) return ret; - ctrlval = ret & ~SCA3000_OUT_CTRL_BUF_DIV_MASK; + ctrlval = ret & ~SCA3000_REG_OUT_CTRL_BUF_DIV_MASK; if (val == base_freq / 2) - ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2; + ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_2; if (val == base_freq / 4) - ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4; + ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_4; else if (val != base_freq) return -EINVAL; @@ -769,7 +768,7 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, } else { /* get the temperature when available */ ret = sca3000_read_data_short(st, - SCA3000_REG_ADDR_TEMP_MSB, + SCA3000_REG_TEMP_MSB_ADDR, 2); if (ret < 0) { mutex_unlock(&st->lock); @@ -840,26 +839,26 @@ static ssize_t sca3000_read_av_freq(struct device *dev, int len = 0, ret, val; mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); val = st->rx[0]; mutex_unlock(&st->lock); if (ret) goto error_ret; - switch (val & 0x03) { - case SCA3000_MEAS_MODE_NORMAL: + switch (val & SCA3000_REG_MODE_MODE_MASK) { + case SCA3000_REG_MODE_MEAS_MODE_NORMAL: len += sprintf(buf + len, "%d %d %d\n", st->info->measurement_mode_freq, st->info->measurement_mode_freq / 2, st->info->measurement_mode_freq / 4); break; - case SCA3000_MEAS_MODE_OP_1: + case SCA3000_REG_MODE_MEAS_MODE_OP_1: len += sprintf(buf + len, "%d %d %d\n", st->info->option_mode_1_freq, st->info->option_mode_1_freq / 2, st->info->option_mode_1_freq / 4); break; - case SCA3000_MEAS_MODE_OP_2: + case SCA3000_REG_MODE_MEAS_MODE_OP_2: len += sprintf(buf + len, "%d %d %d\n", st->info->option_mode_2_freq, st->info->option_mode_2_freq / 2, @@ -1006,8 +1005,9 @@ static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev) int ret, i, num_available; mutex_lock(&st->lock); - if (val & SCA3000_INT_STATUS_HALF) { - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_BUF_COUNT, + + if (val & SCA3000_REG_INT_STATUS_HALF) { + ret = sca3000_read_data_short(st, SCA3000_REG_BUF_COUNT_ADDR, 1); if (ret) goto error_ret; @@ -1016,7 +1016,7 @@ static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev) * num_available is the total number of samples available * i.e. number of time points * number of channels. */ - ret = sca3000_read_data(st, SCA3000_REG_ADDR_RING_OUT, st->rx, + ret = sca3000_read_data(st, SCA3000_REG_RING_OUT_ADDR, st->rx, num_available * 2); if (ret) goto error_ret; @@ -1057,7 +1057,7 @@ static irqreturn_t sca3000_event_handler(int irq, void *private) * but ensures no interrupt is missed. */ mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_STATUS, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1); val = st->rx[0]; mutex_unlock(&st->lock); if (ret) @@ -1115,19 +1115,18 @@ static int sca3000_read_event_config(struct iio_dev *indio_dev, { struct sca3000_state *st = iio_priv(indio_dev); int ret; - u8 protect_mask = 0x03; int num = chan->channel2; /* read current value of mode register */ mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); if (ret) goto error_ret; switch (chan->channel2) { case IIO_MOD_X_AND_Y_AND_Z: - ret = !!(st->rx[0] & SCA3000_FREE_FALL_DETECT); + ret = !!(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT); break; case IIO_MOD_X: case IIO_MOD_Y: @@ -1136,7 +1135,8 @@ static int sca3000_read_event_config(struct iio_dev *indio_dev, * Motion detection mode cannot run at the same time as * acceleration data being read. */ - if ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET) { + if ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) + != SCA3000_REG_MODE_MEAS_MODE_MOT_DET) { ret = 0; } else { ret = sca3000_read_ctrl_reg(st, @@ -1163,18 +1163,18 @@ static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state) int ret; /* read current value of mode register */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); if (ret) return ret; /* if off and should be on */ - if (state && !(st->rx[0] & SCA3000_FREE_FALL_DETECT)) - return sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - st->rx[0] | SCA3000_FREE_FALL_DETECT); + if (state && !(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT)) + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + st->rx[0] | SCA3000_REG_MODE_FREE_FALL_DETECT); /* if on and should be off */ - else if (!state && (st->rx[0] & SCA3000_FREE_FALL_DETECT)) - return sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - st->rx[0] & ~SCA3000_FREE_FALL_DETECT); + else if (!state && (st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT)) + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + st->rx[0] & ~SCA3000_REG_MODE_FREE_FALL_DETECT); else return 0; } @@ -1213,20 +1213,22 @@ static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis, } /* read current value of mode register */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); if (ret) return ret; /* if off and should be on */ if ((st->mo_det_use_count) && - ((st->rx[0] & SCA3000_MODE_MASK) != SCA3000_MEAS_MODE_MOT_DET)) - return sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~SCA3000_MODE_MASK) - | SCA3000_MEAS_MODE_MOT_DET); + ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) + != SCA3000_REG_MODE_MEAS_MODE_MOT_DET)) + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + (st->rx[0] & ~SCA3000_REG_MODE_MODE_MASK) + | SCA3000_REG_MODE_MEAS_MODE_MOT_DET); /* if on and should be off */ else if (!(st->mo_det_use_count) && - ((st->rx[0] & SCA3000_MODE_MASK) == SCA3000_MEAS_MODE_MOT_DET)) - return sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - st->rx[0] & SCA3000_MODE_MASK); + ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) + == SCA3000_REG_MODE_MEAS_MODE_MOT_DET)) + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + st->rx[0] & SCA3000_REG_MODE_MODE_MASK); else return 0; } @@ -1296,18 +1298,18 @@ int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state) int ret; mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); if (ret) goto error_ret; if (state) { dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n"); ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_MODE, - (st->rx[0] | SCA3000_RING_BUF_ENABLE)); + SCA3000_REG_MODE_ADDR, + (st->rx[0] | SCA3000_REG_MODE_RING_BUF_ENABLE)); } else ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_MODE, - (st->rx[0] & ~SCA3000_RING_BUF_ENABLE)); + SCA3000_REG_MODE_ADDR, + (st->rx[0] & ~SCA3000_REG_MODE_RING_BUF_ENABLE)); error_ret: mutex_unlock(&st->lock); @@ -1329,12 +1331,12 @@ static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) mutex_lock(&st->lock); /* Enable the 50% full interrupt */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); if (ret) goto error_unlock; ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_INT_MASK, - st->rx[0] | SCA3000_INT_MASK_RING_HALF); + SCA3000_REG_INT_MASK_ADDR, + st->rx[0] | SCA3000_REG_INT_MASK_RING_HALF); if (ret) goto error_unlock; @@ -1360,12 +1362,12 @@ static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev) /* Disable the 50% full interrupt */ mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); if (ret) goto unlock; ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_INT_MASK, - st->rx[0] & ~SCA3000_INT_MASK_RING_HALF); + SCA3000_REG_INT_MASK_ADDR, + st->rx[0] & ~SCA3000_REG_INT_MASK_RING_HALF); unlock: mutex_unlock(&st->lock); return ret; @@ -1389,7 +1391,7 @@ static int sca3000_clean_setup(struct sca3000_state *st) mutex_lock(&st->lock); /* Ensure all interrupts have been acknowledged */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_STATUS, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1); if (ret) goto error_ret; @@ -1407,21 +1409,21 @@ static int sca3000_clean_setup(struct sca3000_state *st) if (ret < 0) goto error_ret; ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, - (ret & SCA3000_OUT_CTRL_PROT_MASK) - | SCA3000_OUT_CTRL_BUF_X_EN - | SCA3000_OUT_CTRL_BUF_Y_EN - | SCA3000_OUT_CTRL_BUF_Z_EN - | SCA3000_OUT_CTRL_BUF_DIV_4); + (ret & SCA3000_REG_OUT_CTRL_PROT_MASK) + | SCA3000_REG_OUT_CTRL_BUF_X_EN + | SCA3000_REG_OUT_CTRL_BUF_Y_EN + | SCA3000_REG_OUT_CTRL_BUF_Z_EN + | SCA3000_REG_OUT_CTRL_BUF_DIV_4); if (ret) goto error_ret; /* Enable interrupts, relevant to mode and set up as active low */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); if (ret) goto error_ret; ret = sca3000_write_reg(st, - SCA3000_REG_ADDR_INT_MASK, - (ret & SCA3000_INT_MASK_PROT_MASK) - | SCA3000_INT_MASK_ACTIVE_LOW); + SCA3000_REG_INT_MASK_ADDR, + (ret & SCA3000_REG_INT_MASK_PROT_MASK) + | SCA3000_REG_INT_MASK_ACTIVE_LOW); if (ret) goto error_ret; /* @@ -1429,10 +1431,10 @@ static int sca3000_clean_setup(struct sca3000_state *st) * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5 * as that occurs in one of the example on the datasheet */ - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); if (ret) goto error_ret; - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, (st->rx[0] & SCA3000_MODE_PROT_MASK)); error_ret: @@ -1515,14 +1517,14 @@ static int sca3000_stop_all_interrupts(struct sca3000_state *st) int ret; mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); if (ret) goto error_ret; - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_INT_MASK, + ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR, (st->rx[0] & - ~(SCA3000_INT_MASK_RING_THREE_QUARTER | - SCA3000_INT_MASK_RING_HALF | - SCA3000_INT_MASK_ALL_INTS))); + ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER | + SCA3000_REG_INT_MASK_RING_HALF | + SCA3000_REG_INT_MASK_ALL_INTS))); error_ret: mutex_unlock(&st->lock); return ret; -- cgit v1.2.3 From 085fe1b2e3df91a085d15a0bdc3f03cef6a42dab Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:10 +0100 Subject: staging:iio:accel:sca3000 add readback of the 3db low pass filter frequency Driving towards getting rid of the non standard mode control interface. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 48 ++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 86b0f104b592..8aa6980406f1 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -191,10 +191,13 @@ struct sca3000_chip_info { unsigned int scale; bool temp_output; int measurement_mode_freq; + int measurement_mode_3db_freq; int option_mode_1; int option_mode_1_freq; + int option_mode_1_3db_freq; int option_mode_2; int option_mode_2_freq; + int option_mode_2_3db_freq; int mot_det_mult_xz[6]; int mot_det_mult_y[7]; }; @@ -219,36 +222,46 @@ static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = { .scale = 7357, .temp_output = true, .measurement_mode_freq = 250, + .measurement_mode_3db_freq = 45, .option_mode_1 = SCA3000_OP_MODE_BYPASS, .option_mode_1_freq = 250, + .option_mode_1_3db_freq = 70, .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300}, .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750}, }, [e02] = { .scale = 9810, .measurement_mode_freq = 125, + .measurement_mode_3db_freq = 40, .option_mode_1 = SCA3000_OP_MODE_NARROW, .option_mode_1_freq = 63, + .option_mode_1_3db_freq = 11, .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050}, .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700}, }, [e04] = { .scale = 19620, .measurement_mode_freq = 100, + .measurement_mode_3db_freq = 38, .option_mode_1 = SCA3000_OP_MODE_NARROW, .option_mode_1_freq = 50, + .option_mode_1_3db_freq = 9, .option_mode_2 = SCA3000_OP_MODE_WIDE, .option_mode_2_freq = 400, + .option_mode_2_3db_freq = 70, .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100}, .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000}, }, [e05] = { .scale = 61313, .measurement_mode_freq = 200, + .measurement_mode_3db_freq = 60, .option_mode_1 = SCA3000_OP_MODE_NARROW, .option_mode_1_freq = 50, + .option_mode_1_3db_freq = 9, .option_mode_2 = SCA3000_OP_MODE_WIDE, .option_mode_2_freq = 400, + .option_mode_2_3db_freq = 75, .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900}, .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600}, }, @@ -578,7 +591,8 @@ static const struct iio_event_spec sca3000_event = { .modified = 1, \ .channel2 = mod, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |\ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),\ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ .address = index, \ .scan_index = index, \ @@ -738,6 +752,33 @@ static int write_raw_samp_freq(struct sca3000_state *st, int val) ctrlval); } +static int sca3000_read_3db_freq(struct sca3000_state *st, int *val) +{ + int ret; + + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + return ret; + + /* mask bottom 2 bits - only ones that are relevant */ + st->rx[0] &= SCA3000_REG_MODE_MODE_MASK; + switch (st->rx[0]) { + case SCA3000_REG_MODE_MEAS_MODE_NORMAL: + *val = st->info->measurement_mode_3db_freq; + return IIO_VAL_INT; + case SCA3000_REG_MODE_MEAS_MODE_MOT_DET: + return -EBUSY; + case SCA3000_REG_MODE_MEAS_MODE_OP_1: + *val = st->info->option_mode_1_3db_freq; + return IIO_VAL_INT; + case SCA3000_REG_MODE_MEAS_MODE_OP_2: + *val = st->info->option_mode_2_3db_freq; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + static int sca3000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -795,6 +836,11 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, ret = read_raw_samp_freq(st, val); mutex_unlock(&st->lock); return ret ? ret : IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + mutex_lock(&st->lock); + ret = sca3000_read_3db_freq(st, val); + mutex_unlock(&st->lock); + return ret; default: return -EINVAL; } -- cgit v1.2.3 From 74bdc940757608876a77cc0cdc2877b66e5dd47d Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:11 +0100 Subject: staging:iio:accel:sca3000: Fix off by one error in axis due to IIO_NO_MOD Given the introduction of IIO_NO_MOD was prior to the first submission prior to IIO entering staging this has been broken for a while. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 8aa6980406f1..b5dc40523bb5 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -934,16 +934,17 @@ static int sca3000_read_event_value(struct iio_dev *indio_dev, { int ret, i; struct sca3000_state *st = iio_priv(indio_dev); - int num = chan->channel2; + switch (info) { case IIO_EV_INFO_VALUE: mutex_lock(&st->lock); - ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]); + ret = sca3000_read_ctrl_reg(st, + sca3000_addresses[chan->address][1]); mutex_unlock(&st->lock); if (ret < 0) return ret; *val = 0; - if (num == 1) + if (chan->channel2 == IIO_MOD_Y) for_each_set_bit(i, (unsigned long *)&ret, ARRAY_SIZE(st->info->mot_det_mult_y)) *val += st->info->mot_det_mult_y[i]; @@ -973,12 +974,11 @@ static int sca3000_write_event_value(struct iio_dev *indio_dev, int val, int val2) { struct sca3000_state *st = iio_priv(indio_dev); - int num = chan->channel2; int ret; int i; u8 nonlinear = 0; - if (num == IIO_MOD_Y) { + if (chan->channel2 == IIO_MOD_Y) { i = ARRAY_SIZE(st->info->mot_det_mult_y); while (i > 0) if (val >= st->info->mot_det_mult_y[--i]) { @@ -995,7 +995,9 @@ static int sca3000_write_event_value(struct iio_dev *indio_dev, } mutex_lock(&st->lock); - ret = sca3000_write_ctrl_reg(st, sca3000_addresses[num][1], nonlinear); + ret = sca3000_write_ctrl_reg(st, + sca3000_addresses[chan->address][1], + nonlinear); mutex_unlock(&st->lock); return ret; @@ -1161,8 +1163,6 @@ static int sca3000_read_event_config(struct iio_dev *indio_dev, { struct sca3000_state *st = iio_priv(indio_dev); int ret; - int num = chan->channel2; - /* read current value of mode register */ mutex_lock(&st->lock); @@ -1190,7 +1190,7 @@ static int sca3000_read_event_config(struct iio_dev *indio_dev, if (ret < 0) goto error_ret; /* only supporting logical or's for now */ - ret = !!(ret & sca3000_addresses[num][2]); + ret = !!(ret & sca3000_addresses[chan->address][2]); } break; default: @@ -1306,7 +1306,8 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev, case IIO_MOD_X: case IIO_MOD_Y: case IIO_MOD_Z: - ret = sca3000_motion_detect_set_state(indio_dev, chan->channel2, + ret = sca3000_motion_detect_set_state(indio_dev, + chan->address, state); break; default: -- cgit v1.2.3 From 626f971b5b07298e24359999970d0f758253af1e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:12 +0100 Subject: staging:iio:accel:sca3000 Add write support to the low pass filter control Also includes an available attribute. The ordering of values appears a bit random, but as the ABI doesn't specify this and we already have both rising and falling lists I think this is fine. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index b5dc40523bb5..f5ced157ead9 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -433,6 +433,26 @@ error_ret: return ret ? ret : len; } +static ssize_t +sca3000_show_available_3db_freqs(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + int len; + + len = sprintf(buf, "%d", st->info->measurement_mode_3db_freq); + if (st->info->option_mode_1) + len += sprintf(buf + len, " %d", + st->info->option_mode_1_3db_freq); + if (st->info->option_mode_2) + len += sprintf(buf + len, " %d", + st->info->option_mode_2_3db_freq); + len += sprintf(buf + len, "\n"); + + return len; +} /** * sca3000_show_available_measurement_modes() display available modes * @@ -571,6 +591,9 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR, sca3000_store_measurement_mode, 0); +static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, + S_IRUGO, sca3000_show_available_3db_freqs, + NULL, 0); /* More standard attributes */ static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); @@ -779,6 +802,31 @@ static int sca3000_read_3db_freq(struct sca3000_state *st, int *val) } } +static int sca3000_write_3db_freq(struct sca3000_state *st, int val) +{ + int ret; + int mode; + + if (val == st->info->measurement_mode_3db_freq) + mode = SCA3000_REG_MODE_MEAS_MODE_NORMAL; + else if (st->info->option_mode_1 && + (val == st->info->option_mode_1_3db_freq)) + mode = SCA3000_REG_MODE_MEAS_MODE_OP_1; + else if (st->info->option_mode_2 && + (val == st->info->option_mode_2_3db_freq)) + mode = SCA3000_REG_MODE_MEAS_MODE_OP_2; + else + return -EINVAL; + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + return ret; + + st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK; + st->rx[0] |= (mode & SCA3000_REG_MODE_MODE_MASK); + + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]); +} + static int sca3000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -861,6 +909,12 @@ static int sca3000_write_raw(struct iio_dev *indio_dev, ret = write_raw_samp_freq(st, val); mutex_unlock(&st->lock); return ret; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + if (val2) + return -EINVAL; + mutex_lock(&st->lock); + ret = sca3000_write_3db_freq(st, val); + mutex_unlock(&st->lock); default: return -EINVAL; } @@ -1007,6 +1061,7 @@ static struct attribute *sca3000_attributes[] = { &iio_dev_attr_revision.dev_attr.attr, &iio_dev_attr_measurement_mode_available.dev_attr.attr, &iio_dev_attr_measurement_mode.dev_attr.attr, + &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, NULL, }; -- cgit v1.2.3 From 6831c17236a4ad005fb37be94bc7a18305e99bda Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:13 +0100 Subject: staging:iio:accel:sca3000 Drop custom measurement mode attributes This is now represented by the standard 3db filter frequency controls. Things get complex wrt to the sampling frequency as these modes change but that is fine under the IIO ABI where any value is allowed to effect any other. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 139 ------------------------------------ 1 file changed, 139 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index f5ced157ead9..211e1fd6c6e6 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -453,143 +453,6 @@ sca3000_show_available_3db_freqs(struct device *dev, return len; } -/** - * sca3000_show_available_measurement_modes() display available modes - * - * This is all read from chip specific data in the driver. Not all - * of the sca3000 series support modes other than normal. - **/ -static ssize_t -sca3000_show_available_measurement_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int len = 0; - - len += sprintf(buf + len, "0 - normal mode"); - switch (st->info->option_mode_1) { - case SCA3000_OP_MODE_NARROW: - len += sprintf(buf + len, ", 1 - narrow mode"); - break; - case SCA3000_OP_MODE_BYPASS: - len += sprintf(buf + len, ", 1 - bypass mode"); - break; - } - switch (st->info->option_mode_2) { - case SCA3000_OP_MODE_WIDE: - len += sprintf(buf + len, ", 2 - wide mode"); - break; - } - /* always supported */ - len += sprintf(buf + len, " 3 - motion detection\n"); - - return len; -} - -/** - * sca3000_show_measurement_mode() sysfs read of current mode - **/ -static ssize_t -sca3000_show_measurement_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int len = 0, ret; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - goto error_ret; - /* mask bottom 2 bits - only ones that are relevant */ - st->rx[0] &= SCA3000_REG_MODE_MODE_MASK; - switch (st->rx[0]) { - case SCA3000_REG_MODE_MEAS_MODE_NORMAL: - len += sprintf(buf + len, "0 - normal mode\n"); - break; - case SCA3000_REG_MODE_MEAS_MODE_MOT_DET: - len += sprintf(buf + len, "3 - motion detection\n"); - break; - case SCA3000_REG_MODE_MEAS_MODE_OP_1: - switch (st->info->option_mode_1) { - case SCA3000_OP_MODE_NARROW: - len += sprintf(buf + len, "1 - narrow mode\n"); - break; - case SCA3000_OP_MODE_BYPASS: - len += sprintf(buf + len, "1 - bypass mode\n"); - break; - } - break; - case SCA3000_REG_MODE_MEAS_MODE_OP_2: - switch (st->info->option_mode_2) { - case SCA3000_OP_MODE_WIDE: - len += sprintf(buf + len, "2 - wide mode\n"); - break; - } - break; - } - -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - -/** - * sca3000_store_measurement_mode() set the current mode - **/ -static ssize_t -sca3000_store_measurement_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - u8 val; - - mutex_lock(&st->lock); - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - if (val > 3) { - ret = -EINVAL; - goto error_ret; - } - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - goto error_ret; - st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK; - st->rx[0] |= (val & SCA3000_REG_MODE_MODE_MASK); - ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]); - if (ret) - goto error_ret; - mutex_unlock(&st->lock); - - return len; - -error_ret: - mutex_unlock(&st->lock); - - return ret; -} - -/* - * Not even vaguely standard attributes so defined here rather than - * in the relevant IIO core headers - */ -static IIO_DEVICE_ATTR(measurement_mode_available, S_IRUGO, - sca3000_show_available_measurement_modes, - NULL, 0); - -static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR, - sca3000_show_measurement_mode, - sca3000_store_measurement_mode, - 0); static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, S_IRUGO, sca3000_show_available_3db_freqs, @@ -1059,8 +922,6 @@ static int sca3000_write_event_value(struct iio_dev *indio_dev, static struct attribute *sca3000_attributes[] = { &iio_dev_attr_revision.dev_attr.attr, - &iio_dev_attr_measurement_mode_available.dev_attr.attr, - &iio_dev_attr_measurement_mode.dev_attr.attr, &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, NULL, -- cgit v1.2.3 From 7ab9fa0052878c331670ef5a2a1ef09ec3111dea Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:14 +0100 Subject: staging:iio:accel:sca3000 replace non standard revision attr with dev_info on probe There seems little point in being able to query the part revision number via sysfs. Hence just put it in the kernel logs during probe incase anyone ever wants to know. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 211e1fd6c6e6..586c120dbf41 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -411,26 +411,23 @@ error_ret: /** * sca3000_show_rev() - sysfs interface to read the chip revision number **/ -static ssize_t sca3000_show_rev(struct device *dev, - struct device_attribute *attr, - char *buf) +static int sca3000_print_rev(struct iio_dev *indio_dev) { - int len = 0, ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); + int ret; struct sca3000_state *st = iio_priv(indio_dev); mutex_lock(&st->lock); ret = sca3000_read_data_short(st, SCA3000_REG_REVID_ADDR, 1); if (ret < 0) goto error_ret; - len += sprintf(buf + len, - "major=%lu, minor=%lu\n", - st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK, - st->rx[0] & SCA3000_REG_REVID_MINOR_MASK); + dev_info(&indio_dev->dev, + "sca3000 revision major=%lu, minor=%lu\n", + st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK, + st->rx[0] & SCA3000_REG_REVID_MINOR_MASK); error_ret: mutex_unlock(&st->lock); - return ret ? ret : len; + return ret; } static ssize_t @@ -457,9 +454,6 @@ sca3000_show_available_3db_freqs(struct device *dev, static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, S_IRUGO, sca3000_show_available_3db_freqs, NULL, 0); -/* More standard attributes */ - -static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); static const struct iio_event_spec sca3000_event = { .type = IIO_EV_TYPE_MAG, @@ -921,7 +915,6 @@ static int sca3000_write_event_value(struct iio_dev *indio_dev, } static struct attribute *sca3000_attributes[] = { - &iio_dev_attr_revision.dev_attr.attr, &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, NULL, @@ -1465,6 +1458,11 @@ static int sca3000_probe(struct spi_device *spi) ret = sca3000_clean_setup(st); if (ret) goto error_free_irq; + + ret = sca3000_print_rev(indio_dev); + if (ret) + goto error_free_irq; + return 0; error_free_irq: -- cgit v1.2.3 From 9a4936dc89a34e002946a6c08b330918ec6afab8 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:15 +0100 Subject: staging:iio:accel:sca3000 Tidy up probe order to avoid a race. Previously the device was exposed to userspace and in kernel consumers before the interrupts had been configured. As nothing stopped them being enabled in the interval this could cause unhandled interrupts. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 586c120dbf41..6ffd608a2b36 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -1440,9 +1440,6 @@ static int sca3000_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; sca3000_configure_ring(indio_dev); - ret = iio_device_register(indio_dev); - if (ret < 0) - return ret; if (spi->irq) { ret = request_threaded_irq(spi->irq, @@ -1452,7 +1449,7 @@ static int sca3000_probe(struct spi_device *spi) "sca3000", indio_dev); if (ret) - goto error_unregister_dev; + return ret; } indio_dev->setup_ops = &sca3000_ring_setup_ops; ret = sca3000_clean_setup(st); @@ -1463,13 +1460,12 @@ static int sca3000_probe(struct spi_device *spi) if (ret) goto error_free_irq; - return 0; + return iio_device_register(indio_dev); error_free_irq: if (spi->irq) free_irq(spi->irq, indio_dev); -error_unregister_dev: - iio_device_unregister(indio_dev); + return ret; } @@ -1496,11 +1492,13 @@ static int sca3000_remove(struct spi_device *spi) struct iio_dev *indio_dev = spi_get_drvdata(spi); struct sca3000_state *st = iio_priv(indio_dev); + iio_device_unregister(indio_dev); + /* Must ensure no interrupts can be generated after this! */ sca3000_stop_all_interrupts(st); if (spi->irq) free_irq(spi->irq, indio_dev); - iio_device_unregister(indio_dev); + sca3000_unconfigure_ring(indio_dev); return 0; -- cgit v1.2.3 From 389c583fd8cf48a80d9352a43d50619d7bbe124c Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:16 +0100 Subject: staging:iio:accel:sca3000 small checkpatch fixes (alignment etc) Tidied up where checkpatch warning suppressions doesn't effect the readability of the code. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index 6ffd608a2b36..c0542f3d18dd 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -275,8 +275,8 @@ static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val) } static int sca3000_read_data_short(struct sca3000_state *st, - u8 reg_address_high, - int len) + u8 reg_address_high, + int len) { struct spi_transfer xfer[2] = { { -- cgit v1.2.3 From 2ccf61442ff142d2dde7c47471c2798a4d78b0ad Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:17 +0100 Subject: staging:iio:accel:sca3000 kernel docify comments that were nearly kernel doc. Basic tidy up of comments to bring them into a standard style. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/staging/iio/accel/sca3000.c | 106 ++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c index c0542f3d18dd..cb1d83fa19a0 100644 --- a/drivers/staging/iio/accel/sca3000.c +++ b/drivers/staging/iio/accel/sca3000.c @@ -179,10 +179,20 @@ struct sca3000_state { * @scale: scale * 10^-6 * @temp_output: some devices have temperature sensors. * @measurement_mode_freq: normal mode sampling frequency + * @measurement_mode_3db_freq: 3db cutoff frequency of the low pass filter for + * the normal measurement mode. * @option_mode_1: first optional mode. Not all models have one * @option_mode_1_freq: option mode 1 sampling frequency + * @option_mode_1_3db_freq: 3db cutoff frequency of the low pass filter for + * the first option mode. * @option_mode_2: second optional mode. Not all chips have one * @option_mode_2_freq: option mode 2 sampling frequency + * @option_mode_2_3db_freq: 3db cutoff frequency of the low pass filter for + * the second option mode. + * @mod_det_mult_xz: Bit wise multipliers to calculate the threshold + * for motion detection in the x and z axis. + * @mod_det_mult_y: Bit wise multipliers to calculate the threshold + * for motion detection in the y axis. * * This structure is used to hold information about the functionality of a given * sca3000 variant. @@ -293,7 +303,8 @@ static int sca3000_read_data_short(struct sca3000_state *st, } /** - * sca3000_reg_lock_on() test if the ctrl register lock is on + * sca3000_reg_lock_on() - test if the ctrl register lock is on + * @st: Driver specific device instance data. * * Lock must be held. **/ @@ -309,12 +320,13 @@ static int sca3000_reg_lock_on(struct sca3000_state *st) } /** - * __sca3000_unlock_reg_lock() unlock the control registers + * __sca3000_unlock_reg_lock() - unlock the control registers + * @st: Driver specific device instance data. * * Note the device does not appear to support doing this in a single transfer. * This should only ever be used as part of ctrl reg read. * Lock must be held before calling this - **/ + */ static int __sca3000_unlock_reg_lock(struct sca3000_state *st) { struct spi_transfer xfer[3] = { @@ -343,6 +355,7 @@ static int __sca3000_unlock_reg_lock(struct sca3000_state *st) /** * sca3000_write_ctrl_reg() write to a lock protect ctrl register + * @st: Driver specific device instance data. * @sel: selects which registers we wish to write to * @val: the value to be written * @@ -350,7 +363,7 @@ static int __sca3000_unlock_reg_lock(struct sca3000_state *st) * register and use a shared write address. This function allows writing of * these registers. * Lock must be held. - **/ + */ static int sca3000_write_ctrl_reg(struct sca3000_state *st, u8 sel, uint8_t val) @@ -380,9 +393,11 @@ error_ret: /** * sca3000_read_ctrl_reg() read from lock protected control register. + * @st: Driver specific device instance data. + * @ctrl_reg: Which ctrl register do we want to read. * * Lock must be held. - **/ + */ static int sca3000_read_ctrl_reg(struct sca3000_state *st, u8 ctrl_reg) { @@ -410,7 +425,10 @@ error_ret: /** * sca3000_show_rev() - sysfs interface to read the chip revision number - **/ + * @indio_dev: Device instance specific generic IIO data. + * Driver specific device instance data can be obtained via + * via iio_priv(indio_dev) + */ static int sca3000_print_rev(struct iio_dev *indio_dev) { int ret; @@ -540,10 +558,13 @@ static u8 sca3000_addresses[3][3] = { }; /** - * __sca3000_get_base_freq() obtain mode specific base frequency + * __sca3000_get_base_freq() - obtain mode specific base frequency + * @st: Private driver specific device instance specific state. + * @info: chip type specific information. + * @base_freq: Base frequency for the current measurement mode. * * lock must be held - **/ + */ static inline int __sca3000_get_base_freq(struct sca3000_state *st, const struct sca3000_chip_info *info, int *base_freq) @@ -571,11 +592,13 @@ error_ret: } /** - * read_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * sca3000_read_raw_samp_freq() - read_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * @st: Private driver specific device instance specific state. + * @val: The frequency read back. * * lock must be held **/ -static int read_raw_samp_freq(struct sca3000_state *st, int *val) +static int sca3000_read_raw_samp_freq(struct sca3000_state *st, int *val) { int ret; @@ -603,11 +626,13 @@ static int read_raw_samp_freq(struct sca3000_state *st, int *val) } /** - * write_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * sca3000_write_raw_samp_freq() - write_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * @st: Private driver specific device instance specific state. + * @val: The frequency desired. * * lock must be held - **/ -static int write_raw_samp_freq(struct sca3000_state *st, int val) + */ +static int sca3000_write_raw_samp_freq(struct sca3000_state *st, int val) { int ret, base_freq, ctrlval; @@ -738,7 +763,7 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: mutex_lock(&st->lock); - ret = read_raw_samp_freq(st, val); + ret = sca3000_read_raw_samp_freq(st, val); mutex_unlock(&st->lock); return ret ? ret : IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: @@ -763,7 +788,7 @@ static int sca3000_write_raw(struct iio_dev *indio_dev, if (val2) return -EINVAL; mutex_lock(&st->lock); - ret = write_raw_samp_freq(st, val); + ret = sca3000_write_raw_samp_freq(st, val); mutex_unlock(&st->lock); return ret; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: @@ -780,7 +805,10 @@ static int sca3000_write_raw(struct iio_dev *indio_dev, } /** - * sca3000_read_av_freq() sysfs function to get available frequencies + * sca3000_read_av_freq() - sysfs function to get available frequencies + * @dev: Device structure for this device. + * @attr: Description of the attribute. + * @buf: Incoming string * * The later modes are only relevant to the ring buffer - and depend on current * mode. Note that data sheet gives rather wide tolerances for these so integer @@ -875,8 +903,18 @@ static int sca3000_read_event_value(struct iio_dev *indio_dev, } /** - * sca3000_write_value() control of threshold and period - **/ + * sca3000_write_value() - control of threshold and period + * @indio_dev: Device instance specific IIO information. + * @chan: Description of the channel for which the event is being + * configured. + * @type: The type of event being configured, here magnitude rising + * as everything else is read only. + * @dir: Direction of the event (here rising) + * @info: What information about the event are we configuring. + * Here the threshold only. + * @val: Integer part of the value being written.. + * @val2: Non integer part of the value being written. Here always 0. + */ static int sca3000_write_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -951,11 +989,10 @@ static int sca3000_read_data(struct sca3000_state *st, } /** - * sca3000_ring_int_process() ring specific interrupt handling. - * - * This is only split from the main interrupt handler so as to - * reduce the amount of code if the ring buffer is not enabled. - **/ + * sca3000_ring_int_process() - ring specific interrupt handling. + * @val: Value of the interrupt status register. + * @indio_dev: Device instance specific IIO device structure. + */ static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev) { struct sca3000_state *st = iio_priv(indio_dev); @@ -994,6 +1031,8 @@ error_ret: /** * sca3000_event_handler() - handling ring and non ring events + * @irq: The irq being handled. + * @private: struct iio_device pointer for the device. * * Ring related interrupt handler. Depending on event, push to * the ring buffer event chrdev or the event one. @@ -1001,7 +1040,7 @@ error_ret: * This function is complicated by the fact that the devices can signify ring * and non ring events via the same interrupt line and they can only * be distinguished via a read of the relevant status register. - **/ + */ static irqreturn_t sca3000_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; @@ -1189,7 +1228,13 @@ static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis, } /** - * sca3000_write_event_config() simple on off control for motion detector + * sca3000_write_event_config() - simple on off control for motion detector + * @indio_dev: IIO device instance specific structure. Data specific to this + * particular driver may be accessed via iio_priv(indio_dev). + * @chan: Description of the channel whose event we are configuring. + * @type: The type of event. + * @dir: The direction of the event. + * @state: Desired state of event being configured. * * This is a per axis control, but enabling any will result in the * motion detector unit being enabled. @@ -1273,12 +1318,14 @@ error_ret: } /** - * sca3000_hw_ring_preenable() hw ring buffer preenable function + * sca3000_hw_ring_preenable() - hw ring buffer preenable function + * @indio_dev: structure representing the IIO device. Device instance + * specific state can be accessed via iio_priv(indio_dev). * * Very simple enable function as the chip will allows normal reads * during ring buffer operation so as long as it is indeed running * before we notify the core, the precise ordering does not matter. - **/ + */ static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) { int ret; @@ -1335,12 +1382,13 @@ static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { }; /** - * sca3000_clean_setup() get the device into a predictable state + * sca3000_clean_setup() - get the device into a predictable state + * @st: Device instance specific private data structure * * Devices use flash memory to store many of the register values * and hence can come up in somewhat unpredictable states. * Hence reset everything on driver load. - **/ + */ static int sca3000_clean_setup(struct sca3000_state *st) { int ret; -- cgit v1.2.3 From d62e5fee88e26044a48d4b5632c4f89936041d92 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 8 Oct 2016 17:39:18 +0100 Subject: staging:iio:accel:sca3000 Move out of staging. Now the driver is in a reasonable state, lets get it (finally) out of staging. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/iio/accel/Kconfig | 12 + drivers/iio/accel/Makefile | 2 + drivers/iio/accel/sca3000.c | 1576 +++++++++++++++++++++++++++++++++++ drivers/staging/iio/accel/Kconfig | 11 - drivers/staging/iio/accel/Makefile | 2 - drivers/staging/iio/accel/sca3000.c | 1576 ----------------------------------- 6 files changed, 1590 insertions(+), 1589 deletions(-) create mode 100644 drivers/iio/accel/sca3000.c delete mode 100644 drivers/staging/iio/accel/sca3000.c (limited to 'drivers') diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 878e3c9449de..c6cc2c0909a1 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -303,6 +303,18 @@ config MXC6255 To compile this driver as a module, choose M here: the module will be called mxc6255. +config SCA3000 + select IIO_BUFFER + select IIO_KFIFO_BUF + depends on SPI + tristate "VTI SCA3000 series accelerometers" + help + Say Y here to build support for the VTI SCA3000 series of SPI + accelerometers. These devices use a hardware ring buffer. + + To compile this driver as a module, say M here: the module will be + called sca3000. + config STK8312 tristate "Sensortek STK8312 3-Axis Accelerometer Driver" depends on I2C diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 0aa574957047..69fe8edc57a2 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -35,6 +35,8 @@ obj-$(CONFIG_MMA9553) += mma9553.o obj-$(CONFIG_MXC4005) += mxc4005.o obj-$(CONFIG_MXC6255) += mxc6255.o +obj-$(CONFIG_SCA3000) += sca3000.o + obj-$(CONFIG_STK8312) += stk8312.o obj-$(CONFIG_STK8BA50) += stk8ba50.o diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c new file mode 100644 index 000000000000..cb1d83fa19a0 --- /dev/null +++ b/drivers/iio/accel/sca3000.c @@ -0,0 +1,1576 @@ +/* + * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Copyright (c) 2009 Jonathan Cameron + * + * See industrialio/accels/sca3000.h for comments. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02) +#define SCA3000_READ_REG(a) ((a) << 2) + +#define SCA3000_REG_REVID_ADDR 0x00 +#define SCA3000_REG_REVID_MAJOR_MASK GENMASK(8, 4) +#define SCA3000_REG_REVID_MINOR_MASK GENMASK(3, 0) + +#define SCA3000_REG_STATUS_ADDR 0x02 +#define SCA3000_LOCKED BIT(5) +#define SCA3000_EEPROM_CS_ERROR BIT(1) +#define SCA3000_SPI_FRAME_ERROR BIT(0) + +/* All reads done using register decrement so no need to directly access LSBs */ +#define SCA3000_REG_X_MSB_ADDR 0x05 +#define SCA3000_REG_Y_MSB_ADDR 0x07 +#define SCA3000_REG_Z_MSB_ADDR 0x09 + +#define SCA3000_REG_RING_OUT_ADDR 0x0f + +/* Temp read untested - the e05 doesn't have the sensor */ +#define SCA3000_REG_TEMP_MSB_ADDR 0x13 + +#define SCA3000_REG_MODE_ADDR 0x14 +#define SCA3000_MODE_PROT_MASK 0x28 +#define SCA3000_REG_MODE_RING_BUF_ENABLE BIT(7) +#define SCA3000_REG_MODE_RING_BUF_8BIT BIT(6) + +/* + * Free fall detection triggers an interrupt if the acceleration + * is below a threshold for equivalent of 25cm drop + */ +#define SCA3000_REG_MODE_FREE_FALL_DETECT BIT(4) +#define SCA3000_REG_MODE_MEAS_MODE_NORMAL 0x00 +#define SCA3000_REG_MODE_MEAS_MODE_OP_1 0x01 +#define SCA3000_REG_MODE_MEAS_MODE_OP_2 0x02 + +/* + * In motion detection mode the accelerations are band pass filtered + * (approx 1 - 25Hz) and then a programmable threshold used to trigger + * and interrupt. + */ +#define SCA3000_REG_MODE_MEAS_MODE_MOT_DET 0x03 +#define SCA3000_REG_MODE_MODE_MASK 0x03 + +#define SCA3000_REG_BUF_COUNT_ADDR 0x15 + +#define SCA3000_REG_INT_STATUS_ADDR 0x16 +#define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7) +#define SCA3000_REG_INT_STATUS_HALF BIT(6) + +#define SCA3000_INT_STATUS_FREE_FALL BIT(3) +#define SCA3000_INT_STATUS_Y_TRIGGER BIT(2) +#define SCA3000_INT_STATUS_X_TRIGGER BIT(1) +#define SCA3000_INT_STATUS_Z_TRIGGER BIT(0) + +/* Used to allow access to multiplexed registers */ +#define SCA3000_REG_CTRL_SEL_ADDR 0x18 +/* Only available for SCA3000-D03 and SCA3000-D01 */ +#define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01 +#define SCA3000_REG_CTRL_SEL_MD_CTRL 0x02 +#define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03 +#define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04 +#define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05 +/* + * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device + * will not function + */ +#define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B + +#define SCA3000_REG_OUT_CTRL_PROT_MASK 0xE0 +#define SCA3000_REG_OUT_CTRL_BUF_X_EN 0x10 +#define SCA3000_REG_OUT_CTRL_BUF_Y_EN 0x08 +#define SCA3000_REG_OUT_CTRL_BUF_Z_EN 0x04 +#define SCA3000_REG_OUT_CTRL_BUF_DIV_MASK 0x03 +#define SCA3000_REG_OUT_CTRL_BUF_DIV_4 0x02 +#define SCA3000_REG_OUT_CTRL_BUF_DIV_2 0x01 + + +/* + * Control which motion detector interrupts are on. + * For now only OR combinations are supported. + */ +#define SCA3000_MD_CTRL_PROT_MASK 0xC0 +#define SCA3000_MD_CTRL_OR_Y BIT(0) +#define SCA3000_MD_CTRL_OR_X BIT(1) +#define SCA3000_MD_CTRL_OR_Z BIT(2) +/* Currently unsupported */ +#define SCA3000_MD_CTRL_AND_Y BIT(3) +#define SCA3000_MD_CTRL_AND_X BIT(4) +#define SAC3000_MD_CTRL_AND_Z BIT(5) + +/* + * Some control registers of complex access methods requiring this register to + * be used to remove a lock. + */ +#define SCA3000_REG_UNLOCK_ADDR 0x1e + +#define SCA3000_REG_INT_MASK_ADDR 0x21 +#define SCA3000_REG_INT_MASK_PROT_MASK 0x1C + +#define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7) +#define SCA3000_REG_INT_MASK_RING_HALF BIT(6) + +#define SCA3000_REG_INT_MASK_ALL_INTS 0x02 +#define SCA3000_REG_INT_MASK_ACTIVE_HIGH 0x01 +#define SCA3000_REG_INT_MASK_ACTIVE_LOW 0x00 +/* Values of multiplexed registers (write to ctrl_data after select) */ +#define SCA3000_REG_CTRL_DATA_ADDR 0x22 + +/* + * Measurement modes available on some sca3000 series chips. Code assumes others + * may become available in the future. + * + * Bypass - Bypass the low-pass filter in the signal channel so as to increase + * signal bandwidth. + * + * Narrow - Narrow low-pass filtering of the signal channel and half output + * data rate by decimation. + * + * Wide - Widen low-pass filtering of signal channel to increase bandwidth + */ +#define SCA3000_OP_MODE_BYPASS 0x01 +#define SCA3000_OP_MODE_NARROW 0x02 +#define SCA3000_OP_MODE_WIDE 0x04 +#define SCA3000_MAX_TX 6 +#define SCA3000_MAX_RX 2 + +/** + * struct sca3000_state - device instance state information + * @us: the associated spi device + * @info: chip variant information + * @last_timestamp: the timestamp of the last event + * @mo_det_use_count: reference counter for the motion detection unit + * @lock: lock used to protect elements of sca3000_state + * and the underlying device state. + * @tx: dma-able transmit buffer + * @rx: dma-able receive buffer + **/ +struct sca3000_state { + struct spi_device *us; + const struct sca3000_chip_info *info; + s64 last_timestamp; + int mo_det_use_count; + struct mutex lock; + /* Can these share a cacheline ? */ + u8 rx[384] ____cacheline_aligned; + u8 tx[6] ____cacheline_aligned; +}; + +/** + * struct sca3000_chip_info - model dependent parameters + * @scale: scale * 10^-6 + * @temp_output: some devices have temperature sensors. + * @measurement_mode_freq: normal mode sampling frequency + * @measurement_mode_3db_freq: 3db cutoff frequency of the low pass filter for + * the normal measurement mode. + * @option_mode_1: first optional mode. Not all models have one + * @option_mode_1_freq: option mode 1 sampling frequency + * @option_mode_1_3db_freq: 3db cutoff frequency of the low pass filter for + * the first option mode. + * @option_mode_2: second optional mode. Not all chips have one + * @option_mode_2_freq: option mode 2 sampling frequency + * @option_mode_2_3db_freq: 3db cutoff frequency of the low pass filter for + * the second option mode. + * @mod_det_mult_xz: Bit wise multipliers to calculate the threshold + * for motion detection in the x and z axis. + * @mod_det_mult_y: Bit wise multipliers to calculate the threshold + * for motion detection in the y axis. + * + * This structure is used to hold information about the functionality of a given + * sca3000 variant. + **/ +struct sca3000_chip_info { + unsigned int scale; + bool temp_output; + int measurement_mode_freq; + int measurement_mode_3db_freq; + int option_mode_1; + int option_mode_1_freq; + int option_mode_1_3db_freq; + int option_mode_2; + int option_mode_2_freq; + int option_mode_2_3db_freq; + int mot_det_mult_xz[6]; + int mot_det_mult_y[7]; +}; + +enum sca3000_variant { + d01, + e02, + e04, + e05, +}; + +/* + * Note where option modes are not defined, the chip simply does not + * support any. + * Other chips in the sca3000 series use i2c and are not included here. + * + * Some of these devices are only listed in the family data sheet and + * do not actually appear to be available. + */ +static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = { + [d01] = { + .scale = 7357, + .temp_output = true, + .measurement_mode_freq = 250, + .measurement_mode_3db_freq = 45, + .option_mode_1 = SCA3000_OP_MODE_BYPASS, + .option_mode_1_freq = 250, + .option_mode_1_3db_freq = 70, + .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300}, + .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750}, + }, + [e02] = { + .scale = 9810, + .measurement_mode_freq = 125, + .measurement_mode_3db_freq = 40, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 63, + .option_mode_1_3db_freq = 11, + .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050}, + .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700}, + }, + [e04] = { + .scale = 19620, + .measurement_mode_freq = 100, + .measurement_mode_3db_freq = 38, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 50, + .option_mode_1_3db_freq = 9, + .option_mode_2 = SCA3000_OP_MODE_WIDE, + .option_mode_2_freq = 400, + .option_mode_2_3db_freq = 70, + .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100}, + .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000}, + }, + [e05] = { + .scale = 61313, + .measurement_mode_freq = 200, + .measurement_mode_3db_freq = 60, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 50, + .option_mode_1_3db_freq = 9, + .option_mode_2 = SCA3000_OP_MODE_WIDE, + .option_mode_2_freq = 400, + .option_mode_2_3db_freq = 75, + .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900}, + .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600}, + }, +}; + +static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val) +{ + st->tx[0] = SCA3000_WRITE_REG(address); + st->tx[1] = val; + return spi_write(st->us, st->tx, 2); +} + +static int sca3000_read_data_short(struct sca3000_state *st, + u8 reg_address_high, + int len) +{ + struct spi_transfer xfer[2] = { + { + .len = 1, + .tx_buf = st->tx, + }, { + .len = len, + .rx_buf = st->rx, + } + }; + st->tx[0] = SCA3000_READ_REG(reg_address_high); + + return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); +} + +/** + * sca3000_reg_lock_on() - test if the ctrl register lock is on + * @st: Driver specific device instance data. + * + * Lock must be held. + **/ +static int sca3000_reg_lock_on(struct sca3000_state *st) +{ + int ret; + + ret = sca3000_read_data_short(st, SCA3000_REG_STATUS_ADDR, 1); + if (ret < 0) + return ret; + + return !(st->rx[0] & SCA3000_LOCKED); +} + +/** + * __sca3000_unlock_reg_lock() - unlock the control registers + * @st: Driver specific device instance data. + * + * Note the device does not appear to support doing this in a single transfer. + * This should only ever be used as part of ctrl reg read. + * Lock must be held before calling this + */ +static int __sca3000_unlock_reg_lock(struct sca3000_state *st) +{ + struct spi_transfer xfer[3] = { + { + .len = 2, + .cs_change = 1, + .tx_buf = st->tx, + }, { + .len = 2, + .cs_change = 1, + .tx_buf = st->tx + 2, + }, { + .len = 2, + .tx_buf = st->tx + 4, + }, + }; + st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); + st->tx[1] = 0x00; + st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); + st->tx[3] = 0x50; + st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); + st->tx[5] = 0xA0; + + return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); +} + +/** + * sca3000_write_ctrl_reg() write to a lock protect ctrl register + * @st: Driver specific device instance data. + * @sel: selects which registers we wish to write to + * @val: the value to be written + * + * Certain control registers are protected against overwriting by the lock + * register and use a shared write address. This function allows writing of + * these registers. + * Lock must be held. + */ +static int sca3000_write_ctrl_reg(struct sca3000_state *st, + u8 sel, + uint8_t val) +{ + int ret; + + ret = sca3000_reg_lock_on(st); + if (ret < 0) + goto error_ret; + if (ret) { + ret = __sca3000_unlock_reg_lock(st); + if (ret) + goto error_ret; + } + + /* Set the control select register */ + ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, sel); + if (ret) + goto error_ret; + + /* Write the actual value into the register */ + ret = sca3000_write_reg(st, SCA3000_REG_CTRL_DATA_ADDR, val); + +error_ret: + return ret; +} + +/** + * sca3000_read_ctrl_reg() read from lock protected control register. + * @st: Driver specific device instance data. + * @ctrl_reg: Which ctrl register do we want to read. + * + * Lock must be held. + */ +static int sca3000_read_ctrl_reg(struct sca3000_state *st, + u8 ctrl_reg) +{ + int ret; + + ret = sca3000_reg_lock_on(st); + if (ret < 0) + goto error_ret; + if (ret) { + ret = __sca3000_unlock_reg_lock(st); + if (ret) + goto error_ret; + } + /* Set the control select register */ + ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, ctrl_reg); + if (ret) + goto error_ret; + ret = sca3000_read_data_short(st, SCA3000_REG_CTRL_DATA_ADDR, 1); + if (ret) + goto error_ret; + return st->rx[0]; +error_ret: + return ret; +} + +/** + * sca3000_show_rev() - sysfs interface to read the chip revision number + * @indio_dev: Device instance specific generic IIO data. + * Driver specific device instance data can be obtained via + * via iio_priv(indio_dev) + */ +static int sca3000_print_rev(struct iio_dev *indio_dev) +{ + int ret; + struct sca3000_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_REVID_ADDR, 1); + if (ret < 0) + goto error_ret; + dev_info(&indio_dev->dev, + "sca3000 revision major=%lu, minor=%lu\n", + st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK, + st->rx[0] & SCA3000_REG_REVID_MINOR_MASK); +error_ret: + mutex_unlock(&st->lock); + + return ret; +} + +static ssize_t +sca3000_show_available_3db_freqs(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + int len; + + len = sprintf(buf, "%d", st->info->measurement_mode_3db_freq); + if (st->info->option_mode_1) + len += sprintf(buf + len, " %d", + st->info->option_mode_1_3db_freq); + if (st->info->option_mode_2) + len += sprintf(buf + len, " %d", + st->info->option_mode_2_3db_freq); + len += sprintf(buf + len, "\n"); + + return len; +} + +static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, + S_IRUGO, sca3000_show_available_3db_freqs, + NULL, 0); + +static const struct iio_event_spec sca3000_event = { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; + +/* + * Note the hack in the number of bits to pretend we have 2 more than + * we do in the fifo. + */ +#define SCA3000_CHAN(index, mod) \ + { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = mod, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |\ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),\ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 13, \ + .storagebits = 16, \ + .shift = 3, \ + .endianness = IIO_BE, \ + }, \ + .event_spec = &sca3000_event, \ + .num_event_specs = 1, \ + } + +static const struct iio_event_spec sca3000_freefall_event_spec = { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD), +}; + +static const struct iio_chan_spec sca3000_channels[] = { + SCA3000_CHAN(0, IIO_MOD_X), + SCA3000_CHAN(1, IIO_MOD_Y), + SCA3000_CHAN(2, IIO_MOD_Z), + { + .type = IIO_ACCEL, + .modified = 1, + .channel2 = IIO_MOD_X_AND_Y_AND_Z, + .scan_index = -1, /* Fake channel */ + .event_spec = &sca3000_freefall_event_spec, + .num_event_specs = 1, + }, +}; + +static const struct iio_chan_spec sca3000_channels_with_temp[] = { + SCA3000_CHAN(0, IIO_MOD_X), + SCA3000_CHAN(1, IIO_MOD_Y), + SCA3000_CHAN(2, IIO_MOD_Z), + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + /* No buffer support */ + .scan_index = -1, + }, + { + .type = IIO_ACCEL, + .modified = 1, + .channel2 = IIO_MOD_X_AND_Y_AND_Z, + .scan_index = -1, /* Fake channel */ + .event_spec = &sca3000_freefall_event_spec, + .num_event_specs = 1, + }, +}; + +static u8 sca3000_addresses[3][3] = { + [0] = {SCA3000_REG_X_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_X_TH, + SCA3000_MD_CTRL_OR_X}, + [1] = {SCA3000_REG_Y_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Y_TH, + SCA3000_MD_CTRL_OR_Y}, + [2] = {SCA3000_REG_Z_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Z_TH, + SCA3000_MD_CTRL_OR_Z}, +}; + +/** + * __sca3000_get_base_freq() - obtain mode specific base frequency + * @st: Private driver specific device instance specific state. + * @info: chip type specific information. + * @base_freq: Base frequency for the current measurement mode. + * + * lock must be held + */ +static inline int __sca3000_get_base_freq(struct sca3000_state *st, + const struct sca3000_chip_info *info, + int *base_freq) +{ + int ret; + + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + goto error_ret; + switch (SCA3000_REG_MODE_MODE_MASK & st->rx[0]) { + case SCA3000_REG_MODE_MEAS_MODE_NORMAL: + *base_freq = info->measurement_mode_freq; + break; + case SCA3000_REG_MODE_MEAS_MODE_OP_1: + *base_freq = info->option_mode_1_freq; + break; + case SCA3000_REG_MODE_MEAS_MODE_OP_2: + *base_freq = info->option_mode_2_freq; + break; + default: + ret = -EINVAL; + } +error_ret: + return ret; +} + +/** + * sca3000_read_raw_samp_freq() - read_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * @st: Private driver specific device instance specific state. + * @val: The frequency read back. + * + * lock must be held + **/ +static int sca3000_read_raw_samp_freq(struct sca3000_state *st, int *val) +{ + int ret; + + ret = __sca3000_get_base_freq(st, st->info, val); + if (ret) + return ret; + + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + return ret; + + if (*val > 0) { + ret &= SCA3000_REG_OUT_CTRL_BUF_DIV_MASK; + switch (ret) { + case SCA3000_REG_OUT_CTRL_BUF_DIV_2: + *val /= 2; + break; + case SCA3000_REG_OUT_CTRL_BUF_DIV_4: + *val /= 4; + break; + } + } + + return 0; +} + +/** + * sca3000_write_raw_samp_freq() - write_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * @st: Private driver specific device instance specific state. + * @val: The frequency desired. + * + * lock must be held + */ +static int sca3000_write_raw_samp_freq(struct sca3000_state *st, int val) +{ + int ret, base_freq, ctrlval; + + ret = __sca3000_get_base_freq(st, st->info, &base_freq); + if (ret) + return ret; + + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + return ret; + + ctrlval = ret & ~SCA3000_REG_OUT_CTRL_BUF_DIV_MASK; + + if (val == base_freq / 2) + ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_2; + if (val == base_freq / 4) + ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_4; + else if (val != base_freq) + return -EINVAL; + + return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, + ctrlval); +} + +static int sca3000_read_3db_freq(struct sca3000_state *st, int *val) +{ + int ret; + + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + return ret; + + /* mask bottom 2 bits - only ones that are relevant */ + st->rx[0] &= SCA3000_REG_MODE_MODE_MASK; + switch (st->rx[0]) { + case SCA3000_REG_MODE_MEAS_MODE_NORMAL: + *val = st->info->measurement_mode_3db_freq; + return IIO_VAL_INT; + case SCA3000_REG_MODE_MEAS_MODE_MOT_DET: + return -EBUSY; + case SCA3000_REG_MODE_MEAS_MODE_OP_1: + *val = st->info->option_mode_1_3db_freq; + return IIO_VAL_INT; + case SCA3000_REG_MODE_MEAS_MODE_OP_2: + *val = st->info->option_mode_2_3db_freq; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int sca3000_write_3db_freq(struct sca3000_state *st, int val) +{ + int ret; + int mode; + + if (val == st->info->measurement_mode_3db_freq) + mode = SCA3000_REG_MODE_MEAS_MODE_NORMAL; + else if (st->info->option_mode_1 && + (val == st->info->option_mode_1_3db_freq)) + mode = SCA3000_REG_MODE_MEAS_MODE_OP_1; + else if (st->info->option_mode_2 && + (val == st->info->option_mode_2_3db_freq)) + mode = SCA3000_REG_MODE_MEAS_MODE_OP_2; + else + return -EINVAL; + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + return ret; + + st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK; + st->rx[0] |= (mode & SCA3000_REG_MODE_MODE_MASK); + + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]); +} + +static int sca3000_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + u8 address; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&st->lock); + if (chan->type == IIO_ACCEL) { + if (st->mo_det_use_count) { + mutex_unlock(&st->lock); + return -EBUSY; + } + address = sca3000_addresses[chan->address][0]; + ret = sca3000_read_data_short(st, address, 2); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + *val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF; + *val = ((*val) << (sizeof(*val) * 8 - 13)) >> + (sizeof(*val) * 8 - 13); + } else { + /* get the temperature when available */ + ret = sca3000_read_data_short(st, + SCA3000_REG_TEMP_MSB_ADDR, + 2); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + *val = ((st->rx[0] & 0x3F) << 3) | + ((st->rx[1] & 0xE0) >> 5); + } + mutex_unlock(&st->lock); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + if (chan->type == IIO_ACCEL) + *val2 = st->info->scale; + else /* temperature */ + *val2 = 555556; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = -214; + *val2 = 600000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&st->lock); + ret = sca3000_read_raw_samp_freq(st, val); + mutex_unlock(&st->lock); + return ret ? ret : IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + mutex_lock(&st->lock); + ret = sca3000_read_3db_freq(st, val); + mutex_unlock(&st->lock); + return ret; + default: + return -EINVAL; + } +} + +static int sca3000_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&st->lock); + ret = sca3000_write_raw_samp_freq(st, val); + mutex_unlock(&st->lock); + return ret; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + if (val2) + return -EINVAL; + mutex_lock(&st->lock); + ret = sca3000_write_3db_freq(st, val); + mutex_unlock(&st->lock); + default: + return -EINVAL; + } + + return ret; +} + +/** + * sca3000_read_av_freq() - sysfs function to get available frequencies + * @dev: Device structure for this device. + * @attr: Description of the attribute. + * @buf: Incoming string + * + * The later modes are only relevant to the ring buffer - and depend on current + * mode. Note that data sheet gives rather wide tolerances for these so integer + * division will give good enough answer and not all chips have them specified + * at all. + **/ +static ssize_t sca3000_read_av_freq(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sca3000_state *st = iio_priv(indio_dev); + int len = 0, ret, val; + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + val = st->rx[0]; + mutex_unlock(&st->lock); + if (ret) + goto error_ret; + + switch (val & SCA3000_REG_MODE_MODE_MASK) { + case SCA3000_REG_MODE_MEAS_MODE_NORMAL: + len += sprintf(buf + len, "%d %d %d\n", + st->info->measurement_mode_freq, + st->info->measurement_mode_freq / 2, + st->info->measurement_mode_freq / 4); + break; + case SCA3000_REG_MODE_MEAS_MODE_OP_1: + len += sprintf(buf + len, "%d %d %d\n", + st->info->option_mode_1_freq, + st->info->option_mode_1_freq / 2, + st->info->option_mode_1_freq / 4); + break; + case SCA3000_REG_MODE_MEAS_MODE_OP_2: + len += sprintf(buf + len, "%d %d %d\n", + st->info->option_mode_2_freq, + st->info->option_mode_2_freq / 2, + st->info->option_mode_2_freq / 4); + break; + } + return len; +error_ret: + return ret; +} + +/* + * Should only really be registered if ring buffer support is compiled in. + * Does no harm however and doing it right would add a fair bit of complexity + */ +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); + +/** + * sca3000_read_event_value() - query of a threshold or period + **/ +static int sca3000_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + int ret, i; + struct sca3000_state *st = iio_priv(indio_dev); + + switch (info) { + case IIO_EV_INFO_VALUE: + mutex_lock(&st->lock); + ret = sca3000_read_ctrl_reg(st, + sca3000_addresses[chan->address][1]); + mutex_unlock(&st->lock); + if (ret < 0) + return ret; + *val = 0; + if (chan->channel2 == IIO_MOD_Y) + for_each_set_bit(i, (unsigned long *)&ret, + ARRAY_SIZE(st->info->mot_det_mult_y)) + *val += st->info->mot_det_mult_y[i]; + else + for_each_set_bit(i, (unsigned long *)&ret, + ARRAY_SIZE(st->info->mot_det_mult_xz)) + *val += st->info->mot_det_mult_xz[i]; + + return IIO_VAL_INT; + case IIO_EV_INFO_PERIOD: + *val = 0; + *val2 = 226000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +/** + * sca3000_write_value() - control of threshold and period + * @indio_dev: Device instance specific IIO information. + * @chan: Description of the channel for which the event is being + * configured. + * @type: The type of event being configured, here magnitude rising + * as everything else is read only. + * @dir: Direction of the event (here rising) + * @info: What information about the event are we configuring. + * Here the threshold only. + * @val: Integer part of the value being written.. + * @val2: Non integer part of the value being written. Here always 0. + */ +static int sca3000_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + int i; + u8 nonlinear = 0; + + if (chan->channel2 == IIO_MOD_Y) { + i = ARRAY_SIZE(st->info->mot_det_mult_y); + while (i > 0) + if (val >= st->info->mot_det_mult_y[--i]) { + nonlinear |= (1 << i); + val -= st->info->mot_det_mult_y[i]; + } + } else { + i = ARRAY_SIZE(st->info->mot_det_mult_xz); + while (i > 0) + if (val >= st->info->mot_det_mult_xz[--i]) { + nonlinear |= (1 << i); + val -= st->info->mot_det_mult_xz[i]; + } + } + + mutex_lock(&st->lock); + ret = sca3000_write_ctrl_reg(st, + sca3000_addresses[chan->address][1], + nonlinear); + mutex_unlock(&st->lock); + + return ret; +} + +static struct attribute *sca3000_attributes[] = { + &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group sca3000_attribute_group = { + .attrs = sca3000_attributes, +}; + +static int sca3000_read_data(struct sca3000_state *st, + u8 reg_address_high, + u8 *rx, + int len) +{ + int ret; + struct spi_transfer xfer[2] = { + { + .len = 1, + .tx_buf = st->tx, + }, { + .len = len, + .rx_buf = rx, + } + }; + + st->tx[0] = SCA3000_READ_REG(reg_address_high); + ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); + if (ret) { + dev_err(get_device(&st->us->dev), "problem reading register"); + return ret; + } + + return 0; +} + +/** + * sca3000_ring_int_process() - ring specific interrupt handling. + * @val: Value of the interrupt status register. + * @indio_dev: Device instance specific IIO device structure. + */ +static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret, i, num_available; + + mutex_lock(&st->lock); + + if (val & SCA3000_REG_INT_STATUS_HALF) { + ret = sca3000_read_data_short(st, SCA3000_REG_BUF_COUNT_ADDR, + 1); + if (ret) + goto error_ret; + num_available = st->rx[0]; + /* + * num_available is the total number of samples available + * i.e. number of time points * number of channels. + */ + ret = sca3000_read_data(st, SCA3000_REG_RING_OUT_ADDR, st->rx, + num_available * 2); + if (ret) + goto error_ret; + for (i = 0; i < num_available / 3; i++) { + /* + * Dirty hack to cover for 11 bit in fifo, 13 bit + * direct reading. + * + * In theory the bottom two bits are undefined. + * In reality they appear to always be 0. + */ + iio_push_to_buffers(indio_dev, st->rx + i * 3 * 2); + } + } +error_ret: + mutex_unlock(&st->lock); +} + +/** + * sca3000_event_handler() - handling ring and non ring events + * @irq: The irq being handled. + * @private: struct iio_device pointer for the device. + * + * Ring related interrupt handler. Depending on event, push to + * the ring buffer event chrdev or the event one. + * + * This function is complicated by the fact that the devices can signify ring + * and non ring events via the same interrupt line and they can only + * be distinguished via a read of the relevant status register. + */ +static irqreturn_t sca3000_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct sca3000_state *st = iio_priv(indio_dev); + int ret, val; + s64 last_timestamp = iio_get_time_ns(indio_dev); + + /* + * Could lead if badly timed to an extra read of status reg, + * but ensures no interrupt is missed. + */ + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1); + val = st->rx[0]; + mutex_unlock(&st->lock); + if (ret) + goto done; + + sca3000_ring_int_process(val, indio_dev); + + if (val & SCA3000_INT_STATUS_FREE_FALL) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + last_timestamp); + + if (val & SCA3000_INT_STATUS_Y_TRIGGER) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Y, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + last_timestamp); + + if (val & SCA3000_INT_STATUS_X_TRIGGER) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + last_timestamp); + + if (val & SCA3000_INT_STATUS_Z_TRIGGER) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + last_timestamp); + +done: + return IRQ_HANDLED; +} + +/** + * sca3000_read_event_config() what events are enabled + **/ +static int sca3000_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + /* read current value of mode register */ + mutex_lock(&st->lock); + + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + goto error_ret; + + switch (chan->channel2) { + case IIO_MOD_X_AND_Y_AND_Z: + ret = !!(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT); + break; + case IIO_MOD_X: + case IIO_MOD_Y: + case IIO_MOD_Z: + /* + * Motion detection mode cannot run at the same time as + * acceleration data being read. + */ + if ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) + != SCA3000_REG_MODE_MEAS_MODE_MOT_DET) { + ret = 0; + } else { + ret = sca3000_read_ctrl_reg(st, + SCA3000_REG_CTRL_SEL_MD_CTRL); + if (ret < 0) + goto error_ret; + /* only supporting logical or's for now */ + ret = !!(ret & sca3000_addresses[chan->address][2]); + } + break; + default: + ret = -EINVAL; + } + +error_ret: + mutex_unlock(&st->lock); + + return ret; +} + +static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + /* read current value of mode register */ + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + return ret; + + /* if off and should be on */ + if (state && !(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT)) + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + st->rx[0] | SCA3000_REG_MODE_FREE_FALL_DETECT); + /* if on and should be off */ + else if (!state && (st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT)) + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + st->rx[0] & ~SCA3000_REG_MODE_FREE_FALL_DETECT); + else + return 0; +} + +static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis, + int state) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret, ctrlval; + + /* + * First read the motion detector config to find out if + * this axis is on + */ + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); + if (ret < 0) + return ret; + ctrlval = ret; + /* if off and should be on */ + if (state && !(ctrlval & sca3000_addresses[axis][2])) { + ret = sca3000_write_ctrl_reg(st, + SCA3000_REG_CTRL_SEL_MD_CTRL, + ctrlval | + sca3000_addresses[axis][2]); + if (ret) + return ret; + st->mo_det_use_count++; + } else if (!state && (ctrlval & sca3000_addresses[axis][2])) { + ret = sca3000_write_ctrl_reg(st, + SCA3000_REG_CTRL_SEL_MD_CTRL, + ctrlval & + ~(sca3000_addresses[axis][2])); + if (ret) + return ret; + st->mo_det_use_count--; + } + + /* read current value of mode register */ + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + return ret; + /* if off and should be on */ + if ((st->mo_det_use_count) && + ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) + != SCA3000_REG_MODE_MEAS_MODE_MOT_DET)) + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + (st->rx[0] & ~SCA3000_REG_MODE_MODE_MASK) + | SCA3000_REG_MODE_MEAS_MODE_MOT_DET); + /* if on and should be off */ + else if (!(st->mo_det_use_count) && + ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) + == SCA3000_REG_MODE_MEAS_MODE_MOT_DET)) + return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + st->rx[0] & SCA3000_REG_MODE_MODE_MASK); + else + return 0; +} + +/** + * sca3000_write_event_config() - simple on off control for motion detector + * @indio_dev: IIO device instance specific structure. Data specific to this + * particular driver may be accessed via iio_priv(indio_dev). + * @chan: Description of the channel whose event we are configuring. + * @type: The type of event. + * @dir: The direction of the event. + * @state: Desired state of event being configured. + * + * This is a per axis control, but enabling any will result in the + * motion detector unit being enabled. + * N.B. enabling motion detector stops normal data acquisition. + * There is a complexity in knowing which mode to return to when + * this mode is disabled. Currently normal mode is assumed. + **/ +static int sca3000_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + switch (chan->channel2) { + case IIO_MOD_X_AND_Y_AND_Z: + ret = sca3000_freefall_set_state(indio_dev, state); + break; + + case IIO_MOD_X: + case IIO_MOD_Y: + case IIO_MOD_Z: + ret = sca3000_motion_detect_set_state(indio_dev, + chan->address, + state); + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&st->lock); + + return ret; +} + +static int sca3000_configure_ring(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer; + + buffer = iio_kfifo_allocate(); + if (!buffer) + return -ENOMEM; + + iio_device_attach_buffer(indio_dev, buffer); + indio_dev->modes |= INDIO_BUFFER_SOFTWARE; + + return 0; +} + +static void sca3000_unconfigure_ring(struct iio_dev *indio_dev) +{ + iio_kfifo_free(indio_dev->buffer); +} + +static inline +int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + goto error_ret; + if (state) { + dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n"); + ret = sca3000_write_reg(st, + SCA3000_REG_MODE_ADDR, + (st->rx[0] | SCA3000_REG_MODE_RING_BUF_ENABLE)); + } else + ret = sca3000_write_reg(st, + SCA3000_REG_MODE_ADDR, + (st->rx[0] & ~SCA3000_REG_MODE_RING_BUF_ENABLE)); +error_ret: + mutex_unlock(&st->lock); + + return ret; +} + +/** + * sca3000_hw_ring_preenable() - hw ring buffer preenable function + * @indio_dev: structure representing the IIO device. Device instance + * specific state can be accessed via iio_priv(indio_dev). + * + * Very simple enable function as the chip will allows normal reads + * during ring buffer operation so as long as it is indeed running + * before we notify the core, the precise ordering does not matter. + */ +static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) +{ + int ret; + struct sca3000_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + + /* Enable the 50% full interrupt */ + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); + if (ret) + goto error_unlock; + ret = sca3000_write_reg(st, + SCA3000_REG_INT_MASK_ADDR, + st->rx[0] | SCA3000_REG_INT_MASK_RING_HALF); + if (ret) + goto error_unlock; + + mutex_unlock(&st->lock); + + return __sca3000_hw_ring_state_set(indio_dev, 1); + +error_unlock: + mutex_unlock(&st->lock); + + return ret; +} + +static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev) +{ + int ret; + struct sca3000_state *st = iio_priv(indio_dev); + + ret = __sca3000_hw_ring_state_set(indio_dev, 0); + if (ret) + return ret; + + /* Disable the 50% full interrupt */ + mutex_lock(&st->lock); + + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); + if (ret) + goto unlock; + ret = sca3000_write_reg(st, + SCA3000_REG_INT_MASK_ADDR, + st->rx[0] & ~SCA3000_REG_INT_MASK_RING_HALF); +unlock: + mutex_unlock(&st->lock); + return ret; +} + +static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { + .preenable = &sca3000_hw_ring_preenable, + .postdisable = &sca3000_hw_ring_postdisable, +}; + +/** + * sca3000_clean_setup() - get the device into a predictable state + * @st: Device instance specific private data structure + * + * Devices use flash memory to store many of the register values + * and hence can come up in somewhat unpredictable states. + * Hence reset everything on driver load. + */ +static int sca3000_clean_setup(struct sca3000_state *st) +{ + int ret; + + mutex_lock(&st->lock); + /* Ensure all interrupts have been acknowledged */ + ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1); + if (ret) + goto error_ret; + + /* Turn off all motion detection channels */ + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); + if (ret < 0) + goto error_ret; + ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL, + ret & SCA3000_MD_CTRL_PROT_MASK); + if (ret) + goto error_ret; + + /* Disable ring buffer */ + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + goto error_ret; + ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, + (ret & SCA3000_REG_OUT_CTRL_PROT_MASK) + | SCA3000_REG_OUT_CTRL_BUF_X_EN + | SCA3000_REG_OUT_CTRL_BUF_Y_EN + | SCA3000_REG_OUT_CTRL_BUF_Z_EN + | SCA3000_REG_OUT_CTRL_BUF_DIV_4); + if (ret) + goto error_ret; + /* Enable interrupts, relevant to mode and set up as active low */ + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); + if (ret) + goto error_ret; + ret = sca3000_write_reg(st, + SCA3000_REG_INT_MASK_ADDR, + (ret & SCA3000_REG_INT_MASK_PROT_MASK) + | SCA3000_REG_INT_MASK_ACTIVE_LOW); + if (ret) + goto error_ret; + /* + * Select normal measurement mode, free fall off, ring off + * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5 + * as that occurs in one of the example on the datasheet + */ + ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); + if (ret) + goto error_ret; + ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, + (st->rx[0] & SCA3000_MODE_PROT_MASK)); + +error_ret: + mutex_unlock(&st->lock); + return ret; +} + +static const struct iio_info sca3000_info = { + .attrs = &sca3000_attribute_group, + .read_raw = &sca3000_read_raw, + .write_raw = &sca3000_write_raw, + .read_event_value = &sca3000_read_event_value, + .write_event_value = &sca3000_write_event_value, + .read_event_config = &sca3000_read_event_config, + .write_event_config = &sca3000_write_event_config, + .driver_module = THIS_MODULE, +}; + +static int sca3000_probe(struct spi_device *spi) +{ + int ret; + struct sca3000_state *st; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + st->us = spi; + mutex_init(&st->lock); + st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi) + ->driver_data]; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &sca3000_info; + if (st->info->temp_output) { + indio_dev->channels = sca3000_channels_with_temp; + indio_dev->num_channels = + ARRAY_SIZE(sca3000_channels_with_temp); + } else { + indio_dev->channels = sca3000_channels; + indio_dev->num_channels = ARRAY_SIZE(sca3000_channels); + } + indio_dev->modes = INDIO_DIRECT_MODE; + + sca3000_configure_ring(indio_dev); + + if (spi->irq) { + ret = request_threaded_irq(spi->irq, + NULL, + &sca3000_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "sca3000", + indio_dev); + if (ret) + return ret; + } + indio_dev->setup_ops = &sca3000_ring_setup_ops; + ret = sca3000_clean_setup(st); + if (ret) + goto error_free_irq; + + ret = sca3000_print_rev(indio_dev); + if (ret) + goto error_free_irq; + + return iio_device_register(indio_dev); + +error_free_irq: + if (spi->irq) + free_irq(spi->irq, indio_dev); + + return ret; +} + +static int sca3000_stop_all_interrupts(struct sca3000_state *st) +{ + int ret; + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); + if (ret) + goto error_ret; + ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR, + (st->rx[0] & + ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER | + SCA3000_REG_INT_MASK_RING_HALF | + SCA3000_REG_INT_MASK_ALL_INTS))); +error_ret: + mutex_unlock(&st->lock); + return ret; +} + +static int sca3000_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct sca3000_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + /* Must ensure no interrupts can be generated after this! */ + sca3000_stop_all_interrupts(st); + if (spi->irq) + free_irq(spi->irq, indio_dev); + + sca3000_unconfigure_ring(indio_dev); + + return 0; +} + +static const struct spi_device_id sca3000_id[] = { + {"sca3000_d01", d01}, + {"sca3000_e02", e02}, + {"sca3000_e04", e04}, + {"sca3000_e05", e05}, + {} +}; +MODULE_DEVICE_TABLE(spi, sca3000_id); + +static struct spi_driver sca3000_driver = { + .driver = { + .name = "sca3000", + }, + .probe = sca3000_probe, + .remove = sca3000_remove, + .id_table = sca3000_id, +}; +module_spi_driver(sca3000_driver); + +MODULE_AUTHOR("Jonathan Cameron "); +MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index 53389bfdd100..c6b0f5eae7ab 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -51,15 +51,4 @@ config ADIS16240 To compile this driver as a module, say M here: the module will be called adis16240. -config SCA3000 - select IIO_BUFFER - select IIO_KFIFO_BUF - depends on SPI - tristate "VTI SCA3000 series accelerometers" - help - Say Y here to build support for the VTI SCA3000 series of SPI - accelerometers. These devices use a hardware ring buffer. - - To compile this driver as a module, say M here: the module will be - called sca3000. endmenu diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index 1d49b6ab87ab..febb137b60c4 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -13,5 +13,3 @@ obj-$(CONFIG_ADIS16209) += adis16209.o adis16240-y := adis16240_core.o obj-$(CONFIG_ADIS16240) += adis16240.o - -obj-$(CONFIG_SCA3000) += sca3000.o diff --git a/drivers/staging/iio/accel/sca3000.c b/drivers/staging/iio/accel/sca3000.c deleted file mode 100644 index cb1d83fa19a0..000000000000 --- a/drivers/staging/iio/accel/sca3000.c +++ /dev/null @@ -1,1576 +0,0 @@ -/* - * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * Copyright (c) 2009 Jonathan Cameron - * - * See industrialio/accels/sca3000.h for comments. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02) -#define SCA3000_READ_REG(a) ((a) << 2) - -#define SCA3000_REG_REVID_ADDR 0x00 -#define SCA3000_REG_REVID_MAJOR_MASK GENMASK(8, 4) -#define SCA3000_REG_REVID_MINOR_MASK GENMASK(3, 0) - -#define SCA3000_REG_STATUS_ADDR 0x02 -#define SCA3000_LOCKED BIT(5) -#define SCA3000_EEPROM_CS_ERROR BIT(1) -#define SCA3000_SPI_FRAME_ERROR BIT(0) - -/* All reads done using register decrement so no need to directly access LSBs */ -#define SCA3000_REG_X_MSB_ADDR 0x05 -#define SCA3000_REG_Y_MSB_ADDR 0x07 -#define SCA3000_REG_Z_MSB_ADDR 0x09 - -#define SCA3000_REG_RING_OUT_ADDR 0x0f - -/* Temp read untested - the e05 doesn't have the sensor */ -#define SCA3000_REG_TEMP_MSB_ADDR 0x13 - -#define SCA3000_REG_MODE_ADDR 0x14 -#define SCA3000_MODE_PROT_MASK 0x28 -#define SCA3000_REG_MODE_RING_BUF_ENABLE BIT(7) -#define SCA3000_REG_MODE_RING_BUF_8BIT BIT(6) - -/* - * Free fall detection triggers an interrupt if the acceleration - * is below a threshold for equivalent of 25cm drop - */ -#define SCA3000_REG_MODE_FREE_FALL_DETECT BIT(4) -#define SCA3000_REG_MODE_MEAS_MODE_NORMAL 0x00 -#define SCA3000_REG_MODE_MEAS_MODE_OP_1 0x01 -#define SCA3000_REG_MODE_MEAS_MODE_OP_2 0x02 - -/* - * In motion detection mode the accelerations are band pass filtered - * (approx 1 - 25Hz) and then a programmable threshold used to trigger - * and interrupt. - */ -#define SCA3000_REG_MODE_MEAS_MODE_MOT_DET 0x03 -#define SCA3000_REG_MODE_MODE_MASK 0x03 - -#define SCA3000_REG_BUF_COUNT_ADDR 0x15 - -#define SCA3000_REG_INT_STATUS_ADDR 0x16 -#define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7) -#define SCA3000_REG_INT_STATUS_HALF BIT(6) - -#define SCA3000_INT_STATUS_FREE_FALL BIT(3) -#define SCA3000_INT_STATUS_Y_TRIGGER BIT(2) -#define SCA3000_INT_STATUS_X_TRIGGER BIT(1) -#define SCA3000_INT_STATUS_Z_TRIGGER BIT(0) - -/* Used to allow access to multiplexed registers */ -#define SCA3000_REG_CTRL_SEL_ADDR 0x18 -/* Only available for SCA3000-D03 and SCA3000-D01 */ -#define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01 -#define SCA3000_REG_CTRL_SEL_MD_CTRL 0x02 -#define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03 -#define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04 -#define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05 -/* - * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device - * will not function - */ -#define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B - -#define SCA3000_REG_OUT_CTRL_PROT_MASK 0xE0 -#define SCA3000_REG_OUT_CTRL_BUF_X_EN 0x10 -#define SCA3000_REG_OUT_CTRL_BUF_Y_EN 0x08 -#define SCA3000_REG_OUT_CTRL_BUF_Z_EN 0x04 -#define SCA3000_REG_OUT_CTRL_BUF_DIV_MASK 0x03 -#define SCA3000_REG_OUT_CTRL_BUF_DIV_4 0x02 -#define SCA3000_REG_OUT_CTRL_BUF_DIV_2 0x01 - - -/* - * Control which motion detector interrupts are on. - * For now only OR combinations are supported. - */ -#define SCA3000_MD_CTRL_PROT_MASK 0xC0 -#define SCA3000_MD_CTRL_OR_Y BIT(0) -#define SCA3000_MD_CTRL_OR_X BIT(1) -#define SCA3000_MD_CTRL_OR_Z BIT(2) -/* Currently unsupported */ -#define SCA3000_MD_CTRL_AND_Y BIT(3) -#define SCA3000_MD_CTRL_AND_X BIT(4) -#define SAC3000_MD_CTRL_AND_Z BIT(5) - -/* - * Some control registers of complex access methods requiring this register to - * be used to remove a lock. - */ -#define SCA3000_REG_UNLOCK_ADDR 0x1e - -#define SCA3000_REG_INT_MASK_ADDR 0x21 -#define SCA3000_REG_INT_MASK_PROT_MASK 0x1C - -#define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7) -#define SCA3000_REG_INT_MASK_RING_HALF BIT(6) - -#define SCA3000_REG_INT_MASK_ALL_INTS 0x02 -#define SCA3000_REG_INT_MASK_ACTIVE_HIGH 0x01 -#define SCA3000_REG_INT_MASK_ACTIVE_LOW 0x00 -/* Values of multiplexed registers (write to ctrl_data after select) */ -#define SCA3000_REG_CTRL_DATA_ADDR 0x22 - -/* - * Measurement modes available on some sca3000 series chips. Code assumes others - * may become available in the future. - * - * Bypass - Bypass the low-pass filter in the signal channel so as to increase - * signal bandwidth. - * - * Narrow - Narrow low-pass filtering of the signal channel and half output - * data rate by decimation. - * - * Wide - Widen low-pass filtering of signal channel to increase bandwidth - */ -#define SCA3000_OP_MODE_BYPASS 0x01 -#define SCA3000_OP_MODE_NARROW 0x02 -#define SCA3000_OP_MODE_WIDE 0x04 -#define SCA3000_MAX_TX 6 -#define SCA3000_MAX_RX 2 - -/** - * struct sca3000_state - device instance state information - * @us: the associated spi device - * @info: chip variant information - * @last_timestamp: the timestamp of the last event - * @mo_det_use_count: reference counter for the motion detection unit - * @lock: lock used to protect elements of sca3000_state - * and the underlying device state. - * @tx: dma-able transmit buffer - * @rx: dma-able receive buffer - **/ -struct sca3000_state { - struct spi_device *us; - const struct sca3000_chip_info *info; - s64 last_timestamp; - int mo_det_use_count; - struct mutex lock; - /* Can these share a cacheline ? */ - u8 rx[384] ____cacheline_aligned; - u8 tx[6] ____cacheline_aligned; -}; - -/** - * struct sca3000_chip_info - model dependent parameters - * @scale: scale * 10^-6 - * @temp_output: some devices have temperature sensors. - * @measurement_mode_freq: normal mode sampling frequency - * @measurement_mode_3db_freq: 3db cutoff frequency of the low pass filter for - * the normal measurement mode. - * @option_mode_1: first optional mode. Not all models have one - * @option_mode_1_freq: option mode 1 sampling frequency - * @option_mode_1_3db_freq: 3db cutoff frequency of the low pass filter for - * the first option mode. - * @option_mode_2: second optional mode. Not all chips have one - * @option_mode_2_freq: option mode 2 sampling frequency - * @option_mode_2_3db_freq: 3db cutoff frequency of the low pass filter for - * the second option mode. - * @mod_det_mult_xz: Bit wise multipliers to calculate the threshold - * for motion detection in the x and z axis. - * @mod_det_mult_y: Bit wise multipliers to calculate the threshold - * for motion detection in the y axis. - * - * This structure is used to hold information about the functionality of a given - * sca3000 variant. - **/ -struct sca3000_chip_info { - unsigned int scale; - bool temp_output; - int measurement_mode_freq; - int measurement_mode_3db_freq; - int option_mode_1; - int option_mode_1_freq; - int option_mode_1_3db_freq; - int option_mode_2; - int option_mode_2_freq; - int option_mode_2_3db_freq; - int mot_det_mult_xz[6]; - int mot_det_mult_y[7]; -}; - -enum sca3000_variant { - d01, - e02, - e04, - e05, -}; - -/* - * Note where option modes are not defined, the chip simply does not - * support any. - * Other chips in the sca3000 series use i2c and are not included here. - * - * Some of these devices are only listed in the family data sheet and - * do not actually appear to be available. - */ -static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = { - [d01] = { - .scale = 7357, - .temp_output = true, - .measurement_mode_freq = 250, - .measurement_mode_3db_freq = 45, - .option_mode_1 = SCA3000_OP_MODE_BYPASS, - .option_mode_1_freq = 250, - .option_mode_1_3db_freq = 70, - .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300}, - .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750}, - }, - [e02] = { - .scale = 9810, - .measurement_mode_freq = 125, - .measurement_mode_3db_freq = 40, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 63, - .option_mode_1_3db_freq = 11, - .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050}, - .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700}, - }, - [e04] = { - .scale = 19620, - .measurement_mode_freq = 100, - .measurement_mode_3db_freq = 38, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 50, - .option_mode_1_3db_freq = 9, - .option_mode_2 = SCA3000_OP_MODE_WIDE, - .option_mode_2_freq = 400, - .option_mode_2_3db_freq = 70, - .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100}, - .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000}, - }, - [e05] = { - .scale = 61313, - .measurement_mode_freq = 200, - .measurement_mode_3db_freq = 60, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 50, - .option_mode_1_3db_freq = 9, - .option_mode_2 = SCA3000_OP_MODE_WIDE, - .option_mode_2_freq = 400, - .option_mode_2_3db_freq = 75, - .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900}, - .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600}, - }, -}; - -static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val) -{ - st->tx[0] = SCA3000_WRITE_REG(address); - st->tx[1] = val; - return spi_write(st->us, st->tx, 2); -} - -static int sca3000_read_data_short(struct sca3000_state *st, - u8 reg_address_high, - int len) -{ - struct spi_transfer xfer[2] = { - { - .len = 1, - .tx_buf = st->tx, - }, { - .len = len, - .rx_buf = st->rx, - } - }; - st->tx[0] = SCA3000_READ_REG(reg_address_high); - - return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); -} - -/** - * sca3000_reg_lock_on() - test if the ctrl register lock is on - * @st: Driver specific device instance data. - * - * Lock must be held. - **/ -static int sca3000_reg_lock_on(struct sca3000_state *st) -{ - int ret; - - ret = sca3000_read_data_short(st, SCA3000_REG_STATUS_ADDR, 1); - if (ret < 0) - return ret; - - return !(st->rx[0] & SCA3000_LOCKED); -} - -/** - * __sca3000_unlock_reg_lock() - unlock the control registers - * @st: Driver specific device instance data. - * - * Note the device does not appear to support doing this in a single transfer. - * This should only ever be used as part of ctrl reg read. - * Lock must be held before calling this - */ -static int __sca3000_unlock_reg_lock(struct sca3000_state *st) -{ - struct spi_transfer xfer[3] = { - { - .len = 2, - .cs_change = 1, - .tx_buf = st->tx, - }, { - .len = 2, - .cs_change = 1, - .tx_buf = st->tx + 2, - }, { - .len = 2, - .tx_buf = st->tx + 4, - }, - }; - st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); - st->tx[1] = 0x00; - st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); - st->tx[3] = 0x50; - st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); - st->tx[5] = 0xA0; - - return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); -} - -/** - * sca3000_write_ctrl_reg() write to a lock protect ctrl register - * @st: Driver specific device instance data. - * @sel: selects which registers we wish to write to - * @val: the value to be written - * - * Certain control registers are protected against overwriting by the lock - * register and use a shared write address. This function allows writing of - * these registers. - * Lock must be held. - */ -static int sca3000_write_ctrl_reg(struct sca3000_state *st, - u8 sel, - uint8_t val) -{ - int ret; - - ret = sca3000_reg_lock_on(st); - if (ret < 0) - goto error_ret; - if (ret) { - ret = __sca3000_unlock_reg_lock(st); - if (ret) - goto error_ret; - } - - /* Set the control select register */ - ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, sel); - if (ret) - goto error_ret; - - /* Write the actual value into the register */ - ret = sca3000_write_reg(st, SCA3000_REG_CTRL_DATA_ADDR, val); - -error_ret: - return ret; -} - -/** - * sca3000_read_ctrl_reg() read from lock protected control register. - * @st: Driver specific device instance data. - * @ctrl_reg: Which ctrl register do we want to read. - * - * Lock must be held. - */ -static int sca3000_read_ctrl_reg(struct sca3000_state *st, - u8 ctrl_reg) -{ - int ret; - - ret = sca3000_reg_lock_on(st); - if (ret < 0) - goto error_ret; - if (ret) { - ret = __sca3000_unlock_reg_lock(st); - if (ret) - goto error_ret; - } - /* Set the control select register */ - ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, ctrl_reg); - if (ret) - goto error_ret; - ret = sca3000_read_data_short(st, SCA3000_REG_CTRL_DATA_ADDR, 1); - if (ret) - goto error_ret; - return st->rx[0]; -error_ret: - return ret; -} - -/** - * sca3000_show_rev() - sysfs interface to read the chip revision number - * @indio_dev: Device instance specific generic IIO data. - * Driver specific device instance data can be obtained via - * via iio_priv(indio_dev) - */ -static int sca3000_print_rev(struct iio_dev *indio_dev) -{ - int ret; - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_REVID_ADDR, 1); - if (ret < 0) - goto error_ret; - dev_info(&indio_dev->dev, - "sca3000 revision major=%lu, minor=%lu\n", - st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK, - st->rx[0] & SCA3000_REG_REVID_MINOR_MASK); -error_ret: - mutex_unlock(&st->lock); - - return ret; -} - -static ssize_t -sca3000_show_available_3db_freqs(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int len; - - len = sprintf(buf, "%d", st->info->measurement_mode_3db_freq); - if (st->info->option_mode_1) - len += sprintf(buf + len, " %d", - st->info->option_mode_1_3db_freq); - if (st->info->option_mode_2) - len += sprintf(buf + len, " %d", - st->info->option_mode_2_3db_freq); - len += sprintf(buf + len, "\n"); - - return len; -} - -static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, - S_IRUGO, sca3000_show_available_3db_freqs, - NULL, 0); - -static const struct iio_event_spec sca3000_event = { - .type = IIO_EV_TYPE_MAG, - .dir = IIO_EV_DIR_RISING, - .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), -}; - -/* - * Note the hack in the number of bits to pretend we have 2 more than - * we do in the fifo. - */ -#define SCA3000_CHAN(index, mod) \ - { \ - .type = IIO_ACCEL, \ - .modified = 1, \ - .channel2 = mod, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |\ - BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),\ - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ - .address = index, \ - .scan_index = index, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 13, \ - .storagebits = 16, \ - .shift = 3, \ - .endianness = IIO_BE, \ - }, \ - .event_spec = &sca3000_event, \ - .num_event_specs = 1, \ - } - -static const struct iio_event_spec sca3000_freefall_event_spec = { - .type = IIO_EV_TYPE_MAG, - .dir = IIO_EV_DIR_FALLING, - .mask_separate = BIT(IIO_EV_INFO_ENABLE) | - BIT(IIO_EV_INFO_PERIOD), -}; - -static const struct iio_chan_spec sca3000_channels[] = { - SCA3000_CHAN(0, IIO_MOD_X), - SCA3000_CHAN(1, IIO_MOD_Y), - SCA3000_CHAN(2, IIO_MOD_Z), - { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_X_AND_Y_AND_Z, - .scan_index = -1, /* Fake channel */ - .event_spec = &sca3000_freefall_event_spec, - .num_event_specs = 1, - }, -}; - -static const struct iio_chan_spec sca3000_channels_with_temp[] = { - SCA3000_CHAN(0, IIO_MOD_X), - SCA3000_CHAN(1, IIO_MOD_Y), - SCA3000_CHAN(2, IIO_MOD_Z), - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_OFFSET), - /* No buffer support */ - .scan_index = -1, - }, - { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_X_AND_Y_AND_Z, - .scan_index = -1, /* Fake channel */ - .event_spec = &sca3000_freefall_event_spec, - .num_event_specs = 1, - }, -}; - -static u8 sca3000_addresses[3][3] = { - [0] = {SCA3000_REG_X_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_X_TH, - SCA3000_MD_CTRL_OR_X}, - [1] = {SCA3000_REG_Y_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Y_TH, - SCA3000_MD_CTRL_OR_Y}, - [2] = {SCA3000_REG_Z_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Z_TH, - SCA3000_MD_CTRL_OR_Z}, -}; - -/** - * __sca3000_get_base_freq() - obtain mode specific base frequency - * @st: Private driver specific device instance specific state. - * @info: chip type specific information. - * @base_freq: Base frequency for the current measurement mode. - * - * lock must be held - */ -static inline int __sca3000_get_base_freq(struct sca3000_state *st, - const struct sca3000_chip_info *info, - int *base_freq) -{ - int ret; - - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - goto error_ret; - switch (SCA3000_REG_MODE_MODE_MASK & st->rx[0]) { - case SCA3000_REG_MODE_MEAS_MODE_NORMAL: - *base_freq = info->measurement_mode_freq; - break; - case SCA3000_REG_MODE_MEAS_MODE_OP_1: - *base_freq = info->option_mode_1_freq; - break; - case SCA3000_REG_MODE_MEAS_MODE_OP_2: - *base_freq = info->option_mode_2_freq; - break; - default: - ret = -EINVAL; - } -error_ret: - return ret; -} - -/** - * sca3000_read_raw_samp_freq() - read_raw handler for IIO_CHAN_INFO_SAMP_FREQ - * @st: Private driver specific device instance specific state. - * @val: The frequency read back. - * - * lock must be held - **/ -static int sca3000_read_raw_samp_freq(struct sca3000_state *st, int *val) -{ - int ret; - - ret = __sca3000_get_base_freq(st, st->info, val); - if (ret) - return ret; - - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - if (ret < 0) - return ret; - - if (*val > 0) { - ret &= SCA3000_REG_OUT_CTRL_BUF_DIV_MASK; - switch (ret) { - case SCA3000_REG_OUT_CTRL_BUF_DIV_2: - *val /= 2; - break; - case SCA3000_REG_OUT_CTRL_BUF_DIV_4: - *val /= 4; - break; - } - } - - return 0; -} - -/** - * sca3000_write_raw_samp_freq() - write_raw handler for IIO_CHAN_INFO_SAMP_FREQ - * @st: Private driver specific device instance specific state. - * @val: The frequency desired. - * - * lock must be held - */ -static int sca3000_write_raw_samp_freq(struct sca3000_state *st, int val) -{ - int ret, base_freq, ctrlval; - - ret = __sca3000_get_base_freq(st, st->info, &base_freq); - if (ret) - return ret; - - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - if (ret < 0) - return ret; - - ctrlval = ret & ~SCA3000_REG_OUT_CTRL_BUF_DIV_MASK; - - if (val == base_freq / 2) - ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_2; - if (val == base_freq / 4) - ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_4; - else if (val != base_freq) - return -EINVAL; - - return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, - ctrlval); -} - -static int sca3000_read_3db_freq(struct sca3000_state *st, int *val) -{ - int ret; - - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - return ret; - - /* mask bottom 2 bits - only ones that are relevant */ - st->rx[0] &= SCA3000_REG_MODE_MODE_MASK; - switch (st->rx[0]) { - case SCA3000_REG_MODE_MEAS_MODE_NORMAL: - *val = st->info->measurement_mode_3db_freq; - return IIO_VAL_INT; - case SCA3000_REG_MODE_MEAS_MODE_MOT_DET: - return -EBUSY; - case SCA3000_REG_MODE_MEAS_MODE_OP_1: - *val = st->info->option_mode_1_3db_freq; - return IIO_VAL_INT; - case SCA3000_REG_MODE_MEAS_MODE_OP_2: - *val = st->info->option_mode_2_3db_freq; - return IIO_VAL_INT; - default: - return -EINVAL; - } -} - -static int sca3000_write_3db_freq(struct sca3000_state *st, int val) -{ - int ret; - int mode; - - if (val == st->info->measurement_mode_3db_freq) - mode = SCA3000_REG_MODE_MEAS_MODE_NORMAL; - else if (st->info->option_mode_1 && - (val == st->info->option_mode_1_3db_freq)) - mode = SCA3000_REG_MODE_MEAS_MODE_OP_1; - else if (st->info->option_mode_2 && - (val == st->info->option_mode_2_3db_freq)) - mode = SCA3000_REG_MODE_MEAS_MODE_OP_2; - else - return -EINVAL; - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - return ret; - - st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK; - st->rx[0] |= (mode & SCA3000_REG_MODE_MODE_MASK); - - return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]); -} - -static int sca3000_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - u8 address; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - mutex_lock(&st->lock); - if (chan->type == IIO_ACCEL) { - if (st->mo_det_use_count) { - mutex_unlock(&st->lock); - return -EBUSY; - } - address = sca3000_addresses[chan->address][0]; - ret = sca3000_read_data_short(st, address, 2); - if (ret < 0) { - mutex_unlock(&st->lock); - return ret; - } - *val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF; - *val = ((*val) << (sizeof(*val) * 8 - 13)) >> - (sizeof(*val) * 8 - 13); - } else { - /* get the temperature when available */ - ret = sca3000_read_data_short(st, - SCA3000_REG_TEMP_MSB_ADDR, - 2); - if (ret < 0) { - mutex_unlock(&st->lock); - return ret; - } - *val = ((st->rx[0] & 0x3F) << 3) | - ((st->rx[1] & 0xE0) >> 5); - } - mutex_unlock(&st->lock); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - *val = 0; - if (chan->type == IIO_ACCEL) - *val2 = st->info->scale; - else /* temperature */ - *val2 = 555556; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OFFSET: - *val = -214; - *val2 = 600000; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_SAMP_FREQ: - mutex_lock(&st->lock); - ret = sca3000_read_raw_samp_freq(st, val); - mutex_unlock(&st->lock); - return ret ? ret : IIO_VAL_INT; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - mutex_lock(&st->lock); - ret = sca3000_read_3db_freq(st, val); - mutex_unlock(&st->lock); - return ret; - default: - return -EINVAL; - } -} - -static int sca3000_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - if (val2) - return -EINVAL; - mutex_lock(&st->lock); - ret = sca3000_write_raw_samp_freq(st, val); - mutex_unlock(&st->lock); - return ret; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - if (val2) - return -EINVAL; - mutex_lock(&st->lock); - ret = sca3000_write_3db_freq(st, val); - mutex_unlock(&st->lock); - default: - return -EINVAL; - } - - return ret; -} - -/** - * sca3000_read_av_freq() - sysfs function to get available frequencies - * @dev: Device structure for this device. - * @attr: Description of the attribute. - * @buf: Incoming string - * - * The later modes are only relevant to the ring buffer - and depend on current - * mode. Note that data sheet gives rather wide tolerances for these so integer - * division will give good enough answer and not all chips have them specified - * at all. - **/ -static ssize_t sca3000_read_av_freq(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int len = 0, ret, val; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - val = st->rx[0]; - mutex_unlock(&st->lock); - if (ret) - goto error_ret; - - switch (val & SCA3000_REG_MODE_MODE_MASK) { - case SCA3000_REG_MODE_MEAS_MODE_NORMAL: - len += sprintf(buf + len, "%d %d %d\n", - st->info->measurement_mode_freq, - st->info->measurement_mode_freq / 2, - st->info->measurement_mode_freq / 4); - break; - case SCA3000_REG_MODE_MEAS_MODE_OP_1: - len += sprintf(buf + len, "%d %d %d\n", - st->info->option_mode_1_freq, - st->info->option_mode_1_freq / 2, - st->info->option_mode_1_freq / 4); - break; - case SCA3000_REG_MODE_MEAS_MODE_OP_2: - len += sprintf(buf + len, "%d %d %d\n", - st->info->option_mode_2_freq, - st->info->option_mode_2_freq / 2, - st->info->option_mode_2_freq / 4); - break; - } - return len; -error_ret: - return ret; -} - -/* - * Should only really be registered if ring buffer support is compiled in. - * Does no harm however and doing it right would add a fair bit of complexity - */ -static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); - -/** - * sca3000_read_event_value() - query of a threshold or period - **/ -static int sca3000_read_event_value(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int *val, int *val2) -{ - int ret, i; - struct sca3000_state *st = iio_priv(indio_dev); - - switch (info) { - case IIO_EV_INFO_VALUE: - mutex_lock(&st->lock); - ret = sca3000_read_ctrl_reg(st, - sca3000_addresses[chan->address][1]); - mutex_unlock(&st->lock); - if (ret < 0) - return ret; - *val = 0; - if (chan->channel2 == IIO_MOD_Y) - for_each_set_bit(i, (unsigned long *)&ret, - ARRAY_SIZE(st->info->mot_det_mult_y)) - *val += st->info->mot_det_mult_y[i]; - else - for_each_set_bit(i, (unsigned long *)&ret, - ARRAY_SIZE(st->info->mot_det_mult_xz)) - *val += st->info->mot_det_mult_xz[i]; - - return IIO_VAL_INT; - case IIO_EV_INFO_PERIOD: - *val = 0; - *val2 = 226000; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } -} - -/** - * sca3000_write_value() - control of threshold and period - * @indio_dev: Device instance specific IIO information. - * @chan: Description of the channel for which the event is being - * configured. - * @type: The type of event being configured, here magnitude rising - * as everything else is read only. - * @dir: Direction of the event (here rising) - * @info: What information about the event are we configuring. - * Here the threshold only. - * @val: Integer part of the value being written.. - * @val2: Non integer part of the value being written. Here always 0. - */ -static int sca3000_write_event_value(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - int i; - u8 nonlinear = 0; - - if (chan->channel2 == IIO_MOD_Y) { - i = ARRAY_SIZE(st->info->mot_det_mult_y); - while (i > 0) - if (val >= st->info->mot_det_mult_y[--i]) { - nonlinear |= (1 << i); - val -= st->info->mot_det_mult_y[i]; - } - } else { - i = ARRAY_SIZE(st->info->mot_det_mult_xz); - while (i > 0) - if (val >= st->info->mot_det_mult_xz[--i]) { - nonlinear |= (1 << i); - val -= st->info->mot_det_mult_xz[i]; - } - } - - mutex_lock(&st->lock); - ret = sca3000_write_ctrl_reg(st, - sca3000_addresses[chan->address][1], - nonlinear); - mutex_unlock(&st->lock); - - return ret; -} - -static struct attribute *sca3000_attributes[] = { - &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, - &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group sca3000_attribute_group = { - .attrs = sca3000_attributes, -}; - -static int sca3000_read_data(struct sca3000_state *st, - u8 reg_address_high, - u8 *rx, - int len) -{ - int ret; - struct spi_transfer xfer[2] = { - { - .len = 1, - .tx_buf = st->tx, - }, { - .len = len, - .rx_buf = rx, - } - }; - - st->tx[0] = SCA3000_READ_REG(reg_address_high); - ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); - if (ret) { - dev_err(get_device(&st->us->dev), "problem reading register"); - return ret; - } - - return 0; -} - -/** - * sca3000_ring_int_process() - ring specific interrupt handling. - * @val: Value of the interrupt status register. - * @indio_dev: Device instance specific IIO device structure. - */ -static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret, i, num_available; - - mutex_lock(&st->lock); - - if (val & SCA3000_REG_INT_STATUS_HALF) { - ret = sca3000_read_data_short(st, SCA3000_REG_BUF_COUNT_ADDR, - 1); - if (ret) - goto error_ret; - num_available = st->rx[0]; - /* - * num_available is the total number of samples available - * i.e. number of time points * number of channels. - */ - ret = sca3000_read_data(st, SCA3000_REG_RING_OUT_ADDR, st->rx, - num_available * 2); - if (ret) - goto error_ret; - for (i = 0; i < num_available / 3; i++) { - /* - * Dirty hack to cover for 11 bit in fifo, 13 bit - * direct reading. - * - * In theory the bottom two bits are undefined. - * In reality they appear to always be 0. - */ - iio_push_to_buffers(indio_dev, st->rx + i * 3 * 2); - } - } -error_ret: - mutex_unlock(&st->lock); -} - -/** - * sca3000_event_handler() - handling ring and non ring events - * @irq: The irq being handled. - * @private: struct iio_device pointer for the device. - * - * Ring related interrupt handler. Depending on event, push to - * the ring buffer event chrdev or the event one. - * - * This function is complicated by the fact that the devices can signify ring - * and non ring events via the same interrupt line and they can only - * be distinguished via a read of the relevant status register. - */ -static irqreturn_t sca3000_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct sca3000_state *st = iio_priv(indio_dev); - int ret, val; - s64 last_timestamp = iio_get_time_ns(indio_dev); - - /* - * Could lead if badly timed to an extra read of status reg, - * but ensures no interrupt is missed. - */ - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1); - val = st->rx[0]; - mutex_unlock(&st->lock); - if (ret) - goto done; - - sca3000_ring_int_process(val, indio_dev); - - if (val & SCA3000_INT_STATUS_FREE_FALL) - iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_X_AND_Y_AND_Z, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_FALLING), - last_timestamp); - - if (val & SCA3000_INT_STATUS_Y_TRIGGER) - iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_Y, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_RISING), - last_timestamp); - - if (val & SCA3000_INT_STATUS_X_TRIGGER) - iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_X, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_RISING), - last_timestamp); - - if (val & SCA3000_INT_STATUS_Z_TRIGGER) - iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_Z, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_RISING), - last_timestamp); - -done: - return IRQ_HANDLED; -} - -/** - * sca3000_read_event_config() what events are enabled - **/ -static int sca3000_read_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - /* read current value of mode register */ - mutex_lock(&st->lock); - - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - goto error_ret; - - switch (chan->channel2) { - case IIO_MOD_X_AND_Y_AND_Z: - ret = !!(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT); - break; - case IIO_MOD_X: - case IIO_MOD_Y: - case IIO_MOD_Z: - /* - * Motion detection mode cannot run at the same time as - * acceleration data being read. - */ - if ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) - != SCA3000_REG_MODE_MEAS_MODE_MOT_DET) { - ret = 0; - } else { - ret = sca3000_read_ctrl_reg(st, - SCA3000_REG_CTRL_SEL_MD_CTRL); - if (ret < 0) - goto error_ret; - /* only supporting logical or's for now */ - ret = !!(ret & sca3000_addresses[chan->address][2]); - } - break; - default: - ret = -EINVAL; - } - -error_ret: - mutex_unlock(&st->lock); - - return ret; -} - -static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - - /* read current value of mode register */ - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - return ret; - - /* if off and should be on */ - if (state && !(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT)) - return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, - st->rx[0] | SCA3000_REG_MODE_FREE_FALL_DETECT); - /* if on and should be off */ - else if (!state && (st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT)) - return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, - st->rx[0] & ~SCA3000_REG_MODE_FREE_FALL_DETECT); - else - return 0; -} - -static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis, - int state) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret, ctrlval; - - /* - * First read the motion detector config to find out if - * this axis is on - */ - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); - if (ret < 0) - return ret; - ctrlval = ret; - /* if off and should be on */ - if (state && !(ctrlval & sca3000_addresses[axis][2])) { - ret = sca3000_write_ctrl_reg(st, - SCA3000_REG_CTRL_SEL_MD_CTRL, - ctrlval | - sca3000_addresses[axis][2]); - if (ret) - return ret; - st->mo_det_use_count++; - } else if (!state && (ctrlval & sca3000_addresses[axis][2])) { - ret = sca3000_write_ctrl_reg(st, - SCA3000_REG_CTRL_SEL_MD_CTRL, - ctrlval & - ~(sca3000_addresses[axis][2])); - if (ret) - return ret; - st->mo_det_use_count--; - } - - /* read current value of mode register */ - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - return ret; - /* if off and should be on */ - if ((st->mo_det_use_count) && - ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) - != SCA3000_REG_MODE_MEAS_MODE_MOT_DET)) - return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, - (st->rx[0] & ~SCA3000_REG_MODE_MODE_MASK) - | SCA3000_REG_MODE_MEAS_MODE_MOT_DET); - /* if on and should be off */ - else if (!(st->mo_det_use_count) && - ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) - == SCA3000_REG_MODE_MEAS_MODE_MOT_DET)) - return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, - st->rx[0] & SCA3000_REG_MODE_MODE_MASK); - else - return 0; -} - -/** - * sca3000_write_event_config() - simple on off control for motion detector - * @indio_dev: IIO device instance specific structure. Data specific to this - * particular driver may be accessed via iio_priv(indio_dev). - * @chan: Description of the channel whose event we are configuring. - * @type: The type of event. - * @dir: The direction of the event. - * @state: Desired state of event being configured. - * - * This is a per axis control, but enabling any will result in the - * motion detector unit being enabled. - * N.B. enabling motion detector stops normal data acquisition. - * There is a complexity in knowing which mode to return to when - * this mode is disabled. Currently normal mode is assumed. - **/ -static int sca3000_write_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - int state) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->lock); - switch (chan->channel2) { - case IIO_MOD_X_AND_Y_AND_Z: - ret = sca3000_freefall_set_state(indio_dev, state); - break; - - case IIO_MOD_X: - case IIO_MOD_Y: - case IIO_MOD_Z: - ret = sca3000_motion_detect_set_state(indio_dev, - chan->address, - state); - break; - default: - ret = -EINVAL; - break; - } - mutex_unlock(&st->lock); - - return ret; -} - -static int sca3000_configure_ring(struct iio_dev *indio_dev) -{ - struct iio_buffer *buffer; - - buffer = iio_kfifo_allocate(); - if (!buffer) - return -ENOMEM; - - iio_device_attach_buffer(indio_dev, buffer); - indio_dev->modes |= INDIO_BUFFER_SOFTWARE; - - return 0; -} - -static void sca3000_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_kfifo_free(indio_dev->buffer); -} - -static inline -int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state) -{ - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - goto error_ret; - if (state) { - dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n"); - ret = sca3000_write_reg(st, - SCA3000_REG_MODE_ADDR, - (st->rx[0] | SCA3000_REG_MODE_RING_BUF_ENABLE)); - } else - ret = sca3000_write_reg(st, - SCA3000_REG_MODE_ADDR, - (st->rx[0] & ~SCA3000_REG_MODE_RING_BUF_ENABLE)); -error_ret: - mutex_unlock(&st->lock); - - return ret; -} - -/** - * sca3000_hw_ring_preenable() - hw ring buffer preenable function - * @indio_dev: structure representing the IIO device. Device instance - * specific state can be accessed via iio_priv(indio_dev). - * - * Very simple enable function as the chip will allows normal reads - * during ring buffer operation so as long as it is indeed running - * before we notify the core, the precise ordering does not matter. - */ -static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) -{ - int ret; - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - - /* Enable the 50% full interrupt */ - ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); - if (ret) - goto error_unlock; - ret = sca3000_write_reg(st, - SCA3000_REG_INT_MASK_ADDR, - st->rx[0] | SCA3000_REG_INT_MASK_RING_HALF); - if (ret) - goto error_unlock; - - mutex_unlock(&st->lock); - - return __sca3000_hw_ring_state_set(indio_dev, 1); - -error_unlock: - mutex_unlock(&st->lock); - - return ret; -} - -static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev) -{ - int ret; - struct sca3000_state *st = iio_priv(indio_dev); - - ret = __sca3000_hw_ring_state_set(indio_dev, 0); - if (ret) - return ret; - - /* Disable the 50% full interrupt */ - mutex_lock(&st->lock); - - ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); - if (ret) - goto unlock; - ret = sca3000_write_reg(st, - SCA3000_REG_INT_MASK_ADDR, - st->rx[0] & ~SCA3000_REG_INT_MASK_RING_HALF); -unlock: - mutex_unlock(&st->lock); - return ret; -} - -static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { - .preenable = &sca3000_hw_ring_preenable, - .postdisable = &sca3000_hw_ring_postdisable, -}; - -/** - * sca3000_clean_setup() - get the device into a predictable state - * @st: Device instance specific private data structure - * - * Devices use flash memory to store many of the register values - * and hence can come up in somewhat unpredictable states. - * Hence reset everything on driver load. - */ -static int sca3000_clean_setup(struct sca3000_state *st) -{ - int ret; - - mutex_lock(&st->lock); - /* Ensure all interrupts have been acknowledged */ - ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1); - if (ret) - goto error_ret; - - /* Turn off all motion detection channels */ - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); - if (ret < 0) - goto error_ret; - ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL, - ret & SCA3000_MD_CTRL_PROT_MASK); - if (ret) - goto error_ret; - - /* Disable ring buffer */ - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - if (ret < 0) - goto error_ret; - ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, - (ret & SCA3000_REG_OUT_CTRL_PROT_MASK) - | SCA3000_REG_OUT_CTRL_BUF_X_EN - | SCA3000_REG_OUT_CTRL_BUF_Y_EN - | SCA3000_REG_OUT_CTRL_BUF_Z_EN - | SCA3000_REG_OUT_CTRL_BUF_DIV_4); - if (ret) - goto error_ret; - /* Enable interrupts, relevant to mode and set up as active low */ - ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); - if (ret) - goto error_ret; - ret = sca3000_write_reg(st, - SCA3000_REG_INT_MASK_ADDR, - (ret & SCA3000_REG_INT_MASK_PROT_MASK) - | SCA3000_REG_INT_MASK_ACTIVE_LOW); - if (ret) - goto error_ret; - /* - * Select normal measurement mode, free fall off, ring off - * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5 - * as that occurs in one of the example on the datasheet - */ - ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); - if (ret) - goto error_ret; - ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, - (st->rx[0] & SCA3000_MODE_PROT_MASK)); - -error_ret: - mutex_unlock(&st->lock); - return ret; -} - -static const struct iio_info sca3000_info = { - .attrs = &sca3000_attribute_group, - .read_raw = &sca3000_read_raw, - .write_raw = &sca3000_write_raw, - .read_event_value = &sca3000_read_event_value, - .write_event_value = &sca3000_write_event_value, - .read_event_config = &sca3000_read_event_config, - .write_event_config = &sca3000_write_event_config, - .driver_module = THIS_MODULE, -}; - -static int sca3000_probe(struct spi_device *spi) -{ - int ret; - struct sca3000_state *st; - struct iio_dev *indio_dev; - - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->lock); - st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi) - ->driver_data]; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &sca3000_info; - if (st->info->temp_output) { - indio_dev->channels = sca3000_channels_with_temp; - indio_dev->num_channels = - ARRAY_SIZE(sca3000_channels_with_temp); - } else { - indio_dev->channels = sca3000_channels; - indio_dev->num_channels = ARRAY_SIZE(sca3000_channels); - } - indio_dev->modes = INDIO_DIRECT_MODE; - - sca3000_configure_ring(indio_dev); - - if (spi->irq) { - ret = request_threaded_irq(spi->irq, - NULL, - &sca3000_event_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "sca3000", - indio_dev); - if (ret) - return ret; - } - indio_dev->setup_ops = &sca3000_ring_setup_ops; - ret = sca3000_clean_setup(st); - if (ret) - goto error_free_irq; - - ret = sca3000_print_rev(indio_dev); - if (ret) - goto error_free_irq; - - return iio_device_register(indio_dev); - -error_free_irq: - if (spi->irq) - free_irq(spi->irq, indio_dev); - - return ret; -} - -static int sca3000_stop_all_interrupts(struct sca3000_state *st) -{ - int ret; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); - if (ret) - goto error_ret; - ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR, - (st->rx[0] & - ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER | - SCA3000_REG_INT_MASK_RING_HALF | - SCA3000_REG_INT_MASK_ALL_INTS))); -error_ret: - mutex_unlock(&st->lock); - return ret; -} - -static int sca3000_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct sca3000_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - /* Must ensure no interrupts can be generated after this! */ - sca3000_stop_all_interrupts(st); - if (spi->irq) - free_irq(spi->irq, indio_dev); - - sca3000_unconfigure_ring(indio_dev); - - return 0; -} - -static const struct spi_device_id sca3000_id[] = { - {"sca3000_d01", d01}, - {"sca3000_e02", e02}, - {"sca3000_e04", e04}, - {"sca3000_e05", e05}, - {} -}; -MODULE_DEVICE_TABLE(spi, sca3000_id); - -static struct spi_driver sca3000_driver = { - .driver = { - .name = "sca3000", - }, - .probe = sca3000_probe, - .remove = sca3000_remove, - .id_table = sca3000_id, -}; -module_spi_driver(sca3000_driver); - -MODULE_AUTHOR("Jonathan Cameron "); -MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 218e95e9769b8335defc09b04244a78546cfb1e0 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Sat, 15 Oct 2016 22:00:53 -0700 Subject: iio: light: ltr501: claim direct mode during select raw reads Driver was checking for direct mode but not locking it. Use claim/release helper functions to guarantee the device stays in direct mode during required raw read cases. Signed-off-by: Alison Schofield Acked-by: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 3afc53a3d0b6..d57747771197 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -631,14 +631,16 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_PROCESSED: - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; - switch (chan->type) { case IIO_LIGHT: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + mutex_lock(&data->lock_als); ret = ltr501_read_als(data, buf); mutex_unlock(&data->lock_als); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; *val = ltr501_calculate_lux(le16_to_cpu(buf[1]), @@ -648,8 +650,9 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, return -EINVAL; } case IIO_CHAN_INFO_RAW: - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (chan->type) { case IIO_INTENSITY: @@ -657,21 +660,28 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, ret = ltr501_read_als(data, buf); mutex_unlock(&data->lock_als); if (ret < 0) - return ret; + break; *val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ? buf[0] : buf[1]); - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; case IIO_PROXIMITY: mutex_lock(&data->lock_ps); ret = ltr501_read_ps(data); mutex_unlock(&data->lock_ps); if (ret < 0) - return ret; + break; *val = ret & LTR501_PS_DATA_MASK; - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_INTENSITY: -- cgit v1.2.3 From 4aee987380432c5814ef0275d4041de857dc0617 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Sat, 15 Oct 2016 22:02:19 -0700 Subject: iio: light: ltr501: claim direct mode during raw writes Driver was checking for direct mode but not locking it. Use claim/release helper functions to guarantee the device stays in direct mode during all raw write operations. Signed-off-by: Alison Schofield Acked-by: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 81 +++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index d57747771197..b30e0c1c6cc4 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -739,8 +739,9 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, int i, ret, freq_val, freq_val2; struct ltr501_chip_info *info = data->chip_info; - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -749,85 +750,105 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, i = ltr501_get_gain_index(info->als_gain, info->als_gain_tbl_size, val, val2); - if (i < 0) - return -EINVAL; + if (i < 0) { + ret = -EINVAL; + break; + } data->als_contr &= ~info->als_gain_mask; data->als_contr |= i << info->als_gain_shift; - return regmap_write(data->regmap, LTR501_ALS_CONTR, - data->als_contr); + ret = regmap_write(data->regmap, LTR501_ALS_CONTR, + data->als_contr); + break; case IIO_PROXIMITY: i = ltr501_get_gain_index(info->ps_gain, info->ps_gain_tbl_size, val, val2); - if (i < 0) - return -EINVAL; + if (i < 0) { + ret = -EINVAL; + break; + } data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT; - return regmap_write(data->regmap, LTR501_PS_CONTR, - data->ps_contr); + ret = regmap_write(data->regmap, LTR501_PS_CONTR, + data->ps_contr); + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + break; + case IIO_CHAN_INFO_INT_TIME: switch (chan->type) { case IIO_INTENSITY: - if (val != 0) - return -EINVAL; + if (val != 0) { + ret = -EINVAL; + break; + } mutex_lock(&data->lock_als); - i = ltr501_set_it_time(data, val2); + ret = ltr501_set_it_time(data, val2); mutex_unlock(&data->lock_als); - return i; + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + break; + case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_INTENSITY: ret = ltr501_als_read_samp_freq(data, &freq_val, &freq_val2); if (ret < 0) - return ret; + break; ret = ltr501_als_write_samp_freq(data, val, val2); if (ret < 0) - return ret; + break; /* update persistence count when changing frequency */ ret = ltr501_write_intr_prst(data, chan->type, 0, data->als_period); if (ret < 0) - return ltr501_als_write_samp_freq(data, - freq_val, - freq_val2); - return ret; + ret = ltr501_als_write_samp_freq(data, freq_val, + freq_val2); + break; case IIO_PROXIMITY: ret = ltr501_ps_read_samp_freq(data, &freq_val, &freq_val2); if (ret < 0) - return ret; + break; ret = ltr501_ps_write_samp_freq(data, val, val2); if (ret < 0) - return ret; + break; /* update persistence count when changing frequency */ ret = ltr501_write_intr_prst(data, chan->type, 0, data->ps_period); if (ret < 0) - return ltr501_ps_write_samp_freq(data, - freq_val, - freq_val2); - return ret; + ret = ltr501_ps_write_samp_freq(data, freq_val, + freq_val2); + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + break; + + default: + ret = -EINVAL; + break; } - return -EINVAL; + + iio_device_release_direct_mode(indio_dev); + return ret; } static int ltr501_read_thresh(struct iio_dev *indio_dev, -- cgit v1.2.3 From e4a70e3e7d846a8db8e20c18a4d8a6cf35bcf29c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 13 Oct 2016 22:06:04 +0200 Subject: iio: humidity: add support to hts221 rh/temp combo device Add support to STM HTS221 humidity + temperature sensor http://www.st.com/resource/en/datasheet/hts221.pdf - continuous mode support - i2c support - spi support - trigger mode support Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/Kconfig | 22 ++ drivers/iio/humidity/Makefile | 7 + drivers/iio/humidity/hts221.h | 73 ++++ drivers/iio/humidity/hts221_buffer.c | 169 +++++++++ drivers/iio/humidity/hts221_core.c | 687 +++++++++++++++++++++++++++++++++++ drivers/iio/humidity/hts221_i2c.c | 110 ++++++ drivers/iio/humidity/hts221_spi.c | 125 +++++++ 7 files changed, 1193 insertions(+) create mode 100644 drivers/iio/humidity/hts221.h create mode 100644 drivers/iio/humidity/hts221_buffer.c create mode 100644 drivers/iio/humidity/hts221_core.c create mode 100644 drivers/iio/humidity/hts221_i2c.c create mode 100644 drivers/iio/humidity/hts221_spi.c (limited to 'drivers') diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index b17e2e2bd4f5..6fd11d0813ad 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -34,6 +34,28 @@ config HDC100X To compile this driver as a module, choose M here: the module will be called hdc100x. +config HTS221 + tristate "STMicroelectronics HTS221 sensor Driver" + depends on (I2C || SPI) + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select HTS221_I2C if (I2C) + select HTS221_SPI if (SPI_MASTER) + help + Say yes here to build support for STMicroelectronics HTS221 + temperature-humidity sensor + + To compile this driver as a module, choose M here: the module + will be called hts221. + +config HTS221_I2C + tristate + depends on HTS221 + +config HTS221_SPI + tristate + depends on HTS221 + config HTU21 tristate "Measurement Specialties HTU21 humidity & temperature sensor" depends on I2C diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile index 4a73442fcd9c..a6850e47c100 100644 --- a/drivers/iio/humidity/Makefile +++ b/drivers/iio/humidity/Makefile @@ -5,6 +5,13 @@ obj-$(CONFIG_AM2315) += am2315.o obj-$(CONFIG_DHT11) += dht11.o obj-$(CONFIG_HDC100X) += hdc100x.o + +hts221-y := hts221_core.o \ + hts221_buffer.o +obj-$(CONFIG_HTS221) += hts221.o +obj-$(CONFIG_HTS221_I2C) += hts221_i2c.o +obj-$(CONFIG_HTS221_SPI) += hts221_spi.o + obj-$(CONFIG_HTU21) += htu21.o obj-$(CONFIG_SI7005) += si7005.o obj-$(CONFIG_SI7020) += si7020.o diff --git a/drivers/iio/humidity/hts221.h b/drivers/iio/humidity/hts221.h new file mode 100644 index 000000000000..c7154665512e --- /dev/null +++ b/drivers/iio/humidity/hts221.h @@ -0,0 +1,73 @@ +/* + * STMicroelectronics hts221 sensor driver + * + * Copyright 2016 STMicroelectronics Inc. + * + * Lorenzo Bianconi + * + * Licensed under the GPL-2. + */ + +#ifndef HTS221_H +#define HTS221_H + +#define HTS221_DEV_NAME "hts221" + +#include + +#define HTS221_RX_MAX_LENGTH 8 +#define HTS221_TX_MAX_LENGTH 8 + +#define HTS221_DATA_SIZE 2 + +struct hts221_transfer_buffer { + u8 rx_buf[HTS221_RX_MAX_LENGTH]; + u8 tx_buf[HTS221_TX_MAX_LENGTH] ____cacheline_aligned; +}; + +struct hts221_transfer_function { + int (*read)(struct device *dev, u8 addr, int len, u8 *data); + int (*write)(struct device *dev, u8 addr, int len, u8 *data); +}; + +#define HTS221_AVG_DEPTH 8 +struct hts221_avg_avl { + u16 avg; + u8 val; +}; + +enum hts221_sensor_type { + HTS221_SENSOR_H, + HTS221_SENSOR_T, + HTS221_SENSOR_MAX, +}; + +struct hts221_sensor { + u8 cur_avg_idx; + int slope, b_gen; +}; + +struct hts221_hw { + const char *name; + struct device *dev; + + struct mutex lock; + struct iio_trigger *trig; + int irq; + + struct hts221_sensor sensors[HTS221_SENSOR_MAX]; + + u8 odr; + + const struct hts221_transfer_function *tf; + struct hts221_transfer_buffer tb; +}; + +int hts221_config_drdy(struct hts221_hw *hw, bool enable); +int hts221_probe(struct iio_dev *iio_dev); +int hts221_power_on(struct hts221_hw *hw); +int hts221_power_off(struct hts221_hw *hw); +int hts221_allocate_buffers(struct hts221_hw *hw); +int hts221_allocate_trigger(struct hts221_hw *hw); + +#endif /* HTS221_H */ diff --git a/drivers/iio/humidity/hts221_buffer.c b/drivers/iio/humidity/hts221_buffer.c new file mode 100644 index 000000000000..76b2e8130b6f --- /dev/null +++ b/drivers/iio/humidity/hts221_buffer.c @@ -0,0 +1,169 @@ +/* + * STMicroelectronics hts221 sensor driver + * + * Copyright 2016 STMicroelectronics Inc. + * + * Lorenzo Bianconi + * + * Licensed under the GPL-2. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "hts221.h" + +#define HTS221_REG_STATUS_ADDR 0x27 +#define HTS221_RH_DRDY_MASK BIT(1) +#define HTS221_TEMP_DRDY_MASK BIT(0) + +static int hts221_trig_set_state(struct iio_trigger *trig, bool state) +{ + struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig); + struct hts221_hw *hw = iio_priv(iio_dev); + + return hts221_config_drdy(hw, state); +} + +static const struct iio_trigger_ops hts221_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = hts221_trig_set_state, +}; + +static irqreturn_t hts221_trigger_handler_thread(int irq, void *private) +{ + struct hts221_hw *hw = (struct hts221_hw *)private; + u8 status; + int err; + + err = hw->tf->read(hw->dev, HTS221_REG_STATUS_ADDR, sizeof(status), + &status); + if (err < 0) + return IRQ_HANDLED; + + /* + * H_DA bit (humidity data available) is routed to DRDY line. + * Humidity sample is computed after temperature one. + * Here we can assume data channels are both available if H_DA bit + * is set in status register + */ + if (!(status & HTS221_RH_DRDY_MASK)) + return IRQ_NONE; + + iio_trigger_poll_chained(hw->trig); + + return IRQ_HANDLED; +} + +int hts221_allocate_trigger(struct hts221_hw *hw) +{ + struct iio_dev *iio_dev = iio_priv_to_dev(hw); + unsigned long irq_type; + int err; + + irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); + + switch (irq_type) { + case IRQF_TRIGGER_HIGH: + case IRQF_TRIGGER_RISING: + break; + default: + dev_info(hw->dev, + "mode %lx unsupported, using IRQF_TRIGGER_RISING\n", + irq_type); + irq_type = IRQF_TRIGGER_RISING; + break; + } + + err = devm_request_threaded_irq(hw->dev, hw->irq, NULL, + hts221_trigger_handler_thread, + irq_type | IRQF_ONESHOT, + hw->name, hw); + if (err) { + dev_err(hw->dev, "failed to request trigger irq %d\n", + hw->irq); + return err; + } + + hw->trig = devm_iio_trigger_alloc(hw->dev, "%s-trigger", + iio_dev->name); + if (!hw->trig) + return -ENOMEM; + + iio_trigger_set_drvdata(hw->trig, iio_dev); + hw->trig->ops = &hts221_trigger_ops; + hw->trig->dev.parent = hw->dev; + iio_dev->trig = iio_trigger_get(hw->trig); + + return devm_iio_trigger_register(hw->dev, hw->trig); +} + +static int hts221_buffer_preenable(struct iio_dev *iio_dev) +{ + return hts221_power_on(iio_priv(iio_dev)); +} + +static int hts221_buffer_postdisable(struct iio_dev *iio_dev) +{ + return hts221_power_off(iio_priv(iio_dev)); +} + +static const struct iio_buffer_setup_ops hts221_buffer_ops = { + .preenable = hts221_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = hts221_buffer_postdisable, +}; + +static irqreturn_t hts221_buffer_handler_thread(int irq, void *p) +{ + u8 buffer[ALIGN(2 * HTS221_DATA_SIZE, sizeof(s64)) + sizeof(s64)]; + struct iio_poll_func *pf = p; + struct iio_dev *iio_dev = pf->indio_dev; + struct hts221_hw *hw = iio_priv(iio_dev); + struct iio_chan_spec const *ch; + int err; + + /* humidity data */ + ch = &iio_dev->channels[HTS221_SENSOR_H]; + err = hw->tf->read(hw->dev, ch->address, HTS221_DATA_SIZE, + buffer); + if (err < 0) + goto out; + + /* temperature data */ + ch = &iio_dev->channels[HTS221_SENSOR_T]; + err = hw->tf->read(hw->dev, ch->address, HTS221_DATA_SIZE, + buffer + HTS221_DATA_SIZE); + if (err < 0) + goto out; + + iio_push_to_buffers_with_timestamp(iio_dev, buffer, + iio_get_time_ns(iio_dev)); + +out: + iio_trigger_notify_done(hw->trig); + + return IRQ_HANDLED; +} + +int hts221_allocate_buffers(struct hts221_hw *hw) +{ + return devm_iio_triggered_buffer_setup(hw->dev, iio_priv_to_dev(hw), + NULL, hts221_buffer_handler_thread, + &hts221_buffer_ops); +} + +MODULE_AUTHOR("Lorenzo Bianconi "); +MODULE_DESCRIPTION("STMicroelectronics hts221 buffer driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c new file mode 100644 index 000000000000..3f3ef4a1a474 --- /dev/null +++ b/drivers/iio/humidity/hts221_core.c @@ -0,0 +1,687 @@ +/* + * STMicroelectronics hts221 sensor driver + * + * Copyright 2016 STMicroelectronics Inc. + * + * Lorenzo Bianconi + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include + +#include "hts221.h" + +#define HTS221_REG_WHOAMI_ADDR 0x0f +#define HTS221_REG_WHOAMI_VAL 0xbc + +#define HTS221_REG_CNTRL1_ADDR 0x20 +#define HTS221_REG_CNTRL2_ADDR 0x21 +#define HTS221_REG_CNTRL3_ADDR 0x22 + +#define HTS221_REG_AVG_ADDR 0x10 +#define HTS221_REG_H_OUT_L 0x28 +#define HTS221_REG_T_OUT_L 0x2a + +#define HTS221_HUMIDITY_AVG_MASK 0x07 +#define HTS221_TEMP_AVG_MASK 0x38 + +#define HTS221_ODR_MASK 0x87 +#define HTS221_BDU_MASK BIT(2) + +#define HTS221_DRDY_MASK BIT(2) + +#define HTS221_ENABLE_SENSOR BIT(7) + +#define HTS221_HUMIDITY_AVG_4 0x00 /* 0.4 %RH */ +#define HTS221_HUMIDITY_AVG_8 0x01 /* 0.3 %RH */ +#define HTS221_HUMIDITY_AVG_16 0x02 /* 0.2 %RH */ +#define HTS221_HUMIDITY_AVG_32 0x03 /* 0.15 %RH */ +#define HTS221_HUMIDITY_AVG_64 0x04 /* 0.1 %RH */ +#define HTS221_HUMIDITY_AVG_128 0x05 /* 0.07 %RH */ +#define HTS221_HUMIDITY_AVG_256 0x06 /* 0.05 %RH */ +#define HTS221_HUMIDITY_AVG_512 0x07 /* 0.03 %RH */ + +#define HTS221_TEMP_AVG_2 0x00 /* 0.08 degC */ +#define HTS221_TEMP_AVG_4 0x08 /* 0.05 degC */ +#define HTS221_TEMP_AVG_8 0x10 /* 0.04 degC */ +#define HTS221_TEMP_AVG_16 0x18 /* 0.03 degC */ +#define HTS221_TEMP_AVG_32 0x20 /* 0.02 degC */ +#define HTS221_TEMP_AVG_64 0x28 /* 0.015 degC */ +#define HTS221_TEMP_AVG_128 0x30 /* 0.01 degC */ +#define HTS221_TEMP_AVG_256 0x38 /* 0.007 degC */ + +/* calibration registers */ +#define HTS221_REG_0RH_CAL_X_H 0x36 +#define HTS221_REG_1RH_CAL_X_H 0x3a +#define HTS221_REG_0RH_CAL_Y_H 0x30 +#define HTS221_REG_1RH_CAL_Y_H 0x31 +#define HTS221_REG_0T_CAL_X_L 0x3c +#define HTS221_REG_1T_CAL_X_L 0x3e +#define HTS221_REG_0T_CAL_Y_H 0x32 +#define HTS221_REG_1T_CAL_Y_H 0x33 +#define HTS221_REG_T1_T0_CAL_Y_H 0x35 + +struct hts221_odr { + u8 hz; + u8 val; +}; + +struct hts221_avg { + u8 addr; + u8 mask; + struct hts221_avg_avl avg_avl[HTS221_AVG_DEPTH]; +}; + +static const struct hts221_odr hts221_odr_table[] = { + { 1, 0x01 }, /* 1Hz */ + { 7, 0x02 }, /* 7Hz */ + { 13, 0x03 }, /* 12.5Hz */ +}; + +static const struct hts221_avg hts221_avg_list[] = { + { + .addr = HTS221_REG_AVG_ADDR, + .mask = HTS221_HUMIDITY_AVG_MASK, + .avg_avl = { + { 4, HTS221_HUMIDITY_AVG_4 }, + { 8, HTS221_HUMIDITY_AVG_8 }, + { 16, HTS221_HUMIDITY_AVG_16 }, + { 32, HTS221_HUMIDITY_AVG_32 }, + { 64, HTS221_HUMIDITY_AVG_64 }, + { 128, HTS221_HUMIDITY_AVG_128 }, + { 256, HTS221_HUMIDITY_AVG_256 }, + { 512, HTS221_HUMIDITY_AVG_512 }, + }, + }, + { + .addr = HTS221_REG_AVG_ADDR, + .mask = HTS221_TEMP_AVG_MASK, + .avg_avl = { + { 2, HTS221_TEMP_AVG_2 }, + { 4, HTS221_TEMP_AVG_4 }, + { 8, HTS221_TEMP_AVG_8 }, + { 16, HTS221_TEMP_AVG_16 }, + { 32, HTS221_TEMP_AVG_32 }, + { 64, HTS221_TEMP_AVG_64 }, + { 128, HTS221_TEMP_AVG_128 }, + { 256, HTS221_TEMP_AVG_256 }, + }, + }, +}; + +static const struct iio_chan_spec hts221_channels[] = { + { + .type = IIO_HUMIDITYRELATIVE, + .address = HTS221_REG_H_OUT_L, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + }, + { + .type = IIO_TEMP, + .address = HTS221_REG_T_OUT_L, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(2), +}; + +static int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, + u8 val) +{ + u8 data; + int err; + + mutex_lock(&hw->lock); + + err = hw->tf->read(hw->dev, addr, sizeof(data), &data); + if (err < 0) { + dev_err(hw->dev, "failed to read %02x register\n", addr); + goto unlock; + } + + data = (data & ~mask) | (val & mask); + + err = hw->tf->write(hw->dev, addr, sizeof(data), &data); + if (err < 0) + dev_err(hw->dev, "failed to write %02x register\n", addr); + +unlock: + mutex_unlock(&hw->lock); + + return err; +} + +static int hts221_check_whoami(struct hts221_hw *hw) +{ + u8 data; + int err; + + err = hw->tf->read(hw->dev, HTS221_REG_WHOAMI_ADDR, sizeof(data), + &data); + if (err < 0) { + dev_err(hw->dev, "failed to read whoami register\n"); + return err; + } + + if (data != HTS221_REG_WHOAMI_VAL) { + dev_err(hw->dev, "wrong whoami {%02x vs %02x}\n", + data, HTS221_REG_WHOAMI_VAL); + return -ENODEV; + } + + return 0; +} + +int hts221_config_drdy(struct hts221_hw *hw, bool enable) +{ + u8 val = enable ? BIT(2) : 0; + int err; + + err = hts221_write_with_mask(hw, HTS221_REG_CNTRL3_ADDR, + HTS221_DRDY_MASK, val); + + return err < 0 ? err : 0; +} + +static int hts221_update_odr(struct hts221_hw *hw, u8 odr) +{ + int i, err; + u8 val; + + for (i = 0; i < ARRAY_SIZE(hts221_odr_table); i++) + if (hts221_odr_table[i].hz == odr) + break; + + if (i == ARRAY_SIZE(hts221_odr_table)) + return -EINVAL; + + val = HTS221_ENABLE_SENSOR | HTS221_BDU_MASK | hts221_odr_table[i].val; + err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR, + HTS221_ODR_MASK, val); + if (err < 0) + return err; + + hw->odr = odr; + + return 0; +} + +static int hts221_update_avg(struct hts221_hw *hw, + enum hts221_sensor_type type, + u16 val) +{ + int i, err; + const struct hts221_avg *avg = &hts221_avg_list[type]; + + for (i = 0; i < HTS221_AVG_DEPTH; i++) + if (avg->avg_avl[i].avg == val) + break; + + if (i == HTS221_AVG_DEPTH) + return -EINVAL; + + err = hts221_write_with_mask(hw, avg->addr, avg->mask, + avg->avg_avl[i].val); + if (err < 0) + return err; + + hw->sensors[type].cur_avg_idx = i; + + return 0; +} + +static ssize_t hts221_sysfs_sampling_freq(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i; + ssize_t len = 0; + + for (i = 0; i < ARRAY_SIZE(hts221_odr_table); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", + hts221_odr_table[i].hz); + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t +hts221_sysfs_rh_oversampling_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + const struct hts221_avg *avg = &hts221_avg_list[HTS221_SENSOR_H]; + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", + avg->avg_avl[i].avg); + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t +hts221_sysfs_temp_oversampling_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + const struct hts221_avg *avg = &hts221_avg_list[HTS221_SENSOR_T]; + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", + avg->avg_avl[i].avg); + buf[len - 1] = '\n'; + + return len; +} + +int hts221_power_on(struct hts221_hw *hw) +{ + return hts221_update_odr(hw, hw->odr); +} + +int hts221_power_off(struct hts221_hw *hw) +{ + u8 data[] = {0x00, 0x00}; + + return hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data), + data); +} + +static int hts221_parse_temp_caldata(struct hts221_hw *hw) +{ + int err, *slope, *b_gen; + s16 cal_x0, cal_x1, cal_y0, cal_y1; + u8 cal0, cal1; + + err = hw->tf->read(hw->dev, HTS221_REG_0T_CAL_Y_H, + sizeof(cal0), &cal0); + if (err < 0) + return err; + + err = hw->tf->read(hw->dev, HTS221_REG_T1_T0_CAL_Y_H, + sizeof(cal1), &cal1); + if (err < 0) + return err; + cal_y0 = (le16_to_cpu(cal1 & 0x3) << 8) | cal0; + + err = hw->tf->read(hw->dev, HTS221_REG_1T_CAL_Y_H, + sizeof(cal0), &cal0); + if (err < 0) + return err; + cal_y1 = (((cal1 & 0xc) >> 2) << 8) | cal0; + + err = hw->tf->read(hw->dev, HTS221_REG_0T_CAL_X_L, sizeof(cal_x0), + (u8 *)&cal_x0); + if (err < 0) + return err; + cal_x0 = le16_to_cpu(cal_x0); + + err = hw->tf->read(hw->dev, HTS221_REG_1T_CAL_X_L, sizeof(cal_x1), + (u8 *)&cal_x1); + if (err < 0) + return err; + cal_x1 = le16_to_cpu(cal_x1); + + slope = &hw->sensors[HTS221_SENSOR_T].slope; + b_gen = &hw->sensors[HTS221_SENSOR_T].b_gen; + + *slope = ((cal_y1 - cal_y0) * 8000) / (cal_x1 - cal_x0); + *b_gen = (((s32)cal_x1 * cal_y0 - (s32)cal_x0 * cal_y1) * 1000) / + (cal_x1 - cal_x0); + *b_gen *= 8; + + return 0; +} + +static int hts221_parse_rh_caldata(struct hts221_hw *hw) +{ + int err, *slope, *b_gen; + s16 cal_x0, cal_x1, cal_y0, cal_y1; + u8 data; + + err = hw->tf->read(hw->dev, HTS221_REG_0RH_CAL_Y_H, sizeof(data), + &data); + if (err < 0) + return err; + cal_y0 = data; + + err = hw->tf->read(hw->dev, HTS221_REG_1RH_CAL_Y_H, sizeof(data), + &data); + if (err < 0) + return err; + cal_y1 = data; + + err = hw->tf->read(hw->dev, HTS221_REG_0RH_CAL_X_H, sizeof(cal_x0), + (u8 *)&cal_x0); + if (err < 0) + return err; + cal_x0 = le16_to_cpu(cal_x0); + + err = hw->tf->read(hw->dev, HTS221_REG_1RH_CAL_X_H, sizeof(cal_x1), + (u8 *)&cal_x1); + if (err < 0) + return err; + cal_x1 = le16_to_cpu(cal_x1); + + slope = &hw->sensors[HTS221_SENSOR_H].slope; + b_gen = &hw->sensors[HTS221_SENSOR_H].b_gen; + + *slope = ((cal_y1 - cal_y0) * 8000) / (cal_x1 - cal_x0); + *b_gen = (((s32)cal_x1 * cal_y0 - (s32)cal_x0 * cal_y1) * 1000) / + (cal_x1 - cal_x0); + *b_gen *= 8; + + return 0; +} + +static int hts221_get_sensor_scale(struct hts221_hw *hw, + enum iio_chan_type ch_type, + int *val, int *val2) +{ + s64 tmp; + s32 rem, div, data; + + switch (ch_type) { + case IIO_HUMIDITYRELATIVE: + data = hw->sensors[HTS221_SENSOR_H].slope; + div = (1 << 4) * 1000; + break; + case IIO_TEMP: + data = hw->sensors[HTS221_SENSOR_T].slope; + div = (1 << 6) * 1000; + break; + default: + return -EINVAL; + } + + tmp = div_s64(data * 1000000000LL, div); + tmp = div_s64_rem(tmp, 1000000000LL, &rem); + + *val = tmp; + *val2 = rem; + + return IIO_VAL_INT_PLUS_NANO; +} + +static int hts221_get_sensor_offset(struct hts221_hw *hw, + enum iio_chan_type ch_type, + int *val, int *val2) +{ + s64 tmp; + s32 rem, div, data; + + switch (ch_type) { + case IIO_HUMIDITYRELATIVE: + data = hw->sensors[HTS221_SENSOR_H].b_gen; + div = hw->sensors[HTS221_SENSOR_H].slope; + break; + case IIO_TEMP: + data = hw->sensors[HTS221_SENSOR_T].b_gen; + div = hw->sensors[HTS221_SENSOR_T].slope; + break; + default: + return -EINVAL; + } + + tmp = div_s64(data * 1000000000LL, div); + tmp = div_s64_rem(tmp, 1000000000LL, &rem); + + *val = tmp; + *val2 = rem; + + return IIO_VAL_INT_PLUS_NANO; +} + +static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val) +{ + u8 data[HTS221_DATA_SIZE]; + int err; + + err = hts221_power_on(hw); + if (err < 0) + return err; + + msleep(50); + + err = hw->tf->read(hw->dev, addr, sizeof(data), data); + if (err < 0) + return err; + + hts221_power_off(hw); + + *val = (s16)get_unaligned_le16(data); + + return IIO_VAL_INT; +} + +static int hts221_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *ch, + int *val, int *val2, long mask) +{ + struct hts221_hw *hw = iio_priv(iio_dev); + int ret; + + ret = iio_device_claim_direct_mode(iio_dev); + if (ret) + return ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = hts221_read_oneshot(hw, ch->address, val); + break; + case IIO_CHAN_INFO_SCALE: + ret = hts221_get_sensor_scale(hw, ch->type, val, val2); + break; + case IIO_CHAN_INFO_OFFSET: + ret = hts221_get_sensor_offset(hw, ch->type, val, val2); + break; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = hw->odr; + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: { + u8 idx; + const struct hts221_avg *avg; + + switch (ch->type) { + case IIO_HUMIDITYRELATIVE: + avg = &hts221_avg_list[HTS221_SENSOR_H]; + idx = hw->sensors[HTS221_SENSOR_H].cur_avg_idx; + *val = avg->avg_avl[idx].avg; + ret = IIO_VAL_INT; + break; + case IIO_TEMP: + avg = &hts221_avg_list[HTS221_SENSOR_T]; + idx = hw->sensors[HTS221_SENSOR_T].cur_avg_idx; + *val = avg->avg_avl[idx].avg; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + break; + } + default: + ret = -EINVAL; + break; + } + + iio_device_release_direct_mode(iio_dev); + + return ret; +} + +static int hts221_write_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct hts221_hw *hw = iio_priv(iio_dev); + int ret; + + ret = iio_device_claim_direct_mode(iio_dev); + if (ret) + return ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + ret = hts221_update_odr(hw, val); + break; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + switch (chan->type) { + case IIO_HUMIDITYRELATIVE: + ret = hts221_update_avg(hw, HTS221_SENSOR_H, val); + break; + case IIO_TEMP: + ret = hts221_update_avg(hw, HTS221_SENSOR_T, val); + break; + default: + ret = -EINVAL; + break; + } + break; + default: + ret = -EINVAL; + break; + } + + iio_device_release_direct_mode(iio_dev); + + return ret; +} + +static int hts221_validate_trigger(struct iio_dev *iio_dev, + struct iio_trigger *trig) +{ + struct hts221_hw *hw = iio_priv(iio_dev); + + return hw->trig == trig ? 0 : -EINVAL; +} + +static IIO_DEVICE_ATTR(in_humidity_oversampling_ratio_available, S_IRUGO, + hts221_sysfs_rh_oversampling_avail, NULL, 0); +static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available, S_IRUGO, + hts221_sysfs_temp_oversampling_avail, NULL, 0); +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hts221_sysfs_sampling_freq); + +static struct attribute *hts221_attributes[] = { + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_in_humidity_oversampling_ratio_available.dev_attr.attr, + &iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group hts221_attribute_group = { + .attrs = hts221_attributes, +}; + +static const struct iio_info hts221_info = { + .driver_module = THIS_MODULE, + .attrs = &hts221_attribute_group, + .read_raw = hts221_read_raw, + .write_raw = hts221_write_raw, + .validate_trigger = hts221_validate_trigger, +}; + +static const unsigned long hts221_scan_masks[] = {0x3, 0x0}; + +int hts221_probe(struct iio_dev *iio_dev) +{ + struct hts221_hw *hw = iio_priv(iio_dev); + int err; + u8 data; + + mutex_init(&hw->lock); + + err = hts221_check_whoami(hw); + if (err < 0) + return err; + + hw->odr = hts221_odr_table[0].hz; + + iio_dev->modes = INDIO_DIRECT_MODE; + iio_dev->dev.parent = hw->dev; + iio_dev->available_scan_masks = hts221_scan_masks; + iio_dev->channels = hts221_channels; + iio_dev->num_channels = ARRAY_SIZE(hts221_channels); + iio_dev->name = HTS221_DEV_NAME; + iio_dev->info = &hts221_info; + + /* configure humidity sensor */ + err = hts221_parse_rh_caldata(hw); + if (err < 0) { + dev_err(hw->dev, "failed to get rh calibration data\n"); + return err; + } + + data = hts221_avg_list[HTS221_SENSOR_H].avg_avl[3].avg; + err = hts221_update_avg(hw, HTS221_SENSOR_H, data); + if (err < 0) { + dev_err(hw->dev, "failed to set rh oversampling ratio\n"); + return err; + } + + /* configure temperature sensor */ + err = hts221_parse_temp_caldata(hw); + if (err < 0) { + dev_err(hw->dev, + "failed to get temperature calibration data\n"); + return err; + } + + data = hts221_avg_list[HTS221_SENSOR_T].avg_avl[3].avg; + err = hts221_update_avg(hw, HTS221_SENSOR_T, data); + if (err < 0) { + dev_err(hw->dev, + "failed to set temperature oversampling ratio\n"); + return err; + } + + if (hw->irq > 0) { + err = hts221_allocate_buffers(hw); + if (err < 0) + return err; + + err = hts221_allocate_trigger(hw); + if (err) + return err; + } + + return devm_iio_device_register(hw->dev, iio_dev); +} +EXPORT_SYMBOL(hts221_probe); + +MODULE_AUTHOR("Lorenzo Bianconi "); +MODULE_DESCRIPTION("STMicroelectronics hts221 sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c new file mode 100644 index 000000000000..367ecd509f31 --- /dev/null +++ b/drivers/iio/humidity/hts221_i2c.c @@ -0,0 +1,110 @@ +/* + * STMicroelectronics hts221 i2c driver + * + * Copyright 2016 STMicroelectronics Inc. + * + * Lorenzo Bianconi + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include "hts221.h" + +#define I2C_AUTO_INCREMENT 0x80 + +static int hts221_i2c_read(struct device *dev, u8 addr, int len, u8 *data) +{ + struct i2c_msg msg[2]; + struct i2c_client *client = to_i2c_client(dev); + + if (len > 1) + addr |= I2C_AUTO_INCREMENT; + + msg[0].addr = client->addr; + msg[0].flags = client->flags; + msg[0].len = 1; + msg[0].buf = &addr; + + msg[1].addr = client->addr; + msg[1].flags = client->flags | I2C_M_RD; + msg[1].len = len; + msg[1].buf = data; + + return i2c_transfer(client->adapter, msg, 2); +} + +static int hts221_i2c_write(struct device *dev, u8 addr, int len, u8 *data) +{ + u8 send[len + 1]; + struct i2c_msg msg; + struct i2c_client *client = to_i2c_client(dev); + + if (len > 1) + addr |= I2C_AUTO_INCREMENT; + + send[0] = addr; + memcpy(&send[1], data, len * sizeof(u8)); + + msg.addr = client->addr; + msg.flags = client->flags; + msg.len = len + 1; + msg.buf = send; + + return i2c_transfer(client->adapter, &msg, 1); +} + +static const struct hts221_transfer_function hts221_transfer_fn = { + .read = hts221_i2c_read, + .write = hts221_i2c_write, +}; + +static int hts221_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct hts221_hw *hw; + struct iio_dev *iio_dev; + + iio_dev = devm_iio_device_alloc(&client->dev, sizeof(*hw)); + if (!iio_dev) + return -ENOMEM; + + i2c_set_clientdata(client, iio_dev); + + hw = iio_priv(iio_dev); + hw->name = client->name; + hw->dev = &client->dev; + hw->irq = client->irq; + hw->tf = &hts221_transfer_fn; + + return hts221_probe(iio_dev); +} + +static const struct of_device_id hts221_i2c_of_match[] = { + { .compatible = "st,hts221", }, + {}, +}; +MODULE_DEVICE_TABLE(of, hts221_i2c_of_match); + +static const struct i2c_device_id hts221_i2c_id_table[] = { + { HTS221_DEV_NAME }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, hts221_i2c_id_table); + +static struct i2c_driver hts221_driver = { + .driver = { + .name = "hts221_i2c", + .of_match_table = of_match_ptr(hts221_i2c_of_match), + }, + .probe = hts221_i2c_probe, + .id_table = hts221_i2c_id_table, +}; +module_i2c_driver(hts221_driver); + +MODULE_AUTHOR("Lorenzo Bianconi "); +MODULE_DESCRIPTION("STMicroelectronics hts221 i2c driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/humidity/hts221_spi.c b/drivers/iio/humidity/hts221_spi.c new file mode 100644 index 000000000000..70df5e7150c1 --- /dev/null +++ b/drivers/iio/humidity/hts221_spi.c @@ -0,0 +1,125 @@ +/* + * STMicroelectronics hts221 spi driver + * + * Copyright 2016 STMicroelectronics Inc. + * + * Lorenzo Bianconi + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include "hts221.h" + +#define SENSORS_SPI_READ 0x80 +#define SPI_AUTO_INCREMENT 0x40 + +static int hts221_spi_read(struct device *dev, u8 addr, int len, u8 *data) +{ + int err; + struct spi_device *spi = to_spi_device(dev); + struct iio_dev *iio_dev = spi_get_drvdata(spi); + struct hts221_hw *hw = iio_priv(iio_dev); + + struct spi_transfer xfers[] = { + { + .tx_buf = hw->tb.tx_buf, + .bits_per_word = 8, + .len = 1, + }, + { + .rx_buf = hw->tb.rx_buf, + .bits_per_word = 8, + .len = len, + } + }; + + if (len > 1) + addr |= SPI_AUTO_INCREMENT; + hw->tb.tx_buf[0] = addr | SENSORS_SPI_READ; + + err = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); + if (err < 0) + return err; + + memcpy(data, hw->tb.rx_buf, len * sizeof(u8)); + + return len; +} + +static int hts221_spi_write(struct device *dev, u8 addr, int len, u8 *data) +{ + struct spi_device *spi = to_spi_device(dev); + struct iio_dev *iio_dev = spi_get_drvdata(spi); + struct hts221_hw *hw = iio_priv(iio_dev); + + struct spi_transfer xfers = { + .tx_buf = hw->tb.tx_buf, + .bits_per_word = 8, + .len = len + 1, + }; + + if (len >= HTS221_TX_MAX_LENGTH) + return -ENOMEM; + + if (len > 1) + addr |= SPI_AUTO_INCREMENT; + hw->tb.tx_buf[0] = addr; + memcpy(&hw->tb.tx_buf[1], data, len); + + return spi_sync_transfer(spi, &xfers, 1); +} + +static const struct hts221_transfer_function hts221_transfer_fn = { + .read = hts221_spi_read, + .write = hts221_spi_write, +}; + +static int hts221_spi_probe(struct spi_device *spi) +{ + struct hts221_hw *hw; + struct iio_dev *iio_dev; + + iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*hw)); + if (!iio_dev) + return -ENOMEM; + + spi_set_drvdata(spi, iio_dev); + + hw = iio_priv(iio_dev); + hw->name = spi->modalias; + hw->dev = &spi->dev; + hw->irq = spi->irq; + hw->tf = &hts221_transfer_fn; + + return hts221_probe(iio_dev); +} + +static const struct of_device_id hts221_spi_of_match[] = { + { .compatible = "st,hts221", }, + {}, +}; +MODULE_DEVICE_TABLE(of, hts221_spi_of_match); + +static const struct spi_device_id hts221_spi_id_table[] = { + { HTS221_DEV_NAME }, + {}, +}; +MODULE_DEVICE_TABLE(spi, hts221_spi_id_table); + +static struct spi_driver hts221_driver = { + .driver = { + .name = "hts221_spi", + .of_match_table = of_match_ptr(hts221_spi_of_match), + }, + .probe = hts221_spi_probe, + .id_table = hts221_spi_id_table, +}; +module_spi_driver(hts221_driver); + +MODULE_AUTHOR("Lorenzo Bianconi "); +MODULE_DESCRIPTION("STMicroelectronics hts221 spi driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 36534b40673510a0bd0a87cdfaf07cb4596a3159 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:06:56 +0200 Subject: staging:iio:ad7606: Remove unused int_vref_mv field Remove the int_vref_mv field from the ad7606_chip_info struct since the field is never used by the driver. The value is also the same for all derivatives of this chip, so if it will ever be used in the driver a constant value will work just fine. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.h | 2 -- drivers/staging/iio/adc/ad7606_core.c | 3 --- 2 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 39f50440d915..b7e59a6c4b05 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -43,14 +43,12 @@ struct ad7606_platform_data { /** * struct ad7606_chip_info - chip specific information * @name: identification string for chip - * @int_vref_mv: the internal reference voltage * @channels: channel specification * @num_channels: number of channels */ struct ad7606_chip_info { const char *name; - u16 int_vref_mv; const struct iio_chan_spec *channels; unsigned int num_channels; }; diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 204222517a39..a1f18d412cb0 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -261,19 +261,16 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { */ [ID_AD7606_8] = { .name = "ad7606", - .int_vref_mv = 2500, .channels = ad7606_channels, .num_channels = 9, }, [ID_AD7606_6] = { .name = "ad7606-6", - .int_vref_mv = 2500, .channels = ad7606_channels, .num_channels = 7, }, [ID_AD7606_4] = { .name = "ad7606-4", - .int_vref_mv = 2500, .channels = ad7606_channels, .num_channels = 5, }, -- cgit v1.2.3 From 063a51c5bdefaf7972c6ee7945b05eeb7a842961 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:06:57 +0200 Subject: staging:iio:ad7606: Remove redundant name field from ad7606_chip_info The name field in the ad7606_chip_info struct is set to the same value as the as the name field in the corresponding {platform,spi}_device_id table entry. Remove it from the ad7606_chip_info struct and pass the name from the ID to the probe function. This slightly reduces the size of the chip_info table and adding new entries requires less boilerplate. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.h | 4 ++-- drivers/staging/iio/adc/ad7606_core.c | 11 ++++------- drivers/staging/iio/adc/ad7606_par.c | 3 ++- drivers/staging/iio/adc/ad7606_spi.c | 3 ++- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index b7e59a6c4b05..380c56ae6570 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -48,7 +48,6 @@ struct ad7606_platform_data { */ struct ad7606_chip_info { - const char *name; const struct iio_chan_spec *channels; unsigned int num_channels; }; @@ -84,7 +83,8 @@ struct ad7606_bus_ops { }; struct iio_dev *ad7606_probe(struct device *dev, int irq, - void __iomem *base_address, unsigned int id, + void __iomem *base_address, + const char *name, unsigned int id, const struct ad7606_bus_ops *bops); int ad7606_remove(struct iio_dev *indio_dev, int irq); int ad7606_reset(struct ad7606_state *st); diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index a1f18d412cb0..109364750ac7 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -260,17 +260,14 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { * More devices added in future */ [ID_AD7606_8] = { - .name = "ad7606", .channels = ad7606_channels, .num_channels = 9, }, [ID_AD7606_6] = { - .name = "ad7606-6", .channels = ad7606_channels, .num_channels = 7, }, [ID_AD7606_4] = { - .name = "ad7606-4", .channels = ad7606_channels, .num_channels = 5, }, @@ -438,7 +435,7 @@ static const struct iio_info ad7606_info_range = { struct iio_dev *ad7606_probe(struct device *dev, int irq, void __iomem *base_address, - unsigned int id, + const char *name, unsigned int id, const struct ad7606_bus_ops *bops) { struct ad7606_platform_data *pdata = dev->platform_data; @@ -491,7 +488,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, indio_dev->info = &ad7606_info_no_os_or_range; } indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->name = st->chip_info->name; + indio_dev->name = name; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; @@ -505,8 +502,8 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); - ret = request_irq(irq, ad7606_interrupt, - IRQF_TRIGGER_FALLING, st->chip_info->name, indio_dev); + ret = request_irq(irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, name, + indio_dev); if (ret) goto error_free_gpios; diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index 84d23930fdde..0a23cd923415 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -49,6 +49,7 @@ static const struct ad7606_bus_ops ad7606_par8_bops = { static int ad7606_par_probe(struct platform_device *pdev) { + const struct platform_device_id *id = platform_get_device_id(pdev); struct resource *res; struct iio_dev *indio_dev; void __iomem *addr; @@ -69,7 +70,7 @@ static int ad7606_par_probe(struct platform_device *pdev) remap_size = resource_size(res); indio_dev = ad7606_probe(&pdev->dev, irq, addr, - platform_get_device_id(pdev)->driver_data, + id->name, id->driver_data, remap_size > 1 ? &ad7606_par16_bops : &ad7606_par8_bops); diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index 9587fa86dc69..f69db597d6e0 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -42,10 +42,11 @@ static const struct ad7606_bus_ops ad7606_spi_bops = { static int ad7606_spi_probe(struct spi_device *spi) { + const struct spi_device_id *id = spi_get_device_id(spi); struct iio_dev *indio_dev; indio_dev = ad7606_probe(&spi->dev, spi->irq, NULL, - spi_get_device_id(spi)->driver_data, + id->name, id->driver_data, &ad7606_spi_bops); if (IS_ERR(indio_dev)) -- cgit v1.2.3 From 9f72520fa4e0a1c3060c523ca075f323b9c77488 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:06:58 +0200 Subject: staging:iio:ad7606: Remove default device configuration from platform data While for some very selected setups it might be useful to be able to provide default configuration data via the platform data, generally this becomes very impractical as the number of configuration options increases. So the general policy is to use the power-on default values of the device and let the application using the device configure it according to its needs. Implement this scheme for the ad7606 driver by removing support for specifying a default configuration via the platform data. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.h | 4 ---- drivers/staging/iio/adc/ad7606_core.c | 12 ++---------- 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 380c56ae6570..cf6be6500bfb 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -15,8 +15,6 @@ /** * struct ad7606_platform_data - platform/board specific information - * @default_os: default oversampling value {0, 2, 4, 8, 16, 32, 64} - * @default_range: default range +/-{5000, 10000} mVolt * @gpio_convst: number of gpio connected to the CONVST pin * @gpio_reset: gpio connected to the RESET pin, if not used set to -1 * @gpio_range: gpio connected to the RANGE pin, if not used set to -1 @@ -28,8 +26,6 @@ */ struct ad7606_platform_data { - unsigned int default_os; - unsigned int default_range; unsigned int gpio_convst; unsigned int gpio_reset; unsigned int gpio_range; diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 109364750ac7..a16c6f5a333b 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -452,16 +452,8 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, st->dev = dev; st->bops = bops; st->base_address = base_address; - st->range = pdata->default_range == 10000 ? 10000 : 5000; - - ret = ad7606_oversampling_get_index(pdata->default_os); - if (ret < 0) { - dev_warn(dev, "oversampling %d is not supported\n", - pdata->default_os); - st->oversampling = 0; - } else { - st->oversampling = pdata->default_os; - } + st->range = 5000; + st->oversampling = 0; st->reg = devm_regulator_get(dev, "vcc"); if (!IS_ERR(st->reg)) { -- cgit v1.2.3 From aa9602666894ca02935267c348286b4f1efda186 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:06:59 +0200 Subject: staging:iio:ad7606: Remove out-of-band error reporting Currently the ad7606 driver prints a error message to the kernel log when an application writes an invalid value to a sysfs attribute. While for initial driver development and testing this might be useful it is quite disadvantageous in a production environment. The write() call to the sysfs attribute will already return an error if the value was invalid so the application is aware that the operation failed. And generally speaking it is impossible for an application to reliably match a log message in the kernel log to a specific operation it performed, so the message becomes just noise and might distract from more critical messages. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index a16c6f5a333b..d3a35512261a 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -132,10 +132,9 @@ static ssize_t ad7606_store_range(struct device *dev, if (ret) return ret; - if (!(lval == 5000 || lval == 10000)) { - dev_err(dev, "range is not supported\n"); + if (!(lval == 5000 || lval == 10000)) return -EINVAL; - } + mutex_lock(&indio_dev->mlock); gpio_set_value(st->pdata->gpio_range, lval == 10000); st->range = lval; @@ -174,11 +173,8 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, if (val2) return -EINVAL; ret = ad7606_oversampling_get_index(val); - if (ret < 0) { - dev_err(st->dev, "oversampling %d is not supported\n", - val); + if (ret < 0) return ret; - } mutex_lock(&indio_dev->mlock); gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1); -- cgit v1.2.3 From e79e8027c1bb9e5525ad186efef1d89309c378f2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:00 +0200 Subject: staging:iio:ad7606: Use oversampling ratio of 1 for no oversampling Currently the ad7606 driver uses a value of 0 for the oversampling ratio to express that no oversampling is done. Strictly speaking this means though that no data capture is done at all. Instead change the driver to use a value of 1, this is in accordance with what other drivers do and what the IIO spec suggests. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index d3a35512261a..7c093e2a0faf 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -149,7 +149,7 @@ static IIO_CONST_ATTR(in_voltage_range_available, "5000 10000"); static int ad7606_oversampling_get_index(unsigned int val) { - unsigned char supported[] = {0, 2, 4, 8, 16, 32, 64}; + unsigned char supported[] = {1, 2, 4, 8, 16, 32, 64}; int i; for (i = 0; i < ARRAY_SIZE(supported); i++) @@ -188,7 +188,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, } } -static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64"); +static IIO_CONST_ATTR(oversampling_ratio_available, "1 2 4 8 16 32 64"); static struct attribute *ad7606_attributes_os_and_range[] = { &iio_dev_attr_in_voltage_range.dev_attr.attr, @@ -449,7 +449,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, st->bops = bops; st->base_address = base_address; st->range = 5000; - st->oversampling = 0; + st->oversampling = 1; st->reg = devm_regulator_get(dev, "vcc"); if (!IS_ERR(st->reg)) { -- cgit v1.2.3 From f915f7aafba79784b8d89cf186fd63d3b16b91b9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:01 +0200 Subject: staging:iio:ad7606: Avoid allocating buffer for each data capture Currently the ad7606 driver dynamically allocates and frees a transfer buffer each time a sample capture is performed in buffered mode, which introduces unnecessary overhead. The driver state struct already contains a buffer that is used for transfers in one-shot mode. This buffer is large enough to hold all samples, but not the timestamp that might be present in buffered mode. Extend the buffer size to be able to contain the timestamp and update the buffered capture function to use this buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.h | 4 ++-- drivers/staging/iio/adc/ad7606_ring.c | 14 ++++---------- 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index cf6be6500bfb..129f94e57c23 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -68,9 +68,9 @@ struct ad7606_state { /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. + * 8 * 16-bit samples + 64-bit timestamp */ - - unsigned short data[8] ____cacheline_aligned; + unsigned short data[12] ____cacheline_aligned; }; struct ad7606_bus_ops { diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index 0572df9aad85..7fa4ccccb727 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -46,15 +46,10 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) struct ad7606_state *st = container_of(work_s, struct ad7606_state, poll_work); struct iio_dev *indio_dev = iio_priv_to_dev(st); - __u8 *buf; int ret; - buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (!buf) - return; - if (gpio_is_valid(st->pdata->gpio_frstdata)) { - ret = st->bops->read_block(st->dev, 1, buf); + ret = st->bops->read_block(st->dev, 1, st->data); if (ret) goto done; if (!gpio_get_value(st->pdata->gpio_frstdata)) { @@ -67,22 +62,21 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) goto done; } ret = st->bops->read_block(st->dev, - st->chip_info->num_channels - 1, buf + 2); + st->chip_info->num_channels - 1, st->data + 1); if (ret) goto done; } else { ret = st->bops->read_block(st->dev, - st->chip_info->num_channels, buf); + st->chip_info->num_channels, st->data); if (ret) goto done; } - iio_push_to_buffers_with_timestamp(indio_dev, buf, + iio_push_to_buffers_with_timestamp(indio_dev, st->data, iio_get_time_ns(indio_dev)); done: gpio_set_value(st->pdata->gpio_convst, 0); iio_trigger_notify_done(indio_dev->trig); - kfree(buf); } int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) -- cgit v1.2.3 From 91b7334bae734586b153a79fd82873c5d00eb950 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:02 +0200 Subject: staging:iio:ad7606: Factor out common code between periodic and one-shot capture Both the periodic buffer based and one-shot sysfs based capture methods share a large portion of their code. Factor this out into a common helper function. Also provide a comment that better explains in more detail what is going on in the capture function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.h | 1 + drivers/staging/iio/adc/ad7606_core.c | 58 ++++++++++++++++++++++------------- drivers/staging/iio/adc/ad7606_ring.c | 30 +++--------------- 3 files changed, 41 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 129f94e57c23..2257bdbcd73a 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -84,6 +84,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, const struct ad7606_bus_ops *bops); int ad7606_remove(struct iio_dev *indio_dev, int irq); int ad7606_reset(struct ad7606_state *st); +int ad7606_read_samples(struct ad7606_state *st); enum ad7606_supported_device_ids { ID_AD7606_8, diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 7c093e2a0faf..4ce103a16eeb 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -36,6 +36,39 @@ int ad7606_reset(struct ad7606_state *st) return -ENODEV; } +int ad7606_read_samples(struct ad7606_state *st) +{ + unsigned int num = st->chip_info->num_channels; + u16 *data = st->data; + int ret; + + /* + * The frstdata signal is set to high while and after reading the sample + * of the first channel and low for all other channels. This can be used + * to check that the incoming data is correctly aligned. During normal + * operation the data should never become unaligned, but some glitch or + * electrostatic discharge might cause an extra read or clock cycle. + * Monitoring the frstdata signal allows to recover from such failure + * situations. + */ + + if (gpio_is_valid(st->pdata->gpio_frstdata)) { + ret = st->bops->read_block(st->dev, 1, data); + if (ret) + return ret; + + if (!gpio_get_value(st->pdata->gpio_frstdata)) { + ad7606_reset(st); + return -EIO; + } + + data++; + num--; + } + + return st->bops->read_block(st->dev, num, data); +} + static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) { struct ad7606_state *st = iio_priv(indio_dev); @@ -48,28 +81,9 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) if (ret) goto error_ret; - if (gpio_is_valid(st->pdata->gpio_frstdata)) { - ret = st->bops->read_block(st->dev, 1, st->data); - if (ret) - goto error_ret; - if (!gpio_get_value(st->pdata->gpio_frstdata)) { - /* This should never happen */ - ad7606_reset(st); - ret = -EIO; - goto error_ret; - } - ret = st->bops->read_block(st->dev, - st->chip_info->num_channels - 1, &st->data[1]); - if (ret) - goto error_ret; - } else { - ret = st->bops->read_block(st->dev, - st->chip_info->num_channels, st->data); - if (ret) - goto error_ret; - } - - ret = st->data[ch]; + ret = ad7606_read_samples(st); + if (ret == 0) + ret = st->data[ch]; error_ret: gpio_set_value(st->pdata->gpio_convst, 0); diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index 7fa4ccccb727..b7bf0cf87b10 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -48,33 +48,11 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) struct iio_dev *indio_dev = iio_priv_to_dev(st); int ret; - if (gpio_is_valid(st->pdata->gpio_frstdata)) { - ret = st->bops->read_block(st->dev, 1, st->data); - if (ret) - goto done; - if (!gpio_get_value(st->pdata->gpio_frstdata)) { - /* This should never happen. However - * some signal glitch caused by bad PCB desgin or - * electrostatic discharge, could cause an extra read - * or clock. This allows recovery. - */ - ad7606_reset(st); - goto done; - } - ret = st->bops->read_block(st->dev, - st->chip_info->num_channels - 1, st->data + 1); - if (ret) - goto done; - } else { - ret = st->bops->read_block(st->dev, - st->chip_info->num_channels, st->data); - if (ret) - goto done; - } + ret = ad7606_read_samples(st); + if (ret == 0) + iio_push_to_buffers_with_timestamp(indio_dev, st->data, + iio_get_time_ns(indio_dev)); - iio_push_to_buffers_with_timestamp(indio_dev, st->data, - iio_get_time_ns(indio_dev)); -done: gpio_set_value(st->pdata->gpio_convst, 0); iio_trigger_notify_done(indio_dev->trig); } -- cgit v1.2.3 From 382a4777ec03ef2b3320a39eec415003f76e9be4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:03 +0200 Subject: staging:iio:ad7606: Move set_drvdata() into common code Both the platform_device and SPI driver call set_drvdata() at the end of their probe function. Move this into the common probe() function to reduce duplicated code. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 2 ++ drivers/staging/iio/adc/ad7606_par.c | 2 -- drivers/staging/iio/adc/ad7606_spi.c | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 4ce103a16eeb..13d8090bd821 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -517,6 +517,8 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (ret) goto error_unregister_ring; + dev_set_drvdata(dev, indio_dev); + return indio_dev; error_unregister_ring: ad7606_ring_cleanup(indio_dev); diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index 0a23cd923415..c273993a7f2e 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -77,8 +77,6 @@ static int ad7606_par_probe(struct platform_device *pdev) if (IS_ERR(indio_dev)) return PTR_ERR(indio_dev); - platform_set_drvdata(pdev, indio_dev); - return 0; } diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index f69db597d6e0..9abbc151a771 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -52,8 +52,6 @@ static int ad7606_spi_probe(struct spi_device *spi) if (IS_ERR(indio_dev)) return PTR_ERR(indio_dev); - spi_set_drvdata(spi, indio_dev); - return 0; } -- cgit v1.2.3 From 71faca73af90df461c2cb3fccaefcf06793ab99f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:04 +0200 Subject: staging:iio:ad7606: Let the common probe function return int The common probe function for the ad7606 currently returns a struct iio_dev pointer. The returned value is not used by the individual driver probe functions other than for error checking. Let the common probe function return a int instead to report the error value directly (or 0 on success). This allows to simplify the code. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.h | 7 +++---- drivers/staging/iio/adc/ad7606_core.c | 15 +++++++-------- drivers/staging/iio/adc/ad7606_par.c | 14 ++++---------- drivers/staging/iio/adc/ad7606_spi.c | 12 +++--------- 4 files changed, 17 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 2257bdbcd73a..b4b25a2202f2 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -78,10 +78,9 @@ struct ad7606_bus_ops { int (*read_block)(struct device *, int, void *); }; -struct iio_dev *ad7606_probe(struct device *dev, int irq, - void __iomem *base_address, - const char *name, unsigned int id, - const struct ad7606_bus_ops *bops); +int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, + const char *name, unsigned int id, + const struct ad7606_bus_ops *bops); int ad7606_remove(struct iio_dev *indio_dev, int irq); int ad7606_reset(struct ad7606_state *st); int ad7606_read_samples(struct ad7606_state *st); diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 13d8090bd821..1ee7a290cf4d 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -443,10 +443,9 @@ static const struct iio_info ad7606_info_range = { .attrs = &ad7606_attribute_group_range, }; -struct iio_dev *ad7606_probe(struct device *dev, int irq, - void __iomem *base_address, - const char *name, unsigned int id, - const struct ad7606_bus_ops *bops) +int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, + const char *name, unsigned int id, + const struct ad7606_bus_ops *bops) { struct ad7606_platform_data *pdata = dev->platform_data; struct ad7606_state *st; @@ -455,7 +454,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) - return ERR_PTR(-ENOMEM); + return -ENOMEM; st = iio_priv(indio_dev); @@ -469,7 +468,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) - return ERR_PTR(ret); + return ret; } st->pdata = pdata; @@ -519,7 +518,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, dev_set_drvdata(dev, indio_dev); - return indio_dev; + return 0; error_unregister_ring: ad7606_ring_cleanup(indio_dev); @@ -532,7 +531,7 @@ error_free_gpios: error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); - return ERR_PTR(ret); + return ret; } EXPORT_SYMBOL_GPL(ad7606_probe); diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index c273993a7f2e..42eb9e0cae1a 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -51,7 +51,6 @@ static int ad7606_par_probe(struct platform_device *pdev) { const struct platform_device_id *id = platform_get_device_id(pdev); struct resource *res; - struct iio_dev *indio_dev; void __iomem *addr; resource_size_t remap_size; int irq; @@ -69,15 +68,10 @@ static int ad7606_par_probe(struct platform_device *pdev) remap_size = resource_size(res); - indio_dev = ad7606_probe(&pdev->dev, irq, addr, - id->name, id->driver_data, - remap_size > 1 ? &ad7606_par16_bops : - &ad7606_par8_bops); - - if (IS_ERR(indio_dev)) - return PTR_ERR(indio_dev); - - return 0; + return ad7606_probe(&pdev->dev, irq, addr, + id->name, id->driver_data, + remap_size > 1 ? &ad7606_par16_bops : + &ad7606_par8_bops); } static int ad7606_par_remove(struct platform_device *pdev) diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index 9abbc151a771..064c4c217b9b 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -43,16 +43,10 @@ static const struct ad7606_bus_ops ad7606_spi_bops = { static int ad7606_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); - struct iio_dev *indio_dev; - indio_dev = ad7606_probe(&spi->dev, spi->irq, NULL, - id->name, id->driver_data, - &ad7606_spi_bops); - - if (IS_ERR(indio_dev)) - return PTR_ERR(indio_dev); - - return 0; + return ad7606_probe(&spi->dev, spi->irq, NULL, + id->name, id->driver_data, + &ad7606_spi_bops); } static int ad7606_spi_remove(struct spi_device *spi) -- cgit v1.2.3 From a866058f8e40a30c62027990c91aa71008617207 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:05 +0200 Subject: staging:iio:ad7606: Let common remove function take a struct device * Currently the common remove function takes a struct iio_dev *. This parameter is retrieved by the individual driver remove functions by calling get_drvdata() on their device. To simplify the code let the common remove function directly take a struct dev * and do the IIO device in retrieval the common remove function. This also aligns the interface with the common probe function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.h | 2 +- drivers/staging/iio/adc/ad7606_core.c | 3 ++- drivers/staging/iio/adc/ad7606_par.c | 6 +----- drivers/staging/iio/adc/ad7606_spi.c | 4 +--- 4 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index b4b25a2202f2..6dde987f15c1 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -81,7 +81,7 @@ struct ad7606_bus_ops { int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, const char *name, unsigned int id, const struct ad7606_bus_ops *bops); -int ad7606_remove(struct iio_dev *indio_dev, int irq); +int ad7606_remove(struct device *dev, int irq); int ad7606_reset(struct ad7606_state *st); int ad7606_read_samples(struct ad7606_state *st); diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 1ee7a290cf4d..670caa2d3343 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -535,8 +535,9 @@ error_disable_reg: } EXPORT_SYMBOL_GPL(ad7606_probe); -int ad7606_remove(struct iio_dev *indio_dev, int irq) +int ad7606_remove(struct device *dev, int irq) { + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7606_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index 42eb9e0cae1a..cd6c410c0484 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -76,11 +76,7 @@ static int ad7606_par_probe(struct platform_device *pdev) static int ad7606_par_remove(struct platform_device *pdev) { - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - - ad7606_remove(indio_dev, platform_get_irq(pdev, 0)); - - return 0; + return ad7606_remove(&pdev->dev, platform_get_irq(pdev, 0)); } static const struct platform_device_id ad7606_driver_ids[] = { diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index 064c4c217b9b..c9b1f26685f4 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -51,9 +51,7 @@ static int ad7606_spi_probe(struct spi_device *spi) static int ad7606_spi_remove(struct spi_device *spi) { - struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); - - return ad7606_remove(indio_dev, spi->irq); + return ad7606_remove(&spi->dev, spi->irq); } static const struct spi_device_id ad7606_id[] = { -- cgit v1.2.3 From f52666772d579233b5aa3e1fb57187bbec80fc50 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:06 +0200 Subject: staging:iio:ad7606: Run trigger handler only once per trigger event Currently the ad7606 driver installs the same function for the hard-irq and threaded trigger handlers. This was introduced in commit 1caf7cb46135 ("staging:iio:adc:ad7606 Convert to new channel registration method Update Add missing call to iio_trigger_notify_done() Set pollfunc top and bottom half handler"). Unfortunately the commit message does not mention why this was done and Michael does not remember either. Since the trigger handler function is idempotent (set a GPIO to 1) running it twice does not do any harm, but is simply not necessary either. So set the threaded trigger handler for the driver to NULL. While we are at it also remove the function description comment that does no say anything that can't be derived from the function name itself. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_ring.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index b7bf0cf87b10..81e4a0ac51b7 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -18,11 +18,7 @@ #include "ad7606.h" -/** - * ad7606_trigger_handler_th() th/bh of trigger launched polling to ring buffer - * - **/ -static irqreturn_t ad7606_trigger_handler_th_bh(int irq, void *p) +static irqreturn_t ad7606_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct ad7606_state *st = iio_priv(pf->indio_dev); @@ -63,9 +59,8 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); - return iio_triggered_buffer_setup(indio_dev, - &ad7606_trigger_handler_th_bh, &ad7606_trigger_handler_th_bh, - NULL); + return iio_triggered_buffer_setup(indio_dev, &ad7606_trigger_handler, + NULL, NULL); } void ad7606_ring_cleanup(struct iio_dev *indio_dev) -- cgit v1.2.3 From 722407a4e8c03a36736ea4a384688cf8cbf87f4b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:07 +0200 Subject: staging:iio:ad7606: Use GPIO descriptor API Convert the ad7606 driver away from the deprecated legacy GPIO API and use the new GPIO descriptor API. This also means that the platform data struct is now empty and can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.h | 35 ++---- drivers/staging/iio/adc/ad7606_core.c | 200 ++++++++++------------------------ drivers/staging/iio/adc/ad7606_ring.c | 4 +- 3 files changed, 64 insertions(+), 175 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 6dde987f15c1..f5f85faf3921 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -9,33 +9,6 @@ #ifndef IIO_ADC_AD7606_H_ #define IIO_ADC_AD7606_H_ -/* - * TODO: struct ad7606_platform_data needs to go into include/linux/iio - */ - -/** - * struct ad7606_platform_data - platform/board specific information - * @gpio_convst: number of gpio connected to the CONVST pin - * @gpio_reset: gpio connected to the RESET pin, if not used set to -1 - * @gpio_range: gpio connected to the RANGE pin, if not used set to -1 - * @gpio_os0: gpio connected to the OS0 pin, if not used set to -1 - * @gpio_os1: gpio connected to the OS1 pin, if not used set to -1 - * @gpio_os2: gpio connected to the OS2 pin, if not used set to -1 - * @gpio_frstdata: gpio connected to the FRSTDAT pin, if not used set to -1 - * @gpio_stby: gpio connected to the STBY pin, if not used set to -1 - */ - -struct ad7606_platform_data { - unsigned int gpio_convst; - unsigned int gpio_reset; - unsigned int gpio_range; - unsigned int gpio_os0; - unsigned int gpio_os1; - unsigned int gpio_os2; - unsigned int gpio_frstdata; - unsigned int gpio_stby; -}; - /** * struct ad7606_chip_info - chip specific information * @name: identification string for chip @@ -55,7 +28,6 @@ struct ad7606_chip_info { struct ad7606_state { struct device *dev; const struct ad7606_chip_info *chip_info; - struct ad7606_platform_data *pdata; struct regulator *reg; struct work_struct poll_work; wait_queue_head_t wq_data_avail; @@ -65,6 +37,13 @@ struct ad7606_state { bool done; void __iomem *base_address; + struct gpio_desc *gpio_convst; + struct gpio_desc *gpio_reset; + struct gpio_desc *gpio_range; + struct gpio_desc *gpio_standby; + struct gpio_desc *gpio_frstdata; + struct gpio_descs *gpio_os; + /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 670caa2d3343..4ef6cb4a2726 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -26,10 +26,10 @@ int ad7606_reset(struct ad7606_state *st) { - if (gpio_is_valid(st->pdata->gpio_reset)) { - gpio_set_value(st->pdata->gpio_reset, 1); + if (st->gpio_reset) { + gpiod_set_value(st->gpio_reset, 1); ndelay(100); /* t_reset >= 100ns */ - gpio_set_value(st->pdata->gpio_reset, 0); + gpiod_set_value(st->gpio_reset, 0); return 0; } @@ -52,12 +52,12 @@ int ad7606_read_samples(struct ad7606_state *st) * situations. */ - if (gpio_is_valid(st->pdata->gpio_frstdata)) { + if (st->gpio_frstdata) { ret = st->bops->read_block(st->dev, 1, data); if (ret) return ret; - if (!gpio_get_value(st->pdata->gpio_frstdata)) { + if (!gpiod_get_value(st->gpio_frstdata)) { ad7606_reset(st); return -EIO; } @@ -75,7 +75,7 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) int ret; st->done = false; - gpio_set_value(st->pdata->gpio_convst, 1); + gpiod_set_value(st->gpio_convst, 1); ret = wait_event_interruptible(st->wq_data_avail, st->done); if (ret) @@ -86,7 +86,7 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) ret = st->data[ch]; error_ret: - gpio_set_value(st->pdata->gpio_convst, 0); + gpiod_set_value(st->gpio_convst, 0); return ret; } @@ -150,7 +150,7 @@ static ssize_t ad7606_store_range(struct device *dev, return -EINVAL; mutex_lock(&indio_dev->mlock); - gpio_set_value(st->pdata->gpio_range, lval == 10000); + gpiod_set_value(st->gpio_range, lval == 10000); st->range = lval; mutex_unlock(&indio_dev->mlock); @@ -180,6 +180,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, long mask) { struct ad7606_state *st = iio_priv(indio_dev); + int values[3]; int ret; switch (mask) { @@ -190,12 +191,16 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; + values[0] = (ret >> 0) & 1; + values[1] = (ret >> 1) & 1; + values[2] = (ret >> 2) & 1; + mutex_lock(&indio_dev->mlock); - gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1); - gpio_set_value(st->pdata->gpio_os1, (ret >> 1) & 1); - gpio_set_value(st->pdata->gpio_os2, (ret >> 2) & 1); + gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, + values); st->oversampling = val; mutex_unlock(&indio_dev->mlock); + return 0; default: return -EINVAL; @@ -285,119 +290,37 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { static int ad7606_request_gpios(struct ad7606_state *st) { - struct gpio gpio_array[3] = { - [0] = { - .gpio = st->pdata->gpio_os0, - .flags = GPIOF_DIR_OUT | ((st->oversampling & 1) ? - GPIOF_INIT_HIGH : GPIOF_INIT_LOW), - .label = "AD7606_OS0", - }, - [1] = { - .gpio = st->pdata->gpio_os1, - .flags = GPIOF_DIR_OUT | ((st->oversampling & 2) ? - GPIOF_INIT_HIGH : GPIOF_INIT_LOW), - .label = "AD7606_OS1", - }, - [2] = { - .gpio = st->pdata->gpio_os2, - .flags = GPIOF_DIR_OUT | ((st->oversampling & 4) ? - GPIOF_INIT_HIGH : GPIOF_INIT_LOW), - .label = "AD7606_OS2", - }, - }; - int ret; + struct device *dev = st->dev; - if (gpio_is_valid(st->pdata->gpio_convst)) { - ret = gpio_request_one(st->pdata->gpio_convst, - GPIOF_OUT_INIT_LOW, - "AD7606_CONVST"); - if (ret) { - dev_err(st->dev, "failed to request GPIO CONVST\n"); - goto error_ret; - } - } else { - ret = -EIO; - goto error_ret; - } + st->gpio_convst = devm_gpiod_get(dev, "conversion-start", + GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_convst)) + return PTR_ERR(st->gpio_convst); - if (gpio_is_valid(st->pdata->gpio_os0) && - gpio_is_valid(st->pdata->gpio_os1) && - gpio_is_valid(st->pdata->gpio_os2)) { - ret = gpio_request_array(gpio_array, ARRAY_SIZE(gpio_array)); - if (ret < 0) - goto error_free_convst; - } + st->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_reset)) + return PTR_ERR(st->gpio_reset); - if (gpio_is_valid(st->pdata->gpio_reset)) { - ret = gpio_request_one(st->pdata->gpio_reset, - GPIOF_OUT_INIT_LOW, - "AD7606_RESET"); - if (ret < 0) - goto error_free_os; - } + st->gpio_range = devm_gpiod_get_optional(dev, "range", GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_range)) + return PTR_ERR(st->gpio_range); - if (gpio_is_valid(st->pdata->gpio_range)) { - ret = gpio_request_one(st->pdata->gpio_range, GPIOF_DIR_OUT | - ((st->range == 10000) ? GPIOF_INIT_HIGH : - GPIOF_INIT_LOW), "AD7606_RANGE"); - if (ret < 0) - goto error_free_reset; - } - if (gpio_is_valid(st->pdata->gpio_stby)) { - ret = gpio_request_one(st->pdata->gpio_stby, - GPIOF_OUT_INIT_HIGH, - "AD7606_STBY"); - if (ret < 0) - goto error_free_range; - } + st->gpio_standby = devm_gpiod_get_optional(dev, "standby", + GPIOD_OUT_HIGH); + if (IS_ERR(st->gpio_standby)) + return PTR_ERR(st->gpio_standby); - if (gpio_is_valid(st->pdata->gpio_frstdata)) { - ret = gpio_request_one(st->pdata->gpio_frstdata, GPIOF_IN, - "AD7606_FRSTDATA"); - if (ret < 0) - goto error_free_stby; - } + st->gpio_frstdata = devm_gpiod_get_optional(dev, "first-data", + GPIOD_IN); + if (IS_ERR(st->gpio_frstdata)) + return PTR_ERR(st->gpio_frstdata); - return 0; + st->gpio_os = devm_gpiod_get_array_optional(dev, "oversampling-ratio", + GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_os)) + return PTR_ERR(st->gpio_os); -error_free_stby: - if (gpio_is_valid(st->pdata->gpio_stby)) - gpio_free(st->pdata->gpio_stby); -error_free_range: - if (gpio_is_valid(st->pdata->gpio_range)) - gpio_free(st->pdata->gpio_range); -error_free_reset: - if (gpio_is_valid(st->pdata->gpio_reset)) - gpio_free(st->pdata->gpio_reset); -error_free_os: - if (gpio_is_valid(st->pdata->gpio_os0) && - gpio_is_valid(st->pdata->gpio_os1) && - gpio_is_valid(st->pdata->gpio_os2)) - gpio_free_array(gpio_array, ARRAY_SIZE(gpio_array)); -error_free_convst: - gpio_free(st->pdata->gpio_convst); -error_ret: - return ret; -} - -static void ad7606_free_gpios(struct ad7606_state *st) -{ - if (gpio_is_valid(st->pdata->gpio_frstdata)) - gpio_free(st->pdata->gpio_frstdata); - if (gpio_is_valid(st->pdata->gpio_stby)) - gpio_free(st->pdata->gpio_stby); - if (gpio_is_valid(st->pdata->gpio_range)) - gpio_free(st->pdata->gpio_range); - if (gpio_is_valid(st->pdata->gpio_reset)) - gpio_free(st->pdata->gpio_reset); - if (gpio_is_valid(st->pdata->gpio_os0) && - gpio_is_valid(st->pdata->gpio_os1) && - gpio_is_valid(st->pdata->gpio_os2)) { - gpio_free(st->pdata->gpio_os2); - gpio_free(st->pdata->gpio_os1); - gpio_free(st->pdata->gpio_os0); - } - gpio_free(st->pdata->gpio_convst); + return 0; } /** @@ -447,7 +370,6 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, const char *name, unsigned int id, const struct ad7606_bus_ops *bops) { - struct ad7606_platform_data *pdata = dev->platform_data; struct ad7606_state *st; int ret; struct iio_dev *indio_dev; @@ -471,19 +393,20 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, return ret; } - st->pdata = pdata; + ret = ad7606_request_gpios(st); + if (ret) + goto error_disable_reg; + st->chip_info = &ad7606_chip_info_tbl[id]; indio_dev->dev.parent = dev; - if (gpio_is_valid(st->pdata->gpio_os0) && - gpio_is_valid(st->pdata->gpio_os1) && - gpio_is_valid(st->pdata->gpio_os2)) { - if (gpio_is_valid(st->pdata->gpio_range)) + if (st->gpio_os) { + if (st->gpio_range) indio_dev->info = &ad7606_info_os_and_range; else indio_dev->info = &ad7606_info_os; } else { - if (gpio_is_valid(st->pdata->gpio_range)) + if (st->gpio_range) indio_dev->info = &ad7606_info_range; else indio_dev->info = &ad7606_info_no_os_or_range; @@ -495,10 +418,6 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, init_waitqueue_head(&st->wq_data_avail); - ret = ad7606_request_gpios(st); - if (ret) - goto error_disable_reg; - ret = ad7606_reset(st); if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); @@ -506,7 +425,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, ret = request_irq(irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, name, indio_dev); if (ret) - goto error_free_gpios; + goto error_disable_reg; ret = ad7606_register_ring_funcs_and_init(indio_dev); if (ret) @@ -525,9 +444,6 @@ error_unregister_ring: error_free_irq: free_irq(irq, indio_dev); -error_free_gpios: - ad7606_free_gpios(st); - error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); @@ -547,8 +463,6 @@ int ad7606_remove(struct device *dev, int irq) if (!IS_ERR(st->reg)) regulator_disable(st->reg); - ad7606_free_gpios(st); - return 0; } EXPORT_SYMBOL_GPL(ad7606_remove); @@ -560,10 +474,9 @@ static int ad7606_suspend(struct device *dev) struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7606_state *st = iio_priv(indio_dev); - if (gpio_is_valid(st->pdata->gpio_stby)) { - if (gpio_is_valid(st->pdata->gpio_range)) - gpio_set_value(st->pdata->gpio_range, 1); - gpio_set_value(st->pdata->gpio_stby, 0); + if (st->gpio_standby) { + gpiod_set_value(st->gpio_range, 1); + gpiod_set_value(st->gpio_standby, 0); } return 0; @@ -574,12 +487,9 @@ static int ad7606_resume(struct device *dev) struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7606_state *st = iio_priv(indio_dev); - if (gpio_is_valid(st->pdata->gpio_stby)) { - if (gpio_is_valid(st->pdata->gpio_range)) - gpio_set_value(st->pdata->gpio_range, - st->range == 10000); - - gpio_set_value(st->pdata->gpio_stby, 1); + if (st->gpio_standby) { + gpiod_set_value(st->gpio_range, st->range == 10000); + gpiod_set_value(st->gpio_standby, 1); ad7606_reset(st); } diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index 81e4a0ac51b7..68d72b147f59 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -23,7 +23,7 @@ static irqreturn_t ad7606_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct ad7606_state *st = iio_priv(pf->indio_dev); - gpio_set_value(st->pdata->gpio_convst, 1); + gpiod_set_value(st->gpio_convst, 1); return IRQ_HANDLED; } @@ -49,7 +49,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) iio_push_to_buffers_with_timestamp(indio_dev, st->data, iio_get_time_ns(indio_dev)); - gpio_set_value(st->pdata->gpio_convst, 0); + gpiod_set_value(st->gpio_convst, 0); iio_trigger_notify_done(indio_dev->trig); } -- cgit v1.2.3 From fa23105f85749923569a53139a1bb3465bba604d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 19 Oct 2016 19:07:08 +0200 Subject: staging:iio:ad7606: Move buffer code to main source file Currently the ad7606 buffer handling code resides in its own source file. But this file contains only 4 small functions of which half are just wrappers around other functions. Buffer support is also always enabled for this driver, so move them over to the main source file. This reduces the amount of boilerplate code. Also rename the main function from ad7606_core.c to ad7606.c since there is only a single file now. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/Makefile | 1 - drivers/staging/iio/adc/ad7606.c | 545 ++++++++++++++++++++++++++++++++++ drivers/staging/iio/adc/ad7606.h | 5 - drivers/staging/iio/adc/ad7606_core.c | 506 ------------------------------- drivers/staging/iio/adc/ad7606_ring.c | 69 ----- 5 files changed, 545 insertions(+), 581 deletions(-) create mode 100644 drivers/staging/iio/adc/ad7606.c delete mode 100644 drivers/staging/iio/adc/ad7606_core.c delete mode 100644 drivers/staging/iio/adc/ad7606_ring.c (limited to 'drivers') diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index 3cdd83ccec8e..ac09485923b6 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -2,7 +2,6 @@ # Makefile for industrial I/O ADC drivers # -ad7606-y := ad7606_core.o ad7606_ring.o obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o obj-$(CONFIG_AD7606) += ad7606.o diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c new file mode 100644 index 000000000000..010c6e16fb7c --- /dev/null +++ b/drivers/staging/iio/adc/ad7606.c @@ -0,0 +1,545 @@ +/* + * AD7606 SPI ADC driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ad7606.h" + +static int ad7606_reset(struct ad7606_state *st) +{ + if (st->gpio_reset) { + gpiod_set_value(st->gpio_reset, 1); + ndelay(100); /* t_reset >= 100ns */ + gpiod_set_value(st->gpio_reset, 0); + return 0; + } + + return -ENODEV; +} + +static int ad7606_read_samples(struct ad7606_state *st) +{ + unsigned int num = st->chip_info->num_channels; + u16 *data = st->data; + int ret; + + /* + * The frstdata signal is set to high while and after reading the sample + * of the first channel and low for all other channels. This can be used + * to check that the incoming data is correctly aligned. During normal + * operation the data should never become unaligned, but some glitch or + * electrostatic discharge might cause an extra read or clock cycle. + * Monitoring the frstdata signal allows to recover from such failure + * situations. + */ + + if (st->gpio_frstdata) { + ret = st->bops->read_block(st->dev, 1, data); + if (ret) + return ret; + + if (!gpiod_get_value(st->gpio_frstdata)) { + ad7606_reset(st); + return -EIO; + } + + data++; + num--; + } + + return st->bops->read_block(st->dev, num, data); +} + +static irqreturn_t ad7606_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct ad7606_state *st = iio_priv(pf->indio_dev); + + gpiod_set_value(st->gpio_convst, 1); + + return IRQ_HANDLED; +} + +/** + * ad7606_poll_bh_to_ring() bh of trigger launched polling to ring buffer + * @work_s: the work struct through which this was scheduled + * + * Currently there is no option in this driver to disable the saving of + * timestamps within the ring. + * I think the one copy of this at a time was to avoid problems if the + * trigger was set far too high and the reads then locked up the computer. + **/ +static void ad7606_poll_bh_to_ring(struct work_struct *work_s) +{ + struct ad7606_state *st = container_of(work_s, struct ad7606_state, + poll_work); + struct iio_dev *indio_dev = iio_priv_to_dev(st); + int ret; + + ret = ad7606_read_samples(st); + if (ret == 0) + iio_push_to_buffers_with_timestamp(indio_dev, st->data, + iio_get_time_ns(indio_dev)); + + gpiod_set_value(st->gpio_convst, 0); + iio_trigger_notify_done(indio_dev->trig); +} + +static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) +{ + struct ad7606_state *st = iio_priv(indio_dev); + int ret; + + st->done = false; + gpiod_set_value(st->gpio_convst, 1); + + ret = wait_event_interruptible(st->wq_data_avail, st->done); + if (ret) + goto error_ret; + + ret = ad7606_read_samples(st); + if (ret == 0) + ret = st->data[ch]; + +error_ret: + gpiod_set_value(st->gpio_convst, 0); + + return ret; +} + +static int ad7606_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + int ret; + struct ad7606_state *st = iio_priv(indio_dev); + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = ad7606_scan_direct(indio_dev, chan->address); + iio_device_release_direct_mode(indio_dev); + + if (ret < 0) + return ret; + *val = (short)ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = st->range * 2; + *val2 = st->chip_info->channels[0].scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = st->oversampling; + return IIO_VAL_INT; + } + return -EINVAL; +} + +static ssize_t ad7606_show_range(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%u\n", st->range); +} + +static ssize_t ad7606_store_range(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7606_state *st = iio_priv(indio_dev); + unsigned long lval; + int ret; + + ret = kstrtoul(buf, 10, &lval); + if (ret) + return ret; + + if (!(lval == 5000 || lval == 10000)) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + gpiod_set_value(st->gpio_range, lval == 10000); + st->range = lval; + mutex_unlock(&indio_dev->mlock); + + return count; +} + +static IIO_DEVICE_ATTR(in_voltage_range, S_IRUGO | S_IWUSR, + ad7606_show_range, ad7606_store_range, 0); +static IIO_CONST_ATTR(in_voltage_range_available, "5000 10000"); + +static int ad7606_oversampling_get_index(unsigned int val) +{ + unsigned char supported[] = {1, 2, 4, 8, 16, 32, 64}; + int i; + + for (i = 0; i < ARRAY_SIZE(supported); i++) + if (val == supported[i]) + return i; + + return -EINVAL; +} + +static int ad7606_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad7606_state *st = iio_priv(indio_dev); + int values[3]; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + if (val2) + return -EINVAL; + ret = ad7606_oversampling_get_index(val); + if (ret < 0) + return ret; + + values[0] = (ret >> 0) & 1; + values[1] = (ret >> 1) & 1; + values[2] = (ret >> 2) & 1; + + mutex_lock(&indio_dev->mlock); + gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, + values); + st->oversampling = val; + mutex_unlock(&indio_dev->mlock); + + return 0; + default: + return -EINVAL; + } +} + +static IIO_CONST_ATTR(oversampling_ratio_available, "1 2 4 8 16 32 64"); + +static struct attribute *ad7606_attributes_os_and_range[] = { + &iio_dev_attr_in_voltage_range.dev_attr.attr, + &iio_const_attr_in_voltage_range_available.dev_attr.attr, + &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_os_and_range = { + .attrs = ad7606_attributes_os_and_range, +}; + +static struct attribute *ad7606_attributes_os[] = { + &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_os = { + .attrs = ad7606_attributes_os, +}; + +static struct attribute *ad7606_attributes_range[] = { + &iio_dev_attr_in_voltage_range.dev_attr.attr, + &iio_const_attr_in_voltage_range_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_range = { + .attrs = ad7606_attributes_range, +}; + +#define AD7606_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num, \ + .address = num, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .info_mask_shared_by_all = \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .scan_index = num, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ + } + +static const struct iio_chan_spec ad7606_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(8), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), + AD7606_CHANNEL(4), + AD7606_CHANNEL(5), + AD7606_CHANNEL(6), + AD7606_CHANNEL(7), +}; + +static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { + /* + * More devices added in future + */ + [ID_AD7606_8] = { + .channels = ad7606_channels, + .num_channels = 9, + }, + [ID_AD7606_6] = { + .channels = ad7606_channels, + .num_channels = 7, + }, + [ID_AD7606_4] = { + .channels = ad7606_channels, + .num_channels = 5, + }, +}; + +static int ad7606_request_gpios(struct ad7606_state *st) +{ + struct device *dev = st->dev; + + st->gpio_convst = devm_gpiod_get(dev, "conversion-start", + GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_convst)) + return PTR_ERR(st->gpio_convst); + + st->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_reset)) + return PTR_ERR(st->gpio_reset); + + st->gpio_range = devm_gpiod_get_optional(dev, "range", GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_range)) + return PTR_ERR(st->gpio_range); + + st->gpio_standby = devm_gpiod_get_optional(dev, "standby", + GPIOD_OUT_HIGH); + if (IS_ERR(st->gpio_standby)) + return PTR_ERR(st->gpio_standby); + + st->gpio_frstdata = devm_gpiod_get_optional(dev, "first-data", + GPIOD_IN); + if (IS_ERR(st->gpio_frstdata)) + return PTR_ERR(st->gpio_frstdata); + + st->gpio_os = devm_gpiod_get_array_optional(dev, "oversampling-ratio", + GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_os)) + return PTR_ERR(st->gpio_os); + + return 0; +} + +/** + * Interrupt handler + */ +static irqreturn_t ad7606_interrupt(int irq, void *dev_id) +{ + struct iio_dev *indio_dev = dev_id; + struct ad7606_state *st = iio_priv(indio_dev); + + if (iio_buffer_enabled(indio_dev)) { + schedule_work(&st->poll_work); + } else { + st->done = true; + wake_up_interruptible(&st->wq_data_avail); + } + + return IRQ_HANDLED; +}; + +static const struct iio_info ad7606_info_no_os_or_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, +}; + +static const struct iio_info ad7606_info_os_and_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, + .attrs = &ad7606_attribute_group_os_and_range, +}; + +static const struct iio_info ad7606_info_os = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, + .attrs = &ad7606_attribute_group_os, +}; + +static const struct iio_info ad7606_info_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_range, +}; + +int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, + const char *name, unsigned int id, + const struct ad7606_bus_ops *bops) +{ + struct ad7606_state *st; + int ret; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->dev = dev; + st->bops = bops; + st->base_address = base_address; + st->range = 5000; + st->oversampling = 1; + INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); + + st->reg = devm_regulator_get(dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + return ret; + } + + ret = ad7606_request_gpios(st); + if (ret) + goto error_disable_reg; + + st->chip_info = &ad7606_chip_info_tbl[id]; + + indio_dev->dev.parent = dev; + if (st->gpio_os) { + if (st->gpio_range) + indio_dev->info = &ad7606_info_os_and_range; + else + indio_dev->info = &ad7606_info_os; + } else { + if (st->gpio_range) + indio_dev->info = &ad7606_info_range; + else + indio_dev->info = &ad7606_info_no_os_or_range; + } + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = name; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + + init_waitqueue_head(&st->wq_data_avail); + + ret = ad7606_reset(st); + if (ret) + dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); + + ret = request_irq(irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, name, + indio_dev); + if (ret) + goto error_disable_reg; + + ret = iio_triggered_buffer_setup(indio_dev, &ad7606_trigger_handler, + NULL, NULL); + if (ret) + goto error_free_irq; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_unregister_ring; + + dev_set_drvdata(dev, indio_dev); + + return 0; +error_unregister_ring: + iio_triggered_buffer_cleanup(indio_dev); + +error_free_irq: + free_irq(irq, indio_dev); + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); + return ret; +} +EXPORT_SYMBOL_GPL(ad7606_probe); + +int ad7606_remove(struct device *dev, int irq) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + free_irq(irq, indio_dev); + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); + + return 0; +} +EXPORT_SYMBOL_GPL(ad7606_remove); + +#ifdef CONFIG_PM_SLEEP + +static int ad7606_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + if (st->gpio_standby) { + gpiod_set_value(st->gpio_range, 1); + gpiod_set_value(st->gpio_standby, 0); + } + + return 0; +} + +static int ad7606_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + if (st->gpio_standby) { + gpiod_set_value(st->gpio_range, st->range == 10000); + gpiod_set_value(st->gpio_standby, 1); + ad7606_reset(st); + } + + return 0; +} + +SIMPLE_DEV_PM_OPS(ad7606_pm_ops, ad7606_suspend, ad7606_resume); +EXPORT_SYMBOL_GPL(ad7606_pm_ops); + +#endif + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index f5f85faf3921..746f9553d2ba 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -61,8 +61,6 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, const char *name, unsigned int id, const struct ad7606_bus_ops *bops); int ad7606_remove(struct device *dev, int irq); -int ad7606_reset(struct ad7606_state *st); -int ad7606_read_samples(struct ad7606_state *st); enum ad7606_supported_device_ids { ID_AD7606_8, @@ -70,9 +68,6 @@ enum ad7606_supported_device_ids { ID_AD7606_4 }; -int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev); -void ad7606_ring_cleanup(struct iio_dev *indio_dev); - #ifdef CONFIG_PM_SLEEP extern const struct dev_pm_ops ad7606_pm_ops; #define AD7606_PM_OPS (&ad7606_pm_ops) diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c deleted file mode 100644 index 4ef6cb4a2726..000000000000 --- a/drivers/staging/iio/adc/ad7606_core.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * AD7606 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ad7606.h" - -int ad7606_reset(struct ad7606_state *st) -{ - if (st->gpio_reset) { - gpiod_set_value(st->gpio_reset, 1); - ndelay(100); /* t_reset >= 100ns */ - gpiod_set_value(st->gpio_reset, 0); - return 0; - } - - return -ENODEV; -} - -int ad7606_read_samples(struct ad7606_state *st) -{ - unsigned int num = st->chip_info->num_channels; - u16 *data = st->data; - int ret; - - /* - * The frstdata signal is set to high while and after reading the sample - * of the first channel and low for all other channels. This can be used - * to check that the incoming data is correctly aligned. During normal - * operation the data should never become unaligned, but some glitch or - * electrostatic discharge might cause an extra read or clock cycle. - * Monitoring the frstdata signal allows to recover from such failure - * situations. - */ - - if (st->gpio_frstdata) { - ret = st->bops->read_block(st->dev, 1, data); - if (ret) - return ret; - - if (!gpiod_get_value(st->gpio_frstdata)) { - ad7606_reset(st); - return -EIO; - } - - data++; - num--; - } - - return st->bops->read_block(st->dev, num, data); -} - -static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) -{ - struct ad7606_state *st = iio_priv(indio_dev); - int ret; - - st->done = false; - gpiod_set_value(st->gpio_convst, 1); - - ret = wait_event_interruptible(st->wq_data_avail, st->done); - if (ret) - goto error_ret; - - ret = ad7606_read_samples(st); - if (ret == 0) - ret = st->data[ch]; - -error_ret: - gpiod_set_value(st->gpio_convst, 0); - - return ret; -} - -static int ad7606_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - int ret; - struct ad7606_state *st = iio_priv(indio_dev); - - switch (m) { - case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - ret = ad7606_scan_direct(indio_dev, chan->address); - iio_device_release_direct_mode(indio_dev); - - if (ret < 0) - return ret; - *val = (short)ret; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - *val = st->range * 2; - *val2 = st->chip_info->channels[0].scan_type.realbits; - return IIO_VAL_FRACTIONAL_LOG2; - case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - *val = st->oversampling; - return IIO_VAL_INT; - } - return -EINVAL; -} - -static ssize_t ad7606_show_range(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%u\n", st->range); -} - -static ssize_t ad7606_store_range(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7606_state *st = iio_priv(indio_dev); - unsigned long lval; - int ret; - - ret = kstrtoul(buf, 10, &lval); - if (ret) - return ret; - - if (!(lval == 5000 || lval == 10000)) - return -EINVAL; - - mutex_lock(&indio_dev->mlock); - gpiod_set_value(st->gpio_range, lval == 10000); - st->range = lval; - mutex_unlock(&indio_dev->mlock); - - return count; -} - -static IIO_DEVICE_ATTR(in_voltage_range, S_IRUGO | S_IWUSR, - ad7606_show_range, ad7606_store_range, 0); -static IIO_CONST_ATTR(in_voltage_range_available, "5000 10000"); - -static int ad7606_oversampling_get_index(unsigned int val) -{ - unsigned char supported[] = {1, 2, 4, 8, 16, 32, 64}; - int i; - - for (i = 0; i < ARRAY_SIZE(supported); i++) - if (val == supported[i]) - return i; - - return -EINVAL; -} - -static int ad7606_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad7606_state *st = iio_priv(indio_dev); - int values[3]; - int ret; - - switch (mask) { - case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - if (val2) - return -EINVAL; - ret = ad7606_oversampling_get_index(val); - if (ret < 0) - return ret; - - values[0] = (ret >> 0) & 1; - values[1] = (ret >> 1) & 1; - values[2] = (ret >> 2) & 1; - - mutex_lock(&indio_dev->mlock); - gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, - values); - st->oversampling = val; - mutex_unlock(&indio_dev->mlock); - - return 0; - default: - return -EINVAL; - } -} - -static IIO_CONST_ATTR(oversampling_ratio_available, "1 2 4 8 16 32 64"); - -static struct attribute *ad7606_attributes_os_and_range[] = { - &iio_dev_attr_in_voltage_range.dev_attr.attr, - &iio_const_attr_in_voltage_range_available.dev_attr.attr, - &iio_const_attr_oversampling_ratio_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7606_attribute_group_os_and_range = { - .attrs = ad7606_attributes_os_and_range, -}; - -static struct attribute *ad7606_attributes_os[] = { - &iio_const_attr_oversampling_ratio_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7606_attribute_group_os = { - .attrs = ad7606_attributes_os, -}; - -static struct attribute *ad7606_attributes_range[] = { - &iio_dev_attr_in_voltage_range.dev_attr.attr, - &iio_const_attr_in_voltage_range_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7606_attribute_group_range = { - .attrs = ad7606_attributes_range, -}; - -#define AD7606_CHANNEL(num) \ - { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = num, \ - .address = num, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ - .info_mask_shared_by_all = \ - BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ - .scan_index = num, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ - .endianness = IIO_CPU, \ - }, \ - } - -static const struct iio_chan_spec ad7606_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0), - AD7606_CHANNEL(1), - AD7606_CHANNEL(2), - AD7606_CHANNEL(3), - AD7606_CHANNEL(4), - AD7606_CHANNEL(5), - AD7606_CHANNEL(6), - AD7606_CHANNEL(7), -}; - -static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { - /* - * More devices added in future - */ - [ID_AD7606_8] = { - .channels = ad7606_channels, - .num_channels = 9, - }, - [ID_AD7606_6] = { - .channels = ad7606_channels, - .num_channels = 7, - }, - [ID_AD7606_4] = { - .channels = ad7606_channels, - .num_channels = 5, - }, -}; - -static int ad7606_request_gpios(struct ad7606_state *st) -{ - struct device *dev = st->dev; - - st->gpio_convst = devm_gpiod_get(dev, "conversion-start", - GPIOD_OUT_LOW); - if (IS_ERR(st->gpio_convst)) - return PTR_ERR(st->gpio_convst); - - st->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(st->gpio_reset)) - return PTR_ERR(st->gpio_reset); - - st->gpio_range = devm_gpiod_get_optional(dev, "range", GPIOD_OUT_LOW); - if (IS_ERR(st->gpio_range)) - return PTR_ERR(st->gpio_range); - - st->gpio_standby = devm_gpiod_get_optional(dev, "standby", - GPIOD_OUT_HIGH); - if (IS_ERR(st->gpio_standby)) - return PTR_ERR(st->gpio_standby); - - st->gpio_frstdata = devm_gpiod_get_optional(dev, "first-data", - GPIOD_IN); - if (IS_ERR(st->gpio_frstdata)) - return PTR_ERR(st->gpio_frstdata); - - st->gpio_os = devm_gpiod_get_array_optional(dev, "oversampling-ratio", - GPIOD_OUT_LOW); - if (IS_ERR(st->gpio_os)) - return PTR_ERR(st->gpio_os); - - return 0; -} - -/** - * Interrupt handler - */ -static irqreturn_t ad7606_interrupt(int irq, void *dev_id) -{ - struct iio_dev *indio_dev = dev_id; - struct ad7606_state *st = iio_priv(indio_dev); - - if (iio_buffer_enabled(indio_dev)) { - schedule_work(&st->poll_work); - } else { - st->done = true; - wake_up_interruptible(&st->wq_data_avail); - } - - return IRQ_HANDLED; -}; - -static const struct iio_info ad7606_info_no_os_or_range = { - .driver_module = THIS_MODULE, - .read_raw = &ad7606_read_raw, -}; - -static const struct iio_info ad7606_info_os_and_range = { - .driver_module = THIS_MODULE, - .read_raw = &ad7606_read_raw, - .write_raw = &ad7606_write_raw, - .attrs = &ad7606_attribute_group_os_and_range, -}; - -static const struct iio_info ad7606_info_os = { - .driver_module = THIS_MODULE, - .read_raw = &ad7606_read_raw, - .write_raw = &ad7606_write_raw, - .attrs = &ad7606_attribute_group_os, -}; - -static const struct iio_info ad7606_info_range = { - .driver_module = THIS_MODULE, - .read_raw = &ad7606_read_raw, - .attrs = &ad7606_attribute_group_range, -}; - -int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, - const char *name, unsigned int id, - const struct ad7606_bus_ops *bops) -{ - struct ad7606_state *st; - int ret; - struct iio_dev *indio_dev; - - indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - - st = iio_priv(indio_dev); - - st->dev = dev; - st->bops = bops; - st->base_address = base_address; - st->range = 5000; - st->oversampling = 1; - - st->reg = devm_regulator_get(dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - return ret; - } - - ret = ad7606_request_gpios(st); - if (ret) - goto error_disable_reg; - - st->chip_info = &ad7606_chip_info_tbl[id]; - - indio_dev->dev.parent = dev; - if (st->gpio_os) { - if (st->gpio_range) - indio_dev->info = &ad7606_info_os_and_range; - else - indio_dev->info = &ad7606_info_os; - } else { - if (st->gpio_range) - indio_dev->info = &ad7606_info_range; - else - indio_dev->info = &ad7606_info_no_os_or_range; - } - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->name = name; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; - - init_waitqueue_head(&st->wq_data_avail); - - ret = ad7606_reset(st); - if (ret) - dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); - - ret = request_irq(irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, name, - indio_dev); - if (ret) - goto error_disable_reg; - - ret = ad7606_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_free_irq; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_unregister_ring; - - dev_set_drvdata(dev, indio_dev); - - return 0; -error_unregister_ring: - ad7606_ring_cleanup(indio_dev); - -error_free_irq: - free_irq(irq, indio_dev); - -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); - return ret; -} -EXPORT_SYMBOL_GPL(ad7606_probe); - -int ad7606_remove(struct device *dev, int irq) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - ad7606_ring_cleanup(indio_dev); - - free_irq(irq, indio_dev); - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); - - return 0; -} -EXPORT_SYMBOL_GPL(ad7606_remove); - -#ifdef CONFIG_PM_SLEEP - -static int ad7606_suspend(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - if (st->gpio_standby) { - gpiod_set_value(st->gpio_range, 1); - gpiod_set_value(st->gpio_standby, 0); - } - - return 0; -} - -static int ad7606_resume(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - if (st->gpio_standby) { - gpiod_set_value(st->gpio_range, st->range == 10000); - gpiod_set_value(st->gpio_standby, 1); - ad7606_reset(st); - } - - return 0; -} - -SIMPLE_DEV_PM_OPS(ad7606_pm_ops, ad7606_suspend, ad7606_resume); -EXPORT_SYMBOL_GPL(ad7606_pm_ops); - -#endif - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c deleted file mode 100644 index 68d72b147f59..000000000000 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2011-2012 Analog Devices Inc. - * - * Licensed under the GPL-2. - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ad7606.h" - -static irqreturn_t ad7606_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct ad7606_state *st = iio_priv(pf->indio_dev); - - gpiod_set_value(st->gpio_convst, 1); - - return IRQ_HANDLED; -} - -/** - * ad7606_poll_bh_to_ring() bh of trigger launched polling to ring buffer - * @work_s: the work struct through which this was scheduled - * - * Currently there is no option in this driver to disable the saving of - * timestamps within the ring. - * I think the one copy of this at a time was to avoid problems if the - * trigger was set far too high and the reads then locked up the computer. - **/ -static void ad7606_poll_bh_to_ring(struct work_struct *work_s) -{ - struct ad7606_state *st = container_of(work_s, struct ad7606_state, - poll_work); - struct iio_dev *indio_dev = iio_priv_to_dev(st); - int ret; - - ret = ad7606_read_samples(st); - if (ret == 0) - iio_push_to_buffers_with_timestamp(indio_dev, st->data, - iio_get_time_ns(indio_dev)); - - gpiod_set_value(st->gpio_convst, 0); - iio_trigger_notify_done(indio_dev->trig); -} - -int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - struct ad7606_state *st = iio_priv(indio_dev); - - INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); - - return iio_triggered_buffer_setup(indio_dev, &ad7606_trigger_handler, - NULL, NULL); -} - -void ad7606_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_triggered_buffer_cleanup(indio_dev); -} -- cgit v1.2.3 From 12edb97471fd4877bc0e527a42e0cbf8ab3937a5 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Thu, 20 Oct 2016 21:08:22 +0800 Subject: staging: iio: ad7606: set proper supply name to devm_regulator_get() The name passed to devm_regulator_get() should match the name of the supply as specified in the device datasheet. The supply on this device is called 'AVcc' while currently, the driver uses just 'vcc'. Use 'avcc' to specify the supply voltage since it is custom to use the lower-caps version of the datasheet name. Suggested-by: Lars-Peter Clausen Signed-off-by: Eva Rachel Retuya Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index 010c6e16fb7c..f9b354ff820a 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -424,7 +424,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, st->oversampling = 1; INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); - st->reg = devm_regulator_get(dev, "vcc"); + st->reg = devm_regulator_get(dev, "avcc"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) -- cgit v1.2.3 From f0879217a8710289f3a9bac9e5db8f73e8189750 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Thu, 20 Oct 2016 21:08:23 +0800 Subject: staging: iio: ad7606: rework regulator handling Currently, this driver ignores all errors from regulator_get(). The way it is now, it also breaks probe deferral (EPROBE_DEFER). The correct behavior is to propagate the error to the upper layers so they can handle it accordingly. Rework the regulator handling so that it matches the standard behavior. If the specific design uses a static always-on regulator and does not explicitly specify it, regulator_get() will return the dummy regulator. Suggested-by: Lars-Peter Clausen Signed-off-by: Eva Rachel Retuya Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index f9b354ff820a..b0ae04a449ea 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -425,10 +425,13 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); st->reg = devm_regulator_get(dev, "avcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - return ret; + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); + + ret = regulator_enable(st->reg); + if (ret) { + dev_err(dev, "Failed to enable specified AVcc supply\n"); + return ret; } ret = ad7606_request_gpios(st); @@ -484,8 +487,7 @@ error_free_irq: free_irq(irq, indio_dev); error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return ret; } EXPORT_SYMBOL_GPL(ad7606_probe); @@ -499,8 +501,7 @@ int ad7606_remove(struct device *dev, int irq) iio_triggered_buffer_cleanup(indio_dev); free_irq(irq, indio_dev); - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return 0; } -- cgit v1.2.3 From 6a31c225f5d5182cd711019f99a4e87c92884e2b Mon Sep 17 00:00:00 2001 From: Tomas Novotny Date: Tue, 18 Oct 2016 19:43:06 +0200 Subject: iio: dac: mcp4725: fix incorrect comment Number 2 is referencing to the settings with the largest available resistor. No functional change. Signed-off-by: Tomas Novotny Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp4725.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 2b28b1f5b3a2..5b2dfa0a0d2c 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -374,7 +374,7 @@ static int mcp4725_probe(struct i2c_client *client, } pd = (inbuf[0] >> 1) & 0x3; data->powerdown = pd > 0 ? true : false; - data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */ + data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */ data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); err = iio_device_register(indio_dev); -- cgit v1.2.3 From 29157c6d601db8cb9f3bea93fc933b73db3bf869 Mon Sep 17 00:00:00 2001 From: Tomas Novotny Date: Tue, 18 Oct 2016 19:43:08 +0200 Subject: iio: dac: mcp4725: support voltage reference selection MCP47x6 chip supports selection of a voltage reference (VDD, VREF buffered or unbuffered). MCP4725 doesn't have this feature thus the eventual setting is ignored and user is warned. The setting is stored only in the volatile memory of the chip. You need to manually store it to the EEPROM of the chip via 'store_eeprom' sysfs entry. Signed-off-by: Tomas Novotny Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp4725.c | 99 ++++++++++++++++++++++++++++++++++++++--- include/linux/iio/dac/mcp4725.h | 11 +++++ 2 files changed, 103 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 5b2dfa0a0d2c..1e9d8f387e00 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -27,12 +27,20 @@ #define MCP4725_DRV_NAME "mcp4725" +#define MCP472X_REF_VDD 0x00 +#define MCP472X_REF_VREF_UNBUFFERED 0x02 +#define MCP472X_REF_VREF_BUFFERED 0x03 + struct mcp4725_data { struct i2c_client *client; + int id; + unsigned ref_mode; + bool vref_buffered; u16 dac_value; bool powerdown; unsigned powerdown_mode; struct regulator *vdd_reg; + struct regulator *vref_reg; }; static int mcp4725_suspend(struct device *dev) @@ -87,6 +95,7 @@ static ssize_t mcp4725_store_eeprom(struct device *dev, return 0; inoutbuf[0] = 0x60; /* write EEPROM */ + inoutbuf[0] |= data->ref_mode << 3; inoutbuf[1] = data->dac_value >> 4; inoutbuf[2] = (data->dac_value & 0xf) << 4; @@ -279,6 +288,28 @@ static int mcp4725_set_value(struct iio_dev *indio_dev, int val) return 0; } +static int mcp4726_set_cfg(struct iio_dev *indio_dev) +{ + struct mcp4725_data *data = iio_priv(indio_dev); + u8 outbuf[3]; + int ret; + + outbuf[0] = 0x40; + outbuf[0] |= data->ref_mode << 3; + if (data->powerdown) + outbuf[0] |= data->powerdown << 1; + outbuf[1] = data->dac_value >> 4; + outbuf[2] = (data->dac_value & 0xf) << 4; + + ret = i2c_master_send(data->client, outbuf, 3); + if (ret < 0) + return ret; + else if (ret != 3) + return -EIO; + else + return 0; +} + static int mcp4725_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -291,7 +322,11 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev, *val = data->dac_value; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - ret = regulator_get_voltage(data->vdd_reg); + if (data->ref_mode == MCP472X_REF_VDD) + ret = regulator_get_voltage(data->vdd_reg); + else + ret = regulator_get_voltage(data->vref_reg); + if (ret < 0) return ret; @@ -335,8 +370,9 @@ static int mcp4725_probe(struct i2c_client *client, struct mcp4725_data *data; struct iio_dev *indio_dev; struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev); - u8 inbuf[3]; + u8 inbuf[4]; u8 pd; + u8 ref; int err; if (!pdata) { @@ -350,6 +386,26 @@ static int mcp4725_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; + data->id = id->driver_data; + + if (data->id == MCP4725 && pdata->use_vref) { + dev_err(&client->dev, + "external reference is unavailable on MCP4725"); + return -EINVAL; + } + + if (!pdata->use_vref && pdata->vref_buffered) { + dev_err(&client->dev, + "buffering is unavailable on the internal reference"); + return -EINVAL; + } + + if (!pdata->use_vref) + data->ref_mode = MCP472X_REF_VDD; + else + data->ref_mode = pdata->vref_buffered ? + MCP472X_REF_VREF_BUFFERED : + MCP472X_REF_VREF_UNBUFFERED; data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); if (IS_ERR(data->vdd_reg)) @@ -359,6 +415,18 @@ static int mcp4725_probe(struct i2c_client *client, if (err) return err; + if (pdata->use_vref) { + data->vref_reg = devm_regulator_get(&client->dev, "vref"); + if (IS_ERR(data->vref_reg)) { + err = PTR_ERR(data->vdd_reg); + goto err_disable_vdd_reg; + } + + err = regulator_enable(data->vref_reg); + if (err) + goto err_disable_vdd_reg; + } + indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->info = &mcp4725_info; @@ -366,23 +434,38 @@ static int mcp4725_probe(struct i2c_client *client, indio_dev->num_channels = 1; indio_dev->modes = INDIO_DIRECT_MODE; - /* read current DAC value */ - err = i2c_master_recv(client, inbuf, 3); + /* read current DAC value and settings */ + err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4); + if (err < 0) { dev_err(&client->dev, "failed to read DAC value"); - goto err_disable_vdd_reg; + goto err_disable_vref_reg; } pd = (inbuf[0] >> 1) & 0x3; data->powerdown = pd > 0 ? true : false; data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */ data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); - + if (data->id == MCP4726) + ref = (inbuf[3] >> 3) & 0x3; + + if (data->id == MCP4726 && ref != data->ref_mode) { + dev_info(&client->dev, + "voltage reference mode differs (conf: %u, eeprom: %u), setting %u", + data->ref_mode, ref, data->ref_mode); + err = mcp4726_set_cfg(indio_dev); + if (err < 0) + goto err_disable_vref_reg; + } + err = iio_device_register(indio_dev); if (err) - goto err_disable_vdd_reg; + goto err_disable_vref_reg; return 0; +err_disable_vref_reg: + if (data->vref_reg) + regulator_disable(data->vref_reg); err_disable_vdd_reg: regulator_disable(data->vdd_reg); @@ -397,6 +480,8 @@ static int mcp4725_remove(struct i2c_client *client) iio_device_unregister(indio_dev); + if (data->vref_reg) + regulator_disable(data->vref_reg); regulator_disable(data->vdd_reg); return 0; diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h index 7c062e8d2a48..628b2cf54c50 100644 --- a/include/linux/iio/dac/mcp4725.h +++ b/include/linux/iio/dac/mcp4725.h @@ -9,7 +9,18 @@ #ifndef IIO_DAC_MCP4725_H_ #define IIO_DAC_MCP4725_H_ +/** + * struct mcp4725_platform_data - MCP4725/6 DAC specific data. + * @use_vref: Whether an external reference voltage on Vref pin should be used. + * Additional vref-supply must be specified when used. + * @vref_buffered: Controls buffering of the external reference voltage. + * + * Vref related settings are available only on MCP4756. See + * Documentation/devicetree/bindings/iio/dac/mcp4725.txt for more information. + */ struct mcp4725_platform_data { + bool use_vref; + bool vref_buffered; }; #endif /* IIO_DAC_MCP4725_H_ */ -- cgit v1.2.3 From 88e39a88b7ff4ec0deaf596bb653a6ca2c0c1f30 Mon Sep 17 00:00:00 2001 From: Tomas Novotny Date: Tue, 18 Oct 2016 19:43:09 +0200 Subject: iio: dac: mcp4725: add devicetree support Signed-off-by: Tomas Novotny Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp4725.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 1e9d8f387e00..fae80eb1a98a 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -364,22 +365,41 @@ static const struct iio_info mcp4725_info = { .driver_module = THIS_MODULE, }; +#ifdef CONFIG_OF +static int mcp4725_probe_dt(struct device *dev, + struct mcp4725_platform_data *pdata) +{ + struct device_node *np = dev->of_node; + + if (!np) + return -ENODEV; + + /* check if is the vref-supply defined */ + pdata->use_vref = of_property_read_bool(np, "vref-supply"); + pdata->vref_buffered = + of_property_read_bool(np, "microchip,vref-buffered"); + + return 0; +} +#else +static int mcp4725_probe_dt(struct device *dev, + struct mcp4725_platform_data *platform_data) +{ + return -ENODEV; +} +#endif + static int mcp4725_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct mcp4725_data *data; struct iio_dev *indio_dev; - struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev); + struct mcp4725_platform_data *pdata, pdata_dt; u8 inbuf[4]; u8 pd; u8 ref; int err; - if (!pdata) { - dev_err(&client->dev, "invalid platform data"); - return -EINVAL; - } - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (indio_dev == NULL) return -ENOMEM; @@ -387,6 +407,17 @@ static int mcp4725_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; data->id = id->driver_data; + pdata = dev_get_platdata(&client->dev); + + if (!pdata) { + err = mcp4725_probe_dt(&client->dev, &pdata_dt); + if (err) { + dev_err(&client->dev, + "invalid platform or devicetree data"); + return err; + } + pdata = &pdata_dt; + } if (data->id == MCP4725 && pdata->use_vref) { dev_err(&client->dev, -- cgit v1.2.3 From 16bf793f86b21959fd683ec28b8d196a0520de2f Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Fri, 2 Sep 2016 10:23:17 -0700 Subject: iio: humidity: hdc100x: add triggered buffer support for HDC100X Triggered buffer support uses the HDC100X's dual acquisition mode to read both humidity and temperature in one shot. This patch depends on 447136effbf4 ("iio: humidity: hdc100x: fix sensor data reads of temp and humidity") Signed-off-by: Alison Schofield Cc: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/Kconfig | 2 + drivers/iio/humidity/hdc100x.c | 130 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 6fd11d0813ad..912477d54be2 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -27,6 +27,8 @@ config DHT11 config HDC100X tristate "TI HDC100x relative humidity and temperature sensor" depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for the Texas Instruments HDC1000 and HDC1008 relative humidity and temperature sensors. diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index e0c9c70c2a4a..265c34da52d1 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -22,11 +22,15 @@ #include #include +#include +#include +#include #define HDC100X_REG_TEMP 0x00 #define HDC100X_REG_HUMIDITY 0x01 #define HDC100X_REG_CONFIG 0x02 +#define HDC100X_REG_CONFIG_ACQ_MODE BIT(12) #define HDC100X_REG_CONFIG_HEATER_EN BIT(13) struct hdc100x_data { @@ -87,22 +91,40 @@ static const struct iio_chan_spec hdc100x_channels[] = { BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_OFFSET), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_BE, + }, }, { .type = IIO_HUMIDITYRELATIVE, .address = HDC100X_REG_HUMIDITY, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_INT_TIME) + BIT(IIO_CHAN_INFO_INT_TIME), + .scan_index = 1, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_BE, + }, }, { .type = IIO_CURRENT, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .extend_name = "heater", .output = 1, + .scan_index = -1, }, + IIO_CHAN_SOFT_TIMESTAMP(2), }; +static const unsigned long hdc100x_scan_masks[] = {0x3, 0}; + static int hdc100x_update_config(struct hdc100x_data *data, int mask, int val) { int tmp = (~mask & data->config) | val; @@ -183,7 +205,14 @@ static int hdc100x_read_raw(struct iio_dev *indio_dev, *val = hdc100x_get_heater_status(data); ret = IIO_VAL_INT; } else { + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) { + mutex_unlock(&data->lock); + return ret; + } + ret = hdc100x_get_measurement(data, chan); + iio_device_release_direct_mode(indio_dev); if (ret >= 0) { *val = ret; ret = IIO_VAL_INT; @@ -246,6 +275,78 @@ static int hdc100x_write_raw(struct iio_dev *indio_dev, } } +static int hdc100x_buffer_postenable(struct iio_dev *indio_dev) +{ + struct hdc100x_data *data = iio_priv(indio_dev); + int ret; + + /* Buffer is enabled. First set ACQ Mode, then attach poll func */ + mutex_lock(&data->lock); + ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, + HDC100X_REG_CONFIG_ACQ_MODE); + mutex_unlock(&data->lock); + if (ret) + return ret; + + return iio_triggered_buffer_postenable(indio_dev); +} + +static int hdc100x_buffer_predisable(struct iio_dev *indio_dev) +{ + struct hdc100x_data *data = iio_priv(indio_dev); + int ret; + + /* First detach poll func, then reset ACQ mode. OK to disable buffer */ + ret = iio_triggered_buffer_predisable(indio_dev); + if (ret) + return ret; + + mutex_lock(&data->lock); + ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); + mutex_unlock(&data->lock); + + return ret; +} + +static const struct iio_buffer_setup_ops hdc_buffer_setup_ops = { + .postenable = hdc100x_buffer_postenable, + .predisable = hdc100x_buffer_predisable, +}; + +static irqreturn_t hdc100x_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct hdc100x_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + int delay = data->adc_int_us[0] + data->adc_int_us[1]; + int ret; + s16 buf[8]; /* 2x s16 + padding + 8 byte timestamp */ + + /* dual read starts at temp register */ + mutex_lock(&data->lock); + ret = i2c_smbus_write_byte(client, HDC100X_REG_TEMP); + if (ret < 0) { + dev_err(&client->dev, "cannot start measurement\n"); + goto err; + } + usleep_range(delay, delay + 1000); + + ret = i2c_master_recv(client, (u8 *)buf, 4); + if (ret < 0) { + dev_err(&client->dev, "cannot read sensor data\n"); + goto err; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buf, + iio_get_time_ns(indio_dev)); +err: + mutex_unlock(&data->lock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static const struct iio_info hdc100x_info = { .read_raw = hdc100x_read_raw, .write_raw = hdc100x_write_raw, @@ -258,6 +359,7 @@ static int hdc100x_probe(struct i2c_client *client, { struct iio_dev *indio_dev; struct hdc100x_data *data; + int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C)) @@ -279,12 +381,35 @@ static int hdc100x_probe(struct i2c_client *client, indio_dev->channels = hdc100x_channels; indio_dev->num_channels = ARRAY_SIZE(hdc100x_channels); + indio_dev->available_scan_masks = hdc100x_scan_masks; /* be sure we are in a known state */ hdc100x_set_it_time(data, 0, hdc100x_int_time[0][0]); hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]); + hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + hdc100x_trigger_handler, + &hdc_buffer_setup_ops); + if (ret < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + return ret; + } + ret = iio_device_register(indio_dev); + if (ret < 0) + iio_triggered_buffer_cleanup(indio_dev); + + return ret; +} + +static int hdc100x_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); - return devm_iio_device_register(&client->dev, indio_dev); + return 0; } static const struct i2c_device_id hdc100x_id[] = { @@ -298,6 +423,7 @@ static struct i2c_driver hdc100x_driver = { .name = "hdc100x", }, .probe = hdc100x_probe, + .remove = hdc100x_remove, .id_table = hdc100x_id, }; module_i2c_driver(hdc100x_driver); -- cgit v1.2.3 From 815bbc87462ae6e5b4d126f6e698fb990270c891 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 17 Oct 2016 00:59:42 +0900 Subject: iio: ti-adc0832: add triggered buffer support This adds triggered buffer support for the ti-adc0832 driver. Tested with ADC0831 and ADC0832 by using SYSFS trigger. Signed-off-by: Akinobu Mita Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 2 + drivers/iio/adc/ti-adc0832.c | 106 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 89 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 60426685d55d..c3fe98d2dc3b 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -459,6 +459,8 @@ config TI_ADC081C config TI_ADC0832 tristate "Texas Instruments ADC0831/ADC0832/ADC0834/ADC0838" depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help If you say yes here you get support for Texas Instruments ADC0831, ADC0832, ADC0834, ADC0838 ADC chips. diff --git a/drivers/iio/adc/ti-adc0832.c b/drivers/iio/adc/ti-adc0832.c index f4ba23effe9a..e952e94a14af 100644 --- a/drivers/iio/adc/ti-adc0832.c +++ b/drivers/iio/adc/ti-adc0832.c @@ -14,6 +14,10 @@ #include #include #include +#include +#include +#include +#include enum { adc0831, @@ -38,10 +42,16 @@ struct adc0832 { .indexed = 1, \ .channel = chan, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = chan, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 8, \ + .storagebits = 8, \ + }, \ } -#define ADC0832_VOLTAGE_CHANNEL_DIFF(chan1, chan2) \ +#define ADC0832_VOLTAGE_CHANNEL_DIFF(chan1, chan2, si) \ { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ @@ -49,18 +59,26 @@ struct adc0832 { .channel2 = (chan2), \ .differential = 1, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = si, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 8, \ + .storagebits = 8, \ + }, \ } static const struct iio_chan_spec adc0831_channels[] = { - ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1), + ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 0), + IIO_CHAN_SOFT_TIMESTAMP(1), }; static const struct iio_chan_spec adc0832_channels[] = { ADC0832_VOLTAGE_CHANNEL(0), ADC0832_VOLTAGE_CHANNEL(1), - ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1), - ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0), + ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 2), + ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 3), + IIO_CHAN_SOFT_TIMESTAMP(4), }; static const struct iio_chan_spec adc0834_channels[] = { @@ -68,10 +86,11 @@ static const struct iio_chan_spec adc0834_channels[] = { ADC0832_VOLTAGE_CHANNEL(1), ADC0832_VOLTAGE_CHANNEL(2), ADC0832_VOLTAGE_CHANNEL(3), - ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1), - ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0), - ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3), - ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2), + ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 4), + ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 5), + ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3, 6), + ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2, 7), + IIO_CHAN_SOFT_TIMESTAMP(8), }; static const struct iio_chan_spec adc0838_channels[] = { @@ -83,14 +102,15 @@ static const struct iio_chan_spec adc0838_channels[] = { ADC0832_VOLTAGE_CHANNEL(5), ADC0832_VOLTAGE_CHANNEL(6), ADC0832_VOLTAGE_CHANNEL(7), - ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1), - ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0), - ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3), - ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2), - ADC0832_VOLTAGE_CHANNEL_DIFF(4, 5), - ADC0832_VOLTAGE_CHANNEL_DIFF(5, 4), - ADC0832_VOLTAGE_CHANNEL_DIFF(6, 7), - ADC0832_VOLTAGE_CHANNEL_DIFF(7, 6), + ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 8), + ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 9), + ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3, 10), + ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2, 11), + ADC0832_VOLTAGE_CHANNEL_DIFF(4, 5, 12), + ADC0832_VOLTAGE_CHANNEL_DIFF(5, 4, 13), + ADC0832_VOLTAGE_CHANNEL_DIFF(6, 7, 14), + ADC0832_VOLTAGE_CHANNEL_DIFF(7, 6, 15), + IIO_CHAN_SOFT_TIMESTAMP(16), }; static int adc0831_adc_conversion(struct adc0832 *adc) @@ -178,6 +198,42 @@ static const struct iio_info adc0832_info = { .driver_module = THIS_MODULE, }; +static irqreturn_t adc0832_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc0832 *adc = iio_priv(indio_dev); + u8 data[24] = { }; /* 16x 1 byte ADC data + 8 bytes timestamp */ + int scan_index; + int i = 0; + + mutex_lock(&adc->lock); + + for_each_set_bit(scan_index, indio_dev->active_scan_mask, + indio_dev->masklength) { + const struct iio_chan_spec *scan_chan = + &indio_dev->channels[scan_index]; + int ret = adc0832_adc_conversion(adc, scan_chan->channel, + scan_chan->differential); + if (ret < 0) { + dev_warn(&adc->spi->dev, + "failed to get conversion data\n"); + goto out; + } + + data[i] = ret; + i++; + } + iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_get_time_ns(indio_dev)); +out: + mutex_unlock(&adc->lock); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static int adc0832_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -233,9 +289,20 @@ static int adc0832_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); + ret = iio_triggered_buffer_setup(indio_dev, NULL, + adc0832_trigger_handler, NULL); + if (ret) + goto err_reg_disable; + ret = iio_device_register(indio_dev); if (ret) - regulator_disable(adc->reg); + goto err_buffer_cleanup; + + return 0; +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +err_reg_disable: + regulator_disable(adc->reg); return ret; } @@ -246,6 +313,7 @@ static int adc0832_remove(struct spi_device *spi) struct adc0832 *adc = iio_priv(indio_dev); iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); regulator_disable(adc->reg); return 0; -- cgit v1.2.3 From a84a6a8aa0f6e02dec63a2ff69946f80785e35b9 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Sat, 15 Oct 2016 11:04:37 -0700 Subject: iio: proximity: pulsedlight-lidar-lite-v2: cleanup power management Remove pm_runtime_mark_last_busy() call that wasn't need in the probe since the device should be put to sleep. Clarification from Matt: Basically it going to be suspended once pm_runtime_idle() is called, and setting the last busy is useless and not needed. Clearly this doesn't affect the device running but just makes the code more consistent with other uses. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index 3141c3c161bb..1fa9eefa0982 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -301,8 +301,6 @@ static int lidar_probe(struct i2c_client *client, if (ret) goto error_unreg_buffer; pm_runtime_enable(&client->dev); - - pm_runtime_mark_last_busy(&client->dev); pm_runtime_idle(&client->dev); return 0; -- cgit v1.2.3 From dbdef9ba693a5ac7d92368cef7d436b3093e9f4e Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Sun, 23 Oct 2016 03:12:42 +0800 Subject: staging:iio:ad7606: fix ptr_ret.cocci warnings drivers/staging/iio/adc/ad7606.c:357:1-3: WARNING: PTR_ERR_OR_ZERO can be used Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR Generated by: scripts/coccinelle/api/ptr_ret.cocci CC: Lars-Peter Clausen Signed-off-by: Fengguang Wu Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index b0ae04a449ea..453190864b2f 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -354,10 +354,7 @@ static int ad7606_request_gpios(struct ad7606_state *st) st->gpio_os = devm_gpiod_get_array_optional(dev, "oversampling-ratio", GPIOD_OUT_LOW); - if (IS_ERR(st->gpio_os)) - return PTR_ERR(st->gpio_os); - - return 0; + return PTR_ERR_OR_ZERO(st->gpio_os); } /** -- cgit v1.2.3 From 30df2d1879ff65af7b269ee94e9c7fc276b54105 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 22 Oct 2016 22:41:32 +0200 Subject: iio: dac: mcp4725: fix odd_ptr_err.cocci warnings PTR_ERR should access the value just tested by IS_ERR Generated by: scripts/coccinelle/tests/odd_ptr_err.cocci CC: Tomas Novotny Signed-off-by: Julia Lawall Signed-off-by: Fengguang Wu Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp4725.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index fae80eb1a98a..db109f0cdd8c 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -449,7 +449,7 @@ static int mcp4725_probe(struct i2c_client *client, if (pdata->use_vref) { data->vref_reg = devm_regulator_get(&client->dev, "vref"); if (IS_ERR(data->vref_reg)) { - err = PTR_ERR(data->vdd_reg); + err = PTR_ERR(data->vref_reg); goto err_disable_vdd_reg; } -- cgit v1.2.3 From fe0612dc902a299c78f46c776038b91ecf64e8d8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 21 Oct 2016 16:07:18 +0200 Subject: mlxsw: item: Make struct mlxsw_item args const These should be const, so enforce it. Signed-off-by: Jiri Pirko Acked-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/item.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/item.h b/drivers/net/ethernet/mellanox/mlxsw/item.h index a94dbda6590b..1c55a34e0aa2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/item.h +++ b/drivers/net/ethernet/mellanox/mlxsw/item.h @@ -55,7 +55,7 @@ struct mlxsw_item { }; static inline unsigned int -__mlxsw_item_offset(struct mlxsw_item *item, unsigned short index, +__mlxsw_item_offset(const struct mlxsw_item *item, unsigned short index, size_t typesize) { BUG_ON(index && !item->step); @@ -72,7 +72,7 @@ __mlxsw_item_offset(struct mlxsw_item *item, unsigned short index, typesize); } -static inline u16 __mlxsw_item_get16(char *buf, struct mlxsw_item *item, +static inline u16 __mlxsw_item_get16(char *buf, const struct mlxsw_item *item, unsigned short index) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u16)); @@ -87,7 +87,7 @@ static inline u16 __mlxsw_item_get16(char *buf, struct mlxsw_item *item, return tmp; } -static inline void __mlxsw_item_set16(char *buf, struct mlxsw_item *item, +static inline void __mlxsw_item_set16(char *buf, const struct mlxsw_item *item, unsigned short index, u16 val) { unsigned int offset = __mlxsw_item_offset(item, index, @@ -105,7 +105,7 @@ static inline void __mlxsw_item_set16(char *buf, struct mlxsw_item *item, b[offset] = cpu_to_be16(tmp); } -static inline u32 __mlxsw_item_get32(char *buf, struct mlxsw_item *item, +static inline u32 __mlxsw_item_get32(char *buf, const struct mlxsw_item *item, unsigned short index) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u32)); @@ -120,7 +120,7 @@ static inline u32 __mlxsw_item_get32(char *buf, struct mlxsw_item *item, return tmp; } -static inline void __mlxsw_item_set32(char *buf, struct mlxsw_item *item, +static inline void __mlxsw_item_set32(char *buf, const struct mlxsw_item *item, unsigned short index, u32 val) { unsigned int offset = __mlxsw_item_offset(item, index, @@ -138,7 +138,7 @@ static inline void __mlxsw_item_set32(char *buf, struct mlxsw_item *item, b[offset] = cpu_to_be32(tmp); } -static inline u64 __mlxsw_item_get64(char *buf, struct mlxsw_item *item, +static inline u64 __mlxsw_item_get64(char *buf, const struct mlxsw_item *item, unsigned short index) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64)); @@ -153,7 +153,7 @@ static inline u64 __mlxsw_item_get64(char *buf, struct mlxsw_item *item, return tmp; } -static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item, +static inline void __mlxsw_item_set64(char *buf, const struct mlxsw_item *item, unsigned short index, u64 val) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64)); @@ -171,7 +171,7 @@ static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item, } static inline void __mlxsw_item_memcpy_from(char *buf, char *dst, - struct mlxsw_item *item, + const struct mlxsw_item *item, unsigned short index) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char)); @@ -180,7 +180,7 @@ static inline void __mlxsw_item_memcpy_from(char *buf, char *dst, } static inline void __mlxsw_item_memcpy_to(char *buf, const char *src, - struct mlxsw_item *item, + const struct mlxsw_item *item, unsigned short index) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char)); @@ -189,7 +189,8 @@ static inline void __mlxsw_item_memcpy_to(char *buf, const char *src, } static inline u16 -__mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift) +__mlxsw_item_bit_array_offset(const struct mlxsw_item *item, + u16 index, u8 *shift) { u16 max_index, be_index; u16 offset; /* byte offset inside the array */ @@ -212,7 +213,8 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift) return item->offset + offset; } -static inline u8 __mlxsw_item_bit_array_get(char *buf, struct mlxsw_item *item, +static inline u8 __mlxsw_item_bit_array_get(char *buf, + const struct mlxsw_item *item, u16 index) { u8 shift, tmp; @@ -224,7 +226,8 @@ static inline u8 __mlxsw_item_bit_array_get(char *buf, struct mlxsw_item *item, return tmp; } -static inline void __mlxsw_item_bit_array_set(char *buf, struct mlxsw_item *item, +static inline void __mlxsw_item_bit_array_set(char *buf, + const struct mlxsw_item *item, u16 index, u8 val) { u8 shift, tmp; -- cgit v1.2.3 From 412791df394bbf3547204b9875c7f5648e3dcf91 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 21 Oct 2016 16:07:19 +0200 Subject: mlxsw: item: Make char *buf arg constant for getters Enforce const for getter buf args. Signed-off-by: Jiri Pirko Acked-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/item.h | 31 ++++++++++++++------------ drivers/net/ethernet/mellanox/mlxsw/pci.c | 5 +++-- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 ++-- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 2 +- 4 files changed, 23 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/item.h b/drivers/net/ethernet/mellanox/mlxsw/item.h index 1c55a34e0aa2..3c95e3ddd9c2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/item.h +++ b/drivers/net/ethernet/mellanox/mlxsw/item.h @@ -72,7 +72,8 @@ __mlxsw_item_offset(const struct mlxsw_item *item, unsigned short index, typesize); } -static inline u16 __mlxsw_item_get16(char *buf, const struct mlxsw_item *item, +static inline u16 __mlxsw_item_get16(const char *buf, + const struct mlxsw_item *item, unsigned short index) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u16)); @@ -105,7 +106,8 @@ static inline void __mlxsw_item_set16(char *buf, const struct mlxsw_item *item, b[offset] = cpu_to_be16(tmp); } -static inline u32 __mlxsw_item_get32(char *buf, const struct mlxsw_item *item, +static inline u32 __mlxsw_item_get32(const char *buf, + const struct mlxsw_item *item, unsigned short index) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u32)); @@ -138,7 +140,8 @@ static inline void __mlxsw_item_set32(char *buf, const struct mlxsw_item *item, b[offset] = cpu_to_be32(tmp); } -static inline u64 __mlxsw_item_get64(char *buf, const struct mlxsw_item *item, +static inline u64 __mlxsw_item_get64(const char *buf, + const struct mlxsw_item *item, unsigned short index) { unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64)); @@ -170,7 +173,7 @@ static inline void __mlxsw_item_set64(char *buf, const struct mlxsw_item *item, b[offset] = cpu_to_be64(tmp); } -static inline void __mlxsw_item_memcpy_from(char *buf, char *dst, +static inline void __mlxsw_item_memcpy_from(const char *buf, char *dst, const struct mlxsw_item *item, unsigned short index) { @@ -213,7 +216,7 @@ __mlxsw_item_bit_array_offset(const struct mlxsw_item *item, return item->offset + offset; } -static inline u8 __mlxsw_item_bit_array_get(char *buf, +static inline u8 __mlxsw_item_bit_array_get(const char *buf, const struct mlxsw_item *item, u16 index) { @@ -257,7 +260,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .size = {.bits = _sizebits,}, \ .name = #_type "_" #_cname "_" #_iname, \ }; \ -static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf) \ +static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf) \ { \ return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \ } \ @@ -278,7 +281,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .name = #_type "_" #_cname "_" #_iname, \ }; \ static inline u16 \ -mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index) \ +mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\ { \ return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), \ index); \ @@ -298,7 +301,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .size = {.bits = _sizebits,}, \ .name = #_type "_" #_cname "_" #_iname, \ }; \ -static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf) \ +static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf) \ { \ return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \ } \ @@ -319,7 +322,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .name = #_type "_" #_cname "_" #_iname, \ }; \ static inline u32 \ -mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index) \ +mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\ { \ return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), \ index); \ @@ -339,7 +342,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .size = {.bits = _sizebits,}, \ .name = #_type "_" #_cname "_" #_iname, \ }; \ -static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf) \ +static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf) \ { \ return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \ } \ @@ -360,7 +363,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .name = #_type "_" #_cname "_" #_iname, \ }; \ static inline u64 \ -mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index) \ +mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\ { \ return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), \ index); \ @@ -380,7 +383,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .name = #_type "_" #_cname "_" #_iname, \ }; \ static inline void \ -mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, char *dst) \ +mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf, char *dst) \ { \ __mlxsw_item_memcpy_from(buf, dst, \ &__ITEM_NAME(_type, _cname, _iname), 0); \ @@ -402,7 +405,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .name = #_type "_" #_cname "_" #_iname, \ }; \ static inline void \ -mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, \ +mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf, \ unsigned short index, \ char *dst) \ { \ @@ -427,7 +430,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ .name = #_type "_" #_cname "_" #_iname, \ }; \ static inline u8 \ -mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, u16 index) \ +mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, u16 index) \ { \ return __mlxsw_item_bit_array_get(buf, \ &__ITEM_NAME(_type, _cname, _iname), \ diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index e742bd4e8894..6f368068aa15 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -238,8 +238,9 @@ static bool mlxsw_pci_elem_hw_owned(struct mlxsw_pci_queue *q, bool owner_bit) return owner_bit != !!(q->consumer_counter & q->count); } -static char *mlxsw_pci_queue_sw_elem_get(struct mlxsw_pci_queue *q, - u32 (*get_elem_owner_func)(char *)) +static char * +mlxsw_pci_queue_sw_elem_get(struct mlxsw_pci_queue *q, + u32 (*get_elem_owner_func)(const char *)) { struct mlxsw_pci_queue_elem_info *elem_info; char *elem; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 6d8cb22579ee..991a320470a9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1413,7 +1413,7 @@ err_port_pause_configure: struct mlxsw_sp_port_hw_stats { char str[ETH_GSTRING_LEN]; - u64 (*getter)(char *payload); + u64 (*getter)(const char *payload); }; static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = { @@ -1534,7 +1534,7 @@ static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_prio_stats[] = { #define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats) -static u64 mlxsw_reg_ppcnt_tc_transmit_queue_bytes_get(char *ppcnt_pl) +static u64 mlxsw_reg_ppcnt_tc_transmit_queue_bytes_get(const char *ppcnt_pl) { u64 transmit_queue = mlxsw_reg_ppcnt_tc_transmit_queue_get(ppcnt_pl); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 66af63d99b8b..963618da81a9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -410,7 +410,7 @@ static void mlxsw_sx_port_get_drvinfo(struct net_device *dev, struct mlxsw_sx_port_hw_stats { char str[ETH_GSTRING_LEN]; - u64 (*getter)(char *payload); + u64 (*getter)(const char *payload); }; static const struct mlxsw_sx_port_hw_stats mlxsw_sx_port_hw_stats[] = { -- cgit v1.2.3 From 21978dcfc8d847db3e280427547241a59d58ac01 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 21 Oct 2016 16:07:20 +0200 Subject: mlxsw: reg: Use helper macro to define registers Save some code and also prepare to easily carry name in string form. Signed-off-by: Jiri Pirko Acked-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 306 +++++++----------------------- 1 file changed, 66 insertions(+), 240 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 6460c7256f2b..770dbb8daa66 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -50,6 +50,12 @@ struct mlxsw_reg_info { u16 len; /* In u8 */ }; +#define MLXSW_REG_DEFINE(_name, _id, _len) \ +static const struct mlxsw_reg_info mlxsw_reg_##_name = { \ + .id = _id, \ + .len = _len, \ +} + #define MLXSW_REG(type) (&mlxsw_reg_##type) #define MLXSW_REG_LEN(type) MLXSW_REG(type)->len #define MLXSW_REG_ZERO(type, payload) memset(payload, 0, MLXSW_REG(type)->len) @@ -61,10 +67,7 @@ struct mlxsw_reg_info { #define MLXSW_REG_SGCR_ID 0x2000 #define MLXSW_REG_SGCR_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_sgcr = { - .id = MLXSW_REG_SGCR_ID, - .len = MLXSW_REG_SGCR_LEN, -}; +MLXSW_REG_DEFINE(sgcr, MLXSW_REG_SGCR_ID, MLXSW_REG_SGCR_LEN); /* reg_sgcr_llb * Link Local Broadcast (Default=0) @@ -87,10 +90,7 @@ static inline void mlxsw_reg_sgcr_pack(char *payload, bool llb) #define MLXSW_REG_SPAD_ID 0x2002 #define MLXSW_REG_SPAD_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_spad = { - .id = MLXSW_REG_SPAD_ID, - .len = MLXSW_REG_SPAD_LEN, -}; +MLXSW_REG_DEFINE(spad, MLXSW_REG_SPAD_ID, MLXSW_REG_SPAD_LEN); /* reg_spad_base_mac * Base MAC address for the switch partitions. @@ -109,10 +109,7 @@ MLXSW_ITEM_BUF(reg, spad, base_mac, 0x02, 6); #define MLXSW_REG_SMID_ID 0x2007 #define MLXSW_REG_SMID_LEN 0x240 -static const struct mlxsw_reg_info mlxsw_reg_smid = { - .id = MLXSW_REG_SMID_ID, - .len = MLXSW_REG_SMID_LEN, -}; +MLXSW_REG_DEFINE(smid, MLXSW_REG_SMID_ID, MLXSW_REG_SMID_LEN); /* reg_smid_swid * Switch partition ID. @@ -156,10 +153,7 @@ static inline void mlxsw_reg_smid_pack(char *payload, u16 mid, #define MLXSW_REG_SSPR_ID 0x2008 #define MLXSW_REG_SSPR_LEN 0x8 -static const struct mlxsw_reg_info mlxsw_reg_sspr = { - .id = MLXSW_REG_SSPR_ID, - .len = MLXSW_REG_SSPR_LEN, -}; +MLXSW_REG_DEFINE(sspr, MLXSW_REG_SSPR_ID, MLXSW_REG_SSPR_LEN); /* reg_sspr_m * Master - if set, then the record describes the master system port. @@ -215,10 +209,7 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u8 local_port) #define MLXSW_REG_SFDAT_ID 0x2009 #define MLXSW_REG_SFDAT_LEN 0x8 -static const struct mlxsw_reg_info mlxsw_reg_sfdat = { - .id = MLXSW_REG_SFDAT_ID, - .len = MLXSW_REG_SFDAT_LEN, -}; +MLXSW_REG_DEFINE(sfdat, MLXSW_REG_SFDAT_ID, MLXSW_REG_SFDAT_LEN); /* reg_sfdat_swid * Switch partition ID. @@ -256,10 +247,7 @@ static inline void mlxsw_reg_sfdat_pack(char *payload, u32 age_time) #define MLXSW_REG_SFD_LEN (MLXSW_REG_SFD_BASE_LEN + \ MLXSW_REG_SFD_REC_LEN * MLXSW_REG_SFD_REC_MAX_COUNT) -static const struct mlxsw_reg_info mlxsw_reg_sfd = { - .id = MLXSW_REG_SFD_ID, - .len = MLXSW_REG_SFD_LEN, -}; +MLXSW_REG_DEFINE(sfd, MLXSW_REG_SFD_ID, MLXSW_REG_SFD_LEN); /* reg_sfd_swid * Switch partition ID for queries. Reserved on Write. @@ -580,10 +568,7 @@ mlxsw_reg_sfd_mc_pack(char *payload, int rec_index, #define MLXSW_REG_SFN_LEN (MLXSW_REG_SFN_BASE_LEN + \ MLXSW_REG_SFN_REC_LEN * MLXSW_REG_SFN_REC_MAX_COUNT) -static const struct mlxsw_reg_info mlxsw_reg_sfn = { - .id = MLXSW_REG_SFN_ID, - .len = MLXSW_REG_SFN_LEN, -}; +MLXSW_REG_DEFINE(sfn, MLXSW_REG_SFN_ID, MLXSW_REG_SFN_LEN); /* reg_sfn_swid * Switch partition ID. @@ -701,10 +686,7 @@ static inline void mlxsw_reg_sfn_mac_lag_unpack(char *payload, int rec_index, #define MLXSW_REG_SPMS_ID 0x200D #define MLXSW_REG_SPMS_LEN 0x404 -static const struct mlxsw_reg_info mlxsw_reg_spms = { - .id = MLXSW_REG_SPMS_ID, - .len = MLXSW_REG_SPMS_LEN, -}; +MLXSW_REG_DEFINE(spms, MLXSW_REG_SPMS_ID, MLXSW_REG_SPMS_LEN); /* reg_spms_local_port * Local port number. @@ -748,10 +730,7 @@ static inline void mlxsw_reg_spms_vid_pack(char *payload, u16 vid, #define MLXSW_REG_SPVID_ID 0x200E #define MLXSW_REG_SPVID_LEN 0x08 -static const struct mlxsw_reg_info mlxsw_reg_spvid = { - .id = MLXSW_REG_SPVID_ID, - .len = MLXSW_REG_SPVID_LEN, -}; +MLXSW_REG_DEFINE(spvid, MLXSW_REG_SPVID_ID, MLXSW_REG_SPVID_LEN); /* reg_spvid_local_port * Local port number. @@ -792,10 +771,7 @@ static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid) #define MLXSW_REG_SPVM_LEN (MLXSW_REG_SPVM_BASE_LEN + \ MLXSW_REG_SPVM_REC_LEN * MLXSW_REG_SPVM_REC_MAX_COUNT) -static const struct mlxsw_reg_info mlxsw_reg_spvm = { - .id = MLXSW_REG_SPVM_ID, - .len = MLXSW_REG_SPVM_LEN, -}; +MLXSW_REG_DEFINE(spvm, MLXSW_REG_SPVM_ID, MLXSW_REG_SPVM_LEN); /* reg_spvm_pt * Priority tagged. If this bit is set, packets forwarded to the port with @@ -891,10 +867,7 @@ static inline void mlxsw_reg_spvm_pack(char *payload, u8 local_port, #define MLXSW_REG_SPAFT_ID 0x2010 #define MLXSW_REG_SPAFT_LEN 0x08 -static const struct mlxsw_reg_info mlxsw_reg_spaft = { - .id = MLXSW_REG_SPAFT_ID, - .len = MLXSW_REG_SPAFT_LEN, -}; +MLXSW_REG_DEFINE(spaft, MLXSW_REG_SPAFT_ID, MLXSW_REG_SPAFT_LEN); /* reg_spaft_local_port * Local port number. @@ -947,10 +920,7 @@ static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port, #define MLXSW_REG_SFGC_ID 0x2011 #define MLXSW_REG_SFGC_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_sfgc = { - .id = MLXSW_REG_SFGC_ID, - .len = MLXSW_REG_SFGC_LEN, -}; +MLXSW_REG_DEFINE(sfgc, MLXSW_REG_SFGC_ID, MLXSW_REG_SFGC_LEN); enum mlxsw_reg_sfgc_type { MLXSW_REG_SFGC_TYPE_BROADCAST, @@ -1045,10 +1015,7 @@ mlxsw_reg_sfgc_pack(char *payload, enum mlxsw_reg_sfgc_type type, #define MLXSW_REG_SFTR_ID 0x2012 #define MLXSW_REG_SFTR_LEN 0x420 -static const struct mlxsw_reg_info mlxsw_reg_sftr = { - .id = MLXSW_REG_SFTR_ID, - .len = MLXSW_REG_SFTR_LEN, -}; +MLXSW_REG_DEFINE(sftr, MLXSW_REG_SFTR_ID, MLXSW_REG_SFTR_LEN); /* reg_sftr_swid * Switch partition ID with which to associate the port. @@ -1118,10 +1085,7 @@ static inline void mlxsw_reg_sftr_pack(char *payload, #define MLXSW_REG_SFDF_ID 0x2013 #define MLXSW_REG_SFDF_LEN 0x14 -static const struct mlxsw_reg_info mlxsw_reg_sfdf = { - .id = MLXSW_REG_SFDF_ID, - .len = MLXSW_REG_SFDF_LEN, -}; +MLXSW_REG_DEFINE(sfdf, MLXSW_REG_SFDF_ID, MLXSW_REG_SFDF_LEN); /* reg_sfdf_swid * Switch partition ID. @@ -1205,10 +1169,7 @@ MLXSW_ITEM32(reg, sfdf, lag_fid_lag_id, 0x08, 0, 10); #define MLXSW_REG_SLDR_ID 0x2014 #define MLXSW_REG_SLDR_LEN 0x0C /* counting in only one port in list */ -static const struct mlxsw_reg_info mlxsw_reg_sldr = { - .id = MLXSW_REG_SLDR_ID, - .len = MLXSW_REG_SLDR_LEN, -}; +MLXSW_REG_DEFINE(sldr, MLXSW_REG_SLDR_ID, MLXSW_REG_SLDR_LEN); enum mlxsw_reg_sldr_op { /* Indicates a creation of a new LAG-ID, lag_id must be valid */ @@ -1288,10 +1249,7 @@ static inline void mlxsw_reg_sldr_lag_remove_port_pack(char *payload, u8 lag_id, #define MLXSW_REG_SLCR_ID 0x2015 #define MLXSW_REG_SLCR_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_slcr = { - .id = MLXSW_REG_SLCR_ID, - .len = MLXSW_REG_SLCR_LEN, -}; +MLXSW_REG_DEFINE(slcr, MLXSW_REG_SLCR_ID, MLXSW_REG_SLCR_LEN); enum mlxsw_reg_slcr_pp { /* Global Configuration (for all ports) */ @@ -1404,10 +1362,7 @@ static inline void mlxsw_reg_slcr_pack(char *payload, u16 lag_hash) #define MLXSW_REG_SLCOR_ID 0x2016 #define MLXSW_REG_SLCOR_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_slcor = { - .id = MLXSW_REG_SLCOR_ID, - .len = MLXSW_REG_SLCOR_LEN, -}; +MLXSW_REG_DEFINE(slcor, MLXSW_REG_SLCOR_ID, MLXSW_REG_SLCOR_LEN); enum mlxsw_reg_slcor_col { /* Port is added with collector disabled */ @@ -1490,10 +1445,7 @@ static inline void mlxsw_reg_slcor_col_disable_pack(char *payload, #define MLXSW_REG_SPMLR_ID 0x2018 #define MLXSW_REG_SPMLR_LEN 0x8 -static const struct mlxsw_reg_info mlxsw_reg_spmlr = { - .id = MLXSW_REG_SPMLR_ID, - .len = MLXSW_REG_SPMLR_LEN, -}; +MLXSW_REG_DEFINE(spmlr, MLXSW_REG_SPMLR_ID, MLXSW_REG_SPMLR_LEN); /* reg_spmlr_local_port * Local port number. @@ -1544,10 +1496,7 @@ static inline void mlxsw_reg_spmlr_pack(char *payload, u8 local_port, #define MLXSW_REG_SVFA_ID 0x201C #define MLXSW_REG_SVFA_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_svfa = { - .id = MLXSW_REG_SVFA_ID, - .len = MLXSW_REG_SVFA_LEN, -}; +MLXSW_REG_DEFINE(svfa, MLXSW_REG_SVFA_ID, MLXSW_REG_SVFA_LEN); /* reg_svfa_swid * Switch partition ID. @@ -1636,10 +1585,7 @@ static inline void mlxsw_reg_svfa_pack(char *payload, u8 local_port, #define MLXSW_REG_SVPE_ID 0x201E #define MLXSW_REG_SVPE_LEN 0x4 -static const struct mlxsw_reg_info mlxsw_reg_svpe = { - .id = MLXSW_REG_SVPE_ID, - .len = MLXSW_REG_SVPE_LEN, -}; +MLXSW_REG_DEFINE(svpe, MLXSW_REG_SVPE_ID, MLXSW_REG_SVPE_LEN); /* reg_svpe_local_port * Local port number @@ -1672,10 +1618,7 @@ static inline void mlxsw_reg_svpe_pack(char *payload, u8 local_port, #define MLXSW_REG_SFMR_ID 0x201F #define MLXSW_REG_SFMR_LEN 0x18 -static const struct mlxsw_reg_info mlxsw_reg_sfmr = { - .id = MLXSW_REG_SFMR_ID, - .len = MLXSW_REG_SFMR_LEN, -}; +MLXSW_REG_DEFINE(sfmr, MLXSW_REG_SFMR_ID, MLXSW_REG_SFMR_LEN); enum mlxsw_reg_sfmr_op { MLXSW_REG_SFMR_OP_CREATE_FID, @@ -1762,10 +1705,7 @@ static inline void mlxsw_reg_sfmr_pack(char *payload, MLXSW_REG_SPVMLR_REC_LEN * \ MLXSW_REG_SPVMLR_REC_MAX_COUNT) -static const struct mlxsw_reg_info mlxsw_reg_spvmlr = { - .id = MLXSW_REG_SPVMLR_ID, - .len = MLXSW_REG_SPVMLR_LEN, -}; +MLXSW_REG_DEFINE(spvmlr, MLXSW_REG_SPVMLR_ID, MLXSW_REG_SPVMLR_LEN); /* reg_spvmlr_local_port * Local ingress port. @@ -1823,10 +1763,7 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port, #define MLXSW_REG_QTCT_ID 0x400A #define MLXSW_REG_QTCT_LEN 0x08 -static const struct mlxsw_reg_info mlxsw_reg_qtct = { - .id = MLXSW_REG_QTCT_ID, - .len = MLXSW_REG_QTCT_LEN, -}; +MLXSW_REG_DEFINE(qtct, MLXSW_REG_QTCT_ID, MLXSW_REG_QTCT_LEN); /* reg_qtct_local_port * Local port number. @@ -1875,10 +1812,7 @@ static inline void mlxsw_reg_qtct_pack(char *payload, u8 local_port, #define MLXSW_REG_QEEC_ID 0x400D #define MLXSW_REG_QEEC_LEN 0x1C -static const struct mlxsw_reg_info mlxsw_reg_qeec = { - .id = MLXSW_REG_QEEC_ID, - .len = MLXSW_REG_QEEC_LEN, -}; +MLXSW_REG_DEFINE(qeec, MLXSW_REG_QEEC_ID, MLXSW_REG_QEEC_LEN); /* reg_qeec_local_port * Local port number. @@ -2000,10 +1934,7 @@ static inline void mlxsw_reg_qeec_pack(char *payload, u8 local_port, #define MLXSW_REG_PMLP_ID 0x5002 #define MLXSW_REG_PMLP_LEN 0x40 -static const struct mlxsw_reg_info mlxsw_reg_pmlp = { - .id = MLXSW_REG_PMLP_ID, - .len = MLXSW_REG_PMLP_LEN, -}; +MLXSW_REG_DEFINE(pmlp, MLXSW_REG_PMLP_ID, MLXSW_REG_PMLP_LEN); /* reg_pmlp_rxtx * 0 - Tx value is used for both Tx and Rx. @@ -2059,10 +1990,7 @@ static inline void mlxsw_reg_pmlp_pack(char *payload, u8 local_port) #define MLXSW_REG_PMTU_ID 0x5003 #define MLXSW_REG_PMTU_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_pmtu = { - .id = MLXSW_REG_PMTU_ID, - .len = MLXSW_REG_PMTU_LEN, -}; +MLXSW_REG_DEFINE(pmtu, MLXSW_REG_PMTU_ID, MLXSW_REG_PMTU_LEN); /* reg_pmtu_local_port * Local port number. @@ -2116,10 +2044,7 @@ static inline void mlxsw_reg_pmtu_pack(char *payload, u8 local_port, #define MLXSW_REG_PTYS_ID 0x5004 #define MLXSW_REG_PTYS_LEN 0x40 -static const struct mlxsw_reg_info mlxsw_reg_ptys = { - .id = MLXSW_REG_PTYS_ID, - .len = MLXSW_REG_PTYS_LEN, -}; +MLXSW_REG_DEFINE(ptys, MLXSW_REG_PTYS_ID, MLXSW_REG_PTYS_LEN); /* reg_ptys_local_port * Local port number. @@ -2232,10 +2157,7 @@ static inline void mlxsw_reg_ptys_unpack(char *payload, u32 *p_eth_proto_cap, #define MLXSW_REG_PPAD_ID 0x5005 #define MLXSW_REG_PPAD_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_ppad = { - .id = MLXSW_REG_PPAD_ID, - .len = MLXSW_REG_PPAD_LEN, -}; +MLXSW_REG_DEFINE(ppad, MLXSW_REG_PPAD_ID, MLXSW_REG_PPAD_LEN); /* reg_ppad_single_base_mac * 0: base_mac, local port should be 0 and mac[7:0] is @@ -2273,10 +2195,7 @@ static inline void mlxsw_reg_ppad_pack(char *payload, bool single_base_mac, #define MLXSW_REG_PAOS_ID 0x5006 #define MLXSW_REG_PAOS_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_paos = { - .id = MLXSW_REG_PAOS_ID, - .len = MLXSW_REG_PAOS_LEN, -}; +MLXSW_REG_DEFINE(paos, MLXSW_REG_PAOS_ID, MLXSW_REG_PAOS_LEN); /* reg_paos_swid * Switch partition ID with which to associate the port. @@ -2356,10 +2275,7 @@ static inline void mlxsw_reg_paos_pack(char *payload, u8 local_port, #define MLXSW_REG_PFCC_ID 0x5007 #define MLXSW_REG_PFCC_LEN 0x20 -static const struct mlxsw_reg_info mlxsw_reg_pfcc = { - .id = MLXSW_REG_PFCC_ID, - .len = MLXSW_REG_PFCC_LEN, -}; +MLXSW_REG_DEFINE(pfcc, MLXSW_REG_PFCC_ID, MLXSW_REG_PFCC_LEN); /* reg_pfcc_local_port * Local port number. @@ -2495,10 +2411,7 @@ static inline void mlxsw_reg_pfcc_pack(char *payload, u8 local_port) #define MLXSW_REG_PPCNT_ID 0x5008 #define MLXSW_REG_PPCNT_LEN 0x100 -static const struct mlxsw_reg_info mlxsw_reg_ppcnt = { - .id = MLXSW_REG_PPCNT_ID, - .len = MLXSW_REG_PPCNT_LEN, -}; +MLXSW_REG_DEFINE(ppcnt, MLXSW_REG_PPCNT_ID, MLXSW_REG_PPCNT_LEN); /* reg_ppcnt_swid * For HCA: must be always 0. @@ -2768,10 +2681,7 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port, #define MLXSW_REG_PPTB_ID 0x500B #define MLXSW_REG_PPTB_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_pptb = { - .id = MLXSW_REG_PPTB_ID, - .len = MLXSW_REG_PPTB_LEN, -}; +MLXSW_REG_DEFINE(pptb, MLXSW_REG_PPTB_ID, MLXSW_REG_PPTB_LEN); enum { MLXSW_REG_PPTB_MM_UM, @@ -2865,10 +2775,7 @@ static inline void mlxsw_reg_pptb_prio_to_buff_pack(char *payload, u8 prio, #define MLXSW_REG_PBMC_ID 0x500C #define MLXSW_REG_PBMC_LEN 0x6C -static const struct mlxsw_reg_info mlxsw_reg_pbmc = { - .id = MLXSW_REG_PBMC_ID, - .len = MLXSW_REG_PBMC_LEN, -}; +MLXSW_REG_DEFINE(pbmc, MLXSW_REG_PBMC_ID, MLXSW_REG_PBMC_LEN); /* reg_pbmc_local_port * Local port number. @@ -2978,10 +2885,7 @@ static inline void mlxsw_reg_pbmc_lossless_buffer_pack(char *payload, #define MLXSW_REG_PSPA_ID 0x500D #define MLXSW_REG_PSPA_LEN 0x8 -static const struct mlxsw_reg_info mlxsw_reg_pspa = { - .id = MLXSW_REG_PSPA_ID, - .len = MLXSW_REG_PSPA_LEN, -}; +MLXSW_REG_DEFINE(pspa, MLXSW_REG_PSPA_ID, MLXSW_REG_PSPA_LEN); /* reg_pspa_swid * Switch partition ID. @@ -3017,10 +2921,7 @@ static inline void mlxsw_reg_pspa_pack(char *payload, u8 swid, u8 local_port) #define MLXSW_REG_HTGT_ID 0x7002 #define MLXSW_REG_HTGT_LEN 0x100 -static const struct mlxsw_reg_info mlxsw_reg_htgt = { - .id = MLXSW_REG_HTGT_ID, - .len = MLXSW_REG_HTGT_LEN, -}; +MLXSW_REG_DEFINE(htgt, MLXSW_REG_HTGT_ID, MLXSW_REG_HTGT_LEN); /* reg_htgt_swid * Switch partition ID. @@ -3154,10 +3055,7 @@ static inline void mlxsw_reg_htgt_pack(char *payload, #define MLXSW_REG_HPKT_ID 0x7003 #define MLXSW_REG_HPKT_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_hpkt = { - .id = MLXSW_REG_HPKT_ID, - .len = MLXSW_REG_HPKT_LEN, -}; +MLXSW_REG_DEFINE(hpkt, MLXSW_REG_HPKT_ID, MLXSW_REG_HPKT_LEN); enum { MLXSW_REG_HPKT_ACK_NOT_REQUIRED, @@ -3256,10 +3154,7 @@ static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id) #define MLXSW_REG_RGCR_ID 0x8001 #define MLXSW_REG_RGCR_LEN 0x28 -static const struct mlxsw_reg_info mlxsw_reg_rgcr = { - .id = MLXSW_REG_RGCR_ID, - .len = MLXSW_REG_RGCR_LEN, -}; +MLXSW_REG_DEFINE(rgcr, MLXSW_REG_RGCR_ID, MLXSW_REG_RGCR_LEN); /* reg_rgcr_ipv4_en * IPv4 router enable. @@ -3330,10 +3225,7 @@ static inline void mlxsw_reg_rgcr_pack(char *payload, bool ipv4_en) #define MLXSW_REG_RITR_ID 0x8002 #define MLXSW_REG_RITR_LEN 0x40 -static const struct mlxsw_reg_info mlxsw_reg_ritr = { - .id = MLXSW_REG_RITR_ID, - .len = MLXSW_REG_RITR_LEN, -}; +MLXSW_REG_DEFINE(ritr, MLXSW_REG_RITR_ID, MLXSW_REG_RITR_LEN); /* reg_ritr_enable * Enables routing on the router interface. @@ -3533,10 +3425,7 @@ static inline void mlxsw_reg_ritr_pack(char *payload, bool enable, #define MLXSW_REG_RATR_ID 0x8008 #define MLXSW_REG_RATR_LEN 0x2C -static const struct mlxsw_reg_info mlxsw_reg_ratr = { - .id = MLXSW_REG_RATR_ID, - .len = MLXSW_REG_RATR_LEN, -}; +MLXSW_REG_DEFINE(ratr, MLXSW_REG_RATR_ID, MLXSW_REG_RATR_LEN); enum mlxsw_reg_ratr_op { /* Read */ @@ -3663,10 +3552,7 @@ static inline void mlxsw_reg_ratr_eth_entry_pack(char *payload, #define MLXSW_REG_RALTA_ID 0x8010 #define MLXSW_REG_RALTA_LEN 0x04 -static const struct mlxsw_reg_info mlxsw_reg_ralta = { - .id = MLXSW_REG_RALTA_ID, - .len = MLXSW_REG_RALTA_LEN, -}; +MLXSW_REG_DEFINE(ralta, MLXSW_REG_RALTA_ID, MLXSW_REG_RALTA_LEN); /* reg_ralta_op * opcode (valid for Write, must be 0 on Read) @@ -3718,10 +3604,7 @@ static inline void mlxsw_reg_ralta_pack(char *payload, bool alloc, #define MLXSW_REG_RALST_ID 0x8011 #define MLXSW_REG_RALST_LEN 0x104 -static const struct mlxsw_reg_info mlxsw_reg_ralst = { - .id = MLXSW_REG_RALST_ID, - .len = MLXSW_REG_RALST_LEN, -}; +MLXSW_REG_DEFINE(ralst, MLXSW_REG_RALST_ID, MLXSW_REG_RALST_LEN); /* reg_ralst_root_bin * The bin number of the root bin. @@ -3788,10 +3671,7 @@ static inline void mlxsw_reg_ralst_bin_pack(char *payload, u8 bin_number, #define MLXSW_REG_RALTB_ID 0x8012 #define MLXSW_REG_RALTB_LEN 0x04 -static const struct mlxsw_reg_info mlxsw_reg_raltb = { - .id = MLXSW_REG_RALTB_ID, - .len = MLXSW_REG_RALTB_LEN, -}; +MLXSW_REG_DEFINE(raltb, MLXSW_REG_RALTB_ID, MLXSW_REG_RALTB_LEN); /* reg_raltb_virtual_router * Virtual Router ID @@ -3832,10 +3712,7 @@ static inline void mlxsw_reg_raltb_pack(char *payload, u16 virtual_router, #define MLXSW_REG_RALUE_ID 0x8013 #define MLXSW_REG_RALUE_LEN 0x38 -static const struct mlxsw_reg_info mlxsw_reg_ralue = { - .id = MLXSW_REG_RALUE_ID, - .len = MLXSW_REG_RALUE_LEN, -}; +MLXSW_REG_DEFINE(ralue, MLXSW_REG_RALUE_ID, MLXSW_REG_RALUE_LEN); /* reg_ralue_protocol * Protocol. @@ -4095,10 +3972,7 @@ mlxsw_reg_ralue_act_ip2me_pack(char *payload) #define MLXSW_REG_RAUHT_ID 0x8014 #define MLXSW_REG_RAUHT_LEN 0x74 -static const struct mlxsw_reg_info mlxsw_reg_rauht = { - .id = MLXSW_REG_RAUHT_ID, - .len = MLXSW_REG_RAUHT_LEN, -}; +MLXSW_REG_DEFINE(rauht, MLXSW_REG_RAUHT_ID, MLXSW_REG_RAUHT_LEN); enum mlxsw_reg_rauht_type { MLXSW_REG_RAUHT_TYPE_IPV4, @@ -4234,10 +4108,7 @@ static inline void mlxsw_reg_rauht_pack4(char *payload, #define MLXSW_REG_RALEU_ID 0x8015 #define MLXSW_REG_RALEU_LEN 0x28 -static const struct mlxsw_reg_info mlxsw_reg_raleu = { - .id = MLXSW_REG_RALEU_ID, - .len = MLXSW_REG_RALEU_LEN, -}; +MLXSW_REG_DEFINE(raleu, MLXSW_REG_RALEU_ID, MLXSW_REG_RALEU_LEN); /* reg_raleu_protocol * Protocol. @@ -4309,10 +4180,7 @@ static inline void mlxsw_reg_raleu_pack(char *payload, MLXSW_REG_RAUHTD_REC_MAX_NUM * MLXSW_REG_RAUHTD_REC_LEN) #define MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC 4 -static const struct mlxsw_reg_info mlxsw_reg_rauhtd = { - .id = MLXSW_REG_RAUHTD_ID, - .len = MLXSW_REG_RAUHTD_LEN, -}; +MLXSW_REG_DEFINE(rauhtd, MLXSW_REG_RAUHTD_ID, MLXSW_REG_RAUHTD_LEN); #define MLXSW_REG_RAUHTD_FILTER_A BIT(0) #define MLXSW_REG_RAUHTD_FILTER_RIF BIT(3) @@ -4444,10 +4312,7 @@ static inline void mlxsw_reg_rauhtd_ent_ipv4_unpack(char *payload, #define MLXSW_REG_MFCR_ID 0x9001 #define MLXSW_REG_MFCR_LEN 0x08 -static const struct mlxsw_reg_info mlxsw_reg_mfcr = { - .id = MLXSW_REG_MFCR_ID, - .len = MLXSW_REG_MFCR_LEN, -}; +MLXSW_REG_DEFINE(mfcr, MLXSW_REG_MFCR_ID, MLXSW_REG_MFCR_LEN); enum mlxsw_reg_mfcr_pwm_frequency { MLXSW_REG_MFCR_PWM_FEQ_11HZ = 0x00, @@ -4507,10 +4372,7 @@ mlxsw_reg_mfcr_unpack(char *payload, #define MLXSW_REG_MFSC_ID 0x9002 #define MLXSW_REG_MFSC_LEN 0x08 -static const struct mlxsw_reg_info mlxsw_reg_mfsc = { - .id = MLXSW_REG_MFSC_ID, - .len = MLXSW_REG_MFSC_LEN, -}; +MLXSW_REG_DEFINE(mfsc, MLXSW_REG_MFSC_ID, MLXSW_REG_MFSC_LEN); /* reg_mfsc_pwm * Fan pwm to control / monitor. @@ -4541,10 +4403,7 @@ static inline void mlxsw_reg_mfsc_pack(char *payload, u8 pwm, #define MLXSW_REG_MFSM_ID 0x9003 #define MLXSW_REG_MFSM_LEN 0x08 -static const struct mlxsw_reg_info mlxsw_reg_mfsm = { - .id = MLXSW_REG_MFSM_ID, - .len = MLXSW_REG_MFSM_LEN, -}; +MLXSW_REG_DEFINE(mfsm, MLXSW_REG_MFSM_ID, MLXSW_REG_MFSM_LEN); /* reg_mfsm_tacho * Fan tachometer index. @@ -4572,10 +4431,7 @@ static inline void mlxsw_reg_mfsm_pack(char *payload, u8 tacho) #define MLXSW_REG_MTCAP_ID 0x9009 #define MLXSW_REG_MTCAP_LEN 0x08 -static const struct mlxsw_reg_info mlxsw_reg_mtcap = { - .id = MLXSW_REG_MTCAP_ID, - .len = MLXSW_REG_MTCAP_LEN, -}; +MLXSW_REG_DEFINE(mtcap, MLXSW_REG_MTCAP_ID, MLXSW_REG_MTCAP_LEN); /* reg_mtcap_sensor_count * Number of sensors supported by the device. @@ -4593,10 +4449,7 @@ MLXSW_ITEM32(reg, mtcap, sensor_count, 0x00, 0, 7); #define MLXSW_REG_MTMP_ID 0x900A #define MLXSW_REG_MTMP_LEN 0x20 -static const struct mlxsw_reg_info mlxsw_reg_mtmp = { - .id = MLXSW_REG_MTMP_ID, - .len = MLXSW_REG_MTMP_LEN, -}; +MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN); /* reg_mtmp_sensor_index * Sensors index to access. @@ -4679,10 +4532,7 @@ static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp, #define MLXSW_REG_MPAT_ID 0x901A #define MLXSW_REG_MPAT_LEN 0x78 -static const struct mlxsw_reg_info mlxsw_reg_mpat = { - .id = MLXSW_REG_MPAT_ID, - .len = MLXSW_REG_MPAT_LEN, -}; +MLXSW_REG_DEFINE(mpat, MLXSW_REG_MPAT_ID, MLXSW_REG_MPAT_LEN); /* reg_mpat_pa_id * Port Analyzer ID. @@ -4742,10 +4592,7 @@ static inline void mlxsw_reg_mpat_pack(char *payload, u8 pa_id, #define MLXSW_REG_MPAR_ID 0x901B #define MLXSW_REG_MPAR_LEN 0x08 -static const struct mlxsw_reg_info mlxsw_reg_mpar = { - .id = MLXSW_REG_MPAR_ID, - .len = MLXSW_REG_MPAR_LEN, -}; +MLXSW_REG_DEFINE(mpar, MLXSW_REG_MPAR_ID, MLXSW_REG_MPAR_LEN); /* reg_mpar_local_port * The local port to mirror the packets from. @@ -4795,10 +4642,7 @@ static inline void mlxsw_reg_mpar_pack(char *payload, u8 local_port, #define MLXSW_REG_MLCR_ID 0x902B #define MLXSW_REG_MLCR_LEN 0x0C -static const struct mlxsw_reg_info mlxsw_reg_mlcr = { - .id = MLXSW_REG_MLCR_ID, - .len = MLXSW_REG_MLCR_LEN, -}; +MLXSW_REG_DEFINE(mlcr, MLXSW_REG_MLCR_ID, MLXSW_REG_MLCR_LEN); /* reg_mlcr_local_port * Local port number. @@ -4839,10 +4683,7 @@ static inline void mlxsw_reg_mlcr_pack(char *payload, u8 local_port, #define MLXSW_REG_SBPR_ID 0xB001 #define MLXSW_REG_SBPR_LEN 0x14 -static const struct mlxsw_reg_info mlxsw_reg_sbpr = { - .id = MLXSW_REG_SBPR_ID, - .len = MLXSW_REG_SBPR_LEN, -}; +MLXSW_REG_DEFINE(sbpr, MLXSW_REG_SBPR_ID, MLXSW_REG_SBPR_LEN); /* shared direstion enum for SBPR, SBCM, SBPM */ enum mlxsw_reg_sbxx_dir { @@ -4899,10 +4740,7 @@ static inline void mlxsw_reg_sbpr_pack(char *payload, u8 pool, #define MLXSW_REG_SBCM_ID 0xB002 #define MLXSW_REG_SBCM_LEN 0x28 -static const struct mlxsw_reg_info mlxsw_reg_sbcm = { - .id = MLXSW_REG_SBCM_ID, - .len = MLXSW_REG_SBCM_LEN, -}; +MLXSW_REG_DEFINE(sbcm, MLXSW_REG_SBCM_ID, MLXSW_REG_SBCM_LEN); /* reg_sbcm_local_port * Local port number. @@ -4979,10 +4817,7 @@ static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff, #define MLXSW_REG_SBPM_ID 0xB003 #define MLXSW_REG_SBPM_LEN 0x28 -static const struct mlxsw_reg_info mlxsw_reg_sbpm = { - .id = MLXSW_REG_SBPM_ID, - .len = MLXSW_REG_SBPM_LEN, -}; +MLXSW_REG_DEFINE(sbpm, MLXSW_REG_SBPM_ID, MLXSW_REG_SBPM_LEN); /* reg_sbpm_local_port * Local port number. @@ -5073,10 +4908,7 @@ static inline void mlxsw_reg_sbpm_unpack(char *payload, u32 *p_buff_occupancy, #define MLXSW_REG_SBMM_ID 0xB004 #define MLXSW_REG_SBMM_LEN 0x28 -static const struct mlxsw_reg_info mlxsw_reg_sbmm = { - .id = MLXSW_REG_SBMM_ID, - .len = MLXSW_REG_SBMM_LEN, -}; +MLXSW_REG_DEFINE(sbmm, MLXSW_REG_SBMM_ID, MLXSW_REG_SBMM_LEN); /* reg_sbmm_prio * Switch Priority. @@ -5135,10 +4967,7 @@ static inline void mlxsw_reg_sbmm_pack(char *payload, u8 prio, u32 min_buff, MLXSW_REG_SBSR_REC_LEN * \ MLXSW_REG_SBSR_REC_MAX_COUNT) -static const struct mlxsw_reg_info mlxsw_reg_sbsr = { - .id = MLXSW_REG_SBSR_ID, - .len = MLXSW_REG_SBSR_LEN, -}; +MLXSW_REG_DEFINE(sbsr, MLXSW_REG_SBSR_ID, MLXSW_REG_SBSR_LEN); /* reg_sbsr_clr * Clear Max Buffer Occupancy. When this bit is set, the max_buff_occupancy @@ -5228,10 +5057,7 @@ static inline void mlxsw_reg_sbsr_rec_unpack(char *payload, int rec_index, #define MLXSW_REG_SBIB_ID 0xB006 #define MLXSW_REG_SBIB_LEN 0x10 -static const struct mlxsw_reg_info mlxsw_reg_sbib = { - .id = MLXSW_REG_SBIB_ID, - .len = MLXSW_REG_SBIB_LEN, -}; +MLXSW_REG_DEFINE(sbib, MLXSW_REG_SBIB_ID, MLXSW_REG_SBIB_LEN); /* reg_sbib_local_port * Local port number -- cgit v1.2.3 From 8e9658d56718a62d0586f4dbb61b68b07d3c6cc0 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 21 Oct 2016 16:07:21 +0200 Subject: mlxsw: reg: Generare register names automatically Extend the MLXSW_REG_DEFINE macro to store register name in string form. Use this string later on instead of hard coded string values. Signed-off-by: Jiri Pirko Acked-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 196 +++++++++++------------------- 1 file changed, 73 insertions(+), 123 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 770dbb8daa66..debcf2648398 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -48,12 +48,14 @@ struct mlxsw_reg_info { u16 id; u16 len; /* In u8 */ + const char *name; }; #define MLXSW_REG_DEFINE(_name, _id, _len) \ static const struct mlxsw_reg_info mlxsw_reg_##_name = { \ .id = _id, \ .len = _len, \ + .name = #_name, \ } #define MLXSW_REG(type) (&mlxsw_reg_##type) @@ -5082,132 +5084,80 @@ static inline void mlxsw_reg_sbib_pack(char *payload, u8 local_port, mlxsw_reg_sbib_buff_size_set(payload, buff_size); } +static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { + MLXSW_REG(sgcr), + MLXSW_REG(spad), + MLXSW_REG(smid), + MLXSW_REG(sspr), + MLXSW_REG(sfdat), + MLXSW_REG(sfd), + MLXSW_REG(sfn), + MLXSW_REG(spms), + MLXSW_REG(spvid), + MLXSW_REG(spvm), + MLXSW_REG(spaft), + MLXSW_REG(sfgc), + MLXSW_REG(sftr), + MLXSW_REG(sfdf), + MLXSW_REG(sldr), + MLXSW_REG(slcr), + MLXSW_REG(slcor), + MLXSW_REG(spmlr), + MLXSW_REG(svfa), + MLXSW_REG(svpe), + MLXSW_REG(sfmr), + MLXSW_REG(spvmlr), + MLXSW_REG(qtct), + MLXSW_REG(qeec), + MLXSW_REG(pmlp), + MLXSW_REG(pmtu), + MLXSW_REG(ptys), + MLXSW_REG(ppad), + MLXSW_REG(paos), + MLXSW_REG(pfcc), + MLXSW_REG(ppcnt), + MLXSW_REG(pptb), + MLXSW_REG(pbmc), + MLXSW_REG(pspa), + MLXSW_REG(htgt), + MLXSW_REG(hpkt), + MLXSW_REG(rgcr), + MLXSW_REG(ritr), + MLXSW_REG(ratr), + MLXSW_REG(ralta), + MLXSW_REG(ralst), + MLXSW_REG(raltb), + MLXSW_REG(ralue), + MLXSW_REG(rauht), + MLXSW_REG(raleu), + MLXSW_REG(rauhtd), + MLXSW_REG(mfcr), + MLXSW_REG(mfsc), + MLXSW_REG(mfsm), + MLXSW_REG(mtcap), + MLXSW_REG(mtmp), + MLXSW_REG(mpat), + MLXSW_REG(mpar), + MLXSW_REG(mlcr), + MLXSW_REG(sbpr), + MLXSW_REG(sbcm), + MLXSW_REG(sbpm), + MLXSW_REG(sbmm), + MLXSW_REG(sbsr), + MLXSW_REG(sbib), +}; + static inline const char *mlxsw_reg_id_str(u16 reg_id) { - switch (reg_id) { - case MLXSW_REG_SGCR_ID: - return "SGCR"; - case MLXSW_REG_SPAD_ID: - return "SPAD"; - case MLXSW_REG_SMID_ID: - return "SMID"; - case MLXSW_REG_SSPR_ID: - return "SSPR"; - case MLXSW_REG_SFDAT_ID: - return "SFDAT"; - case MLXSW_REG_SFD_ID: - return "SFD"; - case MLXSW_REG_SFN_ID: - return "SFN"; - case MLXSW_REG_SPMS_ID: - return "SPMS"; - case MLXSW_REG_SPVID_ID: - return "SPVID"; - case MLXSW_REG_SPVM_ID: - return "SPVM"; - case MLXSW_REG_SPAFT_ID: - return "SPAFT"; - case MLXSW_REG_SFGC_ID: - return "SFGC"; - case MLXSW_REG_SFTR_ID: - return "SFTR"; - case MLXSW_REG_SFDF_ID: - return "SFDF"; - case MLXSW_REG_SLDR_ID: - return "SLDR"; - case MLXSW_REG_SLCR_ID: - return "SLCR"; - case MLXSW_REG_SLCOR_ID: - return "SLCOR"; - case MLXSW_REG_SPMLR_ID: - return "SPMLR"; - case MLXSW_REG_SVFA_ID: - return "SVFA"; - case MLXSW_REG_SVPE_ID: - return "SVPE"; - case MLXSW_REG_SFMR_ID: - return "SFMR"; - case MLXSW_REG_SPVMLR_ID: - return "SPVMLR"; - case MLXSW_REG_QTCT_ID: - return "QTCT"; - case MLXSW_REG_QEEC_ID: - return "QEEC"; - case MLXSW_REG_PMLP_ID: - return "PMLP"; - case MLXSW_REG_PMTU_ID: - return "PMTU"; - case MLXSW_REG_PTYS_ID: - return "PTYS"; - case MLXSW_REG_PPAD_ID: - return "PPAD"; - case MLXSW_REG_PAOS_ID: - return "PAOS"; - case MLXSW_REG_PFCC_ID: - return "PFCC"; - case MLXSW_REG_PPCNT_ID: - return "PPCNT"; - case MLXSW_REG_PPTB_ID: - return "PPTB"; - case MLXSW_REG_PBMC_ID: - return "PBMC"; - case MLXSW_REG_PSPA_ID: - return "PSPA"; - case MLXSW_REG_HTGT_ID: - return "HTGT"; - case MLXSW_REG_HPKT_ID: - return "HPKT"; - case MLXSW_REG_RGCR_ID: - return "RGCR"; - case MLXSW_REG_RITR_ID: - return "RITR"; - case MLXSW_REG_RATR_ID: - return "RATR"; - case MLXSW_REG_RALTA_ID: - return "RALTA"; - case MLXSW_REG_RALST_ID: - return "RALST"; - case MLXSW_REG_RALTB_ID: - return "RALTB"; - case MLXSW_REG_RALUE_ID: - return "RALUE"; - case MLXSW_REG_RAUHT_ID: - return "RAUHT"; - case MLXSW_REG_RALEU_ID: - return "RALEU"; - case MLXSW_REG_RAUHTD_ID: - return "RAUHTD"; - case MLXSW_REG_MFCR_ID: - return "MFCR"; - case MLXSW_REG_MFSC_ID: - return "MFSC"; - case MLXSW_REG_MFSM_ID: - return "MFSM"; - case MLXSW_REG_MTCAP_ID: - return "MTCAP"; - case MLXSW_REG_MPAT_ID: - return "MPAT"; - case MLXSW_REG_MPAR_ID: - return "MPAR"; - case MLXSW_REG_MTMP_ID: - return "MTMP"; - case MLXSW_REG_MLCR_ID: - return "MLCR"; - case MLXSW_REG_SBPR_ID: - return "SBPR"; - case MLXSW_REG_SBCM_ID: - return "SBCM"; - case MLXSW_REG_SBPM_ID: - return "SBPM"; - case MLXSW_REG_SBMM_ID: - return "SBMM"; - case MLXSW_REG_SBSR_ID: - return "SBSR"; - case MLXSW_REG_SBIB_ID: - return "SBIB"; - default: - return "*UNKNOWN*"; + const struct mlxsw_reg_info *reg_info; + int i; + + for (i = 0; i < ARRAY_SIZE(mlxsw_reg_infos); i++) { + reg_info = mlxsw_reg_infos[i]; + if (reg_info->id == reg_id) + return reg_info->name; } + return "*UNKNOWN*"; } /* PUDE - Port Up / Down Event -- cgit v1.2.3 From f38a2314e55978e7b5c128175db27244665d0765 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 21 Oct 2016 16:07:22 +0200 Subject: mlxsw: cmd: Push resource query defines to cmd.h Push cmd resource query related defines to cmd.h where they belong. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 5 +++++ drivers/net/ethernet/mellanox/mlxsw/pci.c | 10 ++++------ 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 28271bedd957..56e19b0d2f8f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -513,6 +513,11 @@ static inline int mlxsw_cmd_unmap_fa(struct mlxsw_core *mlxsw_core) * are no more sources in the table, will return resource id 0xFFF to indicate * it. */ + +#define MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID 0xffff +#define MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES 100 +#define MLXSW_CMD_QUERY_RESOURCES_PER_QUERY 32 + static inline int mlxsw_cmd_query_resources(struct mlxsw_core *mlxsw_core, char *out_mbox, int index) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 6f368068aa15..c3b16632bfc5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1155,7 +1155,6 @@ mlxsw_pci_config_profile_swid_config(struct mlxsw_pci *mlxsw_pci, mlxsw_cmd_mbox_config_profile_swid_config_mask_set(mbox, index, mask); } -#define MLXSW_RESOURCES_TABLE_END_ID 0xffff #define MLXSW_MAX_SPAN_ID 0x2420 #define MLXSW_MAX_LAG_ID 0x2520 #define MLXSW_MAX_PORTS_IN_LAG_ID 0x2521 @@ -1167,8 +1166,6 @@ mlxsw_pci_config_profile_swid_config(struct mlxsw_pci *mlxsw_pci, #define MLXSW_MAX_VLAN_GROUPS_ID 0x2906 #define MLXSW_MAX_REGIONS_ID 0x2901 #define MLXSW_MAX_RIF_ID 0x2C02 -#define MLXSW_RESOURCES_QUERY_MAX_QUERIES 100 -#define MLXSW_RESOURCES_PER_QUERY 32 static void mlxsw_pci_resources_query_parse(int id, u64 val, struct mlxsw_resources *resources) @@ -1238,16 +1235,17 @@ static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_zero(mbox); - for (index = 0; index < MLXSW_RESOURCES_QUERY_MAX_QUERIES; index++) { + for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES; + index++) { err = mlxsw_cmd_query_resources(mlxsw_pci->core, mbox, index); if (err) return err; - for (i = 0; i < MLXSW_RESOURCES_PER_QUERY; i++) { + for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) { id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i); data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i); - if (id == MLXSW_RESOURCES_TABLE_END_ID) + if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID) return 0; mlxsw_pci_resources_query_parse(id, data, resources); -- cgit v1.2.3 From c1a3831121f60f614fe92314d8c271d4d89d0a9a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 21 Oct 2016 16:07:23 +0200 Subject: mlxsw: Convert resources into array Since the number of resources is going to get much bigger, ease up the addition by simly defining IDs. Convert the existing structure members to a set array, one for validity, one for values. Introduce a set of getters and setters for easy access. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 32 ++++-- drivers/net/ethernet/mellanox/mlxsw/core.h | 44 ++----- drivers/net/ethernet/mellanox/mlxsw/pci.c | 127 ++++++--------------- drivers/net/ethernet/mellanox/mlxsw/resources.h | 121 ++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 38 +++--- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 5 +- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 39 +++---- .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 7 +- 8 files changed, 223 insertions(+), 190 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/resources.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index aa33d58b9f81..a37d471728ed 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -67,6 +67,7 @@ #include "trap.h" #include "emad.h" #include "reg.h" +#include "resources.h" static LIST_HEAD(mlxsw_core_driver_list); static DEFINE_SPINLOCK(mlxsw_core_driver_list_lock); @@ -111,7 +112,7 @@ struct mlxsw_core { struct { u8 *mapping; /* lag_id+port_index to local_port mapping */ } lag; - struct mlxsw_resources resources; + struct mlxsw_res res; struct mlxsw_hwmon *hwmon; unsigned long driver_priv[0]; /* driver_priv has to be always the last item */ @@ -1101,14 +1102,15 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, } err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile, - &mlxsw_core->resources); + &mlxsw_core->res); if (err) goto err_bus_init; - if (mlxsw_core->resources.max_lag_valid && - mlxsw_core->resources.max_ports_in_lag_valid) { - alloc_size = sizeof(u8) * mlxsw_core->resources.max_lag * - mlxsw_core->resources.max_ports_in_lag; + if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) && + MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) { + alloc_size = sizeof(u8) * + MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) * + MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL); if (!mlxsw_core->lag.mapping) { err = -ENOMEM; @@ -1615,7 +1617,7 @@ EXPORT_SYMBOL(mlxsw_core_skb_receive); static int mlxsw_core_lag_mapping_index(struct mlxsw_core *mlxsw_core, u16 lag_id, u8 port_index) { - return mlxsw_core->resources.max_ports_in_lag * lag_id + + return MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS) * lag_id + port_index; } @@ -1644,7 +1646,7 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, { int i; - for (i = 0; i < mlxsw_core->resources.max_ports_in_lag; i++) { + for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); i++) { int index = mlxsw_core_lag_mapping_index(mlxsw_core, lag_id, i); @@ -1654,11 +1656,19 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_core_lag_mapping_clear); -struct mlxsw_resources *mlxsw_core_resources_get(struct mlxsw_core *mlxsw_core) +bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core, + enum mlxsw_res_id res_id) { - return &mlxsw_core->resources; + return mlxsw_res_valid(&mlxsw_core->res, res_id); } -EXPORT_SYMBOL(mlxsw_core_resources_get); +EXPORT_SYMBOL(mlxsw_core_res_valid); + +u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, + enum mlxsw_res_id res_id) +{ + return mlxsw_res_get(&mlxsw_core->res, res_id); +} +EXPORT_SYMBOL(mlxsw_core_res_get); int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, struct mlxsw_core_port *mlxsw_core_port, u8 local_port, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index c4f550b6f783..94a846d34c2f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -48,8 +48,8 @@ #include "trap.h" #include "reg.h" - #include "cmd.h" +#include "resources.h" #define MLXSW_MODULE_ALIAS_PREFIX "mlxsw-driver-" #define MODULE_MLXSW_DRIVER_ALIAS(kind) \ @@ -266,45 +266,23 @@ struct mlxsw_driver { const struct mlxsw_config_profile *profile; }; -struct mlxsw_resources { - u32 max_span_valid:1, - max_lag_valid:1, - max_ports_in_lag_valid:1, - kvd_size_valid:1, - kvd_single_min_size_valid:1, - kvd_double_min_size_valid:1, - max_virtual_routers_valid:1, - max_system_ports_valid:1, - max_vlan_groups_valid:1, - max_regions_valid:1, - max_rif_valid:1; - u8 max_span; - u8 max_lag; - u8 max_ports_in_lag; - u32 kvd_size; - u32 kvd_single_min_size; - u32 kvd_double_min_size; - u16 max_virtual_routers; - u16 max_system_ports; - u16 max_vlan_groups; - u16 max_regions; - u16 max_rif; +bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core, + enum mlxsw_res_id res_id); - /* Internal resources. - * Determined by the SW, not queried from the HW. - */ - u32 kvd_single_size; - u32 kvd_double_size; - u32 kvd_linear_size; -}; +#define MLXSW_CORE_RES_VALID(res, short_res_id) \ + mlxsw_core_res_valid(res, MLXSW_RES_ID_##short_res_id) + +u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, + enum mlxsw_res_id res_id); -struct mlxsw_resources *mlxsw_core_resources_get(struct mlxsw_core *mlxsw_core); +#define MLXSW_CORE_RES_GET(res, short_res_id) \ + mlxsw_core_res_get(res, MLXSW_RES_ID_##short_res_id) struct mlxsw_bus { const char *kind; int (*init)(void *bus_priv, struct mlxsw_core *mlxsw_core, const struct mlxsw_config_profile *profile, - struct mlxsw_resources *resources); + struct mlxsw_res *res); void (*fini)(void *bus_priv); bool (*skb_transmit_busy)(void *bus_priv, const struct mlxsw_tx_info *tx_info); diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index c3b16632bfc5..c88f2ab90a39 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -52,6 +52,7 @@ #include "core.h" #include "cmd.h" #include "port.h" +#include "resources.h" static const char mlxsw_pci_driver_name[] = "mlxsw_pci"; @@ -1155,73 +1156,8 @@ mlxsw_pci_config_profile_swid_config(struct mlxsw_pci *mlxsw_pci, mlxsw_cmd_mbox_config_profile_swid_config_mask_set(mbox, index, mask); } -#define MLXSW_MAX_SPAN_ID 0x2420 -#define MLXSW_MAX_LAG_ID 0x2520 -#define MLXSW_MAX_PORTS_IN_LAG_ID 0x2521 -#define MLXSW_KVD_SIZE_ID 0x1001 -#define MLXSW_KVD_SINGLE_MIN_SIZE_ID 0x1002 -#define MLXSW_KVD_DOUBLE_MIN_SIZE_ID 0x1003 -#define MLXSW_MAX_VIRTUAL_ROUTERS_ID 0x2C01 -#define MLXSW_MAX_SYSTEM_PORT_ID 0x2502 -#define MLXSW_MAX_VLAN_GROUPS_ID 0x2906 -#define MLXSW_MAX_REGIONS_ID 0x2901 -#define MLXSW_MAX_RIF_ID 0x2C02 - -static void mlxsw_pci_resources_query_parse(int id, u64 val, - struct mlxsw_resources *resources) -{ - switch (id) { - case MLXSW_MAX_SPAN_ID: - resources->max_span = val; - resources->max_span_valid = 1; - break; - case MLXSW_MAX_LAG_ID: - resources->max_lag = val; - resources->max_lag_valid = 1; - break; - case MLXSW_MAX_PORTS_IN_LAG_ID: - resources->max_ports_in_lag = val; - resources->max_ports_in_lag_valid = 1; - break; - case MLXSW_KVD_SIZE_ID: - resources->kvd_size = val; - resources->kvd_size_valid = 1; - break; - case MLXSW_KVD_SINGLE_MIN_SIZE_ID: - resources->kvd_single_min_size = val; - resources->kvd_single_min_size_valid = 1; - break; - case MLXSW_KVD_DOUBLE_MIN_SIZE_ID: - resources->kvd_double_min_size = val; - resources->kvd_double_min_size_valid = 1; - break; - case MLXSW_MAX_VIRTUAL_ROUTERS_ID: - resources->max_virtual_routers = val; - resources->max_virtual_routers_valid = 1; - break; - case MLXSW_MAX_SYSTEM_PORT_ID: - resources->max_system_ports = val; - resources->max_system_ports_valid = 1; - break; - case MLXSW_MAX_VLAN_GROUPS_ID: - resources->max_vlan_groups = val; - resources->max_vlan_groups_valid = 1; - break; - case MLXSW_MAX_REGIONS_ID: - resources->max_regions = val; - resources->max_regions_valid = 1; - break; - case MLXSW_MAX_RIF_ID: - resources->max_rif = val; - resources->max_rif_valid = 1; - break; - default: - break; - } -} - static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox, - struct mlxsw_resources *resources, + struct mlxsw_res *res, u8 query_enabled) { int index, i; @@ -1248,7 +1184,7 @@ static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox, if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID) return 0; - mlxsw_pci_resources_query_parse(id, data, resources); + mlxsw_res_parse(res, id, data); } } @@ -1258,13 +1194,14 @@ static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox, return -EIO; } -static int mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile, - struct mlxsw_resources *resources) +static int +mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile, + struct mlxsw_res *res) { - u32 singles_size, doubles_size, linear_size; + u32 single_size, double_size, linear_size; - if (!resources->kvd_single_min_size_valid || - !resources->kvd_double_min_size_valid || + if (!MLXSW_RES_VALID(res, KVD_SINGLE_MIN_SIZE) || + !MLXSW_RES_VALID(res, KVD_DOUBLE_MIN_SIZE) || !profile->used_kvd_split_data) return -EIO; @@ -1276,31 +1213,31 @@ static int mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *pr * Both sizes must be a multiplications of the * granularity from the profile. */ - doubles_size = (resources->kvd_size - linear_size); - doubles_size *= profile->kvd_hash_double_parts; - doubles_size /= (profile->kvd_hash_double_parts + - profile->kvd_hash_single_parts); - doubles_size /= profile->kvd_hash_granularity; - doubles_size *= profile->kvd_hash_granularity; - singles_size = resources->kvd_size - doubles_size - - linear_size; + double_size = MLXSW_RES_GET(res, KVD_SIZE) - linear_size; + double_size *= profile->kvd_hash_double_parts; + double_size /= profile->kvd_hash_double_parts + + profile->kvd_hash_single_parts; + double_size /= profile->kvd_hash_granularity; + double_size *= profile->kvd_hash_granularity; + single_size = MLXSW_RES_GET(res, KVD_SIZE) - double_size - + linear_size; /* Check results are legal. */ - if (singles_size < resources->kvd_single_min_size || - doubles_size < resources->kvd_double_min_size || - resources->kvd_size < linear_size) + if (single_size < MLXSW_RES_GET(res, KVD_SINGLE_MIN_SIZE) || + double_size < MLXSW_RES_GET(res, KVD_DOUBLE_MIN_SIZE) || + MLXSW_RES_GET(res, KVD_SIZE) < linear_size) return -EIO; - resources->kvd_single_size = singles_size; - resources->kvd_double_size = doubles_size; - resources->kvd_linear_size = linear_size; + MLXSW_RES_SET(res, KVD_SINGLE_SIZE, single_size); + MLXSW_RES_SET(res, KVD_DOUBLE_SIZE, double_size); + MLXSW_RES_SET(res, KVD_LINEAR_SIZE, linear_size); return 0; } static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, const struct mlxsw_config_profile *profile, - struct mlxsw_resources *resources) + struct mlxsw_res *res) { int i; int err; @@ -1389,22 +1326,22 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_config_profile_adaptive_routing_group_cap_set( mbox, profile->adaptive_routing_group_cap); } - if (resources->kvd_size_valid) { - err = mlxsw_pci_profile_get_kvd_sizes(profile, resources); + if (MLXSW_RES_VALID(res, KVD_SIZE)) { + err = mlxsw_pci_profile_get_kvd_sizes(profile, res); if (err) return err; mlxsw_cmd_mbox_config_profile_set_kvd_linear_size_set(mbox, 1); mlxsw_cmd_mbox_config_profile_kvd_linear_size_set(mbox, - resources->kvd_linear_size); + MLXSW_RES_GET(res, KVD_LINEAR_SIZE)); mlxsw_cmd_mbox_config_profile_set_kvd_hash_single_size_set(mbox, 1); mlxsw_cmd_mbox_config_profile_kvd_hash_single_size_set(mbox, - resources->kvd_single_size); + MLXSW_RES_GET(res, KVD_SINGLE_SIZE)); mlxsw_cmd_mbox_config_profile_set_kvd_hash_double_size_set( mbox, 1); mlxsw_cmd_mbox_config_profile_kvd_hash_double_size_set(mbox, - resources->kvd_double_size); + MLXSW_RES_GET(res, KVD_DOUBLE_SIZE)); } for (i = 0; i < MLXSW_CONFIG_PROFILE_SWID_COUNT; i++) @@ -1542,7 +1479,7 @@ static void mlxsw_pci_mbox_free(struct mlxsw_pci *mlxsw_pci, static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, const struct mlxsw_config_profile *profile, - struct mlxsw_resources *resources) + struct mlxsw_res *res) { struct mlxsw_pci *mlxsw_pci = bus_priv; struct pci_dev *pdev = mlxsw_pci->pdev; @@ -1601,12 +1538,12 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, if (err) goto err_boardinfo; - err = mlxsw_pci_resources_query(mlxsw_pci, mbox, resources, + err = mlxsw_pci_resources_query(mlxsw_pci, mbox, res, profile->resource_query_enable); if (err) goto err_query_resources; - err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, resources); + err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res); if (err) goto err_config_profile; diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h new file mode 100644 index 000000000000..a031e45c8b06 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h @@ -0,0 +1,121 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/resources.h + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Jiri Pirko + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MLXSW_RESOURCES_H +#define _MLXSW_RESOURCES_H + +#include +#include + +enum mlxsw_res_id { + MLXSW_RES_ID_KVD_SIZE, + MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE, + MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE, + MLXSW_RES_ID_MAX_SPAN, + MLXSW_RES_ID_MAX_SYSTEM_PORT, + MLXSW_RES_ID_MAX_LAG, + MLXSW_RES_ID_MAX_LAG_MEMBERS, + MLXSW_RES_ID_MAX_VRS, + MLXSW_RES_ID_MAX_RIFS, + + /* Internal resources. + * Determined by the SW, not queried from the HW. + */ + MLXSW_RES_ID_KVD_SINGLE_SIZE, + MLXSW_RES_ID_KVD_DOUBLE_SIZE, + MLXSW_RES_ID_KVD_LINEAR_SIZE, + + __MLXSW_RES_ID_MAX, +}; + +static u16 mlxsw_res_ids[] = { + [MLXSW_RES_ID_KVD_SIZE] = 0x1001, + [MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE] = 0x1002, + [MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE] = 0x1003, + [MLXSW_RES_ID_MAX_SPAN] = 0x2420, + [MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502, + [MLXSW_RES_ID_MAX_LAG] = 0x2520, + [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521, + [MLXSW_RES_ID_MAX_VRS] = 0x2C01, + [MLXSW_RES_ID_MAX_RIFS] = 0x2C02, +}; + +struct mlxsw_res { + bool valid[__MLXSW_RES_ID_MAX]; + u64 values[__MLXSW_RES_ID_MAX]; +}; + +static inline bool mlxsw_res_valid(struct mlxsw_res *res, + enum mlxsw_res_id res_id) +{ + return res->valid[res_id]; +} + +#define MLXSW_RES_VALID(res, short_res_id) \ + mlxsw_res_valid(res, MLXSW_RES_ID_##short_res_id) + +static inline u64 mlxsw_res_get(struct mlxsw_res *res, + enum mlxsw_res_id res_id) +{ + if (WARN_ON(!res->valid[res_id])) + return 0; + return res->values[res_id]; +} + +#define MLXSW_RES_GET(res, short_res_id) \ + mlxsw_res_get(res, MLXSW_RES_ID_##short_res_id) + +static inline void mlxsw_res_set(struct mlxsw_res *res, + enum mlxsw_res_id res_id, u64 value) +{ + res->valid[res_id] = true; + res->values[res_id] = value; +} + +#define MLXSW_RES_SET(res, short_res_id, value) \ + mlxsw_res_set(res, MLXSW_RES_ID_##short_res_id, value) + +static inline void mlxsw_res_parse(struct mlxsw_res *res, u16 id, u64 value) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mlxsw_res_ids); i++) { + if (mlxsw_res_ids[i] == id) { + mlxsw_res_set(res, i, value); + return; + } + } +} + +#endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 991a320470a9..5d8f1d51a403 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -168,14 +168,13 @@ static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_resources *resources; int i; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - if (!resources->max_span_valid) + if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN)) return -EIO; - mlxsw_sp->span.entries_count = resources->max_span; + mlxsw_sp->span.entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, + MAX_SPAN); mlxsw_sp->span.entries = kcalloc(mlxsw_sp->span.entries_count, sizeof(struct mlxsw_sp_span_entry), GFP_KERNEL); @@ -2892,7 +2891,6 @@ static int mlxsw_sp_flood_init(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_resources *resources; char slcr_pl[MLXSW_REG_SLCR_LEN]; int err; @@ -2909,11 +2907,11 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp) if (err) return err; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - if (!(resources->max_lag_valid && resources->max_ports_in_lag_valid)) + if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG) || + !MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS)) return -EIO; - mlxsw_sp->lags = kcalloc(resources->max_lag, + mlxsw_sp->lags = kcalloc(MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG), sizeof(struct mlxsw_sp_upper), GFP_KERNEL); if (!mlxsw_sp->lags) @@ -3183,11 +3181,9 @@ static bool mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *r, static int mlxsw_sp_avail_rif_get(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_resources *resources; int i; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_rif; i++) + for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) if (!mlxsw_sp->rifs[i]) return i; @@ -3710,14 +3706,15 @@ static bool mlxsw_sp_port_fdb_should_flush(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; u8 local_port = mlxsw_sp_port->local_port; u16 lag_id = mlxsw_sp_port->lag_id; - struct mlxsw_resources *resources; + u64 max_lag_members; int i, count = 0; if (!mlxsw_sp_port->lagged) return true; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_ports_in_lag; i++) { + max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core, + MAX_LAG_MEMBERS); + for (i = 0; i < max_lag_members; i++) { struct mlxsw_sp_port *lag_port; lag_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i); @@ -3923,13 +3920,13 @@ static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp, struct net_device *lag_dev, u16 *p_lag_id) { - struct mlxsw_resources *resources; struct mlxsw_sp_upper *lag; int free_lag_id = -1; + u64 max_lag; int i; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_lag; i++) { + max_lag = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG); + for (i = 0; i < max_lag; i++) { lag = mlxsw_sp_lag_get(mlxsw_sp, i); if (lag->ref_count) { if (lag->dev == lag_dev) { @@ -3963,11 +3960,12 @@ mlxsw_sp_master_lag_check(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id, u8 *p_port_index) { - struct mlxsw_resources *resources; + u64 max_lag_members; int i; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_ports_in_lag; i++) { + max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core, + MAX_LAG_MEMBERS); + for (i = 0; i < max_lag_members; i++) { if (!mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i)) { *p_port_index = i; return 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 9b22863a924b..cc5462556a83 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -479,12 +479,9 @@ static inline struct mlxsw_sp_rif * mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp, const struct net_device *dev) { - struct mlxsw_resources *resources; int i; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - - for (i = 0; i < resources->max_rif; i++) + for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) if (mlxsw_sp->rifs[i] && mlxsw_sp->rifs[i]->dev == dev) return mlxsw_sp->rifs[i]; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 78fc557d6dd7..113f667e59df 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -379,12 +379,10 @@ static void mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp) static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_resources *resources; struct mlxsw_sp_vr *vr; int i; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_virtual_routers; i++) { + for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { vr = &mlxsw_sp->router.vrs[i]; if (!vr->used) return vr; @@ -426,14 +424,12 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id, enum mlxsw_sp_l3proto proto) { - struct mlxsw_resources *resources; struct mlxsw_sp_vr *vr; int i; tb_id = mlxsw_sp_fix_tb_id(tb_id); - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_virtual_routers; i++) { + for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { vr = &mlxsw_sp->router.vrs[i]; if (vr->used && vr->proto == proto && vr->tb_id == tb_id) return vr; @@ -569,21 +565,20 @@ static void mlxsw_sp_vr_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr) static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_resources *resources; struct mlxsw_sp_vr *vr; + u64 max_vrs; int i; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - if (!resources->max_virtual_routers_valid) + if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS)) return -EIO; - mlxsw_sp->router.vrs = kcalloc(resources->max_virtual_routers, - sizeof(struct mlxsw_sp_vr), + max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); + mlxsw_sp->router.vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr), GFP_KERNEL); if (!mlxsw_sp->router.vrs) return -ENOMEM; - for (i = 0; i < resources->max_virtual_routers; i++) { + for (i = 0; i < max_vrs; i++) { vr = &mlxsw_sp->router.vrs[i]; vr->id = i; } @@ -1875,15 +1870,13 @@ static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_router_fib4_abort(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_resources *resources; struct mlxsw_sp_fib_entry *fib_entry; struct mlxsw_sp_fib_entry *tmp; struct mlxsw_sp_vr *vr; int i; int err; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_virtual_routers; i++) { + for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { vr = &mlxsw_sp->router.vrs[i]; if (!vr->used) continue; @@ -1908,21 +1901,21 @@ static void mlxsw_sp_router_fib4_abort(struct mlxsw_sp *mlxsw_sp) static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_resources *resources; char rgcr_pl[MLXSW_REG_RGCR_LEN]; + u64 max_rifs; int err; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - if (!resources->max_rif_valid) + if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS)) return -EIO; - mlxsw_sp->rifs = kcalloc(resources->max_rif, - sizeof(struct mlxsw_sp_rif *), GFP_KERNEL); + max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); + mlxsw_sp->rifs = kcalloc(max_rifs, sizeof(struct mlxsw_sp_rif *), + GFP_KERNEL); if (!mlxsw_sp->rifs) return -ENOMEM; mlxsw_reg_rgcr_pack(rgcr_pl, true); - mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, resources->max_rif); + mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl); if (err) goto err_rgcr_fail; @@ -1936,15 +1929,13 @@ err_rgcr_fail: static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_resources *resources; char rgcr_pl[MLXSW_REG_RGCR_LEN]; int i; mlxsw_reg_rgcr_pack(rgcr_pl, false); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl); - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_rif; i++) + for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) WARN_ON_ONCE(mlxsw_sp->rifs[i]); kfree(mlxsw_sp->rifs); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 5e00c79e8133..b19552a72778 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1196,11 +1196,12 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, u16 lag_id) { struct mlxsw_sp_port *mlxsw_sp_port; - struct mlxsw_resources *resources; + u64 max_lag_members; int i; - resources = mlxsw_core_resources_get(mlxsw_sp->core); - for (i = 0; i < resources->max_ports_in_lag; i++) { + max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core, + MAX_LAG_MEMBERS); + for (i = 0; i < max_lag_members; i++) { mlxsw_sp_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i); if (mlxsw_sp_port) return mlxsw_sp_port; -- cgit v1.2.3 From d1bbef6d15357bab359177b093c0015dc61aab7c Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 21 Oct 2016 09:59:10 +0800 Subject: drm/i915/gvt: Fix failure when ACPI is not enabled Directly use memremap instead of acpi function for opregion mapping. Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/opregion.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c index 973c8a9d0b15..95218913b0bc 100644 --- a/drivers/gpu/drm/i915/gvt/opregion.c +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -163,7 +163,7 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa) */ void intel_gvt_clean_opregion(struct intel_gvt *gvt) { - iounmap(gvt->opregion.opregion_va); + memunmap(gvt->opregion.opregion_va); gvt->opregion.opregion_va = NULL; } @@ -181,8 +181,8 @@ int intel_gvt_init_opregion(struct intel_gvt *gvt) pci_read_config_dword(gvt->dev_priv->drm.pdev, INTEL_GVT_PCI_OPREGION, &gvt->opregion.opregion_pa); - gvt->opregion.opregion_va = acpi_os_ioremap(gvt->opregion.opregion_pa, - INTEL_GVT_OPREGION_SIZE); + gvt->opregion.opregion_va = memremap(gvt->opregion.opregion_pa, + INTEL_GVT_OPREGION_SIZE, MEMREMAP_WB); if (!gvt->opregion.opregion_va) { gvt_err("fail to map host opregion\n"); return -EFAULT; -- cgit v1.2.3 From 7093f5ff75ae759ef9bdd514f917a1f57cd10d65 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 21 Oct 2016 12:33:56 +0800 Subject: drm/i915: GVT-g driver depends on 64BIT kernel We currently don't support GVT-g driver on i386 kernel. Add explicit dependence on 64bit kernel. Reviewed-by: Joonas Lahtinen Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 6aedc96aa412..c72b007c2048 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -86,6 +86,7 @@ config DRM_I915_USERPTR config DRM_I915_GVT bool "Enable Intel GVT-g graphics virtualization host support" depends on DRM_I915 + depends on 64BIT default n help Choose this option if you want to enable Intel GVT-g graphics -- cgit v1.2.3 From 1c860a306e76756f28f3b4d589a5ca1d1829dd90 Mon Sep 17 00:00:00 2001 From: Arkadiusz Hiler Date: Fri, 21 Oct 2016 13:11:50 +0200 Subject: drm/i915/gvt: Implement WaForceWakeRenderDuringMmioTLBInvalidate When invalidating RCS TLB the device can enter RC6 state interrupting the process, therefore the need for render forcewake for the whole procedure. This WA is needed for all production SKL SKUs. v2: reworked putting and getting forcewake with help of Mika Kuoppala v3: use I915_READ_FW and I915_WRITE_FW as we are handling forcewake on in the code path References: HSD#2136899, HSD#1404391274 Cc: Mika Kuoppala Cc: Zhenyu Wang Signed-off-by: Arkadiusz Hiler Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/render.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index feebb65ba641..be1a7dfd210b 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -118,6 +118,7 @@ static u32 gen9_render_mocs_L3[32]; static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id) { struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + enum forcewake_domains fw; i915_reg_t reg; u32 regs[] = { [RCS] = 0x4260, @@ -135,11 +136,25 @@ static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id) reg = _MMIO(regs[ring_id]); - I915_WRITE(reg, 0x1); + /* WaForceWakeRenderDuringMmioTLBInvalidate:skl + * we need to put a forcewake when invalidating RCS TLB caches, + * otherwise device can go to RC6 state and interrupt invalidation + * process + */ + fw = intel_uncore_forcewake_for_reg(dev_priv, reg, + FW_REG_READ | FW_REG_WRITE); + if (ring_id == RCS && IS_SKYLAKE(dev_priv)) + fw |= FORCEWAKE_RENDER; - if (wait_for_atomic((I915_READ(reg) == 0), 50)) + intel_uncore_forcewake_get(dev_priv, fw); + + I915_WRITE_FW(reg, 0x1); + + if (wait_for_atomic((I915_READ_FW(reg) == 0), 50)) gvt_err("timeout in invalidate ring (%d) tlb\n", ring_id); + intel_uncore_forcewake_put(dev_priv, fw); + gvt_dbg_core("invalidate TLB for ring %d\n", ring_id); } -- cgit v1.2.3 From 946260e5fb60fcf3a4fbe77840280b5191300564 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Sat, 22 Oct 2016 13:21:45 +0800 Subject: drm/i915/gvt: Fix broken mocs offset Fix missed mocs offset reg setting for save/restore function. Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/render.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index be1a7dfd210b..3af894b3d257 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -177,6 +177,7 @@ static void load_mocs(struct intel_vgpu *vgpu, int ring_id) if (!IS_SKYLAKE(dev_priv)) return; + offset.reg = regs[ring_id]; for (i = 0; i < 64; i++) { gen9_render_mocs[ring_id][i] = I915_READ(offset); I915_WRITE(offset, vgpu_vreg(vgpu, offset)); @@ -214,6 +215,7 @@ static void restore_mocs(struct intel_vgpu *vgpu, int ring_id) if (!IS_SKYLAKE(dev_priv)) return; + offset.reg = regs[ring_id]; for (i = 0; i < 64; i++) { vgpu_vreg(vgpu, offset) = I915_READ(offset); I915_WRITE(offset, gen9_render_mocs[ring_id][i]); -- cgit v1.2.3 From 9558e74c26d2d63b9395f4d4153faa05f9de84f8 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 24 Oct 2016 08:25:36 +0200 Subject: drm/i915: Update DRIVER_DATE to 20161024 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5b2b7f3c6e76..f022f438e5b9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -70,8 +70,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20161010" -#define DRIVER_TIMESTAMP 1476452087 +#define DRIVER_DATE "20161024" +#define DRIVER_TIMESTAMP 1477290335 #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v1.2.3 From 2d2c5ad83f772d7d7b0bb8348ecea42e88f89ab0 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Fri, 21 Oct 2016 15:44:54 +0100 Subject: drm: i915: Wait for fences on new fb, not old The previous code would wait for fences on the framebuffer from the old plane state to complete, rather than the new, so you would see tearing everywhere. Fix this to wait on the new state before we make it active. Signed-off-by: Daniel Stone Fixes: 94f050246b42 ("drm/i915: nonblocking commit") Cc: stable@vger.kernel.org Cc: Daniel Vetter Cc: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161021144454.6288-1-daniels@collabora.com --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6ccedf2af98e..d5d96cffac7d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14401,7 +14401,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) for_each_plane_in_state(state, plane, plane_state, i) { struct intel_plane_state *intel_plane_state = - to_intel_plane_state(plane_state); + to_intel_plane_state(plane->state); if (!intel_plane_state->wait_req) continue; -- cgit v1.2.3 From ed4dba99cae80d14afb8ddcc677a2f547dd70162 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 13 Jun 2016 14:03:34 -0400 Subject: reset: berlin: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/reset/Kconfig:config RESET_BERLIN drivers/reset/Kconfig: bool "Berlin Reset Driver" if COMPILE_TEST drivers/reset/Kconfig: default ARCH_BERLIN or arch/arm/mach-berlin/Kconfig:menuconfig ARCH_BERLIN arch/arm/mach-berlin/Kconfig: bool "Marvell Berlin SoCs" if ARCH_MULTI_V7 or arch/arm64/Kconfig.platforms:config ARCH_BERLIN arch/arm64/Kconfig.platforms: bool "Marvell Berlin SoC Family" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Antoine Tenart Cc: Sebastian Hesselbarth Signed-off-by: Paul Gortmaker Signed-off-by: Philipp Zabel --- drivers/reset/reset-berlin.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c index 369f3917fd8e..371197bbd055 100644 --- a/drivers/reset/reset-berlin.c +++ b/drivers/reset/reset-berlin.c @@ -1,6 +1,8 @@ /* * Copyright (C) 2014 Marvell Technology Group Ltd. * + * Marvell Berlin reset driver + * * Antoine Tenart * Sebastian Hesselbarth * @@ -12,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -91,7 +93,6 @@ static const struct of_device_id berlin_reset_dt_match[] = { { .compatible = "marvell,berlin2-reset" }, { }, }; -MODULE_DEVICE_TABLE(of, berlin_reset_dt_match); static struct platform_driver berlin_reset_driver = { .probe = berlin2_reset_probe, @@ -100,9 +101,4 @@ static struct platform_driver berlin_reset_driver = { .of_match_table = berlin_reset_dt_match, }, }; -module_platform_driver(berlin_reset_driver); - -MODULE_AUTHOR("Antoine Tenart "); -MODULE_AUTHOR("Sebastian Hesselbarth "); -MODULE_DESCRIPTION("Marvell Berlin reset driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(berlin_reset_driver); -- cgit v1.2.3 From 02163199bed1aae49f9ebd2a2172523148c0aaa2 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 13 Jun 2016 14:03:35 -0400 Subject: reset: socfpga: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/reset/Kconfig:config RESET_SOCFPGA drivers/reset/Kconfig: bool "SoCFPGA Reset Driver" if COMPILE_TEST drivers/reset/Kconfig: default ARCH_SOCFPGA or arch/arm/mach-socfpga/Kconfig:menuconfig ARCH_SOCFPGA arch/arm/mach-socfpga/Kconfig: bool "Altera SOCFPGA family" if ARCH_MULTI_V7 ...meaning that it currently is not being built as a module by anyone. Lets remove the small amount of modular evidence that remains, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Steffen Trumtrar Cc: Masahiro Yamada Signed-off-by: Paul Gortmaker Signed-off-by: Philipp Zabel --- drivers/reset/reset-socfpga.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index 78ebf8424375..43e4a9f39b9b 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -1,4 +1,6 @@ /* + * Socfpga Reset Controller Driver + * * Copyright 2014 Steffen Trumtrar * * based on @@ -16,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -148,8 +150,4 @@ static struct platform_driver socfpga_reset_driver = { .of_match_table = socfpga_reset_dt_ids, }, }; -module_platform_driver(socfpga_reset_driver); - -MODULE_AUTHOR("Steffen Trumtrar Date: Mon, 13 Jun 2016 14:03:36 -0400 Subject: reset: sunxi: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/reset/Kconfig:config RESET_SUNXI drivers/reset/Kconfig: bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI drivers/reset/Kconfig: default ARCH_SUNXI or arch/arm/mach-sunxi/Kconfig:menuconfig ARCH_SUNXI arch/arm/mach-sunxi/Kconfig: bool "Allwinner SoCs" if ARCH_MULTI_V7 ...meaning that it currently is not being built as a module by anyone. Lets remove the few remaining traces of modular macro usage, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Maxime Ripard Signed-off-by: Paul Gortmaker Signed-off-by: Philipp Zabel --- drivers/reset/reset-sunxi.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c index 3080190b3f90..b44f6b5f87b6 100644 --- a/drivers/reset/reset-sunxi.c +++ b/drivers/reset/reset-sunxi.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include @@ -142,7 +142,6 @@ static const struct of_device_id sunxi_reset_dt_ids[] = { { .compatible = "allwinner,sun6i-a31-clock-reset", }, { /* sentinel */ }, }; -MODULE_DEVICE_TABLE(of, sunxi_reset_dt_ids); static int sunxi_reset_probe(struct platform_device *pdev) { @@ -175,8 +174,4 @@ static struct platform_driver sunxi_reset_driver = { .of_match_table = sunxi_reset_dt_ids, }, }; -module_platform_driver(sunxi_reset_driver); - -MODULE_AUTHOR("Maxime Ripard Date: Mon, 13 Jun 2016 14:03:37 -0400 Subject: reset: zynq: make it explicitly non-modular MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Makefile/Kconfig currently controlling compilation of this code is: drivers/reset/Kconfig:config RESET_ZYNQ drivers/reset/Kconfig: bool "ZYNQ Reset Driver" if COMPILE_TEST drivers/reset/Kconfig: default ARCH_ZYNQ or drivers/reset/Makefile:obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o arch/arm/mach-zynq/Kconfig:config ARCH_ZYNQ arch/arm/mach-zynq/Kconfig: bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7 ...meaning that it currently is not being built as a module by anyone. Lets remove the few remaining traces of modular macro usage, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: "Sören Brinkmann" Signed-off-by: Paul Gortmaker Acked-by: Michal Simek Acked-by: Moritz Fischer Signed-off-by: Philipp Zabel --- drivers/reset/reset-zynq.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/reset-zynq.c b/drivers/reset/reset-zynq.c index 138f2f205662..87a4e355578f 100644 --- a/drivers/reset/reset-zynq.c +++ b/drivers/reset/reset-zynq.c @@ -3,6 +3,8 @@ * * Xilinx Zynq Reset controller driver * + * Author: Moritz Fischer + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. @@ -15,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -137,8 +139,4 @@ static struct platform_driver zynq_reset_driver = { .of_match_table = zynq_reset_dt_ids, }, }; -module_platform_driver(zynq_reset_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Moritz Fischer "); -MODULE_DESCRIPTION("Zynq Reset Controller Driver"); +builtin_platform_driver(zynq_reset_driver); -- cgit v1.2.3 From cdd24f76fe84fd6ee3b46f54b2a475d04d79889d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 13 Jun 2016 14:03:38 -0400 Subject: reset: lpc18xx: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/reset/Kconfig:config RESET_LPC18XX drivers/reset/Kconfig: bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST drivers/reset/Kconfig: default ARCH_LPC18XX or arch/arm/Kconfig:config ARCH_LPC18XX arch/arm/Kconfig: bool "NXP LPC18xx/LPC43xx" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Joachim Eastwood Signed-off-by: Paul Gortmaker Signed-off-by: Philipp Zabel --- drivers/reset/reset-lpc18xx.c | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c index 54cca0055171..a62ad52e262b 100644 --- a/drivers/reset/reset-lpc18xx.c +++ b/drivers/reset/reset-lpc18xx.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -218,39 +218,17 @@ dis_clk_reg: return ret; } -static int lpc18xx_rgu_remove(struct platform_device *pdev) -{ - struct lpc18xx_rgu_data *rc = platform_get_drvdata(pdev); - int ret; - - ret = unregister_restart_handler(&rc->restart_nb); - if (ret) - dev_warn(&pdev->dev, "failed to unregister restart handler\n"); - - reset_controller_unregister(&rc->rcdev); - - clk_disable_unprepare(rc->clk_delay); - clk_disable_unprepare(rc->clk_reg); - - return 0; -} - static const struct of_device_id lpc18xx_rgu_match[] = { { .compatible = "nxp,lpc1850-rgu" }, { } }; -MODULE_DEVICE_TABLE(of, lpc18xx_rgu_match); static struct platform_driver lpc18xx_rgu_driver = { .probe = lpc18xx_rgu_probe, - .remove = lpc18xx_rgu_remove, .driver = { - .name = "lpc18xx-reset", - .of_match_table = lpc18xx_rgu_match, + .name = "lpc18xx-reset", + .of_match_table = lpc18xx_rgu_match, + .suppress_bind_attrs = true, }, }; -module_platform_driver(lpc18xx_rgu_driver); - -MODULE_AUTHOR("Joachim Eastwood "); -MODULE_DESCRIPTION("Reset driver for LPC18xx/43xx RGU"); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(lpc18xx_rgu_driver); -- cgit v1.2.3 From c2b33559200fb3db93a599528816c88f49d4bddf Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 19 Oct 2016 15:46:38 +0200 Subject: USB: serial: cp210x: clean up CSIZE handling CSIZE is two-bit wide and only CS5 through CS8 are possible values. Signed-off-by: Johan Hovold --- drivers/usb/serial/cp210x.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 54a4de0efdba..66e095021512 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -929,16 +929,9 @@ static void cp210x_set_termios(struct tty_struct *tty, dev_dbg(dev, "%s - data bits = 7\n", __func__); break; case CS8: - bits |= BITS_DATA_8; - dev_dbg(dev, "%s - data bits = 8\n", __func__); - break; - /*case CS9: - bits |= BITS_DATA_9; - dev_dbg(dev, "%s - data bits = 9\n", __func__); - break;*/ default: - dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n"); bits |= BITS_DATA_8; + dev_dbg(dev, "%s - data bits = 8\n", __func__); break; } if (cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits)) -- cgit v1.2.3 From 0407f1ce8fce8e93a249833617221c9905210e5b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 19 Oct 2016 15:46:39 +0200 Subject: USB: serial: cp210x: return -EIO on short control transfers Return -EIO on short control transfers rather than -EPROTO which is used for lower-level transfer errors. Signed-off-by: Johan Hovold --- drivers/usb/serial/cp210x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 66e095021512..f5ee4ba4b33b 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -401,7 +401,7 @@ static int cp210x_read_reg_block(struct usb_serial_port *port, u8 req, dev_err(&port->dev, "failed get req 0x%x size %d status: %d\n", req, bufsize, result); if (result >= 0) - result = -EPROTO; + result = -EIO; /* * FIXME Some callers don't bother to check for error, @@ -514,7 +514,7 @@ static int cp210x_write_reg_block(struct usb_serial_port *port, u8 req, dev_err(&port->dev, "failed set req 0x%x size %d status: %d\n", req, bufsize, result); if (result >= 0) - result = -EPROTO; + result = -EIO; } return result; @@ -682,7 +682,7 @@ static int cp210x_get_tx_queue_byte_count(struct usb_serial_port *port, } else { dev_err(&port->dev, "failed to get comm status: %d\n", result); if (result >= 0) - result = -EPROTO; + result = -EIO; } kfree(sts); -- cgit v1.2.3 From cf5276ce7867d6d87c02fbe4977646ed342e323a Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Thu, 20 Oct 2016 15:13:54 +0100 Subject: USB: serial: cp210x: Adding GPIO support for CP2105 This patch adds support for the GPIO found on the CP2105. Unlike the GPIO provided by some of the other devices supported by the cp210x driver, the GPIO on the CP2015 is muxed on pins otherwise used for serial control lines. The GPIO have been configured in 2 separate banks as the choice to configure the pins for GPIO is made separately for pins shared with each of the 2 serial ports this device provides, though the choice is made for all pins associated with that port in one go. The choice of whether to use the pins for GPIO or serial is made by adding configuration to a one-time programable PROM in the chip and can not be changed at runtime. The device defaults to GPIO. This device supports either push-pull or open-drain modes, it doesn't provide an explicit input mode, though the state of the GPIO can be read when used in open-drain mode. Like with pin use, the mode is configured in the one-time programable PROM and can't be changed at runtime. Signed-off-by: Martyn Welch Signed-off-by: Johan Hovold --- drivers/usb/serial/cp210x.c | 388 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 385 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f5ee4ba4b33b..213ed3868fed 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver" @@ -44,6 +47,9 @@ static int cp210x_tiocmset(struct tty_struct *, unsigned int, unsigned int); static int cp210x_tiocmset_port(struct usb_serial_port *port, unsigned int, unsigned int); static void cp210x_break_ctl(struct tty_struct *, int); +static int cp210x_attach(struct usb_serial *); +static void cp210x_disconnect(struct usb_serial *); +static void cp210x_release(struct usb_serial *); static int cp210x_port_probe(struct usb_serial_port *); static int cp210x_port_remove(struct usb_serial_port *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); @@ -208,6 +214,16 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); +struct cp210x_serial_private { +#ifdef CONFIG_GPIOLIB + struct gpio_chip gc; + u8 config; + u8 gpio_mode; + u8 gpio_registered; +#endif + u8 partnum; +}; + struct cp210x_port_private { __u8 bInterfaceNumber; bool has_swapped_line_ctl; @@ -229,6 +245,9 @@ static struct usb_serial_driver cp210x_device = { .tx_empty = cp210x_tx_empty, .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, + .attach = cp210x_attach, + .disconnect = cp210x_disconnect, + .release = cp210x_release, .port_probe = cp210x_port_probe, .port_remove = cp210x_port_remove, .dtr_rts = cp210x_dtr_rts @@ -271,6 +290,7 @@ static struct usb_serial_driver * const serial_drivers[] = { #define CP210X_SET_CHARS 0x19 #define CP210X_GET_BAUDRATE 0x1D #define CP210X_SET_BAUDRATE 0x1E +#define CP210X_VENDOR_SPECIFIC 0xFF /* CP210X_IFC_ENABLE */ #define UART_ENABLE 0x0001 @@ -313,6 +333,21 @@ static struct usb_serial_driver * const serial_drivers[] = { #define CONTROL_WRITE_DTR 0x0100 #define CONTROL_WRITE_RTS 0x0200 +/* CP210X_VENDOR_SPECIFIC values */ +#define CP210X_READ_LATCH 0x00C2 +#define CP210X_GET_PARTNUM 0x370B +#define CP210X_GET_PORTCONFIG 0x370C +#define CP210X_GET_DEVICEMODE 0x3711 +#define CP210X_WRITE_LATCH 0x37E1 + +/* Part number definitions */ +#define CP210X_PARTNUM_CP2101 0x01 +#define CP210X_PARTNUM_CP2102 0x02 +#define CP210X_PARTNUM_CP2103 0x03 +#define CP210X_PARTNUM_CP2104 0x04 +#define CP210X_PARTNUM_CP2105 0x05 +#define CP210X_PARTNUM_CP2108 0x08 + /* CP210X_GET_COMM_STATUS returns these 0x13 bytes */ struct cp210x_comm_status { __le32 ulErrors; @@ -368,6 +403,60 @@ struct cp210x_flow_ctl { #define CP210X_SERIAL_RTS_ACTIVE 1 #define CP210X_SERIAL_RTS_FLOW_CTL 2 +/* CP210X_VENDOR_SPECIFIC, CP210X_GET_DEVICEMODE call reads these 0x2 bytes. */ +struct cp210x_pin_mode { + u8 eci; + u8 sci; +} __packed; + +#define CP210X_PIN_MODE_MODEM 0 +#define CP210X_PIN_MODE_GPIO BIT(0) + +/* + * CP210X_VENDOR_SPECIFIC, CP210X_GET_PORTCONFIG call reads these 0xf bytes. + * Structure needs padding due to unused/unspecified bytes. + */ +struct cp210x_config { + __le16 gpio_mode; + u8 __pad0[2]; + __le16 reset_state; + u8 __pad1[4]; + __le16 suspend_state; + u8 sci_cfg; + u8 eci_cfg; + u8 device_cfg; +} __packed; + +/* GPIO modes */ +#define CP210X_SCI_GPIO_MODE_OFFSET 9 +#define CP210X_SCI_GPIO_MODE_MASK GENMASK(11, 9) + +#define CP210X_ECI_GPIO_MODE_OFFSET 2 +#define CP210X_ECI_GPIO_MODE_MASK GENMASK(3, 2) + +/* CP2105 port configuration values */ +#define CP2105_GPIO0_TXLED_MODE BIT(0) +#define CP2105_GPIO1_RXLED_MODE BIT(1) +#define CP2105_GPIO1_RS485_MODE BIT(2) + +/* CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x2 bytes. */ +struct cp210x_gpio_write { + u8 mask; + u8 state; +} __packed; + +/* + * Helper to get interface number when we only have struct usb_serial. + */ +static u8 cp210x_interface_num(struct usb_serial *serial) +{ + struct usb_host_interface *cur_altsetting; + + cur_altsetting = serial->interface->cur_altsetting; + + return cur_altsetting->desc.bInterfaceNumber; +} + /* * Reads a variable-sized block of CP210X_ registers, identified by req. * Returns data into buf in native USB byte order. @@ -463,6 +552,40 @@ static int cp210x_read_u8_reg(struct usb_serial_port *port, u8 req, u8 *val) return cp210x_read_reg_block(port, req, val, sizeof(*val)); } +/* + * Reads a variable-sized vendor block of CP210X_ registers, identified by val. + * Returns data into buf in native USB byte order. + */ +static int cp210x_read_vendor_block(struct usb_serial *serial, u8 type, u16 val, + void *buf, int bufsize) +{ + void *dmabuf; + int result; + + dmabuf = kmalloc(bufsize, GFP_KERNEL); + if (!dmabuf) + return -ENOMEM; + + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + CP210X_VENDOR_SPECIFIC, type, val, + cp210x_interface_num(serial), dmabuf, bufsize, + USB_CTRL_GET_TIMEOUT); + if (result == bufsize) { + memcpy(buf, dmabuf, bufsize); + result = 0; + } else { + dev_err(&serial->interface->dev, + "failed to get vendor val 0x%04x size %d: %d\n", val, + bufsize, result); + if (result >= 0) + result = -EIO; + } + + kfree(dmabuf); + + return result; +} + /* * Writes any 16-bit CP210X_ register (req) whose value is passed * entirely in the wValue field of the USB request. @@ -532,6 +655,42 @@ static int cp210x_write_u32_reg(struct usb_serial_port *port, u8 req, u32 val) return cp210x_write_reg_block(port, req, &le32_val, sizeof(le32_val)); } +#ifdef CONFIG_GPIOLIB +/* + * Writes a variable-sized vendor block of CP210X_ registers, identified by val. + * Data in buf must be in native USB byte order. + */ +static int cp210x_write_vendor_block(struct usb_serial *serial, u8 type, + u16 val, void *buf, int bufsize) +{ + void *dmabuf; + int result; + + dmabuf = kmemdup(buf, bufsize, GFP_KERNEL); + if (!dmabuf) + return -ENOMEM; + + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + CP210X_VENDOR_SPECIFIC, type, val, + cp210x_interface_num(serial), dmabuf, bufsize, + USB_CTRL_SET_TIMEOUT); + + kfree(dmabuf); + + if (result == bufsize) { + result = 0; + } else { + dev_err(&serial->interface->dev, + "failed to set vendor val 0x%04x size %d: %d\n", val, + bufsize, result); + if (result >= 0) + result = -EIO; + } + + return result; +} +#endif + /* * Detect CP2108 GET_LINE_CTL bug and activate workaround. * Write a known good value 0x800, read it back. @@ -1098,10 +1257,188 @@ static void cp210x_break_ctl(struct tty_struct *tty, int break_state) cp210x_write_u16_reg(port, CP210X_SET_BREAK, state); } +#ifdef CONFIG_GPIOLIB +static int cp210x_gpio_request(struct gpio_chip *gc, unsigned int offset) +{ + struct usb_serial *serial = gpiochip_get_data(gc); + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + + switch (offset) { + case 0: + if (priv->config & CP2105_GPIO0_TXLED_MODE) + return -ENODEV; + break; + case 1: + if (priv->config & (CP2105_GPIO1_RXLED_MODE | + CP2105_GPIO1_RS485_MODE)) + return -ENODEV; + break; + } + + return 0; +} + +static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + struct usb_serial *serial = gpiochip_get_data(gc); + int result; + u8 buf; + + result = cp210x_read_vendor_block(serial, REQTYPE_INTERFACE_TO_HOST, + CP210X_READ_LATCH, &buf, sizeof(buf)); + if (result < 0) + return result; + + return !!(buf & BIT(gpio)); +} + +static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value) +{ + struct usb_serial *serial = gpiochip_get_data(gc); + struct cp210x_gpio_write buf; + + if (value == 1) + buf.state = BIT(gpio); + else + buf.state = 0; + + buf.mask = BIT(gpio); + + cp210x_write_vendor_block(serial, REQTYPE_HOST_TO_INTERFACE, + CP210X_WRITE_LATCH, &buf, sizeof(buf)); +} + +static int cp210x_gpio_direction_get(struct gpio_chip *gc, unsigned int gpio) +{ + /* Hardware does not support an input mode */ + return 0; +} + +static int cp210x_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio) +{ + /* Hardware does not support an input mode */ + return -ENOTSUPP; +} + +static int cp210x_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio, + int value) +{ + return 0; +} + +static int cp210x_gpio_set_single_ended(struct gpio_chip *gc, unsigned int gpio, + enum single_ended_mode mode) +{ + struct usb_serial *serial = gpiochip_get_data(gc); + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + + /* Succeed only if in correct mode (this can't be set at runtime) */ + if ((mode == LINE_MODE_PUSH_PULL) && (priv->gpio_mode & BIT(gpio))) + return 0; + + if ((mode == LINE_MODE_OPEN_DRAIN) && !(priv->gpio_mode & BIT(gpio))) + return 0; + + return -ENOTSUPP; +} + +/* + * This function is for configuring GPIO using shared pins, where other signals + * are made unavailable by configuring the use of GPIO. This is believed to be + * only applicable to the cp2105 at this point, the other devices supported by + * this driver that provide GPIO do so in a way that does not impact other + * signals and are thus expected to have very different initialisation. + */ +static int cp2105_shared_gpio_init(struct usb_serial *serial) +{ + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + struct cp210x_pin_mode mode; + struct cp210x_config config; + u8 intf_num = cp210x_interface_num(serial); + int result; + + result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, + CP210X_GET_DEVICEMODE, &mode, + sizeof(mode)); + if (result < 0) + return result; + + result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, + CP210X_GET_PORTCONFIG, &config, + sizeof(config)); + if (result < 0) + return result; + + /* 2 banks of GPIO - One for the pins taken from each serial port */ + if (intf_num == 0) { + if (mode.eci == CP210X_PIN_MODE_MODEM) + return 0; + + priv->config = config.eci_cfg; + priv->gpio_mode = (u8)((le16_to_cpu(config.gpio_mode) & + CP210X_ECI_GPIO_MODE_MASK) >> + CP210X_ECI_GPIO_MODE_OFFSET); + priv->gc.ngpio = 2; + } else if (intf_num == 1) { + if (mode.sci == CP210X_PIN_MODE_MODEM) + return 0; + + priv->config = config.sci_cfg; + priv->gpio_mode = (u8)((le16_to_cpu(config.gpio_mode) & + CP210X_SCI_GPIO_MODE_MASK) >> + CP210X_SCI_GPIO_MODE_OFFSET); + priv->gc.ngpio = 3; + } else { + return -ENODEV; + } + + priv->gc.label = "cp210x"; + priv->gc.request = cp210x_gpio_request; + priv->gc.get_direction = cp210x_gpio_direction_get; + priv->gc.direction_input = cp210x_gpio_direction_input; + priv->gc.direction_output = cp210x_gpio_direction_output; + priv->gc.get = cp210x_gpio_get; + priv->gc.set = cp210x_gpio_set; + priv->gc.set_single_ended = cp210x_gpio_set_single_ended; + priv->gc.owner = THIS_MODULE; + priv->gc.parent = &serial->interface->dev; + priv->gc.base = -1; + priv->gc.can_sleep = true; + + result = gpiochip_add_data(&priv->gc, serial); + if (!result) + priv->gpio_registered = 1; + + return result; +} + +static void cp210x_gpio_remove(struct usb_serial *serial) +{ + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + + if (priv->gpio_registered) { + gpiochip_remove(&priv->gc); + priv->gpio_registered = 0; + } +} + +#else + +static int cp2105_shared_gpio_init(struct usb_serial *serial) +{ + return 0; +} + +static void cp210x_gpio_remove(struct usb_serial *serial) +{ + /* Nothing to do */ +} + +#endif + static int cp210x_port_probe(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - struct usb_host_interface *cur_altsetting; struct cp210x_port_private *port_priv; int ret; @@ -1109,8 +1446,7 @@ static int cp210x_port_probe(struct usb_serial_port *port) if (!port_priv) return -ENOMEM; - cur_altsetting = serial->interface->cur_altsetting; - port_priv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber; + port_priv->bInterfaceNumber = cp210x_interface_num(serial); usb_set_serial_port_data(port, port_priv); @@ -1133,6 +1469,52 @@ static int cp210x_port_remove(struct usb_serial_port *port) return 0; } +static int cp210x_attach(struct usb_serial *serial) +{ + int result; + struct cp210x_serial_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, + CP210X_GET_PARTNUM, &priv->partnum, + sizeof(priv->partnum)); + if (result < 0) + goto err_free_priv; + + usb_set_serial_data(serial, priv); + + if (priv->partnum == CP210X_PARTNUM_CP2105) { + result = cp2105_shared_gpio_init(serial); + if (result < 0) { + dev_err(&serial->interface->dev, + "GPIO initialisation failed, continuing without GPIO support\n"); + } + } + + return 0; +err_free_priv: + kfree(priv); + + return result; +} + +static void cp210x_disconnect(struct usb_serial *serial) +{ + cp210x_gpio_remove(serial); +} + +static void cp210x_release(struct usb_serial *serial) +{ + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + + cp210x_gpio_remove(serial); + + kfree(priv); +} + module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); -- cgit v1.2.3 From 6b7271d2536abd6f87fbc5ddd22c42dd1ffe360d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 24 Oct 2016 11:58:12 +0200 Subject: USB: serial: cp210x: use bool for registered flag Use bool rather than u8 for the gpio-chip-registered flag. Signed-off-by: Johan Hovold --- drivers/usb/serial/cp210x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 213ed3868fed..ef7f1c01c2cc 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -219,7 +219,7 @@ struct cp210x_serial_private { struct gpio_chip gc; u8 config; u8 gpio_mode; - u8 gpio_registered; + bool gpio_registered; #endif u8 partnum; }; @@ -1407,7 +1407,7 @@ static int cp2105_shared_gpio_init(struct usb_serial *serial) result = gpiochip_add_data(&priv->gc, serial); if (!result) - priv->gpio_registered = 1; + priv->gpio_registered = true; return result; } @@ -1418,7 +1418,7 @@ static void cp210x_gpio_remove(struct usb_serial *serial) if (priv->gpio_registered) { gpiochip_remove(&priv->gc); - priv->gpio_registered = 0; + priv->gpio_registered = false; } } -- cgit v1.2.3 From 8c27ceff3604b249a9efafbd1bd8b141b79e619d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Oct 2016 10:12:27 -0200 Subject: docs: fix locations of several documents that got moved The previous patch renamed several files that are cross-referenced along the Kernel documentation. Adjust the links to point to the right places. Signed-off-by: Mauro Carvalho Chehab --- Documentation/00-INDEX | 54 +++++++++++----------- Documentation/ABI/README | 2 +- Documentation/ABI/testing/sysfs-kernel-slab | 2 +- Documentation/DocBook/kernel-hacking.tmpl | 4 +- Documentation/acpi/video_extension.txt | 2 +- Documentation/admin-guide/README.rst | 13 +++--- Documentation/admin-guide/bad-memory.rst | 2 +- Documentation/admin-guide/binfmt-misc.rst | 4 +- Documentation/admin-guide/braille-console.rst | 6 +-- Documentation/admin-guide/bug-hunting.rst | 7 +-- Documentation/admin-guide/devices.rst | 2 +- Documentation/admin-guide/kernel-parameters.rst | 6 +-- Documentation/admin-guide/oops-tracing.rst | 2 +- Documentation/admin-guide/ramoops.rst | 2 +- Documentation/admin-guide/reporting-bugs.rst | 6 +-- Documentation/admin-guide/security-bugs.rst | 2 +- Documentation/admin-guide/unicode.rst | 2 +- Documentation/arm/Booting | 2 +- Documentation/atomic_ops.txt | 2 +- Documentation/blockdev/ramdisk.txt | 2 +- Documentation/cgroup-v1/00-INDEX | 2 +- .../devicetree/bindings/rtc/maxim,ds3231.txt | 2 +- Documentation/devicetree/bindings/rtc/pcf8563.txt | 2 +- .../devicetree/bindings/submitting-patches.txt | 2 +- Documentation/filesystems/locks.txt | 2 +- Documentation/filesystems/nfs/nfsroot.txt | 4 +- Documentation/frv/booting.txt | 2 +- Documentation/hwmon/submitting-patches | 8 ++-- Documentation/isdn/README | 2 +- Documentation/ja_JP/HOWTO | 24 +++++----- Documentation/ja_JP/SubmitChecklist | 8 ++-- Documentation/ja_JP/SubmittingPatches | 18 ++++---- Documentation/ja_JP/stable_api_nonsense.txt | 4 +- Documentation/ja_JP/stable_kernel_rules.txt | 6 +-- Documentation/kernel-per-CPU-kthreads.txt | 2 +- Documentation/ko_KR/HOWTO | 30 ++++++------ Documentation/ko_KR/stable_api_nonsense.txt | 4 +- Documentation/lockup-watchdogs.txt | 4 +- Documentation/m68k/kernel-options.txt | 2 +- Documentation/media/uapi/v4l/diff-v4l.rst | 4 +- Documentation/media/v4l-drivers/bttv.rst | 4 +- Documentation/memory-hotplug.txt | 2 +- Documentation/networking/netconsole.txt | 2 +- Documentation/networking/netdev-FAQ.txt | 8 ++-- Documentation/networking/vortex.txt | 2 +- Documentation/power/00-INDEX | 2 +- Documentation/power/pci.txt | 10 ++-- Documentation/power/runtime_pm.txt | 2 +- Documentation/power/swsusp-dmcrypt.txt | 2 +- Documentation/process/4.Coding.rst | 4 +- Documentation/process/5.Posting.rst | 12 ++--- Documentation/process/8.Conclusion.rst | 6 +-- Documentation/process/adding-syscalls.rst | 2 +- Documentation/process/coding-style.rst | 2 +- Documentation/process/howto.rst | 24 +++++----- Documentation/process/management-style.rst | 2 +- Documentation/process/stable-kernel-rules.rst | 4 +- Documentation/process/submit-checklist.rst | 6 +-- Documentation/process/submitting-drivers.rst | 8 ++-- Documentation/process/submitting-patches.rst | 14 +++--- Documentation/rfkill.txt | 2 +- Documentation/scsi/scsi-parameters.txt | 2 +- Documentation/scsi/scsi_mid_low_api.txt | 2 +- Documentation/scsi/sym53c8xx_2.txt | 2 +- Documentation/sound/alsa/alsa-parameters.txt | 2 +- Documentation/sound/oss/oss-parameters.txt | 2 +- Documentation/sysctl/kernel.txt | 4 +- Documentation/virtual/kvm/review-checklist.txt | 4 +- Documentation/vm/numa | 2 +- .../watchdog/convert_drivers_to_kernel_api.txt | 2 +- Documentation/watchdog/watchdog-parameters.txt | 2 +- Documentation/x86/boot.txt | 2 +- Documentation/zh_CN/CodingStyle | 6 +-- Documentation/zh_CN/HOWTO | 30 ++++++------ Documentation/zh_CN/SecurityBugs | 6 +-- Documentation/zh_CN/SubmittingDrivers | 12 ++--- Documentation/zh_CN/SubmittingPatches | 14 +++--- Documentation/zh_CN/arm/Booting | 2 +- Documentation/zh_CN/email-clients.txt | 4 +- Documentation/zh_CN/oops-tracing.txt | 6 +-- Documentation/zh_CN/stable_api_nonsense.txt | 4 +- Documentation/zh_CN/stable_kernel_rules.txt | 6 +-- .../zh_CN/volatile-considered-harmful.txt | 4 +- MAINTAINERS | 10 ++-- arch/x86/Kconfig | 2 +- drivers/acpi/Kconfig | 2 +- drivers/ata/libata-core.c | 2 +- drivers/char/pcmcia/cm4000_cs.c | 4 +- drivers/net/can/grcan.c | 2 +- drivers/nvdimm/Kconfig | 2 +- drivers/staging/vme/devices/vme_user.c | 2 +- drivers/video/fbdev/skeletonfb.c | 8 ++-- drivers/virtio/Kconfig | 2 +- fs/Kconfig.binfmt | 4 +- fs/pstore/Kconfig | 2 +- include/linux/device.h | 2 +- include/linux/pm.h | 2 +- include/uapi/linux/major.h | 2 +- init/Kconfig | 2 +- init/main.c | 2 +- lib/Kconfig.debug | 2 +- scripts/checkpatch.pl | 6 +-- tools/testing/selftests/futex/README | 2 +- 103 files changed, 280 insertions(+), 278 deletions(-) (limited to 'drivers') diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index d07575a8499e..39caa6544d1f 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -15,11 +15,11 @@ Following translations are available on the WWW: ABI/ - info on kernel <-> userspace ABI and relative interface stability. -BUG-HUNTING +admin-guide/bug-hunting.rst - brute force method of doing binary search of patches to find bug. -Changes +process/changes.rst - list of changes that break older software packages. -CodingStyle +process/coding-style.rst - how the maintainers expect the C code in the kernel to look. DMA-API.txt - DMA API, pci_ API & extensions for non-consistent memory machines. @@ -33,7 +33,7 @@ DocBook/ - directory with DocBook templates etc. for kernel documentation. EDID/ - directory with info on customizing EDID for broken gfx/displays. -HOWTO +process/howto.rst - the process and procedures of how to do Linux kernel development. IPMI.txt - info on Linux Intelligent Platform Management Interface (IPMI) Driver. @@ -48,7 +48,7 @@ Intel-IOMMU.txt Makefile - This file does nothing. Removing it breaks make htmldocs and make distclean. -ManagementStyle +process/management-style.rst - how to (attempt to) manage kernel hackers. RCU/ - directory with info on RCU (read-copy update). @@ -56,13 +56,13 @@ SAK.txt - info on Secure Attention Keys. SM501.txt - Silicon Motion SM501 multimedia companion chip -SecurityBugs +admin-guide/security-bugs.rst - procedure for reporting security bugs found in the kernel. -SubmitChecklist +process/submit-checklist.rst - Linux kernel patch submission checklist. -SubmittingDrivers +process/submitting-drivers.rst - procedure to get a new driver source included into the kernel tree. -SubmittingPatches +process/submitting-patches.rst - procedure to get a source patch included into the kernel tree. VGA-softcursor.txt - how to change your VGA cursor from a blinking underscore. @@ -72,7 +72,7 @@ acpi/ - info on ACPI-specific hooks in the kernel. aoe/ - description of AoE (ATA over Ethernet) along with config examples. -applying-patches.txt +process/applying-patches.rst - description of various trees and how to apply their patches. arm/ - directory with info about Linux on the ARM architecture. @@ -86,7 +86,7 @@ auxdisplay/ - misc. LCD driver documentation (cfag12864b, ks0108). backlight/ - directory with info on controlling backlights in flat panel displays -bad_memory.txt +admin-guide/bad-memory.rst - how to use kernel parameters to exclude bad RAM regions. basic_profiling.txt - basic instructions for those who wants to profile Linux kernel. @@ -154,7 +154,7 @@ process/ - how to work with the mainline kernel development process. device-mapper/ - directory with info on Device Mapper. -devices.txt +admin-guide/devices.rst - plain ASCII listing of all the nodes in /dev/ with major minor #'s. devicetree/ - directory with info on device tree files used by OF/PowerPC/ARM @@ -178,7 +178,7 @@ efi-stub.txt - How to use the EFI boot stub to bypass GRUB or elilo on EFI systems. eisa.txt - info on EISA bus support. -email-clients.txt +process/email-clients.rst - info on how to use e-mail to send un-mangled (git) patches. extcon/ - directory with porting guide for Android kernel switch driver. @@ -226,9 +226,9 @@ ia64/ - directory with info about Linux on Intel 64 bit architecture. infiniband/ - directory with documents concerning Linux InfiniBand support. -init.txt +admin-guide/init.rst - what to do when the kernel can't find the 1st process to run. -initrd.txt +admin-guide/initrd.rst - how to use the RAM disk as an initial/temporary root filesystem. input/ - info on Linux input device support. @@ -248,7 +248,7 @@ isapnp.txt - info on Linux ISA Plug & Play support. isdn/ - directory with info on the Linux ISDN support, and supported cards. -java.txt +admin-guide/java.rst - info on the in-kernel binary support for Java(tm). ja_JP/ - directory with Japanese translations of various documents @@ -256,11 +256,11 @@ kbuild/ - directory with info about the kernel build process. kdump/ - directory with mini HowTo on getting the crash dump code to work. -kernel-docs.txt +process/kernel-docs.rst - listing of various WWW + books that document kernel internals. kernel-documentation.rst - how to write and format reStructuredText kernel documentation -kernel-parameters.txt +admin-guide/kernel-parameters.rst - summary listing of command line / boot prompt args for the kernel. kernel-per-CPU-kthreads.txt - List of all per-CPU kthreads and how they introduce jitter. @@ -302,7 +302,7 @@ magic-number.txt - list of magic numbers used to mark/protect kernel data structures. mailbox.txt - How to write drivers for the common mailbox framework (IPC). -md.txt +admin-guide/md.rst - info on boot arguments for the multiple devices driver. media-framework.txt - info on media framework, its data structures, functions and usage. @@ -326,7 +326,7 @@ module-signing.txt - Kernel module signing for increased security when loading modules. mtd/ - directory with info about memory technology devices (flash) -mono.txt +admin-guide/mono.rst - how to execute Mono-based .NET binaries with the help of BINFMT_MISC. namespaces/ - directory with various information about namespaces @@ -340,7 +340,7 @@ nommu-mmap.txt - documentation about no-mmu memory mapping support. numastat.txt - info on how to read Numa policy hit/miss statistics in sysfs. -oops-tracing.txt +admin-guide/oops-tracing.rst - how to decode those nasty internal kernel error dump messages. padata.txt - An introduction to the "padata" parallel execution API @@ -378,7 +378,7 @@ ptp/ - directory with info on support for IEEE 1588 PTP clocks in Linux. pwm.txt - info on the pulse width modulation driver subsystem -ramoops.txt +admin-guide/ramoops.rst - documentation of the ramoops oops/panic logging module. rapidio/ - directory with info on RapidIO packet-based fabric interconnect @@ -406,7 +406,7 @@ security/ - directory that contains security-related info serial/ - directory with info on the low level serial API. -serial-console.txt +admin-guide/serial-console.rst - how to set up Linux with a serial line console as the default. sgi-ioc4.txt - description of the SGI IOC4 PCI (multi function) device. @@ -420,9 +420,9 @@ sparse.txt - info on how to obtain and use the sparse tool for typechecking. spi/ - overview of Linux kernel Serial Peripheral Interface (SPI) support. -stable_api_nonsense.txt +process/stable-api-nonsense.rst - info on why the kernel does not have a stable in-kernel api or abi. -stable_kernel_rules.txt +process/stable-kernel-rules.rst - rules and procedures for the -stable kernel releases. static-keys.txt - info on how static keys allow debug code in hotpaths via patching @@ -444,7 +444,7 @@ trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt - info on how to avoid arch breaking unaligned memory access in code. -unicode.txt +admin-guide/unicode.rst - info on the Unicode character/font mapping used in Linux. unshare.txt - description of the Linux unshare system call. @@ -466,7 +466,7 @@ vm/ - directory with info on the Linux vm code. vme_api.txt - file relating info on the VME bus API in linux -volatile-considered-harmful.txt +process/volatile-considered-harmful.rst - Why the "volatile" type class should not be used w1/ - directory with documents regarding the 1-wire (w1) subsystem. diff --git a/Documentation/ABI/README b/Documentation/ABI/README index 1fafc4b0753b..3121029dce21 100644 --- a/Documentation/ABI/README +++ b/Documentation/ABI/README @@ -84,4 +84,4 @@ stable: - Kernel-internal symbols. Do not rely on the presence, absence, location, or type of any kernel symbol, either in System.map files or the kernel binary - itself. See Documentation/stable_api_nonsense.txt. + itself. See Documentation/process/stable-api-nonsense.rst. diff --git a/Documentation/ABI/testing/sysfs-kernel-slab b/Documentation/ABI/testing/sysfs-kernel-slab index 91bd6ca5440f..2cc0a72b64be 100644 --- a/Documentation/ABI/testing/sysfs-kernel-slab +++ b/Documentation/ABI/testing/sysfs-kernel-slab @@ -347,7 +347,7 @@ Description: because of fragmentation, SLUB will retry with the minimum order possible depending on its characteristics. When debug_guardpage_minorder=N (N > 0) parameter is specified - (see Documentation/kernel-parameters.txt), the minimum possible + (see Documentation/admin-guide/kernel-parameters.rst), the minimum possible order is used and this sysfs entry can not be used to change the order at run time. diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl index 2a272275c81b..da5c087462b1 100644 --- a/Documentation/DocBook/kernel-hacking.tmpl +++ b/Documentation/DocBook/kernel-hacking.tmpl @@ -1208,8 +1208,8 @@ static struct block_device_operations opt_fops = { - Finally, don't forget to read Documentation/SubmittingPatches - and possibly Documentation/SubmittingDrivers. + Finally, don't forget to read Documentation/process/submitting-patches.rst + and possibly Documentation/process/submitting-drivers.rst. diff --git a/Documentation/acpi/video_extension.txt b/Documentation/acpi/video_extension.txt index 78b32ac02466..79bf6a4921be 100644 --- a/Documentation/acpi/video_extension.txt +++ b/Documentation/acpi/video_extension.txt @@ -101,6 +101,6 @@ received a notification, it will set the backlight level accordingly. This does not affect the sending of event to user space, they are always sent to user space regardless of whether or not the video module controls the backlight level directly. This behaviour can be controlled through the brightness_switch_enabled -module parameter as documented in kernel-parameters.txt. It is recommended to +module parameter as documented in admin-guide/kernel-parameters.rst. It is recommended to disable this behaviour once a GUI environment starts up and wants to have full control of the backlight level. diff --git a/Documentation/admin-guide/README.rst b/Documentation/admin-guide/README.rst index 05aad8543340..1b6dfb2b3adb 100644 --- a/Documentation/admin-guide/README.rst +++ b/Documentation/admin-guide/README.rst @@ -50,7 +50,8 @@ Documentation - There are various README files in the Documentation/ subdirectory: these typically contain kernel-specific installation notes for some drivers for example. See Documentation/00-INDEX for a list of what - is contained in each file. Please read the Changes file, as it + is contained in each file. Please read the + :ref:`Documentation/process/changes.rst ` file, as it contains information about the problems, which may result by upgrading your kernel. @@ -96,7 +97,7 @@ Installing the kernel source and 4.0.2 patches. Similarly, if you are running kernel version 4.0.2 and want to jump to 4.0.3, you must first reverse the 4.0.2 patch (that is, patch -R) **before** applying the 4.0.3 patch. You can read more on this in - :ref:`Documentation/applying-patches.txt `. + :ref:`Documentation/process/applying-patches.rst `. Alternatively, the script patch-kernel can be used to automate this process. It determines the current kernel version and applies any @@ -120,7 +121,7 @@ Software requirements Compiling and running the 4.x kernels requires up-to-date versions of various software packages. Consult - :ref:`Documentation/Changes ` for the minimum version numbers + :ref:`Documentation/process/changes.rst ` for the minimum version numbers required and how to get updates for these packages. Beware that using excessively old versions of these packages can cause indirect errors that are very difficult to track down, so don't assume that @@ -254,7 +255,7 @@ Compiling the kernel -------------------- - Make sure you have at least gcc 3.2 available. - For more information, refer to :ref:`Documentation/Changes `. + For more information, refer to :ref:`Documentation/process/changes.rst `. Please note that you can still run a.out user programs with this kernel. @@ -355,7 +356,7 @@ If something goes wrong help debugging the problem. The text above the dump is also important: it tells something about why the kernel dumped code (in the above example, it's due to a bad kernel pointer). More information - on making sense of the dump is in Documentation/oops-tracing.txt + on making sense of the dump is in Documentation/admin-guide/oops-tracing.rst - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump as is, otherwise you will have to use the ``ksymoops`` program to make @@ -393,7 +394,7 @@ If something goes wrong If you for some reason cannot do the above (you have a pre-compiled kernel image or similar), telling me as much about your setup as - possible will help. Please read the :ref:`REPORTING-BUGS ` + possible will help. Please read the :ref:`admin-guide/reporting-bugs.rst ` document for details. - Alternatively, you can use gdb on a running kernel. (read-only; i.e. you diff --git a/Documentation/admin-guide/bad-memory.rst b/Documentation/admin-guide/bad-memory.rst index 017fc86430c3..a5c0e25e496f 100644 --- a/Documentation/admin-guide/bad-memory.rst +++ b/Documentation/admin-guide/bad-memory.rst @@ -33,7 +33,7 @@ memmap is already in the kernel and usable as kernel-parameter at boot-time. Its syntax is slightly strange and you may need to calculate the values by yourself! -Syntax to exclude a memory area (see kernel-parameters.txt for details):: +Syntax to exclude a memory area (see admin-guide/kernel-parameters.rst for details):: memmap=$
diff --git a/Documentation/admin-guide/binfmt-misc.rst b/Documentation/admin-guide/binfmt-misc.rst index 9c5ff8f260bf..97b0d7927078 100644 --- a/Documentation/admin-guide/binfmt-misc.rst +++ b/Documentation/admin-guide/binfmt-misc.rst @@ -124,7 +124,7 @@ A few examples (assumed you are in ``/proc/sys/fs/binfmt_misc``): echo ':DOSWin:M::MZ::/usr/local/bin/wine:' > register -For java support see Documentation/java.txt +For java support see Documentation/admin-guide/java.rst You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable) @@ -140,7 +140,7 @@ Hints ----- If you want to pass special arguments to your interpreter, you can -write a wrapper script for it. See Documentation/java.txt for an +write a wrapper script for it. See Documentation/admin-guide/java.rst for an example. Your interpreter should NOT look in the PATH for the filename; the kernel diff --git a/Documentation/admin-guide/braille-console.rst b/Documentation/admin-guide/braille-console.rst index fa3702dc04ab..18e79337dcfd 100644 --- a/Documentation/admin-guide/braille-console.rst +++ b/Documentation/admin-guide/braille-console.rst @@ -3,7 +3,7 @@ Linux Braille Console To get early boot messages on a braille device (before userspace screen readers can start), you first need to compile the support for the usual serial -console (see :ref:`Documentation/serial-console.txt `), and +console (see :ref:`Documentation/admin-guide/serial-console.rst `), and for braille device (in :menuselection:`Device Drivers --> Accessibility support --> Console on braille device`). @@ -13,7 +13,7 @@ format is:: console=brl,serial_options... where ``serial_options...`` are the same as described in -:ref:`Documentation/serial-console.txt `. +:ref:`Documentation/admin-guide/serial-console.rst `. So for instance you can use ``console=brl,ttyS0`` if the braille device is connected to the first serial port, and ``console=brl,ttyS0,115200`` to override the baud rate to 115200, etc. @@ -31,7 +31,7 @@ parameter. For simplicity, only one braille console can be enabled, other uses of ``console=brl,...`` will be discarded. Also note that it does not interfere with the console selection mechanism described in -:ref:`Documentation/serial-console.txt `. +:ref:`Documentation/admin-guide/serial-console.rst `. For now, only the VisioBraille device is supported. diff --git a/Documentation/admin-guide/bug-hunting.rst b/Documentation/admin-guide/bug-hunting.rst index a8ef794aadae..d35dd9fd1af0 100644 --- a/Documentation/admin-guide/bug-hunting.rst +++ b/Documentation/admin-guide/bug-hunting.rst @@ -15,7 +15,7 @@ give up. Report as much as you have found to the relevant maintainer. See MAINTAINERS for who that is for the subsystem you have worked on. Before you submit a bug report read -:ref:`Documentation/REPORTING-BUGS `. +:ref:`Documentation/admin-guide/reporting-bugs.rst `. Devices not appearing ===================== @@ -244,5 +244,6 @@ Once you have worked out a fix please submit it upstream. After all open source is about sharing what you do and don't you want to be recognised for your genius? -Please do read :ref:`Documentation/SubmittingPatches ` -though to help your code get accepted. +Please do read +ref:`Documentation/process/submitting-patches.rst ` though +to help your code get accepted. diff --git a/Documentation/admin-guide/devices.rst b/Documentation/admin-guide/devices.rst index b29555041531..89db341fba7a 100644 --- a/Documentation/admin-guide/devices.rst +++ b/Documentation/admin-guide/devices.rst @@ -10,7 +10,7 @@ The LaTeX version of this document is no longer maintained, nor is the document that used to reside at lanana.org. This version in the mainline Linux kernel is the master document. Updates shall be sent as patches to the kernel maintainers (see the -:ref:`Documentation/SubmittingPatches ` document). +:ref:`Documentation/process/submitting-patches.rst ` document). Specifically explore the sections titled "CHAR and MISC DRIVERS", and "BLOCK LAYER" in the MAINTAINERS file to find the right maintainers to involve for character and block devices. diff --git a/Documentation/admin-guide/kernel-parameters.rst b/Documentation/admin-guide/kernel-parameters.rst index b0804273b6e3..d2f2725f032e 100644 --- a/Documentation/admin-guide/kernel-parameters.rst +++ b/Documentation/admin-guide/kernel-parameters.rst @@ -815,7 +815,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted:: bits, and "f" is flow control ("r" for RTS or omit it). Default is "9600n8". - See Documentation/serial-console.txt for more + See Documentation/admin-guide/serial-console.rst for more information. See Documentation/networking/netconsole.txt for an alternative. @@ -2239,7 +2239,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted:: mce=option [X86-64] See Documentation/x86/x86_64/boot-options.txt md= [HW] RAID subsystems devices and level - See Documentation/md.txt. + See Documentation/admin-guide/md.rst. mdacon= [MDA] Format: , @@ -3322,7 +3322,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted:: r128= [HW,DRM] raid= [HW,RAID] - See Documentation/md.txt. + See Documentation/admin-guide/md.rst. ramdisk_size= [RAM] Sizes of RAM disks in kilobytes See Documentation/blockdev/ramdisk.txt. diff --git a/Documentation/admin-guide/oops-tracing.rst b/Documentation/admin-guide/oops-tracing.rst index 3e25ea7349ee..13be8d7bcfe7 100644 --- a/Documentation/admin-guide/oops-tracing.rst +++ b/Documentation/admin-guide/oops-tracing.rst @@ -44,7 +44,7 @@ the disk is not available then you have three options : so won't help for 'early' oopses) (2) Boot with a serial console (see - :ref:`Documentation/serial-console.txt `), + :ref:`Documentation/admin-guide/serial-console.rst `), run a null modem to a second machine and capture the output there using your favourite communication program. Minicom works well. diff --git a/Documentation/admin-guide/ramoops.rst b/Documentation/admin-guide/ramoops.rst index 7eaf1e71c083..fe95c027e37c 100644 --- a/Documentation/admin-guide/ramoops.rst +++ b/Documentation/admin-guide/ramoops.rst @@ -61,7 +61,7 @@ Setting the ramoops parameters can be done in several different manners: mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1 B. Use Device Tree bindings, as described in - ``Documentation/device-tree/bindings/reserved-memory/ramoops.txt``. + ``Documentation/device-tree/bindings/reserved-memory/admin-guide/ramoops.rst``. For example:: reserved-memory { diff --git a/Documentation/admin-guide/reporting-bugs.rst b/Documentation/admin-guide/reporting-bugs.rst index 05c53ac7fa76..0c0f2698ec5a 100644 --- a/Documentation/admin-guide/reporting-bugs.rst +++ b/Documentation/admin-guide/reporting-bugs.rst @@ -61,7 +61,7 @@ files to the get_maintainer.pl script:: If it is a security bug, please copy the Security Contact listed in the MAINTAINERS file. They can help coordinate bugfix and disclosure. See -:ref:`Documentation/SecurityBugs ` for more information. +:ref:`Documentation/admin-guide/security-bugs.rst ` for more information. If you can't figure out which subsystem caused the issue, you should file a bug in kernel.org bugzilla and send email to @@ -94,7 +94,7 @@ step-by-step instructions for how a user can trigger the bug. If the failure includes an "OOPS:", take a picture of the screen, capture a netconsole trace, or type the message from your screen into the bug -report. Please read "Documentation/oops-tracing.txt" before posting your +report. Please read "Documentation/admin-guide/oops-tracing.rst" before posting your bug report. This explains what you should do with the "Oops" information to make it useful to the recipient. @@ -120,7 +120,7 @@ summary from [1.]>" for easy identification by the developers:: [4.2.] Kernel .config file: [5.] Most recent kernel version which did not have the bug: [6.] Output of Oops.. message (if applicable) with symbolic information - resolved (see Documentation/oops-tracing.txt) + resolved (see Documentation/admin-guide/oops-tracing.rst) [7.] A small shell script or example program which triggers the problem (if possible) [8.] Environment diff --git a/Documentation/admin-guide/security-bugs.rst b/Documentation/admin-guide/security-bugs.rst index df795e22d08b..4f7414cad586 100644 --- a/Documentation/admin-guide/security-bugs.rst +++ b/Documentation/admin-guide/security-bugs.rst @@ -19,7 +19,7 @@ area maintainers to understand and fix the security vulnerability. As it is with any bug, the more information provided the easier it will be to diagnose and fix. Please review the procedure outlined in -REPORTING-BUGS if you are unclear about what information is helpful. +admin-guide/reporting-bugs.rst if you are unclear about what information is helpful. Any exploit code is very helpful and will not be released without consent from the reporter unless it has already been made public. diff --git a/Documentation/admin-guide/unicode.rst b/Documentation/admin-guide/unicode.rst index 012e8e895842..4e5c3df9d55f 100644 --- a/Documentation/admin-guide/unicode.rst +++ b/Documentation/admin-guide/unicode.rst @@ -7,7 +7,7 @@ This file is maintained by H. Peter Anvin as part of the Linux Assigned Names And Numbers Authority (LANANA) project. The current version can be found at: - http://www.lanana.org/docs/unicode/unicode.txt + http://www.lanana.org/docs/unicode/admin-guide/unicode.rst Introdution ----------- diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting index 83c1df2fc758..259f00af3ab3 100644 --- a/Documentation/arm/Booting +++ b/Documentation/arm/Booting @@ -51,7 +51,7 @@ As an alternative, the boot loader can pass the relevant 'console=' option to the kernel via the tagged lists specifying the port, and serial format options as described in - Documentation/kernel-parameters.txt. + Documentation/admin-guide/kernel-parameters.rst. 3. Detect the machine type diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt index c9d1cacb4395..7281bf939779 100644 --- a/Documentation/atomic_ops.txt +++ b/Documentation/atomic_ops.txt @@ -16,7 +16,7 @@ will fail. Something like the following should suffice: typedef struct { long counter; } atomic_long_t; Historically, counter has been declared volatile. This is now discouraged. -See Documentation/volatile-considered-harmful.txt for the complete rationale. +See Documentation/process/volatile-considered-harmful.rst for the complete rationale. local_t is very similar to atomic_t. If the counter is per CPU and only updated by one CPU, local_t is probably more appropriate. Please see diff --git a/Documentation/blockdev/ramdisk.txt b/Documentation/blockdev/ramdisk.txt index fe2ef978d85a..501e12e0323e 100644 --- a/Documentation/blockdev/ramdisk.txt +++ b/Documentation/blockdev/ramdisk.txt @@ -14,7 +14,7 @@ Contents: The RAM disk driver is a way to use main system memory as a block device. It is required for initrd, an initial filesystem used if you need to load modules -in order to access the root filesystem (see Documentation/initrd.txt). It can +in order to access the root filesystem (see Documentation/admin-guide/initrd.rst). It can also be used for a temporary filesystem for crypto work, since the contents are erased on reboot. diff --git a/Documentation/cgroup-v1/00-INDEX b/Documentation/cgroup-v1/00-INDEX index 106885ad670d..13e0c85e7b35 100644 --- a/Documentation/cgroup-v1/00-INDEX +++ b/Documentation/cgroup-v1/00-INDEX @@ -8,7 +8,7 @@ cpuacct.txt - CPU Accounting Controller; account CPU usage for groups of tasks. cpusets.txt - documents the cpusets feature; assign CPUs and Mem to a set of tasks. -devices.txt +admin-guide/devices.rst - Device Whitelist Controller; description, interface and security. freezer-subsystem.txt - checkpointing; rationale to not use signals, interface. diff --git a/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt b/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt index ddef330d2709..1ad4c1c2b3b3 100644 --- a/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt +++ b/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt @@ -1,7 +1,7 @@ * Maxim DS3231 Real Time Clock Required properties: -see: Documentation/devicetree/bindings/i2c/trivial-devices.txt +see: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst Optional property: - #clock-cells: Should be 1. diff --git a/Documentation/devicetree/bindings/rtc/pcf8563.txt b/Documentation/devicetree/bindings/rtc/pcf8563.txt index 72f6d2c9665e..086c998c5561 100644 --- a/Documentation/devicetree/bindings/rtc/pcf8563.txt +++ b/Documentation/devicetree/bindings/rtc/pcf8563.txt @@ -3,7 +3,7 @@ Philips PCF8563/Epson RTC8564 Real Time Clock Required properties: -see: Documentation/devicetree/bindings/i2c/trivial-devices.txt +see: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst Optional property: - #clock-cells: Should be 0. diff --git a/Documentation/devicetree/bindings/submitting-patches.txt b/Documentation/devicetree/bindings/submitting-patches.txt index 7d44eae7ab0b..274058c583dd 100644 --- a/Documentation/devicetree/bindings/submitting-patches.txt +++ b/Documentation/devicetree/bindings/submitting-patches.txt @@ -3,7 +3,7 @@ I. For patch submitters - 0) Normal patch submission rules from Documentation/SubmittingPatches + 0) Normal patch submission rules from Documentation/process/submitting-patches.rst applies. 1) The Documentation/ portion of the patch should be a separate patch. diff --git a/Documentation/filesystems/locks.txt b/Documentation/filesystems/locks.txt index 2cf81082581d..5368690f412e 100644 --- a/Documentation/filesystems/locks.txt +++ b/Documentation/filesystems/locks.txt @@ -19,7 +19,7 @@ forever. This should not cause problems for anybody, since everybody using a 2.1.x kernel should have updated their C library to a suitable version -anyway (see the file "Documentation/Changes".) +anyway (see the file "Documentation/process/changes.rst".) 1.2 Allow Mixed Locks Again --------------------------- diff --git a/Documentation/filesystems/nfs/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt index 0b2883b17d4c..5efae00f6c7f 100644 --- a/Documentation/filesystems/nfs/nfsroot.txt +++ b/Documentation/filesystems/nfs/nfsroot.txt @@ -11,7 +11,7 @@ Updated 2006 by Horms In order to use a diskless system, such as an X-terminal or printer server for example, it is necessary for the root filesystem to be present on a non-disk device. This may be an initramfs (see Documentation/filesystems/ -ramfs-rootfs-initramfs.txt), a ramdisk (see Documentation/initrd.txt) or a +ramfs-rootfs-initramfs.txt), a ramdisk (see Documentation/admin-guide/initrd.rst) or a filesystem mounted via NFS. The following text describes on how to use NFS for the root filesystem. For the rest of this text 'client' means the diskless system, and 'server' means the NFS server. @@ -284,7 +284,7 @@ They depend on various facilities being available: "kernel ". The nfsroot parameters are passed to the kernel by adding them to the "append" line. It is common to use serial console in conjunction with pxeliunx, - see Documentation/serial-console.txt for more information. + see Documentation/admin-guide/serial-console.rst for more information. For more information on isolinux, including how to create bootdisks for prebuilt kernels, see http://syslinux.zytor.com/ diff --git a/Documentation/frv/booting.txt b/Documentation/frv/booting.txt index 9bdf4b46e741..cd9dc1dfb144 100644 --- a/Documentation/frv/booting.txt +++ b/Documentation/frv/booting.txt @@ -119,7 +119,7 @@ separated by spaces: 253:0 Device with major 253 and minor 0 Authoritative information can be found in - "Documentation/kernel-parameters.txt". + "Documentation/admin-guide/kernel-parameters.rst". (*) rw diff --git a/Documentation/hwmon/submitting-patches b/Documentation/hwmon/submitting-patches index 57f60307accc..f88221b46153 100644 --- a/Documentation/hwmon/submitting-patches +++ b/Documentation/hwmon/submitting-patches @@ -10,10 +10,10 @@ increase the chances of your change being accepted. ---------- * It should be unnecessary to mention, but please read and follow - Documentation/SubmitChecklist - Documentation/SubmittingDrivers - Documentation/SubmittingPatches - Documentation/CodingStyle + Documentation/process/submit-checklist.rst + Documentation/process/submitting-drivers.rst + Documentation/process/submitting-patches.rst + Documentation/process/coding-style.rst * Please run your patch through 'checkpatch --strict'. There should be no errors, no warnings, and few if any check messages. If there are any diff --git a/Documentation/isdn/README b/Documentation/isdn/README index cfb1884342ee..32d4e80c2c03 100644 --- a/Documentation/isdn/README +++ b/Documentation/isdn/README @@ -332,7 +332,7 @@ README for the ISDN-subsystem 4. Device-inodes The major and minor numbers and their names are described in - Documentation/devices.txt. The major numbers are: + Documentation/admin-guide/devices.rst. The major numbers are: 43 for the ISDN-tty's. 44 for the ISDN-callout-tty's. diff --git a/Documentation/ja_JP/HOWTO b/Documentation/ja_JP/HOWTO index 581c14bdd7be..b03fc8047f03 100644 --- a/Documentation/ja_JP/HOWTO +++ b/Documentation/ja_JP/HOWTO @@ -127,15 +127,15 @@ linux-api@ver.kernel.org に送ることを勧めます。 小限のレベルで必要な数々のソフトウェアパッケージの一覧を示してい ます。 - Documentation/CodingStyle + Documentation/process/coding-style.rst これは Linux カーネルのコーディングスタイルと背景にある理由を記述 しています。全ての新しいコードはこのドキュメントにあるガイドライン に従っていることを期待されています。大部分のメンテナはこれらのルー ルに従っているものだけを受け付け、多くの人は正しいスタイルのコード だけをレビューします。 - Documentation/SubmittingPatches - Documentation/SubmittingDrivers + Documentation/process/submitting-patches.rst + Documentation/process/submitting-drivers.rst これらのファイルには、どうやってうまくパッチを作って投稿するかに ついて非常に詳しく書かれており、以下を含みます(これだけに限らない けれども) @@ -153,7 +153,7 @@ linux-api@ver.kernel.org に送ることを勧めます。 "Linux kernel patch submission format" http://linux.yyz.us/patch-format.html - Documentation/stable_api_nonsense.txt + Documentation/process/stable-api-nonsense.rst このファイルはカーネルの中に不変のAPIを持たないことにした意識的な 決断の背景にある理由について書かれています。以下のようなことを含 んでいます- @@ -164,29 +164,29 @@ linux-api@ver.kernel.org に送ることを勧めます。 このドキュメントは Linux 開発の思想を理解するのに非常に重要です。 そして、他のOSでの開発者が Linux に移る時にとても重要です。 - Documentation/SecurityBugs + Documentation/admin-guide/security-bugs.rst もし Linux カーネルでセキュリティ問題を発見したように思ったら、こ のドキュメントのステップに従ってカーネル開発者に連絡し、問題解決を 支援してください。 - Documentation/ManagementStyle + Documentation/process/management-style.rst このドキュメントは Linux カーネルのメンテナ達がどう行動するか、 彼らの手法の背景にある共有されている精神について記述しています。こ れはカーネル開発の初心者なら(もしくは、単に興味があるだけの人でも) 重要です。なぜならこのドキュメントは、カーネルメンテナ達の独特な 行動についての多くの誤解や混乱を解消するからです。 - Documentation/stable_kernel_rules.txt + Documentation/process/stable-kernel-rules.rst このファイルはどのように stable カーネルのリリースが行われるかのルー ルが記述されています。そしてこれらのリリースの中のどこかで変更を取 り入れてもらいたい場合に何をすれば良いかが示されています。 - Documentation/kernel-docs.txt + Documentation/process/kernel-docs.rst   カーネル開発に付随する外部ドキュメントのリストです。もしあなたが 探しているものがカーネル内のドキュメントでみつからなかった場合、 このリストをあたってみてください。 - Documentation/applying-patches.txt + Documentation/process/applying-patches.rst パッチとはなにか、パッチをどうやって様々なカーネルの開発ブランチに 適用するのかについて正確に記述した良い入門書です。 @@ -314,7 +314,7 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー た問題がなければもう少し長くなることもあります。セキュリティ関連の問題 の場合はこれに対してだいたいの場合、すぐにリリースがされます。 -カーネルツリーに入っている、Documentation/stable_kernel_rules.txt ファ +カーネルツリーに入っている、Documentation/process/stable-kernel-rules.rst ファ イルにはどのような種類の変更が -stable ツリーに受け入れ可能か、またリ リースプロセスがどう動くかが記述されています。 @@ -372,7 +372,7 @@ bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを 場所です。ユーザは見つけたバグの全てをこのツールで報告すべきです。 どう kernel bugzilla を使うかの詳細は、以下を参照してください- http://bugzilla.kernel.org/page.cgi?id=faq.html -メインカーネルソースディレクトリにあるファイル REPORTING-BUGS はカーネ +メインカーネルソースディレクトリにあるファイル admin-guide/reporting-bugs.rst はカーネ ルバグらしいものについてどうレポートするかの良いテンプレートであり、問 題の追跡を助けるためにカーネル開発者にとってどんな情報が必要なのかの詳 細が書かれています。 @@ -438,7 +438,7 @@ MAINTAINERS ファイルにリストがありますので参照してくださ メールの先頭でなく、各引用行の間にあなたの言いたいことを追加するべきで す。 -もしパッチをメールに付ける場合は、Documentation/SubmittingPatches に提 +もしパッチをメールに付ける場合は、Documentation/process/submitting-patches.rst に提 示されているように、それは プレーンな可読テキストにすることを忘れない ようにしましょう。カーネル開発者は 添付や圧縮したパッチを扱いたがりま せん- diff --git a/Documentation/ja_JP/SubmitChecklist b/Documentation/ja_JP/SubmitChecklist index cb5507b1ac81..60c7c35ac517 100644 --- a/Documentation/ja_JP/SubmitChecklist +++ b/Documentation/ja_JP/SubmitChecklist @@ -1,5 +1,5 @@ NOTE: -This is a version of Documentation/SubmitChecklist into Japanese. +This is a version of Documentation/process/submit-checklist.rst into Japanese. This document is maintained by Takenori Nagano and the JF Project team . If you find any difference between this document and the original file @@ -14,7 +14,7 @@ to update the original English file first. Last Updated: 2008/07/14 ================================== これは、 -linux-2.6.26/Documentation/SubmitChecklist の和訳です。 +linux-2.6.26/Documentation/process/submit-checklist.rst の和訳です。 翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ > 翻訳日: 2008/07/14 @@ -27,7 +27,7 @@ Linux カーネルパッチ投稿者向けチェックリスト ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本書では、パッチをより素早く取り込んでもらいたい開発者が実践すべき基本的な事柄 -をいくつか紹介します。ここにある全ての事柄は、Documentation/SubmittingPatches +をいくつか紹介します。ここにある全ての事柄は、Documentation/process/submitting-patches.rst などのLinuxカーネルパッチ投稿に際しての心得を補足するものです。 1: 妥当なCONFIGオプションや変更されたCONFIGオプション、つまり =y, =m, =n @@ -84,7 +84,7 @@ Linux カーネルパッチ投稿者向けチェックリスト 必ずドキュメントを追加してください。 17: 新しいブートパラメータを追加した場合には、 - 必ずDocumentation/kernel-parameters.txt に説明を追加してください。 + 必ずDocumentation/admin-guide/kernel-parameters.rst に説明を追加してください。 18: 新しくmoduleにパラメータを追加した場合には、MODULE_PARM_DESC()を 利用して必ずその説明を記述してください。 diff --git a/Documentation/ja_JP/SubmittingPatches b/Documentation/ja_JP/SubmittingPatches index 5d6ae639bfa0..02139656463e 100644 --- a/Documentation/ja_JP/SubmittingPatches +++ b/Documentation/ja_JP/SubmittingPatches @@ -1,5 +1,5 @@ NOTE: -This is a version of Documentation/SubmittingPatches into Japanese. +This is a version of Documentation/process/submitting-patches.rst into Japanese. This document is maintained by Keiichi KII and the JF Project team . If you find any difference between this document and the original file @@ -15,7 +15,7 @@ Last Updated: 2011/06/09 ================================== これは、 -linux-2.6.39/Documentation/SubmittingPatches の和訳 +linux-2.6.39/Documentation/process/submitting-patches.rst の和訳 です。 翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ > 翻訳日: 2011/06/09 @@ -34,9 +34,9 @@ Linux カーネルに変更を加えたいと思っている個人又は会社 おじけづかせることもあります。この文章はあなたの変更を大いに受け入れ てもらえやすくする提案を集めたものです。 -コードを投稿する前に、Documentation/SubmitChecklist の項目リストに目 +コードを投稿する前に、Documentation/process/submit-checklist.rst の項目リストに目 を通してチェックしてください。もしあなたがドライバーを投稿しようとし -ているなら、Documentation/SubmittingDrivers にも目を通してください。 +ているなら、Documentation/process/submitting-drivers.rst にも目を通してください。 -------------------------------------------- セクション1 パッチの作り方と送り方 @@ -148,7 +148,7 @@ http://savannah.nongnu.org/projects/quilt 4) パッチのスタイルチェック あなたのパッチが基本的な( Linux カーネルの)コーディングスタイルに違反し -ていないかをチェックして下さい。その詳細を Documentation/CodingStyle で +ていないかをチェックして下さい。その詳細を Documentation/process/coding-style.rst で 見つけることができます。コーディングスタイルの違反はレビューする人の 時間を無駄にするだけなので、恐らくあなたのパッチは読まれることすらなく 拒否されるでしょう。 @@ -246,7 +246,7 @@ MIME 形式の添付ファイルは Linus に手間を取らせることにな あれば、誰かが MIME 形式のパッチを再送するよう求めるかもしれません。 余計な変更を加えずにあなたのパッチを送信するための電子メールクライアントの設定 -のヒントについては Documentation/email-clients.txt を参照してください。 +のヒントについては Documentation/process/email-clients.rst を参照してください。 8) 電子メールのサイズ @@ -609,7 +609,7 @@ diffstat の結果を生成するために「 git diff -M --stat --summary 」 し例外を適用するには、本当に妥当な理由が不可欠です。あなたは恐らくこの セクションを Linus のコンピュータ・サイエンス101と呼ぶでしょう。 -1) Documentation/CodingStyleを参照 +1) Documentation/process/coding-style.rstを参照 言うまでもなく、あなたのコードがこのコーディングスタイルからあまりに も逸脱していると、レビューやコメントなしに受け取ってもらえないかもし @@ -704,8 +704,8 @@ Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer". NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people! -Kernel Documentation/CodingStyle: - +Kernel Documentation/process/coding-style.rst: + Linus Torvalds's mail on the canonical patch format: diff --git a/Documentation/ja_JP/stable_api_nonsense.txt b/Documentation/ja_JP/stable_api_nonsense.txt index 7653b5cbfed2..a3b40a4bdcfd 100644 --- a/Documentation/ja_JP/stable_api_nonsense.txt +++ b/Documentation/ja_JP/stable_api_nonsense.txt @@ -1,5 +1,5 @@ NOTE: -This is a version of Documentation/stable_api_nonsense.txt into Japanese. +This is a version of Documentation/process/stable-api-nonsense.rst into Japanese. This document is maintained by IKEDA, Munehiro and the JF Project team . If you find any difference between this document and the original file @@ -14,7 +14,7 @@ to update the original English file first. Last Updated: 2007/07/18 ================================== これは、 -linux-2.6.22-rc4/Documentation/stable_api_nonsense.txt の和訳 +linux-2.6.22-rc4/Documentation/process/stable-api-nonsense.rst の和訳 です。 翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ > 翻訳日 : 2007/06/11 diff --git a/Documentation/ja_JP/stable_kernel_rules.txt b/Documentation/ja_JP/stable_kernel_rules.txt index 9dbda9b5d21e..f9249aecba64 100644 --- a/Documentation/ja_JP/stable_kernel_rules.txt +++ b/Documentation/ja_JP/stable_kernel_rules.txt @@ -1,5 +1,5 @@ NOTE: -This is Japanese translated version of "Documentation/stable_kernel_rules.txt". +This is Japanese translated version of "Documentation/process/stable-kernel-rules.rst". This one is maintained by Tsugikazu Shibata and JF Project team . If you find difference with original file or problem in translation, @@ -12,7 +12,7 @@ file at first. ================================== これは、 -linux-2.6.29/Documentation/stable_kernel_rules.txt +linux-2.6.29/Documentation/process/stable-kernel-rules.rst の和訳です。 翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ > @@ -43,7 +43,7 @@ linux-2.6.29/Documentation/stable_kernel_rules.txt "理論的には競合状態になる"ようなものは不可。 - いかなる些細な修正も含めることはできない。(スペルの修正、空白のクリー ンアップなど) - - Documentation/SubmittingPatches の規則に従ったものでなければならない。 + - Documentation/process/submitting-patches.rst の規則に従ったものでなければならない。 - パッチ自体か同等の修正が Linus のツリーに既に存在しなければならない。   Linus のツリーでのコミットID を -stable へのパッチ投稿の際に引用す ること。 diff --git a/Documentation/kernel-per-CPU-kthreads.txt b/Documentation/kernel-per-CPU-kthreads.txt index bbc3a8b8cff4..df31e30b6a02 100644 --- a/Documentation/kernel-per-CPU-kthreads.txt +++ b/Documentation/kernel-per-CPU-kthreads.txt @@ -264,7 +264,7 @@ To reduce its OS jitter, do at least one of the following: kthreads from being created in the first place. 2. Boot with "nosoftlockup=0", which will also prevent these kthreads from being created. Other related watchdog and softlockup boot - parameters may be found in Documentation/kernel-parameters.txt + parameters may be found in Documentation/admin-guide/kernel-parameters.rst and Documentation/watchdog/watchdog-parameters.txt. 3. Echo a zero to /proc/sys/kernel/watchdog to disable the watchdog timer. diff --git a/Documentation/ko_KR/HOWTO b/Documentation/ko_KR/HOWTO index 9a3e65924d54..025252731af5 100644 --- a/Documentation/ko_KR/HOWTO +++ b/Documentation/ko_KR/HOWTO @@ -1,5 +1,5 @@ NOTE: -This is a version of Documentation/HOWTO translated into korean +This is a version of Documentation/process/howto.rst translated into korean This document is maintained by Minchan Kim If you find any difference between this document and the original file or a problem with the translation, please contact the maintainer of this file. @@ -11,7 +11,7 @@ try to update the original English file first. ================================== 이 문서는 -Documentation/HOWTO +Documentation/process/howto.rst 의 한글 번역입니다. 역자: 김민찬 @@ -98,18 +98,18 @@ mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다. 빌드하기 위해 필요한 것을 설명한다. 커널에 입문하는 사람들은 여기서 시작해야 한다. - Documentation/Changes + Documentation/process/changes.rst 이 파일은 커널을 성공적으로 빌드하고 실행시키기 위해 필요한 다양한 소프트웨어 패키지들의 최소 버젼을 나열한다. - Documentation/CodingStyle + Documentation/process/coding-style.rst 이 문서는 리눅스 커널 코딩 스타일과 그렇게 한 몇몇 이유를 설명한다. 모든 새로운 코드는 이 문서에 가이드라인들을 따라야 한다. 대부분의 메인테이너들은 이 규칙을 따르는 패치들만을 받아들일 것이고 많은 사람들이 그 패치가 올바른 스타일일 경우만 코드를 검토할 것이다. - Documentation/SubmittingPatches - Documentation/SubmittingDrivers + Documentation/process/submitting-patches.rst + Documentation/process/submitting-drivers.rst 이 파일들은 성공적으로 패치를 만들고 보내는 법을 다음의 내용들로 굉장히 상세히 설명하고 있다(그러나 다음으로 한정되진 않는다). - Email 내용들 @@ -126,7 +126,7 @@ mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다. "Linux kernel patch submission format" http://linux.yyz.us/patch-format.html - Documentation/stable_api_nonsense.txt + Documentation/process/stable-api-nonsense.rst 이 문서는 의도적으로 커널이 불변하는 API를 갖지 않도록 결정한 이유를 설명하며 다음과 같은 것들을 포함한다. - 서브시스템 shim-layer(호환성을 위해?) @@ -136,12 +136,12 @@ mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다. 리눅스로 전향하는 사람들에게는 매우 중요하다. - Documentation/SecurityBugs + Documentation/admin-guide/security-bugs.rst 여러분들이 리눅스 커널의 보안 문제를 발견했다고 생각한다면 이 문서에 나온 단계에 따라서 커널 개발자들에게 알리고 그 문제를 해결할 수 있도록 도와 달라. - Documentation/ManagementStyle + Documentation/process/management-style.rst 이 문서는 리눅스 커널 메인테이너들이 그들의 방법론에 녹아 있는 정신을 어떻게 공유하고 운영하는지를 설명한다. 이것은 커널 개발에 입문하는 모든 사람들(또는 커널 개발에 작은 호기심이라도 있는 사람들)이 @@ -149,17 +149,17 @@ mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다. 독특한 행동에 관하여 흔히 있는 오해들과 혼란들을 해소하고 있기 때문이다. - Documentation/stable_kernel_rules.txt + Documentation/process/stable-kernel-rules.rst 이 문서는 안정적인 커널 배포가 이루어지는 규칙을 설명하고 있으며 여러분들이 이러한 배포들 중 하나에 변경을 하길 원한다면 무엇을 해야 하는지를 설명한다. - Documentation/kernel-docs.txt + Documentation/process/kernel-docs.rst 커널 개발에 관계된 외부 문서의 리스트이다. 커널 내의 포함된 문서들 중에 여러분이 찾고 싶은 문서를 발견하지 못할 경우 이 리스트를 살펴보라. - Documentation/applying-patches.txt + Documentation/process/applying-patches.rst 패치가 무엇이며 그것을 커널의 다른 개발 브랜치들에 어떻게 적용하는지에 관하여 자세히 설명하고 있는 좋은 입문서이다. @@ -276,7 +276,7 @@ Andrew Morton의 글이 있다. 4.x.y는 "stable" 팀에 의해 관리되며 거의 매번 격주로 배포된다. -커널 트리 문서들 내에 Documentation/stable_kernel_rules.txt 파일은 어떤 +커널 트리 문서들 내에 Documentation/process/stable-kernel-rules.rst 파일은 어떤 종류의 변경들이 -stable 트리로 들어왔는지와 배포 프로세스가 어떻게 진행되는지를 설명한다. @@ -328,7 +328,7 @@ bugzilla.kernel.org는 리눅스 커널 개발자들이 커널의 버그를 추 kernel bugzilla를 사용하는 자세한 방법은 다음을 참조하라. http://test.kernel.org/bugzilla/faq.html -메인 커널 소스 디렉토리에 있는 REPORTING-BUGS 파일은 커널 버그라고 생각되는 +메인 커널 소스 디렉토리에 있는 admin-guide/reporting-bugs.rst 파일은 커널 버그라고 생각되는 것을 보고하는 방법에 관한 좋은 템플릿이며 문제를 추적하기 위해서 커널 개발자들이 필요로 하는 정보가 무엇들인지를 상세히 설명하고 있다. @@ -391,7 +391,7 @@ bugme-janitor 메일링 리스트(bugzilla에 모든 변화들이 여기서 메 "John 커널해커는 작성했다...."를 유지하며 여러분들의 의견을 그 메일의 윗부분에 작성하지 말고 각 인용한 단락들 사이에 넣어라. -여러분들이 패치들을 메일에 넣는다면 그것들은 Documentation/SubmittingPatches에 +여러분들이 패치들을 메일에 넣는다면 그것들은 Documentation/process/submitting-patches.rst에 나와있는데로 명백히(plain) 읽을 수 있는 텍스트여야 한다. 커널 개발자들은 첨부파일이나 압축된 패치들을 원하지 않는다. 그들은 여러분들의 패치의 각 라인 단위로 코멘트를 하길 원하며 압축하거나 첨부하지 않고 보내는 것이 diff --git a/Documentation/ko_KR/stable_api_nonsense.txt b/Documentation/ko_KR/stable_api_nonsense.txt index 3ba10b11d556..4d93af1efd61 100644 --- a/Documentation/ko_KR/stable_api_nonsense.txt +++ b/Documentation/ko_KR/stable_api_nonsense.txt @@ -1,5 +1,5 @@ NOTE: -This is a version of Documentation/stable_api_nonsense.txt translated +This is a version of Documentation/process/stable-api-nonsense.rst translated into korean This document is maintained by Minchan Kim If you find any difference between this document and the original file or @@ -12,7 +12,7 @@ try to update the original English file first. ================================== 이 문서는 -Documentation/stable_api_nonsense.txt +Documentation/process/stable-api-nonsense.rst 의 한글 번역입니다. 역자: 김민찬 diff --git a/Documentation/lockup-watchdogs.txt b/Documentation/lockup-watchdogs.txt index 4a6e33e1af61..c8b8378513d6 100644 --- a/Documentation/lockup-watchdogs.txt +++ b/Documentation/lockup-watchdogs.txt @@ -11,7 +11,7 @@ details), without giving other tasks a chance to run. The current stack trace is displayed upon detection and, by default, the system will stay locked up. Alternatively, the kernel can be configured to panic; a sysctl, "kernel.softlockup_panic", a kernel parameter, -"softlockup_panic" (see "Documentation/kernel-parameters.txt" for +"softlockup_panic" (see "Documentation/admin-guide/kernel-parameters.rst" for details), and a compile option, "BOOTPARAM_SOFTLOCKUP_PANIC", are provided for this. @@ -23,7 +23,7 @@ upon detection and the system will stay locked up unless the default behavior is changed, which can be done through a sysctl, 'hardlockup_panic', a compile time knob, "BOOTPARAM_HARDLOCKUP_PANIC", and a kernel parameter, "nmi_watchdog" -(see "Documentation/kernel-parameters.txt" for details). +(see "Documentation/admin-guide/kernel-parameters.rst" for details). The panic option can be used in combination with panic_timeout (this timeout is set through the confusingly named "kernel.panic" sysctl), diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt index eaf32a1fd0b1..79d21246c75a 100644 --- a/Documentation/m68k/kernel-options.txt +++ b/Documentation/m68k/kernel-options.txt @@ -139,7 +139,7 @@ follows: PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF/PARTNROFF=-2 Authoritative information can be found in -"Documentation/kernel-parameters.txt". +"Documentation/admin-guide/kernel-parameters.rst". 2.2) ro, rw diff --git a/Documentation/media/uapi/v4l/diff-v4l.rst b/Documentation/media/uapi/v4l/diff-v4l.rst index 76b2ecab8657..8209eeb63dd2 100644 --- a/Documentation/media/uapi/v4l/diff-v4l.rst +++ b/Documentation/media/uapi/v4l/diff-v4l.rst @@ -648,12 +648,12 @@ microcode programming. A new interface for MPEG compression and playback devices is documented in :ref:`extended-controls`. .. [#f1] - According to Documentation/devices.txt these should be symbolic links + According to Documentation/admin-guide/devices.rst these should be symbolic links to ``/dev/video0``. Note the original bttv interface is not compatible with V4L or V4L2. .. [#f2] - According to ``Documentation/devices.txt`` a symbolic link to + According to ``Documentation/admin-guide/devices.rst`` a symbolic link to ``/dev/radio0``. .. [#f3] diff --git a/Documentation/media/v4l-drivers/bttv.rst b/Documentation/media/v4l-drivers/bttv.rst index 7abc1c9a261b..bc63b12efafd 100644 --- a/Documentation/media/v4l-drivers/bttv.rst +++ b/Documentation/media/v4l-drivers/bttv.rst @@ -304,10 +304,10 @@ bug. It is very helpful if you can tell where exactly it broke With a hard freeze you probably doesn't find anything in the logfiles. The only way to capture any kernel messages is to hook up a serial console and let some terminal application log the messages. /me uses -screen. See Documentation/serial-console.txt for details on setting +screen. See Documentation/admin-guide/serial-console.rst for details on setting up a serial console. -Read Documentation/oops-tracing.txt to learn how to get any useful +Read Documentation/admin-guide/oops-tracing.rst to learn how to get any useful information out of a register+stack dump printed by the kernel on protection faults (so-called "kernel oops"). diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt index 0d7cb955aa01..5de846d3ecc0 100644 --- a/Documentation/memory-hotplug.txt +++ b/Documentation/memory-hotplug.txt @@ -324,7 +324,7 @@ guarantee that the memory block contains only migratable pages. Now, a boot option for making a memory block which consists of migratable pages is supported. By specifying "kernelcore=" or "movablecore=" boot option, you can create ZONE_MOVABLE...a zone which is just used for movable pages. -(See also Documentation/kernel-parameters.txt) +(See also Documentation/admin-guide/kernel-parameters.rst) Assume the system has "TOTAL" amount of memory at boot time, this boot option creates ZONE_MOVABLE as following. diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt index 30409a36e95d..296ea00fd3eb 100644 --- a/Documentation/networking/netconsole.txt +++ b/Documentation/networking/netconsole.txt @@ -200,7 +200,7 @@ priority messages to the console. You can change this at runtime using: or by specifying "debug" on the kernel command line at boot, to send all kernel messages to the console. A specific value for this parameter can also be set using the "loglevel" kernel boot option. See the -dmesg(8) man page and Documentation/kernel-parameters.txt for details. +dmesg(8) man page and Documentation/admin-guide/kernel-parameters.rst for details. Netconsole was designed to be as instantaneous as possible, to enable the logging of even the most critical kernel bugs. It works diff --git a/Documentation/networking/netdev-FAQ.txt b/Documentation/networking/netdev-FAQ.txt index 0fe1c6e0dbcd..cdebc5c8705f 100644 --- a/Documentation/networking/netdev-FAQ.txt +++ b/Documentation/networking/netdev-FAQ.txt @@ -136,14 +136,14 @@ A: Normally Greg Kroah-Hartman collects stable commits himself, but Q: I see a network patch and I think it should be backported to stable. Should I request it via "stable@vger.kernel.org" like the references in - the kernel's Documentation/stable_kernel_rules.txt file say? + the kernel's Documentation/process/stable-kernel-rules.rst file say? A: No, not for networking. Check the stable queues as per above 1st to see if it is already queued. If not, then send a mail to netdev, listing the upstream commit ID and why you think it should be a stable candidate. Before you jump to go do the above, do note that the normal stable rules - in Documentation/stable_kernel_rules.txt still apply. So you need to + in Documentation/process/stable-kernel-rules.rst still apply. So you need to explicitly indicate why it is a critical fix and exactly what users are impacted. In addition, you need to convince yourself that you _really_ think it has been overlooked, vs. having been considered and rejected. @@ -165,7 +165,7 @@ A: No. See above answer. In short, if you think it really belongs in If you think there is some valid information relating to it being in stable that does _not_ belong in the commit log, then use the three - dash marker line as described in Documentation/SubmittingPatches to + dash marker line as described in Documentation/process/submitting-patches.rst to temporarily embed that information into the patch that you send. Q: Someone said that the comment style and coding convention is different @@ -220,5 +220,5 @@ A: Attention to detail. Re-read your own work as if you were the If it is your first patch, mail it to yourself so you can test apply it to an unpatched tree to confirm infrastructure didn't mangle it. - Finally, go back and read Documentation/SubmittingPatches to be + Finally, go back and read Documentation/process/submitting-patches.rst to be sure you are not repeating some common mistake documented there. diff --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt index 97282da82b75..ad3dead052a4 100644 --- a/Documentation/networking/vortex.txt +++ b/Documentation/networking/vortex.txt @@ -364,7 +364,7 @@ steps you should take: - The contents of your report will vary a lot depending upon the problem. If it's a kernel crash then you should refer to the - REPORTING-BUGS file. + admin-guide/reporting-bugs.rst file. But for most problems it is useful to provide the following: diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX index ad04cc8097ed..7cb6085839f3 100644 --- a/Documentation/power/00-INDEX +++ b/Documentation/power/00-INDEX @@ -6,7 +6,7 @@ basic-pm-debugging.txt - Debugging suspend and resume charger-manager.txt - Battery charger management. -devices.txt +admin-guide/devices.rst - How drivers interact with system-wide power management drivers-testing.txt - Testing suspend and resume support in device drivers diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt index 44558882aa60..85c746cbab2c 100644 --- a/Documentation/power/pci.txt +++ b/Documentation/power/pci.txt @@ -8,7 +8,7 @@ management. Based on previous work by Patrick Mochel This document only covers the aspects of power management specific to PCI devices. For general description of the kernel's interfaces related to device -power management refer to Documentation/power/devices.txt and +power management refer to Documentation/power/admin-guide/devices.rst and Documentation/power/runtime_pm.txt. --------------------------------------------------------------------------- @@ -417,7 +417,7 @@ pm->runtime_idle() callback. 2.4. System-Wide Power Transitions ---------------------------------- There are a few different types of system-wide power transitions, described in -Documentation/power/devices.txt. Each of them requires devices to be handled +Documentation/power/admin-guide/devices.rst. Each of them requires devices to be handled in a specific way and the PM core executes subsystem-level power management callbacks for this purpose. They are executed in phases such that each phase involves executing the same subsystem-level callback for every device belonging @@ -623,7 +623,7 @@ System restore requires a hibernation image to be loaded into memory and the pre-hibernation memory contents to be restored before the pre-hibernation system activity can be resumed. -As described in Documentation/power/devices.txt, the hibernation image is loaded +As described in Documentation/power/admin-guide/devices.rst, the hibernation image is loaded into memory by a fresh instance of the kernel, called the boot kernel, which in turn is loaded and run by a boot loader in the usual way. After the boot kernel has loaded the image, it needs to replace its own code and data with the code @@ -677,7 +677,7 @@ controlling the runtime power management of their devices. At the time of this writing there are two ways to define power management callbacks for a PCI device driver, the recommended one, based on using a -dev_pm_ops structure described in Documentation/power/devices.txt, and the +dev_pm_ops structure described in Documentation/power/admin-guide/devices.rst, and the "legacy" one, in which the .suspend(), .suspend_late(), .resume_early(), and .resume() callbacks from struct pci_driver are used. The legacy approach, however, doesn't allow one to define runtime power management callbacks and is @@ -1046,5 +1046,5 @@ PCI Local Bus Specification, Rev. 3.0 PCI Bus Power Management Interface Specification, Rev. 1.2 Advanced Configuration and Power Interface (ACPI) Specification, Rev. 3.0b PCI Express Base Specification, Rev. 2.0 -Documentation/power/devices.txt +Documentation/power/admin-guide/devices.rst Documentation/power/runtime_pm.txt diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 1fd1fbe9ce95..4870980e967e 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -674,7 +674,7 @@ left in runtime suspend. If that happens, the PM core will not execute any system suspend and resume callbacks for all of those devices, except for the complete callback, which is then entirely responsible for handling the device as appropriate. This only applies to system suspend transitions that are not -related to hibernation (see Documentation/power/devices.txt for more +related to hibernation (see Documentation/power/admin-guide/devices.rst for more information). The PM core does its best to reduce the probability of race conditions between diff --git a/Documentation/power/swsusp-dmcrypt.txt b/Documentation/power/swsusp-dmcrypt.txt index 59931b46ff7e..b802fbfd95ef 100644 --- a/Documentation/power/swsusp-dmcrypt.txt +++ b/Documentation/power/swsusp-dmcrypt.txt @@ -8,7 +8,7 @@ Some prerequisites: You know how dm-crypt works. If not, visit the following web page: http://www.saout.de/misc/dm-crypt/ You have read Documentation/power/swsusp.txt and understand it. -You did read Documentation/initrd.txt and know how an initrd works. +You did read Documentation/admin-guide/initrd.rst and know how an initrd works. You know how to create or how to modify an initrd. Now your system is properly set up, your disk is encrypted except for diff --git a/Documentation/process/4.Coding.rst b/Documentation/process/4.Coding.rst index 9d5cef996f7f..983d628c1112 100644 --- a/Documentation/process/4.Coding.rst +++ b/Documentation/process/4.Coding.rst @@ -22,7 +22,7 @@ Coding style ************ The kernel has long had a standard coding style, described in -Documentation/CodingStyle. For much of that time, the policies described +Documentation/process/coding-style.rst. For much of that time, the policies described in that file were taken as being, at most, advisory. As a result, there is a substantial amount of code in the kernel which does not meet the coding style guidelines. The presence of that code leads to two independent @@ -343,7 +343,7 @@ user-space developers to know what they are working with. See Documentation/ABI/README for a description of how this documentation should be formatted and what information needs to be provided. -The file Documentation/kernel-parameters.txt describes all of the kernel's +The file Documentation/admin-guide/kernel-parameters.rst describes all of the kernel's boot-time parameters. Any patch which adds new parameters should add the appropriate entries to this file. diff --git a/Documentation/process/5.Posting.rst b/Documentation/process/5.Posting.rst index b511ddf7e82a..1b7728b19ea7 100644 --- a/Documentation/process/5.Posting.rst +++ b/Documentation/process/5.Posting.rst @@ -9,8 +9,8 @@ kernel. Unsurprisingly, the kernel development community has evolved a set of conventions and procedures which are used in the posting of patches; following them will make life much easier for everybody involved. This document will attempt to cover these expectations in reasonable detail; -more information can also be found in the files SubmittingPatches, -SubmittingDrivers, and SubmitChecklist in the kernel documentation +more information can also be found in the files process/submitting-patches.rst, +process/submitting-drivers.rst, and process/submit-checklist.rst in the kernel documentation directory. @@ -198,7 +198,7 @@ pass it to diff with the "-X" option. The tags mentioned above are used to describe how various developers have been associated with the development of this patch. They are described in -detail in the SubmittingPatches document; what follows here is a brief +detail in the process/submitting-patches.rst document; what follows here is a brief summary. Each of these lines has the format: :: @@ -210,7 +210,7 @@ The tags in common use are: - Signed-off-by: this is a developer's certification that he or she has the right to submit the patch for inclusion into the kernel. It is an agreement to the Developer's Certificate of Origin, the full text of - which can be found in Documentation/SubmittingPatches. Code without a + which can be found in Documentation/process/submitting-patches.rst. Code without a proper signoff cannot be merged into the mainline. - Acked-by: indicates an agreement by another developer (often a @@ -221,7 +221,7 @@ The tags in common use are: it to work. - Reviewed-by: the named developer has reviewed the patch for correctness; - see the reviewer's statement in Documentation/SubmittingPatches for more + see the reviewer's statement in Documentation/process/submitting-patches.rst for more detail. - Reported-by: names a user who reported a problem which is fixed by this @@ -248,7 +248,7 @@ take care of: be examined in any detail. If there is any doubt at all, mail the patch to yourself and convince yourself that it shows up intact. - Documentation/email-clients.txt has some helpful hints on making + Documentation/process/email-clients.rst has some helpful hints on making specific mail clients work for sending patches. - Are you sure your patch is free of silly mistakes? You should always diff --git a/Documentation/process/8.Conclusion.rst b/Documentation/process/8.Conclusion.rst index 23ec7cbc2d2b..1c7f54cd0261 100644 --- a/Documentation/process/8.Conclusion.rst +++ b/Documentation/process/8.Conclusion.rst @@ -5,9 +5,9 @@ For more information There are numerous sources of information on Linux kernel development and related topics. First among those will always be the Documentation -directory found in the kernel source distribution. The top-level HOWTO -file is an important starting point; SubmittingPatches and -SubmittingDrivers are also something which all kernel developers should +directory found in the kernel source distribution. The top-level process/howto.rst +file is an important starting point; process/submitting-patches.rst and +process/submitting-drivers.rst are also something which all kernel developers should read. Many internal kernel APIs are documented using the kerneldoc mechanism; "make htmldocs" or "make pdfdocs" can be used to generate those documents in HTML or PDF format (though the version of TeX shipped by some diff --git a/Documentation/process/adding-syscalls.rst b/Documentation/process/adding-syscalls.rst index f5b5b1aa51b3..8cc25a06f353 100644 --- a/Documentation/process/adding-syscalls.rst +++ b/Documentation/process/adding-syscalls.rst @@ -3,7 +3,7 @@ Adding a New System Call This document describes what's involved in adding a new system call to the Linux kernel, over and above the normal submission advice in -:ref:`Documentation/SubmittingPatches `. +:ref:`Documentation/process/submitting-patches.rst `. System Call Alternatives diff --git a/Documentation/process/coding-style.rst b/Documentation/process/coding-style.rst index 9c61c039ccd9..968808bec407 100644 --- a/Documentation/process/coding-style.rst +++ b/Documentation/process/coding-style.rst @@ -1058,5 +1058,5 @@ gcc internals and indent, all available from http://www.gnu.org/manual/ WG14 is the international standardization working group for the programming language C, URL: http://www.open-std.org/JTC1/SC22/WG14/ -Kernel CodingStyle, by greg@kroah.com at OLS 2002: +Kernel process/coding-style.rst, by greg@kroah.com at OLS 2002: http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ diff --git a/Documentation/process/howto.rst b/Documentation/process/howto.rst index 5f042349f987..3f66a1980726 100644 --- a/Documentation/process/howto.rst +++ b/Documentation/process/howto.rst @@ -90,19 +90,19 @@ required reading: what is necessary to do to configure and build the kernel. People who are new to the kernel should start here. - :ref:`Documentation/Changes ` + :ref:`Documentation/process/changes.rst ` This file gives a list of the minimum levels of various software packages that are necessary to build and run the kernel successfully. - :ref:`Documentation/CodingStyle ` + :ref:`Documentation/process/coding-style.rst ` This describes the Linux kernel coding style, and some of the rationale behind it. All new code is expected to follow the guidelines in this document. Most maintainers will only accept patches if these rules are followed, and many people will only review code if it is in the proper style. - :ref:`Documentation/SubmittingPatches ` and :ref:`Documentation/SubmittingDrivers ` + :ref:`Documentation/process/submitting-patches.rst ` and :ref:`Documentation/process/submitting-drivers.rst ` These files describe in explicit detail how to successfully create and send a patch, including (but not limited to): @@ -122,7 +122,7 @@ required reading: "Linux kernel patch submission format" http://linux.yyz.us/patch-format.html - :ref:`Documentation/stable_api_nonsense.txt ` + :ref:`Documentation/process/stable-api-nonsense.rst ` This file describes the rationale behind the conscious decision to not have a stable API within the kernel, including things like: @@ -135,29 +135,29 @@ required reading: philosophy and is very important for people moving to Linux from development on other Operating Systems. - :ref:`Documentation/SecurityBugs ` + :ref:`Documentation/admin-guide/security-bugs.rst ` If you feel you have found a security problem in the Linux kernel, please follow the steps in this document to help notify the kernel developers, and help solve the issue. - :ref:`Documentation/ManagementStyle ` + :ref:`Documentation/process/management-style.rst ` This document describes how Linux kernel maintainers operate and the shared ethos behind their methodologies. This is important reading for anyone new to kernel development (or anyone simply curious about it), as it resolves a lot of common misconceptions and confusion about the unique behavior of kernel maintainers. - :ref:`Documentation/stable_kernel_rules.txt ` + :ref:`Documentation/process/stable-kernel-rules.rst ` This file describes the rules on how the stable kernel releases happen, and what to do if you want to get a change into one of these releases. - :ref:`Documentation/kernel-docs.txt ` + :ref:`Documentation/process/kernel-docs.rst ` A list of external documentation that pertains to kernel development. Please consult this list if you do not find what you are looking for within the in-kernel documentation. - :ref:`Documentation/applying-patches.txt ` + :ref:`Documentation/process/applying-patches.rst ` A good introduction describing exactly what a patch is and how to apply it to the different development branches of the kernel. @@ -307,7 +307,7 @@ two weeks, but it can be longer if there are no pressing problems. A security-related problem, instead, can cause a release to happen almost instantly. -The file Documentation/stable_kernel_rules.txt in the kernel tree +The file Documentation/process/stable-kernel-rules.rst in the kernel tree documents what kinds of changes are acceptable for the -stable tree, and how the release process works. @@ -366,7 +366,7 @@ tool. For details on how to use the kernel bugzilla, please see: https://bugzilla.kernel.org/page.cgi?id=faq.html -The file REPORTING-BUGS in the main kernel source directory has a good +The file admin-guide/reporting-bugs.rst in the main kernel source directory has a good template for how to report a possible kernel bug, and details what kind of information is needed by the kernel developers to help track down the problem. @@ -440,7 +440,7 @@ add your statements between the individual quoted sections instead of writing at the top of the mail. If you add patches to your mail, make sure they are plain readable text -as stated in Documentation/SubmittingPatches. +as stated in Documentation/process/submitting-patches.rst. Kernel developers don't want to deal with attachments or compressed patches; they may want to comment on individual lines of your patch, which works only that way. Make sure you diff --git a/Documentation/process/management-style.rst b/Documentation/process/management-style.rst index dea2e66c9a10..45595fd8a66b 100644 --- a/Documentation/process/management-style.rst +++ b/Documentation/process/management-style.rst @@ -5,7 +5,7 @@ Linux kernel management style This is a short document describing the preferred (or made up, depending on who you ask) management style for the linux kernel. It's meant to -mirror the CodingStyle document to some degree, and mainly written to +mirror the process/coding-style.rst document to some degree, and mainly written to avoid answering [#f1]_ the same (or similar) questions over and over again. Management style is very personal and much harder to quantify than diff --git a/Documentation/process/stable-kernel-rules.rst b/Documentation/process/stable-kernel-rules.rst index 4d82e31b7958..11ec2d93a5e0 100644 --- a/Documentation/process/stable-kernel-rules.rst +++ b/Documentation/process/stable-kernel-rules.rst @@ -27,7 +27,7 @@ Rules on what kind of patches are accepted, and which ones are not, into the - It cannot contain any "trivial" fixes in it (spelling changes, whitespace cleanups, etc). - It must follow the - :ref:`Documentation/SubmittingPatches ` + :ref:`Documentation/process/submitting-patches.rst ` rules. - It or an equivalent fix must already exist in Linus' tree (upstream). @@ -40,7 +40,7 @@ Procedure for submitting patches to the -stable tree Documentation/networking/netdev-FAQ.txt - Security patches should not be handled (solely) by the -stable review process but should follow the procedures in - :ref:`Documentation/SecurityBugs `. + :ref:`Documentation/admin-guide/security-bugs.rst `. For all other submissions, choose one of the following procedures ----------------------------------------------------------------- diff --git a/Documentation/process/submit-checklist.rst b/Documentation/process/submit-checklist.rst index 894289b22b15..a0d9d34bfb6d 100644 --- a/Documentation/process/submit-checklist.rst +++ b/Documentation/process/submit-checklist.rst @@ -7,7 +7,7 @@ Here are some basic things that developers should do if they want to see their kernel patch submissions accepted more quickly. These are all above and beyond the documentation that is provided in -:ref:`Documentation/SubmittingPatches ` +:ref:`Documentation/process/submitting-patches.rst ` and elsewhere regarding submitting Linux kernel patches. @@ -31,7 +31,7 @@ and elsewhere regarding submitting Linux kernel patches. tends to use ``unsigned long`` for 64-bit quantities. 5) Check your patch for general style as detailed in - :ref:`Documentation/CodingStyle `. + :ref:`Documentation/process/coding-style.rst `. Check for trivial violations with the patch style checker prior to submission (``scripts/checkpatch.pl``). You should be able to justify all violations that remain in @@ -78,7 +78,7 @@ and elsewhere regarding submitting Linux kernel patches. 16) All new ``/proc`` entries are documented under ``Documentation/`` 17) All new kernel boot parameters are documented in - ``Documentation/kernel-parameters.txt``. + ``Documentation/admin-guide/kernel-parameters.rst``. 18) All new module parameters are documented with ``MODULE_PARM_DESC()`` diff --git a/Documentation/process/submitting-drivers.rst b/Documentation/process/submitting-drivers.rst index 252b77a23fad..0939d018c289 100644 --- a/Documentation/process/submitting-drivers.rst +++ b/Documentation/process/submitting-drivers.rst @@ -8,7 +8,7 @@ various kernel trees. Note that if you are interested in video card drivers you should probably talk to XFree86 (http://www.xfree86.org/) and/or X.Org (http://x.org/) instead. -Also read the Documentation/SubmittingPatches document. +Also read the Documentation/process/submitting-patches.rst document. Allocating Device Numbers @@ -19,7 +19,7 @@ by the Linux assigned name and number authority (currently this is Torben Mathiasen). The site is http://www.lanana.org/. This also deals with allocating numbers for devices that are not going to be submitted to the mainstream kernel. -See Documentation/devices.txt for more information on this. +See Documentation/admin-guide/devices.rst for more information on this. If you don't use assigned numbers then when your device is submitted it will be given an assigned number even if that is different from values you may @@ -73,7 +73,7 @@ Interfaces: Code: Please use the Linux style of code formatting as documented - in :ref:`Documentation/CodingStyle `. + in :ref:`Documentation/process/coding-style.rst `. If you have sections of code that need to be in other formats, for example because they are shared with a windows driver kit and you want to @@ -109,7 +109,7 @@ PM support: anything. For the driver testing instructions see Documentation/power/drivers-testing.txt and for a relatively complete overview of the power management issues related to - drivers see Documentation/power/devices.txt . + drivers see Documentation/power/admin-guide/devices.rst . Control: In general if there is active maintenance of a driver by diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst index 4cc20b2c6df3..b4cf8f375184 100644 --- a/Documentation/process/submitting-patches.rst +++ b/Documentation/process/submitting-patches.rst @@ -11,10 +11,10 @@ can greatly increase the chances of your change being accepted. This document contains a large number of suggestions in a relatively terse format. For detailed information on how the kernel development process works, see :ref:`Documentation/process `. -Also, read :ref:`Documentation/SubmitChecklist ` +Also, read :ref:`Documentation/process/submit-checklist.rst ` for a list of items to check before submitting code. If you are submitting a driver, also read -:ref:`Documentation/SubmittingDrivers `; +:ref:`Documentation/process/submitting-drivers.rst `; for device tree binding patches, read Documentation/devicetree/bindings/submitting-patches.txt. @@ -238,7 +238,7 @@ then only post say 15 or so at a time and wait for review and integration. Check your patch for basic style violations, details of which can be found in -:ref:`Documentation/CodingStyle `. +:ref:`Documentation/process/coding-style.rst `. Failure to do so simply wastes the reviewers time and will get your patch rejected, probably without even being read. @@ -305,7 +305,7 @@ toward the stable maintainers by putting a line like this:: into the sign-off area of your patch (note, NOT an email recipient). You should also read -:ref:`Documentation/stable_kernel_rules.txt ` +:ref:`Documentation/process/stable-kernel-rules.rst ` in addition to this file. Note, however, that some subsystem maintainers want to come to their own @@ -363,7 +363,7 @@ decreasing the likelihood of your MIME-attached change being accepted. Exception: If your mailer is mangling patches then someone may ask you to re-send them using MIME. -See :ref:`Documentation/email-clients.txt ` +See :ref:`Documentation/process/email-clients.rst ` for hints about configuring your e-mail client so that it sends your patches untouched. @@ -828,8 +828,8 @@ Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer". NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people! -Kernel Documentation/CodingStyle: - :ref:`Documentation/CodingStyle ` +Kernel Documentation/process/coding-style.rst: + :ref:`Documentation/process/coding-style.rst ` Linus Torvalds's mail on the canonical patch format: diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index 1f0c27049340..8c174063b3f0 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt @@ -26,7 +26,7 @@ whether they can be changed or not: the system software. The rfkill subsystem has two parameters, rfkill.default_state and -rfkill.master_switch_mode, which are documented in kernel-parameters.txt. +rfkill.master_switch_mode, which are documented in admin-guide/kernel-parameters.rst. 2. Implementation details diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 8e66dafa41e1..8477655c0e46 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -1,7 +1,7 @@ SCSI Kernel Parameters ~~~~~~~~~~~~~~~~~~~~~~ -See Documentation/kernel-parameters.txt for general information on +See Documentation/admin-guide/kernel-parameters.rst for general information on specifying module parameters. This document may not be entirely up to date and comprehensive. The command diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index 255075157511..6338400eed73 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -336,7 +336,7 @@ in parallel by these functions. Conventions =========== First, Linus Torvalds's thoughts on C coding style can be found in the -Documentation/CodingStyle file. +Documentation/process/coding-style.rst file. Next, there is a movement to "outlaw" typedefs introducing synonyms for struct tags. Both can be still found in the SCSI subsystem, but diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt index 6af8f7a7770f..d28186553fb0 100644 --- a/Documentation/scsi/sym53c8xx_2.txt +++ b/Documentation/scsi/sym53c8xx_2.txt @@ -427,7 +427,7 @@ Synchronous transfers frequency (default answer: 80) 10.1 Syntax Setup commands can be passed to the driver either at boot time or as -parameters to modprobe, as described in Documentation/kernel-parameters.txt +parameters to modprobe, as described in Documentation/admin-guide/kernel-parameters.rst Example of boot setup command under lilo prompt: diff --git a/Documentation/sound/alsa/alsa-parameters.txt b/Documentation/sound/alsa/alsa-parameters.txt index 0fa40679b080..72eced86f035 100644 --- a/Documentation/sound/alsa/alsa-parameters.txt +++ b/Documentation/sound/alsa/alsa-parameters.txt @@ -1,7 +1,7 @@ ALSA Kernel Parameters ~~~~~~~~~~~~~~~~~~~~~~ -See Documentation/kernel-parameters.txt for general information on +See Documentation/admin-guide/kernel-parameters.rst for general information on specifying module parameters. This document may not be entirely up to date and comprehensive. The command diff --git a/Documentation/sound/oss/oss-parameters.txt b/Documentation/sound/oss/oss-parameters.txt index 3ab391e7c295..cc675f25eee4 100644 --- a/Documentation/sound/oss/oss-parameters.txt +++ b/Documentation/sound/oss/oss-parameters.txt @@ -1,7 +1,7 @@ OSS Kernel Parameters ~~~~~~~~~~~~~~~~~~~~~ -See Documentation/kernel-parameters.txt for general information on +See Documentation/admin-guide/kernel-parameters.rst for general information on specifying module parameters. This document may not be entirely up to date and comprehensive. The command diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index ffab8b5caa60..6bb78f872929 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -71,7 +71,7 @@ show up in /proc/sys/kernel: - printk_ratelimit_burst - pty ==> Documentation/filesystems/devpts.txt - randomize_va_space -- real-root-dev ==> Documentation/initrd.txt +- real-root-dev ==> Documentation/admin-guide/initrd.rst - reboot-cmd [ SPARC only ] - rtsig-max - rtsig-nr @@ -453,7 +453,7 @@ in a KVM virtual machine. This default can be overridden by adding nmi_watchdog=1 -to the guest kernel command line (see Documentation/kernel-parameters.txt). +to the guest kernel command line (see Documentation/admin-guide/kernel-parameters.rst). ============================================================== diff --git a/Documentation/virtual/kvm/review-checklist.txt b/Documentation/virtual/kvm/review-checklist.txt index a850986ed684..a83b27635fdd 100644 --- a/Documentation/virtual/kvm/review-checklist.txt +++ b/Documentation/virtual/kvm/review-checklist.txt @@ -1,8 +1,8 @@ Review checklist for kvm patches ================================ -1. The patch must follow Documentation/CodingStyle and - Documentation/SubmittingPatches. +1. The patch must follow Documentation/process/coding-style.rst and + Documentation/process/submitting-patches.rst. 2. Patches should be against kvm.git master branch. diff --git a/Documentation/vm/numa b/Documentation/vm/numa index e0b58c0e6b49..a08f71647714 100644 --- a/Documentation/vm/numa +++ b/Documentation/vm/numa @@ -82,7 +82,7 @@ such as DMA or DMA32, represent relatively scarce resources. Linux chooses a default zonelist order based on the sizes of the various zone types relative to the total memory of the node and the total memory of the system. The default zonelist order may be overridden using the numa_zonelist_order kernel -boot parameter or sysctl. [see Documentation/kernel-parameters.txt and +boot parameter or sysctl. [see Documentation/admin-guide/kernel-parameters.rst and Documentation/sysctl/vm.txt] By default, Linux will attempt to satisfy memory allocation requests from the diff --git a/Documentation/watchdog/convert_drivers_to_kernel_api.txt b/Documentation/watchdog/convert_drivers_to_kernel_api.txt index 271b8850dde7..9fffb2958d13 100644 --- a/Documentation/watchdog/convert_drivers_to_kernel_api.txt +++ b/Documentation/watchdog/convert_drivers_to_kernel_api.txt @@ -213,6 +213,6 @@ The entry for the driver now needs to select WATCHDOG_CORE: Create a patch and send it to upstream -------------------------------------- -Make sure you understood Documentation/SubmittingPatches and send your patch to +Make sure you understood Documentation/process/submitting-patches.rst and send your patch to linux-watchdog@vger.kernel.org. We are looking forward to it :) diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt index a8d364227a77..e21850e270a0 100644 --- a/Documentation/watchdog/watchdog-parameters.txt +++ b/Documentation/watchdog/watchdog-parameters.txt @@ -4,7 +4,7 @@ be listed here unless the driver has its own driver-specific information file. -See Documentation/kernel-parameters.txt for information on +See Documentation/admin-guide/kernel-parameters.rst for information on providing kernel parameters for builtin drivers versus loadable modules. diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 9da6f3512249..5e9b826b5f62 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -921,7 +921,7 @@ They should normally not be deleted from the kernel command line even though not all of them are actually meaningful to the kernel. Boot loader authors who need additional command line options for the boot loader itself should get them registered in -Documentation/kernel-parameters.txt to make sure they will not +Documentation/admin-guide/kernel-parameters.rst to make sure they will not conflict with actual kernel options now or in the future. vga= diff --git a/Documentation/zh_CN/CodingStyle b/Documentation/zh_CN/CodingStyle index 12717791baac..b02738042799 100644 --- a/Documentation/zh_CN/CodingStyle +++ b/Documentation/zh_CN/CodingStyle @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/CodingStyle +Chinese translated version of Documentation/process/coding-style.rst If you have any comment or update to the content, please post to LKML directly. However, if you have problem communicating in English you can also ask the @@ -7,7 +7,7 @@ translation is outdated or there is problem with translation. Chinese maintainer: Zhang Le --------------------------------------------------------------------- -Documentation/CodingStyle的中文翻译 +Documentation/process/coding-style.rst的中文翻译 如果想评论或更新本文的内容,请直接发信到LKML。如果你使用英文交流有困难的话,也可 以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者。 @@ -809,5 +809,5 @@ GNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent, WG14是C语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/ -Kernel CodingStyle,作者 greg@kroah.com 发表于OLS 2002: +Kernel process/coding-style.rst,作者 greg@kroah.com 发表于OLS 2002: http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ diff --git a/Documentation/zh_CN/HOWTO b/Documentation/zh_CN/HOWTO index f0613b92e0be..11be075ba5fa 100644 --- a/Documentation/zh_CN/HOWTO +++ b/Documentation/zh_CN/HOWTO @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/HOWTO +Chinese translated version of Documentation/process/howto.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -9,7 +9,7 @@ or if there is a problem with the translation. Maintainer: Greg Kroah-Hartman Chinese maintainer: Li Yang --------------------------------------------------------------------- -Documentation/HOWTO 的中文翻译 +Documentation/process/howto.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 @@ -93,16 +93,16 @@ Linux内核代码中包含有大量的文档。这些文档对于学习如何与 文件简要介绍了Linux内核的背景,并且描述了如何配置和编译内核。内核的 新用户应该从这里开始。 - Documentation/Changes + Documentation/process/changes.rst 文件给出了用来编译和使用内核所需要的最小软件包列表。 - Documentation/CodingStyle + Documentation/process/coding-style.rst 描述Linux内核的代码风格和理由。所有新代码需要遵守这篇文档中定义的规 范。大多数维护者只会接收符合规定的补丁,很多人也只会帮忙检查符合风格 的代码。 - Documentation/SubmittingPatches - Documentation/SubmittingDrivers + Documentation/process/submitting-patches.rst + Documentation/process/submitting-drivers.rst 这两份文档明确描述如何创建和发送补丁,其中包括(但不仅限于): - 邮件内容 - 邮件格式 @@ -116,7 +116,7 @@ Linux内核代码中包含有大量的文档。这些文档对于学习如何与 "Linux kernel patch submission format" http://linux.yyz.us/patch-format.html - Documentation/stable_api_nonsense.txt + Documentation/process/stable-api-nonsense.rst 论证内核为什么特意不包括稳定的内核内部API,也就是说不包括像这样的特 性: - 子系统中间层(为了兼容性?) @@ -125,23 +125,23 @@ Linux内核代码中包含有大量的文档。这些文档对于学习如何与 这篇文档对于理解Linux的开发哲学至关重要。对于将开发平台从其他操作系 统转移到Linux的人来说也很重要。 - Documentation/SecurityBugs + Documentation/admin-guide/security-bugs.rst 如果你认为自己发现了Linux内核的安全性问题,请根据这篇文档中的步骤来 提醒其他内核开发者并帮助解决这个问题。 - Documentation/ManagementStyle + Documentation/process/management-style.rst 描述内核维护者的工作方法及其共有特点。这对于刚刚接触内核开发(或者对 它感到好奇)的人来说很重要,因为它解释了很多对于内核维护者独特行为的 普遍误解与迷惑。 - Documentation/stable_kernel_rules.txt + Documentation/process/stable-kernel-rules.rst 解释了稳定版内核发布的规则,以及如何将改动放入这些版本的步骤。 - Documentation/kernel-docs.txt + Documentation/process/kernel-docs.rst 有助于内核开发的外部文档列表。如果你在内核自带的文档中没有找到你想找 的内容,可以查看这些文档。 - Documentation/applying-patches.txt + Documentation/process/applying-patches.rst 关于补丁是什么以及如何将它打在不同内核开发分支上的好介绍 内核还拥有大量从代码自动生成的文档。它包含内核内部API的全面介绍以及如何 @@ -238,7 +238,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循 2.6.x.y版本由“稳定版”小组(邮件地址)维护,一般隔周发 布新版本。 -内核源码中的Documentation/stable_kernel_rules.txt文件具体描述了可被稳定 +内核源码中的Documentation/process/stable-kernel-rules.rst文件具体描述了可被稳定 版内核接受的修改类型以及发布的流程。 @@ -329,7 +329,7 @@ bugzilla.kernel.org是Linux内核开发者们用来跟踪内核Bug的网站。 户在这个工具中报告找到的所有bug。如何使用内核bugzilla的细节请访问: http://test.kernel.org/bugzilla/faq.html -内核源码主目录中的REPORTING-BUGS文件里有一个很好的模板。它指导用户如何报 +内核源码主目录中的admin-guide/reporting-bugs.rst文件里有一个很好的模板。它指导用户如何报 告可能的内核bug以及需要提供哪些信息来帮助内核开发者们找到问题的根源。 @@ -380,7 +380,7 @@ MAINTAINERS文件中可以找到不同话题对应的邮件列表。 这几行。将你的评论加在被引用的段落之间而不要放在邮件的顶部。 如果你在邮件中附带补丁,请确认它们是可以直接阅读的纯文本(如 -Documentation/SubmittingPatches文档中所述)。内核开发者们不希望遇到附件 +Documentation/process/submitting-patches.rst文档中所述)。内核开发者们不希望遇到附件 或者被压缩了的补丁。只有这样才能保证他们可以直接评论你的每行代码。请确保 你使用的邮件发送程序不会修改空格和制表符。一个防范性的测试方法是先将邮件 发送给自己,然后自己尝试是否可以顺利地打上收到的补丁。如果测试不成功,请 diff --git a/Documentation/zh_CN/SecurityBugs b/Documentation/zh_CN/SecurityBugs index d21eb07fe943..2d0fffd122ce 100644 --- a/Documentation/zh_CN/SecurityBugs +++ b/Documentation/zh_CN/SecurityBugs @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/SecurityBugs +Chinese translated version of Documentation/admin-guide/security-bugs.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -8,7 +8,7 @@ or if there is a problem with the translation. Chinese maintainer: Harry Wei --------------------------------------------------------------------- -Documentation/SecurityBugs 的中文翻译 +Documentation/admin-guide/security-bugs.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 @@ -31,7 +31,7 @@ linux内核安全团队可以通过email来联系。这是 一组独立的安全工作人员,可以帮助改善漏洞报告并且公布和取消一个修复。安 全团队有可能会从部分的维护者那里引进额外的帮助来了解并且修复安全漏洞。 当遇到任何漏洞,所能提供的信息越多就越能诊断和修复。如果你不清楚什么 -是有帮助的信息,那就请重温一下REPORTING-BUGS文件中的概述过程。任 +是有帮助的信息,那就请重温一下admin-guide/reporting-bugs.rst文件中的概述过程。任 何攻击性的代码都是非常有用的,未经报告者的同意不会被取消,除非它已经 被公布于众。 diff --git a/Documentation/zh_CN/SubmittingDrivers b/Documentation/zh_CN/SubmittingDrivers index d313f5d8448d..929385e4b194 100644 --- a/Documentation/zh_CN/SubmittingDrivers +++ b/Documentation/zh_CN/SubmittingDrivers @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/SubmittingDrivers +Chinese translated version of Documentation/process/submitting-drivers.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -8,7 +8,7 @@ or if there is a problem with the translation. Chinese maintainer: Li Yang --------------------------------------------------------------------- -Documentation/SubmittingDrivers 的中文翻译 +Documentation/process/submitting-drivers.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 @@ -30,7 +30,7 @@ Documentation/SubmittingDrivers 的中文翻译 兴趣的是显卡驱动程序,你也许应该访问 XFree86 项目(http://www.xfree86.org/) 和/或 X.org 项目 (http://x.org)。 -另请参阅 Documentation/SubmittingPatches 文档。 +另请参阅 Documentation/process/submitting-patches.rst 文档。 分配设备号 @@ -39,7 +39,7 @@ Documentation/SubmittingDrivers 的中文翻译 块设备和字符设备的主设备号与从设备号是由 Linux 命名编号分配权威 LANANA( 现在是 Torben Mathiasen)负责分配。申请的网址是 http://www.lanana.org/。 即使不准备提交到主流内核的设备驱动也需要在这里分配设备号。有关详细信息, -请参阅 Documentation/devices.txt。 +请参阅 Documentation/admin-guide/devices.rst。 如果你使用的不是已经分配的设备号,那么当你提交设备驱动的时候,它将会被强 制分配一个新的设备号,即便这个设备号和你之前发给客户的截然不同。 @@ -81,7 +81,7 @@ Linux 2.6: 如果你需要一个 Linux 和 NT 的通用驱动接口,那么请在用 户空间实现它。 -代码: 请使用 Documentation/CodingStyle 中所描述的 Linux 代码风 +代码: 请使用 Documentation/process/coding-style.rst 中所描述的 Linux 代码风 格。如果你的某些代码段(例如那些与 Windows 驱动程序包共 享的代码段)需要使用其他格式,而你却只希望维护一份代码, 那么请将它们很好地区分出来,并且注明原因。 @@ -107,7 +107,7 @@ Linux 2.6: 程序测试的指导,请参阅 Documentation/power/drivers-testing.txt。有关驱动程序电 源管理问题相对全面的概述,请参阅 - Documentation/power/devices.txt。 + Documentation/power/admin-guide/devices.rst。 管理: 如果一个驱动程序的作者还在进行有效的维护,那么通常除了那 些明显正确且不需要任何检查的补丁以外,其他所有的补丁都会 diff --git a/Documentation/zh_CN/SubmittingPatches b/Documentation/zh_CN/SubmittingPatches index 1d3a10f8746b..e9098da8f1a4 100644 --- a/Documentation/zh_CN/SubmittingPatches +++ b/Documentation/zh_CN/SubmittingPatches @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/SubmittingPatches +Chinese translated version of Documentation/process/submitting-patches.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -8,7 +8,7 @@ or if there is a problem with the translation. Chinese maintainer: TripleX Chung --------------------------------------------------------------------- -Documentation/SubmittingPatches 的中文翻译 +Documentation/process/submitting-patches.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 @@ -30,9 +30,9 @@ Documentation/SubmittingPatches 的中文翻译 对于想要将改动提交到 Linux 内核的个人或者公司来说,如果不熟悉“规矩”, 提交的流程会让人畏惧。本文档收集了一系列建议,这些建议可以大大的提高你 的改动被接受的机会。 -阅读 Documentation/SubmitChecklist 来获得在提交代码前需要检查的项目的列 +阅读 Documentation/process/submit-checklist.rst 来获得在提交代码前需要检查的项目的列 表。如果你在提交一个驱动程序,那么同时阅读一下 -Documentation/SubmittingDrivers 。 +Documentation/process/submitting-drivers.rst 。 -------------------------- @@ -338,7 +338,7 @@ e-mail 标题中的“一句话概述”扼要的描述 e-mail 中的补丁。 本节包含很多和提交到内核的代码有关的通常的"规则"。事情永远有例外...但是 你必须真的有好的理由这样做。你可以把本节叫做Linus的计算机科学入门课。 -1) 读 Document/CodingStyle +1) 读 Document/process/coding-style.rst Nuff 说过,如果你的代码和这个偏离太多,那么它有可能会被拒绝,没有更多的 审查,没有更多的评价。 @@ -404,8 +404,8 @@ Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer". NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people! -Kernel Documentation/CodingStyle: - +Kernel Documentation/process/coding-style.rst: + Linus Torvalds's mail on the canonical patch format: diff --git a/Documentation/zh_CN/arm/Booting b/Documentation/zh_CN/arm/Booting index 6158a64df80c..1fe866f8218f 100644 --- a/Documentation/zh_CN/arm/Booting +++ b/Documentation/zh_CN/arm/Booting @@ -68,7 +68,7 @@ RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何 作为替代方案,引导加载程序也可以通过标签列表传递相关的'console=' 选项给内核以指定某个串口,而串口数据格式的选项在以下文档中描述: - Documentation/kernel-parameters.txt。 + Documentation/admin-guide/kernel-parameters.rst。 3、检测机器类型 diff --git a/Documentation/zh_CN/email-clients.txt b/Documentation/zh_CN/email-clients.txt index b9a1a3e6c78d..ec31d97e8d0e 100644 --- a/Documentation/zh_CN/email-clients.txt +++ b/Documentation/zh_CN/email-clients.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/email-clients.txt +Chinese translated version of Documentation/process/email-clients.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -8,7 +8,7 @@ or if there is a problem with the translation. Chinese maintainer: Harry Wei --------------------------------------------------------------------- -Documentation/email-clients.txt 的中文翻译 +Documentation/process/email-clients.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/zh_CN/oops-tracing.txt b/Documentation/zh_CN/oops-tracing.txt index 9312608ffb8d..41ab53cc0e83 100644 --- a/Documentation/zh_CN/oops-tracing.txt +++ b/Documentation/zh_CN/oops-tracing.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/oops-tracing.txt +Chinese translated version of Documentation/admin-guide/oops-tracing.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -8,7 +8,7 @@ or if there is a problem with the translation. Chinese maintainer: Dave Young --------------------------------------------------------------------- -Documentation/oops-tracing.txt 的中文翻译 +Documentation/admin-guide/oops-tracing.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 @@ -50,7 +50,7 @@ cat /proc/kmsg > file, 然而你必须介入中止传输, kmsg是一个“ 息滚动到了终端的上面,你会发现以高分辩率启动(比如,vga=791)会让你读到更多的文 本。(注意:这需要vesafb,所以对‘早期’的oops没有帮助) -(2)用串口终端启动(请参看Documentation/serial-console.txt),运行一个null +(2)用串口终端启动(请参看Documentation/admin-guide/serial-console.rst),运行一个null modem到另一台机器并用你喜欢的通讯工具获取输出。Minicom工作地很好。 (3)使用Kdump(请参看Documentation/kdump/kdump.txt), diff --git a/Documentation/zh_CN/stable_api_nonsense.txt b/Documentation/zh_CN/stable_api_nonsense.txt index c26a27d1ee7d..a2b27fab382c 100644 --- a/Documentation/zh_CN/stable_api_nonsense.txt +++ b/Documentation/zh_CN/stable_api_nonsense.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/stable_api_nonsense.txt +Chinese translated version of Documentation/process/stable-api-nonsense.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have problem @@ -9,7 +9,7 @@ is problem with translation. Maintainer: Greg Kroah-Hartman Chinese maintainer: TripleX Chung --------------------------------------------------------------------- -Documentation/stable_api_nonsense.txt 的中文翻译 +Documentation/process/stable-api-nonsense.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/zh_CN/stable_kernel_rules.txt b/Documentation/zh_CN/stable_kernel_rules.txt index 26ea5ed7cd9c..db4ba5a0c39a 100644 --- a/Documentation/zh_CN/stable_kernel_rules.txt +++ b/Documentation/zh_CN/stable_kernel_rules.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/stable_kernel_rules.txt +Chinese translated version of Documentation/process/stable-kernel-rules.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -8,7 +8,7 @@ or if there is a problem with the translation. Chinese maintainer: TripleX Chung --------------------------------------------------------------------- -Documentation/stable_kernel_rules.txt 的中文翻译 +Documentation/process/stable-kernel-rules.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 @@ -38,7 +38,7 @@ Documentation/stable_kernel_rules.txt 的中文翻译 - 没有“理论上的竞争条件”,除非能给出竞争条件如何被利用的解释。 - 不能存在任何的“琐碎的”修正(拼写修正,去掉多余空格之类的)。 - 必须被相关子系统的维护者接受。 - - 必须遵循Documentation/SubmittingPatches里的规则。 + - 必须遵循Documentation/process/submitting-patches.rst里的规则。 向稳定版代码树提交补丁的过程: diff --git a/Documentation/zh_CN/volatile-considered-harmful.txt b/Documentation/zh_CN/volatile-considered-harmful.txt index ba8149d2233a..475125967197 100644 --- a/Documentation/zh_CN/volatile-considered-harmful.txt +++ b/Documentation/zh_CN/volatile-considered-harmful.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/volatile-considered-harmful.txt +Chinese translated version of Documentation/process/volatile-considered-harmful.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -9,7 +9,7 @@ or if there is a problem with the translation. Maintainer: Jonathan Corbet Chinese maintainer: Bryan Wu --------------------------------------------------------------------- -Documentation/volatile-considered-harmful.txt 的中文翻译 +Documentation/process/volatile-considered-harmful.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/MAINTAINERS b/MAINTAINERS index de0451df542f..69820b75b2e0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -35,13 +35,13 @@ trivial patch so apply some common sense. PLEASE check your patch with the automated style checker (scripts/checkpatch.pl) to catch trivial style violations. - See Documentation/CodingStyle for guidance here. + See Documentation/process/coding-style.rst for guidance here. PLEASE CC: the maintainers and mailing lists that are generated by scripts/get_maintainer.pl. The results returned by the script will be best if you have git installed and are making your changes in a branch derived from Linus' latest git tree. - See Documentation/SubmittingPatches for details. + See Documentation/process/submitting-patches.rst for details. PLEASE try to include any credit lines you want added with the patch. It avoids people being missed off by mistake and makes @@ -54,7 +54,7 @@ trivial patch so apply some common sense. of the Linux Foundation certificate of contribution and should include a Signed-off-by: line. The current version of this "Developer's Certificate of Origin" (DCO) is listed in the file - Documentation/SubmittingPatches. + Documentation/process/submitting-patches.rst. 6. Make sure you have the right to send any changes you make. If you do changes at work you may find your employer owns the patch @@ -2924,7 +2924,7 @@ CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVER M: Kevin Tsai S: Maintained F: drivers/iio/light/cm* -F: Documentation/devicetree/bindings/i2c/trivial-devices.txt +F: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst CAVIUM I2C DRIVER M: Jan Glauber @@ -11438,7 +11438,7 @@ STABLE BRANCH M: Greg Kroah-Hartman L: stable@vger.kernel.org S: Supported -F: Documentation/stable_kernel_rules.txt +F: Documentation/process/stable-kernel-rules.rst STAGING SUBSYSTEM M: Greg Kroah-Hartman diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bada636d1065..19d237b0737d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1525,7 +1525,7 @@ config X86_CHECK_BIOS_CORRUPTION line. By default it scans the low 64k of memory every 60 seconds; see the memory_corruption_check_size and memory_corruption_check_period parameters in - Documentation/kernel-parameters.txt to adjust this. + Documentation/admin-guide/kernel-parameters.rst to adjust this. When enabled with the default parameters, this option has almost no overhead, as it reserves a relatively small amount diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 535e7828445a..c5f9cbe0ae21 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -342,7 +342,7 @@ config ACPI_DEBUG Use the acpi.debug_layer and acpi.debug_level kernel command-line parameters documented in Documentation/acpi/debug.txt and - Documentation/kernel-parameters.txt to control the type and + Documentation/admin-guide/kernel-parameters.rst to control the type and amount of debug output. config ACPI_PCI_SLOT diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 223a770f78f3..59ce0dd50701 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -129,7 +129,7 @@ static int ata_force_tbl_size; static char ata_force_param_buf[PAGE_SIZE] __initdata; /* param_buf is thrown away after initialization, disallow read */ module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0); -MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)"); +MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/admin-guide/kernel-parameters.rst for details)"); static int atapi_enabled = 1; module_param(atapi_enabled, int, 0444); diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index c115217c79ae..e051fc8aa7d7 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -14,7 +14,7 @@ * (C) 2000,2001,2002,2003,2004 Omnikey AG * * (C) 2005-2006 Harald Welte - * - Adhere to Kernel CodingStyle + * - Adhere to Kernel process/coding-style.rst * - Port to 2.6.13 "new" style PCMCIA * - Check for copy_{from,to}_user return values * - Use nonseekable_open() @@ -151,7 +151,7 @@ static struct pcmcia_device *dev_table[CM4000_MAX_DEV]; static struct class *cmm_class; /* This table doesn't use spaces after the comma between fields and thus - * violates CodingStyle. However, I don't really think wrapping it around will + * violates process/coding-style.rst. However, I don't really think wrapping it around will * make it any clearer to read -HW */ static unsigned char fi_di_table[10][14] = { /*FI 00 01 02 03 04 05 06 07 08 09 10 11 12 13 */ diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index db9538d4b358..a7be12d9a139 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -15,7 +15,7 @@ * See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the * sysfs interface. * - * See "Documentation/kernel-parameters.txt" for information on the module + * See "Documentation/admin-guide/kernel-parameters.rst" for information on the module * parameters. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig index 8b2b740d6679..b20ce7da1ee4 100644 --- a/drivers/nvdimm/Kconfig +++ b/drivers/nvdimm/Kconfig @@ -28,7 +28,7 @@ config BLK_DEV_PMEM non-standard OEM-specific E820 memory type (type-12, see CONFIG_X86_PMEM_LEGACY), or it is manually specified by the 'memmap=nn[KMG]!ss[KMG]' kernel command line (see - Documentation/kernel-parameters.txt). This driver converts + Documentation/admin-guide/kernel-parameters.rst). This driver converts these persistent memory ranges into block devices that are capable of DAX (direct-access) file system mappings. See Documentation/nvdimm/nvdimm.txt for more details. diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index 5dd430f8f921..d84dffb894f4 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -47,7 +47,7 @@ static const char driver_name[] = "vme_user"; static int bus[VME_USER_BUS_MAX]; static unsigned int bus_num; -/* Currently Documentation/devices.txt defines the following for VME: +/* Currently Documentation/admin-guide/devices.rst defines the following for VME: * * 221 char VME bus * 0 = /dev/bus/vme/m0 First master image diff --git a/drivers/video/fbdev/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c index f948baa16d82..e219a0a22077 100644 --- a/drivers/video/fbdev/skeletonfb.c +++ b/drivers/video/fbdev/skeletonfb.c @@ -836,7 +836,7 @@ static void xxxfb_remove(struct pci_dev *dev) * @dev: PCI device * @msg: the suspend event code. * - * See Documentation/power/devices.txt for more information + * See Documentation/power/admin-guide/devices.rst for more information */ static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg) { @@ -851,7 +851,7 @@ static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg) * xxxfb_resume - Optional but recommended function. Resume the device. * @dev: PCI device * - * See Documentation/power/devices.txt for more information + * See Documentation/power/admin-guide/devices.rst for more information */ static int xxxfb_resume(struct pci_dev *dev) { @@ -915,7 +915,7 @@ static void __exit xxxfb_exit(void) * @dev: platform device * @msg: the suspend event code. * - * See Documentation/power/devices.txt for more information + * See Documentation/power/admin-guide/devices.rst for more information */ static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg) { @@ -930,7 +930,7 @@ static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg) * xxxfb_resume - Optional but recommended function. Resume the device. * @dev: platform device * - * See Documentation/power/devices.txt for more information + * See Documentation/power/admin-guide/devices.rst for more information */ static int xxxfb_resume(struct platform_dev *dev) { diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 77590320d44c..623f72334fa5 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -75,7 +75,7 @@ config VIRTIO_MMIO_CMDLINE_DEVICES Allow virtio-mmio devices instantiation via the kernel command line or module parameters. Be aware that using incorrect parameters (base address in particular) can crash your system - you have been warned. - See Documentation/kernel-parameters.txt for details. + See Documentation/admin-guide/kernel-parameters.rst for details. If unsure, say 'N'. diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 4c09d93d9569..b2f82cf6bf86 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -170,8 +170,8 @@ config BINFMT_MISC You can do other nice things, too. Read the file to learn how to use this - feature, for information about how - to include Java support. and for + feature, for information about how + to include Java support. and for information about how to include Mono-based .NET support. To use binfmt_misc, you will need to mount it: diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index be40813eff52..b42e5bd6d8ff 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -86,4 +86,4 @@ config PSTORE_RAM Note that for historical reasons, the module will be named "ramoops.ko". - For more information, see Documentation/ramoops.txt. + For more information, see Documentation/admin-guide/ramoops.rst. diff --git a/include/linux/device.h b/include/linux/device.h index bc41e87a969b..36d3a9867da9 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -733,7 +733,7 @@ struct device_dma_parameters { * minimizes board-specific #ifdefs in drivers. * @driver_data: Private pointer for driver specific info. * @power: For device power management. - * See Documentation/power/devices.txt for details. + * See Documentation/power/admin-guide/devices.rst for details. * @pm_domain: Provide callbacks that are executed during system suspend, * hibernation, system resume and during runtime PM transitions * along with subsystem-level and driver-level callbacks. diff --git a/include/linux/pm.h b/include/linux/pm.h index 06eb353182ab..efa67b2dfee9 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -258,7 +258,7 @@ typedef struct pm_message { * example, if it detects that a child was unplugged while the system was * asleep). * - * Refer to Documentation/power/devices.txt for more information about the role + * Refer to Documentation/power/admin-guide/devices.rst for more information about the role * of the above callbacks in the system suspend process. * * There also are callbacks related to runtime power management of devices. diff --git a/include/uapi/linux/major.h b/include/uapi/linux/major.h index 620252e69b44..19e195bee990 100644 --- a/include/uapi/linux/major.h +++ b/include/uapi/linux/major.h @@ -3,7 +3,7 @@ /* * This file has definitions for major device numbers. - * For the device number assignments, see Documentation/devices.txt. + * For the device number assignments, see Documentation/admin-guide/devices.rst. */ #define UNNAMED_MAJOR 0 diff --git a/init/Kconfig b/init/Kconfig index 34407f15e6d3..172f80ea0d58 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1306,7 +1306,7 @@ config BLK_DEV_INITRD boot loader (loadlin or lilo) and that is mounted as root before the normal boot procedure. It is typically used to load modules needed to mount the "real" root file system, - etc. See for details. + etc. See for details. If RAM disk support (BLK_DEV_RAM) is also included, this also enables initial RAM disk (initrd) support and adds diff --git a/init/main.c b/init/main.c index 2858be732f6d..691eb9351a83 100644 --- a/init/main.c +++ b/init/main.c @@ -980,7 +980,7 @@ static int __ref kernel_init(void *unused) return 0; panic("No working init found. Try passing init= option to kernel. " - "See Linux Documentation/init.txt for guidance."); + "See Linux Documentation/admin-guide/init.rst for guidance."); } static noinline void __init kernel_init_freeable(void) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 33bc56cf60d7..d2df3a93284b 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -13,7 +13,7 @@ config PRINTK_TIME be included, not that the timestamp is recorded. The behavior is also controlled by the kernel command line - parameter printk.time=1. See Documentation/kernel-parameters.txt + parameter printk.time=1. See Documentation/admin-guide/kernel-parameters.rst config MESSAGE_LOGLEVEL_DEFAULT int "Default message log level (1-7)" diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index a8368d1c4348..d0c729ccec20 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2187,7 +2187,7 @@ sub process { if ($rawline=~/^\+\+\+\s+(\S+)/) { $setup_docs = 0; - if ($1 =~ m@Documentation/kernel-parameters.txt$@) { + if ($1 =~ m@Documentation/admin-guide/kernel-parameters.rst$@) { $setup_docs = 1; } #next; @@ -5102,7 +5102,7 @@ sub process { my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { WARN("VOLATILE", - "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); + "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr); } # Check for user-visible strings broken across lines, which breaks the ability @@ -5817,7 +5817,7 @@ sub process { if (!grep(/$name/, @setup_docs)) { CHK("UNDOCUMENTED_SETUP", - "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr); + "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.rst\n" . $herecurr); } } diff --git a/tools/testing/selftests/futex/README b/tools/testing/selftests/futex/README index 0558bb9ce0a6..f3926c33ed4c 100644 --- a/tools/testing/selftests/futex/README +++ b/tools/testing/selftests/futex/README @@ -59,4 +59,4 @@ o FIXME: decide on a sane test naming scheme. Currently the tests are named Coding Style ------------ o The Futex Test project adheres to the coding standards set forth by Linux - kernel as defined in the Linux source Documentation/CodingStyle. + kernel as defined in the Linux source Documentation/process/coding-style.rst. -- cgit v1.2.3 From 352cb4ef2d345fbe1955278890f9ea12cbe7bd21 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 21 Oct 2016 12:14:17 +0300 Subject: drm/i915: remove AGP dependency from DRM_I915 kconfig help text We haven't required AGP since 3e99a6b95614 ("drm/i915: Stop depending upon CONFIG_AGP_INTEL"). Split/rearrange the paragraphs a bit while at it. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477041257-8219-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/Kconfig | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 1c1b19ccb92f..45a5eb71e8e6 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -24,16 +24,17 @@ config DRM_I915 including 830M, 845G, 852GM, 855GM, 865G, 915G, 945G, 965G, G35, G41, G43, G45 chipsets and Celeron, Pentium, Core i3, Core i5, Core i7 as well as Atom CPUs with integrated graphics. - If M is selected, the module will be called i915. AGP support - is required for this driver to work. This driver is used by - the Intel driver in X.org 6.8 and XFree86 4.4 and above. It - replaces the older i830 module that supported a subset of the - hardware in older X.org releases. + + This driver is used by the Intel driver in X.org 6.8 and + XFree86 4.4 and above. It replaces the older i830 module that + supported a subset of the hardware in older X.org releases. Note that the older i810/i815 chipsets require the use of the i810 driver instead, and the Atom z5xx series has an entirely different implementation. + If "M" is selected, the module will be called i915. + config DRM_I915_PRELIMINARY_HW_SUPPORT bool "Enable preliminary support for prerelease Intel hardware by default" depends on DRM_I915 -- cgit v1.2.3 From 4881f0bad9eb56bb7257e2386ffb27ef969bb6ce Mon Sep 17 00:00:00 2001 From: Nehal Shah Date: Wed, 19 Oct 2016 14:30:32 +0530 Subject: ACPI / APD: Add clock frequency for future AMD I2C controller This patch supports 150 Mhz i2c clock frequency for Designware ip of future AMD I2C controller. Reviewed-by: S-k, Shyam-sundar Signed-off-by: Shah, Nehal-bakulchandra Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_apd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index d58fbf7f04e6..5ec7f3af7e9a 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -77,6 +77,11 @@ static const struct apd_device_desc cz_i2c_desc = { .fixed_clk_rate = 133000000, }; +static const struct apd_device_desc wt_i2c_desc = { + .setup = acpi_apd_setup, + .fixed_clk_rate = 150000000, +}; + static struct property_entry uart_properties[] = { PROPERTY_ENTRY_U32("reg-io-width", 4), PROPERTY_ENTRY_U32("reg-shift", 2), @@ -162,7 +167,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = { /* Generic apd devices */ #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE { "AMD0010", APD_ADDR(cz_i2c_desc) }, - { "AMDI0010", APD_ADDR(cz_i2c_desc) }, + { "AMDI0010", APD_ADDR(wt_i2c_desc) }, { "AMD0020", APD_ADDR(cz_uart_desc) }, { "AMDI0020", APD_ADDR(cz_uart_desc) }, { "AMD0030", }, -- cgit v1.2.3 From 88aecde40b84f2f631357c75337f79b8caa97757 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 28 Sep 2016 20:06:01 +0200 Subject: usbtmc: Add, clarify and fix comments Add information regarding lifespan of kref protection: Clarify comment on kref_get for interrupt in urb in usbtmc_probe() Add comment on kref_get in usbtmc_open() Fix endpoint reference in documentation for send_request_dev_dep_msg_in() Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index a6c1fae7d52a..f03692ec5520 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -157,6 +157,7 @@ static int usbtmc_open(struct inode *inode, struct file *filp) } data = usb_get_intfdata(intf); + /* Protect reference to data from file structure until release */ kref_get(&data->kref); /* Store pointer in file structure's private data field */ @@ -531,7 +532,7 @@ static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data, } /* - * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-IN endpoint. + * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-OUT endpoint. * @transfer_size: number of bytes to request from the device. * * See the USBTMC specification, Table 4. @@ -1471,7 +1472,7 @@ static int usbtmc_probe(struct usb_interface *intf, if (!data->iin_urb) goto error_register; - /* will reference data in int urb */ + /* Protect interrupt in endpoint data until iin_urb is freed */ kref_get(&data->kref); /* allocate buffer for interrupt in */ -- cgit v1.2.3 From a4e6a8524f4327105c557eb05dd420a542d7cefc Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 27 Sep 2016 09:16:59 -0700 Subject: usb: Convert pr_warning to pr_warn Use the more common logging mechanism. Miscellanea: o Realign multiline statements o Coalesce format Signed-off-by: Joe Perches Acked-by: Nicolas Ferre Acked-by: Robert Jarzmik Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/rndis.c | 9 ++++----- drivers/usb/gadget/function/u_serial.c | 4 ++-- drivers/usb/gadget/udc/at91_udc.h | 2 +- drivers/usb/gadget/udc/atmel_usba_udc.c | 4 ++-- drivers/usb/gadget/udc/fsl_usb2_udc.h | 2 +- drivers/usb/gadget/udc/m66592-udc.c | 4 ++-- drivers/usb/gadget/udc/omap_udc.h | 2 +- drivers/usb/gadget/udc/pxa25x_udc.h | 2 +- drivers/usb/host/isp1362-hcd.c | 27 ++++++++++++++------------- drivers/usb/isp1760/isp1760-if.c | 2 +- 10 files changed, 29 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index ab6ac1b74ac0..766c328c15c0 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -474,8 +474,7 @@ static int gen_ndis_query_resp(struct rndis_params *params, u32 OID, u8 *buf, break; default: - pr_warning("%s: query unknown OID 0x%08X\n", - __func__, OID); + pr_warn("%s: query unknown OID 0x%08X\n", __func__, OID); } if (retval < 0) length = 0; @@ -546,8 +545,8 @@ static int gen_ndis_set_resp(struct rndis_params *params, u32 OID, break; default: - pr_warning("%s: set unknown OID 0x%08X, size %d\n", - __func__, OID, buf_len); + pr_warn("%s: set unknown OID 0x%08X, size %d\n", + __func__, OID, buf_len); } return retval; @@ -854,7 +853,7 @@ int rndis_msg_parser(struct rndis_params *params, u8 *buf) * In one case those messages seemed to relate to the host * suspending itself. */ - pr_warning("%s: unknown RNDIS message 0x%08X len %d\n", + pr_warn("%s: unknown RNDIS message 0x%08X len %d\n", __func__, MsgType, MsgLength); print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET, buf, MsgLength); diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index e0cd1e4c8892..62ec842874aa 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -622,8 +622,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) switch (req->status) { default: /* presumably a transient fault */ - pr_warning("%s: unexpected %s status %d\n", - __func__, ep->name, req->status); + pr_warn("%s: unexpected %s status %d\n", + __func__, ep->name, req->status); /* FALL THROUGH */ case 0: /* normal completion */ diff --git a/drivers/usb/gadget/udc/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h index 0a433e6b346b..9bbe72764f31 100644 --- a/drivers/usb/gadget/udc/at91_udc.h +++ b/drivers/usb/gadget/udc/at91_udc.h @@ -175,7 +175,7 @@ struct at91_request { #endif #define ERR(stuff...) pr_err("udc: " stuff) -#define WARNING(stuff...) pr_warning("udc: " stuff) +#define WARNING(stuff...) pr_warn("udc: " stuff) #define INFO(stuff...) pr_info("udc: " stuff) #define DBG(stuff...) pr_debug("udc: " stuff) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index bb1f6c8f0f01..67894a9bae75 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -1464,8 +1464,8 @@ restart: pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA)); DBG(DBG_HW, "Packet length: %u\n", pkt_len); if (pkt_len != sizeof(crq)) { - pr_warning("udc: Invalid packet length %u " - "(expected %zu)\n", pkt_len, sizeof(crq)); + pr_warn("udc: Invalid packet length %u (expected %zu)\n", + pkt_len, sizeof(crq)); set_protocol_stall(udc, ep); return; } diff --git a/drivers/usb/gadget/udc/fsl_usb2_udc.h b/drivers/usb/gadget/udc/fsl_usb2_udc.h index 84715625b2b3..e92b8408b6f6 100644 --- a/drivers/usb/gadget/udc/fsl_usb2_udc.h +++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h @@ -554,7 +554,7 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) #endif #define ERR(stuff...) pr_err("udc: " stuff) -#define WARNING(stuff...) pr_warning("udc: " stuff) +#define WARNING(stuff...) pr_warn("udc: " stuff) #define INFO(stuff...) pr_info("udc: " stuff) /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c index 6e977dc22570..de3e03483659 100644 --- a/drivers/usb/gadget/udc/m66592-udc.c +++ b/drivers/usb/gadget/udc/m66592-udc.c @@ -637,7 +637,7 @@ static void init_controller(struct m66592 *m66592) clock = M66592_XTAL48; break; default: - pr_warning("m66592-udc: xtal configuration error\n"); + pr_warn("m66592-udc: xtal configuration error\n"); clock = 0; } @@ -649,7 +649,7 @@ static void init_controller(struct m66592 *m66592) irq_sense = 0; break; default: - pr_warning("m66592-udc: irq trigger config error\n"); + pr_warn("m66592-udc: irq trigger config error\n"); irq_sense = 0; } diff --git a/drivers/usb/gadget/udc/omap_udc.h b/drivers/usb/gadget/udc/omap_udc.h index cfadeb5fc5de..26974196cf44 100644 --- a/drivers/usb/gadget/udc/omap_udc.h +++ b/drivers/usb/gadget/udc/omap_udc.h @@ -187,7 +187,7 @@ struct omap_udc { #endif #define ERR(stuff...) pr_err("udc: " stuff) -#define WARNING(stuff...) pr_warning("udc: " stuff) +#define WARNING(stuff...) pr_warn("udc: " stuff) #define INFO(stuff...) pr_info("udc: " stuff) #define DBG(stuff...) pr_debug("udc: " stuff) diff --git a/drivers/usb/gadget/udc/pxa25x_udc.h b/drivers/usb/gadget/udc/pxa25x_udc.h index 4b8b72d7ab37..a458bec2536d 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.h +++ b/drivers/usb/gadget/udc/pxa25x_udc.h @@ -248,7 +248,7 @@ dump_state(struct pxa25x_udc *dev) #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0) #define ERR(stuff...) pr_err("udc: " stuff) -#define WARNING(stuff...) pr_warning("udc: " stuff) +#define WARNING(stuff...) pr_warn("udc: " stuff) #define INFO(stuff...) pr_info("udc: " stuff) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 6cf82ee460a6..0f2b4b358e1a 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -147,7 +147,7 @@ static inline struct isp1362_ep_queue *get_ptd_queue(struct isp1362_hcd *isp1362 if (epq) DBG(1, "%s: PTD $%04x is on %s queue\n", __func__, offset, epq->name); else - pr_warning("%s: invalid PTD $%04x\n", __func__, offset); + pr_warn("%s: invalid PTD $%04x\n", __func__, offset); return epq; } @@ -157,8 +157,9 @@ static inline int get_ptd_offset(struct isp1362_ep_queue *epq, u8 index) int offset; if (index * epq->blk_size > epq->buf_size) { - pr_warning("%s: Bad %s index %d(%d)\n", __func__, epq->name, index, - epq->buf_size / epq->blk_size); + pr_warn("%s: Bad %s index %d(%d)\n", + __func__, epq->name, index, + epq->buf_size / epq->blk_size); return -EINVAL; } offset = epq->buf_start + index * epq->blk_size; @@ -902,8 +903,8 @@ static void start_iso_transfers(struct isp1362_hcd *isp1362_hcd) ptd_offset = next_ptd(epq, ep); if (ptd_offset < 0) { - pr_warning("%s: req %d No more %s PTD buffers available\n", __func__, - ep->num_req, epq->name); + pr_warn("%s: req %d No more %s PTD buffers available\n", + __func__, ep->num_req, epq->name); break; } } @@ -973,8 +974,8 @@ static void finish_transfers(struct isp1362_hcd *isp1362_hcd, unsigned long done break; } if (done_map) - pr_warning("%s: done_map not clear: %08lx:%08lx\n", __func__, done_map, - epq->skip_map); + pr_warn("%s: done_map not clear: %08lx:%08lx\n", + __func__, done_map, epq->skip_map); atomic_dec(&epq->finishing); } @@ -1433,7 +1434,7 @@ static int isp1362_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) } else DBG(1, "%s: urb %p active; wait4irq\n", __func__, urb); } else { - pr_warning("%s: No EP in URB %p\n", __func__, urb); + pr_warn("%s: No EP in URB %p\n", __func__, urb); retval = -EINVAL; } done: @@ -1748,10 +1749,10 @@ static int isp1362_bus_suspend(struct usb_hcd *hcd) /* FALL THROUGH */ case OHCI_USB_RESET: status = -EBUSY; - pr_warning("%s: needs reinit!\n", __func__); + pr_warn("%s: needs reinit!\n", __func__); goto done; case OHCI_USB_SUSPEND: - pr_warning("%s: already suspended?\n", __func__); + pr_warn("%s: already suspended?\n", __func__); goto done; } DBG(0, "%s: suspend root hub\n", __func__); @@ -1839,7 +1840,7 @@ static int isp1362_bus_resume(struct usb_hcd *hcd) isp1362_hcd->hc_control = isp1362_read_reg32(isp1362_hcd, HCCONTROL); pr_info("%s: HCCONTROL: %08x\n", __func__, isp1362_hcd->hc_control); if (hcd->state == HC_STATE_RESUMING) { - pr_warning("%s: duplicate resume\n", __func__); + pr_warn("%s: duplicate resume\n", __func__); status = 0; } else switch (isp1362_hcd->hc_control & OHCI_CTRL_HCFS) { @@ -2474,8 +2475,8 @@ static int isp1362_chip_test(struct isp1362_hcd *isp1362_hcd) __func__, offset); break; } - pr_warning("%s: memory check with offset %02x ok after second read\n", - __func__, offset); + pr_warn("%s: memory check with offset %02x ok after second read\n", + __func__, offset); } } kfree(ref); diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c index 9535b2872183..79205b31e4a9 100644 --- a/drivers/usb/isp1760/isp1760-if.c +++ b/drivers/usb/isp1760/isp1760-if.c @@ -197,7 +197,7 @@ static int isp1760_plat_probe(struct platform_device *pdev) irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { - pr_warning("isp1760: IRQ resource not available\n"); + pr_warn("isp1760: IRQ resource not available\n"); return -ENODEV; } irqflags = irq_res->flags & IRQF_TRIGGER_MASK; -- cgit v1.2.3 From 5c2ad982fb422ae710184e5911de0d4e030de8ac Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sun, 23 Oct 2016 01:02:02 +0200 Subject: USB: EHCI: elide I/O watchdog on AMD parts This removes 10 timer wakeups per second. I'm running this patch for a while now and haven't spotted any adverse effects. Signed-off-by: Lucas Stach Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 3b3649d88c5f..0ed683c176f0 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -261,6 +261,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci->need_io_watchdog = 0; break; case PCI_VENDOR_ID_INTEL: + case PCI_VENDOR_ID_AMD: ehci->need_io_watchdog = 0; break; case PCI_VENDOR_ID_NVIDIA: -- cgit v1.2.3 From 629dd219881a6d9643806acf4f0166501f4c3374 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sun, 23 Oct 2016 01:02:03 +0200 Subject: USB: EHCI: merge all cases that disable the IO watchdog This merges the vendor NEC case with the INTEL and AMD one, as those 3 do exactly the same thing: disabling of the IO watchdog. Signed-off-by: Lucas Stach Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 0ed683c176f0..93326974ff4b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -258,8 +258,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* These workarounds need to be applied after ehci_setup() */ switch (pdev->vendor) { case PCI_VENDOR_ID_NEC: - ehci->need_io_watchdog = 0; - break; case PCI_VENDOR_ID_INTEL: case PCI_VENDOR_ID_AMD: ehci->need_io_watchdog = 0; -- cgit v1.2.3 From 275f039db56f998aaf6e2fc74acd1f653cdcb480 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 24 Oct 2016 13:42:14 +0100 Subject: drm/i915: Move user fault tracking to a separate list We want to decouple RPM and struct_mutex, but currently RPM has to walk the list of bound objects and remove userspace mmapping before we suspend (otherwise userspace may continue to access the GTT whilst it is powered down). This currently requires the struct_mutex to walk the bound_list, but if we move that to a separate list and lock we can take the first step towards removing the struct_mutex. v2: Split runtime suspend unmapping vs regular unmapping, to make the locking (and barriers) clearer. Add the object to the userfault_list prior to inserting the first PTE, the race between add/revoke depends upon struct_mutex for regular unmappings and rpm for runtime-suspend. Signed-off-by: Chris Wilson Reviewed-by: Daniel Vetter #v1 Link: http://patchwork.freedesktop.org/patch/msgid/20161024124218.18252-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 20 +++++++++++------ drivers/gpu/drm/i915/i915_gem.c | 42 +++++++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_evict.c | 2 +- drivers/gpu/drm/i915/i915_gem_fence.c | 2 +- 5 files changed, 49 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index dc057c770146..2d9617a3472d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -107,7 +107,7 @@ static char get_tiling_flag(struct drm_i915_gem_object *obj) static char get_global_flag(struct drm_i915_gem_object *obj) { - return obj->fault_mappable ? 'g' : ' '; + return !list_empty(&obj->userfault_link) ? 'g' : ' '; } static char get_pin_mapped_flag(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f022f438e5b9..a53172e7790f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1361,6 +1361,14 @@ struct i915_gem_mm { */ struct list_head unbound_list; + /** Protects access to the userfault_list */ + spinlock_t userfault_lock; + + /** List of all objects in gtt_space, currently mmaped by userspace. + * All objects within this list must also be on bound_list. + */ + struct list_head userfault_list; + /** Usable portion of the GTT for GEM */ unsigned long stolen_base; /* limited to low memory (32-bit) */ @@ -2205,6 +2213,11 @@ struct drm_i915_gem_object { struct drm_mm_node *stolen; struct list_head global_list; + /** + * Whether the object is currently in the GGTT mmap. + */ + struct list_head userfault_link; + /** Used in execbuf to temporarily hold a ref */ struct list_head obj_exec_link; @@ -2232,13 +2245,6 @@ struct drm_i915_gem_object { */ unsigned int madv:2; - /** - * Whether the current gtt mapping needs to be mappable (and isn't just - * mappable by accident). Track pin and fault separate for a more - * accurate mappable working set. - */ - unsigned int fault_mappable:1; - /* * Is the object to be mapped as read-only to the GPU * Only honoured if hardware has relevant pte bit diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9bb72e503a30..33ebf6d2556c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1839,16 +1839,19 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf) if (ret) goto err_unpin; + /* Mark as being mmapped into userspace for later revocation */ + spin_lock(&dev_priv->mm.userfault_lock); + if (list_empty(&obj->userfault_link)) + list_add(&obj->userfault_link, &dev_priv->mm.userfault_list); + spin_unlock(&dev_priv->mm.userfault_lock); + /* Finally, remap it using the new GTT offset */ ret = remap_io_mapping(area, area->vm_start + (vma->ggtt_view.params.partial.offset << PAGE_SHIFT), (ggtt->mappable_base + vma->node.start) >> PAGE_SHIFT, min_t(u64, vma->size, area->vm_end - area->vm_start), &ggtt->mappable); - if (ret) - goto err_unpin; - obj->fault_mappable = true; err_unpin: __i915_vma_unpin(vma); err_unlock: @@ -1916,13 +1919,22 @@ err: void i915_gem_release_mmap(struct drm_i915_gem_object *obj) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); + bool zap = false; + /* Serialisation between user GTT access and our code depends upon * revoking the CPU's PTE whilst the mutex is held. The next user * pagefault then has to wait until we release the mutex. */ - lockdep_assert_held(&obj->base.dev->struct_mutex); + lockdep_assert_held(&i915->drm.struct_mutex); - if (!obj->fault_mappable) + spin_lock(&i915->mm.userfault_lock); + if (!list_empty(&obj->userfault_link)) { + list_del_init(&obj->userfault_link); + zap = true; + } + spin_unlock(&i915->mm.userfault_lock); + if (!zap) return; drm_vma_node_unmap(&obj->base.vma_node, @@ -1936,8 +1948,6 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj) * memory writes before touching registers / GSM. */ wmb(); - - obj->fault_mappable = false; } void @@ -1945,8 +1955,19 @@ i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv) { struct drm_i915_gem_object *obj; - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) - i915_gem_release_mmap(obj); + spin_lock(&dev_priv->mm.userfault_lock); + while ((obj = list_first_entry_or_null(&dev_priv->mm.userfault_list, + struct drm_i915_gem_object, + userfault_link))) { + list_del_init(&obj->userfault_link); + spin_unlock(&dev_priv->mm.userfault_lock); + + drm_vma_node_unmap(&obj->base.vma_node, + obj->base.dev->anon_inode->i_mapping); + + spin_lock(&dev_priv->mm.userfault_lock); + } + spin_unlock(&dev_priv->mm.userfault_lock); } /** @@ -4108,6 +4129,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, int i; INIT_LIST_HEAD(&obj->global_list); + INIT_LIST_HEAD(&obj->userfault_link); for (i = 0; i < I915_NUM_ENGINES; i++) init_request_active(&obj->last_read[i], i915_gem_object_retire__read); @@ -4521,6 +4543,7 @@ int i915_gem_init(struct drm_device *dev) int ret; mutex_lock(&dev->struct_mutex); + spin_lock_init(&dev_priv->mm.userfault_lock); if (!i915.enable_execlists) { dev_priv->gt.resume = intel_legacy_submission_resume; @@ -4640,6 +4663,7 @@ i915_gem_load_init(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->mm.unbound_list); INIT_LIST_HEAD(&dev_priv->mm.bound_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); + INIT_LIST_HEAD(&dev_priv->mm.userfault_list); INIT_DELAYED_WORK(&dev_priv->gt.retire_work, i915_gem_retire_work_handler); INIT_DELAYED_WORK(&dev_priv->gt.idle_work, diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index b5e9e669f50f..a934f372c5ce 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -56,7 +56,7 @@ mark_free(struct i915_vma *vma, unsigned int flags, struct list_head *unwind) if (WARN_ON(!list_empty(&vma->exec_list))) return false; - if (flags & PIN_NONFAULT && vma->obj->fault_mappable) + if (flags & PIN_NONFAULT && !list_empty(&vma->obj->userfault_link)) return false; list_add(&vma->exec_list, unwind); diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index a6daf2deab74..67013179b8ed 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -391,7 +391,7 @@ void i915_gem_restore_fences(struct drm_device *dev) */ if (vma && !i915_gem_object_is_tiled(vma->obj)) { GEM_BUG_ON(!reg->dirty); - GEM_BUG_ON(vma->obj->fault_mappable); + GEM_BUG_ON(!list_empty(&vma->obj->userfault_link)); list_move(®->link, &dev_priv->mm.fence_list); vma->fence = NULL; -- cgit v1.2.3 From 9c870d03674f11b49ef4f48b04d709ffa7cf1390 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 24 Oct 2016 13:42:15 +0100 Subject: drm/i915: Use RPM as the barrier for controlling user mmap access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can remove the false coupling between RPM and struct mutex by the observation that we can use the RPM wakeref as the barrier around user mmap access. That is as we tear down the user's PTE atomically from within rpm suspend and then to fault in new PTE requires the rpm wakeref, means that no user access is possible through those PTE without RPM being awake. Having made that observation, we can then remove the presumption of having to take rpm outside of struct_mutex and so allow fine grained acquisition of a wakeref around hw access rather than having to remember to acquire the wakeref early on. v2: Rejig placement of the new intel_runtime_pm_get() to be as tight as possible around the GTT pread/pwrite. Signed-off-by: Chris Wilson Cc: Imre Deak Cc: Daniel Vetter Cc: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161024124218.18252-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 56 ++++++++++++++++++++-------------- drivers/gpu/drm/i915/i915_drv.c | 19 ------------ drivers/gpu/drm/i915/i915_gem.c | 42 +++++++++++++------------ drivers/gpu/drm/i915/i915_gem_gtt.c | 17 ++++++++--- drivers/gpu/drm/i915/i915_gem_tiling.c | 4 --- 5 files changed, 69 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 2d9617a3472d..f85e6fbf27f4 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -743,17 +743,32 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(VLV_IIR_RW)); seq_printf(m, "Display IMR:\t%08x\n", I915_READ(VLV_IMR)); - for_each_pipe(dev_priv, pipe) + for_each_pipe(dev_priv, pipe) { + enum intel_display_power_domain power_domain; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, + power_domain)) { + seq_printf(m, "Pipe %c power disabled\n", + pipe_name(pipe)); + continue; + } + seq_printf(m, "Pipe %c stat:\t%08x\n", pipe_name(pipe), I915_READ(PIPESTAT(pipe))); + intel_display_power_put(dev_priv, power_domain); + } + + intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); seq_printf(m, "Port hotplug:\t%08x\n", I915_READ(PORT_HOTPLUG_EN)); seq_printf(m, "DPFLIPSTAT:\t%08x\n", I915_READ(VLV_DPFLIPSTAT)); seq_printf(m, "DPINVGTT:\t%08x\n", I915_READ(DPINVGTT)); + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); for (i = 0; i < 4; i++) { seq_printf(m, "GT Interrupt IMR %d:\t%08x\n", @@ -1396,14 +1411,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) static int ironlake_drpc_info(struct seq_file *m) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; u32 rgvmodectl, rstdbyctl; u16 crstandvid; - int ret; - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; intel_runtime_pm_get(dev_priv); rgvmodectl = I915_READ(MEMMODECTL); @@ -1411,7 +1421,6 @@ static int ironlake_drpc_info(struct seq_file *m) crstandvid = I915_READ16(CRSTANDVID); intel_runtime_pm_put(dev_priv); - mutex_unlock(&dev->struct_mutex); seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN)); seq_printf(m, "Boost freq: %d\n", @@ -1757,6 +1766,7 @@ static int i915_sr_status(struct seq_file *m, void *unused) bool sr_enabled = false; intel_runtime_pm_get(dev_priv); + intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); if (HAS_PCH_SPLIT(dev_priv)) sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN; @@ -1770,6 +1780,7 @@ static int i915_sr_status(struct seq_file *m, void *unused) else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN; + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); intel_runtime_pm_put(dev_priv); seq_printf(m, "self-refresh: %s\n", @@ -2091,12 +2102,7 @@ static const char *swizzle_string(unsigned swizzle) static int i915_swizzle_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - int ret; - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; intel_runtime_pm_get(dev_priv); seq_printf(m, "bit6 swizzle for X-tiling = %s\n", @@ -2136,7 +2142,6 @@ static int i915_swizzle_info(struct seq_file *m, void *data) seq_puts(m, "L-shaped memory detected\n"); intel_runtime_pm_put(dev_priv); - mutex_unlock(&dev->struct_mutex); return 0; } @@ -2542,11 +2547,22 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE; else { for_each_pipe(dev_priv, pipe) { + enum transcoder cpu_transcoder = + intel_pipe_to_cpu_transcoder(dev_priv, pipe); + enum intel_display_power_domain power_domain; + + power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); + if (!intel_display_power_get_if_enabled(dev_priv, + power_domain)) + continue; + stat[pipe] = I915_READ(VLV_PSRSTAT(pipe)) & VLV_EDP_PSR_CURR_STATE_MASK; if ((stat[pipe] == VLV_EDP_PSR_ACTIVE_NORFB_UP) || (stat[pipe] == VLV_EDP_PSR_ACTIVE_SF_UPDATE)) enabled = true; + + intel_display_power_put(dev_priv, power_domain); } } @@ -3094,6 +3110,8 @@ static int i915_engine_info(struct seq_file *m, void *unused) struct intel_engine_cs *engine; enum intel_engine_id id; + intel_runtime_pm_get(dev_priv); + for_each_engine(engine, dev_priv, id) { struct intel_breadcrumbs *b = &engine->breadcrumbs; struct drm_i915_gem_request *rq; @@ -3213,6 +3231,8 @@ static int i915_engine_info(struct seq_file *m, void *unused) seq_puts(m, "\n"); } + intel_runtime_pm_put(dev_priv); + return 0; } @@ -4799,13 +4819,9 @@ i915_wedged_set(void *data, u64 val) if (i915_reset_in_progress(&dev_priv->gpu_error)) return -EAGAIN; - intel_runtime_pm_get(dev_priv); - i915_handle_error(dev_priv, val, "Manually setting wedged to %llu", val); - intel_runtime_pm_put(dev_priv); - return 0; } @@ -5040,22 +5056,16 @@ static int i915_cache_sharing_get(void *data, u64 *val) { struct drm_i915_private *dev_priv = data; - struct drm_device *dev = &dev_priv->drm; u32 snpcr; - int ret; if (!(IS_GEN6(dev_priv) || IS_GEN7(dev_priv))) return -ENODEV; - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; intel_runtime_pm_get(dev_priv); snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); intel_runtime_pm_put(dev_priv); - mutex_unlock(&dev->struct_mutex); *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 912d5348e3e7..885d33f341f3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2301,24 +2301,6 @@ static int intel_runtime_suspend(struct device *kdev) DRM_DEBUG_KMS("Suspending device\n"); - /* - * We could deadlock here in case another thread holding struct_mutex - * calls RPM suspend concurrently, since the RPM suspend will wait - * first for this RPM suspend to finish. In this case the concurrent - * RPM resume will be followed by its RPM suspend counterpart. Still - * for consistency return -EAGAIN, which will reschedule this suspend. - */ - if (!mutex_trylock(&dev->struct_mutex)) { - DRM_DEBUG_KMS("device lock contention, deffering suspend\n"); - /* - * Bump the expiration timestamp, otherwise the suspend won't - * be rescheduled. - */ - pm_runtime_mark_last_busy(kdev); - - return -EAGAIN; - } - disable_rpm_wakeref_asserts(dev_priv); /* @@ -2326,7 +2308,6 @@ static int intel_runtime_suspend(struct device *kdev) * an RPM reference. */ i915_gem_release_all_mmaps(dev_priv); - mutex_unlock(&dev->struct_mutex); intel_guc_suspend(dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 33ebf6d2556c..63bf51b117a9 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -826,6 +826,7 @@ i915_gem_gtt_pread(struct drm_device *dev, uint64_t offset; int ret; + intel_runtime_pm_get(to_i915(dev)); vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE); if (!IS_ERR(vma)) { node.start = i915_ggtt_offset(vma); @@ -926,6 +927,7 @@ out_unpin: i915_vma_unpin(vma); } out: + intel_runtime_pm_put(to_i915(dev)); return ret; } @@ -1060,12 +1062,9 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, ret = i915_gem_shmem_pread(dev, obj, args, file); /* pread for non shmem backed objects */ - if (ret == -EFAULT || ret == -ENODEV) { - intel_runtime_pm_get(to_i915(dev)); + if (ret == -EFAULT || ret == -ENODEV) ret = i915_gem_gtt_pread(dev, obj, args->size, args->offset, args->data_ptr); - intel_runtime_pm_put(to_i915(dev)); - } i915_gem_object_put(obj); mutex_unlock(&dev->struct_mutex); @@ -1126,6 +1125,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915, if (i915_gem_object_is_tiled(obj)) return -EFAULT; + intel_runtime_pm_get(i915); vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE | PIN_NONBLOCK); if (!IS_ERR(vma)) { @@ -1234,6 +1234,7 @@ out_unpin: i915_vma_unpin(vma); } out: + intel_runtime_pm_put(i915); return ret; } @@ -1466,12 +1467,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, * perspective, requiring manual detiling by the client. */ if (!i915_gem_object_has_struct_page(obj) || - cpu_write_needs_clflush(obj)) { - ret = i915_gem_gtt_pwrite_fast(dev_priv, obj, args, file); + cpu_write_needs_clflush(obj)) /* Note that the gtt paths might fail with non-page-backed user * pointers (e.g. gtt mappings when moving data between - * textures). Fallback to the shmem path in that case. */ - } + * textures). Fallback to the shmem path in that case. + */ + ret = i915_gem_gtt_pwrite_fast(dev_priv, obj, args, file); if (ret == -EFAULT || ret == -ENOSPC) { if (obj->phys_handle) @@ -1840,6 +1841,7 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf) goto err_unpin; /* Mark as being mmapped into userspace for later revocation */ + assert_rpm_wakelock_held(dev_priv); spin_lock(&dev_priv->mm.userfault_lock); if (list_empty(&obj->userfault_link)) list_add(&obj->userfault_link, &dev_priv->mm.userfault_list); @@ -1925,8 +1927,13 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj) /* Serialisation between user GTT access and our code depends upon * revoking the CPU's PTE whilst the mutex is held. The next user * pagefault then has to wait until we release the mutex. + * + * Note that RPM complicates somewhat by adding an additional + * requirement that operations to the GGTT be made holding the RPM + * wakeref. */ lockdep_assert_held(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); spin_lock(&i915->mm.userfault_lock); if (!list_empty(&obj->userfault_link)) { @@ -1935,7 +1942,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj) } spin_unlock(&i915->mm.userfault_lock); if (!zap) - return; + goto out; drm_vma_node_unmap(&obj->base.vma_node, obj->base.dev->anon_inode->i_mapping); @@ -1948,6 +1955,9 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj) * memory writes before touching registers / GSM. */ wmb(); + +out: + intel_runtime_pm_put(i915); } void @@ -3476,7 +3486,7 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(dev); struct drm_i915_gem_caching *args = data; struct drm_i915_gem_object *obj; enum i915_cache_level level; @@ -3493,23 +3503,21 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, * cacheline, whereas normally such cachelines would get * invalidated. */ - if (!HAS_LLC(dev) && !HAS_SNOOP(dev)) + if (!HAS_LLC(i915) && !HAS_SNOOP(i915)) return -ENODEV; level = I915_CACHE_LLC; break; case I915_CACHING_DISPLAY: - level = HAS_WT(dev_priv) ? I915_CACHE_WT : I915_CACHE_NONE; + level = HAS_WT(i915) ? I915_CACHE_WT : I915_CACHE_NONE; break; default: return -EINVAL; } - intel_runtime_pm_get(dev_priv); - ret = i915_mutex_lock_interruptible(dev); if (ret) - goto rpm_put; + return ret; obj = i915_gem_object_lookup(file, args->handle); if (!obj) { @@ -3518,13 +3526,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, } ret = i915_gem_object_set_cache_level(obj, level); - i915_gem_object_put(obj); unlock: mutex_unlock(&dev->struct_mutex); -rpm_put: - intel_runtime_pm_put(dev_priv); - return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 062fb0ad75da..33036359c170 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2667,6 +2667,7 @@ static int ggtt_bind_vma(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { + struct drm_i915_private *i915 = to_i915(vma->vm->dev); struct drm_i915_gem_object *obj = vma->obj; u32 pte_flags = 0; int ret; @@ -2679,8 +2680,10 @@ static int ggtt_bind_vma(struct i915_vma *vma, if (obj->gt_ro) pte_flags |= PTE_READ_ONLY; + intel_runtime_pm_get(i915); vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start, cache_level, pte_flags); + intel_runtime_pm_put(i915); /* * Without aliasing PPGTT there's no difference between @@ -2696,6 +2699,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { + struct drm_i915_private *i915 = to_i915(vma->vm->dev); u32 pte_flags; int ret; @@ -2710,14 +2714,15 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, if (flags & I915_VMA_GLOBAL_BIND) { + intel_runtime_pm_get(i915); vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start, cache_level, pte_flags); + intel_runtime_pm_put(i915); } if (flags & I915_VMA_LOCAL_BIND) { - struct i915_hw_ppgtt *appgtt = - to_i915(vma->vm->dev)->mm.aliasing_ppgtt; + struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt; appgtt->base.insert_entries(&appgtt->base, vma->pages, vma->node.start, cache_level, pte_flags); @@ -2728,12 +2733,16 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, static void ggtt_unbind_vma(struct i915_vma *vma) { - struct i915_hw_ppgtt *appgtt = to_i915(vma->vm->dev)->mm.aliasing_ppgtt; + struct drm_i915_private *i915 = to_i915(vma->vm->dev); + struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt; const u64 size = min(vma->size, vma->node.size); - if (vma->flags & I915_VMA_GLOBAL_BIND) + if (vma->flags & I915_VMA_GLOBAL_BIND) { + intel_runtime_pm_get(i915); vma->vm->clear_range(vma->vm, vma->node.start, size); + intel_runtime_pm_put(i915); + } if (vma->flags & I915_VMA_LOCAL_BIND && appgtt) appgtt->base.clear_range(&appgtt->base, diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index c21bc0068d20..71f80d2a487c 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -205,8 +205,6 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, return -EINVAL; } - intel_runtime_pm_get(dev_priv); - mutex_lock(&dev->struct_mutex); if (obj->pin_display || obj->framebuffer_references) { err = -EBUSY; @@ -302,8 +300,6 @@ err: i915_gem_object_put(obj); mutex_unlock(&dev->struct_mutex); - intel_runtime_pm_put(dev_priv); - return err; } -- cgit v1.2.3 From 3594a3e21f1f77d46e89195f36292a2fd0f4aa83 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 24 Oct 2016 13:42:16 +0100 Subject: drm/i915: Remove superfluous locking around userfault_list Now that we have reduced the access to the list to either (a) under the struct_mutex whilst holding the RPM wakeref (so that concurrent writers to the list are serialised by struct_mutex) and (b) under the atomic runtime suspend (which cannot run concurrently with any other accessor due to the atomic nature of the runtime suspend) we can remove the extra locking around the list itself. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161024124218.18252-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 3 --- drivers/gpu/drm/i915/i915_gem.c | 33 ++++++++++++--------------------- 2 files changed, 12 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a53172e7790f..ba87a852c0db 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1361,9 +1361,6 @@ struct i915_gem_mm { */ struct list_head unbound_list; - /** Protects access to the userfault_list */ - spinlock_t userfault_lock; - /** List of all objects in gtt_space, currently mmaped by userspace. * All objects within this list must also be on bound_list. */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 63bf51b117a9..38053434da8a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1842,10 +1842,8 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf) /* Mark as being mmapped into userspace for later revocation */ assert_rpm_wakelock_held(dev_priv); - spin_lock(&dev_priv->mm.userfault_lock); if (list_empty(&obj->userfault_link)) list_add(&obj->userfault_link, &dev_priv->mm.userfault_list); - spin_unlock(&dev_priv->mm.userfault_lock); /* Finally, remap it using the new GTT offset */ ret = remap_io_mapping(area, @@ -1922,7 +1920,6 @@ void i915_gem_release_mmap(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = to_i915(obj->base.dev); - bool zap = false; /* Serialisation between user GTT access and our code depends upon * revoking the CPU's PTE whilst the mutex is held. The next user @@ -1935,15 +1932,10 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj) lockdep_assert_held(&i915->drm.struct_mutex); intel_runtime_pm_get(i915); - spin_lock(&i915->mm.userfault_lock); - if (!list_empty(&obj->userfault_link)) { - list_del_init(&obj->userfault_link); - zap = true; - } - spin_unlock(&i915->mm.userfault_lock); - if (!zap) + if (list_empty(&obj->userfault_link)) goto out; + list_del_init(&obj->userfault_link); drm_vma_node_unmap(&obj->base.vma_node, obj->base.dev->anon_inode->i_mapping); @@ -1963,21 +1955,21 @@ out: void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv) { - struct drm_i915_gem_object *obj; + struct drm_i915_gem_object *obj, *on; - spin_lock(&dev_priv->mm.userfault_lock); - while ((obj = list_first_entry_or_null(&dev_priv->mm.userfault_list, - struct drm_i915_gem_object, - userfault_link))) { - list_del_init(&obj->userfault_link); - spin_unlock(&dev_priv->mm.userfault_lock); + /* + * Only called during RPM suspend. All users of the userfault_list + * must be holding an RPM wakeref to ensure that this can not + * run concurrently with themselves (and use the struct_mutex for + * protection between themselves). + */ + list_for_each_entry_safe(obj, on, + &dev_priv->mm.userfault_list, userfault_link) { + list_del_init(&obj->userfault_link); drm_vma_node_unmap(&obj->base.vma_node, obj->base.dev->anon_inode->i_mapping); - - spin_lock(&dev_priv->mm.userfault_lock); } - spin_unlock(&dev_priv->mm.userfault_lock); } /** @@ -4547,7 +4539,6 @@ int i915_gem_init(struct drm_device *dev) int ret; mutex_lock(&dev->struct_mutex); - spin_lock_init(&dev_priv->mm.userfault_lock); if (!i915.enable_execlists) { dev_priv->gt.resume = intel_legacy_submission_resume; -- cgit v1.2.3 From 2eedfc7d58997cbd7fd747aa757b8ceac8a2dc50 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 24 Oct 2016 13:42:17 +0100 Subject: drm/i915: Remove RPM sequence checking We only used the RPM sequence checking inside the lowlevel GTT accessors, when we had to rely on callers taking the wakeref on our behalf. Now that we take the RPM wakeref inside the GTT management routines themselves, we can forgo the sanitycheck of the callers. Signed-off-by: Chris Wilson Cc: Imre Deak Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/20161024124218.18252-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_gem_gtt.c | 55 +-------------------------------- drivers/gpu/drm/i915/intel_drv.h | 17 ---------- drivers/gpu/drm/i915/intel_pm.c | 1 - drivers/gpu/drm/i915/intel_runtime_pm.c | 3 +- 5 files changed, 2 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ba87a852c0db..ad1a1fbc5864 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1687,7 +1687,6 @@ struct skl_wm_level { */ struct i915_runtime_pm { atomic_t wakeref_count; - atomic_t atomic_seq; bool suspended; bool irqs_enabled; }; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 33036359c170..947d5ad51fb7 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2395,16 +2395,11 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm, gen8_pte_t __iomem *pte = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + (offset >> PAGE_SHIFT); - int rpm_atomic_seq; - - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); gen8_set_pte(pte, gen8_pte_encode(addr, level)); I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); - - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static void gen8_ggtt_insert_entries(struct i915_address_space *vm, @@ -2418,11 +2413,8 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, gen8_pte_t __iomem *gtt_entries; gen8_pte_t gtt_entry; dma_addr_t addr; - int rpm_atomic_seq; int i = 0; - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); - gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); for_each_sgt_dma(addr, sgt_iter, st) { @@ -2446,8 +2438,6 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, */ I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); - - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } struct insert_entries { @@ -2486,16 +2476,11 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm, gen6_pte_t __iomem *pte = (gen6_pte_t __iomem *)dev_priv->ggtt.gsm + (offset >> PAGE_SHIFT); - int rpm_atomic_seq; - - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); iowrite32(vm->pte_encode(addr, level, flags), pte); I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); - - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } /* @@ -2515,11 +2500,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, gen6_pte_t __iomem *gtt_entries; gen6_pte_t gtt_entry; dma_addr_t addr; - int rpm_atomic_seq; int i = 0; - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); - gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); for_each_sgt_dma(addr, sgt_iter, st) { @@ -2542,8 +2524,6 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, */ I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); - - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static void nop_clear_range(struct i915_address_space *vm, @@ -2554,7 +2534,6 @@ static void nop_clear_range(struct i915_address_space *vm, static void gen8_ggtt_clear_range(struct i915_address_space *vm, uint64_t start, uint64_t length) { - struct drm_i915_private *dev_priv = to_i915(vm->dev); struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); unsigned first_entry = start >> PAGE_SHIFT; unsigned num_entries = length >> PAGE_SHIFT; @@ -2562,9 +2541,6 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, (gen8_pte_t __iomem *)ggtt->gsm + first_entry; const int max_entries = ggtt_total_entries(ggtt) - first_entry; int i; - int rpm_atomic_seq; - - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); if (WARN(num_entries > max_entries, "First entry = %d; Num entries = %d (max=%d)\n", @@ -2576,15 +2552,12 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, for (i = 0; i < num_entries; i++) gen8_set_pte(>t_base[i], scratch_pte); readl(gtt_base); - - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static void gen6_ggtt_clear_range(struct i915_address_space *vm, uint64_t start, uint64_t length) { - struct drm_i915_private *dev_priv = to_i915(vm->dev); struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); unsigned first_entry = start >> PAGE_SHIFT; unsigned num_entries = length >> PAGE_SHIFT; @@ -2592,9 +2565,6 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, (gen6_pte_t __iomem *)ggtt->gsm + first_entry; const int max_entries = ggtt_total_entries(ggtt) - first_entry; int i; - int rpm_atomic_seq; - - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); if (WARN(num_entries > max_entries, "First entry = %d; Num entries = %d (max=%d)\n", @@ -2607,8 +2577,6 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); readl(gtt_base); - - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static void i915_ggtt_insert_page(struct i915_address_space *vm, @@ -2617,16 +2585,10 @@ static void i915_ggtt_insert_page(struct i915_address_space *vm, enum i915_cache_level cache_level, u32 unused) { - struct drm_i915_private *dev_priv = to_i915(vm->dev); unsigned int flags = (cache_level == I915_CACHE_NONE) ? AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; - int rpm_atomic_seq; - - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); intel_gtt_insert_page(addr, offset >> PAGE_SHIFT, flags); - - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static void i915_ggtt_insert_entries(struct i915_address_space *vm, @@ -2634,33 +2596,18 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm, uint64_t start, enum i915_cache_level cache_level, u32 unused) { - struct drm_i915_private *dev_priv = to_i915(vm->dev); unsigned int flags = (cache_level == I915_CACHE_NONE) ? AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; - int rpm_atomic_seq; - - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags); - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); - } static void i915_ggtt_clear_range(struct i915_address_space *vm, uint64_t start, uint64_t length) { - struct drm_i915_private *dev_priv = to_i915(vm->dev); - unsigned first_entry = start >> PAGE_SHIFT; - unsigned num_entries = length >> PAGE_SHIFT; - int rpm_atomic_seq; - - rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); - - intel_gtt_clear_range(first_entry, num_entries); - - assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); + intel_gtt_clear_range(start >> PAGE_SHIFT, length >> PAGE_SHIFT); } static int ggtt_bind_vma(struct i915_vma *vma, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c06a33e0ff19..95a7d3005a74 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1664,23 +1664,6 @@ assert_rpm_wakelock_held(struct drm_i915_private *dev_priv) DRM_DEBUG_DRIVER("RPM wakelock ref not held during HW access"); } -static inline int -assert_rpm_atomic_begin(struct drm_i915_private *dev_priv) -{ - int seq = atomic_read(&dev_priv->pm.atomic_seq); - - assert_rpm_wakelock_held(dev_priv); - - return seq; -} - -static inline void -assert_rpm_atomic_end(struct drm_i915_private *dev_priv, int begin_seq) -{ - WARN_ONCE(atomic_read(&dev_priv->pm.atomic_seq) != begin_seq, - "HW access outside of RPM atomic section\n"); -} - /** * disable_rpm_wakeref_asserts - disable the RPM assert checks * @dev_priv: i915 device instance diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ea01b406d776..8a6dbfd6aee6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -8043,5 +8043,4 @@ void intel_pm_setup(struct drm_device *dev) dev_priv->pm.suspended = false; atomic_set(&dev_priv->pm.wakeref_count, 0); - atomic_set(&dev_priv->pm.atomic_seq, 0); } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index ee56a8756c07..82edba2f3589 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2736,8 +2736,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv) struct device *kdev = &pdev->dev; assert_rpm_wakelock_held(dev_priv); - if (atomic_dec_and_test(&dev_priv->pm.wakeref_count)) - atomic_inc(&dev_priv->pm.atomic_seq); + atomic_dec(&dev_priv->pm.wakeref_count); pm_runtime_mark_last_busy(kdev); pm_runtime_put_autosuspend(kdev); -- cgit v1.2.3 From 7c108fd8feac9a4f380c22444ff8527e8d25bc75 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 24 Oct 2016 13:42:18 +0100 Subject: drm/i915: Move fence cancellation to runtime suspend At the moment, we have dependency on the RPM as a barrier itself in both i915_gem_release_all_mmaps() and i915_gem_restore_fences(). i915_gem_restore_fences() is also called along !runtime pm paths, but we can move the markup of lost fences alongside releasing the mmaps into a common i915_gem_runtime_suspend(). This has the advantage of locating all the tricky barrier dependencies into one location. v2: Just mark the fence as invalid (fence->dirty) so that upon waking we will be sure to clear the fence after use, or restore it to the correct value before use. This makes sure that if the fence is left intact across the sleep, we do not leave it pointing to a region of GTT for the next unsuspecting user. Suggested-by: Daniel Vetter Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Imre Deak Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/20161024124218.18252-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 6 ++---- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gem.c | 21 +++++++++++++++++++-- drivers/gpu/drm/i915/i915_gem_fence.c | 12 +++++------- 4 files changed, 28 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 885d33f341f3..99e4e044e958 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2278,10 +2278,8 @@ static int vlv_resume_prepare(struct drm_i915_private *dev_priv, vlv_check_no_gt_access(dev_priv); - if (rpm_resume) { + if (rpm_resume) intel_init_clock_gating(dev); - i915_gem_restore_fences(dev); - } return ret; } @@ -2307,7 +2305,7 @@ static int intel_runtime_suspend(struct device *kdev) * We are safe here against re-faults, since the fault handler takes * an RPM reference. */ - i915_gem_release_all_mmaps(dev_priv); + i915_gem_runtime_suspend(dev_priv); intel_guc_suspend(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ad1a1fbc5864..dd3acabb7edb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3130,9 +3130,10 @@ void i915_vma_destroy(struct i915_vma *vma); int i915_gem_object_unbind(struct drm_i915_gem_object *obj); int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); -void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); void i915_gem_release_mmap(struct drm_i915_gem_object *obj); +void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv); + int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj); static inline int __sg_page_count(struct scatterlist *sg) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 38053434da8a..58d4ad2026ea 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1952,10 +1952,10 @@ out: intel_runtime_pm_put(i915); } -void -i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv) +void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv) { struct drm_i915_gem_object *obj, *on; + int i; /* * Only called during RPM suspend. All users of the userfault_list @@ -1970,6 +1970,23 @@ i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv) drm_vma_node_unmap(&obj->base.vma_node, obj->base.dev->anon_inode->i_mapping); } + + /* The fence will be lost when the device powers down. If any were + * in use by hardware (i.e. they are pinned), we should not be powering + * down! All other fences will be reacquired by the user upon waking. + */ + for (i = 0; i < dev_priv->num_fence_regs; i++) { + struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; + + if (WARN_ON(reg->pin_count)) + continue; + + if (!reg->vma) + continue; + + GEM_BUG_ON(!list_empty(®->vma->obj->userfault_link)); + reg->dirty = true; + } } /** diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index 67013179b8ed..3c5a8082cac3 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -343,6 +343,9 @@ i915_vma_get_fence(struct i915_vma *vma) struct drm_i915_fence_reg *fence; struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL; + /* Note that we revoke fences on runtime suspend. Therefore the user + * must keep the device awake whilst using the fence. + */ assert_rpm_wakelock_held(to_i915(vma->vm->dev)); /* Just update our place in the LRU if our fence is getting reused. */ @@ -368,19 +371,14 @@ i915_vma_get_fence(struct i915_vma *vma) * @dev: DRM device * * Restore the hw fence state to match the software tracking again, to be called - * after a gpu reset and on resume. + * after a gpu reset and on resume. Note that on runtime suspend we only cancel + * the fences, to be reacquired by the user later. */ void i915_gem_restore_fences(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); int i; - /* Note that this may be called outside of struct_mutex, by - * runtime suspend/resume. The barrier we require is enforced by - * rpm itself - all access to fences/GTT are only within an rpm - * wakeref, and to acquire that wakeref you must pass through here. - */ - for (i = 0; i < dev_priv->num_fence_regs; i++) { struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; struct i915_vma *vma = reg->vma; -- cgit v1.2.3 From 054d4b7b577de6f5d25a0d443f0d59410bf156ad Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Thu, 29 Sep 2016 17:59:02 +0800 Subject: usb: ohci-at91: Use descriptor-based gpio APIs Use the descriptor-based interface to manipulate GPIOs, instead of the legacy integer-based interface. Signed-off-by: Wenyou Yang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-at91.c | 121 +++++++++++-------------------------------- 1 file changed, 31 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 5b5880c0ae19..2ebea306151d 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -14,8 +14,8 @@ #include #include +#include #include -#include #include #include #include @@ -39,8 +39,8 @@ #define AT91_MAX_USBH_PORTS 3 struct at91_usbh_data { - int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */ - int overcurrent_pin[AT91_MAX_USBH_PORTS]; + struct gpio_desc *vbus_pin[AT91_MAX_USBH_PORTS]; + struct gpio_desc *overcurrent_pin[AT91_MAX_USBH_PORTS]; u8 ports; /* number of ports on root hub */ u8 overcurrent_supported; u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS]; @@ -262,11 +262,8 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int if (!valid_port(port)) return; - if (!gpio_is_valid(pdata->vbus_pin[port])) - return; - - gpio_set_value(pdata->vbus_pin[port], - pdata->vbus_pin_active_low[port] ^ enable); + gpiod_set_value(pdata->vbus_pin[port], + pdata->vbus_pin_active_low[port] ^ enable); } static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) @@ -274,11 +271,8 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) if (!valid_port(port)) return -EINVAL; - if (!gpio_is_valid(pdata->vbus_pin[port])) - return -EINVAL; - - return gpio_get_value(pdata->vbus_pin[port]) ^ - pdata->vbus_pin_active_low[port]; + return gpiod_get_value(pdata->vbus_pin[port]) ^ + pdata->vbus_pin_active_low[port]; } /* @@ -468,16 +462,13 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) { struct platform_device *pdev = data; struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); - int val, gpio, port; + int val, port; /* From the GPIO notifying the over-current situation, find * out the corresponding port */ at91_for_each_port(port) { - if (gpio_is_valid(pdata->overcurrent_pin[port]) && - gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { - gpio = pdata->overcurrent_pin[port]; + if (gpiod_to_irq(pdata->overcurrent_pin[port]) == irq) break; - } } if (port == AT91_MAX_USBH_PORTS) { @@ -485,7 +476,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) return IRQ_HANDLED; } - val = gpio_get_value(gpio); + val = gpiod_get_value(pdata->overcurrent_pin[port]); /* When notified of an over-current situation, disable power on the corresponding port, and mark this port in @@ -516,9 +507,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct at91_usbh_data *pdata; int i; - int gpio; int ret; - enum of_gpio_flags flags; + int err; u32 ports; /* Right now device-tree probed devices don't get dma_mask set. @@ -539,38 +529,16 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) pdata->ports = ports; at91_for_each_port(i) { - /* - * do not configure PIO if not in relation with - * real USB port on board - */ - if (i >= pdata->ports) { - pdata->vbus_pin[i] = -EINVAL; - pdata->overcurrent_pin[i] = -EINVAL; + pdata->vbus_pin[i] = devm_gpiod_get_optional(&pdev->dev, + "atmel,vbus-gpio", + GPIOD_IN); + if (IS_ERR(pdata->vbus_pin[i])) { + err = PTR_ERR(pdata->vbus_pin[i]); + dev_err(&pdev->dev, "unable to claim gpio \"vbus\": %d\n", err); continue; } - gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, - &flags); - pdata->vbus_pin[i] = gpio; - if (!gpio_is_valid(gpio)) - continue; - pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW; - - ret = gpio_request(gpio, "ohci_vbus"); - if (ret) { - dev_err(&pdev->dev, - "can't request vbus gpio %d\n", gpio); - continue; - } - ret = gpio_direction_output(gpio, - !pdata->vbus_pin_active_low[i]); - if (ret) { - dev_err(&pdev->dev, - "can't put vbus gpio %d as output %d\n", - gpio, !pdata->vbus_pin_active_low[i]); - gpio_free(gpio); - continue; - } + pdata->vbus_pin_active_low[i] = gpiod_get_value(pdata->vbus_pin[i]); ohci_at91_usb_set_power(pdata, i, 1); } @@ -580,37 +548,21 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) break; pdata->overcurrent_pin[i] = - of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); - - if (!gpio_is_valid(pdata->overcurrent_pin[i])) - continue; - gpio = pdata->overcurrent_pin[i]; - - ret = gpio_request(gpio, "ohci_overcurrent"); - if (ret) { - dev_err(&pdev->dev, - "can't request overcurrent gpio %d\n", - gpio); + devm_gpiod_get_optional(&pdev->dev, + "atmel,oc-gpio", GPIOD_IN); + if (IS_ERR(pdata->overcurrent_pin[i])) { + err = PTR_ERR(pdata->overcurrent_pin[i]); + dev_err(&pdev->dev, "unable to claim gpio \"overcurrent\": %d\n", err); continue; } - ret = gpio_direction_input(gpio); - if (ret) { - dev_err(&pdev->dev, - "can't configure overcurrent gpio %d as input\n", - gpio); - gpio_free(gpio); - continue; - } - - ret = request_irq(gpio_to_irq(gpio), - ohci_hcd_at91_overcurrent_irq, - IRQF_SHARED, "ohci_overcurrent", pdev); - if (ret) { - gpio_free(gpio); - dev_err(&pdev->dev, - "can't get gpio IRQ for overcurrent\n"); - } + ret = devm_request_irq(&pdev->dev, + gpiod_to_irq(pdata->overcurrent_pin[i]), + ohci_hcd_at91_overcurrent_irq, + IRQF_SHARED, + "ohci_overcurrent", pdev); + if (ret) + dev_info(&pdev->dev, "failed to request gpio \"overcurrent\" IRQ\n"); } device_init_wakeup(&pdev->dev, 1); @@ -623,19 +575,8 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) int i; if (pdata) { - at91_for_each_port(i) { - if (!gpio_is_valid(pdata->vbus_pin[i])) - continue; + at91_for_each_port(i) ohci_at91_usb_set_power(pdata, i, 0); - gpio_free(pdata->vbus_pin[i]); - } - - at91_for_each_port(i) { - if (!gpio_is_valid(pdata->overcurrent_pin[i])) - continue; - free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev); - gpio_free(pdata->overcurrent_pin[i]); - } } device_init_wakeup(&pdev->dev, 0); -- cgit v1.2.3 From 6fbbcf38730210dc00123ad0188002189716169d Mon Sep 17 00:00:00 2001 From: Julien Cristau Date: Tue, 4 Oct 2016 22:49:30 +0200 Subject: hwrng: chaoskey - drop workaround for old hwrng core limitation The hwrng core used to mask 'quality' with 1023; that has been removed in commit 506bf0c0464ace57169aadcf02ae397999c57bdd ("hwrng: core - allow perfect entropy from hardware devices"), so we can now just set quality to 1024. Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/chaoskey.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c index 6ddd08a32777..aa350dc9eb25 100644 --- a/drivers/usb/misc/chaoskey.c +++ b/drivers/usb/misc/chaoskey.c @@ -215,19 +215,7 @@ static int chaoskey_probe(struct usb_interface *interface, dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name; dev->hwrng.read = chaoskey_rng_read; - - /* Set the 'quality' metric. Quality is measured in units of - * 1/1024's of a bit ("mills"). This should be set to 1024, - * but there is a bug in the hwrng core which masks it with - * 1023. - * - * The patch that has been merged to the crypto development - * tree for that bug limits the value to 1024 at most, so by - * setting this to 1024 + 1023, we get 1023 before the fix is - * merged and 1024 afterwards. We'll patch this driver once - * both bits of code are in the same tree. - */ - dev->hwrng.quality = 1024 + 1023; + dev->hwrng.quality = 1024; dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0); if (!dev->hwrng_registered) -- cgit v1.2.3 From 6110c425d98b7ed036bba3670e635a9363dd072e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 12 Oct 2016 20:44:46 -0500 Subject: usb: ohci-da8xx: Remove code that references mach Including mach/* is frowned upon in device drivers, so get rid of it. This replaces usb20_clk and code that pokes CFGCHIP2 with a proper phy driver. Signed-off-by: David Lechner Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + drivers/usb/host/ohci-da8xx.c | 102 +++++++++++++++++++++++------------------- 2 files changed, 56 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0b80cee30da4..83b6cec20b33 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -482,6 +482,7 @@ config USB_OHCI_HCD_DAVINCI bool "OHCI support for TI DaVinci DA8xx" depends on ARCH_DAVINCI_DA8XX depends on USB_OHCI_HCD=y + select PHY_DA8XX_USB default y help Enables support for the DaVinci DA8xx integrated OHCI diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index e5c33bc98ea4..3656d7cea58c 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -15,58 +15,50 @@ #include #include #include - -#include +#include #include #ifndef CONFIG_ARCH_DAVINCI_DA8XX #error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX." #endif -#define CFGCHIP2 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG) - static struct clk *usb11_clk; -static struct clk *usb20_clk; +static struct phy *usb11_phy; /* Over-current indicator change bitmask */ static volatile u16 ocic_mask; -static void ohci_da8xx_clock(int on) +static int ohci_da8xx_enable(void) { - u32 cfgchip2; - - cfgchip2 = __raw_readl(CFGCHIP2); - if (on) { - clk_enable(usb11_clk); - - /* - * If USB 1.1 reference clock is sourced from USB 2.0 PHY, we - * need to enable the USB 2.0 module clocking, start its PHY, - * and not allow it to stop the clock during USB 2.0 suspend. - */ - if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) { - clk_enable(usb20_clk); - - cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN); - cfgchip2 |= CFGCHIP2_PHY_PLLON; - __raw_writel(cfgchip2, CFGCHIP2); - - pr_info("Waiting for USB PHY clock good...\n"); - while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD)) - cpu_relax(); - } + int ret; - /* Enable USB 1.1 PHY */ - cfgchip2 |= CFGCHIP2_USB1SUSPENDM; - } else { - clk_disable(usb11_clk); - if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) - clk_disable(usb20_clk); + ret = clk_prepare_enable(usb11_clk); + if (ret) + return ret; - /* Disable USB 1.1 PHY */ - cfgchip2 &= ~CFGCHIP2_USB1SUSPENDM; - } - __raw_writel(cfgchip2, CFGCHIP2); + ret = phy_init(usb11_phy); + if (ret) + goto err_phy_init; + + ret = phy_power_on(usb11_phy); + if (ret) + goto err_phy_power_on; + + return 0; + +err_phy_power_on: + phy_exit(usb11_phy); +err_phy_init: + clk_disable_unprepare(usb11_clk); + + return ret; +} + +static void ohci_da8xx_disable(void) +{ + phy_power_off(usb11_phy); + phy_exit(usb11_phy); + clk_disable_unprepare(usb11_clk); } /* @@ -92,7 +84,9 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) dev_dbg(dev, "starting USB controller\n"); - ohci_da8xx_clock(1); + result = ohci_da8xx_enable(); + if (result < 0) + return result; /* * DA8xx only have 1 port connected to the pins but the HC root hub @@ -101,8 +95,10 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) ohci->num_ports = 1; result = ohci_init(ohci); - if (result < 0) + if (result < 0) { + ohci_da8xx_disable(); return result; + } /* * Since we're providing a board-specific root hub port power control @@ -129,7 +125,7 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) static void ohci_da8xx_stop(struct usb_hcd *hcd) { ohci_stop(hcd); - ohci_da8xx_clock(0); + ohci_da8xx_disable(); } static int ohci_da8xx_start(struct usb_hcd *hcd) @@ -301,12 +297,18 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, return -ENODEV; usb11_clk = devm_clk_get(&pdev->dev, "usb11"); - if (IS_ERR(usb11_clk)) + if (IS_ERR(usb11_clk)) { + if (PTR_ERR(usb11_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get clock.\n"); return PTR_ERR(usb11_clk); + } - usb20_clk = devm_clk_get(&pdev->dev, "usb20"); - if (IS_ERR(usb20_clk)) - return PTR_ERR(usb20_clk); + usb11_phy = devm_phy_get(&pdev->dev, "usb-phy"); + if (IS_ERR(usb11_phy)) { + if (PTR_ERR(usb11_phy) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get phy.\n"); + return PTR_ERR(usb11_phy); + } hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) @@ -316,6 +318,7 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, hcd->regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(hcd->regs)) { error = PTR_ERR(hcd->regs); + dev_err(&pdev->dev, "failed to map ohci.\n"); goto err; } hcd->rsrc_start = mem->start; @@ -397,7 +400,7 @@ static int ohci_da8xx_suspend(struct platform_device *pdev, if (ret) return ret; - ohci_da8xx_clock(0); + ohci_da8xx_disable(); hcd->state = HC_STATE_SUSPENDED; return ret; @@ -407,14 +410,19 @@ static int ohci_da8xx_resume(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; - ohci_da8xx_clock(1); + ret = ohci_da8xx_enable(); + if (ret) + return ret; + dev->dev.power.power_state = PMSG_ON; usb_hcd_resume_root_hub(hcd); + return 0; } #endif -- cgit v1.2.3 From 35b7ebda57affcfd3616d39d5a727a4495b31123 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Wed, 19 Oct 2016 15:58:09 -0700 Subject: staging: vc04_services: Convert dsb() to dsb(sy) The dsb() macro for 32 arm compiles to dsb(sy) in the binary file. This macro is no longer supported on arm64, so instead use dsb(sy) which is completely binary compatible. Signed-off-by: Michael Zoran Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c | 2 +- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index ca1fee35cc73..32d12e6e1b4f 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -210,7 +210,7 @@ remote_event_signal(REMOTE_EVENT_T *event) event->fired = 1; - dsb(); /* data barrier operation */ + dsb(sy); /* data barrier operation */ if (event->armed) writel(0, g_regs + BELL2); /* trigger vc interrupt */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 1254975a57bc..05954f983125 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -419,7 +419,7 @@ remote_event_wait(REMOTE_EVENT_T *event) { if (!event->fired) { event->armed = 1; - dsb(); + dsb(sy); if (!event->fired) { if (down_interruptible(event->event) != 0) { event->armed = 0; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index 9be484c776d0..9013bdbf242c 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -184,11 +184,11 @@ enum { #define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug; #define DEBUG_TRACE(d) \ - do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0) + do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(sy); } while (0) #define DEBUG_VALUE(d, v) \ - do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0) + do { debug_ptr[DEBUG_ ## d] = (v); dsb(sy); } while (0) #define DEBUG_COUNT(d) \ - do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0) + do { debug_ptr[DEBUG_ ## d]++; dsb(sy); } while (0) #else /* VCHIQ_ENABLE_DEBUG */ -- cgit v1.2.3 From e64568b8ea6c04e747e432c17ce2452652075216 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Wed, 19 Oct 2016 15:58:27 -0700 Subject: staging: vc04_services: Change fields of page list structure to fixed length The arm processor core and the GPU have shared data structures. One of these structures is a list of pages of data for messages. This structure can not change since it is dependent on the GPU firmware which is external to the kernel. Convert the fields of this structure to fixed length fields. Signed-off-by: Michael Zoran Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/interface/vchiq_arm/vchiq_pagelist.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h index 54a3ecec69ef..12c304ceb952 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h @@ -43,11 +43,13 @@ #define PAGELIST_READ_WITH_FRAGMENTS 2 typedef struct pagelist_struct { - unsigned long length; - unsigned short type; - unsigned short offset; - unsigned long addrs[1]; /* N.B. 12 LSBs hold the number of following - pages at consecutive addresses. */ + u32 length; + u16 type; + u16 offset; + u32 addrs[1]; /* N.B. 12 LSBs hold the number + * of following pages at consecutive + * addresses. + */ } PAGELIST_T; typedef struct fragments_struct { -- cgit v1.2.3 From 24a4262afb10907fce3cdbc3ae336fcf4cdaece5 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Wed, 19 Oct 2016 15:58:34 -0700 Subject: staging: vc04_services: Convert pointers in shared state to offsets The arm processor core and the GPU have a shared data structure. This structure contains pointers to base linux kernel objects such as events. The size of the pointer changes between 32 bit and 64 bit, so it is necessary to convert these pointers to offsets from the beginning of the state structure. Luckly, the GPU does not interpret these pointers/offsets, but this change is necessary to keep the structure the same since the GPU code is outside the scope of the linux kernel and can't be easily changed. Signed-off-by: Michael Zoran Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/interface/vchiq_arm/vchiq_core.c | 54 +++++++++++----------- .../vc04_services/interface/vchiq_arm/vchiq_core.h | 3 +- 2 files changed, 30 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 05954f983125..3aa5cc4f8576 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -406,22 +406,24 @@ vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate) } static inline void -remote_event_create(REMOTE_EVENT_T *event) +remote_event_create(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) { event->armed = 0; /* Don't clear the 'fired' flag because it may already have been set ** by the other side. */ - sema_init(event->event, 0); + sema_init((struct semaphore *)((char *)state + event->event), 0); } static inline int -remote_event_wait(REMOTE_EVENT_T *event) +remote_event_wait(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) { if (!event->fired) { event->armed = 1; dsb(sy); if (!event->fired) { - if (down_interruptible(event->event) != 0) { + if (down_interruptible( + (struct semaphore *) + ((char *)state + event->event)) != 0) { event->armed = 0; return 0; } @@ -435,26 +437,26 @@ remote_event_wait(REMOTE_EVENT_T *event) } static inline void -remote_event_signal_local(REMOTE_EVENT_T *event) +remote_event_signal_local(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) { event->armed = 0; - up(event->event); + up((struct semaphore *)((char *)state + event->event)); } static inline void -remote_event_poll(REMOTE_EVENT_T *event) +remote_event_poll(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) { if (event->fired && event->armed) - remote_event_signal_local(event); + remote_event_signal_local(state, event); } void remote_event_pollall(VCHIQ_STATE_T *state) { - remote_event_poll(&state->local->sync_trigger); - remote_event_poll(&state->local->sync_release); - remote_event_poll(&state->local->trigger); - remote_event_poll(&state->local->recycle); + remote_event_poll(state, &state->local->sync_trigger); + remote_event_poll(state, &state->local->sync_release); + remote_event_poll(state, &state->local->trigger); + remote_event_poll(state, &state->local->recycle); } /* Round up message sizes so that any space at the end of a slot is always big @@ -535,7 +537,7 @@ request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type) wmb(); /* ... and ensure the slot handler runs. */ - remote_event_signal_local(&state->local->trigger); + remote_event_signal_local(state, &state->local->trigger); } /* Called from queue_message, by the slot handler and application threads, @@ -976,7 +978,7 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, (mutex_lock_interruptible(&state->sync_mutex) != 0)) return VCHIQ_RETRY; - remote_event_wait(&local->sync_release); + remote_event_wait(state, &local->sync_release); rmb(); @@ -1995,7 +1997,7 @@ slot_handler_func(void *v) while (1) { DEBUG_COUNT(SLOT_HANDLER_COUNT); DEBUG_TRACE(SLOT_HANDLER_LINE); - remote_event_wait(&local->trigger); + remote_event_wait(state, &local->trigger); rmb(); @@ -2084,7 +2086,7 @@ recycle_func(void *v) VCHIQ_SHARED_STATE_T *local = state->local; while (1) { - remote_event_wait(&local->recycle); + remote_event_wait(state, &local->recycle); process_free_queue(state); } @@ -2107,7 +2109,7 @@ sync_func(void *v) int type; unsigned int localport, remoteport; - remote_event_wait(&local->sync_trigger); + remote_event_wait(state, &local->sync_trigger); rmb(); @@ -2406,24 +2408,24 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, state->data_use_count = 0; state->data_quota = state->slot_queue_available - 1; - local->trigger.event = &state->trigger_event; - remote_event_create(&local->trigger); + local->trigger.event = offsetof(VCHIQ_STATE_T, trigger_event); + remote_event_create(state, &local->trigger); local->tx_pos = 0; - local->recycle.event = &state->recycle_event; - remote_event_create(&local->recycle); + local->recycle.event = offsetof(VCHIQ_STATE_T, recycle_event); + remote_event_create(state, &local->recycle); local->slot_queue_recycle = state->slot_queue_available; - local->sync_trigger.event = &state->sync_trigger_event; - remote_event_create(&local->sync_trigger); + local->sync_trigger.event = offsetof(VCHIQ_STATE_T, sync_trigger_event); + remote_event_create(state, &local->sync_trigger); - local->sync_release.event = &state->sync_release_event; - remote_event_create(&local->sync_release); + local->sync_release.event = offsetof(VCHIQ_STATE_T, sync_release_event); + remote_event_create(state, &local->sync_release); /* At start-of-day, the slot is empty and available */ ((VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid = VCHIQ_MSGID_PADDING; - remote_event_signal_local(&local->sync_release); + remote_event_signal_local(state, &local->sync_release); local->debug[DEBUG_ENTRIES] = DEBUG_MAX; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index 9013bdbf242c..1c2b1b5b8cc9 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -264,7 +264,8 @@ typedef struct vchiq_bulk_queue_struct { typedef struct remote_event_struct { int armed; int fired; - struct semaphore *event; + /* Contains offset from the beginning of the VCHIQ_STATE_T structure */ + u32 event; } REMOTE_EVENT_T; typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T; -- cgit v1.2.3 From 8e8e2e36f77ab074016f79ac63b7255f645da3ed Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Wed, 19 Oct 2016 15:58:48 -0700 Subject: staging: vc04_services: Handle conversion from VCHIQ_SERVICE_HANDLE_T to VCHI_SERVICE_HANDLE_T A VCHIQ_SERVICE_HANDLE_T which is an int is stuffed into a VCHI_SERVICE_HANDLE_T which is a pointer, passed around, then converted back to a VCHIQ_SERVICE_HANDLE_T. Since the data is always actually a VCHIQ_SERVICE_HANDLE_T(int), never actually a pointer, it is safe to simply cast the two back in forth. Note that pointers are never stuffed into an int. Signed-off-by: Michael Zoran Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/interface/vchiq_arm/vchiq_shim.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c index 8072ff613636..49f9d6a8f78d 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c @@ -400,8 +400,16 @@ EXPORT_SYMBOL(vchi_msg_queuev); ***********************************************************/ int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) { - vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service, - (VCHIQ_HEADER_T *)message->message); + /* + * Convert the service field pointer back to an + * VCHIQ_SERVICE_HANDLE_T which is an int. + * This pointer is opaque to everything except + * vchi_msg_hold which simply upcasted the int + * to a pointer. + */ + + vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)(long)message->service, + (VCHIQ_HEADER_T *)message->message); return 0; } @@ -445,8 +453,16 @@ int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, *data = header->data; *msg_size = header->size; + /* + * upcast the VCHIQ_SERVICE_HANDLE_T which is an int + * to a pointer and stuff it in the held message. + * This pointer is opaque to everything except + * vchi_held_msg_release which simply downcasts it back + * to an int. + */ + message_handle->service = - (struct opaque_vchi_service_t *)service->handle; + (struct opaque_vchi_service_t *)(long)service->handle; message_handle->message = header; return 0; -- cgit v1.2.3 From f9bee6dd24addfa00c2c8d50c25b73efbfbb28ba Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Wed, 19 Oct 2016 15:58:54 -0700 Subject: staging: vc04_services: Add casts to remove warnings in vchiq_core.c When compiling vchiq_core.c for 64 bit, the compiler emits a few warnings that are not actual issues. This change adds a few casts to remove the extra unnecessary warnings. Signed-off-by: Michael Zoran Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../staging/vc04_services/interface/vchiq_arm/vchiq_core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 3aa5cc4f8576..e29262971b02 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -1689,8 +1689,8 @@ parse_rx_slots(VCHIQ_STATE_T *state) min(64, size)); } - if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) - > VCHIQ_SLOT_SIZE) { + if (((unsigned long)header & VCHIQ_SLOT_MASK) + + calc_stride(size) > VCHIQ_SLOT_SIZE) { vchiq_log_error(vchiq_core_log_level, "header %pK (msgid %x) - size %x too big for slot", header, (unsigned int)msgid, @@ -1800,7 +1800,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) bulk = &queue->bulks[ BULK_INDEX(queue->remote_insert)]; bulk->remote_data = - (void *)((int *)header->data)[0]; + (void *)(long)((int *)header->data)[0]; bulk->remote_size = ((int *)header->data)[1]; wmb(); @@ -2223,7 +2223,8 @@ get_conn_state_name(VCHIQ_CONNSTATE_T conn_state) VCHIQ_SLOT_ZERO_T * vchiq_init_slots(void *mem_base, int mem_size) { - int mem_align = (VCHIQ_SLOT_SIZE - (int)mem_base) & VCHIQ_SLOT_MASK; + int mem_align = + (int)((VCHIQ_SLOT_SIZE - (long)mem_base) & VCHIQ_SLOT_MASK); VCHIQ_SLOT_ZERO_T *slot_zero = (VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align); int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE; @@ -3303,7 +3304,7 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, (dir == VCHIQ_BULK_TRANSMIT) ? VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); } else { - int payload[2] = { (int)bulk->data, bulk->size }; + int payload[2] = { (int)(long)bulk->data, bulk->size }; VCHIQ_ELEMENT_T element = { payload, sizeof(payload) }; status = queue_message(state, NULL, -- cgit v1.2.3 From 9fdd532c51ce9c8f08fea329e74ec8021568b97b Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Mon, 17 Oct 2016 22:00:07 -0200 Subject: staging: android: Remove unnecessary parentheses. The removed parentheses are unnecessary and don't add readability. Found using Coccinelle semantic patch: @@ expression e, e1, e2; @@ e = ( (e1 == e2) | - (e1) + e1 ) Signed-off-by: Elise Lennion Acked-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 7e023d505af8..3ebbb75746e8 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -30,7 +30,7 @@ static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_RECLAIM; -static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO); +static gfp_t low_order_gfp_flags = GFP_HIGHUSER | __GFP_ZERO; static const unsigned int orders[] = {8, 4, 0}; static int order_to_index(unsigned int order) -- cgit v1.2.3 From a0f204a4f79d09a102315a67e1ba27de9fea6c8a Mon Sep 17 00:00:00 2001 From: Mihaela Muraru Date: Mon, 17 Oct 2016 17:20:18 +0300 Subject: Staging: android: ion: Make a read-only structure This patch add const qualifier at the declaration of the structure. The structure become a read-only data, this increase the security. Found with Coccinelle: @r disable optional_qualifier@ identifier s,i; @@ * static struct s i ={...}; Signed-off-by: Mihaela Muraru Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_dummy_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c index b23f2c76c753..cf5c010d32bc 100644 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -58,7 +58,7 @@ static struct ion_platform_heap dummy_heaps[] = { }, }; -static struct ion_platform_data dummy_ion_pdata = { +static const struct ion_platform_data dummy_ion_pdata = { .nr = ARRAY_SIZE(dummy_heaps), .heaps = dummy_heaps, }; -- cgit v1.2.3 From 596f144943812954113f028c915e0b6c08200429 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Mon, 17 Oct 2016 22:01:26 -0200 Subject: staging: vt6656: Remove unnecessary parentheses. The removed parentheses are unnecessary and don't add readability. Found using Coccinelle semantic patch: @@ expression e, e1, e2; @@ e += ( (e1 == e2) | - (e1) + e1 ) @@ expression e, e1, e2; @@ e = ( (e1 == e2) | - (e1) + e1 ) Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/mac.c | 2 +- drivers/staging/vt6656/rf.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c index eeed16e9124e..611da4929ddc 100644 --- a/drivers/staging/vt6656/mac.c +++ b/drivers/staging/vt6656/mac.c @@ -121,7 +121,7 @@ void vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx, u16 offset; offset = MISCFIFO_KEYETRY0; - offset += (entry_idx * MISCFIFO_KEYENTRYSIZE); + offset += entry_idx * MISCFIFO_KEYENTRYSIZE; set_key.u.write.key_ctl = cpu_to_le16(key_ctl); ether_addr_copy(set_key.u.write.addr, addr); diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index 79a3108719a6..8b724797734b 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -800,8 +800,8 @@ int vnt_rf_set_txpower(struct vnt_private *priv, u8 power, u32 rate) /* Convert rssi to dbm */ void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm) { - u8 idx = (((rssi & 0xc0) >> 6) & 0x03); - long b = (rssi & 0x3f); + u8 idx = ((rssi & 0xc0) >> 6) & 0x03; + long b = rssi & 0x3f; long a = 0; u8 airoharf[4] = {0, 18, 0, 40}; -- cgit v1.2.3 From 5bc45c9d1ebaa1734c36f2abf1db85b579888224 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Mon, 17 Oct 2016 21:57:58 -0200 Subject: staging: xgifb: Remove unnecessary parentheses. The removed parentheses are unnecessary and don't add readability. Found using Coccinelle semantic patch: @@ expression e, e1, e2; @@ e &= ( (e1 == e2) | - (e1) + e1 ) @@ expression e, e1, e2; @@ e |= ( (e1 == e2) | - (e1) + e1 ) Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index f4bcb15625ce..6467d96414c1 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -507,7 +507,7 @@ static void XGI_SetXG27CRTC(unsigned short RefreshRateTableIndex, /* SR0B */ Tempax = XGI_CRT1Table[index].CR[5]; Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/ - Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */ + Tempbx |= Tempax << 2; /* Tempbx: HRS[9:0] */ Tempax = XGI_CRT1Table[index].CR[4]; /* CR5 HRE */ Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */ @@ -530,7 +530,7 @@ static void XGI_SetXG27CRTC(unsigned short RefreshRateTableIndex, Tempax = XGI_CRT1Table[index].CR[5]; /* SR0B */ Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/ Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/ - Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */ + Tempax |= (Tempbx << 2) & 0xFF; /* Tempax[7:2]: HRE[5:0] */ /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */ xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax); xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00); @@ -548,12 +548,12 @@ static void XGI_SetXG27CRTC(unsigned short RefreshRateTableIndex, Tempax >>= 2; /* Tempax[0]: VRS[8] */ /* SR35[0]: VRS[8] */ xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x01, Tempax); - Tempcx |= (Tempax << 8); /* Tempcx <= VRS[8:0] */ - Tempcx |= ((Tempbx & 0x80) << 2); /* Tempcx <= VRS[9:0] */ + Tempcx |= Tempax << 8; /* Tempcx <= VRS[8:0] */ + Tempcx |= (Tempbx & 0x80) << 2; /* Tempcx <= VRS[9:0] */ /* Tempax: SR0A */ Tempax = XGI_CRT1Table[index].CR[14]; Tempax &= 0x08; /* SR0A[3] VRS[10] */ - Tempcx |= (Tempax << 7); /* Tempcx <= VRS[10:0] */ + Tempcx |= Tempax << 7; /* Tempcx <= VRS[10:0] */ /* Tempax: CR11 VRE */ Tempax = XGI_CRT1Table[index].CR[11]; @@ -1201,12 +1201,12 @@ static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table, while (table[i].PANELID != 0xff) { tempdx = pVBInfo->LCDResInfo; if (tempbx & 0x0080) { /* OEMUtil */ - tempbx &= (~0x0080); + tempbx &= ~0x0080; tempdx = pVBInfo->LCDTypeInfo; } if (pVBInfo->LCDInfo & EnableScalingLCD) - tempdx &= (~PanelResInfo); + tempdx &= ~PanelResInfo; if (table[i].PANELID == tempdx) { tempbx = table[i].MASK; @@ -1918,7 +1918,7 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex, tempbx |= SetCRT2ToHiVision; if (temp != YPbPrMode1080i) { - tempbx &= (~SetCRT2ToHiVision); + tempbx &= ~SetCRT2ToHiVision; tempbx |= SetCRT2ToYPbPr525750; } } -- cgit v1.2.3 From f9a21a3f4919539e6ee02625c22f67c3ef6041ec Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Fri, 14 Oct 2016 19:00:11 -0300 Subject: staging: greybus: audio_manager_sysfs: Replace sscanf with kstrto* to single variable conversion. Fix checkpatch warning: WARNING: Prefer kstrto to single variable sscanf kstrto* is designed to convert string to numerical value and makes it easier to understand what the code does. Signed-off-by: Elise Lennion Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_manager_sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/audio_manager_sysfs.c b/drivers/staging/greybus/audio_manager_sysfs.c index fc0aca6fe912..c6d82f9d656b 100644 --- a/drivers/staging/greybus/audio_manager_sysfs.c +++ b/drivers/staging/greybus/audio_manager_sysfs.c @@ -44,7 +44,7 @@ static ssize_t manager_sysfs_remove_store( { int id; - int num = sscanf(buf, "%d", &id); + int num = kstrtoint(buf, 10, &id); if (num != 1) return -EINVAL; @@ -65,7 +65,7 @@ static ssize_t manager_sysfs_dump_store( { int id; - int num = sscanf(buf, "%d", &id); + int num = kstrtoint(buf, 10, &id); if (num == 1) { num = gb_audio_manager_dump_module(id); -- cgit v1.2.3 From 7fec2bc90a4ca0bbdedf6724cb539dad23e99070 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 19 Oct 2016 13:44:25 +0100 Subject: staging: greybus: es2: fix arpc request size Fix size field of arpc message request by using the header size and not the pointer size. Signed-off-by: Rui Miguel Silva Reviewed-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/es2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 8eabc713a26d..d7fd4a05f113 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1033,7 +1033,7 @@ static struct arpc *arpc_alloc(void *payload, u16 size, u8 type) goto err_free_req; rpc->req->type = type; - rpc->req->size = cpu_to_le16(sizeof(rpc->req) + size); + rpc->req->size = cpu_to_le16(sizeof(*rpc->req) + size); memcpy(rpc->req->data, payload, size); init_completion(&rpc->response_received); -- cgit v1.2.3 From 73270bb498301d733d5e2679b5638fd071c49ef3 Mon Sep 17 00:00:00 2001 From: Rahul Krishnan Date: Fri, 21 Oct 2016 20:59:28 +0530 Subject: Staging: Greybus: Fix trailing */ in block comments This patch fixes the following checkpath.pl warning WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Rahul Krishnan Acked-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/log.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/log.c b/drivers/staging/greybus/log.c index 70dd9e5a1cf2..1a18ab1ff8aa 100644 --- a/drivers/staging/greybus/log.c +++ b/drivers/staging/greybus/log.c @@ -55,8 +55,10 @@ static int gb_log_request_handler(struct gb_operation *op) /* Ensure the buffer is 0 terminated */ receive->msg[len - 1] = '\0'; - /* Print with dev_dbg() so that it can be easily turned off using - * dynamic debugging (and prevent any DoS) */ + /* + * Print with dev_dbg() so that it can be easily turned off using + * dynamic debugging (and prevent any DoS) + */ dev_dbg(dev, "%s", receive->msg); return 0; -- cgit v1.2.3 From 49b9137a6002a06f7e44e59ece9b34fd1e4fca4c Mon Sep 17 00:00:00 2001 From: Pankaj Bharadiya Date: Mon, 17 Oct 2016 14:42:36 +0530 Subject: staging: greybus: audio: remove redundant slot field gb_audio_manager_module_descriptor's intf_id field maintains the information about the interface on which module is connected hence having an extra slot field is redundant. Thus remove the slot field and its associated code. Signed-off-by: Pankaj Bharadiya Acked-by: Viresh Kumar Reviewed-by: Vaibhav Agarwal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_codec.h | 1 - drivers/staging/greybus/audio_manager.h | 1 - drivers/staging/greybus/audio_manager_module.c | 17 +---------------- drivers/staging/greybus/audio_manager_sysfs.c | 7 +++---- drivers/staging/greybus/audio_module.c | 1 - 5 files changed, 4 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index ca027bd99ad7..62fd93939a1f 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -158,7 +158,6 @@ struct gbaudio_module_info { int dev_id; /* check if it should be bundle_id/hd_cport_id */ int vid; int pid; - int slot; int type; int set_uevent; char vstr[NAME_SIZE]; diff --git a/drivers/staging/greybus/audio_manager.h b/drivers/staging/greybus/audio_manager.h index 056088eb12fe..5ab8f5e0ed3f 100644 --- a/drivers/staging/greybus/audio_manager.h +++ b/drivers/staging/greybus/audio_manager.h @@ -18,7 +18,6 @@ struct gb_audio_manager_module_descriptor { char name[GB_AUDIO_MANAGER_MODULE_NAME_LEN]; - int slot; int vid; int pid; int intf_id; diff --git a/drivers/staging/greybus/audio_manager_module.c b/drivers/staging/greybus/audio_manager_module.c index 2bf40a90368d..adc16977452d 100644 --- a/drivers/staging/greybus/audio_manager_module.c +++ b/drivers/staging/greybus/audio_manager_module.c @@ -81,16 +81,6 @@ static ssize_t gb_audio_module_name_show( static struct gb_audio_manager_module_attribute gb_audio_module_name_attribute = __ATTR(name, 0664, gb_audio_module_name_show, NULL); -static ssize_t gb_audio_module_slot_show( - struct gb_audio_manager_module *module, - struct gb_audio_manager_module_attribute *attr, char *buf) -{ - return sprintf(buf, "%d", module->desc.slot); -} - -static struct gb_audio_manager_module_attribute gb_audio_module_slot_attribute = - __ATTR(slot, 0664, gb_audio_module_slot_show, NULL); - static ssize_t gb_audio_module_vid_show( struct gb_audio_manager_module *module, struct gb_audio_manager_module_attribute *attr, char *buf) @@ -146,7 +136,6 @@ static struct gb_audio_manager_module_attribute static struct attribute *gb_audio_module_default_attrs[] = { &gb_audio_module_name_attribute.attr, - &gb_audio_module_slot_attribute.attr, &gb_audio_module_vid_attribute.attr, &gb_audio_module_pid_attribute.attr, &gb_audio_module_intf_id_attribute.attr, @@ -164,7 +153,6 @@ static struct kobj_type gb_audio_module_type = { static void send_add_uevent(struct gb_audio_manager_module *module) { char name_string[128]; - char slot_string[64]; char vid_string[64]; char pid_string[64]; char intf_id_string[64]; @@ -173,7 +161,6 @@ static void send_add_uevent(struct gb_audio_manager_module *module) char *envp[] = { name_string, - slot_string, vid_string, pid_string, intf_id_string, @@ -183,7 +170,6 @@ static void send_add_uevent(struct gb_audio_manager_module *module) }; snprintf(name_string, 128, "NAME=%s", module->desc.name); - snprintf(slot_string, 64, "SLOT=%d", module->desc.slot); snprintf(vid_string, 64, "VID=%d", module->desc.vid); snprintf(pid_string, 64, "PID=%d", module->desc.pid); snprintf(intf_id_string, 64, "INTF_ID=%d", module->desc.intf_id); @@ -246,10 +232,9 @@ int gb_audio_manager_module_create( void gb_audio_manager_module_dump(struct gb_audio_manager_module *module) { - pr_info("audio module #%d name=%s slot=%d vid=%d pid=%d intf_id=%d i/p devices=0x%X o/p devices=0x%X\n", + pr_info("audio module #%d name=%s vid=%d pid=%d intf_id=%d i/p devices=0x%X o/p devices=0x%X\n", module->id, module->desc.name, - module->desc.slot, module->desc.vid, module->desc.pid, module->desc.intf_id, diff --git a/drivers/staging/greybus/audio_manager_sysfs.c b/drivers/staging/greybus/audio_manager_sysfs.c index c6d82f9d656b..34ebd147052f 100644 --- a/drivers/staging/greybus/audio_manager_sysfs.c +++ b/drivers/staging/greybus/audio_manager_sysfs.c @@ -20,10 +20,9 @@ static ssize_t manager_sysfs_add_store( int num = sscanf(buf, "name=%" GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "s " - "slot=%d vid=%d pid=%d intf_id=%d i/p devices=0x%X" - "o/p devices=0x%X", - desc.name, &desc.slot, &desc.vid, &desc.pid, - &desc.intf_id, &desc.ip_devices, &desc.op_devices); + "vid=%d pid=%d intf_id=%d i/p devices=0x%X o/p devices=0x%X", + desc.name, &desc.vid, &desc.pid, &desc.intf_id, + &desc.ip_devices, &desc.op_devices); if (num != 7) return -EINVAL; diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 45b2519322c3..0269a1d31285 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -345,7 +345,6 @@ static int gb_audio_probe(struct gb_bundle *bundle, dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); /* prepare for the audio manager */ strlcpy(desc.name, gbmodule->name, GB_AUDIO_MANAGER_MODULE_NAME_LEN); - desc.slot = 1; /* todo */ desc.vid = 2; /* todo */ desc.pid = 3; /* todo */ desc.intf_id = gbmodule->dev_id; -- cgit v1.2.3 From c20ea8fd498636b8f7408bf10a305d58a4a05927 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sat, 22 Oct 2016 17:14:42 +0800 Subject: drm/i2c/tda998x: mark symbol static where possible We get 1 warning when building kernel with W=1: drivers/gpu/drm/i2c/tda998x_drv.c:1292:5: warning: no previous prototype for 'tda998x_audio_digital_mute' [-Wmissing-prototypes] In fact, this function is only used in the file in which it is declared and don't need a declaration, but can be made static. So this patch marks this function with 'static'. Signed-off-by: Baoyou Xie Reviewed-by: Arnd Bergmann Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477127682-3615-1-git-send-email-baoyou.xie@linaro.org --- drivers/gpu/drm/i2c/tda998x_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 9798d400d817..af8683e0dd54 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1289,7 +1289,8 @@ static void tda998x_audio_shutdown(struct device *dev, void *data) mutex_unlock(&priv->audio_mutex); } -int tda998x_audio_digital_mute(struct device *dev, void *data, bool enable) +static int +tda998x_audio_digital_mute(struct device *dev, void *data, bool enable) { struct tda998x_priv *priv = dev_get_drvdata(dev); -- cgit v1.2.3 From a5725ab0497ad91a2df7c01a78bf1a0cc5be4526 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sat, 22 Oct 2016 17:17:44 +0800 Subject: drm/msm/adreno: move function declarations to header file We get 2 warnings when building kernel with W=1: drivers/gpu/drm/msm/adreno/a3xx_gpu.c:535:17: warning: no previous prototype for 'a3xx_gpu_init' [-Wmissing-prototypes] drivers/gpu/drm/msm/adreno/a4xx_gpu.c:624:17: warning: no previous prototype for 'a4xx_gpu_init' [-Wmissing-prototypes] In fact, both functions are declared in drivers/gpu/drm/msm/adreno/adreno_device.c, but should be declared in a header file. So this patch moves both function declarations to drivers/gpu/drm/msm/adreno/adreno_gpu.h. Signed-off-by: Baoyou Xie Reviewed-by: Arnd Bergmann Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477127865-9381-1-git-send-email-baoyou.xie@linaro.org --- drivers/gpu/drm/msm/adreno/adreno_device.c | 3 --- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 5127b75dbf40..7250ffc6322f 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -25,9 +25,6 @@ bool hang_debug = false; MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)"); module_param_named(hang_debug, hang_debug, bool, 0600); -struct msm_gpu *a3xx_gpu_init(struct drm_device *dev); -struct msm_gpu *a4xx_gpu_init(struct drm_device *dev); - static const struct adreno_info gpulist[] = { { .rev = ADRENO_REV(3, 0, 5, ANY_ID), diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index a54f6e036b4a..07d99bdf7c99 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -311,4 +311,7 @@ static inline void adreno_gpu_write(struct adreno_gpu *gpu, gpu_write(&gpu->base, reg - 1, data); } +struct msm_gpu *a3xx_gpu_init(struct drm_device *dev); +struct msm_gpu *a4xx_gpu_init(struct drm_device *dev); + #endif /* __ADRENO_GPU_H__ */ -- cgit v1.2.3 From c170a14e20299f600f5d5949933cf3b300fee375 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sat, 22 Oct 2016 17:17:45 +0800 Subject: drm/msm: add missing header dependencies We get 2 warnings when building kernel with W=1: drivers/gpu/drm/msm/msm_debugfs.c:141:5: warning: no previous prototype for 'msm_debugfs_init' [-Wmissing-prototypes] drivers/gpu/drm/msm/msm_debugfs.c:158:6: warning: no previous prototype for 'msm_debugfs_cleanup' [-Wmissing-prototypes] In fact, these functions are declared in drivers/gpu/drm/msm/msm_debugfs.h. So this patch adds missing header dependencies. Signed-off-by: Baoyou Xie Reviewed-by: Arnd Bergmann Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477127865-9381-2-git-send-email-baoyou.xie@linaro.org --- drivers/gpu/drm/msm/msm_debugfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index 663f2b6ef091..3c853733c99a 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -18,6 +18,7 @@ #ifdef CONFIG_DEBUG_FS #include "msm_drv.h" #include "msm_gpu.h" +#include "msm_debugfs.h" static int msm_gpu_show(struct drm_device *dev, struct seq_file *m) { -- cgit v1.2.3 From f233dbca6227703eaae2f67d6d9c79819773f16b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 17:45:59 +0200 Subject: pinctrl: sunxi: Rework the pin config building code In order to support more easily the generic pinctrl properties, rework the pinctrl maps configuration and split it into several sub-functions. One of the side-effects from that rework is that we only parse the pin configuration once, since it's going to be common to every pin, instead of having to parsing once for each pin. Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 178 +++++++++++++++++++++++++--------- 1 file changed, 130 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 0facbea5f465..cf7eb799c6de 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -145,6 +145,110 @@ static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev, return 0; } +static bool sunxi_pctrl_has_bias_prop(struct device_node *node) +{ + return of_find_property(node, "allwinner,pull", NULL); +} + +static bool sunxi_pctrl_has_drive_prop(struct device_node *node) +{ + return of_find_property(node, "allwinner,drive", NULL); +} + +static int sunxi_pctrl_parse_bias_prop(struct device_node *node) +{ + u32 val; + + if (of_property_read_u32(node, "allwinner,pull", &val)) + return -EINVAL; + + switch (val) { + case 1: + return PIN_CONFIG_BIAS_PULL_UP; + case 2: + return PIN_CONFIG_BIAS_PULL_DOWN; + } + + return -EINVAL; +} + +static int sunxi_pctrl_parse_drive_prop(struct device_node *node) +{ + u32 val; + + if (of_property_read_u32(node, "allwinner,drive", &val)) + return -EINVAL; + + return (val + 1) * 10; +} + +static const char *sunxi_pctrl_parse_function_prop(struct device_node *node) +{ + const char *function; + int ret; + + ret = of_property_read_string(node, "allwinner,function", &function); + if (!ret) + return function; + + return NULL; +} + +static const char *sunxi_pctrl_find_pins_prop(struct device_node *node, + int *npins) +{ + int count; + + count = of_property_count_strings(node, "allwinner,pins"); + if (count > 0) { + *npins = count; + return "allwinner,pins"; + } + + return NULL; +} + +static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, + unsigned int *len) +{ + unsigned long *pinconfig; + unsigned int configlen = 0, idx = 0; + + if (sunxi_pctrl_has_drive_prop(node)) + configlen++; + if (sunxi_pctrl_has_bias_prop(node)) + configlen++; + + pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); + if (!pinconfig) + return NULL; + + if (sunxi_pctrl_has_drive_prop(node)) { + int drive = sunxi_pctrl_parse_drive_prop(node); + if (drive < 0) + goto err_free; + + pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, + drive); + } + + if (sunxi_pctrl_has_bias_prop(node)) { + int pull = sunxi_pctrl_parse_bias_prop(node); + if (pull < 0) + goto err_free; + + pinconfig[idx++] = pinconf_to_config_packed(pull, 0); + } + + + *len = configlen; + return pinconfig; + +err_free: + kfree(pinconfig); + return NULL; +} + static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *node, struct pinctrl_map **map, @@ -153,38 +257,45 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); unsigned long *pinconfig; struct property *prop; - const char *function; + const char *function, *pin_prop; const char *group; - int ret, nmaps, i = 0; - u32 val; + int ret, npins, nmaps, configlen = 0, i = 0; *map = NULL; *num_maps = 0; - ret = of_property_read_string(node, "allwinner,function", &function); - if (ret) { - dev_err(pctl->dev, - "missing allwinner,function property in node %s\n", + function = sunxi_pctrl_parse_function_prop(node); + if (!function) { + dev_err(pctl->dev, "missing function property in node %s\n", node->name); return -EINVAL; } - nmaps = of_property_count_strings(node, "allwinner,pins") * 2; - if (nmaps < 0) { - dev_err(pctl->dev, - "missing allwinner,pins property in node %s\n", + pin_prop = sunxi_pctrl_find_pins_prop(node, &npins); + if (!pin_prop) { + dev_err(pctl->dev, "missing pins property in node %s\n", node->name); return -EINVAL; } + /* + * We have two maps for each pin: one for the function, one + * for the configuration (bias, strength, etc) + */ + nmaps = npins * 2; *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); if (!*map) return -ENOMEM; - of_property_for_each_string(node, "allwinner,pins", prop, group) { + pinconfig = sunxi_pctrl_build_pin_config(node, &configlen); + if (!pinconfig) { + ret = -EINVAL; + goto err_free_map; + } + + of_property_for_each_string(node, pin_prop, prop, group) { struct sunxi_pinctrl_group *grp = sunxi_pinctrl_find_group_by_name(pctl, group); - int j = 0, configlen = 0; if (!grp) { dev_err(pctl->dev, "unknown pin %s", group); @@ -207,34 +318,6 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; (*map)[i].data.configs.group_or_pin = group; - - if (of_find_property(node, "allwinner,drive", NULL)) - configlen++; - if (of_find_property(node, "allwinner,pull", NULL)) - configlen++; - - pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); - if (!pinconfig) { - kfree(*map); - return -ENOMEM; - } - - if (!of_property_read_u32(node, "allwinner,drive", &val)) { - u16 strength = (val + 1) * 10; - pinconfig[j++] = - pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, - strength); - } - - if (!of_property_read_u32(node, "allwinner,pull", &val)) { - enum pin_config_param pull = PIN_CONFIG_END; - if (val == 1) - pull = PIN_CONFIG_BIAS_PULL_UP; - else if (val == 2) - pull = PIN_CONFIG_BIAS_PULL_DOWN; - pinconfig[j++] = pinconf_to_config_packed(pull, 0); - } - (*map)[i].data.configs.configs = pinconfig; (*map)[i].data.configs.num_configs = configlen; @@ -244,19 +327,18 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, *num_maps = nmaps; return 0; + +err_free_map: + kfree(map); + return ret; } static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps) { - int i; - - for (i = 0; i < num_maps; i++) { - if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) - kfree(map[i].data.configs.configs); - } - + /* All the maps have the same pin config, free only the first one */ + kfree(map[0].data.configs.configs); kfree(map); } -- cgit v1.2.3 From 42676fa4aa87eda4fc762df495d4bde2ddc4bfce Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 17:46:00 +0200 Subject: pinctrl: sunxi: Use macros from bindings header file for DT parsing Since we have some bindings header for our hardcoded flags, let's use them when we can. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index cf7eb799c6de..62a9d012b35f 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -28,6 +28,8 @@ #include #include +#include + #include "../core.h" #include "pinctrl-sunxi.h" @@ -163,9 +165,9 @@ static int sunxi_pctrl_parse_bias_prop(struct device_node *node) return -EINVAL; switch (val) { - case 1: + case SUN4I_PINCTRL_PULL_UP: return PIN_CONFIG_BIAS_PULL_UP; - case 2: + case SUN4I_PINCTRL_PULL_DOWN: return PIN_CONFIG_BIAS_PULL_DOWN; } -- cgit v1.2.3 From 07fe64ba213f36ca8f6ffd8c4d5893f022744fdb Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 17:46:01 +0200 Subject: pinctrl: sunxi: Handle bias disable So far, putting NO_PULL in allwinner,pull was ignored, behaving like if that property was not there at all. Obviously, this is not the right thing to do, and in that case, we really need to just disable the bias. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 62a9d012b35f..c44bf1320e08 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -165,6 +165,8 @@ static int sunxi_pctrl_parse_bias_prop(struct device_node *node) return -EINVAL; switch (val) { + case SUN4I_PINCTRL_NO_PULL: + return PIN_CONFIG_BIAS_DISABLE; case SUN4I_PINCTRL_PULL_UP: return PIN_CONFIG_BIAS_PULL_UP; case SUN4I_PINCTRL_PULL_DOWN: @@ -401,6 +403,12 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, | dlevel << sunxi_dlevel_offset(pin), pctl->membase + sunxi_dlevel_reg(pin)); break; + case PIN_CONFIG_BIAS_DISABLE: + val = readl(pctl->membase + sunxi_pull_reg(pin)); + mask = PULL_PINS_MASK << sunxi_pull_offset(pin); + writel((val & ~mask), + pctl->membase + sunxi_pull_reg(pin)); + break; case PIN_CONFIG_BIAS_PULL_UP: val = readl(pctl->membase + sunxi_pull_reg(pin)); mask = PULL_PINS_MASK << sunxi_pull_offset(pin); -- cgit v1.2.3 From 93f889b9657ff541417f498c2ee0f69775fe3cef Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 4 Oct 2016 15:41:46 +0200 Subject: pinctrl: oxnas: Move OX810SE specific function and structure as separate Add refactoring to move ox810se specific functions into specific ops structures an add support for the dt match data to get soc specific structures. Signed-off-by: Neil Armstrong Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-oxnas.c | 176 +++++++++++++++++++++++----------------- 1 file changed, 101 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c index 917a7d2535d7..218ad48f455a 100644 --- a/drivers/pinctrl/pinctrl-oxnas.c +++ b/drivers/pinctrl/pinctrl-oxnas.c @@ -37,15 +37,15 @@ #define GPIO_BANK_START(bank) ((bank) * PINS_PER_BANK) -/* Regmap Offsets */ -#define PINMUX_PRIMARY_SEL0 0x0c -#define PINMUX_SECONDARY_SEL0 0x14 -#define PINMUX_TERTIARY_SEL0 0x8c -#define PINMUX_PRIMARY_SEL1 0x10 -#define PINMUX_SECONDARY_SEL1 0x18 -#define PINMUX_TERTIARY_SEL1 0x90 -#define PINMUX_PULLUP_CTRL0 0xac -#define PINMUX_PULLUP_CTRL1 0xb0 +/* OX810 Regmap Offsets */ +#define PINMUX_810_PRIMARY_SEL0 0x0c +#define PINMUX_810_SECONDARY_SEL0 0x14 +#define PINMUX_810_TERTIARY_SEL0 0x8c +#define PINMUX_810_PRIMARY_SEL1 0x10 +#define PINMUX_810_SECONDARY_SEL1 0x18 +#define PINMUX_810_TERTIARY_SEL1 0x90 +#define PINMUX_810_PULLUP_CTRL0 0xac +#define PINMUX_810_PULLUP_CTRL1 0xb0 /* GPIO Registers */ #define INPUT_VALUE 0x00 @@ -87,8 +87,6 @@ struct oxnas_pinctrl { struct regmap *regmap; struct device *dev; struct pinctrl_dev *pctldev; - const struct pinctrl_pin_desc *pins; - unsigned int npins; const struct oxnas_function *functions; unsigned int nfunctions; const struct oxnas_pin_group *groups; @@ -97,7 +95,12 @@ struct oxnas_pinctrl { unsigned int nbanks; }; -static const struct pinctrl_pin_desc oxnas_pins[] = { +struct oxnas_pinctrl_data { + struct pinctrl_desc *desc; + struct oxnas_pinctrl *pctl; +}; + +static const struct pinctrl_pin_desc oxnas_ox810se_pins[] = { PINCTRL_PIN(0, "gpio0"), PINCTRL_PIN(1, "gpio1"), PINCTRL_PIN(2, "gpio2"), @@ -135,7 +138,7 @@ static const struct pinctrl_pin_desc oxnas_pins[] = { PINCTRL_PIN(34, "gpio34"), }; -static const char * const oxnas_fct0_group[] = { +static const char * const oxnas_ox810se_fct0_group[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", @@ -147,7 +150,7 @@ static const char * const oxnas_fct0_group[] = { "gpio32", "gpio33", "gpio34" }; -static const char * const oxnas_fct3_group[] = { +static const char * const oxnas_ox810se_fct3_group[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", "gpio9", @@ -165,9 +168,9 @@ static const char * const oxnas_fct3_group[] = { .ngroups = ARRAY_SIZE(oxnas_##_gr##_group), \ } -static const struct oxnas_function oxnas_functions[] = { - FUNCTION(gpio, fct0), - FUNCTION(fct3, fct3), +static const struct oxnas_function oxnas_ox810se_functions[] = { + FUNCTION(gpio, ox810se_fct0), + FUNCTION(fct3, ox810se_fct3), }; #define OXNAS_PINCTRL_GROUP(_pin, _name, ...) \ @@ -185,7 +188,7 @@ static const struct oxnas_function oxnas_functions[] = { .fct = _fct, \ } -static const struct oxnas_pin_group oxnas_groups[] = { +static const struct oxnas_pin_group oxnas_ox810se_groups[] = { OXNAS_PINCTRL_GROUP(0, gpio0, OXNAS_PINCTRL_FUNCTION(gpio, 0), OXNAS_PINCTRL_FUNCTION(fct3, 3)), @@ -352,8 +355,8 @@ static int oxnas_pinmux_get_function_groups(struct pinctrl_dev *pctldev, return 0; } -static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev, - unsigned int func, unsigned int group) +static int oxnas_ox810se_pinmux_enable(struct pinctrl_dev *pctldev, + unsigned int func, unsigned int group) { struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); const struct oxnas_pin_group *pg = &pctl->groups[group]; @@ -371,22 +374,22 @@ static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev, regmap_write_bits(pctl->regmap, (pg->bank ? - PINMUX_PRIMARY_SEL1 : - PINMUX_PRIMARY_SEL0), + PINMUX_810_PRIMARY_SEL1 : + PINMUX_810_PRIMARY_SEL0), mask, (functions->fct == 1 ? mask : 0)); regmap_write_bits(pctl->regmap, (pg->bank ? - PINMUX_SECONDARY_SEL1 : - PINMUX_SECONDARY_SEL0), + PINMUX_810_SECONDARY_SEL1 : + PINMUX_810_SECONDARY_SEL0), mask, (functions->fct == 2 ? mask : 0)); regmap_write_bits(pctl->regmap, (pg->bank ? - PINMUX_TERTIARY_SEL1 : - PINMUX_TERTIARY_SEL0), + PINMUX_810_TERTIARY_SEL1 : + PINMUX_810_TERTIARY_SEL0), mask, (functions->fct == 3 ? mask : 0)); @@ -402,9 +405,9 @@ static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev, return -EINVAL; } -static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, - unsigned int offset) +static int oxnas_ox810se_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) { struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); struct oxnas_gpio_bank *bank = gpiochip_get_data(range->gc); @@ -415,18 +418,18 @@ static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev, regmap_write_bits(pctl->regmap, (bank->id ? - PINMUX_PRIMARY_SEL1 : - PINMUX_PRIMARY_SEL0), + PINMUX_810_PRIMARY_SEL1 : + PINMUX_810_PRIMARY_SEL0), mask, 0); regmap_write_bits(pctl->regmap, (bank->id ? - PINMUX_SECONDARY_SEL1 : - PINMUX_SECONDARY_SEL0), + PINMUX_810_SECONDARY_SEL1 : + PINMUX_810_SECONDARY_SEL0), mask, 0); regmap_write_bits(pctl->regmap, (bank->id ? - PINMUX_TERTIARY_SEL1 : - PINMUX_TERTIARY_SEL0), + PINMUX_810_TERTIARY_SEL1 : + PINMUX_810_TERTIARY_SEL0), mask, 0); return 0; @@ -498,17 +501,17 @@ static int oxnas_gpio_set_direction(struct pinctrl_dev *pctldev, return 0; } -static const struct pinmux_ops oxnas_pinmux_ops = { +static const struct pinmux_ops oxnas_ox810se_pinmux_ops = { .get_functions_count = oxnas_pinmux_get_functions_count, .get_function_name = oxnas_pinmux_get_function_name, .get_function_groups = oxnas_pinmux_get_function_groups, - .set_mux = oxnas_pinmux_enable, - .gpio_request_enable = oxnas_gpio_request_enable, + .set_mux = oxnas_ox810se_pinmux_enable, + .gpio_request_enable = oxnas_ox810se_gpio_request_enable, .gpio_set_direction = oxnas_gpio_set_direction, }; -static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *config) +static int oxnas_ox810se_pinconf_get(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *config) { struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin); @@ -521,8 +524,8 @@ static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_PULL_UP: ret = regmap_read(pctl->regmap, (bank->id ? - PINMUX_PULLUP_CTRL1 : - PINMUX_PULLUP_CTRL0), + PINMUX_810_PULLUP_CTRL1 : + PINMUX_810_PULLUP_CTRL0), &arg); if (ret) return ret; @@ -538,8 +541,9 @@ static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, return 0; } -static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *configs, unsigned int num_configs) +static int oxnas_ox810se_pinconf_set(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *configs, + unsigned int num_configs) { struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin); @@ -561,8 +565,8 @@ static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, dev_dbg(pctl->dev, " pullup\n"); regmap_write_bits(pctl->regmap, (bank->id ? - PINMUX_PULLUP_CTRL1 : - PINMUX_PULLUP_CTRL0), + PINMUX_810_PULLUP_CTRL1 : + PINMUX_810_PULLUP_CTRL0), mask, mask); break; default: @@ -575,20 +579,12 @@ static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, return 0; } -static const struct pinconf_ops oxnas_pinconf_ops = { - .pin_config_get = oxnas_pinconf_get, - .pin_config_set = oxnas_pinconf_set, +static const struct pinconf_ops oxnas_ox810se_pinconf_ops = { + .pin_config_get = oxnas_ox810se_pinconf_get, + .pin_config_set = oxnas_ox810se_pinconf_set, .is_generic = true, }; -static struct pinctrl_desc oxnas_pinctrl_desc = { - .name = "oxnas-pinctrl", - .pctlops = &oxnas_pinctrl_ops, - .pmxops = &oxnas_pinmux_ops, - .confops = &oxnas_pinconf_ops, - .owner = THIS_MODULE, -}; - static void oxnas_gpio_irq_ack(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); @@ -699,10 +695,51 @@ static struct oxnas_gpio_bank oxnas_gpio_banks[] = { GPIO_BANK(1), }; +static struct oxnas_pinctrl ox810se_pinctrl = { + .functions = oxnas_ox810se_functions, + .nfunctions = ARRAY_SIZE(oxnas_ox810se_functions), + .groups = oxnas_ox810se_groups, + .ngroups = ARRAY_SIZE(oxnas_ox810se_groups), + .gpio_banks = oxnas_gpio_banks, + .nbanks = ARRAY_SIZE(oxnas_gpio_banks), +}; + +static struct pinctrl_desc oxnas_ox810se_pinctrl_desc = { + .name = "oxnas-pinctrl", + .pins = oxnas_ox810se_pins, + .npins = ARRAY_SIZE(oxnas_ox810se_pins), + .pctlops = &oxnas_pinctrl_ops, + .pmxops = &oxnas_ox810se_pinmux_ops, + .confops = &oxnas_ox810se_pinconf_ops, + .owner = THIS_MODULE, +}; + +static struct oxnas_pinctrl_data oxnas_ox810se_pinctrl_data = { + .desc = &oxnas_ox810se_pinctrl_desc, + .pctl = &ox810se_pinctrl, +}; + +static const struct of_device_id oxnas_pinctrl_of_match[] = { + { .compatible = "oxsemi,ox810se-pinctrl", + .data = &oxnas_ox810se_pinctrl_data + }, + { }, +}; + static int oxnas_pinctrl_probe(struct platform_device *pdev) { + const struct of_device_id *id; + const struct oxnas_pinctrl_data *data; struct oxnas_pinctrl *pctl; + id = of_match_node(oxnas_pinctrl_of_match, pdev->dev.of_node); + if (!id) + return -ENODEV; + + data = id->data; + if (!data || !data->pctl || !data->desc) + return -EINVAL; + pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); if (!pctl) return -ENOMEM; @@ -716,20 +753,14 @@ static int oxnas_pinctrl_probe(struct platform_device *pdev) return -ENODEV; } - pctl->pins = oxnas_pins; - pctl->npins = ARRAY_SIZE(oxnas_pins); - pctl->functions = oxnas_functions; - pctl->nfunctions = ARRAY_SIZE(oxnas_functions); - pctl->groups = oxnas_groups; - pctl->ngroups = ARRAY_SIZE(oxnas_groups); - pctl->gpio_banks = oxnas_gpio_banks; - pctl->nbanks = ARRAY_SIZE(oxnas_gpio_banks); + pctl->functions = data->pctl->functions; + pctl->nfunctions = data->pctl->nfunctions; + pctl->groups = data->pctl->groups; + pctl->ngroups = data->pctl->ngroups; + pctl->gpio_banks = data->pctl->gpio_banks; + pctl->nbanks = data->pctl->nbanks; - oxnas_pinctrl_desc.pins = pctl->pins; - oxnas_pinctrl_desc.npins = pctl->npins; - - pctl->pctldev = pinctrl_register(&oxnas_pinctrl_desc, - &pdev->dev, pctl); + pctl->pctldev = pinctrl_register(data->desc, &pdev->dev, pctl); if (IS_ERR(pctl->pctldev)) { dev_err(&pdev->dev, "Failed to register pinctrl device\n"); return PTR_ERR(pctl->pctldev); @@ -805,11 +836,6 @@ static int oxnas_gpio_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id oxnas_pinctrl_of_match[] = { - { .compatible = "oxsemi,ox810se-pinctrl", }, - { }, -}; - static struct platform_driver oxnas_pinctrl_driver = { .driver = { .name = "oxnas-pinctrl", -- cgit v1.2.3 From 4b0c0c25fa7965f859b4489b3670e5a1e36ffab8 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 4 Oct 2016 15:41:47 +0200 Subject: pinctrl: oxnas: Add support for OX820 Add support for the Oxford Semiconductor OX820 which is similar as OX810 but has 50 pins and two registers banks to setup alternate functions. Add specific pins, groups and functions structures. Add DT match data to select corresponding support. Signed-off-by: Neil Armstrong Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-oxnas.c | 433 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 433 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c index 218ad48f455a..494ec9a7573a 100644 --- a/drivers/pinctrl/pinctrl-oxnas.c +++ b/drivers/pinctrl/pinctrl-oxnas.c @@ -47,6 +47,15 @@ #define PINMUX_810_PULLUP_CTRL0 0xac #define PINMUX_810_PULLUP_CTRL1 0xb0 +/* OX820 Regmap Offsets */ +#define PINMUX_820_BANK_OFFSET 0x100000 +#define PINMUX_820_SECONDARY_SEL 0x14 +#define PINMUX_820_TERTIARY_SEL 0x8c +#define PINMUX_820_QUATERNARY_SEL 0x94 +#define PINMUX_820_DEBUG_SEL 0x9c +#define PINMUX_820_ALTERNATIVE_SEL 0xa4 +#define PINMUX_820_PULLUP_CTRL 0xac + /* GPIO Registers */ #define INPUT_VALUE 0x00 #define OUTPUT_EN 0x04 @@ -138,6 +147,59 @@ static const struct pinctrl_pin_desc oxnas_ox810se_pins[] = { PINCTRL_PIN(34, "gpio34"), }; +static const struct pinctrl_pin_desc oxnas_ox820_pins[] = { + PINCTRL_PIN(0, "gpio0"), + PINCTRL_PIN(1, "gpio1"), + PINCTRL_PIN(2, "gpio2"), + PINCTRL_PIN(3, "gpio3"), + PINCTRL_PIN(4, "gpio4"), + PINCTRL_PIN(5, "gpio5"), + PINCTRL_PIN(6, "gpio6"), + PINCTRL_PIN(7, "gpio7"), + PINCTRL_PIN(8, "gpio8"), + PINCTRL_PIN(9, "gpio9"), + PINCTRL_PIN(10, "gpio10"), + PINCTRL_PIN(11, "gpio11"), + PINCTRL_PIN(12, "gpio12"), + PINCTRL_PIN(13, "gpio13"), + PINCTRL_PIN(14, "gpio14"), + PINCTRL_PIN(15, "gpio15"), + PINCTRL_PIN(16, "gpio16"), + PINCTRL_PIN(17, "gpio17"), + PINCTRL_PIN(18, "gpio18"), + PINCTRL_PIN(19, "gpio19"), + PINCTRL_PIN(20, "gpio20"), + PINCTRL_PIN(21, "gpio21"), + PINCTRL_PIN(22, "gpio22"), + PINCTRL_PIN(23, "gpio23"), + PINCTRL_PIN(24, "gpio24"), + PINCTRL_PIN(25, "gpio25"), + PINCTRL_PIN(26, "gpio26"), + PINCTRL_PIN(27, "gpio27"), + PINCTRL_PIN(28, "gpio28"), + PINCTRL_PIN(29, "gpio29"), + PINCTRL_PIN(30, "gpio30"), + PINCTRL_PIN(31, "gpio31"), + PINCTRL_PIN(32, "gpio32"), + PINCTRL_PIN(33, "gpio33"), + PINCTRL_PIN(34, "gpio34"), + PINCTRL_PIN(35, "gpio35"), + PINCTRL_PIN(36, "gpio36"), + PINCTRL_PIN(37, "gpio37"), + PINCTRL_PIN(38, "gpio38"), + PINCTRL_PIN(39, "gpio39"), + PINCTRL_PIN(40, "gpio40"), + PINCTRL_PIN(41, "gpio41"), + PINCTRL_PIN(42, "gpio42"), + PINCTRL_PIN(43, "gpio43"), + PINCTRL_PIN(44, "gpio44"), + PINCTRL_PIN(45, "gpio45"), + PINCTRL_PIN(46, "gpio46"), + PINCTRL_PIN(47, "gpio47"), + PINCTRL_PIN(48, "gpio48"), + PINCTRL_PIN(49, "gpio49"), +}; + static const char * const oxnas_ox810se_fct0_group[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", @@ -161,6 +223,40 @@ static const char * const oxnas_ox810se_fct3_group[] = { "gpio34" }; +static const char * const oxnas_ox820_fct0_group[] = { + "gpio0", "gpio1", "gpio2", "gpio3", + "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", + "gpio12", "gpio13", "gpio14", "gpio15", + "gpio16", "gpio17", "gpio18", "gpio19", + "gpio20", "gpio21", "gpio22", "gpio23", + "gpio24", "gpio25", "gpio26", "gpio27", + "gpio28", "gpio29", "gpio30", "gpio31", + "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", + "gpio40", "gpio41", "gpio42", "gpio43", + "gpio44", "gpio45", "gpio46", "gpio47", + "gpio48", "gpio49" +}; + +static const char * const oxnas_ox820_fct1_group[] = { + "gpio3", "gpio4", + "gpio12", "gpio13", "gpio14", "gpio15", + "gpio16", "gpio17", "gpio18", "gpio19", + "gpio20", "gpio21", "gpio22", "gpio23", + "gpio24" +}; + +static const char * const oxnas_ox820_fct4_group[] = { + "gpio5", "gpio6", "gpio7", "gpio8", + "gpio24", "gpio25", "gpio26", "gpio27", + "gpio40", "gpio41", "gpio42", "gpio43" +}; + +static const char * const oxnas_ox820_fct5_group[] = { + "gpio28", "gpio29", "gpio30", "gpio31" +}; + #define FUNCTION(_name, _gr) \ { \ .name = #_name, \ @@ -173,6 +269,13 @@ static const struct oxnas_function oxnas_ox810se_functions[] = { FUNCTION(fct3, ox810se_fct3), }; +static const struct oxnas_function oxnas_ox820_functions[] = { + FUNCTION(gpio, ox820_fct0), + FUNCTION(fct1, ox820_fct1), + FUNCTION(fct4, ox820_fct4), + FUNCTION(fct5, ox820_fct5), +}; + #define OXNAS_PINCTRL_GROUP(_pin, _name, ...) \ { \ .name = #_name, \ @@ -285,6 +388,140 @@ static const struct oxnas_pin_group oxnas_ox810se_groups[] = { OXNAS_PINCTRL_FUNCTION(fct3, 3)), }; +static const struct oxnas_pin_group oxnas_ox820_groups[] = { + OXNAS_PINCTRL_GROUP(0, gpio0, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(1, gpio1, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(2, gpio2, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(3, gpio3, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(4, gpio4, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(5, gpio5, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(6, gpio6, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(7, gpio7, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(8, gpio8, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(9, gpio9, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(10, gpio10, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(11, gpio11, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(12, gpio12, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(13, gpio13, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(14, gpio14, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(15, gpio15, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(16, gpio16, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(17, gpio17, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(18, gpio18, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(19, gpio19, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(20, gpio20, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(21, gpio21, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(22, gpio22, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(23, gpio23, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1)), + OXNAS_PINCTRL_GROUP(24, gpio24, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct1, 1), + OXNAS_PINCTRL_FUNCTION(fct4, 5)), + OXNAS_PINCTRL_GROUP(25, gpio25, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(26, gpio26, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(27, gpio27, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(28, gpio28, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct5, 5)), + OXNAS_PINCTRL_GROUP(29, gpio29, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct5, 5)), + OXNAS_PINCTRL_GROUP(30, gpio30, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct5, 5)), + OXNAS_PINCTRL_GROUP(31, gpio31, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct5, 5)), + OXNAS_PINCTRL_GROUP(32, gpio32, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(33, gpio33, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(34, gpio34, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(35, gpio35, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(36, gpio36, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(37, gpio37, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(38, gpio38, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(39, gpio39, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(40, gpio40, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(41, gpio41, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(42, gpio42, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(43, gpio43, + OXNAS_PINCTRL_FUNCTION(gpio, 0), + OXNAS_PINCTRL_FUNCTION(fct4, 4)), + OXNAS_PINCTRL_GROUP(44, gpio44, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(45, gpio45, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(46, gpio46, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(47, gpio47, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(48, gpio48, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), + OXNAS_PINCTRL_GROUP(49, gpio49, + OXNAS_PINCTRL_FUNCTION(gpio, 0)), +}; + static inline struct oxnas_gpio_bank *pctl_to_bank(struct oxnas_pinctrl *pctl, unsigned int pin) { @@ -405,6 +642,61 @@ static int oxnas_ox810se_pinmux_enable(struct pinctrl_dev *pctldev, return -EINVAL; } +static int oxnas_ox820_pinmux_enable(struct pinctrl_dev *pctldev, + unsigned int func, unsigned int group) +{ + struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + const struct oxnas_pin_group *pg = &pctl->groups[group]; + const struct oxnas_function *pf = &pctl->functions[func]; + const char *fname = pf->name; + struct oxnas_desc_function *functions = pg->functions; + unsigned int offset = (pg->bank ? PINMUX_820_BANK_OFFSET : 0); + u32 mask = BIT(pg->pin); + + while (functions->name) { + if (!strcmp(functions->name, fname)) { + dev_dbg(pctl->dev, + "setting function %s bank %d pin %d fct %d mask %x\n", + fname, pg->bank, pg->pin, + functions->fct, mask); + + regmap_write_bits(pctl->regmap, + offset + PINMUX_820_SECONDARY_SEL, + mask, + (functions->fct == 1 ? + mask : 0)); + regmap_write_bits(pctl->regmap, + offset + PINMUX_820_TERTIARY_SEL, + mask, + (functions->fct == 2 ? + mask : 0)); + regmap_write_bits(pctl->regmap, + offset + PINMUX_820_QUATERNARY_SEL, + mask, + (functions->fct == 3 ? + mask : 0)); + regmap_write_bits(pctl->regmap, + offset + PINMUX_820_DEBUG_SEL, + mask, + (functions->fct == 4 ? + mask : 0)); + regmap_write_bits(pctl->regmap, + offset + PINMUX_820_ALTERNATIVE_SEL, + mask, + (functions->fct == 5 ? + mask : 0)); + + return 0; + } + + functions++; + } + + dev_err(pctl->dev, "cannot mux pin %u to function %u\n", group, func); + + return -EINVAL; +} + static int oxnas_ox810se_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned int offset) @@ -435,6 +727,37 @@ static int oxnas_ox810se_gpio_request_enable(struct pinctrl_dev *pctldev, return 0; } +static int oxnas_ox820_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct oxnas_gpio_bank *bank = gpiochip_get_data(range->gc); + unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0); + u32 mask = BIT(offset - bank->gpio_chip.base); + + dev_dbg(pctl->dev, "requesting gpio %d in bank %d (id %d) with mask 0x%x\n", + offset, bank->gpio_chip.base, bank->id, mask); + + regmap_write_bits(pctl->regmap, + bank_offset + PINMUX_820_SECONDARY_SEL, + mask, 0); + regmap_write_bits(pctl->regmap, + bank_offset + PINMUX_820_TERTIARY_SEL, + mask, 0); + regmap_write_bits(pctl->regmap, + bank_offset + PINMUX_820_QUATERNARY_SEL, + mask, 0); + regmap_write_bits(pctl->regmap, + bank_offset + PINMUX_820_DEBUG_SEL, + mask, 0); + regmap_write_bits(pctl->regmap, + bank_offset + PINMUX_820_ALTERNATIVE_SEL, + mask, 0); + + return 0; +} + static int oxnas_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { @@ -510,6 +833,15 @@ static const struct pinmux_ops oxnas_ox810se_pinmux_ops = { .gpio_set_direction = oxnas_gpio_set_direction, }; +static const struct pinmux_ops oxnas_ox820_pinmux_ops = { + .get_functions_count = oxnas_pinmux_get_functions_count, + .get_function_name = oxnas_pinmux_get_function_name, + .get_function_groups = oxnas_pinmux_get_function_groups, + .set_mux = oxnas_ox820_pinmux_enable, + .gpio_request_enable = oxnas_ox820_gpio_request_enable, + .gpio_set_direction = oxnas_gpio_set_direction, +}; + static int oxnas_ox810se_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *config) { @@ -541,6 +873,36 @@ static int oxnas_ox810se_pinconf_get(struct pinctrl_dev *pctldev, return 0; } +static int oxnas_ox820_pinconf_get(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *config) +{ + struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin); + unsigned int param = pinconf_to_config_param(*config); + unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0); + u32 mask = BIT(pin - bank->gpio_chip.base); + int ret; + u32 arg; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + ret = regmap_read(pctl->regmap, + bank_offset + PINMUX_820_PULLUP_CTRL, + &arg); + if (ret) + return ret; + + arg = !!(arg & mask); + break; + default: + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + static int oxnas_ox810se_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *configs, unsigned int num_configs) @@ -579,12 +941,55 @@ static int oxnas_ox810se_pinconf_set(struct pinctrl_dev *pctldev, return 0; } +static int oxnas_ox820_pinconf_set(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *configs, + unsigned int num_configs) +{ + struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin); + unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0); + unsigned int param; + u32 arg; + unsigned int i; + u32 offset = pin - bank->gpio_chip.base; + u32 mask = BIT(offset); + + dev_dbg(pctl->dev, "setting pin %d bank %d mask 0x%x\n", + pin, bank->gpio_chip.base, mask); + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + dev_dbg(pctl->dev, " pullup\n"); + regmap_write_bits(pctl->regmap, + bank_offset + PINMUX_820_PULLUP_CTRL, + mask, mask); + break; + default: + dev_err(pctl->dev, "Property %u not supported\n", + param); + return -ENOTSUPP; + } + } + + return 0; +} + static const struct pinconf_ops oxnas_ox810se_pinconf_ops = { .pin_config_get = oxnas_ox810se_pinconf_get, .pin_config_set = oxnas_ox810se_pinconf_set, .is_generic = true, }; +static const struct pinconf_ops oxnas_ox820_pinconf_ops = { + .pin_config_get = oxnas_ox820_pinconf_get, + .pin_config_set = oxnas_ox820_pinconf_set, + .is_generic = true, +}; + static void oxnas_gpio_irq_ack(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); @@ -714,15 +1119,42 @@ static struct pinctrl_desc oxnas_ox810se_pinctrl_desc = { .owner = THIS_MODULE, }; +static struct oxnas_pinctrl ox820_pinctrl = { + .functions = oxnas_ox820_functions, + .nfunctions = ARRAY_SIZE(oxnas_ox820_functions), + .groups = oxnas_ox820_groups, + .ngroups = ARRAY_SIZE(oxnas_ox820_groups), + .gpio_banks = oxnas_gpio_banks, + .nbanks = ARRAY_SIZE(oxnas_gpio_banks), +}; + +static struct pinctrl_desc oxnas_ox820_pinctrl_desc = { + .name = "oxnas-pinctrl", + .pins = oxnas_ox820_pins, + .npins = ARRAY_SIZE(oxnas_ox820_pins), + .pctlops = &oxnas_pinctrl_ops, + .pmxops = &oxnas_ox820_pinmux_ops, + .confops = &oxnas_ox820_pinconf_ops, + .owner = THIS_MODULE, +}; + static struct oxnas_pinctrl_data oxnas_ox810se_pinctrl_data = { .desc = &oxnas_ox810se_pinctrl_desc, .pctl = &ox810se_pinctrl, }; +static struct oxnas_pinctrl_data oxnas_ox820_pinctrl_data = { + .desc = &oxnas_ox820_pinctrl_desc, + .pctl = &ox820_pinctrl, +}; + static const struct of_device_id oxnas_pinctrl_of_match[] = { { .compatible = "oxsemi,ox810se-pinctrl", .data = &oxnas_ox810se_pinctrl_data }, + { .compatible = "oxsemi,ox820-pinctrl", + .data = &oxnas_ox820_pinctrl_data, + }, { }, }; @@ -847,6 +1279,7 @@ static struct platform_driver oxnas_pinctrl_driver = { static const struct of_device_id oxnas_gpio_of_match[] = { { .compatible = "oxsemi,ox810se-gpio", }, + { .compatible = "oxsemi,ox820-gpio", }, { }, }; -- cgit v1.2.3 From cefbf1a1b29531a970bc2908a50a75d6474fcc38 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 20 Oct 2016 15:49:03 +0200 Subject: pinctrl: sunxi: Support generic binding Our bindings are mostly irrelevant now that we have generic pinctrl bindings that cover exactly the same uses cases. Add support for the new ones, and obviously keep our old binding support in order to keep the ABI stable. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 48 +++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index c44bf1320e08..7e27204d3eea 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -149,18 +149,33 @@ static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev, static bool sunxi_pctrl_has_bias_prop(struct device_node *node) { - return of_find_property(node, "allwinner,pull", NULL); + return of_find_property(node, "bias-pull-up", NULL) || + of_find_property(node, "bias-pull-down", NULL) || + of_find_property(node, "bias-disable", NULL) || + of_find_property(node, "allwinner,pull", NULL); } static bool sunxi_pctrl_has_drive_prop(struct device_node *node) { - return of_find_property(node, "allwinner,drive", NULL); + return of_find_property(node, "drive-strength", NULL) || + of_find_property(node, "allwinner,drive", NULL); } static int sunxi_pctrl_parse_bias_prop(struct device_node *node) { u32 val; + /* Try the new style binding */ + if (of_find_property(node, "bias-pull-up", NULL)) + return PIN_CONFIG_BIAS_PULL_UP; + + if (of_find_property(node, "bias-pull-down", NULL)) + return PIN_CONFIG_BIAS_PULL_DOWN; + + if (of_find_property(node, "bias-disable", NULL)) + return PIN_CONFIG_BIAS_DISABLE; + + /* And fall back to the old binding */ if (of_property_read_u32(node, "allwinner,pull", &val)) return -EINVAL; @@ -180,6 +195,21 @@ static int sunxi_pctrl_parse_drive_prop(struct device_node *node) { u32 val; + /* Try the new style binding */ + if (!of_property_read_u32(node, "drive-strength", &val)) { + /* We can't go below 10mA ... */ + if (val < 10) + return -EINVAL; + + /* ... and only up to 40 mA ... */ + if (val > 40) + val = 40; + + /* by steps of 10 mA */ + return rounddown(val, 10); + } + + /* And then fall back to the old binding */ if (of_property_read_u32(node, "allwinner,drive", &val)) return -EINVAL; @@ -191,6 +221,12 @@ static const char *sunxi_pctrl_parse_function_prop(struct device_node *node) const char *function; int ret; + /* Try the generic binding */ + ret = of_property_read_string(node, "function", &function); + if (!ret) + return function; + + /* And fall back to our legacy one */ ret = of_property_read_string(node, "allwinner,function", &function); if (!ret) return function; @@ -203,6 +239,14 @@ static const char *sunxi_pctrl_find_pins_prop(struct device_node *node, { int count; + /* Try the generic binding */ + count = of_property_count_strings(node, "pins"); + if (count > 0) { + *npins = count; + return "pins"; + } + + /* And fall back to our legacy one */ count = of_property_count_strings(node, "allwinner,pins"); if (count > 0) { *npins = count; -- cgit v1.2.3 From 9e80f9064e73f9f82679884ddf8b03ac3606cf4a Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 21 Oct 2016 11:09:58 +0200 Subject: pinctrl: Add SX150X GPIO Extender Pinctrl Driver Since the I2C sx150x GPIO expander driver uses platform_data to manage the pins configurations, rewrite the driver as a pinctrl driver using pinconf to get/set pin configurations from DT or debugfs. The pinctrl driver is functionnally equivalent as the gpio-only driver and can use DT for pinconf. The platform_data confirmation is dropped. This patchset removed the gpio-only driver and selects the Pinctrl driver config instead. This patchset also migrates the gpio dt-bindings to pinctrl and add the pinctrl optional properties. The driver was tested with a SX1509 device on a BeagleBone black with interrupt support and on an X86_64 machine over an I2C to USB converter. This is a fixed version that builds and runs on non-OF platforms and on arm based OF. The GPIO version is removed and the bindings are also moved to the pinctrl bindings. Changes since v2 - rebased on v4.9-rc1 - removed MODULE_DEVICE_TABLE as in upstream bb411e771b0e ("gpio: sx150x: fix implicit assumption module.h is present") Changes since v1 - Fix Kconfig descriptions on pinctrl and gpio - Fix Kconfig dependency - Remove oscio support for non-789 devices - correct typo in dt bindings - remove probe reset for non-789 devices Changes since RFC - Put #ifdef CONFIG_OF/CONFIG_OF_GPIO to remove OF code for non-of platforms - No more rely on OF_GPIO config - Moved and enhanced bindings to pinctrl bindings - Removed gpio-sx150x.c - Temporary select PINCTRL_SX150X when GPIO_SX150X - Temporary mark GPIO_SX150X as deprecated Signed-off-by: Neil Armstrong Tested-by: Peter Rosin Acked-by: Rob Herring ested-by: Andrey Smirnov Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-sx150x.txt | 41 - .../devicetree/bindings/pinctrl/pinctrl-sx150x.txt | 69 ++ drivers/gpio/Kconfig | 13 +- drivers/gpio/Makefile | 1 - drivers/gpio/gpio-sx150x.c | 792 --------------- drivers/pinctrl/Kconfig | 14 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-sx150x.c | 1062 ++++++++++++++++++++ 8 files changed, 1151 insertions(+), 842 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/gpio-sx150x.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt delete mode 100644 drivers/gpio/gpio-sx150x.c create mode 100644 drivers/pinctrl/pinctrl-sx150x.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt b/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt deleted file mode 100644 index c809acb9c71b..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt +++ /dev/null @@ -1,41 +0,0 @@ -SEMTECH SX150x GPIO expander bindings - - -Required properties: - -- compatible: should be "semtech,sx1506q", - "semtech,sx1508q", - "semtech,sx1509q", - "semtech,sx1502q". - -- reg: The I2C slave address for this device. - -- interrupt-parent: phandle of the parent interrupt controller. - -- interrupts: Interrupt specifier for the controllers interrupt. - -- #gpio-cells: Should be 2. The first cell is the GPIO number and the - second cell is used to specify optional parameters: - bit 0: polarity (0: normal, 1: inverted) - -- gpio-controller: Marks the device as a GPIO controller. - -- interrupt-controller: Marks the device as a interrupt controller. - -The GPIO expander can optionally be used as an interrupt controller, in -which case it uses the default two cell specifier as described in -Documentation/devicetree/bindings/interrupt-controller/interrupts.txt. - -Example: - - i2c_gpio_expander@20{ - #gpio-cells = <2>; - #interrupt-cells = <2>; - compatible = "semtech,sx1506q"; - reg = <0x20>; - interrupt-parent = <&gpio_1>; - interrupts = <16 0>; - - gpio-controller; - interrupt-controller; - }; diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt new file mode 100644 index 000000000000..c293c8aaac73 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt @@ -0,0 +1,69 @@ +SEMTECH SX150x GPIO expander bindings + +Please refer to pinctrl-bindings.txt, ../gpio/gpio.txt, and +../interrupt-controller/interrupts.txt for generic information regarding +pin controller, GPIO, and interrupt bindings. + +Required properties: +- compatible: should be one of : + "semtech,sx1506q", + "semtech,sx1508q", + "semtech,sx1509q", + "semtech,sx1502q". + +- reg: The I2C slave address for this device. + +- #gpio-cells: Should be 2. The first cell is the GPIO number and the + second cell is used to specify optional parameters: + bit 0: polarity (0: normal, 1: inverted) + +- gpio-controller: Marks the device as a GPIO controller. + +Optional properties : +- interrupt-parent: phandle of the parent interrupt controller. + +- interrupts: Interrupt specifier for the controllers interrupt. + +- interrupt-controller: Marks the device as a interrupt controller. + +- semtech,probe-reset: Will trigger a reset of the GPIO expander on probe, + only for sx1508q and sx1509q + +The GPIO expander can optionally be used as an interrupt controller, in +which case it uses the default two cell specifier. + +Required properties for pin configuration sub-nodes: + - pins: List of pins to which the configuration applies. + +Optional properties for pin configuration sub-nodes: +---------------------------------------------------- + - bias-disable: disable any pin bias, except the OSCIO pin + - bias-pull-up: pull up the pin, except the OSCIO pin + - bias-pull-down: pull down the pin, except the OSCIO pin + - bias-pull-pin-default: use pin-default pull state, except the OSCIO pin + - drive-push-pull: drive actively high and low + - drive-open-drain: drive with open drain only for sx1508q and sx1509q and except the OSCIO pin + - output-low: set the pin to output mode with low level + - output-high: set the pin to output mode with high level + +Example: + + i2c0gpio-expander@20{ + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "semtech,sx1506q"; + reg = <0x20>; + interrupt-parent = <&gpio_1>; + interrupts = <16 0>; + + gpio-controller; + interrupt-controller; + + pinctrl-names = "default"; + pinctrl-0 = <&gpio1_cfg_pins>; + + gpio1_cfg_pins: gpio1-cfg { + pins = "gpio1"; + bias-pull-up; + }; + }; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 26ee00f6bd58..db3f7aab4160 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -781,16 +781,13 @@ config GPIO_PCF857X platform-neutral GPIO calls. config GPIO_SX150X - bool "Semtech SX150x I2C GPIO expander" - depends on I2C=y - select GPIOLIB_IRQCHIP + bool "Semtech SX150x I2C GPIO expander (deprecated)" + depends on PINCTRL && I2C=y + select PINCTRL_SX150X default n help - Say yes here to provide support for Semtech SX150-series I2C - GPIO expanders. Compatible models include: - - 8 bits: sx1508q - 16 bits: sx1509q + Say yes here to provide support for Semtech SX150x-series I2C + GPIO expanders. The GPIO driver was replaced by a Pinctrl version. config GPIO_TPIC2810 tristate "TPIC2810 8-Bit I2C GPO expander" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ab28a2daeacc..76c7af6c5839 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -102,7 +102,6 @@ obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o -obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c deleted file mode 100644 index af95de89db01..000000000000 --- a/drivers/gpio/gpio-sx150x.c +++ /dev/null @@ -1,792 +0,0 @@ -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. - * - * Driver for Semtech SX150X I2C GPIO Expanders - * - * Author: Gregory Bean - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NO_UPDATE_PENDING -1 - -/* The chip models of sx150x */ -#define SX150X_123 0 -#define SX150X_456 1 -#define SX150X_789 2 - -struct sx150x_123_pri { - u8 reg_pld_mode; - u8 reg_pld_table0; - u8 reg_pld_table1; - u8 reg_pld_table2; - u8 reg_pld_table3; - u8 reg_pld_table4; - u8 reg_advance; -}; - -struct sx150x_456_pri { - u8 reg_pld_mode; - u8 reg_pld_table0; - u8 reg_pld_table1; - u8 reg_pld_table2; - u8 reg_pld_table3; - u8 reg_pld_table4; - u8 reg_advance; -}; - -struct sx150x_789_pri { - u8 reg_drain; - u8 reg_polarity; - u8 reg_clock; - u8 reg_misc; - u8 reg_reset; - u8 ngpios; -}; - -struct sx150x_device_data { - u8 model; - u8 reg_pullup; - u8 reg_pulldn; - u8 reg_dir; - u8 reg_data; - u8 reg_irq_mask; - u8 reg_irq_src; - u8 reg_sense; - u8 ngpios; - union { - struct sx150x_123_pri x123; - struct sx150x_456_pri x456; - struct sx150x_789_pri x789; - } pri; -}; - -/** - * struct sx150x_platform_data - config data for SX150x driver - * @gpio_base: The index number of the first GPIO assigned to this - * GPIO expander. The expander will create a block of - * consecutively numbered gpios beginning at the given base, - * with the size of the block depending on the model of the - * expander chip. - * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO - * instead of as an oscillator, increasing the size of the - * GP(I)O pool created by this expander by one. The - * output-only GPO pin will be added at the end of the block. - * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor - * for each IO line in the expander. Setting the bit at - * position n will enable the pull-up for the IO at - * the corresponding offset. For chips with fewer than - * 16 IO pins, high-end bits are ignored. - * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down - * resistor for each IO line in the expander. Setting the - * bit at position n will enable the pull-down for the IO at - * the corresponding offset. For chips with fewer than - * 16 IO pins, high-end bits are ignored. - * @io_polarity: A bit-mask which enables polarity inversion for each IO line - * in the expander. Setting the bit at position n inverts - * the polarity of that IO line, while clearing it results - * in normal polarity. For chips with fewer than 16 IO pins, - * high-end bits are ignored. - * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line - * is connected, via which it reports interrupt events - * across all GPIO lines. This must be a real, - * pre-existing IRQ line. - * Setting this value < 0 disables the irq_chip functionality - * of the driver. - * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based - * IRQ lines will appear. Similarly to gpio_base, the expander - * will create a block of irqs beginning at this number. - * This value is ignored if irq_summary is < 0. - * @reset_during_probe: If set to true, the driver will trigger a full - * reset of the chip at the beginning of the probe - * in order to place it in a known state. - */ -struct sx150x_platform_data { - unsigned gpio_base; - bool oscio_is_gpo; - u16 io_pullup_ena; - u16 io_pulldn_ena; - u16 io_polarity; - int irq_summary; - unsigned irq_base; - bool reset_during_probe; -}; - -struct sx150x_chip { - struct gpio_chip gpio_chip; - struct i2c_client *client; - const struct sx150x_device_data *dev_cfg; - int irq_summary; - int irq_base; - int irq_update; - u32 irq_sense; - u32 irq_masked; - u32 dev_sense; - u32 dev_masked; - struct irq_chip irq_chip; - struct mutex lock; -}; - -static const struct sx150x_device_data sx150x_devices[] = { - [0] = { /* sx1508q */ - .model = SX150X_789, - .reg_pullup = 0x03, - .reg_pulldn = 0x04, - .reg_dir = 0x07, - .reg_data = 0x08, - .reg_irq_mask = 0x09, - .reg_irq_src = 0x0c, - .reg_sense = 0x0b, - .pri.x789 = { - .reg_drain = 0x05, - .reg_polarity = 0x06, - .reg_clock = 0x0f, - .reg_misc = 0x10, - .reg_reset = 0x7d, - }, - .ngpios = 8, - }, - [1] = { /* sx1509q */ - .model = SX150X_789, - .reg_pullup = 0x07, - .reg_pulldn = 0x09, - .reg_dir = 0x0f, - .reg_data = 0x11, - .reg_irq_mask = 0x13, - .reg_irq_src = 0x19, - .reg_sense = 0x17, - .pri.x789 = { - .reg_drain = 0x0b, - .reg_polarity = 0x0d, - .reg_clock = 0x1e, - .reg_misc = 0x1f, - .reg_reset = 0x7d, - }, - .ngpios = 16 - }, - [2] = { /* sx1506q */ - .model = SX150X_456, - .reg_pullup = 0x05, - .reg_pulldn = 0x07, - .reg_dir = 0x03, - .reg_data = 0x01, - .reg_irq_mask = 0x09, - .reg_irq_src = 0x0f, - .reg_sense = 0x0d, - .pri.x456 = { - .reg_pld_mode = 0x21, - .reg_pld_table0 = 0x23, - .reg_pld_table1 = 0x25, - .reg_pld_table2 = 0x27, - .reg_pld_table3 = 0x29, - .reg_pld_table4 = 0x2b, - .reg_advance = 0xad, - }, - .ngpios = 16 - }, - [3] = { /* sx1502q */ - .model = SX150X_123, - .reg_pullup = 0x02, - .reg_pulldn = 0x03, - .reg_dir = 0x01, - .reg_data = 0x00, - .reg_irq_mask = 0x05, - .reg_irq_src = 0x08, - .reg_sense = 0x07, - .pri.x123 = { - .reg_pld_mode = 0x10, - .reg_pld_table0 = 0x11, - .reg_pld_table1 = 0x12, - .reg_pld_table2 = 0x13, - .reg_pld_table3 = 0x14, - .reg_pld_table4 = 0x15, - .reg_advance = 0xad, - }, - .ngpios = 8, - }, -}; - -static const struct i2c_device_id sx150x_id[] = { - {"sx1508q", 0}, - {"sx1509q", 1}, - {"sx1506q", 2}, - {"sx1502q", 3}, - {} -}; - -static const struct of_device_id sx150x_of_match[] = { - { .compatible = "semtech,sx1508q" }, - { .compatible = "semtech,sx1509q" }, - { .compatible = "semtech,sx1506q" }, - { .compatible = "semtech,sx1502q" }, - {}, -}; - -static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) -{ - s32 err = i2c_smbus_write_byte_data(client, reg, val); - - if (err < 0) - dev_warn(&client->dev, - "i2c write fail: can't write %02x to %02x: %d\n", - val, reg, err); - return err; -} - -static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) -{ - s32 err = i2c_smbus_read_byte_data(client, reg); - - if (err >= 0) - *val = err; - else - dev_warn(&client->dev, - "i2c read fail: can't read from %02x: %d\n", - reg, err); - return err; -} - -static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset) -{ - return (chip->dev_cfg->ngpios == offset); -} - -/* - * These utility functions solve the common problem of locating and setting - * configuration bits. Configuration bits are grouped into registers - * whose indexes increase downwards. For example, with eight-bit registers, - * sixteen gpios would have their config bits grouped in the following order: - * REGISTER N-1 [ f e d c b a 9 8 ] - * N [ 7 6 5 4 3 2 1 0 ] - * - * For multi-bit configurations, the pattern gets wider: - * REGISTER N-3 [ f f e e d d c c ] - * N-2 [ b b a a 9 9 8 8 ] - * N-1 [ 7 7 6 6 5 5 4 4 ] - * N [ 3 3 2 2 1 1 0 0 ] - * - * Given the address of the starting register 'N', the index of the gpio - * whose configuration we seek to change, and the width in bits of that - * configuration, these functions allow us to locate the correct - * register and mask the correct bits. - */ -static inline void sx150x_find_cfg(u8 offset, u8 width, - u8 *reg, u8 *mask, u8 *shift) -{ - *reg -= offset * width / 8; - *mask = (1 << width) - 1; - *shift = (offset * width) % 8; - *mask <<= *shift; -} - -static s32 sx150x_write_cfg(struct sx150x_chip *chip, - u8 offset, u8 width, u8 reg, u8 val) -{ - u8 mask; - u8 data; - u8 shift; - s32 err; - - sx150x_find_cfg(offset, width, ®, &mask, &shift); - err = sx150x_i2c_read(chip->client, reg, &data); - if (err < 0) - return err; - - data &= ~mask; - data |= (val << shift) & mask; - return sx150x_i2c_write(chip->client, reg, data); -} - -static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset) -{ - u8 reg = chip->dev_cfg->reg_data; - u8 mask; - u8 data; - u8 shift; - s32 err; - - sx150x_find_cfg(offset, 1, ®, &mask, &shift); - err = sx150x_i2c_read(chip->client, reg, &data); - if (err >= 0) - err = (data & mask) != 0 ? 1 : 0; - - return err; -} - -static void sx150x_set_oscio(struct sx150x_chip *chip, int val) -{ - sx150x_i2c_write(chip->client, - chip->dev_cfg->pri.x789.reg_clock, - (val ? 0x1f : 0x10)); -} - -static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val) -{ - sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_data, - (val ? 1 : 0)); -} - -static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset) -{ - return sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_dir, - 1); -} - -static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val) -{ - int err; - - err = sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_data, - (val ? 1 : 0)); - if (err >= 0) - err = sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_dir, - 0); - return err; -} - -static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - int status = -EINVAL; - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_get_io(chip, offset); - mutex_unlock(&chip->lock); - } - - return (status < 0) ? status : !!status; -} - -static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - - mutex_lock(&chip->lock); - if (offset_is_oscio(chip, offset)) - sx150x_set_oscio(chip, val); - else - sx150x_set_io(chip, offset, val); - mutex_unlock(&chip->lock); -} - -static int sx150x_gpio_set_single_ended(struct gpio_chip *gc, - unsigned offset, - enum single_ended_mode mode) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - - /* On the SX160X 789 we can set open drain */ - if (chip->dev_cfg->model != SX150X_789) - return -ENOTSUPP; - - if (mode == LINE_MODE_PUSH_PULL) - return sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->pri.x789.reg_drain, - 0); - - if (mode == LINE_MODE_OPEN_DRAIN) - return sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->pri.x789.reg_drain, - 1); - return -ENOTSUPP; -} - -static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - int status = -EINVAL; - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_io_input(chip, offset); - mutex_unlock(&chip->lock); - } - return status; -} - -static int sx150x_gpio_direction_output(struct gpio_chip *gc, - unsigned offset, - int val) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - int status = 0; - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_io_output(chip, offset, val); - mutex_unlock(&chip->lock); - } - return status; -} - -static void sx150x_irq_mask(struct irq_data *d) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned n = d->hwirq; - - chip->irq_masked |= (1 << n); - chip->irq_update = n; -} - -static void sx150x_irq_unmask(struct irq_data *d) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned n = d->hwirq; - - chip->irq_masked &= ~(1 << n); - chip->irq_update = n; -} - -static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned n, val = 0; - - if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) - return -EINVAL; - - n = d->hwirq; - - if (flow_type & IRQ_TYPE_EDGE_RISING) - val |= 0x1; - if (flow_type & IRQ_TYPE_EDGE_FALLING) - val |= 0x2; - - chip->irq_sense &= ~(3UL << (n * 2)); - chip->irq_sense |= val << (n * 2); - chip->irq_update = n; - return 0; -} - -static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) -{ - struct sx150x_chip *chip = (struct sx150x_chip *)dev_id; - unsigned nhandled = 0; - unsigned sub_irq; - unsigned n; - s32 err; - u8 val; - int i; - - for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) { - err = sx150x_i2c_read(chip->client, - chip->dev_cfg->reg_irq_src - i, - &val); - if (err < 0) - continue; - - sx150x_i2c_write(chip->client, - chip->dev_cfg->reg_irq_src - i, - val); - for (n = 0; n < 8; ++n) { - if (val & (1 << n)) { - sub_irq = irq_find_mapping( - chip->gpio_chip.irqdomain, - (i * 8) + n); - handle_nested_irq(sub_irq); - ++nhandled; - } - } - } - - return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); -} - -static void sx150x_irq_bus_lock(struct irq_data *d) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - - mutex_lock(&chip->lock); -} - -static void sx150x_irq_bus_sync_unlock(struct irq_data *d) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned n; - - if (chip->irq_update == NO_UPDATE_PENDING) - goto out; - - n = chip->irq_update; - chip->irq_update = NO_UPDATE_PENDING; - - /* Avoid updates if nothing changed */ - if (chip->dev_sense == chip->irq_sense && - chip->dev_masked == chip->irq_masked) - goto out; - - chip->dev_sense = chip->irq_sense; - chip->dev_masked = chip->irq_masked; - - if (chip->irq_masked & (1 << n)) { - sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); - sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); - } else { - sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); - sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, - chip->irq_sense >> (n * 2)); - } -out: - mutex_unlock(&chip->lock); -} - -static void sx150x_init_chip(struct sx150x_chip *chip, - struct i2c_client *client, - kernel_ulong_t driver_data, - struct sx150x_platform_data *pdata) -{ - mutex_init(&chip->lock); - - chip->client = client; - chip->dev_cfg = &sx150x_devices[driver_data]; - chip->gpio_chip.parent = &client->dev; - chip->gpio_chip.label = client->name; - chip->gpio_chip.direction_input = sx150x_gpio_direction_input; - chip->gpio_chip.direction_output = sx150x_gpio_direction_output; - chip->gpio_chip.get = sx150x_gpio_get; - chip->gpio_chip.set = sx150x_gpio_set; - chip->gpio_chip.set_single_ended = sx150x_gpio_set_single_ended; - chip->gpio_chip.base = pdata->gpio_base; - chip->gpio_chip.can_sleep = true; - chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; -#ifdef CONFIG_OF_GPIO - chip->gpio_chip.of_node = client->dev.of_node; - chip->gpio_chip.of_gpio_n_cells = 2; -#endif - if (pdata->oscio_is_gpo) - ++chip->gpio_chip.ngpio; - - chip->irq_chip.name = client->name; - chip->irq_chip.irq_mask = sx150x_irq_mask; - chip->irq_chip.irq_unmask = sx150x_irq_unmask; - chip->irq_chip.irq_set_type = sx150x_irq_set_type; - chip->irq_chip.irq_bus_lock = sx150x_irq_bus_lock; - chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock; - chip->irq_summary = -1; - chip->irq_base = -1; - chip->irq_masked = ~0; - chip->irq_sense = 0; - chip->dev_masked = ~0; - chip->dev_sense = 0; - chip->irq_update = NO_UPDATE_PENDING; -} - -static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) -{ - int err = 0; - unsigned n; - - for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n) - err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8)); - return err; -} - -static int sx150x_reset(struct sx150x_chip *chip) -{ - int err; - - err = i2c_smbus_write_byte_data(chip->client, - chip->dev_cfg->pri.x789.reg_reset, - 0x12); - if (err < 0) - return err; - - err = i2c_smbus_write_byte_data(chip->client, - chip->dev_cfg->pri.x789.reg_reset, - 0x34); - return err; -} - -static int sx150x_init_hw(struct sx150x_chip *chip, - struct sx150x_platform_data *pdata) -{ - int err = 0; - - if (pdata->reset_during_probe) { - err = sx150x_reset(chip); - if (err < 0) - return err; - } - - if (chip->dev_cfg->model == SX150X_789) - err = sx150x_i2c_write(chip->client, - chip->dev_cfg->pri.x789.reg_misc, - 0x01); - else if (chip->dev_cfg->model == SX150X_456) - err = sx150x_i2c_write(chip->client, - chip->dev_cfg->pri.x456.reg_advance, - 0x04); - else - err = sx150x_i2c_write(chip->client, - chip->dev_cfg->pri.x123.reg_advance, - 0x00); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup, - pdata->io_pullup_ena); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn, - pdata->io_pulldn_ena); - if (err < 0) - return err; - - if (chip->dev_cfg->model == SX150X_789) { - err = sx150x_init_io(chip, - chip->dev_cfg->pri.x789.reg_polarity, - pdata->io_polarity); - if (err < 0) - return err; - } else if (chip->dev_cfg->model == SX150X_456) { - /* Set all pins to work in normal mode */ - err = sx150x_init_io(chip, - chip->dev_cfg->pri.x456.reg_pld_mode, - 0); - if (err < 0) - return err; - } else { - /* Set all pins to work in normal mode */ - err = sx150x_init_io(chip, - chip->dev_cfg->pri.x123.reg_pld_mode, - 0); - if (err < 0) - return err; - } - - - if (pdata->oscio_is_gpo) - sx150x_set_oscio(chip, 0); - - return err; -} - -static int sx150x_install_irq_chip(struct sx150x_chip *chip, - int irq_summary, - int irq_base) -{ - int err; - - chip->irq_summary = irq_summary; - chip->irq_base = irq_base; - - /* Add gpio chip to irq subsystem */ - err = gpiochip_irqchip_add(&chip->gpio_chip, - &chip->irq_chip, chip->irq_base, - handle_edge_irq, IRQ_TYPE_EDGE_BOTH); - if (err) { - dev_err(&chip->client->dev, - "could not connect irqchip to gpiochip\n"); - return err; - } - - err = devm_request_threaded_irq(&chip->client->dev, - irq_summary, NULL, sx150x_irq_thread_fn, - IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING, - chip->irq_chip.name, chip); - if (err < 0) { - chip->irq_summary = -1; - chip->irq_base = -1; - } - - return err; -} - -static int sx150x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WRITE_WORD_DATA; - struct sx150x_platform_data *pdata; - struct sx150x_chip *chip; - int rc; - - pdata = dev_get_platdata(&client->dev); - if (!pdata) - return -EINVAL; - - if (!i2c_check_functionality(client->adapter, i2c_funcs)) - return -ENOSYS; - - chip = devm_kzalloc(&client->dev, - sizeof(struct sx150x_chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - sx150x_init_chip(chip, client, id->driver_data, pdata); - rc = sx150x_init_hw(chip, pdata); - if (rc < 0) - return rc; - - rc = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip); - if (rc) - return rc; - - if (pdata->irq_summary >= 0) { - rc = sx150x_install_irq_chip(chip, - pdata->irq_summary, - pdata->irq_base); - if (rc < 0) - return rc; - } - - i2c_set_clientdata(client, chip); - - return 0; -} - -static struct i2c_driver sx150x_driver = { - .driver = { - .name = "sx150x", - .of_match_table = of_match_ptr(sx150x_of_match), - }, - .probe = sx150x_probe, - .id_table = sx150x_id, -}; - -static int __init sx150x_init(void) -{ - return i2c_add_driver(&sx150x_driver); -} -subsys_initcall(sx150x_init); diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 0e75d94972ba..801fa8bb05e1 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -164,6 +164,20 @@ config PINCTRL_SIRF select GENERIC_PINCONF select GPIOLIB_IRQCHIP +config PINCTRL_SX150X + bool "Semtech SX150x I2C GPIO expander pinctrl driver" + depends on GPIOLIB && I2C=y + select PINMUX + select PINCONF + select GENERIC_PINCONF + select GPIOLIB_IRQCHIP + help + Say yes here to provide support for Semtech SX150x-series I2C + GPIO expanders as pinctrl module. + Compatible models include: + - 8 bits: sx1508q, sx1502q + - 16 bits: sx1509q, sx1506q + config PINCTRL_PISTACHIO def_bool y if MACH_PISTACHIO depends on GPIOLIB diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 11bad373dfe0..3b8e6f726acb 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_SIRF) += sirf/ +obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c new file mode 100644 index 000000000000..d2d4211e615e --- /dev/null +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -0,0 +1,1062 @@ +/* + * Copyright (c) 2016, BayLibre, SAS. All rights reserved. + * Author: Neil Armstrong + * + * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * Driver for Semtech SX150X I2C GPIO Expanders + * + * Author: Gregory Bean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "pinconf.h" +#include "pinctrl-utils.h" + +/* The chip models of sx150x */ +enum { + SX150X_123 = 0, + SX150X_456, + SX150X_789, +}; + +struct sx150x_123_pri { + u8 reg_pld_mode; + u8 reg_pld_table0; + u8 reg_pld_table1; + u8 reg_pld_table2; + u8 reg_pld_table3; + u8 reg_pld_table4; + u8 reg_advance; +}; + +struct sx150x_456_pri { + u8 reg_pld_mode; + u8 reg_pld_table0; + u8 reg_pld_table1; + u8 reg_pld_table2; + u8 reg_pld_table3; + u8 reg_pld_table4; + u8 reg_advance; +}; + +struct sx150x_789_pri { + u8 reg_drain; + u8 reg_polarity; + u8 reg_clock; + u8 reg_misc; + u8 reg_reset; + u8 ngpios; +}; + +struct sx150x_device_data { + u8 model; + u8 reg_pullup; + u8 reg_pulldn; + u8 reg_dir; + u8 reg_data; + u8 reg_irq_mask; + u8 reg_irq_src; + u8 reg_sense; + u8 ngpios; + union { + struct sx150x_123_pri x123; + struct sx150x_456_pri x456; + struct sx150x_789_pri x789; + } pri; + const struct pinctrl_pin_desc *pins; + unsigned int npins; +}; + +struct sx150x_pinctrl { + struct device *dev; + struct i2c_client *client; + struct pinctrl_dev *pctldev; + struct pinctrl_desc pinctrl_desc; + struct gpio_chip gpio; + struct irq_chip irq_chip; + struct { + int update; + u32 sense; + u32 masked; + u32 dev_sense; + u32 dev_masked; + } irq; + struct mutex lock; + const struct sx150x_device_data *data; +}; + +static const struct pinctrl_pin_desc sx150x_8_pins[] = { + PINCTRL_PIN(0, "gpio0"), + PINCTRL_PIN(1, "gpio1"), + PINCTRL_PIN(2, "gpio2"), + PINCTRL_PIN(3, "gpio3"), + PINCTRL_PIN(4, "gpio4"), + PINCTRL_PIN(5, "gpio5"), + PINCTRL_PIN(6, "gpio6"), + PINCTRL_PIN(7, "gpio7"), + PINCTRL_PIN(8, "oscio"), +}; + +static const struct pinctrl_pin_desc sx150x_16_pins[] = { + PINCTRL_PIN(0, "gpio0"), + PINCTRL_PIN(1, "gpio1"), + PINCTRL_PIN(2, "gpio2"), + PINCTRL_PIN(3, "gpio3"), + PINCTRL_PIN(4, "gpio4"), + PINCTRL_PIN(5, "gpio5"), + PINCTRL_PIN(6, "gpio6"), + PINCTRL_PIN(7, "gpio7"), + PINCTRL_PIN(8, "gpio8"), + PINCTRL_PIN(9, "gpio9"), + PINCTRL_PIN(10, "gpio10"), + PINCTRL_PIN(11, "gpio11"), + PINCTRL_PIN(12, "gpio12"), + PINCTRL_PIN(13, "gpio13"), + PINCTRL_PIN(14, "gpio14"), + PINCTRL_PIN(15, "gpio15"), + PINCTRL_PIN(16, "oscio"), +}; + +static const struct sx150x_device_data sx1508q_device_data = { + .model = SX150X_789, + .reg_pullup = 0x03, + .reg_pulldn = 0x04, + .reg_dir = 0x07, + .reg_data = 0x08, + .reg_irq_mask = 0x09, + .reg_irq_src = 0x0c, + .reg_sense = 0x0b, + .pri.x789 = { + .reg_drain = 0x05, + .reg_polarity = 0x06, + .reg_clock = 0x0f, + .reg_misc = 0x10, + .reg_reset = 0x7d, + }, + .ngpios = 8, + .pins = sx150x_8_pins, + .npins = ARRAY_SIZE(sx150x_8_pins), +}; + +static const struct sx150x_device_data sx1509q_device_data = { + .model = SX150X_789, + .reg_pullup = 0x07, + .reg_pulldn = 0x09, + .reg_dir = 0x0f, + .reg_data = 0x11, + .reg_irq_mask = 0x13, + .reg_irq_src = 0x19, + .reg_sense = 0x17, + .pri.x789 = { + .reg_drain = 0x0b, + .reg_polarity = 0x0d, + .reg_clock = 0x1e, + .reg_misc = 0x1f, + .reg_reset = 0x7d, + }, + .ngpios = 16, + .pins = sx150x_16_pins, + .npins = ARRAY_SIZE(sx150x_16_pins), +}; + +static const struct sx150x_device_data sx1506q_device_data = { + .model = SX150X_456, + .reg_pullup = 0x05, + .reg_pulldn = 0x07, + .reg_dir = 0x03, + .reg_data = 0x01, + .reg_irq_mask = 0x09, + .reg_irq_src = 0x0f, + .reg_sense = 0x0d, + .pri.x456 = { + .reg_pld_mode = 0x21, + .reg_pld_table0 = 0x23, + .reg_pld_table1 = 0x25, + .reg_pld_table2 = 0x27, + .reg_pld_table3 = 0x29, + .reg_pld_table4 = 0x2b, + .reg_advance = 0xad, + }, + .ngpios = 16, + .pins = sx150x_16_pins, + .npins = 16, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1502q_device_data = { + .model = SX150X_123, + .reg_pullup = 0x02, + .reg_pulldn = 0x03, + .reg_dir = 0x01, + .reg_data = 0x00, + .reg_irq_mask = 0x05, + .reg_irq_src = 0x08, + .reg_sense = 0x07, + .pri.x123 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table1 = 0x12, + .reg_pld_table2 = 0x13, + .reg_pld_table3 = 0x14, + .reg_pld_table4 = 0x15, + .reg_advance = 0xad, + }, + .ngpios = 8, + .pins = sx150x_8_pins, + .npins = 8, /* oscio not available */ +}; + +static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) +{ + s32 err = i2c_smbus_write_byte_data(client, reg, val); + + if (err < 0) + dev_warn(&client->dev, + "i2c write fail: can't write %02x to %02x: %d\n", + val, reg, err); + return err; +} + +static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) +{ + s32 err = i2c_smbus_read_byte_data(client, reg); + + if (err >= 0) + *val = err; + else + dev_warn(&client->dev, + "i2c read fail: can't read from %02x: %d\n", + reg, err); + return err; +} + +/* + * These utility functions solve the common problem of locating and setting + * configuration bits. Configuration bits are grouped into registers + * whose indexes increase downwards. For example, with eight-bit registers, + * sixteen gpios would have their config bits grouped in the following order: + * REGISTER N-1 [ f e d c b a 9 8 ] + * N [ 7 6 5 4 3 2 1 0 ] + * + * For multi-bit configurations, the pattern gets wider: + * REGISTER N-3 [ f f e e d d c c ] + * N-2 [ b b a a 9 9 8 8 ] + * N-1 [ 7 7 6 6 5 5 4 4 ] + * N [ 3 3 2 2 1 1 0 0 ] + * + * Given the address of the starting register 'N', the index of the gpio + * whose configuration we seek to change, and the width in bits of that + * configuration, these functions allow us to locate the correct + * register and mask the correct bits. + */ +static inline void sx150x_find_cfg(u8 offset, u8 width, + u8 *reg, u8 *mask, u8 *shift) +{ + *reg -= offset * width / 8; + *mask = (1 << width) - 1; + *shift = (offset * width) % 8; + *mask <<= *shift; +} + +static int sx150x_write_cfg(struct i2c_client *client, + u8 offset, u8 width, u8 reg, u8 val) +{ + u8 mask; + u8 data; + u8 shift; + int err; + + sx150x_find_cfg(offset, width, ®, &mask, &shift); + err = sx150x_i2c_read(client, reg, &data); + if (err < 0) + return err; + + data &= ~mask; + data |= (val << shift) & mask; + return sx150x_i2c_write(client, reg, data); +} + +static int sx150x_read_cfg(struct i2c_client *client, + u8 offset, u8 width, u8 reg) +{ + u8 mask; + u8 data; + u8 shift; + int err; + + sx150x_find_cfg(offset, width, ®, &mask, &shift); + err = sx150x_i2c_read(client, reg, &data); + if (err < 0) + return err; + + return (data & mask); +} + +static int sx150x_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + return 0; +} + +static const char *sx150x_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int group) +{ + return NULL; +} + +static int sx150x_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int group, + const unsigned int **pins, + unsigned int *num_pins) +{ + return -ENOTSUPP; +} + +static const struct pinctrl_ops sx150x_pinctrl_ops = { + .get_groups_count = sx150x_pinctrl_get_groups_count, + .get_group_name = sx150x_pinctrl_get_group_name, + .get_group_pins = sx150x_pinctrl_get_group_pins, +#ifdef CONFIG_OF + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinctrl_utils_free_map, +#endif +}; + +static bool sx150x_pin_is_oscio(struct sx150x_pinctrl *pctl, unsigned int pin) +{ + if (pin >= pctl->data->npins) + return false; + + /* OSCIO pin is only present in 789 devices */ + if (pctl->data->model != SX150X_789) + return false; + + return !strcmp(pctl->data->pins[pin].name, "oscio"); +} + +static int sx150x_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); + int status; + + if (sx150x_pin_is_oscio(pctl, offset)) + return false; + + status = sx150x_read_cfg(pctl->client, offset, 1, pctl->data->reg_dir); + if (status >= 0) + status = !!status; + + return status; +} + +static int sx150x_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); + int status; + + if (sx150x_pin_is_oscio(pctl, offset)) + return -EINVAL; + + status = sx150x_read_cfg(pctl->client, offset, 1, pctl->data->reg_data); + if (status >= 0) + status = !!status; + + return status; +} + +static int sx150x_gpio_set_single_ended(struct gpio_chip *chip, + unsigned int offset, + enum single_ended_mode mode) +{ + struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); + int ret; + + switch (mode) { + case LINE_MODE_PUSH_PULL: + if (pctl->data->model != SX150X_789 || + sx150x_pin_is_oscio(pctl, offset)) + return 0; + + mutex_lock(&pctl->lock); + ret = sx150x_write_cfg(pctl->client, offset, 1, + pctl->data->pri.x789.reg_drain, + 0); + mutex_unlock(&pctl->lock); + if (ret < 0) + return ret; + break; + + case LINE_MODE_OPEN_DRAIN: + if (pctl->data->model != SX150X_789 || + sx150x_pin_is_oscio(pctl, offset)) + return -ENOTSUPP; + + mutex_lock(&pctl->lock); + ret = sx150x_write_cfg(pctl->client, offset, 1, + pctl->data->pri.x789.reg_drain, + 1); + mutex_unlock(&pctl->lock); + if (ret < 0) + return ret; + break; + + default: + return -ENOTSUPP; + } + + return 0; +} + +static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); + + if (sx150x_pin_is_oscio(pctl, offset)) { + + mutex_lock(&pctl->lock); + sx150x_i2c_write(pctl->client, + pctl->data->pri.x789.reg_clock, + (value ? 0x1f : 0x10)); + mutex_unlock(&pctl->lock); + } else { + mutex_lock(&pctl->lock); + sx150x_write_cfg(pctl->client, offset, 1, + pctl->data->reg_data, + (value ? 1 : 0)); + mutex_unlock(&pctl->lock); + } +} + +static int sx150x_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); + int ret; + + if (sx150x_pin_is_oscio(pctl, offset)) + return -EINVAL; + + mutex_lock(&pctl->lock); + ret = sx150x_write_cfg(pctl->client, offset, 1, + pctl->data->reg_dir, 1); + mutex_unlock(&pctl->lock); + + return ret; +} + +static int sx150x_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); + int status; + + if (sx150x_pin_is_oscio(pctl, offset)) { + sx150x_gpio_set(chip, offset, value); + return 0; + } + + mutex_lock(&pctl->lock); + status = sx150x_write_cfg(pctl->client, offset, 1, + pctl->data->reg_data, + (value ? 1 : 0)); + if (status >= 0) + status = sx150x_write_cfg(pctl->client, offset, 1, + pctl->data->reg_dir, 0); + mutex_unlock(&pctl->lock); + + return status; +} + +static void sx150x_irq_mask(struct irq_data *d) +{ + struct sx150x_pinctrl *pctl = + gpiochip_get_data(irq_data_get_irq_chip_data(d)); + unsigned int n = d->hwirq; + + pctl->irq.masked |= (1 << n); + pctl->irq.update = n; +} + +static void sx150x_irq_unmask(struct irq_data *d) +{ + struct sx150x_pinctrl *pctl = + gpiochip_get_data(irq_data_get_irq_chip_data(d)); + unsigned int n = d->hwirq; + + pctl->irq.masked &= ~(1 << n); + pctl->irq.update = n; +} + +static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + struct sx150x_pinctrl *pctl = + gpiochip_get_data(irq_data_get_irq_chip_data(d)); + unsigned int n, val = 0; + + if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) + return -EINVAL; + + n = d->hwirq; + + if (flow_type & IRQ_TYPE_EDGE_RISING) + val |= 0x1; + if (flow_type & IRQ_TYPE_EDGE_FALLING) + val |= 0x2; + + pctl->irq.sense &= ~(3UL << (n * 2)); + pctl->irq.sense |= val << (n * 2); + pctl->irq.update = n; + return 0; +} + +static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) +{ + struct sx150x_pinctrl *pctl = (struct sx150x_pinctrl *)dev_id; + unsigned int nhandled = 0; + unsigned int sub_irq; + unsigned int n; + s32 err; + u8 val; + int i; + + for (i = (pctl->data->ngpios / 8) - 1; i >= 0; --i) { + err = sx150x_i2c_read(pctl->client, + pctl->data->reg_irq_src - i, + &val); + if (err < 0) + continue; + + err = sx150x_i2c_write(pctl->client, + pctl->data->reg_irq_src - i, + val); + if (err < 0) + continue; + + for (n = 0; n < 8; ++n) { + if (val & (1 << n)) { + sub_irq = irq_find_mapping( + pctl->gpio.irqdomain, + (i * 8) + n); + handle_nested_irq(sub_irq); + ++nhandled; + } + } + } + + return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); +} + +static void sx150x_irq_bus_lock(struct irq_data *d) +{ + struct sx150x_pinctrl *pctl = + gpiochip_get_data(irq_data_get_irq_chip_data(d)); + + mutex_lock(&pctl->lock); +} + +static void sx150x_irq_bus_sync_unlock(struct irq_data *d) +{ + struct sx150x_pinctrl *pctl = + gpiochip_get_data(irq_data_get_irq_chip_data(d)); + unsigned int n; + + if (pctl->irq.update < 0) + goto out; + + n = pctl->irq.update; + pctl->irq.update = -1; + + /* Avoid updates if nothing changed */ + if (pctl->irq.dev_sense == pctl->irq.sense && + pctl->irq.dev_masked == pctl->irq.masked) + goto out; + + pctl->irq.dev_sense = pctl->irq.sense; + pctl->irq.dev_masked = pctl->irq.masked; + + if (pctl->irq.masked & (1 << n)) { + sx150x_write_cfg(pctl->client, n, 1, + pctl->data->reg_irq_mask, 1); + sx150x_write_cfg(pctl->client, n, 2, + pctl->data->reg_sense, 0); + } else { + sx150x_write_cfg(pctl->client, n, 1, + pctl->data->reg_irq_mask, 0); + sx150x_write_cfg(pctl->client, n, 2, + pctl->data->reg_sense, + pctl->irq.sense >> (n * 2)); + } +out: + mutex_unlock(&pctl->lock); +} + +static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *config) +{ + struct sx150x_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + unsigned int param = pinconf_to_config_param(*config); + int ret; + u32 arg; + + if (sx150x_pin_is_oscio(pctl, pin)) { + u8 data; + + switch (param) { + case PIN_CONFIG_DRIVE_PUSH_PULL: + case PIN_CONFIG_OUTPUT: + mutex_lock(&pctl->lock); + ret = sx150x_i2c_read(pctl->client, + pctl->data->pri.x789.reg_clock, + &data); + mutex_unlock(&pctl->lock); + + if (ret < 0) + return ret; + + if (param == PIN_CONFIG_DRIVE_PUSH_PULL) + arg = (data & 0x1f) ? 1 : 0; + else { + if ((data & 0x1f) == 0x1f) + arg = 1; + else if ((data & 0x1f) == 0x10) + arg = 0; + else + return -EINVAL; + } + + break; + default: + return -ENOTSUPP; + } + + goto out; + } + + switch (param) { + case PIN_CONFIG_BIAS_PULL_DOWN: + mutex_lock(&pctl->lock); + ret = sx150x_read_cfg(pctl->client, pin, 1, + pctl->data->reg_pulldn); + mutex_unlock(&pctl->lock); + + if (ret < 0) + return ret; + + if (!ret) + return -EINVAL; + + arg = 1; + break; + + case PIN_CONFIG_BIAS_PULL_UP: + mutex_lock(&pctl->lock); + ret = sx150x_read_cfg(pctl->client, pin, 1, + pctl->data->reg_pullup); + mutex_unlock(&pctl->lock); + + if (ret < 0) + return ret; + + if (!ret) + return -EINVAL; + + arg = 1; + break; + + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (pctl->data->model != SX150X_789) + return -ENOTSUPP; + + mutex_lock(&pctl->lock); + ret = sx150x_read_cfg(pctl->client, pin, 1, + pctl->data->pri.x789.reg_drain); + mutex_unlock(&pctl->lock); + + if (ret < 0) + return ret; + + if (!ret) + return -EINVAL; + + arg = 1; + break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (pctl->data->model != SX150X_789) + arg = true; + else { + mutex_lock(&pctl->lock); + ret = sx150x_read_cfg(pctl->client, pin, 1, + pctl->data->pri.x789.reg_drain); + mutex_unlock(&pctl->lock); + + if (ret < 0) + return ret; + + if (ret) + return -EINVAL; + + arg = 1; + } + break; + + case PIN_CONFIG_OUTPUT: + ret = sx150x_gpio_get_direction(&pctl->gpio, pin); + if (ret < 0) + return ret; + + if (ret) + return -EINVAL; + + ret = sx150x_gpio_get(&pctl->gpio, pin); + if (ret < 0) + return ret; + + arg = ret; + break; + + default: + return -ENOTSUPP; + } + +out: + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int sx150x_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + struct sx150x_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param param; + u32 arg; + int i; + int ret; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + if (sx150x_pin_is_oscio(pctl, pin)) { + if (param == PIN_CONFIG_OUTPUT) { + ret = sx150x_gpio_direction_output(&pctl->gpio, + pin, arg); + if (ret < 0) + return ret; + + continue; + } else + return -ENOTSUPP; + } + + switch (param) { + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: + case PIN_CONFIG_BIAS_DISABLE: + mutex_lock(&pctl->lock); + ret = sx150x_write_cfg(pctl->client, pin, 1, + pctl->data->reg_pulldn, 0); + mutex_unlock(&pctl->lock); + if (ret < 0) + return ret; + + mutex_lock(&pctl->lock); + ret = sx150x_write_cfg(pctl->client, pin, 1, + pctl->data->reg_pullup, 0); + mutex_unlock(&pctl->lock); + if (ret < 0) + return ret; + + break; + + case PIN_CONFIG_BIAS_PULL_UP: + mutex_lock(&pctl->lock); + ret = sx150x_write_cfg(pctl->client, pin, 1, + pctl->data->reg_pullup, + 1); + mutex_unlock(&pctl->lock); + if (ret < 0) + return ret; + + break; + + case PIN_CONFIG_BIAS_PULL_DOWN: + mutex_lock(&pctl->lock); + ret = sx150x_write_cfg(pctl->client, pin, 1, + pctl->data->reg_pulldn, + 1); + mutex_unlock(&pctl->lock); + if (ret < 0) + return ret; + + break; + + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + ret = sx150x_gpio_set_single_ended(&pctl->gpio, + pin, LINE_MODE_OPEN_DRAIN); + if (ret < 0) + return ret; + + break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + ret = sx150x_gpio_set_single_ended(&pctl->gpio, + pin, LINE_MODE_PUSH_PULL); + if (ret < 0) + return ret; + + break; + + case PIN_CONFIG_OUTPUT: + ret = sx150x_gpio_direction_output(&pctl->gpio, + pin, arg); + if (ret < 0) + return ret; + + break; + + default: + return -ENOTSUPP; + } + } /* for each config */ + + return 0; +} + +static const struct pinconf_ops sx150x_pinconf_ops = { + .pin_config_get = sx150x_pinconf_get, + .pin_config_set = sx150x_pinconf_set, + .is_generic = true, +}; + +static const struct i2c_device_id sx150x_id[] = { + {"sx1508q", (kernel_ulong_t) &sx1508q_device_data }, + {"sx1509q", (kernel_ulong_t) &sx1509q_device_data }, + {"sx1506q", (kernel_ulong_t) &sx1506q_device_data }, + {"sx1502q", (kernel_ulong_t) &sx1502q_device_data }, + {} +}; + +static const struct of_device_id sx150x_of_match[] = { + { .compatible = "semtech,sx1508q" }, + { .compatible = "semtech,sx1509q" }, + { .compatible = "semtech,sx1506q" }, + { .compatible = "semtech,sx1502q" }, + {}, +}; + +static int sx150x_init_io(struct sx150x_pinctrl *pctl, u8 base, u16 cfg) +{ + int err = 0; + unsigned int n; + + for (n = 0; err >= 0 && n < (pctl->data->ngpios / 8); ++n) + err = sx150x_i2c_write(pctl->client, base - n, cfg >> (n * 8)); + return err; +} + +static int sx150x_reset(struct sx150x_pinctrl *pctl) +{ + int err; + + err = i2c_smbus_write_byte_data(pctl->client, + pctl->data->pri.x789.reg_reset, + 0x12); + if (err < 0) + return err; + + err = i2c_smbus_write_byte_data(pctl->client, + pctl->data->pri.x789.reg_reset, + 0x34); + return err; +} + +static int sx150x_init_hw(struct sx150x_pinctrl *pctl) +{ + int err; + + if (pctl->data->model == SX150X_789 && + of_property_read_bool(pctl->dev->of_node, "semtech,probe-reset")) { + err = sx150x_reset(pctl); + if (err < 0) + return err; + } + + if (pctl->data->model == SX150X_789) + err = sx150x_i2c_write(pctl->client, + pctl->data->pri.x789.reg_misc, + 0x01); + else if (pctl->data->model == SX150X_456) + err = sx150x_i2c_write(pctl->client, + pctl->data->pri.x456.reg_advance, + 0x04); + else + err = sx150x_i2c_write(pctl->client, + pctl->data->pri.x123.reg_advance, + 0x00); + if (err < 0) + return err; + + /* Set all pins to work in normal mode */ + if (pctl->data->model == SX150X_789) { + err = sx150x_init_io(pctl, + pctl->data->pri.x789.reg_polarity, + 0); + if (err < 0) + return err; + } else if (pctl->data->model == SX150X_456) { + /* Set all pins to work in normal mode */ + err = sx150x_init_io(pctl, + pctl->data->pri.x456.reg_pld_mode, + 0); + if (err < 0) + return err; + } else { + /* Set all pins to work in normal mode */ + err = sx150x_init_io(pctl, + pctl->data->pri.x123.reg_pld_mode, + 0); + if (err < 0) + return err; + } + + return 0; +} + +static int sx150x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WRITE_WORD_DATA; + struct device *dev = &client->dev; + struct sx150x_pinctrl *pctl; + int ret; + + if (!id->driver_data) + return -EINVAL; + + if (!i2c_check_functionality(client->adapter, i2c_funcs)) + return -ENOSYS; + + pctl = devm_kzalloc(dev, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + + pctl->dev = dev; + pctl->client = client; + pctl->data = (void *)id->driver_data; + + mutex_init(&pctl->lock); + + ret = sx150x_init_hw(pctl); + if (ret) + return ret; + + /* Register GPIO controller */ + pctl->gpio.label = devm_kstrdup(dev, client->name, GFP_KERNEL); + pctl->gpio.base = -1; + pctl->gpio.ngpio = pctl->data->npins; + pctl->gpio.get_direction = sx150x_gpio_get_direction; + pctl->gpio.direction_input = sx150x_gpio_direction_input; + pctl->gpio.direction_output = sx150x_gpio_direction_output; + pctl->gpio.get = sx150x_gpio_get; + pctl->gpio.set = sx150x_gpio_set; + pctl->gpio.set_single_ended = sx150x_gpio_set_single_ended; + pctl->gpio.parent = dev; +#ifdef CONFIG_OF_GPIO + pctl->gpio.of_node = dev->of_node; +#endif + pctl->gpio.can_sleep = true; + + ret = devm_gpiochip_add_data(dev, &pctl->gpio, pctl); + if (ret) + return ret; + + /* Add Interrupt support if an irq is specified */ + if (client->irq > 0) { + pctl->irq_chip.name = devm_kstrdup(dev, client->name, + GFP_KERNEL); + pctl->irq_chip.irq_mask = sx150x_irq_mask; + pctl->irq_chip.irq_unmask = sx150x_irq_unmask; + pctl->irq_chip.irq_set_type = sx150x_irq_set_type; + pctl->irq_chip.irq_bus_lock = sx150x_irq_bus_lock; + pctl->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock; + + pctl->irq.masked = ~0; + pctl->irq.sense = 0; + pctl->irq.dev_masked = ~0; + pctl->irq.dev_sense = 0; + pctl->irq.update = -1; + + ret = gpiochip_irqchip_add(&pctl->gpio, + &pctl->irq_chip, 0, + handle_edge_irq, IRQ_TYPE_NONE); + if (ret) { + dev_err(dev, "could not connect irqchip to gpiochip\n"); + return ret; + } + + ret = devm_request_threaded_irq(dev, client->irq, NULL, + sx150x_irq_thread_fn, + IRQF_ONESHOT | IRQF_SHARED | + IRQF_TRIGGER_FALLING, + pctl->irq_chip.name, pctl); + if (ret < 0) + return ret; + } + + /* Pinctrl_desc */ + pctl->pinctrl_desc.name = "sx150x-pinctrl"; + pctl->pinctrl_desc.pctlops = &sx150x_pinctrl_ops; + pctl->pinctrl_desc.confops = &sx150x_pinconf_ops; + pctl->pinctrl_desc.pins = pctl->data->pins; + pctl->pinctrl_desc.npins = pctl->data->npins; + pctl->pinctrl_desc.owner = THIS_MODULE; + + pctl->pctldev = pinctrl_register(&pctl->pinctrl_desc, dev, pctl); + if (IS_ERR(pctl->pctldev)) { + dev_err(dev, "Failed to register pinctrl device\n"); + return PTR_ERR(pctl->pctldev); + } + + return 0; +} + +static struct i2c_driver sx150x_driver = { + .driver = { + .name = "sx150x-pinctrl", + .of_match_table = of_match_ptr(sx150x_of_match), + }, + .probe = sx150x_probe, + .id_table = sx150x_id, +}; + +static int __init sx150x_init(void) +{ + return i2c_add_driver(&sx150x_driver); +} +subsys_initcall(sx150x_init); -- cgit v1.2.3 From fdf4332fdef28b401c36c229174469c3cf3e8241 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 25 Sep 2016 20:44:04 +0800 Subject: gpio: max77620: Remove unused fields from struct max77620_gpio Current code does not use gpio_irq/irq_base/gpio_base fields from struct max77620_gpio, so remove them. Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/gpio/gpio-max77620.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c index b46b436cb97f..df035866d7a2 100644 --- a/drivers/gpio/gpio-max77620.c +++ b/drivers/gpio/gpio-max77620.c @@ -21,9 +21,6 @@ struct max77620_gpio { struct gpio_chip gpio_chip; struct regmap *rmap; struct device *dev; - int gpio_irq; - int irq_base; - int gpio_base; }; static const struct regmap_irq max77620_gpio_irqs[] = { @@ -254,7 +251,6 @@ static int max77620_gpio_probe(struct platform_device *pdev) mgpio->rmap = chip->rmap; mgpio->dev = &pdev->dev; - mgpio->gpio_irq = gpio_irq; mgpio->gpio_chip.label = pdev->name; mgpio->gpio_chip.parent = &pdev->dev; @@ -268,7 +264,6 @@ static int max77620_gpio_probe(struct platform_device *pdev) mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR; mgpio->gpio_chip.can_sleep = 1; mgpio->gpio_chip.base = -1; - mgpio->irq_base = -1; #ifdef CONFIG_OF_GPIO mgpio->gpio_chip.of_node = pdev->dev.parent->of_node; #endif @@ -281,9 +276,8 @@ static int max77620_gpio_probe(struct platform_device *pdev) return ret; } - mgpio->gpio_base = mgpio->gpio_chip.base; - ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, mgpio->gpio_irq, - IRQF_ONESHOT, mgpio->irq_base, + ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, gpio_irq, + IRQF_ONESHOT, -1, &max77620_gpio_irq_chip, &chip->gpio_irq_data); if (ret < 0) { -- cgit v1.2.3 From e78ade0a2f50fd1a5254d8c801dbb37f46a85e12 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 Oct 2016 12:07:53 +0300 Subject: gpio: merrifield: set default handler to be handle_bad_irq() We switch the default handler to be handle_bad_irq() instead of handle_simple_irq() (which was not correct anyway). Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-merrifield.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 45b51278b8ee..82cdcdc779bb 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -411,7 +411,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id } retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base, - handle_simple_irq, IRQ_TYPE_NONE); + handle_bad_irq, IRQ_TYPE_NONE); if (retval) { dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n"); return retval; -- cgit v1.2.3 From 26a48c4cc2f15d516513e4a980a8a63a21aff018 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 2 Jun 2016 12:52:24 -0500 Subject: gpio: altera-a10sr: Add A10 System Resource Chip GPIO support. Add the GPIO functionality for the Altera Arria10 MAX5 System Resource Chip. The A10 MAX5 has 12 bits of GPIO assigned to switches, buttons, and LEDs as a GPIO extender on the SPI bus. Signed-off-by: Thor Thayer Acked-by: Linus Walleij i Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 8 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-altera-a10sr.c | 140 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 drivers/gpio/gpio-altera-a10sr.c (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 26ee00f6bd58..41e2a8f84289 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -818,6 +818,14 @@ config GPIO_ADP5520 This option enables support for on-chip GPIO found on Analog Devices ADP5520 PMICs. +config GPIO_ALTERA_A10SR + tristate "Altera Arria10 System Resource GPIO" + depends on MFD_ALTERA_A10SR + help + Driver for Arria10 Development Kit GPIO expansion which + includes reads of pushbuttons and DIP switches as well + as writes to LEDs. + config GPIO_ARIZONA tristate "Wolfson Microelectronics Arizona class devices" depends on MFD_ARIZONA diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ab28a2daeacc..145847a4d1d5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o +obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c new file mode 100644 index 000000000000..8274f98e3bee --- /dev/null +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -0,0 +1,140 @@ +/* + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * GPIO driver for Altera Arria10 MAX5 System Resource Chip + * + * Adapted from gpio-tps65910.c + */ + +#include +#include +#include + +/** + * struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure + * @gp: : instance of the gpio_chip + * @regmap: the regmap from the parent device. + */ +struct altr_a10sr_gpio { + struct gpio_chip gp; + struct regmap *regmap; +}; + +static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip); + int ret, val; + + ret = regmap_read(gpio->regmap, ALTR_A10SR_PBDSW_REG, &val); + if (ret < 0) + return ret; + + return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT)); +} + +static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip); + + regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG, + BIT(ALTR_A10SR_LED_VALID_SHIFT + offset), + value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset) + : 0); +} + +static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc, + unsigned int nr) +{ + if (nr >= (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT)) + return 0; + return -EINVAL; +} + +static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, + unsigned int nr, int value) +{ + if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) + return 0; + return -EINVAL; +} + +static struct gpio_chip altr_a10sr_gc = { + .label = "altr_a10sr_gpio", + .owner = THIS_MODULE, + .get = altr_a10sr_gpio_get, + .set = altr_a10sr_gpio_set, + .direction_input = altr_a10sr_gpio_direction_input, + .direction_output = altr_a10sr_gpio_direction_output, + .can_sleep = true, + .ngpio = 12, + .base = -1, +}; + +static int altr_a10sr_gpio_probe(struct platform_device *pdev) +{ + struct altr_a10sr_gpio *gpio; + int ret; + struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent); + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->regmap = a10sr->regmap; + + gpio->gp = altr_a10sr_gc; + + gpio->gp.of_node = pdev->dev.of_node; + + ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, gpio); + + return 0; +} + +static int altr_a10sr_gpio_remove(struct platform_device *pdev) +{ + struct altr_a10sr_gpio *gpio = platform_get_drvdata(pdev); + + gpiochip_remove(&gpio->gp); + + return 0; +} + +static const struct of_device_id altr_a10sr_gpio_of_match[] = { + { .compatible = "altr,a10sr-gpio" }, + { }, +}; +MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match); + +static struct platform_driver altr_a10sr_gpio_driver = { + .probe = altr_a10sr_gpio_probe, + .remove = altr_a10sr_gpio_remove, + .driver = { + .name = "altr_a10sr_gpio", + .of_match_table = of_match_ptr(altr_a10sr_gpio_of_match), + }, +}; +module_platform_driver(altr_a10sr_gpio_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Thor Thayer "); +MODULE_DESCRIPTION("Altera Arria10 System Resource Chip GPIO"); -- cgit v1.2.3 From 4c5f15b71b22ea51fcb70e538056bcb4958edd9f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 14 Oct 2016 14:24:09 +0200 Subject: gpio: ts4900: Add hardware dependencies All the boards supported by the gpio-ts4900 driver are i.MX6 boards, so only offer the driver for building on this platform, unless build-testing. Signed-off-by: Jean Delvare Cc: Lucile Quirion Cc: Linus Walleij Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 41e2a8f84289..8eea33269433 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -802,6 +802,7 @@ config GPIO_TPIC2810 config GPIO_TS4900 tristate "Technologic Systems FPGA I2C GPIO" + depends on SOC_IMX6 || COMPILE_TEST select REGMAP_I2C help Say yes here to enabled the GPIO driver for Technologic's FPGA core. -- cgit v1.2.3 From 1208c93525f9385354588f74c3db5413bd7781dc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 17 Oct 2016 18:36:49 +0200 Subject: gpio: pca953x: Add MAX7318 compatible Add compatible string for the MAX7318 part. This is a two bank, 16 lines, I2C GPIO expander with interrupt line. Signed-off-by: Marek Vasut Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index e422568e14ad..601c4550ee27 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -74,6 +74,7 @@ static const struct i2c_device_id pca953x_id[] = { { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, { "max7313", 16 | PCA953X_TYPE | PCA_INT, }, { "max7315", 8 | PCA953X_TYPE | PCA_INT, }, + { "max7318", 16 | PCA953X_TYPE | PCA_INT, }, { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, @@ -907,6 +908,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), }, + { .compatible = "maxim,max7318", .data = OF_953X(16, PCA_INT), }, { .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), }, { .compatible = "ti,pca9536", .data = OF_953X( 4, 0), }, -- cgit v1.2.3 From 6f7194a10bdba1588357342c6daaaeef98e0004f Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 21 Oct 2016 17:21:29 +0300 Subject: ACPI / gpio: Allow holes in list of GPIOs for a device Make it possible to have an empty GPIOs in a GPIO list for device. For example a SPI master may use both GPIOs and native pins as chip selects and we need to be able to distinguish between the two. This makes it mandatory to have exactly 3 arguments for GPIOs and then converts gpiolib to use of __acpi_node_get_property_reference() instead. In addition we make acpi_gpio_package_count() to handle holes as well (this matches the DT version). Signed-off-by: Mika Westerberg Acked-by: Rafael J. Wysocki Signed-off-by: Linus Walleij --- Documentation/acpi/gpio-properties.txt | 15 +++++++++++++++ drivers/gpio/gpiolib-acpi.c | 32 +++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/Documentation/acpi/gpio-properties.txt b/Documentation/acpi/gpio-properties.txt index 5aafe0b351a1..09cff657b82c 100644 --- a/Documentation/acpi/gpio-properties.txt +++ b/Documentation/acpi/gpio-properties.txt @@ -51,6 +51,21 @@ it to 1 marks the GPIO as active low. In our Bluetooth example the "reset-gpios" refers to the second GpioIo() resource, second pin in that resource with the GPIO number of 31. +It is possible to leave holes in the array of GPIOs. This is useful in +cases like with SPI host controllers where some chip selects may be +implemented as GPIOs and some as native signals. For example a SPI host +controller can have chip selects 0 and 2 implemented as GPIOs and 1 as +native: + + Package () { + "cs-gpios", + Package () { + ^GPIO, 19, 0, 0, // chip select 0: GPIO + 0, // chip select 1: native signal + ^GPIO, 20, 0, 0, // chip select 2: GPIO + } + } + ACPI GPIO Mappings Provided by Drivers -------------------------------------- diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 58ece201b8e6..700ea6ad609b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -468,7 +468,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, int ret; memset(&args, 0, sizeof(args)); - ret = acpi_node_get_property_reference(fwnode, propname, index, &args); + ret = __acpi_node_get_property_reference(fwnode, propname, index, 3, + &args); if (ret) { struct acpi_device *adev = to_acpi_device_node(fwnode); @@ -483,13 +484,13 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, * on returned args. */ lookup->adev = args.adev; - if (args.nargs >= 2) { - lookup->index = args.args[0]; - lookup->pin_index = args.args[1]; - /* 3rd argument, if present is used to specify active_low. */ - if (args.nargs >= 3) - lookup->active_low = !!args.args[2]; - } + if (args.nargs != 3) + return -EPROTO; + + lookup->index = args.args[0]; + lookup->pin_index = args.args[1]; + lookup->active_low = !!args.args[2]; + return 0; } @@ -915,18 +916,27 @@ void acpi_gpiochip_remove(struct gpio_chip *chip) kfree(acpi_gpio); } -static unsigned int acpi_gpio_package_count(const union acpi_object *obj) +static int acpi_gpio_package_count(const union acpi_object *obj) { const union acpi_object *element = obj->package.elements; const union acpi_object *end = element + obj->package.count; unsigned int count = 0; while (element < end) { - if (element->type == ACPI_TYPE_LOCAL_REFERENCE) + switch (element->type) { + case ACPI_TYPE_LOCAL_REFERENCE: + element += 3; + /* Fallthrough */ + case ACPI_TYPE_INTEGER: + element++; count++; + break; - element++; + default: + return -EPROTO; + } } + return count; } -- cgit v1.2.3 From c80f1ba75df25837fb76044e06686b6587d33f6a Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 21 Oct 2016 17:21:30 +0300 Subject: ACPI / gpio: Add hogging support GPIO hogging means that the GPIO controller can "hog" and configure certain GPIOs without need for a driver or userspace to do that. This is useful in open-connected boards where BIOS cannot possibly know beforehand which devices will be connected to the board. This adds GPIO hogging mechanism to ACPI analogous to Device Tree. Signed-off-by: Mika Westerberg Acked-by: Rafael J. Wysocki Signed-off-by: Linus Walleij --- Documentation/acpi/gpio-properties.txt | 35 +++++++++++++++++ drivers/gpio/gpiolib-acpi.c | 71 ++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) (limited to 'drivers') diff --git a/Documentation/acpi/gpio-properties.txt b/Documentation/acpi/gpio-properties.txt index 09cff657b82c..d9076af271f5 100644 --- a/Documentation/acpi/gpio-properties.txt +++ b/Documentation/acpi/gpio-properties.txt @@ -66,6 +66,41 @@ native: } } +Other supported properties +-------------------------- + +Following Device Tree compatible device properties are also supported by +_DSD device properties for GPIO controllers: + +- gpio-hog +- output-high +- output-low +- input +- line-name + +Example: + + Name (_DSD, Package () { + // _DSD Hierarchical Properties Extension UUID + ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), + Package () { + Package () {"hog-gpio8", "G8PU"} + } + }) + + Name (G8PU, Package () { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () { + Package () {"gpio-hog", 1}, + Package () {"gpios", Package () {8, 0}}, + Package () {"output-high", 1}, + Package () {"line-name", "gpio8-pullup"}, + } + }) + +See Documentation/devicetree/bindings/gpio/gpio.txt for more information +about these properties. + ACPI GPIO Mappings Provided by Drivers -------------------------------------- diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 700ea6ad609b..4f46982ce982 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -857,6 +857,76 @@ static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip) } } +struct gpio_desc *acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip, + struct fwnode_handle *fwnode, const char **name, unsigned int *lflags, + unsigned int *dflags) +{ + struct gpio_chip *chip = achip->chip; + struct gpio_desc *desc; + u32 gpios[2]; + int ret; + + ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios, + ARRAY_SIZE(gpios)); + if (ret < 0) + return ERR_PTR(ret); + + ret = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, gpios[0]); + if (ret < 0) + return ERR_PTR(ret); + + desc = gpiochip_get_desc(chip, ret); + if (IS_ERR(desc)) + return desc; + + *lflags = 0; + *dflags = 0; + *name = NULL; + + if (gpios[1]) + *lflags |= GPIO_ACTIVE_LOW; + + if (fwnode_property_present(fwnode, "input")) + *dflags |= GPIOD_IN; + else if (fwnode_property_present(fwnode, "output-low")) + *dflags |= GPIOD_OUT_LOW; + else if (fwnode_property_present(fwnode, "output-high")) + *dflags |= GPIOD_OUT_HIGH; + else + return ERR_PTR(-EINVAL); + + fwnode_property_read_string(fwnode, "line-name", name); + + return desc; +} + +static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip) +{ + struct gpio_chip *chip = achip->chip; + struct fwnode_handle *fwnode; + + device_for_each_child_node(chip->parent, fwnode) { + unsigned int lflags, dflags; + struct gpio_desc *desc; + const char *name; + int ret; + + if (!fwnode_property_present(fwnode, "gpio-hog")) + continue; + + desc = acpi_gpiochip_parse_own_gpio(achip, fwnode, &name, + &lflags, &dflags); + if (IS_ERR(desc)) + continue; + + ret = gpiod_hog(desc, name, lflags, dflags); + if (ret) { + dev_err(chip->parent, "Failed to hog GPIO\n"); + return; + } + } +} + void acpi_gpiochip_add(struct gpio_chip *chip) { struct acpi_gpio_chip *acpi_gpio; @@ -888,6 +958,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip) } acpi_gpiochip_request_regions(acpi_gpio); + acpi_gpiochip_scan_gpios(acpi_gpio); acpi_walk_dep_device_list(handle); } -- cgit v1.2.3 From 9427ecbed46cc8425338084ae42ce8749566586f Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 21 Oct 2016 17:21:31 +0300 Subject: gpio: Rework of_gpiochip_set_names() to use device property accessors In order to use "gpio-line-names" property in systems not having DT as their boot firmware, rework of_gpiochip_set_names() to use device property accessors. This reworked function is placed in a separate file making it clear it deals with universal device properties. Signed-off-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/Makefile | 1 + drivers/gpio/gpiolib-devprop.c | 62 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib-of.c | 47 +------------------------------- drivers/gpio/gpiolib.h | 2 ++ 4 files changed, 66 insertions(+), 46 deletions(-) create mode 100644 drivers/gpio/gpiolib-devprop.c (limited to 'drivers') diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 145847a4d1d5..bd51ad8b4841 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_GPIO_DEVRES) += devres.o obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o +obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o diff --git a/drivers/gpio/gpiolib-devprop.c b/drivers/gpio/gpiolib-devprop.c new file mode 100644 index 000000000000..17bfc41692ef --- /dev/null +++ b/drivers/gpio/gpiolib-devprop.c @@ -0,0 +1,62 @@ +/* + * Device property helpers for GPIO chips. + * + * Copyright (C) 2016, Intel Corporation + * Author: Mika Westerberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "gpiolib.h" + +/** + * devprop_gpiochip_set_names - Set GPIO line names using device properties + * @chip: GPIO chip whose lines should be named, if possible + * + * Looks for device property "gpio-line-names" and if it exists assigns + * GPIO line names for the chip. The memory allocated for the assigned + * names belong to the underlying firmware node and should not be released + * by the caller. + */ +void devprop_gpiochip_set_names(struct gpio_chip *chip) +{ + struct gpio_device *gdev = chip->gpiodev; + const char **names; + int ret, i; + + ret = device_property_read_string_array(chip->parent, "gpio-line-names", + NULL, 0); + if (ret < 0) + return; + + if (ret != gdev->ngpio) { + dev_warn(chip->parent, + "names %d do not match number of GPIOs %d\n", ret, + gdev->ngpio); + return; + } + + names = kcalloc(gdev->ngpio, sizeof(*names), GFP_KERNEL); + if (!names) + return; + + ret = device_property_read_string_array(chip->parent, "gpio-line-names", + names, gdev->ngpio); + if (ret < 0) { + dev_warn(chip->parent, "failed to read GPIO line names\n"); + kfree(names); + return; + } + + for (i = 0; i < gdev->ngpio; i++) + gdev->descs[i].name = names[i]; + + kfree(names); +} diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index ecad3f0e3b77..3fa4e84b4327 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -221,51 +221,6 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, return desc; } -/** - * of_gpiochip_set_names() - set up the names of the lines - * @chip: GPIO chip whose lines should be named, if possible - */ -static void of_gpiochip_set_names(struct gpio_chip *gc) -{ - struct gpio_device *gdev = gc->gpiodev; - struct device_node *np = gc->of_node; - int i; - int nstrings; - - nstrings = of_property_count_strings(np, "gpio-line-names"); - if (nstrings <= 0) - /* Lines names not present */ - return; - - /* This is normally not what you want */ - if (gdev->ngpio != nstrings) - dev_info(&gdev->dev, "gpio-line-names specifies %d line " - "names but there are %d lines on the chip\n", - nstrings, gdev->ngpio); - - /* - * Make sure to not index beyond the end of the number of descriptors - * of the GPIO device. - */ - for (i = 0; i < gdev->ngpio; i++) { - const char *name; - int ret; - - ret = of_property_read_string_index(np, - "gpio-line-names", - i, - &name); - if (ret) { - if (ret != -ENODATA) - dev_err(&gdev->dev, - "unable to name line %d: %d\n", - i, ret); - break; - } - gdev->descs[i].name = name; - } -} - /** * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions * @chip: gpio chip to act on @@ -522,7 +477,7 @@ int of_gpiochip_add(struct gpio_chip *chip) /* If the chip defines names itself, these take precedence */ if (!chip->names) - of_gpiochip_set_names(chip); + devprop_gpiochip_set_names(chip); of_node_get(chip->of_node); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 346fbda39220..d10eaf520860 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -209,6 +209,8 @@ static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc) return desc - &desc->gdev->descs[0]; } +void devprop_gpiochip_set_names(struct gpio_chip *chip); + /* With descriptor prefix */ #define gpiod_emerg(desc, fmt, ...) \ -- cgit v1.2.3 From 4035cc15b99f4f4a4e29081b82aca010137e33da Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 21 Oct 2016 17:21:32 +0300 Subject: ACPI / gpio: Add support for naming GPIOs Now that we have the new helper function that sets nice names for GPIO lines based on "gpio-line-names" device property, we can take advantage of this in acpi_gpiochip_add(). Signed-off-by: Mika Westerberg Signed-off-by: Linus Walleij --- Documentation/acpi/gpio-properties.txt | 12 ++++++++++++ drivers/gpio/gpiolib-acpi.c | 3 +++ 2 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/Documentation/acpi/gpio-properties.txt b/Documentation/acpi/gpio-properties.txt index d9076af271f5..2aff0349facd 100644 --- a/Documentation/acpi/gpio-properties.txt +++ b/Documentation/acpi/gpio-properties.txt @@ -98,6 +98,18 @@ Example: } }) +- gpio-line-names + +Example: + + Package () { + "gpio-line-names", + Package () { + "SPI0_CS_N", "EXP2_INT", "MUX6_IO", "UART0_RXD", "MUX7_IO", + "LVL_C_A1", "MUX0_IO", "SPI1_MISO" + } + } + See Documentation/devicetree/bindings/gpio/gpio.txt for more information about these properties. diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 4f46982ce982..53266ef12008 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -957,6 +957,9 @@ void acpi_gpiochip_add(struct gpio_chip *chip) return; } + if (!chip->names) + devprop_gpiochip_set_names(chip); + acpi_gpiochip_request_regions(acpi_gpio); acpi_gpiochip_scan_gpios(acpi_gpio); acpi_walk_dep_device_list(handle); -- cgit v1.2.3 From 66a37c3bbf7348758a154fe99f8035df2874ebeb Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 21 Oct 2016 15:11:37 +0200 Subject: gpio: mxs: use enable/disable regs to (un)mask irqs The mxs gpio controller does not only have a mask register to mask interrupts, but also enable/disable registers. Use the enable/disable registers rather than the mask register. This does not have any advantage for now, but makes the next patch simpler. Signed-off-by: Sascha Hauer Reviewed-by: Marek Vasut Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index b9daa0bf32a4..1cf579f670ec 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -211,12 +211,13 @@ static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) ct = gc->chip_types; ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_mask = irq_gc_mask_clr_bit; - ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + ct->chip.irq_unmask = irq_gc_unmask_enable_reg; ct->chip.irq_set_type = mxs_gpio_set_irq_type; ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; - ct->regs.mask = PINCTRL_IRQEN(port); + ct->regs.enable = PINCTRL_IRQEN(port) + MXS_SET; + ct->regs.disable = PINCTRL_IRQEN(port) + MXS_CLR; irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); -- cgit v1.2.3 From f08ea3cc94eeaf938ad9da86014e8fee79299458 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 21 Oct 2016 15:11:38 +0200 Subject: gpio: mxs: fix duplicate level interrupts According to the reference manual level interrupts can't be acked using the IRQSTAT registers. The effect is that when a level interrupt triggers the following ack is a no-op and the same interrupt triggers again right after it has been unmasked after running the interrupt handler. The reference manual says: Status bits for pins configured as level sensitive interrupts cannot be cleared unless either the actual pin is in the non-interrupting state, or the pin has been disabled as an interrupt source by clearing its bit in HW_PINCTRL_PIN2IRQ. To work around the duplicated interrupts we can use the PIN2IRQ rather than the IRQEN registers to mask the interrupts. This probably does not work for the edge interrupts, so we have to split up the irq chip into two chip types, one for the level interrupts and one for the edge interrupts. We now make use of two different enable registers, so we have to take care to always enable the right one, especially during switching of the interrupt type. An easy way to accomplish this is to use the IRQCHIP_SET_TYPE_MASKED which makes sure that set_irq_type is called with masked interrupts. With this the flow to change the irq type is like: - core masks interrupt (using the current chip type) - mxs_gpio_set_irq_type() changes chip type if necessary - mxs_gpio_set_irq_type() unconditionally sets the enable bit in the now unused enable register - core eventually unmasks the interrupt (using the new chip type) Signed-off-by: Sascha Hauer Reviewed-by: Marek Vasut Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 1cf579f670ec..62061f740ccf 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -87,10 +87,15 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) u32 val; u32 pin_mask = 1 << d->hwirq; struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct irq_chip_type *ct = irq_data_get_chip_type(d); struct mxs_gpio_port *port = gc->private; void __iomem *pin_addr; int edge; + if (!(ct->type & type)) + if (irq_setup_alt_chip(d, type)) + return -EINVAL; + port->both_edges &= ~pin_mask; switch (type) { case IRQ_TYPE_EDGE_BOTH: @@ -119,10 +124,13 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) /* set level or edge */ pin_addr = port->base + PINCTRL_IRQLEV(port); - if (edge & GPIO_INT_LEV_MASK) + if (edge & GPIO_INT_LEV_MASK) { writel(pin_mask, pin_addr + MXS_SET); - else + writel(pin_mask, port->base + PINCTRL_IRQEN(port) + MXS_SET); + } else { writel(pin_mask, pin_addr + MXS_CLR); + writel(pin_mask, port->base + PINCTRL_PIN2IRQ(port) + MXS_SET); + } /* set polarity */ pin_addr = port->base + PINCTRL_IRQPOL(port); @@ -202,22 +210,37 @@ static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) struct irq_chip_generic *gc; struct irq_chip_type *ct; - gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base, + gc = irq_alloc_generic_chip("gpio-mxs", 2, irq_base, port->base, handle_level_irq); if (!gc) return -ENOMEM; gc->private = port; - ct = gc->chip_types; + ct = &gc->chip_types[0]; + ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; + ct->chip.irq_ack = irq_gc_ack_set_bit; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + ct->chip.irq_unmask = irq_gc_unmask_enable_reg; + ct->chip.irq_set_type = mxs_gpio_set_irq_type; + ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; + ct->chip.flags = IRQCHIP_SET_TYPE_MASKED; + ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; + ct->regs.enable = PINCTRL_PIN2IRQ(port) + MXS_SET; + ct->regs.disable = PINCTRL_PIN2IRQ(port) + MXS_CLR; + + ct = &gc->chip_types[1]; + ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ct->chip.irq_ack = irq_gc_ack_set_bit; ct->chip.irq_mask = irq_gc_mask_disable_reg; ct->chip.irq_unmask = irq_gc_unmask_enable_reg; ct->chip.irq_set_type = mxs_gpio_set_irq_type; ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; + ct->chip.flags = IRQCHIP_SET_TYPE_MASKED; ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; ct->regs.enable = PINCTRL_IRQEN(port) + MXS_SET; ct->regs.disable = PINCTRL_IRQEN(port) + MXS_CLR; + ct->handler = handle_level_irq; irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); @@ -298,11 +321,8 @@ static int mxs_gpio_probe(struct platform_device *pdev) } port->base = base; - /* - * select the pin interrupt functionality but initially - * disable the interrupts - */ - writel(~0U, port->base + PINCTRL_PIN2IRQ(port)); + /* initially disable the interrupts */ + writel(0, port->base + PINCTRL_PIN2IRQ(port)); writel(0, port->base + PINCTRL_IRQEN(port)); /* clear address has to be used to clear IRQSTAT bits */ -- cgit v1.2.3 From 2e9c079cccedbe0d47265ca0c8121c8c66ebb241 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 14:33:17 +0000 Subject: spi: omap2-mcspi: Remove redundant return value check of platform_get_resource() Remove unneeded error handling on the result of a call to platform_get_resource() when the value is passed to devm_ioremap_resource(). Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 3567e1dfd30d..79800e991ccd 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1386,11 +1386,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev) regs_offset = pdata->regs_offset; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - status = -ENODEV; - goto free_master; - } - mcspi->base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(mcspi->base)) { status = PTR_ERR(mcspi->base); -- cgit v1.2.3 From 6fde8d29b0424f292a4ec5dbce01458ad759a41f Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Sat, 22 Oct 2016 22:02:23 +0100 Subject: USB: serial: ch341: add register and USB request definitions No functional changes, this just gives names to some registers and USB requests based on Grigori Goronzy's work and WinChipTech's Linux driver (which reassuringly agree), then uses them in place of magic numbers. This also renames the misnamed BREAK2 register (actually UART config) Signed-off-by: Aidan Thornton Reviewed-by: Grigori Goronzy Signed-off-by: Johan Hovold --- drivers/usb/serial/ch341.c | 51 +++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index f139488d0816..bdf525fe7807 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -61,13 +61,26 @@ * the Net/FreeBSD uchcom.c driver by Takanori Watanabe. Domo arigato. */ +#define CH341_REQ_READ_VERSION 0x5F #define CH341_REQ_WRITE_REG 0x9A #define CH341_REQ_READ_REG 0x95 -#define CH341_REG_BREAK1 0x05 -#define CH341_REG_BREAK2 0x18 -#define CH341_NBREAK_BITS_REG1 0x01 -#define CH341_NBREAK_BITS_REG2 0x40 - +#define CH341_REQ_SERIAL_INIT 0xA1 +#define CH341_REQ_MODEM_CTRL 0xA4 + +#define CH341_REG_BREAK 0x05 +#define CH341_REG_LCR 0x18 +#define CH341_NBREAK_BITS 0x01 + +#define CH341_LCR_ENABLE_RX 0x80 +#define CH341_LCR_ENABLE_TX 0x40 +#define CH341_LCR_MARK_SPACE 0x20 +#define CH341_LCR_PAR_EVEN 0x10 +#define CH341_LCR_ENABLE_PAR 0x08 +#define CH341_LCR_STOP_BITS_2 0x04 +#define CH341_LCR_CS8 0x03 +#define CH341_LCR_CS7 0x02 +#define CH341_LCR_CS6 0x01 +#define CH341_LCR_CS5 0x00 static const struct usb_device_id id_table[] = { { USB_DEVICE(0x4348, 0x5523) }, @@ -144,16 +157,16 @@ static int ch341_set_baudrate(struct usb_device *dev, a = (factor & 0xff00) | divisor; b = factor & 0xff; - r = ch341_control_out(dev, 0x9a, 0x1312, a); + r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, a); if (!r) - r = ch341_control_out(dev, 0x9a, 0x0f2c, b); + r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x0f2c, b); return r; } static int ch341_set_handshake(struct usb_device *dev, u8 control) { - return ch341_control_out(dev, 0xa4, ~control, 0); + return ch341_control_out(dev, CH341_REQ_MODEM_CTRL, ~control, 0); } static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) @@ -167,7 +180,7 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) if (!buffer) return -ENOMEM; - r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size); + r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x0706, 0, buffer, size); if (r < 0) goto out; @@ -197,11 +210,11 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) return -ENOMEM; /* expect two bytes 0x27 0x00 */ - r = ch341_control_in(dev, 0x5f, 0, 0, buffer, size); + r = ch341_control_in(dev, CH341_REQ_READ_VERSION, 0, 0, buffer, size); if (r < 0) goto out; - r = ch341_control_out(dev, 0xa1, 0, 0); + r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0, 0); if (r < 0) goto out; @@ -210,11 +223,11 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) goto out; /* expect two bytes 0x56 0x00 */ - r = ch341_control_in(dev, 0x95, 0x2518, 0, buffer, size); + r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x2518, 0, buffer, size); if (r < 0) goto out; - r = ch341_control_out(dev, 0x9a, 0x2518, 0x0050); + r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, 0x0050); if (r < 0) goto out; @@ -223,7 +236,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) if (r < 0) goto out; - r = ch341_control_out(dev, 0xa1, 0x501f, 0xd90a); + r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0x501f, 0xd90a); if (r < 0) goto out; @@ -370,7 +383,7 @@ static void ch341_set_termios(struct tty_struct *tty, static void ch341_break_ctl(struct tty_struct *tty, int break_state) { const uint16_t ch341_break_reg = - ((uint16_t) CH341_REG_BREAK2 << 8) | CH341_REG_BREAK1; + ((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK; struct usb_serial_port *port = tty->driver_data; int r; uint16_t reg_contents; @@ -391,12 +404,12 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) __func__, break_reg[0], break_reg[1]); if (break_state != 0) { dev_dbg(&port->dev, "%s - Enter break state requested\n", __func__); - break_reg[0] &= ~CH341_NBREAK_BITS_REG1; - break_reg[1] &= ~CH341_NBREAK_BITS_REG2; + break_reg[0] &= ~CH341_NBREAK_BITS; + break_reg[1] &= ~CH341_LCR_ENABLE_TX; } else { dev_dbg(&port->dev, "%s - Leave break state requested\n", __func__); - break_reg[0] |= CH341_NBREAK_BITS_REG1; - break_reg[1] |= CH341_NBREAK_BITS_REG2; + break_reg[0] |= CH341_NBREAK_BITS; + break_reg[1] |= CH341_LCR_ENABLE_TX; } dev_dbg(&port->dev, "%s - New ch341 break register contents - reg1: %x, reg2: %x\n", __func__, break_reg[0], break_reg[1]); -- cgit v1.2.3 From 4e46c410e050bcac36deadbd8e20449d078204e8 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Sat, 22 Oct 2016 22:02:24 +0100 Subject: USB: serial: ch341: reinitialize chip on reconfiguration Changing the LCR register after initialization does not seem to be reliable on all chips (particularly not on CH341A). Restructure initialization and configuration to always reinit the chip on configuration changes instead and pass the LCR register value directly to the initialization command. (Note that baud rates above 500kbaud are incorrect, but they're incorrect in the same way both before and after this patch at least on the CH340G. Fixing this isn't a priority as higher baud rates don't seem that reliable anyway.) Cleaned-up version of a patch by Grigori Goronzy Signed-off-by: Aidan Thornton Reviewed-by: Grigori Goronzy Signed-off-by: Johan Hovold --- drivers/usb/serial/ch341.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index bdf525fe7807..096bc070635a 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -132,10 +132,10 @@ static int ch341_control_in(struct usb_device *dev, return r; } -static int ch341_set_baudrate(struct usb_device *dev, - struct ch341_private *priv) +static int ch341_init_set_baudrate(struct usb_device *dev, + struct ch341_private *priv, unsigned ctrl) { - short a, b; + short a; int r; unsigned long factor; short divisor; @@ -155,11 +155,10 @@ static int ch341_set_baudrate(struct usb_device *dev, factor = 0x10000 - factor; a = (factor & 0xff00) | divisor; - b = factor & 0xff; - r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, a); - if (!r) - r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x0f2c, b); + /* 0x9c is "enable SFR_UART Control register and timer" */ + r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, + 0x9c | (ctrl << 8), a | 0x80); return r; } @@ -218,10 +217,6 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) if (r < 0) goto out; - r = ch341_set_baudrate(dev, priv); - if (r < 0) - goto out; - /* expect two bytes 0x56 0x00 */ r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x2518, 0, buffer, size); if (r < 0) @@ -236,11 +231,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) if (r < 0) goto out; - r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0x501f, 0xd90a); - if (r < 0) - goto out; - - r = ch341_set_baudrate(dev, priv); + r = ch341_init_set_baudrate(dev, priv, 0); if (r < 0) goto out; @@ -355,16 +346,28 @@ static void ch341_set_termios(struct tty_struct *tty, struct ch341_private *priv = usb_get_serial_port_data(port); unsigned baud_rate; unsigned long flags; + unsigned char ctrl; + int r; + + /* redundant changes may cause the chip to lose bytes */ + if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) + return; baud_rate = tty_get_baud_rate(tty); priv->baud_rate = baud_rate; + ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8; + if (baud_rate) { spin_lock_irqsave(&priv->lock, flags); priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS); spin_unlock_irqrestore(&priv->lock, flags); - ch341_set_baudrate(port->serial->dev, priv); + r = ch341_init_set_baudrate(port->serial->dev, priv, ctrl); + if (r < 0 && old_termios) { + priv->baud_rate = tty_termios_baud_rate(old_termios); + tty_termios_copy_hw(&tty->termios, old_termios); + } } else { spin_lock_irqsave(&priv->lock, flags); priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS); -- cgit v1.2.3 From ba781bdf86621b71aa79a1ac0ad584f1e8aac307 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Sat, 22 Oct 2016 22:02:25 +0100 Subject: USB: serial: ch341: add support for parity, frame length, stop bits With the new reinitialization method, configuring parity, different frame lengths and different stop bit settings should work as expected on both CH340G and CH341A. Tested on a loopback-connected CH340G with a logic analyzer in a number of different configurations. Based on a patch by Grigori Goronzy Signed-off-by: Aidan Thornton Reviewed-by: Grigori Goronzy Signed-off-by: Johan Hovold --- drivers/usb/serial/ch341.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 096bc070635a..af9edbedfd28 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -356,8 +356,33 @@ static void ch341_set_termios(struct tty_struct *tty, baud_rate = tty_get_baud_rate(tty); priv->baud_rate = baud_rate; + ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX; - ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8; + switch (C_CSIZE(tty)) { + case CS5: + ctrl |= CH341_LCR_CS5; + break; + case CS6: + ctrl |= CH341_LCR_CS6; + break; + case CS7: + ctrl |= CH341_LCR_CS7; + break; + case CS8: + ctrl |= CH341_LCR_CS8; + break; + } + + if (C_PARENB(tty)) { + ctrl |= CH341_LCR_ENABLE_PAR; + if (C_PARODD(tty) == 0) + ctrl |= CH341_LCR_PAR_EVEN; + if (C_CMSPAR(tty)) + ctrl |= CH341_LCR_MARK_SPACE; + } + + if (C_CSTOPB(tty)) + ctrl |= CH341_LCR_STOP_BITS_2; if (baud_rate) { spin_lock_irqsave(&priv->lock, flags); @@ -376,11 +401,6 @@ static void ch341_set_termios(struct tty_struct *tty, ch341_set_handshake(port->serial->dev, priv->line_control); - /* Unimplemented: - * (cflag & CSIZE) : data bits [5, 8] - * (cflag & PARENB) : parity {NONE, EVEN, ODD} - * (cflag & CSTOPB) : stop bits [1, 2] - */ } static void ch341_break_ctl(struct tty_struct *tty, int break_state) -- cgit v1.2.3 From a98b69002a1656f1d50e24d6c189a66a5f55f783 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Sat, 22 Oct 2016 22:02:26 +0100 Subject: USB: serial: ch341: add debug output for chip version Will probably be helpful if there are any more compatibility issues. Signed-off-by: Aidan Thornton Reviewed-by: Grigori Goronzy Signed-off-by: Johan Hovold --- drivers/usb/serial/ch341.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index af9edbedfd28..2597b83a8ae2 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -212,6 +212,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) r = ch341_control_in(dev, CH341_REQ_READ_VERSION, 0, 0, buffer, size); if (r < 0) goto out; + dev_dbg(&dev->dev, "Chip version: 0x%02x\n", buffer[0]); r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0, 0); if (r < 0) -- cgit v1.2.3 From 88f0e3a5e6ed674f485d3a09d53c2ead0000378d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 21 Oct 2016 14:47:42 +0100 Subject: regulator: arizona-ldo1: Set appropriate value for ramp_delay Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/arizona-ldo1.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index f7c88ff90c43..302b57cb89c6 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -130,6 +130,7 @@ static const struct regulator_desc arizona_ldo1_hc = { .uV_step = 50000, .n_voltages = 8, .enable_time = 1500, + .ramp_delay = 24000, .owner = THIS_MODULE, }; @@ -153,6 +154,7 @@ static const struct regulator_desc arizona_ldo1 = { .uV_step = 25000, .n_voltages = 13, .enable_time = 500, + .ramp_delay = 24000, .owner = THIS_MODULE, }; -- cgit v1.2.3 From e98d5fef8556f1da7f903fd1908feed84bb0f90d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 21 Oct 2016 16:40:05 +0800 Subject: regulator: tps6507x: Drop pointless static qualifier for *reg_data variable There is no need to use static for this local variable. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6507x-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index dad0bac09ecf..c179a3a221af 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -375,7 +375,7 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data( struct device_node *np = pdev->dev.parent->of_node; struct device_node *regulators; struct of_regulator_match *matches; - static struct regulator_init_data *reg_data; + struct regulator_init_data *reg_data; int idx = 0, count, ret; tps_board = devm_kzalloc(&pdev->dev, sizeof(*tps_board), -- cgit v1.2.3 From bf8e27621effb49da525fb92a1f192db685d39bd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 21 Oct 2016 10:30:16 +0800 Subject: regulator: rk808: Use rdev_get_id() to access id of regulator RK808_ID_DCDC1 is 0, no need to do subtract RK808_ID_DCDC1. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 3314bf299a51..fb44d5215e30 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -120,7 +120,7 @@ static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = { static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); - int id = rdev->desc->id - RK808_ID_DCDC1; + int id = rdev_get_id(rdev); struct gpio_desc *gpio = pdata->dvs_gpio[id]; unsigned int val; int ret; @@ -193,7 +193,7 @@ static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); - int id = rdev->desc->id - RK808_ID_DCDC1; + int id = rdev_get_id(rdev); struct gpio_desc *gpio = pdata->dvs_gpio[id]; unsigned int reg = rdev->desc->vsel_reg; unsigned old_sel; @@ -232,7 +232,7 @@ static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int new_selector) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); - int id = rdev->desc->id - RK808_ID_DCDC1; + int id = rdev_get_id(rdev); struct gpio_desc *gpio = pdata->dvs_gpio[id]; /* if there is no dvs1/2 pin, we don't need wait extra time here. */ @@ -245,8 +245,7 @@ static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev, static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US; - unsigned int reg = rk808_buck_config_regs[rdev->desc->id - - RK808_ID_DCDC1]; + unsigned int reg = rk808_buck_config_regs[rdev_get_id(rdev)]; switch (ramp_delay) { case 1 ... 2000: -- cgit v1.2.3 From 2dd33f9cec90499029fd49ffae2922c3f9ccad11 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 20 Oct 2016 00:42:25 +0200 Subject: spi: imx: support DMA for imx35 Support DMA transfers on imx35 and compatible chipsets (imx31, imx25). If DMA can be used, set the start mode control (SMC) bit to start the SPI burst as soon as data is written into the tx fifo. Configure DMA requests when the fifo is half empty during tx or half full during rx. Signed-off-by: Martin Kaiser Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index deb782f6556c..08124b29665e 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -442,6 +442,7 @@ static void mx51_ecspi_reset(struct spi_imx_data *spi_imx) #define MX31_CSPICTRL_ENABLE (1 << 0) #define MX31_CSPICTRL_MASTER (1 << 1) #define MX31_CSPICTRL_XCH (1 << 2) +#define MX31_CSPICTRL_SMC (1 << 3) #define MX31_CSPICTRL_POL (1 << 4) #define MX31_CSPICTRL_PHA (1 << 5) #define MX31_CSPICTRL_SSCTL (1 << 6) @@ -452,6 +453,10 @@ static void mx51_ecspi_reset(struct spi_imx_data *spi_imx) #define MX35_CSPICTRL_CS_SHIFT 12 #define MX31_CSPICTRL_DR_SHIFT 16 +#define MX31_CSPI_DMAREG 0x10 +#define MX31_DMAREG_RH_DEN (1<<4) +#define MX31_DMAREG_TH_DEN (1<<1) + #define MX31_CSPISTATUS 0x14 #define MX31_STATUS_RR (1 << 3) @@ -511,6 +516,9 @@ static int mx31_config(struct spi_device *spi, struct spi_imx_config *config) (is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT : MX31_CSPICTRL_CS_SHIFT); + if (spi_imx->usedma) + reg |= MX31_CSPICTRL_SMC; + writel(reg, spi_imx->base + MXC_CSPICTRL); reg = readl(spi_imx->base + MX31_CSPI_TESTREG); @@ -520,6 +528,13 @@ static int mx31_config(struct spi_device *spi, struct spi_imx_config *config) reg &= ~MX31_TEST_LBC; writel(reg, spi_imx->base + MX31_CSPI_TESTREG); + if (spi_imx->usedma) { + /* configure DMA requests when RXFIFO is half full and + when TXFIFO is half empty */ + writel(MX31_DMAREG_RH_DEN | MX31_DMAREG_TH_DEN, + spi_imx->base + MX31_CSPI_DMAREG); + } + return 0; } @@ -1244,10 +1259,10 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per); /* - * Only validated on i.mx6 now, can remove the constrain if validated on - * other chips. + * Only validated on i.mx35 and i.mx6 now, can remove the constraint + * if validated on other chips. */ - if (is_imx51_ecspi(spi_imx)) { + if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx)) { ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master); if (ret == -EPROBE_DEFER) goto out_clk_put; -- cgit v1.2.3 From 79f2624b1b9f776b173b41d743fb3dd7374b3827 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 21 Oct 2016 13:55:45 -0200 Subject: drm/i915/fbc: fix CFB size calculation for gen8+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broadwell and newer actually compress up to 2560 lines instead of 2048 (as documented in the FBC_CTL page). If we don't take this into consideration we end up reserving too little stolen memory for the CFB, so we may allocate something else (such as a ring) right after what we reserved, and the hardware will overwrite it with the contents of the CFB when FBC is active, causing GPU hangs. Another possibility is that the CFB may be allocated at the very end of the available space, so the CFB will overlap the reserved stolen area, leading to FIFO underruns. This bug has always been a problem on BDW (the only affected platform where FBC is enabled by default), but it's much easier to reproduce since the following commit: commit c58b735fc762e891481e92af7124b85cb0a51fce Author: Chris Wilson Date: Thu Aug 18 17:16:57 2016 +0100 drm/i915: Allocate rings from stolen Of course, you can only reproduce the bug if your screen is taller than 2048 lines. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98213 Fixes: a98ee79317b4 ("drm/i915/fbc: enable FBC by default on HSW and BDW") Cc: # v4.6+ Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477065346-13736-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 617189ae04b4..6345cb879e45 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -104,8 +104,10 @@ static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv, int lines; intel_fbc_get_plane_source_size(cache, NULL, &lines); - if (INTEL_INFO(dev_priv)->gen >= 7) + if (INTEL_GEN(dev_priv) == 7) lines = min(lines, 2048); + else if (INTEL_GEN(dev_priv) >= 8) + lines = min(lines, 2560); /* Hardware needs the full buffer stride, not just the active area. */ return lines * cache->fb.stride; -- cgit v1.2.3 From 0fc6a9dc94e44c8eaca364b9da03d26862d6b068 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 21 Oct 2016 13:55:46 -0200 Subject: drm/i915/fbc: fix FBC_COMPRESSION_MASK on BDW+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Its size is 11:0 instead of 10:0. Found by inspecting the spec. I'm not aware of any real-world IGT failures caused by this. Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477065346-13736-2-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 10 ++++++---- drivers/gpu/drm/i915/i915_reg.h | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f85e6fbf27f4..a5e575a7dbde 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1683,11 +1683,13 @@ static int i915_fbc_status(struct seq_file *m, void *unused) seq_printf(m, "FBC disabled: %s\n", dev_priv->fbc.no_fbc_reason); - if (intel_fbc_is_active(dev_priv) && - INTEL_GEN(dev_priv) >= 7) + if (intel_fbc_is_active(dev_priv) && INTEL_GEN(dev_priv) >= 7) { + uint32_t mask = INTEL_GEN(dev_priv) >= 8 ? + BDW_FBC_COMPRESSION_MASK : + IVB_FBC_COMPRESSION_MASK; seq_printf(m, "Compressing: %s\n", - yesno(I915_READ(FBC_STATUS2) & - FBC_COMPRESSION_MASK)); + yesno(I915_READ(FBC_STATUS2) & mask)); + } mutex_unlock(&dev_priv->fbc.lock); intel_runtime_pm_put(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00efaa13974d..a9be3f037f43 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2188,8 +2188,9 @@ enum skl_disp_power_wells { #define FBC_FENCE_OFF _MMIO(0x3218) /* BSpec typo has 321Bh */ #define FBC_TAG(i) _MMIO(0x3300 + (i) * 4) -#define FBC_STATUS2 _MMIO(0x43214) -#define FBC_COMPRESSION_MASK 0x7ff +#define FBC_STATUS2 _MMIO(0x43214) +#define IVB_FBC_COMPRESSION_MASK 0x7ff +#define BDW_FBC_COMPRESSION_MASK 0xfff #define FBC_LL_SIZE (1536) -- cgit v1.2.3 From 31f09cb79e797797bc745d98f93ac50b2cbda9e6 Mon Sep 17 00:00:00 2001 From: Jérémy Lefaure Date: Thu, 20 Oct 2016 18:05:57 -0400 Subject: drm/i915/gvt: fix bad 32 bit shift in gtt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since ioread32 returns a 32-bit value, it is impossible to left-shift this value by 32 bits (it produces a compilation error). Casting the return value of ioread32 fix this issue. Signed-off-by: Jérémy Lefaure Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 2cc761328569..b35bda0ce46b 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -276,7 +276,7 @@ static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index) pte = readq(addr); #else pte = ioread32(addr); - pte |= ioread32(addr + 4) << 32; + pte |= (u64)ioread32(addr + 4) << 32; #endif return pte; } -- cgit v1.2.3 From 2cce9b2894661fbc08d8aa67881c616dd8e669b5 Mon Sep 17 00:00:00 2001 From: Jérémy Lefaure Date: Thu, 20 Oct 2016 18:05:58 -0400 Subject: drm/i915/gvt: fix an error string format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is better to use %p format for void pointers instead of casting them because a void* is not necessary a 64 bits value. Signed-off-by: Jérémy Lefaure Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index b35bda0ce46b..6554da9f9f5b 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1944,7 +1944,7 @@ static int create_scratch_page(struct intel_vgpu *vgpu) mfn = intel_gvt_hypervisor_virt_to_mfn(vaddr); if (mfn == INTEL_GVT_INVALID_ADDR) { - gvt_err("fail to translate vaddr:0x%llx\n", (u64)vaddr); + gvt_err("fail to translate vaddr: 0x%p\n", vaddr); __free_page(gtt->scratch_page); gtt->scratch_page = NULL; return -ENXIO; -- cgit v1.2.3 From 99c79fd4dfdaeb8874d5f3f14a9cd6ce7a436e1d Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Mon, 24 Oct 2016 15:57:47 +0800 Subject: drm/i915/gvt: use well wrapped set_mask_bits() instead of defining new one Macro set_mask_bits() is ready for us, just invoke it and remove our write_bits(). Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index aafb57e26288..477b0d41ae65 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1201,20 +1201,19 @@ static int gen8_update_plane_mmio_from_mi_display_flip( struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; struct intel_vgpu *vgpu = s->vgpu; -#define write_bits(reg, e, s, v) do { \ - vgpu_vreg(vgpu, reg) &= ~GENMASK(e, s); \ - vgpu_vreg(vgpu, reg) |= (v << s); \ -} while (0) - - write_bits(info->surf_reg, 31, 12, info->surf_val); - if (IS_SKYLAKE(dev_priv)) - write_bits(info->stride_reg, 9, 0, info->stride_val); - else - write_bits(info->stride_reg, 15, 6, info->stride_val); - write_bits(info->ctrl_reg, IS_SKYLAKE(dev_priv) ? 12 : 10, - 10, info->tile_val); - -#undef write_bits + set_mask_bits(&vgpu_vreg(vgpu, info->surf_reg), GENMASK(31, 12), + info->surf_val << 12); + if (IS_SKYLAKE(dev_priv)) { + set_mask_bits(&vgpu_vreg(vgpu, info->stride_reg), GENMASK(9, 0), + info->stride_val); + set_mask_bits(&vgpu_vreg(vgpu, info->ctrl_reg), GENMASK(12, 10), + info->tile_val << 10); + } else { + set_mask_bits(&vgpu_vreg(vgpu, info->stride_reg), GENMASK(15, 6), + info->stride_val << 6); + set_mask_bits(&vgpu_vreg(vgpu, info->ctrl_reg), GENMASK(10, 10), + info->tile_val << 10); + } vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(info->pipe))++; intel_vgpu_trigger_virtual_event(vgpu, info->event); -- cgit v1.2.3 From 49129204c31cb3b6f0fbc23d6afe66c88c1c12ae Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Mon, 24 Oct 2016 15:58:44 +0800 Subject: drm/i915/gvt: get msi cap offset from pdev directly Linux PCI driver saves the msi and msix capability offset in pci_dev->msi_cap and pci_dev->msix_cap. We can use msi_cap in pci_dev directly, no need hardcode. Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gvt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 31b59d40f3fb..bf0377768a0d 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -103,19 +103,20 @@ int intel_gvt_init_host(void) static void init_device_info(struct intel_gvt *gvt) { struct intel_gvt_device_info *info = &gvt->device_info; + struct pci_dev *pdev = gvt->dev_priv->drm.pdev; if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { info->max_support_vgpus = 8; info->cfg_space_size = 256; info->mmio_size = 2 * 1024 * 1024; info->mmio_bar = 0; - info->msi_cap_offset = IS_SKYLAKE(gvt->dev_priv) ? 0xac : 0x90; info->gtt_start_offset = 8 * 1024 * 1024; info->gtt_entry_size = 8; info->gtt_entry_size_shift = 3; info->gmadr_bytes_in_cmd = 8; info->max_surface_size = 36 * 1024 * 1024; } + info->msi_cap_offset = pdev->msi_cap; } static int gvt_service_thread(void *data) -- cgit v1.2.3 From 5f2808ff1582202175d3908973eb9e05a5e6625d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 21 Oct 2016 17:32:24 +0200 Subject: sd: fix uninitialized variable access in error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If sd_zbc_report_zones fails, the check for 'zone_blocks == 0' later in the function accesses uninitialized data: drivers/scsi/sd_zbc.c: In function ‘sd_zbc_read_zones’: drivers/scsi/sd_zbc.c:520:7: error: ‘zone_blocks’ may be used uninitialized in this function [-Werror=maybe-uninitialized] This sets it to zero, which has the desired effect of leaving the sd_zbc_read_zones successfully with sdkp->zone_blocks = 0. Fixes: 89d947561077 ("sd: Implement support for ZBC devices") Signed-off-by: Arnd Bergmann Reviewed-by: Shaun Tancheff Reviewed-by: Damien Le Moal Reviewed-by: Hannes Reinecke Signed-off-by: Jens Axboe --- drivers/scsi/sd_zbc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 16d3fa62d8ac..d5b3bd915d9e 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -455,8 +455,10 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) /* Do a report zone to get the same field */ ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0); - if (ret) + if (ret) { + zone_blocks = 0; goto out; + } same = buf[4] & 0x0f; if (same > 0) { -- cgit v1.2.3 From 4e518816a938187b3bfe1b62fa291d4e38dca06e Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Mon, 17 Oct 2016 13:28:00 +0200 Subject: crypto: caam - add support for iMX6UL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i.MX6UL does only require three clocks to enable CAAM module. Signed-off-by: Marcus Folkesson Acked-by: Rob Herring Reviewed-by: Horia Geantă Signed-off-by: Herbert Xu --- .../devicetree/bindings/crypto/fsl-sec4.txt | 20 +++++++++++++ drivers/crypto/caam/ctrl.c | 35 ++++++++++++---------- 2 files changed, 40 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt index adeca34c5a33..10a425f451fc 100644 --- a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt +++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt @@ -123,6 +123,9 @@ PROPERTIES EXAMPLE + +iMX6QDL/SX requires four clocks + crypto@300000 { compatible = "fsl,sec-v4.0"; fsl,sec-era = <2>; @@ -139,6 +142,23 @@ EXAMPLE clock-names = "mem", "aclk", "ipg", "emi_slow"; }; + +iMX6UL does only require three clocks + + crypto: caam@2140000 { + compatible = "fsl,sec-v4.0"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x2140000 0x3c000>; + ranges = <0 0x2140000 0x3c000>; + interrupts = ; + + clocks = <&clks IMX6UL_CLK_CAAM_MEM>, + <&clks IMX6UL_CLK_CAAM_ACLK>, + <&clks IMX6UL_CLK_CAAM_IPG>; + clock-names = "mem", "aclk", "ipg"; + }; + ===================================================================== Job Ring (JR) Node diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 72ff19658985..a79937d68c26 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -330,8 +330,8 @@ static int caam_remove(struct platform_device *pdev) clk_disable_unprepare(ctrlpriv->caam_ipg); clk_disable_unprepare(ctrlpriv->caam_mem); clk_disable_unprepare(ctrlpriv->caam_aclk); - clk_disable_unprepare(ctrlpriv->caam_emi_slow); - + if (!of_machine_is_compatible("fsl,imx6ul")) + clk_disable_unprepare(ctrlpriv->caam_emi_slow); return 0; } @@ -482,14 +482,16 @@ static int caam_probe(struct platform_device *pdev) } ctrlpriv->caam_aclk = clk; - clk = caam_drv_identify_clk(&pdev->dev, "emi_slow"); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - dev_err(&pdev->dev, - "can't identify CAAM emi_slow clk: %d\n", ret); - return ret; + if (!of_machine_is_compatible("fsl,imx6ul")) { + clk = caam_drv_identify_clk(&pdev->dev, "emi_slow"); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + dev_err(&pdev->dev, + "can't identify CAAM emi_slow clk: %d\n", ret); + return ret; + } + ctrlpriv->caam_emi_slow = clk; } - ctrlpriv->caam_emi_slow = clk; ret = clk_prepare_enable(ctrlpriv->caam_ipg); if (ret < 0) { @@ -510,11 +512,13 @@ static int caam_probe(struct platform_device *pdev) goto disable_caam_mem; } - ret = clk_prepare_enable(ctrlpriv->caam_emi_slow); - if (ret < 0) { - dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n", - ret); - goto disable_caam_aclk; + if (!of_machine_is_compatible("fsl,imx6ul")) { + ret = clk_prepare_enable(ctrlpriv->caam_emi_slow); + if (ret < 0) { + dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n", + ret); + goto disable_caam_aclk; + } } /* Get configuration properties from device tree */ @@ -832,7 +836,8 @@ caam_remove: iounmap_ctrl: iounmap(ctrl); disable_caam_emi_slow: - clk_disable_unprepare(ctrlpriv->caam_emi_slow); + if (!of_machine_is_compatible("fsl,imx6ul")) + clk_disable_unprepare(ctrlpriv->caam_emi_slow); disable_caam_aclk: clk_disable_unprepare(ctrlpriv->caam_aclk); disable_caam_mem: -- cgit v1.2.3 From ff4f44de44dbd98feecf8fa76e14353a3993b335 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 17 Oct 2016 15:08:50 +0000 Subject: crypto: ccp - Fix non static symbol warning Fixes the following sparse warning: drivers/crypto/ccp/ccp-dev.c:44:6: warning: symbol 'ccp_error_codes' was not declared. Should it be static? Signed-off-by: Wei Yongjun Acked-by: Gary R Hook Acked-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index cafa633aae10..c25515a80d33 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -41,7 +41,7 @@ struct ccp_tasklet_data { }; /* Human-readable error strings */ -char *ccp_error_codes[] = { +static char *ccp_error_codes[] = { "", "ERR 01: ILLEGAL_ENGINE", "ERR 02: ILLEGAL_KEY_ID", -- cgit v1.2.3 From 877f69a81eeee94a195cfbcfcf1dbb1b25f12fc8 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 16:51:17 -0300 Subject: hwrng: meson - Fix module autoload for OF registration If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/char/hw_random/meson-rng.ko | grep alias alias: platform:meson-rng After this patch: $ modinfo drivers/char/hw_random/meson-rng.ko | grep alias alias: platform:meson-rng alias: of:N*T*Camlogic,meson-rngC* alias: of:N*T*Camlogic,meson-rng Signed-off-by: Javier Martinez Canillas Acked-by: Neil Armstrong Signed-off-by: Herbert Xu --- drivers/char/hw_random/meson-rng.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/hw_random/meson-rng.c b/drivers/char/hw_random/meson-rng.c index 58bef39f7286..51864a509be7 100644 --- a/drivers/char/hw_random/meson-rng.c +++ b/drivers/char/hw_random/meson-rng.c @@ -110,6 +110,7 @@ static const struct of_device_id meson_rng_of_match[] = { { .compatible = "amlogic,meson-rng", }, {}, }; +MODULE_DEVICE_TABLE(of, meson_rng_of_match); static struct platform_driver meson_rng_driver = { .probe = meson_rng_probe, -- cgit v1.2.3 From fdd2cf9db1e25a46a74c5802d18435171c92e7df Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Tue, 18 Oct 2016 17:28:35 -0500 Subject: crypto: ccp - change bitfield type to unsigned ints Bit fields are not sensitive to endianness, so use a transparent standard data type Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.h | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index 5afaa53672b3..58e8d382e9ad 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -541,23 +541,23 @@ static inline u32 ccp_addr_hi(struct ccp_dma_info *info) * word 7: upper 16 bits of key pointer; key memory type */ struct dword0 { - __le32 soc:1; - __le32 ioc:1; - __le32 rsvd1:1; - __le32 init:1; - __le32 eom:1; /* AES/SHA only */ - __le32 function:15; - __le32 engine:4; - __le32 prot:1; - __le32 rsvd2:7; + unsigned int soc:1; + unsigned int ioc:1; + unsigned int rsvd1:1; + unsigned int init:1; + unsigned int eom:1; /* AES/SHA only */ + unsigned int function:15; + unsigned int engine:4; + unsigned int prot:1; + unsigned int rsvd2:7; }; struct dword3 { - __le32 src_hi:16; - __le32 src_mem:2; - __le32 lsb_cxt_id:8; - __le32 rsvd1:5; - __le32 fixed:1; + unsigned int src_hi:16; + unsigned int src_mem:2; + unsigned int lsb_cxt_id:8; + unsigned int rsvd1:5; + unsigned int fixed:1; }; union dword4 { @@ -567,18 +567,18 @@ union dword4 { union dword5 { struct { - __le32 dst_hi:16; - __le32 dst_mem:2; - __le32 rsvd1:13; - __le32 fixed:1; + unsigned int dst_hi:16; + unsigned int dst_mem:2; + unsigned int rsvd1:13; + unsigned int fixed:1; } fields; __le32 sha_len_hi; }; struct dword7 { - __le32 key_hi:16; - __le32 key_mem:2; - __le32 rsvd1:14; + unsigned int key_hi:16; + unsigned int key_mem:2; + unsigned int rsvd1:14; }; struct ccp5_desc { -- cgit v1.2.3 From ec9b70df75b3600ca20338198a43173f23e6bb9b Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Tue, 18 Oct 2016 17:28:49 -0500 Subject: crypto: ccp - remove unneeded code Clean up patch for an unneeded structure member. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index 58e8d382e9ad..830f35e6005f 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -515,7 +515,6 @@ struct ccp_op { struct ccp_passthru_op passthru; struct ccp_ecc_op ecc; } u; - struct ccp_mem key; }; static inline u32 ccp_addr_lo(struct ccp_dma_info *info) -- cgit v1.2.3 From 103600ab966a2f02d8986bbfdf87b762b1c6a06d Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Tue, 18 Oct 2016 17:33:37 -0500 Subject: crypto: ccp - Clean up the LSB slot allocation code Fix a few problems revealed by testing: verify consistent units, especially in public slot allocation. Percolate some common initialization code up to a common routine. Add some comments. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev-v3.c | 4 ---- drivers/crypto/ccp/ccp-dev-v5.c | 20 ++++++++++++-------- drivers/crypto/ccp/ccp-dev.c | 4 ++++ 3 files changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c index 8d2dbacc6161..7bc09989e18a 100644 --- a/drivers/crypto/ccp/ccp-dev-v3.c +++ b/drivers/crypto/ccp/ccp-dev-v3.c @@ -404,10 +404,6 @@ static int ccp_init(struct ccp_device *ccp) goto e_pool; } - /* Initialize the queues used to wait for KSB space and suspend */ - init_waitqueue_head(&ccp->sb_queue); - init_waitqueue_head(&ccp->suspend_queue); - dev_dbg(dev, "Starting threads...\n"); /* Create a kthread for each queue */ for (i = 0; i < ccp->cmd_q_count; i++) { diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index faf3cb3ddce2..ff7816a2b8af 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -21,6 +21,12 @@ #include "ccp-dev.h" +/* Allocate the requested number of contiguous LSB slots + * from the LSB bitmap. Look in the private range for this + * queue first; failing that, check the public area. + * If no space is available, wait around. + * Return: first slot number + */ static u32 ccp_lsb_alloc(struct ccp_cmd_queue *cmd_q, unsigned int count) { struct ccp_device *ccp; @@ -50,7 +56,7 @@ static u32 ccp_lsb_alloc(struct ccp_cmd_queue *cmd_q, unsigned int count) bitmap_set(ccp->lsbmap, start, count); mutex_unlock(&ccp->sb_mutex); - return start * LSB_ITEM_SIZE; + return start; } ccp->sb_avail = 0; @@ -63,17 +69,18 @@ static u32 ccp_lsb_alloc(struct ccp_cmd_queue *cmd_q, unsigned int count) } } +/* Free a number of LSB slots from the bitmap, starting at + * the indicated starting slot number. + */ static void ccp_lsb_free(struct ccp_cmd_queue *cmd_q, unsigned int start, unsigned int count) { - int lsbno = start / LSB_SIZE; - if (!start) return; - if (cmd_q->lsb == lsbno) { + if (cmd_q->lsb == start) { /* An entry from the private LSB */ - bitmap_clear(cmd_q->lsbmap, start % LSB_SIZE, count); + bitmap_clear(cmd_q->lsbmap, start, count); } else { /* From the shared LSBs */ struct ccp_device *ccp = cmd_q->ccp; @@ -751,9 +758,6 @@ static int ccp5_init(struct ccp_device *ccp) goto e_pool; } - /* Initialize the queue used to suspend */ - init_waitqueue_head(&ccp->suspend_queue); - dev_dbg(dev, "Loading LSB map...\n"); /* Copy the private LSB mask to the public registers */ status_lo = ioread32(ccp->io_regs + LSB_PRIVATE_MASK_LO_OFFSET); diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index c25515a80d33..511ab042b5e7 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -478,6 +478,10 @@ struct ccp_device *ccp_alloc_struct(struct device *dev) ccp->sb_count = KSB_COUNT; ccp->sb_start = 0; + /* Initialize the wait queues */ + init_waitqueue_head(&ccp->sb_queue); + init_waitqueue_head(&ccp->suspend_queue); + ccp->ord = ccp_increment_unit_ordinal(); snprintf(ccp->name, MAX_CCP_NAME_LEN, "ccp-%u", ccp->ord); snprintf(ccp->rngname, MAX_CCP_NAME_LEN, "ccp-%u-rng", ccp->ord); -- cgit v1.2.3 From 4e88768a959ad61b77f2f99315e0f352dca4fc31 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 19 Oct 2016 16:50:18 -0300 Subject: hwrng: meson - Remove unneeded platform MODULE_ALIAS The Amlogic Meson is a DT-only platform, which means the devices are registered via OF and not using the legacy platform devices support. So there's no need to have a MODULE_ALIAS("platform:meson-rng") since the reported uevent MODALIAS to user-space will always be the OF one. Signed-off-by: Javier Martinez Canillas Acked-by: Kevin Hilman Acked-by: Neil Armstrong Signed-off-by: Herbert Xu --- drivers/char/hw_random/meson-rng.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/meson-rng.c b/drivers/char/hw_random/meson-rng.c index 51864a509be7..119d698439ae 100644 --- a/drivers/char/hw_random/meson-rng.c +++ b/drivers/char/hw_random/meson-rng.c @@ -122,7 +122,6 @@ static struct platform_driver meson_rng_driver = { module_platform_driver(meson_rng_driver); -MODULE_ALIAS("platform:meson-rng"); MODULE_DESCRIPTION("Meson H/W Random Number Generator driver"); MODULE_AUTHOR("Lawrence Mok "); MODULE_AUTHOR("Neil Armstrong "); -- cgit v1.2.3 From 14544d0937bf0160018a47ba74fff7fd61c22731 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 24 Oct 2016 12:38:21 +0100 Subject: drm/edid: Only print the bad edid when aborting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, if drm.debug is enabled, we get a DRM_ERROR message on the intermediate edid reads. This causes transient failures in CI which flags up the sporadic EDID read failures, which are recovered by rereading the EDID automatically. This patch combines the reporting done by drm_do_get_edid() itself with the bad block printing from get_edid_block(), into a single warning associated with the connector once all attempts to retrieve the EDID fail. v2: Print the whole EDID, marking up the bad/zero blocks. This requires recording the whole of the raw edid, then a second pass to reduce it to the valid extensions. v3: Fix invalid/valid extension fumble. References: https://bugs.freedesktop.org/show_bug.cgi?id=98228 Signed-off-by: Chris Wilson Cc: Ville Syrjälä Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161024113821.26263-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_edid.c | 79 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 95de47ba1e77..9506933b41cd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1260,6 +1260,34 @@ drm_do_probe_ddc_edid(void *data, u8 *buf, unsigned int block, size_t len) return ret == xfers ? 0 : -1; } +static void connector_bad_edid(struct drm_connector *connector, + u8 *edid, int num_blocks) +{ + int i; + + if (connector->bad_edid_counter++ && !(drm_debug & DRM_UT_KMS)) + return; + + dev_warn(connector->dev->dev, + "%s: EDID is invalid:\n", + connector->name); + for (i = 0; i < num_blocks; i++) { + u8 *block = edid + i * EDID_LENGTH; + char prefix[20]; + + if (drm_edid_is_zero(block, EDID_LENGTH)) + sprintf(prefix, "\t[%02x] ZERO ", i); + else if (!drm_edid_block_valid(block, i, false, NULL)) + sprintf(prefix, "\t[%02x] BAD ", i); + else + sprintf(prefix, "\t[%02x] GOOD ", i); + + print_hex_dump(KERN_WARNING, + prefix, DUMP_PREFIX_NONE, 16, 1, + block, EDID_LENGTH, false); + } +} + /** * drm_do_get_edid - get EDID data using a custom EDID block read function * @connector: connector we're probing @@ -1283,7 +1311,6 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, { int i, j = 0, valid_extensions = 0; u8 *edid, *new; - bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS); if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) return NULL; @@ -1292,7 +1319,7 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, for (i = 0; i < 4; i++) { if (get_edid_block(data, edid, 0, EDID_LENGTH)) goto out; - if (drm_edid_block_valid(edid, 0, print_bad_edid, + if (drm_edid_block_valid(edid, 0, false, &connector->edid_corrupt)) break; if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) { @@ -1304,54 +1331,60 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, goto carp; /* if there's no extensions, we're done */ - if (edid[0x7e] == 0) + valid_extensions = edid[0x7e]; + if (valid_extensions == 0) return (struct edid *)edid; - new = krealloc(edid, (edid[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); + new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); if (!new) goto out; edid = new; for (j = 1; j <= edid[0x7e]; j++) { - u8 *block = edid + (valid_extensions + 1) * EDID_LENGTH; + u8 *block = edid + j * EDID_LENGTH; for (i = 0; i < 4; i++) { if (get_edid_block(data, block, j, EDID_LENGTH)) goto out; - if (drm_edid_block_valid(block, j, - print_bad_edid, NULL)) { - valid_extensions++; + if (drm_edid_block_valid(block, j, false, NULL)) break; - } } - if (i == 4 && print_bad_edid) { - dev_warn(connector->dev->dev, - "%s: Ignoring invalid EDID block %d.\n", - connector->name, j); - - connector->bad_edid_counter++; - } + if (i == 4) + valid_extensions--; } if (valid_extensions != edid[0x7e]) { + u8 *base; + + connector_bad_edid(connector, edid, edid[0x7e] + 1); + edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions; edid[0x7e] = valid_extensions; - new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); + + new = kmalloc((valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); if (!new) goto out; + + base = new; + for (i = 0; i <= edid[0x7e]; i++) { + u8 *block = edid + i * EDID_LENGTH; + + if (!drm_edid_block_valid(block, i, false, NULL)) + continue; + + memcpy(base, block, EDID_LENGTH); + base += EDID_LENGTH; + } + + kfree(edid); edid = new; } return (struct edid *)edid; carp: - if (print_bad_edid) { - dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", - connector->name, j); - } - connector->bad_edid_counter++; - + connector_bad_edid(connector, edid, 1); out: kfree(edid); return NULL; -- cgit v1.2.3 From 714cf7ea505502186de0e87e9f029a4c46f03631 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 24 Oct 2016 19:33:24 +0300 Subject: drm/dp: Factor out helper to distinguish between branch and sink devices This check is open-coded in a few places, so it makes sense to simplify things by having a helper for it similar to the rest of DPCD feature helpers. v2: (Jani) - Move the helper to drm_dp_helper.h. - Split out this change to a separate patch. Cc: Jani Nikula Cc: dri-devel@lists.freedesktop.org Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477326811-30431-2-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 11 ++++------- include/drm/drm_dp_helper.h | 6 ++++++ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index acd0c51f74d5..01bc67194dba 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1452,8 +1452,7 @@ static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) if ((drm_debug & DRM_UT_KMS) == 0) return; - if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT)) + if (!drm_dp_is_branch(intel_dp->dpcd)) return; len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_HW_REV, &rev, 1); @@ -1471,8 +1470,7 @@ static void intel_dp_print_sw_revision(struct intel_dp *intel_dp) if ((drm_debug & DRM_UT_KMS) == 0) return; - if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT)) + if (!drm_dp_is_branch(intel_dp->dpcd)) return; len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV, &rev, 2); @@ -3607,8 +3605,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) if (!is_edp(intel_dp) && !intel_dp->sink_count) return false; - if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT)) + if (!drm_dp_is_branch(intel_dp->dpcd)) return true; /* native DP sink */ if (intel_dp->dpcd[DP_DPCD_REV] == 0x10) @@ -4096,7 +4093,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) return connector_status_connected; /* if there's no downstream port, we're done */ - if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)) + if (!drm_dp_is_branch(dpcd)) return connector_status_connected; /* If we're HPD-aware, SINK_COUNT changes dynamically */ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 2a79882cb68e..55bbeb0ff594 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -690,6 +690,12 @@ drm_dp_tps3_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED; } +static inline bool +drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + return dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT; +} + /* * DisplayPort AUX channel */ -- cgit v1.2.3 From 78010cd9736ec571796f4404524ed575b81238b9 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 24 Oct 2016 15:57:10 -0400 Subject: dma-buf/fence: add an lockdep_assert_held() Signed-off-by: Rob Clark Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477339030-32657-1-git-send-email-robdclark@gmail.com --- drivers/dma-buf/fence.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c index 4d51f9e83fa8..cc05dddc77a6 100644 --- a/drivers/dma-buf/fence.c +++ b/drivers/dma-buf/fence.c @@ -68,6 +68,8 @@ int fence_signal_locked(struct fence *fence) struct fence_cb *cur, *tmp; int ret = 0; + lockdep_assert_held(fence->lock); + if (WARN_ON(!fence)) return -EINVAL; -- cgit v1.2.3 From 02782a1963c97ae04e644592fbad3c3f2b365728 Mon Sep 17 00:00:00 2001 From: Pankaj Bharadiya Date: Mon, 17 Oct 2016 16:17:07 +0530 Subject: staging: dgnc: Remove some redundant functions dgnc_tty_preinit() and dgnc_tty_post_uninit() functions are used to allocate and free "dgnc_TmpWriteBuf" and this "dgnc_TmpWriteBuf" is not really getting used. Hence remove these redundant functions. Also remove dgnc_TmpWriteBuf variable as it is not used anymore. Signed-off-by: Pankaj Bharadiya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_driver.c | 13 ----------- drivers/staging/dgnc/dgnc_tty.c | 45 ++------------------------------------ drivers/staging/dgnc/dgnc_tty.h | 2 -- 3 files changed, 2 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 6576674e75b0..d3243a3c2a09 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -151,7 +151,6 @@ static void cleanup(bool sysfiles) dgnc_cleanup_board(dgnc_board[i]); } - dgnc_tty_post_uninit(); } /* @@ -241,16 +240,6 @@ static int dgnc_start(void) goto failed_device; } - /* - * Init any global tty stuff. - */ - rc = dgnc_tty_preinit(); - - if (rc < 0) { - pr_err(DRVSTR ": tty preinit - not enough memory (%d)\n", rc); - goto failed_tty; - } - /* Start the poller */ spin_lock_irqsave(&dgnc_poll_lock, flags); setup_timer(&dgnc_poll_timer, dgnc_poll_handler, 0); @@ -262,8 +251,6 @@ static int dgnc_start(void) return 0; -failed_tty: - device_destroy(dgnc_class, MKDEV(dgnc_major, 0)); failed_device: class_destroy(dgnc_class); failed_class: diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index cf8aefdc9534..5fb2fefcdaa3 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -42,11 +42,6 @@ #include "dgnc_sysfs.h" #include "dgnc_utils.h" -/* - * internal variables - */ -static unsigned char *dgnc_TmpWriteBuf; - /* * Default transparent print information. */ @@ -143,31 +138,6 @@ static const struct tty_operations dgnc_tty_ops = { * ************************************************************************/ -/* - * dgnc_tty_preinit() - * - * Initialize any global tty related data before we download any boards. - */ -int dgnc_tty_preinit(void) -{ - /* - * Allocate a buffer for doing the copy from user space to - * kernel space in dgnc_write(). We only use one buffer and - * control access to it with a semaphore. If we are paging, we - * are already in trouble so one buffer won't hurt much anyway. - * - * We are okay to sleep in the malloc, as this routine - * is only called during module load, (not in interrupt context), - * and with no locks held. - */ - dgnc_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_KERNEL); - - if (!dgnc_TmpWriteBuf) - return -ENOMEM; - - return 0; -} - /* * dgnc_tty_register() * @@ -364,17 +334,6 @@ err_free_channels: return -ENOMEM; } -/* - * dgnc_tty_post_uninit() - * - * UnInitialize any global tty related data. - */ -void dgnc_tty_post_uninit(void) -{ - kfree(dgnc_TmpWriteBuf); - dgnc_TmpWriteBuf = NULL; -} - /* * dgnc_cleanup_tty() * @@ -1543,7 +1502,7 @@ static int dgnc_tty_write_room(struct tty_struct *tty) int ret = 0; unsigned long flags; - if (!tty || !dgnc_TmpWriteBuf) + if (!tty) return 0; un = tty->driver_data; @@ -1623,7 +1582,7 @@ static int dgnc_tty_write(struct tty_struct *tty, ushort tmask; uint remain; - if (!tty || !dgnc_TmpWriteBuf) + if (!tty) return 0; un = tty->driver_data; diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h index 24c9a412211e..85a131075bd8 100644 --- a/drivers/staging/dgnc/dgnc_tty.h +++ b/drivers/staging/dgnc/dgnc_tty.h @@ -21,10 +21,8 @@ int dgnc_tty_register(struct dgnc_board *brd); void dgnc_tty_unregister(struct dgnc_board *brd); -int dgnc_tty_preinit(void); int dgnc_tty_init(struct dgnc_board *); -void dgnc_tty_post_uninit(void); void dgnc_cleanup_tty(struct dgnc_board *); void dgnc_input(struct channel_t *ch); -- cgit v1.2.3 From 4efdb3702580ffa18fdfcb3e45eb452c049e0d2a Mon Sep 17 00:00:00 2001 From: Pankaj Bharadiya Date: Mon, 17 Oct 2016 16:17:08 +0530 Subject: staging: dgnc: Replace CamelCase namings with underscores Replace CamelCase names with underscores to comply with the standard kernel coding style. Signed-off-by: Pankaj Bharadiya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_tty.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 5fb2fefcdaa3..8f8a3d117150 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -64,7 +64,7 @@ static const struct digi_t dgnc_digi_init = { * This defines a raw port at 9600 baud, 8 data bits, no parity, * 1 stop bit. */ -static struct ktermios DgncDefaultTermios = { +static struct ktermios default_termios = { .c_iflag = (DEFAULT_IFLAGS), /* iflags */ .c_oflag = (DEFAULT_OFLAGS), /* oflags */ .c_cflag = (DEFAULT_CFLAGS), /* cflags */ @@ -164,7 +164,7 @@ int dgnc_tty_register(struct dgnc_board *brd) brd->serial_driver->minor_start = 0; brd->serial_driver->type = TTY_DRIVER_TYPE_SERIAL; brd->serial_driver->subtype = SERIAL_TYPE_NORMAL; - brd->serial_driver->init_termios = DgncDefaultTermios; + brd->serial_driver->init_termios = default_termios; brd->serial_driver->driver_name = DRVSTR; /* @@ -203,7 +203,7 @@ int dgnc_tty_register(struct dgnc_board *brd) brd->print_driver->minor_start = 0x80; brd->print_driver->type = TTY_DRIVER_TYPE_SERIAL; brd->print_driver->subtype = SERIAL_TYPE_NORMAL; - brd->print_driver->init_termios = DgncDefaultTermios; + brd->print_driver->init_termios = default_termios; brd->print_driver->driver_name = DRVSTR; /* -- cgit v1.2.3 From 4b4462ecd025b7ec17cb9049707024a3a2915f57 Mon Sep 17 00:00:00 2001 From: Shyam Saini Date: Mon, 17 Oct 2016 19:04:46 +0530 Subject: Staging: gs_fpgaboot: Use octal permissions '0444' Fixed following checkpatch warning WARNING: Symbolic permissions 'S_IRUGO' are not preferred. Consider using octal permissions '0444'. Signed-off-by: Shyam Saini Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/gs_fpgaboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index 8ed4d395be58..19b550fff04b 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -38,7 +38,7 @@ static u8 bits_magic[] = { static struct platform_device *firmware_pdev; static char *file = "xlinx_fpga_firmware.bit"; -module_param(file, charp, S_IRUGO); +module_param(file, charp, 0444); MODULE_PARM_DESC(file, "Xilinx FPGA firmware file."); static void read_bitstream(char *bitdata, char *buf, int *offset, int rdsize) -- cgit v1.2.3 From 723863e82eb062c855becbf21aaa96cf6eee4234 Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Mon, 17 Oct 2016 17:39:22 +0200 Subject: staging: rtl8188eu: Fix coding style errors Fix coding style errors reported by checkpatch.pl, specifically: ERROR: space prohibited before that ',' (ctx:WxW) This patch get rid of all "ERROR" messages from checkpatch.pl for this file Signed-off-by: Carlos Maiolino Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index c94700cf5664..d9c114776cab 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -669,10 +669,10 @@ static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pss get_rate_set(padapter, bssrate, &bssrate_len); if (bssrate_len > 8) { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen)); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); } else { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen)); } /* add wps_ie for wps2.0 */ @@ -1001,7 +1001,7 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, } if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen)); /* add WPS IE ie for wps 2.0 */ if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) { @@ -1122,10 +1122,10 @@ static void issue_assocreq(struct adapter *padapter) if (bssrate_len > 8) { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen)); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); } else { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen)); } /* RSN */ @@ -1167,7 +1167,7 @@ static void issue_assocreq(struct adapter *padapter) memcpy(&pmlmeinfo->HT_caps.mcs, MCS_rate_2R, 16); break; } - pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); } } @@ -1196,7 +1196,7 @@ static void issue_assocreq(struct adapter *padapter) } if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen)); + pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen)); pattrib->last_txcmdsz = pattrib->pktlen; dump_mgntframe(padapter, pmgntframe); @@ -2646,7 +2646,7 @@ static unsigned int OnBeacon(struct adapter *padapter, ret = rtw_check_bcn_info(padapter, pframe, len); if (!ret) { DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n "); - receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 65535); + receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 65535); return _SUCCESS; } /* update WMM, ERP in the beacon */ @@ -2804,7 +2804,7 @@ static unsigned int OnAuth(struct adapter *padapter, /* checking for challenging txt... */ DBG_88E("checking for challenging txt...\n"); - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len, + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len, len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); if ((p == NULL) || (ie_len <= 0)) { @@ -3048,7 +3048,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, memcpy(supportRate, p+2, ie_len); supportRateNum = ie_len; - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len, + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); if (p != NULL) { if (supportRateNum <= sizeof(supportRate)) { @@ -3148,7 +3148,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, if (pmlmepriv->wps_beacon_ie) { u8 selected_registrar = 0; - rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL); + rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); if (!selected_registrar) { DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n"); @@ -3513,7 +3513,7 @@ static unsigned int OnDeAuth(struct adapter *padapter, DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n", reason, GetAddr3Ptr(pframe)); - receive_disconnect(padapter, GetAddr3Ptr(pframe) , reason); + receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); } pmlmepriv->LinkDetectInfo.bBusyTraffic = false; return _SUCCESS; -- cgit v1.2.3 From 5d43dfdba0e377c22fdd69e5d7b3e361c77348bb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 24 Oct 2016 17:38:34 +0200 Subject: staging: rtl8192x: fix bogus maybe-uninitialized warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rtllib_rx_extract_addr() is supposed to set up the mac addresses for four possible cases, based on two bits of input data. For some reason, gcc decides that it's possible that none of the these four cases apply and the addresses remain uninitialized: drivers/staging/rtl8192e/rtllib_rx.c: In function ‘rtllib_rx_InfraAdhoc’: include/linux/etherdevice.h:316:61: error: ‘*((void *)&dst+4)’ may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/staging/rtl8192e/rtllib_rx.c:1318:5: note: ‘*((void *)&dst+4)’ was declared here ded from /git/arm-soc/drivers/staging/rtl8192e/rtllib_rx.c:40:0: include/linux/etherdevice.h:316:36: error: ‘dst’ may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/staging/rtl8192e/rtllib_rx.c:1318:5: note: ‘dst’ was declared here This warning is clearly nonsense, but changing the last case into 'default' makes it obvious to the compiler too, which avoids the warning and probably leads to better object code too. As the same warning appears in other files that have the exact same code, I'm fixing it in both rtl8192e and rtl8192u, even though I did not observe it for the latter. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_rx.c | 2 +- drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c | 2 +- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index c743182b933e..d6777ecda64d 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -986,7 +986,7 @@ static void rtllib_rx_extract_addr(struct rtllib_device *ieee, ether_addr_copy(src, hdr->addr4); ether_addr_copy(bssid, ieee->current_network.bssid); break; - case 0: + default: ether_addr_copy(dst, hdr->addr1); ether_addr_copy(src, hdr->addr2); ether_addr_copy(bssid, hdr->addr3); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c index 6fa96d57d316..e68850897adf 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c @@ -553,7 +553,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */ break; - case 0: + default: memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ break; diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 89cbc077a48d..2e4d2d7bc2e7 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -1079,7 +1079,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, memcpy(src, hdr->addr4, ETH_ALEN); memcpy(bssid, ieee->current_network.bssid, ETH_ALEN); break; - case 0: + default: memcpy(dst, hdr->addr1, ETH_ALEN); memcpy(src, hdr->addr2, ETH_ALEN); memcpy(bssid, hdr->addr3, ETH_ALEN); -- cgit v1.2.3 From 824ebf182db01e705550bf4f031fabfc969a74bc Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Mon, 17 Oct 2016 13:42:18 -0500 Subject: staging: fsl-mc: cleanup: move dpbp and dpcon cmd headers The dpbp and dpcon cmd header files should not be in the public include directory but should be private to the bus driver. Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpbp-cmd.h | 185 ++++++++++++++++++++++++++ drivers/staging/fsl-mc/bus/dpbp.c | 3 +- drivers/staging/fsl-mc/bus/dpcon-cmd.h | 62 +++++++++ drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 4 +- drivers/staging/fsl-mc/include/dpbp-cmd.h | 185 -------------------------- drivers/staging/fsl-mc/include/dpcon-cmd.h | 62 --------- 6 files changed, 251 insertions(+), 250 deletions(-) create mode 100644 drivers/staging/fsl-mc/bus/dpbp-cmd.h create mode 100644 drivers/staging/fsl-mc/bus/dpcon-cmd.h delete mode 100644 drivers/staging/fsl-mc/include/dpbp-cmd.h delete mode 100644 drivers/staging/fsl-mc/include/dpcon-cmd.h (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpbp-cmd.h b/drivers/staging/fsl-mc/bus/dpbp-cmd.h new file mode 100644 index 000000000000..2860411ddb51 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpbp-cmd.h @@ -0,0 +1,185 @@ +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _FSL_DPBP_CMD_H +#define _FSL_DPBP_CMD_H + +/* DPBP Version */ +#define DPBP_VER_MAJOR 2 +#define DPBP_VER_MINOR 2 + +/* Command IDs */ +#define DPBP_CMDID_CLOSE 0x800 +#define DPBP_CMDID_OPEN 0x804 +#define DPBP_CMDID_CREATE 0x904 +#define DPBP_CMDID_DESTROY 0x900 + +#define DPBP_CMDID_ENABLE 0x002 +#define DPBP_CMDID_DISABLE 0x003 +#define DPBP_CMDID_GET_ATTR 0x004 +#define DPBP_CMDID_RESET 0x005 +#define DPBP_CMDID_IS_ENABLED 0x006 + +#define DPBP_CMDID_SET_IRQ 0x010 +#define DPBP_CMDID_GET_IRQ 0x011 +#define DPBP_CMDID_SET_IRQ_ENABLE 0x012 +#define DPBP_CMDID_GET_IRQ_ENABLE 0x013 +#define DPBP_CMDID_SET_IRQ_MASK 0x014 +#define DPBP_CMDID_GET_IRQ_MASK 0x015 +#define DPBP_CMDID_GET_IRQ_STATUS 0x016 +#define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017 + +#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0 +#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1 + +struct dpbp_cmd_open { + __le32 dpbp_id; +}; + +#define DPBP_ENABLE 0x1 + +struct dpbp_rsp_is_enabled { + u8 enabled; +}; + +struct dpbp_cmd_set_irq { + /* cmd word 0 */ + u8 irq_index; + u8 pad[3]; + __le32 irq_val; + /* cmd word 1 */ + __le64 irq_addr; + /* cmd word 2 */ + __le32 irq_num; +}; + +struct dpbp_cmd_get_irq { + __le32 pad; + u8 irq_index; +}; + +struct dpbp_rsp_get_irq { + /* response word 0 */ + __le32 irq_val; + __le32 pad; + /* response word 1 */ + __le64 irq_addr; + /* response word 2 */ + __le32 irq_num; + __le32 type; +}; + +struct dpbp_cmd_set_irq_enable { + u8 enable; + u8 pad[3]; + u8 irq_index; +}; + +struct dpbp_cmd_get_irq_enable { + __le32 pad; + u8 irq_index; +}; + +struct dpbp_rsp_get_irq_enable { + u8 enabled; +}; + +struct dpbp_cmd_set_irq_mask { + __le32 mask; + u8 irq_index; +}; + +struct dpbp_cmd_get_irq_mask { + __le32 pad; + u8 irq_index; +}; + +struct dpbp_rsp_get_irq_mask { + __le32 mask; +}; + +struct dpbp_cmd_get_irq_status { + __le32 status; + u8 irq_index; +}; + +struct dpbp_rsp_get_irq_status { + __le32 status; +}; + +struct dpbp_cmd_clear_irq_status { + __le32 status; + u8 irq_index; +}; + +struct dpbp_rsp_get_attributes { + /* response word 0 */ + __le16 pad; + __le16 bpid; + __le32 id; + /* response word 1 */ + __le16 version_major; + __le16 version_minor; +}; + +struct dpbp_cmd_set_notifications { + /* cmd word 0 */ + __le32 depletion_entry; + __le32 depletion_exit; + /* cmd word 1 */ + __le32 surplus_entry; + __le32 surplus_exit; + /* cmd word 2 */ + __le16 options; + __le16 pad[3]; + /* cmd word 3 */ + __le64 message_ctx; + /* cmd word 4 */ + __le64 message_iova; +}; + +struct dpbp_rsp_get_notifications { + /* response word 0 */ + __le32 depletion_entry; + __le32 depletion_exit; + /* response word 1 */ + __le32 surplus_entry; + __le32 surplus_exit; + /* response word 2 */ + __le16 options; + __le16 pad[3]; + /* response word 3 */ + __le64 message_ctx; + /* response word 4 */ + __le64 message_iova; +}; + +#endif /* _FSL_DPBP_CMD_H */ diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index 5d4cd812a400..b392745a4f83 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -32,7 +32,8 @@ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dpbp.h" -#include "../include/dpbp-cmd.h" + +#include "dpbp-cmd.h" /** * dpbp_open() - Open a control session for the specified object. diff --git a/drivers/staging/fsl-mc/bus/dpcon-cmd.h b/drivers/staging/fsl-mc/bus/dpcon-cmd.h new file mode 100644 index 000000000000..536b2ef13507 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpcon-cmd.h @@ -0,0 +1,62 @@ +/* Copyright 2013-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _FSL_DPCON_CMD_H +#define _FSL_DPCON_CMD_H + +/* DPCON Version */ +#define DPCON_VER_MAJOR 2 +#define DPCON_VER_MINOR 1 + +/* Command IDs */ +#define DPCON_CMDID_CLOSE 0x800 +#define DPCON_CMDID_OPEN 0x808 +#define DPCON_CMDID_CREATE 0x908 +#define DPCON_CMDID_DESTROY 0x900 + +#define DPCON_CMDID_ENABLE 0x002 +#define DPCON_CMDID_DISABLE 0x003 +#define DPCON_CMDID_GET_ATTR 0x004 +#define DPCON_CMDID_RESET 0x005 +#define DPCON_CMDID_IS_ENABLED 0x006 + +#define DPCON_CMDID_SET_IRQ 0x010 +#define DPCON_CMDID_GET_IRQ 0x011 +#define DPCON_CMDID_SET_IRQ_ENABLE 0x012 +#define DPCON_CMDID_GET_IRQ_ENABLE 0x013 +#define DPCON_CMDID_SET_IRQ_MASK 0x014 +#define DPCON_CMDID_GET_IRQ_MASK 0x015 +#define DPCON_CMDID_GET_IRQ_STATUS 0x016 +#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017 + +#define DPCON_CMDID_SET_NOTIFICATION 0x100 + +#endif /* _FSL_DPCON_CMD_H */ diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index e93ab53bae67..cf1014822906 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -12,9 +12,9 @@ #include #include "../include/mc-bus.h" #include "../include/mc-sys.h" -#include "../include/dpbp-cmd.h" -#include "../include/dpcon-cmd.h" +#include "dpbp-cmd.h" +#include "dpcon-cmd.h" #include "fsl-mc-private.h" #define FSL_MC_IS_ALLOCATABLE(_obj_type) \ diff --git a/drivers/staging/fsl-mc/include/dpbp-cmd.h b/drivers/staging/fsl-mc/include/dpbp-cmd.h deleted file mode 100644 index 2860411ddb51..000000000000 --- a/drivers/staging/fsl-mc/include/dpbp-cmd.h +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the above-listed copyright holders nor the - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any - * later version. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _FSL_DPBP_CMD_H -#define _FSL_DPBP_CMD_H - -/* DPBP Version */ -#define DPBP_VER_MAJOR 2 -#define DPBP_VER_MINOR 2 - -/* Command IDs */ -#define DPBP_CMDID_CLOSE 0x800 -#define DPBP_CMDID_OPEN 0x804 -#define DPBP_CMDID_CREATE 0x904 -#define DPBP_CMDID_DESTROY 0x900 - -#define DPBP_CMDID_ENABLE 0x002 -#define DPBP_CMDID_DISABLE 0x003 -#define DPBP_CMDID_GET_ATTR 0x004 -#define DPBP_CMDID_RESET 0x005 -#define DPBP_CMDID_IS_ENABLED 0x006 - -#define DPBP_CMDID_SET_IRQ 0x010 -#define DPBP_CMDID_GET_IRQ 0x011 -#define DPBP_CMDID_SET_IRQ_ENABLE 0x012 -#define DPBP_CMDID_GET_IRQ_ENABLE 0x013 -#define DPBP_CMDID_SET_IRQ_MASK 0x014 -#define DPBP_CMDID_GET_IRQ_MASK 0x015 -#define DPBP_CMDID_GET_IRQ_STATUS 0x016 -#define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017 - -#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0 -#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1 - -struct dpbp_cmd_open { - __le32 dpbp_id; -}; - -#define DPBP_ENABLE 0x1 - -struct dpbp_rsp_is_enabled { - u8 enabled; -}; - -struct dpbp_cmd_set_irq { - /* cmd word 0 */ - u8 irq_index; - u8 pad[3]; - __le32 irq_val; - /* cmd word 1 */ - __le64 irq_addr; - /* cmd word 2 */ - __le32 irq_num; -}; - -struct dpbp_cmd_get_irq { - __le32 pad; - u8 irq_index; -}; - -struct dpbp_rsp_get_irq { - /* response word 0 */ - __le32 irq_val; - __le32 pad; - /* response word 1 */ - __le64 irq_addr; - /* response word 2 */ - __le32 irq_num; - __le32 type; -}; - -struct dpbp_cmd_set_irq_enable { - u8 enable; - u8 pad[3]; - u8 irq_index; -}; - -struct dpbp_cmd_get_irq_enable { - __le32 pad; - u8 irq_index; -}; - -struct dpbp_rsp_get_irq_enable { - u8 enabled; -}; - -struct dpbp_cmd_set_irq_mask { - __le32 mask; - u8 irq_index; -}; - -struct dpbp_cmd_get_irq_mask { - __le32 pad; - u8 irq_index; -}; - -struct dpbp_rsp_get_irq_mask { - __le32 mask; -}; - -struct dpbp_cmd_get_irq_status { - __le32 status; - u8 irq_index; -}; - -struct dpbp_rsp_get_irq_status { - __le32 status; -}; - -struct dpbp_cmd_clear_irq_status { - __le32 status; - u8 irq_index; -}; - -struct dpbp_rsp_get_attributes { - /* response word 0 */ - __le16 pad; - __le16 bpid; - __le32 id; - /* response word 1 */ - __le16 version_major; - __le16 version_minor; -}; - -struct dpbp_cmd_set_notifications { - /* cmd word 0 */ - __le32 depletion_entry; - __le32 depletion_exit; - /* cmd word 1 */ - __le32 surplus_entry; - __le32 surplus_exit; - /* cmd word 2 */ - __le16 options; - __le16 pad[3]; - /* cmd word 3 */ - __le64 message_ctx; - /* cmd word 4 */ - __le64 message_iova; -}; - -struct dpbp_rsp_get_notifications { - /* response word 0 */ - __le32 depletion_entry; - __le32 depletion_exit; - /* response word 1 */ - __le32 surplus_entry; - __le32 surplus_exit; - /* response word 2 */ - __le16 options; - __le16 pad[3]; - /* response word 3 */ - __le64 message_ctx; - /* response word 4 */ - __le64 message_iova; -}; - -#endif /* _FSL_DPBP_CMD_H */ diff --git a/drivers/staging/fsl-mc/include/dpcon-cmd.h b/drivers/staging/fsl-mc/include/dpcon-cmd.h deleted file mode 100644 index 536b2ef13507..000000000000 --- a/drivers/staging/fsl-mc/include/dpcon-cmd.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the above-listed copyright holders nor the - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any - * later version. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _FSL_DPCON_CMD_H -#define _FSL_DPCON_CMD_H - -/* DPCON Version */ -#define DPCON_VER_MAJOR 2 -#define DPCON_VER_MINOR 1 - -/* Command IDs */ -#define DPCON_CMDID_CLOSE 0x800 -#define DPCON_CMDID_OPEN 0x808 -#define DPCON_CMDID_CREATE 0x908 -#define DPCON_CMDID_DESTROY 0x900 - -#define DPCON_CMDID_ENABLE 0x002 -#define DPCON_CMDID_DISABLE 0x003 -#define DPCON_CMDID_GET_ATTR 0x004 -#define DPCON_CMDID_RESET 0x005 -#define DPCON_CMDID_IS_ENABLED 0x006 - -#define DPCON_CMDID_SET_IRQ 0x010 -#define DPCON_CMDID_GET_IRQ 0x011 -#define DPCON_CMDID_SET_IRQ_ENABLE 0x012 -#define DPCON_CMDID_GET_IRQ_ENABLE 0x013 -#define DPCON_CMDID_SET_IRQ_MASK 0x014 -#define DPCON_CMDID_GET_IRQ_MASK 0x015 -#define DPCON_CMDID_GET_IRQ_STATUS 0x016 -#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017 - -#define DPCON_CMDID_SET_NOTIFICATION 0x100 - -#endif /* _FSL_DPCON_CMD_H */ -- cgit v1.2.3 From 8cf663053411f4b98689144e0588a8090df53fcb Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Mon, 17 Oct 2016 13:42:28 -0500 Subject: staging: fsl-mc: add missing includes to fsl-mc-private.h fsl-mc-private.h references several definitions that it does not explicitly have includes for. Up until now we've gotten lucky due to include ordering that things compile. Add the missing includes. Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/fsl-mc-private.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-private.h b/drivers/staging/fsl-mc/bus/fsl-mc-private.h index d459c2673f39..5c49c9d2df6a 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-private.h +++ b/drivers/staging/fsl-mc/bus/fsl-mc-private.h @@ -10,6 +10,9 @@ #ifndef _FSL_MC_PRIVATE_H_ #define _FSL_MC_PRIVATE_H_ +#include "../include/mc.h" +#include "../include/mc-bus.h" + int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, struct fsl_mc_io *mc_io, struct device *parent_dev, -- cgit v1.2.3 From 8431dc5d8dfb4941805cbf06ce2307c3b3f7f1f7 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Mon, 17 Oct 2016 13:42:34 -0500 Subject: staging: fsl-mc: clean up Kconfig description Except for copyrights we are avoiding all references to Freescale, which no longer exists as a brand. Cleanup Freescale references and simplify the Kconfig description of the fsl-mc bus. Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/Kconfig | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig index 1f959339c671..aa9c04cf3b04 100644 --- a/drivers/staging/fsl-mc/bus/Kconfig +++ b/drivers/staging/fsl-mc/bus/Kconfig @@ -1,25 +1,17 @@ # -# Freescale Management Complex (MC) bus drivers +# DPAA2 fsl-mc bus # -# Copyright (C) 2014 Freescale Semiconductor, Inc. +# Copyright (C) 2014-2016 Freescale Semiconductor, Inc. # # This file is released under the GPLv2 # config FSL_MC_BUS - bool "Freescale Management Complex (MC) bus driver" + bool "QorIQ DPAA2 fsl-mc bus driver" depends on OF && ARM64 select GENERIC_MSI_IRQ_DOMAIN help - Driver to enable the bus infrastructure for the Freescale - QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware - module of the QorIQ LS2 SoCs, that does resource management - for hardware building-blocks in the SoC that can be used - to dynamically create networking hardware objects such as - network interfaces (NICs), crypto accelerator instances, - or L2 switches. - - Only enable this option when building the kernel for - Freescale QorQIQ LS2xxxx SoCs. - - + Driver to enable the bus infrastructure for the QorIQ DPAA2 + architecture. The fsl-mc bus driver handles discovery of + DPAA2 objects (which are represented as Linux devices) and + binding objects to drivers. -- cgit v1.2.3 From 3642b8ea38cd433ab16ea1f87e56dda7f0659ea4 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Mon, 17 Oct 2016 13:42:40 -0500 Subject: staging: fsl-mc: update Kconfig dependency The Kconfig dependency previously included ARM64, which is not strictly correct. Change it to ARCH_LAYERSCAPE which is the SoC platform that includes the DPAA2 hardware. Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig index aa9c04cf3b04..5c009ab48f00 100644 --- a/drivers/staging/fsl-mc/bus/Kconfig +++ b/drivers/staging/fsl-mc/bus/Kconfig @@ -8,7 +8,7 @@ config FSL_MC_BUS bool "QorIQ DPAA2 fsl-mc bus driver" - depends on OF && ARM64 + depends on OF && ARCH_LAYERSCAPE select GENERIC_MSI_IRQ_DOMAIN help Driver to enable the bus infrastructure for the QorIQ DPAA2 -- cgit v1.2.3 From d64c28a3139a52febc9549894ccb4c0a47c94466 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Mon, 17 Oct 2016 13:42:53 -0500 Subject: staging: fsl-mc: irq: shorten name of interrupt name For /proc/interrupts readability, platform bus MSIs are named "ITS-pMSI" in the GIC ITS implementation for that bus. Follow a similar naming convention and call fsl-mc bus MSIs "ITS-fMSI". Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index 7a6ac640752f..16b0d4a60205 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -19,7 +19,7 @@ #include "../include/mc-bus.h" static struct irq_chip its_msi_irq_chip = { - .name = "fsl-mc-bus-msi", + .name = "ITS-fMSI", .irq_mask = irq_chip_mask_parent, .irq_unmask = irq_chip_unmask_parent, .irq_eoi = irq_chip_eoi_parent, -- cgit v1.2.3 From dffeacd95ed626b4f94f9af5c49145c615422e91 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Mon, 17 Oct 2016 13:43:01 -0500 Subject: staging: fsl-mc: dprc: shorten DPRC interrupt name improve readibility of the DPRC interrupt name in sysfs by shortening this and just using the device name. There is only one interrupt DPRC used, so no further differentiation is needed. Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index c5ee4639682b..6aa2915e8096 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -505,7 +505,7 @@ static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) dprc_irq0_handler, dprc_irq0_handler_thread, IRQF_NO_SUSPEND | IRQF_ONESHOT, - "FSL MC DPRC irq0", + dev_name(&mc_dev->dev), &mc_dev->dev); if (error < 0) { dev_err(&mc_dev->dev, -- cgit v1.2.3 From 3e93e354de1e103d012c9f9909bf5a1026d4e46a Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 17 Oct 2016 13:43:08 -0500 Subject: staging: fsl-mc: cleanup: convert uintX_t types to uX Replace all uses of uintX_t types with uX types in order to comply with kernel coding style and resolve checkpatch warnings. Signed-off-by: Ioana Ciornei Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpmcp.h | 84 +++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h index fe79d4d9293d..5434e094985b 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/drivers/staging/fsl-mc/bus/dpmcp.h @@ -39,16 +39,16 @@ struct fsl_mc_io; int dpmcp_open(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, + u32 cmd_flags, int dpmcp_id, - uint16_t *token); + u16 *token); /* Get portal ID from pool */ #define DPMCP_GET_PORTAL_ID_FROM_POOL (-1) int dpmcp_close(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token); + u32 cmd_flags, + u16 token); /** * struct dpmcp_cfg - Structure representing DPMCP configuration @@ -60,17 +60,17 @@ struct dpmcp_cfg { }; int dpmcp_create(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, + u32 cmd_flags, const struct dpmcp_cfg *cfg, - uint16_t *token); + u16 *token); int dpmcp_destroy(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token); + u32 cmd_flags, + u16 token); int dpmcp_reset(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token); + u32 cmd_flags, + u16 token); /* IRQ */ /* IRQ Index */ @@ -85,53 +85,53 @@ int dpmcp_reset(struct fsl_mc_io *mc_io, * @irq_num: A user defined number associated with this IRQ */ struct dpmcp_irq_cfg { - uint64_t paddr; - uint32_t val; + u64 paddr; + u32 val; int irq_num; }; int dpmcp_set_irq(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t irq_index, + u32 cmd_flags, + u16 token, + u8 irq_index, struct dpmcp_irq_cfg *irq_cfg); int dpmcp_get_irq(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t irq_index, + u32 cmd_flags, + u16 token, + u8 irq_index, int *type, struct dpmcp_irq_cfg *irq_cfg); int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t irq_index, - uint8_t en); + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 en); int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t irq_index, - uint8_t *en); + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 *en); int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t irq_index, - uint32_t mask); + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 mask); int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t irq_index, - uint32_t *mask); + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *mask); int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t irq_index, - uint32_t *status); + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *status); /** * struct dpmcp_attr - Structure representing DPMCP attributes @@ -146,14 +146,14 @@ struct dpmcp_attr { * @minor: DPMCP minor version */ struct { - uint16_t major; - uint16_t minor; + u16 major; + u16 minor; } version; }; int dpmcp_get_attributes(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, + u32 cmd_flags, + u16 token, struct dpmcp_attr *attr); #endif /* __FSL_DPMCP_H */ -- cgit v1.2.3 From f2503acfe3ffe8771d2a1f4ea1b89f67d819d037 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 17 Oct 2016 16:21:21 -0300 Subject: staging: fbtft: Fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/staging/fbtft/flexfb.ko | grep alias $ After this patch: $ modinfo drivers/staging/fbtft/flexfb.ko | grep alias alias: platform:flexpfb Signed-off-by: Javier Martinez Canillas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/flexfb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c index 2dc5f9b6b47e..ded10718712b 100644 --- a/drivers/staging/fbtft/flexfb.c +++ b/drivers/staging/fbtft/flexfb.c @@ -830,6 +830,7 @@ static const struct platform_device_id flexfb_platform_ids[] = { { "flexpfb", 0 }, { }, }; +MODULE_DEVICE_TABLE(platform, flexfb_platform_ids); static struct platform_driver flexfb_platform_driver = { .driver = { -- cgit v1.2.3 From c444ebc83ee233849f32b41d43953bddce06c8f3 Mon Sep 17 00:00:00 2001 From: Nadim Almas Date: Mon, 24 Oct 2016 22:14:37 +0530 Subject: Staging:fbtft: Replace decimal permissions with 4 digit octal ERROR: Use 4 digit octal (0777) not decimal permissions This error was detected by checkpatch.pl Signed-off-by: Nadim Almas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_ili9325.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index 4ab44791d27c..19e33bab9cac 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -33,23 +33,23 @@ "04 16 2 7 6 3 2 1 7 7" static unsigned int bt = 6; /* VGL=Vci*4 , VGH=Vci*4 */ -module_param(bt, uint, 0); +module_param(bt, uint, 0000); MODULE_PARM_DESC(bt, "Sets the factor used in the step-up circuits"); static unsigned int vc = 0x03; /* Vci1=Vci*0.80 */ -module_param(vc, uint, 0); +module_param(vc, uint, 0000); MODULE_PARM_DESC(vc, "Sets the ratio factor of Vci to generate the reference voltages Vci1"); static unsigned int vrh = 0x0d; /* VREG1OUT=Vci*1.85 */ -module_param(vrh, uint, 0); +module_param(vrh, uint, 0000); MODULE_PARM_DESC(vrh, "Set the amplifying rate (1.6 ~ 1.9) of Vci applied to output the VREG1OUT"); static unsigned int vdv = 0x12; /* VCOMH amplitude=VREG1OUT*0.98 */ -module_param(vdv, uint, 0); +module_param(vdv, uint, 0000); MODULE_PARM_DESC(vdv, "Select the factor of VREG1OUT to set the amplitude of Vcom"); static unsigned int vcm = 0x0a; /* VCOMH=VREG1OUT*0.735 */ -module_param(vcm, uint, 0); +module_param(vcm, uint, 0000); MODULE_PARM_DESC(vcm, "Set the internal VcomH voltage"); /* -- cgit v1.2.3 From d4bcd7e75cce12cc596144688a8167cef19e886c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 18 Oct 2016 00:42:27 +0200 Subject: staging: lustre: restore initialization of return code A recent rework dropped the initialization of the initialization of the successful return code in lov_getstripe: drivers/staging/lustre/lustre/lov/lov_pack.c: In function 'lov_getstripe': drivers/staging/lustre/lustre/lov/lov_pack.c:426:9: error: 'rc' may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/staging/lustre/lustre/lov/lov_pack.c:313:6: note: 'rc' was declared here This adds it back. Fixes: e10a431b3fd0 ("staging: lustre: lov: move LSM to LOV layer") Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_pack.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 17bceadd66f8..ccc1fae35791 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -418,6 +418,8 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, ((struct lov_user_md *)lmmk)->lmm_stripe_count = lum.lmm_stripe_count; if (copy_to_user(lump, lmmk, lmm_size)) rc = -EFAULT; + else + rc = 0; out_free: kvfree(lmmk); -- cgit v1.2.3 From 1b301e8343d24a7345bb84831f92e13afe6afeef Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 18 Oct 2016 00:08:56 +0200 Subject: staging: lustre: remove broken dead code in cfs_cpt_table_create_pattern After a recent bugfix, we get a warning about the use of an uninitialized variable: drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c: In function 'cfs_cpt_table_create_pattern': drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c:833:7: error: 'str' may be used uninitialized in this function [-Werror=maybe-uninitialized] This part of the function used to not do anything as we would reassign the 'str' pointer to something else right away, but now we pass an uninitialized pointer into 'strchr', which can cause a kernel page fault or worse. Fixes: 239fd5d41f9b ("staging: lustre: libcfs: shortcut to create CPT from NUMA topology") Cc: Liang Zhen Cc: James Simmons Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c index 464b27923ac0..6a31521f6ae0 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c @@ -829,13 +829,6 @@ cfs_cpt_table_create_pattern(char *pattern) int c; int i; - for (ncpt = 0;; ncpt++) { /* quick scan bracket */ - str = strchr(str, '['); - if (!str) - break; - str++; - } - str = cfs_trimwhite(pattern); if (*str == 'n' || *str == 'N') { pattern = str + 1; -- cgit v1.2.3 From f99e73a5e3ff556bc69e5e592fee18d4cb7600dd Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Sat, 22 Oct 2016 08:34:49 +0800 Subject: Staging: lustre: lov: check return value of lov_sub_get() Check return value of lov_sub_get() in lov_io_read_ahead(). Signed-off-by: Jinshan Xiong Reported-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_io.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index a1d1ec9dd72e..011ab0f3ccc1 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -606,6 +606,8 @@ static int lov_io_read_ahead(const struct lu_env *env, return -EIO; sub = lov_sub_get(env, lio, stripe); + if (IS_ERR(sub)) + return PTR_ERR(sub); lov_stripe_offset(loo->lo_lsm, cl_offset(obj, start), stripe, &suboff); rc = cl_io_read_ahead(sub->sub_env, sub->sub_io, -- cgit v1.2.3 From a6ec5bb812fdaab5e2b7e73d4527c7cc477448a2 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Sat, 22 Oct 2016 22:30:44 -0200 Subject: staging: lustre: Move assignments out of function calls. Assignments inside of function calls confuse the reader and should be avoided, so it was moved out before the call. Found with Coccinelle, semantic patch: @@ identifier f; expression e1, e2; assignment operator a; @@ + e1 a e2; f(..., - (e1 a e2) + e1 ,...); Signed-off-by: Elise Lennion Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/vvp_io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 1a4b89723bc6..87fdab240bc0 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -450,7 +450,8 @@ static void vvp_io_advance(const struct lu_env *env, struct vvp_io *vio = cl2vvp_io(env, ios); CLOBINVRNT(env, obj, vvp_object_invariant(obj)); - iov_iter_reexpand(vio->vui_iter, vio->vui_tot_count -= nob); + vio->vui_tot_count -= nob; + iov_iter_reexpand(vio->vui_iter, vio->vui_tot_count); } static void vvp_io_update_iov(const struct lu_env *env, -- cgit v1.2.3 From a95cd6deebb44f6e3192e6819e1671f623b8449b Mon Sep 17 00:00:00 2001 From: Xavier Roumegue Date: Tue, 18 Oct 2016 22:56:50 +0200 Subject: staging: clocking-wizard: Fix incorrect type of speed grade MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The speed grade type is unsigned according to the dt-bindings. Fix sparse issue (-Wtypesign): CHECK drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:162:56: warning: incorrect type in argument 3 (different signedness) drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:162:56: expected unsigned int [usertype] *out_value drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:162:56: got int * Signed-off-by: Xavier Roumegue Acked-by: Sören Brinkmann Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c index 7b8be5293883..bf3fe7c61be5 100644 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c @@ -68,7 +68,7 @@ struct clk_wzrd { struct clk *axi_clk; struct clk *clks_internal[wzrd_clk_int_max]; struct clk *clkout[WZRD_NUM_OUTPUTS]; - int speed_grade; + unsigned int speed_grade; bool suspended; }; -- cgit v1.2.3 From 5123e93e193951249ff10b4c382e678b95433721 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 17 Oct 2016 12:44:05 -0700 Subject: staging/vchi: Add a TODO file of things I know we need to deal with. I've left out the downstream HDMI audio driver from the "to be imported" section, as we'll want to handle it natively in vc4. The downstream kernel will likely continue to use that driver for a while due to using the interim "vc4 firmware KMS" mode while vc4 gets its featureset (such as HDMI audio!) completed. I've also left out VC-CMA, which appears to be about having Linux manage a CMA area that the firmware gets to make allocations out of. I'm not clear on if this is useful (the firmware's need for memory drops massively with vc4 present, and may drop even more depending on how we resolve dmabuf handling for camera and video decode) Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchi/TODO | 50 +++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 drivers/staging/vc04_services/interface/vchi/TODO (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchi/TODO b/drivers/staging/vc04_services/interface/vchi/TODO new file mode 100644 index 000000000000..03aa65183b25 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/TODO @@ -0,0 +1,50 @@ +1) Port to aarch64 + +This driver won't be very useful unless we also have it working on +Raspberry Pi 3. This requires, at least: + + - Figure out an alternative to the dmac_map_area() hack. + + - Decide what to use instead of dsb(). + + - Do something about (int) cast of bulk->data in + vchiq_bulk_transfer(). + + bulk->data is a bus address going across to the firmware. We know + our bus addresses are <32bit. + +2) Write a DT binding doc and get the corresponding DT node merged to + bcm2835. + +This will let the driver probe when enabled. + +3) Import drivers using VCHI. + +VCHI is just a tool to let drivers talk to the firmware. Here are +some of the ones we want: + + - vc_mem (https://github.com/raspberrypi/linux/blob/rpi-4.4.y/drivers/char/broadcom/vc_mem.c) + + This driver is what the vcdbg userspace program uses to set up its + requests to the firmware, which are transmitted across VCHIQ. vcdbg + is really useful for debugging firmware interactions. + + - bcm2835-camera (https://github.com/raspberrypi/linux/tree/rpi-4.4.y/drivers/media/platform/bcm2835) + + This driver will let us get images from the camera using the MMAL + protocol over VCHI. + + - VCSM (https://github.com/raspberrypi/linux/tree/rpi-4.4.y/drivers/char/broadcom/vc_sm) + + This driver is used for talking about regions of VC memory across + firmware protocols including VCHI. We'll want to extend this driver + to manage these buffers as dmabufs so that we can zero-copy import + camera images into vc4 for rendering/display. + +4) Garbage-collect unused code + +One of the reasons this driver wasn't upstreamed previously was that +there's a lot code that got built that's probably unnecessary these +days. Once we have the set of VCHI-using drivers we want in tree, we +should be able to do a sweep of the code to see what's left that's +unused. -- cgit v1.2.3 From cf8e732b54b6250086c6bbef22a97e423f90c8f4 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 17 Oct 2016 15:08:14 +0000 Subject: staging: bcm2708_vchiq: remove .owner field for driver Remove .owner field if calls are used which set it automatically. Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 5ec7c96fad33..ed388c41747b 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2884,7 +2884,6 @@ MODULE_DEVICE_TABLE(of, vchiq_of_match); static struct platform_driver vchiq_driver = { .driver = { .name = "bcm2835_vchiq", - .owner = THIS_MODULE, .of_match_table = vchiq_of_match, }, .probe = vchiq_probe, -- cgit v1.2.3 From b04451d7dfac891daaab2eb88422839660560ba4 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 17 Oct 2016 15:06:07 +0000 Subject: staging: bcm2708_vchiq: fix return value check in vchiq_platform_conn_state_changed() In case of error, the function kthread_create() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index ed388c41747b..a89375d56fa0 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2774,7 +2774,7 @@ void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, &vchiq_keepalive_thread_func, (void *)state, threadname); - if (arm_state->ka_thread == NULL) { + if (IS_ERR(arm_state->ka_thread)) { vchiq_log_error(vchiq_susp_log_level, "vchiq: FATAL: couldn't create thread %s", threadname); -- cgit v1.2.3 From d298ec65803b48a764ae9ccf2ed2238669a4d02b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 17 Oct 2016 15:05:36 +0000 Subject: staging: bcm2708_vchiq: fix return value check in vchiq_init_state() In case of error, the function kthread_create() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index e29262971b02..c58f5cb16318 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -2440,7 +2440,7 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, (void *)state, threadname); - if (state->slot_handler_thread == NULL) { + if (IS_ERR(state->slot_handler_thread)) { vchiq_loud_error_header(); vchiq_loud_error("couldn't create thread %s", threadname); vchiq_loud_error_footer(); @@ -2453,7 +2453,7 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, state->recycle_thread = kthread_create(&recycle_func, (void *)state, threadname); - if (state->recycle_thread == NULL) { + if (IS_ERR(state->recycle_thread)) { vchiq_loud_error_header(); vchiq_loud_error("couldn't create thread %s", threadname); vchiq_loud_error_footer(); @@ -2466,7 +2466,7 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, state->sync_thread = kthread_create(&sync_func, (void *)state, threadname); - if (state->sync_thread == NULL) { + if (IS_ERR(state->sync_thread)) { vchiq_loud_error_header(); vchiq_loud_error("couldn't create thread %s", threadname); vchiq_loud_error_footer(); -- cgit v1.2.3 From ef5aa934cf031ef9525b29e35c5d381698d55ca5 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 17 Oct 2016 23:35:49 +0000 Subject: staging: rts5208: rtsx.c: Fix invalid use of sizeof in rtsx_probe() sizeof() when applied to a pointer typed expression gives the size of the pointer, not that of the pointed data. Fixes: 2eb9d8cbb3c3 ("staging: rts5208: rtsx.c: Alloc sizeof struct") Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index f3e5efdf0ffc..68d75d0d5efd 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -884,7 +884,7 @@ static int rtsx_probe(struct pci_dev *pci, dev = host_to_rtsx(host); memset(dev, 0, sizeof(struct rtsx_dev)); - dev->chip = kzalloc(sizeof(dev->chip), GFP_KERNEL); + dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL); if (!dev->chip) { err = -ENOMEM; goto errout; -- cgit v1.2.3 From c536c5de34580f23573805ee4ec3a7600e3f44f8 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Oct 2016 14:37:26 +0000 Subject: staging: i4l: pcbit: drv: remove duplicated include from drv.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/pcbit/drv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/i4l/pcbit/drv.c b/drivers/staging/i4l/pcbit/drv.c index 87b852259b89..89b0b5b94ce5 100644 --- a/drivers/staging/i4l/pcbit/drv.c +++ b/drivers/staging/i4l/pcbit/drv.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From b26639697b1274cbce4eab54ae7d69c0a35e2f0e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Oct 2016 14:37:10 +0000 Subject: staging: i4l: pcbit: remove duplicated include from capi.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/pcbit/capi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/i4l/pcbit/capi.c b/drivers/staging/i4l/pcbit/capi.c index 91f299477d43..a6c4e00dc726 100644 --- a/drivers/staging/i4l/pcbit/capi.c +++ b/drivers/staging/i4l/pcbit/capi.c @@ -27,7 +27,6 @@ * encode our number in CallerPN and ConnectedPN */ -#include #include #include -- cgit v1.2.3 From 5e935b782a7177361603ffb061c5d2fe49ea6b80 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Oct 2016 14:38:06 +0000 Subject: staging: ks7010: remove unused including Remove including that don't need it. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan.h b/drivers/staging/ks7010/ks_wlan.h index 5851714b6359..69811706bd24 100644 --- a/drivers/staging/ks7010/ks_wlan.h +++ b/drivers/staging/ks7010/ks_wlan.h @@ -14,7 +14,6 @@ #define WPS -#include #include #include #include -- cgit v1.2.3 From 35092b6d9b74d4ff555191f86c44a54e35708893 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Oct 2016 14:37:47 +0000 Subject: staging: ks7010: convert list_for_each to entry variant convert list_for_each() to list_for_each_entry() where applicable. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index cbf49c951514..1fbd495e5e63 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -2402,13 +2402,11 @@ void hostif_sme_set_pmksa(struct ks_wlan_private *priv) } __packed list[PMK_LIST_MAX]; } __packed pmkcache; struct pmk_t *pmk; - struct list_head *ptr; int i; DPRINTK(4, "pmklist.size=%d\n", priv->pmklist.size); i = 0; - list_for_each(ptr, &priv->pmklist.head) { - pmk = list_entry(ptr, struct pmk_t, list); + list_for_each_entry(pmk, &priv->pmklist.head, list) { if (i < PMK_LIST_MAX) { memcpy(pmkcache.list[i].bssid, pmk->bssid, ETH_ALEN); memcpy(pmkcache.list[i].pmkid, pmk->pmkid, -- cgit v1.2.3 From 0371fa4f6a9efb6ebdc3529e9210218d727c3d4d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Oct 2016 14:38:33 +0000 Subject: staging: ks7010: ks_wlan_net: Use setup_timer instead of init_timer and data fields Use setup_timer function instead of initializing timer with the function and data fields Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan_net.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 7b864c02348b..3c58f8427e03 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -3460,9 +3460,8 @@ int ks_wlan_net_start(struct net_device *dev) /* phy information update timer */ atomic_set(&update_phyinfo, 0); - init_timer(&update_phyinfo_timer); - update_phyinfo_timer.function = ks_wlan_update_phyinfo_timeout; - update_phyinfo_timer.data = (unsigned long)priv; + setup_timer(&update_phyinfo_timer, ks_wlan_update_phyinfo_timeout, + (unsigned long)priv); /* dummy address set */ memcpy(priv->eth_addr, dummy_addr, ETH_ALEN); -- cgit v1.2.3 From 0966c755040d16f923121175ac9e5f7d315e8e6e Mon Sep 17 00:00:00 2001 From: Nick Rosbrook Date: Wed, 19 Oct 2016 18:52:04 -0400 Subject: staging: ks7010: Add spaces around '*' Added spaces around a '*' in ks7010_sdio.c. Issue found by checkpatch. Signed-off-by: Nick Rosbrook Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks7010_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index b02980d9bec2..55ece81af3ab 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -719,7 +719,7 @@ static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index) return rc; } -#define ROM_BUFF_SIZE (64*1024) +#define ROM_BUFF_SIZE (64 * 1024) static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address, unsigned char *data, unsigned int size) { -- cgit v1.2.3 From f3f2d351db4e63d4a5bcdacab7d74b8e5a114d35 Mon Sep 17 00:00:00 2001 From: Nick Rosbrook Date: Thu, 20 Oct 2016 13:08:06 -0400 Subject: staging: ks7010: Corrected a spelling mistake This patch corrects the spelling of 'initialize' in ks7010_sdio.c. The issue was found by checkpatch. Signed-off-by: Nick Rosbrook Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks7010_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 55ece81af3ab..6f76d1a8c92a 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -956,7 +956,7 @@ static int ks7010_sdio_probe(struct sdio_func *func, priv = NULL; netdev = NULL; - /* initilize ks_sdio_card */ + /* initialize ks_sdio_card */ card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; -- cgit v1.2.3 From 20358d1384c39e385d8ed873049b7f4fdbcc585e Mon Sep 17 00:00:00 2001 From: Nick Rosbrook Date: Fri, 21 Oct 2016 13:15:13 -0400 Subject: staging: ks7010: ks7010_sdio.c: Fixing multiple assignments Running checkpatch on ks7010_sdio.c shows two locations where multiple assignment statements are used. This patch modifies the assignments into single assignments. Signed-off-by: Nick Rosbrook Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks7010_sdio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 6f76d1a8c92a..a604c83c957e 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -659,10 +659,12 @@ static void ks_sdio_interrupt(struct sdio_func *func) static int trx_device_init(struct ks_wlan_private *priv) { /* initialize values (tx) */ - priv->tx_dev.qtail = priv->tx_dev.qhead = 0; + priv->tx_dev.qhead = 0; + priv->tx_dev.qtail = 0; /* initialize values (rx) */ - priv->rx_dev.qtail = priv->rx_dev.qhead = 0; + priv->rx_dev.qhead = 0; + priv->rx_dev.qtail = 0; /* initialize spinLock (tx,rx) */ spin_lock_init(&priv->tx_dev.tx_dev_lock); -- cgit v1.2.3 From 7b0f8525c38cc1cad317965b21b2ae93963b4fe0 Mon Sep 17 00:00:00 2001 From: Jiong Du Date: Mon, 24 Oct 2016 21:50:41 +0800 Subject: staging: ks7010: Remove trailing whitespace Fixes checkpatch error: tailing whitespace Signed-off-by: Jiong Du Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/michael_mic.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/michael_mic.h b/drivers/staging/ks7010/michael_mic.h index efaa21788fc7..9f6d23aaa6f1 100644 --- a/drivers/staging/ks7010/michael_mic.h +++ b/drivers/staging/ks7010/michael_mic.h @@ -11,12 +11,12 @@ /* MichelMIC routine define */ struct michel_mic_t { - uint32_t K0; // Key - uint32_t K1; // Key - uint32_t L; // Current state - uint32_t R; // Current state - uint8_t M[4]; // Message accumulator (single word) - int nBytesInM; // # bytes in M + uint32_t K0; // Key + uint32_t K1; // Key + uint32_t L; // Current state + uint32_t R; // Current state + uint8_t M[4]; // Message accumulator (single word) + int nBytesInM; // # bytes in M uint8_t Result[8]; }; -- cgit v1.2.3 From 36a80337d7af6a7bd21d06f89f93a72a02b9ae4f Mon Sep 17 00:00:00 2001 From: Ryan Swan Date: Tue, 18 Oct 2016 17:26:43 -0400 Subject: staging: slicoss: replace memcpy_fromio with memcpy As per discusion with Lino Sanfilippo, memcpy is the proper way to copy across dma memory, which also removes sparse warning that triggered inquiry. Signed-off-by: Ryan Swan Reviewed-by: Lino Sanfilippo Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slicoss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 062307ad7fed..d2929b92c54f 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1057,7 +1057,7 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr) if (stats->rcv_drops > old->rcv_drops) adapter->rcv_drops += (stats->rcv_drops - old->rcv_drops); - memcpy_fromio(old, stats, sizeof(*stats)); + memcpy(old, stats, sizeof(*stats)); break; } case SLIC_UPR_RLSR: -- cgit v1.2.3 From b1e37103f251f31344c7a5cc086968d982de1b1b Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 12 Oct 2016 21:54:27 +0530 Subject: drm/i915: Decouple GuC log setup from verbosity parameter GuC Log buffer allocation was tied up with verbosity level module param i915.guc_log_level. User would be given a provision to enable firmware logging at runtime, through a host2guc action, and not necessarily during Driver load time. But the address of log buffer can be passed only in init params, at firmware load time, so GuC has to be reset and firmware needs to be reloaded to pass the log buffer address at runtime. To avoid reset of GuC & reload of firmware, allocation of log buffer will be done always but logging would be enabled initially on GuC side based on the value of module parameter guc_log_level. v2: Update commit message to describe the constraint with allocation of log buffer at runtime. (Tvrtko) v3: Rebase. Signed-off-by: Sagar Arun Kamble Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 3 --- drivers/gpu/drm/i915/intel_guc_loader.c | 6 ++++-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index a1f76c8f8cde..a1bea7ead696 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -853,9 +853,6 @@ static void guc_log_create(struct intel_guc *guc) unsigned long offset; uint32_t size, flags; - if (i915.guc_log_level < GUC_LOG_VERBOSITY_MIN) - return; - if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX) i915.guc_log_level = GUC_LOG_VERBOSITY_MAX; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 3c8eaae13732..740be0b2a360 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -211,11 +211,13 @@ static void guc_params_init(struct drm_i915_private *dev_priv) params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER | GUC_CTL_VCS2_ENABLED; + params[GUC_CTL_LOG_PARAMS] = guc->log_flags; + if (i915.guc_log_level >= 0) { - params[GUC_CTL_LOG_PARAMS] = guc->log_flags; params[GUC_CTL_DEBUG] = i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT; - } + } else + params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED; if (guc->ads_vma) { u32 ads = i915_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; -- cgit v1.2.3 From 5d34e85a9ea526611445ffedbf883c94b55ee780 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 12 Oct 2016 21:54:28 +0530 Subject: drm/i915: Add GuC ukernel logging related fields to fw interface file The first page of the GuC log buffer contains state info or meta data which is required to parse the logs contained in the subsequent pages. The structure representing the state info is added to interface file as Driver would need to handle log buffer flush interrupts from GuC. Added an enum for the different message/event types that can be send by the GuC ukernel to Host. Also added 2 new Host to GuC action types to inform GuC when Host has flushed the log buffer and forcefuly cause the GuC to send a new log buffer flush interrupt. v2: - Make documentation of log buffer state structure more elaborate & rename LOGBUFFERFLUSH action to LOG_BUFFER_FLUSH for consistency.(Tvrtko) v3: Add GuC log buffer layout diagram for more clarity. Signed-off-by: Sagar Arun Kamble Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_guc_fwif.h | 78 +++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index e40db2d2ae99..adb1ffdc37c2 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -419,15 +419,87 @@ struct guc_ads { u32 reserved2[4]; } __packed; +/* GuC logging structures */ + +enum guc_log_buffer_type { + GUC_ISR_LOG_BUFFER, + GUC_DPC_LOG_BUFFER, + GUC_CRASH_DUMP_LOG_BUFFER, + GUC_MAX_LOG_BUFFER +}; + +/** + * DOC: GuC Log buffer Layout + * + * Page0 +-------------------------------+ + * | ISR state header (32 bytes) | + * | DPC state header | + * | Crash dump state header | + * Page1 +-------------------------------+ + * | ISR logs | + * Page5 +-------------------------------+ + * | DPC logs | + * Page9 +-------------------------------+ + * | Crash Dump logs | + * +-------------------------------+ + * + * Below state structure is used for coordination of retrieval of GuC firmware + * logs. Separate state is maintained for each log buffer type. + * read_ptr points to the location where i915 read last in log buffer and + * is read only for GuC firmware. write_ptr is incremented by GuC with number + * of bytes written for each log entry and is read only for i915. + * When any type of log buffer becomes half full, GuC sends a flush interrupt. + * GuC firmware expects that while it is writing to 2nd half of the buffer, + * first half would get consumed by Host and then get a flush completed + * acknowledgment from Host, so that it does not end up doing any overwrite + * causing loss of logs. So when buffer gets half filled & i915 has requested + * for interrupt, GuC will set flush_to_file field, set the sampled_write_ptr + * to the value of write_ptr and raise the interrupt. + * On receiving the interrupt i915 should read the buffer, clear flush_to_file + * field and also update read_ptr with the value of sample_write_ptr, before + * sending an acknowledgment to GuC. marker & version fields are for internal + * usage of GuC and opaque to i915. buffer_full_cnt field is incremented every + * time GuC detects the log buffer overflow. + */ +struct guc_log_buffer_state { + u32 marker[2]; + u32 read_ptr; + u32 write_ptr; + u32 size; + u32 sampled_write_ptr; + union { + struct { + u32 flush_to_file:1; + u32 buffer_full_cnt:4; + u32 reserved:27; + }; + u32 flags; + }; + u32 version; +} __packed; + +union guc_log_control { + struct { + u32 logging_enabled:1; + u32 reserved1:3; + u32 verbosity:4; + u32 reserved2:24; + }; + u32 value; +} __packed; + /* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */ enum host2guc_action { HOST2GUC_ACTION_DEFAULT = 0x0, HOST2GUC_ACTION_SAMPLE_FORCEWAKE = 0x6, HOST2GUC_ACTION_ALLOCATE_DOORBELL = 0x10, HOST2GUC_ACTION_DEALLOCATE_DOORBELL = 0x20, + HOST2GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE = 0x30, + HOST2GUC_ACTION_FORCE_LOG_BUFFER_FLUSH = 0x302, HOST2GUC_ACTION_ENTER_S_STATE = 0x501, HOST2GUC_ACTION_EXIT_S_STATE = 0x502, HOST2GUC_ACTION_SLPC_REQUEST = 0x3003, + HOST2GUC_ACTION_UK_LOG_ENABLE_LOGGING = 0x0E000, HOST2GUC_ACTION_LIMIT }; @@ -449,4 +521,10 @@ enum guc2host_status { GUC2HOST_STATUS_GENERIC_FAIL = GUC2HOST_STATUS(0x0000F000) }; +/* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */ +enum guc2host_message { + GUC2HOST_MSG_CRASH_DUMP_POSTED = (1 << 1), + GUC2HOST_MSG_FLUSH_LOG_BUFFER = (1 << 3) +}; + #endif -- cgit v1.2.3 From d6b40b4b179d5c3f57d1191052d4527af7321ad6 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:29 +0530 Subject: drm/i915: New structure to contain GuC logging related fields So far there were 2 fields related to GuC logs in 'intel_guc' structure. For the support of capturing GuC logs & storing them in a local buffer, multiple new fields would have to be added. This warrants a separate structure to contain the fields related to GuC logging state. Added a new structure 'intel_guc_log' and instance of it inside 'intel_guc' structure. v2: Rebase. Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/i915_guc_submission.c | 8 ++++---- drivers/gpu/drm/i915/intel_guc.h | 8 ++++++-- drivers/gpu/drm/i915/intel_guc_loader.c | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4751b618ae12..c5716397da20 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2500,10 +2500,10 @@ static int i915_guc_log_dump(struct seq_file *m, void *data) struct drm_i915_gem_object *obj; int i = 0, pg; - if (!dev_priv->guc.log_vma) + if (!dev_priv->guc.log.vma) return 0; - obj = dev_priv->guc.log_vma->obj; + obj = dev_priv->guc.log.vma->obj; for (pg = 0; pg < obj->base.size / PAGE_SIZE; pg++) { u32 *log = kmap_atomic(i915_gem_object_get_page(obj, pg)); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index a1bea7ead696..5e76b923ab4b 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -862,7 +862,7 @@ static void guc_log_create(struct intel_guc *guc) GUC_LOG_ISR_PAGES + 1 + GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT; - vma = guc->log_vma; + vma = guc->log.vma; if (!vma) { vma = guc_allocate_vma(guc, size); if (IS_ERR(vma)) { @@ -871,7 +871,7 @@ static void guc_log_create(struct intel_guc *guc) return; } - guc->log_vma = vma; + guc->log.vma = vma; } /* each allocated unit is a page */ @@ -881,7 +881,7 @@ static void guc_log_create(struct intel_guc *guc) (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT); offset = i915_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */ - guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; + guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; } static void guc_policies_init(struct guc_policies *policies) @@ -1065,7 +1065,7 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv) struct intel_guc *guc = &dev_priv->guc; i915_vma_unpin_and_release(&guc->ads_vma); - i915_vma_unpin_and_release(&guc->log_vma); + i915_vma_unpin_and_release(&guc->log.vma); if (guc->ctx_pool_vma) ida_destroy(&guc->ctx_ids); diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 5cdf7aa75be5..c73294164fed 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -123,10 +123,14 @@ struct intel_guc_fw { uint32_t ucode_offset; }; +struct intel_guc_log { + uint32_t flags; + struct i915_vma *vma; +}; + struct intel_guc { struct intel_guc_fw guc_fw; - uint32_t log_flags; - struct i915_vma *log_vma; + struct intel_guc_log log; struct i915_vma *ads_vma; struct i915_vma *ctx_pool_vma; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 740be0b2a360..a75abb8cc0cc 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -211,7 +211,7 @@ static void guc_params_init(struct drm_i915_private *dev_priv) params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER | GUC_CTL_VCS2_ENABLED; - params[GUC_CTL_LOG_PARAMS] = guc->log_flags; + params[GUC_CTL_LOG_PARAMS] = guc->log.flags; if (i915.guc_log_level >= 0) { params[GUC_CTL_DEBUG] = -- cgit v1.2.3 From f4e9af4f5af5dab9aee632f3aff0bd8040f1b2c5 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:30 +0530 Subject: drm/i915: Add low level set of routines for programming PM IER/IIR/IMR register set So far PM IER/IIR/IMR registers were being used only for Turbo related interrupts. But interrupts coming from GuC also use the same set. As a precursor to supporting GuC interrupts, added new low level routines so as to allow sharing the programming of PM IER/IIR/IMR registers between Turbo & GuC. Also similar to PM IMR, maintaining a bitmask for PM IER register, to allow easy sharing of it between Turbo & GuC without involving a rmw operation. v2: - For appropriateness & avoid any ambiguity, rename old functions enable/disable pm_irq to mask/unmask pm_irq and rename new functions enable/disable pm_interrupts to enable/disable pm_irq. (Tvrtko) - Use u32 in place of uint32_t. (Tvrtko) v3: - Rename the fields pm_irq_mask & pm_ier_mask and do some cleanup. (Chris) - Rebase. v4: Fix the inadvertent disabling of User interrupt for VECS ring causing failure for certain IGTs. v5: Use dev_priv with HAS_VEBOX macro. (Tvrtko) Suggested-by: Chris Wilson Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_irq.c | 75 ++++++++++++++++++++++----------- drivers/gpu/drm/i915/intel_drv.h | 3 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 4 +- 4 files changed, 57 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dd3acabb7edb..58d332bda227 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1836,7 +1836,8 @@ struct drm_i915_private { u32 de_irq_mask[I915_MAX_PIPES]; }; u32 gt_irq_mask; - u32 pm_irq_mask; + u32 pm_imr; + u32 pm_ier; u32 pm_rps_events; u32 pipestat_irq_mask[I915_MAX_PIPES]; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 23315e5461bf..6412aac74346 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -303,18 +303,18 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv, assert_spin_locked(&dev_priv->irq_lock); - new_val = dev_priv->pm_irq_mask; + new_val = dev_priv->pm_imr; new_val &= ~interrupt_mask; new_val |= (~enabled_irq_mask & interrupt_mask); - if (new_val != dev_priv->pm_irq_mask) { - dev_priv->pm_irq_mask = new_val; - I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_irq_mask); + if (new_val != dev_priv->pm_imr) { + dev_priv->pm_imr = new_val; + I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_imr); POSTING_READ(gen6_pm_imr(dev_priv)); } } -void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) +void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) { if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; @@ -322,28 +322,54 @@ void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) snb_update_pm_irq(dev_priv, mask, mask); } -static void __gen6_disable_pm_irq(struct drm_i915_private *dev_priv, - uint32_t mask) +static void __gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) { snb_update_pm_irq(dev_priv, mask, 0); } -void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) +void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) { if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; - __gen6_disable_pm_irq(dev_priv, mask); + __gen6_mask_pm_irq(dev_priv, mask); } -void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) +void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask) { i915_reg_t reg = gen6_pm_iir(dev_priv); - spin_lock_irq(&dev_priv->irq_lock); - I915_WRITE(reg, dev_priv->pm_rps_events); - I915_WRITE(reg, dev_priv->pm_rps_events); + assert_spin_locked(&dev_priv->irq_lock); + + I915_WRITE(reg, reset_mask); + I915_WRITE(reg, reset_mask); POSTING_READ(reg); +} + +void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask) +{ + assert_spin_locked(&dev_priv->irq_lock); + + dev_priv->pm_ier |= enable_mask; + I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); + gen6_unmask_pm_irq(dev_priv, enable_mask); + /* unmask_pm_irq provides an implicit barrier (POSTING_READ) */ +} + +void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_mask) +{ + assert_spin_locked(&dev_priv->irq_lock); + + dev_priv->pm_ier &= ~disable_mask; + __gen6_mask_pm_irq(dev_priv, disable_mask); + I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); + /* though a barrier is missing here, but don't really need a one */ +} + +void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) +{ + spin_lock_irq(&dev_priv->irq_lock); + gen6_reset_pm_iir(dev_priv, dev_priv->pm_rps_events); dev_priv->rps.pm_iir = 0; spin_unlock_irq(&dev_priv->irq_lock); } @@ -357,8 +383,6 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) WARN_ON_ONCE(dev_priv->rps.pm_iir); WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); dev_priv->rps.interrupts_enabled = true; - I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) | - dev_priv->pm_rps_events); gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); spin_unlock_irq(&dev_priv->irq_lock); @@ -379,9 +403,7 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0u)); - __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); - I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) & - ~dev_priv->pm_rps_events); + gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); spin_unlock_irq(&dev_priv->irq_lock); synchronize_irq(dev_priv->drm.irq); @@ -1085,7 +1107,7 @@ static void gen6_pm_rps_work(struct work_struct *work) pm_iir = dev_priv->rps.pm_iir; dev_priv->rps.pm_iir = 0; /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */ - gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); + gen6_unmask_pm_irq(dev_priv, dev_priv->pm_rps_events); client_boost = dev_priv->rps.client_boost; dev_priv->rps.client_boost = false; spin_unlock_irq(&dev_priv->irq_lock); @@ -1586,7 +1608,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) { if (pm_iir & dev_priv->pm_rps_events) { spin_lock(&dev_priv->irq_lock); - gen6_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); + gen6_mask_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); if (dev_priv->rps.interrupts_enabled) { dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events; schedule_work(&dev_priv->rps.work); @@ -3545,11 +3567,13 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) * RPS interrupts will get enabled/disabled on demand when RPS * itself is enabled/disabled. */ - if (HAS_VEBOX(dev)) + if (HAS_VEBOX(dev_priv)) { pm_irqs |= PM_VEBOX_USER_INTERRUPT; + dev_priv->pm_ier |= PM_VEBOX_USER_INTERRUPT; + } - dev_priv->pm_irq_mask = 0xffffffff; - GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_irq_mask, pm_irqs); + dev_priv->pm_imr = 0xffffffff; + GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs); } } @@ -3669,14 +3693,15 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) if (HAS_L3_DPF(dev_priv)) gt_interrupts[0] |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; - dev_priv->pm_irq_mask = 0xffffffff; + dev_priv->pm_ier = 0x0; + dev_priv->pm_imr = ~dev_priv->pm_ier; GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); /* * RPS interrupts will get enabled/disabled on demand when RPS itself * is enabled/disabled. */ - GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, 0); + GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_imr, dev_priv->pm_ier); GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 16b33f59dd6f..07308eb2e240 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1123,6 +1123,9 @@ void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv); /* i915_irq.c */ void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); +void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 mask); +void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); +void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 32786ba199b9..67a70c5e6453 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1608,7 +1608,7 @@ hsw_vebox_irq_enable(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->i915; I915_WRITE_IMR(engine, ~engine->irq_enable_mask); - gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask); + gen6_unmask_pm_irq(dev_priv, engine->irq_enable_mask); } static void @@ -1617,7 +1617,7 @@ hsw_vebox_irq_disable(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->i915; I915_WRITE_IMR(engine, ~0); - gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask); + gen6_mask_pm_irq(dev_priv, engine->irq_enable_mask); } static void -- cgit v1.2.3 From 26705e20752a4ad12dbbe334ed6402c7f0317326 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 12 Oct 2016 21:54:31 +0530 Subject: drm/i915: Support for GuC interrupts There are certain types of interrupts which Host can receive from GuC. GuC ukernel sends an interrupt to Host for certain events, like for example retrieve/consume the logs generated by ukernel. This patch adds support to receive interrupts from GuC but currently enables & partially handles only the interrupt sent by GuC ukernel. Future patches will add support for handling other interrupt types. v2: - Use common low level routines for PM IER/IIR programming (Chris) - Rename interrupt functions to gen9_xxx from gen8_xxx (Chris) - Replace disabling of wake ref asserts with rpm get/put (Chris) v3: - Update comments for more clarity. (Tvrtko) - Remove the masking of GuC interrupt, which was kept masked till the start of bottom half, its not really needed as there is only a single instance of work item & wq is ordered. (Tvrtko) v4: - Rebase. - Rename guc_events to pm_guc_events so as to be indicative of the register/control block it is associated with. (Chris) - Add handling for back to back log buffer flush interrupts. v5: - Move the read & clearing of register, containing Guc2Host message bits, outside the irq spinlock. (Tvrtko) v6: - Move the log buffer flush interrupt related stuff to the following patch so as to do only generic bits in this patch. (Tvrtko) - Rebase. v7: - Remove the interrupts_enabled check from gen9_guc_irq_handler, want to process that last interrupt also before disabling the interrupt, sync against the work queued by irq handler will be done by caller disabling the interrupt. Signed-off-by: Sagar Arun Kamble Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_guc_submission.c | 5 +++ drivers/gpu/drm/i915/i915_irq.c | 56 +++++++++++++++++++++++++++--- drivers/gpu/drm/i915/i915_reg.h | 11 ++++++ drivers/gpu/drm/i915/intel_drv.h | 3 ++ drivers/gpu/drm/i915/intel_guc.h | 3 ++ drivers/gpu/drm/i915/intel_guc_loader.c | 4 +++ 7 files changed, 79 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 58d332bda227..72215b7b5b89 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1839,6 +1839,7 @@ struct drm_i915_private { u32 pm_imr; u32 pm_ier; u32 pm_rps_events; + u32 pm_guc_events; u32 pipestat_irq_mask[I915_MAX_PIPES]; struct i915_hotplug hotplug; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 5e76b923ab4b..6b77af253327 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1086,6 +1086,8 @@ int intel_guc_suspend(struct drm_device *dev) if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS) return 0; + gen9_disable_guc_interrupts(dev_priv); + ctx = dev_priv->kernel_context; data[0] = HOST2GUC_ACTION_ENTER_S_STATE; @@ -1112,6 +1114,9 @@ int intel_guc_resume(struct drm_device *dev) if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS) return 0; + if (i915.guc_log_level >= 0) + gen9_enable_guc_interrupts(dev_priv); + ctx = dev_priv->kernel_context; data[0] = HOST2GUC_ACTION_EXIT_S_STATE; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6412aac74346..b37959fdfb0e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -170,6 +170,7 @@ static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, } while (0) static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); +static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); /* For display hotplug interrupt */ static inline void @@ -417,6 +418,38 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) gen6_reset_rps_interrupts(dev_priv); } +void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv) +{ + spin_lock_irq(&dev_priv->irq_lock); + gen6_reset_pm_iir(dev_priv, dev_priv->pm_guc_events); + spin_unlock_irq(&dev_priv->irq_lock); +} + +void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv) +{ + spin_lock_irq(&dev_priv->irq_lock); + if (!dev_priv->guc.interrupts_enabled) { + WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & + dev_priv->pm_guc_events); + dev_priv->guc.interrupts_enabled = true; + gen6_enable_pm_irq(dev_priv, dev_priv->pm_guc_events); + } + spin_unlock_irq(&dev_priv->irq_lock); +} + +void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv) +{ + spin_lock_irq(&dev_priv->irq_lock); + dev_priv->guc.interrupts_enabled = false; + + gen6_disable_pm_irq(dev_priv, dev_priv->pm_guc_events); + + spin_unlock_irq(&dev_priv->irq_lock); + synchronize_irq(dev_priv->drm.irq); + + gen9_reset_guc_interrupts(dev_priv); +} + /** * bdw_update_port_irq - update DE port interrupt * @dev_priv: driver private @@ -1346,11 +1379,13 @@ static irqreturn_t gen8_gt_irq_ack(struct drm_i915_private *dev_priv, DRM_ERROR("The master control interrupt lied (GT3)!\n"); } - if (master_ctl & GEN8_GT_PM_IRQ) { + if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { gt_iir[2] = I915_READ_FW(GEN8_GT_IIR(2)); - if (gt_iir[2] & dev_priv->pm_rps_events) { + if (gt_iir[2] & (dev_priv->pm_rps_events | + dev_priv->pm_guc_events)) { I915_WRITE_FW(GEN8_GT_IIR(2), - gt_iir[2] & dev_priv->pm_rps_events); + gt_iir[2] & (dev_priv->pm_rps_events | + dev_priv->pm_guc_events)); ret = IRQ_HANDLED; } else DRM_ERROR("The master control interrupt lied (PM)!\n"); @@ -1382,6 +1417,9 @@ static void gen8_gt_irq_handler(struct drm_i915_private *dev_priv, if (gt_iir[2] & dev_priv->pm_rps_events) gen6_rps_irq_handler(dev_priv, gt_iir[2]); + + if (gt_iir[2] & dev_priv->pm_guc_events) + gen9_guc_irq_handler(dev_priv, gt_iir[2]); } static bool bxt_port_hotplug_long_detect(enum port port, u32 val) @@ -1628,6 +1666,13 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) } } +static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) +{ + if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) { + /* TODO: Handle events for which GuC interrupted host */ + } +} + static bool intel_pipe_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) { @@ -3699,7 +3744,7 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); /* * RPS interrupts will get enabled/disabled on demand when RPS itself - * is enabled/disabled. + * is enabled/disabled. Same wil be the case for GuC interrupts. */ GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_imr, dev_priv->pm_ier); GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); @@ -4485,6 +4530,9 @@ void intel_irq_init(struct drm_i915_private *dev_priv) INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work); INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); + if (HAS_GUC_SCHED(dev)) + dev_priv->pm_guc_events = GEN9_GUC_TO_HOST_INT_EVENT; + /* Let's track the enabled rps events */ if (IS_VALLEYVIEW(dev_priv)) /* WaGsvRC0ResidencyMethod:vlv */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a9be3f037f43..bdc7b3591e1c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6016,6 +6016,7 @@ enum { #define GEN8_DE_PIPE_A_IRQ (1<<16) #define GEN8_DE_PIPE_IRQ(pipe) (1<<(16+(pipe))) #define GEN8_GT_VECS_IRQ (1<<6) +#define GEN8_GT_GUC_IRQ (1<<5) #define GEN8_GT_PM_IRQ (1<<4) #define GEN8_GT_VCS2_IRQ (1<<3) #define GEN8_GT_VCS1_IRQ (1<<2) @@ -6027,6 +6028,16 @@ enum { #define GEN8_GT_IIR(which) _MMIO(0x44308 + (0x10 * (which))) #define GEN8_GT_IER(which) _MMIO(0x4430c + (0x10 * (which))) +#define GEN9_GUC_TO_HOST_INT_EVENT (1<<31) +#define GEN9_GUC_EXEC_ERROR_EVENT (1<<30) +#define GEN9_GUC_DISPLAY_EVENT (1<<29) +#define GEN9_GUC_SEMA_SIGNAL_EVENT (1<<28) +#define GEN9_GUC_IOMMU_MSG_EVENT (1<<27) +#define GEN9_GUC_DB_RING_EVENT (1<<26) +#define GEN9_GUC_DMA_DONE_EVENT (1<<25) +#define GEN9_GUC_FATAL_ERROR_EVENT (1<<24) +#define GEN9_GUC_NOTIFICATION_EVENT (1<<23) + #define GEN8_RCS_IRQ_SHIFT 0 #define GEN8_BCS_IRQ_SHIFT 16 #define GEN8_VCS1_IRQ_SHIFT 0 diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 07308eb2e240..7dda79df55d0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1148,6 +1148,9 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, unsigned int pipe_mask); void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, unsigned int pipe_mask); +void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv); +void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv); +void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv); /* intel_crt.c */ void intel_crt_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index c73294164fed..81bd345c7598 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -132,6 +132,9 @@ struct intel_guc { struct intel_guc_fw guc_fw; struct intel_guc_log log; + /* GuC2Host interrupt related state */ + bool interrupts_enabled; + struct i915_vma *ads_vma; struct i915_vma *ctx_pool_vma; struct ida ctx_ids; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index a75abb8cc0cc..1aa85236b788 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -485,6 +485,7 @@ int intel_guc_setup(struct drm_device *dev) } guc_interrupts_release(dev_priv); + gen9_reset_guc_interrupts(dev_priv); guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING; @@ -529,6 +530,9 @@ int intel_guc_setup(struct drm_device *dev) intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); if (i915.enable_guc_submission) { + if (i915.guc_log_level >= 0) + gen9_enable_guc_interrupts(dev_priv); + err = i915_guc_submission_enable(dev_priv); if (err) goto fail; -- cgit v1.2.3 From 4100b2ab3e8b2932554295ba79371d10687f1bb4 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 12 Oct 2016 21:54:32 +0530 Subject: drm/i915: Handle log buffer flush interrupt event from GuC GuC ukernel sends an interrupt to Host to flush the log buffer and expects Host to correspondingly update the read pointer information in the state structure, once it has consumed the log buffer contents by copying them to a file or buffer. Even if Host couldn't copy the contents, it can still update the read pointer so that logging state is not disturbed on GuC side. v2: - Use a dedicated workqueue for handling flush interrupt. (Tvrtko) - Reduce the overall log buffer copying time by skipping the copy of crash buffer area for regular cases and copying only the state structure data in first page. v3: - Create a vmalloc mapping of log buffer. (Chris) - Cover the flush acknowledgment under rpm get & put.(Chris) - Revert the change of skipping the copy of crash dump area, as not really needed, will be covered by subsequent patch. v4: - Destroy the wq under the same condition in which it was created, pass dev_piv pointer instead of dev to newly added GuC function, add more comments & rename variable for clarity. (Tvrtko) v5: - Allocate & destroy the dedicated wq, for handling flush interrupt, from the setup/teardown routines of GuC logging. (Chris) - Validate the log buffer size value retrieved from state structure and do some minor cleanup. (Tvrtko) - Fix error/warnings reported by checkpatch. (Tvrtko) - Rebase. v6: - Remove the interrupts_enabled check from guc_capture_logs_work, need to process that last work item also, queued just before disabling the interrupt as log buffer flush interrupt handling is a bit different case where GuC is actually expecting an ACK from host, which should be provided to keep the logging going. Sync against the work will be done by caller disabling the interrupt. - Don't sample the log buffer size value from state structure, directly use the expected value to move the pointer & do the copy and that cannot go wrong (out of bounds) as Driver only allocated the log buffer and the relay buffers. Driver should refrain from interpreting the log packet, as much possible and let Userspace parser detect the anomaly. (Chris) v7: - Use switch statement instead of 'if else' for retrieving the GuC log buffer size. (Tvrtko) - Refactored the log buffer copying function and shortended the name of couple of variables for better readability. (Tvrtko) v8: - Make the dedicated wq as a high priority one to further reduce the turnaround time of handing log buffer flush event from GuC. Signed-off-by: Sagar Arun Kamble Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 186 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_irq.c | 28 ++++- drivers/gpu/drm/i915/intel_guc.h | 4 + 3 files changed, 217 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 6b77af253327..1f27de2c0e1b 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -170,6 +170,15 @@ static int host2guc_sample_forcewake(struct intel_guc *guc, return host2guc_action(guc, data, ARRAY_SIZE(data)); } +static int host2guc_logbuffer_flush_complete(struct intel_guc *guc) +{ + u32 data[1]; + + data[0] = HOST2GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE; + + return host2guc_action(guc, data, 1); +} + /* * Initialise, update, or clear doorbell data shared with the GuC * @@ -847,6 +856,163 @@ err: return NULL; } +static void guc_move_to_next_buf(struct intel_guc *guc) +{ +} + +static void *guc_get_write_buffer(struct intel_guc *guc) +{ + return NULL; +} + +static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) +{ + switch (type) { + case GUC_ISR_LOG_BUFFER: + return (GUC_LOG_ISR_PAGES + 1) * PAGE_SIZE; + case GUC_DPC_LOG_BUFFER: + return (GUC_LOG_DPC_PAGES + 1) * PAGE_SIZE; + case GUC_CRASH_DUMP_LOG_BUFFER: + return (GUC_LOG_CRASH_PAGES + 1) * PAGE_SIZE; + default: + MISSING_CASE(type); + } + + return 0; +} + +static void guc_read_update_log_buffer(struct intel_guc *guc) +{ + struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; + struct guc_log_buffer_state log_buf_state_local; + unsigned int buffer_size, write_offset; + enum guc_log_buffer_type type; + void *src_data, *dst_data; + + if (WARN_ON(!guc->log.buf_addr)) + return; + + /* Get the pointer to shared GuC log buffer */ + log_buf_state = src_data = guc->log.buf_addr; + + /* Get the pointer to local buffer to store the logs */ + log_buf_snapshot_state = dst_data = guc_get_write_buffer(guc); + + /* Actual logs are present from the 2nd page */ + src_data += PAGE_SIZE; + dst_data += PAGE_SIZE; + + for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) { + /* Make a copy of the state structure, inside GuC log buffer + * (which is uncached mapped), on the stack to avoid reading + * from it multiple times. + */ + memcpy(&log_buf_state_local, log_buf_state, + sizeof(struct guc_log_buffer_state)); + buffer_size = guc_get_log_buffer_size(type); + write_offset = log_buf_state_local.sampled_write_ptr; + + /* Update the state of shared log buffer */ + log_buf_state->read_ptr = write_offset; + log_buf_state->flush_to_file = 0; + log_buf_state++; + + if (unlikely(!log_buf_snapshot_state)) + continue; + + /* First copy the state structure in snapshot buffer */ + memcpy(log_buf_snapshot_state, &log_buf_state_local, + sizeof(struct guc_log_buffer_state)); + + /* The write pointer could have been updated by GuC firmware, + * after sending the flush interrupt to Host, for consistency + * set write pointer value to same value of sampled_write_ptr + * in the snapshot buffer. + */ + log_buf_snapshot_state->write_ptr = write_offset; + log_buf_snapshot_state++; + + /* Now copy the actual logs. */ + memcpy(dst_data, src_data, buffer_size); + + src_data += buffer_size; + dst_data += buffer_size; + + /* FIXME: invalidate/flush for log buffer needed */ + } + + if (log_buf_snapshot_state) + guc_move_to_next_buf(guc); +} + +static void guc_capture_logs_work(struct work_struct *work) +{ + struct drm_i915_private *dev_priv = + container_of(work, struct drm_i915_private, guc.log.flush_work); + + i915_guc_capture_logs(dev_priv); +} + +static void guc_log_cleanup(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + + lockdep_assert_held(&dev_priv->drm.struct_mutex); + + /* First disable the flush interrupt */ + gen9_disable_guc_interrupts(dev_priv); + + if (guc->log.flush_wq) + destroy_workqueue(guc->log.flush_wq); + + guc->log.flush_wq = NULL; + + if (guc->log.buf_addr) + i915_gem_object_unpin_map(guc->log.vma->obj); + + guc->log.buf_addr = NULL; +} + +static int guc_log_create_extras(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + void *vaddr; + int ret; + + lockdep_assert_held(&dev_priv->drm.struct_mutex); + + /* Nothing to do */ + if (i915.guc_log_level < 0) + return 0; + + if (!guc->log.buf_addr) { + /* Create a vmalloc mapping of log buffer pages */ + vaddr = i915_gem_object_pin_map(guc->log.vma->obj, I915_MAP_WB); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + DRM_ERROR("Couldn't map log buffer pages %d\n", ret); + return ret; + } + + guc->log.buf_addr = vaddr; + } + + if (!guc->log.flush_wq) { + INIT_WORK(&guc->log.flush_work, guc_capture_logs_work); + + /* Need a dedicated wq to process log buffer flush interrupts + * from GuC without much delay so as to avoid any loss of logs. + */ + guc->log.flush_wq = alloc_ordered_workqueue("i915-guc_log", WQ_HIGHPRI); + if (guc->log.flush_wq == NULL) { + DRM_ERROR("Couldn't allocate the wq for GuC logging\n"); + return -ENOMEM; + } + } + + return 0; +} + static void guc_log_create(struct intel_guc *guc) { struct i915_vma *vma; @@ -872,6 +1038,13 @@ static void guc_log_create(struct intel_guc *guc) } guc->log.vma = vma; + + if (guc_log_create_extras(guc)) { + guc_log_cleanup(guc); + i915_vma_unpin_and_release(&guc->log.vma); + i915.guc_log_level = -1; + return; + } } /* each allocated unit is a page */ @@ -1065,6 +1238,7 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv) struct intel_guc *guc = &dev_priv->guc; i915_vma_unpin_and_release(&guc->ads_vma); + guc_log_cleanup(guc); i915_vma_unpin_and_release(&guc->log.vma); if (guc->ctx_pool_vma) @@ -1126,3 +1300,15 @@ int intel_guc_resume(struct drm_device *dev) return host2guc_action(guc, data, ARRAY_SIZE(data)); } + +void i915_guc_capture_logs(struct drm_i915_private *dev_priv) +{ + guc_read_update_log_buffer(&dev_priv->guc); + + /* Generally device is expected to be active only at this + * time, so get/put should be really quick. + */ + intel_runtime_pm_get(dev_priv); + host2guc_logbuffer_flush_complete(&dev_priv->guc); + intel_runtime_pm_put(dev_priv); +} diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b37959fdfb0e..253c22109c3f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1669,7 +1669,33 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) { if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) { - /* TODO: Handle events for which GuC interrupted host */ + /* Sample the log buffer flush related bits & clear them out now + * itself from the message identity register to minimize the + * probability of losing a flush interrupt, when there are back + * to back flush interrupts. + * There can be a new flush interrupt, for different log buffer + * type (like for ISR), whilst Host is handling one (for DPC). + * Since same bit is used in message register for ISR & DPC, it + * could happen that GuC sets the bit for 2nd interrupt but Host + * clears out the bit on handling the 1st interrupt. + */ + u32 msg, flush; + + msg = I915_READ(SOFT_SCRATCH(15)); + flush = msg & (GUC2HOST_MSG_CRASH_DUMP_POSTED | + GUC2HOST_MSG_FLUSH_LOG_BUFFER); + if (flush) { + /* Clear the message bits that are handled */ + I915_WRITE(SOFT_SCRATCH(15), msg & ~flush); + + /* Handle flush interrupt in bottom half */ + queue_work(dev_priv->guc.log.flush_wq, + &dev_priv->guc.log.flush_work); + } else { + /* Not clearing of unhandled event bits won't result in + * re-triggering of the interrupt. + */ + } } } diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 81bd345c7598..fb72313c8649 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -126,6 +126,9 @@ struct intel_guc_fw { struct intel_guc_log { uint32_t flags; struct i915_vma *vma; + void *buf_addr; + struct workqueue_struct *flush_wq; + struct work_struct flush_work; }; struct intel_guc { @@ -170,5 +173,6 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *rq); void i915_guc_wq_unreserve(struct drm_i915_gem_request *request); void i915_guc_submission_disable(struct drm_i915_private *dev_priv); void i915_guc_submission_fini(struct drm_i915_private *dev_priv); +void i915_guc_capture_logs(struct drm_i915_private *dev_priv); #endif -- cgit v1.2.3 From f824083559af27d92db938733dba54617824d702 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:34 +0530 Subject: drm/i915: Add a relay backed debugfs interface for capturing GuC logs Added a new debugfs interface '/sys/kernel/debug/dri/guc_log' for the User to capture GuC firmware logs. Availed relay framework to implement the interface, where Driver will have to just use a relay API to store snapshots of the GuC log buffer in the buffer managed by relay. The snapshot will be taken when GuC firmware sends a log buffer flush interrupt and up to four snapshots could be stored in the relay buffer. The relay buffer will be operated in a mode where it will overwrite the data not yet collected by User. Besides mmap method, through which User can directly access the relay buffer contents, relay also supports the 'poll' method. Through the 'poll' call on log file, User can come to know whenever a new snapshot of the log buffer is taken by Driver, so can run in tandem with the Driver and capture the logs in a sustained/streaming manner, without any loss of data. v2: Defer the creation of relay channel & associated debugfs file, as debugfs setup is now done at the end of i915 Driver load. (Chris) v3: - Switch to no-overwrite mode for relay. - Fix the relay sub buffer switching sequence. v4: - Update i915 Kconfig to select RELAY config. (TvrtKo) - Log a message when there is no sub buffer available to capture the GuC log buffer. (Tvrtko) - Increase the number of relay sub buffers to 8 from 4, to have sufficient buffering for boot time logs v5: - Fix the alignment, indentation issues and some minor cleanup. (Tvrtko) - Update the comment to elaborate on why a relay channel has to be associated with the debugfs file. (Tvrtko) v6: - Move the write to 'is_global' after the NULL check on parent directory dentry pointer. (Tvrtko) v7: Add a BUG_ON to validate relay buffer allocation size. (Chris) Testcase: igt/tools/intel_guc_logger Suggested-by: Chris Wilson Signed-off-by: Sourab Gupta Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/Kconfig | 1 + drivers/gpu/drm/i915/i915_drv.c | 2 + drivers/gpu/drm/i915/i915_guc_submission.c | 213 ++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_guc.h | 3 + 4 files changed, 217 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 45a5eb71e8e6..af13c624de9d 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -11,6 +11,7 @@ config DRM_I915 select DRM_KMS_HELPER select DRM_PANEL select DRM_MIPI_DSI + select RELAY # i915 depends on ACPI_VIDEO when ACPI is enabled # but for select to work, need to select ACPI_VIDEO's dependencies, ick select BACKLIGHT_LCD_SUPPORT if ACPI diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 99e4e044e958..af3559d34328 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1111,6 +1111,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) /* Reveal our presence to userspace */ if (drm_dev_register(dev, 0) == 0) { i915_debugfs_register(dev_priv); + i915_guc_register(dev_priv); i915_setup_sysfs(dev_priv); } else DRM_ERROR("Failed to register driver for userspace access!\n"); @@ -1149,6 +1150,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) intel_opregion_unregister(dev_priv); i915_teardown_sysfs(dev_priv); + i915_guc_unregister(dev_priv); i915_debugfs_unregister(dev_priv); drm_dev_unregister(&dev_priv->drm); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 1f27de2c0e1b..c1d2a9042a1c 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -23,6 +23,8 @@ */ #include #include +#include +#include #include "i915_drv.h" #include "intel_guc.h" @@ -856,13 +858,160 @@ err: return NULL; } +/* + * Sub buffer switch callback. Called whenever relay has to switch to a new + * sub buffer, relay stays on the same sub buffer if 0 is returned. + */ +static int subbuf_start_callback(struct rchan_buf *buf, + void *subbuf, + void *prev_subbuf, + size_t prev_padding) +{ + /* Use no-overwrite mode by default, where relay will stop accepting + * new data if there are no empty sub buffers left. + * There is no strict synchronization enforced by relay between Consumer + * and Producer. In overwrite mode, there is a possibility of getting + * inconsistent/garbled data, the producer could be writing on to the + * same sub buffer from which Consumer is reading. This can't be avoided + * unless Consumer is fast enough and can always run in tandem with + * Producer. + */ + if (relay_buf_full(buf)) + return 0; + + return 1; +} + +/* + * file_create() callback. Creates relay file in debugfs. + */ +static struct dentry *create_buf_file_callback(const char *filename, + struct dentry *parent, + umode_t mode, + struct rchan_buf *buf, + int *is_global) +{ + struct dentry *buf_file; + + if (!parent) + return NULL; + + /* This to enable the use of a single buffer for the relay channel and + * correspondingly have a single file exposed to User, through which + * it can collect the logs in order without any post-processing. + */ + *is_global = 1; + + /* Not using the channel filename passed as an argument, since for each + * channel relay appends the corresponding CPU number to the filename + * passed in relay_open(). This should be fine as relay just needs a + * dentry of the file associated with the channel buffer and that file's + * name need not be same as the filename passed as an argument. + */ + buf_file = debugfs_create_file("guc_log", mode, + parent, buf, &relay_file_operations); + return buf_file; +} + +/* + * file_remove() default callback. Removes relay file in debugfs. + */ +static int remove_buf_file_callback(struct dentry *dentry) +{ + debugfs_remove(dentry); + return 0; +} + +/* relay channel callbacks */ +static struct rchan_callbacks relay_callbacks = { + .subbuf_start = subbuf_start_callback, + .create_buf_file = create_buf_file_callback, + .remove_buf_file = remove_buf_file_callback, +}; + +static void guc_log_remove_relay_file(struct intel_guc *guc) +{ + relay_close(guc->log.relay_chan); +} + +static int guc_log_create_relay_file(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct rchan *guc_log_relay_chan; + struct dentry *log_dir; + size_t n_subbufs, subbuf_size; + + /* For now create the log file in /sys/kernel/debug/dri/0 dir */ + log_dir = dev_priv->drm.primary->debugfs_root; + + /* If /sys/kernel/debug/dri/0 location do not exist, then debugfs is + * not mounted and so can't create the relay file. + * The relay API seems to fit well with debugfs only, for availing relay + * there are 3 requirements which can be met for debugfs file only in a + * straightforward/clean manner :- + * i) Need the associated dentry pointer of the file, while opening the + * relay channel. + * ii) Should be able to use 'relay_file_operations' fops for the file. + * iii) Set the 'i_private' field of file's inode to the pointer of + * relay channel buffer. + */ + if (!log_dir) { + DRM_ERROR("Debugfs dir not available yet for GuC log file\n"); + return -ENODEV; + } + + /* Keep the size of sub buffers same as shared log buffer */ + subbuf_size = guc->log.vma->obj->base.size; + + /* Store up to 8 snapshots, which is large enough to buffer sufficient + * boot time logs and provides enough leeway to User, in terms of + * latency, for consuming the logs from relay. Also doesn't take + * up too much memory. + */ + n_subbufs = 8; + + guc_log_relay_chan = relay_open("guc_log", log_dir, subbuf_size, + n_subbufs, &relay_callbacks, dev_priv); + if (!guc_log_relay_chan) { + DRM_ERROR("Couldn't create relay chan for GuC logging\n"); + return -ENOMEM; + } + + GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); + /* FIXME: Cover the update under a lock ? */ + guc->log.relay_chan = guc_log_relay_chan; + return 0; +} + static void guc_move_to_next_buf(struct intel_guc *guc) { + /* Make sure the updates made in the sub buffer are visible when + * Consumer sees the following update to offset inside the sub buffer. + */ + smp_wmb(); + + /* All data has been written, so now move the offset of sub buffer. */ + relay_reserve(guc->log.relay_chan, guc->log.vma->obj->base.size); + + /* Switch to the next sub buffer */ + relay_flush(guc->log.relay_chan); } static void *guc_get_write_buffer(struct intel_guc *guc) { - return NULL; + /* FIXME: Cover the check under a lock ? */ + if (!guc->log.relay_chan) + return NULL; + + /* Just get the base address of a new sub buffer and copy data into it + * ourselves. NULL will be returned in no-overwrite mode, if all sub + * buffers are full. Could have used the relay_write() to indirectly + * copy the data, but that would have been bit convoluted, as we need to + * write to only certain locations inside a sub buffer which cannot be + * done without using relay_reserve() along with relay_write(). So its + * better to use relay_reserve() alone. + */ + return relay_reserve(guc->log.relay_chan, 0); } static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) @@ -943,6 +1092,12 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) if (log_buf_snapshot_state) guc_move_to_next_buf(guc); + else { + /* Used rate limited to avoid deluge of messages, logs might be + * getting consumed by User at a slow rate. + */ + DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n"); + } } static void guc_capture_logs_work(struct work_struct *work) @@ -967,6 +1122,11 @@ static void guc_log_cleanup(struct intel_guc *guc) guc->log.flush_wq = NULL; + if (guc->log.relay_chan) + guc_log_remove_relay_file(guc); + + guc->log.relay_chan = NULL; + if (guc->log.buf_addr) i915_gem_object_unpin_map(guc->log.vma->obj); @@ -1057,6 +1217,36 @@ static void guc_log_create(struct intel_guc *guc) guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; } +static int guc_log_late_setup(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + int ret; + + lockdep_assert_held(&dev_priv->drm.struct_mutex); + + if (i915.guc_log_level < 0) + return -EINVAL; + + /* If log_level was set as -1 at boot time, then setup needed to + * handle log buffer flush interrupts would not have been done yet, + * so do that now. + */ + ret = guc_log_create_extras(guc); + if (ret) + goto err; + + ret = guc_log_create_relay_file(guc); + if (ret) + goto err; + + return 0; +err: + guc_log_cleanup(guc); + /* logging will remain off */ + i915.guc_log_level = -1; + return ret; +} + static void guc_policies_init(struct guc_policies *policies) { struct guc_policy *policy; @@ -1238,7 +1428,6 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv) struct intel_guc *guc = &dev_priv->guc; i915_vma_unpin_and_release(&guc->ads_vma); - guc_log_cleanup(guc); i915_vma_unpin_and_release(&guc->log.vma); if (guc->ctx_pool_vma) @@ -1312,3 +1501,23 @@ void i915_guc_capture_logs(struct drm_i915_private *dev_priv) host2guc_logbuffer_flush_complete(&dev_priv->guc); intel_runtime_pm_put(dev_priv); } + +void i915_guc_unregister(struct drm_i915_private *dev_priv) +{ + if (!i915.enable_guc_submission) + return; + + mutex_lock(&dev_priv->drm.struct_mutex); + guc_log_cleanup(&dev_priv->guc); + mutex_unlock(&dev_priv->drm.struct_mutex); +} + +void i915_guc_register(struct drm_i915_private *dev_priv) +{ + if (!i915.enable_guc_submission) + return; + + mutex_lock(&dev_priv->drm.struct_mutex); + guc_log_late_setup(&dev_priv->guc); + mutex_unlock(&dev_priv->drm.struct_mutex); +} diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index fb72313c8649..e7999dd0f315 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -129,6 +129,7 @@ struct intel_guc_log { void *buf_addr; struct workqueue_struct *flush_wq; struct work_struct flush_work; + struct rchan *relay_chan; }; struct intel_guc { @@ -174,5 +175,7 @@ void i915_guc_wq_unreserve(struct drm_i915_gem_request *request); void i915_guc_submission_disable(struct drm_i915_private *dev_priv); void i915_guc_submission_fini(struct drm_i915_private *dev_priv); void i915_guc_capture_logs(struct drm_i915_private *dev_priv); +void i915_guc_register(struct drm_i915_private *dev_priv); +void i915_guc_unregister(struct drm_i915_private *dev_priv); #endif -- cgit v1.2.3 From 5dd7989bbd28a76f1740344e4e2d01dc848158a9 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:35 +0530 Subject: drm/i915: New lock to serialize the Host2GuC actions With the addition of new Host2GuC actions related to GuC logging, there is a need of a lock to serialize them, as they can execute concurrently with each other and also with other existing actions. v2: Use mutex in place of spinlock to serialize, as sleep can happen while waiting for the action's response from GuC. (Tvrtko) v3: To conform to the general rules, acquire mutex before taking the forcewake. (Tvrtko) Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 3 +++ drivers/gpu/drm/i915/intel_guc.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index c1d2a9042a1c..cafff7ca71c7 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -87,6 +87,7 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len) if (WARN_ON(len < 1 || len > 15)) return -EINVAL; + mutex_lock(&guc->action_lock); intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); dev_priv->guc.action_count += 1; @@ -125,6 +126,7 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len) dev_priv->guc.action_status = status; intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + mutex_unlock(&guc->action_lock); return ret; } @@ -1366,6 +1368,7 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv) guc->ctx_pool_vma = vma; ida_init(&guc->ctx_ids); + mutex_init(&guc->action_lock); guc_log_create(guc); guc_addon_create(guc); diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index e7999dd0f315..907d13a71c23 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -157,6 +157,9 @@ struct intel_guc { uint64_t submissions[I915_NUM_ENGINES]; uint32_t last_seqno[I915_NUM_ENGINES]; + + /* To serialize the Host2GuC actions */ + struct mutex action_lock; }; /* intel_guc_loader.c */ -- cgit v1.2.3 From 5aa1ee4b12bee127576b3ea41eeafda2c45bc118 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:36 +0530 Subject: drm/i915: Add stats for GuC log buffer flush interrupts GuC firmware sends an interrupt to flush the log buffer when it becomes half full. GuC firmware also tracks how many times the buffer overflowed. It would be useful to maintain a statistics of how many flush interrupts were received and for which type of log buffer, along with the overflow count of each buffer type. Augmented i915_log_info debugfs to report back these statistics. v2: - Update the logic to detect multiple overflows between the 2 flush interrupts and also log a message for overflow (Tvrtko) - Track the number of times there was no free sub buffer to capture the GuC log buffer. (Tvrtko) v3: - Fix the printf field width for overflow counter, set it to 10 as per the max value of u32, which takes 10 digits in decimal form. (Tvrtko) v4: - Move the log buffer overflow handling to a new function for better readability. (Tvrtko) Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_debugfs.c | 28 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_guc_submission.c | 31 +++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_irq.c | 2 ++ drivers/gpu/drm/i915/intel_guc.h | 7 +++++++ 4 files changed, 67 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index c5716397da20..e24f69cdc69b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2416,6 +2416,32 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data) return 0; } +static void i915_guc_log_info(struct seq_file *m, + struct drm_i915_private *dev_priv) +{ + struct intel_guc *guc = &dev_priv->guc; + + seq_puts(m, "\nGuC logging stats:\n"); + + seq_printf(m, "\tISR: flush count %10u, overflow count %10u\n", + guc->log.flush_count[GUC_ISR_LOG_BUFFER], + guc->log.total_overflow_count[GUC_ISR_LOG_BUFFER]); + + seq_printf(m, "\tDPC: flush count %10u, overflow count %10u\n", + guc->log.flush_count[GUC_DPC_LOG_BUFFER], + guc->log.total_overflow_count[GUC_DPC_LOG_BUFFER]); + + seq_printf(m, "\tCRASH: flush count %10u, overflow count %10u\n", + guc->log.flush_count[GUC_CRASH_DUMP_LOG_BUFFER], + guc->log.total_overflow_count[GUC_CRASH_DUMP_LOG_BUFFER]); + + seq_printf(m, "\tTotal flush interrupt count: %u\n", + guc->log.flush_interrupt_count); + + seq_printf(m, "\tCapture miss count: %u\n", + guc->log.capture_miss_count); +} + static void i915_guc_client_info(struct seq_file *m, struct drm_i915_private *dev_priv, struct i915_guc_client *client) @@ -2489,6 +2515,8 @@ static int i915_guc_info(struct seq_file *m, void *data) seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client); i915_guc_client_info(m, dev_priv, &client); + i915_guc_log_info(m, dev_priv); + /* Add more as required ... */ return 0; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index cafff7ca71c7..f2d71cadae99 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1016,6 +1016,29 @@ static void *guc_get_write_buffer(struct intel_guc *guc) return relay_reserve(guc->log.relay_chan, 0); } +static bool +guc_check_log_buf_overflow(struct intel_guc *guc, + enum guc_log_buffer_type type, unsigned int full_cnt) +{ + unsigned int prev_full_cnt = guc->log.prev_overflow_count[type]; + bool overflow = false; + + if (full_cnt != prev_full_cnt) { + overflow = true; + + guc->log.prev_overflow_count[type] = full_cnt; + guc->log.total_overflow_count[type] += full_cnt - prev_full_cnt; + + if (full_cnt < prev_full_cnt) { + /* buffer_full_cnt is a 4 bit counter */ + guc->log.total_overflow_count[type] += 16; + } + DRM_ERROR_RATELIMITED("GuC log buffer overflow\n"); + } + + return overflow; +} + static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) { switch (type) { @@ -1036,7 +1059,7 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) { struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; struct guc_log_buffer_state log_buf_state_local; - unsigned int buffer_size, write_offset; + unsigned int buffer_size, write_offset, full_cnt; enum guc_log_buffer_type type; void *src_data, *dst_data; @@ -1062,6 +1085,11 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) sizeof(struct guc_log_buffer_state)); buffer_size = guc_get_log_buffer_size(type); write_offset = log_buf_state_local.sampled_write_ptr; + full_cnt = log_buf_state_local.buffer_full_cnt; + + /* Bookkeeping stuff */ + guc->log.flush_count[type] += log_buf_state_local.flush_to_file; + guc_check_log_buf_overflow(guc, type, full_cnt); /* Update the state of shared log buffer */ log_buf_state->read_ptr = write_offset; @@ -1099,6 +1127,7 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) * getting consumed by User at a slow rate. */ DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n"); + guc->log.capture_miss_count++; } } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 253c22109c3f..9111cfdf217a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1691,6 +1691,8 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) /* Handle flush interrupt in bottom half */ queue_work(dev_priv->guc.log.flush_wq, &dev_priv->guc.log.flush_work); + + dev_priv->guc.log.flush_interrupt_count++; } else { /* Not clearing of unhandled event bits won't result in * re-triggering of the interrupt. diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 907d13a71c23..d034c9845a22 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -130,6 +130,13 @@ struct intel_guc_log { struct workqueue_struct *flush_wq; struct work_struct flush_work; struct rchan *relay_chan; + + /* logging related stats */ + u32 capture_miss_count; + u32 flush_interrupt_count; + u32 prev_overflow_count[GUC_MAX_LOG_BUFFER]; + u32 total_overflow_count[GUC_MAX_LOG_BUFFER]; + u32 flush_count[GUC_MAX_LOG_BUFFER]; }; struct intel_guc { -- cgit v1.2.3 From 6941f3c9ce4a86fdcc25a9af924e32c4b77cae96 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:37 +0530 Subject: drm/i915: Optimization to reduce the sampling time of GuC log buffer GuC firmware sends an interrupt to flush the log buffer when it becomes half full, so Driver doesn't really need to sample the complete buffer and can just copy only the newly written data by GuC into the local buffer, i.e. as per the read & write pointer values. Moreover the flush interrupt would generally come for one type of log buffer, when it becomes half full, so at that time the other 2 types of log buffer would comparatively have much lesser unread data in them. In case of overflow reported by GuC, Driver do need to copy the entire buffer as the whole buffer would contain the unread data. v2: Rebase. v3: Fix the blooper of doing the copy twice. (Tvrtko) v4: Add curlies for 'else' case also, matching the 'if'. (Tvrtko) Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index f2d71cadae99..7fb0077aedcd 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1057,11 +1057,12 @@ static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) static void guc_read_update_log_buffer(struct intel_guc *guc) { + unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; struct guc_log_buffer_state log_buf_state_local; - unsigned int buffer_size, write_offset, full_cnt; enum guc_log_buffer_type type; void *src_data, *dst_data; + bool new_overflow; if (WARN_ON(!guc->log.buf_addr)) return; @@ -1084,12 +1085,13 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); buffer_size = guc_get_log_buffer_size(type); + read_offset = log_buf_state_local.read_ptr; write_offset = log_buf_state_local.sampled_write_ptr; full_cnt = log_buf_state_local.buffer_full_cnt; /* Bookkeeping stuff */ guc->log.flush_count[type] += log_buf_state_local.flush_to_file; - guc_check_log_buf_overflow(guc, type, full_cnt); + new_overflow = guc_check_log_buf_overflow(guc, type, full_cnt); /* Update the state of shared log buffer */ log_buf_state->read_ptr = write_offset; @@ -1112,7 +1114,27 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) log_buf_snapshot_state++; /* Now copy the actual logs. */ - memcpy(dst_data, src_data, buffer_size); + if (unlikely(new_overflow)) { + /* copy the whole buffer in case of overflow */ + read_offset = 0; + write_offset = buffer_size; + } else if (unlikely((read_offset > buffer_size) || + (write_offset > buffer_size))) { + DRM_ERROR("invalid log buffer state\n"); + /* copy whole buffer as offsets are unreliable */ + read_offset = 0; + write_offset = buffer_size; + } + + /* Just copy the newly written data */ + if (read_offset > write_offset) { + memcpy(dst_data, src_data, write_offset); + bytes_to_copy = buffer_size - read_offset; + } else { + bytes_to_copy = write_offset - read_offset; + } + memcpy(dst_data + read_offset, + src_data + read_offset, bytes_to_copy); src_data += buffer_size; dst_data += buffer_size; -- cgit v1.2.3 From 72c0bc66ca57d1f88df1d330a84c3e362be53af3 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:38 +0530 Subject: drm/i915: Increase GuC log buffer size to reduce flush interrupts In cases where GuC generate logs at a very high rate, correspondingly the rate of flush interrupts is also very high. So far total 8 pages were allocated for storing both ISR & DPC logs. As per the half-full draining protocol followed by GuC, by doubling the number of pages, the frequency of flush interrupts can be cut down to almost half, which then helps in reducing the logging overhead. So now allocating 8 pages apiece for ISR & DPC logs. This also helps in reducing the output log file size, apart from reducing the flush interrupt count. With the original settings, 44 KB was needed for one snapshot. With modified settings, 76 KB is needed for a snapshot which will be equivalent to 2 snapshots of the original setting. So 12KB saving, every 88 KB, over the original setting. Suggested-by: Tvrtko Ursulin Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_guc_fwif.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index adb1ffdc37c2..324ea902558b 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -104,9 +104,9 @@ #define GUC_LOG_ALLOC_IN_MEGABYTE (1 << 3) #define GUC_LOG_CRASH_PAGES 1 #define GUC_LOG_CRASH_SHIFT 4 -#define GUC_LOG_DPC_PAGES 3 +#define GUC_LOG_DPC_PAGES 7 #define GUC_LOG_DPC_SHIFT 6 -#define GUC_LOG_ISR_PAGES 3 +#define GUC_LOG_ISR_PAGES 7 #define GUC_LOG_ISR_SHIFT 9 #define GUC_LOG_BUF_ADDR_SHIFT 12 @@ -437,9 +437,9 @@ enum guc_log_buffer_type { * | Crash dump state header | * Page1 +-------------------------------+ * | ISR logs | - * Page5 +-------------------------------+ - * | DPC logs | * Page9 +-------------------------------+ + * | DPC logs | + * Page17 +-------------------------------+ * | Crash Dump logs | * +-------------------------------+ * -- cgit v1.2.3 From 27b85beae0e75232dedf5a141d3eb50f36567dd2 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:39 +0530 Subject: drm/i915: Augment i915 error state to include the dump of GuC log buffer Added the dump of GuC log buffer to i915 error state, as the contents of GuC log buffer would also be useful to determine that why the GPU reset was triggered. v2: - For uniformity use existing helper function print_error_obj() to dump out contents of GuC log buffer, pretty printing is better left to userspace. (Chris) - Skip the dumping of GuC log buffer when logging is disabled as it won't be of any use. - Rebase. v3: Rebase. Suggested-by: Chris Wilson Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 72215b7b5b89..b4cb1f0f0632 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -778,6 +778,7 @@ struct drm_i915_error_state { struct intel_overlay_error_state *overlay; struct intel_display_error_state *display; struct drm_i915_error_object *semaphore; + struct drm_i915_error_object *guc_log; struct drm_i915_error_engine { int engine_id; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 242b9a927899..48fece3bb7a9 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -702,6 +702,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, print_error_obj(m, NULL, "Semaphores", error->semaphore); + print_error_obj(m, NULL, "GuC log buffer", error->guc_log); + if (error->overlay) intel_overlay_print_error_state(m, error->overlay); @@ -782,6 +784,7 @@ static void i915_error_state_free(struct kref *error_ref) } i915_error_object_free(error->semaphore); + i915_error_object_free(error->guc_log); for (i = 0; i < ARRAY_SIZE(error->active_bo); i++) kfree(error->active_bo[i]); @@ -1408,6 +1411,17 @@ static void i915_capture_pinned_buffers(struct drm_i915_private *dev_priv, error->pinned_bo = bo; } +static void i915_gem_capture_guc_log_buffer(struct drm_i915_private *dev_priv, + struct drm_i915_error_state *error) +{ + /* Capturing log buf contents won't be useful if logging was disabled */ + if (!dev_priv->guc.log.vma || (i915.guc_log_level < 0)) + return; + + error->guc_log = i915_error_object_create(dev_priv, + dev_priv->guc.log.vma); +} + /* Capture all registers which don't fit into another category. */ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, struct drm_i915_error_state *error) @@ -1532,6 +1546,7 @@ static int capture(void *data) i915_gem_record_rings(error->i915, error); i915_capture_active_buffers(error->i915, error); i915_capture_pinned_buffers(error->i915, error); + i915_gem_capture_guc_log_buffer(error->i915, error); do_gettimeofday(&error->time); -- cgit v1.2.3 From 896a0cb0fe728b24597439db684b18420ed97fde Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 12 Oct 2016 21:54:40 +0530 Subject: drm/i915: Support for forceful flush of GuC log buffer GuC firmware sends a flush interrupt to Host when the log buffer is half full and at that time only it updates the log buffer state. But in certain cases, as described below, it could be useful to have all that even when log buffer is only partially full. For that there is a force log buffer flush Host2GuC action supported by GuC firmware. For Validation requirements, a forceful flush is needed to collect the left over logs on disabling logging. The same can be done before proceeding with GPU/GuC reset as there could be some data in log buffer which is yet to be captured and those logs would be particularly useful to understand that why the reset was initiated. Signed-off-by: Sagar Arun Kamble Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 30 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_guc.h | 1 + 2 files changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 7fb0077aedcd..9fd9a3ae1229 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -183,6 +183,16 @@ static int host2guc_logbuffer_flush_complete(struct intel_guc *guc) return host2guc_action(guc, data, 1); } +static int host2guc_force_logbuffer_flush(struct intel_guc *guc) +{ + u32 data[2]; + + data[0] = HOST2GUC_ACTION_FORCE_LOG_BUFFER_FLUSH; + data[1] = 0; + + return host2guc_action(guc, data, 2); +} + /* * Initialise, update, or clear doorbell data shared with the GuC * @@ -1556,6 +1566,26 @@ void i915_guc_capture_logs(struct drm_i915_private *dev_priv) intel_runtime_pm_put(dev_priv); } +void i915_guc_flush_logs(struct drm_i915_private *dev_priv) +{ + if (!i915.enable_guc_submission || (i915.guc_log_level < 0)) + return; + + /* First disable the interrupts, will be renabled afterwards */ + gen9_disable_guc_interrupts(dev_priv); + + /* Before initiating the forceful flush, wait for any pending/ongoing + * flush to complete otherwise forceful flush may not actually happen. + */ + flush_work(&dev_priv->guc.log.flush_work); + + /* Ask GuC to update the log buffer state */ + host2guc_force_logbuffer_flush(&dev_priv->guc); + + /* GuC would have updated log buffer by now, so capture it */ + i915_guc_capture_logs(dev_priv); +} + void i915_guc_unregister(struct drm_i915_private *dev_priv) { if (!i915.enable_guc_submission) diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index d034c9845a22..71da75e7f6b4 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -185,6 +185,7 @@ void i915_guc_wq_unreserve(struct drm_i915_gem_request *request); void i915_guc_submission_disable(struct drm_i915_private *dev_priv); void i915_guc_submission_fini(struct drm_i915_private *dev_priv); void i915_guc_capture_logs(struct drm_i915_private *dev_priv); +void i915_guc_flush_logs(struct drm_i915_private *dev_priv); void i915_guc_register(struct drm_i915_private *dev_priv); void i915_guc_unregister(struct drm_i915_private *dev_priv); -- cgit v1.2.3 From 685534ef4c8faff1f69c9962ad3013e17354ff8b Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 12 Oct 2016 21:54:41 +0530 Subject: drm/i915: Debugfs support for GuC logging control This patch provides debugfs interface i915_guc_output_control for on the fly enabling/disabling of logging in GuC firmware and controlling the verbosity level of logs. The value written to the file, should have bit 0 set to enable logging and bits 4-7 should contain the verbosity info. v2: Add a forceful flush, to collect left over logs, on disabling logging. Useful for Validation. v3: Besides minor cleanup, implement read method for the debugfs file and set the guc_log_level to -1 when logging is disabled. (Tvrtko) v4: Minor cleanup & rebase. (Tvrtko) v5: - Lock struct_mutex after the NULL check for guc log buffer vma. (Chris) - Rebase. Signed-off-by: Sagar Arun Kamble Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_debugfs.c | 41 ++++++++++++++++++++- drivers/gpu/drm/i915/i915_guc_submission.c | 59 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_guc.h | 1 + 3 files changed, 100 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e24f69cdc69b..be92efe3453f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2548,6 +2548,44 @@ static int i915_guc_log_dump(struct seq_file *m, void *data) return 0; } +static int i915_guc_log_control_get(void *data, u64 *val) +{ + struct drm_device *dev = data; + struct drm_i915_private *dev_priv = to_i915(dev); + + if (!dev_priv->guc.log.vma) + return -EINVAL; + + *val = i915.guc_log_level; + + return 0; +} + +static int i915_guc_log_control_set(void *data, u64 val) +{ + struct drm_device *dev = data; + struct drm_i915_private *dev_priv = to_i915(dev); + int ret; + + if (!dev_priv->guc.log.vma) + return -EINVAL; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + intel_runtime_pm_get(dev_priv); + ret = i915_guc_log_control(dev_priv, val); + intel_runtime_pm_put(dev_priv); + + mutex_unlock(&dev->struct_mutex); + return ret; +} + +DEFINE_SIMPLE_ATTRIBUTE(i915_guc_log_control_fops, + i915_guc_log_control_get, i915_guc_log_control_set, + "%lld\n"); + static int i915_edp_psr_status(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -5454,7 +5492,8 @@ static const struct i915_debugfs_files { {"i915_fbc_false_color", &i915_fbc_fc_fops}, {"i915_dp_test_data", &i915_displayport_test_data_fops}, {"i915_dp_test_type", &i915_displayport_test_type_fops}, - {"i915_dp_test_active", &i915_displayport_test_active_fops} + {"i915_dp_test_active", &i915_displayport_test_active_fops}, + {"i915_guc_log_control", &i915_guc_log_control_fops} }; void intel_display_crc_init(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 9fd9a3ae1229..6fac8e9cbd38 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -193,6 +193,16 @@ static int host2guc_force_logbuffer_flush(struct intel_guc *guc) return host2guc_action(guc, data, 2); } +static int host2guc_logging_control(struct intel_guc *guc, u32 control_val) +{ + u32 data[2]; + + data[0] = HOST2GUC_ACTION_UK_LOG_ENABLE_LOGGING; + data[1] = control_val; + + return host2guc_action(guc, data, 2); +} + /* * Initialise, update, or clear doorbell data shared with the GuC * @@ -1605,3 +1615,52 @@ void i915_guc_register(struct drm_i915_private *dev_priv) guc_log_late_setup(&dev_priv->guc); mutex_unlock(&dev_priv->drm.struct_mutex); } + +int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) +{ + union guc_log_control log_param; + int ret; + + log_param.value = control_val; + + if (log_param.verbosity < GUC_LOG_VERBOSITY_MIN || + log_param.verbosity > GUC_LOG_VERBOSITY_MAX) + return -EINVAL; + + /* This combination doesn't make sense & won't have any effect */ + if (!log_param.logging_enabled && (i915.guc_log_level < 0)) + return 0; + + ret = host2guc_logging_control(&dev_priv->guc, log_param.value); + if (ret < 0) { + DRM_DEBUG_DRIVER("host2guc action failed %d\n", ret); + return ret; + } + + i915.guc_log_level = log_param.verbosity; + + /* If log_level was set as -1 at boot time, then the relay channel file + * wouldn't have been created by now and interrupts also would not have + * been enabled. + */ + if (!dev_priv->guc.log.relay_chan) { + ret = guc_log_late_setup(&dev_priv->guc); + if (!ret) + gen9_enable_guc_interrupts(dev_priv); + } else if (!log_param.logging_enabled) { + /* Once logging is disabled, GuC won't generate logs & send an + * interrupt. But there could be some data in the log buffer + * which is yet to be captured. So request GuC to update the log + * buffer state and then collect the left over logs. + */ + i915_guc_flush_logs(dev_priv); + + /* As logging is disabled, update log level to reflect that */ + i915.guc_log_level = -1; + } else { + /* In case interrupts were disabled, enable them now */ + gen9_enable_guc_interrupts(dev_priv); + } + + return ret; +} diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 71da75e7f6b4..49ced0bad0f5 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -188,5 +188,6 @@ void i915_guc_capture_logs(struct drm_i915_private *dev_priv); void i915_guc_flush_logs(struct drm_i915_private *dev_priv); void i915_guc_register(struct drm_i915_private *dev_priv); void i915_guc_unregister(struct drm_i915_private *dev_priv); +int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val); #endif -- cgit v1.2.3 From 717065907ff7df57c268eac7bee44fbf3ef6faab Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:42 +0530 Subject: drm/i915: Use SSE4.1 movntdqa based memcpy for sampling GuC log buffer To ensure that we always get the up-to-date data from log buffer, its better to access the buffer through an uncached CPU mapping. Also the way buffer is accessed from GuC & Host side, manually doing cache flush may not be effective always if cached CPU mapping is used. In order to avoid any performance drop & have fast reads from the GuC log buffer, used SSE4.1 movntdqa based memcpy function i915_memcpy_from_wc, as copying using movntqda from WC type memory is almost as fast as reading from WB memory. This way log buffer sampling time will not get increased and so would be able to deal with the flush interrupt storm when GuC is generating logs at a very high rate. Ideally SSE 4.1 should be present on all chipsets supporting GuC based submisssions, but if not then logging will not be enabled. v2: Rebase. v3: Squash the WC type vmalloc mapping patch with this patch. (Chris) Suggested-by: Chris Wilson Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 6fac8e9cbd38..8cdcc459884f 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1148,18 +1148,16 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) /* Just copy the newly written data */ if (read_offset > write_offset) { - memcpy(dst_data, src_data, write_offset); + i915_memcpy_from_wc(dst_data, src_data, write_offset); bytes_to_copy = buffer_size - read_offset; } else { bytes_to_copy = write_offset - read_offset; } - memcpy(dst_data + read_offset, - src_data + read_offset, bytes_to_copy); + i915_memcpy_from_wc(dst_data + read_offset, + src_data + read_offset, bytes_to_copy); src_data += buffer_size; dst_data += buffer_size; - - /* FIXME: invalidate/flush for log buffer needed */ } if (log_buf_snapshot_state) @@ -1219,8 +1217,11 @@ static int guc_log_create_extras(struct intel_guc *guc) return 0; if (!guc->log.buf_addr) { - /* Create a vmalloc mapping of log buffer pages */ - vaddr = i915_gem_object_pin_map(guc->log.vma->obj, I915_MAP_WB); + /* Create a WC (Uncached for read) vmalloc mapping of log + * buffer pages, so that we can directly get the data + * (up-to-date) from memory. + */ + vaddr = i915_gem_object_pin_map(guc->log.vma->obj, I915_MAP_WC); if (IS_ERR(vaddr)) { ret = PTR_ERR(vaddr); DRM_ERROR("Couldn't map log buffer pages %d\n", ret); @@ -1263,6 +1264,16 @@ static void guc_log_create(struct intel_guc *guc) vma = guc->log.vma; if (!vma) { + /* We require SSE 4.1 for fast reads from the GuC log buffer and + * it should be present on the chipsets supporting GuC based + * submisssions. + */ + if (WARN_ON(!i915_memcpy_from_wc(NULL, NULL, 0))) { + /* logging will not be enabled */ + i915.guc_log_level = -1; + return; + } + vma = guc_allocate_vma(guc, size); if (IS_ERR(vma)) { /* logging will be off */ -- cgit v1.2.3 From 1e6b8b0dc8d48f413237c215ceaea031f3469b2d Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:43 +0530 Subject: drm/i915: Early creation of relay channel for capturing boot time logs As per the current i915 Driver load sequence, debugfs registration is done at the end and so the relay channel debugfs file is also created after that but the GuC firmware is loaded much earlier in the sequence. As a result Driver could miss capturing the boot-time logs of GuC firmware if there are flush interrupts from the GuC side. Relay has a provision to support early logging where initially only relay channel can be created, to have buffers for storing logs, and later on channel can be associated with a debugfs file at appropriate time. Have availed that, which allows Driver to capture boot time logs also, which can be collected once Userspace comes up. v2: - Remove the couple of FIXMEs, as now the relay channel will be created early before enabling the flush interrupts, so no possibility of relay channel pointer being modified & read at the same time from 2 different execution contexts. - Rebase. v3: - Add a comment to justiy setting 'is_global' before the NULL check on the parent directory dentry pointer. Suggested-by: Chris Wilson Signed-off-by: Akash Goel Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 71 ++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 8cdcc459884f..ac8fe8bd97aa 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -915,15 +915,16 @@ static struct dentry *create_buf_file_callback(const char *filename, { struct dentry *buf_file; - if (!parent) - return NULL; - /* This to enable the use of a single buffer for the relay channel and * correspondingly have a single file exposed to User, through which * it can collect the logs in order without any post-processing. + * Need to set 'is_global' even if parent is NULL for early logging. */ *is_global = 1; + if (!parent) + return NULL; + /* Not using the channel filename passed as an argument, since for each * channel relay appends the corresponding CPU number to the filename * passed in relay_open(). This should be fine as relay just needs a @@ -956,13 +957,40 @@ static void guc_log_remove_relay_file(struct intel_guc *guc) relay_close(guc->log.relay_chan); } -static int guc_log_create_relay_file(struct intel_guc *guc) +static int guc_log_create_relay_channel(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); struct rchan *guc_log_relay_chan; - struct dentry *log_dir; size_t n_subbufs, subbuf_size; + /* Keep the size of sub buffers same as shared log buffer */ + subbuf_size = guc->log.vma->obj->base.size; + + /* Store up to 8 snapshots, which is large enough to buffer sufficient + * boot time logs and provides enough leeway to User, in terms of + * latency, for consuming the logs from relay. Also doesn't take + * up too much memory. + */ + n_subbufs = 8; + + guc_log_relay_chan = relay_open(NULL, NULL, subbuf_size, + n_subbufs, &relay_callbacks, dev_priv); + if (!guc_log_relay_chan) { + DRM_ERROR("Couldn't create relay chan for GuC logging\n"); + return -ENOMEM; + } + + GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); + guc->log.relay_chan = guc_log_relay_chan; + return 0; +} + +static int guc_log_create_relay_file(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct dentry *log_dir; + int ret; + /* For now create the log file in /sys/kernel/debug/dri/0 dir */ log_dir = dev_priv->drm.primary->debugfs_root; @@ -982,26 +1010,12 @@ static int guc_log_create_relay_file(struct intel_guc *guc) return -ENODEV; } - /* Keep the size of sub buffers same as shared log buffer */ - subbuf_size = guc->log.vma->obj->base.size; - - /* Store up to 8 snapshots, which is large enough to buffer sufficient - * boot time logs and provides enough leeway to User, in terms of - * latency, for consuming the logs from relay. Also doesn't take - * up too much memory. - */ - n_subbufs = 8; - - guc_log_relay_chan = relay_open("guc_log", log_dir, subbuf_size, - n_subbufs, &relay_callbacks, dev_priv); - if (!guc_log_relay_chan) { - DRM_ERROR("Couldn't create relay chan for GuC logging\n"); - return -ENOMEM; + ret = relay_late_setup_files(guc->log.relay_chan, "guc_log", log_dir); + if (ret) { + DRM_ERROR("Couldn't associate relay chan with file %d\n", ret); + return ret; } - GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); - /* FIXME: Cover the update under a lock ? */ - guc->log.relay_chan = guc_log_relay_chan; return 0; } @@ -1021,7 +1035,6 @@ static void guc_move_to_next_buf(struct intel_guc *guc) static void *guc_get_write_buffer(struct intel_guc *guc) { - /* FIXME: Cover the check under a lock ? */ if (!guc->log.relay_chan) return NULL; @@ -1231,6 +1244,16 @@ static int guc_log_create_extras(struct intel_guc *guc) guc->log.buf_addr = vaddr; } + if (!guc->log.relay_chan) { + /* Create a relay channel, so that we have buffers for storing + * the GuC firmware logs, the channel will be linked with a file + * later on when debugfs is registered. + */ + ret = guc_log_create_relay_channel(guc); + if (ret) + return ret; + } + if (!guc->log.flush_wq) { INIT_WORK(&guc->log.flush_work, guc_capture_logs_work); -- cgit v1.2.3 From 7ef54de7fdf13953c1721e4b6b43e7b8d76d5521 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Wed, 12 Oct 2016 21:54:44 +0530 Subject: drm/i915: Mark the GuC log buffer flush interrupts handling WQ as freezable The GuC log buffer flush work item has to do a register access to send the ack to GuC and this work item, if not synced before suspend, can potentially get executed after the GFX device is suspended. This work item function uses rpm get/put calls around the Hw access, which covers the rpm suspend case but for system suspend a sync would be required as kernel can potentially schedule the work items even after some devices, including GFX, have been put to suspend. But sync has to be done only for the system suspend case, as sync along with rpm get/put can cause a deadlock for rpm suspend path. To have the sync, but like a NOOP, for rpm suspend path also this work item could have been queued from the irq handler only when the device is runtime active & kept active while that work item is pending or getting executed but an interrupt can come even after the device is out of use and so can potentially lead to missing of this work item. By marking the workqueue, dedicated for handling GuC log buffer flush interrupts, as freezable we don't have to bother about flushing of this work item from the suspend hooks, the pending work item if any will be either executed before the suspend or scheduled later on resume. This way the handling of log buffer flush work item can be kept same between system suspend & rpm suspend. Suggested-by: Imre Deak Cc: Imre Deak Signed-off-by: Akash Goel Reviewed-by: Imre Deak Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index ac8fe8bd97aa..bf65ffa7e4ce 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1257,10 +1257,19 @@ static int guc_log_create_extras(struct intel_guc *guc) if (!guc->log.flush_wq) { INIT_WORK(&guc->log.flush_work, guc_capture_logs_work); - /* Need a dedicated wq to process log buffer flush interrupts - * from GuC without much delay so as to avoid any loss of logs. + /* + * GuC log buffer flush work item has to do register access to + * send the ack to GuC and this work item, if not synced before + * suspend, can potentially get executed after the GFX device is + * suspended. + * By marking the WQ as freezable, we don't have to bother about + * flushing of this work item from the suspend hooks, the pending + * work item if any will be either executed before the suspend + * or scheduled later on resume. This way the handling of work + * item can be kept same between system suspend & rpm suspend. */ - guc->log.flush_wq = alloc_ordered_workqueue("i915-guc_log", WQ_HIGHPRI); + guc->log.flush_wq = alloc_ordered_workqueue("i915-guc_log", + WQ_HIGHPRI | WQ_FREEZABLE); if (guc->log.flush_wq == NULL) { DRM_ERROR("Couldn't allocate the wq for GuC logging\n"); return -ENOMEM; -- cgit v1.2.3 From b937612f9d0d4586c18a42f9bb7d1623a08d7d13 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:12 +0200 Subject: staging: wlan-ng: avoid CamelCase: HFA384x_RID_CNFAPBCNint Replace CamelCase define to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 2 +- drivers/staging/wlan-ng/prism2mgmt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 6337b1da9eaa..1c7a171a5736 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -286,7 +286,7 @@ #define HFA384x_RID_CNFWEPFLAGS ((u16)0xFC28) #define HFA384x_RID_CNFAUTHENTICATION ((u16)0xFC2A) #define HFA384x_RID_CNFROAMINGMODE ((u16)0xFC2D) -#define HFA384x_RID_CNFAPBCNint ((u16)0xFC33) +#define HFA384x_RID_CNFAPBCNINT ((u16)0xFC33) #define HFA384x_RID_CNFDBMADJUST ((u16)0xFC46) #define HFA384x_RID_CNFWPADATA ((u16)0xFC48) #define HFA384x_RID_CNFBASICRATES ((u16)0xFCB3) diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 90db53dc7196..8be3a74c5419 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -583,7 +583,7 @@ int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) /* beacon period */ word = msg->beaconperiod.data; - result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word); + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word); if (result) { netdev_err(wlandev->netdev, "Failed to set beacon period=%d.\n", word); -- cgit v1.2.3 From e474b4d4ea6970d3762155c26fb70d3c04450ba6 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:13 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_HostScanRequest_data Replace CamelCase struct name and fields with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 6 +++--- drivers/staging/wlan-ng/prism2mgmt.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1c7a171a5736..89380ace6a3b 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -408,9 +408,9 @@ struct hfa384x_caplevel { #define HFA384x_CREATEIBSS_JOINCREATEIBSS 0 /*-- Configuration Record: HostScanRequest (data portion only) --*/ -struct hfa384x_HostScanRequest_data { - u16 channelList; - u16 txRate; +struct hfa384x_host_scan_request_data { + u16 channel_list; + u16 tx_rate; struct hfa384x_bytestr32 ssid; } __packed; diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 8be3a74c5419..3a56308332cc 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -123,7 +123,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) int i, timeout; int istmpenable = 0; - struct hfa384x_HostScanRequest_data scanreq; + struct hfa384x_host_scan_request_data scanreq; /* gatekeeper check */ if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, @@ -185,7 +185,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) /* set up the txrate to be 2MBPS. Should be fastest basicrate... */ word = HFA384x_RATEBIT_2; - scanreq.txRate = cpu_to_le16(word); + scanreq.tx_rate = cpu_to_le16(word); /* set up the channel list */ word = 0; @@ -197,7 +197,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) /* channel 1 is BIT 0 ... channel 14 is BIT 13 */ word |= (1 << (channel - 1)); } - scanreq.channelList = cpu_to_le16(word); + scanreq.channel_list = cpu_to_le16(word); /* set up the ssid, if present. */ scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len); @@ -293,7 +293,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) result = hfa384x_drvr_setconfig(hw, HFA384x_RID_HOSTSCAN, &scanreq, - sizeof(struct hfa384x_HostScanRequest_data)); + sizeof(struct hfa384x_host_scan_request_data)); if (result) { netdev_err(wlandev->netdev, "setconfig(SCANREQUEST) failed. result=%d\n", -- cgit v1.2.3 From 162da263c2c1b425b984cb092a348e1d157162e3 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:14 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_WPAData Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 2 +- drivers/staging/wlan-ng/prism2mib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 89380ace6a3b..a3a0ed577a00 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -428,7 +428,7 @@ struct hfa384x_authenticate_station_data { } __packed; /*-- Configuration Record: WPAData (data portion only) --*/ -struct hfa384x_WPAData { +struct hfa384x_wpa_data { u16 datalen; u8 data[0]; /* max 80 */ } __packed; diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index d7792cde2c6a..8ea6a647d037 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -709,7 +709,7 @@ static int prism2mib_priv(struct mibrec *mib, switch (mib->did) { case DIDmib_lnx_lnxConfigTable_lnxRSNAIE:{ - struct hfa384x_WPAData wpa; + struct hfa384x_wpa_data wpa; if (isget) { hfa384x_drvr_getconfig(hw, -- cgit v1.2.3 From c08510e166a65c119ae97e8add6cbb77d98c83aa Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:15 +0200 Subject: staging: wlan-ng: avoid CamelCase in fields of struct hfa384x_dbmcommsquality Replace CamelCase fields of struct with underscores to comply with the standard kernel coding style Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index a3a0ed577a00..2034c42662de 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -462,9 +462,9 @@ struct hfa384x_commsquality { /*-- Information Record: dmbcommsquality --*/ struct hfa384x_dbmcommsquality { - u16 CQdbm_currBSS; - u16 ASLdbm_currBSS; - u16 ANLdbm_currFC; + u16 cq_dbm_curr_bss; + u16 asl_dbm_curr_bss; + u16 anl_dbm_curr_fc; } __packed; /*-------------------------------------------------------------------- -- cgit v1.2.3 From 4cc454f27de75e79178d7b85516780b3a9ae45c9 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:16 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_CommTallies16 Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 2034c42662de..955609877988 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -610,7 +610,7 @@ struct hfa384x_rx_frame { */ /*-- Inquiry Frame, Diagnose: Communication Tallies --*/ -struct hfa384x_CommTallies16 { +struct hfa384x_comm_tallies_16 { u16 txunicastframes; u16 txmulticastframes; u16 txfragments; @@ -762,7 +762,7 @@ struct hfa384x_KeyIDChanged { /*-- Collection of all Inf frames ---------------*/ union hfa384x_infodata { - struct hfa384x_CommTallies16 commtallies16; + struct hfa384x_comm_tallies_16 commtallies16; struct hfa384x_comm_tallies_32 commtallies32; struct hfa384x_scan_result scanresult; struct hfa384x_ChInfoResult chinforesult; -- cgit v1.2.3 From c447358a76d1efb9f68321d94a9ebebb842be094 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:17 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_ChInfoResult Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 955609877988..c5b52088338a 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -688,7 +688,7 @@ struct hfa384x_ch_info_result_sub { #define HFA384x_CHINFORESULT_BSSACTIVE BIT(0) #define HFA384x_CHINFORESULT_PCFACTIVE BIT(1) -struct hfa384x_ChInfoResult { +struct hfa384x_ch_info_result { u16 scanchannels; struct hfa384x_ch_info_result_sub result[HFA384x_CHINFORESULT_MAX]; } __packed; @@ -765,7 +765,7 @@ union hfa384x_infodata { struct hfa384x_comm_tallies_16 commtallies16; struct hfa384x_comm_tallies_32 commtallies32; struct hfa384x_scan_result scanresult; - struct hfa384x_ChInfoResult chinforesult; + struct hfa384x_ch_info_result chinforesult; struct hfa384x_HScanResult hscanresult; struct hfa384x_LinkStatus linkstatus; struct hfa384x_assoc_status assocstatus; @@ -1366,7 +1366,7 @@ struct hfa384x { struct { atomic_t done; u8 count; - struct hfa384x_ChInfoResult results; + struct hfa384x_ch_info_result results; } channel_info; struct hfa384x_inf_frame *scanresults; -- cgit v1.2.3 From 8f8149de8c8ed370d516b8660f6fd9880bba0be6 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:18 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_HScanResultSub Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- drivers/staging/wlan-ng/prism2mgmt.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index c5b52088338a..46855feeb548 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -694,7 +694,7 @@ struct hfa384x_ch_info_result { } __packed; /*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ -struct hfa384x_HScanResultSub { +struct hfa384x_hscan_result_sub { u16 chid; u16 anl; u16 sl; @@ -710,7 +710,7 @@ struct hfa384x_HScanResultSub { struct hfa384x_HScanResult { u16 nresult; u16 rsvd; - struct hfa384x_HScanResultSub result[HFA384x_HSCANRESULT_MAX]; + struct hfa384x_hscan_result_sub result[HFA384x_HSCANRESULT_MAX]; } __packed; /*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/ diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 3a56308332cc..f63704a54073 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -373,7 +373,7 @@ int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp) int result = 0; struct p80211msg_dot11req_scan_results *req; struct hfa384x *hw = wlandev->priv; - struct hfa384x_HScanResultSub *item = NULL; + struct hfa384x_hscan_result_sub *item = NULL; int count; -- cgit v1.2.3 From 0e2ce9adcaa9005aa22ffbf86d19adbdbc5c0574 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:19 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_HScanResult Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 46855feeb548..e5b72dce447d 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -707,7 +707,7 @@ struct hfa384x_hscan_result_sub { u16 atim; } __packed; -struct hfa384x_HScanResult { +struct hfa384x_hscan_result { u16 nresult; u16 rsvd; struct hfa384x_hscan_result_sub result[HFA384x_HSCANRESULT_MAX]; @@ -766,7 +766,7 @@ union hfa384x_infodata { struct hfa384x_comm_tallies_32 commtallies32; struct hfa384x_scan_result scanresult; struct hfa384x_ch_info_result chinforesult; - struct hfa384x_HScanResult hscanresult; + struct hfa384x_hscan_result hscanresult; struct hfa384x_LinkStatus linkstatus; struct hfa384x_assoc_status assocstatus; struct hfa384x_AuthRequest authreq; -- cgit v1.2.3 From 7190f3f1cf735364ced6dc5f72a894418b7c360d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:20 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_LinkStatus Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index e5b72dce447d..2c08f8b85f38 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -723,7 +723,7 @@ struct hfa384x_hscan_result { #define HFA384x_LINK_AP_INRANGE ((u16)5) #define HFA384x_LINK_ASSOCFAIL ((u16)6) -struct hfa384x_LinkStatus { +struct hfa384x_link_status { u16 linkstatus; } __packed; @@ -767,7 +767,7 @@ union hfa384x_infodata { struct hfa384x_scan_result scanresult; struct hfa384x_ch_info_result chinforesult; struct hfa384x_hscan_result hscanresult; - struct hfa384x_LinkStatus linkstatus; + struct hfa384x_link_status linkstatus; struct hfa384x_assoc_status assocstatus; struct hfa384x_AuthRequest authreq; struct hfa384x_PSUserCount psusercnt; -- cgit v1.2.3 From b8f55192ab1c22b4e310185e9288d7dca886d81a Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:21 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_AuthRequest Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 2c08f8b85f38..c81ca9396aee 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -744,7 +744,7 @@ struct hfa384x_assoc_status { /*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/ -struct hfa384x_AuthRequest { +struct hfa384x_auth_request { u8 sta_addr[ETH_ALEN]; u16 algorithm; } __packed; @@ -769,7 +769,7 @@ union hfa384x_infodata { struct hfa384x_hscan_result hscanresult; struct hfa384x_link_status linkstatus; struct hfa384x_assoc_status assocstatus; - struct hfa384x_AuthRequest authreq; + struct hfa384x_auth_request authreq; struct hfa384x_PSUserCount psusercnt; struct hfa384x_KeyIDChanged keyidchanged; } __packed; -- cgit v1.2.3 From 0c3b2bd7b7cca7426fc206e9609d226d56d321d3 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:22 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_PSUserCount Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index c81ca9396aee..f989ce2056f0 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -751,7 +751,7 @@ struct hfa384x_auth_request { /*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/ -struct hfa384x_PSUserCount { +struct hfa384x_ps_user_count { u16 usercnt; } __packed; @@ -770,7 +770,7 @@ union hfa384x_infodata { struct hfa384x_link_status linkstatus; struct hfa384x_assoc_status assocstatus; struct hfa384x_auth_request authreq; - struct hfa384x_PSUserCount psusercnt; + struct hfa384x_ps_user_count psusercnt; struct hfa384x_KeyIDChanged keyidchanged; } __packed; -- cgit v1.2.3 From ab42187a17db55c053f20eee3c888dc129b815a3 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:59:23 +0200 Subject: staging: wlan-ng: avoid CamelCase: hfa384x_KeyIDChanged Replace CamelCase struct name with underscores to comply with the standard kernel coding style. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index f989ce2056f0..01945a93bac3 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -755,7 +755,7 @@ struct hfa384x_ps_user_count { u16 usercnt; } __packed; -struct hfa384x_KeyIDChanged { +struct hfa384x_key_id_changed { u8 sta_addr[ETH_ALEN]; u16 keyid; } __packed; @@ -771,7 +771,7 @@ union hfa384x_infodata { struct hfa384x_assoc_status assocstatus; struct hfa384x_auth_request authreq; struct hfa384x_ps_user_count psusercnt; - struct hfa384x_KeyIDChanged keyidchanged; + struct hfa384x_key_id_changed keyidchanged; } __packed; struct hfa384x_inf_frame { -- cgit v1.2.3 From e0e6964805c6427f2c07b5a52820c0163de74010 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Wed, 19 Oct 2016 17:51:30 +0200 Subject: staging: wlan-ng: Replace data type declaration with variable of same type in prism2mgmt.c sizeof(var) instead of sizeof(struct XXX) is preferred. It also fix the following checkpatch.pl script warning: WARNING: line over 80 characters Fix this two in prism2mgmt.c file. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index f63704a54073..16fb2d3e0f51 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -293,7 +293,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) result = hfa384x_drvr_setconfig(hw, HFA384x_RID_HOSTSCAN, &scanreq, - sizeof(struct hfa384x_host_scan_request_data)); + sizeof(scanreq)); if (result) { netdev_err(wlandev->netdev, "setconfig(SCANREQUEST) failed. result=%d\n", -- cgit v1.2.3 From f0208b7155bc6e395c09652290a16b66e77442f3 Mon Sep 17 00:00:00 2001 From: Cathal Mullaney Date: Wed, 19 Oct 2016 22:43:25 +0100 Subject: staging: unisys: visorbus: visorchannel: Refactor locking code to be statically deterministic. This patch makes locking in visorchannel_signalempty statically deterministic. As a result this patch fixes the sparse warning: Context imbalance in 'visorchannel_signalempty' - different lock contexts for basic block. The logic of the locking code doesn't change but the layout of the original code is "frowned upon" according to mails on sparse context checking. Refactoring removes the warning and makes the code more readable. Signed-off-by: Cathal Mullaney Tested-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchannel.c | 30 ++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index a1381eb81674..a41115733a50 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -300,22 +300,30 @@ EXPORT_SYMBOL_GPL(visorchannel_signalremove); * Return: boolean indicating whether any messages in the designated * channel/queue are present */ + +static bool +queue_empty(struct visorchannel *channel, u32 queue) +{ + struct signal_queue_header sig_hdr; + + if (sig_read_header(channel, queue, &sig_hdr)) + return true; + + return (sig_hdr.head == sig_hdr.tail); +} + bool visorchannel_signalempty(struct visorchannel *channel, u32 queue) { - unsigned long flags = 0; - struct signal_queue_header sig_hdr; - bool rc = false; + bool rc; + unsigned long flags; - if (channel->needs_lock) - spin_lock_irqsave(&channel->remove_lock, flags); + if (!channel->needs_lock) + return queue_empty(channel, queue); - if (sig_read_header(channel, queue, &sig_hdr)) - rc = true; - if (sig_hdr.head == sig_hdr.tail) - rc = true; - if (channel->needs_lock) - spin_unlock_irqrestore(&channel->remove_lock, flags); + spin_lock_irqsave(&channel->remove_lock, flags); + rc = queue_empty(channel, queue); + spin_unlock_irqrestore(&channel->remove_lock, flags); return rc; } -- cgit v1.2.3 From 31b15fe6262a62a116c2347419ad39c56b25b3d7 Mon Sep 17 00:00:00 2001 From: Binoy Jayan Date: Thu, 20 Oct 2016 15:06:30 +0530 Subject: staging: wilc1000: Remove unused function wilc_lock_timeout Semaphore are going away in the future, so remove the unused function wilc_lock_timeout which calls a semaphore api but has no users. Signed-off-by: Binoy Jayan Reviewed-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 11 ----------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - 2 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 42bb86bdb7c2..82c602ba3289 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -220,17 +220,6 @@ static void deinit_irq(struct net_device *dev) } } -int wilc_lock_timeout(struct wilc *nic, void *vp, u32 timeout) -{ - /* FIXME: replace with mutex_lock or wait_for_completion */ - int error = -1; - - if (vp) - error = down_timeout(vp, - msecs_to_jiffies(timeout)); - return error; -} - void wilc_mac_indicate(struct wilc *wilc, int flag) { int status; diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index ec6b1674cf38..d431673bc46c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -225,7 +225,6 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif); void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); void wilc_mac_indicate(struct wilc *wilc, int flag); -int wilc_lock_timeout(struct wilc *wilc, void *, u32 timeout); void wilc_netdev_cleanup(struct wilc *wilc); int wilc_netdev_init(struct wilc **wilc, struct device *, int io_type, int gpio, const struct wilc_hif_func *ops); -- cgit v1.2.3 From 6d408e0b94061d7d38b66175cb4698bbe2423815 Mon Sep 17 00:00:00 2001 From: Maninder Singh Date: Thu, 20 Oct 2016 18:17:03 +0530 Subject: Staging: xgifb: Fix NULL pointer comparison warning Replace direct comparisons to NULL i.e. 'x == NULL' with '!x'. This problem was detected by checkpatch. Signed-off-by: Maninder Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 0c78491ff5a1..89bd4dd6e8a5 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -518,7 +518,7 @@ static void XGIfb_search_crt2type(const char *name) { int i = 0; - if (name == NULL) + if (!name) return; while (XGI_crt2type[i].type_no != -1) { @@ -589,7 +589,7 @@ static void XGIfb_search_tvstd(const char *name) { int i = 0; - if (name == NULL) + if (!name) return; while (XGI_tvtype[i].type_no != -1) { -- cgit v1.2.3 From 2ce7b194c6d084db25e1b7b01584e2c384e126f2 Mon Sep 17 00:00:00 2001 From: Nadim Almas Date: Fri, 21 Oct 2016 21:59:05 +0530 Subject: Staging:vt6656:main_usb: fix Block comments should align the * on each line Block comments should align the * on each line as reported by checkpatch.pl Signed-off-by: Nadim Almas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index fe84da363fbd..50d02d9aa535 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -326,9 +326,9 @@ static int vnt_init_registers(struct vnt_private *priv) priv->current_net_addr); /* - * set BB and packet type at the same time - * set Short Slot Time, xIFS, and RSPINF - */ + * set BB and packet type at the same time + * set Short Slot Time, xIFS, and RSPINF + */ if (priv->bb_type == BB_TYPE_11A) priv->short_slot_time = true; else -- cgit v1.2.3 From 57935a3f8729243783f609551561eeac319b7ae7 Mon Sep 17 00:00:00 2001 From: Alex Briskin Date: Sat, 22 Oct 2016 14:34:28 +0300 Subject: staging:r8188eu: Remove space before comma Trivial style fix to remove unnecessary errors in checkpatch.pl Signed-off-by: Alex Briskin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index edc6b528a7af..0ce7db723a5d 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -488,8 +488,8 @@ void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool Auto } if (bIn24G) { DBG_88E("======= Path %d, Channel %d =======\n", 0, ch); - DBG_88E("Index24G_CCK_Base[%d][%d] = 0x%x\n", 0, ch , pHalData->Index24G_CCK_Base[0][ch]); - DBG_88E("Index24G_BW40_Base[%d][%d] = 0x%x\n", 0, ch , pHalData->Index24G_BW40_Base[0][ch]); + DBG_88E("Index24G_CCK_Base[%d][%d] = 0x%x\n", 0, ch, pHalData->Index24G_CCK_Base[0][ch]); + DBG_88E("Index24G_BW40_Base[%d][%d] = 0x%x\n", 0, ch, pHalData->Index24G_BW40_Base[0][ch]); } } for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { -- cgit v1.2.3 From f5016082f63d42f109b4c8405291e481805d4828 Mon Sep 17 00:00:00 2001 From: "Eric S. Stone" Date: Sat, 22 Oct 2016 19:51:29 -0700 Subject: staging: sm750fb: restructure multi-line comments to follow CodingStyle Eliminates all checkpatch.pl BLOCK_COMMENT_STYLE warnings in sm750fb, and coincidentally eliminates some line-length (80) warnings. Signed-off-by: Eric S. Stone Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750.h | 22 ++++++------ drivers/staging/sm750fb/ddk750_chip.c | 39 ++++++++++++-------- drivers/staging/sm750fb/ddk750_chip.h | 61 +++++++++++++++++++------------- drivers/staging/sm750fb/ddk750_display.h | 30 ++++++++++------ drivers/staging/sm750fb/ddk750_hwi2c.c | 9 +++-- drivers/staging/sm750fb/ddk750_mode.c | 25 +++++++------ drivers/staging/sm750fb/ddk750_sii164.c | 3 +- drivers/staging/sm750fb/ddk750_swi2c.c | 27 +++++++------- drivers/staging/sm750fb/ddk750_swi2c.h | 24 ++++++------- drivers/staging/sm750fb/sm750.h | 6 ++-- drivers/staging/sm750fb/sm750_accel.c | 40 +++++++++++++-------- drivers/staging/sm750fb/sm750_hw.c | 25 ++++++++----- 12 files changed, 184 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750.h b/drivers/staging/sm750fb/ddk750.h index 05669114c4b1..734010324a8f 100644 --- a/drivers/staging/sm750fb/ddk750.h +++ b/drivers/staging/sm750fb/ddk750.h @@ -1,16 +1,16 @@ +/* + * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) + * + * All rights are reserved. Reproduction or in part is prohibited + * without the written consent of the copyright owner. + * + * RegSC.h --- SM718 SDK + * This file contains the definitions for the System Configuration registers. + */ + #ifndef DDK750_H__ #define DDK750_H__ -/******************************************************************* -* -* Copyright (c) 2007 by Silicon Motion, Inc. (SMI) -* -* All rights are reserved. Reproduction or in part is prohibited -* without the written consent of the copyright owner. -* -* RegSC.h --- SM718 SDK -* This file contains the definitions for the System Configuration registers. -* -*******************************************************************/ + #include "ddk750_reg.h" #include "ddk750_mode.h" #include "ddk750_chip.h" diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index a127eb2b4cbc..c8c14eeeb3c7 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -62,17 +62,18 @@ static void set_chip_clock(unsigned int frequency) if (frequency) { /* - * Set up PLL, a structure to hold the value to be set in clocks. - */ + * Set up PLL structure to hold the value to be set in clocks. + */ pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */ pll.clockType = MXCLK_PLL; /* - * Call calc_pll_value() to fill the other fields of PLL structure. - * Sometime, the chip cannot set up the exact clock - * required by the User. - * Return value of calc_pll_value gives the actual possible clock. - */ + * Call calc_pll_value() to fill the other fields of the PLL + * structure. Sometimes, the chip cannot set up the exact + * clock required by the User. + * Return value of calc_pll_value gives the actual possible + * clock. + */ ulActualMxClk = calc_pll_value(frequency, &pll); /* Master Clock Control: MXCLK_PLL */ @@ -84,7 +85,8 @@ static void set_memory_clock(unsigned int frequency) { unsigned int reg, divisor; - /* Cheok_0509: For SM750LE, the memory clock is fixed. + /* + * Cheok_0509: For SM750LE, the memory clock is fixed. * Nothing to set. */ if (sm750_get_chip_type() == SM750LE) @@ -135,14 +137,16 @@ static void set_master_clock(unsigned int frequency) { unsigned int reg, divisor; - /* Cheok_0509: For SM750LE, the memory clock is fixed. + /* + * Cheok_0509: For SM750LE, the memory clock is fixed. * Nothing to set. */ if (sm750_get_chip_type() == SM750LE) return; if (frequency) { - /* Set the frequency to the maximum frequency + /* + * Set the frequency to the maximum frequency * that the SM750 engine can run, which is about 190 MHz. */ if (frequency > MHz(190)) @@ -241,7 +245,8 @@ int ddk750_init_hw(struct initchip_param *pInitParam) set_master_clock(MHz(pInitParam->masterClock)); - /* Reset the memory controller. + /* + * Reset the memory controller. * If the memory controller is not reset in SM750, * the system might hang when sw accesses the memory. * The memory should be resetted after changing the MXCLK. @@ -306,7 +311,8 @@ int ddk750_init_hw(struct initchip_param *pInitParam) */ unsigned int calc_pll_value(unsigned int request_orig, struct pll_value *pll) { - /* as sm750 register definition, + /* + * as sm750 register definition, * N located in 2,15 and M located in 1,255 */ int N, M, X, d; @@ -318,7 +324,8 @@ unsigned int calc_pll_value(unsigned int request_orig, struct pll_value *pll) int max_d = 6; if (sm750_get_chip_type() == SM750LE) { - /* SM750LE don't have + /* + * SM750LE don't have * programmable PLL and M/N values to work on. * Just return the requested clock. */ @@ -330,14 +337,16 @@ unsigned int calc_pll_value(unsigned int request_orig, struct pll_value *pll) request = request_orig / 1000; input = pll->inputFreq / 1000; - /* for MXCLK register, + /* + * for MXCLK register, * no POD provided, so need be treated differently */ if (pll->clockType == MXCLK_PLL) max_d = 3; for (N = 15; N > 1; N--) { - /* RN will not exceed maximum long + /* + * RN will not exceed maximum long * if @request <= 285 MHZ (for 32bit cpu) */ RN = N * request; diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h index 3b731b48bfb5..5eee29dfc4b3 100644 --- a/drivers/staging/sm750fb/ddk750_chip.h +++ b/drivers/staging/sm750fb/ddk750_chip.h @@ -46,31 +46,42 @@ struct pll_value { /* input struct to initChipParam() function */ struct initchip_param { - unsigned short powerMode; /* Use power mode 0 or 1 */ - unsigned short chipClock; /** - * Speed of main chip clock in MHz unit - * 0 = keep the current clock setting - * Others = the new main chip clock - */ - unsigned short memClock; /** - * Speed of memory clock in MHz unit - * 0 = keep the current clock setting - * Others = the new memory clock - */ - unsigned short masterClock; /** - * Speed of master clock in MHz unit - * 0 = keep the current clock setting - * Others = the new master clock - */ - unsigned short setAllEngOff; /** - * 0 = leave all engine state untouched. - * 1 = make sure they are off: 2D, Overlay, - * video alpha, alpha, hardware cursors - */ - unsigned char resetMemory; /** - * 0 = Do not reset the memory controller - * 1 = Reset the memory controller - */ + /* Use power mode 0 or 1 */ + unsigned short powerMode; + + /* + * Speed of main chip clock in MHz unit + * 0 = keep the current clock setting + * Others = the new main chip clock + */ + unsigned short chipClock; + + /* + * Speed of memory clock in MHz unit + * 0 = keep the current clock setting + * Others = the new memory clock + */ + unsigned short memClock; + + /* + * Speed of master clock in MHz unit + * 0 = keep the current clock setting + * Others = the new master clock + */ + unsigned short masterClock; + + /* + * 0 = leave all engine state untouched. + * 1 = make sure they are off: 2D, Overlay, + * video alpha, alpha, hardware cursors + */ + unsigned short setAllEngOff; + + /* + * 0 = Do not reset the memory controller + * 1 = Reset the memory controller + */ + unsigned char resetMemory; /* More initialization parameter can be added if needed */ }; diff --git a/drivers/staging/sm750fb/ddk750_display.h b/drivers/staging/sm750fb/ddk750_display.h index e3fde428c52b..8abca88f089e 100644 --- a/drivers/staging/sm750fb/ddk750_display.h +++ b/drivers/staging/sm750fb/ddk750_display.h @@ -1,7 +1,8 @@ #ifndef DDK750_DISPLAY_H__ #define DDK750_DISPLAY_H__ -/* panel path select +/* + * panel path select * 80000[29:28] */ @@ -12,7 +13,8 @@ #define PNL_2_SEC ((2 << PNL_2_OFFSET) | PNL_2_USAGE) -/* primary timing & plane enable bit +/* + * primary timing & plane enable bit * 1: 80000[8] & 80000[2] on * 0: both off */ @@ -23,7 +25,8 @@ #define PRI_TP_OFF ((0x0 << PRI_TP_OFFSET) | PRI_TP_USAGE) -/* panel sequency status +/* + * panel sequency status * 80000[27:24] */ #define PNL_SEQ_OFFSET 6 @@ -32,7 +35,8 @@ #define PNL_SEQ_ON (BIT(PNL_SEQ_OFFSET) | PNL_SEQ_USAGE) #define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET) | PNL_SEQ_USAGE) -/* dual digital output +/* + * dual digital output * 80000[19] */ #define DUAL_TFT_OFFSET 8 @@ -41,7 +45,8 @@ #define DUAL_TFT_ON (BIT(DUAL_TFT_OFFSET) | DUAL_TFT_USAGE) #define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET) | DUAL_TFT_USAGE) -/* secondary timing & plane enable bit +/* + * secondary timing & plane enable bit * 1:80200[8] & 80200[2] on * 0: both off */ @@ -51,7 +56,8 @@ #define SEC_TP_ON ((0x1 << SEC_TP_OFFSET) | SEC_TP_USAGE) #define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET) | SEC_TP_USAGE) -/* crt path select +/* + * crt path select * 80200[19:18] */ #define CRT_2_OFFSET 2 @@ -61,7 +67,8 @@ #define CRT_2_SEC ((0x2 << CRT_2_OFFSET) | CRT_2_USAGE) -/* DAC affect both DVI and DSUB +/* + * DAC affect both DVI and DSUB * 4[20] */ #define DAC_OFFSET 7 @@ -70,7 +77,8 @@ #define DAC_ON ((0x0 << DAC_OFFSET) | DAC_USAGE) #define DAC_OFF ((0x1 << DAC_OFFSET) | DAC_USAGE) -/* DPMS only affect D-SUB head +/* + * DPMS only affect D-SUB head * 0[31:30] */ #define DPMS_OFFSET 9 @@ -81,7 +89,8 @@ -/* LCD1 means panel path TFT1 & panel path DVI (so enable DAC) +/* + * LCD1 means panel path TFT1 & panel path DVI (so enable DAC) * CRT means crt path DSUB */ typedef enum _disp_output_t { @@ -89,7 +98,8 @@ typedef enum _disp_output_t { do_LCD1_SEC = PNL_2_SEC | SEC_TP_ON | PNL_SEQ_ON | DAC_ON, do_LCD2_PRI = CRT_2_PRI | PRI_TP_ON | DUAL_TFT_ON, do_LCD2_SEC = CRT_2_SEC | SEC_TP_ON | DUAL_TFT_ON, - /* do_DSUB_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON|DAC_ON, + /* + * do_DSUB_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON|DAC_ON, * do_DSUB_SEC = CRT_2_SEC | SEC_TP_ON | DPMS_ON|DAC_ON, */ do_CRT_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON | DAC_ON, diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index 4ce0fbeba55e..b60bedf6a854 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -20,7 +20,8 @@ unsigned char bus_speed_mode value |= (GPIO_MUX_30 | GPIO_MUX_31); POKE32(GPIO_MUX, value); - /* Enable Hardware I2C power. + /* + * Enable Hardware I2C power. * TODO: Check if we need to enable GPIO power? */ enableI2C(1); @@ -92,7 +93,8 @@ static unsigned int hw_i2c_write_data( /* Set the Device Address */ POKE32(I2C_SLAVE_ADDRESS, addr & ~0x01); - /* Write data. + /* + * Write data. * Note: * Only 16 byte can be accessed per i2c start instruction. */ @@ -158,7 +160,8 @@ static unsigned int hw_i2c_read_data( /* Set the Device Address */ POKE32(I2C_SLAVE_ADDRESS, addr | 0x01); - /* Read data and save them to the buffer. + /* + * Read data and save them to the buffer. * Note: * Only 16 byte can be accessed per i2c start instruction. */ diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index b6af6f31e21c..47d224e542c3 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -3,7 +3,8 @@ #include "ddk750_mode.h" #include "ddk750_chip.h" -/* SM750LE only: +/* + * SM750LE only: * This function takes care extra registers and bit fields required to set * up a mode in SM750LE * @@ -18,7 +19,8 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, x = pModeParam->horizontal_display_end; y = pModeParam->vertical_display_end; - /* SM750LE has to set up the top-left and bottom-right + /* + * SM750LE has to set up the top-left and bottom-right * registers as well. * Note that normal SM750/SM718 only use those two register for * auto-centering mode. @@ -30,7 +32,8 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, CRT_AUTO_CENTERING_BR_BOTTOM_MASK) | ((x - 1) & CRT_AUTO_CENTERING_BR_RIGHT_MASK)); - /* Assume common fields in dispControl have been properly set before + /* + * Assume common fields in dispControl have been properly set before * calling this function. * This function only sets the extra fields in dispControl. */ @@ -176,14 +179,14 @@ static int programModeRegisters(mode_parameter_t *pModeParam, DISPLAY_CTRL_HSYNC_PHASE | DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE); - /* May a hardware bug or just my test chip (not confirmed). - * PANEL_DISPLAY_CTRL register seems requiring few writes - * before a value can be successfully written in. - * Added some masks to mask out the reserved bits. - * Note: This problem happens by design. The hardware will wait for the - * next vertical sync to turn on/off the plane. - */ - + /* + * May a hardware bug or just my test chip (not confirmed). + * PANEL_DISPLAY_CTRL register seems requiring few writes + * before a value can be successfully written in. + * Added some masks to mask out the reserved bits. + * Note: This problem happens by design. The hardware will wait + * for the next vertical sync to turn on/off the plane. + */ POKE32(PANEL_DISPLAY_CTRL, tmp | reg); while ((PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) != diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c index 99a8683e6383..259006ace219 100644 --- a/drivers/staging/sm750fb/ddk750_sii164.c +++ b/drivers/staging/sm750fb/ddk750_sii164.c @@ -173,7 +173,8 @@ long sii164InitChip( i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config); - /* De-skew enabled with default 111b value. + /* + * De-skew enabled with default 111b value. * This fixes some artifacts problem in some mode on board 2.2. * Somehow this fix does not affect board 2.1. */ diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c index 78bfba0e03e8..7fce55df5fa6 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.c +++ b/drivers/staging/sm750fb/ddk750_swi2c.c @@ -1,21 +1,20 @@ -/******************************************************************* -* -* Copyright (c) 2007 by Silicon Motion, Inc. (SMI) -* -* All rights are reserved. Reproduction or in part is prohibited -* without the written consent of the copyright owner. -* -* swi2c.c --- SM750/SM718 DDK -* This file contains the source code for I2C using software -* implementation. -* -*******************************************************************/ +/* + * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) + * + * All rights are reserved. Reproduction or in part is prohibited + * without the written consent of the copyright owner. + * + * swi2c.c --- SM750/SM718 DDK + * This file contains the source code for I2C using software + * implementation. + */ + #include "ddk750_chip.h" #include "ddk750_reg.h" #include "ddk750_swi2c.h" #include "ddk750_power.h" -/******************************************************************* +/* * I2C Software Master Driver: * =========================== * Each i2c cycle is split into 4 sections. Each of these section marks @@ -51,7 +50,7 @@ * SCL | L | | H | | * ---------------+---+---+---+---+ * - ******************************************************************/ + */ /* GPIO pins used for this I2C. It ranges from 0 to 63. */ static unsigned char sw_i2c_clk_gpio = DEFAULT_I2C_SCL; diff --git a/drivers/staging/sm750fb/ddk750_swi2c.h b/drivers/staging/sm750fb/ddk750_swi2c.h index b53629cda095..5a9466efc7bd 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.h +++ b/drivers/staging/sm750fb/ddk750_swi2c.h @@ -1,15 +1,15 @@ -/******************************************************************* -* -* Copyright (c) 2007 by Silicon Motion, Inc. (SMI) -* -* All rights are reserved. Reproduction or in part is prohibited -* without the written consent of the copyright owner. -* -* swi2c.h --- SM750/SM718 DDK -* This file contains the definitions for i2c using software -* implementation. -* -*******************************************************************/ +/* + * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) + * + * All rights are reserved. Reproduction or in part is prohibited + * without the written consent of the copyright owner. + * + * swi2c.h --- SM750/SM718 DDK + * This file contains the definitions for i2c using software + * implementation. + * + */ + #ifndef _SWI2C_H_ #define _SWI2C_H_ diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h index ff31c5c9cc6f..28f4b9b4f95f 100644 --- a/drivers/staging/sm750fb/sm750.h +++ b/drivers/staging/sm750fb/sm750.h @@ -146,14 +146,16 @@ struct lynxfb_crtc { struct lynxfb_output { int dpms; int paths; - /* which paths(s) this output stands for,for sm750: + /* + * which paths(s) this output stands for,for sm750: * paths=1:means output for panel paths * paths=2:means output for crt paths * paths=3:means output for both panel and crt paths */ int *channel; - /* which channel these outputs linked with,for sm750: + /* + * which channel these outputs linked with,for sm750: * *channel=0 means primary channel * *channel=1 means secondary channel * output->channel ==> &crtc->channel diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c index 38adae6b5d83..2e9c94142274 100644 --- a/drivers/staging/sm750fb/sm750_accel.c +++ b/drivers/staging/sm750fb/sm750_accel.c @@ -65,7 +65,8 @@ void hw_de_init(struct lynx_accel *accel) write_dpr(accel, DE_CONTROL, read_dpr(accel, DE_CONTROL) & ~clr); } -/* set2dformat only be called from setmode functions +/* + * set2dformat only be called from setmode functions * but if you need dual framebuffer driver,need call set2dformat * every time you use 2d function */ @@ -90,7 +91,8 @@ int hw_fillrect(struct lynx_accel *accel, u32 deCtrl; if (accel->de_wait() != 0) { - /* int time wait and always busy,seems hardware + /* + * int time wait and always busy,seems hardware * got something error */ pr_debug("De engine always busy\n"); @@ -213,25 +215,29 @@ unsigned int rop2) /* ROP value */ opSign = (-1); } - /* Note: + /* + * Note: * DE_FOREGROUND are DE_BACKGROUND are don't care. * DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS * are set by set deSetTransparency(). */ - /* 2D Source Base. + /* + * 2D Source Base. * It is an address offset (128 bit aligned) * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */ - /* 2D Destination Base. + /* + * 2D Destination Base. * It is an address offset (128 bit aligned) * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */ - /* Program pitch (distance between the 1st points of two adjacent lines). + /* + * Program pitch (distance between the 1st points of two adjacent lines). * Note that input pitch is BYTE value, but the 2D Pitch register uses * pixel values. Need Byte to pixel conversion. */ @@ -240,7 +246,8 @@ unsigned int rop2) /* ROP value */ DE_PITCH_DESTINATION_MASK) | (sPitch / Bpp & DE_PITCH_SOURCE_MASK)); /* dpr10 */ - /* Screen Window width in Pixels. + /* + * Screen Window width in Pixels. * 2D engine uses this value to calculate the linear address in frame buffer * for a given point. */ @@ -316,7 +323,8 @@ int hw_imageblit(struct lynx_accel *accel, if (accel->de_wait() != 0) return -1; - /* 2D Source Base. + /* + * 2D Source Base. * Use 0 for HOST Blt. */ write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0); @@ -326,16 +334,19 @@ int hw_imageblit(struct lynx_accel *accel, * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); - /* Program pitch (distance between the 1st points of two adjacent lines). - * Note that input pitch is BYTE value, but the 2D Pitch register uses - * pixel values. Need Byte to pixel conversion. - */ + + /* + * Program pitch (distance between the 1st points of two adjacent + * lines). Note that input pitch is BYTE value, but the 2D Pitch + * register uses pixel values. Need Byte to pixel conversion. + */ write_dpr(accel, DE_PITCH, ((dPitch / bytePerPixel << DE_PITCH_DESTINATION_SHIFT) & DE_PITCH_DESTINATION_MASK) | (dPitch / bytePerPixel & DE_PITCH_SOURCE_MASK)); /* dpr10 */ - /* Screen Window width in Pixels. + /* + * Screen Window width in Pixels. * 2D engine uses this value to calculate the linear address * in frame buffer for a given point. */ @@ -344,7 +355,8 @@ int hw_imageblit(struct lynx_accel *accel, DE_WINDOW_WIDTH_DST_MASK) | (dPitch / bytePerPixel & DE_WINDOW_WIDTH_SRC_MASK)); - /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, + /* + * Note: For 2D Source in Host Write, only X_K1_MONO field is needed, * and Y_K2 field is not used. * For mono bitmap, use startBit for X_K1. */ diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index d5508ba0e5ff..d2da7a0ef5f0 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -36,7 +36,8 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start); - /* reserve the vidreg space of smi adaptor + /* + * reserve the vidreg space of smi adaptor * if you do this, you need to add release region code * in lynxfb_remove, or memory will not be mapped again * successfully @@ -65,7 +66,8 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) sm750_set_chip_type(sm750_dev->devid, sm750_dev->revid); sm750_dev->vidmem_start = pci_resource_start(pdev, 0); - /* don't use pdev_resource[x].end - resource[x].start to + /* + * don't use pdev_resource[x].end - resource[x].start to * calculate the resource size, it's only the maximum available * size but not the actual size, using * @ddk750_get_vm_size function can be safe. @@ -144,7 +146,8 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) } POKE32(PANEL_DISPLAY_CTRL, val); } else { - /* for 750LE, no DVI chip initialization + /* + * for 750LE, no DVI chip initialization * makes Monitor no signal * * Set up GPIO for software I2C to program DVI chip in the @@ -152,13 +155,15 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) */ sm750_sw_i2c_init(0, 1); - /* Customer may NOT use CH7301 DVI chip, which has to be + /* + * Customer may NOT use CH7301 DVI chip, which has to be * initialized differently. */ if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) { - /* The following register values for CH7301 are from - * Chrontel app note and our experiment. - */ + /* + * The following register values for CH7301 are from + * Chrontel app note and our experiment. + */ pr_info("yes,CH7301 DVI chip found\n"); sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16); sm750_sw_i2c_write_reg(0xec, 0x21, 0x9); @@ -311,7 +316,8 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK); reg = var->xres * (var->bits_per_pixel >> 3); - /* crtc->channel is not equal to par->index on numeric, + /* + * crtc->channel is not equal to par->index on numeric, * be aware of that */ reg = ALIGN(reg, crtc->line_pad); @@ -345,7 +351,8 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, /* not implemented now */ POKE32(CRT_FB_ADDRESS, crtc->oScreen); reg = var->xres * (var->bits_per_pixel >> 3); - /* crtc->channel is not equal to par->index on numeric, + /* + * crtc->channel is not equal to par->index on numeric, * be aware of that */ reg = ALIGN(reg, crtc->line_pad) << CRT_FB_WIDTH_WIDTH_SHIFT; -- cgit v1.2.3 From 3e9e3bb7f784308b948bdd199beeca37642dfa32 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Kerbrat Date: Wed, 19 Oct 2016 20:49:49 +0200 Subject: staging: rtl8188eu: os_dep: remove empty lines Remove unnecessary empty lines (issue found by checkpatch) Signed-off-by: Pierre-Yves Kerbrat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/osdep_service.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 7cd2655f27fe..2b9ae441b88e 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -12,8 +12,6 @@ * more details. * ******************************************************************************/ - - #define _OSDEP_SERVICE_C_ #include -- cgit v1.2.3 From ec0f85f8ccdd83ec1d93d560db8bafa51d2d735d Mon Sep 17 00:00:00 2001 From: Pierre-Yves Kerbrat Date: Wed, 19 Oct 2016 20:49:50 +0200 Subject: staging: rtl8188eu: os_dep: fix block comment alignment issue Fix coding style issue in block comment in osdep_service.c found by checkpatch tool Signed-off-by: Pierre-Yves Kerbrat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/osdep_service.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 2b9ae441b88e..534e58ecc510 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -22,9 +22,10 @@ #include /* -* Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE -* @return: one of RTW_STATUS_CODE -*/ + * Translate the OS dependent @param error_code to OS independent + * RTW_STATUS_CODE + * @return: one of RTW_STATUS_CODE + */ inline int RTW_STATUS_CODE(int error_code) { if (error_code >= 0) -- cgit v1.2.3 From 3ddaf64835d473e86494f2c8dc776f1962c86808 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Kerbrat Date: Wed, 19 Oct 2016 20:49:51 +0200 Subject: staging: rtl8188eu: os_dep: fix missing spaces around operators Fix missing space around operators in rtw_alloc2d function in osdep_service.c Signed-off-by: Pierre-Yves Kerbrat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/osdep_service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 534e58ecc510..df5f44000cf0 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -42,14 +42,14 @@ void *rtw_malloc2d(int h, int w, int size) { int j; - void **a = kzalloc(h*sizeof(void *) + h*w*size, GFP_KERNEL); + void **a = kzalloc(h * sizeof(void *) + h * w * size, GFP_KERNEL); if (!a) { pr_info("%s: alloc memory fail!\n", __func__); return NULL; } for (j = 0; j < h; j++) - a[j] = ((char *)(a+h)) + j*w*size; + a[j] = ((char *)(a + h)) + j * w * size; return a; } -- cgit v1.2.3 From 1050394cd7f0223adfb8ae6faf11a30bd0b7b5f3 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Kerbrat Date: Wed, 19 Oct 2016 20:49:52 +0200 Subject: staging: rtl8188eu: os_dep: remove unnecessary parentheses Remove parentheses in _rtw_init_queue to fix checkpatch warning Signed-off-by: Pierre-Yves Kerbrat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/osdep_service.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index df5f44000cf0..c036fe7d1df8 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -54,10 +54,10 @@ void *rtw_malloc2d(int h, int w, int size) return a; } -void _rtw_init_queue(struct __queue *pqueue) +void _rtw_init_queue(struct __queue *pqueue) { - INIT_LIST_HEAD(&(pqueue->queue)); - spin_lock_init(&(pqueue->lock)); + INIT_LIST_HEAD(&pqueue->queue); + spin_lock_init(&pqueue->lock); } struct net_device *rtw_alloc_etherdev_with_old_priv(void *old_priv) -- cgit v1.2.3 From fb26718744c46f34fb9b8cdf5f73030548978b49 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Kerbrat Date: Wed, 19 Oct 2016 20:49:53 +0200 Subject: staging: rtl8188eu: os_dep: remove unnecessary alloc fail message Remove redundant alloc fail message This patch fixes the warning found by checkpatch Signed-off-by: Pierre-Yves Kerbrat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/osdep_service.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index c036fe7d1df8..6ff836f481da 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -43,14 +43,12 @@ void *rtw_malloc2d(int h, int w, int size) int j; void **a = kzalloc(h * sizeof(void *) + h * w * size, GFP_KERNEL); - if (!a) { - pr_info("%s: alloc memory fail!\n", __func__); - return NULL; - } + if (!a) + goto out; for (j = 0; j < h; j++) a[j] = ((char *)(a + h)) + j * w * size; - +out: return a; } -- cgit v1.2.3 From b8fd7220752fe10f6df3755ce40aa0a9acd2c6be Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 24 Oct 2016 17:22:01 +0200 Subject: staging: iio: ad5933: avoid uninitialized variable in error case The ad5933_i2c_read function returns an error code to indicate whether it could read data or not. However ad5933_work() ignores this return code and just accesses the data unconditionally, which gets detected by gcc as a possible bug: drivers/staging/iio/impedance-analyzer/ad5933.c: In function 'ad5933_work': drivers/staging/iio/impedance-analyzer/ad5933.c:649:16: warning: 'status' may be used uninitialized in this function [-Wmaybe-uninitialized] This adds minimal error handling so we only evaluate the data if it was correctly read. Link: https://patchwork.kernel.org/patch/8110281/ Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/impedance-analyzer/ad5933.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 5eecf1cb1028..3892a7470410 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -655,6 +655,7 @@ static void ad5933_work(struct work_struct *work) __be16 buf[2]; int val[2]; unsigned char status; + int ret; mutex_lock(&indio_dev->mlock); if (st->state == AD5933_CTRL_INIT_START_FREQ) { @@ -662,19 +663,22 @@ static void ad5933_work(struct work_struct *work) ad5933_cmd(st, AD5933_CTRL_START_SWEEP); st->state = AD5933_CTRL_START_SWEEP; schedule_delayed_work(&st->work, st->poll_time_jiffies); - mutex_unlock(&indio_dev->mlock); - return; + goto out; } - ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); + ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); + if (ret) + goto out; if (status & AD5933_STAT_DATA_VALID) { int scan_count = bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength); - ad5933_i2c_read(st->client, + ret = ad5933_i2c_read(st->client, test_bit(1, indio_dev->active_scan_mask) ? AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA, scan_count * 2, (u8 *)buf); + if (ret) + goto out; if (scan_count == 2) { val[0] = be16_to_cpu(buf[0]); @@ -686,8 +690,7 @@ static void ad5933_work(struct work_struct *work) } else { /* no data available - try again later */ schedule_delayed_work(&st->work, st->poll_time_jiffies); - mutex_unlock(&indio_dev->mlock); - return; + goto out; } if (status & AD5933_STAT_SWEEP_DONE) { @@ -700,7 +703,7 @@ static void ad5933_work(struct work_struct *work) ad5933_cmd(st, AD5933_CTRL_INC_FREQ); schedule_delayed_work(&st->work, st->poll_time_jiffies); } - +out: mutex_unlock(&indio_dev->mlock); } -- cgit v1.2.3 From 54dc7ed37d390f75e31a323defe30424835490c7 Mon Sep 17 00:00:00 2001 From: Leo Sperling Date: Sun, 23 Oct 2016 14:02:23 +0200 Subject: Staging: media: davinci_vpfe: fix indentation issue in vpfe_video.c This is a patch to the vpfe_video.c file that fixes an indentation warning reported by checkpatch.pl Signed-off-by: Leo Sperling Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/davinci_vpfe/vpfe_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 8be9f854510f..c34bf4621767 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -1143,8 +1143,8 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb) /* Initialize buffer */ vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage); if (vb2_plane_vaddr(vb, 0) && - vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) - return -EINVAL; + vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) + return -EINVAL; addr = vb2_dma_contig_plane_dma_addr(vb, 0); /* Make sure user addresses are aligned to 32 bytes */ -- cgit v1.2.3 From 3ab7c086d5ec72585ef0158dbc265cb03ddc682a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 25 Aug 2016 18:02:41 +0200 Subject: locking/drm: Kill mutex trickery Poking at lock internals is not cool. Since I'm going to change the implementation this will break, take it out. Tested-by: Jason Low Signed-off-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Chris Wilson Cc: Daniel Vetter Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Rob Clark Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 20 +------------------- drivers/gpu/drm/msm/msm_gem_shrinker.c | 23 +++-------------------- 2 files changed, 4 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 1c237d02f30b..36953757687e 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -35,19 +35,6 @@ #include "i915_drv.h" #include "i915_trace.h" -static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) -{ - if (!mutex_is_locked(mutex)) - return false; - -#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER) - return mutex->owner == task; -#else - /* Since UP may be pre-empted, we cannot assume that we own the lock */ - return false; -#endif -} - static bool any_vma_pinned(struct drm_i915_gem_object *obj) { struct i915_vma *vma; @@ -240,13 +227,8 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv) static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock) { - if (!mutex_trylock(&dev->struct_mutex)) { - if (!mutex_is_locked_by(&dev->struct_mutex, current)) - return false; - + if (!mutex_trylock(&dev->struct_mutex)) *unlock = false; - } else - *unlock = true; return true; } diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 283d2841ba58..6d2e885bd58e 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -18,29 +18,12 @@ #include "msm_drv.h" #include "msm_gem.h" -static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) -{ - if (!mutex_is_locked(mutex)) - return false; - -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES) - return mutex->owner == task; -#else - /* Since UP may be pre-empted, we cannot assume that we own the lock */ - return false; -#endif -} - static bool msm_gem_shrinker_lock(struct drm_device *dev, bool *unlock) { - if (!mutex_trylock(&dev->struct_mutex)) { - if (!mutex_is_locked_by(&dev->struct_mutex, current)) - return false; - *unlock = false; - } else { - *unlock = true; - } + if (!mutex_trylock(&dev->struct_mutex)) + return false; + *unlock = true; return true; } -- cgit v1.2.3 From ee28648cb2b4d4ab5c2eb8199ea86675fe19016b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 29 Sep 2016 22:53:12 +0200 Subject: clk: sunxi-ng: Remove the use of rational computations While the rational library works great, it doesn't really allow us to add more constraints, like the minimum. Remove that in order to be able to deal with the constraints we'll need. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai --- drivers/clk/sunxi-ng/Kconfig | 3 --- drivers/clk/sunxi-ng/ccu_nkm.c | 31 ++++++++++++----------- drivers/clk/sunxi-ng/ccu_nkmp.c | 37 ++++++++++++++-------------- drivers/clk/sunxi-ng/ccu_nm.c | 54 +++++++++++++++++++++++++++++++---------- 4 files changed, 74 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 254d9526c018..1b4c55a53d7a 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -35,17 +35,14 @@ config SUNXI_CCU_NK config SUNXI_CCU_NKM bool - select RATIONAL select SUNXI_CCU_GATE config SUNXI_CCU_NKMP bool - select RATIONAL select SUNXI_CCU_GATE config SUNXI_CCU_NM bool - select RATIONAL select SUNXI_CCU_FRAC select SUNXI_CCU_GATE diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c index 059fdc3b4f96..0b08d000eb38 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.c +++ b/drivers/clk/sunxi-ng/ccu_nkm.c @@ -9,7 +9,6 @@ */ #include -#include #include "ccu_gate.h" #include "ccu_nkm.h" @@ -28,21 +27,21 @@ static void ccu_nkm_find_best(unsigned long parent, unsigned long rate, unsigned long _n, _k, _m; for (_k = 1; _k <= nkm->max_k; _k++) { - unsigned long tmp_rate; - - rational_best_approximation(rate / _k, parent, - nkm->max_n, nkm->max_m, &_n, &_m); - - tmp_rate = parent * _n * _k / _m; - - if (tmp_rate > rate) - continue; - - if ((rate - tmp_rate) < (rate - best_rate)) { - best_rate = tmp_rate; - best_n = _n; - best_k = _k; - best_m = _m; + for (_n = 1; _n <= nkm->max_n; _n++) { + for (_m = 1; _n <= nkm->max_m; _m++) { + unsigned long tmp_rate; + + tmp_rate = parent * _n * _k / _m; + + if (tmp_rate > rate) + continue; + if ((rate - tmp_rate) < (rate - best_rate)) { + best_rate = tmp_rate; + best_n = _n; + best_k = _k; + best_m = _m; + } + } } } diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c index 9769dee99511..fcf67572e55c 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.c +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c @@ -9,7 +9,6 @@ */ #include -#include #include "ccu_gate.h" #include "ccu_nkmp.h" @@ -29,24 +28,24 @@ static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate, unsigned long _n, _k, _m, _p; for (_k = 1; _k <= nkmp->max_k; _k++) { - for (_p = 1; _p <= nkmp->max_p; _p <<= 1) { - unsigned long tmp_rate; - - rational_best_approximation(rate / _k, parent / _p, - nkmp->max_n, nkmp->max_m, - &_n, &_m); - - tmp_rate = parent * _n * _k / (_m * _p); - - if (tmp_rate > rate) - continue; - - if ((rate - tmp_rate) < (rate - best_rate)) { - best_rate = tmp_rate; - best_n = _n; - best_k = _k; - best_m = _m; - best_p = _p; + for (_n = 1; _n <= nkmp->max_n; _n++) { + for (_m = 1; _n <= nkmp->max_m; _m++) { + for (_p = 1; _p <= nkmp->max_p; _p <<= 1) { + unsigned long tmp_rate; + + tmp_rate = parent * _n * _k / (_m * _p); + + if (tmp_rate > rate) + continue; + + if ((rate - tmp_rate) < (rate - best_rate)) { + best_rate = tmp_rate; + best_n = _n; + best_k = _k; + best_m = _m; + best_p = _p; + } + } } } } diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index b61bdd8c7a7f..c6d652289320 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -9,12 +9,42 @@ */ #include -#include #include "ccu_frac.h" #include "ccu_gate.h" #include "ccu_nm.h" +struct _ccu_nm { + unsigned long n, max_n; + unsigned long m, max_m; +}; + +static void ccu_nm_find_best(unsigned long parent, unsigned long rate, + struct _ccu_nm *nm) +{ + unsigned long best_rate = 0; + unsigned long best_n = 0, best_m = 0; + unsigned long _n, _m; + + for (_n = 1; _n <= nm->max_n; _n++) { + for (_m = 1; _n <= nm->max_m; _m++) { + unsigned long tmp_rate = parent * _n / _m; + + if (tmp_rate > rate) + continue; + + if ((rate - tmp_rate) < (rate - best_rate)) { + best_rate = tmp_rate; + best_n = _n; + best_m = _m; + } + } + } + + nm->n = best_n; + nm->m = best_m; +} + static void ccu_nm_disable(struct clk_hw *hw) { struct ccu_nm *nm = hw_to_ccu_nm(hw); @@ -61,24 +91,22 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { struct ccu_nm *nm = hw_to_ccu_nm(hw); - unsigned long max_n, max_m; - unsigned long n, m; + struct _ccu_nm _nm; - max_n = 1 << nm->n.width; - max_m = nm->m.max ?: 1 << nm->m.width; + _nm.max_n = 1 << nm->n.width; + _nm.max_m = nm->m.max ?: 1 << nm->m.width; - rational_best_approximation(rate, *parent_rate, max_n, max_m, &n, &m); + ccu_nm_find_best(*parent_rate, rate, &_nm); - return *parent_rate * n / m; + return *parent_rate * _nm.n / _nm.m; } static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct ccu_nm *nm = hw_to_ccu_nm(hw); + struct _ccu_nm _nm; unsigned long flags; - unsigned long max_n, max_m; - unsigned long n, m; u32 reg; if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) @@ -86,10 +114,10 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, else ccu_frac_helper_disable(&nm->common, &nm->frac); - max_n = 1 << nm->n.width; - max_m = nm->m.max ?: 1 << nm->m.width; + _nm.max_n = 1 << nm->n.width; + _nm.max_m = nm->m.max ?: 1 << nm->m.width; - rational_best_approximation(rate, parent_rate, max_n, max_m, &n, &m); + ccu_nm_find_best(parent_rate, rate, &_nm); spin_lock_irqsave(nm->common.lock, flags); @@ -97,7 +125,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift); reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift); - writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift), + writel(reg | ((_nm.m - 1) << nm->m.shift) | ((_nm.n - 1) << nm->n.shift), nm->common.base + nm->common.reg); spin_unlock_irqrestore(nm->common.lock, flags); -- cgit v1.2.3 From b8302c7267dedaeeb1bf38143f099defbf16dce8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 29 Sep 2016 23:50:21 +0200 Subject: clk: sunxi-ng: Finish to convert to structures for arguments Some clocks still use an explicit list of arguments, which make it a bit more tedious to add new parameters. Convert those over to a structure pointer argument to add as many arguments as possible without having to many noise in our patches, or a very long list of arguments. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai --- drivers/clk/sunxi-ng/ccu_mult.c | 28 ++++++++++++++++++++-------- drivers/clk/sunxi-ng/ccu_nk.c | 39 ++++++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c index 010e9424691d..32a1964439a2 100644 --- a/drivers/clk/sunxi-ng/ccu_mult.c +++ b/drivers/clk/sunxi-ng/ccu_mult.c @@ -13,10 +13,20 @@ #include "ccu_gate.h" #include "ccu_mult.h" +struct _ccu_mult { + unsigned long mult, max; +}; + static void ccu_mult_find_best(unsigned long parent, unsigned long rate, - unsigned int max_n, unsigned int *n) + struct _ccu_mult *mult) { - *n = rate / parent; + int _mult; + + _mult = rate / parent; + if (_mult > mult->max) + _mult = mult->max; + + mult->mult = _mult; } static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux, @@ -25,11 +35,12 @@ static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux, void *data) { struct ccu_mult *cm = data; - unsigned int n; + struct _ccu_mult _cm; - ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n); + _cm.max = 1 << cm->mult.width; + ccu_mult_find_best(parent_rate, rate, &_cm); - return parent_rate * n; + return parent_rate * _cm.mult; } static void ccu_mult_disable(struct clk_hw *hw) @@ -83,21 +94,22 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct ccu_mult *cm = hw_to_ccu_mult(hw); + struct _ccu_mult _cm; unsigned long flags; - unsigned int n; u32 reg; ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1, &parent_rate); - ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n); + _cm.max = 1 << cm->mult.width; + ccu_mult_find_best(parent_rate, rate, &_cm); spin_lock_irqsave(cm->common.lock, flags); reg = readl(cm->common.base + cm->common.reg); reg &= ~GENMASK(cm->mult.width + cm->mult.shift - 1, cm->mult.shift); - writel(reg | ((n - 1) << cm->mult.shift), + writel(reg | ((_cm.mult - 1) << cm->mult.shift), cm->common.base + cm->common.reg); spin_unlock_irqrestore(cm->common.lock, flags); diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c index d6fafb397489..e7e2e75618ef 100644 --- a/drivers/clk/sunxi-ng/ccu_nk.c +++ b/drivers/clk/sunxi-ng/ccu_nk.c @@ -9,21 +9,24 @@ */ #include -#include #include "ccu_gate.h" #include "ccu_nk.h" +struct _ccu_nk { + unsigned long n, max_n; + unsigned long k, max_k; +}; + static void ccu_nk_find_best(unsigned long parent, unsigned long rate, - unsigned int max_n, unsigned int max_k, - unsigned int *n, unsigned int *k) + struct _ccu_nk *nk) { unsigned long best_rate = 0; unsigned int best_k = 0, best_n = 0; unsigned int _k, _n; - for (_k = 1; _k <= max_k; _k++) { - for (_n = 1; _n <= max_n; _n++) { + for (_k = 1; _k <= nk->max_k; _k++) { + for (_n = 1; _n <= nk->max_n; _n++) { unsigned long tmp_rate = parent * _n * _k; if (tmp_rate > rate) @@ -37,8 +40,8 @@ static void ccu_nk_find_best(unsigned long parent, unsigned long rate, } } - *k = best_k; - *n = best_n; + nk->k = best_k; + nk->n = best_n; } static void ccu_nk_disable(struct clk_hw *hw) @@ -89,16 +92,17 @@ static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { struct ccu_nk *nk = hw_to_ccu_nk(hw); - unsigned int n, k; + struct _ccu_nk _nk; if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) rate *= nk->fixed_post_div; - ccu_nk_find_best(*parent_rate, rate, - 1 << nk->n.width, 1 << nk->k.width, - &n, &k); + _nk.max_n = 1 << nk->n.width; + _nk.max_k = 1 << nk->k.width; + + ccu_nk_find_best(*parent_rate, rate, &_nk); + rate = *parent_rate * _nk.n * _nk.k; - rate = *parent_rate * n * k; if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) rate = rate / nk->fixed_post_div; @@ -110,15 +114,16 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate, { struct ccu_nk *nk = hw_to_ccu_nk(hw); unsigned long flags; - unsigned int n, k; + struct _ccu_nk _nk; u32 reg; if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) rate = rate * nk->fixed_post_div; - ccu_nk_find_best(parent_rate, rate, - 1 << nk->n.width, 1 << nk->k.width, - &n, &k); + _nk.max_n = 1 << nk->n.width; + _nk.max_k = 1 << nk->k.width; + + ccu_nk_find_best(parent_rate, rate, &_nk); spin_lock_irqsave(nk->common.lock, flags); @@ -126,7 +131,7 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate, reg &= ~GENMASK(nk->n.width + nk->n.shift - 1, nk->n.shift); reg &= ~GENMASK(nk->k.width + nk->k.shift - 1, nk->k.shift); - writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift), + writel(reg | ((_nk.k - 1) << nk->k.shift) | ((_nk.n - 1) << nk->n.shift), nk->common.base + nk->common.reg); spin_unlock_irqrestore(nk->common.lock, flags); -- cgit v1.2.3 From 6e0d50daa97f4bf9706e343b4f71171e88921209 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 29 Sep 2016 22:57:26 +0200 Subject: clk: sunxi-ng: Add minimums for all the relevant structures and clocks Modify the current clocks we have to be able to specify the minimum for each clocks we support, just like we support the max. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai --- drivers/clk/sunxi-ng/ccu_mult.c | 7 ++++++- drivers/clk/sunxi-ng/ccu_nk.c | 12 ++++++++---- drivers/clk/sunxi-ng/ccu_nkm.c | 18 ++++++++++++------ drivers/clk/sunxi-ng/ccu_nkmp.c | 24 ++++++++++++++++-------- drivers/clk/sunxi-ng/ccu_nm.c | 12 ++++++++---- 5 files changed, 50 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c index 32a1964439a2..6a02ffee5386 100644 --- a/drivers/clk/sunxi-ng/ccu_mult.c +++ b/drivers/clk/sunxi-ng/ccu_mult.c @@ -14,7 +14,7 @@ #include "ccu_mult.h" struct _ccu_mult { - unsigned long mult, max; + unsigned long mult, min, max; }; static void ccu_mult_find_best(unsigned long parent, unsigned long rate, @@ -23,6 +23,9 @@ static void ccu_mult_find_best(unsigned long parent, unsigned long rate, int _mult; _mult = rate / parent; + if (_mult < mult->min) + _mult = mult->min; + if (_mult > mult->max) _mult = mult->max; @@ -37,6 +40,7 @@ static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux, struct ccu_mult *cm = data; struct _ccu_mult _cm; + _cm.min = 1; _cm.max = 1 << cm->mult.width; ccu_mult_find_best(parent_rate, rate, &_cm); @@ -101,6 +105,7 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate, ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1, &parent_rate); + _cm.min = 1; _cm.max = 1 << cm->mult.width; ccu_mult_find_best(parent_rate, rate, &_cm); diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c index e7e2e75618ef..a42d870ba0ef 100644 --- a/drivers/clk/sunxi-ng/ccu_nk.c +++ b/drivers/clk/sunxi-ng/ccu_nk.c @@ -14,8 +14,8 @@ #include "ccu_nk.h" struct _ccu_nk { - unsigned long n, max_n; - unsigned long k, max_k; + unsigned long n, min_n, max_n; + unsigned long k, min_k, max_k; }; static void ccu_nk_find_best(unsigned long parent, unsigned long rate, @@ -25,8 +25,8 @@ static void ccu_nk_find_best(unsigned long parent, unsigned long rate, unsigned int best_k = 0, best_n = 0; unsigned int _k, _n; - for (_k = 1; _k <= nk->max_k; _k++) { - for (_n = 1; _n <= nk->max_n; _n++) { + for (_k = nk->min_k; _k <= nk->max_k; _k++) { + for (_n = nk->min_n; _n <= nk->max_n; _n++) { unsigned long tmp_rate = parent * _n * _k; if (tmp_rate > rate) @@ -97,7 +97,9 @@ static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate, if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) rate *= nk->fixed_post_div; + _nk.min_n = 1; _nk.max_n = 1 << nk->n.width; + _nk.min_k = 1; _nk.max_k = 1 << nk->k.width; ccu_nk_find_best(*parent_rate, rate, &_nk); @@ -120,7 +122,9 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate, if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) rate = rate * nk->fixed_post_div; + _nk.min_n = 1; _nk.max_n = 1 << nk->n.width; + _nk.min_k = 1; _nk.max_k = 1 << nk->k.width; ccu_nk_find_best(parent_rate, rate, &_nk); diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c index 0b08d000eb38..42177320930d 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.c +++ b/drivers/clk/sunxi-ng/ccu_nkm.c @@ -14,9 +14,9 @@ #include "ccu_nkm.h" struct _ccu_nkm { - unsigned long n, max_n; - unsigned long k, max_k; - unsigned long m, max_m; + unsigned long n, min_n, max_n; + unsigned long k, min_k, max_k; + unsigned long m, min_m, max_m; }; static void ccu_nkm_find_best(unsigned long parent, unsigned long rate, @@ -26,9 +26,9 @@ static void ccu_nkm_find_best(unsigned long parent, unsigned long rate, unsigned long best_n = 0, best_k = 0, best_m = 0; unsigned long _n, _k, _m; - for (_k = 1; _k <= nkm->max_k; _k++) { - for (_n = 1; _n <= nkm->max_n; _n++) { - for (_m = 1; _n <= nkm->max_m; _m++) { + for (_k = nkm->min_k; _k <= nkm->max_k; _k++) { + for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { + for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { unsigned long tmp_rate; tmp_rate = parent * _n * _k / _m; @@ -100,8 +100,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, struct ccu_nkm *nkm = data; struct _ccu_nkm _nkm; + _nkm.min_n = 1; _nkm.max_n = 1 << nkm->n.width; + _nkm.min_k = 1; _nkm.max_k = 1 << nkm->k.width; + _nkm.min_m = 1; _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; ccu_nkm_find_best(parent_rate, rate, &_nkm); @@ -126,8 +129,11 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long flags; u32 reg; + _nkm.min_n = 1; _nkm.max_n = 1 << nkm->n.width; + _nkm.min_k = 1; _nkm.max_k = 1 << nkm->k.width; + _nkm.min_m = 1; _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; ccu_nkm_find_best(parent_rate, rate, &_nkm); diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c index fcf67572e55c..67c856e381a8 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.c +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c @@ -14,10 +14,10 @@ #include "ccu_nkmp.h" struct _ccu_nkmp { - unsigned long n, max_n; - unsigned long k, max_k; - unsigned long m, max_m; - unsigned long p, max_p; + unsigned long n, min_n, max_n; + unsigned long k, min_k, max_k; + unsigned long m, min_m, max_m; + unsigned long p, min_p, max_p; }; static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate, @@ -27,10 +27,10 @@ static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate, unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0; unsigned long _n, _k, _m, _p; - for (_k = 1; _k <= nkmp->max_k; _k++) { - for (_n = 1; _n <= nkmp->max_n; _n++) { - for (_m = 1; _n <= nkmp->max_m; _m++) { - for (_p = 1; _p <= nkmp->max_p; _p <<= 1) { + for (_k = nkmp->min_k; _k <= nkmp->max_k; _k++) { + for (_n = nkmp->min_n; _n <= nkmp->max_n; _n++) { + for (_m = nkmp->min_m; _m <= nkmp->max_m; _m++) { + for (_p = nkmp->min_p; _p <= nkmp->max_p; _p <<= 1) { unsigned long tmp_rate; tmp_rate = parent * _n * _k / (_m * _p); @@ -107,9 +107,13 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); struct _ccu_nkmp _nkmp; + _nkmp.min_n = 1; _nkmp.max_n = 1 << nkmp->n.width; + _nkmp.min_k = 1; _nkmp.max_k = 1 << nkmp->k.width; + _nkmp.min_m = 1; _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width; + _nkmp.min_p = 1; _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1); ccu_nkmp_find_best(*parent_rate, rate, &_nkmp); @@ -125,9 +129,13 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long flags; u32 reg; + _nkmp.min_n = 1; _nkmp.max_n = 1 << nkmp->n.width; + _nkmp.min_k = 1; _nkmp.max_k = 1 << nkmp->k.width; + _nkmp.min_m = 1; _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width; + _nkmp.min_p = 1; _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1); ccu_nkmp_find_best(parent_rate, rate, &_nkmp); diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index c6d652289320..1dae4f3ed00d 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -15,8 +15,8 @@ #include "ccu_nm.h" struct _ccu_nm { - unsigned long n, max_n; - unsigned long m, max_m; + unsigned long n, min_n, max_n; + unsigned long m, min_m, max_m; }; static void ccu_nm_find_best(unsigned long parent, unsigned long rate, @@ -26,8 +26,8 @@ static void ccu_nm_find_best(unsigned long parent, unsigned long rate, unsigned long best_n = 0, best_m = 0; unsigned long _n, _m; - for (_n = 1; _n <= nm->max_n; _n++) { - for (_m = 1; _n <= nm->max_m; _m++) { + for (_n = nm->min_n; _n <= nm->max_n; _n++) { + for (_m = nm->min_m; _m <= nm->max_m; _m++) { unsigned long tmp_rate = parent * _n / _m; if (tmp_rate > rate) @@ -93,7 +93,9 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, struct ccu_nm *nm = hw_to_ccu_nm(hw); struct _ccu_nm _nm; + _nm.min_n = 1; _nm.max_n = 1 << nm->n.width; + _nm.min_m = 1; _nm.max_m = nm->m.max ?: 1 << nm->m.width; ccu_nm_find_best(*parent_rate, rate, &_nm); @@ -114,7 +116,9 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, else ccu_frac_helper_disable(&nm->common, &nm->frac); + _nm.min_n = 1; _nm.max_n = 1 << nm->n.width; + _nm.min_m = 1; _nm.max_m = nm->m.max ?: 1 << nm->m.width; ccu_nm_find_best(parent_rate, rate, &_nm); -- cgit v1.2.3 From 2beaa601c849e72683a2dd0fe6fd77763f19f051 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Sep 2016 22:16:51 +0200 Subject: clk: sunxi-ng: Implement minimum for multipliers Allow the CCU drivers to specify a multiplier for their clocks. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai --- drivers/clk/sunxi-ng/ccu_mult.c | 2 +- drivers/clk/sunxi-ng/ccu_mult.h | 13 +++++++++---- drivers/clk/sunxi-ng/ccu_nk.c | 8 ++++---- drivers/clk/sunxi-ng/ccu_nkm.c | 8 ++++---- drivers/clk/sunxi-ng/ccu_nkmp.c | 4 ++-- drivers/clk/sunxi-ng/ccu_nm.c | 2 +- 6 files changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c index 6a02ffee5386..678b6cb49f01 100644 --- a/drivers/clk/sunxi-ng/ccu_mult.c +++ b/drivers/clk/sunxi-ng/ccu_mult.c @@ -105,7 +105,7 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate, ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1, &parent_rate); - _cm.min = 1; + _cm.min = cm->mult.min; _cm.max = 1 << cm->mult.width; ccu_mult_find_best(parent_rate, rate, &_cm); diff --git a/drivers/clk/sunxi-ng/ccu_mult.h b/drivers/clk/sunxi-ng/ccu_mult.h index 113780b7558e..c1a2134bdc71 100644 --- a/drivers/clk/sunxi-ng/ccu_mult.h +++ b/drivers/clk/sunxi-ng/ccu_mult.h @@ -7,14 +7,19 @@ struct ccu_mult_internal { u8 shift; u8 width; + u8 min; }; -#define _SUNXI_CCU_MULT(_shift, _width) \ - { \ - .shift = _shift, \ - .width = _width, \ +#define _SUNXI_CCU_MULT_MIN(_shift, _width, _min) \ + { \ + .shift = _shift, \ + .width = _width, \ + .min = _min, \ } +#define _SUNXI_CCU_MULT(_shift, _width) \ + _SUNXI_CCU_MULT_MIN(_shift, _width, 1) + struct ccu_mult { u32 enable; diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c index a42d870ba0ef..eaf0fdf78d2b 100644 --- a/drivers/clk/sunxi-ng/ccu_nk.c +++ b/drivers/clk/sunxi-ng/ccu_nk.c @@ -97,9 +97,9 @@ static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate, if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) rate *= nk->fixed_post_div; - _nk.min_n = 1; + _nk.min_n = nk->n.min; _nk.max_n = 1 << nk->n.width; - _nk.min_k = 1; + _nk.min_k = nk->k.min; _nk.max_k = 1 << nk->k.width; ccu_nk_find_best(*parent_rate, rate, &_nk); @@ -122,9 +122,9 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate, if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) rate = rate * nk->fixed_post_div; - _nk.min_n = 1; + _nk.min_n = nk->n.min; _nk.max_n = 1 << nk->n.width; - _nk.min_k = 1; + _nk.min_k = nk->k.min; _nk.max_k = 1 << nk->k.width; ccu_nk_find_best(parent_rate, rate, &_nk); diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c index 42177320930d..9b840a47a94d 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.c +++ b/drivers/clk/sunxi-ng/ccu_nkm.c @@ -100,9 +100,9 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, struct ccu_nkm *nkm = data; struct _ccu_nkm _nkm; - _nkm.min_n = 1; + _nkm.min_n = nkm->n.min; _nkm.max_n = 1 << nkm->n.width; - _nkm.min_k = 1; + _nkm.min_k = nkm->k.min; _nkm.max_k = 1 << nkm->k.width; _nkm.min_m = 1; _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; @@ -129,9 +129,9 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long flags; u32 reg; - _nkm.min_n = 1; + _nkm.min_n = nkm->n.min; _nkm.max_n = 1 << nkm->n.width; - _nkm.min_k = 1; + _nkm.min_k = nkm->k.min; _nkm.max_k = 1 << nkm->k.width; _nkm.min_m = 1; _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c index 67c856e381a8..684c42da3ebb 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.c +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c @@ -107,9 +107,9 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); struct _ccu_nkmp _nkmp; - _nkmp.min_n = 1; + _nkmp.min_n = nkmp->n.min; _nkmp.max_n = 1 << nkmp->n.width; - _nkmp.min_k = 1; + _nkmp.min_k = nkmp->k.min; _nkmp.max_k = 1 << nkmp->k.width; _nkmp.min_m = 1; _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width; diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index 1dae4f3ed00d..c9f3b6c982f0 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -93,7 +93,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, struct ccu_nm *nm = hw_to_ccu_nm(hw); struct _ccu_nm _nm; - _nm.min_n = 1; + _nm.min_n = nm->n.min; _nm.max_n = 1 << nm->n.width; _nm.min_m = 1; _nm.max_m = nm->m.max ?: 1 << nm->m.width; -- cgit v1.2.3 From f85522c207ce395fc9c1f6b80a47f211d00914b0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 24 Oct 2016 14:49:13 +0000 Subject: gpio: altera-a10sr: Drop unnecessary gpiochip_remove It's not necessary to unregister gpio_chip which registered with devm_gpiochip_add_data(). Also get rid of useless altr_a10sr_gpio_remove(). Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/gpio/gpio-altera-a10sr.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index 8274f98e3bee..9e1a138fed53 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -110,15 +110,6 @@ static int altr_a10sr_gpio_probe(struct platform_device *pdev) return 0; } -static int altr_a10sr_gpio_remove(struct platform_device *pdev) -{ - struct altr_a10sr_gpio *gpio = platform_get_drvdata(pdev); - - gpiochip_remove(&gpio->gp); - - return 0; -} - static const struct of_device_id altr_a10sr_gpio_of_match[] = { { .compatible = "altr,a10sr-gpio" }, { }, @@ -127,7 +118,6 @@ MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match); static struct platform_driver altr_a10sr_gpio_driver = { .probe = altr_a10sr_gpio_probe, - .remove = altr_a10sr_gpio_remove, .driver = { .name = "altr_a10sr_gpio", .of_match_table = of_match_ptr(altr_a10sr_gpio_of_match), -- cgit v1.2.3 From de867c20b94b6d52a0b10cb02f10a1f475abf7f5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 25 Oct 2016 13:16:02 +0100 Subject: drm/i915: Include the kernel uptime in the error state As well as knowing when the error occurred, it is more interesting to me to know how long after booting the error occurred, and for good measure record the time since last hw initialisation. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: http://patchwork.freedesktop.org/patch/msgid/20161025121602.1457-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ drivers/gpu/drm/i915/i915_gem.c | 2 ++ drivers/gpu/drm/i915/i915_gpu_error.c | 12 ++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b4cb1f0f0632..7a621c74254e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -746,6 +746,8 @@ struct intel_display_error_state; struct drm_i915_error_state { struct kref ref; struct timeval time; + struct timeval boottime; + struct timeval uptime; struct drm_i915_private *i915; @@ -2099,6 +2101,8 @@ struct drm_i915_private { * off the idle_work. */ struct delayed_work idle_work; + + ktime_t last_init_time; } gt; /* perform PHY state sanity checks? */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0e26ee96856e..9361c7b54a7f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4470,6 +4470,8 @@ i915_gem_init_hw(struct drm_device *dev) enum intel_engine_id id; int ret; + dev_priv->gt.last_init_time = ktime_get(); + /* Double layer security blanket, see i915_gem_init() */ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 48fece3bb7a9..d5feace8de0d 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -546,9 +546,13 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } err_printf(m, "%s\n", error->error_msg); - err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, - error->time.tv_usec); err_printf(m, "Kernel: " UTS_RELEASE "\n"); + err_printf(m, "Time: %ld s %ld us\n", + error->time.tv_sec, error->time.tv_usec); + err_printf(m, "Boottime: %ld s %ld us\n", + error->boottime.tv_sec, error->boottime.tv_usec); + err_printf(m, "Uptime: %ld s %ld us\n", + error->uptime.tv_sec, error->uptime.tv_usec); err_print_capabilities(m, &error->device_info); max_hangcheck_score = 0; for (i = 0; i < ARRAY_SIZE(error->engine); i++) { @@ -1549,6 +1553,10 @@ static int capture(void *data) i915_gem_capture_guc_log_buffer(error->i915, error); do_gettimeofday(&error->time); + error->boottime = ktime_to_timeval(ktime_get_boottime()); + error->uptime = + ktime_to_timeval(ktime_sub(ktime_get(), + error->i915->gt.last_init_time)); error->overlay = intel_overlay_capture_error_state(error->i915); error->display = intel_display_capture_error_state(error->i915); -- cgit v1.2.3 From f54d1867005c3323f5d8ad83eed823e84226c429 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 25 Oct 2016 13:00:45 +0100 Subject: dma-buf: Rename struct fence to dma_fence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I plan to usurp the short name of struct fence for a core kernel struct, and so I need to rename the specialised fence/timeline for DMA operations to make room. A consensus was reached in https://lists.freedesktop.org/archives/dri-devel/2016-July/113083.html that making clear this fence applies to DMA operations was a good thing. Since then the patch has grown a bit as usage increases, so hopefully it remains a good thing! (v2...: rebase, rerun spatch) v3: Compile on msm, spotted a manual fixup that I broke. v4: Try again for msm, sorry Daniel coccinelle script: @@ @@ - struct fence + struct dma_fence @@ @@ - struct fence_ops + struct dma_fence_ops @@ @@ - struct fence_cb + struct dma_fence_cb @@ @@ - struct fence_array + struct dma_fence_array @@ @@ - enum fence_flag_bits + enum dma_fence_flag_bits @@ @@ ( - fence_init + dma_fence_init | - fence_release + dma_fence_release | - fence_free + dma_fence_free | - fence_get + dma_fence_get | - fence_get_rcu + dma_fence_get_rcu | - fence_put + dma_fence_put | - fence_signal + dma_fence_signal | - fence_signal_locked + dma_fence_signal_locked | - fence_default_wait + dma_fence_default_wait | - fence_add_callback + dma_fence_add_callback | - fence_remove_callback + dma_fence_remove_callback | - fence_enable_sw_signaling + dma_fence_enable_sw_signaling | - fence_is_signaled_locked + dma_fence_is_signaled_locked | - fence_is_signaled + dma_fence_is_signaled | - fence_is_later + dma_fence_is_later | - fence_later + dma_fence_later | - fence_wait_timeout + dma_fence_wait_timeout | - fence_wait_any_timeout + dma_fence_wait_any_timeout | - fence_wait + dma_fence_wait | - fence_context_alloc + dma_fence_context_alloc | - fence_array_create + dma_fence_array_create | - to_fence_array + to_dma_fence_array | - fence_is_array + dma_fence_is_array | - trace_fence_emit + trace_dma_fence_emit | - FENCE_TRACE + DMA_FENCE_TRACE | - FENCE_WARN + DMA_FENCE_WARN | - FENCE_ERR + DMA_FENCE_ERR ) ( ... ) Signed-off-by: Chris Wilson Reviewed-by: Gustavo Padovan Acked-by: Sumit Semwal Acked-by: Christian König Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161025120045.28839-1-chris@chris-wilson.co.uk --- Documentation/sync_file.txt | 14 +- drivers/base/Kconfig | 6 +- drivers/dma-buf/Kconfig | 2 +- drivers/dma-buf/Makefile | 2 +- drivers/dma-buf/dma-buf.c | 28 +- drivers/dma-buf/dma-fence-array.c | 146 +++++++ drivers/dma-buf/dma-fence.c | 537 ++++++++++++++++++++++++ drivers/dma-buf/fence-array.c | 145 ------- drivers/dma-buf/fence.c | 534 ----------------------- drivers/dma-buf/reservation.c | 94 +++-- drivers/dma-buf/seqno-fence.c | 18 +- drivers/dma-buf/sw_sync.c | 48 +-- drivers/dma-buf/sync_debug.c | 13 +- drivers/dma-buf/sync_debug.h | 9 +- drivers/dma-buf/sync_file.c | 63 +-- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 54 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 16 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 22 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 16 +- drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 58 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 22 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 24 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 48 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_test.c | 12 +- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 10 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 26 +- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 26 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 79 ++-- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 12 +- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 6 +- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/si_dma.c | 6 +- drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h | 4 +- drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 67 +-- drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 26 +- drivers/gpu/drm/amd/scheduler/sched_fence.c | 48 ++- drivers/gpu/drm/drm_atomic.c | 2 +- drivers/gpu/drm/drm_atomic_helper.c | 8 +- drivers/gpu/drm/drm_fops.c | 6 +- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 6 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 46 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 4 +- drivers/gpu/drm/i915/i915_gem_request.c | 32 +- drivers/gpu/drm/i915/i915_gem_request.h | 18 +- drivers/gpu/drm/i915/i915_sw_fence.c | 41 +- drivers/gpu/drm/i915/i915_sw_fence.h | 8 +- drivers/gpu/drm/i915/i915_trace.h | 2 +- drivers/gpu/drm/i915/intel_breadcrumbs.c | 4 +- drivers/gpu/drm/i915/intel_engine_cs.c | 2 +- drivers/gpu/drm/msm/msm_drv.h | 2 +- drivers/gpu/drm/msm/msm_fence.c | 28 +- drivers/gpu/drm/msm/msm_fence.h | 2 +- drivers/gpu/drm/msm/msm_gem.c | 14 +- drivers/gpu/drm/msm/msm_gem.h | 2 +- drivers/gpu/drm/msm/msm_gem_submit.c | 8 +- drivers/gpu/drm/msm/msm_gpu.c | 2 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 6 +- drivers/gpu/drm/nouveau/nouveau_fence.c | 80 ++-- drivers/gpu/drm/nouveau/nouveau_fence.h | 6 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +- drivers/gpu/drm/nouveau/nv04_fence.c | 2 +- drivers/gpu/drm/nouveau/nv10_fence.c | 2 +- drivers/gpu/drm/nouveau/nv17_fence.c | 2 +- drivers/gpu/drm/nouveau/nv50_fence.c | 2 +- drivers/gpu/drm/nouveau/nv84_fence.c | 2 +- drivers/gpu/drm/qxl/qxl_drv.h | 4 +- drivers/gpu/drm/qxl/qxl_release.c | 35 +- drivers/gpu/drm/radeon/radeon.h | 10 +- drivers/gpu/drm/radeon/radeon_device.c | 2 +- drivers/gpu/drm/radeon/radeon_display.c | 8 +- drivers/gpu/drm/radeon/radeon_fence.c | 56 +-- drivers/gpu/drm/radeon/radeon_sync.c | 6 +- drivers/gpu/drm/radeon/radeon_uvd.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 24 +- drivers/gpu/drm/ttm/ttm_bo_util.c | 22 +- drivers/gpu/drm/ttm/ttm_bo_vm.c | 8 +- drivers/gpu/drm/ttm/ttm_execbuf_util.c | 3 +- drivers/gpu/drm/vgem/vgem_fence.c | 53 +-- drivers/gpu/drm/virtio/virtgpu_drv.h | 2 +- drivers/gpu/drm/virtio/virtgpu_fence.c | 26 +- drivers/gpu/drm/virtio/virtgpu_ioctl.c | 12 +- drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 44 +- drivers/gpu/drm/vmwgfx/vmwgfx_fence.h | 8 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 2 +- include/drm/drmP.h | 4 +- include/drm/drm_crtc.h | 2 +- include/drm/drm_plane.h | 2 +- include/drm/ttm/ttm_bo_api.h | 2 +- include/drm/ttm/ttm_bo_driver.h | 6 +- include/drm/ttm/ttm_execbuf_util.h | 2 +- include/linux/dma-buf.h | 4 +- include/linux/dma-fence-array.h | 86 ++++ include/linux/dma-fence.h | 437 +++++++++++++++++++ include/linux/fence-array.h | 84 ---- include/linux/fence.h | 424 ------------------- include/linux/reservation.h | 28 +- include/linux/seqno-fence.h | 20 +- include/linux/sync_file.h | 14 +- include/trace/events/dma_fence.h | 128 ++++++ include/trace/events/fence.h | 128 ------ 114 files changed, 2206 insertions(+), 2168 deletions(-) create mode 100644 drivers/dma-buf/dma-fence-array.c create mode 100644 drivers/dma-buf/dma-fence.c delete mode 100644 drivers/dma-buf/fence-array.c delete mode 100644 drivers/dma-buf/fence.c create mode 100644 include/linux/dma-fence-array.h create mode 100644 include/linux/dma-fence.h delete mode 100644 include/linux/fence-array.h delete mode 100644 include/linux/fence.h create mode 100644 include/trace/events/dma_fence.h delete mode 100644 include/trace/events/fence.h (limited to 'drivers') diff --git a/Documentation/sync_file.txt b/Documentation/sync_file.txt index b63a68531afd..269681a6faec 100644 --- a/Documentation/sync_file.txt +++ b/Documentation/sync_file.txt @@ -6,7 +6,7 @@ This document serves as a guide for device drivers writers on what the sync_file API is, and how drivers can support it. Sync file is the carrier of -the fences(struct fence) that are needed to synchronize between drivers or +the fences(struct dma_fence) that are needed to synchronize between drivers or across process boundaries. The sync_file API is meant to be used to send and receive fence information @@ -32,9 +32,9 @@ in-fences and out-fences Sync files can go either to or from userspace. When a sync_file is sent from the driver to userspace we call the fences it contains 'out-fences'. They are related to a buffer that the driver is processing or is going to process, so -the driver creates an out-fence to be able to notify, through fence_signal(), -when it has finished using (or processing) that buffer. Out-fences are fences -that the driver creates. +the driver creates an out-fence to be able to notify, through +dma_fence_signal(), when it has finished using (or processing) that buffer. +Out-fences are fences that the driver creates. On the other hand if the driver receives fence(s) through a sync_file from userspace we call these fence(s) 'in-fences'. Receiveing in-fences means that @@ -47,7 +47,7 @@ Creating Sync Files When a driver needs to send an out-fence userspace it creates a sync_file. Interface: - struct sync_file *sync_file_create(struct fence *fence); + struct sync_file *sync_file_create(struct dma_fence *fence); The caller pass the out-fence and gets back the sync_file. That is just the first step, next it needs to install an fd on sync_file->file. So it gets an @@ -72,11 +72,11 @@ of the Sync File to the kernel. The kernel can then retrieve the fences from it. Interface: - struct fence *sync_file_get_fence(int fd); + struct dma_fence *sync_file_get_fence(int fd); The returned reference is owned by the caller and must be disposed of -afterwards using fence_put(). In case of error, a NULL is returned instead. +afterwards using dma_fence_put(). In case of error, a NULL is returned instead. References: [1] struct sync_file in include/linux/sync_file.h diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index fdf44cac08e6..37bf25c6b4a6 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -248,11 +248,11 @@ config DMA_SHARED_BUFFER APIs extension; the file's descriptor can then be passed on to other driver. -config FENCE_TRACE - bool "Enable verbose FENCE_TRACE messages" +config DMA_FENCE_TRACE + bool "Enable verbose DMA_FENCE_TRACE messages" depends on DMA_SHARED_BUFFER help - Enable the FENCE_TRACE printks. This will add extra + Enable the DMA_FENCE_TRACE printks. This will add extra spam to the console log, but will make it easier to diagnose lockup related problems for dma-buffers shared across multiple devices. diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig index 2585821b24ab..ed3b785bae37 100644 --- a/drivers/dma-buf/Kconfig +++ b/drivers/dma-buf/Kconfig @@ -7,7 +7,7 @@ config SYNC_FILE select DMA_SHARED_BUFFER ---help--- The Sync File Framework adds explicit syncronization via - userspace. It enables send/receive 'struct fence' objects to/from + userspace. It enables send/receive 'struct dma_fence' objects to/from userspace via Sync File fds for synchronization between drivers via userspace components. It has been ported from Android. diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile index 210a10bfad2b..c33bf8863147 100644 --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1,3 +1,3 @@ -obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o +obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o obj-$(CONFIG_SYNC_FILE) += sync_file.o obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index cf04d249a6a4..e72e64484131 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -124,7 +124,7 @@ static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence) return base + offset; } -static void dma_buf_poll_cb(struct fence *fence, struct fence_cb *cb) +static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb) { struct dma_buf_poll_cb_t *dcb = (struct dma_buf_poll_cb_t *)cb; unsigned long flags; @@ -140,7 +140,7 @@ static unsigned int dma_buf_poll(struct file *file, poll_table *poll) struct dma_buf *dmabuf; struct reservation_object *resv; struct reservation_object_list *fobj; - struct fence *fence_excl; + struct dma_fence *fence_excl; unsigned long events; unsigned shared_count, seq; @@ -187,20 +187,20 @@ retry: spin_unlock_irq(&dmabuf->poll.lock); if (events & pevents) { - if (!fence_get_rcu(fence_excl)) { + if (!dma_fence_get_rcu(fence_excl)) { /* force a recheck */ events &= ~pevents; dma_buf_poll_cb(NULL, &dcb->cb); - } else if (!fence_add_callback(fence_excl, &dcb->cb, - dma_buf_poll_cb)) { + } else if (!dma_fence_add_callback(fence_excl, &dcb->cb, + dma_buf_poll_cb)) { events &= ~pevents; - fence_put(fence_excl); + dma_fence_put(fence_excl); } else { /* * No callback queued, wake up any additional * waiters. */ - fence_put(fence_excl); + dma_fence_put(fence_excl); dma_buf_poll_cb(NULL, &dcb->cb); } } @@ -222,9 +222,9 @@ retry: goto out; for (i = 0; i < shared_count; ++i) { - struct fence *fence = rcu_dereference(fobj->shared[i]); + struct dma_fence *fence = rcu_dereference(fobj->shared[i]); - if (!fence_get_rcu(fence)) { + if (!dma_fence_get_rcu(fence)) { /* * fence refcount dropped to zero, this means * that fobj has been freed @@ -235,13 +235,13 @@ retry: dma_buf_poll_cb(NULL, &dcb->cb); break; } - if (!fence_add_callback(fence, &dcb->cb, - dma_buf_poll_cb)) { - fence_put(fence); + if (!dma_fence_add_callback(fence, &dcb->cb, + dma_buf_poll_cb)) { + dma_fence_put(fence); events &= ~POLLOUT; break; } - fence_put(fence); + dma_fence_put(fence); } /* No callback queued, wake up any additional waiters. */ diff --git a/drivers/dma-buf/dma-fence-array.c b/drivers/dma-buf/dma-fence-array.c new file mode 100644 index 000000000000..67eb7c8fb88c --- /dev/null +++ b/drivers/dma-buf/dma-fence-array.c @@ -0,0 +1,146 @@ +/* + * dma-fence-array: aggregate fences to be waited together + * + * Copyright (C) 2016 Collabora Ltd + * Copyright (C) 2016 Advanced Micro Devices, Inc. + * Authors: + * Gustavo Padovan + * Christian König + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +static const char *dma_fence_array_get_driver_name(struct dma_fence *fence) +{ + return "dma_fence_array"; +} + +static const char *dma_fence_array_get_timeline_name(struct dma_fence *fence) +{ + return "unbound"; +} + +static void dma_fence_array_cb_func(struct dma_fence *f, + struct dma_fence_cb *cb) +{ + struct dma_fence_array_cb *array_cb = + container_of(cb, struct dma_fence_array_cb, cb); + struct dma_fence_array *array = array_cb->array; + + if (atomic_dec_and_test(&array->num_pending)) + dma_fence_signal(&array->base); + dma_fence_put(&array->base); +} + +static bool dma_fence_array_enable_signaling(struct dma_fence *fence) +{ + struct dma_fence_array *array = to_dma_fence_array(fence); + struct dma_fence_array_cb *cb = (void *)(&array[1]); + unsigned i; + + for (i = 0; i < array->num_fences; ++i) { + cb[i].array = array; + /* + * As we may report that the fence is signaled before all + * callbacks are complete, we need to take an additional + * reference count on the array so that we do not free it too + * early. The core fence handling will only hold the reference + * until we signal the array as complete (but that is now + * insufficient). + */ + dma_fence_get(&array->base); + if (dma_fence_add_callback(array->fences[i], &cb[i].cb, + dma_fence_array_cb_func)) { + dma_fence_put(&array->base); + if (atomic_dec_and_test(&array->num_pending)) + return false; + } + } + + return true; +} + +static bool dma_fence_array_signaled(struct dma_fence *fence) +{ + struct dma_fence_array *array = to_dma_fence_array(fence); + + return atomic_read(&array->num_pending) <= 0; +} + +static void dma_fence_array_release(struct dma_fence *fence) +{ + struct dma_fence_array *array = to_dma_fence_array(fence); + unsigned i; + + for (i = 0; i < array->num_fences; ++i) + dma_fence_put(array->fences[i]); + + kfree(array->fences); + dma_fence_free(fence); +} + +const struct dma_fence_ops dma_fence_array_ops = { + .get_driver_name = dma_fence_array_get_driver_name, + .get_timeline_name = dma_fence_array_get_timeline_name, + .enable_signaling = dma_fence_array_enable_signaling, + .signaled = dma_fence_array_signaled, + .wait = dma_fence_default_wait, + .release = dma_fence_array_release, +}; +EXPORT_SYMBOL(dma_fence_array_ops); + +/** + * dma_fence_array_create - Create a custom fence array + * @num_fences: [in] number of fences to add in the array + * @fences: [in] array containing the fences + * @context: [in] fence context to use + * @seqno: [in] sequence number to use + * @signal_on_any: [in] signal on any fence in the array + * + * Allocate a dma_fence_array object and initialize the base fence with + * dma_fence_init(). + * In case of error it returns NULL. + * + * The caller should allocate the fences array with num_fences size + * and fill it with the fences it wants to add to the object. Ownership of this + * array is taken and dma_fence_put() is used on each fence on release. + * + * If @signal_on_any is true the fence array signals if any fence in the array + * signals, otherwise it signals when all fences in the array signal. + */ +struct dma_fence_array *dma_fence_array_create(int num_fences, + struct dma_fence **fences, + u64 context, unsigned seqno, + bool signal_on_any) +{ + struct dma_fence_array *array; + size_t size = sizeof(*array); + + /* Allocate the callback structures behind the array. */ + size += num_fences * sizeof(struct dma_fence_array_cb); + array = kzalloc(size, GFP_KERNEL); + if (!array) + return NULL; + + spin_lock_init(&array->lock); + dma_fence_init(&array->base, &dma_fence_array_ops, &array->lock, + context, seqno); + + array->num_fences = num_fences; + atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences); + array->fences = fences; + + return array; +} +EXPORT_SYMBOL(dma_fence_array_create); diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c new file mode 100644 index 000000000000..3a7bf009c21c --- /dev/null +++ b/drivers/dma-buf/dma-fence.c @@ -0,0 +1,537 @@ +/* + * Fence mechanism for dma-buf and to allow for asynchronous dma access + * + * Copyright (C) 2012 Canonical Ltd + * Copyright (C) 2012 Texas Instruments + * + * Authors: + * Rob Clark + * Maarten Lankhorst + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include + +#define CREATE_TRACE_POINTS +#include + +EXPORT_TRACEPOINT_SYMBOL(dma_fence_annotate_wait_on); +EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit); + +/* + * fence context counter: each execution context should have its own + * fence context, this allows checking if fences belong to the same + * context or not. One device can have multiple separate contexts, + * and they're used if some engine can run independently of another. + */ +static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(0); + +/** + * dma_fence_context_alloc - allocate an array of fence contexts + * @num: [in] amount of contexts to allocate + * + * This function will return the first index of the number of fences allocated. + * The fence context is used for setting fence->context to a unique number. + */ +u64 dma_fence_context_alloc(unsigned num) +{ + BUG_ON(!num); + return atomic64_add_return(num, &dma_fence_context_counter) - num; +} +EXPORT_SYMBOL(dma_fence_context_alloc); + +/** + * dma_fence_signal_locked - signal completion of a fence + * @fence: the fence to signal + * + * Signal completion for software callbacks on a fence, this will unblock + * dma_fence_wait() calls and run all the callbacks added with + * dma_fence_add_callback(). Can be called multiple times, but since a fence + * can only go from unsignaled to signaled state, it will only be effective + * the first time. + * + * Unlike dma_fence_signal, this function must be called with fence->lock held. + */ +int dma_fence_signal_locked(struct dma_fence *fence) +{ + struct dma_fence_cb *cur, *tmp; + int ret = 0; + + lockdep_assert_held(fence->lock); + + if (WARN_ON(!fence)) + return -EINVAL; + + if (!ktime_to_ns(fence->timestamp)) { + fence->timestamp = ktime_get(); + smp_mb__before_atomic(); + } + + if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + ret = -EINVAL; + + /* + * we might have raced with the unlocked dma_fence_signal, + * still run through all callbacks + */ + } else + trace_dma_fence_signaled(fence); + + list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) { + list_del_init(&cur->node); + cur->func(fence, cur); + } + return ret; +} +EXPORT_SYMBOL(dma_fence_signal_locked); + +/** + * dma_fence_signal - signal completion of a fence + * @fence: the fence to signal + * + * Signal completion for software callbacks on a fence, this will unblock + * dma_fence_wait() calls and run all the callbacks added with + * dma_fence_add_callback(). Can be called multiple times, but since a fence + * can only go from unsignaled to signaled state, it will only be effective + * the first time. + */ +int dma_fence_signal(struct dma_fence *fence) +{ + unsigned long flags; + + if (!fence) + return -EINVAL; + + if (!ktime_to_ns(fence->timestamp)) { + fence->timestamp = ktime_get(); + smp_mb__before_atomic(); + } + + if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return -EINVAL; + + trace_dma_fence_signaled(fence); + + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) { + struct dma_fence_cb *cur, *tmp; + + spin_lock_irqsave(fence->lock, flags); + list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) { + list_del_init(&cur->node); + cur->func(fence, cur); + } + spin_unlock_irqrestore(fence->lock, flags); + } + return 0; +} +EXPORT_SYMBOL(dma_fence_signal); + +/** + * dma_fence_wait_timeout - sleep until the fence gets signaled + * or until timeout elapses + * @fence: [in] the fence to wait on + * @intr: [in] if true, do an interruptible wait + * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT + * + * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the + * remaining timeout in jiffies on success. Other error values may be + * returned on custom implementations. + * + * Performs a synchronous wait on this fence. It is assumed the caller + * directly or indirectly (buf-mgr between reservation and committing) + * holds a reference to the fence, otherwise the fence might be + * freed before return, resulting in undefined behavior. + */ +signed long +dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout) +{ + signed long ret; + + if (WARN_ON(timeout < 0)) + return -EINVAL; + + if (timeout == 0) + return dma_fence_is_signaled(fence); + + trace_dma_fence_wait_start(fence); + ret = fence->ops->wait(fence, intr, timeout); + trace_dma_fence_wait_end(fence); + return ret; +} +EXPORT_SYMBOL(dma_fence_wait_timeout); + +void dma_fence_release(struct kref *kref) +{ + struct dma_fence *fence = + container_of(kref, struct dma_fence, refcount); + + trace_dma_fence_destroy(fence); + + BUG_ON(!list_empty(&fence->cb_list)); + + if (fence->ops->release) + fence->ops->release(fence); + else + dma_fence_free(fence); +} +EXPORT_SYMBOL(dma_fence_release); + +void dma_fence_free(struct dma_fence *fence) +{ + kfree_rcu(fence, rcu); +} +EXPORT_SYMBOL(dma_fence_free); + +/** + * dma_fence_enable_sw_signaling - enable signaling on fence + * @fence: [in] the fence to enable + * + * this will request for sw signaling to be enabled, to make the fence + * complete as soon as possible + */ +void dma_fence_enable_sw_signaling(struct dma_fence *fence) +{ + unsigned long flags; + + if (!test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, + &fence->flags) && + !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + trace_dma_fence_enable_signal(fence); + + spin_lock_irqsave(fence->lock, flags); + + if (!fence->ops->enable_signaling(fence)) + dma_fence_signal_locked(fence); + + spin_unlock_irqrestore(fence->lock, flags); + } +} +EXPORT_SYMBOL(dma_fence_enable_sw_signaling); + +/** + * dma_fence_add_callback - add a callback to be called when the fence + * is signaled + * @fence: [in] the fence to wait on + * @cb: [in] the callback to register + * @func: [in] the function to call + * + * cb will be initialized by dma_fence_add_callback, no initialization + * by the caller is required. Any number of callbacks can be registered + * to a fence, but a callback can only be registered to one fence at a time. + * + * Note that the callback can be called from an atomic context. If + * fence is already signaled, this function will return -ENOENT (and + * *not* call the callback) + * + * Add a software callback to the fence. Same restrictions apply to + * refcount as it does to dma_fence_wait, however the caller doesn't need to + * keep a refcount to fence afterwards: when software access is enabled, + * the creator of the fence is required to keep the fence alive until + * after it signals with dma_fence_signal. The callback itself can be called + * from irq context. + * + */ +int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb, + dma_fence_func_t func) +{ + unsigned long flags; + int ret = 0; + bool was_set; + + if (WARN_ON(!fence || !func)) + return -EINVAL; + + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + INIT_LIST_HEAD(&cb->node); + return -ENOENT; + } + + spin_lock_irqsave(fence->lock, flags); + + was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, + &fence->flags); + + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + ret = -ENOENT; + else if (!was_set) { + trace_dma_fence_enable_signal(fence); + + if (!fence->ops->enable_signaling(fence)) { + dma_fence_signal_locked(fence); + ret = -ENOENT; + } + } + + if (!ret) { + cb->func = func; + list_add_tail(&cb->node, &fence->cb_list); + } else + INIT_LIST_HEAD(&cb->node); + spin_unlock_irqrestore(fence->lock, flags); + + return ret; +} +EXPORT_SYMBOL(dma_fence_add_callback); + +/** + * dma_fence_remove_callback - remove a callback from the signaling list + * @fence: [in] the fence to wait on + * @cb: [in] the callback to remove + * + * Remove a previously queued callback from the fence. This function returns + * true if the callback is successfully removed, or false if the fence has + * already been signaled. + * + * *WARNING*: + * Cancelling a callback should only be done if you really know what you're + * doing, since deadlocks and race conditions could occur all too easily. For + * this reason, it should only ever be done on hardware lockup recovery, + * with a reference held to the fence. + */ +bool +dma_fence_remove_callback(struct dma_fence *fence, struct dma_fence_cb *cb) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(fence->lock, flags); + + ret = !list_empty(&cb->node); + if (ret) + list_del_init(&cb->node); + + spin_unlock_irqrestore(fence->lock, flags); + + return ret; +} +EXPORT_SYMBOL(dma_fence_remove_callback); + +struct default_wait_cb { + struct dma_fence_cb base; + struct task_struct *task; +}; + +static void +dma_fence_default_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb) +{ + struct default_wait_cb *wait = + container_of(cb, struct default_wait_cb, base); + + wake_up_state(wait->task, TASK_NORMAL); +} + +/** + * dma_fence_default_wait - default sleep until the fence gets signaled + * or until timeout elapses + * @fence: [in] the fence to wait on + * @intr: [in] if true, do an interruptible wait + * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT + * + * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the + * remaining timeout in jiffies on success. + */ +signed long +dma_fence_default_wait(struct dma_fence *fence, bool intr, signed long timeout) +{ + struct default_wait_cb cb; + unsigned long flags; + signed long ret = timeout; + bool was_set; + + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return timeout; + + spin_lock_irqsave(fence->lock, flags); + + if (intr && signal_pending(current)) { + ret = -ERESTARTSYS; + goto out; + } + + was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, + &fence->flags); + + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + goto out; + + if (!was_set) { + trace_dma_fence_enable_signal(fence); + + if (!fence->ops->enable_signaling(fence)) { + dma_fence_signal_locked(fence); + goto out; + } + } + + cb.base.func = dma_fence_default_wait_cb; + cb.task = current; + list_add(&cb.base.node, &fence->cb_list); + + while (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) && ret > 0) { + if (intr) + __set_current_state(TASK_INTERRUPTIBLE); + else + __set_current_state(TASK_UNINTERRUPTIBLE); + spin_unlock_irqrestore(fence->lock, flags); + + ret = schedule_timeout(ret); + + spin_lock_irqsave(fence->lock, flags); + if (ret > 0 && intr && signal_pending(current)) + ret = -ERESTARTSYS; + } + + if (!list_empty(&cb.base.node)) + list_del(&cb.base.node); + __set_current_state(TASK_RUNNING); + +out: + spin_unlock_irqrestore(fence->lock, flags); + return ret; +} +EXPORT_SYMBOL(dma_fence_default_wait); + +static bool +dma_fence_test_signaled_any(struct dma_fence **fences, uint32_t count) +{ + int i; + + for (i = 0; i < count; ++i) { + struct dma_fence *fence = fences[i]; + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return true; + } + return false; +} + +/** + * dma_fence_wait_any_timeout - sleep until any fence gets signaled + * or until timeout elapses + * @fences: [in] array of fences to wait on + * @count: [in] number of fences to wait on + * @intr: [in] if true, do an interruptible wait + * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT + * + * Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if + * interrupted, 0 if the wait timed out, or the remaining timeout in jiffies + * on success. + * + * Synchronous waits for the first fence in the array to be signaled. The + * caller needs to hold a reference to all fences in the array, otherwise a + * fence might be freed before return, resulting in undefined behavior. + */ +signed long +dma_fence_wait_any_timeout(struct dma_fence **fences, uint32_t count, + bool intr, signed long timeout) +{ + struct default_wait_cb *cb; + signed long ret = timeout; + unsigned i; + + if (WARN_ON(!fences || !count || timeout < 0)) + return -EINVAL; + + if (timeout == 0) { + for (i = 0; i < count; ++i) + if (dma_fence_is_signaled(fences[i])) + return 1; + + return 0; + } + + cb = kcalloc(count, sizeof(struct default_wait_cb), GFP_KERNEL); + if (cb == NULL) { + ret = -ENOMEM; + goto err_free_cb; + } + + for (i = 0; i < count; ++i) { + struct dma_fence *fence = fences[i]; + + if (fence->ops->wait != dma_fence_default_wait) { + ret = -EINVAL; + goto fence_rm_cb; + } + + cb[i].task = current; + if (dma_fence_add_callback(fence, &cb[i].base, + dma_fence_default_wait_cb)) { + /* This fence is already signaled */ + goto fence_rm_cb; + } + } + + while (ret > 0) { + if (intr) + set_current_state(TASK_INTERRUPTIBLE); + else + set_current_state(TASK_UNINTERRUPTIBLE); + + if (dma_fence_test_signaled_any(fences, count)) + break; + + ret = schedule_timeout(ret); + + if (ret > 0 && intr && signal_pending(current)) + ret = -ERESTARTSYS; + } + + __set_current_state(TASK_RUNNING); + +fence_rm_cb: + while (i-- > 0) + dma_fence_remove_callback(fences[i], &cb[i].base); + +err_free_cb: + kfree(cb); + + return ret; +} +EXPORT_SYMBOL(dma_fence_wait_any_timeout); + +/** + * dma_fence_init - Initialize a custom fence. + * @fence: [in] the fence to initialize + * @ops: [in] the dma_fence_ops for operations on this fence + * @lock: [in] the irqsafe spinlock to use for locking this fence + * @context: [in] the execution context this fence is run on + * @seqno: [in] a linear increasing sequence number for this context + * + * Initializes an allocated fence, the caller doesn't have to keep its + * refcount after committing with this fence, but it will need to hold a + * refcount again if dma_fence_ops.enable_signaling gets called. This can + * be used for other implementing other types of fence. + * + * context and seqno are used for easy comparison between fences, allowing + * to check which fence is later by simply using dma_fence_later. + */ +void +dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, + spinlock_t *lock, u64 context, unsigned seqno) +{ + BUG_ON(!lock); + BUG_ON(!ops || !ops->wait || !ops->enable_signaling || + !ops->get_driver_name || !ops->get_timeline_name); + + kref_init(&fence->refcount); + fence->ops = ops; + INIT_LIST_HEAD(&fence->cb_list); + fence->lock = lock; + fence->context = context; + fence->seqno = seqno; + fence->flags = 0UL; + + trace_dma_fence_init(fence); +} +EXPORT_SYMBOL(dma_fence_init); diff --git a/drivers/dma-buf/fence-array.c b/drivers/dma-buf/fence-array.c deleted file mode 100644 index f1989fcaf354..000000000000 --- a/drivers/dma-buf/fence-array.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * fence-array: aggregate fences to be waited together - * - * Copyright (C) 2016 Collabora Ltd - * Copyright (C) 2016 Advanced Micro Devices, Inc. - * Authors: - * Gustavo Padovan - * Christian König - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#include -#include -#include - -static void fence_array_cb_func(struct fence *f, struct fence_cb *cb); - -static const char *fence_array_get_driver_name(struct fence *fence) -{ - return "fence_array"; -} - -static const char *fence_array_get_timeline_name(struct fence *fence) -{ - return "unbound"; -} - -static void fence_array_cb_func(struct fence *f, struct fence_cb *cb) -{ - struct fence_array_cb *array_cb = - container_of(cb, struct fence_array_cb, cb); - struct fence_array *array = array_cb->array; - - if (atomic_dec_and_test(&array->num_pending)) - fence_signal(&array->base); - fence_put(&array->base); -} - -static bool fence_array_enable_signaling(struct fence *fence) -{ - struct fence_array *array = to_fence_array(fence); - struct fence_array_cb *cb = (void *)(&array[1]); - unsigned i; - - for (i = 0; i < array->num_fences; ++i) { - cb[i].array = array; - /* - * As we may report that the fence is signaled before all - * callbacks are complete, we need to take an additional - * reference count on the array so that we do not free it too - * early. The core fence handling will only hold the reference - * until we signal the array as complete (but that is now - * insufficient). - */ - fence_get(&array->base); - if (fence_add_callback(array->fences[i], &cb[i].cb, - fence_array_cb_func)) { - fence_put(&array->base); - if (atomic_dec_and_test(&array->num_pending)) - return false; - } - } - - return true; -} - -static bool fence_array_signaled(struct fence *fence) -{ - struct fence_array *array = to_fence_array(fence); - - return atomic_read(&array->num_pending) <= 0; -} - -static void fence_array_release(struct fence *fence) -{ - struct fence_array *array = to_fence_array(fence); - unsigned i; - - for (i = 0; i < array->num_fences; ++i) - fence_put(array->fences[i]); - - kfree(array->fences); - fence_free(fence); -} - -const struct fence_ops fence_array_ops = { - .get_driver_name = fence_array_get_driver_name, - .get_timeline_name = fence_array_get_timeline_name, - .enable_signaling = fence_array_enable_signaling, - .signaled = fence_array_signaled, - .wait = fence_default_wait, - .release = fence_array_release, -}; -EXPORT_SYMBOL(fence_array_ops); - -/** - * fence_array_create - Create a custom fence array - * @num_fences: [in] number of fences to add in the array - * @fences: [in] array containing the fences - * @context: [in] fence context to use - * @seqno: [in] sequence number to use - * @signal_on_any: [in] signal on any fence in the array - * - * Allocate a fence_array object and initialize the base fence with fence_init(). - * In case of error it returns NULL. - * - * The caller should allocate the fences array with num_fences size - * and fill it with the fences it wants to add to the object. Ownership of this - * array is taken and fence_put() is used on each fence on release. - * - * If @signal_on_any is true the fence array signals if any fence in the array - * signals, otherwise it signals when all fences in the array signal. - */ -struct fence_array *fence_array_create(int num_fences, struct fence **fences, - u64 context, unsigned seqno, - bool signal_on_any) -{ - struct fence_array *array; - size_t size = sizeof(*array); - - /* Allocate the callback structures behind the array. */ - size += num_fences * sizeof(struct fence_array_cb); - array = kzalloc(size, GFP_KERNEL); - if (!array) - return NULL; - - spin_lock_init(&array->lock); - fence_init(&array->base, &fence_array_ops, &array->lock, - context, seqno); - - array->num_fences = num_fences; - atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences); - array->fences = fences; - - return array; -} -EXPORT_SYMBOL(fence_array_create); diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c deleted file mode 100644 index cc05dddc77a6..000000000000 --- a/drivers/dma-buf/fence.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Fence mechanism for dma-buf and to allow for asynchronous dma access - * - * Copyright (C) 2012 Canonical Ltd - * Copyright (C) 2012 Texas Instruments - * - * Authors: - * Rob Clark - * Maarten Lankhorst - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#include -#include -#include -#include - -#define CREATE_TRACE_POINTS -#include - -EXPORT_TRACEPOINT_SYMBOL(fence_annotate_wait_on); -EXPORT_TRACEPOINT_SYMBOL(fence_emit); - -/* - * fence context counter: each execution context should have its own - * fence context, this allows checking if fences belong to the same - * context or not. One device can have multiple separate contexts, - * and they're used if some engine can run independently of another. - */ -static atomic64_t fence_context_counter = ATOMIC64_INIT(0); - -/** - * fence_context_alloc - allocate an array of fence contexts - * @num: [in] amount of contexts to allocate - * - * This function will return the first index of the number of fences allocated. - * The fence context is used for setting fence->context to a unique number. - */ -u64 fence_context_alloc(unsigned num) -{ - BUG_ON(!num); - return atomic64_add_return(num, &fence_context_counter) - num; -} -EXPORT_SYMBOL(fence_context_alloc); - -/** - * fence_signal_locked - signal completion of a fence - * @fence: the fence to signal - * - * Signal completion for software callbacks on a fence, this will unblock - * fence_wait() calls and run all the callbacks added with - * fence_add_callback(). Can be called multiple times, but since a fence - * can only go from unsignaled to signaled state, it will only be effective - * the first time. - * - * Unlike fence_signal, this function must be called with fence->lock held. - */ -int fence_signal_locked(struct fence *fence) -{ - struct fence_cb *cur, *tmp; - int ret = 0; - - lockdep_assert_held(fence->lock); - - if (WARN_ON(!fence)) - return -EINVAL; - - if (!ktime_to_ns(fence->timestamp)) { - fence->timestamp = ktime_get(); - smp_mb__before_atomic(); - } - - if (test_and_set_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { - ret = -EINVAL; - - /* - * we might have raced with the unlocked fence_signal, - * still run through all callbacks - */ - } else - trace_fence_signaled(fence); - - list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) { - list_del_init(&cur->node); - cur->func(fence, cur); - } - return ret; -} -EXPORT_SYMBOL(fence_signal_locked); - -/** - * fence_signal - signal completion of a fence - * @fence: the fence to signal - * - * Signal completion for software callbacks on a fence, this will unblock - * fence_wait() calls and run all the callbacks added with - * fence_add_callback(). Can be called multiple times, but since a fence - * can only go from unsignaled to signaled state, it will only be effective - * the first time. - */ -int fence_signal(struct fence *fence) -{ - unsigned long flags; - - if (!fence) - return -EINVAL; - - if (!ktime_to_ns(fence->timestamp)) { - fence->timestamp = ktime_get(); - smp_mb__before_atomic(); - } - - if (test_and_set_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - return -EINVAL; - - trace_fence_signaled(fence); - - if (test_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) { - struct fence_cb *cur, *tmp; - - spin_lock_irqsave(fence->lock, flags); - list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) { - list_del_init(&cur->node); - cur->func(fence, cur); - } - spin_unlock_irqrestore(fence->lock, flags); - } - return 0; -} -EXPORT_SYMBOL(fence_signal); - -/** - * fence_wait_timeout - sleep until the fence gets signaled - * or until timeout elapses - * @fence: [in] the fence to wait on - * @intr: [in] if true, do an interruptible wait - * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT - * - * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the - * remaining timeout in jiffies on success. Other error values may be - * returned on custom implementations. - * - * Performs a synchronous wait on this fence. It is assumed the caller - * directly or indirectly (buf-mgr between reservation and committing) - * holds a reference to the fence, otherwise the fence might be - * freed before return, resulting in undefined behavior. - */ -signed long -fence_wait_timeout(struct fence *fence, bool intr, signed long timeout) -{ - signed long ret; - - if (WARN_ON(timeout < 0)) - return -EINVAL; - - if (timeout == 0) - return fence_is_signaled(fence); - - trace_fence_wait_start(fence); - ret = fence->ops->wait(fence, intr, timeout); - trace_fence_wait_end(fence); - return ret; -} -EXPORT_SYMBOL(fence_wait_timeout); - -void fence_release(struct kref *kref) -{ - struct fence *fence = - container_of(kref, struct fence, refcount); - - trace_fence_destroy(fence); - - BUG_ON(!list_empty(&fence->cb_list)); - - if (fence->ops->release) - fence->ops->release(fence); - else - fence_free(fence); -} -EXPORT_SYMBOL(fence_release); - -void fence_free(struct fence *fence) -{ - kfree_rcu(fence, rcu); -} -EXPORT_SYMBOL(fence_free); - -/** - * fence_enable_sw_signaling - enable signaling on fence - * @fence: [in] the fence to enable - * - * this will request for sw signaling to be enabled, to make the fence - * complete as soon as possible - */ -void fence_enable_sw_signaling(struct fence *fence) -{ - unsigned long flags; - - if (!test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags) && - !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { - trace_fence_enable_signal(fence); - - spin_lock_irqsave(fence->lock, flags); - - if (!fence->ops->enable_signaling(fence)) - fence_signal_locked(fence); - - spin_unlock_irqrestore(fence->lock, flags); - } -} -EXPORT_SYMBOL(fence_enable_sw_signaling); - -/** - * fence_add_callback - add a callback to be called when the fence - * is signaled - * @fence: [in] the fence to wait on - * @cb: [in] the callback to register - * @func: [in] the function to call - * - * cb will be initialized by fence_add_callback, no initialization - * by the caller is required. Any number of callbacks can be registered - * to a fence, but a callback can only be registered to one fence at a time. - * - * Note that the callback can be called from an atomic context. If - * fence is already signaled, this function will return -ENOENT (and - * *not* call the callback) - * - * Add a software callback to the fence. Same restrictions apply to - * refcount as it does to fence_wait, however the caller doesn't need to - * keep a refcount to fence afterwards: when software access is enabled, - * the creator of the fence is required to keep the fence alive until - * after it signals with fence_signal. The callback itself can be called - * from irq context. - * - */ -int fence_add_callback(struct fence *fence, struct fence_cb *cb, - fence_func_t func) -{ - unsigned long flags; - int ret = 0; - bool was_set; - - if (WARN_ON(!fence || !func)) - return -EINVAL; - - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { - INIT_LIST_HEAD(&cb->node); - return -ENOENT; - } - - spin_lock_irqsave(fence->lock, flags); - - was_set = test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags); - - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - ret = -ENOENT; - else if (!was_set) { - trace_fence_enable_signal(fence); - - if (!fence->ops->enable_signaling(fence)) { - fence_signal_locked(fence); - ret = -ENOENT; - } - } - - if (!ret) { - cb->func = func; - list_add_tail(&cb->node, &fence->cb_list); - } else - INIT_LIST_HEAD(&cb->node); - spin_unlock_irqrestore(fence->lock, flags); - - return ret; -} -EXPORT_SYMBOL(fence_add_callback); - -/** - * fence_remove_callback - remove a callback from the signaling list - * @fence: [in] the fence to wait on - * @cb: [in] the callback to remove - * - * Remove a previously queued callback from the fence. This function returns - * true if the callback is successfully removed, or false if the fence has - * already been signaled. - * - * *WARNING*: - * Cancelling a callback should only be done if you really know what you're - * doing, since deadlocks and race conditions could occur all too easily. For - * this reason, it should only ever be done on hardware lockup recovery, - * with a reference held to the fence. - */ -bool -fence_remove_callback(struct fence *fence, struct fence_cb *cb) -{ - unsigned long flags; - bool ret; - - spin_lock_irqsave(fence->lock, flags); - - ret = !list_empty(&cb->node); - if (ret) - list_del_init(&cb->node); - - spin_unlock_irqrestore(fence->lock, flags); - - return ret; -} -EXPORT_SYMBOL(fence_remove_callback); - -struct default_wait_cb { - struct fence_cb base; - struct task_struct *task; -}; - -static void -fence_default_wait_cb(struct fence *fence, struct fence_cb *cb) -{ - struct default_wait_cb *wait = - container_of(cb, struct default_wait_cb, base); - - wake_up_state(wait->task, TASK_NORMAL); -} - -/** - * fence_default_wait - default sleep until the fence gets signaled - * or until timeout elapses - * @fence: [in] the fence to wait on - * @intr: [in] if true, do an interruptible wait - * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT - * - * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the - * remaining timeout in jiffies on success. - */ -signed long -fence_default_wait(struct fence *fence, bool intr, signed long timeout) -{ - struct default_wait_cb cb; - unsigned long flags; - signed long ret = timeout; - bool was_set; - - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - return timeout; - - spin_lock_irqsave(fence->lock, flags); - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; - goto out; - } - - was_set = test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags); - - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - goto out; - - if (!was_set) { - trace_fence_enable_signal(fence); - - if (!fence->ops->enable_signaling(fence)) { - fence_signal_locked(fence); - goto out; - } - } - - cb.base.func = fence_default_wait_cb; - cb.task = current; - list_add(&cb.base.node, &fence->cb_list); - - while (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags) && ret > 0) { - if (intr) - __set_current_state(TASK_INTERRUPTIBLE); - else - __set_current_state(TASK_UNINTERRUPTIBLE); - spin_unlock_irqrestore(fence->lock, flags); - - ret = schedule_timeout(ret); - - spin_lock_irqsave(fence->lock, flags); - if (ret > 0 && intr && signal_pending(current)) - ret = -ERESTARTSYS; - } - - if (!list_empty(&cb.base.node)) - list_del(&cb.base.node); - __set_current_state(TASK_RUNNING); - -out: - spin_unlock_irqrestore(fence->lock, flags); - return ret; -} -EXPORT_SYMBOL(fence_default_wait); - -static bool -fence_test_signaled_any(struct fence **fences, uint32_t count) -{ - int i; - - for (i = 0; i < count; ++i) { - struct fence *fence = fences[i]; - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - return true; - } - return false; -} - -/** - * fence_wait_any_timeout - sleep until any fence gets signaled - * or until timeout elapses - * @fences: [in] array of fences to wait on - * @count: [in] number of fences to wait on - * @intr: [in] if true, do an interruptible wait - * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT - * - * Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if - * interrupted, 0 if the wait timed out, or the remaining timeout in jiffies - * on success. - * - * Synchronous waits for the first fence in the array to be signaled. The - * caller needs to hold a reference to all fences in the array, otherwise a - * fence might be freed before return, resulting in undefined behavior. - */ -signed long -fence_wait_any_timeout(struct fence **fences, uint32_t count, - bool intr, signed long timeout) -{ - struct default_wait_cb *cb; - signed long ret = timeout; - unsigned i; - - if (WARN_ON(!fences || !count || timeout < 0)) - return -EINVAL; - - if (timeout == 0) { - for (i = 0; i < count; ++i) - if (fence_is_signaled(fences[i])) - return 1; - - return 0; - } - - cb = kcalloc(count, sizeof(struct default_wait_cb), GFP_KERNEL); - if (cb == NULL) { - ret = -ENOMEM; - goto err_free_cb; - } - - for (i = 0; i < count; ++i) { - struct fence *fence = fences[i]; - - if (fence->ops->wait != fence_default_wait) { - ret = -EINVAL; - goto fence_rm_cb; - } - - cb[i].task = current; - if (fence_add_callback(fence, &cb[i].base, - fence_default_wait_cb)) { - /* This fence is already signaled */ - goto fence_rm_cb; - } - } - - while (ret > 0) { - if (intr) - set_current_state(TASK_INTERRUPTIBLE); - else - set_current_state(TASK_UNINTERRUPTIBLE); - - if (fence_test_signaled_any(fences, count)) - break; - - ret = schedule_timeout(ret); - - if (ret > 0 && intr && signal_pending(current)) - ret = -ERESTARTSYS; - } - - __set_current_state(TASK_RUNNING); - -fence_rm_cb: - while (i-- > 0) - fence_remove_callback(fences[i], &cb[i].base); - -err_free_cb: - kfree(cb); - - return ret; -} -EXPORT_SYMBOL(fence_wait_any_timeout); - -/** - * fence_init - Initialize a custom fence. - * @fence: [in] the fence to initialize - * @ops: [in] the fence_ops for operations on this fence - * @lock: [in] the irqsafe spinlock to use for locking this fence - * @context: [in] the execution context this fence is run on - * @seqno: [in] a linear increasing sequence number for this context - * - * Initializes an allocated fence, the caller doesn't have to keep its - * refcount after committing with this fence, but it will need to hold a - * refcount again if fence_ops.enable_signaling gets called. This can - * be used for other implementing other types of fence. - * - * context and seqno are used for easy comparison between fences, allowing - * to check which fence is later by simply using fence_later. - */ -void -fence_init(struct fence *fence, const struct fence_ops *ops, - spinlock_t *lock, u64 context, unsigned seqno) -{ - BUG_ON(!lock); - BUG_ON(!ops || !ops->wait || !ops->enable_signaling || - !ops->get_driver_name || !ops->get_timeline_name); - - kref_init(&fence->refcount); - fence->ops = ops; - INIT_LIST_HEAD(&fence->cb_list); - fence->lock = lock; - fence->context = context; - fence->seqno = seqno; - fence->flags = 0UL; - - trace_fence_init(fence); -} -EXPORT_SYMBOL(fence_init); diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 82de59f7cbbd..7ed56f3edfb7 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -102,17 +102,17 @@ EXPORT_SYMBOL(reservation_object_reserve_shared); static void reservation_object_add_shared_inplace(struct reservation_object *obj, struct reservation_object_list *fobj, - struct fence *fence) + struct dma_fence *fence) { u32 i; - fence_get(fence); + dma_fence_get(fence); preempt_disable(); write_seqcount_begin(&obj->seq); for (i = 0; i < fobj->shared_count; ++i) { - struct fence *old_fence; + struct dma_fence *old_fence; old_fence = rcu_dereference_protected(fobj->shared[i], reservation_object_held(obj)); @@ -123,7 +123,7 @@ reservation_object_add_shared_inplace(struct reservation_object *obj, write_seqcount_end(&obj->seq); preempt_enable(); - fence_put(old_fence); + dma_fence_put(old_fence); return; } } @@ -143,12 +143,12 @@ static void reservation_object_add_shared_replace(struct reservation_object *obj, struct reservation_object_list *old, struct reservation_object_list *fobj, - struct fence *fence) + struct dma_fence *fence) { unsigned i; - struct fence *old_fence = NULL; + struct dma_fence *old_fence = NULL; - fence_get(fence); + dma_fence_get(fence); if (!old) { RCU_INIT_POINTER(fobj->shared[0], fence); @@ -165,7 +165,7 @@ reservation_object_add_shared_replace(struct reservation_object *obj, fobj->shared_count = old->shared_count; for (i = 0; i < old->shared_count; ++i) { - struct fence *check; + struct dma_fence *check; check = rcu_dereference_protected(old->shared[i], reservation_object_held(obj)); @@ -196,7 +196,7 @@ done: kfree_rcu(old, rcu); if (old_fence) - fence_put(old_fence); + dma_fence_put(old_fence); } /** @@ -208,7 +208,7 @@ done: * reservation_object_reserve_shared() has been called. */ void reservation_object_add_shared_fence(struct reservation_object *obj, - struct fence *fence) + struct dma_fence *fence) { struct reservation_object_list *old, *fobj = obj->staged; @@ -231,9 +231,9 @@ EXPORT_SYMBOL(reservation_object_add_shared_fence); * Add a fence to the exclusive slot. The obj->lock must be held. */ void reservation_object_add_excl_fence(struct reservation_object *obj, - struct fence *fence) + struct dma_fence *fence) { - struct fence *old_fence = reservation_object_get_excl(obj); + struct dma_fence *old_fence = reservation_object_get_excl(obj); struct reservation_object_list *old; u32 i = 0; @@ -242,7 +242,7 @@ void reservation_object_add_excl_fence(struct reservation_object *obj, i = old->shared_count; if (fence) - fence_get(fence); + dma_fence_get(fence); preempt_disable(); write_seqcount_begin(&obj->seq); @@ -255,11 +255,11 @@ void reservation_object_add_excl_fence(struct reservation_object *obj, /* inplace update, no shared fences */ while (i--) - fence_put(rcu_dereference_protected(old->shared[i], + dma_fence_put(rcu_dereference_protected(old->shared[i], reservation_object_held(obj))); if (old_fence) - fence_put(old_fence); + dma_fence_put(old_fence); } EXPORT_SYMBOL(reservation_object_add_excl_fence); @@ -276,12 +276,12 @@ EXPORT_SYMBOL(reservation_object_add_excl_fence); * Zero or -errno */ int reservation_object_get_fences_rcu(struct reservation_object *obj, - struct fence **pfence_excl, + struct dma_fence **pfence_excl, unsigned *pshared_count, - struct fence ***pshared) + struct dma_fence ***pshared) { - struct fence **shared = NULL; - struct fence *fence_excl; + struct dma_fence **shared = NULL; + struct dma_fence *fence_excl; unsigned int shared_count; int ret = 1; @@ -296,12 +296,12 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, seq = read_seqcount_begin(&obj->seq); fence_excl = rcu_dereference(obj->fence_excl); - if (fence_excl && !fence_get_rcu(fence_excl)) + if (fence_excl && !dma_fence_get_rcu(fence_excl)) goto unlock; fobj = rcu_dereference(obj->fence); if (fobj) { - struct fence **nshared; + struct dma_fence **nshared; size_t sz = sizeof(*shared) * fobj->shared_max; nshared = krealloc(shared, sz, @@ -322,15 +322,15 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, for (i = 0; i < shared_count; ++i) { shared[i] = rcu_dereference(fobj->shared[i]); - if (!fence_get_rcu(shared[i])) + if (!dma_fence_get_rcu(shared[i])) break; } } if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) { while (i--) - fence_put(shared[i]); - fence_put(fence_excl); + dma_fence_put(shared[i]); + dma_fence_put(fence_excl); goto unlock; } @@ -368,7 +368,7 @@ long reservation_object_wait_timeout_rcu(struct reservation_object *obj, bool wait_all, bool intr, unsigned long timeout) { - struct fence *fence; + struct dma_fence *fence; unsigned seq, shared_count, i = 0; long ret = timeout; @@ -389,16 +389,17 @@ retry: shared_count = fobj->shared_count; for (i = 0; i < shared_count; ++i) { - struct fence *lfence = rcu_dereference(fobj->shared[i]); + struct dma_fence *lfence = rcu_dereference(fobj->shared[i]); - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, + &lfence->flags)) continue; - if (!fence_get_rcu(lfence)) + if (!dma_fence_get_rcu(lfence)) goto unlock_retry; - if (fence_is_signaled(lfence)) { - fence_put(lfence); + if (dma_fence_is_signaled(lfence)) { + dma_fence_put(lfence); continue; } @@ -408,15 +409,16 @@ retry: } if (!shared_count) { - struct fence *fence_excl = rcu_dereference(obj->fence_excl); + struct dma_fence *fence_excl = rcu_dereference(obj->fence_excl); if (fence_excl && - !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) { - if (!fence_get_rcu(fence_excl)) + !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, + &fence_excl->flags)) { + if (!dma_fence_get_rcu(fence_excl)) goto unlock_retry; - if (fence_is_signaled(fence_excl)) - fence_put(fence_excl); + if (dma_fence_is_signaled(fence_excl)) + dma_fence_put(fence_excl); else fence = fence_excl; } @@ -425,12 +427,12 @@ retry: rcu_read_unlock(); if (fence) { if (read_seqcount_retry(&obj->seq, seq)) { - fence_put(fence); + dma_fence_put(fence); goto retry; } - ret = fence_wait_timeout(fence, intr, ret); - fence_put(fence); + ret = dma_fence_wait_timeout(fence, intr, ret); + dma_fence_put(fence); if (ret > 0 && wait_all && (i + 1 < shared_count)) goto retry; } @@ -444,18 +446,18 @@ EXPORT_SYMBOL_GPL(reservation_object_wait_timeout_rcu); static inline int -reservation_object_test_signaled_single(struct fence *passed_fence) +reservation_object_test_signaled_single(struct dma_fence *passed_fence) { - struct fence *fence, *lfence = passed_fence; + struct dma_fence *fence, *lfence = passed_fence; int ret = 1; - if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) { - fence = fence_get_rcu(lfence); + if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) { + fence = dma_fence_get_rcu(lfence); if (!fence) return -1; - ret = !!fence_is_signaled(fence); - fence_put(fence); + ret = !!dma_fence_is_signaled(fence); + dma_fence_put(fence); } return ret; } @@ -492,7 +494,7 @@ retry: shared_count = fobj->shared_count; for (i = 0; i < shared_count; ++i) { - struct fence *fence = rcu_dereference(fobj->shared[i]); + struct dma_fence *fence = rcu_dereference(fobj->shared[i]); ret = reservation_object_test_signaled_single(fence); if (ret < 0) @@ -506,7 +508,7 @@ retry: } if (!shared_count) { - struct fence *fence_excl = rcu_dereference(obj->fence_excl); + struct dma_fence *fence_excl = rcu_dereference(obj->fence_excl); if (fence_excl) { ret = reservation_object_test_signaled_single( diff --git a/drivers/dma-buf/seqno-fence.c b/drivers/dma-buf/seqno-fence.c index 71127f8f1626..f47112a64763 100644 --- a/drivers/dma-buf/seqno-fence.c +++ b/drivers/dma-buf/seqno-fence.c @@ -21,35 +21,35 @@ #include #include -static const char *seqno_fence_get_driver_name(struct fence *fence) +static const char *seqno_fence_get_driver_name(struct dma_fence *fence) { struct seqno_fence *seqno_fence = to_seqno_fence(fence); return seqno_fence->ops->get_driver_name(fence); } -static const char *seqno_fence_get_timeline_name(struct fence *fence) +static const char *seqno_fence_get_timeline_name(struct dma_fence *fence) { struct seqno_fence *seqno_fence = to_seqno_fence(fence); return seqno_fence->ops->get_timeline_name(fence); } -static bool seqno_enable_signaling(struct fence *fence) +static bool seqno_enable_signaling(struct dma_fence *fence) { struct seqno_fence *seqno_fence = to_seqno_fence(fence); return seqno_fence->ops->enable_signaling(fence); } -static bool seqno_signaled(struct fence *fence) +static bool seqno_signaled(struct dma_fence *fence) { struct seqno_fence *seqno_fence = to_seqno_fence(fence); return seqno_fence->ops->signaled && seqno_fence->ops->signaled(fence); } -static void seqno_release(struct fence *fence) +static void seqno_release(struct dma_fence *fence) { struct seqno_fence *f = to_seqno_fence(fence); @@ -57,18 +57,18 @@ static void seqno_release(struct fence *fence) if (f->ops->release) f->ops->release(fence); else - fence_free(&f->base); + dma_fence_free(&f->base); } -static signed long seqno_wait(struct fence *fence, bool intr, - signed long timeout) +static signed long seqno_wait(struct dma_fence *fence, bool intr, + signed long timeout) { struct seqno_fence *f = to_seqno_fence(fence); return f->ops->wait(fence, intr, timeout); } -const struct fence_ops seqno_fence_ops = { +const struct dma_fence_ops seqno_fence_ops = { .get_driver_name = seqno_fence_get_driver_name, .get_timeline_name = seqno_fence_get_timeline_name, .enable_signaling = seqno_enable_signaling, diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 62e8e6dc7953..82e0ca4dd0c1 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -68,9 +68,9 @@ struct sw_sync_create_fence_data { #define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) -static const struct fence_ops timeline_fence_ops; +static const struct dma_fence_ops timeline_fence_ops; -static inline struct sync_pt *fence_to_sync_pt(struct fence *fence) +static inline struct sync_pt *dma_fence_to_sync_pt(struct dma_fence *fence) { if (fence->ops != &timeline_fence_ops) return NULL; @@ -93,7 +93,7 @@ struct sync_timeline *sync_timeline_create(const char *name) return NULL; kref_init(&obj->kref); - obj->context = fence_context_alloc(1); + obj->context = dma_fence_context_alloc(1); strlcpy(obj->name, name, sizeof(obj->name)); INIT_LIST_HEAD(&obj->child_list_head); @@ -146,7 +146,7 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) list_for_each_entry_safe(pt, next, &obj->active_list_head, active_list) { - if (fence_is_signaled_locked(&pt->base)) + if (dma_fence_is_signaled_locked(&pt->base)) list_del_init(&pt->active_list); } @@ -179,30 +179,30 @@ static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size, spin_lock_irqsave(&obj->child_list_lock, flags); sync_timeline_get(obj); - fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock, - obj->context, value); + dma_fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock, + obj->context, value); list_add_tail(&pt->child_list, &obj->child_list_head); INIT_LIST_HEAD(&pt->active_list); spin_unlock_irqrestore(&obj->child_list_lock, flags); return pt; } -static const char *timeline_fence_get_driver_name(struct fence *fence) +static const char *timeline_fence_get_driver_name(struct dma_fence *fence) { return "sw_sync"; } -static const char *timeline_fence_get_timeline_name(struct fence *fence) +static const char *timeline_fence_get_timeline_name(struct dma_fence *fence) { - struct sync_timeline *parent = fence_parent(fence); + struct sync_timeline *parent = dma_fence_parent(fence); return parent->name; } -static void timeline_fence_release(struct fence *fence) +static void timeline_fence_release(struct dma_fence *fence) { - struct sync_pt *pt = fence_to_sync_pt(fence); - struct sync_timeline *parent = fence_parent(fence); + struct sync_pt *pt = dma_fence_to_sync_pt(fence); + struct sync_timeline *parent = dma_fence_parent(fence); unsigned long flags; spin_lock_irqsave(fence->lock, flags); @@ -212,20 +212,20 @@ static void timeline_fence_release(struct fence *fence) spin_unlock_irqrestore(fence->lock, flags); sync_timeline_put(parent); - fence_free(fence); + dma_fence_free(fence); } -static bool timeline_fence_signaled(struct fence *fence) +static bool timeline_fence_signaled(struct dma_fence *fence) { - struct sync_timeline *parent = fence_parent(fence); + struct sync_timeline *parent = dma_fence_parent(fence); return (fence->seqno > parent->value) ? false : true; } -static bool timeline_fence_enable_signaling(struct fence *fence) +static bool timeline_fence_enable_signaling(struct dma_fence *fence) { - struct sync_pt *pt = fence_to_sync_pt(fence); - struct sync_timeline *parent = fence_parent(fence); + struct sync_pt *pt = dma_fence_to_sync_pt(fence); + struct sync_timeline *parent = dma_fence_parent(fence); if (timeline_fence_signaled(fence)) return false; @@ -234,26 +234,26 @@ static bool timeline_fence_enable_signaling(struct fence *fence) return true; } -static void timeline_fence_value_str(struct fence *fence, +static void timeline_fence_value_str(struct dma_fence *fence, char *str, int size) { snprintf(str, size, "%d", fence->seqno); } -static void timeline_fence_timeline_value_str(struct fence *fence, +static void timeline_fence_timeline_value_str(struct dma_fence *fence, char *str, int size) { - struct sync_timeline *parent = fence_parent(fence); + struct sync_timeline *parent = dma_fence_parent(fence); snprintf(str, size, "%d", parent->value); } -static const struct fence_ops timeline_fence_ops = { +static const struct dma_fence_ops timeline_fence_ops = { .get_driver_name = timeline_fence_get_driver_name, .get_timeline_name = timeline_fence_get_timeline_name, .enable_signaling = timeline_fence_enable_signaling, .signaled = timeline_fence_signaled, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .release = timeline_fence_release, .fence_value_str = timeline_fence_value_str, .timeline_value_str = timeline_fence_timeline_value_str, @@ -317,7 +317,7 @@ static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, sync_file = sync_file_create(&pt->base); if (!sync_file) { - fence_put(&pt->base); + dma_fence_put(&pt->base); err = -ENOMEM; goto err; } diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c index 2dd4c3db6caa..48b20e34fb6d 100644 --- a/drivers/dma-buf/sync_debug.c +++ b/drivers/dma-buf/sync_debug.c @@ -71,12 +71,13 @@ static const char *sync_status_str(int status) return "error"; } -static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show) +static void sync_print_fence(struct seq_file *s, + struct dma_fence *fence, bool show) { int status = 1; - struct sync_timeline *parent = fence_parent(fence); + struct sync_timeline *parent = dma_fence_parent(fence); - if (fence_is_signaled_locked(fence)) + if (dma_fence_is_signaled_locked(fence)) status = fence->status; seq_printf(s, " %s%sfence %s", @@ -135,10 +136,10 @@ static void sync_print_sync_file(struct seq_file *s, int i; seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, - sync_status_str(!fence_is_signaled(sync_file->fence))); + sync_status_str(!dma_fence_is_signaled(sync_file->fence))); - if (fence_is_array(sync_file->fence)) { - struct fence_array *array = to_fence_array(sync_file->fence); + if (dma_fence_is_array(sync_file->fence)) { + struct dma_fence_array *array = to_dma_fence_array(sync_file->fence); for (i = 0; i < array->num_fences; ++i) sync_print_fence(s, array->fences[i], true); diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h index d269aa6783aa..26fe8b9907b3 100644 --- a/drivers/dma-buf/sync_debug.h +++ b/drivers/dma-buf/sync_debug.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -45,10 +45,9 @@ struct sync_timeline { struct list_head sync_timeline_list; }; -static inline struct sync_timeline *fence_parent(struct fence *fence) +static inline struct sync_timeline *dma_fence_parent(struct dma_fence *fence) { - return container_of(fence->lock, struct sync_timeline, - child_list_lock); + return container_of(fence->lock, struct sync_timeline, child_list_lock); } /** @@ -58,7 +57,7 @@ static inline struct sync_timeline *fence_parent(struct fence *fence) * @active_list: sync timeline active child's list */ struct sync_pt { - struct fence base; + struct dma_fence base; struct list_head child_list; struct list_head active_list; }; diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 235f8ac113cc..69d8ef98d34c 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -54,7 +54,7 @@ err: return NULL; } -static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) +static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb) { struct sync_file *sync_file; @@ -71,7 +71,7 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) * takes ownership of @fence. The sync_file can be released with * fput(sync_file->file). Returns the sync_file or NULL in case of error. */ -struct sync_file *sync_file_create(struct fence *fence) +struct sync_file *sync_file_create(struct dma_fence *fence) { struct sync_file *sync_file; @@ -79,7 +79,7 @@ struct sync_file *sync_file_create(struct fence *fence) if (!sync_file) return NULL; - sync_file->fence = fence_get(fence); + sync_file->fence = dma_fence_get(fence); snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d", fence->ops->get_driver_name(fence), @@ -121,16 +121,16 @@ err: * Ensures @fd references a valid sync_file and returns a fence that * represents all fence in the sync_file. On error NULL is returned. */ -struct fence *sync_file_get_fence(int fd) +struct dma_fence *sync_file_get_fence(int fd) { struct sync_file *sync_file; - struct fence *fence; + struct dma_fence *fence; sync_file = sync_file_fdget(fd); if (!sync_file) return NULL; - fence = fence_get(sync_file->fence); + fence = dma_fence_get(sync_file->fence); fput(sync_file->file); return fence; @@ -138,22 +138,23 @@ struct fence *sync_file_get_fence(int fd) EXPORT_SYMBOL(sync_file_get_fence); static int sync_file_set_fence(struct sync_file *sync_file, - struct fence **fences, int num_fences) + struct dma_fence **fences, int num_fences) { - struct fence_array *array; + struct dma_fence_array *array; /* * The reference for the fences in the new sync_file and held * in add_fence() during the merge procedure, so for num_fences == 1 * we already own a new reference to the fence. For num_fence > 1 - * we own the reference of the fence_array creation. + * we own the reference of the dma_fence_array creation. */ if (num_fences == 1) { sync_file->fence = fences[0]; kfree(fences); } else { - array = fence_array_create(num_fences, fences, - fence_context_alloc(1), 1, false); + array = dma_fence_array_create(num_fences, fences, + dma_fence_context_alloc(1), + 1, false); if (!array) return -ENOMEM; @@ -163,10 +164,11 @@ static int sync_file_set_fence(struct sync_file *sync_file, return 0; } -static struct fence **get_fences(struct sync_file *sync_file, int *num_fences) +static struct dma_fence **get_fences(struct sync_file *sync_file, + int *num_fences) { - if (fence_is_array(sync_file->fence)) { - struct fence_array *array = to_fence_array(sync_file->fence); + if (dma_fence_is_array(sync_file->fence)) { + struct dma_fence_array *array = to_dma_fence_array(sync_file->fence); *num_fences = array->num_fences; return array->fences; @@ -176,12 +178,13 @@ static struct fence **get_fences(struct sync_file *sync_file, int *num_fences) return &sync_file->fence; } -static void add_fence(struct fence **fences, int *i, struct fence *fence) +static void add_fence(struct dma_fence **fences, + int *i, struct dma_fence *fence) { fences[*i] = fence; - if (!fence_is_signaled(fence)) { - fence_get(fence); + if (!dma_fence_is_signaled(fence)) { + dma_fence_get(fence); (*i)++; } } @@ -200,7 +203,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, struct sync_file *b) { struct sync_file *sync_file; - struct fence **fences, **nfences, **a_fences, **b_fences; + struct dma_fence **fences, **nfences, **a_fences, **b_fences; int i, i_a, i_b, num_fences, a_num_fences, b_num_fences; sync_file = sync_file_alloc(); @@ -226,8 +229,8 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, * and sync_file_create, this is a reasonable assumption. */ for (i = i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) { - struct fence *pt_a = a_fences[i_a]; - struct fence *pt_b = b_fences[i_b]; + struct dma_fence *pt_a = a_fences[i_a]; + struct dma_fence *pt_b = b_fences[i_b]; if (pt_a->context < pt_b->context) { add_fence(fences, &i, pt_a); @@ -255,7 +258,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, add_fence(fences, &i, b_fences[i_b]); if (i == 0) - fences[i++] = fence_get(a_fences[0]); + fences[i++] = dma_fence_get(a_fences[0]); if (num_fences > i) { nfences = krealloc(fences, i * sizeof(*fences), @@ -286,8 +289,8 @@ static void sync_file_free(struct kref *kref) kref); if (test_bit(POLL_ENABLED, &sync_file->fence->flags)) - fence_remove_callback(sync_file->fence, &sync_file->cb); - fence_put(sync_file->fence); + dma_fence_remove_callback(sync_file->fence, &sync_file->cb); + dma_fence_put(sync_file->fence); kfree(sync_file); } @@ -307,12 +310,12 @@ static unsigned int sync_file_poll(struct file *file, poll_table *wait) if (!poll_does_not_wait(wait) && !test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) { - if (fence_add_callback(sync_file->fence, &sync_file->cb, - fence_check_cb_func) < 0) + if (dma_fence_add_callback(sync_file->fence, &sync_file->cb, + fence_check_cb_func) < 0) wake_up_all(&sync_file->wq); } - return fence_is_signaled(sync_file->fence) ? POLLIN : 0; + return dma_fence_is_signaled(sync_file->fence) ? POLLIN : 0; } static long sync_file_ioctl_merge(struct sync_file *sync_file, @@ -370,14 +373,14 @@ err_put_fd: return err; } -static void sync_fill_fence_info(struct fence *fence, +static void sync_fill_fence_info(struct dma_fence *fence, struct sync_fence_info *info) { strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), sizeof(info->obj_name)); strlcpy(info->driver_name, fence->ops->get_driver_name(fence), sizeof(info->driver_name)); - if (fence_is_signaled(fence)) + if (dma_fence_is_signaled(fence)) info->status = fence->status >= 0 ? 1 : fence->status; else info->status = 0; @@ -389,7 +392,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, { struct sync_file_info info; struct sync_fence_info *fence_info = NULL; - struct fence **fences; + struct dma_fence **fences; __u32 size; int num_fences, ret, i; @@ -429,7 +432,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, no_fences: strlcpy(info.name, sync_file->name, sizeof(info.name)); - info.status = fence_is_signaled(sync_file->fence); + info.status = dma_fence_is_signaled(sync_file->fence); info.num_fences = num_fences; if (copy_to_user((void __user *)arg, &info, sizeof(info))) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 039b57e4644c..283d05927d15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include @@ -378,7 +378,7 @@ struct amdgpu_fence_driver { struct timer_list fallback_timer; unsigned num_fences_mask; spinlock_t lock; - struct fence **fences; + struct dma_fence **fences; }; /* some special values for the owner field */ @@ -399,7 +399,7 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, unsigned irq_type); void amdgpu_fence_driver_suspend(struct amdgpu_device *adev); void amdgpu_fence_driver_resume(struct amdgpu_device *adev); -int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **fence); +int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence); void amdgpu_fence_process(struct amdgpu_ring *ring); int amdgpu_fence_wait_empty(struct amdgpu_ring *ring); unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); @@ -427,7 +427,7 @@ struct amdgpu_bo_va_mapping { struct amdgpu_bo_va { /* protected by bo being reserved */ struct list_head bo_list; - struct fence *last_pt_update; + struct dma_fence *last_pt_update; unsigned ref_count; /* protected by vm mutex and spinlock */ @@ -543,7 +543,7 @@ struct amdgpu_sa_bo { struct amdgpu_sa_manager *manager; unsigned soffset; unsigned eoffset; - struct fence *fence; + struct dma_fence *fence; }; /* @@ -566,19 +566,19 @@ int amdgpu_mode_dumb_mmap(struct drm_file *filp, */ struct amdgpu_sync { DECLARE_HASHTABLE(fences, 4); - struct fence *last_vm_update; + struct dma_fence *last_vm_update; }; void amdgpu_sync_create(struct amdgpu_sync *sync); int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, - struct fence *f); + struct dma_fence *f); int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, struct reservation_object *resv, void *owner); -struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, +struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, struct amdgpu_ring *ring); -struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync); +struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync); void amdgpu_sync_free(struct amdgpu_sync *sync); int amdgpu_sync_init(void); void amdgpu_sync_fini(void); @@ -703,10 +703,10 @@ struct amdgpu_flip_work { uint64_t base; struct drm_pending_vblank_event *event; struct amdgpu_bo *old_abo; - struct fence *excl; + struct dma_fence *excl; unsigned shared_count; - struct fence **shared; - struct fence_cb cb; + struct dma_fence **shared; + struct dma_fence_cb cb; bool async; }; @@ -742,7 +742,7 @@ void amdgpu_job_free_resources(struct amdgpu_job *job); void amdgpu_job_free(struct amdgpu_job *job); int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, struct amd_sched_entity *entity, void *owner, - struct fence **f); + struct dma_fence **f); struct amdgpu_ring { struct amdgpu_device *adev; @@ -844,7 +844,7 @@ struct amdgpu_vm { /* contains the page directory */ struct amdgpu_bo *page_directory; unsigned max_pde_used; - struct fence *page_directory_fence; + struct dma_fence *page_directory_fence; uint64_t last_eviction_counter; /* array of page tables, one for each page directory entry */ @@ -865,14 +865,14 @@ struct amdgpu_vm { struct amdgpu_vm_id { struct list_head list; - struct fence *first; + struct dma_fence *first; struct amdgpu_sync active; - struct fence *last_flush; + struct dma_fence *last_flush; atomic64_t owner; uint64_t pd_gpu_addr; /* last flushed PD/PT update */ - struct fence *flushed_updates; + struct dma_fence *flushed_updates; uint32_t current_gpu_reset_count; @@ -921,7 +921,7 @@ void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, struct amdgpu_vm *vm); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, - struct amdgpu_sync *sync, struct fence *fence, + struct amdgpu_sync *sync, struct dma_fence *fence, struct amdgpu_job *job); int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job); void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id); @@ -957,7 +957,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, struct amdgpu_ctx_ring { uint64_t sequence; - struct fence **fences; + struct dma_fence **fences; struct amd_sched_entity entity; }; @@ -966,7 +966,7 @@ struct amdgpu_ctx { struct amdgpu_device *adev; unsigned reset_counter; spinlock_t ring_lock; - struct fence **fences; + struct dma_fence **fences; struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS]; bool preamble_presented; }; @@ -982,8 +982,8 @@ struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id); int amdgpu_ctx_put(struct amdgpu_ctx *ctx); uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, - struct fence *fence); -struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, + struct dma_fence *fence); +struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, uint64_t seq); int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, @@ -1181,10 +1181,10 @@ struct amdgpu_gfx { int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned size, struct amdgpu_ib *ib); void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, - struct fence *f); + struct dma_fence *f); int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, - struct amdgpu_ib *ib, struct fence *last_vm_update, - struct amdgpu_job *job, struct fence **f); + struct amdgpu_ib *ib, struct dma_fence *last_vm_update, + struct amdgpu_job *job, struct dma_fence **f); int amdgpu_ib_pool_init(struct amdgpu_device *adev); void amdgpu_ib_pool_fini(struct amdgpu_device *adev); int amdgpu_ib_ring_tests(struct amdgpu_device *adev); @@ -1225,7 +1225,7 @@ struct amdgpu_cs_parser { struct amdgpu_bo_list *bo_list; struct amdgpu_bo_list_entry vm_pd; struct list_head validated; - struct fence *fence; + struct dma_fence *fence; uint64_t bytes_moved_threshold; uint64_t bytes_moved; struct amdgpu_bo_list_entry *evictable; @@ -1245,7 +1245,7 @@ struct amdgpu_job { struct amdgpu_ring *ring; struct amdgpu_sync sync; struct amdgpu_ib *ibs; - struct fence *fence; /* the hw fence */ + struct dma_fence *fence; /* the hw fence */ uint32_t preamble_status; uint32_t num_ibs; void *owner; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c index 345305235349..cc97eee93226 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c @@ -33,7 +33,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size, { unsigned long start_jiffies; unsigned long end_jiffies; - struct fence *fence = NULL; + struct dma_fence *fence = NULL; int i, r; start_jiffies = jiffies; @@ -43,17 +43,17 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size, false); if (r) goto exit_do_move; - r = fence_wait(fence, false); + r = dma_fence_wait(fence, false); if (r) goto exit_do_move; - fence_put(fence); + dma_fence_put(fence); } end_jiffies = jiffies; r = jiffies_to_msecs(end_jiffies - start_jiffies); exit_do_move: if (fence) - fence_put(fence); + dma_fence_put(fence); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index b0f6e6957536..5d582265e929 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -719,7 +719,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo ttm_eu_backoff_reservation(&parser->ticket, &parser->validated); } - fence_put(parser->fence); + dma_fence_put(parser->fence); if (parser->ctx) amdgpu_ctx_put(parser->ctx); @@ -756,7 +756,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, if (p->bo_list) { for (i = 0; i < p->bo_list->num_entries; i++) { - struct fence *f; + struct dma_fence *f; /* ignore duplicates */ bo = p->bo_list->array[i].robj; @@ -956,7 +956,7 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, for (j = 0; j < num_deps; ++j) { struct amdgpu_ring *ring; struct amdgpu_ctx *ctx; - struct fence *fence; + struct dma_fence *fence; r = amdgpu_cs_get_ring(adev, deps[j].ip_type, deps[j].ip_instance, @@ -978,7 +978,7 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, } else if (fence) { r = amdgpu_sync_fence(adev, &p->job->sync, fence); - fence_put(fence); + dma_fence_put(fence); amdgpu_ctx_put(ctx); if (r) return r; @@ -1008,7 +1008,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, job->owner = p->filp; job->fence_ctx = entity->fence_context; - p->fence = fence_get(&job->base.s_fence->finished); + p->fence = dma_fence_get(&job->base.s_fence->finished); cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, p->fence); job->uf_sequence = cs->out.handle; amdgpu_job_free_resources(job); @@ -1091,7 +1091,7 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout); struct amdgpu_ring *ring = NULL; struct amdgpu_ctx *ctx; - struct fence *fence; + struct dma_fence *fence; long r; r = amdgpu_cs_get_ring(adev, wait->in.ip_type, wait->in.ip_instance, @@ -1107,8 +1107,8 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, if (IS_ERR(fence)) r = PTR_ERR(fence); else if (fence) { - r = fence_wait_timeout(fence, true, timeout); - fence_put(fence); + r = dma_fence_wait_timeout(fence, true, timeout); + dma_fence_put(fence); } else r = 1; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index a5e2fcbef0f0..99bbc860322f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -35,7 +35,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx) kref_init(&ctx->refcount); spin_lock_init(&ctx->ring_lock); ctx->fences = kcalloc(amdgpu_sched_jobs * AMDGPU_MAX_RINGS, - sizeof(struct fence*), GFP_KERNEL); + sizeof(struct dma_fence*), GFP_KERNEL); if (!ctx->fences) return -ENOMEM; @@ -79,7 +79,7 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx) for (i = 0; i < AMDGPU_MAX_RINGS; ++i) for (j = 0; j < amdgpu_sched_jobs; ++j) - fence_put(ctx->rings[i].fences[j]); + dma_fence_put(ctx->rings[i].fences[j]); kfree(ctx->fences); ctx->fences = NULL; @@ -241,39 +241,39 @@ int amdgpu_ctx_put(struct amdgpu_ctx *ctx) } uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, - struct fence *fence) + struct dma_fence *fence) { struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx]; uint64_t seq = cring->sequence; unsigned idx = 0; - struct fence *other = NULL; + struct dma_fence *other = NULL; idx = seq & (amdgpu_sched_jobs - 1); other = cring->fences[idx]; if (other) { signed long r; - r = fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT); + r = dma_fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT); if (r < 0) DRM_ERROR("Error (%ld) waiting for fence!\n", r); } - fence_get(fence); + dma_fence_get(fence); spin_lock(&ctx->ring_lock); cring->fences[idx] = fence; cring->sequence++; spin_unlock(&ctx->ring_lock); - fence_put(other); + dma_fence_put(other); return seq; } -struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, - struct amdgpu_ring *ring, uint64_t seq) +struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, + struct amdgpu_ring *ring, uint64_t seq) { struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx]; - struct fence *fence; + struct dma_fence *fence; spin_lock(&ctx->ring_lock); @@ -288,7 +288,7 @@ struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, return NULL; } - fence = fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]); + fence = dma_fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]); spin_unlock(&ctx->ring_lock); return fence; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b4f4a9239069..0262b43c8f0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1599,7 +1599,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->vm_manager.vm_pte_funcs = NULL; adev->vm_manager.vm_pte_num_rings = 0; adev->gart.gart_funcs = NULL; - adev->fence_context = fence_context_alloc(AMDGPU_MAX_RINGS); + adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS); adev->smc_rreg = &amdgpu_invalid_rreg; adev->smc_wreg = &amdgpu_invalid_wreg; @@ -2193,7 +2193,7 @@ bool amdgpu_need_backup(struct amdgpu_device *adev) static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, - struct fence **fence) + struct dma_fence **fence) { uint32_t domain; int r; @@ -2312,30 +2312,30 @@ retry: if (need_full_reset && amdgpu_need_backup(adev)) { struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; struct amdgpu_bo *bo, *tmp; - struct fence *fence = NULL, *next = NULL; + struct dma_fence *fence = NULL, *next = NULL; DRM_INFO("recover vram bo from shadow\n"); mutex_lock(&adev->shadow_list_lock); list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) { amdgpu_recover_vram_from_shadow(adev, ring, bo, &next); if (fence) { - r = fence_wait(fence, false); + r = dma_fence_wait(fence, false); if (r) { WARN(r, "recovery from shadow isn't comleted\n"); break; } } - fence_put(fence); + dma_fence_put(fence); fence = next; } mutex_unlock(&adev->shadow_list_lock); if (fence) { - r = fence_wait(fence, false); + r = dma_fence_wait(fence, false); if (r) WARN(r, "recovery from shadow isn't comleted\n"); } - fence_put(fence); + dma_fence_put(fence); } for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { struct amdgpu_ring *ring = adev->rings[i]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 083e2b429872..075c0d7db205 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -35,29 +35,29 @@ #include #include -static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb) +static void amdgpu_flip_callback(struct dma_fence *f, struct dma_fence_cb *cb) { struct amdgpu_flip_work *work = container_of(cb, struct amdgpu_flip_work, cb); - fence_put(f); + dma_fence_put(f); schedule_work(&work->flip_work.work); } static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work, - struct fence **f) + struct dma_fence **f) { - struct fence *fence= *f; + struct dma_fence *fence= *f; if (fence == NULL) return false; *f = NULL; - if (!fence_add_callback(fence, &work->cb, amdgpu_flip_callback)) + if (!dma_fence_add_callback(fence, &work->cb, amdgpu_flip_callback)) return true; - fence_put(fence); + dma_fence_put(fence); return false; } @@ -244,9 +244,9 @@ unreserve: cleanup: amdgpu_bo_unref(&work->old_abo); - fence_put(work->excl); + dma_fence_put(work->excl); for (i = 0; i < work->shared_count; ++i) - fence_put(work->shared[i]); + dma_fence_put(work->shared[i]); kfree(work->shared); kfree(work); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 3a2e42f4b897..57552c79ec58 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -48,7 +48,7 @@ */ struct amdgpu_fence { - struct fence base; + struct dma_fence base; /* RB, DMA, etc. */ struct amdgpu_ring *ring; @@ -73,8 +73,8 @@ void amdgpu_fence_slab_fini(void) /* * Cast helper */ -static const struct fence_ops amdgpu_fence_ops; -static inline struct amdgpu_fence *to_amdgpu_fence(struct fence *f) +static const struct dma_fence_ops amdgpu_fence_ops; +static inline struct amdgpu_fence *to_amdgpu_fence(struct dma_fence *f) { struct amdgpu_fence *__f = container_of(f, struct amdgpu_fence, base); @@ -130,11 +130,11 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring) * Emits a fence command on the requested ring (all asics). * Returns 0 on success, -ENOMEM on failure. */ -int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f) +int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f) { struct amdgpu_device *adev = ring->adev; struct amdgpu_fence *fence; - struct fence *old, **ptr; + struct dma_fence *old, **ptr; uint32_t seq; fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL); @@ -143,10 +143,10 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f) seq = ++ring->fence_drv.sync_seq; fence->ring = ring; - fence_init(&fence->base, &amdgpu_fence_ops, - &ring->fence_drv.lock, - adev->fence_context + ring->idx, - seq); + dma_fence_init(&fence->base, &amdgpu_fence_ops, + &ring->fence_drv.lock, + adev->fence_context + ring->idx, + seq); amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, seq, AMDGPU_FENCE_FLAG_INT); @@ -155,12 +155,12 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f) * emitting the fence would mess up the hardware ring buffer. */ old = rcu_dereference_protected(*ptr, 1); - if (old && !fence_is_signaled(old)) { + if (old && !dma_fence_is_signaled(old)) { DRM_INFO("rcu slot is busy\n"); - fence_wait(old, false); + dma_fence_wait(old, false); } - rcu_assign_pointer(*ptr, fence_get(&fence->base)); + rcu_assign_pointer(*ptr, dma_fence_get(&fence->base)); *f = &fence->base; @@ -211,7 +211,7 @@ void amdgpu_fence_process(struct amdgpu_ring *ring) seq &= drv->num_fences_mask; do { - struct fence *fence, **ptr; + struct dma_fence *fence, **ptr; ++last_seq; last_seq &= drv->num_fences_mask; @@ -224,13 +224,13 @@ void amdgpu_fence_process(struct amdgpu_ring *ring) if (!fence) continue; - r = fence_signal(fence); + r = dma_fence_signal(fence); if (!r) - FENCE_TRACE(fence, "signaled from irq context\n"); + DMA_FENCE_TRACE(fence, "signaled from irq context\n"); else BUG(); - fence_put(fence); + dma_fence_put(fence); } while (last_seq != seq); } @@ -260,7 +260,7 @@ static void amdgpu_fence_fallback(unsigned long arg) int amdgpu_fence_wait_empty(struct amdgpu_ring *ring) { uint64_t seq = ACCESS_ONCE(ring->fence_drv.sync_seq); - struct fence *fence, **ptr; + struct dma_fence *fence, **ptr; int r; if (!seq) @@ -269,14 +269,14 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring) ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; rcu_read_lock(); fence = rcu_dereference(*ptr); - if (!fence || !fence_get_rcu(fence)) { + if (!fence || !dma_fence_get_rcu(fence)) { rcu_read_unlock(); return 0; } rcu_read_unlock(); - r = fence_wait(fence, false); - fence_put(fence); + r = dma_fence_wait(fence, false); + dma_fence_put(fence); return r; } @@ -452,7 +452,7 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev) amd_sched_fini(&ring->sched); del_timer_sync(&ring->fence_drv.fallback_timer); for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j) - fence_put(ring->fence_drv.fences[j]); + dma_fence_put(ring->fence_drv.fences[j]); kfree(ring->fence_drv.fences); ring->fence_drv.fences = NULL; ring->fence_drv.initialized = false; @@ -541,12 +541,12 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev) * Common fence implementation */ -static const char *amdgpu_fence_get_driver_name(struct fence *fence) +static const char *amdgpu_fence_get_driver_name(struct dma_fence *fence) { return "amdgpu"; } -static const char *amdgpu_fence_get_timeline_name(struct fence *f) +static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f) { struct amdgpu_fence *fence = to_amdgpu_fence(f); return (const char *)fence->ring->name; @@ -560,7 +560,7 @@ static const char *amdgpu_fence_get_timeline_name(struct fence *f) * to fence_queue that checks if this fence is signaled, and if so it * signals the fence and removes itself. */ -static bool amdgpu_fence_enable_signaling(struct fence *f) +static bool amdgpu_fence_enable_signaling(struct dma_fence *f) { struct amdgpu_fence *fence = to_amdgpu_fence(f); struct amdgpu_ring *ring = fence->ring; @@ -568,7 +568,7 @@ static bool amdgpu_fence_enable_signaling(struct fence *f) if (!timer_pending(&ring->fence_drv.fallback_timer)) amdgpu_fence_schedule_fallback(ring); - FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx); + DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx); return true; } @@ -582,7 +582,7 @@ static bool amdgpu_fence_enable_signaling(struct fence *f) */ static void amdgpu_fence_free(struct rcu_head *rcu) { - struct fence *f = container_of(rcu, struct fence, rcu); + struct dma_fence *f = container_of(rcu, struct dma_fence, rcu); struct amdgpu_fence *fence = to_amdgpu_fence(f); kmem_cache_free(amdgpu_fence_slab, fence); } @@ -595,16 +595,16 @@ static void amdgpu_fence_free(struct rcu_head *rcu) * This function is called when the reference count becomes zero. * It just RCU schedules freeing up the fence. */ -static void amdgpu_fence_release(struct fence *f) +static void amdgpu_fence_release(struct dma_fence *f) { call_rcu(&f->rcu, amdgpu_fence_free); } -static const struct fence_ops amdgpu_fence_ops = { +static const struct dma_fence_ops amdgpu_fence_ops = { .get_driver_name = amdgpu_fence_get_driver_name, .get_timeline_name = amdgpu_fence_get_timeline_name, .enable_signaling = amdgpu_fence_enable_signaling, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .release = amdgpu_fence_release, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 6a6c86c9c169..c3672dfcfd6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -89,7 +89,7 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, * Free an IB (all asics). */ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, - struct fence *f) + struct dma_fence *f) { amdgpu_sa_bo_free(adev, &ib->sa_bo, f); } @@ -116,8 +116,8 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, * to SI there was just a DE IB. */ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, - struct amdgpu_ib *ibs, struct fence *last_vm_update, - struct amdgpu_job *job, struct fence **f) + struct amdgpu_ib *ibs, struct dma_fence *last_vm_update, + struct amdgpu_job *job, struct dma_fence **f) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib *ib = &ibs[0]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 8c5807994073..a0de6286c453 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -81,7 +81,7 @@ int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size, void amdgpu_job_free_resources(struct amdgpu_job *job) { - struct fence *f; + struct dma_fence *f; unsigned i; /* use sched fence if available */ @@ -95,7 +95,7 @@ static void amdgpu_job_free_cb(struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base); - fence_put(job->fence); + dma_fence_put(job->fence); amdgpu_sync_free(&job->sync); kfree(job); } @@ -104,14 +104,14 @@ void amdgpu_job_free(struct amdgpu_job *job) { amdgpu_job_free_resources(job); - fence_put(job->fence); + dma_fence_put(job->fence); amdgpu_sync_free(&job->sync); kfree(job); } int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, struct amd_sched_entity *entity, void *owner, - struct fence **f) + struct dma_fence **f) { int r; job->ring = ring; @@ -125,19 +125,19 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, job->owner = owner; job->fence_ctx = entity->fence_context; - *f = fence_get(&job->base.s_fence->finished); + *f = dma_fence_get(&job->base.s_fence->finished); amdgpu_job_free_resources(job); amd_sched_entity_push_job(&job->base); return 0; } -static struct fence *amdgpu_job_dependency(struct amd_sched_job *sched_job) +static struct dma_fence *amdgpu_job_dependency(struct amd_sched_job *sched_job) { struct amdgpu_job *job = to_amdgpu_job(sched_job); struct amdgpu_vm *vm = job->vm; - struct fence *fence = amdgpu_sync_get_fence(&job->sync); + struct dma_fence *fence = amdgpu_sync_get_fence(&job->sync); if (fence == NULL && vm && !job->vm_id) { struct amdgpu_ring *ring = job->ring; @@ -155,9 +155,9 @@ static struct fence *amdgpu_job_dependency(struct amd_sched_job *sched_job) return fence; } -static struct fence *amdgpu_job_run(struct amd_sched_job *sched_job) +static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job) { - struct fence *fence = NULL; + struct dma_fence *fence = NULL; struct amdgpu_job *job; int r; @@ -176,8 +176,8 @@ static struct fence *amdgpu_job_run(struct amd_sched_job *sched_job) DRM_ERROR("Error scheduling IBs (%d)\n", r); /* if gpu reset, hw fence will be replaced here */ - fence_put(job->fence); - job->fence = fence_get(fence); + dma_fence_put(job->fence); + job->fence = dma_fence_get(fence); amdgpu_job_free_resources(job); return fence; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index aa074fac0c7f..55e142a5ff5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -383,7 +383,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, if (flags & AMDGPU_GEM_CREATE_VRAM_CLEARED && bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) { - struct fence *fence; + struct dma_fence *fence; if (adev->mman.buffer_funcs_ring == NULL || !adev->mman.buffer_funcs_ring->ready) { @@ -403,9 +403,9 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence); amdgpu_bo_fence(bo, fence, false); amdgpu_bo_unreserve(bo); - fence_put(bo->tbo.moving); - bo->tbo.moving = fence_get(fence); - fence_put(fence); + dma_fence_put(bo->tbo.moving); + bo->tbo.moving = dma_fence_get(fence); + dma_fence_put(fence); } *bo_ptr = bo; @@ -491,7 +491,7 @@ int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, struct reservation_object *resv, - struct fence **fence, + struct dma_fence **fence, bool direct) { @@ -523,7 +523,7 @@ int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, struct reservation_object *resv, - struct fence **fence, + struct dma_fence **fence, bool direct) { @@ -926,7 +926,7 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) * @shared: true if fence should be added shared * */ -void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence, +void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared) { struct reservation_object *resv = bo->tbo.resv; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 8255034d73eb..3e785ed3cb4b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -156,19 +156,19 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem); int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); -void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence, +void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared); u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo); int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, struct reservation_object *resv, - struct fence **fence, bool direct); + struct dma_fence **fence, bool direct); int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, struct reservation_object *resv, - struct fence **fence, + struct dma_fence **fence, bool direct); @@ -200,7 +200,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, unsigned size, unsigned align); void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo, - struct fence *fence); + struct dma_fence *fence); #if defined(CONFIG_DEBUG_FS) void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, struct seq_file *m); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c index d8af37a845f4..fd26c4b8d793 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c @@ -147,7 +147,7 @@ static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo) } list_del_init(&sa_bo->olist); list_del_init(&sa_bo->flist); - fence_put(sa_bo->fence); + dma_fence_put(sa_bo->fence); kfree(sa_bo); } @@ -161,7 +161,7 @@ static void amdgpu_sa_bo_try_free(struct amdgpu_sa_manager *sa_manager) sa_bo = list_entry(sa_manager->hole->next, struct amdgpu_sa_bo, olist); list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) { if (sa_bo->fence == NULL || - !fence_is_signaled(sa_bo->fence)) { + !dma_fence_is_signaled(sa_bo->fence)) { return; } amdgpu_sa_bo_remove_locked(sa_bo); @@ -244,7 +244,7 @@ static bool amdgpu_sa_event(struct amdgpu_sa_manager *sa_manager, } static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager, - struct fence **fences, + struct dma_fence **fences, unsigned *tries) { struct amdgpu_sa_bo *best_bo = NULL; @@ -272,7 +272,7 @@ static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager, sa_bo = list_first_entry(&sa_manager->flist[i], struct amdgpu_sa_bo, flist); - if (!fence_is_signaled(sa_bo->fence)) { + if (!dma_fence_is_signaled(sa_bo->fence)) { fences[i] = sa_bo->fence; continue; } @@ -314,7 +314,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, struct amdgpu_sa_bo **sa_bo, unsigned size, unsigned align) { - struct fence *fences[AMDGPU_SA_NUM_FENCE_LISTS]; + struct dma_fence *fences[AMDGPU_SA_NUM_FENCE_LISTS]; unsigned tries[AMDGPU_SA_NUM_FENCE_LISTS]; unsigned count; int i, r; @@ -356,14 +356,14 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, for (i = 0, count = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i) if (fences[i]) - fences[count++] = fence_get(fences[i]); + fences[count++] = dma_fence_get(fences[i]); if (count) { spin_unlock(&sa_manager->wq.lock); - t = fence_wait_any_timeout(fences, count, false, - MAX_SCHEDULE_TIMEOUT); + t = dma_fence_wait_any_timeout(fences, count, false, + MAX_SCHEDULE_TIMEOUT); for (i = 0; i < count; ++i) - fence_put(fences[i]); + dma_fence_put(fences[i]); r = (t > 0) ? 0 : t; spin_lock(&sa_manager->wq.lock); @@ -384,7 +384,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, } void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo, - struct fence *fence) + struct dma_fence *fence) { struct amdgpu_sa_manager *sa_manager; @@ -394,10 +394,10 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo, sa_manager = (*sa_bo)->manager; spin_lock(&sa_manager->wq.lock); - if (fence && !fence_is_signaled(fence)) { + if (fence && !dma_fence_is_signaled(fence)) { uint32_t idx; - (*sa_bo)->fence = fence_get(fence); + (*sa_bo)->fence = dma_fence_get(fence); idx = fence->context % AMDGPU_SA_NUM_FENCE_LISTS; list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[idx]); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c index 5c8d3022fb87..ed814e6d0207 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c @@ -34,7 +34,7 @@ struct amdgpu_sync_entry { struct hlist_node node; - struct fence *fence; + struct dma_fence *fence; }; static struct kmem_cache *amdgpu_sync_slab; @@ -60,7 +60,8 @@ void amdgpu_sync_create(struct amdgpu_sync *sync) * * Test if the fence was issued by us. */ -static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f) +static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, + struct dma_fence *f) { struct amd_sched_fence *s_fence = to_amd_sched_fence(f); @@ -81,7 +82,7 @@ static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f) * * Extract who originally created the fence. */ -static void *amdgpu_sync_get_owner(struct fence *f) +static void *amdgpu_sync_get_owner(struct dma_fence *f) { struct amd_sched_fence *s_fence = to_amd_sched_fence(f); @@ -99,13 +100,14 @@ static void *amdgpu_sync_get_owner(struct fence *f) * * Either keep the existing fence or the new one, depending which one is later. */ -static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence) +static void amdgpu_sync_keep_later(struct dma_fence **keep, + struct dma_fence *fence) { - if (*keep && fence_is_later(*keep, fence)) + if (*keep && dma_fence_is_later(*keep, fence)) return; - fence_put(*keep); - *keep = fence_get(fence); + dma_fence_put(*keep); + *keep = dma_fence_get(fence); } /** @@ -117,7 +119,7 @@ static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence) * Tries to add the fence to an existing hash entry. Returns true when an entry * was found, false otherwise. */ -static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct fence *f) +static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f) { struct amdgpu_sync_entry *e; @@ -139,7 +141,7 @@ static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct fence *f) * */ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, - struct fence *f) + struct dma_fence *f) { struct amdgpu_sync_entry *e; @@ -158,7 +160,7 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, return -ENOMEM; hash_add(sync->fences, &e->node, f->context); - e->fence = fence_get(f); + e->fence = dma_fence_get(f); return 0; } @@ -177,7 +179,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, void *owner) { struct reservation_object_list *flist; - struct fence *f; + struct dma_fence *f; void *fence_owner; unsigned i; int r = 0; @@ -231,15 +233,15 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, * Returns the next fence not signaled yet without removing it from the sync * object. */ -struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, - struct amdgpu_ring *ring) +struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, + struct amdgpu_ring *ring) { struct amdgpu_sync_entry *e; struct hlist_node *tmp; int i; hash_for_each_safe(sync->fences, i, tmp, e, node) { - struct fence *f = e->fence; + struct dma_fence *f = e->fence; struct amd_sched_fence *s_fence = to_amd_sched_fence(f); if (ring && s_fence) { @@ -247,16 +249,16 @@ struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, * when they are scheduled. */ if (s_fence->sched == &ring->sched) { - if (fence_is_signaled(&s_fence->scheduled)) + if (dma_fence_is_signaled(&s_fence->scheduled)) continue; return &s_fence->scheduled; } } - if (fence_is_signaled(f)) { + if (dma_fence_is_signaled(f)) { hash_del(&e->node); - fence_put(f); + dma_fence_put(f); kmem_cache_free(amdgpu_sync_slab, e); continue; } @@ -274,11 +276,11 @@ struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, * * Get and removes the next fence from the sync object not signaled yet. */ -struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync) +struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync) { struct amdgpu_sync_entry *e; struct hlist_node *tmp; - struct fence *f; + struct dma_fence *f; int i; hash_for_each_safe(sync->fences, i, tmp, e, node) { @@ -288,10 +290,10 @@ struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync) hash_del(&e->node); kmem_cache_free(amdgpu_sync_slab, e); - if (!fence_is_signaled(f)) + if (!dma_fence_is_signaled(f)) return f; - fence_put(f); + dma_fence_put(f); } return NULL; } @@ -311,11 +313,11 @@ void amdgpu_sync_free(struct amdgpu_sync *sync) hash_for_each_safe(sync->fences, i, tmp, e, node) { hash_del(&e->node); - fence_put(e->fence); + dma_fence_put(e->fence); kmem_cache_free(amdgpu_sync_slab, e); } - fence_put(sync->last_vm_update); + dma_fence_put(sync->last_vm_update); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c index b827c75e95de..e05a24325eeb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c @@ -78,7 +78,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) void *gtt_map, *vram_map; void **gtt_start, **gtt_end; void **vram_start, **vram_end; - struct fence *fence = NULL; + struct dma_fence *fence = NULL; r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_GTT, 0, NULL, @@ -118,13 +118,13 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) goto out_lclean_unpin; } - r = fence_wait(fence, false); + r = dma_fence_wait(fence, false); if (r) { DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i); goto out_lclean_unpin; } - fence_put(fence); + dma_fence_put(fence); r = amdgpu_bo_kmap(vram_obj, &vram_map); if (r) { @@ -163,13 +163,13 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) goto out_lclean_unpin; } - r = fence_wait(fence, false); + r = dma_fence_wait(fence, false); if (r) { DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i); goto out_lclean_unpin; } - fence_put(fence); + dma_fence_put(fence); r = amdgpu_bo_kmap(gtt_obj[i], >t_map); if (r) { @@ -216,7 +216,7 @@ out_lclean: amdgpu_bo_unref(>t_obj[i]); } if (fence) - fence_put(fence); + dma_fence_put(fence); break; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 067e5e683bb3..bb964a8ff938 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -104,7 +104,7 @@ TRACE_EVENT(amdgpu_cs_ioctl, __field(struct amdgpu_device *, adev) __field(struct amd_sched_job *, sched_job) __field(struct amdgpu_ib *, ib) - __field(struct fence *, fence) + __field(struct dma_fence *, fence) __field(char *, ring_name) __field(u32, num_ibs) ), @@ -129,7 +129,7 @@ TRACE_EVENT(amdgpu_sched_run_job, __field(struct amdgpu_device *, adev) __field(struct amd_sched_job *, sched_job) __field(struct amdgpu_ib *, ib) - __field(struct fence *, fence) + __field(struct dma_fence *, fence) __field(char *, ring_name) __field(u32, num_ibs) ), diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index dcaf691f56b5..a743aeabc767 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -268,7 +268,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, struct amdgpu_device *adev; struct amdgpu_ring *ring; uint64_t old_start, new_start; - struct fence *fence; + struct dma_fence *fence; int r; adev = amdgpu_get_adev(bo->bdev); @@ -316,7 +316,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, return r; r = ttm_bo_pipeline_move(bo, fence, evict, new_mem); - fence_put(fence); + dma_fence_put(fence); return r; } @@ -1247,7 +1247,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t dst_offset, uint32_t byte_count, struct reservation_object *resv, - struct fence **fence, bool direct_submit) + struct dma_fence **fence, bool direct_submit) { struct amdgpu_device *adev = ring->adev; struct amdgpu_job *job; @@ -1294,7 +1294,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, if (direct_submit) { r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, NULL, NULL, fence); - job->fence = fence_get(*fence); + job->fence = dma_fence_get(*fence); if (r) DRM_ERROR("Error scheduling IBs (%d)\n", r); amdgpu_job_free(job); @@ -1315,7 +1315,7 @@ error_free: int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint32_t src_data, struct reservation_object *resv, - struct fence **fence) + struct dma_fence **fence) { struct amdgpu_device *adev = bo->adev; struct amdgpu_job *job; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 9812c805326c..3f293e189378 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -77,11 +77,11 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t dst_offset, uint32_t byte_count, struct reservation_object *resv, - struct fence **fence, bool direct_submit); + struct dma_fence **fence, bool direct_submit); int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint32_t src_data, struct reservation_object *resv, - struct fence **fence); + struct dma_fence **fence); int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); bool amdgpu_ttm_is_bound(struct ttm_tt *ttm); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index e3281cacc586..0f6575e7ef8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -333,7 +333,7 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp) for (i = 0; i < adev->uvd.max_handles; ++i) { uint32_t handle = atomic_read(&adev->uvd.handles[i]); if (handle != 0 && adev->uvd.filp[i] == filp) { - struct fence *fence; + struct dma_fence *fence; r = amdgpu_uvd_get_destroy_msg(ring, handle, false, &fence); @@ -342,8 +342,8 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp) continue; } - fence_wait(fence, false); - fence_put(fence); + dma_fence_wait(fence, false); + dma_fence_put(fence); adev->uvd.filp[i] = NULL; atomic_set(&adev->uvd.handles[i], 0); @@ -909,14 +909,14 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx) } static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, - bool direct, struct fence **fence) + bool direct, struct dma_fence **fence) { struct ttm_validate_buffer tv; struct ww_acquire_ctx ticket; struct list_head head; struct amdgpu_job *job; struct amdgpu_ib *ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; struct amdgpu_device *adev = ring->adev; uint64_t addr; int i, r; @@ -960,7 +960,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, if (direct) { r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); - job->fence = fence_get(f); + job->fence = dma_fence_get(f); if (r) goto err_free; @@ -975,9 +975,9 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, ttm_eu_fence_buffer_objects(&ticket, &head, f); if (fence) - *fence = fence_get(f); + *fence = dma_fence_get(f); amdgpu_bo_unref(&bo); - fence_put(f); + dma_fence_put(f); return 0; @@ -993,7 +993,7 @@ err: crash the vcpu so just try to emmit a dummy create/destroy msg to avoid this */ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct fence **fence) + struct dma_fence **fence) { struct amdgpu_device *adev = ring->adev; struct amdgpu_bo *bo; @@ -1042,7 +1042,7 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, } int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, - bool direct, struct fence **fence) + bool direct, struct dma_fence **fence) { struct amdgpu_device *adev = ring->adev; struct amdgpu_bo *bo; @@ -1128,7 +1128,7 @@ void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring) */ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout) { - struct fence *fence; + struct dma_fence *fence; long r; r = amdgpu_uvd_get_create_msg(ring, 1, NULL); @@ -1143,7 +1143,7 @@ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout) goto error; } - r = fence_wait_timeout(fence, false, timeout); + r = dma_fence_wait_timeout(fence, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out.\n"); r = -ETIMEDOUT; @@ -1154,7 +1154,7 @@ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout) r = 0; } - fence_put(fence); + dma_fence_put(fence); error: return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h index c850009602d1..6249ba1bde2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h @@ -29,9 +29,9 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev); int amdgpu_uvd_suspend(struct amdgpu_device *adev); int amdgpu_uvd_resume(struct amdgpu_device *adev); int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct fence **fence); + struct dma_fence **fence); int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, - bool direct, struct fence **fence); + bool direct, struct dma_fence **fence); void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp); int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 7fe8fd884f06..f0f8afb85585 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -395,12 +395,12 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp) * Open up a stream for HW test */ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct fence **fence) + struct dma_fence **fence) { const unsigned ib_size_dw = 1024; struct amdgpu_job *job; struct amdgpu_ib *ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; uint64_t dummy; int i, r; @@ -450,14 +450,14 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, ib->ptr[i] = 0x0; r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); - job->fence = fence_get(f); + job->fence = dma_fence_get(f); if (r) goto err; amdgpu_job_free(job); if (fence) - *fence = fence_get(f); - fence_put(f); + *fence = dma_fence_get(f); + dma_fence_put(f); return 0; err: @@ -476,12 +476,12 @@ err: * Close up a stream for HW test or if userspace failed to do so */ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, - bool direct, struct fence **fence) + bool direct, struct dma_fence **fence) { const unsigned ib_size_dw = 1024; struct amdgpu_job *job; struct amdgpu_ib *ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; int i, r; r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -513,7 +513,7 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, if (direct) { r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); - job->fence = fence_get(f); + job->fence = dma_fence_get(f); if (r) goto err; @@ -526,8 +526,8 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, } if (fence) - *fence = fence_get(f); - fence_put(f); + *fence = dma_fence_get(f); + dma_fence_put(f); return 0; err: @@ -883,7 +883,7 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring) */ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) { - struct fence *fence = NULL; + struct dma_fence *fence = NULL; long r; /* skip vce ring1/2 ib test for now, since it's not reliable */ @@ -902,7 +902,7 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) goto error; } - r = fence_wait_timeout(fence, false, timeout); + r = dma_fence_wait_timeout(fence, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out.\n"); r = -ETIMEDOUT; @@ -913,6 +913,6 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) r = 0; } error: - fence_put(fence); + dma_fence_put(fence); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h index 12729d2852df..566c29ddeeb6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h @@ -29,9 +29,9 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev); int amdgpu_vce_suspend(struct amdgpu_device *adev); int amdgpu_vce_resume(struct amdgpu_device *adev); int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct fence **fence); + struct dma_fence **fence); int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, - bool direct, struct fence **fence); + bool direct, struct dma_fence **fence); void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp); int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx); void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 06f24322e7c3..22cabb5456e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -25,7 +25,7 @@ * Alex Deucher * Jerome Glisse */ -#include +#include #include #include #include "amdgpu.h" @@ -194,14 +194,14 @@ static bool amdgpu_vm_is_gpu_reset(struct amdgpu_device *adev, * Allocate an id for the vm, adding fences to the sync obj as necessary. */ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, - struct amdgpu_sync *sync, struct fence *fence, + struct amdgpu_sync *sync, struct dma_fence *fence, struct amdgpu_job *job) { struct amdgpu_device *adev = ring->adev; uint64_t fence_context = adev->fence_context + ring->idx; - struct fence *updates = sync->last_vm_update; + struct dma_fence *updates = sync->last_vm_update; struct amdgpu_vm_id *id, *idle; - struct fence **fences; + struct dma_fence **fences; unsigned i; int r = 0; @@ -225,17 +225,17 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (&idle->list == &adev->vm_manager.ids_lru) { u64 fence_context = adev->vm_manager.fence_context + ring->idx; unsigned seqno = ++adev->vm_manager.seqno[ring->idx]; - struct fence_array *array; + struct dma_fence_array *array; unsigned j; for (j = 0; j < i; ++j) - fence_get(fences[j]); + dma_fence_get(fences[j]); - array = fence_array_create(i, fences, fence_context, + array = dma_fence_array_create(i, fences, fence_context, seqno, true); if (!array) { for (j = 0; j < i; ++j) - fence_put(fences[j]); + dma_fence_put(fences[j]); kfree(fences); r = -ENOMEM; goto error; @@ -243,7 +243,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, r = amdgpu_sync_fence(ring->adev, sync, &array->base); - fence_put(&array->base); + dma_fence_put(&array->base); if (r) goto error; @@ -257,7 +257,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, /* Check if we can use a VMID already assigned to this VM */ i = ring->idx; do { - struct fence *flushed; + struct dma_fence *flushed; id = vm->ids[i++]; if (i == AMDGPU_MAX_RINGS) @@ -279,12 +279,12 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, continue; if (id->last_flush->context != fence_context && - !fence_is_signaled(id->last_flush)) + !dma_fence_is_signaled(id->last_flush)) continue; flushed = id->flushed_updates; if (updates && - (!flushed || fence_is_later(updates, flushed))) + (!flushed || dma_fence_is_later(updates, flushed))) continue; /* Good we can use this VMID. Remember this submission as @@ -315,14 +315,14 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (r) goto error; - fence_put(id->first); - id->first = fence_get(fence); + dma_fence_put(id->first); + id->first = dma_fence_get(fence); - fence_put(id->last_flush); + dma_fence_put(id->last_flush); id->last_flush = NULL; - fence_put(id->flushed_updates); - id->flushed_updates = fence_get(updates); + dma_fence_put(id->flushed_updates); + id->flushed_updates = dma_fence_get(updates); id->pd_gpu_addr = job->vm_pd_addr; id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter); @@ -393,7 +393,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) if (ring->funcs->emit_vm_flush && (job->vm_needs_flush || amdgpu_vm_is_gpu_reset(adev, id))) { - struct fence *fence; + struct dma_fence *fence; trace_amdgpu_vm_flush(job->vm_pd_addr, ring->idx, job->vm_id); amdgpu_ring_emit_vm_flush(ring, job->vm_id, job->vm_pd_addr); @@ -403,7 +403,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) return r; mutex_lock(&adev->vm_manager.lock); - fence_put(id->last_flush); + dma_fence_put(id->last_flush); id->last_flush = fence; mutex_unlock(&adev->vm_manager.lock); } @@ -537,7 +537,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, struct amdgpu_bo *bo) { struct amdgpu_ring *ring; - struct fence *fence = NULL; + struct dma_fence *fence = NULL; struct amdgpu_job *job; struct amdgpu_pte_update_params params; unsigned entries; @@ -578,7 +578,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, goto error_free; amdgpu_bo_fence(bo, fence, true); - fence_put(fence); + dma_fence_put(fence); return 0; error_free: @@ -625,7 +625,7 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, unsigned count = 0, pt_idx, ndw; struct amdgpu_job *job; struct amdgpu_pte_update_params params; - struct fence *fence = NULL; + struct dma_fence *fence = NULL; int r; @@ -714,9 +714,9 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, goto error_free; amdgpu_bo_fence(pd, fence, true); - fence_put(vm->page_directory_fence); - vm->page_directory_fence = fence_get(fence); - fence_put(fence); + dma_fence_put(vm->page_directory_fence); + vm->page_directory_fence = dma_fence_get(fence); + dma_fence_put(fence); } else { amdgpu_job_free(job); @@ -929,20 +929,20 @@ static void amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, * Returns 0 for success, -EINVAL for failure. */ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, - struct fence *exclusive, + struct dma_fence *exclusive, uint64_t src, dma_addr_t *pages_addr, struct amdgpu_vm *vm, uint64_t start, uint64_t last, uint32_t flags, uint64_t addr, - struct fence **fence) + struct dma_fence **fence) { struct amdgpu_ring *ring; void *owner = AMDGPU_FENCE_OWNER_VM; unsigned nptes, ncmds, ndw; struct amdgpu_job *job; struct amdgpu_pte_update_params params; - struct fence *f = NULL; + struct dma_fence *f = NULL; int r; memset(¶ms, 0, sizeof(params)); @@ -1045,10 +1045,10 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, amdgpu_bo_fence(vm->page_directory, f, true); if (fence) { - fence_put(*fence); - *fence = fence_get(f); + dma_fence_put(*fence); + *fence = dma_fence_get(f); } - fence_put(f); + dma_fence_put(f); return 0; error_free: @@ -1074,13 +1074,13 @@ error_free: * Returns 0 for success, -EINVAL for failure. */ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, - struct fence *exclusive, + struct dma_fence *exclusive, uint32_t gtt_flags, dma_addr_t *pages_addr, struct amdgpu_vm *vm, struct amdgpu_bo_va_mapping *mapping, uint32_t flags, uint64_t addr, - struct fence **fence) + struct dma_fence **fence) { const uint64_t max_size = 64ULL * 1024ULL * 1024ULL / AMDGPU_GPU_PAGE_SIZE; @@ -1147,7 +1147,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, dma_addr_t *pages_addr = NULL; uint32_t gtt_flags, flags; struct ttm_mem_reg *mem; - struct fence *exclusive; + struct dma_fence *exclusive; uint64_t addr; int r; @@ -1547,7 +1547,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, kfree(mapping); } - fence_put(bo_va->last_pt_update); + dma_fence_put(bo_va->last_pt_update); kfree(bo_va); } @@ -1709,7 +1709,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) amdgpu_bo_unref(&vm->page_directory->shadow); amdgpu_bo_unref(&vm->page_directory); - fence_put(vm->page_directory_fence); + dma_fence_put(vm->page_directory_fence); } /** @@ -1733,7 +1733,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) &adev->vm_manager.ids_lru); } - adev->vm_manager.fence_context = fence_context_alloc(AMDGPU_MAX_RINGS); + adev->vm_manager.fence_context = + dma_fence_context_alloc(AMDGPU_MAX_RINGS); for (i = 0; i < AMDGPU_MAX_RINGS; ++i) adev->vm_manager.seqno[i] = 0; @@ -1755,8 +1756,8 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev) for (i = 0; i < AMDGPU_NUM_VM; ++i) { struct amdgpu_vm_id *id = &adev->vm_manager.ids[i]; - fence_put(adev->vm_manager.ids[i].first); + dma_fence_put(adev->vm_manager.ids[i].first); amdgpu_sync_free(&adev->vm_manager.ids[i].active); - fence_put(id->flushed_updates); + dma_fence_put(id->flushed_updates); } } diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index cb952acc7133..321b9d5a4e6e 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -622,7 +622,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; unsigned index; u32 tmp = 0; u64 gpu_addr; @@ -655,7 +655,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout) if (r) goto err1; - r = fence_wait_timeout(f, false, timeout); + r = dma_fence_wait_timeout(f, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out\n"); r = -ETIMEDOUT; @@ -675,7 +675,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout) err1: amdgpu_ib_free(adev, &ib, NULL); - fence_put(f); + dma_fence_put(f); err0: amdgpu_wb_free(adev, index); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 40abb6b81c09..7dc11a19e49d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -1522,7 +1522,7 @@ static int gfx_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; uint32_t scratch; uint32_t tmp = 0; long r; @@ -1548,7 +1548,7 @@ static int gfx_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) if (r) goto err2; - r = fence_wait_timeout(f, false, timeout); + r = dma_fence_wait_timeout(f, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out\n"); r = -ETIMEDOUT; @@ -1569,7 +1569,7 @@ static int gfx_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) err2: amdgpu_ib_free(adev, &ib, NULL); - fence_put(f); + dma_fence_put(f); err1: amdgpu_gfx_scratch_free(adev, scratch); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 71116da9e782..3865ffe7de55 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2286,7 +2286,7 @@ static int gfx_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; uint32_t scratch; uint32_t tmp = 0; long r; @@ -2312,7 +2312,7 @@ static int gfx_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) if (r) goto err2; - r = fence_wait_timeout(f, false, timeout); + r = dma_fence_wait_timeout(f, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out\n"); r = -ETIMEDOUT; @@ -2333,7 +2333,7 @@ static int gfx_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) err2: amdgpu_ib_free(adev, &ib, NULL); - fence_put(f); + dma_fence_put(f); err1: amdgpu_gfx_scratch_free(adev, scratch); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index ee6a48a09214..a9dd18847c40 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -798,7 +798,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; uint32_t scratch; uint32_t tmp = 0; long r; @@ -824,7 +824,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) if (r) goto err2; - r = fence_wait_timeout(f, false, timeout); + r = dma_fence_wait_timeout(f, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out.\n"); r = -ETIMEDOUT; @@ -844,7 +844,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) } err2: amdgpu_ib_free(adev, &ib, NULL); - fence_put(f); + dma_fence_put(f); err1: amdgpu_gfx_scratch_free(adev, scratch); return r; @@ -1575,7 +1575,7 @@ static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev) { struct amdgpu_ring *ring = &adev->gfx.compute_ring[0]; struct amdgpu_ib ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; int r, i; u32 tmp; unsigned total_size, vgpr_offset, sgpr_offset; @@ -1708,7 +1708,7 @@ static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev) } /* wait for the GPU to finish processing the IB */ - r = fence_wait(f, false); + r = dma_fence_wait(f, false); if (r) { DRM_ERROR("amdgpu: fence wait failed (%d).\n", r); goto fail; @@ -1729,7 +1729,7 @@ static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev) fail: amdgpu_ib_free(adev, &ib, NULL); - fence_put(f); + dma_fence_put(f); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 565dab3c7218..7edf6e8c63dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -668,7 +668,7 @@ static int sdma_v2_4_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; unsigned index; u32 tmp = 0; u64 gpu_addr; @@ -705,7 +705,7 @@ static int sdma_v2_4_ring_test_ib(struct amdgpu_ring *ring, long timeout) if (r) goto err1; - r = fence_wait_timeout(f, false, timeout); + r = dma_fence_wait_timeout(f, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out\n"); r = -ETIMEDOUT; @@ -725,7 +725,7 @@ static int sdma_v2_4_ring_test_ib(struct amdgpu_ring *ring, long timeout) err1: amdgpu_ib_free(adev, &ib, NULL); - fence_put(f); + dma_fence_put(f); err0: amdgpu_wb_free(adev, index); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index a9d10941fb53..1932a67c62ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -871,7 +871,7 @@ static int sdma_v3_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; unsigned index; u32 tmp = 0; u64 gpu_addr; @@ -908,7 +908,7 @@ static int sdma_v3_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) if (r) goto err1; - r = fence_wait_timeout(f, false, timeout); + r = dma_fence_wait_timeout(f, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out\n"); r = -ETIMEDOUT; @@ -927,7 +927,7 @@ static int sdma_v3_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) } err1: amdgpu_ib_free(adev, &ib, NULL); - fence_put(f); + dma_fence_put(f); err0: amdgpu_wb_free(adev, index); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index de358193a8f9..b4cf4e25bf91 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -274,7 +274,7 @@ static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib ib; - struct fence *f = NULL; + struct dma_fence *f = NULL; unsigned index; u32 tmp = 0; u64 gpu_addr; @@ -305,7 +305,7 @@ static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout) if (r) goto err1; - r = fence_wait_timeout(f, false, timeout); + r = dma_fence_wait_timeout(f, false, timeout); if (r == 0) { DRM_ERROR("amdgpu: IB test timed out\n"); r = -ETIMEDOUT; @@ -325,7 +325,7 @@ static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout) err1: amdgpu_ib_free(adev, &ib, NULL); - fence_put(f); + dma_fence_put(f); err0: amdgpu_wb_free(adev, index); return r; diff --git a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h index b961a1c6caf3..dbd4fd3a810b 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h @@ -17,7 +17,7 @@ TRACE_EVENT(amd_sched_job, TP_STRUCT__entry( __field(struct amd_sched_entity *, entity) __field(struct amd_sched_job *, sched_job) - __field(struct fence *, fence) + __field(struct dma_fence *, fence) __field(const char *, name) __field(u32, job_count) __field(int, hw_job_count) @@ -42,7 +42,7 @@ TRACE_EVENT(amd_sched_process_job, TP_PROTO(struct amd_sched_fence *fence), TP_ARGS(fence), TP_STRUCT__entry( - __field(struct fence *, fence) + __field(struct dma_fence *, fence) ), TP_fast_assign( diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 963a24d46a93..5364e6a7ec8f 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -32,7 +32,7 @@ static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity); static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); -static void amd_sched_process_job(struct fence *f, struct fence_cb *cb); +static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb); struct kmem_cache *sched_fence_slab; atomic_t sched_fence_slab_ref = ATOMIC_INIT(0); @@ -141,7 +141,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched, return r; atomic_set(&entity->fence_seq, 0); - entity->fence_context = fence_context_alloc(2); + entity->fence_context = dma_fence_context_alloc(2); return 0; } @@ -221,32 +221,32 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, kfifo_free(&entity->job_queue); } -static void amd_sched_entity_wakeup(struct fence *f, struct fence_cb *cb) +static void amd_sched_entity_wakeup(struct dma_fence *f, struct dma_fence_cb *cb) { struct amd_sched_entity *entity = container_of(cb, struct amd_sched_entity, cb); entity->dependency = NULL; - fence_put(f); + dma_fence_put(f); amd_sched_wakeup(entity->sched); } -static void amd_sched_entity_clear_dep(struct fence *f, struct fence_cb *cb) +static void amd_sched_entity_clear_dep(struct dma_fence *f, struct dma_fence_cb *cb) { struct amd_sched_entity *entity = container_of(cb, struct amd_sched_entity, cb); entity->dependency = NULL; - fence_put(f); + dma_fence_put(f); } static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity) { struct amd_gpu_scheduler *sched = entity->sched; - struct fence * fence = entity->dependency; + struct dma_fence * fence = entity->dependency; struct amd_sched_fence *s_fence; if (fence->context == entity->fence_context) { /* We can ignore fences from ourself */ - fence_put(entity->dependency); + dma_fence_put(entity->dependency); return false; } @@ -257,23 +257,23 @@ static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity) * Fence is from the same scheduler, only need to wait for * it to be scheduled */ - fence = fence_get(&s_fence->scheduled); - fence_put(entity->dependency); + fence = dma_fence_get(&s_fence->scheduled); + dma_fence_put(entity->dependency); entity->dependency = fence; - if (!fence_add_callback(fence, &entity->cb, - amd_sched_entity_clear_dep)) + if (!dma_fence_add_callback(fence, &entity->cb, + amd_sched_entity_clear_dep)) return true; /* Ignore it when it is already scheduled */ - fence_put(fence); + dma_fence_put(fence); return false; } - if (!fence_add_callback(entity->dependency, &entity->cb, - amd_sched_entity_wakeup)) + if (!dma_fence_add_callback(entity->dependency, &entity->cb, + amd_sched_entity_wakeup)) return true; - fence_put(entity->dependency); + dma_fence_put(entity->dependency); return false; } @@ -354,7 +354,8 @@ static void amd_sched_job_finish(struct work_struct *work) sched->ops->free_job(s_job); } -static void amd_sched_job_finish_cb(struct fence *f, struct fence_cb *cb) +static void amd_sched_job_finish_cb(struct dma_fence *f, + struct dma_fence_cb *cb) { struct amd_sched_job *job = container_of(cb, struct amd_sched_job, finish_cb); @@ -388,8 +389,8 @@ void amd_sched_hw_job_reset(struct amd_gpu_scheduler *sched) spin_lock(&sched->job_list_lock); list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) { - if (fence_remove_callback(s_job->s_fence->parent, &s_job->s_fence->cb)) { - fence_put(s_job->s_fence->parent); + if (dma_fence_remove_callback(s_job->s_fence->parent, &s_job->s_fence->cb)) { + dma_fence_put(s_job->s_fence->parent); s_job->s_fence->parent = NULL; } } @@ -410,21 +411,21 @@ void amd_sched_job_recovery(struct amd_gpu_scheduler *sched) list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) { struct amd_sched_fence *s_fence = s_job->s_fence; - struct fence *fence; + struct dma_fence *fence; spin_unlock(&sched->job_list_lock); fence = sched->ops->run_job(s_job); atomic_inc(&sched->hw_rq_count); if (fence) { - s_fence->parent = fence_get(fence); - r = fence_add_callback(fence, &s_fence->cb, - amd_sched_process_job); + s_fence->parent = dma_fence_get(fence); + r = dma_fence_add_callback(fence, &s_fence->cb, + amd_sched_process_job); if (r == -ENOENT) amd_sched_process_job(fence, &s_fence->cb); else if (r) DRM_ERROR("fence add callback failed (%d)\n", r); - fence_put(fence); + dma_fence_put(fence); } else { DRM_ERROR("Failed to run job!\n"); amd_sched_process_job(NULL, &s_fence->cb); @@ -446,8 +447,8 @@ void amd_sched_entity_push_job(struct amd_sched_job *sched_job) struct amd_sched_entity *entity = sched_job->s_entity; trace_amd_sched_job(sched_job); - fence_add_callback(&sched_job->s_fence->finished, &sched_job->finish_cb, - amd_sched_job_finish_cb); + dma_fence_add_callback(&sched_job->s_fence->finished, &sched_job->finish_cb, + amd_sched_job_finish_cb); wait_event(entity->sched->job_scheduled, amd_sched_entity_in(sched_job)); } @@ -511,7 +512,7 @@ amd_sched_select_entity(struct amd_gpu_scheduler *sched) return entity; } -static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) +static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb) { struct amd_sched_fence *s_fence = container_of(cb, struct amd_sched_fence, cb); @@ -521,7 +522,7 @@ static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) amd_sched_fence_finished(s_fence); trace_amd_sched_process_job(s_fence); - fence_put(&s_fence->finished); + dma_fence_put(&s_fence->finished); wake_up_interruptible(&sched->wake_up_worker); } @@ -547,7 +548,7 @@ static int amd_sched_main(void *param) struct amd_sched_entity *entity = NULL; struct amd_sched_fence *s_fence; struct amd_sched_job *sched_job; - struct fence *fence; + struct dma_fence *fence; wait_event_interruptible(sched->wake_up_worker, (!amd_sched_blocked(sched) && @@ -569,15 +570,15 @@ static int amd_sched_main(void *param) fence = sched->ops->run_job(sched_job); amd_sched_fence_scheduled(s_fence); if (fence) { - s_fence->parent = fence_get(fence); - r = fence_add_callback(fence, &s_fence->cb, - amd_sched_process_job); + s_fence->parent = dma_fence_get(fence); + r = dma_fence_add_callback(fence, &s_fence->cb, + amd_sched_process_job); if (r == -ENOENT) amd_sched_process_job(fence, &s_fence->cb); else if (r) DRM_ERROR("fence add callback failed (%d)\n", r); - fence_put(fence); + dma_fence_put(fence); } else { DRM_ERROR("Failed to run job!\n"); amd_sched_process_job(NULL, &s_fence->cb); diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h index 7cbbbfb502ef..876aa43b57df 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h @@ -25,7 +25,7 @@ #define _GPU_SCHEDULER_H_ #include -#include +#include struct amd_gpu_scheduler; struct amd_sched_rq; @@ -50,8 +50,8 @@ struct amd_sched_entity { atomic_t fence_seq; uint64_t fence_context; - struct fence *dependency; - struct fence_cb cb; + struct dma_fence *dependency; + struct dma_fence_cb cb; }; /** @@ -66,10 +66,10 @@ struct amd_sched_rq { }; struct amd_sched_fence { - struct fence scheduled; - struct fence finished; - struct fence_cb cb; - struct fence *parent; + struct dma_fence scheduled; + struct dma_fence finished; + struct dma_fence_cb cb; + struct dma_fence *parent; struct amd_gpu_scheduler *sched; spinlock_t lock; void *owner; @@ -79,15 +79,15 @@ struct amd_sched_job { struct amd_gpu_scheduler *sched; struct amd_sched_entity *s_entity; struct amd_sched_fence *s_fence; - struct fence_cb finish_cb; + struct dma_fence_cb finish_cb; struct work_struct finish_work; struct list_head node; struct delayed_work work_tdr; }; -extern const struct fence_ops amd_sched_fence_ops_scheduled; -extern const struct fence_ops amd_sched_fence_ops_finished; -static inline struct amd_sched_fence *to_amd_sched_fence(struct fence *f) +extern const struct dma_fence_ops amd_sched_fence_ops_scheduled; +extern const struct dma_fence_ops amd_sched_fence_ops_finished; +static inline struct amd_sched_fence *to_amd_sched_fence(struct dma_fence *f) { if (f->ops == &amd_sched_fence_ops_scheduled) return container_of(f, struct amd_sched_fence, scheduled); @@ -103,8 +103,8 @@ static inline struct amd_sched_fence *to_amd_sched_fence(struct fence *f) * these functions should be implemented in driver side */ struct amd_sched_backend_ops { - struct fence *(*dependency)(struct amd_sched_job *sched_job); - struct fence *(*run_job)(struct amd_sched_job *sched_job); + struct dma_fence *(*dependency)(struct amd_sched_job *sched_job); + struct dma_fence *(*run_job)(struct amd_sched_job *sched_job); void (*timedout_job)(struct amd_sched_job *sched_job); void (*free_job)(struct amd_sched_job *sched_job); }; diff --git a/drivers/gpu/drm/amd/scheduler/sched_fence.c b/drivers/gpu/drm/amd/scheduler/sched_fence.c index 6b63beaf7574..c26fa298fe9e 100644 --- a/drivers/gpu/drm/amd/scheduler/sched_fence.c +++ b/drivers/gpu/drm/amd/scheduler/sched_fence.c @@ -42,46 +42,50 @@ struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *entity, spin_lock_init(&fence->lock); seq = atomic_inc_return(&entity->fence_seq); - fence_init(&fence->scheduled, &amd_sched_fence_ops_scheduled, - &fence->lock, entity->fence_context, seq); - fence_init(&fence->finished, &amd_sched_fence_ops_finished, - &fence->lock, entity->fence_context + 1, seq); + dma_fence_init(&fence->scheduled, &amd_sched_fence_ops_scheduled, + &fence->lock, entity->fence_context, seq); + dma_fence_init(&fence->finished, &amd_sched_fence_ops_finished, + &fence->lock, entity->fence_context + 1, seq); return fence; } void amd_sched_fence_scheduled(struct amd_sched_fence *fence) { - int ret = fence_signal(&fence->scheduled); + int ret = dma_fence_signal(&fence->scheduled); if (!ret) - FENCE_TRACE(&fence->scheduled, "signaled from irq context\n"); + DMA_FENCE_TRACE(&fence->scheduled, + "signaled from irq context\n"); else - FENCE_TRACE(&fence->scheduled, "was already signaled\n"); + DMA_FENCE_TRACE(&fence->scheduled, + "was already signaled\n"); } void amd_sched_fence_finished(struct amd_sched_fence *fence) { - int ret = fence_signal(&fence->finished); + int ret = dma_fence_signal(&fence->finished); if (!ret) - FENCE_TRACE(&fence->finished, "signaled from irq context\n"); + DMA_FENCE_TRACE(&fence->finished, + "signaled from irq context\n"); else - FENCE_TRACE(&fence->finished, "was already signaled\n"); + DMA_FENCE_TRACE(&fence->finished, + "was already signaled\n"); } -static const char *amd_sched_fence_get_driver_name(struct fence *fence) +static const char *amd_sched_fence_get_driver_name(struct dma_fence *fence) { return "amd_sched"; } -static const char *amd_sched_fence_get_timeline_name(struct fence *f) +static const char *amd_sched_fence_get_timeline_name(struct dma_fence *f) { struct amd_sched_fence *fence = to_amd_sched_fence(f); return (const char *)fence->sched->name; } -static bool amd_sched_fence_enable_signaling(struct fence *f) +static bool amd_sched_fence_enable_signaling(struct dma_fence *f) { return true; } @@ -95,10 +99,10 @@ static bool amd_sched_fence_enable_signaling(struct fence *f) */ static void amd_sched_fence_free(struct rcu_head *rcu) { - struct fence *f = container_of(rcu, struct fence, rcu); + struct dma_fence *f = container_of(rcu, struct dma_fence, rcu); struct amd_sched_fence *fence = to_amd_sched_fence(f); - fence_put(fence->parent); + dma_fence_put(fence->parent); kmem_cache_free(sched_fence_slab, fence); } @@ -110,7 +114,7 @@ static void amd_sched_fence_free(struct rcu_head *rcu) * This function is called when the reference count becomes zero. * It just RCU schedules freeing up the fence. */ -static void amd_sched_fence_release_scheduled(struct fence *f) +static void amd_sched_fence_release_scheduled(struct dma_fence *f) { struct amd_sched_fence *fence = to_amd_sched_fence(f); @@ -124,27 +128,27 @@ static void amd_sched_fence_release_scheduled(struct fence *f) * * Drop the extra reference from the scheduled fence to the base fence. */ -static void amd_sched_fence_release_finished(struct fence *f) +static void amd_sched_fence_release_finished(struct dma_fence *f) { struct amd_sched_fence *fence = to_amd_sched_fence(f); - fence_put(&fence->scheduled); + dma_fence_put(&fence->scheduled); } -const struct fence_ops amd_sched_fence_ops_scheduled = { +const struct dma_fence_ops amd_sched_fence_ops_scheduled = { .get_driver_name = amd_sched_fence_get_driver_name, .get_timeline_name = amd_sched_fence_get_timeline_name, .enable_signaling = amd_sched_fence_enable_signaling, .signaled = NULL, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .release = amd_sched_fence_release_scheduled, }; -const struct fence_ops amd_sched_fence_ops_finished = { +const struct dma_fence_ops amd_sched_fence_ops_finished = { .get_driver_name = amd_sched_fence_get_driver_name, .get_timeline_name = amd_sched_fence_get_timeline_name, .enable_signaling = amd_sched_fence_enable_signaling, .signaled = NULL, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .release = amd_sched_fence_release_finished, }; diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 1b5a32df9a9a..c32fb3c1d6f0 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1463,7 +1463,7 @@ EXPORT_SYMBOL(drm_atomic_nonblocking_commit); static struct drm_pending_vblank_event *create_vblank_event( struct drm_device *dev, struct drm_file *file_priv, - struct fence *fence, uint64_t user_data) + struct dma_fence *fence, uint64_t user_data) { struct drm_pending_vblank_event *e = NULL; int ret; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f9362760bfb2..75ad01d595fd 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "drm_crtc_internal.h" @@ -1017,7 +1017,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables); * drm_atomic_helper_swap_state() so it uses the current plane state (and * just uses the atomic state to find the changed planes) * - * Returns zero if success or < 0 if fence_wait() fails. + * Returns zero if success or < 0 if dma_fence_wait() fails. */ int drm_atomic_helper_wait_for_fences(struct drm_device *dev, struct drm_atomic_state *state, @@ -1041,11 +1041,11 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev, * still interrupt the operation. Instead of blocking until the * timer expires, make the wait interruptible. */ - ret = fence_wait(plane_state->fence, pre_swap); + ret = dma_fence_wait(plane_state->fence, pre_swap); if (ret) return ret; - fence_put(plane_state->fence); + dma_fence_put(plane_state->fence); plane_state->fence = NULL; } diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 8bed5f459182..cf993dbf602e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -665,7 +665,7 @@ void drm_event_cancel_free(struct drm_device *dev, spin_unlock_irqrestore(&dev->event_lock, flags); if (p->fence) - fence_put(p->fence); + dma_fence_put(p->fence); kfree(p); } @@ -696,8 +696,8 @@ void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e) } if (e->fence) { - fence_signal(e->fence); - fence_put(e->fence); + dma_fence_signal(e->fence); + dma_fence_put(e->fence); } if (!e->file_priv) { diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 3755ef935af4..7d066a91d778 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -466,10 +466,10 @@ int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj, } #ifdef CONFIG_DEBUG_FS -static void etnaviv_gem_describe_fence(struct fence *fence, +static void etnaviv_gem_describe_fence(struct dma_fence *fence, const char *type, struct seq_file *m) { - if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) seq_printf(m, "\t%9s: %s %s seq %u\n", type, fence->ops->get_driver_name(fence), @@ -482,7 +482,7 @@ static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m) struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); struct reservation_object *robj = etnaviv_obj->resv; struct reservation_object_list *fobj; - struct fence *fence; + struct dma_fence *fence; unsigned long off = drm_vma_node_start(&obj->vma_node); seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n", diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index b1254f885fed..d2211825e5c8 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -15,7 +15,7 @@ */ #include -#include +#include #include #include #include "etnaviv_dump.h" @@ -882,7 +882,7 @@ static void recover_worker(struct work_struct *work) for (i = 0; i < ARRAY_SIZE(gpu->event); i++) { if (!gpu->event[i].used) continue; - fence_signal(gpu->event[i].fence); + dma_fence_signal(gpu->event[i].fence); gpu->event[i].fence = NULL; gpu->event[i].used = false; complete(&gpu->event_free); @@ -952,55 +952,55 @@ static void hangcheck_disable(struct etnaviv_gpu *gpu) /* fence object management */ struct etnaviv_fence { struct etnaviv_gpu *gpu; - struct fence base; + struct dma_fence base; }; -static inline struct etnaviv_fence *to_etnaviv_fence(struct fence *fence) +static inline struct etnaviv_fence *to_etnaviv_fence(struct dma_fence *fence) { return container_of(fence, struct etnaviv_fence, base); } -static const char *etnaviv_fence_get_driver_name(struct fence *fence) +static const char *etnaviv_fence_get_driver_name(struct dma_fence *fence) { return "etnaviv"; } -static const char *etnaviv_fence_get_timeline_name(struct fence *fence) +static const char *etnaviv_fence_get_timeline_name(struct dma_fence *fence) { struct etnaviv_fence *f = to_etnaviv_fence(fence); return dev_name(f->gpu->dev); } -static bool etnaviv_fence_enable_signaling(struct fence *fence) +static bool etnaviv_fence_enable_signaling(struct dma_fence *fence) { return true; } -static bool etnaviv_fence_signaled(struct fence *fence) +static bool etnaviv_fence_signaled(struct dma_fence *fence) { struct etnaviv_fence *f = to_etnaviv_fence(fence); return fence_completed(f->gpu, f->base.seqno); } -static void etnaviv_fence_release(struct fence *fence) +static void etnaviv_fence_release(struct dma_fence *fence) { struct etnaviv_fence *f = to_etnaviv_fence(fence); kfree_rcu(f, base.rcu); } -static const struct fence_ops etnaviv_fence_ops = { +static const struct dma_fence_ops etnaviv_fence_ops = { .get_driver_name = etnaviv_fence_get_driver_name, .get_timeline_name = etnaviv_fence_get_timeline_name, .enable_signaling = etnaviv_fence_enable_signaling, .signaled = etnaviv_fence_signaled, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .release = etnaviv_fence_release, }; -static struct fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu) +static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu) { struct etnaviv_fence *f; @@ -1010,8 +1010,8 @@ static struct fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu) f->gpu = gpu; - fence_init(&f->base, &etnaviv_fence_ops, &gpu->fence_spinlock, - gpu->fence_context, ++gpu->next_fence); + dma_fence_init(&f->base, &etnaviv_fence_ops, &gpu->fence_spinlock, + gpu->fence_context, ++gpu->next_fence); return &f->base; } @@ -1021,7 +1021,7 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj, { struct reservation_object *robj = etnaviv_obj->resv; struct reservation_object_list *fobj; - struct fence *fence; + struct dma_fence *fence; int i, ret; if (!exclusive) { @@ -1039,7 +1039,7 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj, /* Wait on any existing exclusive fence which isn't our own */ fence = reservation_object_get_excl(robj); if (fence && fence->context != context) { - ret = fence_wait(fence, true); + ret = dma_fence_wait(fence, true); if (ret) return ret; } @@ -1052,7 +1052,7 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj, fence = rcu_dereference_protected(fobj->shared[i], reservation_object_held(robj)); if (fence->context != context) { - ret = fence_wait(fence, true); + ret = dma_fence_wait(fence, true); if (ret) return ret; } @@ -1158,11 +1158,11 @@ static void retire_worker(struct work_struct *work) mutex_lock(&gpu->lock); list_for_each_entry_safe(cmdbuf, tmp, &gpu->active_cmd_list, node) { - if (!fence_is_signaled(cmdbuf->fence)) + if (!dma_fence_is_signaled(cmdbuf->fence)) break; list_del(&cmdbuf->node); - fence_put(cmdbuf->fence); + dma_fence_put(cmdbuf->fence); for (i = 0; i < cmdbuf->nr_bos; i++) { struct etnaviv_vram_mapping *mapping = cmdbuf->bo_map[i]; @@ -1275,7 +1275,7 @@ void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu) int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf) { - struct fence *fence; + struct dma_fence *fence; unsigned int event, i; int ret; @@ -1391,7 +1391,7 @@ static irqreturn_t irq_handler(int irq, void *data) } while ((event = ffs(intr)) != 0) { - struct fence *fence; + struct dma_fence *fence; event -= 1; @@ -1401,7 +1401,7 @@ static irqreturn_t irq_handler(int irq, void *data) fence = gpu->event[event].fence; gpu->event[event].fence = NULL; - fence_signal(fence); + dma_fence_signal(fence); /* * Events can be processed out of order. Eg, @@ -1553,7 +1553,7 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master, return ret; gpu->drm = drm; - gpu->fence_context = fence_context_alloc(1); + gpu->fence_context = dma_fence_context_alloc(1); spin_lock_init(&gpu->fence_spinlock); INIT_LIST_HEAD(&gpu->active_cmd_list); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 73c278dc3706..8c6b824e9d0a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -89,7 +89,7 @@ struct etnaviv_chip_identity { struct etnaviv_event { bool used; - struct fence *fence; + struct dma_fence *fence; }; struct etnaviv_cmdbuf; @@ -163,7 +163,7 @@ struct etnaviv_cmdbuf { /* vram node used if the cmdbuf is mapped through the MMUv2 */ struct drm_mm_node vram_node; /* fence after which this buffer is to be disposed */ - struct fence *fence; + struct dma_fence *fence; /* target exec state */ u32 exec_state; /* per GPU in-flight list */ diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 74ede1f53372..f9af2a00625e 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -26,12 +26,12 @@ #include "i915_drv.h" -static const char *i915_fence_get_driver_name(struct fence *fence) +static const char *i915_fence_get_driver_name(struct dma_fence *fence) { return "i915"; } -static const char *i915_fence_get_timeline_name(struct fence *fence) +static const char *i915_fence_get_timeline_name(struct dma_fence *fence) { /* Timelines are bound by eviction to a VM. However, since * we only have a global seqno at the moment, we only have @@ -42,12 +42,12 @@ static const char *i915_fence_get_timeline_name(struct fence *fence) return "global"; } -static bool i915_fence_signaled(struct fence *fence) +static bool i915_fence_signaled(struct dma_fence *fence) { return i915_gem_request_completed(to_request(fence)); } -static bool i915_fence_enable_signaling(struct fence *fence) +static bool i915_fence_enable_signaling(struct dma_fence *fence) { if (i915_fence_signaled(fence)) return false; @@ -56,7 +56,7 @@ static bool i915_fence_enable_signaling(struct fence *fence) return true; } -static signed long i915_fence_wait(struct fence *fence, +static signed long i915_fence_wait(struct dma_fence *fence, bool interruptible, signed long timeout_jiffies) { @@ -85,26 +85,26 @@ static signed long i915_fence_wait(struct fence *fence, return timeout_jiffies; } -static void i915_fence_value_str(struct fence *fence, char *str, int size) +static void i915_fence_value_str(struct dma_fence *fence, char *str, int size) { snprintf(str, size, "%u", fence->seqno); } -static void i915_fence_timeline_value_str(struct fence *fence, char *str, +static void i915_fence_timeline_value_str(struct dma_fence *fence, char *str, int size) { snprintf(str, size, "%u", intel_engine_get_seqno(to_request(fence)->engine)); } -static void i915_fence_release(struct fence *fence) +static void i915_fence_release(struct dma_fence *fence) { struct drm_i915_gem_request *req = to_request(fence); kmem_cache_free(req->i915->requests, req); } -const struct fence_ops i915_fence_ops = { +const struct dma_fence_ops i915_fence_ops = { .get_driver_name = i915_fence_get_driver_name, .get_timeline_name = i915_fence_get_timeline_name, .enable_signaling = i915_fence_enable_signaling, @@ -388,8 +388,8 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, * The reference count is incremented atomically. If it is zero, * the lookup knows the request is unallocated and complete. Otherwise, * it is either still in use, or has been reallocated and reset - * with fence_init(). This increment is safe for release as we check - * that the request we have a reference to and matches the active + * with dma_fence_init(). This increment is safe for release as we + * check that the request we have a reference to and matches the active * request. * * Before we increment the refcount, we chase the request->engine @@ -412,11 +412,11 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, goto err; spin_lock_init(&req->lock); - fence_init(&req->fence, - &i915_fence_ops, - &req->lock, - engine->fence_context, - seqno); + dma_fence_init(&req->fence, + &i915_fence_ops, + &req->lock, + engine->fence_context, + seqno); i915_sw_fence_init(&req->submit, submit_notify); diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 974bd7bcc801..bceeaa3a5193 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -25,7 +25,7 @@ #ifndef I915_GEM_REQUEST_H #define I915_GEM_REQUEST_H -#include +#include #include "i915_gem.h" #include "i915_sw_fence.h" @@ -62,7 +62,7 @@ struct intel_signal_node { * The requests are reference counted. */ struct drm_i915_gem_request { - struct fence fence; + struct dma_fence fence; spinlock_t lock; /** On Which ring this request was generated */ @@ -145,9 +145,9 @@ struct drm_i915_gem_request { struct list_head execlist_link; }; -extern const struct fence_ops i915_fence_ops; +extern const struct dma_fence_ops i915_fence_ops; -static inline bool fence_is_i915(struct fence *fence) +static inline bool fence_is_i915(struct dma_fence *fence) { return fence->ops == &i915_fence_ops; } @@ -172,7 +172,7 @@ i915_gem_request_get_engine(struct drm_i915_gem_request *req) } static inline struct drm_i915_gem_request * -to_request(struct fence *fence) +to_request(struct dma_fence *fence) { /* We assume that NULL fence/request are interoperable */ BUILD_BUG_ON(offsetof(struct drm_i915_gem_request, fence) != 0); @@ -183,19 +183,19 @@ to_request(struct fence *fence) static inline struct drm_i915_gem_request * i915_gem_request_get(struct drm_i915_gem_request *req) { - return to_request(fence_get(&req->fence)); + return to_request(dma_fence_get(&req->fence)); } static inline struct drm_i915_gem_request * i915_gem_request_get_rcu(struct drm_i915_gem_request *req) { - return to_request(fence_get_rcu(&req->fence)); + return to_request(dma_fence_get_rcu(&req->fence)); } static inline void i915_gem_request_put(struct drm_i915_gem_request *req) { - fence_put(&req->fence); + dma_fence_put(&req->fence); } static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst, @@ -497,7 +497,7 @@ __i915_gem_active_get_rcu(const struct i915_gem_active *active) * compiler. * * The atomic operation at the heart of - * i915_gem_request_get_rcu(), see fence_get_rcu(), is + * i915_gem_request_get_rcu(), see dma_fence_get_rcu(), is * atomic_inc_not_zero() which is only a full memory barrier * when successful. That is, if i915_gem_request_get_rcu() * returns the request (and so with the reference counted diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 1e5cbc585ca2..8185002d7ec8 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -8,7 +8,7 @@ */ #include -#include +#include #include #include "i915_sw_fence.h" @@ -226,49 +226,50 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, return pending; } -struct dma_fence_cb { - struct fence_cb base; +struct i915_sw_dma_fence_cb { + struct dma_fence_cb base; struct i915_sw_fence *fence; - struct fence *dma; + struct dma_fence *dma; struct timer_list timer; }; static void timer_i915_sw_fence_wake(unsigned long data) { - struct dma_fence_cb *cb = (struct dma_fence_cb *)data; + struct i915_sw_dma_fence_cb *cb = (struct i915_sw_dma_fence_cb *)data; printk(KERN_WARNING "asynchronous wait on fence %s:%s:%x timed out\n", cb->dma->ops->get_driver_name(cb->dma), cb->dma->ops->get_timeline_name(cb->dma), cb->dma->seqno); - fence_put(cb->dma); + dma_fence_put(cb->dma); cb->dma = NULL; i915_sw_fence_commit(cb->fence); cb->timer.function = NULL; } -static void dma_i915_sw_fence_wake(struct fence *dma, struct fence_cb *data) +static void dma_i915_sw_fence_wake(struct dma_fence *dma, + struct dma_fence_cb *data) { - struct dma_fence_cb *cb = container_of(data, typeof(*cb), base); + struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base); del_timer_sync(&cb->timer); if (cb->timer.function) i915_sw_fence_commit(cb->fence); - fence_put(cb->dma); + dma_fence_put(cb->dma); kfree(cb); } int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, - struct fence *dma, + struct dma_fence *dma, unsigned long timeout, gfp_t gfp) { - struct dma_fence_cb *cb; + struct i915_sw_dma_fence_cb *cb; int ret; - if (fence_is_signaled(dma)) + if (dma_fence_is_signaled(dma)) return 0; cb = kmalloc(sizeof(*cb), gfp); @@ -276,7 +277,7 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, if (!gfpflags_allow_blocking(gfp)) return -ENOMEM; - return fence_wait(dma, false); + return dma_fence_wait(dma, false); } cb->fence = i915_sw_fence_get(fence); @@ -287,11 +288,11 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, timer_i915_sw_fence_wake, (unsigned long)cb, TIMER_IRQSAFE); if (timeout) { - cb->dma = fence_get(dma); + cb->dma = dma_fence_get(dma); mod_timer(&cb->timer, round_jiffies_up(jiffies + timeout)); } - ret = fence_add_callback(dma, &cb->base, dma_i915_sw_fence_wake); + ret = dma_fence_add_callback(dma, &cb->base, dma_i915_sw_fence_wake); if (ret == 0) { ret = 1; } else { @@ -305,16 +306,16 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, struct reservation_object *resv, - const struct fence_ops *exclude, + const struct dma_fence_ops *exclude, bool write, unsigned long timeout, gfp_t gfp) { - struct fence *excl; + struct dma_fence *excl; int ret = 0, pending; if (write) { - struct fence **shared; + struct dma_fence **shared; unsigned int count, i; ret = reservation_object_get_fences_rcu(resv, @@ -339,7 +340,7 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, } for (i = 0; i < count; i++) - fence_put(shared[i]); + dma_fence_put(shared[i]); kfree(shared); } else { excl = reservation_object_get_excl_rcu(resv); @@ -356,7 +357,7 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, ret |= pending; } - fence_put(excl); + dma_fence_put(excl); return ret; } diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index 373141602ca4..cd239e92f67f 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -16,8 +16,8 @@ #include struct completion; -struct fence; -struct fence_ops; +struct dma_fence; +struct dma_fence_ops; struct reservation_object; struct i915_sw_fence { @@ -47,12 +47,12 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, struct i915_sw_fence *after, wait_queue_t *wq); int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, - struct fence *dma, + struct dma_fence *dma, unsigned long timeout, gfp_t gfp); int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, struct reservation_object *resv, - const struct fence_ops *exclude, + const struct dma_fence_ops *exclude, bool write, unsigned long timeout, gfp_t gfp); diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 178798002a73..5c912c25f7d3 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -491,7 +491,7 @@ TRACE_EVENT(i915_gem_ring_dispatch, __entry->ring = req->engine->id; __entry->seqno = req->fence.seqno; __entry->flags = flags; - fence_enable_sw_signaling(&req->fence); + dma_fence_enable_sw_signaling(&req->fence); ), TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x", diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 23fc1042fed4..56efcc507ea2 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -464,7 +464,7 @@ static int intel_breadcrumbs_signaler(void *arg) &request->signaling.wait); local_bh_disable(); - fence_signal(&request->fence); + dma_fence_signal(&request->fence); local_bh_enable(); /* kick start the tasklets */ /* Find the next oldest signal. Note that as we have @@ -502,7 +502,7 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request) struct rb_node *parent, **p; bool first, wakeup; - /* locked by fence_enable_sw_signaling() */ + /* locked by dma_fence_enable_sw_signaling() */ assert_spin_locked(&request->lock); request->signaling.wait.tsk = b->signaler; diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 2dc94812bea5..8cceb345aa0f 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -245,7 +245,7 @@ void intel_engine_setup_common(struct intel_engine_cs *engine) INIT_LIST_HEAD(&engine->execlist_queue); spin_lock_init(&engine->execlist_lock); - engine->fence_context = fence_context_alloc(1); + engine->fence_context = dma_fence_context_alloc(1); intel_engine_init_requests(engine); intel_engine_init_hangcheck(engine); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d0da52f2a806..940bf4992fe2 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -217,7 +217,7 @@ void msm_gem_vunmap(struct drm_gem_object *obj); int msm_gem_sync_object(struct drm_gem_object *obj, struct msm_fence_context *fctx, bool exclusive); void msm_gem_move_to_active(struct drm_gem_object *obj, - struct msm_gpu *gpu, bool exclusive, struct fence *fence); + struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence); void msm_gem_move_to_inactive(struct drm_gem_object *obj); int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); int msm_gem_cpu_fini(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c index a9b9b1c95a2e..3f299c537b77 100644 --- a/drivers/gpu/drm/msm/msm_fence.c +++ b/drivers/gpu/drm/msm/msm_fence.c @@ -15,7 +15,7 @@ * this program. If not, see . */ -#include +#include #include "msm_drv.h" #include "msm_fence.h" @@ -32,7 +32,7 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name) fctx->dev = dev; fctx->name = name; - fctx->context = fence_context_alloc(1); + fctx->context = dma_fence_context_alloc(1); init_waitqueue_head(&fctx->event); spin_lock_init(&fctx->spinlock); @@ -100,52 +100,52 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) struct msm_fence { struct msm_fence_context *fctx; - struct fence base; + struct dma_fence base; }; -static inline struct msm_fence *to_msm_fence(struct fence *fence) +static inline struct msm_fence *to_msm_fence(struct dma_fence *fence) { return container_of(fence, struct msm_fence, base); } -static const char *msm_fence_get_driver_name(struct fence *fence) +static const char *msm_fence_get_driver_name(struct dma_fence *fence) { return "msm"; } -static const char *msm_fence_get_timeline_name(struct fence *fence) +static const char *msm_fence_get_timeline_name(struct dma_fence *fence) { struct msm_fence *f = to_msm_fence(fence); return f->fctx->name; } -static bool msm_fence_enable_signaling(struct fence *fence) +static bool msm_fence_enable_signaling(struct dma_fence *fence) { return true; } -static bool msm_fence_signaled(struct fence *fence) +static bool msm_fence_signaled(struct dma_fence *fence) { struct msm_fence *f = to_msm_fence(fence); return fence_completed(f->fctx, f->base.seqno); } -static void msm_fence_release(struct fence *fence) +static void msm_fence_release(struct dma_fence *fence) { struct msm_fence *f = to_msm_fence(fence); kfree_rcu(f, base.rcu); } -static const struct fence_ops msm_fence_ops = { +static const struct dma_fence_ops msm_fence_ops = { .get_driver_name = msm_fence_get_driver_name, .get_timeline_name = msm_fence_get_timeline_name, .enable_signaling = msm_fence_enable_signaling, .signaled = msm_fence_signaled, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .release = msm_fence_release, }; -struct fence * +struct dma_fence * msm_fence_alloc(struct msm_fence_context *fctx) { struct msm_fence *f; @@ -156,8 +156,8 @@ msm_fence_alloc(struct msm_fence_context *fctx) f->fctx = fctx; - fence_init(&f->base, &msm_fence_ops, &fctx->spinlock, - fctx->context, ++fctx->last_fence); + dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock, + fctx->context, ++fctx->last_fence); return &f->base; } diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h index ceb5b3d314b4..56061aa1959d 100644 --- a/drivers/gpu/drm/msm/msm_fence.h +++ b/drivers/gpu/drm/msm/msm_fence.h @@ -41,6 +41,6 @@ int msm_queue_fence_cb(struct msm_fence_context *fctx, struct msm_fence_cb *cb, uint32_t fence); void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence); -struct fence * msm_fence_alloc(struct msm_fence_context *fctx); +struct dma_fence * msm_fence_alloc(struct msm_fence_context *fctx); #endif diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index b6ac27e31929..57db7dbbb618 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -521,7 +521,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj, { struct msm_gem_object *msm_obj = to_msm_bo(obj); struct reservation_object_list *fobj; - struct fence *fence; + struct dma_fence *fence; int i, ret; if (!exclusive) { @@ -540,7 +540,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj, fence = reservation_object_get_excl(msm_obj->resv); /* don't need to wait on our own fences, since ring is fifo */ if (fence && (fence->context != fctx->context)) { - ret = fence_wait(fence, true); + ret = dma_fence_wait(fence, true); if (ret) return ret; } @@ -553,7 +553,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj, fence = rcu_dereference_protected(fobj->shared[i], reservation_object_held(msm_obj->resv)); if (fence->context != fctx->context) { - ret = fence_wait(fence, true); + ret = dma_fence_wait(fence, true); if (ret) return ret; } @@ -563,7 +563,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj, } void msm_gem_move_to_active(struct drm_gem_object *obj, - struct msm_gpu *gpu, bool exclusive, struct fence *fence) + struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence) { struct msm_gem_object *msm_obj = to_msm_bo(obj); WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED); @@ -616,10 +616,10 @@ int msm_gem_cpu_fini(struct drm_gem_object *obj) } #ifdef CONFIG_DEBUG_FS -static void describe_fence(struct fence *fence, const char *type, +static void describe_fence(struct dma_fence *fence, const char *type, struct seq_file *m) { - if (!fence_is_signaled(fence)) + if (!dma_fence_is_signaled(fence)) seq_printf(m, "\t%9s: %s %s seq %u\n", type, fence->ops->get_driver_name(fence), fence->ops->get_timeline_name(fence), @@ -631,7 +631,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) struct msm_gem_object *msm_obj = to_msm_bo(obj); struct reservation_object *robj = msm_obj->resv; struct reservation_object_list *fobj; - struct fence *fence; + struct dma_fence *fence; uint64_t off = drm_vma_node_start(&obj->vma_node); const char *madv; diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index b2f13cfe945e..2cb8551fda70 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -104,7 +104,7 @@ struct msm_gem_submit { struct list_head node; /* node in gpu submit_list */ struct list_head bo_list; struct ww_acquire_ctx ticket; - struct fence *fence; + struct dma_fence *fence; struct pid *pid; /* submitting process */ bool valid; /* true if no cmdstream patching needed */ unsigned int nr_cmds; diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index b6a0f37a65f3..25e8786fa4ca 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -60,7 +60,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, void msm_gem_submit_free(struct msm_gem_submit *submit) { - fence_put(submit->fence); + dma_fence_put(submit->fence); list_del(&submit->node); put_pid(submit->pid); kfree(submit); @@ -380,7 +380,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct msm_file_private *ctx = file->driver_priv; struct msm_gem_submit *submit; struct msm_gpu *gpu = priv->gpu; - struct fence *in_fence = NULL; + struct dma_fence *in_fence = NULL; struct sync_file *sync_file = NULL; int out_fence_fd = -1; unsigned i; @@ -439,7 +439,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, */ if (in_fence->context != gpu->fctx->context) { - ret = fence_wait(in_fence, true); + ret = dma_fence_wait(in_fence, true); if (ret) goto out; } @@ -542,7 +542,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, out: if (in_fence) - fence_put(in_fence); + dma_fence_put(in_fence); submit_cleanup(submit); if (ret) msm_gem_submit_free(submit); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 5bb09838b5ae..3249707e6834 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -476,7 +476,7 @@ static void retire_submits(struct msm_gpu *gpu) submit = list_first_entry(&gpu->submit_list, struct msm_gem_submit, node); - if (fence_is_signaled(submit->fence)) { + if (dma_fence_is_signaled(submit->fence)) { retire_submit(gpu, submit); } else { break; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 343b8659472c..ec8ac756aab4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -83,13 +83,13 @@ nv10_bo_get_tile_region(struct drm_device *dev, int i) static void nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile, - struct fence *fence) + struct dma_fence *fence) { struct nouveau_drm *drm = nouveau_drm(dev); if (tile) { spin_lock(&drm->tile.lock); - tile->fence = (struct nouveau_fence *)fence_get(fence); + tile->fence = (struct nouveau_fence *)dma_fence_get(fence); tile->used = false; spin_unlock(&drm->tile.lock); } @@ -1243,7 +1243,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct drm_device *dev = drm->dev; - struct fence *fence = reservation_object_get_excl(bo->resv); + struct dma_fence *fence = reservation_object_get_excl(bo->resv); nv10_bo_put_tile_region(dev, *old_tile, fence); *old_tile = new_tile; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 4bb9ab892ae1..e9529ee6bc23 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include @@ -38,11 +38,11 @@ #include "nouveau_dma.h" #include "nouveau_fence.h" -static const struct fence_ops nouveau_fence_ops_uevent; -static const struct fence_ops nouveau_fence_ops_legacy; +static const struct dma_fence_ops nouveau_fence_ops_uevent; +static const struct dma_fence_ops nouveau_fence_ops_legacy; static inline struct nouveau_fence * -from_fence(struct fence *fence) +from_fence(struct dma_fence *fence) { return container_of(fence, struct nouveau_fence, base); } @@ -58,23 +58,23 @@ nouveau_fence_signal(struct nouveau_fence *fence) { int drop = 0; - fence_signal_locked(&fence->base); + dma_fence_signal_locked(&fence->base); list_del(&fence->head); rcu_assign_pointer(fence->channel, NULL); - if (test_bit(FENCE_FLAG_USER_BITS, &fence->base.flags)) { + if (test_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags)) { struct nouveau_fence_chan *fctx = nouveau_fctx(fence); if (!--fctx->notify_ref) drop = 1; } - fence_put(&fence->base); + dma_fence_put(&fence->base); return drop; } static struct nouveau_fence * -nouveau_local_fence(struct fence *fence, struct nouveau_drm *drm) { +nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) { struct nouveau_fence_priv *priv = (void*)drm->fence; if (fence->ops != &nouveau_fence_ops_legacy && @@ -201,7 +201,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha struct nouveau_fence_work { struct work_struct work; - struct fence_cb cb; + struct dma_fence_cb cb; void (*func)(void *); void *data; }; @@ -214,7 +214,7 @@ nouveau_fence_work_handler(struct work_struct *kwork) kfree(work); } -static void nouveau_fence_work_cb(struct fence *fence, struct fence_cb *cb) +static void nouveau_fence_work_cb(struct dma_fence *fence, struct dma_fence_cb *cb) { struct nouveau_fence_work *work = container_of(cb, typeof(*work), cb); @@ -222,12 +222,12 @@ static void nouveau_fence_work_cb(struct fence *fence, struct fence_cb *cb) } void -nouveau_fence_work(struct fence *fence, +nouveau_fence_work(struct dma_fence *fence, void (*func)(void *), void *data) { struct nouveau_fence_work *work; - if (fence_is_signaled(fence)) + if (dma_fence_is_signaled(fence)) goto err; work = kmalloc(sizeof(*work), GFP_KERNEL); @@ -245,7 +245,7 @@ nouveau_fence_work(struct fence *fence, work->func = func; work->data = data; - if (fence_add_callback(fence, &work->cb, nouveau_fence_work_cb) < 0) + if (dma_fence_add_callback(fence, &work->cb, nouveau_fence_work_cb) < 0) goto err_free; return; @@ -266,17 +266,17 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) fence->timeout = jiffies + (15 * HZ); if (priv->uevent) - fence_init(&fence->base, &nouveau_fence_ops_uevent, - &fctx->lock, fctx->context, ++fctx->sequence); + dma_fence_init(&fence->base, &nouveau_fence_ops_uevent, + &fctx->lock, fctx->context, ++fctx->sequence); else - fence_init(&fence->base, &nouveau_fence_ops_legacy, - &fctx->lock, fctx->context, ++fctx->sequence); + dma_fence_init(&fence->base, &nouveau_fence_ops_legacy, + &fctx->lock, fctx->context, ++fctx->sequence); kref_get(&fctx->fence_ref); - trace_fence_emit(&fence->base); + trace_dma_fence_emit(&fence->base); ret = fctx->emit(fence); if (!ret) { - fence_get(&fence->base); + dma_fence_get(&fence->base); spin_lock_irq(&fctx->lock); if (nouveau_fence_update(chan, fctx)) @@ -298,7 +298,7 @@ nouveau_fence_done(struct nouveau_fence *fence) struct nouveau_channel *chan; unsigned long flags; - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags)) + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags)) return true; spin_lock_irqsave(&fctx->lock, flags); @@ -307,11 +307,11 @@ nouveau_fence_done(struct nouveau_fence *fence) nvif_notify_put(&fctx->notify); spin_unlock_irqrestore(&fctx->lock, flags); } - return fence_is_signaled(&fence->base); + return dma_fence_is_signaled(&fence->base); } static long -nouveau_fence_wait_legacy(struct fence *f, bool intr, long wait) +nouveau_fence_wait_legacy(struct dma_fence *f, bool intr, long wait) { struct nouveau_fence *fence = from_fence(f); unsigned long sleep_time = NSEC_PER_MSEC / 1000; @@ -378,7 +378,7 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) if (!lazy) return nouveau_fence_wait_busy(fence, intr); - ret = fence_wait_timeout(&fence->base, intr, 15 * HZ); + ret = dma_fence_wait_timeout(&fence->base, intr, 15 * HZ); if (ret < 0) return ret; else if (!ret) @@ -391,7 +391,7 @@ int nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool exclusive, bool intr) { struct nouveau_fence_chan *fctx = chan->fence; - struct fence *fence; + struct dma_fence *fence; struct reservation_object *resv = nvbo->bo.resv; struct reservation_object_list *fobj; struct nouveau_fence *f; @@ -421,7 +421,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e } if (must_wait) - ret = fence_wait(fence, intr); + ret = dma_fence_wait(fence, intr); return ret; } @@ -446,7 +446,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e } if (must_wait) - ret = fence_wait(fence, intr); + ret = dma_fence_wait(fence, intr); } return ret; @@ -456,7 +456,7 @@ void nouveau_fence_unref(struct nouveau_fence **pfence) { if (*pfence) - fence_put(&(*pfence)->base); + dma_fence_put(&(*pfence)->base); *pfence = NULL; } @@ -484,12 +484,12 @@ nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, return ret; } -static const char *nouveau_fence_get_get_driver_name(struct fence *fence) +static const char *nouveau_fence_get_get_driver_name(struct dma_fence *fence) { return "nouveau"; } -static const char *nouveau_fence_get_timeline_name(struct fence *f) +static const char *nouveau_fence_get_timeline_name(struct dma_fence *f) { struct nouveau_fence *fence = from_fence(f); struct nouveau_fence_chan *fctx = nouveau_fctx(fence); @@ -503,7 +503,7 @@ static const char *nouveau_fence_get_timeline_name(struct fence *f) * result. The drm node should still be there, so we can derive the index from * the fence context. */ -static bool nouveau_fence_is_signaled(struct fence *f) +static bool nouveau_fence_is_signaled(struct dma_fence *f) { struct nouveau_fence *fence = from_fence(f); struct nouveau_fence_chan *fctx = nouveau_fctx(fence); @@ -519,7 +519,7 @@ static bool nouveau_fence_is_signaled(struct fence *f) return ret; } -static bool nouveau_fence_no_signaling(struct fence *f) +static bool nouveau_fence_no_signaling(struct dma_fence *f) { struct nouveau_fence *fence = from_fence(f); @@ -530,30 +530,30 @@ static bool nouveau_fence_no_signaling(struct fence *f) WARN_ON(atomic_read(&fence->base.refcount.refcount) <= 1); /* - * This needs uevents to work correctly, but fence_add_callback relies on + * This needs uevents to work correctly, but dma_fence_add_callback relies on * being able to enable signaling. It will still get signaled eventually, * just not right away. */ if (nouveau_fence_is_signaled(f)) { list_del(&fence->head); - fence_put(&fence->base); + dma_fence_put(&fence->base); return false; } return true; } -static void nouveau_fence_release(struct fence *f) +static void nouveau_fence_release(struct dma_fence *f) { struct nouveau_fence *fence = from_fence(f); struct nouveau_fence_chan *fctx = nouveau_fctx(fence); kref_put(&fctx->fence_ref, nouveau_fence_context_put); - fence_free(&fence->base); + dma_fence_free(&fence->base); } -static const struct fence_ops nouveau_fence_ops_legacy = { +static const struct dma_fence_ops nouveau_fence_ops_legacy = { .get_driver_name = nouveau_fence_get_get_driver_name, .get_timeline_name = nouveau_fence_get_timeline_name, .enable_signaling = nouveau_fence_no_signaling, @@ -562,7 +562,7 @@ static const struct fence_ops nouveau_fence_ops_legacy = { .release = nouveau_fence_release }; -static bool nouveau_fence_enable_signaling(struct fence *f) +static bool nouveau_fence_enable_signaling(struct dma_fence *f) { struct nouveau_fence *fence = from_fence(f); struct nouveau_fence_chan *fctx = nouveau_fctx(fence); @@ -573,18 +573,18 @@ static bool nouveau_fence_enable_signaling(struct fence *f) ret = nouveau_fence_no_signaling(f); if (ret) - set_bit(FENCE_FLAG_USER_BITS, &fence->base.flags); + set_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags); else if (!--fctx->notify_ref) nvif_notify_put(&fctx->notify); return ret; } -static const struct fence_ops nouveau_fence_ops_uevent = { +static const struct dma_fence_ops nouveau_fence_ops_uevent = { .get_driver_name = nouveau_fence_get_get_driver_name, .get_timeline_name = nouveau_fence_get_timeline_name, .enable_signaling = nouveau_fence_enable_signaling, .signaled = nouveau_fence_is_signaled, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .release = NULL }; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 64c4ce7115ad..41f3c019e534 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -1,14 +1,14 @@ #ifndef __NOUVEAU_FENCE_H__ #define __NOUVEAU_FENCE_H__ -#include +#include #include struct nouveau_drm; struct nouveau_bo; struct nouveau_fence { - struct fence base; + struct dma_fence base; struct list_head head; @@ -24,7 +24,7 @@ void nouveau_fence_unref(struct nouveau_fence **); int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); bool nouveau_fence_done(struct nouveau_fence *); -void nouveau_fence_work(struct fence *, void (*)(void *), void *); +void nouveau_fence_work(struct dma_fence *, void (*)(void *), void *); int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 0bd7164bc817..7f083c95f422 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -119,7 +119,7 @@ nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nvkm_vma *vma) const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM; struct reservation_object *resv = nvbo->bo.resv; struct reservation_object_list *fobj; - struct fence *fence = NULL; + struct dma_fence *fence = NULL; fobj = reservation_object_get_list(resv); diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c index 1915b7b82a59..fa8f2375c398 100644 --- a/drivers/gpu/drm/nouveau/nv04_fence.c +++ b/drivers/gpu/drm/nouveau/nv04_fence.c @@ -110,6 +110,6 @@ nv04_fence_create(struct nouveau_drm *drm) priv->base.context_new = nv04_fence_context_new; priv->base.context_del = nv04_fence_context_del; priv->base.contexts = 15; - priv->base.context_base = fence_context_alloc(priv->base.contexts); + priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 4e3de34ff6f4..f99fcf56928a 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c @@ -107,7 +107,7 @@ nv10_fence_create(struct nouveau_drm *drm) priv->base.context_new = nv10_fence_context_new; priv->base.context_del = nv10_fence_context_del; priv->base.contexts = 31; - priv->base.context_base = fence_context_alloc(priv->base.contexts); + priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); spin_lock_init(&priv->lock); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c index 7d5e562a55c5..79bc01111351 100644 --- a/drivers/gpu/drm/nouveau/nv17_fence.c +++ b/drivers/gpu/drm/nouveau/nv17_fence.c @@ -126,7 +126,7 @@ nv17_fence_create(struct nouveau_drm *drm) priv->base.context_new = nv17_fence_context_new; priv->base.context_del = nv10_fence_context_del; priv->base.contexts = 31; - priv->base.context_base = fence_context_alloc(priv->base.contexts); + priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); spin_lock_init(&priv->lock); ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index 4d6f202b7770..8c5295414578 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -97,7 +97,7 @@ nv50_fence_create(struct nouveau_drm *drm) priv->base.context_new = nv50_fence_context_new; priv->base.context_del = nv10_fence_context_del; priv->base.contexts = 127; - priv->base.context_base = fence_context_alloc(priv->base.contexts); + priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); spin_lock_init(&priv->lock); ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index 18bde9d8e6d6..23ef04b4e0b2 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -229,7 +229,7 @@ nv84_fence_create(struct nouveau_drm *drm) priv->base.context_del = nv84_fence_context_del; priv->base.contexts = fifo->nr; - priv->base.context_base = fence_context_alloc(priv->base.contexts); + priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); priv->base.uevent = true; /* Use VRAM if there is any ; otherwise fallback to system memory */ diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 5f3e5ad99de7..84995ebc6ffc 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -31,7 +31,7 @@ * Definitions taken from spice-protocol, plus kernel driver specific bits. */ -#include +#include #include #include #include @@ -190,7 +190,7 @@ enum { * spice-protocol/qxl_dev.h */ #define QXL_MAX_RES 96 struct qxl_release { - struct fence base; + struct dma_fence base; int id; int type; diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index cd83f050cf3e..50b4e522f05f 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -21,7 +21,7 @@ */ #include "qxl_drv.h" #include "qxl_object.h" -#include +#include /* * drawable cmd cache - allocate a bunch of VRAM pages, suballocate @@ -40,23 +40,24 @@ static const int release_size_per_bo[] = { RELEASE_SIZE, SURFACE_RELEASE_SIZE, RELEASE_SIZE }; static const int releases_per_bo[] = { RELEASES_PER_BO, SURFACE_RELEASES_PER_BO, RELEASES_PER_BO }; -static const char *qxl_get_driver_name(struct fence *fence) +static const char *qxl_get_driver_name(struct dma_fence *fence) { return "qxl"; } -static const char *qxl_get_timeline_name(struct fence *fence) +static const char *qxl_get_timeline_name(struct dma_fence *fence) { return "release"; } -static bool qxl_nop_signaling(struct fence *fence) +static bool qxl_nop_signaling(struct dma_fence *fence) { /* fences are always automatically signaled, so just pretend we did this.. */ return true; } -static long qxl_fence_wait(struct fence *fence, bool intr, signed long timeout) +static long qxl_fence_wait(struct dma_fence *fence, bool intr, + signed long timeout) { struct qxl_device *qdev; struct qxl_release *release; @@ -71,7 +72,7 @@ static long qxl_fence_wait(struct fence *fence, bool intr, signed long timeout) retry: sc++; - if (fence_is_signaled(fence)) + if (dma_fence_is_signaled(fence)) goto signaled; qxl_io_notify_oom(qdev); @@ -80,11 +81,11 @@ retry: if (!qxl_queue_garbage_collect(qdev, true)) break; - if (fence_is_signaled(fence)) + if (dma_fence_is_signaled(fence)) goto signaled; } - if (fence_is_signaled(fence)) + if (dma_fence_is_signaled(fence)) goto signaled; if (have_drawable_releases || sc < 4) { @@ -96,9 +97,9 @@ retry: return 0; if (have_drawable_releases && sc > 300) { - FENCE_WARN(fence, "failed to wait on release %llu " - "after spincount %d\n", - fence->context & ~0xf0000000, sc); + DMA_FENCE_WARN(fence, "failed to wait on release %llu " + "after spincount %d\n", + fence->context & ~0xf0000000, sc); goto signaled; } goto retry; @@ -115,7 +116,7 @@ signaled: return end - cur; } -static const struct fence_ops qxl_fence_ops = { +static const struct dma_fence_ops qxl_fence_ops = { .get_driver_name = qxl_get_driver_name, .get_timeline_name = qxl_get_timeline_name, .enable_signaling = qxl_nop_signaling, @@ -192,8 +193,8 @@ qxl_release_free(struct qxl_device *qdev, WARN_ON(list_empty(&release->bos)); qxl_release_free_list(release); - fence_signal(&release->base); - fence_put(&release->base); + dma_fence_signal(&release->base); + dma_fence_put(&release->base); } else { qxl_release_free_list(release); kfree(release); @@ -453,9 +454,9 @@ void qxl_release_fence_buffer_objects(struct qxl_release *release) * Since we never really allocated a context and we don't want to conflict, * set the highest bits. This will break if we really allow exporting of dma-bufs. */ - fence_init(&release->base, &qxl_fence_ops, &qdev->release_lock, - release->id | 0xf0000000, release->base.seqno); - trace_fence_emit(&release->base); + dma_fence_init(&release->base, &qxl_fence_ops, &qdev->release_lock, + release->id | 0xf0000000, release->base.seqno); + trace_dma_fence_emit(&release->base); driver = bdev->driver; glob = bo->glob; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 1b0dcad916b0..44e0c5ed6418 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -66,7 +66,7 @@ #include #include #include -#include +#include #include #include @@ -367,7 +367,7 @@ struct radeon_fence_driver { }; struct radeon_fence { - struct fence base; + struct dma_fence base; struct radeon_device *rdev; uint64_t seq; @@ -746,7 +746,7 @@ struct radeon_flip_work { uint64_t base; struct drm_pending_vblank_event *event; struct radeon_bo *old_rbo; - struct fence *fence; + struct dma_fence *fence; bool async; }; @@ -2514,9 +2514,9 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v); /* * Cast helper */ -extern const struct fence_ops radeon_fence_ops; +extern const struct dma_fence_ops radeon_fence_ops; -static inline struct radeon_fence *to_radeon_fence(struct fence *f) +static inline struct radeon_fence *to_radeon_fence(struct dma_fence *f) { struct radeon_fence *__f = container_of(f, struct radeon_fence, base); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index eb92aef46e3c..36b7ac7e57e5 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1320,7 +1320,7 @@ int radeon_device_init(struct radeon_device *rdev, for (i = 0; i < RADEON_NUM_RINGS; i++) { rdev->ring[i].idx = i; } - rdev->fence_context = fence_context_alloc(RADEON_NUM_RINGS); + rdev->fence_context = dma_fence_context_alloc(RADEON_NUM_RINGS); DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n", radeon_family_name[rdev->family], pdev->vendor, pdev->device, diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index cdb8cb568c15..e7409e8a9f87 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -437,7 +437,7 @@ static void radeon_flip_work_func(struct work_struct *__work) down_read(&rdev->exclusive_lock); } } else - r = fence_wait(work->fence, false); + r = dma_fence_wait(work->fence, false); if (r) DRM_ERROR("failed to wait on page flip fence (%d)!\n", r); @@ -447,7 +447,7 @@ static void radeon_flip_work_func(struct work_struct *__work) * confused about which BO the CRTC is scanning out */ - fence_put(work->fence); + dma_fence_put(work->fence); work->fence = NULL; } @@ -542,7 +542,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, DRM_ERROR("failed to pin new rbo buffer before flip\n"); goto cleanup; } - work->fence = fence_get(reservation_object_get_excl(new_rbo->tbo.resv)); + work->fence = dma_fence_get(reservation_object_get_excl(new_rbo->tbo.resv)); radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL); radeon_bo_unreserve(new_rbo); @@ -617,7 +617,7 @@ pflip_cleanup: cleanup: drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); - fence_put(work->fence); + dma_fence_put(work->fence); kfree(work); return r; } diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 7ef075acde9c..ef09f0a63754 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -141,8 +141,10 @@ int radeon_fence_emit(struct radeon_device *rdev, (*fence)->seq = seq = ++rdev->fence_drv[ring].sync_seq[ring]; (*fence)->ring = ring; (*fence)->is_vm_update = false; - fence_init(&(*fence)->base, &radeon_fence_ops, - &rdev->fence_queue.lock, rdev->fence_context + ring, seq); + dma_fence_init(&(*fence)->base, &radeon_fence_ops, + &rdev->fence_queue.lock, + rdev->fence_context + ring, + seq); radeon_fence_ring_emit(rdev, ring, *fence); trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq); radeon_fence_schedule_check(rdev, ring); @@ -169,18 +171,18 @@ static int radeon_fence_check_signaled(wait_queue_t *wait, unsigned mode, int fl */ seq = atomic64_read(&fence->rdev->fence_drv[fence->ring].last_seq); if (seq >= fence->seq) { - int ret = fence_signal_locked(&fence->base); + int ret = dma_fence_signal_locked(&fence->base); if (!ret) - FENCE_TRACE(&fence->base, "signaled from irq context\n"); + DMA_FENCE_TRACE(&fence->base, "signaled from irq context\n"); else - FENCE_TRACE(&fence->base, "was already signaled\n"); + DMA_FENCE_TRACE(&fence->base, "was already signaled\n"); radeon_irq_kms_sw_irq_put(fence->rdev, fence->ring); __remove_wait_queue(&fence->rdev->fence_queue, &fence->fence_wake); - fence_put(&fence->base); + dma_fence_put(&fence->base); } else - FENCE_TRACE(&fence->base, "pending\n"); + DMA_FENCE_TRACE(&fence->base, "pending\n"); return 0; } @@ -351,7 +353,7 @@ static bool radeon_fence_seq_signaled(struct radeon_device *rdev, return false; } -static bool radeon_fence_is_signaled(struct fence *f) +static bool radeon_fence_is_signaled(struct dma_fence *f) { struct radeon_fence *fence = to_radeon_fence(f); struct radeon_device *rdev = fence->rdev; @@ -381,7 +383,7 @@ static bool radeon_fence_is_signaled(struct fence *f) * to fence_queue that checks if this fence is signaled, and if so it * signals the fence and removes itself. */ -static bool radeon_fence_enable_signaling(struct fence *f) +static bool radeon_fence_enable_signaling(struct dma_fence *f) { struct radeon_fence *fence = to_radeon_fence(f); struct radeon_device *rdev = fence->rdev; @@ -414,9 +416,9 @@ static bool radeon_fence_enable_signaling(struct fence *f) fence->fence_wake.private = NULL; fence->fence_wake.func = radeon_fence_check_signaled; __add_wait_queue(&rdev->fence_queue, &fence->fence_wake); - fence_get(f); + dma_fence_get(f); - FENCE_TRACE(&fence->base, "armed on ring %i!\n", fence->ring); + DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", fence->ring); return true; } @@ -436,9 +438,9 @@ bool radeon_fence_signaled(struct radeon_fence *fence) if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) { int ret; - ret = fence_signal(&fence->base); + ret = dma_fence_signal(&fence->base); if (!ret) - FENCE_TRACE(&fence->base, "signaled from radeon_fence_signaled\n"); + DMA_FENCE_TRACE(&fence->base, "signaled from radeon_fence_signaled\n"); return true; } return false; @@ -552,7 +554,7 @@ long radeon_fence_wait_timeout(struct radeon_fence *fence, bool intr, long timeo * exclusive_lock is not held in that case. */ if (WARN_ON_ONCE(!to_radeon_fence(&fence->base))) - return fence_wait(&fence->base, intr); + return dma_fence_wait(&fence->base, intr); seq[fence->ring] = fence->seq; r = radeon_fence_wait_seq_timeout(fence->rdev, seq, intr, timeout); @@ -560,9 +562,9 @@ long radeon_fence_wait_timeout(struct radeon_fence *fence, bool intr, long timeo return r; } - r_sig = fence_signal(&fence->base); + r_sig = dma_fence_signal(&fence->base); if (!r_sig) - FENCE_TRACE(&fence->base, "signaled from fence_wait\n"); + DMA_FENCE_TRACE(&fence->base, "signaled from fence_wait\n"); return r; } @@ -697,7 +699,7 @@ int radeon_fence_wait_empty(struct radeon_device *rdev, int ring) */ struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) { - fence_get(&fence->base); + dma_fence_get(&fence->base); return fence; } @@ -714,7 +716,7 @@ void radeon_fence_unref(struct radeon_fence **fence) *fence = NULL; if (tmp) { - fence_put(&tmp->base); + dma_fence_put(&tmp->base); } } @@ -1028,12 +1030,12 @@ int radeon_debugfs_fence_init(struct radeon_device *rdev) #endif } -static const char *radeon_fence_get_driver_name(struct fence *fence) +static const char *radeon_fence_get_driver_name(struct dma_fence *fence) { return "radeon"; } -static const char *radeon_fence_get_timeline_name(struct fence *f) +static const char *radeon_fence_get_timeline_name(struct dma_fence *f) { struct radeon_fence *fence = to_radeon_fence(f); switch (fence->ring) { @@ -1051,16 +1053,16 @@ static const char *radeon_fence_get_timeline_name(struct fence *f) static inline bool radeon_test_signaled(struct radeon_fence *fence) { - return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags); + return test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags); } struct radeon_wait_cb { - struct fence_cb base; + struct dma_fence_cb base; struct task_struct *task; }; static void -radeon_fence_wait_cb(struct fence *fence, struct fence_cb *cb) +radeon_fence_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb) { struct radeon_wait_cb *wait = container_of(cb, struct radeon_wait_cb, base); @@ -1068,7 +1070,7 @@ radeon_fence_wait_cb(struct fence *fence, struct fence_cb *cb) wake_up_process(wait->task); } -static signed long radeon_fence_default_wait(struct fence *f, bool intr, +static signed long radeon_fence_default_wait(struct dma_fence *f, bool intr, signed long t) { struct radeon_fence *fence = to_radeon_fence(f); @@ -1077,7 +1079,7 @@ static signed long radeon_fence_default_wait(struct fence *f, bool intr, cb.task = current; - if (fence_add_callback(f, &cb.base, radeon_fence_wait_cb)) + if (dma_fence_add_callback(f, &cb.base, radeon_fence_wait_cb)) return t; while (t > 0) { @@ -1105,12 +1107,12 @@ static signed long radeon_fence_default_wait(struct fence *f, bool intr, } __set_current_state(TASK_RUNNING); - fence_remove_callback(f, &cb.base); + dma_fence_remove_callback(f, &cb.base); return t; } -const struct fence_ops radeon_fence_ops = { +const struct dma_fence_ops radeon_fence_ops = { .get_driver_name = radeon_fence_get_driver_name, .get_timeline_name = radeon_fence_get_timeline_name, .enable_signaling = radeon_fence_enable_signaling, diff --git a/drivers/gpu/drm/radeon/radeon_sync.c b/drivers/gpu/drm/radeon/radeon_sync.c index 02ac8a1de4ff..be5d7a38d3aa 100644 --- a/drivers/gpu/drm/radeon/radeon_sync.c +++ b/drivers/gpu/drm/radeon/radeon_sync.c @@ -92,7 +92,7 @@ int radeon_sync_resv(struct radeon_device *rdev, bool shared) { struct reservation_object_list *flist; - struct fence *f; + struct dma_fence *f; struct radeon_fence *fence; unsigned i; int r = 0; @@ -103,7 +103,7 @@ int radeon_sync_resv(struct radeon_device *rdev, if (fence && fence->rdev == rdev) radeon_sync_fence(sync, fence); else if (f) - r = fence_wait(f, true); + r = dma_fence_wait(f, true); flist = reservation_object_get_list(resv); if (shared || !flist || r) @@ -116,7 +116,7 @@ int radeon_sync_resv(struct radeon_device *rdev, if (fence && fence->rdev == rdev) radeon_sync_fence(sync, fence); else - r = fence_wait(f, true); + r = dma_fence_wait(f, true); if (r) break; diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 0cd0e7bdee55..d34d1cf33895 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -467,7 +467,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, { int32_t *msg, msg_type, handle; unsigned img_size = 0; - struct fence *f; + struct dma_fence *f; void *ptr; int i, r; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index fc6217dfe401..915e0d1c316a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -148,7 +148,7 @@ static void ttm_bo_release_list(struct kref *list_kref) BUG_ON(!list_empty(&bo->ddestroy)); ttm_tt_destroy(bo->ttm); atomic_dec(&bo->glob->bo_count); - fence_put(bo->moving); + dma_fence_put(bo->moving); if (bo->resv == &bo->ttm_resv) reservation_object_fini(&bo->ttm_resv); mutex_destroy(&bo->wu_mutex); @@ -426,20 +426,20 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) { struct reservation_object_list *fobj; - struct fence *fence; + struct dma_fence *fence; int i; fobj = reservation_object_get_list(bo->resv); fence = reservation_object_get_excl(bo->resv); if (fence && !fence->ops->signaled) - fence_enable_sw_signaling(fence); + dma_fence_enable_sw_signaling(fence); for (i = 0; fobj && i < fobj->shared_count; ++i) { fence = rcu_dereference_protected(fobj->shared[i], reservation_object_held(bo->resv)); if (!fence->ops->signaled) - fence_enable_sw_signaling(fence); + dma_fence_enable_sw_signaling(fence); } } @@ -792,11 +792,11 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { - struct fence *fence; + struct dma_fence *fence; int ret; spin_lock(&man->move_lock); - fence = fence_get(man->move); + fence = dma_fence_get(man->move); spin_unlock(&man->move_lock); if (fence) { @@ -806,7 +806,7 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, if (unlikely(ret)) return ret; - fence_put(bo->moving); + dma_fence_put(bo->moving); bo->moving = fence; } @@ -1286,7 +1286,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, { struct ttm_mem_type_manager *man = &bdev->man[mem_type]; struct ttm_bo_global *glob = bdev->glob; - struct fence *fence; + struct dma_fence *fence; int ret; /* @@ -1309,12 +1309,12 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, spin_unlock(&glob->lru_lock); spin_lock(&man->move_lock); - fence = fence_get(man->move); + fence = dma_fence_get(man->move); spin_unlock(&man->move_lock); if (fence) { - ret = fence_wait(fence, false); - fence_put(fence); + ret = dma_fence_wait(fence, false); + dma_fence_put(fence); if (ret) { if (allow_errors) { return ret; @@ -1343,7 +1343,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) mem_type); return ret; } - fence_put(man->move); + dma_fence_put(man->move); man->use_type = false; man->has_type = false; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index bf6e21655c57..d0459b392e5e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -644,7 +644,7 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) EXPORT_SYMBOL(ttm_bo_kunmap); int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, - struct fence *fence, + struct dma_fence *fence, bool evict, struct ttm_mem_reg *new_mem) { @@ -674,8 +674,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, * operation has completed. */ - fence_put(bo->moving); - bo->moving = fence_get(fence); + dma_fence_put(bo->moving); + bo->moving = dma_fence_get(fence); ret = ttm_buffer_object_transfer(bo, &ghost_obj); if (ret) @@ -706,7 +706,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, EXPORT_SYMBOL(ttm_bo_move_accel_cleanup); int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, - struct fence *fence, bool evict, + struct dma_fence *fence, bool evict, struct ttm_mem_reg *new_mem) { struct ttm_bo_device *bdev = bo->bdev; @@ -730,8 +730,8 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, * operation has completed. */ - fence_put(bo->moving); - bo->moving = fence_get(fence); + dma_fence_put(bo->moving); + bo->moving = dma_fence_get(fence); ret = ttm_buffer_object_transfer(bo, &ghost_obj); if (ret) @@ -761,16 +761,16 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, */ spin_lock(&from->move_lock); - if (!from->move || fence_is_later(fence, from->move)) { - fence_put(from->move); - from->move = fence_get(fence); + if (!from->move || dma_fence_is_later(fence, from->move)) { + dma_fence_put(from->move); + from->move = dma_fence_get(fence); } spin_unlock(&from->move_lock); ttm_bo_free_old_node(bo); - fence_put(bo->moving); - bo->moving = fence_get(fence); + dma_fence_put(bo->moving); + bo->moving = dma_fence_get(fence); } else { /** diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index a6ed9d5e5167..4748aedc933a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -54,7 +54,7 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo, /* * Quick non-stalling check for idle. */ - if (fence_is_signaled(bo->moving)) + if (dma_fence_is_signaled(bo->moving)) goto out_clear; /* @@ -67,14 +67,14 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo, goto out_unlock; up_read(&vma->vm_mm->mmap_sem); - (void) fence_wait(bo->moving, true); + (void) dma_fence_wait(bo->moving, true); goto out_unlock; } /* * Ordinary wait. */ - ret = fence_wait(bo->moving, true); + ret = dma_fence_wait(bo->moving, true); if (unlikely(ret != 0)) { ret = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; @@ -82,7 +82,7 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo, } out_clear: - fence_put(bo->moving); + dma_fence_put(bo->moving); bo->moving = NULL; out_unlock: diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index a80717b35dc6..d35bc491e8de 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -179,7 +179,8 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, EXPORT_SYMBOL(ttm_eu_reserve_buffers); void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, - struct list_head *list, struct fence *fence) + struct list_head *list, + struct dma_fence *fence) { struct ttm_validate_buffer *entry; struct ttm_buffer_object *bo; diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c index 5c57c1ffa1f9..488909a21ed8 100644 --- a/drivers/gpu/drm/vgem/vgem_fence.c +++ b/drivers/gpu/drm/vgem/vgem_fence.c @@ -28,56 +28,57 @@ #define VGEM_FENCE_TIMEOUT (10*HZ) struct vgem_fence { - struct fence base; + struct dma_fence base; struct spinlock lock; struct timer_list timer; }; -static const char *vgem_fence_get_driver_name(struct fence *fence) +static const char *vgem_fence_get_driver_name(struct dma_fence *fence) { return "vgem"; } -static const char *vgem_fence_get_timeline_name(struct fence *fence) +static const char *vgem_fence_get_timeline_name(struct dma_fence *fence) { return "unbound"; } -static bool vgem_fence_signaled(struct fence *fence) +static bool vgem_fence_signaled(struct dma_fence *fence) { return false; } -static bool vgem_fence_enable_signaling(struct fence *fence) +static bool vgem_fence_enable_signaling(struct dma_fence *fence) { return true; } -static void vgem_fence_release(struct fence *base) +static void vgem_fence_release(struct dma_fence *base) { struct vgem_fence *fence = container_of(base, typeof(*fence), base); del_timer_sync(&fence->timer); - fence_free(&fence->base); + dma_fence_free(&fence->base); } -static void vgem_fence_value_str(struct fence *fence, char *str, int size) +static void vgem_fence_value_str(struct dma_fence *fence, char *str, int size) { snprintf(str, size, "%u", fence->seqno); } -static void vgem_fence_timeline_value_str(struct fence *fence, char *str, +static void vgem_fence_timeline_value_str(struct dma_fence *fence, char *str, int size) { - snprintf(str, size, "%u", fence_is_signaled(fence) ? fence->seqno : 0); + snprintf(str, size, "%u", + dma_fence_is_signaled(fence) ? fence->seqno : 0); } -static const struct fence_ops vgem_fence_ops = { +static const struct dma_fence_ops vgem_fence_ops = { .get_driver_name = vgem_fence_get_driver_name, .get_timeline_name = vgem_fence_get_timeline_name, .enable_signaling = vgem_fence_enable_signaling, .signaled = vgem_fence_signaled, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .release = vgem_fence_release, .fence_value_str = vgem_fence_value_str, @@ -88,11 +89,11 @@ static void vgem_fence_timeout(unsigned long data) { struct vgem_fence *fence = (struct vgem_fence *)data; - fence_signal(&fence->base); + dma_fence_signal(&fence->base); } -static struct fence *vgem_fence_create(struct vgem_file *vfile, - unsigned int flags) +static struct dma_fence *vgem_fence_create(struct vgem_file *vfile, + unsigned int flags) { struct vgem_fence *fence; @@ -101,8 +102,8 @@ static struct fence *vgem_fence_create(struct vgem_file *vfile, return NULL; spin_lock_init(&fence->lock); - fence_init(&fence->base, &vgem_fence_ops, &fence->lock, - fence_context_alloc(1), 1); + dma_fence_init(&fence->base, &vgem_fence_ops, &fence->lock, + dma_fence_context_alloc(1), 1); setup_timer(&fence->timer, vgem_fence_timeout, (unsigned long)fence); @@ -157,7 +158,7 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, struct vgem_file *vfile = file->driver_priv; struct reservation_object *resv; struct drm_gem_object *obj; - struct fence *fence; + struct dma_fence *fence; int ret; if (arg->flags & ~VGEM_FENCE_WRITE) @@ -209,8 +210,8 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, } err_fence: if (ret) { - fence_signal(fence); - fence_put(fence); + dma_fence_signal(fence); + dma_fence_put(fence); } err: drm_gem_object_unreference_unlocked(obj); @@ -239,7 +240,7 @@ int vgem_fence_signal_ioctl(struct drm_device *dev, { struct vgem_file *vfile = file->driver_priv; struct drm_vgem_fence_signal *arg = data; - struct fence *fence; + struct dma_fence *fence; int ret = 0; if (arg->flags) @@ -253,11 +254,11 @@ int vgem_fence_signal_ioctl(struct drm_device *dev, if (IS_ERR(fence)) return PTR_ERR(fence); - if (fence_is_signaled(fence)) + if (dma_fence_is_signaled(fence)) ret = -ETIMEDOUT; - fence_signal(fence); - fence_put(fence); + dma_fence_signal(fence); + dma_fence_put(fence); return ret; } @@ -271,8 +272,8 @@ int vgem_fence_open(struct vgem_file *vfile) static int __vgem_fence_idr_fini(int id, void *p, void *data) { - fence_signal(p); - fence_put(p); + dma_fence_signal(p); + dma_fence_put(p); return 0; } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index ae59080d63d1..ec1ebdcfe80b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -82,7 +82,7 @@ struct virtio_gpu_fence_driver { }; struct virtio_gpu_fence { - struct fence f; + struct dma_fence f; struct virtio_gpu_fence_driver *drv; struct list_head node; uint64_t seq; diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c index f3f70fa8a4c7..23353521f903 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fence.c +++ b/drivers/gpu/drm/virtio/virtgpu_fence.c @@ -26,22 +26,22 @@ #include #include "virtgpu_drv.h" -static const char *virtio_get_driver_name(struct fence *f) +static const char *virtio_get_driver_name(struct dma_fence *f) { return "virtio_gpu"; } -static const char *virtio_get_timeline_name(struct fence *f) +static const char *virtio_get_timeline_name(struct dma_fence *f) { return "controlq"; } -static bool virtio_enable_signaling(struct fence *f) +static bool virtio_enable_signaling(struct dma_fence *f) { return true; } -static bool virtio_signaled(struct fence *f) +static bool virtio_signaled(struct dma_fence *f) { struct virtio_gpu_fence *fence = to_virtio_fence(f); @@ -50,26 +50,26 @@ static bool virtio_signaled(struct fence *f) return false; } -static void virtio_fence_value_str(struct fence *f, char *str, int size) +static void virtio_fence_value_str(struct dma_fence *f, char *str, int size) { struct virtio_gpu_fence *fence = to_virtio_fence(f); snprintf(str, size, "%llu", fence->seq); } -static void virtio_timeline_value_str(struct fence *f, char *str, int size) +static void virtio_timeline_value_str(struct dma_fence *f, char *str, int size) { struct virtio_gpu_fence *fence = to_virtio_fence(f); snprintf(str, size, "%llu", (u64)atomic64_read(&fence->drv->last_seq)); } -static const struct fence_ops virtio_fence_ops = { +static const struct dma_fence_ops virtio_fence_ops = { .get_driver_name = virtio_get_driver_name, .get_timeline_name = virtio_get_timeline_name, .enable_signaling = virtio_enable_signaling, .signaled = virtio_signaled, - .wait = fence_default_wait, + .wait = dma_fence_default_wait, .fence_value_str = virtio_fence_value_str, .timeline_value_str = virtio_timeline_value_str, }; @@ -88,9 +88,9 @@ int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev, spin_lock_irqsave(&drv->lock, irq_flags); (*fence)->drv = drv; (*fence)->seq = ++drv->sync_seq; - fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock, - drv->context, (*fence)->seq); - fence_get(&(*fence)->f); + dma_fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock, + drv->context, (*fence)->seq); + dma_fence_get(&(*fence)->f); list_add_tail(&(*fence)->node, &drv->fences); spin_unlock_irqrestore(&drv->lock, irq_flags); @@ -111,9 +111,9 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev, list_for_each_entry_safe(fence, tmp, &drv->fences, node) { if (last_seq < fence->seq) continue; - fence_signal_locked(&fence->f); + dma_fence_signal_locked(&fence->f); list_del(&fence->node); - fence_put(&fence->f); + dma_fence_put(&fence->f); } spin_unlock_irqrestore(&drv->lock, irq_flags); } diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 818478b4c4f0..61f3a963af95 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -172,7 +172,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, /* fence the command bo */ virtio_gpu_unref_list(&validate_list); drm_free_large(buflist); - fence_put(&fence->f); + dma_fence_put(&fence->f); return 0; out_unresv: @@ -298,7 +298,7 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, drm_gem_object_release(obj); if (vgdev->has_virgl_3d) { virtio_gpu_unref_list(&validate_list); - fence_put(&fence->f); + dma_fence_put(&fence->f); } return ret; } @@ -309,13 +309,13 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, if (vgdev->has_virgl_3d) { virtio_gpu_unref_list(&validate_list); - fence_put(&fence->f); + dma_fence_put(&fence->f); } return 0; fail_unref: if (vgdev->has_virgl_3d) { virtio_gpu_unref_list(&validate_list); - fence_put(&fence->f); + dma_fence_put(&fence->f); } //fail_obj: // drm_gem_object_handle_unreference_unlocked(obj); @@ -383,7 +383,7 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, reservation_object_add_excl_fence(qobj->tbo.resv, &fence->f); - fence_put(&fence->f); + dma_fence_put(&fence->f); out_unres: virtio_gpu_object_unreserve(qobj); out: @@ -431,7 +431,7 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, args->level, &box, &fence); reservation_object_add_excl_fence(qobj->tbo.resv, &fence->f); - fence_put(&fence->f); + dma_fence_put(&fence->f); } out_unres: diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 036b0fbae0fb..1235519853f4 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -159,7 +159,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) virtio_gpu_init_vq(&vgdev->ctrlq, virtio_gpu_dequeue_ctrl_func); virtio_gpu_init_vq(&vgdev->cursorq, virtio_gpu_dequeue_cursor_func); - vgdev->fence_drv.context = fence_context_alloc(1); + vgdev->fence_drv.context = dma_fence_context_alloc(1); spin_lock_init(&vgdev->fence_drv.lock); INIT_LIST_HEAD(&vgdev->fence_drv.fences); INIT_LIST_HEAD(&vgdev->cap_cache); diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index ba28c0f6f28a..cb75f0663ba0 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -152,7 +152,7 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane, if (!ret) { reservation_object_add_excl_fence(bo->tbo.resv, &fence->f); - fence_put(&fence->f); + dma_fence_put(&fence->f); fence = NULL; virtio_gpu_object_unreserve(bo); virtio_gpu_object_wait(bo, false); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 26ac8e80a478..6541dd8b82dc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -108,7 +108,7 @@ fman_from_fence(struct vmw_fence_obj *fence) * objects with actions attached to them. */ -static void vmw_fence_obj_destroy(struct fence *f) +static void vmw_fence_obj_destroy(struct dma_fence *f) { struct vmw_fence_obj *fence = container_of(f, struct vmw_fence_obj, base); @@ -123,17 +123,17 @@ static void vmw_fence_obj_destroy(struct fence *f) fence->destroy(fence); } -static const char *vmw_fence_get_driver_name(struct fence *f) +static const char *vmw_fence_get_driver_name(struct dma_fence *f) { return "vmwgfx"; } -static const char *vmw_fence_get_timeline_name(struct fence *f) +static const char *vmw_fence_get_timeline_name(struct dma_fence *f) { return "svga"; } -static bool vmw_fence_enable_signaling(struct fence *f) +static bool vmw_fence_enable_signaling(struct dma_fence *f) { struct vmw_fence_obj *fence = container_of(f, struct vmw_fence_obj, base); @@ -152,12 +152,12 @@ static bool vmw_fence_enable_signaling(struct fence *f) } struct vmwgfx_wait_cb { - struct fence_cb base; + struct dma_fence_cb base; struct task_struct *task; }; static void -vmwgfx_wait_cb(struct fence *fence, struct fence_cb *cb) +vmwgfx_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb) { struct vmwgfx_wait_cb *wait = container_of(cb, struct vmwgfx_wait_cb, base); @@ -167,7 +167,7 @@ vmwgfx_wait_cb(struct fence *fence, struct fence_cb *cb) static void __vmw_fences_update(struct vmw_fence_manager *fman); -static long vmw_fence_wait(struct fence *f, bool intr, signed long timeout) +static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout) { struct vmw_fence_obj *fence = container_of(f, struct vmw_fence_obj, base); @@ -197,7 +197,7 @@ static long vmw_fence_wait(struct fence *f, bool intr, signed long timeout) while (ret > 0) { __vmw_fences_update(fman); - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &f->flags)) + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags)) break; if (intr) @@ -225,7 +225,7 @@ out: return ret; } -static struct fence_ops vmw_fence_ops = { +static struct dma_fence_ops vmw_fence_ops = { .get_driver_name = vmw_fence_get_driver_name, .get_timeline_name = vmw_fence_get_timeline_name, .enable_signaling = vmw_fence_enable_signaling, @@ -298,7 +298,7 @@ struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv) fman->event_fence_action_size = ttm_round_pot(sizeof(struct vmw_event_fence_action)); mutex_init(&fman->goal_irq_mutex); - fman->ctx = fence_context_alloc(1); + fman->ctx = dma_fence_context_alloc(1); return fman; } @@ -326,8 +326,8 @@ static int vmw_fence_obj_init(struct vmw_fence_manager *fman, unsigned long irq_flags; int ret = 0; - fence_init(&fence->base, &vmw_fence_ops, &fman->lock, - fman->ctx, seqno); + dma_fence_init(&fence->base, &vmw_fence_ops, &fman->lock, + fman->ctx, seqno); INIT_LIST_HEAD(&fence->seq_passed_actions); fence->destroy = destroy; @@ -431,7 +431,7 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence) u32 goal_seqno; u32 *fifo_mem; - if (fence_is_signaled_locked(&fence->base)) + if (dma_fence_is_signaled_locked(&fence->base)) return false; fifo_mem = fman->dev_priv->mmio_virt; @@ -459,7 +459,7 @@ rerun: list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) { if (seqno - fence->base.seqno < VMW_FENCE_WRAP) { list_del_init(&fence->head); - fence_signal_locked(&fence->base); + dma_fence_signal_locked(&fence->base); INIT_LIST_HEAD(&action_list); list_splice_init(&fence->seq_passed_actions, &action_list); @@ -500,18 +500,18 @@ bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence) { struct vmw_fence_manager *fman = fman_from_fence(fence); - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags)) + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags)) return 1; vmw_fences_update(fman); - return fence_is_signaled(&fence->base); + return dma_fence_is_signaled(&fence->base); } int vmw_fence_obj_wait(struct vmw_fence_obj *fence, bool lazy, bool interruptible, unsigned long timeout) { - long ret = fence_wait_timeout(&fence->base, interruptible, timeout); + long ret = dma_fence_wait_timeout(&fence->base, interruptible, timeout); if (likely(ret > 0)) return 0; @@ -530,7 +530,7 @@ void vmw_fence_obj_flush(struct vmw_fence_obj *fence) static void vmw_fence_destroy(struct vmw_fence_obj *fence) { - fence_free(&fence->base); + dma_fence_free(&fence->base); } int vmw_fence_create(struct vmw_fence_manager *fman, @@ -669,7 +669,7 @@ void vmw_fence_fifo_down(struct vmw_fence_manager *fman) struct vmw_fence_obj *fence = list_entry(fman->fence_list.prev, struct vmw_fence_obj, head); - fence_get(&fence->base); + dma_fence_get(&fence->base); spin_unlock_irq(&fman->lock); ret = vmw_fence_obj_wait(fence, false, false, @@ -677,7 +677,7 @@ void vmw_fence_fifo_down(struct vmw_fence_manager *fman) if (unlikely(ret != 0)) { list_del_init(&fence->head); - fence_signal(&fence->base); + dma_fence_signal(&fence->base); INIT_LIST_HEAD(&action_list); list_splice_init(&fence->seq_passed_actions, &action_list); @@ -685,7 +685,7 @@ void vmw_fence_fifo_down(struct vmw_fence_manager *fman) } BUG_ON(!list_empty(&fence->head)); - fence_put(&fence->base); + dma_fence_put(&fence->base); spin_lock_irq(&fman->lock); } spin_unlock_irq(&fman->lock); @@ -884,7 +884,7 @@ static void vmw_fence_obj_add_action(struct vmw_fence_obj *fence, spin_lock_irqsave(&fman->lock, irq_flags); fman->pending_actions[action->type]++; - if (fence_is_signaled_locked(&fence->base)) { + if (dma_fence_is_signaled_locked(&fence->base)) { struct list_head action_list; INIT_LIST_HEAD(&action_list); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h index 83ae301ee141..d9d85aa6ed20 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h @@ -27,7 +27,7 @@ #ifndef _VMWGFX_FENCE_H_ -#include +#include #define VMW_FENCE_WAIT_TIMEOUT (5*HZ) @@ -52,7 +52,7 @@ struct vmw_fence_action { }; struct vmw_fence_obj { - struct fence base; + struct dma_fence base; struct list_head head; struct list_head seq_passed_actions; @@ -71,14 +71,14 @@ vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p) *fence_p = NULL; if (fence) - fence_put(&fence->base); + dma_fence_put(&fence->base); } static inline struct vmw_fence_obj * vmw_fence_obj_reference(struct vmw_fence_obj *fence) { if (fence) - fence_get(&fence->base); + dma_fence_get(&fence->base); return fence; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 1a85fb2d4dc6..8e86d6d4141b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1454,7 +1454,7 @@ void vmw_fence_single_bo(struct ttm_buffer_object *bo, if (fence == NULL) { vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); reservation_object_add_excl_fence(bo->resv, &fence->base); - fence_put(&fence->base); + dma_fence_put(&fence->base); } else reservation_object_add_excl_fence(bo->resv, &fence->base); } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 672644031bd5..e336e3901876 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -57,7 +57,7 @@ #include #include #include -#include +#include #include #include @@ -362,7 +362,7 @@ struct drm_ioctl_desc { struct drm_pending_event { struct completion *completion; struct drm_event *event; - struct fence *fence; + struct dma_fence *fence; struct list_head link; struct list_head pending_link; struct drm_file *file_priv; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index bc860cfc67ca..fa1aa214c8ea 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -54,7 +54,7 @@ struct drm_mode_set; struct drm_file; struct drm_clip_rect; struct device_node; -struct fence; +struct dma_fence; struct edid; static inline int64_t U642I64(uint64_t val) diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 98b39d66eb32..c5e8a0df1623 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -59,7 +59,7 @@ struct drm_plane_state { struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */ struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */ - struct fence *fence; + struct dma_fence *fence; /* Signed dest location allows it to be partially off screen */ int32_t crtc_x, crtc_y; diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 9eb940d6755f..5beae7969bf7 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -209,7 +209,7 @@ struct ttm_buffer_object { * Members protected by a bo reservation. */ - struct fence *moving; + struct dma_fence *moving; struct drm_vma_offset_node vma_node; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 4f0a92185995..27e9c26c9150 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -303,7 +303,7 @@ struct ttm_mem_type_manager { /* * Protected by @move_lock. */ - struct fence *move; + struct dma_fence *move; }; /** @@ -1025,7 +1025,7 @@ extern void ttm_bo_free_old_node(struct ttm_buffer_object *bo); */ extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, - struct fence *fence, bool evict, + struct dma_fence *fence, bool evict, struct ttm_mem_reg *new_mem); /** @@ -1040,7 +1040,7 @@ extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, * immediately or hang it on a temporary buffer object. */ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, - struct fence *fence, bool evict, + struct dma_fence *fence, bool evict, struct ttm_mem_reg *new_mem); /** diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h index b620c317c772..47f35b8e6d09 100644 --- a/include/drm/ttm/ttm_execbuf_util.h +++ b/include/drm/ttm/ttm_execbuf_util.h @@ -114,6 +114,6 @@ extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, extern void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, struct list_head *list, - struct fence *fence); + struct dma_fence *fence); #endif diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index e0b0741ae671..8daeb3ce0016 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include struct device; @@ -143,7 +143,7 @@ struct dma_buf { wait_queue_head_t poll; struct dma_buf_poll_cb_t { - struct fence_cb cb; + struct dma_fence_cb cb; wait_queue_head_t *poll; unsigned long active; diff --git a/include/linux/dma-fence-array.h b/include/linux/dma-fence-array.h new file mode 100644 index 000000000000..5900945f962d --- /dev/null +++ b/include/linux/dma-fence-array.h @@ -0,0 +1,86 @@ +/* + * fence-array: aggregates fence to be waited together + * + * Copyright (C) 2016 Collabora Ltd + * Copyright (C) 2016 Advanced Micro Devices, Inc. + * Authors: + * Gustavo Padovan + * Christian König + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __LINUX_DMA_FENCE_ARRAY_H +#define __LINUX_DMA_FENCE_ARRAY_H + +#include + +/** + * struct dma_fence_array_cb - callback helper for fence array + * @cb: fence callback structure for signaling + * @array: reference to the parent fence array object + */ +struct dma_fence_array_cb { + struct dma_fence_cb cb; + struct dma_fence_array *array; +}; + +/** + * struct dma_fence_array - fence to represent an array of fences + * @base: fence base class + * @lock: spinlock for fence handling + * @num_fences: number of fences in the array + * @num_pending: fences in the array still pending + * @fences: array of the fences + */ +struct dma_fence_array { + struct dma_fence base; + + spinlock_t lock; + unsigned num_fences; + atomic_t num_pending; + struct dma_fence **fences; +}; + +extern const struct dma_fence_ops dma_fence_array_ops; + +/** + * dma_fence_is_array - check if a fence is from the array subsclass + * @fence: fence to test + * + * Return true if it is a dma_fence_array and false otherwise. + */ +static inline bool dma_fence_is_array(struct dma_fence *fence) +{ + return fence->ops == &dma_fence_array_ops; +} + +/** + * to_dma_fence_array - cast a fence to a dma_fence_array + * @fence: fence to cast to a dma_fence_array + * + * Returns NULL if the fence is not a dma_fence_array, + * or the dma_fence_array otherwise. + */ +static inline struct dma_fence_array * +to_dma_fence_array(struct dma_fence *fence) +{ + if (fence->ops != &dma_fence_array_ops) + return NULL; + + return container_of(fence, struct dma_fence_array, base); +} + +struct dma_fence_array *dma_fence_array_create(int num_fences, + struct dma_fence **fences, + u64 context, unsigned seqno, + bool signal_on_any); + +#endif /* __LINUX_DMA_FENCE_ARRAY_H */ diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h new file mode 100644 index 000000000000..ba60c043a5d3 --- /dev/null +++ b/include/linux/dma-fence.h @@ -0,0 +1,437 @@ +/* + * Fence mechanism for dma-buf to allow for asynchronous dma access + * + * Copyright (C) 2012 Canonical Ltd + * Copyright (C) 2012 Texas Instruments + * + * Authors: + * Rob Clark + * Maarten Lankhorst + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __LINUX_DMA_FENCE_H +#define __LINUX_DMA_FENCE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +struct dma_fence; +struct dma_fence_ops; +struct dma_fence_cb; + +/** + * struct dma_fence - software synchronization primitive + * @refcount: refcount for this fence + * @ops: dma_fence_ops associated with this fence + * @rcu: used for releasing fence with kfree_rcu + * @cb_list: list of all callbacks to call + * @lock: spin_lock_irqsave used for locking + * @context: execution context this fence belongs to, returned by + * dma_fence_context_alloc() + * @seqno: the sequence number of this fence inside the execution context, + * can be compared to decide which fence would be signaled later. + * @flags: A mask of DMA_FENCE_FLAG_* defined below + * @timestamp: Timestamp when the fence was signaled. + * @status: Optional, only valid if < 0, must be set before calling + * dma_fence_signal, indicates that the fence has completed with an error. + * + * the flags member must be manipulated and read using the appropriate + * atomic ops (bit_*), so taking the spinlock will not be needed most + * of the time. + * + * DMA_FENCE_FLAG_SIGNALED_BIT - fence is already signaled + * DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT - enable_signaling might have been called + * DMA_FENCE_FLAG_USER_BITS - start of the unused bits, can be used by the + * implementer of the fence for its own purposes. Can be used in different + * ways by different fence implementers, so do not rely on this. + * + * Since atomic bitops are used, this is not guaranteed to be the case. + * Particularly, if the bit was set, but dma_fence_signal was called right + * before this bit was set, it would have been able to set the + * DMA_FENCE_FLAG_SIGNALED_BIT, before enable_signaling was called. + * Adding a check for DMA_FENCE_FLAG_SIGNALED_BIT after setting + * DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT closes this race, and makes sure that + * after dma_fence_signal was called, any enable_signaling call will have either + * been completed, or never called at all. + */ +struct dma_fence { + struct kref refcount; + const struct dma_fence_ops *ops; + struct rcu_head rcu; + struct list_head cb_list; + spinlock_t *lock; + u64 context; + unsigned seqno; + unsigned long flags; + ktime_t timestamp; + int status; +}; + +enum dma_fence_flag_bits { + DMA_FENCE_FLAG_SIGNALED_BIT, + DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, + DMA_FENCE_FLAG_USER_BITS, /* must always be last member */ +}; + +typedef void (*dma_fence_func_t)(struct dma_fence *fence, + struct dma_fence_cb *cb); + +/** + * struct dma_fence_cb - callback for dma_fence_add_callback + * @node: used by dma_fence_add_callback to append this struct to fence::cb_list + * @func: dma_fence_func_t to call + * + * This struct will be initialized by dma_fence_add_callback, additional + * data can be passed along by embedding dma_fence_cb in another struct. + */ +struct dma_fence_cb { + struct list_head node; + dma_fence_func_t func; +}; + +/** + * struct dma_fence_ops - operations implemented for fence + * @get_driver_name: returns the driver name. + * @get_timeline_name: return the name of the context this fence belongs to. + * @enable_signaling: enable software signaling of fence. + * @signaled: [optional] peek whether the fence is signaled, can be null. + * @wait: custom wait implementation, or dma_fence_default_wait. + * @release: [optional] called on destruction of fence, can be null + * @fill_driver_data: [optional] callback to fill in free-form debug info + * Returns amount of bytes filled, or -errno. + * @fence_value_str: [optional] fills in the value of the fence as a string + * @timeline_value_str: [optional] fills in the current value of the timeline + * as a string + * + * Notes on enable_signaling: + * For fence implementations that have the capability for hw->hw + * signaling, they can implement this op to enable the necessary + * irqs, or insert commands into cmdstream, etc. This is called + * in the first wait() or add_callback() path to let the fence + * implementation know that there is another driver waiting on + * the signal (ie. hw->sw case). + * + * This function can be called called from atomic context, but not + * from irq context, so normal spinlocks can be used. + * + * A return value of false indicates the fence already passed, + * or some failure occurred that made it impossible to enable + * signaling. True indicates successful enabling. + * + * fence->status may be set in enable_signaling, but only when false is + * returned. + * + * Calling dma_fence_signal before enable_signaling is called allows + * for a tiny race window in which enable_signaling is called during, + * before, or after dma_fence_signal. To fight this, it is recommended + * that before enable_signaling returns true an extra reference is + * taken on the fence, to be released when the fence is signaled. + * This will mean dma_fence_signal will still be called twice, but + * the second time will be a noop since it was already signaled. + * + * Notes on signaled: + * May set fence->status if returning true. + * + * Notes on wait: + * Must not be NULL, set to dma_fence_default_wait for default implementation. + * the dma_fence_default_wait implementation should work for any fence, as long + * as enable_signaling works correctly. + * + * Must return -ERESTARTSYS if the wait is intr = true and the wait was + * interrupted, and remaining jiffies if fence has signaled, or 0 if wait + * timed out. Can also return other error values on custom implementations, + * which should be treated as if the fence is signaled. For example a hardware + * lockup could be reported like that. + * + * Notes on release: + * Can be NULL, this function allows additional commands to run on + * destruction of the fence. Can be called from irq context. + * If pointer is set to NULL, kfree will get called instead. + */ + +struct dma_fence_ops { + const char * (*get_driver_name)(struct dma_fence *fence); + const char * (*get_timeline_name)(struct dma_fence *fence); + bool (*enable_signaling)(struct dma_fence *fence); + bool (*signaled)(struct dma_fence *fence); + signed long (*wait)(struct dma_fence *fence, + bool intr, signed long timeout); + void (*release)(struct dma_fence *fence); + + int (*fill_driver_data)(struct dma_fence *fence, void *data, int size); + void (*fence_value_str)(struct dma_fence *fence, char *str, int size); + void (*timeline_value_str)(struct dma_fence *fence, + char *str, int size); +}; + +void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, + spinlock_t *lock, u64 context, unsigned seqno); + +void dma_fence_release(struct kref *kref); +void dma_fence_free(struct dma_fence *fence); + +/** + * dma_fence_put - decreases refcount of the fence + * @fence: [in] fence to reduce refcount of + */ +static inline void dma_fence_put(struct dma_fence *fence) +{ + if (fence) + kref_put(&fence->refcount, dma_fence_release); +} + +/** + * dma_fence_get - increases refcount of the fence + * @fence: [in] fence to increase refcount of + * + * Returns the same fence, with refcount increased by 1. + */ +static inline struct dma_fence *dma_fence_get(struct dma_fence *fence) +{ + if (fence) + kref_get(&fence->refcount); + return fence; +} + +/** + * dma_fence_get_rcu - get a fence from a reservation_object_list with + * rcu read lock + * @fence: [in] fence to increase refcount of + * + * Function returns NULL if no refcount could be obtained, or the fence. + */ +static inline struct dma_fence *dma_fence_get_rcu(struct dma_fence *fence) +{ + if (kref_get_unless_zero(&fence->refcount)) + return fence; + else + return NULL; +} + +/** + * dma_fence_get_rcu_safe - acquire a reference to an RCU tracked fence + * @fence: [in] pointer to fence to increase refcount of + * + * Function returns NULL if no refcount could be obtained, or the fence. + * This function handles acquiring a reference to a fence that may be + * reallocated within the RCU grace period (such as with SLAB_DESTROY_BY_RCU), + * so long as the caller is using RCU on the pointer to the fence. + * + * An alternative mechanism is to employ a seqlock to protect a bunch of + * fences, such as used by struct reservation_object. When using a seqlock, + * the seqlock must be taken before and checked after a reference to the + * fence is acquired (as shown here). + * + * The caller is required to hold the RCU read lock. + */ +static inline struct dma_fence * +dma_fence_get_rcu_safe(struct dma_fence * __rcu *fencep) +{ + do { + struct dma_fence *fence; + + fence = rcu_dereference(*fencep); + if (!fence || !dma_fence_get_rcu(fence)) + return NULL; + + /* The atomic_inc_not_zero() inside dma_fence_get_rcu() + * provides a full memory barrier upon success (such as now). + * This is paired with the write barrier from assigning + * to the __rcu protected fence pointer so that if that + * pointer still matches the current fence, we know we + * have successfully acquire a reference to it. If it no + * longer matches, we are holding a reference to some other + * reallocated pointer. This is possible if the allocator + * is using a freelist like SLAB_DESTROY_BY_RCU where the + * fence remains valid for the RCU grace period, but it + * may be reallocated. When using such allocators, we are + * responsible for ensuring the reference we get is to + * the right fence, as below. + */ + if (fence == rcu_access_pointer(*fencep)) + return rcu_pointer_handoff(fence); + + dma_fence_put(fence); + } while (1); +} + +int dma_fence_signal(struct dma_fence *fence); +int dma_fence_signal_locked(struct dma_fence *fence); +signed long dma_fence_default_wait(struct dma_fence *fence, + bool intr, signed long timeout); +int dma_fence_add_callback(struct dma_fence *fence, + struct dma_fence_cb *cb, + dma_fence_func_t func); +bool dma_fence_remove_callback(struct dma_fence *fence, + struct dma_fence_cb *cb); +void dma_fence_enable_sw_signaling(struct dma_fence *fence); + +/** + * dma_fence_is_signaled_locked - Return an indication if the fence + * is signaled yet. + * @fence: [in] the fence to check + * + * Returns true if the fence was already signaled, false if not. Since this + * function doesn't enable signaling, it is not guaranteed to ever return + * true if dma_fence_add_callback, dma_fence_wait or + * dma_fence_enable_sw_signaling haven't been called before. + * + * This function requires fence->lock to be held. + */ +static inline bool +dma_fence_is_signaled_locked(struct dma_fence *fence) +{ + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return true; + + if (fence->ops->signaled && fence->ops->signaled(fence)) { + dma_fence_signal_locked(fence); + return true; + } + + return false; +} + +/** + * dma_fence_is_signaled - Return an indication if the fence is signaled yet. + * @fence: [in] the fence to check + * + * Returns true if the fence was already signaled, false if not. Since this + * function doesn't enable signaling, it is not guaranteed to ever return + * true if dma_fence_add_callback, dma_fence_wait or + * dma_fence_enable_sw_signaling haven't been called before. + * + * It's recommended for seqno fences to call dma_fence_signal when the + * operation is complete, it makes it possible to prevent issues from + * wraparound between time of issue and time of use by checking the return + * value of this function before calling hardware-specific wait instructions. + */ +static inline bool +dma_fence_is_signaled(struct dma_fence *fence) +{ + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return true; + + if (fence->ops->signaled && fence->ops->signaled(fence)) { + dma_fence_signal(fence); + return true; + } + + return false; +} + +/** + * dma_fence_is_later - return if f1 is chronologically later than f2 + * @f1: [in] the first fence from the same context + * @f2: [in] the second fence from the same context + * + * Returns true if f1 is chronologically later than f2. Both fences must be + * from the same context, since a seqno is not re-used across contexts. + */ +static inline bool dma_fence_is_later(struct dma_fence *f1, + struct dma_fence *f2) +{ + if (WARN_ON(f1->context != f2->context)) + return false; + + return (int)(f1->seqno - f2->seqno) > 0; +} + +/** + * dma_fence_later - return the chronologically later fence + * @f1: [in] the first fence from the same context + * @f2: [in] the second fence from the same context + * + * Returns NULL if both fences are signaled, otherwise the fence that would be + * signaled last. Both fences must be from the same context, since a seqno is + * not re-used across contexts. + */ +static inline struct dma_fence *dma_fence_later(struct dma_fence *f1, + struct dma_fence *f2) +{ + if (WARN_ON(f1->context != f2->context)) + return NULL; + + /* + * Can't check just DMA_FENCE_FLAG_SIGNALED_BIT here, it may never + * have been set if enable_signaling wasn't called, and enabling that + * here is overkill. + */ + if (dma_fence_is_later(f1, f2)) + return dma_fence_is_signaled(f1) ? NULL : f1; + else + return dma_fence_is_signaled(f2) ? NULL : f2; +} + +signed long dma_fence_wait_timeout(struct dma_fence *, + bool intr, signed long timeout); +signed long dma_fence_wait_any_timeout(struct dma_fence **fences, + uint32_t count, + bool intr, signed long timeout); + +/** + * dma_fence_wait - sleep until the fence gets signaled + * @fence: [in] the fence to wait on + * @intr: [in] if true, do an interruptible wait + * + * This function will return -ERESTARTSYS if interrupted by a signal, + * or 0 if the fence was signaled. Other error values may be + * returned on custom implementations. + * + * Performs a synchronous wait on this fence. It is assumed the caller + * directly or indirectly holds a reference to the fence, otherwise the + * fence might be freed before return, resulting in undefined behavior. + */ +static inline signed long dma_fence_wait(struct dma_fence *fence, bool intr) +{ + signed long ret; + + /* Since dma_fence_wait_timeout cannot timeout with + * MAX_SCHEDULE_TIMEOUT, only valid return values are + * -ERESTARTSYS and MAX_SCHEDULE_TIMEOUT. + */ + ret = dma_fence_wait_timeout(fence, intr, MAX_SCHEDULE_TIMEOUT); + + return ret < 0 ? ret : 0; +} + +u64 dma_fence_context_alloc(unsigned num); + +#define DMA_FENCE_TRACE(f, fmt, args...) \ + do { \ + struct dma_fence *__ff = (f); \ + if (IS_ENABLED(CONFIG_DMA_FENCE_TRACE)) \ + pr_info("f %llu#%u: " fmt, \ + __ff->context, __ff->seqno, ##args); \ + } while (0) + +#define DMA_FENCE_WARN(f, fmt, args...) \ + do { \ + struct dma_fence *__ff = (f); \ + pr_warn("f %llu#%u: " fmt, __ff->context, __ff->seqno, \ + ##args); \ + } while (0) + +#define DMA_FENCE_ERR(f, fmt, args...) \ + do { \ + struct dma_fence *__ff = (f); \ + pr_err("f %llu#%u: " fmt, __ff->context, __ff->seqno, \ + ##args); \ + } while (0) + +#endif /* __LINUX_DMA_FENCE_H */ diff --git a/include/linux/fence-array.h b/include/linux/fence-array.h deleted file mode 100644 index 9ea2bde10ac1..000000000000 --- a/include/linux/fence-array.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * fence-array: aggregates fence to be waited together - * - * Copyright (C) 2016 Collabora Ltd - * Copyright (C) 2016 Advanced Micro Devices, Inc. - * Authors: - * Gustavo Padovan - * Christian König - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#ifndef __LINUX_FENCE_ARRAY_H -#define __LINUX_FENCE_ARRAY_H - -#include - -/** - * struct fence_array_cb - callback helper for fence array - * @cb: fence callback structure for signaling - * @array: reference to the parent fence array object - */ -struct fence_array_cb { - struct fence_cb cb; - struct fence_array *array; -}; - -/** - * struct fence_array - fence to represent an array of fences - * @base: fence base class - * @lock: spinlock for fence handling - * @num_fences: number of fences in the array - * @num_pending: fences in the array still pending - * @fences: array of the fences - */ -struct fence_array { - struct fence base; - - spinlock_t lock; - unsigned num_fences; - atomic_t num_pending; - struct fence **fences; -}; - -extern const struct fence_ops fence_array_ops; - -/** - * fence_is_array - check if a fence is from the array subsclass - * @fence: fence to test - * - * Return true if it is a fence_array and false otherwise. - */ -static inline bool fence_is_array(struct fence *fence) -{ - return fence->ops == &fence_array_ops; -} - -/** - * to_fence_array - cast a fence to a fence_array - * @fence: fence to cast to a fence_array - * - * Returns NULL if the fence is not a fence_array, - * or the fence_array otherwise. - */ -static inline struct fence_array *to_fence_array(struct fence *fence) -{ - if (fence->ops != &fence_array_ops) - return NULL; - - return container_of(fence, struct fence_array, base); -} - -struct fence_array *fence_array_create(int num_fences, struct fence **fences, - u64 context, unsigned seqno, - bool signal_on_any); - -#endif /* __LINUX_FENCE_ARRAY_H */ diff --git a/include/linux/fence.h b/include/linux/fence.h deleted file mode 100644 index c9c5ba98c302..000000000000 --- a/include/linux/fence.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Fence mechanism for dma-buf to allow for asynchronous dma access - * - * Copyright (C) 2012 Canonical Ltd - * Copyright (C) 2012 Texas Instruments - * - * Authors: - * Rob Clark - * Maarten Lankhorst - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#ifndef __LINUX_FENCE_H -#define __LINUX_FENCE_H - -#include -#include -#include -#include -#include -#include -#include -#include - -struct fence; -struct fence_ops; -struct fence_cb; - -/** - * struct fence - software synchronization primitive - * @refcount: refcount for this fence - * @ops: fence_ops associated with this fence - * @rcu: used for releasing fence with kfree_rcu - * @cb_list: list of all callbacks to call - * @lock: spin_lock_irqsave used for locking - * @context: execution context this fence belongs to, returned by - * fence_context_alloc() - * @seqno: the sequence number of this fence inside the execution context, - * can be compared to decide which fence would be signaled later. - * @flags: A mask of FENCE_FLAG_* defined below - * @timestamp: Timestamp when the fence was signaled. - * @status: Optional, only valid if < 0, must be set before calling - * fence_signal, indicates that the fence has completed with an error. - * - * the flags member must be manipulated and read using the appropriate - * atomic ops (bit_*), so taking the spinlock will not be needed most - * of the time. - * - * FENCE_FLAG_SIGNALED_BIT - fence is already signaled - * FENCE_FLAG_ENABLE_SIGNAL_BIT - enable_signaling might have been called* - * FENCE_FLAG_USER_BITS - start of the unused bits, can be used by the - * implementer of the fence for its own purposes. Can be used in different - * ways by different fence implementers, so do not rely on this. - * - * Since atomic bitops are used, this is not guaranteed to be the case. - * Particularly, if the bit was set, but fence_signal was called right - * before this bit was set, it would have been able to set the - * FENCE_FLAG_SIGNALED_BIT, before enable_signaling was called. - * Adding a check for FENCE_FLAG_SIGNALED_BIT after setting - * FENCE_FLAG_ENABLE_SIGNAL_BIT closes this race, and makes sure that - * after fence_signal was called, any enable_signaling call will have either - * been completed, or never called at all. - */ -struct fence { - struct kref refcount; - const struct fence_ops *ops; - struct rcu_head rcu; - struct list_head cb_list; - spinlock_t *lock; - u64 context; - unsigned seqno; - unsigned long flags; - ktime_t timestamp; - int status; -}; - -enum fence_flag_bits { - FENCE_FLAG_SIGNALED_BIT, - FENCE_FLAG_ENABLE_SIGNAL_BIT, - FENCE_FLAG_USER_BITS, /* must always be last member */ -}; - -typedef void (*fence_func_t)(struct fence *fence, struct fence_cb *cb); - -/** - * struct fence_cb - callback for fence_add_callback - * @node: used by fence_add_callback to append this struct to fence::cb_list - * @func: fence_func_t to call - * - * This struct will be initialized by fence_add_callback, additional - * data can be passed along by embedding fence_cb in another struct. - */ -struct fence_cb { - struct list_head node; - fence_func_t func; -}; - -/** - * struct fence_ops - operations implemented for fence - * @get_driver_name: returns the driver name. - * @get_timeline_name: return the name of the context this fence belongs to. - * @enable_signaling: enable software signaling of fence. - * @signaled: [optional] peek whether the fence is signaled, can be null. - * @wait: custom wait implementation, or fence_default_wait. - * @release: [optional] called on destruction of fence, can be null - * @fill_driver_data: [optional] callback to fill in free-form debug info - * Returns amount of bytes filled, or -errno. - * @fence_value_str: [optional] fills in the value of the fence as a string - * @timeline_value_str: [optional] fills in the current value of the timeline - * as a string - * - * Notes on enable_signaling: - * For fence implementations that have the capability for hw->hw - * signaling, they can implement this op to enable the necessary - * irqs, or insert commands into cmdstream, etc. This is called - * in the first wait() or add_callback() path to let the fence - * implementation know that there is another driver waiting on - * the signal (ie. hw->sw case). - * - * This function can be called called from atomic context, but not - * from irq context, so normal spinlocks can be used. - * - * A return value of false indicates the fence already passed, - * or some failure occurred that made it impossible to enable - * signaling. True indicates successful enabling. - * - * fence->status may be set in enable_signaling, but only when false is - * returned. - * - * Calling fence_signal before enable_signaling is called allows - * for a tiny race window in which enable_signaling is called during, - * before, or after fence_signal. To fight this, it is recommended - * that before enable_signaling returns true an extra reference is - * taken on the fence, to be released when the fence is signaled. - * This will mean fence_signal will still be called twice, but - * the second time will be a noop since it was already signaled. - * - * Notes on signaled: - * May set fence->status if returning true. - * - * Notes on wait: - * Must not be NULL, set to fence_default_wait for default implementation. - * the fence_default_wait implementation should work for any fence, as long - * as enable_signaling works correctly. - * - * Must return -ERESTARTSYS if the wait is intr = true and the wait was - * interrupted, and remaining jiffies if fence has signaled, or 0 if wait - * timed out. Can also return other error values on custom implementations, - * which should be treated as if the fence is signaled. For example a hardware - * lockup could be reported like that. - * - * Notes on release: - * Can be NULL, this function allows additional commands to run on - * destruction of the fence. Can be called from irq context. - * If pointer is set to NULL, kfree will get called instead. - */ - -struct fence_ops { - const char * (*get_driver_name)(struct fence *fence); - const char * (*get_timeline_name)(struct fence *fence); - bool (*enable_signaling)(struct fence *fence); - bool (*signaled)(struct fence *fence); - signed long (*wait)(struct fence *fence, bool intr, signed long timeout); - void (*release)(struct fence *fence); - - int (*fill_driver_data)(struct fence *fence, void *data, int size); - void (*fence_value_str)(struct fence *fence, char *str, int size); - void (*timeline_value_str)(struct fence *fence, char *str, int size); -}; - -void fence_init(struct fence *fence, const struct fence_ops *ops, - spinlock_t *lock, u64 context, unsigned seqno); - -void fence_release(struct kref *kref); -void fence_free(struct fence *fence); - -/** - * fence_put - decreases refcount of the fence - * @fence: [in] fence to reduce refcount of - */ -static inline void fence_put(struct fence *fence) -{ - if (fence) - kref_put(&fence->refcount, fence_release); -} - -/** - * fence_get - increases refcount of the fence - * @fence: [in] fence to increase refcount of - * - * Returns the same fence, with refcount increased by 1. - */ -static inline struct fence *fence_get(struct fence *fence) -{ - if (fence) - kref_get(&fence->refcount); - return fence; -} - -/** - * fence_get_rcu - get a fence from a reservation_object_list with rcu read lock - * @fence: [in] fence to increase refcount of - * - * Function returns NULL if no refcount could be obtained, or the fence. - */ -static inline struct fence *fence_get_rcu(struct fence *fence) -{ - if (kref_get_unless_zero(&fence->refcount)) - return fence; - else - return NULL; -} - -/** - * fence_get_rcu_safe - acquire a reference to an RCU tracked fence - * @fence: [in] pointer to fence to increase refcount of - * - * Function returns NULL if no refcount could be obtained, or the fence. - * This function handles acquiring a reference to a fence that may be - * reallocated within the RCU grace period (such as with SLAB_DESTROY_BY_RCU), - * so long as the caller is using RCU on the pointer to the fence. - * - * An alternative mechanism is to employ a seqlock to protect a bunch of - * fences, such as used by struct reservation_object. When using a seqlock, - * the seqlock must be taken before and checked after a reference to the - * fence is acquired (as shown here). - * - * The caller is required to hold the RCU read lock. - */ -static inline struct fence *fence_get_rcu_safe(struct fence * __rcu *fencep) -{ - do { - struct fence *fence; - - fence = rcu_dereference(*fencep); - if (!fence || !fence_get_rcu(fence)) - return NULL; - - /* The atomic_inc_not_zero() inside fence_get_rcu() - * provides a full memory barrier upon success (such as now). - * This is paired with the write barrier from assigning - * to the __rcu protected fence pointer so that if that - * pointer still matches the current fence, we know we - * have successfully acquire a reference to it. If it no - * longer matches, we are holding a reference to some other - * reallocated pointer. This is possible if the allocator - * is using a freelist like SLAB_DESTROY_BY_RCU where the - * fence remains valid for the RCU grace period, but it - * may be reallocated. When using such allocators, we are - * responsible for ensuring the reference we get is to - * the right fence, as below. - */ - if (fence == rcu_access_pointer(*fencep)) - return rcu_pointer_handoff(fence); - - fence_put(fence); - } while (1); -} - -int fence_signal(struct fence *fence); -int fence_signal_locked(struct fence *fence); -signed long fence_default_wait(struct fence *fence, bool intr, signed long timeout); -int fence_add_callback(struct fence *fence, struct fence_cb *cb, - fence_func_t func); -bool fence_remove_callback(struct fence *fence, struct fence_cb *cb); -void fence_enable_sw_signaling(struct fence *fence); - -/** - * fence_is_signaled_locked - Return an indication if the fence is signaled yet. - * @fence: [in] the fence to check - * - * Returns true if the fence was already signaled, false if not. Since this - * function doesn't enable signaling, it is not guaranteed to ever return - * true if fence_add_callback, fence_wait or fence_enable_sw_signaling - * haven't been called before. - * - * This function requires fence->lock to be held. - */ -static inline bool -fence_is_signaled_locked(struct fence *fence) -{ - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - return true; - - if (fence->ops->signaled && fence->ops->signaled(fence)) { - fence_signal_locked(fence); - return true; - } - - return false; -} - -/** - * fence_is_signaled - Return an indication if the fence is signaled yet. - * @fence: [in] the fence to check - * - * Returns true if the fence was already signaled, false if not. Since this - * function doesn't enable signaling, it is not guaranteed to ever return - * true if fence_add_callback, fence_wait or fence_enable_sw_signaling - * haven't been called before. - * - * It's recommended for seqno fences to call fence_signal when the - * operation is complete, it makes it possible to prevent issues from - * wraparound between time of issue and time of use by checking the return - * value of this function before calling hardware-specific wait instructions. - */ -static inline bool -fence_is_signaled(struct fence *fence) -{ - if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - return true; - - if (fence->ops->signaled && fence->ops->signaled(fence)) { - fence_signal(fence); - return true; - } - - return false; -} - -/** - * fence_is_later - return if f1 is chronologically later than f2 - * @f1: [in] the first fence from the same context - * @f2: [in] the second fence from the same context - * - * Returns true if f1 is chronologically later than f2. Both fences must be - * from the same context, since a seqno is not re-used across contexts. - */ -static inline bool fence_is_later(struct fence *f1, struct fence *f2) -{ - if (WARN_ON(f1->context != f2->context)) - return false; - - return (int)(f1->seqno - f2->seqno) > 0; -} - -/** - * fence_later - return the chronologically later fence - * @f1: [in] the first fence from the same context - * @f2: [in] the second fence from the same context - * - * Returns NULL if both fences are signaled, otherwise the fence that would be - * signaled last. Both fences must be from the same context, since a seqno is - * not re-used across contexts. - */ -static inline struct fence *fence_later(struct fence *f1, struct fence *f2) -{ - if (WARN_ON(f1->context != f2->context)) - return NULL; - - /* - * can't check just FENCE_FLAG_SIGNALED_BIT here, it may never have been - * set if enable_signaling wasn't called, and enabling that here is - * overkill. - */ - if (fence_is_later(f1, f2)) - return fence_is_signaled(f1) ? NULL : f1; - else - return fence_is_signaled(f2) ? NULL : f2; -} - -signed long fence_wait_timeout(struct fence *, bool intr, signed long timeout); -signed long fence_wait_any_timeout(struct fence **fences, uint32_t count, - bool intr, signed long timeout); - -/** - * fence_wait - sleep until the fence gets signaled - * @fence: [in] the fence to wait on - * @intr: [in] if true, do an interruptible wait - * - * This function will return -ERESTARTSYS if interrupted by a signal, - * or 0 if the fence was signaled. Other error values may be - * returned on custom implementations. - * - * Performs a synchronous wait on this fence. It is assumed the caller - * directly or indirectly holds a reference to the fence, otherwise the - * fence might be freed before return, resulting in undefined behavior. - */ -static inline signed long fence_wait(struct fence *fence, bool intr) -{ - signed long ret; - - /* Since fence_wait_timeout cannot timeout with - * MAX_SCHEDULE_TIMEOUT, only valid return values are - * -ERESTARTSYS and MAX_SCHEDULE_TIMEOUT. - */ - ret = fence_wait_timeout(fence, intr, MAX_SCHEDULE_TIMEOUT); - - return ret < 0 ? ret : 0; -} - -u64 fence_context_alloc(unsigned num); - -#define FENCE_TRACE(f, fmt, args...) \ - do { \ - struct fence *__ff = (f); \ - if (IS_ENABLED(CONFIG_FENCE_TRACE)) \ - pr_info("f %llu#%u: " fmt, \ - __ff->context, __ff->seqno, ##args); \ - } while (0) - -#define FENCE_WARN(f, fmt, args...) \ - do { \ - struct fence *__ff = (f); \ - pr_warn("f %llu#%u: " fmt, __ff->context, __ff->seqno, \ - ##args); \ - } while (0) - -#define FENCE_ERR(f, fmt, args...) \ - do { \ - struct fence *__ff = (f); \ - pr_err("f %llu#%u: " fmt, __ff->context, __ff->seqno, \ - ##args); \ - } while (0) - -#endif /* __LINUX_FENCE_H */ diff --git a/include/linux/reservation.h b/include/linux/reservation.h index b0f305e77b7f..2e313cca08f0 100644 --- a/include/linux/reservation.h +++ b/include/linux/reservation.h @@ -40,7 +40,7 @@ #define _LINUX_RESERVATION_H #include -#include +#include #include #include #include @@ -59,7 +59,7 @@ extern const char reservation_seqcount_string[]; struct reservation_object_list { struct rcu_head rcu; u32 shared_count, shared_max; - struct fence __rcu *shared[]; + struct dma_fence __rcu *shared[]; }; /** @@ -74,7 +74,7 @@ struct reservation_object { struct ww_mutex lock; seqcount_t seq; - struct fence __rcu *fence_excl; + struct dma_fence __rcu *fence_excl; struct reservation_object_list __rcu *fence; struct reservation_object_list *staged; }; @@ -107,7 +107,7 @@ reservation_object_fini(struct reservation_object *obj) { int i; struct reservation_object_list *fobj; - struct fence *excl; + struct dma_fence *excl; /* * This object should be dead and all references must have @@ -115,12 +115,12 @@ reservation_object_fini(struct reservation_object *obj) */ excl = rcu_dereference_protected(obj->fence_excl, 1); if (excl) - fence_put(excl); + dma_fence_put(excl); fobj = rcu_dereference_protected(obj->fence, 1); if (fobj) { for (i = 0; i < fobj->shared_count; ++i) - fence_put(rcu_dereference_protected(fobj->shared[i], 1)); + dma_fence_put(rcu_dereference_protected(fobj->shared[i], 1)); kfree(fobj); } @@ -155,7 +155,7 @@ reservation_object_get_list(struct reservation_object *obj) * RETURNS * The exclusive fence or NULL */ -static inline struct fence * +static inline struct dma_fence * reservation_object_get_excl(struct reservation_object *obj) { return rcu_dereference_protected(obj->fence_excl, @@ -173,10 +173,10 @@ reservation_object_get_excl(struct reservation_object *obj) * RETURNS * The exclusive fence or NULL if none */ -static inline struct fence * +static inline struct dma_fence * reservation_object_get_excl_rcu(struct reservation_object *obj) { - struct fence *fence; + struct dma_fence *fence; unsigned seq; retry: seq = read_seqcount_begin(&obj->seq); @@ -186,22 +186,22 @@ retry: rcu_read_unlock(); goto retry; } - fence = fence_get(fence); + fence = dma_fence_get(fence); rcu_read_unlock(); return fence; } int reservation_object_reserve_shared(struct reservation_object *obj); void reservation_object_add_shared_fence(struct reservation_object *obj, - struct fence *fence); + struct dma_fence *fence); void reservation_object_add_excl_fence(struct reservation_object *obj, - struct fence *fence); + struct dma_fence *fence); int reservation_object_get_fences_rcu(struct reservation_object *obj, - struct fence **pfence_excl, + struct dma_fence **pfence_excl, unsigned *pshared_count, - struct fence ***pshared); + struct dma_fence ***pshared); long reservation_object_wait_timeout_rcu(struct reservation_object *obj, bool wait_all, bool intr, diff --git a/include/linux/seqno-fence.h b/include/linux/seqno-fence.h index a1ba6a5ccdd6..c58c535d12a8 100644 --- a/include/linux/seqno-fence.h +++ b/include/linux/seqno-fence.h @@ -20,7 +20,7 @@ #ifndef __LINUX_SEQNO_FENCE_H #define __LINUX_SEQNO_FENCE_H -#include +#include #include enum seqno_fence_condition { @@ -29,15 +29,15 @@ enum seqno_fence_condition { }; struct seqno_fence { - struct fence base; + struct dma_fence base; - const struct fence_ops *ops; + const struct dma_fence_ops *ops; struct dma_buf *sync_buf; uint32_t seqno_ofs; enum seqno_fence_condition condition; }; -extern const struct fence_ops seqno_fence_ops; +extern const struct dma_fence_ops seqno_fence_ops; /** * to_seqno_fence - cast a fence to a seqno_fence @@ -47,7 +47,7 @@ extern const struct fence_ops seqno_fence_ops; * or the seqno_fence otherwise. */ static inline struct seqno_fence * -to_seqno_fence(struct fence *fence) +to_seqno_fence(struct dma_fence *fence) { if (fence->ops != &seqno_fence_ops) return NULL; @@ -83,9 +83,9 @@ to_seqno_fence(struct fence *fence) * dma-buf for sync_buf, since mapping or unmapping the sync_buf to the * device's vm can be expensive. * - * It is recommended for creators of seqno_fence to call fence_signal + * It is recommended for creators of seqno_fence to call dma_fence_signal() * before destruction. This will prevent possible issues from wraparound at - * time of issue vs time of check, since users can check fence_is_signaled + * time of issue vs time of check, since users can check dma_fence_is_signaled() * before submitting instructions for the hardware to wait on the fence. * However, when ops.enable_signaling is not called, it doesn't have to be * done as soon as possible, just before there's any real danger of seqno @@ -96,18 +96,18 @@ seqno_fence_init(struct seqno_fence *fence, spinlock_t *lock, struct dma_buf *sync_buf, uint32_t context, uint32_t seqno_ofs, uint32_t seqno, enum seqno_fence_condition cond, - const struct fence_ops *ops) + const struct dma_fence_ops *ops) { BUG_ON(!fence || !sync_buf || !ops); BUG_ON(!ops->wait || !ops->enable_signaling || !ops->get_driver_name || !ops->get_timeline_name); /* - * ops is used in fence_init for get_driver_name, so needs to be + * ops is used in dma_fence_init for get_driver_name, so needs to be * initialized first */ fence->ops = ops; - fence_init(&fence->base, &seqno_fence_ops, lock, context, seqno); + dma_fence_init(&fence->base, &seqno_fence_ops, lock, context, seqno); get_dma_buf(sync_buf); fence->sync_buf = sync_buf; fence->seqno_ofs = seqno_ofs; diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h index aa17ccfc2f57..3e3ab84fc4cd 100644 --- a/include/linux/sync_file.h +++ b/include/linux/sync_file.h @@ -18,8 +18,8 @@ #include #include #include -#include -#include +#include +#include /** * struct sync_file - sync file to export to the userspace @@ -41,13 +41,13 @@ struct sync_file { wait_queue_head_t wq; - struct fence *fence; - struct fence_cb cb; + struct dma_fence *fence; + struct dma_fence_cb cb; }; -#define POLL_ENABLED FENCE_FLAG_USER_BITS +#define POLL_ENABLED DMA_FENCE_FLAG_USER_BITS -struct sync_file *sync_file_create(struct fence *fence); -struct fence *sync_file_get_fence(int fd); +struct sync_file *sync_file_create(struct dma_fence *fence); +struct dma_fence *sync_file_get_fence(int fd); #endif /* _LINUX_SYNC_H */ diff --git a/include/trace/events/dma_fence.h b/include/trace/events/dma_fence.h new file mode 100644 index 000000000000..1157cb4c3c6f --- /dev/null +++ b/include/trace/events/dma_fence.h @@ -0,0 +1,128 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM dma_fence + +#if !defined(_TRACE_FENCE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_DMA_FENCE_H + +#include + +struct dma_fence; + +TRACE_EVENT(dma_fence_annotate_wait_on, + + /* fence: the fence waiting on f1, f1: the fence to be waited on. */ + TP_PROTO(struct dma_fence *fence, struct dma_fence *f1), + + TP_ARGS(fence, f1), + + TP_STRUCT__entry( + __string(driver, fence->ops->get_driver_name(fence)) + __string(timeline, fence->ops->get_timeline_name(fence)) + __field(unsigned int, context) + __field(unsigned int, seqno) + + __string(waiting_driver, f1->ops->get_driver_name(f1)) + __string(waiting_timeline, f1->ops->get_timeline_name(f1)) + __field(unsigned int, waiting_context) + __field(unsigned int, waiting_seqno) + ), + + TP_fast_assign( + __assign_str(driver, fence->ops->get_driver_name(fence)) + __assign_str(timeline, fence->ops->get_timeline_name(fence)) + __entry->context = fence->context; + __entry->seqno = fence->seqno; + + __assign_str(waiting_driver, f1->ops->get_driver_name(f1)) + __assign_str(waiting_timeline, f1->ops->get_timeline_name(f1)) + __entry->waiting_context = f1->context; + __entry->waiting_seqno = f1->seqno; + + ), + + TP_printk("driver=%s timeline=%s context=%u seqno=%u " \ + "waits on driver=%s timeline=%s context=%u seqno=%u", + __get_str(driver), __get_str(timeline), __entry->context, + __entry->seqno, + __get_str(waiting_driver), __get_str(waiting_timeline), + __entry->waiting_context, __entry->waiting_seqno) +); + +DECLARE_EVENT_CLASS(dma_fence, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence), + + TP_STRUCT__entry( + __string(driver, fence->ops->get_driver_name(fence)) + __string(timeline, fence->ops->get_timeline_name(fence)) + __field(unsigned int, context) + __field(unsigned int, seqno) + ), + + TP_fast_assign( + __assign_str(driver, fence->ops->get_driver_name(fence)) + __assign_str(timeline, fence->ops->get_timeline_name(fence)) + __entry->context = fence->context; + __entry->seqno = fence->seqno; + ), + + TP_printk("driver=%s timeline=%s context=%u seqno=%u", + __get_str(driver), __get_str(timeline), __entry->context, + __entry->seqno) +); + +DEFINE_EVENT(dma_fence, dma_fence_emit, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence) +); + +DEFINE_EVENT(dma_fence, dma_fence_init, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence) +); + +DEFINE_EVENT(dma_fence, dma_fence_destroy, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence) +); + +DEFINE_EVENT(dma_fence, dma_fence_enable_signal, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence) +); + +DEFINE_EVENT(dma_fence, dma_fence_signaled, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence) +); + +DEFINE_EVENT(dma_fence, dma_fence_wait_start, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence) +); + +DEFINE_EVENT(dma_fence, dma_fence_wait_end, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence) +); + +#endif /* _TRACE_DMA_FENCE_H */ + +/* This part must be outside protection */ +#include diff --git a/include/trace/events/fence.h b/include/trace/events/fence.h deleted file mode 100644 index d6dfa05ba322..000000000000 --- a/include/trace/events/fence.h +++ /dev/null @@ -1,128 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM fence - -#if !defined(_TRACE_FENCE_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_FENCE_H - -#include - -struct fence; - -TRACE_EVENT(fence_annotate_wait_on, - - /* fence: the fence waiting on f1, f1: the fence to be waited on. */ - TP_PROTO(struct fence *fence, struct fence *f1), - - TP_ARGS(fence, f1), - - TP_STRUCT__entry( - __string(driver, fence->ops->get_driver_name(fence)) - __string(timeline, fence->ops->get_timeline_name(fence)) - __field(unsigned int, context) - __field(unsigned int, seqno) - - __string(waiting_driver, f1->ops->get_driver_name(f1)) - __string(waiting_timeline, f1->ops->get_timeline_name(f1)) - __field(unsigned int, waiting_context) - __field(unsigned int, waiting_seqno) - ), - - TP_fast_assign( - __assign_str(driver, fence->ops->get_driver_name(fence)) - __assign_str(timeline, fence->ops->get_timeline_name(fence)) - __entry->context = fence->context; - __entry->seqno = fence->seqno; - - __assign_str(waiting_driver, f1->ops->get_driver_name(f1)) - __assign_str(waiting_timeline, f1->ops->get_timeline_name(f1)) - __entry->waiting_context = f1->context; - __entry->waiting_seqno = f1->seqno; - - ), - - TP_printk("driver=%s timeline=%s context=%u seqno=%u " \ - "waits on driver=%s timeline=%s context=%u seqno=%u", - __get_str(driver), __get_str(timeline), __entry->context, - __entry->seqno, - __get_str(waiting_driver), __get_str(waiting_timeline), - __entry->waiting_context, __entry->waiting_seqno) -); - -DECLARE_EVENT_CLASS(fence, - - TP_PROTO(struct fence *fence), - - TP_ARGS(fence), - - TP_STRUCT__entry( - __string(driver, fence->ops->get_driver_name(fence)) - __string(timeline, fence->ops->get_timeline_name(fence)) - __field(unsigned int, context) - __field(unsigned int, seqno) - ), - - TP_fast_assign( - __assign_str(driver, fence->ops->get_driver_name(fence)) - __assign_str(timeline, fence->ops->get_timeline_name(fence)) - __entry->context = fence->context; - __entry->seqno = fence->seqno; - ), - - TP_printk("driver=%s timeline=%s context=%u seqno=%u", - __get_str(driver), __get_str(timeline), __entry->context, - __entry->seqno) -); - -DEFINE_EVENT(fence, fence_emit, - - TP_PROTO(struct fence *fence), - - TP_ARGS(fence) -); - -DEFINE_EVENT(fence, fence_init, - - TP_PROTO(struct fence *fence), - - TP_ARGS(fence) -); - -DEFINE_EVENT(fence, fence_destroy, - - TP_PROTO(struct fence *fence), - - TP_ARGS(fence) -); - -DEFINE_EVENT(fence, fence_enable_signal, - - TP_PROTO(struct fence *fence), - - TP_ARGS(fence) -); - -DEFINE_EVENT(fence, fence_signaled, - - TP_PROTO(struct fence *fence), - - TP_ARGS(fence) -); - -DEFINE_EVENT(fence, fence_wait_start, - - TP_PROTO(struct fence *fence), - - TP_ARGS(fence) -); - -DEFINE_EVENT(fence, fence_wait_end, - - TP_PROTO(struct fence *fence), - - TP_ARGS(fence) -); - -#endif /* _TRACE_FENCE_H */ - -/* This part must be outside protection */ -#include -- cgit v1.2.3 From 97ac0e47aed5f635893b0e2df634c64b38ca7541 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Oct 2016 11:28:27 +0100 Subject: drm: convert DT component matching to component_match_add_release() Convert DT component matching to use component_match_add_release(). Acked-by: Jyri Sarha Reviewed-by: Jyri Sarha Signed-off-by: Russell King Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/E1bwo6l-0005Io-Q1@rmk-PC.armlinux.org.uk --- drivers/gpu/drm/arm/hdlcd_drv.c | 3 ++- drivers/gpu/drm/arm/malidp_drv.c | 4 +++- drivers/gpu/drm/armada/armada_drv.c | 2 +- drivers/gpu/drm/drm_of.c | 28 +++++++++++++++++++++++-- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 5 +++-- drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 7 ++++--- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 +++- drivers/gpu/drm/msm/msm_drv.c | 12 ++++++----- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 6 ++++-- drivers/gpu/drm/sti/sti_drv.c | 5 +++-- drivers/gpu/drm/sun4i/sun4i_drv.c | 3 ++- drivers/gpu/drm/tilcdc/tilcdc_external.c | 4 +++- include/drm/drm_of.h | 12 +++++++++++ 13 files changed, 73 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index fb6a418ce6be..6477d1a65266 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -453,7 +453,8 @@ static int hdlcd_probe(struct platform_device *pdev) return -EAGAIN; } - component_match_add(&pdev->dev, &match, compare_dev, port); + drm_of_component_match_add(&pdev->dev, &match, compare_dev, port); + of_node_put(port); return component_master_add_with_match(&pdev->dev, &hdlcd_master_ops, match); diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 9280358b8f15..9f4739452a25 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -493,7 +493,9 @@ static int malidp_platform_probe(struct platform_device *pdev) return -EAGAIN; } - component_match_add(&pdev->dev, &match, malidp_compare_dev, port); + drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev, + port); + of_node_put(port); return component_master_add_with_match(&pdev->dev, &malidp_master_ops, match); } diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 1e0e68f608e4..94e46da9a758 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -254,7 +254,7 @@ static void armada_add_endpoints(struct device *dev, continue; } - component_match_add(dev, match, compare_of, remote); + drm_of_component_match_add(dev, match, compare_of, remote); of_node_put(remote); } } diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index bc98bb94264d..47848ed8ca48 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -6,6 +6,11 @@ #include #include +static void drm_release_of(struct device *dev, void *data) +{ + of_node_put(data); +} + /** * drm_crtc_port_mask - find the mask of a registered CRTC by port OF node * @dev: DRM device @@ -63,6 +68,24 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, } EXPORT_SYMBOL(drm_of_find_possible_crtcs); +/** + * drm_of_component_match_add - Add a component helper OF node match rule + * @master: master device + * @matchptr: component match pointer + * @compare: compare function used for matching component + * @node: of_node + */ +void drm_of_component_match_add(struct device *master, + struct component_match **matchptr, + int (*compare)(struct device *, void *), + struct device_node *node) +{ + of_node_get(node); + component_match_add_release(master, matchptr, drm_release_of, + compare, node); +} +EXPORT_SYMBOL_GPL(drm_of_component_match_add); + /** * drm_of_component_probe - Generic probe function for a component based master * @dev: master device containing the OF node @@ -101,7 +124,7 @@ int drm_of_component_probe(struct device *dev, continue; } - component_match_add(dev, &match, compare_of, port); + drm_of_component_match_add(dev, &match, compare_of, port); of_node_put(port); } @@ -140,7 +163,8 @@ int drm_of_component_probe(struct device *dev, continue; } - component_match_add(dev, &match, compare_of, remote); + drm_of_component_match_add(dev, &match, compare_of, + remote); of_node_put(remote); } of_node_put(port); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index aa687669e22b..0dee6acbd880 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -16,6 +16,7 @@ #include #include +#include #include "etnaviv_drv.h" #include "etnaviv_gpu.h" @@ -629,8 +630,8 @@ static int etnaviv_pdev_probe(struct platform_device *pdev) if (!core_node) break; - component_match_add(&pdev->dev, &match, compare_of, - core_node); + drm_of_component_match_add(&pdev->dev, &match, + compare_of, core_node); of_node_put(core_node); } } else if (dev->platform_data) { diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 90377a609c98..e88fde18c946 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "kirin_drm_drv.h" @@ -260,14 +261,13 @@ static struct device_node *kirin_get_remote_node(struct device_node *np) DRM_ERROR("no valid endpoint node\n"); return ERR_PTR(-ENODEV); } - of_node_put(endpoint); remote = of_graph_get_remote_port_parent(endpoint); + of_node_put(endpoint); if (!remote) { DRM_ERROR("no valid remote node\n"); return ERR_PTR(-ENODEV); } - of_node_put(remote); if (!of_device_is_available(remote)) { DRM_ERROR("not available for remote node\n"); @@ -294,7 +294,8 @@ static int kirin_drm_platform_probe(struct platform_device *pdev) if (IS_ERR(remote)) return PTR_ERR(remote); - component_match_add(dev, &match, compare_of, remote); + drm_of_component_match_add(dev, &match, compare_of, remote); + of_node_put(remote); return component_master_add_with_match(dev, &kirin_drm_ops, match); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index db61aa5f32ef..296f541fbe2f 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -416,7 +417,8 @@ static int mtk_drm_probe(struct platform_device *pdev) comp_type == MTK_DPI) { dev_info(dev, "Adding component match for %s\n", node->full_name); - component_match_add(dev, &match, compare_of, node); + drm_of_component_match_add(dev, &match, compare_of, + node); } else { struct mtk_ddp_comp *comp; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index fb5c0b0a7594..84d38eaea585 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -15,6 +15,8 @@ * this program. If not, see . */ +#include + #include "msm_drv.h" #include "msm_debugfs.h" #include "msm_fence.h" @@ -919,8 +921,8 @@ static int add_components_mdp(struct device *mdp_dev, continue; } - component_match_add(master_dev, matchptr, compare_of, intf); - + drm_of_component_match_add(master_dev, matchptr, compare_of, + intf); of_node_put(intf); of_node_put(ep_node); } @@ -962,8 +964,8 @@ static int add_display_components(struct device *dev, put_device(mdp_dev); /* add the MDP component itself */ - component_match_add(dev, matchptr, compare_of, - mdp_dev->of_node); + drm_of_component_match_add(dev, matchptr, compare_of, + mdp_dev->of_node); } else { /* MDP4 */ mdp_dev = dev; @@ -996,7 +998,7 @@ static int add_gpu_components(struct device *dev, if (!np) return 0; - component_match_add(dev, matchptr, compare_of, np); + drm_of_component_match_add(dev, matchptr, compare_of, np); of_node_put(np); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 8c8cbe837e61..6fe161192bb4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -388,7 +389,7 @@ static void rockchip_add_endpoints(struct device *dev, continue; } - component_match_add(dev, match, compare_of, remote); + drm_of_component_match_add(dev, match, compare_of, remote); of_node_put(remote); } } @@ -437,7 +438,8 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) } of_node_put(iommu); - component_match_add(dev, &match, compare_of, port->parent); + drm_of_component_match_add(dev, &match, compare_of, + port->parent); of_node_put(port); } diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 7087499969bc..6aead2013b62 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "sti_crtc.h" #include "sti_drv.h" @@ -424,8 +425,8 @@ static int sti_platform_probe(struct platform_device *pdev) child_np = of_get_next_available_child(node, NULL); while (child_np) { - component_match_add(dev, &match, compare_of, child_np); - of_node_put(child_np); + drm_of_component_match_add(dev, &match, compare_of, + child_np); child_np = of_get_next_available_child(node, child_np); } diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 0da9862ad8ed..b3c4ad605e81 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "sun4i_crtc.h" #include "sun4i_drv.h" @@ -239,7 +240,7 @@ static int sun4i_drv_add_endpoints(struct device *dev, /* Add current component */ DRM_DEBUG_DRIVER("Adding component %s\n", of_node_full_name(node)); - component_match_add(dev, match, compare_of, node); + drm_of_component_match_add(dev, match, compare_of, node); count++; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c index 68e895021005..06a4c584f3cb 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c @@ -10,6 +10,7 @@ #include #include +#include #include "tilcdc_drv.h" #include "tilcdc_external.h" @@ -160,7 +161,8 @@ int tilcdc_get_external_components(struct device *dev, dev_dbg(dev, "Subdevice node '%s' found\n", node->name); if (match) - component_match_add(dev, match, dev_match_of, node); + drm_of_component_match_add(dev, match, dev_match_of, + node); of_node_put(node); count++; } diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index 3fd87b386ed7..d6b4c5587bbe 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -4,6 +4,7 @@ #include struct component_master_ops; +struct component_match; struct device; struct drm_device; struct drm_encoder; @@ -12,6 +13,10 @@ struct device_node; #ifdef CONFIG_OF extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, struct device_node *port); +extern void drm_of_component_match_add(struct device *master, + struct component_match **matchptr, + int (*compare)(struct device *, void *), + struct device_node *node); extern int drm_of_component_probe(struct device *dev, int (*compare_of)(struct device *, void *), const struct component_master_ops *m_ops); @@ -25,6 +30,13 @@ static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, return 0; } +static void drm_of_component_match_add(struct device *master, + struct component_match **matchptr, + int (*compare)(struct device *, void *), + struct device_node *node) +{ +} + static inline int drm_of_component_probe(struct device *dev, int (*compare_of)(struct device *, void *), -- cgit v1.2.3 From 3904b28efb2c780c23dcddfb87e07fe0230661e5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Oct 2016 16:15:54 +0200 Subject: iio: gyro: Add driver for the MPU-3050 gyroscope This adds a new driver for the Invensense MPU-3050 gyroscope. This driver is based on information from the rough input driver in drivers/input/misc/mpu3050.c and the scratch misc driver posted by Nathan Royer in 2011. Some years have passed but this is finally a fully-fledged driver for this gyroscope. It was developed and tested on the Qualcomm APQ8060 Dragonboard. The driver supports both raw and buffered input. It also supports the internal trigger mechanism by registering a trigger that can fire in response to the internal sample engine of the component. In addition to reading out the gyroscope sensor values, the driver also supports reading the temperature from the sensor. The driver currently only supports I2C but the MPU-3050 can also be used from SPI, so the I2C portions are split in their own file and we just use regmap to access all registers, so it will be trivial to plug in SPI support if/when someone has a system requiring this. To conserve power, the driver utilizes the runtime PM framework and will put the sensor in off mode and disable the regulators when unused, after a timeout of 10 seconds. The fullscale can be set for the sensor to 250, 500, 1000 or 2000 deg/s. This corresponds to scale values of rougly 0.000122, 0.000275, 0.000512 or 0.001068. By writing such values (or close to these) into "in_anglevel_scale", the corresponding fullscale can be chosen. It will default to 2000 deg/s (~35 rad/s). The gyro component can have DC offsets on all axes. These can be compensated using the standard sysfs ABI property "in_anglevel_[xyz]_calibbias". This is in positive/negative values of the raw values, so a suitable calibration bias can be determined by userspace by reading the "in_anglevel_[xyz]_raw" for a few iterations while holding the sensor still, create an average integer, and writing the negative inverse of that into "in_anglevel_[xyz]_calibbias". After this the hardware will automatically subtract the bias, also when using buffered readings. Since the MPU-3050 has an outgoing I2C port it needs to act as an I2C mux. This means that the device is switching I2C traffic to devices beyond it. On my system this is the only way to reach the accelerometer. The "sensor fusion" ability of the MPU-3050 to directly talk to the device on the outgoing I2C port is currently not used by the driver, but it has code to allow I2C traffic to pass through so that the Linux kernel can reach the device on the other side with a kernel driver. Example usage with the native trigger: $ generic_buffer -a -c10 -n mpu3050 iio device number being used is 0 iio trigger number being used is 0 No channels are enabled, enabling all channels Enabling: in_anglvel_z_en Enabling: in_timestamp_en Enabling: in_anglvel_y_en Enabling: in_temp_en Enabling: in_anglvel_x_en /sys/bus/iio/devices/iio:device0 mpu3050-dev0 29607.142578 -0.117493 0.074768 0.012817 180788797150 29639.285156 -0.117493 0.076904 0.013885 180888982335 29696.427734 -0.116425 0.076904 0.012817 180989178039 29742.857422 -0.117493 0.076904 0.012817 181089377742 29764.285156 -0.116425 0.077972 0.012817 181189574187 29860.714844 -0.115356 0.076904 0.012817 181289772705 29864.285156 -0.117493 0.076904 0.012817 181389971520 29910.714844 -0.115356 0.076904 0.013885 181490170483 29917.857422 -0.116425 0.076904 0.011749 181590369742 29975.000000 -0.116425 0.076904 0.012817 181690567075 Disabling: in_anglvel_z_en Disabling: in_timestamp_en Disabling: in_anglvel_y_en Disabling: in_temp_en Disabling: in_anglvel_x_en The first column is the temperature in millidegrees, then the x,y,z axes in succession followed by the timestamp. Also tested successfully using the HRTimer trigger. Cc: Nick Vaccaro Cc: Ge Gao Cc: Anna Si Cc: Dmitry Torokhov Cc: Crestez Dan Leonard Cc: Daniel Baluta Cc: Gregor Boirie Cc: Peter Rosin Cc: Peter Meerwald-Stadler Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- MAINTAINERS | 7 + drivers/iio/gyro/Kconfig | 17 + drivers/iio/gyro/Makefile | 5 + drivers/iio/gyro/mpu3050-core.c | 1307 +++++++++++++++++++++++++++++++++++++++ drivers/iio/gyro/mpu3050-i2c.c | 124 ++++ drivers/iio/gyro/mpu3050.h | 96 +++ 6 files changed, 1556 insertions(+) create mode 100644 drivers/iio/gyro/mpu3050-core.c create mode 100644 drivers/iio/gyro/mpu3050-i2c.c create mode 100644 drivers/iio/gyro/mpu3050.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 7084d8e8592f..5e218aaa4c7a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6496,6 +6496,13 @@ S: Maintained F: arch/x86/include/asm/pmc_core.h F: drivers/platform/x86/intel_pmc_core* +INVENSENSE MPU-3050 GYROSCOPE DRIVER +M: Linus Walleij +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/iio/gyro/mpu3050* +F: Documentation/devicetree/bindings/iio/gyroscope/inv,mpu3050.txt + IOC3 ETHERNET DRIVER M: Ralf Baechle L: linux-mips@linux-mips.org diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 205a84420ae9..107b5efd4178 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -84,6 +84,23 @@ config HID_SENSOR_GYRO_3D Say yes here to build support for the HID SENSOR Gyroscope 3D. +config MPU3050 + tristate + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select REGMAP + +config MPU3050_I2C + tristate "Invensense MPU3050 devices on I2C" + depends on !(INPUT_MPU3050=y || INPUT_MPU3050=m) + select MPU3050 + select REGMAP_I2C + select I2C_MUX + help + This driver supports the Invensense MPU3050 gyroscope over I2C. + This driver can be built as a module. The module will be called + inv-mpu3050-i2c. + config IIO_ST_GYRO_3AXIS tristate "STMicroelectronics gyroscopes 3-Axis Driver" depends on (I2C || SPI_MASTER) && SYSFS diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index f866a4be0667..f0e149a606b0 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile @@ -14,6 +14,11 @@ obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o +# Currently this is rolled into one module, split it if +# we ever create a separate SPI interface for MPU-3050 +obj-$(CONFIG_MPU3050) += mpu3050.o +mpu3050-objs := mpu3050-core.o mpu3050-i2c.o + itg3200-y := itg3200_core.o itg3200-$(CONFIG_IIO_BUFFER) += itg3200_buffer.o obj-$(CONFIG_ITG3200) += itg3200.o diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c new file mode 100644 index 000000000000..ed681c70a7b4 --- /dev/null +++ b/drivers/iio/gyro/mpu3050-core.c @@ -0,0 +1,1307 @@ +/* + * MPU3050 gyroscope driver + * + * Copyright (C) 2016 Linaro Ltd. + * Author: Linus Walleij + * + * Based on the input subsystem driver, Copyright (C) 2011 Wistron Co.Ltd + * Joseph Lai and trimmed down by + * Alan Cox in turn based on bma023.c. + * Device behaviour based on a misc driver posted by Nathan Royer in 2011. + * + * TODO: add support for setting up the low pass 3dB frequency. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpu3050.h" + +#define MPU3050_CHIP_ID 0x69 + +/* + * Register map: anything suffixed *_H is a big-endian high byte and always + * followed by the corresponding low byte (*_L) even though these are not + * explicitly included in the register definitions. + */ +#define MPU3050_CHIP_ID_REG 0x00 +#define MPU3050_PRODUCT_ID_REG 0x01 +#define MPU3050_XG_OFFS_TC 0x05 +#define MPU3050_YG_OFFS_TC 0x08 +#define MPU3050_ZG_OFFS_TC 0x0B +#define MPU3050_X_OFFS_USR_H 0x0C +#define MPU3050_Y_OFFS_USR_H 0x0E +#define MPU3050_Z_OFFS_USR_H 0x10 +#define MPU3050_FIFO_EN 0x12 +#define MPU3050_AUX_VDDIO 0x13 +#define MPU3050_SLV_ADDR 0x14 +#define MPU3050_SMPLRT_DIV 0x15 +#define MPU3050_DLPF_FS_SYNC 0x16 +#define MPU3050_INT_CFG 0x17 +#define MPU3050_AUX_ADDR 0x18 +#define MPU3050_INT_STATUS 0x1A +#define MPU3050_TEMP_H 0x1B +#define MPU3050_XOUT_H 0x1D +#define MPU3050_YOUT_H 0x1F +#define MPU3050_ZOUT_H 0x21 +#define MPU3050_DMP_CFG1 0x35 +#define MPU3050_DMP_CFG2 0x36 +#define MPU3050_BANK_SEL 0x37 +#define MPU3050_MEM_START_ADDR 0x38 +#define MPU3050_MEM_R_W 0x39 +#define MPU3050_FIFO_COUNT_H 0x3A +#define MPU3050_FIFO_R 0x3C +#define MPU3050_USR_CTRL 0x3D +#define MPU3050_PWR_MGM 0x3E + +/* MPU memory bank read options */ +#define MPU3050_MEM_PRFTCH BIT(5) +#define MPU3050_MEM_USER_BANK BIT(4) +/* Bits 8-11 select memory bank */ +#define MPU3050_MEM_RAM_BANK_0 0 +#define MPU3050_MEM_RAM_BANK_1 1 +#define MPU3050_MEM_RAM_BANK_2 2 +#define MPU3050_MEM_RAM_BANK_3 3 +#define MPU3050_MEM_OTP_BANK_0 4 + +#define MPU3050_AXIS_REGS(axis) (MPU3050_XOUT_H + (axis * 2)) + +/* Register bits */ + +/* FIFO Enable */ +#define MPU3050_FIFO_EN_FOOTER BIT(0) +#define MPU3050_FIFO_EN_AUX_ZOUT BIT(1) +#define MPU3050_FIFO_EN_AUX_YOUT BIT(2) +#define MPU3050_FIFO_EN_AUX_XOUT BIT(3) +#define MPU3050_FIFO_EN_GYRO_ZOUT BIT(4) +#define MPU3050_FIFO_EN_GYRO_YOUT BIT(5) +#define MPU3050_FIFO_EN_GYRO_XOUT BIT(6) +#define MPU3050_FIFO_EN_TEMP_OUT BIT(7) + +/* + * Digital Low Pass filter (DLPF) + * Full Scale (FS) + * and Synchronization + */ +#define MPU3050_EXT_SYNC_NONE 0x00 +#define MPU3050_EXT_SYNC_TEMP 0x20 +#define MPU3050_EXT_SYNC_GYROX 0x40 +#define MPU3050_EXT_SYNC_GYROY 0x60 +#define MPU3050_EXT_SYNC_GYROZ 0x80 +#define MPU3050_EXT_SYNC_ACCELX 0xA0 +#define MPU3050_EXT_SYNC_ACCELY 0xC0 +#define MPU3050_EXT_SYNC_ACCELZ 0xE0 +#define MPU3050_EXT_SYNC_MASK 0xE0 +#define MPU3050_EXT_SYNC_SHIFT 5 + +#define MPU3050_FS_250DPS 0x00 +#define MPU3050_FS_500DPS 0x08 +#define MPU3050_FS_1000DPS 0x10 +#define MPU3050_FS_2000DPS 0x18 +#define MPU3050_FS_MASK 0x18 +#define MPU3050_FS_SHIFT 3 + +#define MPU3050_DLPF_CFG_256HZ_NOLPF2 0x00 +#define MPU3050_DLPF_CFG_188HZ 0x01 +#define MPU3050_DLPF_CFG_98HZ 0x02 +#define MPU3050_DLPF_CFG_42HZ 0x03 +#define MPU3050_DLPF_CFG_20HZ 0x04 +#define MPU3050_DLPF_CFG_10HZ 0x05 +#define MPU3050_DLPF_CFG_5HZ 0x06 +#define MPU3050_DLPF_CFG_2100HZ_NOLPF 0x07 +#define MPU3050_DLPF_CFG_MASK 0x07 +#define MPU3050_DLPF_CFG_SHIFT 0 + +/* Interrupt config */ +#define MPU3050_INT_RAW_RDY_EN BIT(0) +#define MPU3050_INT_DMP_DONE_EN BIT(1) +#define MPU3050_INT_MPU_RDY_EN BIT(2) +#define MPU3050_INT_ANYRD_2CLEAR BIT(4) +#define MPU3050_INT_LATCH_EN BIT(5) +#define MPU3050_INT_OPEN BIT(6) +#define MPU3050_INT_ACTL BIT(7) +/* Interrupt status */ +#define MPU3050_INT_STATUS_RAW_RDY BIT(0) +#define MPU3050_INT_STATUS_DMP_DONE BIT(1) +#define MPU3050_INT_STATUS_MPU_RDY BIT(2) +#define MPU3050_INT_STATUS_FIFO_OVFLW BIT(7) +/* USR_CTRL */ +#define MPU3050_USR_CTRL_FIFO_EN BIT(6) +#define MPU3050_USR_CTRL_AUX_IF_EN BIT(5) +#define MPU3050_USR_CTRL_AUX_IF_RST BIT(3) +#define MPU3050_USR_CTRL_FIFO_RST BIT(1) +#define MPU3050_USR_CTRL_GYRO_RST BIT(0) +/* PWR_MGM */ +#define MPU3050_PWR_MGM_PLL_X 0x01 +#define MPU3050_PWR_MGM_PLL_Y 0x02 +#define MPU3050_PWR_MGM_PLL_Z 0x03 +#define MPU3050_PWR_MGM_CLKSEL_MASK 0x07 +#define MPU3050_PWR_MGM_STBY_ZG BIT(3) +#define MPU3050_PWR_MGM_STBY_YG BIT(4) +#define MPU3050_PWR_MGM_STBY_XG BIT(5) +#define MPU3050_PWR_MGM_SLEEP BIT(6) +#define MPU3050_PWR_MGM_RESET BIT(7) +#define MPU3050_PWR_MGM_MASK 0xff + +/* + * Fullscale precision is (for finest precision) +/- 250 deg/s, so the full + * scale is actually 500 deg/s. All 16 bits are then used to cover this scale, + * in two's complement. + */ +static unsigned int mpu3050_fs_precision[] = { + IIO_DEGREE_TO_RAD(250), + IIO_DEGREE_TO_RAD(500), + IIO_DEGREE_TO_RAD(1000), + IIO_DEGREE_TO_RAD(2000) +}; + +/* + * Regulator names + */ +static const char mpu3050_reg_vdd[] = "vdd"; +static const char mpu3050_reg_vlogic[] = "vlogic"; + +static unsigned int mpu3050_get_freq(struct mpu3050 *mpu3050) +{ + unsigned int freq; + + if (mpu3050->lpf == MPU3050_DLPF_CFG_256HZ_NOLPF2) + freq = 8000; + else + freq = 1000; + freq /= (mpu3050->divisor + 1); + + return freq; +} + +static int mpu3050_start_sampling(struct mpu3050 *mpu3050) +{ + __be16 raw_val[3]; + int ret; + int i; + + /* Reset */ + ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM, + MPU3050_PWR_MGM_RESET, MPU3050_PWR_MGM_RESET); + if (ret) + return ret; + + /* Turn on the Z-axis PLL */ + ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM, + MPU3050_PWR_MGM_CLKSEL_MASK, + MPU3050_PWR_MGM_PLL_Z); + if (ret) + return ret; + + /* Write calibration offset registers */ + for (i = 0; i < 3; i++) + raw_val[i] = cpu_to_be16(mpu3050->calibration[i]); + + ret = regmap_bulk_write(mpu3050->map, MPU3050_X_OFFS_USR_H, raw_val, + sizeof(raw_val)); + if (ret) + return ret; + + /* Set low pass filter (sample rate), sync and full scale */ + ret = regmap_write(mpu3050->map, MPU3050_DLPF_FS_SYNC, + MPU3050_EXT_SYNC_NONE << MPU3050_EXT_SYNC_SHIFT | + mpu3050->fullscale << MPU3050_FS_SHIFT | + mpu3050->lpf << MPU3050_DLPF_CFG_SHIFT); + if (ret) + return ret; + + /* Set up sampling frequency */ + ret = regmap_write(mpu3050->map, MPU3050_SMPLRT_DIV, mpu3050->divisor); + if (ret) + return ret; + + /* + * Max 50 ms start-up time after setting DLPF_FS_SYNC + * according to the data sheet, then wait for the next sample + * at this frequency T = 1000/f ms. + */ + msleep(50 + 1000 / mpu3050_get_freq(mpu3050)); + + return 0; +} + +static int mpu3050_set_8khz_samplerate(struct mpu3050 *mpu3050) +{ + int ret; + u8 divisor; + enum mpu3050_lpf lpf; + + lpf = mpu3050->lpf; + divisor = mpu3050->divisor; + + mpu3050->lpf = LPF_256_HZ_NOLPF; /* 8 kHz base frequency */ + mpu3050->divisor = 0; /* Divide by 1 */ + ret = mpu3050_start_sampling(mpu3050); + + mpu3050->lpf = lpf; + mpu3050->divisor = divisor; + + return ret; +} + +static int mpu3050_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + int ret; + __be16 raw_val; + + switch (mask) { + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + /* The temperature scaling is (x+23000)/280 Celsius */ + *val = 23000; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_CALIBBIAS: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = mpu3050->calibration[chan->scan_index-1]; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + *val = mpu3050_get_freq(mpu3050); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + /* Millidegrees, see about temperature scaling above */ + *val = 1000; + *val2 = 280; + return IIO_VAL_FRACTIONAL; + case IIO_ANGL_VEL: + /* + * Convert to the corresponding full scale in + * radians. All 16 bits are used with sign to + * span the available scale: to account for the one + * missing value if we multiply by 1/S16_MAX, instead + * multiply with 2/U16_MAX. + */ + *val = mpu3050_fs_precision[mpu3050->fullscale] * 2; + *val2 = U16_MAX; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_RAW: + /* Resume device */ + pm_runtime_get_sync(mpu3050->dev); + mutex_lock(&mpu3050->lock); + + ret = mpu3050_set_8khz_samplerate(mpu3050); + if (ret) + goto out_read_raw_unlock; + + switch (chan->type) { + case IIO_TEMP: + ret = regmap_bulk_read(mpu3050->map, MPU3050_TEMP_H, + &raw_val, sizeof(raw_val)); + if (ret) { + dev_err(mpu3050->dev, + "error reading temperature\n"); + goto out_read_raw_unlock; + } + + *val = be16_to_cpu(raw_val); + ret = IIO_VAL_INT; + + goto out_read_raw_unlock; + case IIO_ANGL_VEL: + ret = regmap_bulk_read(mpu3050->map, + MPU3050_AXIS_REGS(chan->scan_index-1), + &raw_val, + sizeof(raw_val)); + if (ret) { + dev_err(mpu3050->dev, + "error reading axis data\n"); + goto out_read_raw_unlock; + } + + *val = be16_to_cpu(raw_val); + ret = IIO_VAL_INT; + + goto out_read_raw_unlock; + default: + ret = -EINVAL; + goto out_read_raw_unlock; + } + default: + break; + } + + return -EINVAL; + +out_read_raw_unlock: + mutex_unlock(&mpu3050->lock); + pm_runtime_mark_last_busy(mpu3050->dev); + pm_runtime_put_autosuspend(mpu3050->dev); + + return ret; +} + +static int mpu3050_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int val, int val2, long mask) +{ + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + /* + * Couldn't figure out a way to precalculate these at compile time. + */ + unsigned int fs250 = + DIV_ROUND_CLOSEST(mpu3050_fs_precision[0] * 1000000 * 2, + U16_MAX); + unsigned int fs500 = + DIV_ROUND_CLOSEST(mpu3050_fs_precision[1] * 1000000 * 2, + U16_MAX); + unsigned int fs1000 = + DIV_ROUND_CLOSEST(mpu3050_fs_precision[2] * 1000000 * 2, + U16_MAX); + unsigned int fs2000 = + DIV_ROUND_CLOSEST(mpu3050_fs_precision[3] * 1000000 * 2, + U16_MAX); + + switch (mask) { + case IIO_CHAN_INFO_CALIBBIAS: + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + mpu3050->calibration[chan->scan_index-1] = val; + return 0; + case IIO_CHAN_INFO_SAMP_FREQ: + /* + * The max samplerate is 8000 Hz, the minimum + * 1000 / 256 ~= 4 Hz + */ + if (val < 4 || val > 8000) + return -EINVAL; + + /* + * Above 1000 Hz we must turn off the digital low pass filter + * so we get a base frequency of 8kHz to the divider + */ + if (val > 1000) { + mpu3050->lpf = LPF_256_HZ_NOLPF; + mpu3050->divisor = DIV_ROUND_CLOSEST(8000, val) - 1; + return 0; + } + + mpu3050->lpf = LPF_188_HZ; + mpu3050->divisor = DIV_ROUND_CLOSEST(1000, val) - 1; + return 0; + case IIO_CHAN_INFO_SCALE: + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + /* + * We support +/-250, +/-500, +/-1000 and +/2000 deg/s + * which means we need to round to the closest radians + * which will be roughly +/-4.3, +/-8.7, +/-17.5, +/-35 + * rad/s. The scale is then for the 16 bits used to cover + * it 2/(2^16) of that. + */ + + /* Just too large, set the max range */ + if (val != 0) { + mpu3050->fullscale = FS_2000_DPS; + return 0; + } + + /* + * Now we're dealing with fractions below zero in millirad/s + * do some integer interpolation and match with the closest + * fullscale in the table. + */ + if (val2 <= fs250 || + val2 < ((fs500 + fs250) / 2)) + mpu3050->fullscale = FS_250_DPS; + else if (val2 <= fs500 || + val2 < ((fs1000 + fs500) / 2)) + mpu3050->fullscale = FS_500_DPS; + else if (val2 <= fs1000 || + val2 < ((fs2000 + fs1000) / 2)) + mpu3050->fullscale = FS_1000_DPS; + else + /* Catch-all */ + mpu3050->fullscale = FS_2000_DPS; + return 0; + default: + break; + } + + return -EINVAL; +} + +static irqreturn_t mpu3050_trigger_handler(int irq, void *p) +{ + const struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + int ret; + /* + * Temperature 1*16 bits + * Three axes 3*16 bits + * Timestamp 64 bits (4*16 bits) + * Sum total 8*16 bits + */ + __be16 hw_values[8]; + s64 timestamp; + unsigned int datums_from_fifo = 0; + + /* + * If we're using the hardware trigger, get the precise timestamp from + * the top half of the threaded IRQ handler. Otherwise get the + * timestamp here so it will be close in time to the actual values + * read from the registers. + */ + if (iio_trigger_using_own(indio_dev)) + timestamp = mpu3050->hw_timestamp; + else + timestamp = iio_get_time_ns(indio_dev); + + mutex_lock(&mpu3050->lock); + + /* Using the hardware IRQ trigger? Check the buffer then. */ + if (mpu3050->hw_irq_trigger) { + __be16 raw_fifocnt; + u16 fifocnt; + /* X, Y, Z + temperature */ + unsigned int bytes_per_datum = 8; + bool fifo_overflow = false; + + ret = regmap_bulk_read(mpu3050->map, + MPU3050_FIFO_COUNT_H, + &raw_fifocnt, + sizeof(raw_fifocnt)); + if (ret) + goto out_trigger_unlock; + fifocnt = be16_to_cpu(raw_fifocnt); + + if (fifocnt == 512) { + dev_info(mpu3050->dev, + "FIFO overflow! Emptying and resetting FIFO\n"); + fifo_overflow = true; + /* Reset and enable the FIFO */ + ret = regmap_update_bits(mpu3050->map, + MPU3050_USR_CTRL, + MPU3050_USR_CTRL_FIFO_EN | + MPU3050_USR_CTRL_FIFO_RST, + MPU3050_USR_CTRL_FIFO_EN | + MPU3050_USR_CTRL_FIFO_RST); + if (ret) { + dev_info(mpu3050->dev, "error resetting FIFO\n"); + goto out_trigger_unlock; + } + mpu3050->pending_fifo_footer = false; + } + + if (fifocnt) + dev_dbg(mpu3050->dev, + "%d bytes in the FIFO\n", + fifocnt); + + while (!fifo_overflow && fifocnt > bytes_per_datum) { + unsigned int toread; + unsigned int offset; + __be16 fifo_values[5]; + + /* + * If there is a FIFO footer in the pipe, first clear + * that out. This follows the complex algorithm in the + * datasheet that states that you may never leave the + * FIFO empty after the first reading: you have to + * always leave two footer bytes in it. The footer is + * in practice just two zero bytes. + */ + if (mpu3050->pending_fifo_footer) { + toread = bytes_per_datum + 2; + offset = 0; + } else { + toread = bytes_per_datum; + offset = 1; + /* Put in some dummy value */ + fifo_values[0] = 0xAAAA; + } + + ret = regmap_bulk_read(mpu3050->map, + MPU3050_FIFO_R, + &fifo_values[offset], + toread); + + dev_dbg(mpu3050->dev, + "%04x %04x %04x %04x %04x\n", + fifo_values[0], + fifo_values[1], + fifo_values[2], + fifo_values[3], + fifo_values[4]); + + /* Index past the footer (fifo_values[0]) and push */ + iio_push_to_buffers_with_timestamp(indio_dev, + &fifo_values[1], + timestamp); + + fifocnt -= toread; + datums_from_fifo++; + mpu3050->pending_fifo_footer = true; + + /* + * If we're emptying the FIFO, just make sure to + * check if something new appeared. + */ + if (fifocnt < bytes_per_datum) { + ret = regmap_bulk_read(mpu3050->map, + MPU3050_FIFO_COUNT_H, + &raw_fifocnt, + sizeof(raw_fifocnt)); + if (ret) + goto out_trigger_unlock; + fifocnt = be16_to_cpu(raw_fifocnt); + } + + if (fifocnt < bytes_per_datum) + dev_dbg(mpu3050->dev, + "%d bytes left in the FIFO\n", + fifocnt); + + /* + * At this point, the timestamp that triggered the + * hardware interrupt is no longer valid for what + * we are reading (the interrupt likely fired for + * the value on the top of the FIFO), so set the + * timestamp to zero and let userspace deal with it. + */ + timestamp = 0; + } + } + + /* + * If we picked some datums from the FIFO that's enough, else + * fall through and just read from the current value registers. + * This happens in two cases: + * + * - We are using some other trigger (external, like an HRTimer) + * than the sensor's own sample generator. In this case the + * sensor is just set to the max sampling frequency and we give + * the trigger a copy of the latest value every time we get here. + * + * - The hardware trigger is active but unused and we actually use + * another trigger which calls here with a frequency higher + * than what the device provides data. We will then just read + * duplicate values directly from the hardware registers. + */ + if (datums_from_fifo) { + dev_dbg(mpu3050->dev, + "read %d datums from the FIFO\n", + datums_from_fifo); + goto out_trigger_unlock; + } + + ret = regmap_bulk_read(mpu3050->map, MPU3050_TEMP_H, &hw_values, + sizeof(hw_values)); + if (ret) { + dev_err(mpu3050->dev, + "error reading axis data\n"); + goto out_trigger_unlock; + } + + iio_push_to_buffers_with_timestamp(indio_dev, hw_values, timestamp); + +out_trigger_unlock: + mutex_unlock(&mpu3050->lock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int mpu3050_buffer_preenable(struct iio_dev *indio_dev) +{ + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + + pm_runtime_get_sync(mpu3050->dev); + + /* Unless we have OUR trigger active, run at full speed */ + if (!mpu3050->hw_irq_trigger) + return mpu3050_set_8khz_samplerate(mpu3050); + + return 0; +} + +static int mpu3050_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + + pm_runtime_mark_last_busy(mpu3050->dev); + pm_runtime_put_autosuspend(mpu3050->dev); + + return 0; +} + +static const struct iio_buffer_setup_ops mpu3050_buffer_setup_ops = { + .preenable = mpu3050_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = mpu3050_buffer_postdisable, +}; + +static const struct iio_mount_matrix * +mpu3050_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + + return &mpu3050->orientation; +} + +static const struct iio_chan_spec_ext_info mpu3050_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, mpu3050_get_mount_matrix), + { }, +}; + +#define MPU3050_AXIS_CHANNEL(axis, index) \ + { \ + .type = IIO_ANGL_VEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ + .ext_info = mpu3050_ext_info, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec mpu3050_channels[] = { + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_BE, + }, + }, + MPU3050_AXIS_CHANNEL(X, 1), + MPU3050_AXIS_CHANNEL(Y, 2), + MPU3050_AXIS_CHANNEL(Z, 3), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +/* Four channels apart from timestamp, scan mask = 0x0f */ +static const unsigned long mpu3050_scan_masks[] = { 0xf, 0 }; + +/* + * These are just the hardcoded factors resulting from the more elaborate + * calculations done with fractions in the scale raw get/set functions. + */ +static IIO_CONST_ATTR(anglevel_scale_available, + "0.000122070 " + "0.000274658 " + "0.000518798 " + "0.001068115"); + +static struct attribute *mpu3050_attributes[] = { + &iio_const_attr_anglevel_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group mpu3050_attribute_group = { + .attrs = mpu3050_attributes, +}; + +static const struct iio_info mpu3050_info = { + .driver_module = THIS_MODULE, + .read_raw = mpu3050_read_raw, + .write_raw = mpu3050_write_raw, + .attrs = &mpu3050_attribute_group, + .driver_module = THIS_MODULE, +}; + +/** + * mpu3050_read_mem() - read MPU-3050 internal memory + * @mpu3050: device to read from + * @bank: target bank + * @addr: target address + * @len: number of bytes + * @buf: the buffer to store the read bytes in + */ +static int mpu3050_read_mem(struct mpu3050 *mpu3050, + u8 bank, + u8 addr, + u8 len, + u8 *buf) +{ + int ret; + + ret = regmap_write(mpu3050->map, + MPU3050_BANK_SEL, + bank); + if (ret) + return ret; + + ret = regmap_write(mpu3050->map, + MPU3050_MEM_START_ADDR, + addr); + if (ret) + return ret; + + return regmap_bulk_read(mpu3050->map, + MPU3050_MEM_R_W, + buf, + len); +} + +static int mpu3050_hw_init(struct mpu3050 *mpu3050) +{ + int ret; + u8 otp[8]; + + /* Reset */ + ret = regmap_update_bits(mpu3050->map, + MPU3050_PWR_MGM, + MPU3050_PWR_MGM_RESET, + MPU3050_PWR_MGM_RESET); + if (ret) + return ret; + + /* Turn on the PLL */ + ret = regmap_update_bits(mpu3050->map, + MPU3050_PWR_MGM, + MPU3050_PWR_MGM_CLKSEL_MASK, + MPU3050_PWR_MGM_PLL_Z); + if (ret) + return ret; + + /* Disable IRQs */ + ret = regmap_write(mpu3050->map, + MPU3050_INT_CFG, + 0); + if (ret) + return ret; + + /* Read out the 8 bytes of OTP (one-time-programmable) memory */ + ret = mpu3050_read_mem(mpu3050, + (MPU3050_MEM_PRFTCH | + MPU3050_MEM_USER_BANK | + MPU3050_MEM_OTP_BANK_0), + 0, + sizeof(otp), + otp); + if (ret) + return ret; + + /* This is device-unique data so it goes into the entropy pool */ + add_device_randomness(otp, sizeof(otp)); + + dev_info(mpu3050->dev, + "die ID: %04X, wafer ID: %02X, A lot ID: %04X, " + "W lot ID: %03X, WP ID: %01X, rev ID: %02X\n", + /* Die ID, bits 0-12 */ + (otp[1] << 8 | otp[0]) & 0x1fff, + /* Wafer ID, bits 13-17 */ + ((otp[2] << 8 | otp[1]) & 0x03e0) >> 5, + /* A lot ID, bits 18-33 */ + ((otp[4] << 16 | otp[3] << 8 | otp[2]) & 0x3fffc) >> 2, + /* W lot ID, bits 34-45 */ + ((otp[5] << 8 | otp[4]) & 0x3ffc) >> 2, + /* WP ID, bits 47-49 */ + ((otp[6] << 8 | otp[5]) & 0x0380) >> 7, + /* rev ID, bits 50-55 */ + otp[6] >> 2); + + return 0; +} + +static int mpu3050_power_up(struct mpu3050 *mpu3050) +{ + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(mpu3050->regs), mpu3050->regs); + if (ret) { + dev_err(mpu3050->dev, "cannot enable regulators\n"); + return ret; + } + /* + * 20-100 ms start-up time for register read/write according to + * the datasheet, be on the safe side and wait 200 ms. + */ + msleep(200); + + /* Take device out of sleep mode */ + ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM, + MPU3050_PWR_MGM_SLEEP, 0); + if (ret) { + dev_err(mpu3050->dev, "error setting power mode\n"); + return ret; + } + msleep(10); + + return 0; +} + +static int mpu3050_power_down(struct mpu3050 *mpu3050) +{ + int ret; + + /* + * Put MPU-3050 into sleep mode before cutting regulators. + * This is important, because we may not be the sole user + * of the regulator so the power may stay on after this, and + * then we would be wasting power unless we go to sleep mode + * first. + */ + ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM, + MPU3050_PWR_MGM_SLEEP, MPU3050_PWR_MGM_SLEEP); + if (ret) + dev_err(mpu3050->dev, "error putting to sleep\n"); + + ret = regulator_bulk_disable(ARRAY_SIZE(mpu3050->regs), mpu3050->regs); + if (ret) + dev_err(mpu3050->dev, "error disabling regulators\n"); + + return 0; +} + +static irqreturn_t mpu3050_irq_handler(int irq, void *p) +{ + struct iio_trigger *trig = p; + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + + if (!mpu3050->hw_irq_trigger) + return IRQ_NONE; + + /* Get the time stamp as close in time as possible */ + mpu3050->hw_timestamp = iio_get_time_ns(indio_dev); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t mpu3050_irq_thread(int irq, void *p) +{ + struct iio_trigger *trig = p; + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + unsigned int val; + int ret; + + /* ACK IRQ and check if it was from us */ + ret = regmap_read(mpu3050->map, MPU3050_INT_STATUS, &val); + if (ret) { + dev_err(mpu3050->dev, "error reading IRQ status\n"); + return IRQ_HANDLED; + } + if (!(val & MPU3050_INT_STATUS_RAW_RDY)) + return IRQ_NONE; + + iio_trigger_poll_chained(p); + + return IRQ_HANDLED; +} + +/** + * mpu3050_drdy_trigger_set_state() - set data ready interrupt state + * @trig: trigger instance + * @enable: true if trigger should be enabled, false to disable + */ +static int mpu3050_drdy_trigger_set_state(struct iio_trigger *trig, + bool enable) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + unsigned int val; + int ret; + + /* Disabling trigger: disable interrupt and return */ + if (!enable) { + /* Disable all interrupts */ + ret = regmap_write(mpu3050->map, + MPU3050_INT_CFG, + 0); + if (ret) + dev_err(mpu3050->dev, "error disabling IRQ\n"); + + /* Clear IRQ flag */ + ret = regmap_read(mpu3050->map, MPU3050_INT_STATUS, &val); + if (ret) + dev_err(mpu3050->dev, "error clearing IRQ status\n"); + + /* Disable all things in the FIFO and reset it */ + ret = regmap_write(mpu3050->map, MPU3050_FIFO_EN, 0); + if (ret) + dev_err(mpu3050->dev, "error disabling FIFO\n"); + + ret = regmap_write(mpu3050->map, MPU3050_USR_CTRL, + MPU3050_USR_CTRL_FIFO_RST); + if (ret) + dev_err(mpu3050->dev, "error resetting FIFO\n"); + + pm_runtime_mark_last_busy(mpu3050->dev); + pm_runtime_put_autosuspend(mpu3050->dev); + mpu3050->hw_irq_trigger = false; + + return 0; + } else { + /* Else we're enabling the trigger from this point */ + pm_runtime_get_sync(mpu3050->dev); + mpu3050->hw_irq_trigger = true; + + /* Disable all things in the FIFO */ + ret = regmap_write(mpu3050->map, MPU3050_FIFO_EN, 0); + if (ret) + return ret; + + /* Reset and enable the FIFO */ + ret = regmap_update_bits(mpu3050->map, MPU3050_USR_CTRL, + MPU3050_USR_CTRL_FIFO_EN | + MPU3050_USR_CTRL_FIFO_RST, + MPU3050_USR_CTRL_FIFO_EN | + MPU3050_USR_CTRL_FIFO_RST); + if (ret) + return ret; + + mpu3050->pending_fifo_footer = false; + + /* Turn on the FIFO for temp+X+Y+Z */ + ret = regmap_write(mpu3050->map, MPU3050_FIFO_EN, + MPU3050_FIFO_EN_TEMP_OUT | + MPU3050_FIFO_EN_GYRO_XOUT | + MPU3050_FIFO_EN_GYRO_YOUT | + MPU3050_FIFO_EN_GYRO_ZOUT | + MPU3050_FIFO_EN_FOOTER); + if (ret) + return ret; + + /* Configure the sample engine */ + ret = mpu3050_start_sampling(mpu3050); + if (ret) + return ret; + + /* Clear IRQ flag */ + ret = regmap_read(mpu3050->map, MPU3050_INT_STATUS, &val); + if (ret) + dev_err(mpu3050->dev, "error clearing IRQ status\n"); + + /* Give us interrupts whenever there is new data ready */ + val = MPU3050_INT_RAW_RDY_EN; + + if (mpu3050->irq_actl) + val |= MPU3050_INT_ACTL; + if (mpu3050->irq_latch) + val |= MPU3050_INT_LATCH_EN; + if (mpu3050->irq_opendrain) + val |= MPU3050_INT_OPEN; + + ret = regmap_write(mpu3050->map, MPU3050_INT_CFG, val); + if (ret) + return ret; + } + + return 0; +} + +static const struct iio_trigger_ops mpu3050_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = mpu3050_drdy_trigger_set_state, +}; + +static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) +{ + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + unsigned long irq_trig; + int ret; + + mpu3050->trig = devm_iio_trigger_alloc(&indio_dev->dev, + "%s-dev%d", + indio_dev->name, + indio_dev->id); + if (!mpu3050->trig) + return -ENOMEM; + + /* Check if IRQ is open drain */ + if (of_property_read_bool(mpu3050->dev->of_node, "drive-open-drain")) + mpu3050->irq_opendrain = true; + + irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); + /* + * Configure the interrupt generator hardware to supply whatever + * the interrupt is configured for, edges low/high level low/high, + * we can provide it all. + */ + switch (irq_trig) { + case IRQF_TRIGGER_RISING: + dev_info(&indio_dev->dev, + "pulse interrupts on the rising edge\n"); + if (mpu3050->irq_opendrain) { + dev_info(&indio_dev->dev, + "rising edge incompatible with open drain\n"); + mpu3050->irq_opendrain = false; + } + break; + case IRQF_TRIGGER_FALLING: + mpu3050->irq_actl = true; + dev_info(&indio_dev->dev, + "pulse interrupts on the falling edge\n"); + break; + case IRQF_TRIGGER_HIGH: + mpu3050->irq_latch = true; + dev_info(&indio_dev->dev, + "interrupts active high level\n"); + if (mpu3050->irq_opendrain) { + dev_info(&indio_dev->dev, + "active high incompatible with open drain\n"); + mpu3050->irq_opendrain = false; + } + /* + * With level IRQs, we mask the IRQ until it is processed, + * but with edge IRQs (pulses) we can queue several interrupts + * in the top half. + */ + irq_trig |= IRQF_ONESHOT; + break; + case IRQF_TRIGGER_LOW: + mpu3050->irq_latch = true; + mpu3050->irq_actl = true; + irq_trig |= IRQF_ONESHOT; + dev_info(&indio_dev->dev, + "interrupts active low level\n"); + break; + default: + /* This is the most preferred mode, if possible */ + dev_err(&indio_dev->dev, + "unsupported IRQ trigger specified (%lx), enforce " + "rising edge\n", irq_trig); + irq_trig = IRQF_TRIGGER_RISING; + break; + } + + /* An open drain line can be shared with several devices */ + if (mpu3050->irq_opendrain) + irq_trig |= IRQF_SHARED; + + ret = request_threaded_irq(irq, + mpu3050_irq_handler, + mpu3050_irq_thread, + irq_trig, + mpu3050->trig->name, + mpu3050->trig); + if (ret) { + dev_err(mpu3050->dev, + "can't get IRQ %d, error %d\n", irq, ret); + return ret; + } + + mpu3050->irq = irq; + mpu3050->trig->dev.parent = mpu3050->dev; + mpu3050->trig->ops = &mpu3050_trigger_ops; + iio_trigger_set_drvdata(mpu3050->trig, indio_dev); + + ret = iio_trigger_register(mpu3050->trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(mpu3050->trig); + + return 0; +} + +int mpu3050_common_probe(struct device *dev, + struct regmap *map, + int irq, + const char *name) +{ + struct iio_dev *indio_dev; + struct mpu3050 *mpu3050; + unsigned int val; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*mpu3050)); + if (!indio_dev) + return -ENOMEM; + mpu3050 = iio_priv(indio_dev); + + mpu3050->dev = dev; + mpu3050->map = map; + mutex_init(&mpu3050->lock); + /* Default fullscale: 2000 degrees per second */ + mpu3050->fullscale = FS_2000_DPS; + /* 1 kHz, divide by 100, default frequency = 10 Hz */ + mpu3050->lpf = MPU3050_DLPF_CFG_188HZ; + mpu3050->divisor = 99; + + /* Read the mounting matrix, if present */ + ret = of_iio_read_mount_matrix(dev, "mount-matrix", + &mpu3050->orientation); + if (ret) + return ret; + + /* Fetch and turn on regulators */ + mpu3050->regs[0].supply = mpu3050_reg_vdd; + mpu3050->regs[1].supply = mpu3050_reg_vlogic; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(mpu3050->regs), + mpu3050->regs); + if (ret) { + dev_err(dev, "Cannot get regulators\n"); + return ret; + } + + ret = mpu3050_power_up(mpu3050); + if (ret) + return ret; + + ret = regmap_read(map, MPU3050_CHIP_ID_REG, &val); + if (ret) { + dev_err(dev, "could not read device ID\n"); + ret = -ENODEV; + + goto err_power_down; + } + + if (val != MPU3050_CHIP_ID) { + dev_err(dev, "unsupported chip id %02x\n", (u8)val); + ret = -ENODEV; + goto err_power_down; + } + + ret = regmap_read(map, MPU3050_PRODUCT_ID_REG, &val); + if (ret) { + dev_err(dev, "could not read device ID\n"); + ret = -ENODEV; + + goto err_power_down; + } + dev_info(dev, "found MPU-3050 part no: %d, version: %d\n", + ((val >> 4) & 0xf), (val & 0xf)); + + ret = mpu3050_hw_init(mpu3050); + if (ret) + goto err_power_down; + + indio_dev->dev.parent = dev; + indio_dev->channels = mpu3050_channels; + indio_dev->num_channels = ARRAY_SIZE(mpu3050_channels); + indio_dev->info = &mpu3050_info; + indio_dev->available_scan_masks = mpu3050_scan_masks; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = name; + + ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time, + mpu3050_trigger_handler, + &mpu3050_buffer_setup_ops); + if (ret) { + dev_err(dev, "triggered buffer setup failed\n"); + goto err_power_down; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(dev, "device register failed\n"); + goto err_cleanup_buffer; + } + + dev_set_drvdata(dev, indio_dev); + + /* Check if we have an assigned IRQ to use as trigger */ + if (irq) { + ret = mpu3050_trigger_probe(indio_dev, irq); + if (ret) + dev_err(dev, "failed to register trigger\n"); + } + + /* Enable runtime PM */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + /* + * Set autosuspend to two orders of magnitude larger than the + * start-up time. 100ms start-up time means 10000ms autosuspend, + * i.e. 10 seconds. + */ + pm_runtime_set_autosuspend_delay(dev, 10000); + pm_runtime_use_autosuspend(dev); + pm_runtime_put(dev); + + return 0; + +err_cleanup_buffer: + iio_triggered_buffer_cleanup(indio_dev); +err_power_down: + mpu3050_power_down(mpu3050); + + return ret; +} +EXPORT_SYMBOL(mpu3050_common_probe); + +int mpu3050_common_remove(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + + pm_runtime_get_sync(dev); + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + iio_triggered_buffer_cleanup(indio_dev); + if (mpu3050->irq) + free_irq(mpu3050->irq, mpu3050); + iio_device_unregister(indio_dev); + mpu3050_power_down(mpu3050); + + return 0; +} +EXPORT_SYMBOL(mpu3050_common_remove); + +#ifdef CONFIG_PM +static int mpu3050_runtime_suspend(struct device *dev) +{ + return mpu3050_power_down(iio_priv(dev_get_drvdata(dev))); +} + +static int mpu3050_runtime_resume(struct device *dev) +{ + return mpu3050_power_up(iio_priv(dev_get_drvdata(dev))); +} +#endif /* CONFIG_PM */ + +const struct dev_pm_ops mpu3050_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(mpu3050_runtime_suspend, + mpu3050_runtime_resume, NULL) +}; +EXPORT_SYMBOL(mpu3050_dev_pm_ops); + +MODULE_AUTHOR("Linus Walleij"); +MODULE_DESCRIPTION("MPU3050 gyroscope driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/gyro/mpu3050-i2c.c b/drivers/iio/gyro/mpu3050-i2c.c new file mode 100644 index 000000000000..06007200bf49 --- /dev/null +++ b/drivers/iio/gyro/mpu3050-i2c.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "mpu3050.h" + +static const struct regmap_config mpu3050_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int mpu3050_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id) +{ + struct mpu3050 *mpu3050 = i2c_mux_priv(mux); + + /* Just power up the device, that is all that is needed */ + pm_runtime_get_sync(mpu3050->dev); + return 0; +} + +static int mpu3050_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id) +{ + struct mpu3050 *mpu3050 = i2c_mux_priv(mux); + + pm_runtime_mark_last_busy(mpu3050->dev); + pm_runtime_put_autosuspend(mpu3050->dev); + return 0; +} + +static int mpu3050_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + const char *name; + struct mpu3050 *mpu3050; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_I2C_BLOCK)) + return -EOPNOTSUPP; + + if (id) + name = id->name; + else + return -ENODEV; + + regmap = devm_regmap_init_i2c(client, &mpu3050_i2c_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Failed to register i2c regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + ret = mpu3050_common_probe(&client->dev, regmap, client->irq, name); + if (ret) + return ret; + + /* The main driver is up, now register the I2C mux */ + mpu3050 = iio_priv(dev_get_drvdata(&client->dev)); + mpu3050->i2cmux = i2c_mux_alloc(client->adapter, &client->dev, + 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE, + mpu3050_i2c_bypass_select, + mpu3050_i2c_bypass_deselect); + /* Just fail the mux, there is no point in killing the driver */ + if (!mpu3050->i2cmux) + dev_err(&client->dev, "failed to allocate I2C mux\n"); + else { + mpu3050->i2cmux->priv = mpu3050; + ret = i2c_mux_add_adapter(mpu3050->i2cmux, 0, 0, 0); + if (ret) + dev_err(&client->dev, "failed to add I2C mux\n"); + } + + return 0; +} + +static int mpu3050_i2c_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); + struct mpu3050 *mpu3050 = iio_priv(indio_dev); + + if (mpu3050->i2cmux) + i2c_mux_del_adapters(mpu3050->i2cmux); + + return mpu3050_common_remove(&client->dev); +} + +/* + * device id table is used to identify what device can be + * supported by this driver + */ +static const struct i2c_device_id mpu3050_i2c_id[] = { + { "mpu3050" }, + {} +}; +MODULE_DEVICE_TABLE(i2c, mpu3050_i2c_id); + +static const struct of_device_id mpu3050_i2c_of_match[] = { + { .compatible = "invensense,mpu3050", .data = "mpu3050" }, + /* Deprecated vendor ID from the Input driver */ + { .compatible = "invn,mpu3050", .data = "mpu3050" }, + { }, +}; +MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match); + +static struct i2c_driver mpu3050_i2c_driver = { + .probe = mpu3050_i2c_probe, + .remove = mpu3050_i2c_remove, + .id_table = mpu3050_i2c_id, + .driver = { + .of_match_table = mpu3050_i2c_of_match, + .name = "mpu3050-i2c", + .pm = &mpu3050_dev_pm_ops, + }, +}; +module_i2c_driver(mpu3050_i2c_driver); + +MODULE_AUTHOR("Linus Walleij"); +MODULE_DESCRIPTION("Invensense MPU3050 gyroscope driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/gyro/mpu3050.h b/drivers/iio/gyro/mpu3050.h new file mode 100644 index 000000000000..bef87a714dc5 --- /dev/null +++ b/drivers/iio/gyro/mpu3050.h @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include + +/** + * enum mpu3050_fullscale - indicates the full range of the sensor in deg/sec + */ +enum mpu3050_fullscale { + FS_250_DPS = 0, + FS_500_DPS, + FS_1000_DPS, + FS_2000_DPS, +}; + +/** + * enum mpu3050_lpf - indicates the low pass filter width + */ +enum mpu3050_lpf { + /* This implicity sets sample frequency to 8 kHz */ + LPF_256_HZ_NOLPF = 0, + /* All others sets the sample frequency to 1 kHz */ + LPF_188_HZ, + LPF_98_HZ, + LPF_42_HZ, + LPF_20_HZ, + LPF_10_HZ, + LPF_5_HZ, + LPF_2100_HZ_NOLPF, +}; + +enum mpu3050_axis { + AXIS_X = 0, + AXIS_Y, + AXIS_Z, + AXIS_MAX, +}; + +/** + * struct mpu3050 - instance state container for the device + * @dev: parent device for this instance + * @orientation: mounting matrix, flipped axis etc + * @map: regmap to reach the registers + * @lock: serialization lock to marshal all requests + * @irq: the IRQ used for this device + * @regs: the regulators to power this device + * @fullscale: the current fullscale setting for the device + * @lpf: digital low pass filter setting for the device + * @divisor: base frequency divider: divides 8 or 1 kHz + * @calibration: the three signed 16-bit calibration settings that + * get written into the offset registers for each axis to compensate + * for DC offsets + * @trig: trigger for the MPU-3050 interrupt, if present + * @hw_irq_trigger: hardware interrupt trigger is in use + * @irq_actl: interrupt is active low + * @irq_latch: latched IRQ, this means that it is a level IRQ + * @irq_opendrain: the interrupt line shall be configured open drain + * @pending_fifo_footer: tells us if there is a pending footer in the FIFO + * that we have to read out first when handling the FIFO + * @hw_timestamp: latest hardware timestamp from the trigger IRQ, when in + * use + * @i2cmux: an I2C mux reflecting the fact that this sensor is a hub with + * a pass-through I2C interface coming out of it: this device needs to be + * powered up in order to reach devices on the other side of this mux + */ +struct mpu3050 { + struct device *dev; + struct iio_mount_matrix orientation; + struct regmap *map; + struct mutex lock; + int irq; + struct regulator_bulk_data regs[2]; + enum mpu3050_fullscale fullscale; + enum mpu3050_lpf lpf; + u8 divisor; + s16 calibration[3]; + struct iio_trigger *trig; + bool hw_irq_trigger; + bool irq_actl; + bool irq_latch; + bool irq_opendrain; + bool pending_fifo_footer; + s64 hw_timestamp; + struct i2c_mux_core *i2cmux; +}; + +/* Probe called from different transports */ +int mpu3050_common_probe(struct device *dev, + struct regmap *map, + int irq, + const char *name); +int mpu3050_common_remove(struct device *dev); + +/* PM ops */ +extern const struct dev_pm_ops mpu3050_dev_pm_ops; -- cgit v1.2.3 From 3089ec2c104ccfb7295d6c2a25d5b505cc59669b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 25 Oct 2016 17:56:23 +0200 Subject: staging: iio: cdc/ad7746: fix missing return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As found by "gcc -Wmaybe-uninitialized", the latest change to the driver lacked an initalization for the return code in one of the added cases: drivers/staging/iio/cdc/ad7746.c: In function ‘ad7746_read_raw’: drivers/staging/iio/cdc/ad7746.c:655:2: error: ‘ret’ may be used uninitialized in this function [-Werror=maybe-uninitialized] This sets it to IIO_VAL_INT, which I think is what we want here. Fixes: 2296c0623eb7 ("staging: iio: cdc: ad7746: implement IIO_CHAN_INFO_SAMP_FREQ") Signed-off-by: Arnd Bergmann Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index f41251ceeacd..a5828f9aa437 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -642,6 +642,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, case IIO_VOLTAGE: *val = ad7746_vt_filter_rate_table[ (chip->config >> 6) & 0x3][0]; + ret = IIO_VAL_INT; break; default: ret = -EINVAL; -- cgit v1.2.3 From 32cb7d27e65df9daa7cee8f1fdf7b259f214bee2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 25 Oct 2016 17:55:04 +0200 Subject: iio: maxim_thermocouple: detect invalid storage size in read() As found by gcc -Wmaybe-uninitialized, having a storage_bytes value other than 2 or 4 will result in undefined behavior: drivers/iio/temperature/maxim_thermocouple.c: In function 'maxim_thermocouple_read': drivers/iio/temperature/maxim_thermocouple.c:141:5: error: 'ret' may be used uninitialized in this function [-Werror=maybe-uninitialized] This probably cannot happen, but returning -EINVAL here is appropriate and makes gcc happy and the code more robust. Fixes: 231147ee77f3 ("iio: maxim_thermocouple: Align 16 bit big endian value of raw reads") Signed-off-by: Arnd Bergmann Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/maxim_thermocouple.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index 39dd2026ccc9..d19a4dea4c3c 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -137,6 +137,8 @@ static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, case 4: *val = be32_to_cpu(buf); break; + default: + ret = -EINVAL; } /* check to be sure this is a valid reading */ -- cgit v1.2.3 From 974e6f02e27e1b46c6c5e600e70ced25079f73eb Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Mon, 1 Aug 2016 11:54:35 +0200 Subject: iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub. Add the core functions to be able to support the sensors attached behind the ChromeOS Embedded Controller and used by other IIO cros-ec sensor drivers. The cros_ec_sensor_core driver matches with current driver in ChromeOS 4.4 tree, so it includes all the fixes at the moment. The support for this driver was made by Gwendal Grignou. The original patch and all the fixes has been squashed and rebased on top of mainline. Signed-off-by: Gwendal Grignou Signed-off-by: Guenter Roeck [eballetbo: split, squash and rebase on top of mainline the patches found in ChromeOS tree] Signed-off-by: Enric Balletbo i Serra Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio-cros-ec | 18 + drivers/iio/common/Kconfig | 1 + drivers/iio/common/Makefile | 1 + drivers/iio/common/cros_ec_sensors/Kconfig | 14 + drivers/iio/common/cros_ec_sensors/Makefile | 5 + .../common/cros_ec_sensors/cros_ec_sensors_core.c | 450 +++++++++++++++++++++ .../common/cros_ec_sensors/cros_ec_sensors_core.h | 175 ++++++++ include/linux/mfd/cros_ec.h | 9 + include/linux/mfd/cros_ec_commands.h | 99 ++++- 9 files changed, 767 insertions(+), 5 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-bus-iio-cros-ec b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec new file mode 100644 index 000000000000..297b9720f024 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec @@ -0,0 +1,18 @@ +What: /sys/bus/iio/devices/iio:deviceX/calibrate +Date: July 2015 +KernelVersion: 4.7 +Contact: linux-iio@vger.kernel.org +Description: + Writing '1' will perform a FOC (Fast Online Calibration). The + corresponding calibration offsets can be read from *_calibbias + entries. + +What: /sys/bus/iio/devices/iio:deviceX/location +Date: July 2015 +KernelVersion: 4.7 +Contact: linux-iio@vger.kernel.org +Description: + This attribute returns a string with the physical location where + the motion sensor is placed. For example, in a laptop a motion + sensor can be located on the base or on the lid. Current valid + values are 'base' and 'lid'. diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig index 26a6026de614..e108996a9627 100644 --- a/drivers/iio/common/Kconfig +++ b/drivers/iio/common/Kconfig @@ -2,6 +2,7 @@ # IIO common modules # +source "drivers/iio/common/cros_ec_sensors/Kconfig" source "drivers/iio/common/hid-sensors/Kconfig" source "drivers/iio/common/ms_sensors/Kconfig" source "drivers/iio/common/ssp_sensors/Kconfig" diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile index 585da6a1b188..6fa760e1bdd5 100644 --- a/drivers/iio/common/Makefile +++ b/drivers/iio/common/Makefile @@ -7,6 +7,7 @@ # # When adding new entries keep the list in alphabetical order +obj-y += cros_ec_sensors/ obj-y += hid-sensors/ obj-y += ms_sensors/ obj-y += ssp_sensors/ diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig new file mode 100644 index 000000000000..24743be15a5b --- /dev/null +++ b/drivers/iio/common/cros_ec_sensors/Kconfig @@ -0,0 +1,14 @@ +# +# Chrome OS Embedded Controller managed sensors library +# +config IIO_CROS_EC_SENSORS_CORE + tristate "ChromeOS EC Sensors Core" + depends on SYSFS && MFD_CROS_EC + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Base module for the ChromeOS EC Sensors module. + Contains core functions used by other IIO CrosEC sensor + drivers. + Define common attributes and sysfs interrupt handler. + diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile new file mode 100644 index 000000000000..95b690139bfd --- /dev/null +++ b/drivers/iio/common/cros_ec_sensors/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for sensors seen through the ChromeOS EC sensor hub. +# + +obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c new file mode 100644 index 000000000000..a3be7991355e --- /dev/null +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -0,0 +1,450 @@ +/* + * cros_ec_sensors_core - Common function for Chrome OS EC sensor driver. + * + * Copyright (C) 2016 Google, Inc + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cros_ec_sensors_core.h" + +static char *cros_ec_loc[] = { + [MOTIONSENSE_LOC_BASE] = "base", + [MOTIONSENSE_LOC_LID] = "lid", + [MOTIONSENSE_LOC_MAX] = "unknown", +}; + +int cros_ec_sensors_core_init(struct platform_device *pdev, + struct iio_dev *indio_dev, + bool physical_device) +{ + struct device *dev = &pdev->dev; + struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); + struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); + struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); + + platform_set_drvdata(pdev, indio_dev); + + state->ec = ec->ec_dev; + state->msg = devm_kzalloc(&pdev->dev, + max((u16)sizeof(struct ec_params_motion_sense), + state->ec->max_response), GFP_KERNEL); + if (!state->msg) + return -ENOMEM; + + state->resp = (struct ec_response_motion_sense *)state->msg->data; + + mutex_init(&state->cmd_lock); + + /* Set up the host command structure. */ + state->msg->version = 2; + state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; + state->msg->outsize = sizeof(struct ec_params_motion_sense); + + indio_dev->dev.parent = &pdev->dev; + indio_dev->name = pdev->name; + + if (physical_device) { + indio_dev->modes = INDIO_DIRECT_MODE; + + state->param.cmd = MOTIONSENSE_CMD_INFO; + state->param.info.sensor_num = sensor_platform->sensor_num; + if (cros_ec_motion_send_host_cmd(state, 0)) { + dev_warn(dev, "Can not access sensor info\n"); + return -EIO; + } + state->type = state->resp->info.type; + state->loc = state->resp->info.location; + } + + return 0; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init); + +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state, + u16 opt_length) +{ + int ret; + + if (opt_length) + state->msg->insize = min(opt_length, state->ec->max_response); + else + state->msg->insize = state->ec->max_response; + + memcpy(state->msg->data, &state->param, sizeof(state->param)); + + ret = cros_ec_cmd_xfer_status(state->ec, state->msg); + if (ret < 0) + return -EIO; + + if (ret && + state->resp != (struct ec_response_motion_sense *)state->msg->data) + memcpy(state->resp, state->msg->data, ret); + + return 0; +} +EXPORT_SYMBOL_GPL(cros_ec_motion_send_host_cmd); + +static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + int ret, i; + bool calibrate; + + ret = strtobool(buf, &calibrate); + if (ret < 0) + return ret; + if (!calibrate) + return -EINVAL; + + mutex_lock(&st->cmd_lock); + st->param.cmd = MOTIONSENSE_CMD_PERFORM_CALIB; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret != 0) { + dev_warn(&indio_dev->dev, "Unable to calibrate sensor\n"); + } else { + /* Save values */ + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->calib[i] = st->resp->perform_calib.offset[i]; + } + mutex_unlock(&st->cmd_lock); + + return ret ? ret : len; +} + +static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, + char *buf) +{ + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + + return snprintf(buf, PAGE_SIZE, "%s\n", cros_ec_loc[st->loc]); +} + +const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[] = { + { + .name = "calibrate", + .shared = IIO_SHARED_BY_ALL, + .write = cros_ec_sensors_calibrate + }, + { + .name = "location", + .shared = IIO_SHARED_BY_ALL, + .read = cros_ec_sensors_loc + }, + { }, +}; +EXPORT_SYMBOL_GPL(cros_ec_sensors_ext_info); + +/** + * cros_ec_sensors_idx_to_reg - convert index into offset in shared memory + * @st: pointer to state information for device + * @idx: sensor index (should be element of enum sensor_index) + * + * Return: address to read at + */ +static unsigned int cros_ec_sensors_idx_to_reg( + struct cros_ec_sensors_core_state *st, + unsigned int idx) +{ + /* + * When using LPC interface, only space for 2 Accel and one Gyro. + * First halfword of MOTIONSENSE_TYPE_ACCEL is used by angle. + */ + if (st->type == MOTIONSENSE_TYPE_ACCEL) + return EC_MEMMAP_ACC_DATA + sizeof(u16) * + (1 + idx + st->param.info.sensor_num * + CROS_EC_SENSOR_MAX_AXIS); + + return EC_MEMMAP_GYRO_DATA + sizeof(u16) * idx; +} + +static int cros_ec_sensors_cmd_read_u8(struct cros_ec_device *ec, + unsigned int offset, u8 *dest) +{ + return ec->cmd_readmem(ec, offset, 1, dest); +} + +static int cros_ec_sensors_cmd_read_u16(struct cros_ec_device *ec, + unsigned int offset, u16 *dest) +{ + __le16 tmp; + int ret = ec->cmd_readmem(ec, offset, 2, &tmp); + + if (ret >= 0) + *dest = le16_to_cpu(tmp); + + return ret; +} + +/** + * cros_ec_sensors_read_until_not_busy() - read until is not busy + * + * @st: pointer to state information for device + * + * Read from EC status byte until it reads not busy. + * Return: 8-bit status if ok, -errno on failure. + */ +static int cros_ec_sensors_read_until_not_busy( + struct cros_ec_sensors_core_state *st) +{ + struct cros_ec_device *ec = st->ec; + u8 status; + int ret, attempts = 0; + + ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status); + if (ret < 0) + return ret; + + while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) { + /* Give up after enough attempts, return error. */ + if (attempts++ >= 50) + return -EIO; + + /* Small delay every so often. */ + if (attempts % 5 == 0) + msleep(25); + + ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, + &status); + if (ret < 0) + return ret; + } + + return status; +} + +/** + * read_ec_sensors_data_unsafe() - read acceleration data from EC shared memory + * @indio_dev: pointer to IIO device + * @scan_mask: bitmap of the sensor indices to scan + * @data: location to store data + * + * This is the unsafe function for reading the EC data. It does not guarantee + * that the EC will not modify the data as it is being read in. + * + * Return: 0 on success, -errno on failure. + */ +static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev, + unsigned long scan_mask, s16 *data) +{ + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + struct cros_ec_device *ec = st->ec; + unsigned int i; + int ret; + + /* Read all sensors enabled in scan_mask. Each value is 2 bytes. */ + for_each_set_bit(i, &scan_mask, indio_dev->masklength) { + ret = cros_ec_sensors_cmd_read_u16(ec, + cros_ec_sensors_idx_to_reg(st, i), + data); + if (ret < 0) + return ret; + + data++; + } + + return 0; +} + +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, + unsigned long scan_mask, s16 *data) +{ + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + struct cros_ec_device *ec = st->ec; + u8 samp_id = 0xff, status = 0; + int ret, attempts = 0; + + /* + * Continually read all data from EC until the status byte after + * all reads reflects that the EC is not busy and the sample id + * matches the sample id from before all reads. This guarantees + * that data read in was not modified by the EC while reading. + */ + while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT | + EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) { + /* If we have tried to read too many times, return error. */ + if (attempts++ >= 5) + return -EIO; + + /* Read status byte until EC is not busy. */ + status = cros_ec_sensors_read_until_not_busy(st); + if (status < 0) + return status; + + /* + * Store the current sample id so that we can compare to the + * sample id after reading the data. + */ + samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK; + + /* Read all EC data, format it, and store it into data. */ + ret = cros_ec_sensors_read_data_unsafe(indio_dev, scan_mask, + data); + if (ret < 0) + return ret; + + /* Read status byte. */ + ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, + &status); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc); + +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, + unsigned long scan_mask, s16 *data) +{ + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + int ret; + unsigned int i; + + /* Read all sensor data through a command. */ + st->param.cmd = MOTIONSENSE_CMD_DATA; + ret = cros_ec_motion_send_host_cmd(st, sizeof(st->resp->data)); + if (ret != 0) { + dev_warn(&indio_dev->dev, "Unable to read sensor data\n"); + return ret; + } + + for_each_set_bit(i, &scan_mask, indio_dev->masklength) { + *data = st->resp->data.data[i]; + data++; + } + + return 0; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd); + +irqreturn_t cros_ec_sensors_capture(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->cmd_lock); + + /* Clear capture data. */ + memset(st->samples, 0, indio_dev->scan_bytes); + + /* Read data based on which channels are enabled in scan mask. */ + ret = st->read_ec_sensors_data(indio_dev, + *(indio_dev->active_scan_mask), + (s16 *)st->samples); + if (ret < 0) + goto done; + + iio_push_to_buffers_with_timestamp(indio_dev, st->samples, + iio_get_time_ns(indio_dev)); + +done: + /* + * Tell the core we are done with this trigger and ready for the + * next one. + */ + iio_trigger_notify_done(indio_dev->trig); + + mutex_unlock(&st->cmd_lock); + + return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_capture); + +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret = IIO_VAL_INT; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + st->param.cmd = MOTIONSENSE_CMD_EC_RATE; + st->param.ec_rate.data = + EC_MOTION_SENSE_NO_VALUE; + + if (cros_ec_motion_send_host_cmd(st, 0)) + ret = -EIO; + else + *val = st->resp->ec_rate.ret; + break; + case IIO_CHAN_INFO_FREQUENCY: + st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; + st->param.sensor_odr.data = + EC_MOTION_SENSE_NO_VALUE; + + if (cros_ec_motion_send_host_cmd(st, 0)) + ret = -EIO; + else + *val = st->resp->sensor_odr.ret; + break; + default: + break; + } + + return ret; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read); + +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int ret = 0; + + switch (mask) { + case IIO_CHAN_INFO_FREQUENCY: + st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; + st->param.sensor_odr.data = val; + + /* Always roundup, so caller gets at least what it asks for. */ + st->param.sensor_odr.roundup = 1; + + if (cros_ec_motion_send_host_cmd(st, 0)) + ret = -EIO; + break; + case IIO_CHAN_INFO_SAMP_FREQ: + st->param.cmd = MOTIONSENSE_CMD_EC_RATE; + st->param.ec_rate.data = val; + + if (cros_ec_motion_send_host_cmd(st, 0)) + ret = -EIO; + else + st->curr_sampl_freq = val; + break; + default: + ret = -EINVAL; + break; + } + return ret; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write); + +MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h new file mode 100644 index 000000000000..8bc2ca3c2e2e --- /dev/null +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h @@ -0,0 +1,175 @@ +/* + * ChromeOS EC sensor hub + * + * Copyright (C) 2016 Google, Inc + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __CROS_EC_SENSORS_CORE_H +#define __CROS_EC_SENSORS_CORE_H + +#include + +enum { + CROS_EC_SENSOR_X, + CROS_EC_SENSOR_Y, + CROS_EC_SENSOR_Z, + CROS_EC_SENSOR_MAX_AXIS, +}; + +/* EC returns sensor values using signed 16 bit registers */ +#define CROS_EC_SENSOR_BITS 16 + +/* + * 4 16 bit channels are allowed. + * Good enough for current sensors, they use up to 3 16 bit vectors. + */ +#define CROS_EC_SAMPLE_SIZE (sizeof(s64) * 2) + +/* Minimum sampling period to use when device is suspending */ +#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000 /* 1 second */ + +/** + * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver + * @ec: cros EC device structure + * @cmd_lock: lock used to prevent simultaneous access to the + * commands. + * @msg: cros EC command structure + * @param: motion sensor parameters structure + * @resp: motion sensor response structure + * @type: type of motion sensor + * @loc: location where the motion sensor is placed + * @calib: calibration parameters. Note that trigger + * captured data will always provide the calibrated + * data + * @samples: static array to hold data from a single capture. + * For each channel we need 2 bytes, except for + * the timestamp. The timestamp is always last and + * is always 8-byte aligned. + * @read_ec_sensors_data: function used for accessing sensors values + * @cuur_sampl_freq: current sampling period + */ +struct cros_ec_sensors_core_state { + struct cros_ec_device *ec; + struct mutex cmd_lock; + + struct cros_ec_command *msg; + struct ec_params_motion_sense param; + struct ec_response_motion_sense *resp; + + enum motionsensor_type type; + enum motionsensor_location loc; + + s16 calib[CROS_EC_SENSOR_MAX_AXIS]; + + u8 samples[CROS_EC_SAMPLE_SIZE]; + + int (*read_ec_sensors_data)(struct iio_dev *indio_dev, + unsigned long scan_mask, s16 *data); + + int curr_sampl_freq; +}; + +/** + * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory + * @indio_dev: pointer to IIO device + * @scan_mask: bitmap of the sensor indices to scan + * @data: location to store data + * + * This is the safe function for reading the EC data. It guarantees that the + * data sampled was not modified by the EC while being read. + * + * Return: 0 on success, -errno on failure. + */ +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask, + s16 *data); + +/** + * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol + * @indio_dev: pointer to IIO device + * @scan_mask: bitmap of the sensor indices to scan + * @data: location to store data + * + * Return: 0 on success, -errno on failure. + */ +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask, + s16 *data); + +/** + * cros_ec_sensors_core_init() - basic initialization of the core structure + * @pdev: platform device created for the sensors + * @indio_dev: iio device structure of the device + * @physical_device: true if the device refers to a physical device + * + * Return: 0 on success, -errno on failure. + */ +int cros_ec_sensors_core_init(struct platform_device *pdev, + struct iio_dev *indio_dev, bool physical_device); + +/** + * cros_ec_sensors_capture() - the trigger handler function + * @irq: the interrupt number. + * @p: a pointer to the poll function. + * + * On a trigger event occurring, if the pollfunc is attached then this + * handler is called as a threaded interrupt (and hence may sleep). It + * is responsible for grabbing data from the device and pushing it into + * the associated buffer. + * + * Return: IRQ_HANDLED + */ +irqreturn_t cros_ec_sensors_capture(int irq, void *p); + +/** + * cros_ec_motion_send_host_cmd() - send motion sense host command + * @st: pointer to state information for device + * @opt_length: optional length to reduce the response size, useful on the data + * path. Otherwise, the maximal allowed response size is used + * + * When called, the sub-command is assumed to be set in param->cmd. + * + * Return: 0 on success, -errno on failure. + */ +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st, + u16 opt_length); + +/** + * cros_ec_sensors_core_read() - function to request a value from the sensor + * @st: pointer to state information for device + * @chan: channel specification structure table + * @val: will contain one element making up the returned value + * @val2: will contain another element making up the returned value + * @mask: specifies which values to be requested + * + * Return: the type of value returned by the device + */ +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask); + +/** + * cros_ec_sensors_core_write() - function to write a value to the sensor + * @st: pointer to state information for device + * @chan: channel specification structure table + * @val: first part of value to write + * @val2: second part of value to write + * @mask: specifies which values to write + * + * Return: the type of value returned by the device + */ +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, + struct iio_chan_spec const *chan, + int val, int val2, long mask); + +/* List of extended channel specification for all sensors */ +extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[]; + +#endif /* __CROS_EC_SENSORS_CORE_H */ diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index 76f7ef4d3a0d..1f85b7aff097 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -148,6 +148,15 @@ struct cros_ec_device { int event_size; }; +/** + * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information + * + * @sensor_num: Id of the sensor, as reported by the EC. + */ +struct cros_ec_sensor_platform { + u8 sensor_num; +}; + /* struct cros_ec_platform - ChromeOS EC platform information * * @ec_name: name of EC device (e.g. 'cros-ec', 'cros-pd', ...) diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index 76728ff37d01..8826e0f64b0e 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h @@ -1315,6 +1315,24 @@ enum motionsense_command { */ MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5, + /* + * Returns a single sensor data. + */ + MOTIONSENSE_CMD_DATA = 6, + + /* + * Perform low level calibration.. On sensors that support it, ask to + * do offset calibration. + */ + MOTIONSENSE_CMD_PERFORM_CALIB = 10, + + /* + * Sensor Offset command is a setter/getter command for the offset used + * for calibration. The offsets can be calculated by the host, or via + * PERFORM_CALIB command. + */ + MOTIONSENSE_CMD_SENSOR_OFFSET = 11, + /* Number of motionsense sub-commands. */ MOTIONSENSE_NUM_CMDS }; @@ -1335,12 +1353,18 @@ enum motionsensor_id { enum motionsensor_type { MOTIONSENSE_TYPE_ACCEL = 0, MOTIONSENSE_TYPE_GYRO = 1, + MOTIONSENSE_TYPE_MAG = 2, + MOTIONSENSE_TYPE_PROX = 3, + MOTIONSENSE_TYPE_LIGHT = 4, + MOTIONSENSE_TYPE_ACTIVITY = 5, + MOTIONSENSE_TYPE_MAX }; /* List of motion sensor locations. */ enum motionsensor_location { MOTIONSENSE_LOC_BASE = 0, MOTIONSENSE_LOC_LID = 1, + MOTIONSENSE_LOC_MAX, }; /* List of motion sensor chips. */ @@ -1361,6 +1385,31 @@ enum motionsensor_chip { */ #define EC_MOTION_SENSE_NO_VALUE -1 +#define EC_MOTION_SENSE_INVALID_CALIB_TEMP 0x8000 + +/* Set Calibration information */ +#define MOTION_SENSE_SET_OFFSET 1 + +struct ec_response_motion_sensor_data { + /* Flags for each sensor. */ + uint8_t flags; + /* Sensor number the data comes from */ + uint8_t sensor_num; + /* Each sensor is up to 3-axis. */ + union { + int16_t data[3]; + struct { + uint16_t rsvd; + uint32_t timestamp; + } __packed; + struct { + uint8_t activity; /* motionsensor_activity */ + uint8_t state; + int16_t add_info[2]; + }; + }; +} __packed; + struct ec_params_motion_sense { uint8_t cmd; union { @@ -1378,9 +1427,37 @@ struct ec_params_motion_sense { int16_t data; } ec_rate, kb_wake_angle; + /* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */ + struct { + uint8_t sensor_num; + + /* + * bit 0: If set (MOTION_SENSE_SET_OFFSET), set + * the calibration information in the EC. + * If unset, just retrieve calibration information. + */ + uint16_t flags; + + /* + * Temperature at calibration, in units of 0.01 C + * 0x8000: invalid / unknown. + * 0x0: 0C + * 0x7fff: +327.67C + */ + int16_t temp; + + /* + * Offset for calibration. + * Unit: + * Accelerometer: 1/1024 g + * Gyro: 1/1024 deg/s + * Compass: 1/16 uT + */ + int16_t offset[3]; + } __packed sensor_offset; + /* Used for MOTIONSENSE_CMD_INFO. */ struct { - /* Should be element of enum motionsensor_id. */ uint8_t sensor_num; } info; @@ -1410,11 +1487,14 @@ struct ec_response_motion_sense { /* Flags representing the motion sensor module. */ uint8_t module_flags; - /* Flags for each sensor in enum motionsensor_id. */ - uint8_t sensor_flags[EC_MOTION_SENSOR_COUNT]; + /* Number of sensors managed directly by the EC. */ + uint8_t sensor_count; - /* Array of all sensor data. Each sensor is 3-axis. */ - int16_t data[3*EC_MOTION_SENSOR_COUNT]; + /* + * Sensor data is truncated if response_max is too small + * for holding all the data. + */ + struct ec_response_motion_sensor_data sensor[0]; } dump; /* Used for MOTIONSENSE_CMD_INFO. */ @@ -1429,6 +1509,9 @@ struct ec_response_motion_sense { uint8_t chip; } info; + /* Used for MOTIONSENSE_CMD_DATA */ + struct ec_response_motion_sensor_data data; + /* * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR, * MOTIONSENSE_CMD_SENSOR_RANGE, and @@ -1438,6 +1521,12 @@ struct ec_response_motion_sense { /* Current value of the parameter queried. */ int32_t ret; } ec_rate, sensor_odr, sensor_range, kb_wake_angle; + + /* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */ + struct { + int16_t temp; + int16_t offset[3]; + } sensor_offset, perform_calib; }; } __packed; -- cgit v1.2.3 From c14dca07a31dac8bd91aa818df62fb3bf1d846c5 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Mon, 1 Aug 2016 11:54:36 +0200 Subject: iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver Handle 3d contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are presented by the ChromeOS EC Sensor hub. Signed-off-by: Guenter Roeck Signed-off-by: Enric Balletbo i Serra Signed-off-by: Jonathan Cameron --- drivers/iio/common/cros_ec_sensors/Kconfig | 9 + drivers/iio/common/cros_ec_sensors/Makefile | 1 + .../iio/common/cros_ec_sensors/cros_ec_sensors.c | 322 +++++++++++++++++++++ 3 files changed, 332 insertions(+) create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c (limited to 'drivers') diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig index 24743be15a5b..3349c9d2cf7a 100644 --- a/drivers/iio/common/cros_ec_sensors/Kconfig +++ b/drivers/iio/common/cros_ec_sensors/Kconfig @@ -12,3 +12,12 @@ config IIO_CROS_EC_SENSORS_CORE drivers. Define common attributes and sysfs interrupt handler. +config IIO_CROS_EC_SENSORS + tristate "ChromeOS EC Contiguous Sensors" + select IIO_CROS_EC_SENSORS_CORE + select MFD_CROSS_EC + help + Module to handle 3d contiguous sensors like + Accelerometers, Gyroscope and Magnetometer that are + presented by the ChromeOS EC Sensor hub. + Creates an IIO device for each functions. diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile index 95b690139bfd..ec716ff2a775 100644 --- a/drivers/iio/common/cros_ec_sensors/Makefile +++ b/drivers/iio/common/cros_ec_sensors/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o +obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c new file mode 100644 index 000000000000..48edeba35b83 --- /dev/null +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -0,0 +1,322 @@ +/* + * cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors. + * + * Copyright (C) 2016 Google, Inc + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This driver uses the cros-ec interface to communicate with the Chrome OS + * EC about sensors data. Data access is presented through iio sysfs. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cros_ec_sensors_core.h" + +#define CROS_EC_SENSORS_MAX_CHANNELS 4 + +/* State data for ec_sensors iio driver. */ +struct cros_ec_sensors_state { + /* Shared by all sensors */ + struct cros_ec_sensors_core_state core; + + struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS]; +}; + +static int cros_ec_sensors_read(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct cros_ec_sensors_state *st = iio_priv(indio_dev); + s16 data = 0; + s64 val64; + int i; + int ret = IIO_VAL_INT; + int idx = chan->scan_index; + + mutex_lock(&st->core.cmd_lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, &data); + if (ret < 0) + break; + + *val = data; + break; + case IIO_CHAN_INFO_CALIBBIAS: + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; + st->core.param.sensor_offset.flags = 0; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret < 0) + break; + + /* Save values */ + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->core.calib[i] = + st->core.resp->sensor_offset.offset[i]; + + *val = st->core.calib[idx]; + break; + case IIO_CHAN_INFO_SCALE: + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; + st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret < 0) + break; + + val64 = st->core.resp->sensor_range.ret; + switch (st->core.type) { + case MOTIONSENSE_TYPE_ACCEL: + /* + * EC returns data in g, iio exepects m/s^2. + * Do not use IIO_G_TO_M_S_2 to avoid precision loss. + */ + *val = div_s64(val64 * 980665, 10); + *val2 = 10000 << (CROS_EC_SENSOR_BITS - 1); + ret = IIO_VAL_FRACTIONAL; + break; + case MOTIONSENSE_TYPE_GYRO: + /* + * EC returns data in dps, iio expects rad/s. + * Do not use IIO_DEGREE_TO_RAD to avoid precision + * loss. Round to the nearest integer. + */ + *val = div_s64(val64 * 314159 + 9000000ULL, 1000); + *val2 = 18000 << (CROS_EC_SENSOR_BITS - 1); + ret = IIO_VAL_FRACTIONAL; + break; + case MOTIONSENSE_TYPE_MAG: + /* + * EC returns data in 16LSB / uT, + * iio expects Gauss + */ + *val = val64; + *val2 = 100 << (CROS_EC_SENSOR_BITS - 1); + ret = IIO_VAL_FRACTIONAL; + break; + default: + ret = -EINVAL; + } + break; + default: + ret = cros_ec_sensors_core_read(&st->core, chan, val, val2, + mask); + break; + } + mutex_unlock(&st->core.cmd_lock); + + return ret; +} + +static int cros_ec_sensors_write(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct cros_ec_sensors_state *st = iio_priv(indio_dev); + int i; + int ret = 0; + int idx = chan->scan_index; + + mutex_lock(&st->core.cmd_lock); + + switch (mask) { + case IIO_CHAN_INFO_CALIBBIAS: + st->core.calib[idx] = val; + + /* Send to EC for each axis, even if not complete */ + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; + st->core.param.sensor_offset.flags = + MOTION_SENSE_SET_OFFSET; + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->core.param.sensor_offset.offset[i] = + st->core.calib[i]; + st->core.param.sensor_offset.temp = + EC_MOTION_SENSE_INVALID_CALIB_TEMP; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + break; + case IIO_CHAN_INFO_SCALE: + if (st->core.type == MOTIONSENSE_TYPE_MAG) { + ret = -EINVAL; + break; + } + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; + st->core.param.sensor_range.data = val; + + /* Always roundup, so caller gets at least what it asks for. */ + st->core.param.sensor_range.roundup = 1; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + break; + default: + ret = cros_ec_sensors_core_write( + &st->core, chan, val, val2, mask); + break; + } + + mutex_unlock(&st->core.cmd_lock); + + return ret; +} + +static const struct iio_info ec_sensors_info = { + .read_raw = &cros_ec_sensors_read, + .write_raw = &cros_ec_sensors_write, + .driver_module = THIS_MODULE, +}; + +static int cros_ec_sensors_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); + struct cros_ec_device *ec_device; + struct iio_dev *indio_dev; + struct cros_ec_sensors_state *state; + struct iio_chan_spec *channel; + int ret, i; + + if (!ec_dev || !ec_dev->ec_dev) { + dev_warn(&pdev->dev, "No CROS EC device found.\n"); + return -EINVAL; + } + ec_device = ec_dev->ec_dev; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); + if (!indio_dev) + return -ENOMEM; + + ret = cros_ec_sensors_core_init(pdev, indio_dev, true); + if (ret) + return ret; + + indio_dev->info = &ec_sensors_info; + state = iio_priv(indio_dev); + for (channel = state->channels, i = CROS_EC_SENSOR_X; + i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) { + /* Common part */ + channel->info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBBIAS); + channel->info_mask_shared_by_all = + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_FREQUENCY) | + BIT(IIO_CHAN_INFO_SAMP_FREQ); + channel->scan_type.realbits = CROS_EC_SENSOR_BITS; + channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; + channel->scan_index = i; + channel->ext_info = cros_ec_sensors_ext_info; + channel->modified = 1; + channel->channel2 = IIO_MOD_X + i; + channel->scan_type.sign = 's'; + + /* Sensor specific */ + switch (state->core.type) { + case MOTIONSENSE_TYPE_ACCEL: + channel->type = IIO_ACCEL; + break; + case MOTIONSENSE_TYPE_GYRO: + channel->type = IIO_ANGL_VEL; + break; + case MOTIONSENSE_TYPE_MAG: + channel->type = IIO_MAGN; + break; + default: + dev_err(&pdev->dev, "Unknown motion sensor\n"); + return -EINVAL; + } + } + + /* Timestamp */ + channel->type = IIO_TIMESTAMP; + channel->channel = -1; + channel->scan_index = CROS_EC_SENSOR_MAX_AXIS; + channel->scan_type.sign = 's'; + channel->scan_type.realbits = 64; + channel->scan_type.storagebits = 64; + + indio_dev->channels = state->channels; + indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS; + + /* There is only enough room for accel and gyro in the io space */ + if ((state->core.ec->cmd_readmem != NULL) && + (state->core.type != MOTIONSENSE_TYPE_MAG)) + state->core.read_ec_sensors_data = cros_ec_sensors_read_lpc; + else + state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + cros_ec_sensors_capture, NULL); + if (ret) + return ret; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_uninit_buffer; + + return 0; + +error_uninit_buffer: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; +} + +static int cros_ec_sensors_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + return 0; +} + +static const struct platform_device_id cros_ec_sensors_ids[] = { + { + .name = "cros-ec-accel", + }, + { + .name = "cros-ec-gyro", + }, + { + .name = "cros-ec-mag", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids); + +static struct platform_driver cros_ec_sensors_platform_driver = { + .driver = { + .name = "cros-ec-sensors", + }, + .probe = cros_ec_sensors_probe, + .remove = cros_ec_sensors_remove, + .id_table = cros_ec_sensors_ids, +}; +module_platform_driver(cros_ec_sensors_platform_driver); + +MODULE_DESCRIPTION("ChromeOS EC 3-axis sensors driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From e4244ebddae27e9200146bba897f12a3950ce722 Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Mon, 1 Aug 2016 11:54:37 +0200 Subject: platform/chrome: Introduce a new function to check EC features. Use the EC_CMD_GET_FEATURES message to check the supported features for each MCU. Signed-off-by: Vincent Palatin [tomeu: adapted to changes in mainline] Signed-off-by: Tomeu Vizoso [enric: remove references to USB PD feature and do it more generic] Signed-off-by: Enric Balletbo i Serra Reviewed-by: Guenter Roeck For the MFD changes: Acked-by: Lee Jones Signed-off-by: Jonathan Cameron --- drivers/platform/chrome/cros_ec_dev.c | 37 +++++++++++++++ include/linux/mfd/cros_ec.h | 1 + include/linux/mfd/cros_ec_commands.h | 84 +++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c index 8abd80dbcbed..7eb53078b03d 100644 --- a/drivers/platform/chrome/cros_ec_dev.c +++ b/drivers/platform/chrome/cros_ec_dev.c @@ -87,6 +87,41 @@ exit: return ret; } +static int cros_ec_check_features(struct cros_ec_dev *ec, int feature) +{ + struct cros_ec_command *msg; + int ret; + + if (ec->features[0] == -1U && ec->features[1] == -1U) { + /* features bitmap not read yet */ + + msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + msg->version = 0; + msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset; + msg->insize = sizeof(ec->features); + msg->outsize = 0; + + ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + if (ret < 0 || msg->result != EC_RES_SUCCESS) { + dev_warn(ec->dev, "cannot get EC features: %d/%d\n", + ret, msg->result); + memset(ec->features, 0, sizeof(ec->features)); + } + + memcpy(ec->features, msg->data, sizeof(ec->features)); + + dev_dbg(ec->dev, "EC features %08x %08x\n", + ec->features[0], ec->features[1]); + + kfree(msg); + } + + return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature); +} + /* Device file ops */ static int ec_device_open(struct inode *inode, struct file *filp) { @@ -245,6 +280,8 @@ static int ec_device_probe(struct platform_device *pdev) ec->ec_dev = dev_get_drvdata(dev->parent); ec->dev = dev; ec->cmd_offset = ec_platform->cmd_offset; + ec->features[0] = -1U; /* Not cached yet */ + ec->features[1] = -1U; /* Not cached yet */ device_initialize(&ec->class_dev); cdev_init(&ec->cdev, &fops); diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index 1f85b7aff097..f62043a75f43 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -184,6 +184,7 @@ struct cros_ec_dev { struct cros_ec_device *ec_dev; struct device *dev; u16 cmd_offset; + u32 features[2]; }; /** diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index 8826e0f64b0e..1683003603f3 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h @@ -713,6 +713,90 @@ struct ec_response_get_set_value { /* More than one command can use these structs to get/set paramters. */ #define EC_CMD_GSV_PAUSE_IN_S5 0x0c +/*****************************************************************************/ +/* List the features supported by the firmware */ +#define EC_CMD_GET_FEATURES 0x0d + +/* Supported features */ +enum ec_feature_code { + /* + * This image contains a limited set of features. Another image + * in RW partition may support more features. + */ + EC_FEATURE_LIMITED = 0, + /* + * Commands for probing/reading/writing/erasing the flash in the + * EC are present. + */ + EC_FEATURE_FLASH = 1, + /* + * Can control the fan speed directly. + */ + EC_FEATURE_PWM_FAN = 2, + /* + * Can control the intensity of the keyboard backlight. + */ + EC_FEATURE_PWM_KEYB = 3, + /* + * Support Google lightbar, introduced on Pixel. + */ + EC_FEATURE_LIGHTBAR = 4, + /* Control of LEDs */ + EC_FEATURE_LED = 5, + /* Exposes an interface to control gyro and sensors. + * The host goes through the EC to access these sensors. + * In addition, the EC may provide composite sensors, like lid angle. + */ + EC_FEATURE_MOTION_SENSE = 6, + /* The keyboard is controlled by the EC */ + EC_FEATURE_KEYB = 7, + /* The AP can use part of the EC flash as persistent storage. */ + EC_FEATURE_PSTORE = 8, + /* The EC monitors BIOS port 80h, and can return POST codes. */ + EC_FEATURE_PORT80 = 9, + /* + * Thermal management: include TMP specific commands. + * Higher level than direct fan control. + */ + EC_FEATURE_THERMAL = 10, + /* Can switch the screen backlight on/off */ + EC_FEATURE_BKLIGHT_SWITCH = 11, + /* Can switch the wifi module on/off */ + EC_FEATURE_WIFI_SWITCH = 12, + /* Monitor host events, through for example SMI or SCI */ + EC_FEATURE_HOST_EVENTS = 13, + /* The EC exposes GPIO commands to control/monitor connected devices. */ + EC_FEATURE_GPIO = 14, + /* The EC can send i2c messages to downstream devices. */ + EC_FEATURE_I2C = 15, + /* Command to control charger are included */ + EC_FEATURE_CHARGER = 16, + /* Simple battery support. */ + EC_FEATURE_BATTERY = 17, + /* + * Support Smart battery protocol + * (Common Smart Battery System Interface Specification) + */ + EC_FEATURE_SMART_BATTERY = 18, + /* EC can dectect when the host hangs. */ + EC_FEATURE_HANG_DETECT = 19, + /* Report power information, for pit only */ + EC_FEATURE_PMU = 20, + /* Another Cros EC device is present downstream of this one */ + EC_FEATURE_SUB_MCU = 21, + /* Support USB Power delivery (PD) commands */ + EC_FEATURE_USB_PD = 22, + /* Control USB multiplexer, for audio through USB port for instance. */ + EC_FEATURE_USB_MUX = 23, + /* Motion Sensor code has an internal software FIFO */ + EC_FEATURE_MOTION_SENSE_FIFO = 24, +}; + +#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32)) +#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32)) +struct ec_response_get_features { + uint32_t flags[2]; +} __packed; /*****************************************************************************/ /* Flash commands */ -- cgit v1.2.3 From 5668bfdd90cd7b330aa25a5ff853b55dc224d13d Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Mon, 1 Aug 2016 11:54:38 +0200 Subject: platform/chrome: cros_ec_dev - Register cros-ec sensors Check whether the ChromeOS Embedded Controller is a sensor hub and in such case issue a command to get the number of sensors and register them all. Signed-off-by: Gwendal Grignou Signed-off-by: Enric Balletbo i Serra Reviewed-by: Guenter Roeck Acked-by: Olof Johansson Signed-off-by: Jonathan Cameron --- .../iio/common/cros_ec_sensors/cros_ec_sensors.c | 4 +- drivers/platform/chrome/cros_ec_dev.c | 122 +++++++++++++++++++++ 2 files changed, 124 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 48edeba35b83..d6c372bb433b 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -51,7 +51,7 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev, s16 data = 0; s64 val64; int i; - int ret = IIO_VAL_INT; + int ret; int idx = chan->scan_index; mutex_lock(&st->core.cmd_lock); @@ -137,7 +137,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, { struct cros_ec_sensors_state *st = iio_priv(indio_dev); int i; - int ret = 0; + int ret; int idx = chan->scan_index; mutex_lock(&st->core.cmd_lock); diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c index 7eb53078b03d..47268ecedc4d 100644 --- a/drivers/platform/chrome/cros_ec_dev.c +++ b/drivers/platform/chrome/cros_ec_dev.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -265,6 +266,123 @@ static void __remove(struct device *dev) kfree(ec); } +static void cros_ec_sensors_register(struct cros_ec_dev *ec) +{ + /* + * Issue a command to get the number of sensor reported. + * Build an array of sensors driver and register them all. + */ + int ret, i, id, sensor_num; + struct mfd_cell *sensor_cells; + struct cros_ec_sensor_platform *sensor_platforms; + int sensor_type[MOTIONSENSE_TYPE_MAX]; + struct ec_params_motion_sense *params; + struct ec_response_motion_sense *resp; + struct cros_ec_command *msg; + + msg = kzalloc(sizeof(struct cros_ec_command) + + max(sizeof(*params), sizeof(*resp)), GFP_KERNEL); + if (msg == NULL) + return; + + msg->version = 2; + msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; + msg->outsize = sizeof(*params); + msg->insize = sizeof(*resp); + + params = (struct ec_params_motion_sense *)msg->data; + params->cmd = MOTIONSENSE_CMD_DUMP; + + ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + if (ret < 0 || msg->result != EC_RES_SUCCESS) { + dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n", + ret, msg->result); + goto error; + } + + resp = (struct ec_response_motion_sense *)msg->data; + sensor_num = resp->dump.sensor_count; + /* Allocate 2 extra sensors in case lid angle or FIFO are needed */ + sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2), + GFP_KERNEL); + if (sensor_cells == NULL) + goto error; + + sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) * + (sensor_num + 1), GFP_KERNEL); + if (sensor_platforms == NULL) + goto error_platforms; + + memset(sensor_type, 0, sizeof(sensor_type)); + id = 0; + for (i = 0; i < sensor_num; i++) { + params->cmd = MOTIONSENSE_CMD_INFO; + params->info.sensor_num = i; + ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + if (ret < 0 || msg->result != EC_RES_SUCCESS) { + dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n", + i, ret, msg->result); + continue; + } + switch (resp->info.type) { + case MOTIONSENSE_TYPE_ACCEL: + sensor_cells[id].name = "cros-ec-accel"; + break; + case MOTIONSENSE_TYPE_GYRO: + sensor_cells[id].name = "cros-ec-gyro"; + break; + case MOTIONSENSE_TYPE_MAG: + sensor_cells[id].name = "cros-ec-mag"; + break; + case MOTIONSENSE_TYPE_PROX: + sensor_cells[id].name = "cros-ec-prox"; + break; + case MOTIONSENSE_TYPE_LIGHT: + sensor_cells[id].name = "cros-ec-light"; + break; + case MOTIONSENSE_TYPE_ACTIVITY: + sensor_cells[id].name = "cros-ec-activity"; + break; + default: + dev_warn(ec->dev, "unknown type %d\n", resp->info.type); + continue; + } + sensor_platforms[id].sensor_num = i; + sensor_cells[id].id = sensor_type[resp->info.type]; + sensor_cells[id].platform_data = &sensor_platforms[id]; + sensor_cells[id].pdata_size = + sizeof(struct cros_ec_sensor_platform); + + sensor_type[resp->info.type]++; + id++; + } + if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) { + sensor_platforms[id].sensor_num = sensor_num; + + sensor_cells[id].name = "cros-ec-angle"; + sensor_cells[id].id = 0; + sensor_cells[id].platform_data = &sensor_platforms[id]; + sensor_cells[id].pdata_size = + sizeof(struct cros_ec_sensor_platform); + id++; + } + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { + sensor_cells[id].name = "cros-ec-ring"; + id++; + } + + ret = mfd_add_devices(ec->dev, 0, sensor_cells, id, + NULL, 0, NULL); + if (ret) + dev_err(ec->dev, "failed to add EC sensors\n"); + + kfree(sensor_platforms); +error_platforms: + kfree(sensor_cells); +error: + kfree(msg); +} + static int ec_device_probe(struct platform_device *pdev) { int retval = -ENOMEM; @@ -319,6 +437,10 @@ static int ec_device_probe(struct platform_device *pdev) goto dev_reg_failed; } + /* check whether this EC is a sensor hub. */ + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) + cros_ec_sensors_register(ec); + return 0; dev_reg_failed: -- cgit v1.2.3 From 366f4aea649a65c3735d91b4409d84c771811290 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 25 Oct 2016 13:53:27 +0200 Subject: brd: Switch rd_size to unsigned long Currently rd_size was int which lead to overflow and bogus device size once the requested ramdisk size was 1 TB or more. Although these days ramdisks with 1 TB size are mostly a mistake, the days when they are useful are not far. Reported-by: Bart Van Assche Signed-off-by: Jan Kara Signed-off-by: Jens Axboe --- drivers/block/brd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 0c76d4016eeb..9d5335857191 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -443,8 +443,8 @@ static int rd_nr = CONFIG_BLK_DEV_RAM_COUNT; module_param(rd_nr, int, S_IRUGO); MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices"); -int rd_size = CONFIG_BLK_DEV_RAM_SIZE; -module_param(rd_size, int, S_IRUGO); +unsigned long rd_size = CONFIG_BLK_DEV_RAM_SIZE; +module_param(rd_size, ulong, S_IRUGO); MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes."); static int max_part = 1; -- cgit v1.2.3 From ff26956875c2f05e12ecec9938411a2c7dfc767d Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 25 Oct 2016 08:46:23 -0600 Subject: brd: remove support for BLKFLSBUF Discontinue having the brd driver destructively free all pages in the ramdisk in response to the BLKFLSBUF ioctl. Doing so allows a BLKFLSBUF ioctl issued to a logical partition to destroy pages of the parent brd device (and all other partitions of that brd device). This change breaks compatibility - but in this case the compatibility breaks more than it helps. Reported-by: Mikulas Patocka Suggested-by: Christoph Hellwig Signed-off-by: Mike Snitzer Signed-off-by: Jens Axboe --- drivers/block/brd.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'drivers') diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 9d5335857191..ad793f35632c 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -395,44 +395,9 @@ static long brd_direct_access(struct block_device *bdev, sector_t sector, #define brd_direct_access NULL #endif -static int brd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - int error; - struct brd_device *brd = bdev->bd_disk->private_data; - - if (cmd != BLKFLSBUF) - return -ENOTTY; - - /* - * ram device BLKFLSBUF has special semantics, we want to actually - * release and destroy the ramdisk data. - */ - mutex_lock(&brd_mutex); - mutex_lock(&bdev->bd_mutex); - error = -EBUSY; - if (bdev->bd_openers <= 1) { - /* - * Kill the cache first, so it isn't written back to the - * device. - * - * Another thread might instantiate more buffercache here, - * but there is not much we can do to close that race. - */ - kill_bdev(bdev); - brd_free_pages(brd); - error = 0; - } - mutex_unlock(&bdev->bd_mutex); - mutex_unlock(&brd_mutex); - - return error; -} - static const struct block_device_operations brd_fops = { .owner = THIS_MODULE, .rw_page = brd_rw_page, - .ioctl = brd_ioctl, .direct_access = brd_direct_access, }; -- cgit v1.2.3 From 5a195c6d4ecf43be26ee1c8be6140025832adfd2 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Tue, 25 Oct 2016 11:31:23 -0500 Subject: gpio: gpiolib-devprop: Check chip->parent pointer before dereferencing Confirm the chip->parent is valid before dereferencing because the parent parameter is optional. Signed-off-by: Thor Thayer Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-devprop.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib-devprop.c b/drivers/gpio/gpiolib-devprop.c index 17bfc41692ef..27f383bda7d9 100644 --- a/drivers/gpio/gpiolib-devprop.c +++ b/drivers/gpio/gpiolib-devprop.c @@ -31,6 +31,11 @@ void devprop_gpiochip_set_names(struct gpio_chip *chip) const char **names; int ret, i; + if (!chip->parent) { + dev_warn(&gdev->dev, "GPIO chip parent is NULL\n"); + return; + } + ret = device_property_read_string_array(chip->parent, "gpio-line-names", NULL, 0); if (ret < 0) -- cgit v1.2.3 From 1d160f430301d033053fc3a5237324d17552390b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 29 Sep 2016 23:30:21 -0400 Subject: drm/amdgpu/dce6: add dce_v6_0_disable_dce Needed for virtual dce support Reviewed-By: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 50 ++++++++++++++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/dce_v6_0.h | 2 ++ 2 files changed, 48 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index b948d6cb1399..e6a7687dec21 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -611,12 +611,55 @@ static void dce_v6_0_resume_mc_access(struct amdgpu_device *adev, static void dce_v6_0_set_vga_render_state(struct amdgpu_device *adev, bool render) { - if (!render) + if (!render) WREG32(R_000300_VGA_RENDER_CONTROL, RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL); } +static int dce_v6_0_get_num_crtc(struct amdgpu_device *adev) +{ + int num_crtc = 0; + + switch (adev->asic_type) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + num_crtc = 6; + break; + case CHIP_OLAND: + num_crtc = 2; + break; + default: + num_crtc = 0; + } + return num_crtc; +} + +void dce_v6_0_disable_dce(struct amdgpu_device *adev) +{ + /*Disable VGA render and enabled crtc, if has DCE engine*/ + if (amdgpu_atombios_has_dce_engine_info(adev)) { + u32 tmp; + int crtc_enabled, i; + + dce_v6_0_set_vga_render_state(adev, false); + + /*Disable crtc*/ + for (i = 0; i < dce_v6_0_get_num_crtc(adev); i++) { + crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & + EVERGREEN_CRTC_MASTER_EN; + if (crtc_enabled) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + tmp &= ~EVERGREEN_CRTC_MASTER_EN; + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + } + } +} + static void dce_v6_0_program_fmt(struct drm_encoder *encoder) { @@ -2338,21 +2381,20 @@ static int dce_v6_0_early_init(void *handle) dce_v6_0_set_display_funcs(adev); dce_v6_0_set_irq_funcs(adev); + adev->mode_info.num_crtc = dce_v6_0_get_num_crtc(adev); + switch (adev->asic_type) { case CHIP_TAHITI: case CHIP_PITCAIRN: case CHIP_VERDE: - adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; break; case CHIP_OLAND: - adev->mode_info.num_crtc = 2; adev->mode_info.num_hpd = 2; adev->mode_info.num_dig = 2; break; default: - /* FIXME: not supported yet */ return -EINVAL; } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h index 6a5528105bb6..4c6cd18e9053 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h @@ -26,4 +26,6 @@ extern const struct amd_ip_funcs dce_v6_0_ip_funcs; +void dce_v6_0_disable_dce(struct amdgpu_device *adev); + #endif -- cgit v1.2.3 From a1d37046d4ff26c563fa509c28287278bc5ec80c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 29 Sep 2016 23:36:12 -0400 Subject: drm/amdgpu/virtual_dce: add dce6 support disable the real dce hw if the asic supports dce. Reviewed-By: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index c2bd9f045532..4da46bed971a 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -27,6 +27,9 @@ #include "atom.h" #include "amdgpu_pll.h" #include "amdgpu_connectors.h" +#ifdef CONFIG_DRM_AMDGPU_SI +#include "dce_v6_0.h" +#endif #ifdef CONFIG_DRM_AMDGPU_CIK #include "dce_v8_0.h" #endif @@ -99,6 +102,14 @@ static void dce_virtual_stop_mc_access(struct amdgpu_device *adev, struct amdgpu_mode_mc_save *save) { switch (adev->asic_type) { +#ifdef CONFIG_DRM_AMDGPU_SI + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: + dce_v6_0_disable_dce(adev); + break; +#endif #ifdef CONFIG_DRM_AMDGPU_CIK case CHIP_BONAIRE: case CHIP_HAWAII: @@ -119,6 +130,9 @@ static void dce_virtual_stop_mc_access(struct amdgpu_device *adev, dce_v11_0_disable_dce(adev); break; case CHIP_TOPAZ: +#ifdef CONFIG_DRM_AMDGPU_SI + case CHIP_HAINAN: +#endif /* no DCE */ return; default: -- cgit v1.2.3 From 425f6d603371d1592830f27cc9779181a7146d6b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 29 Sep 2016 23:19:25 -0400 Subject: drm/amdgpu/virtual_dce: drop empty function No need to ack non-existent interrupts. Reviewed-By: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 4da46bed971a..f71a1f0dd487 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -707,15 +707,6 @@ static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev, return 0; } -static void dce_virtual_crtc_vblank_int_ack(struct amdgpu_device *adev, - int crtc) -{ - if (crtc >= adev->mode_info.num_crtc) { - DRM_DEBUG("invalid crtc %d\n", crtc); - return; - } -} - static int dce_virtual_crtc_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) @@ -723,8 +714,6 @@ static int dce_virtual_crtc_irq(struct amdgpu_device *adev, unsigned crtc = 0; unsigned irq_type = AMDGPU_CRTC_IRQ_VBLANK1; - dce_virtual_crtc_vblank_int_ack(adev, crtc); - if (amdgpu_irq_enabled(adev, source, irq_type)) { drm_handle_vblank(adev->ddev, crtc); } -- cgit v1.2.3 From 82b9f817607060770a92900bd1e708028b7f2a2e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Sep 2016 11:19:41 -0400 Subject: drm/amdgpu/virtual_dce: drop pageflip_irq funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Never used. Reviewed-By: Emily Deng Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 35 ++++++-------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index f71a1f0dd487..23a842fd8376 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -209,10 +209,9 @@ static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode) switch (mode) { case DRM_MODE_DPMS_ON: amdgpu_crtc->enabled = true; - /* Make sure VBLANK and PFLIP interrupts are still enabled */ + /* Make sure VBLANK interrupts are still enabled */ type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); amdgpu_irq_update(adev, &adev->crtc_irq, type); - amdgpu_irq_update(adev, &adev->pageflip_irq, type); drm_vblank_on(dev, amdgpu_crtc->crtc_id); break; case DRM_MODE_DPMS_STANDBY: @@ -668,8 +667,8 @@ static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vbla } static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev, - int crtc, - enum amdgpu_interrupt_state state) + int crtc, + enum amdgpu_interrupt_state state) { if (crtc >= adev->mode_info.num_crtc) { DRM_DEBUG("invalid crtc %d\n", crtc); @@ -693,9 +692,9 @@ static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *ad static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned type, - enum amdgpu_interrupt_state state) + struct amdgpu_irq_src *source, + unsigned type, + enum amdgpu_interrupt_state state) { switch (type) { case AMDGPU_CRTC_IRQ_VBLANK1: @@ -722,20 +721,6 @@ static int dce_virtual_crtc_irq(struct amdgpu_device *adev, return 0; } -static int dce_virtual_set_pageflip_irq_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *src, - unsigned type, - enum amdgpu_interrupt_state state) -{ - if (type >= adev->mode_info.num_crtc) { - DRM_ERROR("invalid pageflip crtc %d\n", type); - return -EINVAL; - } - DRM_DEBUG("[FM]set pageflip irq type %d state %d\n", type, state); - - return 0; -} - static int dce_virtual_pageflip_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) @@ -789,17 +774,9 @@ static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = { .process = dce_virtual_crtc_irq, }; -static const struct amdgpu_irq_src_funcs dce_virtual_pageflip_irq_funcs = { - .set = dce_virtual_set_pageflip_irq_state, - .process = dce_virtual_pageflip_irq, -}; - static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev) { adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST; adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs; - - adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST; - adev->pageflip_irq.funcs = &dce_virtual_pageflip_irq_funcs; } -- cgit v1.2.3 From bf2335a54e191ab68d10d61490f8cbbd47585790 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Sep 2016 11:23:30 -0400 Subject: drm/amdgpu/virtual_dce: no need to an irq process callback Virtual crtcs interrupts do not show up in the IV ring, so it will never be called. Reviewed-By: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 23a842fd8376..0771d6df7186 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -706,21 +706,6 @@ static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev, return 0; } -static int dce_virtual_crtc_irq(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) -{ - unsigned crtc = 0; - unsigned irq_type = AMDGPU_CRTC_IRQ_VBLANK1; - - if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); - } - dce_virtual_pageflip_irq(adev, NULL, NULL); - DRM_DEBUG("IH: D%d vblank\n", crtc + 1); - return 0; -} - static int dce_virtual_pageflip_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) @@ -771,7 +756,7 @@ static int dce_virtual_pageflip_irq(struct amdgpu_device *adev, static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = { .set = dce_virtual_set_crtc_irq_state, - .process = dce_virtual_crtc_irq, + .process = NULL, }; static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev) -- cgit v1.2.3 From 9405e47dbab33706c43caba72cf8d83b5746f843 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Sep 2016 11:41:37 -0400 Subject: drm/amdgpu/virtual_dce: clean up interrupt handling We handle the virtual interrupts from a timer so no need to try an look like we are handling IV ring events. Reviewed-By: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 109 +++++++++++++++---------------- 1 file changed, 54 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 0771d6df7186..bc8f5e332915 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -39,9 +39,6 @@ static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); -static int dce_virtual_pageflip_irq(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry); /** * dce_virtual_vblank_wait - vblank wait asic callback. @@ -655,14 +652,64 @@ static void dce_virtual_set_display_funcs(struct amdgpu_device *adev) adev->mode_info.funcs = &dce_virtual_display_funcs; } +static int dce_virtual_pageflip(struct amdgpu_device *adev, + unsigned crtc_id) +{ + unsigned long flags; + struct amdgpu_crtc *amdgpu_crtc; + struct amdgpu_flip_work *works; + + amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; + + if (crtc_id >= adev->mode_info.num_crtc) { + DRM_ERROR("invalid pageflip crtc %d\n", crtc_id); + return -EINVAL; + } + + /* IRQ could occur when in initial stage */ + if (amdgpu_crtc == NULL) + return 0; + + spin_lock_irqsave(&adev->ddev->event_lock, flags); + works = amdgpu_crtc->pflip_works; + if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { + DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " + "AMDGPU_FLIP_SUBMITTED(%d)\n", + amdgpu_crtc->pflip_status, + AMDGPU_FLIP_SUBMITTED); + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + return 0; + } + + /* page flip completed. clean up */ + amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; + amdgpu_crtc->pflip_works = NULL; + + /* wakeup usersapce */ + if (works->event) + drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); + + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + + drm_crtc_vblank_put(&amdgpu_crtc->base); + schedule_work(&works->unpin_work); + + return 0; +} + static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer) { - struct amdgpu_mode_info *mode_info = container_of(vblank_timer, struct amdgpu_mode_info ,vblank_timer); - struct amdgpu_device *adev = container_of(mode_info, struct amdgpu_device ,mode_info); + struct amdgpu_mode_info *mode_info = + container_of(vblank_timer, struct amdgpu_mode_info , vblank_timer); + struct amdgpu_device *adev = + container_of(mode_info, struct amdgpu_device , mode_info); unsigned crtc = 0; + drm_handle_vblank(adev->ddev, crtc); - dce_virtual_pageflip_irq(adev, NULL, NULL); - hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL); + dce_virtual_pageflip(adev, crtc); + hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), + HRTIMER_MODE_REL); + return HRTIMER_NORESTART; } @@ -706,54 +753,6 @@ static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev, return 0; } -static int dce_virtual_pageflip_irq(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) -{ - unsigned long flags; - unsigned crtc_id = 0; - struct amdgpu_crtc *amdgpu_crtc; - struct amdgpu_flip_work *works; - - crtc_id = 0; - amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; - - if (crtc_id >= adev->mode_info.num_crtc) { - DRM_ERROR("invalid pageflip crtc %d\n", crtc_id); - return -EINVAL; - } - - /* IRQ could occur when in initial stage */ - if (amdgpu_crtc == NULL) - return 0; - - spin_lock_irqsave(&adev->ddev->event_lock, flags); - works = amdgpu_crtc->pflip_works; - if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { - DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " - "AMDGPU_FLIP_SUBMITTED(%d)\n", - amdgpu_crtc->pflip_status, - AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - return 0; - } - - /* page flip completed. clean up */ - amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; - amdgpu_crtc->pflip_works = NULL; - - /* wakeup usersapce */ - if (works->event) - drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - - drm_crtc_vblank_put(&amdgpu_crtc->base); - schedule_work(&works->unpin_work); - - return 0; -} - static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = { .set = dce_virtual_set_crtc_irq_state, .process = NULL, -- cgit v1.2.3 From 66264ba80492571d9177158f2989e267a591507b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Sep 2016 12:37:36 -0400 Subject: drm/amdgpu: simplify encoder and connector setup (v2) No need to emulate all of the stuff for real hw. v2: warning fix Reviewed-By: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 93 ---------- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 231 +++++++++++++++---------- 2 files changed, 144 insertions(+), 180 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index e3281d4e3e41..3af8ffb45b64 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -1517,88 +1517,6 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = { .force = amdgpu_connector_dvi_force, }; -static struct drm_encoder * -amdgpu_connector_virtual_encoder(struct drm_connector *connector) -{ - int enc_id = connector->encoder_ids[0]; - struct drm_encoder *encoder; - int i; - for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - if (connector->encoder_ids[i] == 0) - break; - - encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); - if (!encoder) - continue; - - if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) - return encoder; - } - - /* pick the first one */ - if (enc_id) - return drm_encoder_find(connector->dev, enc_id); - return NULL; -} - -static int amdgpu_connector_virtual_get_modes(struct drm_connector *connector) -{ - struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector); - - if (encoder) { - amdgpu_connector_add_common_modes(encoder, connector); - } - - return 0; -} - -static int amdgpu_connector_virtual_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - return MODE_OK; -} - -static int -amdgpu_connector_virtual_dpms(struct drm_connector *connector, int mode) -{ - return 0; -} - -static enum drm_connector_status - -amdgpu_connector_virtual_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - -static int -amdgpu_connector_virtual_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t val) -{ - return 0; -} - -static void amdgpu_connector_virtual_force(struct drm_connector *connector) -{ - return; -} - -static const struct drm_connector_helper_funcs amdgpu_connector_virtual_helper_funcs = { - .get_modes = amdgpu_connector_virtual_get_modes, - .mode_valid = amdgpu_connector_virtual_mode_valid, - .best_encoder = amdgpu_connector_virtual_encoder, -}; - -static const struct drm_connector_funcs amdgpu_connector_virtual_funcs = { - .dpms = amdgpu_connector_virtual_dpms, - .detect = amdgpu_connector_virtual_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .set_property = amdgpu_connector_virtual_set_property, - .destroy = amdgpu_connector_destroy, - .force = amdgpu_connector_virtual_force, -}; - void amdgpu_connector_add(struct amdgpu_device *adev, uint32_t connector_id, @@ -1983,17 +1901,6 @@ amdgpu_connector_add(struct amdgpu_device *adev, connector->interlace_allowed = false; connector->doublescan_allowed = false; break; - case DRM_MODE_CONNECTOR_VIRTUAL: - amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL); - if (!amdgpu_dig_connector) - goto failed; - amdgpu_connector->con_priv = amdgpu_dig_connector; - drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_virtual_funcs, connector_type); - drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_virtual_helper_funcs); - subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - break; } } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index bc8f5e332915..b981e769603b 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -39,6 +39,8 @@ static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); +static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, + int index); /** * dce_virtual_vblank_wait - vblank wait asic callback. @@ -274,24 +276,6 @@ static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct drm_encoder *encoder; - - /* assign the encoder to the amdgpu crtc to avoid repeated lookups later */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->crtc == crtc) { - amdgpu_crtc->encoder = encoder; - amdgpu_crtc->connector = amdgpu_get_connector_for_encoder(encoder); - break; - } - } - if ((amdgpu_crtc->encoder == NULL) || (amdgpu_crtc->connector == NULL)) { - amdgpu_crtc->encoder = NULL; - amdgpu_crtc->connector = NULL; - return false; - } - return true; } @@ -370,38 +354,120 @@ static int dce_virtual_early_init(void *handle) return 0; } -static bool dce_virtual_get_connector_info(struct amdgpu_device *adev) +static struct drm_encoder * +dce_virtual_encoder(struct drm_connector *connector) { - struct amdgpu_i2c_bus_rec ddc_bus; - struct amdgpu_router router; - struct amdgpu_hpd hpd; + int enc_id = connector->encoder_ids[0]; + struct drm_encoder *encoder; + int i; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); + if (!encoder) + continue; - /* look up gpio for ddc, hpd */ - ddc_bus.valid = false; - hpd.hpd = AMDGPU_HPD_NONE; - /* needed for aux chan transactions */ - ddc_bus.hpd = hpd.hpd; + if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) + return encoder; + } - memset(&router, 0, sizeof(router)); - router.ddc_valid = false; - router.cd_valid = false; - amdgpu_display_add_connector(adev, - 0, - ATOM_DEVICE_CRT1_SUPPORT, - DRM_MODE_CONNECTOR_VIRTUAL, &ddc_bus, - CONNECTOR_OBJECT_ID_VIRTUAL, - &hpd, - &router); + /* pick the first one */ + if (enc_id) + return drm_encoder_find(connector->dev, enc_id); + return NULL; +} + +static int dce_virtual_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode = NULL; + unsigned i; + static const struct mode_size { + int w; + int h; + } common_modes[17] = { + { 640, 480}, + { 720, 480}, + { 800, 600}, + { 848, 480}, + {1024, 768}, + {1152, 768}, + {1280, 720}, + {1280, 800}, + {1280, 854}, + {1280, 960}, + {1280, 1024}, + {1440, 900}, + {1400, 1050}, + {1680, 1050}, + {1600, 1200}, + {1920, 1080}, + {1920, 1200} + }; + + for (i = 0; i < 17; i++) { + mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); + drm_mode_probed_add(connector, mode); + } - amdgpu_display_add_encoder(adev, ENCODER_VIRTUAL_ENUM_VIRTUAL, - ATOM_DEVICE_CRT1_SUPPORT, - 0); + return 0; +} - amdgpu_link_encoder_connector(adev->ddev); +static int dce_virtual_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + return MODE_OK; +} - return true; +static int +dce_virtual_dpms(struct drm_connector *connector, int mode) +{ + return 0; } +static enum drm_connector_status +dce_virtual_detect(struct drm_connector *connector, bool force) +{ + return connector_status_connected; +} + +static int +dce_virtual_set_property(struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + return 0; +} + +static void dce_virtual_destroy(struct drm_connector *connector) +{ + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +static void dce_virtual_force(struct drm_connector *connector) +{ + return; +} + +static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = { + .get_modes = dce_virtual_get_modes, + .mode_valid = dce_virtual_mode_valid, + .best_encoder = dce_virtual_encoder, +}; + +static const struct drm_connector_funcs dce_virtual_connector_funcs = { + .dpms = dce_virtual_dpms, + .detect = dce_virtual_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = dce_virtual_set_property, + .destroy = dce_virtual_destroy, + .force = dce_virtual_force, +}; + static int dce_virtual_sw_init(void *handle) { int r, i; @@ -430,16 +496,16 @@ static int dce_virtual_sw_init(void *handle) adev->ddev->mode_config.max_width = 16384; adev->ddev->mode_config.max_height = 16384; - /* allocate crtcs */ + /* allocate crtcs, encoders, connectors */ for (i = 0; i < adev->mode_info.num_crtc; i++) { r = dce_virtual_crtc_init(adev, i); if (r) return r; + r = dce_virtual_connector_encoder_init(adev, i); + if (r) + return r; } - dce_virtual_get_connector_info(adev); - amdgpu_print_display_setup(adev->ddev); - drm_kms_helper_poll_init(adev->ddev); adev->mode_info.mode_config_initialized = true; @@ -536,8 +602,8 @@ static void dce_virtual_encoder_commit(struct drm_encoder *encoder) static void dce_virtual_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return; } @@ -557,10 +623,6 @@ static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - - /* set the active encoder to connector routing */ - amdgpu_encoder_set_active_device(encoder); - return true; } @@ -586,45 +648,40 @@ static const struct drm_encoder_funcs dce_virtual_encoder_funcs = { .destroy = dce_virtual_encoder_destroy, }; -static void dce_virtual_encoder_add(struct amdgpu_device *adev, - uint32_t encoder_enum, - uint32_t supported_device, - u16 caps) +static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, + int index) { - struct drm_device *dev = adev->ddev; struct drm_encoder *encoder; - struct amdgpu_encoder *amdgpu_encoder; - - /* see if we already added it */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - amdgpu_encoder = to_amdgpu_encoder(encoder); - if (amdgpu_encoder->encoder_enum == encoder_enum) { - amdgpu_encoder->devices |= supported_device; - return; - } + struct drm_connector *connector; + /* add a new encoder */ + encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL); + if (!encoder) + return -ENOMEM; + encoder->possible_crtcs = 1 << index; + drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs, + DRM_MODE_ENCODER_VIRTUAL, NULL); + drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); + + connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL); + if (!connector) { + kfree(encoder); + return -ENOMEM; } - /* add a new one */ - amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL); - if (!amdgpu_encoder) - return; + /* add a new connector */ + drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL); + drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs); + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + drm_connector_register(connector); - encoder = &amdgpu_encoder->base; - encoder->possible_crtcs = 0x1; - amdgpu_encoder->enc_priv = NULL; - amdgpu_encoder->encoder_enum = encoder_enum; - amdgpu_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; - amdgpu_encoder->devices = supported_device; - amdgpu_encoder->rmx_type = RMX_OFF; - amdgpu_encoder->underscan_type = UNDERSCAN_OFF; - amdgpu_encoder->is_ext_encoder = false; - amdgpu_encoder->caps = caps; - - drm_encoder_init(dev, encoder, &dce_virtual_encoder_funcs, - DRM_MODE_ENCODER_VIRTUAL, NULL); - drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); - DRM_INFO("[FM]encoder: %d is VIRTUAL\n", amdgpu_encoder->encoder_id); + /* link them */ + drm_mode_connector_attach_encoder(connector, encoder); + + return 0; } static const struct amdgpu_display_funcs dce_virtual_display_funcs = { @@ -640,8 +697,8 @@ static const struct amdgpu_display_funcs dce_virtual_display_funcs = { .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg, .page_flip = &dce_virtual_page_flip, .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos, - .add_encoder = &dce_virtual_encoder_add, - .add_connector = &amdgpu_connector_add, + .add_encoder = NULL, + .add_connector = NULL, .stop_mc_access = &dce_virtual_stop_mc_access, .resume_mc_access = &dce_virtual_resume_mc_access, }; -- cgit v1.2.3 From 87320cafbcbe177a08c9928395e760b48c8f917e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Sep 2016 12:38:20 -0400 Subject: Revert "drm/amdgpu: Add virtual connector and encoder macros." This reverts commit 16925c92dbd97524655525b6816625e1f0063d12. This is no longer necessary. Reviewed-By: Emily Deng --- drivers/gpu/drm/amd/amdgpu/ObjectID.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/ObjectID.h b/drivers/gpu/drm/amd/amdgpu/ObjectID.h index b8d66670bb17..06192698bd96 100644 --- a/drivers/gpu/drm/amd/amdgpu/ObjectID.h +++ b/drivers/gpu/drm/amd/amdgpu/ObjectID.h @@ -90,7 +90,6 @@ #define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24 #define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 0x25 #define ENCODER_OBJECT_ID_INTERNAL_AMCLK 0x27 -#define ENCODER_OBJECT_ID_VIRTUAL 0x28 #define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF @@ -120,7 +119,6 @@ #define CONNECTOR_OBJECT_ID_eDP 0x14 #define CONNECTOR_OBJECT_ID_MXM 0x15 #define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16 -#define CONNECTOR_OBJECT_ID_VIRTUAL 0x17 /* deleted */ @@ -149,7 +147,6 @@ #define GRAPH_OBJECT_ENUM_ID5 0x05 #define GRAPH_OBJECT_ENUM_ID6 0x06 #define GRAPH_OBJECT_ENUM_ID7 0x07 -#define GRAPH_OBJECT_ENUM_VIRTUAL 0x08 /****************************************************/ /* Graphics Object ID Bit definition */ @@ -411,10 +408,6 @@ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT) -#define ENCODER_VIRTUAL_ENUM_VIRTUAL ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_VIRTUAL << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_VIRTUAL << OBJECT_ID_SHIFT) - /****************************************************/ /* Connector Object ID definition - Shared with BIOS */ /****************************************************/ -- cgit v1.2.3 From 483ef98588aa9f2236392f505beadb621f288861 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Sep 2016 12:43:04 -0400 Subject: drm/amdgpu: rename amdgpu_whether_enable_virtual_display to match the other functions in that file. Reviewed-By: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b4f4a9239069..874c33b43955 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1231,7 +1231,7 @@ int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev, return 1; } -static void amdgpu_whether_enable_virtual_display(struct amdgpu_device *adev) +static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev) { adev->enable_virtual_display = false; @@ -1261,7 +1261,7 @@ static int amdgpu_early_init(struct amdgpu_device *adev) { int i, r; - amdgpu_whether_enable_virtual_display(adev); + amdgpu_device_enable_virtual_display(adev); switch (adev->asic_type) { case CHIP_TOPAZ: -- cgit v1.2.3 From 0f66356d24c6950bf6b1a47df7c77ca57305074d Mon Sep 17 00:00:00 2001 From: Emily Deng Date: Fri, 30 Sep 2016 13:02:18 -0400 Subject: drm/amd/amdgpu: For virtual display, enable multi crtcs. (v3) Enable multi crtcs for virtual display, user can set the number of crtcs by amdgpu module parameter virtual_display. v2: make timers per crtc v3: agd: simplify implementation Signed-off-by: Emily Deng Reviewed-By: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 28 +++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 5 ++-- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 48 +++++++++++++++--------------- 4 files changed, 52 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 874c33b43955..22d331947aca 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1238,20 +1238,38 @@ static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev) if (amdgpu_virtual_display) { struct drm_device *ddev = adev->ddev; const char *pci_address_name = pci_name(ddev->pdev); - char *pciaddstr, *pciaddstr_tmp, *pciaddname; + char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, *pciaddname; pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL); pciaddstr_tmp = pciaddstr; - while ((pciaddname = strsep(&pciaddstr_tmp, ";"))) { + while ((pciaddname_tmp = strsep(&pciaddstr_tmp, ";"))) { + pciaddname = strsep(&pciaddname_tmp, ","); if (!strcmp(pci_address_name, pciaddname)) { + long num_crtc; + int res = -1; + adev->enable_virtual_display = true; + + if (pciaddname_tmp) + res = kstrtol(pciaddname_tmp, 10, + &num_crtc); + + if (!res) { + if (num_crtc < 1) + num_crtc = 1; + if (num_crtc > 6) + num_crtc = 6; + adev->mode_info.num_crtc = num_crtc; + } else { + adev->mode_info.num_crtc = 1; + } break; } } - DRM_INFO("virtual display string:%s, %s:virtual_display:%d\n", - amdgpu_virtual_display, pci_address_name, - adev->enable_virtual_display); + DRM_INFO("virtual display string:%s, %s:virtual_display:%d, num_crtc:%d\n", + amdgpu_virtual_display, pci_address_name, + adev->enable_virtual_display, adev->mode_info.num_crtc); kfree(pciaddstr); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 71ed27eb3dde..2201f05ecc94 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -201,7 +201,8 @@ module_param_named(pg_mask, amdgpu_pg_mask, uint, 0444); MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)"); module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444); -MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x;xxxx:xx:xx.x)"); +MODULE_PARM_DESC(virtual_display, + "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x,x;xxxx:xx:xx.x,x)"); module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444); static const struct pci_device_id pciidlist[] = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 7b0eff7d060b..1e23334b07fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -341,8 +341,6 @@ struct amdgpu_mode_info { int num_dig; /* number of dig blocks */ int disp_priority; const struct amdgpu_display_funcs *funcs; - struct hrtimer vblank_timer; - enum amdgpu_interrupt_state vsync_timer_enabled; }; #define AMDGPU_MAX_BL_LEVEL 0xFF @@ -413,6 +411,9 @@ struct amdgpu_crtc { u32 wm_high; u32 lb_vblank_lead_lines; struct drm_display_mode hw_mode; + /* for virtual dce */ + struct hrtimer vblank_timer; + enum amdgpu_interrupt_state vsync_timer_enabled; }; struct amdgpu_encoder_atom_dig { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index b981e769603b..226b914aa315 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -335,6 +335,7 @@ static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; amdgpu_crtc->encoder = NULL; amdgpu_crtc->connector = NULL; + amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs); return 0; @@ -344,11 +345,9 @@ static int dce_virtual_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - adev->mode_info.vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; dce_virtual_set_display_funcs(adev); dce_virtual_set_irq_funcs(adev); - adev->mode_info.num_crtc = 1; adev->mode_info.num_hpd = 1; adev->mode_info.num_dig = 1; return 0; @@ -756,14 +755,13 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev, static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer) { - struct amdgpu_mode_info *mode_info = - container_of(vblank_timer, struct amdgpu_mode_info , vblank_timer); - struct amdgpu_device *adev = - container_of(mode_info, struct amdgpu_device , mode_info); - unsigned crtc = 0; + struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer, + struct amdgpu_crtc, vblank_timer); + struct drm_device *ddev = amdgpu_crtc->base.dev; + struct amdgpu_device *adev = ddev->dev_private; - drm_handle_vblank(adev->ddev, crtc); - dce_virtual_pageflip(adev, crtc); + drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); + dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL); @@ -779,18 +777,22 @@ static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *ad return; } - if (state && !adev->mode_info.vsync_timer_enabled) { + if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { DRM_DEBUG("Enable software vsync timer\n"); - hrtimer_init(&adev->mode_info.vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - hrtimer_set_expires(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD)); - adev->mode_info.vblank_timer.function = dce_virtual_vblank_timer_handle; - hrtimer_start(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL); - } else if (!state && adev->mode_info.vsync_timer_enabled) { + hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer, + ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD)); + adev->mode_info.crtcs[crtc]->vblank_timer.function = + dce_virtual_vblank_timer_handle; + hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer, + ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL); + } else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { DRM_DEBUG("Disable software vsync timer\n"); - hrtimer_cancel(&adev->mode_info.vblank_timer); + hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer); } - adev->mode_info.vsync_timer_enabled = state; + adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state; DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state); } @@ -800,13 +802,11 @@ static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev, unsigned type, enum amdgpu_interrupt_state state) { - switch (type) { - case AMDGPU_CRTC_IRQ_VBLANK1: - dce_virtual_set_crtc_vblank_interrupt_state(adev, 0, state); - break; - default: - break; - } + if (type > AMDGPU_CRTC_IRQ_VBLANK6) + return -EINVAL; + + dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state); + return 0; } -- cgit v1.2.3 From 2285b91cd2d995acc8c62028c7bd4ae5f939b1ea Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Sep 2016 12:59:11 -0400 Subject: drm/amdgpu/dce8: simplify hpd code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use an address offset like other dce code. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cikd.h | 8 ++ drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 236 +++++++--------------------------- 2 files changed, 54 insertions(+), 190 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/cikd.h b/drivers/gpu/drm/amd/amdgpu/cikd.h index 8659852aea9e..6cbd913fd12e 100644 --- a/drivers/gpu/drm/amd/amdgpu/cikd.h +++ b/drivers/gpu/drm/amd/amdgpu/cikd.h @@ -43,6 +43,14 @@ #define CRTC4_REGISTER_OFFSET (0x477c - 0x1b7c) #define CRTC5_REGISTER_OFFSET (0x4a7c - 0x1b7c) +/* hpd instance offsets */ +#define HPD0_REGISTER_OFFSET (0x1807 - 0x1807) +#define HPD1_REGISTER_OFFSET (0x180a - 0x1807) +#define HPD2_REGISTER_OFFSET (0x180d - 0x1807) +#define HPD3_REGISTER_OFFSET (0x1810 - 0x1807) +#define HPD4_REGISTER_OFFSET (0x1813 - 0x1807) +#define HPD5_REGISTER_OFFSET (0x1816 - 0x1807) + #define BONAIRE_GB_ADDR_CONFIG_GOLDEN 0x12010001 #define HAWAII_GB_ADDR_CONFIG_GOLDEN 0x12011003 diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 5966166ec94c..d0034e4645b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -56,6 +56,16 @@ static const u32 crtc_offsets[6] = CRTC5_REGISTER_OFFSET }; +static const u32 hpd_offsets[] = +{ + HPD0_REGISTER_OFFSET, + HPD1_REGISTER_OFFSET, + HPD2_REGISTER_OFFSET, + HPD3_REGISTER_OFFSET, + HPD4_REGISTER_OFFSET, + HPD5_REGISTER_OFFSET +}; + static const uint32_t dig_offsets[] = { CRTC0_REGISTER_OFFSET, CRTC1_REGISTER_OFFSET, @@ -104,15 +114,6 @@ static const struct { .hpd = DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK } }; -static const uint32_t hpd_int_control_offsets[6] = { - mmDC_HPD1_INT_CONTROL, - mmDC_HPD2_INT_CONTROL, - mmDC_HPD3_INT_CONTROL, - mmDC_HPD4_INT_CONTROL, - mmDC_HPD5_INT_CONTROL, - mmDC_HPD6_INT_CONTROL, -}; - static u32 dce_v8_0_audio_endpt_rreg(struct amdgpu_device *adev, u32 block_offset, u32 reg) { @@ -278,34 +279,12 @@ static bool dce_v8_0_hpd_sense(struct amdgpu_device *adev, { bool connected = false; - switch (hpd) { - case AMDGPU_HPD_1: - if (RREG32(mmDC_HPD1_INT_STATUS) & DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK) - connected = true; - break; - case AMDGPU_HPD_2: - if (RREG32(mmDC_HPD2_INT_STATUS) & DC_HPD2_INT_STATUS__DC_HPD2_SENSE_MASK) - connected = true; - break; - case AMDGPU_HPD_3: - if (RREG32(mmDC_HPD3_INT_STATUS) & DC_HPD3_INT_STATUS__DC_HPD3_SENSE_MASK) - connected = true; - break; - case AMDGPU_HPD_4: - if (RREG32(mmDC_HPD4_INT_STATUS) & DC_HPD4_INT_STATUS__DC_HPD4_SENSE_MASK) - connected = true; - break; - case AMDGPU_HPD_5: - if (RREG32(mmDC_HPD5_INT_STATUS) & DC_HPD5_INT_STATUS__DC_HPD5_SENSE_MASK) - connected = true; - break; - case AMDGPU_HPD_6: - if (RREG32(mmDC_HPD6_INT_STATUS) & DC_HPD6_INT_STATUS__DC_HPD6_SENSE_MASK) - connected = true; - break; - default: - break; - } + if (hpd >= adev->mode_info.num_hpd) + return connected; + + if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) & + DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK) + connected = true; return connected; } @@ -324,58 +303,15 @@ static void dce_v8_0_hpd_set_polarity(struct amdgpu_device *adev, u32 tmp; bool connected = dce_v8_0_hpd_sense(adev, hpd); - switch (hpd) { - case AMDGPU_HPD_1: - tmp = RREG32(mmDC_HPD1_INT_CONTROL); - if (connected) - tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK; - else - tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK; - WREG32(mmDC_HPD1_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_2: - tmp = RREG32(mmDC_HPD2_INT_CONTROL); - if (connected) - tmp &= ~DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY_MASK; - else - tmp |= DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY_MASK; - WREG32(mmDC_HPD2_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_3: - tmp = RREG32(mmDC_HPD3_INT_CONTROL); - if (connected) - tmp &= ~DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY_MASK; - else - tmp |= DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY_MASK; - WREG32(mmDC_HPD3_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_4: - tmp = RREG32(mmDC_HPD4_INT_CONTROL); - if (connected) - tmp &= ~DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY_MASK; - else - tmp |= DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY_MASK; - WREG32(mmDC_HPD4_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_5: - tmp = RREG32(mmDC_HPD5_INT_CONTROL); - if (connected) - tmp &= ~DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY_MASK; - else - tmp |= DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY_MASK; - WREG32(mmDC_HPD5_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_6: - tmp = RREG32(mmDC_HPD6_INT_CONTROL); - if (connected) - tmp &= ~DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY_MASK; - else - tmp |= DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY_MASK; - WREG32(mmDC_HPD6_INT_CONTROL, tmp); - break; - default: - break; - } + if (hpd >= adev->mode_info.num_hpd) + return; + + tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]); + if (connected) + tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK; + else + tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK; + WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp); } /** @@ -397,28 +333,10 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - WREG32(mmDC_HPD1_CONTROL, tmp); - break; - case AMDGPU_HPD_2: - WREG32(mmDC_HPD2_CONTROL, tmp); - break; - case AMDGPU_HPD_3: - WREG32(mmDC_HPD3_CONTROL, tmp); - break; - case AMDGPU_HPD_4: - WREG32(mmDC_HPD4_CONTROL, tmp); - break; - case AMDGPU_HPD_5: - WREG32(mmDC_HPD5_CONTROL, tmp); - break; - case AMDGPU_HPD_6: - WREG32(mmDC_HPD6_CONTROL, tmp); - break; - default: - break; - } + if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) + continue; + + WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { @@ -427,34 +345,9 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev) * https://bugzilla.redhat.com/show_bug.cgi?id=726143 * also avoid interrupt storms during dpms. */ - u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl; - - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - dc_hpd_int_cntl_reg = mmDC_HPD1_INT_CONTROL; - break; - case AMDGPU_HPD_2: - dc_hpd_int_cntl_reg = mmDC_HPD2_INT_CONTROL; - break; - case AMDGPU_HPD_3: - dc_hpd_int_cntl_reg = mmDC_HPD3_INT_CONTROL; - break; - case AMDGPU_HPD_4: - dc_hpd_int_cntl_reg = mmDC_HPD4_INT_CONTROL; - break; - case AMDGPU_HPD_5: - dc_hpd_int_cntl_reg = mmDC_HPD5_INT_CONTROL; - break; - case AMDGPU_HPD_6: - dc_hpd_int_cntl_reg = mmDC_HPD6_INT_CONTROL; - break; - default: - continue; - } - - dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg); - dc_hpd_int_cntl &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK; - WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl); + tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); + tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK; + WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); continue; } @@ -479,28 +372,11 @@ static void dce_v8_0_hpd_fini(struct amdgpu_device *adev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - WREG32(mmDC_HPD1_CONTROL, 0); - break; - case AMDGPU_HPD_2: - WREG32(mmDC_HPD2_CONTROL, 0); - break; - case AMDGPU_HPD_3: - WREG32(mmDC_HPD3_CONTROL, 0); - break; - case AMDGPU_HPD_4: - WREG32(mmDC_HPD4_CONTROL, 0); - break; - case AMDGPU_HPD_5: - WREG32(mmDC_HPD5_CONTROL, 0); - break; - case AMDGPU_HPD_6: - WREG32(mmDC_HPD6_CONTROL, 0); - break; - default: - break; - } + if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) + continue; + + WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], 0); + amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); } } @@ -3204,42 +3080,23 @@ static int dce_v8_0_set_hpd_interrupt_state(struct amdgpu_device *adev, unsigned type, enum amdgpu_interrupt_state state) { - u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl; + u32 dc_hpd_int_cntl; - switch (type) { - case AMDGPU_HPD_1: - dc_hpd_int_cntl_reg = mmDC_HPD1_INT_CONTROL; - break; - case AMDGPU_HPD_2: - dc_hpd_int_cntl_reg = mmDC_HPD2_INT_CONTROL; - break; - case AMDGPU_HPD_3: - dc_hpd_int_cntl_reg = mmDC_HPD3_INT_CONTROL; - break; - case AMDGPU_HPD_4: - dc_hpd_int_cntl_reg = mmDC_HPD4_INT_CONTROL; - break; - case AMDGPU_HPD_5: - dc_hpd_int_cntl_reg = mmDC_HPD5_INT_CONTROL; - break; - case AMDGPU_HPD_6: - dc_hpd_int_cntl_reg = mmDC_HPD6_INT_CONTROL; - break; - default: + if (type >= adev->mode_info.num_hpd) { DRM_DEBUG("invalid hdp %d\n", type); return 0; } switch (state) { case AMDGPU_IRQ_STATE_DISABLE: - dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg); + dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]); dc_hpd_int_cntl &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK; - WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl); + WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl); break; case AMDGPU_IRQ_STATE_ENABLE: - dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg); + dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]); dc_hpd_int_cntl |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK; - WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl); + WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl); break; default: break; @@ -3412,7 +3269,7 @@ static int dce_v8_0_hpd_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - uint32_t disp_int, mask, int_control, tmp; + uint32_t disp_int, mask, tmp; unsigned hpd; if (entry->src_data >= adev->mode_info.num_hpd) { @@ -3423,12 +3280,11 @@ static int dce_v8_0_hpd_irq(struct amdgpu_device *adev, hpd = entry->src_data; disp_int = RREG32(interrupt_status_offsets[hpd].reg); mask = interrupt_status_offsets[hpd].hpd; - int_control = hpd_int_control_offsets[hpd]; if (disp_int & mask) { - tmp = RREG32(int_control); + tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]); tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK; - WREG32(int_control, tmp); + WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp); schedule_work(&adev->hotplug_work); DRM_DEBUG("IH: HPD%d\n", hpd + 1); } -- cgit v1.2.3 From 6753ac2bf4c794d33f3232f84de790d4a0c3309d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Sep 2016 13:44:00 -0400 Subject: drm/amdgpu/dce10: simplify hpd code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use the hpd enum directly as an index Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 114 +++++---------------------------- 1 file changed, 15 insertions(+), 99 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 4108c686aa7c..15c38331a319 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -330,33 +330,12 @@ static int dce_v10_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, static bool dce_v10_0_hpd_sense(struct amdgpu_device *adev, enum amdgpu_hpd_id hpd) { - int idx; bool connected = false; - switch (hpd) { - case AMDGPU_HPD_1: - idx = 0; - break; - case AMDGPU_HPD_2: - idx = 1; - break; - case AMDGPU_HPD_3: - idx = 2; - break; - case AMDGPU_HPD_4: - idx = 3; - break; - case AMDGPU_HPD_5: - idx = 4; - break; - case AMDGPU_HPD_6: - idx = 5; - break; - default: + if (hpd >= adev->mode_info.num_hpd) return connected; - } - if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[idx]) & + if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[hpd]) & DC_HPD_INT_STATUS__DC_HPD_SENSE_MASK) connected = true; @@ -376,37 +355,16 @@ static void dce_v10_0_hpd_set_polarity(struct amdgpu_device *adev, { u32 tmp; bool connected = dce_v10_0_hpd_sense(adev, hpd); - int idx; - switch (hpd) { - case AMDGPU_HPD_1: - idx = 0; - break; - case AMDGPU_HPD_2: - idx = 1; - break; - case AMDGPU_HPD_3: - idx = 2; - break; - case AMDGPU_HPD_4: - idx = 3; - break; - case AMDGPU_HPD_5: - idx = 4; - break; - case AMDGPU_HPD_6: - idx = 5; - break; - default: + if (hpd >= adev->mode_info.num_hpd) return; - } - tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd]); if (connected) tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 0); else tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 1); - WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd], tmp); } /** @@ -422,33 +380,12 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev) struct drm_device *dev = adev->ddev; struct drm_connector *connector; u32 tmp; - int idx; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - idx = 0; - break; - case AMDGPU_HPD_2: - idx = 1; - break; - case AMDGPU_HPD_3: - idx = 2; - break; - case AMDGPU_HPD_4: - idx = 3; - break; - case AMDGPU_HPD_5: - idx = 4; - break; - case AMDGPU_HPD_6: - idx = 5; - break; - default: + if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) continue; - } if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { @@ -457,24 +394,24 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev) * https://bugzilla.redhat.com/show_bug.cgi?id=726143 * also avoid interrupt storms during dpms. */ - tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0); - WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); continue; } - tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1); - WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); - tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd]); tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, AMDGPU_HPD_CONNECT_INT_DELAY_IN_MS); tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, AMDGPU_HPD_DISCONNECT_INT_DELAY_IN_MS); - WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); dce_v10_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd); amdgpu_irq_get(adev, &adev->hpd_irq, @@ -495,37 +432,16 @@ static void dce_v10_0_hpd_fini(struct amdgpu_device *adev) struct drm_device *dev = adev->ddev; struct drm_connector *connector; u32 tmp; - int idx; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - idx = 0; - break; - case AMDGPU_HPD_2: - idx = 1; - break; - case AMDGPU_HPD_3: - idx = 2; - break; - case AMDGPU_HPD_4: - idx = 3; - break; - case AMDGPU_HPD_5: - idx = 4; - break; - case AMDGPU_HPD_6: - idx = 5; - break; - default: + if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) continue; - } - tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 0); - WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); -- cgit v1.2.3 From 03ae23b93bcbeebd7bd15e5afd3cddaf537d3f5c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Sep 2016 13:50:27 -0400 Subject: drm/amdgpu/dce8: RMW hpd registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to hard code the entire register to just set/clear one bit. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index d0034e4645b9..0245ed605107 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -326,9 +326,7 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev) { struct drm_device *dev = adev->ddev; struct drm_connector *connector; - u32 tmp = (0x9c4 << DC_HPD1_CONTROL__DC_HPD1_CONNECTION_TIMER__SHIFT) | - (0xfa << DC_HPD1_CONTROL__DC_HPD1_RX_INT_TIMER__SHIFT) | - DC_HPD1_CONTROL__DC_HPD1_EN_MASK; + u32 tmp; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); @@ -336,6 +334,8 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev) if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) continue; + tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); + tmp |= DC_HPD1_CONTROL__DC_HPD1_EN_MASK; WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || @@ -368,6 +368,7 @@ static void dce_v8_0_hpd_fini(struct amdgpu_device *adev) { struct drm_device *dev = adev->ddev; struct drm_connector *connector; + u32 tmp; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); @@ -375,6 +376,8 @@ static void dce_v8_0_hpd_fini(struct amdgpu_device *adev) if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) continue; + tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); + tmp &= ~DC_HPD1_CONTROL__DC_HPD1_EN_MASK; WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], 0); amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); -- cgit v1.2.3 From d2486d25bdfc837d5f0f86ea83051f8355763d30 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Sep 2016 13:56:50 -0400 Subject: drm/amdgpu/dce11: simplify hpd code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use the hpd enum directly as an index Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 114 +++++---------------------------- 1 file changed, 15 insertions(+), 99 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index f264b8f17ad1..2696428bed05 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -346,33 +346,12 @@ static int dce_v11_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, static bool dce_v11_0_hpd_sense(struct amdgpu_device *adev, enum amdgpu_hpd_id hpd) { - int idx; bool connected = false; - switch (hpd) { - case AMDGPU_HPD_1: - idx = 0; - break; - case AMDGPU_HPD_2: - idx = 1; - break; - case AMDGPU_HPD_3: - idx = 2; - break; - case AMDGPU_HPD_4: - idx = 3; - break; - case AMDGPU_HPD_5: - idx = 4; - break; - case AMDGPU_HPD_6: - idx = 5; - break; - default: + if (hpd >= adev->mode_info.num_hpd) return connected; - } - if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[idx]) & + if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[hpd]) & DC_HPD_INT_STATUS__DC_HPD_SENSE_MASK) connected = true; @@ -392,37 +371,16 @@ static void dce_v11_0_hpd_set_polarity(struct amdgpu_device *adev, { u32 tmp; bool connected = dce_v11_0_hpd_sense(adev, hpd); - int idx; - switch (hpd) { - case AMDGPU_HPD_1: - idx = 0; - break; - case AMDGPU_HPD_2: - idx = 1; - break; - case AMDGPU_HPD_3: - idx = 2; - break; - case AMDGPU_HPD_4: - idx = 3; - break; - case AMDGPU_HPD_5: - idx = 4; - break; - case AMDGPU_HPD_6: - idx = 5; - break; - default: + if (hpd >= adev->mode_info.num_hpd) return; - } - tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd]); if (connected) tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 0); else tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 1); - WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd], tmp); } /** @@ -438,33 +396,12 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev) struct drm_device *dev = adev->ddev; struct drm_connector *connector; u32 tmp; - int idx; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - idx = 0; - break; - case AMDGPU_HPD_2: - idx = 1; - break; - case AMDGPU_HPD_3: - idx = 2; - break; - case AMDGPU_HPD_4: - idx = 3; - break; - case AMDGPU_HPD_5: - idx = 4; - break; - case AMDGPU_HPD_6: - idx = 5; - break; - default: + if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) continue; - } if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { @@ -473,24 +410,24 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev) * https://bugzilla.redhat.com/show_bug.cgi?id=726143 * also avoid interrupt storms during dpms. */ - tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0); - WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); continue; } - tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1); - WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); - tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd]); tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, AMDGPU_HPD_CONNECT_INT_DELAY_IN_MS); tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, AMDGPU_HPD_DISCONNECT_INT_DELAY_IN_MS); - WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); dce_v11_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd); amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); @@ -510,37 +447,16 @@ static void dce_v11_0_hpd_fini(struct amdgpu_device *adev) struct drm_device *dev = adev->ddev; struct drm_connector *connector; u32 tmp; - int idx; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - idx = 0; - break; - case AMDGPU_HPD_2: - idx = 1; - break; - case AMDGPU_HPD_3: - idx = 2; - break; - case AMDGPU_HPD_4: - idx = 3; - break; - case AMDGPU_HPD_5: - idx = 4; - break; - case AMDGPU_HPD_6: - idx = 5; - break; - default: + if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) continue; - } - tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]); + tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 0); - WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp); + WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); } -- cgit v1.2.3 From 34386043d90489898240a2211545f5c46c3b7c3b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Sep 2016 14:15:24 -0400 Subject: drm/amdgpu/dce6: simplify hpd code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use an address offset like other dce code. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 235 +++++++--------------------------- 1 file changed, 45 insertions(+), 190 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index e6a7687dec21..0bf262d7a31b 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -46,6 +46,16 @@ static const u32 crtc_offsets[6] = SI_CRTC5_REGISTER_OFFSET }; +static const u32 hpd_offsets[] = +{ + DC_HPD1_INT_STATUS - DC_HPD1_INT_STATUS, + DC_HPD2_INT_STATUS - DC_HPD1_INT_STATUS, + DC_HPD3_INT_STATUS - DC_HPD1_INT_STATUS, + DC_HPD4_INT_STATUS - DC_HPD1_INT_STATUS, + DC_HPD5_INT_STATUS - DC_HPD1_INT_STATUS, + DC_HPD6_INT_STATUS - DC_HPD1_INT_STATUS, +}; + static const uint32_t dig_offsets[] = { SI_CRTC0_REGISTER_OFFSET, SI_CRTC1_REGISTER_OFFSET, @@ -94,15 +104,6 @@ static const struct { .hpd = DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK } }; -static const uint32_t hpd_int_control_offsets[6] = { - DC_HPD1_INT_CONTROL, - DC_HPD2_INT_CONTROL, - DC_HPD3_INT_CONTROL, - DC_HPD4_INT_CONTROL, - DC_HPD5_INT_CONTROL, - DC_HPD6_INT_CONTROL, -}; - static u32 dce_v6_0_audio_endpt_rreg(struct amdgpu_device *adev, u32 block_offset, u32 reg) { @@ -257,34 +258,11 @@ static bool dce_v6_0_hpd_sense(struct amdgpu_device *adev, { bool connected = false; - switch (hpd) { - case AMDGPU_HPD_1: - if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE) - connected = true; - break; - case AMDGPU_HPD_2: - if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE) - connected = true; - break; - case AMDGPU_HPD_3: - if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE) - connected = true; - break; - case AMDGPU_HPD_4: - if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE) - connected = true; - break; - case AMDGPU_HPD_5: - if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE) - connected = true; - break; - case AMDGPU_HPD_6: - if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) - connected = true; - break; - default: - break; - } + if (hpd >= adev->mode_info.num_hpd) + return connected; + + if (RREG32(DC_HPD1_INT_STATUS + hpd_offsets[hpd]) & DC_HPDx_SENSE) + connected = true; return connected; } @@ -303,58 +281,15 @@ static void dce_v6_0_hpd_set_polarity(struct amdgpu_device *adev, u32 tmp; bool connected = dce_v6_0_hpd_sense(adev, hpd); - switch (hpd) { - case AMDGPU_HPD_1: - tmp = RREG32(DC_HPD1_INT_CONTROL); - if (connected) - tmp &= ~DC_HPDx_INT_POLARITY; - else - tmp |= DC_HPDx_INT_POLARITY; - WREG32(DC_HPD1_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_2: - tmp = RREG32(DC_HPD2_INT_CONTROL); - if (connected) - tmp &= ~DC_HPDx_INT_POLARITY; - else - tmp |= DC_HPDx_INT_POLARITY; - WREG32(DC_HPD2_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_3: - tmp = RREG32(DC_HPD3_INT_CONTROL); - if (connected) - tmp &= ~DC_HPDx_INT_POLARITY; - else - tmp |= DC_HPDx_INT_POLARITY; - WREG32(DC_HPD3_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_4: - tmp = RREG32(DC_HPD4_INT_CONTROL); - if (connected) - tmp &= ~DC_HPDx_INT_POLARITY; - else - tmp |= DC_HPDx_INT_POLARITY; - WREG32(DC_HPD4_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_5: - tmp = RREG32(DC_HPD5_INT_CONTROL); - if (connected) - tmp &= ~DC_HPDx_INT_POLARITY; - else - tmp |= DC_HPDx_INT_POLARITY; - WREG32(DC_HPD5_INT_CONTROL, tmp); - break; - case AMDGPU_HPD_6: - tmp = RREG32(DC_HPD6_INT_CONTROL); - if (connected) - tmp &= ~DC_HPDx_INT_POLARITY; - else - tmp |= DC_HPDx_INT_POLARITY; - WREG32(DC_HPD6_INT_CONTROL, tmp); - break; - default: - break; - } + if (hpd >= adev->mode_info.num_hpd) + return; + + tmp = RREG32(DC_HPD1_INT_CONTROL + hpd_offsets[hpd]); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp); } /** @@ -375,28 +310,10 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - WREG32(DC_HPD1_CONTROL, tmp); - break; - case AMDGPU_HPD_2: - WREG32(DC_HPD2_CONTROL, tmp); - break; - case AMDGPU_HPD_3: - WREG32(DC_HPD3_CONTROL, tmp); - break; - case AMDGPU_HPD_4: - WREG32(DC_HPD4_CONTROL, tmp); - break; - case AMDGPU_HPD_5: - WREG32(DC_HPD5_CONTROL, tmp); - break; - case AMDGPU_HPD_6: - WREG32(DC_HPD6_CONTROL, tmp); - break; - default: - break; - } + if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) + continue; + + WREG32(DC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { @@ -405,34 +322,9 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev) * https://bugzilla.redhat.com/show_bug.cgi?id=726143 * also avoid interrupt storms during dpms. */ - u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl; - - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - dc_hpd_int_cntl_reg = DC_HPD1_INT_CONTROL; - break; - case AMDGPU_HPD_2: - dc_hpd_int_cntl_reg = DC_HPD2_INT_CONTROL; - break; - case AMDGPU_HPD_3: - dc_hpd_int_cntl_reg = DC_HPD3_INT_CONTROL; - break; - case AMDGPU_HPD_4: - dc_hpd_int_cntl_reg = DC_HPD4_INT_CONTROL; - break; - case AMDGPU_HPD_5: - dc_hpd_int_cntl_reg = DC_HPD5_INT_CONTROL; - break; - case AMDGPU_HPD_6: - dc_hpd_int_cntl_reg = DC_HPD6_INT_CONTROL; - break; - default: - continue; - } - - dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg); - dc_hpd_int_cntl &= ~DC_HPDx_INT_EN; - WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl); + tmp = RREG32(DC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); + tmp &= ~DC_HPDx_INT_EN; + WREG32(DC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); continue; } @@ -458,28 +350,11 @@ static void dce_v6_0_hpd_fini(struct amdgpu_device *adev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - switch (amdgpu_connector->hpd.hpd) { - case AMDGPU_HPD_1: - WREG32(DC_HPD1_CONTROL, 0); - break; - case AMDGPU_HPD_2: - WREG32(DC_HPD2_CONTROL, 0); - break; - case AMDGPU_HPD_3: - WREG32(DC_HPD3_CONTROL, 0); - break; - case AMDGPU_HPD_4: - WREG32(DC_HPD4_CONTROL, 0); - break; - case AMDGPU_HPD_5: - WREG32(DC_HPD5_CONTROL, 0); - break; - case AMDGPU_HPD_6: - WREG32(DC_HPD6_CONTROL, 0); - break; - default: - break; - } + if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) + continue; + + WREG32(DC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], 0); + amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); } } @@ -2630,42 +2505,23 @@ static int dce_v6_0_set_hpd_interrupt_state(struct amdgpu_device *adev, unsigned type, enum amdgpu_interrupt_state state) { - u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl; + u32 dc_hpd_int_cntl; - switch (type) { - case AMDGPU_HPD_1: - dc_hpd_int_cntl_reg = DC_HPD1_INT_CONTROL; - break; - case AMDGPU_HPD_2: - dc_hpd_int_cntl_reg = DC_HPD2_INT_CONTROL; - break; - case AMDGPU_HPD_3: - dc_hpd_int_cntl_reg = DC_HPD3_INT_CONTROL; - break; - case AMDGPU_HPD_4: - dc_hpd_int_cntl_reg = DC_HPD4_INT_CONTROL; - break; - case AMDGPU_HPD_5: - dc_hpd_int_cntl_reg = DC_HPD5_INT_CONTROL; - break; - case AMDGPU_HPD_6: - dc_hpd_int_cntl_reg = DC_HPD6_INT_CONTROL; - break; - default: + if (type >= adev->mode_info.num_hpd) { DRM_DEBUG("invalid hdp %d\n", type); return 0; } switch (state) { case AMDGPU_IRQ_STATE_DISABLE: - dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg); + dc_hpd_int_cntl = RREG32(DC_HPD1_INT_CONTROL + hpd_offsets[type]); dc_hpd_int_cntl &= ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN); - WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl); + WREG32(DC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl); break; case AMDGPU_IRQ_STATE_ENABLE: - dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg); + dc_hpd_int_cntl = RREG32(DC_HPD1_INT_CONTROL + hpd_offsets[type]); dc_hpd_int_cntl |= (DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN); - WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl); + WREG32(DC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl); break; default: break; @@ -2838,7 +2694,7 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - uint32_t disp_int, mask, int_control, tmp; + uint32_t disp_int, mask, tmp; unsigned hpd; if (entry->src_data >= adev->mode_info.num_hpd) { @@ -2849,12 +2705,11 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev, hpd = entry->src_data; disp_int = RREG32(interrupt_status_offsets[hpd].reg); mask = interrupt_status_offsets[hpd].hpd; - int_control = hpd_int_control_offsets[hpd]; if (disp_int & mask) { - tmp = RREG32(int_control); + tmp = RREG32(DC_HPD1_INT_CONTROL + hpd_offsets[hpd]); tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK; - WREG32(int_control, tmp); + WREG32(DC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp); schedule_work(&adev->hotplug_work); DRM_INFO("IH: HPD%d\n", hpd + 1); } -- cgit v1.2.3 From 079ea1901b7186165d958ee54338c68883096d92 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Sep 2016 14:21:55 -0400 Subject: drm/amdgpu/dce6: RMW hpd registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to hard code the entire register to just set/clear one bit. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 0bf262d7a31b..72ab20a757c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -304,8 +304,7 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev) { struct drm_device *dev = adev->ddev; struct drm_connector *connector; - u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | - DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; + u32 tmp; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); @@ -313,6 +312,8 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev) if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) continue; + tmp = RREG32(DC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); + tmp |= DC_HPDx_EN; WREG32(DC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || @@ -346,6 +347,7 @@ static void dce_v6_0_hpd_fini(struct amdgpu_device *adev) { struct drm_device *dev = adev->ddev; struct drm_connector *connector; + u32 tmp; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); @@ -353,6 +355,8 @@ static void dce_v6_0_hpd_fini(struct amdgpu_device *adev) if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd) continue; + tmp = RREG32(DC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]); + tmp &= ~DC_HPDx_EN; WREG32(DC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], 0); amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); -- cgit v1.2.3 From 46c9cc11a5e362bfc850426d892086bf7c4e2d26 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Sep 2016 14:23:49 -0400 Subject: drm/amdgpu/dce6: don't enable HPD Rx interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not used currently. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 72ab20a757c8..502e97963d6d 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -2519,12 +2519,12 @@ static int dce_v6_0_set_hpd_interrupt_state(struct amdgpu_device *adev, switch (state) { case AMDGPU_IRQ_STATE_DISABLE: dc_hpd_int_cntl = RREG32(DC_HPD1_INT_CONTROL + hpd_offsets[type]); - dc_hpd_int_cntl &= ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN); + dc_hpd_int_cntl &= ~DC_HPDx_INT_EN; WREG32(DC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl); break; case AMDGPU_IRQ_STATE_ENABLE: dc_hpd_int_cntl = RREG32(DC_HPD1_INT_CONTROL + hpd_offsets[type]); - dc_hpd_int_cntl |= (DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN); + dc_hpd_int_cntl |= DC_HPDx_INT_EN; WREG32(DC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl); break; default: -- cgit v1.2.3 From 9f6163e7e342bd150efd01aa51432a2e73039762 Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Wed, 21 Sep 2016 10:17:22 +0800 Subject: drm/amd/amdgpu: add info about vram and gtt total size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Junwei Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 10 ++++++++++ include/uapi/drm/amdgpu_drm.h | 8 ++++++++ 2 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index c2c7fb140338..67b6274e25c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -411,6 +411,16 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file return copy_to_user(out, &vram_gtt, min((size_t)size, sizeof(vram_gtt))) ? -EFAULT : 0; } + case AMDGPU_INFO_VRAM_GTT_TOTAL: { + struct drm_amdgpu_info_vram_gtt_total vram_gtt_total; + + vram_gtt_total.vram_total_size = adev->mc.real_vram_size; + vram_gtt_total.vram_cpu_accessible_total_size = adev->mc.visible_vram_size; + vram_gtt_total.gtt_total_size = adev->mc.gtt_size; + return copy_to_user(out, &vram_gtt_total, + min((size_t)size, sizeof(vram_gtt_total))) + ? -EFAULT : 0; + } case AMDGPU_INFO_READ_MMR_REG: { unsigned n, alloc_size; uint32_t *regs; diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index d6b5a21f3d3c..dbfce2035b1f 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -487,6 +487,8 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_VIS_VRAM_USAGE 0x17 /* number of TTM buffer evictions */ #define AMDGPU_INFO_NUM_EVICTIONS 0x18 +/* Query the total size of VRAM and GTT domains */ +#define AMDGPU_INFO_VRAM_GTT_TOTAL 0x19 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0 #define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff @@ -572,6 +574,12 @@ struct drm_amdgpu_info_vram_gtt { __u64 gtt_size; }; +struct drm_amdgpu_info_vram_gtt_total { + __u64 vram_total_size; + __u64 vram_cpu_accessible_total_size; + __u64 gtt_total_size; +}; + struct drm_amdgpu_info_firmware { __u32 ver; __u32 feature; -- cgit v1.2.3 From cfa32556e58d8a353666fb007f708a4955c6711c Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Wed, 21 Sep 2016 10:33:26 +0800 Subject: drm/amd/amdgpu: add info about vram and gtt max allocation size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Junwei Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 18 ++++++++++++++++++ include/uapi/drm/amdgpu_drm.h | 8 ++++++++ 2 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 67b6274e25c8..09b94901faec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -421,6 +421,24 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file min((size_t)size, sizeof(vram_gtt_total))) ? -EFAULT : 0; } + case AMDGPU_INFO_VRAM_GTT_MAX: { + struct drm_amdgpu_info_vram_gtt_max vram_gtt_max; + u64 max_size; + + max_size = adev->mc.real_vram_size - adev->vram_pin_size; + vram_gtt_max.vram_max_size = max_size * 3 / 4; + + max_size = adev->mc.visible_vram_size - (adev->vram_pin_size - + adev->invisible_pin_size); + vram_gtt_max.vram_cpu_accessible_max_size = max_size * 3 / 4; + + max_size = adev->mc.gtt_size - adev->gart_pin_size; + vram_gtt_max.gtt_max_size = max_size * 3 / 4; + + return copy_to_user(out, &vram_gtt_max, + min((size_t)size, sizeof(vram_gtt_max))) + ? -EFAULT : 0; + } case AMDGPU_INFO_READ_MMR_REG: { unsigned n, alloc_size; uint32_t *regs; diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index dbfce2035b1f..0db0d66dc2ba 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -489,6 +489,8 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_NUM_EVICTIONS 0x18 /* Query the total size of VRAM and GTT domains */ #define AMDGPU_INFO_VRAM_GTT_TOTAL 0x19 +/* Query the max allocation size of VRAM and GTT domains */ +#define AMDGPU_INFO_VRAM_GTT_MAX 0x1a #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0 #define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff @@ -580,6 +582,12 @@ struct drm_amdgpu_info_vram_gtt_total { __u64 gtt_total_size; }; +struct drm_amdgpu_info_vram_gtt_max { + __u64 vram_max_size; + __u64 vram_cpu_accessible_max_size; + __u64 gtt_max_size; +}; + struct drm_amdgpu_info_firmware { __u32 ver; __u32 feature; -- cgit v1.2.3 From 03f48dd5d2085b978353a804635b6d34e77a5635 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 15 Aug 2016 17:00:22 +0200 Subject: drm/amdgpu: add AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS flag v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a flag noting that a BO must be created using linear VRAM and set this flag on all in kernel users where appropriate. Hopefully I haven't missed anything. v2: add it in a few more places, fix CPU mapping. v3: rename to VRAM_CONTIGUOUS, fix typo in CS code. Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 12 ++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 9 ++++++--- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 ++++-- include/uapi/drm/amdgpu_drm.h | 2 ++ 13 files changed, 53 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 7a8bfa34682f..a61f4186a7dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -146,7 +146,8 @@ static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device, switch(type) { case CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB: case CGS_GPU_MEM_TYPE__VISIBLE_FB: - flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; + flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; domain = AMDGPU_GEM_DOMAIN_VRAM; if (max_offset > adev->mc.real_vram_size) return -EINVAL; @@ -157,7 +158,8 @@ static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device, break; case CGS_GPU_MEM_TYPE__INVISIBLE_CONTIG_FB: case CGS_GPU_MEM_TYPE__INVISIBLE_FB: - flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS; + flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; domain = AMDGPU_GEM_DOMAIN_VRAM; if (adev->mc.visible_vram_size < adev->mc.real_vram_size) { place.fpfn = diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index b0f6e6957536..187c3662b72c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1195,6 +1195,15 @@ int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser) r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem); if (unlikely(r)) return r; + + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) + continue; + + bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; + amdgpu_ttm_placement_from_domain(bo, bo->allowed_domains); + r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); + if (unlikely(r)) + return r; } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 22d331947aca..246bbd1ab5ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -264,7 +264,8 @@ static int amdgpu_vram_scratch_init(struct amdgpu_device *adev) if (adev->vram_scratch.robj == NULL) { r = amdgpu_bo_create(adev, AMDGPU_GPU_PAGE_SIZE, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->vram_scratch.robj); if (r) { return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 8d01aa24d68a..38bdc2d300a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -152,7 +152,8 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, aligned_size = ALIGN(size, PAGE_SIZE); ret = amdgpu_gem_object_create(adev, aligned_size, 0, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, true, &gobj); if (ret) { printk(KERN_ERR "failed to allocate framebuffer (%d)\n", diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index 21a1242fc13b..964d2a946ed5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -126,7 +126,8 @@ int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev) if (adev->gart.robj == NULL) { r = amdgpu_bo_create(adev, adev->gart.table_size, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->gart.robj); if (r) { return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index aa074fac0c7f..ba41807eb917 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -245,7 +245,8 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev, int r; r = amdgpu_bo_create(adev, size, align, true, domain, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, bo_ptr); if (r) { dev_err(adev->dev, "(%d) failed to allocate kernel bo\n", r); @@ -643,6 +644,8 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, return 0; } + + bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; amdgpu_ttm_placement_from_domain(bo, domain); for (i = 0; i < bo->placement.num_placement; i++) { /* force to pin into visible video ram */ @@ -885,7 +888,9 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) size = bo->mem.num_pages << PAGE_SHIFT; offset = bo->mem.start << PAGE_SHIFT; - if ((offset + size) <= adev->mc.visible_vram_size) + /* TODO: figure out how to map scattered VRAM to the CPU */ + if ((offset + size) <= adev->mc.visible_vram_size && + (abo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) return 0; /* Can't move a pinned BO to visible VRAM */ @@ -893,6 +898,7 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) return -EINVAL; /* hurrah the memory is not visible ! */ + abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM); lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; for (i = 0; i < abo->placement.num_placement; i++) { @@ -954,6 +960,8 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) && !bo->pin_count); WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET); + WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_VRAM && + !(bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)); return bo->tbo.offset; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index dcaf691f56b5..a06cf9988912 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1119,7 +1119,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) r = amdgpu_bo_create(adev, 256 * 1024, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->stollen_vga_memory); if (r) { return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index e3281cacc586..4cf3ca755810 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -1002,7 +1002,8 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &bo); if (r) return r; @@ -1051,7 +1052,8 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &bo); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 7fe8fd884f06..9a534e2757cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -157,7 +157,8 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size) r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->vce.vcpu_bo); if (r) { dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 06f24322e7c3..7b9e94f235ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1416,7 +1416,8 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, AMDGPU_GPU_PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_CREATE_NO_CPU_ACCESS | - AMDGPU_GEM_CREATE_SHADOW, + AMDGPU_GEM_CREATE_SHADOW | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, resv, &pt); if (r) goto error_free; @@ -1626,7 +1627,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) r = amdgpu_bo_create(adev, pd_size, align, true, AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_CREATE_NO_CPU_ACCESS | - AMDGPU_GEM_CREATE_SHADOW, + AMDGPU_GEM_CREATE_SHADOW | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &vm->page_directory); if (r) goto error_free_sched_entity; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 71116da9e782..b2cf1290c1cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -3391,7 +3391,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.save_restore_obj == NULL) { r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->gfx.rlc.save_restore_obj); if (r) { @@ -3435,7 +3436,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.clear_state_obj == NULL) { r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->gfx.rlc.clear_state_obj); if (r) { @@ -3475,7 +3477,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.cp_table_obj == NULL) { r = amdgpu_bo_create(adev, adev->gfx.rlc.cp_table_size, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->gfx.rlc.cp_table_obj); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index ee6a48a09214..bd4d041717bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1273,7 +1273,8 @@ static int gfx_v8_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.clear_state_obj == NULL) { r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->gfx.rlc.clear_state_obj); if (r) { @@ -1315,7 +1316,8 @@ static int gfx_v8_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.cp_table_obj == NULL) { r = amdgpu_bo_create(adev, adev->gfx.rlc.cp_table_size, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->gfx.rlc.cp_table_obj); if (r) { diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 0db0d66dc2ba..6491e8b9a309 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -81,6 +81,8 @@ extern "C" { #define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3) /* Flag that create shadow bo(GTT) while allocating vram bo */ #define AMDGPU_GEM_CREATE_SHADOW (1 << 4) +/* Flag that allocating the BO should use linear VRAM */ +#define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS (1 << 5) struct drm_amdgpu_gem_create_in { /** the requested memory size */ -- cgit v1.2.3 From 56de55a1a8fcabf8b3f6a64eedd3b6079b1f2fc7 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 24 Aug 2016 14:30:21 +0200 Subject: drm/amdgpu: use explicit limit for VRAM_CONTIGUOUS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split VRAM won't have a valid offset, so just set an explicit limit when the flag is given to trigger reallocation if necessary. Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index ba41807eb917..c6754e71e1f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -121,12 +121,17 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev, if (domain & AMDGPU_GEM_DOMAIN_VRAM) { unsigned visible_pfn = adev->mc.visible_vram_size >> PAGE_SHIFT; + unsigned lpfn = 0; + + /* This forces a reallocation if the flag wasn't set before */ + if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) + lpfn = adev->mc.real_vram_size >> PAGE_SHIFT; if (flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS && !(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && adev->mc.visible_vram_size < adev->mc.real_vram_size) { places[c].fpfn = visible_pfn; - places[c].lpfn = 0; + places[c].lpfn = lpfn; places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM | TTM_PL_FLAG_TOPDOWN; @@ -134,7 +139,7 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev, } places[c].fpfn = 0; - places[c].lpfn = 0; + places[c].lpfn = lpfn; places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) -- cgit v1.2.3 From d2e938701ac54cc44f28f79aa1dd640ba43b936f Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 14 Sep 2016 10:35:19 +0200 Subject: drm/amdgpu: set at least the node size in the gtt manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the new VM code becomes confused. Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index f86c84427778..3c634f02a3d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -168,6 +168,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man, return -ENOMEM; node->start = AMDGPU_BO_INVALID_OFFSET; + node->size = mem->num_pages; mem->mm_node = node; if (place->fpfn || place->lpfn || place->flags & TTM_PL_FLAG_TOPDOWN) { -- cgit v1.2.3 From 63e0ba40e52c60f25ab67e27c89ed2b99b847562 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 16 Aug 2016 17:38:37 +0200 Subject: drm/amdgpu: handle multiple MM nodes in the VMs v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to map scattered VRAM BOs to the VMs. v2: fix offset handling, use pfn instead of offset, fix PAGE_SIZE != AMDGPU_GPU_PAGE_SIZE case Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 81 +++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 7b9e94f235ab..e2fefbbd3cc8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1065,8 +1065,8 @@ error_free: * @pages_addr: DMA addresses to use for mapping * @vm: requested vm * @mapping: mapped range and flags to use for the update - * @addr: addr to set the area to * @flags: HW flags for the mapping + * @nodes: array of drm_mm_nodes with the MC addresses * @fence: optional resulting fence * * Split the mapping into smaller chunks so that each update fits @@ -1079,12 +1079,11 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, dma_addr_t *pages_addr, struct amdgpu_vm *vm, struct amdgpu_bo_va_mapping *mapping, - uint32_t flags, uint64_t addr, + uint32_t flags, + struct drm_mm_node *nodes, struct fence **fence) { - const uint64_t max_size = 64ULL * 1024ULL * 1024ULL / AMDGPU_GPU_PAGE_SIZE; - - uint64_t src = 0, start = mapping->it.start; + uint64_t pfn, src = 0, start = mapping->it.start; int r; /* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here @@ -1097,23 +1096,40 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, trace_amdgpu_vm_bo_update(mapping); - if (pages_addr) { - if (flags == gtt_flags) - src = adev->gart.table_addr + (addr >> 12) * 8; - addr = 0; + pfn = mapping->offset >> PAGE_SHIFT; + if (nodes) { + while (pfn >= nodes->size) { + pfn -= nodes->size; + ++nodes; + } } - addr += mapping->offset; - if (!pages_addr || src) - return amdgpu_vm_bo_update_mapping(adev, exclusive, - src, pages_addr, vm, - start, mapping->it.last, - flags, addr, fence); + do { + uint64_t max_entries; + uint64_t addr, last; - while (start != mapping->it.last + 1) { - uint64_t last; + if (nodes) { + addr = nodes->start << PAGE_SHIFT; + max_entries = (nodes->size - pfn) * + (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); + } else { + addr = 0; + max_entries = S64_MAX; + } - last = min((uint64_t)mapping->it.last, start + max_size - 1); + if (pages_addr) { + if (flags == gtt_flags) + src = adev->gart.table_addr + + (addr >> AMDGPU_GPU_PAGE_SHIFT) * 8; + else + max_entries = min(max_entries, 16ull * 1024ull); + addr = 0; + } else if (flags & AMDGPU_PTE_VALID) { + addr += adev->vm_manager.vram_base_offset; + } + addr += pfn << PAGE_SHIFT; + + last = min((uint64_t)mapping->it.last, start + max_entries - 1); r = amdgpu_vm_bo_update_mapping(adev, exclusive, src, pages_addr, vm, start, last, flags, addr, @@ -1121,9 +1137,14 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, if (r) return r; + pfn += last - start + 1; + if (nodes && nodes->size == pfn) { + pfn = 0; + ++nodes; + } start = last + 1; - addr += max_size * AMDGPU_GPU_PAGE_SIZE; - } + + } while (unlikely(start != mapping->it.last + 1)); return 0; } @@ -1147,34 +1168,24 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, dma_addr_t *pages_addr = NULL; uint32_t gtt_flags, flags; struct ttm_mem_reg *mem; + struct drm_mm_node *nodes; struct fence *exclusive; - uint64_t addr; int r; if (clear) { mem = NULL; - addr = 0; + nodes = NULL; exclusive = NULL; } else { struct ttm_dma_tt *ttm; mem = &bo_va->bo->tbo.mem; - addr = (u64)mem->start << PAGE_SHIFT; - switch (mem->mem_type) { - case TTM_PL_TT: + nodes = mem->mm_node; + if (mem->mem_type == TTM_PL_TT) { ttm = container_of(bo_va->bo->tbo.ttm, struct ttm_dma_tt, ttm); pages_addr = ttm->dma_address; - break; - - case TTM_PL_VRAM: - addr += adev->vm_manager.vram_base_offset; - break; - - default: - break; } - exclusive = reservation_object_get_excl(bo_va->bo->tbo.resv); } @@ -1190,7 +1201,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, list_for_each_entry(mapping, &bo_va->invalids, list) { r = amdgpu_vm_bo_split_mapping(adev, exclusive, gtt_flags, pages_addr, vm, - mapping, flags, addr, + mapping, flags, nodes, &bo_va->last_pt_update); if (r) return r; -- cgit v1.2.3 From 8892f153c83e521aff2ee7ac620856e2983cd7a0 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 17 Aug 2016 10:46:52 +0200 Subject: drm/amdgpu: enable amdgpu_move_blit to handle multiple MM nodes v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to move scattered buffers around. v2: fix a couple of typos, handle scattered to scattered moves as well. Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 118 +++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a06cf9988912..1427c40c70bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -260,64 +260,116 @@ static void amdgpu_move_null(struct ttm_buffer_object *bo, new_mem->mm_node = NULL; } -static int amdgpu_move_blit(struct ttm_buffer_object *bo, - bool evict, bool no_wait_gpu, - struct ttm_mem_reg *new_mem, - struct ttm_mem_reg *old_mem) +static int amdgpu_mm_node_addr(struct ttm_buffer_object *bo, + struct drm_mm_node *mm_node, + struct ttm_mem_reg *mem, + uint64_t *addr) { - struct amdgpu_device *adev; - struct amdgpu_ring *ring; - uint64_t old_start, new_start; - struct fence *fence; int r; - adev = amdgpu_get_adev(bo->bdev); - ring = adev->mman.buffer_funcs_ring; - - switch (old_mem->mem_type) { + switch (mem->mem_type) { case TTM_PL_TT: - r = amdgpu_ttm_bind(bo, old_mem); + r = amdgpu_ttm_bind(bo, mem); if (r) return r; case TTM_PL_VRAM: - old_start = (u64)old_mem->start << PAGE_SHIFT; - old_start += bo->bdev->man[old_mem->mem_type].gpu_offset; + *addr = mm_node->start << PAGE_SHIFT; + *addr += bo->bdev->man[mem->mem_type].gpu_offset; break; default: - DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + DRM_ERROR("Unknown placement %d\n", mem->mem_type); return -EINVAL; } - switch (new_mem->mem_type) { - case TTM_PL_TT: - r = amdgpu_ttm_bind(bo, new_mem); - if (r) - return r; - case TTM_PL_VRAM: - new_start = (u64)new_mem->start << PAGE_SHIFT; - new_start += bo->bdev->man[new_mem->mem_type].gpu_offset; - break; - default: - DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); - return -EINVAL; - } + return 0; +} + +static int amdgpu_move_blit(struct ttm_buffer_object *bo, + bool evict, bool no_wait_gpu, + struct ttm_mem_reg *new_mem, + struct ttm_mem_reg *old_mem) +{ + struct amdgpu_device *adev = amdgpu_get_adev(bo->bdev); + struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; + + struct drm_mm_node *old_mm, *new_mm; + uint64_t old_start, old_size, new_start, new_size; + unsigned long num_pages; + struct fence *fence = NULL; + int r; + + BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0); + if (!ring->ready) { DRM_ERROR("Trying to move memory with ring turned off.\n"); return -EINVAL; } - BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0); + old_mm = old_mem->mm_node; + r = amdgpu_mm_node_addr(bo, old_mm, old_mem, &old_start); + if (r) + return r; + old_size = old_mm->size; + - r = amdgpu_copy_buffer(ring, old_start, new_start, - new_mem->num_pages * PAGE_SIZE, /* bytes */ - bo->resv, &fence, false); + new_mm = new_mem->mm_node; + r = amdgpu_mm_node_addr(bo, new_mm, new_mem, &new_start); if (r) return r; + new_size = new_mm->size; + + num_pages = new_mem->num_pages; + while (num_pages) { + unsigned long cur_pages = min(old_size, new_size); + struct fence *next; + + r = amdgpu_copy_buffer(ring, old_start, new_start, + cur_pages * PAGE_SIZE, + bo->resv, &next, false); + if (r) + goto error; + + fence_put(fence); + fence = next; + + num_pages -= cur_pages; + if (!num_pages) + break; + + old_size -= cur_pages; + if (!old_size) { + r = amdgpu_mm_node_addr(bo, ++old_mm, old_mem, + &old_start); + if (r) + goto error; + old_size = old_mm->size; + } else { + old_start += cur_pages * PAGE_SIZE; + } + + new_size -= cur_pages; + if (!new_size) { + r = amdgpu_mm_node_addr(bo, ++new_mm, new_mem, + &new_start); + if (r) + goto error; + + new_size = new_mm->size; + } else { + new_start += cur_pages * PAGE_SIZE; + } + } r = ttm_bo_pipeline_move(bo, fence, evict, new_mem); fence_put(fence); return r; + +error: + if (fence) + fence_wait(fence, false); + fence_put(fence); + return r; } static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, -- cgit v1.2.3 From 6a7f76e70fac0b1d41e7c5e193c33b1ee7e902c6 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 24 Aug 2016 15:51:49 +0200 Subject: drm/amdgpu: add VRAM manager v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split VRAM allocations into 4MB blocks. v2: fix typo in comment, some suggested cleanups v3: document how to disable the feature, fix rebase issue Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 222 +++++++++++++++++++++++++++ 7 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 248a05d02917..41bd2bf28f4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -24,7 +24,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ - amdgpu_gtt_mgr.o + amdgpu_gtt_mgr.o amdgpu_vram_mgr.o # add asic specific block amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 039b57e4644c..1296f5967bd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -97,6 +97,7 @@ extern char *amdgpu_disable_cu; extern int amdgpu_sclk_deep_sleep_en; extern char *amdgpu_virtual_display; extern unsigned amdgpu_pp_feature_mask; +extern int amdgpu_vram_page_split; #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 #define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 246bbd1ab5ec..9df66d1e843d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1052,6 +1052,13 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev) amdgpu_vm_block_size); amdgpu_vm_block_size = 9; } + + if ((amdgpu_vram_page_split != -1 && amdgpu_vram_page_split < 16) || + !amdgpu_check_pot_argument(amdgpu_vram_page_split)) { + dev_warn(adev->dev, "invalid VRAM page split (%d)\n", + amdgpu_vram_page_split); + amdgpu_vram_page_split = 1024; + } } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 2201f05ecc94..528d6531dd49 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -85,6 +85,7 @@ int amdgpu_vm_size = 64; int amdgpu_vm_block_size = -1; int amdgpu_vm_fault_stop = 0; int amdgpu_vm_debug = 0; +int amdgpu_vram_page_split = 1024; int amdgpu_exp_hw_support = 0; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; @@ -165,6 +166,9 @@ module_param_named(vm_fault_stop, amdgpu_vm_fault_stop, int, 0444); MODULE_PARM_DESC(vm_debug, "Debug VM handling (0 = disabled (default), 1 = enabled)"); module_param_named(vm_debug, amdgpu_vm_debug, int, 0644); +MODULE_PARM_DESC(vram_page_split, "Number of pages after we split VRAM allocations (default 1024, -1 = disable)"); +module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444); + MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))"); module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1427c40c70bb..f757f68418b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -168,7 +168,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, break; case TTM_PL_VRAM: /* "On-card" video ram */ - man->func = &ttm_bo_manager_func; + man->func = &amdgpu_vram_mgr_func; man->gpu_offset = adev->mc.vram_start; man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 9812c805326c..d1c00c04782f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -66,6 +66,7 @@ struct amdgpu_mman { }; extern const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; +extern const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, struct ttm_buffer_object *tbo, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c new file mode 100644 index 000000000000..180eed7c8bca --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -0,0 +1,222 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ + +#include +#include "amdgpu.h" + +struct amdgpu_vram_mgr { + struct drm_mm mm; + spinlock_t lock; +}; + +/** + * amdgpu_vram_mgr_init - init VRAM manager and DRM MM + * + * @man: TTM memory type manager + * @p_size: maximum size of VRAM + * + * Allocate and initialize the VRAM manager. + */ +static int amdgpu_vram_mgr_init(struct ttm_mem_type_manager *man, + unsigned long p_size) +{ + struct amdgpu_vram_mgr *mgr; + + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + if (!mgr) + return -ENOMEM; + + drm_mm_init(&mgr->mm, 0, p_size); + spin_lock_init(&mgr->lock); + man->priv = mgr; + return 0; +} + +/** + * amdgpu_vram_mgr_fini - free and destroy VRAM manager + * + * @man: TTM memory type manager + * + * Destroy and free the VRAM manager, returns -EBUSY if ranges are still + * allocated inside it. + */ +static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man) +{ + struct amdgpu_vram_mgr *mgr = man->priv; + + spin_lock(&mgr->lock); + if (!drm_mm_clean(&mgr->mm)) { + spin_unlock(&mgr->lock); + return -EBUSY; + } + + drm_mm_takedown(&mgr->mm); + spin_unlock(&mgr->lock); + kfree(mgr); + man->priv = NULL; + return 0; +} + +/** + * amdgpu_vram_mgr_new - allocate new ranges + * + * @man: TTM memory type manager + * @tbo: TTM BO we need this range for + * @place: placement flags and restrictions + * @mem: the resulting mem object + * + * Allocate VRAM for the given BO. + */ +static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, + struct ttm_buffer_object *tbo, + const struct ttm_place *place, + struct ttm_mem_reg *mem) +{ + struct amdgpu_bo *bo = container_of(tbo, struct amdgpu_bo, tbo); + struct amdgpu_vram_mgr *mgr = man->priv; + struct drm_mm *mm = &mgr->mm; + struct drm_mm_node *nodes; + enum drm_mm_search_flags sflags = DRM_MM_SEARCH_DEFAULT; + enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT; + unsigned long lpfn, num_nodes, pages_per_node, pages_left; + unsigned i; + int r; + + lpfn = place->lpfn; + if (!lpfn) + lpfn = man->size; + + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS || + amdgpu_vram_page_split == -1) { + pages_per_node = ~0ul; + num_nodes = 1; + } else { + pages_per_node = max((uint32_t)amdgpu_vram_page_split, + mem->page_alignment); + num_nodes = DIV_ROUND_UP(mem->num_pages, pages_per_node); + } + + nodes = kcalloc(num_nodes, sizeof(*nodes), GFP_KERNEL); + if (!nodes) + return -ENOMEM; + + if (place->flags & TTM_PL_FLAG_TOPDOWN) { + sflags = DRM_MM_SEARCH_BELOW; + aflags = DRM_MM_CREATE_TOP; + } + + pages_left = mem->num_pages; + + spin_lock(&mgr->lock); + for (i = 0; i < num_nodes; ++i) { + unsigned long pages = min(pages_left, pages_per_node); + uint32_t alignment = mem->page_alignment; + + if (pages == pages_per_node) + alignment = pages_per_node; + else + sflags |= DRM_MM_SEARCH_BEST; + + r = drm_mm_insert_node_in_range_generic(mm, &nodes[i], pages, + alignment, 0, + place->fpfn, lpfn, + sflags, aflags); + if (unlikely(r)) + goto error; + + pages_left -= pages; + } + spin_unlock(&mgr->lock); + + mem->start = num_nodes == 1 ? nodes[0].start : AMDGPU_BO_INVALID_OFFSET; + mem->mm_node = nodes; + + return 0; + +error: + while (i--) + drm_mm_remove_node(&nodes[i]); + spin_unlock(&mgr->lock); + + kfree(nodes); + return r == -ENOSPC ? 0 : r; +} + +/** + * amdgpu_vram_mgr_del - free ranges + * + * @man: TTM memory type manager + * @tbo: TTM BO we need this range for + * @place: placement flags and restrictions + * @mem: TTM memory object + * + * Free the allocated VRAM again. + */ +static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man, + struct ttm_mem_reg *mem) +{ + struct amdgpu_vram_mgr *mgr = man->priv; + struct drm_mm_node *nodes = mem->mm_node; + unsigned pages = mem->num_pages; + + if (!mem->mm_node) + return; + + spin_lock(&mgr->lock); + while (pages) { + pages -= nodes->size; + drm_mm_remove_node(nodes); + ++nodes; + } + spin_unlock(&mgr->lock); + + kfree(mem->mm_node); + mem->mm_node = NULL; +} + +/** + * amdgpu_vram_mgr_debug - dump VRAM table + * + * @man: TTM memory type manager + * @prefix: text prefix + * + * Dump the table content using printk. + */ +static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man, + const char *prefix) +{ + struct amdgpu_vram_mgr *mgr = man->priv; + + spin_lock(&mgr->lock); + drm_mm_debug_table(&mgr->mm, prefix); + spin_unlock(&mgr->lock); +} + +const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = { + amdgpu_vram_mgr_init, + amdgpu_vram_mgr_fini, + amdgpu_vram_mgr_new, + amdgpu_vram_mgr_del, + amdgpu_vram_mgr_debug +}; -- cgit v1.2.3 From e0adf6c86ceb717132bfb1aec298a308663bb853 Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Thu, 29 Sep 2016 09:39:10 +0800 Subject: drm/amd/amdgpu: unify memory query info interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Junwei Zhang Reviewed-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 54 +++++++++++++++++---------------- include/uapi/drm/amdgpu_drm.h | 38 +++++++++++++++-------- 2 files changed, 54 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 09b94901faec..1ecfe9a046ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -411,32 +411,34 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file return copy_to_user(out, &vram_gtt, min((size_t)size, sizeof(vram_gtt))) ? -EFAULT : 0; } - case AMDGPU_INFO_VRAM_GTT_TOTAL: { - struct drm_amdgpu_info_vram_gtt_total vram_gtt_total; - - vram_gtt_total.vram_total_size = adev->mc.real_vram_size; - vram_gtt_total.vram_cpu_accessible_total_size = adev->mc.visible_vram_size; - vram_gtt_total.gtt_total_size = adev->mc.gtt_size; - return copy_to_user(out, &vram_gtt_total, - min((size_t)size, sizeof(vram_gtt_total))) - ? -EFAULT : 0; - } - case AMDGPU_INFO_VRAM_GTT_MAX: { - struct drm_amdgpu_info_vram_gtt_max vram_gtt_max; - u64 max_size; - - max_size = adev->mc.real_vram_size - adev->vram_pin_size; - vram_gtt_max.vram_max_size = max_size * 3 / 4; - - max_size = adev->mc.visible_vram_size - (adev->vram_pin_size - - adev->invisible_pin_size); - vram_gtt_max.vram_cpu_accessible_max_size = max_size * 3 / 4; - - max_size = adev->mc.gtt_size - adev->gart_pin_size; - vram_gtt_max.gtt_max_size = max_size * 3 / 4; - - return copy_to_user(out, &vram_gtt_max, - min((size_t)size, sizeof(vram_gtt_max))) + case AMDGPU_INFO_MEMORY: { + struct drm_amdgpu_memory_info mem; + + memset(&mem, 0, sizeof(mem)); + mem.vram.total_heap_size = adev->mc.real_vram_size; + mem.vram.usable_heap_size = + adev->mc.real_vram_size - adev->vram_pin_size; + mem.vram.heap_usage = atomic64_read(&adev->vram_usage); + mem.vram.max_allocation = mem.vram.usable_heap_size * 3 / 4; + + mem.cpu_accessible_vram.total_heap_size = + adev->mc.visible_vram_size; + mem.cpu_accessible_vram.usable_heap_size = + adev->mc.visible_vram_size - + (adev->vram_pin_size - adev->invisible_pin_size); + mem.cpu_accessible_vram.heap_usage = + atomic64_read(&adev->vram_vis_usage); + mem.cpu_accessible_vram.max_allocation = + mem.cpu_accessible_vram.usable_heap_size * 3 / 4; + + mem.gtt.total_heap_size = adev->mc.gtt_size; + mem.gtt.usable_heap_size = + adev->mc.gtt_size - adev->gart_pin_size; + mem.gtt.heap_usage = atomic64_read(&adev->gtt_usage); + mem.gtt.max_allocation = mem.gtt.usable_heap_size * 3 / 4; + + return copy_to_user(out, &mem, + min((size_t)size, sizeof(mem))) ? -EFAULT : 0; } case AMDGPU_INFO_READ_MMR_REG: { diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 6491e8b9a309..b6a04d48f457 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -489,10 +489,8 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_VIS_VRAM_USAGE 0x17 /* number of TTM buffer evictions */ #define AMDGPU_INFO_NUM_EVICTIONS 0x18 -/* Query the total size of VRAM and GTT domains */ -#define AMDGPU_INFO_VRAM_GTT_TOTAL 0x19 -/* Query the max allocation size of VRAM and GTT domains */ -#define AMDGPU_INFO_VRAM_GTT_MAX 0x1a +/* Query memory about VRAM and GTT domains */ +#define AMDGPU_INFO_MEMORY 0x19 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0 #define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff @@ -578,16 +576,32 @@ struct drm_amdgpu_info_vram_gtt { __u64 gtt_size; }; -struct drm_amdgpu_info_vram_gtt_total { - __u64 vram_total_size; - __u64 vram_cpu_accessible_total_size; - __u64 gtt_total_size; +struct drm_amdgpu_heap_info { + /** max. physical memory */ + __u64 total_heap_size; + + /** Theoretical max. available memory in the given heap */ + __u64 usable_heap_size; + + /** + * Number of bytes allocated in the heap. This includes all processes + * and private allocations in the kernel. It changes when new buffers + * are allocated, freed, and moved. It cannot be larger than + * heap_size. + */ + __u64 heap_usage; + + /** + * Theoretical possible max. size of buffer which + * could be allocated in the given heap + */ + __u64 max_allocation; }; -struct drm_amdgpu_info_vram_gtt_max { - __u64 vram_max_size; - __u64 vram_cpu_accessible_max_size; - __u64 gtt_max_size; +struct drm_amdgpu_memory_info { + struct drm_amdgpu_heap_info vram; + struct drm_amdgpu_heap_info cpu_accessible_vram; + struct drm_amdgpu_heap_info gtt; }; struct drm_amdgpu_info_firmware { -- cgit v1.2.3 From ef704318d351b89ca3f1e8b36f48aeb26fd80f69 Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Wed, 28 Sep 2016 13:27:15 +0800 Subject: drm/amd/amdgpu: bump version for memory query info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Junwei Zhang Reviewed-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 528d6531dd49..a113a432d3a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -58,9 +58,10 @@ * - 3.6.0 - kmd involves use CONTEXT_CONTROL in ring buffer. * - 3.7.0 - Add support for VCE clock list packet * - 3.8.0 - Add support raster config init in the kernel + * - 3.9.0 - Add support for memory query info about VRAM and GTT. */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 8 +#define KMS_DRIVER_MINOR 9 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; -- cgit v1.2.3 From 297b12862d738f82c9f82b9b0f6df80dc447189a Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Fri, 30 Sep 2016 16:13:01 +0800 Subject: drm/radeon: add missing header dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get a few warnings when building kernel with W=1: drivers/gpu/drm/radeon/radeon_clocks.c:35:10: warning: no previous prototype for 'radeon_legacy_get_engine_clock' [-Wmissing-prototypes] drivers/gpu/drm/radeon/atombios_encoders.c:75:1: warning: no previous prototype for 'atombios_get_backlight_level' [-Wmissing-prototypes] drivers/gpu/drm/radeon/r600_cs.c:2268:5: warning: no previous prototype for 'r600_cs_parse' [-Wmissing-prototypes] drivers/gpu/drm/radeon/evergreen_cs.c:2671:5: warning: no previous prototype for 'evergreen_cs_parse' [-Wmissing-prototypes] .... In fact, these functions are declared in drivers/gpu/drm/radeon/radeon_asic.h, so this patch adds missing header dependencies. Reviewed-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_encoders.c | 1 + drivers/gpu/drm/radeon/evergreen_cs.c | 1 + drivers/gpu/drm/radeon/r600_cs.c | 1 + drivers/gpu/drm/radeon/radeon_atombios.c | 1 + drivers/gpu/drm/radeon/radeon_clocks.c | 1 + drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 1 + 6 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 56bb758f4e33..fa4f8f008e4d 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -28,6 +28,7 @@ #include #include "radeon.h" #include "radeon_audio.h" +#include "radeon_asic.h" #include "atom.h" #include diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index d960d3915408..f8b05090232a 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -27,6 +27,7 @@ */ #include #include "radeon.h" +#include "radeon_asic.h" #include "evergreend.h" #include "evergreen_reg_safe.h" #include "cayman_reg_safe.h" diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index b69c8de35bd3..595a19736458 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -28,6 +28,7 @@ #include #include #include "radeon.h" +#include "radeon_asic.h" #include "r600d.h" #include "r600_reg_safe.h" diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 5df3ec73021b..4134759a6823 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -29,6 +29,7 @@ #include "atom.h" #include "atom-bits.h" +#include "radeon_asic.h" extern void radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 38e396dae0a9..c1135feb93c1 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -29,6 +29,7 @@ #include #include "radeon_reg.h" #include "radeon.h" +#include "radeon_asic.h" #include "atom.h" /* 10 khz */ diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 868c3ba2efaa..222a1fa41d7c 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -27,6 +27,7 @@ #include #include #include "radeon.h" +#include "radeon_asic.h" #include "atom.h" #include #ifdef CONFIG_PMAC_BACKLIGHT -- cgit v1.2.3 From 22e5808ebae9bca33bdefc7e4d9e5e48a2f1c9ab Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Fri, 30 Sep 2016 16:13:02 +0800 Subject: drm/radeon: mark symbols static where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get 4 warnings when building kernel with W=1: drivers/gpu/drm/radeon/si.c:7850:5: warning: no previous prototype for 'si_vce_send_vcepll_ctlreq' [-Wmissing-prototypes] drivers/gpu/drm/radeon/radeon_dp_mst.c:226:21: warning: no previous prototype for 'radeon_mst_best_encoder' [-Wmissing-prototypes] drivers/gpu/drm/radeon/radeon_dp_mst.c:344:26: warning: no previous prototype for 'radeon_mst_find_connector' [-Wmissing-prototypes] drivers/gpu/drm/radeon/radeon_dp_mst.c:600:6: warning: no previous prototype for 'radeon_dp_mst_encoder_destroy' [-Wmissing-prototypes] In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. So this patch marks these functions with 'static'. Reviewed-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_dp_mst.c | 8 +++++--- drivers/gpu/drm/radeon/si.c | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index de504ea29c06..6d1237d6e1b8 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -223,7 +223,8 @@ radeon_dp_mst_mode_valid(struct drm_connector *connector, return MODE_OK; } -struct drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector) +static struct +drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -341,7 +342,8 @@ const struct drm_dp_mst_topology_cbs mst_cbs = { .hotplug = radeon_dp_mst_hotplug, }; -struct radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder) +static struct +radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct drm_connector *connector; @@ -597,7 +599,7 @@ static const struct drm_encoder_helper_funcs radeon_mst_helper_funcs = { .commit = radeon_mst_encoder_commit, }; -void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder) +static void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder) { drm_encoder_cleanup(encoder); kfree(encoder); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index e402be8821c4..143280dc0851 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -7858,7 +7858,7 @@ static void si_program_aspm(struct radeon_device *rdev) } } -int si_vce_send_vcepll_ctlreq(struct radeon_device *rdev) +static int si_vce_send_vcepll_ctlreq(struct radeon_device *rdev) { unsigned i; -- cgit v1.2.3 From f8a4c11b0a33f98212f39a6882d46dfb7b33a006 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Fri, 30 Sep 2016 17:58:42 +0800 Subject: drm/amd/powerplay: mark symbols static where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get a few warnings when building kernel with W=1: drivers/gpu/drm/amd/amdgpu/../powerplay/smumgr/fiji_smumgr.c:162:5: warning: no previous prototype for 'fiji_setup_pwr_virus' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/../powerplay/smumgr/fiji_smc.c:2052:5: warning: no previous prototype for 'fiji_program_mem_timing_parameters' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/../powerplay/smumgr/polaris10_smumgr.c:175:5: warning: no previous prototype for 'polaris10_avfs_event_mgr' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/../powerplay/hwmgr/cz_hwmgr.c:69:10: warning: no previous prototype for 'cz_get_eclk_level' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/../powerplay/hwmgr/smu7_hwmgr.c:92:26: warning: no previous prototype for 'cast_phw_smu7_power_state' [-Wmissing-prototypes] .... In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. So this patch marks these functions with 'static'. Acked-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 5 ++- drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 12 +++--- .../amd/powerplay/hwmgr/process_pptables_v1_0.c | 6 +-- .../gpu/drm/amd/powerplay/hwmgr/processpptables.c | 4 +- .../amd/powerplay/hwmgr/smu7_clockpowergating.c | 10 ++--- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 45 ++++++++++++---------- drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c | 2 +- drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c | 12 +++--- .../drm/amd/powerplay/smumgr/polaris10_smumgr.c | 5 ++- 9 files changed, 54 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 7174f7a68266..bb8a345c750a 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -436,7 +436,8 @@ static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state) } } -int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output) +static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, + void *input, void *output) { int ret = 0; struct pp_instance *pp_handle; @@ -475,7 +476,7 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, return ret; } -enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) +static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) { struct pp_hwmgr *hwmgr; struct pp_power_state *state; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 960424913496..4b14f259a147 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -66,7 +66,7 @@ static const struct cz_power_state *cast_const_PhwCzPowerState( return (struct cz_power_state *)hw_ps; } -uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr, +static uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr, uint32_t clock, uint32_t msg) { int i = 0; @@ -1017,7 +1017,7 @@ static int cz_tf_program_bootup_state(struct pp_hwmgr *hwmgr, void *input, return 0; } -int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input, +static int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -1225,7 +1225,7 @@ static int cz_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) return 0; } -int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr) +static int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -1239,7 +1239,7 @@ int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr) return 0; } -int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +static int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); struct phm_clock_voltage_dependency_table *table = @@ -1277,7 +1277,7 @@ int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr) return 0; } -int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr) +static int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -1533,7 +1533,7 @@ static int cz_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr, return result; } -int cz_get_power_state_size(struct pp_hwmgr *hwmgr) +static int cz_get_power_state_size(struct pp_hwmgr *hwmgr) { return sizeof(struct cz_power_state); } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c index 7de701d8a450..155cd0dfe0c5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c @@ -131,7 +131,7 @@ static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) /** * Private Function to get the PowerPlay Table Address. */ -const void *get_powerplay_table(struct pp_hwmgr *hwmgr) +static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) { int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); @@ -1049,7 +1049,7 @@ static int check_powerplay_tables( return 0; } -int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr) +static int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr) { int result = 0; const ATOM_Tonga_POWERPLAYTABLE *powerplay_table; @@ -1100,7 +1100,7 @@ int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr) return result; } -int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr) +static int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr) { struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c index ccf7ebeaf892..bd1f19010315 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c @@ -1507,7 +1507,7 @@ static int init_phase_shedding_table(struct pp_hwmgr *hwmgr, return 0; } -int get_number_of_vce_state_table_entries( +static int get_number_of_vce_state_table_entries( struct pp_hwmgr *hwmgr) { const ATOM_PPLIB_POWERPLAYTABLE *table = @@ -1521,7 +1521,7 @@ int get_number_of_vce_state_table_entries( return 0; } -int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, +static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, unsigned long i, struct pp_vce_state *vce_state, void **clock_info, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c index 6eb6db199250..f5a58d489b4b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c @@ -75,7 +75,7 @@ int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr) return 0; } -int smu7_powerup_uvd(struct pp_hwmgr *hwmgr) +static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr) { if (phm_cf_want_uvd_power_gating(hwmgr)) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, @@ -91,7 +91,7 @@ int smu7_powerup_uvd(struct pp_hwmgr *hwmgr) return 0; } -int smu7_powerdown_vce(struct pp_hwmgr *hwmgr) +static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr) { if (phm_cf_want_vce_power_gating(hwmgr)) return smum_send_msg_to_smc(hwmgr->smumgr, @@ -99,7 +99,7 @@ int smu7_powerdown_vce(struct pp_hwmgr *hwmgr) return 0; } -int smu7_powerup_vce(struct pp_hwmgr *hwmgr) +static int smu7_powerup_vce(struct pp_hwmgr *hwmgr) { if (phm_cf_want_vce_power_gating(hwmgr)) return smum_send_msg_to_smc(hwmgr->smumgr, @@ -107,7 +107,7 @@ int smu7_powerup_vce(struct pp_hwmgr *hwmgr) return 0; } -int smu7_powerdown_samu(struct pp_hwmgr *hwmgr) +static int smu7_powerdown_samu(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SamuPowerGating)) @@ -116,7 +116,7 @@ int smu7_powerdown_samu(struct pp_hwmgr *hwmgr) return 0; } -int smu7_powerup_samu(struct pp_hwmgr *hwmgr) +static int smu7_powerup_samu(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SamuPowerGating)) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 609996c84ad5..173f9f3f2068 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -89,7 +89,7 @@ enum DPM_EVENT_SRC { static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic); -struct smu7_power_state *cast_phw_smu7_power_state( +static struct smu7_power_state *cast_phw_smu7_power_state( struct pp_hw_power_state *hw_ps) { PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic), @@ -99,7 +99,7 @@ struct smu7_power_state *cast_phw_smu7_power_state( return (struct smu7_power_state *)hw_ps; } -const struct smu7_power_state *cast_const_phw_smu7_power_state( +static const struct smu7_power_state *cast_const_phw_smu7_power_state( const struct pp_hw_power_state *hw_ps) { PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic), @@ -115,7 +115,7 @@ const struct smu7_power_state *cast_const_phw_smu7_power_state( * @param hwmgr the address of the powerplay hardware manager. * @return always 0 */ -int smu7_get_mc_microcode_version (struct pp_hwmgr *hwmgr) +static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr) { cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F); @@ -124,7 +124,7 @@ int smu7_get_mc_microcode_version (struct pp_hwmgr *hwmgr) return 0; } -uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr) +static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr) { uint32_t speedCntl = 0; @@ -135,7 +135,7 @@ uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr) PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE)); } -int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) +static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) { uint32_t link_width; @@ -155,7 +155,7 @@ int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) * @param pHwMgr the address of the powerplay hardware manager. * @return always PP_Result_OK */ -int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) +static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) { if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK) smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Enable); @@ -802,7 +802,7 @@ static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr) return 0; } -int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) +static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -1153,7 +1153,7 @@ static int smu7_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); } -int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr) +static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); data->pcie_performance_request = true; @@ -1161,7 +1161,7 @@ int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr) return 0; } -int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) { int tmp_result = 0; int result = 0; @@ -1864,7 +1864,7 @@ static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr) return 0; } -int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr) +static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr) { struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2253,7 +2253,7 @@ static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr) return 0; } -int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data; int result; @@ -3672,14 +3672,16 @@ static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm); } -int smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) +static int +smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) { PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ? 0 : -1; } -int smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) +static int +smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) { uint32_t num_active_displays = 0; struct cgs_display_info info = {0}; @@ -3701,7 +3703,7 @@ int smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) * @param hwmgr the address of the powerplay hardware manager. * @return always OK */ -int smu7_program_display_gap(struct pp_hwmgr *hwmgr) +static int smu7_program_display_gap(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); uint32_t num_active_displays = 0; @@ -3751,7 +3753,7 @@ int smu7_program_display_gap(struct pp_hwmgr *hwmgr) return 0; } -int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr) { return smu7_program_display_gap(hwmgr); } @@ -3775,13 +3777,14 @@ static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm); } -int smu7_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr, +static int smu7_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *thermal_interrupt_info) { return 0; } -bool smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +static bool +smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); bool is_update_required = false; @@ -3810,7 +3813,9 @@ static inline bool smu7_are_power_levels_equal(const struct smu7_performance_lev (pl1->pcie_lane == pl2->pcie_lane)); } -int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal) +static int smu7_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, bool *equal) { const struct smu7_power_state *psa; const struct smu7_power_state *psb; @@ -3843,7 +3848,7 @@ int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_sta return 0; } -int smu7_upload_mc_firmware(struct pp_hwmgr *hwmgr) +static int smu7_upload_mc_firmware(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -3972,7 +3977,7 @@ static int smu7_init_sclk_threshold(struct pp_hwmgr *hwmgr) return 0; } -int smu7_setup_asic_task(struct pp_hwmgr *hwmgr) +static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr) { int tmp_result, result = 0; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c index 76310ac7ef0d..e7e8944ba8b2 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c @@ -2049,7 +2049,7 @@ int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) return 0; } -int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c index 02fe1df855a9..b86e48fb40d1 100755 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c @@ -159,7 +159,7 @@ static int fiji_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr) return result; } -int fiji_setup_pwr_virus(struct pp_smumgr *smumgr) +static int fiji_setup_pwr_virus(struct pp_smumgr *smumgr) { int i, result = -1; uint32_t reg, data; @@ -224,7 +224,7 @@ static int fiji_start_avfs_btc(struct pp_smumgr *smumgr) return result; } -int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr) +static int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr) { int result = 0; uint32_t table_start; @@ -260,7 +260,7 @@ int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr) return result; } -int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) +static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) { int32_t vr_config; uint32_t table_start; @@ -299,7 +299,7 @@ int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) } /* Work in Progress */ -int fiji_restore_vft_table(struct pp_smumgr *smumgr) +static int fiji_restore_vft_table(struct pp_smumgr *smumgr) { struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); @@ -311,7 +311,7 @@ int fiji_restore_vft_table(struct pp_smumgr *smumgr) } /* Work in Progress */ -int fiji_save_vft_table(struct pp_smumgr *smumgr) +static int fiji_save_vft_table(struct pp_smumgr *smumgr) { struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); @@ -322,7 +322,7 @@ int fiji_save_vft_table(struct pp_smumgr *smumgr) return -EINVAL; } -int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) +static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) { struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index 5c3598ab7dae..f38a68747df0 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -118,7 +118,7 @@ static int polaris10_perform_btc(struct pp_smumgr *smumgr) } -int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) +static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) { uint32_t vr_config; uint32_t dpm_table_start; @@ -172,7 +172,8 @@ int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) return 0; } -int polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT) +static int +polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT) { struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); -- cgit v1.2.3 From e1d99217d02c52e141d61491f91160a9e6bd8fe7 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Wed, 27 Apr 2016 19:07:18 +0800 Subject: drm/amdgpu:add one more fiji device id Signed-off-by: Frank Min Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index a113a432d3a4..6bb4d9e9afe4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -387,6 +387,7 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x6939, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA}, /* fiji */ {0x1002, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_FIJI}, + {0x1002, 0x730F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_FIJI}, /* carrizo */ {0x1002, 0x9870, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU}, {0x1002, 0x9874, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU}, -- cgit v1.2.3 From 4bc10d168a419dc07194fdb93ccc4c8cad1788e4 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Tue, 29 Mar 2016 11:01:51 +0800 Subject: drm/amdgpu:use smc_index_11 for VI for VI smc, index_0 to index_8 are all not safe, they may used by BIOS/FW, and index_11 is reserved only for driver. Signed-off-by: Monk Liu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 16 ++++++++-------- drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h | 2 ++ drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h | 2 ++ drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h | 2 ++ drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h | 2 -- 5 files changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index c0d9aad7126f..ea3331c40391 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -121,8 +121,8 @@ static u32 vi_smc_rreg(struct amdgpu_device *adev, u32 reg) u32 r; spin_lock_irqsave(&adev->smc_idx_lock, flags); - WREG32(mmSMC_IND_INDEX_0, (reg)); - r = RREG32(mmSMC_IND_DATA_0); + WREG32(mmSMC_IND_INDEX_11, (reg)); + r = RREG32(mmSMC_IND_DATA_11); spin_unlock_irqrestore(&adev->smc_idx_lock, flags); return r; } @@ -132,8 +132,8 @@ static void vi_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v) unsigned long flags; spin_lock_irqsave(&adev->smc_idx_lock, flags); - WREG32(mmSMC_IND_INDEX_0, (reg)); - WREG32(mmSMC_IND_DATA_0, (v)); + WREG32(mmSMC_IND_INDEX_11, (reg)); + WREG32(mmSMC_IND_DATA_11, (v)); spin_unlock_irqrestore(&adev->smc_idx_lock, flags); } @@ -437,12 +437,12 @@ static bool vi_read_bios_from_rom(struct amdgpu_device *adev, /* take the smc lock since we are using the smc index */ spin_lock_irqsave(&adev->smc_idx_lock, flags); /* set rom index to 0 */ - WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX); - WREG32(mmSMC_IND_DATA_0, 0); + WREG32(mmSMC_IND_INDEX_11, ixROM_INDEX); + WREG32(mmSMC_IND_DATA_11, 0); /* set index to data for continous read */ - WREG32(mmSMC_IND_INDEX_0, ixROM_DATA); + WREG32(mmSMC_IND_INDEX_11, ixROM_DATA); for (i = 0; i < length_dw; i++) - dw_ptr[i] = RREG32(mmSMC_IND_DATA_0); + dw_ptr[i] = RREG32(mmSMC_IND_DATA_11); spin_unlock_irqrestore(&adev->smc_idx_lock, flags); return true; diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h index 3014d4a58c43..a9ef1562f43b 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h +++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h @@ -176,6 +176,8 @@ #define mmSMU1_SMU_SMC_IND_DATA 0x83 #define mmSMU2_SMU_SMC_IND_DATA 0x85 #define mmSMU3_SMU_SMC_IND_DATA 0x87 +#define mmSMC_IND_INDEX_11 0x1AC +#define mmSMC_IND_DATA_11 0x1AD #define ixRCU_UC_EVENTS 0xc0000004 #define ixRCU_MISC_CTRL 0xc0000010 #define ixCC_RCU_FUSES 0xc00c0000 diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h index 933917479985..22dd4c2b7290 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h +++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h @@ -87,6 +87,8 @@ #define mmSMC_IND_DATA_6 0x8d #define mmSMC_IND_INDEX_7 0x8e #define mmSMC_IND_DATA_7 0x8f +#define mmSMC_IND_INDEX_11 0x1AC +#define mmSMC_IND_DATA_11 0x1AD #define mmSMC_IND_ACCESS_CNTL 0x92 #define mmSMC_MESSAGE_0 0x94 #define mmSMC_RESP_0 0x95 diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h index 44b1855cb8df..eca2b851f25f 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h +++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h @@ -90,6 +90,8 @@ #define mmSMC_IND_DATA_6 0x8d #define mmSMC_IND_INDEX_7 0x8e #define mmSMC_IND_DATA_7 0x8f +#define mmSMC_IND_INDEX_11 0x1AC +#define mmSMC_IND_DATA_11 0x1AD #define mmSMC_IND_ACCESS_CNTL 0x92 #define mmSMC_MESSAGE_0 0x94 #define mmSMC_RESP_0 0x95 diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h index 76352f2423ae..919be435b49c 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h @@ -28,8 +28,6 @@ #include #define SMC_RAM_END 0x40000 -#define mmSMC_IND_INDEX_11 0x01AC -#define mmSMC_IND_DATA_11 0x01AD struct smu7_buffer_entry { uint32_t data_size; -- cgit v1.2.3 From 01ab960d49cdc8d7fbfa5a6f2b717f491927a776 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Wed, 27 Apr 2016 18:33:35 +0800 Subject: drm/amdgpu:keep bo pinned in prefered domain Signed-off-by: Frank Min Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index a61f4186a7dd..44f565465b09 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -242,7 +242,7 @@ static int amdgpu_cgs_gmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h r = amdgpu_bo_reserve(obj, false); if (unlikely(r != 0)) return r; - r = amdgpu_bo_pin_restricted(obj, AMDGPU_GEM_DOMAIN_GTT, + r = amdgpu_bo_pin_restricted(obj, obj->prefered_domains, min_offset, max_offset, mcaddr); amdgpu_bo_unreserve(obj); return r; -- cgit v1.2.3 From f501a7e550015bc3170c24d18ba1a008e38bddbf Mon Sep 17 00:00:00 2001 From: Frank Min Date: Wed, 27 Apr 2016 20:02:57 +0800 Subject: drm/amdgpu:fw bo should be in VRAM for SRIOV for GTT memory SMC can only access it within PF space, which is not used for SRIOV case, thus for SRIOV case, we let SMC use FB space for ucode bo. Signed-off-by: Frank Min Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index cb3d252f3c78..b7b82a270420 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -247,7 +247,8 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) const struct common_firmware_header *header = NULL; err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true, - AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, bo); + amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, + 0, NULL, NULL, bo); if (err) { dev_err(adev->dev, "(%d) Firmware buffer allocate failed\n", err); goto failed; @@ -259,7 +260,8 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) goto failed_reserve; } - err = amdgpu_bo_pin(*bo, AMDGPU_GEM_DOMAIN_GTT, &fw_mc_addr); + err = amdgpu_bo_pin(*bo, amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, + &fw_mc_addr); if (err) { dev_err(adev->dev, "(%d) Firmware buffer pin failed\n", err); goto failed_pin; -- cgit v1.2.3 From ac00bbf32b02b74cf9ff1b9e861de9befaf00be5 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Wed, 27 Apr 2016 20:04:58 +0800 Subject: drm/amdgpu:add callback in cgs for sriov detect Signed-off-by: Frank Min Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 7 +++++++ drivers/gpu/drm/amd/include/cgs_common.h | 5 +++++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 44f565465b09..1950c25557de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -853,6 +853,12 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device, return 0; } +static int amdgpu_cgs_is_virtualization_enabled(void *cgs_device) +{ + CGS_FUNC_ADEV; + return amdgpu_sriov_vf(adev); +} + static int amdgpu_cgs_query_system_info(struct cgs_device *cgs_device, struct cgs_system_info *sys_info) { @@ -1206,6 +1212,7 @@ static const struct cgs_ops amdgpu_cgs_ops = { amdgpu_cgs_notify_dpm_enabled, amdgpu_cgs_call_acpi_method, amdgpu_cgs_query_system_info, + amdgpu_cgs_is_virtualization_enabled }; static const struct cgs_os_ops amdgpu_cgs_os_ops = { diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index df7c18b6a02a..9695c2ebd92a 100755 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -619,6 +619,8 @@ typedef int (*cgs_call_acpi_method)(struct cgs_device *cgs_device, typedef int (*cgs_query_system_info)(struct cgs_device *cgs_device, struct cgs_system_info *sys_info); +typedef int (*cgs_is_virtualization_enabled_t)(void *cgs_device); + struct cgs_ops { /* memory management calls (similar to KFD interface) */ cgs_gpu_mem_info_t gpu_mem_info; @@ -670,6 +672,7 @@ struct cgs_ops { cgs_call_acpi_method call_acpi_method; /* get system info */ cgs_query_system_info query_system_info; + cgs_is_virtualization_enabled_t is_virtualization_enabled; }; struct cgs_os_ops; /* To be define in OS-specific CGS header */ @@ -773,4 +776,6 @@ struct cgs_device CGS_CALL(get_pci_resource, cgs_device, resource_type, size, offset, \ resource_base) +#define cgs_is_virtualization_enabled(cgs_device) \ + CGS_CALL(is_virtualization_enabled, cgs_device) #endif /* _CGS_COMMON_H */ -- cgit v1.2.3 From bed5712e1a52bb5d177722bc0d76c2a3a71b8338 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Mon, 26 Sep 2016 16:35:03 +0800 Subject: drm/amdgpu:add MEC_STORAGE ucode id for sriov for sriov, SMC need MEC_STORAGE reserved in fw bo. Signed-off-by: Monk Liu Signed-off-by: Frank Min Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 8 ++++++++ drivers/gpu/drm/amd/include/cgs_common.h | 1 + drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c | 7 +++++++ 6 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 1950c25557de..e6b1bf3dc292 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -696,6 +696,9 @@ static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type) case CGS_UCODE_ID_RLC_G: result = AMDGPU_UCODE_ID_RLC_G; break; + case CGS_UCODE_ID_STORAGE: + result = AMDGPU_UCODE_ID_STORAGE; + break; default: DRM_ERROR("Firmware type not supported\n"); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index b7b82a270420..5d3f6ca742a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -228,6 +228,9 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_firmware_info *ucode, ucode->mc_addr = mc_addr; ucode->kaddr = kptr; + if (ucode->ucode_id == AMDGPU_UCODE_ID_STORAGE) + return 0; + header = (const struct common_firmware_header *)ucode->fw->data; memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data + le32_to_cpu(header->ucode_array_offset_bytes)), diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index e468be4e28fa..a8a4230729f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -130,6 +130,7 @@ enum AMDGPU_UCODE_ID { AMDGPU_UCODE_ID_CP_MEC1, AMDGPU_UCODE_ID_CP_MEC2, AMDGPU_UCODE_ID_RLC_G, + AMDGPU_UCODE_ID_STORAGE, AMDGPU_UCODE_ID_MAXIMUM, }; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index bd4d041717bf..45d194a58c57 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1058,6 +1058,14 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) adev->firmware.fw_size += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE); + if (amdgpu_sriov_vf(adev)) { + info = &adev->firmware.ucode[AMDGPU_UCODE_ID_STORAGE]; + info->ucode_id = AMDGPU_UCODE_ID_STORAGE; + info->fw = adev->gfx.mec_fw; + adev->firmware.fw_size += + ALIGN(le32_to_cpu(64 * PAGE_SIZE), PAGE_SIZE); + } + if (adev->gfx.mec2_fw) { info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2]; info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2; diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index 9695c2ebd92a..e4a1697ec1d3 100755 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -106,6 +106,7 @@ enum cgs_ucode_id { CGS_UCODE_ID_CP_MEC_JT2, CGS_UCODE_ID_GMCON_RENG, CGS_UCODE_ID_RLC_G, + CGS_UCODE_ID_STORAGE, CGS_UCODE_ID_MAXIMUM, }; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c index 6af744f42ec9..6df0d6edfdd1 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c @@ -278,6 +278,9 @@ enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type) case UCODE_ID_RLC_G: result = CGS_UCODE_ID_RLC_G; break; + case UCODE_ID_MEC_STORAGE: + result = CGS_UCODE_ID_STORAGE; + break; default: break; } @@ -452,6 +455,10 @@ int smu7_request_smu_load_fw(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); + if (cgs_is_virtualization_enabled(smumgr->device)) + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", return -EINVAL); smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, smu_data->header_buffer.mc_addr_high); smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, smu_data->header_buffer.mc_addr_low); -- cgit v1.2.3 From 4c2b2453ef9be2e105a987cd13cf3ce14e53f5e0 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Tue, 27 Sep 2016 16:39:58 +0800 Subject: drm/amdgpu:properly fix some JumpTable issues we found some MEC ucode leads to IB test fail or even ring test fail if Jump Table of it is not start in FW bo with page aligned address, fixed by always make JT address page aligned. we don't need to patch JT2 for MEC2, because for VI, MEC2 is a copy of MEC1, thus when converting fw_type for MEC_JT2 we just return MEC1,hw can use the same JT for both MEC1 & MEC2. above two change fixed some ring/ib test failure issue for some version of MEC ucode. Signed-off-by: Frank Min Signed-off-by: Monk Liu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 21 ++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 32 +++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 5 +++++ 3 files changed, 52 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index e6b1bf3dc292..34049d67a0d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -687,11 +687,14 @@ static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type) result = AMDGPU_UCODE_ID_CP_MEC1; break; case CGS_UCODE_ID_CP_MEC_JT2: - if (adev->asic_type == CHIP_TONGA || adev->asic_type == CHIP_POLARIS11 - || adev->asic_type == CHIP_POLARIS10) - result = AMDGPU_UCODE_ID_CP_MEC2; - else + /* for VI. JT2 should be the same as JT1, because: + 1, MEC2 and MEC1 use exactly same FW. + 2, JT2 is not pached but JT1 is. + */ + if (adev->asic_type >= CHIP_TOPAZ) result = AMDGPU_UCODE_ID_CP_MEC1; + else + result = AMDGPU_UCODE_ID_CP_MEC2; break; case CGS_UCODE_ID_RLC_G: result = AMDGPU_UCODE_ID_RLC_G; @@ -781,12 +784,18 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device, if ((type == CGS_UCODE_ID_CP_MEC_JT1) || (type == CGS_UCODE_ID_CP_MEC_JT2)) { - gpu_addr += le32_to_cpu(header->jt_offset) << 2; + gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE); data_size = le32_to_cpu(header->jt_size) << 2; } - info->mc_addr = gpu_addr; + + info->kptr = ucode->kaddr; info->image_size = data_size; + info->mc_addr = gpu_addr; info->version = (uint16_t)le32_to_cpu(header->header.ucode_version); + + if (CGS_UCODE_ID_CP_MEC == type) + info->image_size = (header->jt_offset) << 2; + info->fw_version = amdgpu_get_firmware_version(cgs_device, type); info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 5d3f6ca742a4..0f0b38191fac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -239,6 +239,31 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_firmware_info *ucode, return 0; } +static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode, + uint64_t mc_addr, void *kptr) +{ + const struct gfx_firmware_header_v1_0 *header = NULL; + const struct common_firmware_header *comm_hdr = NULL; + uint8_t* src_addr = NULL; + uint8_t* dst_addr = NULL; + + if (NULL == ucode->fw) + return 0; + + comm_hdr = (const struct common_firmware_header *)ucode->fw->data; + header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data; + dst_addr = ucode->kaddr + + ALIGN(le32_to_cpu(comm_hdr->ucode_size_bytes), + PAGE_SIZE); + src_addr = (uint8_t *)ucode->fw->data + + le32_to_cpu(comm_hdr->ucode_array_offset_bytes) + + (le32_to_cpu(header->jt_offset) * 4); + memcpy(dst_addr, src_addr, le32_to_cpu(header->jt_size) * 4); + + return 0; +} + + int amdgpu_ucode_init_bo(struct amdgpu_device *adev) { struct amdgpu_bo **bo = &adev->firmware.fw_buf; @@ -284,6 +309,13 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) header = (const struct common_firmware_header *)ucode->fw->data; amdgpu_ucode_init_single_fw(ucode, fw_mc_addr + fw_offset, fw_buf_ptr + fw_offset); + if (i == AMDGPU_UCODE_ID_CP_MEC1) { + const struct gfx_firmware_header_v1_0 *cp_hdr; + cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data; + amdgpu_ucode_patch_jt(ucode, fw_mc_addr + fw_offset, + fw_buf_ptr + fw_offset); + fw_offset += ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE); + } fw_offset += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE); } } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 45d194a58c57..0637349f9b65 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1058,6 +1058,11 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) adev->firmware.fw_size += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE); + /* we need account JT in */ + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; + adev->firmware.fw_size += + ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE); + if (amdgpu_sriov_vf(adev)) { info = &adev->firmware.ucode[AMDGPU_UCODE_ID_STORAGE]; info->ucode_id = AMDGPU_UCODE_ID_STORAGE; -- cgit v1.2.3 From 42e8cb5001d317ebbfcd95af26f263af377ff3a5 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Wed, 27 Apr 2016 19:44:56 +0800 Subject: drm/amdgpu:wptr poll address of gfx8 is needed for GFX8, gfx ring's wptr_addr is needed by SRIOV & CP for polling. Signed-off-by: Frank Min Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 0637349f9b65..ba36db8002e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4346,7 +4346,7 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev) struct amdgpu_ring *ring; u32 tmp; u32 rb_bufsz; - u64 rb_addr, rptr_addr; + u64 rb_addr, rptr_addr, wptr_gpu_addr; int r; /* Set the write pointer delay */ @@ -4377,6 +4377,9 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev) WREG32(mmCP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr)); WREG32(mmCP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF); + wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4); + WREG32(mmCP_RB_WPTR_POLL_ADDR_LO, lower_32_bits(wptr_gpu_addr)); + WREG32(mmCP_RB_WPTR_POLL_ADDR_HI, upper_32_bits(wptr_gpu_addr)); mdelay(1); WREG32(mmCP_RB0_CNTL, tmp); -- cgit v1.2.3 From f8991bab1aa2121e33b8569857dfb22e536bc396 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 16 Sep 2016 15:36:49 +0200 Subject: drm/amdgpu: update the shadow PD together with the real one v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Far less CPU cycles needed for this approach. v2: fix typo Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 134 +++++++++++++++++---------------- 2 files changed, 69 insertions(+), 66 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 1296f5967bd6..4e51009283a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -823,7 +823,6 @@ struct amdgpu_ring { struct amdgpu_vm_pt { struct amdgpu_bo_list_entry entry; uint64_t addr; - uint64_t shadow_addr; }; struct amdgpu_vm { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index e2fefbbd3cc8..840ac52f45b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -612,16 +612,26 @@ static uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr) return result; } -static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - bool shadow) +/* + * amdgpu_vm_update_pdes - make sure that page directory is valid + * + * @adev: amdgpu_device pointer + * @vm: requested vm + * @start: start of GPU address range + * @end: end of GPU address range + * + * Allocates new page tables if necessary + * and updates the page directory. + * Returns 0 for success, error for failure. + */ +int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, + struct amdgpu_vm *vm) { + struct amdgpu_bo *shadow; struct amdgpu_ring *ring; - struct amdgpu_bo *pd = shadow ? vm->page_directory->shadow : - vm->page_directory; - uint64_t pd_addr; + uint64_t pd_addr, shadow_addr; uint32_t incr = AMDGPU_VM_PTE_COUNT * 8; - uint64_t last_pde = ~0, last_pt = ~0; + uint64_t last_pde = ~0, last_pt = ~0, last_shadow = ~0; unsigned count = 0, pt_idx, ndw; struct amdgpu_job *job; struct amdgpu_pte_update_params params; @@ -629,15 +639,8 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, int r; - if (!pd) - return 0; - - r = amdgpu_ttm_bind(&pd->tbo, &pd->tbo.mem); - if (r) - return r; - - pd_addr = amdgpu_bo_gpu_offset(pd); ring = container_of(vm->entity.sched, struct amdgpu_ring, sched); + shadow = vm->page_directory->shadow; /* padding, etc. */ ndw = 64; @@ -645,6 +648,17 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, /* assume the worst case */ ndw += vm->max_pde_used * 6; + pd_addr = amdgpu_bo_gpu_offset(vm->page_directory); + if (shadow) { + r = amdgpu_ttm_bind(&shadow->tbo, &shadow->tbo.mem); + if (r) + return r; + shadow_addr = amdgpu_bo_gpu_offset(shadow); + ndw *= 2; + } else { + shadow_addr = 0; + } + r = amdgpu_job_alloc_with_ib(adev, ndw * 4, &job); if (r) return r; @@ -662,23 +676,19 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, continue; if (bo->shadow) { - struct amdgpu_bo *shadow = bo->shadow; + struct amdgpu_bo *pt_shadow = bo->shadow; - r = amdgpu_ttm_bind(&shadow->tbo, &shadow->tbo.mem); + r = amdgpu_ttm_bind(&pt_shadow->tbo, + &pt_shadow->tbo.mem); if (r) return r; } pt = amdgpu_bo_gpu_offset(bo); - if (!shadow) { - if (vm->page_tables[pt_idx].addr == pt) - continue; - vm->page_tables[pt_idx].addr = pt; - } else { - if (vm->page_tables[pt_idx].shadow_addr == pt) - continue; - vm->page_tables[pt_idx].shadow_addr = pt; - } + if (vm->page_tables[pt_idx].addr == pt) + continue; + + vm->page_tables[pt_idx].addr = pt; pde = pd_addr + pt_idx * 8; if (((last_pde + 8 * count) != pde) || @@ -686,6 +696,13 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, (count == AMDGPU_VM_MAX_UPDATE_SIZE)) { if (count) { + if (shadow) + amdgpu_vm_do_set_ptes(¶ms, + last_shadow, + last_pt, count, + incr, + AMDGPU_PTE_VALID); + amdgpu_vm_do_set_ptes(¶ms, last_pde, last_pt, count, incr, AMDGPU_PTE_VALID); @@ -693,34 +710,44 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, count = 1; last_pde = pde; + last_shadow = shadow_addr + pt_idx * 8; last_pt = pt; } else { ++count; } } - if (count) + if (count) { + if (vm->page_directory->shadow) + amdgpu_vm_do_set_ptes(¶ms, last_shadow, last_pt, + count, incr, AMDGPU_PTE_VALID); + amdgpu_vm_do_set_ptes(¶ms, last_pde, last_pt, count, incr, AMDGPU_PTE_VALID); + } + + if (params.ib->length_dw == 0) { + amdgpu_job_free(job); + return 0; + } - if (params.ib->length_dw != 0) { - amdgpu_ring_pad_ib(ring, params.ib); - amdgpu_sync_resv(adev, &job->sync, pd->tbo.resv, + amdgpu_ring_pad_ib(ring, params.ib); + amdgpu_sync_resv(adev, &job->sync, vm->page_directory->tbo.resv, + AMDGPU_FENCE_OWNER_VM); + if (shadow) + amdgpu_sync_resv(adev, &job->sync, shadow->tbo.resv, AMDGPU_FENCE_OWNER_VM); - WARN_ON(params.ib->length_dw > ndw); - r = amdgpu_job_submit(job, ring, &vm->entity, - AMDGPU_FENCE_OWNER_VM, &fence); - if (r) - goto error_free; - amdgpu_bo_fence(pd, fence, true); - fence_put(vm->page_directory_fence); - vm->page_directory_fence = fence_get(fence); - fence_put(fence); + WARN_ON(params.ib->length_dw > ndw); + r = amdgpu_job_submit(job, ring, &vm->entity, + AMDGPU_FENCE_OWNER_VM, &fence); + if (r) + goto error_free; - } else { - amdgpu_job_free(job); - } + amdgpu_bo_fence(vm->page_directory, fence, true); + fence_put(vm->page_directory_fence); + vm->page_directory_fence = fence_get(fence); + fence_put(fence); return 0; @@ -729,29 +756,6 @@ error_free: return r; } -/* - * amdgpu_vm_update_pdes - make sure that page directory is valid - * - * @adev: amdgpu_device pointer - * @vm: requested vm - * @start: start of GPU address range - * @end: end of GPU address range - * - * Allocates new page tables if necessary - * and updates the page directory. - * Returns 0 for success, error for failure. - */ -int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, - struct amdgpu_vm *vm) -{ - int r; - - r = amdgpu_vm_update_pd_or_shadow(adev, vm, true); - if (r) - return r; - return amdgpu_vm_update_pd_or_shadow(adev, vm, false); -} - /** * amdgpu_vm_update_ptes - make sure that page tables are valid * -- cgit v1.2.3 From 97f40ef049dded1962bc9e70ad4d197fa8a5cadb Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 30 Sep 2016 10:58:44 -0400 Subject: drm/amd/powerplay: Enable UVD powergating for SMU7 This patch enables detecting VCE/UVD PG features and fixes the UVD powergate function. Tested on a Tonga (by reading UVD tile/clk bits during playback/idle). Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c | 12 +++++++++--- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c index f5a58d489b4b..cf2ee93d8475 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c @@ -149,15 +149,21 @@ int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) if (bgate) { cgs_set_clockgating_state(hwmgr->device, AMD_IP_BLOCK_TYPE_UVD, - AMD_CG_STATE_GATE); + AMD_CG_STATE_UNGATE); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); smu7_update_uvd_dpm(hwmgr, true); smu7_powerdown_uvd(hwmgr); } else { smu7_powerup_uvd(hwmgr); - smu7_update_uvd_dpm(hwmgr, false); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_UNGATE); cgs_set_clockgating_state(hwmgr->device, AMD_IP_BLOCK_TYPE_UVD, - AMD_CG_STATE_UNGATE); + AMD_CG_STATE_GATE); + smu7_update_uvd_dpm(hwmgr, false); } return 0; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 173f9f3f2068..073e0bfa22a0 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -1352,6 +1352,8 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct cgs_system_info sys_info = {0}; + int result; data->dll_default_on = false; data->mclk_dpm0_activity_target = 0xa; @@ -1439,6 +1441,18 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) data->pcie_lane_performance.min = 16; data->pcie_lane_power_saving.max = 0; data->pcie_lane_power_saving.min = 16; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS; + result = cgs_query_system_info(hwmgr->device, &sys_info); + if (!result) { + if (sys_info.value & AMD_PG_SUPPORT_UVD) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating); + if (sys_info.value & AMD_PG_SUPPORT_VCE) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating); + } } /** -- cgit v1.2.3 From f3fd451263f0dbfb99adaa40d7ac7cc458f9c533 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 30 Sep 2016 11:00:16 -0400 Subject: drm/amd/amdgpu: Enable UVD PG on Tonga Tested by reading tile/clk bits during load/idle. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index ea3331c40391..657de2a9ba34 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1593,7 +1593,7 @@ static int vi_common_early_init(void *handle) break; case CHIP_TONGA: adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG; - adev->pg_flags = 0; + adev->pg_flags = AMD_PG_SUPPORT_UVD; adev->external_rev_id = adev->rev_id + 0x14; break; case CHIP_POLARIS11: -- cgit v1.2.3 From a7d64de659946e852cd8f2a9691a21ddbb4ebc86 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 15 Sep 2016 14:58:48 +0200 Subject: drm/amdgpu: remove adev pointer from struct amdgpu_bo v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's completely pointless to have two pointers to the device in the same structure. v2: rename function to amdgpu_ttm_adev, fix typos Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 10 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 7 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 4 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 50 ++++++++++++++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 43 ++++++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- 9 files changed, 65 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 4e51009283a4..1c874fd525a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -465,7 +465,6 @@ struct amdgpu_bo { */ struct list_head va; /* Constant after initialization */ - struct amdgpu_device *adev; struct drm_gem_object gem_base; struct amdgpu_bo *parent; struct amdgpu_bo *shadow; @@ -2127,6 +2126,11 @@ struct amdgpu_device { }; +static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) +{ + return container_of(bdev, struct amdgpu_device, mman.bdev); +} + bool amdgpu_device_is_px(struct drm_device *dev); int amdgpu_device_init(struct amdgpu_device *adev, struct drm_device *ddev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 187c3662b72c..504ae09d3991 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -355,6 +355,7 @@ static void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, struct amdgpu_bo *bo) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); u64 initial_bytes_moved; uint32_t domain; int r; @@ -372,9 +373,9 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, retry: amdgpu_ttm_placement_from_domain(bo, domain); - initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved); + initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); - p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) - + p->bytes_moved += atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved; if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) { @@ -400,6 +401,7 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, struct amdgpu_bo_list_entry *candidate = p->evictable; struct amdgpu_bo *bo = candidate->robj; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); u64 initial_bytes_moved; uint32_t other; @@ -420,9 +422,9 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, /* Good we can try to move this BO somewhere else */ amdgpu_ttm_placement_from_domain(bo, other); - initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved); + initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); - p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) - + p->bytes_moved += atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved; if (unlikely(r)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 3ad0bf6ce3e4..d4fce326502b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -116,10 +116,11 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev) * Call from drm_gem_handle_create which appear in both new and open ioctl * case. */ -int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv) +int amdgpu_gem_object_open(struct drm_gem_object *obj, + struct drm_file *file_priv) { struct amdgpu_bo *abo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = abo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_va *bo_va; @@ -142,7 +143,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, struct drm_file *file_priv) { struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = bo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c index 32fa7b7913f7..7ea3cacf9f9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c @@ -285,7 +285,7 @@ free_rmn: int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) { unsigned long end = addr + amdgpu_bo_size(bo) - 1; - struct amdgpu_device *adev = bo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct amdgpu_mn *rmn; struct amdgpu_mn_node *node = NULL; struct list_head bos; @@ -340,7 +340,7 @@ int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) */ void amdgpu_mn_unregister(struct amdgpu_bo *bo) { - struct amdgpu_device *adev = bo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct amdgpu_mn *rmn; struct list_head *head; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index c6754e71e1f5..6efa8d73b394 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -88,18 +88,19 @@ static void amdgpu_update_memory_usage(struct amdgpu_device *adev, static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) { + struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); struct amdgpu_bo *bo; bo = container_of(tbo, struct amdgpu_bo, tbo); - amdgpu_update_memory_usage(bo->adev, &bo->tbo.mem, NULL); + amdgpu_update_memory_usage(adev, &bo->tbo.mem, NULL); drm_gem_object_release(&bo->gem_base); amdgpu_bo_unref(&bo->parent); if (!list_empty(&bo->shadow_list)) { - mutex_lock(&bo->adev->shadow_list_lock); + mutex_lock(&adev->shadow_list_lock); list_del_init(&bo->shadow_list); - mutex_unlock(&bo->adev->shadow_list_lock); + mutex_unlock(&adev->shadow_list_lock); } kfree(bo->metadata); kfree(bo); @@ -210,8 +211,10 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev, void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain) { - amdgpu_ttm_placement_init(abo->adev, &abo->placement, - abo->placements, domain, abo->flags); + struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); + + amdgpu_ttm_placement_init(adev, &abo->placement, abo->placements, + domain, abo->flags); } static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo, @@ -357,7 +360,6 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, kfree(bo); return r; } - bo->adev = adev; INIT_LIST_HEAD(&bo->shadow_list); INIT_LIST_HEAD(&bo->va); bo->prefered_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM | @@ -622,6 +624,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 min_offset, u64 max_offset, u64 *gpu_addr) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); int r, i; unsigned fpfn, lpfn; @@ -657,12 +660,12 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) && !(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) && (!max_offset || max_offset > - bo->adev->mc.visible_vram_size)) { + adev->mc.visible_vram_size)) { if (WARN_ON_ONCE(min_offset > - bo->adev->mc.visible_vram_size)) + adev->mc.visible_vram_size)) return -EINVAL; fpfn = min_offset >> PAGE_SHIFT; - lpfn = bo->adev->mc.visible_vram_size >> PAGE_SHIFT; + lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; } else { fpfn = min_offset >> PAGE_SHIFT; lpfn = max_offset >> PAGE_SHIFT; @@ -677,12 +680,12 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); if (unlikely(r)) { - dev_err(bo->adev->dev, "%p pin failed\n", bo); + dev_err(adev->dev, "%p pin failed\n", bo); goto error; } r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem); if (unlikely(r)) { - dev_err(bo->adev->dev, "%p bind failed\n", bo); + dev_err(adev->dev, "%p bind failed\n", bo); goto error; } @@ -690,11 +693,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, if (gpu_addr != NULL) *gpu_addr = amdgpu_bo_gpu_offset(bo); if (domain == AMDGPU_GEM_DOMAIN_VRAM) { - bo->adev->vram_pin_size += amdgpu_bo_size(bo); + adev->vram_pin_size += amdgpu_bo_size(bo); if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) - bo->adev->invisible_pin_size += amdgpu_bo_size(bo); + adev->invisible_pin_size += amdgpu_bo_size(bo); } else if (domain == AMDGPU_GEM_DOMAIN_GTT) { - bo->adev->gart_pin_size += amdgpu_bo_size(bo); + adev->gart_pin_size += amdgpu_bo_size(bo); } error: @@ -708,10 +711,11 @@ int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain, u64 *gpu_addr) int amdgpu_bo_unpin(struct amdgpu_bo *bo) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); int r, i; if (!bo->pin_count) { - dev_warn(bo->adev->dev, "%p unpin not necessary\n", bo); + dev_warn(adev->dev, "%p unpin not necessary\n", bo); return 0; } bo->pin_count--; @@ -723,16 +727,16 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo) } r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); if (unlikely(r)) { - dev_err(bo->adev->dev, "%p validate failed for unpin\n", bo); + dev_err(adev->dev, "%p validate failed for unpin\n", bo); goto error; } if (bo->tbo.mem.mem_type == TTM_PL_VRAM) { - bo->adev->vram_pin_size -= amdgpu_bo_size(bo); + adev->vram_pin_size -= amdgpu_bo_size(bo); if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) - bo->adev->invisible_pin_size -= amdgpu_bo_size(bo); + adev->invisible_pin_size -= amdgpu_bo_size(bo); } else if (bo->tbo.mem.mem_type == TTM_PL_TT) { - bo->adev->gart_pin_size -= amdgpu_bo_size(bo); + adev->gart_pin_size -= amdgpu_bo_size(bo); } error: @@ -857,6 +861,7 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem; @@ -864,21 +869,21 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, return; abo = container_of(bo, struct amdgpu_bo, tbo); - amdgpu_vm_bo_invalidate(abo->adev, abo); + amdgpu_vm_bo_invalidate(adev, abo); /* update statistics */ if (!new_mem) return; /* move_notify is called before move happens */ - amdgpu_update_memory_usage(abo->adev, &bo->mem, new_mem); + amdgpu_update_memory_usage(adev, &bo->mem, new_mem); trace_amdgpu_ttm_bo_move(abo, new_mem->mem_type, old_mem->mem_type); } int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { - struct amdgpu_device *adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; unsigned long offset, size, lpfn; int i, r; @@ -887,7 +892,6 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) return 0; abo = container_of(bo, struct amdgpu_bo, tbo); - adev = abo->adev; if (bo->mem.mem_type != TTM_PL_VRAM) return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 8255034d73eb..d3baf834ac24 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -71,12 +71,13 @@ static inline unsigned amdgpu_mem_type_to_domain(u32 mem_type) */ static inline int amdgpu_bo_reserve(struct amdgpu_bo *bo, bool no_intr) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); int r; r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) - dev_err(bo->adev->dev, "%p reserve failed\n", bo); + dev_err(adev->dev, "%p reserve failed\n", bo); return r; } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index f757f68418b7..414fa8fa8488 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -51,16 +51,6 @@ static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev); static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev); -static struct amdgpu_device *amdgpu_get_adev(struct ttm_bo_device *bdev) -{ - struct amdgpu_mman *mman; - struct amdgpu_device *adev; - - mman = container_of(bdev, struct amdgpu_mman, bdev); - adev = container_of(mman, struct amdgpu_device, mman); - return adev; -} - /* * Global memory. @@ -150,7 +140,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, { struct amdgpu_device *adev; - adev = amdgpu_get_adev(bdev); + adev = amdgpu_ttm_adev(bdev); switch (type) { case TTM_PL_SYSTEM: @@ -195,6 +185,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, static void amdgpu_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; static struct ttm_place placements = { .fpfn = 0, @@ -213,7 +204,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, abo = container_of(bo, struct amdgpu_bo, tbo); switch (bo->mem.mem_type) { case TTM_PL_VRAM: - if (abo->adev->mman.buffer_funcs_ring->ready == false) { + if (adev->mman.buffer_funcs_ring->ready == false) { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); } else { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); @@ -229,7 +220,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, * allocating address space for the BO. */ abo->placements[i].lpfn = - abo->adev->mc.gtt_size >> PAGE_SHIFT; + adev->mc.gtt_size >> PAGE_SHIFT; } } break; @@ -290,7 +281,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, struct ttm_mem_reg *old_mem) { - struct amdgpu_device *adev = amdgpu_get_adev(bo->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; struct drm_mm_node *old_mm, *new_mm; @@ -384,7 +375,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, struct ttm_placement placement; int r; - adev = amdgpu_get_adev(bo->bdev); + adev = amdgpu_ttm_adev(bo->bdev); tmp_mem = *new_mem; tmp_mem.mm_node = NULL; placement.num_placement = 1; @@ -431,7 +422,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, struct ttm_place placements; int r; - adev = amdgpu_get_adev(bo->bdev); + adev = amdgpu_ttm_adev(bo->bdev); tmp_mem = *new_mem; tmp_mem.mm_node = NULL; placement.num_placement = 1; @@ -474,7 +465,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, if (WARN_ON_ONCE(abo->pin_count > 0)) return -EINVAL; - adev = amdgpu_get_adev(bo->bdev); + adev = amdgpu_ttm_adev(bo->bdev); /* remember the eviction */ if (evict) @@ -527,7 +518,7 @@ memcpy: static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct amdgpu_device *adev = amdgpu_get_adev(bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); mem->bus.addr = NULL; mem->bus.offset = 0; @@ -659,7 +650,7 @@ release_pages: /* prepare the sg table with the user pages */ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) { - struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; unsigned nents; int r; @@ -691,7 +682,7 @@ release_sg: static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) { - struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; struct sg_page_iter sg_iter; @@ -851,7 +842,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_bo_device *bdev, struct amdgpu_device *adev; struct amdgpu_ttm_tt *gtt; - adev = amdgpu_get_adev(bdev); + adev = amdgpu_ttm_adev(bdev); gtt = kzalloc(sizeof(struct amdgpu_ttm_tt), GFP_KERNEL); if (gtt == NULL) { @@ -895,7 +886,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm) return 0; } - adev = amdgpu_get_adev(ttm->bdev); + adev = amdgpu_ttm_adev(ttm->bdev); #ifdef CONFIG_SWIOTLB if (swiotlb_nr_tbl()) { @@ -941,7 +932,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) if (slave) return; - adev = amdgpu_get_adev(ttm->bdev); + adev = amdgpu_ttm_adev(ttm->bdev); #ifdef CONFIG_SWIOTLB if (swiotlb_nr_tbl()) { @@ -1064,7 +1055,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo) { - struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); unsigned i, j; for (i = 0; i < AMDGPU_TTM_LRU_SIZE; ++i) { @@ -1081,7 +1072,7 @@ static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo) static struct amdgpu_mman_lru *amdgpu_ttm_lru(struct ttm_buffer_object *tbo) { - struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); unsigned log2_size = min(ilog2(tbo->num_pages), AMDGPU_TTM_LRU_SIZE - 1); @@ -1370,7 +1361,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct reservation_object *resv, struct fence **fence) { - struct amdgpu_device *adev = bo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct amdgpu_job *job; struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index 4cf3ca755810..d67eadaa91a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -931,7 +931,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, if (r) return r; - if (!bo->adev->uvd.address_64_bit) { + if (!ring->adev->uvd.address_64_bit) { amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM); amdgpu_uvd_force_into_uvd_segment(bo); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 840ac52f45b6..f4b78b66444d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1195,7 +1195,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem); gtt_flags = (amdgpu_ttm_is_bound(bo_va->bo->tbo.ttm) && - adev == bo_va->bo->adev) ? flags : 0; + adev == amdgpu_ttm_adev(bo_va->bo->tbo.bdev)) ? flags : 0; spin_lock(&vm->status_lock); if (!list_empty(&bo_va->vm_status)) -- cgit v1.2.3 From f7da30d979d4c6af4b7f4fe3094e581d8c5812d7 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Sep 2016 12:03:04 +0200 Subject: drm/amdgpu: move PT validation back into VM code v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Saves a bunch of CPU cycles when swapping things back in and allows us to split the VM headers into a separate file. v2: rename parameters Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 42 ++++++++++++++++++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 27 ++++++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 21 ++++++++++------- 4 files changed, 60 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 1c874fd525a0..848e4ed7e32a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -915,8 +915,9 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, struct list_head *validated, struct amdgpu_bo_list_entry *entry); -void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct list_head *duplicates); +int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, + int (*callback)(void *p, struct amdgpu_bo *bo), + void *param); void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, struct amdgpu_vm *vm); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 504ae09d3991..a13e551e67cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -388,9 +388,9 @@ retry: /* Last resort, try to evict something from the current working set */ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, - struct amdgpu_bo_list_entry *lobj) + struct amdgpu_bo *validated) { - uint32_t domain = lobj->robj->allowed_domains; + uint32_t domain = validated->allowed_domains; int r; if (!p->evictable) @@ -406,7 +406,7 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, uint32_t other; /* If we reached our current BO we can forget it */ - if (candidate == lobj) + if (candidate->robj == validated) break; other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); @@ -439,6 +439,23 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, return false; } +static int amdgpu_cs_validate(void *param, struct amdgpu_bo *bo) +{ + struct amdgpu_cs_parser *p = param; + int r; + + do { + r = amdgpu_cs_bo_validate(p, bo); + } while (r == -ENOMEM && amdgpu_cs_try_evict(p, bo)); + if (r) + return r; + + if (bo->shadow) + r = amdgpu_cs_bo_validate(p, bo); + + return r; +} + static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, struct list_head *validated) { @@ -466,18 +483,10 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, if (p->evictable == lobj) p->evictable = NULL; - do { - r = amdgpu_cs_bo_validate(p, bo); - } while (r == -ENOMEM && amdgpu_cs_try_evict(p, lobj)); + r = amdgpu_cs_validate(p, bo); if (r) return r; - if (bo->shadow) { - r = amdgpu_cs_bo_validate(p, bo); - if (r) - return r; - } - if (binding_userptr) { drm_free_large(lobj->user_pages); lobj->user_pages = NULL; @@ -595,14 +604,19 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, list_splice(&need_pages, &p->validated); } - amdgpu_vm_get_pt_bos(p->adev, &fpriv->vm, &duplicates); - p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev); p->bytes_moved = 0; p->evictable = list_last_entry(&p->validated, struct amdgpu_bo_list_entry, tv.head); + r = amdgpu_vm_validate_pt_bos(p->adev, &fpriv->vm, + amdgpu_cs_validate, p); + if (r) { + DRM_ERROR("amdgpu_vm_validate_pt_bos() failed.\n"); + goto error_validate; + } + r = amdgpu_cs_list_validate(p, &duplicates); if (r) { DRM_ERROR("amdgpu_cs_list_validate(duplicates) failed.\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index d4fce326502b..5dc0158b12db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -469,6 +469,16 @@ out: return r; } +static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) +{ + unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); + + /* if anything is swapped out don't swap it in here, + just abort and wait for the next CS */ + + return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0; +} + /** * amdgpu_gem_va_update_vm -update the bo_va in its VM * @@ -479,7 +489,8 @@ out: * vital here, so they are not reported back to userspace. */ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, - struct amdgpu_bo_va *bo_va, uint32_t operation) + struct amdgpu_bo_va *bo_va, + uint32_t operation) { struct ttm_validate_buffer tv, *entry; struct amdgpu_bo_list_entry vm_pd; @@ -502,7 +513,6 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, if (r) goto error_print; - amdgpu_vm_get_pt_bos(adev, bo_va->vm, &duplicates); list_for_each_entry(entry, &list, head) { domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type); /* if anything is swapped out don't swap it in here, @@ -510,13 +520,10 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, if (domain == AMDGPU_GEM_DOMAIN_CPU) goto error_unreserve; } - list_for_each_entry(entry, &duplicates, head) { - domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type); - /* if anything is swapped out don't swap it in here, - just abort and wait for the next CS */ - if (domain == AMDGPU_GEM_DOMAIN_CPU) - goto error_unreserve; - } + r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check, + NULL); + if (r) + goto error_unreserve; r = amdgpu_vm_update_page_directory(adev, bo_va->vm); if (r) @@ -537,8 +544,6 @@ error_print: DRM_ERROR("Couldn't update BO_VA (%d)\n", r); } - - int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f4b78b66444d..c171b16cf0f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -116,27 +116,29 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, } /** - * amdgpu_vm_get_bos - add the vm BOs to a duplicates list + * amdgpu_vm_validate_pt_bos - validate the page table BOs * * @adev: amdgpu device pointer * @vm: vm providing the BOs - * @duplicates: head of duplicates list + * @validate: callback to do the validation + * @param: parameter for the validation callback * - * Add the page directory to the BO duplicates list - * for command submission. + * Validate the page table BOs on command submission if neccessary. */ -void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct list_head *duplicates) +int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, + int (*validate)(void *p, struct amdgpu_bo *bo), + void *param) { uint64_t num_evictions; unsigned i; + int r; /* We only need to validate the page tables * if they aren't already valid. */ num_evictions = atomic64_read(&adev->num_evictions); if (num_evictions == vm->last_eviction_counter) - return; + return 0; /* add the vm page table to the list */ for (i = 0; i <= vm->max_pde_used; ++i) { @@ -145,9 +147,12 @@ void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, if (!entry->robj) continue; - list_add(&entry->tv.head, duplicates); + r = validate(param, entry->robj); + if (r) + return r; } + return 0; } /** -- cgit v1.2.3 From 914b4dce4fda09baa059414be01ae9484dc78120 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Sep 2016 12:27:37 +0200 Subject: drm/amdgpu: stop using a bo list entry for the VM PTs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Saves us a bit of memory. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 34 ++++++++++++++-------------------- 2 files changed, 16 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 848e4ed7e32a..9d9831f2e2d0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -820,8 +820,8 @@ struct amdgpu_ring { #define AMDGPU_VM_FAULT_STOP_ALWAYS 2 struct amdgpu_vm_pt { - struct amdgpu_bo_list_entry entry; - uint64_t addr; + struct amdgpu_bo *bo; + uint64_t addr; }; struct amdgpu_vm { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index c171b16cf0f1..b8620d3dd61e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -142,12 +142,12 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, /* add the vm page table to the list */ for (i = 0; i <= vm->max_pde_used; ++i) { - struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry; + struct amdgpu_bo *bo = vm->page_tables[i].bo; - if (!entry->robj) + if (!bo) continue; - r = validate(param, entry->robj); + r = validate(param, bo); if (r) return r; } @@ -171,12 +171,12 @@ void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, spin_lock(&glob->lru_lock); for (i = 0; i <= vm->max_pde_used; ++i) { - struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry; + struct amdgpu_bo *bo = vm->page_tables[i].bo; - if (!entry->robj) + if (!bo) continue; - ttm_bo_move_to_lru_tail(&entry->robj->tbo); + ttm_bo_move_to_lru_tail(&bo->tbo); } spin_unlock(&glob->lru_lock); } @@ -674,7 +674,7 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, /* walk over the address space and update the page directory */ for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) { - struct amdgpu_bo *bo = vm->page_tables[pt_idx].entry.robj; + struct amdgpu_bo *bo = vm->page_tables[pt_idx].bo; uint64_t pde, pt; if (bo == NULL) @@ -790,11 +790,11 @@ static void amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, /* initialize the variables */ addr = start; pt_idx = addr >> amdgpu_vm_block_size; - pt = vm->page_tables[pt_idx].entry.robj; + pt = vm->page_tables[pt_idx].bo; if (params->shadow) { if (!pt->shadow) return; - pt = vm->page_tables[pt_idx].entry.robj->shadow; + pt = pt->shadow; } if ((addr & ~mask) == (end & ~mask)) nptes = end - addr; @@ -813,11 +813,11 @@ static void amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, /* walk over the address space and update the page tables */ while (addr < end) { pt_idx = addr >> amdgpu_vm_block_size; - pt = vm->page_tables[pt_idx].entry.robj; + pt = vm->page_tables[pt_idx].bo; if (params->shadow) { if (!pt->shadow) return; - pt = vm->page_tables[pt_idx].entry.robj->shadow; + pt = pt->shadow; } if ((addr & ~mask) == (end & ~mask)) @@ -1425,11 +1425,9 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, /* walk over the address space and allocate the page tables */ for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) { struct reservation_object *resv = vm->page_directory->tbo.resv; - struct amdgpu_bo_list_entry *entry; struct amdgpu_bo *pt; - entry = &vm->page_tables[pt_idx].entry; - if (entry->robj) + if (vm->page_tables[pt_idx].bo) continue; r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8, @@ -1463,11 +1461,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, } } - entry->robj = pt; - entry->priority = 0; - entry->tv.bo = &entry->robj->tbo; - entry->tv.shared = true; - entry->user_pages = NULL; + vm->page_tables[pt_idx].bo = pt; vm->page_tables[pt_idx].addr = 0; } @@ -1719,7 +1713,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) } for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) { - struct amdgpu_bo *pt = vm->page_tables[i].entry.robj; + struct amdgpu_bo *pt = vm->page_tables[i].bo; if (!pt) continue; -- cgit v1.2.3 From 561135049992aa23d3b965cea3418b5d0334a930 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Sep 2016 12:36:44 +0200 Subject: drm/amdgpu: move sync handling into a separate header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only cleanup, no intended functional change. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 22 +------------ drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 21 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9d9831f2e2d0..b6f5425ee52e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -53,6 +53,7 @@ #include "amdgpu_ucode.h" #include "amdgpu_ttm.h" #include "amdgpu_gds.h" +#include "amdgpu_sync.h" #include "amd_powerplay.h" #include "amdgpu_acp.h" @@ -561,27 +562,6 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, int amdgpu_mode_dumb_mmap(struct drm_file *filp, struct drm_device *dev, uint32_t handle, uint64_t *offset_p); -/* - * Synchronization - */ -struct amdgpu_sync { - DECLARE_HASHTABLE(fences, 4); - struct fence *last_vm_update; -}; - -void amdgpu_sync_create(struct amdgpu_sync *sync); -int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, - struct fence *f); -int amdgpu_sync_resv(struct amdgpu_device *adev, - struct amdgpu_sync *sync, - struct reservation_object *resv, - void *owner); -struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, - struct amdgpu_ring *ring); -struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync); -void amdgpu_sync_free(struct amdgpu_sync *sync); -int amdgpu_sync_init(void); -void amdgpu_sync_fini(void); int amdgpu_fence_slab_init(void); void amdgpu_fence_slab_fini(void); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h new file mode 100644 index 000000000000..405f379ac186 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h @@ -0,0 +1,56 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ +#ifndef __AMDGPU_SYNC_H__ +#define __AMDGPU_SYNC_H__ + +#include + +struct fence; +struct reservation_object; +struct amdgpu_device; +struct amdgpu_ring; + +/* + * Container for fences used to sync command submissions. + */ +struct amdgpu_sync { + DECLARE_HASHTABLE(fences, 4); + struct fence *last_vm_update; +}; + +void amdgpu_sync_create(struct amdgpu_sync *sync); +int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, + struct fence *f); +int amdgpu_sync_resv(struct amdgpu_device *adev, + struct amdgpu_sync *sync, + struct reservation_object *resv, + void *owner); +struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, + struct amdgpu_ring *ring); +struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync); +void amdgpu_sync_free(struct amdgpu_sync *sync); +int amdgpu_sync_init(void); +void amdgpu_sync_fini(void); + +#endif -- cgit v1.2.3 From 78023016116f9fbf4783a99293987ccdfc4d7a92 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Sep 2016 15:33:18 +0200 Subject: drm/amdgpu: move fence and ring defines into amdgpu_ring.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only cleanup, no intended functional change. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 147 +----------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 184 +++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 146 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index b6f5425ee52e..3ba97ea5e62c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -54,6 +54,7 @@ #include "amdgpu_ttm.h" #include "amdgpu_gds.h" #include "amdgpu_sync.h" +#include "amdgpu_ring.h" #include "amd_powerplay.h" #include "amdgpu_acp.h" @@ -109,12 +110,6 @@ extern int amdgpu_vram_page_split; #define AMDGPUFB_CONN_LIMIT 4 #define AMDGPU_BIOS_NUM_SCRATCH 8 -/* max number of rings */ -#define AMDGPU_MAX_RINGS 16 -#define AMDGPU_MAX_GFX_RINGS 1 -#define AMDGPU_MAX_COMPUTE_RINGS 8 -#define AMDGPU_MAX_VCE_RINGS 3 - /* max number of IP instances */ #define AMDGPU_MAX_SDMA_INSTANCES 2 @@ -155,7 +150,6 @@ extern int amdgpu_vram_page_split; struct amdgpu_device; struct amdgpu_ib; struct amdgpu_vm; -struct amdgpu_ring; struct amdgpu_cs_parser; struct amdgpu_job; struct amdgpu_irq_src; @@ -288,47 +282,6 @@ struct amdgpu_ih_funcs { void (*set_rptr)(struct amdgpu_device *adev); }; -/* provided by hw blocks that expose a ring buffer for commands */ -struct amdgpu_ring_funcs { - /* ring read/write ptr handling */ - u32 (*get_rptr)(struct amdgpu_ring *ring); - u32 (*get_wptr)(struct amdgpu_ring *ring); - void (*set_wptr)(struct amdgpu_ring *ring); - /* validating and patching of IBs */ - int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx); - /* command emit functions */ - void (*emit_ib)(struct amdgpu_ring *ring, - struct amdgpu_ib *ib, - unsigned vm_id, bool ctx_switch); - void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr, - uint64_t seq, unsigned flags); - void (*emit_pipeline_sync)(struct amdgpu_ring *ring); - void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id, - uint64_t pd_addr); - void (*emit_hdp_flush)(struct amdgpu_ring *ring); - void (*emit_hdp_invalidate)(struct amdgpu_ring *ring); - void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid, - uint32_t gds_base, uint32_t gds_size, - uint32_t gws_base, uint32_t gws_size, - uint32_t oa_base, uint32_t oa_size); - /* testing functions */ - int (*test_ring)(struct amdgpu_ring *ring); - int (*test_ib)(struct amdgpu_ring *ring, long timeout); - /* insert NOP packets */ - void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count); - /* pad the indirect buffer to the necessary number of dw */ - void (*pad_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib); - unsigned (*init_cond_exec)(struct amdgpu_ring *ring); - void (*patch_cond_exec)(struct amdgpu_ring *ring, unsigned offset); - /* note usage for clock and power gating */ - void (*begin_use)(struct amdgpu_ring *ring); - void (*end_use)(struct amdgpu_ring *ring); - void (*emit_switch_buffer) (struct amdgpu_ring *ring); - void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags); - unsigned (*get_emit_ib_size) (struct amdgpu_ring *ring); - unsigned (*get_dma_frame_size) (struct amdgpu_ring *ring); -}; - /* * BIOS. */ @@ -365,47 +318,6 @@ struct amdgpu_clock { uint32_t max_pixel_clock; }; -/* - * Fences. - */ -struct amdgpu_fence_driver { - uint64_t gpu_addr; - volatile uint32_t *cpu_addr; - /* sync_seq is protected by ring emission lock */ - uint32_t sync_seq; - atomic_t last_seq; - bool initialized; - struct amdgpu_irq_src *irq_src; - unsigned irq_type; - struct timer_list fallback_timer; - unsigned num_fences_mask; - spinlock_t lock; - struct fence **fences; -}; - -/* some special values for the owner field */ -#define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul) -#define AMDGPU_FENCE_OWNER_VM ((void*)1ul) - -#define AMDGPU_FENCE_FLAG_64BIT (1 << 0) -#define AMDGPU_FENCE_FLAG_INT (1 << 1) - -int amdgpu_fence_driver_init(struct amdgpu_device *adev); -void amdgpu_fence_driver_fini(struct amdgpu_device *adev); -void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev); - -int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, - unsigned num_hw_submission); -int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, - struct amdgpu_irq_src *irq_src, - unsigned irq_type); -void amdgpu_fence_driver_suspend(struct amdgpu_device *adev); -void amdgpu_fence_driver_resume(struct amdgpu_device *adev); -int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **fence); -void amdgpu_fence_process(struct amdgpu_ring *ring); -int amdgpu_fence_wait_empty(struct amdgpu_ring *ring); -unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); - /* * BO. */ @@ -703,14 +615,6 @@ struct amdgpu_ib { uint32_t flags; }; -enum amdgpu_ring_type { - AMDGPU_RING_TYPE_GFX, - AMDGPU_RING_TYPE_COMPUTE, - AMDGPU_RING_TYPE_SDMA, - AMDGPU_RING_TYPE_UVD, - AMDGPU_RING_TYPE_VCE -}; - extern const struct amd_sched_backend_ops amdgpu_sched_ops; int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, @@ -724,45 +628,6 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, struct amd_sched_entity *entity, void *owner, struct fence **f); -struct amdgpu_ring { - struct amdgpu_device *adev; - const struct amdgpu_ring_funcs *funcs; - struct amdgpu_fence_driver fence_drv; - struct amd_gpu_scheduler sched; - - struct amdgpu_bo *ring_obj; - volatile uint32_t *ring; - unsigned rptr_offs; - unsigned wptr; - unsigned wptr_old; - unsigned ring_size; - unsigned max_dw; - int count_dw; - uint64_t gpu_addr; - uint32_t align_mask; - uint32_t ptr_mask; - bool ready; - u32 nop; - u32 idx; - u32 me; - u32 pipe; - u32 queue; - struct amdgpu_bo *mqd_obj; - u32 doorbell_index; - bool use_doorbell; - unsigned wptr_offs; - unsigned fence_offs; - uint64_t current_ctx; - enum amdgpu_ring_type type; - char name[16]; - unsigned cond_exe_offs; - u64 cond_exe_gpu_addr; - volatile u32 *cond_exe_cpu_addr; -#if defined(CONFIG_DEBUG_FS) - struct dentry *ent; -#endif -}; - /* * VM */ @@ -1168,16 +1033,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, int amdgpu_ib_pool_init(struct amdgpu_device *adev); void amdgpu_ib_pool_fini(struct amdgpu_device *adev); int amdgpu_ib_ring_tests(struct amdgpu_device *adev); -int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw); -void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count); -void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib); -void amdgpu_ring_commit(struct amdgpu_ring *ring); -void amdgpu_ring_undo(struct amdgpu_ring *ring); -int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, - unsigned ring_size, u32 nop, u32 align_mask, - struct amdgpu_irq_src *irq_src, unsigned irq_type, - enum amdgpu_ring_type ring_type); -void amdgpu_ring_fini(struct amdgpu_ring *ring); /* * CS. diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h new file mode 100644 index 000000000000..2f935888c64b --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -0,0 +1,184 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ +#ifndef __AMDGPU_RING_H__ +#define __AMDGPU_RING_H__ + +#include "gpu_scheduler.h" + +/* max number of rings */ +#define AMDGPU_MAX_RINGS 16 +#define AMDGPU_MAX_GFX_RINGS 1 +#define AMDGPU_MAX_COMPUTE_RINGS 8 +#define AMDGPU_MAX_VCE_RINGS 3 + +/* some special values for the owner field */ +#define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul) +#define AMDGPU_FENCE_OWNER_VM ((void*)1ul) + +#define AMDGPU_FENCE_FLAG_64BIT (1 << 0) +#define AMDGPU_FENCE_FLAG_INT (1 << 1) + +enum amdgpu_ring_type { + AMDGPU_RING_TYPE_GFX, + AMDGPU_RING_TYPE_COMPUTE, + AMDGPU_RING_TYPE_SDMA, + AMDGPU_RING_TYPE_UVD, + AMDGPU_RING_TYPE_VCE +}; + +struct amdgpu_device; +struct amdgpu_ring; +struct amdgpu_ib; +struct amdgpu_cs_parser; + +/* + * Fences. + */ +struct amdgpu_fence_driver { + uint64_t gpu_addr; + volatile uint32_t *cpu_addr; + /* sync_seq is protected by ring emission lock */ + uint32_t sync_seq; + atomic_t last_seq; + bool initialized; + struct amdgpu_irq_src *irq_src; + unsigned irq_type; + struct timer_list fallback_timer; + unsigned num_fences_mask; + spinlock_t lock; + struct fence **fences; +}; + +int amdgpu_fence_driver_init(struct amdgpu_device *adev); +void amdgpu_fence_driver_fini(struct amdgpu_device *adev); +void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev); + +int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, + unsigned num_hw_submission); +int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, + struct amdgpu_irq_src *irq_src, + unsigned irq_type); +void amdgpu_fence_driver_suspend(struct amdgpu_device *adev); +void amdgpu_fence_driver_resume(struct amdgpu_device *adev); +int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **fence); +void amdgpu_fence_process(struct amdgpu_ring *ring); +int amdgpu_fence_wait_empty(struct amdgpu_ring *ring); +unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); + +/* + * Rings. + */ + +/* provided by hw blocks that expose a ring buffer for commands */ +struct amdgpu_ring_funcs { + /* ring read/write ptr handling */ + u32 (*get_rptr)(struct amdgpu_ring *ring); + u32 (*get_wptr)(struct amdgpu_ring *ring); + void (*set_wptr)(struct amdgpu_ring *ring); + /* validating and patching of IBs */ + int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx); + /* command emit functions */ + void (*emit_ib)(struct amdgpu_ring *ring, + struct amdgpu_ib *ib, + unsigned vm_id, bool ctx_switch); + void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr, + uint64_t seq, unsigned flags); + void (*emit_pipeline_sync)(struct amdgpu_ring *ring); + void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id, + uint64_t pd_addr); + void (*emit_hdp_flush)(struct amdgpu_ring *ring); + void (*emit_hdp_invalidate)(struct amdgpu_ring *ring); + void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid, + uint32_t gds_base, uint32_t gds_size, + uint32_t gws_base, uint32_t gws_size, + uint32_t oa_base, uint32_t oa_size); + /* testing functions */ + int (*test_ring)(struct amdgpu_ring *ring); + int (*test_ib)(struct amdgpu_ring *ring, long timeout); + /* insert NOP packets */ + void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count); + /* pad the indirect buffer to the necessary number of dw */ + void (*pad_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib); + unsigned (*init_cond_exec)(struct amdgpu_ring *ring); + void (*patch_cond_exec)(struct amdgpu_ring *ring, unsigned offset); + /* note usage for clock and power gating */ + void (*begin_use)(struct amdgpu_ring *ring); + void (*end_use)(struct amdgpu_ring *ring); + void (*emit_switch_buffer) (struct amdgpu_ring *ring); + void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags); + unsigned (*get_emit_ib_size) (struct amdgpu_ring *ring); + unsigned (*get_dma_frame_size) (struct amdgpu_ring *ring); +}; + +struct amdgpu_ring { + struct amdgpu_device *adev; + const struct amdgpu_ring_funcs *funcs; + struct amdgpu_fence_driver fence_drv; + struct amd_gpu_scheduler sched; + + struct amdgpu_bo *ring_obj; + volatile uint32_t *ring; + unsigned rptr_offs; + unsigned wptr; + unsigned wptr_old; + unsigned ring_size; + unsigned max_dw; + int count_dw; + uint64_t gpu_addr; + uint32_t align_mask; + uint32_t ptr_mask; + bool ready; + u32 nop; + u32 idx; + u32 me; + u32 pipe; + u32 queue; + struct amdgpu_bo *mqd_obj; + u32 doorbell_index; + bool use_doorbell; + unsigned wptr_offs; + unsigned fence_offs; + uint64_t current_ctx; + enum amdgpu_ring_type type; + char name[16]; + unsigned cond_exe_offs; + u64 cond_exe_gpu_addr; + volatile u32 *cond_exe_cpu_addr; +#if defined(CONFIG_DEBUG_FS) + struct dentry *ent; +#endif +}; + +int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw); +void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count); +void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib); +void amdgpu_ring_commit(struct amdgpu_ring *ring); +void amdgpu_ring_undo(struct amdgpu_ring *ring); +int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, + unsigned ring_size, u32 nop, u32 align_mask, + struct amdgpu_irq_src *irq_src, unsigned irq_type, + enum amdgpu_ring_type ring_type); +void amdgpu_ring_fini(struct amdgpu_ring *ring); + +#endif -- cgit v1.2.3 From 073440d26272dc983bed51a3aa7bddc4aa344ab0 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Sep 2016 15:41:50 +0200 Subject: drm/amdgpu: move VM defines into amdgpu_vm.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only cleanup, no intended functional change. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 170 +-------------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 205 +++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 169 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3ba97ea5e62c..7d30a8e03bed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -55,6 +55,7 @@ #include "amdgpu_gds.h" #include "amdgpu_sync.h" #include "amdgpu_ring.h" +#include "amdgpu_vm.h" #include "amd_powerplay.h" #include "amdgpu_acp.h" @@ -149,7 +150,6 @@ extern int amdgpu_vram_page_split; struct amdgpu_device; struct amdgpu_ib; -struct amdgpu_vm; struct amdgpu_cs_parser; struct amdgpu_job; struct amdgpu_irq_src; @@ -628,174 +628,6 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, struct amd_sched_entity *entity, void *owner, struct fence **f); -/* - * VM - */ - -/* maximum number of VMIDs */ -#define AMDGPU_NUM_VM 16 - -/* Maximum number of PTEs the hardware can write with one command */ -#define AMDGPU_VM_MAX_UPDATE_SIZE 0x3FFFF - -/* number of entries in page table */ -#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size) - -/* PTBs (Page Table Blocks) need to be aligned to 32K */ -#define AMDGPU_VM_PTB_ALIGN_SIZE 32768 - -/* LOG2 number of continuous pages for the fragment field */ -#define AMDGPU_LOG2_PAGES_PER_FRAG 4 - -#define AMDGPU_PTE_VALID (1 << 0) -#define AMDGPU_PTE_SYSTEM (1 << 1) -#define AMDGPU_PTE_SNOOPED (1 << 2) - -/* VI only */ -#define AMDGPU_PTE_EXECUTABLE (1 << 4) - -#define AMDGPU_PTE_READABLE (1 << 5) -#define AMDGPU_PTE_WRITEABLE (1 << 6) - -#define AMDGPU_PTE_FRAG(x) ((x & 0x1f) << 7) - -/* How to programm VM fault handling */ -#define AMDGPU_VM_FAULT_STOP_NEVER 0 -#define AMDGPU_VM_FAULT_STOP_FIRST 1 -#define AMDGPU_VM_FAULT_STOP_ALWAYS 2 - -struct amdgpu_vm_pt { - struct amdgpu_bo *bo; - uint64_t addr; -}; - -struct amdgpu_vm { - /* tree of virtual addresses mapped */ - struct rb_root va; - - /* protecting invalidated */ - spinlock_t status_lock; - - /* BOs moved, but not yet updated in the PT */ - struct list_head invalidated; - - /* BOs cleared in the PT because of a move */ - struct list_head cleared; - - /* BO mappings freed, but not yet updated in the PT */ - struct list_head freed; - - /* contains the page directory */ - struct amdgpu_bo *page_directory; - unsigned max_pde_used; - struct fence *page_directory_fence; - uint64_t last_eviction_counter; - - /* array of page tables, one for each page directory entry */ - struct amdgpu_vm_pt *page_tables; - - /* for id and flush management per ring */ - struct amdgpu_vm_id *ids[AMDGPU_MAX_RINGS]; - - /* protecting freed */ - spinlock_t freed_lock; - - /* Scheduler entity for page table updates */ - struct amd_sched_entity entity; - - /* client id */ - u64 client_id; -}; - -struct amdgpu_vm_id { - struct list_head list; - struct fence *first; - struct amdgpu_sync active; - struct fence *last_flush; - atomic64_t owner; - - uint64_t pd_gpu_addr; - /* last flushed PD/PT update */ - struct fence *flushed_updates; - - uint32_t current_gpu_reset_count; - - uint32_t gds_base; - uint32_t gds_size; - uint32_t gws_base; - uint32_t gws_size; - uint32_t oa_base; - uint32_t oa_size; -}; - -struct amdgpu_vm_manager { - /* Handling of VMIDs */ - struct mutex lock; - unsigned num_ids; - struct list_head ids_lru; - struct amdgpu_vm_id ids[AMDGPU_NUM_VM]; - - /* Handling of VM fences */ - u64 fence_context; - unsigned seqno[AMDGPU_MAX_RINGS]; - - uint32_t max_pfn; - /* vram base address for page table entry */ - u64 vram_base_offset; - /* is vm enabled? */ - bool enabled; - /* vm pte handling */ - const struct amdgpu_vm_pte_funcs *vm_pte_funcs; - struct amdgpu_ring *vm_pte_rings[AMDGPU_MAX_RINGS]; - unsigned vm_pte_num_rings; - atomic_t vm_pte_next_ring; - /* client id counter */ - atomic64_t client_counter; -}; - -void amdgpu_vm_manager_init(struct amdgpu_device *adev); -void amdgpu_vm_manager_fini(struct amdgpu_device *adev); -int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); -void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); -void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, - struct list_head *validated, - struct amdgpu_bo_list_entry *entry); -int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, - int (*callback)(void *p, struct amdgpu_bo *bo), - void *param); -void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, - struct amdgpu_vm *vm); -int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, - struct amdgpu_sync *sync, struct fence *fence, - struct amdgpu_job *job); -int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job); -void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id); -int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, - struct amdgpu_vm *vm); -int amdgpu_vm_clear_freed(struct amdgpu_device *adev, - struct amdgpu_vm *vm); -int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct amdgpu_sync *sync); -int amdgpu_vm_bo_update(struct amdgpu_device *adev, - struct amdgpu_bo_va *bo_va, - bool clear); -void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, - struct amdgpu_bo *bo); -struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm, - struct amdgpu_bo *bo); -struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct amdgpu_bo *bo); -int amdgpu_vm_bo_map(struct amdgpu_device *adev, - struct amdgpu_bo_va *bo_va, - uint64_t addr, uint64_t offset, - uint64_t size, uint32_t flags); -int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, - struct amdgpu_bo_va *bo_va, - uint64_t addr); -void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, - struct amdgpu_bo_va *bo_va); - /* * context related structures */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h new file mode 100644 index 000000000000..42a629b56095 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -0,0 +1,205 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ +#ifndef __AMDGPU_VM_H__ +#define __AMDGPU_VM_H__ + +#include + +#include "gpu_scheduler.h" +#include "amdgpu_sync.h" +#include "amdgpu_ring.h" + +struct amdgpu_bo_va; +struct amdgpu_job; +struct amdgpu_bo_list_entry; + +/* + * GPUVM handling + */ + +/* maximum number of VMIDs */ +#define AMDGPU_NUM_VM 16 + +/* Maximum number of PTEs the hardware can write with one command */ +#define AMDGPU_VM_MAX_UPDATE_SIZE 0x3FFFF + +/* number of entries in page table */ +#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size) + +/* PTBs (Page Table Blocks) need to be aligned to 32K */ +#define AMDGPU_VM_PTB_ALIGN_SIZE 32768 + +/* LOG2 number of continuous pages for the fragment field */ +#define AMDGPU_LOG2_PAGES_PER_FRAG 4 + +#define AMDGPU_PTE_VALID (1 << 0) +#define AMDGPU_PTE_SYSTEM (1 << 1) +#define AMDGPU_PTE_SNOOPED (1 << 2) + +/* VI only */ +#define AMDGPU_PTE_EXECUTABLE (1 << 4) + +#define AMDGPU_PTE_READABLE (1 << 5) +#define AMDGPU_PTE_WRITEABLE (1 << 6) + +#define AMDGPU_PTE_FRAG(x) ((x & 0x1f) << 7) + +/* How to programm VM fault handling */ +#define AMDGPU_VM_FAULT_STOP_NEVER 0 +#define AMDGPU_VM_FAULT_STOP_FIRST 1 +#define AMDGPU_VM_FAULT_STOP_ALWAYS 2 + +struct amdgpu_vm_pt { + struct amdgpu_bo *bo; + uint64_t addr; +}; + +struct amdgpu_vm { + /* tree of virtual addresses mapped */ + struct rb_root va; + + /* protecting invalidated */ + spinlock_t status_lock; + + /* BOs moved, but not yet updated in the PT */ + struct list_head invalidated; + + /* BOs cleared in the PT because of a move */ + struct list_head cleared; + + /* BO mappings freed, but not yet updated in the PT */ + struct list_head freed; + + /* contains the page directory */ + struct amdgpu_bo *page_directory; + unsigned max_pde_used; + struct fence *page_directory_fence; + uint64_t last_eviction_counter; + + /* array of page tables, one for each page directory entry */ + struct amdgpu_vm_pt *page_tables; + + /* for id and flush management per ring */ + struct amdgpu_vm_id *ids[AMDGPU_MAX_RINGS]; + + /* protecting freed */ + spinlock_t freed_lock; + + /* Scheduler entity for page table updates */ + struct amd_sched_entity entity; + + /* client id */ + u64 client_id; +}; + +struct amdgpu_vm_id { + struct list_head list; + struct fence *first; + struct amdgpu_sync active; + struct fence *last_flush; + atomic64_t owner; + + uint64_t pd_gpu_addr; + /* last flushed PD/PT update */ + struct fence *flushed_updates; + + uint32_t current_gpu_reset_count; + + uint32_t gds_base; + uint32_t gds_size; + uint32_t gws_base; + uint32_t gws_size; + uint32_t oa_base; + uint32_t oa_size; +}; + +struct amdgpu_vm_manager { + /* Handling of VMIDs */ + struct mutex lock; + unsigned num_ids; + struct list_head ids_lru; + struct amdgpu_vm_id ids[AMDGPU_NUM_VM]; + + /* Handling of VM fences */ + u64 fence_context; + unsigned seqno[AMDGPU_MAX_RINGS]; + + uint32_t max_pfn; + /* vram base address for page table entry */ + u64 vram_base_offset; + /* is vm enabled? */ + bool enabled; + /* vm pte handling */ + const struct amdgpu_vm_pte_funcs *vm_pte_funcs; + struct amdgpu_ring *vm_pte_rings[AMDGPU_MAX_RINGS]; + unsigned vm_pte_num_rings; + atomic_t vm_pte_next_ring; + /* client id counter */ + atomic64_t client_counter; +}; + +void amdgpu_vm_manager_init(struct amdgpu_device *adev); +void amdgpu_vm_manager_fini(struct amdgpu_device *adev); +int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); +void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); +void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, + struct list_head *validated, + struct amdgpu_bo_list_entry *entry); +int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, + int (*callback)(void *p, struct amdgpu_bo *bo), + void *param); +void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, + struct amdgpu_vm *vm); +int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, + struct amdgpu_sync *sync, struct fence *fence, + struct amdgpu_job *job); +int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job); +void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id); +int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, + struct amdgpu_vm *vm); +int amdgpu_vm_clear_freed(struct amdgpu_device *adev, + struct amdgpu_vm *vm); +int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm, + struct amdgpu_sync *sync); +int amdgpu_vm_bo_update(struct amdgpu_device *adev, + struct amdgpu_bo_va *bo_va, + bool clear); +void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, + struct amdgpu_bo *bo); +struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm, + struct amdgpu_bo *bo); +struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, + struct amdgpu_vm *vm, + struct amdgpu_bo *bo); +int amdgpu_vm_bo_map(struct amdgpu_device *adev, + struct amdgpu_bo_va *bo_va, + uint64_t addr, uint64_t offset, + uint64_t size, uint32_t flags); +int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, + struct amdgpu_bo_va *bo_va, + uint64_t addr); +void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, + struct amdgpu_bo_va *bo_va); + +#endif -- cgit v1.2.3 From b88c8796d815f80b958d6a35043d16d74bdfed24 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Sep 2016 16:33:01 +0200 Subject: drm/amdgpu: use amdgpu_vm_get_pd_bo in the GEM code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of messing with the PD directly. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 5dc0158b12db..cd62f6ffde2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -553,7 +553,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, struct amdgpu_fpriv *fpriv = filp->driver_priv; struct amdgpu_bo *abo; struct amdgpu_bo_va *bo_va; - struct ttm_validate_buffer tv, tv_pd; + struct amdgpu_bo_list_entry vm_pd; + struct ttm_validate_buffer tv; struct ww_acquire_ctx ticket; struct list_head list, duplicates; uint32_t invalid_flags, va_flags = 0; @@ -598,9 +599,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, tv.shared = true; list_add(&tv.head, &list); - tv_pd.bo = &fpriv->vm.page_directory->tbo; - tv_pd.shared = true; - list_add(&tv_pd.head, &list); + amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd); r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); if (r) { -- cgit v1.2.3 From e3fa76306f072e1c92b50f866c2583d74ace58ed Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Oct 2016 10:56:21 -0400 Subject: drm/amdgpu: add additional cached gca config variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to cache some additional values to handle SR-IOV and PG. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 7d30a8e03bed..efbd9ef41785 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -770,6 +770,16 @@ struct amdgpu_scratch { /* * GFX configurations */ +#define AMDGPU_GFX_MAX_SE 4 +#define AMDGPU_GFX_MAX_SH_PER_SE 2 + +struct amdgpu_rb_config { + uint32_t rb_backend_disable; + uint32_t user_rb_backend_disable; + uint32_t raster_config; + uint32_t raster_config_1; +}; + struct amdgpu_gca_config { unsigned max_shader_engines; unsigned max_tile_pipes; @@ -798,6 +808,8 @@ struct amdgpu_gca_config { uint32_t tile_mode_array[32]; uint32_t macrotile_mode_array[16]; + + struct amdgpu_rb_config rb_config[AMDGPU_GFX_MAX_SE][AMDGPU_GFX_MAX_SH_PER_SE]; }; struct amdgpu_cu_info { -- cgit v1.2.3 From 392f0c775c80de0eae4c07227cc220015df70abc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Oct 2016 11:15:24 -0400 Subject: drm/amdgpu/gfx8: cache rb config values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed when for SR-IOV and when PG is enabled. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index ba36db8002e7..e0664415b18e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3694,6 +3694,21 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev) num_rb_pipes); } + /* cache the values for userspace */ + for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { + for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { + gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff); + adev->gfx.config.rb_config[i][j].rb_backend_disable = + RREG32(mmCC_RB_BACKEND_DISABLE); + adev->gfx.config.rb_config[i][j].user_rb_backend_disable = + RREG32(mmGC_USER_RB_BACKEND_DISABLE); + adev->gfx.config.rb_config[i][j].raster_config = + RREG32(mmPA_SC_RASTER_CONFIG); + adev->gfx.config.rb_config[i][j].raster_config_1 = + RREG32(mmPA_SC_RASTER_CONFIG_1); + } + } + gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); } -- cgit v1.2.3 From 34817db6c73d110d460daf02b977f583caa05a97 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Oct 2016 11:17:58 -0400 Subject: drm/amdgpu/gfx8: use cached raster config values in csb setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the code and properly set the csb for harvest values. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index e0664415b18e..8dc8f576d2c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1140,34 +1140,8 @@ static void gfx_v8_0_get_csb_buffer(struct amdgpu_device *adev, buffer[count++] = cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, 2)); buffer[count++] = cpu_to_le32(mmPA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START); - switch (adev->asic_type) { - case CHIP_TONGA: - case CHIP_POLARIS10: - buffer[count++] = cpu_to_le32(0x16000012); - buffer[count++] = cpu_to_le32(0x0000002A); - break; - case CHIP_POLARIS11: - buffer[count++] = cpu_to_le32(0x16000012); - buffer[count++] = cpu_to_le32(0x00000000); - break; - case CHIP_FIJI: - buffer[count++] = cpu_to_le32(0x3a00161a); - buffer[count++] = cpu_to_le32(0x0000002e); - break; - case CHIP_TOPAZ: - case CHIP_CARRIZO: - buffer[count++] = cpu_to_le32(0x00000002); - buffer[count++] = cpu_to_le32(0x00000000); - break; - case CHIP_STONEY: - buffer[count++] = cpu_to_le32(0x00000000); - buffer[count++] = cpu_to_le32(0x00000000); - break; - default: - buffer[count++] = cpu_to_le32(0x00000000); - buffer[count++] = cpu_to_le32(0x00000000); - break; - } + buffer[count++] = cpu_to_le32(adev->gfx.config.rb_config[0][0].raster_config); + buffer[count++] = cpu_to_le32(adev->gfx.config.rb_config[0][0].raster_config_1); buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0)); buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_END_CLEAR_STATE); -- cgit v1.2.3 From db9635cc14f316346c5b3954153d7e8c7016105d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Oct 2016 12:05:32 -0400 Subject: drm/amdgpu: used cached gca values for vi_read_register (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the cached values has less latency for bare metal and SR-IOV, and prevents reading back bogus values if the engine is powergated. v2: fix typo in tile idx calculation Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 117 +++++++++++++++++++++++++++++++++------- 1 file changed, 97 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 657de2a9ba34..82f72cd1aebe 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -556,21 +556,100 @@ static const struct amdgpu_allowed_register_entry vi_allowed_read_registers[] = {mmPA_SC_RASTER_CONFIG_1, false, true}, }; -static uint32_t vi_read_indexed_register(struct amdgpu_device *adev, u32 se_num, - u32 sh_num, u32 reg_offset) -{ - uint32_t val; +static uint32_t vi_get_register_value(struct amdgpu_device *adev, + bool indexed, u32 se_num, + u32 sh_num, u32 reg_offset) +{ + if (indexed) { + uint32_t val; + unsigned se_idx = (se_num == 0xffffffff) ? 0 : se_num; + unsigned sh_idx = (sh_num == 0xffffffff) ? 0 : sh_num; + + switch (reg_offset) { + case mmCC_RB_BACKEND_DISABLE: + return adev->gfx.config.rb_config[se_idx][sh_idx].rb_backend_disable; + case mmGC_USER_RB_BACKEND_DISABLE: + return adev->gfx.config.rb_config[se_idx][sh_idx].user_rb_backend_disable; + case mmPA_SC_RASTER_CONFIG: + return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config; + case mmPA_SC_RASTER_CONFIG_1: + return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config_1; + } - mutex_lock(&adev->grbm_idx_mutex); - if (se_num != 0xffffffff || sh_num != 0xffffffff) - amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff); + mutex_lock(&adev->grbm_idx_mutex); + if (se_num != 0xffffffff || sh_num != 0xffffffff) + amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff); - val = RREG32(reg_offset); + val = RREG32(reg_offset); - if (se_num != 0xffffffff || sh_num != 0xffffffff) - amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); - mutex_unlock(&adev->grbm_idx_mutex); - return val; + if (se_num != 0xffffffff || sh_num != 0xffffffff) + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); + return val; + } else { + unsigned idx; + + switch (reg_offset) { + case mmGB_ADDR_CONFIG: + return adev->gfx.config.gb_addr_config; + case mmMC_ARB_RAMCFG: + return adev->gfx.config.mc_arb_ramcfg; + case mmGB_TILE_MODE0: + case mmGB_TILE_MODE1: + case mmGB_TILE_MODE2: + case mmGB_TILE_MODE3: + case mmGB_TILE_MODE4: + case mmGB_TILE_MODE5: + case mmGB_TILE_MODE6: + case mmGB_TILE_MODE7: + case mmGB_TILE_MODE8: + case mmGB_TILE_MODE9: + case mmGB_TILE_MODE10: + case mmGB_TILE_MODE11: + case mmGB_TILE_MODE12: + case mmGB_TILE_MODE13: + case mmGB_TILE_MODE14: + case mmGB_TILE_MODE15: + case mmGB_TILE_MODE16: + case mmGB_TILE_MODE17: + case mmGB_TILE_MODE18: + case mmGB_TILE_MODE19: + case mmGB_TILE_MODE20: + case mmGB_TILE_MODE21: + case mmGB_TILE_MODE22: + case mmGB_TILE_MODE23: + case mmGB_TILE_MODE24: + case mmGB_TILE_MODE25: + case mmGB_TILE_MODE26: + case mmGB_TILE_MODE27: + case mmGB_TILE_MODE28: + case mmGB_TILE_MODE29: + case mmGB_TILE_MODE30: + case mmGB_TILE_MODE31: + idx = (reg_offset - mmGB_TILE_MODE0); + return adev->gfx.config.tile_mode_array[idx]; + case mmGB_MACROTILE_MODE0: + case mmGB_MACROTILE_MODE1: + case mmGB_MACROTILE_MODE2: + case mmGB_MACROTILE_MODE3: + case mmGB_MACROTILE_MODE4: + case mmGB_MACROTILE_MODE5: + case mmGB_MACROTILE_MODE6: + case mmGB_MACROTILE_MODE7: + case mmGB_MACROTILE_MODE8: + case mmGB_MACROTILE_MODE9: + case mmGB_MACROTILE_MODE10: + case mmGB_MACROTILE_MODE11: + case mmGB_MACROTILE_MODE12: + case mmGB_MACROTILE_MODE13: + case mmGB_MACROTILE_MODE14: + case mmGB_MACROTILE_MODE15: + idx = (reg_offset - mmGB_MACROTILE_MODE0); + return adev->gfx.config.macrotile_mode_array[idx]; + default: + return RREG32(reg_offset); + } + } } static int vi_read_register(struct amdgpu_device *adev, u32 se_num, @@ -605,10 +684,9 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num, if (reg_offset != asic_register_entry->reg_offset) continue; if (!asic_register_entry->untouched) - *value = asic_register_entry->grbm_indexed ? - vi_read_indexed_register(adev, se_num, - sh_num, reg_offset) : - RREG32(reg_offset); + *value = vi_get_register_value(adev, + asic_register_entry->grbm_indexed, + se_num, sh_num, reg_offset); return 0; } } @@ -618,10 +696,9 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num, continue; if (!vi_allowed_read_registers[i].untouched) - *value = vi_allowed_read_registers[i].grbm_indexed ? - vi_read_indexed_register(adev, se_num, - sh_num, reg_offset) : - RREG32(reg_offset); + *value = vi_get_register_value(adev, + vi_allowed_read_registers[i].grbm_indexed, + se_num, sh_num, reg_offset); return 0; } return -EINVAL; -- cgit v1.2.3 From a0a71e49f533fe67c71abd5f3a0adf2fd10769f2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Oct 2016 12:41:36 -0400 Subject: drm/amdgpu: clarify why we evict vram twice on suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the comment to explain why we do this. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 9df66d1e843d..afeb7ab16d09 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1982,7 +1982,10 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) r = amdgpu_suspend(adev); - /* evict remaining vram memory */ + /* evict remaining vram memory + * This second call to evict vram is to evict the gart page table + * using the CPU. + */ amdgpu_bo_evict_vram(adev); pci_save_state(dev->pdev); -- cgit v1.2.3 From ec9aaaff66668217c0c5634d062b350429d8cfd2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Oct 2016 12:42:33 -0400 Subject: drm/radeon: clarify why we evict vram twice on suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the comment to explain why we do this. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index eb92aef46e3c..79c9b6f3f013 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1651,7 +1651,10 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, radeon_suspend(rdev); radeon_hpd_fini(rdev); - /* evict remaining vram memory */ + /* evict remaining vram memory + * This second call to evict vram is to evict the gart page table + * using the CPU. + */ radeon_bo_evict_vram(rdev); radeon_agp_suspend(rdev); -- cgit v1.2.3 From 66f3b2d527154bd258a57c8815004b5964aa1cf5 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 5 Oct 2016 12:38:21 +0200 Subject: drm/amdgpu: pad gfx and compute rings to 256 dw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same as on windows to avoid further problems with CE/DE command submission overlaps. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 40abb6b81c09..e3be5bd7ec50 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -2896,7 +2896,7 @@ static int gfx_v6_0_sw_init(void *handle) ring->ring_obj = NULL; sprintf(ring->name, "gfx"); r = amdgpu_ring_init(adev, ring, 1024, - 0x80000000, 0xf, + 0x80000000, 0xff, &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP, AMDGPU_RING_TYPE_GFX); if (r) @@ -2920,7 +2920,7 @@ static int gfx_v6_0_sw_init(void *handle) sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue); irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; r = amdgpu_ring_init(adev, ring, 1024, - 0x80000000, 0xf, + 0x80000000, 0xff, &adev->gfx.eop_irq, irq_type, AMDGPU_RING_TYPE_COMPUTE); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index b2cf1290c1cf..e239e1db3ab0 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4646,7 +4646,7 @@ static int gfx_v7_0_sw_init(void *handle) ring->ring_obj = NULL; sprintf(ring->name, "gfx"); r = amdgpu_ring_init(adev, ring, 1024, - PACKET3(PACKET3_NOP, 0x3FFF), 0xf, + PACKET3(PACKET3_NOP, 0x3FFF), 0xff, &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP, AMDGPU_RING_TYPE_GFX); if (r) @@ -4673,7 +4673,7 @@ static int gfx_v7_0_sw_init(void *handle) irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; /* type-2 packets are deprecated on MEC, use type-3 instead */ r = amdgpu_ring_init(adev, ring, 1024, - PACKET3(PACKET3_NOP, 0x3FFF), 0xf, + PACKET3(PACKET3_NOP, 0x3FFF), 0xff, &adev->gfx.eop_irq, irq_type, AMDGPU_RING_TYPE_COMPUTE); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 8dc8f576d2c7..8efcc8d2ad60 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -2035,7 +2035,7 @@ static int gfx_v8_0_sw_init(void *handle) } r = amdgpu_ring_init(adev, ring, 1024, - PACKET3(PACKET3_NOP, 0x3FFF), 0xf, + PACKET3(PACKET3_NOP, 0x3FFF), 0xff, &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP, AMDGPU_RING_TYPE_GFX); if (r) @@ -2062,7 +2062,7 @@ static int gfx_v8_0_sw_init(void *handle) irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; /* type-2 packets are deprecated on MEC, use type-3 instead */ r = amdgpu_ring_init(adev, ring, 1024, - PACKET3(PACKET3_NOP, 0x3FFF), 0xf, + PACKET3(PACKET3_NOP, 0x3FFF), 0xff, &adev->gfx.eop_irq, irq_type, AMDGPU_RING_TYPE_COMPUTE); if (r) -- cgit v1.2.3 From c81b07e6bcbc3a29270b4eaf5c0696837212d468 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 5 Oct 2016 12:51:57 +0200 Subject: drm/amdgpu: remove ring type check for conditional execution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a ring doesn't support that it shouldn't implement the function. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 6a6c86c9c169..3c9a6da0966e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -161,7 +161,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, return r; } - if (ring->type == AMDGPU_RING_TYPE_SDMA && ring->funcs->init_cond_exec) + if (ring->funcs->init_cond_exec) patch_offset = amdgpu_ring_init_cond_exec(ring); if (vm) { -- cgit v1.2.3 From e08c90a7746041d0816e32614fd161c2194c7ded Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 5 Oct 2016 12:59:20 +0200 Subject: drm/amdgpu: remove 128 NOP hack from vm_flush v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the padding raised to 256 DW that shouldn't be needed any more. v2: reduce estimation as well Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 8efcc8d2ad60..bb17538ff109 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6249,10 +6249,6 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring, { int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); - /* GFX8 emits 128 dw nop to prevent DE do vm_flush before CE finish CEIB */ - if (usepfp) - amdgpu_ring_insert_nop(ring, 128); - amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) | WRITE_DATA_DST_SEL(0)) | @@ -6381,7 +6377,7 @@ static unsigned gfx_v8_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring) 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */ 6 + 6 + 6 +/* gfx_v8_0_ring_emit_fence_gfx x3 for user fence, vm fence */ 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ - 256 + 19 + /* gfx_v8_0_ring_emit_vm_flush */ + 128 + 19 + /* gfx_v8_0_ring_emit_vm_flush */ 2 + /* gfx_v8_ring_emit_sb */ 3; /* gfx_v8_ring_emit_cntxcntl */ } -- cgit v1.2.3 From 7bc6be825a2efb00cf8a194e1d0560c92d5a2f6c Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 5 Oct 2016 14:23:00 +0200 Subject: drm/amdgpu: remove explicit NULL init for parse_cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sed -i "/\.parse_cs = NULL,/d" drivers/gpu/drm/amd/amdgpu/*.c That's just a leftover from radeon. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 1 - drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 2 -- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 2 -- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 -- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 1 - drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 1 - drivers/gpu/drm/amd/amdgpu/si_dma.c | 1 - drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 1 - drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 1 - 9 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index cb952acc7133..34e41590c5c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -1228,7 +1228,6 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = { .get_rptr = cik_sdma_ring_get_rptr, .get_wptr = cik_sdma_ring_get_wptr, .set_wptr = cik_sdma_ring_set_wptr, - .parse_cs = NULL, .emit_ib = cik_sdma_ring_emit_ib, .emit_fence = cik_sdma_ring_emit_fence, .emit_pipeline_sync = cik_sdma_ring_emit_pipeline_sync, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index e3be5bd7ec50..4e35e16d1311 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -3258,7 +3258,6 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_gfx, - .parse_cs = NULL, .emit_ib = gfx_v6_0_ring_emit_ib, .emit_fence = gfx_v6_0_ring_emit_fence, .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, @@ -3277,7 +3276,6 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_compute, - .parse_cs = NULL, .emit_ib = gfx_v6_0_ring_emit_ib, .emit_fence = gfx_v6_0_ring_emit_fence, .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index e239e1db3ab0..9a54ea982b87 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -5147,7 +5147,6 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_gfx, .set_wptr = gfx_v7_0_ring_set_wptr_gfx, - .parse_cs = NULL, .emit_ib = gfx_v7_0_ring_emit_ib_gfx, .emit_fence = gfx_v7_0_ring_emit_fence_gfx, .emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync, @@ -5168,7 +5167,6 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_compute, .set_wptr = gfx_v7_0_ring_set_wptr_compute, - .parse_cs = NULL, .emit_ib = gfx_v7_0_ring_emit_ib_compute, .emit_fence = gfx_v7_0_ring_emit_fence_compute, .emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index bb17538ff109..404c49c45b03 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6568,7 +6568,6 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_gfx, .set_wptr = gfx_v8_0_ring_set_wptr_gfx, - .parse_cs = NULL, .emit_ib = gfx_v8_0_ring_emit_ib_gfx, .emit_fence = gfx_v8_0_ring_emit_fence_gfx, .emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync, @@ -6590,7 +6589,6 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_compute, .set_wptr = gfx_v8_0_ring_set_wptr_compute, - .parse_cs = NULL, .emit_ib = gfx_v8_0_ring_emit_ib_compute, .emit_fence = gfx_v8_0_ring_emit_fence_compute, .emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 565dab3c7218..16cc1f5d0d4e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -1225,7 +1225,6 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { .get_rptr = sdma_v2_4_ring_get_rptr, .get_wptr = sdma_v2_4_ring_get_wptr, .set_wptr = sdma_v2_4_ring_set_wptr, - .parse_cs = NULL, .emit_ib = sdma_v2_4_ring_emit_ib, .emit_fence = sdma_v2_4_ring_emit_fence, .emit_pipeline_sync = sdma_v2_4_ring_emit_pipeline_sync, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index a9d10941fb53..2c2f24fff64b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1568,7 +1568,6 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { .get_rptr = sdma_v3_0_ring_get_rptr, .get_wptr = sdma_v3_0_ring_get_wptr, .set_wptr = sdma_v3_0_ring_set_wptr, - .parse_cs = NULL, .emit_ib = sdma_v3_0_ring_emit_ib, .emit_fence = sdma_v3_0_ring_emit_fence, .emit_pipeline_sync = sdma_v3_0_ring_emit_pipeline_sync, diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index de358193a8f9..9f11e3792077 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -783,7 +783,6 @@ static const struct amdgpu_ring_funcs si_dma_ring_funcs = { .get_rptr = si_dma_ring_get_rptr, .get_wptr = si_dma_ring_get_wptr, .set_wptr = si_dma_ring_set_wptr, - .parse_cs = NULL, .emit_ib = si_dma_ring_emit_ib, .emit_fence = si_dma_ring_emit_fence, .emit_pipeline_sync = si_dma_ring_emit_pipeline_sync, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index ab3df6d75656..f74229496cc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -1070,7 +1070,6 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = { .get_rptr = uvd_v6_0_ring_get_rptr, .get_wptr = uvd_v6_0_ring_get_wptr, .set_wptr = uvd_v6_0_ring_set_wptr, - .parse_cs = NULL, .emit_ib = uvd_v6_0_ring_emit_ib, .emit_fence = uvd_v6_0_ring_emit_fence, .emit_vm_flush = uvd_v6_0_ring_emit_vm_flush, diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 8533269ec160..e76bc092becc 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -870,7 +870,6 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { .get_rptr = vce_v3_0_ring_get_rptr, .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, - .parse_cs = NULL, .emit_ib = vce_v3_0_ring_emit_ib, .emit_vm_flush = vce_v3_0_emit_vm_flush, .emit_pipeline_sync = vce_v3_0_emit_pipeline_sync, -- cgit v1.2.3 From e12f3d7a23c99617f72305a805ed827567a43a9c Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 5 Oct 2016 14:29:38 +0200 Subject: drm/amdgpu: move IB and frame size directly into the engine description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I should have suggested that on the initial patchset. This saves us a few CPU cycles during CS and a bunch of loc. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 -- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 4 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 5 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 12 ------- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 25 ++++---------- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 46 +++++++++---------------- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 56 ++++++++++-------------------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 58 ++++++++++---------------------- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 25 ++++---------- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 25 ++++---------- drivers/gpu/drm/amd/amdgpu/si_dma.c | 25 ++++---------- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 21 +++--------- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 21 +++--------- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 42 +++++++---------------- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 4 +-- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 34 +++++-------------- 16 files changed, 117 insertions(+), 288 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index efbd9ef41785..fa99c0d6158c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1962,8 +1962,6 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib))) #define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r)) #define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o)) -#define amdgpu_ring_get_emit_ib_size(r) (r)->funcs->get_emit_ib_size((r)) -#define amdgpu_ring_get_dma_frame_size(r) (r)->funcs->get_dma_frame_size((r)) #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 3c9a6da0966e..16308eb22e7f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -152,8 +152,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, return -EINVAL; } - alloc_size = amdgpu_ring_get_dma_frame_size(ring) + - num_ibs * amdgpu_ring_get_emit_ib_size(ring); + alloc_size = ring->funcs->emit_frame_size + num_ibs * + ring->funcs->emit_ib_size; r = amdgpu_ring_alloc(ring, alloc_size); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 2f935888c64b..767843c2b1d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -98,6 +98,9 @@ struct amdgpu_ring_funcs { void (*set_wptr)(struct amdgpu_ring *ring); /* validating and patching of IBs */ int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx); + /* constants to calculate how many DW are needed for an emit */ + unsigned emit_frame_size; + unsigned emit_ib_size; /* command emit functions */ void (*emit_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib, @@ -127,8 +130,6 @@ struct amdgpu_ring_funcs { void (*end_use)(struct amdgpu_ring *ring); void (*emit_switch_buffer) (struct amdgpu_ring *ring); void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags); - unsigned (*get_emit_ib_size) (struct amdgpu_ring *ring); - unsigned (*get_dma_frame_size) (struct amdgpu_ring *ring); }; struct amdgpu_ring { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 9a534e2757cd..2fb469aa850a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -824,18 +824,6 @@ void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, amdgpu_ring_write(ring, VCE_CMD_END); } -unsigned amdgpu_vce_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 4; /* amdgpu_vce_ring_emit_ib */ -} - -unsigned amdgpu_vce_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 6; /* amdgpu_vce_ring_emit_fence x1 no user fence */ -} - /** * amdgpu_vce_ring_test_ring - test if VCE ring is working * diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index 34e41590c5c8..49b34decce58 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -848,22 +848,6 @@ static void cik_sdma_ring_emit_vm_flush(struct amdgpu_ring *ring, amdgpu_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */ } -static unsigned cik_sdma_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 7 + 4; /* cik_sdma_ring_emit_ib */ -} - -static unsigned cik_sdma_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 6 + /* cik_sdma_ring_emit_hdp_flush */ - 3 + /* cik_sdma_ring_emit_hdp_invalidate */ - 6 + /* cik_sdma_ring_emit_pipeline_sync */ - 12 + /* cik_sdma_ring_emit_vm_flush */ - 9 + 9 + 9; /* cik_sdma_ring_emit_fence x3 for user fence, vm fence */ -} - static void cik_enable_sdma_mgcg(struct amdgpu_device *adev, bool enable) { @@ -1228,6 +1212,13 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = { .get_rptr = cik_sdma_ring_get_rptr, .get_wptr = cik_sdma_ring_get_wptr, .set_wptr = cik_sdma_ring_set_wptr, + .emit_frame_size = + 6 + /* cik_sdma_ring_emit_hdp_flush */ + 3 + /* cik_sdma_ring_emit_hdp_invalidate */ + 6 + /* cik_sdma_ring_emit_pipeline_sync */ + 12 + /* cik_sdma_ring_emit_vm_flush */ + 9 + 9 + 9, /* cik_sdma_ring_emit_fence x3 for user fence, vm fence */ + .emit_ib_size = 7 + 4, /* cik_sdma_ring_emit_ib */ .emit_ib = cik_sdma_ring_emit_ib, .emit_fence = cik_sdma_ring_emit_fence, .emit_pipeline_sync = cik_sdma_ring_emit_pipeline_sync, @@ -1238,8 +1229,6 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = { .test_ib = cik_sdma_ring_test_ib, .insert_nop = cik_sdma_ring_insert_nop, .pad_ib = cik_sdma_ring_pad_ib, - .get_emit_ib_size = cik_sdma_ring_get_emit_ib_size, - .get_dma_frame_size = cik_sdma_ring_get_dma_frame_size, }; static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 4e35e16d1311..a86b17944bcf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -2814,33 +2814,6 @@ static void gfx_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) amdgpu_ring_write(ring, 0); } -static unsigned gfx_v6_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 6; /* gfx_v6_0_ring_emit_ib */ -} - -static unsigned gfx_v6_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring) -{ - return - 5 + /* gfx_v6_0_ring_emit_hdp_flush */ - 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */ - 14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */ - 7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */ - 17 + 6 + /* gfx_v6_0_ring_emit_vm_flush */ - 3; /* gfx_v6_ring_emit_cntxcntl */ -} - -static unsigned gfx_v6_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring) -{ - return - 5 + /* gfx_v6_0_ring_emit_hdp_flush */ - 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */ - 7 + /* gfx_v6_0_ring_emit_pipeline_sync */ - 17 + /* gfx_v6_0_ring_emit_vm_flush */ - 14 + 14 + 14; /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */ -} - static const struct amdgpu_gfx_funcs gfx_v6_0_gfx_funcs = { .get_gpu_clock_counter = &gfx_v6_0_get_gpu_clock_counter, .select_se_sh = &gfx_v6_0_select_se_sh, @@ -3258,6 +3231,14 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_gfx, + .emit_frame_size = + 5 + /* gfx_v6_0_ring_emit_hdp_flush */ + 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */ + 14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */ + 7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */ + 17 + 6 + /* gfx_v6_0_ring_emit_vm_flush */ + 3, /* gfx_v6_ring_emit_cntxcntl */ + .emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */ .emit_ib = gfx_v6_0_ring_emit_ib, .emit_fence = gfx_v6_0_ring_emit_fence, .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, @@ -3268,14 +3249,19 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .test_ib = gfx_v6_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .emit_cntxcntl = gfx_v6_ring_emit_cntxcntl, - .get_emit_ib_size = gfx_v6_0_ring_get_emit_ib_size, - .get_dma_frame_size = gfx_v6_0_ring_get_dma_frame_size_gfx, }; static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_compute, + .emit_frame_size = + 5 + /* gfx_v6_0_ring_emit_hdp_flush */ + 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */ + 7 + /* gfx_v6_0_ring_emit_pipeline_sync */ + 17 + /* gfx_v6_0_ring_emit_vm_flush */ + 14 + 14 + 14, /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */ + .emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */ .emit_ib = gfx_v6_0_ring_emit_ib, .emit_fence = gfx_v6_0_ring_emit_fence, .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, @@ -3285,8 +3271,6 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { .test_ring = gfx_v6_0_ring_test_ring, .test_ib = gfx_v6_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, - .get_emit_ib_size = gfx_v6_0_ring_get_emit_ib_size, - .get_dma_frame_size = gfx_v6_0_ring_get_dma_frame_size_compute, }; static void gfx_v6_0_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 9a54ea982b87..f2415f58c160 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4357,41 +4357,6 @@ static void gfx_v7_0_ring_emit_gds_switch(struct amdgpu_ring *ring, amdgpu_ring_write(ring, (1 << (oa_size + oa_base)) - (1 << oa_base)); } -static unsigned gfx_v7_0_ring_get_emit_ib_size_gfx(struct amdgpu_ring *ring) -{ - return - 4; /* gfx_v7_0_ring_emit_ib_gfx */ -} - -static unsigned gfx_v7_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring) -{ - return - 20 + /* gfx_v7_0_ring_emit_gds_switch */ - 7 + /* gfx_v7_0_ring_emit_hdp_flush */ - 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */ - 12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */ - 7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */ - 17 + 6 + /* gfx_v7_0_ring_emit_vm_flush */ - 3; /* gfx_v7_ring_emit_cntxcntl */ -} - -static unsigned gfx_v7_0_ring_get_emit_ib_size_compute(struct amdgpu_ring *ring) -{ - return - 4; /* gfx_v7_0_ring_emit_ib_compute */ -} - -static unsigned gfx_v7_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring) -{ - return - 20 + /* gfx_v7_0_ring_emit_gds_switch */ - 7 + /* gfx_v7_0_ring_emit_hdp_flush */ - 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */ - 7 + /* gfx_v7_0_ring_emit_pipeline_sync */ - 17 + /* gfx_v7_0_ring_emit_vm_flush */ - 7 + 7 + 7; /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */ -} - static const struct amdgpu_gfx_funcs gfx_v7_0_gfx_funcs = { .get_gpu_clock_counter = &gfx_v7_0_get_gpu_clock_counter, .select_se_sh = &gfx_v7_0_select_se_sh, @@ -5147,6 +5112,15 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_gfx, .set_wptr = gfx_v7_0_ring_set_wptr_gfx, + .emit_frame_size = + 20 + /* gfx_v7_0_ring_emit_gds_switch */ + 7 + /* gfx_v7_0_ring_emit_hdp_flush */ + 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */ + 12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */ + 7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */ + 17 + 6 + /* gfx_v7_0_ring_emit_vm_flush */ + 3, /* gfx_v7_ring_emit_cntxcntl */ + .emit_ib_size = 4, /* gfx_v7_0_ring_emit_ib_gfx */ .emit_ib = gfx_v7_0_ring_emit_ib_gfx, .emit_fence = gfx_v7_0_ring_emit_fence_gfx, .emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync, @@ -5159,14 +5133,20 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, .emit_cntxcntl = gfx_v7_ring_emit_cntxcntl, - .get_emit_ib_size = gfx_v7_0_ring_get_emit_ib_size_gfx, - .get_dma_frame_size = gfx_v7_0_ring_get_dma_frame_size_gfx, }; static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_compute, .set_wptr = gfx_v7_0_ring_set_wptr_compute, + .emit_frame_size = + 20 + /* gfx_v7_0_ring_emit_gds_switch */ + 7 + /* gfx_v7_0_ring_emit_hdp_flush */ + 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */ + 7 + /* gfx_v7_0_ring_emit_pipeline_sync */ + 17 + /* gfx_v7_0_ring_emit_vm_flush */ + 7 + 7 + 7, /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */ + .emit_ib_size = 4, /* gfx_v7_0_ring_emit_ib_compute */ .emit_ib = gfx_v7_0_ring_emit_ib_compute, .emit_fence = gfx_v7_0_ring_emit_fence_compute, .emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync, @@ -5178,8 +5158,6 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { .test_ib = gfx_v7_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, - .get_emit_ib_size = gfx_v7_0_ring_get_emit_ib_size_compute, - .get_dma_frame_size = gfx_v7_0_ring_get_dma_frame_size_compute, }; static void gfx_v7_0_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 404c49c45b03..e3330d06af9a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6363,42 +6363,6 @@ static void gfx_v8_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) amdgpu_ring_write(ring, 0); } -static unsigned gfx_v8_0_ring_get_emit_ib_size_gfx(struct amdgpu_ring *ring) -{ - return - 4; /* gfx_v8_0_ring_emit_ib_gfx */ -} - -static unsigned gfx_v8_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring) -{ - return - 20 + /* gfx_v8_0_ring_emit_gds_switch */ - 7 + /* gfx_v8_0_ring_emit_hdp_flush */ - 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */ - 6 + 6 + 6 +/* gfx_v8_0_ring_emit_fence_gfx x3 for user fence, vm fence */ - 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ - 128 + 19 + /* gfx_v8_0_ring_emit_vm_flush */ - 2 + /* gfx_v8_ring_emit_sb */ - 3; /* gfx_v8_ring_emit_cntxcntl */ -} - -static unsigned gfx_v8_0_ring_get_emit_ib_size_compute(struct amdgpu_ring *ring) -{ - return - 4; /* gfx_v8_0_ring_emit_ib_compute */ -} - -static unsigned gfx_v8_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring) -{ - return - 20 + /* gfx_v8_0_ring_emit_gds_switch */ - 7 + /* gfx_v8_0_ring_emit_hdp_flush */ - 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */ - 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ - 17 + /* gfx_v8_0_ring_emit_vm_flush */ - 7 + 7 + 7; /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */ -} - static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, enum amdgpu_interrupt_state state) { @@ -6568,6 +6532,16 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_gfx, .set_wptr = gfx_v8_0_ring_set_wptr_gfx, + .emit_frame_size = + 20 + /* gfx_v8_0_ring_emit_gds_switch */ + 7 + /* gfx_v8_0_ring_emit_hdp_flush */ + 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */ + 6 + 6 + 6 +/* gfx_v8_0_ring_emit_fence_gfx x3 for user fence, vm fence */ + 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ + 128 + 19 + /* gfx_v8_0_ring_emit_vm_flush */ + 2 + /* gfx_v8_ring_emit_sb */ + 3, /* gfx_v8_ring_emit_cntxcntl */ + .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_gfx */ .emit_ib = gfx_v8_0_ring_emit_ib_gfx, .emit_fence = gfx_v8_0_ring_emit_fence_gfx, .emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync, @@ -6581,14 +6555,20 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .pad_ib = amdgpu_ring_generic_pad_ib, .emit_switch_buffer = gfx_v8_ring_emit_sb, .emit_cntxcntl = gfx_v8_ring_emit_cntxcntl, - .get_emit_ib_size = gfx_v8_0_ring_get_emit_ib_size_gfx, - .get_dma_frame_size = gfx_v8_0_ring_get_dma_frame_size_gfx, }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_compute, .set_wptr = gfx_v8_0_ring_set_wptr_compute, + .emit_frame_size = + 20 + /* gfx_v8_0_ring_emit_gds_switch */ + 7 + /* gfx_v8_0_ring_emit_hdp_flush */ + 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */ + 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ + 17 + /* gfx_v8_0_ring_emit_vm_flush */ + 7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */ + .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_compute */ .emit_ib = gfx_v8_0_ring_emit_ib_compute, .emit_fence = gfx_v8_0_ring_emit_fence_compute, .emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync, @@ -6600,8 +6580,6 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { .test_ib = gfx_v8_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, - .get_emit_ib_size = gfx_v8_0_ring_get_emit_ib_size_compute, - .get_dma_frame_size = gfx_v8_0_ring_get_dma_frame_size_compute, }; static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 16cc1f5d0d4e..7cd24e42aa9a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -902,22 +902,6 @@ static void sdma_v2_4_ring_emit_vm_flush(struct amdgpu_ring *ring, SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */ } -static unsigned sdma_v2_4_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 7 + 6; /* sdma_v2_4_ring_emit_ib */ -} - -static unsigned sdma_v2_4_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 6 + /* sdma_v2_4_ring_emit_hdp_flush */ - 3 + /* sdma_v2_4_ring_emit_hdp_invalidate */ - 6 + /* sdma_v2_4_ring_emit_pipeline_sync */ - 12 + /* sdma_v2_4_ring_emit_vm_flush */ - 10 + 10 + 10; /* sdma_v2_4_ring_emit_fence x3 for user fence, vm fence */ -} - static int sdma_v2_4_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1225,6 +1209,13 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { .get_rptr = sdma_v2_4_ring_get_rptr, .get_wptr = sdma_v2_4_ring_get_wptr, .set_wptr = sdma_v2_4_ring_set_wptr, + .emit_frame_size = + 6 + /* sdma_v2_4_ring_emit_hdp_flush */ + 3 + /* sdma_v2_4_ring_emit_hdp_invalidate */ + 6 + /* sdma_v2_4_ring_emit_pipeline_sync */ + 12 + /* sdma_v2_4_ring_emit_vm_flush */ + 10 + 10 + 10, /* sdma_v2_4_ring_emit_fence x3 for user fence, vm fence */ + .emit_ib_size = 7 + 6, /* sdma_v2_4_ring_emit_ib */ .emit_ib = sdma_v2_4_ring_emit_ib, .emit_fence = sdma_v2_4_ring_emit_fence, .emit_pipeline_sync = sdma_v2_4_ring_emit_pipeline_sync, @@ -1235,8 +1226,6 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { .test_ib = sdma_v2_4_ring_test_ib, .insert_nop = sdma_v2_4_ring_insert_nop, .pad_ib = sdma_v2_4_ring_pad_ib, - .get_emit_ib_size = sdma_v2_4_ring_get_emit_ib_size, - .get_dma_frame_size = sdma_v2_4_ring_get_dma_frame_size, }; static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 2c2f24fff64b..6518993e23a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1104,22 +1104,6 @@ static void sdma_v3_0_ring_emit_vm_flush(struct amdgpu_ring *ring, SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */ } -static unsigned sdma_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 7 + 6; /* sdma_v3_0_ring_emit_ib */ -} - -static unsigned sdma_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 6 + /* sdma_v3_0_ring_emit_hdp_flush */ - 3 + /* sdma_v3_0_ring_emit_hdp_invalidate */ - 6 + /* sdma_v3_0_ring_emit_pipeline_sync */ - 12 + /* sdma_v3_0_ring_emit_vm_flush */ - 10 + 10 + 10; /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */ -} - static int sdma_v3_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1568,6 +1552,13 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { .get_rptr = sdma_v3_0_ring_get_rptr, .get_wptr = sdma_v3_0_ring_get_wptr, .set_wptr = sdma_v3_0_ring_set_wptr, + .emit_frame_size = + 6 + /* sdma_v3_0_ring_emit_hdp_flush */ + 3 + /* sdma_v3_0_ring_emit_hdp_invalidate */ + 6 + /* sdma_v3_0_ring_emit_pipeline_sync */ + 12 + /* sdma_v3_0_ring_emit_vm_flush */ + 10 + 10 + 10, /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */ + .emit_ib_size = 7 + 6, /* sdma_v3_0_ring_emit_ib */ .emit_ib = sdma_v3_0_ring_emit_ib, .emit_fence = sdma_v3_0_ring_emit_fence, .emit_pipeline_sync = sdma_v3_0_ring_emit_pipeline_sync, @@ -1578,8 +1569,6 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { .test_ib = sdma_v3_0_ring_test_ib, .insert_nop = sdma_v3_0_ring_insert_nop, .pad_ib = sdma_v3_0_ring_pad_ib, - .get_emit_ib_size = sdma_v3_0_ring_get_emit_ib_size, - .get_dma_frame_size = sdma_v3_0_ring_get_dma_frame_size, }; static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 9f11e3792077..c1c1b5179de5 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -495,22 +495,6 @@ static void si_dma_ring_emit_vm_flush(struct amdgpu_ring *ring, amdgpu_ring_write(ring, (0 << 28) | 0x20); /* func(always) | poll interval */ } -static unsigned si_dma_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 7 + 3; /* si_dma_ring_emit_ib */ -} - -static unsigned si_dma_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 3 + /* si_dma_ring_emit_hdp_flush */ - 3 + /* si_dma_ring_emit_hdp_invalidate */ - 6 + /* si_dma_ring_emit_pipeline_sync */ - 12 + /* si_dma_ring_emit_vm_flush */ - 9 + 9 + 9; /* si_dma_ring_emit_fence x3 for user fence, vm fence */ -} - static int si_dma_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -783,6 +767,13 @@ static const struct amdgpu_ring_funcs si_dma_ring_funcs = { .get_rptr = si_dma_ring_get_rptr, .get_wptr = si_dma_ring_get_wptr, .set_wptr = si_dma_ring_set_wptr, + .emit_frame_size = + 3 + /* si_dma_ring_emit_hdp_flush */ + 3 + /* si_dma_ring_emit_hdp_invalidate */ + 6 + /* si_dma_ring_emit_pipeline_sync */ + 12 + /* si_dma_ring_emit_vm_flush */ + 9 + 9 + 9, /* si_dma_ring_emit_fence x3 for user fence, vm fence */ + .emit_ib_size = 7 + 3, /* si_dma_ring_emit_ib */ .emit_ib = si_dma_ring_emit_ib, .emit_fence = si_dma_ring_emit_fence, .emit_pipeline_sync = si_dma_ring_emit_pipeline_sync, @@ -793,8 +784,6 @@ static const struct amdgpu_ring_funcs si_dma_ring_funcs = { .test_ib = si_dma_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = si_dma_ring_pad_ib, - .get_emit_ib_size = si_dma_ring_get_emit_ib_size, - .get_dma_frame_size = si_dma_ring_get_dma_frame_size, }; static void si_dma_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index f6c941550b8f..708de997e3b0 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -526,20 +526,6 @@ static void uvd_v4_2_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, ib->length_dw); } -static unsigned uvd_v4_2_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 4; /* uvd_v4_2_ring_emit_ib */ -} - -static unsigned uvd_v4_2_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 2 + /* uvd_v4_2_ring_emit_hdp_flush */ - 2 + /* uvd_v4_2_ring_emit_hdp_invalidate */ - 14; /* uvd_v4_2_ring_emit_fence x1 no user fence */ -} - /** * uvd_v4_2_mc_resume - memory controller programming * @@ -760,6 +746,11 @@ static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = { .get_wptr = uvd_v4_2_ring_get_wptr, .set_wptr = uvd_v4_2_ring_set_wptr, .parse_cs = amdgpu_uvd_ring_parse_cs, + .emit_frame_size = + 2 + /* uvd_v4_2_ring_emit_hdp_flush */ + 2 + /* uvd_v4_2_ring_emit_hdp_invalidate */ + 14, /* uvd_v4_2_ring_emit_fence x1 no user fence */ + .emit_ib_size = 4, /* uvd_v4_2_ring_emit_ib */ .emit_ib = uvd_v4_2_ring_emit_ib, .emit_fence = uvd_v4_2_ring_emit_fence, .emit_hdp_flush = uvd_v4_2_ring_emit_hdp_flush, @@ -770,8 +761,6 @@ static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_uvd_ring_begin_use, .end_use = amdgpu_uvd_ring_end_use, - .get_emit_ib_size = uvd_v4_2_ring_get_emit_ib_size, - .get_dma_frame_size = uvd_v4_2_ring_get_dma_frame_size, }; static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index 400c16fe579e..9e695e01f8b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -577,20 +577,6 @@ static void uvd_v5_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, ib->length_dw); } -static unsigned uvd_v5_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 6; /* uvd_v5_0_ring_emit_ib */ -} - -static unsigned uvd_v5_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 2 + /* uvd_v5_0_ring_emit_hdp_flush */ - 2 + /* uvd_v5_0_ring_emit_hdp_invalidate */ - 14; /* uvd_v5_0_ring_emit_fence x1 no user fence */ -} - static bool uvd_v5_0_is_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -811,6 +797,11 @@ static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = { .get_wptr = uvd_v5_0_ring_get_wptr, .set_wptr = uvd_v5_0_ring_set_wptr, .parse_cs = amdgpu_uvd_ring_parse_cs, + .emit_frame_size = + 2 + /* uvd_v5_0_ring_emit_hdp_flush */ + 2 + /* uvd_v5_0_ring_emit_hdp_invalidate */ + 14, /* uvd_v5_0_ring_emit_fence x1 no user fence */ + .emit_ib_size = 6, /* uvd_v5_0_ring_emit_ib */ .emit_ib = uvd_v5_0_ring_emit_ib, .emit_fence = uvd_v5_0_ring_emit_fence, .emit_hdp_flush = uvd_v5_0_ring_emit_hdp_flush, @@ -821,8 +812,6 @@ static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_uvd_ring_begin_use, .end_use = amdgpu_uvd_ring_end_use, - .get_emit_ib_size = uvd_v5_0_ring_get_emit_ib_size, - .get_dma_frame_size = uvd_v5_0_ring_get_dma_frame_size, }; static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index f74229496cc7..aeb1b6e2c518 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -725,31 +725,6 @@ static void uvd_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, 0xE); } -static unsigned uvd_v6_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 8; /* uvd_v6_0_ring_emit_ib */ -} - -static unsigned uvd_v6_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 2 + /* uvd_v6_0_ring_emit_hdp_flush */ - 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */ - 10 + /* uvd_v6_0_ring_emit_pipeline_sync */ - 14; /* uvd_v6_0_ring_emit_fence x1 no user fence */ -} - -static unsigned uvd_v6_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring) -{ - return - 2 + /* uvd_v6_0_ring_emit_hdp_flush */ - 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */ - 10 + /* uvd_v6_0_ring_emit_pipeline_sync */ - 20 + /* uvd_v6_0_ring_emit_vm_flush */ - 14 + 14; /* uvd_v6_0_ring_emit_fence x2 vm fence */ -} - static bool uvd_v6_0_is_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1052,6 +1027,12 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = { .get_wptr = uvd_v6_0_ring_get_wptr, .set_wptr = uvd_v6_0_ring_set_wptr, .parse_cs = amdgpu_uvd_ring_parse_cs, + .emit_frame_size = + 2 + /* uvd_v6_0_ring_emit_hdp_flush */ + 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */ + 10 + /* uvd_v6_0_ring_emit_pipeline_sync */ + 14, /* uvd_v6_0_ring_emit_fence x1 no user fence */ + .emit_ib_size = 8, /* uvd_v6_0_ring_emit_ib */ .emit_ib = uvd_v6_0_ring_emit_ib, .emit_fence = uvd_v6_0_ring_emit_fence, .emit_hdp_flush = uvd_v6_0_ring_emit_hdp_flush, @@ -1062,14 +1043,19 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_uvd_ring_begin_use, .end_use = amdgpu_uvd_ring_end_use, - .get_emit_ib_size = uvd_v6_0_ring_get_emit_ib_size, - .get_dma_frame_size = uvd_v6_0_ring_get_dma_frame_size, }; static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = { .get_rptr = uvd_v6_0_ring_get_rptr, .get_wptr = uvd_v6_0_ring_get_wptr, .set_wptr = uvd_v6_0_ring_set_wptr, + .emit_frame_size = + 2 + /* uvd_v6_0_ring_emit_hdp_flush */ + 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */ + 10 + /* uvd_v6_0_ring_emit_pipeline_sync */ + 20 + /* uvd_v6_0_ring_emit_vm_flush */ + 14 + 14, /* uvd_v6_0_ring_emit_fence x2 vm fence */ + .emit_ib_size = 8, /* uvd_v6_0_ring_emit_ib */ .emit_ib = uvd_v6_0_ring_emit_ib, .emit_fence = uvd_v6_0_ring_emit_fence, .emit_vm_flush = uvd_v6_0_ring_emit_vm_flush, @@ -1082,8 +1068,6 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_uvd_ring_begin_use, .end_use = amdgpu_uvd_ring_end_use, - .get_emit_ib_size = uvd_v6_0_ring_get_emit_ib_size, - .get_dma_frame_size = uvd_v6_0_ring_get_dma_frame_size_vm, }; static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index 76e64ad04a53..7ada30ddfa0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -614,6 +614,8 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = { .get_wptr = vce_v2_0_ring_get_wptr, .set_wptr = vce_v2_0_ring_set_wptr, .parse_cs = amdgpu_vce_ring_parse_cs, + .emit_frame_size = 6, /* amdgpu_vce_ring_emit_fence x1 no user fence */ + .emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */ .emit_ib = amdgpu_vce_ring_emit_ib, .emit_fence = amdgpu_vce_ring_emit_fence, .test_ring = amdgpu_vce_ring_test_ring, @@ -622,8 +624,6 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_vce_ring_begin_use, .end_use = amdgpu_vce_ring_end_use, - .get_emit_ib_size = amdgpu_vce_ring_get_emit_ib_size, - .get_dma_frame_size = amdgpu_vce_ring_get_dma_frame_size, }; static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index e76bc092becc..0db59d885f04 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -808,27 +808,6 @@ static void vce_v3_0_emit_pipeline_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, seq); } -static unsigned vce_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ - return - 5; /* vce_v3_0_ring_emit_ib */ -} - -static unsigned vce_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ - return - 4 + /* vce_v3_0_emit_pipeline_sync */ - 6; /* amdgpu_vce_ring_emit_fence x1 no user fence */ -} - -static unsigned vce_v3_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring) -{ - return - 6 + /* vce_v3_0_emit_vm_flush */ - 4 + /* vce_v3_0_emit_pipeline_sync */ - 6 + 6; /* amdgpu_vce_ring_emit_fence x2 vm fence */ -} - const struct amd_ip_funcs vce_v3_0_ip_funcs = { .name = "vce_v3_0", .early_init = vce_v3_0_early_init, @@ -854,6 +833,10 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, .parse_cs = amdgpu_vce_ring_parse_cs, + .emit_frame_size = + 4 + /* vce_v3_0_emit_pipeline_sync */ + 6, /* amdgpu_vce_ring_emit_fence x1 no user fence */ + .emit_ib_size = 5, /* vce_v3_0_ring_emit_ib */ .emit_ib = amdgpu_vce_ring_emit_ib, .emit_fence = amdgpu_vce_ring_emit_fence, .test_ring = amdgpu_vce_ring_test_ring, @@ -862,14 +845,17 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_vce_ring_begin_use, .end_use = amdgpu_vce_ring_end_use, - .get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size, - .get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size, }; static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { .get_rptr = vce_v3_0_ring_get_rptr, .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, + .emit_frame_size = + 6 + /* vce_v3_0_emit_vm_flush */ + 4 + /* vce_v3_0_emit_pipeline_sync */ + 6 + 6, /* amdgpu_vce_ring_emit_fence x2 vm fence */ + .emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */ .emit_ib = vce_v3_0_ring_emit_ib, .emit_vm_flush = vce_v3_0_emit_vm_flush, .emit_pipeline_sync = vce_v3_0_emit_pipeline_sync, @@ -880,8 +866,6 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_vce_ring_begin_use, .end_use = amdgpu_vce_ring_end_use, - .get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size, - .get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size_vm, }; static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.2.3 From 21cd942e5c471941769cd0515164b169d012ad8a Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 5 Oct 2016 15:36:39 +0200 Subject: drm/amdgpu: move the ring type into the funcs structure (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's constant, so it doesn't make to much sense to keep it with the variable data. v2: update vce and uvd phys mode ring structures as well Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 4 +--- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 6 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 12 ++++++------ drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 16 ++++++++-------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 14 +++++++------- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/si_dma.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 3 ++- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 4 +++- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 4 +++- 16 files changed, 52 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a13e551e67cf..04b7aaf770e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -942,8 +942,8 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, /* UVD & VCE fw doesn't support user fences */ if (parser->job->uf_addr && ( - parser->job->ring->type == AMDGPU_RING_TYPE_UVD || - parser->job->ring->type == AMDGPU_RING_TYPE_VCE)) + parser->job->ring->funcs->type == AMDGPU_RING_TYPE_UVD || + parser->job->ring->funcs->type == AMDGPU_RING_TYPE_VCE)) return -EINVAL; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 3cb5e903cd62..b81b1244a120 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -164,8 +164,7 @@ void amdgpu_ring_undo(struct amdgpu_ring *ring) */ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, unsigned max_dw, u32 nop, u32 align_mask, - struct amdgpu_irq_src *irq_src, unsigned irq_type, - enum amdgpu_ring_type ring_type) + struct amdgpu_irq_src *irq_src, unsigned irq_type) { int r; @@ -218,7 +217,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, amdgpu_sched_hw_submission); ring->align_mask = align_mask; ring->nop = nop; - ring->type = ring_type; /* Allocate ring buffer */ if (ring->ring_obj == NULL) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 767843c2b1d7..6cf89c97ef8e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -92,6 +92,8 @@ unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); /* provided by hw blocks that expose a ring buffer for commands */ struct amdgpu_ring_funcs { + enum amdgpu_ring_type type; + /* ring read/write ptr handling */ u32 (*get_rptr)(struct amdgpu_ring *ring); u32 (*get_wptr)(struct amdgpu_ring *ring); @@ -161,7 +163,6 @@ struct amdgpu_ring { unsigned wptr_offs; unsigned fence_offs; uint64_t current_ctx; - enum amdgpu_ring_type type; char name[16]; unsigned cond_exe_offs; u64 cond_exe_gpu_addr; @@ -178,8 +179,7 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring); void amdgpu_ring_undo(struct amdgpu_ring *ring); int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, unsigned ring_size, u32 nop, u32 align_mask, - struct amdgpu_irq_src *irq_src, unsigned irq_type, - enum amdgpu_ring_type ring_type); + struct amdgpu_irq_src *irq_src, unsigned irq_type); void amdgpu_ring_fini(struct amdgpu_ring *ring); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index b8620d3dd61e..da66823eff1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -348,7 +348,7 @@ static bool amdgpu_vm_ring_has_compute_vm_bug(struct amdgpu_ring *ring) struct amdgpu_device *adev = ring->adev; const struct amdgpu_ip_block_version *ip_block; - if (ring->type != AMDGPU_RING_TYPE_COMPUTE) + if (ring->funcs->type != AMDGPU_RING_TYPE_COMPUTE) /* only compute rings */ return false; diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index 49b34decce58..472cfff28ccf 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -946,8 +946,8 @@ static int cik_sdma_sw_init(void *handle) SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0), 0xf, &adev->sdma.trap_irq, (i == 0) ? - AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1, - AMDGPU_RING_TYPE_SDMA); + AMDGPU_SDMA_IRQ_TRAP0 : + AMDGPU_SDMA_IRQ_TRAP1); if (r) return r; } @@ -1209,6 +1209,7 @@ const struct amd_ip_funcs cik_sdma_ip_funcs = { }; static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = { + .type = AMDGPU_RING_TYPE_SDMA, .get_rptr = cik_sdma_ring_get_rptr, .get_wptr = cik_sdma_ring_get_wptr, .set_wptr = cik_sdma_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index a86b17944bcf..1f8687fd8662 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -1940,7 +1940,7 @@ static int gfx_v6_0_cp_resume(struct amdgpu_device *adev) static void gfx_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) { - int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX); uint32_t seq = ring->fence_drv.sync_seq; uint64_t addr = ring->fence_drv.gpu_addr; @@ -1966,7 +1966,7 @@ static void gfx_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { - int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX); /* write new base address */ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); @@ -2870,8 +2870,7 @@ static int gfx_v6_0_sw_init(void *handle) sprintf(ring->name, "gfx"); r = amdgpu_ring_init(adev, ring, 1024, 0x80000000, 0xff, - &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP, - AMDGPU_RING_TYPE_GFX); + &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP); if (r) return r; } @@ -2894,8 +2893,7 @@ static int gfx_v6_0_sw_init(void *handle) irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; r = amdgpu_ring_init(adev, ring, 1024, 0x80000000, 0xff, - &adev->gfx.eop_irq, irq_type, - AMDGPU_RING_TYPE_COMPUTE); + &adev->gfx.eop_irq, irq_type); if (r) return r; } @@ -3228,6 +3226,7 @@ const struct amd_ip_funcs gfx_v6_0_ip_funcs = { }; static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { + .type = AMDGPU_RING_TYPE_GFX, .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_gfx, @@ -3252,6 +3251,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { }; static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { + .type = AMDGPU_RING_TYPE_COMPUTE, .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index f2415f58c160..cb2fc826f95c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2077,9 +2077,9 @@ static int gfx_v7_0_ring_test_ring(struct amdgpu_ring *ring) static void gfx_v7_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 ref_and_mask; - int usepfp = ring->type == AMDGPU_RING_TYPE_COMPUTE ? 0 : 1; + int usepfp = ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE ? 0 : 1; - if (ring->type == AMDGPU_RING_TYPE_COMPUTE) { + if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) { switch (ring->me) { case 1: ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe; @@ -3222,7 +3222,7 @@ static int gfx_v7_0_cp_resume(struct amdgpu_device *adev) */ static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) { - int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX); uint32_t seq = ring->fence_drv.sync_seq; uint64_t addr = ring->fence_drv.gpu_addr; @@ -3262,7 +3262,7 @@ static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { - int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX); amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) | @@ -4612,8 +4612,7 @@ static int gfx_v7_0_sw_init(void *handle) sprintf(ring->name, "gfx"); r = amdgpu_ring_init(adev, ring, 1024, PACKET3(PACKET3_NOP, 0x3FFF), 0xff, - &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP, - AMDGPU_RING_TYPE_GFX); + &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP); if (r) return r; } @@ -4639,8 +4638,7 @@ static int gfx_v7_0_sw_init(void *handle) /* type-2 packets are deprecated on MEC, use type-3 instead */ r = amdgpu_ring_init(adev, ring, 1024, PACKET3(PACKET3_NOP, 0x3FFF), 0xff, - &adev->gfx.eop_irq, irq_type, - AMDGPU_RING_TYPE_COMPUTE); + &adev->gfx.eop_irq, irq_type); if (r) return r; } @@ -5109,6 +5107,7 @@ const struct amd_ip_funcs gfx_v7_0_ip_funcs = { }; static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { + .type = AMDGPU_RING_TYPE_GFX, .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_gfx, .set_wptr = gfx_v7_0_ring_set_wptr_gfx, @@ -5136,6 +5135,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { }; static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { + .type = AMDGPU_RING_TYPE_COMPUTE, .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_compute, .set_wptr = gfx_v7_0_ring_set_wptr_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index e3330d06af9a..637dbc1a2e48 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -2036,8 +2036,7 @@ static int gfx_v8_0_sw_init(void *handle) r = amdgpu_ring_init(adev, ring, 1024, PACKET3(PACKET3_NOP, 0x3FFF), 0xff, - &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP, - AMDGPU_RING_TYPE_GFX); + &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP); if (r) return r; } @@ -2063,8 +2062,7 @@ static int gfx_v8_0_sw_init(void *handle) /* type-2 packets are deprecated on MEC, use type-3 instead */ r = amdgpu_ring_init(adev, ring, 1024, PACKET3(PACKET3_NOP, 0x3FFF), 0xff, - &adev->gfx.eop_irq, irq_type, - AMDGPU_RING_TYPE_COMPUTE); + &adev->gfx.eop_irq, irq_type); if (r) return r; } @@ -6127,7 +6125,7 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 ref_and_mask, reg_mem_engine; - if (ring->type == AMDGPU_RING_TYPE_COMPUTE) { + if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) { switch (ring->me) { case 1: ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe; @@ -6229,7 +6227,7 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, static void gfx_v8_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) { - int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX); uint32_t seq = ring->fence_drv.sync_seq; uint64_t addr = ring->fence_drv.gpu_addr; @@ -6247,7 +6245,7 @@ static void gfx_v8_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { - int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX); amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) | @@ -6529,6 +6527,7 @@ const struct amd_ip_funcs gfx_v8_0_ip_funcs = { }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { + .type = AMDGPU_RING_TYPE_GFX, .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_gfx, .set_wptr = gfx_v8_0_ring_set_wptr_gfx, @@ -6558,6 +6557,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { + .type = AMDGPU_RING_TYPE_COMPUTE, .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_compute, .set_wptr = gfx_v8_0_ring_set_wptr_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 7cd24e42aa9a..36a135de44fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -952,8 +952,8 @@ static int sdma_v2_4_sw_init(void *handle) SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf, &adev->sdma.trap_irq, (i == 0) ? - AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1, - AMDGPU_RING_TYPE_SDMA); + AMDGPU_SDMA_IRQ_TRAP0 : + AMDGPU_SDMA_IRQ_TRAP1); if (r) return r; } @@ -1206,6 +1206,7 @@ const struct amd_ip_funcs sdma_v2_4_ip_funcs = { }; static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { + .type = AMDGPU_RING_TYPE_SDMA, .get_rptr = sdma_v2_4_ring_get_rptr, .get_wptr = sdma_v2_4_ring_get_wptr, .set_wptr = sdma_v2_4_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 6518993e23a8..e4f59c36f989 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1164,8 +1164,8 @@ static int sdma_v3_0_sw_init(void *handle) SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf, &adev->sdma.trap_irq, (i == 0) ? - AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1, - AMDGPU_RING_TYPE_SDMA); + AMDGPU_SDMA_IRQ_TRAP0 : + AMDGPU_SDMA_IRQ_TRAP1); if (r) return r; } @@ -1549,6 +1549,7 @@ const struct amd_ip_funcs sdma_v3_0_ip_funcs = { }; static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { + .type = AMDGPU_RING_TYPE_SDMA, .get_rptr = sdma_v3_0_ring_get_rptr, .get_wptr = sdma_v3_0_ring_get_wptr, .set_wptr = sdma_v3_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index c1c1b5179de5..1aee45b0bb9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -534,8 +534,8 @@ static int si_dma_sw_init(void *handle) DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0), 0xf, &adev->sdma.trap_irq, (i == 0) ? - AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1, - AMDGPU_RING_TYPE_SDMA); + AMDGPU_SDMA_IRQ_TRAP0 : + AMDGPU_SDMA_IRQ_TRAP1); if (r) return r; } @@ -764,6 +764,7 @@ const struct amd_ip_funcs si_dma_ip_funcs = { }; static const struct amdgpu_ring_funcs si_dma_ring_funcs = { + .type = AMDGPU_RING_TYPE_SDMA, .get_rptr = si_dma_ring_get_rptr, .get_wptr = si_dma_ring_get_wptr, .set_wptr = si_dma_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 708de997e3b0..55af8aca4b2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -117,7 +117,7 @@ static int uvd_v4_2_sw_init(void *handle) ring = &adev->uvd.ring; sprintf(ring->name, "uvd"); r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf, - &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD); + &adev->uvd.irq, 0); return r; } @@ -742,6 +742,7 @@ const struct amd_ip_funcs uvd_v4_2_ip_funcs = { }; static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = { + .type = AMDGPU_RING_TYPE_UVD, .get_rptr = uvd_v4_2_ring_get_rptr, .get_wptr = uvd_v4_2_ring_get_wptr, .set_wptr = uvd_v4_2_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index 9e695e01f8b8..21e725b50a90 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -113,7 +113,7 @@ static int uvd_v5_0_sw_init(void *handle) ring = &adev->uvd.ring; sprintf(ring->name, "uvd"); r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf, - &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD); + &adev->uvd.irq, 0); return r; } @@ -793,6 +793,7 @@ const struct amd_ip_funcs uvd_v5_0_ip_funcs = { }; static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = { + .type = AMDGPU_RING_TYPE_UVD, .get_rptr = uvd_v5_0_ring_get_rptr, .get_wptr = uvd_v5_0_ring_get_wptr, .set_wptr = uvd_v5_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index aeb1b6e2c518..65df5b208243 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -117,7 +117,7 @@ static int uvd_v6_0_sw_init(void *handle) ring = &adev->uvd.ring; sprintf(ring->name, "uvd"); r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf, - &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD); + &adev->uvd.irq, 0); return r; } @@ -1023,6 +1023,7 @@ const struct amd_ip_funcs uvd_v6_0_ip_funcs = { }; static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = { + .type = AMDGPU_RING_TYPE_UVD, .get_rptr = uvd_v6_0_ring_get_rptr, .get_wptr = uvd_v6_0_ring_get_wptr, .set_wptr = uvd_v6_0_ring_set_wptr, @@ -1046,6 +1047,7 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = { }; static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = { + .type = AMDGPU_RING_TYPE_UVD, .get_rptr = uvd_v6_0_ring_get_rptr, .get_wptr = uvd_v6_0_ring_get_wptr, .set_wptr = uvd_v6_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index 7ada30ddfa0d..cf0c68fda20e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -225,7 +225,7 @@ static int vce_v2_0_sw_init(void *handle) ring = &adev->vce.ring[i]; sprintf(ring->name, "vce%d", i); r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); + &adev->vce.irq, 0); if (r) return r; } @@ -610,6 +610,7 @@ const struct amd_ip_funcs vce_v2_0_ip_funcs = { }; static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = { + .type = AMDGPU_RING_TYPE_VCE, .get_rptr = vce_v2_0_ring_get_rptr, .get_wptr = vce_v2_0_ring_get_wptr, .set_wptr = vce_v2_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 0db59d885f04..95fe8a8bda12 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -390,7 +390,7 @@ static int vce_v3_0_sw_init(void *handle) ring = &adev->vce.ring[i]; sprintf(ring->name, "vce%d", i); r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); + &adev->vce.irq, 0); if (r) return r; } @@ -829,6 +829,7 @@ const struct amd_ip_funcs vce_v3_0_ip_funcs = { }; static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { + .type = AMDGPU_RING_TYPE_VCE, .get_rptr = vce_v3_0_ring_get_rptr, .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, @@ -848,6 +849,7 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { }; static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { + .type = AMDGPU_RING_TYPE_VCE, .get_rptr = vce_v3_0_ring_get_rptr, .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, -- cgit v1.2.3 From 7988714237c6a548011dcd7dcce84e9f16dda427 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 5 Oct 2016 16:09:32 +0200 Subject: drm/amdgpu: move align_mask and nop into ring funcs as well (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are constant as well. v2: update uvd and vce phys ring structures as well Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 19 +++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 8 ++++---- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 7 ++++--- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 14 ++++++++------ drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 7 ++++--- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 7 ++++--- drivers/gpu/drm/amd/amdgpu/si_dma.c | 3 ++- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 7 +++++-- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 4 +++- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 7 +++++-- 14 files changed, 62 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index b81b1244a120..4c992826d2d6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -65,7 +65,7 @@ int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw) { /* Align requested size with padding so unlock_commit can * pad safely */ - ndw = (ndw + ring->align_mask) & ~ring->align_mask; + ndw = (ndw + ring->funcs->align_mask) & ~ring->funcs->align_mask; /* Make sure we aren't trying to allocate more space * than the maximum for one submission @@ -94,7 +94,7 @@ void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) int i; for (i = 0; i < count; i++) - amdgpu_ring_write(ring, ring->nop); + amdgpu_ring_write(ring, ring->funcs->nop); } /** amdgpu_ring_generic_pad_ib - pad IB with NOP packets @@ -106,8 +106,8 @@ void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) */ void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib) { - while (ib->length_dw & ring->align_mask) - ib->ptr[ib->length_dw++] = ring->nop; + while (ib->length_dw & ring->funcs->align_mask) + ib->ptr[ib->length_dw++] = ring->funcs->nop; } /** @@ -125,8 +125,9 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring) uint32_t count; /* We pad to match fetch size */ - count = ring->align_mask + 1 - (ring->wptr & ring->align_mask); - count %= ring->align_mask + 1; + count = ring->funcs->align_mask + 1 - + (ring->wptr & ring->funcs->align_mask); + count %= ring->funcs->align_mask + 1; ring->funcs->insert_nop(ring, count); mb(); @@ -163,8 +164,8 @@ void amdgpu_ring_undo(struct amdgpu_ring *ring) * Returns 0 on success, error on failure. */ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, - unsigned max_dw, u32 nop, u32 align_mask, - struct amdgpu_irq_src *irq_src, unsigned irq_type) + unsigned max_dw, struct amdgpu_irq_src *irq_src, + unsigned irq_type) { int r; @@ -215,8 +216,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ring->ring_size = roundup_pow_of_two(max_dw * 4 * amdgpu_sched_hw_submission); - ring->align_mask = align_mask; - ring->nop = nop; /* Allocate ring buffer */ if (ring->ring_obj == NULL) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 6cf89c97ef8e..1ee1b65d7eff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -93,6 +93,8 @@ unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); /* provided by hw blocks that expose a ring buffer for commands */ struct amdgpu_ring_funcs { enum amdgpu_ring_type type; + uint32_t align_mask; + u32 nop; /* ring read/write ptr handling */ u32 (*get_rptr)(struct amdgpu_ring *ring); @@ -149,10 +151,8 @@ struct amdgpu_ring { unsigned max_dw; int count_dw; uint64_t gpu_addr; - uint32_t align_mask; uint32_t ptr_mask; bool ready; - u32 nop; u32 idx; u32 me; u32 pipe; @@ -178,8 +178,8 @@ void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib); void amdgpu_ring_commit(struct amdgpu_ring *ring); void amdgpu_ring_undo(struct amdgpu_ring *ring); int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, - unsigned ring_size, u32 nop, u32 align_mask, - struct amdgpu_irq_src *irq_src, unsigned irq_type); + unsigned ring_size, struct amdgpu_irq_src *irq_src, + unsigned irq_type); void amdgpu_ring_fini(struct amdgpu_ring *ring); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index 472cfff28ccf..b96ef20e871f 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -206,10 +206,10 @@ static void cik_sdma_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) for (i = 0; i < count; i++) if (sdma && sdma->burst_nop && (i == 0)) - amdgpu_ring_write(ring, ring->nop | + amdgpu_ring_write(ring, ring->funcs->nop | SDMA_NOP_COUNT(count - 1)); else - amdgpu_ring_write(ring, ring->nop); + amdgpu_ring_write(ring, ring->funcs->nop); } /** @@ -943,7 +943,6 @@ static int cik_sdma_sw_init(void *handle) ring->ring_obj = NULL; sprintf(ring->name, "sdma%d", i); r = amdgpu_ring_init(adev, ring, 1024, - SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0), 0xf, &adev->sdma.trap_irq, (i == 0) ? AMDGPU_SDMA_IRQ_TRAP0 : @@ -1210,6 +1209,8 @@ const struct amd_ip_funcs cik_sdma_ip_funcs = { static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = { .type = AMDGPU_RING_TYPE_SDMA, + .align_mask = 0xf, + .nop = SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0), .get_rptr = cik_sdma_ring_get_rptr, .get_wptr = cik_sdma_ring_get_wptr, .set_wptr = cik_sdma_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 1f8687fd8662..367b14e16e53 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -2869,7 +2869,6 @@ static int gfx_v6_0_sw_init(void *handle) ring->ring_obj = NULL; sprintf(ring->name, "gfx"); r = amdgpu_ring_init(adev, ring, 1024, - 0x80000000, 0xff, &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP); if (r) return r; @@ -2892,7 +2891,6 @@ static int gfx_v6_0_sw_init(void *handle) sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue); irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; r = amdgpu_ring_init(adev, ring, 1024, - 0x80000000, 0xff, &adev->gfx.eop_irq, irq_type); if (r) return r; @@ -3227,6 +3225,8 @@ const struct amd_ip_funcs gfx_v6_0_ip_funcs = { static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .type = AMDGPU_RING_TYPE_GFX, + .align_mask = 0xff, + .nop = 0x80000000, .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_gfx, @@ -3252,6 +3252,8 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { .type = AMDGPU_RING_TYPE_COMPUTE, + .align_mask = 0xff, + .nop = 0x80000000, .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index cb2fc826f95c..388649734b36 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4611,7 +4611,6 @@ static int gfx_v7_0_sw_init(void *handle) ring->ring_obj = NULL; sprintf(ring->name, "gfx"); r = amdgpu_ring_init(adev, ring, 1024, - PACKET3(PACKET3_NOP, 0x3FFF), 0xff, &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP); if (r) return r; @@ -4637,7 +4636,6 @@ static int gfx_v7_0_sw_init(void *handle) irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; /* type-2 packets are deprecated on MEC, use type-3 instead */ r = amdgpu_ring_init(adev, ring, 1024, - PACKET3(PACKET3_NOP, 0x3FFF), 0xff, &adev->gfx.eop_irq, irq_type); if (r) return r; @@ -5108,6 +5106,8 @@ const struct amd_ip_funcs gfx_v7_0_ip_funcs = { static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { .type = AMDGPU_RING_TYPE_GFX, + .align_mask = 0xff, + .nop = PACKET3(PACKET3_NOP, 0x3FFF), .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_gfx, .set_wptr = gfx_v7_0_ring_set_wptr_gfx, @@ -5136,6 +5136,8 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { .type = AMDGPU_RING_TYPE_COMPUTE, + .align_mask = 0xff, + .nop = PACKET3(PACKET3_NOP, 0x3FFF), .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_compute, .set_wptr = gfx_v7_0_ring_set_wptr_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 637dbc1a2e48..6f3996f6d39a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -2034,9 +2034,8 @@ static int gfx_v8_0_sw_init(void *handle) ring->doorbell_index = AMDGPU_DOORBELL_GFX_RING0; } - r = amdgpu_ring_init(adev, ring, 1024, - PACKET3(PACKET3_NOP, 0x3FFF), 0xff, - &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP); + r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, + AMDGPU_CP_IRQ_GFX_EOP); if (r) return r; } @@ -2060,9 +2059,8 @@ static int gfx_v8_0_sw_init(void *handle) sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue); irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; /* type-2 packets are deprecated on MEC, use type-3 instead */ - r = amdgpu_ring_init(adev, ring, 1024, - PACKET3(PACKET3_NOP, 0x3FFF), 0xff, - &adev->gfx.eop_irq, irq_type); + r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, + irq_type); if (r) return r; } @@ -6528,6 +6526,8 @@ const struct amd_ip_funcs gfx_v8_0_ip_funcs = { static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .type = AMDGPU_RING_TYPE_GFX, + .align_mask = 0xff, + .nop = PACKET3(PACKET3_NOP, 0x3FFF), .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_gfx, .set_wptr = gfx_v8_0_ring_set_wptr_gfx, @@ -6558,6 +6558,8 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { .type = AMDGPU_RING_TYPE_COMPUTE, + .align_mask = 0xff, + .nop = PACKET3(PACKET3_NOP, 0x3FFF), .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_compute, .set_wptr = gfx_v8_0_ring_set_wptr_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 36a135de44fe..5859a106608b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -232,10 +232,10 @@ static void sdma_v2_4_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) for (i = 0; i < count; i++) if (sdma && sdma->burst_nop && (i == 0)) - amdgpu_ring_write(ring, ring->nop | + amdgpu_ring_write(ring, ring->funcs->nop | SDMA_PKT_NOP_HEADER_COUNT(count - 1)); else - amdgpu_ring_write(ring, ring->nop); + amdgpu_ring_write(ring, ring->funcs->nop); } /** @@ -949,7 +949,6 @@ static int sdma_v2_4_sw_init(void *handle) ring->use_doorbell = false; sprintf(ring->name, "sdma%d", i); r = amdgpu_ring_init(adev, ring, 1024, - SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf, &adev->sdma.trap_irq, (i == 0) ? AMDGPU_SDMA_IRQ_TRAP0 : @@ -1207,6 +1206,8 @@ const struct amd_ip_funcs sdma_v2_4_ip_funcs = { static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { .type = AMDGPU_RING_TYPE_SDMA, + .align_mask = 0xf, + .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .get_rptr = sdma_v2_4_ring_get_rptr, .get_wptr = sdma_v2_4_ring_get_wptr, .set_wptr = sdma_v2_4_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index e4f59c36f989..24642f92b4b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -392,10 +392,10 @@ static void sdma_v3_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) for (i = 0; i < count; i++) if (sdma && sdma->burst_nop && (i == 0)) - amdgpu_ring_write(ring, ring->nop | + amdgpu_ring_write(ring, ring->funcs->nop | SDMA_PKT_NOP_HEADER_COUNT(count - 1)); else - amdgpu_ring_write(ring, ring->nop); + amdgpu_ring_write(ring, ring->funcs->nop); } /** @@ -1161,7 +1161,6 @@ static int sdma_v3_0_sw_init(void *handle) sprintf(ring->name, "sdma%d", i); r = amdgpu_ring_init(adev, ring, 1024, - SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf, &adev->sdma.trap_irq, (i == 0) ? AMDGPU_SDMA_IRQ_TRAP0 : @@ -1550,6 +1549,8 @@ const struct amd_ip_funcs sdma_v3_0_ip_funcs = { static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { .type = AMDGPU_RING_TYPE_SDMA, + .align_mask = 0xf, + .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .get_rptr = sdma_v3_0_ring_get_rptr, .get_wptr = sdma_v3_0_ring_get_wptr, .set_wptr = sdma_v3_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 1aee45b0bb9e..7fece1fe4130 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -531,7 +531,6 @@ static int si_dma_sw_init(void *handle) ring->use_doorbell = false; sprintf(ring->name, "sdma%d", i); r = amdgpu_ring_init(adev, ring, 1024, - DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0), 0xf, &adev->sdma.trap_irq, (i == 0) ? AMDGPU_SDMA_IRQ_TRAP0 : @@ -765,6 +764,8 @@ const struct amd_ip_funcs si_dma_ip_funcs = { static const struct amdgpu_ring_funcs si_dma_ring_funcs = { .type = AMDGPU_RING_TYPE_SDMA, + .align_mask = 0xf, + .nop = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0), .get_rptr = si_dma_ring_get_rptr, .get_wptr = si_dma_ring_get_wptr, .set_wptr = si_dma_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 55af8aca4b2a..1bab75afba5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -116,8 +116,7 @@ static int uvd_v4_2_sw_init(void *handle) ring = &adev->uvd.ring; sprintf(ring->name, "uvd"); - r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf, - &adev->uvd.irq, 0); + r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0); return r; } @@ -743,6 +742,8 @@ const struct amd_ip_funcs uvd_v4_2_ip_funcs = { static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = { .type = AMDGPU_RING_TYPE_UVD, + .align_mask = 0xf, + .nop = PACKET0(mmUVD_NO_OP, 0), .get_rptr = uvd_v4_2_ring_get_rptr, .get_wptr = uvd_v4_2_ring_get_wptr, .set_wptr = uvd_v4_2_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index 21e725b50a90..ec848fc57f70 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -112,8 +112,7 @@ static int uvd_v5_0_sw_init(void *handle) ring = &adev->uvd.ring; sprintf(ring->name, "uvd"); - r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf, - &adev->uvd.irq, 0); + r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0); return r; } @@ -794,6 +793,8 @@ const struct amd_ip_funcs uvd_v5_0_ip_funcs = { static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = { .type = AMDGPU_RING_TYPE_UVD, + .align_mask = 0xf, + .nop = PACKET0(mmUVD_NO_OP, 0), .get_rptr = uvd_v5_0_ring_get_rptr, .get_wptr = uvd_v5_0_ring_get_wptr, .set_wptr = uvd_v5_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 65df5b208243..be912933b073 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -116,8 +116,7 @@ static int uvd_v6_0_sw_init(void *handle) ring = &adev->uvd.ring; sprintf(ring->name, "uvd"); - r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf, - &adev->uvd.irq, 0); + r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0); return r; } @@ -1024,6 +1023,8 @@ const struct amd_ip_funcs uvd_v6_0_ip_funcs = { static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = { .type = AMDGPU_RING_TYPE_UVD, + .align_mask = 0xf, + .nop = PACKET0(mmUVD_NO_OP, 0), .get_rptr = uvd_v6_0_ring_get_rptr, .get_wptr = uvd_v6_0_ring_get_wptr, .set_wptr = uvd_v6_0_ring_set_wptr, @@ -1048,6 +1049,8 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = { static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = { .type = AMDGPU_RING_TYPE_UVD, + .align_mask = 0xf, + .nop = PACKET0(mmUVD_NO_OP, 0), .get_rptr = uvd_v6_0_ring_get_rptr, .get_wptr = uvd_v6_0_ring_get_wptr, .set_wptr = uvd_v6_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index cf0c68fda20e..d58583983b11 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -224,7 +224,7 @@ static int vce_v2_0_sw_init(void *handle) for (i = 0; i < adev->vce.num_rings; i++) { ring = &adev->vce.ring[i]; sprintf(ring->name, "vce%d", i); - r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, + r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0); if (r) return r; @@ -611,6 +611,8 @@ const struct amd_ip_funcs vce_v2_0_ip_funcs = { static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = { .type = AMDGPU_RING_TYPE_VCE, + .align_mask = 0xf, + .nop = VCE_CMD_NO_OP, .get_rptr = vce_v2_0_ring_get_rptr, .get_wptr = vce_v2_0_ring_get_wptr, .set_wptr = vce_v2_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 95fe8a8bda12..589fff19aa78 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -389,8 +389,7 @@ static int vce_v3_0_sw_init(void *handle) for (i = 0; i < adev->vce.num_rings; i++) { ring = &adev->vce.ring[i]; sprintf(ring->name, "vce%d", i); - r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0); + r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0); if (r) return r; } @@ -830,6 +829,8 @@ const struct amd_ip_funcs vce_v3_0_ip_funcs = { static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { .type = AMDGPU_RING_TYPE_VCE, + .align_mask = 0xf, + .nop = VCE_CMD_NO_OP, .get_rptr = vce_v3_0_ring_get_rptr, .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, @@ -850,6 +851,8 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { .type = AMDGPU_RING_TYPE_VCE, + .align_mask = 0xf, + .nop = VCE_CMD_NO_OP, .get_rptr = vce_v3_0_ring_get_rptr, .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, -- cgit v1.2.3 From cf0978819cf78cef8d36ca39cb242dde4731d338 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Oct 2016 11:40:09 -0400 Subject: drm/amdgpu: move dpm related definitions to amdgpu_dpm.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No intended functional change. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 449 +------------------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 447 +++++++++++++++++++++++++++++++ 2 files changed, 448 insertions(+), 448 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index fa99c0d6158c..e6f86b83652b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -57,6 +57,7 @@ #include "amdgpu_ring.h" #include "amdgpu_vm.h" #include "amd_powerplay.h" +#include "amdgpu_dpm.h" #include "amdgpu_acp.h" #include "gpu_scheduler.h" @@ -973,354 +974,6 @@ struct amdgpu_wb { int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb); void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb); - - -enum amdgpu_int_thermal_type { - THERMAL_TYPE_NONE, - THERMAL_TYPE_EXTERNAL, - THERMAL_TYPE_EXTERNAL_GPIO, - THERMAL_TYPE_RV6XX, - THERMAL_TYPE_RV770, - THERMAL_TYPE_ADT7473_WITH_INTERNAL, - THERMAL_TYPE_EVERGREEN, - THERMAL_TYPE_SUMO, - THERMAL_TYPE_NI, - THERMAL_TYPE_SI, - THERMAL_TYPE_EMC2103_WITH_INTERNAL, - THERMAL_TYPE_CI, - THERMAL_TYPE_KV, -}; - -enum amdgpu_dpm_auto_throttle_src { - AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, - AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL -}; - -enum amdgpu_dpm_event_src { - AMDGPU_DPM_EVENT_SRC_ANALOG = 0, - AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1, - AMDGPU_DPM_EVENT_SRC_DIGITAL = 2, - AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, - AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 -}; - -#define AMDGPU_MAX_VCE_LEVELS 6 - -enum amdgpu_vce_level { - AMDGPU_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */ - AMDGPU_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */ - AMDGPU_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */ - AMDGPU_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */ - AMDGPU_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */ - AMDGPU_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */ -}; - -struct amdgpu_ps { - u32 caps; /* vbios flags */ - u32 class; /* vbios flags */ - u32 class2; /* vbios flags */ - /* UVD clocks */ - u32 vclk; - u32 dclk; - /* VCE clocks */ - u32 evclk; - u32 ecclk; - bool vce_active; - enum amdgpu_vce_level vce_level; - /* asic priv */ - void *ps_priv; -}; - -struct amdgpu_dpm_thermal { - /* thermal interrupt work */ - struct work_struct work; - /* low temperature threshold */ - int min_temp; - /* high temperature threshold */ - int max_temp; - /* was last interrupt low to high or high to low */ - bool high_to_low; - /* interrupt source */ - struct amdgpu_irq_src irq; -}; - -enum amdgpu_clk_action -{ - AMDGPU_SCLK_UP = 1, - AMDGPU_SCLK_DOWN -}; - -struct amdgpu_blacklist_clocks -{ - u32 sclk; - u32 mclk; - enum amdgpu_clk_action action; -}; - -struct amdgpu_clock_and_voltage_limits { - u32 sclk; - u32 mclk; - u16 vddc; - u16 vddci; -}; - -struct amdgpu_clock_array { - u32 count; - u32 *values; -}; - -struct amdgpu_clock_voltage_dependency_entry { - u32 clk; - u16 v; -}; - -struct amdgpu_clock_voltage_dependency_table { - u32 count; - struct amdgpu_clock_voltage_dependency_entry *entries; -}; - -union amdgpu_cac_leakage_entry { - struct { - u16 vddc; - u32 leakage; - }; - struct { - u16 vddc1; - u16 vddc2; - u16 vddc3; - }; -}; - -struct amdgpu_cac_leakage_table { - u32 count; - union amdgpu_cac_leakage_entry *entries; -}; - -struct amdgpu_phase_shedding_limits_entry { - u16 voltage; - u32 sclk; - u32 mclk; -}; - -struct amdgpu_phase_shedding_limits_table { - u32 count; - struct amdgpu_phase_shedding_limits_entry *entries; -}; - -struct amdgpu_uvd_clock_voltage_dependency_entry { - u32 vclk; - u32 dclk; - u16 v; -}; - -struct amdgpu_uvd_clock_voltage_dependency_table { - u8 count; - struct amdgpu_uvd_clock_voltage_dependency_entry *entries; -}; - -struct amdgpu_vce_clock_voltage_dependency_entry { - u32 ecclk; - u32 evclk; - u16 v; -}; - -struct amdgpu_vce_clock_voltage_dependency_table { - u8 count; - struct amdgpu_vce_clock_voltage_dependency_entry *entries; -}; - -struct amdgpu_ppm_table { - u8 ppm_design; - u16 cpu_core_number; - u32 platform_tdp; - u32 small_ac_platform_tdp; - u32 platform_tdc; - u32 small_ac_platform_tdc; - u32 apu_tdp; - u32 dgpu_tdp; - u32 dgpu_ulv_power; - u32 tj_max; -}; - -struct amdgpu_cac_tdp_table { - u16 tdp; - u16 configurable_tdp; - u16 tdc; - u16 battery_power_limit; - u16 small_power_limit; - u16 low_cac_leakage; - u16 high_cac_leakage; - u16 maximum_power_delivery_limit; -}; - -struct amdgpu_dpm_dynamic_state { - struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_sclk; - struct amdgpu_clock_voltage_dependency_table vddci_dependency_on_mclk; - struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_mclk; - struct amdgpu_clock_voltage_dependency_table mvdd_dependency_on_mclk; - struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_dispclk; - struct amdgpu_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table; - struct amdgpu_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table; - struct amdgpu_clock_voltage_dependency_table samu_clock_voltage_dependency_table; - struct amdgpu_clock_voltage_dependency_table acp_clock_voltage_dependency_table; - struct amdgpu_clock_voltage_dependency_table vddgfx_dependency_on_sclk; - struct amdgpu_clock_array valid_sclk_values; - struct amdgpu_clock_array valid_mclk_values; - struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_dc; - struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_ac; - u32 mclk_sclk_ratio; - u32 sclk_mclk_delta; - u16 vddc_vddci_delta; - u16 min_vddc_for_pcie_gen2; - struct amdgpu_cac_leakage_table cac_leakage_table; - struct amdgpu_phase_shedding_limits_table phase_shedding_limits_table; - struct amdgpu_ppm_table *ppm_table; - struct amdgpu_cac_tdp_table *cac_tdp_table; -}; - -struct amdgpu_dpm_fan { - u16 t_min; - u16 t_med; - u16 t_high; - u16 pwm_min; - u16 pwm_med; - u16 pwm_high; - u8 t_hyst; - u32 cycle_delay; - u16 t_max; - u8 control_mode; - u16 default_max_fan_pwm; - u16 default_fan_output_sensitivity; - u16 fan_output_sensitivity; - bool ucode_fan_control; -}; - -enum amdgpu_pcie_gen { - AMDGPU_PCIE_GEN1 = 0, - AMDGPU_PCIE_GEN2 = 1, - AMDGPU_PCIE_GEN3 = 2, - AMDGPU_PCIE_GEN_INVALID = 0xffff -}; - -enum amdgpu_dpm_forced_level { - AMDGPU_DPM_FORCED_LEVEL_AUTO = 0, - AMDGPU_DPM_FORCED_LEVEL_LOW = 1, - AMDGPU_DPM_FORCED_LEVEL_HIGH = 2, - AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3, -}; - -struct amdgpu_vce_state { - /* vce clocks */ - u32 evclk; - u32 ecclk; - /* gpu clocks */ - u32 sclk; - u32 mclk; - u8 clk_idx; - u8 pstate; -}; - -struct amdgpu_dpm_funcs { - int (*get_temperature)(struct amdgpu_device *adev); - int (*pre_set_power_state)(struct amdgpu_device *adev); - int (*set_power_state)(struct amdgpu_device *adev); - void (*post_set_power_state)(struct amdgpu_device *adev); - void (*display_configuration_changed)(struct amdgpu_device *adev); - u32 (*get_sclk)(struct amdgpu_device *adev, bool low); - u32 (*get_mclk)(struct amdgpu_device *adev, bool low); - void (*print_power_state)(struct amdgpu_device *adev, struct amdgpu_ps *ps); - void (*debugfs_print_current_performance_level)(struct amdgpu_device *adev, struct seq_file *m); - int (*force_performance_level)(struct amdgpu_device *adev, enum amdgpu_dpm_forced_level level); - bool (*vblank_too_short)(struct amdgpu_device *adev); - void (*powergate_uvd)(struct amdgpu_device *adev, bool gate); - void (*powergate_vce)(struct amdgpu_device *adev, bool gate); - void (*enable_bapm)(struct amdgpu_device *adev, bool enable); - void (*set_fan_control_mode)(struct amdgpu_device *adev, u32 mode); - u32 (*get_fan_control_mode)(struct amdgpu_device *adev); - int (*set_fan_speed_percent)(struct amdgpu_device *adev, u32 speed); - int (*get_fan_speed_percent)(struct amdgpu_device *adev, u32 *speed); - int (*force_clock_level)(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t mask); - int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf); - int (*get_sclk_od)(struct amdgpu_device *adev); - int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value); - int (*get_mclk_od)(struct amdgpu_device *adev); - int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value); -}; - -struct amdgpu_dpm { - struct amdgpu_ps *ps; - /* number of valid power states */ - int num_ps; - /* current power state that is active */ - struct amdgpu_ps *current_ps; - /* requested power state */ - struct amdgpu_ps *requested_ps; - /* boot up power state */ - struct amdgpu_ps *boot_ps; - /* default uvd power state */ - struct amdgpu_ps *uvd_ps; - /* vce requirements */ - struct amdgpu_vce_state vce_states[AMDGPU_MAX_VCE_LEVELS]; - enum amdgpu_vce_level vce_level; - enum amd_pm_state_type state; - enum amd_pm_state_type user_state; - u32 platform_caps; - u32 voltage_response_time; - u32 backbias_response_time; - void *priv; - u32 new_active_crtcs; - int new_active_crtc_count; - u32 current_active_crtcs; - int current_active_crtc_count; - struct amdgpu_dpm_dynamic_state dyn_state; - struct amdgpu_dpm_fan fan; - u32 tdp_limit; - u32 near_tdp_limit; - u32 near_tdp_limit_adjusted; - u32 sq_ramping_threshold; - u32 cac_leakage; - u16 tdp_od_limit; - u32 tdp_adjustment; - u16 load_line_slope; - bool power_control; - bool ac_power; - /* special states active */ - bool thermal_active; - bool uvd_active; - bool vce_active; - /* thermal handling */ - struct amdgpu_dpm_thermal thermal; - /* forced levels */ - enum amdgpu_dpm_forced_level forced_level; -}; - -struct amdgpu_pm { - struct mutex mutex; - u32 current_sclk; - u32 current_mclk; - u32 default_sclk; - u32 default_mclk; - struct amdgpu_i2c_chan *i2c_bus; - /* internal thermal controller on rv6xx+ */ - enum amdgpu_int_thermal_type int_thermal_type; - struct device *int_hwmon_dev; - /* fan control parameters */ - bool no_fan; - u8 fan_pulses_per_revolution; - u8 fan_min_rpm; - u8 fan_max_rpm; - /* dpm */ - bool dpm_enabled; - bool sysfs_initialized; - struct amdgpu_dpm dpm; - const struct firmware *fw; /* SMC firmware */ - uint32_t fw_version; - const struct amdgpu_dpm_funcs *funcs; - uint32_t pcie_gen_mask; - uint32_t pcie_mlw_mask; - struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */ -}; - void amdgpu_get_pcie_info(struct amdgpu_device *adev); /* @@ -1983,108 +1636,8 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s)) #define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b)) #define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b)) -#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev)) -#define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev)) -#define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev)) -#define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev)) -#define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps)) -#define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev)) -#define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) #define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev)) #define amdgpu_gfx_select_se_sh(adev, se, sh, instance) (adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance)) - -#define amdgpu_dpm_read_sensor(adev, idx, value) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value)) : \ - -EINVAL) - -#define amdgpu_dpm_get_temperature(adev) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \ - (adev)->pm.funcs->get_temperature((adev))) - -#define amdgpu_dpm_set_fan_control_mode(adev, m) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \ - (adev)->pm.funcs->set_fan_control_mode((adev), (m))) - -#define amdgpu_dpm_get_fan_control_mode(adev) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \ - (adev)->pm.funcs->get_fan_control_mode((adev))) - -#define amdgpu_dpm_set_fan_speed_percent(adev, s) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ - (adev)->pm.funcs->set_fan_speed_percent((adev), (s))) - -#define amdgpu_dpm_get_fan_speed_percent(adev, s) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ - (adev)->pm.funcs->get_fan_speed_percent((adev), (s))) - -#define amdgpu_dpm_get_sclk(adev, l) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->get_sclk((adev), (l))) - -#define amdgpu_dpm_get_mclk(adev, l) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->get_mclk((adev), (l))) - - -#define amdgpu_dpm_force_performance_level(adev, l) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->force_performance_level((adev), (l))) - -#define amdgpu_dpm_powergate_uvd(adev, g) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \ - (adev)->pm.funcs->powergate_uvd((adev), (g))) - -#define amdgpu_dpm_powergate_vce(adev, g) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \ - (adev)->pm.funcs->powergate_vce((adev), (g))) - -#define amdgpu_dpm_get_current_power_state(adev) \ - (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle) - -#define amdgpu_dpm_get_performance_level(adev) \ - (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) - -#define amdgpu_dpm_get_pp_num_states(adev, data) \ - (adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data) - -#define amdgpu_dpm_get_pp_table(adev, table) \ - (adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table) - -#define amdgpu_dpm_set_pp_table(adev, buf, size) \ - (adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size) - -#define amdgpu_dpm_print_clock_levels(adev, type, buf) \ - (adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf) - -#define amdgpu_dpm_force_clock_level(adev, type, level) \ - (adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level) - -#define amdgpu_dpm_get_sclk_od(adev) \ - (adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle) - -#define amdgpu_dpm_set_sclk_od(adev, value) \ - (adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value) - -#define amdgpu_dpm_get_mclk_od(adev) \ - ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_set_mclk_od(adev, value) \ - ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value)) - -#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ - (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) - #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a)) /* Common functions */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 3738a96c2619..d06496d3e08e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -23,6 +23,453 @@ #ifndef __AMDGPU_DPM_H__ #define __AMDGPU_DPM_H__ +enum amdgpu_int_thermal_type { + THERMAL_TYPE_NONE, + THERMAL_TYPE_EXTERNAL, + THERMAL_TYPE_EXTERNAL_GPIO, + THERMAL_TYPE_RV6XX, + THERMAL_TYPE_RV770, + THERMAL_TYPE_ADT7473_WITH_INTERNAL, + THERMAL_TYPE_EVERGREEN, + THERMAL_TYPE_SUMO, + THERMAL_TYPE_NI, + THERMAL_TYPE_SI, + THERMAL_TYPE_EMC2103_WITH_INTERNAL, + THERMAL_TYPE_CI, + THERMAL_TYPE_KV, +}; + +enum amdgpu_dpm_auto_throttle_src { + AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, + AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL +}; + +enum amdgpu_dpm_event_src { + AMDGPU_DPM_EVENT_SRC_ANALOG = 0, + AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1, + AMDGPU_DPM_EVENT_SRC_DIGITAL = 2, + AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, + AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 +}; + +#define AMDGPU_MAX_VCE_LEVELS 6 + +enum amdgpu_vce_level { + AMDGPU_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */ + AMDGPU_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */ + AMDGPU_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */ + AMDGPU_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */ + AMDGPU_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */ + AMDGPU_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */ +}; + +struct amdgpu_ps { + u32 caps; /* vbios flags */ + u32 class; /* vbios flags */ + u32 class2; /* vbios flags */ + /* UVD clocks */ + u32 vclk; + u32 dclk; + /* VCE clocks */ + u32 evclk; + u32 ecclk; + bool vce_active; + enum amdgpu_vce_level vce_level; + /* asic priv */ + void *ps_priv; +}; + +struct amdgpu_dpm_thermal { + /* thermal interrupt work */ + struct work_struct work; + /* low temperature threshold */ + int min_temp; + /* high temperature threshold */ + int max_temp; + /* was last interrupt low to high or high to low */ + bool high_to_low; + /* interrupt source */ + struct amdgpu_irq_src irq; +}; + +enum amdgpu_clk_action +{ + AMDGPU_SCLK_UP = 1, + AMDGPU_SCLK_DOWN +}; + +struct amdgpu_blacklist_clocks +{ + u32 sclk; + u32 mclk; + enum amdgpu_clk_action action; +}; + +struct amdgpu_clock_and_voltage_limits { + u32 sclk; + u32 mclk; + u16 vddc; + u16 vddci; +}; + +struct amdgpu_clock_array { + u32 count; + u32 *values; +}; + +struct amdgpu_clock_voltage_dependency_entry { + u32 clk; + u16 v; +}; + +struct amdgpu_clock_voltage_dependency_table { + u32 count; + struct amdgpu_clock_voltage_dependency_entry *entries; +}; + +union amdgpu_cac_leakage_entry { + struct { + u16 vddc; + u32 leakage; + }; + struct { + u16 vddc1; + u16 vddc2; + u16 vddc3; + }; +}; + +struct amdgpu_cac_leakage_table { + u32 count; + union amdgpu_cac_leakage_entry *entries; +}; + +struct amdgpu_phase_shedding_limits_entry { + u16 voltage; + u32 sclk; + u32 mclk; +}; + +struct amdgpu_phase_shedding_limits_table { + u32 count; + struct amdgpu_phase_shedding_limits_entry *entries; +}; + +struct amdgpu_uvd_clock_voltage_dependency_entry { + u32 vclk; + u32 dclk; + u16 v; +}; + +struct amdgpu_uvd_clock_voltage_dependency_table { + u8 count; + struct amdgpu_uvd_clock_voltage_dependency_entry *entries; +}; + +struct amdgpu_vce_clock_voltage_dependency_entry { + u32 ecclk; + u32 evclk; + u16 v; +}; + +struct amdgpu_vce_clock_voltage_dependency_table { + u8 count; + struct amdgpu_vce_clock_voltage_dependency_entry *entries; +}; + +struct amdgpu_ppm_table { + u8 ppm_design; + u16 cpu_core_number; + u32 platform_tdp; + u32 small_ac_platform_tdp; + u32 platform_tdc; + u32 small_ac_platform_tdc; + u32 apu_tdp; + u32 dgpu_tdp; + u32 dgpu_ulv_power; + u32 tj_max; +}; + +struct amdgpu_cac_tdp_table { + u16 tdp; + u16 configurable_tdp; + u16 tdc; + u16 battery_power_limit; + u16 small_power_limit; + u16 low_cac_leakage; + u16 high_cac_leakage; + u16 maximum_power_delivery_limit; +}; + +struct amdgpu_dpm_dynamic_state { + struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_sclk; + struct amdgpu_clock_voltage_dependency_table vddci_dependency_on_mclk; + struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_mclk; + struct amdgpu_clock_voltage_dependency_table mvdd_dependency_on_mclk; + struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_dispclk; + struct amdgpu_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table; + struct amdgpu_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table; + struct amdgpu_clock_voltage_dependency_table samu_clock_voltage_dependency_table; + struct amdgpu_clock_voltage_dependency_table acp_clock_voltage_dependency_table; + struct amdgpu_clock_voltage_dependency_table vddgfx_dependency_on_sclk; + struct amdgpu_clock_array valid_sclk_values; + struct amdgpu_clock_array valid_mclk_values; + struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_dc; + struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_ac; + u32 mclk_sclk_ratio; + u32 sclk_mclk_delta; + u16 vddc_vddci_delta; + u16 min_vddc_for_pcie_gen2; + struct amdgpu_cac_leakage_table cac_leakage_table; + struct amdgpu_phase_shedding_limits_table phase_shedding_limits_table; + struct amdgpu_ppm_table *ppm_table; + struct amdgpu_cac_tdp_table *cac_tdp_table; +}; + +struct amdgpu_dpm_fan { + u16 t_min; + u16 t_med; + u16 t_high; + u16 pwm_min; + u16 pwm_med; + u16 pwm_high; + u8 t_hyst; + u32 cycle_delay; + u16 t_max; + u8 control_mode; + u16 default_max_fan_pwm; + u16 default_fan_output_sensitivity; + u16 fan_output_sensitivity; + bool ucode_fan_control; +}; + +enum amdgpu_pcie_gen { + AMDGPU_PCIE_GEN1 = 0, + AMDGPU_PCIE_GEN2 = 1, + AMDGPU_PCIE_GEN3 = 2, + AMDGPU_PCIE_GEN_INVALID = 0xffff +}; + +enum amdgpu_dpm_forced_level { + AMDGPU_DPM_FORCED_LEVEL_AUTO = 0, + AMDGPU_DPM_FORCED_LEVEL_LOW = 1, + AMDGPU_DPM_FORCED_LEVEL_HIGH = 2, + AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3, +}; + +struct amdgpu_vce_state { + /* vce clocks */ + u32 evclk; + u32 ecclk; + /* gpu clocks */ + u32 sclk; + u32 mclk; + u8 clk_idx; + u8 pstate; +}; + +struct amdgpu_dpm_funcs { + int (*get_temperature)(struct amdgpu_device *adev); + int (*pre_set_power_state)(struct amdgpu_device *adev); + int (*set_power_state)(struct amdgpu_device *adev); + void (*post_set_power_state)(struct amdgpu_device *adev); + void (*display_configuration_changed)(struct amdgpu_device *adev); + u32 (*get_sclk)(struct amdgpu_device *adev, bool low); + u32 (*get_mclk)(struct amdgpu_device *adev, bool low); + void (*print_power_state)(struct amdgpu_device *adev, struct amdgpu_ps *ps); + void (*debugfs_print_current_performance_level)(struct amdgpu_device *adev, struct seq_file *m); + int (*force_performance_level)(struct amdgpu_device *adev, enum amdgpu_dpm_forced_level level); + bool (*vblank_too_short)(struct amdgpu_device *adev); + void (*powergate_uvd)(struct amdgpu_device *adev, bool gate); + void (*powergate_vce)(struct amdgpu_device *adev, bool gate); + void (*enable_bapm)(struct amdgpu_device *adev, bool enable); + void (*set_fan_control_mode)(struct amdgpu_device *adev, u32 mode); + u32 (*get_fan_control_mode)(struct amdgpu_device *adev); + int (*set_fan_speed_percent)(struct amdgpu_device *adev, u32 speed); + int (*get_fan_speed_percent)(struct amdgpu_device *adev, u32 *speed); + int (*force_clock_level)(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t mask); + int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf); + int (*get_sclk_od)(struct amdgpu_device *adev); + int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value); + int (*get_mclk_od)(struct amdgpu_device *adev); + int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value); +}; + +#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev)) +#define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev)) +#define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev)) +#define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev)) +#define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps)) +#define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev)) +#define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) + +#define amdgpu_dpm_read_sensor(adev, idx, value) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value)) : \ + -EINVAL) + +#define amdgpu_dpm_get_temperature(adev) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \ + (adev)->pm.funcs->get_temperature((adev))) + +#define amdgpu_dpm_set_fan_control_mode(adev, m) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \ + (adev)->pm.funcs->set_fan_control_mode((adev), (m))) + +#define amdgpu_dpm_get_fan_control_mode(adev) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \ + (adev)->pm.funcs->get_fan_control_mode((adev))) + +#define amdgpu_dpm_set_fan_speed_percent(adev, s) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ + (adev)->pm.funcs->set_fan_speed_percent((adev), (s))) + +#define amdgpu_dpm_get_fan_speed_percent(adev, s) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ + (adev)->pm.funcs->get_fan_speed_percent((adev), (s))) + +#define amdgpu_dpm_get_sclk(adev, l) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->get_sclk((adev), (l))) + +#define amdgpu_dpm_get_mclk(adev, l) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->get_mclk((adev), (l))) + + +#define amdgpu_dpm_force_performance_level(adev, l) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->force_performance_level((adev), (l))) + +#define amdgpu_dpm_powergate_uvd(adev, g) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \ + (adev)->pm.funcs->powergate_uvd((adev), (g))) + +#define amdgpu_dpm_powergate_vce(adev, g) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \ + (adev)->pm.funcs->powergate_vce((adev), (g))) + +#define amdgpu_dpm_get_current_power_state(adev) \ + (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle) + +#define amdgpu_dpm_get_performance_level(adev) \ + (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) + +#define amdgpu_dpm_get_pp_num_states(adev, data) \ + (adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data) + +#define amdgpu_dpm_get_pp_table(adev, table) \ + (adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table) + +#define amdgpu_dpm_set_pp_table(adev, buf, size) \ + (adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size) + +#define amdgpu_dpm_print_clock_levels(adev, type, buf) \ + (adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf) + +#define amdgpu_dpm_force_clock_level(adev, type, level) \ + (adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level) + +#define amdgpu_dpm_get_sclk_od(adev) \ + (adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle) + +#define amdgpu_dpm_set_sclk_od(adev, value) \ + (adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value) + +#define amdgpu_dpm_get_mclk_od(adev) \ + ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_set_mclk_od(adev, value) \ + ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value)) + +#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ + (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) + + +struct amdgpu_dpm { + struct amdgpu_ps *ps; + /* number of valid power states */ + int num_ps; + /* current power state that is active */ + struct amdgpu_ps *current_ps; + /* requested power state */ + struct amdgpu_ps *requested_ps; + /* boot up power state */ + struct amdgpu_ps *boot_ps; + /* default uvd power state */ + struct amdgpu_ps *uvd_ps; + /* vce requirements */ + struct amdgpu_vce_state vce_states[AMDGPU_MAX_VCE_LEVELS]; + enum amdgpu_vce_level vce_level; + enum amd_pm_state_type state; + enum amd_pm_state_type user_state; + u32 platform_caps; + u32 voltage_response_time; + u32 backbias_response_time; + void *priv; + u32 new_active_crtcs; + int new_active_crtc_count; + u32 current_active_crtcs; + int current_active_crtc_count; + struct amdgpu_dpm_dynamic_state dyn_state; + struct amdgpu_dpm_fan fan; + u32 tdp_limit; + u32 near_tdp_limit; + u32 near_tdp_limit_adjusted; + u32 sq_ramping_threshold; + u32 cac_leakage; + u16 tdp_od_limit; + u32 tdp_adjustment; + u16 load_line_slope; + bool power_control; + bool ac_power; + /* special states active */ + bool thermal_active; + bool uvd_active; + bool vce_active; + /* thermal handling */ + struct amdgpu_dpm_thermal thermal; + /* forced levels */ + enum amdgpu_dpm_forced_level forced_level; +}; + +struct amdgpu_pm { + struct mutex mutex; + u32 current_sclk; + u32 current_mclk; + u32 default_sclk; + u32 default_mclk; + struct amdgpu_i2c_chan *i2c_bus; + /* internal thermal controller on rv6xx+ */ + enum amdgpu_int_thermal_type int_thermal_type; + struct device *int_hwmon_dev; + /* fan control parameters */ + bool no_fan; + u8 fan_pulses_per_revolution; + u8 fan_min_rpm; + u8 fan_max_rpm; + /* dpm */ + bool dpm_enabled; + bool sysfs_initialized; + struct amdgpu_dpm dpm; + const struct firmware *fw; /* SMC firmware */ + uint32_t fw_version; + const struct amdgpu_dpm_funcs *funcs; + uint32_t pcie_gen_mask; + uint32_t pcie_mlw_mask; + struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */ +}; + #define R600_SSTU_DFLT 0 #define R600_SST_DFLT 0x00C8 -- cgit v1.2.3 From 0d8de7ca0b01332c404d3b5877db89727618c3d0 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 12 Oct 2016 15:13:29 +0800 Subject: drm/amdgpu: use same vce state definition in dpm and powerplay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 28 +++------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 2 +- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 2 +- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 2 +- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 2 +- drivers/gpu/drm/amd/include/amd_shared.h | 23 ++++++++++++++++++ .../amd/powerplay/hwmgr/process_pptables_v1_0.c | 4 ++-- .../gpu/drm/amd/powerplay/hwmgr/processpptables.c | 2 +- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 16 ++----------- drivers/gpu/drm/amd/powerplay/inc/power_state.h | 9 ------- 11 files changed, 36 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 14f57d9915e3..4f8d3a5a682f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -554,7 +554,7 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); } for (i = 0; i < states->numEntries; i++) { - if (i >= AMDGPU_MAX_VCE_LEVELS) + if (i >= AMD_MAX_VCE_LEVELS) break; vce_clk = (VCEClockInfo *) ((u8 *)&array->entries[0] + diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index d06496d3e08e..68dac0c569fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -52,17 +52,6 @@ enum amdgpu_dpm_event_src { AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 }; -#define AMDGPU_MAX_VCE_LEVELS 6 - -enum amdgpu_vce_level { - AMDGPU_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */ - AMDGPU_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */ - AMDGPU_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */ - AMDGPU_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */ - AMDGPU_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */ - AMDGPU_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */ -}; - struct amdgpu_ps { u32 caps; /* vbios flags */ u32 class; /* vbios flags */ @@ -74,7 +63,7 @@ struct amdgpu_ps { u32 evclk; u32 ecclk; bool vce_active; - enum amdgpu_vce_level vce_level; + enum amd_vce_level vce_level; /* asic priv */ void *ps_priv; }; @@ -257,17 +246,6 @@ enum amdgpu_dpm_forced_level { AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3, }; -struct amdgpu_vce_state { - /* vce clocks */ - u32 evclk; - u32 ecclk; - /* gpu clocks */ - u32 sclk; - u32 mclk; - u8 clk_idx; - u8 pstate; -}; - struct amdgpu_dpm_funcs { int (*get_temperature)(struct amdgpu_device *adev); int (*pre_set_power_state)(struct amdgpu_device *adev); @@ -409,8 +387,8 @@ struct amdgpu_dpm { /* default uvd power state */ struct amdgpu_ps *uvd_ps; /* vce requirements */ - struct amdgpu_vce_state vce_states[AMDGPU_MAX_VCE_LEVELS]; - enum amdgpu_vce_level vce_level; + struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS]; + enum amd_vce_level vce_level; enum amd_pm_state_type state; enum amd_pm_state_type user_state; u32 platform_caps; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index accc908bdc88..4656ad697154 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1135,7 +1135,7 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) mutex_lock(&adev->pm.mutex); adev->pm.dpm.vce_active = true; /* XXX select vce level based on ring/task */ - adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL; + adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; mutex_unlock(&adev->pm.mutex); } else { mutex_lock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 1d8c375a3561..dc3196e13256 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -5689,7 +5689,7 @@ static int ci_parse_power_table(struct amdgpu_device *adev) adev->pm.dpm.num_ps = state_array->ucNumEntries; /* fill in the vce power states */ - for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) { + for (i = 0; i < AMD_MAX_VCE_LEVELS; i++) { u32 sclk, mclk; clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; clock_info = (union pplib_clock_info *) diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index f8618a3881a8..a03690abe38d 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -2796,7 +2796,7 @@ static int kv_parse_power_table(struct amdgpu_device *adev) adev->pm.dpm.num_ps = state_array->ucNumEntries; /* fill in the vce power states */ - for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) { + for (i = 0; i < AMD_MAX_VCE_LEVELS; i++) { u32 sclk; clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; clock_info = (union pplib_clock_info *) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 3de7bca5854b..15f9ca55bba9 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -7320,7 +7320,7 @@ static int si_parse_power_table(struct amdgpu_device *adev) adev->pm.dpm.num_ps = state_array->ucNumEntries; /* fill in the vce power states */ - for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) { + for (i = 0; i < AMD_MAX_VCE_LEVELS; i++) { u32 sclk, mclk; clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; clock_info = (union pplib_clock_info *) diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index bec8125bceb0..d1986276dbbd 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -84,6 +84,29 @@ enum amd_powergating_state { AMD_PG_STATE_UNGATE, }; +struct amd_vce_state { + /* vce clocks */ + u32 evclk; + u32 ecclk; + /* gpu clocks */ + u32 sclk; + u32 mclk; + u8 clk_idx; + u8 pstate; +}; + + +#define AMD_MAX_VCE_LEVELS 6 + +enum amd_vce_level { + AMD_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */ + AMD_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */ + AMD_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */ + AMD_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */ + AMD_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */ + AMD_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */ +}; + /* CG flags */ #define AMD_CG_SUPPORT_GFX_MGCG (1 << 0) #define AMD_CG_SUPPORT_GFX_MGLS (1 << 1) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c index 155cd0dfe0c5..baf0f3d4c2f0 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c @@ -1211,7 +1211,7 @@ static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr) } static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i, - struct pp_vce_state *vce_state, void **clock_info, uint32_t *flag) + struct amd_vce_state *vce_state, void **clock_info, uint32_t *flag) { const ATOM_Tonga_VCE_State_Record *vce_state_record; ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; @@ -1315,7 +1315,7 @@ int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr); - if ((i != 0) && (i <= PP_MAX_VCE_LEVELS)) { + if ((i != 0) && (i <= AMD_MAX_VCE_LEVELS)) { for (j = 0; j < i; j++) ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags); } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c index bd1f19010315..a4e9cf429e62 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c @@ -1523,7 +1523,7 @@ static int get_number_of_vce_state_table_entries( static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, unsigned long i, - struct pp_vce_state *vce_state, + struct amd_vce_state *vce_state, void **clock_info, unsigned long *flag) { diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 4f0fedd1e9d3..e38b999e3235 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -367,7 +367,7 @@ struct pp_table_func { int (*pptable_get_vce_state_table_entry)( struct pp_hwmgr *hwmgr, unsigned long i, - struct pp_vce_state *vce_state, + struct amd_vce_state *vce_state, void **clock_info, unsigned long *flag); }; @@ -586,18 +586,6 @@ struct phm_microcode_version_info { uint32_t NB; }; -#define PP_MAX_VCE_LEVELS 6 - -enum PP_VCE_LEVEL { - PP_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */ - PP_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */ - PP_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */ - PP_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */ - PP_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */ - PP_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */ -}; - - enum PP_TABLE_VERSION { PP_TABLE_V0 = 0, PP_TABLE_V1, @@ -620,7 +608,7 @@ struct pp_hwmgr { void *hardcode_pp_table; bool need_pp_table_upload; - struct pp_vce_state vce_states[PP_MAX_VCE_LEVELS]; + struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS]; uint32_t num_vce_state_tables; enum amd_dpm_forced_level dpm_level; diff --git a/drivers/gpu/drm/amd/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/powerplay/inc/power_state.h index 9ceaed9ac52a..827860fffe78 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/power_state.h +++ b/drivers/gpu/drm/amd/powerplay/inc/power_state.h @@ -156,15 +156,6 @@ struct pp_power_state { struct pp_hw_power_state hardware; }; - -/*Structure to hold a VCE state entry*/ -struct pp_vce_state { - uint32_t evclk; - uint32_t ecclk; - uint32_t sclk; - uint32_t mclk; -}; - enum PP_MMProfilingState { PP_MMProfilingState_NA = 0, PP_MMProfilingState_Started, -- cgit v1.2.3 From 66ba1afd854211435cc91159a1ededb1d0f04464 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 12 Oct 2016 15:38:56 +0800 Subject: drm/amdgpu: save number of vce states in dpm struct. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 7 ++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 1 + drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 2 +- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 2 +- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 4f8d3a5a682f..009ccb961541 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -553,9 +553,10 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); } - for (i = 0; i < states->numEntries; i++) { - if (i >= AMD_MAX_VCE_LEVELS) - break; + adev->pm.dpm.num_of_vce_states = + states->numEntries > AMD_MAX_VCE_LEVELS ? + AMD_MAX_VCE_LEVELS : states->numEntries; + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { vce_clk = (VCEClockInfo *) ((u8 *)&array->entries[0] + (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 68dac0c569fd..5097415d2172 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -387,6 +387,7 @@ struct amdgpu_dpm { /* default uvd power state */ struct amdgpu_ps *uvd_ps; /* vce requirements */ + u32 num_of_vce_states; struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS]; enum amd_vce_level vce_level; enum amd_pm_state_type state; diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index dc3196e13256..fa939df942f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -5689,7 +5689,7 @@ static int ci_parse_power_table(struct amdgpu_device *adev) adev->pm.dpm.num_ps = state_array->ucNumEntries; /* fill in the vce power states */ - for (i = 0; i < AMD_MAX_VCE_LEVELS; i++) { + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { u32 sclk, mclk; clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; clock_info = (union pplib_clock_info *) diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index a03690abe38d..b23f643f6d0f 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -2796,7 +2796,7 @@ static int kv_parse_power_table(struct amdgpu_device *adev) adev->pm.dpm.num_ps = state_array->ucNumEntries; /* fill in the vce power states */ - for (i = 0; i < AMD_MAX_VCE_LEVELS; i++) { + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { u32 sclk; clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; clock_info = (union pplib_clock_info *) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 15f9ca55bba9..dbfecc29f2a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -7320,7 +7320,7 @@ static int si_parse_power_table(struct amdgpu_device *adev) adev->pm.dpm.num_ps = state_array->ucNumEntries; /* fill in the vce power states */ - for (i = 0; i < AMD_MAX_VCE_LEVELS; i++) { + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { u32 sclk, mclk; clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; clock_info = (union pplib_clock_info *) -- cgit v1.2.3 From 230cf1ba7274413659d3ff94be6862c26f7dd7a9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Oct 2016 14:10:15 -0400 Subject: drm/amdgpu/dpm: add new callback to fetch vce clock state (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Will be used by the new info ioctl query. v2: fetch a single state per request Reviewed-by: Rex Zhu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 5 +++++ drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 1 + 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 5097415d2172..fdcf9688e7ae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -271,6 +271,7 @@ struct amdgpu_dpm_funcs { int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value); int (*get_mclk_od)(struct amdgpu_device *adev); int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value); + struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx); }; #define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev)) @@ -373,6 +374,10 @@ struct amdgpu_dpm_funcs { #define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) +#define amdgpu_dpm_get_vce_clock_state(adev, i) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i)) : \ + (adev)->pm.funcs->get_vce_clock_state((adev), (i))) struct amdgpu_dpm { struct amdgpu_ps *ps; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 3fb5e57a378b..eb3e83d7af31 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -359,6 +359,7 @@ struct amd_powerplay_funcs { int (*get_mclk_od)(void *handle); int (*set_mclk_od)(void *handle, uint32_t value); int (*read_sensor)(void *handle, int idx, int32_t *value); + struct amd_vce_state* (*get_vce_clock_state)(void *handle, unsigned idx); }; struct amd_powerplay { -- cgit v1.2.3 From 825cc9974d15c0dee8e735c7abf975b576fadf6a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Oct 2016 12:38:04 -0400 Subject: drm/amdgpu/dpm: add an implementation for get_vce_clock_state (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Used by the non-powerplay dpm code. v2: update to the new API Reviewed-by: Rex Zhu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 3 +++ drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 1 + drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 1 + drivers/gpu/drm/amd/amdgpu/si_dpm.c | 1 + 5 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 009ccb961541..6ca0333ca4c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -956,3 +956,12 @@ u8 amdgpu_encode_pci_lane_width(u32 lanes) return encoded_lanes[lanes]; } + +struct amd_vce_state* +amdgpu_get_vce_clock_state(struct amdgpu_device *adev, unsigned idx) +{ + if (idx < adev->pm.dpm.num_of_vce_states) + return &adev->pm.dpm.vce_states[idx]; + + return NULL; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index fdcf9688e7ae..4f25c030148e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -513,4 +513,7 @@ u16 amdgpu_get_pcie_lane_support(struct amdgpu_device *adev, u16 default_lanes); u8 amdgpu_encode_pci_lane_width(u32 lanes); +struct amd_vce_state* +amdgpu_get_vce_clock_state(struct amdgpu_device *adev, unsigned idx); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index fa939df942f4..3f891076c070 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6644,6 +6644,7 @@ static const struct amdgpu_dpm_funcs ci_dpm_funcs = { .set_sclk_od = ci_dpm_set_sclk_od, .get_mclk_od = ci_dpm_get_mclk_od, .set_mclk_od = ci_dpm_set_mclk_od, + .get_vce_clock_state = amdgpu_get_vce_clock_state, }; static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index b23f643f6d0f..c3367d6f311a 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -3273,6 +3273,7 @@ static const struct amdgpu_dpm_funcs kv_dpm_funcs = { .force_performance_level = &kv_dpm_force_performance_level, .powergate_uvd = &kv_dpm_powergate_uvd, .enable_bapm = &kv_dpm_enable_bapm, + .get_vce_clock_state = amdgpu_get_vce_clock_state, }; static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index dbfecc29f2a1..38b4b9789584 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -7991,6 +7991,7 @@ static const struct amdgpu_dpm_funcs si_dpm_funcs = { .get_fan_control_mode = &si_dpm_get_fan_control_mode, .set_fan_speed_percent = &si_dpm_set_fan_speed_percent, .get_fan_speed_percent = &si_dpm_get_fan_speed_percent, + .get_vce_clock_state = amdgpu_get_vce_clock_state, }; static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev) -- cgit v1.2.3 From 597be302f1d30e908115632fd90049242c470e37 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Oct 2016 13:52:43 -0400 Subject: drm/amdgpu/powerplay: add an implementation for get_vce_clock_state (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Used by the powerplay dpm code. v2: update to the new API v3: drop old include Reviewed-by: Rex Zhu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index bb8a345c750a..0b1f2205c2f1 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -821,6 +821,21 @@ static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value) return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value); } +static struct amd_vce_state* +pp_dpm_get_vce_clock_state(void *handle, unsigned idx) +{ + struct pp_hwmgr *hwmgr; + + if (handle) { + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr && idx < hwmgr->num_vce_state_tables) + return &hwmgr->vce_states[idx]; + } + + return NULL; +} + const struct amd_powerplay_funcs pp_dpm_funcs = { .get_temperature = pp_dpm_get_temperature, .load_firmware = pp_dpm_load_fw, @@ -847,6 +862,7 @@ const struct amd_powerplay_funcs pp_dpm_funcs = { .get_mclk_od = pp_dpm_get_mclk_od, .set_mclk_od = pp_dpm_set_mclk_od, .read_sensor = pp_dpm_read_sensor, + .get_vce_clock_state = pp_dpm_get_vce_clock_state, }; static int amd_pp_instance_init(struct amd_pp_init *pp_init, -- cgit v1.2.3 From 07fecde5d3ece770234e2b71e052079af776869a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Oct 2016 12:22:02 -0400 Subject: drm/amdgpu: fill in vce clock info ioctl query (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returns the vce clock table for the user mode driver. The user mode driver can fill this data into vce clock data packet for optimal VCE DPM. v2: update to the new API Reviewed-by: Rex Zhu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 1ecfe9a046ab..3570124ed186 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -524,6 +524,24 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file return copy_to_user(out, &dev_info, min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0; } + case AMDGPU_INFO_VCE_CLOCK_TABLE: { + unsigned i; + struct drm_amdgpu_info_vce_clock_table vce_clk_table = {}; + struct amd_vce_state *vce_state; + + for (i = 0; i < AMDGPU_VCE_CLOCK_TABLE_ENTRIES; i++) { + vce_state = amdgpu_dpm_get_vce_clock_state(adev, i); + if (vce_state) { + vce_clk_table.entries[i].sclk = vce_state->sclk; + vce_clk_table.entries[i].mclk = vce_state->mclk; + vce_clk_table.entries[i].eclk = vce_state->evclk; + vce_clk_table.num_valid_entries++; + } + } + + return copy_to_user(out, &vce_clk_table, + min((size_t)size, sizeof(vce_clk_table))) ? -EFAULT : 0; + } default: DRM_DEBUG_KMS("Invalid request %d\n", info->query); return -EINVAL; -- cgit v1.2.3 From 2120df475d6d5c7db1b888a8e26a5a51ce56e860 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 13 Oct 2016 16:01:18 -0400 Subject: drm/amdgpu: enable virtual dce on SI Add the proper IP module when requested. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 140 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index dc9511c5ecb8..1d40c26de324 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -39,6 +39,7 @@ #include "si_dma.h" #include "dce_v6_0.h" #include "si.h" +#include "dce_virtual.h" static const u32 tahiti_golden_registers[] = { @@ -1897,6 +1898,74 @@ static const struct amdgpu_ip_block_version verde_ip_blocks[] = }; +static const struct amdgpu_ip_block_version verde_ip_blocks_vd[] = +{ + { + .type = AMD_IP_BLOCK_TYPE_COMMON, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_common_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gmc_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_ih_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &amdgpu_pp_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &dce_virtual_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gfx_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_dma_ip_funcs, + }, +/* { + .type = AMD_IP_BLOCK_TYPE_UVD, + .major = 3, + .minor = 1, + .rev = 0, + .funcs = &si_null_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_VCE, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_null_ip_funcs, + }, + */ +}; + static const struct amdgpu_ip_block_version hainan_ip_blocks[] = { { @@ -1943,6 +2012,59 @@ static const struct amdgpu_ip_block_version hainan_ip_blocks[] = }, }; +static const struct amdgpu_ip_block_version hainan_ip_blocks_vd[] = +{ + { + .type = AMD_IP_BLOCK_TYPE_COMMON, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_common_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gmc_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_ih_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &amdgpu_pp_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &dce_virtual_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gfx_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_dma_ip_funcs, + }, +}; + int si_set_ip_blocks(struct amdgpu_device *adev) { switch (adev->asic_type) { @@ -1950,12 +2072,22 @@ int si_set_ip_blocks(struct amdgpu_device *adev) case CHIP_TAHITI: case CHIP_PITCAIRN: case CHIP_OLAND: - adev->ip_blocks = verde_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(verde_ip_blocks); + if (adev->enable_virtual_display) { + adev->ip_blocks = verde_ip_blocks_vd; + adev->num_ip_blocks = ARRAY_SIZE(verde_ip_blocks_vd); + } else { + adev->ip_blocks = verde_ip_blocks; + adev->num_ip_blocks = ARRAY_SIZE(verde_ip_blocks); + } break; case CHIP_HAINAN: - adev->ip_blocks = hainan_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(hainan_ip_blocks); + if (adev->enable_virtual_display) { + adev->ip_blocks = hainan_ip_blocks_vd; + adev->num_ip_blocks = ARRAY_SIZE(hainan_ip_blocks_vd); + } else { + adev->ip_blocks = hainan_ip_blocks; + adev->num_ip_blocks = ARRAY_SIZE(hainan_ip_blocks); + } break; default: BUG(); -- cgit v1.2.3 From 623fea1868ee49965bdaa73fe27c64430de5179e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 13 Oct 2016 17:36:46 -0400 Subject: drm/amdgpu/virtual_dce: move define into source file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not used outside the file. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 3 +++ drivers/gpu/drm/amd/amdgpu/dce_virtual.h | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 226b914aa315..7d041b9a4d61 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -37,6 +37,9 @@ #include "dce_v11_0.h" #include "dce_virtual.h" +#define DCE_VIRTUAL_VBLANK_PERIOD 16666666 + + static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h index e239243f6ebc..393ce97f783e 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h @@ -25,7 +25,6 @@ #define __DCE_VIRTUAL_H__ extern const struct amd_ip_funcs dce_virtual_ip_funcs; -#define DCE_VIRTUAL_VBLANK_PERIOD 16666666 #endif -- cgit v1.2.3 From cf35c7ca3d50286a3ac7672aa7d26a8d2e930706 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 14 Oct 2016 11:27:15 -0400 Subject: drm/amdgpu/powerplay: fix spelling in amdgpu_powerplay.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and update a comment as well. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h index da5cf47cfd99..ee6ea6c98e4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h @@ -23,11 +23,11 @@ * */ -#ifndef __AMDGPU_POPWERPLAY_H__ -#define __AMDGPU_POPWERPLAY_H__ +#ifndef __AMDGPU_POWERPLAY_H__ +#define __AMDGPU_POWERPLAY_H__ #include "amd_shared.h" extern const struct amd_ip_funcs amdgpu_pp_ip_funcs; -#endif /* __AMDSOC_DM_H__ */ +#endif /* __AMDGPU_POWERPLAY_H__ */ -- cgit v1.2.3 From a12551072126758ecb0743147054f22bf233bb7d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 13 Oct 2016 17:41:13 -0400 Subject: drm/amdgpu: rework IP block registration (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier to replace specific IP blocks on asics for handling virtual_dce, DAL, etc. and for building IP lists for hw or tables. This also stored the status information in the same structure. v2: split out spelling fix into a separate patch add a function to add IPs to the list Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 42 +- drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 17 +- drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 12 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 260 ++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 12 +- drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 11 +- drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 +- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 9 + drivers/gpu/drm/amd/amdgpu/cik.c | 817 +++---------------------- drivers/gpu/drm/amd/amdgpu/cik.h | 2 - drivers/gpu/drm/amd/amdgpu/cik_ih.c | 11 +- drivers/gpu/drm/amd/amdgpu/cik_ih.h | 2 +- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 11 +- drivers/gpu/drm/amd/amdgpu/cik_sdma.h | 2 +- drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 9 + drivers/gpu/drm/amd/amdgpu/cz_ih.c | 10 +- drivers/gpu/drm/amd/amdgpu/cz_ih.h | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 20 +- drivers/gpu/drm/amd/amdgpu/dce_v10_0.h | 4 +- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 20 +- drivers/gpu/drm/amd/amdgpu/dce_v11_0.h | 3 +- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 20 +- drivers/gpu/drm/amd/amdgpu/dce_v6_0.h | 3 +- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 47 +- drivers/gpu/drm/amd/amdgpu/dce_v8_0.h | 6 +- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 10 +- drivers/gpu/drm/amd/amdgpu/dce_virtual.h | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 11 +- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 38 +- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h | 5 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 20 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h | 3 +- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 20 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h | 3 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 29 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h | 4 +- drivers/gpu/drm/amd/amdgpu/iceland_ih.c | 10 +- drivers/gpu/drm/amd/amdgpu/iceland_ih.h | 2 +- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 9 + drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 11 +- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h | 2 +- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 20 +- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h | 3 +- drivers/gpu/drm/amd/amdgpu/si.c | 288 ++------- drivers/gpu/drm/amd/amdgpu/si.h | 2 - drivers/gpu/drm/amd/amdgpu/si_dma.c | 11 +- drivers/gpu/drm/amd/amdgpu/si_dma.h | 2 +- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 8 + drivers/gpu/drm/amd/amdgpu/si_ih.c | 10 +- drivers/gpu/drm/amd/amdgpu/si_ih.h | 2 +- drivers/gpu/drm/amd/amdgpu/tonga_ih.c | 10 +- drivers/gpu/drm/amd/amdgpu/tonga_ih.h | 4 +- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 11 +- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h | 2 +- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 11 +- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h | 2 +- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 29 +- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h | 4 +- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 11 +- drivers/gpu/drm/amd/amdgpu/vce_v2_0.h | 2 +- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 29 +- drivers/gpu/drm/amd/amdgpu/vce_v3_0.h | 4 +- drivers/gpu/drm/amd/amdgpu/vi.c | 837 ++++---------------------- drivers/gpu/drm/amd/amdgpu/vi.h | 2 - 69 files changed, 924 insertions(+), 1935 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e6f86b83652b..1800ea139c98 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -195,21 +195,38 @@ int amdgpu_wait_for_idle(struct amdgpu_device *adev, bool amdgpu_is_idle(struct amdgpu_device *adev, enum amd_ip_block_type block_type); +#define AMDGPU_MAX_IP_NUM 16 + +struct amdgpu_ip_block_status { + bool valid; + bool sw; + bool hw; + bool late_initialized; + bool hang; +}; + struct amdgpu_ip_block_version { - enum amd_ip_block_type type; - u32 major; - u32 minor; - u32 rev; + const enum amd_ip_block_type type; + const u32 major; + const u32 minor; + const u32 rev; const struct amd_ip_funcs *funcs; }; +struct amdgpu_ip_block { + struct amdgpu_ip_block_status status; + const struct amdgpu_ip_block_version *version; +}; + int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev, enum amd_ip_block_type type, u32 major, u32 minor); -const struct amdgpu_ip_block_version * amdgpu_get_ip_block( - struct amdgpu_device *adev, - enum amd_ip_block_type type); +struct amdgpu_ip_block * amdgpu_get_ip_block(struct amdgpu_device *adev, + enum amd_ip_block_type type); + +int amdgpu_ip_block_add(struct amdgpu_device *adev, + const struct amdgpu_ip_block_version *ip_block_version); /* provided by hw blocks that can move/clear data. e.g., gfx or sdma */ struct amdgpu_buffer_funcs { @@ -1271,14 +1288,6 @@ typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t); typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t); typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t); -struct amdgpu_ip_block_status { - bool valid; - bool sw; - bool hw; - bool late_initialized; - bool hang; -}; - struct amdgpu_device { struct device *dev; struct drm_device *ddev; @@ -1434,9 +1443,8 @@ struct amdgpu_device { /* GDS */ struct amdgpu_gds gds; - const struct amdgpu_ip_block_version *ip_blocks; + struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM]; int num_ip_blocks; - struct amdgpu_ip_block_status *ip_block_status; struct mutex mn_lock; DECLARE_HASHTABLE(mn_hash, 7); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index 892d60fb225b..2f9f96cc9f65 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c @@ -265,14 +265,14 @@ static int acp_hw_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; - const struct amdgpu_ip_block_version *ip_version = + const struct amdgpu_ip_block *ip_block = amdgpu_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ACP); - if (!ip_version) + if (!ip_block) return -EINVAL; r = amd_acp_hw_init(adev->acp.cgs_device, - ip_version->major, ip_version->minor); + ip_block->version->major, ip_block->version->minor); /* -ENODEV means board uses AZ rather than ACP */ if (r == -ENODEV) return 0; @@ -456,7 +456,7 @@ static int acp_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs acp_ip_funcs = { +static const struct amd_ip_funcs acp_ip_funcs = { .name = "acp_ip", .early_init = acp_early_init, .late_init = NULL, @@ -472,3 +472,12 @@ const struct amd_ip_funcs acp_ip_funcs = { .set_clockgating_state = acp_set_clockgating_state, .set_powergating_state = acp_set_powergating_state, }; + +const struct amdgpu_ip_block_version acp_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_ACP, + .major = 2, + .minor = 2, + .rev = 0, + .funcs = &acp_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h index 8a396313c86f..a288ce25c176 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h @@ -37,6 +37,6 @@ struct amdgpu_acp { struct acp_pm_domain *acp_genpd; }; -extern const struct amd_ip_funcs acp_ip_funcs; +extern const struct amdgpu_ip_block_version acp_ip_block; #endif /* __AMDGPU_ACP_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 34049d67a0d8..017556ca22e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -626,11 +626,11 @@ static int amdgpu_cgs_set_clockgating_state(struct cgs_device *cgs_device, int i, r = -1; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_blocks[i].type == block_type) { - r = adev->ip_blocks[i].funcs->set_clockgating_state( + if (adev->ip_blocks[i].version->type == block_type) { + r = adev->ip_blocks[i].version->funcs->set_clockgating_state( (void *)adev, state); break; @@ -647,11 +647,11 @@ static int amdgpu_cgs_set_powergating_state(struct cgs_device *cgs_device, int i, r = -1; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_blocks[i].type == block_type) { - r = adev->ip_blocks[i].funcs->set_powergating_state( + if (adev->ip_blocks[i].version->type == block_type) { + r = adev->ip_blocks[i].version->funcs->set_powergating_state( (void *)adev, state); break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index afeb7ab16d09..27a729c70c29 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1133,11 +1133,11 @@ int amdgpu_set_clockgating_state(struct amdgpu_device *adev, int i, r = 0; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_blocks[i].type == block_type) { - r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, - state); + if (adev->ip_blocks[i].version->type == block_type) { + r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev, + state); if (r) return r; break; @@ -1153,11 +1153,11 @@ int amdgpu_set_powergating_state(struct amdgpu_device *adev, int i, r = 0; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_blocks[i].type == block_type) { - r = adev->ip_blocks[i].funcs->set_powergating_state((void *)adev, - state); + if (adev->ip_blocks[i].version->type == block_type) { + r = adev->ip_blocks[i].version->funcs->set_powergating_state((void *)adev, + state); if (r) return r; break; @@ -1172,10 +1172,10 @@ int amdgpu_wait_for_idle(struct amdgpu_device *adev, int i, r; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_blocks[i].type == block_type) { - r = adev->ip_blocks[i].funcs->wait_for_idle((void *)adev); + if (adev->ip_blocks[i].version->type == block_type) { + r = adev->ip_blocks[i].version->funcs->wait_for_idle((void *)adev); if (r) return r; break; @@ -1191,23 +1191,22 @@ bool amdgpu_is_idle(struct amdgpu_device *adev, int i; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_blocks[i].type == block_type) - return adev->ip_blocks[i].funcs->is_idle((void *)adev); + if (adev->ip_blocks[i].version->type == block_type) + return adev->ip_blocks[i].version->funcs->is_idle((void *)adev); } return true; } -const struct amdgpu_ip_block_version * amdgpu_get_ip_block( - struct amdgpu_device *adev, - enum amd_ip_block_type type) +struct amdgpu_ip_block * amdgpu_get_ip_block(struct amdgpu_device *adev, + enum amd_ip_block_type type) { int i; for (i = 0; i < adev->num_ip_blocks; i++) - if (adev->ip_blocks[i].type == type) + if (adev->ip_blocks[i].version->type == type) return &adev->ip_blocks[i]; return NULL; @@ -1228,17 +1227,36 @@ int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev, enum amd_ip_block_type type, u32 major, u32 minor) { - const struct amdgpu_ip_block_version *ip_block; - ip_block = amdgpu_get_ip_block(adev, type); + struct amdgpu_ip_block *ip_block = amdgpu_get_ip_block(adev, type); - if (ip_block && ((ip_block->major > major) || - ((ip_block->major == major) && - (ip_block->minor >= minor)))) + if (ip_block && ((ip_block->version->major > major) || + ((ip_block->version->major == major) && + (ip_block->version->minor >= minor)))) return 0; return 1; } +/** + * amdgpu_ip_block_add + * + * @adev: amdgpu_device pointer + * @ip_block_version: pointer to the IP to add + * + * Adds the IP block driver information to the collection of IPs + * on the asic. + */ +int amdgpu_ip_block_add(struct amdgpu_device *adev, + const struct amdgpu_ip_block_version *ip_block_version) +{ + if (!ip_block_version) + return -EINVAL; + + adev->ip_blocks[adev->num_ip_blocks++].version = ip_block_version; + + return 0; +} + static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev) { adev->enable_virtual_display = false; @@ -1339,33 +1357,24 @@ static int amdgpu_early_init(struct amdgpu_device *adev) return -EINVAL; } - adev->ip_block_status = kcalloc(adev->num_ip_blocks, - sizeof(struct amdgpu_ip_block_status), GFP_KERNEL); - if (adev->ip_block_status == NULL) - return -ENOMEM; - - if (adev->ip_blocks == NULL) { - DRM_ERROR("No IP blocks found!\n"); - return r; - } - for (i = 0; i < adev->num_ip_blocks; i++) { if ((amdgpu_ip_block_mask & (1 << i)) == 0) { DRM_ERROR("disabled ip block: %d\n", i); - adev->ip_block_status[i].valid = false; + adev->ip_blocks[i].status.valid = false; } else { - if (adev->ip_blocks[i].funcs->early_init) { - r = adev->ip_blocks[i].funcs->early_init((void *)adev); + if (adev->ip_blocks[i].version->funcs->early_init) { + r = adev->ip_blocks[i].version->funcs->early_init((void *)adev); if (r == -ENOENT) { - adev->ip_block_status[i].valid = false; + adev->ip_blocks[i].status.valid = false; } else if (r) { - DRM_ERROR("early_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_ERROR("early_init of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); return r; } else { - adev->ip_block_status[i].valid = true; + adev->ip_blocks[i].status.valid = true; } } else { - adev->ip_block_status[i].valid = true; + adev->ip_blocks[i].status.valid = true; } } } @@ -1381,22 +1390,23 @@ static int amdgpu_init(struct amdgpu_device *adev) int i, r; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - r = adev->ip_blocks[i].funcs->sw_init((void *)adev); + r = adev->ip_blocks[i].version->funcs->sw_init((void *)adev); if (r) { - DRM_ERROR("sw_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_ERROR("sw_init of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); return r; } - adev->ip_block_status[i].sw = true; + adev->ip_blocks[i].status.sw = true; /* need to do gmc hw init early so we can allocate gpu mem */ - if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { + if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) { r = amdgpu_vram_scratch_init(adev); if (r) { DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r); return r; } - r = adev->ip_blocks[i].funcs->hw_init((void *)adev); + r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev); if (r) { DRM_ERROR("hw_init %d failed %d\n", i, r); return r; @@ -1406,22 +1416,23 @@ static int amdgpu_init(struct amdgpu_device *adev) DRM_ERROR("amdgpu_wb_init failed %d\n", r); return r; } - adev->ip_block_status[i].hw = true; + adev->ip_blocks[i].status.hw = true; } } for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].sw) + if (!adev->ip_blocks[i].status.sw) continue; /* gmc hw init is done early */ - if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) + if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) continue; - r = adev->ip_blocks[i].funcs->hw_init((void *)adev); + r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev); if (r) { - DRM_ERROR("hw_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_ERROR("hw_init of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); return r; } - adev->ip_block_status[i].hw = true; + adev->ip_blocks[i].status.hw = true; } return 0; @@ -1432,25 +1443,26 @@ static int amdgpu_late_init(struct amdgpu_device *adev) int i = 0, r; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_blocks[i].funcs->late_init) { - r = adev->ip_blocks[i].funcs->late_init((void *)adev); + if (adev->ip_blocks[i].version->funcs->late_init) { + r = adev->ip_blocks[i].version->funcs->late_init((void *)adev); if (r) { - DRM_ERROR("late_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_ERROR("late_init of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); return r; } - adev->ip_block_status[i].late_initialized = true; + adev->ip_blocks[i].status.late_initialized = true; } /* skip CG for VCE/UVD, it's handled specially */ - if (adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_UVD && - adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_VCE) { + if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD && + adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) { /* enable clockgating to save power */ - r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, - AMD_CG_STATE_GATE); + r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev, + AMD_CG_STATE_GATE); if (r) { DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n", - adev->ip_blocks[i].funcs->name, r); + adev->ip_blocks[i].version->funcs->name, r); return r; } } @@ -1465,68 +1477,71 @@ static int amdgpu_fini(struct amdgpu_device *adev) /* need to disable SMC first */ for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].hw) + if (!adev->ip_blocks[i].status.hw) continue; - if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) { + if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) { /* ungate blocks before hw fini so that we can shutdown the blocks safely */ - r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, - AMD_CG_STATE_UNGATE); + r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev, + AMD_CG_STATE_UNGATE); if (r) { DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", - adev->ip_blocks[i].funcs->name, r); + adev->ip_blocks[i].version->funcs->name, r); return r; } - r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); + r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev); /* XXX handle errors */ if (r) { DRM_DEBUG("hw_fini of IP block <%s> failed %d\n", - adev->ip_blocks[i].funcs->name, r); + adev->ip_blocks[i].version->funcs->name, r); } - adev->ip_block_status[i].hw = false; + adev->ip_blocks[i].status.hw = false; break; } } for (i = adev->num_ip_blocks - 1; i >= 0; i--) { - if (!adev->ip_block_status[i].hw) + if (!adev->ip_blocks[i].status.hw) continue; - if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { + if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) { amdgpu_wb_fini(adev); amdgpu_vram_scratch_fini(adev); } /* ungate blocks before hw fini so that we can shutdown the blocks safely */ - r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, - AMD_CG_STATE_UNGATE); + r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev, + AMD_CG_STATE_UNGATE); if (r) { - DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); return r; } - r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); + r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev); /* XXX handle errors */ if (r) { - DRM_DEBUG("hw_fini of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_DEBUG("hw_fini of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); } - adev->ip_block_status[i].hw = false; + adev->ip_blocks[i].status.hw = false; } for (i = adev->num_ip_blocks - 1; i >= 0; i--) { - if (!adev->ip_block_status[i].sw) + if (!adev->ip_blocks[i].status.sw) continue; - r = adev->ip_blocks[i].funcs->sw_fini((void *)adev); + r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev); /* XXX handle errors */ if (r) { - DRM_DEBUG("sw_fini of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_DEBUG("sw_fini of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); } - adev->ip_block_status[i].sw = false; - adev->ip_block_status[i].valid = false; + adev->ip_blocks[i].status.sw = false; + adev->ip_blocks[i].status.valid = false; } for (i = adev->num_ip_blocks - 1; i >= 0; i--) { - if (!adev->ip_block_status[i].late_initialized) + if (!adev->ip_blocks[i].status.late_initialized) continue; - if (adev->ip_blocks[i].funcs->late_fini) - adev->ip_blocks[i].funcs->late_fini((void *)adev); - adev->ip_block_status[i].late_initialized = false; + if (adev->ip_blocks[i].version->funcs->late_fini) + adev->ip_blocks[i].version->funcs->late_fini((void *)adev); + adev->ip_blocks[i].status.late_initialized = false; } return 0; @@ -1544,21 +1559,23 @@ static int amdgpu_suspend(struct amdgpu_device *adev) } for (i = adev->num_ip_blocks - 1; i >= 0; i--) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; /* ungate blocks so that suspend can properly shut them down */ if (i != AMD_IP_BLOCK_TYPE_SMC) { - r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, - AMD_CG_STATE_UNGATE); + r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev, + AMD_CG_STATE_UNGATE); if (r) { - DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); } } /* XXX handle errors */ - r = adev->ip_blocks[i].funcs->suspend(adev); + r = adev->ip_blocks[i].version->funcs->suspend(adev); /* XXX handle errors */ if (r) { - DRM_ERROR("suspend of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_ERROR("suspend of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); } } @@ -1570,11 +1587,12 @@ static int amdgpu_resume(struct amdgpu_device *adev) int i, r; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - r = adev->ip_blocks[i].funcs->resume(adev); + r = adev->ip_blocks[i].version->funcs->resume(adev); if (r) { - DRM_ERROR("resume of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); + DRM_ERROR("resume of IP block <%s> failed %d\n", + adev->ip_blocks[i].version->funcs->name, r); return r; } } @@ -1885,8 +1903,6 @@ void amdgpu_device_fini(struct amdgpu_device *adev) amdgpu_fence_driver_fini(adev); amdgpu_fbdev_fini(adev); r = amdgpu_fini(adev); - kfree(adev->ip_block_status); - adev->ip_block_status = NULL; adev->accel_working = false; /* free i2c buses */ amdgpu_i2c_fini(adev); @@ -2125,13 +2141,13 @@ static bool amdgpu_check_soft_reset(struct amdgpu_device *adev) bool asic_hang = false; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_blocks[i].funcs->check_soft_reset) - adev->ip_block_status[i].hang = - adev->ip_blocks[i].funcs->check_soft_reset(adev); - if (adev->ip_block_status[i].hang) { - DRM_INFO("IP block:%d is hang!\n", i); + if (adev->ip_blocks[i].version->funcs->check_soft_reset) + adev->ip_blocks[i].status.hang = + adev->ip_blocks[i].version->funcs->check_soft_reset(adev); + if (adev->ip_blocks[i].status.hang) { + DRM_INFO("IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name); asic_hang = true; } } @@ -2143,11 +2159,11 @@ static int amdgpu_pre_soft_reset(struct amdgpu_device *adev) int i, r = 0; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_block_status[i].hang && - adev->ip_blocks[i].funcs->pre_soft_reset) { - r = adev->ip_blocks[i].funcs->pre_soft_reset(adev); + if (adev->ip_blocks[i].status.hang && + adev->ip_blocks[i].version->funcs->pre_soft_reset) { + r = adev->ip_blocks[i].version->funcs->pre_soft_reset(adev); if (r) return r; } @@ -2161,13 +2177,13 @@ static bool amdgpu_need_full_reset(struct amdgpu_device *adev) int i; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if ((adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) || - (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) || - (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_ACP) || - (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_DCE)) { - if (adev->ip_block_status[i].hang) { + if ((adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) || + (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) || + (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_ACP) || + (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE)) { + if (adev->ip_blocks[i].status.hang) { DRM_INFO("Some block need full reset!\n"); return true; } @@ -2181,11 +2197,11 @@ static int amdgpu_soft_reset(struct amdgpu_device *adev) int i, r = 0; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_block_status[i].hang && - adev->ip_blocks[i].funcs->soft_reset) { - r = adev->ip_blocks[i].funcs->soft_reset(adev); + if (adev->ip_blocks[i].status.hang && + adev->ip_blocks[i].version->funcs->soft_reset) { + r = adev->ip_blocks[i].version->funcs->soft_reset(adev); if (r) return r; } @@ -2199,11 +2215,11 @@ static int amdgpu_post_soft_reset(struct amdgpu_device *adev) int i, r = 0; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) + if (!adev->ip_blocks[i].status.valid) continue; - if (adev->ip_block_status[i].hang && - adev->ip_blocks[i].funcs->post_soft_reset) - r = adev->ip_blocks[i].funcs->post_soft_reset(adev); + if (adev->ip_blocks[i].status.hang && + adev->ip_blocks[i].version->funcs->post_soft_reset) + r = adev->ip_blocks[i].version->funcs->post_soft_reset(adev); if (r) return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 3570124ed186..d17424663fe2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -306,10 +306,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file } for (i = 0; i < adev->num_ip_blocks; i++) { - if (adev->ip_blocks[i].type == type && - adev->ip_block_status[i].valid) { - ip.hw_ip_version_major = adev->ip_blocks[i].major; - ip.hw_ip_version_minor = adev->ip_blocks[i].minor; + if (adev->ip_blocks[i].version->type == type && + adev->ip_blocks[i].status.valid) { + ip.hw_ip_version_major = adev->ip_blocks[i].version->major; + ip.hw_ip_version_minor = adev->ip_blocks[i].version->minor; ip.capabilities_flags = 0; ip.available_rings = ring_mask; ip.ib_start_alignment = ib_start_alignment; @@ -345,8 +345,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file } for (i = 0; i < adev->num_ip_blocks; i++) - if (adev->ip_blocks[i].type == type && - adev->ip_block_status[i].valid && + if (adev->ip_blocks[i].version->type == type && + adev->ip_blocks[i].status.valid && count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT) count++; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index 7532ff822aa7..fa6baf31a35d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -299,7 +299,7 @@ static int amdgpu_pp_soft_reset(void *handle) return ret; } -const struct amd_ip_funcs amdgpu_pp_ip_funcs = { +static const struct amd_ip_funcs amdgpu_pp_ip_funcs = { .name = "amdgpu_powerplay", .early_init = amdgpu_pp_early_init, .late_init = amdgpu_pp_late_init, @@ -316,3 +316,12 @@ const struct amd_ip_funcs amdgpu_pp_ip_funcs = { .set_clockgating_state = amdgpu_pp_set_clockgating_state, .set_powergating_state = amdgpu_pp_set_powergating_state, }; + +const struct amdgpu_ip_block_version amdgpu_pp_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &amdgpu_pp_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h index ee6ea6c98e4f..c0c4bfdcdb14 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h @@ -28,6 +28,6 @@ #include "amd_shared.h" -extern const struct amd_ip_funcs amdgpu_pp_ip_funcs; +extern const struct amdgpu_ip_block_version amdgpu_pp_ip_block; #endif /* __AMDGPU_POWERPLAY_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index da66823eff1c..ded57dd538e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -346,7 +346,7 @@ error: static bool amdgpu_vm_ring_has_compute_vm_bug(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - const struct amdgpu_ip_block_version *ip_block; + const struct amdgpu_ip_block *ip_block; if (ring->funcs->type != AMDGPU_RING_TYPE_COMPUTE) /* only compute rings */ @@ -356,10 +356,10 @@ static bool amdgpu_vm_ring_has_compute_vm_bug(struct amdgpu_ring *ring) if (!ip_block) return false; - if (ip_block->major <= 7) { + if (ip_block->version->major <= 7) { /* gfx7 has no workaround */ return true; - } else if (ip_block->major == 8) { + } else if (ip_block->version->major == 8) { if (adev->gfx.mec_fw_version >= 673) /* gfx8 is fixed in MEC firmware 673 */ return false; diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 3f891076c070..885f08c3f496 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6663,3 +6663,12 @@ static void ci_dpm_set_irq_funcs(struct amdgpu_device *adev) adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; adev->pm.dpm.thermal.irq.funcs = &ci_dpm_irq_funcs; } + +const struct amdgpu_ip_block_version ci_dpm_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 7, + .minor = 0, + .rev = 0, + .funcs = &ci_dpm_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index a845b6a93b79..1b70f8fa4280 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1641,745 +1641,6 @@ static void cik_detect_hw_virtualization(struct amdgpu_device *adev) adev->virtualization.virtual_caps |= AMDGPU_PASSTHROUGH_MODE; } -static const struct amdgpu_ip_block_version bonaire_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 2, - .rev = 0, - .funcs = &dce_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 2, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version bonaire_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 2, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 2, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version hawaii_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 5, - .rev = 0, - .funcs = &dce_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 3, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version hawaii_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 5, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 3, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version kabini_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 3, - .rev = 0, - .funcs = &dce_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 2, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version kabini_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 3, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 2, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version mullins_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 3, - .rev = 0, - .funcs = &dce_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 2, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version mullins_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 3, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 2, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version kaveri_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 1, - .rev = 0, - .funcs = &dce_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 1, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version kaveri_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &cik_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 8, - .minor = 1, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 7, - .minor = 1, - .rev = 0, - .funcs = &gfx_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &cik_sdma_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 4, - .minor = 2, - .rev = 0, - .funcs = &uvd_v4_2_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vce_v2_0_ip_funcs, - }, -}; - -int cik_set_ip_blocks(struct amdgpu_device *adev) -{ - if (adev->enable_virtual_display) { - switch (adev->asic_type) { - case CHIP_BONAIRE: - adev->ip_blocks = bonaire_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks_vd); - break; - case CHIP_HAWAII: - adev->ip_blocks = hawaii_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks_vd); - break; - case CHIP_KAVERI: - adev->ip_blocks = kaveri_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks_vd); - break; - case CHIP_KABINI: - adev->ip_blocks = kabini_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks_vd); - break; - case CHIP_MULLINS: - adev->ip_blocks = mullins_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks_vd); - break; - default: - /* FIXME: not supported yet */ - return -EINVAL; - } - } else { - switch (adev->asic_type) { - case CHIP_BONAIRE: - adev->ip_blocks = bonaire_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks); - break; - case CHIP_HAWAII: - adev->ip_blocks = hawaii_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks); - break; - case CHIP_KAVERI: - adev->ip_blocks = kaveri_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks); - break; - case CHIP_KABINI: - adev->ip_blocks = kabini_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks); - break; - case CHIP_MULLINS: - adev->ip_blocks = mullins_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks); - break; - default: - /* FIXME: not supported yet */ - return -EINVAL; - } - } - - return 0; -} - static const struct amdgpu_asic_funcs cik_asic_funcs = { .read_disabled_bios = &cik_read_disabled_bios, @@ -2612,7 +1873,7 @@ static int cik_common_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs cik_common_ip_funcs = { +static const struct amd_ip_funcs cik_common_ip_funcs = { .name = "cik_common", .early_init = cik_common_early_init, .late_init = NULL, @@ -2628,3 +1889,79 @@ const struct amd_ip_funcs cik_common_ip_funcs = { .set_clockgating_state = cik_common_set_clockgating_state, .set_powergating_state = cik_common_set_powergating_state, }; + +static const struct amdgpu_ip_block_version cik_common_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_COMMON, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &cik_common_ip_funcs, +}; + +int cik_set_ip_blocks(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_BONAIRE: + amdgpu_ip_block_add(adev, &cik_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block); + amdgpu_ip_block_add(adev, &cik_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v8_2_ip_block); + amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block); + amdgpu_ip_block_add(adev, &cik_sdma_ip_block); + amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block); + amdgpu_ip_block_add(adev, &vce_v2_0_ip_block); + break; + case CHIP_HAWAII: + amdgpu_ip_block_add(adev, &cik_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block); + amdgpu_ip_block_add(adev, &cik_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v8_5_ip_block); + amdgpu_ip_block_add(adev, &gfx_v7_3_ip_block); + amdgpu_ip_block_add(adev, &cik_sdma_ip_block); + amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block); + amdgpu_ip_block_add(adev, &vce_v2_0_ip_block); + break; + case CHIP_KAVERI: + amdgpu_ip_block_add(adev, &cik_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block); + amdgpu_ip_block_add(adev, &cik_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v8_1_ip_block); + amdgpu_ip_block_add(adev, &gfx_v7_1_ip_block); + amdgpu_ip_block_add(adev, &cik_sdma_ip_block); + amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block); + amdgpu_ip_block_add(adev, &vce_v2_0_ip_block); + break; + case CHIP_KABINI: + case CHIP_MULLINS: + amdgpu_ip_block_add(adev, &cik_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block); + amdgpu_ip_block_add(adev, &cik_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v8_3_ip_block); + amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block); + amdgpu_ip_block_add(adev, &cik_sdma_ip_block); + amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block); + amdgpu_ip_block_add(adev, &vce_v2_0_ip_block); + break; + default: + /* FIXME: not supported yet */ + return -EINVAL; + } + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/cik.h b/drivers/gpu/drm/amd/amdgpu/cik.h index 5ebd2d7a0327..c4989f51ecef 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.h +++ b/drivers/gpu/drm/amd/amdgpu/cik.h @@ -24,8 +24,6 @@ #ifndef __CIK_H__ #define __CIK_H__ -extern const struct amd_ip_funcs cik_common_ip_funcs; - void cik_srbm_select(struct amdgpu_device *adev, u32 me, u32 pipe, u32 queue, u32 vmid); int cik_set_ip_blocks(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c index be3d6f79a864..319b32cdea84 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c @@ -413,7 +413,7 @@ static int cik_ih_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs cik_ih_ip_funcs = { +static const struct amd_ip_funcs cik_ih_ip_funcs = { .name = "cik_ih", .early_init = cik_ih_early_init, .late_init = NULL, @@ -441,3 +441,12 @@ static void cik_ih_set_interrupt_funcs(struct amdgpu_device *adev) if (adev->irq.ih_funcs == NULL) adev->irq.ih_funcs = &cik_ih_funcs; } + +const struct amdgpu_ip_block_version cik_ih_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 2, + .minor = 0, + .rev = 0, + .funcs = &cik_ih_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.h b/drivers/gpu/drm/amd/amdgpu/cik_ih.h index 6b0f375ec244..1d9ddee2868e 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_ih.h +++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.h @@ -24,6 +24,6 @@ #ifndef __CIK_IH_H__ #define __CIK_IH_H__ -extern const struct amd_ip_funcs cik_ih_ip_funcs; +extern const struct amdgpu_ip_block_version cik_ih_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index b96ef20e871f..c7340b6e17c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -1190,7 +1190,7 @@ static int cik_sdma_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs cik_sdma_ip_funcs = { +static const struct amd_ip_funcs cik_sdma_ip_funcs = { .name = "cik_sdma", .early_init = cik_sdma_early_init, .late_init = NULL, @@ -1342,3 +1342,12 @@ static void cik_sdma_set_vm_pte_funcs(struct amdgpu_device *adev) adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances; } } + +const struct amdgpu_ip_block_version cik_sdma_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 2, + .minor = 0, + .rev = 0, + .funcs = &cik_sdma_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.h b/drivers/gpu/drm/amd/amdgpu/cik_sdma.h index 027727c677b8..a4a8fe01410b 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.h +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.h @@ -24,6 +24,6 @@ #ifndef __CIK_SDMA_H__ #define __CIK_SDMA_H__ -extern const struct amd_ip_funcs cik_sdma_ip_funcs; +extern const struct amdgpu_ip_block_version cik_sdma_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index 3c082e143730..ad2cc4be6737 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -2296,3 +2296,12 @@ static void cz_dpm_set_funcs(struct amdgpu_device *adev) if (NULL == adev->pm.funcs) adev->pm.funcs = &cz_dpm_funcs; } + +const struct amdgpu_ip_block_version cz_dpm_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 8, + .minor = 0, + .rev = 0, + .funcs = &cz_dpm_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c index 3d23a70b6432..fe7cbb24da7b 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c @@ -394,7 +394,7 @@ static int cz_ih_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs cz_ih_ip_funcs = { +static const struct amd_ip_funcs cz_ih_ip_funcs = { .name = "cz_ih", .early_init = cz_ih_early_init, .late_init = NULL, @@ -423,3 +423,11 @@ static void cz_ih_set_interrupt_funcs(struct amdgpu_device *adev) adev->irq.ih_funcs = &cz_ih_funcs; } +const struct amdgpu_ip_block_version cz_ih_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 3, + .minor = 0, + .rev = 0, + .funcs = &cz_ih_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.h b/drivers/gpu/drm/amd/amdgpu/cz_ih.h index fc4057a2ecb9..14be7753221b 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ih.h +++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.h @@ -24,6 +24,6 @@ #ifndef __CZ_IH_H__ #define __CZ_IH_H__ -extern const struct amd_ip_funcs cz_ih_ip_funcs; +extern const struct amdgpu_ip_block_version cz_ih_ip_block; #endif /* __CZ_IH_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 15c38331a319..e5d0edfb4309 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -3470,7 +3470,7 @@ static int dce_v10_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs dce_v10_0_ip_funcs = { +static const struct amd_ip_funcs dce_v10_0_ip_funcs = { .name = "dce_v10_0", .early_init = dce_v10_0_early_init, .late_init = NULL, @@ -3801,3 +3801,21 @@ static void dce_v10_0_set_irq_funcs(struct amdgpu_device *adev) adev->hpd_irq.num_types = AMDGPU_HPD_LAST; adev->hpd_irq.funcs = &dce_v10_0_hpd_irq_funcs; } + +const struct amdgpu_ip_block_version dce_v10_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 10, + .minor = 0, + .rev = 0, + .funcs = &dce_v10_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version dce_v10_1_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 10, + .minor = 1, + .rev = 0, + .funcs = &dce_v10_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h index e3dc04d293e4..7a0747789f1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h @@ -24,7 +24,9 @@ #ifndef __DCE_V10_0_H__ #define __DCE_V10_0_H__ -extern const struct amd_ip_funcs dce_v10_0_ip_funcs; + +extern const struct amdgpu_ip_block_version dce_v10_0_ip_block; +extern const struct amdgpu_ip_block_version dce_v10_1_ip_block; void dce_v10_0_disable_dce(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 2696428bed05..9719b2b14186 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -3527,7 +3527,7 @@ static int dce_v11_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs dce_v11_0_ip_funcs = { +static const struct amd_ip_funcs dce_v11_0_ip_funcs = { .name = "dce_v11_0", .early_init = dce_v11_0_early_init, .late_init = NULL, @@ -3857,3 +3857,21 @@ static void dce_v11_0_set_irq_funcs(struct amdgpu_device *adev) adev->hpd_irq.num_types = AMDGPU_HPD_LAST; adev->hpd_irq.funcs = &dce_v11_0_hpd_irq_funcs; } + +const struct amdgpu_ip_block_version dce_v11_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 11, + .minor = 0, + .rev = 0, + .funcs = &dce_v11_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version dce_v11_2_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 11, + .minor = 2, + .rev = 0, + .funcs = &dce_v11_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h index 1f58a65ba2ef..0d878ca3acba 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h @@ -24,7 +24,8 @@ #ifndef __DCE_V11_0_H__ #define __DCE_V11_0_H__ -extern const struct amd_ip_funcs dce_v11_0_ip_funcs; +extern const struct amdgpu_ip_block_version dce_v11_0_ip_block; +extern const struct amdgpu_ip_block_version dce_v11_2_ip_block; void dce_v11_0_disable_dce(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 502e97963d6d..44547f951d92 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -2734,7 +2734,7 @@ static int dce_v6_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs dce_v6_0_ip_funcs = { +static const struct amd_ip_funcs dce_v6_0_ip_funcs = { .name = "dce_v6_0", .early_init = dce_v6_0_early_init, .late_init = NULL, @@ -3075,3 +3075,21 @@ static void dce_v6_0_set_irq_funcs(struct amdgpu_device *adev) adev->hpd_irq.num_types = AMDGPU_HPD_LAST; adev->hpd_irq.funcs = &dce_v6_0_hpd_irq_funcs; } + +const struct amdgpu_ip_block_version dce_v6_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &dce_v6_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version dce_v6_4_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 6, + .minor = 4, + .rev = 0, + .funcs = &dce_v6_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h index 4c6cd18e9053..7b546b596de1 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h @@ -24,7 +24,8 @@ #ifndef __DCE_V6_0_H__ #define __DCE_V6_0_H__ -extern const struct amd_ip_funcs dce_v6_0_ip_funcs; +extern const struct amdgpu_ip_block_version dce_v6_0_ip_block; +extern const struct amdgpu_ip_block_version dce_v6_4_ip_block; void dce_v6_0_disable_dce(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 0245ed605107..16a2f1faaf19 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -3308,7 +3308,7 @@ static int dce_v8_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs dce_v8_0_ip_funcs = { +static const struct amd_ip_funcs dce_v8_0_ip_funcs = { .name = "dce_v8_0", .early_init = dce_v8_0_early_init, .late_init = NULL, @@ -3638,3 +3638,48 @@ static void dce_v8_0_set_irq_funcs(struct amdgpu_device *adev) adev->hpd_irq.num_types = AMDGPU_HPD_LAST; adev->hpd_irq.funcs = &dce_v8_0_hpd_irq_funcs; } + +const struct amdgpu_ip_block_version dce_v8_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 8, + .minor = 0, + .rev = 0, + .funcs = &dce_v8_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version dce_v8_1_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 8, + .minor = 1, + .rev = 0, + .funcs = &dce_v8_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version dce_v8_2_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 8, + .minor = 2, + .rev = 0, + .funcs = &dce_v8_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version dce_v8_3_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 8, + .minor = 3, + .rev = 0, + .funcs = &dce_v8_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version dce_v8_5_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 8, + .minor = 5, + .rev = 0, + .funcs = &dce_v8_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h index 7d0770c3a49b..13b802dd946a 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h @@ -24,7 +24,11 @@ #ifndef __DCE_V8_0_H__ #define __DCE_V8_0_H__ -extern const struct amd_ip_funcs dce_v8_0_ip_funcs; +extern const struct amdgpu_ip_block_version dce_v8_0_ip_block; +extern const struct amdgpu_ip_block_version dce_v8_1_ip_block; +extern const struct amdgpu_ip_block_version dce_v8_2_ip_block; +extern const struct amdgpu_ip_block_version dce_v8_3_ip_block; +extern const struct amdgpu_ip_block_version dce_v8_5_ip_block; void dce_v8_0_disable_dce(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 7d041b9a4d61..cc85676a68d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -574,7 +574,7 @@ static int dce_virtual_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs dce_virtual_ip_funcs = { +static const struct amd_ip_funcs dce_virtual_ip_funcs = { .name = "dce_virtual", .early_init = dce_virtual_early_init, .late_init = NULL, @@ -824,3 +824,11 @@ static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev) adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs; } +const struct amdgpu_ip_block_version dce_virtual_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &dce_virtual_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h index 393ce97f783e..ed422012c8c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h @@ -24,7 +24,7 @@ #ifndef __DCE_VIRTUAL_H__ #define __DCE_VIRTUAL_H__ -extern const struct amd_ip_funcs dce_virtual_ip_funcs; +extern const struct amdgpu_ip_block_version dce_virtual_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 367b14e16e53..96dd05dca694 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -3206,7 +3206,7 @@ static int gfx_v6_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs gfx_v6_0_ip_funcs = { +static const struct amd_ip_funcs gfx_v6_0_ip_funcs = { .name = "gfx_v6_0", .early_init = gfx_v6_0_early_init, .late_init = NULL, @@ -3344,3 +3344,12 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev) cu_info->number = active_cu_number; cu_info->ao_cu_mask = ao_cu_mask; } + +const struct amdgpu_ip_block_version gfx_v6_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gfx_v6_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h index b9657e72b248..ced6fc42f688 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h @@ -24,6 +24,6 @@ #ifndef __GFX_V6_0_H__ #define __GFX_V6_0_H__ -extern const struct amd_ip_funcs gfx_v6_0_ip_funcs; +extern const struct amdgpu_ip_block_version gfx_v6_0_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 388649734b36..bc6ccd05010f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -5087,7 +5087,7 @@ static int gfx_v7_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs gfx_v7_0_ip_funcs = { +static const struct amd_ip_funcs gfx_v7_0_ip_funcs = { .name = "gfx_v7_0", .early_init = gfx_v7_0_early_init, .late_init = gfx_v7_0_late_init, @@ -5270,3 +5270,39 @@ static void gfx_v7_0_get_cu_info(struct amdgpu_device *adev) cu_info->number = active_cu_number; cu_info->ao_cu_mask = ao_cu_mask; } + +const struct amdgpu_ip_block_version gfx_v7_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 7, + .minor = 0, + .rev = 0, + .funcs = &gfx_v7_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version gfx_v7_1_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 7, + .minor = 1, + .rev = 0, + .funcs = &gfx_v7_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version gfx_v7_2_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 7, + .minor = 2, + .rev = 0, + .funcs = &gfx_v7_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version gfx_v7_3_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 7, + .minor = 3, + .rev = 0, + .funcs = &gfx_v7_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h index 94e3ea147c26..2f5164cc0e53 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h @@ -24,6 +24,9 @@ #ifndef __GFX_V7_0_H__ #define __GFX_V7_0_H__ -extern const struct amd_ip_funcs gfx_v7_0_ip_funcs; +extern const struct amdgpu_ip_block_version gfx_v7_0_ip_block; +extern const struct amdgpu_ip_block_version gfx_v7_1_ip_block; +extern const struct amdgpu_ip_block_version gfx_v7_2_ip_block; +extern const struct amdgpu_ip_block_version gfx_v7_3_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 6f3996f6d39a..27b3de44add7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6504,7 +6504,7 @@ static int gfx_v8_0_priv_inst_irq(struct amdgpu_device *adev, return 0; } -const struct amd_ip_funcs gfx_v8_0_ip_funcs = { +static const struct amd_ip_funcs gfx_v8_0_ip_funcs = { .name = "gfx_v8_0", .early_init = gfx_v8_0_early_init, .late_init = gfx_v8_0_late_init, @@ -6734,3 +6734,21 @@ static void gfx_v8_0_get_cu_info(struct amdgpu_device *adev) cu_info->number = active_cu_number; cu_info->ao_cu_mask = ao_cu_mask; } + +const struct amdgpu_ip_block_version gfx_v8_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 8, + .minor = 0, + .rev = 0, + .funcs = &gfx_v8_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version gfx_v8_1_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 8, + .minor = 1, + .rev = 0, + .funcs = &gfx_v8_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h index ebed1f829297..788cc3ab584b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h @@ -24,6 +24,7 @@ #ifndef __GFX_V8_0_H__ #define __GFX_V8_0_H__ -extern const struct amd_ip_funcs gfx_v8_0_ip_funcs; +extern const struct amdgpu_ip_block_version gfx_v8_0_ip_block; +extern const struct amdgpu_ip_block_version gfx_v8_1_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index b13c8aaec078..1940d36bc304 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -1030,7 +1030,7 @@ static int gmc_v6_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs gmc_v6_0_ip_funcs = { +static const struct amd_ip_funcs gmc_v6_0_ip_funcs = { .name = "gmc_v6_0", .early_init = gmc_v6_0_early_init, .late_init = gmc_v6_0_late_init, @@ -1069,3 +1069,11 @@ static void gmc_v6_0_set_irq_funcs(struct amdgpu_device *adev) adev->mc.vm_fault.funcs = &gmc_v6_0_irq_funcs; } +const struct amdgpu_ip_block_version gmc_v6_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gmc_v6_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h index 42c4fc676cd4..ed2f64dec47a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h @@ -24,6 +24,6 @@ #ifndef __GMC_V6_0_H__ #define __GMC_V6_0_H__ -extern const struct amd_ip_funcs gmc_v6_0_ip_funcs; +extern const struct amdgpu_ip_block_version gmc_v6_0_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index aa0c4b964621..3a25f72980c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -1235,7 +1235,7 @@ static int gmc_v7_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs gmc_v7_0_ip_funcs = { +static const struct amd_ip_funcs gmc_v7_0_ip_funcs = { .name = "gmc_v7_0", .early_init = gmc_v7_0_early_init, .late_init = gmc_v7_0_late_init, @@ -1273,3 +1273,21 @@ static void gmc_v7_0_set_irq_funcs(struct amdgpu_device *adev) adev->mc.vm_fault.num_types = 1; adev->mc.vm_fault.funcs = &gmc_v7_0_irq_funcs; } + +const struct amdgpu_ip_block_version gmc_v7_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 7, + .minor = 0, + .rev = 0, + .funcs = &gmc_v7_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version gmc_v7_4_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 7, + .minor = 4, + .rev = 0, + .funcs = &gmc_v7_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h index 0b386b5d2f7a..ebce2966c1c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h @@ -24,6 +24,7 @@ #ifndef __GMC_V7_0_H__ #define __GMC_V7_0_H__ -extern const struct amd_ip_funcs gmc_v7_0_ip_funcs; +extern const struct amdgpu_ip_block_version gmc_v7_0_ip_block; +extern const struct amdgpu_ip_block_version gmc_v7_4_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index c22ef140a542..74d7cc3f7e8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1436,7 +1436,7 @@ static int gmc_v8_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs gmc_v8_0_ip_funcs = { +static const struct amd_ip_funcs gmc_v8_0_ip_funcs = { .name = "gmc_v8_0", .early_init = gmc_v8_0_early_init, .late_init = gmc_v8_0_late_init, @@ -1477,3 +1477,30 @@ static void gmc_v8_0_set_irq_funcs(struct amdgpu_device *adev) adev->mc.vm_fault.num_types = 1; adev->mc.vm_fault.funcs = &gmc_v8_0_irq_funcs; } + +const struct amdgpu_ip_block_version gmc_v8_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 8, + .minor = 0, + .rev = 0, + .funcs = &gmc_v8_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version gmc_v8_1_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 8, + .minor = 1, + .rev = 0, + .funcs = &gmc_v8_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version gmc_v8_5_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 8, + .minor = 5, + .rev = 0, + .funcs = &gmc_v8_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h index fc5001a8119d..19b8a8aed204 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h @@ -24,6 +24,8 @@ #ifndef __GMC_V8_0_H__ #define __GMC_V8_0_H__ -extern const struct amd_ip_funcs gmc_v8_0_ip_funcs; +extern const struct amdgpu_ip_block_version gmc_v8_0_ip_block; +extern const struct amdgpu_ip_block_version gmc_v8_1_ip_block; +extern const struct amdgpu_ip_block_version gmc_v8_5_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c index 3b8906ce3511..ac21bb7bc0f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c @@ -392,7 +392,7 @@ static int iceland_ih_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs iceland_ih_ip_funcs = { +static const struct amd_ip_funcs iceland_ih_ip_funcs = { .name = "iceland_ih", .early_init = iceland_ih_early_init, .late_init = NULL, @@ -421,3 +421,11 @@ static void iceland_ih_set_interrupt_funcs(struct amdgpu_device *adev) adev->irq.ih_funcs = &iceland_ih_funcs; } +const struct amdgpu_ip_block_version iceland_ih_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 2, + .minor = 4, + .rev = 0, + .funcs = &iceland_ih_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.h b/drivers/gpu/drm/amd/amdgpu/iceland_ih.h index 57558cddfbcb..3235f4277548 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.h +++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.h @@ -24,6 +24,6 @@ #ifndef __ICELAND_IH_H__ #define __ICELAND_IH_H__ -extern const struct amd_ip_funcs iceland_ih_ip_funcs; +extern const struct amdgpu_ip_block_version iceland_ih_ip_block; #endif /* __ICELAND_IH_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index c3367d6f311a..42e5c9400f97 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -3292,3 +3292,12 @@ static void kv_dpm_set_irq_funcs(struct amdgpu_device *adev) adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; adev->pm.dpm.thermal.irq.funcs = &kv_dpm_irq_funcs; } + +const struct amdgpu_ip_block_version kv_dpm_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 7, + .minor = 0, + .rev = 0, + .funcs = &kv_dpm_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 5859a106608b..03e8856b08ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -1187,7 +1187,7 @@ static int sdma_v2_4_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs sdma_v2_4_ip_funcs = { +static const struct amd_ip_funcs sdma_v2_4_ip_funcs = { .name = "sdma_v2_4", .early_init = sdma_v2_4_early_init, .late_init = NULL, @@ -1340,3 +1340,12 @@ static void sdma_v2_4_set_vm_pte_funcs(struct amdgpu_device *adev) adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances; } } + +const struct amdgpu_ip_block_version sdma_v2_4_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 2, + .minor = 4, + .rev = 0, + .funcs = &sdma_v2_4_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h index 07349f5ee10f..28b433729216 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h @@ -24,6 +24,6 @@ #ifndef __SDMA_V2_4_H__ #define __SDMA_V2_4_H__ -extern const struct amd_ip_funcs sdma_v2_4_ip_funcs; +extern const struct amdgpu_ip_block_version sdma_v2_4_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 24642f92b4b5..6172d01e985a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1527,7 +1527,7 @@ static int sdma_v3_0_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs sdma_v3_0_ip_funcs = { +static const struct amd_ip_funcs sdma_v3_0_ip_funcs = { .name = "sdma_v3_0", .early_init = sdma_v3_0_early_init, .late_init = NULL, @@ -1683,3 +1683,21 @@ static void sdma_v3_0_set_vm_pte_funcs(struct amdgpu_device *adev) adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances; } } + +const struct amdgpu_ip_block_version sdma_v3_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 3, + .minor = 0, + .rev = 0, + .funcs = &sdma_v3_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version sdma_v3_1_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 3, + .minor = 1, + .rev = 0, + .funcs = &sdma_v3_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h index 0cb9698a3054..7aa223d35f1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h @@ -24,6 +24,7 @@ #ifndef __SDMA_V3_0_H__ #define __SDMA_V3_0_H__ -extern const struct amd_ip_funcs sdma_v3_0_ip_funcs; +extern const struct amdgpu_ip_block_version sdma_v3_0_ip_block; +extern const struct amdgpu_ip_block_version sdma_v3_1_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 1d40c26de324..d2d79206bcf9 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1812,7 +1812,7 @@ static int si_common_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs si_common_ip_funcs = { +static const struct amd_ip_funcs si_common_ip_funcs = { .name = "si_common", .early_init = si_common_early_init, .late_init = NULL, @@ -1829,240 +1829,13 @@ const struct amd_ip_funcs si_common_ip_funcs = { .set_powergating_state = si_common_set_powergating_state, }; -static const struct amdgpu_ip_block_version verde_ip_blocks[] = +static const struct amdgpu_ip_block_version si_common_ip_block = { - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &gmc_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &dce_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &gfx_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_dma_ip_funcs, - }, -/* { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 3, - .minor = 1, - .rev = 0, - .funcs = &si_null_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_null_ip_funcs, - }, - */ -}; - - -static const struct amdgpu_ip_block_version verde_ip_blocks_vd[] = -{ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &gmc_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &gfx_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_dma_ip_funcs, - }, -/* { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 3, - .minor = 1, - .rev = 0, - .funcs = &si_null_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_null_ip_funcs, - }, - */ -}; - -static const struct amdgpu_ip_block_version hainan_ip_blocks[] = -{ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &gmc_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &gfx_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_dma_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version hainan_ip_blocks_vd[] = -{ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &gmc_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &gfx_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &si_dma_ip_funcs, - }, + .type = AMD_IP_BLOCK_TYPE_COMMON, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_common_ip_funcs, }; int si_set_ip_blocks(struct amdgpu_device *adev) @@ -2071,23 +1844,42 @@ int si_set_ip_blocks(struct amdgpu_device *adev) case CHIP_VERDE: case CHIP_TAHITI: case CHIP_PITCAIRN: + amdgpu_ip_block_add(adev, &si_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block); + amdgpu_ip_block_add(adev, &si_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v6_0_ip_block); + amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block); + amdgpu_ip_block_add(adev, &si_dma_ip_block); + /* amdgpu_ip_block_add(adev, &uvd_v3_1_ip_block); */ + /* amdgpu_ip_block_add(adev, &vce_v1_0_ip_block); */ + break; case CHIP_OLAND: - if (adev->enable_virtual_display) { - adev->ip_blocks = verde_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(verde_ip_blocks_vd); - } else { - adev->ip_blocks = verde_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(verde_ip_blocks); - } + amdgpu_ip_block_add(adev, &si_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block); + amdgpu_ip_block_add(adev, &si_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v6_4_ip_block); + amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block); + amdgpu_ip_block_add(adev, &si_dma_ip_block); + /* amdgpu_ip_block_add(adev, &uvd_v3_1_ip_block); */ + /* amdgpu_ip_block_add(adev, &vce_v1_0_ip_block); */ break; case CHIP_HAINAN: - if (adev->enable_virtual_display) { - adev->ip_blocks = hainan_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(hainan_ip_blocks_vd); - } else { - adev->ip_blocks = hainan_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(hainan_ip_blocks); - } + amdgpu_ip_block_add(adev, &si_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block); + amdgpu_ip_block_add(adev, &si_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block); + amdgpu_ip_block_add(adev, &si_dma_ip_block); break; default: BUG(); diff --git a/drivers/gpu/drm/amd/amdgpu/si.h b/drivers/gpu/drm/amd/amdgpu/si.h index 959d7b63e0e5..589225080c24 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.h +++ b/drivers/gpu/drm/amd/amdgpu/si.h @@ -24,8 +24,6 @@ #ifndef __SI_H__ #define __SI_H__ -extern const struct amd_ip_funcs si_common_ip_funcs; - void si_srbm_select(struct amdgpu_device *adev, u32 me, u32 pipe, u32 queue, u32 vmid); int si_set_ip_blocks(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 7fece1fe4130..14265c5c349e 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -745,7 +745,7 @@ static int si_dma_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs si_dma_ip_funcs = { +static const struct amd_ip_funcs si_dma_ip_funcs = { .name = "si_dma", .early_init = si_dma_early_init, .late_init = NULL, @@ -903,3 +903,12 @@ static void si_dma_set_vm_pte_funcs(struct amdgpu_device *adev) adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances; } } + +const struct amdgpu_ip_block_version si_dma_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_dma_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.h b/drivers/gpu/drm/amd/amdgpu/si_dma.h index 3a3e0c78a54b..5ac1b8452fb4 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.h +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.h @@ -24,6 +24,6 @@ #ifndef __SI_DMA_H__ #define __SI_DMA_H__ -extern const struct amd_ip_funcs si_dma_ip_funcs; +extern const struct amdgpu_ip_block_version si_dma_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 38b4b9789584..6e6c7cee3332 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -8011,3 +8011,11 @@ static void si_dpm_set_irq_funcs(struct amdgpu_device *adev) adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs; } +const struct amdgpu_ip_block_version si_dpm_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &si_dpm_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c index 8fae3d4a2360..db0f36846661 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c @@ -268,7 +268,7 @@ static int si_ih_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs si_ih_ip_funcs = { +static const struct amd_ip_funcs si_ih_ip_funcs = { .name = "si_ih", .early_init = si_ih_early_init, .late_init = NULL, @@ -297,3 +297,11 @@ static void si_ih_set_interrupt_funcs(struct amdgpu_device *adev) adev->irq.ih_funcs = &si_ih_funcs; } +const struct amdgpu_ip_block_version si_ih_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_ih_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.h b/drivers/gpu/drm/amd/amdgpu/si_ih.h index f3e3a954369c..42e64a53e24f 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_ih.h +++ b/drivers/gpu/drm/amd/amdgpu/si_ih.h @@ -24,6 +24,6 @@ #ifndef __SI_IH_H__ #define __SI_IH_H__ -extern const struct amd_ip_funcs si_ih_ip_funcs; +extern const struct amdgpu_ip_block_version si_ih_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index b4ea229bb449..52b71ee58793 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -455,7 +455,7 @@ static int tonga_ih_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs tonga_ih_ip_funcs = { +static const struct amd_ip_funcs tonga_ih_ip_funcs = { .name = "tonga_ih", .early_init = tonga_ih_early_init, .late_init = NULL, @@ -487,3 +487,11 @@ static void tonga_ih_set_interrupt_funcs(struct amdgpu_device *adev) adev->irq.ih_funcs = &tonga_ih_funcs; } +const struct amdgpu_ip_block_version tonga_ih_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 3, + .minor = 0, + .rev = 0, + .funcs = &tonga_ih_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.h b/drivers/gpu/drm/amd/amdgpu/tonga_ih.h index 7392d70fa4a7..499027eee5c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.h +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.h @@ -24,6 +24,6 @@ #ifndef __TONGA_IH_H__ #define __TONGA_IH_H__ -extern const struct amd_ip_funcs tonga_ih_ip_funcs; +extern const struct amdgpu_ip_block_version tonga_ih_ip_block; -#endif /* __CZ_IH_H__ */ +#endif /* __TONGA_IH_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 1bab75afba5d..3c2dce67b5f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -723,7 +723,7 @@ static int uvd_v4_2_set_powergating_state(void *handle, } } -const struct amd_ip_funcs uvd_v4_2_ip_funcs = { +static const struct amd_ip_funcs uvd_v4_2_ip_funcs = { .name = "uvd_v4_2", .early_init = uvd_v4_2_early_init, .late_init = NULL, @@ -780,3 +780,12 @@ static void uvd_v4_2_set_irq_funcs(struct amdgpu_device *adev) adev->uvd.irq.num_types = 1; adev->uvd.irq.funcs = &uvd_v4_2_irq_funcs; } + +const struct amdgpu_ip_block_version uvd_v4_2_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_UVD, + .major = 4, + .minor = 2, + .rev = 0, + .funcs = &uvd_v4_2_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h index 0a615dd50840..8a0444bb8b95 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h @@ -24,6 +24,6 @@ #ifndef __UVD_V4_2_H__ #define __UVD_V4_2_H__ -extern const struct amd_ip_funcs uvd_v4_2_ip_funcs; +extern const struct amdgpu_ip_block_version uvd_v4_2_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index ec848fc57f70..05088ec4c41b 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -774,7 +774,7 @@ static int uvd_v5_0_set_powergating_state(void *handle, } } -const struct amd_ip_funcs uvd_v5_0_ip_funcs = { +static const struct amd_ip_funcs uvd_v5_0_ip_funcs = { .name = "uvd_v5_0", .early_init = uvd_v5_0_early_init, .late_init = NULL, @@ -831,3 +831,12 @@ static void uvd_v5_0_set_irq_funcs(struct amdgpu_device *adev) adev->uvd.irq.num_types = 1; adev->uvd.irq.funcs = &uvd_v5_0_irq_funcs; } + +const struct amdgpu_ip_block_version uvd_v5_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_UVD, + .major = 5, + .minor = 0, + .rev = 0, + .funcs = &uvd_v5_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h index e3b3c49fa5de..2eaaea793ac5 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h @@ -24,6 +24,6 @@ #ifndef __UVD_V5_0_H__ #define __UVD_V5_0_H__ -extern const struct amd_ip_funcs uvd_v5_0_ip_funcs; +extern const struct amdgpu_ip_block_version uvd_v5_0_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index be912933b073..2e2baa614b28 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -1001,7 +1001,7 @@ static int uvd_v6_0_set_powergating_state(void *handle, } } -const struct amd_ip_funcs uvd_v6_0_ip_funcs = { +static const struct amd_ip_funcs uvd_v6_0_ip_funcs = { .name = "uvd_v6_0", .early_init = uvd_v6_0_early_init, .late_init = NULL, @@ -1096,3 +1096,30 @@ static void uvd_v6_0_set_irq_funcs(struct amdgpu_device *adev) adev->uvd.irq.num_types = 1; adev->uvd.irq.funcs = &uvd_v6_0_irq_funcs; } + +const struct amdgpu_ip_block_version uvd_v6_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_UVD, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &uvd_v6_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version uvd_v6_2_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_UVD, + .major = 6, + .minor = 2, + .rev = 0, + .funcs = &uvd_v6_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version uvd_v6_3_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_UVD, + .major = 6, + .minor = 3, + .rev = 0, + .funcs = &uvd_v6_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h index 6b92a2352986..d3d48c6428cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h @@ -24,6 +24,8 @@ #ifndef __UVD_V6_0_H__ #define __UVD_V6_0_H__ -extern const struct amd_ip_funcs uvd_v6_0_ip_funcs; +extern const struct amdgpu_ip_block_version uvd_v6_0_ip_block; +extern const struct amdgpu_ip_block_version uvd_v6_2_ip_block; +extern const struct amdgpu_ip_block_version uvd_v6_3_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index d58583983b11..38ed903dd6f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -592,7 +592,7 @@ static int vce_v2_0_set_powergating_state(void *handle, return vce_v2_0_start(adev); } -const struct amd_ip_funcs vce_v2_0_ip_funcs = { +static const struct amd_ip_funcs vce_v2_0_ip_funcs = { .name = "vce_v2_0", .early_init = vce_v2_0_early_init, .late_init = NULL, @@ -647,3 +647,12 @@ static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev) adev->vce.irq.num_types = 1; adev->vce.irq.funcs = &vce_v2_0_irq_funcs; }; + +const struct amdgpu_ip_block_version vce_v2_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_VCE, + .major = 2, + .minor = 0, + .rev = 0, + .funcs = &vce_v2_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h index 0d2ae8a01acd..4d15167654a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h @@ -24,6 +24,6 @@ #ifndef __VCE_V2_0_H__ #define __VCE_V2_0_H__ -extern const struct amd_ip_funcs vce_v2_0_ip_funcs; +extern const struct amdgpu_ip_block_version vce_v2_0_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 589fff19aa78..3f899e3326d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -807,7 +807,7 @@ static void vce_v3_0_emit_pipeline_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, seq); } -const struct amd_ip_funcs vce_v3_0_ip_funcs = { +static const struct amd_ip_funcs vce_v3_0_ip_funcs = { .name = "vce_v3_0", .early_init = vce_v3_0_early_init, .late_init = NULL, @@ -898,3 +898,30 @@ static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev) adev->vce.irq.num_types = 1; adev->vce.irq.funcs = &vce_v3_0_irq_funcs; }; + +const struct amdgpu_ip_block_version vce_v3_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_VCE, + .major = 3, + .minor = 0, + .rev = 0, + .funcs = &vce_v3_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version vce_v3_1_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_VCE, + .major = 3, + .minor = 1, + .rev = 0, + .funcs = &vce_v3_0_ip_funcs, +}; + +const struct amdgpu_ip_block_version vce_v3_4_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_VCE, + .major = 3, + .minor = 4, + .rev = 0, + .funcs = &vce_v3_0_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h index b45af65da81f..08b908c7de0f 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h @@ -24,6 +24,8 @@ #ifndef __VCE_V3_0_H__ #define __VCE_V3_0_H__ -extern const struct amd_ip_funcs vce_v3_0_ip_funcs; +extern const struct amdgpu_ip_block_version vce_v3_0_ip_block; +extern const struct amdgpu_ip_block_version vce_v3_1_ip_block; +extern const struct amdgpu_ip_block_version vce_v3_4_ip_block; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 82f72cd1aebe..e33399cd1376 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -858,734 +858,6 @@ static void vi_enable_doorbell_aperture(struct amdgpu_device *adev, WREG32(mmBIF_DOORBELL_APER_EN, tmp); } -/* topaz has no DCE, UVD, VCE */ -static const struct amdgpu_ip_block_version topaz_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 4, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 4, - .rev = 0, - .funcs = &iceland_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 1, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 4, - .rev = 0, - .funcs = &sdma_v2_4_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version topaz_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 7, - .minor = 4, - .rev = 0, - .funcs = &gmc_v7_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 2, - .minor = 4, - .rev = 0, - .funcs = &iceland_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 1, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 2, - .minor = 4, - .rev = 0, - .funcs = &sdma_v2_4_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version tonga_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &tonga_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 1, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 10, - .minor = 0, - .rev = 0, - .funcs = &dce_v10_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &sdma_v3_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 5, - .minor = 0, - .rev = 0, - .funcs = &uvd_v5_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &vce_v3_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version tonga_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &tonga_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 1, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 10, - .minor = 0, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &sdma_v3_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 5, - .minor = 0, - .rev = 0, - .funcs = &uvd_v5_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &vce_v3_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version fiji_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 5, - .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &tonga_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 1, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 10, - .minor = 1, - .rev = 0, - .funcs = &dce_v10_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &sdma_v3_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &uvd_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &vce_v3_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version fiji_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 5, - .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &tonga_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 1, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 10, - .minor = 1, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &sdma_v3_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &uvd_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &vce_v3_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version polaris11_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 1, - .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 3, - .minor = 1, - .rev = 0, - .funcs = &tonga_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 2, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 11, - .minor = 2, - .rev = 0, - .funcs = &dce_v11_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 3, - .minor = 1, - .rev = 0, - .funcs = &sdma_v3_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 6, - .minor = 3, - .rev = 0, - .funcs = &uvd_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 3, - .minor = 4, - .rev = 0, - .funcs = &vce_v3_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version polaris11_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 1, - .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 3, - .minor = 1, - .rev = 0, - .funcs = &tonga_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 2, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 11, - .minor = 2, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 3, - .minor = 1, - .rev = 0, - .funcs = &sdma_v3_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 6, - .minor = 3, - .rev = 0, - .funcs = &uvd_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 3, - .minor = 4, - .rev = 0, - .funcs = &vce_v3_0_ip_funcs, - }, -}; - -static const struct amdgpu_ip_block_version cz_ip_blocks[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &cz_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 11, - .minor = 0, - .rev = 0, - .funcs = &dce_v11_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &sdma_v3_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &uvd_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &vce_v3_0_ip_funcs, - }, -#if defined(CONFIG_DRM_AMD_ACP) - { - .type = AMD_IP_BLOCK_TYPE_ACP, - .major = 2, - .minor = 2, - .rev = 0, - .funcs = &acp_ip_funcs, - }, -#endif -}; - -static const struct amdgpu_ip_block_version cz_ip_blocks_vd[] = -{ - /* ORDER MATTERS! */ - { - .type = AMD_IP_BLOCK_TYPE_COMMON, - .major = 2, - .minor = 0, - .rev = 0, - .funcs = &vi_common_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_IH, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &cz_ih_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &amdgpu_pp_ip_funcs - }, - { - .type = AMD_IP_BLOCK_TYPE_DCE, - .major = 11, - .minor = 0, - .rev = 0, - .funcs = &dce_virtual_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_GFX, - .major = 8, - .minor = 0, - .rev = 0, - .funcs = &gfx_v8_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_SDMA, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &sdma_v3_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_UVD, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &uvd_v6_0_ip_funcs, - }, - { - .type = AMD_IP_BLOCK_TYPE_VCE, - .major = 3, - .minor = 0, - .rev = 0, - .funcs = &vce_v3_0_ip_funcs, - }, -#if defined(CONFIG_DRM_AMD_ACP) - { - .type = AMD_IP_BLOCK_TYPE_ACP, - .major = 2, - .minor = 2, - .rev = 0, - .funcs = &acp_ip_funcs, - }, -#endif -}; - -int vi_set_ip_blocks(struct amdgpu_device *adev) -{ - if (adev->enable_virtual_display) { - switch (adev->asic_type) { - case CHIP_TOPAZ: - adev->ip_blocks = topaz_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks_vd); - break; - case CHIP_FIJI: - adev->ip_blocks = fiji_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks_vd); - break; - case CHIP_TONGA: - adev->ip_blocks = tonga_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks_vd); - break; - case CHIP_POLARIS11: - case CHIP_POLARIS10: - adev->ip_blocks = polaris11_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(polaris11_ip_blocks_vd); - break; - - case CHIP_CARRIZO: - case CHIP_STONEY: - adev->ip_blocks = cz_ip_blocks_vd; - adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks_vd); - break; - default: - /* FIXME: not supported yet */ - return -EINVAL; - } - } else { - switch (adev->asic_type) { - case CHIP_TOPAZ: - adev->ip_blocks = topaz_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks); - break; - case CHIP_FIJI: - adev->ip_blocks = fiji_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks); - break; - case CHIP_TONGA: - adev->ip_blocks = tonga_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks); - break; - case CHIP_POLARIS11: - case CHIP_POLARIS10: - adev->ip_blocks = polaris11_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(polaris11_ip_blocks); - break; - case CHIP_CARRIZO: - case CHIP_STONEY: - adev->ip_blocks = cz_ip_blocks; - adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks); - break; - default: - /* FIXME: not supported yet */ - return -EINVAL; - } - } - - return 0; -} - #define ATI_REV_ID_FUSE_MACRO__ADDRESS 0xC0014044 #define ATI_REV_ID_FUSE_MACRO__SHIFT 9 #define ATI_REV_ID_FUSE_MACRO__MASK 0x00001E00 @@ -1985,7 +1257,7 @@ static int vi_common_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs vi_common_ip_funcs = { +static const struct amd_ip_funcs vi_common_ip_funcs = { .name = "vi_common", .early_init = vi_common_early_init, .late_init = NULL, @@ -2002,3 +1274,110 @@ const struct amd_ip_funcs vi_common_ip_funcs = { .set_powergating_state = vi_common_set_powergating_state, }; +static const struct amdgpu_ip_block_version vi_common_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_COMMON, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &vi_common_ip_funcs, +}; + +int vi_set_ip_blocks(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_TOPAZ: + /* topaz has no DCE, UVD, VCE */ + amdgpu_ip_block_add(adev, &vi_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v7_4_ip_block); + amdgpu_ip_block_add(adev, &iceland_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); + amdgpu_ip_block_add(adev, &sdma_v2_4_ip_block); + break; + case CHIP_FIJI: + amdgpu_ip_block_add(adev, &vi_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v8_5_ip_block); + amdgpu_ip_block_add(adev, &tonga_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v10_1_ip_block); + amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); + amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block); + amdgpu_ip_block_add(adev, &uvd_v6_0_ip_block); + amdgpu_ip_block_add(adev, &vce_v3_0_ip_block); + break; + case CHIP_TONGA: + amdgpu_ip_block_add(adev, &vi_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block); + amdgpu_ip_block_add(adev, &tonga_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v10_0_ip_block); + amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); + amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block); + amdgpu_ip_block_add(adev, &uvd_v5_0_ip_block); + amdgpu_ip_block_add(adev, &vce_v3_0_ip_block); + break; + case CHIP_POLARIS11: + case CHIP_POLARIS10: + amdgpu_ip_block_add(adev, &vi_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v8_1_ip_block); + amdgpu_ip_block_add(adev, &tonga_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v11_2_ip_block); + amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); + amdgpu_ip_block_add(adev, &sdma_v3_1_ip_block); + amdgpu_ip_block_add(adev, &uvd_v6_3_ip_block); + amdgpu_ip_block_add(adev, &vce_v3_4_ip_block); + break; + case CHIP_CARRIZO: + amdgpu_ip_block_add(adev, &vi_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block); + amdgpu_ip_block_add(adev, &cz_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v11_0_ip_block); + amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); + amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block); + amdgpu_ip_block_add(adev, &uvd_v6_0_ip_block); + amdgpu_ip_block_add(adev, &vce_v3_1_ip_block); +#if defined(CONFIG_DRM_AMD_ACP) + amdgpu_ip_block_add(adev, &acp_ip_block); +#endif + break; + case CHIP_STONEY: + amdgpu_ip_block_add(adev, &vi_common_ip_block); + amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block); + amdgpu_ip_block_add(adev, &cz_ih_ip_block); + amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); + if (adev->enable_virtual_display) + amdgpu_ip_block_add(adev, &dce_virtual_ip_block); + else + amdgpu_ip_block_add(adev, &dce_v11_0_ip_block); + amdgpu_ip_block_add(adev, &gfx_v8_1_ip_block); + amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block); + amdgpu_ip_block_add(adev, &uvd_v6_2_ip_block); + amdgpu_ip_block_add(adev, &vce_v3_4_ip_block); +#if defined(CONFIG_DRM_AMD_ACP) + amdgpu_ip_block_add(adev, &acp_ip_block); +#endif + break; + default: + /* FIXME: not supported yet */ + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/vi.h b/drivers/gpu/drm/amd/amdgpu/vi.h index 502094042462..575d7aed5d32 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.h +++ b/drivers/gpu/drm/amd/amdgpu/vi.h @@ -24,8 +24,6 @@ #ifndef __VI_H__ #define __VI_H__ -extern const struct amd_ip_funcs vi_common_ip_funcs; - void vi_srbm_select(struct amdgpu_device *adev, u32 me, u32 pipe, u32 queue, u32 vmid); int vi_set_ip_blocks(struct amdgpu_device *adev); -- cgit v1.2.3 From 273d7aa13c212964cbc725e637b07a13d1b765b4 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 11 Oct 2016 14:48:55 -0400 Subject: drm/amd/amdgpu: Add wave reader to debugfs Currently supports CZ/VI. Allows nearly atomic read of wave data from GPU. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 74 ++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 27a729c70c29..62c360435732 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2916,6 +2916,72 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, return !r ? 4 : r; } +static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t SQ_INDEX, uint32_t SQ_DATA, uint32_t simd, uint32_t wave, uint32_t address) +{ + WREG32(SQ_INDEX, (wave & 0xF) | ((simd & 0x3) << 4) | (address << 16) | (1 << 13)); + return RREG32(SQ_DATA); +} + +static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = f->f_inode->i_private; + int r, x; + ssize_t result=0; + uint32_t offset, se, sh, cu, wave, simd, data[16]; + + if (size & 3 || *pos & 3) + return -EINVAL; + + /* decode offset */ + offset = (*pos & 0x7F); + se = ((*pos >> 7) & 0xFF); + sh = ((*pos >> 15) & 0xFF); + cu = ((*pos >> 23) & 0xFF); + wave = ((*pos >> 31) & 0xFF); + simd = ((*pos >> 37) & 0xFF); + *pos &= 0x7F; + + /* switch to the specific se/sh/cu */ + mutex_lock(&adev->grbm_idx_mutex); + amdgpu_gfx_select_se_sh(adev, se, sh, cu); + + x = 0; + if (adev->family == AMDGPU_FAMILY_CZ || adev->family == AMDGPU_FAMILY_VI) { + /* type 0 wave data */ + data[x++] = 0; + data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x12); + data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x18); + data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x19); + data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x27E); + data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x27F); + data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x14); + data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x1A); + data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x1B); + } else { + return -EINVAL; + } + + amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); + mutex_unlock(&adev->grbm_idx_mutex); + + while (size && (*pos < x * 4)) { + uint32_t value; + + value = data[*pos >> 2]; + r = put_user(value, (uint32_t *)buf); + if (r) + return r; + + result += 4; + buf += 4; + *pos += 4; + size -= 4; + } + + return result; +} + static const struct file_operations amdgpu_debugfs_regs_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_regs_read, @@ -2953,6 +3019,12 @@ static const struct file_operations amdgpu_debugfs_sensors_fops = { .llseek = default_llseek }; +static const struct file_operations amdgpu_debugfs_wave_fops = { + .owner = THIS_MODULE, + .read = amdgpu_debugfs_wave_read, + .llseek = default_llseek +}; + static const struct file_operations *debugfs_regs[] = { &amdgpu_debugfs_regs_fops, &amdgpu_debugfs_regs_didt_fops, @@ -2960,6 +3032,7 @@ static const struct file_operations *debugfs_regs[] = { &amdgpu_debugfs_regs_smc_fops, &amdgpu_debugfs_gca_config_fops, &amdgpu_debugfs_sensors_fops, + &amdgpu_debugfs_wave_fops, }; static const char *debugfs_regs_names[] = { @@ -2969,6 +3042,7 @@ static const char *debugfs_regs_names[] = { "amdgpu_regs_smc", "amdgpu_gca_config", "amdgpu_sensors", + "amdgpu_wave", }; static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) -- cgit v1.2.3 From 5ecfb3b8fcb45b971a2f81a7a52d409a52b8b7d9 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 13 Oct 2016 12:15:03 -0400 Subject: drm/amd/amdgpu: Fix debugfs wave reader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On non VI/CZ platforms it would not free the grbm index lock. Reviewed-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Tom St Denis Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 62c360435732..188b8e0d7bca 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2958,13 +2958,14 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x14); data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x1A); data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x1B); - } else { - return -EINVAL; } amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); mutex_unlock(&adev->grbm_idx_mutex); + if (!x) + return -EINVAL; + while (size && (*pos < x * 4)) { uint32_t value; -- cgit v1.2.3 From 32977f93b4eb032f52d429a7c5ea657111d5df47 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Sun, 9 Oct 2016 07:41:26 -0400 Subject: drm/amd/amdgpu: Allow broadcast on debugfs read (v2) Allow any of the se/sh/instance fields to be specified as a broadcast by submitting 0x3FF. (v2) Fix broadcast range checking Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 188b8e0d7bca..822dfc205a2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2576,6 +2576,13 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, se_bank = (*pos >> 24) & 0x3FF; sh_bank = (*pos >> 34) & 0x3FF; instance_bank = (*pos >> 44) & 0x3FF; + + if (se_bank == 0x3FF) + se_bank = 0xFFFFFFFF; + if (sh_bank == 0x3FF) + sh_bank = 0xFFFFFFFF; + if (instance_bank == 0x3FF) + instance_bank = 0xFFFFFFFF; use_bank = 1; } else { use_bank = 0; @@ -2584,8 +2591,8 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, *pos &= 0x3FFFF; if (use_bank) { - if (sh_bank >= adev->gfx.config.max_sh_per_se || - se_bank >= adev->gfx.config.max_shader_engines) + if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || + (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) return -EINVAL; mutex_lock(&adev->grbm_idx_mutex); amdgpu_gfx_select_se_sh(adev, se_bank, -- cgit v1.2.3 From 394fdde256adb5bdbe5d410cf7bdc3d7cbb889f8 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Mon, 10 Oct 2016 07:31:23 -0400 Subject: drm/amd/amdgpu: Make debugfs write compliment read Add PG lock support as well as bank selection to the MMIO write function. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 822dfc205a2a..cd44364267f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2639,10 +2639,45 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, struct amdgpu_device *adev = f->f_inode->i_private; ssize_t result = 0; int r; + bool pm_pg_lock, use_bank; + unsigned instance_bank, sh_bank, se_bank; if (size & 0x3 || *pos & 0x3) return -EINVAL; + /* are we reading registers for which a PG lock is necessary? */ + pm_pg_lock = (*pos >> 23) & 1; + + if (*pos & (1ULL << 62)) { + se_bank = (*pos >> 24) & 0x3FF; + sh_bank = (*pos >> 34) & 0x3FF; + instance_bank = (*pos >> 44) & 0x3FF; + + if (se_bank == 0x3FF) + se_bank = 0xFFFFFFFF; + if (sh_bank == 0x3FF) + sh_bank = 0xFFFFFFFF; + if (instance_bank == 0x3FF) + instance_bank = 0xFFFFFFFF; + use_bank = 1; + } else { + use_bank = 0; + } + + *pos &= 0x3FFFF; + + if (use_bank) { + if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || + (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) + return -EINVAL; + mutex_lock(&adev->grbm_idx_mutex); + amdgpu_gfx_select_se_sh(adev, se_bank, + sh_bank, instance_bank); + } + + if (pm_pg_lock) + mutex_lock(&adev->pm.mutex); + while (size) { uint32_t value; @@ -2661,6 +2696,14 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, size -= 4; } + if (use_bank) { + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); + } + + if (pm_pg_lock) + mutex_unlock(&adev->pm.mutex); + return result; } -- cgit v1.2.3 From 472259f02657ef99cba2a64832ccadad8e3baabe Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 14 Oct 2016 09:49:09 -0400 Subject: drm/amd/amdgpu: re-factor debugfs wave reader Move IP version specific code into a callback. Also add support for gfx7 devices. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 29 ++++++----------------------- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 25 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 26 ++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 1800ea139c98..217df2459a98 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -840,6 +840,7 @@ struct amdgpu_gfx_funcs { /* get the gpu clock counter */ uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev); void (*select_se_sh)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance); + void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields); }; struct amdgpu_gfx { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index cd44364267f7..b0c7cb797300 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2966,19 +2966,13 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, return !r ? 4 : r; } -static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t SQ_INDEX, uint32_t SQ_DATA, uint32_t simd, uint32_t wave, uint32_t address) -{ - WREG32(SQ_INDEX, (wave & 0xF) | ((simd & 0x3) << 4) | (address << 16) | (1 << 13)); - return RREG32(SQ_DATA); -} - static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { struct amdgpu_device *adev = f->f_inode->i_private; int r, x; ssize_t result=0; - uint32_t offset, se, sh, cu, wave, simd, data[16]; + uint32_t offset, se, sh, cu, wave, simd, data[32]; if (size & 3 || *pos & 3) return -EINVAL; @@ -2990,25 +2984,14 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, cu = ((*pos >> 23) & 0xFF); wave = ((*pos >> 31) & 0xFF); simd = ((*pos >> 37) & 0xFF); - *pos &= 0x7F; /* switch to the specific se/sh/cu */ mutex_lock(&adev->grbm_idx_mutex); amdgpu_gfx_select_se_sh(adev, se, sh, cu); x = 0; - if (adev->family == AMDGPU_FAMILY_CZ || adev->family == AMDGPU_FAMILY_VI) { - /* type 0 wave data */ - data[x++] = 0; - data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x12); - data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x18); - data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x19); - data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x27E); - data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x27F); - data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x14); - data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x1A); - data[x++] = wave_read_ind(adev, 0x2378, 0x2379, simd, wave, 0x1B); - } + if (adev->gfx.funcs->read_wave_data) + adev->gfx.funcs->read_wave_data(adev, simd, wave, data, &x); amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); mutex_unlock(&adev->grbm_idx_mutex); @@ -3016,17 +2999,17 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, if (!x) return -EINVAL; - while (size && (*pos < x * 4)) { + while (size && (offset < x * 4)) { uint32_t value; - value = data[*pos >> 2]; + value = data[offset >> 2]; r = put_user(value, (uint32_t *)buf); if (r) return r; result += 4; buf += 4; - *pos += 4; + offset += 4; size -= 4; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index bc6ccd05010f..91176005eaff 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4357,9 +4357,34 @@ static void gfx_v7_0_ring_emit_gds_switch(struct amdgpu_ring *ring, amdgpu_ring_write(ring, (1 << (oa_size + oa_base)) - (1 << oa_base)); } +static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address) +{ + WREG32(mmSQ_IND_INDEX, (wave & 0xF) | ((simd & 0x3) << 4) | (address << 16) | (1 << 13)); + return RREG32(mmSQ_IND_DATA); +} + +static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields) +{ + /* type 0 wave data */ + dst[(*no_fields)++] = 0; + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS); +} + static const struct amdgpu_gfx_funcs gfx_v7_0_gfx_funcs = { .get_gpu_clock_counter = &gfx_v7_0_get_gpu_clock_counter, .select_se_sh = &gfx_v7_0_select_se_sh, + .read_wave_data = &gfx_v7_0_read_wave_data, }; static const struct amdgpu_rlc_funcs gfx_v7_0_rlc_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 27b3de44add7..eeb522c0de0b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5441,9 +5441,35 @@ static void gfx_v8_0_ring_emit_gds_switch(struct amdgpu_ring *ring, amdgpu_ring_write(ring, (1 << (oa_size + oa_base)) - (1 << oa_base)); } +static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address) +{ + WREG32(mmSQ_IND_INDEX, (wave & 0xF) | ((simd & 0x3) << 4) | (address << 16) | (1 << 13)); + return RREG32(mmSQ_IND_DATA); +} + +static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields) +{ + /* type 0 wave data */ + dst[(*no_fields)++] = 0; + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS); +} + + static const struct amdgpu_gfx_funcs gfx_v8_0_gfx_funcs = { .get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter, .select_se_sh = &gfx_v8_0_select_se_sh, + .read_wave_data = &gfx_v8_0_read_wave_data, }; static int gfx_v8_0_early_init(void *handle) -- cgit v1.2.3 From 74f3ce31e991c44cd7a0e989433b22704ea861d9 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 14 Oct 2016 10:50:46 -0400 Subject: drm/amd/amdgpu: Put in rest of wave fields Add the rest of the basic SQ WAVE fields to finish off the implementation. Eventually, a separate interface will be needed for GPRs. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 91176005eaff..903aa240e946 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4379,6 +4379,12 @@ static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC); dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS); dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_LO); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_HI); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_LO); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); } static const struct amdgpu_gfx_funcs gfx_v7_0_gfx_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index eeb522c0de0b..1c2544f314c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5463,6 +5463,12 @@ static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC); dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS); dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_LO); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_HI); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_LO); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); } -- cgit v1.2.3 From db82b67c5764c02ced886ca2c8c61a7b00b53075 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 12 Oct 2016 20:05:03 +0800 Subject: drm/amdgpu: check min clock set by DAL before set ps. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 885f08c3f496..68fe70eda5ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -960,6 +960,12 @@ static void ci_apply_state_adjust_rules(struct amdgpu_device *adev, sclk = ps->performance_levels[0].sclk; } + if (adev->pm.pm_display_cfg.min_core_set_clock > sclk) + sclk = adev->pm.pm_display_cfg.min_core_set_clock; + + if (adev->pm.pm_display_cfg.min_mem_set_clock > mclk) + mclk = adev->pm.pm_display_cfg.min_mem_set_clock; + if (rps->vce_active) { if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk) sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk; -- cgit v1.2.3 From fbebf2c6bc2ad746d1c124c35976868b2a41ac51 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 17 Oct 2016 13:49:27 +0800 Subject: drm/amdgpu: add new callback to check power state info Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 4f25c030148e..e5e0a9a1abaf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -271,6 +271,11 @@ struct amdgpu_dpm_funcs { int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value); int (*get_mclk_od)(struct amdgpu_device *adev); int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value); + int (*check_state_equal)(struct amdgpu_device *adev, + struct amdgpu_ps *cps, + struct amdgpu_ps *rps, + bool *equal); + struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx); }; @@ -374,6 +379,8 @@ struct amdgpu_dpm_funcs { #define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) +#define amgdpu_dpm_check_state_equal(adev, cps, rps, equal) (adev)->pm.funcs->check_state_equal((adev), (cps),(rps),(equal)) + #define amdgpu_dpm_get_vce_clock_state(adev, i) \ ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i)) : \ -- cgit v1.2.3 From 1d516c41d9b19e3c264c5da8c64e7f5d503e8268 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 14 Oct 2016 19:16:54 +0800 Subject: drm/amdgpu: add an implement for check_power_state equal for CI Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 68fe70eda5ad..2ca019bc7b93 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6100,6 +6100,56 @@ static void ci_dpm_print_power_state(struct amdgpu_device *adev, amdgpu_dpm_print_ps_status(adev, rps); } +static inline bool ci_are_power_levels_equal(const struct ci_pl *ci_cpl1, + const struct ci_pl *ci_cpl2) +{ + return ((ci_cpl1->mclk == ci_cpl2->mclk) && + (ci_cpl1->sclk == ci_cpl2->sclk) && + (ci_cpl1->pcie_gen == ci_cpl2->pcie_gen) && + (ci_cpl1->pcie_lane == ci_cpl2->pcie_lane)); +} + +static int ci_check_state_equal(struct amdgpu_device *adev, + struct amdgpu_ps *cps, + struct amdgpu_ps *rps, + bool *equal) +{ + struct ci_ps *ci_cps; + struct ci_ps *ci_rps; + int i; + + if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) + return -EINVAL; + + ci_cps = ci_get_ps(cps); + ci_rps = ci_get_ps(rps); + + if (ci_cps == NULL) { + *equal = false; + return 0; + } + + if (ci_cps->performance_level_count != ci_rps->performance_level_count) { + + *equal = false; + return 0; + } + + for (i = 0; i < ci_cps->performance_level_count; i++) { + if (!ci_are_power_levels_equal(&(ci_cps->performance_levels[i]), + &(ci_rps->performance_levels[i]))) { + *equal = false; + return 0; + } + } + + /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ + *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk)); + *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk)); + + return 0; +} + static u32 ci_dpm_get_sclk(struct amdgpu_device *adev, bool low) { struct ci_power_info *pi = ci_get_pi(adev); @@ -6650,6 +6700,7 @@ static const struct amdgpu_dpm_funcs ci_dpm_funcs = { .set_sclk_od = ci_dpm_set_sclk_od, .get_mclk_od = ci_dpm_get_mclk_od, .set_mclk_od = ci_dpm_set_mclk_od, + .check_state_equal = ci_check_state_equal, .get_vce_clock_state = amdgpu_get_vce_clock_state, }; -- cgit v1.2.3 From 73909a746a6636706e72287fb268103a9d8b5104 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 14 Oct 2016 19:30:08 +0800 Subject: drm/amdgpu: add an implement for check_power_state equal for Cz. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index ad2cc4be6737..adbb6e150acc 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -2257,6 +2257,18 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate) } } +static int cz_check_state_equal(struct amdgpu_device *adev, + struct amdgpu_ps *cps, + struct amdgpu_ps *rps, + bool *equal) +{ + if (equal == NULL) + return -EINVAL; + + *equal = false; + return 0; +} + const struct amd_ip_funcs cz_dpm_ip_funcs = { .name = "cz_dpm", .early_init = cz_dpm_early_init, @@ -2289,6 +2301,7 @@ static const struct amdgpu_dpm_funcs cz_dpm_funcs = { .vblank_too_short = NULL, .powergate_uvd = cz_dpm_powergate_uvd, .powergate_vce = cz_dpm_powergate_vce, + .check_state_equal = cz_check_state_equal, }; static void cz_dpm_set_funcs(struct amdgpu_device *adev) -- cgit v1.2.3 From 3411717501dce5896a024bd52039c44cd23f3792 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 14 Oct 2016 19:39:52 +0800 Subject: drm/amdgpu: add an implement for check_power_state equal for Si. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 6e6c7cee3332..62edc87f33f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -7957,6 +7957,57 @@ static int si_dpm_early_init(void *handle) return 0; } +static inline bool si_are_power_levels_equal(const struct rv7xx_pl *si_cpl1, + const struct rv7xx_pl *si_cpl2) +{ + return ((si_cpl1->mclk == si_cpl2->mclk) && + (si_cpl1->sclk == si_cpl2->sclk) && + (si_cpl1->pcie_gen == si_cpl2->pcie_gen) && + (si_cpl1->vddc == si_cpl2->vddc) && + (si_cpl1->vddci == si_cpl2->vddci)); +} + +static int si_check_state_equal(struct amdgpu_device *adev, + struct amdgpu_ps *cps, + struct amdgpu_ps *rps, + bool *equal) +{ + struct si_ps *si_cps; + struct si_ps *si_rps; + int i; + + if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) + return -EINVAL; + + si_cps = si_get_ps(cps); + si_rps = si_get_ps(rps); + + if (si_cps == NULL) { + printk("si_cps is NULL\n"); + *equal = false; + return 0; + } + + if (si_cps->performance_level_count != si_rps->performance_level_count) { + *equal = false; + return 0; + } + + for (i = 0; i < si_cps->performance_level_count; i++) { + if (!si_are_power_levels_equal(&(si_cps->performance_levels[i]), + &(si_rps->performance_levels[i]))) { + *equal = false; + return 0; + } + } + + /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ + *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk)); + *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk)); + + return 0; +} + const struct amd_ip_funcs si_dpm_ip_funcs = { .name = "si_dpm", @@ -7991,6 +8042,7 @@ static const struct amdgpu_dpm_funcs si_dpm_funcs = { .get_fan_control_mode = &si_dpm_get_fan_control_mode, .set_fan_speed_percent = &si_dpm_set_fan_speed_percent, .get_fan_speed_percent = &si_dpm_get_fan_speed_percent, + .check_state_equal = &si_check_state_equal, .get_vce_clock_state = amdgpu_get_vce_clock_state, }; -- cgit v1.2.3 From 6061789a455b15293422a92c0f3e85f4cd143619 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 24 Oct 2016 15:50:17 -0400 Subject: drm/amdgpu: add an implement for check_power_state equal for KV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KV/KB/ML was missed these was implemented for other asics. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index 42e5c9400f97..b6f2e50636a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -3243,6 +3243,18 @@ static int kv_dpm_set_powergating_state(void *handle, return 0; } +static int kv_check_state_equal(struct amdgpu_device *adev, + struct amdgpu_ps *cps, + struct amdgpu_ps *rps, + bool *equal) +{ + if (equal == NULL) + return -EINVAL; + + *equal = false; + return 0; +} + const struct amd_ip_funcs kv_dpm_ip_funcs = { .name = "kv_dpm", .early_init = kv_dpm_early_init, @@ -3274,6 +3286,7 @@ static const struct amdgpu_dpm_funcs kv_dpm_funcs = { .powergate_uvd = &kv_dpm_powergate_uvd, .enable_bapm = &kv_dpm_enable_bapm, .get_vce_clock_state = amdgpu_get_vce_clock_state, + .check_state_equal = kv_check_state_equal, }; static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev) -- cgit v1.2.3 From 8c8e2c30d2da29f67156e2a3f5087b758552f86d Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 14 Oct 2016 19:29:02 +0800 Subject: drm/amdgpu: update current ps/requeset ps in adev with real ps. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 2 ++ drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 2ca019bc7b93..6ecfc4885b84 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -5225,6 +5225,7 @@ static void ci_update_current_ps(struct amdgpu_device *adev, pi->current_rps = *rps; pi->current_ps = *new_ps; pi->current_rps.ps_priv = &pi->current_ps; + adev->pm.dpm.current_ps = &pi->current_rps; } static void ci_update_requested_ps(struct amdgpu_device *adev, @@ -5236,6 +5237,7 @@ static void ci_update_requested_ps(struct amdgpu_device *adev, pi->requested_rps = *rps; pi->requested_ps = *new_ps; pi->requested_rps.ps_priv = &pi->requested_ps; + adev->pm.dpm.requested_ps = &pi->requested_rps; } static int ci_dpm_pre_set_power_state(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index adbb6e150acc..352b5fad5a06 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -1250,7 +1250,8 @@ static void cz_update_current_ps(struct amdgpu_device *adev, pi->current_ps = *ps; pi->current_rps = *rps; - pi->current_rps.ps_priv = ps; + pi->current_rps.ps_priv = &pi->current_ps; + adev->pm.dpm.current_ps = &pi->current_rps; } @@ -1262,7 +1263,8 @@ static void cz_update_requested_ps(struct amdgpu_device *adev, pi->requested_ps = *ps; pi->requested_rps = *rps; - pi->requested_rps.ps_priv = ps; + pi->requested_rps.ps_priv = &pi->requested_ps; + adev->pm.dpm.requested_ps = &pi->requested_rps; } diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 62edc87f33f6..917213396787 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -3171,6 +3171,7 @@ static void ni_update_current_ps(struct amdgpu_device *adev, eg_pi->current_rps = *rps; ni_pi->current_ps = *new_ps; eg_pi->current_rps.ps_priv = &ni_pi->current_ps; + adev->pm.dpm.current_ps = &eg_pi->current_rps; } static void ni_update_requested_ps(struct amdgpu_device *adev, @@ -3183,6 +3184,7 @@ static void ni_update_requested_ps(struct amdgpu_device *adev, eg_pi->requested_rps = *rps; ni_pi->requested_ps = *new_ps; eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps; + adev->pm.dpm.requested_ps = &eg_pi->requested_rps; } static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev, -- cgit v1.2.3 From 5e876c62d85a93381140f5e37bfabfb9a5a3345d Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 14 Oct 2016 19:23:34 +0800 Subject: drm/amdgpu: refine set power state logic for dpm. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 80 +++++++--------------------------- 1 file changed, 15 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 4656ad697154..274f3309aec9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -986,10 +986,10 @@ restart_search: static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) { - int i; struct amdgpu_ps *ps; enum amd_pm_state_type dpm_state; int ret; + bool equal; /* if dpm init failed */ if (!adev->pm.dpm_enabled) @@ -1009,46 +1009,6 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) else return; - /* no need to reprogram if nothing changed unless we are on BTC+ */ - if (adev->pm.dpm.current_ps == adev->pm.dpm.requested_ps) { - /* vce just modifies an existing state so force a change */ - if (ps->vce_active != adev->pm.dpm.vce_active) - goto force; - if (adev->flags & AMD_IS_APU) { - /* for APUs if the num crtcs changed but state is the same, - * all we need to do is update the display configuration. - */ - if (adev->pm.dpm.new_active_crtcs != adev->pm.dpm.current_active_crtcs) { - /* update display watermarks based on new power state */ - amdgpu_display_bandwidth_update(adev); - /* update displays */ - amdgpu_dpm_display_configuration_changed(adev); - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; - adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - } - return; - } else { - /* for BTC+ if the num crtcs hasn't changed and state is the same, - * nothing to do, if the num crtcs is > 1 and state is the same, - * update display configuration. - */ - if (adev->pm.dpm.new_active_crtcs == - adev->pm.dpm.current_active_crtcs) { - return; - } else if ((adev->pm.dpm.current_active_crtc_count > 1) && - (adev->pm.dpm.new_active_crtc_count > 1)) { - /* update display watermarks based on new power state */ - amdgpu_display_bandwidth_update(adev); - /* update displays */ - amdgpu_dpm_display_configuration_changed(adev); - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; - adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - return; - } - } - } - -force: if (amdgpu_dpm == 1) { printk("switching from power state:\n"); amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); @@ -1059,31 +1019,21 @@ force: /* update whether vce is active */ ps->vce_active = adev->pm.dpm.vce_active; + amdgpu_dpm_display_configuration_changed(adev); + ret = amdgpu_dpm_pre_set_power_state(adev); if (ret) return; - /* update display watermarks based on new power state */ - amdgpu_display_bandwidth_update(adev); + if ((0 != amgdpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal))) + equal = false; - /* wait for the rings to drain */ - for (i = 0; i < AMDGPU_MAX_RINGS; i++) { - struct amdgpu_ring *ring = adev->rings[i]; - if (ring && ring->ready) - amdgpu_fence_wait_empty(ring); - } + if (equal) + return; - /* program the new power state */ amdgpu_dpm_set_power_state(adev); - - /* update current power state */ - adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps; - amdgpu_dpm_post_set_power_state(adev); - /* update displays */ - amdgpu_dpm_display_configuration_changed(adev); - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; @@ -1276,20 +1226,20 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) struct drm_device *ddev = adev->ddev; struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; + int i = 0; if (!adev->pm.dpm_enabled) return; - if (adev->pp_enabled) { - int i = 0; + amdgpu_display_bandwidth_update(adev); - amdgpu_display_bandwidth_update(adev); - for (i = 0; i < AMDGPU_MAX_RINGS; i++) { - struct amdgpu_ring *ring = adev->rings[i]; - if (ring && ring->ready) - amdgpu_fence_wait_empty(ring); - } + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { + struct amdgpu_ring *ring = adev->rings[i]; + if (ring && ring->ready) + amdgpu_fence_wait_empty(ring); + } + if (adev->pp_enabled) { amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL); } else { mutex_lock(&adev->pm.mutex); -- cgit v1.2.3 From 45088efc8529de969de91dcefb6284f8d7837cd6 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 5 Oct 2016 16:49:19 +0200 Subject: drm/amdgpu: improve parse_cs handling a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we can use parse_cs and still keep VM mode enabled. Signed-off-by: Christian König Reviewed-and-Tested by: Leo Liu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 9 +++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 04b7aaf770e4..cf03f9f01f40 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -822,13 +822,14 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, /* Only for UVD/VCE VM emulation */ if (ring->funcs->parse_cs) { - p->job->vm = NULL; for (i = 0; i < p->job->num_ibs; i++) { r = amdgpu_ring_parse_cs(ring, p, i); if (r) return r; } - } else { + } + + if (p->job->vm) { p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->page_directory); r = amdgpu_bo_vm_update_pte(p, vm); @@ -917,7 +918,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, offset = ((uint64_t)m->it.start) * AMDGPU_GPU_PAGE_SIZE; kptr += chunk_ib->va_start - offset; - r = amdgpu_ib_get(adev, NULL, chunk_ib->ib_bytes, ib); + r = amdgpu_ib_get(adev, vm, chunk_ib->ib_bytes, ib); if (r) { DRM_ERROR("Failed to get ib !\n"); return r; @@ -932,9 +933,9 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, return r; } - ib->gpu_addr = chunk_ib->va_start; } + ib->gpu_addr = chunk_ib->va_start; ib->length_dw = chunk_ib->ib_bytes / 4; ib->flags = chunk_ib->flags; j++; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index d67eadaa91a3..1b54cc218b47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -876,6 +876,9 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx) struct amdgpu_ib *ib = &parser->job->ibs[ib_idx]; int r; + parser->job->vm = NULL; + ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); + if (ib->length_dw % 16) { DRM_ERROR("UVD IB length (%d) not 16 dwords aligned!\n", ib->length_dw); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 2fb469aa850a..05a1ea998fd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -642,6 +642,9 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) uint32_t *size = &tmp; int i, r, idx = 0; + p->job->vm = NULL; + ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); + r = amdgpu_cs_sysvm_access_required(p); if (r) return r; -- cgit v1.2.3 From 986147018171dc5eecf263d06920e043f7aca27d Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 10 Oct 2016 15:23:32 +0200 Subject: drm/amdgpu: add VCE VM session tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the problems with killing VCE sessions in VM mode. Signed-off-by: Christian König Reviewed-and-Tested by: Leo Liu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 90 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h | 1 + drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 1 + 3 files changed, 92 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 05a1ea998fd6..3d6f86cd028f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -791,6 +791,96 @@ out: return r; } +/** + * amdgpu_vce_cs_parse_vm - parse the command stream in VM mode + * + * @p: parser context + * + */ +int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx) +{ + struct amdgpu_ib *ib = &p->job->ibs[ib_idx]; + int session_idx = -1; + uint32_t destroyed = 0; + uint32_t created = 0; + uint32_t allocated = 0; + uint32_t tmp, handle = 0; + int i, r = 0, idx = 0; + + while (idx < ib->length_dw) { + uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); + uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); + + if ((len < 8) || (len & 3)) { + DRM_ERROR("invalid VCE command length (%d)!\n", len); + r = -EINVAL; + goto out; + } + + switch (cmd) { + case 0x00000001: /* session */ + handle = amdgpu_get_ib_value(p, ib_idx, idx + 2); + session_idx = amdgpu_vce_validate_handle(p, handle, + &allocated); + if (session_idx < 0) { + r = session_idx; + goto out; + } + break; + + case 0x01000001: /* create */ + created |= 1 << session_idx; + if (destroyed & (1 << session_idx)) { + destroyed &= ~(1 << session_idx); + allocated |= 1 << session_idx; + + } else if (!(allocated & (1 << session_idx))) { + DRM_ERROR("Handle already in use!\n"); + r = -EINVAL; + goto out; + } + + break; + + case 0x02000001: /* destroy */ + destroyed |= 1 << session_idx; + break; + + default: + break; + } + + if (session_idx == -1) { + DRM_ERROR("no session command at start of IB\n"); + r = -EINVAL; + goto out; + } + + idx += len / 4; + } + + if (allocated & ~created) { + DRM_ERROR("New session without create command!\n"); + r = -ENOENT; + } + +out: + if (!r) { + /* No error, free all destroyed handle slots */ + tmp = destroyed; + amdgpu_ib_free(p->adev, ib, NULL); + } else { + /* Error during parsing, free all allocated handle slots */ + tmp = allocated; + } + + for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) + if (tmp & (1 << i)) + atomic_set(&p->adev->vce.handles[i], 0); + + return r; +} + /** * amdgpu_vce_ring_emit_ib - execute indirect buffer * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h index 12729d2852df..44d49b576513 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h @@ -34,6 +34,7 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, bool direct, struct fence **fence); void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp); int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx); +int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx); void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib, unsigned vm_id, bool ctx_switch); void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 3f899e3326d3..5ed2930a8568 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -856,6 +856,7 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { .get_rptr = vce_v3_0_ring_get_rptr, .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, + .parse_cs = amdgpu_vce_ring_parse_cs_vm, .emit_frame_size = 6 + /* vce_v3_0_emit_vm_flush */ 4 + /* vce_v3_0_emit_pipeline_sync */ -- cgit v1.2.3 From a76ed485c57e37d22c7f47eb63120b3618930297 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 21 Oct 2016 15:30:36 -0400 Subject: drm/amdgpu: use amdgpu_bo_[create|free]_kernel for wb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than open coding it. Acked-by: Edward O'Callaghan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 37 ++++++------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b0c7cb797300..3b9b58debabd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -443,13 +443,9 @@ void amdgpu_doorbell_get_kfd_info(struct amdgpu_device *adev, static void amdgpu_wb_fini(struct amdgpu_device *adev) { if (adev->wb.wb_obj) { - if (!amdgpu_bo_reserve(adev->wb.wb_obj, false)) { - amdgpu_bo_kunmap(adev->wb.wb_obj); - amdgpu_bo_unpin(adev->wb.wb_obj); - amdgpu_bo_unreserve(adev->wb.wb_obj); - } - amdgpu_bo_unref(&adev->wb.wb_obj); - adev->wb.wb = NULL; + amdgpu_bo_free_kernel(&adev->wb.wb_obj, + &adev->wb.gpu_addr, + (void **)&adev->wb.wb); adev->wb.wb_obj = NULL; } } @@ -468,33 +464,14 @@ static int amdgpu_wb_init(struct amdgpu_device *adev) int r; if (adev->wb.wb_obj == NULL) { - r = amdgpu_bo_create(adev, AMDGPU_MAX_WB * 4, PAGE_SIZE, true, - AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, - &adev->wb.wb_obj); + r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * 4, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, + &adev->wb.wb_obj, &adev->wb.gpu_addr, + (void **)&adev->wb.wb); if (r) { dev_warn(adev->dev, "(%d) create WB bo failed\n", r); return r; } - r = amdgpu_bo_reserve(adev->wb.wb_obj, false); - if (unlikely(r != 0)) { - amdgpu_wb_fini(adev); - return r; - } - r = amdgpu_bo_pin(adev->wb.wb_obj, AMDGPU_GEM_DOMAIN_GTT, - &adev->wb.gpu_addr); - if (r) { - amdgpu_bo_unreserve(adev->wb.wb_obj); - dev_warn(adev->dev, "(%d) pin WB bo failed\n", r); - amdgpu_wb_fini(adev); - return r; - } - r = amdgpu_bo_kmap(adev->wb.wb_obj, (void **)&adev->wb.wb); - amdgpu_bo_unreserve(adev->wb.wb_obj); - if (r) { - dev_warn(adev->dev, "(%d) map WB bo failed\n", r); - amdgpu_wb_fini(adev); - return r; - } adev->wb.num_wb = AMDGPU_MAX_WB; memset(&adev->wb.used, 0, sizeof(adev->wb.used)); -- cgit v1.2.3 From 72a57438d1b4a17dc2f3743fcbb8f0b473a63373 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 21 Oct 2016 15:45:22 -0400 Subject: drm/amdgpu: consolidate atom scratch reg handling for hangs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move from asic specific code to common atom code. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 13 +++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 2 ++ drivers/gpu/drm/amd/amdgpu/cik.c | 17 +++-------------- drivers/gpu/drm/amd/amdgpu/vi.c | 16 ++-------------- 4 files changed, 20 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 8e6bf548d689..76cbb1d08bce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1784,6 +1784,19 @@ void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev) WREG32(mmBIOS_SCRATCH_0 + i, adev->bios_scratch[i]); } +void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev, + bool hung) +{ + u32 tmp = RREG32(mmBIOS_SCRATCH_3); + + if (hung) + tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; + else + tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; + + WREG32(mmBIOS_SCRATCH_3, tmp); +} + /* Atom needs data in little endian format * so swap as appropriate when copying data to * or from atom. Note that atom operates on diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h index 17356151db38..e4afb1652fde 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h @@ -206,6 +206,8 @@ void amdgpu_atombios_scratch_regs_lock(struct amdgpu_device *adev, bool lock); void amdgpu_atombios_scratch_regs_init(struct amdgpu_device *adev); void amdgpu_atombios_scratch_regs_save(struct amdgpu_device *adev); void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev); +void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev, + bool hung); void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 1b70f8fa4280..302df85893ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1189,18 +1189,6 @@ static int cik_gpu_pci_config_reset(struct amdgpu_device *adev) return r; } -static void cik_set_bios_scratch_engine_hung(struct amdgpu_device *adev, bool hung) -{ - u32 tmp = RREG32(mmBIOS_SCRATCH_3); - - if (hung) - tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; - else - tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; - - WREG32(mmBIOS_SCRATCH_3, tmp); -} - /** * cik_asic_reset - soft reset GPU * @@ -1213,11 +1201,12 @@ static void cik_set_bios_scratch_engine_hung(struct amdgpu_device *adev, bool hu static int cik_asic_reset(struct amdgpu_device *adev) { int r; - cik_set_bios_scratch_engine_hung(adev, true); + + amdgpu_atombios_scratch_regs_engine_hung(adev, true); r = cik_gpu_pci_config_reset(adev); - cik_set_bios_scratch_engine_hung(adev, false); + amdgpu_atombios_scratch_regs_engine_hung(adev, false); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index e33399cd1376..25c0a71b257d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -729,18 +729,6 @@ static int vi_gpu_pci_config_reset(struct amdgpu_device *adev) return -EINVAL; } -static void vi_set_bios_scratch_engine_hung(struct amdgpu_device *adev, bool hung) -{ - u32 tmp = RREG32(mmBIOS_SCRATCH_3); - - if (hung) - tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; - else - tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; - - WREG32(mmBIOS_SCRATCH_3, tmp); -} - /** * vi_asic_reset - soft reset GPU * @@ -754,11 +742,11 @@ static int vi_asic_reset(struct amdgpu_device *adev) { int r; - vi_set_bios_scratch_engine_hung(adev, true); + amdgpu_atombios_scratch_regs_engine_hung(adev, true); r = vi_gpu_pci_config_reset(adev); - vi_set_bios_scratch_engine_hung(adev, false); + amdgpu_atombios_scratch_regs_engine_hung(adev, false); return r; } -- cgit v1.2.3 From f1e68a7cf582b41d6da1dd15b9f0bfb9057c1164 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 21 Oct 2016 15:54:18 -0400 Subject: drm/amdgpu/atom: remove a bunch of unused functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Leftovers from the radeon. Reviewed-by: Edward O'Callaghan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 82 ---------------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 10 ---- 2 files changed, 92 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 76cbb1d08bce..56a86dd5789e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1115,49 +1115,6 @@ int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev, return 0; } -uint32_t amdgpu_atombios_get_engine_clock(struct amdgpu_device *adev) -{ - GET_ENGINE_CLOCK_PS_ALLOCATION args; - int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock); - - amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); - return le32_to_cpu(args.ulReturnEngineClock); -} - -uint32_t amdgpu_atombios_get_memory_clock(struct amdgpu_device *adev) -{ - GET_MEMORY_CLOCK_PS_ALLOCATION args; - int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock); - - amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); - return le32_to_cpu(args.ulReturnMemoryClock); -} - -void amdgpu_atombios_set_engine_clock(struct amdgpu_device *adev, - uint32_t eng_clock) -{ - SET_ENGINE_CLOCK_PS_ALLOCATION args; - int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock); - - args.ulTargetEngineClock = cpu_to_le32(eng_clock); /* 10 khz */ - - amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); -} - -void amdgpu_atombios_set_memory_clock(struct amdgpu_device *adev, - uint32_t mem_clock) -{ - SET_MEMORY_CLOCK_PS_ALLOCATION args; - int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock); - - if (adev->flags & AMD_IS_APU) - return; - - args.ulTargetMemoryClock = cpu_to_le32(mem_clock); /* 10 khz */ - - amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); -} - void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev, u32 eng_clock, u32 mem_clock) { @@ -1256,45 +1213,6 @@ int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device * return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage); } -void amdgpu_atombios_set_voltage(struct amdgpu_device *adev, - u16 voltage_level, - u8 voltage_type) -{ - union set_voltage args; - int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); - u8 frev, crev, volt_index = voltage_level; - - if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev)) - return; - - /* 0xff01 is a flag rather then an actual voltage */ - if (voltage_level == 0xff01) - return; - - switch (crev) { - case 1: - args.v1.ucVoltageType = voltage_type; - args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE; - args.v1.ucVoltageIndex = volt_index; - break; - case 2: - args.v2.ucVoltageType = voltage_type; - args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE; - args.v2.usVoltageLevel = cpu_to_le16(voltage_level); - break; - case 3: - args.v3.ucVoltageType = voltage_type; - args.v3.ucVoltageMode = ATOM_SET_VOLTAGE; - args.v3.usVoltageLevel = cpu_to_le16(voltage_level); - break; - default: - DRM_ERROR("Unknown table version %d, %d\n", frev, crev); - return; - } - - amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); -} - int amdgpu_atombios_get_leakage_id_from_vbios(struct amdgpu_device *adev, u16 *leakage_id) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h index e4afb1652fde..70e9acef5d9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h @@ -163,16 +163,6 @@ int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev, bool strobe_mode, struct atom_mpll_param *mpll_param); -uint32_t amdgpu_atombios_get_engine_clock(struct amdgpu_device *adev); -uint32_t amdgpu_atombios_get_memory_clock(struct amdgpu_device *adev); -void amdgpu_atombios_set_engine_clock(struct amdgpu_device *adev, - uint32_t eng_clock); -void amdgpu_atombios_set_memory_clock(struct amdgpu_device *adev, - uint32_t mem_clock); -void amdgpu_atombios_set_voltage(struct amdgpu_device *adev, - u16 voltage_level, - u8 voltage_type); - void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev, u32 eng_clock, u32 mem_clock); -- cgit v1.2.3 From f93932bcdcbbd3c3bb532c478cbbb939c3b12492 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 21 Oct 2016 16:36:12 -0400 Subject: drm/amdgpu: s/amdgpuCrtc/amdgpu_crtc/ in pageflip code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix random CamelCase that has annoyed me for a while. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 083e2b429872..c7bc2b3c1b97 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -68,9 +68,9 @@ static void amdgpu_flip_work_func(struct work_struct *__work) struct amdgpu_flip_work *work = container_of(delayed_work, struct amdgpu_flip_work, flip_work); struct amdgpu_device *adev = work->adev; - struct amdgpu_crtc *amdgpuCrtc = adev->mode_info.crtcs[work->crtc_id]; + struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[work->crtc_id]; - struct drm_crtc *crtc = &amdgpuCrtc->base; + struct drm_crtc *crtc = &amdgpu_crtc->base; unsigned long flags; unsigned i; int vpos, hpos; @@ -85,14 +85,14 @@ static void amdgpu_flip_work_func(struct work_struct *__work) /* Wait until we're out of the vertical blank period before the one * targeted by the flip */ - if (amdgpuCrtc->enabled && + if (amdgpu_crtc->enabled && (amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0, &vpos, &hpos, NULL, NULL, &crtc->hwmode) & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && (int)(work->target_vblank - - amdgpu_get_vblank_counter_kms(adev->ddev, amdgpuCrtc->crtc_id)) > 0) { + amdgpu_get_vblank_counter_kms(adev->ddev, amdgpu_crtc->crtc_id)) > 0) { schedule_delayed_work(&work->flip_work, usecs_to_jiffies(1000)); return; } @@ -104,12 +104,12 @@ static void amdgpu_flip_work_func(struct work_struct *__work) adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base, work->async); /* Set the flip status */ - amdgpuCrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + amdgpu_crtc->pflip_status = AMDGPU_FLIP_SUBMITTED; spin_unlock_irqrestore(&crtc->dev->event_lock, flags); DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: %p,\n", - amdgpuCrtc->crtc_id, amdgpuCrtc, work); + amdgpu_crtc->crtc_id, amdgpu_crtc, work); } -- cgit v1.2.3 From 356aee305af62fd05eaa0ea09453ddb3e137474c Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sat, 22 Oct 2016 16:48:25 +0800 Subject: drm/amdgpu: change function declarations and add missing header dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get a few warnings when building kernel with W=1: drivers/gpu/drm/amd/amdgpu/atombios_crtc.c:38:6: warning: no previous prototype for 'amdgpu_atombios_crtc_overscan_setup' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/dce_v8_0.c:661:6: warning: no previous prototype for 'dce_v8_0_disable_dce' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c:40:5: warning: no previous prototype for 'amdgpu_gfx_scratch_get' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c:62:6: warning: no previous prototype for 'amdgpu_gfx_scratch_free' [-Wmissing-prototypes] .... In fact, these functions are declared in drivers/gpu/drm/amd/amdgpu/atombios_crtc.h drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h drivers/gpu/drm/amd/amdgpu/dce_v8_0.h drivers/gpu/drm/amd/amdgpu/dce_v10_0.h drivers/gpu/drm/amd/amdgpu/dce_v11_0.h drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h. So this patch adds missing header dependencies. By the way, this patch changes declaration of amdgpu_gfx_parse_disable_cu() to subject to its implement, and clean three function declarations in pp_acpi.h up. Acked-by: Edward O'Callaghan Acked-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 3 ++- drivers/gpu/drm/amd/amdgpu/atombios_crtc.c | 1 + drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 1 + drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 1 + drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 1 + drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c | 1 + drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h | 9 +++------ 8 files changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index a074edd95c70..01a42b6a69a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -24,6 +24,7 @@ */ #include #include "amdgpu.h" +#include "amdgpu_gfx.h" /* * GPU scratch registers helpers function. diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index 51321e154c09..e02044086445 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -27,6 +27,7 @@ int amdgpu_gfx_scratch_get(struct amdgpu_device *adev, uint32_t *reg); void amdgpu_gfx_scratch_free(struct amdgpu_device *adev, uint32_t reg); -unsigned amdgpu_gfx_parse_disable_cu(unsigned *mask, unsigned max_se, unsigned max_sh); +void amdgpu_gfx_parse_disable_cu(unsigned *mask, unsigned max_se, + unsigned max_sh); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c index f7d236f95e74..8c9bc75a9c2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c @@ -31,6 +31,7 @@ #include "atom.h" #include "atom-bits.h" #include "atombios_encoders.h" +#include "atombios_crtc.h" #include "amdgpu_atombios.h" #include "amdgpu_pll.h" #include "amdgpu_connectors.h" diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index e5d0edfb4309..199d3f7235d6 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -31,6 +31,7 @@ #include "atombios_encoders.h" #include "amdgpu_pll.h" #include "amdgpu_connectors.h" +#include "dce_v10_0.h" #include "dce/dce_10_0_d.h" #include "dce/dce_10_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 9719b2b14186..ecd000e35981 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -31,6 +31,7 @@ #include "atombios_encoders.h" #include "amdgpu_pll.h" #include "amdgpu_connectors.h" +#include "dce_v11_0.h" #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 16a2f1faaf19..979aedf4b74d 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -31,6 +31,7 @@ #include "atombios_encoders.h" #include "amdgpu_pll.h" #include "amdgpu_connectors.h" +#include "dce_v8_0.h" #include "dce/dce_8_0_d.h" #include "dce/dce_8_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c index 1944d289f846..f5e8fda964f7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c @@ -25,6 +25,7 @@ #include "linux/delay.h" #include "hwmgr.h" #include "amd_acpi.h" +#include "pp_acpi.h" bool acpi_atcs_functions_supported(void *device, uint32_t index) { diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h b/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h index 3df5de2cdab0..8fe8ba9434ff 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h @@ -21,9 +21,6 @@ * */ -extern bool acpi_atcs_functions_supported(void *device, - uint32_t index); -extern int acpi_pcie_perf_request(void *device, - uint8_t perf_req, - bool advertise); -extern bool acpi_atcs_notify_pcie_device_ready(void *device); +bool acpi_atcs_functions_supported(void *device, uint32_t index); +int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise); +bool acpi_atcs_notify_pcie_device_ready(void *device); -- cgit v1.2.3 From d1936cc2fc56f4cd7399b963fd66d58b539bb515 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sat, 22 Oct 2016 16:48:26 +0800 Subject: drm/amdgpu: mark symbols static where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get 2 warnings when building kernel with W=1: drivers/gpu/drm/amd/amdgpu/si.c:908:5: warning: no previous prototype for 'si_pciep_rreg' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/si.c:921:6: warning: no previous prototype for 'si_pciep_wreg' [-Wmissing-prototypes] In fact, both functions are only used in the file in which they are declared and don't need a declaration, but can be made static. So this patch marks these functions with 'static'. Acked-by: Edward O'Callaghan Reviewed-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index d2d79206bcf9..3ed8ad8725b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -906,7 +906,7 @@ static void si_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); } -u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) +static u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags; u32 r; @@ -919,7 +919,7 @@ u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) return r; } -void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +static void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { unsigned long flags; -- cgit v1.2.3 From aafcafa0fa5f4b45d99a9a0374fa9590814ff274 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Mon, 24 Oct 2016 11:36:17 +0800 Subject: drm/amdgpu:new ids flag for preempt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Monk Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 ++ include/uapi/drm/amdgpu_drm.h | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index d17424663fe2..78392671046a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -505,6 +505,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file dev_info.ids_flags = 0; if (adev->flags & AMD_IS_APU) dev_info.ids_flags |= AMDGPU_IDS_FLAGS_FUSION; + if (amdgpu_sriov_vf(adev)) + dev_info.ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION; dev_info.virtual_address_offset = AMDGPU_VA_RESERVED_SIZE; dev_info.virtual_address_max = (uint64_t)adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE; dev_info.virtual_address_alignment = max((int)PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE); diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index a03beb109d78..4684f378f046 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -438,6 +438,7 @@ struct drm_amdgpu_cs_chunk_data { * */ #define AMDGPU_IDS_FLAGS_FUSION 0x1 +#define AMDGPU_IDS_FLAGS_PREEMPTION 0x2 /* indicate if acceleration can be working */ #define AMDGPU_INFO_ACCEL_WORKING 0x00 -- cgit v1.2.3 From fad742f89d20f8b0d6765ff8312eb091f6767e43 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 25 Oct 2016 00:14:12 +0100 Subject: drm/amd/powerplay: fix spelling mistake and add KERN_WARNING to printks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix trivial spelling mistake cant't -> can't and add KERN_WARNING to printk messages. Remove redundant spaces before \n too (thanks to Joe Perches for spotting those). Reviewed-by: Christian König Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c | 4 ++-- drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c | 4 ++-- drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c | 4 ++-- drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c index e7e8944ba8b2..34523fe6ed6f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c @@ -2125,7 +2125,7 @@ uint32_t fiji_get_offsetof(uint32_t type, uint32_t member) return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold); } } - printk("cant't get the offset of type %x member %x \n", type, member); + printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member); return 0; } @@ -2150,7 +2150,7 @@ uint32_t fiji_get_mac_definition(uint32_t value) return SMU73_MAX_LEVELS_MVDD; } - printk("cant't get the mac of %x \n", value); + printk(KERN_WARNING "can't get the mac of %x\n", value); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c index 8c889caba420..b579f0c175e6 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c @@ -2140,7 +2140,7 @@ uint32_t iceland_get_offsetof(uint32_t type, uint32_t member) return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold); } } - printk("cant't get the offset of type %x member %x \n", type, member); + printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member); return 0; } @@ -2163,7 +2163,7 @@ uint32_t iceland_get_mac_definition(uint32_t value) return SMU71_MAX_LEVELS_MVDD; } - printk("cant't get the mac of %x \n", value); + printk(KERN_WARNING "can't get the mac of %x\n", value); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c index 4ccc0b72324d..006b22071685 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c @@ -2174,7 +2174,7 @@ uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member) return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold); } } - printk("cant't get the offset of type %x member %x \n", type, member); + printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member); return 0; } @@ -2201,7 +2201,7 @@ uint32_t polaris10_get_mac_definition(uint32_t value) return SMU7_UVD_MCLK_HANDSHAKE_DISABLE; } - printk("cant't get the mac of %x \n", value); + printk(KERN_WARNING "can't get the mac of %x\n", value); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c index de2a24d85f48..d08f6f19b454 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c @@ -2651,7 +2651,7 @@ uint32_t tonga_get_offsetof(uint32_t type, uint32_t member) return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold); } } - printk("cant't get the offset of type %x member %x\n", type, member); + printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member); return 0; } @@ -2675,7 +2675,7 @@ uint32_t tonga_get_mac_definition(uint32_t value) case SMU_MAX_LEVELS_MVDD: return SMU72_MAX_LEVELS_MVDD; } - printk("cant't get the mac value %x\n", value); + printk(KERN_WARNING "can't get the mac value %x\n", value); return 0; } -- cgit v1.2.3 From 1c331f75aa6ccbf64ebcc5a019183e617c9d818a Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sun, 23 Oct 2016 01:05:33 +0200 Subject: drm/radeon/pm: autoswitch power state when in balanced mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current default of always using the performance power state leads to increased power consumption of mobile devices, which have a dedicated battery power state. Switch between the performance and battery power state automatically, dpending on the current AC power status, when the user asked for the balanced power state. The user can still override this logic by asking for the performance or battery power state explicitly. Tested-by: Michel Dänzer Acked-by: Christian König Signed-off-by: Lucas Stach Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_pm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 4b6542538ff9..326ad068c15a 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -47,6 +47,7 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev); static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish); static void radeon_pm_update_profile(struct radeon_device *rdev); static void radeon_pm_set_clocks(struct radeon_device *rdev); +static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev); int radeon_pm_get_type_index(struct radeon_device *rdev, enum radeon_pm_state_type ps_type, @@ -79,6 +80,8 @@ void radeon_pm_acpi_event_handler(struct radeon_device *rdev) radeon_dpm_enable_bapm(rdev, rdev->pm.dpm.ac_power); } mutex_unlock(&rdev->pm.mutex); + /* allow new DPM state to be picked */ + radeon_pm_compute_clocks_dpm(rdev); } else if (rdev->pm.pm_method == PM_METHOD_PROFILE) { if (rdev->pm.profile == PM_PROFILE_AUTO) { mutex_lock(&rdev->pm.mutex); @@ -882,7 +885,8 @@ static struct radeon_ps *radeon_dpm_pick_power_state(struct radeon_device *rdev, dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; /* balanced states don't exist at the moment */ if (dpm_state == POWER_STATE_TYPE_BALANCED) - dpm_state = POWER_STATE_TYPE_PERFORMANCE; + dpm_state = rdev->pm.dpm.ac_power ? + POWER_STATE_TYPE_PERFORMANCE : POWER_STATE_TYPE_BATTERY; restart_search: /* Pick the best power state based on current conditions */ -- cgit v1.2.3 From a2ab19fed9d1dc5a7a2ced44f4b289885c522a8f Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 30 Aug 2016 17:26:04 +0200 Subject: drm/ttm: make eviction decision a driver callback v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way the driver can decide if it is valuable to evict a BO or not. The current implementation is added as default to all existing drivers. v2: fix some typos found during internal testing Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 1 + drivers/gpu/drm/ast/ast_ttm.c | 1 + drivers/gpu/drm/bochs/bochs_mm.c | 1 + drivers/gpu/drm/cirrus/cirrus_ttm.c | 1 + drivers/gpu/drm/mgag200/mgag200_ttm.c | 1 + drivers/gpu/drm/nouveau/nouveau_bo.c | 1 + drivers/gpu/drm/qxl/qxl_ttm.c | 1 + drivers/gpu/drm/radeon/radeon_ttm.c | 1 + drivers/gpu/drm/ttm/ttm_bo.c | 35 +++++++++++++++++++++------------ drivers/gpu/drm/virtio/virtgpu_ttm.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 1 + include/drm/ttm/ttm_bo_api.h | 13 ++++++++++++ include/drm/ttm/ttm_bo_driver.h | 12 +++++++++++ 13 files changed, 57 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 414fa8fa8488..fb646c44faae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1109,6 +1109,7 @@ static struct ttm_bo_driver amdgpu_bo_driver = { .ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate, .invalidate_caches = &amdgpu_invalidate_caches, .init_mem_type = &amdgpu_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, .verify_access = &amdgpu_verify_access, diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c index 608df4c90520..7134fdf49210 100644 --- a/drivers/gpu/drm/ast/ast_ttm.c +++ b/drivers/gpu/drm/ast/ast_ttm.c @@ -230,6 +230,7 @@ struct ttm_bo_driver ast_bo_driver = { .ttm_tt_populate = ast_ttm_tt_populate, .ttm_tt_unpopulate = ast_ttm_tt_unpopulate, .init_mem_type = ast_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = ast_bo_evict_flags, .move = NULL, .verify_access = ast_bo_verify_access, diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index 269cfca9ca06..099a3c688c26 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c @@ -199,6 +199,7 @@ struct ttm_bo_driver bochs_bo_driver = { .ttm_tt_populate = ttm_pool_populate, .ttm_tt_unpopulate = ttm_pool_unpopulate, .init_mem_type = bochs_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = bochs_bo_evict_flags, .move = NULL, .verify_access = bochs_bo_verify_access, diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c index bb2438dd8733..de52b20800e1 100644 --- a/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c @@ -230,6 +230,7 @@ struct ttm_bo_driver cirrus_bo_driver = { .ttm_tt_populate = cirrus_ttm_tt_populate, .ttm_tt_unpopulate = cirrus_ttm_tt_unpopulate, .init_mem_type = cirrus_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = cirrus_bo_evict_flags, .move = NULL, .verify_access = cirrus_bo_verify_access, diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c index 919b35f2ad24..83272b456329 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ttm.c +++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c @@ -230,6 +230,7 @@ struct ttm_bo_driver mgag200_bo_driver = { .ttm_tt_populate = mgag200_ttm_tt_populate, .ttm_tt_unpopulate = mgag200_ttm_tt_unpopulate, .init_mem_type = mgag200_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = mgag200_bo_evict_flags, .move = NULL, .verify_access = mgag200_bo_verify_access, diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 343b8659472c..e395cb6f511f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1561,6 +1561,7 @@ struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate, .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = nouveau_bo_evict_flags, .move_notify = nouveau_bo_move_ntfy, .move = nouveau_bo_move, diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index e26c82db948b..11761330a6b8 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -387,6 +387,7 @@ static struct ttm_bo_driver qxl_bo_driver = { .ttm_tt_unpopulate = &qxl_ttm_tt_unpopulate, .invalidate_caches = &qxl_invalidate_caches, .init_mem_type = &qxl_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &qxl_evict_flags, .move = &qxl_bo_move, .verify_access = &qxl_verify_access, diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 3de5e6e21662..0cf03ccbf0a7 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -863,6 +863,7 @@ static struct ttm_bo_driver radeon_bo_driver = { .ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate, .invalidate_caches = &radeon_invalidate_caches, .init_mem_type = &radeon_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &radeon_evict_flags, .move = &radeon_bo_move, .verify_access = &radeon_verify_access, diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index fc6217dfe401..31fcf11a2831 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -717,6 +717,20 @@ out: return ret; } +bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, + const struct ttm_place *place) +{ + /* Don't evict this BO if it's outside of the + * requested placement range + */ + if (place->fpfn >= (bo->mem.start + bo->mem.size) || + (place->lpfn && place->lpfn <= bo->mem.start)) + return false; + + return true; +} +EXPORT_SYMBOL(ttm_bo_eviction_valuable); + static int ttm_mem_evict_first(struct ttm_bo_device *bdev, uint32_t mem_type, const struct ttm_place *place, @@ -731,21 +745,16 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, spin_lock(&glob->lru_lock); list_for_each_entry(bo, &man->lru, lru) { ret = __ttm_bo_reserve(bo, false, true, NULL); - if (!ret) { - if (place && (place->fpfn || place->lpfn)) { - /* Don't evict this BO if it's outside of the - * requested placement range - */ - if (place->fpfn >= (bo->mem.start + bo->mem.size) || - (place->lpfn && place->lpfn <= bo->mem.start)) { - __ttm_bo_unreserve(bo); - ret = -EBUSY; - continue; - } - } + if (ret) + continue; - break; + if (place && !bdev->driver->eviction_valuable(bo, place)) { + __ttm_bo_unreserve(bo); + ret = -EBUSY; + continue; } + + break; } if (ret) { diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index 80482ac5f95d..4a1de9f81193 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -425,6 +425,7 @@ static struct ttm_bo_driver virtio_gpu_bo_driver = { .ttm_tt_unpopulate = &virtio_gpu_ttm_tt_unpopulate, .invalidate_caches = &virtio_gpu_invalidate_caches, .init_mem_type = &virtio_gpu_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &virtio_gpu_evict_flags, .move = &virtio_gpu_bo_move, .verify_access = &virtio_gpu_verify_access, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 78b75ee3c931..c894a48a74a6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -849,6 +849,7 @@ struct ttm_bo_driver vmw_bo_driver = { .ttm_tt_unpopulate = &vmw_ttm_unpopulate, .invalidate_caches = vmw_invalidate_caches, .init_mem_type = vmw_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = vmw_evict_flags, .move = NULL, .verify_access = vmw_verify_access, diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 9eb940d6755f..bb6a3357a817 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -47,6 +47,8 @@ struct drm_mm_node; struct ttm_placement; +struct ttm_place; + /** * struct ttm_bus_placement * @@ -395,6 +397,17 @@ extern int ttm_bo_lock_delayed_workqueue(struct ttm_bo_device *bdev); extern void ttm_bo_unlock_delayed_workqueue(struct ttm_bo_device *bdev, int resched); +/** + * ttm_bo_eviction_valuable + * + * @bo: The buffer object to evict + * @place: the placement we need to make room for + * + * Check if it is valuable to evict the BO to make room for the given placement. + */ +bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, + const struct ttm_place *place); + /** * ttm_bo_synccpu_write_grab * diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 7a76663d4045..d3d83dfe89e2 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -374,6 +374,18 @@ struct ttm_bo_driver { int (*invalidate_caches)(struct ttm_bo_device *bdev, uint32_t flags); int (*init_mem_type)(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man); + + /** + * struct ttm_bo_driver member eviction_valuable + * + * @bo: the buffer object to be evicted + * @place: placement we need room for + * + * Check with the driver if it is valuable to evict a BO to make room + * for a certain placement. + */ + bool (*eviction_valuable)(struct ttm_buffer_object *bo, + const struct ttm_place *place); /** * struct ttm_bo_driver member evict_flags: * -- cgit v1.2.3 From 9982ca681e430907cb7f4e19e2ae4845031d5d59 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 19 Oct 2016 14:44:22 +0200 Subject: drm/amdgpu: add amdgpu_ttm_bo_eviction_valuable callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we can correctly check split VRAM buffers as well. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fb646c44faae..f1a206df9823 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1103,13 +1103,37 @@ static struct list_head *amdgpu_ttm_swap_lru_tail(struct ttm_buffer_object *tbo) return res; } +static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, + const struct ttm_place *place) +{ + if (bo->mem.mem_type == TTM_PL_VRAM && + bo->mem.start == AMDGPU_BO_INVALID_OFFSET) { + unsigned long num_pages = bo->mem.num_pages; + struct drm_mm_node *node = bo->mem.mm_node; + + /* Check each drm MM node individually */ + while (num_pages) { + if (place->fpfn < (node->start + node->size) && + !(place->lpfn && place->lpfn <= node->start)) + return true; + + num_pages -= node->size; + ++node; + } + + return false; + } + + return ttm_bo_eviction_valuable(bo, place); +} + static struct ttm_bo_driver amdgpu_bo_driver = { .ttm_tt_create = &amdgpu_ttm_tt_create, .ttm_tt_populate = &amdgpu_ttm_tt_populate, .ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate, .invalidate_caches = &amdgpu_invalidate_caches, .init_mem_type = &amdgpu_init_mem_type, - .eviction_valuable = ttm_bo_eviction_valuable, + .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, .verify_access = &amdgpu_verify_access, -- cgit v1.2.3 From ed4596ea992db45a27bfc3a0e401fb95ef2d5f23 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Tue, 25 Oct 2016 22:05:23 +0530 Subject: drm/i915/guc: WA to address the Ringbuffer coherency issue Driver accesses the ringbuffer pages, via GMADR BAR, if the pages are pinned in mappable aperture portion of GGTT and for ringbuffer pages allocated from Stolen memory, access can only be done through GMADR BAR. In case of GuC based submission, updates done in ringbuffer via GMADR may not get committed to memory by the time the Command streamer starts reading them, resulting in fetching of stale data. For Host based submission, such problem is not there as the write to Ring Tail or ELSP register happens from the Host side prior to submission. Access to any GFX register from CPU side goes to GTTMMADR BAR and Hw already enforces the ordering between outstanding GMADR writes & new GTTMADR access. MMIO writes from GuC side do not go to GTTMMADR BAR as GuC communication to registers within GT is contained within GT, so ordering is not enforced resulting in a race, which can manifest in form of a hang. To ensure the flush of in-flight GMADR writes, a POSTING READ is done to GuC register prior to doorbell ring. There is already a similar WA in i915_gem_object_flush_gtt_write_domain(), which takes care of GMADR writes from User space to GEM buffers, but not the ringbuffer writes from KMD. This WA is needed on all recent HW. v2: - Use POSTING_READ_FW instead of POSTING_READ as GuC register do not lie in any forcewake domain range and so the overhead of spinlock & search in the forcewake table is avoidable. (Chris) Cc: Chris Wilson Signed-off-by: Sagar Arun Kamble Signed-off-by: Akash Goel Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1477413323-1880-1-git-send-email-akash.goel@intel.com --- drivers/gpu/drm/i915/i915_guc_submission.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index bf65ffa7e4ce..74235ea3950f 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -634,6 +634,7 @@ static int guc_ring_doorbell(struct i915_guc_client *gc) */ static void i915_guc_submit(struct drm_i915_gem_request *rq) { + struct drm_i915_private *dev_priv = rq->i915; unsigned int engine_id = rq->engine->id; struct intel_guc *guc = &rq->i915->guc; struct i915_guc_client *client = guc->execbuf_client; @@ -641,6 +642,11 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq) spin_lock(&client->wq_lock); guc_wq_item_append(client, rq); + + /* WA to flush out the pending GMADR writes to ring buffer. */ + if (i915_vma_is_map_and_fenceable(rq->ring->vma)) + POSTING_READ_FW(GUC_STATUS); + b_ret = guc_ring_doorbell(client); client->submissions[engine_id] += 1; -- cgit v1.2.3 From 64fafcf5a2fa2f3c33fa7f5957923839b36f1e8c Mon Sep 17 00:00:00 2001 From: Min He Date: Tue, 25 Oct 2016 16:26:04 +0800 Subject: drm/i915/gvt: fix an typo in skl_decode_mi_display_flip Fix type to set correct pipe number. Signed-off-by: Min He Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 477b0d41ae65..0084ece8d8ff 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1145,7 +1145,7 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s, info->event = PRIMARY_B_FLIP_DONE; break; case MI_DISPLAY_FLIP_SKL_PLANE_1_C: - info->pipe = PIPE_B; + info->pipe = PIPE_C; info->event = PRIMARY_C_FLIP_DONE; break; default: -- cgit v1.2.3 From b0122f3114e20f7d73520761648f8f0c141f3a30 Mon Sep 17 00:00:00 2001 From: Xiaoguang Chen Date: Tue, 25 Oct 2016 16:56:45 +0800 Subject: drm/i915/gvt: fix detect_host calling logic Like other routines, intel_gvt_hypervisor_detect_host returns 0 for success. Signed-off-by: Xiaoguang Chen Signed-off-by: Jike Song Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gvt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index bf0377768a0d..385969a89216 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -65,6 +65,8 @@ struct intel_gvt_io_emulation_ops intel_gvt_io_emulation_ops = { */ int intel_gvt_init_host(void) { + int ret; + if (intel_gvt_host.initialized) return 0; @@ -90,7 +92,8 @@ int intel_gvt_init_host(void) return -EINVAL; /* Try to detect if we're running in host instead of VM. */ - if (!intel_gvt_hypervisor_detect_host()) + ret = intel_gvt_hypervisor_detect_host(); + if (ret) return -ENODEV; gvt_dbg_core("Running with hypervisor %s in host mode\n", -- cgit v1.2.3 From 40d2428b3a6aaa3d6ba0de0e8780c4b4eb53426c Mon Sep 17 00:00:00 2001 From: Ping Gao Date: Wed, 26 Oct 2016 09:38:50 +0800 Subject: drm/i915/gvt: add vreg write for GDRST handler The emulation handler for MMIO GDRST miss vreg write in it, as result the vreg cannot update correspondingly. Signed-off-by: Ping Gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/handlers.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 3e74fb3d4aa9..52af51728cc1 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -258,6 +258,7 @@ static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, u32 data; u64 bitmap = 0; + write_vreg(vgpu, offset, p_data, bytes); data = vgpu_vreg(vgpu, offset); if (data & GEN6_GRDOM_FULL) { -- cgit v1.2.3 From 0a8b66e3adbe302a02bb33e1a662416281ade616 Mon Sep 17 00:00:00 2001 From: Ping Gao Date: Wed, 26 Oct 2016 13:36:41 +0800 Subject: drm/i915/gvt: correct the reset logic The current_vgpu will set to NULL after stopping the scheduler when the reset is triggered by current vgpu, so here need change the judgement condition for current vgpu detection. Signed-off-by: Ping Gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/handlers.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 52af51728cc1..7832e49ed5b3 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -239,7 +239,11 @@ static int handle_device_reset(struct intel_vgpu *vgpu, unsigned int offset, vgpu->resetting = true; intel_vgpu_stop_schedule(vgpu); - if (scheduler->current_vgpu == vgpu) { + /* + * The current_vgpu will set to NULL after stopping the + * scheduler when the reset is triggered by current vgpu. + */ + if (scheduler->current_vgpu == NULL) { mutex_unlock(&vgpu->gvt->lock); intel_gvt_wait_vgpu_idle(vgpu); mutex_lock(&vgpu->gvt->lock); -- cgit v1.2.3 From ce6e153f414a73a52fa1498489ce4adf20229445 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 10 Oct 2016 09:39:17 +0200 Subject: drm/bridge: add Silicon Image SiI8620 driver SiI8620 transmitter converts eTMDS/HDMI signal to MHL 3.0. It is controlled via I2C bus. Its interaction with other devices in video pipeline is performed mainly on HW level. The only interaction it does on device driver level is filtering-out unsupported video modes, it exposes drm_bridge interface to perform this operation. Signed-off-by: Andrzej Hajda Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1476085157-5266-1-git-send-email-a.hajda@samsung.com --- drivers/gpu/drm/bridge/Kconfig | 7 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/sil-sii8620.c | 1565 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/bridge/sil-sii8620.h | 1517 ++++++++++++++++++++++++++++++++ 4 files changed, 3090 insertions(+) create mode 100644 drivers/gpu/drm/bridge/sil-sii8620.c create mode 100644 drivers/gpu/drm/bridge/sil-sii8620.h (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 10e12e74fc9f..bd6acc829f97 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -57,6 +57,13 @@ config DRM_PARADE_PS8622 ---help--- Parade eDP-LVDS bridge chip driver. +config DRM_SIL_SII8620 + tristate "Silicon Image SII8620 HDMI/MHL bridge" + depends on OF + select DRM_KMS_HELPER + help + Silicon Image SII8620 HDMI/MHL bridge chip driver. + config DRM_SII902X tristate "Silicon Image sii902x RGB/HDMI bridge" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index cdf3a3cf765d..97ed1a5fea9a 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o +obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o obj-$(CONFIG_DRM_SII902X) += sii902x.o obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c new file mode 100644 index 000000000000..1345e7cc7bf0 --- /dev/null +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -0,0 +1,1565 @@ +/* + * Silicon Image SiI8620 HDMI/MHL bridge driver + * + * Copyright (C) 2015, Samsung Electronics Co., Ltd. + * Andrzej Hajda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sil-sii8620.h" + +#define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3) + +enum sii8620_mode { + CM_DISCONNECTED, + CM_DISCOVERY, + CM_MHL1, + CM_MHL3, + CM_ECBUS_S +}; + +enum sii8620_sink_type { + SINK_NONE, + SINK_HDMI, + SINK_DVI +}; + +enum sii8620_mt_state { + MT_STATE_READY, + MT_STATE_BUSY, + MT_STATE_DONE +}; + +struct sii8620 { + struct drm_bridge bridge; + struct device *dev; + struct clk *clk_xtal; + struct gpio_desc *gpio_reset; + struct gpio_desc *gpio_int; + struct regulator_bulk_data supplies[2]; + struct mutex lock; /* context lock, protects fields below */ + int error; + enum sii8620_mode mode; + enum sii8620_sink_type sink_type; + u8 cbus_status; + u8 stat[MHL_DST_SIZE]; + u8 xstat[MHL_XDS_SIZE]; + u8 devcap[MHL_DCAP_SIZE]; + u8 xdevcap[MHL_XDC_SIZE]; + u8 avif[19]; + struct edid *edid; + unsigned int gen2_write_burst:1; + enum sii8620_mt_state mt_state; + struct list_head mt_queue; +}; + +struct sii8620_mt_msg; + +typedef void (*sii8620_mt_msg_cb)(struct sii8620 *ctx, + struct sii8620_mt_msg *msg); + +struct sii8620_mt_msg { + struct list_head node; + u8 reg[4]; + u8 ret; + sii8620_mt_msg_cb send; + sii8620_mt_msg_cb recv; +}; + +static const u8 sii8620_i2c_page[] = { + 0x39, /* Main System */ + 0x3d, /* TDM and HSIC */ + 0x49, /* TMDS Receiver, MHL EDID */ + 0x4d, /* eMSC, HDCP, HSIC */ + 0x5d, /* MHL Spec */ + 0x64, /* MHL CBUS */ + 0x59, /* Hardware TPI (Transmitter Programming Interface) */ + 0x61, /* eCBUS-S, eCBUS-D */ +}; + +static void sii8620_fetch_edid(struct sii8620 *ctx); +static void sii8620_set_upstream_edid(struct sii8620 *ctx); +static void sii8620_enable_hpd(struct sii8620 *ctx); +static void sii8620_mhl_disconnected(struct sii8620 *ctx); + +static int sii8620_clear_error(struct sii8620 *ctx) +{ + int ret = ctx->error; + + ctx->error = 0; + return ret; +} + +static void sii8620_read_buf(struct sii8620 *ctx, u16 addr, u8 *buf, int len) +{ + struct device *dev = ctx->dev; + struct i2c_client *client = to_i2c_client(dev); + u8 data = addr; + struct i2c_msg msg[] = { + { + .addr = sii8620_i2c_page[addr >> 8], + .flags = client->flags, + .len = 1, + .buf = &data + }, + { + .addr = sii8620_i2c_page[addr >> 8], + .flags = client->flags | I2C_M_RD, + .len = len, + .buf = buf + }, + }; + int ret; + + if (ctx->error) + return; + + ret = i2c_transfer(client->adapter, msg, 2); + dev_dbg(dev, "read at %04x: %*ph, %d\n", addr, len, buf, ret); + + if (ret != 2) { + dev_err(dev, "Read at %#06x of %d bytes failed with code %d.\n", + addr, len, ret); + ctx->error = ret < 0 ? ret : -EIO; + } +} + +static u8 sii8620_readb(struct sii8620 *ctx, u16 addr) +{ + u8 ret; + + sii8620_read_buf(ctx, addr, &ret, 1); + return ret; +} + +static void sii8620_write_buf(struct sii8620 *ctx, u16 addr, const u8 *buf, + int len) +{ + struct device *dev = ctx->dev; + struct i2c_client *client = to_i2c_client(dev); + u8 data[2]; + struct i2c_msg msg = { + .addr = sii8620_i2c_page[addr >> 8], + .flags = client->flags, + .len = len + 1, + }; + int ret; + + if (ctx->error) + return; + + if (len > 1) { + msg.buf = kmalloc(len + 1, GFP_KERNEL); + if (!msg.buf) { + ctx->error = -ENOMEM; + return; + } + memcpy(msg.buf + 1, buf, len); + } else { + msg.buf = data; + msg.buf[1] = *buf; + } + + msg.buf[0] = addr; + + ret = i2c_transfer(client->adapter, &msg, 1); + dev_dbg(dev, "write at %04x: %*ph, %d\n", addr, len, buf, ret); + + if (ret != 1) { + dev_err(dev, "Write at %#06x of %*ph failed with code %d.\n", + addr, len, buf, ret); + ctx->error = ret ?: -EIO; + } + + if (len > 1) + kfree(msg.buf); +} + +#define sii8620_write(ctx, addr, arr...) \ +({\ + u8 d[] = { arr }; \ + sii8620_write_buf(ctx, addr, d, ARRAY_SIZE(d)); \ +}) + +static void __sii8620_write_seq(struct sii8620 *ctx, const u16 *seq, int len) +{ + int i; + + for (i = 0; i < len; i += 2) + sii8620_write(ctx, seq[i], seq[i + 1]); +} + +#define sii8620_write_seq(ctx, seq...) \ +({\ + const u16 d[] = { seq }; \ + __sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \ +}) + +#define sii8620_write_seq_static(ctx, seq...) \ +({\ + static const u16 d[] = { seq }; \ + __sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \ +}) + +static void sii8620_setbits(struct sii8620 *ctx, u16 addr, u8 mask, u8 val) +{ + val = (val & mask) | (sii8620_readb(ctx, addr) & ~mask); + sii8620_write(ctx, addr, val); +} + +static void sii8620_mt_cleanup(struct sii8620 *ctx) +{ + struct sii8620_mt_msg *msg, *n; + + list_for_each_entry_safe(msg, n, &ctx->mt_queue, node) { + list_del(&msg->node); + kfree(msg); + } + ctx->mt_state = MT_STATE_READY; +} + +static void sii8620_mt_work(struct sii8620 *ctx) +{ + struct sii8620_mt_msg *msg; + + if (ctx->error) + return; + if (ctx->mt_state == MT_STATE_BUSY || list_empty(&ctx->mt_queue)) + return; + + if (ctx->mt_state == MT_STATE_DONE) { + ctx->mt_state = MT_STATE_READY; + msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, + node); + if (msg->recv) + msg->recv(ctx, msg); + list_del(&msg->node); + kfree(msg); + } + + if (ctx->mt_state != MT_STATE_READY || list_empty(&ctx->mt_queue)) + return; + + ctx->mt_state = MT_STATE_BUSY; + msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node); + if (msg->send) + msg->send(ctx, msg); +} + +static void sii8620_mt_msc_cmd_send(struct sii8620 *ctx, + struct sii8620_mt_msg *msg) +{ + switch (msg->reg[0]) { + case MHL_WRITE_STAT: + case MHL_SET_INT: + sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg + 1, 2); + sii8620_write(ctx, REG_MSC_COMMAND_START, + BIT_MSC_COMMAND_START_WRITE_STAT); + break; + case MHL_MSC_MSG: + sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg, 3); + sii8620_write(ctx, REG_MSC_COMMAND_START, + BIT_MSC_COMMAND_START_MSC_MSG); + break; + default: + dev_err(ctx->dev, "%s: command %#x not supported\n", __func__, + msg->reg[0]); + } +} + +static struct sii8620_mt_msg *sii8620_mt_msg_new(struct sii8620 *ctx) +{ + struct sii8620_mt_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); + + if (!msg) + ctx->error = -ENOMEM; + else + list_add_tail(&msg->node, &ctx->mt_queue); + + return msg; +} + +static void sii8620_mt_msc_cmd(struct sii8620 *ctx, u8 cmd, u8 arg1, u8 arg2) +{ + struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx); + + if (!msg) + return; + + msg->reg[0] = cmd; + msg->reg[1] = arg1; + msg->reg[2] = arg2; + msg->send = sii8620_mt_msc_cmd_send; +} + +static void sii8620_mt_write_stat(struct sii8620 *ctx, u8 reg, u8 val) +{ + sii8620_mt_msc_cmd(ctx, MHL_WRITE_STAT, reg, val); +} + +static inline void sii8620_mt_set_int(struct sii8620 *ctx, u8 irq, u8 mask) +{ + sii8620_mt_msc_cmd(ctx, MHL_SET_INT, irq, mask); +} + +static void sii8620_mt_msc_msg(struct sii8620 *ctx, u8 cmd, u8 data) +{ + sii8620_mt_msc_cmd(ctx, MHL_MSC_MSG, cmd, data); +} + +static void sii8620_mt_rap(struct sii8620 *ctx, u8 code) +{ + sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RAP, code); +} + +static void sii8620_mt_read_devcap_send(struct sii8620 *ctx, + struct sii8620_mt_msg *msg) +{ + u8 ctrl = BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP + | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO + | BIT_EDID_CTRL_EDID_MODE_EN; + + if (msg->reg[0] == MHL_READ_XDEVCAP) + ctrl |= BIT_EDID_CTRL_XDEVCAP_EN; + + sii8620_write_seq(ctx, + REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE, + REG_EDID_CTRL, ctrl, + REG_TPI_CBUS_START, BIT_TPI_CBUS_START_GET_DEVCAP_START + ); +} + +/* copy src to dst and set changed bits in src */ +static void sii8620_update_array(u8 *dst, u8 *src, int count) +{ + while (--count >= 0) { + *src ^= *dst; + *dst++ ^= *src++; + } +} + +static void sii8620_mr_devcap(struct sii8620 *ctx) +{ + static const char * const sink_str[] = { + [SINK_NONE] = "NONE", + [SINK_HDMI] = "HDMI", + [SINK_DVI] = "DVI" + }; + + u8 dcap[MHL_DCAP_SIZE]; + char sink_name[20]; + struct device *dev = ctx->dev; + + sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, dcap, MHL_DCAP_SIZE); + if (ctx->error < 0) + return; + + dev_info(dev, "dcap: %*ph\n", MHL_DCAP_SIZE, dcap); + dev_info(dev, "detected dongle MHL %d.%d, ChipID %02x%02x:%02x%02x\n", + dcap[MHL_DCAP_MHL_VERSION] / 16, + dcap[MHL_DCAP_MHL_VERSION] % 16, dcap[MHL_DCAP_ADOPTER_ID_H], + dcap[MHL_DCAP_ADOPTER_ID_L], dcap[MHL_DCAP_DEVICE_ID_H], + dcap[MHL_DCAP_DEVICE_ID_L]); + sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE); + + if (!(dcap[MHL_DCAP_CAT] & MHL_DCAP_CAT_SINK)) + return; + + sii8620_fetch_edid(ctx); + if (!ctx->edid) { + dev_err(ctx->dev, "Cannot fetch EDID\n"); + sii8620_mhl_disconnected(ctx); + return; + } + + if (drm_detect_hdmi_monitor(ctx->edid)) + ctx->sink_type = SINK_HDMI; + else + ctx->sink_type = SINK_DVI; + + drm_edid_get_monitor_name(ctx->edid, sink_name, ARRAY_SIZE(sink_name)); + + dev_info(dev, "detected sink(type: %s): %s\n", + sink_str[ctx->sink_type], sink_name); + sii8620_set_upstream_edid(ctx); + sii8620_enable_hpd(ctx); +} + +static void sii8620_mr_xdevcap(struct sii8620 *ctx) +{ + sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, ctx->xdevcap, + MHL_XDC_SIZE); + + sii8620_mt_write_stat(ctx, MHL_XDS_REG(CURR_ECBUS_MODE), + MHL_XDS_ECBUS_S | MHL_XDS_SLOT_MODE_8BIT); + sii8620_mt_rap(ctx, MHL_RAP_CBUS_MODE_UP); +} + +static void sii8620_mt_read_devcap_recv(struct sii8620 *ctx, + struct sii8620_mt_msg *msg) +{ + u8 ctrl = BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP + | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO + | BIT_EDID_CTRL_EDID_MODE_EN; + + if (msg->reg[0] == MHL_READ_XDEVCAP) + ctrl |= BIT_EDID_CTRL_XDEVCAP_EN; + + sii8620_write_seq(ctx, + REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE | BIT_INTR9_EDID_DONE + | BIT_INTR9_EDID_ERROR, + REG_EDID_CTRL, ctrl, + REG_EDID_FIFO_ADDR, 0 + ); + + if (msg->reg[0] == MHL_READ_XDEVCAP) + sii8620_mr_xdevcap(ctx); + else + sii8620_mr_devcap(ctx); +} + +static void sii8620_mt_read_devcap(struct sii8620 *ctx, bool xdevcap) +{ + struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx); + + if (!msg) + return; + + msg->reg[0] = xdevcap ? MHL_READ_XDEVCAP : MHL_READ_DEVCAP; + msg->send = sii8620_mt_read_devcap_send; + msg->recv = sii8620_mt_read_devcap_recv; +} + +static void sii8620_fetch_edid(struct sii8620 *ctx) +{ + u8 lm_ddc, ddc_cmd, int3, cbus; + int fetched, i; + int edid_len = EDID_LENGTH; + u8 *edid; + + sii8620_readb(ctx, REG_CBUS_STATUS); + lm_ddc = sii8620_readb(ctx, REG_LM_DDC); + ddc_cmd = sii8620_readb(ctx, REG_DDC_CMD); + + sii8620_write_seq(ctx, + REG_INTR9_MASK, 0, + REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO, + REG_HDCP2X_POLL_CS, 0x71, + REG_HDCP2X_CTRL_0, BIT_HDCP2X_CTRL_0_HDCP2X_HDCPTX, + REG_LM_DDC, lm_ddc | BIT_LM_DDC_SW_TPI_EN_DISABLED, + ); + + for (i = 0; i < 256; ++i) { + u8 ddc_stat = sii8620_readb(ctx, REG_DDC_STATUS); + + if (!(ddc_stat & BIT_DDC_STATUS_DDC_I2C_IN_PROG)) + break; + sii8620_write(ctx, REG_DDC_STATUS, + BIT_DDC_STATUS_DDC_FIFO_EMPTY); + } + + sii8620_write(ctx, REG_DDC_ADDR, 0x50 << 1); + + edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (!edid) { + ctx->error = -ENOMEM; + return; + } + +#define FETCH_SIZE 16 + for (fetched = 0; fetched < edid_len; fetched += FETCH_SIZE) { + sii8620_readb(ctx, REG_DDC_STATUS); + sii8620_write_seq(ctx, + REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_DDC_CMD_ABORT, + REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_DDC_CMD_CLEAR_FIFO, + REG_DDC_STATUS, BIT_DDC_STATUS_DDC_FIFO_EMPTY + ); + sii8620_write_seq(ctx, + REG_DDC_SEGM, fetched >> 8, + REG_DDC_OFFSET, fetched & 0xff, + REG_DDC_DIN_CNT1, FETCH_SIZE, + REG_DDC_DIN_CNT2, 0, + REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_ENH_DDC_READ_NO_ACK + ); + + do { + int3 = sii8620_readb(ctx, REG_INTR3); + cbus = sii8620_readb(ctx, REG_CBUS_STATUS); + + if (int3 & BIT_DDC_CMD_DONE) + break; + + if (!(cbus & BIT_CBUS_STATUS_CBUS_CONNECTED)) { + kfree(edid); + edid = NULL; + goto end; + } + } while (1); + + sii8620_readb(ctx, REG_DDC_STATUS); + while (sii8620_readb(ctx, REG_DDC_DOUT_CNT) < FETCH_SIZE) + usleep_range(10, 20); + + sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE); + if (fetched + FETCH_SIZE == EDID_LENGTH) { + u8 ext = ((struct edid *)edid)->extensions; + + if (ext) { + u8 *new_edid; + + edid_len += ext * EDID_LENGTH; + new_edid = krealloc(edid, edid_len, GFP_KERNEL); + if (!new_edid) { + kfree(edid); + ctx->error = -ENOMEM; + return; + } + edid = new_edid; + } + } + + if (fetched + FETCH_SIZE == edid_len) + sii8620_write(ctx, REG_INTR3, int3); + } + + sii8620_write(ctx, REG_LM_DDC, lm_ddc); + +end: + kfree(ctx->edid); + ctx->edid = (struct edid *)edid; +} + +static void sii8620_set_upstream_edid(struct sii8620 *ctx) +{ + sii8620_setbits(ctx, REG_DPD, BIT_DPD_PDNRX12 | BIT_DPD_PDIDCK_N + | BIT_DPD_PD_MHL_CLK_N, 0xff); + + sii8620_write_seq_static(ctx, + REG_RX_HDMI_CTRL3, 0x00, + REG_PKT_FILTER_0, 0xFF, + REG_PKT_FILTER_1, 0xFF, + REG_ALICE0_BW_I2C, 0x06 + ); + + sii8620_setbits(ctx, REG_RX_HDMI_CLR_BUFFER, + BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_EN, 0xff); + + sii8620_write_seq_static(ctx, + REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO + | BIT_EDID_CTRL_EDID_MODE_EN, + REG_EDID_FIFO_ADDR, 0, + ); + + sii8620_write_buf(ctx, REG_EDID_FIFO_WR_DATA, (u8 *)ctx->edid, + (ctx->edid->extensions + 1) * EDID_LENGTH); + + sii8620_write_seq_static(ctx, + REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID + | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO + | BIT_EDID_CTRL_EDID_MODE_EN, + REG_INTR5_MASK, BIT_INTR_SCDT_CHANGE, + REG_INTR9_MASK, 0 + ); +} + +static void sii8620_xtal_set_rate(struct sii8620 *ctx) +{ + static const struct { + unsigned int rate; + u8 div; + u8 tp1; + } rates[] = { + { 19200, 0x04, 0x53 }, + { 20000, 0x04, 0x62 }, + { 24000, 0x05, 0x75 }, + { 30000, 0x06, 0x92 }, + { 38400, 0x0c, 0xbc }, + }; + unsigned long rate = clk_get_rate(ctx->clk_xtal) / 1000; + int i; + + for (i = 0; i < ARRAY_SIZE(rates) - 1; ++i) + if (rate <= rates[i].rate) + break; + + if (rate != rates[i].rate) + dev_err(ctx->dev, "xtal clock rate(%lukHz) not supported, setting MHL for %ukHz.\n", + rate, rates[i].rate); + + sii8620_write(ctx, REG_DIV_CTL_MAIN, rates[i].div); + sii8620_write(ctx, REG_HDCP2X_TP1, rates[i].tp1); +} + +static int sii8620_hw_on(struct sii8620 *ctx) +{ + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + if (ret) + return ret; + usleep_range(10000, 20000); + return clk_prepare_enable(ctx->clk_xtal); +} + +static int sii8620_hw_off(struct sii8620 *ctx) +{ + clk_disable_unprepare(ctx->clk_xtal); + gpiod_set_value(ctx->gpio_reset, 1); + return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); +} + +static void sii8620_hw_reset(struct sii8620 *ctx) +{ + usleep_range(10000, 20000); + gpiod_set_value(ctx->gpio_reset, 0); + usleep_range(5000, 20000); + gpiod_set_value(ctx->gpio_reset, 1); + usleep_range(10000, 20000); + gpiod_set_value(ctx->gpio_reset, 0); + msleep(300); +} + +static void sii8620_cbus_reset(struct sii8620 *ctx) +{ + sii8620_write_seq_static(ctx, + REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST + | BIT_PWD_SRST_CBUS_RST_SW_EN, + REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST_SW_EN + ); +} + +static void sii8620_set_auto_zone(struct sii8620 *ctx) +{ + if (ctx->mode != CM_MHL1) { + sii8620_write_seq_static(ctx, + REG_TX_ZONE_CTL1, 0x0, + REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X + | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL + | BIT_MHL_PLL_CTL0_ZONE_MASK_OE + ); + } else { + sii8620_write_seq_static(ctx, + REG_TX_ZONE_CTL1, VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE, + REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X + | BIT_MHL_PLL_CTL0_ZONE_MASK_OE + ); + } +} + +static void sii8620_stop_video(struct sii8620 *ctx) +{ + u8 uninitialized_var(val); + + sii8620_write_seq_static(ctx, + REG_TPI_INTR_EN, 0, + REG_HDCP2X_INTR0_MASK, 0, + REG_TPI_COPP_DATA2, 0, + REG_TPI_INTR_ST0, ~0, + ); + + switch (ctx->sink_type) { + case SINK_DVI: + val = BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN + | BIT_TPI_SC_TPI_AV_MUTE; + break; + case SINK_HDMI: + val = BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN + | BIT_TPI_SC_TPI_AV_MUTE + | BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI; + break; + default: + return; + } + + sii8620_write(ctx, REG_TPI_SC, val); +} + +static void sii8620_start_hdmi(struct sii8620 *ctx) +{ + sii8620_write_seq_static(ctx, + REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL + | BIT_RX_HDMI_CTRL2_USE_AV_MUTE, + REG_VID_OVRRD, BIT_VID_OVRRD_PP_AUTO_DISABLE + | BIT_VID_OVRRD_M1080P_OVRRD, + REG_VID_MODE, 0, + REG_MHL_TOP_CTL, 0x1, + REG_MHLTX_CTL6, 0xa0, + REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL), + REG_TPI_OUTPUT, VAL_TPI_FORMAT(RGB, FULL), + ); + + sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), + MHL_DST_LM_CLK_MODE_NORMAL | + MHL_DST_LM_PATH_ENABLED); + + sii8620_set_auto_zone(ctx); + + sii8620_write(ctx, REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI); + + sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif, + ARRAY_SIZE(ctx->avif)); + + sii8620_write(ctx, REG_PKT_FILTER_0, 0xa1, 0x2); +} + +static void sii8620_start_video(struct sii8620 *ctx) +{ + if (ctx->mode < CM_MHL3) + sii8620_stop_video(ctx); + + switch (ctx->sink_type) { + case SINK_HDMI: + sii8620_start_hdmi(ctx); + break; + case SINK_DVI: + default: + break; + } +} + +static void sii8620_disable_hpd(struct sii8620 *ctx) +{ + sii8620_setbits(ctx, REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID, 0); + sii8620_write_seq_static(ctx, + REG_HPD_CTRL, BIT_HPD_CTRL_HPD_OUT_OVR_EN, + REG_INTR8_MASK, 0 + ); +} + +static void sii8620_enable_hpd(struct sii8620 *ctx) +{ + sii8620_setbits(ctx, REG_TMDS_CSTAT_P3, + BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS + | BIT_TMDS_CSTAT_P3_CLR_AVI, ~0); + sii8620_write_seq_static(ctx, + REG_HPD_CTRL, BIT_HPD_CTRL_HPD_OUT_OVR_EN + | BIT_HPD_CTRL_HPD_HIGH, + ); +} + +static void sii8620_enable_gen2_write_burst(struct sii8620 *ctx) +{ + if (ctx->gen2_write_burst) + return; + + sii8620_write_seq_static(ctx, + REG_MDT_RCV_TIMEOUT, 100, + REG_MDT_RCV_CTRL, BIT_MDT_RCV_CTRL_MDT_RCV_EN + ); + ctx->gen2_write_burst = 1; +} + +static void sii8620_disable_gen2_write_burst(struct sii8620 *ctx) +{ + if (!ctx->gen2_write_burst) + return; + + sii8620_write_seq_static(ctx, + REG_MDT_XMIT_CTRL, 0, + REG_MDT_RCV_CTRL, 0 + ); + ctx->gen2_write_burst = 0; +} + +static void sii8620_start_gen2_write_burst(struct sii8620 *ctx) +{ + sii8620_write_seq_static(ctx, + REG_MDT_INT_1_MASK, BIT_MDT_RCV_TIMEOUT + | BIT_MDT_RCV_SM_ABORT_PKT_RCVD | BIT_MDT_RCV_SM_ERROR + | BIT_MDT_XMIT_TIMEOUT | BIT_MDT_XMIT_SM_ABORT_PKT_RCVD + | BIT_MDT_XMIT_SM_ERROR, + REG_MDT_INT_0_MASK, BIT_MDT_XFIFO_EMPTY + | BIT_MDT_IDLE_AFTER_HAWB_DISABLE + | BIT_MDT_RFIFO_DATA_RDY + ); + sii8620_enable_gen2_write_burst(ctx); +} + +static void sii8620_mhl_discover(struct sii8620 *ctx) +{ + sii8620_write_seq_static(ctx, + REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT + | BIT_DISC_CTRL9_DISC_PULSE_PROCEED, + REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_5K, VAL_PUP_20K), + REG_CBUS_DISC_INTR0_MASK, BIT_MHL3_EST_INT + | BIT_MHL_EST_INT + | BIT_NOT_MHL_EST_INT + | BIT_CBUS_MHL3_DISCON_INT + | BIT_CBUS_MHL12_DISCON_INT + | BIT_RGND_READY_INT, + REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X + | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL + | BIT_MHL_PLL_CTL0_ZONE_MASK_OE, + REG_MHL_DP_CTL0, BIT_MHL_DP_CTL0_DP_OE + | BIT_MHL_DP_CTL0_TX_OE_OVR, + REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE, + REG_MHL_DP_CTL1, 0xA2, + REG_MHL_DP_CTL2, 0x03, + REG_MHL_DP_CTL3, 0x35, + REG_MHL_DP_CTL5, 0x02, + REG_MHL_DP_CTL6, 0x02, + REG_MHL_DP_CTL7, 0x03, + REG_COC_CTLC, 0xFF, + REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 + | BIT_DPD_OSC_EN | BIT_DPD_PWRON_HSIC, + REG_COC_INTR_MASK, BIT_COC_PLL_LOCK_STATUS_CHANGE + | BIT_COC_CALIBRATION_DONE, + REG_CBUS_INT_1_MASK, BIT_CBUS_MSC_ABORT_RCVD + | BIT_CBUS_CMD_ABORT, + REG_CBUS_INT_0_MASK, BIT_CBUS_MSC_MT_DONE + | BIT_CBUS_HPD_CHG + | BIT_CBUS_MSC_MR_WRITE_STAT + | BIT_CBUS_MSC_MR_MSC_MSG + | BIT_CBUS_MSC_MR_WRITE_BURST + | BIT_CBUS_MSC_MR_SET_INT + | BIT_CBUS_MSC_MT_DONE_NACK + ); +} + +static void sii8620_peer_specific_init(struct sii8620 *ctx) +{ + if (ctx->mode == CM_MHL3) + sii8620_write_seq_static(ctx, + REG_SYS_CTRL1, BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD, + REG_EMSCINTRMASK1, + BIT_EMSCINTR1_EMSC_TRAINING_COMMA_ERR + ); + else + sii8620_write_seq_static(ctx, + REG_HDCP2X_INTR0_MASK, 0x00, + REG_EMSCINTRMASK1, 0x00, + REG_HDCP2X_INTR0, 0xFF, + REG_INTR1, 0xFF, + REG_SYS_CTRL1, BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD + | BIT_SYS_CTRL1_TX_CTRL_HDMI + ); +} + +#define SII8620_MHL_VERSION 0x32 +#define SII8620_SCRATCHPAD_SIZE 16 +#define SII8620_INT_STAT_SIZE 0x33 + +static void sii8620_set_dev_cap(struct sii8620 *ctx) +{ + static const u8 devcap[MHL_DCAP_SIZE] = { + [MHL_DCAP_MHL_VERSION] = SII8620_MHL_VERSION, + [MHL_DCAP_CAT] = MHL_DCAP_CAT_SOURCE | MHL_DCAP_CAT_POWER, + [MHL_DCAP_ADOPTER_ID_H] = 0x01, + [MHL_DCAP_ADOPTER_ID_L] = 0x41, + [MHL_DCAP_VID_LINK_MODE] = MHL_DCAP_VID_LINK_RGB444 + | MHL_DCAP_VID_LINK_PPIXEL + | MHL_DCAP_VID_LINK_16BPP, + [MHL_DCAP_AUD_LINK_MODE] = MHL_DCAP_AUD_LINK_2CH, + [MHL_DCAP_VIDEO_TYPE] = MHL_DCAP_VT_GRAPHICS, + [MHL_DCAP_LOG_DEV_MAP] = MHL_DCAP_LD_GUI, + [MHL_DCAP_BANDWIDTH] = 0x0f, + [MHL_DCAP_FEATURE_FLAG] = MHL_DCAP_FEATURE_RCP_SUPPORT + | MHL_DCAP_FEATURE_RAP_SUPPORT + | MHL_DCAP_FEATURE_SP_SUPPORT, + [MHL_DCAP_SCRATCHPAD_SIZE] = SII8620_SCRATCHPAD_SIZE, + [MHL_DCAP_INT_STAT_SIZE] = SII8620_INT_STAT_SIZE, + }; + static const u8 xdcap[MHL_XDC_SIZE] = { + [MHL_XDC_ECBUS_SPEEDS] = MHL_XDC_ECBUS_S_075 + | MHL_XDC_ECBUS_S_8BIT, + [MHL_XDC_TMDS_SPEEDS] = MHL_XDC_TMDS_150 + | MHL_XDC_TMDS_300 | MHL_XDC_TMDS_600, + [MHL_XDC_ECBUS_ROLES] = MHL_XDC_DEV_HOST, + [MHL_XDC_LOG_DEV_MAPX] = MHL_XDC_LD_PHONE, + }; + + sii8620_write_buf(ctx, REG_MHL_DEVCAP_0, devcap, ARRAY_SIZE(devcap)); + sii8620_write_buf(ctx, REG_MHL_EXTDEVCAP_0, xdcap, ARRAY_SIZE(xdcap)); +} + +static void sii8620_mhl_init(struct sii8620 *ctx) +{ + sii8620_write_seq_static(ctx, + REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K), + REG_CBUS_MSC_COMPAT_CTRL, + BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN, + ); + + sii8620_peer_specific_init(ctx); + + sii8620_disable_hpd(ctx); + + sii8620_write_seq_static(ctx, + REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO, + REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT + | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS, + REG_TMDS0_CCTRL1, 0x90, + REG_TMDS_CLK_EN, 0x01, + REG_TMDS_CH_EN, 0x11, + REG_BGR_BIAS, 0x87, + REG_ALICE0_ZONE_CTRL, 0xE8, + REG_ALICE0_MODE_CTRL, 0x04, + ); + sii8620_setbits(ctx, REG_LM_DDC, BIT_LM_DDC_SW_TPI_EN_DISABLED, 0); + sii8620_write_seq_static(ctx, + REG_TPI_HW_OPT3, 0x76, + REG_TMDS_CCTRL, BIT_TMDS_CCTRL_TMDS_OE, + REG_TPI_DTD_B2, 79, + ); + sii8620_set_dev_cap(ctx); + sii8620_write_seq_static(ctx, + REG_MDT_XMIT_TIMEOUT, 100, + REG_MDT_XMIT_CTRL, 0x03, + REG_MDT_XFIFO_STAT, 0x00, + REG_MDT_RCV_TIMEOUT, 100, + REG_CBUS_LINK_CTRL_8, 0x1D, + ); + + sii8620_start_gen2_write_burst(ctx); + sii8620_write_seq_static(ctx, + REG_BIST_CTRL, 0x00, + REG_COC_CTL1, 0x10, + REG_COC_CTL2, 0x18, + REG_COC_CTLF, 0x07, + REG_COC_CTL11, 0xF8, + REG_COC_CTL17, 0x61, + REG_COC_CTL18, 0x46, + REG_COC_CTL19, 0x15, + REG_COC_CTL1A, 0x01, + REG_MHL_COC_CTL3, BIT_MHL_COC_CTL3_COC_AECHO_EN, + REG_MHL_COC_CTL4, 0x2D, + REG_MHL_COC_CTL5, 0xF9, + REG_MSC_HEARTBEAT_CTRL, 0x27, + ); + sii8620_disable_gen2_write_burst(ctx); + + /* currently MHL3 is not supported, so we force version to 0 */ + sii8620_mt_write_stat(ctx, MHL_DST_REG(VERSION), 0); + sii8620_mt_write_stat(ctx, MHL_DST_REG(CONNECTED_RDY), + MHL_DST_CONN_DCAP_RDY | MHL_DST_CONN_XDEVCAPP_SUPP + | MHL_DST_CONN_POW_STAT); + sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE), MHL_INT_RC_DCAP_CHG); +} + +static void sii8620_set_mode(struct sii8620 *ctx, enum sii8620_mode mode) +{ + if (ctx->mode == mode) + return; + + ctx->mode = mode; + + switch (mode) { + case CM_MHL1: + sii8620_write_seq_static(ctx, + REG_CBUS_MSC_COMPAT_CTRL, 0x02, + REG_M3_CTRL, VAL_M3_CTRL_MHL1_2_VALUE, + REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 + | BIT_DPD_OSC_EN, + REG_COC_INTR_MASK, 0 + ); + break; + case CM_MHL3: + sii8620_write_seq_static(ctx, + REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE, + REG_COC_CTL0, 0x40, + REG_MHL_COC_CTL1, 0x07 + ); + break; + case CM_DISCONNECTED: + break; + default: + dev_err(ctx->dev, "%s mode %d not supported\n", __func__, mode); + break; + }; + + sii8620_set_auto_zone(ctx); + + if (mode != CM_MHL1) + return; + + sii8620_write_seq_static(ctx, + REG_MHL_DP_CTL0, 0xBC, + REG_MHL_DP_CTL1, 0xBB, + REG_MHL_DP_CTL3, 0x48, + REG_MHL_DP_CTL5, 0x39, + REG_MHL_DP_CTL2, 0x2A, + REG_MHL_DP_CTL6, 0x2A, + REG_MHL_DP_CTL7, 0x08 + ); +} + +static void sii8620_disconnect(struct sii8620 *ctx) +{ + sii8620_disable_gen2_write_burst(ctx); + sii8620_stop_video(ctx); + msleep(50); + sii8620_cbus_reset(ctx); + sii8620_set_mode(ctx, CM_DISCONNECTED); + sii8620_write_seq_static(ctx, + REG_COC_CTL0, 0x40, + REG_CBUS3_CNVT, 0x84, + REG_COC_CTL14, 0x00, + REG_COC_CTL0, 0x40, + REG_HRXCTRL3, 0x07, + REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X + | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL + | BIT_MHL_PLL_CTL0_ZONE_MASK_OE, + REG_MHL_DP_CTL0, BIT_MHL_DP_CTL0_DP_OE + | BIT_MHL_DP_CTL0_TX_OE_OVR, + REG_MHL_DP_CTL1, 0xBB, + REG_MHL_DP_CTL3, 0x48, + REG_MHL_DP_CTL5, 0x3F, + REG_MHL_DP_CTL2, 0x2F, + REG_MHL_DP_CTL6, 0x2A, + REG_MHL_DP_CTL7, 0x03 + ); + sii8620_disable_hpd(ctx); + sii8620_write_seq_static(ctx, + REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE, + REG_MHL_COC_CTL1, 0x07, + REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K), + REG_DISC_CTRL8, 0x00, + REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT + | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS, + REG_INT_CTRL, 0x00, + REG_MSC_HEARTBEAT_CTRL, 0x27, + REG_DISC_CTRL1, 0x25, + REG_CBUS_DISC_INTR0, (u8)~BIT_RGND_READY_INT, + REG_CBUS_DISC_INTR0_MASK, BIT_RGND_READY_INT, + REG_MDT_INT_1, 0xff, + REG_MDT_INT_1_MASK, 0x00, + REG_MDT_INT_0, 0xff, + REG_MDT_INT_0_MASK, 0x00, + REG_COC_INTR, 0xff, + REG_COC_INTR_MASK, 0x00, + REG_TRXINTH, 0xff, + REG_TRXINTMH, 0x00, + REG_CBUS_INT_0, 0xff, + REG_CBUS_INT_0_MASK, 0x00, + REG_CBUS_INT_1, 0xff, + REG_CBUS_INT_1_MASK, 0x00, + REG_EMSCINTR, 0xff, + REG_EMSCINTRMASK, 0x00, + REG_EMSCINTR1, 0xff, + REG_EMSCINTRMASK1, 0x00, + REG_INTR8, 0xff, + REG_INTR8_MASK, 0x00, + REG_TPI_INTR_ST0, 0xff, + REG_TPI_INTR_EN, 0x00, + REG_HDCP2X_INTR0, 0xff, + REG_HDCP2X_INTR0_MASK, 0x00, + REG_INTR9, 0xff, + REG_INTR9_MASK, 0x00, + REG_INTR3, 0xff, + REG_INTR3_MASK, 0x00, + REG_INTR5, 0xff, + REG_INTR5_MASK, 0x00, + REG_INTR2, 0xff, + REG_INTR2_MASK, 0x00, + ); + memset(ctx->stat, 0, sizeof(ctx->stat)); + memset(ctx->xstat, 0, sizeof(ctx->xstat)); + memset(ctx->devcap, 0, sizeof(ctx->devcap)); + memset(ctx->xdevcap, 0, sizeof(ctx->xdevcap)); + ctx->cbus_status = 0; + ctx->sink_type = SINK_NONE; + kfree(ctx->edid); + ctx->edid = NULL; + sii8620_mt_cleanup(ctx); +} + +static void sii8620_mhl_disconnected(struct sii8620 *ctx) +{ + sii8620_write_seq_static(ctx, + REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K), + REG_CBUS_MSC_COMPAT_CTRL, + BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN + ); + sii8620_disconnect(ctx); +} + +static void sii8620_irq_disc(struct sii8620 *ctx) +{ + u8 stat = sii8620_readb(ctx, REG_CBUS_DISC_INTR0); + + if (stat & VAL_CBUS_MHL_DISCON) + sii8620_mhl_disconnected(ctx); + + if (stat & BIT_RGND_READY_INT) { + u8 stat2 = sii8620_readb(ctx, REG_DISC_STAT2); + + if ((stat2 & MSK_DISC_STAT2_RGND) == VAL_RGND_1K) { + sii8620_mhl_discover(ctx); + } else { + sii8620_write_seq_static(ctx, + REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT + | BIT_DISC_CTRL9_NOMHL_EST + | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS, + REG_CBUS_DISC_INTR0_MASK, BIT_RGND_READY_INT + | BIT_CBUS_MHL3_DISCON_INT + | BIT_CBUS_MHL12_DISCON_INT + | BIT_NOT_MHL_EST_INT + ); + } + } + if (stat & BIT_MHL_EST_INT) + sii8620_mhl_init(ctx); + + sii8620_write(ctx, REG_CBUS_DISC_INTR0, stat); +} + +static void sii8620_irq_g2wb(struct sii8620 *ctx) +{ + u8 stat = sii8620_readb(ctx, REG_MDT_INT_0); + + if (stat & BIT_MDT_IDLE_AFTER_HAWB_DISABLE) + dev_dbg(ctx->dev, "HAWB idle\n"); + + sii8620_write(ctx, REG_MDT_INT_0, stat); +} + +static void sii8620_status_changed_dcap(struct sii8620 *ctx) +{ + if (ctx->stat[MHL_DST_CONNECTED_RDY] & MHL_DST_CONN_DCAP_RDY) { + sii8620_set_mode(ctx, CM_MHL1); + sii8620_peer_specific_init(ctx); + sii8620_write(ctx, REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE + | BIT_INTR9_EDID_DONE | BIT_INTR9_EDID_ERROR); + } +} + +static void sii8620_status_changed_path(struct sii8620 *ctx) +{ + if (ctx->stat[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED) { + sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), + MHL_DST_LM_CLK_MODE_NORMAL + | MHL_DST_LM_PATH_ENABLED); + sii8620_mt_read_devcap(ctx, false); + } else { + sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), + MHL_DST_LM_CLK_MODE_NORMAL); + } +} + +static void sii8620_msc_mr_write_stat(struct sii8620 *ctx) +{ + u8 st[MHL_DST_SIZE], xst[MHL_XDS_SIZE]; + + sii8620_read_buf(ctx, REG_MHL_STAT_0, st, MHL_DST_SIZE); + sii8620_read_buf(ctx, REG_MHL_EXTSTAT_0, xst, MHL_XDS_SIZE); + + sii8620_update_array(ctx->stat, st, MHL_DST_SIZE); + sii8620_update_array(ctx->xstat, xst, MHL_XDS_SIZE); + + if (st[MHL_DST_CONNECTED_RDY] & MHL_DST_CONN_DCAP_RDY) + sii8620_status_changed_dcap(ctx); + + if (st[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED) + sii8620_status_changed_path(ctx); +} + +static void sii8620_msc_mr_set_int(struct sii8620 *ctx) +{ + u8 ints[MHL_INT_SIZE]; + + sii8620_read_buf(ctx, REG_MHL_INT_0, ints, MHL_INT_SIZE); + sii8620_write_buf(ctx, REG_MHL_INT_0, ints, MHL_INT_SIZE); +} + +static struct sii8620_mt_msg *sii8620_msc_msg_first(struct sii8620 *ctx) +{ + struct device *dev = ctx->dev; + + if (list_empty(&ctx->mt_queue)) { + dev_err(dev, "unexpected MSC MT response\n"); + return NULL; + } + + return list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node); +} + +static void sii8620_msc_mt_done(struct sii8620 *ctx) +{ + struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx); + + if (!msg) + return; + + msg->ret = sii8620_readb(ctx, REG_MSC_MT_RCVD_DATA0); + ctx->mt_state = MT_STATE_DONE; +} + +static void sii8620_msc_mr_msc_msg(struct sii8620 *ctx) +{ + struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx); + u8 buf[2]; + + if (!msg) + return; + + sii8620_read_buf(ctx, REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA, buf, 2); + + switch (buf[0]) { + case MHL_MSC_MSG_RAPK: + msg->ret = buf[1]; + ctx->mt_state = MT_STATE_DONE; + break; + default: + dev_err(ctx->dev, "%s message type %d,%d not supported", + __func__, buf[0], buf[1]); + } +} + +static void sii8620_irq_msc(struct sii8620 *ctx) +{ + u8 stat = sii8620_readb(ctx, REG_CBUS_INT_0); + + if (stat & ~BIT_CBUS_HPD_CHG) + sii8620_write(ctx, REG_CBUS_INT_0, stat & ~BIT_CBUS_HPD_CHG); + + if (stat & BIT_CBUS_HPD_CHG) { + u8 cbus_stat = sii8620_readb(ctx, REG_CBUS_STATUS); + + if ((cbus_stat ^ ctx->cbus_status) & BIT_CBUS_STATUS_CBUS_HPD) { + sii8620_write(ctx, REG_CBUS_INT_0, BIT_CBUS_HPD_CHG); + } else { + stat ^= BIT_CBUS_STATUS_CBUS_HPD; + cbus_stat ^= BIT_CBUS_STATUS_CBUS_HPD; + } + ctx->cbus_status = cbus_stat; + } + + if (stat & BIT_CBUS_MSC_MR_WRITE_STAT) + sii8620_msc_mr_write_stat(ctx); + + if (stat & BIT_CBUS_MSC_MR_SET_INT) + sii8620_msc_mr_set_int(ctx); + + if (stat & BIT_CBUS_MSC_MT_DONE) + sii8620_msc_mt_done(ctx); + + if (stat & BIT_CBUS_MSC_MR_MSC_MSG) + sii8620_msc_mr_msc_msg(ctx); +} + +static void sii8620_irq_coc(struct sii8620 *ctx) +{ + u8 stat = sii8620_readb(ctx, REG_COC_INTR); + + sii8620_write(ctx, REG_COC_INTR, stat); +} + +static void sii8620_irq_merr(struct sii8620 *ctx) +{ + u8 stat = sii8620_readb(ctx, REG_CBUS_INT_1); + + sii8620_write(ctx, REG_CBUS_INT_1, stat); +} + +static void sii8620_irq_edid(struct sii8620 *ctx) +{ + u8 stat = sii8620_readb(ctx, REG_INTR9); + + sii8620_write(ctx, REG_INTR9, stat); + + if (stat & BIT_INTR9_DEVCAP_DONE) + ctx->mt_state = MT_STATE_DONE; +} + +static void sii8620_scdt_high(struct sii8620 *ctx) +{ + sii8620_write_seq_static(ctx, + REG_INTR8_MASK, BIT_CEA_NEW_AVI | BIT_CEA_NEW_VSI, + REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI, + ); +} + +static void sii8620_scdt_low(struct sii8620 *ctx) +{ + sii8620_write(ctx, REG_TMDS_CSTAT_P3, + BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS | + BIT_TMDS_CSTAT_P3_CLR_AVI); + + sii8620_stop_video(ctx); + + sii8620_write(ctx, REG_INTR8_MASK, 0); +} + +static void sii8620_irq_scdt(struct sii8620 *ctx) +{ + u8 stat = sii8620_readb(ctx, REG_INTR5); + + if (stat & BIT_INTR_SCDT_CHANGE) { + u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3); + + if (cstat & BIT_TMDS_CSTAT_P3_SCDT) + sii8620_scdt_high(ctx); + else + sii8620_scdt_low(ctx); + } + + sii8620_write(ctx, REG_INTR5, stat); +} + +static void sii8620_new_vsi(struct sii8620 *ctx) +{ + u8 vsif[11]; + + sii8620_write(ctx, REG_RX_HDMI_CTRL2, + VAL_RX_HDMI_CTRL2_DEFVAL | + BIT_RX_HDMI_CTRL2_VSI_MON_SEL_VSI); + sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, vsif, + ARRAY_SIZE(vsif)); +} + +static void sii8620_new_avi(struct sii8620 *ctx) +{ + sii8620_write(ctx, REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL); + sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, ctx->avif, + ARRAY_SIZE(ctx->avif)); +} + +static void sii8620_irq_infr(struct sii8620 *ctx) +{ + u8 stat = sii8620_readb(ctx, REG_INTR8) + & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI); + + sii8620_write(ctx, REG_INTR8, stat); + + if (stat & BIT_CEA_NEW_VSI) + sii8620_new_vsi(ctx); + + if (stat & BIT_CEA_NEW_AVI) + sii8620_new_avi(ctx); + + if (stat & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI)) + sii8620_start_video(ctx); +} + +/* endian agnostic, non-volatile version of test_bit */ +static bool sii8620_test_bit(unsigned int nr, const u8 *addr) +{ + return 1 & (addr[nr / BITS_PER_BYTE] >> (nr % BITS_PER_BYTE)); +} + +static irqreturn_t sii8620_irq_thread(int irq, void *data) +{ + static const struct { + int bit; + void (*handler)(struct sii8620 *ctx); + } irq_vec[] = { + { BIT_FAST_INTR_STAT_DISC, sii8620_irq_disc }, + { BIT_FAST_INTR_STAT_G2WB, sii8620_irq_g2wb }, + { BIT_FAST_INTR_STAT_COC, sii8620_irq_coc }, + { BIT_FAST_INTR_STAT_MSC, sii8620_irq_msc }, + { BIT_FAST_INTR_STAT_MERR, sii8620_irq_merr }, + { BIT_FAST_INTR_STAT_EDID, sii8620_irq_edid }, + { BIT_FAST_INTR_STAT_SCDT, sii8620_irq_scdt }, + { BIT_FAST_INTR_STAT_INFR, sii8620_irq_infr }, + }; + struct sii8620 *ctx = data; + u8 stats[LEN_FAST_INTR_STAT]; + int i, ret; + + mutex_lock(&ctx->lock); + + sii8620_read_buf(ctx, REG_FAST_INTR_STAT, stats, ARRAY_SIZE(stats)); + for (i = 0; i < ARRAY_SIZE(irq_vec); ++i) + if (sii8620_test_bit(irq_vec[i].bit, stats)) + irq_vec[i].handler(ctx); + + sii8620_mt_work(ctx); + + ret = sii8620_clear_error(ctx); + if (ret) { + dev_err(ctx->dev, "Error during IRQ handling, %d.\n", ret); + sii8620_mhl_disconnected(ctx); + } + mutex_unlock(&ctx->lock); + + return IRQ_HANDLED; +} + +static void sii8620_cable_in(struct sii8620 *ctx) +{ + struct device *dev = ctx->dev; + u8 ver[5]; + int ret; + + ret = sii8620_hw_on(ctx); + if (ret) { + dev_err(dev, "Error powering on, %d.\n", ret); + return; + } + sii8620_hw_reset(ctx); + + sii8620_read_buf(ctx, REG_VND_IDL, ver, ARRAY_SIZE(ver)); + ret = sii8620_clear_error(ctx); + if (ret) { + dev_err(dev, "Error accessing I2C bus, %d.\n", ret); + return; + } + + dev_info(dev, "ChipID %02x%02x:%02x%02x rev %02x.\n", ver[1], ver[0], + ver[3], ver[2], ver[4]); + + sii8620_write(ctx, REG_DPD, + BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 | BIT_DPD_OSC_EN); + + sii8620_xtal_set_rate(ctx); + sii8620_disconnect(ctx); + + sii8620_write_seq_static(ctx, + REG_MHL_CBUS_CTL0, VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONG + | VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_734, + REG_MHL_CBUS_CTL1, VAL_MHL_CBUS_CTL1_1115_OHM, + REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 | BIT_DPD_OSC_EN, + ); + + ret = sii8620_clear_error(ctx); + if (ret) { + dev_err(dev, "Error accessing I2C bus, %d.\n", ret); + return; + } + + enable_irq(to_i2c_client(ctx->dev)->irq); +} + +static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge) +{ + return container_of(bridge, struct sii8620, bridge); +} + +static bool sii8620_mode_fixup(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct sii8620 *ctx = bridge_to_sii8620(bridge); + bool ret = false; + int max_clock = 74250; + + mutex_lock(&ctx->lock); + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + goto out; + + if (ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL) + max_clock = 300000; + + ret = mode->clock <= max_clock; + +out: + mutex_unlock(&ctx->lock); + + return ret; +} + +static const struct drm_bridge_funcs sii8620_bridge_funcs = { + .mode_fixup = sii8620_mode_fixup, +}; + +static int sii8620_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct sii8620 *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->dev = dev; + mutex_init(&ctx->lock); + INIT_LIST_HEAD(&ctx->mt_queue); + + ctx->clk_xtal = devm_clk_get(dev, "xtal"); + if (IS_ERR(ctx->clk_xtal)) { + dev_err(dev, "failed to get xtal clock from DT\n"); + return PTR_ERR(ctx->clk_xtal); + } + + if (!client->irq) { + dev_err(dev, "no irq provided\n"); + return -EINVAL; + } + irq_set_status_flags(client->irq, IRQ_NOAUTOEN); + ret = devm_request_threaded_irq(dev, client->irq, NULL, + sii8620_irq_thread, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "sii8620", ctx); + + ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->gpio_reset)) { + dev_err(dev, "failed to get reset gpio from DT\n"); + return PTR_ERR(ctx->gpio_reset); + } + + ctx->supplies[0].supply = "cvcc10"; + ctx->supplies[1].supply = "iovcc18"; + ret = devm_regulator_bulk_get(dev, 2, ctx->supplies); + if (ret) + return ret; + + i2c_set_clientdata(client, ctx); + + ctx->bridge.funcs = &sii8620_bridge_funcs; + ctx->bridge.of_node = dev->of_node; + drm_bridge_add(&ctx->bridge); + + sii8620_cable_in(ctx); + + return 0; +} + +static int sii8620_remove(struct i2c_client *client) +{ + struct sii8620 *ctx = i2c_get_clientdata(client); + + disable_irq(to_i2c_client(ctx->dev)->irq); + drm_bridge_remove(&ctx->bridge); + sii8620_hw_off(ctx); + + return 0; +} + +static const struct of_device_id sii8620_dt_match[] = { + { .compatible = "sil,sii8620" }, + { }, +}; +MODULE_DEVICE_TABLE(of, sii8620_dt_match); + +static const struct i2c_device_id sii8620_id[] = { + { "sii8620", 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, sii8620_id); +static struct i2c_driver sii8620_driver = { + .driver = { + .name = "sii8620", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(sii8620_dt_match), + }, + .probe = sii8620_probe, + .remove = sii8620_remove, + .id_table = sii8620_id, +}; + +module_i2c_driver(sii8620_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/bridge/sil-sii8620.h b/drivers/gpu/drm/bridge/sil-sii8620.h new file mode 100644 index 000000000000..6ff616a4f6ce --- /dev/null +++ b/drivers/gpu/drm/bridge/sil-sii8620.h @@ -0,0 +1,1517 @@ +/* + * Registers of Silicon Image SiI8620 Mobile HD Transmitter + * + * Copyright (C) 2015, Samsung Electronics Co., Ltd. + * Andrzej Hajda + * + * Based on MHL driver for Android devices. + * Copyright (C) 2013-2014 Silicon Image, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __SIL_SII8620_H__ +#define __SIL_SII8620_H__ + +/* Vendor ID Low byte, default value: 0x01 */ +#define REG_VND_IDL 0x0000 + +/* Vendor ID High byte, default value: 0x00 */ +#define REG_VND_IDH 0x0001 + +/* Device ID Low byte, default value: 0x60 */ +#define REG_DEV_IDL 0x0002 + +/* Device ID High byte, default value: 0x86 */ +#define REG_DEV_IDH 0x0003 + +/* Device Revision, default value: 0x10 */ +#define REG_DEV_REV 0x0004 + +/* OTP DBYTE510, default value: 0x00 */ +#define REG_OTP_DBYTE510 0x0006 + +/* System Control #1, default value: 0x00 */ +#define REG_SYS_CTRL1 0x0008 +#define BIT_SYS_CTRL1_OTPVMUTEOVR_SET BIT(7) +#define BIT_SYS_CTRL1_VSYNCPIN BIT(6) +#define BIT_SYS_CTRL1_OTPADROPOVR_SET BIT(5) +#define BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD BIT(4) +#define BIT_SYS_CTRL1_OTP2XVOVR_EN BIT(3) +#define BIT_SYS_CTRL1_OTP2XAOVR_EN BIT(2) +#define BIT_SYS_CTRL1_TX_CTRL_HDMI BIT(1) +#define BIT_SYS_CTRL1_OTPAMUTEOVR_SET BIT(0) + +/* System Control DPD, default value: 0x90 */ +#define REG_DPD 0x000b +#define BIT_DPD_PWRON_PLL BIT(7) +#define BIT_DPD_PDNTX12 BIT(6) +#define BIT_DPD_PDNRX12 BIT(5) +#define BIT_DPD_OSC_EN BIT(4) +#define BIT_DPD_PWRON_HSIC BIT(3) +#define BIT_DPD_PDIDCK_N BIT(2) +#define BIT_DPD_PD_MHL_CLK_N BIT(1) + +/* Dual link Control, default value: 0x00 */ +#define REG_DCTL 0x000d +#define BIT_DCTL_TDM_LCLK_PHASE BIT(7) +#define BIT_DCTL_HSIC_CLK_PHASE BIT(6) +#define BIT_DCTL_CTS_TCK_PHASE BIT(5) +#define BIT_DCTL_EXT_DDC_SEL BIT(4) +#define BIT_DCTL_TRANSCODE BIT(3) +#define BIT_DCTL_HSIC_RX_STROBE_PHASE BIT(2) +#define BIT_DCTL_HSIC_TX_BIST_START_SEL BIT(1) +#define BIT_DCTL_TCLKNX_PHASE BIT(0) + +/* PWD Software Reset, default value: 0x20 */ +#define REG_PWD_SRST 0x000e +#define BIT_PWD_SRST_COC_DOC_RST BIT(7) +#define BIT_PWD_SRST_CBUS_RST_SW BIT(6) +#define BIT_PWD_SRST_CBUS_RST_SW_EN BIT(5) +#define BIT_PWD_SRST_MHLFIFO_RST BIT(4) +#define BIT_PWD_SRST_CBUS_RST BIT(3) +#define BIT_PWD_SRST_SW_RST_AUTO BIT(2) +#define BIT_PWD_SRST_HDCP2X_SW_RST BIT(1) +#define BIT_PWD_SRST_SW_RST BIT(0) + +/* AKSV_1, default value: 0x00 */ +#define REG_AKSV_1 0x001d + +/* Video H Resolution #1, default value: 0x00 */ +#define REG_H_RESL 0x003a + +/* Video Mode, default value: 0x00 */ +#define REG_VID_MODE 0x004a +#define BIT_VID_MODE_M1080P BIT(6) + +/* Video Input Mode, default value: 0xc0 */ +#define REG_VID_OVRRD 0x0051 +#define BIT_VID_OVRRD_PP_AUTO_DISABLE BIT(7) +#define BIT_VID_OVRRD_M1080P_OVRRD BIT(6) +#define BIT_VID_OVRRD_MINIVSYNC_ON BIT(5) +#define BIT_VID_OVRRD_3DCONV_EN_FRAME_PACK BIT(4) +#define BIT_VID_OVRRD_ENABLE_AUTO_PATH_EN BIT(3) +#define BIT_VID_OVRRD_ENRGB2YCBCR_OVRRD BIT(2) +#define BIT_VID_OVRRD_ENDOWNSAMPLE_OVRRD BIT(0) + +/* I2C Address reassignment, default value: 0x00 */ +#define REG_PAGE_MHLSPEC_ADDR 0x0057 +#define REG_PAGE7_ADDR 0x0058 +#define REG_PAGE8_ADDR 0x005c + +/* Fast Interrupt Status, default value: 0x00 */ +#define REG_FAST_INTR_STAT 0x005f +#define LEN_FAST_INTR_STAT 7 +#define BIT_FAST_INTR_STAT_TIMR 8 +#define BIT_FAST_INTR_STAT_INT2 9 +#define BIT_FAST_INTR_STAT_DDC 10 +#define BIT_FAST_INTR_STAT_SCDT 11 +#define BIT_FAST_INTR_STAT_INFR 13 +#define BIT_FAST_INTR_STAT_EDID 14 +#define BIT_FAST_INTR_STAT_HDCP 15 +#define BIT_FAST_INTR_STAT_MSC 16 +#define BIT_FAST_INTR_STAT_MERR 17 +#define BIT_FAST_INTR_STAT_G2WB 18 +#define BIT_FAST_INTR_STAT_G2WB_ERR 19 +#define BIT_FAST_INTR_STAT_DISC 28 +#define BIT_FAST_INTR_STAT_BLOCK 30 +#define BIT_FAST_INTR_STAT_LTRN 31 +#define BIT_FAST_INTR_STAT_HDCP2 32 +#define BIT_FAST_INTR_STAT_TDM 42 +#define BIT_FAST_INTR_STAT_COC 51 + +/* GPIO Control, default value: 0x15 */ +#define REG_GPIO_CTRL1 0x006e +#define BIT_CTRL1_GPIO_I_8 BIT(5) +#define BIT_CTRL1_GPIO_OEN_8 BIT(4) +#define BIT_CTRL1_GPIO_I_7 BIT(3) +#define BIT_CTRL1_GPIO_OEN_7 BIT(2) +#define BIT_CTRL1_GPIO_I_6 BIT(1) +#define BIT_CTRL1_GPIO_OEN_6 BIT(0) + +/* Interrupt Control, default value: 0x06 */ +#define REG_INT_CTRL 0x006f +#define BIT_INT_CTRL_SOFTWARE_WP BIT(7) +#define BIT_INT_CTRL_INTR_OD BIT(2) +#define BIT_INT_CTRL_INTR_POLARITY BIT(1) + +/* Interrupt State, default value: 0x00 */ +#define REG_INTR_STATE 0x0070 +#define BIT_INTR_STATE_INTR_STATE BIT(0) + +/* Interrupt Source #1, default value: 0x00 */ +#define REG_INTR1 0x0071 + +/* Interrupt Source #2, default value: 0x00 */ +#define REG_INTR2 0x0072 + +/* Interrupt Source #3, default value: 0x01 */ +#define REG_INTR3 0x0073 +#define BIT_DDC_CMD_DONE BIT(3) + +/* Interrupt Source #5, default value: 0x00 */ +#define REG_INTR5 0x0074 + +/* Interrupt #1 Mask, default value: 0x00 */ +#define REG_INTR1_MASK 0x0075 + +/* Interrupt #2 Mask, default value: 0x00 */ +#define REG_INTR2_MASK 0x0076 + +/* Interrupt #3 Mask, default value: 0x00 */ +#define REG_INTR3_MASK 0x0077 + +/* Interrupt #5 Mask, default value: 0x00 */ +#define REG_INTR5_MASK 0x0078 +#define BIT_INTR_SCDT_CHANGE BIT(0) + +/* Hot Plug Connection Control, default value: 0x45 */ +#define REG_HPD_CTRL 0x0079 +#define BIT_HPD_CTRL_HPD_DS_SIGNAL BIT(7) +#define BIT_HPD_CTRL_HPD_OUT_OD_EN BIT(6) +#define BIT_HPD_CTRL_HPD_HIGH BIT(5) +#define BIT_HPD_CTRL_HPD_OUT_OVR_EN BIT(4) +#define BIT_HPD_CTRL_GPIO_I_1 BIT(3) +#define BIT_HPD_CTRL_GPIO_OEN_1 BIT(2) +#define BIT_HPD_CTRL_GPIO_I_0 BIT(1) +#define BIT_HPD_CTRL_GPIO_OEN_0 BIT(0) + +/* GPIO Control, default value: 0x55 */ +#define REG_GPIO_CTRL 0x007a +#define BIT_CTRL_GPIO_I_5 BIT(7) +#define BIT_CTRL_GPIO_OEN_5 BIT(6) +#define BIT_CTRL_GPIO_I_4 BIT(5) +#define BIT_CTRL_GPIO_OEN_4 BIT(4) +#define BIT_CTRL_GPIO_I_3 BIT(3) +#define BIT_CTRL_GPIO_OEN_3 BIT(2) +#define BIT_CTRL_GPIO_I_2 BIT(1) +#define BIT_CTRL_GPIO_OEN_2 BIT(0) + +/* Interrupt Source 7, default value: 0x00 */ +#define REG_INTR7 0x007b + +/* Interrupt Source 8, default value: 0x00 */ +#define REG_INTR8 0x007c + +/* Interrupt #7 Mask, default value: 0x00 */ +#define REG_INTR7_MASK 0x007d + +/* Interrupt #8 Mask, default value: 0x00 */ +#define REG_INTR8_MASK 0x007e +#define BIT_CEA_NEW_VSI BIT(2) +#define BIT_CEA_NEW_AVI BIT(1) + +/* IEEE, default value: 0x10 */ +#define REG_TMDS_CCTRL 0x0080 +#define BIT_TMDS_CCTRL_TMDS_OE BIT(4) + +/* TMDS Control #4, default value: 0x02 */ +#define REG_TMDS_CTRL4 0x0085 +#define BIT_TMDS_CTRL4_SCDT_CKDT_SEL BIT(1) +#define BIT_TMDS_CTRL4_TX_EN_BY_SCDT BIT(0) + +/* BIST CNTL, default value: 0x00 */ +#define REG_BIST_CTRL 0x00bb +#define BIT_RXBIST_VGB_EN BIT(7) +#define BIT_TXBIST_VGB_EN BIT(6) +#define BIT_BIST_START_SEL BIT(5) +#define BIT_BIST_START_BIT BIT(4) +#define BIT_BIST_ALWAYS_ON BIT(3) +#define BIT_BIST_TRANS BIT(2) +#define BIT_BIST_RESET BIT(1) +#define BIT_BIST_EN BIT(0) + +/* BIST DURATION0, default value: 0x00 */ +#define REG_BIST_TEST_SEL 0x00bd +#define MSK_BIST_TEST_SEL_BIST_PATT_SEL 0x0f + +/* BIST VIDEO_MODE, default value: 0x00 */ +#define REG_BIST_VIDEO_MODE 0x00be +#define MSK_BIST_VIDEO_MODE_BIST_VIDEO_MODE_3_0 0x0f + +/* BIST DURATION0, default value: 0x00 */ +#define REG_BIST_DURATION_0 0x00bf + +/* BIST DURATION1, default value: 0x00 */ +#define REG_BIST_DURATION_1 0x00c0 + +/* BIST DURATION2, default value: 0x00 */ +#define REG_BIST_DURATION_2 0x00c1 + +/* BIST 8BIT_PATTERN, default value: 0x00 */ +#define REG_BIST_8BIT_PATTERN 0x00c2 + +/* LM DDC, default value: 0x80 */ +#define REG_LM_DDC 0x00c7 +#define BIT_LM_DDC_SW_TPI_EN_DISABLED BIT(7) + +#define BIT_LM_DDC_VIDEO_MUTE_EN BIT(5) +#define BIT_LM_DDC_DDC_TPI_SW BIT(2) +#define BIT_LM_DDC_DDC_GRANT BIT(1) +#define BIT_LM_DDC_DDC_GPU_REQUEST BIT(0) + +/* DDC I2C Manual, default value: 0x03 */ +#define REG_DDC_MANUAL 0x00ec +#define BIT_DDC_MANUAL_MAN_DDC BIT(7) +#define BIT_DDC_MANUAL_VP_SEL BIT(6) +#define BIT_DDC_MANUAL_DSDA BIT(5) +#define BIT_DDC_MANUAL_DSCL BIT(4) +#define BIT_DDC_MANUAL_GCP_HW_CTL_EN BIT(3) +#define BIT_DDC_MANUAL_DDCM_ABORT_WP BIT(2) +#define BIT_DDC_MANUAL_IO_DSDA BIT(1) +#define BIT_DDC_MANUAL_IO_DSCL BIT(0) + +/* DDC I2C Target Slave Address, default value: 0x00 */ +#define REG_DDC_ADDR 0x00ed +#define MSK_DDC_ADDR_DDC_ADDR 0xfe + +/* DDC I2C Target Segment Address, default value: 0x00 */ +#define REG_DDC_SEGM 0x00ee + +/* DDC I2C Target Offset Address, default value: 0x00 */ +#define REG_DDC_OFFSET 0x00ef + +/* DDC I2C Data In count #1, default value: 0x00 */ +#define REG_DDC_DIN_CNT1 0x00f0 + +/* DDC I2C Data In count #2, default value: 0x00 */ +#define REG_DDC_DIN_CNT2 0x00f1 +#define MSK_DDC_DIN_CNT2_DDC_DIN_CNT_9_8 0x03 + +/* DDC I2C Status, default value: 0x04 */ +#define REG_DDC_STATUS 0x00f2 +#define BIT_DDC_STATUS_DDC_BUS_LOW BIT(6) +#define BIT_DDC_STATUS_DDC_NO_ACK BIT(5) +#define BIT_DDC_STATUS_DDC_I2C_IN_PROG BIT(4) +#define BIT_DDC_STATUS_DDC_FIFO_FULL BIT(3) +#define BIT_DDC_STATUS_DDC_FIFO_EMPTY BIT(2) +#define BIT_DDC_STATUS_DDC_FIFO_READ_IN_SUE BIT(1) +#define BIT_DDC_STATUS_DDC_FIFO_WRITE_IN_USE BIT(0) + +/* DDC I2C Command, default value: 0x70 */ +#define REG_DDC_CMD 0x00f3 +#define BIT_DDC_CMD_HDCP_DDC_EN BIT(6) +#define BIT_DDC_CMD_SDA_DEL_EN BIT(5) +#define BIT_DDC_CMD_DDC_FLT_EN BIT(4) + +#define MSK_DDC_CMD_DDC_CMD 0x0f +#define VAL_DDC_CMD_ENH_DDC_READ_NO_ACK 0x04 +#define VAL_DDC_CMD_DDC_CMD_CLEAR_FIFO 0x09 +#define VAL_DDC_CMD_DDC_CMD_ABORT 0x0f + +/* DDC I2C FIFO Data In/Out, default value: 0x00 */ +#define REG_DDC_DATA 0x00f4 + +/* DDC I2C Data Out Counter, default value: 0x00 */ +#define REG_DDC_DOUT_CNT 0x00f5 +#define BIT_DDC_DOUT_CNT_DDC_DELAY_CNT_8 BIT(7) +#define MSK_DDC_DOUT_CNT_DDC_DATA_OUT_CNT 0x1f + +/* DDC I2C Delay Count, default value: 0x14 */ +#define REG_DDC_DELAY_CNT 0x00f6 + +/* Test Control, default value: 0x80 */ +#define REG_TEST_TXCTRL 0x00f7 +#define BIT_TEST_TXCTRL_RCLK_REF_SEL BIT(7) +#define BIT_TEST_TXCTRL_PCLK_REF_SEL BIT(6) +#define MSK_TEST_TXCTRL_BYPASS_PLL_CLK 0x3c +#define BIT_TEST_TXCTRL_HDMI_MODE BIT(1) +#define BIT_TEST_TXCTRL_TST_PLLCK BIT(0) + +/* CBUS Address, default value: 0x00 */ +#define REG_PAGE_CBUS_ADDR 0x00f8 + +/* I2C Device Address re-assignment */ +#define REG_PAGE1_ADDR 0x00fc +#define REG_PAGE2_ADDR 0x00fd +#define REG_PAGE3_ADDR 0x00fe +#define REG_HW_TPI_ADDR 0x00ff + +/* USBT CTRL0, default value: 0x00 */ +#define REG_UTSRST 0x0100 +#define BIT_UTSRST_FC_SRST BIT(5) +#define BIT_UTSRST_KEEPER_SRST BIT(4) +#define BIT_UTSRST_HTX_SRST BIT(3) +#define BIT_UTSRST_TRX_SRST BIT(2) +#define BIT_UTSRST_TTX_SRST BIT(1) +#define BIT_UTSRST_HRX_SRST BIT(0) + +/* HSIC RX Control3, default value: 0x07 */ +#define REG_HRXCTRL3 0x0104 +#define MSK_HRXCTRL3_HRX_AFFCTRL 0xf0 +#define BIT_HRXCTRL3_HRX_OUT_EN BIT(2) +#define BIT_HRXCTRL3_STATUS_EN BIT(1) +#define BIT_HRXCTRL3_HRX_STAY_RESET BIT(0) + +/* HSIC RX INT Registers */ +#define REG_HRXINTL 0x0111 +#define REG_HRXINTH 0x0112 + +/* TDM TX NUMBITS, default value: 0x0c */ +#define REG_TTXNUMB 0x0116 +#define MSK_TTXNUMB_TTX_AFFCTRL_3_0 0xf0 +#define BIT_TTXNUMB_TTX_COM1_AT_SYNC_WAIT BIT(3) +#define MSK_TTXNUMB_TTX_NUMBPS_2_0 0x07 + +/* TDM TX NUMSPISYM, default value: 0x04 */ +#define REG_TTXSPINUMS 0x0117 + +/* TDM TX NUMHSICSYM, default value: 0x14 */ +#define REG_TTXHSICNUMS 0x0118 + +/* TDM TX NUMTOTSYM, default value: 0x18 */ +#define REG_TTXTOTNUMS 0x0119 + +/* TDM TX INT Low, default value: 0x00 */ +#define REG_TTXINTL 0x0136 +#define BIT_TTXINTL_TTX_INTR7 BIT(7) +#define BIT_TTXINTL_TTX_INTR6 BIT(6) +#define BIT_TTXINTL_TTX_INTR5 BIT(5) +#define BIT_TTXINTL_TTX_INTR4 BIT(4) +#define BIT_TTXINTL_TTX_INTR3 BIT(3) +#define BIT_TTXINTL_TTX_INTR2 BIT(2) +#define BIT_TTXINTL_TTX_INTR1 BIT(1) +#define BIT_TTXINTL_TTX_INTR0 BIT(0) + +/* TDM TX INT High, default value: 0x00 */ +#define REG_TTXINTH 0x0137 +#define BIT_TTXINTH_TTX_INTR15 BIT(7) +#define BIT_TTXINTH_TTX_INTR14 BIT(6) +#define BIT_TTXINTH_TTX_INTR13 BIT(5) +#define BIT_TTXINTH_TTX_INTR12 BIT(4) +#define BIT_TTXINTH_TTX_INTR11 BIT(3) +#define BIT_TTXINTH_TTX_INTR10 BIT(2) +#define BIT_TTXINTH_TTX_INTR9 BIT(1) +#define BIT_TTXINTH_TTX_INTR8 BIT(0) + +/* TDM RX Control, default value: 0x1c */ +#define REG_TRXCTRL 0x013b +#define BIT_TRXCTRL_TRX_CLR_WVALLOW BIT(4) +#define BIT_TRXCTRL_TRX_FROM_SE_COC BIT(3) +#define MSK_TRXCTRL_TRX_NUMBPS_2_0 0x07 + +/* TDM RX NUMSPISYM, default value: 0x04 */ +#define REG_TRXSPINUMS 0x013c + +/* TDM RX NUMHSICSYM, default value: 0x14 */ +#define REG_TRXHSICNUMS 0x013d + +/* TDM RX NUMTOTSYM, default value: 0x18 */ +#define REG_TRXTOTNUMS 0x013e + +/* TDM RX Status 2nd, default value: 0x00 */ +#define REG_TRXSTA2 0x015c + +/* TDM RX INT Low, default value: 0x00 */ +#define REG_TRXINTL 0x0163 + +/* TDM RX INT High, default value: 0x00 */ +#define REG_TRXINTH 0x0164 + +/* TDM RX INTMASK High, default value: 0x00 */ +#define REG_TRXINTMH 0x0166 + +/* HSIC TX CRTL, default value: 0x00 */ +#define REG_HTXCTRL 0x0169 +#define BIT_HTXCTRL_HTX_ALLSBE_SOP BIT(4) +#define BIT_HTXCTRL_HTX_RGDINV_USB BIT(3) +#define BIT_HTXCTRL_HTX_RSPTDM_BUSY BIT(2) +#define BIT_HTXCTRL_HTX_DRVCONN1 BIT(1) +#define BIT_HTXCTRL_HTX_DRVRST1 BIT(0) + +/* HSIC TX INT Low, default value: 0x00 */ +#define REG_HTXINTL 0x017d + +/* HSIC TX INT High, default value: 0x00 */ +#define REG_HTXINTH 0x017e + +/* HSIC Keeper, default value: 0x00 */ +#define REG_KEEPER 0x0181 +#define MSK_KEEPER_KEEPER_MODE_1_0 0x03 + +/* HSIC Flow Control General, default value: 0x02 */ +#define REG_FCGC 0x0183 +#define BIT_FCGC_HSIC_FC_HOSTMODE BIT(1) +#define BIT_FCGC_HSIC_FC_ENABLE BIT(0) + +/* HSIC Flow Control CTR13, default value: 0xfc */ +#define REG_FCCTR13 0x0191 + +/* HSIC Flow Control CTR14, default value: 0xff */ +#define REG_FCCTR14 0x0192 + +/* HSIC Flow Control CTR15, default value: 0xff */ +#define REG_FCCTR15 0x0193 + +/* HSIC Flow Control CTR50, default value: 0x03 */ +#define REG_FCCTR50 0x01b6 + +/* HSIC Flow Control INTR0, default value: 0x00 */ +#define REG_FCINTR0 0x01ec +#define REG_FCINTR1 0x01ed +#define REG_FCINTR2 0x01ee +#define REG_FCINTR3 0x01ef +#define REG_FCINTR4 0x01f0 +#define REG_FCINTR5 0x01f1 +#define REG_FCINTR6 0x01f2 +#define REG_FCINTR7 0x01f3 + +/* TDM Low Latency, default value: 0x20 */ +#define REG_TDMLLCTL 0x01fc +#define MSK_TDMLLCTL_TRX_LL_SEL_MANUAL 0xc0 +#define MSK_TDMLLCTL_TRX_LL_SEL_MODE 0x30 +#define MSK_TDMLLCTL_TTX_LL_SEL_MANUAL 0x0c +#define BIT_TDMLLCTL_TTX_LL_TIE_LOW BIT(1) +#define BIT_TDMLLCTL_TTX_LL_SEL_MODE BIT(0) + +/* TMDS 0 Clock Control, default value: 0x10 */ +#define REG_TMDS0_CCTRL1 0x0210 +#define MSK_TMDS0_CCTRL1_TEST_SEL 0xc0 +#define MSK_TMDS0_CCTRL1_CLK1X_CTL 0x30 + +/* TMDS Clock Enable, default value: 0x00 */ +#define REG_TMDS_CLK_EN 0x0211 +#define BIT_TMDS_CLK_EN_CLK_EN BIT(0) + +/* TMDS Channel Enable, default value: 0x00 */ +#define REG_TMDS_CH_EN 0x0212 +#define BIT_TMDS_CH_EN_CH0_EN BIT(4) +#define BIT_TMDS_CH_EN_CH12_EN BIT(0) + +/* BGR_BIAS, default value: 0x07 */ +#define REG_BGR_BIAS 0x0215 +#define BIT_BGR_BIAS_BGR_EN BIT(7) +#define MSK_BGR_BIAS_BIAS_BGR_D 0x0f + +/* TMDS 0 Digital I2C BW, default value: 0x0a */ +#define REG_ALICE0_BW_I2C 0x0231 + +/* TMDS 0 Digital Zone Control, default value: 0xe0 */ +#define REG_ALICE0_ZONE_CTRL 0x024c +#define BIT_ALICE0_ZONE_CTRL_ICRST_N BIT(7) +#define BIT_ALICE0_ZONE_CTRL_USE_INT_DIV20 BIT(6) +#define MSK_ALICE0_ZONE_CTRL_SZONE_I2C 0x30 +#define MSK_ALICE0_ZONE_CTRL_ZONE_CTRL 0x0f + +/* TMDS 0 Digital PLL Mode Control, default value: 0x00 */ +#define REG_ALICE0_MODE_CTRL 0x024d +#define MSK_ALICE0_MODE_CTRL_PLL_MODE_I2C 0x0c +#define MSK_ALICE0_MODE_CTRL_DIV20_CTRL 0x03 + +/* MHL Tx Control 6th, default value: 0xa0 */ +#define REG_MHLTX_CTL6 0x0285 +#define MSK_MHLTX_CTL6_EMI_SEL 0xe0 +#define MSK_MHLTX_CTL6_TX_CLK_SHAPE_9_8 0x03 + +/* Packet Filter0, default value: 0x00 */ +#define REG_PKT_FILTER_0 0x0290 +#define BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT BIT(7) +#define BIT_PKT_FILTER_0_DROP_CEA_CP_PKT BIT(6) +#define BIT_PKT_FILTER_0_DROP_MPEG_PKT BIT(5) +#define BIT_PKT_FILTER_0_DROP_SPIF_PKT BIT(4) +#define BIT_PKT_FILTER_0_DROP_AIF_PKT BIT(3) +#define BIT_PKT_FILTER_0_DROP_AVI_PKT BIT(2) +#define BIT_PKT_FILTER_0_DROP_CTS_PKT BIT(1) +#define BIT_PKT_FILTER_0_DROP_GCP_PKT BIT(0) + +/* Packet Filter1, default value: 0x00 */ +#define REG_PKT_FILTER_1 0x0291 +#define BIT_PKT_FILTER_1_VSI_OVERRIDE_DIS BIT(7) +#define BIT_PKT_FILTER_1_AVI_OVERRIDE_DIS BIT(6) +#define BIT_PKT_FILTER_1_DROP_AUDIO_PKT BIT(3) +#define BIT_PKT_FILTER_1_DROP_GEN2_PKT BIT(2) +#define BIT_PKT_FILTER_1_DROP_GEN_PKT BIT(1) +#define BIT_PKT_FILTER_1_DROP_VSIF_PKT BIT(0) + +/* TMDS Clock Status, default value: 0x10 */ +#define REG_TMDS_CSTAT_P3 0x02a0 +#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_CLR_MUTE BIT(7) +#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_SET_MUTE BIT(6) +#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_NEW_CP BIT(5) +#define BIT_TMDS_CSTAT_P3_CLR_AVI BIT(3) +#define BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS BIT(2) +#define BIT_TMDS_CSTAT_P3_SCDT BIT(1) +#define BIT_TMDS_CSTAT_P3_CKDT BIT(0) + +/* RX_HDMI Control, default value: 0x10 */ +#define REG_RX_HDMI_CTRL0 0x02a1 +#define BIT_RX_HDMI_CTRL0_BYP_DVIFILT_SYNC BIT(5) +#define BIT_RX_HDMI_CTRL0_HDMI_MODE_EN_ITSELF_CLR BIT(4) +#define BIT_RX_HDMI_CTRL0_HDMI_MODE_SW_VALUE BIT(3) +#define BIT_RX_HDMI_CTRL0_HDMI_MODE_OVERWRITE BIT(2) +#define BIT_RX_HDMI_CTRL0_RX_HDMI_HDMI_MODE_EN BIT(1) +#define BIT_RX_HDMI_CTRL0_RX_HDMI_HDMI_MODE BIT(0) + +/* RX_HDMI Control, default value: 0x38 */ +#define REG_RX_HDMI_CTRL2 0x02a3 +#define MSK_RX_HDMI_CTRL2_IDLE_CNT 0xf0 +#define VAL_RX_HDMI_CTRL2_IDLE_CNT(n) ((n) << 4) +#define BIT_RX_HDMI_CTRL2_USE_AV_MUTE BIT(3) +#define BIT_RX_HDMI_CTRL2_VSI_MON_SEL_VSI BIT(0) + +/* RX_HDMI Control, default value: 0x0f */ +#define REG_RX_HDMI_CTRL3 0x02a4 +#define MSK_RX_HDMI_CTRL3_PP_MODE_CLK_EN 0x0f + +/* rx_hdmi Clear Buffer, default value: 0x00 */ +#define REG_RX_HDMI_CLR_BUFFER 0x02ac +#define MSK_RX_HDMI_CLR_BUFFER_AIF4VSI_CMP 0xc0 +#define BIT_RX_HDMI_CLR_BUFFER_USE_AIF4VSI BIT(5) +#define BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_W_AVI BIT(4) +#define BIT_RX_HDMI_CLR_BUFFER_VSI_IEEE_ID_CHK_EN BIT(3) +#define BIT_RX_HDMI_CLR_BUFFER_SWAP_VSI_IEEE_ID BIT(2) +#define BIT_RX_HDMI_CLR_BUFFER_AIF_CLR_EN BIT(1) +#define BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_EN BIT(0) + +/* RX_HDMI VSI Header1, default value: 0x00 */ +#define REG_RX_HDMI_MON_PKT_HEADER1 0x02b8 + +/* RX_HDMI VSI MHL Monitor, default value: 0x3c */ +#define REG_RX_HDMI_VSIF_MHL_MON 0x02d7 + +#define MSK_RX_HDMI_VSIF_MHL_MON_RX_HDMI_MHL_3D_FORMAT 0x3c +#define MSK_RX_HDMI_VSIF_MHL_MON_RX_HDMI_MHL_VID_FORMAT 0x03 + +/* Interrupt Source 9, default value: 0x00 */ +#define REG_INTR9 0x02e0 +#define BIT_INTR9_EDID_ERROR BIT(6) +#define BIT_INTR9_EDID_DONE BIT(5) +#define BIT_INTR9_DEVCAP_DONE BIT(4) + +/* Interrupt 9 Mask, default value: 0x00 */ +#define REG_INTR9_MASK 0x02e1 + +/* TPI CBUS Start, default value: 0x00 */ +#define REG_TPI_CBUS_START 0x02e2 +#define BIT_TPI_CBUS_START_RCP_REQ_START BIT(7) +#define BIT_TPI_CBUS_START_RCPK_REPLY_START BIT(6) +#define BIT_TPI_CBUS_START_RCPE_REPLY_START BIT(5) +#define BIT_TPI_CBUS_START_PUT_LINK_MODE_START BIT(4) +#define BIT_TPI_CBUS_START_PUT_DCAPCHG_START BIT(3) +#define BIT_TPI_CBUS_START_PUT_DCAPRDY_START BIT(2) +#define BIT_TPI_CBUS_START_GET_EDID_START_0 BIT(1) +#define BIT_TPI_CBUS_START_GET_DEVCAP_START BIT(0) + +/* EDID Control, default value: 0x10 */ +#define REG_EDID_CTRL 0x02e3 +#define BIT_EDID_CTRL_EDID_PRIME_VALID BIT(7) +#define BIT_EDID_CTRL_XDEVCAP_EN BIT(6) +#define BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP BIT(5) +#define BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO BIT(4) +#define BIT_EDID_CTRL_EDID_FIFO_ACCESS_ALWAYS_EN BIT(3) +#define BIT_EDID_CTRL_EDID_FIFO_BLOCK_SEL BIT(2) +#define BIT_EDID_CTRL_INVALID_BKSV BIT(1) +#define BIT_EDID_CTRL_EDID_MODE_EN BIT(0) + +/* EDID FIFO Addr, default value: 0x00 */ +#define REG_EDID_FIFO_ADDR 0x02e9 + +/* EDID FIFO Write Data, default value: 0x00 */ +#define REG_EDID_FIFO_WR_DATA 0x02ea + +/* EDID/DEVCAP FIFO Internal Addr, default value: 0x00 */ +#define REG_EDID_FIFO_ADDR_MON 0x02eb + +/* EDID FIFO Read Data, default value: 0x00 */ +#define REG_EDID_FIFO_RD_DATA 0x02ec + +/* EDID DDC Segment Pointer, default value: 0x00 */ +#define REG_EDID_START_EXT 0x02ed + +/* TX IP BIST CNTL and Status, default value: 0x00 */ +#define REG_TX_IP_BIST_CNTLSTA 0x02f2 +#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_QUARTER_CLK_SEL BIT(6) +#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_DONE BIT(5) +#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_ON BIT(4) +#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_RUN BIT(3) +#define BIT_TX_IP_BIST_CNTLSTA_TXCLK_HALF_SEL BIT(2) +#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_EN BIT(1) +#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_SEL BIT(0) + +/* TX IP BIST INST LOW, default value: 0x00 */ +#define REG_TX_IP_BIST_INST_LOW 0x02f3 +#define REG_TX_IP_BIST_INST_HIGH 0x02f4 + +/* TX IP BIST PATTERN LOW, default value: 0x00 */ +#define REG_TX_IP_BIST_PAT_LOW 0x02f5 +#define REG_TX_IP_BIST_PAT_HIGH 0x02f6 + +/* TX IP BIST CONFIGURE LOW, default value: 0x00 */ +#define REG_TX_IP_BIST_CONF_LOW 0x02f7 +#define REG_TX_IP_BIST_CONF_HIGH 0x02f8 + +/* E-MSC General Control, default value: 0x80 */ +#define REG_GENCTL 0x0300 +#define BIT_GENCTL_SPEC_TRANS_DIS BIT(7) +#define BIT_GENCTL_DIS_XMIT_ERR_STATE BIT(6) +#define BIT_GENCTL_SPI_MISO_EDGE BIT(5) +#define BIT_GENCTL_SPI_MOSI_EDGE BIT(4) +#define BIT_GENCTL_CLR_EMSC_RFIFO BIT(3) +#define BIT_GENCTL_CLR_EMSC_XFIFO BIT(2) +#define BIT_GENCTL_START_TRAIN_SEQ BIT(1) +#define BIT_GENCTL_EMSC_EN BIT(0) + +/* E-MSC Comma ErrorCNT, default value: 0x03 */ +#define REG_COMMECNT 0x0305 +#define BIT_COMMECNT_I2C_TO_EMSC_EN BIT(7) +#define MSK_COMMECNT_COMMA_CHAR_ERR_CNT 0x0f + +/* E-MSC RFIFO ByteCnt, default value: 0x00 */ +#define REG_EMSCRFIFOBCNTL 0x031a +#define REG_EMSCRFIFOBCNTH 0x031b + +/* SPI Burst Cnt Status, default value: 0x00 */ +#define REG_SPIBURSTCNT 0x031e + +/* SPI Burst Status and SWRST, default value: 0x00 */ +#define REG_SPIBURSTSTAT 0x0322 +#define BIT_SPIBURSTSTAT_SPI_HDCPRST BIT(7) +#define BIT_SPIBURSTSTAT_SPI_CBUSRST BIT(6) +#define BIT_SPIBURSTSTAT_SPI_SRST BIT(5) +#define BIT_SPIBURSTSTAT_EMSC_NORMAL_MODE BIT(0) + +/* E-MSC 1st Interrupt, default value: 0x00 */ +#define REG_EMSCINTR 0x0323 +#define BIT_EMSCINTR_EMSC_XFIFO_EMPTY BIT(7) +#define BIT_EMSCINTR_EMSC_XMIT_ACK_TOUT BIT(6) +#define BIT_EMSCINTR_EMSC_RFIFO_READ_ERR BIT(5) +#define BIT_EMSCINTR_EMSC_XFIFO_WRITE_ERR BIT(4) +#define BIT_EMSCINTR_EMSC_COMMA_CHAR_ERR BIT(3) +#define BIT_EMSCINTR_EMSC_XMIT_DONE BIT(2) +#define BIT_EMSCINTR_EMSC_XMIT_GNT_TOUT BIT(1) +#define BIT_EMSCINTR_SPI_DVLD BIT(0) + +/* E-MSC Interrupt Mask, default value: 0x00 */ +#define REG_EMSCINTRMASK 0x0324 + +/* I2C E-MSC XMIT FIFO Write Port, default value: 0x00 */ +#define REG_EMSC_XMIT_WRITE_PORT 0x032a + +/* I2C E-MSC RCV FIFO Write Port, default value: 0x00 */ +#define REG_EMSC_RCV_READ_PORT 0x032b + +/* E-MSC 2nd Interrupt, default value: 0x00 */ +#define REG_EMSCINTR1 0x032c +#define BIT_EMSCINTR1_EMSC_TRAINING_COMMA_ERR BIT(0) + +/* E-MSC Interrupt Mask, default value: 0x00 */ +#define REG_EMSCINTRMASK1 0x032d +#define BIT_EMSCINTRMASK1_EMSC_INTRMASK1_0 BIT(0) + +/* MHL Top Ctl, default value: 0x00 */ +#define REG_MHL_TOP_CTL 0x0330 +#define BIT_MHL_TOP_CTL_MHL3_DOC_SEL BIT(7) +#define BIT_MHL_TOP_CTL_MHL_PP_SEL BIT(6) +#define MSK_MHL_TOP_CTL_IF_TIMING_CTL 0x03 + +/* MHL DataPath 1st Ctl, default value: 0xbc */ +#define REG_MHL_DP_CTL0 0x0331 +#define BIT_MHL_DP_CTL0_DP_OE BIT(7) +#define BIT_MHL_DP_CTL0_TX_OE_OVR BIT(6) +#define MSK_MHL_DP_CTL0_TX_OE 0x3f + +/* MHL DataPath 2nd Ctl, default value: 0xbb */ +#define REG_MHL_DP_CTL1 0x0332 +#define MSK_MHL_DP_CTL1_CK_SWING_CTL 0xf0 +#define MSK_MHL_DP_CTL1_DT_SWING_CTL 0x0f + +/* MHL DataPath 3rd Ctl, default value: 0x2f */ +#define REG_MHL_DP_CTL2 0x0333 +#define BIT_MHL_DP_CTL2_CLK_BYPASS_EN BIT(7) +#define MSK_MHL_DP_CTL2_DAMP_TERM_SEL 0x30 +#define MSK_MHL_DP_CTL2_CK_TERM_SEL 0x0c +#define MSK_MHL_DP_CTL2_DT_TERM_SEL 0x03 + +/* MHL DataPath 4th Ctl, default value: 0x48 */ +#define REG_MHL_DP_CTL3 0x0334 +#define MSK_MHL_DP_CTL3_DT_DRV_VNBC_CTL 0xf0 +#define MSK_MHL_DP_CTL3_DT_DRV_VNB_CTL 0x0f + +/* MHL DataPath 5th Ctl, default value: 0x48 */ +#define REG_MHL_DP_CTL4 0x0335 +#define MSK_MHL_DP_CTL4_CK_DRV_VNBC_CTL 0xf0 +#define MSK_MHL_DP_CTL4_CK_DRV_VNB_CTL 0x0f + +/* MHL DataPath 6th Ctl, default value: 0x3f */ +#define REG_MHL_DP_CTL5 0x0336 +#define BIT_MHL_DP_CTL5_RSEN_EN_OVR BIT(7) +#define BIT_MHL_DP_CTL5_RSEN_EN BIT(6) +#define MSK_MHL_DP_CTL5_DAMP_TERM_VGS_CTL 0x30 +#define MSK_MHL_DP_CTL5_CK_TERM_VGS_CTL 0x0c +#define MSK_MHL_DP_CTL5_DT_TERM_VGS_CTL 0x03 + +/* MHL PLL 1st Ctl, default value: 0x05 */ +#define REG_MHL_PLL_CTL0 0x0337 +#define BIT_MHL_PLL_CTL0_AUD_CLK_EN BIT(7) + +#define MSK_MHL_PLL_CTL0_AUD_CLK_RATIO 0x70 +#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_10 0x70 +#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_6 0x60 +#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_4 0x50 +#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_2 0x40 +#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_5 0x30 +#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_3 0x20 +#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_2_PRIME 0x10 +#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_1 0x00 + +#define MSK_MHL_PLL_CTL0_HDMI_CLK_RATIO 0x0c +#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_4X 0x0c +#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_2X 0x08 +#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X 0x04 +#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_HALF_X 0x00 + +#define BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL BIT(1) +#define BIT_MHL_PLL_CTL0_ZONE_MASK_OE BIT(0) + +/* MHL PLL 3rd Ctl, default value: 0x80 */ +#define REG_MHL_PLL_CTL2 0x0339 +#define BIT_MHL_PLL_CTL2_CLKDETECT_EN BIT(7) +#define BIT_MHL_PLL_CTL2_MEAS_FVCO BIT(3) +#define BIT_MHL_PLL_CTL2_PLL_FAST_LOCK BIT(2) +#define MSK_MHL_PLL_CTL2_PLL_LF_SEL 0x03 + +/* MHL CBUS 1st Ctl, default value: 0x12 */ +#define REG_MHL_CBUS_CTL0 0x0340 +#define BIT_MHL_CBUS_CTL0_CBUS_RGND_TEST_MODE BIT(7) + +#define MSK_MHL_CBUS_CTL0_CBUS_RGND_VTH_CTL 0x30 +#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_734 0x00 +#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_747 0x10 +#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_740 0x20 +#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_754 0x30 + +#define MSK_MHL_CBUS_CTL0_CBUS_RES_TEST_SEL 0x0c + +#define MSK_MHL_CBUS_CTL0_CBUS_DRV_SEL 0x03 +#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_WEAKEST 0x00 +#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_WEAK 0x01 +#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONG 0x02 +#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONGEST 0x03 + +/* MHL CBUS 2nd Ctl, default value: 0x03 */ +#define REG_MHL_CBUS_CTL1 0x0341 +#define MSK_MHL_CBUS_CTL1_CBUS_RGND_RES_CTL 0x07 +#define VAL_MHL_CBUS_CTL1_0888_OHM 0x00 +#define VAL_MHL_CBUS_CTL1_1115_OHM 0x04 +#define VAL_MHL_CBUS_CTL1_1378_OHM 0x07 + +/* MHL CoC 1st Ctl, default value: 0xc3 */ +#define REG_MHL_COC_CTL0 0x0342 +#define BIT_MHL_COC_CTL0_COC_BIAS_EN BIT(7) +#define MSK_MHL_COC_CTL0_COC_BIAS_CTL 0x70 +#define MSK_MHL_COC_CTL0_COC_TERM_CTL 0x07 + +/* MHL CoC 2nd Ctl, default value: 0x87 */ +#define REG_MHL_COC_CTL1 0x0343 +#define BIT_MHL_COC_CTL1_COC_EN BIT(7) +#define MSK_MHL_COC_CTL1_COC_DRV_CTL 0x3f + +/* MHL CoC 4th Ctl, default value: 0x00 */ +#define REG_MHL_COC_CTL3 0x0345 +#define BIT_MHL_COC_CTL3_COC_AECHO_EN BIT(0) + +/* MHL CoC 5th Ctl, default value: 0x28 */ +#define REG_MHL_COC_CTL4 0x0346 +#define MSK_MHL_COC_CTL4_COC_IF_CTL 0xf0 +#define MSK_MHL_COC_CTL4_COC_SLEW_CTL 0x0f + +/* MHL CoC 6th Ctl, default value: 0x0d */ +#define REG_MHL_COC_CTL5 0x0347 + +/* MHL DoC 1st Ctl, default value: 0x18 */ +#define REG_MHL_DOC_CTL0 0x0349 +#define BIT_MHL_DOC_CTL0_DOC_RXDATA_EN BIT(7) +#define MSK_MHL_DOC_CTL0_DOC_DM_TERM 0x38 +#define MSK_MHL_DOC_CTL0_DOC_OPMODE 0x06 +#define BIT_MHL_DOC_CTL0_DOC_RXBIAS_EN BIT(0) + +/* MHL DataPath 7th Ctl, default value: 0x2a */ +#define REG_MHL_DP_CTL6 0x0350 +#define BIT_MHL_DP_CTL6_DP_TAP2_SGN BIT(5) +#define BIT_MHL_DP_CTL6_DP_TAP2_EN BIT(4) +#define BIT_MHL_DP_CTL6_DP_TAP1_SGN BIT(3) +#define BIT_MHL_DP_CTL6_DP_TAP1_EN BIT(2) +#define BIT_MHL_DP_CTL6_DT_PREDRV_FEEDCAP_EN BIT(1) +#define BIT_MHL_DP_CTL6_DP_PRE_POST_SEL BIT(0) + +/* MHL DataPath 8th Ctl, default value: 0x06 */ +#define REG_MHL_DP_CTL7 0x0351 +#define MSK_MHL_DP_CTL7_DT_DRV_VBIAS_CASCTL 0xf0 +#define MSK_MHL_DP_CTL7_DT_DRV_IREF_CTL 0x0f + +/* Tx Zone Ctl1, default value: 0x00 */ +#define REG_TX_ZONE_CTL1 0x0361 +#define VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE 0x08 + +/* MHL3 Tx Zone Ctl, default value: 0x00 */ +#define REG_MHL3_TX_ZONE_CTL 0x0364 +#define BIT_MHL3_TX_ZONE_CTL_MHL2_INTPLT_ZONE_MANU_EN BIT(7) +#define MSK_MHL3_TX_ZONE_CTL_MHL3_TX_ZONE 0x03 + +#define MSK_TX_ZONE_CTL3_TX_ZONE 0x03 +#define VAL_TX_ZONE_CTL3_TX_ZONE_6GBPS 0x00 +#define VAL_TX_ZONE_CTL3_TX_ZONE_3GBPS 0x01 +#define VAL_TX_ZONE_CTL3_TX_ZONE_1_5GBPS 0x02 + +/* HDCP Polling Control and Status, default value: 0x70 */ +#define REG_HDCP2X_POLL_CS 0x0391 + +#define BIT_HDCP2X_POLL_CS_HDCP2X_MSG_SZ_CLR_OPTION BIT(6) +#define BIT_HDCP2X_POLL_CS_HDCP2X_RPT_READY_CLR_OPTION BIT(5) +#define BIT_HDCP2X_POLL_CS_HDCP2X_REAUTH_REQ_CLR_OPTION BIT(4) +#define MSK_HDCP2X_POLL_CS_ 0x0c +#define BIT_HDCP2X_POLL_CS_HDCP2X_DIS_POLL_GNT BIT(1) +#define BIT_HDCP2X_POLL_CS_HDCP2X_DIS_POLL_EN BIT(0) + +/* HDCP Interrupt 0, default value: 0x00 */ +#define REG_HDCP2X_INTR0 0x0398 + +/* HDCP Interrupt 0 Mask, default value: 0x00 */ +#define REG_HDCP2X_INTR0_MASK 0x0399 + +/* HDCP General Control 0, default value: 0x02 */ +#define REG_HDCP2X_CTRL_0 0x03a0 +#define BIT_HDCP2X_CTRL_0_HDCP2X_ENCRYPT_EN BIT(7) +#define BIT_HDCP2X_CTRL_0_HDCP2X_POLINT_SEL BIT(6) +#define BIT_HDCP2X_CTRL_0_HDCP2X_POLINT_OVR BIT(5) +#define BIT_HDCP2X_CTRL_0_HDCP2X_PRECOMPUTE BIT(4) +#define BIT_HDCP2X_CTRL_0_HDCP2X_HDMIMODE BIT(3) +#define BIT_HDCP2X_CTRL_0_HDCP2X_REPEATER BIT(2) +#define BIT_HDCP2X_CTRL_0_HDCP2X_HDCPTX BIT(1) +#define BIT_HDCP2X_CTRL_0_HDCP2X_EN BIT(0) + +/* HDCP General Control 1, default value: 0x08 */ +#define REG_HDCP2X_CTRL_1 0x03a1 +#define MSK_HDCP2X_CTRL_1_HDCP2X_REAUTH_MSK_3_0 0xf0 +#define BIT_HDCP2X_CTRL_1_HDCP2X_HPD_SW BIT(3) +#define BIT_HDCP2X_CTRL_1_HDCP2X_HPD_OVR BIT(2) +#define BIT_HDCP2X_CTRL_1_HDCP2X_CTL3MSK BIT(1) +#define BIT_HDCP2X_CTRL_1_HDCP2X_REAUTH_SW BIT(0) + +/* HDCP Misc Control, default value: 0x00 */ +#define REG_HDCP2X_MISC_CTRL 0x03a5 +#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_XFER_START BIT(4) +#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_WR_START BIT(3) +#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_WR BIT(2) +#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_RCVID_RD_START BIT(1) +#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_RCVID_RD BIT(0) + +/* HDCP RPT SMNG K, default value: 0x00 */ +#define REG_HDCP2X_RPT_SMNG_K 0x03a6 + +/* HDCP RPT SMNG In, default value: 0x00 */ +#define REG_HDCP2X_RPT_SMNG_IN 0x03a7 + +/* HDCP Auth Status, default value: 0x00 */ +#define REG_HDCP2X_AUTH_STAT 0x03aa + +/* HDCP RPT RCVID Out, default value: 0x00 */ +#define REG_HDCP2X_RPT_RCVID_OUT 0x03ac + +/* HDCP TP1, default value: 0x62 */ +#define REG_HDCP2X_TP1 0x03b4 + +/* HDCP GP Out 0, default value: 0x00 */ +#define REG_HDCP2X_GP_OUT0 0x03c7 + +/* HDCP Repeater RCVR ID 0, default value: 0x00 */ +#define REG_HDCP2X_RPT_RCVR_ID0 0x03d1 + +/* HDCP DDCM Status, default value: 0x00 */ +#define REG_HDCP2X_DDCM_STS 0x03d8 +#define MSK_HDCP2X_DDCM_STS_HDCP2X_DDCM_ERR_STS_3_0 0xf0 +#define MSK_HDCP2X_DDCM_STS_HDCP2X_DDCM_CTL_CS_3_0 0x0f + +/* HDMI2MHL3 Control, default value: 0x0a */ +#define REG_M3_CTRL 0x03e0 +#define BIT_M3_CTRL_H2M_SWRST BIT(4) +#define BIT_M3_CTRL_SW_MHL3_SEL BIT(3) +#define BIT_M3_CTRL_M3AV_EN BIT(2) +#define BIT_M3_CTRL_ENC_TMDS BIT(1) +#define BIT_M3_CTRL_MHL3_MASTER_EN BIT(0) + +#define VAL_M3_CTRL_MHL1_2_VALUE (BIT_M3_CTRL_SW_MHL3_SEL \ + | BIT_M3_CTRL_ENC_TMDS) +#define VAL_M3_CTRL_MHL3_VALUE (BIT_M3_CTRL_SW_MHL3_SEL \ + | BIT_M3_CTRL_M3AV_EN \ + | BIT_M3_CTRL_ENC_TMDS \ + | BIT_M3_CTRL_MHL3_MASTER_EN) + +/* HDMI2MHL3 Port0 Control, default value: 0x04 */ +#define REG_M3_P0CTRL 0x03e1 +#define BIT_M3_P0CTRL_MHL3_P0_HDCP_ENC_EN BIT(4) +#define BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN BIT(3) +#define BIT_M3_P0CTRL_MHL3_P0_HDCP_EN BIT(2) +#define BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED BIT(1) +#define BIT_M3_P0CTRL_MHL3_P0_PORT_EN BIT(0) + +#define REG_M3_POSTM 0x03e2 +#define MSK_M3_POSTM_RRP_DECODE 0xf8 +#define MSK_M3_POSTM_MHL3_P0_STM_ID 0x07 + +/* HDMI2MHL3 Scramble Control, default value: 0x41 */ +#define REG_M3_SCTRL 0x03e6 +#define MSK_M3_SCTRL_MHL3_SR_LENGTH 0xf0 +#define BIT_M3_SCTRL_MHL3_SCRAMBLER_EN BIT(0) + +/* HSIC Div Ctl, default value: 0x05 */ +#define REG_DIV_CTL_MAIN 0x03f2 +#define MSK_DIV_CTL_MAIN_PRE_DIV_CTL_MAIN 0x1c +#define MSK_DIV_CTL_MAIN_FB_DIV_CTL_MAIN 0x03 + +/* MHL Capability 1st Byte, default value: 0x00 */ +#define REG_MHL_DEVCAP_0 0x0400 + +/* MHL Interrupt 1st Byte, default value: 0x00 */ +#define REG_MHL_INT_0 0x0420 + +/* Device Status 1st byte, default value: 0x00 */ +#define REG_MHL_STAT_0 0x0430 + +/* CBUS Scratch Pad 1st Byte, default value: 0x00 */ +#define REG_MHL_SCRPAD_0 0x0440 + +/* MHL Extended Capability 1st Byte, default value: 0x00 */ +#define REG_MHL_EXTDEVCAP_0 0x0480 + +/* Device Extended Status 1st byte, default value: 0x00 */ +#define REG_MHL_EXTSTAT_0 0x0490 + +/* TPI DTD Byte2, default value: 0x00 */ +#define REG_TPI_DTD_B2 0x0602 + +#define VAL_TPI_QUAN_RANGE_LIMITED 0x01 +#define VAL_TPI_QUAN_RANGE_FULL 0x02 +#define VAL_TPI_FORMAT_RGB 0x00 +#define VAL_TPI_FORMAT_YCBCR444 0x01 +#define VAL_TPI_FORMAT_YCBCR422 0x02 +#define VAL_TPI_FORMAT_INTERNAL_RGB 0x03 +#define VAL_TPI_FORMAT(_fmt, _qr) \ + (VAL_TPI_FORMAT_##_fmt | (VAL_TPI_QUAN_RANGE_##_qr << 2)) + +/* Input Format, default value: 0x00 */ +#define REG_TPI_INPUT 0x0609 +#define BIT_TPI_INPUT_EXTENDEDBITMODE BIT(7) +#define BIT_TPI_INPUT_ENDITHER BIT(6) +#define MSK_TPI_INPUT_INPUT_QUAN_RANGE 0x0c +#define MSK_TPI_INPUT_INPUT_FORMAT 0x03 + +/* Output Format, default value: 0x00 */ +#define REG_TPI_OUTPUT 0x060a +#define BIT_TPI_OUTPUT_CSCMODE709 BIT(4) +#define MSK_TPI_OUTPUT_OUTPUT_QUAN_RANGE 0x0c +#define MSK_TPI_OUTPUT_OUTPUT_FORMAT 0x03 + +/* TPI AVI Check Sum, default value: 0x00 */ +#define REG_TPI_AVI_CHSUM 0x060c + +/* TPI System Control, default value: 0x00 */ +#define REG_TPI_SC 0x061a +#define BIT_TPI_SC_TPI_UPDATE_FLG BIT(7) +#define BIT_TPI_SC_TPI_REAUTH_CTL BIT(6) +#define BIT_TPI_SC_TPI_OUTPUT_MODE_1 BIT(5) +#define BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN BIT(4) +#define BIT_TPI_SC_TPI_AV_MUTE BIT(3) +#define BIT_TPI_SC_DDC_GPU_REQUEST BIT(2) +#define BIT_TPI_SC_DDC_TPI_SW BIT(1) +#define BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI BIT(0) + +/* TPI COPP Query Data, default value: 0x00 */ +#define REG_TPI_COPP_DATA1 0x0629 +#define BIT_TPI_COPP_DATA1_COPP_GPROT BIT(7) +#define BIT_TPI_COPP_DATA1_COPP_LPROT BIT(6) +#define MSK_TPI_COPP_DATA1_COPP_LINK_STATUS 0x30 +#define VAL_TPI_COPP_LINK_STATUS_NORMAL 0x00 +#define VAL_TPI_COPP_LINK_STATUS_LINK_LOST 0x10 +#define VAL_TPI_COPP_LINK_STATUS_RENEGOTIATION_REQ 0x20 +#define VAL_TPI_COPP_LINK_STATUS_LINK_SUSPENDED 0x30 +#define BIT_TPI_COPP_DATA1_COPP_HDCP_REP BIT(3) +#define BIT_TPI_COPP_DATA1_COPP_CONNTYPE_0 BIT(2) +#define BIT_TPI_COPP_DATA1_COPP_PROTYPE BIT(1) +#define BIT_TPI_COPP_DATA1_COPP_CONNTYPE_1 BIT(0) + +/* TPI COPP Control Data, default value: 0x00 */ +#define REG_TPI_COPP_DATA2 0x062a +#define BIT_TPI_COPP_DATA2_INTR_ENCRYPTION BIT(5) +#define BIT_TPI_COPP_DATA2_KSV_FORWARD BIT(4) +#define BIT_TPI_COPP_DATA2_INTERM_RI_CHECK_EN BIT(3) +#define BIT_TPI_COPP_DATA2_DOUBLE_RI_CHECK BIT(2) +#define BIT_TPI_COPP_DATA2_DDC_SHORT_RI_RD BIT(1) +#define BIT_TPI_COPP_DATA2_COPP_PROTLEVEL BIT(0) + +/* TPI Interrupt Enable, default value: 0x00 */ +#define REG_TPI_INTR_EN 0x063c + +/* TPI Interrupt Status Low Byte, default value: 0x00 */ +#define REG_TPI_INTR_ST0 0x063d +#define BIT_TPI_INTR_ST0_TPI_AUTH_CHNGE_STAT BIT(7) +#define BIT_TPI_INTR_ST0_TPI_V_RDY_STAT BIT(6) +#define BIT_TPI_INTR_ST0_TPI_COPP_CHNGE_STAT BIT(5) +#define BIT_TPI_INTR_ST0_KSV_FIFO_FIRST_STAT BIT(3) +#define BIT_TPI_INTR_ST0_READ_BKSV_BCAPS_DONE_STAT BIT(2) +#define BIT_TPI_INTR_ST0_READ_BKSV_BCAPS_ERR_STAT BIT(1) +#define BIT_TPI_INTR_ST0_READ_BKSV_ERR_STAT BIT(0) + +/* TPI DS BCAPS Status, default value: 0x00 */ +#define REG_TPI_DS_BCAPS 0x0644 + +/* TPI BStatus1, default value: 0x00 */ +#define REG_TPI_BSTATUS1 0x0645 +#define BIT_TPI_BSTATUS1_DS_DEV_EXCEED BIT(7) +#define MSK_TPI_BSTATUS1_DS_DEV_CNT 0x7f + +/* TPI BStatus2, default value: 0x10 */ +#define REG_TPI_BSTATUS2 0x0646 +#define MSK_TPI_BSTATUS2_DS_BSTATUS 0xe0 +#define BIT_TPI_BSTATUS2_DS_HDMI_MODE BIT(4) +#define BIT_TPI_BSTATUS2_DS_CASC_EXCEED BIT(3) +#define MSK_TPI_BSTATUS2_DS_DEPTH 0x07 + +/* TPI HW Optimization Control #3, default value: 0x00 */ +#define REG_TPI_HW_OPT3 0x06bb +#define BIT_TPI_HW_OPT3_DDC_DEBUG BIT(7) +#define BIT_TPI_HW_OPT3_RI_CHECK_SKIP BIT(3) +#define BIT_TPI_HW_OPT3_TPI_DDC_BURST_MODE BIT(2) +#define MSK_TPI_HW_OPT3_TPI_DDC_REQ_LEVEL 0x03 + +/* TPI Info Frame Select, default value: 0x00 */ +#define REG_TPI_INFO_FSEL 0x06bf +#define BIT_TPI_INFO_FSEL_TPI_INFO_EN BIT(7) +#define BIT_TPI_INFO_FSEL_TPI_INFO_RPT BIT(6) +#define BIT_TPI_INFO_FSEL_TPI_INFO_READ_FLAG BIT(5) +#define MSK_TPI_INFO_FSEL_TPI_INFO_SEL 0x07 + +/* TPI Info Byte #0, default value: 0x00 */ +#define REG_TPI_INFO_B0 0x06c0 + +/* CoC Status, default value: 0x00 */ +#define REG_COC_STAT_0 0x0700 +#define REG_COC_STAT_1 0x0701 +#define REG_COC_STAT_2 0x0702 +#define REG_COC_STAT_3 0x0703 +#define REG_COC_STAT_4 0x0704 +#define REG_COC_STAT_5 0x0705 + +/* CoC 1st Ctl, default value: 0x40 */ +#define REG_COC_CTL0 0x0710 + +/* CoC 2nd Ctl, default value: 0x0a */ +#define REG_COC_CTL1 0x0711 +#define MSK_COC_CTL1_COC_CTRL1_7_6 0xc0 +#define MSK_COC_CTL1_COC_CTRL1_5_0 0x3f + +/* CoC 3rd Ctl, default value: 0x14 */ +#define REG_COC_CTL2 0x0712 +#define MSK_COC_CTL2_COC_CTRL2_7_6 0xc0 +#define MSK_COC_CTL2_COC_CTRL2_5_0 0x3f + +/* CoC 4th Ctl, default value: 0x40 */ +#define REG_COC_CTL3 0x0713 +#define BIT_COC_CTL3_COC_CTRL3_7 BIT(7) +#define MSK_COC_CTL3_COC_CTRL3_6_0 0x7f + +/* CoC 7th Ctl, default value: 0x00 */ +#define REG_COC_CTL6 0x0716 +#define BIT_COC_CTL6_COC_CTRL6_7 BIT(7) +#define BIT_COC_CTL6_COC_CTRL6_6 BIT(6) +#define MSK_COC_CTL6_COC_CTRL6_5_0 0x3f + +/* CoC 8th Ctl, default value: 0x06 */ +#define REG_COC_CTL7 0x0717 +#define BIT_COC_CTL7_COC_CTRL7_7 BIT(7) +#define BIT_COC_CTL7_COC_CTRL7_6 BIT(6) +#define BIT_COC_CTL7_COC_CTRL7_5 BIT(5) +#define MSK_COC_CTL7_COC_CTRL7_4_3 0x18 +#define MSK_COC_CTL7_COC_CTRL7_2_0 0x07 + +/* CoC 10th Ctl, default value: 0x00 */ +#define REG_COC_CTL9 0x0719 + +/* CoC 11th Ctl, default value: 0x00 */ +#define REG_COC_CTLA 0x071a + +/* CoC 12th Ctl, default value: 0x00 */ +#define REG_COC_CTLB 0x071b + +/* CoC 13th Ctl, default value: 0x0f */ +#define REG_COC_CTLC 0x071c + +/* CoC 14th Ctl, default value: 0x0a */ +#define REG_COC_CTLD 0x071d +#define BIT_COC_CTLD_COC_CTRLD_7 BIT(7) +#define MSK_COC_CTLD_COC_CTRLD_6_0 0x7f + +/* CoC 15th Ctl, default value: 0x0a */ +#define REG_COC_CTLE 0x071e +#define BIT_COC_CTLE_COC_CTRLE_7 BIT(7) +#define MSK_COC_CTLE_COC_CTRLE_6_0 0x7f + +/* CoC 16th Ctl, default value: 0x00 */ +#define REG_COC_CTLF 0x071f +#define MSK_COC_CTLF_COC_CTRLF_7_3 0xf8 +#define MSK_COC_CTLF_COC_CTRLF_2_0 0x07 + +/* CoC 18th Ctl, default value: 0x32 */ +#define REG_COC_CTL11 0x0721 +#define MSK_COC_CTL11_COC_CTRL11_7_4 0xf0 +#define MSK_COC_CTL11_COC_CTRL11_3_0 0x0f + +/* CoC 21st Ctl, default value: 0x00 */ +#define REG_COC_CTL14 0x0724 +#define MSK_COC_CTL14_COC_CTRL14_7_4 0xf0 +#define MSK_COC_CTL14_COC_CTRL14_3_0 0x0f + +/* CoC 22nd Ctl, default value: 0x00 */ +#define REG_COC_CTL15 0x0725 +#define BIT_COC_CTL15_COC_CTRL15_7 BIT(7) +#define MSK_COC_CTL15_COC_CTRL15_6_4 0x70 +#define MSK_COC_CTL15_COC_CTRL15_3_0 0x0f + +/* CoC Interrupt, default value: 0x00 */ +#define REG_COC_INTR 0x0726 + +/* CoC Interrupt Mask, default value: 0x00 */ +#define REG_COC_INTR_MASK 0x0727 +#define BIT_COC_PLL_LOCK_STATUS_CHANGE BIT(0) +#define BIT_COC_CALIBRATION_DONE BIT(1) + +/* CoC Misc Ctl, default value: 0x00 */ +#define REG_COC_MISC_CTL0 0x0728 +#define BIT_COC_MISC_CTL0_FSM_MON BIT(7) + +/* CoC 24th Ctl, default value: 0x00 */ +#define REG_COC_CTL17 0x072a +#define MSK_COC_CTL17_COC_CTRL17_7_4 0xf0 +#define MSK_COC_CTL17_COC_CTRL17_3_0 0x0f + +/* CoC 25th Ctl, default value: 0x00 */ +#define REG_COC_CTL18 0x072b +#define MSK_COC_CTL18_COC_CTRL18_7_4 0xf0 +#define MSK_COC_CTL18_COC_CTRL18_3_0 0x0f + +/* CoC 26th Ctl, default value: 0x00 */ +#define REG_COC_CTL19 0x072c +#define MSK_COC_CTL19_COC_CTRL19_7_4 0xf0 +#define MSK_COC_CTL19_COC_CTRL19_3_0 0x0f + +/* CoC 27th Ctl, default value: 0x00 */ +#define REG_COC_CTL1A 0x072d +#define MSK_COC_CTL1A_COC_CTRL1A_7_2 0xfc +#define MSK_COC_CTL1A_COC_CTRL1A_1_0 0x03 + +/* DoC 9th Status, default value: 0x00 */ +#define REG_DOC_STAT_8 0x0740 + +/* DoC 10th Status, default value: 0x00 */ +#define REG_DOC_STAT_9 0x0741 + +/* DoC 5th CFG, default value: 0x00 */ +#define REG_DOC_CFG4 0x074e +#define MSK_DOC_CFG4_DBG_STATE_DOC_FSM 0x0f + +/* DoC 1st Ctl, default value: 0x40 */ +#define REG_DOC_CTL0 0x0751 + +/* DoC 7th Ctl, default value: 0x00 */ +#define REG_DOC_CTL6 0x0757 +#define BIT_DOC_CTL6_DOC_CTRL6_7 BIT(7) +#define BIT_DOC_CTL6_DOC_CTRL6_6 BIT(6) +#define MSK_DOC_CTL6_DOC_CTRL6_5_4 0x30 +#define MSK_DOC_CTL6_DOC_CTRL6_3_0 0x0f + +/* DoC 8th Ctl, default value: 0x00 */ +#define REG_DOC_CTL7 0x0758 +#define BIT_DOC_CTL7_DOC_CTRL7_7 BIT(7) +#define BIT_DOC_CTL7_DOC_CTRL7_6 BIT(6) +#define BIT_DOC_CTL7_DOC_CTRL7_5 BIT(5) +#define MSK_DOC_CTL7_DOC_CTRL7_4_3 0x18 +#define MSK_DOC_CTL7_DOC_CTRL7_2_0 0x07 + +/* DoC 9th Ctl, default value: 0x00 */ +#define REG_DOC_CTL8 0x076c +#define BIT_DOC_CTL8_DOC_CTRL8_7 BIT(7) +#define MSK_DOC_CTL8_DOC_CTRL8_6_4 0x70 +#define MSK_DOC_CTL8_DOC_CTRL8_3_2 0x0c +#define MSK_DOC_CTL8_DOC_CTRL8_1_0 0x03 + +/* DoC 10th Ctl, default value: 0x00 */ +#define REG_DOC_CTL9 0x076d + +/* DoC 11th Ctl, default value: 0x00 */ +#define REG_DOC_CTLA 0x076e + +/* DoC 15th Ctl, default value: 0x00 */ +#define REG_DOC_CTLE 0x0772 +#define BIT_DOC_CTLE_DOC_CTRLE_7 BIT(7) +#define BIT_DOC_CTLE_DOC_CTRLE_6 BIT(6) +#define MSK_DOC_CTLE_DOC_CTRLE_5_4 0x30 +#define MSK_DOC_CTLE_DOC_CTRLE_3_0 0x0f + +/* Interrupt Mask 1st, default value: 0x00 */ +#define REG_MHL_INT_0_MASK 0x0580 + +/* Interrupt Mask 2nd, default value: 0x00 */ +#define REG_MHL_INT_1_MASK 0x0581 + +/* Interrupt Mask 3rd, default value: 0x00 */ +#define REG_MHL_INT_2_MASK 0x0582 + +/* Interrupt Mask 4th, default value: 0x00 */ +#define REG_MHL_INT_3_MASK 0x0583 + +/* MDT Receive Time Out, default value: 0x00 */ +#define REG_MDT_RCV_TIMEOUT 0x0584 + +/* MDT Transmit Time Out, default value: 0x00 */ +#define REG_MDT_XMIT_TIMEOUT 0x0585 + +/* MDT Receive Control, default value: 0x00 */ +#define REG_MDT_RCV_CTRL 0x0586 +#define BIT_MDT_RCV_CTRL_MDT_RCV_EN BIT(7) +#define BIT_MDT_RCV_CTRL_MDT_DELAY_RCV_EN BIT(6) +#define BIT_MDT_RCV_CTRL_MDT_RFIFO_OVER_WR_EN BIT(4) +#define BIT_MDT_RCV_CTRL_MDT_XFIFO_OVER_WR_EN BIT(3) +#define BIT_MDT_RCV_CTRL_MDT_DISABLE BIT(2) +#define BIT_MDT_RCV_CTRL_MDT_RFIFO_CLR_ALL BIT(1) +#define BIT_MDT_RCV_CTRL_MDT_RFIFO_CLR_CUR BIT(0) + +/* MDT Receive Read Port, default value: 0x00 */ +#define REG_MDT_RCV_READ_PORT 0x0587 + +/* MDT Transmit Control, default value: 0x70 */ +#define REG_MDT_XMIT_CTRL 0x0588 +#define BIT_MDT_XMIT_CTRL_MDT_XMIT_EN BIT(7) +#define BIT_MDT_XMIT_CTRL_MDT_XMIT_CMD_MERGE_EN BIT(6) +#define BIT_MDT_XMIT_CTRL_MDT_XMIT_FIXED_BURST_LEN BIT(5) +#define BIT_MDT_XMIT_CTRL_MDT_XMIT_FIXED_AID BIT(4) +#define BIT_MDT_XMIT_CTRL_MDT_XMIT_SINGLE_RUN_EN BIT(3) +#define BIT_MDT_XMIT_CTRL_MDT_CLR_ABORT_WAIT BIT(2) +#define BIT_MDT_XMIT_CTRL_MDT_XFIFO_CLR_ALL BIT(1) +#define BIT_MDT_XMIT_CTRL_MDT_XFIFO_CLR_CUR BIT(0) + +/* MDT Receive WRITE Port, default value: 0x00 */ +#define REG_MDT_XMIT_WRITE_PORT 0x0589 + +/* MDT RFIFO Status, default value: 0x00 */ +#define REG_MDT_RFIFO_STAT 0x058a +#define MSK_MDT_RFIFO_STAT_MDT_RFIFO_CNT 0xe0 +#define MSK_MDT_RFIFO_STAT_MDT_RFIFO_CUR_BYTE_CNT 0x1f + +/* MDT XFIFO Status, default value: 0x80 */ +#define REG_MDT_XFIFO_STAT 0x058b +#define MSK_MDT_XFIFO_STAT_MDT_XFIFO_LEVEL_AVAIL 0xe0 +#define BIT_MDT_XFIFO_STAT_MDT_XMIT_PRE_HS_EN BIT(4) +#define MSK_MDT_XFIFO_STAT_MDT_WRITE_BURST_LEN 0x0f + +/* MDT Interrupt 0, default value: 0x0c */ +#define REG_MDT_INT_0 0x058c +#define BIT_MDT_RFIFO_DATA_RDY BIT(0) +#define BIT_MDT_IDLE_AFTER_HAWB_DISABLE BIT(2) +#define BIT_MDT_XFIFO_EMPTY BIT(3) + +/* MDT Interrupt 0 Mask, default value: 0x00 */ +#define REG_MDT_INT_0_MASK 0x058d + +/* MDT Interrupt 1, default value: 0x00 */ +#define REG_MDT_INT_1 0x058e +#define BIT_MDT_RCV_TIMEOUT BIT(0) +#define BIT_MDT_RCV_SM_ABORT_PKT_RCVD BIT(1) +#define BIT_MDT_RCV_SM_ERROR BIT(2) +#define BIT_MDT_XMIT_TIMEOUT BIT(5) +#define BIT_MDT_XMIT_SM_ABORT_PKT_RCVD BIT(6) +#define BIT_MDT_XMIT_SM_ERROR BIT(7) + +/* MDT Interrupt 1 Mask, default value: 0x00 */ +#define REG_MDT_INT_1_MASK 0x058f + +/* CBUS Vendor ID, default value: 0x01 */ +#define REG_CBUS_VENDOR_ID 0x0590 + +/* CBUS Connection Status, default value: 0x00 */ +#define REG_CBUS_STATUS 0x0591 +#define BIT_CBUS_STATUS_MHL_CABLE_PRESENT BIT(4) +#define BIT_CBUS_STATUS_MSC_HB_SUCCESS BIT(3) +#define BIT_CBUS_STATUS_CBUS_HPD BIT(2) +#define BIT_CBUS_STATUS_MHL_MODE BIT(1) +#define BIT_CBUS_STATUS_CBUS_CONNECTED BIT(0) + +/* CBUS Interrupt 1st, default value: 0x00 */ +#define REG_CBUS_INT_0 0x0592 +#define BIT_CBUS_MSC_MT_DONE_NACK BIT(7) +#define BIT_CBUS_MSC_MR_SET_INT BIT(6) +#define BIT_CBUS_MSC_MR_WRITE_BURST BIT(5) +#define BIT_CBUS_MSC_MR_MSC_MSG BIT(4) +#define BIT_CBUS_MSC_MR_WRITE_STAT BIT(3) +#define BIT_CBUS_HPD_CHG BIT(2) +#define BIT_CBUS_MSC_MT_DONE BIT(1) +#define BIT_CBUS_CNX_CHG BIT(0) + +/* CBUS Interrupt Mask 1st, default value: 0x00 */ +#define REG_CBUS_INT_0_MASK 0x0593 + +/* CBUS Interrupt 2nd, default value: 0x00 */ +#define REG_CBUS_INT_1 0x0594 +#define BIT_CBUS_CMD_ABORT BIT(6) +#define BIT_CBUS_MSC_ABORT_RCVD BIT(3) +#define BIT_CBUS_DDC_ABORT BIT(2) +#define BIT_CBUS_CEC_ABORT BIT(1) + +/* CBUS Interrupt Mask 2nd, default value: 0x00 */ +#define REG_CBUS_INT_1_MASK 0x0595 + +/* CBUS DDC Abort Interrupt, default value: 0x00 */ +#define REG_DDC_ABORT_INT 0x0598 + +/* CBUS DDC Abort Interrupt Mask, default value: 0x00 */ +#define REG_DDC_ABORT_INT_MASK 0x0599 + +/* CBUS MSC Requester Abort Interrupt, default value: 0x00 */ +#define REG_MSC_MT_ABORT_INT 0x059a + +/* CBUS MSC Requester Abort Interrupt Mask, default value: 0x00 */ +#define REG_MSC_MT_ABORT_INT_MASK 0x059b + +/* CBUS MSC Responder Abort Interrupt, default value: 0x00 */ +#define REG_MSC_MR_ABORT_INT 0x059c + +/* CBUS MSC Responder Abort Interrupt Mask, default value: 0x00 */ +#define REG_MSC_MR_ABORT_INT_MASK 0x059d + +/* CBUS RX DISCOVERY interrupt, default value: 0x00 */ +#define REG_CBUS_RX_DISC_INT0 0x059e + +/* CBUS RX DISCOVERY Interrupt Mask, default value: 0x00 */ +#define REG_CBUS_RX_DISC_INT0_MASK 0x059f + +/* CBUS_Link_Layer Control #8, default value: 0x00 */ +#define REG_CBUS_LINK_CTRL_8 0x05a7 + +/* MDT State Machine Status, default value: 0x00 */ +#define REG_MDT_SM_STAT 0x05b5 +#define MSK_MDT_SM_STAT_MDT_RCV_STATE 0xf0 +#define MSK_MDT_SM_STAT_MDT_XMIT_STATE 0x0f + +/* CBUS MSC command trigger, default value: 0x00 */ +#define REG_MSC_COMMAND_START 0x05b8 +#define BIT_MSC_COMMAND_START_DEBUG BIT(5) +#define BIT_MSC_COMMAND_START_WRITE_BURST BIT(4) +#define BIT_MSC_COMMAND_START_WRITE_STAT BIT(3) +#define BIT_MSC_COMMAND_START_READ_DEVCAP BIT(2) +#define BIT_MSC_COMMAND_START_MSC_MSG BIT(1) +#define BIT_MSC_COMMAND_START_PEER BIT(0) + +/* CBUS MSC Command/Offset, default value: 0x00 */ +#define REG_MSC_CMD_OR_OFFSET 0x05b9 + +/* CBUS MSC Transmit Data */ +#define REG_MSC_1ST_TRANSMIT_DATA 0x05ba +#define REG_MSC_2ND_TRANSMIT_DATA 0x05bb + +/* CBUS MSC Requester Received Data */ +#define REG_MSC_MT_RCVD_DATA0 0x05bc +#define REG_MSC_MT_RCVD_DATA1 0x05bd + +/* CBUS MSC Responder MSC_MSG Received Data */ +#define REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA 0x05bf +#define REG_MSC_MR_MSC_MSG_RCVD_2ND_DATA 0x05c0 + +/* CBUS MSC Heartbeat Control, default value: 0x27 */ +#define REG_MSC_HEARTBEAT_CTRL 0x05c4 +#define BIT_MSC_HEARTBEAT_CTRL_MSC_HB_EN BIT(7) +#define MSK_MSC_HEARTBEAT_CTRL_MSC_HB_FAIL_LIMIT 0x70 +#define MSK_MSC_HEARTBEAT_CTRL_MSC_HB_PERIOD_MSB 0x0f + +/* CBUS MSC Compatibility Control, default value: 0x02 */ +#define REG_CBUS_MSC_COMPAT_CTRL 0x05c7 +#define BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN BIT(7) +#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_MSC_ON_CBUS BIT(6) +#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_DDC_ON_CBUS BIT(5) +#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_GET_DDC_ERRORCODE BIT(3) +#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_GET_VS1_ERRORCODE BIT(2) + +/* CBUS3 Converter Control, default value: 0x24 */ +#define REG_CBUS3_CNVT 0x05dc +#define MSK_CBUS3_CNVT_CBUS3_RETRYLMT 0xf0 +#define MSK_CBUS3_CNVT_CBUS3_PEERTOUT_SEL 0x0c +#define BIT_CBUS3_CNVT_TEARCBUS_EN BIT(1) +#define BIT_CBUS3_CNVT_CBUS3CNVT_EN BIT(0) + +/* Discovery Control1, default value: 0x24 */ +#define REG_DISC_CTRL1 0x05e0 +#define BIT_DISC_CTRL1_CBUS_INTR_EN BIT(7) +#define BIT_DISC_CTRL1_HB_ONLY BIT(6) +#define MSK_DISC_CTRL1_DISC_ATT 0x30 +#define MSK_DISC_CTRL1_DISC_CYC 0x0c +#define BIT_DISC_CTRL1_DISC_EN BIT(0) + +#define VAL_PUP_OFF 0 +#define VAL_PUP_20K 1 +#define VAL_PUP_5K 2 + +/* Discovery Control4, default value: 0x80 */ +#define REG_DISC_CTRL4 0x05e3 +#define MSK_DISC_CTRL4_CBUSDISC_PUP_SEL 0xc0 +#define MSK_DISC_CTRL4_CBUSIDLE_PUP_SEL 0x30 +#define VAL_DISC_CTRL4(pup_disc, pup_idle) (((pup_disc) << 6) | (pup_idle << 4)) + +/* Discovery Control5, default value: 0x03 */ +#define REG_DISC_CTRL5 0x05e4 +#define BIT_DISC_CTRL5_DSM_OVRIDE BIT(3) +#define MSK_DISC_CTRL5_CBUSMHL_PUP_SEL 0x03 + +/* Discovery Control8, default value: 0x81 */ +#define REG_DISC_CTRL8 0x05e7 +#define BIT_DISC_CTRL8_NOMHLINT_CLR_BYPASS BIT(7) +#define BIT_DISC_CTRL8_DELAY_CBUS_INTR_EN BIT(0) + +/* Discovery Control9, default value: 0x54 */ +#define REG_DISC_CTRL9 0x05e8 +#define BIT_DISC_CTRL9_MHL3_RSEN_BYP BIT(7) +#define BIT_DISC_CTRL9_MHL3DISC_EN BIT(6) +#define BIT_DISC_CTRL9_WAKE_DRVFLT BIT(4) +#define BIT_DISC_CTRL9_NOMHL_EST BIT(3) +#define BIT_DISC_CTRL9_DISC_PULSE_PROCEED BIT(2) +#define BIT_DISC_CTRL9_WAKE_PULSE_BYPASS BIT(1) +#define BIT_DISC_CTRL9_VBUS_OUTPUT_CAPABILITY_SRC BIT(0) + +/* Discovery Status1, default value: 0x00 */ +#define REG_DISC_STAT1 0x05eb +#define BIT_DISC_STAT1_PSM_OVRIDE BIT(5) +#define MSK_DISC_STAT1_DISC_SM 0x0f + +/* Discovery Status2, default value: 0x00 */ +#define REG_DISC_STAT2 0x05ec +#define BIT_DISC_STAT2_CBUS_OE_POL BIT(6) +#define BIT_DISC_STAT2_CBUS_SATUS BIT(5) +#define BIT_DISC_STAT2_RSEN BIT(4) + +#define MSK_DISC_STAT2_MHL_VRSN 0x0c +#define VAL_DISC_STAT2_DEFAULT 0x00 +#define VAL_DISC_STAT2_MHL1_2 0x04 +#define VAL_DISC_STAT2_MHL3 0x08 +#define VAL_DISC_STAT2_RESERVED 0x0c + +#define MSK_DISC_STAT2_RGND 0x03 +#define VAL_RGND_OPEN 0x00 +#define VAL_RGND_2K 0x01 +#define VAL_RGND_1K 0x02 +#define VAL_RGND_SHORT 0x03 + +/* Interrupt CBUS_reg1 INTR0, default value: 0x00 */ +#define REG_CBUS_DISC_INTR0 0x05ed +#define BIT_RGND_READY_INT BIT(6) +#define BIT_CBUS_MHL12_DISCON_INT BIT(5) +#define BIT_CBUS_MHL3_DISCON_INT BIT(4) +#define BIT_NOT_MHL_EST_INT BIT(3) +#define BIT_MHL_EST_INT BIT(2) +#define BIT_MHL3_EST_INT BIT(1) +#define VAL_CBUS_MHL_DISCON (BIT_CBUS_MHL12_DISCON_INT \ + | BIT_CBUS_MHL3_DISCON_INT \ + | BIT_NOT_MHL_EST_INT) + +/* Interrupt CBUS_reg1 INTR0 Mask, default value: 0x00 */ +#define REG_CBUS_DISC_INTR0_MASK 0x05ee + +#endif /* __SIL_SII8620_H__ */ -- cgit v1.2.3 From 7948b87308a489c2caa23574ea3c72298288c374 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Thu, 22 Sep 2016 14:41:28 +0300 Subject: iwlwifi: mvm: enable dynamic queue allocation mode New firmwares support dynamic queue allocation (DQA), which enables on-demand allocation of queues per RA/TID, instead of allocating them statically per vif. This allows an AP to send, for instance, BE traffic to STA2 even if it also needs to send traffic to a sleeping STA1, without being blocked by the sleeping station. The implementation in the driver is now ready, so we can enable this feature by default when running firmwares that support it. Signed-off-by: Liad Kaufman [reworded the commit message] Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 726ba48da15d..cde8c6cda594 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1111,9 +1111,8 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm) { - /* Make sure DQA isn't allowed in driver until feature is complete */ - return false && fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_DQA_SUPPORT); + return fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_DQA_SUPPORT); } static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm) -- cgit v1.2.3 From 7e62a699aafbd97928f19a8356d719b71b0e151c Mon Sep 17 00:00:00 2001 From: Aviya Erenfeld Date: Tue, 20 Sep 2016 18:07:44 +0300 Subject: iwlwifi: mvm: use dev_coredumpsg() iwlmvm currently uses dev_coredumpm() to collect multiple buffers, but this has the downside of pinning the module until the coredump expires, if the data isn't read by any userspace. Avoid this by using the new dev_coredumpsg() method. We still copy the data from the old way of generating it, but neither hold on to vmalloc'ed data for a long time, nor do we pin the module now. Signed-off-by: Aviya Erenfeld [rewrite commit message] Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 100 +++++++++++++----------- 1 file changed, 55 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index d89d0a1fd34e..2e8e3e8e30a3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -70,49 +70,6 @@ #include "iwl-prph.h" #include "iwl-csr.h" -static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count, - void *data, size_t datalen) -{ - const struct iwl_mvm_dump_ptrs *dump_ptrs = data; - ssize_t bytes_read; - ssize_t bytes_read_trans; - - if (offset < dump_ptrs->op_mode_len) { - bytes_read = min_t(ssize_t, count, - dump_ptrs->op_mode_len - offset); - memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset, - bytes_read); - offset += bytes_read; - count -= bytes_read; - - if (count == 0) - return bytes_read; - } else { - bytes_read = 0; - } - - if (!dump_ptrs->trans_ptr) - return bytes_read; - - offset -= dump_ptrs->op_mode_len; - bytes_read_trans = min_t(ssize_t, count, - dump_ptrs->trans_ptr->len - offset); - memcpy(buffer + bytes_read, - (u8 *)dump_ptrs->trans_ptr->data + offset, - bytes_read_trans); - - return bytes_read + bytes_read_trans; -} - -static void iwl_mvm_free_coredump(void *data) -{ - const struct iwl_mvm_dump_ptrs *fw_error_dump = data; - - vfree(fw_error_dump->op_mode_ptr); - vfree(fw_error_dump->trans_ptr); - kfree(fw_error_dump); -} - #define RADIO_REG_MAX_READ 0x2ad static void iwl_mvm_read_radio_reg(struct iwl_mvm *mvm, struct iwl_fw_error_dump_data **dump_data) @@ -491,6 +448,43 @@ static u32 iwl_dump_prph(struct iwl_trans *trans, return prph_len; } +/* + * alloc_sgtable - allocates scallerlist table in the given size, + * fills it with pages and returns it + * @size: the size (in bytes) of the table +*/ +static struct scatterlist *alloc_sgtable(int size) +{ + int alloc_size, nents, i; + struct page *new_page; + struct scatterlist *iter; + struct scatterlist *table; + + nents = DIV_ROUND_UP(size, PAGE_SIZE); + table = kcalloc(nents, sizeof(*table), GFP_KERNEL); + if (!table) + return NULL; + sg_init_table(table, nents); + iter = table; + for_each_sg(table, iter, sg_nents(table), i) { + new_page = alloc_page(GFP_KERNEL); + if (!new_page) { + /* release all previous allocated pages in the table */ + iter = table; + for_each_sg(table, iter, sg_nents(table), i) { + new_page = sg_page(iter); + if (new_page) + __free_page(new_page); + } + return NULL; + } + alloc_size = min_t(int, size, PAGE_SIZE); + size -= PAGE_SIZE; + sg_set_page(iter, new_page, alloc_size, 0); + } + return table; +} + void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) { struct iwl_fw_error_dump_file *dump_file; @@ -499,6 +493,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) struct iwl_fw_error_dump_mem *dump_mem; struct iwl_fw_error_dump_trigger_desc *dump_trig; struct iwl_mvm_dump_ptrs *fw_error_dump; + struct scatterlist *sg_dump_data; u32 sram_len, sram_ofs; struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem = mvm->fw->dbg_mem_tlv; @@ -815,8 +810,23 @@ dump_trans_data: file_len += fw_error_dump->trans_ptr->len; dump_file->file_len = cpu_to_le32(file_len); - dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0, - GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump); + sg_dump_data = alloc_sgtable(file_len); + if (sg_dump_data) { + sg_pcopy_from_buffer(sg_dump_data, + sg_nents(sg_dump_data), + fw_error_dump->op_mode_ptr, + fw_error_dump->op_mode_len, 0); + sg_pcopy_from_buffer(sg_dump_data, + sg_nents(sg_dump_data), + fw_error_dump->trans_ptr->data, + fw_error_dump->trans_ptr->len, + fw_error_dump->op_mode_len); + dev_coredumpsg(mvm->trans->dev, sg_dump_data, file_len, + GFP_KERNEL); + } + vfree(fw_error_dump->op_mode_ptr); + vfree(fw_error_dump->trans_ptr); + kfree(fw_error_dump); out: iwl_mvm_free_fw_dump_desc(mvm); -- cgit v1.2.3 From 07ee2bce6a516e0218dba22581803cb8f11bcf82 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 25 Oct 2016 17:40:35 +0100 Subject: drm/i915: Rotated view does not need a fence We do not need to set up a fence for the rotated view. Display does not need it and no one can access it. v2: Move code to __i915_vma_set_map_and_fenceable. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Fixes: 05a20d098db1 ("drm/i915: Move map-and-fenceable tracking to the VMA") Cc: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9361c7b54a7f..eb524bdf0c35 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3790,7 +3790,12 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma) mappable = (vma->node.start + fence_size <= dev_priv->ggtt.mappable_end); - if (mappable && fenceable) + /* + * Explicitly disable for rotated VMA since the display does not + * need the fence and the VMA is not accessible to other users. + */ + if (mappable && fenceable && + vma->ggtt_view.type != I915_GGTT_VIEW_ROTATED) vma->flags |= I915_VMA_CAN_FENCE; else vma->flags &= ~I915_VMA_CAN_FENCE; -- cgit v1.2.3 From 3299e7e43484a85eeb5c7ec09958bff05c9d0543 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 25 Oct 2016 17:41:12 +0100 Subject: drm/i915: Remove two invalid warns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Objects can have multiple VMAs used for display in which case assertion that objects must not be pinned for display more times than the current VMA is incorrect. v2: Commit message update. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Fixes: 058d88c4330f ("drm/i915: Track pinned VMA") Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Ville Syrjälä Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1477413635-3876-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_gem.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index eb524bdf0c35..87018df94d68 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3595,8 +3595,6 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, vma->display_alignment = max_t(u64, vma->display_alignment, alignment); - WARN_ON(obj->pin_display > i915_vma_pin_count(vma)); - i915_gem_object_flush_cpu_write_domain(obj); old_write_domain = obj->base.write_domain; @@ -3633,7 +3631,6 @@ i915_gem_object_unpin_from_display_plane(struct i915_vma *vma) list_move_tail(&vma->vm_link, &vma->vm->inactive_list); i915_vma_unpin(vma); - WARN_ON(vma->obj->pin_display > i915_vma_pin_count(vma)); } /** -- cgit v1.2.3 From 1aab956c7b8872fb6976328316bfad62c6e67cf8 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 21 Oct 2016 16:44:38 +0300 Subject: drm/i915: Refresh that status of MST capable connectors in ->detect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Once we've determined that the sink is MST capable we never end up running through the full detect cycle again, despite getting HPDs. Fix tht by ripping out the incorrect piece of code responsible. This got broken when I moved the long HPD handling to the ->detect() hook, but failed to remove the leftover code. Cc: Ander Conselvan de Oliveira Cc: drm-intel-fixes@lists.freedesktop.org Cc: Rui Tiago Matos Tested-by: Rui Tiago Matos Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98323 Cc: Kirill A. Shutemov Tested-by: Kirill A. Shutemov References: https://bugs.freedesktop.org/show_bug.cgi?id=98306 Fixes: 27d4efc5591a ("drm/i915: Move long hpd handling into the hotplug work") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477057478-29328-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_dp.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f30db8f2425e..80db8a3ac38f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4492,21 +4492,11 @@ static enum drm_connector_status intel_dp_detect(struct drm_connector *connector, bool force) { struct intel_dp *intel_dp = intel_attached_dp(connector); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct intel_encoder *intel_encoder = &intel_dig_port->base; enum drm_connector_status status = connector->status; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); - if (intel_dp->is_mst) { - /* MST devices are disconnected from a monitor POV */ - intel_dp_unset_edid(intel_dp); - if (intel_encoder->type != INTEL_OUTPUT_EDP) - intel_encoder->type = INTEL_OUTPUT_DP; - return connector_status_disconnected; - } - /* If full detect is not performed yet, do a full detect */ if (!intel_dp->detect_done) status = intel_dp_long_pulse(intel_dp->attached_connector); -- cgit v1.2.3 From 9ca89c443de94751cd6fb5d84b215ec48279e8c2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 25 Oct 2016 17:54:17 +0300 Subject: drm/i915/audio: drop extra crtc clock check from HDMI audio N lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The array contains the crtc clock, rely on that. While at it, debug log the HDMI N value or automatic mode. Cc: Ville Syrjälä Cc: "Lin, Mengdong" Cc: Libin Yang Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477407258-30599-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 7093cfbb62b1..1a5c21209446 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -254,16 +254,15 @@ hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, tmp &= ~AUD_CONFIG_N_PROG_ENABLE; tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); - if (adjusted_mode->crtc_clock == TMDS_296M || - adjusted_mode->crtc_clock == TMDS_297M) { - n = audio_config_hdmi_get_n(adjusted_mode, rate); - if (n != 0) { - tmp &= ~AUD_CONFIG_N_MASK; - tmp |= AUD_CONFIG_N(n); - tmp |= AUD_CONFIG_N_PROG_ENABLE; - } else { - DRM_DEBUG_KMS("no suitable N value is found\n"); - } + n = audio_config_hdmi_get_n(adjusted_mode, rate); + if (n != 0) { + DRM_DEBUG_KMS("using N %d\n", n); + + tmp &= ~AUD_CONFIG_N_MASK; + tmp |= AUD_CONFIG_N(n); + tmp |= AUD_CONFIG_N_PROG_ENABLE; + } else { + DRM_DEBUG_KMS("using automatic N\n"); } I915_WRITE(HSW_AUD_CFG(pipe), tmp); -- cgit v1.2.3 From 0aced355757ddc150f78a6bf4f8d885bd4eaf0e2 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Mon, 19 Sep 2016 13:09:02 +0530 Subject: mfd: tps65218: Remove redundant read wrapper Currently read directly calls the repmap read function. Hence remove the redundant wrapper and use regmap read wherever needed. Signed-off-by: Keerthy Signed-off-by: Lee Jones --- drivers/gpio/gpio-tps65218.c | 3 ++- drivers/mfd/tps65218.c | 18 ++---------------- drivers/regulator/tps65218-regulator.c | 5 +++-- include/linux/mfd/tps65218.h | 2 -- 4 files changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index d779307a9685..46e6dcc089cb 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -16,6 +16,7 @@ #include #include #include +#include #include struct tps65218_gpio { @@ -30,7 +31,7 @@ static int tps65218_gpio_get(struct gpio_chip *gc, unsigned offset) unsigned int val; int ret; - ret = tps65218_reg_read(tps65218, TPS65218_REG_ENABLE2, &val); + ret = regmap_read(tps65218->regmap, TPS65218_REG_ENABLE2, &val); if (ret) return ret; diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c index ba610adbdbff..9bca1b1b60ce 100644 --- a/drivers/mfd/tps65218.c +++ b/drivers/mfd/tps65218.c @@ -33,20 +33,6 @@ #define TPS65218_PASSWORD_REGS_UNLOCK 0x7D -/** - * tps65218_reg_read: Read a single tps65218 register. - * - * @tps: Device to read from. - * @reg: Register to read. - * @val: Contians the value - */ -int tps65218_reg_read(struct tps65218 *tps, unsigned int reg, - unsigned int *val) -{ - return regmap_read(tps->regmap, reg, val); -} -EXPORT_SYMBOL_GPL(tps65218_reg_read); - /** * tps65218_reg_write: Write a single tps65218 register. * @@ -93,7 +79,7 @@ static int tps65218_update_bits(struct tps65218 *tps, unsigned int reg, int ret; unsigned int data; - ret = tps65218_reg_read(tps, reg, &data); + ret = regmap_read(tps->regmap, reg, &data); if (ret) { dev_err(tps->dev, "Read from reg 0x%x failed\n", reg); return ret; @@ -251,7 +237,7 @@ static int tps65218_probe(struct i2c_client *client, if (ret < 0) return ret; - ret = tps65218_reg_read(tps, TPS65218_REG_CHIPID, &chipid); + ret = regmap_read(tps->regmap, TPS65218_REG_CHIPID, &chipid); if (ret) { dev_err(tps->dev, "Failed to read chipid: %d\n", ret); return ret; diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index eb0f5b13841a..ae16caf4151c 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -272,7 +273,7 @@ static int tps65218_pmic_get_current_limit(struct regulator_dev *dev) unsigned int index; struct tps65218 *tps = rdev_get_drvdata(dev); - retval = tps65218_reg_read(tps, dev->desc->csel_reg, &index); + retval = regmap_read(tps->regmap, dev->desc->csel_reg, &index); if (retval < 0) return retval; @@ -383,7 +384,7 @@ static int tps65218_regulator_probe(struct platform_device *pdev) return PTR_ERR(rdev); } - ret = tps65218_reg_read(tps, regulators[id].bypass_reg, &val); + ret = regmap_read(tps->regmap, regulators[id].bypass_reg, &val); if (ret) return ret; diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h index d1db9527fab5..51bef539091c 100644 --- a/include/linux/mfd/tps65218.h +++ b/include/linux/mfd/tps65218.h @@ -284,8 +284,6 @@ struct tps65218 { struct regmap *regmap; }; -int tps65218_reg_read(struct tps65218 *tps, unsigned int reg, - unsigned int *val); int tps65218_reg_write(struct tps65218 *tps, unsigned int reg, unsigned int val, unsigned int level); int tps65218_set_bits(struct tps65218 *tps, unsigned int reg, -- cgit v1.2.3 From 77aa99265a8dda5b497ff4ebbcafafa7fa07e87f Mon Sep 17 00:00:00 2001 From: Keerthy Date: Mon, 19 Sep 2016 13:09:04 +0530 Subject: input: tps65218-pwrbutton: Add platform_device_id table platform_device_id table is needed for adding the tps65218-pwrbutton module to the mfd_cell array. Signed-off-by: Keerthy Acked-by: Dmitry Torokhov Signed-off-by: Lee Jones --- drivers/input/misc/tps65218-pwrbutton.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/input/misc/tps65218-pwrbutton.c b/drivers/input/misc/tps65218-pwrbutton.c index 3273217ce80c..cc74a41bdb0d 100644 --- a/drivers/input/misc/tps65218-pwrbutton.c +++ b/drivers/input/misc/tps65218-pwrbutton.c @@ -150,12 +150,20 @@ static int tps6521x_pb_probe(struct platform_device *pdev) return 0; } +static const struct platform_device_id tps6521x_pwrbtn_id_table[] = { + { "tps65218-pwrbutton", }, + { "tps65217-pwrbutton", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, tps6521x_pwrbtn_id_table); + static struct platform_driver tps6521x_pb_driver = { .probe = tps6521x_pb_probe, .driver = { .name = "tps6521x_pwrbutton", .of_match_table = of_tps6521x_pb_match, }, + .id_table = tps6521x_pwrbtn_id_table, }; module_platform_driver(tps6521x_pb_driver); -- cgit v1.2.3 From 4531156db726d27e593d35800d43c74be4e393b9 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Mon, 19 Sep 2016 13:09:05 +0530 Subject: mfd: tps65218: Use mfd_add_devices instead of of_platform_populate mfd_add_devices enables parsing device tree nodes without compatibles for regulators and gpio modules. Replace of_platform_populate with mfd_add_devices. mfd_cell currently is populated with regulators, gpio and powerbutton. Signed-off-by: Keerthy Signed-off-by: Lee Jones --- drivers/mfd/tps65218.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c index 9bca1b1b60ce..13834a0d2817 100644 --- a/drivers/mfd/tps65218.c +++ b/drivers/mfd/tps65218.c @@ -33,6 +33,18 @@ #define TPS65218_PASSWORD_REGS_UNLOCK 0x7D +static const struct mfd_cell tps65218_cells[] = { + { + .name = "tps65218-pwrbutton", + .of_compatible = "ti,tps65218-pwrbutton", + }, + { + .name = "tps65218-gpio", + .of_compatible = "ti,tps65218-gpio", + }, + { .name = "tps65218-regulator", }, +}; + /** * tps65218_reg_write: Write a single tps65218 register. * @@ -245,8 +257,10 @@ static int tps65218_probe(struct i2c_client *client, tps->rev = chipid & TPS65218_CHIPID_REV_MASK; - ret = of_platform_populate(client->dev.of_node, NULL, NULL, - &client->dev); + ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65218_cells, + ARRAY_SIZE(tps65218_cells), NULL, 0, + regmap_irq_get_domain(tps->irq_data)); + if (ret < 0) goto err_irq; -- cgit v1.2.3 From 2dc4940360d4c0c38aa9275532c7c0d7542f6258 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Mon, 19 Sep 2016 13:09:06 +0530 Subject: regulator: tps65218: Remove all the compatibles Remove all the individual compatibles for all the regulators and introduce id_table and update the driver accordingly to parse device tree nodes using the regulator framework. Signed-off-by: Keerthy Acked-by: Mark Brown Signed-off-by: Lee Jones --- drivers/regulator/tps65218-regulator.c | 150 ++++++++++++--------------------- include/linux/mfd/tps65218.h | 1 + 2 files changed, 57 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index ae16caf4151c..9aafbb03482d 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c @@ -31,10 +31,11 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1, LS3 }; -#define TPS65218_REGULATOR(_name, _id, _type, _ops, _n, _vr, _vm, _er, _em, \ - _cr, _cm, _lr, _nlr, _delay, _fuv, _sr, _sm) \ +#define TPS65218_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \ + _em, _cr, _cm, _lr, _nlr, _delay, _fuv, _sr, _sm) \ { \ .name = _name, \ + .of_match = _of, \ .id = _id, \ .ops = &_ops, \ .n_voltages = _n, \ @@ -55,14 +56,6 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, .bypass_mask = _sm, \ } \ -#define TPS65218_INFO(_id, _nm, _min, _max) \ - [_id] = { \ - .id = _id, \ - .name = _nm, \ - .min_uV = _min, \ - .max_uV = _max, \ - } - static const struct regulator_linear_range dcdc1_dcdc2_ranges[] = { REGULATOR_LINEAR_RANGE(850000, 0x0, 0x32, 10000), REGULATOR_LINEAR_RANGE(1375000, 0x33, 0x3f, 25000), @@ -78,36 +71,6 @@ static const struct regulator_linear_range dcdc4_ranges[] = { REGULATOR_LINEAR_RANGE(1600000, 0x10, 0x34, 50000), }; -static struct tps_info tps65218_pmic_regs[] = { - TPS65218_INFO(DCDC1, "DCDC1", 850000, 1675000), - TPS65218_INFO(DCDC2, "DCDC2", 850000, 1675000), - TPS65218_INFO(DCDC3, "DCDC3", 900000, 3400000), - TPS65218_INFO(DCDC4, "DCDC4", 1175000, 3400000), - TPS65218_INFO(DCDC5, "DCDC5", 1000000, 1000000), - TPS65218_INFO(DCDC6, "DCDC6", 1800000, 1800000), - TPS65218_INFO(LDO1, "LDO1", 900000, 3400000), - TPS65218_INFO(LS3, "LS3", -1, -1), -}; - -#define TPS65218_OF_MATCH(comp, label) \ - { \ - .compatible = comp, \ - .data = &label, \ - } - -static const struct of_device_id tps65218_of_match[] = { - TPS65218_OF_MATCH("ti,tps65218-dcdc1", tps65218_pmic_regs[DCDC1]), - TPS65218_OF_MATCH("ti,tps65218-dcdc2", tps65218_pmic_regs[DCDC2]), - TPS65218_OF_MATCH("ti,tps65218-dcdc3", tps65218_pmic_regs[DCDC3]), - TPS65218_OF_MATCH("ti,tps65218-dcdc4", tps65218_pmic_regs[DCDC4]), - TPS65218_OF_MATCH("ti,tps65218-dcdc5", tps65218_pmic_regs[DCDC5]), - TPS65218_OF_MATCH("ti,tps65218-dcdc6", tps65218_pmic_regs[DCDC6]), - TPS65218_OF_MATCH("ti,tps65218-ldo1", tps65218_pmic_regs[LDO1]), - TPS65218_OF_MATCH("ti,tps65218-ls3", tps65218_pmic_regs[LS3]), - { } -}; -MODULE_DEVICE_TABLE(of, tps65218_of_match); - static int tps65218_pmic_set_voltage_sel(struct regulator_dev *dev, unsigned selector) { @@ -189,7 +152,7 @@ static int tps65218_pmic_set_suspend_disable(struct regulator_dev *dev) if (rid == TPS65218_DCDC_3 && tps->rev == TPS65218_REV_2_1) return 0; - if (!tps->info[rid]->strobe) { + if (!tps->strobes[rid]) { if (rid == TPS65218_DCDC_3) tps->info[rid]->strobe = 3; else @@ -198,8 +161,7 @@ static int tps65218_pmic_set_suspend_disable(struct regulator_dev *dev) return tps65218_set_bits(tps, dev->desc->bypass_reg, dev->desc->bypass_mask, - tps->info[rid]->strobe, - TPS65218_PROTECT_L1); + tps->strobes[rid], TPS65218_PROTECT_L1); } /* Operations permitted on DCDC1, DCDC2 */ @@ -301,104 +263,104 @@ static struct regulator_ops tps65218_dcdc56_pmic_ops = { }; static const struct regulator_desc regulators[] = { - TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, REGULATOR_VOLTAGE, - tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC1, + TPS65218_REGULATOR("DCDC1", "regulator-dcdc1", TPS65218_DCDC_1, + REGULATOR_VOLTAGE, tps65218_dcdc12_ops, 64, + TPS65218_REG_CONTROL_DCDC1, TPS65218_CONTROL_DCDC1_MASK, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, 0, 0, dcdc1_dcdc2_ranges, 2, 4000, 0, TPS65218_REG_SEQ3, TPS65218_SEQ3_DC1_SEQ_MASK), - TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, REGULATOR_VOLTAGE, - tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC2, + TPS65218_REGULATOR("DCDC2", "regulator-dcdc2", TPS65218_DCDC_2, + REGULATOR_VOLTAGE, tps65218_dcdc12_ops, 64, + TPS65218_REG_CONTROL_DCDC2, TPS65218_CONTROL_DCDC2_MASK, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, 0, 0, dcdc1_dcdc2_ranges, 2, 4000, 0, TPS65218_REG_SEQ3, TPS65218_SEQ3_DC2_SEQ_MASK), - TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, REGULATOR_VOLTAGE, - tps65218_ldo1_dcdc34_ops, 64, + TPS65218_REGULATOR("DCDC3", "regulator-dcdc3", TPS65218_DCDC_3, + REGULATOR_VOLTAGE, tps65218_ldo1_dcdc34_ops, 64, TPS65218_REG_CONTROL_DCDC3, TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC3_EN, 0, 0, ldo1_dcdc3_ranges, 2, 0, 0, TPS65218_REG_SEQ4, TPS65218_SEQ4_DC3_SEQ_MASK), - TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, REGULATOR_VOLTAGE, - tps65218_ldo1_dcdc34_ops, 53, + TPS65218_REGULATOR("DCDC4", "regulator-dcdc4", TPS65218_DCDC_4, + REGULATOR_VOLTAGE, tps65218_ldo1_dcdc34_ops, 53, TPS65218_REG_CONTROL_DCDC4, TPS65218_CONTROL_DCDC4_MASK, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, 0, 0, dcdc4_ranges, 2, 0, 0, TPS65218_REG_SEQ4, TPS65218_SEQ4_DC4_SEQ_MASK), - TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, REGULATOR_VOLTAGE, - tps65218_dcdc56_pmic_ops, 1, -1, -1, - TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC5_EN, 0, 0, - NULL, 0, 0, 1000000, TPS65218_REG_SEQ5, + TPS65218_REGULATOR("DCDC5", "regulator-dcdc5", TPS65218_DCDC_5, + REGULATOR_VOLTAGE, tps65218_dcdc56_pmic_ops, 1, -1, + -1, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC5_EN, 0, + 0, NULL, 0, 0, 1000000, TPS65218_REG_SEQ5, TPS65218_SEQ5_DC5_SEQ_MASK), - TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, REGULATOR_VOLTAGE, - tps65218_dcdc56_pmic_ops, 1, -1, -1, - TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC6_EN, 0, 0, - NULL, 0, 0, 1800000, TPS65218_REG_SEQ5, + TPS65218_REGULATOR("DCDC6", "regulator-dcdc6", TPS65218_DCDC_6, + REGULATOR_VOLTAGE, tps65218_dcdc56_pmic_ops, 1, -1, + -1, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC6_EN, 0, + 0, NULL, 0, 0, 1800000, TPS65218_REG_SEQ5, TPS65218_SEQ5_DC6_SEQ_MASK), - TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, REGULATOR_VOLTAGE, - tps65218_ldo1_dcdc34_ops, 64, + TPS65218_REGULATOR("LDO1", "regulator-ldo1", TPS65218_LDO_1, + REGULATOR_VOLTAGE, tps65218_ldo1_dcdc34_ops, 64, TPS65218_REG_CONTROL_LDO1, TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LDO1_EN, 0, 0, ldo1_dcdc3_ranges, 2, 0, 0, TPS65218_REG_SEQ6, TPS65218_SEQ6_LDO1_SEQ_MASK), - TPS65218_REGULATOR("LS3", TPS65218_LS_3, REGULATOR_CURRENT, - tps65218_ls3_ops, 0, 0, 0, TPS65218_REG_ENABLE2, - TPS65218_ENABLE2_LS3_EN, TPS65218_REG_CONFIG2, - TPS65218_CONFIG2_LS3ILIM_MASK, NULL, 0, 0, 0, 0, 0), + TPS65218_REGULATOR("LS3", "regulator-ls3", TPS65218_LS_3, + REGULATOR_CURRENT, tps65218_ls3_ops, 0, 0, 0, + TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LS3_EN, + TPS65218_REG_CONFIG2, TPS65218_CONFIG2_LS3ILIM_MASK, + NULL, 0, 0, 0, 0, 0), }; static int tps65218_regulator_probe(struct platform_device *pdev) { struct tps65218 *tps = dev_get_drvdata(pdev->dev.parent); - struct regulator_init_data *init_data; - const struct tps_info *template; struct regulator_dev *rdev; - const struct of_device_id *match; struct regulator_config config = { }; - int id, ret; + int i, ret; unsigned int val; - match = of_match_device(tps65218_of_match, &pdev->dev); - if (!match) - return -ENODEV; - - template = match->data; - id = template->id; - init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, - ®ulators[id]); - - platform_set_drvdata(pdev, tps); - - tps->info[id] = &tps65218_pmic_regs[id]; config.dev = &pdev->dev; - config.init_data = init_data; + config.dev->of_node = tps->dev->of_node; config.driver_data = tps; config.regmap = tps->regmap; - config.of_node = pdev->dev.of_node; - rdev = devm_regulator_register(&pdev->dev, ®ulators[id], &config); - if (IS_ERR(rdev)) { - dev_err(tps->dev, "failed to register %s regulator\n", - pdev->name); - return PTR_ERR(rdev); - } + /* Allocate memory for strobes */ + tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) * + TPS65218_NUM_REGULATOR, GFP_KERNEL); - ret = regmap_read(tps->regmap, regulators[id].bypass_reg, &val); - if (ret) - return ret; + for (i = 0; i < ARRAY_SIZE(regulators); i++) { + rdev = devm_regulator_register(&pdev->dev, ®ulators[i], + &config); + if (IS_ERR(rdev)) { + dev_err(tps->dev, "failed to register %s regulator\n", + pdev->name); + return PTR_ERR(rdev); + } - tps->info[id]->strobe = val & regulators[id].bypass_mask; + ret = regmap_read(tps->regmap, regulators[i].bypass_reg, &val); + if (ret) + return ret; + + tps->strobes[i] = val & regulators[i].bypass_mask; + } return 0; } +static const struct platform_device_id tps65218_regulator_id_table[] = { + { "tps65218-regulator", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, tps65218_regulator_id_table); + static struct platform_driver tps65218_regulator_driver = { .driver = { .name = "tps65218-pmic", - .of_match_table = tps65218_of_match, }, .probe = tps65218_regulator_probe, + .id_table = tps65218_regulator_id_table, }; module_platform_driver(tps65218_regulator_driver); diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h index 51bef539091c..bccd2d68b1e3 100644 --- a/include/linux/mfd/tps65218.h +++ b/include/linux/mfd/tps65218.h @@ -282,6 +282,7 @@ struct tps65218 { struct regulator_desc desc[TPS65218_NUM_REGULATOR]; struct tps_info *info[TPS65218_NUM_REGULATOR]; struct regmap *regmap; + u8 *strobes; }; int tps65218_reg_write(struct tps65218 *tps, unsigned int reg, -- cgit v1.2.3 From 6014ac122ed081feca99217bc57b2e15c7fc1a51 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Tue, 25 Oct 2016 17:54:18 +0300 Subject: drm/i915/audio: set proper N/M in modeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When modeset occurs and the LS_CLK is set to some special values in DP mode, the N/M need to be set manually if audio is playing. Otherwise the first several seconds may be silent in audio playback. The relationship of Maud and Naud is expressed in the following equation: Maud/Naud = 512 * fs / f_LS_Clk Please refer VESA DisplayPort Standard spec for details. v2 by Jani: - organize Maud/Naud table according to DP 1.4 spec - add 64k and 128k audio rates - update HSW_AUD_M_CTS_ENABLE register when Maud not found - remove extra checks for port clock - simplify Maud/Naud lookup - reset patch author back to Libin Cc: "Zhang, Keqiao" Cc: Ville Syrjälä Cc: "Lin, Mengdong" Reviewed-by: Ville Syrjälä Signed-off-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477407258-30599-3-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 7 +++ drivers/gpu/drm/i915/intel_audio.c | 93 +++++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bdc7b3591e1c..542e570b3578 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7370,6 +7370,13 @@ enum { #define _HSW_AUD_MISC_CTRL_B 0x65110 #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B) +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028 +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128 +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B) +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21) +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20) +#define AUD_CONFIG_M_MASK 0xfffff + #define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4 #define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4 #define HSW_AUD_DIP_ELD_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_DIP_ELD_CTRL_ST_A, _HSW_AUD_DIP_ELD_CTRL_ST_B) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 1a5c21209446..813fd74d9c8d 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -57,6 +57,63 @@ * struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver. */ +/* DP N/M table */ +#define LC_540M 540000 +#define LC_270M 270000 +#define LC_162M 162000 + +struct dp_aud_n_m { + int sample_rate; + int clock; + u16 m; + u16 n; +}; + +/* Values according to DP 1.4 Table 2-104 */ +static const struct dp_aud_n_m dp_aud_n_m[] = { + { 32000, LC_162M, 1024, 10125 }, + { 44100, LC_162M, 784, 5625 }, + { 48000, LC_162M, 512, 3375 }, + { 64000, LC_162M, 2048, 10125 }, + { 88200, LC_162M, 1568, 5625 }, + { 96000, LC_162M, 1024, 3375 }, + { 128000, LC_162M, 4096, 10125 }, + { 176400, LC_162M, 3136, 5625 }, + { 192000, LC_162M, 2048, 3375 }, + { 32000, LC_270M, 1024, 16875 }, + { 44100, LC_270M, 784, 9375 }, + { 48000, LC_270M, 512, 5625 }, + { 64000, LC_270M, 2048, 16875 }, + { 88200, LC_270M, 1568, 9375 }, + { 96000, LC_270M, 1024, 5625 }, + { 128000, LC_270M, 4096, 16875 }, + { 176400, LC_270M, 3136, 9375 }, + { 192000, LC_270M, 2048, 5625 }, + { 32000, LC_540M, 1024, 33750 }, + { 44100, LC_540M, 784, 18750 }, + { 48000, LC_540M, 512, 11250 }, + { 64000, LC_540M, 2048, 33750 }, + { 88200, LC_540M, 1568, 18750 }, + { 96000, LC_540M, 1024, 11250 }, + { 128000, LC_540M, 4096, 33750 }, + { 176400, LC_540M, 3136, 18750 }, + { 192000, LC_540M, 2048, 11250 }, +}; + +static const struct dp_aud_n_m * +audio_config_dp_get_n_m(struct intel_crtc *intel_crtc, int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dp_aud_n_m); i++) { + if (rate == dp_aud_n_m[i].sample_rate && + intel_crtc->config->port_clock == dp_aud_n_m[i].clock) + return &dp_aud_n_m[i]; + } + + return NULL; +} + static const struct { int clock; u32 config; @@ -225,16 +282,43 @@ hsw_dp_audio_config_update(struct intel_crtc *intel_crtc, enum port port, const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); + struct i915_audio_component *acomp = dev_priv->audio_component; + int rate = acomp ? acomp->aud_sample_rate[port] : 0; + const struct dp_aud_n_m *nm = audio_config_dp_get_n_m(intel_crtc, rate); enum pipe pipe = intel_crtc->pipe; u32 tmp; + if (nm) + DRM_DEBUG_KMS("using Maud %u, Naud %u\n", nm->m, nm->n); + else + DRM_DEBUG_KMS("using automatic Maud, Naud\n"); + tmp = I915_READ(HSW_AUD_CFG(pipe)); tmp &= ~AUD_CONFIG_N_VALUE_INDEX; tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; tmp &= ~AUD_CONFIG_N_PROG_ENABLE; tmp |= AUD_CONFIG_N_VALUE_INDEX; + if (nm) { + tmp &= ~AUD_CONFIG_N_MASK; + tmp |= AUD_CONFIG_N(nm->n); + tmp |= AUD_CONFIG_N_PROG_ENABLE; + } + I915_WRITE(HSW_AUD_CFG(pipe), tmp); + + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe)); + tmp &= ~AUD_CONFIG_M_MASK; + tmp &= ~AUD_M_CTS_M_VALUE_INDEX; + tmp &= ~AUD_M_CTS_M_PROG_ENABLE; + + if (nm) { + tmp |= nm->m; + tmp |= AUD_M_CTS_M_VALUE_INDEX; + tmp |= AUD_M_CTS_M_PROG_ENABLE; + } + + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp); } static void @@ -266,6 +350,12 @@ hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, } I915_WRITE(HSW_AUD_CFG(pipe), tmp); + + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe)); + tmp &= ~AUD_CONFIG_M_MASK; + tmp &= ~AUD_M_CTS_M_VALUE_INDEX; + tmp |= AUD_M_CTS_M_PROG_ENABLE; + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp); } static void @@ -686,7 +776,8 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, /* 1. get the pipe */ intel_encoder = get_saved_enc(dev_priv, port, pipe); if (!intel_encoder || !intel_encoder->base.crtc || - intel_encoder->type != INTEL_OUTPUT_HDMI) { + (intel_encoder->type != INTEL_OUTPUT_HDMI && + intel_encoder->type != INTEL_OUTPUT_DP)) { DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port)); err = -ENODEV; goto unlock; -- cgit v1.2.3 From c726ad01d2e3e27400421de85800d954df55aeea Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 24 Oct 2016 19:33:24 +0300 Subject: drm/dp: Factor out helper to distinguish between branch and sink devices This check is open-coded in a few places, so it makes sense to simplify things by having a helper for it similar to the rest of DPCD feature helpers. v2: (Jani) - Move the helper to drm_dp_helper.h. - Split out this change to a separate patch. Cc: Jani Nikula Cc: dri-devel@lists.freedesktop.org Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477326811-30431-2-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 11 ++++------- include/drm/drm_dp_helper.h | 6 ++++++ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 80db8a3ac38f..951a0bbc03c5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1459,8 +1459,7 @@ static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) if ((drm_debug & DRM_UT_KMS) == 0) return; - if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT)) + if (!drm_dp_is_branch(intel_dp->dpcd)) return; len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_HW_REV, &rev, 1); @@ -1478,8 +1477,7 @@ static void intel_dp_print_sw_revision(struct intel_dp *intel_dp) if ((drm_debug & DRM_UT_KMS) == 0) return; - if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT)) + if (!drm_dp_is_branch(intel_dp->dpcd)) return; len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV, &rev, 2); @@ -3615,8 +3613,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) if (!is_edp(intel_dp) && !intel_dp->sink_count) return false; - if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT)) + if (!drm_dp_is_branch(intel_dp->dpcd)) return true; /* native DP sink */ if (intel_dp->dpcd[DP_DPCD_REV] == 0x10) @@ -4134,7 +4131,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) return connector_status_connected; /* if there's no downstream port, we're done */ - if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)) + if (!drm_dp_is_branch(dpcd)) return connector_status_connected; /* If we're HPD-aware, SINK_COUNT changes dynamically */ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 2a79882cb68e..55bbeb0ff594 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -690,6 +690,12 @@ drm_dp_tps3_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED; } +static inline bool +drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + return dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT; +} + /* * DisplayPort AUX channel */ -- cgit v1.2.3 From 6f172a43a6d679e4a6563376f749868a9bf29752 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 24 Oct 2016 19:33:25 +0300 Subject: drm/i915/dp: Remove debug dependency of DPCD SW/HW revision read Performing DPCD AUX reads based on debug settings may introduce obscure bugs in other places that depend on the read being done (or being not done). To reduce the uncertainty perform the reads unconditionally. Cc: Mika Kahola Suggested-by: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477326811-30431-3-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 951a0bbc03c5..5af3907cf672 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1456,9 +1456,6 @@ static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) uint8_t rev; int len; - if ((drm_debug & DRM_UT_KMS) == 0) - return; - if (!drm_dp_is_branch(intel_dp->dpcd)) return; @@ -1474,9 +1471,6 @@ static void intel_dp_print_sw_revision(struct intel_dp *intel_dp) uint8_t rev[2]; int len; - if ((drm_debug & DRM_UT_KMS) == 0) - return; - if (!drm_dp_is_branch(intel_dp->dpcd)) return; -- cgit v1.2.3 From 5e8966774253778b861d5c0cbdaf66535233c873 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 24 Oct 2016 19:33:26 +0300 Subject: drm/i915/dp: Print only sink or branch specific OUI based on dev type There are two separate sets of DPCD registers for the DP OUI - as well as for the device ID and HW/SW revision - based on whether the given DP device is a branch or a sink. Currently we print both branch and sink OUIs, for consistency print only the one that corresponds to the probed device. v2: - Split out this change into a separate patch. (Jani) Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477326811-30431-4-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5af3907cf672..332dc86a325f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3624,17 +3624,17 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) static void intel_dp_probe_oui(struct intel_dp *intel_dp) { + bool is_branch = drm_dp_is_branch(intel_dp->dpcd); u8 buf[3]; if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3) - DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", - buf[0], buf[1], buf[2]); - - if (drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3) - DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", + if (drm_dp_dpcd_read(&intel_dp->aux, + is_branch ? DP_BRANCH_OUI : DP_SINK_OUI, + buf, 3) == 3) + DRM_DEBUG_KMS("%s OUI: %02hx%02hx%02hx\n", + is_branch ? "Branch" : "Sink", buf[0], buf[1], buf[2]); } -- cgit v1.2.3 From 7b3fc170d6a6ac1d1622178a2db317671cb89b9c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 25 Oct 2016 16:12:39 +0300 Subject: drm/i915/dp: Print full branch/sink descriptor Extend the branch/sink descriptor info with the missing device ID field. While at it also read out all the descriptor registers in one transfer and make the debug print more compact. v2: (Jani) - Cache the descriptor in intel_dp. - Split out this change into a separate patch. v3: (Jani) - Fix return value check of __intel_dp_read_desc(). - Use %pE instead of %s to print the device ID. Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477401159-15098-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 63 ++++++++++++++-------------------------- drivers/gpu/drm/i915/intel_drv.h | 10 +++++++ 2 files changed, 32 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 332dc86a325f..bff27b7c5b62 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1451,34 +1451,35 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) DRM_DEBUG_KMS("common rates: %s\n", str); } -static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) +static bool +__intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc) { - uint8_t rev; - int len; - - if (!drm_dp_is_branch(intel_dp->dpcd)) - return; + u32 base = drm_dp_is_branch(intel_dp->dpcd) ? DP_BRANCH_OUI : + DP_SINK_OUI; - len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_HW_REV, &rev, 1); - if (len < 0) - return; - - DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf); + return drm_dp_dpcd_read(&intel_dp->aux, base, desc, sizeof(*desc)) == + sizeof(*desc); } -static void intel_dp_print_sw_revision(struct intel_dp *intel_dp) +static bool intel_dp_read_desc(struct intel_dp *intel_dp) { - uint8_t rev[2]; - int len; + struct intel_dp_desc *desc = &intel_dp->desc; + bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & + DP_OUI_SUPPORT; + int dev_id_len; - if (!drm_dp_is_branch(intel_dp->dpcd)) - return; + if (!__intel_dp_read_desc(intel_dp, desc)) + return false; - len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV, &rev, 2); - if (len < 0) - return; + dev_id_len = strnlen(desc->device_id, sizeof(desc->device_id)); + DRM_DEBUG_KMS("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n", + drm_dp_is_branch(intel_dp->dpcd) ? "branch" : "sink", + (int)sizeof(desc->oui), desc->oui, oui_sup ? "" : "(NS)", + dev_id_len, desc->device_id, + desc->hw_rev >> 4, desc->hw_rev & 0xf, + desc->sw_major_rev, desc->sw_minor_rev); - DRM_DEBUG_KMS("sink sw revision: %d.%d\n", rev[0], rev[1]); + return true; } static int rate_to_index(int find, const int *rates) @@ -3621,23 +3622,6 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) return true; } -static void -intel_dp_probe_oui(struct intel_dp *intel_dp) -{ - bool is_branch = drm_dp_is_branch(intel_dp->dpcd); - u8 buf[3]; - - if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) - return; - - if (drm_dp_dpcd_read(&intel_dp->aux, - is_branch ? DP_BRANCH_OUI : DP_SINK_OUI, - buf, 3) == 3) - DRM_DEBUG_KMS("%s OUI: %02hx%02hx%02hx\n", - is_branch ? "Branch" : "Sink", - buf[0], buf[1], buf[2]); -} - static bool intel_dp_can_mst(struct intel_dp *intel_dp) { @@ -4416,10 +4400,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp_print_rates(intel_dp); - intel_dp_probe_oui(intel_dp); - - intel_dp_print_hw_revision(intel_dp); - intel_dp_print_sw_revision(intel_dp); + intel_dp_read_desc(intel_dp); intel_dp_configure_mst(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7dda79df55d0..65ebe92e0e96 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -883,6 +883,14 @@ enum link_m_n_set { M2_N2 }; +struct intel_dp_desc { + u8 oui[3]; + u8 device_id[6]; + u8 hw_rev; + u8 sw_major_rev; + u8 sw_minor_rev; +} __packed; + struct intel_dp { i915_reg_t output_reg; i915_reg_t aux_ch_ctl_reg; @@ -905,6 +913,8 @@ struct intel_dp { /* sink rates as reported by DP_SUPPORTED_LINK_RATES */ uint8_t num_sink_rates; int sink_rates[DP_MAX_SUPPORTED_RATES]; + /* sink or branch descriptor */ + struct intel_dp_desc desc; struct drm_dp_aux aux; uint8_t train_set[4]; int panel_power_up_delay; -- cgit v1.2.3 From 24e807e79f103cd9e7799eed704ed6916915d65a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 24 Oct 2016 19:33:28 +0300 Subject: drm/i915/lspcon: Fail LSPCON probe if the start of DPCD can't be read All types of DP devices (eDP, DP sink, DP branch) will fail their probe if the start of DPCD can't be read. The LSPCON PCON functionality also depends on accessing this area, so fail the probe if the read fails. Cc: Shashank Sharma Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477326811-30431-6-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_lspcon.c | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bff27b7c5b62..07a502fd6773 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3497,7 +3497,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) intel_dp->DP = DP; } -static bool +bool intel_dp_read_dpcd(struct intel_dp *intel_dp) { if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 65ebe92e0e96..b9583268aafb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1467,6 +1467,8 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) return ~((1 << lane_count) - 1) & 0xf; } +bool intel_dp_read_dpcd(struct intel_dp *intel_dp); + /* intel_dp_aux_backlight.c */ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector); diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 632149c6b3ad..23b817acd99d 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -131,6 +131,11 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port) } } + if (!intel_dp_read_dpcd(dp)) { + DRM_ERROR("LSPCON DPCD read failed\n"); + return false; + } + DRM_DEBUG_KMS("Success: LSPCON init\n"); return true; } -- cgit v1.2.3 From 12a47a422862214d3a715a0bd93140b8176dcdc9 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 24 Oct 2016 19:33:29 +0300 Subject: drm/i915/dp: Read DP descriptor for eDP and LSPCON too As for external DP sink and branch devices read and print the DP descriptor for eDP and LSPCON devices as well to aid debugging. v2: - Split out this change to a separate patch. (Jani) Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477326811-30431-7-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 4 +++- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_lspcon.c | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 07a502fd6773..6eb43647163c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1461,7 +1461,7 @@ __intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc) sizeof(*desc); } -static bool intel_dp_read_desc(struct intel_dp *intel_dp) +bool intel_dp_read_desc(struct intel_dp *intel_dp) { struct intel_dp_desc *desc = &intel_dp->desc; bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & @@ -3521,6 +3521,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) if (!intel_dp_read_dpcd(intel_dp)) return false; + intel_dp_read_desc(intel_dp); + if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_NO_AUX_HANDSHAKE_LINK_TRAINING; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b9583268aafb..20fb6e72e90e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1468,6 +1468,7 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) } bool intel_dp_read_dpcd(struct intel_dp *intel_dp); +bool intel_dp_read_desc(struct intel_dp *intel_dp); /* intel_dp_aux_backlight.c */ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector); diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 23b817acd99d..c5f278b250a7 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -136,6 +136,8 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port) return false; } + intel_dp_read_desc(dp); + DRM_DEBUG_KMS("Success: LSPCON init\n"); return true; } -- cgit v1.2.3 From a5d94b83ec709dbd90f17cba79142fde123d3869 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 24 Oct 2016 19:33:30 +0300 Subject: drm/i915/lspcon: Get DDC adapter via container_of() instead of cached ptr We can use the container_of() magic to get to the DDC adapter, so no need for caching a pointer to it. We'll also need to get at the intel_dp ptr in the following patch, so add a helper that can be used for both purposes. Cc: Shashank Sharma Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477326811-30431-8-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_lspcon.c | 15 +++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 20fb6e72e90e..5989c48d7964 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -974,7 +974,6 @@ struct intel_dp { struct intel_lspcon { bool active; enum drm_lspcon_mode mode; - struct drm_dp_aux *aux; }; struct intel_digital_port { diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index c5f278b250a7..3dc5a0be7857 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -27,10 +27,18 @@ #include #include "intel_drv.h" +static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon) +{ + struct intel_digital_port *dig_port = + container_of(lspcon, struct intel_digital_port, lspcon); + + return &dig_port->dp; +} + static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) { enum drm_lspcon_mode current_mode = DRM_LSPCON_MODE_INVALID; - struct i2c_adapter *adapter = &lspcon->aux->ddc; + struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc; if (drm_lspcon_get_mode(adapter, ¤t_mode)) DRM_ERROR("Error reading LSPCON mode\n"); @@ -45,7 +53,7 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon, { int err; enum drm_lspcon_mode current_mode; - struct i2c_adapter *adapter = &lspcon->aux->ddc; + struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc; err = drm_lspcon_get_mode(adapter, ¤t_mode); if (err) { @@ -72,7 +80,7 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon, static bool lspcon_probe(struct intel_lspcon *lspcon) { enum drm_dp_dual_mode_type adaptor_type; - struct i2c_adapter *adapter = &lspcon->aux->ddc; + struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc; /* Lets probe the adaptor and check its type */ adaptor_type = drm_dp_dual_mode_detect(adapter); @@ -111,7 +119,6 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port) lspcon->active = false; lspcon->mode = DRM_LSPCON_MODE_INVALID; - lspcon->aux = &dp->aux; if (!lspcon_probe(lspcon)) { DRM_ERROR("Failed to probe lspcon\n"); -- cgit v1.2.3 From 489375c866c111f16cea93b2467ebe59c9022cc7 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 24 Oct 2016 19:33:31 +0300 Subject: drm/i915/lspcon: Add workaround for resuming in PCON mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On my APL the LSPCON firmware resumes in PCON mode as opposed to the expected LS mode. It also appears to be in a state where AUX DPCD reads will succeed but return garbage recovering only after a few hundreds of milliseconds. After the recovery time DPCD reads will result in the correct values and things will continue to work. If I2C over AUX is attempted during this recovery time (implying an AUX write transaction) the firmware won't recover and will stay in this broken state. As a workaround check if the firmware is in PCON state after resume and if so wait until the correct DPCD values are returned. For this we compare the branch descriptor with the one we cached during init time. If the firmware was in the LS state, we skip the w/a and continue as before. v2: - Use the DP descriptor value cached in intel_dp. (Jani) - Get to intel_dp using container_of(), instead of a cached ptr. (Shashank) - Use usleep_range() instead of msleep(). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98353 Cc: Shashank Sharma Cc: Ville Syrjälä Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477326811-30431-9-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 3 +++ drivers/gpu/drm/i915/intel_lspcon.c | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 6eb43647163c..8f313c1d374d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1451,7 +1451,7 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) DRM_DEBUG_KMS("common rates: %s\n", str); } -static bool +bool __intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc) { u32 base = drm_dp_is_branch(intel_dp->dpcd) ? DP_BRANCH_OUI : diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5989c48d7964..c2f38634e86e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -974,6 +974,7 @@ struct intel_dp { struct intel_lspcon { bool active; enum drm_lspcon_mode mode; + bool desc_valid; }; struct intel_digital_port { @@ -1467,6 +1468,8 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) } bool intel_dp_read_dpcd(struct intel_dp *intel_dp); +bool __intel_dp_read_desc(struct intel_dp *intel_dp, + struct intel_dp_desc *desc); bool intel_dp_read_desc(struct intel_dp *intel_dp); /* intel_dp_aux_backlight.c */ diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 3dc5a0be7857..daa523410953 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -97,8 +97,43 @@ static bool lspcon_probe(struct intel_lspcon *lspcon) return true; } +static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon) +{ + struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); + unsigned long start = jiffies; + + if (!lspcon->desc_valid) + return; + + while (1) { + struct intel_dp_desc desc; + + /* + * The w/a only applies in PCON mode and we don't expect any + * AUX errors. + */ + if (!__intel_dp_read_desc(intel_dp, &desc)) + return; + + if (!memcmp(&intel_dp->desc, &desc, sizeof(desc))) { + DRM_DEBUG_KMS("LSPCON recovering in PCON mode after %u ms\n", + jiffies_to_msecs(jiffies - start)); + return; + } + + if (time_after(jiffies, start + msecs_to_jiffies(1000))) + break; + + usleep_range(10000, 15000); + } + + DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n"); +} + void lspcon_resume(struct intel_lspcon *lspcon) { + lspcon_resume_in_pcon_wa(lspcon); + if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON, true)) DRM_ERROR("LSPCON resume failed\n"); else @@ -143,7 +178,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port) return false; } - intel_dp_read_desc(dp); + lspcon->desc_valid = intel_dp_read_desc(dp); DRM_DEBUG_KMS("Success: LSPCON init\n"); return true; -- cgit v1.2.3 From 8244bd3ab405a1268223a282b32d28031f7e16fe Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Fri, 7 Oct 2016 18:55:47 +0800 Subject: spi: change post transfer udelay() to usleep_range() for long delays The spi_transfer parameter delay_usecs allows specifying a time to wait after transferring a spi message. This wait can be quite long - some devices, such as some Chrome OS ECs, require as much as 2000 usecs after a SPI transaction, before it can respond. (cf: arch/arm64/boot/dts/nvidia/tegra132-norrin.dts: google,cros-ec-spi-msg-delay = <2000> ) Blocking a CPU for 2 msecs in a busy loop like this doesn't seem very friendly to other processes, so change the blocking delay to a sleep to allow other things to use this CPU (or so it can sleep). This should be safe to do, because: (a) A post-transaction delay like this is always specified as a minimum wait time (b) A delay here is most likely not very time sensitive, as it occurs after all data has been transferred (c) This delay occurs in a non-critical section of the spi worker thread so where it is safe to sleep. Two caveats: 1) To avoid penalizing short delays, still use udelay for delays < 10us. 2) usleep_range() very often picks the upper bound, an upper bounds 10% should be plenty. Signed-off-by: Daniel Kurtz Signed-off-by: Mark Brown --- drivers/spi/spi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5787b723b593..42f3e1cb9212 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1034,8 +1034,14 @@ static int spi_transfer_one_message(struct spi_master *master, if (msg->status != -EINPROGRESS) goto out; - if (xfer->delay_usecs) - udelay(xfer->delay_usecs); + if (xfer->delay_usecs) { + u16 us = xfer->delay_usecs; + + if (us <= 10) + udelay(us); + else + usleep_range(us, us + DIV_ROUND_UP(us, 10)); + } if (xfer->cs_change) { if (list_is_last(&xfer->transfer_list, -- cgit v1.2.3 From aafee2eb8ce86c13b3dde819de2f93d0ba61a040 Mon Sep 17 00:00:00 2001 From: Arkadiusz Hiler Date: Tue, 25 Oct 2016 14:48:02 +0200 Subject: drm/i915: fix comment on I915_{READ, WRITE}_FW Comment mentioned use of intel_uncore_forcewake_irq{unlock, lock} functions which are nonexistent (and never were). The description was also incomplete and could cause confusion. Updated comment is more elaborate on usage and caveats. v2: mention __locked variant of intel_uncore_forcewake_{get,put} instead of plain ones Cc: Chris Wilson Cc: Matthew Auld Cc: Mika Kuoppala Signed-off-by: Arkadiusz Hiler Reviewed-by: Matthew Auld Reviewed-by: Chris Wilson [Mika: removed two superfluous lines on comment noted by Chris] Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1477399682-3133-1-git-send-email-arkadiusz.hiler@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7a621c74254e..55afb664b2f8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3844,11 +3844,30 @@ __raw_write(64, q) #undef __raw_write /* These are untraced mmio-accessors that are only valid to be used inside - * critical sections inside IRQ handlers where forcewake is explicitly + * critical sections, such as inside IRQ handlers, where forcewake is explicitly * controlled. + * * Think twice, and think again, before using these. - * Note: Should only be used between intel_uncore_forcewake_irqlock() and - * intel_uncore_forcewake_irqunlock(). + * + * As an example, these accessors can possibly be used between: + * + * spin_lock_irq(&dev_priv->uncore.lock); + * intel_uncore_forcewake_get__locked(); + * + * and + * + * intel_uncore_forcewake_put__locked(); + * spin_unlock_irq(&dev_priv->uncore.lock); + * + * + * Note: some registers may not need forcewake held, so + * intel_uncore_forcewake_{get,put} can be omitted, see + * intel_uncore_forcewake_for_reg(). + * + * Certain architectures will die if the same cacheline is concurrently accessed + * by different clients (e.g. on Ivybridge). Access to registers should + * therefore generally be serialised, by either the dev_priv->uncore.lock or + * a more localised lock guarding all access to that bank of registers. */ #define I915_READ_FW(reg__) __raw_i915_read32(dev_priv, (reg__)) #define I915_WRITE_FW(reg__, val__) __raw_i915_write32(dev_priv, (reg__), (val__)) -- cgit v1.2.3 From da064b47c0b8d0dff1905b38c76e7e51fb5a9547 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 24 Oct 2016 19:13:04 +0300 Subject: drm/i915: Fix SKL+ 90/270 degree rotated plane coordinate computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the framebuffer size in .16 fixed point coordinates to drm_rect_rotate() since that's what the source coordinates are as well at this stage. We used to do this part of the computation in integer coordinates, but that got changed when moving the computation to happen in the check phase of the operation. Unfortunately I forgot to shift up the fb width and height appropriately. With the bogus size we ended up with some negative fb offset, which when added to the vma offset caused out scanout to start at an offset earlier than we inteded. Eg. when testing on my SKL I saw a row of incorrect tiles at the top of my screen. Cc: Tvrtko Ursulin Cc: Sivakumar Thulasimani Cc: drm-intel-fixes@lists.freedesktop.org Fixes: b63a16f6cd89 ("drm/i915: Compute display surface offset in the plane check hook for SKL+") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477325584-23679-1-git-send-email-ville.syrjala@linux.intel.com Tested-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2a5a7c2868de..895b3dc50e3f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2985,7 +2985,8 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) /* Rotate src coordinates to match rotated GTT view */ if (drm_rotation_90_or_270(rotation)) drm_rect_rotate(&plane_state->base.src, - fb->width, fb->height, DRM_ROTATE_270); + fb->width << 16, fb->height << 16, + DRM_ROTATE_270); /* * Handle the AUX surface first since -- cgit v1.2.3 From 9ff7a1b0ba823b6cdefc10fc641b8289274d7d81 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 26 Oct 2016 19:29:19 +0300 Subject: drm: Print some debug/error info during DP dual mode detect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's at least one LSPCON device that occasionally returns an unexpected adaptor ID which leads to a failed detect. Print some debug info to help debugging this and future cases. Also print an error for an unexpected adaptor ID, so users can report it. v2: - s/adapter/adaptor/ and add code comment about incorrect type 1 adaptor IDs. (Ville) Cc: dri-devel@lists.freedesktop.org Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1477499359-12001-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/drm_dp_dual_mode_helper.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c index 488355bdafb9..e02563966271 100644 --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c @@ -142,6 +142,11 @@ static bool is_hdmi_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN]) sizeof(dp_dual_mode_hdmi_id)) == 0; } +static bool is_type1_adaptor(uint8_t adaptor_id) +{ + return adaptor_id == 0 || adaptor_id == 0xff; +} + static bool is_type2_adaptor(uint8_t adaptor_id) { return adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 | @@ -193,6 +198,8 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter) */ ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_HDMI_ID, hdmi_id, sizeof(hdmi_id)); + DRM_DEBUG_KMS("DP dual mode HDMI ID: %*pE (err %zd)\n", + ret ? 0 : (int)sizeof(hdmi_id), hdmi_id, ret); if (ret) return DRM_DP_DUAL_MODE_UNKNOWN; @@ -210,6 +217,8 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter) */ ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID, &adaptor_id, sizeof(adaptor_id)); + DRM_DEBUG_KMS("DP dual mode adaptor ID: %02x (err %zd)\n", + adaptor_id, ret); if (ret == 0) { if (is_lspcon_adaptor(hdmi_id, adaptor_id)) return DRM_DP_DUAL_MODE_LSPCON; @@ -219,6 +228,15 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter) else return DRM_DP_DUAL_MODE_TYPE2_DVI; } + /* + * If neither a proper type 1 ID nor a broken type 1 adaptor + * as described above, assume type 1, but let the user know + * that we may have misdetected the type. + */ + if (!is_type1_adaptor(adaptor_id) && adaptor_id != hdmi_id[0]) + DRM_ERROR("Unexpected DP dual mode adaptor ID %02x\n", + adaptor_id); + } if (is_hdmi_adaptor(hdmi_id)) -- cgit v1.2.3 From e9a2ea5a1ba09c35258f3663842fb8d8cf2e00c2 Mon Sep 17 00:00:00 2001 From: Fenghua Yu Date: Sat, 22 Oct 2016 06:19:49 -0700 Subject: cacheinfo: Introduce cache id Cache management software needs an id for each instance of a cache of a particular type. The current cacheinfo structure does not provide any information about the underlying hardware so there is no way to expose it. Hardware with cache management features provides means (cpuid, enumeration etc.) to retrieve the hardware id of a particular cache instance. Cache instances which share hardware have the same hardware id. Add an 'id' field to struct cacheinfo to store this information. Expose this information under the /sys/devices/system/cpu/cpu*/cache/index*/ directory as well. Signed-off-by: Fenghua Yu Cc: "Ravi V Shankar" Cc: "Tony Luck" Cc: "David Carrillo-Cisneros" Cc: "Sai Prakhya" Cc: "Peter Zijlstra" Cc: "Stephane Eranian" Cc: "Dave Hansen" Cc: "Shaohua Li" Cc: "Nilay Vaish" Cc: "Vikas Shivappa" Cc: "Ingo Molnar" Cc: "Borislav Petkov" Cc: "H. Peter Anvin" Link: http://lkml.kernel.org/r/1477142405-32078-3-git-send-email-fenghua.yu@intel.com Signed-off-by: Thomas Gleixner --- drivers/base/cacheinfo.c | 5 +++++ include/linux/cacheinfo.h | 3 +++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index e9fd32e91668..00a9688043f4 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -233,6 +233,7 @@ static ssize_t file_name##_show(struct device *dev, \ return sprintf(buf, "%u\n", this_leaf->object); \ } +show_one(id, id); show_one(level, level); show_one(coherency_line_size, coherency_line_size); show_one(number_of_sets, number_of_sets); @@ -314,6 +315,7 @@ static ssize_t write_policy_show(struct device *dev, return n; } +static DEVICE_ATTR_RO(id); static DEVICE_ATTR_RO(level); static DEVICE_ATTR_RO(type); static DEVICE_ATTR_RO(coherency_line_size); @@ -327,6 +329,7 @@ static DEVICE_ATTR_RO(shared_cpu_list); static DEVICE_ATTR_RO(physical_line_partition); static struct attribute *cache_default_attrs[] = { + &dev_attr_id.attr, &dev_attr_type.attr, &dev_attr_level.attr, &dev_attr_shared_cpu_map.attr, @@ -350,6 +353,8 @@ cache_default_attrs_is_visible(struct kobject *kobj, const struct cpumask *mask = &this_leaf->shared_cpu_map; umode_t mode = attr->mode; + if ((attr == &dev_attr_id.attr) && (this_leaf->attributes & CACHE_ID)) + return mode; if ((attr == &dev_attr_type.attr) && this_leaf->type) return mode; if ((attr == &dev_attr_level.attr) && this_leaf->level) diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 2189935075b4..0bcbb674da9d 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -18,6 +18,7 @@ enum cache_type { /** * struct cacheinfo - represent a cache leaf node + * @id: This cache's id. It is unique among caches with the same (type, level). * @type: type of the cache - data, inst or unified * @level: represents the hierarchy in the multi-level cache * @coherency_line_size: size of each cache line usually representing @@ -44,6 +45,7 @@ enum cache_type { * keeping, the remaining members form the core properties of the cache */ struct cacheinfo { + unsigned int id; enum cache_type type; unsigned int level; unsigned int coherency_line_size; @@ -61,6 +63,7 @@ struct cacheinfo { #define CACHE_WRITE_ALLOCATE BIT(3) #define CACHE_ALLOCATE_POLICY_MASK \ (CACHE_READ_ALLOCATE | CACHE_WRITE_ALLOCATE) +#define CACHE_ID BIT(4) struct device_node *of_node; bool disable_sysfs; -- cgit v1.2.3 From d92ead16be405b6d52ff7b366d1c9865ccc684bd Mon Sep 17 00:00:00 2001 From: Xo Wang Date: Fri, 21 Oct 2016 10:20:13 -0700 Subject: net: phy: broadcom: Add support for BCM54612E This PHY has internal delays enabled after reset. This clears the internal delay enables unless the interface specifically requests them. Signed-off-by: Xo Wang Reviewed-by: Florian Fainelli Reviewed-by: Joel Stanley Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/brcmphy.h | 1 + 2 files changed, 49 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 870327efccf7..583ef8a2ec8d 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -337,6 +337,41 @@ static int bcm5481_config_aneg(struct phy_device *phydev) return ret; } +static int bcm54612e_config_aneg(struct phy_device *phydev) +{ + int ret; + + /* First, auto-negotiate. */ + ret = genphy_config_aneg(phydev); + + /* Clear TX internal delay unless requested. */ + if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) && + (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) { + /* Disable TXD to GTXCLK clock delay (default set) */ + /* Bit 9 is the only field in shadow register 00011 */ + bcm_phy_write_shadow(phydev, 0x03, 0); + } + + /* Clear RX internal delay unless requested. */ + if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) && + (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) { + u16 reg; + + /* Errata: reads require filling in the write selector field */ + bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, + MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC); + reg = phy_read(phydev, MII_BCM54XX_AUX_CTL); + /* Disable RXD to RXC delay (default set) */ + reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW; + /* Clear shadow selector field */ + reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK; + bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, + MII_BCM54XX_AUXCTL_MISC_WREN | reg); + } + + return ret; +} + static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) { int val; @@ -484,6 +519,18 @@ static struct phy_driver broadcom_drivers[] = { .read_status = genphy_read_status, .ack_interrupt = bcm_phy_ack_intr, .config_intr = bcm_phy_config_intr, +}, { + .phy_id = PHY_ID_BCM54612E, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM54612E", + .features = PHY_GBIT_FEATURES | + SUPPORTED_Pause | SUPPORTED_Asym_Pause, + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .config_init = bcm54xx_config_init, + .config_aneg = bcm54612e_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, }, { .phy_id = PHY_ID_BCM54616S, .phy_id_mask = 0xfffffff0, @@ -600,6 +647,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = { { PHY_ID_BCM5411, 0xfffffff0 }, { PHY_ID_BCM5421, 0xfffffff0 }, { PHY_ID_BCM5461, 0xfffffff0 }, + { PHY_ID_BCM54612E, 0xfffffff0 }, { PHY_ID_BCM54616S, 0xfffffff0 }, { PHY_ID_BCM5464, 0xfffffff0 }, { PHY_ID_BCM5481, 0xfffffff0 }, diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 22c4421c916c..60def78c4e12 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -18,6 +18,7 @@ #define PHY_ID_BCM5421 0x002060e0 #define PHY_ID_BCM5464 0x002060b0 #define PHY_ID_BCM5461 0x002060c0 +#define PHY_ID_BCM54612E 0x03625e60 #define PHY_ID_BCM54616S 0x03625d10 #define PHY_ID_BCM57780 0x03625d90 -- cgit v1.2.3 From 1c00164d4cd1f513ea44a1b068490e52e7cbf04f Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Mon, 24 Oct 2016 17:28:21 -0700 Subject: drm/i915/DMC/KBL: Load DMC on KBL using the no_stepping_info array Currently, for display there is only one DMC image for KBL. Remove the stepping_info table for KBL and use the no_stepping_info array for loading the firmware. v2: Removed the block of code as pointed out by Rodrigo to make the loads as generic as possible. Cc: Rodrigo Vivi Signed-off-by: Anusha Srivatsa Reviewed-by: Rodrigo Vivi Acked-by: Imre Deak Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1477355301-7035-1-git-send-email-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/intel_csr.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 1ea0e1f43397..d7a04bca8c28 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -168,12 +168,6 @@ struct stepping_info { char substepping; }; -static const struct stepping_info kbl_stepping_info[] = { - {'A', '0'}, {'B', '0'}, {'C', '0'}, - {'D', '0'}, {'E', '0'}, {'F', '0'}, - {'G', '0'}, {'H', '0'}, {'I', '0'}, -}; - static const struct stepping_info skl_stepping_info[] = { {'A', '0'}, {'B', '0'}, {'C', '0'}, {'D', '0'}, {'E', '0'}, {'F', '0'}, @@ -194,10 +188,7 @@ intel_get_stepping_info(struct drm_i915_private *dev_priv) const struct stepping_info *si; unsigned int size; - if (IS_KABYLAKE(dev_priv)) { - size = ARRAY_SIZE(kbl_stepping_info); - si = kbl_stepping_info; - } else if (IS_SKYLAKE(dev_priv)) { + if (IS_SKYLAKE(dev_priv)) { size = ARRAY_SIZE(skl_stepping_info); si = skl_stepping_info; } else if (IS_BROXTON(dev_priv)) { -- cgit v1.2.3 From 1aaa87aff688bbb47e9ab36c638e1bb876810a39 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 12:32:04 +0000 Subject: net: netcp: drop kfree for memory allocated with devm_kzalloc It's not necessary to free memory allocated with devm_kzalloc in the remove path and using kfree leads to a double free. Fixes: 84640e27f230 ("net: netcp: Add Keystone NetCP core ethernet driver") Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/netcp_core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 11609d5467fc..2fb5b6dd5231 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -2058,7 +2058,6 @@ static void netcp_delete_interface(struct netcp_device *netcp_device, if (module->release) module->release(intf_modpriv->module_priv); list_del(&intf_modpriv->intf_list); - kfree(intf_modpriv); } WARN(!list_empty(&netcp->module_head), "%s interface module list is not empty!\n", ndev->name); @@ -2153,7 +2152,6 @@ static int netcp_remove(struct platform_device *pdev) dev_dbg(&pdev->dev, "Removing module \"%s\"\n", module->name); module->remove(netcp_device, inst_modpriv->module_priv); list_del(&inst_modpriv->inst_list); - kfree(inst_modpriv); } /* now that all modules are removed, clean up the interfaces */ -- cgit v1.2.3 From 68497a87c4f4f918cbbdbae88652e796c75e11bd Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 14:28:00 +0000 Subject: net: dsa: mv88e6xxx: use setup_timer to simplify the code Use setup_timer function instead of initializing timer with the function and data fields. Signed-off-by: Wei Yongjun Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 157360f25069..72b9dac29901 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -639,9 +639,8 @@ static void mv88e6xxx_ppu_state_init(struct mv88e6xxx_chip *chip) { mutex_init(&chip->ppu_mutex); INIT_WORK(&chip->ppu_work, mv88e6xxx_ppu_reenable_work); - init_timer(&chip->ppu_timer); - chip->ppu_timer.data = (unsigned long)chip; - chip->ppu_timer.function = mv88e6xxx_ppu_reenable_timer; + setup_timer(&chip->ppu_timer, mv88e6xxx_ppu_reenable_timer, + (unsigned long)chip); } static void mv88e6xxx_ppu_state_destroy(struct mv88e6xxx_chip *chip) -- cgit v1.2.3 From a24a9d7aca2daef4ac87d1ef00ef21586ec6affe Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 14:28:38 +0000 Subject: net: eth: altera: Fix error return code in altera_tse_probe() Fix to return error code -EINVAL from the error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/altera/altera_tse_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index cc9787e33acf..8e9208434262 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -1329,11 +1329,13 @@ static int altera_tse_probe(struct platform_device *pdev) if (upper_32_bits(priv->rxdescmem_busaddr)) { dev_dbg(priv->device, "SGDMA bus addresses greater than 32-bits\n"); + ret = -EINVAL; goto err_free_netdev; } if (upper_32_bits(priv->txdescmem_busaddr)) { dev_dbg(priv->device, "SGDMA bus addresses greater than 32-bits\n"); + ret = -EINVAL; goto err_free_netdev; } } else if (priv->dmaops && -- cgit v1.2.3 From 0942170f32e1e9076f9a5f350250b8ec59ac04fa Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 14:34:55 +0000 Subject: net: ns83820: use dev_kfree_skb_irq instead of kfree_skb It is not allowed to call kfree_skb() from hardware interrupt context or with interrupts being disabled, spin_lock_irqsave() make sure always in irq disable context. So the kfree_skb() should be replaced with dev_kfree_skb_irq(). This is detected by Coccinelle semantic patch. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/ns83820.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index a34631ed741d..93c4bdc0cdca 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -919,7 +919,7 @@ netdev_mangle_me_harder_failed: ndev->stats.rx_dropped++; } } else { - kfree_skb(skb); + dev_kfree_skb_irq(skb); } nr++; -- cgit v1.2.3 From 675a6ceefc31a952bd5a29b6433c2c2d8c595af3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 14:35:30 +0000 Subject: amd-xgbe: Fix error return code in xgbe_probe() Fix to return error code -ENODEV from the DMA is not supported error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 667e1209a2f5..6997f1110ece 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -613,6 +613,7 @@ static int xgbe_probe(struct platform_device *pdev) attr = device_get_dma_attr(dev); if (attr == DEV_DMA_NOT_SUPPORTED) { dev_err(dev, "DMA is not supported"); + ret = -ENODEV; goto err_io; } pdata->coherent = (attr == DEV_DMA_COHERENT); -- cgit v1.2.3 From f850b4a77d71a9cac513dadff91891a78c12ba05 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 14:36:36 +0000 Subject: net: ena: use setup_timer() and mod_timer() Use setup_timer() instead of init_timer(), being the preferred/standard way to set a timer up. Also, quoting the mod_timer() function comment: -> mod_timer() is a more efficient way to update the expire field of an active timer (if the timer is inactive it will be activated). Use setup_timer and mod_timer to setup and arm a timer, to make the code cleaner and easier to read. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 2a55ab00686a..cc8b13ebfa75 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -3013,12 +3013,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->last_keep_alive_jiffies = jiffies; - init_timer(&adapter->timer_service); - adapter->timer_service.expires = round_jiffies(jiffies + HZ); - adapter->timer_service.function = ena_timer_service; - adapter->timer_service.data = (unsigned long)adapter; - - add_timer(&adapter->timer_service); + setup_timer(&adapter->timer_service, ena_timer_service, + (unsigned long)adapter); + mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ)); dev_info(&pdev->dev, "%s found at mem %lx, mac addr %pM Queues %d\n", DEVICE_NAME, (long)pci_resource_start(pdev, 0), -- cgit v1.2.3 From e2897b8238ab8fdee067cfe472dd52a3414d5716 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Oct 2016 14:40:17 +0000 Subject: net: netcp: add missing of_node_put() in netcp_probe() This node pointer is returned by of_get_child_by_name() with refcount incremented in this function. of_node_put() on it before exitting this function. This is detected by Coccinelle semantic patch. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/netcp_core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 2fb5b6dd5231..78b4c831f5ad 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -2120,6 +2120,8 @@ static int netcp_probe(struct platform_device *pdev) } } + of_node_put(interfaces); + /* Add the device instance to the list */ list_add_tail(&netcp_device->device_list, &netcp_devices); @@ -2132,6 +2134,8 @@ probe_quit_interface: netcp_delete_interface(netcp_device, netcp_intf->ndev); } + of_node_put(interfaces); + probe_quit: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); -- cgit v1.2.3 From 5d48f00d836a628c695c6e3f96881d73641f6a2f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Oct 2016 16:29:03 +0200 Subject: firewire: net: fix maximum possible MTU Commit b3e3893e1253 ("net: use core MTU range checking in misc drivers") mistakenly introduced an upper limit for firewire-net's MTU based on the local link layer controller's reception capability. Revert this. Neither RFC 2734 nor our implementation impose any particular upper limit. Actually, to be on the safe side and to make the code explicit, set ETH_MAX_MTU = 65535 as upper limit now. (I replaced sizeof(struct rfc2734_header) by the equivalent RFC2374_FRAG_HDR_SIZE in order to avoid distracting long/int conversions.) Fixes: b3e3893e1253('net: use core MTU range checking in misc drivers') CC: netdev@vger.kernel.org CC: linux1394-devel@lists.sourceforge.net CC: Jarod Wilson Signed-off-by: Stefan Richter Acked-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/firewire/net.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 8430222151fc..99379542b263 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -1467,10 +1467,11 @@ static int fwnet_probe(struct fw_unit *unit, * Use the RFC 2734 default 1500 octets or the maximum payload * as initial MTU */ - net->max_mtu = (1 << (card->max_receive + 1)) - - sizeof(struct rfc2734_header) - IEEE1394_GASP_HDR_SIZE; - net->mtu = min(1500U, net->max_mtu); + net->mtu = min(1500U, + (1U << (card->max_receive + 1)) + - RFC2374_FRAG_HDR_SIZE - IEEE1394_GASP_HDR_SIZE); net->min_mtu = ETH_MIN_MTU; + net->max_mtu = ETH_MAX_MTU; /* Set our hardware address while we're at it */ ha = (union fwnet_hwaddr *)net->dev_addr; -- cgit v1.2.3 From 89ab88b01bacc5bfc338693da3925504757e7844 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Oct 2016 16:30:56 +0200 Subject: firewire: net: set initial MTU = 1500 unconditionally, fix IPv6 on some CardBus cards firewire-net, like the older eth1394 driver, reduced the initial MTU to less than 1500 octets if the local link layer controller's asynchronous packet reception limit was lower. This is bogus, since this reception limit does not have anything to do with the transmission limit. Neither did this reduction affect the TX path positively, nor could it prevent link fragmentation at the RX path. Many FireWire CardBus cards have a max_rec of 9, causing an initial MTU of 1024 - 16 = 1008. RFC 2734 and RFC 3146 allow a minimum max_rec = 8, which would result in an initial MTU of 512 - 16 = 496. On such cards, IPv6 could only be employed if the MTU was manually increased to 1280 or more, i.e. IPv6 would not work without intervention from userland. We now always initialize the MTU to 1500, which is the default according to RFC 2734 and RFC 3146. On a VIA VT6316 based CardBus card which was affected by this, changing the MTU from 1008 to 1500 also increases TX bandwidth by 6 %. RX remains unaffected. CC: netdev@vger.kernel.org CC: linux1394-devel@lists.sourceforge.net CC: Jarod Wilson Signed-off-by: Stefan Richter Signed-off-by: David S. Miller --- drivers/firewire/net.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 99379542b263..03715e7d9d92 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -1463,13 +1463,7 @@ static int fwnet_probe(struct fw_unit *unit, goto out; dev->local_fifo = dev->handler.offset; - /* - * Use the RFC 2734 default 1500 octets or the maximum payload - * as initial MTU - */ - net->mtu = min(1500U, - (1U << (card->max_receive + 1)) - - RFC2374_FRAG_HDR_SIZE - IEEE1394_GASP_HDR_SIZE); + net->mtu = 1500U; net->min_mtu = ETH_MIN_MTU; net->max_mtu = ETH_MAX_MTU; -- cgit v1.2.3 From 6d86c4714da526243d7b0578eaf5e1b54f8c2ed2 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 25 Oct 2016 09:35:40 -0700 Subject: Input: pxa27x_keypad - fix typo "debpunce" -> "debounce" Trivial fix to typo in dev_err message Signed-off-by: Colin Ian King Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/pxa27x_keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index fcef5d1365e2..e24443376e75 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -316,7 +316,7 @@ static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad) error = of_property_read_u32(np, "marvell,debounce-interval", &pdata->debounce_interval); if (error) { - dev_err(dev, "failed to parse debpunce-interval\n"); + dev_err(dev, "failed to parse debounce-interval\n"); return error; } -- cgit v1.2.3 From 04d7ad83c6a61395582cd236aa6dc61c8430e227 Mon Sep 17 00:00:00 2001 From: Steve Twiss Date: Wed, 26 Oct 2016 15:49:13 -0700 Subject: Input: da9061 - onkey driver Copyright header is updated to add DA9061 in its description and the module description macro is extended to include DA9061. Minor change to the code, alters dev_dbg() statements to report a generic "PMIC" instead of DA9063. This device driver is compatible with DA9061, DA9062 and DA9063. Kconfig is updated to reflect support for DA9061/62/63. Signed-off-by: Steve Twiss Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 7 ++++--- drivers/input/misc/da9063_onkey.c | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7ffb614ce566..1ae4d9617ff8 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -625,11 +625,12 @@ config INPUT_DA9055_ONKEY will be called da9055_onkey. config INPUT_DA9063_ONKEY - tristate "Dialog DA9062/63 OnKey" + tristate "Dialog DA9063/62/61 OnKey" depends on MFD_DA9063 || MFD_DA9062 help - Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs - as an input device capable of reporting the power button status. + Support the ONKEY of Dialog DA9063, DA9062 and DA9061 Power + Management ICs as an input device capable of reporting the + power button status. To compile this driver as a module, choose M here: the module will be called da9063_onkey. diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c index bb863e062b03..dff6fe5724fe 100644 --- a/drivers/input/misc/da9063_onkey.c +++ b/drivers/input/misc/da9063_onkey.c @@ -1,5 +1,5 @@ /* - * OnKey device driver for DA9063 and DA9062 PMICs + * OnKey device driver for DA9063, DA9062 and DA9061 PMICs * Copyright (C) 2015 Dialog Semiconductor Ltd. * * This program is free software; you can redistribute it and/or @@ -149,13 +149,13 @@ static void da9063_poll_on(struct work_struct *work) * and then send shutdown command */ dev_dbg(&onkey->input->dev, - "Sending SHUTDOWN to DA9063 ...\n"); + "Sending SHUTDOWN to PMIC ...\n"); error = regmap_write(onkey->regmap, config->onkey_shutdown, config->onkey_shutdown_mask); if (error) dev_err(&onkey->input->dev, - "Cannot SHUTDOWN DA9063: %d\n", + "Cannot SHUTDOWN PMIC: %d\n", error); } } @@ -300,6 +300,6 @@ static struct platform_driver da9063_onkey_driver = { module_platform_driver(da9063_onkey_driver); MODULE_AUTHOR("S Twiss "); -MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062"); +MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063, DA9062 and DA9061"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY); -- cgit v1.2.3 From c2c4ba82022cbe14ab15f394078aaf592664bd69 Mon Sep 17 00:00:00 2001 From: Sangwon Jee Date: Wed, 26 Oct 2016 15:53:13 -0700 Subject: Input: melfas_mip4 - use product id for firmware name Use product id for firmware name to request compatible firmware. Signed-off-by: Sangwon Jee Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/melfas_mip4.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 8739cb718b4c..0f2230a9b1a1 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -162,6 +162,7 @@ struct mip4_ts { char product_name[16]; u16 product_id; char ic_name[4]; + char fw_name[32]; unsigned int max_x; unsigned int max_y; @@ -280,6 +281,11 @@ static int mip4_query_device(struct mip4_ts *ts) dev_dbg(&ts->client->dev, "product id: %04X\n", ts->product_id); } + /* Firmware name */ + snprintf(ts->fw_name, sizeof(ts->fw_name), + "melfas_mip4_%04X.fw", ts->product_id); + dev_dbg(&ts->client->dev, "firmware name: %s\n", ts->fw_name); + /* IC name */ cmd[0] = MIP4_R0_INFO; cmd[1] = MIP4_R1_INFO_IC_NAME; @@ -1285,11 +1291,11 @@ static ssize_t mip4_sysfs_fw_update(struct device *dev, const struct firmware *fw; int error; - error = request_firmware(&fw, MIP4_FW_NAME, dev); + error = request_firmware(&fw, ts->fw_name, dev); if (error) { dev_err(&ts->client->dev, "Failed to retrieve firmware %s: %d\n", - MIP4_FW_NAME, error); + ts->fw_name, error); return error; } @@ -1608,6 +1614,6 @@ static struct i2c_driver mip4_driver = { module_i2c_driver(mip4_driver); MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen"); -MODULE_VERSION("2016.10.20"); +MODULE_VERSION("2016.10.24"); MODULE_AUTHOR("Sangwon Jee "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ea4348c8462a20e8b1b6455a7145d2b86f8a49b6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 26 Oct 2016 15:55:02 -0700 Subject: Input: tca8418_keypad - hide gcc-4.9 -Wmaybe-uninitialized warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older versions of gcc warn about the tca8418_irq_handler function as they can't keep track of the variable assignment inside of the loop when using the -Wmaybe-unintialized flag: drivers/input/keyboard/tca8418_keypad.c: In function ‘tca8418_irq_handler’: drivers/input/keyboard/tca8418_keypad.c:172:9: error: ‘reg’ may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/input/keyboard/tca8418_keypad.c:165:5: note: ‘reg’ was declared here This is fixed in gcc-6, but it's possible to rearrange the code in a way that avoids the warning on older compilers as well. Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tca8418_keypad.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 9002298698fc..3048ef3e3e16 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -164,11 +164,18 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data) int error, col, row; u8 reg, state, code; - /* Initial read of the key event FIFO */ - error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, ®); + do { + error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, ®); + if (error < 0) { + dev_err(&keypad_data->client->dev, + "unable to read REG_KEY_EVENT_A\n"); + break; + } + + /* Assume that key code 0 signifies empty FIFO */ + if (reg <= 0) + break; - /* Assume that key code 0 signifies empty FIFO */ - while (error >= 0 && reg > 0) { state = reg & KEY_EVENT_VALUE; code = reg & KEY_EVENT_CODE; @@ -184,11 +191,7 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data) /* Read for next loop */ error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, ®); - } - - if (error < 0) - dev_err(&keypad_data->client->dev, - "unable to read REG_KEY_EVENT_A\n"); + } while (1); input_sync(input); } -- cgit v1.2.3 From 39a0d75ae32c061fa403824e56438501d7fb09f7 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 26 Oct 2016 16:26:19 -0700 Subject: Input: elan_i2c - always output the device information it's always easier to retrieve these information in bug reports when it is always printed in the dmesg. Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index d15b33813021..fa598f7f4372 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1093,19 +1093,18 @@ static int elan_probe(struct i2c_client *client, if (error) return error; + dev_info(&client->dev, + "Elan Touchpad: Module ID: 0x%04x, Firmware: 0x%04x, Sample: 0x%04x, IAP: 0x%04x\n", + data->product_id, + data->fw_version, + data->sm_version, + data->iap_version); + dev_dbg(&client->dev, - "Elan Touchpad Information:\n" - " Module product ID: 0x%04x\n" - " Firmware Version: 0x%04x\n" - " Sample Version: 0x%04x\n" - " IAP Version: 0x%04x\n" + "Elan Touchpad Extra Information:\n" " Max ABS X,Y: %d,%d\n" " Width X,Y: %d,%d\n" " Resolution X,Y: %d,%d (dots/mm)\n", - data->product_id, - data->fw_version, - data->sm_version, - data->iap_version, data->max_x, data->max_y, data->width_x, data->width_y, data->x_res, data->y_res); -- cgit v1.2.3 From e1cb73f6f53676fa6ca7eec6b3c371cf68a6797e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 26 Oct 2016 16:46:20 -0700 Subject: Input: fsl-imx25-tcq - fix module autoload when registered via OF If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/input/touchscreen/fsl-imx25-tcq.ko | grep alias After this patch: $ modinfo drivers/input/touchscreen/fsl-imx25-tcq.ko | grep alias alias: of:N*T*Cfsl,imx25-tcqC* alias: of:N*T*Cfsl,imx25-tcq Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/fsl-imx25-tcq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c index fe9877a6af9e..d50ee490c9cc 100644 --- a/drivers/input/touchscreen/fsl-imx25-tcq.c +++ b/drivers/input/touchscreen/fsl-imx25-tcq.c @@ -55,6 +55,7 @@ static const struct of_device_id mx25_tcq_ids[] = { { .compatible = "fsl,imx25-tcq", }, { /* Sentinel */ } }; +MODULE_DEVICE_TABLE(of, mx25_tcq_ids); #define TSC_4WIRE_PRE_INDEX 0 #define TSC_4WIRE_X_INDEX 1 -- cgit v1.2.3 From 8dd5e0b364e5b83864cd918475e5a5ef3b352446 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 26 Oct 2016 16:46:41 -0700 Subject: Input: da9063 - fix module autoload when registered via OF If the driver is built as a module, autoload won't work because the module alias information is not filled. So user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/input/misc/da9063_onkey.ko | grep alias alias: platform:da9063-onkey After this patch: $ modinfo drivers/input/misc/da9063_onkey.ko | grep alias alias: platform:da9063-onkey alias: of:N*T*Cdlg,da9062-onkeyC* alias: of:N*T*Cdlg,da9062-onkey alias: of:N*T*Cdlg,da9063-onkeyC* alias: of:N*T*Cdlg,da9063-onkey Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/misc/da9063_onkey.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c index dff6fe5724fe..b4ff1e86d3d3 100644 --- a/drivers/input/misc/da9063_onkey.c +++ b/drivers/input/misc/da9063_onkey.c @@ -87,6 +87,7 @@ static const struct of_device_id da9063_compatible_reg_id_table[] = { { .compatible = "dlg,da9062-onkey", .data = &da9062_regs }, { }, }; +MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table); static void da9063_poll_on(struct work_struct *work) { -- cgit v1.2.3 From 23736d1b1b2321f7e4647d8d5f8ff16fab11d24f Mon Sep 17 00:00:00 2001 From: Ping Gao Date: Wed, 26 Oct 2016 09:38:52 +0800 Subject: drm/i915/gvt: add full vGPU reset support Full vGPU reset need to release all the shadow PPGGT pages to avoid unnecessary write-protect and also should re-initialize pvinfo after resetting vregs to keep pvinfo correct. Signed-off-by: Ping Gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gvt.h | 2 ++ drivers/gpu/drm/i915/gvt/handlers.c | 10 ++++++++++ drivers/gpu/drm/i915/gvt/vgpu.c | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 11df62b542b1..62fc9e3ac5c6 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -382,6 +382,8 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu); int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa); int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci); +int setup_vgpu_mmio(struct intel_vgpu *vgpu); +void populate_pvinfo_page(struct intel_vgpu *vgpu); #include "mpt.h" diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 7832e49ed5b3..4850cf3e0dbd 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -251,6 +251,16 @@ static int handle_device_reset(struct intel_vgpu *vgpu, unsigned int offset, intel_vgpu_reset_execlist(vgpu, bitmap); + /* full GPU reset */ + if (bitmap == 0xff) { + mutex_unlock(&vgpu->gvt->lock); + intel_vgpu_clean_gtt(vgpu); + mutex_lock(&vgpu->gvt->lock); + setup_vgpu_mmio(vgpu); + populate_pvinfo_page(vgpu); + intel_vgpu_init_gtt(vgpu); + } + vgpu->resetting = false; return 0; diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 9401436d721f..4f54005b976d 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -41,7 +41,7 @@ static void clean_vgpu_mmio(struct intel_vgpu *vgpu) vgpu->mmio.vreg = vgpu->mmio.sreg = NULL; } -static int setup_vgpu_mmio(struct intel_vgpu *vgpu) +int setup_vgpu_mmio(struct intel_vgpu *vgpu) { struct intel_gvt *gvt = vgpu->gvt; const struct intel_gvt_device_info *info = &gvt->device_info; @@ -103,7 +103,7 @@ static void setup_vgpu_cfg_space(struct intel_vgpu *vgpu, } } -static void populate_pvinfo_page(struct intel_vgpu *vgpu) +void populate_pvinfo_page(struct intel_vgpu *vgpu) { /* setup the ballooning information */ vgpu_vreg64(vgpu, vgtif_reg(magic)) = VGT_MAGIC; -- cgit v1.2.3 From 6fb5082a8c4243c22ecf310b9f3add8371dfa26e Mon Sep 17 00:00:00 2001 From: Bing Niu Date: Mon, 31 Oct 2016 17:35:12 +0800 Subject: drm/i915/gvt: throw error basing on execlist submit result throw error message in elsp emulation handler basing on execlist submit result. guest will trigger tdr process for recovering, gvt just follow guest's desire. v2: populate error to top of mmio emulation logic, comments from zhenyu Signed-off-by: Bing Niu Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/handlers.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 4850cf3e0dbd..9ab1f95dddc5 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1320,7 +1320,7 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); struct intel_vgpu_execlist *execlist; u32 data = *(u32 *)p_data; - int ret; + int ret = 0; if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1)) return -EINVAL; @@ -1328,12 +1328,15 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, execlist = &vgpu->execlist[ring_id]; execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data; - if (execlist->elsp_dwords.index == 3) + if (execlist->elsp_dwords.index == 3) { ret = intel_vgpu_submit_execlist(vgpu, ring_id); + if(ret) + gvt_err("fail submit workload on ring %d\n", ring_id); + } ++execlist->elsp_dwords.index; execlist->elsp_dwords.index &= 0x3; - return 0; + return ret; } static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, -- cgit v1.2.3 From e45d7b7f47a4849a5d3d55a2cf5802a72924d37b Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Thu, 27 Oct 2016 11:10:31 +0800 Subject: drm/i915/gvt: fix nested sleeping issue We cannot use blocking method mutex_lock inside a wait loop. Here we invoke pick_next_workload() which needs acquire a mutex in our "condition" experssion. Then we go into a another of the going-to-sleep sequence and changing the task state. This is a dangerous. Let's rewrite the wait sequence to avoid nested sleeping. v2: fix do...while loop exit condition (zhenyu) v3: rebase to gvt-staging branch Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/scheduler.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index e96eaeebeb0a..f7e320b9b17a 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -402,19 +402,24 @@ static int workload_thread(void *priv) struct intel_vgpu_workload *workload = NULL; int ret; bool need_force_wake = IS_SKYLAKE(gvt->dev_priv); + DEFINE_WAIT_FUNC(wait, woken_wake_function); kfree(p); gvt_dbg_core("workload thread for ring %d started\n", ring_id); while (!kthread_should_stop()) { - ret = wait_event_interruptible(scheduler->waitq[ring_id], - kthread_should_stop() || - (workload = pick_next_workload(gvt, ring_id))); - - WARN_ON_ONCE(ret); - - if (kthread_should_stop()) + add_wait_queue(&scheduler->waitq[ring_id], &wait); + do { + workload = pick_next_workload(gvt, ring_id); + if (workload) + break; + wait_woken(&wait, TASK_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT); + } while (!kthread_should_stop()); + remove_wait_queue(&scheduler->waitq[ring_id], &wait); + + if (!workload) break; mutex_lock(&scheduler_mutex); -- cgit v1.2.3 From 3a81e96094b769d9cf5dc58761b9b85fa889e3aa Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 27 Oct 2016 00:58:36 +0800 Subject: drm/bridge: fix semicolon.cocci warnings drivers/gpu/drm/bridge/sil-sii8620.c:988:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci CC: Andrzej Hajda Signed-off-by: Fengguang Wu Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/20161026165836.GA98907@lkp-sb04.lkp.intel.com --- drivers/gpu/drm/bridge/sil-sii8620.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c index 1345e7cc7bf0..4f0526e9edbe 100644 --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -985,7 +985,7 @@ static void sii8620_set_mode(struct sii8620 *ctx, enum sii8620_mode mode) default: dev_err(ctx->dev, "%s mode %d not supported\n", __func__, mode); break; - }; + } sii8620_set_auto_zone(ctx); -- cgit v1.2.3 From 56df51d003203f1c3a8eab05605973515aa15feb Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 27 Oct 2016 00:58:36 +0800 Subject: drm/bridge: fix platform_no_drv_owner.cocci warnings drivers/gpu/drm/bridge/sil-sii8620.c:1556:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci CC: Andrzej Hajda Signed-off-by: Fengguang Wu Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/20161026165836.GA98766@lkp-sb04.lkp.intel.com --- drivers/gpu/drm/bridge/sil-sii8620.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c index 4f0526e9edbe..b2c267df7ee7 100644 --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -1553,7 +1553,6 @@ MODULE_DEVICE_TABLE(i2c, sii8620_id); static struct i2c_driver sii8620_driver = { .driver = { .name = "sii8620", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(sii8620_dt_match), }, .probe = sii8620_probe, -- cgit v1.2.3 From 8f20542386c57bc5f40a09e38d2772d84c0b2afa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 18 Oct 2016 10:28:57 +0200 Subject: wireless: deprecate WDS and disable by default The old WDS 4-addr frame support is very limited, e.g. * no encryption is possible on such links * it cannot support rate/HT/VHT negotiation * management APIs are very restricted These make the WDS legacy mode useless in practice. All of these are resolved by the 4-addr AP/client support, so there's also no reason to improve WDS in the future. Therefore, add a Kconfig option to disable legacy WDS. This gives people an "emergency valve" while they migrate to the better-supported 4-addr AP/client option; we plan to remove it (and the associated cfg80211/mac80211 code, which is the ultimate goal) in the future. Signed-off-by: Johannes Berg --- drivers/net/wireless/Kconfig | 13 +++++++++++++ drivers/net/wireless/ath/ath9k/init.c | 6 ++++++ drivers/net/wireless/broadcom/b43/main.c | 2 ++ drivers/net/wireless/broadcom/b43legacy/main.c | 2 ++ drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 6 ++++-- net/wireless/core.c | 10 ++++++++++ 6 files changed, 37 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 8c8edaf1bba6..8f5a3f4a43f2 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -17,6 +17,19 @@ menuconfig WLAN if WLAN +config WIRELESS_WDS + bool "mac80211-based legacy WDS support" if EXPERT + help + This option enables the deprecated WDS support, the newer + mac80211-based 4-addr AP/client support supersedes it with + a much better feature set (HT, VHT, ...) + + We plan to remove this option and code, so if you find + that you have to enable it, please let us know on the + linux-wireless@vger.kernel.org mailing list, so we can + help you migrate to 4-addr AP/client (or, if it's really + necessary, give up on our plan of removing it). + source "drivers/net/wireless/admtek/Kconfig" source "drivers/net/wireless/ath/Kconfig" source "drivers/net/wireless/atmel/Kconfig" diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index cfa3fe82ade3..368d9b313823 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -734,9 +734,11 @@ static const struct ieee80211_iface_limit if_limits[] = { BIT(NL80211_IFTYPE_P2P_GO) }, }; +#ifdef CONFIG_WIRELESS_WDS static const struct ieee80211_iface_limit wds_limits[] = { { .max = 2048, .types = BIT(NL80211_IFTYPE_WDS) }, }; +#endif #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT @@ -774,6 +776,7 @@ static const struct ieee80211_iface_combination if_comb[] = { BIT(NL80211_CHAN_WIDTH_40), #endif }, +#ifdef CONFIG_WIRELESS_WDS { .limits = wds_limits, .n_limits = ARRAY_SIZE(wds_limits), @@ -781,6 +784,7 @@ static const struct ieee80211_iface_combination if_comb[] = { .num_different_channels = 1, .beacon_int_infra_match = true, }, +#endif }; #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT @@ -851,7 +855,9 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT) | +#ifdef CONFIG_WIRELESS_WDS BIT(NL80211_IFTYPE_WDS) | +#endif BIT(NL80211_IFTYPE_OCB); if (ath9k_is_chanctx_enabled()) diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index 6e5d9095b195..52f3541ecbcf 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -5591,7 +5591,9 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_STATION) | +#ifdef CONFIG_WIRELESS_WDS BIT(NL80211_IFTYPE_WDS) | +#endif BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c index 83770d2ea057..e97ab2b91663 100644 --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c @@ -3838,7 +3838,9 @@ static int b43legacy_wireless_init(struct ssb_device *dev) hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | +#ifdef CONFIG_WIRELESS_WDS BIT(NL80211_IFTYPE_WDS) | +#endif BIT(NL80211_IFTYPE_ADHOC); hw->queues = 1; /* FIXME: hardware has more queues */ hw->max_rates = 2; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c index 4e0c5653054b..236f790e097a 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c @@ -1362,11 +1362,13 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) if (rt2x00dev->bcn->limit > 0) rt2x00dev->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | #ifdef CONFIG_MAC80211_MESH BIT(NL80211_IFTYPE_MESH_POINT) | #endif - BIT(NL80211_IFTYPE_WDS); +#ifdef CONFIG_WIRELESS_WDS + BIT(NL80211_IFTYPE_WDS) | +#endif + BIT(NL80211_IFTYPE_AP); rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; diff --git a/net/wireless/core.c b/net/wireless/core.c index 8201e6d7449e..f433f15f9222 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -571,6 +571,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) return -EINVAL; } +#ifndef CONFIG_WIRELESS_WDS + if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS))) + return -EINVAL; +#endif + /* You can't even choose that many! */ if (WARN_ON(cnt < c->max_interfaces)) return -EINVAL; @@ -609,6 +614,11 @@ int wiphy_register(struct wiphy *wiphy) !rdev->ops->add_nan_func || !rdev->ops->del_nan_func))) return -EINVAL; +#ifndef CONFIG_WIRELESS_WDS + if (WARN_ON(wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))) + return -EINVAL; +#endif + /* * if a wiphy has unsupported modes for regulatory channel enforcement, * opt-out of enforcement checking -- cgit v1.2.3 From aa276781a64a5f15ecc21e920960c5b1f84e5fee Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 18 Oct 2016 18:08:34 -0500 Subject: firmware: Add basic support for TI System Control Interface (TI-SCI) protocol Texas Instrument's System Control Interface (TI-SCI) Message Protocol is used in Texas Instrument's System on Chip (SoC) such as those in keystone family K2G SoC to communicate between various compute processors with a central system controller entity. TI-SCI message protocol provides support for management of various hardware entities within the SoC. Add support driver to allow communication with system controller entity within the SoC using the mailbox client. We introduce the basic registration and query capability for the driver protocol as part of this change. Subsequent patches add in functionality specific to the TI-SCI features. Signed-off-by: Nishanth Menon Signed-off-by: Tero Kristo --- MAINTAINERS | 2 + drivers/firmware/Kconfig | 15 + drivers/firmware/Makefile | 1 + drivers/firmware/ti_sci.c | 790 +++++++++++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 93 ++++ include/linux/soc/ti/ti_sci_protocol.h | 69 +++ 6 files changed, 970 insertions(+) create mode 100644 drivers/firmware/ti_sci.c create mode 100644 drivers/firmware/ti_sci.h create mode 100644 include/linux/soc/ti/ti_sci_protocol.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 2bafadf5747a..467b29fafaca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11890,6 +11890,8 @@ M: Santosh Shilimkar L: linux-arm-kernel@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt +F: drivers/firmware/ti_sci* +F: include/linux/soc/ti/ti_sci_protocol.h THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER M: Hans Verkuil diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index bca172d42c74..9418d7d1b0a5 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -203,6 +203,21 @@ config QCOM_SCM_64 def_bool y depends on QCOM_SCM && ARM64 +config TI_SCI_PROTOCOL + tristate "TI System Control Interface (TISCI) Message Protocol" + depends on TI_MESSAGE_MANAGER + help + TI System Control Interface (TISCI) Message Protocol is used to manage + compute systems such as ARM, DSP etc with the system controller in + complex System on Chip(SoC) such as those found on certain keystone + generation SoC from TI. + + System controller provides various facilities including power + management function support. + + This protocol library is used by client drivers to use the features + provided by the system controller. + config HAVE_ARM_SMCCC bool diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 898ac41fa8b3..dcb52c423151 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_QCOM_SCM) += qcom_scm.o obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a +obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-y += broadcom/ obj-y += meson/ diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c new file mode 100644 index 000000000000..5e99d7c18276 --- /dev/null +++ b/drivers/firmware/ti_sci.c @@ -0,0 +1,790 @@ +/* + * Texas Instruments System Control Interface Protocol Driver + * + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ti_sci.h" + +/* List of all TI SCI devices active in system */ +static LIST_HEAD(ti_sci_list); +/* Protection for the entire list */ +static DEFINE_MUTEX(ti_sci_list_mutex); + +/** + * struct ti_sci_xfer - Structure representing a message flow + * @tx_message: Transmit message + * @rx_len: Receive message length + * @xfer_buf: Preallocated buffer to store receive message + * Since we work with request-ACK protocol, we can + * reuse the same buffer for the rx path as we + * use for the tx path. + * @done: completion event + */ +struct ti_sci_xfer { + struct ti_msgmgr_message tx_message; + u8 rx_len; + u8 *xfer_buf; + struct completion done; +}; + +/** + * struct ti_sci_xfers_info - Structure to manage transfer information + * @sem_xfer_count: Counting Semaphore for managing max simultaneous + * Messages. + * @xfer_block: Preallocated Message array + * @xfer_alloc_table: Bitmap table for allocated messages. + * Index of this bitmap table is also used for message + * sequence identifier. + * @xfer_lock: Protection for message allocation + */ +struct ti_sci_xfers_info { + struct semaphore sem_xfer_count; + struct ti_sci_xfer *xfer_block; + unsigned long *xfer_alloc_table; + /* protect transfer allocation */ + spinlock_t xfer_lock; +}; + +/** + * struct ti_sci_desc - Description of SoC integration + * @host_id: Host identifier representing the compute entity + * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) + * @max_msgs: Maximum number of messages that can be pending + * simultaneously in the system + * @max_msg_size: Maximum size of data per message that can be handled. + */ +struct ti_sci_desc { + u8 host_id; + int max_rx_timeout_ms; + int max_msgs; + int max_msg_size; +}; + +/** + * struct ti_sci_info - Structure representing a TI SCI instance + * @dev: Device pointer + * @desc: SoC description for this instance + * @d: Debugfs file entry + * @debug_region: Memory region where the debug message are available + * @debug_region_size: Debug region size + * @debug_buffer: Buffer allocated to copy debug messages. + * @handle: Instance of TI SCI handle to send to clients. + * @cl: Mailbox Client + * @chan_tx: Transmit mailbox channel + * @chan_rx: Receive mailbox channel + * @minfo: Message info + * @node: list head + * @users: Number of users of this instance + */ +struct ti_sci_info { + struct device *dev; + const struct ti_sci_desc *desc; + struct dentry *d; + void __iomem *debug_region; + char *debug_buffer; + size_t debug_region_size; + struct ti_sci_handle handle; + struct mbox_client cl; + struct mbox_chan *chan_tx; + struct mbox_chan *chan_rx; + struct ti_sci_xfers_info minfo; + struct list_head node; + /* protected by ti_sci_list_mutex */ + int users; +}; + +#define cl_to_ti_sci_info(c) container_of(c, struct ti_sci_info, cl) +#define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle) + +#ifdef CONFIG_DEBUG_FS + +/** + * ti_sci_debug_show() - Helper to dump the debug log + * @s: sequence file pointer + * @unused: unused. + * + * Return: 0 + */ +static int ti_sci_debug_show(struct seq_file *s, void *unused) +{ + struct ti_sci_info *info = s->private; + + memcpy_fromio(info->debug_buffer, info->debug_region, + info->debug_region_size); + /* + * We don't trust firmware to leave NULL terminated last byte (hence + * we have allocated 1 extra 0 byte). Since we cannot guarantee any + * specific data format for debug messages, We just present the data + * in the buffer as is - we expect the messages to be self explanatory. + */ + seq_puts(s, info->debug_buffer); + return 0; +} + +/** + * ti_sci_debug_open() - debug file open + * @inode: inode pointer + * @file: file pointer + * + * Return: result of single_open + */ +static int ti_sci_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, ti_sci_debug_show, inode->i_private); +} + +/* log file operations */ +static const struct file_operations ti_sci_debug_fops = { + .open = ti_sci_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/** + * ti_sci_debugfs_create() - Create log debug file + * @pdev: platform device pointer + * @info: Pointer to SCI entity information + * + * Return: 0 if all went fine, else corresponding error. + */ +static int ti_sci_debugfs_create(struct platform_device *pdev, + struct ti_sci_info *info) +{ + struct device *dev = &pdev->dev; + struct resource *res; + char debug_name[50] = "ti_sci_debug@"; + + /* Debug region is optional */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "debug_messages"); + info->debug_region = devm_ioremap_resource(dev, res); + if (IS_ERR(info->debug_region)) + return 0; + info->debug_region_size = resource_size(res); + + info->debug_buffer = devm_kcalloc(dev, info->debug_region_size + 1, + sizeof(char), GFP_KERNEL); + if (!info->debug_buffer) + return -ENOMEM; + /* Setup NULL termination */ + info->debug_buffer[info->debug_region_size] = 0; + + info->d = debugfs_create_file(strncat(debug_name, dev_name(dev), + sizeof(debug_name)), + 0444, NULL, info, &ti_sci_debug_fops); + if (IS_ERR(info->d)) + return PTR_ERR(info->d); + + dev_dbg(dev, "Debug region => %p, size = %zu bytes, resource: %pr\n", + info->debug_region, info->debug_region_size, res); + return 0; +} + +/** + * ti_sci_debugfs_destroy() - clean up log debug file + * @pdev: platform device pointer + * @info: Pointer to SCI entity information + */ +static void ti_sci_debugfs_destroy(struct platform_device *pdev, + struct ti_sci_info *info) +{ + if (IS_ERR(info->debug_region)) + return; + + debugfs_remove(info->d); +} +#else /* CONFIG_DEBUG_FS */ +static inline int ti_sci_debugfs_create(struct platform_device *dev, + struct ti_sci_info *info) +{ + return 0; +} + +static inline void ti_sci_debugfs_destroy(struct platform_device *dev, + struct ti_sci_info *info) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +/** + * ti_sci_dump_header_dbg() - Helper to dump a message header. + * @dev: Device pointer corresponding to the SCI entity + * @hdr: pointer to header. + */ +static inline void ti_sci_dump_header_dbg(struct device *dev, + struct ti_sci_msg_hdr *hdr) +{ + dev_dbg(dev, "MSGHDR:type=0x%04x host=0x%02x seq=0x%02x flags=0x%08x\n", + hdr->type, hdr->host, hdr->seq, hdr->flags); +} + +/** + * ti_sci_rx_callback() - mailbox client callback for receive messages + * @cl: client pointer + * @m: mailbox message + * + * Processes one received message to appropriate transfer information and + * signals completion of the transfer. + * + * NOTE: This function will be invoked in IRQ context, hence should be + * as optimal as possible. + */ +static void ti_sci_rx_callback(struct mbox_client *cl, void *m) +{ + struct ti_sci_info *info = cl_to_ti_sci_info(cl); + struct device *dev = info->dev; + struct ti_sci_xfers_info *minfo = &info->minfo; + struct ti_msgmgr_message *mbox_msg = m; + struct ti_sci_msg_hdr *hdr = (struct ti_sci_msg_hdr *)mbox_msg->buf; + struct ti_sci_xfer *xfer; + u8 xfer_id; + + xfer_id = hdr->seq; + + /* + * Are we even expecting this? + * NOTE: barriers were implicit in locks used for modifying the bitmap + */ + if (!test_bit(xfer_id, minfo->xfer_alloc_table)) { + dev_err(dev, "Message for %d is not expected!\n", xfer_id); + return; + } + + xfer = &minfo->xfer_block[xfer_id]; + + /* Is the message of valid length? */ + if (mbox_msg->len > info->desc->max_msg_size) { + dev_err(dev, "Unable to handle %d xfer(max %d)\n", + mbox_msg->len, info->desc->max_msg_size); + ti_sci_dump_header_dbg(dev, hdr); + return; + } + if (mbox_msg->len < xfer->rx_len) { + dev_err(dev, "Recv xfer %d < expected %d length\n", + mbox_msg->len, xfer->rx_len); + ti_sci_dump_header_dbg(dev, hdr); + return; + } + + ti_sci_dump_header_dbg(dev, hdr); + /* Take a copy to the rx buffer.. */ + memcpy(xfer->xfer_buf, mbox_msg->buf, xfer->rx_len); + complete(&xfer->done); +} + +/** + * ti_sci_get_one_xfer() - Allocate one message + * @info: Pointer to SCI entity information + * @msg_type: Message type + * @msg_flags: Flag to set for the message + * @tx_message_size: transmit message size + * @rx_message_size: receive message size + * + * Helper function which is used by various command functions that are + * exposed to clients of this driver for allocating a message traffic event. + * + * This function can sleep depending on pending requests already in the system + * for the SCI entity. Further, this also holds a spinlock to maintain integrity + * of internal data structures. + * + * Return: 0 if all went fine, else corresponding error. + */ +static struct ti_sci_xfer *ti_sci_get_one_xfer(struct ti_sci_info *info, + u16 msg_type, u32 msg_flags, + size_t tx_message_size, + size_t rx_message_size) +{ + struct ti_sci_xfers_info *minfo = &info->minfo; + struct ti_sci_xfer *xfer; + struct ti_sci_msg_hdr *hdr; + unsigned long flags; + unsigned long bit_pos; + u8 xfer_id; + int ret; + int timeout; + + /* Ensure we have sane transfer sizes */ + if (rx_message_size > info->desc->max_msg_size || + tx_message_size > info->desc->max_msg_size || + rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr)) + return ERR_PTR(-ERANGE); + + /* + * Ensure we have only controlled number of pending messages. + * Ideally, we might just have to wait a single message, be + * conservative and wait 5 times that.. + */ + timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms) * 5; + ret = down_timeout(&minfo->sem_xfer_count, timeout); + if (ret < 0) + return ERR_PTR(ret); + + /* Keep the locked section as small as possible */ + spin_lock_irqsave(&minfo->xfer_lock, flags); + bit_pos = find_first_zero_bit(minfo->xfer_alloc_table, + info->desc->max_msgs); + set_bit(bit_pos, minfo->xfer_alloc_table); + spin_unlock_irqrestore(&minfo->xfer_lock, flags); + + /* + * We already ensured in probe that we can have max messages that can + * fit in hdr.seq - NOTE: this improves access latencies + * to predictable O(1) access, BUT, it opens us to risk if + * remote misbehaves with corrupted message sequence responses. + * If that happens, we are going to be messed up anyways.. + */ + xfer_id = (u8)bit_pos; + + xfer = &minfo->xfer_block[xfer_id]; + + hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + xfer->tx_message.len = tx_message_size; + xfer->rx_len = (u8)rx_message_size; + + reinit_completion(&xfer->done); + + hdr->seq = xfer_id; + hdr->type = msg_type; + hdr->host = info->desc->host_id; + hdr->flags = msg_flags; + + return xfer; +} + +/** + * ti_sci_put_one_xfer() - Release a message + * @minfo: transfer info pointer + * @xfer: message that was reserved by ti_sci_get_one_xfer + * + * This holds a spinlock to maintain integrity of internal data structures. + */ +static void ti_sci_put_one_xfer(struct ti_sci_xfers_info *minfo, + struct ti_sci_xfer *xfer) +{ + unsigned long flags; + struct ti_sci_msg_hdr *hdr; + u8 xfer_id; + + hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + xfer_id = hdr->seq; + + /* + * Keep the locked section as small as possible + * NOTE: we might escape with smp_mb and no lock here.. + * but just be conservative and symmetric. + */ + spin_lock_irqsave(&minfo->xfer_lock, flags); + clear_bit(xfer_id, minfo->xfer_alloc_table); + spin_unlock_irqrestore(&minfo->xfer_lock, flags); + + /* Increment the count for the next user to get through */ + up(&minfo->sem_xfer_count); +} + +/** + * ti_sci_do_xfer() - Do one transfer + * @info: Pointer to SCI entity information + * @xfer: Transfer to initiate and wait for response + * + * Return: -ETIMEDOUT in case of no response, if transmit error, + * return corresponding error, else if all goes well, + * return 0. + */ +static inline int ti_sci_do_xfer(struct ti_sci_info *info, + struct ti_sci_xfer *xfer) +{ + int ret; + int timeout; + struct device *dev = info->dev; + + ret = mbox_send_message(info->chan_tx, &xfer->tx_message); + if (ret < 0) + return ret; + + ret = 0; + + /* And we wait for the response. */ + timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms); + if (!wait_for_completion_timeout(&xfer->done, timeout)) { + dev_err(dev, "Mbox timedout in resp(caller: %pF)\n", + (void *)_RET_IP_); + ret = -ETIMEDOUT; + } + /* + * NOTE: we might prefer not to need the mailbox ticker to manage the + * transfer queueing since the protocol layer queues things by itself. + * Unfortunately, we have to kick the mailbox framework after we have + * received our message. + */ + mbox_client_txdone(info->chan_tx, ret); + + return ret; +} + +/** + * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity + * @info: Pointer to SCI entity information + * + * Updates the SCI information in the internal data structure. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_get_revision(struct ti_sci_info *info) +{ + struct device *dev = info->dev; + struct ti_sci_handle *handle = &info->handle; + struct ti_sci_version_info *ver = &handle->version; + struct ti_sci_msg_resp_version *rev_info; + struct ti_sci_xfer *xfer; + int ret; + + /* No need to setup flags since it is expected to respond */ + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_VERSION, + 0x0, sizeof(struct ti_sci_msg_hdr), + sizeof(*rev_info)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + rev_info = (struct ti_sci_msg_resp_version *)xfer->xfer_buf; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + ver->abi_major = rev_info->abi_major; + ver->abi_minor = rev_info->abi_minor; + ver->firmware_revision = rev_info->firmware_revision; + strncpy(ver->firmware_description, rev_info->firmware_description, + sizeof(ver->firmware_description)); + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + return ret; +} + +/** + * ti_sci_get_handle() - Get the TI SCI handle for a device + * @dev: Pointer to device for which we want SCI handle + * + * NOTE: The function does not track individual clients of the framework + * and is expected to be maintained by caller of TI SCI protocol library. + * ti_sci_put_handle must be balanced with successful ti_sci_get_handle + * Return: pointer to handle if successful, else: + * -EPROBE_DEFER if the instance is not ready + * -ENODEV if the required node handler is missing + * -EINVAL if invalid conditions are encountered. + */ +const struct ti_sci_handle *ti_sci_get_handle(struct device *dev) +{ + struct device_node *ti_sci_np; + struct list_head *p; + struct ti_sci_handle *handle = NULL; + struct ti_sci_info *info; + + if (!dev) { + pr_err("I need a device pointer\n"); + return ERR_PTR(-EINVAL); + } + ti_sci_np = of_get_parent(dev->of_node); + if (!ti_sci_np) { + dev_err(dev, "No OF information\n"); + return ERR_PTR(-EINVAL); + } + + mutex_lock(&ti_sci_list_mutex); + list_for_each(p, &ti_sci_list) { + info = list_entry(p, struct ti_sci_info, node); + if (ti_sci_np == info->dev->of_node) { + handle = &info->handle; + info->users++; + break; + } + } + mutex_unlock(&ti_sci_list_mutex); + of_node_put(ti_sci_np); + + if (!handle) + return ERR_PTR(-EPROBE_DEFER); + + return handle; +} +EXPORT_SYMBOL_GPL(ti_sci_get_handle); + +/** + * ti_sci_put_handle() - Release the handle acquired by ti_sci_get_handle + * @handle: Handle acquired by ti_sci_get_handle + * + * NOTE: The function does not track individual clients of the framework + * and is expected to be maintained by caller of TI SCI protocol library. + * ti_sci_put_handle must be balanced with successful ti_sci_get_handle + * + * Return: 0 is successfully released + * if an error pointer was passed, it returns the error value back, + * if null was passed, it returns -EINVAL; + */ +int ti_sci_put_handle(const struct ti_sci_handle *handle) +{ + struct ti_sci_info *info; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + mutex_lock(&ti_sci_list_mutex); + if (!WARN_ON(!info->users)) + info->users--; + mutex_unlock(&ti_sci_list_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(ti_sci_put_handle); + +static void devm_ti_sci_release(struct device *dev, void *res) +{ + const struct ti_sci_handle **ptr = res; + const struct ti_sci_handle *handle = *ptr; + int ret; + + ret = ti_sci_put_handle(handle); + if (ret) + dev_err(dev, "failed to put handle %d\n", ret); +} + +/** + * devm_ti_sci_get_handle() - Managed get handle + * @dev: device for which we want SCI handle for. + * + * NOTE: This releases the handle once the device resources are + * no longer needed. MUST NOT BE released with ti_sci_put_handle. + * The function does not track individual clients of the framework + * and is expected to be maintained by caller of TI SCI protocol library. + * + * Return: 0 if all went fine, else corresponding error. + */ +const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) +{ + const struct ti_sci_handle **ptr; + const struct ti_sci_handle *handle; + + ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + handle = ti_sci_get_handle(dev); + + if (!IS_ERR(handle)) { + *ptr = handle; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return handle; +} +EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle); + +/* Description for K2G */ +static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { + .host_id = 2, + /* Conservative duration */ + .max_rx_timeout_ms = 1000, + /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ + .max_msgs = 20, + .max_msg_size = 64, +}; + +static const struct of_device_id ti_sci_of_match[] = { + {.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc}, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ti_sci_of_match); + +static int ti_sci_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct of_device_id *of_id; + const struct ti_sci_desc *desc; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info = NULL; + struct ti_sci_xfers_info *minfo; + struct mbox_client *cl; + int ret = -EINVAL; + int i; + + of_id = of_match_device(ti_sci_of_match, dev); + if (!of_id) { + dev_err(dev, "OF data missing\n"); + return -EINVAL; + } + desc = of_id->data; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->dev = dev; + info->desc = desc; + INIT_LIST_HEAD(&info->node); + minfo = &info->minfo; + + /* + * Pre-allocate messages + * NEVER allocate more than what we can indicate in hdr.seq + * if we have data description bug, force a fix.. + */ + if (WARN_ON(desc->max_msgs >= + 1 << 8 * sizeof(((struct ti_sci_msg_hdr *)0)->seq))) + return -EINVAL; + + minfo->xfer_block = devm_kcalloc(dev, + desc->max_msgs, + sizeof(*minfo->xfer_block), + GFP_KERNEL); + if (!minfo->xfer_block) + return -ENOMEM; + + minfo->xfer_alloc_table = devm_kzalloc(dev, + BITS_TO_LONGS(desc->max_msgs) + * sizeof(unsigned long), + GFP_KERNEL); + if (!minfo->xfer_alloc_table) + return -ENOMEM; + bitmap_zero(minfo->xfer_alloc_table, desc->max_msgs); + + /* Pre-initialize the buffer pointer to pre-allocated buffers */ + for (i = 0, xfer = minfo->xfer_block; i < desc->max_msgs; i++, xfer++) { + xfer->xfer_buf = devm_kcalloc(dev, 1, desc->max_msg_size, + GFP_KERNEL); + if (!xfer->xfer_buf) + return -ENOMEM; + + xfer->tx_message.buf = xfer->xfer_buf; + init_completion(&xfer->done); + } + + ret = ti_sci_debugfs_create(pdev, info); + if (ret) + dev_warn(dev, "Failed to create debug file\n"); + + platform_set_drvdata(pdev, info); + + cl = &info->cl; + cl->dev = dev; + cl->tx_block = false; + cl->rx_callback = ti_sci_rx_callback; + cl->knows_txdone = true; + + spin_lock_init(&minfo->xfer_lock); + sema_init(&minfo->sem_xfer_count, desc->max_msgs); + + info->chan_rx = mbox_request_channel_byname(cl, "rx"); + if (IS_ERR(info->chan_rx)) { + ret = PTR_ERR(info->chan_rx); + goto out; + } + + info->chan_tx = mbox_request_channel_byname(cl, "tx"); + if (IS_ERR(info->chan_tx)) { + ret = PTR_ERR(info->chan_tx); + goto out; + } + ret = ti_sci_cmd_get_revision(info); + if (ret) { + dev_err(dev, "Unable to communicate with TISCI(%d)\n", ret); + goto out; + } + + dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n", + info->handle.version.abi_major, info->handle.version.abi_minor, + info->handle.version.firmware_revision, + info->handle.version.firmware_description); + + mutex_lock(&ti_sci_list_mutex); + list_add_tail(&info->node, &ti_sci_list); + mutex_unlock(&ti_sci_list_mutex); + + return of_platform_populate(dev->of_node, NULL, NULL, dev); +out: + if (!IS_ERR(info->chan_tx)) + mbox_free_channel(info->chan_tx); + if (!IS_ERR(info->chan_rx)) + mbox_free_channel(info->chan_rx); + debugfs_remove(info->d); + return ret; +} + +static int ti_sci_remove(struct platform_device *pdev) +{ + struct ti_sci_info *info; + struct device *dev = &pdev->dev; + int ret = 0; + + of_platform_depopulate(dev); + + info = platform_get_drvdata(pdev); + + mutex_lock(&ti_sci_list_mutex); + if (info->users) + ret = -EBUSY; + else + list_del(&info->node); + mutex_unlock(&ti_sci_list_mutex); + + if (!ret) { + ti_sci_debugfs_destroy(pdev, info); + + /* Safe to free channels since no more users */ + mbox_free_channel(info->chan_tx); + mbox_free_channel(info->chan_rx); + } + + return ret; +} + +static struct platform_driver ti_sci_driver = { + .probe = ti_sci_probe, + .remove = ti_sci_remove, + .driver = { + .name = "ti-sci", + .of_match_table = of_match_ptr(ti_sci_of_match), + }, +}; +module_platform_driver(ti_sci_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("TI System Control Interface(SCI) driver"); +MODULE_AUTHOR("Nishanth Menon"); +MODULE_ALIAS("platform:ti-sci"); diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h new file mode 100644 index 000000000000..e9dc53f26e0e --- /dev/null +++ b/drivers/firmware/ti_sci.h @@ -0,0 +1,93 @@ +/* + * Texas Instruments System Control Interface (TISCI) Protocol + * + * Communication protocol with TI SCI hardware + * The system works in a message response protocol + * See: http://processors.wiki.ti.com/index.php/TISCI for details + * + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __TI_SCI_H +#define __TI_SCI_H + +/* Generic Messages */ +#define TI_SCI_MSG_ENABLE_WDT 0x0000 +#define TI_SCI_MSG_WAKE_RESET 0x0001 +#define TI_SCI_MSG_VERSION 0x0002 +#define TI_SCI_MSG_WAKE_REASON 0x0003 +#define TI_SCI_MSG_GOODBYE 0x0004 + +/** + * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses + * @type: Type of messages: One of TI_SCI_MSG* values + * @host: Host of the message + * @seq: Message identifier indicating a transfer sequence + * @flags: Flag for the message + */ +struct ti_sci_msg_hdr { + u16 type; + u8 host; + u8 seq; +#define TI_SCI_MSG_FLAG(val) (1 << (val)) +#define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0 +#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0) +#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1) +#define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0 +#define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1) + /* Additional Flags */ + u32 flags; +} __packed; + +/** + * struct ti_sci_msg_resp_version - Response for a message + * @hdr: Generic header + * @firmware_description: String describing the firmware + * @firmware_revision: Firmware revision + * @abi_major: Major version of the ABI that firmware supports + * @abi_minor: Minor version of the ABI that firmware supports + * + * In general, ABI version changes follow the rule that minor version increments + * are backward compatible. Major revision changes in ABI may not be + * backward compatible. + * + * Response to a generic message with message type TI_SCI_MSG_VERSION + */ +struct ti_sci_msg_resp_version { + struct ti_sci_msg_hdr hdr; + char firmware_description[32]; + u16 firmware_revision; + u8 abi_major; + u8 abi_minor; +} __packed; + +#endif /* __TI_SCI_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h new file mode 100644 index 000000000000..e73483fd5327 --- /dev/null +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -0,0 +1,69 @@ +/* + * Texas Instruments System Control Interface Protocol + * + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __TISCI_PROTOCOL_H +#define __TISCI_PROTOCOL_H + +/** + * struct ti_sci_version_info - version information structure + * @abi_major: Major ABI version. Change here implies risk of backward + * compatibility break. + * @abi_minor: Minor ABI version. Change here implies new feature addition, + * or compatible change in ABI. + * @firmware_revision: Firmware revision (not usually used). + * @firmware_description: Firmware description (not usually used). + */ +struct ti_sci_version_info { + u8 abi_major; + u8 abi_minor; + u16 firmware_revision; + char firmware_description[32]; +}; + +/** + * struct ti_sci_handle - Handle returned to TI SCI clients for usage. + * @version: structure containing version information + */ +struct ti_sci_handle { + struct ti_sci_version_info version; +}; + +#if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL) +const struct ti_sci_handle *ti_sci_get_handle(struct device *dev); +int ti_sci_put_handle(const struct ti_sci_handle *handle); +const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev); + +#else /* CONFIG_TI_SCI_PROTOCOL */ + +static inline const struct ti_sci_handle *ti_sci_get_handle(struct device *dev) +{ + return ERR_PTR(-EINVAL); +} + +static inline int ti_sci_put_handle(const struct ti_sci_handle *handle) +{ + return -EINVAL; +} + +static inline +const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) +{ + return ERR_PTR(-EINVAL); +} + +#endif /* CONFIG_TI_SCI_PROTOCOL */ + +#endif /* __TISCI_PROTOCOL_H */ -- cgit v1.2.3 From 9e7d756da7a5b0cc756d1f512f3eaf261834180a Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 18 Oct 2016 18:08:35 -0500 Subject: firmware: ti_sci: Add support for Device control Texas Instrument's System Control Interface (TI-SCI) Message Protocol is used in Texas Instrument's System on Chip (SoC) such as those in keystone family K2G SoC to communicate between various compute processors with a central system controller entity. TI-SCI message protocol provides support for management of various hardware entitites within the SoC. Add support driver to allow communication with system controller entity within the SoC using the mailbox client. We introduce the fundamental device management capability support to the driver protocol as part of this change. [d-gerlach@ti.com: Contributed device reset handling] Signed-off-by: Dave Gerlach Signed-off-by: Nishanth Menon Signed-off-by: Tero Kristo --- drivers/firmware/ti_sci.c | 433 +++++++++++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 98 ++++++++ include/linux/soc/ti/ti_sci_protocol.h | 91 +++++++ 3 files changed, 622 insertions(+) (limited to 'drivers') diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 5e99d7c18276..c7b25ccf6f07 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -494,6 +494,437 @@ fail: return ret; } +/** + * ti_sci_is_response_ack() - Generic ACK/NACK message checkup + * @r: pointer to response buffer + * + * Return: true if the response was an ACK, else returns false. + */ +static inline bool ti_sci_is_response_ack(void *r) +{ + struct ti_sci_msg_hdr *hdr = r; + + return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false; +} + +/** + * ti_sci_set_device_state() - Set device state helper + * @handle: pointer to TI SCI handle + * @id: Device identifier + * @flags: flags to setup for the device + * @state: State to move the device to + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_set_device_state(const struct ti_sci_handle *handle, + u32 id, u32 flags, u8 state) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_set_device_state *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE, + flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_set_device_state *)xfer->xfer_buf; + req->id = id; + req->state = state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_get_device_state() - Get device state helper + * @handle: Handle to the device + * @id: Device Identifier + * @clcnt: Pointer to Context Loss Count + * @resets: pointer to resets + * @p_state: pointer to p_state + * @c_state: pointer to c_state + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_get_device_state(const struct ti_sci_handle *handle, + u32 id, u32 *clcnt, u32 *resets, + u8 *p_state, u8 *c_state) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_get_device_state *req; + struct ti_sci_msg_resp_get_device_state *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + if (!clcnt && !resets && !p_state && !c_state) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + /* Response is expected, so need of any flags */ + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, + 0, sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_get_device_state *)xfer->xfer_buf; + req->id = id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_get_device_state *)xfer->xfer_buf; + if (!ti_sci_is_response_ack(resp)) { + ret = -ENODEV; + goto fail; + } + + if (clcnt) + *clcnt = resp->context_loss_count; + if (resets) + *resets = resp->resets; + if (p_state) + *p_state = resp->programmed_state; + if (c_state) + *c_state = resp->current_state; +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_get_device() - command to request for device managed by TISCI + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * NOTE: The request is for exclusive access for the processor. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id) +{ + return ti_sci_set_device_state(handle, id, + MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_ON); +} + +/** + * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id) +{ + return ti_sci_set_device_state(handle, id, + MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_RETENTION); +} + +/** + * ti_sci_cmd_put_device() - command to release a device managed by TISCI + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id) +{ + return ti_sci_set_device_state(handle, id, + 0, MSG_DEVICE_SW_STATE_AUTO_OFF); +} + +/** + * ti_sci_cmd_dev_is_valid() - Is the device valid + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * + * Return: 0 if all went fine and the device ID is valid, else return + * appropriate error. + */ +static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id) +{ + u8 unused; + + /* check the device state which will also tell us if the ID is valid */ + return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused); +} + +/** + * ti_sci_cmd_dev_get_clcnt() - Get context loss counter + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @count: Pointer to Context Loss counter to populate + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id, + u32 *count) +{ + return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL); +} + +/** + * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @r_state: true if requested to be idle + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id, + bool *r_state) +{ + int ret; + u8 state; + + if (!r_state) + return -EINVAL; + + ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL); + if (ret) + return ret; + + *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION); + + return 0; +} + +/** + * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @r_state: true if requested to be stopped + * @curr_state: true if currently stopped. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id, + bool *r_state, bool *curr_state) +{ + int ret; + u8 p_state, c_state; + + if (!r_state && !curr_state) + return -EINVAL; + + ret = + ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state); + if (ret) + return ret; + + if (r_state) + *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF); + if (curr_state) + *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF); + + return 0; +} + +/** + * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @r_state: true if requested to be ON + * @curr_state: true if currently ON and active + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id, + bool *r_state, bool *curr_state) +{ + int ret; + u8 p_state, c_state; + + if (!r_state && !curr_state) + return -EINVAL; + + ret = + ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state); + if (ret) + return ret; + + if (r_state) + *r_state = (p_state == MSG_DEVICE_SW_STATE_ON); + if (curr_state) + *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON); + + return 0; +} + +/** + * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @curr_state: true if currently transitioning. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id, + bool *curr_state) +{ + int ret; + u8 state; + + if (!curr_state) + return -EINVAL; + + ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state); + if (ret) + return ret; + + *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS); + + return 0; +} + +/** + * ti_sci_cmd_set_device_resets() - command to set resets for device managed + * by TISCI + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * @reset_state: Device specific reset bit field + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle, + u32 id, u32 reset_state) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_set_device_resets *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_set_device_resets *)xfer->xfer_buf; + req->id = id; + req->resets = reset_state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_get_device_resets() - Get reset state for device managed + * by TISCI + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @reset_state: Pointer to reset state to populate + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle, + u32 id, u32 *reset_state) +{ + return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL, + NULL); +} + +/* + * ti_sci_setup_ops() - Setup the operations structures + * @info: pointer to TISCI pointer + */ +static void ti_sci_setup_ops(struct ti_sci_info *info) +{ + struct ti_sci_ops *ops = &info->handle.ops; + struct ti_sci_dev_ops *dops = &ops->dev_ops; + + dops->get_device = ti_sci_cmd_get_device; + dops->idle_device = ti_sci_cmd_idle_device; + dops->put_device = ti_sci_cmd_put_device; + + dops->is_valid = ti_sci_cmd_dev_is_valid; + dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt; + dops->is_idle = ti_sci_cmd_dev_is_idle; + dops->is_stop = ti_sci_cmd_dev_is_stop; + dops->is_on = ti_sci_cmd_dev_is_on; + dops->is_transitioning = ti_sci_cmd_dev_is_trans; + dops->set_device_resets = ti_sci_cmd_set_device_resets; + dops->get_device_resets = ti_sci_cmd_get_device_resets; +} + /** * ti_sci_get_handle() - Get the TI SCI handle for a device * @dev: Pointer to device for which we want SCI handle @@ -727,6 +1158,8 @@ static int ti_sci_probe(struct platform_device *pdev) goto out; } + ti_sci_setup_ops(info); + dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n", info->handle.version.abi_major, info->handle.version.abi_minor, info->handle.version.firmware_revision, diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index e9dc53f26e0e..29ce0532a7ca 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -47,6 +47,11 @@ #define TI_SCI_MSG_WAKE_REASON 0x0003 #define TI_SCI_MSG_GOODBYE 0x0004 +/* Device requests */ +#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 +#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201 +#define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202 + /** * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses * @type: Type of messages: One of TI_SCI_MSG* values @@ -90,4 +95,97 @@ struct ti_sci_msg_resp_version { u8 abi_minor; } __packed; +/** + * struct ti_sci_msg_req_set_device_state - Set the desired state of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @reserved: Reserved space in message, must be 0 for backward compatibility + * @state: The desired state of the device. + * + * Certain flags can also be set to alter the device state: + * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source. + * The meaning of this flag will vary slightly from device to device and from + * SoC to SoC but it generally allows the device to wake the SoC out of deep + * suspend states. + * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device. + * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed + * with STATE_RETENTION or STATE_ON, it will claim the device exclusively. + * If another host already has this device set to STATE_RETENTION or STATE_ON, + * the message will fail. Once successful, other hosts attempting to set + * STATE_RETENTION or STATE_ON will fail. + * + * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + u32 id; + u32 reserved; + +#define MSG_DEVICE_SW_STATE_AUTO_OFF 0 +#define MSG_DEVICE_SW_STATE_RETENTION 1 +#define MSG_DEVICE_SW_STATE_ON 2 + u8 state; +} __packed; + +/** + * struct ti_sci_msg_req_get_device_state - Request to get device. + * @hdr: Generic header + * @id: Device Identifier + * + * Request type is TI_SCI_MSG_GET_DEVICE_STATE, responded device state + * information + */ +struct ti_sci_msg_req_get_device_state { + struct ti_sci_msg_hdr hdr; + u32 id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_device_state - Response to get device request. + * @hdr: Generic header + * @context_loss_count: Indicates how many times the device has lost context. A + * driver can use this monotonic counter to determine if the device has + * lost context since the last time this message was exchanged. + * @resets: Programmed state of the reset lines. + * @programmed_state: The state as programmed by set_device. + * - Uses the MSG_DEVICE_SW_* macros + * @current_state: The actual state of the hardware. + * + * Response to request TI_SCI_MSG_GET_DEVICE_STATE. + */ +struct ti_sci_msg_resp_get_device_state { + struct ti_sci_msg_hdr hdr; + u32 context_loss_count; + u32 resets; + u8 programmed_state; +#define MSG_DEVICE_HW_STATE_OFF 0 +#define MSG_DEVICE_HW_STATE_ON 1 +#define MSG_DEVICE_HW_STATE_TRANS 2 + u8 current_state; +} __packed; + +/** + * struct ti_sci_msg_req_set_device_resets - Set the desired resets + * configuration of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @resets: A bit field of resets for the device. The meaning, behavior, + * and usage of the reset flags are device specific. 0 for a bit + * indicates releasing the reset represented by that bit while 1 + * indicates keeping it held. + * + * Request type is TI_SCI_MSG_SET_DEVICE_RESETS, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_resets { + struct ti_sci_msg_hdr hdr; + u32 id; + u32 resets; +} __packed; + #endif /* __TI_SCI_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index e73483fd5327..87fa73851471 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -33,12 +33,103 @@ struct ti_sci_version_info { char firmware_description[32]; }; +struct ti_sci_handle; + +/** + * struct ti_sci_dev_ops - Device control operations + * @get_device: Command to request for device managed by TISCI + * Returns 0 for successful exclusive request, else returns + * corresponding error message. + * @idle_device: Command to idle a device managed by TISCI + * Returns 0 for successful exclusive request, else returns + * corresponding error message. + * @put_device: Command to release a device managed by TISCI + * Returns 0 for successful release, else returns corresponding + * error message. + * @is_valid: Check if the device ID is a valid ID. + * Returns 0 if the ID is valid, else returns corresponding error. + * @get_context_loss_count: Command to retrieve context loss counter - this + * increments every time the device looses context. Overflow + * is possible. + * - count: pointer to u32 which will retrieve counter + * Returns 0 for successful information request and count has + * proper data, else returns corresponding error message. + * @is_idle: Reports back about device idle state + * - req_state: Returns requested idle state + * Returns 0 for successful information request and req_state and + * current_state has proper data, else returns corresponding error + * message. + * @is_stop: Reports back about device stop state + * - req_state: Returns requested stop state + * - current_state: Returns current stop state + * Returns 0 for successful information request and req_state and + * current_state has proper data, else returns corresponding error + * message. + * @is_on: Reports back about device ON(or active) state + * - req_state: Returns requested ON state + * - current_state: Returns current ON state + * Returns 0 for successful information request and req_state and + * current_state has proper data, else returns corresponding error + * message. + * @is_transitioning: Reports back if the device is in the middle of transition + * of state. + * -current_state: Returns 'true' if currently transitioning. + * @set_device_resets: Command to configure resets for device managed by TISCI. + * -reset_state: Device specific reset bit field + * Returns 0 for successful request, else returns + * corresponding error message. + * @get_device_resets: Command to read state of resets for device managed + * by TISCI. + * -reset_state: pointer to u32 which will retrieve resets + * Returns 0 for successful request, else returns + * corresponding error message. + * + * NOTE: for all these functions, the following parameters are generic in + * nature: + * -handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * -id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + */ +struct ti_sci_dev_ops { + int (*get_device)(const struct ti_sci_handle *handle, u32 id); + int (*idle_device)(const struct ti_sci_handle *handle, u32 id); + int (*put_device)(const struct ti_sci_handle *handle, u32 id); + int (*is_valid)(const struct ti_sci_handle *handle, u32 id); + int (*get_context_loss_count)(const struct ti_sci_handle *handle, + u32 id, u32 *count); + int (*is_idle)(const struct ti_sci_handle *handle, u32 id, + bool *requested_state); + int (*is_stop)(const struct ti_sci_handle *handle, u32 id, + bool *req_state, bool *current_state); + int (*is_on)(const struct ti_sci_handle *handle, u32 id, + bool *req_state, bool *current_state); + int (*is_transitioning)(const struct ti_sci_handle *handle, u32 id, + bool *current_state); + int (*set_device_resets)(const struct ti_sci_handle *handle, u32 id, + u32 reset_state); + int (*get_device_resets)(const struct ti_sci_handle *handle, u32 id, + u32 *reset_state); +}; + +/** + * struct ti_sci_ops - Function support for TI SCI + * @dev_ops: Device specific operations + */ +struct ti_sci_ops { + struct ti_sci_dev_ops dev_ops; +}; + /** * struct ti_sci_handle - Handle returned to TI SCI clients for usage. * @version: structure containing version information + * @ops: operations that are made available to TI SCI clients */ struct ti_sci_handle { struct ti_sci_version_info version; + struct ti_sci_ops ops; }; #if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL) -- cgit v1.2.3 From 9f72322050e4762adde66619f048b7317ad12d77 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 18 Oct 2016 18:08:36 -0500 Subject: firmware: ti_sci: Add support for Clock control Texas Instrument's System Control Interface (TI-SCI) Message Protocol is used in Texas Instrument's System on Chip (SoC) such as those in keystone family K2G SoC to communicate between various compute processors with a central system controller entity. TI-SCI message protocol provides support for management of various hardware entities within the SoC. Add support driver to allow communication with system controller entity within the SoC using the mailbox client. In general, we expect to function at a device level of abstraction, however, for proper operation of hardware blocks, many clocks directly supplying the hardware block needs to be queried or configured. Introduce support for the set of SCI message protocol support that provide us with this capability. Signed-off-by: Nishanth Menon Signed-off-by: Tero Kristo --- drivers/firmware/ti_sci.c | 685 +++++++++++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 289 ++++++++++++++ include/linux/soc/ti/ti_sci_protocol.h | 78 ++++ 3 files changed, 1052 insertions(+) (limited to 'drivers') diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index c7b25ccf6f07..496a007e5c69 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -902,6 +902,675 @@ static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle, NULL); } +/** + * ti_sci_set_clock_state() - Set clock state helper + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @flags: Header flags as needed + * @state: State to request for the clock. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_set_clock_state(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, + u32 flags, u8 state) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_set_clock_state *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE, + flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_set_clock_state *)xfer->xfer_buf; + req->dev_id = dev_id; + req->clk_id = clk_id; + req->request_state = state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_get_clock_state() - Get clock state helper + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @programmed_state: State requested for clock to move to + * @current_state: State that the clock is currently in + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, + u8 *programmed_state, u8 *current_state) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_get_clock_state *req; + struct ti_sci_msg_resp_get_clock_state *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + if (!programmed_state && !current_state) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_get_clock_state *)xfer->xfer_buf; + req->dev_id = dev_id; + req->clk_id = clk_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) { + ret = -ENODEV; + goto fail; + } + + if (programmed_state) + *programmed_state = resp->programmed_state; + if (current_state) + *current_state = resp->current_state; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false' + * @can_change_freq: 'true' if frequency change is desired, else 'false' + * @enable_input_term: 'true' if input termination is desired, else 'false' + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id, + u8 clk_id, bool needs_ssc, bool can_change_freq, + bool enable_input_term) +{ + u32 flags = 0; + + flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0; + flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0; + flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0; + + return ti_sci_set_clock_state(handle, dev_id, clk_id, flags, + MSG_CLOCK_SW_STATE_REQ); +} + +/** + * ti_sci_cmd_idle_clock() - Idle a clock which is in our control + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * + * NOTE: This clock must have been requested by get_clock previously. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id) +{ + return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, + MSG_CLOCK_SW_STATE_UNREQ); +} + +/** + * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * + * NOTE: This clock must have been requested by get_clock previously. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id) +{ + return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, + MSG_CLOCK_SW_STATE_AUTO); +} + +/** + * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is auto managed + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, bool *req_state) +{ + u8 state = 0; + int ret; + + if (!req_state) + return -EINVAL; + + ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL); + if (ret) + return ret; + + *req_state = (state == MSG_CLOCK_SW_STATE_AUTO); + return 0; +} + +/** + * ti_sci_cmd_clk_is_on() - Is the clock ON + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is managed by us and enabled + * @curr_state: state indicating if the clock is ready for operation + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id, + u8 clk_id, bool *req_state, bool *curr_state) +{ + u8 c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) + return -EINVAL; + + ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, + &r_state, &c_state); + if (ret) + return ret; + + if (req_state) + *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ); + if (curr_state) + *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY); + return 0; +} + +/** + * ti_sci_cmd_clk_is_off() - Is the clock OFF + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is managed by us and disabled + * @curr_state: state indicating if the clock is NOT ready for operation + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id, + u8 clk_id, bool *req_state, bool *curr_state) +{ + u8 c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) + return -EINVAL; + + ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, + &r_state, &c_state); + if (ret) + return ret; + + if (req_state) + *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ); + if (curr_state) + *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY); + return 0; +} + +/** + * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: Parent clock identifier to set + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u8 parent_id) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_set_clock_parent *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_set_clock_parent *)xfer->xfer_buf; + req->dev_id = dev_id; + req->clk_id = clk_id; + req->parent_id = parent_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_clk_get_parent() - Get current parent clock source + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: Current clock parent + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u8 *parent_id) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_get_clock_parent *req; + struct ti_sci_msg_resp_get_clock_parent *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle || !parent_id) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_get_clock_parent *)xfer->xfer_buf; + req->dev_id = dev_id; + req->clk_id = clk_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + *parent_id = resp->parent_id; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @num_parents: Returns he number of parents to the current clock. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, + u8 *num_parents) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_get_clock_num_parents *req; + struct ti_sci_msg_resp_get_clock_num_parents *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle || !num_parents) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_get_clock_num_parents *)xfer->xfer_buf; + req->dev_id = dev_id; + req->clk_id = clk_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_get_clock_num_parents *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + *num_parents = resp->num_parents; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @match_freq: Frequency match in Hz response. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u64 min_freq, + u64 target_freq, u64 max_freq, + u64 *match_freq) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_query_clock_freq *req; + struct ti_sci_msg_resp_query_clock_freq *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle || !match_freq) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_query_clock_freq *)xfer->xfer_buf; + req->dev_id = dev_id; + req->clk_id = clk_id; + req->min_freq_hz = min_freq; + req->target_freq_hz = target_freq; + req->max_freq_hz = max_freq; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + *match_freq = resp->freq_hz; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_clk_set_freq() - Set a frequency for clock + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u64 min_freq, + u64 target_freq, u64 max_freq) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_set_clock_freq *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_set_clock_freq *)xfer->xfer_buf; + req->dev_id = dev_id; + req->clk_id = clk_id; + req->min_freq_hz = min_freq; + req->target_freq_hz = target_freq; + req->max_freq_hz = max_freq; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_clk_get_freq() - Get current frequency + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @freq: Currently frequency in Hz + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u64 *freq) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_get_clock_freq *req; + struct ti_sci_msg_resp_get_clock_freq *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle || !freq) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_get_clock_freq *)xfer->xfer_buf; + req->dev_id = dev_id; + req->clk_id = clk_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + *freq = resp->freq_hz; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + /* * ti_sci_setup_ops() - Setup the operations structures * @info: pointer to TISCI pointer @@ -910,6 +1579,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) { struct ti_sci_ops *ops = &info->handle.ops; struct ti_sci_dev_ops *dops = &ops->dev_ops; + struct ti_sci_clk_ops *cops = &ops->clk_ops; dops->get_device = ti_sci_cmd_get_device; dops->idle_device = ti_sci_cmd_idle_device; @@ -923,6 +1593,21 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) dops->is_transitioning = ti_sci_cmd_dev_is_trans; dops->set_device_resets = ti_sci_cmd_set_device_resets; dops->get_device_resets = ti_sci_cmd_get_device_resets; + + cops->get_clock = ti_sci_cmd_get_clock; + cops->idle_clock = ti_sci_cmd_idle_clock; + cops->put_clock = ti_sci_cmd_put_clock; + cops->is_auto = ti_sci_cmd_clk_is_auto; + cops->is_on = ti_sci_cmd_clk_is_on; + cops->is_off = ti_sci_cmd_clk_is_off; + + cops->set_parent = ti_sci_cmd_clk_set_parent; + cops->get_parent = ti_sci_cmd_clk_get_parent; + cops->get_num_parents = ti_sci_cmd_clk_get_num_parents; + + cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq; + cops->set_freq = ti_sci_cmd_clk_set_freq; + cops->get_freq = ti_sci_cmd_clk_get_freq; } /** diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 29ce0532a7ca..f69907cfc128 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -52,6 +52,16 @@ #define TI_SCI_MSG_GET_DEVICE_STATE 0x0201 #define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202 +/* Clock requests */ +#define TI_SCI_MSG_SET_CLOCK_STATE 0x0100 +#define TI_SCI_MSG_GET_CLOCK_STATE 0x0101 +#define TI_SCI_MSG_SET_CLOCK_PARENT 0x0102 +#define TI_SCI_MSG_GET_CLOCK_PARENT 0x0103 +#define TI_SCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104 +#define TI_SCI_MSG_SET_CLOCK_FREQ 0x010c +#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d +#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e + /** * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses * @type: Type of messages: One of TI_SCI_MSG* values @@ -188,4 +198,283 @@ struct ti_sci_msg_req_set_device_resets { u32 resets; } __packed; +/** + * struct ti_sci_msg_req_set_clock_state - Request to setup a Clock state + * @hdr: Generic Header, Certain flags can be set specific to the clocks: + * MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified + * via spread spectrum clocking. + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's + * frequency to be changed while it is running so long as it + * is within the min/max limits. + * MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this + * is only applicable to clock inputs on the SoC pseudo-device. + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @request_state: Request the state for the clock to be set to. + * MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock, + * it can be disabled, regardless of the state of the device + * MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to + * automatically manage the state of this clock. If the device + * is enabled, then the clock is enabled. If the device is set + * to off or retention, then the clock is internally set as not + * being required by the device.(default) + * MSG_CLOCK_SW_STATE_REQ: Configure the clock to be enabled, + * regardless of the state of the device. + * + * Normally, all required clocks are managed by TISCI entity, this is used + * only for specific control *IF* required. Auto managed state is + * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote + * will explicitly control. + * + * Request type is TI_SCI_MSG_SET_CLOCK_STATE, response is a generic + * ACK or NACK message. + */ +struct ti_sci_msg_req_set_clock_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_CLOCK_ALLOW_SSC TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_CLOCK_INPUT_TERM TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +#define MSG_CLOCK_SW_STATE_UNREQ 0 +#define MSG_CLOCK_SW_STATE_AUTO 1 +#define MSG_CLOCK_SW_STATE_REQ 2 + u8 request_state; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_state - Request for clock state + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get state of. + * + * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state + * of the clock + */ +struct ti_sci_msg_req_get_clock_state { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_state - Response to get clock state + * @hdr: Generic Header + * @programmed_state: Any programmed state of the clock. This is one of + * MSG_CLOCK_SW_STATE* values. + * @current_state: Current state of the clock. This is one of: + * MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready + * MSG_CLOCK_HW_STATE_READY: Clock is ready + * + * Response to TI_SCI_MSG_GET_CLOCK_STATE. + */ +struct ti_sci_msg_resp_get_clock_state { + struct ti_sci_msg_hdr hdr; + u8 programmed_state; +#define MSG_CLOCK_HW_STATE_NOT_READY 0 +#define MSG_CLOCK_HW_STATE_READY 1 + u8 current_state; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_parent - Set the clock parent + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: The new clock parent is selectable by an index via this + * parameter. + * + * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic + * ACK / NACK message. + */ +struct ti_sci_msg_req_set_clock_parent { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; + u8 parent_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_parent - Get the clock parent + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get the parent for. + * + * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information + */ +struct ti_sci_msg_req_get_clock_parent { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent + * @hdr: Generic Header + * @parent_id: The current clock parent + * + * Response to TI_SCI_MSG_GET_CLOCK_PARENT. + */ +struct ti_sci_msg_resp_get_clock_parent { + struct ti_sci_msg_hdr hdr; + u8 parent_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents + * @hdr: Generic header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * + * This request provides information about how many clock parent options + * are available for a given clock to a device. This is typically used + * for input clocks. + * + * Request type is TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_get_clock_num_parents { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents + * @hdr: Generic header + * @num_parents: Number of clock parents + * + * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS + */ +struct ti_sci_msg_resp_get_clock_num_parents { + struct ti_sci_msg_hdr hdr; + u8 num_parents; +} __packed; + +/** + * struct ti_sci_msg_req_query_clock_freq - Request to query a frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq_hz: The target clock frequency. A frequency will be found + * as close to this target frequency as possible. + * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested frequency within provided range and responds with + * result message. + * + * Request type is TI_SCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message, + * or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_query_clock_freq { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u64 min_freq_hz; + u64 target_freq_hz; + u64 max_freq_hz; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_query_clock_freq - Response to a clock frequency query + * @hdr: Generic Header + * @freq_hz: Frequency that is the best match in Hz. + * + * Response to request type TI_SCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request + * cannot be satisfied, the message will be of type NACK. + */ +struct ti_sci_msg_resp_query_clock_freq { + struct ti_sci_msg_hdr hdr; + u64 freq_hz; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_freq - Request to setup a clock frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq_hz: The target clock frequency. The clock will be programmed + * at a rate as close to this target frequency as possible. + * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested range and responds with success/failure message. + * + * This sets the desired frequency for a clock within an allowable + * range. This message will fail on an enabled clock unless + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally, + * if other clocks have their frequency modified due to this message, + * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled. + * + * Calling set frequency on a clock input to the SoC pseudo-device will + * inform the PMMC of that clock's frequency. Setting a frequency of + * zero will indicate the clock is disabled. + * + * Calling set frequency on clock outputs from the SoC pseudo-device will + * function similarly to setting the clock frequency on a device. + * + * Request type is TI_SCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_clock_freq { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u64 min_freq_hz; + u64 target_freq_hz; + u64 max_freq_hz; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In some cases, clock frequencies are configured by host. + * + * Request type is TI_SCI_MSG_GET_CLOCK_FREQ, responded with clock frequency + * that the clock is currently at. + */ +struct ti_sci_msg_req_get_clock_freq { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_freq - Response of clock frequency request + * @hdr: Generic Header + * @freq_hz: Frequency that the clock is currently on, in Hz. + * + * Response to request type TI_SCI_MSG_GET_CLOCK_FREQ. + */ +struct ti_sci_msg_resp_get_clock_freq { + struct ti_sci_msg_hdr hdr; + u64 freq_hz; +} __packed; + #endif /* __TI_SCI_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 87fa73851471..76378fddf609 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -114,12 +114,90 @@ struct ti_sci_dev_ops { u32 *reset_state); }; +/** + * struct ti_sci_clk_ops - Clock control operations + * @get_clock: Request for activation of clock and manage by processor + * - needs_ssc: 'true' if Spread Spectrum clock is desired. + * - can_change_freq: 'true' if frequency change is desired. + * - enable_input_term: 'true' if input termination is desired. + * @idle_clock: Request for Idling a clock managed by processor + * @put_clock: Release the clock to be auto managed by TISCI + * @is_auto: Is the clock being auto managed + * - req_state: state indicating if the clock is auto managed + * @is_on: Is the clock ON + * - req_state: if the clock is requested to be forced ON + * - current_state: if the clock is currently ON + * @is_off: Is the clock OFF + * - req_state: if the clock is requested to be forced OFF + * - current_state: if the clock is currently Gated + * @set_parent: Set the clock source of a specific device clock + * - parent_id: Parent clock identifier to set. + * @get_parent: Get the current clock source of a specific device clock + * - parent_id: Parent clock identifier which is the parent. + * @get_num_parents: Get the number of parents of the current clock source + * - num_parents: returns the number of parent clocks. + * @get_best_match_freq: Find a best matching frequency for a frequency + * range. + * - match_freq: Best matching frequency in Hz. + * @set_freq: Set the Clock frequency + * @get_freq: Get the Clock frequency + * - current_freq: Frequency in Hz that the clock is at. + * + * NOTE: for all these functions, the following parameters are generic in + * nature: + * -handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * -did: Device identifier this request is for + * -cid: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * -min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * -target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * -max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * + * Request for the clock - NOTE: the client MUST maintain integrity of + * usage count by balancing get_clock with put_clock. No refcounting is + * managed by driver for that purpose. + */ +struct ti_sci_clk_ops { + int (*get_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid, + bool needs_ssc, bool can_change_freq, + bool enable_input_term); + int (*idle_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid); + int (*put_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid); + int (*is_auto)(const struct ti_sci_handle *handle, u32 did, u8 cid, + bool *req_state); + int (*is_on)(const struct ti_sci_handle *handle, u32 did, u8 cid, + bool *req_state, bool *current_state); + int (*is_off)(const struct ti_sci_handle *handle, u32 did, u8 cid, + bool *req_state, bool *current_state); + int (*set_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid, + u8 parent_id); + int (*get_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid, + u8 *parent_id); + int (*get_num_parents)(const struct ti_sci_handle *handle, u32 did, + u8 cid, u8 *num_parents); + int (*get_best_match_freq)(const struct ti_sci_handle *handle, u32 did, + u8 cid, u64 min_freq, u64 target_freq, + u64 max_freq, u64 *match_freq); + int (*set_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid, + u64 min_freq, u64 target_freq, u64 max_freq); + int (*get_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid, + u64 *current_freq); +}; + /** * struct ti_sci_ops - Function support for TI SCI * @dev_ops: Device specific operations + * @clk_ops: Clock specific operations */ struct ti_sci_ops { struct ti_sci_dev_ops dev_ops; + struct ti_sci_clk_ops clk_ops; }; /** -- cgit v1.2.3 From 912cffb4ed8612dc99ee0251cc0c9785855162cd Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 18 Oct 2016 18:08:37 -0500 Subject: firmware: ti_sci: Add support for reboot core service Since system controller now has control over SoC power management, it needs to be explicitly requested to reboot the SoC. Add support for it. In some systems however, SoC needs to toggle a GPIO or send event to an external entity (like a PMIC) for a system reboot to take place. To facilitate that, we allow for a DT property to determine if the reboot handler will be registered and further, the service is also made available to other drivers (such as PMIC driver) to sequence the additional operation and trigger the SoC reboot as the last step. Tested-by: Lokesh Vutla Signed-off-by: Nishanth Menon Signed-off-by: Tero Kristo --- drivers/firmware/ti_sci.c | 83 ++++++++++++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 12 +++++ include/linux/soc/ti/ti_sci_protocol.h | 11 +++++ 3 files changed, 106 insertions(+) (limited to 'drivers') diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 496a007e5c69..874ff32db366 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "ti_sci.h" @@ -90,6 +91,7 @@ struct ti_sci_desc { * struct ti_sci_info - Structure representing a TI SCI instance * @dev: Device pointer * @desc: SoC description for this instance + * @nb: Reboot Notifier block * @d: Debugfs file entry * @debug_region: Memory region where the debug message are available * @debug_region_size: Debug region size @@ -104,6 +106,7 @@ struct ti_sci_desc { */ struct ti_sci_info { struct device *dev; + struct notifier_block nb; const struct ti_sci_desc *desc; struct dentry *d; void __iomem *debug_region; @@ -117,10 +120,12 @@ struct ti_sci_info { struct list_head node; /* protected by ti_sci_list_mutex */ int users; + }; #define cl_to_ti_sci_info(c) container_of(c, struct ti_sci_info, cl) #define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle) +#define reboot_to_ti_sci_info(n) container_of(n, struct ti_sci_info, nb) #ifdef CONFIG_DEBUG_FS @@ -1571,6 +1576,52 @@ fail: return ret; } +static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_reboot *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SYS_RESET, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_reboot *)xfer->xfer_buf; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + ret = 0; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + /* * ti_sci_setup_ops() - Setup the operations structures * @info: pointer to TISCI pointer @@ -1578,9 +1629,12 @@ fail: static void ti_sci_setup_ops(struct ti_sci_info *info) { struct ti_sci_ops *ops = &info->handle.ops; + struct ti_sci_core_ops *core_ops = &ops->core_ops; struct ti_sci_dev_ops *dops = &ops->dev_ops; struct ti_sci_clk_ops *cops = &ops->clk_ops; + core_ops->reboot_device = ti_sci_cmd_core_reboot; + dops->get_device = ti_sci_cmd_get_device; dops->idle_device = ti_sci_cmd_idle_device; dops->put_device = ti_sci_cmd_put_device; @@ -1732,6 +1786,18 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) } EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle); +static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode, + void *cmd) +{ + struct ti_sci_info *info = reboot_to_ti_sci_info(nb); + const struct ti_sci_handle *handle = &info->handle; + + ti_sci_cmd_core_reboot(handle); + + /* call fail OR pass, we should not be here in the first place */ + return NOTIFY_BAD; +} + /* Description for K2G */ static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { .host_id = 2, @@ -1759,6 +1825,7 @@ static int ti_sci_probe(struct platform_device *pdev) struct mbox_client *cl; int ret = -EINVAL; int i; + int reboot = 0; of_id = of_match_device(ti_sci_of_match, dev); if (!of_id) { @@ -1773,6 +1840,8 @@ static int ti_sci_probe(struct platform_device *pdev) info->dev = dev; info->desc = desc; + reboot = of_property_read_bool(dev->of_node, + "ti,system-reboot-controller"); INIT_LIST_HEAD(&info->node); minfo = &info->minfo; @@ -1845,6 +1914,17 @@ static int ti_sci_probe(struct platform_device *pdev) ti_sci_setup_ops(info); + if (reboot) { + info->nb.notifier_call = tisci_reboot_handler; + info->nb.priority = 128; + + ret = register_restart_handler(&info->nb); + if (ret) { + dev_err(dev, "reboot registration fail(%d)\n", ret); + return ret; + } + } + dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n", info->handle.version.abi_major, info->handle.version.abi_minor, info->handle.version.firmware_revision, @@ -1874,6 +1954,9 @@ static int ti_sci_remove(struct platform_device *pdev) info = platform_get_drvdata(pdev); + if (info->nb.notifier_call) + unregister_restart_handler(&info->nb); + mutex_lock(&ti_sci_list_mutex); if (info->users) ret = -EBUSY; diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index f69907cfc128..9b611e9e6f6d 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -46,6 +46,7 @@ #define TI_SCI_MSG_VERSION 0x0002 #define TI_SCI_MSG_WAKE_REASON 0x0003 #define TI_SCI_MSG_GOODBYE 0x0004 +#define TI_SCI_MSG_SYS_RESET 0x0005 /* Device requests */ #define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 @@ -105,6 +106,17 @@ struct ti_sci_msg_resp_version { u8 abi_minor; } __packed; +/** + * struct ti_sci_msg_req_reboot - Reboot the SoC + * @hdr: Generic Header + * + * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_reboot { + struct ti_sci_msg_hdr hdr; +} __packed; + /** * struct ti_sci_msg_req_set_device_state - Set the desired state of the device * @hdr: Generic header diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 76378fddf609..0ccbc138c26a 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -35,6 +35,16 @@ struct ti_sci_version_info { struct ti_sci_handle; +/** + * struct ti_sci_core_ops - SoC Core Operations + * @reboot_device: Reboot the SoC + * Returns 0 for successful request(ideally should never return), + * else returns corresponding error value. + */ +struct ti_sci_core_ops { + int (*reboot_device)(const struct ti_sci_handle *handle); +}; + /** * struct ti_sci_dev_ops - Device control operations * @get_device: Command to request for device managed by TISCI @@ -196,6 +206,7 @@ struct ti_sci_clk_ops { * @clk_ops: Clock specific operations */ struct ti_sci_ops { + struct ti_sci_core_ops core_ops; struct ti_sci_dev_ops dev_ops; struct ti_sci_clk_ops clk_ops; }; -- cgit v1.2.3 From a1fee00dc95644e0590b4f1a3755c9f6b1243b3a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 25 Oct 2016 17:33:27 +0100 Subject: PM / Domains: check for negative return from of_count_phandle_with_args() The return from of_count_phandle_with_args can be negative, so we should avoid kcalloc of a negative count of genpd_power_stat structs by sanity checking if count is zero or less. Signed-off-by: Colin Ian King Acked-by: Kevin Hilman Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index aac656a889dc..661737c2bae0 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2113,7 +2113,7 @@ int of_genpd_parse_idle_states(struct device_node *dn, struct of_phandle_iterator it; count = of_count_phandle_with_args(dn, "domain-idle-states", NULL); - if (!count) + if (count <= 0) return -EINVAL; st = kcalloc(count, sizeof(*st), GFP_KERNEL); -- cgit v1.2.3 From 1e80e19ce9c67b2fecce9068ad40d1e778faa58f Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 25 Oct 2016 17:44:19 +0200 Subject: staging: most: aim-networking: keep channels closed if ndo_open fails This patch stops all started channels whenever the function most_nd_open returns an error. Additionally, it renames variable wait_res to ret for the consistency. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-network/networking.c | 38 +++++++++++++++------------ 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index fe0d516cf506..ce1764cba5f0 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -181,7 +181,7 @@ static int most_nd_set_mac_address(struct net_device *dev, void *p) static int most_nd_open(struct net_device *dev) { struct net_dev_context *nd = dev->ml_priv; - long wait_res; + long ret; netdev_info(dev, "open net device\n"); @@ -203,26 +203,30 @@ static int most_nd_open(struct net_device *dev) return -EBUSY; } - nd->channels_opened = true; - netif_wake_queue(dev); - - if (is_valid_ether_addr(dev->dev_addr)) - return 0; - - nd->iface->request_netinfo(nd->iface, nd->tx.ch_id); - wait_res = wait_for_completion_interruptible_timeout( - &nd->mac_compl, msecs_to_jiffies(5000)); - if (!wait_res) { - netdev_err(dev, "mac timeout\n"); - return -EBUSY; - } + if (!is_valid_ether_addr(dev->dev_addr)) { + nd->iface->request_netinfo(nd->iface, nd->tx.ch_id); + ret = wait_for_completion_interruptible_timeout( + &nd->mac_compl, msecs_to_jiffies(5000)); + if (!ret) { + netdev_err(dev, "mac timeout\n"); + ret = -EBUSY; + goto err; + } - if (wait_res < 0) { - netdev_warn(dev, "mac waiting interrupted\n"); - return wait_res; + if (ret < 0) { + netdev_warn(dev, "mac waiting interrupted\n"); + goto err; + } } + nd->channels_opened = true; + netif_wake_queue(dev); return 0; + +err: + most_stop_channel(nd->iface, nd->tx.ch_id, &aim); + most_stop_channel(nd->iface, nd->rx.ch_id, &aim); + return ret; } static int most_nd_stop(struct net_device *dev) -- cgit v1.2.3 From 7c23baa90db1115fbd2b1aca5e07fae091c8dc28 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 25 Oct 2016 17:44:20 +0200 Subject: staging: most: hdm-usb: do h/w specific synchronization at configuration time This patch puts the synchronization procedure trigger for asynchronous channels into the function hdm_configure_channel. Likewise, it removes triggering of hardware specific synchronization for other channel types from the probe function as it is not required. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-usb/hdm_usb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 1a630e1b9392..db11930f2811 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -695,6 +695,15 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, - conf->buffer_size; exit: mdev->conf[channel] = *conf; + if (conf->data_type == MOST_CH_ASYNC) { + u16 ep = mdev->ep_address[channel]; + int err = drci_wr_reg(mdev->usb_device, + DRCI_REG_BASE + DRCI_COMMAND + ep * 16, + 1); + + if (err < 0) + dev_warn(dev, "sync for ep%02x failed", ep); + } return 0; } @@ -1111,7 +1120,6 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) struct most_channel_capability *tmp_cap; struct usb_endpoint_descriptor *ep_desc; int ret = 0; - int err; if (!mdev) goto exit_ENOMEM; @@ -1187,13 +1195,6 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) tmp_cap++; init_usb_anchor(&mdev->busy_urbs[i]); spin_lock_init(&mdev->channel_lock[i]); - err = drci_wr_reg(usb_dev, - DRCI_REG_BASE + DRCI_COMMAND + - ep_desc->bEndpointAddress * 16, - 1); - if (err < 0) - dev_warn(dev, "DCI Sync for EP %02x failed", - ep_desc->bEndpointAddress); } dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n", le16_to_cpu(usb_dev->descriptor.idVendor), -- cgit v1.2.3 From e33269f60ae11443c36e1289e72cf032f31a1972 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 25 Oct 2016 17:44:21 +0200 Subject: staging: most: hdm-usb: introduce synchronization function This patch introduces the function start_sync_ep() and relocates the triggers for synchronization to this function. Signed-off-by: Andrey Shvetsov Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-usb/hdm_usb.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index db11930f2811..34336465c5fa 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -182,6 +182,11 @@ static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) 5 * HZ); } +static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep) +{ + return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1); +} + /** * get_stream_frame_size - calculate frame size of current configuration * @cfg: channel configuration @@ -697,11 +702,8 @@ exit: mdev->conf[channel] = *conf; if (conf->data_type == MOST_CH_ASYNC) { u16 ep = mdev->ep_address[channel]; - int err = drci_wr_reg(mdev->usb_device, - DRCI_REG_BASE + DRCI_COMMAND + ep * 16, - 1); - if (err < 0) + if (start_sync_ep(mdev->usb_device, ep) < 0) dev_warn(dev, "sync for ep%02x failed", ep); } return 0; @@ -987,6 +989,7 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, u16 val; u16 reg_addr; const char *name = attr->attr.name; + struct usb_device *usb_dev = dci_obj->usb_device; int err = kstrtou16(buf, 16, &val); if (err) @@ -997,18 +1000,15 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, return count; } - if (!strcmp(name, "arb_value")) { - reg_addr = dci_obj->reg_addr; - } else if (!strcmp(name, "sync_ep")) { - u16 ep = val; - - reg_addr = DRCI_REG_BASE + DRCI_COMMAND + ep * 16; - val = 1; - } else if (get_static_reg_addr(ro_regs, name, ®_addr)) { + if (!strcmp(name, "arb_value")) + err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val); + else if (!strcmp(name, "sync_ep")) + err = start_sync_ep(usb_dev, val); + else if (!get_static_reg_addr(ro_regs, name, ®_addr)) + err = drci_wr_reg(usb_dev, reg_addr, val); + else return -EFAULT; - } - err = drci_wr_reg(dci_obj->usb_device, reg_addr, val); if (err < 0) return err; -- cgit v1.2.3 From 9d5b4d838f742819b8a531390086ce22e34f91bd Mon Sep 17 00:00:00 2001 From: Nadim Almas Date: Tue, 25 Oct 2016 14:52:21 +0530 Subject: Staging:dgnc:dgnc_tty: fix Block comments should align the * on each line Block comments should align the * on each line as reported by checkpatch.pl Signed-off-by: Nadim Almas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 8f8a3d117150..8dc7c62f4f2f 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -2666,7 +2666,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, uint loopback = 0; /* Let go of locks when accessing user space, * could sleep - */ + */ spin_unlock_irqrestore(&ch->ch_lock, flags); rc = get_user(loopback, (unsigned int __user *)arg); if (rc) -- cgit v1.2.3 From b4cdc9160228a3ea3f71a08915a58da81d5296aa Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 26 Oct 2016 11:20:24 -0500 Subject: staging: fsl-mc: whitespace cleanup: remove blank lines remove instances of multiple blank lines in comments Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpbp-cmd.h | 1 - drivers/staging/fsl-mc/bus/dpbp.c | 1 - drivers/staging/fsl-mc/bus/dpcon-cmd.h | 1 - drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 1 - drivers/staging/fsl-mc/bus/dpmcp.c | 1 - drivers/staging/fsl-mc/bus/dpmcp.h | 1 - drivers/staging/fsl-mc/bus/dpmng-cmd.h | 1 - drivers/staging/fsl-mc/bus/dpmng.c | 1 - drivers/staging/fsl-mc/bus/dprc-cmd.h | 1 - drivers/staging/fsl-mc/bus/dprc.c | 1 - drivers/staging/fsl-mc/bus/mc-io.c | 1 - drivers/staging/fsl-mc/bus/mc-sys.c | 1 - 12 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpbp-cmd.h b/drivers/staging/fsl-mc/bus/dpbp-cmd.h index 2860411ddb51..489c27f68e9b 100644 --- a/drivers/staging/fsl-mc/bus/dpbp-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpbp-cmd.h @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index b392745a4f83..0b2064e44189 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dpcon-cmd.h b/drivers/staging/fsl-mc/bus/dpcon-cmd.h index 536b2ef13507..c89b3051d995 100644 --- a/drivers/staging/fsl-mc/bus/dpcon-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpcon-cmd.h @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h index d098a6d8f6bc..b77c902b58cf 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c index 55766f78a528..865572d4ca02 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.c +++ b/drivers/staging/fsl-mc/bus/dpmcp.c @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h index 5434e094985b..c40253aa73d6 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/drivers/staging/fsl-mc/bus/dpmcp.h @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dpmng-cmd.h b/drivers/staging/fsl-mc/bus/dpmng-cmd.h index a7b77d58c8cd..d42d9773c724 100644 --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpmng-cmd.h @@ -12,7 +12,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/staging/fsl-mc/bus/dpmng.c index 96b1d67756fa..13bec9eaa011 100644 --- a/drivers/staging/fsl-mc/bus/dpmng.c +++ b/drivers/staging/fsl-mc/bus/dpmng.c @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h index 009d65673155..154ce2f756d8 100644 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h +++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h @@ -12,7 +12,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index 9fea3def6041..24c8dfbc90c7 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c index 798c965fe203..fbfda4ca8eeb 100644 --- a/drivers/staging/fsl-mc/bus/mc-io.c +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -11,7 +11,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 285917c7c8e4..b55a53ece51d 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -13,7 +13,6 @@ * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * - * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any -- cgit v1.2.3 From eacaebdd5299e36a2e750c3cbbb414d80aa87fda Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 26 Oct 2016 11:20:25 -0500 Subject: staging: fsl-mc: whitespace cleanup: remove extraenous tabs use one tab to separate name and value in #define definitions Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/include/dprc.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index 593b2bbe7f71..07a11b31fd41 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -139,7 +139,7 @@ int dprc_reset_container(struct fsl_mc_io *mc_io, #define DPRC_IRQ_INDEX 0 /* Number of dprc's IRQs */ -#define DPRC_NUM_OF_IRQS 1 +#define DPRC_NUM_OF_IRQS 1 /* DPRC IRQ events */ @@ -274,20 +274,20 @@ int dprc_get_res_quota(struct fsl_mc_io *mc_io, * are explicit and sequential (in case of resources). * The base ID is given at res_req at base_align field */ -#define DPRC_RES_REQ_OPT_EXPLICIT 0x00000001 +#define DPRC_RES_REQ_OPT_EXPLICIT 0x00000001 /* Aligned resources request - Relevant only for resources * request (and not objects). Indicates that resources base ID should be * sequential and aligned to the value given at dprc_res_req base_align field */ -#define DPRC_RES_REQ_OPT_ALIGNED 0x00000002 +#define DPRC_RES_REQ_OPT_ALIGNED 0x00000002 /* Plugged Flag - Relevant only for object assignment request. * Indicates that after all objects assigned. An interrupt will be invoked at * the relevant GPP. The assigned object will be marked as plugged. * plugged objects can't be assigned from their container */ -#define DPRC_RES_REQ_OPT_PLUGGED 0x00000004 +#define DPRC_RES_REQ_OPT_PLUGGED 0x00000004 /** * struct dprc_res_req - Resource request descriptor, to be used in assignment @@ -353,7 +353,7 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io, * masters; * user is responsible for proper memory handling through IOMMU configuration. */ -#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 +#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 /** * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj() -- cgit v1.2.3 From 7eef98273d785b3ade4dfdb0b9210cff110e2e79 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Wed, 26 Oct 2016 11:20:26 -0500 Subject: staging: fsl-mc: whitespace cleanup: align function args align function arguments that were not aligned to the starting parenthesis Signed-off-by: Ioana Ciornei Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpmcp.h | 32 ++++++++++++++++---------------- drivers/staging/fsl-mc/include/dprc.h | 8 ++++---- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h index c40253aa73d6..0a24c372f90d 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/drivers/staging/fsl-mc/bus/dpmcp.h @@ -61,7 +61,7 @@ struct dpmcp_cfg { int dpmcp_create(struct fsl_mc_io *mc_io, u32 cmd_flags, const struct dpmcp_cfg *cfg, - u16 *token); + u16 *token); int dpmcp_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, @@ -92,45 +92,45 @@ struct dpmcp_irq_cfg { int dpmcp_set_irq(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u8 irq_index, + u8 irq_index, struct dpmcp_irq_cfg *irq_cfg); int dpmcp_get_irq(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u8 irq_index, - int *type, - struct dpmcp_irq_cfg *irq_cfg); + u8 irq_index, + int *type, + struct dpmcp_irq_cfg *irq_cfg); int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u8 irq_index, - u8 en); + u8 irq_index, + u8 en); int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u8 irq_index, - u8 *en); + u8 irq_index, + u8 *en); int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u8 irq_index, - u32 mask); + u8 irq_index, + u32 mask); int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u8 irq_index, - u32 *mask); + u8 irq_index, + u32 *mask); int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u8 irq_index, - u32 *status); + u8 irq_index, + u32 *status); /** * struct dpmcp_attr - Structure representing DPMCP attributes @@ -153,6 +153,6 @@ struct dpmcp_attr { int dpmcp_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - struct dpmcp_attr *attr); + struct dpmcp_attr *attr); #endif /* __FSL_DPMCP_H */ diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index 07a11b31fd41..c40abcda8a32 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -389,10 +389,10 @@ int dprc_get_obj(struct fsl_mc_io *mc_io, int dprc_get_obj_desc(struct fsl_mc_io *mc_io, u32 cmd_flags, - u16 token, - char *obj_type, - int obj_id, - struct dprc_obj_desc *obj_desc); + u16 token, + char *obj_type, + int obj_id, + struct dprc_obj_desc *obj_desc); int dprc_set_obj_irq(struct fsl_mc_io *mc_io, u32 cmd_flags, -- cgit v1.2.3 From fea9a0f51ffce06509c1cad4b9f23589f5e23506 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Wed, 26 Oct 2016 11:20:27 -0500 Subject: staging: fsl-mc: whitespace cleanup: improve alignment in prototypes To improve readability for structs and function definitions, separate type and variable name by a single space, instead of an inconsistent number of tabs. Signed-off-by: Ioana Ciornei Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpmcp.h | 104 +++++----- drivers/staging/fsl-mc/include/dpbp.h | 144 +++++++------- drivers/staging/fsl-mc/include/dpmng.h | 12 +- drivers/staging/fsl-mc/include/dprc.h | 342 ++++++++++++++++----------------- 4 files changed, 301 insertions(+), 301 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h index 0a24c372f90d..c0e6017e3b57 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/drivers/staging/fsl-mc/bus/dpmcp.h @@ -58,10 +58,10 @@ struct dpmcp_cfg { int portal_id; }; -int dpmcp_create(struct fsl_mc_io *mc_io, - u32 cmd_flags, +int dpmcp_create(struct fsl_mc_io *mc_io, + u32 cmd_flags, const struct dpmcp_cfg *cfg, - u16 *token); + u16 *token); int dpmcp_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, @@ -84,53 +84,53 @@ int dpmcp_reset(struct fsl_mc_io *mc_io, * @irq_num: A user defined number associated with this IRQ */ struct dpmcp_irq_cfg { - u64 paddr; - u32 val; - int irq_num; + u64 paddr; + u32 val; + int irq_num; }; -int dpmcp_set_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - struct dpmcp_irq_cfg *irq_cfg); - -int dpmcp_get_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - int *type, - struct dpmcp_irq_cfg *irq_cfg); - -int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u8 en); - -int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u8 *en); - -int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 mask); - -int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 *mask); - -int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 *status); +int dpmcp_set_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + struct dpmcp_irq_cfg *irq_cfg); + +int dpmcp_get_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + int *type, + struct dpmcp_irq_cfg *irq_cfg); + +int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 en); + +int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 *en); + +int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 mask); + +int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *mask); + +int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *status); /** * struct dpmcp_attr - Structure representing DPMCP attributes @@ -150,9 +150,9 @@ struct dpmcp_attr { } version; }; -int dpmcp_get_attributes(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dpmcp_attr *attr); +int dpmcp_get_attributes(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dpmcp_attr *attr); #endif /* __FSL_DPMCP_H */ diff --git a/drivers/staging/fsl-mc/include/dpbp.h b/drivers/staging/fsl-mc/include/dpbp.h index e14e85a5d6df..3ae64056322f 100644 --- a/drivers/staging/fsl-mc/include/dpbp.h +++ b/drivers/staging/fsl-mc/include/dpbp.h @@ -44,8 +44,8 @@ int dpbp_open(struct fsl_mc_io *mc_io, u16 *token); int dpbp_close(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); + u32 cmd_flags, + u16 token); /** * struct dpbp_cfg - Structure representing DPBP configuration @@ -55,10 +55,10 @@ struct dpbp_cfg { u32 options; }; -int dpbp_create(struct fsl_mc_io *mc_io, - u32 cmd_flags, - const struct dpbp_cfg *cfg, - u16 *token); +int dpbp_create(struct fsl_mc_io *mc_io, + u32 cmd_flags, + const struct dpbp_cfg *cfg, + u16 *token); int dpbp_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, @@ -88,59 +88,59 @@ int dpbp_reset(struct fsl_mc_io *mc_io, * @irq_num: A user defined number associated with this IRQ */ struct dpbp_irq_cfg { - u64 addr; - u32 val; - int irq_num; + u64 addr; + u32 val; + int irq_num; }; -int dpbp_set_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - struct dpbp_irq_cfg *irq_cfg); - -int dpbp_get_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - int *type, - struct dpbp_irq_cfg *irq_cfg); - -int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u8 en); - -int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u8 *en); +int dpbp_set_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + struct dpbp_irq_cfg *irq_cfg); + +int dpbp_get_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + int *type, + struct dpbp_irq_cfg *irq_cfg); + +int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 en); + +int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 *en); int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 mask); + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 mask); int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 *mask); - -int dpbp_get_irq_status(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 *status); - -int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 status); + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *mask); + +int dpbp_get_irq_status(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *status); + +int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 status); /** * struct dpbp_attr - Structure representing DPBP attributes @@ -163,10 +163,10 @@ struct dpbp_attr { u16 bpid; }; -int dpbp_get_attributes(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dpbp_attr *attr); +int dpbp_get_attributes(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dpbp_attr *attr); /** * DPBP notifications options @@ -196,24 +196,24 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, * @options: Mask of available options; use 'DPBP_NOTIF_OPT_' values */ struct dpbp_notification_cfg { - u32 depletion_entry; - u32 depletion_exit; - u32 surplus_entry; - u32 surplus_exit; - u64 message_iova; - u64 message_ctx; - u16 options; + u32 depletion_entry; + u32 depletion_exit; + u32 surplus_entry; + u32 surplus_exit; + u64 message_iova; + u64 message_ctx; + u16 options; }; -int dpbp_set_notifications(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dpbp_notification_cfg *cfg); +int dpbp_set_notifications(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dpbp_notification_cfg *cfg); -int dpbp_get_notifications(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dpbp_notification_cfg *cfg); +int dpbp_get_notifications(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dpbp_notification_cfg *cfg); /** @} */ diff --git a/drivers/staging/fsl-mc/include/dpmng.h b/drivers/staging/fsl-mc/include/dpmng.h index e5cfd017f9a5..50343173f5e6 100644 --- a/drivers/staging/fsl-mc/include/dpmng.h +++ b/drivers/staging/fsl-mc/include/dpmng.h @@ -58,12 +58,12 @@ struct mc_version { u32 revision; }; -int mc_get_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - struct mc_version *mc_ver_info); +int mc_get_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + struct mc_version *mc_ver_info); -int dpmng_get_container_id(struct fsl_mc_io *mc_io, - u32 cmd_flags, - int *container_id); +int dpmng_get_container_id(struct fsl_mc_io *mc_io, + u32 cmd_flags, + int *container_id); #endif /* __FSL_DPMNG_H */ diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index c40abcda8a32..a3aa6f98cdd3 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -116,17 +116,17 @@ struct dprc_cfg { char label[16]; }; -int dprc_create_container(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dprc_cfg *cfg, - int *child_container_id, - u64 *child_portal_offset); - -int dprc_destroy_container(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int child_container_id); +int dprc_create_container(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dprc_cfg *cfg, + int *child_container_id, + u64 *child_portal_offset); + +int dprc_destroy_container(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + int child_container_id); int dprc_reset_container(struct fsl_mc_io *mc_io, u32 cmd_flags, @@ -171,59 +171,59 @@ int dprc_reset_container(struct fsl_mc_io *mc_io, * @irq_num: A user defined number associated with this IRQ */ struct dprc_irq_cfg { - phys_addr_t paddr; - u32 val; - int irq_num; + phys_addr_t paddr; + u32 val; + int irq_num; }; -int dprc_set_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - struct dprc_irq_cfg *irq_cfg); - -int dprc_get_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - int *type, - struct dprc_irq_cfg *irq_cfg); - -int dprc_set_irq_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u8 en); - -int dprc_get_irq_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u8 *en); - -int dprc_set_irq_mask(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 mask); - -int dprc_get_irq_mask(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 *mask); - -int dprc_get_irq_status(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 *status); - -int dprc_clear_irq_status(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 status); +int dprc_set_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + struct dprc_irq_cfg *irq_cfg); + +int dprc_get_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + int *type, + struct dprc_irq_cfg *irq_cfg); + +int dprc_set_irq_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 en); + +int dprc_get_irq_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 *en); + +int dprc_set_irq_mask(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 mask); + +int dprc_get_irq_mask(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *mask); + +int dprc_get_irq_status(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 *status); + +int dprc_clear_irq_status(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 status); /** * struct dprc_attributes - Container attributes @@ -249,24 +249,24 @@ struct dprc_attributes { } version; }; -int dprc_get_attributes(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dprc_attributes *attributes); +int dprc_get_attributes(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dprc_attributes *attributes); int dprc_set_res_quota(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int child_container_id, - char *type, - u16 quota); + u32 cmd_flags, + u16 token, + int child_container_id, + char *type, + u16 quota); int dprc_get_res_quota(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int child_container_id, - char *type, - u16 *quota); + u32 cmd_flags, + u16 token, + int child_container_id, + char *type, + u16 *quota); /* Resource request options */ @@ -312,33 +312,33 @@ struct dprc_res_req { int id_base_align; }; -int dprc_assign(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int container_id, - struct dprc_res_req *res_req); - -int dprc_unassign(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int child_container_id, - struct dprc_res_req *res_req); - -int dprc_get_pool_count(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int *pool_count); - -int dprc_get_pool(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int pool_index, - char *type); +int dprc_assign(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + int container_id, + struct dprc_res_req *res_req); + +int dprc_unassign(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + int child_container_id, + struct dprc_res_req *res_req); + +int dprc_get_pool_count(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + int *pool_count); + +int dprc_get_pool(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + int pool_index, + char *type); int dprc_get_obj_count(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int *obj_count); + u32 cmd_flags, + u16 token, + int *obj_count); /* Objects Attributes Flags */ @@ -381,41 +381,41 @@ struct dprc_obj_desc { u16 flags; }; -int dprc_get_obj(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int obj_index, - struct dprc_obj_desc *obj_desc); - -int dprc_get_obj_desc(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - char *obj_type, - int obj_id, - struct dprc_obj_desc *obj_desc); - -int dprc_set_obj_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - char *obj_type, - int obj_id, - u8 irq_index, - struct dprc_irq_cfg *irq_cfg); - -int dprc_get_obj_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - char *obj_type, - int obj_id, - u8 irq_index, - int *type, - struct dprc_irq_cfg *irq_cfg); - -int dprc_get_res_count(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - char *type, - int *res_count); +int dprc_get_obj(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + int obj_index, + struct dprc_obj_desc *obj_desc); + +int dprc_get_obj_desc(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + struct dprc_obj_desc *obj_desc); + +int dprc_set_obj_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + u8 irq_index, + struct dprc_irq_cfg *irq_cfg); + +int dprc_get_obj_irq(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + u8 irq_index, + int *type, + struct dprc_irq_cfg *irq_cfg); + +int dprc_get_res_count(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *type, + int *res_count); /** * enum dprc_iter_status - Iteration status @@ -444,11 +444,11 @@ struct dprc_res_ids_range_desc { enum dprc_iter_status iter_status; }; -int dprc_get_res_ids(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - char *type, - struct dprc_res_ids_range_desc *range_desc); +int dprc_get_res_ids(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *type, + struct dprc_res_ids_range_desc *range_desc); /* Region flags */ /* Cacheable - Indicates that region should be mapped as cacheable */ @@ -481,20 +481,20 @@ struct dprc_region_desc { enum dprc_region_type type; }; -int dprc_get_obj_region(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - char *obj_type, - int obj_id, - u8 region_index, - struct dprc_region_desc *region_desc); - -int dprc_set_obj_label(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - char *obj_type, - int obj_id, - char *label); +int dprc_get_obj_region(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + u8 region_index, + struct dprc_region_desc *region_desc); + +int dprc_set_obj_label(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + char *obj_type, + int obj_id, + char *label); /** * struct dprc_endpoint - Endpoint description for link connect/disconnect @@ -521,24 +521,24 @@ struct dprc_connection_cfg { u32 max_rate; }; -int dprc_connect(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - const struct dprc_endpoint *endpoint1, - const struct dprc_endpoint *endpoint2, +int dprc_connect(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + const struct dprc_endpoint *endpoint1, + const struct dprc_endpoint *endpoint2, const struct dprc_connection_cfg *cfg); -int dprc_disconnect(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - const struct dprc_endpoint *endpoint); - -int dprc_get_connection(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - const struct dprc_endpoint *endpoint1, - struct dprc_endpoint *endpoint2, - int *state); +int dprc_disconnect(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + const struct dprc_endpoint *endpoint); + +int dprc_get_connection(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + const struct dprc_endpoint *endpoint1, + struct dprc_endpoint *endpoint2, + int *state); #endif /* _FSL_DPRC_H */ -- cgit v1.2.3 From 363b0cbf3d978038dc4b532356861bb2c048b03e Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 26 Oct 2016 11:20:28 -0500 Subject: staging: fsl-mc: cleanup comment style Be consistent and use kernel-preferred multi-line comment style everywhere. Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpbp-cmd.h | 3 ++- drivers/staging/fsl-mc/bus/dpbp.c | 3 ++- drivers/staging/fsl-mc/bus/dpcon-cmd.h | 3 ++- drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 3 ++- drivers/staging/fsl-mc/bus/dpmcp.c | 3 ++- drivers/staging/fsl-mc/bus/dpmcp.h | 6 ++++-- drivers/staging/fsl-mc/bus/dpmng.c | 3 ++- drivers/staging/fsl-mc/bus/dprc.c | 3 ++- drivers/staging/fsl-mc/bus/mc-io.c | 3 ++- drivers/staging/fsl-mc/bus/mc-sys.c | 3 ++- drivers/staging/fsl-mc/include/dpbp.h | 6 ++++-- drivers/staging/fsl-mc/include/dpmng.h | 6 ++++-- drivers/staging/fsl-mc/include/dprc.h | 33 ++++++++++++++++++++++----------- drivers/staging/fsl-mc/include/mc-cmd.h | 3 ++- drivers/staging/fsl-mc/include/mc-sys.h | 3 ++- 15 files changed, 56 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpbp-cmd.h b/drivers/staging/fsl-mc/bus/dpbp-cmd.h index 489c27f68e9b..4cc2918ddc51 100644 --- a/drivers/staging/fsl-mc/bus/dpbp-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpbp-cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index 0b2064e44189..122c40d96b2d 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/dpcon-cmd.h b/drivers/staging/fsl-mc/bus/dpcon-cmd.h index c89b3051d995..4ebb3fcab825 100644 --- a/drivers/staging/fsl-mc/bus/dpcon-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpcon-cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. +/* + * Copyright 2013-2015 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h index b77c902b58cf..1073ca272a59 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c index 865572d4ca02..faade1e847f7 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.c +++ b/drivers/staging/fsl-mc/bus/dpmcp.c @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h index c0e6017e3b57..3cd1e3ae897b 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/drivers/staging/fsl-mc/bus/dpmcp.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. +/* + * Copyright 2013-2015 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -31,7 +32,8 @@ #ifndef __FSL_DPMCP_H #define __FSL_DPMCP_H -/* Data Path Management Command Portal API +/* + * Data Path Management Command Portal API * Contains initialization APIs and runtime control APIs for DPMCP */ diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/staging/fsl-mc/bus/dpmng.c index 13bec9eaa011..831c6ed84043 100644 --- a/drivers/staging/fsl-mc/bus/dpmng.c +++ b/drivers/staging/fsl-mc/bus/dpmng.c @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index 24c8dfbc90c7..ace3441ac66b 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c index fbfda4ca8eeb..d66b87f0903b 100644 --- a/drivers/staging/fsl-mc/bus/mc-io.c +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index b55a53ece51d..71140645445a 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -1,4 +1,5 @@ -/* Copyright 2013-2014 Freescale Semiconductor Inc. +/* + * Copyright 2013-2014 Freescale Semiconductor Inc. * * I/O services to send MC commands to the MC hardware * diff --git a/drivers/staging/fsl-mc/include/dpbp.h b/drivers/staging/fsl-mc/include/dpbp.h index 3ae64056322f..2520bf8447c7 100644 --- a/drivers/staging/fsl-mc/include/dpbp.h +++ b/drivers/staging/fsl-mc/include/dpbp.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. +/* + * Copyright 2013-2015 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -32,7 +33,8 @@ #ifndef __FSL_DPBP_H #define __FSL_DPBP_H -/* Data Path Buffer Pool API +/* + * Data Path Buffer Pool API * Contains initialization APIs and runtime control APIs for DPBP */ diff --git a/drivers/staging/fsl-mc/include/dpmng.h b/drivers/staging/fsl-mc/include/dpmng.h index 50343173f5e6..8cd206ef229b 100644 --- a/drivers/staging/fsl-mc/include/dpmng.h +++ b/drivers/staging/fsl-mc/include/dpmng.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. +/* + * Copyright 2013-2015 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -32,7 +33,8 @@ #ifndef __FSL_DPMNG_H #define __FSL_DPMNG_H -/* Management Complex General API +/* + * Management Complex General API * Contains general API for the Management Complex firmware */ diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index a3aa6f98cdd3..67844181a2bc 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. +/* + * Copyright 2013-2015 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -34,7 +35,8 @@ #include "mc-cmd.h" -/* Data Path Resource Container API +/* + * Data Path Resource Container API * Contains DPRC API for managing and querying DPAA resources */ @@ -70,12 +72,14 @@ int dprc_close(struct fsl_mc_io *mc_io, * and can be retrieved using dprc_get_attributes() */ -/* Spawn Policy Option allowed - Indicates that the new container is allowed +/* + * Spawn Policy Option allowed - Indicates that the new container is allowed * to spawn and have its own child containers. */ #define DPRC_CFG_OPT_SPAWN_ALLOWED 0x00000001 -/* General Container allocation policy - Indicates that the new container is +/* + * General Container allocation policy - Indicates that the new container is * allowed to allocate requested resources from its parent container; if not * set, the container is only allowed to use resources in its own pools; Note * that this is a container's global policy, but the parent container may @@ -83,12 +87,14 @@ int dprc_close(struct fsl_mc_io *mc_io, */ #define DPRC_CFG_OPT_ALLOC_ALLOWED 0x00000002 -/* Object initialization allowed - software context associated with this +/* + * Object initialization allowed - software context associated with this * container is allowed to invoke object initialization operations. */ #define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004 -/* Topology change allowed - software context associated with this +/* + * Topology change allowed - software context associated with this * container is allowed to invoke topology operations, such as attach/detach * of network objects. */ @@ -151,12 +157,14 @@ int dprc_reset_container(struct fsl_mc_io *mc_io, #define DPRC_IRQ_EVENT_RES_ADDED 0x00000004 /* IRQ event - Indicates that resources removed from the container */ #define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008 -/* IRQ event - Indicates that one of the descendant containers that opened by +/* + * IRQ event - Indicates that one of the descendant containers that opened by * this container is destroyed */ #define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 -/* IRQ event - Indicates that on one of the container's opened object is +/* + * IRQ event - Indicates that on one of the container's opened object is * destroyed */ #define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 @@ -270,19 +278,22 @@ int dprc_get_res_quota(struct fsl_mc_io *mc_io, /* Resource request options */ -/* Explicit resource ID request - The requested objects/resources +/* + * Explicit resource ID request - The requested objects/resources * are explicit and sequential (in case of resources). * The base ID is given at res_req at base_align field */ #define DPRC_RES_REQ_OPT_EXPLICIT 0x00000001 -/* Aligned resources request - Relevant only for resources +/* + * Aligned resources request - Relevant only for resources * request (and not objects). Indicates that resources base ID should be * sequential and aligned to the value given at dprc_res_req base_align field */ #define DPRC_RES_REQ_OPT_ALIGNED 0x00000002 -/* Plugged Flag - Relevant only for object assignment request. +/* + * Plugged Flag - Relevant only for object assignment request. * Indicates that after all objects assigned. An interrupt will be invoked at * the relevant GPP. The assigned object will be marked as plugged. * plugged objects can't be assigned from their container diff --git a/drivers/staging/fsl-mc/include/mc-cmd.h b/drivers/staging/fsl-mc/include/mc-cmd.h index 5decb9890c31..b07f831ca849 100644 --- a/drivers/staging/fsl-mc/include/mc-cmd.h +++ b/drivers/staging/fsl-mc/include/mc-cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. +/* + * Copyright 2013-2015 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/include/mc-sys.h b/drivers/staging/fsl-mc/include/mc-sys.h index 89ad0cf54702..7276ae311096 100644 --- a/drivers/staging/fsl-mc/include/mc-sys.h +++ b/drivers/staging/fsl-mc/include/mc-sys.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2014 Freescale Semiconductor Inc. +/* + * Copyright 2013-2014 Freescale Semiconductor Inc. * * Interface of the I/O services to send MC commands to the MC hardware * -- cgit v1.2.3 From a673783771d0cb306dc883951cd204a21cbbc2b5 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 26 Oct 2016 11:20:29 -0500 Subject: staging: fsl-mc: improve pr_* messages define pr_fmt so non dev_* messages will have an fsl-mc prefix and remove "fsl-mc" from messages where it would now be redundant Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 44f64b6f0fc9..245acbfe701b 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -9,6 +9,8 @@ * warranty of any kind, whether express or implied. */ +#define pr_fmt(fmt) "fsl-mc: " fmt + #include #include #include @@ -875,11 +877,11 @@ static int __init fsl_mc_bus_driver_init(void) error = bus_register(&fsl_mc_bus_type); if (error < 0) { - pr_err("fsl-mc bus type registration failed: %d\n", error); + pr_err("bus type registration failed: %d\n", error); goto error_cleanup_cache; } - pr_info("fsl-mc bus type registered\n"); + pr_info("bus type registered\n"); error = platform_driver_register(&fsl_mc_bus_driver); if (error < 0) { -- cgit v1.2.3 From 66fcc741edc66a9aa5fd18c1146c8117d30674f4 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 26 Oct 2016 11:20:30 -0500 Subject: staging: fsl-mc: improve message clarity by adding __func__ clarify some error messages by printing the actual function name involved Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 245acbfe701b..5267c503c75b 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -166,8 +166,7 @@ static int fsl_mc_driver_probe(struct device *dev) error = mc_drv->probe(mc_dev); if (error < 0) { - dev_err(dev, "MC object device probe callback failed: %d\n", - error); + dev_err(dev, "%s failed: %d\n", __func__, error); return error; } @@ -185,9 +184,7 @@ static int fsl_mc_driver_remove(struct device *dev) error = mc_drv->remove(mc_dev); if (error < 0) { - dev_err(dev, - "MC object device remove callback failed: %d\n", - error); + dev_err(dev, "%s failed: %d\n", __func__, error); return error; } -- cgit v1.2.3 From e3494af5ce5f7c657e84588de10d0c777ccea8f8 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 26 Oct 2016 11:20:31 -0500 Subject: staging: fsl-mc: cleanup: improve clarity of messages improve some messages by shortening and rewording Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 4 ++-- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 13 +++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index cf1014822906..e92c7804daab 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -605,7 +605,7 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) return error; dev_dbg(&mc_dev->dev, - "Allocatable MC object device bound to fsl_mc_allocator driver"); + "Allocatable fsl-mc device bound to fsl_mc_allocator driver"); return 0; } @@ -627,7 +627,7 @@ static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) } dev_dbg(&mc_dev->dev, - "Allocatable MC object device unbound from fsl_mc_allocator driver"); + "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); return 0; } diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 5267c503c75b..fb062d39503f 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -231,8 +231,7 @@ int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, return error; } - pr_info("MC object device driver %s registered\n", - mc_driver->driver.name); + pr_info("driver %s registered\n", mc_driver->driver.name); return 0; } EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); @@ -571,8 +570,7 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, } (void)get_device(&mc_dev->dev); - dev_dbg(parent_dev, "Added MC object device %s\n", - dev_name(&mc_dev->dev)); + dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev)); *new_mc_dev = mc_dev; return 0; @@ -748,7 +746,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) struct mc_version mc_version; struct resource res; - dev_info(&pdev->dev, "Root MC bus device probed"); + dev_info(&pdev->dev, "root DPRC probed"); mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); if (!mc) @@ -782,8 +780,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) goto error_cleanup_mc_io; } - dev_info(&pdev->dev, - "Freescale Management Complex Firmware version: %u.%u.%u\n", + dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n", mc_version.major, mc_version.minor, mc_version.revision); error = get_mc_addr_translation_ranges(&pdev->dev, @@ -839,7 +836,7 @@ static int fsl_mc_bus_remove(struct platform_device *pdev) fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); mc->root_mc_bus_dev->mc_io = NULL; - dev_info(&pdev->dev, "Root MC bus device removed"); + dev_info(&pdev->dev, "root DPRC removed"); return 0; } -- cgit v1.2.3 From 58caaac1f50331dd687ab39d8b3f90f7eabdb1b5 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 26 Oct 2016 11:20:32 -0500 Subject: staging: fsl-mc: improve wording in comments improve and clarify miscellaneous comments in the bus driver and allocator Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 68 +++++++++++++-------------- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 18 +++---- 2 files changed, 42 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index e92c7804daab..4a7ac976f3fa 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -1,5 +1,5 @@ /* - * Freescale MC object device allocator driver + * fsl-mc object allocator driver * * Copyright (C) 2013 Freescale Semiconductor, Inc. * @@ -23,15 +23,12 @@ strcmp(_obj_type, "dpcon") == 0) /** - * fsl_mc_resource_pool_add_device - add allocatable device to a resource - * pool of a given MC bus + * fsl_mc_resource_pool_add_device - add allocatable object to a resource + * pool of a given fsl-mc bus * - * @mc_bus: pointer to the MC bus - * @pool_type: MC bus pool type - * @mc_dev: Pointer to allocatable MC object device - * - * It adds an allocatable MC object device to a container's resource pool of - * the given resource type + * @mc_bus: pointer to the fsl-mc bus + * @pool_type: pool type + * @mc_dev: pointer to allocatable fsl-mc device */ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus *mc_bus, @@ -95,10 +92,10 @@ out: * fsl_mc_resource_pool_remove_device - remove an allocatable device from a * resource pool * - * @mc_dev: Pointer to allocatable MC object device + * @mc_dev: pointer to allocatable fsl-mc device * - * It permanently removes an allocatable MC object device from the resource - * pool, the device is currently in, as long as it is in the pool's free list. + * It permanently removes an allocatable fsl-mc device from the resource + * pool. It's an error if the device is in use. */ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device *mc_dev) @@ -255,17 +252,18 @@ out_unlock: EXPORT_SYMBOL_GPL(fsl_mc_resource_free); /** - * fsl_mc_object_allocate - Allocates a MC object device of the given - * pool type from a given MC bus + * fsl_mc_object_allocate - Allocates an fsl-mc object of the given + * pool type from a given fsl-mc bus instance * - * @mc_dev: MC device for which the MC object device is to be allocated - * @pool_type: MC bus resource pool type - * @new_mc_dev: Pointer to area where the pointer to the allocated - * MC object device is to be returned + * @mc_dev: fsl-mc device which is used in conjunction with the + * allocated object + * @pool_type: pool type + * @new_mc_dev: pointer to area where the pointer to the allocated device + * is to be returned * - * This function allocates a MC object device from the device's parent DPRC, - * from the corresponding MC bus' pool of allocatable MC object devices of - * the given resource type. mc_dev cannot be a DPRC itself. + * Allocatable objects are always used in conjunction with some functional + * device. This function allocates an object of the specified type from + * the DPRC containing the functional device. * * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC * portals are allocated using fsl_mc_portal_allocate(), instead of @@ -312,10 +310,9 @@ error: EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); /** - * fsl_mc_object_free - Returns an allocatable MC object device to the - * corresponding resource pool of a given MC bus. - * - * @mc_adev: Pointer to the MC object device + * fsl_mc_object_free - Returns an fsl-mc object to the resource + * pool where it came from. + * @mc_adev: Pointer to the fsl-mc device */ void fsl_mc_object_free(struct fsl_mc_device *mc_adev) { @@ -332,8 +329,14 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev) EXPORT_SYMBOL_GPL(fsl_mc_object_free); /* - * Initialize the interrupt pool associated with a MC bus. - * It allocates a block of IRQs from the GIC-ITS + * A DPRC and the devices in the DPRC all share the same GIC-ITS device + * ID. A block of IRQs is pre-allocated and maintained in a pool + * from which devices can allocate them when needed. + */ + +/* + * Initialize the interrupt pool associated with an fsl-mc bus. + * It allocates a block of IRQs from the GIC-ITS. */ int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, unsigned int irq_count) @@ -395,7 +398,7 @@ cleanup_msi_irqs: EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); /** - * Teardown the interrupt pool associated with an MC bus. + * Teardown the interrupt pool associated with an fsl-mc bus. * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. */ void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) @@ -422,11 +425,7 @@ void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); /** - * It allocates the IRQs required by a given MC object device. The - * IRQs are allocated from the interrupt pool associated with the - * MC bus that contains the device, if the device is not a DPRC device. - * Otherwise, the IRQs are allocated from the interrupt pool associated - * with the MC bus that represents the DPRC device itself. + * Allocate the IRQs required by a given fsl-mc device. */ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) { @@ -495,8 +494,7 @@ error_resource_alloc: EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); /* - * It frees the IRQs that were allocated for a MC object device, by - * returning them to the corresponding interrupt pool. + * Frees the IRQs that were allocated for an fsl-mc device. */ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) { diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index fb062d39503f..6f148b2cd504 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -36,7 +36,7 @@ static struct kmem_cache *mc_dev_cache; /** * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device - * @root_mc_bus_dev: MC object device representing the root DPRC + * @root_mc_bus_dev: fsl-mc device representing the root DPRC * @num_translation_ranges: number of entries in addr_translation_ranges * @translation_ranges: array of bus to system address translation ranges */ @@ -64,8 +64,8 @@ struct fsl_mc_addr_translation_range { /** * fsl_mc_bus_match - device to driver matching callback - * @dev: the MC object device structure to match against - * @drv: the device driver to search for matching MC object device id + * @dev: the fsl-mc device to match against + * @drv: the device driver to search for matching fsl-mc object type * structures * * Returns 1 on success, 0 otherwise. @@ -93,7 +93,7 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) /* * Traverse the match_id table of the given driver, trying to find - * a matching for the given MC object device. + * a matching for the given device. */ for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { if (id->vendor == mc_dev->obj_desc.vendor && @@ -450,7 +450,7 @@ bool fsl_mc_is_root_dprc(struct device *dev) } /** - * Add a newly discovered MC object device to be visible in Linux + * Add a newly discovered fsl-mc device to be visible in Linux */ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, struct fsl_mc_io *mc_io, @@ -531,8 +531,8 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, goto error_cleanup_dev; } else { /* - * A non-DPRC MC object device has to be a child of another - * MC object (specifically a DPRC object) + * A non-DPRC object has to be a child of a DPRC, use the + * parent's ICID and interrupt domain. */ mc_dev->icid = parent_mc_dev->icid; mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; @@ -587,10 +587,10 @@ error_cleanup_dev: EXPORT_SYMBOL_GPL(fsl_mc_device_add); /** - * fsl_mc_device_remove - Remove a MC object device from being visible to + * fsl_mc_device_remove - Remove an fsl-mc device from being visible to * Linux * - * @mc_dev: Pointer to a MC object device object + * @mc_dev: Pointer to an fsl-mc device */ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) { -- cgit v1.2.3 From 6466dac79c5a8327972c0a98881102cb00a7ac32 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 26 Oct 2016 11:20:33 -0500 Subject: staging: fsl-mc: update copyright dates Many source files have evolved without copyright date updates. Update the dates to reflect work through 2016. Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpcon-cmd.h | 2 +- drivers/staging/fsl-mc/bus/dpmcp.h | 2 +- drivers/staging/fsl-mc/bus/dprc-driver.c | 2 +- drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 2 +- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 2 +- drivers/staging/fsl-mc/bus/fsl-mc-msi.c | 2 +- drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 2 +- drivers/staging/fsl-mc/bus/mc-sys.c | 2 +- drivers/staging/fsl-mc/include/dpbp.h | 2 +- drivers/staging/fsl-mc/include/dpmng.h | 2 +- drivers/staging/fsl-mc/include/dprc.h | 2 +- drivers/staging/fsl-mc/include/mc-bus.h | 2 +- drivers/staging/fsl-mc/include/mc-cmd.h | 2 +- drivers/staging/fsl-mc/include/mc-sys.h | 2 +- drivers/staging/fsl-mc/include/mc.h | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpcon-cmd.h b/drivers/staging/fsl-mc/bus/dpcon-cmd.h index 4ebb3fcab825..d0a5e194c5e1 100644 --- a/drivers/staging/fsl-mc/bus/dpcon-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpcon-cmd.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 Freescale Semiconductor Inc. + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h index 3cd1e3ae897b..ff971744aa7a 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/drivers/staging/fsl-mc/bus/dpmcp.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 Freescale Semiconductor Inc. + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 6aa2915e8096..b4e46fb0bd77 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -1,7 +1,7 @@ /* * Freescale data path resource container (DPRC) driver * - * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. * Author: German Rivera * * This file is licensed under the terms of the GNU General Public diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 4a7ac976f3fa..ce07096c3b1f 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -1,7 +1,7 @@ /* * fsl-mc object allocator driver * - * Copyright (C) 2013 Freescale Semiconductor, Inc. + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 6f148b2cd504..4588202af035 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -1,7 +1,7 @@ /* * Freescale Management Complex (MC) bus driver * - * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. * Author: German Rivera * * This file is licensed under the terms of the GNU General Public diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c index 3d46b1b1fa18..7975c6e6fee3 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -1,7 +1,7 @@ /* * Freescale Management Complex (MC) bus driver MSI support * - * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. * Author: German Rivera * * This file is licensed under the terms of the GNU General Public diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index 16b0d4a60205..6b1cd574644f 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -1,7 +1,7 @@ /* * Freescale Management Complex (MC) bus driver MSI support * - * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. * Author: German Rivera * * This file is licensed under the terms of the GNU General Public diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 71140645445a..e47bd2375ed7 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 Freescale Semiconductor Inc. + * Copyright 2013-2016 Freescale Semiconductor Inc. * * I/O services to send MC commands to the MC hardware * diff --git a/drivers/staging/fsl-mc/include/dpbp.h b/drivers/staging/fsl-mc/include/dpbp.h index 2520bf8447c7..550b5e117044 100644 --- a/drivers/staging/fsl-mc/include/dpbp.h +++ b/drivers/staging/fsl-mc/include/dpbp.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 Freescale Semiconductor Inc. + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/include/dpmng.h b/drivers/staging/fsl-mc/include/dpmng.h index 8cd206ef229b..7d8e255da578 100644 --- a/drivers/staging/fsl-mc/include/dpmng.h +++ b/drivers/staging/fsl-mc/include/dpmng.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 Freescale Semiconductor Inc. + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index 67844181a2bc..6365159c0424 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 Freescale Semiconductor Inc. + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index 170684a57ca2..e915574d9147 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -1,7 +1,7 @@ /* * Freescale Management Complex (MC) bus declarations * - * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. * Author: German Rivera * * This file is licensed under the terms of the GNU General Public diff --git a/drivers/staging/fsl-mc/include/mc-cmd.h b/drivers/staging/fsl-mc/include/mc-cmd.h index b07f831ca849..f33ad1718130 100644 --- a/drivers/staging/fsl-mc/include/mc-cmd.h +++ b/drivers/staging/fsl-mc/include/mc-cmd.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 Freescale Semiconductor Inc. + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/drivers/staging/fsl-mc/include/mc-sys.h b/drivers/staging/fsl-mc/include/mc-sys.h index 7276ae311096..dca7f9084e05 100644 --- a/drivers/staging/fsl-mc/include/mc-sys.h +++ b/drivers/staging/fsl-mc/include/mc-sys.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 Freescale Semiconductor Inc. + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Interface of the I/O services to send MC commands to the MC hardware * diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index f6e720e84460..a781a36971a5 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -1,7 +1,7 @@ /* * Freescale Management Complex (MC) bus public interface * - * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. * Author: German Rivera * * This file is licensed under the terms of the GNU General Public -- cgit v1.2.3 From decd3d0cfda6ccb2d6d3e942777a4eb18949704c Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Wed, 26 Oct 2016 11:20:34 -0500 Subject: staging: fsl-mc: uprev binary interface to match MC v10.x DPAA2 will not support MC firmware versions prior to MC v10.x. Update the MC interface code and drivers to reflect this. -update the object .h files and code that builds commands to include the new command version in the command header -object versions are no longer available in the object attributes, so remove references to them and instead get the version from the new get_api_version() command -create/destroy commands for all objects have new arguments -dpmng_get_container_id() is replaced by dprc_get_container_id() This supports a hardware ABI change and thus to match the new ABI all the above changes need to happen in a single patch. All MC firmware versions >= 10 will be supported going forward. Signed-off-by: Ioana Ciornei Signed-off-by: Stuart Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpbp-cmd.h | 57 +++++++++++--------- drivers/staging/fsl-mc/bus/dpbp.c | 67 ++++++++++++++++++------ drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 45 ++++++++++------ drivers/staging/fsl-mc/bus/dpmcp.c | 66 +++++++++++++++++------ drivers/staging/fsl-mc/bus/dpmcp.h | 18 ++----- drivers/staging/fsl-mc/bus/dpmng-cmd.h | 13 ++--- drivers/staging/fsl-mc/bus/dpmng.c | 33 ------------ drivers/staging/fsl-mc/bus/dprc-cmd.h | 89 +++++++++++++++++--------------- drivers/staging/fsl-mc/bus/dprc-driver.c | 19 +++++-- drivers/staging/fsl-mc/bus/dprc.c | 65 ++++++++++++++++++++++- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 22 ++------ drivers/staging/fsl-mc/bus/mc-sys.c | 8 +-- drivers/staging/fsl-mc/include/dpbp.h | 21 ++++---- drivers/staging/fsl-mc/include/dprc.h | 19 ++++--- drivers/staging/fsl-mc/include/mc-cmd.h | 41 +++++++++++---- 15 files changed, 356 insertions(+), 227 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpbp-cmd.h b/drivers/staging/fsl-mc/bus/dpbp-cmd.h index 4cc2918ddc51..7d86539b5414 100644 --- a/drivers/staging/fsl-mc/bus/dpbp-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpbp-cmd.h @@ -33,37 +33,48 @@ #define _FSL_DPBP_CMD_H /* DPBP Version */ -#define DPBP_VER_MAJOR 2 +#define DPBP_VER_MAJOR 3 #define DPBP_VER_MINOR 2 +/* Command versioning */ +#define DPBP_CMD_BASE_VERSION 1 +#define DPBP_CMD_ID_OFFSET 4 + +#define DPBP_CMD(id) ((id << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION) + /* Command IDs */ -#define DPBP_CMDID_CLOSE 0x800 -#define DPBP_CMDID_OPEN 0x804 -#define DPBP_CMDID_CREATE 0x904 -#define DPBP_CMDID_DESTROY 0x900 - -#define DPBP_CMDID_ENABLE 0x002 -#define DPBP_CMDID_DISABLE 0x003 -#define DPBP_CMDID_GET_ATTR 0x004 -#define DPBP_CMDID_RESET 0x005 -#define DPBP_CMDID_IS_ENABLED 0x006 - -#define DPBP_CMDID_SET_IRQ 0x010 -#define DPBP_CMDID_GET_IRQ 0x011 -#define DPBP_CMDID_SET_IRQ_ENABLE 0x012 -#define DPBP_CMDID_GET_IRQ_ENABLE 0x013 -#define DPBP_CMDID_SET_IRQ_MASK 0x014 -#define DPBP_CMDID_GET_IRQ_MASK 0x015 -#define DPBP_CMDID_GET_IRQ_STATUS 0x016 -#define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017 - -#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0 -#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1 +#define DPBP_CMDID_CLOSE DPBP_CMD(0x800) +#define DPBP_CMDID_OPEN DPBP_CMD(0x804) +#define DPBP_CMDID_CREATE DPBP_CMD(0x904) +#define DPBP_CMDID_DESTROY DPBP_CMD(0x984) +#define DPBP_CMDID_GET_API_VERSION DPBP_CMD(0xa04) + +#define DPBP_CMDID_ENABLE DPBP_CMD(0x002) +#define DPBP_CMDID_DISABLE DPBP_CMD(0x003) +#define DPBP_CMDID_GET_ATTR DPBP_CMD(0x004) +#define DPBP_CMDID_RESET DPBP_CMD(0x005) +#define DPBP_CMDID_IS_ENABLED DPBP_CMD(0x006) + +#define DPBP_CMDID_SET_IRQ DPBP_CMD(0x010) +#define DPBP_CMDID_GET_IRQ DPBP_CMD(0x011) +#define DPBP_CMDID_SET_IRQ_ENABLE DPBP_CMD(0x012) +#define DPBP_CMDID_GET_IRQ_ENABLE DPBP_CMD(0x013) +#define DPBP_CMDID_SET_IRQ_MASK DPBP_CMD(0x014) +#define DPBP_CMDID_GET_IRQ_MASK DPBP_CMD(0x015) +#define DPBP_CMDID_GET_IRQ_STATUS DPBP_CMD(0x016) +#define DPBP_CMDID_CLEAR_IRQ_STATUS DPBP_CMD(0x017) + +#define DPBP_CMDID_SET_NOTIFICATIONS DPBP_CMD(0x01b0) +#define DPBP_CMDID_GET_NOTIFICATIONS DPBP_CMD(0x01b1) struct dpbp_cmd_open { __le32 dpbp_id; }; +struct dpbp_cmd_destroy { + __le32 object_id; +}; + #define DPBP_ENABLE 0x1 struct dpbp_rsp_is_enabled { diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index 122c40d96b2d..cf4782f6a049 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -108,28 +108,26 @@ EXPORT_SYMBOL(dpbp_close); /** * dpbp_create() - Create the DPBP object. * @mc_io: Pointer to MC portal's I/O object + * @dprc_token: Parent container token; '0' for default container * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @cfg: Configuration structure - * @token: Returned token; use in subsequent API calls + * @obj_id: Returned object id; use in subsequent API calls * * Create the DPBP object, allocate required resources and * perform required initialization. * - * The object can be created either by declaring it in the - * DPL file, or by calling this function. - * This function returns a unique authentication token, - * associated with the specific object ID and the specific MC - * portal; this token must be used in all subsequent calls to - * this specific object. For objects that are created using the - * DPL file, call dpbp_open function to get an authentication - * token first. + * This function accepts an authentication token of a parent + * container that this object should be assigned to and returns + * an object id. This object_id will be used in all subsequent calls to + * this specific object. * * Return: '0' on Success; Error code otherwise. */ int dpbp_create(struct fsl_mc_io *mc_io, + u16 dprc_token, u32 cmd_flags, const struct dpbp_cfg *cfg, - u16 *token) + u32 *obj_id) { struct mc_command cmd = { 0 }; int err; @@ -138,7 +136,7 @@ int dpbp_create(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE, - cmd_flags, 0); + cmd_flags, dprc_token); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -146,7 +144,7 @@ int dpbp_create(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *token = mc_cmd_hdr_read_token(&cmd); + *obj_id = mc_cmd_read_object_id(&cmd); return 0; } @@ -154,20 +152,25 @@ int dpbp_create(struct fsl_mc_io *mc_io, /** * dpbp_destroy() - Destroy the DPBP object and release all its resources. * @mc_io: Pointer to MC portal's I/O object + * @dprc_token: Parent container token; '0' for default container * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPBP object + * @obj_id: ID of DPBP object * * Return: '0' on Success; error code otherwise. */ int dpbp_destroy(struct fsl_mc_io *mc_io, + u16 dprc_token, u32 cmd_flags, - u16 token) + u32 obj_id) { + struct dpbp_cmd_destroy *cmd_params; struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY, - cmd_flags, token); + cmd_flags, dprc_token); + cmd_params = (struct dpbp_cmd_destroy *)cmd.params; + cmd_params->object_id = cpu_to_le32(obj_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -610,8 +613,6 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params; attr->bpid = le16_to_cpu(rsp_params->bpid); attr->id = le32_to_cpu(rsp_params->id); - attr->version.major = le16_to_cpu(rsp_params->version_major); - attr->version.minor = le16_to_cpu(rsp_params->version_minor); return 0; } @@ -690,3 +691,35 @@ int dpbp_get_notifications(struct fsl_mc_io *mc_io, return 0; } + +/** + * dpbp_get_api_version - Get Data Path Buffer Pool API version + * @mc_io: Pointer to Mc portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @major_ver: Major version of Buffer Pool API + * @minor_ver: Minor version of Buffer Pool API + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_API_VERSION, + cmd_flags, 0); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); + + return 0; +} diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h index 1073ca272a59..7cb514963c26 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h @@ -33,25 +33,32 @@ #define _FSL_DPMCP_CMD_H /* Minimal supported DPMCP Version */ -#define DPMCP_MIN_VER_MAJOR 3 -#define DPMCP_MIN_VER_MINOR 0 +#define DPMCP_MIN_VER_MAJOR 3 +#define DPMCP_MIN_VER_MINOR 0 + +/* Command versioning */ +#define DPMCP_CMD_BASE_VERSION 1 +#define DPMCP_CMD_ID_OFFSET 4 + +#define DPMCP_CMD(id) ((id << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION) /* Command IDs */ -#define DPMCP_CMDID_CLOSE 0x800 -#define DPMCP_CMDID_OPEN 0x80b -#define DPMCP_CMDID_CREATE 0x90b -#define DPMCP_CMDID_DESTROY 0x900 - -#define DPMCP_CMDID_GET_ATTR 0x004 -#define DPMCP_CMDID_RESET 0x005 - -#define DPMCP_CMDID_SET_IRQ 0x010 -#define DPMCP_CMDID_GET_IRQ 0x011 -#define DPMCP_CMDID_SET_IRQ_ENABLE 0x012 -#define DPMCP_CMDID_GET_IRQ_ENABLE 0x013 -#define DPMCP_CMDID_SET_IRQ_MASK 0x014 -#define DPMCP_CMDID_GET_IRQ_MASK 0x015 -#define DPMCP_CMDID_GET_IRQ_STATUS 0x016 +#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) +#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b) +#define DPMCP_CMDID_CREATE DPMCP_CMD(0x90b) +#define DPMCP_CMDID_DESTROY DPMCP_CMD(0x98b) +#define DPMCP_CMDID_GET_API_VERSION DPMCP_CMD(0xa0b) + +#define DPMCP_CMDID_GET_ATTR DPMCP_CMD(0x004) +#define DPMCP_CMDID_RESET DPMCP_CMD(0x005) + +#define DPMCP_CMDID_SET_IRQ DPMCP_CMD(0x010) +#define DPMCP_CMDID_GET_IRQ DPMCP_CMD(0x011) +#define DPMCP_CMDID_SET_IRQ_ENABLE DPMCP_CMD(0x012) +#define DPMCP_CMDID_GET_IRQ_ENABLE DPMCP_CMD(0x013) +#define DPMCP_CMDID_SET_IRQ_MASK DPMCP_CMD(0x014) +#define DPMCP_CMDID_GET_IRQ_MASK DPMCP_CMD(0x015) +#define DPMCP_CMDID_GET_IRQ_STATUS DPMCP_CMD(0x016) struct dpmcp_cmd_open { __le32 dpmcp_id; @@ -61,6 +68,10 @@ struct dpmcp_cmd_create { __le32 portal_id; }; +struct dpmcp_cmd_destroy { + __le32 object_id; +}; + struct dpmcp_cmd_set_irq { /* cmd word 0 */ u8 irq_index; diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c index faade1e847f7..e4d16519bcb4 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.c +++ b/drivers/staging/fsl-mc/bus/dpmcp.c @@ -106,28 +106,29 @@ int dpmcp_close(struct fsl_mc_io *mc_io, /** * dpmcp_create() - Create the DPMCP object. * @mc_io: Pointer to MC portal's I/O object + * @dprc_token: Parent container token; '0' for default container * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @cfg: Configuration structure - * @token: Returned token; use in subsequent API calls + * @obj_id: Returned object id; use in subsequent API calls * * Create the DPMCP object, allocate required resources and * perform required initialization. * * The object can be created either by declaring it in the * DPL file, or by calling this function. - * This function returns a unique authentication token, - * associated with the specific object ID and the specific MC - * portal; this token must be used in all subsequent calls to - * this specific object. For objects that are created using the - * DPL file, call dpmcp_open function to get an authentication - * token first. + + * This function accepts an authentication token of a parent + * container that this object should be assigned to and returns + * an object id. This object_id will be used in all subsequent calls to + * this specific object. * * Return: '0' on Success; Error code otherwise. */ int dpmcp_create(struct fsl_mc_io *mc_io, + u16 dprc_token, u32 cmd_flags, const struct dpmcp_cfg *cfg, - u16 *token) + u32 *obj_id) { struct mc_command cmd = { 0 }; struct dpmcp_cmd_create *cmd_params; @@ -136,7 +137,7 @@ int dpmcp_create(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE, - cmd_flags, 0); + cmd_flags, dprc_token); cmd_params = (struct dpmcp_cmd_create *)cmd.params; cmd_params->portal_id = cpu_to_le32(cfg->portal_id); @@ -146,7 +147,7 @@ int dpmcp_create(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *token = mc_cmd_hdr_read_token(&cmd); + *obj_id = mc_cmd_read_object_id(&cmd); return 0; } @@ -154,20 +155,25 @@ int dpmcp_create(struct fsl_mc_io *mc_io, /** * dpmcp_destroy() - Destroy the DPMCP object and release all its resources. * @mc_io: Pointer to MC portal's I/O object + * @dprc_token: Parent container token; '0' for default container * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPMCP object + * @obj_id: ID of DPMCP object * * Return: '0' on Success; error code otherwise. */ int dpmcp_destroy(struct fsl_mc_io *mc_io, + u16 dprc_token, u32 cmd_flags, - u16 token) + u32 obj_id) { struct mc_command cmd = { 0 }; + struct dpmcp_cmd_destroy *cmd_params; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY, - cmd_flags, token); + cmd_flags, dprc_token); + cmd_params = (struct dpmcp_cmd_destroy *)cmd.params; + cmd_params->object_id = cpu_to_le32(obj_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -497,8 +503,38 @@ int dpmcp_get_attributes(struct fsl_mc_io *mc_io, /* retrieve response parameters */ rsp_params = (struct dpmcp_rsp_get_attributes *)cmd.params; attr->id = le32_to_cpu(rsp_params->id); - attr->version.major = le16_to_cpu(rsp_params->version_major); - attr->version.minor = le16_to_cpu(rsp_params->version_minor); + + return 0; +} + +/** + * dpmcp_get_api_version - Get Data Path Management Command Portal API version + * @mc_io: Pointer to Mc portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @major_ver: Major version of Data Path Management Command Portal API + * @minor_ver: Minor version of Data Path Management Command Portal API + * + * Return: '0' on Success; Error code otherwise. + */ +int dpmcp_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_API_VERSION, + cmd_flags, 0); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); return 0; } diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h index ff971744aa7a..98a100d543f6 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/drivers/staging/fsl-mc/bus/dpmcp.h @@ -61,13 +61,15 @@ struct dpmcp_cfg { }; int dpmcp_create(struct fsl_mc_io *mc_io, + u16 dprc_token, u32 cmd_flags, - const struct dpmcp_cfg *cfg, - u16 *token); + const struct dpmcp_cfg *cfg, + u32 *obj_id); int dpmcp_destroy(struct fsl_mc_io *mc_io, + u16 dprc_token, u32 cmd_flags, - u16 token); + u32 obj_id); int dpmcp_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, @@ -137,19 +139,9 @@ int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, /** * struct dpmcp_attr - Structure representing DPMCP attributes * @id: DPMCP object ID - * @version: DPMCP version */ struct dpmcp_attr { int id; - /** - * struct version - Structure representing DPMCP version - * @major: DPMCP major version - * @minor: DPMCP minor version - */ - struct { - u16 major; - u16 minor; - } version; }; int dpmcp_get_attributes(struct fsl_mc_io *mc_io, diff --git a/drivers/staging/fsl-mc/bus/dpmng-cmd.h b/drivers/staging/fsl-mc/bus/dpmng-cmd.h index d42d9773c724..cdddfb80eecc 100644 --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpmng-cmd.h @@ -40,13 +40,14 @@ #ifndef __FSL_DPMNG_CMD_H #define __FSL_DPMNG_CMD_H -/* Command IDs */ -#define DPMNG_CMDID_GET_CONT_ID 0x830 -#define DPMNG_CMDID_GET_VERSION 0x831 +/* Command versioning */ +#define DPMNG_CMD_BASE_VERSION 1 +#define DPMNG_CMD_ID_OFFSET 4 -struct dpmng_rsp_get_container_id { - __le32 container_id; -}; +#define DPMNG_CMD(id) ((id << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION) + +/* Command IDs */ +#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831) struct dpmng_rsp_get_version { __le32 revision; diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/staging/fsl-mc/bus/dpmng.c index 831c6ed84043..ad5d5bbec529 100644 --- a/drivers/staging/fsl-mc/bus/dpmng.c +++ b/drivers/staging/fsl-mc/bus/dpmng.c @@ -72,36 +72,3 @@ int mc_get_version(struct fsl_mc_io *mc_io, } EXPORT_SYMBOL(mc_get_version); -/** - * dpmng_get_container_id() - Get container ID associated with a given portal. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @container_id: Requested container ID - * - * Return: '0' on Success; Error code otherwise. - */ -int dpmng_get_container_id(struct fsl_mc_io *mc_io, - u32 cmd_flags, - int *container_id) -{ - struct mc_command cmd = { 0 }; - struct dpmng_rsp_get_container_id *rsp_params; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_CONT_ID, - cmd_flags, - 0); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - rsp_params = (struct dpmng_rsp_get_container_id *)cmd.params; - *container_id = le32_to_cpu(rsp_params->container_id); - - return 0; -} - diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h index 154ce2f756d8..588b8cafdbc7 100644 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h +++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h @@ -41,48 +41,56 @@ #define _FSL_DPRC_CMD_H /* Minimal supported DPRC Version */ -#define DPRC_MIN_VER_MAJOR 5 +#define DPRC_MIN_VER_MAJOR 6 #define DPRC_MIN_VER_MINOR 0 +/* Command versioning */ +#define DPRC_CMD_BASE_VERSION 1 +#define DPRC_CMD_ID_OFFSET 4 + +#define DPRC_CMD(id) ((id << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) + /* Command IDs */ -#define DPRC_CMDID_CLOSE 0x800 -#define DPRC_CMDID_OPEN 0x805 -#define DPRC_CMDID_CREATE 0x905 - -#define DPRC_CMDID_GET_ATTR 0x004 -#define DPRC_CMDID_RESET_CONT 0x005 - -#define DPRC_CMDID_SET_IRQ 0x010 -#define DPRC_CMDID_GET_IRQ 0x011 -#define DPRC_CMDID_SET_IRQ_ENABLE 0x012 -#define DPRC_CMDID_GET_IRQ_ENABLE 0x013 -#define DPRC_CMDID_SET_IRQ_MASK 0x014 -#define DPRC_CMDID_GET_IRQ_MASK 0x015 -#define DPRC_CMDID_GET_IRQ_STATUS 0x016 -#define DPRC_CMDID_CLEAR_IRQ_STATUS 0x017 - -#define DPRC_CMDID_CREATE_CONT 0x151 -#define DPRC_CMDID_DESTROY_CONT 0x152 -#define DPRC_CMDID_SET_RES_QUOTA 0x155 -#define DPRC_CMDID_GET_RES_QUOTA 0x156 -#define DPRC_CMDID_ASSIGN 0x157 -#define DPRC_CMDID_UNASSIGN 0x158 -#define DPRC_CMDID_GET_OBJ_COUNT 0x159 -#define DPRC_CMDID_GET_OBJ 0x15A -#define DPRC_CMDID_GET_RES_COUNT 0x15B -#define DPRC_CMDID_GET_RES_IDS 0x15C -#define DPRC_CMDID_GET_OBJ_REG 0x15E -#define DPRC_CMDID_SET_OBJ_IRQ 0x15F -#define DPRC_CMDID_GET_OBJ_IRQ 0x160 -#define DPRC_CMDID_SET_OBJ_LABEL 0x161 -#define DPRC_CMDID_GET_OBJ_DESC 0x162 - -#define DPRC_CMDID_CONNECT 0x167 -#define DPRC_CMDID_DISCONNECT 0x168 -#define DPRC_CMDID_GET_POOL 0x169 -#define DPRC_CMDID_GET_POOL_COUNT 0x16A - -#define DPRC_CMDID_GET_CONNECTION 0x16C +#define DPRC_CMDID_CLOSE DPRC_CMD(0x800) +#define DPRC_CMDID_OPEN DPRC_CMD(0x805) +#define DPRC_CMDID_CREATE DPRC_CMD(0x905) +#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05) + +#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004) +#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005) + +#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010) +#define DPRC_CMDID_GET_IRQ DPRC_CMD(0x011) +#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012) +#define DPRC_CMDID_GET_IRQ_ENABLE DPRC_CMD(0x013) +#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014) +#define DPRC_CMDID_GET_IRQ_MASK DPRC_CMD(0x015) +#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016) +#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017) + +#define DPRC_CMDID_CREATE_CONT DPRC_CMD(0x151) +#define DPRC_CMDID_DESTROY_CONT DPRC_CMD(0x152) +#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830) +#define DPRC_CMDID_SET_RES_QUOTA DPRC_CMD(0x155) +#define DPRC_CMDID_GET_RES_QUOTA DPRC_CMD(0x156) +#define DPRC_CMDID_ASSIGN DPRC_CMD(0x157) +#define DPRC_CMDID_UNASSIGN DPRC_CMD(0x158) +#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159) +#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A) +#define DPRC_CMDID_GET_RES_COUNT DPRC_CMD(0x15B) +#define DPRC_CMDID_GET_RES_IDS DPRC_CMD(0x15C) +#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) +#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) +#define DPRC_CMDID_GET_OBJ_IRQ DPRC_CMD(0x160) +#define DPRC_CMDID_SET_OBJ_LABEL DPRC_CMD(0x161) +#define DPRC_CMDID_GET_OBJ_DESC DPRC_CMD(0x162) + +#define DPRC_CMDID_CONNECT DPRC_CMD(0x167) +#define DPRC_CMDID_DISCONNECT DPRC_CMD(0x168) +#define DPRC_CMDID_GET_POOL DPRC_CMD(0x169) +#define DPRC_CMDID_GET_POOL_COUNT DPRC_CMD(0x16A) + +#define DPRC_CMDID_GET_CONNECTION DPRC_CMD(0x16C) struct dprc_cmd_open { __le32 container_id; @@ -198,9 +206,6 @@ struct dprc_rsp_get_attributes { /* response word 1 */ __le32 options; __le32 portal_id; - /* response word 2 */ - __le16 version_major; - __le16 version_minor; }; struct dprc_cmd_set_res_quota { diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index b4e46fb0bd77..4e416d89b736 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -597,6 +597,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); bool mc_io_created = false; bool msi_domain_set = false; + u16 major_ver, minor_ver; if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) return -EINVAL; @@ -669,13 +670,21 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) goto error_cleanup_open; } - if (mc_bus->dprc_attr.version.major < DPRC_MIN_VER_MAJOR || - (mc_bus->dprc_attr.version.major == DPRC_MIN_VER_MAJOR && - mc_bus->dprc_attr.version.minor < DPRC_MIN_VER_MINOR)) { + error = dprc_get_api_version(mc_dev->mc_io, 0, + &major_ver, + &minor_ver); + if (error < 0) { + dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n", + error); + goto error_cleanup_open; + } + + if (major_ver < DPRC_MIN_VER_MAJOR || + (major_ver == DPRC_MIN_VER_MAJOR && + minor_ver < DPRC_MIN_VER_MINOR)) { dev_err(&mc_dev->dev, "ERROR: DPRC version %d.%d not supported\n", - mc_bus->dprc_attr.version.major, - mc_bus->dprc_attr.version.minor); + major_ver, minor_ver); error = -ENOTSUPP; goto error_cleanup_open; } diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index ace3441ac66b..572edd4c066e 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -565,8 +565,6 @@ int dprc_get_attributes(struct fsl_mc_io *mc_io, attr->icid = le16_to_cpu(rsp_params->icid); attr->options = le32_to_cpu(rsp_params->options); attr->portal_id = le32_to_cpu(rsp_params->portal_id); - attr->version.major = le16_to_cpu(rsp_params->version_major); - attr->version.minor = le16_to_cpu(rsp_params->version_minor); return 0; } @@ -1386,3 +1384,66 @@ int dprc_get_connection(struct fsl_mc_io *mc_io, return 0; } + +/** + * dprc_get_api_version - Get Data Path Resource Container API version + * @mc_io: Pointer to Mc portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @major_ver: Major version of Data Path Resource Container API + * @minor_ver: Minor version of Data Path Resource Container API + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION, + cmd_flags, 0); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); + + return 0; +} + +/** + * dprc_get_container_id - Get container ID associated with a given portal. + * @mc_io: Pointer to Mc portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @container_id: Requested container id + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_container_id(struct fsl_mc_io *mc_io, + u32 cmd_flags, + int *container_id) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, + cmd_flags, + 0); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + *container_id = (int)mc_cmd_read_object_id(&cmd); + + return 0; +} diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 4588202af035..f9fed6323b22 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -313,21 +313,6 @@ static int get_dprc_icid(struct fsl_mc_io *mc_io, return error; } -static int get_dprc_version(struct fsl_mc_io *mc_io, - int container_id, u16 *major, u16 *minor) -{ - struct dprc_attributes attr; - int error; - - error = get_dprc_attr(mc_io, container_id, &attr); - if (error == 0) { - *major = attr.version.major; - *minor = attr.version.minor; - } - - return error; -} - static int translate_mc_addr(struct fsl_mc_device *mc_dev, enum dprc_region_type mc_region_type, u64 mc_offset, phys_addr_t *phys_addr) @@ -789,7 +774,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) if (error < 0) goto error_cleanup_mc_io; - error = dpmng_get_container_id(mc_io, 0, &container_id); + error = dprc_get_container_id(mc_io, 0, &container_id); if (error < 0) { dev_err(&pdev->dev, "dpmng_get_container_id() failed: %d\n", error); @@ -797,8 +782,9 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) } memset(&obj_desc, 0, sizeof(struct dprc_obj_desc)); - error = get_dprc_version(mc_io, container_id, - &obj_desc.ver_major, &obj_desc.ver_minor); + error = dprc_get_api_version(mc_io, 0, + &obj_desc.ver_major, + &obj_desc.ver_minor); if (error < 0) goto error_cleanup_mc_io; diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index e47bd2375ed7..4d82802b384d 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -67,7 +67,7 @@ static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd) struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; u16 cmd_id = le16_to_cpu(hdr->cmd_id); - return (cmd_id & MC_CMD_HDR_CMDID_MASK) >> MC_CMD_HDR_CMDID_SHIFT; + return cmd_id; } static int mc_status_to_error(enum mc_cmd_status status) @@ -200,7 +200,7 @@ static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, if (time_after_eq(jiffies, jiffies_until_timeout)) { dev_dbg(mc_io->dev, - "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", + "MC command timed out (portal: %#llx, dprc handle: %#x, command: %#x)\n", mc_io->portal_phys_addr, (unsigned int)mc_cmd_hdr_read_token(cmd), (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); @@ -240,7 +240,7 @@ static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; if (timeout_usecs == 0) { dev_dbg(mc_io->dev, - "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", + "MC command timed out (portal: %#llx, dprc handle: %#x, command: %#x)\n", mc_io->portal_phys_addr, (unsigned int)mc_cmd_hdr_read_token(cmd), (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); @@ -294,7 +294,7 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) if (status != MC_CMD_STATUS_OK) { dev_dbg(mc_io->dev, - "MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n", + "MC command failed: portal: %#llx, dprc handle: %#x, command: %#x, status: %s (%#x)\n", mc_io->portal_phys_addr, (unsigned int)mc_cmd_hdr_read_token(cmd), (unsigned int)mc_cmd_hdr_read_cmdid(cmd), diff --git a/drivers/staging/fsl-mc/include/dpbp.h b/drivers/staging/fsl-mc/include/dpbp.h index 550b5e117044..bf34b1e0e730 100644 --- a/drivers/staging/fsl-mc/include/dpbp.h +++ b/drivers/staging/fsl-mc/include/dpbp.h @@ -58,13 +58,15 @@ struct dpbp_cfg { }; int dpbp_create(struct fsl_mc_io *mc_io, + u16 dprc_token, u32 cmd_flags, const struct dpbp_cfg *cfg, - u16 *token); + u32 *obj_id); int dpbp_destroy(struct fsl_mc_io *mc_io, + u16 dprc_token, u32 cmd_flags, - u16 token); + u32 obj_id); int dpbp_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, @@ -147,21 +149,11 @@ int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, /** * struct dpbp_attr - Structure representing DPBP attributes * @id: DPBP object ID - * @version: DPBP version * @bpid: Hardware buffer pool ID; should be used as an argument in * acquire/release operations on buffers */ struct dpbp_attr { int id; - /** - * struct version - Structure representing DPBP version - * @major: DPBP major version - * @minor: DPBP minor version - */ - struct { - u16 major; - u16 minor; - } version; u16 bpid; }; @@ -217,6 +209,11 @@ int dpbp_get_notifications(struct fsl_mc_io *mc_io, u16 token, struct dpbp_notification_cfg *cfg); +int dpbp_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver); + /** @} */ #endif /* __FSL_DPBP_H */ diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index 6365159c0424..f9ea769ccfab 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -239,22 +239,12 @@ int dprc_clear_irq_status(struct fsl_mc_io *mc_io, * @icid: Container's ICID * @portal_id: Container's portal ID * @options: Container's options as set at container's creation - * @version: DPRC version */ struct dprc_attributes { int container_id; u16 icid; int portal_id; u64 options; - /** - * struct version - DPRC version - * @major: DPRC major version - * @minor: DPRC minor version - */ - struct { - u16 major; - u16 minor; - } version; }; int dprc_get_attributes(struct fsl_mc_io *mc_io, @@ -551,5 +541,14 @@ int dprc_get_connection(struct fsl_mc_io *mc_io, struct dprc_endpoint *endpoint2, int *state); +int dprc_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver); + +int dprc_get_container_id(struct fsl_mc_io *mc_io, + u32 cmd_flags, + int *container_id); + #endif /* _FSL_DPRC_H */ diff --git a/drivers/staging/fsl-mc/include/mc-cmd.h b/drivers/staging/fsl-mc/include/mc-cmd.h index f33ad1718130..2e08aa31b084 100644 --- a/drivers/staging/fsl-mc/include/mc-cmd.h +++ b/drivers/staging/fsl-mc/include/mc-cmd.h @@ -49,6 +49,15 @@ struct mc_command { u64 params[MC_CMD_NUM_OF_PARAMS]; }; +struct mc_rsp_create { + __le32 object_id; +}; + +struct mc_rsp_api_ver { + __le16 major_ver; + __le16 minor_ver; +}; + enum mc_cmd_status { MC_CMD_STATUS_OK = 0x0, /* Completed successfully */ MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */ @@ -73,11 +82,6 @@ enum mc_cmd_status { /* Command completion flag */ #define MC_CMD_FLAG_INTR_DIS 0x01 -#define MC_CMD_HDR_CMDID_MASK 0xFFF0 -#define MC_CMD_HDR_CMDID_SHIFT 4 -#define MC_CMD_HDR_TOKEN_MASK 0xFFC0 -#define MC_CMD_HDR_TOKEN_SHIFT 6 - static inline u64 mc_encode_cmd_header(u16 cmd_id, u32 cmd_flags, u16 token) @@ -85,10 +89,8 @@ static inline u64 mc_encode_cmd_header(u16 cmd_id, u64 header = 0; struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header; - hdr->cmd_id = cpu_to_le16((cmd_id << MC_CMD_HDR_CMDID_SHIFT) & - MC_CMD_HDR_CMDID_MASK); - hdr->token = cpu_to_le16((token << MC_CMD_HDR_TOKEN_SHIFT) & - MC_CMD_HDR_TOKEN_MASK); + hdr->cmd_id = cpu_to_le16(cmd_id); + hdr->token = cpu_to_le16(token); hdr->status = MC_CMD_STATUS_READY; if (cmd_flags & MC_CMD_FLAG_PRI) hdr->flags_hw = MC_CMD_FLAG_PRI; @@ -103,7 +105,26 @@ static inline u16 mc_cmd_hdr_read_token(struct mc_command *cmd) struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; u16 token = le16_to_cpu(hdr->token); - return (token & MC_CMD_HDR_TOKEN_MASK) >> MC_CMD_HDR_TOKEN_SHIFT; + return token; +} + +static inline u32 mc_cmd_read_object_id(struct mc_command *cmd) +{ + struct mc_rsp_create *rsp_params; + + rsp_params = (struct mc_rsp_create *)cmd->params; + return le32_to_cpu(rsp_params->object_id); +} + +static inline void mc_cmd_read_api_version(struct mc_command *cmd, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_rsp_api_ver *rsp_params; + + rsp_params = (struct mc_rsp_api_ver *)cmd->params; + *major_ver = le16_to_cpu(rsp_params->major_ver); + *minor_ver = le16_to_cpu(rsp_params->minor_ver); } #endif /* __FSL_MC_CMD_H */ -- cgit v1.2.3 From df86d641db7659ad29394df71e7ea286beec4380 Mon Sep 17 00:00:00 2001 From: Jiong Du Date: Tue, 25 Oct 2016 19:40:46 +0800 Subject: staging: ks7010: fix spacing errors Fixes checkpatch errors: spacing errors Signed-off-by: Jiong Du Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/michael_mic.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c index 78ae2b8fb7f3..fadc5636c148 100644 --- a/drivers/staging/ks7010/michael_mic.c +++ b/drivers/staging/ks7010/michael_mic.c @@ -14,10 +14,10 @@ #include "michael_mic.h" // Rotation functions on 32 bit values -#define ROL32( A, n ) ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) -#define ROR32( A, n ) ROL32( (A), 32-(n) ) +#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) +#define ROR32(A, n) ROL32((A), 32-(n)) // Convert from Byte[] to UInt32 in a portable way -#define getUInt32( A, B ) (uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24) +#define getUInt32(A, B) (uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24) // Convert from UInt32 to Byte[] in a portable way #define putUInt32(A, B, C) \ @@ -48,16 +48,16 @@ void MichaelInitializeFunction(struct michel_mic_t *Mic, uint8_t *key) } #define MichaelBlockFunction(L, R) \ -do{ \ - R ^= ROL32( L, 17 ); \ +do { \ + R ^= ROL32(L, 17); \ L += R; \ R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8); \ L += R; \ - R ^= ROL32( L, 3 ); \ + R ^= ROL32(L, 3); \ L += R; \ - R ^= ROR32( L, 2 ); \ + R ^= ROR32(L, 2); \ L += R; \ -}while(0) +} while (0) static void MichaelAppend(struct michel_mic_t *Mic, uint8_t *src, int nBytes) -- cgit v1.2.3 From 84b8ae9fd5981884dbdbdeda9ef5efd16ade5ddc Mon Sep 17 00:00:00 2001 From: Jiong Du Date: Tue, 25 Oct 2016 19:40:47 +0800 Subject: staging: ks7010: fix complex macro error Fixes checkpatch error: Macros with complex values should be enclosed in parentheses Signed-off-by: Jiong Du Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/michael_mic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c index fadc5636c148..09202adf399f 100644 --- a/drivers/staging/ks7010/michael_mic.c +++ b/drivers/staging/ks7010/michael_mic.c @@ -17,7 +17,7 @@ #define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) #define ROR32(A, n) ROL32((A), 32-(n)) // Convert from Byte[] to UInt32 in a portable way -#define getUInt32(A, B) (uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24) +#define getUInt32(A, B) ((uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24)) // Convert from UInt32 to Byte[] in a portable way #define putUInt32(A, B, C) \ -- cgit v1.2.3 From 5906d33c5fd6590f56b236b85349079b7665416f Mon Sep 17 00:00:00 2001 From: Jiong Du Date: Tue, 25 Oct 2016 19:40:48 +0800 Subject: staging: ks7010: remove space before tab Fixes checkpatch warning: space before tabs Signed-off-by: Jiong Du Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/michael_mic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c index 09202adf399f..50e158fc0159 100644 --- a/drivers/staging/ks7010/michael_mic.c +++ b/drivers/staging/ks7010/michael_mic.c @@ -14,10 +14,10 @@ #include "michael_mic.h" // Rotation functions on 32 bit values -#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) -#define ROR32(A, n) ROL32((A), 32-(n)) +#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) +#define ROR32(A, n) ROL32((A), 32-(n)) // Convert from Byte[] to UInt32 in a portable way -#define getUInt32(A, B) ((uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24)) +#define getUInt32(A, B) ((uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24)) // Convert from UInt32 to Byte[] in a portable way #define putUInt32(A, B, C) \ -- cgit v1.2.3 From 091a3d58f099e0918964d577e647fef41f1efa7b Mon Sep 17 00:00:00 2001 From: Jiong Du Date: Tue, 25 Oct 2016 19:40:49 +0800 Subject: staging: ks7010: split long line Fixes checkpatch warning: line over 80 characters Signed-off-by: Jiong Du Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/michael_mic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c index 50e158fc0159..5f3c1496db94 100644 --- a/drivers/staging/ks7010/michael_mic.c +++ b/drivers/staging/ks7010/michael_mic.c @@ -17,7 +17,8 @@ #define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) #define ROR32(A, n) ROL32((A), 32-(n)) // Convert from Byte[] to UInt32 in a portable way -#define getUInt32(A, B) ((uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24)) +#define getUInt32(A, B) ((uint32_t)(A[B+0] << 0) \ + + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24)) // Convert from UInt32 to Byte[] in a portable way #define putUInt32(A, B, C) \ -- cgit v1.2.3 From c4b370efc7fba6a489eda2cafd41109acbce81fb Mon Sep 17 00:00:00 2001 From: Jiong Du Date: Tue, 25 Oct 2016 19:40:50 +0800 Subject: staging: ks7010: add a blank line after declarations Fixes checkpatch warning: Missing a blank line after declarations Signed-off-by: Jiong Du Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/michael_mic.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c index 5f3c1496db94..f1064c1f6056 100644 --- a/drivers/staging/ks7010/michael_mic.c +++ b/drivers/staging/ks7010/michael_mic.c @@ -64,6 +64,7 @@ static void MichaelAppend(struct michel_mic_t *Mic, uint8_t *src, int nBytes) { int addlen; + if (Mic->nBytesInM) { addlen = 4 - Mic->nBytesInM; if (addlen > nBytes) @@ -98,6 +99,7 @@ static void MichaelGetMIC(struct michel_mic_t *Mic, uint8_t *dst) { uint8_t *data = Mic->M; + switch (Mic->nBytesInM) { case 0: Mic->L ^= 0x5a; -- cgit v1.2.3 From cf9caf1929882b66922aee698e99e6c8f357bee5 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Tue, 25 Oct 2016 19:23:27 -0700 Subject: staging: vc04_services: Replace dmac_map_area with dmac_map_sg The original arm implementation uses dmac_map_area which is not portable. Replace it with an architecture neutral version which uses dma_map_sg. As you can see that for larger page sizes, the dma_map_sg implementation is faster then the original unportable dma_map_area implementation. Test dmac_map_area dma_map_page dma_map_sg vchiq_test -b 4 10000 51us/iter 76us/iter 76us vchiq_test -b 8 10000 70us/iter 82us/iter 91us vchiq_test -b 16 10000 94us/iter 118us/iter 121us vchiq_test -b 32 10000 146us/iter 173us/iter 187us vchiq_test -b 64 10000 263us/iter 328us/iter 299us vchiq_test -b 128 10000 529us/iter 631us/iter 595us vchiq_test -b 256 10000 2285us/iter 2275us/iter 2001us vchiq_test -b 512 10000 4372us/iter 4616us/iter 4123us For message sizes >= 64KB, dma_map_sg is faster then dma_map_page. For message size >= 256KB, the dma_map_sg is the fastest implementation. "Normal" messages sizes should be about 1MB which is beyond the length that this change shows a speed increase. This is v2 of the patch which includes extra WARN_ONs and incorporates feedback from Eric Anholt . Signed-off-by: Michael Zoran Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../interface/vchiq_arm/vchiq_2835_arm.c | 152 +++++++++++++-------- 1 file changed, 93 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 32d12e6e1b4f..a5afcc5fd03b 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -45,13 +45,8 @@ #include #include -#define dmac_map_area __glue(_CACHE,_dma_map_area) -#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) -#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) - #include "vchiq_arm.h" #include "vchiq_2835.h" #include "vchiq_connected.h" @@ -73,7 +68,7 @@ static unsigned int g_fragments_size; static char *g_fragments_base; static char *g_free_fragments; static struct semaphore g_free_fragments_sema; -static unsigned long g_virt_to_bus_offset; +static struct device *g_dev; extern int vchiq_arm_log_level; @@ -84,10 +79,11 @@ vchiq_doorbell_irq(int irq, void *dev_id); static int create_pagelist(char __user *buf, size_t count, unsigned short type, - struct task_struct *task, PAGELIST_T ** ppagelist); + struct task_struct *task, PAGELIST_T **ppagelist, + dma_addr_t *dma_addr); static void -free_pagelist(PAGELIST_T *pagelist, int actual); +free_pagelist(dma_addr_t dma_addr, PAGELIST_T *pagelist, int actual); int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) { @@ -101,8 +97,6 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) int slot_mem_size, frag_mem_size; int err, irq, i; - g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); - (void)of_property_read_u32(dev->of_node, "cache-line-size", &g_cache_line_size); g_fragments_size = 2 * g_cache_line_size; @@ -118,7 +112,7 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) return -ENOMEM; } - WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); + WARN_ON(((unsigned long)slot_mem & (PAGE_SIZE - 1)) != 0); vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); if (!vchiq_slot_zero) @@ -170,6 +164,7 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) return err ? : -ENXIO; } + g_dev = dev; vchiq_log_info(vchiq_arm_log_level, "vchiq_init - done (slots %pK, phys %pad)", vchiq_slot_zero, &slot_phys); @@ -233,6 +228,7 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, { PAGELIST_T *pagelist; int ret; + dma_addr_t dma_addr; WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID); @@ -241,12 +237,14 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, ? PAGELIST_READ : PAGELIST_WRITE, current, - &pagelist); + &pagelist, + &dma_addr); + if (ret != 0) return VCHIQ_ERROR; bulk->handle = memhandle; - bulk->data = VCHIQ_ARM_ADDRESS(pagelist); + bulk->data = (void *)(unsigned long)dma_addr; /* Store the pagelist address in remote_data, which isn't used by the slave. */ @@ -259,7 +257,8 @@ void vchiq_complete_bulk(VCHIQ_BULK_T *bulk) { if (bulk && bulk->remote_data && bulk->actual) - free_pagelist((PAGELIST_T *)bulk->remote_data, bulk->actual); + free_pagelist((dma_addr_t)(unsigned long)bulk->data, + (PAGELIST_T *)bulk->remote_data, bulk->actual); } void @@ -353,38 +352,44 @@ vchiq_doorbell_irq(int irq, void *dev_id) ** obscuring the new data underneath. We can solve this by transferring the ** partial cache lines separately, and allowing the ARM to copy into the ** cached area. - -** N.B. This implementation plays slightly fast and loose with the Linux -** driver programming rules, e.g. its use of dmac_map_area instead of -** dma_map_single, but it isn't a multi-platform driver and it benefits -** from increased speed as a result. */ static int create_pagelist(char __user *buf, size_t count, unsigned short type, - struct task_struct *task, PAGELIST_T ** ppagelist) + struct task_struct *task, PAGELIST_T **ppagelist, + dma_addr_t *dma_addr) { PAGELIST_T *pagelist; struct page **pages; - unsigned long *addrs; - unsigned int num_pages, offset, i; - char *addr, *base_addr, *next_addr; - int run, addridx, actual_pages; + u32 *addrs; + unsigned int num_pages, offset, i, k; + int actual_pages; unsigned long *need_release; + size_t pagelist_size; + struct scatterlist *scatterlist, *sg; + int dma_buffers; + int dir; - offset = (unsigned int)buf & (PAGE_SIZE - 1); + offset = ((unsigned int)(unsigned long)buf & (PAGE_SIZE - 1)); num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE; + pagelist_size = sizeof(PAGELIST_T) + + (num_pages * sizeof(unsigned long)) + + sizeof(unsigned long) + + (num_pages * sizeof(pages[0]) + + (num_pages * sizeof(struct scatterlist))); + *ppagelist = NULL; + dir = (type == PAGELIST_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + /* Allocate enough storage to hold the page pointers and the page ** list */ - pagelist = kmalloc(sizeof(PAGELIST_T) + - (num_pages * sizeof(unsigned long)) + - sizeof(unsigned long) + - (num_pages * sizeof(pages[0])), - GFP_KERNEL); + pagelist = dma_zalloc_coherent(g_dev, + pagelist_size, + dma_addr, + GFP_KERNEL); vchiq_log_trace(vchiq_arm_log_level, "create_pagelist - %pK", pagelist); @@ -394,10 +399,9 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, addrs = pagelist->addrs; need_release = (unsigned long *)(addrs + num_pages); pages = (struct page **)(addrs + num_pages + 1); + scatterlist = (struct scatterlist *)(pages + num_pages); if (is_vmalloc_addr(buf)) { - int dir = (type == PAGELIST_WRITE) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE; unsigned long length = count; unsigned int off = offset; @@ -410,7 +414,6 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, if (bytes > length) bytes = length; pages[actual_pages] = pg; - dmac_map_area(page_address(pg) + off, bytes, dir); length -= bytes; off = 0; } @@ -438,7 +441,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, actual_pages--; put_page(pages[actual_pages]); } - kfree(pagelist); + dma_free_coherent(g_dev, pagelist_size, + pagelist, *dma_addr); if (actual_pages == 0) actual_pages = -ENOMEM; return actual_pages; @@ -450,30 +454,44 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, pagelist->type = type; pagelist->offset = offset; - /* Group the pages into runs of contiguous pages */ + for (i = 0; i < num_pages; i++) + sg_set_page(scatterlist + i, pages[i], PAGE_SIZE, 0); + + dma_buffers = dma_map_sg(g_dev, + scatterlist, + num_pages, + dir); - base_addr = VCHIQ_ARM_ADDRESS(page_address(pages[0])); - next_addr = base_addr + PAGE_SIZE; - addridx = 0; - run = 0; + if (dma_buffers == 0) { + dma_free_coherent(g_dev, pagelist_size, + pagelist, *dma_addr); - for (i = 1; i < num_pages; i++) { - addr = VCHIQ_ARM_ADDRESS(page_address(pages[i])); - if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) { - next_addr += PAGE_SIZE; - run++; + return -EINTR; + } + + /* Combine adjacent blocks for performance */ + k = 0; + for_each_sg(scatterlist, sg, dma_buffers, i) { + u32 len = sg_dma_len(sg); + u32 addr = sg_dma_address(sg); + + /* Note: addrs is the address + page_count - 1 + * The firmware expects the block to be page + * aligned and a multiple of the page size + */ + WARN_ON(len == 0); + WARN_ON(len & ~PAGE_MASK); + WARN_ON(addr & ~PAGE_MASK); + if (k > 0 && + ((addrs[k - 1] & PAGE_MASK) | + ((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT) + == addr) { + addrs[k - 1] += (len >> PAGE_SHIFT); } else { - addrs[addridx] = (unsigned long)base_addr + run; - addridx++; - base_addr = addr; - next_addr = addr + PAGE_SIZE; - run = 0; + addrs[k++] = addr | ((len >> PAGE_SHIFT) - 1); } } - addrs[addridx] = (unsigned long)base_addr + run; - addridx++; - /* Partial cache lines (fragments) require special measures */ if ((type == PAGELIST_READ) && ((pagelist->offset & (g_cache_line_size - 1)) || @@ -482,7 +500,10 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, char *fragments; if (down_interruptible(&g_free_fragments_sema) != 0) { - kfree(pagelist); + dma_unmap_sg(g_dev, scatterlist, num_pages, + DMA_BIDIRECTIONAL); + dma_free_coherent(g_dev, pagelist_size, + pagelist, *dma_addr); return -EINTR; } @@ -497,29 +518,42 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, (fragments - g_fragments_base) / g_fragments_size; } - dmac_flush_range(pagelist, addrs + num_pages); - *ppagelist = pagelist; return 0; } static void -free_pagelist(PAGELIST_T *pagelist, int actual) +free_pagelist(dma_addr_t dma_addr, PAGELIST_T *pagelist, int actual) { unsigned long *need_release; struct page **pages; unsigned int num_pages, i; + size_t pagelist_size; + struct scatterlist *scatterlist; + int dir; vchiq_log_trace(vchiq_arm_log_level, "free_pagelist - %pK, %d", pagelist, actual); + dir = (pagelist->type == PAGELIST_WRITE) ? DMA_TO_DEVICE : + DMA_FROM_DEVICE; + num_pages = (pagelist->length + pagelist->offset + PAGE_SIZE - 1) / PAGE_SIZE; + pagelist_size = sizeof(PAGELIST_T) + + (num_pages * sizeof(unsigned long)) + + sizeof(unsigned long) + + (num_pages * sizeof(pages[0]) + + (num_pages * sizeof(struct scatterlist))); + need_release = (unsigned long *)(pagelist->addrs + num_pages); pages = (struct page **)(pagelist->addrs + num_pages + 1); + scatterlist = (struct scatterlist *)(pages + num_pages); + + dma_unmap_sg(g_dev, scatterlist, num_pages, dir); /* Deal with any partial cache lines (fragments) */ if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) { @@ -569,8 +603,7 @@ free_pagelist(PAGELIST_T *pagelist, int actual) if (bytes > length) bytes = length; - dmac_unmap_area(page_address(pg) + offset, - bytes, DMA_FROM_DEVICE); + length -= bytes; offset = 0; set_page_dirty(pg); @@ -579,5 +612,6 @@ free_pagelist(PAGELIST_T *pagelist, int actual) } } - kfree(pagelist); + dma_free_coherent(g_dev, pagelist_size, + pagelist, dma_addr); } -- cgit v1.2.3 From 57499d136e351ccd8143d02c6a1f6261b1775a69 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Wed, 26 Oct 2016 00:03:43 -0200 Subject: staging: sm750fb: Refine the code and remove unused code. Every call to the function waitNextVerticalSync() used the macro primaryWaitVerticalSync(), so the macro was removed and the function waitNextVerticalSync() renamed to primary_wait_vertical_sync(). With this change, an unnecessary 'if' statement was removed together with the lines within the 'else' statement, because it was never satisfied. The modified function was refined to better match the Kernel coding style. Signed-off-by: Elise Lennion Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 71 ++++++++++---------------------- 1 file changed, 21 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index aea97361d937..0f3a875b0ef8 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -4,8 +4,6 @@ #include "ddk750_power.h" #include "ddk750_dvi.h" -#define primaryWaitVerticalSync(delay) waitNextVerticalSync(0, delay) - static void setDisplayControl(int ctrl, int disp_state) { /* state != 0 means turn on both timing & plane en_bit */ @@ -61,55 +59,28 @@ static void setDisplayControl(int ctrl, int disp_state) } } -static void waitNextVerticalSync(int ctrl, int delay) +static void primary_wait_vertical_sync(int delay) { unsigned int status; - if (!ctrl) { - /* primary controller */ + /* + * Do not wait when the Primary PLL is off or display control is + * already off. This will prevent the software to wait forever. + */ + if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || + !(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) + return; - /* - * Do not wait when the Primary PLL is off or display control is - * already off. This will prevent the software to wait forever. - */ - if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || - !(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { - return; - } - - while (delay-- > 0) { - /* Wait for end of vsync. */ - do { - status = PEEK32(SYSTEM_CTRL); - } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); - - /* Wait for start of vsync. */ - do { - status = PEEK32(SYSTEM_CTRL); - } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); - } + while (delay-- > 0) { + /* Wait for end of vsync. */ + do { + status = PEEK32(SYSTEM_CTRL); + } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); - } else { - /* - * Do not wait when the Primary PLL is off or display control is - * already off. This will prevent the software to wait forever. - */ - if (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) || - !(PEEK32(CRT_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { - return; - } - - while (delay-- > 0) { - /* Wait for end of vsync. */ - do { - status = PEEK32(SYSTEM_CTRL); - } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); - - /* Wait for start of vsync. */ - do { - status = PEEK32(SYSTEM_CTRL); - } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); - } + /* Wait for start of vsync. */ + do { + status = PEEK32(SYSTEM_CTRL); + } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); } } @@ -121,22 +92,22 @@ static void swPanelPowerSequence(int disp, int delay) reg = PEEK32(PANEL_DISPLAY_CTRL); reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); POKE32(PANEL_DISPLAY_CTRL, reg); - primaryWaitVerticalSync(delay); + primary_wait_vertical_sync(delay); reg = PEEK32(PANEL_DISPLAY_CTRL); reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0); POKE32(PANEL_DISPLAY_CTRL, reg); - primaryWaitVerticalSync(delay); + primary_wait_vertical_sync(delay); reg = PEEK32(PANEL_DISPLAY_CTRL); reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0); POKE32(PANEL_DISPLAY_CTRL, reg); - primaryWaitVerticalSync(delay); + primary_wait_vertical_sync(delay); reg = PEEK32(PANEL_DISPLAY_CTRL); reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); POKE32(PANEL_DISPLAY_CTRL, reg); - primaryWaitVerticalSync(delay); + primary_wait_vertical_sync(delay); } void ddk750_setLogicalDispOut(disp_output_t output) -- cgit v1.2.3 From 8f8a34026ec5fcf0eeabbe2535bd90dec5da64e0 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Wed, 26 Oct 2016 18:34:17 +0000 Subject: staging: vchiq_arm: add MODULE_DESCRIPTION This patch adds the missing module description for the driver. Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index a89375d56fa0..119ca145dbc4 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2892,4 +2892,5 @@ static struct platform_driver vchiq_driver = { module_platform_driver(vchiq_driver); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Videocore VCHIQ driver"); MODULE_AUTHOR("Broadcom Corporation"); -- cgit v1.2.3 From bea845af8d877310bbbacd54e8252566019d5a5e Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Wed, 26 Oct 2016 18:34:18 +0000 Subject: staging: vchiq_arm: Make DT firmware node mandatory In Linux Mainline there wasn't a chance to boot the RPi without DT. So we can make the firmware node mandatory. Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 119ca145dbc4..ce3ba37fbeb0 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2794,12 +2794,11 @@ static int vchiq_probe(struct platform_device *pdev) void *ptr_err; fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -/* Remove comment when booting without Device Tree is no longer supported if (!fw_node) { dev_err(&pdev->dev, "Missing firmware node\n"); return -ENOENT; } -*/ + fw = rpi_firmware_get(fw_node); if (!fw) return -EPROBE_DEFER; -- cgit v1.2.3 From 6e474d8e3981a63b6e1cf11b838014ed52499804 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Wed, 26 Oct 2016 18:34:19 +0000 Subject: staging: vchiq_shim: avoid code duplication Rearrange the polling loops in order to avoid code duplication. Btw we fix the style of the comments. Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/interface/vchiq_arm/vchiq_shim.c | 56 ++++++++++++---------- 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c index 49f9d6a8f78d..7694627b925c 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c @@ -172,15 +172,18 @@ int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); - status = vchiq_queue_message(service->handle, &element, 1); + while (1) { + status = vchiq_queue_message(service->handle, &element, 1); + + /* + * vchiq_queue_message() may return VCHIQ_RETRY, so we need to + * implement a retry mechanism since this function is supposed + * to block until queued + */ + if (status != VCHIQ_RETRY) + break; - /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to - ** implement a retry mechanism since this function is supposed - ** to block until queued - */ - while (status == VCHIQ_RETRY) { msleep(1); - status = vchiq_queue_message(service->handle, &element, 1); } return vchiq_status_to_vchi(status); @@ -229,17 +232,18 @@ int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, return vchiq_status_to_vchi(VCHIQ_ERROR); } - status = vchiq_bulk_receive(service->handle, data_dst, data_size, - bulk_handle, mode); - - /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to - ** implement a retry mechanism since this function is supposed - ** to block until queued - */ - while (status == VCHIQ_RETRY) { - msleep(1); + while (1) { status = vchiq_bulk_receive(service->handle, data_dst, data_size, bulk_handle, mode); + /* + * vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to + * implement a retry mechanism since this function is supposed + * to block until queued + */ + if (status != VCHIQ_RETRY) + break; + + msleep(1); } return vchiq_status_to_vchi(status); @@ -289,17 +293,19 @@ int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, return vchiq_status_to_vchi(VCHIQ_ERROR); } - status = vchiq_bulk_transmit(service->handle, data_src, data_size, - bulk_handle, mode); - - /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to - ** implement a retry mechanism since this function is supposed - ** to block until queued - */ - while (status == VCHIQ_RETRY) { - msleep(1); + while (1) { status = vchiq_bulk_transmit(service->handle, data_src, data_size, bulk_handle, mode); + + /* + * vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to + * implement a retry mechanism since this function is supposed + * to block until queued + */ + if (status != VCHIQ_RETRY) + break; + + msleep(1); } return vchiq_status_to_vchi(status); -- cgit v1.2.3 From 801b1aa002d377c1363d671df09120f11266832c Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Wed, 26 Oct 2016 18:34:20 +0000 Subject: staging: vc04_services: fix CamelCase This fixes the CamelCase of some variables. Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/interface/vchiq_arm/vchiq_core.c | 26 +++++++++++----------- .../interface/vchiq_arm/vchiq_kern_lib.c | 4 ++-- .../interface/vchiq_arm/vchiq_memdrv.h | 12 +++++----- 3 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index c58f5cb16318..f3e10004a368 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -3827,26 +3827,26 @@ VCHIQ_STATUS_T vchiq_send_remote_use_active(VCHIQ_STATE_T *state) return status; } -void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, - size_t numBytes) +void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *void_mem, + size_t num_bytes) { - const uint8_t *mem = (const uint8_t *)voidMem; + const uint8_t *mem = (const uint8_t *)void_mem; size_t offset; - char lineBuf[100]; + char line_buf[100]; char *s; - while (numBytes > 0) { - s = lineBuf; + while (num_bytes > 0) { + s = line_buf; for (offset = 0; offset < 16; offset++) { - if (offset < numBytes) + if (offset < num_bytes) s += snprintf(s, 4, "%02x ", mem[offset]); else s += snprintf(s, 4, " "); } for (offset = 0; offset < 16; offset++) { - if (offset < numBytes) { + if (offset < num_bytes) { uint8_t ch = mem[offset]; if ((ch < ' ') || (ch > '~')) @@ -3858,16 +3858,16 @@ void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, if ((label != NULL) && (*label != '\0')) vchiq_log_trace(VCHIQ_LOG_TRACE, - "%s: %08x: %s", label, addr, lineBuf); + "%s: %08x: %s", label, addr, line_buf); else vchiq_log_trace(VCHIQ_LOG_TRACE, - "%08x: %s", addr, lineBuf); + "%08x: %s", addr, line_buf); addr += 16; mem += 16; - if (numBytes > 16) - numBytes -= 16; + if (num_bytes > 16) + num_bytes -= 16; else - numBytes = 0; + num_bytes = 0; } } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c index 563642c8664f..14bd2857e462 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c @@ -70,7 +70,7 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, * ***************************************************************************/ #define VCHIQ_INIT_RETRIES 10 -VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut) +VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out) { VCHIQ_STATUS_T status = VCHIQ_ERROR; VCHIQ_STATE_T *state; @@ -108,7 +108,7 @@ VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut) mutex_init(&instance->bulk_waiter_list_mutex); INIT_LIST_HEAD(&instance->bulk_waiter_list); - *instanceOut = instance; + *instance_out = instance; status = VCHIQ_SUCCESS; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h index d02e7764bd0d..dd43458f306f 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h @@ -42,13 +42,13 @@ /* ---- Constants and Types ---------------------------------------------- */ typedef struct { - void *armSharedMemVirt; - dma_addr_t armSharedMemPhys; - size_t armSharedMemSize; + void *arm_shared_mem_virt; + dma_addr_t arm_shared_mem_phys; + size_t arm_shared_mem_size; - void *vcSharedMemVirt; - dma_addr_t vcSharedMemPhys; - size_t vcSharedMemSize; + void *vc_shared_mem_virt; + dma_addr_t vc_shared_mem_phys; + size_t vc_shared_mem_size; } VCHIQ_SHARED_MEM_INFO_T; /* ---- Variable Externs ------------------------------------------------- */ -- cgit v1.2.3 From 32774ef3e4bb339cec19655946996a8c50063be4 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Wed, 26 Oct 2016 18:34:21 +0000 Subject: staging: vc04_services: use bcm2835 consequently The naming bcm2708 is used only in the vendor kernel, so better replace it with bcm2835 which is used in mainline in order to avoid any confusion. Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Makefile | 2 +- drivers/staging/vc04_services/Kconfig | 4 ++-- drivers/staging/vc04_services/Makefile | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 2fa9745db614..323753216999 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -41,4 +41,4 @@ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_ISDN_I4L) += i4l/ obj-$(CONFIG_KS7010) += ks7010/ obj-$(CONFIG_GREYBUS) += greybus/ -obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/ +obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig index 9676fb29075a..f839a542a2ff 100644 --- a/drivers/staging/vc04_services/Kconfig +++ b/drivers/staging/vc04_services/Kconfig @@ -1,9 +1,9 @@ -config BCM2708_VCHIQ +config BCM2835_VCHIQ tristate "Videocore VCHIQ" depends on RASPBERRYPI_FIRMWARE && BROKEN default y help Kernel to VideoCore communication interface for the - BCM2708 family of products. + BCM2835 family of products. Defaults to Y when the Broadcom Videocore services are included in the build, N otherwise. diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile index 90ab4781df2c..1a9e742ee40d 100644 --- a/drivers/staging/vc04_services/Makefile +++ b/drivers/staging/vc04_services/Makefile @@ -1,4 +1,4 @@ -obj-$(CONFIG_BCM2708_VCHIQ) += vchiq.o +obj-$(CONFIG_BCM2835_VCHIQ) += vchiq.o vchiq-objs := \ interface/vchiq_arm/vchiq_core.o \ -- cgit v1.2.3 From ab28f51c77cd46189aa5726c98d5153052567a3c Mon Sep 17 00:00:00 2001 From: Sergey Yanovich Date: Tue, 27 Sep 2016 18:23:16 +0200 Subject: serial: rewrite pxa2xx-uart to use 8250_core pxa2xx-uart was a separate uart platform driver. It was declaring the same device names and numbers as 8250 driver. As a result, it was impossible to use 8250 driver on PXA SoCs. Upon closer examination pxa2xx-uart turned out to be a clone of 8250_core driver. Workaround for Erratum #19 according to Marvel(R) PXA270M Processor Specification Update (April 19, 2010) is dropped. 8250_core reads from FIFO immediately after checking DR bit in LSR. The patch leaves the original SERIAL_PXA driver around. The original driver is just marked DEPRECATED in Kconfig and C source. When the original driver is considered safe to remove, no changes to SERIAL_8250 will be necessary. Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new and the original drivers are made mutually exclusive. Signed-off-by: Sergei Ianovich CC: Heikki Krogerus CC: James Cameron CC: Robert Jarzmik CC: Russell King Reviewed-by: Heikki Krogerus [rebased on v4.8] Tested-by: Robert Jarzmik Signed-off-by: Robert Jarzmik Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pxa.c | 177 +++++++++++++++++++++++++++++++++++++ drivers/tty/serial/8250/Kconfig | 10 +++ drivers/tty/serial/8250/Makefile | 1 + drivers/tty/serial/Kconfig | 17 +++- drivers/tty/serial/Makefile | 2 +- drivers/tty/serial/pxa.c | 4 +- 6 files changed, 207 insertions(+), 4 deletions(-) create mode 100644 drivers/tty/serial/8250/8250_pxa.c (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c new file mode 100644 index 000000000000..6a14df013754 --- /dev/null +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -0,0 +1,177 @@ +/* + * drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS + * Copyright: (C) 2013 Sergei Ianovich + * + * replaces drivers/serial/pxa.c by Nicolas Pitre + * Created: Feb 20, 2003 + * Copyright: (C) 2003 Monta Vista Software, Inc. + * + * Based on drivers/serial/8250.c by Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "8250.h" + +struct pxa8250_data { + int line; + struct clk *clk; +}; + +#ifdef CONFIG_PM +static int serial_pxa_suspend(struct device *dev) +{ + struct pxa8250_data *data = dev_get_drvdata(dev); + + serial8250_suspend_port(data->line); + + return 0; +} + +static int serial_pxa_resume(struct device *dev) +{ + struct pxa8250_data *data = dev_get_drvdata(dev); + + serial8250_resume_port(data->line); + + return 0; +} +#endif + +static const struct dev_pm_ops serial_pxa_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume) +}; + +static const struct of_device_id serial_pxa_dt_ids[] = { + { .compatible = "mrvl,pxa-uart", }, + { .compatible = "mrvl,mmp-uart", }, + {} +}; +MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids); + +/* Uart divisor latch write */ +static void serial_pxa_dl_write(struct uart_8250_port *up, int value) +{ + unsigned int dll; + + serial_out(up, UART_DLL, value & 0xff); + /* + * work around Erratum #74 according to Marvel(R) PXA270M Processor + * Specification Update (April 19, 2010) + */ + dll = serial_in(up, UART_DLL); + WARN_ON(dll != (value & 0xff)); + + serial_out(up, UART_DLM, value >> 8 & 0xff); +} + + +static void serial_pxa_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + struct pxa8250_data *data = port->private_data; + + if (!state) + clk_prepare_enable(data->clk); + else + clk_disable_unprepare(data->clk); +} + +static int serial_pxa_probe(struct platform_device *pdev) +{ + struct uart_8250_port uart = {}; + struct pxa8250_data *data; + struct resource *mmres, *irqres; + int ret; + + mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!mmres || !irqres) + return -ENODEV; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(data->clk)) + return PTR_ERR(data->clk); + + ret = clk_prepare(data->clk); + if (ret) + return ret; + + uart.port.type = PORT_XSCALE; + uart.port.iotype = UPIO_MEM32; + uart.port.mapbase = mmres->start; + uart.port.regshift = 2; + uart.port.irq = irqres->start; + uart.port.fifosize = 64; + uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST; + uart.port.dev = &pdev->dev; + uart.port.uartclk = clk_get_rate(data->clk); + uart.port.pm = serial_pxa_pm; + uart.port.private_data = data; + uart.dl_write = serial_pxa_dl_write; + + ret = serial8250_register_8250_port(&uart); + if (ret < 0) + goto err_clk; + + data->line = ret; + + platform_set_drvdata(pdev, data); + + return 0; + + err_clk: + clk_unprepare(data->clk); + return ret; +} + +static int serial_pxa_remove(struct platform_device *pdev) +{ + struct pxa8250_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); + + clk_unprepare(data->clk); + + return 0; +} + +static struct platform_driver serial_pxa_driver = { + .probe = serial_pxa_probe, + .remove = serial_pxa_remove, + + .driver = { + .name = "pxa2xx-uart", + .pm = &serial_pxa_pm_ops, + .of_match_table = serial_pxa_dt_ids, + }, +}; + +module_platform_driver(serial_pxa_driver); + +MODULE_AUTHOR("Sergei Ianovich"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pxa2xx-uart"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 899834776b36..0b8b6740ba43 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -439,6 +439,16 @@ config SERIAL_8250_MOXA This driver can also be built as a module. The module will be called 8250_moxa. If you want to do that, say M here. +config SERIAL_8250_PXA + tristate "PXA serial port support" + depends on SERIAL_8250 + depends on ARCH_PXA || ARCH_MMP + help + If you have a machine based on an Intel XScale PXA2xx CPU you can + enable its onboard serial ports by enabling this option. The option is + applicable to both devicetree and legacy boards, and early console is + part of its support. + config SERIAL_OF_PLATFORM tristate "Devicetree based probing for 8250 ports" depends on SERIAL_8250 && OF diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 276c6fb60337..850e721877a9 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o +obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index c7831407a882..f9c595ca2832 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -438,17 +438,27 @@ config SERIAL_MPSC_CONSOLE Say Y here if you want to support a serial console on a Marvell MPSC. config SERIAL_PXA - bool "PXA serial port support" + bool "PXA serial port support (DEPRECATED)" depends on ARCH_PXA || ARCH_MMP select SERIAL_CORE + select SERIAL_8250_PXA if SERIAL_8250=y + select SERIAL_PXA_NON8250 if !SERIAL_8250=y help If you have a machine based on an Intel XScale PXA2xx CPU you can enable its onboard serial ports by enabling this option. + Unless you have a specific need, you should use SERIAL_8250_PXA + instead of this. + +config SERIAL_PXA_NON8250 + bool + depends on !SERIAL_8250 + config SERIAL_PXA_CONSOLE - bool "Console on PXA serial port" + bool "Console on PXA serial port (DEPRECATED)" depends on SERIAL_PXA select SERIAL_CORE_CONSOLE + select SERIAL_8250_CONSOLE if SERIAL_8250=y help If you have enabled the serial port on the Intel XScale PXA CPU you can make it the console by answering Y to this option. @@ -460,6 +470,9 @@ config SERIAL_PXA_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) + Unless you have a specific need, you should use SERIAL_8250_PXA + and SERIAL_8250_CONSOLE instead of this. + config SERIAL_SA1100 bool "SA1100 serial port support" depends on ARCH_SA1100 diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 1278d376da50..1fa21ec616bd 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o -obj-$(CONFIG_SERIAL_PXA) += pxa.o +obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o obj-$(CONFIG_SERIAL_SA1100) += sa1100.o obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index cd9d9e878475..b9dd787cb561 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -925,7 +925,9 @@ static struct platform_driver serial_pxa_driver = { }, }; -static int __init serial_pxa_init(void) + +/* 8250 driver for PXA serial ports should be used */ +static int __deprecated __init serial_pxa_init(void) { int ret; -- cgit v1.2.3 From 1353ec3833360ffab479d17781493ead1d38a006 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 27 Oct 2016 13:48:32 +0100 Subject: drm/i915: Correct pipe fault reporting string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Newline somehow ended up in the middle of the line. Signed-off-by: Tvrtko Ursulin Reviewed-by: Ville Syrjälä Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1477572512-4030-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9111cfdf217a..88239e1b29e4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2503,7 +2503,7 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) fault_errors &= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; if (fault_errors) - DRM_ERROR("Fault errors on pipe %c\n: 0x%08x", + DRM_ERROR("Fault errors on pipe %c: 0x%08x\n", pipe_name(pipe), fault_errors); } -- cgit v1.2.3 From 10879ae5f12e9cab3c4e8e9504c1aaa8a033bde7 Mon Sep 17 00:00:00 2001 From: Aleksey Makarov Date: Tue, 4 Oct 2016 10:15:32 +0300 Subject: serial: pl011: add console matching function This patch adds function pl011_console_match() that implements method match of struct console. It allows to match consoles against data specified in a string, for example taken from command line or compiled by ACPI SPCR table handler. This patch was merged to tty-next but then reverted because of conflict with commit 46e36683f433 ("serial: earlycon: Extend earlycon command line option to support 64-bit addresses") Now it is fixed. Signed-off-by: Aleksey Makarov Reviewed-by: Peter Hurley Acked-by: Russell King Tested-by: Christopher Covington Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index e2c33b9528d8..c00ab22afe9e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2315,12 +2315,67 @@ static int __init pl011_console_setup(struct console *co, char *options) return uart_set_options(&uap->port, co, baud, parity, bits, flow); } +/** + * pl011_console_match - non-standard console matching + * @co: registering console + * @name: name from console command line + * @idx: index from console command line + * @options: ptr to option string from console command line + * + * Only attempts to match console command lines of the form: + * console=pl011,mmio|mmio32,[,] + * console=pl011,0x[,] + * This form is used to register an initial earlycon boot console and + * replace it with the amba_console at pl011 driver init. + * + * Performs console setup for a match (as required by interface) + * If no are specified, then assume the h/w is already setup. + * + * Returns 0 if console matches; otherwise non-zero to use default matching + */ +static int __init pl011_console_match(struct console *co, char *name, int idx, + char *options) +{ + unsigned char iotype; + resource_size_t addr; + int i; + + if (strcmp(name, "pl011") != 0) + return -ENODEV; + + if (uart_parse_earlycon(options, &iotype, &addr, &options)) + return -ENODEV; + + if (iotype != UPIO_MEM && iotype != UPIO_MEM32) + return -ENODEV; + + /* try to match the port specified on the command line */ + for (i = 0; i < ARRAY_SIZE(amba_ports); i++) { + struct uart_port *port; + + if (!amba_ports[i]) + continue; + + port = &amba_ports[i]->port; + + if (port->mapbase != addr) + continue; + + co->index = i; + port->cons = co; + return pl011_console_setup(co, options); + } + + return -ENODEV; +} + static struct uart_driver amba_reg; static struct console amba_console = { .name = "ttyAMA", .write = pl011_console_write, .device = uart_console_device, .setup = pl011_console_setup, + .match = pl011_console_match, .flags = CON_PRINTBUFFER, .index = -1, .data = &amba_reg, -- cgit v1.2.3 From 2a41bc2a2b0533afca11335ed7e636c62623d7c6 Mon Sep 17 00:00:00 2001 From: Nicolae Rosia Date: Tue, 4 Oct 2016 15:46:16 +0300 Subject: tty: serial: fsl_lpuart: add polled console functions This adds polling functions as used by kgdb. Signed-off-by: Nicolae Rosia Signed-off-by: Stefan Golinschi Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 66 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index de9d5107c00a..49d7526e2587 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -431,6 +431,67 @@ static void lpuart_flush_buffer(struct uart_port *port) } } +#if defined(CONFIG_CONSOLE_POLL) + +static int lpuart_poll_init(struct uart_port *port) +{ + struct lpuart_port *sport = container_of(port, + struct lpuart_port, port); + unsigned long flags; + unsigned char temp; + + sport->port.fifosize = 0; + + spin_lock_irqsave(&sport->port.lock, flags); + /* Disable Rx & Tx */ + writeb(0, sport->port.membase + UARTCR2); + + temp = readb(sport->port.membase + UARTPFIFO); + /* Enable Rx and Tx FIFO */ + writeb(temp | UARTPFIFO_RXFE | UARTPFIFO_TXFE, + sport->port.membase + UARTPFIFO); + + /* flush Tx and Rx FIFO */ + writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH, + sport->port.membase + UARTCFIFO); + + /* explicitly clear RDRF */ + if (readb(sport->port.membase + UARTSR1) & UARTSR1_RDRF) { + readb(sport->port.membase + UARTDR); + writeb(UARTSFIFO_RXUF, sport->port.membase + UARTSFIFO); + } + + writeb(0, sport->port.membase + UARTTWFIFO); + writeb(1, sport->port.membase + UARTRWFIFO); + + /* Enable Rx and Tx */ + writeb(UARTCR2_RE | UARTCR2_TE, sport->port.membase + UARTCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); + + return 0; +} + +static void lpuart_poll_put_char(struct uart_port *port, unsigned char c) +{ + unsigned int status; + + /* drain */ + while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE)) + barrier(); + + writeb(c, port->membase + UARTDR); +} + +static int lpuart_poll_get_char(struct uart_port *port) +{ + if (!(readb(port->membase + UARTSR1) & UARTSR1_RDRF)) + return NO_POLL_CHAR; + + return readb(port->membase + UARTDR); +} + +#endif + static inline void lpuart_transmit_buffer(struct lpuart_port *sport) { struct circ_buf *xmit = &sport->port.state->xmit; @@ -1596,6 +1657,11 @@ static const struct uart_ops lpuart_pops = { .config_port = lpuart_config_port, .verify_port = lpuart_verify_port, .flush_buffer = lpuart_flush_buffer, +#if defined(CONFIG_CONSOLE_POLL) + .poll_init = lpuart_poll_init, + .poll_get_char = lpuart_poll_get_char, + .poll_put_char = lpuart_poll_put_char, +#endif }; static const struct uart_ops lpuart32_pops = { -- cgit v1.2.3 From 0fe07647cc5003307fc4258f0b87239849aff68a Mon Sep 17 00:00:00 2001 From: Nicolae Rosia Date: Tue, 4 Oct 2016 15:46:17 +0300 Subject: tty: serial: Makefile: move kgdb to be initialized last fsl_lpuart cannot be used with kgdb because the kgdb initcall is called before the driver's init. Move kgdb to be initialized after all serial drivers have been inited. Signed-off-by: Nicolae Rosia Signed-off-by: Stefan Golinschi Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 1fa21ec616bd..2d6288bc4554 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -62,13 +62,11 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o -obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o obj-$(CONFIG_SERIAL_TILEGX) += tilegx.o -obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o @@ -96,3 +94,6 @@ obj-$(CONFIG_SERIAL_MPS2_UART) += mps2-uart.o # GPIOLIB helpers for modem control lines obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o + +obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o +obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o -- cgit v1.2.3 From 3f3a46951e02a89961f47db97624767b5b9befec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 Oct 2016 11:27:18 +0300 Subject: serial: 8250_lpss: set PCI master only for private DMA There is no need to set PCI bus mastering when device is not doing any DMA. Though on Intel Quark DMA is a part of UART IP and thus shares same device in Linux kernel. Enable bus mastering only for Quark case. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 886fcf37f291..353c90ea50b1 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -183,6 +183,8 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) if (ret) return; + pci_set_master(pdev); + /* Special DMA address for UART */ dma->rx_dma_addr = 0xfffff000; dma->tx_dma_addr = 0xfffff000; @@ -280,8 +282,6 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; - pci_set_master(pdev); - lpss = devm_kzalloc(&pdev->dev, sizeof(*lpss), GFP_KERNEL); if (!lpss) return -ENOMEM; -- cgit v1.2.3 From eca84e99d1afac871cd85b3444862f36fa8bbb37 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 Oct 2016 11:27:19 +0300 Subject: serial: 8250_lpss: Try to enable Memory-Write-Invalidate Enable MWI mechanism if PCI bus master supports it. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpss.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 353c90ea50b1..ac2a34ecfd66 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -184,6 +184,7 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) return; pci_set_master(pdev); + pci_try_set_mwi(pdev); /* Special DMA address for UART */ dma->rx_dma_addr = 0xfffff000; -- cgit v1.2.3 From 04da73803c05dc1150ccc31cbf93e8cd56679c09 Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Thu, 13 Oct 2016 10:44:33 -0500 Subject: sc16is7xx: Drop bogus use of IRQF_ONESHOT The use of IRQF_ONESHOT when registering an interrupt handler with request_irq() is non-sensical. Not only that, it also prevents the handler from being threaded when it otherwise should be w/ IRQ_FORCED_THREADING is enabled. This causes the following deadlock observed by Sean Nyekjaer on -rt: Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM [..] rt_spin_lock_slowlock from queue_kthread_work queue_kthread_work from sc16is7xx_irq sc16is7xx_irq [sc16is7xx] from handle_irq_event_percpu handle_irq_event_percpu from handle_irq_event handle_irq_event from handle_level_irq handle_level_irq from generic_handle_irq generic_handle_irq from mxc_gpio_irq_handler mxc_gpio_irq_handler from mx3_gpio_irq_handler mx3_gpio_irq_handler from generic_handle_irq generic_handle_irq from __handle_domain_irq __handle_domain_irq from gic_handle_irq gic_handle_irq from __irq_svc __irq_svc from rt_spin_unlock rt_spin_unlock from kthread_worker_fn kthread_worker_fn from kthread kthread from ret_from_fork Fixes: 9e6f4ca3e567 ("sc16is7xx: use kthread_worker for tx_work and irq") Reported-by: Sean Nyekjaer Signed-off-by: Josh Cartwright Cc: linux-rt-users@vger.kernel.org Cc: Jakub Kicinski Cc: stable@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: Sebastian Andrzej Siewior Signed-off-by: Julia Cartwright Acked-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 2675792a8f59..28cf48d41f66 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1260,7 +1260,7 @@ static int sc16is7xx_probe(struct device *dev, /* Setup interrupt */ ret = devm_request_irq(dev, irq, sc16is7xx_irq, - IRQF_ONESHOT | flags, dev_name(dev), s); + flags, dev_name(dev), s); if (!ret) return 0; -- cgit v1.2.3 From ba061c1a9066a40a1ee6800b828c83bca3cbf631 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 21 Oct 2016 19:19:15 +0300 Subject: serial: 8250_lpss: get IRQ via pci_irq_vector() Instead of a direct assignment use pci_irq_vector() call as it's done for the other case. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index ac2a34ecfd66..fe7a36fbeef9 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -174,7 +174,7 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) int ret; chip->dev = &pdev->dev; - chip->irq = pdev->irq; + chip->irq = pci_irq_vector(pdev, 0); chip->regs = pci_ioremap_bar(pdev, 1); chip->pdata = &qrk_serial_dma_pdata; -- cgit v1.2.3 From fea6dd14868aa8f954804cf4a629b6af3e47c484 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 22 Oct 2016 00:06:21 +0200 Subject: serial: 8250: pxa: add devicetree earlyconsole Transfer the device-tree pxa uart handling from 8250_of to the new 8250_pxa. As a corollary, add the early console definition into 8250_pxa. This enables to have the same uart node for the early console and the normal uart. Signed-off-by: Robert Jarzmik Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_of.c | 2 -- drivers/tty/serial/8250/8250_pxa.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 7a8b5fc81a19..d25ab1cd4295 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -332,8 +332,6 @@ static const struct of_device_id of_platform_serial_table[] = { .data = (void *)PORT_ALTR_16550_F128, }, { .compatible = "mrvl,mmp-uart", .data = (void *)PORT_XSCALE, }, - { .compatible = "mrvl,pxa-uart", - .data = (void *)PORT_XSCALE, }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, of_platform_serial_table); diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c index 6a14df013754..3b08f342851a 100644 --- a/drivers/tty/serial/8250/8250_pxa.c +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -172,6 +172,19 @@ static struct platform_driver serial_pxa_driver = { module_platform_driver(serial_pxa_driver); +static int __init early_serial_pxa_setup(struct earlycon_device *device, + const char *options) +{ + struct uart_port *port = &device->port; + + if (!(device->port.membase || device->port.iobase)) + return -ENODEV; + + port->regshift = 2; + return early_serial8250_setup(device, NULL); +} +OF_EARLYCON_DECLARE(early_pxa, "mrvl,pxa-uart", early_serial_pxa_setup); + MODULE_AUTHOR("Sergei Ianovich"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:pxa2xx-uart"); -- cgit v1.2.3 From f1232ac229cc078206a72ca365c3526e37ea1ae5 Mon Sep 17 00:00:00 2001 From: "Ji-Ze Hong (Peter Hong)" Date: Tue, 4 Oct 2016 16:27:59 +0800 Subject: serial: 8250_fintek: Refactoring read/write method If we need to access SuperIO registers, It should write register offset to base_addr and read/write value to base_addr + 1 to perform read/write. We can make it more simply with write/read functions. This patch add sio_read_reg()/sio_write_reg()/sio_write_mask_reg() to reduce SuperIO register operation with lot of outb()/inb(). Signed-off-by: Ji-Ze Hong (Peter Hong) Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fintek.c | 73 ++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 0facc789fe7d..2ae846e2c6d0 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -49,6 +49,27 @@ struct fintek_8250 { u8 key; }; +static u8 sio_read_reg(struct fintek_8250 *pdata, u8 reg) +{ + outb(reg, pdata->base_port + ADDR_PORT); + return inb(pdata->base_port + DATA_PORT); +} + +static void sio_write_reg(struct fintek_8250 *pdata, u8 reg, u8 data) +{ + outb(reg, pdata->base_port + ADDR_PORT); + outb(data, pdata->base_port + DATA_PORT); +} + +static void sio_write_mask_reg(struct fintek_8250 *pdata, u8 reg, u8 mask, + u8 data) +{ + u8 tmp; + + tmp = (sio_read_reg(pdata, reg) & ~mask) | (mask & data); + sio_write_reg(pdata, reg, tmp); +} + static int fintek_8250_enter_key(u16 base_port, u8 key) { if (!request_muxed_region(base_port, 2, "8250_fintek")) @@ -66,22 +87,18 @@ static void fintek_8250_exit_key(u16 base_port) release_region(base_port + ADDR_PORT, 2); } -static int fintek_8250_check_id(u16 base_port) +static int fintek_8250_check_id(struct fintek_8250 *pdata) { u16 chip; - outb(VENDOR_ID1, base_port + ADDR_PORT); - if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL) + if (sio_read_reg(pdata, VENDOR_ID1) != VENDOR_ID1_VAL) return -ENODEV; - outb(VENDOR_ID2, base_port + ADDR_PORT); - if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL) + if (sio_read_reg(pdata, VENDOR_ID2) != VENDOR_ID2_VAL) return -ENODEV; - outb(CHIP_ID1, base_port + ADDR_PORT); - chip = inb(base_port + DATA_PORT); - outb(CHIP_ID2, base_port + ADDR_PORT); - chip |= inb(base_port + DATA_PORT) << 8; + chip = sio_read_reg(pdata, CHIP_ID1); + chip |= sio_read_reg(pdata, CHIP_ID2) << 8; if (chip != CHIP_ID_0 && chip != CHIP_ID_1) return -ENODEV; @@ -128,10 +145,8 @@ static int fintek_8250_rs485_config(struct uart_port *port, if (fintek_8250_enter_key(pdata->base_port, pdata->key)) return -EBUSY; - outb(LDN, pdata->base_port + ADDR_PORT); - outb(pdata->index, pdata->base_port + DATA_PORT); - outb(RS485, pdata->base_port + ADDR_PORT); - outb(config, pdata->base_port + DATA_PORT); + sio_write_reg(pdata, LDN, pdata->index); + sio_write_reg(pdata, RS485, config); fintek_8250_exit_key(pdata->base_port); port->rs485 = *rs485; @@ -147,10 +162,12 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address) for (i = 0; i < ARRAY_SIZE(addr); i++) { for (j = 0; j < ARRAY_SIZE(keys); j++) { + pdata->base_port = addr[i]; + pdata->key = keys[j]; if (fintek_8250_enter_key(addr[i], keys[j])) continue; - if (fintek_8250_check_id(addr[i])) { + if (fintek_8250_check_id(pdata)) { fintek_8250_exit_key(addr[i]); continue; } @@ -158,19 +175,13 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address) for (k = 0; k < 4; k++) { u16 aux; - outb(LDN, addr[i] + ADDR_PORT); - outb(k, addr[i] + DATA_PORT); - - outb(IO_ADDR1, addr[i] + ADDR_PORT); - aux = inb(addr[i] + DATA_PORT); - outb(IO_ADDR2, addr[i] + ADDR_PORT); - aux |= inb(addr[i] + DATA_PORT) << 8; + sio_write_reg(pdata, LDN, k); + aux = sio_read_reg(pdata, IO_ADDR1); + aux |= sio_read_reg(pdata, IO_ADDR2) << 8; if (aux != io_address) continue; fintek_8250_exit_key(addr[i]); - pdata->key = keys[j]; - pdata->base_port = addr[i]; pdata->index = k; return 0; @@ -186,24 +197,16 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address) static int fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool level_mode) { int status; - u8 tmp; status = fintek_8250_enter_key(pdata->base_port, pdata->key); if (status) return status; - outb(LDN, pdata->base_port + ADDR_PORT); - outb(pdata->index, pdata->base_port + DATA_PORT); - - outb(FINTEK_IRQ_MODE, pdata->base_port + ADDR_PORT); - tmp = inb(pdata->base_port + DATA_PORT); - - tmp &= ~IRQ_MODE_MASK; - tmp |= IRQ_SHARE; - if (!level_mode) - tmp |= IRQ_EDGE_HIGH; + sio_write_reg(pdata, LDN, pdata->index); + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, IRQ_SHARE); + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, + level_mode ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); - outb(tmp, pdata->base_port + DATA_PORT); fintek_8250_exit_key(pdata->base_port); return 0; } -- cgit v1.2.3 From 06e3957259ef9003061c3c153232266ab8967e34 Mon Sep 17 00:00:00 2001 From: "Ji-Ze Hong (Peter Hong)" Date: Tue, 4 Oct 2016 16:28:00 +0800 Subject: serial: 8250_fintek: Set IRQ Mode when port probed Set IRQ Mode when port probed in probe_setup_port() It should hold the IO port premission via fintek_8250_enter_key() and release via fintek_8250_exit_key() when we configure the SuperIO. This patch will move all SuperIO configure operations to probe_setup_port() to reduce fintek_8250_enter_key() and fintek_8250_exit_key() usage. Suggested-by: Ricardo Ribalda Delgado Signed-off-by: Ji-Ze Hong (Peter Hong) Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fintek.c | 45 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 2ae846e2c6d0..deccd0e8434b 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -154,10 +154,21 @@ static int fintek_8250_rs485_config(struct uart_port *port, return 0; } -static int find_base_port(struct fintek_8250 *pdata, u16 io_address) +static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) +{ + sio_write_reg(pdata, LDN, pdata->index); + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, IRQ_SHARE); + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, + is_level ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); +} + +static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address, + unsigned int irq) { static const u16 addr[] = {0x4e, 0x2e}; static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67}; + struct irq_data *irq_data; + bool level_mode = false; int i, j, k; for (i = 0; i < ARRAY_SIZE(addr); i++) { @@ -181,9 +192,16 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address) if (aux != io_address) continue; - fintek_8250_exit_key(addr[i]); pdata->index = k; + irq_data = irq_get_irq_data(irq); + if (irq_data) + level_mode = + irqd_is_level_type(irq_data); + + fintek_8250_set_irq_mode(pdata, level_mode); + fintek_8250_exit_key(addr[i]); + return 0; } @@ -194,31 +212,12 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address) return -ENODEV; } -static int fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool level_mode) -{ - int status; - - status = fintek_8250_enter_key(pdata->base_port, pdata->key); - if (status) - return status; - - sio_write_reg(pdata, LDN, pdata->index); - sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, IRQ_SHARE); - sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, - level_mode ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); - - fintek_8250_exit_key(pdata->base_port); - return 0; -} - int fintek_8250_probe(struct uart_8250_port *uart) { struct fintek_8250 *pdata; struct fintek_8250 probe_data; - struct irq_data *irq_data = irq_get_irq_data(uart->port.irq); - bool level_mode = irqd_is_level_type(irq_data); - if (find_base_port(&probe_data, uart->port.iobase)) + if (probe_setup_port(&probe_data, uart->port.iobase, uart->port.irq)) return -ENODEV; pdata = devm_kzalloc(uart->port.dev, sizeof(*pdata), GFP_KERNEL); @@ -229,5 +228,5 @@ int fintek_8250_probe(struct uart_8250_port *uart) uart->port.rs485_config = fintek_8250_rs485_config; uart->port.private_data = pdata; - return fintek_8250_set_irq_mode(pdata, level_mode); + return 0; } -- cgit v1.2.3 From c2236facaec9e4bdd3b350a6a54d29440a234a04 Mon Sep 17 00:00:00 2001 From: "Ji-Ze Hong (Peter Hong)" Date: Tue, 4 Oct 2016 16:28:01 +0800 Subject: serial: 8250_fintek: Set maximum FIFO of F81216H The Fintek F81216H had maximum 128Bytes FIFO, but some BIOS configurated as normal 16Bytes FIFO. This patch will set 128Bytes FIFO and trigger level multiplier as 4x when F81216H detected. Default 16550A trigger level is 8Bytes. When this patch applied, the trigger level will change to 8Byte x 4 = 32Byte. It can be reduce the RX incoming interrupts. Suggested-by: Ricardo Ribalda Delgado Signed-off-by: Ji-Ze Hong (Peter Hong) Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fintek.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index deccd0e8434b..e039a33e59e3 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -21,8 +21,8 @@ #define EXIT_KEY 0xAA #define CHIP_ID1 0x20 #define CHIP_ID2 0x21 -#define CHIP_ID_0 0x1602 -#define CHIP_ID_1 0x0501 +#define CHIP_ID_F81216AD 0x1602 +#define CHIP_ID_F81216H 0x0501 #define VENDOR_ID1 0x23 #define VENDOR_ID1_VAL 0x19 #define VENDOR_ID2 0x24 @@ -43,7 +43,14 @@ #define RXW4C_IRA BIT(3) #define TXW4C_IRA BIT(2) +#define FIFO_CTRL 0xF6 +#define FIFO_MODE_MASK (BIT(1) | BIT(0)) +#define FIFO_MODE_128 (BIT(1) | BIT(0)) +#define RXFTHR_MODE_MASK (BIT(5) | BIT(4)) +#define RXFTHR_MODE_4X BIT(5) + struct fintek_8250 { + u16 pid; u16 base_port; u8 index; u8 key; @@ -100,9 +107,10 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata) chip = sio_read_reg(pdata, CHIP_ID1); chip |= sio_read_reg(pdata, CHIP_ID2) << 8; - if (chip != CHIP_ID_0 && chip != CHIP_ID_1) + if (chip != CHIP_ID_F81216AD && chip != CHIP_ID_F81216H) return -ENODEV; + pdata->pid = chip; return 0; } @@ -162,6 +170,20 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) is_level ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); } +static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata) +{ + switch (pdata->pid) { + case CHIP_ID_F81216H: /* 128Bytes FIFO */ + sio_write_mask_reg(pdata, FIFO_CTRL, + FIFO_MODE_MASK | RXFTHR_MODE_MASK, + FIFO_MODE_128 | RXFTHR_MODE_4X); + break; + + default: /* Default 16Bytes FIFO */ + break; + } +} + static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address, unsigned int irq) { @@ -200,6 +222,7 @@ static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address, irqd_is_level_type(irq_data); fintek_8250_set_irq_mode(pdata, level_mode); + fintek_8250_set_max_fifo(pdata); fintek_8250_exit_key(addr[i]); return 0; -- cgit v1.2.3 From 1e26c472c1a299c843f9762f74e8cd503cd977a2 Mon Sep 17 00:00:00 2001 From: "Ji-Ze Hong (Peter Hong)" Date: Tue, 4 Oct 2016 16:28:02 +0800 Subject: serial: 8250_fintek: Add F81216 Support Fintek F81216 is a LPC to 4 UARTs device. It's the F81216 series but support less functional than F81216AD/F81216H The following list is brief descriptions of F81216 series: F81216H (0105) 9Bit/High baud rate(not implements with mainline) RS485, 128Bytes FIFO (implemented) F81216AD (0216) 9Bit(not implements with mainline) RS485(implemented) F81216 (0208) basically 16550A Suggested-by: Ricardo Ribalda Delgado Signed-off-by: Ji-Ze Hong (Peter Hong) Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fintek.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index e039a33e59e3..523d873731be 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -23,6 +23,7 @@ #define CHIP_ID2 0x21 #define CHIP_ID_F81216AD 0x1602 #define CHIP_ID_F81216H 0x0501 +#define CHIP_ID_F81216 0x0802 #define VENDOR_ID1 0x23 #define VENDOR_ID1_VAL 0x19 #define VENDOR_ID2 0x24 @@ -107,8 +108,14 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata) chip = sio_read_reg(pdata, CHIP_ID1); chip |= sio_read_reg(pdata, CHIP_ID2) << 8; - if (chip != CHIP_ID_F81216AD && chip != CHIP_ID_F81216H) + switch (chip) { + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + break; + default: return -ENODEV; + } pdata->pid = chip; return 0; @@ -235,6 +242,21 @@ static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address, return -ENODEV; } +static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) +{ + struct fintek_8250 *pdata = uart->port.private_data; + + switch (pdata->pid) { + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + uart->port.rs485_config = fintek_8250_rs485_config; + break; + + default: /* No RS485 Auto direction functional */ + break; + } +} + int fintek_8250_probe(struct uart_8250_port *uart) { struct fintek_8250 *pdata; @@ -248,8 +270,8 @@ int fintek_8250_probe(struct uart_8250_port *uart) return -ENOMEM; memcpy(pdata, &probe_data, sizeof(probe_data)); - uart->port.rs485_config = fintek_8250_rs485_config; uart->port.private_data = pdata; + fintek_8250_set_rs485_handler(uart); return 0; } -- cgit v1.2.3 From da60d6afaa3e7be561d202c78b6859eda4c87973 Mon Sep 17 00:00:00 2001 From: "Ji-Ze Hong (Peter Hong)" Date: Tue, 4 Oct 2016 16:28:03 +0800 Subject: serial: 8250_fintek: Add F81866 Support Fintek F81866 is a LPC to 6 UARTs SuperIO. It has fully functional UARTs likes F81216H. It's also need check the IRQ mode with system assigned, but the configuration is not the same with F81216 series. F81866 IRQ Mode setting: 0xf0 Bit1: IRQ_MODE0 Bit0: Share mode (always on) 0xf6 Bit3: IRQ_MODE1 Level/Low: IRQ_MODE0:0, IRQ_MODE1:0 Edge/High: IRQ_MODE0:1, IRQ_MODE1:0 The following list is brief descriptions of F81866: F81866 (1010) 9Bit/High baud rate(not implements with mainline) RS485, 128Bytes FIFO (implemented) Signed-off-by: Ji-Ze Hong (Peter Hong) Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fintek.c | 74 ++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 523d873731be..ff4286bab791 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -21,6 +21,7 @@ #define EXIT_KEY 0xAA #define CHIP_ID1 0x20 #define CHIP_ID2 0x21 +#define CHIP_ID_F81866 0x1010 #define CHIP_ID_F81216AD 0x1602 #define CHIP_ID_F81216H 0x0501 #define CHIP_ID_F81216 0x0802 @@ -50,6 +51,26 @@ #define RXFTHR_MODE_MASK (BIT(5) | BIT(4)) #define RXFTHR_MODE_4X BIT(5) +#define F81216_LDN_LOW 0x0 +#define F81216_LDN_HIGH 0x4 + +/* + * F81866 registers + * + * The IRQ setting mode of F81866 is not the same with F81216 series. + * Level/Low: IRQ_MODE0:0, IRQ_MODE1:0 + * Edge/High: IRQ_MODE0:1, IRQ_MODE1:0 + */ +#define F81866_IRQ_MODE 0xf0 +#define F81866_IRQ_SHARE BIT(0) +#define F81866_IRQ_MODE0 BIT(1) + +#define F81866_FIFO_CTRL FIFO_CTRL +#define F81866_IRQ_MODE1 BIT(3) + +#define F81866_LDN_LOW 0x10 +#define F81866_LDN_HIGH 0x16 + struct fintek_8250 { u16 pid; u16 base_port; @@ -109,6 +130,7 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata) chip |= sio_read_reg(pdata, CHIP_ID2) << 8; switch (chip) { + case CHIP_ID_F81866: case CHIP_ID_F81216AD: case CHIP_ID_F81216H: case CHIP_ID_F81216: @@ -121,6 +143,26 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata) return 0; } +static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min, + int *max) +{ + switch (pdata->pid) { + case CHIP_ID_F81866: + *min = F81866_LDN_LOW; + *max = F81866_LDN_HIGH; + return 0; + + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + *min = F81216_LDN_LOW; + *max = F81216_LDN_HIGH; + return 0; + } + + return -ENODEV; +} + static int fintek_8250_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { @@ -172,15 +214,33 @@ static int fintek_8250_rs485_config(struct uart_port *port, static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) { sio_write_reg(pdata, LDN, pdata->index); - sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, IRQ_SHARE); - sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, - is_level ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); + + switch (pdata->pid) { + case CHIP_ID_F81866: + sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1, + 0); + sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_SHARE, + F81866_IRQ_SHARE); + sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_MODE0, + is_level ? 0 : F81866_IRQ_MODE0); + break; + + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, + IRQ_SHARE); + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, + is_level ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); + break; + } } static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata) { switch (pdata->pid) { case CHIP_ID_F81216H: /* 128Bytes FIFO */ + case CHIP_ID_F81866: sio_write_mask_reg(pdata, FIFO_CTRL, FIFO_MODE_MASK | RXFTHR_MODE_MASK, FIFO_MODE_128 | RXFTHR_MODE_4X); @@ -198,7 +258,7 @@ static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address, static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67}; struct irq_data *irq_data; bool level_mode = false; - int i, j, k; + int i, j, k, min, max; for (i = 0; i < ARRAY_SIZE(addr); i++) { for (j = 0; j < ARRAY_SIZE(keys); j++) { @@ -207,12 +267,13 @@ static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address, if (fintek_8250_enter_key(addr[i], keys[j])) continue; - if (fintek_8250_check_id(pdata)) { + if (fintek_8250_check_id(pdata) || + fintek_8250_get_ldn_range(pdata, &min, &max)) { fintek_8250_exit_key(addr[i]); continue; } - for (k = 0; k < 4; k++) { + for (k = min; k < max; k++) { u16 aux; sio_write_reg(pdata, LDN, k); @@ -249,6 +310,7 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) switch (pdata->pid) { case CHIP_ID_F81216AD: case CHIP_ID_F81216H: + case CHIP_ID_F81866: uart->port.rs485_config = fintek_8250_rs485_config; break; -- cgit v1.2.3 From de48b0999df44b5d2ab75500a48aedff5a36f0e6 Mon Sep 17 00:00:00 2001 From: "Ji-Ze Hong (Peter Hong)" Date: Tue, 4 Oct 2016 16:28:04 +0800 Subject: serial: 8250_fintek: Add F81865 Support Fintek F81865 is a LPC to 6 UARTs SuperIO. It has less functional UARTs likes F81866. It's also need check the IRQ mode with system assigned, but the configuration is not the same with F81216 series. F81865 IRQ Mode setting: 0xf0 Bit1: IRQ_MODE0 Bit0: Share mode (always on) Level/Low: IRQ_MODE0:0 Edge/High: IRQ_MODE0:1 The following list is brief descriptions of F81865: F81865 (0704) 9Bit(not implements with mainline) RS485(implemented) Suggested-by: Ricardo Ribalda Delgado Signed-off-by: Ji-Ze Hong (Peter Hong) Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fintek.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index ff4286bab791..b67e7a544935 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -21,6 +21,7 @@ #define EXIT_KEY 0xAA #define CHIP_ID1 0x20 #define CHIP_ID2 0x21 +#define CHIP_ID_F81865 0x0407 #define CHIP_ID_F81866 0x1010 #define CHIP_ID_F81216AD 0x1602 #define CHIP_ID_F81216H 0x0501 @@ -130,6 +131,7 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata) chip |= sio_read_reg(pdata, CHIP_ID2) << 8; switch (chip) { + case CHIP_ID_F81865: case CHIP_ID_F81866: case CHIP_ID_F81216AD: case CHIP_ID_F81216H: @@ -147,6 +149,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min, int *max) { switch (pdata->pid) { + case CHIP_ID_F81865: case CHIP_ID_F81866: *min = F81866_LDN_LOW; *max = F81866_LDN_HIGH; @@ -219,6 +222,8 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) case CHIP_ID_F81866: sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1, 0); + /* fall through */ + case CHIP_ID_F81865: sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_SHARE, F81866_IRQ_SHARE); sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_MODE0, @@ -311,6 +316,7 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) case CHIP_ID_F81216AD: case CHIP_ID_F81216H: case CHIP_ID_F81866: + case CHIP_ID_F81865: uart->port.rs485_config = fintek_8250_rs485_config; break; -- cgit v1.2.3 From d705ff38189fcfbbfa6aa97363d30c23348ad166 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 3 Oct 2016 11:18:33 +0200 Subject: tty: vt, cleanup and document con_scroll Scrolling helpers scrup and scrdown both accept 'top' and 'bottom' as unsigned int. Number of lines 'nr' is accepted as int, but all callers pass down unsigned too. So change the type of 'nr' to unsigned too. Now, promote unsigned int from the helpers up to the con_scroll hook which actually accepted all those as signed int. Next, the 'dir' parameter can have only two values and we define constants for that: SM_UP and SM_DOWN. Switch them to enum and do proper type checking on 'dir' too. Finally, document the behaviour of the hook. Signed-off-by: Jiri Slaby Cc: Thomas Winischhofer Cc: Tomi Valkeinen Cc: "James E.J. Bottomley" Cc: Helge Deller Cc: Cc: Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 6 ++++-- drivers/usb/misc/sisusbvga/sisusb_con.c | 18 ++++++++++-------- drivers/video/console/fbcon.c | 18 ++++++++---------- drivers/video/console/mdacon.c | 7 ++++--- drivers/video/console/newport_con.c | 8 ++++---- drivers/video/console/sticon.c | 7 ++++--- drivers/video/console/vgacon.c | 12 +++++------- include/linux/console.h | 16 +++++++++++----- 8 files changed, 50 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 06fb39c1d6dd..c4bf96fee32e 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -315,7 +315,8 @@ void schedule_console_callback(void) schedule_work(&console_work); } -static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr) +static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, + unsigned int nr) { unsigned short *d, *s; @@ -332,7 +333,8 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr) vc->vc_size_row * nr); } -static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr) +static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, + unsigned int nr) { unsigned short *s; unsigned int step; diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 460cebf322e3..6331965daa0b 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -808,9 +808,10 @@ sisusbcon_cursor(struct vc_data *c, int mode) mutex_unlock(&sisusb->lock); } -static int +static bool sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb, - int t, int b, int dir, int lines) + unsigned int t, unsigned int b, enum con_scroll dir, + unsigned int lines) { int cols = sisusb->sisusb_num_columns; int length = ((b - t) * cols) * 2; @@ -852,8 +853,9 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb, } /* Interface routine */ -static int -sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) +static bool +sisusbcon_scroll(struct vc_data *c, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int lines) { struct sisusb_usb_data *sisusb; u16 eattr = c->vc_video_erase_char; @@ -870,17 +872,17 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) */ if (!lines) - return 1; + return true; sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num); if (!sisusb) - return 0; + return false; /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { mutex_unlock(&sisusb->lock); - return 0; + return false; } /* Special case */ @@ -971,7 +973,7 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) mutex_unlock(&sisusb->lock); - return 1; + return true; } /* Interface routine */ diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b87f5cfdaea5..a44f5627b82a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -164,8 +164,6 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, int count, int ypos, int xpos); static void fbcon_clear_margins(struct vc_data *vc, int bottom_only); static void fbcon_cursor(struct vc_data *vc, int mode); -static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, - int count); static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, int height, int width); static int fbcon_switch(struct vc_data *vc); @@ -1795,15 +1793,15 @@ static inline void fbcon_softback_note(struct vc_data *vc, int t, softback_curr = softback_in; } -static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, - int count) +static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; if (fbcon_is_inactive(vc, info)) - return -EINVAL; + return true; fbcon_cursor(vc, CM_ERASE); @@ -1831,7 +1829,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, (b - count)), vc->vc_video_erase_char, vc->vc_size_row * count); - return 1; + return true; break; case SCROLL_WRAP_MOVE: @@ -1903,7 +1901,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, (b - count)), vc->vc_video_erase_char, vc->vc_size_row * count); - return 1; + return true; } break; @@ -1922,7 +1920,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, t), vc->vc_video_erase_char, vc->vc_size_row * count); - return 1; + return true; break; case SCROLL_WRAP_MOVE: @@ -1992,10 +1990,10 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, t), vc->vc_video_erase_char, vc->vc_size_row * count); - return 1; + return true; } } - return 0; + return false; } diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index bacbb044d77c..ec192a1bf297 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -488,12 +488,13 @@ static void mdacon_cursor(struct vc_data *c, int mode) } } -static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) +static bool mdacon_scroll(struct vc_data *c, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int lines) { u16 eattr = mda_convert_attr(c->vc_video_erase_char); if (!lines) - return 0; + return false; if (lines > c->vc_rows) /* maximum realistic size */ lines = c->vc_rows; @@ -514,7 +515,7 @@ static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) break; } - return 0; + return false; } diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index e3b9521e4ec3..1e11614322fe 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -574,8 +574,8 @@ static int newport_font_set(struct vc_data *vc, struct console_font *font, unsig return newport_set_font(vc->vc_num, font); } -static int newport_scroll(struct vc_data *vc, int t, int b, int dir, - int lines) +static bool newport_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int lines) { int count, x, y; unsigned short *s, *d; @@ -595,7 +595,7 @@ static int newport_scroll(struct vc_data *vc, int t, int b, int dir, (vc->vc_color & 0xf0) >> 4); } npregs->cset.topscan = (topscan - 1) & 0x3ff; - return 0; + return false; } count = (b - t - lines) * vc->vc_cols; @@ -670,7 +670,7 @@ static int newport_scroll(struct vc_data *vc, int t, int b, int dir, } } } - return 1; + return true; } static int newport_dummy(struct vc_data *c) diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 3a10ac19598f..79c9bd8d3025 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -153,12 +153,13 @@ static void sticon_cursor(struct vc_data *conp, int mode) } } -static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count) +static bool sticon_scroll(struct vc_data *conp, unsigned int t, + unsigned int b, enum con_scroll dir, unsigned int count) { struct sti_struct *sti = sticon_sti; if (vga_is_gfx) - return 0; + return false; sticon_cursor(conp, CM_ERASE); @@ -174,7 +175,7 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count) break; } - return 0; + return false; } static void sticon_init(struct vc_data *c, int init) diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 11576611a974..4c54a873452e 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -83,8 +83,6 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch); static void vgacon_scrolldelta(struct vc_data *c, int lines); static int vgacon_set_origin(struct vc_data *c); static void vgacon_save_screen(struct vc_data *c); -static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, - int lines); static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); static struct uni_pagedir *vgacon_uni_pagedir; static int vgacon_refcount; @@ -1350,17 +1348,17 @@ static void vgacon_save_screen(struct vc_data *c) c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); } -static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, - int lines) +static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int lines) { unsigned long oldo; unsigned int delta; if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT) - return 0; + return false; if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2) - return 0; + return false; vgacon_restore_screen(c); oldo = c->vc_origin; @@ -1396,7 +1394,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, c->vc_visible_origin = c->vc_origin; vga_set_mem_top(c); c->vc_pos = (c->vc_pos - oldo) + c->vc_origin; - return 1; + return true; } diff --git a/include/linux/console.h b/include/linux/console.h index 3672809234a7..508b012bd5bd 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -28,9 +28,17 @@ struct tty_struct; #define VT100ID "\033[?1;2c" #define VT102ID "\033[?6c" +enum con_scroll { + SM_UP, + SM_DOWN, +}; + /** * struct consw - callbacks for consoles * + * @con_scroll: move lines from @top to @bottom in direction @dir by @lines. + * Return true if no generic handling should be done. + * Invoked by csi_M and printing to the console. * @con_set_palette: sets the palette of the console to @table (optional) * @con_scrolldelta: the contents of the console should be scrolled by @lines. * Invoked by user. (optional) @@ -44,7 +52,9 @@ struct consw { void (*con_putc)(struct vc_data *, int, int, int); void (*con_putcs)(struct vc_data *, const unsigned short *, int, int, int); void (*con_cursor)(struct vc_data *, int); - int (*con_scroll)(struct vc_data *, int, int, int, int); + bool (*con_scroll)(struct vc_data *, unsigned int top, + unsigned int bottom, enum con_scroll dir, + unsigned int lines); int (*con_switch)(struct vc_data *); int (*con_blank)(struct vc_data *, int, int); int (*con_font_set)(struct vc_data *, struct console_font *, unsigned); @@ -99,10 +109,6 @@ static inline int con_debug_leave(void) } #endif -/* scroll */ -#define SM_UP (1) -#define SM_DOWN (2) - /* cursor */ #define CM_DRAW (1) #define CM_ERASE (2) -- cgit v1.2.3 From 89765b9424eafb954b1ca167a00c2a10e4f025be Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 3 Oct 2016 11:18:34 +0200 Subject: tty: vt, unify scrolling functions Both scrup and scrdown are copies of the same code except source and destination pointers computation. Unify those functions into a single one named con_scroll. Note that scrdown used step to compute the destination, while scrup did the computation explicitly. We sticked to the latter here. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 47 +++++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index c4bf96fee32e..a0b7576747cd 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -315,40 +315,27 @@ void schedule_console_callback(void) schedule_work(&console_work); } -static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, - unsigned int nr) +static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int nr) { - unsigned short *d, *s; + u16 *clear, *d, *s; - if (t+nr >= b) + if (t + nr >= b) nr = b - t - 1; if (b > vc->vc_rows || t >= b || nr < 1) return; - if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr)) + if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, dir, nr)) return; - d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); - s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr)); - scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row); - scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char, - vc->vc_size_row * nr); -} -static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, - unsigned int nr) -{ - unsigned short *s; - unsigned int step; + s = clear = (u16 *)(vc->vc_origin + vc->vc_size_row * t); + d = (u16 *)(vc->vc_origin + vc->vc_size_row * (t + nr)); - if (t+nr >= b) - nr = b - t - 1; - if (b > vc->vc_rows || t >= b || nr < 1) - return; - if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr)) - return; - s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); - step = vc->vc_cols * nr; - scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row); - scr_memsetw(s, vc->vc_video_erase_char, 2 * step); + if (dir == SM_UP) { + clear = s + (b - t - nr) * vc->vc_cols; + swap(s, d); + } + scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row); + scr_memsetw(clear, vc->vc_video_erase_char, vc->vc_size_row * nr); } static void do_update_region(struct vc_data *vc, unsigned long start, int count) @@ -1117,7 +1104,7 @@ static void lf(struct vc_data *vc) * if below scrolling region */ if (vc->vc_y + 1 == vc->vc_bottom) - scrup(vc, vc->vc_top, vc->vc_bottom, 1); + con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_UP, 1); else if (vc->vc_y < vc->vc_rows - 1) { vc->vc_y++; vc->vc_pos += vc->vc_size_row; @@ -1132,7 +1119,7 @@ static void ri(struct vc_data *vc) * if above scrolling region */ if (vc->vc_y == vc->vc_top) - scrdown(vc, vc->vc_top, vc->vc_bottom, 1); + con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_DOWN, 1); else if (vc->vc_y > 0) { vc->vc_y--; vc->vc_pos -= vc->vc_size_row; @@ -1628,7 +1615,7 @@ static void csi_L(struct vc_data *vc, unsigned int nr) nr = vc->vc_rows - vc->vc_y; else if (!nr) nr = 1; - scrdown(vc, vc->vc_y, vc->vc_bottom, nr); + con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_DOWN, nr); vc->vc_need_wrap = 0; } @@ -1649,7 +1636,7 @@ static void csi_M(struct vc_data *vc, unsigned int nr) nr = vc->vc_rows - vc->vc_y; else if (!nr) nr=1; - scrup(vc, vc->vc_y, vc->vc_bottom, nr); + con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_UP, nr); vc->vc_need_wrap = 0; } -- cgit v1.2.3 From 35cc56f9a30480c8a0cca809cf341614a2144758 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 3 Oct 2016 11:18:35 +0200 Subject: tty: vgacon+sisusb, move scrolldelta to a common helper The code is mirrorred in scrolldelta implementations of both vgacon and sisusb. Let's move the code to a separate helper where we will perform a common cleanup and further changes. While we are moving the code, make it linear and save one indentation level. This is done by returning from the "!lines" then-branch immediatelly. This allows flushing the else-branch 1 level to the left, obviously. Few more new lines and comments were added too. And do not forget to export the helper function given sisusb can be built as module. Signed-off-by: Jiri Slaby Cc: Thomas Winischhofer Cc: Tomi Valkeinen Cc: Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 38 +++++++++++++++++++++++++++++++++ drivers/usb/misc/sisusbvga/sisusb_con.c | 37 ++------------------------------ drivers/video/console/vgacon.c | 27 ++--------------------- include/linux/vt_kern.h | 2 ++ 4 files changed, 44 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index a0b7576747cd..2eab714aab67 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4279,6 +4279,44 @@ void vcs_scr_updated(struct vc_data *vc) notify_update(vc); } +void vc_scrolldelta_helper(struct vc_data *c, int lines, + unsigned int rolled_over, void *base, unsigned int size) +{ + unsigned long ubase = (unsigned long)base; + int margin = c->vc_size_row * 4; + int ul, we, p, st; + + /* Turn scrollback off */ + if (!lines) { + c->vc_visible_origin = c->vc_origin; + return; + } + + /* Do we have already enough to allow jumping from 0 to the end? */ + if (rolled_over > (c->vc_scr_end - ubase) + margin) { + ul = c->vc_scr_end - ubase; + we = rolled_over + c->vc_size_row; + } else { + ul = 0; + we = size; + } + + p = (c->vc_visible_origin - ubase - ul + we) % we + + lines * c->vc_size_row; + st = (c->vc_origin - ubase - ul + we) % we; + + /* Only a little piece would be left? Show all incl. the piece! */ + if (st < 2 * margin) + margin = 0; + if (p < margin) + p = 0; + if (p > st - margin) + p = st; + + c->vc_visible_origin = ubase + (p + ul) % we; +} +EXPORT_SYMBOL_GPL(vc_scrolldelta_helper); + /* * Visible symbols for modules */ diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 6331965daa0b..4b5777ec1501 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -686,8 +686,6 @@ static void sisusbcon_scrolldelta(struct vc_data *c, int lines) { struct sisusb_usb_data *sisusb; - int margin = c->vc_size_row * 4; - int ul, we, p, st; sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num); if (!sisusb) @@ -700,39 +698,8 @@ sisusbcon_scrolldelta(struct vc_data *c, int lines) return; } - if (!lines) /* Turn scrollback off */ - c->vc_visible_origin = c->vc_origin; - else { - - if (sisusb->con_rolled_over > - (c->vc_scr_end - sisusb->scrbuf) + margin) { - - ul = c->vc_scr_end - sisusb->scrbuf; - we = sisusb->con_rolled_over + c->vc_size_row; - - } else { - - ul = 0; - we = sisusb->scrbuf_size; - - } - - p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we + - lines * c->vc_size_row; - - st = (c->vc_origin - sisusb->scrbuf - ul + we) % we; - - if (st < 2 * margin) - margin = 0; - - if (p < margin) - p = 0; - - if (p > st - margin) - p = st; - - c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we; - } + vc_scrolldelta_helper(c, lines, sisusb->con_rolled_over, + (void *)sisusb->scrbuf, sisusb->scrbuf_size); sisusbcon_set_start_address(sisusb, c); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 4c54a873452e..ede6a5a85ccd 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -332,31 +332,8 @@ static void vgacon_restore_screen(struct vc_data *c) static void vgacon_scrolldelta(struct vc_data *c, int lines) { - if (!lines) /* Turn scrollback off */ - c->vc_visible_origin = c->vc_origin; - else { - int margin = c->vc_size_row * 4; - int ul, we, p, st; - - if (vga_rolled_over > - (c->vc_scr_end - vga_vram_base) + margin) { - ul = c->vc_scr_end - vga_vram_base; - we = vga_rolled_over + c->vc_size_row; - } else { - ul = 0; - we = vga_vram_size; - } - p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + - lines * c->vc_size_row; - st = (c->vc_origin - vga_vram_base - ul + we) % we; - if (st < 2 * margin) - margin = 0; - if (p < margin) - p = 0; - if (p > st - margin) - p = st; - c->vc_visible_origin = vga_vram_base + (p + ul) % we; - } + vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base, + vga_vram_size); vga_set_mem_top(c); } #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */ diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 6abd24f258bc..833fdd4794a0 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -191,5 +191,7 @@ extern void vt_set_led_state(int console, int leds); extern void vt_kbd_con_start(int console); extern void vt_kbd_con_stop(int console); +void vc_scrolldelta_helper(struct vc_data *c, int lines, + unsigned int rolled_over, void *_base, unsigned int size); #endif /* _VT_KERN_H */ -- cgit v1.2.3 From 210fd7460e755c6de4972bca4ffa9cd9580279aa Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 3 Oct 2016 11:18:36 +0200 Subject: tty: vt, compute vc offsets in advance Only improves readability, no functional changes. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2eab714aab67..3cb6504b41d3 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4283,6 +4283,9 @@ void vc_scrolldelta_helper(struct vc_data *c, int lines, unsigned int rolled_over, void *base, unsigned int size) { unsigned long ubase = (unsigned long)base; + ptrdiff_t scr_end = (void *)c->vc_scr_end - base; + ptrdiff_t vorigin = (void *)c->vc_visible_origin - base; + ptrdiff_t origin = (void *)c->vc_origin - base; int margin = c->vc_size_row * 4; int ul, we, p, st; @@ -4293,17 +4296,16 @@ void vc_scrolldelta_helper(struct vc_data *c, int lines, } /* Do we have already enough to allow jumping from 0 to the end? */ - if (rolled_over > (c->vc_scr_end - ubase) + margin) { - ul = c->vc_scr_end - ubase; + if (rolled_over > scr_end + margin) { + ul = scr_end; we = rolled_over + c->vc_size_row; } else { ul = 0; we = size; } - p = (c->vc_visible_origin - ubase - ul + we) % we + - lines * c->vc_size_row; - st = (c->vc_origin - ubase - ul + we) % we; + p = (vorigin - ul + we) % we + lines * c->vc_size_row; + st = (origin - ul + we) % we; /* Only a little piece would be left? Show all incl. the piece! */ if (st < 2 * margin) -- cgit v1.2.3 From 7c918cdceb32c50b3f4a31eec177076c9a151b35 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 3 Oct 2016 11:18:37 +0200 Subject: tty: vt, rename variables to sane names This makes the code understandable at least. No functional changes. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 3cb6504b41d3..804cc3151b13 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4287,7 +4287,7 @@ void vc_scrolldelta_helper(struct vc_data *c, int lines, ptrdiff_t vorigin = (void *)c->vc_visible_origin - base; ptrdiff_t origin = (void *)c->vc_origin - base; int margin = c->vc_size_row * 4; - int ul, we, p, st; + int from, wrap, from_off, avail; /* Turn scrollback off */ if (!lines) { @@ -4297,25 +4297,25 @@ void vc_scrolldelta_helper(struct vc_data *c, int lines, /* Do we have already enough to allow jumping from 0 to the end? */ if (rolled_over > scr_end + margin) { - ul = scr_end; - we = rolled_over + c->vc_size_row; + from = scr_end; + wrap = rolled_over + c->vc_size_row; } else { - ul = 0; - we = size; + from = 0; + wrap = size; } - p = (vorigin - ul + we) % we + lines * c->vc_size_row; - st = (origin - ul + we) % we; + from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row; + avail = (origin - from + wrap) % wrap; /* Only a little piece would be left? Show all incl. the piece! */ - if (st < 2 * margin) + if (avail < 2 * margin) margin = 0; - if (p < margin) - p = 0; - if (p > st - margin) - p = st; + if (from_off < margin) + from_off = 0; + if (from_off > avail - margin) + from_off = avail; - c->vc_visible_origin = ubase + (p + ul) % we; + c->vc_visible_origin = ubase + (from + from_off) % wrap; } EXPORT_SYMBOL_GPL(vc_scrolldelta_helper); -- cgit v1.2.3 From 96fd95542391d2ceb15515f41566dbb6776d9858 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 3 Oct 2016 11:18:38 +0200 Subject: vgacon: switch boolean variables to bool These variables: * vga_can_do_color * vgacon_text_mode_force * vga_font_is_default * vga_hardscroll_enabled * vga_hardscroll_user_enable * vga_init_done * vga_is_gfx * vga_palette_blanked * vga_512_chars are used exclusively as a boolean value, so make them really a bool. Remove also useless "? true : false". __read_mostly annotations removed too as they obfuscate the code and I doubt they improve anything measurable given the variables are used from .con_scroll, .con_startup and such. Signed-off-by: Jiri Slaby Cc: Tomi Valkeinen Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/video/console/vgacon.c | 45 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index ede6a5a85ccd..d13d5d372604 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -88,7 +88,7 @@ static struct uni_pagedir *vgacon_uni_pagedir; static int vgacon_refcount; /* Description of the hardware situation */ -static int vga_init_done __read_mostly; +static bool vga_init_done; static unsigned long vga_vram_base __read_mostly; /* Base of video memory */ static unsigned long vga_vram_end __read_mostly; /* End of video memory */ static unsigned int vga_vram_size __read_mostly; /* Size of video memory */ @@ -96,31 +96,31 @@ static u16 vga_video_port_reg __read_mostly; /* Video register select port */ static u16 vga_video_port_val __read_mostly; /* Video register value port */ static unsigned int vga_video_num_columns; /* Number of text columns */ static unsigned int vga_video_num_lines; /* Number of text lines */ -static int vga_can_do_color __read_mostly; /* Do we support colors? */ +static bool vga_can_do_color; /* Do we support colors? */ static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ static unsigned char vga_video_type __read_mostly; /* Card type */ -static unsigned char vga_hardscroll_enabled __read_mostly; -static unsigned char vga_hardscroll_user_enable __read_mostly = 1; -static unsigned char vga_font_is_default = 1; +static bool vga_font_is_default = true; static int vga_vesa_blanked; -static int vga_palette_blanked; -static int vga_is_gfx; -static int vga_512_chars; +static bool vga_palette_blanked; +static bool vga_is_gfx; +static bool vga_512_chars; static int vga_video_font_height; static int vga_scan_lines __read_mostly; static unsigned int vga_rolled_over; -static int vgacon_text_mode_force; +static bool vgacon_text_mode_force; +static bool vga_hardscroll_enabled; +static bool vga_hardscroll_user_enable = true; bool vgacon_text_force(void) { - return vgacon_text_mode_force ? true : false; + return vgacon_text_mode_force; } EXPORT_SYMBOL(vgacon_text_force); static int __init text_mode(char *str) { - vgacon_text_mode_force = 1; + vgacon_text_mode_force = true; return 1; } @@ -134,7 +134,7 @@ static int __init no_scroll(char *str) * Braille reader made by F.H. Papenmeier (Germany). * Use the "no-scroll" bootflag. */ - vga_hardscroll_user_enable = vga_hardscroll_enabled = 0; + vga_hardscroll_user_enable = vga_hardscroll_enabled = false; return 1; } @@ -402,7 +402,7 @@ static const char *vgacon_startup(void) } } else { /* If not, it is color. */ - vga_can_do_color = 1; + vga_can_do_color = true; vga_vram_base = 0xb8000; vga_video_port_reg = VGA_CRT_IC; vga_video_port_val = VGA_CRT_DC; @@ -517,7 +517,7 @@ static const char *vgacon_startup(void) if (!vga_init_done) { vgacon_scrollback_startup(); - vga_init_done = 1; + vga_init_done = true; } return display_desc; @@ -609,7 +609,7 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, static void vgacon_invert_region(struct vc_data *c, u16 * p, int count) { - int col = vga_can_do_color; + const bool col = vga_can_do_color; while (count--) { u16 a = scr_readw(p); @@ -981,24 +981,24 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) } if (vga_palette_blanked) { vga_set_palette(c, color_table); - vga_palette_blanked = 0; + vga_palette_blanked = false; return 0; } - vga_is_gfx = 0; + vga_is_gfx = false; /* Tell console.c that it has to restore the screen itself */ return 1; case 1: /* Normal blanking */ case -1: /* Obsolete */ if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { vga_pal_blank(&vgastate); - vga_palette_blanked = 1; + vga_palette_blanked = true; return 0; } vgacon_set_origin(c); scr_memsetw((void *) vga_vram_base, BLANK, c->vc_screenbuf_size); if (mode_switch) - vga_is_gfx = 1; + vga_is_gfx = true; return 1; default: /* VESA blanking */ if (vga_video_type == VIDEO_TYPE_VGAC) { @@ -1029,7 +1029,8 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) #define blackwmap 0xa0000 #define cmapsz 8192 -static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) +static int vgacon_do_font_op(struct vgastate *state, char *arg, int set, + bool ch512) { unsigned short video_port_status = vga_video_port_reg + 6; int font_select = 0x00, beg, i; @@ -1055,7 +1056,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) if (!arg) return -EINVAL; /* Return to default font not supported */ - vga_font_is_default = 0; + vga_font_is_default = false; font_select = ch512 ? 0x04 : 0x00; #else /* @@ -1066,7 +1067,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) if (set) { vga_font_is_default = !arg; if (!arg) - ch512 = 0; /* Default font is always 256 */ + ch512 = false; /* Default font is always 256 */ font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00; } -- cgit v1.2.3 From b9c8b7fc252cd8e7e629f14bb8a68d54889470da Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 3 Oct 2016 11:18:39 +0200 Subject: vgacon: remove prehistoric macros These macros: * CAN_LOAD_EGA_FONTS * CAN_LOAD_PALETTE * TRIDENT_GLITCH * VGA_CAN_DO_64KB * SLOW_VGA are either always set or always unset. They come from the linux 2.1 times. And given nobody switched them to some configurable options, I assume nobody actually uses them. So remove the macros and leave in place appropriate branches of the conditional code. Signed-off-by: Jiri Slaby Cc: Tomi Valkeinen Cc: Cc: Signed-off-by: Greg Kroah-Hartman --- Documentation/VGA-softcursor.txt | 12 ++++------ drivers/video/console/vgacon.c | 49 ---------------------------------------- 2 files changed, 5 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/Documentation/VGA-softcursor.txt b/Documentation/VGA-softcursor.txt index 70acfbf399eb..2ea8968b64a6 100644 --- a/Documentation/VGA-softcursor.txt +++ b/Documentation/VGA-softcursor.txt @@ -2,13 +2,11 @@ Software cursor for VGA by Pavel Machek ======================= and Martin Mares Linux now has some ability to manipulate cursor appearance. Normally, you -can set the size of hardware cursor (and also work around some ugly bugs in -those miserable Trident cards--see #define TRIDENT_GLITCH in drivers/video/ -vgacon.c). You can now play a few new tricks: you can make your cursor look -like a non-blinking red block, make it inverse background of the character it's -over or to highlight that character and still choose whether the original -hardware cursor should remain visible or not. There may be other things I have -never thought of. +can set the size of hardware cursor. You can now play a few new tricks: you +can make your cursor look like a non-blinking red block, make it inverse +background of the character it's over or to highlight that character and still +choose whether the original hardware cursor should remain visible or not. +There may be other things I have never thought of. The cursor appearance is controlled by a "[?1;2;3c" escape sequence where 1, 2 and 3 are parameters described below. If you omit any of them, diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d13d5d372604..c22a56232b7c 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -60,15 +60,6 @@ static struct vgastate vgastate; #define BLANK 0x0020 -#define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */ -#define CAN_LOAD_PALETTE /* undefine if the user must not do this */ - -/* You really do _NOT_ want to define this, unless you have buggy - * Trident VGA which will resize cursor when moving it between column - * 15 & 16. If you define this and your VGA is OK, inverse bug will - * appear. - */ -#undef TRIDENT_GLITCH #define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */ /* * Interface used by the world @@ -157,18 +148,10 @@ static inline void write_vga(unsigned char reg, unsigned int val) * handlers, thus the write has to be IRQ-atomic. */ raw_spin_lock_irqsave(&vga_lock, flags); - -#ifndef SLOW_VGA v1 = reg + (val & 0xff00); v2 = reg + 1 + ((val << 8) & 0xff00); outw(v1, vga_video_port_reg); outw(v2, vga_video_port_reg); -#else - outb_p(reg, vga_video_port_reg); - outb_p(val >> 8, vga_video_port_val); - outb_p(reg + 1, vga_video_port_reg); - outb_p(val & 0xff, vga_video_port_val); -#endif raw_spin_unlock_irqrestore(&vga_lock, flags); } @@ -426,18 +409,6 @@ static const char *vgacon_startup(void) request_resource(&ioport_resource, &vga_console_resource); -#ifdef VGA_CAN_DO_64KB - /* - * get 64K rather than 32K of video RAM. - * This doesn't actually work on all "VGA" - * controllers (it seems like setting MM=01 - * and COE=1 isn't necessarily a good idea) - */ - vga_vram_base = 0xa0000; - vga_vram_size = 0x10000; - outb_p(6, VGA_GFX_I); - outb_p(6, VGA_GFX_D); -#endif /* * Normalise the palette registers, to point * the 16 screen colours to the first 16 @@ -627,11 +598,6 @@ static void vgacon_set_cursor_size(int xpos, int from, int to) unsigned long flags; int curs, cure; -#ifdef TRIDENT_GLITCH - if (xpos < 16) - from--, to--; -#endif - if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto)) return; cursor_size_lastfrom = from; @@ -833,12 +799,10 @@ static void vga_set_palette(struct vc_data *vc, const unsigned char *table) static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table) { -#ifdef CAN_LOAD_PALETTE if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked || !con_is_visible(vc)) return; vga_set_palette(vc, table); -#endif } /* structure holding original VGA register settings */ @@ -1021,8 +985,6 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) * (sizif@botik.yaroslavl.su). */ -#ifdef CAN_LOAD_EGA_FONTS - #define colourmap 0xa0000 /* Pauline Middelink reports that we should use 0xA0000 for the bwmap as well.. */ @@ -1039,10 +1001,6 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set, if (vga_video_type != VIDEO_TYPE_EGAM) { charmap = (char *) VGA_MAP_MEM(colourmap, 0); beg = 0x0e; -#ifdef VGA_CAN_DO_64KB - if (vga_video_type == VIDEO_TYPE_VGAC) - beg = 0x06; -#endif } else { charmap = (char *) VGA_MAP_MEM(blackwmap, 0); beg = 0x0a; @@ -1271,13 +1229,6 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars); } -#else - -#define vgacon_font_set NULL -#define vgacon_font_get NULL - -#endif - static int vgacon_resize(struct vc_data *c, unsigned int width, unsigned int height, unsigned int user) { -- cgit v1.2.3 From 51fa91475e431e75b802dbab7c056f2829dc9410 Mon Sep 17 00:00:00 2001 From: Vijay Kumar Date: Thu, 6 Oct 2016 12:06:11 -0700 Subject: usb/core: Added devspec sysfs entry for devices behind the usb hub Grub finds incorrect of_node path for devices behind usb hub. Added devspec sysfs entry for devices behind usb hub so that right of_node path is returned during grub sysfs walk for these devices. Signed-off-by: Vijay Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index c953a0f1c695..84d66d573196 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "usb.h" /* Active configuration fields */ @@ -104,6 +105,17 @@ static ssize_t bConfigurationValue_store(struct device *dev, static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR, bConfigurationValue_show, bConfigurationValue_store); +#ifdef CONFIG_OF +static ssize_t devspec_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct device_node *of_node = dev->of_node; + + return sprintf(buf, "%s\n", of_node_full_name(of_node)); +} +static DEVICE_ATTR_RO(devspec); +#endif + /* String fields */ #define usb_string_attr(name) \ static ssize_t name##_show(struct device *dev, \ @@ -786,6 +798,9 @@ static struct attribute *dev_attrs[] = { &dev_attr_remove.attr, &dev_attr_removable.attr, &dev_attr_ltm_capable.attr, +#ifdef CONFIG_OF + &dev_attr_devspec.attr, +#endif NULL, }; static struct attribute_group dev_attr_grp = { -- cgit v1.2.3 From 1f0c41dd0c216401e88a2665dc6a07ce24d6079d Mon Sep 17 00:00:00 2001 From: Jai Krishna Date: Tue, 25 Oct 2016 14:32:32 +0530 Subject: usb: usbip:checkpatch; fix bare use of unsigned This patch fixes the following checkpatch warning for usbip files WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: Jai Krishna Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc_dev.c | 8 ++++---- drivers/usb/usbip/vudc_transfer.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c index 7091848df6c8..c5375e74ffc5 100644 --- a/drivers/usb/usbip/vudc_dev.c +++ b/drivers/usb/usbip/vudc_dev.c @@ -242,10 +242,10 @@ static const struct usb_gadget_ops vgadget_ops = { static int vep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { - struct vep *ep; - struct vudc *udc; - unsigned maxp; - unsigned long flags; + struct vep *ep; + struct vudc *udc; + unsigned int maxp; + unsigned long flags; ep = to_vep(_ep); udc = ep_to_vudc(ep); diff --git a/drivers/usb/usbip/vudc_transfer.c b/drivers/usb/usbip/vudc_transfer.c index aba6bd478045..8b3dacc90183 100644 --- a/drivers/usb/usbip/vudc_transfer.c +++ b/drivers/usb/usbip/vudc_transfer.c @@ -73,8 +73,8 @@ static int handle_control_request(struct vudc *udc, struct urb *urb, { struct vep *ep2; int ret_val = 1; - unsigned w_index; - unsigned w_value; + unsigned int w_index; + unsigned int w_value; w_index = le16_to_cpu(setup->wIndex); w_value = le16_to_cpu(setup->wValue); @@ -200,7 +200,7 @@ static int transfer(struct vudc *udc, top: /* if there's no request queued, the device is NAKing; return */ list_for_each_entry(req, &ep->req_queue, req_entry) { - unsigned host_len, dev_len, len; + unsigned int host_len, dev_len, len; void *ubuf_pos, *rbuf_pos; int is_short, to_host; int rescan = 0; -- cgit v1.2.3 From 6c21caa333f98e9adb93be5f01f5a4041c0d9256 Mon Sep 17 00:00:00 2001 From: Manjunath Goudar Date: Thu, 27 Oct 2016 15:52:29 +0200 Subject: USB: OHCI: make ohci-da8xx a separate driver Separate the Davinci OHCI host controller driver from ohci-hcd host code so that it can be built as a separate driver module. This work is part of enabling multi-platform kernels on ARM Tested-by: David Lechner Signed-off-by: Manjunath Goudar [Axel: adapted and rebased, fixed minor comments] Signed-off-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 4 +- drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-da8xx.c | 182 ++++++++++++++++-------------------------- drivers/usb/host/ohci-hcd.c | 18 ----- 4 files changed, 74 insertions(+), 131 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 83b6cec20b33..6361fc739306 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -479,9 +479,9 @@ config USB_OHCI_HCD_OMAP3 OMAP3 and later chips. config USB_OHCI_HCD_DAVINCI - bool "OHCI support for TI DaVinci DA8xx" + tristate "OHCI support for TI DaVinci DA8xx" depends on ARCH_DAVINCI_DA8XX - depends on USB_OHCI_HCD=y + depends on USB_OHCI_HCD select PHY_DA8XX_USB default y help diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 6ef785b0ea8f..2644537b7bcf 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o obj-$(CONFIG_USB_OHCI_HCD_S3C2410) += ohci-s3c2410.o obj-$(CONFIG_USB_OHCI_HCD_LPC32XX) += ohci-nxp.o obj-$(CONFIG_USB_OHCI_HCD_PXA27X) += ohci-pxa27x.o +obj-$(CONFIG_USB_OHCI_HCD_DAVINCI) += ohci-da8xx.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 3656d7cea58c..30c48789389e 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -11,16 +11,29 @@ * kind, whether express or implied. */ +#include +#include #include #include +#include +#include #include -#include #include #include +#include +#include +#include -#ifndef CONFIG_ARCH_DAVINCI_DA8XX -#error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX." -#endif +#include "ohci.h" + +#define DRIVER_DESC "DA8XX" +#define DRV_NAME "ohci" + +static struct hc_driver __read_mostly ohci_da8xx_hc_driver; + +static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq, + u16 wValue, u16 wIndex, char *buf, u16 wLength); +static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf); static struct clk *usb11_clk; static struct phy *usb11_phy; @@ -74,7 +87,7 @@ static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub, hub->set_power(port, 0); } -static int ohci_da8xx_init(struct usb_hcd *hcd) +static int ohci_da8xx_reset(struct usb_hcd *hcd) { struct device *dev = hcd->self.controller; struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); @@ -94,7 +107,7 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) */ ohci->num_ports = 1; - result = ohci_init(ohci); + result = ohci_setup(hcd); if (result < 0) { ohci_da8xx_disable(); return result; @@ -122,30 +135,12 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) return result; } -static void ohci_da8xx_stop(struct usb_hcd *hcd) -{ - ohci_stop(hcd); - ohci_da8xx_disable(); -} - -static int ohci_da8xx_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int result; - - result = ohci_run(ohci); - if (result < 0) - ohci_da8xx_stop(hcd); - - return result; -} - /* * Update the status data from the hub with the over-current indicator change. */ static int ohci_da8xx_hub_status_data(struct usb_hcd *hcd, char *buf) { - int length = ohci_hub_status_data(hcd, buf); + int length = orig_ohci_hub_status_data(hcd, buf); /* See if we have OCIC bit set on port 1 */ if (ocic_mask & (1 << 1)) { @@ -227,66 +222,13 @@ check_port: } } - return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); + return orig_ohci_hub_control(hcd, typeReq, wValue, + wIndex, buf, wLength); } -static const struct hc_driver ohci_da8xx_hc_driver = { - .description = hcd_name, - .product_desc = "DA8xx OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ohci_da8xx_init, - .start = ohci_da8xx_start, - .stop = ohci_da8xx_stop, - .shutdown = ohci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_da8xx_hub_status_data, - .hub_control = ohci_da8xx_hub_control, - -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - /*-------------------------------------------------------------------------*/ - -/** - * usb_hcd_da8xx_probe - initialize DA8xx-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - */ -static int usb_hcd_da8xx_probe(const struct hc_driver *driver, - struct platform_device *pdev) +static int ohci_da8xx_probe(struct platform_device *pdev) { struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); struct usb_hcd *hcd; @@ -310,7 +252,8 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, return PTR_ERR(usb11_phy); } - hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); + hcd = usb_create_hcd(&ohci_da8xx_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; @@ -324,13 +267,12 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, hcd->rsrc_start = mem->start; hcd->rsrc_len = resource_size(mem); - ohci_hcd_init(hcd_to_ohci(hcd)); - irq = platform_get_irq(pdev, 0); if (irq < 0) { error = -ENODEV; goto err; } + error = usb_add_hcd(hcd, irq, 0); if (error) goto err; @@ -349,35 +291,14 @@ err: return error; } -/** - * usb_hcd_da8xx_remove - shutdown processing for DA8xx-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_da8xx_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - */ -static inline void -usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev) +static int ohci_da8xx_remove(struct platform_device *pdev) { + struct usb_hcd *hcd = platform_get_drvdata(pdev); struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); hub->ocic_notify(NULL); usb_remove_hcd(hcd); usb_put_hcd(hcd); -} - -static int ohci_hcd_da8xx_drv_probe(struct platform_device *dev) -{ - return usb_hcd_da8xx_probe(&ohci_da8xx_hc_driver, dev); -} - -static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - usb_hcd_da8xx_remove(hcd, dev); return 0; } @@ -427,20 +348,59 @@ static int ohci_da8xx_resume(struct platform_device *dev) } #endif +static const struct ohci_driver_overrides da8xx_overrides __initconst = { + .reset = ohci_da8xx_reset, +}; + /* * Driver definition to register with platform structure. */ static struct platform_driver ohci_hcd_da8xx_driver = { - .probe = ohci_hcd_da8xx_drv_probe, - .remove = ohci_hcd_da8xx_drv_remove, + .probe = ohci_da8xx_probe, + .remove = ohci_da8xx_remove, .shutdown = usb_hcd_platform_shutdown, #ifdef CONFIG_PM .suspend = ohci_da8xx_suspend, .resume = ohci_da8xx_resume, #endif .driver = { - .name = "ohci", + .name = DRV_NAME, }, }; -MODULE_ALIAS("platform:ohci"); +static int __init ohci_da8xx_init(void) +{ + + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", DRV_NAME); + ohci_init_driver(&ohci_da8xx_hc_driver, &da8xx_overrides); + + /* + * The Davinci da8xx HW has some unusual quirks, which require + * da8xx-specific workarounds. We override certain hc_driver + * functions here to achieve that. We explicitly do not enhance + * ohci_driver_overrides to allow this more easily, since this + * is an unusual case, and we don't want to encourage others to + * override these functions by making it too easy. + */ + + orig_ohci_hub_control = ohci_da8xx_hc_driver.hub_control; + orig_ohci_hub_status_data = ohci_da8xx_hc_driver.hub_status_data; + + ohci_da8xx_hc_driver.hub_status_data = ohci_da8xx_hub_status_data; + ohci_da8xx_hc_driver.hub_control = ohci_da8xx_hub_control; + + return platform_driver_register(&ohci_hcd_da8xx_driver); +} +module_init(ohci_da8xx_init); + +static void __exit ohci_da8xx_exit(void) +{ + platform_driver_unregister(&ohci_hcd_da8xx_driver); +} +module_exit(ohci_da8xx_exit); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 1700908b84ef..8de174aa7415 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1219,11 +1219,6 @@ MODULE_LICENSE ("GPL"); #define SA1111_DRIVER ohci_hcd_sa1111_driver #endif -#ifdef CONFIG_USB_OHCI_HCD_DAVINCI -#include "ohci-da8xx.c" -#define DAVINCI_PLATFORM_DRIVER ohci_hcd_da8xx_driver -#endif - #ifdef CONFIG_USB_OHCI_HCD_PPC_OF #include "ohci-ppc-of.c" #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver @@ -1303,19 +1298,9 @@ static int __init ohci_hcd_mod_init(void) goto error_tmio; #endif -#ifdef DAVINCI_PLATFORM_DRIVER - retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER); - if (retval < 0) - goto error_davinci; -#endif - return retval; /* Error path */ -#ifdef DAVINCI_PLATFORM_DRIVER - platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); - error_davinci: -#endif #ifdef TMIO_OHCI_DRIVER platform_driver_unregister(&TMIO_OHCI_DRIVER); error_tmio: @@ -1351,9 +1336,6 @@ module_init(ohci_hcd_mod_init); static void __exit ohci_hcd_mod_exit(void) { -#ifdef DAVINCI_PLATFORM_DRIVER - platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); -#endif #ifdef TMIO_OHCI_DRIVER platform_driver_unregister(&TMIO_OHCI_DRIVER); #endif -- cgit v1.2.3 From 065d48cf403e421819b706f83a2a65b29be75ad1 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Wed, 19 Oct 2016 10:28:22 +0800 Subject: usb: xhci-mtk: make IPPC register optional Make IPPC register optional to support host side of dual-role mode, due to it is moved into common glue layer for simplification. Signed-off-by: Chunfeng Yun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mtk.c | 38 +++++++++++++++++++++++++++++++------- drivers/usb/host/xhci-mtk.h | 1 + 2 files changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 79959f17c38c..1094ebd2838f 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -94,6 +94,9 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) int ret; int i; + if (!mtk->has_ippc) + return 0; + /* power on host ip */ value = readl(&ippc->ip_pw_ctr1); value &= ~CTRL1_IP_HOST_PDN; @@ -139,6 +142,9 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk) int ret; int i; + if (!mtk->has_ippc) + return 0; + /* power down all u3 ports */ for (i = 0; i < mtk->num_u3_ports; i++) { value = readl(&ippc->u3_ctrl_p[i]); @@ -173,6 +179,9 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk) struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; u32 value; + if (!mtk->has_ippc) + return 0; + /* reset whole ip */ value = readl(&ippc->ip_pw_ctr0); value |= CTRL0_IP_SW_RST; @@ -475,6 +484,7 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) /* called during probe() after chip reset completes */ static int xhci_mtk_setup(struct usb_hcd *hcd) { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); int ret; @@ -482,12 +492,21 @@ static int xhci_mtk_setup(struct usb_hcd *hcd) ret = xhci_mtk_ssusb_config(mtk); if (ret) return ret; + } + + ret = xhci_gen_setup(hcd, xhci_mtk_quirks); + if (ret) + return ret; + + if (usb_hcd_is_primary_hcd(hcd)) { + mtk->num_u3_ports = xhci->num_usb3_ports; + mtk->num_u2_ports = xhci->num_usb2_ports; ret = xhci_mtk_sch_init(mtk); if (ret) return ret; } - return xhci_gen_setup(hcd, xhci_mtk_quirks); + return ret; } static int xhci_mtk_probe(struct platform_device *pdev) @@ -586,7 +605,7 @@ static int xhci_mtk_probe(struct platform_device *pdev) mtk->hcd = platform_get_drvdata(pdev); platform_set_drvdata(pdev, mtk); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); hcd->regs = devm_ioremap_resource(dev, res); if (IS_ERR(hcd->regs)) { ret = PTR_ERR(hcd->regs); @@ -595,11 +614,16 @@ static int xhci_mtk_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - mtk->ippc_regs = devm_ioremap_resource(dev, res); - if (IS_ERR(mtk->ippc_regs)) { - ret = PTR_ERR(mtk->ippc_regs); - goto put_usb2_hcd; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc"); + if (res) { /* ippc register is optional */ + mtk->ippc_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(mtk->ippc_regs)) { + ret = PTR_ERR(mtk->ippc_regs); + goto put_usb2_hcd; + } + mtk->has_ippc = true; + } else { + mtk->has_ippc = false; } for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) { diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index 7da677c79ea8..2845c49efe1b 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -118,6 +118,7 @@ struct xhci_hcd_mtk { struct usb_hcd *hcd; struct mu3h_sch_bw_info *sch_array; struct mu3c_ippc_regs __iomem *ippc_regs; + bool has_ippc; int num_u2_ports; int num_u3_ports; struct regulator *vusb33; -- cgit v1.2.3 From df2069acb00569a6299d6e11aa1865eeba463848 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Wed, 19 Oct 2016 10:28:23 +0800 Subject: usb: Add MediaTek USB3 DRD driver This patch adds support for the MediaTek USB3 controller integrated into MT8173. It currently supports High-Speed Peripheral Only mode. Super-Speed Peripheral, Dual-Role Device and Host Only (xHCI) modes will be added in the next patchs. Signed-off-by: Chunfeng Yun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Kconfig | 2 + drivers/usb/Makefile | 1 + drivers/usb/mtu3/Kconfig | 32 ++ drivers/usb/mtu3/Makefile | 2 + drivers/usb/mtu3/mtu3.h | 341 ++++++++++++++++ drivers/usb/mtu3/mtu3_core.c | 675 +++++++++++++++++++++++++++++++ drivers/usb/mtu3/mtu3_gadget.c | 709 +++++++++++++++++++++++++++++++++ drivers/usb/mtu3/mtu3_gadget_ep0.c | 791 +++++++++++++++++++++++++++++++++++++ drivers/usb/mtu3/mtu3_hw_regs.h | 440 +++++++++++++++++++++ drivers/usb/mtu3/mtu3_plat.c | 251 ++++++++++++ drivers/usb/mtu3/mtu3_qmu.c | 573 +++++++++++++++++++++++++++ drivers/usb/mtu3/mtu3_qmu.h | 43 ++ 12 files changed, 3860 insertions(+) create mode 100644 drivers/usb/mtu3/Kconfig create mode 100644 drivers/usb/mtu3/Makefile create mode 100644 drivers/usb/mtu3/mtu3.h create mode 100644 drivers/usb/mtu3/mtu3_core.c create mode 100644 drivers/usb/mtu3/mtu3_gadget.c create mode 100644 drivers/usb/mtu3/mtu3_gadget_ep0.c create mode 100644 drivers/usb/mtu3/mtu3_hw_regs.h create mode 100644 drivers/usb/mtu3/mtu3_plat.c create mode 100644 drivers/usb/mtu3/mtu3_qmu.c create mode 100644 drivers/usb/mtu3/mtu3_qmu.h (limited to 'drivers') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 644e978cbd3e..fbe493d44e81 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -95,6 +95,8 @@ source "drivers/usb/usbip/Kconfig" endif +source "drivers/usb/mtu3/Kconfig" + source "drivers/usb/musb/Kconfig" source "drivers/usb/dwc3/Kconfig" diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index dca78565eb55..7791af6c102c 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_USB_DWC2) += dwc2/ obj-$(CONFIG_USB_ISP1760) += isp1760/ obj-$(CONFIG_USB_MON) += mon/ +obj-$(CONFIG_USB_MTU3) += mtu3/ obj-$(CONFIG_PCI) += host/ obj-$(CONFIG_USB_EHCI_HCD) += host/ diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig new file mode 100644 index 000000000000..54dadee36f4d --- /dev/null +++ b/drivers/usb/mtu3/Kconfig @@ -0,0 +1,32 @@ +# For MTK USB3.0 IP + +config USB_MTU3 + tristate "MediaTek USB3 Dual Role controller" + depends on (USB || USB_GADGET) && HAS_DMA + depends on ARCH_MEDIATEK || COMPILE_TEST + help + Say Y or M here if your system runs on MediaTek SoCs with + Dual Role SuperSpeed USB controller. You can select usb + mode as peripheral role or host role, or both. + + If you don't know what this is, please say N. + + Choose M here to compile this driver as a module, and it + will be called mtu3.ko. + + +if USB_MTU3 +choice + bool "MTU3 Mode Selection" + default USB_MTU3_GADGET if (!USB && USB_GADGET) + +config USB_MTU3_GADGET + bool "Gadget only mode" + depends on USB_GADGET=y || USB_GADGET=USB_MTU3 + help + Select this when you want to use MTU3 in gadget mode only, + thereby the host feature will be regressed. + +endchoice + +endif diff --git a/drivers/usb/mtu3/Makefile b/drivers/usb/mtu3/Makefile new file mode 100644 index 000000000000..532c2570c58b --- /dev/null +++ b/drivers/usb/mtu3/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_USB_MTU3) += mtu3.o +mtu3-y := mtu3_plat.o mtu3_core.o mtu3_gadget_ep0.o mtu3_gadget.o mtu3_qmu.o diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h new file mode 100644 index 000000000000..ad1a1338bff1 --- /dev/null +++ b/drivers/usb/mtu3/mtu3.h @@ -0,0 +1,341 @@ +/* + * mtu3.h - MediaTek USB3 DRD header + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __MTU3_H__ +#define __MTU3_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mtu3; +struct mtu3_ep; +struct mtu3_request; + +#include "mtu3_hw_regs.h" +#include "mtu3_qmu.h" + +#define MU3D_EP_TXCR0(epnum) (U3D_TX1CSR0 + (((epnum) - 1) * 0x10)) +#define MU3D_EP_TXCR1(epnum) (U3D_TX1CSR1 + (((epnum) - 1) * 0x10)) +#define MU3D_EP_TXCR2(epnum) (U3D_TX1CSR2 + (((epnum) - 1) * 0x10)) + +#define MU3D_EP_RXCR0(epnum) (U3D_RX1CSR0 + (((epnum) - 1) * 0x10)) +#define MU3D_EP_RXCR1(epnum) (U3D_RX1CSR1 + (((epnum) - 1) * 0x10)) +#define MU3D_EP_RXCR2(epnum) (U3D_RX1CSR2 + (((epnum) - 1) * 0x10)) + +#define USB_QMU_RQCSR(epnum) (U3D_RXQCSR1 + (((epnum) - 1) * 0x10)) +#define USB_QMU_RQSAR(epnum) (U3D_RXQSAR1 + (((epnum) - 1) * 0x10)) +#define USB_QMU_RQCPR(epnum) (U3D_RXQCPR1 + (((epnum) - 1) * 0x10)) + +#define USB_QMU_TQCSR(epnum) (U3D_TXQCSR1 + (((epnum) - 1) * 0x10)) +#define USB_QMU_TQSAR(epnum) (U3D_TXQSAR1 + (((epnum) - 1) * 0x10)) +#define USB_QMU_TQCPR(epnum) (U3D_TXQCPR1 + (((epnum) - 1) * 0x10)) + +#define SSUSB_U2_CTRL(p) (U3D_SSUSB_U2_CTRL_0P + ((p) * 0x08)) + +#define MTU3_DRIVER_NAME "mtu3" +#define DMA_ADDR_INVALID (~(dma_addr_t)0) + +#define MTU3_EP_ENABLED BIT(0) +#define MTU3_EP_STALL BIT(1) +#define MTU3_EP_WEDGE BIT(2) +#define MTU3_EP_BUSY BIT(3) + +#define MTU3_U2_IP_SLOT_DEFAULT 1 + +/** + * Normally the device works on HS or SS, to simplify fifo management, + * devide fifo into some 512B parts, use bitmap to manage it; And + * 128 bits size of bitmap is large enough, that means it can manage + * up to 64KB fifo size. + * NOTE: MTU3_EP_FIFO_UNIT should be power of two + */ +#define MTU3_EP_FIFO_UNIT (1 << 9) +#define MTU3_FIFO_BIT_SIZE 128 +#define MTU3_U2_IP_EP0_FIFO_SIZE 64 + +/** + * Maximum size of ep0 response buffer for ch9 requests, + * the SET_SEL request uses 6 so far, and GET_STATUS is 2 + */ +#define EP0_RESPONSE_BUF 6 + +/* device operated link and speed got from DEVICE_CONF register */ +enum mtu3_speed { + MTU3_SPEED_INACTIVE = 0, + MTU3_SPEED_FULL = 1, + MTU3_SPEED_HIGH = 3, +}; + +/** + * @MU3D_EP0_STATE_SETUP: waits for SETUP or received a SETUP + * without data stage. + * @MU3D_EP0_STATE_TX: IN data stage + * @MU3D_EP0_STATE_RX: OUT data stage + * @MU3D_EP0_STATE_TX_END: the last IN data is transferred, and + * waits for its completion interrupt + * @MU3D_EP0_STATE_STALL: ep0 is in stall status, will be auto-cleared + * after receives a SETUP. + */ +enum mtu3_g_ep0_state { + MU3D_EP0_STATE_SETUP = 1, + MU3D_EP0_STATE_TX, + MU3D_EP0_STATE_RX, + MU3D_EP0_STATE_TX_END, + MU3D_EP0_STATE_STALL, +}; + +/** + * @base: the base address of fifo + * @limit: the bitmap size in bits + * @bitmap: fifo bitmap in unit of @MTU3_EP_FIFO_UNIT + */ +struct mtu3_fifo_info { + u32 base; + u32 limit; + DECLARE_BITMAP(bitmap, MTU3_FIFO_BIT_SIZE); +}; + +/** + * General Purpose Descriptor (GPD): + * The format of TX GPD is a little different from RX one. + * And the size of GPD is 16 bytes. + * + * @flag: + * bit0: Hardware Own (HWO) + * bit1: Buffer Descriptor Present (BDP), always 0, BD is not supported + * bit2: Bypass (BPS), 1: HW skips this GPD if HWO = 1 + * bit7: Interrupt On Completion (IOC) + * @chksum: This is used to validate the contents of this GPD; + * If TXQ_CS_EN / RXQ_CS_EN bit is set, an interrupt is issued + * when checksum validation fails; + * Checksum value is calculated over the 16 bytes of the GPD by default; + * @data_buf_len (RX ONLY): This value indicates the length of + * the assigned data buffer + * @next_gpd: Physical address of the next GPD + * @buffer: Physical address of the data buffer + * @buf_len: + * (TX): This value indicates the length of the assigned data buffer + * (RX): The total length of data received + * @ext_len: reserved + * @ext_flag: + * bit5 (TX ONLY): Zero Length Packet (ZLP), + */ +struct qmu_gpd { + __u8 flag; + __u8 chksum; + __le16 data_buf_len; + __le32 next_gpd; + __le32 buffer; + __le16 buf_len; + __u8 ext_len; + __u8 ext_flag; +} __packed; + +/** +* dma: physical base address of GPD segment +* start: virtual base address of GPD segment +* end: the last GPD element +* enqueue: the first empty GPD to use +* dequeue: the first completed GPD serviced by ISR +* NOTE: the size of GPD ring should be >= 2 +*/ +struct mtu3_gpd_ring { + dma_addr_t dma; + struct qmu_gpd *start; + struct qmu_gpd *end; + struct qmu_gpd *enqueue; + struct qmu_gpd *dequeue; +}; + +/** + * @fifo_size: it is (@slot + 1) * @fifo_seg_size + * @fifo_seg_size: it is roundup_pow_of_two(@maxp) + */ +struct mtu3_ep { + struct usb_ep ep; + char name[12]; + struct mtu3 *mtu; + u8 epnum; + u8 type; + u8 is_in; + u16 maxp; + int slot; + u32 fifo_size; + u32 fifo_addr; + u32 fifo_seg_size; + struct mtu3_fifo_info *fifo; + + struct list_head req_list; + struct mtu3_gpd_ring gpd_ring; + const struct usb_endpoint_descriptor *desc; + + int flags; + u8 wedged; + u8 busy; +}; + +struct mtu3_request { + struct usb_request request; + struct list_head list; + struct mtu3_ep *mep; + struct mtu3 *mtu; + struct qmu_gpd *gpd; + int epnum; +}; + +/** + * struct mtu3 - device driver instance data. + * @slot: MTU3_U2_IP_SLOT_DEFAULT for U2 IP + * @may_wakeup: means device's remote wakeup is enabled + * @is_self_powered: is reported in device status and the config descriptor + * @ep0_req: dummy request used while handling standard USB requests + * for GET_STATUS and SET_SEL + * @setup_buf: ep0 response buffer for GET_STATUS and SET_SEL requests + */ +struct mtu3 { + spinlock_t lock; + struct device *dev; + void __iomem *mac_base; + void __iomem *ippc_base; + struct phy *phy; + struct regulator *vusb33; + struct clk *sys_clk; + int irq; + + struct mtu3_fifo_info tx_fifo; + struct mtu3_fifo_info rx_fifo; + + struct mtu3_ep *ep_array; + struct mtu3_ep *in_eps; + struct mtu3_ep *out_eps; + struct mtu3_ep *ep0; + int num_eps; + int slot; + int active_ep; + + struct dma_pool *qmu_gpd_pool; + enum mtu3_g_ep0_state ep0_state; + struct usb_gadget g; /* the gadget */ + struct usb_gadget_driver *gadget_driver; + struct mtu3_request ep0_req; + u8 setup_buf[EP0_RESPONSE_BUF]; + + unsigned is_active:1; + unsigned may_wakeup:1; + unsigned is_self_powered:1; + unsigned test_mode:1; + unsigned softconnect:1; + + u8 address; + u8 test_mode_nr; + u32 hw_version; +}; + +static inline struct mtu3 *gadget_to_mtu3(struct usb_gadget *g) +{ + return container_of(g, struct mtu3, g); +} + +static inline int is_first_entry(const struct list_head *list, + const struct list_head *head) +{ + return list_is_last(head, list); +} + +static inline struct mtu3_request *to_mtu3_request(struct usb_request *req) +{ + return req ? container_of(req, struct mtu3_request, request) : NULL; +} + +static inline struct mtu3_ep *to_mtu3_ep(struct usb_ep *ep) +{ + return ep ? container_of(ep, struct mtu3_ep, ep) : NULL; +} + +static inline struct mtu3_request *next_request(struct mtu3_ep *mep) +{ + struct list_head *queue = &mep->req_list; + + if (list_empty(queue)) + return NULL; + + return list_first_entry(queue, struct mtu3_request, list); +} + +static inline void mtu3_writel(void __iomem *base, u32 offset, u32 data) +{ + writel(data, base + offset); +} + +static inline u32 mtu3_readl(void __iomem *base, u32 offset) +{ + return readl(base + offset); +} + +static inline void mtu3_setbits(void __iomem *base, u32 offset, u32 bits) +{ + void __iomem *addr = base + offset; + u32 tmp = readl(addr); + + writel((tmp | (bits)), addr); +} + +static inline void mtu3_clrbits(void __iomem *base, u32 offset, u32 bits) +{ + void __iomem *addr = base + offset; + u32 tmp = readl(addr); + + writel((tmp & ~(bits)), addr); +} + +int ssusb_check_clocks(struct mtu3 *mtu, u32 ex_clks); +struct usb_request *mtu3_alloc_request(struct usb_ep *ep, gfp_t gfp_flags); +void mtu3_free_request(struct usb_ep *ep, struct usb_request *req); +void mtu3_req_complete(struct mtu3_ep *mep, + struct usb_request *req, int status); + +int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep, + int interval, int burst, int mult); +void mtu3_deconfig_ep(struct mtu3 *mtu, struct mtu3_ep *mep); +void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set); +void mtu3_ep0_setup(struct mtu3 *mtu); +void mtu3_start(struct mtu3 *mtu); +void mtu3_stop(struct mtu3 *mtu); +void mtu3_hs_softconn_set(struct mtu3 *mtu, bool enable); + +int mtu3_gadget_setup(struct mtu3 *mtu); +void mtu3_gadget_cleanup(struct mtu3 *mtu); +void mtu3_gadget_reset(struct mtu3 *mtu); +void mtu3_gadget_suspend(struct mtu3 *mtu); +void mtu3_gadget_resume(struct mtu3 *mtu); +void mtu3_gadget_disconnect(struct mtu3 *mtu); +int ssusb_gadget_init(struct mtu3 *mtu); +void ssusb_gadget_exit(struct mtu3 *mtu); + +irqreturn_t mtu3_ep0_isr(struct mtu3 *mtu); +extern const struct usb_ep_ops mtu3_ep0_ops; + +#endif diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c new file mode 100644 index 000000000000..33d21dddb8a0 --- /dev/null +++ b/drivers/usb/mtu3/mtu3_core.c @@ -0,0 +1,675 @@ +/* + * mtu3_core.c - hardware access layer and gadget init/exit of + * MediaTek usb3 Dual-Role Controller Driver + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include + +#include "mtu3.h" + +static int ep_fifo_alloc(struct mtu3_ep *mep, u32 seg_size) +{ + struct mtu3_fifo_info *fifo = mep->fifo; + u32 num_bits = DIV_ROUND_UP(seg_size, MTU3_EP_FIFO_UNIT); + u32 start_bit; + + /* ensure that @mep->fifo_seg_size is power of two */ + num_bits = roundup_pow_of_two(num_bits); + if (num_bits > fifo->limit) + return -EINVAL; + + mep->fifo_seg_size = num_bits * MTU3_EP_FIFO_UNIT; + num_bits = num_bits * (mep->slot + 1); + start_bit = bitmap_find_next_zero_area(fifo->bitmap, + fifo->limit, 0, num_bits, 0); + if (start_bit >= fifo->limit) + return -EOVERFLOW; + + bitmap_set(fifo->bitmap, start_bit, num_bits); + mep->fifo_size = num_bits * MTU3_EP_FIFO_UNIT; + mep->fifo_addr = fifo->base + MTU3_EP_FIFO_UNIT * start_bit; + + dev_dbg(mep->mtu->dev, "%s fifo:%#x/%#x, start_bit: %d\n", + __func__, mep->fifo_seg_size, mep->fifo_size, start_bit); + + return mep->fifo_addr; +} + +static void ep_fifo_free(struct mtu3_ep *mep) +{ + struct mtu3_fifo_info *fifo = mep->fifo; + u32 addr = mep->fifo_addr; + u32 bits = mep->fifo_size / MTU3_EP_FIFO_UNIT; + u32 start_bit; + + if (unlikely(addr < fifo->base || bits > fifo->limit)) + return; + + start_bit = (addr - fifo->base) / MTU3_EP_FIFO_UNIT; + bitmap_clear(fifo->bitmap, start_bit, bits); + mep->fifo_size = 0; + mep->fifo_seg_size = 0; + + dev_dbg(mep->mtu->dev, "%s size:%#x/%#x, start_bit: %d\n", + __func__, mep->fifo_seg_size, mep->fifo_size, start_bit); +} + +/* set/clear U3D HS device soft connect */ +void mtu3_hs_softconn_set(struct mtu3 *mtu, bool enable) +{ + if (enable) { + mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, + SOFT_CONN | SUSPENDM_ENABLE); + } else { + mtu3_clrbits(mtu->mac_base, U3D_POWER_MANAGEMENT, + SOFT_CONN | SUSPENDM_ENABLE); + } + dev_dbg(mtu->dev, "SOFTCONN = %d\n", !!enable); +} + +/* only port0 of U2/U3 supports device mode */ +static int mtu3_device_enable(struct mtu3 *mtu) +{ + void __iomem *ibase = mtu->ippc_base; + u32 check_clk = 0; + + mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); + mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), + (SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN | + SSUSB_U2_PORT_HOST_SEL)); + mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); + + return ssusb_check_clocks(mtu, check_clk); +} + +static void mtu3_device_disable(struct mtu3 *mtu) +{ + void __iomem *ibase = mtu->ippc_base; + + mtu3_setbits(ibase, SSUSB_U2_CTRL(0), + SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN); + mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); + mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); +} + +/* reset U3D's device module. */ +static void mtu3_device_reset(struct mtu3 *mtu) +{ + void __iomem *ibase = mtu->ippc_base; + + mtu3_setbits(ibase, U3D_SSUSB_DEV_RST_CTRL, SSUSB_DEV_SW_RST); + udelay(1); + mtu3_clrbits(ibase, U3D_SSUSB_DEV_RST_CTRL, SSUSB_DEV_SW_RST); +} + +/* disable all interrupts */ +static void mtu3_intr_disable(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + + /* Disable level 1 interrupts */ + mtu3_writel(mbase, U3D_LV1IECR, ~0x0); + + /* Disable endpoint interrupts */ + mtu3_writel(mbase, U3D_EPIECR, ~0x0); +} + +static void mtu3_intr_status_clear(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + + /* Clear EP0 and Tx/Rx EPn interrupts status */ + mtu3_writel(mbase, U3D_EPISR, ~0x0); + + /* Clear U2 USB common interrupts status */ + mtu3_writel(mbase, U3D_COMMON_USB_INTR, ~0x0); + + /* Clear speed change interrupt status */ + mtu3_writel(mbase, U3D_DEV_LINK_INTR, ~0x0); +} + +/* enable system global interrupt */ +static void mtu3_intr_enable(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + u32 value; + + /*Enable level 1 interrupts (BMU, QMU, MAC3, DMA, MAC2, EPCTL) */ + value = BMU_INTR | QMU_INTR | MAC2_INTR | EP_CTRL_INTR; + mtu3_writel(mbase, U3D_LV1IESR, value); + + /* Enable U2 common USB interrupts */ + value = SUSPEND_INTR | RESUME_INTR | RESET_INTR; + mtu3_writel(mbase, U3D_COMMON_USB_INTR_ENABLE, value); + + /* Enable QMU interrupts. */ + value = TXQ_CSERR_INT | TXQ_LENERR_INT | RXQ_CSERR_INT | + RXQ_LENERR_INT | RXQ_ZLPERR_INT; + mtu3_writel(mbase, U3D_QIESR1, value); + + /* Enable speed change interrupt */ + mtu3_writel(mbase, U3D_DEV_LINK_INTR_ENABLE, SSUSB_DEV_SPEED_CHG_INTR); +} + +/* set/clear the stall and toggle bits for non-ep0 */ +void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set) +{ + struct mtu3 *mtu = mep->mtu; + void __iomem *mbase = mtu->mac_base; + u8 epnum = mep->epnum; + u32 csr; + + if (mep->is_in) { /* TX */ + csr = mtu3_readl(mbase, MU3D_EP_TXCR0(epnum)) & TX_W1C_BITS; + if (set) + csr |= TX_SENDSTALL; + else + csr = (csr & (~TX_SENDSTALL)) | TX_SENTSTALL; + mtu3_writel(mbase, MU3D_EP_TXCR0(epnum), csr); + } else { /* RX */ + csr = mtu3_readl(mbase, MU3D_EP_RXCR0(epnum)) & RX_W1C_BITS; + if (set) + csr |= RX_SENDSTALL; + else + csr = (csr & (~RX_SENDSTALL)) | RX_SENTSTALL; + mtu3_writel(mbase, MU3D_EP_RXCR0(epnum), csr); + } + + if (!set) { + mtu3_setbits(mbase, U3D_EP_RST, EP_RST(mep->is_in, epnum)); + mtu3_clrbits(mbase, U3D_EP_RST, EP_RST(mep->is_in, epnum)); + mep->flags &= ~MTU3_EP_STALL; + } else { + mep->flags |= MTU3_EP_STALL; + } + + dev_dbg(mtu->dev, "%s: %s\n", mep->name, + set ? "SEND STALL" : "CLEAR STALL, with EP RESET"); +} + +void mtu3_start(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + + dev_dbg(mtu->dev, "%s devctl 0x%x\n", __func__, + mtu3_readl(mbase, U3D_DEVICE_CONTROL)); + + mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); + + /* Initialize the default interrupts */ + mtu3_intr_enable(mtu); + + mtu->is_active = 1; + + if (mtu->softconnect) + mtu3_hs_softconn_set(mtu, 1); +} + +void mtu3_stop(struct mtu3 *mtu) +{ + dev_dbg(mtu->dev, "%s\n", __func__); + + mtu3_intr_disable(mtu); + mtu3_intr_status_clear(mtu); + + if (mtu->softconnect) + mtu3_hs_softconn_set(mtu, 0); + + mtu->is_active = 0; + mtu3_setbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); +} + +/* for non-ep0 */ +int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep, + int interval, int burst, int mult) +{ + void __iomem *mbase = mtu->mac_base; + int epnum = mep->epnum; + u32 csr0, csr1, csr2; + int fifo_sgsz, fifo_addr; + int num_pkts; + + fifo_addr = ep_fifo_alloc(mep, mep->maxp); + if (fifo_addr < 0) { + dev_err(mtu->dev, "alloc ep fifo failed(%d)\n", mep->maxp); + return -ENOMEM; + } + fifo_sgsz = ilog2(mep->fifo_seg_size); + dev_dbg(mtu->dev, "%s fifosz: %x(%x/%x)\n", __func__, fifo_sgsz, + mep->fifo_seg_size, mep->fifo_size); + + if (mep->is_in) { + csr0 = TX_TXMAXPKTSZ(mep->maxp); + csr0 |= TX_DMAREQEN; + + num_pkts = (burst + 1) * (mult + 1) - 1; + csr1 = TX_SS_BURST(burst) | TX_SLOT(mep->slot); + csr1 |= TX_MAX_PKT(num_pkts) | TX_MULT(mult); + + csr2 = TX_FIFOADDR(fifo_addr >> 4); + csr2 |= TX_FIFOSEGSIZE(fifo_sgsz); + + switch (mep->type) { + case USB_ENDPOINT_XFER_BULK: + csr1 |= TX_TYPE(TYPE_BULK); + break; + case USB_ENDPOINT_XFER_ISOC: + csr1 |= TX_TYPE(TYPE_ISO); + csr2 |= TX_BINTERVAL(interval); + break; + case USB_ENDPOINT_XFER_INT: + csr1 |= TX_TYPE(TYPE_INT); + csr2 |= TX_BINTERVAL(interval); + break; + } + + /* Enable QMU Done interrupt */ + mtu3_setbits(mbase, U3D_QIESR0, QMU_TX_DONE_INT(epnum)); + + mtu3_writel(mbase, MU3D_EP_TXCR0(epnum), csr0); + mtu3_writel(mbase, MU3D_EP_TXCR1(epnum), csr1); + mtu3_writel(mbase, MU3D_EP_TXCR2(epnum), csr2); + + dev_dbg(mtu->dev, "U3D_TX%d CSR0:%#x, CSR1:%#x, CSR2:%#x\n", + epnum, mtu3_readl(mbase, MU3D_EP_TXCR0(epnum)), + mtu3_readl(mbase, MU3D_EP_TXCR1(epnum)), + mtu3_readl(mbase, MU3D_EP_TXCR2(epnum))); + } else { + csr0 = RX_RXMAXPKTSZ(mep->maxp); + csr0 |= RX_DMAREQEN; + + num_pkts = (burst + 1) * (mult + 1) - 1; + csr1 = RX_SS_BURST(burst) | RX_SLOT(mep->slot); + csr1 |= RX_MAX_PKT(num_pkts) | RX_MULT(mult); + + csr2 = RX_FIFOADDR(fifo_addr >> 4); + csr2 |= RX_FIFOSEGSIZE(fifo_sgsz); + + switch (mep->type) { + case USB_ENDPOINT_XFER_BULK: + csr1 |= RX_TYPE(TYPE_BULK); + break; + case USB_ENDPOINT_XFER_ISOC: + csr1 |= RX_TYPE(TYPE_ISO); + csr2 |= RX_BINTERVAL(interval); + break; + case USB_ENDPOINT_XFER_INT: + csr1 |= RX_TYPE(TYPE_INT); + csr2 |= RX_BINTERVAL(interval); + break; + } + + /*Enable QMU Done interrupt */ + mtu3_setbits(mbase, U3D_QIESR0, QMU_RX_DONE_INT(epnum)); + + mtu3_writel(mbase, MU3D_EP_RXCR0(epnum), csr0); + mtu3_writel(mbase, MU3D_EP_RXCR1(epnum), csr1); + mtu3_writel(mbase, MU3D_EP_RXCR2(epnum), csr2); + + dev_dbg(mtu->dev, "U3D_RX%d CSR0:%#x, CSR1:%#x, CSR2:%#x\n", + epnum, mtu3_readl(mbase, MU3D_EP_RXCR0(epnum)), + mtu3_readl(mbase, MU3D_EP_RXCR1(epnum)), + mtu3_readl(mbase, MU3D_EP_RXCR2(epnum))); + } + + dev_dbg(mtu->dev, "csr0:%#x, csr1:%#x, csr2:%#x\n", csr0, csr1, csr2); + dev_dbg(mtu->dev, "%s: %s, fifo-addr:%#x, fifo-size:%#x(%#x/%#x)\n", + __func__, mep->name, mep->fifo_addr, mep->fifo_size, + fifo_sgsz, mep->fifo_seg_size); + + return 0; +} + +/* for non-ep0 */ +void mtu3_deconfig_ep(struct mtu3 *mtu, struct mtu3_ep *mep) +{ + void __iomem *mbase = mtu->mac_base; + int epnum = mep->epnum; + + if (mep->is_in) { + mtu3_writel(mbase, MU3D_EP_TXCR0(epnum), 0); + mtu3_writel(mbase, MU3D_EP_TXCR1(epnum), 0); + mtu3_writel(mbase, MU3D_EP_TXCR2(epnum), 0); + mtu3_setbits(mbase, U3D_QIECR0, QMU_TX_DONE_INT(epnum)); + } else { + mtu3_writel(mbase, MU3D_EP_RXCR0(epnum), 0); + mtu3_writel(mbase, MU3D_EP_RXCR1(epnum), 0); + mtu3_writel(mbase, MU3D_EP_RXCR2(epnum), 0); + mtu3_setbits(mbase, U3D_QIECR0, QMU_RX_DONE_INT(epnum)); + } + + ep_fifo_free(mep); + + dev_dbg(mtu->dev, "%s: %s\n", __func__, mep->name); +} + +/* + * 1. when supports only HS, the fifo is shared for all EPs, and + * the capability registers of @EPNTXFFSZ or @EPNRXFFSZ indicate + * the total fifo size of non-ep0, and ep0's is fixed to 64B, + * so the total fifo size is 64B + @EPNTXFFSZ; + * Due to the first 64B should be reserved for EP0, non-ep0's fifo + * starts from offset 64 and are divided into two equal parts for + * TX or RX EPs for simplification. + */ +static void get_ep_fifo_config(struct mtu3 *mtu) +{ + struct mtu3_fifo_info *tx_fifo; + struct mtu3_fifo_info *rx_fifo; + u32 fifosize; + + fifosize = mtu3_readl(mtu->mac_base, U3D_CAP_EPNTXFFSZ); + tx_fifo = &mtu->tx_fifo; + tx_fifo->base = MTU3_U2_IP_EP0_FIFO_SIZE; + tx_fifo->limit = (fifosize / MTU3_EP_FIFO_UNIT) >> 1; + bitmap_zero(tx_fifo->bitmap, MTU3_FIFO_BIT_SIZE); + + rx_fifo = &mtu->rx_fifo; + rx_fifo->base = + tx_fifo->base + tx_fifo->limit * MTU3_EP_FIFO_UNIT; + rx_fifo->limit = tx_fifo->limit; + bitmap_zero(rx_fifo->bitmap, MTU3_FIFO_BIT_SIZE); + mtu->slot = MTU3_U2_IP_SLOT_DEFAULT; + + dev_dbg(mtu->dev, "%s, TX: base-%d, limit-%d; RX: base-%d, limit-%d\n", + __func__, tx_fifo->base, tx_fifo->limit, + rx_fifo->base, rx_fifo->limit); +} + +void mtu3_ep0_setup(struct mtu3 *mtu) +{ + u32 maxpacket = mtu->g.ep0->maxpacket; + u32 csr; + + dev_dbg(mtu->dev, "%s maxpacket: %d\n", __func__, maxpacket); + + csr = mtu3_readl(mtu->mac_base, U3D_EP0CSR); + csr &= ~EP0_MAXPKTSZ_MSK; + csr |= EP0_MAXPKTSZ(maxpacket); + csr &= EP0_W1C_BITS; + mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr); + + /* Enable EP0 interrupt */ + mtu3_writel(mtu->mac_base, U3D_EPIESR, EP0ISR); +} + +static int mtu3_mem_alloc(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + struct mtu3_ep *ep_array; + int in_ep_num, out_ep_num; + u32 cap_epinfo; + int ret; + int i; + + mtu->hw_version = mtu3_readl(mtu->ippc_base, U3D_SSUSB_HW_ID); + + cap_epinfo = mtu3_readl(mbase, U3D_CAP_EPINFO); + in_ep_num = CAP_TX_EP_NUM(cap_epinfo); + out_ep_num = CAP_RX_EP_NUM(cap_epinfo); + + dev_info(mtu->dev, "IP version 0x%x\n", mtu->hw_version); + dev_info(mtu->dev, "fifosz/epnum: Tx=%#x/%d, Rx=%#x/%d\n", + mtu3_readl(mbase, U3D_CAP_EPNTXFFSZ), in_ep_num, + mtu3_readl(mbase, U3D_CAP_EPNRXFFSZ), out_ep_num); + + /* one for ep0, another is reserved */ + mtu->num_eps = min(in_ep_num, out_ep_num) + 1; + ep_array = kcalloc(mtu->num_eps * 2, sizeof(*ep_array), GFP_KERNEL); + if (ep_array == NULL) + return -ENOMEM; + + mtu->ep_array = ep_array; + mtu->in_eps = ep_array; + mtu->out_eps = &ep_array[mtu->num_eps]; + /* ep0 uses in_eps[0], out_eps[0] is reserved */ + mtu->ep0 = mtu->in_eps; + + mtu->ep0->mtu = mtu; + mtu->ep0->epnum = 0; + + for (i = 1; i < mtu->num_eps; i++) { + struct mtu3_ep *mep = mtu->in_eps + i; + + mep->fifo = &mtu->tx_fifo; + mep = mtu->out_eps + i; + mep->fifo = &mtu->rx_fifo; + } + + get_ep_fifo_config(mtu); + + ret = mtu3_qmu_init(mtu); + if (ret) + kfree(mtu->ep_array); + + return ret; +} + +static void mtu3_mem_free(struct mtu3 *mtu) +{ + mtu3_qmu_exit(mtu); + kfree(mtu->ep_array); +} + +static void mtu3_regs_init(struct mtu3 *mtu) +{ + + void __iomem *mbase = mtu->mac_base; + + /* be sure interrupts are disabled before registration of ISR */ + mtu3_intr_disable(mtu); + mtu3_intr_status_clear(mtu); + + mtu3_clrbits(mbase, U3D_USB3_CONFIG, USB3_EN); + /* HS/FS detected by HW */ + mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); + + /* delay about 0.1us from detecting reset to send chirp-K */ + mtu3_clrbits(mbase, U3D_LINK_RESET_INFO, WTCHRP_MSK); + + /* U2/U3 detected by HW */ + mtu3_writel(mbase, U3D_DEVICE_CONF, 0); + + /* enable QMU 16B checksum */ + mtu3_setbits(mbase, U3D_QCR0, QMU_CS16B_EN); + + /* vbus detected by HW */ + mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); +} + +static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + enum usb_device_speed udev_speed; + u32 maxpkt = 64; + u32 link; + u32 speed; + + link = mtu3_readl(mbase, U3D_DEV_LINK_INTR); + link &= mtu3_readl(mbase, U3D_DEV_LINK_INTR_ENABLE); + mtu3_writel(mbase, U3D_DEV_LINK_INTR, link); /* W1C */ + dev_dbg(mtu->dev, "=== LINK[%x] ===\n", link); + + if (!(link & SSUSB_DEV_SPEED_CHG_INTR)) + return IRQ_NONE; + + speed = SSUSB_DEV_SPEED(mtu3_readl(mbase, U3D_DEVICE_CONF)); + + switch (speed) { + case MTU3_SPEED_FULL: + udev_speed = USB_SPEED_FULL; + /*BESLCK = 4 < BESLCK_U3 = 10 < BESLDCK = 15 */ + mtu3_writel(mbase, U3D_USB20_LPM_PARAMETER, LPM_BESLDCK(0xf) + | LPM_BESLCK(4) | LPM_BESLCK_U3(0xa)); + mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, + LPM_BESL_STALL | LPM_BESLD_STALL); + break; + case MTU3_SPEED_HIGH: + udev_speed = USB_SPEED_HIGH; + /*BESLCK = 4 < BESLCK_U3 = 10 < BESLDCK = 15 */ + mtu3_writel(mbase, U3D_USB20_LPM_PARAMETER, LPM_BESLDCK(0xf) + | LPM_BESLCK(4) | LPM_BESLCK_U3(0xa)); + mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, + LPM_BESL_STALL | LPM_BESLD_STALL); + break; + default: + udev_speed = USB_SPEED_UNKNOWN; + break; + } + dev_dbg(mtu->dev, "%s: %s\n", __func__, usb_speed_string(udev_speed)); + + mtu->g.speed = udev_speed; + mtu->g.ep0->maxpacket = maxpkt; + mtu->ep0_state = MU3D_EP0_STATE_SETUP; + + if (udev_speed == USB_SPEED_UNKNOWN) + mtu3_gadget_disconnect(mtu); + else + mtu3_ep0_setup(mtu); + + return IRQ_HANDLED; +} + +static irqreturn_t mtu3_u2_common_isr(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + u32 u2comm; + + u2comm = mtu3_readl(mbase, U3D_COMMON_USB_INTR); + u2comm &= mtu3_readl(mbase, U3D_COMMON_USB_INTR_ENABLE); + mtu3_writel(mbase, U3D_COMMON_USB_INTR, u2comm); /* W1C */ + dev_dbg(mtu->dev, "=== U2COMM[%x] ===\n", u2comm); + + if (u2comm & SUSPEND_INTR) + mtu3_gadget_suspend(mtu); + + if (u2comm & RESUME_INTR) + mtu3_gadget_resume(mtu); + + if (u2comm & RESET_INTR) + mtu3_gadget_reset(mtu); + + return IRQ_HANDLED; +} + +irqreturn_t mtu3_irq(int irq, void *data) +{ + struct mtu3 *mtu = (struct mtu3 *)data; + unsigned long flags; + u32 level1; + + spin_lock_irqsave(&mtu->lock, flags); + + /* U3D_LV1ISR is RU */ + level1 = mtu3_readl(mtu->mac_base, U3D_LV1ISR); + level1 &= mtu3_readl(mtu->mac_base, U3D_LV1IER); + + if (level1 & EP_CTRL_INTR) + mtu3_link_isr(mtu); + + if (level1 & MAC2_INTR) + mtu3_u2_common_isr(mtu); + + if (level1 & BMU_INTR) + mtu3_ep0_isr(mtu); + + if (level1 & QMU_INTR) + mtu3_qmu_isr(mtu); + + spin_unlock_irqrestore(&mtu->lock, flags); + + return IRQ_HANDLED; +} + +static int mtu3_hw_init(struct mtu3 *mtu) +{ + int ret; + + mtu3_device_reset(mtu); + + ret = mtu3_device_enable(mtu); + if (ret) { + dev_err(mtu->dev, "device enable failed %d\n", ret); + return ret; + } + + ret = mtu3_mem_alloc(mtu); + if (ret) + return -ENOMEM; + + mtu3_regs_init(mtu); + + return 0; +} + +static void mtu3_hw_exit(struct mtu3 *mtu) +{ + mtu3_device_disable(mtu); + mtu3_mem_free(mtu); +} + +/*-------------------------------------------------------------------------*/ + +int ssusb_gadget_init(struct mtu3 *mtu) +{ + struct device *dev = mtu->dev; + int ret; + + ret = mtu3_hw_init(mtu); + if (ret) { + dev_err(dev, "mtu3 hw init failed:%d\n", ret); + return ret; + } + + ret = devm_request_irq(dev, mtu->irq, mtu3_irq, 0, dev_name(dev), mtu); + if (ret) { + dev_err(dev, "request irq %d failed!\n", mtu->irq); + goto irq_err; + } + + device_init_wakeup(dev, true); + + ret = mtu3_gadget_setup(mtu); + if (ret) { + dev_err(dev, "mtu3 gadget init failed:%d\n", ret); + goto gadget_err; + } + + dev_dbg(dev, " %s() done...\n", __func__); + + return 0; + +gadget_err: + device_init_wakeup(dev, false); + +irq_err: + mtu3_hw_exit(mtu); + dev_err(dev, " %s() fail...\n", __func__); + + return ret; +} + +void ssusb_gadget_exit(struct mtu3 *mtu) +{ + mtu3_gadget_cleanup(mtu); + device_init_wakeup(mtu->dev, false); + mtu3_hw_exit(mtu); +} diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c new file mode 100644 index 000000000000..0e25e0f9e605 --- /dev/null +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -0,0 +1,709 @@ +/* + * mtu3_gadget.c - MediaTek usb3 DRD peripheral support + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "mtu3.h" + +void mtu3_req_complete(struct mtu3_ep *mep, + struct usb_request *req, int status) +__releases(mep->mtu->lock) +__acquires(mep->mtu->lock) +{ + struct mtu3_request *mreq; + struct mtu3 *mtu; + int busy = mep->busy; + + mreq = to_mtu3_request(req); + list_del(&mreq->list); + if (mreq->request.status == -EINPROGRESS) + mreq->request.status = status; + + mtu = mreq->mtu; + mep->busy = 1; + spin_unlock(&mtu->lock); + + /* ep0 makes use of PIO, needn't unmap it */ + if (mep->epnum) + usb_gadget_unmap_request(&mtu->g, req, mep->is_in); + + dev_dbg(mtu->dev, "%s complete req: %p, sts %d, %d/%d\n", mep->name, + req, req->status, mreq->request.actual, mreq->request.length); + + usb_gadget_giveback_request(&mep->ep, &mreq->request); + + spin_lock(&mtu->lock); + mep->busy = busy; +} + +static void nuke(struct mtu3_ep *mep, const int status) +{ + struct mtu3_request *mreq = NULL; + + mep->busy = 1; + if (list_empty(&mep->req_list)) + return; + + dev_dbg(mep->mtu->dev, "abort %s's req: sts %d\n", mep->name, status); + + /* exclude EP0 */ + if (mep->epnum) + mtu3_qmu_flush(mep); + + while (!list_empty(&mep->req_list)) { + mreq = list_first_entry(&mep->req_list, + struct mtu3_request, list); + mtu3_req_complete(mep, &mreq->request, status); + } +} + +static int mtu3_ep_enable(struct mtu3_ep *mep) +{ + const struct usb_endpoint_descriptor *desc; + struct mtu3 *mtu = mep->mtu; + u32 interval = 0; + u32 mult = 0; + u32 burst = 0; + int max_packet; + int ret; + + desc = mep->desc; + mep->type = usb_endpoint_type(desc); + max_packet = usb_endpoint_maxp(desc); + mep->maxp = max_packet & GENMASK(10, 0); + + switch (mtu->g.speed) { + case USB_SPEED_HIGH: + if (usb_endpoint_xfer_isoc(desc) || + usb_endpoint_xfer_int(desc)) { + interval = desc->bInterval; + interval = clamp_val(interval, 1, 16) - 1; + burst = (max_packet & GENMASK(12, 11)) >> 11; + } + break; + default: + break; /*others are ignored */ + } + + dev_dbg(mtu->dev, "%s maxp:%d, interval:%d, burst:%d, mult:%d\n", + __func__, mep->maxp, interval, burst, mult); + + mep->ep.maxpacket = mep->maxp; + mep->ep.desc = desc; + + /* slot mainly affects bulk/isoc transfer, so ignore int */ + mep->slot = usb_endpoint_xfer_int(desc) ? 0 : mtu->slot; + + ret = mtu3_config_ep(mtu, mep, interval, burst, mult); + if (ret < 0) + return ret; + + ret = mtu3_gpd_ring_alloc(mep); + if (ret < 0) { + mtu3_deconfig_ep(mtu, mep); + return ret; + } + + mtu3_qmu_start(mep); + + return 0; +} + +static int mtu3_ep_disable(struct mtu3_ep *mep) +{ + struct mtu3 *mtu = mep->mtu; + + mtu3_qmu_stop(mep); + + /* abort all pending requests */ + nuke(mep, -ESHUTDOWN); + mtu3_deconfig_ep(mtu, mep); + mtu3_gpd_ring_free(mep); + + mep->desc = NULL; + mep->ep.desc = NULL; + mep->type = 0; + mep->flags = 0; + + return 0; +} + +static int mtu3_gadget_ep_enable(struct usb_ep *ep, + const struct usb_endpoint_descriptor *desc) +{ + struct mtu3_ep *mep; + struct mtu3 *mtu; + unsigned long flags; + int ret = -EINVAL; + + if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { + pr_debug("%s invalid parameters\n", __func__); + return -EINVAL; + } + + if (!desc->wMaxPacketSize) { + pr_debug("%s missing wMaxPacketSize\n", __func__); + return -EINVAL; + } + mep = to_mtu3_ep(ep); + mtu = mep->mtu; + + /* check ep number and direction against endpoint */ + if (usb_endpoint_num(desc) != mep->epnum) + return -EINVAL; + + if (!!usb_endpoint_dir_in(desc) ^ !!mep->is_in) + return -EINVAL; + + dev_dbg(mtu->dev, "%s %s\n", __func__, ep->name); + + if (mep->flags & MTU3_EP_ENABLED) { + dev_WARN_ONCE(mtu->dev, true, "%s is already enabled\n", + mep->name); + return 0; + } + + spin_lock_irqsave(&mtu->lock, flags); + mep->desc = desc; + + ret = mtu3_ep_enable(mep); + if (ret) + goto error; + + mep->busy = 0; + mep->wedged = 0; + mep->flags |= MTU3_EP_ENABLED; + mtu->active_ep++; + +error: + spin_unlock_irqrestore(&mtu->lock, flags); + + dev_dbg(mtu->dev, "%s active_ep=%d\n", __func__, mtu->active_ep); + + return ret; +} + +static int mtu3_gadget_ep_disable(struct usb_ep *ep) +{ + struct mtu3_ep *mep = to_mtu3_ep(ep); + struct mtu3 *mtu = mep->mtu; + unsigned long flags; + + dev_dbg(mtu->dev, "%s %s\n", __func__, mep->name); + + if (!(mep->flags & MTU3_EP_ENABLED)) { + dev_warn(mtu->dev, "%s is already disabled\n", mep->name); + return 0; + } + + spin_lock_irqsave(&mtu->lock, flags); + mtu3_ep_disable(mep); + mep->flags &= ~MTU3_EP_ENABLED; + mtu->active_ep--; + spin_unlock_irqrestore(&(mtu->lock), flags); + + dev_dbg(mtu->dev, "%s active_ep=%d, mtu3 is_active=%d\n", + __func__, mtu->active_ep, mtu->is_active); + + return 0; +} + +struct usb_request *mtu3_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) +{ + struct mtu3_ep *mep = to_mtu3_ep(ep); + struct mtu3_request *mreq; + + mreq = kzalloc(sizeof(*mreq), gfp_flags); + if (!mreq) + return NULL; + + mreq->request.dma = DMA_ADDR_INVALID; + mreq->epnum = mep->epnum; + mreq->mep = mep; + + return &mreq->request; +} + +void mtu3_free_request(struct usb_ep *ep, struct usb_request *req) +{ + kfree(to_mtu3_request(req)); +} + +static int mtu3_gadget_queue(struct usb_ep *ep, + struct usb_request *req, gfp_t gfp_flags) +{ + struct mtu3_ep *mep; + struct mtu3_request *mreq; + struct mtu3 *mtu; + unsigned long flags; + int ret = 0; + + if (!ep || !req) + return -EINVAL; + + if (!req->buf) + return -ENODATA; + + mep = to_mtu3_ep(ep); + mtu = mep->mtu; + mreq = to_mtu3_request(req); + mreq->mtu = mtu; + + if (mreq->mep != mep) + return -EINVAL; + + dev_dbg(mtu->dev, "%s %s EP%d(%s), req=%p, maxp=%d, len#%d\n", + __func__, mep->is_in ? "TX" : "RX", mreq->epnum, ep->name, + mreq, ep->maxpacket, mreq->request.length); + + if (req->length > GPD_BUF_SIZE) { + dev_warn(mtu->dev, + "req length > supported MAX:%d requested:%d\n", + GPD_BUF_SIZE, req->length); + return -EOPNOTSUPP; + } + + /* don't queue if the ep is down */ + if (!mep->desc) { + dev_dbg(mtu->dev, "req=%p queued to %s while it's disabled\n", + req, ep->name); + return -ESHUTDOWN; + } + + mreq->request.actual = 0; + mreq->request.status = -EINPROGRESS; + + ret = usb_gadget_map_request(&mtu->g, req, mep->is_in); + if (ret) { + dev_err(mtu->dev, "dma mapping failed\n"); + return ret; + } + + spin_lock_irqsave(&mtu->lock, flags); + + if (mtu3_prepare_transfer(mep)) { + ret = -EAGAIN; + goto error; + } + + list_add_tail(&mreq->list, &mep->req_list); + mtu3_insert_gpd(mep, mreq); + mtu3_qmu_resume(mep); + +error: + spin_unlock_irqrestore(&mtu->lock, flags); + + return ret; +} + +static int mtu3_gadget_dequeue(struct usb_ep *ep, struct usb_request *req) +{ + struct mtu3_ep *mep = to_mtu3_ep(ep); + struct mtu3_request *mreq = to_mtu3_request(req); + struct mtu3_request *r; + unsigned long flags; + int ret = 0; + struct mtu3 *mtu = mep->mtu; + + if (!ep || !req || mreq->mep != mep) + return -EINVAL; + + dev_dbg(mtu->dev, "%s : req=%p\n", __func__, req); + + spin_lock_irqsave(&mtu->lock, flags); + + list_for_each_entry(r, &mep->req_list, list) { + if (r == mreq) + break; + } + if (r != mreq) { + dev_dbg(mtu->dev, "req=%p not queued to %s\n", req, ep->name); + ret = -EINVAL; + goto done; + } + + mtu3_qmu_flush(mep); /* REVISIT: set BPS ?? */ + mtu3_req_complete(mep, req, -ECONNRESET); + mtu3_qmu_start(mep); + +done: + spin_unlock_irqrestore(&mtu->lock, flags); + + return ret; +} + +/* + * Set or clear the halt bit of an EP. + * A halted EP won't TX/RX any data but will queue requests. + */ +static int mtu3_gadget_ep_set_halt(struct usb_ep *ep, int value) +{ + struct mtu3_ep *mep = to_mtu3_ep(ep); + struct mtu3 *mtu = mep->mtu; + struct mtu3_request *mreq; + unsigned long flags; + int ret = 0; + + if (!ep) + return -EINVAL; + + dev_dbg(mtu->dev, "%s : %s...", __func__, ep->name); + + spin_lock_irqsave(&mtu->lock, flags); + + if (mep->type == USB_ENDPOINT_XFER_ISOC) { + ret = -EINVAL; + goto done; + } + + mreq = next_request(mep); + if (value) { + /* + * If there is not request for TX-EP, QMU will not transfer + * data to TX-FIFO, so no need check whether TX-FIFO + * holds bytes or not here + */ + if (mreq) { + dev_dbg(mtu->dev, "req in progress, cannot halt %s\n", + ep->name); + ret = -EAGAIN; + goto done; + } + } else { + mep->wedged = 0; + } + + dev_dbg(mtu->dev, "%s %s stall\n", ep->name, value ? "set" : "clear"); + + mtu3_ep_stall_set(mep, value); + +done: + spin_unlock_irqrestore(&mtu->lock, flags); + + return ret; +} + +/* Sets the halt feature with the clear requests ignored */ +static int mtu3_gadget_ep_set_wedge(struct usb_ep *ep) +{ + struct mtu3_ep *mep = to_mtu3_ep(ep); + + if (!ep) + return -EINVAL; + + mep->wedged = 1; + + return usb_ep_set_halt(ep); +} + +static const struct usb_ep_ops mtu3_ep_ops = { + .enable = mtu3_gadget_ep_enable, + .disable = mtu3_gadget_ep_disable, + .alloc_request = mtu3_alloc_request, + .free_request = mtu3_free_request, + .queue = mtu3_gadget_queue, + .dequeue = mtu3_gadget_dequeue, + .set_halt = mtu3_gadget_ep_set_halt, + .set_wedge = mtu3_gadget_ep_set_wedge, +}; + +static int mtu3_gadget_get_frame(struct usb_gadget *gadget) +{ + struct mtu3 *mtu = gadget_to_mtu3(gadget); + + return (int)mtu3_readl(mtu->mac_base, U3D_USB20_FRAME_NUM); +} + +static int mtu3_gadget_wakeup(struct usb_gadget *gadget) +{ + struct mtu3 *mtu = gadget_to_mtu3(gadget); + unsigned long flags; + + dev_dbg(mtu->dev, "%s\n", __func__); + + /* remote wakeup feature is not enabled by host */ + if (!mtu->may_wakeup) + return -EOPNOTSUPP; + + spin_lock_irqsave(&mtu->lock, flags); + + mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME); + spin_unlock_irqrestore(&mtu->lock, flags); + usleep_range(10000, 11000); + spin_lock_irqsave(&mtu->lock, flags); + mtu3_clrbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME); + + spin_unlock_irqrestore(&mtu->lock, flags); + return 0; +} + +static int mtu3_gadget_set_self_powered(struct usb_gadget *gadget, + int is_selfpowered) +{ + struct mtu3 *mtu = gadget_to_mtu3(gadget); + + mtu->is_self_powered = !!is_selfpowered; + return 0; +} + +static int mtu3_gadget_pullup(struct usb_gadget *gadget, int is_on) +{ + struct mtu3 *mtu = gadget_to_mtu3(gadget); + unsigned long flags; + + dev_dbg(mtu->dev, "%s (%s) for %sactive device\n", __func__, + is_on ? "on" : "off", mtu->is_active ? "" : "in"); + + /* we'd rather not pullup unless the device is active. */ + spin_lock_irqsave(&mtu->lock, flags); + + is_on = !!is_on; + if (!mtu->is_active) { + /* save it for mtu3_start() to process the request */ + mtu->softconnect = is_on; + } else if (is_on != mtu->softconnect) { + mtu->softconnect = is_on; + mtu3_hs_softconn_set(mtu, is_on); + } + + spin_unlock_irqrestore(&mtu->lock, flags); + + return 0; +} + +static int mtu3_gadget_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) +{ + struct mtu3 *mtu = gadget_to_mtu3(gadget); + unsigned long flags; + + if (mtu->gadget_driver) { + dev_err(mtu->dev, "%s is already bound to %s\n", + mtu->g.name, mtu->gadget_driver->driver.name); + return -EBUSY; + } + + dev_dbg(mtu->dev, "bind driver %s\n", driver->function); + + spin_lock_irqsave(&mtu->lock, flags); + + mtu->softconnect = 0; + mtu->gadget_driver = driver; + + mtu3_start(mtu); + + spin_unlock_irqrestore(&mtu->lock, flags); + + return 0; +} + +static void stop_activity(struct mtu3 *mtu) +{ + struct usb_gadget_driver *driver = mtu->gadget_driver; + int i; + + /* don't disconnect if it's not connected */ + if (mtu->g.speed == USB_SPEED_UNKNOWN) + driver = NULL; + else + mtu->g.speed = USB_SPEED_UNKNOWN; + + /* deactivate the hardware */ + if (mtu->softconnect) { + mtu->softconnect = 0; + mtu3_hs_softconn_set(mtu, 0); + } + + /* + * killing any outstanding requests will quiesce the driver; + * then report disconnect + */ + nuke(mtu->ep0, -ESHUTDOWN); + for (i = 1; i < mtu->num_eps; i++) { + nuke(mtu->in_eps + i, -ESHUTDOWN); + nuke(mtu->out_eps + i, -ESHUTDOWN); + } + + if (driver) { + spin_unlock(&mtu->lock); + driver->disconnect(&mtu->g); + spin_lock(&mtu->lock); + } +} + +static int mtu3_gadget_stop(struct usb_gadget *g) +{ + struct mtu3 *mtu = gadget_to_mtu3(g); + unsigned long flags; + + dev_dbg(mtu->dev, "%s\n", __func__); + + spin_lock_irqsave(&mtu->lock, flags); + + stop_activity(mtu); + mtu->gadget_driver = NULL; + + mtu3_stop(mtu); + + spin_unlock_irqrestore(&mtu->lock, flags); + + return 0; +} + +static const struct usb_gadget_ops mtu3_gadget_ops = { + .get_frame = mtu3_gadget_get_frame, + .wakeup = mtu3_gadget_wakeup, + .set_selfpowered = mtu3_gadget_set_self_powered, + .pullup = mtu3_gadget_pullup, + .udc_start = mtu3_gadget_start, + .udc_stop = mtu3_gadget_stop, +}; + +static void init_hw_ep(struct mtu3 *mtu, struct mtu3_ep *mep, + u32 epnum, u32 is_in) +{ + mep->epnum = epnum; + mep->mtu = mtu; + mep->is_in = is_in; + + INIT_LIST_HEAD(&mep->req_list); + + sprintf(mep->name, "ep%d%s", epnum, + !epnum ? "" : (is_in ? "in" : "out")); + + mep->ep.name = mep->name; + INIT_LIST_HEAD(&mep->ep.ep_list); + + /* initialize maxpacket as HS */ + if (!epnum) { + usb_ep_set_maxpacket_limit(&mep->ep, 64); + mep->ep.caps.type_control = true; + mep->ep.ops = &mtu3_ep0_ops; + mtu->g.ep0 = &mep->ep; + } else { + usb_ep_set_maxpacket_limit(&mep->ep, 512); + mep->ep.caps.type_iso = true; + mep->ep.caps.type_bulk = true; + mep->ep.caps.type_int = true; + mep->ep.ops = &mtu3_ep_ops; + list_add_tail(&mep->ep.ep_list, &mtu->g.ep_list); + } + + dev_dbg(mtu->dev, "%s, name=%s, maxp=%d\n", __func__, mep->ep.name, + mep->ep.maxpacket); + + if (!epnum) { + mep->ep.caps.dir_in = true; + mep->ep.caps.dir_out = true; + } else if (is_in) { + mep->ep.caps.dir_in = true; + } else { + mep->ep.caps.dir_out = true; + } +} + +static void mtu3_gadget_init_eps(struct mtu3 *mtu) +{ + u8 epnum; + + /* initialize endpoint list just once */ + INIT_LIST_HEAD(&(mtu->g.ep_list)); + + dev_dbg(mtu->dev, "%s num_eps(1 for a pair of tx&rx ep)=%d\n", + __func__, mtu->num_eps); + + init_hw_ep(mtu, mtu->ep0, 0, 0); + for (epnum = 1; epnum < mtu->num_eps; epnum++) { + init_hw_ep(mtu, mtu->in_eps + epnum, epnum, 1); + init_hw_ep(mtu, mtu->out_eps + epnum, epnum, 0); + } +} + +int mtu3_gadget_setup(struct mtu3 *mtu) +{ + int ret; + + mtu->g.ops = &mtu3_gadget_ops; + mtu->g.max_speed = USB_SPEED_HIGH; + mtu->g.speed = USB_SPEED_UNKNOWN; + mtu->g.sg_supported = 0; + mtu->g.name = MTU3_DRIVER_NAME; + mtu->is_active = 0; + + mtu3_gadget_init_eps(mtu); + + ret = usb_add_gadget_udc(mtu->dev, &mtu->g); + if (ret) { + dev_err(mtu->dev, "failed to register udc\n"); + return ret; + } + + usb_gadget_set_state(&mtu->g, USB_STATE_NOTATTACHED); + + return 0; +} + +void mtu3_gadget_cleanup(struct mtu3 *mtu) +{ + usb_del_gadget_udc(&mtu->g); +} + +void mtu3_gadget_resume(struct mtu3 *mtu) +{ + dev_dbg(mtu->dev, "gadget RESUME\n"); + if (mtu->gadget_driver && mtu->gadget_driver->resume) { + spin_unlock(&mtu->lock); + mtu->gadget_driver->resume(&mtu->g); + spin_lock(&mtu->lock); + } +} + +/* called when SOF packets stop for 3+ msec or enters U3 */ +void mtu3_gadget_suspend(struct mtu3 *mtu) +{ + dev_dbg(mtu->dev, "gadget SUSPEND\n"); + if (mtu->gadget_driver && mtu->gadget_driver->suspend) { + spin_unlock(&mtu->lock); + mtu->gadget_driver->suspend(&mtu->g); + spin_lock(&mtu->lock); + } +} + +/* called when VBUS drops below session threshold, and in other cases */ +void mtu3_gadget_disconnect(struct mtu3 *mtu) +{ + dev_dbg(mtu->dev, "gadget DISCONNECT\n"); + if (mtu->gadget_driver && mtu->gadget_driver->disconnect) { + spin_unlock(&mtu->lock); + mtu->gadget_driver->disconnect(&mtu->g); + spin_lock(&mtu->lock); + } + + usb_gadget_set_state(&mtu->g, USB_STATE_NOTATTACHED); +} + +void mtu3_gadget_reset(struct mtu3 *mtu) +{ + dev_dbg(mtu->dev, "gadget RESET\n"); + + /* report disconnect, if we didn't flush EP state */ + if (mtu->g.speed != USB_SPEED_UNKNOWN) + mtu3_gadget_disconnect(mtu); + + mtu->address = 0; + mtu->ep0_state = MU3D_EP0_STATE_SETUP; + mtu->may_wakeup = 0; +} diff --git a/drivers/usb/mtu3/mtu3_gadget_ep0.c b/drivers/usb/mtu3/mtu3_gadget_ep0.c new file mode 100644 index 000000000000..4e2c2babad20 --- /dev/null +++ b/drivers/usb/mtu3/mtu3_gadget_ep0.c @@ -0,0 +1,791 @@ +/* + * mtu3_gadget_ep0.c - MediaTek USB3 DRD peripheral driver ep0 handling + * + * Copyright (c) 2016 MediaTek Inc. + * + * Author: Chunfeng.Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "mtu3.h" + +/* ep0 is always mtu3->in_eps[0] */ +#define next_ep0_request(mtu) next_request((mtu)->ep0) + +/* for high speed test mode; see USB 2.0 spec 7.1.20 */ +static const u8 mtu3_test_packet[53] = { + /* implicit SYNC then DATA0 to start */ + + /* JKJKJKJK x9 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* JJKKJJKK x8 */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + /* JJJJKKKK x8 */ + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + /* JJJJJJJKKKKKKK x8 */ + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + /* JJJJJJJK x8 */ + 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, + /* JKKKKKKK x10, JK */ + 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e, + /* implicit CRC16 then EOP to end */ +}; + +static char *decode_ep0_state(struct mtu3 *mtu) +{ + switch (mtu->ep0_state) { + case MU3D_EP0_STATE_SETUP: + return "SETUP"; + case MU3D_EP0_STATE_TX: + return "IN"; + case MU3D_EP0_STATE_RX: + return "OUT"; + case MU3D_EP0_STATE_TX_END: + return "TX-END"; + case MU3D_EP0_STATE_STALL: + return "STALL"; + default: + return "??"; + } +} + +static void ep0_req_giveback(struct mtu3 *mtu, struct usb_request *req) +{ + mtu3_req_complete(mtu->ep0, req, 0); +} + +static int +forward_to_driver(struct mtu3 *mtu, const struct usb_ctrlrequest *setup) +__releases(mtu->lock) +__acquires(mtu->lock) +{ + int ret; + + if (!mtu->gadget_driver) + return -EOPNOTSUPP; + + spin_unlock(&mtu->lock); + ret = mtu->gadget_driver->setup(&mtu->g, setup); + spin_lock(&mtu->lock); + + dev_dbg(mtu->dev, "%s ret %d\n", __func__, ret); + return ret; +} + +static void ep0_write_fifo(struct mtu3_ep *mep, const u8 *src, u16 len) +{ + void __iomem *fifo = mep->mtu->mac_base + U3D_FIFO0; + u16 index = 0; + + dev_dbg(mep->mtu->dev, "%s: ep%din, len=%d, buf=%p\n", + __func__, mep->epnum, len, src); + + if (len >= 4) { + iowrite32_rep(fifo, src, len >> 2); + index = len & ~0x03; + } + if (len & 0x02) { + writew(*(u16 *)&src[index], fifo); + index += 2; + } + if (len & 0x01) + writeb(src[index], fifo); +} + +static void ep0_read_fifo(struct mtu3_ep *mep, u8 *dst, u16 len) +{ + void __iomem *fifo = mep->mtu->mac_base + U3D_FIFO0; + u32 value; + u16 index = 0; + + dev_dbg(mep->mtu->dev, "%s: ep%dout len=%d buf=%p\n", + __func__, mep->epnum, len, dst); + + if (len >= 4) { + ioread32_rep(fifo, dst, len >> 2); + index = len & ~0x03; + } + if (len & 0x3) { + value = readl(fifo); + memcpy(&dst[index], &value, len & 0x3); + } + +} + +static void ep0_load_test_packet(struct mtu3 *mtu) +{ + /* + * because the length of test packet is less than max packet of HS ep0, + * write it into fifo directly. + */ + ep0_write_fifo(mtu->ep0, mtu3_test_packet, sizeof(mtu3_test_packet)); +} + +/* + * A. send STALL for setup transfer without data stage: + * set SENDSTALL and SETUPPKTRDY at the same time; + * B. send STALL for other cases: + * set SENDSTALL only. + */ +static void ep0_stall_set(struct mtu3_ep *mep0, bool set, u32 pktrdy) +{ + struct mtu3 *mtu = mep0->mtu; + void __iomem *mbase = mtu->mac_base; + u32 csr; + + /* EP0_SENTSTALL is W1C */ + csr = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS; + if (set) + csr |= EP0_SENDSTALL | pktrdy; + else + csr = (csr & ~EP0_SENDSTALL) | EP0_SENTSTALL; + mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr); + + mtu->ep0_state = MU3D_EP0_STATE_SETUP; + + dev_dbg(mtu->dev, "ep0: %s STALL, ep0_state: %s\n", + set ? "SEND" : "CLEAR", decode_ep0_state(mtu)); +} + +static int ep0_queue(struct mtu3_ep *mep0, struct mtu3_request *mreq); + +static void ep0_dummy_complete(struct usb_ep *ep, struct usb_request *req) +{} + +static int +ep0_get_status(struct mtu3 *mtu, const struct usb_ctrlrequest *setup) +{ + struct mtu3_ep *mep = NULL; + int handled = 1; + u8 result[2] = {0, 0}; + u8 epnum = 0; + int is_in; + + switch (setup->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: + result[0] = mtu->is_self_powered << USB_DEVICE_SELF_POWERED; + result[0] |= mtu->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; + break; + case USB_RECIP_INTERFACE: + break; + case USB_RECIP_ENDPOINT: + epnum = (u8) le16_to_cpu(setup->wIndex); + is_in = epnum & USB_DIR_IN; + epnum &= USB_ENDPOINT_NUMBER_MASK; + + if (epnum >= mtu->num_eps) { + handled = -EINVAL; + break; + } + if (!epnum) + break; + + mep = (is_in ? mtu->in_eps : mtu->out_eps) + epnum; + if (!mep->desc) { + handled = -EINVAL; + break; + } + if (mep->flags & MTU3_EP_STALL) + result[0] |= 1 << USB_ENDPOINT_HALT; + + break; + default: + /* class, vendor, etc ... delegate */ + handled = 0; + break; + } + + if (handled > 0) { + int ret; + + /* prepare a data stage for GET_STATUS */ + dev_dbg(mtu->dev, "get_status=%x\n", *(u16 *)result); + memcpy(mtu->setup_buf, result, sizeof(result)); + mtu->ep0_req.mep = mtu->ep0; + mtu->ep0_req.request.length = 2; + mtu->ep0_req.request.buf = &mtu->setup_buf; + mtu->ep0_req.request.complete = ep0_dummy_complete; + ret = ep0_queue(mtu->ep0, &mtu->ep0_req); + if (ret < 0) + handled = ret; + } + return handled; +} + +static int handle_test_mode(struct mtu3 *mtu, struct usb_ctrlrequest *setup) +{ + void __iomem *mbase = mtu->mac_base; + int handled = 1; + + switch (le16_to_cpu(setup->wIndex) >> 8) { + case TEST_J: + dev_dbg(mtu->dev, "TEST_J\n"); + mtu->test_mode_nr = TEST_J_MODE; + break; + case TEST_K: + dev_dbg(mtu->dev, "TEST_K\n"); + mtu->test_mode_nr = TEST_K_MODE; + break; + case TEST_SE0_NAK: + dev_dbg(mtu->dev, "TEST_SE0_NAK\n"); + mtu->test_mode_nr = TEST_SE0_NAK_MODE; + break; + case TEST_PACKET: + dev_dbg(mtu->dev, "TEST_PACKET\n"); + mtu->test_mode_nr = TEST_PACKET_MODE; + break; + default: + handled = -EINVAL; + goto out; + } + + mtu->test_mode = true; + + /* no TX completion interrupt, and need restart platform after test */ + if (mtu->test_mode_nr == TEST_PACKET_MODE) + ep0_load_test_packet(mtu); + + mtu3_writel(mbase, U3D_USB2_TEST_MODE, mtu->test_mode_nr); + + mtu->ep0_state = MU3D_EP0_STATE_SETUP; + +out: + return handled; +} + +static int ep0_handle_feature_dev(struct mtu3 *mtu, + struct usb_ctrlrequest *setup, bool set) +{ + int handled = -EINVAL; + + switch (le16_to_cpu(setup->wValue)) { + case USB_DEVICE_REMOTE_WAKEUP: + mtu->may_wakeup = !!set; + handled = 1; + break; + case USB_DEVICE_TEST_MODE: + if (!set || (mtu->g.speed != USB_SPEED_HIGH) || + (le16_to_cpu(setup->wIndex) & 0xff)) + break; + + handled = handle_test_mode(mtu, setup); + break; + default: + handled = -EINVAL; + break; + } + return handled; +} + +static int ep0_handle_feature(struct mtu3 *mtu, + struct usb_ctrlrequest *setup, bool set) +{ + struct mtu3_ep *mep; + int handled = -EINVAL; + int is_in; + u16 value; + u16 index; + u8 epnum; + + value = le16_to_cpu(setup->wValue); + index = le16_to_cpu(setup->wIndex); + + switch (setup->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: + handled = ep0_handle_feature_dev(mtu, setup, set); + break; + case USB_RECIP_ENDPOINT: + epnum = index & USB_ENDPOINT_NUMBER_MASK; + if (epnum == 0 || epnum >= mtu->num_eps || + value != USB_ENDPOINT_HALT) + break; + + is_in = index & USB_DIR_IN; + mep = (is_in ? mtu->in_eps : mtu->out_eps) + epnum; + if (!mep->desc) + break; + + handled = 1; + /* ignore request if endpoint is wedged */ + if (mep->wedged) + break; + + mtu3_ep_stall_set(mep, set); + break; + default: + /* class, vendor, etc ... delegate */ + handled = 0; + break; + } + return handled; +} + +/* + * handle all control requests can be handled + * returns: + * negative errno - error happened + * zero - need delegate SETUP to gadget driver + * positive - already handled + */ +static int handle_standard_request(struct mtu3 *mtu, + struct usb_ctrlrequest *setup) +{ + void __iomem *mbase = mtu->mac_base; + enum usb_device_state state = mtu->g.state; + int handled = -EINVAL; + u32 dev_conf; + u16 value; + + value = le16_to_cpu(setup->wValue); + + /* the gadget driver handles everything except what we must handle */ + switch (setup->bRequest) { + case USB_REQ_SET_ADDRESS: + /* change it after the status stage */ + mtu->address = (u8) (value & 0x7f); + dev_dbg(mtu->dev, "set address to 0x%x\n", mtu->address); + + dev_conf = mtu3_readl(mbase, U3D_DEVICE_CONF); + dev_conf &= ~DEV_ADDR_MSK; + dev_conf |= DEV_ADDR(mtu->address); + mtu3_writel(mbase, U3D_DEVICE_CONF, dev_conf); + + if (mtu->address) + usb_gadget_set_state(&mtu->g, USB_STATE_ADDRESS); + else + usb_gadget_set_state(&mtu->g, USB_STATE_DEFAULT); + + handled = 1; + break; + case USB_REQ_SET_CONFIGURATION: + if (state == USB_STATE_ADDRESS) { + usb_gadget_set_state(&mtu->g, + USB_STATE_CONFIGURED); + } else if (state == USB_STATE_CONFIGURED) { + /* + * USB2 spec sec 9.4.7, if wValue is 0 then dev + * is moved to addressed state + */ + if (!value) + usb_gadget_set_state(&mtu->g, + USB_STATE_ADDRESS); + } + handled = 0; + break; + case USB_REQ_CLEAR_FEATURE: + handled = ep0_handle_feature(mtu, setup, 0); + break; + case USB_REQ_SET_FEATURE: + handled = ep0_handle_feature(mtu, setup, 1); + break; + case USB_REQ_GET_STATUS: + handled = ep0_get_status(mtu, setup); + break; + case USB_REQ_SET_ISOCH_DELAY: + handled = 1; + break; + default: + /* delegate SET_CONFIGURATION, etc */ + handled = 0; + } + + return handled; +} + +/* receive an data packet (OUT) */ +static void ep0_rx_state(struct mtu3 *mtu) +{ + struct mtu3_request *mreq; + struct usb_request *req; + void __iomem *mbase = mtu->mac_base; + u32 maxp; + u32 csr; + u16 count = 0; + + dev_dbg(mtu->dev, "%s\n", __func__); + + csr = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS; + mreq = next_ep0_request(mtu); + req = &mreq->request; + + /* read packet and ack; or stall because of gadget driver bug */ + if (req) { + void *buf = req->buf + req->actual; + unsigned int len = req->length - req->actual; + + /* read the buffer */ + count = mtu3_readl(mbase, U3D_RXCOUNT0); + if (count > len) { + req->status = -EOVERFLOW; + count = len; + } + ep0_read_fifo(mtu->ep0, buf, count); + req->actual += count; + csr |= EP0_RXPKTRDY; + + maxp = mtu->g.ep0->maxpacket; + if (count < maxp || req->actual == req->length) { + mtu->ep0_state = MU3D_EP0_STATE_SETUP; + dev_dbg(mtu->dev, "ep0 state: %s\n", + decode_ep0_state(mtu)); + + csr |= EP0_DATAEND; + } else { + req = NULL; + } + } else { + csr |= EP0_RXPKTRDY | EP0_SENDSTALL; + dev_dbg(mtu->dev, "%s: SENDSTALL\n", __func__); + } + + mtu3_writel(mbase, U3D_EP0CSR, csr); + + /* give back the request if have received all data */ + if (req) + ep0_req_giveback(mtu, req); + +} + +/* transmitting to the host (IN) */ +static void ep0_tx_state(struct mtu3 *mtu) +{ + struct mtu3_request *mreq = next_ep0_request(mtu); + struct usb_request *req; + u32 csr; + u8 *src; + u8 count; + u32 maxp; + + dev_dbg(mtu->dev, "%s\n", __func__); + + if (!mreq) + return; + + maxp = mtu->g.ep0->maxpacket; + req = &mreq->request; + + /* load the data */ + src = (u8 *)req->buf + req->actual; + count = min(maxp, req->length - req->actual); + if (count) + ep0_write_fifo(mtu->ep0, src, count); + + dev_dbg(mtu->dev, "%s act=%d, len=%d, cnt=%d, maxp=%d zero=%d\n", + __func__, req->actual, req->length, count, maxp, req->zero); + + req->actual += count; + + if ((count < maxp) + || ((req->actual == req->length) && !req->zero)) + mtu->ep0_state = MU3D_EP0_STATE_TX_END; + + /* send it out, triggering a "txpktrdy cleared" irq */ + csr = mtu3_readl(mtu->mac_base, U3D_EP0CSR) & EP0_W1C_BITS; + mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr | EP0_TXPKTRDY); + + dev_dbg(mtu->dev, "%s ep0csr=0x%x\n", __func__, + mtu3_readl(mtu->mac_base, U3D_EP0CSR)); +} + +static void ep0_read_setup(struct mtu3 *mtu, struct usb_ctrlrequest *setup) +{ + struct mtu3_request *mreq; + u32 count; + u32 csr; + + csr = mtu3_readl(mtu->mac_base, U3D_EP0CSR) & EP0_W1C_BITS; + count = mtu3_readl(mtu->mac_base, U3D_RXCOUNT0); + + ep0_read_fifo(mtu->ep0, (u8 *)setup, count); + + dev_dbg(mtu->dev, "SETUP req%02x.%02x v%04x i%04x l%04x\n", + setup->bRequestType, setup->bRequest, + le16_to_cpu(setup->wValue), le16_to_cpu(setup->wIndex), + le16_to_cpu(setup->wLength)); + + /* clean up any leftover transfers */ + mreq = next_ep0_request(mtu); + if (mreq) + ep0_req_giveback(mtu, &mreq->request); + + if (le16_to_cpu(setup->wLength) == 0) { + ; /* no data stage, nothing to do */ + } else if (setup->bRequestType & USB_DIR_IN) { + mtu3_writel(mtu->mac_base, U3D_EP0CSR, + csr | EP0_SETUPPKTRDY | EP0_DPHTX); + mtu->ep0_state = MU3D_EP0_STATE_TX; + } else { + mtu3_writel(mtu->mac_base, U3D_EP0CSR, + (csr | EP0_SETUPPKTRDY) & (~EP0_DPHTX)); + mtu->ep0_state = MU3D_EP0_STATE_RX; + } +} + +static int ep0_handle_setup(struct mtu3 *mtu) +__releases(mtu->lock) +__acquires(mtu->lock) +{ + struct usb_ctrlrequest setup; + struct mtu3_request *mreq; + void __iomem *mbase = mtu->mac_base; + int handled = 0; + + ep0_read_setup(mtu, &setup); + + if ((setup.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) + handled = handle_standard_request(mtu, &setup); + + dev_dbg(mtu->dev, "handled %d, ep0_state: %s\n", + handled, decode_ep0_state(mtu)); + + if (handled < 0) + goto stall; + else if (handled > 0) + goto finish; + + handled = forward_to_driver(mtu, &setup); + if (handled < 0) { +stall: + dev_dbg(mtu->dev, "%s stall (%d)\n", __func__, handled); + + ep0_stall_set(mtu->ep0, true, + le16_to_cpu(setup.wLength) ? 0 : EP0_SETUPPKTRDY); + + return 0; + } + +finish: + if (mtu->test_mode) { + ; /* nothing to do */ + } else if (le16_to_cpu(setup.wLength) == 0) { /* no data stage */ + + mtu3_writel(mbase, U3D_EP0CSR, + (mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS) + | EP0_SETUPPKTRDY | EP0_DATAEND); + + /* complete zlp request directly */ + mreq = next_ep0_request(mtu); + if (mreq && !mreq->request.length) + ep0_req_giveback(mtu, &mreq->request); + } + + return 0; +} + +irqreturn_t mtu3_ep0_isr(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + struct mtu3_request *mreq; + u32 int_status; + irqreturn_t ret = IRQ_NONE; + u32 csr; + u32 len; + + int_status = mtu3_readl(mbase, U3D_EPISR); + int_status &= mtu3_readl(mbase, U3D_EPIER); + mtu3_writel(mbase, U3D_EPISR, int_status); /* W1C */ + + /* only handle ep0's */ + if (!(int_status & EP0ISR)) + return IRQ_NONE; + + csr = mtu3_readl(mbase, U3D_EP0CSR); + + dev_dbg(mtu->dev, "%s csr=0x%x\n", __func__, csr); + + /* we sent a stall.. need to clear it now.. */ + if (csr & EP0_SENTSTALL) { + ep0_stall_set(mtu->ep0, false, 0); + csr = mtu3_readl(mbase, U3D_EP0CSR); + ret = IRQ_HANDLED; + } + dev_dbg(mtu->dev, "ep0_state: %s\n", decode_ep0_state(mtu)); + + switch (mtu->ep0_state) { + case MU3D_EP0_STATE_TX: + /* irq on clearing txpktrdy */ + if ((csr & EP0_FIFOFULL) == 0) { + ep0_tx_state(mtu); + ret = IRQ_HANDLED; + } + break; + case MU3D_EP0_STATE_RX: + /* irq on set rxpktrdy */ + if (csr & EP0_RXPKTRDY) { + ep0_rx_state(mtu); + ret = IRQ_HANDLED; + } + break; + case MU3D_EP0_STATE_TX_END: + mtu3_writel(mbase, U3D_EP0CSR, + (csr & EP0_W1C_BITS) | EP0_DATAEND); + + mreq = next_ep0_request(mtu); + if (mreq) + ep0_req_giveback(mtu, &mreq->request); + + mtu->ep0_state = MU3D_EP0_STATE_SETUP; + ret = IRQ_HANDLED; + dev_dbg(mtu->dev, "ep0_state: %s\n", decode_ep0_state(mtu)); + break; + case MU3D_EP0_STATE_SETUP: + if (!(csr & EP0_SETUPPKTRDY)) + break; + + len = mtu3_readl(mbase, U3D_RXCOUNT0); + if (len != 8) { + dev_err(mtu->dev, "SETUP packet len %d != 8 ?\n", len); + break; + } + + ep0_handle_setup(mtu); + ret = IRQ_HANDLED; + break; + default: + /* can't happen */ + ep0_stall_set(mtu->ep0, true, 0); + WARN_ON(1); + break; + } + + return ret; +} + + +static int mtu3_ep0_enable(struct usb_ep *ep, + const struct usb_endpoint_descriptor *desc) +{ + /* always enabled */ + return -EINVAL; +} + +static int mtu3_ep0_disable(struct usb_ep *ep) +{ + /* always enabled */ + return -EINVAL; +} + +static int ep0_queue(struct mtu3_ep *mep, struct mtu3_request *mreq) +{ + struct mtu3 *mtu = mep->mtu; + + mreq->mtu = mtu; + mreq->request.actual = 0; + mreq->request.status = -EINPROGRESS; + + dev_dbg(mtu->dev, "%s %s (ep0_state: %s), len#%d\n", __func__, + mep->name, decode_ep0_state(mtu), mreq->request.length); + + if (!list_empty(&mep->req_list)) + return -EBUSY; + + switch (mtu->ep0_state) { + case MU3D_EP0_STATE_SETUP: + case MU3D_EP0_STATE_RX: /* control-OUT data */ + case MU3D_EP0_STATE_TX: /* control-IN data */ + break; + default: + dev_err(mtu->dev, "%s, error in ep0 state %s\n", __func__, + decode_ep0_state(mtu)); + return -EINVAL; + } + + list_add_tail(&mreq->list, &mep->req_list); + + /* sequence #1, IN ... start writing the data */ + if (mtu->ep0_state == MU3D_EP0_STATE_TX) + ep0_tx_state(mtu); + + return 0; +} + +static int mtu3_ep0_queue(struct usb_ep *ep, + struct usb_request *req, gfp_t gfp) +{ + struct mtu3_ep *mep; + struct mtu3_request *mreq; + struct mtu3 *mtu; + unsigned long flags; + int ret = 0; + + if (!ep || !req) + return -EINVAL; + + mep = to_mtu3_ep(ep); + mtu = mep->mtu; + mreq = to_mtu3_request(req); + + spin_lock_irqsave(&mtu->lock, flags); + ret = ep0_queue(mep, mreq); + spin_unlock_irqrestore(&mtu->lock, flags); + return ret; +} + +static int mtu3_ep0_dequeue(struct usb_ep *ep, struct usb_request *req) +{ + /* we just won't support this */ + return -EINVAL; +} + +static int mtu3_ep0_halt(struct usb_ep *ep, int value) +{ + struct mtu3_ep *mep; + struct mtu3 *mtu; + unsigned long flags; + int ret = 0; + + if (!ep || !value) + return -EINVAL; + + mep = to_mtu3_ep(ep); + mtu = mep->mtu; + + dev_dbg(mtu->dev, "%s\n", __func__); + + spin_lock_irqsave(&mtu->lock, flags); + + if (!list_empty(&mep->req_list)) { + ret = -EBUSY; + goto cleanup; + } + + switch (mtu->ep0_state) { + /* + * stalls are usually issued after parsing SETUP packet, either + * directly in irq context from setup() or else later. + */ + case MU3D_EP0_STATE_TX: + case MU3D_EP0_STATE_TX_END: + case MU3D_EP0_STATE_RX: + case MU3D_EP0_STATE_SETUP: + ep0_stall_set(mtu->ep0, true, 0); + break; + default: + dev_dbg(mtu->dev, "ep0 can't halt in state %s\n", + decode_ep0_state(mtu)); + ret = -EINVAL; + } + +cleanup: + spin_unlock_irqrestore(&mtu->lock, flags); + return ret; +} + +const struct usb_ep_ops mtu3_ep0_ops = { + .enable = mtu3_ep0_enable, + .disable = mtu3_ep0_disable, + .alloc_request = mtu3_alloc_request, + .free_request = mtu3_free_request, + .queue = mtu3_ep0_queue, + .dequeue = mtu3_ep0_dequeue, + .set_halt = mtu3_ep0_halt, +}; diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h new file mode 100644 index 000000000000..08c83c5f6109 --- /dev/null +++ b/drivers/usb/mtu3/mtu3_hw_regs.h @@ -0,0 +1,440 @@ +/* + * mtu3_hw_regs.h - MediaTek USB3 DRD register and field definitions + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _SSUSB_HW_REGS_H_ +#define _SSUSB_HW_REGS_H_ + +/* segment offset of MAC register */ +#define SSUSB_DEV_BASE 0x0000 +#define SSUSB_EPCTL_CSR_BASE 0x0800 +#define SSUSB_USB3_MAC_CSR_BASE 0x1400 +#define SSUSB_USB3_SYS_CSR_BASE 0x1400 +#define SSUSB_USB2_CSR_BASE 0x2400 + +/* IPPC register in Infra */ +#define SSUSB_SIFSLV_IPPC_BASE 0x0000 + +/* --------------- SSUSB_DEV REGISTER DEFINITION --------------- */ + +#define U3D_LV1ISR (SSUSB_DEV_BASE + 0x0000) +#define U3D_LV1IER (SSUSB_DEV_BASE + 0x0004) +#define U3D_LV1IESR (SSUSB_DEV_BASE + 0x0008) +#define U3D_LV1IECR (SSUSB_DEV_BASE + 0x000C) + +#define U3D_EPISR (SSUSB_DEV_BASE + 0x0080) +#define U3D_EPIER (SSUSB_DEV_BASE + 0x0084) +#define U3D_EPIESR (SSUSB_DEV_BASE + 0x0088) +#define U3D_EPIECR (SSUSB_DEV_BASE + 0x008C) + +#define U3D_EP0CSR (SSUSB_DEV_BASE + 0x0100) +#define U3D_RXCOUNT0 (SSUSB_DEV_BASE + 0x0108) +#define U3D_RESERVED (SSUSB_DEV_BASE + 0x010C) +#define U3D_TX1CSR0 (SSUSB_DEV_BASE + 0x0110) +#define U3D_TX1CSR1 (SSUSB_DEV_BASE + 0x0114) +#define U3D_TX1CSR2 (SSUSB_DEV_BASE + 0x0118) + +#define U3D_RX1CSR0 (SSUSB_DEV_BASE + 0x0210) +#define U3D_RX1CSR1 (SSUSB_DEV_BASE + 0x0214) +#define U3D_RX1CSR2 (SSUSB_DEV_BASE + 0x0218) + +#define U3D_FIFO0 (SSUSB_DEV_BASE + 0x0300) + +#define U3D_QCR0 (SSUSB_DEV_BASE + 0x0400) +#define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404) +#define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408) +#define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C) + +#define U3D_TXQCSR1 (SSUSB_DEV_BASE + 0x0510) +#define U3D_TXQSAR1 (SSUSB_DEV_BASE + 0x0514) +#define U3D_TXQCPR1 (SSUSB_DEV_BASE + 0x0518) + +#define U3D_RXQCSR1 (SSUSB_DEV_BASE + 0x0610) +#define U3D_RXQSAR1 (SSUSB_DEV_BASE + 0x0614) +#define U3D_RXQCPR1 (SSUSB_DEV_BASE + 0x0618) +#define U3D_RXQLDPR1 (SSUSB_DEV_BASE + 0x061C) + +#define U3D_QISAR0 (SSUSB_DEV_BASE + 0x0700) +#define U3D_QIER0 (SSUSB_DEV_BASE + 0x0704) +#define U3D_QIESR0 (SSUSB_DEV_BASE + 0x0708) +#define U3D_QIECR0 (SSUSB_DEV_BASE + 0x070C) +#define U3D_QISAR1 (SSUSB_DEV_BASE + 0x0710) +#define U3D_QIER1 (SSUSB_DEV_BASE + 0x0714) +#define U3D_QIESR1 (SSUSB_DEV_BASE + 0x0718) +#define U3D_QIECR1 (SSUSB_DEV_BASE + 0x071C) + +#define U3D_TQERRIR0 (SSUSB_DEV_BASE + 0x0780) +#define U3D_TQERRIER0 (SSUSB_DEV_BASE + 0x0784) +#define U3D_TQERRIESR0 (SSUSB_DEV_BASE + 0x0788) +#define U3D_TQERRIECR0 (SSUSB_DEV_BASE + 0x078C) +#define U3D_RQERRIR0 (SSUSB_DEV_BASE + 0x07C0) +#define U3D_RQERRIER0 (SSUSB_DEV_BASE + 0x07C4) +#define U3D_RQERRIESR0 (SSUSB_DEV_BASE + 0x07C8) +#define U3D_RQERRIECR0 (SSUSB_DEV_BASE + 0x07CC) +#define U3D_RQERRIR1 (SSUSB_DEV_BASE + 0x07D0) +#define U3D_RQERRIER1 (SSUSB_DEV_BASE + 0x07D4) +#define U3D_RQERRIESR1 (SSUSB_DEV_BASE + 0x07D8) +#define U3D_RQERRIECR1 (SSUSB_DEV_BASE + 0x07DC) + +#define U3D_CAP_EP0FFSZ (SSUSB_DEV_BASE + 0x0C04) +#define U3D_CAP_EPNTXFFSZ (SSUSB_DEV_BASE + 0x0C08) +#define U3D_CAP_EPNRXFFSZ (SSUSB_DEV_BASE + 0x0C0C) +#define U3D_CAP_EPINFO (SSUSB_DEV_BASE + 0x0C10) +#define U3D_MISC_CTRL (SSUSB_DEV_BASE + 0x0C84) + +/*---------------- SSUSB_DEV FIELD DEFINITION ---------------*/ + +/* U3D_LV1ISR */ +#define EP_CTRL_INTR BIT(5) +#define MAC2_INTR BIT(4) +#define DMA_INTR BIT(3) +#define MAC3_INTR BIT(2) +#define QMU_INTR BIT(1) +#define BMU_INTR BIT(0) + +/* U3D_LV1IECR */ +#define LV1IECR_MSK GENMASK(31, 0) + +/* U3D_EPISR */ +#define EPRISR(x) (BIT(16) << (x)) +#define EPTISR(x) (BIT(0) << (x)) +#define EP0ISR BIT(0) + +/* U3D_EP0CSR */ +#define EP0_SENDSTALL BIT(25) +#define EP0_FIFOFULL BIT(23) +#define EP0_SENTSTALL BIT(22) +#define EP0_DPHTX BIT(20) +#define EP0_DATAEND BIT(19) +#define EP0_TXPKTRDY BIT(18) +#define EP0_SETUPPKTRDY BIT(17) +#define EP0_RXPKTRDY BIT(16) +#define EP0_MAXPKTSZ_MSK GENMASK(9, 0) +#define EP0_MAXPKTSZ(x) ((x) & EP0_MAXPKTSZ_MSK) +#define EP0_W1C_BITS (~(EP0_RXPKTRDY | EP0_SETUPPKTRDY | EP0_SENTSTALL)) + +/* U3D_TX1CSR0 */ +#define TX_DMAREQEN BIT(29) +#define TX_FIFOFULL BIT(25) +#define TX_FIFOEMPTY BIT(24) +#define TX_SENTSTALL BIT(22) +#define TX_SENDSTALL BIT(21) +#define TX_TXPKTRDY BIT(16) +#define TX_TXMAXPKTSZ_MSK GENMASK(10, 0) +#define TX_TXMAXPKTSZ(x) ((x) & TX_TXMAXPKTSZ_MSK) +#define TX_W1C_BITS (~(TX_SENTSTALL)) + +/* U3D_TX1CSR1 */ +#define TX_MULT(x) (((x) & 0x3) << 22) +#define TX_MAX_PKT(x) (((x) & 0x3f) << 16) +#define TX_SLOT(x) (((x) & 0x3f) << 8) +#define TX_TYPE(x) (((x) & 0x3) << 4) +#define TX_SS_BURST(x) (((x) & 0xf) << 0) + +/* for TX_TYPE & RX_TYPE */ +#define TYPE_BULK (0x0) +#define TYPE_INT (0x1) +#define TYPE_ISO (0x2) +#define TYPE_MASK (0x3) + +/* U3D_TX1CSR2 */ +#define TX_BINTERVAL(x) (((x) & 0xff) << 24) +#define TX_FIFOSEGSIZE(x) (((x) & 0xf) << 16) +#define TX_FIFOADDR(x) (((x) & 0x1fff) << 0) + +/* U3D_RX1CSR0 */ +#define RX_DMAREQEN BIT(29) +#define RX_SENTSTALL BIT(22) +#define RX_SENDSTALL BIT(21) +#define RX_RXPKTRDY BIT(16) +#define RX_RXMAXPKTSZ_MSK GENMASK(10, 0) +#define RX_RXMAXPKTSZ(x) ((x) & RX_RXMAXPKTSZ_MSK) +#define RX_W1C_BITS (~(RX_SENTSTALL | RX_RXPKTRDY)) + +/* U3D_RX1CSR1 */ +#define RX_MULT(x) (((x) & 0x3) << 22) +#define RX_MAX_PKT(x) (((x) & 0x3f) << 16) +#define RX_SLOT(x) (((x) & 0x3f) << 8) +#define RX_TYPE(x) (((x) & 0x3) << 4) +#define RX_SS_BURST(x) (((x) & 0xf) << 0) + +/* U3D_RX1CSR2 */ +#define RX_BINTERVAL(x) (((x) & 0xff) << 24) +#define RX_FIFOSEGSIZE(x) (((x) & 0xf) << 16) +#define RX_FIFOADDR(x) (((x) & 0x1fff) << 0) + +/* U3D_QCR0 */ +#define QMU_RX_CS_EN(x) (BIT(16) << (x)) +#define QMU_TX_CS_EN(x) (BIT(0) << (x)) +#define QMU_CS16B_EN BIT(0) + +/* U3D_QCR1 */ +#define QMU_TX_ZLP(x) (BIT(0) << (x)) + +/* U3D_QCR3 */ +#define QMU_RX_COZ(x) (BIT(16) << (x)) +#define QMU_RX_ZLP(x) (BIT(0) << (x)) + +/* U3D_TXQCSR1 */ +/* U3D_RXQCSR1 */ +#define QMU_Q_ACTIVE BIT(15) +#define QMU_Q_STOP BIT(2) +#define QMU_Q_RESUME BIT(1) +#define QMU_Q_START BIT(0) + +/* U3D_QISAR0, U3D_QIER0, U3D_QIESR0, U3D_QIECR0 */ +#define QMU_RX_DONE_INT(x) (BIT(16) << (x)) +#define QMU_TX_DONE_INT(x) (BIT(0) << (x)) + +/* U3D_QISAR1, U3D_QIER1, U3D_QIESR1, U3D_QIECR1 */ +#define RXQ_ZLPERR_INT BIT(20) +#define RXQ_LENERR_INT BIT(18) +#define RXQ_CSERR_INT BIT(17) +#define RXQ_EMPTY_INT BIT(16) +#define TXQ_LENERR_INT BIT(2) +#define TXQ_CSERR_INT BIT(1) +#define TXQ_EMPTY_INT BIT(0) + +/* U3D_TQERRIR0, U3D_TQERRIER0, U3D_TQERRIESR0, U3D_TQERRIECR0 */ +#define QMU_TX_LEN_ERR(x) (BIT(16) << (x)) +#define QMU_TX_CS_ERR(x) (BIT(0) << (x)) + +/* U3D_RQERRIR0, U3D_RQERRIER0, U3D_RQERRIESR0, U3D_RQERRIECR0 */ +#define QMU_RX_LEN_ERR(x) (BIT(16) << (x)) +#define QMU_RX_CS_ERR(x) (BIT(0) << (x)) + +/* U3D_RQERRIR1, U3D_RQERRIER1, U3D_RQERRIESR1, U3D_RQERRIECR1 */ +#define QMU_RX_ZLP_ERR(n) (BIT(16) << (n)) + +/* U3D_CAP_EPINFO */ +#define CAP_RX_EP_NUM(x) (((x) >> 8) & 0x1f) +#define CAP_TX_EP_NUM(x) ((x) & 0x1f) + +/* U3D_MISC_CTRL */ +#define VBUS_ON BIT(1) +#define VBUS_FRC_EN BIT(0) + + +/*---------------- SSUSB_EPCTL_CSR REGISTER DEFINITION ----------------*/ + +#define U3D_DEVICE_CONF (SSUSB_EPCTL_CSR_BASE + 0x0000) +#define U3D_EP_RST (SSUSB_EPCTL_CSR_BASE + 0x0004) + +#define U3D_DEV_LINK_INTR_ENABLE (SSUSB_EPCTL_CSR_BASE + 0x0050) +#define U3D_DEV_LINK_INTR (SSUSB_EPCTL_CSR_BASE + 0x0054) + +/*---------------- SSUSB_EPCTL_CSR FIELD DEFINITION ----------------*/ + +/* U3D_DEVICE_CONF */ +#define DEV_ADDR_MSK GENMASK(30, 24) +#define DEV_ADDR(x) ((0x7f & (x)) << 24) +#define HW_USB2_3_SEL BIT(18) +#define SW_USB2_3_SEL_EN BIT(17) +#define SW_USB2_3_SEL BIT(16) +#define SSUSB_DEV_SPEED(x) ((x) & 0x7) + +/* U3D_EP_RST */ +#define EP1_IN_RST BIT(17) +#define EP1_OUT_RST BIT(1) +#define EP_RST(is_in, epnum) (((is_in) ? BIT(16) : BIT(0)) << (epnum)) +#define EP0_RST BIT(0) + +/* U3D_DEV_LINK_INTR_ENABLE */ +/* U3D_DEV_LINK_INTR */ +#define SSUSB_DEV_SPEED_CHG_INTR BIT(0) + + +/*---------------- SSUSB_USB3_MAC_CSR REGISTER DEFINITION ----------------*/ + +#define U3D_USB3_CONFIG (SSUSB_USB3_MAC_CSR_BASE + 0x001C) + +/*---------------- SSUSB_USB3_MAC_CSR FIELD DEFINITION ----------------*/ + +/* U3D_USB3_CONFIG */ +#define USB3_EN BIT(0) + +/*---------------- SSUSB_USB3_SYS_CSR REGISTER DEFINITION ----------------*/ + +#define U3D_LINK_UX_INACT_TIMER (SSUSB_USB3_SYS_CSR_BASE + 0x020C) +#define U3D_LINK_POWER_CONTROL (SSUSB_USB3_SYS_CSR_BASE + 0x0210) +#define U3D_LINK_ERR_COUNT (SSUSB_USB3_SYS_CSR_BASE + 0x0214) + +/*---------------- SSUSB_USB3_SYS_CSR FIELD DEFINITION ----------------*/ + +/* U3D_LINK_UX_INACT_TIMER */ +#define DEV_U2_INACT_TIMEOUT_MSK GENMASK(23, 16) +#define DEV_U2_INACT_TIMEOUT_VALUE(x) (((x) & 0xff) << 16) +#define U2_INACT_TIMEOUT_MSK GENMASK(15, 8) +#define U1_INACT_TIMEOUT_MSK GENMASK(7, 0) +#define U1_INACT_TIMEOUT_VALUE(x) ((x) & 0xff) + +/* U3D_LINK_POWER_CONTROL */ +#define SW_U2_ACCEPT_ENABLE BIT(9) +#define SW_U1_ACCEPT_ENABLE BIT(8) +#define UX_EXIT BIT(5) +#define LGO_U3 BIT(4) +#define LGO_U2 BIT(3) +#define LGO_U1 BIT(2) +#define SW_U2_REQUEST_ENABLE BIT(1) +#define SW_U1_REQUEST_ENABLE BIT(0) + +/* U3D_LINK_ERR_COUNT */ +#define CLR_LINK_ERR_CNT BIT(16) +#define LINK_ERROR_COUNT GENMASK(15, 0) + +/*---------------- SSUSB_USB2_CSR REGISTER DEFINITION ----------------*/ + +#define U3D_POWER_MANAGEMENT (SSUSB_USB2_CSR_BASE + 0x0004) +#define U3D_DEVICE_CONTROL (SSUSB_USB2_CSR_BASE + 0x000C) +#define U3D_USB2_TEST_MODE (SSUSB_USB2_CSR_BASE + 0x0014) +#define U3D_COMMON_USB_INTR_ENABLE (SSUSB_USB2_CSR_BASE + 0x0018) +#define U3D_COMMON_USB_INTR (SSUSB_USB2_CSR_BASE + 0x001C) +#define U3D_LINK_RESET_INFO (SSUSB_USB2_CSR_BASE + 0x0024) +#define U3D_USB20_FRAME_NUM (SSUSB_USB2_CSR_BASE + 0x003C) +#define U3D_USB20_LPM_PARAMETER (SSUSB_USB2_CSR_BASE + 0x0044) +#define U3D_USB20_MISC_CONTROL (SSUSB_USB2_CSR_BASE + 0x004C) + +/*---------------- SSUSB_USB2_CSR FIELD DEFINITION ----------------*/ + +/* U3D_POWER_MANAGEMENT */ +#define LPM_BESL_STALL BIT(14) +#define LPM_BESLD_STALL BIT(13) +#define LPM_RWP BIT(11) +#define LPM_HRWE BIT(10) +#define LPM_MODE(x) (((x) & 0x3) << 8) +#define ISO_UPDATE BIT(7) +#define SOFT_CONN BIT(6) +#define HS_ENABLE BIT(5) +#define RESUME BIT(2) +#define SUSPENDM_ENABLE BIT(0) + +/* U3D_DEVICE_CONTROL */ +#define DC_HOSTREQ BIT(1) +#define DC_SESSION BIT(0) + +/* U3D_USB2_TEST_MODE */ +#define U2U3_AUTO_SWITCH BIT(10) +#define LPM_FORCE_STALL BIT(8) +#define FIFO_ACCESS BIT(6) +#define FORCE_FS BIT(5) +#define FORCE_HS BIT(4) +#define TEST_PACKET_MODE BIT(3) +#define TEST_K_MODE BIT(2) +#define TEST_J_MODE BIT(1) +#define TEST_SE0_NAK_MODE BIT(0) + +/* U3D_COMMON_USB_INTR_ENABLE */ +/* U3D_COMMON_USB_INTR */ +#define LPM_RESUME_INTR BIT(9) +#define LPM_INTR BIT(8) +#define DISCONN_INTR BIT(5) +#define CONN_INTR BIT(4) +#define SOF_INTR BIT(3) +#define RESET_INTR BIT(2) +#define RESUME_INTR BIT(1) +#define SUSPEND_INTR BIT(0) + +/* U3D_LINK_RESET_INFO */ +#define WTCHRP_MSK GENMASK(19, 16) + +/* U3D_USB20_LPM_PARAMETER */ +#define LPM_BESLCK_U3(x) (((x) & 0xf) << 12) +#define LPM_BESLCK(x) (((x) & 0xf) << 8) +#define LPM_BESLDCK(x) (((x) & 0xf) << 4) +#define LPM_BESL GENMASK(3, 0) + +/* U3D_USB20_MISC_CONTROL */ +#define LPM_U3_ACK_EN BIT(0) + +/*---------------- SSUSB_SIFSLV_IPPC REGISTER DEFINITION ----------------*/ + +#define U3D_SSUSB_IP_PW_CTRL0 (SSUSB_SIFSLV_IPPC_BASE + 0x0000) +#define U3D_SSUSB_IP_PW_CTRL1 (SSUSB_SIFSLV_IPPC_BASE + 0x0004) +#define U3D_SSUSB_IP_PW_CTRL2 (SSUSB_SIFSLV_IPPC_BASE + 0x0008) +#define U3D_SSUSB_IP_PW_CTRL3 (SSUSB_SIFSLV_IPPC_BASE + 0x000C) +#define U3D_SSUSB_IP_PW_STS1 (SSUSB_SIFSLV_IPPC_BASE + 0x0010) +#define U3D_SSUSB_IP_PW_STS2 (SSUSB_SIFSLV_IPPC_BASE + 0x0014) +#define U3D_SSUSB_OTG_STS (SSUSB_SIFSLV_IPPC_BASE + 0x0018) +#define U3D_SSUSB_OTG_STS_CLR (SSUSB_SIFSLV_IPPC_BASE + 0x001C) +#define U3D_SSUSB_IP_XHCI_CAP (SSUSB_SIFSLV_IPPC_BASE + 0x0024) +#define U3D_SSUSB_IP_DEV_CAP (SSUSB_SIFSLV_IPPC_BASE + 0x0028) +#define U3D_SSUSB_OTG_INT_EN (SSUSB_SIFSLV_IPPC_BASE + 0x002C) +#define U3D_SSUSB_U3_CTRL_0P (SSUSB_SIFSLV_IPPC_BASE + 0x0030) +#define U3D_SSUSB_U2_CTRL_0P (SSUSB_SIFSLV_IPPC_BASE + 0x0050) +#define U3D_SSUSB_REF_CK_CTRL (SSUSB_SIFSLV_IPPC_BASE + 0x008C) +#define U3D_SSUSB_DEV_RST_CTRL (SSUSB_SIFSLV_IPPC_BASE + 0x0098) +#define U3D_SSUSB_HW_ID (SSUSB_SIFSLV_IPPC_BASE + 0x00A0) +#define U3D_SSUSB_HW_SUB_ID (SSUSB_SIFSLV_IPPC_BASE + 0x00A4) +#define U3D_SSUSB_IP_SPARE0 (SSUSB_SIFSLV_IPPC_BASE + 0x00C8) + +/*---------------- SSUSB_SIFSLV_IPPC FIELD DEFINITION ----------------*/ + +/* U3D_SSUSB_IP_PW_CTRL0 */ +#define SSUSB_IP_SW_RST BIT(0) + +/* U3D_SSUSB_IP_PW_CTRL1 */ +#define SSUSB_IP_HOST_PDN BIT(0) + +/* U3D_SSUSB_IP_PW_CTRL2 */ +#define SSUSB_IP_DEV_PDN BIT(0) + +/* U3D_SSUSB_IP_PW_CTRL3 */ +#define SSUSB_IP_PCIE_PDN BIT(0) + +/* U3D_SSUSB_IP_PW_STS1 */ +#define SSUSB_IP_SLEEP_STS BIT(30) +#define SSUSB_U3_MAC_RST_B_STS BIT(16) +#define SSUSB_XHCI_RST_B_STS BIT(11) +#define SSUSB_SYS125_RST_B_STS BIT(10) +#define SSUSB_REF_RST_B_STS BIT(8) +#define SSUSB_SYSPLL_STABLE BIT(0) + +/* U3D_SSUSB_IP_PW_STS2 */ +#define SSUSB_U2_MAC_SYS_RST_B_STS BIT(0) + +/* U3D_SSUSB_OTG_STS */ +#define SSUSB_VBUS_VALID BIT(9) + +/* U3D_SSUSB_OTG_STS_CLR */ +#define SSUSB_VBUS_INTR_CLR BIT(6) + +/* U3D_SSUSB_IP_XHCI_CAP */ +#define SSUSB_IP_XHCI_U2_PORT_NUM(x) (((x) >> 8) & 0xff) +#define SSUSB_IP_XHCI_U3_PORT_NUM(x) ((x) & 0xff) + +/* U3D_SSUSB_IP_DEV_CAP */ +#define SSUSB_IP_DEV_U3_PORT_NUM(x) ((x) & 0xff) + +/* U3D_SSUSB_OTG_INT_EN */ +#define SSUSB_VBUS_CHG_INT_A_EN BIT(7) +#define SSUSB_VBUS_CHG_INT_B_EN BIT(6) + +/* U3D_SSUSB_U3_CTRL_0P */ +#define SSUSB_U3_PORT_HOST_SEL BIT(2) +#define SSUSB_U3_PORT_PDN BIT(1) +#define SSUSB_U3_PORT_DIS BIT(0) + +/* U3D_SSUSB_U2_CTRL_0P */ +#define SSUSB_U2_PORT_OTG_SEL BIT(7) +#define SSUSB_U2_PORT_HOST_SEL BIT(2) +#define SSUSB_U2_PORT_PDN BIT(1) +#define SSUSB_U2_PORT_DIS BIT(0) + +/* U3D_SSUSB_DEV_RST_CTRL */ +#define SSUSB_DEV_SW_RST BIT(0) + +#endif /* _SSUSB_HW_REGS_H_ */ diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c new file mode 100644 index 000000000000..52fc0edbe3ee --- /dev/null +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtu3.h" + +/* u2-port0 should be powered on and enabled; */ +int ssusb_check_clocks(struct mtu3 *mtu, u32 ex_clks) +{ + void __iomem *ibase = mtu->ippc_base; + u32 value, check_val; + int ret; + + check_val = ex_clks | SSUSB_SYS125_RST_B_STS | SSUSB_SYSPLL_STABLE | + SSUSB_REF_RST_B_STS; + + ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS1, value, + (check_val == (value & check_val)), 100, 20000); + if (ret) { + dev_err(mtu->dev, "clks of sts1 are not stable!\n"); + return ret; + } + + ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS2, value, + (value & SSUSB_U2_MAC_SYS_RST_B_STS), 100, 10000); + if (ret) { + dev_err(mtu->dev, "mac2 clock is not stable\n"); + return ret; + } + + return 0; +} + +static int ssusb_rscs_init(struct mtu3 *mtu) +{ + int ret = 0; + + ret = regulator_enable(mtu->vusb33); + if (ret) { + dev_err(mtu->dev, "failed to enable vusb33\n"); + goto vusb33_err; + } + + ret = clk_prepare_enable(mtu->sys_clk); + if (ret) { + dev_err(mtu->dev, "failed to enable sys_clk\n"); + goto clk_err; + } + + ret = phy_init(mtu->phy); + if (ret) { + dev_err(mtu->dev, "failed to init phy\n"); + goto phy_init_err; + } + + ret = phy_power_on(mtu->phy); + if (ret) { + dev_err(mtu->dev, "failed to power on phy\n"); + goto phy_err; + } + + return 0; + +phy_err: + phy_exit(mtu->phy); + +phy_init_err: + clk_disable_unprepare(mtu->sys_clk); + +clk_err: + regulator_disable(mtu->vusb33); + +vusb33_err: + + return ret; +} + +static void ssusb_rscs_exit(struct mtu3 *mtu) +{ + clk_disable_unprepare(mtu->sys_clk); + regulator_disable(mtu->vusb33); + phy_power_off(mtu->phy); + phy_exit(mtu->phy); +} + +static void ssusb_ip_sw_reset(struct mtu3 *mtu) +{ + mtu3_setbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); + udelay(1); + mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); +} + +static int get_ssusb_rscs(struct platform_device *pdev, struct mtu3 *mtu) +{ + struct device_node *node = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct resource *res; + + mtu->phy = devm_of_phy_get_by_index(dev, node, 0); + if (IS_ERR(mtu->phy)) { + dev_err(dev, "failed to get phy\n"); + return PTR_ERR(mtu->phy); + } + + mtu->irq = platform_get_irq(pdev, 0); + if (mtu->irq <= 0) { + dev_err(dev, "fail to get irq number\n"); + return -ENODEV; + } + dev_info(dev, "irq %d\n", mtu->irq); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); + mtu->mac_base = devm_ioremap_resource(dev, res); + if (IS_ERR(mtu->mac_base)) { + dev_err(dev, "error mapping memory for dev mac\n"); + return PTR_ERR(mtu->mac_base); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc"); + mtu->ippc_base = devm_ioremap_resource(dev, res); + if (IS_ERR(mtu->ippc_base)) { + dev_err(dev, "failed to map memory for ippc\n"); + return PTR_ERR(mtu->ippc_base); + } + + mtu->vusb33 = devm_regulator_get(&pdev->dev, "vusb33"); + if (IS_ERR(mtu->vusb33)) { + dev_err(dev, "failed to get vusb33\n"); + return PTR_ERR(mtu->vusb33); + } + + mtu->sys_clk = devm_clk_get(dev, "sys_ck"); + if (IS_ERR(mtu->sys_clk)) { + dev_err(dev, "failed to get sys clock\n"); + return PTR_ERR(mtu->sys_clk); + } + + return 0; +} + +static int mtu3_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mtu3 *mtu; + int ret = -ENOMEM; + + /* all elements are set to ZERO as default value */ + mtu = devm_kzalloc(dev, sizeof(struct mtu3), GFP_KERNEL); + if (!mtu) + return -ENOMEM; + + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(dev, "No suitable DMA config available\n"); + return -ENOTSUPP; + } + + platform_set_drvdata(pdev, mtu); + mtu->dev = dev; + spin_lock_init(&mtu->lock); + + ret = get_ssusb_rscs(pdev, mtu); + if (ret) + return ret; + + /* enable power domain */ + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + device_enable_async_suspend(dev); + + ret = ssusb_rscs_init(mtu); + if (ret) + goto comm_init_err; + + ssusb_ip_sw_reset(mtu); + + ret = ssusb_gadget_init(mtu); + if (ret) { + dev_err(dev, "failed to initialize gadget\n"); + goto comm_exit; + } + + return 0; + +comm_exit: + ssusb_rscs_exit(mtu); + +comm_init_err: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + + return ret; +} + +static int mtu3_remove(struct platform_device *pdev) +{ + struct mtu3 *mtu = platform_get_drvdata(pdev); + + ssusb_gadget_exit(mtu); + ssusb_rscs_exit(mtu); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +#ifdef CONFIG_OF + +static const struct of_device_id mtu3_of_match[] = { + {.compatible = "mediatek,mt8173-mtu3",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, mtu3_of_match); + +#endif + +static struct platform_driver mtu3_driver = { + .probe = mtu3_probe, + .remove = mtu3_remove, + .driver = { + .name = MTU3_DRIVER_NAME, + .of_match_table = of_match_ptr(mtu3_of_match), + }, +}; +module_platform_driver(mtu3_driver); + +MODULE_AUTHOR("Chunfeng Yun "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MediaTek USB3 DRD Controller Driver"); diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c new file mode 100644 index 000000000000..a6dd292c63ec --- /dev/null +++ b/drivers/usb/mtu3/mtu3_qmu.c @@ -0,0 +1,573 @@ +/* + * mtu3_qmu.c - Queue Management Unit driver for device controller + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* + * Queue Management Unit (QMU) is designed to unload SW effort + * to serve DMA interrupts. + * By preparing General Purpose Descriptor (GPD) and Buffer Descriptor (BD), + * SW links data buffers and triggers QMU to send / receive data to + * host / from device at a time. + * And now only GPD is supported. + * + * For more detailed information, please refer to QMU Programming Guide + */ + +#include +#include + +#include "mtu3.h" + +#define QMU_CHECKSUM_LEN 16 + +#define GPD_FLAGS_HWO BIT(0) +#define GPD_FLAGS_BDP BIT(1) +#define GPD_FLAGS_BPS BIT(2) +#define GPD_FLAGS_IOC BIT(7) + +#define GPD_EXT_FLAG_ZLP BIT(5) + + +static struct qmu_gpd *gpd_dma_to_virt(struct mtu3_gpd_ring *ring, + dma_addr_t dma_addr) +{ + dma_addr_t dma_base = ring->dma; + struct qmu_gpd *gpd_head = ring->start; + u32 offset = (dma_addr - dma_base) / sizeof(*gpd_head); + + if (offset >= MAX_GPD_NUM) + return NULL; + + return gpd_head + offset; +} + +static dma_addr_t gpd_virt_to_dma(struct mtu3_gpd_ring *ring, + struct qmu_gpd *gpd) +{ + dma_addr_t dma_base = ring->dma; + struct qmu_gpd *gpd_head = ring->start; + u32 offset; + + offset = gpd - gpd_head; + if (offset >= MAX_GPD_NUM) + return 0; + + return dma_base + (offset * sizeof(*gpd)); +} + +static void gpd_ring_init(struct mtu3_gpd_ring *ring, struct qmu_gpd *gpd) +{ + ring->start = gpd; + ring->enqueue = gpd; + ring->dequeue = gpd; + ring->end = gpd + MAX_GPD_NUM - 1; +} + +static void reset_gpd_list(struct mtu3_ep *mep) +{ + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + struct qmu_gpd *gpd = ring->start; + + if (gpd) { + gpd->flag &= ~GPD_FLAGS_HWO; + gpd_ring_init(ring, gpd); + } +} + +int mtu3_gpd_ring_alloc(struct mtu3_ep *mep) +{ + struct qmu_gpd *gpd; + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + + /* software own all gpds as default */ + gpd = dma_pool_zalloc(mep->mtu->qmu_gpd_pool, GFP_ATOMIC, &ring->dma); + if (gpd == NULL) + return -ENOMEM; + + gpd_ring_init(ring, gpd); + + return 0; +} + +void mtu3_gpd_ring_free(struct mtu3_ep *mep) +{ + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + + dma_pool_free(mep->mtu->qmu_gpd_pool, + ring->start, ring->dma); + memset(ring, 0, sizeof(*ring)); +} + +/* + * calculate check sum of a gpd or bd + * add "noinline" and "mb" to prevent wrong calculation + */ +static noinline u8 qmu_calc_checksum(u8 *data) +{ + u8 chksum = 0; + int i; + + data[1] = 0x0; /* set checksum to 0 */ + + mb(); /* ensure the gpd/bd is really up-to-date */ + for (i = 0; i < QMU_CHECKSUM_LEN; i++) + chksum += data[i]; + + /* Default: HWO=1, @flag[bit0] */ + chksum += 1; + + return 0xFF - chksum; +} + +void mtu3_qmu_resume(struct mtu3_ep *mep) +{ + struct mtu3 *mtu = mep->mtu; + void __iomem *mbase = mtu->mac_base; + int epnum = mep->epnum; + u32 offset; + + offset = mep->is_in ? USB_QMU_TQCSR(epnum) : USB_QMU_RQCSR(epnum); + + mtu3_writel(mbase, offset, QMU_Q_RESUME); + if (!(mtu3_readl(mbase, offset) & QMU_Q_ACTIVE)) + mtu3_writel(mbase, offset, QMU_Q_RESUME); +} + +static struct qmu_gpd *advance_enq_gpd(struct mtu3_gpd_ring *ring) +{ + if (ring->enqueue < ring->end) + ring->enqueue++; + else + ring->enqueue = ring->start; + + return ring->enqueue; +} + +static struct qmu_gpd *advance_deq_gpd(struct mtu3_gpd_ring *ring) +{ + if (ring->dequeue < ring->end) + ring->dequeue++; + else + ring->dequeue = ring->start; + + return ring->dequeue; +} + +/* check if a ring is emtpy */ +int gpd_ring_empty(struct mtu3_gpd_ring *ring) +{ + struct qmu_gpd *enq = ring->enqueue; + struct qmu_gpd *next; + + if (ring->enqueue < ring->end) + next = enq + 1; + else + next = ring->start; + + /* one gpd is reserved to simplify gpd preparation */ + return next == ring->dequeue; +} + +int mtu3_prepare_transfer(struct mtu3_ep *mep) +{ + return gpd_ring_empty(&mep->gpd_ring); +} + +static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) +{ + struct qmu_gpd *enq; + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + struct qmu_gpd *gpd = ring->enqueue; + struct usb_request *req = &mreq->request; + + /* set all fields to zero as default value */ + memset(gpd, 0, sizeof(*gpd)); + + gpd->buffer = cpu_to_le32((u32)req->dma); + gpd->buf_len = cpu_to_le16(req->length); + gpd->flag |= GPD_FLAGS_IOC; + + /* get the next GPD */ + enq = advance_enq_gpd(ring); + dev_dbg(mep->mtu->dev, "TX-EP%d queue gpd=%p, enq=%p\n", + mep->epnum, gpd, enq); + + enq->flag &= ~GPD_FLAGS_HWO; + gpd->next_gpd = cpu_to_le32((u32)gpd_virt_to_dma(ring, enq)); + + if (req->zero) + gpd->ext_flag |= GPD_EXT_FLAG_ZLP; + + gpd->chksum = qmu_calc_checksum((u8 *)gpd); + gpd->flag |= GPD_FLAGS_HWO; + + mreq->gpd = gpd; + + return 0; +} + +static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) +{ + struct qmu_gpd *enq; + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + struct qmu_gpd *gpd = ring->enqueue; + struct usb_request *req = &mreq->request; + + /* set all fields to zero as default value */ + memset(gpd, 0, sizeof(*gpd)); + + gpd->buffer = cpu_to_le32((u32)req->dma); + gpd->data_buf_len = cpu_to_le16(req->length); + gpd->flag |= GPD_FLAGS_IOC; + + /* get the next GPD */ + enq = advance_enq_gpd(ring); + dev_dbg(mep->mtu->dev, "RX-EP%d queue gpd=%p, enq=%p\n", + mep->epnum, gpd, enq); + + enq->flag &= ~GPD_FLAGS_HWO; + gpd->next_gpd = cpu_to_le32((u32)gpd_virt_to_dma(ring, enq)); + gpd->chksum = qmu_calc_checksum((u8 *)gpd); + gpd->flag |= GPD_FLAGS_HWO; + + mreq->gpd = gpd; + + return 0; +} + +void mtu3_insert_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) +{ + + if (mep->is_in) + mtu3_prepare_tx_gpd(mep, mreq); + else + mtu3_prepare_rx_gpd(mep, mreq); +} + +int mtu3_qmu_start(struct mtu3_ep *mep) +{ + struct mtu3 *mtu = mep->mtu; + void __iomem *mbase = mtu->mac_base; + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + u8 epnum = mep->epnum; + + if (mep->is_in) { + /* set QMU start address */ + mtu3_writel(mbase, USB_QMU_TQSAR(mep->epnum), ring->dma); + mtu3_setbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN); + mtu3_setbits(mbase, U3D_QCR0, QMU_TX_CS_EN(epnum)); + /* send zero length packet according to ZLP flag in GPD */ + mtu3_setbits(mbase, U3D_QCR1, QMU_TX_ZLP(epnum)); + mtu3_writel(mbase, U3D_TQERRIESR0, + QMU_TX_LEN_ERR(epnum) | QMU_TX_CS_ERR(epnum)); + + if (mtu3_readl(mbase, USB_QMU_TQCSR(epnum)) & QMU_Q_ACTIVE) { + dev_warn(mtu->dev, "Tx %d Active Now!\n", epnum); + return 0; + } + mtu3_writel(mbase, USB_QMU_TQCSR(epnum), QMU_Q_START); + + } else { + mtu3_writel(mbase, USB_QMU_RQSAR(mep->epnum), ring->dma); + mtu3_setbits(mbase, MU3D_EP_RXCR0(mep->epnum), RX_DMAREQEN); + mtu3_setbits(mbase, U3D_QCR0, QMU_RX_CS_EN(epnum)); + /* don't expect ZLP */ + mtu3_clrbits(mbase, U3D_QCR3, QMU_RX_ZLP(epnum)); + /* move to next GPD when receive ZLP */ + mtu3_setbits(mbase, U3D_QCR3, QMU_RX_COZ(epnum)); + mtu3_writel(mbase, U3D_RQERRIESR0, + QMU_RX_LEN_ERR(epnum) | QMU_RX_CS_ERR(epnum)); + mtu3_writel(mbase, U3D_RQERRIESR1, QMU_RX_ZLP_ERR(epnum)); + + if (mtu3_readl(mbase, USB_QMU_RQCSR(epnum)) & QMU_Q_ACTIVE) { + dev_warn(mtu->dev, "Rx %d Active Now!\n", epnum); + return 0; + } + mtu3_writel(mbase, USB_QMU_RQCSR(epnum), QMU_Q_START); + } + + return 0; +} + +/* may called in atomic context */ +void mtu3_qmu_stop(struct mtu3_ep *mep) +{ + struct mtu3 *mtu = mep->mtu; + void __iomem *mbase = mtu->mac_base; + int epnum = mep->epnum; + u32 value = 0; + u32 qcsr; + int ret; + + qcsr = mep->is_in ? USB_QMU_TQCSR(epnum) : USB_QMU_RQCSR(epnum); + + if (!(mtu3_readl(mbase, qcsr) & QMU_Q_ACTIVE)) { + dev_dbg(mtu->dev, "%s's qmu is inactive now!\n", mep->name); + return; + } + mtu3_writel(mbase, qcsr, QMU_Q_STOP); + + ret = readl_poll_timeout_atomic(mbase + qcsr, value, + !(value & QMU_Q_ACTIVE), 1, 1000); + if (ret) { + dev_err(mtu->dev, "stop %s's qmu failed\n", mep->name); + return; + } + + dev_dbg(mtu->dev, "%s's qmu stop now!\n", mep->name); +} + +void mtu3_qmu_flush(struct mtu3_ep *mep) +{ + + dev_dbg(mep->mtu->dev, "%s flush QMU %s\n", __func__, + ((mep->is_in) ? "TX" : "RX")); + + /*Stop QMU */ + mtu3_qmu_stop(mep); + reset_gpd_list(mep); +} + +/* + * QMU can't transfer zero length packet directly (a hardware limit + * on old SoCs), so when needs to send ZLP, we intentionally trigger + * a length error interrupt, and in the ISR sends a ZLP by BMU. + */ +static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) +{ + struct mtu3_ep *mep = mtu->in_eps + epnum; + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + void __iomem *mbase = mtu->mac_base; + struct qmu_gpd *gpd_current = NULL; + dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_TQCPR(epnum)); + struct usb_request *req = NULL; + struct mtu3_request *mreq; + u32 txcsr = 0; + int ret; + + mreq = next_request(mep); + if (mreq && mreq->request.length == 0) + req = &mreq->request; + else + return; + + gpd_current = gpd_dma_to_virt(ring, gpd_dma); + + if (le16_to_cpu(gpd_current->buf_len) != 0) { + dev_err(mtu->dev, "TX EP%d buffer length error(!=0)\n", epnum); + return; + } + + dev_dbg(mtu->dev, "%s send ZLP for req=%p\n", __func__, mreq); + + mtu3_clrbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN); + + ret = readl_poll_timeout_atomic(mbase + MU3D_EP_TXCR0(mep->epnum), + txcsr, !(txcsr & TX_FIFOFULL), 1, 1000); + if (ret) { + dev_err(mtu->dev, "%s wait for fifo empty fail\n", __func__); + return; + } + mtu3_setbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_TXPKTRDY); + + /* by pass the current GDP */ + gpd_current->flag |= GPD_FLAGS_BPS; + gpd_current->chksum = qmu_calc_checksum((u8 *)gpd_current); + gpd_current->flag |= GPD_FLAGS_HWO; + + /*enable DMAREQEN, switch back to QMU mode */ + mtu3_setbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN); + mtu3_qmu_resume(mep); +} + +/* + * NOTE: request list maybe is already empty as following case: + * queue_tx --> qmu_interrupt(clear interrupt pending, schedule tasklet)--> + * queue_tx --> process_tasklet(meanwhile, the second one is transferred, + * tasklet process both of them)-->qmu_interrupt for second one. + * To avoid upper case, put qmu_done_tx in ISR directly to process it. + */ +static void qmu_done_tx(struct mtu3 *mtu, u8 epnum) +{ + struct mtu3_ep *mep = mtu->in_eps + epnum; + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + void __iomem *mbase = mtu->mac_base; + struct qmu_gpd *gpd = ring->dequeue; + struct qmu_gpd *gpd_current = NULL; + dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_TQCPR(epnum)); + struct usb_request *request = NULL; + struct mtu3_request *mreq; + + /*transfer phy address got from QMU register to virtual address */ + gpd_current = gpd_dma_to_virt(ring, gpd_dma); + + dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n", + __func__, epnum, gpd, gpd_current, ring->enqueue); + + while (gpd != gpd_current && !(gpd->flag & GPD_FLAGS_HWO)) { + + mreq = next_request(mep); + + if (mreq == NULL || mreq->gpd != gpd) { + dev_err(mtu->dev, "no correct TX req is found\n"); + break; + } + + request = &mreq->request; + request->actual = le16_to_cpu(gpd->buf_len); + mtu3_req_complete(mep, request, 0); + + gpd = advance_deq_gpd(ring); + } + + dev_dbg(mtu->dev, "%s EP%d, deq=%p, enq=%p, complete\n", + __func__, epnum, ring->dequeue, ring->enqueue); + +} + +static void qmu_done_rx(struct mtu3 *mtu, u8 epnum) +{ + struct mtu3_ep *mep = mtu->out_eps + epnum; + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + void __iomem *mbase = mtu->mac_base; + struct qmu_gpd *gpd = ring->dequeue; + struct qmu_gpd *gpd_current = NULL; + dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_RQCPR(epnum)); + struct usb_request *req = NULL; + struct mtu3_request *mreq; + + gpd_current = gpd_dma_to_virt(ring, gpd_dma); + + dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n", + __func__, epnum, gpd, gpd_current, ring->enqueue); + + while (gpd != gpd_current && !(gpd->flag & GPD_FLAGS_HWO)) { + + mreq = next_request(mep); + + if (mreq == NULL || mreq->gpd != gpd) { + dev_err(mtu->dev, "no correct RX req is found\n"); + break; + } + req = &mreq->request; + + req->actual = le16_to_cpu(gpd->buf_len); + mtu3_req_complete(mep, req, 0); + + gpd = advance_deq_gpd(ring); + } + + dev_dbg(mtu->dev, "%s EP%d, deq=%p, enq=%p, complete\n", + __func__, epnum, ring->dequeue, ring->enqueue); +} + +static void qmu_done_isr(struct mtu3 *mtu, u32 done_status) +{ + int i; + + for (i = 1; i < mtu->num_eps; i++) { + if (done_status & QMU_RX_DONE_INT(i)) + qmu_done_rx(mtu, i); + if (done_status & QMU_TX_DONE_INT(i)) + qmu_done_tx(mtu, i); + } +} + +static void qmu_exception_isr(struct mtu3 *mtu, u32 qmu_status) +{ + void __iomem *mbase = mtu->mac_base; + u32 errval; + int i; + + if ((qmu_status & RXQ_CSERR_INT) || (qmu_status & RXQ_LENERR_INT)) { + errval = mtu3_readl(mbase, U3D_RQERRIR0); + for (i = 1; i < mtu->num_eps; i++) { + if (errval & QMU_RX_CS_ERR(i)) + dev_err(mtu->dev, "Rx %d CS error!\n", i); + + if (errval & QMU_RX_LEN_ERR(i)) + dev_err(mtu->dev, "RX %d Length error\n", i); + } + mtu3_writel(mbase, U3D_RQERRIR0, errval); + } + + if (qmu_status & RXQ_ZLPERR_INT) { + errval = mtu3_readl(mbase, U3D_RQERRIR1); + for (i = 1; i < mtu->num_eps; i++) { + if (errval & QMU_RX_ZLP_ERR(i)) + dev_dbg(mtu->dev, "RX EP%d Recv ZLP\n", i); + } + mtu3_writel(mbase, U3D_RQERRIR1, errval); + } + + if ((qmu_status & TXQ_CSERR_INT) || (qmu_status & TXQ_LENERR_INT)) { + errval = mtu3_readl(mbase, U3D_TQERRIR0); + for (i = 1; i < mtu->num_eps; i++) { + if (errval & QMU_TX_CS_ERR(i)) + dev_err(mtu->dev, "Tx %d checksum error!\n", i); + + if (errval & QMU_TX_LEN_ERR(i)) + qmu_tx_zlp_error_handler(mtu, i); + } + mtu3_writel(mbase, U3D_TQERRIR0, errval); + } +} + +irqreturn_t mtu3_qmu_isr(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + u32 qmu_status; + u32 qmu_done_status; + + /* U3D_QISAR1 is read update */ + qmu_status = mtu3_readl(mbase, U3D_QISAR1); + qmu_status &= mtu3_readl(mbase, U3D_QIER1); + + qmu_done_status = mtu3_readl(mbase, U3D_QISAR0); + qmu_done_status &= mtu3_readl(mbase, U3D_QIER0); + mtu3_writel(mbase, U3D_QISAR0, qmu_done_status); /* W1C */ + dev_dbg(mtu->dev, "=== QMUdone[tx=%x, rx=%x] QMUexp[%x] ===\n", + (qmu_done_status & 0xFFFF), qmu_done_status >> 16, + qmu_status); + + if (qmu_done_status) + qmu_done_isr(mtu, qmu_done_status); + + if (qmu_status) + qmu_exception_isr(mtu, qmu_status); + + return IRQ_HANDLED; +} + +int mtu3_qmu_init(struct mtu3 *mtu) +{ + + compiletime_assert(QMU_GPD_SIZE == 16, "QMU_GPD size SHOULD be 16B"); + + mtu->qmu_gpd_pool = dma_pool_create("QMU_GPD", mtu->dev, + QMU_GPD_RING_SIZE, QMU_GPD_SIZE, 0); + + if (!mtu->qmu_gpd_pool) + return -ENOMEM; + + return 0; +} + +void mtu3_qmu_exit(struct mtu3 *mtu) +{ + dma_pool_destroy(mtu->qmu_gpd_pool); +} diff --git a/drivers/usb/mtu3/mtu3_qmu.h b/drivers/usb/mtu3/mtu3_qmu.h new file mode 100644 index 000000000000..4dafa16bf120 --- /dev/null +++ b/drivers/usb/mtu3/mtu3_qmu.h @@ -0,0 +1,43 @@ +/* + * mtu3_qmu.h - Queue Management Unit driver header + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __MTK_QMU_H__ +#define __MTK_QMU_H__ + +#define MAX_GPD_NUM 64 +#define QMU_GPD_SIZE (sizeof(struct qmu_gpd)) +#define QMU_GPD_RING_SIZE (MAX_GPD_NUM * QMU_GPD_SIZE) + +#define GPD_BUF_SIZE 65532 + +void mtu3_qmu_stop(struct mtu3_ep *mep); +int mtu3_qmu_start(struct mtu3_ep *mep); +void mtu3_qmu_resume(struct mtu3_ep *mep); +void mtu3_qmu_flush(struct mtu3_ep *mep); + +void mtu3_insert_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq); +int mtu3_prepare_transfer(struct mtu3_ep *mep); + +int mtu3_gpd_ring_alloc(struct mtu3_ep *mep); +void mtu3_gpd_ring_free(struct mtu3_ep *mep); + +irqreturn_t mtu3_qmu_isr(struct mtu3 *mtu); +int mtu3_qmu_init(struct mtu3 *mtu); +void mtu3_qmu_exit(struct mtu3 *mtu); + +#endif -- cgit v1.2.3 From a29de31b9ed37ebc905fe8580506b93f28701e67 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Wed, 19 Oct 2016 10:28:24 +0800 Subject: usb: mtu3: Super-Speed Peripheral mode support add super-speed funtion for peripheral mode Signed-off-by: Chunfeng Yun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mtu3/mtu3.h | 13 ++- drivers/usb/mtu3/mtu3_core.c | 202 +++++++++++++++++++++++++++++++++---- drivers/usb/mtu3/mtu3_gadget.c | 45 ++++++--- drivers/usb/mtu3/mtu3_gadget_ep0.c | 90 +++++++++++++++++ drivers/usb/mtu3/mtu3_hw_regs.h | 33 ++++++ 5 files changed, 346 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index ad1a1338bff1..41a04732a274 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -53,6 +53,7 @@ struct mtu3_request; #define USB_QMU_TQSAR(epnum) (U3D_TXQSAR1 + (((epnum) - 1) * 0x10)) #define USB_QMU_TQCPR(epnum) (U3D_TXQCPR1 + (((epnum) - 1) * 0x10)) +#define SSUSB_U3_CTRL(p) (U3D_SSUSB_U3_CTRL_0P + ((p) * 0x08)) #define SSUSB_U2_CTRL(p) (U3D_SSUSB_U2_CTRL_0P + ((p) * 0x08)) #define MTU3_DRIVER_NAME "mtu3" @@ -63,6 +64,7 @@ struct mtu3_request; #define MTU3_EP_WEDGE BIT(2) #define MTU3_EP_BUSY BIT(3) +#define MTU3_U3_IP_SLOT_DEFAULT 2 #define MTU3_U2_IP_SLOT_DEFAULT 1 /** @@ -87,6 +89,7 @@ enum mtu3_speed { MTU3_SPEED_INACTIVE = 0, MTU3_SPEED_FULL = 1, MTU3_SPEED_HIGH = 3, + MTU3_SPEED_SUPER = 4, }; /** @@ -190,6 +193,7 @@ struct mtu3_ep { struct list_head req_list; struct mtu3_gpd_ring gpd_ring; + const struct usb_ss_ep_comp_descriptor *comp_desc; const struct usb_endpoint_descriptor *desc; int flags; @@ -208,7 +212,8 @@ struct mtu3_request { /** * struct mtu3 - device driver instance data. - * @slot: MTU3_U2_IP_SLOT_DEFAULT for U2 IP + * @slot: MTU3_U2_IP_SLOT_DEFAULT for U2 IP only, + * MTU3_U3_IP_SLOT_DEFAULT for U3 IP * @may_wakeup: means device's remote wakeup is enabled * @is_self_powered: is reported in device status and the config descriptor * @ep0_req: dummy request used while handling standard USB requests @@ -242,12 +247,16 @@ struct mtu3 { struct usb_gadget_driver *gadget_driver; struct mtu3_request ep0_req; u8 setup_buf[EP0_RESPONSE_BUF]; + u32 max_speed; unsigned is_active:1; unsigned may_wakeup:1; unsigned is_self_powered:1; unsigned test_mode:1; unsigned softconnect:1; + unsigned u1_enable:1; + unsigned u2_enable:1; + unsigned is_u3_ip:1; u8 address; u8 test_mode_nr; @@ -324,7 +333,7 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set); void mtu3_ep0_setup(struct mtu3 *mtu); void mtu3_start(struct mtu3 *mtu); void mtu3_stop(struct mtu3 *mtu); -void mtu3_hs_softconn_set(struct mtu3 *mtu, bool enable); +void mtu3_dev_on_off(struct mtu3 *mtu, int is_on); int mtu3_gadget_setup(struct mtu3 *mtu); void mtu3_gadget_cleanup(struct mtu3 *mtu); diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index 33d21dddb8a0..f9817ad53e3c 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -72,8 +72,20 @@ static void ep_fifo_free(struct mtu3_ep *mep) __func__, mep->fifo_seg_size, mep->fifo_size, start_bit); } +/* enable/disable U3D SS function */ +static inline void mtu3_ss_func_set(struct mtu3 *mtu, bool enable) +{ + /* If usb3_en==0, LTSSM will go to SS.Disable state */ + if (enable) + mtu3_setbits(mtu->mac_base, U3D_USB3_CONFIG, USB3_EN); + else + mtu3_clrbits(mtu->mac_base, U3D_USB3_CONFIG, USB3_EN); + + dev_dbg(mtu->dev, "USB3_EN = %d\n", !!enable); +} + /* set/clear U3D HS device soft connect */ -void mtu3_hs_softconn_set(struct mtu3 *mtu, bool enable) +static inline void mtu3_hs_softconn_set(struct mtu3 *mtu, bool enable) { if (enable) { mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, @@ -92,6 +104,13 @@ static int mtu3_device_enable(struct mtu3 *mtu) u32 check_clk = 0; mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); + + if (mtu->is_u3_ip) { + check_clk = SSUSB_U3_MAC_RST_B_STS; + mtu3_clrbits(ibase, SSUSB_U3_CTRL(0), + (SSUSB_U3_PORT_DIS | SSUSB_U3_PORT_PDN | + SSUSB_U3_PORT_HOST_SEL)); + } mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), (SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_HOST_SEL)); @@ -104,6 +123,10 @@ static void mtu3_device_disable(struct mtu3 *mtu) { void __iomem *ibase = mtu->ippc_base; + if (mtu->is_u3_ip) + mtu3_setbits(ibase, SSUSB_U3_CTRL(0), + (SSUSB_U3_PORT_DIS | SSUSB_U3_PORT_PDN)); + mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN); mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); @@ -142,6 +165,9 @@ static void mtu3_intr_status_clear(struct mtu3 *mtu) /* Clear U2 USB common interrupts status */ mtu3_writel(mbase, U3D_COMMON_USB_INTR, ~0x0); + /* Clear U3 LTSSM interrupts status */ + mtu3_writel(mbase, U3D_LTSSM_INTR, ~0x0); + /* Clear speed change interrupt status */ mtu3_writel(mbase, U3D_DEV_LINK_INTR, ~0x0); } @@ -153,13 +179,20 @@ static void mtu3_intr_enable(struct mtu3 *mtu) u32 value; /*Enable level 1 interrupts (BMU, QMU, MAC3, DMA, MAC2, EPCTL) */ - value = BMU_INTR | QMU_INTR | MAC2_INTR | EP_CTRL_INTR; + value = BMU_INTR | QMU_INTR | MAC3_INTR | MAC2_INTR | EP_CTRL_INTR; mtu3_writel(mbase, U3D_LV1IESR, value); /* Enable U2 common USB interrupts */ value = SUSPEND_INTR | RESUME_INTR | RESET_INTR; mtu3_writel(mbase, U3D_COMMON_USB_INTR_ENABLE, value); + if (mtu->is_u3_ip) { + /* Enable U3 LTSSM interrupts */ + value = HOT_RST_INTR | WARM_RST_INTR | VBUS_RISE_INTR | + VBUS_FALL_INTR | ENTER_U3_INTR | EXIT_U3_INTR; + mtu3_writel(mbase, U3D_LTSSM_INTR_ENABLE, value); + } + /* Enable QMU interrupts. */ value = TXQ_CSERR_INT | TXQ_LENERR_INT | RXQ_CSERR_INT | RXQ_LENERR_INT | RXQ_ZLPERR_INT; @@ -205,6 +238,17 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set) set ? "SEND STALL" : "CLEAR STALL, with EP RESET"); } +void mtu3_dev_on_off(struct mtu3 *mtu, int is_on) +{ + if (mtu->is_u3_ip && (mtu->max_speed == USB_SPEED_SUPER)) + mtu3_ss_func_set(mtu, is_on); + else + mtu3_hs_softconn_set(mtu, is_on); + + dev_info(mtu->dev, "gadget (%s) pullup D%s\n", + usb_speed_string(mtu->max_speed), is_on ? "+" : "-"); +} + void mtu3_start(struct mtu3 *mtu) { void __iomem *mbase = mtu->mac_base; @@ -214,13 +258,21 @@ void mtu3_start(struct mtu3 *mtu) mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); + /* + * When disable U2 port, USB2_CSR's register will be reset to + * default value after re-enable it again(HS is enabled by default). + * So if force mac to work as FS, disable HS function. + */ + if (mtu->max_speed == USB_SPEED_FULL) + mtu3_clrbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); + /* Initialize the default interrupts */ mtu3_intr_enable(mtu); mtu->is_active = 1; if (mtu->softconnect) - mtu3_hs_softconn_set(mtu, 1); + mtu3_dev_on_off(mtu, 1); } void mtu3_stop(struct mtu3 *mtu) @@ -231,7 +283,7 @@ void mtu3_stop(struct mtu3 *mtu) mtu3_intr_status_clear(mtu); if (mtu->softconnect) - mtu3_hs_softconn_set(mtu, 0); + mtu3_dev_on_off(mtu, 0); mtu->is_active = 0; mtu3_setbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); @@ -362,7 +414,10 @@ void mtu3_deconfig_ep(struct mtu3 *mtu, struct mtu3_ep *mep) } /* - * 1. when supports only HS, the fifo is shared for all EPs, and + * Two scenarios: + * 1. when device IP supports SS, the fifo of EP0, TX EPs, RX EPs + * are separated; + * 2. when supports only HS, the fifo is shared for all EPs, and * the capability registers of @EPNTXFFSZ or @EPNRXFFSZ indicate * the total fifo size of non-ep0, and ep0's is fixed to 64B, * so the total fifo size is 64B + @EPNTXFFSZ; @@ -376,18 +431,33 @@ static void get_ep_fifo_config(struct mtu3 *mtu) struct mtu3_fifo_info *rx_fifo; u32 fifosize; - fifosize = mtu3_readl(mtu->mac_base, U3D_CAP_EPNTXFFSZ); - tx_fifo = &mtu->tx_fifo; - tx_fifo->base = MTU3_U2_IP_EP0_FIFO_SIZE; - tx_fifo->limit = (fifosize / MTU3_EP_FIFO_UNIT) >> 1; - bitmap_zero(tx_fifo->bitmap, MTU3_FIFO_BIT_SIZE); - - rx_fifo = &mtu->rx_fifo; - rx_fifo->base = - tx_fifo->base + tx_fifo->limit * MTU3_EP_FIFO_UNIT; - rx_fifo->limit = tx_fifo->limit; - bitmap_zero(rx_fifo->bitmap, MTU3_FIFO_BIT_SIZE); - mtu->slot = MTU3_U2_IP_SLOT_DEFAULT; + if (mtu->is_u3_ip) { + fifosize = mtu3_readl(mtu->mac_base, U3D_CAP_EPNTXFFSZ); + tx_fifo = &mtu->tx_fifo; + tx_fifo->base = 0; + tx_fifo->limit = fifosize / MTU3_EP_FIFO_UNIT; + bitmap_zero(tx_fifo->bitmap, MTU3_FIFO_BIT_SIZE); + + fifosize = mtu3_readl(mtu->mac_base, U3D_CAP_EPNRXFFSZ); + rx_fifo = &mtu->rx_fifo; + rx_fifo->base = 0; + rx_fifo->limit = fifosize / MTU3_EP_FIFO_UNIT; + bitmap_zero(rx_fifo->bitmap, MTU3_FIFO_BIT_SIZE); + mtu->slot = MTU3_U3_IP_SLOT_DEFAULT; + } else { + fifosize = mtu3_readl(mtu->mac_base, U3D_CAP_EPNTXFFSZ); + tx_fifo = &mtu->tx_fifo; + tx_fifo->base = MTU3_U2_IP_EP0_FIFO_SIZE; + tx_fifo->limit = (fifosize / MTU3_EP_FIFO_UNIT) >> 1; + bitmap_zero(tx_fifo->bitmap, MTU3_FIFO_BIT_SIZE); + + rx_fifo = &mtu->rx_fifo; + rx_fifo->base = + tx_fifo->base + tx_fifo->limit * MTU3_EP_FIFO_UNIT; + rx_fifo->limit = tx_fifo->limit; + bitmap_zero(rx_fifo->bitmap, MTU3_FIFO_BIT_SIZE); + mtu->slot = MTU3_U2_IP_SLOT_DEFAULT; + } dev_dbg(mtu->dev, "%s, TX: base-%d, limit-%d; RX: base-%d, limit-%d\n", __func__, tx_fifo->base, tx_fifo->limit, @@ -416,17 +486,21 @@ static int mtu3_mem_alloc(struct mtu3 *mtu) void __iomem *mbase = mtu->mac_base; struct mtu3_ep *ep_array; int in_ep_num, out_ep_num; - u32 cap_epinfo; + u32 cap_epinfo, cap_dev; int ret; int i; mtu->hw_version = mtu3_readl(mtu->ippc_base, U3D_SSUSB_HW_ID); + cap_dev = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); + mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(cap_dev); + cap_epinfo = mtu3_readl(mbase, U3D_CAP_EPINFO); in_ep_num = CAP_TX_EP_NUM(cap_epinfo); out_ep_num = CAP_RX_EP_NUM(cap_epinfo); - dev_info(mtu->dev, "IP version 0x%x\n", mtu->hw_version); + dev_info(mtu->dev, "IP version 0x%x(%s IP)\n", mtu->hw_version, + mtu->is_u3_ip ? "U3" : "U2"); dev_info(mtu->dev, "fifosz/epnum: Tx=%#x/%d, Rx=%#x/%d\n", mtu3_readl(mbase, U3D_CAP_EPNTXFFSZ), in_ep_num, mtu3_readl(mbase, U3D_CAP_EPNRXFFSZ), out_ep_num); @@ -469,6 +543,27 @@ static void mtu3_mem_free(struct mtu3 *mtu) kfree(mtu->ep_array); } +static void mtu3_set_speed(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + + if (!mtu->is_u3_ip && (mtu->max_speed > USB_SPEED_HIGH)) + mtu->max_speed = USB_SPEED_HIGH; + + if (mtu->max_speed == USB_SPEED_FULL) { + /* disable U3 SS function */ + mtu3_clrbits(mbase, U3D_USB3_CONFIG, USB3_EN); + /* disable HS function */ + mtu3_clrbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); + } else if (mtu->max_speed == USB_SPEED_HIGH) { + mtu3_clrbits(mbase, U3D_USB3_CONFIG, USB3_EN); + /* HS/FS detected by HW */ + mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); + } + dev_info(mtu->dev, "max_speed: %s\n", + usb_speed_string(mtu->max_speed)); +} + static void mtu3_regs_init(struct mtu3 *mtu) { @@ -478,9 +573,16 @@ static void mtu3_regs_init(struct mtu3 *mtu) mtu3_intr_disable(mtu); mtu3_intr_status_clear(mtu); - mtu3_clrbits(mbase, U3D_USB3_CONFIG, USB3_EN); - /* HS/FS detected by HW */ - mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); + if (mtu->is_u3_ip) { + /* disable LGO_U1/U2 by default */ + mtu3_clrbits(mbase, U3D_LINK_POWER_CONTROL, + SW_U1_ACCEPT_ENABLE | SW_U2_ACCEPT_ENABLE | + SW_U1_REQUEST_ENABLE | SW_U2_REQUEST_ENABLE); + /* device responses to u3_exit from host automatically */ + mtu3_clrbits(mbase, U3D_LTSSM_CTRL, SOFT_U3_EXIT_EN); + } + + mtu3_set_speed(mtu); /* delay about 0.1us from detecting reset to send chirp-K */ mtu3_clrbits(mbase, U3D_LINK_RESET_INFO, WTCHRP_MSK); @@ -530,6 +632,10 @@ static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, LPM_BESL_STALL | LPM_BESLD_STALL); break; + case MTU3_SPEED_SUPER: + udev_speed = USB_SPEED_SUPER; + maxpkt = 512; + break; default: udev_speed = USB_SPEED_UNKNOWN; break; @@ -548,6 +654,34 @@ static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) return IRQ_HANDLED; } +static irqreturn_t mtu3_u3_ltssm_isr(struct mtu3 *mtu) +{ + void __iomem *mbase = mtu->mac_base; + u32 ltssm; + + ltssm = mtu3_readl(mbase, U3D_LTSSM_INTR); + ltssm &= mtu3_readl(mbase, U3D_LTSSM_INTR_ENABLE); + mtu3_writel(mbase, U3D_LTSSM_INTR, ltssm); /* W1C */ + dev_dbg(mtu->dev, "=== LTSSM[%x] ===\n", ltssm); + + if (ltssm & (HOT_RST_INTR | WARM_RST_INTR)) + mtu3_gadget_reset(mtu); + + if (ltssm & VBUS_FALL_INTR) + mtu3_ss_func_set(mtu, false); + + if (ltssm & VBUS_RISE_INTR) + mtu3_ss_func_set(mtu, true); + + if (ltssm & EXIT_U3_INTR) + mtu3_gadget_resume(mtu); + + if (ltssm & ENTER_U3_INTR) + mtu3_gadget_suspend(mtu); + + return IRQ_HANDLED; +} + static irqreturn_t mtu3_u2_common_isr(struct mtu3 *mtu) { void __iomem *mbase = mtu->mac_base; @@ -588,6 +722,9 @@ irqreturn_t mtu3_irq(int irq, void *data) if (level1 & MAC2_INTR) mtu3_u2_common_isr(mtu); + if (level1 & MAC3_INTR) + mtu3_u3_ltssm_isr(mtu); + if (level1 & BMU_INTR) mtu3_ep0_isr(mtu); @@ -633,6 +770,27 @@ int ssusb_gadget_init(struct mtu3 *mtu) struct device *dev = mtu->dev; int ret; + mtu->max_speed = usb_get_maximum_speed(dev); + + /* check the max_speed parameter */ + switch (mtu->max_speed) { + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + case USB_SPEED_SUPER: + break; + default: + dev_err(dev, "invalid max_speed: %s\n", + usb_speed_string(mtu->max_speed)); + /* fall through */ + case USB_SPEED_UNKNOWN: + /* default as SS */ + mtu->max_speed = USB_SPEED_SUPER; + break; + } + + dev_dbg(dev, "mac_base=0x%p, ippc_base=0x%p\n", + mtu->mac_base, mtu->ippc_base); + ret = mtu3_hw_init(mtu); if (ret) { dev_err(dev, "mtu3 hw init failed:%d\n", ret); diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index 0e25e0f9e605..84f3fe169928 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -73,6 +73,7 @@ static void nuke(struct mtu3_ep *mep, const int status) static int mtu3_ep_enable(struct mtu3_ep *mep) { const struct usb_endpoint_descriptor *desc; + const struct usb_ss_ep_comp_descriptor *comp_desc; struct mtu3 *mtu = mep->mtu; u32 interval = 0; u32 mult = 0; @@ -81,11 +82,24 @@ static int mtu3_ep_enable(struct mtu3_ep *mep) int ret; desc = mep->desc; + comp_desc = mep->comp_desc; mep->type = usb_endpoint_type(desc); max_packet = usb_endpoint_maxp(desc); mep->maxp = max_packet & GENMASK(10, 0); switch (mtu->g.speed) { + case USB_SPEED_SUPER: + if (usb_endpoint_xfer_int(desc) || + usb_endpoint_xfer_isoc(desc)) { + interval = desc->bInterval; + interval = clamp_val(interval, 1, 16) - 1; + if (usb_endpoint_xfer_isoc(desc) && comp_desc) + mult = comp_desc->bmAttributes; + } + if (comp_desc) + burst = comp_desc->bMaxBurst; + + break; case USB_SPEED_HIGH: if (usb_endpoint_xfer_isoc(desc) || usb_endpoint_xfer_int(desc)) { @@ -103,6 +117,7 @@ static int mtu3_ep_enable(struct mtu3_ep *mep) mep->ep.maxpacket = mep->maxp; mep->ep.desc = desc; + mep->ep.comp_desc = comp_desc; /* slot mainly affects bulk/isoc transfer, so ignore int */ mep->slot = usb_endpoint_xfer_int(desc) ? 0 : mtu->slot; @@ -135,6 +150,7 @@ static int mtu3_ep_disable(struct mtu3_ep *mep) mep->desc = NULL; mep->ep.desc = NULL; + mep->comp_desc = NULL; mep->type = 0; mep->flags = 0; @@ -178,6 +194,7 @@ static int mtu3_gadget_ep_enable(struct usb_ep *ep, spin_lock_irqsave(&mtu->lock, flags); mep->desc = desc; + mep->comp_desc = ep->comp_desc; ret = mtu3_ep_enable(mep); if (ret) @@ -439,13 +456,15 @@ static int mtu3_gadget_wakeup(struct usb_gadget *gadget) return -EOPNOTSUPP; spin_lock_irqsave(&mtu->lock, flags); - - mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME); - spin_unlock_irqrestore(&mtu->lock, flags); - usleep_range(10000, 11000); - spin_lock_irqsave(&mtu->lock, flags); - mtu3_clrbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME); - + if (mtu->g.speed == USB_SPEED_SUPER) { + mtu3_setbits(mtu->mac_base, U3D_LINK_POWER_CONTROL, UX_EXIT); + } else { + mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME); + spin_unlock_irqrestore(&mtu->lock, flags); + usleep_range(10000, 11000); + spin_lock_irqsave(&mtu->lock, flags); + mtu3_clrbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME); + } spin_unlock_irqrestore(&mtu->lock, flags); return 0; } @@ -476,7 +495,7 @@ static int mtu3_gadget_pullup(struct usb_gadget *gadget, int is_on) mtu->softconnect = is_on; } else if (is_on != mtu->softconnect) { mtu->softconnect = is_on; - mtu3_hs_softconn_set(mtu, is_on); + mtu3_dev_on_off(mtu, is_on); } spin_unlock_irqrestore(&mtu->lock, flags); @@ -524,7 +543,7 @@ static void stop_activity(struct mtu3 *mtu) /* deactivate the hardware */ if (mtu->softconnect) { mtu->softconnect = 0; - mtu3_hs_softconn_set(mtu, 0); + mtu3_dev_on_off(mtu, 0); } /* @@ -587,14 +606,14 @@ static void init_hw_ep(struct mtu3 *mtu, struct mtu3_ep *mep, mep->ep.name = mep->name; INIT_LIST_HEAD(&mep->ep.ep_list); - /* initialize maxpacket as HS */ + /* initialize maxpacket as SS */ if (!epnum) { - usb_ep_set_maxpacket_limit(&mep->ep, 64); + usb_ep_set_maxpacket_limit(&mep->ep, 512); mep->ep.caps.type_control = true; mep->ep.ops = &mtu3_ep0_ops; mtu->g.ep0 = &mep->ep; } else { - usb_ep_set_maxpacket_limit(&mep->ep, 512); + usb_ep_set_maxpacket_limit(&mep->ep, 1024); mep->ep.caps.type_iso = true; mep->ep.caps.type_bulk = true; mep->ep.caps.type_int = true; @@ -637,7 +656,7 @@ int mtu3_gadget_setup(struct mtu3 *mtu) int ret; mtu->g.ops = &mtu3_gadget_ops; - mtu->g.max_speed = USB_SPEED_HIGH; + mtu->g.max_speed = mtu->max_speed; mtu->g.speed = USB_SPEED_UNKNOWN; mtu->g.sg_supported = 0; mtu->g.name = MTU3_DRIVER_NAME; diff --git a/drivers/usb/mtu3/mtu3_gadget_ep0.c b/drivers/usb/mtu3/mtu3_gadget_ep0.c index 4e2c2babad20..2d7427b48775 100644 --- a/drivers/usb/mtu3/mtu3_gadget_ep0.c +++ b/drivers/usb/mtu3/mtu3_gadget_ep0.c @@ -161,6 +161,41 @@ static int ep0_queue(struct mtu3_ep *mep0, struct mtu3_request *mreq); static void ep0_dummy_complete(struct usb_ep *ep, struct usb_request *req) {} +static void ep0_set_sel_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct mtu3_request *mreq; + struct mtu3 *mtu; + struct usb_set_sel_req sel; + + memcpy(&sel, req->buf, sizeof(sel)); + + mreq = to_mtu3_request(req); + mtu = mreq->mtu; + dev_dbg(mtu->dev, "u1sel:%d, u1pel:%d, u2sel:%d, u2pel:%d\n", + sel.u1_sel, sel.u1_pel, sel.u2_sel, sel.u2_pel); +} + +/* queue data stage to handle 6 byte SET_SEL request */ +static int ep0_set_sel(struct mtu3 *mtu, struct usb_ctrlrequest *setup) +{ + int ret; + u16 length = le16_to_cpu(setup->wLength); + + if (unlikely(length != 6)) { + dev_err(mtu->dev, "%s wrong wLength:%d\n", + __func__, length); + return -EINVAL; + } + + mtu->ep0_req.mep = mtu->ep0; + mtu->ep0_req.request.length = 6; + mtu->ep0_req.request.buf = mtu->setup_buf; + mtu->ep0_req.request.complete = ep0_set_sel_complete; + ret = ep0_queue(mtu->ep0, &mtu->ep0_req); + + return ret < 0 ? ret : 1; +} + static int ep0_get_status(struct mtu3 *mtu, const struct usb_ctrlrequest *setup) { @@ -174,6 +209,15 @@ ep0_get_status(struct mtu3 *mtu, const struct usb_ctrlrequest *setup) case USB_RECIP_DEVICE: result[0] = mtu->is_self_powered << USB_DEVICE_SELF_POWERED; result[0] |= mtu->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; + /* superspeed only */ + if (mtu->g.speed == USB_SPEED_SUPER) { + result[0] |= mtu->u1_enable << USB_DEV_STAT_U1_ENABLED; + result[0] |= mtu->u2_enable << USB_DEV_STAT_U2_ENABLED; + } + + dev_dbg(mtu->dev, "%s result=%x, U1=%x, U2=%x\n", __func__, + result[0], mtu->u1_enable, mtu->u2_enable); + break; case USB_RECIP_INTERFACE: break; @@ -265,7 +309,9 @@ out: static int ep0_handle_feature_dev(struct mtu3 *mtu, struct usb_ctrlrequest *setup, bool set) { + void __iomem *mbase = mtu->mac_base; int handled = -EINVAL; + u32 lpc; switch (le16_to_cpu(setup->wValue)) { case USB_DEVICE_REMOTE_WAKEUP: @@ -279,6 +325,36 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu, handled = handle_test_mode(mtu, setup); break; + case USB_DEVICE_U1_ENABLE: + if (mtu->g.speed != USB_SPEED_SUPER || + mtu->g.state != USB_STATE_CONFIGURED) + break; + + lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); + if (set) + lpc |= SW_U1_ACCEPT_ENABLE; + else + lpc &= ~SW_U1_ACCEPT_ENABLE; + mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc); + + mtu->u1_enable = !!set; + handled = 1; + break; + case USB_DEVICE_U2_ENABLE: + if (mtu->g.speed != USB_SPEED_SUPER || + mtu->g.state != USB_STATE_CONFIGURED) + break; + + lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); + if (set) + lpc |= SW_U2_ACCEPT_ENABLE; + else + lpc &= ~SW_U2_ACCEPT_ENABLE; + mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc); + + mtu->u2_enable = !!set; + handled = 1; + break; default: handled = -EINVAL; break; @@ -303,6 +379,17 @@ static int ep0_handle_feature(struct mtu3 *mtu, case USB_RECIP_DEVICE: handled = ep0_handle_feature_dev(mtu, setup, set); break; + case USB_RECIP_INTERFACE: + /* superspeed only */ + if ((value == USB_INTRF_FUNC_SUSPEND) + && (mtu->g.speed == USB_SPEED_SUPER)) { + /* + * forward the request because function drivers + * should handle it + */ + handled = 0; + } + break; case USB_RECIP_ENDPOINT: epnum = index & USB_ENDPOINT_NUMBER_MASK; if (epnum == 0 || epnum >= mtu->num_eps || @@ -390,6 +477,9 @@ static int handle_standard_request(struct mtu3 *mtu, case USB_REQ_GET_STATUS: handled = ep0_get_status(mtu, setup); break; + case USB_REQ_SET_SEL: + handled = ep0_set_sel(mtu, setup); + break; case USB_REQ_SET_ISOCH_DELAY: handled = 1; break; diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h index 08c83c5f6109..212367295276 100644 --- a/drivers/usb/mtu3/mtu3_hw_regs.h +++ b/drivers/usb/mtu3/mtu3_hw_regs.h @@ -260,13 +260,46 @@ /*---------------- SSUSB_USB3_MAC_CSR REGISTER DEFINITION ----------------*/ +#define U3D_LTSSM_CTRL (SSUSB_USB3_MAC_CSR_BASE + 0x0010) #define U3D_USB3_CONFIG (SSUSB_USB3_MAC_CSR_BASE + 0x001C) +#define U3D_LTSSM_INTR_ENABLE (SSUSB_USB3_MAC_CSR_BASE + 0x013C) +#define U3D_LTSSM_INTR (SSUSB_USB3_MAC_CSR_BASE + 0x0140) + /*---------------- SSUSB_USB3_MAC_CSR FIELD DEFINITION ----------------*/ +/* U3D_LTSSM_CTRL */ +#define FORCE_POLLING_FAIL BIT(4) +#define FORCE_RXDETECT_FAIL BIT(3) +#define SOFT_U3_EXIT_EN BIT(2) +#define COMPLIANCE_EN BIT(1) +#define U1_GO_U2_EN BIT(0) + /* U3D_USB3_CONFIG */ #define USB3_EN BIT(0) +/* U3D_LTSSM_INTR_ENABLE */ +/* U3D_LTSSM_INTR */ +#define U3_RESUME_INTR BIT(18) +#define U3_LFPS_TMOUT_INTR BIT(17) +#define VBUS_FALL_INTR BIT(16) +#define VBUS_RISE_INTR BIT(15) +#define RXDET_SUCCESS_INTR BIT(14) +#define EXIT_U3_INTR BIT(13) +#define EXIT_U2_INTR BIT(12) +#define EXIT_U1_INTR BIT(11) +#define ENTER_U3_INTR BIT(10) +#define ENTER_U2_INTR BIT(9) +#define ENTER_U1_INTR BIT(8) +#define ENTER_U0_INTR BIT(7) +#define RECOVERY_INTR BIT(6) +#define WARM_RST_INTR BIT(5) +#define HOT_RST_INTR BIT(4) +#define LOOPBACK_INTR BIT(3) +#define COMPLIANCE_INTR BIT(2) +#define SS_DISABLE_INTR BIT(1) +#define SS_INACTIVE_INTR BIT(0) + /*---------------- SSUSB_USB3_SYS_CSR REGISTER DEFINITION ----------------*/ #define U3D_LINK_UX_INACT_TIMER (SSUSB_USB3_SYS_CSR_BASE + 0x020C) -- cgit v1.2.3 From b3f4e727c1ecec36e628e89298349d9c51a32aac Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Wed, 19 Oct 2016 10:28:25 +0800 Subject: usb: mtu3: host only mode support supports host only mode and the code is ported from host/xhci-mtk.c IPPC register shared between host and device is moved into common glue layer. Signed-off-by: Chunfeng Yun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mtu3/Kconfig | 9 ++ drivers/usb/mtu3/Makefile | 11 +- drivers/usb/mtu3/mtu3.h | 47 ++++++- drivers/usb/mtu3/mtu3_core.c | 42 ++++++- drivers/usb/mtu3/mtu3_dr.h | 85 +++++++++++++ drivers/usb/mtu3/mtu3_host.c | 288 ++++++++++++++++++++++++++++++++++++++++++ drivers/usb/mtu3/mtu3_plat.c | 289 +++++++++++++++++++++++++++++++++---------- 7 files changed, 691 insertions(+), 80 deletions(-) create mode 100644 drivers/usb/mtu3/mtu3_dr.h create mode 100644 drivers/usb/mtu3/mtu3_host.c (limited to 'drivers') diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index 54dadee36f4d..59e3f6fa0da0 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig @@ -4,6 +4,7 @@ config USB_MTU3 tristate "MediaTek USB3 Dual Role controller" depends on (USB || USB_GADGET) && HAS_DMA depends on ARCH_MEDIATEK || COMPILE_TEST + select USB_XHCI_MTK if USB_SUPPORT && USB_XHCI_HCD help Say Y or M here if your system runs on MediaTek SoCs with Dual Role SuperSpeed USB controller. You can select usb @@ -18,8 +19,16 @@ config USB_MTU3 if USB_MTU3 choice bool "MTU3 Mode Selection" + default USB_MTU3_HOST if (USB && !USB_GADGET) default USB_MTU3_GADGET if (!USB && USB_GADGET) +config USB_MTU3_HOST + bool "Host only mode" + depends on USB=y || USB=USB_MTU3 + help + Select this when you want to use MTU3 in host mode only, + thereby the gadget feature will be regressed. + config USB_MTU3_GADGET bool "Gadget only mode" depends on USB_GADGET=y || USB_GADGET=USB_MTU3 diff --git a/drivers/usb/mtu3/Makefile b/drivers/usb/mtu3/Makefile index 532c2570c58b..41e45e99ee6b 100644 --- a/drivers/usb/mtu3/Makefile +++ b/drivers/usb/mtu3/Makefile @@ -1,2 +1,11 @@ obj-$(CONFIG_USB_MTU3) += mtu3.o -mtu3-y := mtu3_plat.o mtu3_core.o mtu3_gadget_ep0.o mtu3_gadget.o mtu3_qmu.o + +mtu3-y := mtu3_plat.o + +ifneq ($(filter y,$(CONFIG_USB_MTU3_HOST)),) + mtu3-y += mtu3_host.o +endif + +ifneq ($(filter y,$(CONFIG_USB_MTU3_GADGET)),) + mtu3-y += mtu3_core.o mtu3_gadget_ep0.o mtu3_gadget.o mtu3_qmu.o +endif diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 41a04732a274..a7c0ce873c44 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -172,6 +172,40 @@ struct mtu3_gpd_ring { struct qmu_gpd *enqueue; struct qmu_gpd *dequeue; }; +/** + * @mac_base: register base address of device MAC, exclude xHCI's + * @ippc_base: register base address of ip port controller interface (IPPC) + * @vusb33: usb3.3V shared by device/host IP + * @sys_clk: system clock of mtu3, shared by device/host IP + * @dr_mode: works in which mode: + * host only, device only or dual-role mode + * @u2_ports: number of usb2.0 host ports + * @u3_ports: number of usb3.0 host ports + * @wakeup_en: it's true when supports remote wakeup in host mode + * @wk_deb_p0: port0's wakeup debounce clock + * @wk_deb_p1: it's optional, and depends on port1 is supported or not + */ +struct ssusb_mtk { + struct device *dev; + struct mtu3 *u3d; + void __iomem *mac_base; + void __iomem *ippc_base; + struct phy **phys; + int num_phys; + /* common power & clock */ + struct regulator *vusb33; + struct clk *sys_clk; + /* otg */ + enum usb_dr_mode dr_mode; + bool is_host; + int u2_ports; + int u3_ports; + /* usb wakeup for host mode */ + bool wakeup_en; + struct clk *wk_deb_p0; + struct clk *wk_deb_p1; + struct regmap *pericfg; +}; /** * @fifo_size: it is (@slot + 1) * @fifo_seg_size @@ -210,6 +244,11 @@ struct mtu3_request { int epnum; }; +static inline struct ssusb_mtk *dev_to_ssusb(struct device *dev) +{ + return dev_get_drvdata(dev); +} + /** * struct mtu3 - device driver instance data. * @slot: MTU3_U2_IP_SLOT_DEFAULT for U2 IP only, @@ -222,12 +261,10 @@ struct mtu3_request { */ struct mtu3 { spinlock_t lock; + struct ssusb_mtk *ssusb; struct device *dev; void __iomem *mac_base; void __iomem *ippc_base; - struct phy *phy; - struct regulator *vusb33; - struct clk *sys_clk; int irq; struct mtu3_fifo_info tx_fifo; @@ -320,7 +357,7 @@ static inline void mtu3_clrbits(void __iomem *base, u32 offset, u32 bits) writel((tmp & ~(bits)), addr); } -int ssusb_check_clocks(struct mtu3 *mtu, u32 ex_clks); +int ssusb_check_clocks(struct ssusb_mtk *ssusb, u32 ex_clks); struct usb_request *mtu3_alloc_request(struct usb_ep *ep, gfp_t gfp_flags); void mtu3_free_request(struct usb_ep *ep, struct usb_request *req); void mtu3_req_complete(struct mtu3_ep *mep, @@ -341,8 +378,6 @@ void mtu3_gadget_reset(struct mtu3 *mtu); void mtu3_gadget_suspend(struct mtu3 *mtu); void mtu3_gadget_resume(struct mtu3 *mtu); void mtu3_gadget_disconnect(struct mtu3 *mtu); -int ssusb_gadget_init(struct mtu3 *mtu); -void ssusb_gadget_exit(struct mtu3 *mtu); irqreturn_t mtu3_ep0_isr(struct mtu3 *mtu); extern const struct usb_ep_ops mtu3_ep0_ops; diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index f9817ad53e3c..2eef9727312c 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -116,7 +116,7 @@ static int mtu3_device_enable(struct mtu3 *mtu) SSUSB_U2_PORT_HOST_SEL)); mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); - return ssusb_check_clocks(mtu, check_clk); + return ssusb_check_clocks(mtu->ssusb, check_clk); } static void mtu3_device_disable(struct mtu3 *mtu) @@ -765,11 +765,38 @@ static void mtu3_hw_exit(struct mtu3 *mtu) /*-------------------------------------------------------------------------*/ -int ssusb_gadget_init(struct mtu3 *mtu) +int ssusb_gadget_init(struct ssusb_mtk *ssusb) { - struct device *dev = mtu->dev; - int ret; + struct device *dev = ssusb->dev; + struct platform_device *pdev = to_platform_device(dev); + struct mtu3 *mtu = NULL; + struct resource *res; + int ret = -ENOMEM; + + mtu = devm_kzalloc(dev, sizeof(struct mtu3), GFP_KERNEL); + if (mtu == NULL) + return -ENOMEM; + + mtu->irq = platform_get_irq(pdev, 0); + if (mtu->irq <= 0) { + dev_err(dev, "fail to get irq number\n"); + return -ENODEV; + } + dev_info(dev, "irq %d\n", mtu->irq); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); + mtu->mac_base = devm_ioremap_resource(dev, res); + if (IS_ERR(mtu->mac_base)) { + dev_err(dev, "error mapping memory for dev mac\n"); + return PTR_ERR(mtu->mac_base); + } + + spin_lock_init(&mtu->lock); + mtu->dev = dev; + mtu->ippc_base = ssusb->ippc_base; + ssusb->mac_base = mtu->mac_base; + ssusb->u3d = mtu; + mtu->ssusb = ssusb; mtu->max_speed = usb_get_maximum_speed(dev); /* check the max_speed parameter */ @@ -820,14 +847,17 @@ gadget_err: irq_err: mtu3_hw_exit(mtu); + ssusb->u3d = NULL; dev_err(dev, " %s() fail...\n", __func__); return ret; } -void ssusb_gadget_exit(struct mtu3 *mtu) +void ssusb_gadget_exit(struct ssusb_mtk *ssusb) { + struct mtu3 *mtu = ssusb->u3d; + mtu3_gadget_cleanup(mtu); - device_init_wakeup(mtu->dev, false); + device_init_wakeup(ssusb->dev, false); mtu3_hw_exit(mtu); } diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h new file mode 100644 index 000000000000..07066f4093ab --- /dev/null +++ b/drivers/usb/mtu3/mtu3_dr.h @@ -0,0 +1,85 @@ +/* + * mtu3_dr.h - dual role switch and host glue layer header + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _MTU3_DR_H_ +#define _MTU3_DR_H_ + +#if IS_ENABLED(CONFIG_USB_MTU3_HOST) + +int ssusb_host_init(struct ssusb_mtk *ssusb, struct device_node *parent_dn); +void ssusb_host_exit(struct ssusb_mtk *ssusb); +int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb, + struct device_node *dn); +int ssusb_host_enable(struct ssusb_mtk *ssusb); +int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend); +int ssusb_wakeup_enable(struct ssusb_mtk *ssusb); +void ssusb_wakeup_disable(struct ssusb_mtk *ssusb); + +#else + +static inline int ssusb_host_init(struct ssusb_mtk *ssusb, + + struct device_node *parent_dn) +{ + return 0; +} + +static inline void ssusb_host_exit(struct ssusb_mtk *ssusb) +{} + +static inline int ssusb_wakeup_of_property_parse( + struct ssusb_mtk *ssusb, struct device_node *dn) +{ + return 0; +} + +static inline int ssusb_host_enable(struct ssusb_mtk *ssusb) +{ + return 0; +} + +static inline int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend) +{ + return 0; +} + +static inline int ssusb_wakeup_enable(struct ssusb_mtk *ssusb) +{ + return 0; +} + +static inline void ssusb_wakeup_disable(struct ssusb_mtk *ssusb) +{} + +#endif + + +#if IS_ENABLED(CONFIG_USB_MTU3_GADGET) +int ssusb_gadget_init(struct ssusb_mtk *ssusb); +void ssusb_gadget_exit(struct ssusb_mtk *ssusb); +#else +static inline int ssusb_gadget_init(struct ssusb_mtk *ssusb) +{ + return 0; +} + +static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb) +{} +#endif + +#endif /* _MTU3_DR_H_ */ diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c new file mode 100644 index 000000000000..361d6d844ce5 --- /dev/null +++ b/drivers/usb/mtu3/mtu3_host.c @@ -0,0 +1,288 @@ +/* + * mtu3_dr.c - dual role switch and host glue layer + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mtu3.h" +#include "mtu3_dr.h" + +#define PERI_WK_CTRL1 0x404 +#define UWK_CTL1_IS_C(x) (((x) & 0xf) << 26) +#define UWK_CTL1_IS_E BIT(25) +#define UWK_CTL1_IDDIG_C(x) (((x) & 0xf) << 11) /* cycle debounce */ +#define UWK_CTL1_IDDIG_E BIT(10) /* enable debounce */ +#define UWK_CTL1_IDDIG_P BIT(9) /* polarity */ +#define UWK_CTL1_IS_P BIT(6) /* polarity for ip sleep */ + +/* + * ip-sleep wakeup mode: + * all clocks can be turn off, but power domain should be kept on + */ +static void ssusb_wakeup_ip_sleep_en(struct ssusb_mtk *ssusb) +{ + u32 tmp; + struct regmap *pericfg = ssusb->pericfg; + + regmap_read(pericfg, PERI_WK_CTRL1, &tmp); + tmp &= ~UWK_CTL1_IS_P; + tmp &= ~(UWK_CTL1_IS_C(0xf)); + tmp |= UWK_CTL1_IS_C(0x8); + regmap_write(pericfg, PERI_WK_CTRL1, tmp); + regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_IS_E); + + regmap_read(pericfg, PERI_WK_CTRL1, &tmp); + dev_dbg(ssusb->dev, "%s(): WK_CTRL1[P6,E25,C26:29]=%#x\n", + __func__, tmp); +} + +static void ssusb_wakeup_ip_sleep_dis(struct ssusb_mtk *ssusb) +{ + u32 tmp; + + regmap_read(ssusb->pericfg, PERI_WK_CTRL1, &tmp); + tmp &= ~UWK_CTL1_IS_E; + regmap_write(ssusb->pericfg, PERI_WK_CTRL1, tmp); +} + +int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb, + struct device_node *dn) +{ + struct device *dev = ssusb->dev; + + /* + * Wakeup function is optional, so it is not an error if this property + * does not exist, and in such case, no need to get relative + * properties anymore. + */ + ssusb->wakeup_en = of_property_read_bool(dn, "mediatek,enable-wakeup"); + if (!ssusb->wakeup_en) + return 0; + + ssusb->wk_deb_p0 = devm_clk_get(dev, "wakeup_deb_p0"); + if (IS_ERR(ssusb->wk_deb_p0)) { + dev_err(dev, "fail to get wakeup_deb_p0\n"); + return PTR_ERR(ssusb->wk_deb_p0); + } + + if (of_property_read_bool(dn, "wakeup_deb_p1")) { + ssusb->wk_deb_p1 = devm_clk_get(dev, "wakeup_deb_p1"); + if (IS_ERR(ssusb->wk_deb_p1)) { + dev_err(dev, "fail to get wakeup_deb_p1\n"); + return PTR_ERR(ssusb->wk_deb_p1); + } + } + + ssusb->pericfg = syscon_regmap_lookup_by_phandle(dn, + "mediatek,syscon-wakeup"); + if (IS_ERR(ssusb->pericfg)) { + dev_err(dev, "fail to get pericfg regs\n"); + return PTR_ERR(ssusb->pericfg); + } + + return 0; +} + +static int ssusb_wakeup_clks_enable(struct ssusb_mtk *ssusb) +{ + int ret; + + ret = clk_prepare_enable(ssusb->wk_deb_p0); + if (ret) { + dev_err(ssusb->dev, "failed to enable wk_deb_p0\n"); + goto usb_p0_err; + } + + ret = clk_prepare_enable(ssusb->wk_deb_p1); + if (ret) { + dev_err(ssusb->dev, "failed to enable wk_deb_p1\n"); + goto usb_p1_err; + } + + return 0; + +usb_p1_err: + clk_disable_unprepare(ssusb->wk_deb_p0); +usb_p0_err: + return -EINVAL; +} + +static void ssusb_wakeup_clks_disable(struct ssusb_mtk *ssusb) +{ + clk_disable_unprepare(ssusb->wk_deb_p1); + clk_disable_unprepare(ssusb->wk_deb_p0); +} + +static void host_ports_num_get(struct ssusb_mtk *ssusb) +{ + u32 xhci_cap; + + xhci_cap = mtu3_readl(ssusb->ippc_base, U3D_SSUSB_IP_XHCI_CAP); + ssusb->u2_ports = SSUSB_IP_XHCI_U2_PORT_NUM(xhci_cap); + ssusb->u3_ports = SSUSB_IP_XHCI_U3_PORT_NUM(xhci_cap); + + dev_dbg(ssusb->dev, "host - u2_ports:%d, u3_ports:%d\n", + ssusb->u2_ports, ssusb->u3_ports); +} + +/* only configure ports will be used later */ +int ssusb_host_enable(struct ssusb_mtk *ssusb) +{ + void __iomem *ibase = ssusb->ippc_base; + int num_u3p = ssusb->u3_ports; + int num_u2p = ssusb->u2_ports; + u32 check_clk; + u32 value; + int i; + + /* power on host ip */ + mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN); + + /* power on and enable all u3 ports */ + for (i = 0; i < num_u3p; i++) { + value = mtu3_readl(ibase, SSUSB_U3_CTRL(i)); + value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS); + value |= SSUSB_U3_PORT_HOST_SEL; + mtu3_writel(ibase, SSUSB_U3_CTRL(i), value); + } + + /* power on and enable all u2 ports */ + for (i = 0; i < num_u2p; i++) { + value = mtu3_readl(ibase, SSUSB_U2_CTRL(i)); + value &= ~(SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS); + value |= SSUSB_U2_PORT_HOST_SEL; + mtu3_writel(ibase, SSUSB_U2_CTRL(i), value); + } + + check_clk = SSUSB_XHCI_RST_B_STS; + if (num_u3p) + check_clk = SSUSB_U3_MAC_RST_B_STS; + + return ssusb_check_clocks(ssusb, check_clk); +} + +int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend) +{ + void __iomem *ibase = ssusb->ippc_base; + int num_u3p = ssusb->u3_ports; + int num_u2p = ssusb->u2_ports; + u32 value; + int ret; + int i; + + /* power down and disable all u3 ports */ + for (i = 0; i < num_u3p; i++) { + value = mtu3_readl(ibase, SSUSB_U3_CTRL(i)); + value |= SSUSB_U3_PORT_PDN; + value |= suspend ? 0 : SSUSB_U3_PORT_DIS; + mtu3_writel(ibase, SSUSB_U3_CTRL(i), value); + } + + /* power down and disable all u2 ports */ + for (i = 0; i < num_u2p; i++) { + value = mtu3_readl(ibase, SSUSB_U2_CTRL(i)); + value |= SSUSB_U2_PORT_PDN; + value |= suspend ? 0 : SSUSB_U2_PORT_DIS; + mtu3_writel(ibase, SSUSB_U2_CTRL(i), value); + } + + /* power down host ip */ + mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN); + + if (!suspend) + return 0; + + /* wait for host ip to sleep */ + ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS1, value, + (value & SSUSB_IP_SLEEP_STS), 100, 100000); + if (ret) + dev_err(ssusb->dev, "ip sleep failed!!!\n"); + + return ret; +} + +static void ssusb_host_setup(struct ssusb_mtk *ssusb) +{ + host_ports_num_get(ssusb); + + /* + * power on host and power on/enable all ports + * if support OTG, gadget driver will switch port0 to device mode + */ + ssusb_host_enable(ssusb); +} + +static void ssusb_host_cleanup(struct ssusb_mtk *ssusb) +{ + ssusb_host_disable(ssusb, false); +} + +/* + * If host supports multiple ports, the VBUSes(5V) of ports except port0 + * which supports OTG are better to be enabled by default in DTS. + * Because the host driver will keep link with devices attached when system + * enters suspend mode, so no need to control VBUSes after initialization. + */ +int ssusb_host_init(struct ssusb_mtk *ssusb, struct device_node *parent_dn) +{ + struct device *parent_dev = ssusb->dev; + int ret; + + ssusb_host_setup(ssusb); + + ret = of_platform_populate(parent_dn, NULL, NULL, parent_dev); + if (ret) { + dev_dbg(parent_dev, "failed to create child devices at %s\n", + parent_dn->full_name); + return ret; + } + + dev_info(parent_dev, "xHCI platform device register success...\n"); + + return 0; +} + +void ssusb_host_exit(struct ssusb_mtk *ssusb) +{ + of_platform_depopulate(ssusb->dev); + ssusb_host_cleanup(ssusb); +} + +int ssusb_wakeup_enable(struct ssusb_mtk *ssusb) +{ + int ret = 0; + + if (ssusb->wakeup_en) { + ret = ssusb_wakeup_clks_enable(ssusb); + ssusb_wakeup_ip_sleep_en(ssusb); + } + return ret; +} + +void ssusb_wakeup_disable(struct ssusb_mtk *ssusb) +{ + if (ssusb->wakeup_en) { + ssusb_wakeup_ip_sleep_dis(ssusb); + ssusb_wakeup_clks_disable(ssusb); + } +} diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 52fc0edbe3ee..facb76c2877b 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -21,14 +21,16 @@ #include #include #include +#include #include #include "mtu3.h" +#include "mtu3_dr.h" /* u2-port0 should be powered on and enabled; */ -int ssusb_check_clocks(struct mtu3 *mtu, u32 ex_clks) +int ssusb_check_clocks(struct ssusb_mtk *ssusb, u32 ex_clks) { - void __iomem *ibase = mtu->ippc_base; + void __iomem *ibase = ssusb->ippc_base; u32 value, check_val; int ret; @@ -38,136 +40,209 @@ int ssusb_check_clocks(struct mtu3 *mtu, u32 ex_clks) ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS1, value, (check_val == (value & check_val)), 100, 20000); if (ret) { - dev_err(mtu->dev, "clks of sts1 are not stable!\n"); + dev_err(ssusb->dev, "clks of sts1 are not stable!\n"); return ret; } ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS2, value, (value & SSUSB_U2_MAC_SYS_RST_B_STS), 100, 10000); if (ret) { - dev_err(mtu->dev, "mac2 clock is not stable\n"); + dev_err(ssusb->dev, "mac2 clock is not stable\n"); return ret; } return 0; } -static int ssusb_rscs_init(struct mtu3 *mtu) +static int ssusb_phy_init(struct ssusb_mtk *ssusb) +{ + int i; + int ret; + + for (i = 0; i < ssusb->num_phys; i++) { + ret = phy_init(ssusb->phys[i]); + if (ret) + goto exit_phy; + } + return 0; + +exit_phy: + for (; i > 0; i--) + phy_exit(ssusb->phys[i - 1]); + + return ret; +} + +static int ssusb_phy_exit(struct ssusb_mtk *ssusb) +{ + int i; + + for (i = 0; i < ssusb->num_phys; i++) + phy_exit(ssusb->phys[i]); + + return 0; +} + +static int ssusb_phy_power_on(struct ssusb_mtk *ssusb) +{ + int i; + int ret; + + for (i = 0; i < ssusb->num_phys; i++) { + ret = phy_power_on(ssusb->phys[i]); + if (ret) + goto power_off_phy; + } + return 0; + +power_off_phy: + for (; i > 0; i--) + phy_power_off(ssusb->phys[i - 1]); + + return ret; +} + +static void ssusb_phy_power_off(struct ssusb_mtk *ssusb) +{ + unsigned int i; + + for (i = 0; i < ssusb->num_phys; i++) + phy_power_off(ssusb->phys[i]); +} + +static int ssusb_rscs_init(struct ssusb_mtk *ssusb) { int ret = 0; - ret = regulator_enable(mtu->vusb33); + ret = regulator_enable(ssusb->vusb33); if (ret) { - dev_err(mtu->dev, "failed to enable vusb33\n"); + dev_err(ssusb->dev, "failed to enable vusb33\n"); goto vusb33_err; } - ret = clk_prepare_enable(mtu->sys_clk); + ret = clk_prepare_enable(ssusb->sys_clk); if (ret) { - dev_err(mtu->dev, "failed to enable sys_clk\n"); + dev_err(ssusb->dev, "failed to enable sys_clk\n"); goto clk_err; } - ret = phy_init(mtu->phy); + ret = ssusb_phy_init(ssusb); if (ret) { - dev_err(mtu->dev, "failed to init phy\n"); + dev_err(ssusb->dev, "failed to init phy\n"); goto phy_init_err; } - ret = phy_power_on(mtu->phy); + ret = ssusb_phy_power_on(ssusb); if (ret) { - dev_err(mtu->dev, "failed to power on phy\n"); + dev_err(ssusb->dev, "failed to power on phy\n"); goto phy_err; } return 0; phy_err: - phy_exit(mtu->phy); + ssusb_phy_exit(ssusb); phy_init_err: - clk_disable_unprepare(mtu->sys_clk); + clk_disable_unprepare(ssusb->sys_clk); clk_err: - regulator_disable(mtu->vusb33); + regulator_disable(ssusb->vusb33); vusb33_err: return ret; } -static void ssusb_rscs_exit(struct mtu3 *mtu) +static void ssusb_rscs_exit(struct ssusb_mtk *ssusb) { - clk_disable_unprepare(mtu->sys_clk); - regulator_disable(mtu->vusb33); - phy_power_off(mtu->phy); - phy_exit(mtu->phy); + clk_disable_unprepare(ssusb->sys_clk); + regulator_disable(ssusb->vusb33); + ssusb_phy_power_off(ssusb); + ssusb_phy_exit(ssusb); } -static void ssusb_ip_sw_reset(struct mtu3 *mtu) +static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb) { - mtu3_setbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); + /* reset whole ip (xhci & u3d) */ + mtu3_setbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); udelay(1); - mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); + mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); } -static int get_ssusb_rscs(struct platform_device *pdev, struct mtu3 *mtu) +static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) { struct device_node *node = pdev->dev.of_node; struct device *dev = &pdev->dev; struct resource *res; + int i; + int ret; - mtu->phy = devm_of_phy_get_by_index(dev, node, 0); - if (IS_ERR(mtu->phy)) { - dev_err(dev, "failed to get phy\n"); - return PTR_ERR(mtu->phy); - } - - mtu->irq = platform_get_irq(pdev, 0); - if (mtu->irq <= 0) { - dev_err(dev, "fail to get irq number\n"); - return -ENODEV; + ssusb->num_phys = of_count_phandle_with_args(node, + "phys", "#phy-cells"); + if (ssusb->num_phys > 0) { + ssusb->phys = devm_kcalloc(dev, ssusb->num_phys, + sizeof(*ssusb->phys), GFP_KERNEL); + if (!ssusb->phys) + return -ENOMEM; + } else { + ssusb->num_phys = 0; } - dev_info(dev, "irq %d\n", mtu->irq); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); - mtu->mac_base = devm_ioremap_resource(dev, res); - if (IS_ERR(mtu->mac_base)) { - dev_err(dev, "error mapping memory for dev mac\n"); - return PTR_ERR(mtu->mac_base); + for (i = 0; i < ssusb->num_phys; i++) { + ssusb->phys[i] = devm_of_phy_get_by_index(dev, node, i); + if (IS_ERR(ssusb->phys[i])) { + dev_err(dev, "failed to get phy-%d\n", i); + return PTR_ERR(ssusb->phys[i]); + } } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc"); - mtu->ippc_base = devm_ioremap_resource(dev, res); - if (IS_ERR(mtu->ippc_base)) { + ssusb->ippc_base = devm_ioremap_resource(dev, res); + if (IS_ERR(ssusb->ippc_base)) { dev_err(dev, "failed to map memory for ippc\n"); - return PTR_ERR(mtu->ippc_base); + return PTR_ERR(ssusb->ippc_base); } - mtu->vusb33 = devm_regulator_get(&pdev->dev, "vusb33"); - if (IS_ERR(mtu->vusb33)) { + ssusb->vusb33 = devm_regulator_get(&pdev->dev, "vusb33"); + if (IS_ERR(ssusb->vusb33)) { dev_err(dev, "failed to get vusb33\n"); - return PTR_ERR(mtu->vusb33); + return PTR_ERR(ssusb->vusb33); } - mtu->sys_clk = devm_clk_get(dev, "sys_ck"); - if (IS_ERR(mtu->sys_clk)) { + ssusb->sys_clk = devm_clk_get(dev, "sys_ck"); + if (IS_ERR(ssusb->sys_clk)) { dev_err(dev, "failed to get sys clock\n"); - return PTR_ERR(mtu->sys_clk); + return PTR_ERR(ssusb->sys_clk); + } + + ssusb->dr_mode = usb_get_dr_mode(dev); + if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN) { + dev_err(dev, "dr_mode is error\n"); + return -EINVAL; } + if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL) + return 0; + + /* if host role is supported */ + ret = ssusb_wakeup_of_property_parse(ssusb, node); + if (ret) + return ret; + return 0; } static int mtu3_probe(struct platform_device *pdev) { + struct device_node *node = pdev->dev.of_node; struct device *dev = &pdev->dev; - struct mtu3 *mtu; + struct ssusb_mtk *ssusb; int ret = -ENOMEM; /* all elements are set to ZERO as default value */ - mtu = devm_kzalloc(dev, sizeof(struct mtu3), GFP_KERNEL); - if (!mtu) + ssusb = devm_kzalloc(dev, sizeof(*ssusb), GFP_KERNEL); + if (!ssusb) return -ENOMEM; ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); @@ -176,11 +251,10 @@ static int mtu3_probe(struct platform_device *pdev) return -ENOTSUPP; } - platform_set_drvdata(pdev, mtu); - mtu->dev = dev; - spin_lock_init(&mtu->lock); + platform_set_drvdata(pdev, ssusb); + ssusb->dev = dev; - ret = get_ssusb_rscs(pdev, mtu); + ret = get_ssusb_rscs(pdev, ssusb); if (ret) return ret; @@ -189,22 +263,45 @@ static int mtu3_probe(struct platform_device *pdev) pm_runtime_get_sync(dev); device_enable_async_suspend(dev); - ret = ssusb_rscs_init(mtu); + ret = ssusb_rscs_init(ssusb); if (ret) goto comm_init_err; - ssusb_ip_sw_reset(mtu); - - ret = ssusb_gadget_init(mtu); - if (ret) { - dev_err(dev, "failed to initialize gadget\n"); + ssusb_ip_sw_reset(ssusb); + + if (IS_ENABLED(CONFIG_USB_MTU3_HOST)) + ssusb->dr_mode = USB_DR_MODE_HOST; + else if (IS_ENABLED(CONFIG_USB_MTU3_GADGET)) + ssusb->dr_mode = USB_DR_MODE_PERIPHERAL; + + /* default as host */ + ssusb->is_host = !(ssusb->dr_mode == USB_DR_MODE_PERIPHERAL); + + switch (ssusb->dr_mode) { + case USB_DR_MODE_PERIPHERAL: + ret = ssusb_gadget_init(ssusb); + if (ret) { + dev_err(dev, "failed to initialize gadget\n"); + goto comm_exit; + } + break; + case USB_DR_MODE_HOST: + ret = ssusb_host_init(ssusb, node); + if (ret) { + dev_err(dev, "failed to initialize host\n"); + goto comm_exit; + } + break; + default: + dev_err(dev, "unsupported mode: %d\n", ssusb->dr_mode); + ret = -EINVAL; goto comm_exit; } return 0; comm_exit: - ssusb_rscs_exit(mtu); + ssusb_rscs_exit(ssusb); comm_init_err: pm_runtime_put_sync(dev); @@ -215,16 +312,73 @@ comm_init_err: static int mtu3_remove(struct platform_device *pdev) { - struct mtu3 *mtu = platform_get_drvdata(pdev); + struct ssusb_mtk *ssusb = platform_get_drvdata(pdev); + + switch (ssusb->dr_mode) { + case USB_DR_MODE_PERIPHERAL: + ssusb_gadget_exit(ssusb); + break; + case USB_DR_MODE_HOST: + ssusb_host_exit(ssusb); + break; + default: + return -EINVAL; + } - ssusb_gadget_exit(mtu); - ssusb_rscs_exit(mtu); + ssusb_rscs_exit(ssusb); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); return 0; } +/* + * when support dual-role mode, we reject suspend when + * it works as device mode; + */ +static int __maybe_unused mtu3_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ssusb_mtk *ssusb = platform_get_drvdata(pdev); + + dev_dbg(dev, "%s\n", __func__); + + /* REVISIT: disconnect it for only device mode? */ + if (!ssusb->is_host) + return 0; + + ssusb_host_disable(ssusb, true); + ssusb_phy_power_off(ssusb); + clk_disable_unprepare(ssusb->sys_clk); + ssusb_wakeup_enable(ssusb); + + return 0; +} + +static int __maybe_unused mtu3_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ssusb_mtk *ssusb = platform_get_drvdata(pdev); + + dev_dbg(dev, "%s\n", __func__); + + if (!ssusb->is_host) + return 0; + + ssusb_wakeup_disable(ssusb); + clk_prepare_enable(ssusb->sys_clk); + ssusb_phy_power_on(ssusb); + ssusb_host_enable(ssusb); + + return 0; +} + +static const struct dev_pm_ops mtu3_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mtu3_suspend, mtu3_resume) +}; + +#define DEV_PM_OPS (IS_ENABLED(CONFIG_PM) ? &mtu3_pm_ops : NULL) + #ifdef CONFIG_OF static const struct of_device_id mtu3_of_match[] = { @@ -241,6 +395,7 @@ static struct platform_driver mtu3_driver = { .remove = mtu3_remove, .driver = { .name = MTU3_DRIVER_NAME, + .pm = DEV_PM_OPS, .of_match_table = of_match_ptr(mtu3_of_match), }, }; -- cgit v1.2.3 From d0ed062a8b75b9c9ba5a942894636f2d9bb72040 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Wed, 19 Oct 2016 10:28:26 +0800 Subject: usb: mtu3: dual-role mode support support dual-role mode; there are two ways to switch between host and device modes, one is by idpin, another is by debugfs which depends on user input. Signed-off-by: Chunfeng Yun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mtu3/Kconfig | 15 +- drivers/usb/mtu3/Makefile | 11 +- drivers/usb/mtu3/mtu3.h | 34 +++- drivers/usb/mtu3/mtu3_core.c | 14 +- drivers/usb/mtu3/mtu3_dr.c | 379 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/mtu3/mtu3_dr.h | 27 ++- drivers/usb/mtu3/mtu3_gadget.c | 6 +- drivers/usb/mtu3/mtu3_host.c | 6 + drivers/usb/mtu3/mtu3_plat.c | 86 +++++++++- 9 files changed, 557 insertions(+), 21 deletions(-) create mode 100644 drivers/usb/mtu3/mtu3_dr.c (limited to 'drivers') diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index 59e3f6fa0da0..25cd61947bee 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig @@ -2,7 +2,7 @@ config USB_MTU3 tristate "MediaTek USB3 Dual Role controller" - depends on (USB || USB_GADGET) && HAS_DMA + depends on EXTCON && (USB || USB_GADGET) && HAS_DMA depends on ARCH_MEDIATEK || COMPILE_TEST select USB_XHCI_MTK if USB_SUPPORT && USB_XHCI_HCD help @@ -19,6 +19,7 @@ config USB_MTU3 if USB_MTU3 choice bool "MTU3 Mode Selection" + default USB_MTU3_DUAL_ROLE if (USB && USB_GADGET) default USB_MTU3_HOST if (USB && !USB_GADGET) default USB_MTU3_GADGET if (!USB && USB_GADGET) @@ -36,6 +37,18 @@ config USB_MTU3_GADGET Select this when you want to use MTU3 in gadget mode only, thereby the host feature will be regressed. +config USB_MTU3_DUAL_ROLE + bool "Dual Role mode" + depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) + help + This is the default mode of working of MTU3 controller where + both host and gadget features are enabled. + endchoice +config USB_MTU3_DEBUG + bool "Enable Debugging Messages" + help + Say Y here to enable debugging messages in the MTU3 Driver. + endif diff --git a/drivers/usb/mtu3/Makefile b/drivers/usb/mtu3/Makefile index 41e45e99ee6b..60e0fff7a847 100644 --- a/drivers/usb/mtu3/Makefile +++ b/drivers/usb/mtu3/Makefile @@ -1,11 +1,18 @@ + +ccflags-$(CONFIG_USB_MTU3_DEBUG) += -DDEBUG + obj-$(CONFIG_USB_MTU3) += mtu3.o mtu3-y := mtu3_plat.o -ifneq ($(filter y,$(CONFIG_USB_MTU3_HOST)),) +ifneq ($(filter y,$(CONFIG_USB_MTU3_HOST) $(CONFIG_USB_MTU3_DUAL_ROLE)),) mtu3-y += mtu3_host.o endif -ifneq ($(filter y,$(CONFIG_USB_MTU3_GADGET)),) +ifneq ($(filter y,$(CONFIG_USB_MTU3_GADGET) $(CONFIG_USB_MTU3_DUAL_ROLE)),) mtu3-y += mtu3_core.o mtu3_gadget_ep0.o mtu3_gadget.o mtu3_qmu.o endif + +ifneq ($(CONFIG_USB_MTU3_DUAL_ROLE),) + mtu3-y += mtu3_dr.o +endif diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index a7c0ce873c44..ba9df719f363 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -172,15 +173,44 @@ struct mtu3_gpd_ring { struct qmu_gpd *enqueue; struct qmu_gpd *dequeue; }; + +/** +* @vbus: vbus 5V used by host mode +* @edev: external connector used to detect vbus and iddig changes +* @vbus_nb: notifier for vbus detection +* @vbus_nb: notifier for iddig(idpin) detection +* @extcon_reg_dwork: delay work for extcon notifier register, waiting for +* xHCI driver initialization, it's necessary for system bootup +* as device. +* @is_u3_drd: whether port0 supports usb3.0 dual-role device or not +* @id_*: used to maually switch between host and device modes by idpin +* @manual_drd_enabled: it's true when supports dual-role device by debugfs +* to switch host/device modes depending on user input. +*/ +struct otg_switch_mtk { + struct regulator *vbus; + struct extcon_dev *edev; + struct notifier_block vbus_nb; + struct notifier_block id_nb; + struct delayed_work extcon_reg_dwork; + bool is_u3_drd; + /* dual-role switch by debugfs */ + struct pinctrl *id_pinctrl; + struct pinctrl_state *id_float; + struct pinctrl_state *id_ground; + bool manual_drd_enabled; +}; + /** * @mac_base: register base address of device MAC, exclude xHCI's - * @ippc_base: register base address of ip port controller interface (IPPC) + * @ippc_base: register base address of IP Power and Clock interface (IPPC) * @vusb33: usb3.3V shared by device/host IP * @sys_clk: system clock of mtu3, shared by device/host IP * @dr_mode: works in which mode: * host only, device only or dual-role mode * @u2_ports: number of usb2.0 host ports * @u3_ports: number of usb3.0 host ports + * @dbgfs_root: only used when supports manual dual-role switch via debugfs * @wakeup_en: it's true when supports remote wakeup in host mode * @wk_deb_p0: port0's wakeup debounce clock * @wk_deb_p1: it's optional, and depends on port1 is supported or not @@ -196,10 +226,12 @@ struct ssusb_mtk { struct regulator *vusb33; struct clk *sys_clk; /* otg */ + struct otg_switch_mtk otg_switch; enum usb_dr_mode dr_mode; bool is_host; int u2_ports; int u3_ports; + struct dentry *dbgfs_root; /* usb wakeup for host mode */ bool wakeup_en; struct clk *wk_deb_p0; diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index 2eef9727312c..520e55a760c9 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -150,7 +150,6 @@ static void mtu3_intr_disable(struct mtu3 *mtu) /* Disable level 1 interrupts */ mtu3_writel(mbase, U3D_LV1IECR, ~0x0); - /* Disable endpoint interrupts */ mtu3_writel(mbase, U3D_EPIECR, ~0x0); } @@ -161,13 +160,10 @@ static void mtu3_intr_status_clear(struct mtu3 *mtu) /* Clear EP0 and Tx/Rx EPn interrupts status */ mtu3_writel(mbase, U3D_EPISR, ~0x0); - /* Clear U2 USB common interrupts status */ mtu3_writel(mbase, U3D_COMMON_USB_INTR, ~0x0); - /* Clear U3 LTSSM interrupts status */ mtu3_writel(mbase, U3D_LTSSM_INTR, ~0x0); - /* Clear speed change interrupt status */ mtu3_writel(mbase, U3D_DEV_LINK_INTR, ~0x0); } @@ -268,7 +264,6 @@ void mtu3_start(struct mtu3 *mtu) /* Initialize the default interrupts */ mtu3_intr_enable(mtu); - mtu->is_active = 1; if (mtu->softconnect) @@ -516,7 +511,6 @@ static int mtu3_mem_alloc(struct mtu3 *mtu) mtu->out_eps = &ep_array[mtu->num_eps]; /* ep0 uses in_eps[0], out_eps[0] is reserved */ mtu->ep0 = mtu->in_eps; - mtu->ep0->mtu = mtu; mtu->ep0->epnum = 0; @@ -560,6 +554,7 @@ static void mtu3_set_speed(struct mtu3 *mtu) /* HS/FS detected by HW */ mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); } + dev_info(mtu->dev, "max_speed: %s\n", usb_speed_string(mtu->max_speed)); } @@ -586,13 +581,10 @@ static void mtu3_regs_init(struct mtu3 *mtu) /* delay about 0.1us from detecting reset to send chirp-K */ mtu3_clrbits(mbase, U3D_LINK_RESET_INFO, WTCHRP_MSK); - /* U2/U3 detected by HW */ mtu3_writel(mbase, U3D_DEVICE_CONF, 0); - /* enable QMU 16B checksum */ mtu3_setbits(mbase, U3D_QCR0, QMU_CS16B_EN); - /* vbus detected by HW */ mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); } @@ -838,6 +830,10 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) goto gadget_err; } + /* init as host mode, power down device IP for power saving */ + if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) + mtu3_stop(mtu); + dev_dbg(dev, " %s() done...\n", __func__); return 0; diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c new file mode 100644 index 000000000000..1a8987e7c5b0 --- /dev/null +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -0,0 +1,379 @@ +/* + * mtu3_dr.c - dual role switch and host glue layer + * + * Copyright (C) 2016 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mtu3.h" +#include "mtu3_dr.h" + +#define USB2_PORT 2 +#define USB3_PORT 3 + +enum mtu3_vbus_id_state { + MTU3_ID_FLOAT = 1, + MTU3_ID_GROUND, + MTU3_VBUS_OFF, + MTU3_VBUS_VALID, +}; + +static void toggle_opstate(struct ssusb_mtk *ssusb) +{ + if (!ssusb->otg_switch.is_u3_drd) { + mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION); + mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN); + } +} + +/* only port0 supports dual-role mode */ +static int ssusb_port0_switch(struct ssusb_mtk *ssusb, + int version, bool tohost) +{ + void __iomem *ibase = ssusb->ippc_base; + u32 value; + + dev_dbg(ssusb->dev, "%s (switch u%d port0 to %s)\n", __func__, + version, tohost ? "host" : "device"); + + if (version == USB2_PORT) { + /* 1. power off and disable u2 port0 */ + value = mtu3_readl(ibase, SSUSB_U2_CTRL(0)); + value |= SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS; + mtu3_writel(ibase, SSUSB_U2_CTRL(0), value); + + /* 2. power on, enable u2 port0 and select its mode */ + value = mtu3_readl(ibase, SSUSB_U2_CTRL(0)); + value &= ~(SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS); + value = tohost ? (value | SSUSB_U2_PORT_HOST_SEL) : + (value & (~SSUSB_U2_PORT_HOST_SEL)); + mtu3_writel(ibase, SSUSB_U2_CTRL(0), value); + } else { + /* 1. power off and disable u3 port0 */ + value = mtu3_readl(ibase, SSUSB_U3_CTRL(0)); + value |= SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS; + mtu3_writel(ibase, SSUSB_U3_CTRL(0), value); + + /* 2. power on, enable u3 port0 and select its mode */ + value = mtu3_readl(ibase, SSUSB_U3_CTRL(0)); + value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS); + value = tohost ? (value | SSUSB_U3_PORT_HOST_SEL) : + (value & (~SSUSB_U3_PORT_HOST_SEL)); + mtu3_writel(ibase, SSUSB_U3_CTRL(0), value); + } + + return 0; +} + +static void switch_port_to_host(struct ssusb_mtk *ssusb) +{ + u32 check_clk = 0; + + dev_dbg(ssusb->dev, "%s\n", __func__); + + ssusb_port0_switch(ssusb, USB2_PORT, true); + + if (ssusb->otg_switch.is_u3_drd) { + ssusb_port0_switch(ssusb, USB3_PORT, true); + check_clk = SSUSB_U3_MAC_RST_B_STS; + } + + ssusb_check_clocks(ssusb, check_clk); + + /* after all clocks are stable */ + toggle_opstate(ssusb); +} + +static void switch_port_to_device(struct ssusb_mtk *ssusb) +{ + u32 check_clk = 0; + + dev_dbg(ssusb->dev, "%s\n", __func__); + + ssusb_port0_switch(ssusb, USB2_PORT, false); + + if (ssusb->otg_switch.is_u3_drd) { + ssusb_port0_switch(ssusb, USB3_PORT, false); + check_clk = SSUSB_U3_MAC_RST_B_STS; + } + + ssusb_check_clocks(ssusb, check_clk); +} + +int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) +{ + struct ssusb_mtk *ssusb = + container_of(otg_sx, struct ssusb_mtk, otg_switch); + struct regulator *vbus = otg_sx->vbus; + int ret; + + /* vbus is optional */ + if (!vbus) + return 0; + + dev_dbg(ssusb->dev, "%s: turn %s\n", __func__, is_on ? "on" : "off"); + + if (is_on) { + ret = regulator_enable(vbus); + if (ret) { + dev_err(ssusb->dev, "vbus regulator enable failed\n"); + return ret; + } + } else { + regulator_disable(vbus); + } + + return 0; +} + +/* + * switch to host: -> MTU3_VBUS_OFF --> MTU3_ID_GROUND + * switch to device: -> MTU3_ID_FLOAT --> MTU3_VBUS_VALID + */ +static void ssusb_set_mailbox(struct otg_switch_mtk *otg_sx, + enum mtu3_vbus_id_state status) +{ + struct ssusb_mtk *ssusb = + container_of(otg_sx, struct ssusb_mtk, otg_switch); + struct mtu3 *mtu = ssusb->u3d; + + dev_dbg(ssusb->dev, "mailbox state(%d)\n", status); + + switch (status) { + case MTU3_ID_GROUND: + switch_port_to_host(ssusb); + ssusb_set_vbus(otg_sx, 1); + ssusb->is_host = true; + break; + case MTU3_ID_FLOAT: + ssusb->is_host = false; + ssusb_set_vbus(otg_sx, 0); + switch_port_to_device(ssusb); + break; + case MTU3_VBUS_OFF: + mtu3_stop(mtu); + pm_relax(ssusb->dev); + break; + case MTU3_VBUS_VALID: + /* avoid suspend when works as device */ + pm_stay_awake(ssusb->dev); + mtu3_start(mtu); + break; + default: + dev_err(ssusb->dev, "invalid state\n"); + } +} + +static int ssusb_id_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct otg_switch_mtk *otg_sx = + container_of(nb, struct otg_switch_mtk, id_nb); + + if (event) + ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND); + else + ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); + + return NOTIFY_DONE; +} + +static int ssusb_vbus_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct otg_switch_mtk *otg_sx = + container_of(nb, struct otg_switch_mtk, vbus_nb); + + if (event) + ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); + else + ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF); + + return NOTIFY_DONE; +} + +static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) +{ + struct ssusb_mtk *ssusb = + container_of(otg_sx, struct ssusb_mtk, otg_switch); + struct extcon_dev *edev = otg_sx->edev; + int ret; + + /* extcon is optional */ + if (!edev) + return 0; + + otg_sx->vbus_nb.notifier_call = ssusb_vbus_notifier; + ret = extcon_register_notifier(edev, EXTCON_USB, + &otg_sx->vbus_nb); + if (ret < 0) + dev_err(ssusb->dev, "failed to register notifier for USB\n"); + + otg_sx->id_nb.notifier_call = ssusb_id_notifier; + ret = extcon_register_notifier(edev, EXTCON_USB_HOST, + &otg_sx->id_nb); + if (ret < 0) + dev_err(ssusb->dev, "failed to register notifier for USB-HOST\n"); + + dev_dbg(ssusb->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n", + extcon_get_cable_state_(edev, EXTCON_USB), + extcon_get_cable_state_(edev, EXTCON_USB_HOST)); + + /* default as host, switch to device mode if needed */ + if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == false) + ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); + if (extcon_get_cable_state_(edev, EXTCON_USB) == true) + ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); + + return 0; +} + +static void extcon_register_dwork(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct otg_switch_mtk *otg_sx = + container_of(dwork, struct otg_switch_mtk, extcon_reg_dwork); + + ssusb_extcon_register(otg_sx); +} + +/* + * We provide an interface via debugfs to switch between host and device modes + * depending on user input. + * This is useful in special cases, such as uses TYPE-A receptacle but also + * wants to support dual-role mode. + * It generates cable state changes by pulling up/down IDPIN and + * notifies driver to switch mode by "extcon-usb-gpio". + * NOTE: when use MICRO receptacle, should not enable this interface. + */ +static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) +{ + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + + if (to_host) + pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_ground); + else + pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_float); +} + + +static int ssusb_mode_show(struct seq_file *sf, void *unused) +{ + struct ssusb_mtk *ssusb = sf->private; + + seq_printf(sf, "current mode: %s(%s drd)\n(echo device/host)\n", + ssusb->is_host ? "host" : "device", + ssusb->otg_switch.manual_drd_enabled ? "manual" : "auto"); + + return 0; +} + +static int ssusb_mode_open(struct inode *inode, struct file *file) +{ + return single_open(file, ssusb_mode_show, inode->i_private); +} + +static ssize_t ssusb_mode_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + struct seq_file *sf = file->private_data; + struct ssusb_mtk *ssusb = sf->private; + char buf[16]; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "host", 4) && !ssusb->is_host) { + ssusb_mode_manual_switch(ssusb, 1); + } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { + ssusb_mode_manual_switch(ssusb, 0); + } else { + dev_err(ssusb->dev, "wrong or duplicated setting\n"); + return -EINVAL; + } + + return count; +} + +static const struct file_operations ssusb_mode_fops = { + .open = ssusb_mode_open, + .write = ssusb_mode_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void ssusb_debugfs_init(struct ssusb_mtk *ssusb) +{ + struct dentry *root; + struct dentry *file; + + root = debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root); + if (IS_ERR_OR_NULL(root)) { + if (!root) + dev_err(ssusb->dev, "create debugfs root failed\n"); + return; + } + ssusb->dbgfs_root = root; + + file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, + ssusb, &ssusb_mode_fops); + if (!file) + dev_dbg(ssusb->dev, "create debugfs mode failed\n"); +} + +static void ssusb_debugfs_exit(struct ssusb_mtk *ssusb) +{ + debugfs_remove_recursive(ssusb->dbgfs_root); +} + +int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) +{ + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + + INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork, extcon_register_dwork); + + if (otg_sx->manual_drd_enabled) + ssusb_debugfs_init(ssusb); + + /* It is enough to delay 1s for waiting for host initialization */ + schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ); + + return 0; +} + +void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) +{ + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + + cancel_delayed_work(&otg_sx->extcon_reg_dwork); + + if (otg_sx->edev) { + extcon_unregister_notifier(otg_sx->edev, + EXTCON_USB, &otg_sx->vbus_nb); + extcon_unregister_notifier(otg_sx->edev, + EXTCON_USB_HOST, &otg_sx->id_nb); + } + + if (otg_sx->manual_drd_enabled) + ssusb_debugfs_exit(ssusb); +} diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h index 07066f4093ab..9b228b5811b0 100644 --- a/drivers/usb/mtu3/mtu3_dr.h +++ b/drivers/usb/mtu3/mtu3_dr.h @@ -19,7 +19,7 @@ #ifndef _MTU3_DR_H_ #define _MTU3_DR_H_ -#if IS_ENABLED(CONFIG_USB_MTU3_HOST) +#if IS_ENABLED(CONFIG_USB_MTU3_HOST) || IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE) int ssusb_host_init(struct ssusb_mtk *ssusb, struct device_node *parent_dn); void ssusb_host_exit(struct ssusb_mtk *ssusb); @@ -69,7 +69,7 @@ static inline void ssusb_wakeup_disable(struct ssusb_mtk *ssusb) #endif -#if IS_ENABLED(CONFIG_USB_MTU3_GADGET) +#if IS_ENABLED(CONFIG_USB_MTU3_GADGET) || IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE) int ssusb_gadget_init(struct ssusb_mtk *ssusb); void ssusb_gadget_exit(struct ssusb_mtk *ssusb); #else @@ -82,4 +82,27 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb) {} #endif + +#if IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE) +int ssusb_otg_switch_init(struct ssusb_mtk *ssusb); +void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb); +int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on); + +#else + +static inline int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) +{ + return 0; +} + +static inline void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) +{} + +static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) +{ + return 0; +} + +#endif + #endif /* _MTU3_DR_H_ */ diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index 84f3fe169928..9dd2441b4fa1 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -522,7 +522,8 @@ static int mtu3_gadget_start(struct usb_gadget *gadget, mtu->softconnect = 0; mtu->gadget_driver = driver; - mtu3_start(mtu); + if (mtu->ssusb->dr_mode == USB_DR_MODE_PERIPHERAL) + mtu3_start(mtu); spin_unlock_irqrestore(&mtu->lock, flags); @@ -575,7 +576,8 @@ static int mtu3_gadget_stop(struct usb_gadget *g) stop_activity(mtu); mtu->gadget_driver = NULL; - mtu3_stop(mtu); + if (mtu->ssusb->dr_mode == USB_DR_MODE_PERIPHERAL) + mtu3_stop(mtu); spin_unlock_irqrestore(&mtu->lock, flags); diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c index 361d6d844ce5..cd4d01087855 100644 --- a/drivers/usb/mtu3/mtu3_host.c +++ b/drivers/usb/mtu3/mtu3_host.c @@ -230,10 +230,16 @@ static void ssusb_host_setup(struct ssusb_mtk *ssusb) * if support OTG, gadget driver will switch port0 to device mode */ ssusb_host_enable(ssusb); + + /* if port0 supports dual-role, works as host mode by default */ + ssusb_set_vbus(&ssusb->otg_switch, 1); } static void ssusb_host_cleanup(struct ssusb_mtk *ssusb) { + if (ssusb->is_host) + ssusb_set_vbus(&ssusb->otg_switch, 0); + ssusb_host_disable(ssusb, false); } diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index facb76c2877b..783367805c99 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -142,13 +142,10 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb) phy_err: ssusb_phy_exit(ssusb); - phy_init_err: clk_disable_unprepare(ssusb->sys_clk); - clk_err: regulator_disable(ssusb->vusb33); - vusb33_err: return ret; @@ -170,10 +167,39 @@ static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb) mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); } +static int get_iddig_pinctrl(struct ssusb_mtk *ssusb) +{ + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + + otg_sx->id_pinctrl = devm_pinctrl_get(ssusb->dev); + if (IS_ERR(otg_sx->id_pinctrl)) { + dev_err(ssusb->dev, "Cannot find id pinctrl!\n"); + return PTR_ERR(otg_sx->id_pinctrl); + } + + otg_sx->id_float = + pinctrl_lookup_state(otg_sx->id_pinctrl, "id_float"); + if (IS_ERR(otg_sx->id_float)) { + dev_err(ssusb->dev, "Cannot find pinctrl id_float!\n"); + return PTR_ERR(otg_sx->id_float); + } + + otg_sx->id_ground = + pinctrl_lookup_state(otg_sx->id_pinctrl, "id_ground"); + if (IS_ERR(otg_sx->id_ground)) { + dev_err(ssusb->dev, "Cannot find pinctrl id_ground!\n"); + return PTR_ERR(otg_sx->id_ground); + } + + return 0; +} + static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) { struct device_node *node = pdev->dev.of_node; + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; struct device *dev = &pdev->dev; + struct regulator *vbus; struct resource *res; int i; int ret; @@ -230,6 +256,37 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) if (ret) return ret; + if (ssusb->dr_mode != USB_DR_MODE_OTG) + return 0; + + /* if dual-role mode is supported */ + vbus = devm_regulator_get(&pdev->dev, "vbus"); + if (IS_ERR(vbus)) { + dev_err(dev, "failed to get vbus\n"); + return PTR_ERR(vbus); + } + otg_sx->vbus = vbus; + + otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd"); + otg_sx->manual_drd_enabled = + of_property_read_bool(node, "enable-manual-drd"); + + if (of_property_read_bool(node, "extcon")) { + otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0); + if (IS_ERR(otg_sx->edev)) { + dev_err(ssusb->dev, "couldn't get extcon device\n"); + return -EPROBE_DEFER; + } + if (otg_sx->manual_drd_enabled) { + ret = get_iddig_pinctrl(ssusb); + if (ret) + return ret; + } + } + + dev_info(dev, "dr_mode: %d, is_u3_dr: %d\n", + ssusb->dr_mode, otg_sx->is_u3_drd); + return 0; } @@ -292,6 +349,21 @@ static int mtu3_probe(struct platform_device *pdev) goto comm_exit; } break; + case USB_DR_MODE_OTG: + ret = ssusb_gadget_init(ssusb); + if (ret) { + dev_err(dev, "failed to initialize gadget\n"); + goto comm_exit; + } + + ret = ssusb_host_init(ssusb, node); + if (ret) { + dev_err(dev, "failed to initialize host\n"); + goto gadget_exit; + } + + ssusb_otg_switch_init(ssusb); + break; default: dev_err(dev, "unsupported mode: %d\n", ssusb->dr_mode); ret = -EINVAL; @@ -300,9 +372,10 @@ static int mtu3_probe(struct platform_device *pdev) return 0; +gadget_exit: + ssusb_gadget_exit(ssusb); comm_exit: ssusb_rscs_exit(ssusb); - comm_init_err: pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -321,6 +394,11 @@ static int mtu3_remove(struct platform_device *pdev) case USB_DR_MODE_HOST: ssusb_host_exit(ssusb); break; + case USB_DR_MODE_OTG: + ssusb_otg_switch_exit(ssusb); + ssusb_gadget_exit(ssusb); + ssusb_host_exit(ssusb); + break; default: return -EINVAL; } -- cgit v1.2.3 From 8ed8147abc7cf1f689245deb316aabfe2f657ade Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 26 Oct 2016 17:07:03 +0800 Subject: drm/amdgpu: use failed label to handle context init failure Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index a5e2fcbef0f0..6d86eaef934c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -55,18 +55,18 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx) r = amd_sched_entity_init(&ring->sched, &ctx->rings[i].entity, rq, amdgpu_sched_jobs); if (r) - break; + goto failed; } - if (i < adev->num_rings) { - for (j = 0; j < i; j++) - amd_sched_entity_fini(&adev->rings[j]->sched, - &ctx->rings[j].entity); - kfree(ctx->fences); - ctx->fences = NULL; - return r; - } return 0; + +failed: + for (j = 0; j < i; j++) + amd_sched_entity_fini(&adev->rings[j]->sched, + &ctx->rings[j].entity); + kfree(ctx->fences); + ctx->fences = NULL; + return r; } static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx) -- cgit v1.2.3 From 86f8c599b09c916f9aad30563271440dbd79213a Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 3 Oct 2016 20:46:36 +0800 Subject: drm/amdgpu: when suspend, set boot state instand of disable dpm. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix pm-hibernate bug, when suspend/resume, dpm start failed. Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 2 ++ drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index e5e0a9a1abaf..bd85e35998e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -404,6 +404,8 @@ struct amdgpu_dpm { enum amd_vce_level vce_level; enum amd_pm_state_type state; enum amd_pm_state_type user_state; + enum amd_pm_state_type last_state; + enum amd_pm_state_type last_user_state; u32 platform_caps; u32 voltage_response_time; u32 backbias_response_time; diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 6ecfc4885b84..1c3b5c411ef7 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6345,12 +6345,19 @@ static int ci_dpm_suspend(void *handle) if (adev->pm.dpm_enabled) { mutex_lock(&adev->pm.mutex); - /* disable dpm */ - ci_dpm_disable(adev); - /* reset the power state */ - adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, + AMDGPU_THERMAL_IRQ_LOW_TO_HIGH); + amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, + AMDGPU_THERMAL_IRQ_HIGH_TO_LOW); + adev->pm.dpm.last_user_state = adev->pm.dpm.user_state; + adev->pm.dpm.last_state = adev->pm.dpm.state; + adev->pm.dpm.user_state = POWER_STATE_TYPE_INTERNAL_BOOT; + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_BOOT; mutex_unlock(&adev->pm.mutex); + amdgpu_pm_compute_clocks(adev); + } + return 0; } @@ -6368,6 +6375,8 @@ static int ci_dpm_resume(void *handle) adev->pm.dpm_enabled = false; else adev->pm.dpm_enabled = true; + adev->pm.dpm.user_state = adev->pm.dpm.last_user_state; + adev->pm.dpm.state = adev->pm.dpm.last_state; mutex_unlock(&adev->pm.mutex); if (adev->pm.dpm_enabled) amdgpu_pm_compute_clocks(adev); -- cgit v1.2.3 From 3f767e3d076dd2a24a614917c8f0b05d8d82b90b Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 26 Oct 2016 13:44:12 +0800 Subject: drm/amdgpu: just not load smc firmware if smu is already running MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 1c3b5c411ef7..f1baf6715b05 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -2207,6 +2207,11 @@ static int ci_upload_firmware(struct amdgpu_device *adev) struct ci_power_info *pi = ci_get_pi(adev); int i, ret; + if (amdgpu_ci_is_smc_running(adev)) { + DRM_INFO("smc is running, no need to load smc firmware\n"); + return 0; + } + for (i = 0; i < adev->usec_timeout; i++) { if (RREG32_SMC(ixRCU_UC_EVENTS) & RCU_UC_EVENTS__boot_seq_done_MASK) break; @@ -5275,8 +5280,6 @@ static int ci_dpm_enable(struct amdgpu_device *adev) struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; int ret; - if (amdgpu_ci_is_smc_running(adev)) - return -EINVAL; if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE) { ci_enable_voltage_control(adev); ret = ci_construct_voltage_tables(adev); -- cgit v1.2.3 From 4be5097ccba6dd6006b24db238c75dfcf66bcad3 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 26 Oct 2016 17:04:33 +0800 Subject: drm/amdgpu: enable uvd bypass mode for CI/VI. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 25 ++++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 18 ++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 9 ++++----- 3 files changed, 44 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 3c2dce67b5f3..8f9c7d55ddda 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -36,6 +36,9 @@ #include "bif/bif_4_1_d.h" +#include "smu/smu_7_0_1_d.h" +#include "smu/smu_7_0_1_sh_mask.h" + static void uvd_v4_2_mc_resume(struct amdgpu_device *adev); static void uvd_v4_2_init_cg(struct amdgpu_device *adev); static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev); @@ -683,18 +686,34 @@ static int uvd_v4_2_process_interrupt(struct amdgpu_device *adev, return 0; } +static void uvd_v5_0_set_bypass_mode(struct amdgpu_device *adev, bool enable) +{ + u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL); + + if (enable) + tmp |= (GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK | + GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK); + else + tmp &= ~(GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK | + GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK); + + WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp); +} + static int uvd_v4_2_set_clockgating_state(void *handle, enum amd_clockgating_state state) { bool gate = false; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) - return 0; - if (state == AMD_CG_STATE_GATE) gate = true; + uvd_v5_0_set_bypass_mode(adev, gate); + + if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) + return 0; + uvd_v4_2_enable_mgcg(adev, gate); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index 05088ec4c41b..95303e2d5f92 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -33,6 +33,8 @@ #include "oss/oss_2_0_sh_mask.h" #include "bif/bif_5_0_d.h" #include "vi.h" +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev); static void uvd_v5_0_set_irq_funcs(struct amdgpu_device *adev); @@ -722,6 +724,20 @@ static void uvd_v5_0_set_hw_clock_gating(struct amdgpu_device *adev) } #endif +static void uvd_v5_0_set_bypass_mode(struct amdgpu_device *adev, bool enable) +{ + u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL); + + if (enable) + tmp |= (GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK | + GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK); + else + tmp &= ~(GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK | + GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK); + + WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp); +} + static int uvd_v5_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { @@ -729,6 +745,8 @@ static int uvd_v5_0_set_clockgating_state(void *handle, bool enable = (state == AMD_CG_STATE_GATE) ? true : false; static int curstate = -1; + uvd_v5_0_set_bypass_mode(adev, enable); + if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 2e2baa614b28..a339b5ccb296 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -935,7 +935,7 @@ static void uvd_v6_0_set_hw_clock_gating(struct amdgpu_device *adev) } #endif -static void uvd_v6_set_bypass_mode(struct amdgpu_device *adev, bool enable) +static void uvd_v6_0_set_bypass_mode(struct amdgpu_device *adev, bool enable) { u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL); @@ -953,15 +953,14 @@ static int uvd_v6_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + bool enable = (state == AMD_CG_STATE_GATE) ? true : false; - if (adev->asic_type == CHIP_FIJI || - adev->asic_type == CHIP_POLARIS10) - uvd_v6_set_bypass_mode(adev, state == AMD_CG_STATE_GATE ? true : false); + uvd_v6_0_set_bypass_mode(adev, enable); if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) return 0; - if (state == AMD_CG_STATE_GATE) { + if (enable) { /* disable HW gating and enable Sw gating */ uvd_v6_0_set_sw_clock_gating(adev); } else { -- cgit v1.2.3 From 415282b15e15c2d7fb18e29c5b554cc7f4ff5c52 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 26 Oct 2016 17:05:30 +0800 Subject: drm/amdgpu: disable dpm before turn off clock when vce idle. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: move return value check as well Signed-off-by: Rex Zhu Reviewed-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index f1baf6715b05..3295fbbdf8c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -4258,13 +4258,12 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev, ret = ci_enable_vce_dpm(adev, true); } else { + ret = ci_enable_vce_dpm(adev, false); + if (ret) + return ret; /* turn the clocks off when not encoding */ ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, AMD_CG_STATE_GATE); - if (ret) - return ret; - - ret = ci_enable_vce_dpm(adev, false); } } return ret; -- cgit v1.2.3 From 3495a103579380288a130dc1862488cd8a4293f5 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 26 Oct 2016 18:05:00 +0800 Subject: drm/amdgpu: turn on/off uvd clock when dpm enable/disable on CI Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 3295fbbdf8c8..e9b1964d4e61 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -887,9 +887,6 @@ static void ci_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) { struct ci_power_info *pi = ci_get_pi(adev); - if (pi->uvd_power_gated == gate) - return; - pi->uvd_power_gated = gate; ci_update_uvd_dpm(adev, gate); @@ -4201,8 +4198,15 @@ static int ci_update_uvd_dpm(struct amdgpu_device *adev, bool gate) { struct ci_power_info *pi = ci_get_pi(adev); u32 tmp; + int ret = 0; if (!gate) { + /* turn the clocks on when decoding */ + ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_UNGATE); + if (ret) + return ret; + if (pi->caps_uvd_dpm || (adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count <= 0)) pi->smc_state_table.UvdBootLevel = 0; @@ -4214,9 +4218,17 @@ static int ci_update_uvd_dpm(struct amdgpu_device *adev, bool gate) tmp &= ~DPM_TABLE_475__UvdBootLevel_MASK; tmp |= (pi->smc_state_table.UvdBootLevel << DPM_TABLE_475__UvdBootLevel__SHIFT); WREG32_SMC(ixDPM_TABLE_475, tmp); + ret = ci_enable_uvd_dpm(adev, true); + } else { + ret = ci_enable_uvd_dpm(adev, false); + if (ret) + return ret; + + ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_GATE); } - return ci_enable_uvd_dpm(adev, !gate); + return ret; } static u8 ci_get_vce_boot_level(struct amdgpu_device *adev) -- cgit v1.2.3 From a07ea4d9941af5a0c6f0be2a71b51ac9c083c5e5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 24 Oct 2016 14:40:02 +0200 Subject: genetlink: no longer support using static family IDs Static family IDs have never really been used, the only use case was the workaround I introduced for those users that assumed their family ID was also their multicast group ID. Additionally, because static family IDs would never be reserved by the generic netlink code, using a relatively low ID would only work for built-in families that can be registered immediately after generic netlink is started, which is basically only the control family (apart from the workaround code, which I also had to add code for so it would reserve those IDs) Thus, anything other than GENL_ID_GENERATE is flawed and luckily not used except in the cases I mentioned. Move those workarounds into a few lines of code, and then get rid of GENL_ID_GENERATE entirely, making it more robust. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/acpi/event.c | 1 - drivers/net/gtp.c | 1 - drivers/net/macsec.c | 1 - drivers/net/team/team.c | 1 - drivers/net/wireless/mac80211_hwsim.c | 1 - drivers/scsi/pmcraid.c | 6 ------ drivers/target/target_core_user.c | 1 - drivers/thermal/thermal_core.c | 1 - fs/dlm/netlink.c | 1 - fs/quota/netlink.c | 7 ------- include/linux/genl_magic_func.h | 1 - include/net/genetlink.h | 7 ++----- include/uapi/linux/genetlink.h | 1 - kernel/taskstats.c | 1 - net/batman-adv/netlink.c | 1 - net/core/devlink.c | 1 - net/core/drop_monitor.c | 1 - net/hsr/hsr_netlink.c | 1 - net/ieee802154/netlink.c | 1 - net/ieee802154/nl802154.c | 1 - net/ipv4/fou.c | 1 - net/ipv4/tcp_metrics.c | 1 - net/ipv6/ila/ila_xlat.c | 1 - net/irda/irnetlink.c | 1 - net/l2tp/l2tp_netlink.c | 1 - net/netfilter/ipvs/ip_vs_ctl.c | 1 - net/netlabel/netlabel_calipso.c | 1 - net/netlabel/netlabel_cipso_v4.c | 1 - net/netlabel/netlabel_mgmt.c | 1 - net/netlabel/netlabel_unlabeled.c | 1 - net/netlink/genetlink.c | 37 +++++++++++++++++++++-------------- net/nfc/netlink.c | 1 - net/openvswitch/datapath.c | 4 ---- net/tipc/netlink.c | 1 - net/tipc/netlink_compat.c | 1 - net/wimax/stack.c | 1 - net/wireless/nl80211.c | 1 - 37 files changed, 24 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index e24ea4e796e4..8dfca3d53131 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -83,7 +83,6 @@ static const struct genl_multicast_group acpi_event_mcgrps[] = { }; static struct genl_family acpi_event_genl_family = { - .id = GENL_ID_GENERATE, .name = ACPI_GENL_FAMILY_NAME, .version = ACPI_GENL_VERSION, .maxattr = ACPI_GENL_ATTR_MAX, diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 97e0cbca0a08..f66737ba1299 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1095,7 +1095,6 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info) } static struct genl_family gtp_genl_family = { - .id = GENL_ID_GENERATE, .name = "gtp", .version = 0, .hdrsize = 0, diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 1a134cb2d52c..a5309b81a786 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -1422,7 +1422,6 @@ static void clear_tx_sa(struct macsec_tx_sa *tx_sa) } static struct genl_family macsec_fam = { - .id = GENL_ID_GENERATE, .name = MACSEC_GENL_NAME, .hdrsize = 0, .version = MACSEC_GENL_VERSION, diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index a380649bf6b5..0b50205764ff 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2151,7 +2151,6 @@ static struct rtnl_link_ops team_link_ops __read_mostly = { ***********************************/ static struct genl_family team_nl_family = { - .id = GENL_ID_GENERATE, .name = TEAM_GENL_NAME, .version = TEAM_GENL_VERSION, .maxattr = TEAM_ATTR_MAX, diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e95b79bccf9b..54b6cd62676e 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -589,7 +589,6 @@ struct hwsim_radiotap_ack_hdr { /* MAC80211_HWSIM netlinf family */ static struct genl_family hwsim_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = "MAC80211_HWSIM", .version = 1, diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 68a5c347fae9..cc50eb87b28a 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -1369,12 +1369,6 @@ static struct genl_multicast_group pmcraid_mcgrps[] = { }; static struct genl_family pmcraid_event_family = { - /* - * Due to prior multicast group abuse (the code having assumed that - * the family ID can be used as a multicast group ID) we need to - * statically allocate a family (and thus group) ID. - */ - .id = GENL_ID_PMCRAID, .name = "pmcraid", .version = 1, .maxattr = PMCRAID_AEN_ATTR_MAX, diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 62bf4fe5704a..313a0ef3cda7 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -148,7 +148,6 @@ static const struct genl_multicast_group tcmu_mcgrps[] = { /* Our generic netlink family */ static struct genl_family tcmu_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = "TCM-USER", .version = 1, diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 226b0b4aced6..68d7503f6417 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -2164,7 +2164,6 @@ static const struct genl_multicast_group thermal_event_mcgrps[] = { }; static struct genl_family thermal_event_genl_family = { - .id = GENL_ID_GENERATE, .name = THERMAL_GENL_FAMILY_NAME, .version = THERMAL_GENL_VERSION, .maxattr = THERMAL_GENL_ATTR_MAX, diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index 1e6e227134d7..00d226956264 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c @@ -17,7 +17,6 @@ static uint32_t dlm_nl_seqnum; static uint32_t listener_nlportid; static struct genl_family family = { - .id = GENL_ID_GENERATE, .name = DLM_GENL_NAME, .version = DLM_GENL_VERSION, }; diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c index 8b252673d454..3965a5cdfaa2 100644 --- a/fs/quota/netlink.c +++ b/fs/quota/netlink.c @@ -13,13 +13,6 @@ static const struct genl_multicast_group quota_mcgrps[] = { /* Netlink family structure for quota */ static struct genl_family quota_genl_family = { - /* - * Needed due to multicast group ID abuse - old code assumed - * the family ID was also a valid multicast group ID (which - * isn't true) and userspace might thus rely on it. Assign a - * static ID for this group to make dealing with that easier. - */ - .id = GENL_ID_VFS_DQUOT, .hdrsize = 0, .name = "VFS_DQUOT", .version = 1, diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h index 667c31101b8b..7c070c1fe457 100644 --- a/include/linux/genl_magic_func.h +++ b/include/linux/genl_magic_func.h @@ -260,7 +260,6 @@ static struct genl_ops ZZZ_genl_ops[] __read_mostly = { */ #define ZZZ_genl_family CONCAT_(GENL_MAGIC_FAMILY, _genl_family) static struct genl_family ZZZ_genl_family __read_mostly = { - .id = GENL_ID_GENERATE, .name = __stringify(GENL_MAGIC_FAMILY), .version = GENL_MAGIC_VERSION, #ifdef GENL_MAGIC_FAMILY_HDRSZ diff --git a/include/net/genetlink.h b/include/net/genetlink.h index ef9defb3f5bc..43a5c3975a2f 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -20,7 +20,7 @@ struct genl_info; /** * struct genl_family - generic netlink family - * @id: protocol family idenfitier + * @id: protocol family identifier (private) * @hdrsize: length of user specific header in bytes * @name: name of family * @version: protocol version @@ -48,7 +48,7 @@ struct genl_info; * @n_ops: number of operations supported by this family (private) */ struct genl_family { - unsigned int id; + unsigned int id; /* private */ unsigned int hdrsize; char name[GENL_NAMSIZ]; unsigned int version; @@ -149,9 +149,6 @@ static inline int genl_register_family(struct genl_family *family) * Registers the specified family and operations from the specified table. * Only one family may be registered with the same family name or identifier. * - * The family id may equal GENL_ID_GENERATE causing an unique id to - * be automatically generated and assigned. - * * Either a doit or dumpit callback must be specified for every registered * operation or the function will fail. Only one operation structure per * command identifier may be registered. diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h index 5512c90af7e3..d9b2db4a29c6 100644 --- a/include/uapi/linux/genetlink.h +++ b/include/uapi/linux/genetlink.h @@ -26,7 +26,6 @@ struct genlmsghdr { /* * List of reserved static generic netlink identifiers: */ -#define GENL_ID_GENERATE 0 #define GENL_ID_CTRL NLMSG_MIN_TYPE #define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1) #define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2) diff --git a/kernel/taskstats.c b/kernel/taskstats.c index b3f05ee20d18..d7a1a9461a10 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -42,7 +42,6 @@ static int family_registered; struct kmem_cache *taskstats_cache; static struct genl_family family = { - .id = GENL_ID_GENERATE, .name = TASKSTATS_GENL_NAME, .version = TASKSTATS_GENL_VERSION, .maxattr = TASKSTATS_CMD_ATTR_MAX, diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 64cb6acbe0a6..a03b0ed7e8dd 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -49,7 +49,6 @@ #include "translation-table.h" struct genl_family batadv_netlink_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = BATADV_NL_NAME, .version = 1, diff --git a/net/core/devlink.c b/net/core/devlink.c index d2fd736de6a2..3008d9c33875 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -342,7 +342,6 @@ static void devlink_nl_post_doit(const struct genl_ops *ops, } static struct genl_family devlink_nl_family = { - .id = GENL_ID_GENERATE, .name = DEVLINK_GENL_NAME, .version = DEVLINK_GENL_VERSION, .maxattr = DEVLINK_ATTR_MAX, diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 72cfb0c61125..a5320dfcd978 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -60,7 +60,6 @@ struct dm_hw_stat_delta { }; static struct genl_family net_drop_monitor_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = "NET_DM", .version = 2, diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index d4d1617f43a8..2ad039492bee 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -132,7 +132,6 @@ static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = { }; static struct genl_family hsr_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = "HSR", .version = 1, diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index c8133c07ceee..19144158b696 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -29,7 +29,6 @@ static unsigned int ieee802154_seq_num; static DEFINE_SPINLOCK(ieee802154_seq_lock); struct genl_family nl802154_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = IEEE802154_NL_NAME, .version = 1, diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 21aabadccd0e..182299858f1d 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -34,7 +34,6 @@ static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb, /* the netlink family */ static struct genl_family nl802154_fam = { - .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ .name = NL802154_GENL_NAME, /* have users key off the name instead */ .hdrsize = 0, /* no private header */ .version = 1, /* no particular meaning now */ diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index cf50f7e2b012..e3fc527c5d37 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -623,7 +623,6 @@ static int fou_destroy(struct net *net, struct fou_cfg *cfg) } static struct genl_family fou_nl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = FOU_GENL_NAME, .version = FOU_GENL_VERSION, diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index bf1f3b2b29d1..3da305127b32 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -743,7 +743,6 @@ void tcp_fastopen_cache_set(struct sock *sk, u16 mss, } static struct genl_family tcp_metrics_nl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = TCP_METRICS_GENL_NAME, .version = TCP_METRICS_GENL_VERSION, diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index e604013dd814..0d57e27d1cdd 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -119,7 +119,6 @@ static const struct rhashtable_params rht_params = { }; static struct genl_family ila_nl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = ILA_GENL_NAME, .version = ILA_GENL_VERSION, diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c index e15c40e86660..f23b81aa91fe 100644 --- a/net/irda/irnetlink.c +++ b/net/irda/irnetlink.c @@ -25,7 +25,6 @@ static struct genl_family irda_nl_family = { - .id = GENL_ID_GENERATE, .name = IRDA_NL_NAME, .hdrsize = 0, .version = IRDA_NL_VERSION, diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index bf3117771822..4fbf1f41ac52 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -32,7 +32,6 @@ static struct genl_family l2tp_nl_family = { - .id = GENL_ID_GENERATE, .name = L2TP_GENL_NAME, .version = L2TP_GENL_VERSION, .hdrsize = 0, diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index c3c809b2e712..ceed66cdd03e 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2841,7 +2841,6 @@ static struct nf_sockopt_ops ip_vs_sockopts = { /* IPVS genetlink family */ static struct genl_family ip_vs_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = IPVS_GENL_NAME, .version = IPVS_GENL_VERSION, diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c index 2ec93c5e77bb..152e503b8c5d 100644 --- a/net/netlabel/netlabel_calipso.c +++ b/net/netlabel/netlabel_calipso.c @@ -61,7 +61,6 @@ struct netlbl_domhsh_walk_arg { /* NetLabel Generic NETLINK CALIPSO family */ static struct genl_family netlbl_calipso_gnl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = NETLBL_NLTYPE_CALIPSO_NAME, .version = NETLBL_PROTO_VERSION, diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index 7fd1104ba900..755b284e7ad4 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -60,7 +60,6 @@ struct netlbl_domhsh_walk_arg { /* NetLabel Generic NETLINK CIPSOv4 family */ static struct genl_family netlbl_cipsov4_gnl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = NETLBL_NLTYPE_CIPSOV4_NAME, .version = NETLBL_PROTO_VERSION, diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index f85d0e07af2d..3b00f2368fcd 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -61,7 +61,6 @@ struct netlbl_domhsh_walk_arg { /* NetLabel Generic NETLINK CIPSOv4 family */ static struct genl_family netlbl_mgmt_gnl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = NETLBL_NLTYPE_MGMT_NAME, .version = NETLBL_PROTO_VERSION, diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 4528cff9138b..c2ea8d1f653a 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -124,7 +124,6 @@ static u8 netlabel_unlabel_acceptflg; /* NetLabel Generic NETLINK unlabeled family */ static struct genl_family netlbl_unlabel_gnl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = NETLBL_NLTYPE_UNLABELED_NAME, .version = NETLBL_PROTO_VERSION, diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 01291b7a27bb..f19ec969edee 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -349,8 +349,6 @@ static int genl_validate_ops(const struct genl_family *family) * * Registers the specified family after validating it first. Only one * family may be registered with the same family name or identifier. - * The family id may equal GENL_ID_GENERATE causing an unique id to - * be automatically generated and assigned. * * The family's ops array must already be assigned, you can use the * genl_register_family_with_ops() helper function. @@ -359,13 +357,7 @@ static int genl_validate_ops(const struct genl_family *family) */ int __genl_register_family(struct genl_family *family) { - int err = -EINVAL, i; - - if (family->id && family->id < GENL_MIN_ID) - goto errout; - - if (family->id > GENL_MAX_ID) - goto errout; + int err, i; err = genl_validate_ops(family); if (err) @@ -378,8 +370,27 @@ int __genl_register_family(struct genl_family *family) goto errout_locked; } - if (family->id == GENL_ID_GENERATE) { - u16 newid = genl_generate_id(); + if (family == &genl_ctrl) { + family->id = GENL_ID_CTRL; + } else { + u16 newid; + + /* this should be left zero in the struct */ + WARN_ON(family->id); + + /* + * Sadly, a few cases need to be special-cased + * due to them having previously abused the API + * and having used their family ID also as their + * multicast group ID, so we use reserved IDs + * for both to be sure we can do that mapping. + */ + if (strcmp(family->name, "pmcraid") == 0) + newid = GENL_ID_PMCRAID; + else if (strcmp(family->name, "VFS_DQUOT") == 0) + newid = GENL_ID_VFS_DQUOT; + else + newid = genl_generate_id(); if (!newid) { err = -ENOMEM; @@ -387,9 +398,6 @@ int __genl_register_family(struct genl_family *family) } family->id = newid; - } else if (genl_family_find_byid(family->id)) { - err = -EEXIST; - goto errout_locked; } if (family->maxattr && !family->parallel_ops) { @@ -419,7 +427,6 @@ int __genl_register_family(struct genl_family *family) errout_locked: genl_unlock_all(); -errout: return err; } EXPORT_SYMBOL(__genl_register_family); diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 79786bf62b88..c230403e066c 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -39,7 +39,6 @@ static const struct genl_multicast_group nfc_genl_mcgrps[] = { }; static struct genl_family nfc_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = 0, .name = NFC_GENL_NAME, .version = NFC_GENL_VERSION, diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 194435aa1165..f9fef7dfba15 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -671,7 +671,6 @@ static const struct genl_ops dp_packet_genl_ops[] = { }; static struct genl_family dp_packet_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = sizeof(struct ovs_header), .name = OVS_PACKET_FAMILY, .version = OVS_PACKET_VERSION, @@ -1436,7 +1435,6 @@ static const struct genl_ops dp_flow_genl_ops[] = { }; static struct genl_family dp_flow_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = sizeof(struct ovs_header), .name = OVS_FLOW_FAMILY, .version = OVS_FLOW_VERSION, @@ -1822,7 +1820,6 @@ static const struct genl_ops dp_datapath_genl_ops[] = { }; static struct genl_family dp_datapath_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = sizeof(struct ovs_header), .name = OVS_DATAPATH_FAMILY, .version = OVS_DATAPATH_VERSION, @@ -2244,7 +2241,6 @@ static const struct genl_ops dp_vport_genl_ops[] = { }; struct genl_family dp_vport_genl_family = { - .id = GENL_ID_GENERATE, .hdrsize = sizeof(struct ovs_header), .name = OVS_VPORT_FAMILY, .version = OVS_VPORT_VERSION, diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 4b94f3cfe3af..383b8fedabc7 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -136,7 +136,6 @@ const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = { * so we have a separate genl handling for the new API. */ struct genl_family tipc_genl_family = { - .id = GENL_ID_GENERATE, .name = TIPC_GENL_V2_NAME, .version = TIPC_GENL_V2_VERSION, .hdrsize = 0, diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 1fd464764765..f04428e4c8e5 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -1216,7 +1216,6 @@ send: } static struct genl_family tipc_genl_compat_family = { - .id = GENL_ID_GENERATE, .name = TIPC_GENL_NAME, .version = TIPC_GENL_VERSION, .hdrsize = TIPC_GENL_HDRLEN, diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 3f816e2971ee..8ac83a41585f 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -573,7 +573,6 @@ size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); struct genl_family wimax_gnl_family = { - .id = GENL_ID_GENERATE, .name = "WiMAX", .version = WIMAX_GNL_VERSION, .hdrsize = 0, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7d8cb3330c86..714beafe05e0 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -39,7 +39,6 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, /* the netlink family */ static struct genl_family nl80211_fam = { - .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ .name = NL80211_GENL_NAME, /* have users key off the name instead */ .hdrsize = 0, /* no private header */ .version = 1, /* no particular meaning now */ -- cgit v1.2.3 From 489111e5c25b93be80340c3113d71903d7c82136 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 24 Oct 2016 14:40:03 +0200 Subject: genetlink: statically initialize families Instead of providing macros/inline functions to initialize the families, make all users initialize them statically and get rid of the macros. This reduces the kernel code size by about 1.6k on x86-64 (with allyesconfig). Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/acpi/event.c | 1 + drivers/net/gtp.c | 21 +++++++---- drivers/net/macsec.c | 21 +++++++---- drivers/net/team/team.c | 22 +++++++---- drivers/net/wireless/mac80211_hwsim.c | 26 +++++++------ drivers/scsi/pmcraid.c | 1 + drivers/target/target_core_user.c | 1 + drivers/thermal/thermal_core.c | 1 + fs/dlm/netlink.c | 15 +++++--- fs/quota/netlink.c | 1 + include/linux/drbd_genl.h | 2 +- include/linux/genl_magic_func.h | 28 ++++++++------ include/net/genetlink.h | 71 ++++++----------------------------- kernel/taskstats.c | 17 ++++++--- net/batman-adv/netlink.c | 25 +++++++----- net/core/devlink.c | 27 +++++++------ net/core/drop_monitor.c | 20 ++++++---- net/hsr/hsr_netlink.c | 22 +++++++---- net/ieee802154/netlink.c | 23 +++++++----- net/ieee802154/nl802154.c | 34 ++++++++--------- net/ipv4/fou.c | 22 ++++++----- net/ipv4/tcp_metrics.c | 22 ++++++----- net/ipv6/ila/ila_xlat.c | 24 +++++++----- net/irda/irnetlink.c | 19 ++++++---- net/l2tp/l2tp_netlink.c | 25 +++++++----- net/netfilter/ipvs/ip_vs_ctl.c | 22 ++++++----- net/netlabel/netlabel_calipso.c | 20 ++++++---- net/netlabel/netlabel_cipso_v4.c | 21 ++++++----- net/netlabel/netlabel_mgmt.c | 20 ++++++---- net/netlabel/netlabel_unlabeled.c | 20 ++++++---- net/netlink/genetlink.c | 35 +++++++++-------- net/nfc/netlink.c | 24 +++++++----- net/openvswitch/datapath.c | 4 ++ net/tipc/netlink.c | 22 ++++++----- net/tipc/netlink_compat.c | 20 +++++----- net/wimax/stack.c | 19 +++++----- net/wireless/nl80211.c | 33 ++++++++-------- 37 files changed, 414 insertions(+), 337 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 8dfca3d53131..1ab12ad7d5ba 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -83,6 +83,7 @@ static const struct genl_multicast_group acpi_event_mcgrps[] = { }; static struct genl_family acpi_event_genl_family = { + .module = THIS_MODULE, .name = ACPI_GENL_FAMILY_NAME, .version = ACPI_GENL_VERSION, .maxattr = ACPI_GENL_ATTR_MAX, diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index f66737ba1299..0604fd78f826 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1094,13 +1094,7 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info) return 0; } -static struct genl_family gtp_genl_family = { - .name = "gtp", - .version = 0, - .hdrsize = 0, - .maxattr = GTPA_MAX, - .netnsok = true, -}; +static struct genl_family gtp_genl_family; static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, u32 type, struct pdp_ctx *pctx) @@ -1296,6 +1290,17 @@ static const struct genl_ops gtp_genl_ops[] = { }, }; +static struct genl_family gtp_genl_family = { + .name = "gtp", + .version = 0, + .hdrsize = 0, + .maxattr = GTPA_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = gtp_genl_ops, + .n_ops = ARRAY_SIZE(gtp_genl_ops), +}; + static int __net_init gtp_net_init(struct net *net) { struct gtp_net *gn = net_generic(net, gtp_net_id); @@ -1335,7 +1340,7 @@ static int __init gtp_init(void) if (err < 0) goto error_out; - err = genl_register_family_with_ops(>p_genl_family, gtp_genl_ops); + err = genl_register_family(>p_genl_family); if (err < 0) goto unreg_rtnl_link; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index a5309b81a786..63ca7a3c77cf 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -1421,13 +1421,7 @@ static void clear_tx_sa(struct macsec_tx_sa *tx_sa) macsec_txsa_put(tx_sa); } -static struct genl_family macsec_fam = { - .name = MACSEC_GENL_NAME, - .hdrsize = 0, - .version = MACSEC_GENL_VERSION, - .maxattr = MACSEC_ATTR_MAX, - .netnsok = true, -}; +static struct genl_family macsec_fam; static struct net_device *get_dev_from_nl(struct net *net, struct nlattr **attrs) @@ -2654,6 +2648,17 @@ static const struct genl_ops macsec_genl_ops[] = { }, }; +static struct genl_family macsec_fam = { + .name = MACSEC_GENL_NAME, + .hdrsize = 0, + .version = MACSEC_GENL_VERSION, + .maxattr = MACSEC_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = macsec_genl_ops, + .n_ops = ARRAY_SIZE(macsec_genl_ops), +}; + static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -3461,7 +3466,7 @@ static int __init macsec_init(void) if (err) goto notifier; - err = genl_register_family_with_ops(&macsec_fam, macsec_genl_ops); + err = genl_register_family(&macsec_fam); if (err) goto rtnl; diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 0b50205764ff..46bf7c1216c0 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2150,12 +2150,7 @@ static struct rtnl_link_ops team_link_ops __read_mostly = { * Generic netlink custom interface ***********************************/ -static struct genl_family team_nl_family = { - .name = TEAM_GENL_NAME, - .version = TEAM_GENL_VERSION, - .maxattr = TEAM_ATTR_MAX, - .netnsok = true, -}; +static struct genl_family team_nl_family; static const struct nla_policy team_nl_policy[TEAM_ATTR_MAX + 1] = { [TEAM_ATTR_UNSPEC] = { .type = NLA_UNSPEC, }, @@ -2745,6 +2740,18 @@ static const struct genl_multicast_group team_nl_mcgrps[] = { { .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, }, }; +static struct genl_family team_nl_family = { + .name = TEAM_GENL_NAME, + .version = TEAM_GENL_VERSION, + .maxattr = TEAM_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = team_nl_ops, + .n_ops = ARRAY_SIZE(team_nl_ops), + .mcgrps = team_nl_mcgrps, + .n_mcgrps = ARRAY_SIZE(team_nl_mcgrps), +}; + static int team_nl_send_multicast(struct sk_buff *skb, struct team *team, u32 portid) { @@ -2768,8 +2775,7 @@ static int team_nl_send_event_port_get(struct team *team, static int team_nl_init(void) { - return genl_register_family_with_ops_groups(&team_nl_family, team_nl_ops, - team_nl_mcgrps); + return genl_register_family(&team_nl_family); } static void team_nl_fini(void) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 54b6cd62676e..5d4637e586e8 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -587,14 +587,8 @@ struct hwsim_radiotap_ack_hdr { __le16 rt_chbitmask; } __packed; -/* MAC80211_HWSIM netlinf family */ -static struct genl_family hwsim_genl_family = { - .hdrsize = 0, - .name = "MAC80211_HWSIM", - .version = 1, - .maxattr = HWSIM_ATTR_MAX, - .netnsok = true, -}; +/* MAC80211_HWSIM netlink family */ +static struct genl_family hwsim_genl_family; enum hwsim_multicast_groups { HWSIM_MCGRP_CONFIG, @@ -3234,6 +3228,18 @@ static const struct genl_ops hwsim_ops[] = { }, }; +static struct genl_family hwsim_genl_family = { + .name = "MAC80211_HWSIM", + .version = 1, + .maxattr = HWSIM_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = hwsim_ops, + .n_ops = ARRAY_SIZE(hwsim_ops), + .mcgrps = hwsim_mcgrps, + .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps), +}; + static void destroy_radio(struct work_struct *work) { struct mac80211_hwsim_data *data = @@ -3287,9 +3293,7 @@ static int hwsim_init_netlink(void) printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); - rc = genl_register_family_with_ops_groups(&hwsim_genl_family, - hwsim_ops, - hwsim_mcgrps); + rc = genl_register_family(&hwsim_genl_family); if (rc) goto failure; diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index cc50eb87b28a..c0ab7bb8c3ce 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -1369,6 +1369,7 @@ static struct genl_multicast_group pmcraid_mcgrps[] = { }; static struct genl_family pmcraid_event_family = { + .module = THIS_MODULE, .name = "pmcraid", .version = 1, .maxattr = PMCRAID_AEN_ATTR_MAX, diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 313a0ef3cda7..3483372f5562 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -148,6 +148,7 @@ static const struct genl_multicast_group tcmu_mcgrps[] = { /* Our generic netlink family */ static struct genl_family tcmu_genl_family = { + .module = THIS_MODULE, .hdrsize = 0, .name = "TCM-USER", .version = 1, diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 68d7503f6417..93b6caab2d9f 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -2164,6 +2164,7 @@ static const struct genl_multicast_group thermal_event_mcgrps[] = { }; static struct genl_family thermal_event_genl_family = { + .module = THIS_MODULE, .name = THERMAL_GENL_FAMILY_NAME, .version = THERMAL_GENL_VERSION, .maxattr = THERMAL_GENL_ATTR_MAX, diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index 00d226956264..04042d69573c 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c @@ -16,10 +16,7 @@ static uint32_t dlm_nl_seqnum; static uint32_t listener_nlportid; -static struct genl_family family = { - .name = DLM_GENL_NAME, - .version = DLM_GENL_VERSION, -}; +static struct genl_family family; static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size) { @@ -75,9 +72,17 @@ static struct genl_ops dlm_nl_ops[] = { }, }; +static struct genl_family family = { + .name = DLM_GENL_NAME, + .version = DLM_GENL_VERSION, + .ops = dlm_nl_ops, + .n_ops = ARRAY_SIZE(dlm_nl_ops), + .module = THIS_MODULE, +}; + int __init dlm_netlink_init(void) { - return genl_register_family_with_ops(&family, dlm_nl_ops); + return genl_register_family(&family); } void dlm_netlink_exit(void) diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c index 3965a5cdfaa2..9457c7b0dfa2 100644 --- a/fs/quota/netlink.c +++ b/fs/quota/netlink.c @@ -13,6 +13,7 @@ static const struct genl_multicast_group quota_mcgrps[] = { /* Netlink family structure for quota */ static struct genl_family quota_genl_family = { + .module = THIS_MODULE, .hdrsize = 0, .name = "VFS_DQUOT", .version = 1, diff --git a/include/linux/drbd_genl.h b/include/linux/drbd_genl.h index c934d3a96b5e..2896f93808ae 100644 --- a/include/linux/drbd_genl.h +++ b/include/linux/drbd_genl.h @@ -67,7 +67,7 @@ * genl_magic_func.h * generates an entry in the static genl_ops array, * and static register/unregister functions to - * genl_register_family_with_ops(). + * genl_register_family(). * * flags and handler: * GENL_op_init( .doit = x, .dumpit = y, .flags = something) diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h index 7c070c1fe457..40c2e39362c8 100644 --- a/include/linux/genl_magic_func.h +++ b/include/linux/genl_magic_func.h @@ -259,15 +259,7 @@ static struct genl_ops ZZZ_genl_ops[] __read_mostly = { * {{{2 */ #define ZZZ_genl_family CONCAT_(GENL_MAGIC_FAMILY, _genl_family) -static struct genl_family ZZZ_genl_family __read_mostly = { - .name = __stringify(GENL_MAGIC_FAMILY), - .version = GENL_MAGIC_VERSION, -#ifdef GENL_MAGIC_FAMILY_HDRSZ - .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ), -#endif - .maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1, -}; - +static struct genl_family ZZZ_genl_family; /* * Magic: define multicast groups * Magic: define multicast group registration helper @@ -301,11 +293,23 @@ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ #undef GENL_mc_group #define GENL_mc_group(group) +static struct genl_family ZZZ_genl_family __read_mostly = { + .name = __stringify(GENL_MAGIC_FAMILY), + .version = GENL_MAGIC_VERSION, +#ifdef GENL_MAGIC_FAMILY_HDRSZ + .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ), +#endif + .maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1, + .ops = ZZZ_genl_ops, + .n_ops = ARRAY_SIZE(ZZZ_genl_ops), + .mcgrps = ZZZ_genl_mcgrps, + .n_mcgrps = ARRAY_SIZE(ZZZ_genl_mcgrps), + .module = THIS_MODULE, +}; + int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void) { - return genl_register_family_with_ops_groups(&ZZZ_genl_family, \ - ZZZ_genl_ops, \ - ZZZ_genl_mcgrps); + return genl_register_family(&ZZZ_genl_family); } void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void) diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 43a5c3975a2f..2298b50cee34 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -39,13 +39,14 @@ struct genl_info; * Note that unbind() will not be called symmetrically if the * generic netlink family is removed while there are still open * sockets. - * @attrbuf: buffer to store parsed attributes - * @family_list: family list - * @mcgrps: multicast groups used by this family (private) - * @n_mcgrps: number of multicast groups (private) + * @attrbuf: buffer to store parsed attributes (private) + * @family_list: family list (private) + * @mcgrps: multicast groups used by this family + * @n_mcgrps: number of multicast groups * @mcgrp_offset: starting number of multicast group IDs in this family - * @ops: the operations supported by this family (private) - * @n_ops: number of operations supported by this family (private) + * (private) + * @ops: the operations supported by this family + * @n_ops: number of operations supported by this family */ struct genl_family { unsigned int id; /* private */ @@ -64,10 +65,10 @@ struct genl_family { int (*mcast_bind)(struct net *net, int group); void (*mcast_unbind)(struct net *net, int group); struct nlattr ** attrbuf; /* private */ - const struct genl_ops * ops; /* private */ - const struct genl_multicast_group *mcgrps; /* private */ - unsigned int n_ops; /* private */ - unsigned int n_mcgrps; /* private */ + const struct genl_ops * ops; + const struct genl_multicast_group *mcgrps; + unsigned int n_ops; + unsigned int n_mcgrps; unsigned int mcgrp_offset; /* private */ struct list_head family_list; /* private */ struct module *module; @@ -132,55 +133,7 @@ struct genl_ops { u8 flags; }; -int __genl_register_family(struct genl_family *family); - -static inline int genl_register_family(struct genl_family *family) -{ - family->module = THIS_MODULE; - return __genl_register_family(family); -} - -/** - * genl_register_family_with_ops - register a generic netlink family with ops - * @family: generic netlink family - * @ops: operations to be registered - * @n_ops: number of elements to register - * - * Registers the specified family and operations from the specified table. - * Only one family may be registered with the same family name or identifier. - * - * Either a doit or dumpit callback must be specified for every registered - * operation or the function will fail. Only one operation structure per - * command identifier may be registered. - * - * See include/net/genetlink.h for more documenation on the operations - * structure. - * - * Return 0 on success or a negative error code. - */ -static inline int -_genl_register_family_with_ops_grps(struct genl_family *family, - const struct genl_ops *ops, size_t n_ops, - const struct genl_multicast_group *mcgrps, - size_t n_mcgrps) -{ - family->module = THIS_MODULE; - family->ops = ops; - family->n_ops = n_ops; - family->mcgrps = mcgrps; - family->n_mcgrps = n_mcgrps; - return __genl_register_family(family); -} - -#define genl_register_family_with_ops(family, ops) \ - _genl_register_family_with_ops_grps((family), \ - (ops), ARRAY_SIZE(ops), \ - NULL, 0) -#define genl_register_family_with_ops_groups(family, ops, grps) \ - _genl_register_family_with_ops_grps((family), \ - (ops), ARRAY_SIZE(ops), \ - (grps), ARRAY_SIZE(grps)) - +int genl_register_family(struct genl_family *family); int genl_unregister_family(struct genl_family *family); void genl_notify(struct genl_family *family, struct sk_buff *skb, struct genl_info *info, u32 group, gfp_t flags); diff --git a/kernel/taskstats.c b/kernel/taskstats.c index d7a1a9461a10..4075ece592f2 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -41,11 +41,7 @@ static DEFINE_PER_CPU(__u32, taskstats_seqnum); static int family_registered; struct kmem_cache *taskstats_cache; -static struct genl_family family = { - .name = TASKSTATS_GENL_NAME, - .version = TASKSTATS_GENL_VERSION, - .maxattr = TASKSTATS_CMD_ATTR_MAX, -}; +static struct genl_family family; static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = { [TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 }, @@ -650,6 +646,15 @@ static const struct genl_ops taskstats_ops[] = { }, }; +static struct genl_family family = { + .name = TASKSTATS_GENL_NAME, + .version = TASKSTATS_GENL_VERSION, + .maxattr = TASKSTATS_CMD_ATTR_MAX, + .module = THIS_MODULE, + .ops = taskstats_ops, + .n_ops = ARRAY_SIZE(taskstats_ops), +}; + /* Needed early in initialization */ void __init taskstats_init_early(void) { @@ -666,7 +671,7 @@ static int __init taskstats_init(void) { int rc; - rc = genl_register_family_with_ops(&family, taskstats_ops); + rc = genl_register_family(&family); if (rc) return rc; diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index a03b0ed7e8dd..e28cec34a016 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -48,13 +48,7 @@ #include "tp_meter.h" #include "translation-table.h" -struct genl_family batadv_netlink_family = { - .hdrsize = 0, - .name = BATADV_NL_NAME, - .version = 1, - .maxattr = BATADV_ATTR_MAX, - .netnsok = true, -}; +struct genl_family batadv_netlink_family; /* multicast groups */ enum batadv_netlink_multicast_groups { @@ -609,6 +603,19 @@ static struct genl_ops batadv_netlink_ops[] = { }; +struct genl_family batadv_netlink_family = { + .hdrsize = 0, + .name = BATADV_NL_NAME, + .version = 1, + .maxattr = BATADV_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = batadv_netlink_ops, + .n_ops = ARRAY_SIZE(batadv_netlink_ops), + .mcgrps = batadv_netlink_mcgrps, + .n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps), +}; + /** * batadv_netlink_register - register batadv genl netlink family */ @@ -616,9 +623,7 @@ void __init batadv_netlink_register(void) { int ret; - ret = genl_register_family_with_ops_groups(&batadv_netlink_family, - batadv_netlink_ops, - batadv_netlink_mcgrps); + ret = genl_register_family(&batadv_netlink_family); if (ret) pr_warn("unable to register netlink family"); } diff --git a/net/core/devlink.c b/net/core/devlink.c index 3008d9c33875..063da8091aef 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -341,14 +341,7 @@ static void devlink_nl_post_doit(const struct genl_ops *ops, mutex_unlock(&devlink_mutex); } -static struct genl_family devlink_nl_family = { - .name = DEVLINK_GENL_NAME, - .version = DEVLINK_GENL_VERSION, - .maxattr = DEVLINK_ATTR_MAX, - .netnsok = true, - .pre_doit = devlink_nl_pre_doit, - .post_doit = devlink_nl_post_doit, -}; +static struct genl_family devlink_nl_family; enum devlink_multicast_groups { DEVLINK_MCGRP_CONFIG, @@ -1619,6 +1612,20 @@ static const struct genl_ops devlink_nl_ops[] = { }, }; +static struct genl_family devlink_nl_family = { + .name = DEVLINK_GENL_NAME, + .version = DEVLINK_GENL_VERSION, + .maxattr = DEVLINK_ATTR_MAX, + .netnsok = true, + .pre_doit = devlink_nl_pre_doit, + .post_doit = devlink_nl_post_doit, + .module = THIS_MODULE, + .ops = devlink_nl_ops, + .n_ops = ARRAY_SIZE(devlink_nl_ops), + .mcgrps = devlink_nl_mcgrps, + .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), +}; + /** * devlink_alloc - Allocate new devlink instance resources * @@ -1841,9 +1848,7 @@ EXPORT_SYMBOL_GPL(devlink_sb_unregister); static int __init devlink_module_init(void) { - return genl_register_family_with_ops_groups(&devlink_nl_family, - devlink_nl_ops, - devlink_nl_mcgrps); + return genl_register_family(&devlink_nl_family); } static void __exit devlink_module_exit(void) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index a5320dfcd978..80c002794ff6 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -59,11 +59,7 @@ struct dm_hw_stat_delta { unsigned long last_drop_val; }; -static struct genl_family net_drop_monitor_family = { - .hdrsize = 0, - .name = "NET_DM", - .version = 2, -}; +static struct genl_family net_drop_monitor_family; static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data); @@ -350,6 +346,17 @@ static const struct genl_ops dropmon_ops[] = { }, }; +static struct genl_family net_drop_monitor_family = { + .hdrsize = 0, + .name = "NET_DM", + .version = 2, + .module = THIS_MODULE, + .ops = dropmon_ops, + .n_ops = ARRAY_SIZE(dropmon_ops), + .mcgrps = dropmon_mcgrps, + .n_mcgrps = ARRAY_SIZE(dropmon_mcgrps), +}; + static struct notifier_block dropmon_net_notifier = { .notifier_call = dropmon_net_event }; @@ -366,8 +373,7 @@ static int __init init_net_drop_monitor(void) return -ENOSPC; } - rc = genl_register_family_with_ops_groups(&net_drop_monitor_family, - dropmon_ops, dropmon_mcgrps); + rc = genl_register_family(&net_drop_monitor_family); if (rc) { pr_err("Could not create drop monitor netlink family\n"); return rc; diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index 2ad039492bee..aab34c7f6f89 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -131,12 +131,7 @@ static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = { [HSR_A_IF2_SEQ] = { .type = NLA_U16 }, }; -static struct genl_family hsr_genl_family = { - .hdrsize = 0, - .name = "HSR", - .version = 1, - .maxattr = HSR_A_MAX, -}; +static struct genl_family hsr_genl_family; static const struct genl_multicast_group hsr_mcgrps[] = { { .name = "hsr-network", }, @@ -466,6 +461,18 @@ static const struct genl_ops hsr_ops[] = { }, }; +static struct genl_family hsr_genl_family = { + .hdrsize = 0, + .name = "HSR", + .version = 1, + .maxattr = HSR_A_MAX, + .module = THIS_MODULE, + .ops = hsr_ops, + .n_ops = ARRAY_SIZE(hsr_ops), + .mcgrps = hsr_mcgrps, + .n_mcgrps = ARRAY_SIZE(hsr_mcgrps), +}; + int __init hsr_netlink_init(void) { int rc; @@ -474,8 +481,7 @@ int __init hsr_netlink_init(void) if (rc) goto fail_rtnl_link_register; - rc = genl_register_family_with_ops_groups(&hsr_genl_family, hsr_ops, - hsr_mcgrps); + rc = genl_register_family(&hsr_genl_family); if (rc) goto fail_genl_register_family; diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 19144158b696..08e62470bac2 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -28,13 +28,6 @@ static unsigned int ieee802154_seq_num; static DEFINE_SPINLOCK(ieee802154_seq_lock); -struct genl_family nl802154_family = { - .hdrsize = 0, - .name = IEEE802154_NL_NAME, - .version = 1, - .maxattr = IEEE802154_ATTR_MAX, -}; - /* Requests to userspace */ struct sk_buff *ieee802154_nl_create(int flags, u8 req) { @@ -138,11 +131,21 @@ static const struct genl_multicast_group ieee802154_mcgrps[] = { [IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, }, }; +struct genl_family nl802154_family = { + .hdrsize = 0, + .name = IEEE802154_NL_NAME, + .version = 1, + .maxattr = IEEE802154_ATTR_MAX, + .module = THIS_MODULE, + .ops = ieee8021154_ops, + .n_ops = ARRAY_SIZE(ieee8021154_ops), + .mcgrps = ieee802154_mcgrps, + .n_mcgrps = ARRAY_SIZE(ieee802154_mcgrps), +}; + int __init ieee802154_nl_init(void) { - return genl_register_family_with_ops_groups(&nl802154_family, - ieee8021154_ops, - ieee802154_mcgrps); + return genl_register_family(&nl802154_family); } void ieee802154_nl_exit(void) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 182299858f1d..f7e75578aedd 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -26,22 +26,8 @@ #include "rdev-ops.h" #include "core.h" -static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, - struct genl_info *info); - -static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb, - struct genl_info *info); - /* the netlink family */ -static struct genl_family nl802154_fam = { - .name = NL802154_GENL_NAME, /* have users key off the name instead */ - .hdrsize = 0, /* no private header */ - .version = 1, /* no particular meaning now */ - .maxattr = NL802154_ATTR_MAX, - .netnsok = true, - .pre_doit = nl802154_pre_doit, - .post_doit = nl802154_post_doit, -}; +static struct genl_family nl802154_fam; /* multicast groups */ enum nl802154_multicast_groups { @@ -2476,11 +2462,25 @@ static const struct genl_ops nl802154_ops[] = { #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ }; +static struct genl_family nl802154_fam = { + .name = NL802154_GENL_NAME, /* have users key off the name instead */ + .hdrsize = 0, /* no private header */ + .version = 1, /* no particular meaning now */ + .maxattr = NL802154_ATTR_MAX, + .netnsok = true, + .pre_doit = nl802154_pre_doit, + .post_doit = nl802154_post_doit, + .module = THIS_MODULE, + .ops = nl802154_ops, + .n_ops = ARRAY_SIZE(nl802154_ops), + .mcgrps = nl802154_mcgrps, + .n_mcgrps = ARRAY_SIZE(nl802154_mcgrps), +}; + /* initialisation/exit functions */ int nl802154_init(void) { - return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops, - nl802154_mcgrps); + return genl_register_family(&nl802154_fam); } void nl802154_exit(void) diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index e3fc527c5d37..5b5226a2434f 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -622,13 +622,7 @@ static int fou_destroy(struct net *net, struct fou_cfg *cfg) return err; } -static struct genl_family fou_nl_family = { - .hdrsize = 0, - .name = FOU_GENL_NAME, - .version = FOU_GENL_VERSION, - .maxattr = FOU_ATTR_MAX, - .netnsok = true, -}; +static struct genl_family fou_nl_family; static const struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = { [FOU_ATTR_PORT] = { .type = NLA_U16, }, @@ -830,6 +824,17 @@ static const struct genl_ops fou_nl_ops[] = { }, }; +static struct genl_family fou_nl_family = { + .hdrsize = 0, + .name = FOU_GENL_NAME, + .version = FOU_GENL_VERSION, + .maxattr = FOU_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = fou_nl_ops, + .n_ops = ARRAY_SIZE(fou_nl_ops), +}; + size_t fou_encap_hlen(struct ip_tunnel_encap *e) { return sizeof(struct udphdr); @@ -1085,8 +1090,7 @@ static int __init fou_init(void) if (ret) goto exit; - ret = genl_register_family_with_ops(&fou_nl_family, - fou_nl_ops); + ret = genl_register_family(&fou_nl_family); if (ret < 0) goto unregister; diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 3da305127b32..bba3c72c4a39 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -742,13 +742,7 @@ void tcp_fastopen_cache_set(struct sock *sk, u16 mss, rcu_read_unlock(); } -static struct genl_family tcp_metrics_nl_family = { - .hdrsize = 0, - .name = TCP_METRICS_GENL_NAME, - .version = TCP_METRICS_GENL_VERSION, - .maxattr = TCP_METRICS_ATTR_MAX, - .netnsok = true, -}; +static struct genl_family tcp_metrics_nl_family; static const struct nla_policy tcp_metrics_nl_policy[TCP_METRICS_ATTR_MAX + 1] = { [TCP_METRICS_ATTR_ADDR_IPV4] = { .type = NLA_U32, }, @@ -1115,6 +1109,17 @@ static const struct genl_ops tcp_metrics_nl_ops[] = { }, }; +static struct genl_family tcp_metrics_nl_family = { + .hdrsize = 0, + .name = TCP_METRICS_GENL_NAME, + .version = TCP_METRICS_GENL_VERSION, + .maxattr = TCP_METRICS_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = tcp_metrics_nl_ops, + .n_ops = ARRAY_SIZE(tcp_metrics_nl_ops), +}; + static unsigned int tcpmhash_entries; static int __init set_tcpmhash_entries(char *str) { @@ -1178,8 +1183,7 @@ void __init tcp_metrics_init(void) if (ret < 0) panic("Could not allocate the tcp_metrics hash table\n"); - ret = genl_register_family_with_ops(&tcp_metrics_nl_family, - tcp_metrics_nl_ops); + ret = genl_register_family(&tcp_metrics_nl_family); if (ret < 0) panic("Could not register tcp_metrics generic netlink\n"); } diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 0d57e27d1cdd..97f7b0cc4675 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -118,14 +118,7 @@ static const struct rhashtable_params rht_params = { .obj_cmpfn = ila_cmpfn, }; -static struct genl_family ila_nl_family = { - .hdrsize = 0, - .name = ILA_GENL_NAME, - .version = ILA_GENL_VERSION, - .maxattr = ILA_ATTR_MAX, - .netnsok = true, - .parallel_ops = true, -}; +static struct genl_family ila_nl_family; static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, @@ -560,6 +553,18 @@ static const struct genl_ops ila_nl_ops[] = { }, }; +static struct genl_family ila_nl_family = { + .hdrsize = 0, + .name = ILA_GENL_NAME, + .version = ILA_GENL_VERSION, + .maxattr = ILA_ATTR_MAX, + .netnsok = true, + .parallel_ops = true, + .module = THIS_MODULE, + .ops = ila_nl_ops, + .n_ops = ARRAY_SIZE(ila_nl_ops), +}; + #define ILA_HASH_TABLE_SIZE 1024 static __net_init int ila_init_net(struct net *net) @@ -630,8 +635,7 @@ int ila_xlat_init(void) if (ret) goto exit; - ret = genl_register_family_with_ops(&ila_nl_family, - ila_nl_ops); + ret = genl_register_family(&ila_nl_family); if (ret < 0) goto unregister; diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c index f23b81aa91fe..07877347c2f7 100644 --- a/net/irda/irnetlink.c +++ b/net/irda/irnetlink.c @@ -24,12 +24,7 @@ -static struct genl_family irda_nl_family = { - .name = IRDA_NL_NAME, - .hdrsize = 0, - .version = IRDA_NL_VERSION, - .maxattr = IRDA_NL_CMD_MAX, -}; +static struct genl_family irda_nl_family; static struct net_device * ifname_to_netdev(struct net *net, struct genl_info *info) { @@ -146,9 +141,19 @@ static const struct genl_ops irda_nl_ops[] = { }; +static struct genl_family irda_nl_family = { + .name = IRDA_NL_NAME, + .hdrsize = 0, + .version = IRDA_NL_VERSION, + .maxattr = IRDA_NL_CMD_MAX, + .module = THIS_MODULE, + .ops = irda_nl_ops, + .n_ops = ARRAY_SIZE(irda_nl_ops), +}; + int irda_nl_register(void) { - return genl_register_family_with_ops(&irda_nl_family, irda_nl_ops); + return genl_register_family(&irda_nl_family); } void irda_nl_unregister(void) diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 4fbf1f41ac52..e4e8c0769a6b 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -31,13 +31,7 @@ #include "l2tp_core.h" -static struct genl_family l2tp_nl_family = { - .name = L2TP_GENL_NAME, - .version = L2TP_GENL_VERSION, - .hdrsize = 0, - .maxattr = L2TP_ATTR_MAX, - .netnsok = true, -}; +static struct genl_family l2tp_nl_family; static const struct genl_multicast_group l2tp_multicast_group[] = { { @@ -976,6 +970,19 @@ static const struct genl_ops l2tp_nl_ops[] = { }, }; +static struct genl_family l2tp_nl_family = { + .name = L2TP_GENL_NAME, + .version = L2TP_GENL_VERSION, + .hdrsize = 0, + .maxattr = L2TP_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = l2tp_nl_ops, + .n_ops = ARRAY_SIZE(l2tp_nl_ops), + .mcgrps = l2tp_multicast_group, + .n_mcgrps = ARRAY_SIZE(l2tp_multicast_group), +}; + int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops) { int ret; @@ -1012,9 +1019,7 @@ EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops); static int l2tp_nl_init(void) { pr_info("L2TP netlink interface\n"); - return genl_register_family_with_ops_groups(&l2tp_nl_family, - l2tp_nl_ops, - l2tp_multicast_group); + return genl_register_family(&l2tp_nl_family); } static void l2tp_nl_cleanup(void) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index ceed66cdd03e..ea3e8aed063f 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2840,13 +2840,7 @@ static struct nf_sockopt_ops ip_vs_sockopts = { */ /* IPVS genetlink family */ -static struct genl_family ip_vs_genl_family = { - .hdrsize = 0, - .name = IPVS_GENL_NAME, - .version = IPVS_GENL_VERSION, - .maxattr = IPVS_CMD_MAX, - .netnsok = true, /* Make ipvsadm to work on netns */ -}; +static struct genl_family ip_vs_genl_family; /* Policy used for first-level command attributes */ static const struct nla_policy ip_vs_cmd_policy[IPVS_CMD_ATTR_MAX + 1] = { @@ -3871,10 +3865,20 @@ static const struct genl_ops ip_vs_genl_ops[] = { }, }; +static struct genl_family ip_vs_genl_family = { + .hdrsize = 0, + .name = IPVS_GENL_NAME, + .version = IPVS_GENL_VERSION, + .maxattr = IPVS_CMD_MAX, + .netnsok = true, /* Make ipvsadm to work on netns */ + .module = THIS_MODULE, + .ops = ip_vs_genl_ops, + .n_ops = ARRAY_SIZE(ip_vs_genl_ops), +}; + static int __init ip_vs_genl_register(void) { - return genl_register_family_with_ops(&ip_vs_genl_family, - ip_vs_genl_ops); + return genl_register_family(&ip_vs_genl_family); } static void ip_vs_genl_unregister(void) diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c index 152e503b8c5d..ca7c9c411a5c 100644 --- a/net/netlabel/netlabel_calipso.c +++ b/net/netlabel/netlabel_calipso.c @@ -60,12 +60,7 @@ struct netlbl_domhsh_walk_arg { }; /* NetLabel Generic NETLINK CALIPSO family */ -static struct genl_family netlbl_calipso_gnl_family = { - .hdrsize = 0, - .name = NETLBL_NLTYPE_CALIPSO_NAME, - .version = NETLBL_PROTO_VERSION, - .maxattr = NLBL_CALIPSO_A_MAX, -}; +static struct genl_family netlbl_calipso_gnl_family; /* NetLabel Netlink attribute policy */ static const struct nla_policy calipso_genl_policy[NLBL_CALIPSO_A_MAX + 1] = { @@ -354,6 +349,16 @@ static const struct genl_ops netlbl_calipso_ops[] = { }, }; +static struct genl_family netlbl_calipso_gnl_family = { + .hdrsize = 0, + .name = NETLBL_NLTYPE_CALIPSO_NAME, + .version = NETLBL_PROTO_VERSION, + .maxattr = NLBL_CALIPSO_A_MAX, + .module = THIS_MODULE, + .ops = netlbl_calipso_ops, + .n_ops = ARRAY_SIZE(netlbl_calipso_ops), +}; + /* NetLabel Generic NETLINK Protocol Functions */ @@ -367,8 +372,7 @@ static const struct genl_ops netlbl_calipso_ops[] = { */ int __init netlbl_calipso_genl_init(void) { - return genl_register_family_with_ops(&netlbl_calipso_gnl_family, - netlbl_calipso_ops); + return genl_register_family(&netlbl_calipso_gnl_family); } static const struct netlbl_calipso_ops *calipso_ops; diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index 755b284e7ad4..a665eae91245 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -59,13 +59,7 @@ struct netlbl_domhsh_walk_arg { }; /* NetLabel Generic NETLINK CIPSOv4 family */ -static struct genl_family netlbl_cipsov4_gnl_family = { - .hdrsize = 0, - .name = NETLBL_NLTYPE_CIPSOV4_NAME, - .version = NETLBL_PROTO_VERSION, - .maxattr = NLBL_CIPSOV4_A_MAX, -}; - +static struct genl_family netlbl_cipsov4_gnl_family; /* NetLabel Netlink attribute policy */ static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = { [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 }, @@ -766,6 +760,16 @@ static const struct genl_ops netlbl_cipsov4_ops[] = { }, }; +static struct genl_family netlbl_cipsov4_gnl_family = { + .hdrsize = 0, + .name = NETLBL_NLTYPE_CIPSOV4_NAME, + .version = NETLBL_PROTO_VERSION, + .maxattr = NLBL_CIPSOV4_A_MAX, + .module = THIS_MODULE, + .ops = netlbl_cipsov4_ops, + .n_ops = ARRAY_SIZE(netlbl_cipsov4_ops), +}; + /* * NetLabel Generic NETLINK Protocol Functions */ @@ -780,6 +784,5 @@ static const struct genl_ops netlbl_cipsov4_ops[] = { */ int __init netlbl_cipsov4_genl_init(void) { - return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family, - netlbl_cipsov4_ops); + return genl_register_family(&netlbl_cipsov4_gnl_family); } diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 3b00f2368fcd..ecfe8eb149db 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -60,12 +60,7 @@ struct netlbl_domhsh_walk_arg { }; /* NetLabel Generic NETLINK CIPSOv4 family */ -static struct genl_family netlbl_mgmt_gnl_family = { - .hdrsize = 0, - .name = NETLBL_NLTYPE_MGMT_NAME, - .version = NETLBL_PROTO_VERSION, - .maxattr = NLBL_MGMT_A_MAX, -}; +static struct genl_family netlbl_mgmt_gnl_family; /* NetLabel Netlink attribute policy */ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { @@ -833,6 +828,16 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = { }, }; +static struct genl_family netlbl_mgmt_gnl_family = { + .hdrsize = 0, + .name = NETLBL_NLTYPE_MGMT_NAME, + .version = NETLBL_PROTO_VERSION, + .maxattr = NLBL_MGMT_A_MAX, + .module = THIS_MODULE, + .ops = netlbl_mgmt_genl_ops, + .n_ops = ARRAY_SIZE(netlbl_mgmt_genl_ops), +}; + /* * NetLabel Generic NETLINK Protocol Functions */ @@ -847,6 +852,5 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = { */ int __init netlbl_mgmt_genl_init(void) { - return genl_register_family_with_ops(&netlbl_mgmt_gnl_family, - netlbl_mgmt_genl_ops); + return genl_register_family(&netlbl_mgmt_gnl_family); } diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index c2ea8d1f653a..5dbbad41114f 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -123,12 +123,7 @@ static struct netlbl_unlhsh_iface __rcu *netlbl_unlhsh_def; static u8 netlabel_unlabel_acceptflg; /* NetLabel Generic NETLINK unlabeled family */ -static struct genl_family netlbl_unlabel_gnl_family = { - .hdrsize = 0, - .name = NETLBL_NLTYPE_UNLABELED_NAME, - .version = NETLBL_PROTO_VERSION, - .maxattr = NLBL_UNLABEL_A_MAX, -}; +static struct genl_family netlbl_unlabel_gnl_family; /* NetLabel Netlink attribute policy */ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = { @@ -1377,6 +1372,16 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = { }, }; +static struct genl_family netlbl_unlabel_gnl_family = { + .hdrsize = 0, + .name = NETLBL_NLTYPE_UNLABELED_NAME, + .version = NETLBL_PROTO_VERSION, + .maxattr = NLBL_UNLABEL_A_MAX, + .module = THIS_MODULE, + .ops = netlbl_unlabel_genl_ops, + .n_ops = ARRAY_SIZE(netlbl_unlabel_genl_ops), +}; + /* * NetLabel Generic NETLINK Protocol Functions */ @@ -1391,8 +1396,7 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = { */ int __init netlbl_unlabel_genl_init(void) { - return genl_register_family_with_ops(&netlbl_unlabel_gnl_family, - netlbl_unlabel_genl_ops); + return genl_register_family(&netlbl_unlabel_gnl_family); } /* diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index f19ec969edee..ca582ee4ae05 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -344,18 +344,18 @@ static int genl_validate_ops(const struct genl_family *family) } /** - * __genl_register_family - register a generic netlink family + * genl_register_family - register a generic netlink family * @family: generic netlink family * * Registers the specified family after validating it first. Only one * family may be registered with the same family name or identifier. * - * The family's ops array must already be assigned, you can use the - * genl_register_family_with_ops() helper function. + * The family's ops, multicast groups and module pointer must already + * be assigned. * * Return 0 on success or a negative error code. */ -int __genl_register_family(struct genl_family *family) +int genl_register_family(struct genl_family *family) { int err, i; @@ -429,7 +429,7 @@ errout_locked: genl_unlock_all(); return err; } -EXPORT_SYMBOL(__genl_register_family); +EXPORT_SYMBOL(genl_register_family); /** * genl_unregister_family - unregister generic netlink family @@ -452,7 +452,6 @@ int genl_unregister_family(struct genl_family *family) genl_unregister_mc_groups(family); list_del(&rc->family_list); - family->n_ops = 0; up_write(&cb_lock); wait_event(genl_sk_destructing_waitq, atomic_read(&genl_sk_destructing_cnt) == 0); @@ -681,13 +680,7 @@ static void genl_rcv(struct sk_buff *skb) * Controller **************************************************************************/ -static struct genl_family genl_ctrl = { - .id = GENL_ID_CTRL, - .name = "nlctrl", - .version = 0x2, - .maxattr = CTRL_ATTR_MAX, - .netnsok = true, -}; +static struct genl_family genl_ctrl; static int ctrl_fill_info(struct genl_family *family, u32 portid, u32 seq, u32 flags, struct sk_buff *skb, u8 cmd) @@ -997,6 +990,19 @@ static const struct genl_multicast_group genl_ctrl_groups[] = { { .name = "notify", }, }; +static struct genl_family genl_ctrl = { + .module = THIS_MODULE, + .ops = genl_ctrl_ops, + .n_ops = ARRAY_SIZE(genl_ctrl_ops), + .mcgrps = genl_ctrl_groups, + .n_mcgrps = ARRAY_SIZE(genl_ctrl_groups), + .id = GENL_ID_CTRL, + .name = "nlctrl", + .version = 0x2, + .maxattr = CTRL_ATTR_MAX, + .netnsok = true, +}; + static int genl_bind(struct net *net, int group) { int i, err = -ENOENT; @@ -1086,8 +1092,7 @@ static int __init genl_init(void) for (i = 0; i < GENL_FAM_TAB_SIZE; i++) INIT_LIST_HEAD(&family_ht[i]); - err = genl_register_family_with_ops_groups(&genl_ctrl, genl_ctrl_ops, - genl_ctrl_groups); + err = genl_register_family(&genl_ctrl); if (err < 0) goto problem; diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index c230403e066c..450b1e5144cc 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -38,13 +38,7 @@ static const struct genl_multicast_group nfc_genl_mcgrps[] = { { .name = NFC_GENL_MCAST_EVENT_NAME, }, }; -static struct genl_family nfc_genl_family = { - .hdrsize = 0, - .name = NFC_GENL_NAME, - .version = NFC_GENL_VERSION, - .maxattr = NFC_ATTR_MAX, -}; - +static struct genl_family nfc_genl_family; static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { [NFC_ATTR_DEVICE_INDEX] = { .type = NLA_U32 }, [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING, @@ -1752,6 +1746,18 @@ static const struct genl_ops nfc_genl_ops[] = { }, }; +static struct genl_family nfc_genl_family = { + .hdrsize = 0, + .name = NFC_GENL_NAME, + .version = NFC_GENL_VERSION, + .maxattr = NFC_ATTR_MAX, + .module = THIS_MODULE, + .ops = nfc_genl_ops, + .n_ops = ARRAY_SIZE(nfc_genl_ops), + .mcgrps = nfc_genl_mcgrps, + .n_mcgrps = ARRAY_SIZE(nfc_genl_mcgrps), +}; + struct urelease_work { struct work_struct w; @@ -1837,9 +1843,7 @@ int __init nfc_genl_init(void) { int rc; - rc = genl_register_family_with_ops_groups(&nfc_genl_family, - nfc_genl_ops, - nfc_genl_mcgrps); + rc = genl_register_family(&nfc_genl_family); if (rc) return rc; diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index f9fef7dfba15..ad6a111a0014 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -679,6 +679,7 @@ static struct genl_family dp_packet_genl_family = { .parallel_ops = true, .ops = dp_packet_genl_ops, .n_ops = ARRAY_SIZE(dp_packet_genl_ops), + .module = THIS_MODULE, }; static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats, @@ -1445,6 +1446,7 @@ static struct genl_family dp_flow_genl_family = { .n_ops = ARRAY_SIZE(dp_flow_genl_ops), .mcgrps = &ovs_dp_flow_multicast_group, .n_mcgrps = 1, + .module = THIS_MODULE, }; static size_t ovs_dp_cmd_msg_size(void) @@ -1830,6 +1832,7 @@ static struct genl_family dp_datapath_genl_family = { .n_ops = ARRAY_SIZE(dp_datapath_genl_ops), .mcgrps = &ovs_dp_datapath_multicast_group, .n_mcgrps = 1, + .module = THIS_MODULE, }; /* Called with ovs_mutex or RCU read lock. */ @@ -2251,6 +2254,7 @@ struct genl_family dp_vport_genl_family = { .n_ops = ARRAY_SIZE(dp_vport_genl_ops), .mcgrps = &ovs_dp_vport_multicast_group, .n_mcgrps = 1, + .module = THIS_MODULE, }; static struct genl_family * const dp_genl_families[] = { diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 383b8fedabc7..74a405bf107b 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -135,14 +135,6 @@ const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = { /* Users of the legacy API (tipc-config) can't handle that we add operations, * so we have a separate genl handling for the new API. */ -struct genl_family tipc_genl_family = { - .name = TIPC_GENL_V2_NAME, - .version = TIPC_GENL_V2_VERSION, - .hdrsize = 0, - .maxattr = TIPC_NLA_MAX, - .netnsok = true, -}; - static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_BEARER_DISABLE, @@ -257,6 +249,17 @@ static const struct genl_ops tipc_genl_v2_ops[] = { #endif }; +struct genl_family tipc_genl_family = { + .name = TIPC_GENL_V2_NAME, + .version = TIPC_GENL_V2_VERSION, + .hdrsize = 0, + .maxattr = TIPC_NLA_MAX, + .netnsok = true, + .module = THIS_MODULE, + .ops = tipc_genl_v2_ops, + .n_ops = ARRAY_SIZE(tipc_genl_v2_ops), +}; + int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) { u32 maxattr = tipc_genl_family.maxattr; @@ -272,8 +275,7 @@ int tipc_netlink_start(void) { int res; - res = genl_register_family_with_ops(&tipc_genl_family, - tipc_genl_v2_ops); + res = genl_register_family(&tipc_genl_family); if (res) { pr_err("Failed to register netlink interface\n"); return res; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index f04428e4c8e5..07b19931e458 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -1215,27 +1215,29 @@ send: return err; } +static struct genl_ops tipc_genl_compat_ops[] = { + { + .cmd = TIPC_GENL_CMD, + .doit = tipc_nl_compat_recv, + }, +}; + static struct genl_family tipc_genl_compat_family = { .name = TIPC_GENL_NAME, .version = TIPC_GENL_VERSION, .hdrsize = TIPC_GENL_HDRLEN, .maxattr = 0, .netnsok = true, -}; - -static struct genl_ops tipc_genl_compat_ops[] = { - { - .cmd = TIPC_GENL_CMD, - .doit = tipc_nl_compat_recv, - }, + .module = THIS_MODULE, + .ops = tipc_genl_compat_ops, + .n_ops = ARRAY_SIZE(tipc_genl_compat_ops), }; int tipc_netlink_compat_start(void) { int res; - res = genl_register_family_with_ops(&tipc_genl_compat_family, - tipc_genl_compat_ops); + res = genl_register_family(&tipc_genl_compat_family); if (res) { pr_err("Failed to register legacy compat interface\n"); return res; diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 8ac83a41585f..587e1627681f 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -572,15 +572,20 @@ struct d_level D_LEVEL[] = { size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); +static const struct genl_multicast_group wimax_gnl_mcgrps[] = { + { .name = "msg", }, +}; + struct genl_family wimax_gnl_family = { .name = "WiMAX", .version = WIMAX_GNL_VERSION, .hdrsize = 0, .maxattr = WIMAX_GNL_ATTR_MAX, -}; - -static const struct genl_multicast_group wimax_gnl_mcgrps[] = { - { .name = "msg", }, + .module = THIS_MODULE, + .ops = wimax_gnl_ops, + .n_ops = ARRAY_SIZE(wimax_gnl_ops), + .mcgrps = wimax_gnl_mcgrps, + .n_mcgrps = ARRAY_SIZE(wimax_gnl_mcgrps), }; @@ -595,11 +600,7 @@ int __init wimax_subsys_init(void) d_parse_params(D_LEVEL, D_LEVEL_SIZE, wimax_debug_params, "wimax.debug"); - snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name), - "WiMAX"); - result = genl_register_family_with_ops_groups(&wimax_gnl_family, - wimax_gnl_ops, - wimax_gnl_mcgrps); + result = genl_register_family(&wimax_gnl_family); if (unlikely(result < 0)) { pr_err("cannot register generic netlink family: %d\n", result); goto error_register_family; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 714beafe05e0..8e5ca3c47593 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -32,21 +32,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, struct cfg80211_crypto_settings *settings, int cipher_limit); -static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, - struct genl_info *info); -static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, - struct genl_info *info); - /* the netlink family */ -static struct genl_family nl80211_fam = { - .name = NL80211_GENL_NAME, /* have users key off the name instead */ - .hdrsize = 0, /* no private header */ - .version = 1, /* no particular meaning now */ - .maxattr = NL80211_ATTR_MAX, - .netnsok = true, - .pre_doit = nl80211_pre_doit, - .post_doit = nl80211_post_doit, -}; +static struct genl_family nl80211_fam; /* multicast groups */ enum nl80211_multicast_groups { @@ -12599,6 +12586,21 @@ static const struct genl_ops nl80211_ops[] = { }, }; +static struct genl_family nl80211_fam = { + .name = NL80211_GENL_NAME, /* have users key off the name instead */ + .hdrsize = 0, /* no private header */ + .version = 1, /* no particular meaning now */ + .maxattr = NL80211_ATTR_MAX, + .netnsok = true, + .pre_doit = nl80211_pre_doit, + .post_doit = nl80211_post_doit, + .module = THIS_MODULE, + .ops = nl80211_ops, + .n_ops = ARRAY_SIZE(nl80211_ops), + .mcgrps = nl80211_mcgrps, + .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps), +}; + /* notification functions */ void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev, @@ -14565,8 +14567,7 @@ int nl80211_init(void) { int err; - err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops, - nl80211_mcgrps); + err = genl_register_family(&nl80211_fam); if (err) return err; -- cgit v1.2.3 From 56989f6d8568c21257dcec0f5e644d5570ba3281 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 24 Oct 2016 14:40:05 +0200 Subject: genetlink: mark families as __ro_after_init Now genl_register_family() is the only thing (other than the users themselves, perhaps, but I didn't find any doing that) writing to the family struct. In all families that I found, genl_register_family() is only called from __init functions (some indirectly, in which case I've add __init annotations to clarifly things), so all can actually be marked __ro_after_init. This protects the data structure from accidental corruption. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/acpi/event.c | 4 ++-- drivers/net/gtp.c | 2 +- drivers/net/macsec.c | 2 +- drivers/net/team/team.c | 4 ++-- drivers/net/wireless/mac80211_hwsim.c | 4 ++-- drivers/scsi/pmcraid.c | 4 ++-- drivers/target/target_core_user.c | 2 +- drivers/thermal/thermal_core.c | 4 ++-- fs/dlm/netlink.c | 2 +- fs/quota/netlink.c | 2 +- include/linux/genl_magic_func.h | 2 +- kernel/taskstats.c | 2 +- net/batman-adv/netlink.c | 2 +- net/core/devlink.c | 2 +- net/core/drop_monitor.c | 2 +- net/hsr/hsr_netlink.c | 2 +- net/ieee802154/netlink.c | 2 +- net/ieee802154/nl802154.c | 4 ++-- net/ipv4/fou.c | 2 +- net/ipv4/tcp_metrics.c | 2 +- net/ipv6/ila/ila_xlat.c | 4 ++-- net/irda/irnetlink.c | 4 ++-- net/l2tp/l2tp_netlink.c | 4 ++-- net/netfilter/ipvs/ip_vs_ctl.c | 2 +- net/netlabel/netlabel_calipso.c | 2 +- net/netlabel/netlabel_cipso_v4.c | 2 +- net/netlabel/netlabel_mgmt.c | 2 +- net/netlabel/netlabel_unlabeled.c | 2 +- net/netlink/genetlink.c | 2 +- net/nfc/netlink.c | 2 +- net/openvswitch/datapath.c | 10 +++++----- net/tipc/netlink.c | 4 ++-- net/tipc/netlink_compat.c | 4 ++-- net/wimax/stack.c | 2 +- net/wireless/nl80211.c | 4 ++-- 35 files changed, 51 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 1ab12ad7d5ba..7fceb3b4691b 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -82,7 +82,7 @@ static const struct genl_multicast_group acpi_event_mcgrps[] = { { .name = ACPI_GENL_MCAST_GROUP_NAME, }, }; -static struct genl_family acpi_event_genl_family = { +static struct genl_family acpi_event_genl_family __ro_after_init = { .module = THIS_MODULE, .name = ACPI_GENL_FAMILY_NAME, .version = ACPI_GENL_VERSION, @@ -144,7 +144,7 @@ int acpi_bus_generate_netlink_event(const char *device_class, EXPORT_SYMBOL(acpi_bus_generate_netlink_event); -static int acpi_event_genetlink_init(void) +static int __init acpi_event_genetlink_init(void) { return genl_register_family(&acpi_event_genl_family); } diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 0604fd78f826..719d19f35673 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1290,7 +1290,7 @@ static const struct genl_ops gtp_genl_ops[] = { }, }; -static struct genl_family gtp_genl_family = { +static struct genl_family gtp_genl_family __ro_after_init = { .name = "gtp", .version = 0, .hdrsize = 0, diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 63ca7a3c77cf..0a715ab9d9cc 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2648,7 +2648,7 @@ static const struct genl_ops macsec_genl_ops[] = { }, }; -static struct genl_family macsec_fam = { +static struct genl_family macsec_fam __ro_after_init = { .name = MACSEC_GENL_NAME, .hdrsize = 0, .version = MACSEC_GENL_VERSION, diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 46bf7c1216c0..bdc58567d10e 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2740,7 +2740,7 @@ static const struct genl_multicast_group team_nl_mcgrps[] = { { .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, }, }; -static struct genl_family team_nl_family = { +static struct genl_family team_nl_family __ro_after_init = { .name = TEAM_GENL_NAME, .version = TEAM_GENL_VERSION, .maxattr = TEAM_ATTR_MAX, @@ -2773,7 +2773,7 @@ static int team_nl_send_event_port_get(struct team *team, port); } -static int team_nl_init(void) +static int __init team_nl_init(void) { return genl_register_family(&team_nl_family); } diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 5d4637e586e8..220e9dc8ccf8 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -3228,7 +3228,7 @@ static const struct genl_ops hwsim_ops[] = { }, }; -static struct genl_family hwsim_genl_family = { +static struct genl_family hwsim_genl_family __ro_after_init = { .name = "MAC80211_HWSIM", .version = 1, .maxattr = HWSIM_ATTR_MAX, @@ -3287,7 +3287,7 @@ static struct notifier_block hwsim_netlink_notifier = { .notifier_call = mac80211_hwsim_netlink_notify, }; -static int hwsim_init_netlink(void) +static int __init hwsim_init_netlink(void) { int rc; diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index c0ab7bb8c3ce..845affa112f7 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -1368,7 +1368,7 @@ static struct genl_multicast_group pmcraid_mcgrps[] = { { .name = "events", /* not really used - see ID discussion below */ }, }; -static struct genl_family pmcraid_event_family = { +static struct genl_family pmcraid_event_family __ro_after_init = { .module = THIS_MODULE, .name = "pmcraid", .version = 1, @@ -1384,7 +1384,7 @@ static struct genl_family pmcraid_event_family = { * 0 if the pmcraid_event_family is successfully registered * with netlink generic, non-zero otherwise */ -static int pmcraid_netlink_init(void) +static int __init pmcraid_netlink_init(void) { int result; diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 3483372f5562..0f173bf7dbac 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -147,7 +147,7 @@ static const struct genl_multicast_group tcmu_mcgrps[] = { }; /* Our generic netlink family */ -static struct genl_family tcmu_genl_family = { +static struct genl_family tcmu_genl_family __ro_after_init = { .module = THIS_MODULE, .hdrsize = 0, .name = "TCM-USER", diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 93b6caab2d9f..911fd964c742 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -2163,7 +2163,7 @@ static const struct genl_multicast_group thermal_event_mcgrps[] = { { .name = THERMAL_GENL_MCAST_GROUP_NAME, }, }; -static struct genl_family thermal_event_genl_family = { +static struct genl_family thermal_event_genl_family __ro_after_init = { .module = THIS_MODULE, .name = THERMAL_GENL_FAMILY_NAME, .version = THERMAL_GENL_VERSION, @@ -2235,7 +2235,7 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz, } EXPORT_SYMBOL_GPL(thermal_generate_netlink_event); -static int genetlink_init(void) +static int __init genetlink_init(void) { return genl_register_family(&thermal_event_genl_family); } diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index 04042d69573c..0643ae44f342 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c @@ -72,7 +72,7 @@ static struct genl_ops dlm_nl_ops[] = { }, }; -static struct genl_family family = { +static struct genl_family family __ro_after_init = { .name = DLM_GENL_NAME, .version = DLM_GENL_VERSION, .ops = dlm_nl_ops, diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c index 9457c7b0dfa2..e99b1a72d9a7 100644 --- a/fs/quota/netlink.c +++ b/fs/quota/netlink.c @@ -12,7 +12,7 @@ static const struct genl_multicast_group quota_mcgrps[] = { }; /* Netlink family structure for quota */ -static struct genl_family quota_genl_family = { +static struct genl_family quota_genl_family __ro_after_init = { .module = THIS_MODULE, .hdrsize = 0, .name = "VFS_DQUOT", diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h index 40c2e39362c8..377257d8f7e3 100644 --- a/include/linux/genl_magic_func.h +++ b/include/linux/genl_magic_func.h @@ -293,7 +293,7 @@ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ #undef GENL_mc_group #define GENL_mc_group(group) -static struct genl_family ZZZ_genl_family __read_mostly = { +static struct genl_family ZZZ_genl_family __ro_after_init = { .name = __stringify(GENL_MAGIC_FAMILY), .version = GENL_MAGIC_VERSION, #ifdef GENL_MAGIC_FAMILY_HDRSZ diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 4075ece592f2..9b7f838511ce 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -646,7 +646,7 @@ static const struct genl_ops taskstats_ops[] = { }, }; -static struct genl_family family = { +static struct genl_family family __ro_after_init = { .name = TASKSTATS_GENL_NAME, .version = TASKSTATS_GENL_VERSION, .maxattr = TASKSTATS_CMD_ATTR_MAX, diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index e28cec34a016..005012ba9b48 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -603,7 +603,7 @@ static struct genl_ops batadv_netlink_ops[] = { }; -struct genl_family batadv_netlink_family = { +struct genl_family batadv_netlink_family __ro_after_init = { .hdrsize = 0, .name = BATADV_NL_NAME, .version = 1, diff --git a/net/core/devlink.c b/net/core/devlink.c index 063da8091aef..c14f8b661db9 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -1612,7 +1612,7 @@ static const struct genl_ops devlink_nl_ops[] = { }, }; -static struct genl_family devlink_nl_family = { +static struct genl_family devlink_nl_family __ro_after_init = { .name = DEVLINK_GENL_NAME, .version = DEVLINK_GENL_VERSION, .maxattr = DEVLINK_ATTR_MAX, diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 80c002794ff6..8e0c0635ee97 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -346,7 +346,7 @@ static const struct genl_ops dropmon_ops[] = { }, }; -static struct genl_family net_drop_monitor_family = { +static struct genl_family net_drop_monitor_family __ro_after_init = { .hdrsize = 0, .name = "NET_DM", .version = 2, diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index aab34c7f6f89..1ab30e7d3f99 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -461,7 +461,7 @@ static const struct genl_ops hsr_ops[] = { }, }; -static struct genl_family hsr_genl_family = { +static struct genl_family hsr_genl_family __ro_after_init = { .hdrsize = 0, .name = "HSR", .version = 1, diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 08e62470bac2..6bde9e5a5503 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -131,7 +131,7 @@ static const struct genl_multicast_group ieee802154_mcgrps[] = { [IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, }, }; -struct genl_family nl802154_family = { +struct genl_family nl802154_family __ro_after_init = { .hdrsize = 0, .name = IEEE802154_NL_NAME, .version = 1, diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index f7e75578aedd..fc60cd061f39 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -2462,7 +2462,7 @@ static const struct genl_ops nl802154_ops[] = { #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ }; -static struct genl_family nl802154_fam = { +static struct genl_family nl802154_fam __ro_after_init = { .name = NL802154_GENL_NAME, /* have users key off the name instead */ .hdrsize = 0, /* no private header */ .version = 1, /* no particular meaning now */ @@ -2478,7 +2478,7 @@ static struct genl_family nl802154_fam = { }; /* initialisation/exit functions */ -int nl802154_init(void) +int __init nl802154_init(void) { return genl_register_family(&nl802154_fam); } diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 5b5226a2434f..6cb57bb8692d 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -824,7 +824,7 @@ static const struct genl_ops fou_nl_ops[] = { }, }; -static struct genl_family fou_nl_family = { +static struct genl_family fou_nl_family __ro_after_init = { .hdrsize = 0, .name = FOU_GENL_NAME, .version = FOU_GENL_VERSION, diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index bba3c72c4a39..d46f4d5b1c62 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -1109,7 +1109,7 @@ static const struct genl_ops tcp_metrics_nl_ops[] = { }, }; -static struct genl_family tcp_metrics_nl_family = { +static struct genl_family tcp_metrics_nl_family __ro_after_init = { .hdrsize = 0, .name = TCP_METRICS_GENL_NAME, .version = TCP_METRICS_GENL_VERSION, diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 97f7b0cc4675..628ae6d85b59 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -553,7 +553,7 @@ static const struct genl_ops ila_nl_ops[] = { }, }; -static struct genl_family ila_nl_family = { +static struct genl_family ila_nl_family __ro_after_init = { .hdrsize = 0, .name = ILA_GENL_NAME, .version = ILA_GENL_VERSION, @@ -627,7 +627,7 @@ static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral) return 0; } -int ila_xlat_init(void) +int __init ila_xlat_init(void) { int ret; diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c index 07877347c2f7..7fc340e574cf 100644 --- a/net/irda/irnetlink.c +++ b/net/irda/irnetlink.c @@ -141,7 +141,7 @@ static const struct genl_ops irda_nl_ops[] = { }; -static struct genl_family irda_nl_family = { +static struct genl_family irda_nl_family __ro_after_init = { .name = IRDA_NL_NAME, .hdrsize = 0, .version = IRDA_NL_VERSION, @@ -151,7 +151,7 @@ static struct genl_family irda_nl_family = { .n_ops = ARRAY_SIZE(irda_nl_ops), }; -int irda_nl_register(void) +int __init irda_nl_register(void) { return genl_register_family(&irda_nl_family); } diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index e4e8c0769a6b..59aa2d204e4a 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -970,7 +970,7 @@ static const struct genl_ops l2tp_nl_ops[] = { }, }; -static struct genl_family l2tp_nl_family = { +static struct genl_family l2tp_nl_family __ro_after_init = { .name = L2TP_GENL_NAME, .version = L2TP_GENL_VERSION, .hdrsize = 0, @@ -1016,7 +1016,7 @@ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type) } EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops); -static int l2tp_nl_init(void) +static int __init l2tp_nl_init(void) { pr_info("L2TP netlink interface\n"); return genl_register_family(&l2tp_nl_family); diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index ea3e8aed063f..6b85ded4f91d 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -3865,7 +3865,7 @@ static const struct genl_ops ip_vs_genl_ops[] = { }, }; -static struct genl_family ip_vs_genl_family = { +static struct genl_family ip_vs_genl_family __ro_after_init = { .hdrsize = 0, .name = IPVS_GENL_NAME, .version = IPVS_GENL_VERSION, diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c index ca7c9c411a5c..d177dd066504 100644 --- a/net/netlabel/netlabel_calipso.c +++ b/net/netlabel/netlabel_calipso.c @@ -349,7 +349,7 @@ static const struct genl_ops netlbl_calipso_ops[] = { }, }; -static struct genl_family netlbl_calipso_gnl_family = { +static struct genl_family netlbl_calipso_gnl_family __ro_after_init = { .hdrsize = 0, .name = NETLBL_NLTYPE_CALIPSO_NAME, .version = NETLBL_PROTO_VERSION, diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index a665eae91245..4149d3e63589 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -760,7 +760,7 @@ static const struct genl_ops netlbl_cipsov4_ops[] = { }, }; -static struct genl_family netlbl_cipsov4_gnl_family = { +static struct genl_family netlbl_cipsov4_gnl_family __ro_after_init = { .hdrsize = 0, .name = NETLBL_NLTYPE_CIPSOV4_NAME, .version = NETLBL_PROTO_VERSION, diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index ecfe8eb149db..21e0095b1d14 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -828,7 +828,7 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = { }, }; -static struct genl_family netlbl_mgmt_gnl_family = { +static struct genl_family netlbl_mgmt_gnl_family __ro_after_init = { .hdrsize = 0, .name = NETLBL_NLTYPE_MGMT_NAME, .version = NETLBL_PROTO_VERSION, diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 5dbbad41114f..22dc1b9d6362 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1372,7 +1372,7 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = { }, }; -static struct genl_family netlbl_unlabel_gnl_family = { +static struct genl_family netlbl_unlabel_gnl_family __ro_after_init = { .hdrsize = 0, .name = NETLBL_NLTYPE_UNLABELED_NAME, .version = NETLBL_PROTO_VERSION, diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 85659921e7b2..df0cbcddda2c 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -936,7 +936,7 @@ static const struct genl_multicast_group genl_ctrl_groups[] = { { .name = "notify", }, }; -static struct genl_family genl_ctrl = { +static struct genl_family genl_ctrl __ro_after_init = { .module = THIS_MODULE, .ops = genl_ctrl_ops, .n_ops = ARRAY_SIZE(genl_ctrl_ops), diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 450b1e5144cc..03f3d5c7beb8 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -1746,7 +1746,7 @@ static const struct genl_ops nfc_genl_ops[] = { }, }; -static struct genl_family nfc_genl_family = { +static struct genl_family nfc_genl_family __ro_after_init = { .hdrsize = 0, .name = NFC_GENL_NAME, .version = NFC_GENL_VERSION, diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index ad6a111a0014..fa8760176b7d 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -670,7 +670,7 @@ static const struct genl_ops dp_packet_genl_ops[] = { } }; -static struct genl_family dp_packet_genl_family = { +static struct genl_family dp_packet_genl_family __ro_after_init = { .hdrsize = sizeof(struct ovs_header), .name = OVS_PACKET_FAMILY, .version = OVS_PACKET_VERSION, @@ -1435,7 +1435,7 @@ static const struct genl_ops dp_flow_genl_ops[] = { }, }; -static struct genl_family dp_flow_genl_family = { +static struct genl_family dp_flow_genl_family __ro_after_init = { .hdrsize = sizeof(struct ovs_header), .name = OVS_FLOW_FAMILY, .version = OVS_FLOW_VERSION, @@ -1821,7 +1821,7 @@ static const struct genl_ops dp_datapath_genl_ops[] = { }, }; -static struct genl_family dp_datapath_genl_family = { +static struct genl_family dp_datapath_genl_family __ro_after_init = { .hdrsize = sizeof(struct ovs_header), .name = OVS_DATAPATH_FAMILY, .version = OVS_DATAPATH_VERSION, @@ -2243,7 +2243,7 @@ static const struct genl_ops dp_vport_genl_ops[] = { }, }; -struct genl_family dp_vport_genl_family = { +struct genl_family dp_vport_genl_family __ro_after_init = { .hdrsize = sizeof(struct ovs_header), .name = OVS_VPORT_FAMILY, .version = OVS_VPORT_VERSION, @@ -2272,7 +2272,7 @@ static void dp_unregister_genl(int n_families) genl_unregister_family(dp_genl_families[i]); } -static int dp_register_genl(void) +static int __init dp_register_genl(void) { int err; int i; diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 74a405bf107b..26ca8dd64ded 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -249,7 +249,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = { #endif }; -struct genl_family tipc_genl_family = { +struct genl_family tipc_genl_family __ro_after_init = { .name = TIPC_GENL_V2_NAME, .version = TIPC_GENL_V2_VERSION, .hdrsize = 0, @@ -271,7 +271,7 @@ int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) return nlmsg_parse(nlh, GENL_HDRLEN, *attr, maxattr, tipc_nl_policy); } -int tipc_netlink_start(void) +int __init tipc_netlink_start(void) { int res; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 07b19931e458..e1ae8a8a2b8e 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -1222,7 +1222,7 @@ static struct genl_ops tipc_genl_compat_ops[] = { }, }; -static struct genl_family tipc_genl_compat_family = { +static struct genl_family tipc_genl_compat_family __ro_after_init = { .name = TIPC_GENL_NAME, .version = TIPC_GENL_VERSION, .hdrsize = TIPC_GENL_HDRLEN, @@ -1233,7 +1233,7 @@ static struct genl_family tipc_genl_compat_family = { .n_ops = ARRAY_SIZE(tipc_genl_compat_ops), }; -int tipc_netlink_compat_start(void) +int __init tipc_netlink_compat_start(void) { int res; diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 587e1627681f..5db731512014 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -576,7 +576,7 @@ static const struct genl_multicast_group wimax_gnl_mcgrps[] = { { .name = "msg", }, }; -struct genl_family wimax_gnl_family = { +struct genl_family wimax_gnl_family __ro_after_init = { .name = "WiMAX", .version = WIMAX_GNL_VERSION, .hdrsize = 0, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8e5ca3c47593..271707dacfea 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -12586,7 +12586,7 @@ static const struct genl_ops nl80211_ops[] = { }, }; -static struct genl_family nl80211_fam = { +static struct genl_family nl80211_fam __ro_after_init = { .name = NL80211_GENL_NAME, /* have users key off the name instead */ .hdrsize = 0, /* no private header */ .version = 1, /* no particular meaning now */ @@ -14563,7 +14563,7 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev) /* initialisation/exit functions */ -int nl80211_init(void) +int __init nl80211_init(void) { int err; -- cgit v1.2.3 From 110447f8269a608cd69203fa2ccd801ea92e0a1a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 24 Oct 2016 14:42:26 +0200 Subject: ethernet: fix min/max MTU typos Fixes: d894be57ca92('ethernet: use net core MTU range checking in more drivers') CC: Jarod Wilson CC: Thomas Falcon Signed-off-by: Stefan Richter Acked-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/sb1250-mac.c | 2 +- drivers/net/ethernet/ibm/ibmveth.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index cb312e4c89f4..435a2e4739d1 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -2219,7 +2219,7 @@ static int sbmac_init(struct platform_device *pldev, long long base) dev->netdev_ops = &sbmac_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; - dev->max_mtu = 0; + dev->min_mtu = 0; dev->max_mtu = ENET_PACKET_SIZE; netif_napi_add(dev, &sc->napi, sbmac_poll, 16); diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 29c05d0d79a9..4a81c892fc31 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1549,7 +1549,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) } netdev->min_mtu = IBMVETH_MIN_MTU; - netdev->min_mtu = ETH_MAX_MTU; + netdev->max_mtu = ETH_MAX_MTU; memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN); -- cgit v1.2.3 From 861adc44d2905469f2b9a2e053f3dc64728091ee Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Fri, 21 Oct 2016 11:23:28 +0200 Subject: clk: stm32f4: Add LSI & LSE clocks This patch introduces the support of the LSI & LSE clocks. The clock drivers needs to disable the power domain write protection using syscon/regmap to enable these clocks. Signed-off-by: Gabriel Fernandez Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32f4.c | 131 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 126 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index 02d681008401..6427e0fdde59 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -19,10 +19,14 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include #define STM32F4_RCC_PLLCFGR 0x04 #define STM32F4_RCC_CFGR 0x08 @@ -31,6 +35,8 @@ #define STM32F4_RCC_AHB3ENR 0x38 #define STM32F4_RCC_APB1ENR 0x40 #define STM32F4_RCC_APB2ENR 0x44 +#define STM32F4_RCC_BDCR 0x70 +#define STM32F4_RCC_CSR 0x74 struct stm32f4_gate_data { u8 offset; @@ -120,13 +126,12 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = { { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, }; +enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, END_PRIMARY_CLK }; /* * MAX_CLKS is the maximum value in the enumeration below plus the combined * hweight of stm32f42xx_gate_map (plus one). */ -#define MAX_CLKS 74 - -enum { SYSTICK, FCLK }; +#define MAX_CLKS (71 + END_PRIMARY_CLK + 1) /* * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx @@ -140,6 +145,8 @@ static struct clk_hw *clks[MAX_CLKS]; static DEFINE_SPINLOCK(stm32f4_clk_lock); static void __iomem *base; +static struct regmap *pdrm; + /* * "Multiplier" device for APBx clocks. * @@ -259,7 +266,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) u64 table[ARRAY_SIZE(stm32f42xx_gate_map)]; if (primary == 1) { - if (WARN_ON(secondary > FCLK)) + if (WARN_ON(secondary >= END_PRIMARY_CLK)) return -EINVAL; return secondary; } @@ -276,7 +283,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) table[BIT_ULL_WORD(secondary)] &= GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0); - return FCLK + hweight64(table[0]) + + return END_PRIMARY_CLK - 1 + hweight64(table[0]) + (BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) + (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0); } @@ -292,6 +299,98 @@ stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data) return clks[i]; } +#define to_rgclk(_rgate) container_of(_rgate, struct stm32_rgate, gate) + +static inline void disable_power_domain_write_protection(void) +{ + if (pdrm) + regmap_update_bits(pdrm, 0x00, (1 << 8), (1 << 8)); +} + +static inline void enable_power_domain_write_protection(void) +{ + if (pdrm) + regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8)); +} + +struct stm32_rgate { + struct clk_gate gate; + u8 bit_rdy_idx; +}; + +#define RTC_TIMEOUT 1000000 + +static int rgclk_enable(struct clk_hw *hw) +{ + struct clk_gate *gate = to_clk_gate(hw); + struct stm32_rgate *rgate = to_rgclk(gate); + u32 reg; + int ret; + + disable_power_domain_write_protection(); + + clk_gate_ops.enable(hw); + + ret = readl_relaxed_poll_timeout_atomic(gate->reg, reg, + reg & rgate->bit_rdy_idx, 1000, RTC_TIMEOUT); + + enable_power_domain_write_protection(); + return ret; +} + +static void rgclk_disable(struct clk_hw *hw) +{ + clk_gate_ops.disable(hw); +} + +static int rgclk_is_enabled(struct clk_hw *hw) +{ + return clk_gate_ops.is_enabled(hw); +} + +static const struct clk_ops rgclk_ops = { + .enable = rgclk_enable, + .disable = rgclk_disable, + .is_enabled = rgclk_is_enabled, +}; + +static struct clk_hw *clk_register_rgate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, u8 bit_rdy_idx, + u8 clk_gate_flags, spinlock_t *lock) +{ + struct stm32_rgate *rgate; + struct clk_init_data init = { NULL }; + struct clk_hw *hw; + int ret; + + rgate = kzalloc(sizeof(*rgate), GFP_KERNEL); + if (!rgate) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &rgclk_ops; + init.flags = flags; + init.parent_names = &parent_name; + init.num_parents = 1; + + rgate->bit_rdy_idx = bit_rdy_idx; + + rgate->gate.lock = lock; + rgate->gate.reg = reg; + rgate->gate.bit_idx = bit_idx; + rgate->gate.hw.init = &init; + + hw = &rgate->gate.hw; + ret = clk_hw_register(dev, hw); + if (ret) { + kfree(rgate); + hw = ERR_PTR(ret); + } + + return hw; +} + static const char *sys_parents[] __initdata = { "hsi", NULL, "pll" }; static const struct clk_div_table ahb_div_table[] = { @@ -319,6 +418,12 @@ static void __init stm32f4_rcc_init(struct device_node *np) return; } + pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(pdrm)) { + pdrm = NULL; + pr_warn("%s: Unable to get syscfg\n", __func__); + } + hse_clk = of_clk_get_parent_name(np, 0); clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0, @@ -371,6 +476,22 @@ static void __init stm32f4_rcc_init(struct device_node *np) } } + clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0, + base + STM32F4_RCC_CSR, 0, 2, 0, &stm32f4_clk_lock); + + if (IS_ERR(clks[CLK_LSI])) { + pr_err("Unable to register lsi clock\n"); + goto fail; + } + + clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0, + base + STM32F4_RCC_BDCR, 0, 2, 0, &stm32f4_clk_lock); + + if (IS_ERR(clks[CLK_LSE])) { + pr_err("Unable to register lse clock\n"); + goto fail; + } + of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL); return; fail: -- cgit v1.2.3 From 4261a881cfee3758ca92a59e4f473ddac7e56103 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Fri, 21 Oct 2016 11:23:29 +0200 Subject: clk: stm32f4: Add RTC clock This patch introduces the support of the RTC clock. RTC clock can have 3 sources: lsi, lse and hse_rtc. Signed-off-by: Gabriel Fernandez Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32f4.c | 137 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index 6427e0fdde59..cbc814868508 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -126,7 +126,7 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = { { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, }; -enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, END_PRIMARY_CLK }; +enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK }; /* * MAX_CLKS is the maximum value in the enumeration below plus the combined * hweight of stm32f42xx_gate_map (plus one). @@ -313,6 +313,15 @@ static inline void enable_power_domain_write_protection(void) regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8)); } +static inline void sofware_reset_backup_domain(void) +{ + unsigned long val; + + val = readl(base + STM32F4_RCC_BDCR); + writel(val | BIT(16), base + STM32F4_RCC_BDCR); + writel(val & ~BIT(16), base + STM32F4_RCC_BDCR); +} + struct stm32_rgate { struct clk_gate gate; u8 bit_rdy_idx; @@ -391,6 +400,111 @@ static struct clk_hw *clk_register_rgate(struct device *dev, const char *name, return hw; } +static int cclk_gate_enable(struct clk_hw *hw) +{ + int ret; + + disable_power_domain_write_protection(); + + ret = clk_gate_ops.enable(hw); + + enable_power_domain_write_protection(); + + return ret; +} + +static void cclk_gate_disable(struct clk_hw *hw) +{ + disable_power_domain_write_protection(); + + clk_gate_ops.disable(hw); + + enable_power_domain_write_protection(); +} + +static int cclk_gate_is_enabled(struct clk_hw *hw) +{ + return clk_gate_ops.is_enabled(hw); +} + +static const struct clk_ops cclk_gate_ops = { + .enable = cclk_gate_enable, + .disable = cclk_gate_disable, + .is_enabled = cclk_gate_is_enabled, +}; + +static u8 cclk_mux_get_parent(struct clk_hw *hw) +{ + return clk_mux_ops.get_parent(hw); +} + +static int cclk_mux_set_parent(struct clk_hw *hw, u8 index) +{ + int ret; + + disable_power_domain_write_protection(); + + sofware_reset_backup_domain(); + + ret = clk_mux_ops.set_parent(hw, index); + + enable_power_domain_write_protection(); + + return ret; +} + +static const struct clk_ops cclk_mux_ops = { + .get_parent = cclk_mux_get_parent, + .set_parent = cclk_mux_set_parent, +}; + +static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name, + const char * const *parent_names, int num_parents, + void __iomem *reg, u8 bit_idx, u8 shift, unsigned long flags, + spinlock_t *lock) +{ + struct clk_hw *hw; + struct clk_gate *gate; + struct clk_mux *mux; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) { + hw = ERR_PTR(-EINVAL); + goto fail; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + kfree(gate); + hw = ERR_PTR(-EINVAL); + goto fail; + } + + gate->reg = reg; + gate->bit_idx = bit_idx; + gate->flags = 0; + gate->lock = lock; + + mux->reg = reg; + mux->shift = shift; + mux->mask = 3; + mux->flags = 0; + + hw = clk_hw_register_composite(dev, name, parent_names, num_parents, + &mux->hw, &cclk_mux_ops, + NULL, NULL, + &gate->hw, &cclk_gate_ops, + flags); + + if (IS_ERR(hw)) { + kfree(gate); + kfree(mux); + } + +fail: + return hw; +} + static const char *sys_parents[] __initdata = { "hsi", NULL, "pll" }; static const struct clk_div_table ahb_div_table[] = { @@ -407,6 +521,10 @@ static const struct clk_div_table apb_div_table[] = { { 0 }, }; +static const char *rtc_parents[4] = { + "no-clock", "lse", "lsi", "hse-rtc" +}; + static void __init stm32f4_rcc_init(struct device_node *np) { const char *hse_clk; @@ -492,6 +610,23 @@ static void __init stm32f4_rcc_init(struct device_node *np) goto fail; } + clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse", + 0, base + STM32F4_RCC_CFGR, 16, 5, 0, + &stm32f4_clk_lock); + + if (IS_ERR(clks[CLK_HSE_RTC])) { + pr_err("Unable to register hse-rtc clock\n"); + goto fail; + } + + clks[CLK_RTC] = stm32_register_cclk(NULL, "rtc", rtc_parents, 4, + base + STM32F4_RCC_BDCR, 15, 8, 0, &stm32f4_clk_lock); + + if (IS_ERR(clks[CLK_RTC])) { + pr_err("Unable to register rtc clock\n"); + goto fail; + } + of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL); return; fail: -- cgit v1.2.3 From a064a07f72e92cae31cb09c5734ec3c4edd52f47 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Fri, 21 Oct 2016 11:23:30 +0200 Subject: clk: stm32f469: Add QSPI clock This patch adds the QSPI clock for stm32f469 discovery board. The gate mapping is a little bit different from stm32f429 soc. Signed-off-by: Gabriel Fernandez Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/st,stm32-rcc.txt | 4 +- drivers/clk/clk-stm32f4.c | 173 ++++++++++++++++++--- 2 files changed, 158 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt index c209de6cfadb..0532d815dae3 100644 --- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt +++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt @@ -7,7 +7,9 @@ Please refer to clock-bindings.txt for common clock controller binding usage. Please also refer to reset.txt for common reset controller binding usage. Required properties: -- compatible: Should be "st,stm32f42xx-rcc" +- compatible: Should be: + "st,stm32f42xx-rcc" + "st,stm32f469-rcc" - reg: should be register base and length as documented in the datasheet - #reset-cells: 1, see below diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index cbc814868508..5eb05dbf59b8 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -46,7 +46,7 @@ struct stm32f4_gate_data { unsigned long flags; }; -static const struct stm32f4_gate_data stm32f4_gates[] __initconst = { +static const struct stm32f4_gate_data stm32f429_gates[] __initconst = { { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" }, { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" }, { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" }, @@ -126,22 +126,108 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = { { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, }; +static const struct stm32f4_gate_data stm32f469_gates[] __initconst = { + { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 20, "ccmdatam", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" }, + { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" }, + + { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" }, + { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" }, + { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" }, + { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" }, + { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" }, + + { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div", + CLK_IGNORE_UNUSED }, + { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div", + CLK_IGNORE_UNUSED }, + + { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" }, + { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 17, "uart2", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 18, "uart3", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 19, "uart4", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 20, "uart5", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 21, "i2c1", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 22, "i2c2", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 23, "i2c3", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 30, "uart7", "apb1_div" }, + { STM32F4_RCC_APB1ENR, 31, "uart8", "apb1_div" }, + + { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" }, + { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" }, + { STM32F4_RCC_APB2ENR, 4, "usart1", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 5, "usart6", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 11, "sdio", "pll48" }, + { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" }, + { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" }, + { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" }, + { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, +}; + enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK }; -/* - * MAX_CLKS is the maximum value in the enumeration below plus the combined - * hweight of stm32f42xx_gate_map (plus one). - */ -#define MAX_CLKS (71 + END_PRIMARY_CLK + 1) /* * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx * have gate bits associated with them. Its combined hweight is 71. */ -static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull, - 0x0000000000000001ull, - 0x04777f33f6fec9ffull }; +#define MAX_GATE_MAP 3 + +static const u64 stm32f42xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull, + 0x0000000000000001ull, + 0x04777f33f6fec9ffull }; + +static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull, + 0x0000000000000003ull, + 0x0c777f33f6fec9ffull }; + +static const u64 *stm32f4_gate_map; + +static struct clk_hw **clks; -static struct clk_hw *clks[MAX_CLKS]; static DEFINE_SPINLOCK(stm32f4_clk_lock); static void __iomem *base; @@ -263,7 +349,7 @@ static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk) */ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) { - u64 table[ARRAY_SIZE(stm32f42xx_gate_map)]; + u64 table[MAX_GATE_MAP]; if (primary == 1) { if (WARN_ON(secondary >= END_PRIMARY_CLK)) @@ -271,7 +357,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) return secondary; } - memcpy(table, stm32f42xx_gate_map, sizeof(table)); + memcpy(table, stm32f4_gate_map, sizeof(table)); /* only bits set in table can be used as indices */ if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) || @@ -525,10 +611,42 @@ static const char *rtc_parents[4] = { "no-clock", "lse", "lsi", "hse-rtc" }; +struct stm32f4_clk_data { + const struct stm32f4_gate_data *gates_data; + const u64 *gates_map; + int gates_num; +}; + +static const struct stm32f4_clk_data stm32f429_clk_data = { + .gates_data = stm32f429_gates, + .gates_map = stm32f42xx_gate_map, + .gates_num = ARRAY_SIZE(stm32f429_gates), +}; + +static const struct stm32f4_clk_data stm32f469_clk_data = { + .gates_data = stm32f469_gates, + .gates_map = stm32f46xx_gate_map, + .gates_num = ARRAY_SIZE(stm32f469_gates), +}; + +static const struct of_device_id stm32f4_of_match[] = { + { + .compatible = "st,stm32f42xx-rcc", + .data = &stm32f429_clk_data + }, + { + .compatible = "st,stm32f469-rcc", + .data = &stm32f469_clk_data + }, + {} +}; + static void __init stm32f4_rcc_init(struct device_node *np) { const char *hse_clk; int n; + const struct of_device_id *match; + const struct stm32f4_clk_data *data; base = of_iomap(np, 0); if (!base) { @@ -542,6 +660,19 @@ static void __init stm32f4_rcc_init(struct device_node *np) pr_warn("%s: Unable to get syscfg\n", __func__); } + match = of_match_node(stm32f4_of_match, np); + if (WARN_ON(!match)) + return; + + data = match->data; + + clks = kmalloc_array(data->gates_num + END_PRIMARY_CLK, + sizeof(*clks), GFP_KERNEL); + if (!clks) + goto fail; + + stm32f4_gate_map = data->gates_map; + hse_clk = of_clk_get_parent_name(np, 0); clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0, @@ -574,11 +705,15 @@ static void __init stm32f4_rcc_init(struct device_node *np) clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div", 0, 1, 1); - for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) { - const struct stm32f4_gate_data *gd = &stm32f4_gates[n]; - unsigned int secondary = - 8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx; - int idx = stm32f4_rcc_lookup_clk_idx(0, secondary); + for (n = 0; n < data->gates_num; n++) { + const struct stm32f4_gate_data *gd; + unsigned int secondary; + int idx; + + gd = &data->gates_data[n]; + secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) + + gd->bit_idx; + idx = stm32f4_rcc_lookup_clk_idx(0, secondary); if (idx < 0) goto fail; @@ -630,6 +765,8 @@ static void __init stm32f4_rcc_init(struct device_node *np) of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL); return; fail: + kfree(clks); iounmap(base); } -CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init); +CLK_OF_DECLARE(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init); +CLK_OF_DECLARE(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init); -- cgit v1.2.3 From 4bdb35506b89cbbd150c1baa284e7c191698241f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 10 Oct 2016 14:37:56 +0200 Subject: driver core: Add a wrapper around __device_release_driver() Add an internal wrapper around __device_release_driver() that will acquire device locks and do the necessary checks before calling it. The next patch will make use of it. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index d22a7260f42b..df4ab5509c04 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -811,6 +811,22 @@ static void __device_release_driver(struct device *dev) } } +static void device_release_driver_internal(struct device *dev, + struct device_driver *drv, + struct device *parent) +{ + if (parent) + device_lock(parent); + + device_lock(dev); + if (!drv || drv == dev->driver) + __device_release_driver(dev); + + device_unlock(dev); + if (parent) + device_unlock(parent); +} + /** * device_release_driver - manually detach device from driver. * @dev: device. @@ -825,9 +841,7 @@ void device_release_driver(struct device *dev) * within their ->remove callback for the same device, they * will deadlock right here. */ - device_lock(dev); - __device_release_driver(dev); - device_unlock(dev); + device_release_driver_internal(dev, NULL, NULL); } EXPORT_SYMBOL_GPL(device_release_driver); @@ -852,15 +866,7 @@ void driver_detach(struct device_driver *drv) dev = dev_prv->device; get_device(dev); spin_unlock(&drv->p->klist_devices.k_lock); - - if (dev->parent) /* Needed for USB */ - device_lock(dev->parent); - device_lock(dev); - if (dev->driver == drv) - __device_release_driver(dev); - device_unlock(dev); - if (dev->parent) - device_unlock(dev->parent); + device_release_driver_internal(dev, drv, dev->parent); put_device(dev); } } -- cgit v1.2.3 From 463e2a2b8996aabc0dca67cc716a00e30bffc110 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Oct 2016 02:47:35 -0400 Subject: serial: fsl_lpuart: remove build warning commit 2a41bc2a2b05 ("tty: serial: fsl_lpuart: add polled console functions") caused a build warning about an unused variable, so fix it. Reported-by: kbuild test robot Cc: Nicolae Rosia Cc: Stefan Golinschi Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 49d7526e2587..23f09f2a14f7 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -473,8 +473,6 @@ static int lpuart_poll_init(struct uart_port *port) static void lpuart_poll_put_char(struct uart_port *port, unsigned char c) { - unsigned int status; - /* drain */ while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE)) barrier(); -- cgit v1.2.3 From 5303e6578f4a57e3be13a60825d3ae9f0d18af36 Mon Sep 17 00:00:00 2001 From: Jan Höppner Date: Thu, 30 Jun 2016 12:58:51 +0200 Subject: s390/dasd: Make setting queue_max_segments more explicit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the block queue value max_segments is set to -1L, which is then implicitly casted to unsigned short in blk_queue_max_segments. This results in 65535 (64k) max_segments. Even though the resulting value is correct, setting it implicitly using -1L is rather confusing. Set the value explicitly using the USHRT_MAX macro instead. Reviewed-by: Stefan Haberland Signed-off-by: Jan Höppner Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 1de089019268..6a0c9df8f323 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3140,7 +3140,7 @@ static void dasd_setup_queue(struct dasd_block *block) blk_queue_logical_block_size(block->request_queue, block->bp_block); blk_queue_max_hw_sectors(block->request_queue, max); - blk_queue_max_segments(block->request_queue, -1L); + blk_queue_max_segments(block->request_queue, USHRT_MAX); /* with page sized segments we can translate each segement into * one idaw/tidaw */ -- cgit v1.2.3 From 62ba6f85ee3f3e5c908af0ff7d6e0ae1cd399b85 Mon Sep 17 00:00:00 2001 From: Jan Höppner Date: Thu, 30 Jun 2016 13:18:16 +0200 Subject: s390/dasd: Define often used variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit block->request_queue is used many times in dasd_setup_queue. Define a separate variable to increase readability a bit and to make it better reusable. Reviewed-by: Stefan Haberland Signed-off-by: Jan Höppner Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 6a0c9df8f323..a4388f59c39f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3121,6 +3121,7 @@ static int dasd_alloc_queue(struct dasd_block *block) */ static void dasd_setup_queue(struct dasd_block *block) { + struct request_queue *q = block->request_queue; int max; if (block->base->features & DASD_FEATURE_USERAW) { @@ -3135,17 +3136,16 @@ static void dasd_setup_queue(struct dasd_block *block) } else { max = block->base->discipline->max_blocks << block->s2b_shift; } - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, block->request_queue); - block->request_queue->limits.max_dev_sectors = max; - blk_queue_logical_block_size(block->request_queue, - block->bp_block); - blk_queue_max_hw_sectors(block->request_queue, max); - blk_queue_max_segments(block->request_queue, USHRT_MAX); + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); + q->limits.max_dev_sectors = max; + blk_queue_logical_block_size(q, block->bp_block); + blk_queue_max_hw_sectors(q, max); + blk_queue_max_segments(q, USHRT_MAX); /* with page sized segments we can translate each segement into * one idaw/tidaw */ - blk_queue_max_segment_size(block->request_queue, PAGE_SIZE); - blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1); + blk_queue_max_segment_size(q, PAGE_SIZE); + blk_queue_segment_boundary(q, PAGE_SIZE - 1); } /* -- cgit v1.2.3 From 8139d8526c3c925ef73fe61cde7904cecf4e440d Mon Sep 17 00:00:00 2001 From: Dong Jia Shi Date: Thu, 20 Oct 2016 03:29:47 +0200 Subject: s390/cio: clean up DEV_STATE_SENSE_PGID Clean up DEV_STATE_SENSE_PGID related code, since it's not used anymore. Everything related to path verification is handled within DEV_STATE_VERIFY. Signed-off-by: Dong Jia Shi Acked-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.h | 1 - drivers/s390/cio/device_fsm.c | 6 ------ 2 files changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 065b1be98e2c..ec497af99dd8 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -13,7 +13,6 @@ */ enum dev_state { DEV_STATE_NOT_OPER, - DEV_STATE_SENSE_PGID, DEV_STATE_SENSE_ID, DEV_STATE_OFFLINE, DEV_STATE_VERIFY, diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8327d47e08b6..9afb5ce13007 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -1058,12 +1058,6 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { [DEV_EVENT_TIMEOUT] = ccw_device_nop, [DEV_EVENT_VERIFY] = ccw_device_nop, }, - [DEV_STATE_SENSE_PGID] = { - [DEV_EVENT_NOTOPER] = ccw_device_request_event, - [DEV_EVENT_INTERRUPT] = ccw_device_request_event, - [DEV_EVENT_TIMEOUT] = ccw_device_request_event, - [DEV_EVENT_VERIFY] = ccw_device_nop, - }, [DEV_STATE_SENSE_ID] = { [DEV_EVENT_NOTOPER] = ccw_device_request_event, [DEV_EVENT_INTERRUPT] = ccw_device_request_event, -- cgit v1.2.3 From ce7a788f4d5aba3361572067c7ac7c4e85d4a070 Mon Sep 17 00:00:00 2001 From: Jan Höppner Date: Mon, 10 Oct 2016 18:29:48 +0200 Subject: s390/dasd: Replace simple_strtoul with kstrtouint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit simple_strtoul() has been marked obsolete for quite some time now. Replace a few last occurrences with kstrtouint(). Reviewed-by: Stefan Haberland Signed-off-by: Jan Höppner Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_devmap.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 15a1a70cace9..6da7083decba 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -726,15 +726,13 @@ static ssize_t dasd_ff_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dasd_devmap *devmap; - int val; - char *endp; + unsigned int val; devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); if (IS_ERR(devmap)) return PTR_ERR(devmap); - val = simple_strtoul(buf, &endp, 0); - if (((endp + 1) < (buf + count)) || (val > 1)) + if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; spin_lock(&dasd_devmap_lock); @@ -773,15 +771,13 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, { struct dasd_devmap *devmap; struct dasd_device *device; - int val; - char *endp; + unsigned int val; devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); if (IS_ERR(devmap)) return PTR_ERR(devmap); - val = simple_strtoul(buf, &endp, 0); - if (((endp + 1) < (buf + count)) || (val > 1)) + if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; spin_lock(&dasd_devmap_lock); @@ -824,15 +820,13 @@ dasd_erplog_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dasd_devmap *devmap; - int val; - char *endp; + unsigned int val; devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); if (IS_ERR(devmap)) return PTR_ERR(devmap); - val = simple_strtoul(buf, &endp, 0); - if (((endp + 1) < (buf + count)) || (val > 1)) + if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; spin_lock(&dasd_devmap_lock); @@ -871,16 +865,14 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dasd_devmap *devmap; + unsigned int val; ssize_t rc; - int val; - char *endp; devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); if (IS_ERR(devmap)) return PTR_ERR(devmap); - val = simple_strtoul(buf, &endp, 0); - if (((endp + 1) < (buf + count)) || (val > 1)) + if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; spin_lock(&dasd_devmap_lock); @@ -1198,8 +1190,8 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dasd_devmap *devmap; - int val, rc; - char *endp; + unsigned int val; + int rc; devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); if (IS_ERR(devmap)) @@ -1207,8 +1199,7 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr, if (!devmap->device) return -ENODEV; - val = simple_strtoul(buf, &endp, 0); - if (((endp + 1) < (buf + count)) || (val > 1)) + if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; if (val) { -- cgit v1.2.3 From 1081f3a70b74b90b6db60eb1ac6cc3c480d62d57 Mon Sep 17 00:00:00 2001 From: Jan Höppner Date: Fri, 7 Oct 2016 17:21:24 +0200 Subject: s390/dasd: Make use of dasd_set_feature() more often MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When setting certain attributes, we actually set the according feature flag. Do this by using dasd_set_feature() at a few occurrences and remove duplicate code. In dasd_set_feature() dasd_find_busid() is used to retrieve the devmap for the device in question. Combined with the change above, this would require the device to be set online at least once so that a devmap is being created. Change that by using dasd_devmap_from_cdev() instead, which uses dasd_find_busid() first and will create a devmap accordingly if there is none yet. Reviewed-by: Stefan Haberland Signed-off-by: Jan Höppner Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_devmap.c | 90 +++++++++++++--------------------------- 1 file changed, 29 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 6da7083decba..221d8c8e63d5 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -725,25 +725,15 @@ static ssize_t dasd_ff_show(struct device *dev, struct device_attribute *attr, static ssize_t dasd_ff_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct dasd_devmap *devmap; unsigned int val; - - devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); - if (IS_ERR(devmap)) - return PTR_ERR(devmap); + int rc; if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; - spin_lock(&dasd_devmap_lock); - if (val) - devmap->features |= DASD_FEATURE_FAILFAST; - else - devmap->features &= ~DASD_FEATURE_FAILFAST; - if (devmap->device) - devmap->device->features = devmap->features; - spin_unlock(&dasd_devmap_lock); - return count; + rc = dasd_set_feature(to_ccwdev(dev), DASD_FEATURE_FAILFAST, val); + + return rc ? : count; } static DEVICE_ATTR(failfast, 0644, dasd_ff_show, dasd_ff_store); @@ -769,30 +759,28 @@ static ssize_t dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct dasd_devmap *devmap; + struct ccw_device *cdev = to_ccwdev(dev); struct dasd_device *device; unsigned int val; - - devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); - if (IS_ERR(devmap)) - return PTR_ERR(devmap); + int rc; if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; - spin_lock(&dasd_devmap_lock); - if (val) - devmap->features |= DASD_FEATURE_READONLY; - else - devmap->features &= ~DASD_FEATURE_READONLY; - device = devmap->device; - if (device) { - device->features = devmap->features; - val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags); - } - spin_unlock(&dasd_devmap_lock); - if (device && device->block && device->block->gdp) + rc = dasd_set_feature(cdev, DASD_FEATURE_READONLY, val); + if (rc) + return rc; + + device = dasd_device_from_cdev(cdev); + if (IS_ERR(device)) + return PTR_ERR(device); + + val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags); + if (device->block && device->block->gdp) set_disk_ro(device->block->gdp, val); + + dasd_put_device(device); + return count; } @@ -819,25 +807,15 @@ static ssize_t dasd_erplog_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct dasd_devmap *devmap; unsigned int val; - - devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); - if (IS_ERR(devmap)) - return PTR_ERR(devmap); + int rc; if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; - spin_lock(&dasd_devmap_lock); - if (val) - devmap->features |= DASD_FEATURE_ERPLOG; - else - devmap->features &= ~DASD_FEATURE_ERPLOG; - if (devmap->device) - devmap->device->features = devmap->features; - spin_unlock(&dasd_devmap_lock); - return count; + rc = dasd_set_feature(to_ccwdev(dev), DASD_FEATURE_ERPLOG, val); + + return rc ? : count; } static DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store); @@ -1376,27 +1354,17 @@ static ssize_t dasd_reservation_policy_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct dasd_devmap *devmap; + struct ccw_device *cdev = to_ccwdev(dev); int rc; - devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); - if (IS_ERR(devmap)) - return PTR_ERR(devmap); - rc = 0; - spin_lock(&dasd_devmap_lock); if (sysfs_streq("ignore", buf)) - devmap->features &= ~DASD_FEATURE_FAILONSLCK; + rc = dasd_set_feature(cdev, DASD_FEATURE_FAILONSLCK, 0); else if (sysfs_streq("fail", buf)) - devmap->features |= DASD_FEATURE_FAILONSLCK; + rc = dasd_set_feature(cdev, DASD_FEATURE_FAILONSLCK, 1); else rc = -EINVAL; - if (devmap->device) - devmap->device->features = devmap->features; - spin_unlock(&dasd_devmap_lock); - if (rc) - return rc; - else - return count; + + return rc ? : count; } static DEVICE_ATTR(reservation_policy, 0644, @@ -1522,7 +1490,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag) { struct dasd_devmap *devmap; - devmap = dasd_find_busid(dev_name(&cdev->dev)); + devmap = dasd_devmap_from_cdev(cdev); if (IS_ERR(devmap)) return PTR_ERR(devmap); -- cgit v1.2.3 From 0f57c97f241b4fc18251fb2b1c499e9f71e93c78 Mon Sep 17 00:00:00 2001 From: Jan Höppner Date: Tue, 18 Oct 2016 17:54:49 +0200 Subject: s390/dasd: Eliminate race condition in dasd_generic_set_offline() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before we set a device offline, the open_count for the block device is checked and certain flags are checked and set as well. However, this is all done without holding any lock. Potentially, if the open_count was checked but the DASD_FLAG_OFFLINE wasn't set yet, a different process might want to increase the open_count depending on whether DASD_FLAG_OFFLINE is set or not in the meanwhile. This is quite racy and can lead to the loss of the device for that process and subsequently lead to a panic. Fix this by checking the open_count and setting the offline flags while holding the ccwdev lock. Reviewed-by: Stefan Haberland Signed-off-by: Jan Höppner Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index a4388f59c39f..e21465ecb60f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3517,11 +3517,15 @@ int dasd_generic_set_offline(struct ccw_device *cdev) struct dasd_device *device; struct dasd_block *block; int max_count, open_count, rc; + unsigned long flags; rc = 0; - device = dasd_device_from_cdev(cdev); - if (IS_ERR(device)) + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + device = dasd_device_from_cdev_locked(cdev); + if (IS_ERR(device)) { + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); return PTR_ERR(device); + } /* * We must make sure that this device is currently not in use. @@ -3540,8 +3544,7 @@ int dasd_generic_set_offline(struct ccw_device *cdev) pr_warn("%s: The DASD cannot be set offline while it is in use\n", dev_name(&cdev->dev)); clear_bit(DASD_FLAG_OFFLINE, &device->flags); - dasd_put_device(device); - return -EBUSY; + goto out_busy; } } @@ -3551,19 +3554,19 @@ int dasd_generic_set_offline(struct ccw_device *cdev) * could only be called by normal offline so safe_offline flag * needs to be removed to run normal offline and kill all I/O */ - if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags)) { + if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags)) /* Already doing normal offline processing */ - dasd_put_device(device); - return -EBUSY; - } else + goto out_busy; + else clear_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags); - - } else - if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) { + } else { + if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) /* Already doing offline processing */ - dasd_put_device(device); - return -EBUSY; - } + goto out_busy; + } + + set_bit(DASD_FLAG_OFFLINE, &device->flags); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); /* * if safe_offline called set safe_offline_running flag and @@ -3591,7 +3594,6 @@ int dasd_generic_set_offline(struct ccw_device *cdev) goto interrupted; } - set_bit(DASD_FLAG_OFFLINE, &device->flags); dasd_set_target_state(device, DASD_STATE_NEW); /* dasd_delete_device destroys the device reference. */ block = device->block; @@ -3610,7 +3612,14 @@ interrupted: clear_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags); clear_bit(DASD_FLAG_OFFLINE, &device->flags); dasd_put_device(device); + return rc; + +out_busy: + dasd_put_device(device); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + + return -EBUSY; } EXPORT_SYMBOL_GPL(dasd_generic_set_offline); -- cgit v1.2.3 From 9de67725c80cb8a7b34b1932e196d2ed61a08879 Mon Sep 17 00:00:00 2001 From: Jan Höppner Date: Wed, 12 Oct 2016 12:51:04 +0200 Subject: s390/dasd: Fix locking issue when changing EER attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reference to a device in question may get lost when the extended error reporting (EER) attribute is being enabled/disabled while the device is set offline at the same time. This is due to missing refcounting and incorrect locking. Fix this by the following: - In dasd_eer_store() get the device directly and handle the refcount accordingly. - Move the lock in dasd_eer_enable() up so we can ensure safe processing. - Check if the device is being set offline and return with -EBUSY if so. - While at it, change the return code from -EPERM to -EMEDIUMTYPE as suggested by a FIXME, since that is what we're actually checking. Reviewed-by: Stefan Haberland Signed-off-by: Jan Höppner Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_devmap.c | 27 +++++++++++++-------------- drivers/s390/block/dasd_eer.c | 29 +++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 221d8c8e63d5..c1979ecce821 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -1167,26 +1167,25 @@ static ssize_t dasd_eer_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct dasd_devmap *devmap; + struct dasd_device *device; unsigned int val; - int rc; + int rc = 0; - devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); - if (IS_ERR(devmap)) - return PTR_ERR(devmap); - if (!devmap->device) - return -ENODEV; + device = dasd_device_from_cdev(to_ccwdev(dev)); + if (IS_ERR(device)) + return PTR_ERR(device); if (kstrtouint(buf, 0, &val) || val > 1) return -EINVAL; - if (val) { - rc = dasd_eer_enable(devmap->device); - if (rc) - return rc; - } else - dasd_eer_disable(devmap->device); - return count; + if (val) + rc = dasd_eer_enable(device); + else + dasd_eer_disable(device); + + dasd_put_device(device); + + return rc ? : count; } static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 21ef63cf0960..6c5d671304b4 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -454,20 +454,30 @@ static void dasd_eer_snss_cb(struct dasd_ccw_req *cqr, void *data) */ int dasd_eer_enable(struct dasd_device *device) { - struct dasd_ccw_req *cqr; + struct dasd_ccw_req *cqr = NULL; unsigned long flags; struct ccw1 *ccw; + int rc = 0; + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); if (device->eer_cqr) - return 0; + goto out; + else if (!device->discipline || + strcmp(device->discipline->name, "ECKD")) + rc = -EMEDIUMTYPE; + else if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) + rc = -EBUSY; - if (!device->discipline || strcmp(device->discipline->name, "ECKD")) - return -EPERM; /* FIXME: -EMEDIUMTYPE ? */ + if (rc) + goto out; cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 /* SNSS */, SNSS_DATA_SIZE, device); - if (IS_ERR(cqr)) - return -ENOMEM; + if (IS_ERR(cqr)) { + rc = -ENOMEM; + cqr = NULL; + goto out; + } cqr->startdev = device; cqr->retries = 255; @@ -485,15 +495,18 @@ int dasd_eer_enable(struct dasd_device *device) cqr->status = DASD_CQR_FILLED; cqr->callback = dasd_eer_snss_cb; - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); if (!device->eer_cqr) { device->eer_cqr = cqr; cqr = NULL; } + +out: spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + if (cqr) dasd_kfree_request(cqr, device); - return 0; + + return rc; } /* -- cgit v1.2.3 From 9f9d53e5bdb4362a73b801176cae49e77bea41fb Mon Sep 17 00:00:00 2001 From: Jan Höppner Date: Thu, 13 Oct 2016 13:31:39 +0200 Subject: s390/dasd: Fix locking issue when changing RO attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function dasd_ro_store() calls set_disk_ro() to set the device in question read-only. Since set_disk_ro() might sleep, we can't call it while holding a lock. However, we also can't simply check if the device, block, and gdp references are valid before we call set_disk_ro() because an offline processing might have been started in the meanwhile which will destroy those references. In order to reliably call set_disk_ro() we have to ensure several things: - Still check validity of the mentioned references but additionally check if offline processing is running and bail out accordingly. Also, do this while holding the device lock. - To ensure that the block device is still safe after the lock, increase the open_count while still holding the device lock. Reviewed-by: Stefan Haberland Signed-off-by: Jan Höppner Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_devmap.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index c1979ecce821..cbae6ab448b8 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -761,6 +761,7 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, { struct ccw_device *cdev = to_ccwdev(dev); struct dasd_device *device; + unsigned long flags; unsigned int val; int rc; @@ -775,10 +776,22 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, if (IS_ERR(device)) return PTR_ERR(device); + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags); - if (device->block && device->block->gdp) - set_disk_ro(device->block->gdp, val); + if (!device->block || !device->block->gdp || + test_bit(DASD_FLAG_OFFLINE, &device->flags)) { + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + goto out; + } + /* Increase open_count to avoid losing the block device */ + atomic_inc(&device->block->open_count); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + + set_disk_ro(device->block->gdp, val); + atomic_dec(&device->block->open_count); + +out: dasd_put_device(device); return count; -- cgit v1.2.3 From 01c3faa70bcde3519f0dba08e6218806bca03435 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 6 Oct 2016 19:22:14 +0300 Subject: drm/i915: Rename struct i915_power_well field data to id Calling it data seems to imply arbitrary data can be associated with the power well. However, that field is used for look ups and expected to be unique, so rename it. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/f3916c3c5bfa793b0fc870fd44007a3ff425194d.1475770848.git-series.ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 112 ++++++++++++++++---------------- 2 files changed, 58 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 55afb664b2f8..61449fab1f11 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1322,7 +1322,8 @@ struct i915_power_well { /* cached hw enabled state */ bool hw_enabled; unsigned long domains; - unsigned long data; + /* unique identifier for this power well */ + unsigned long id; const struct i915_power_well_ops *ops; }; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 82edba2f3589..53ba45a74163 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -330,7 +330,7 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, * sure vgacon can keep working normally without triggering interrupts * and error messages. */ - if (power_well->data == SKL_DISP_PW_2) { + if (power_well->id == SKL_DISP_PW_2) { vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); vga_put(pdev, VGA_RSRC_LEGACY_IO); @@ -343,7 +343,7 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, static void skl_power_well_pre_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - if (power_well->data == SKL_DISP_PW_2) + if (power_well->id == SKL_DISP_PW_2) gen8_irq_power_well_pre_disable(dev_priv, 1 << PIPE_C | 1 << PIPE_B); } @@ -658,7 +658,7 @@ static void gen9_sanitize_power_well_requests(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum skl_disp_power_wells power_well_id = power_well->data; + enum skl_disp_power_wells power_well_id = power_well->id; u32 val; u32 mask; @@ -703,7 +703,7 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, tmp = I915_READ(HSW_PWR_WELL_DRIVER); fuse_status = I915_READ(SKL_FUSE_STATUS); - switch (power_well->data) { + switch (power_well->id) { case SKL_DISP_PW_1: if (intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, @@ -727,13 +727,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, case SKL_DISP_PW_MISC_IO: break; default: - WARN(1, "Unknown power well %lu\n", power_well->data); + WARN(1, "Unknown power well %lu\n", power_well->id); return; } - req_mask = SKL_POWER_WELL_REQ(power_well->data); + req_mask = SKL_POWER_WELL_REQ(power_well->id); enable_requested = tmp & req_mask; - state_mask = SKL_POWER_WELL_STATE(power_well->data); + state_mask = SKL_POWER_WELL_STATE(power_well->id); is_enabled = tmp & state_mask; if (!enable && enable_requested) @@ -769,14 +769,14 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, power_well->name, enable ? "enable" : "disable"); if (check_fuse_status) { - if (power_well->data == SKL_DISP_PW_1) { + if (power_well->id == SKL_DISP_PW_1) { if (intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, SKL_FUSE_PG1_DIST_STATUS, SKL_FUSE_PG1_DIST_STATUS, 1)) DRM_ERROR("PG1 distributing status timeout\n"); - } else if (power_well->data == SKL_DISP_PW_2) { + } else if (power_well->id == SKL_DISP_PW_2) { if (intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, SKL_FUSE_PG2_DIST_STATUS, @@ -818,8 +818,8 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv, static bool skl_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - uint32_t mask = SKL_POWER_WELL_REQ(power_well->data) | - SKL_POWER_WELL_STATE(power_well->data); + uint32_t mask = SKL_POWER_WELL_REQ(power_well->id) | + SKL_POWER_WELL_STATE(power_well->id); return (I915_READ(HSW_PWR_WELL_DRIVER) & mask) == mask; } @@ -847,7 +847,7 @@ static void skl_power_well_disable(struct drm_i915_private *dev_priv, static enum dpio_phy bxt_power_well_to_phy(struct i915_power_well *power_well) { - enum skl_disp_power_wells power_well_id = power_well->data; + enum skl_disp_power_wells power_well_id = power_well->id; return power_well_id == BXT_DPIO_CMN_A ? DPIO_PHY1 : DPIO_PHY0; } @@ -855,7 +855,7 @@ static enum dpio_phy bxt_power_well_to_phy(struct i915_power_well *power_well) static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum skl_disp_power_wells power_well_id = power_well->data; + enum skl_disp_power_wells power_well_id = power_well->id; struct i915_power_well *cmn_a_well = NULL; if (power_well_id == BXT_DPIO_CMN_BC) { @@ -975,7 +975,7 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv, static void vlv_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { - enum punit_power_well power_well_id = power_well->data; + enum punit_power_well power_well_id = power_well->id; u32 mask; u32 state; u32 ctrl; @@ -1029,7 +1029,7 @@ static void vlv_power_well_disable(struct drm_i915_private *dev_priv, static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - int power_well_id = power_well->data; + int power_well_id = power_well->id; bool enabled = false; u32 mask; u32 state; @@ -1144,7 +1144,7 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv) static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D); + WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D); vlv_set_power_well(dev_priv, power_well, true); @@ -1154,7 +1154,7 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv, static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D); + WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D); vlv_display_power_well_deinit(dev_priv); @@ -1164,7 +1164,7 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC); + WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC); /* since ref/cri clock was enabled */ udelay(1); /* >10ns for cmnreset, >0ns for sidereset */ @@ -1190,7 +1190,7 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, { enum pipe pipe; - WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC); + WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC); for_each_pipe(dev_priv, pipe) assert_pll_disabled(dev_priv, pipe); @@ -1213,7 +1213,7 @@ static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_pr struct i915_power_well *power_well; power_well = &power_domains->power_wells[i]; - if (power_well->data == power_well_id) + if (power_well->id == power_well_id) return power_well; } @@ -1337,10 +1337,10 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, enum pipe pipe; uint32_t tmp; - WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC && - power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D); + WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC && + power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D); - if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { + if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) { pipe = PIPE_A; phy = DPIO_PHY0; } else { @@ -1368,7 +1368,7 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, DPIO_SUS_CLK_CONFIG_GATE_CLKREQ; vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp); - if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { + if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) { tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1); tmp |= DPIO_DYNPWRDOWNEN_CH1; vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp); @@ -1399,10 +1399,10 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, { enum dpio_phy phy; - WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC && - power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D); + WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC && + power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D); - if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { + if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) { phy = DPIO_PHY0; assert_pll_disabled(dev_priv, PIPE_A); assert_pll_disabled(dev_priv, PIPE_B); @@ -1551,7 +1551,7 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum pipe pipe = power_well->data; + enum pipe pipe = power_well->id; bool enabled; u32 state, ctrl; @@ -1581,7 +1581,7 @@ static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { - enum pipe pipe = power_well->data; + enum pipe pipe = power_well->id; u32 state; u32 ctrl; @@ -1614,7 +1614,7 @@ out: static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - WARN_ON_ONCE(power_well->data != PIPE_A); + WARN_ON_ONCE(power_well->id != PIPE_A); chv_set_pipe_power_well(dev_priv, power_well, power_well->count > 0); } @@ -1622,7 +1622,7 @@ static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv, static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - WARN_ON_ONCE(power_well->data != PIPE_A); + WARN_ON_ONCE(power_well->id != PIPE_A); chv_set_pipe_power_well(dev_priv, power_well, true); @@ -1632,7 +1632,7 @@ static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv, static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - WARN_ON_ONCE(power_well->data != PIPE_A); + WARN_ON_ONCE(power_well->id != PIPE_A); vlv_display_power_well_deinit(dev_priv); @@ -1976,12 +1976,12 @@ static struct i915_power_well vlv_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, - .data = PUNIT_POWER_WELL_ALWAYS_ON, + .id = PUNIT_POWER_WELL_ALWAYS_ON, }, { .name = "display", .domains = VLV_DISPLAY_POWER_DOMAINS, - .data = PUNIT_POWER_WELL_DISP2D, + .id = PUNIT_POWER_WELL_DISP2D, .ops = &vlv_display_power_well_ops, }, { @@ -1991,7 +1991,7 @@ static struct i915_power_well vlv_power_wells[] = { VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS | VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS, .ops = &vlv_dpio_power_well_ops, - .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01, + .id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01, }, { .name = "dpio-tx-b-23", @@ -2000,7 +2000,7 @@ static struct i915_power_well vlv_power_wells[] = { VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS | VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS, .ops = &vlv_dpio_power_well_ops, - .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23, + .id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23, }, { .name = "dpio-tx-c-01", @@ -2009,7 +2009,7 @@ static struct i915_power_well vlv_power_wells[] = { VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS | VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS, .ops = &vlv_dpio_power_well_ops, - .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01, + .id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01, }, { .name = "dpio-tx-c-23", @@ -2018,12 +2018,12 @@ static struct i915_power_well vlv_power_wells[] = { VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS | VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS, .ops = &vlv_dpio_power_well_ops, - .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23, + .id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23, }, { .name = "dpio-common", .domains = VLV_DPIO_CMN_BC_POWER_DOMAINS, - .data = PUNIT_POWER_WELL_DPIO_CMN_BC, + .id = PUNIT_POWER_WELL_DPIO_CMN_BC, .ops = &vlv_dpio_cmn_power_well_ops, }, }; @@ -2043,19 +2043,19 @@ static struct i915_power_well chv_power_wells[] = { * required for any pipe to work. */ .domains = CHV_DISPLAY_POWER_DOMAINS, - .data = PIPE_A, + .id = PIPE_A, .ops = &chv_pipe_power_well_ops, }, { .name = "dpio-common-bc", .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS, - .data = PUNIT_POWER_WELL_DPIO_CMN_BC, + .id = PUNIT_POWER_WELL_DPIO_CMN_BC, .ops = &chv_dpio_cmn_power_well_ops, }, { .name = "dpio-common-d", .domains = CHV_DPIO_CMN_D_POWER_DOMAINS, - .data = PUNIT_POWER_WELL_DPIO_CMN_D, + .id = PUNIT_POWER_WELL_DPIO_CMN_D, .ops = &chv_dpio_cmn_power_well_ops, }, }; @@ -2078,57 +2078,57 @@ static struct i915_power_well skl_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, - .data = SKL_DISP_PW_ALWAYS_ON, + .id = SKL_DISP_PW_ALWAYS_ON, }, { .name = "power well 1", /* Handled by the DMC firmware */ .domains = 0, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_1, + .id = SKL_DISP_PW_1, }, { .name = "MISC IO power well", /* Handled by the DMC firmware */ .domains = 0, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_MISC_IO, + .id = SKL_DISP_PW_MISC_IO, }, { .name = "DC off", .domains = SKL_DISPLAY_DC_OFF_POWER_DOMAINS, .ops = &gen9_dc_off_power_well_ops, - .data = SKL_DISP_PW_DC_OFF, + .id = SKL_DISP_PW_DC_OFF, }, { .name = "power well 2", .domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_2, + .id = SKL_DISP_PW_2, }, { .name = "DDI A/E power well", .domains = SKL_DISPLAY_DDI_A_E_POWER_DOMAINS, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_DDI_A_E, + .id = SKL_DISP_PW_DDI_A_E, }, { .name = "DDI B power well", .domains = SKL_DISPLAY_DDI_B_POWER_DOMAINS, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_DDI_B, + .id = SKL_DISP_PW_DDI_B, }, { .name = "DDI C power well", .domains = SKL_DISPLAY_DDI_C_POWER_DOMAINS, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_DDI_C, + .id = SKL_DISP_PW_DDI_C, }, { .name = "DDI D power well", .domains = SKL_DISPLAY_DDI_D_POWER_DOMAINS, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_DDI_D, + .id = SKL_DISP_PW_DDI_D, }, }; @@ -2143,31 +2143,31 @@ static struct i915_power_well bxt_power_wells[] = { .name = "power well 1", .domains = 0, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_1, + .id = SKL_DISP_PW_1, }, { .name = "DC off", .domains = BXT_DISPLAY_DC_OFF_POWER_DOMAINS, .ops = &gen9_dc_off_power_well_ops, - .data = SKL_DISP_PW_DC_OFF, + .id = SKL_DISP_PW_DC_OFF, }, { .name = "power well 2", .domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS, .ops = &skl_power_well_ops, - .data = SKL_DISP_PW_2, + .id = SKL_DISP_PW_2, }, { .name = "dpio-common-a", .domains = BXT_DPIO_CMN_A_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, - .data = BXT_DPIO_CMN_A, + .id = BXT_DPIO_CMN_A, }, { .name = "dpio-common-bc", .domains = BXT_DPIO_CMN_BC_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, - .data = BXT_DPIO_CMN_BC, + .id = BXT_DPIO_CMN_BC, }, }; -- cgit v1.2.3 From 362624c9ba3f6bff2df6304068a45b355d4ab13b Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 6 Oct 2016 19:22:15 +0300 Subject: drm/i915: Explicitly map broxton DPIO power wells to phys The mapping from the BXT_DPIO_CMN_* power wells to their respective phys required a detour implemented in the bxt_power_well_to_phy() function. Instead, embed that information directly into the power_well struct, by resurrecting the data field. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/7fe97582fa08c7340ce6a3b6b0ea3e72a73182d7.1475770848.git-series.ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 5 +++++ drivers/gpu/drm/i915/intel_runtime_pm.c | 22 +++++++--------------- 2 files changed, 12 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 61449fab1f11..d3249e9c198c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1324,6 +1324,11 @@ struct i915_power_well { unsigned long domains; /* unique identifier for this power well */ unsigned long id; + /* + * Arbitraty data associated with this power well. Platform and power + * well specific. + */ + unsigned long data; const struct i915_power_well_ops *ops; }; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 53ba45a74163..5fd76ee0f4ca 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -845,13 +845,6 @@ static void skl_power_well_disable(struct drm_i915_private *dev_priv, skl_set_power_well(dev_priv, power_well, false); } -static enum dpio_phy bxt_power_well_to_phy(struct i915_power_well *power_well) -{ - enum skl_disp_power_wells power_well_id = power_well->id; - - return power_well_id == BXT_DPIO_CMN_A ? DPIO_PHY1 : DPIO_PHY0; -} - static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -867,7 +860,7 @@ static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, intel_power_well_get(dev_priv, cmn_a_well); } - bxt_ddi_phy_init(dev_priv, bxt_power_well_to_phy(power_well)); + bxt_ddi_phy_init(dev_priv, power_well->data); if (cmn_a_well) intel_power_well_put(dev_priv, cmn_a_well); @@ -876,14 +869,13 @@ static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - bxt_ddi_phy_uninit(dev_priv, bxt_power_well_to_phy(power_well)); + bxt_ddi_phy_uninit(dev_priv, power_well->data); } static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - return bxt_ddi_phy_is_enabled(dev_priv, - bxt_power_well_to_phy(power_well)); + return bxt_ddi_phy_is_enabled(dev_priv, power_well->data); } static void bxt_dpio_cmn_power_well_sync_hw(struct drm_i915_private *dev_priv, @@ -902,13 +894,11 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A); if (power_well->count > 0) - bxt_ddi_phy_verify_state(dev_priv, - bxt_power_well_to_phy(power_well)); + bxt_ddi_phy_verify_state(dev_priv, power_well->data); power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC); if (power_well->count > 0) - bxt_ddi_phy_verify_state(dev_priv, - bxt_power_well_to_phy(power_well)); + bxt_ddi_phy_verify_state(dev_priv, power_well->data); } static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv, @@ -2162,12 +2152,14 @@ static struct i915_power_well bxt_power_wells[] = { .domains = BXT_DPIO_CMN_A_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, .id = BXT_DPIO_CMN_A, + .data = DPIO_PHY1, }, { .name = "dpio-common-bc", .domains = BXT_DPIO_CMN_BC_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, .id = BXT_DPIO_CMN_BC, + .data = DPIO_PHY0, }, }; -- cgit v1.2.3 From b284eedaf74bdbd262f71a7937ca78f45354173f Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 6 Oct 2016 19:22:16 +0300 Subject: drm/i915: Pass lane count to bxt_ddi_phy_calc_lane_optmin_mask() Pass lane count to bxt_ddi_phy_calc_lane_optmin_mask() instead of having it extract that number from a pipe_config to decouple the phy code from intel_crtc_state. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/a4977e0207e594953c4f9d1b5f2ef972a8679e74.1475770848.git-series.ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index fb18d699ce10..1de0276eecdd 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2190,9 +2190,9 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, static uint8_t bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + uint8_t lane_count) { - switch (pipe_config->lane_count) { + switch (lane_count) { case 1: return 0; case 2: @@ -2200,7 +2200,7 @@ bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, case 4: return BIT(3) | BIT(2) | BIT(0); default: - MISSING_CASE(pipe_config->lane_count); + MISSING_CASE(lane_count); return 0; } @@ -2417,7 +2417,7 @@ static bool intel_ddi_compute_config(struct intel_encoder *encoder, if (IS_BROXTON(dev_priv) && ret) pipe_config->lane_lat_optim_mask = bxt_ddi_phy_calc_lane_lat_optim_mask(encoder, - pipe_config); + pipe_config->lane_count); return ret; -- cgit v1.2.3 From 47a6bc61b86657646aea38e837a7f25c68cec7f8 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 6 Oct 2016 19:22:17 +0300 Subject: drm/i915: Move broxton phy code to intel_dpio_phy.c The phy in broxton is also a dpio phy, similar to cherryview but with programming through MMIO. So move the code together with the other similar phys. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/d611de6d256593cf904172db7ff27f164480c228.1475770848.git-series.ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 12 ++ drivers/gpu/drm/i915/intel_ddi.c | 322 +-------------------------------- drivers/gpu/drm/i915/intel_dpio_phy.c | 327 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 6 - 4 files changed, 341 insertions(+), 326 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d3249e9c198c..c642f1097b8c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3761,6 +3761,18 @@ u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); /* intel_dpio_phy.c */ +void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy); +void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy); +bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, + enum dpio_phy phy); +bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, + enum dpio_phy phy); +uint8_t bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, + uint8_t lane_count); +void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, + uint8_t lane_lat_optim_mask); +uint8_t bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder); + void chv_set_phy_signal_level(struct intel_encoder *encoder, u32 deemph_reg_value, u32 margin_reg_value, bool uniq_trans_scale); diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 1de0276eecdd..51ca8eae2c8f 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1923,332 +1923,14 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder, } } -bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, - enum dpio_phy phy) -{ - enum port port; - - if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy))) - return false; - - if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & - (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) { - DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n", - phy); - - return false; - } - - if (phy == DPIO_PHY1 && - !(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE)) { - DRM_DEBUG_DRIVER("DDI PHY 1 powered, but GRC isn't done\n"); - - return false; - } - - if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) { - DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n", - phy); - - return false; - } - - for_each_port_masked(port, - phy == DPIO_PHY0 ? BIT(PORT_B) | BIT(PORT_C) : - BIT(PORT_A)) { - u32 tmp = I915_READ(BXT_PHY_CTL(port)); - - if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) { - DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane " - "for port %c powered down " - "(PHY_CTL %08x)\n", - phy, port_name(port), tmp); - - return false; - } - } - - return true; -} - -static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy) -{ - u32 val = I915_READ(BXT_PORT_REF_DW6(phy)); - - return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; -} - -static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, - enum dpio_phy phy) -{ - if (intel_wait_for_register(dev_priv, - BXT_PORT_REF_DW3(phy), - GRC_DONE, GRC_DONE, - 10)) - DRM_ERROR("timeout waiting for PHY%d GRC\n", phy); -} - -void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) -{ - u32 val; - - if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { - /* Still read out the GRC value for state verification */ - if (phy == DPIO_PHY0) - dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy); - - if (bxt_ddi_phy_verify_state(dev_priv, phy)) { - DRM_DEBUG_DRIVER("DDI PHY %d already enabled, " - "won't reprogram it\n", phy); - - return; - } - - DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, " - "force reprogramming it\n", phy); - } - - val = I915_READ(BXT_P_CR_GT_DISP_PWRON); - val |= GT_DISPLAY_POWER_ON(phy); - I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); - - /* - * The PHY registers start out inaccessible and respond to reads with - * all 1s. Eventually they become accessible as they power up, then - * the reserved bit will give the default 0. Poll on the reserved bit - * becoming 0 to find when the PHY is accessible. - * HW team confirmed that the time to reach phypowergood status is - * anywhere between 50 us and 100us. - */ - if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & - (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) { - DRM_ERROR("timeout during PHY%d power on\n", phy); - } - - /* Program PLL Rcomp code offset */ - val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); - val &= ~IREF0RC_OFFSET_MASK; - val |= 0xE4 << IREF0RC_OFFSET_SHIFT; - I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val); - - val = I915_READ(BXT_PORT_CL1CM_DW10(phy)); - val &= ~IREF1RC_OFFSET_MASK; - val |= 0xE4 << IREF1RC_OFFSET_SHIFT; - I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val); - - /* Program power gating */ - val = I915_READ(BXT_PORT_CL1CM_DW28(phy)); - val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | - SUS_CLK_CONFIG; - I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val); - - if (phy == DPIO_PHY0) { - val = I915_READ(BXT_PORT_CL2CM_DW6_BC); - val |= DW6_OLDO_DYN_PWR_DOWN_EN; - I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val); - } - - val = I915_READ(BXT_PORT_CL1CM_DW30(phy)); - val &= ~OCL2_LDOFUSE_PWR_DIS; - /* - * On PHY1 disable power on the second channel, since no port is - * connected there. On PHY0 both channels have a port, so leave it - * enabled. - * TODO: port C is only connected on BXT-P, so on BXT0/1 we should - * power down the second channel on PHY0 as well. - * - * FIXME: Clarify programming of the following, the register is - * read-only with bit 6 fixed at 0 at least in stepping A. - */ - if (phy == DPIO_PHY1) - val |= OCL2_LDOFUSE_PWR_DIS; - I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val); - - if (phy == DPIO_PHY0) { - uint32_t grc_code; - /* - * PHY0 isn't connected to an RCOMP resistor so copy over - * the corresponding calibrated value from PHY1, and disable - * the automatic calibration on PHY0. - */ - val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, DPIO_PHY1); - grc_code = val << GRC_CODE_FAST_SHIFT | - val << GRC_CODE_SLOW_SHIFT | - val; - I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code); - - val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0)); - val |= GRC_DIS | GRC_RDY_OVRD; - I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val); - } - - val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); - val |= COMMON_RESET_DIS; - I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); - - if (phy == DPIO_PHY1) - bxt_phy_wait_grc_done(dev_priv, DPIO_PHY1); -} - -void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) -{ - uint32_t val; - - val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); - val &= ~COMMON_RESET_DIS; - I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); - - val = I915_READ(BXT_P_CR_GT_DISP_PWRON); - val &= ~GT_DISPLAY_POWER_ON(phy); - I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); -} - -static bool __printf(6, 7) -__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, - i915_reg_t reg, u32 mask, u32 expected, - const char *reg_fmt, ...) -{ - struct va_format vaf; - va_list args; - u32 val; - - val = I915_READ(reg); - if ((val & mask) == expected) - return true; - - va_start(args, reg_fmt); - vaf.fmt = reg_fmt; - vaf.va = &args; - - DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: " - "current %08x, expected %08x (mask %08x)\n", - phy, &vaf, reg.reg, val, (val & ~mask) | expected, - mask); - - va_end(args); - - return false; -} - -bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, - enum dpio_phy phy) -{ - uint32_t mask; - bool ok; - -#define _CHK(reg, mask, exp, fmt, ...) \ - __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \ - ## __VA_ARGS__) - - if (!bxt_ddi_phy_is_enabled(dev_priv, phy)) - return false; - - ok = true; - - /* PLL Rcomp code offset */ - ok &= _CHK(BXT_PORT_CL1CM_DW9(phy), - IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT, - "BXT_PORT_CL1CM_DW9(%d)", phy); - ok &= _CHK(BXT_PORT_CL1CM_DW10(phy), - IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT, - "BXT_PORT_CL1CM_DW10(%d)", phy); - - /* Power gating */ - mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG; - ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask, - "BXT_PORT_CL1CM_DW28(%d)", phy); - - if (phy == DPIO_PHY0) - ok &= _CHK(BXT_PORT_CL2CM_DW6_BC, - DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN, - "BXT_PORT_CL2CM_DW6_BC"); - - /* - * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS, - * at least on stepping A this bit is read-only and fixed at 0. - */ - - if (phy == DPIO_PHY0) { - u32 grc_code = dev_priv->bxt_phy_grc; - - grc_code = grc_code << GRC_CODE_FAST_SHIFT | - grc_code << GRC_CODE_SLOW_SHIFT | - grc_code; - mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | - GRC_CODE_NOM_MASK; - ok &= _CHK(BXT_PORT_REF_DW6(DPIO_PHY0), mask, grc_code, - "BXT_PORT_REF_DW6(%d)", DPIO_PHY0); - - mask = GRC_DIS | GRC_RDY_OVRD; - ok &= _CHK(BXT_PORT_REF_DW8(DPIO_PHY0), mask, mask, - "BXT_PORT_REF_DW8(%d)", DPIO_PHY0); - } - - return ok; -#undef _CHK -} - -static uint8_t -bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, - uint8_t lane_count) -{ - switch (lane_count) { - case 1: - return 0; - case 2: - return BIT(2) | BIT(0); - case 4: - return BIT(3) | BIT(2) | BIT(0); - default: - MISSING_CASE(lane_count); - - return 0; - } -} - static void bxt_ddi_pre_pll_enable(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); - struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); - enum port port = dport->port; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int lane; - - for (lane = 0; lane < 4; lane++) { - u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); - - /* - * Note that on CHV this flag is called UPAR, but has - * the same function. - */ - val &= ~LATENCY_OPTIM; - if (intel_crtc->config->lane_lat_optim_mask & BIT(lane)) - val |= LATENCY_OPTIM; - - I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val); - } -} - -static uint8_t -bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) -{ - struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); - struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); - enum port port = dport->port; - int lane; - uint8_t mask; - - mask = 0; - for (lane = 0; lane < 4; lane++) { - u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); - - if (val & LATENCY_OPTIM) - mask |= BIT(lane); - } + uint8_t mask = intel_crtc->config->lane_lat_optim_mask; - return mask; + bxt_ddi_phy_set_lane_optim_mask(encoder, mask); } void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 047f48748944..edf0cfd860c4 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -23,6 +23,333 @@ #include "intel_drv.h" +bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, + enum dpio_phy phy) +{ + enum port port; + + if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy))) + return false; + + if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & + (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) { + DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n", + phy); + + return false; + } + + if (phy == DPIO_PHY1 && + !(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE)) { + DRM_DEBUG_DRIVER("DDI PHY 1 powered, but GRC isn't done\n"); + + return false; + } + + if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) { + DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n", + phy); + + return false; + } + + for_each_port_masked(port, + phy == DPIO_PHY0 ? BIT(PORT_B) | BIT(PORT_C) : + BIT(PORT_A)) { + u32 tmp = I915_READ(BXT_PHY_CTL(port)); + + if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) { + DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane " + "for port %c powered down " + "(PHY_CTL %08x)\n", + phy, port_name(port), tmp); + + return false; + } + } + + return true; +} + +static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy) +{ + u32 val = I915_READ(BXT_PORT_REF_DW6(phy)); + + return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; +} + +static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, + enum dpio_phy phy) +{ + if (intel_wait_for_register(dev_priv, + BXT_PORT_REF_DW3(phy), + GRC_DONE, GRC_DONE, + 10)) + DRM_ERROR("timeout waiting for PHY%d GRC\n", phy); +} + +void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) +{ + u32 val; + + if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { + /* Still read out the GRC value for state verification */ + if (phy == DPIO_PHY0) + dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy); + + if (bxt_ddi_phy_verify_state(dev_priv, phy)) { + DRM_DEBUG_DRIVER("DDI PHY %d already enabled, " + "won't reprogram it\n", phy); + + return; + } + + DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, " + "force reprogramming it\n", phy); + } + + val = I915_READ(BXT_P_CR_GT_DISP_PWRON); + val |= GT_DISPLAY_POWER_ON(phy); + I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); + + /* + * The PHY registers start out inaccessible and respond to reads with + * all 1s. Eventually they become accessible as they power up, then + * the reserved bit will give the default 0. Poll on the reserved bit + * becoming 0 to find when the PHY is accessible. + * HW team confirmed that the time to reach phypowergood status is + * anywhere between 50 us and 100us. + */ + if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & + (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) { + DRM_ERROR("timeout during PHY%d power on\n", phy); + } + + /* Program PLL Rcomp code offset */ + val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); + val &= ~IREF0RC_OFFSET_MASK; + val |= 0xE4 << IREF0RC_OFFSET_SHIFT; + I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val); + + val = I915_READ(BXT_PORT_CL1CM_DW10(phy)); + val &= ~IREF1RC_OFFSET_MASK; + val |= 0xE4 << IREF1RC_OFFSET_SHIFT; + I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val); + + /* Program power gating */ + val = I915_READ(BXT_PORT_CL1CM_DW28(phy)); + val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | + SUS_CLK_CONFIG; + I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val); + + if (phy == DPIO_PHY0) { + val = I915_READ(BXT_PORT_CL2CM_DW6_BC); + val |= DW6_OLDO_DYN_PWR_DOWN_EN; + I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val); + } + + val = I915_READ(BXT_PORT_CL1CM_DW30(phy)); + val &= ~OCL2_LDOFUSE_PWR_DIS; + /* + * On PHY1 disable power on the second channel, since no port is + * connected there. On PHY0 both channels have a port, so leave it + * enabled. + * TODO: port C is only connected on BXT-P, so on BXT0/1 we should + * power down the second channel on PHY0 as well. + * + * FIXME: Clarify programming of the following, the register is + * read-only with bit 6 fixed at 0 at least in stepping A. + */ + if (phy == DPIO_PHY1) + val |= OCL2_LDOFUSE_PWR_DIS; + I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val); + + if (phy == DPIO_PHY0) { + uint32_t grc_code; + /* + * PHY0 isn't connected to an RCOMP resistor so copy over + * the corresponding calibrated value from PHY1, and disable + * the automatic calibration on PHY0. + */ + val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, DPIO_PHY1); + grc_code = val << GRC_CODE_FAST_SHIFT | + val << GRC_CODE_SLOW_SHIFT | + val; + I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code); + + val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0)); + val |= GRC_DIS | GRC_RDY_OVRD; + I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val); + } + + val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); + val |= COMMON_RESET_DIS; + I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); + + if (phy == DPIO_PHY1) + bxt_phy_wait_grc_done(dev_priv, DPIO_PHY1); +} + +void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) +{ + uint32_t val; + + val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); + val &= ~COMMON_RESET_DIS; + I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); + + val = I915_READ(BXT_P_CR_GT_DISP_PWRON); + val &= ~GT_DISPLAY_POWER_ON(phy); + I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); +} + +static bool __printf(6, 7) +__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, + i915_reg_t reg, u32 mask, u32 expected, + const char *reg_fmt, ...) +{ + struct va_format vaf; + va_list args; + u32 val; + + val = I915_READ(reg); + if ((val & mask) == expected) + return true; + + va_start(args, reg_fmt); + vaf.fmt = reg_fmt; + vaf.va = &args; + + DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: " + "current %08x, expected %08x (mask %08x)\n", + phy, &vaf, reg.reg, val, (val & ~mask) | expected, + mask); + + va_end(args); + + return false; +} + +bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, + enum dpio_phy phy) +{ + uint32_t mask; + bool ok; + +#define _CHK(reg, mask, exp, fmt, ...) \ + __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \ + ## __VA_ARGS__) + + if (!bxt_ddi_phy_is_enabled(dev_priv, phy)) + return false; + + ok = true; + + /* PLL Rcomp code offset */ + ok &= _CHK(BXT_PORT_CL1CM_DW9(phy), + IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT, + "BXT_PORT_CL1CM_DW9(%d)", phy); + ok &= _CHK(BXT_PORT_CL1CM_DW10(phy), + IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT, + "BXT_PORT_CL1CM_DW10(%d)", phy); + + /* Power gating */ + mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG; + ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask, + "BXT_PORT_CL1CM_DW28(%d)", phy); + + if (phy == DPIO_PHY0) + ok &= _CHK(BXT_PORT_CL2CM_DW6_BC, + DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN, + "BXT_PORT_CL2CM_DW6_BC"); + + /* + * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS, + * at least on stepping A this bit is read-only and fixed at 0. + */ + + if (phy == DPIO_PHY0) { + u32 grc_code = dev_priv->bxt_phy_grc; + + grc_code = grc_code << GRC_CODE_FAST_SHIFT | + grc_code << GRC_CODE_SLOW_SHIFT | + grc_code; + mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | + GRC_CODE_NOM_MASK; + ok &= _CHK(BXT_PORT_REF_DW6(DPIO_PHY0), mask, grc_code, + "BXT_PORT_REF_DW6(%d)", DPIO_PHY0); + + mask = GRC_DIS | GRC_RDY_OVRD; + ok &= _CHK(BXT_PORT_REF_DW8(DPIO_PHY0), mask, mask, + "BXT_PORT_REF_DW8(%d)", DPIO_PHY0); + } + + return ok; +#undef _CHK +} + +uint8_t +bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, + uint8_t lane_count) +{ + switch (lane_count) { + case 1: + return 0; + case 2: + return BIT(2) | BIT(0); + case 4: + return BIT(3) | BIT(2) | BIT(0); + default: + MISSING_CASE(lane_count); + + return 0; + } +} + +void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, + uint8_t lane_lat_optim_mask) +{ + struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); + struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); + enum port port = dport->port; + int lane; + + for (lane = 0; lane < 4; lane++) { + u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); + + /* + * Note that on CHV this flag is called UPAR, but has + * the same function. + */ + val &= ~LATENCY_OPTIM; + if (lane_lat_optim_mask & BIT(lane)) + val |= LATENCY_OPTIM; + + I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val); + } +} + +uint8_t +bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) +{ + struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); + struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); + enum port port = dport->port; + int lane; + uint8_t mask; + + mask = 0; + for (lane = 0; lane < 4; lane++) { + u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); + + if (val & LATENCY_OPTIM) + mask |= BIT(lane); + } + + return mask; +} + + void chv_set_phy_signal_level(struct intel_encoder *encoder, u32 deemph_reg_value, u32 margin_reg_value, bool uniq_trans_scale) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c2f38634e86e..29ab5260f100 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1351,12 +1351,6 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv); void hsw_disable_pc8(struct drm_i915_private *dev_priv); void bxt_init_cdclk(struct drm_i915_private *dev_priv); void bxt_uninit_cdclk(struct drm_i915_private *dev_priv); -void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy); -void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy); -bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, - enum dpio_phy phy); -bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, - enum dpio_phy phy); void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv); void bxt_enable_dc9(struct drm_i915_private *dev_priv); void bxt_disable_dc9(struct drm_i915_private *dev_priv); -- cgit v1.2.3 From f38861b814b530fbf5add9fa845da99444ebbde0 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 6 Oct 2016 19:22:18 +0300 Subject: drm/i915: Move DPIO phy documentation section to intel_dpio_phy.c Move the DPIO phy documentation section to intel_dpio_phy.c, since that is a more suitable place now that there is a source file dedicated for those phys. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/55a2d38c15c06a8c5bce498b28decc03948f0224.1475770848.git-series.ander.conselvan.de.oliveira@intel.com --- Documentation/gpu/i915.rst | 2 +- drivers/gpu/drm/i915/i915_reg.h | 91 +---------------------------------- drivers/gpu/drm/i915/intel_dpio_phy.c | 91 +++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index 95ce77ff4342..ba83b7d88f1f 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -189,7 +189,7 @@ Display Refresh Rate Switching (DRRS) DPIO ---- -.. kernel-doc:: drivers/gpu/drm/i915/i915_reg.h +.. kernel-doc:: drivers/gpu/drm/i915/intel_dpio_phy.c :doc: DPIO CSR firmware support for DMC diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 542e570b3578..2f504f6a1c51 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -830,96 +830,7 @@ enum skl_disp_power_wells { #define CCK_FREQUENCY_STATUS_SHIFT 8 #define CCK_FREQUENCY_VALUES (0x1f << 0) -/** - * DOC: DPIO - * - * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI - * ports. DPIO is the name given to such a display PHY. These PHYs - * don't follow the standard programming model using direct MMIO - * registers, and instead their registers must be accessed trough IOSF - * sideband. VLV has one such PHY for driving ports B and C, and CHV - * adds another PHY for driving port D. Each PHY responds to specific - * IOSF-SB port. - * - * Each display PHY is made up of one or two channels. Each channel - * houses a common lane part which contains the PLL and other common - * logic. CH0 common lane also contains the IOSF-SB logic for the - * Common Register Interface (CRI) ie. the DPIO registers. CRI clock - * must be running when any DPIO registers are accessed. - * - * In addition to having their own registers, the PHYs are also - * controlled through some dedicated signals from the display - * controller. These include PLL reference clock enable, PLL enable, - * and CRI clock selection, for example. - * - * Eeach channel also has two splines (also called data lanes), and - * each spline is made up of one Physical Access Coding Sub-Layer - * (PCS) block and two TX lanes. So each channel has two PCS blocks - * and four TX lanes. The TX lanes are used as DP lanes or TMDS - * data/clock pairs depending on the output type. - * - * Additionally the PHY also contains an AUX lane with AUX blocks - * for each channel. This is used for DP AUX communication, but - * this fact isn't really relevant for the driver since AUX is - * controlled from the display controller side. No DPIO registers - * need to be accessed during AUX communication, - * - * Generally on VLV/CHV the common lane corresponds to the pipe and - * the spline (PCS/TX) corresponds to the port. - * - * For dual channel PHY (VLV/CHV): - * - * pipe A == CMN/PLL/REF CH0 - * - * pipe B == CMN/PLL/REF CH1 - * - * port B == PCS/TX CH0 - * - * port C == PCS/TX CH1 - * - * This is especially important when we cross the streams - * ie. drive port B with pipe B, or port C with pipe A. - * - * For single channel PHY (CHV): - * - * pipe C == CMN/PLL/REF CH0 - * - * port D == PCS/TX CH0 - * - * On BXT the entire PHY channel corresponds to the port. That means - * the PLL is also now associated with the port rather than the pipe, - * and so the clock needs to be routed to the appropriate transcoder. - * Port A PLL is directly connected to transcoder EDP and port B/C - * PLLs can be routed to any transcoder A/B/C. - * - * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is - * digital port D (CHV) or port A (BXT). :: - * - * - * Dual channel PHY (VLV/CHV/BXT) - * --------------------------------- - * | CH0 | CH1 | - * | CMN/PLL/REF | CMN/PLL/REF | - * |---------------|---------------| Display PHY - * | PCS01 | PCS23 | PCS01 | PCS23 | - * |-------|-------|-------|-------| - * |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3| - * --------------------------------- - * | DDI0 | DDI1 | DP/HDMI ports - * --------------------------------- - * - * Single channel PHY (CHV/BXT) - * ----------------- - * | CH0 | - * | CMN/PLL/REF | - * |---------------| Display PHY - * | PCS01 | PCS23 | - * |-------|-------| - * |TX0|TX1|TX2|TX3| - * ----------------- - * | DDI2 | DP/HDMI port - * ----------------- - */ +/* DPIO registers */ #define DPIO_DEVFN 0 #define DPIO_CTL _MMIO(VLV_DISPLAY_BASE + 0x2110) diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index edf0cfd860c4..680629697ea6 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -23,6 +23,97 @@ #include "intel_drv.h" +/** + * DOC: DPIO + * + * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI + * ports. DPIO is the name given to such a display PHY. These PHYs + * don't follow the standard programming model using direct MMIO + * registers, and instead their registers must be accessed trough IOSF + * sideband. VLV has one such PHY for driving ports B and C, and CHV + * adds another PHY for driving port D. Each PHY responds to specific + * IOSF-SB port. + * + * Each display PHY is made up of one or two channels. Each channel + * houses a common lane part which contains the PLL and other common + * logic. CH0 common lane also contains the IOSF-SB logic for the + * Common Register Interface (CRI) ie. the DPIO registers. CRI clock + * must be running when any DPIO registers are accessed. + * + * In addition to having their own registers, the PHYs are also + * controlled through some dedicated signals from the display + * controller. These include PLL reference clock enable, PLL enable, + * and CRI clock selection, for example. + * + * Eeach channel also has two splines (also called data lanes), and + * each spline is made up of one Physical Access Coding Sub-Layer + * (PCS) block and two TX lanes. So each channel has two PCS blocks + * and four TX lanes. The TX lanes are used as DP lanes or TMDS + * data/clock pairs depending on the output type. + * + * Additionally the PHY also contains an AUX lane with AUX blocks + * for each channel. This is used for DP AUX communication, but + * this fact isn't really relevant for the driver since AUX is + * controlled from the display controller side. No DPIO registers + * need to be accessed during AUX communication, + * + * Generally on VLV/CHV the common lane corresponds to the pipe and + * the spline (PCS/TX) corresponds to the port. + * + * For dual channel PHY (VLV/CHV): + * + * pipe A == CMN/PLL/REF CH0 + * + * pipe B == CMN/PLL/REF CH1 + * + * port B == PCS/TX CH0 + * + * port C == PCS/TX CH1 + * + * This is especially important when we cross the streams + * ie. drive port B with pipe B, or port C with pipe A. + * + * For single channel PHY (CHV): + * + * pipe C == CMN/PLL/REF CH0 + * + * port D == PCS/TX CH0 + * + * On BXT the entire PHY channel corresponds to the port. That means + * the PLL is also now associated with the port rather than the pipe, + * and so the clock needs to be routed to the appropriate transcoder. + * Port A PLL is directly connected to transcoder EDP and port B/C + * PLLs can be routed to any transcoder A/B/C. + * + * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is + * digital port D (CHV) or port A (BXT). :: + * + * + * Dual channel PHY (VLV/CHV/BXT) + * --------------------------------- + * | CH0 | CH1 | + * | CMN/PLL/REF | CMN/PLL/REF | + * |---------------|---------------| Display PHY + * | PCS01 | PCS23 | PCS01 | PCS23 | + * |-------|-------|-------|-------| + * |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3| + * --------------------------------- + * | DDI0 | DDI1 | DP/HDMI ports + * --------------------------------- + * + * Single channel PHY (CHV/BXT) + * ----------------- + * | CH0 | + * | CMN/PLL/REF | + * |---------------| Display PHY + * | PCS01 | PCS23 | + * |-------|-------| + * |TX0|TX1|TX2|TX3| + * ----------------- + * | DDI2 | DP/HDMI port + * ----------------- + */ + bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, enum dpio_phy phy) { -- cgit v1.2.3 From b6e08203cc1f453d1807df38b5b95b93853cebd9 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 6 Oct 2016 19:22:19 +0300 Subject: drm/i915: Move broxton vswing sequence to intel_dpio_phy.c The vswing sequence is related to the DPIO phy, so move it closer to the rest of DPIO phy related code. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/59aa5c85a115c5cbed81e793f20cd7b9f8de694b.1475770848.git-series.ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/intel_ddi.c | 38 +++++----------------------------- drivers/gpu/drm/i915/intel_dpio_phy.c | 39 +++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c642f1097b8c..7e79298dc9d2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3761,6 +3761,9 @@ u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); /* intel_dpio_phy.c */ +void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, + enum port port, u32 margin, u32 scale, + u32 enable, u32 deemphasis); void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy); void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy); bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 51ca8eae2c8f..938ac4dbcb45 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1547,7 +1547,6 @@ static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, { const struct bxt_ddi_buf_trans *ddi_translations; u32 n_entries, i; - uint32_t val; if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { n_entries = ARRAY_SIZE(bxt_ddi_translations_edp); @@ -1576,38 +1575,11 @@ static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, } } - /* - * While we write to the group register to program all lanes at once we - * can read only lane registers and we pick lanes 0/1 for that. - */ - val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); - val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); - I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); - - val = I915_READ(BXT_PORT_TX_DW2_LN0(port)); - val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); - val |= ddi_translations[level].margin << MARGIN_000_SHIFT | - ddi_translations[level].scale << UNIQ_TRANS_SCALE_SHIFT; - I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val); - - val = I915_READ(BXT_PORT_TX_DW3_LN0(port)); - val &= ~SCALE_DCOMP_METHOD; - if (ddi_translations[level].enable) - val |= SCALE_DCOMP_METHOD; - - if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) - DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set"); - - I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val); - - val = I915_READ(BXT_PORT_TX_DW4_LN0(port)); - val &= ~DE_EMPHASIS; - val |= ddi_translations[level].deemphasis << DEEMPH_SHIFT; - I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val); - - val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); - val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; - I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); + bxt_ddi_phy_set_signal_level(dev_priv, port, + ddi_translations[level].margin, + ddi_translations[level].scale, + ddi_translations[level].enable, + ddi_translations[level].deemphasis); } static uint32_t translate_signal_level(int signal_levels) diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 680629697ea6..2a18724f9c3b 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -114,6 +114,45 @@ * ----------------- */ +void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, + enum port port, u32 margin, u32 scale, + u32 enable, u32 deemphasis) +{ + u32 val; + + /* + * While we write to the group register to program all lanes at once we + * can read only lane registers and we pick lanes 0/1 for that. + */ + val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); + val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); + I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); + + val = I915_READ(BXT_PORT_TX_DW2_LN0(port)); + val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); + val |= margin << MARGIN_000_SHIFT | scale << UNIQ_TRANS_SCALE_SHIFT; + I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val); + + val = I915_READ(BXT_PORT_TX_DW3_LN0(port)); + val &= ~SCALE_DCOMP_METHOD; + if (enable) + val |= SCALE_DCOMP_METHOD; + + if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) + DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set"); + + I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val); + + val = I915_READ(BXT_PORT_TX_DW4_LN0(port)); + val &= ~DE_EMPHASIS; + val |= deemphasis << DEEMPH_SHIFT; + I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val); + + val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); + val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; + I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); +} + bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, enum dpio_phy phy) { -- cgit v1.2.3 From 842d416654ebbcae86c32c0a354da9f649335410 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 6 Oct 2016 19:22:20 +0300 Subject: drm/i915: Create a struct to hold information about the broxton phys Information about which phy is dual channel is hardcoded in the phy init sequence. Split that to a separate struct so the init sequence is more generic. v2: Restore mangled part that ended up in following patch. (Imre) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/9102f4c984044126057e4fdd1b91a615ff25fae6.1475770848.git-series.ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 9 +++-- drivers/gpu/drm/i915/intel_dpio_phy.c | 65 +++++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2f504f6a1c51..44683f9286a1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1307,8 +1307,13 @@ enum skl_disp_power_wells { #define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC, \ _PORT_CL1CM_DW30_A) -/* Defined for PHY0 only */ -#define BXT_PORT_CL2CM_DW6_BC _MMIO(0x6C358) +/* The spec defines this only for BXT PHY0, but lets assume that this + * would exist for PHY1 too if it had a second channel. + */ +#define _PORT_CL2CM_DW6_A 0x162358 +#define _PORT_CL2CM_DW6_BC 0x6C358 +#define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC, \ + _PORT_CL2CM_DW6_A) #define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28) /* BXT PHY Ref registers */ diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 2a18724f9c3b..1b1fba16d4e9 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -114,6 +114,50 @@ * ----------------- */ +/** + * struct bxt_ddi_phy_info - Hold info for a broxton DDI phy + */ +struct bxt_ddi_phy_info { + /** + * @dual_channel: true if this phy has a second channel. + */ + bool dual_channel; + + /** + * @channel: struct containing per channel information. + */ + struct { + /** + * @port: which port maps to this channel. + */ + enum port port; + } channel[2]; +}; + +static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = { + [DPIO_PHY0] = { + .dual_channel = true, + + .channel = { + [DPIO_CH0] = { .port = PORT_B }, + [DPIO_CH1] = { .port = PORT_C }, + } + }, + [DPIO_PHY1] = { + .dual_channel = false, + + .channel = { + [DPIO_CH0] = { .port = PORT_A }, + } + }, +}; + +static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info) +{ + return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) | + BIT(phy_info->channel[DPIO_CH0].port); +} + void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, enum port port, u32 margin, u32 scale, u32 enable, u32 deemphasis) @@ -156,6 +200,7 @@ void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, enum dpio_phy phy) { + const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; enum port port; if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy))) @@ -183,9 +228,7 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, return false; } - for_each_port_masked(port, - phy == DPIO_PHY0 ? BIT(PORT_B) | BIT(PORT_C) : - BIT(PORT_A)) { + for_each_port_masked(port, bxt_phy_port_mask(phy_info)) { u32 tmp = I915_READ(BXT_PHY_CTL(port)); if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) { @@ -220,6 +263,7 @@ static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) { + const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; u32 val; if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { @@ -272,10 +316,10 @@ void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) SUS_CLK_CONFIG; I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val); - if (phy == DPIO_PHY0) { - val = I915_READ(BXT_PORT_CL2CM_DW6_BC); + if (phy_info->dual_channel) { + val = I915_READ(BXT_PORT_CL2CM_DW6(phy)); val |= DW6_OLDO_DYN_PWR_DOWN_EN; - I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val); + I915_WRITE(BXT_PORT_CL2CM_DW6(phy), val); } val = I915_READ(BXT_PORT_CL1CM_DW30(phy)); @@ -290,7 +334,7 @@ void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) * FIXME: Clarify programming of the following, the register is * read-only with bit 6 fixed at 0 at least in stepping A. */ - if (phy == DPIO_PHY1) + if (!phy_info->dual_channel) val |= OCL2_LDOFUSE_PWR_DIS; I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val); @@ -363,6 +407,7 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy) { + const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; uint32_t mask; bool ok; @@ -388,10 +433,10 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask, "BXT_PORT_CL1CM_DW28(%d)", phy); - if (phy == DPIO_PHY0) - ok &= _CHK(BXT_PORT_CL2CM_DW6_BC, + if (phy_info->dual_channel) + ok &= _CHK(BXT_PORT_CL2CM_DW6(phy), DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN, - "BXT_PORT_CL2CM_DW6_BC"); + "BXT_PORT_CL2CM_DW6(%d)", phy); /* * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS, -- cgit v1.2.3 From e7583f7b1018a862b2c93fd50650181881b2a0e1 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 6 Oct 2016 19:22:21 +0300 Subject: drm/i915: Add location of the Rcomp resistor to bxt_ddi_phy_info Use struct bxt_ddi_phy_info to hold information of where the Rcomp resistor is located, instead of hard coding it in the init sequence. Note that this moves the enabling of the phy with the Rcomp resistor out of the power well enable code. That should be safe since bxt_ddi_phy_init() is called while the power domains lock is held, and that is the only way that function gets called, so there is no possibility of a concurrent phy enable caused by a power domain get call. v2: Replace comment about lock with lockdep_assert_held() (Imre) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/62d209950ad48484564f3e793cf247cf62572a39.1475770848.git-series.ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/intel_dpio_phy.c | 72 +++++++++++++++++++++++++-------- drivers/gpu/drm/i915/intel_runtime_pm.c | 15 ------- 2 files changed, 55 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 1b1fba16d4e9..6711e3a53f13 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -123,6 +123,13 @@ struct bxt_ddi_phy_info { */ bool dual_channel; + /** + * @rcomp_phy: If -1, indicates this phy has its own rcomp resistor. + * Otherwise the GRC value will be copied from the phy indicated by + * this field. + */ + enum dpio_phy rcomp_phy; + /** * @channel: struct containing per channel information. */ @@ -137,6 +144,7 @@ struct bxt_ddi_phy_info { static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = { [DPIO_PHY0] = { .dual_channel = true, + .rcomp_phy = DPIO_PHY1, .channel = { [DPIO_CH0] = { .port = PORT_B }, @@ -145,6 +153,7 @@ static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = { }, [DPIO_PHY1] = { .dual_channel = false, + .rcomp_phy = -1, .channel = { [DPIO_CH0] = { .port = PORT_A }, @@ -214,9 +223,10 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, return false; } - if (phy == DPIO_PHY1 && - !(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE)) { - DRM_DEBUG_DRIVER("DDI PHY 1 powered, but GRC isn't done\n"); + if (phy_info->rcomp_phy == -1 && + !(I915_READ(BXT_PORT_REF_DW3(phy)) & GRC_DONE)) { + DRM_DEBUG_DRIVER("DDI PHY %d powered, but GRC isn't done\n", + phy); return false; } @@ -261,14 +271,15 @@ static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, DRM_ERROR("timeout waiting for PHY%d GRC\n", phy); } -void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) +static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, + enum dpio_phy phy) { const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; u32 val; if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { /* Still read out the GRC value for state verification */ - if (phy == DPIO_PHY0) + if (phy_info->rcomp_phy != -1) dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy); if (bxt_ddi_phy_verify_state(dev_priv, phy)) { @@ -338,30 +349,32 @@ void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) val |= OCL2_LDOFUSE_PWR_DIS; I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val); - if (phy == DPIO_PHY0) { + if (phy_info->rcomp_phy != -1) { uint32_t grc_code; /* * PHY0 isn't connected to an RCOMP resistor so copy over * the corresponding calibrated value from PHY1, and disable * the automatic calibration on PHY0. */ - val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, DPIO_PHY1); + val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, + phy_info->rcomp_phy); grc_code = val << GRC_CODE_FAST_SHIFT | val << GRC_CODE_SLOW_SHIFT | val; - I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code); + I915_WRITE(BXT_PORT_REF_DW6(phy), grc_code); - val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0)); + val = I915_READ(BXT_PORT_REF_DW8(phy)); val |= GRC_DIS | GRC_RDY_OVRD; - I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val); + I915_WRITE(BXT_PORT_REF_DW8(phy), val); } val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); val |= COMMON_RESET_DIS; I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); - if (phy == DPIO_PHY1) - bxt_phy_wait_grc_done(dev_priv, DPIO_PHY1); + if (phy_info->rcomp_phy == -1) + bxt_phy_wait_grc_done(dev_priv, phy); + } void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) @@ -377,6 +390,31 @@ void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); } +void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) +{ + const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; + enum dpio_phy rcomp_phy = phy_info->rcomp_phy; + bool was_enabled; + + lockdep_assert_held(&dev_priv->power_domains.lock); + + if (rcomp_phy != -1) { + was_enabled = bxt_ddi_phy_is_enabled(dev_priv, rcomp_phy); + + /* + * We need to copy the GRC calibration value from rcomp_phy, + * so make sure it's powered up. + */ + if (!was_enabled) + _bxt_ddi_phy_init(dev_priv, rcomp_phy); + } + + _bxt_ddi_phy_init(dev_priv, phy); + + if (rcomp_phy != -1 && !was_enabled) + bxt_ddi_phy_uninit(dev_priv, phy_info->rcomp_phy); +} + static bool __printf(6, 7) __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, i915_reg_t reg, u32 mask, u32 expected, @@ -443,7 +481,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, * at least on stepping A this bit is read-only and fixed at 0. */ - if (phy == DPIO_PHY0) { + if (phy_info->rcomp_phy != -1) { u32 grc_code = dev_priv->bxt_phy_grc; grc_code = grc_code << GRC_CODE_FAST_SHIFT | @@ -451,12 +489,12 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, grc_code; mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | GRC_CODE_NOM_MASK; - ok &= _CHK(BXT_PORT_REF_DW6(DPIO_PHY0), mask, grc_code, - "BXT_PORT_REF_DW6(%d)", DPIO_PHY0); + ok &= _CHK(BXT_PORT_REF_DW6(phy), mask, grc_code, + "BXT_PORT_REF_DW6(%d)", phy); mask = GRC_DIS | GRC_RDY_OVRD; - ok &= _CHK(BXT_PORT_REF_DW8(DPIO_PHY0), mask, mask, - "BXT_PORT_REF_DW8(%d)", DPIO_PHY0); + ok &= _CHK(BXT_PORT_REF_DW8(phy), mask, mask, + "BXT_PORT_REF_DW8(%d)", phy); } return ok; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 5fd76ee0f4ca..95034a06d4ad 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -848,22 +848,7 @@ static void skl_power_well_disable(struct drm_i915_private *dev_priv, static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum skl_disp_power_wells power_well_id = power_well->id; - struct i915_power_well *cmn_a_well = NULL; - - if (power_well_id == BXT_DPIO_CMN_BC) { - /* - * We need to copy the GRC calibration value from the eDP PHY, - * so make sure it's powered up. - */ - cmn_a_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A); - intel_power_well_get(dev_priv, cmn_a_well); - } - bxt_ddi_phy_init(dev_priv, power_well->data); - - if (cmn_a_well) - intel_power_well_put(dev_priv, cmn_a_well); } static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, -- cgit v1.2.3 From ed37892e6df2a3caae4928583c211970a46375a6 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Wed, 19 Oct 2016 10:59:00 +0300 Subject: drm/i915: Address broxton phy registers based on phy and channel number The port registers related to the phys in broxton map to different channels and specific phys. Make that mapping explicit. v2: Pass enum dpio_phy to macros instead of mmio base. (Imre) v3: Fix typo in macros. (Imre) v4: Also change variables from u32 to enum dpio_phy. (Imre) Remove leftovers from previous version. (Imre) v5: Actually git add the changes. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1476863940-6019-1-git-send-email-ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 141 ++++++++++++++++++---------------- drivers/gpu/drm/i915/intel_dpio_phy.c | 68 ++++++++++++---- drivers/gpu/drm/i915/intel_dpll_mgr.c | 84 +++++++++++--------- 4 files changed, 175 insertions(+), 120 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7e79298dc9d2..a8f006e3b45d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3761,6 +3761,8 @@ u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); /* intel_dpio_phy.c */ +void bxt_port_to_phy_channel(enum port port, + enum dpio_phy *phy, enum dpio_channel *ch); void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, enum port port, u32 margin, u32 scale, u32 enable, u32 deemphasis); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 44683f9286a1..3361d7ffc63e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1186,7 +1186,19 @@ enum skl_disp_power_wells { #define DPIO_UPAR_SHIFT 30 /* BXT PHY registers */ -#define _BXT_PHY(phy, a, b) _MMIO_PIPE((phy), (a), (b)) +#define _BXT_PHY0_BASE 0x6C000 +#define _BXT_PHY1_BASE 0x162000 +#define BXT_PHY_BASE(phy) _PIPE((phy), _BXT_PHY0_BASE, \ + _BXT_PHY1_BASE) + +#define _BXT_PHY(phy, reg) \ + _MMIO(BXT_PHY_BASE(phy) - _BXT_PHY0_BASE + (reg)) + +#define _BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \ + (BXT_PHY_BASE(phy) + _PIPE((ch), (reg_ch0) - _BXT_PHY0_BASE, \ + (reg_ch1) - _BXT_PHY0_BASE)) +#define _MMIO_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \ + _MMIO(_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1)) #define BXT_P_CR_GT_DISP_PWRON _MMIO(0x138090) #define GT_DISPLAY_POWER_ON(phy) (1 << (phy)) @@ -1203,8 +1215,8 @@ enum skl_disp_power_wells { #define _PHY_CTL_FAMILY_EDP 0x64C80 #define _PHY_CTL_FAMILY_DDI 0x64C90 #define COMMON_RESET_DIS (1 << 31) -#define BXT_PHY_CTL_FAMILY(phy) _BXT_PHY((phy), _PHY_CTL_FAMILY_DDI, \ - _PHY_CTL_FAMILY_EDP) +#define BXT_PHY_CTL_FAMILY(phy) _MMIO_PIPE((phy), _PHY_CTL_FAMILY_DDI, \ + _PHY_CTL_FAMILY_EDP) /* BXT PHY PLL registers */ #define _PORT_PLL_A 0x46074 @@ -1224,18 +1236,18 @@ enum skl_disp_power_wells { #define PORT_PLL_P2_SHIFT 8 #define PORT_PLL_P2_MASK (0x1f << PORT_PLL_P2_SHIFT) #define PORT_PLL_P2(x) ((x) << PORT_PLL_P2_SHIFT) -#define BXT_PORT_PLL_EBB_0(port) _MMIO_PORT3(port, _PORT_PLL_EBB_0_A, \ - _PORT_PLL_EBB_0_B, \ - _PORT_PLL_EBB_0_C) +#define BXT_PORT_PLL_EBB_0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PLL_EBB_0_B, \ + _PORT_PLL_EBB_0_C) #define _PORT_PLL_EBB_4_A 0x162038 #define _PORT_PLL_EBB_4_B 0x6C038 #define _PORT_PLL_EBB_4_C 0x6C344 #define PORT_PLL_10BIT_CLK_ENABLE (1 << 13) #define PORT_PLL_RECALIBRATE (1 << 14) -#define BXT_PORT_PLL_EBB_4(port) _MMIO_PORT3(port, _PORT_PLL_EBB_4_A, \ - _PORT_PLL_EBB_4_B, \ - _PORT_PLL_EBB_4_C) +#define BXT_PORT_PLL_EBB_4(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PLL_EBB_4_B, \ + _PORT_PLL_EBB_4_C) #define _PORT_PLL_0_A 0x162100 #define _PORT_PLL_0_B 0x6C100 @@ -1266,62 +1278,56 @@ enum skl_disp_power_wells { #define PORT_PLL_DCO_AMP_DEFAULT 15 #define PORT_PLL_DCO_AMP_MASK 0x3c00 #define PORT_PLL_DCO_AMP(x) ((x)<<10) -#define _PORT_PLL_BASE(port) _PORT3(port, _PORT_PLL_0_A, \ - _PORT_PLL_0_B, \ - _PORT_PLL_0_C) -#define BXT_PORT_PLL(port, idx) _MMIO(_PORT_PLL_BASE(port) + (idx) * 4) +#define _PORT_PLL_BASE(phy, ch) _BXT_PHY_CH(phy, ch, \ + _PORT_PLL_0_B, \ + _PORT_PLL_0_C) +#define BXT_PORT_PLL(phy, ch, idx) _MMIO(_PORT_PLL_BASE(phy, ch) + \ + (idx) * 4) /* BXT PHY common lane registers */ #define _PORT_CL1CM_DW0_A 0x162000 #define _PORT_CL1CM_DW0_BC 0x6C000 #define PHY_POWER_GOOD (1 << 16) #define PHY_RESERVED (1 << 7) -#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC, \ - _PORT_CL1CM_DW0_A) +#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC) #define _PORT_CL1CM_DW9_A 0x162024 #define _PORT_CL1CM_DW9_BC 0x6C024 #define IREF0RC_OFFSET_SHIFT 8 #define IREF0RC_OFFSET_MASK (0xFF << IREF0RC_OFFSET_SHIFT) -#define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC, \ - _PORT_CL1CM_DW9_A) +#define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC) #define _PORT_CL1CM_DW10_A 0x162028 #define _PORT_CL1CM_DW10_BC 0x6C028 #define IREF1RC_OFFSET_SHIFT 8 #define IREF1RC_OFFSET_MASK (0xFF << IREF1RC_OFFSET_SHIFT) -#define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC, \ - _PORT_CL1CM_DW10_A) +#define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC) #define _PORT_CL1CM_DW28_A 0x162070 #define _PORT_CL1CM_DW28_BC 0x6C070 #define OCL1_POWER_DOWN_EN (1 << 23) #define DW28_OLDO_DYN_PWR_DOWN_EN (1 << 22) #define SUS_CLK_CONFIG 0x3 -#define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC, \ - _PORT_CL1CM_DW28_A) +#define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC) #define _PORT_CL1CM_DW30_A 0x162078 #define _PORT_CL1CM_DW30_BC 0x6C078 #define OCL2_LDOFUSE_PWR_DIS (1 << 6) -#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC, \ - _PORT_CL1CM_DW30_A) +#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC) /* The spec defines this only for BXT PHY0, but lets assume that this * would exist for PHY1 too if it had a second channel. */ #define _PORT_CL2CM_DW6_A 0x162358 #define _PORT_CL2CM_DW6_BC 0x6C358 -#define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC, \ - _PORT_CL2CM_DW6_A) +#define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC) #define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28) /* BXT PHY Ref registers */ #define _PORT_REF_DW3_A 0x16218C #define _PORT_REF_DW3_BC 0x6C18C #define GRC_DONE (1 << 22) -#define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC, \ - _PORT_REF_DW3_A) +#define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC) #define _PORT_REF_DW6_A 0x162198 #define _PORT_REF_DW6_BC 0x6C198 @@ -1332,15 +1338,13 @@ enum skl_disp_power_wells { #define GRC_CODE_SLOW_SHIFT 8 #define GRC_CODE_SLOW_MASK (0xFF << GRC_CODE_SLOW_SHIFT) #define GRC_CODE_NOM_MASK 0xFF -#define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC, \ - _PORT_REF_DW6_A) +#define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC) #define _PORT_REF_DW8_A 0x1621A0 #define _PORT_REF_DW8_BC 0x6C1A0 #define GRC_DIS (1 << 15) #define GRC_RDY_OVRD (1 << 1) -#define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC, \ - _PORT_REF_DW8_A) +#define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC) /* BXT PHY PCS registers */ #define _PORT_PCS_DW10_LN01_A 0x162428 @@ -1349,12 +1353,13 @@ enum skl_disp_power_wells { #define _PORT_PCS_DW10_GRP_A 0x162C28 #define _PORT_PCS_DW10_GRP_B 0x6CC28 #define _PORT_PCS_DW10_GRP_C 0x6CE28 -#define BXT_PORT_PCS_DW10_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW10_LN01_A, \ - _PORT_PCS_DW10_LN01_B, \ - _PORT_PCS_DW10_LN01_C) -#define BXT_PORT_PCS_DW10_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW10_GRP_A, \ - _PORT_PCS_DW10_GRP_B, \ - _PORT_PCS_DW10_GRP_C) +#define BXT_PORT_PCS_DW10_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW10_LN01_B, \ + _PORT_PCS_DW10_LN01_C) +#define BXT_PORT_PCS_DW10_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW10_GRP_B, \ + _PORT_PCS_DW10_GRP_C) + #define TX2_SWING_CALC_INIT (1 << 31) #define TX1_SWING_CALC_INIT (1 << 30) @@ -1369,15 +1374,15 @@ enum skl_disp_power_wells { #define _PORT_PCS_DW12_GRP_C 0x6CE30 #define LANESTAGGER_STRAP_OVRD (1 << 6) #define LANE_STAGGER_MASK 0x1F -#define BXT_PORT_PCS_DW12_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN01_A, \ - _PORT_PCS_DW12_LN01_B, \ - _PORT_PCS_DW12_LN01_C) -#define BXT_PORT_PCS_DW12_LN23(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN23_A, \ - _PORT_PCS_DW12_LN23_B, \ - _PORT_PCS_DW12_LN23_C) -#define BXT_PORT_PCS_DW12_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW12_GRP_A, \ - _PORT_PCS_DW12_GRP_B, \ - _PORT_PCS_DW12_GRP_C) +#define BXT_PORT_PCS_DW12_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW12_LN01_B, \ + _PORT_PCS_DW12_LN01_C) +#define BXT_PORT_PCS_DW12_LN23(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW12_LN23_B, \ + _PORT_PCS_DW12_LN23_C) +#define BXT_PORT_PCS_DW12_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW12_GRP_B, \ + _PORT_PCS_DW12_GRP_C) /* BXT PHY TX registers */ #define _BXT_LANE_OFFSET(lane) (((lane) >> 1) * 0x200 + \ @@ -1389,12 +1394,12 @@ enum skl_disp_power_wells { #define _PORT_TX_DW2_GRP_A 0x162D08 #define _PORT_TX_DW2_GRP_B 0x6CD08 #define _PORT_TX_DW2_GRP_C 0x6CF08 -#define BXT_PORT_TX_DW2_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW2_GRP_A, \ - _PORT_TX_DW2_GRP_B, \ - _PORT_TX_DW2_GRP_C) -#define BXT_PORT_TX_DW2_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW2_LN0_A, \ - _PORT_TX_DW2_LN0_B, \ - _PORT_TX_DW2_LN0_C) +#define BXT_PORT_TX_DW2_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW2_LN0_B, \ + _PORT_TX_DW2_LN0_C) +#define BXT_PORT_TX_DW2_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW2_GRP_B, \ + _PORT_TX_DW2_GRP_C) #define MARGIN_000_SHIFT 16 #define MARGIN_000 (0xFF << MARGIN_000_SHIFT) #define UNIQ_TRANS_SCALE_SHIFT 8 @@ -1406,12 +1411,12 @@ enum skl_disp_power_wells { #define _PORT_TX_DW3_GRP_A 0x162D0C #define _PORT_TX_DW3_GRP_B 0x6CD0C #define _PORT_TX_DW3_GRP_C 0x6CF0C -#define BXT_PORT_TX_DW3_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW3_GRP_A, \ - _PORT_TX_DW3_GRP_B, \ - _PORT_TX_DW3_GRP_C) -#define BXT_PORT_TX_DW3_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW3_LN0_A, \ - _PORT_TX_DW3_LN0_B, \ - _PORT_TX_DW3_LN0_C) +#define BXT_PORT_TX_DW3_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW3_LN0_B, \ + _PORT_TX_DW3_LN0_C) +#define BXT_PORT_TX_DW3_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW3_GRP_B, \ + _PORT_TX_DW3_GRP_C) #define SCALE_DCOMP_METHOD (1 << 26) #define UNIQUE_TRANGE_EN_METHOD (1 << 27) @@ -1421,12 +1426,12 @@ enum skl_disp_power_wells { #define _PORT_TX_DW4_GRP_A 0x162D10 #define _PORT_TX_DW4_GRP_B 0x6CD10 #define _PORT_TX_DW4_GRP_C 0x6CF10 -#define BXT_PORT_TX_DW4_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW4_LN0_A, \ - _PORT_TX_DW4_LN0_B, \ - _PORT_TX_DW4_LN0_C) -#define BXT_PORT_TX_DW4_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW4_GRP_A, \ - _PORT_TX_DW4_GRP_B, \ - _PORT_TX_DW4_GRP_C) +#define BXT_PORT_TX_DW4_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW4_LN0_B, \ + _PORT_TX_DW4_LN0_C) +#define BXT_PORT_TX_DW4_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW4_GRP_B, \ + _PORT_TX_DW4_GRP_C) #define DEEMPH_SHIFT 24 #define DE_EMPHASIS (0xFF << DEEMPH_SHIFT) @@ -1435,10 +1440,10 @@ enum skl_disp_power_wells { #define _PORT_TX_DW14_LN0_C 0x6C938 #define LATENCY_OPTIM_SHIFT 30 #define LATENCY_OPTIM (1 << LATENCY_OPTIM_SHIFT) -#define BXT_PORT_TX_DW14_LN(port, lane) _MMIO(_PORT3((port), _PORT_TX_DW14_LN0_A, \ - _PORT_TX_DW14_LN0_B, \ - _PORT_TX_DW14_LN0_C) + \ - _BXT_LANE_OFFSET(lane)) +#define BXT_PORT_TX_DW14_LN(phy, ch, lane) \ + _MMIO(_BXT_PHY_CH(phy, ch, _PORT_TX_DW14_LN0_B, \ + _PORT_TX_DW14_LN0_C) + \ + _BXT_LANE_OFFSET(lane)) /* UAIMI scratch pad register 1 */ #define UAIMI_SPR1 _MMIO(0x4F074) diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 6711e3a53f13..4a6164a20718 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -167,26 +167,58 @@ static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info) BIT(phy_info->channel[DPIO_CH0].port); } +void bxt_port_to_phy_channel(enum port port, + enum dpio_phy *phy, enum dpio_channel *ch) +{ + const struct bxt_ddi_phy_info *phy_info; + int i; + + for (i = 0; i < ARRAY_SIZE(bxt_ddi_phy_info); i++) { + phy_info = &bxt_ddi_phy_info[i]; + + if (port == phy_info->channel[DPIO_CH0].port) { + *phy = i; + *ch = DPIO_CH0; + return; + } + + if (phy_info->dual_channel && + port == phy_info->channel[DPIO_CH1].port) { + *phy = i; + *ch = DPIO_CH1; + return; + } + } + + WARN(1, "PHY not found for PORT %c", port_name(port)); + *phy = DPIO_PHY0; + *ch = DPIO_CH0; +} + void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, enum port port, u32 margin, u32 scale, u32 enable, u32 deemphasis) { u32 val; + enum dpio_phy phy; + enum dpio_channel ch; + + bxt_port_to_phy_channel(port, &phy, &ch); /* * While we write to the group register to program all lanes at once we * can read only lane registers and we pick lanes 0/1 for that. */ - val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); + val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch)); val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); - I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); + I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val); - val = I915_READ(BXT_PORT_TX_DW2_LN0(port)); + val = I915_READ(BXT_PORT_TX_DW2_LN0(phy, ch)); val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); val |= margin << MARGIN_000_SHIFT | scale << UNIQ_TRANS_SCALE_SHIFT; - I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val); + I915_WRITE(BXT_PORT_TX_DW2_GRP(phy, ch), val); - val = I915_READ(BXT_PORT_TX_DW3_LN0(port)); + val = I915_READ(BXT_PORT_TX_DW3_LN0(phy, ch)); val &= ~SCALE_DCOMP_METHOD; if (enable) val |= SCALE_DCOMP_METHOD; @@ -194,16 +226,16 @@ void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set"); - I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val); + I915_WRITE(BXT_PORT_TX_DW3_GRP(phy, ch), val); - val = I915_READ(BXT_PORT_TX_DW4_LN0(port)); + val = I915_READ(BXT_PORT_TX_DW4_LN0(phy, ch)); val &= ~DE_EMPHASIS; val |= deemphasis << DEEMPH_SHIFT; - I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val); + I915_WRITE(BXT_PORT_TX_DW4_GRP(phy, ch), val); - val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); + val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch)); val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; - I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); + I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val); } bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, @@ -490,7 +522,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | GRC_CODE_NOM_MASK; ok &= _CHK(BXT_PORT_REF_DW6(phy), mask, grc_code, - "BXT_PORT_REF_DW6(%d)", phy); + "BXT_PORT_REF_DW6(%d)", phy); mask = GRC_DIS | GRC_RDY_OVRD; ok &= _CHK(BXT_PORT_REF_DW8(phy), mask, mask, @@ -525,10 +557,14 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); enum port port = dport->port; + enum dpio_phy phy; + enum dpio_channel ch; int lane; + bxt_port_to_phy_channel(port, &phy, &ch); + for (lane = 0; lane < 4; lane++) { - u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); + u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane)); /* * Note that on CHV this flag is called UPAR, but has @@ -538,7 +574,7 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, if (lane_lat_optim_mask & BIT(lane)) val |= LATENCY_OPTIM; - I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val); + I915_WRITE(BXT_PORT_TX_DW14_LN(phy, ch, lane), val); } } @@ -548,12 +584,16 @@ bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); enum port port = dport->port; + enum dpio_phy phy; + enum dpio_channel ch; int lane; uint8_t mask; + bxt_port_to_phy_channel(port, &phy, &ch); + mask = 0; for (lane = 0; lane < 4; lane++) { - u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); + u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane)); if (val & LATENCY_OPTIM) mask |= BIT(lane); diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 605d0b509f24..21853a17b6d9 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1371,6 +1371,10 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, { uint32_t temp; enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ + enum dpio_phy phy; + enum dpio_channel ch; + + bxt_port_to_phy_channel(port, &phy, &ch); /* Non-SSC reference */ temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); @@ -1378,72 +1382,72 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); /* Disable 10 bit clock */ - temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); + temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch)); temp &= ~PORT_PLL_10BIT_CLK_ENABLE; - I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp); /* Write P1 & P2 */ - temp = I915_READ(BXT_PORT_PLL_EBB_0(port)); + temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch)); temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK); temp |= pll->config.hw_state.ebb0; - I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp); + I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp); /* Write M2 integer */ - temp = I915_READ(BXT_PORT_PLL(port, 0)); + temp = I915_READ(BXT_PORT_PLL(phy, ch, 0)); temp &= ~PORT_PLL_M2_MASK; temp |= pll->config.hw_state.pll0; - I915_WRITE(BXT_PORT_PLL(port, 0), temp); + I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp); /* Write N */ - temp = I915_READ(BXT_PORT_PLL(port, 1)); + temp = I915_READ(BXT_PORT_PLL(phy, ch, 1)); temp &= ~PORT_PLL_N_MASK; temp |= pll->config.hw_state.pll1; - I915_WRITE(BXT_PORT_PLL(port, 1), temp); + I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp); /* Write M2 fraction */ - temp = I915_READ(BXT_PORT_PLL(port, 2)); + temp = I915_READ(BXT_PORT_PLL(phy, ch, 2)); temp &= ~PORT_PLL_M2_FRAC_MASK; temp |= pll->config.hw_state.pll2; - I915_WRITE(BXT_PORT_PLL(port, 2), temp); + I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp); /* Write M2 fraction enable */ - temp = I915_READ(BXT_PORT_PLL(port, 3)); + temp = I915_READ(BXT_PORT_PLL(phy, ch, 3)); temp &= ~PORT_PLL_M2_FRAC_ENABLE; temp |= pll->config.hw_state.pll3; - I915_WRITE(BXT_PORT_PLL(port, 3), temp); + I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp); /* Write coeff */ - temp = I915_READ(BXT_PORT_PLL(port, 6)); + temp = I915_READ(BXT_PORT_PLL(phy, ch, 6)); temp &= ~PORT_PLL_PROP_COEFF_MASK; temp &= ~PORT_PLL_INT_COEFF_MASK; temp &= ~PORT_PLL_GAIN_CTL_MASK; temp |= pll->config.hw_state.pll6; - I915_WRITE(BXT_PORT_PLL(port, 6), temp); + I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp); /* Write calibration val */ - temp = I915_READ(BXT_PORT_PLL(port, 8)); + temp = I915_READ(BXT_PORT_PLL(phy, ch, 8)); temp &= ~PORT_PLL_TARGET_CNT_MASK; temp |= pll->config.hw_state.pll8; - I915_WRITE(BXT_PORT_PLL(port, 8), temp); + I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp); - temp = I915_READ(BXT_PORT_PLL(port, 9)); + temp = I915_READ(BXT_PORT_PLL(phy, ch, 9)); temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK; temp |= pll->config.hw_state.pll9; - I915_WRITE(BXT_PORT_PLL(port, 9), temp); + I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp); - temp = I915_READ(BXT_PORT_PLL(port, 10)); + temp = I915_READ(BXT_PORT_PLL(phy, ch, 10)); temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H; temp &= ~PORT_PLL_DCO_AMP_MASK; temp |= pll->config.hw_state.pll10; - I915_WRITE(BXT_PORT_PLL(port, 10), temp); + I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp); /* Recalibrate with new settings */ - temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); + temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch)); temp |= PORT_PLL_RECALIBRATE; - I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp); temp &= ~PORT_PLL_10BIT_CLK_ENABLE; temp |= pll->config.hw_state.ebb4; - I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp); /* Enable PLL */ temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); @@ -1459,11 +1463,11 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, * While we write to the group register to program all lanes at once we * can read only lane registers and we pick lanes 0/1 for that. */ - temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); + temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch)); temp &= ~LANE_STAGGER_MASK; temp &= ~LANESTAGGER_STRAP_OVRD; temp |= pll->config.hw_state.pcsdw12; - I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp); + I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp); } static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, @@ -1485,6 +1489,10 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ uint32_t val; bool ret; + enum dpio_phy phy; + enum dpio_channel ch; + + bxt_port_to_phy_channel(port, &phy, &ch); if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; @@ -1495,36 +1503,36 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, if (!(val & PORT_PLL_ENABLE)) goto out; - hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); + hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch)); hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK; - hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port)); + hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch)); hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE; - hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0)); + hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0)); hw_state->pll0 &= PORT_PLL_M2_MASK; - hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1)); + hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1)); hw_state->pll1 &= PORT_PLL_N_MASK; - hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2)); + hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2)); hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK; - hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3)); + hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3)); hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE; - hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6)); + hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6)); hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK | PORT_PLL_INT_COEFF_MASK | PORT_PLL_GAIN_CTL_MASK; - hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8)); + hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8)); hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK; - hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9)); + hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9)); hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK; - hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10)); + hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10)); hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H | PORT_PLL_DCO_AMP_MASK; @@ -1533,11 +1541,11 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, * can read only lane registers. We configure all lanes the same way, so * here just read out lanes 0/1 and output a note if lanes 2/3 differ. */ - hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); - if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12) + hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch)); + if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12) DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n", hw_state->pcsdw12, - I915_READ(BXT_PORT_PCS_DW12_LN23(port))); + I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch))); hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD; ret = true; -- cgit v1.2.3 From 223decc457c992976e4d4e6936f6225d4b6dd99e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 27 Oct 2016 07:59:52 -0700 Subject: pinctrl: single: Drop custom names >From tony Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 25 Oct 2016 08:33:34 -0700 Subject: [PATCHv2] pinctrl: single: Drop custom names We no longer need to allocate custom names as those are dynamically generated in pinctrl_register_one_pin() if no name is passed to pinctrl_register_pins(). Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index bfdf720db270..d125f3f502be 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -36,7 +36,6 @@ #define DRIVER_NAME "pinctrl-single" #define PCS_MUX_PINS_NAME "pinctrl-single,pins" #define PCS_MUX_BITS_NAME "pinctrl-single,bits" -#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 3) #define PCS_OFF_DISABLED ~0U /** @@ -141,20 +140,6 @@ struct pcs_data { int cur; }; -/** - * struct pcs_name - register name for a pin - * @name: name of the pinctrl register - * - * REVISIT: We may want to make names optional in the pinctrl - * framework as some drivers may not care about pin names to - * avoid kernel bloat. The pin names can be deciphered by user - * space tools using debugfs based on the register address and - * SoC packaging information. - */ -struct pcs_name { - char name[PCS_REG_NAME_LEN]; -}; - /** * struct pcs_soc_data - SoC specific settings * @flags: initial SoC specific PCS_FEAT_xxx values @@ -187,7 +172,6 @@ struct pcs_soc_data { * @foff: value to turn mux off * @fmax: max number of functions in fmask * @bits_per_pin:number of bits per pin - * @names: array of register names for pins * @pins: physical pins on the SoC * @pgtree: pingroup index radix tree * @ftree: function index radix tree @@ -223,7 +207,6 @@ struct pcs_device { unsigned fmax; bool bits_per_mux; unsigned bits_per_pin; - struct pcs_name *names; struct pcs_data pins; struct radix_tree_root pgtree; struct radix_tree_root ftree; @@ -354,13 +337,17 @@ static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev, { struct pcs_device *pcs; unsigned val, mux_bytes; + unsigned long offset; + size_t pa; pcs = pinctrl_dev_get_drvdata(pctldev); mux_bytes = pcs->width / BITS_PER_BYTE; - val = pcs->read(pcs->base + pin * mux_bytes); + offset = pin * mux_bytes; + val = pcs->read(pcs->base + offset); + pa = pcs->res->start + offset; - seq_printf(s, "%08x %s " , val, DRIVER_NAME); + seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME); } static void pcs_dt_free_map(struct pinctrl_dev *pctldev, @@ -763,7 +750,6 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, { struct pcs_soc_data *pcs_soc = &pcs->socdata; struct pinctrl_pin_desc *pin; - struct pcs_name *pn; int i; i = pcs->pins.cur; @@ -786,10 +772,6 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, } pin = &pcs->pins.pa[i]; - pn = &pcs->names[i]; - sprintf(pn->name, "%lx.%u", - (unsigned long)pcs->res->start + offset, pin_pos); - pin->name = pn->name; pin->number = i; pcs->pins.cur++; @@ -827,12 +809,6 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs) if (!pcs->pins.pa) return -ENOMEM; - pcs->names = devm_kzalloc(pcs->dev, - sizeof(struct pcs_name) * nr_pins, - GFP_KERNEL); - if (!pcs->names) - return -ENOMEM; - pcs->desc.pins = pcs->pins.pa; pcs->desc.npins = nr_pins; -- cgit v1.2.3 From cd23604a4b2575c7d6786a3d6cd29d79941a5542 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 25 Oct 2016 09:09:00 -0700 Subject: pinctrl: single: Drop pointless macro This is left over from initial experiments with more properties. It's only used in one place, so let's just get rid of it to make the code more readable. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index d125f3f502be..7cc9b7dc8656 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1472,15 +1472,6 @@ static void pcs_free_resources(struct pcs_device *pcs) pcs_free_pingroups(pcs); } -#define PCS_GET_PROP_U32(name, reg, err) \ - do { \ - ret = of_property_read_u32(np, name, reg); \ - if (ret) { \ - dev_err(pcs->dev, err); \ - return ret; \ - } \ - } while (0); - static const struct of_device_id pcs_of_match[]; static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs) @@ -1825,8 +1816,13 @@ static int pcs_probe(struct platform_device *pdev) pcs->flags = soc->flags; memcpy(&pcs->socdata, soc, sizeof(*soc)); - PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width, - "register width not specified\n"); + ret = of_property_read_u32(np, "pinctrl-single,register-width", + &pcs->width); + if (ret) { + dev_err(pcs->dev, "register width not specified\n"); + + return ret; + } ret = of_property_read_u32(np, "pinctrl-single,function-mask", &pcs->fmask); -- cgit v1.2.3 From 40dba341124bea94be8adbd60821eb2284aa24fe Mon Sep 17 00:00:00 2001 From: "Navare, Manasi D" Date: Wed, 26 Oct 2016 16:25:55 -0700 Subject: drm/i915: Change the placement of some static functions in intel_dp.c These static helper functions are required to be used during fallback link rate implemnetation so they need to be placed at the top of the file. v3: * Add cleanup to other patch (Mika Kahola) v2: * Dont move around functions declared in intel_drv.h (Rodrigo Vivi) Cc: Jani Nikula Cc: Daniel Vetter Cc: Ville Syrjala Signed-off-by: Manasi Navare Reviewed-by: Mika Kahola Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477524358-16563-4-git-send-email-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 150 ++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8f313c1d374d..1063afe5174d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -213,6 +213,81 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp) return max_dotclk; } +static int +intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) +{ + if (intel_dp->num_sink_rates) { + *sink_rates = intel_dp->sink_rates; + return intel_dp->num_sink_rates; + } + + *sink_rates = default_rates; + + return (intel_dp_max_link_bw(intel_dp) >> 3) + 1; +} + +static int +intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); + int size; + + if (IS_BROXTON(dev_priv)) { + *source_rates = bxt_rates; + size = ARRAY_SIZE(bxt_rates); + } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { + *source_rates = skl_rates; + size = ARRAY_SIZE(skl_rates); + } else { + *source_rates = default_rates; + size = ARRAY_SIZE(default_rates); + } + + /* This depends on the fact that 5.4 is last value in the array */ + if (!intel_dp_source_supports_hbr2(intel_dp)) + size--; + + return size; +} + +static int intersect_rates(const int *source_rates, int source_len, + const int *sink_rates, int sink_len, + int *common_rates) +{ + int i = 0, j = 0, k = 0; + + while (i < source_len && j < sink_len) { + if (source_rates[i] == sink_rates[j]) { + if (WARN_ON(k >= DP_MAX_SUPPORTED_RATES)) + return k; + common_rates[k] = source_rates[i]; + ++k; + ++i; + ++j; + } else if (source_rates[i] < sink_rates[j]) { + ++i; + } else { + ++j; + } + } + return k; +} + +static int intel_dp_common_rates(struct intel_dp *intel_dp, + int *common_rates) +{ + const int *source_rates, *sink_rates; + int source_len, sink_len; + + sink_len = intel_dp_sink_rates(intel_dp, &sink_rates); + source_len = intel_dp_source_rates(intel_dp, &source_rates); + + return intersect_rates(source_rates, source_len, + sink_rates, sink_len, + common_rates); +} + static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) @@ -1291,19 +1366,6 @@ intel_dp_aux_init(struct intel_dp *intel_dp) intel_dp->aux.transfer = intel_dp_aux_transfer; } -static int -intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) -{ - if (intel_dp->num_sink_rates) { - *sink_rates = intel_dp->sink_rates; - return intel_dp->num_sink_rates; - } - - *sink_rates = default_rates; - - return (intel_dp_max_link_bw(intel_dp) >> 3) + 1; -} - bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -1316,31 +1378,6 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) return false; } -static int -intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates) -{ - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); - int size; - - if (IS_BROXTON(dev_priv)) { - *source_rates = bxt_rates; - size = ARRAY_SIZE(bxt_rates); - } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { - *source_rates = skl_rates; - size = ARRAY_SIZE(skl_rates); - } else { - *source_rates = default_rates; - size = ARRAY_SIZE(default_rates); - } - - /* This depends on the fact that 5.4 is last value in the array */ - if (!intel_dp_source_supports_hbr2(intel_dp)) - size--; - - return size; -} - static void intel_dp_set_clock(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) @@ -1375,43 +1412,6 @@ intel_dp_set_clock(struct intel_encoder *encoder, } } -static int intersect_rates(const int *source_rates, int source_len, - const int *sink_rates, int sink_len, - int *common_rates) -{ - int i = 0, j = 0, k = 0; - - while (i < source_len && j < sink_len) { - if (source_rates[i] == sink_rates[j]) { - if (WARN_ON(k >= DP_MAX_SUPPORTED_RATES)) - return k; - common_rates[k] = source_rates[i]; - ++k; - ++i; - ++j; - } else if (source_rates[i] < sink_rates[j]) { - ++i; - } else { - ++j; - } - } - return k; -} - -static int intel_dp_common_rates(struct intel_dp *intel_dp, - int *common_rates) -{ - const int *source_rates, *sink_rates; - int source_len, sink_len; - - sink_len = intel_dp_sink_rates(intel_dp, &sink_rates); - source_len = intel_dp_source_rates(intel_dp, &source_rates); - - return intersect_rates(source_rates, source_len, - sink_rates, sink_len, - common_rates); -} - static void snprintf_int_array(char *str, size_t len, const int *array, int nelem) { -- cgit v1.2.3 From b2a2f70863d2af5445b9a46b099c79cca981d002 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 19 Oct 2016 16:33:28 +0300 Subject: watchdog: mei_wdt: use module_mei_cl_driver macro Replace boilerplate driver registration with module_mei_cl_driver macro. Signed-off-by: Tomas Winkler Acked-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index 630bd189f167..116be477c8fd 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -699,25 +699,7 @@ static struct mei_cl_driver mei_wdt_driver = { .remove = mei_wdt_remove, }; -static int __init mei_wdt_init(void) -{ - int ret; - - ret = mei_cldev_driver_register(&mei_wdt_driver); - if (ret) { - pr_err(KBUILD_MODNAME ": module registration failed\n"); - return ret; - } - return 0; -} - -static void __exit mei_wdt_exit(void) -{ - mei_cldev_driver_unregister(&mei_wdt_driver); -} - -module_init(mei_wdt_init); -module_exit(mei_wdt_exit); +module_mei_cl_driver(mei_wdt_driver); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 094dbffedcc593ad11436d61376b884156ee0bd9 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 19 Oct 2016 16:33:29 +0300 Subject: nfc: mei: use module_mei_cl_driver macro Replace boilerplate driver registration with module_mei_cl_driver macro in pn544 and microread devices. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/microread/mei.c | 23 +---------------------- drivers/nfc/pn544/mei.c | 23 +---------------------- 2 files changed, 2 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index 3092501f26c4..eb5eddf1794e 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c @@ -82,28 +82,7 @@ static struct mei_cl_driver microread_driver = { .remove = microread_mei_remove, }; -static int microread_mei_init(void) -{ - int r; - - pr_debug(DRIVER_DESC ": %s\n", __func__); - - r = mei_cldev_driver_register(µread_driver); - if (r) { - pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n"); - return r; - } - - return 0; -} - -static void microread_mei_exit(void) -{ - mei_cldev_driver_unregister(µread_driver); -} - -module_init(microread_mei_init); -module_exit(microread_mei_exit); +module_mei_cl_driver(microread_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c index 46d0eb24eef9..ad57a8ec00d6 100644 --- a/drivers/nfc/pn544/mei.c +++ b/drivers/nfc/pn544/mei.c @@ -82,28 +82,7 @@ static struct mei_cl_driver pn544_driver = { .remove = pn544_mei_remove, }; -static int pn544_mei_init(void) -{ - int r; - - pr_debug(DRIVER_DESC ": %s\n", __func__); - - r = mei_cldev_driver_register(&pn544_driver); - if (r) { - pr_err(PN544_DRIVER_NAME ": driver registration failed\n"); - return r; - } - - return 0; -} - -static void pn544_mei_exit(void) -{ - mei_cldev_driver_unregister(&pn544_driver); -} - -module_init(pn544_mei_init); -module_exit(pn544_mei_exit); +module_mei_cl_driver(pn544_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION(DRIVER_DESC); -- cgit v1.2.3 From 972cedf6e39a49a79a66cd7f46132d21369d0083 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 19 Oct 2016 16:33:30 +0300 Subject: nfc: mei_phy: get phy from the driver data In order to remove rather redundant context from the callback signature we the get nfc mei_phy from the driver's data. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/mei_phy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index 83deda4bb4d6..66dfd81ffb18 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c @@ -300,7 +300,10 @@ static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length) static void nfc_mei_event_cb(struct mei_cl_device *cldev, u32 events, void *context) { - struct nfc_mei_phy *phy = context; + struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev); + + if (!phy) + return; if (phy->hard_fault != 0) return; -- cgit v1.2.3 From 1e4edb3fe93ff9f7b678a8f1b8d9df717edf6ad9 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 19 Oct 2016 16:33:31 +0300 Subject: mei: bus: remove rx callback context The callback context is redunant as all the information can be retrived from the device struture of its private data. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 6 ++---- drivers/nfc/mei_phy.c | 5 ++--- drivers/watchdog/mei_wdt.c | 6 ++---- include/linux/mei_cl_bus.h | 6 ++---- 4 files changed, 8 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 8cac7ef9ad0d..89a694ca624c 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -228,7 +228,7 @@ static void mei_cl_bus_event_work(struct work_struct *work) bus = cldev->bus; if (cldev->event_cb) - cldev->event_cb(cldev, cldev->events, cldev->event_context); + cldev->event_cb(cldev, cldev->events); cldev->events = 0; @@ -301,7 +301,6 @@ bool mei_cl_bus_rx_event(struct mei_cl *cl) * @cldev: me client devices * @event_cb: callback function * @events_mask: requested events bitmask - * @context: driver context data * * Return: 0 on success * -EALREADY if an callback is already registered @@ -309,7 +308,7 @@ bool mei_cl_bus_rx_event(struct mei_cl *cl) */ int mei_cldev_register_event_cb(struct mei_cl_device *cldev, unsigned long events_mask, - mei_cldev_event_cb_t event_cb, void *context) + mei_cldev_event_cb_t event_cb) { struct mei_device *bus = cldev->bus; int ret; @@ -320,7 +319,6 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev, cldev->events = 0; cldev->events_mask = events_mask; cldev->event_cb = event_cb; - cldev->event_context = context; INIT_WORK(&cldev->event_work, mei_cl_bus_event_work); if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index 66dfd81ffb18..07b4239585fa 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c @@ -297,8 +297,7 @@ static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length) } -static void nfc_mei_event_cb(struct mei_cl_device *cldev, u32 events, - void *context) +static void nfc_mei_event_cb(struct mei_cl_device *cldev, u32 events) { struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev); @@ -360,7 +359,7 @@ static int nfc_mei_phy_enable(void *phy_id) } r = mei_cldev_register_event_cb(phy->cldev, BIT(MEI_CL_EVENT_RX), - nfc_mei_event_cb, phy); + nfc_mei_event_cb); if (r) { pr_err("Event cb registration failed %d\n", r); goto err; diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index 116be477c8fd..e0af52265511 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -501,10 +501,8 @@ static void mei_wdt_notify_event(struct mei_cl_device *cldev) * * @cldev: bus device * @events: event mask - * @context: callback context */ -static void mei_wdt_event(struct mei_cl_device *cldev, - u32 events, void *context) +static void mei_wdt_event(struct mei_cl_device *cldev, u32 events) { if (events & BIT(MEI_CL_EVENT_RX)) mei_wdt_event_rx(cldev); @@ -626,7 +624,7 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, ret = mei_cldev_register_event_cb(wdt->cldev, BIT(MEI_CL_EVENT_RX) | BIT(MEI_CL_EVENT_NOTIF), - mei_wdt_event, NULL); + mei_wdt_event); /* on legacy devices notification is not supported * this doesn't fail the registration for RX event diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h index e6fbd98ea90e..4adb2e7c9f84 100644 --- a/include/linux/mei_cl_bus.h +++ b/include/linux/mei_cl_bus.h @@ -9,7 +9,7 @@ struct mei_cl_device; struct mei_device; typedef void (*mei_cldev_event_cb_t)(struct mei_cl_device *cldev, - u32 events, void *context); + u32 events); /** * struct mei_cl_device - MEI device handle @@ -27,7 +27,6 @@ typedef void (*mei_cldev_event_cb_t)(struct mei_cl_device *cldev, * @event_work: async work to execute event callback * @event_cb: Drivers register this callback to get asynchronous ME * events (e.g. Rx buffer pending) notifications. - * @event_context: event callback run context * @events_mask: Events bit mask requested by driver. * @events: Events bitmask sent to the driver. * @@ -46,7 +45,6 @@ struct mei_cl_device { struct work_struct event_work; mei_cldev_event_cb_t event_cb; - void *event_context; unsigned long events_mask; unsigned long events; @@ -92,7 +90,7 @@ ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length); int mei_cldev_register_event_cb(struct mei_cl_device *cldev, unsigned long event_mask, - mei_cldev_event_cb_t read_cb, void *context); + mei_cldev_event_cb_t read_cb); #define MEI_CL_EVENT_RX 0 #define MEI_CL_EVENT_TX 1 -- cgit v1.2.3 From e334cd69fa65fc9e916d6adc8d860a9b6b9e7281 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Mon, 10 Oct 2016 13:34:33 +0800 Subject: Move CONFIG_DEVKMEM default to n Kconfig comment suggests setting it as "n" if in doubt thus move the default value to 'n'. Signed-off-by: Dave Young Suggested-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/char/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index dcc09739a54e..dc4f35ad19d0 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -17,7 +17,6 @@ config DEVMEM config DEVKMEM bool "/dev/kmem virtual device support" - default y help Say Y here if you want to support the /dev/kmem device. The /dev/kmem device is rarely used, but can be used for certain -- cgit v1.2.3 From e806402130c9c494e22c73ae9ead4e79d2a5811c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 20 Oct 2016 15:12:13 +0200 Subject: block: split out request-only flags into a new namespace A lot of the REQ_* flags are only used on struct requests, and only of use to the block layer and a few drivers that dig into struct request internals. This patch adds a new req_flags_t rq_flags field to struct request for them, and thus dramatically shrinks the number of common requests. It also removes the unfortunate situation where we have to fit the fields from the same enum into 32 bits for struct bio and 64 bits for struct request. Signed-off-by: Christoph Hellwig Reviewed-by: Shaun Tancheff Signed-off-by: Jens Axboe --- Documentation/block/biodoc.txt | 2 +- block/blk-core.c | 71 ++++++++++++++------------- block/blk-exec.c | 2 +- block/blk-flush.c | 9 ++-- block/blk-map.c | 4 +- block/blk-merge.c | 8 +-- block/blk-mq.c | 19 ++++---- block/blk-tag.c | 6 +-- block/blk.h | 4 +- block/elevator.c | 32 ++++++------ drivers/block/pktcdvd.c | 2 +- drivers/ide/ide-atapi.c | 6 +-- drivers/ide/ide-cd.c | 46 +++++++++--------- drivers/ide/ide-cd.h | 2 +- drivers/ide/ide-cd_ioctl.c | 6 +-- drivers/ide/ide-io.c | 6 +-- drivers/ide/ide-pm.c | 4 +- drivers/md/dm-rq.c | 12 ++--- drivers/memstick/core/ms_block.c | 2 +- drivers/memstick/core/mspro_block.c | 2 +- drivers/mmc/card/block.c | 4 +- drivers/mmc/card/queue.c | 4 +- drivers/nvme/host/pci.c | 4 +- drivers/scsi/device_handler/scsi_dh_alua.c | 8 +-- drivers/scsi/device_handler/scsi_dh_emc.c | 2 +- drivers/scsi/device_handler/scsi_dh_hp_sw.c | 2 +- drivers/scsi/device_handler/scsi_dh_rdac.c | 2 +- drivers/scsi/osd/osd_initiator.c | 2 +- drivers/scsi/osst.c | 2 +- drivers/scsi/scsi_error.c | 2 +- drivers/scsi/scsi_lib.c | 75 +++++++++++++++++------------ drivers/scsi/sd.c | 6 +-- drivers/scsi/sd_zbc.c | 2 +- drivers/scsi/st.c | 2 +- drivers/scsi/ufs/ufshcd.c | 6 +-- include/linux/blk_types.h | 39 +-------------- include/linux/blkdev.h | 49 ++++++++++++++++++- include/scsi/scsi_device.h | 4 +- 38 files changed, 242 insertions(+), 218 deletions(-) (limited to 'drivers') diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 918e1e0d0e78..6acea160298c 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -348,7 +348,7 @@ Drivers can now specify a request prepare function (q->prep_rq_fn) that the block layer would invoke to pre-build device commands for a given request, or perform other preparatory processing for the request. This is routine is called by elv_next_request(), i.e. typically just before servicing a request. -(The prepare function would not be called for requests that have REQ_DONTPREP +(The prepare function would not be called for requests that have RQF_DONTPREP enabled) Aside: diff --git a/block/blk-core.c b/block/blk-core.c index e4eda5d2aa56..fd416651a676 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -145,13 +145,13 @@ static void req_bio_endio(struct request *rq, struct bio *bio, if (error) bio->bi_error = error; - if (unlikely(rq->cmd_flags & REQ_QUIET)) + if (unlikely(rq->rq_flags & RQF_QUIET)) bio_set_flag(bio, BIO_QUIET); bio_advance(bio, nbytes); /* don't actually finish bio if it's part of flush sequence */ - if (bio->bi_iter.bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ)) + if (bio->bi_iter.bi_size == 0 && !(rq->rq_flags & RQF_FLUSH_SEQ)) bio_endio(bio); } @@ -899,7 +899,7 @@ EXPORT_SYMBOL(blk_get_queue); static inline void blk_free_request(struct request_list *rl, struct request *rq) { - if (rq->cmd_flags & REQ_ELVPRIV) { + if (rq->rq_flags & RQF_ELVPRIV) { elv_put_request(rl->q, rq); if (rq->elv.icq) put_io_context(rq->elv.icq->ioc); @@ -961,14 +961,14 @@ static void __freed_request(struct request_list *rl, int sync) * A request has just been released. Account for it, update the full and * congestion status, wake up any waiters. Called under q->queue_lock. */ -static void freed_request(struct request_list *rl, int op, unsigned int flags) +static void freed_request(struct request_list *rl, bool sync, + req_flags_t rq_flags) { struct request_queue *q = rl->q; - int sync = rw_is_sync(op, flags); q->nr_rqs[sync]--; rl->count[sync]--; - if (flags & REQ_ELVPRIV) + if (rq_flags & RQF_ELVPRIV) q->nr_rqs_elvpriv--; __freed_request(rl, sync); @@ -1079,6 +1079,7 @@ static struct request *__get_request(struct request_list *rl, int op, struct io_cq *icq = NULL; const bool is_sync = rw_is_sync(op, op_flags) != 0; int may_queue; + req_flags_t rq_flags = RQF_ALLOCED; if (unlikely(blk_queue_dying(q))) return ERR_PTR(-ENODEV); @@ -1127,7 +1128,7 @@ static struct request *__get_request(struct request_list *rl, int op, /* * Decide whether the new request will be managed by elevator. If - * so, mark @op_flags and increment elvpriv. Non-zero elvpriv will + * so, mark @rq_flags and increment elvpriv. Non-zero elvpriv will * prevent the current elevator from being destroyed until the new * request is freed. This guarantees icq's won't be destroyed and * makes creating new ones safe. @@ -1136,14 +1137,14 @@ static struct request *__get_request(struct request_list *rl, int op, * it will be created after releasing queue_lock. */ if (blk_rq_should_init_elevator(bio) && !blk_queue_bypass(q)) { - op_flags |= REQ_ELVPRIV; + rq_flags |= RQF_ELVPRIV; q->nr_rqs_elvpriv++; if (et->icq_cache && ioc) icq = ioc_lookup_icq(ioc, q); } if (blk_queue_io_stat(q)) - op_flags |= REQ_IO_STAT; + rq_flags |= RQF_IO_STAT; spin_unlock_irq(q->queue_lock); /* allocate and init request */ @@ -1153,10 +1154,11 @@ static struct request *__get_request(struct request_list *rl, int op, blk_rq_init(q, rq); blk_rq_set_rl(rq, rl); - req_set_op_attrs(rq, op, op_flags | REQ_ALLOCED); + req_set_op_attrs(rq, op, op_flags); + rq->rq_flags = rq_flags; /* init elvpriv */ - if (op_flags & REQ_ELVPRIV) { + if (rq_flags & RQF_ELVPRIV) { if (unlikely(et->icq_cache && !icq)) { if (ioc) icq = ioc_create_icq(ioc, q, gfp_mask); @@ -1195,7 +1197,7 @@ fail_elvpriv: printk_ratelimited(KERN_WARNING "%s: dev %s: request aux data allocation failed, iosched may be disturbed\n", __func__, dev_name(q->backing_dev_info.dev)); - rq->cmd_flags &= ~REQ_ELVPRIV; + rq->rq_flags &= ~RQF_ELVPRIV; rq->elv.icq = NULL; spin_lock_irq(q->queue_lock); @@ -1212,7 +1214,7 @@ fail_alloc: * queue, but this is pretty rare. */ spin_lock_irq(q->queue_lock); - freed_request(rl, op, op_flags); + freed_request(rl, is_sync, rq_flags); /* * in the very unlikely event that allocation failed and no @@ -1347,7 +1349,7 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) blk_clear_rq_complete(rq); trace_block_rq_requeue(q, rq); - if (rq->cmd_flags & REQ_QUEUED) + if (rq->rq_flags & RQF_QUEUED) blk_queue_end_tag(q, rq); BUG_ON(blk_queued_rq(rq)); @@ -1409,7 +1411,7 @@ EXPORT_SYMBOL_GPL(part_round_stats); #ifdef CONFIG_PM static void blk_pm_put_request(struct request *rq) { - if (rq->q->dev && !(rq->cmd_flags & REQ_PM) && !--rq->q->nr_pending) + if (rq->q->dev && !(rq->rq_flags & RQF_PM) && !--rq->q->nr_pending) pm_runtime_mark_last_busy(rq->q->dev); } #else @@ -1421,6 +1423,8 @@ static inline void blk_pm_put_request(struct request *rq) {} */ void __blk_put_request(struct request_queue *q, struct request *req) { + req_flags_t rq_flags = req->rq_flags; + if (unlikely(!q)) return; @@ -1440,16 +1444,15 @@ void __blk_put_request(struct request_queue *q, struct request *req) * Request may not have originated from ll_rw_blk. if not, * it didn't come out of our reserved rq pools */ - if (req->cmd_flags & REQ_ALLOCED) { - unsigned int flags = req->cmd_flags; - int op = req_op(req); + if (rq_flags & RQF_ALLOCED) { struct request_list *rl = blk_rq_rl(req); + bool sync = rw_is_sync(req_op(req), req->cmd_flags); BUG_ON(!list_empty(&req->queuelist)); BUG_ON(ELV_ON_HASH(req)); blk_free_request(rl, req); - freed_request(rl, op, flags); + freed_request(rl, sync, rq_flags); blk_put_rl(rl); } } @@ -2214,7 +2217,7 @@ unsigned int blk_rq_err_bytes(const struct request *rq) unsigned int bytes = 0; struct bio *bio; - if (!(rq->cmd_flags & REQ_MIXED_MERGE)) + if (!(rq->rq_flags & RQF_MIXED_MERGE)) return blk_rq_bytes(rq); /* @@ -2257,7 +2260,7 @@ void blk_account_io_done(struct request *req) * normal IO on queueing nor completion. Accounting the * containing request is enough. */ - if (blk_do_io_stat(req) && !(req->cmd_flags & REQ_FLUSH_SEQ)) { + if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) { unsigned long duration = jiffies - req->start_time; const int rw = rq_data_dir(req); struct hd_struct *part; @@ -2285,7 +2288,7 @@ static struct request *blk_pm_peek_request(struct request_queue *q, struct request *rq) { if (q->dev && (q->rpm_status == RPM_SUSPENDED || - (q->rpm_status != RPM_ACTIVE && !(rq->cmd_flags & REQ_PM)))) + (q->rpm_status != RPM_ACTIVE && !(rq->rq_flags & RQF_PM)))) return NULL; else return rq; @@ -2361,13 +2364,13 @@ struct request *blk_peek_request(struct request_queue *q) if (!rq) break; - if (!(rq->cmd_flags & REQ_STARTED)) { + if (!(rq->rq_flags & RQF_STARTED)) { /* * This is the first time the device driver * sees this request (possibly after * requeueing). Notify IO scheduler. */ - if (rq->cmd_flags & REQ_SORTED) + if (rq->rq_flags & RQF_SORTED) elv_activate_rq(q, rq); /* @@ -2375,7 +2378,7 @@ struct request *blk_peek_request(struct request_queue *q) * it, a request that has been delayed should * not be passed by new incoming requests */ - rq->cmd_flags |= REQ_STARTED; + rq->rq_flags |= RQF_STARTED; trace_block_rq_issue(q, rq); } @@ -2384,7 +2387,7 @@ struct request *blk_peek_request(struct request_queue *q) q->boundary_rq = NULL; } - if (rq->cmd_flags & REQ_DONTPREP) + if (rq->rq_flags & RQF_DONTPREP) break; if (q->dma_drain_size && blk_rq_bytes(rq)) { @@ -2407,11 +2410,11 @@ struct request *blk_peek_request(struct request_queue *q) /* * the request may have been (partially) prepped. * we need to keep this request in the front to - * avoid resource deadlock. REQ_STARTED will + * avoid resource deadlock. RQF_STARTED will * prevent other fs requests from passing this one. */ if (q->dma_drain_size && blk_rq_bytes(rq) && - !(rq->cmd_flags & REQ_DONTPREP)) { + !(rq->rq_flags & RQF_DONTPREP)) { /* * remove the space for the drain we added * so that we don't add it again @@ -2424,7 +2427,7 @@ struct request *blk_peek_request(struct request_queue *q) } else if (ret == BLKPREP_KILL || ret == BLKPREP_INVALID) { int err = (ret == BLKPREP_INVALID) ? -EREMOTEIO : -EIO; - rq->cmd_flags |= REQ_QUIET; + rq->rq_flags |= RQF_QUIET; /* * Mark this request as started so we don't trigger * any debug logic in the end I/O path. @@ -2561,7 +2564,7 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) req->errors = 0; if (error && req->cmd_type == REQ_TYPE_FS && - !(req->cmd_flags & REQ_QUIET)) { + !(req->rq_flags & RQF_QUIET)) { char *error_type; switch (error) { @@ -2634,7 +2637,7 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) req->__sector += total_bytes >> 9; /* mixed attributes always follow the first bio */ - if (req->cmd_flags & REQ_MIXED_MERGE) { + if (req->rq_flags & RQF_MIXED_MERGE) { req->cmd_flags &= ~REQ_FAILFAST_MASK; req->cmd_flags |= req->bio->bi_opf & REQ_FAILFAST_MASK; } @@ -2687,7 +2690,7 @@ void blk_unprep_request(struct request *req) { struct request_queue *q = req->q; - req->cmd_flags &= ~REQ_DONTPREP; + req->rq_flags &= ~RQF_DONTPREP; if (q->unprep_rq_fn) q->unprep_rq_fn(q, req); } @@ -2698,7 +2701,7 @@ EXPORT_SYMBOL_GPL(blk_unprep_request); */ void blk_finish_request(struct request *req, int error) { - if (req->cmd_flags & REQ_QUEUED) + if (req->rq_flags & RQF_QUEUED) blk_queue_end_tag(req->q, req); BUG_ON(blk_queued_rq(req)); @@ -2708,7 +2711,7 @@ void blk_finish_request(struct request *req, int error) blk_delete_timer(req); - if (req->cmd_flags & REQ_DONTPREP) + if (req->rq_flags & RQF_DONTPREP) blk_unprep_request(req); blk_account_io_done(req); diff --git a/block/blk-exec.c b/block/blk-exec.c index 7ea04325d02f..3ecb00a6cf45 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -72,7 +72,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, spin_lock_irq(q->queue_lock); if (unlikely(blk_queue_dying(q))) { - rq->cmd_flags |= REQ_QUIET; + rq->rq_flags |= RQF_QUIET; rq->errors = -ENXIO; __blk_end_request_all(rq, rq->errors); spin_unlock_irq(q->queue_lock); diff --git a/block/blk-flush.c b/block/blk-flush.c index 6a14b68b9135..3990b9cfbda5 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -56,7 +56,7 @@ * Once while executing DATA and again after the whole sequence is * complete. The first completion updates the contained bio but doesn't * finish it so that the bio submitter is notified only after the whole - * sequence is complete. This is implemented by testing REQ_FLUSH_SEQ in + * sequence is complete. This is implemented by testing RQF_FLUSH_SEQ in * req_bio_endio(). * * The above peculiarity requires that each FLUSH/FUA request has only one @@ -127,7 +127,7 @@ static void blk_flush_restore_request(struct request *rq) rq->bio = rq->biotail; /* make @rq a normal request */ - rq->cmd_flags &= ~REQ_FLUSH_SEQ; + rq->rq_flags &= ~RQF_FLUSH_SEQ; rq->end_io = rq->flush.saved_end_io; } @@ -330,7 +330,8 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq) } flush_rq->cmd_type = REQ_TYPE_FS; - req_set_op_attrs(flush_rq, REQ_OP_FLUSH, WRITE_FLUSH | REQ_FLUSH_SEQ); + req_set_op_attrs(flush_rq, REQ_OP_FLUSH, WRITE_FLUSH); + flush_rq->rq_flags |= RQF_FLUSH_SEQ; flush_rq->rq_disk = first_rq->rq_disk; flush_rq->end_io = flush_end_io; @@ -433,7 +434,7 @@ void blk_insert_flush(struct request *rq) */ memset(&rq->flush, 0, sizeof(rq->flush)); INIT_LIST_HEAD(&rq->flush.list); - rq->cmd_flags |= REQ_FLUSH_SEQ; + rq->rq_flags |= RQF_FLUSH_SEQ; rq->flush.saved_end_io = rq->end_io; /* Usually NULL */ if (q->mq_ops) { rq->end_io = mq_flush_data_end_io; diff --git a/block/blk-map.c b/block/blk-map.c index b8657fa8dc9a..2c5ae5fef473 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -135,7 +135,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, } while (iov_iter_count(&i)); if (!bio_flagged(bio, BIO_USER_MAPPED)) - rq->cmd_flags |= REQ_COPY_USER; + rq->rq_flags |= RQF_COPY_USER; return 0; unmap_rq: @@ -232,7 +232,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, bio_set_op_attrs(bio, REQ_OP_WRITE, 0); if (do_copy) - rq->cmd_flags |= REQ_COPY_USER; + rq->rq_flags |= RQF_COPY_USER; ret = blk_rq_append_bio(rq, bio); if (unlikely(ret)) { diff --git a/block/blk-merge.c b/block/blk-merge.c index 2642e5fc8b69..fda6a12fc776 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -456,7 +456,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, if (rq->bio) nsegs = __blk_bios_map_sg(q, rq->bio, sglist, &sg); - if (unlikely(rq->cmd_flags & REQ_COPY_USER) && + if (unlikely(rq->rq_flags & RQF_COPY_USER) && (blk_rq_bytes(rq) & q->dma_pad_mask)) { unsigned int pad_len = (q->dma_pad_mask & ~blk_rq_bytes(rq)) + 1; @@ -634,7 +634,7 @@ void blk_rq_set_mixed_merge(struct request *rq) unsigned int ff = rq->cmd_flags & REQ_FAILFAST_MASK; struct bio *bio; - if (rq->cmd_flags & REQ_MIXED_MERGE) + if (rq->rq_flags & RQF_MIXED_MERGE) return; /* @@ -647,7 +647,7 @@ void blk_rq_set_mixed_merge(struct request *rq) (bio->bi_opf & REQ_FAILFAST_MASK) != ff); bio->bi_opf |= ff; } - rq->cmd_flags |= REQ_MIXED_MERGE; + rq->rq_flags |= RQF_MIXED_MERGE; } static void blk_account_io_merge(struct request *req) @@ -709,7 +709,7 @@ static int attempt_merge(struct request_queue *q, struct request *req, * makes sure that all involved bios have mixable attributes * set properly. */ - if ((req->cmd_flags | next->cmd_flags) & REQ_MIXED_MERGE || + if (((req->rq_flags | next->rq_flags) & RQF_MIXED_MERGE) || (req->cmd_flags & REQ_FAILFAST_MASK) != (next->cmd_flags & REQ_FAILFAST_MASK)) { blk_rq_set_mixed_merge(req); diff --git a/block/blk-mq.c b/block/blk-mq.c index d74a74a9f9ef..b49c6658eb05 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -142,14 +142,13 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, struct request *rq, int op, unsigned int op_flags) { - if (blk_queue_io_stat(q)) - op_flags |= REQ_IO_STAT; - INIT_LIST_HEAD(&rq->queuelist); /* csd/requeue_work/fifo_time is initialized before use */ rq->q = q; rq->mq_ctx = ctx; req_set_op_attrs(rq, op, op_flags); + if (blk_queue_io_stat(q)) + rq->rq_flags |= RQF_IO_STAT; /* do not touch atomic flags, it needs atomic ops against the timer */ rq->cpu = -1; INIT_HLIST_NODE(&rq->hash); @@ -198,7 +197,7 @@ __blk_mq_alloc_request(struct blk_mq_alloc_data *data, int op, int op_flags) rq = data->hctx->tags->rqs[tag]; if (blk_mq_tag_busy(data->hctx)) { - rq->cmd_flags = REQ_MQ_INFLIGHT; + rq->rq_flags = RQF_MQ_INFLIGHT; atomic_inc(&data->hctx->nr_active); } @@ -298,9 +297,9 @@ static void __blk_mq_free_request(struct blk_mq_hw_ctx *hctx, const int tag = rq->tag; struct request_queue *q = rq->q; - if (rq->cmd_flags & REQ_MQ_INFLIGHT) + if (rq->rq_flags & RQF_MQ_INFLIGHT) atomic_dec(&hctx->nr_active); - rq->cmd_flags = 0; + rq->rq_flags = 0; clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags); blk_mq_put_tag(hctx, ctx, tag); @@ -489,10 +488,10 @@ static void blk_mq_requeue_work(struct work_struct *work) spin_unlock_irqrestore(&q->requeue_lock, flags); list_for_each_entry_safe(rq, next, &rq_list, queuelist) { - if (!(rq->cmd_flags & REQ_SOFTBARRIER)) + if (!(rq->rq_flags & RQF_SOFTBARRIER)) continue; - rq->cmd_flags &= ~REQ_SOFTBARRIER; + rq->rq_flags &= ~RQF_SOFTBARRIER; list_del_init(&rq->queuelist); blk_mq_insert_request(rq, true, false, false); } @@ -519,11 +518,11 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head) * We abuse this flag that is otherwise used by the I/O scheduler to * request head insertation from the workqueue. */ - BUG_ON(rq->cmd_flags & REQ_SOFTBARRIER); + BUG_ON(rq->rq_flags & RQF_SOFTBARRIER); spin_lock_irqsave(&q->requeue_lock, flags); if (at_head) { - rq->cmd_flags |= REQ_SOFTBARRIER; + rq->rq_flags |= RQF_SOFTBARRIER; list_add(&rq->queuelist, &q->requeue_list); } else { list_add_tail(&rq->queuelist, &q->requeue_list); diff --git a/block/blk-tag.c b/block/blk-tag.c index f0344e6939d5..bae1decb6ec3 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -270,7 +270,7 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq) BUG_ON(tag >= bqt->real_max_depth); list_del_init(&rq->queuelist); - rq->cmd_flags &= ~REQ_QUEUED; + rq->rq_flags &= ~RQF_QUEUED; rq->tag = -1; if (unlikely(bqt->tag_index[tag] == NULL)) @@ -316,7 +316,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) unsigned max_depth; int tag; - if (unlikely((rq->cmd_flags & REQ_QUEUED))) { + if (unlikely((rq->rq_flags & RQF_QUEUED))) { printk(KERN_ERR "%s: request %p for device [%s] already tagged %d", __func__, rq, @@ -371,7 +371,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) */ bqt->next_tag = (tag + 1) % bqt->max_depth; - rq->cmd_flags |= REQ_QUEUED; + rq->rq_flags |= RQF_QUEUED; rq->tag = tag; bqt->tag_index[tag] = rq; blk_start_request(rq); diff --git a/block/blk.h b/block/blk.h index 74444c49078f..aa132dea598c 100644 --- a/block/blk.h +++ b/block/blk.h @@ -130,7 +130,7 @@ static inline void blk_clear_rq_complete(struct request *rq) /* * Internal elevator interface */ -#define ELV_ON_HASH(rq) ((rq)->cmd_flags & REQ_HASHED) +#define ELV_ON_HASH(rq) ((rq)->rq_flags & RQF_HASHED) void blk_insert_flush(struct request *rq); @@ -247,7 +247,7 @@ extern int blk_update_nr_requests(struct request_queue *, unsigned int); static inline int blk_do_io_stat(struct request *rq) { return rq->rq_disk && - (rq->cmd_flags & REQ_IO_STAT) && + (rq->rq_flags & RQF_IO_STAT) && (rq->cmd_type == REQ_TYPE_FS); } diff --git a/block/elevator.c b/block/elevator.c index f7d973a56fd7..ac80f89a0842 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -245,7 +245,7 @@ EXPORT_SYMBOL(elevator_exit); static inline void __elv_rqhash_del(struct request *rq) { hash_del(&rq->hash); - rq->cmd_flags &= ~REQ_HASHED; + rq->rq_flags &= ~RQF_HASHED; } static void elv_rqhash_del(struct request_queue *q, struct request *rq) @@ -260,7 +260,7 @@ static void elv_rqhash_add(struct request_queue *q, struct request *rq) BUG_ON(ELV_ON_HASH(rq)); hash_add(e->hash, &rq->hash, rq_hash_key(rq)); - rq->cmd_flags |= REQ_HASHED; + rq->rq_flags |= RQF_HASHED; } static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) @@ -352,7 +352,6 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) { sector_t boundary; struct list_head *entry; - int stop_flags; if (q->last_merge == rq) q->last_merge = NULL; @@ -362,7 +361,6 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) q->nr_sorted--; boundary = q->end_sector; - stop_flags = REQ_SOFTBARRIER | REQ_STARTED; list_for_each_prev(entry, &q->queue_head) { struct request *pos = list_entry_rq(entry); @@ -370,7 +368,7 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) break; if (rq_data_dir(rq) != rq_data_dir(pos)) break; - if (pos->cmd_flags & stop_flags) + if (pos->rq_flags & (RQF_STARTED | RQF_SOFTBARRIER)) break; if (blk_rq_pos(rq) >= boundary) { if (blk_rq_pos(pos) < boundary) @@ -510,7 +508,7 @@ void elv_merge_requests(struct request_queue *q, struct request *rq, struct request *next) { struct elevator_queue *e = q->elevator; - const int next_sorted = next->cmd_flags & REQ_SORTED; + const int next_sorted = next->rq_flags & RQF_SORTED; if (next_sorted && e->type->ops.elevator_merge_req_fn) e->type->ops.elevator_merge_req_fn(q, rq, next); @@ -537,13 +535,13 @@ void elv_bio_merged(struct request_queue *q, struct request *rq, #ifdef CONFIG_PM static void blk_pm_requeue_request(struct request *rq) { - if (rq->q->dev && !(rq->cmd_flags & REQ_PM)) + if (rq->q->dev && !(rq->rq_flags & RQF_PM)) rq->q->nr_pending--; } static void blk_pm_add_request(struct request_queue *q, struct request *rq) { - if (q->dev && !(rq->cmd_flags & REQ_PM) && q->nr_pending++ == 0 && + if (q->dev && !(rq->rq_flags & RQF_PM) && q->nr_pending++ == 0 && (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING)) pm_request_resume(q->dev); } @@ -563,11 +561,11 @@ void elv_requeue_request(struct request_queue *q, struct request *rq) */ if (blk_account_rq(rq)) { q->in_flight[rq_is_sync(rq)]--; - if (rq->cmd_flags & REQ_SORTED) + if (rq->rq_flags & RQF_SORTED) elv_deactivate_rq(q, rq); } - rq->cmd_flags &= ~REQ_STARTED; + rq->rq_flags &= ~RQF_STARTED; blk_pm_requeue_request(rq); @@ -597,13 +595,13 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where) rq->q = q; - if (rq->cmd_flags & REQ_SOFTBARRIER) { + if (rq->rq_flags & RQF_SOFTBARRIER) { /* barriers are scheduling boundary, update end_sector */ if (rq->cmd_type == REQ_TYPE_FS) { q->end_sector = rq_end_sector(rq); q->boundary_rq = rq; } - } else if (!(rq->cmd_flags & REQ_ELVPRIV) && + } else if (!(rq->rq_flags & RQF_ELVPRIV) && (where == ELEVATOR_INSERT_SORT || where == ELEVATOR_INSERT_SORT_MERGE)) where = ELEVATOR_INSERT_BACK; @@ -611,12 +609,12 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where) switch (where) { case ELEVATOR_INSERT_REQUEUE: case ELEVATOR_INSERT_FRONT: - rq->cmd_flags |= REQ_SOFTBARRIER; + rq->rq_flags |= RQF_SOFTBARRIER; list_add(&rq->queuelist, &q->queue_head); break; case ELEVATOR_INSERT_BACK: - rq->cmd_flags |= REQ_SOFTBARRIER; + rq->rq_flags |= RQF_SOFTBARRIER; elv_drain_elevator(q); list_add_tail(&rq->queuelist, &q->queue_head); /* @@ -642,7 +640,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where) break; case ELEVATOR_INSERT_SORT: BUG_ON(rq->cmd_type != REQ_TYPE_FS); - rq->cmd_flags |= REQ_SORTED; + rq->rq_flags |= RQF_SORTED; q->nr_sorted++; if (rq_mergeable(rq)) { elv_rqhash_add(q, rq); @@ -659,7 +657,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where) break; case ELEVATOR_INSERT_FLUSH: - rq->cmd_flags |= REQ_SOFTBARRIER; + rq->rq_flags |= RQF_SOFTBARRIER; blk_insert_flush(rq); break; default: @@ -735,7 +733,7 @@ void elv_completed_request(struct request_queue *q, struct request *rq) */ if (blk_account_rq(rq)) { q->in_flight[rq_is_sync(rq)]--; - if ((rq->cmd_flags & REQ_SORTED) && + if ((rq->rq_flags & RQF_SORTED) && e->type->ops.elevator_completed_req_fn) e->type->ops.elevator_completed_req_fn(q, rq); } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 90fa4ac149db..7cf795e0fc8d 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -721,7 +721,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * rq->timeout = 60*HZ; if (cgc->quiet) - rq->cmd_flags |= REQ_QUIET; + rq->rq_flags |= RQF_QUIET; blk_execute_rq(rq->q, pd->bdev->bd_disk, rq, 0); if (rq->errors) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 05352f490d60..f90ea221f7f2 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -211,7 +211,7 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) sense_rq->cmd[0] = GPCMD_REQUEST_SENSE; sense_rq->cmd[4] = cmd_len; sense_rq->cmd_type = REQ_TYPE_ATA_SENSE; - sense_rq->cmd_flags |= REQ_PREEMPT; + sense_rq->rq_flags |= RQF_PREEMPT; if (drive->media == ide_tape) sense_rq->cmd[13] = REQ_IDETAPE_PC1; @@ -295,7 +295,7 @@ int ide_cd_expiry(ide_drive_t *drive) wait = ATAPI_WAIT_PC; break; default: - if (!(rq->cmd_flags & REQ_QUIET)) + if (!(rq->rq_flags & RQF_QUIET)) printk(KERN_INFO PFX "cmd 0x%x timed out\n", rq->cmd[0]); wait = 0; @@ -375,7 +375,7 @@ int ide_check_ireason(ide_drive_t *drive, struct request *rq, int len, } if (dev_is_idecd(drive) && rq->cmd_type == REQ_TYPE_ATA_PC) - rq->cmd_flags |= REQ_FAILED; + rq->rq_flags |= RQF_FAILED; return 1; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index bf9a2ad296ed..9cbd217bc0c9 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -98,7 +98,7 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq) struct request_sense *sense = &drive->sense_data; int log = 0; - if (!sense || !rq || (rq->cmd_flags & REQ_QUIET)) + if (!sense || !rq || (rq->rq_flags & RQF_QUIET)) return 0; ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key); @@ -291,7 +291,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * (probably while trying to recover from a former error). * Just give up. */ - rq->cmd_flags |= REQ_FAILED; + rq->rq_flags |= RQF_FAILED; return 2; } @@ -311,7 +311,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) cdrom_saw_media_change(drive); if (rq->cmd_type == REQ_TYPE_FS && - !(rq->cmd_flags & REQ_QUIET)) + !(rq->rq_flags & RQF_QUIET)) printk(KERN_ERR PFX "%s: tray open\n", drive->name); } @@ -346,7 +346,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in retrying after an illegal request or data * protect error. */ - if (!(rq->cmd_flags & REQ_QUIET)) + if (!(rq->rq_flags & RQF_QUIET)) ide_dump_status(drive, "command error", stat); do_end_request = 1; break; @@ -355,14 +355,14 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in re-trying a zillion times on a bad sector. * If we got here the error is not correctable. */ - if (!(rq->cmd_flags & REQ_QUIET)) + if (!(rq->rq_flags & RQF_QUIET)) ide_dump_status(drive, "media error " "(bad sector)", stat); do_end_request = 1; break; case BLANK_CHECK: /* disk appears blank? */ - if (!(rq->cmd_flags & REQ_QUIET)) + if (!(rq->rq_flags & RQF_QUIET)) ide_dump_status(drive, "media error (blank)", stat); do_end_request = 1; @@ -380,7 +380,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) } if (rq->cmd_type != REQ_TYPE_FS) { - rq->cmd_flags |= REQ_FAILED; + rq->rq_flags |= RQF_FAILED; do_end_request = 1; } @@ -422,19 +422,19 @@ static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, int write, void *buffer, unsigned *bufflen, struct request_sense *sense, int timeout, - unsigned int cmd_flags) + req_flags_t rq_flags) { struct cdrom_info *info = drive->driver_data; struct request_sense local_sense; int retries = 10; - unsigned int flags = 0; + req_flags_t flags = 0; if (!sense) sense = &local_sense; ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x, timeout: %d, " - "cmd_flags: 0x%x", - cmd[0], write, timeout, cmd_flags); + "rq_flags: 0x%x", + cmd[0], write, timeout, rq_flags); /* start of retry loop */ do { @@ -446,7 +446,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, memcpy(rq->cmd, cmd, BLK_MAX_CDB); rq->cmd_type = REQ_TYPE_ATA_PC; rq->sense = sense; - rq->cmd_flags |= cmd_flags; + rq->rq_flags |= rq_flags; rq->timeout = timeout; if (buffer) { error = blk_rq_map_kern(drive->queue, rq, buffer, @@ -462,14 +462,14 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, if (buffer) *bufflen = rq->resid_len; - flags = rq->cmd_flags; + flags = rq->rq_flags; blk_put_request(rq); /* * FIXME: we should probably abort/retry or something in case of * failure. */ - if (flags & REQ_FAILED) { + if (flags & RQF_FAILED) { /* * The request failed. Retry if it was due to a unit * attention status (usually means media was changed). @@ -494,10 +494,10 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, } /* end of retry loop */ - } while ((flags & REQ_FAILED) && retries >= 0); + } while ((flags & RQF_FAILED) && retries >= 0); /* return an error if the command failed */ - return (flags & REQ_FAILED) ? -EIO : 0; + return (flags & RQF_FAILED) ? -EIO : 0; } /* @@ -589,7 +589,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) "(%u bytes)\n", drive->name, __func__, cmd->nleft); if (!write) - rq->cmd_flags |= REQ_FAILED; + rq->rq_flags |= RQF_FAILED; uptodate = 0; } } else if (rq->cmd_type != REQ_TYPE_BLOCK_PC) { @@ -607,7 +607,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } if (!uptodate) - rq->cmd_flags |= REQ_FAILED; + rq->rq_flags |= RQF_FAILED; } goto out_end; } @@ -745,9 +745,9 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) rq->cmd[0], rq->cmd_type); if (rq->cmd_type == REQ_TYPE_BLOCK_PC) - rq->cmd_flags |= REQ_QUIET; + rq->rq_flags |= RQF_QUIET; else - rq->cmd_flags &= ~REQ_FAILED; + rq->rq_flags &= ~RQF_FAILED; drive->dma = 0; @@ -867,7 +867,7 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) */ cmd[7] = cdi->sanyo_slot % 3; - return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET); + return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, RQF_QUIET); } static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, @@ -890,7 +890,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, cmd[0] = GPCMD_READ_CDVD_CAPACITY; stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0, - REQ_QUIET); + RQF_QUIET); if (stat) return stat; @@ -943,7 +943,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, if (msf_flag) cmd[1] = 2; - return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, REQ_QUIET); + return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, RQF_QUIET); } /* Try to read the entire TOC for the disk into our internal buffer. */ diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 1efc936f5b66..eea60c986c4f 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -101,7 +101,7 @@ void ide_cd_log_error(const char *, struct request *, struct request_sense *); /* ide-cd.c functions used by ide-cd_ioctl.c */ int ide_cd_queue_pc(ide_drive_t *, const unsigned char *, int, void *, - unsigned *, struct request_sense *, int, unsigned int); + unsigned *, struct request_sense *, int, req_flags_t); int ide_cd_read_toc(ide_drive_t *, struct request_sense *); int ide_cdrom_get_capabilities(ide_drive_t *, u8 *); void ide_cdrom_update_speed(ide_drive_t *, u8 *); diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c index 5887a7a09e37..f085e3a2e1d6 100644 --- a/drivers/ide/ide-cd_ioctl.c +++ b/drivers/ide/ide-cd_ioctl.c @@ -305,7 +305,7 @@ int ide_cdrom_reset(struct cdrom_device_info *cdi) rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM); rq->cmd_type = REQ_TYPE_DRV_PRIV; - rq->cmd_flags = REQ_QUIET; + rq->rq_flags = RQF_QUIET; ret = blk_execute_rq(drive->queue, cd->disk, rq, 0); blk_put_request(rq); /* @@ -449,7 +449,7 @@ int ide_cdrom_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) { ide_drive_t *drive = cdi->handle; - unsigned int flags = 0; + req_flags_t flags = 0; unsigned len = cgc->buflen; if (cgc->timeout <= 0) @@ -463,7 +463,7 @@ int ide_cdrom_packet(struct cdrom_device_info *cdi, memset(cgc->sense, 0, sizeof(struct request_sense)); if (cgc->quiet) - flags |= REQ_QUIET; + flags |= RQF_QUIET; cgc->stat = ide_cd_queue_pc(drive, cgc->cmd, cgc->data_direction == CGC_DATA_WRITE, diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 669ea1e45795..6360bbd37efe 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -307,7 +307,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; - BUG_ON(!(rq->cmd_flags & REQ_STARTED)); + BUG_ON(!(rq->rq_flags & RQF_STARTED)); #ifdef DEBUG printk("%s: start_request: current=0x%08lx\n", @@ -316,7 +316,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) /* bail early if we've exceeded max_failures */ if (drive->max_failures && (drive->failures > drive->max_failures)) { - rq->cmd_flags |= REQ_FAILED; + rq->rq_flags |= RQF_FAILED; goto kill_rq; } @@ -539,7 +539,7 @@ repeat: */ if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && ata_pm_request(rq) == 0 && - (rq->cmd_flags & REQ_PREEMPT) == 0) { + (rq->rq_flags & RQF_PREEMPT) == 0) { /* there should be no pending command at this point */ ide_unlock_port(hwif); goto plug_device; diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index e34af488693a..a015acdffb39 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c @@ -53,7 +53,7 @@ static int ide_pm_execute_rq(struct request *rq) spin_lock_irq(q->queue_lock); if (unlikely(blk_queue_dying(q))) { - rq->cmd_flags |= REQ_QUIET; + rq->rq_flags |= RQF_QUIET; rq->errors = -ENXIO; __blk_end_request_all(rq, rq->errors); spin_unlock_irq(q->queue_lock); @@ -90,7 +90,7 @@ int generic_ide_resume(struct device *dev) memset(&rqpm, 0, sizeof(rqpm)); rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM); rq->cmd_type = REQ_TYPE_ATA_PM_RESUME; - rq->cmd_flags |= REQ_PREEMPT; + rq->rq_flags |= RQF_PREEMPT; rq->special = &rqpm; rqpm.pm_step = IDE_PM_START_RESUME; rqpm.pm_state = PM_EVENT_ON; diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index dc75bea0d541..f76cc36b8546 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -313,7 +313,7 @@ static void dm_unprep_request(struct request *rq) if (!rq->q->mq_ops) { rq->special = NULL; - rq->cmd_flags &= ~REQ_DONTPREP; + rq->rq_flags &= ~RQF_DONTPREP; } if (clone) @@ -431,7 +431,7 @@ static void dm_softirq_done(struct request *rq) return; } - if (rq->cmd_flags & REQ_FAILED) + if (rq->rq_flags & RQF_FAILED) mapped = false; dm_done(clone, tio->error, mapped); @@ -460,7 +460,7 @@ static void dm_complete_request(struct request *rq, int error) */ static void dm_kill_unmapped_request(struct request *rq, int error) { - rq->cmd_flags |= REQ_FAILED; + rq->rq_flags |= RQF_FAILED; dm_complete_request(rq, error); } @@ -476,7 +476,7 @@ static void end_clone_request(struct request *clone, int error) * For just cleaning up the information of the queue in which * the clone was dispatched. * The clone is *NOT* freed actually here because it is alloced - * from dm own mempool (REQ_ALLOCED isn't set). + * from dm own mempool (RQF_ALLOCED isn't set). */ __blk_put_request(clone->q, clone); } @@ -497,7 +497,7 @@ static void dm_dispatch_clone_request(struct request *clone, struct request *rq) int r; if (blk_queue_io_stat(clone->q)) - clone->cmd_flags |= REQ_IO_STAT; + clone->rq_flags |= RQF_IO_STAT; clone->start_time = jiffies; r = blk_insert_cloned_request(clone->q, clone); @@ -633,7 +633,7 @@ static int dm_old_prep_fn(struct request_queue *q, struct request *rq) return BLKPREP_DEFER; rq->special = tio; - rq->cmd_flags |= REQ_DONTPREP; + rq->rq_flags |= RQF_DONTPREP; return BLKPREP_OK; } diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index aacf584f2a42..f3512404bc52 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -2006,7 +2006,7 @@ static int msb_prepare_req(struct request_queue *q, struct request *req) blk_dump_rq_flags(req, "MS unsupported request"); return BLKPREP_KILL; } - req->cmd_flags |= REQ_DONTPREP; + req->rq_flags |= RQF_DONTPREP; return BLKPREP_OK; } diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index c1472275fe57..fa0746d182ff 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -834,7 +834,7 @@ static int mspro_block_prepare_req(struct request_queue *q, struct request *req) return BLKPREP_KILL; } - req->cmd_flags |= REQ_DONTPREP; + req->rq_flags |= RQF_DONTPREP; return BLKPREP_OK; } diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c3335112e68c..f8190dd4a35c 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2117,7 +2117,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) mmc_blk_abort_packed_req(mq_rq); } else { if (mmc_card_removed(card)) - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; while (ret) ret = blk_end_request(req, -EIO, blk_rq_cur_bytes(req)); @@ -2126,7 +2126,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) start_new_req: if (rqc) { if (mmc_card_removed(card)) { - rqc->cmd_flags |= REQ_QUIET; + rqc->rq_flags |= RQF_QUIET; blk_end_request_all(rqc, -EIO); } else { /* diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 8037f73a109a..8a67f1c2ce21 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -44,7 +44,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq))) return BLKPREP_KILL; - req->cmd_flags |= REQ_DONTPREP; + req->rq_flags |= RQF_DONTPREP; return BLKPREP_OK; } @@ -120,7 +120,7 @@ static void mmc_request_fn(struct request_queue *q) if (!mq) { while ((req = blk_fetch_request(q)) != NULL) { - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; __blk_end_request_all(req, -EIO); } return; diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 0fc99f0f2571..0955e9d22020 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -323,9 +323,9 @@ static int nvme_init_iod(struct request *rq, unsigned size, iod->nents = 0; iod->length = size; - if (!(rq->cmd_flags & REQ_DONTPREP)) { + if (!(rq->rq_flags & RQF_DONTPREP)) { rq->retries = 0; - rq->cmd_flags |= REQ_DONTPREP; + rq->rq_flags |= RQF_DONTPREP; } return 0; } diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 241829e59668..05813a420188 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -154,7 +154,8 @@ static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff, return scsi_execute_req_flags(sdev, cdb, DMA_FROM_DEVICE, buff, bufflen, sshdr, ALUA_FAILOVER_TIMEOUT * HZ, - ALUA_FAILOVER_RETRIES, NULL, req_flags); + ALUA_FAILOVER_RETRIES, NULL, + req_flags, 0); } /* @@ -187,7 +188,8 @@ static int submit_stpg(struct scsi_device *sdev, int group_id, return scsi_execute_req_flags(sdev, cdb, DMA_TO_DEVICE, stpg_data, stpg_len, sshdr, ALUA_FAILOVER_TIMEOUT * HZ, - ALUA_FAILOVER_RETRIES, NULL, req_flags); + ALUA_FAILOVER_RETRIES, NULL, + req_flags, 0); } static struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, @@ -1063,7 +1065,7 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) state != SCSI_ACCESS_STATE_ACTIVE && state != SCSI_ACCESS_STATE_LBA) { ret = BLKPREP_KILL; - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; } return ret; diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 375d81850f15..5b80746980b8 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -452,7 +452,7 @@ static int clariion_prep_fn(struct scsi_device *sdev, struct request *req) if (h->lun_state != CLARIION_LUN_OWNED) { ret = BLKPREP_KILL; - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; } return ret; diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 9406d5f4a3d3..308e87195dc1 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -266,7 +266,7 @@ static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) if (h->path_state != HP_SW_PATH_ACTIVE) { ret = BLKPREP_KILL; - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; } return ret; diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 06fbd0b0c68a..00d9c326158e 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -724,7 +724,7 @@ static int rdac_prep_fn(struct scsi_device *sdev, struct request *req) if (h->state != RDAC_STATE_ACTIVE) { ret = BLKPREP_KILL; - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; } return ret; diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 2f2a9910e30e..ef99f62831fb 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -1595,7 +1595,7 @@ static int _init_blk_request(struct osd_request *or, } or->request = req; - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; req->timeout = or->timeout; req->retries = or->retries; diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 5033223f6287..a2960f5d98ec 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -368,7 +368,7 @@ static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd, return DRIVER_ERROR << 24; blk_rq_set_block_pc(req); - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; SRpnt->bio = NULL; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 106a6adbd6f1..996e134d79fa 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1988,7 +1988,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) req->cmd_len = COMMAND_SIZE(req->cmd[0]); - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; req->timeout = 10 * HZ; req->retries = 5; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 2cca9cffc63f..8c52622ac257 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -163,26 +163,11 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int reason) { __scsi_queue_insert(cmd, reason, 1); } -/** - * scsi_execute - insert request and wait for the result - * @sdev: scsi device - * @cmd: scsi command - * @data_direction: data direction - * @buffer: data buffer - * @bufflen: len of buffer - * @sense: optional sense buffer - * @timeout: request timeout in seconds - * @retries: number of times to retry request - * @flags: or into request flags; - * @resid: optional residual length - * - * returns the req->errors value which is the scsi_cmnd result - * field. - */ -int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, + +static int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, unsigned char *sense, int timeout, int retries, u64 flags, - int *resid) + req_flags_t rq_flags, int *resid) { struct request *req; int write = (data_direction == DMA_TO_DEVICE); @@ -203,7 +188,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, req->sense_len = 0; req->retries = retries; req->timeout = timeout; - req->cmd_flags |= flags | REQ_QUIET | REQ_PREEMPT; + req->cmd_flags |= flags; + req->rq_flags |= rq_flags | RQF_QUIET | RQF_PREEMPT; /* * head injection *required* here otherwise quiesce won't work @@ -227,12 +213,37 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, return ret; } + +/** + * scsi_execute - insert request and wait for the result + * @sdev: scsi device + * @cmd: scsi command + * @data_direction: data direction + * @buffer: data buffer + * @bufflen: len of buffer + * @sense: optional sense buffer + * @timeout: request timeout in seconds + * @retries: number of times to retry request + * @flags: or into request flags; + * @resid: optional residual length + * + * returns the req->errors value which is the scsi_cmnd result + * field. + */ +int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + unsigned char *sense, int timeout, int retries, u64 flags, + int *resid) +{ + return __scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, + timeout, retries, flags, 0, resid); +} EXPORT_SYMBOL(scsi_execute); int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout, int retries, - int *resid, u64 flags) + int *resid, u64 flags, req_flags_t rq_flags) { char *sense = NULL; int result; @@ -242,8 +253,8 @@ int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd, if (!sense) return DRIVER_ERROR << 24; } - result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, - sense, timeout, retries, flags, resid); + result = __scsi_execute(sdev, cmd, data_direction, buffer, bufflen, + sense, timeout, retries, flags, rq_flags, resid); if (sshdr) scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); @@ -813,7 +824,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) */ if ((sshdr.asc == 0x0) && (sshdr.ascq == 0x1d)) ; - else if (!(req->cmd_flags & REQ_QUIET)) + else if (!(req->rq_flags & RQF_QUIET)) scsi_print_sense(cmd); result = 0; /* BLOCK_PC may have set error */ @@ -943,7 +954,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) switch (action) { case ACTION_FAIL: /* Give up and fail the remainder of the request */ - if (!(req->cmd_flags & REQ_QUIET)) { + if (!(req->rq_flags & RQF_QUIET)) { static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); @@ -972,7 +983,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) * A new command will be prepared and issued. */ if (q->mq_ops) { - cmd->request->cmd_flags &= ~REQ_DONTPREP; + cmd->request->rq_flags &= ~RQF_DONTPREP; scsi_mq_uninit_cmd(cmd); scsi_mq_requeue_cmd(cmd); } else { @@ -1234,7 +1245,7 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req) /* * If the devices is blocked we defer normal commands. */ - if (!(req->cmd_flags & REQ_PREEMPT)) + if (!(req->rq_flags & RQF_PREEMPT)) ret = BLKPREP_DEFER; break; default: @@ -1243,7 +1254,7 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req) * special commands. In particular any user initiated * command is not allowed. */ - if (!(req->cmd_flags & REQ_PREEMPT)) + if (!(req->rq_flags & RQF_PREEMPT)) ret = BLKPREP_KILL; break; } @@ -1279,7 +1290,7 @@ scsi_prep_return(struct request_queue *q, struct request *req, int ret) blk_delay_queue(q, SCSI_QUEUE_DELAY); break; default: - req->cmd_flags |= REQ_DONTPREP; + req->rq_flags |= RQF_DONTPREP; } return ret; @@ -1736,7 +1747,7 @@ static void scsi_request_fn(struct request_queue *q) * we add the dev to the starved list so it eventually gets * a run when a tag is freed. */ - if (blk_queue_tagged(q) && !(req->cmd_flags & REQ_QUEUED)) { + if (blk_queue_tagged(q) && !(req->rq_flags & RQF_QUEUED)) { spin_lock_irq(shost->host_lock); if (list_empty(&sdev->starved_entry)) list_add_tail(&sdev->starved_entry, @@ -1903,11 +1914,11 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, goto out_dec_target_busy; - if (!(req->cmd_flags & REQ_DONTPREP)) { + if (!(req->rq_flags & RQF_DONTPREP)) { ret = prep_to_mq(scsi_mq_prep_fn(req)); if (ret) goto out_dec_host_busy; - req->cmd_flags |= REQ_DONTPREP; + req->rq_flags |= RQF_DONTPREP; } else { blk_mq_start_request(req); } @@ -1952,7 +1963,7 @@ out: * we hit an error, as we will never see this command * again. */ - if (req->cmd_flags & REQ_DONTPREP) + if (req->rq_flags & RQF_DONTPREP) scsi_mq_uninit_cmd(cmd); break; default: diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index b9618ffca829..cef1f78031d4 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1520,7 +1520,7 @@ static int sd_sync_cache(struct scsi_disk *sdkp) */ res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, timeout, SD_MAX_RETRIES, - NULL, REQ_PM); + NULL, 0, RQF_PM); if (res == 0) break; } @@ -1879,7 +1879,7 @@ static int sd_done(struct scsi_cmnd *SCpnt) good_bytes = 0; req->__data_len = blk_rq_bytes(req); - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; } } } @@ -3278,7 +3278,7 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) return -ENODEV; res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, - SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM); + SD_TIMEOUT, SD_MAX_RETRIES, NULL, 0, RQF_PM); if (res) { sd_print_result(sdkp, "Start/Stop Unit failed", res); if (driver_byte(res) & DRIVER_SENSE) diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index d5b3bd915d9e..394ab490919c 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -348,7 +348,7 @@ void sd_zbc_complete(struct scsi_cmnd *cmd, * this case, so be quiet about the error. */ if (req_op(rq) == REQ_OP_ZONE_RESET) - rq->cmd_flags |= REQ_QUIET; + rq->rq_flags |= RQF_QUIET; break; case 0x21: /* diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 7af5226aa55b..3bc46a4abd43 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -546,7 +546,7 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, return DRIVER_ERROR << 24; blk_rq_set_block_pc(req); - req->cmd_flags |= REQ_QUIET; + req->rq_flags |= RQF_QUIET; mdata->null_mapped = 1; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 05c745663c10..cf549871c1ee 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5590,7 +5590,7 @@ ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp) ret = scsi_execute_req_flags(sdp, cmd, DMA_FROM_DEVICE, buffer, SCSI_SENSE_BUFFERSIZE, NULL, - msecs_to_jiffies(1000), 3, NULL, REQ_PM); + msecs_to_jiffies(1000), 3, NULL, 0, RQF_PM); if (ret) pr_err("%s: failed with err %d\n", __func__, ret); @@ -5652,11 +5652,11 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, /* * Current function would be generally called from the power management - * callbacks hence set the REQ_PM flag so that it doesn't resume the + * callbacks hence set the RQF_PM flag so that it doesn't resume the * already suspended childs. */ ret = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, - START_STOP_TIMEOUT, 0, NULL, REQ_PM); + START_STOP_TIMEOUT, 0, NULL, 0, RQF_PM); if (ret) { sdev_printk(KERN_WARNING, sdp, "START_STOP failed for power mode: %d, result %x\n", diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 6df722de2e22..ec69a8fe3b29 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -167,26 +167,6 @@ enum rq_flag_bits { __REQ_PREFLUSH, /* request for cache flush */ __REQ_RAHEAD, /* read ahead, can fail anytime */ - /* request only flags */ - __REQ_SORTED, /* elevator knows about this request */ - __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ - __REQ_STARTED, /* drive already may have started this one */ - __REQ_DONTPREP, /* don't call prep for this one */ - __REQ_QUEUED, /* uses queueing */ - __REQ_ELVPRIV, /* elevator private data attached */ - __REQ_FAILED, /* set if the request failed */ - __REQ_QUIET, /* don't worry about errors */ - __REQ_PREEMPT, /* set for "ide_preempt" requests and also - for requests for which the SCSI "quiesce" - state must be ignored. */ - __REQ_ALLOCED, /* request came from our alloc pool */ - __REQ_COPY_USER, /* contains copies of user pages */ - __REQ_FLUSH_SEQ, /* request for flush sequence */ - __REQ_IO_STAT, /* account I/O stat */ - __REQ_MIXED_MERGE, /* merge of different types, fail separately */ - __REQ_PM, /* runtime pm request */ - __REQ_HASHED, /* on IO scheduler merge hash */ - __REQ_MQ_INFLIGHT, /* track inflight for MQ */ __REQ_NR_BITS, /* stops here */ }; @@ -208,29 +188,12 @@ enum rq_flag_bits { /* This mask is used for both bio and request merge checking */ #define REQ_NOMERGE_FLAGS \ - (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_PREFLUSH | REQ_FUA | REQ_FLUSH_SEQ) + (REQ_NOMERGE | REQ_PREFLUSH | REQ_FUA) #define REQ_RAHEAD (1ULL << __REQ_RAHEAD) -#define REQ_SORTED (1ULL << __REQ_SORTED) -#define REQ_SOFTBARRIER (1ULL << __REQ_SOFTBARRIER) #define REQ_FUA (1ULL << __REQ_FUA) #define REQ_NOMERGE (1ULL << __REQ_NOMERGE) -#define REQ_STARTED (1ULL << __REQ_STARTED) -#define REQ_DONTPREP (1ULL << __REQ_DONTPREP) -#define REQ_QUEUED (1ULL << __REQ_QUEUED) -#define REQ_ELVPRIV (1ULL << __REQ_ELVPRIV) -#define REQ_FAILED (1ULL << __REQ_FAILED) -#define REQ_QUIET (1ULL << __REQ_QUIET) -#define REQ_PREEMPT (1ULL << __REQ_PREEMPT) -#define REQ_ALLOCED (1ULL << __REQ_ALLOCED) -#define REQ_COPY_USER (1ULL << __REQ_COPY_USER) #define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH) -#define REQ_FLUSH_SEQ (1ULL << __REQ_FLUSH_SEQ) -#define REQ_IO_STAT (1ULL << __REQ_IO_STAT) -#define REQ_MIXED_MERGE (1ULL << __REQ_MIXED_MERGE) -#define REQ_PM (1ULL << __REQ_PM) -#define REQ_HASHED (1ULL << __REQ_HASHED) -#define REQ_MQ_INFLIGHT (1ULL << __REQ_MQ_INFLIGHT) enum req_op { REQ_OP_READ, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 90097dd8b8ed..b4415feac679 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -78,6 +78,50 @@ enum rq_cmd_type_bits { REQ_TYPE_DRV_PRIV, /* driver defined types from here */ }; +/* + * request flags */ +typedef __u32 __bitwise req_flags_t; + +/* elevator knows about this request */ +#define RQF_SORTED ((__force req_flags_t)(1 << 0)) +/* drive already may have started this one */ +#define RQF_STARTED ((__force req_flags_t)(1 << 1)) +/* uses tagged queueing */ +#define RQF_QUEUED ((__force req_flags_t)(1 << 2)) +/* may not be passed by ioscheduler */ +#define RQF_SOFTBARRIER ((__force req_flags_t)(1 << 3)) +/* request for flush sequence */ +#define RQF_FLUSH_SEQ ((__force req_flags_t)(1 << 4)) +/* merge of different types, fail separately */ +#define RQF_MIXED_MERGE ((__force req_flags_t)(1 << 5)) +/* track inflight for MQ */ +#define RQF_MQ_INFLIGHT ((__force req_flags_t)(1 << 6)) +/* don't call prep for this one */ +#define RQF_DONTPREP ((__force req_flags_t)(1 << 7)) +/* set for "ide_preempt" requests and also for requests for which the SCSI + "quiesce" state must be ignored. */ +#define RQF_PREEMPT ((__force req_flags_t)(1 << 8)) +/* contains copies of user pages */ +#define RQF_COPY_USER ((__force req_flags_t)(1 << 9)) +/* vaguely specified driver internal error. Ignored by the block layer */ +#define RQF_FAILED ((__force req_flags_t)(1 << 10)) +/* don't warn about errors */ +#define RQF_QUIET ((__force req_flags_t)(1 << 11)) +/* elevator private data attached */ +#define RQF_ELVPRIV ((__force req_flags_t)(1 << 12)) +/* account I/O stat */ +#define RQF_IO_STAT ((__force req_flags_t)(1 << 13)) +/* request came from our alloc pool */ +#define RQF_ALLOCED ((__force req_flags_t)(1 << 14)) +/* runtime pm request */ +#define RQF_PM ((__force req_flags_t)(1 << 15)) +/* on IO scheduler merge hash */ +#define RQF_HASHED ((__force req_flags_t)(1 << 16)) + +/* flags that prevent us from merging requests: */ +#define RQF_NOMERGE_FLAGS \ + (RQF_STARTED | RQF_SOFTBARRIER | RQF_FLUSH_SEQ) + #define BLK_MAX_CDB 16 /* @@ -99,6 +143,7 @@ struct request { int cpu; unsigned cmd_type; u64 cmd_flags; + req_flags_t rq_flags; unsigned long atomic_flags; /* the following two fields are internal, NEVER access directly */ @@ -648,7 +693,7 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q) REQ_FAILFAST_DRIVER)) #define blk_account_rq(rq) \ - (((rq)->cmd_flags & REQ_STARTED) && \ + (((rq)->rq_flags & RQF_STARTED) && \ ((rq)->cmd_type == REQ_TYPE_FS)) #define blk_rq_cpu_valid(rq) ((rq)->cpu != -1) @@ -740,6 +785,8 @@ static inline bool rq_mergeable(struct request *rq) if (rq->cmd_flags & REQ_NOMERGE_FLAGS) return false; + if (rq->rq_flags & RQF_NOMERGE_FLAGS) + return false; return true; } diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 8a9563144890..8990e580b278 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -414,14 +414,14 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, extern int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout, - int retries, int *resid, u64 flags); + int retries, int *resid, u64 flags, req_flags_t rq_flags); static inline int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout, int retries, int *resid) { return scsi_execute_req_flags(sdev, cmd, data_direction, buffer, - bufflen, sshdr, timeout, retries, resid, 0); + bufflen, sshdr, timeout, retries, resid, 0, 0); } extern void sdev_disable_disk_events(struct scsi_device *sdev); extern void sdev_enable_disk_events(struct scsi_device *sdev); -- cgit v1.2.3 From ef295ecf090d3e86e5b742fc6ab34f1122a43773 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 28 Oct 2016 08:48:16 -0600 Subject: block: better op and flags encoding Now that we don't need the common flags to overflow outside the range of a 32-bit type we can encode them the same way for both the bio and request fields. This in addition allows us to place the operation first (and make some room for more ops while we're at it) and to stop having to shift around the operation values. In addition this allows passing around only one value in the block layer instead of two (and eventuall also in the file systems, but we can do that later) and thus clean up a lot of code. Last but not least this allows decreasing the size of the cmd_flags field in struct request to 32-bits. Various functions passing this value could also be updated, but I'd like to avoid the churn for now. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- Documentation/block/biodoc.txt | 4 +- block/blk-core.c | 60 ++++++++++-------------------- block/blk-flush.c | 2 +- block/blk-lib.c | 2 +- block/blk-map.c | 2 + block/blk-mq.c | 28 ++++++-------- block/cfq-iosched.c | 66 ++++++++++++++++----------------- block/elevator.c | 4 +- drivers/md/dm-crypt.c | 2 +- drivers/scsi/sd.c | 3 +- fs/btrfs/inode.c | 5 +-- fs/buffer.c | 2 +- fs/f2fs/f2fs.h | 2 +- fs/gfs2/lops.c | 2 +- include/linux/blk-cgroup.h | 11 +++--- include/linux/blk_types.h | 83 +++++++++++++++++++----------------------- include/linux/blkdev.h | 26 +------------ include/linux/blktrace_api.h | 2 +- include/linux/dm-io.h | 2 +- include/linux/elevator.h | 4 +- include/trace/events/bcache.h | 12 ++---- include/trace/events/block.h | 31 ++++++---------- kernel/trace/blktrace.c | 14 +++---- 23 files changed, 148 insertions(+), 221 deletions(-) (limited to 'drivers') diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 6acea160298c..01ddeaf64b0f 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -553,8 +553,8 @@ struct request { struct request_list *rl; } -See the rq_flag_bits definitions for an explanation of the various flags -available. Some bits are used by the block layer or i/o scheduler. +See the req_ops and req_flag_bits definitions for an explanation of the various +flags available. Some bits are used by the block layer or i/o scheduler. The behaviour of the various sector counts are almost the same as before, except that since we have multi-segment bios, current_nr_sectors refers diff --git a/block/blk-core.c b/block/blk-core.c index fd416651a676..0bfaa54d3e9f 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1056,8 +1056,7 @@ static struct io_context *rq_ioc(struct bio *bio) /** * __get_request - get a free request * @rl: request list to allocate from - * @op: REQ_OP_READ/REQ_OP_WRITE - * @op_flags: rq_flag_bits + * @op: operation and flags * @bio: bio to allocate request for (can be %NULL) * @gfp_mask: allocation mask * @@ -1068,23 +1067,22 @@ static struct io_context *rq_ioc(struct bio *bio) * Returns ERR_PTR on failure, with @q->queue_lock held. * Returns request pointer on success, with @q->queue_lock *not held*. */ -static struct request *__get_request(struct request_list *rl, int op, - int op_flags, struct bio *bio, - gfp_t gfp_mask) +static struct request *__get_request(struct request_list *rl, unsigned int op, + struct bio *bio, gfp_t gfp_mask) { struct request_queue *q = rl->q; struct request *rq; struct elevator_type *et = q->elevator->type; struct io_context *ioc = rq_ioc(bio); struct io_cq *icq = NULL; - const bool is_sync = rw_is_sync(op, op_flags) != 0; + const bool is_sync = op_is_sync(op); int may_queue; req_flags_t rq_flags = RQF_ALLOCED; if (unlikely(blk_queue_dying(q))) return ERR_PTR(-ENODEV); - may_queue = elv_may_queue(q, op, op_flags); + may_queue = elv_may_queue(q, op); if (may_queue == ELV_MQUEUE_NO) goto rq_starved; @@ -1154,7 +1152,7 @@ static struct request *__get_request(struct request_list *rl, int op, blk_rq_init(q, rq); blk_rq_set_rl(rq, rl); - req_set_op_attrs(rq, op, op_flags); + rq->cmd_flags = op; rq->rq_flags = rq_flags; /* init elvpriv */ @@ -1232,8 +1230,7 @@ rq_starved: /** * get_request - get a free request * @q: request_queue to allocate request from - * @op: REQ_OP_READ/REQ_OP_WRITE - * @op_flags: rq_flag_bits + * @op: operation and flags * @bio: bio to allocate request for (can be %NULL) * @gfp_mask: allocation mask * @@ -1244,18 +1241,17 @@ rq_starved: * Returns ERR_PTR on failure, with @q->queue_lock held. * Returns request pointer on success, with @q->queue_lock *not held*. */ -static struct request *get_request(struct request_queue *q, int op, - int op_flags, struct bio *bio, - gfp_t gfp_mask) +static struct request *get_request(struct request_queue *q, unsigned int op, + struct bio *bio, gfp_t gfp_mask) { - const bool is_sync = rw_is_sync(op, op_flags) != 0; + const bool is_sync = op_is_sync(op); DEFINE_WAIT(wait); struct request_list *rl; struct request *rq; rl = blk_get_rl(q, bio); /* transferred to @rq on success */ retry: - rq = __get_request(rl, op, op_flags, bio, gfp_mask); + rq = __get_request(rl, op, bio, gfp_mask); if (!IS_ERR(rq)) return rq; @@ -1297,7 +1293,7 @@ static struct request *blk_old_get_request(struct request_queue *q, int rw, create_io_context(gfp_mask, q->node); spin_lock_irq(q->queue_lock); - rq = get_request(q, rw, 0, NULL, gfp_mask); + rq = get_request(q, rw, NULL, gfp_mask); if (IS_ERR(rq)) { spin_unlock_irq(q->queue_lock); return rq; @@ -1446,7 +1442,7 @@ void __blk_put_request(struct request_queue *q, struct request *req) */ if (rq_flags & RQF_ALLOCED) { struct request_list *rl = blk_rq_rl(req); - bool sync = rw_is_sync(req_op(req), req->cmd_flags); + bool sync = op_is_sync(req->cmd_flags); BUG_ON(!list_empty(&req->queuelist)); BUG_ON(ELV_ON_HASH(req)); @@ -1652,8 +1648,6 @@ out: void init_request_from_bio(struct request *req, struct bio *bio) { req->cmd_type = REQ_TYPE_FS; - - req->cmd_flags |= bio->bi_opf & REQ_COMMON_MASK; if (bio->bi_opf & REQ_RAHEAD) req->cmd_flags |= REQ_FAILFAST_MASK; @@ -1665,9 +1659,8 @@ void init_request_from_bio(struct request *req, struct bio *bio) static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio) { - const bool sync = !!(bio->bi_opf & REQ_SYNC); struct blk_plug *plug; - int el_ret, rw_flags = 0, where = ELEVATOR_INSERT_SORT; + int el_ret, where = ELEVATOR_INSERT_SORT; struct request *req; unsigned int request_count = 0; @@ -1722,24 +1715,11 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio) } get_rq: - /* - * This sync check and mask will be re-done in init_request_from_bio(), - * but we need to set it earlier to expose the sync flag to the - * rq allocator and io schedulers. - */ - if (sync) - rw_flags |= REQ_SYNC; - - /* - * Add in META/PRIO flags, if set, before we get to the IO scheduler - */ - rw_flags |= (bio->bi_opf & (REQ_META | REQ_PRIO)); - /* * Grab a free request. This is might sleep but can not fail. * Returns with the queue unlocked. */ - req = get_request(q, bio_data_dir(bio), rw_flags, bio, GFP_NOIO); + req = get_request(q, bio->bi_opf, bio, GFP_NOIO); if (IS_ERR(req)) { bio->bi_error = PTR_ERR(req); bio_endio(bio); @@ -2946,8 +2926,6 @@ EXPORT_SYMBOL_GPL(__blk_end_request_err); void blk_rq_bio_prep(struct request_queue *q, struct request *rq, struct bio *bio) { - req_set_op(rq, bio_op(bio)); - if (bio_has_data(bio)) rq->nr_phys_segments = bio_phys_segments(q, bio); @@ -3031,8 +3009,7 @@ EXPORT_SYMBOL_GPL(blk_rq_unprep_clone); static void __blk_rq_prep_clone(struct request *dst, struct request *src) { dst->cpu = src->cpu; - req_set_op_attrs(dst, req_op(src), - (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE); + dst->cmd_flags = src->cmd_flags | REQ_NOMERGE; dst->cmd_type = src->cmd_type; dst->__sector = blk_rq_pos(src); dst->__data_len = blk_rq_bytes(src); @@ -3537,8 +3514,11 @@ EXPORT_SYMBOL(blk_set_runtime_active); int __init blk_dev_init(void) { - BUILD_BUG_ON(__REQ_NR_BITS > 8 * + BUILD_BUG_ON(REQ_OP_LAST >= (1 << REQ_OP_BITS)); + BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 * FIELD_SIZEOF(struct request, cmd_flags)); + BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 * + FIELD_SIZEOF(struct bio, bi_opf)); /* used for unplugging and affects IO latency/throughput - HIGHPRI */ kblockd_workqueue = alloc_workqueue("kblockd", diff --git a/block/blk-flush.c b/block/blk-flush.c index 3990b9cfbda5..95f1d4d357df 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -330,7 +330,7 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq) } flush_rq->cmd_type = REQ_TYPE_FS; - req_set_op_attrs(flush_rq, REQ_OP_FLUSH, WRITE_FLUSH); + flush_rq->cmd_flags = REQ_OP_FLUSH | WRITE_FLUSH; flush_rq->rq_flags |= RQF_FLUSH_SEQ; flush_rq->rq_disk = first_rq->rq_disk; flush_rq->end_io = flush_end_io; diff --git a/block/blk-lib.c b/block/blk-lib.c index 46fe9248410d..18abda862915 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -29,7 +29,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, struct request_queue *q = bdev_get_queue(bdev); struct bio *bio = *biop; unsigned int granularity; - enum req_op op; + unsigned int op; int alignment; sector_t bs_mask; diff --git a/block/blk-map.c b/block/blk-map.c index 2c5ae5fef473..0173a72a8aa9 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -16,6 +16,8 @@ int blk_rq_append_bio(struct request *rq, struct bio *bio) { if (!rq->bio) { + rq->cmd_flags &= REQ_OP_MASK; + rq->cmd_flags |= (bio->bi_opf & REQ_OP_MASK); blk_rq_bio_prep(rq->q, rq, bio); } else { if (!ll_back_merge_fn(rq->q, rq, bio)) diff --git a/block/blk-mq.c b/block/blk-mq.c index b49c6658eb05..2da1a0ee3318 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -139,14 +139,13 @@ bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx) EXPORT_SYMBOL(blk_mq_can_queue); static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, - struct request *rq, int op, - unsigned int op_flags) + struct request *rq, unsigned int op) { INIT_LIST_HEAD(&rq->queuelist); /* csd/requeue_work/fifo_time is initialized before use */ rq->q = q; rq->mq_ctx = ctx; - req_set_op_attrs(rq, op, op_flags); + rq->cmd_flags = op; if (blk_queue_io_stat(q)) rq->rq_flags |= RQF_IO_STAT; /* do not touch atomic flags, it needs atomic ops against the timer */ @@ -183,11 +182,11 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, rq->end_io_data = NULL; rq->next_rq = NULL; - ctx->rq_dispatched[rw_is_sync(op, op_flags)]++; + ctx->rq_dispatched[op_is_sync(op)]++; } static struct request * -__blk_mq_alloc_request(struct blk_mq_alloc_data *data, int op, int op_flags) +__blk_mq_alloc_request(struct blk_mq_alloc_data *data, unsigned int op) { struct request *rq; unsigned int tag; @@ -202,7 +201,7 @@ __blk_mq_alloc_request(struct blk_mq_alloc_data *data, int op, int op_flags) } rq->tag = tag; - blk_mq_rq_ctx_init(data->q, data->ctx, rq, op, op_flags); + blk_mq_rq_ctx_init(data->q, data->ctx, rq, op); return rq; } @@ -225,7 +224,7 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw, ctx = blk_mq_get_ctx(q); hctx = blk_mq_map_queue(q, ctx->cpu); blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx); - rq = __blk_mq_alloc_request(&alloc_data, rw, 0); + rq = __blk_mq_alloc_request(&alloc_data, rw); blk_mq_put_ctx(ctx); if (!rq) { @@ -277,7 +276,7 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q, int rw, ctx = __blk_mq_get_ctx(q, cpumask_first(hctx->cpumask)); blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx); - rq = __blk_mq_alloc_request(&alloc_data, rw, 0); + rq = __blk_mq_alloc_request(&alloc_data, rw); if (!rq) { ret = -EWOULDBLOCK; goto out_queue_exit; @@ -1196,19 +1195,14 @@ static struct request *blk_mq_map_request(struct request_queue *q, struct blk_mq_hw_ctx *hctx; struct blk_mq_ctx *ctx; struct request *rq; - int op = bio_data_dir(bio); - int op_flags = 0; blk_queue_enter_live(q); ctx = blk_mq_get_ctx(q); hctx = blk_mq_map_queue(q, ctx->cpu); - if (rw_is_sync(bio_op(bio), bio->bi_opf)) - op_flags |= REQ_SYNC; - - trace_block_getrq(q, bio, op); + trace_block_getrq(q, bio, bio->bi_opf); blk_mq_set_alloc_data(data, q, 0, ctx, hctx); - rq = __blk_mq_alloc_request(data, op, op_flags); + rq = __blk_mq_alloc_request(data, bio->bi_opf); data->hctx->queued++; return rq; @@ -1256,7 +1250,7 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie) */ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) { - const int is_sync = rw_is_sync(bio_op(bio), bio->bi_opf); + const int is_sync = op_is_sync(bio->bi_opf); const int is_flush_fua = bio->bi_opf & (REQ_PREFLUSH | REQ_FUA); struct blk_mq_alloc_data data; struct request *rq; @@ -1350,7 +1344,7 @@ done: */ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio) { - const int is_sync = rw_is_sync(bio_op(bio), bio->bi_opf); + const int is_sync = op_is_sync(bio->bi_opf); const int is_flush_fua = bio->bi_opf & (REQ_PREFLUSH | REQ_FUA); struct blk_plug *plug; unsigned int request_count = 0; diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5e24d880306c..c96186adaa66 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -667,10 +667,10 @@ static inline void cfqg_put(struct cfq_group *cfqg) } while (0) static inline void cfqg_stats_update_io_add(struct cfq_group *cfqg, - struct cfq_group *curr_cfqg, int op, - int op_flags) + struct cfq_group *curr_cfqg, + unsigned int op) { - blkg_rwstat_add(&cfqg->stats.queued, op, op_flags, 1); + blkg_rwstat_add(&cfqg->stats.queued, op, 1); cfqg_stats_end_empty_time(&cfqg->stats); cfqg_stats_set_start_group_wait_time(cfqg, curr_cfqg); } @@ -684,30 +684,29 @@ static inline void cfqg_stats_update_timeslice_used(struct cfq_group *cfqg, #endif } -static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int op, - int op_flags) +static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, + unsigned int op) { - blkg_rwstat_add(&cfqg->stats.queued, op, op_flags, -1); + blkg_rwstat_add(&cfqg->stats.queued, op, -1); } -static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int op, - int op_flags) +static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, + unsigned int op) { - blkg_rwstat_add(&cfqg->stats.merged, op, op_flags, 1); + blkg_rwstat_add(&cfqg->stats.merged, op, 1); } static inline void cfqg_stats_update_completion(struct cfq_group *cfqg, - uint64_t start_time, uint64_t io_start_time, int op, - int op_flags) + uint64_t start_time, uint64_t io_start_time, + unsigned int op) { struct cfqg_stats *stats = &cfqg->stats; unsigned long long now = sched_clock(); if (time_after64(now, io_start_time)) - blkg_rwstat_add(&stats->service_time, op, op_flags, - now - io_start_time); + blkg_rwstat_add(&stats->service_time, op, now - io_start_time); if (time_after64(io_start_time, start_time)) - blkg_rwstat_add(&stats->wait_time, op, op_flags, + blkg_rwstat_add(&stats->wait_time, op, io_start_time - start_time); } @@ -786,16 +785,16 @@ static inline void cfqg_put(struct cfq_group *cfqg) { } #define cfq_log_cfqg(cfqd, cfqg, fmt, args...) do {} while (0) static inline void cfqg_stats_update_io_add(struct cfq_group *cfqg, - struct cfq_group *curr_cfqg, int op, int op_flags) { } + struct cfq_group *curr_cfqg, unsigned int op) { } static inline void cfqg_stats_update_timeslice_used(struct cfq_group *cfqg, uint64_t time, unsigned long unaccounted_time) { } -static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int op, - int op_flags) { } -static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int op, - int op_flags) { } +static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, + unsigned int op) { } +static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, + unsigned int op) { } static inline void cfqg_stats_update_completion(struct cfq_group *cfqg, - uint64_t start_time, uint64_t io_start_time, int op, - int op_flags) { } + uint64_t start_time, uint64_t io_start_time, + unsigned int op) { } #endif /* CONFIG_CFQ_GROUP_IOSCHED */ @@ -2474,10 +2473,10 @@ static void cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq) { elv_rb_del(&cfqq->sort_list, rq); cfqq->queued[rq_is_sync(rq)]--; - cfqg_stats_update_io_remove(RQ_CFQG(rq), req_op(rq), rq->cmd_flags); + cfqg_stats_update_io_remove(RQ_CFQG(rq), rq->cmd_flags); cfq_add_rq_rb(rq); cfqg_stats_update_io_add(RQ_CFQG(rq), cfqq->cfqd->serving_group, - req_op(rq), rq->cmd_flags); + rq->cmd_flags); } static struct request * @@ -2530,7 +2529,7 @@ static void cfq_remove_request(struct request *rq) cfq_del_rq_rb(rq); cfqq->cfqd->rq_queued--; - cfqg_stats_update_io_remove(RQ_CFQG(rq), req_op(rq), rq->cmd_flags); + cfqg_stats_update_io_remove(RQ_CFQG(rq), rq->cmd_flags); if (rq->cmd_flags & REQ_PRIO) { WARN_ON(!cfqq->prio_pending); cfqq->prio_pending--; @@ -2565,7 +2564,7 @@ static void cfq_merged_request(struct request_queue *q, struct request *req, static void cfq_bio_merged(struct request_queue *q, struct request *req, struct bio *bio) { - cfqg_stats_update_io_merged(RQ_CFQG(req), bio_op(bio), bio->bi_opf); + cfqg_stats_update_io_merged(RQ_CFQG(req), bio->bi_opf); } static void @@ -2588,7 +2587,7 @@ cfq_merged_requests(struct request_queue *q, struct request *rq, if (cfqq->next_rq == next) cfqq->next_rq = rq; cfq_remove_request(next); - cfqg_stats_update_io_merged(RQ_CFQG(rq), req_op(next), next->cmd_flags); + cfqg_stats_update_io_merged(RQ_CFQG(rq), next->cmd_flags); cfqq = RQ_CFQQ(next); /* @@ -4142,7 +4141,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) rq->fifo_time = ktime_get_ns() + cfqd->cfq_fifo_expire[rq_is_sync(rq)]; list_add_tail(&rq->queuelist, &cfqq->fifo); cfq_add_rq_rb(rq); - cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group, req_op(rq), + cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group, rq->cmd_flags); cfq_rq_enqueued(cfqd, cfqq, rq); } @@ -4240,8 +4239,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) cfqq->dispatched--; (RQ_CFQG(rq))->dispatched--; cfqg_stats_update_completion(cfqq->cfqg, rq_start_time_ns(rq), - rq_io_start_time_ns(rq), req_op(rq), - rq->cmd_flags); + rq_io_start_time_ns(rq), rq->cmd_flags); cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--; @@ -4319,14 +4317,14 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) cfq_schedule_dispatch(cfqd); } -static void cfqq_boost_on_prio(struct cfq_queue *cfqq, int op_flags) +static void cfqq_boost_on_prio(struct cfq_queue *cfqq, unsigned int op) { /* * If REQ_PRIO is set, boost class and prio level, if it's below * BE/NORM. If prio is not set, restore the potentially boosted * class/prio level. */ - if (!(op_flags & REQ_PRIO)) { + if (!(op & REQ_PRIO)) { cfqq->ioprio_class = cfqq->org_ioprio_class; cfqq->ioprio = cfqq->org_ioprio; } else { @@ -4347,7 +4345,7 @@ static inline int __cfq_may_queue(struct cfq_queue *cfqq) return ELV_MQUEUE_MAY; } -static int cfq_may_queue(struct request_queue *q, int op, int op_flags) +static int cfq_may_queue(struct request_queue *q, unsigned int op) { struct cfq_data *cfqd = q->elevator->elevator_data; struct task_struct *tsk = current; @@ -4364,10 +4362,10 @@ static int cfq_may_queue(struct request_queue *q, int op, int op_flags) if (!cic) return ELV_MQUEUE_MAY; - cfqq = cic_to_cfqq(cic, rw_is_sync(op, op_flags)); + cfqq = cic_to_cfqq(cic, op_is_sync(op)); if (cfqq) { cfq_init_prio_data(cfqq, cic); - cfqq_boost_on_prio(cfqq, op_flags); + cfqq_boost_on_prio(cfqq, op); return __cfq_may_queue(cfqq); } diff --git a/block/elevator.c b/block/elevator.c index ac80f89a0842..a18a5db274e4 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -714,12 +714,12 @@ void elv_put_request(struct request_queue *q, struct request *rq) e->type->ops.elevator_put_req_fn(rq); } -int elv_may_queue(struct request_queue *q, int op, int op_flags) +int elv_may_queue(struct request_queue *q, unsigned int op) { struct elevator_queue *e = q->elevator; if (e->type->ops.elevator_may_queue_fn) - return e->type->ops.elevator_may_queue_fn(q, op, op_flags); + return e->type->ops.elevator_may_queue_fn(q, op); return ELV_MQUEUE_MAY; } diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a2768835d394..68a9eb4f3f36 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1135,7 +1135,7 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone) clone->bi_private = io; clone->bi_end_io = crypt_endio; clone->bi_bdev = cc->dev->bdev; - bio_set_op_attrs(clone, bio_op(io->base_bio), bio_flags(io->base_bio)); + clone->bi_opf = io->base_bio->bi_opf; } static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cef1f78031d4..65738b0aad36 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1031,8 +1031,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_6; } else { - scmd_printk(KERN_ERR, SCpnt, "Unknown command %llu,%llx\n", - req_op(rq), (unsigned long long) rq->cmd_flags); + scmd_printk(KERN_ERR, SCpnt, "Unknown command %d\n", req_op(rq)); goto out; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2b790bda7998..9a377079af26 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -8427,7 +8427,7 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip, if (!bio) return -ENOMEM; - bio_set_op_attrs(bio, bio_op(orig_bio), bio_flags(orig_bio)); + bio->bi_opf = orig_bio->bi_opf; bio->bi_private = dip; bio->bi_end_io = btrfs_end_dio_bio; btrfs_io_bio(bio)->logical = file_offset; @@ -8465,8 +8465,7 @@ next_block: start_sector, GFP_NOFS); if (!bio) goto out_err; - bio_set_op_attrs(bio, bio_op(orig_bio), - bio_flags(orig_bio)); + bio->bi_opf = orig_bio->bi_opf; bio->bi_private = dip; bio->bi_end_io = btrfs_end_dio_bio; btrfs_io_bio(bio)->logical = file_offset; diff --git a/fs/buffer.c b/fs/buffer.c index b205a629001d..a29335867e30 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -3118,7 +3118,7 @@ EXPORT_SYMBOL(submit_bh); /** * ll_rw_block: low-level access to block devices (DEPRECATED) * @op: whether to %READ or %WRITE - * @op_flags: rq_flag_bits + * @op_flags: req_flag_bits * @nr: number of &struct buffer_heads in the array * @bhs: array of pointers to &struct buffer_head * diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 9e8de18a168a..2cf4f7f09e32 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -688,7 +688,7 @@ struct f2fs_io_info { struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */ enum page_type type; /* contains DATA/NODE/META/META_FLUSH */ int op; /* contains REQ_OP_ */ - int op_flags; /* rq_flag_bits */ + int op_flags; /* req_flag_bits */ block_t new_blkaddr; /* new block address to be written */ block_t old_blkaddr; /* old block address before Cow */ struct page *page; /* page to be written */ diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 49d5a1b61b06..b1f9144b42c7 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -231,7 +231,7 @@ static void gfs2_end_log_write(struct bio *bio) * gfs2_log_flush_bio - Submit any pending log bio * @sdp: The superblock * @op: REQ_OP - * @op_flags: rq_flag_bits + * @op_flags: req_flag_bits * * Submit any pending part-built or full bio to the block device. If * there is no pending bio, then this is a no-op. diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index 3bf5d33800ab..ddaf28d0988f 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h @@ -581,15 +581,14 @@ static inline void blkg_rwstat_exit(struct blkg_rwstat *rwstat) /** * blkg_rwstat_add - add a value to a blkg_rwstat * @rwstat: target blkg_rwstat - * @op: REQ_OP - * @op_flags: rq_flag_bits + * @op: REQ_OP and flags * @val: value to add * * Add @val to @rwstat. The counters are chosen according to @rw. The * caller is responsible for synchronizing calls to this function. */ static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, - int op, int op_flags, uint64_t val) + unsigned int op, uint64_t val) { struct percpu_counter *cnt; @@ -600,7 +599,7 @@ static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, __percpu_counter_add(cnt, val, BLKG_STAT_CPU_BATCH); - if (op_flags & REQ_SYNC) + if (op & REQ_SYNC) cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_SYNC]; else cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_ASYNC]; @@ -705,9 +704,9 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q, if (!throtl) { blkg = blkg ?: q->root_blkg; - blkg_rwstat_add(&blkg->stat_bytes, bio_op(bio), bio->bi_opf, + blkg_rwstat_add(&blkg->stat_bytes, bio->bi_opf, bio->bi_iter.bi_size); - blkg_rwstat_add(&blkg->stat_ios, bio_op(bio), bio->bi_opf, 1); + blkg_rwstat_add(&blkg->stat_ios, bio->bi_opf, 1); } rcu_read_unlock(); diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index ec69a8fe3b29..dca972d67548 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -88,24 +88,6 @@ struct bio { struct bio_vec bi_inline_vecs[0]; }; -#define BIO_OP_SHIFT (8 * FIELD_SIZEOF(struct bio, bi_opf) - REQ_OP_BITS) -#define bio_flags(bio) ((bio)->bi_opf & ((1 << BIO_OP_SHIFT) - 1)) -#define bio_op(bio) ((bio)->bi_opf >> BIO_OP_SHIFT) - -#define bio_set_op_attrs(bio, op, op_flags) do { \ - if (__builtin_constant_p(op)) \ - BUILD_BUG_ON((op) + 0U >= (1U << REQ_OP_BITS)); \ - else \ - WARN_ON_ONCE((op) + 0U >= (1U << REQ_OP_BITS)); \ - if (__builtin_constant_p(op_flags)) \ - BUILD_BUG_ON((op_flags) + 0U >= (1U << BIO_OP_SHIFT)); \ - else \ - WARN_ON_ONCE((op_flags) + 0U >= (1U << BIO_OP_SHIFT)); \ - (bio)->bi_opf = bio_flags(bio); \ - (bio)->bi_opf |= (((op) + 0U) << BIO_OP_SHIFT); \ - (bio)->bi_opf |= (op_flags); \ -} while (0) - #define BIO_RESET_BYTES offsetof(struct bio, bi_max_vecs) /* @@ -147,26 +129,40 @@ struct bio { #endif /* CONFIG_BLOCK */ /* - * Request flags. For use in the cmd_flags field of struct request, and in - * bi_opf of struct bio. Note that some flags are only valid in either one. + * Operations and flags common to the bio and request structures. + * We use 8 bits for encoding the operation, and the remaining 24 for flags. */ -enum rq_flag_bits { - /* common flags */ - __REQ_FAILFAST_DEV, /* no driver retries of device errors */ +#define REQ_OP_BITS 8 +#define REQ_OP_MASK ((1 << REQ_OP_BITS) - 1) +#define REQ_FLAG_BITS 24 + +enum req_opf { + REQ_OP_READ, + REQ_OP_WRITE, + REQ_OP_DISCARD, /* request to discard sectors */ + REQ_OP_SECURE_ERASE, /* request to securely erase sectors */ + REQ_OP_WRITE_SAME, /* write same block many times */ + REQ_OP_FLUSH, /* request for cache flush */ + REQ_OP_ZONE_REPORT, /* Get zone information */ + REQ_OP_ZONE_RESET, /* Reset a zone write pointer */ + + REQ_OP_LAST, +}; + +enum req_flag_bits { + __REQ_FAILFAST_DEV = /* no driver retries of device errors */ + REQ_OP_BITS, __REQ_FAILFAST_TRANSPORT, /* no driver retries of transport errors */ __REQ_FAILFAST_DRIVER, /* no driver retries of driver errors */ - __REQ_SYNC, /* request is sync (sync write or read) */ __REQ_META, /* metadata io request */ __REQ_PRIO, /* boost priority in cfq */ - __REQ_NOMERGE, /* don't touch this for merging */ __REQ_NOIDLE, /* don't anticipate more IO after this one */ __REQ_INTEGRITY, /* I/O includes block integrity payload */ __REQ_FUA, /* forced unit access */ __REQ_PREFLUSH, /* request for cache flush */ __REQ_RAHEAD, /* read ahead, can fail anytime */ - __REQ_NR_BITS, /* stops here */ }; @@ -176,37 +172,32 @@ enum rq_flag_bits { #define REQ_SYNC (1ULL << __REQ_SYNC) #define REQ_META (1ULL << __REQ_META) #define REQ_PRIO (1ULL << __REQ_PRIO) +#define REQ_NOMERGE (1ULL << __REQ_NOMERGE) #define REQ_NOIDLE (1ULL << __REQ_NOIDLE) #define REQ_INTEGRITY (1ULL << __REQ_INTEGRITY) +#define REQ_FUA (1ULL << __REQ_FUA) +#define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH) +#define REQ_RAHEAD (1ULL << __REQ_RAHEAD) #define REQ_FAILFAST_MASK \ (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) -#define REQ_COMMON_MASK \ - (REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | REQ_NOIDLE | \ - REQ_PREFLUSH | REQ_FUA | REQ_INTEGRITY | REQ_NOMERGE | REQ_RAHEAD) -#define REQ_CLONE_MASK REQ_COMMON_MASK -/* This mask is used for both bio and request merge checking */ #define REQ_NOMERGE_FLAGS \ (REQ_NOMERGE | REQ_PREFLUSH | REQ_FUA) -#define REQ_RAHEAD (1ULL << __REQ_RAHEAD) -#define REQ_FUA (1ULL << __REQ_FUA) -#define REQ_NOMERGE (1ULL << __REQ_NOMERGE) -#define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH) +#define bio_op(bio) \ + ((bio)->bi_opf & REQ_OP_MASK) +#define req_op(req) \ + ((req)->cmd_flags & REQ_OP_MASK) -enum req_op { - REQ_OP_READ, - REQ_OP_WRITE, - REQ_OP_DISCARD, /* request to discard sectors */ - REQ_OP_SECURE_ERASE, /* request to securely erase sectors */ - REQ_OP_WRITE_SAME, /* write same block many times */ - REQ_OP_FLUSH, /* request for cache flush */ - REQ_OP_ZONE_REPORT, /* Get zone information */ - REQ_OP_ZONE_RESET, /* Reset a zone write pointer */ -}; +/* obsolete, don't use in new code */ +#define bio_set_op_attrs(bio, op, op_flags) \ + ((bio)->bi_opf |= (op | op_flags)) -#define REQ_OP_BITS 3 +static inline bool op_is_sync(unsigned int op) +{ + return (op & REQ_OP_MASK) == REQ_OP_READ || (op & REQ_SYNC); +} typedef unsigned int blk_qc_t; #define BLK_QC_T_NONE -1U diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index b4415feac679..8396da2bb698 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -142,7 +142,7 @@ struct request { int cpu; unsigned cmd_type; - u64 cmd_flags; + unsigned int cmd_flags; /* op and common flags */ req_flags_t rq_flags; unsigned long atomic_flags; @@ -244,20 +244,6 @@ struct request { struct request *next_rq; }; -#define REQ_OP_SHIFT (8 * sizeof(u64) - REQ_OP_BITS) -#define req_op(req) ((req)->cmd_flags >> REQ_OP_SHIFT) - -#define req_set_op(req, op) do { \ - WARN_ON(op >= (1 << REQ_OP_BITS)); \ - (req)->cmd_flags &= ((1ULL << REQ_OP_SHIFT) - 1); \ - (req)->cmd_flags |= ((u64) (op) << REQ_OP_SHIFT); \ -} while (0) - -#define req_set_op_attrs(req, op, flags) do { \ - req_set_op(req, op); \ - (req)->cmd_flags |= flags; \ -} while (0) - static inline unsigned short req_get_ioprio(struct request *req) { return req->ioprio; @@ -741,17 +727,9 @@ static inline unsigned int blk_queue_zone_size(struct request_queue *q) return blk_queue_is_zoned(q) ? q->limits.chunk_sectors : 0; } -/* - * We regard a request as sync, if either a read or a sync write - */ -static inline bool rw_is_sync(int op, unsigned int rw_flags) -{ - return op == REQ_OP_READ || (rw_flags & REQ_SYNC); -} - static inline bool rq_is_sync(struct request *rq) { - return rw_is_sync(req_op(rq), rq->cmd_flags); + return op_is_sync(rq->cmd_flags); } static inline bool blk_rl_full(struct request_list *rl, bool sync) diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index cceb72f9e29f..e417f080219a 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -118,7 +118,7 @@ static inline int blk_cmd_buf_len(struct request *rq) } extern void blk_dump_cmd(char *buf, struct request *rq); -extern void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes); +extern void blk_fill_rwbs(char *rwbs, unsigned int op, int bytes); #endif /* CONFIG_EVENT_TRACING && CONFIG_BLOCK */ diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h index b91b023deffb..a52c6580cc9a 100644 --- a/include/linux/dm-io.h +++ b/include/linux/dm-io.h @@ -58,7 +58,7 @@ struct dm_io_notify { struct dm_io_client; struct dm_io_request { int bi_op; /* REQ_OP */ - int bi_op_flags; /* rq_flag_bits */ + int bi_op_flags; /* req_flag_bits */ struct dm_io_memory mem; /* Memory to use for io */ struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */ struct dm_io_client *client; /* Client memory handler */ diff --git a/include/linux/elevator.h b/include/linux/elevator.h index e7f358d2e5fc..f219c9aed360 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -30,7 +30,7 @@ typedef int (elevator_dispatch_fn) (struct request_queue *, int); typedef void (elevator_add_req_fn) (struct request_queue *, struct request *); typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *); typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *); -typedef int (elevator_may_queue_fn) (struct request_queue *, int, int); +typedef int (elevator_may_queue_fn) (struct request_queue *, unsigned int); typedef void (elevator_init_icq_fn) (struct io_cq *); typedef void (elevator_exit_icq_fn) (struct io_cq *); @@ -139,7 +139,7 @@ extern struct request *elv_former_request(struct request_queue *, struct request extern struct request *elv_latter_request(struct request_queue *, struct request *); extern int elv_register_queue(struct request_queue *q); extern void elv_unregister_queue(struct request_queue *q); -extern int elv_may_queue(struct request_queue *, int, int); +extern int elv_may_queue(struct request_queue *, unsigned int); extern void elv_completed_request(struct request_queue *, struct request *); extern int elv_set_request(struct request_queue *q, struct request *rq, struct bio *bio, gfp_t gfp_mask); diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h index d336b890e31f..df3e9ae5ad8d 100644 --- a/include/trace/events/bcache.h +++ b/include/trace/events/bcache.h @@ -27,8 +27,7 @@ DECLARE_EVENT_CLASS(bcache_request, __entry->sector = bio->bi_iter.bi_sector; __entry->orig_sector = bio->bi_iter.bi_sector - 16; __entry->nr_sector = bio->bi_iter.bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u (from %d,%d @ %llu)", @@ -102,8 +101,7 @@ DECLARE_EVENT_CLASS(bcache_bio, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio->bi_iter.bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u", @@ -138,8 +136,7 @@ TRACE_EVENT(bcache_read, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio->bi_iter.bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); __entry->cache_hit = hit; __entry->bypass = bypass; ), @@ -170,8 +167,7 @@ TRACE_EVENT(bcache_write, __entry->inode = inode; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio->bi_iter.bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); __entry->writeback = writeback; __entry->bypass = bypass; ), diff --git a/include/trace/events/block.h b/include/trace/events/block.h index 8f3a163b8166..3e02e3a25413 100644 --- a/include/trace/events/block.h +++ b/include/trace/events/block.h @@ -84,8 +84,7 @@ DECLARE_EVENT_CLASS(block_rq_with_error, 0 : blk_rq_sectors(rq); __entry->errors = rq->errors; - blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, - blk_rq_bytes(rq)); + blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); blk_dump_cmd(__get_str(cmd), rq); ), @@ -163,7 +162,7 @@ TRACE_EVENT(block_rq_complete, __entry->nr_sector = nr_bytes >> 9; __entry->errors = rq->errors; - blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, nr_bytes); + blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, nr_bytes); blk_dump_cmd(__get_str(cmd), rq); ), @@ -199,8 +198,7 @@ DECLARE_EVENT_CLASS(block_rq, __entry->bytes = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? blk_rq_bytes(rq) : 0; - blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, - blk_rq_bytes(rq)); + blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); blk_dump_cmd(__get_str(cmd), rq); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -274,8 +272,7 @@ TRACE_EVENT(block_bio_bounce, bio->bi_bdev->bd_dev : 0; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -313,8 +310,7 @@ TRACE_EVENT(block_bio_complete, __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); __entry->error = error; - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u [%d]", @@ -341,8 +337,7 @@ DECLARE_EVENT_CLASS(block_bio_merge, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -409,8 +404,7 @@ TRACE_EVENT(block_bio_queue, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -438,7 +432,7 @@ DECLARE_EVENT_CLASS(block_get_rq, __entry->dev = bio ? bio->bi_bdev->bd_dev : 0; __entry->sector = bio ? bio->bi_iter.bi_sector : 0; __entry->nr_sector = bio ? bio_sectors(bio) : 0; - blk_fill_rwbs(__entry->rwbs, bio ? bio_op(bio) : 0, + blk_fill_rwbs(__entry->rwbs, bio ? bio->bi_opf : 0, __entry->nr_sector); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -573,8 +567,7 @@ TRACE_EVENT(block_split, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->new_sector = new_sector; - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -617,8 +610,7 @@ TRACE_EVENT(block_bio_remap, __entry->nr_sector = bio_sectors(bio); __entry->old_dev = dev; __entry->old_sector = from; - blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf, - bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu", @@ -664,8 +656,7 @@ TRACE_EVENT(block_rq_remap, __entry->old_dev = dev; __entry->old_sector = from; __entry->nr_bios = blk_rq_count_bios(rq); - blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, - blk_rq_bytes(rq)); + blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); ), TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu %u", diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index dbafc5df03f3..95cecbf67f5c 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -1777,14 +1777,14 @@ void blk_dump_cmd(char *buf, struct request *rq) } } -void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes) +void blk_fill_rwbs(char *rwbs, unsigned int op, int bytes) { int i = 0; - if (rw & REQ_PREFLUSH) + if (op & REQ_PREFLUSH) rwbs[i++] = 'F'; - switch (op) { + switch (op & REQ_OP_MASK) { case REQ_OP_WRITE: case REQ_OP_WRITE_SAME: rwbs[i++] = 'W'; @@ -1806,13 +1806,13 @@ void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes) rwbs[i++] = 'N'; } - if (rw & REQ_FUA) + if (op & REQ_FUA) rwbs[i++] = 'F'; - if (rw & REQ_RAHEAD) + if (op & REQ_RAHEAD) rwbs[i++] = 'A'; - if (rw & REQ_SYNC) + if (op & REQ_SYNC) rwbs[i++] = 'S'; - if (rw & REQ_META) + if (op & REQ_META) rwbs[i++] = 'M'; rwbs[i] = '\0'; -- cgit v1.2.3 From 8c9583a81cd3fb51eff26a1459d00ffa5fdd4dbd Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 27 Oct 2016 15:12:57 +0200 Subject: mlxsw: spectrum: Remove extra whitespace Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 113f667e59df..107934fe06ce 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -1980,7 +1980,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp) if (err) goto err_vrs_init; - err = mlxsw_sp_neigh_init(mlxsw_sp); + err = mlxsw_sp_neigh_init(mlxsw_sp); if (err) goto err_neigh_init; -- cgit v1.2.3 From 62e86f9e828128ce6452a2d8ab4a26609885dda6 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 27 Oct 2016 15:12:58 +0200 Subject: mlxsw: pci: Rename header with HW definitions pci.h needs to be used for inner function declarations. So move the original one to more appropriate name, pci_hw.h. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/pci.h | 231 --------------------------- drivers/net/ethernet/mellanox/mlxsw/pci_hw.h | 231 +++++++++++++++++++++++++++ 3 files changed, 232 insertions(+), 232 deletions(-) delete mode 100644 drivers/net/ethernet/mellanox/mlxsw/pci.h create mode 100644 drivers/net/ethernet/mellanox/mlxsw/pci_hw.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index c88f2ab90a39..209630c98ef7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -48,7 +48,7 @@ #include #include -#include "pci.h" +#include "pci_hw.h" #include "core.h" #include "cmd.h" #include "port.h" diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h deleted file mode 100644 index d942a3e6fa41..000000000000 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * drivers/net/ethernet/mellanox/mlxsw/pci.h - * Copyright (c) 2015 Mellanox Technologies. All rights reserved. - * Copyright (c) 2015 Jiri Pirko - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MLXSW_PCI_H -#define _MLXSW_PCI_H - -#include - -#include "item.h" - -#define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738 -#define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84 -#define MLXSW_PCI_BAR0_SIZE (1024 * 1024) /* 1MB */ -#define MLXSW_PCI_PAGE_SIZE 4096 - -#define MLXSW_PCI_CIR_BASE 0x71000 -#define MLXSW_PCI_CIR_IN_PARAM_HI MLXSW_PCI_CIR_BASE -#define MLXSW_PCI_CIR_IN_PARAM_LO (MLXSW_PCI_CIR_BASE + 0x04) -#define MLXSW_PCI_CIR_IN_MODIFIER (MLXSW_PCI_CIR_BASE + 0x08) -#define MLXSW_PCI_CIR_OUT_PARAM_HI (MLXSW_PCI_CIR_BASE + 0x0C) -#define MLXSW_PCI_CIR_OUT_PARAM_LO (MLXSW_PCI_CIR_BASE + 0x10) -#define MLXSW_PCI_CIR_TOKEN (MLXSW_PCI_CIR_BASE + 0x14) -#define MLXSW_PCI_CIR_CTRL (MLXSW_PCI_CIR_BASE + 0x18) -#define MLXSW_PCI_CIR_CTRL_GO_BIT BIT(23) -#define MLXSW_PCI_CIR_CTRL_EVREQ_BIT BIT(22) -#define MLXSW_PCI_CIR_CTRL_OPCODE_MOD_SHIFT 12 -#define MLXSW_PCI_CIR_CTRL_STATUS_SHIFT 24 -#define MLXSW_PCI_CIR_TIMEOUT_MSECS 1000 - -#define MLXSW_PCI_SW_RESET 0xF0010 -#define MLXSW_PCI_SW_RESET_RST_BIT BIT(0) -#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 5000 -#define MLXSW_PCI_FW_READY 0xA1844 -#define MLXSW_PCI_FW_READY_MASK 0xFF -#define MLXSW_PCI_FW_READY_MAGIC 0x5E - -#define MLXSW_PCI_DOORBELL_SDQ_OFFSET 0x000 -#define MLXSW_PCI_DOORBELL_RDQ_OFFSET 0x200 -#define MLXSW_PCI_DOORBELL_CQ_OFFSET 0x400 -#define MLXSW_PCI_DOORBELL_EQ_OFFSET 0x600 -#define MLXSW_PCI_DOORBELL_ARM_CQ_OFFSET 0x800 -#define MLXSW_PCI_DOORBELL_ARM_EQ_OFFSET 0xA00 - -#define MLXSW_PCI_DOORBELL(offset, type_offset, num) \ - ((offset) + (type_offset) + (num) * 4) - -#define MLXSW_PCI_CQS_MAX 96 -#define MLXSW_PCI_EQS_COUNT 2 -#define MLXSW_PCI_EQ_ASYNC_NUM 0 -#define MLXSW_PCI_EQ_COMP_NUM 1 - -#define MLXSW_PCI_AQ_PAGES 8 -#define MLXSW_PCI_AQ_SIZE (MLXSW_PCI_PAGE_SIZE * MLXSW_PCI_AQ_PAGES) -#define MLXSW_PCI_WQE_SIZE 32 /* 32 bytes per element */ -#define MLXSW_PCI_CQE_SIZE 16 /* 16 bytes per element */ -#define MLXSW_PCI_EQE_SIZE 16 /* 16 bytes per element */ -#define MLXSW_PCI_WQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE) -#define MLXSW_PCI_CQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE_SIZE) -#define MLXSW_PCI_EQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_EQE_SIZE) -#define MLXSW_PCI_EQE_UPDATE_COUNT 0x80 - -#define MLXSW_PCI_WQE_SG_ENTRIES 3 -#define MLXSW_PCI_WQE_TYPE_ETHERNET 0xA - -/* pci_wqe_c - * If set it indicates that a completion should be reported upon - * execution of this descriptor. - */ -MLXSW_ITEM32(pci, wqe, c, 0x00, 31, 1); - -/* pci_wqe_lp - * Local Processing, set if packet should be processed by the local - * switch hardware: - * For Ethernet EMAD (Direct Route and non Direct Route) - - * must be set if packet destination is local device - * For InfiniBand CTL - must be set if packet destination is local device - * Otherwise it must be clear - * Local Process packets must not exceed the size of 2K (including payload - * and headers). - */ -MLXSW_ITEM32(pci, wqe, lp, 0x00, 30, 1); - -/* pci_wqe_type - * Packet type. - */ -MLXSW_ITEM32(pci, wqe, type, 0x00, 23, 4); - -/* pci_wqe_byte_count - * Size of i-th scatter/gather entry, 0 if entry is unused. - */ -MLXSW_ITEM16_INDEXED(pci, wqe, byte_count, 0x02, 0, 14, 0x02, 0x00, false); - -/* pci_wqe_address - * Physical address of i-th scatter/gather entry. - * Gather Entries must be 2Byte aligned. - */ -MLXSW_ITEM64_INDEXED(pci, wqe, address, 0x08, 0, 64, 0x8, 0x0, false); - -/* pci_cqe_lag - * Packet arrives from a port which is a LAG - */ -MLXSW_ITEM32(pci, cqe, lag, 0x00, 23, 1); - -/* pci_cqe_system_port/lag_id - * When lag=0: System port on which the packet was received - * When lag=1: - * bits [15:4] LAG ID on which the packet was received - * bits [3:0] sub_port on which the packet was received - */ -MLXSW_ITEM32(pci, cqe, system_port, 0x00, 0, 16); -MLXSW_ITEM32(pci, cqe, lag_id, 0x00, 4, 12); -MLXSW_ITEM32(pci, cqe, lag_port_index, 0x00, 0, 4); - -/* pci_cqe_wqe_counter - * WQE count of the WQEs completed on the associated dqn - */ -MLXSW_ITEM32(pci, cqe, wqe_counter, 0x04, 16, 16); - -/* pci_cqe_byte_count - * Byte count of received packets including additional two - * Reserved Bytes that are append to the end of the frame. - * Reserved for Send CQE. - */ -MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14); - -/* pci_cqe_trap_id - * Trap ID that captured the packet. - */ -MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 8); - -/* pci_cqe_crc - * Length include CRC. Indicates the length field includes - * the packet's CRC. - */ -MLXSW_ITEM32(pci, cqe, crc, 0x0C, 8, 1); - -/* pci_cqe_e - * CQE with Error. - */ -MLXSW_ITEM32(pci, cqe, e, 0x0C, 7, 1); - -/* pci_cqe_sr - * 1 - Send Queue - * 0 - Receive Queue - */ -MLXSW_ITEM32(pci, cqe, sr, 0x0C, 6, 1); - -/* pci_cqe_dqn - * Descriptor Queue (DQ) Number. - */ -MLXSW_ITEM32(pci, cqe, dqn, 0x0C, 1, 5); - -/* pci_cqe_owner - * Ownership bit. - */ -MLXSW_ITEM32(pci, cqe, owner, 0x0C, 0, 1); - -/* pci_eqe_event_type - * Event type. - */ -MLXSW_ITEM32(pci, eqe, event_type, 0x0C, 24, 8); -#define MLXSW_PCI_EQE_EVENT_TYPE_COMP 0x00 -#define MLXSW_PCI_EQE_EVENT_TYPE_CMD 0x0A - -/* pci_eqe_event_sub_type - * Event type. - */ -MLXSW_ITEM32(pci, eqe, event_sub_type, 0x0C, 16, 8); - -/* pci_eqe_cqn - * Completion Queue that triggeret this EQE. - */ -MLXSW_ITEM32(pci, eqe, cqn, 0x0C, 8, 7); - -/* pci_eqe_owner - * Ownership bit. - */ -MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1); - -/* pci_eqe_cmd_token - * Command completion event - token - */ -MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16); - -/* pci_eqe_cmd_status - * Command completion event - status - */ -MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8); - -/* pci_eqe_cmd_out_param_h - * Command completion event - output parameter - higher part - */ -MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32); - -/* pci_eqe_cmd_out_param_l - * Command completion event - output parameter - lower part - */ -MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32); - -#endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h new file mode 100644 index 000000000000..45bc19790be4 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h @@ -0,0 +1,231 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/pci_hw.h + * Copyright (c) 2015-2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2015-2016 Jiri Pirko + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MLXSW_PCI_HW_H +#define _MLXSW_PCI_HW_H + +#include + +#include "item.h" + +#define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738 +#define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84 +#define MLXSW_PCI_BAR0_SIZE (1024 * 1024) /* 1MB */ +#define MLXSW_PCI_PAGE_SIZE 4096 + +#define MLXSW_PCI_CIR_BASE 0x71000 +#define MLXSW_PCI_CIR_IN_PARAM_HI MLXSW_PCI_CIR_BASE +#define MLXSW_PCI_CIR_IN_PARAM_LO (MLXSW_PCI_CIR_BASE + 0x04) +#define MLXSW_PCI_CIR_IN_MODIFIER (MLXSW_PCI_CIR_BASE + 0x08) +#define MLXSW_PCI_CIR_OUT_PARAM_HI (MLXSW_PCI_CIR_BASE + 0x0C) +#define MLXSW_PCI_CIR_OUT_PARAM_LO (MLXSW_PCI_CIR_BASE + 0x10) +#define MLXSW_PCI_CIR_TOKEN (MLXSW_PCI_CIR_BASE + 0x14) +#define MLXSW_PCI_CIR_CTRL (MLXSW_PCI_CIR_BASE + 0x18) +#define MLXSW_PCI_CIR_CTRL_GO_BIT BIT(23) +#define MLXSW_PCI_CIR_CTRL_EVREQ_BIT BIT(22) +#define MLXSW_PCI_CIR_CTRL_OPCODE_MOD_SHIFT 12 +#define MLXSW_PCI_CIR_CTRL_STATUS_SHIFT 24 +#define MLXSW_PCI_CIR_TIMEOUT_MSECS 1000 + +#define MLXSW_PCI_SW_RESET 0xF0010 +#define MLXSW_PCI_SW_RESET_RST_BIT BIT(0) +#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 5000 +#define MLXSW_PCI_FW_READY 0xA1844 +#define MLXSW_PCI_FW_READY_MASK 0xFF +#define MLXSW_PCI_FW_READY_MAGIC 0x5E + +#define MLXSW_PCI_DOORBELL_SDQ_OFFSET 0x000 +#define MLXSW_PCI_DOORBELL_RDQ_OFFSET 0x200 +#define MLXSW_PCI_DOORBELL_CQ_OFFSET 0x400 +#define MLXSW_PCI_DOORBELL_EQ_OFFSET 0x600 +#define MLXSW_PCI_DOORBELL_ARM_CQ_OFFSET 0x800 +#define MLXSW_PCI_DOORBELL_ARM_EQ_OFFSET 0xA00 + +#define MLXSW_PCI_DOORBELL(offset, type_offset, num) \ + ((offset) + (type_offset) + (num) * 4) + +#define MLXSW_PCI_CQS_MAX 96 +#define MLXSW_PCI_EQS_COUNT 2 +#define MLXSW_PCI_EQ_ASYNC_NUM 0 +#define MLXSW_PCI_EQ_COMP_NUM 1 + +#define MLXSW_PCI_AQ_PAGES 8 +#define MLXSW_PCI_AQ_SIZE (MLXSW_PCI_PAGE_SIZE * MLXSW_PCI_AQ_PAGES) +#define MLXSW_PCI_WQE_SIZE 32 /* 32 bytes per element */ +#define MLXSW_PCI_CQE_SIZE 16 /* 16 bytes per element */ +#define MLXSW_PCI_EQE_SIZE 16 /* 16 bytes per element */ +#define MLXSW_PCI_WQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE) +#define MLXSW_PCI_CQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE_SIZE) +#define MLXSW_PCI_EQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_EQE_SIZE) +#define MLXSW_PCI_EQE_UPDATE_COUNT 0x80 + +#define MLXSW_PCI_WQE_SG_ENTRIES 3 +#define MLXSW_PCI_WQE_TYPE_ETHERNET 0xA + +/* pci_wqe_c + * If set it indicates that a completion should be reported upon + * execution of this descriptor. + */ +MLXSW_ITEM32(pci, wqe, c, 0x00, 31, 1); + +/* pci_wqe_lp + * Local Processing, set if packet should be processed by the local + * switch hardware: + * For Ethernet EMAD (Direct Route and non Direct Route) - + * must be set if packet destination is local device + * For InfiniBand CTL - must be set if packet destination is local device + * Otherwise it must be clear + * Local Process packets must not exceed the size of 2K (including payload + * and headers). + */ +MLXSW_ITEM32(pci, wqe, lp, 0x00, 30, 1); + +/* pci_wqe_type + * Packet type. + */ +MLXSW_ITEM32(pci, wqe, type, 0x00, 23, 4); + +/* pci_wqe_byte_count + * Size of i-th scatter/gather entry, 0 if entry is unused. + */ +MLXSW_ITEM16_INDEXED(pci, wqe, byte_count, 0x02, 0, 14, 0x02, 0x00, false); + +/* pci_wqe_address + * Physical address of i-th scatter/gather entry. + * Gather Entries must be 2Byte aligned. + */ +MLXSW_ITEM64_INDEXED(pci, wqe, address, 0x08, 0, 64, 0x8, 0x0, false); + +/* pci_cqe_lag + * Packet arrives from a port which is a LAG + */ +MLXSW_ITEM32(pci, cqe, lag, 0x00, 23, 1); + +/* pci_cqe_system_port/lag_id + * When lag=0: System port on which the packet was received + * When lag=1: + * bits [15:4] LAG ID on which the packet was received + * bits [3:0] sub_port on which the packet was received + */ +MLXSW_ITEM32(pci, cqe, system_port, 0x00, 0, 16); +MLXSW_ITEM32(pci, cqe, lag_id, 0x00, 4, 12); +MLXSW_ITEM32(pci, cqe, lag_port_index, 0x00, 0, 4); + +/* pci_cqe_wqe_counter + * WQE count of the WQEs completed on the associated dqn + */ +MLXSW_ITEM32(pci, cqe, wqe_counter, 0x04, 16, 16); + +/* pci_cqe_byte_count + * Byte count of received packets including additional two + * Reserved Bytes that are append to the end of the frame. + * Reserved for Send CQE. + */ +MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14); + +/* pci_cqe_trap_id + * Trap ID that captured the packet. + */ +MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 8); + +/* pci_cqe_crc + * Length include CRC. Indicates the length field includes + * the packet's CRC. + */ +MLXSW_ITEM32(pci, cqe, crc, 0x0C, 8, 1); + +/* pci_cqe_e + * CQE with Error. + */ +MLXSW_ITEM32(pci, cqe, e, 0x0C, 7, 1); + +/* pci_cqe_sr + * 1 - Send Queue + * 0 - Receive Queue + */ +MLXSW_ITEM32(pci, cqe, sr, 0x0C, 6, 1); + +/* pci_cqe_dqn + * Descriptor Queue (DQ) Number. + */ +MLXSW_ITEM32(pci, cqe, dqn, 0x0C, 1, 5); + +/* pci_cqe_owner + * Ownership bit. + */ +MLXSW_ITEM32(pci, cqe, owner, 0x0C, 0, 1); + +/* pci_eqe_event_type + * Event type. + */ +MLXSW_ITEM32(pci, eqe, event_type, 0x0C, 24, 8); +#define MLXSW_PCI_EQE_EVENT_TYPE_COMP 0x00 +#define MLXSW_PCI_EQE_EVENT_TYPE_CMD 0x0A + +/* pci_eqe_event_sub_type + * Event type. + */ +MLXSW_ITEM32(pci, eqe, event_sub_type, 0x0C, 16, 8); + +/* pci_eqe_cqn + * Completion Queue that triggeret this EQE. + */ +MLXSW_ITEM32(pci, eqe, cqn, 0x0C, 8, 7); + +/* pci_eqe_owner + * Ownership bit. + */ +MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1); + +/* pci_eqe_cmd_token + * Command completion event - token + */ +MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16); + +/* pci_eqe_cmd_status + * Command completion event - status + */ +MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8); + +/* pci_eqe_cmd_out_param_h + * Command completion event - output parameter - higher part + */ +MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32); + +/* pci_eqe_cmd_out_param_l + * Command completion event - output parameter - lower part + */ +MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32); + +#endif -- cgit v1.2.3 From 1d20d23c59c93a8b381063ef9785564018ad4c3a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 27 Oct 2016 15:12:59 +0200 Subject: mlxsw: Move PCI id table definitions into driver modules So far, mlxsw_pci.ko is the module that registers PCI table for all drivers (spectrum and switchx2). That is problematic for example with dracut. Since mlxsw_spectrum.ko and mlxsw_switchx2.ko are loaded dynamically from within mlxsw_core.ko, dracut does not have track of them and avoids them from being included in initramfs. So make this in an ordinary way and define the PCI tables in individual driver modules, so it can be properly loaded and included in dracut initramfs image. As a side effect, this patch could remove no longer necessary driver "kind" strings which were used to link PCI ids with individual mlxsw drivers. Suggested-by: Ivan Vecera Tested-by: Ivan Vecera Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Acked-by: Ivan Vecera Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Kconfig | 4 +- drivers/net/ethernet/mellanox/mlxsw/core.c | 14 ------ drivers/net/ethernet/mellanox/mlxsw/core.h | 8 ---- drivers/net/ethernet/mellanox/mlxsw/pci.c | 56 ++++++++--------------- drivers/net/ethernet/mellanox/mlxsw/pci.h | 63 ++++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/pci_hw.h | 2 - drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 25 ++++++++-- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 34 ++++++++++++-- 8 files changed, 135 insertions(+), 71 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/pci.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index 5989f7cb5462..d0bcf59c1bd6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig @@ -31,7 +31,7 @@ config MLXSW_PCI config MLXSW_SWITCHX2 tristate "Mellanox Technologies SwitchX-2 support" - depends on MLXSW_CORE && NET_SWITCHDEV + depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV default m ---help--- This driver supports Mellanox Technologies SwitchX-2 Ethernet @@ -42,7 +42,7 @@ config MLXSW_SWITCHX2 config MLXSW_SPECTRUM tristate "Mellanox Technologies Spectrum support" - depends on MLXSW_CORE && NET_SWITCHDEV && VLAN_8021Q + depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q default m ---help--- This driver supports Mellanox Technologies Spectrum Ethernet diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index a37d471728ed..02183f6a8b93 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -823,17 +823,6 @@ static struct mlxsw_driver *mlxsw_core_driver_get(const char *kind) spin_lock(&mlxsw_core_driver_list_lock); mlxsw_driver = __driver_find(kind); - if (!mlxsw_driver) { - spin_unlock(&mlxsw_core_driver_list_lock); - request_module(MLXSW_MODULE_ALIAS_PREFIX "%s", kind); - spin_lock(&mlxsw_core_driver_list_lock); - mlxsw_driver = __driver_find(kind); - } - if (mlxsw_driver) { - if (!try_module_get(mlxsw_driver->owner)) - mlxsw_driver = NULL; - } - spin_unlock(&mlxsw_core_driver_list_lock); return mlxsw_driver; } @@ -845,9 +834,6 @@ static void mlxsw_core_driver_put(const char *kind) spin_lock(&mlxsw_core_driver_list_lock); mlxsw_driver = __driver_find(kind); spin_unlock(&mlxsw_core_driver_list_lock); - if (!mlxsw_driver) - return; - module_put(mlxsw_driver->owner); } static int mlxsw_core_debugfs_init(struct mlxsw_core *mlxsw_core) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 94a846d34c2f..0cf721cee7fb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -51,13 +51,6 @@ #include "cmd.h" #include "resources.h" -#define MLXSW_MODULE_ALIAS_PREFIX "mlxsw-driver-" -#define MODULE_MLXSW_DRIVER_ALIAS(kind) \ - MODULE_ALIAS(MLXSW_MODULE_ALIAS_PREFIX kind) - -#define MLXSW_DEVICE_KIND_SWITCHX2 "switchx2" -#define MLXSW_DEVICE_KIND_SPECTRUM "spectrum" - struct mlxsw_core; struct mlxsw_driver; struct mlxsw_bus; @@ -221,7 +214,6 @@ struct mlxsw_config_profile { struct mlxsw_driver { struct list_head list; const char *kind; - struct module *owner; size_t priv_size; int (*init)(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info); diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 209630c98ef7..63d89f787ad7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -49,6 +49,7 @@ #include #include "pci_hw.h" +#include "pci.h" #include "core.h" #include "cmd.h" #include "port.h" @@ -56,26 +57,8 @@ static const char mlxsw_pci_driver_name[] = "mlxsw_pci"; -static const struct pci_device_id mlxsw_pci_id_table[] = { - {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0}, - {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0}, - {0, } -}; - static struct dentry *mlxsw_pci_dbg_root; -static const char *mlxsw_pci_device_kind_get(const struct pci_device_id *id) -{ - switch (id->device) { - case PCI_DEVICE_ID_MELLANOX_SWITCHX2: - return MLXSW_DEVICE_KIND_SWITCHX2; - case PCI_DEVICE_ID_MELLANOX_SPECTRUM: - return MLXSW_DEVICE_KIND_SPECTRUM; - default: - BUG(); - } -} - #define mlxsw_pci_write32(mlxsw_pci, reg, val) \ iowrite32be(val, (mlxsw_pci)->hw_addr + (MLXSW_PCI_ ## reg)) #define mlxsw_pci_read32(mlxsw_pci, reg) \ @@ -1553,7 +1536,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, err = request_irq(mlxsw_pci->msix_entry.vector, mlxsw_pci_eq_irq_handler, 0, - mlxsw_pci_driver_name, mlxsw_pci); + mlxsw_pci->bus_info.device_kind, mlxsw_pci); if (err) { dev_err(&pdev->dev, "IRQ request failed\n"); goto err_request_eq_irq; @@ -1793,6 +1776,7 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci) static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + const char *driver_name = pdev->driver->name; struct mlxsw_pci *mlxsw_pci; int err; @@ -1806,7 +1790,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_pci_enable_device; } - err = pci_request_regions(pdev, mlxsw_pci_driver_name); + err = pci_request_regions(pdev, driver_name); if (err) { dev_err(&pdev->dev, "pci_request_regions failed\n"); goto err_pci_request_regions; @@ -1857,7 +1841,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_msix_init; } - mlxsw_pci->bus_info.device_kind = mlxsw_pci_device_kind_get(id); + mlxsw_pci->bus_info.device_kind = driver_name; mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev); mlxsw_pci->bus_info.dev = &pdev->dev; @@ -1909,33 +1893,30 @@ static void mlxsw_pci_remove(struct pci_dev *pdev) kfree(mlxsw_pci); } -static struct pci_driver mlxsw_pci_driver = { - .name = mlxsw_pci_driver_name, - .id_table = mlxsw_pci_id_table, - .probe = mlxsw_pci_probe, - .remove = mlxsw_pci_remove, -}; +int mlxsw_pci_driver_register(struct pci_driver *pci_driver) +{ + pci_driver->probe = mlxsw_pci_probe; + pci_driver->remove = mlxsw_pci_remove; + return pci_register_driver(pci_driver); +} +EXPORT_SYMBOL(mlxsw_pci_driver_register); -static int __init mlxsw_pci_module_init(void) +void mlxsw_pci_driver_unregister(struct pci_driver *pci_driver) { - int err; + pci_unregister_driver(pci_driver); +} +EXPORT_SYMBOL(mlxsw_pci_driver_unregister); +static int __init mlxsw_pci_module_init(void) +{ mlxsw_pci_dbg_root = debugfs_create_dir(mlxsw_pci_driver_name, NULL); if (!mlxsw_pci_dbg_root) return -ENOMEM; - err = pci_register_driver(&mlxsw_pci_driver); - if (err) - goto err_register_driver; return 0; - -err_register_driver: - debugfs_remove_recursive(mlxsw_pci_dbg_root); - return err; } static void __exit mlxsw_pci_module_exit(void) { - pci_unregister_driver(&mlxsw_pci_driver); debugfs_remove_recursive(mlxsw_pci_dbg_root); } @@ -1945,4 +1926,3 @@ module_exit(mlxsw_pci_module_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Jiri Pirko "); MODULE_DESCRIPTION("Mellanox switch PCI interface driver"); -MODULE_DEVICE_TABLE(pci, mlxsw_pci_id_table); diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h new file mode 100644 index 000000000000..35a0011be64d --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h @@ -0,0 +1,63 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/pci.h + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Jiri Pirko + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MLXSW_PCI_H +#define _MLXSW_PCI_H + +#include + +#define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738 +#define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84 + +#if IS_ENABLED(CONFIG_MLXSW_PCI) + +int mlxsw_pci_driver_register(struct pci_driver *pci_driver); +void mlxsw_pci_driver_unregister(struct pci_driver *pci_driver); + +#else + +static inline int +mlxsw_pci_driver_register(struct pci_driver *pci_driver) +{ + return 0; +} + +static inline void +mlxsw_pci_driver_unregister(struct pci_driver *pci_driver) +{ +} + +#endif + +#endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h index 45bc19790be4..708736f387e2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h @@ -39,8 +39,6 @@ #include "item.h" -#define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738 -#define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84 #define MLXSW_PCI_BAR0_SIZE (1024 * 1024) /* 1MB */ #define MLXSW_PCI_PAGE_SIZE 4096 diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 5d8f1d51a403..780524065889 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ #include #include "spectrum.h" +#include "pci.h" #include "core.h" #include "reg.h" #include "port.h" @@ -3066,8 +3068,7 @@ static struct mlxsw_config_profile mlxsw_sp_config_profile = { }; static struct mlxsw_driver mlxsw_sp_driver = { - .kind = MLXSW_DEVICE_KIND_SPECTRUM, - .owner = THIS_MODULE, + .kind = mlxsw_sp_driver_name, .priv_size = sizeof(struct mlxsw_sp), .init = mlxsw_sp_init, .fini = mlxsw_sp_fini, @@ -4662,6 +4663,16 @@ static struct notifier_block mlxsw_sp_router_netevent_nb __read_mostly = { .notifier_call = mlxsw_sp_router_netevent_event, }; +static const struct pci_device_id mlxsw_sp_pci_id_table[] = { + {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0}, + {0, }, +}; + +static struct pci_driver mlxsw_sp_pci_driver = { + .name = mlxsw_sp_driver_name, + .id_table = mlxsw_sp_pci_id_table, +}; + static int __init mlxsw_sp_module_init(void) { int err; @@ -4673,8 +4684,15 @@ static int __init mlxsw_sp_module_init(void) err = mlxsw_core_driver_register(&mlxsw_sp_driver); if (err) goto err_core_driver_register; + + err = mlxsw_pci_driver_register(&mlxsw_sp_pci_driver); + if (err) + goto err_pci_driver_register; + return 0; +err_pci_driver_register: + mlxsw_core_driver_unregister(&mlxsw_sp_driver); err_core_driver_register: unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb); unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); @@ -4684,6 +4702,7 @@ err_core_driver_register: static void __exit mlxsw_sp_module_exit(void) { + mlxsw_pci_driver_unregister(&mlxsw_sp_pci_driver); mlxsw_core_driver_unregister(&mlxsw_sp_driver); unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb); unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); @@ -4696,4 +4715,4 @@ module_exit(mlxsw_sp_module_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Jiri Pirko "); MODULE_DESCRIPTION("Mellanox Spectrum driver"); -MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SPECTRUM); +MODULE_DEVICE_TABLE(pci, mlxsw_sp_pci_id_table); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 963618da81a9..938e22d14e11 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #include #include +#include "pci.h" #include "core.h" #include "reg.h" #include "port.h" @@ -1544,8 +1546,7 @@ static struct mlxsw_config_profile mlxsw_sx_config_profile = { }; static struct mlxsw_driver mlxsw_sx_driver = { - .kind = MLXSW_DEVICE_KIND_SWITCHX2, - .owner = THIS_MODULE, + .kind = mlxsw_sx_driver_name, .priv_size = sizeof(struct mlxsw_sx), .init = mlxsw_sx_init, .fini = mlxsw_sx_fini, @@ -1554,13 +1555,38 @@ static struct mlxsw_driver mlxsw_sx_driver = { .profile = &mlxsw_sx_config_profile, }; +static const struct pci_device_id mlxsw_sx_pci_id_table[] = { + {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0}, + {0, }, +}; + +static struct pci_driver mlxsw_sx_pci_driver = { + .name = mlxsw_sx_driver_name, + .id_table = mlxsw_sx_pci_id_table, +}; + static int __init mlxsw_sx_module_init(void) { - return mlxsw_core_driver_register(&mlxsw_sx_driver); + int err; + + err = mlxsw_core_driver_register(&mlxsw_sx_driver); + if (err) + return err; + + err = mlxsw_pci_driver_register(&mlxsw_sx_pci_driver); + if (err) + goto err_pci_driver_register; + + return 0; + +err_pci_driver_register: + mlxsw_core_driver_unregister(&mlxsw_sx_driver); + return err; } static void __exit mlxsw_sx_module_exit(void) { + mlxsw_pci_driver_unregister(&mlxsw_sx_pci_driver); mlxsw_core_driver_unregister(&mlxsw_sx_driver); } @@ -1570,4 +1596,4 @@ module_exit(mlxsw_sx_module_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Jiri Pirko "); MODULE_DESCRIPTION("Mellanox SwitchX-2 driver"); -MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SWITCHX2); +MODULE_DEVICE_TABLE(pci, mlxsw_sx_pci_id_table); -- cgit v1.2.3 From f20a91f1cc70105852d029e642cef7c583f397d3 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 27 Oct 2016 15:13:00 +0200 Subject: mlxsw: spectrum: Set physical device for port netdevice Do this so the sysfs has "device" link correctly set. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 780524065889..d652f7f030cb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2222,6 +2222,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, dev = alloc_etherdev(sizeof(struct mlxsw_sp_port)); if (!dev) return -ENOMEM; + SET_NETDEV_DEV(dev, mlxsw_sp->bus_info->dev); mlxsw_sp_port = netdev_priv(dev); mlxsw_sp_port->dev = dev; mlxsw_sp_port->mlxsw_sp = mlxsw_sp; -- cgit v1.2.3 From 71fac305fb78967b2c856848dead355262ba9e03 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 27 Oct 2016 15:13:01 +0200 Subject: mlxsw: switchx2: Set physical device for port netdevice Do this so the sysfs has "device" link correctly set. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 938e22d14e11..dc3c5ed73ecd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -968,6 +968,7 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) dev = alloc_etherdev(sizeof(struct mlxsw_sx_port)); if (!dev) return -ENOMEM; + SET_NETDEV_DEV(dev, mlxsw_sx->bus_info->dev); mlxsw_sx_port = netdev_priv(dev); mlxsw_sx_port->dev = dev; mlxsw_sx_port->mlxsw_sx = mlxsw_sx; -- cgit v1.2.3 From e3cd6cf425bf40061418edf7b295f654301446fe Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 27 Oct 2016 20:24:19 +0200 Subject: spi: fsl-espi: fix merge conflict for commit "avoid processing uninitalized data on error" Commit 5c0ba57744b1 ("spi: fsl-espi: avoid processing uninitalized data on error") applied fine to stable but caused a merge conflict on next. This patch fixes that. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index a7e4c284d50a..4e8a99d0cb63 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -456,7 +456,7 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) mspi->len -= rx_nr_bytes; if (rx_nr_bytes && mspi->rx) { - mspi->get_rx(rx_data, mspi); + *(u32 *)mspi->rx = rx_data; mspi->rx += 4; } } -- cgit v1.2.3 From 8b364b41ced2ac8eea9958ea084f10289a85419b Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 26 Oct 2016 15:51:28 -0700 Subject: drm/i915: Rename for_each_plane -> for_each_universal_plane This macro's name is a bit misleading; it doesn't actually iterate over all planes since it omits the cursor plane. Its only uses are in gen9 code which is using it to iterate over the universal planes (which we treat as primary+sprites); in these cases the legacy cursor registers are programmed independently if necessary. The macro's iterator value (0 for primary plane, spritenum+1 for each secondary plane) also isn't meaningful outside the gen9 context where the hardware considers them to all be "universal" planes that follow this numbering. This is just a renaming/clarification patch with no functional change. However it will make the subsequent patches more clear. Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1477522291-10874-2-git-send-email-matthew.d.roper@intel.com Reviewed-by: Paulo Zanoni --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index be92efe3453f..9f5a39209f52 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3463,7 +3463,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused) for_each_pipe(dev_priv, pipe) { seq_printf(m, "Pipe %c\n", pipe_name(pipe)); - for_each_plane(dev_priv, pipe, plane) { + for_each_universal_plane(dev_priv, pipe, plane) { entry = &ddb->plane[pipe][plane]; seq_printf(m, " Plane%-8d%8u%8u%8u\n", plane + 1, entry->start, entry->end, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a8f006e3b45d..930503aac46d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -312,7 +312,7 @@ struct i915_hotplug { #define for_each_pipe_masked(__dev_priv, __p, __mask) \ for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) \ for_each_if ((__mask) & (1 << (__p))) -#define for_each_plane(__dev_priv, __pipe, __p) \ +#define for_each_universal_plane(__dev_priv, __pipe, __p) \ for ((__p) = 0; \ (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \ (__p)++) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 895b3dc50e3f..cb7dd11277fd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13485,7 +13485,7 @@ static void verify_wm_state(struct drm_crtc *crtc, sw_ddb = &dev_priv->wm.skl_hw.ddb; /* planes */ - for_each_plane(dev_priv, pipe, plane) { + for_each_universal_plane(dev_priv, pipe, plane) { hw_plane_wm = &hw_wm.planes[plane]; sw_plane_wm = &sw_wm->planes[plane]; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9e0e8741253e..58d3ba05b219 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3160,7 +3160,7 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) continue; - for_each_plane(dev_priv, pipe, plane) { + for_each_universal_plane(dev_priv, pipe, plane) { val = I915_READ(PLANE_BUF_CFG(pipe, plane)); skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane], val); -- cgit v1.2.3 From 2c4b49a0f73f142cdc81002eb306fd9b8b6308d9 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 26 Oct 2016 15:51:29 -0700 Subject: drm/i915: Use macro in place of open-coded for_each_universal_plane loop This was the only use of (misleadingly-named) intel_num_planes() function, so we can remove it as well. Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1477522291-10874-3-git-send-email-matthew.d.roper@intel.com Reviewed-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_drv.h | 9 --------- drivers/gpu/drm/i915/intel_pm.c | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 29ab5260f100..ace222c74f71 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1108,15 +1108,6 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) return container_of(intel_hdmi, struct intel_digital_port, hdmi); } -/* - * Returns the number of planes for this pipe, ie the number of sprites + 1 - * (primary plane). This doesn't count the cursor plane then. - */ -static inline unsigned int intel_num_planes(struct intel_crtc *crtc) -{ - return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1; -} - /* intel_fifo_underrun.c */ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv, enum pipe pipe, bool enable); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 58d3ba05b219..6f19e60628ed 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4232,7 +4232,7 @@ static void skl_update_wm(struct drm_crtc *crtc) if (crtc->state->active_changed) { int plane; - for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) + for_each_universal_plane(dev_priv, pipe, plane) skl_write_plane_wm(intel_crtc, &pipe_wm->planes[plane], &results->ddb, plane); -- cgit v1.2.3 From e9e128a69af2b5fd2a4e01a59cc7e479ce9b8813 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 27 Oct 2016 21:24:01 +0200 Subject: spi: fsl-espi: improve check for SPI_QE_CPU_MODE SPI_QE_CPU_MODE doesn't exist for ESPI and is set by of_mpc8xxx_spi_probe based on DT property "mode". This property is not defined for ESPI, see Documentation/devicetree/bindings/spi/fsl-spi.txt. So print an error message and bail out if SPI_QE_CPU_MODE is set. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 4e8a99d0cb63..f04c2464e854 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -583,8 +583,9 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, goto err_probe; if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { - mpc8xxx_spi->rx_shift = 16; - mpc8xxx_spi->tx_shift = 24; + dev_err(dev, "SPI_QE_CPU_MODE is not supported on ESPI!\n"); + ret = -EINVAL; + goto err_probe; } /* SPI controller initializations */ -- cgit v1.2.3 From 54731265966db742dda09008bd9bbe12ae11e93e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 27 Oct 2016 21:25:58 +0200 Subject: spi: fsl-espi: fix and improve writing to TX FIFO This change addresses two issues: - If the TX FIFO is full the ISR polls until there's free space again. An ISR should never wait for something. - Currently the number of bytes to transfer is rounded up to the next multiple of 4. For most transfers therefore few bytes remain in the TX FIFO after end of transfer. This would cause the next transfer to fail and as a workaround the ESPI block is disabled / re-enabled in fsl_espi_change_mode. This seems to clear the FIFO's (although it's not mentioned in the spec). With this change the TX FIFO is filled as much as possible initially and whenever the ISR is called. Also the exact number of bytes is transferred. The spinlock protects against a potential race if the first interrupt occurs whilst the TX FIFO is still being initially filled. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 68 ++++++++++++++++++++++++++++------------------ drivers/spi/spi-fsl-lib.h | 2 ++ 2 files changed, 44 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index f04c2464e854..95c1fbfe1cbe 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -54,6 +54,8 @@ #define CSMODE_AFT(x) ((x) << 8) #define CSMODE_CG(x) ((x) << 3) +#define FSL_ESPI_FIFO_SIZE 32 + /* Default mode/csmode for eSPI controller */ #define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3)) #define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \ @@ -200,6 +202,27 @@ static int fsl_espi_check_message(struct spi_message *m) return 0; } +static void fsl_espi_fill_tx_fifo(struct mpc8xxx_spi *mspi, u32 events) +{ + u32 tx_fifo_avail; + + /* if events is zero transfer has not started and tx fifo is empty */ + tx_fifo_avail = events ? SPIE_TXCNT(events) : FSL_ESPI_FIFO_SIZE; + + while (tx_fifo_avail >= min(4U, mspi->tx_len) && mspi->tx_len) + if (mspi->tx_len >= 4) { + fsl_espi_write_reg(mspi, ESPI_SPITF, *(u32 *)mspi->tx); + mspi->tx += 4; + mspi->tx_len -= 4; + tx_fifo_avail -= 4; + } else { + fsl_espi_write_reg8(mspi, ESPI_SPITF, *(u8 *)mspi->tx); + mspi->tx += 1; + mspi->tx_len -= 1; + tx_fifo_avail -= 1; + } +} + static void fsl_espi_change_mode(struct spi_device *spi) { struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); @@ -262,7 +285,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) int ret; mpc8xxx_spi->len = t->len; - mpc8xxx_spi->count = roundup(t->len, 4) / 4; + mpc8xxx_spi->tx_len = t->len; mpc8xxx_spi->tx = t->tx_buf; mpc8xxx_spi->rx = t->rx_buf; @@ -276,21 +299,22 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) /* enable rx ints */ fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, SPIM_RNE); - /* transmit word */ - fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPITF, *(u32 *)mpc8xxx_spi->tx); - mpc8xxx_spi->tx += 4; + /* Prevent filling the fifo from getting interrupted */ + spin_lock_irq(&mpc8xxx_spi->lock); + fsl_espi_fill_tx_fifo(mpc8xxx_spi, 0); + spin_unlock_irq(&mpc8xxx_spi->lock); /* Won't hang up forever, SPI bus sometimes got lost interrupts... */ ret = wait_for_completion_timeout(&mpc8xxx_spi->done, 2 * HZ); if (ret == 0) dev_err(mpc8xxx_spi->dev, - "Transaction hanging up (left %d bytes)\n", - mpc8xxx_spi->count); + "Transaction hanging up (left %u bytes)\n", + mpc8xxx_spi->tx_len); /* disable rx ints */ fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, 0); - return mpc8xxx_spi->count > 0 ? -EMSGSIZE : 0; + return mpc8xxx_spi->tx_len > 0 ? -EMSGSIZE : 0; } static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) @@ -461,26 +485,11 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) } } - if (!(events & SPIE_TNF)) { - int ret; - - /* spin until TX is done */ - ret = spin_event_timeout(((events = fsl_espi_read_reg( - mspi, ESPI_SPIE)) & SPIE_TNF), 1000, 0); - if (!ret) { - dev_err(mspi->dev, "tired waiting for SPIE_TNF\n"); - complete(&mspi->done); - return; - } - } + if (mspi->tx_len) + fsl_espi_fill_tx_fifo(mspi, events); - mspi->count -= 1; - if (mspi->count) { - fsl_espi_write_reg(mspi, ESPI_SPITF, *(u32 *)mspi->tx); - mspi->tx += 4; - } else { + if (!mspi->tx_len && !mspi->len) complete(&mspi->done); - } } static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) @@ -488,10 +497,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) struct mpc8xxx_spi *mspi = context_data; u32 events; + spin_lock(&mspi->lock); + /* Get interrupt events(tx/rx) */ events = fsl_espi_read_reg(mspi, ESPI_SPIE); - if (!events) + if (!events) { + spin_unlock_irq(&mspi->lock); return IRQ_NONE; + } dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events); @@ -500,6 +513,8 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) /* Clear the events */ fsl_espi_write_reg(mspi, ESPI_SPIE, events); + spin_unlock(&mspi->lock); + return IRQ_HANDLED; } @@ -562,6 +577,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, master->max_message_size = fsl_espi_max_message_size; mpc8xxx_spi = spi_master_get_devdata(master); + spin_lock_init(&mpc8xxx_spi->lock); mpc8xxx_spi->local_buf = devm_kmalloc(dev, SPCOM_TRANLEN_MAX, GFP_KERNEL); diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h index 2925c8089fd9..24d8bc84a111 100644 --- a/drivers/spi/spi-fsl-lib.h +++ b/drivers/spi/spi-fsl-lib.h @@ -30,7 +30,9 @@ struct mpc8xxx_spi { void *rx; #if IS_ENABLED(CONFIG_SPI_FSL_ESPI) int len; + unsigned int tx_len; u8 *local_buf; + spinlock_t lock; #endif int subblock; -- cgit v1.2.3 From f895e27f591228704954cc8927d9c61b3f3da90f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 27 Oct 2016 21:26:08 +0200 Subject: spi: fsl-espi: Rename len in struct mpc8xxx_spi to rx_len and make it unsigned Now that we introduced element tx_len in struct mpc8xxx_spi let's rename element len to rx_len as it actually is the number of bytes to receive. In addition make it unsigned. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 22 +++++++++++----------- drivers/spi/spi-fsl-lib.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 95c1fbfe1cbe..5a7449f3b3b8 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -284,7 +284,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); int ret; - mpc8xxx_spi->len = t->len; + mpc8xxx_spi->rx_len = t->len; mpc8xxx_spi->tx_len = t->len; mpc8xxx_spi->tx = t->tx_buf; @@ -445,28 +445,28 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) int ret; /* Spin until RX is done */ - if (SPIE_RXCNT(events) < min(4, mspi->len)) { + if (SPIE_RXCNT(events) < min(4U, mspi->rx_len)) { ret = spin_event_timeout( !(SPIE_RXCNT(events = fsl_espi_read_reg(mspi, ESPI_SPIE)) < - min(4, mspi->len)), + min(4U, mspi->rx_len)), 10000, 0); /* 10 msec */ if (!ret) dev_err(mspi->dev, "tired waiting for SPIE_RXCNT\n"); } - if (mspi->len >= 4) { + if (mspi->rx_len >= 4) { rx_data = fsl_espi_read_reg(mspi, ESPI_SPIRF); - } else if (mspi->len <= 0) { + } else if (!mspi->rx_len) { dev_err(mspi->dev, "unexpected RX(SPIE_RNE) interrupt occurred,\n" "(local rxlen %d bytes, reg rxlen %d bytes)\n", - min(4, mspi->len), SPIE_RXCNT(events)); + min(4U, mspi->rx_len), SPIE_RXCNT(events)); rx_nr_bytes = 0; } else { - rx_nr_bytes = mspi->len; - tmp = mspi->len; + rx_nr_bytes = mspi->rx_len; + tmp = mspi->rx_len; rx_data = 0; while (tmp--) { rx_data_8 = fsl_espi_read_reg8(mspi, @@ -474,10 +474,10 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) rx_data |= (rx_data_8 << (tmp * 8)); } - rx_data <<= (4 - mspi->len) * 8; + rx_data <<= (4 - mspi->rx_len) * 8; } - mspi->len -= rx_nr_bytes; + mspi->rx_len -= rx_nr_bytes; if (rx_nr_bytes && mspi->rx) { *(u32 *)mspi->rx = rx_data; @@ -488,7 +488,7 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) if (mspi->tx_len) fsl_espi_fill_tx_fifo(mspi, events); - if (!mspi->tx_len && !mspi->len) + if (!mspi->tx_len && !mspi->rx_len) complete(&mspi->done); } diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h index 24d8bc84a111..35a7a1730d0c 100644 --- a/drivers/spi/spi-fsl-lib.h +++ b/drivers/spi/spi-fsl-lib.h @@ -29,7 +29,7 @@ struct mpc8xxx_spi { const void *tx; void *rx; #if IS_ENABLED(CONFIG_SPI_FSL_ESPI) - int len; + unsigned int rx_len; unsigned int tx_len; u8 *local_buf; spinlock_t lock; -- cgit v1.2.3 From b3bec5f95f73520feb05b90244522f24546e96aa Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 27 Oct 2016 21:26:46 +0200 Subject: spi: fsl-espi: simplify and inline function fsl_espi_change_mode The ESPI spec mentions no requirement to turn off the ESPI unit prior to changing the mode. Most likely the ESPI unit is only turned off to clear the FIFO's as before this patch series single bytes could remain in the TX FIFO after transfer end. Therefore remove disabling / re-enabling the ESPI unit. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 5a7449f3b3b8..d5506852e63c 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -223,26 +223,6 @@ static void fsl_espi_fill_tx_fifo(struct mpc8xxx_spi *mspi, u32 events) } } -static void fsl_espi_change_mode(struct spi_device *spi) -{ - struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); - struct spi_mpc8xxx_cs *cs = spi->controller_state; - u32 tmp; - unsigned long flags; - - /* Turn off IRQs locally to minimize time that SPI is disabled. */ - local_irq_save(flags); - - /* Turn off SPI unit prior changing mode */ - tmp = fsl_espi_read_reg(mspi, ESPI_SPMODE); - fsl_espi_write_reg(mspi, ESPI_SPMODE, tmp & ~SPMODE_ENABLE); - fsl_espi_write_reg(mspi, ESPI_SPMODEx(spi->chip_select), - cs->hw_mode); - fsl_espi_write_reg(mspi, ESPI_SPMODE, tmp); - - local_irq_restore(flags); -} - static void fsl_espi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { @@ -276,7 +256,8 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, cs->hw_mode |= CSMODE_PM(pm); - fsl_espi_change_mode(spi); + fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODEx(spi->chip_select), + cs->hw_mode); } static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) -- cgit v1.2.3 From db1b049fad8b12062edffade8272d604b4019eb7 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 27 Oct 2016 21:28:02 +0200 Subject: spi: fsl-espi: extend and improve transfer error handling Extend and improve transfer error handling - in case of timeout report also number of remaining rx bytes - in case of timeout return ETIMEDOUT instead of EMSGSIZE - add sanity checks after all bytes have been sent / read: - check that HW has flag SPIE_DON set - check that RX / TX FIFO are empty Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index d5506852e63c..a9593f9691ec 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -289,13 +289,13 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) ret = wait_for_completion_timeout(&mpc8xxx_spi->done, 2 * HZ); if (ret == 0) dev_err(mpc8xxx_spi->dev, - "Transaction hanging up (left %u bytes)\n", - mpc8xxx_spi->tx_len); + "Transaction hanging up (left %u tx bytes, %u rx bytes)\n", + mpc8xxx_spi->tx_len, mpc8xxx_spi->rx_len); /* disable rx ints */ fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, 0); - return mpc8xxx_spi->tx_len > 0 ? -EMSGSIZE : 0; + return ret == 0 ? -ETIMEDOUT : 0; } static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) @@ -469,8 +469,20 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) if (mspi->tx_len) fsl_espi_fill_tx_fifo(mspi, events); - if (!mspi->tx_len && !mspi->rx_len) - complete(&mspi->done); + if (mspi->tx_len || mspi->rx_len) + return; + + /* we're done, but check for errors before returning */ + events = fsl_espi_read_reg(mspi, ESPI_SPIE); + + if (!(events & SPIE_DON)) + dev_err(mspi->dev, + "Transfer done but SPIE_DON isn't set!\n"); + + if (SPIE_RXCNT(events) || SPIE_TXCNT(events) != FSL_ESPI_FIFO_SIZE) + dev_err(mspi->dev, "Transfer done but rx/tx fifo's aren't empty!\n"); + + complete(&mspi->done); } static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) -- cgit v1.2.3 From e508cea45bc31de87b35180a9ba5ef9572ffde3f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 27 Oct 2016 21:27:56 +0200 Subject: spi: fsl-espi: make better use of the RX FIFO So far an interrupt is triggered whenever there's at least one byte in the RX FIFO. This results in a unnecessarily high number of interrupts. Change this to generate an interrupt if - RX FIFO is half full (except if all bytes to read fit into the RX FIFO anyway) - end of transfer has been reached This way the number of interrupts can be significantly reduced. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index a9593f9691ec..239f0362df61 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -55,9 +55,10 @@ #define CSMODE_CG(x) ((x) << 3) #define FSL_ESPI_FIFO_SIZE 32 +#define FSL_ESPI_RXTHR 15 /* Default mode/csmode for eSPI controller */ -#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3)) +#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(FSL_ESPI_RXTHR)) #define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \ | CSMODE_AFT(0) | CSMODE_CG(1)) @@ -263,6 +264,7 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) { struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); + u32 mask; int ret; mpc8xxx_spi->rx_len = t->len; @@ -277,8 +279,11 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPCOM, (SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1))); - /* enable rx ints */ - fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, SPIM_RNE); + /* enable interrupts */ + mask = SPIM_DON; + if (mpc8xxx_spi->rx_len > FSL_ESPI_FIFO_SIZE) + mask |= SPIM_RXT; + fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, mask); /* Prevent filling the fifo from getting interrupted */ spin_lock_irq(&mpc8xxx_spi->lock); -- cgit v1.2.3 From f05689a662d47896da742f5338eab183ed692c1c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 27 Oct 2016 21:27:35 +0200 Subject: spi: fsl-espi: fix and improve reading from RX FIFO Currently the driver polls in the ISR for enough bytes in the RX FIFO. An ISR should never do this. Change it to read as much as possible whenever the ISR is called. This also allows to significantly simplify the code. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 67 ++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 239f0362df61..2f95b19e67f7 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -224,6 +224,24 @@ static void fsl_espi_fill_tx_fifo(struct mpc8xxx_spi *mspi, u32 events) } } +static void fsl_espi_read_rx_fifo(struct mpc8xxx_spi *mspi, u32 events) +{ + u32 rx_fifo_avail = SPIE_RXCNT(events); + + while (rx_fifo_avail >= min(4U, mspi->rx_len) && mspi->rx_len) + if (mspi->rx_len >= 4) { + *(u32 *)mspi->rx = fsl_espi_read_reg(mspi, ESPI_SPIRF); + mspi->rx += 4; + mspi->rx_len -= 4; + rx_fifo_avail -= 4; + } else { + *(u8 *)mspi->rx = fsl_espi_read_reg8(mspi, ESPI_SPIRF); + mspi->rx += 1; + mspi->rx_len -= 1; + rx_fifo_avail -= 1; + } +} + static void fsl_espi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { @@ -423,53 +441,8 @@ static void fsl_espi_cleanup(struct spi_device *spi) static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) { - /* We need handle RX first */ - if (events & SPIE_RNE) { - u32 rx_data, tmp; - u8 rx_data_8; - int rx_nr_bytes = 4; - int ret; - - /* Spin until RX is done */ - if (SPIE_RXCNT(events) < min(4U, mspi->rx_len)) { - ret = spin_event_timeout( - !(SPIE_RXCNT(events = - fsl_espi_read_reg(mspi, ESPI_SPIE)) < - min(4U, mspi->rx_len)), - 10000, 0); /* 10 msec */ - if (!ret) - dev_err(mspi->dev, - "tired waiting for SPIE_RXCNT\n"); - } - - if (mspi->rx_len >= 4) { - rx_data = fsl_espi_read_reg(mspi, ESPI_SPIRF); - } else if (!mspi->rx_len) { - dev_err(mspi->dev, - "unexpected RX(SPIE_RNE) interrupt occurred,\n" - "(local rxlen %d bytes, reg rxlen %d bytes)\n", - min(4U, mspi->rx_len), SPIE_RXCNT(events)); - rx_nr_bytes = 0; - } else { - rx_nr_bytes = mspi->rx_len; - tmp = mspi->rx_len; - rx_data = 0; - while (tmp--) { - rx_data_8 = fsl_espi_read_reg8(mspi, - ESPI_SPIRF); - rx_data |= (rx_data_8 << (tmp * 8)); - } - - rx_data <<= (4 - mspi->rx_len) * 8; - } - - mspi->rx_len -= rx_nr_bytes; - - if (rx_nr_bytes && mspi->rx) { - *(u32 *)mspi->rx = rx_data; - mspi->rx += 4; - } - } + if (mspi->rx_len) + fsl_espi_read_rx_fifo(mspi, events); if (mspi->tx_len) fsl_espi_fill_tx_fifo(mspi, events); -- cgit v1.2.3 From fc0990903c479ecafc67f7bf030c68b19215f2d5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 15:27:56 +0100 Subject: drm/i915: Remove insert-page shortcut from execbuf relocate_iomap() We are not allowed to touch the GTT entries underneath an atomic section, as they take a rpm wakelock (which is illegal from atomic context) and in the near future acquiring the DMA address for a page within an object may sleep for an allocation. This makes the current shortcircuit in relocation_iomap() for performing a second relocation on an adjacent page illegal, and we need to release the atomic iomapping, lookup the DMA, insert it into the GTT before reentering the atomic iomap section. As it happens, this is precisely what we do on if we are using an iomapping over the full object and not just a single page and by removing the shortcut, we do the right thing. Fixes: 9c870d03674f ("drm/i915: Use RPM as the barrier for controlling...") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161028142756.3850-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index e52affdcc125..4b1019edd8c2 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -418,15 +418,6 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, unsigned long offset; void *vaddr; - if (cache->node.allocated) { - wmb(); - ggtt->base.insert_page(&ggtt->base, - i915_gem_object_get_dma_address(obj, page), - cache->node.start, I915_CACHE_NONE, 0); - cache->page = page; - return unmask_page(cache->vaddr); - } - if (cache->vaddr) { io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr)); } else { @@ -466,6 +457,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, offset = cache->node.start; if (cache->node.allocated) { + wmb(); ggtt->base.insert_page(&ggtt->base, i915_gem_object_get_dma_address(obj, page), offset, I915_CACHE_NONE, 0); -- cgit v1.2.3 From b52992c06c9020cecb1b9807855301e5f62ec968 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:24 +0100 Subject: drm/i915: Support asynchronous waits on struct fence from i915_gem_request We will need to wait on DMA completion (as signaled via struct fence) before executing our i915_gem_request. Therefore we want to expose a method for adding the await on the fence itself to the request. v2: Add a comment detailing a failure to handle a signal-on-any fence-array. v3: Pretend that magic numbers don't exist. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +- drivers/gpu/drm/i915/i915_gem_request.c | 48 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem_request.h | 6 ++-- 5 files changed, 58 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 930503aac46d..e95352cc5ac2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1423,6 +1423,9 @@ struct i915_error_state_file_priv { struct drm_i915_error_state *error; }; +#define I915_RESET_TIMEOUT (10 * HZ) /* 10s */ +#define I915_FENCE_TIMEOUT (10 * HZ) /* 10s */ + struct i915_gpu_error { /* For hangcheck timer */ #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 87018df94d68..0c186b75ec86 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -114,7 +114,7 @@ i915_gem_wait_for_error(struct i915_gpu_error *error) */ ret = wait_event_interruptible_timeout(error->reset_queue, !i915_reset_in_progress(error), - 10*HZ); + I915_RESET_TIMEOUT); if (ret == 0) { DRM_ERROR("Timed out waiting for the gpu reset to complete\n"); return -EIO; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 4b1019edd8c2..61365ae22b53 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1134,7 +1134,8 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, if (resv) { ret = i915_sw_fence_await_reservation (&req->submit, resv, &i915_fence_ops, - obj->base.pending_write_domain, 10*HZ, + obj->base.pending_write_domain, + I915_FENCE_TIMEOUT, GFP_KERNEL | __GFP_NOWARN); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index f9af2a00625e..5e38bc04a4f0 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -23,6 +23,7 @@ */ #include +#include #include "i915_drv.h" @@ -496,6 +497,53 @@ i915_gem_request_await_request(struct drm_i915_gem_request *to, return 0; } +int +i915_gem_request_await_dma_fence(struct drm_i915_gem_request *req, + struct dma_fence *fence) +{ + struct dma_fence_array *array; + int ret; + int i; + + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return 0; + + if (dma_fence_is_i915(fence)) + return i915_gem_request_await_request(req, to_request(fence)); + + if (!dma_fence_is_array(fence)) { + ret = i915_sw_fence_await_dma_fence(&req->submit, + fence, I915_FENCE_TIMEOUT, + GFP_KERNEL); + return ret < 0 ? ret : 0; + } + + /* Note that if the fence-array was created in signal-on-any mode, + * we should *not* decompose it into its individual fences. However, + * we don't currently store which mode the fence-array is operating + * in. Fortunately, the only user of signal-on-any is private to + * amdgpu and we should not see any incoming fence-array from + * sync-file being in signal-on-any mode. + */ + + array = to_dma_fence_array(fence); + for (i = 0; i < array->num_fences; i++) { + struct dma_fence *child = array->fences[i]; + + if (dma_fence_is_i915(child)) + ret = i915_gem_request_await_request(req, + to_request(child)); + else + ret = i915_sw_fence_await_dma_fence(&req->submit, + child, I915_FENCE_TIMEOUT, + GFP_KERNEL); + if (ret < 0) + return ret; + } + + return 0; +} + /** * i915_gem_request_await_object - set this request to (async) wait upon a bo * diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index bceeaa3a5193..4e6d038cc9de 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -147,7 +147,7 @@ struct drm_i915_gem_request { extern const struct dma_fence_ops i915_fence_ops; -static inline bool fence_is_i915(struct dma_fence *fence) +static inline bool dma_fence_is_i915(const struct dma_fence *fence) { return fence->ops == &i915_fence_ops; } @@ -176,7 +176,7 @@ to_request(struct dma_fence *fence) { /* We assume that NULL fence/request are interoperable */ BUILD_BUG_ON(offsetof(struct drm_i915_gem_request, fence) != 0); - GEM_BUG_ON(fence && !fence_is_i915(fence)); + GEM_BUG_ON(fence && !dma_fence_is_i915(fence)); return container_of(fence, struct drm_i915_gem_request, fence); } @@ -214,6 +214,8 @@ int i915_gem_request_await_object(struct drm_i915_gem_request *to, struct drm_i915_gem_object *obj, bool write); +int i915_gem_request_await_dma_fence(struct drm_i915_gem_request *req, + struct dma_fence *fence); void __i915_add_request(struct drm_i915_gem_request *req, bool flush_caches); #define i915_add_request(req) \ -- cgit v1.2.3 From 7e941861c9c2aa69c0ef6665e2c0c1174c4a4b0e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:25 +0100 Subject: drm/i915: Allow i915_sw_fence_await_sw_fence() to allocate In forthcoming patches, we want to be able to dynamically allocate the wait_queue_t used whilst awaiting. This is more convenient if we extend the i915_sw_fence_await_sw_fence() to perform the allocation for us if we pass in a gfp mask as an alternative than a preallocated struct. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_sw_fence.c | 40 ++++++++++++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_sw_fence.h | 8 ++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 8185002d7ec8..95f2f12e0917 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -13,6 +13,8 @@ #include "i915_sw_fence.h" +#define I915_SW_FENCE_FLAG_ALLOC BIT(3) /* after WQ_FLAG_* for safety */ + static DEFINE_SPINLOCK(i915_sw_fence_lock); static int __i915_sw_fence_notify(struct i915_sw_fence *fence, @@ -135,6 +137,8 @@ static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int flags, void * list_del(&wq->task_list); __i915_sw_fence_complete(wq->private, key); i915_sw_fence_put(wq->private); + if (wq->flags & I915_SW_FENCE_FLAG_ALLOC) + kfree(wq); return 0; } @@ -192,9 +196,9 @@ static bool i915_sw_fence_check_if_after(struct i915_sw_fence *fence, return err; } -int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, - struct i915_sw_fence *signaler, - wait_queue_t *wq) +static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, + struct i915_sw_fence *signaler, + wait_queue_t *wq, gfp_t gfp) { unsigned long flags; int pending; @@ -206,8 +210,22 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, if (unlikely(i915_sw_fence_check_if_after(fence, signaler))) return -EINVAL; + pending = 0; + if (!wq) { + wq = kmalloc(sizeof(*wq), gfp); + if (!wq) { + if (!gfpflags_allow_blocking(gfp)) + return -ENOMEM; + + i915_sw_fence_wait(signaler); + return 0; + } + + pending |= I915_SW_FENCE_FLAG_ALLOC; + } + INIT_LIST_HEAD(&wq->task_list); - wq->flags = 0; + wq->flags = pending; wq->func = i915_sw_fence_wake; wq->private = i915_sw_fence_get(fence); @@ -226,6 +244,20 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, return pending; } +int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, + struct i915_sw_fence *signaler, + wait_queue_t *wq) +{ + return __i915_sw_fence_await_sw_fence(fence, signaler, wq, 0); +} + +int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence, + struct i915_sw_fence *signaler, + gfp_t gfp) +{ + return __i915_sw_fence_await_sw_fence(fence, signaler, NULL, gfp); +} + struct i915_sw_dma_fence_cb { struct dma_fence_cb base; struct i915_sw_fence *fence; diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index cd239e92f67f..707dfc4f0da5 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -46,6 +46,9 @@ void i915_sw_fence_commit(struct i915_sw_fence *fence); int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, struct i915_sw_fence *after, wait_queue_t *wq); +int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence, + struct i915_sw_fence *after, + gfp_t gfp); int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, struct dma_fence *dma, unsigned long timeout, @@ -62,4 +65,9 @@ static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence) return atomic_read(&fence->pending) < 0; } +static inline void i915_sw_fence_wait(struct i915_sw_fence *fence) +{ + wait_event(fence->wait, i915_sw_fence_done(fence)); +} + #endif /* _I915_SW_FENCE_H_ */ -- cgit v1.2.3 From c92ac094a9c647ebcff56c0535f865bc7f2aa052 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:26 +0100 Subject: drm/i915: Remove superfluous wait_for_error() from throttle-ioctl The throttle-ioctl never touches the struct_mutex. It does, however, as part of its ABI report whether the hardware is terminally wedged. For that purposes, it only has to report the current state and not incur the cost of checking/waiting every invocation, as we do not have to wait for a reset before waiting on a request to ensure completion (that is baked into the wait request implementation). Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0c186b75ec86..1254143ab121 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3705,10 +3705,6 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) struct drm_i915_gem_request *request, *target = NULL; int ret; - ret = i915_gem_wait_for_error(&dev_priv->gpu_error); - if (ret) - return ret; - /* ABI: return -EIO if already wedged */ if (i915_terminally_wedged(&dev_priv->gpu_error)) return -EIO; -- cgit v1.2.3 From 2e36991a8aa2fb5b06eee7958cced0665ea6f35d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:28 +0100 Subject: drm/i915: Remove unused i915_gem_active_wait() in favour of _unlocked() Since we only use the more generic unlocked variant, just rename it as the normal i915_gem_active_wait(). The temporary cost is that we need to always acquire the reference in a RCU safe manner, but the benefit is that we will combine the common paths. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.h | 34 +++------------------------------ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 2 files changed, 4 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index ae0913adfec6..602234f91583 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -569,40 +569,13 @@ i915_gem_active_is_idle(const struct i915_gem_active *active, } /** - * i915_gem_active_wait - waits until the request is completed - * @active - the active request on which to wait - * - * i915_gem_active_wait() waits until the request is completed before - * returning. Note that it does not guarantee that the request is - * retired first, see i915_gem_active_retire(). - * - * i915_gem_active_wait() returns immediately if the active - * request is already complete. - */ -static inline int __must_check -i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) -{ - struct drm_i915_gem_request *request; - long ret; - - request = i915_gem_active_peek(active, mutex); - if (!request) - return 0; - - ret = i915_wait_request(request, - I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, - MAX_SCHEDULE_TIMEOUT); - return ret < 0 ? ret : 0; -} - -/** - * i915_gem_active_wait_unlocked - waits until the request is completed + * i915_gem_active_wait- waits until the request is completed * @active - the active request on which to wait * @flags - how to wait * @timeout - how long to wait at most * @rps - userspace client to charge for a waitboost * - * i915_gem_active_wait_unlocked() waits until the request is completed before + * i915_gem_active_wait() waits until the request is completed before * returning, without requiring any locks to be held. Note that it does not * retire any requests before returning. * @@ -618,8 +591,7 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) * Returns 0 if successful, or a negative error code. */ static inline int -i915_gem_active_wait_unlocked(const struct i915_gem_active *active, - unsigned int flags) +i915_gem_active_wait(const struct i915_gem_active *active, unsigned int flags) { struct drm_i915_gem_request *request; long ret = 0; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 884a5ae2225d..09bb89cfb7c3 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -524,7 +524,7 @@ static inline int intel_engine_idle(struct intel_engine_cs *engine, unsigned int flags) { /* Wait upon the last request to be completed */ - return i915_gem_active_wait_unlocked(&engine->last_request, flags); + return i915_gem_active_wait(&engine->last_request, flags); } int intel_init_render_ring_buffer(struct intel_engine_cs *engine); -- cgit v1.2.3 From f8a7fde4561067a8ebc956b27afeb530ac97cb9d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:29 +0100 Subject: drm/i915: Defer active reference until required We only need the active reference to keep the object alive after the handle has been deleted (so as to prevent a synchronous gem_close). Why then pay the price of a kref on every execbuf when we can insert that final active ref just in time for the handle deletion? Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-6-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 22 +++++++++++++++++++++- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 2 +- drivers/gpu/drm/i915/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 -- drivers/gpu/drm/i915/i915_gem_gtt.c | 7 ++++++- drivers/gpu/drm/i915/i915_gem_render_state.c | 3 ++- drivers/gpu/drm/i915/intel_ringbuffer.c | 15 ++++++++++++--- 8 files changed, 71 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index cf4b2427aff3..edc59d08d017 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2246,6 +2246,12 @@ struct drm_i915_gem_object { #define __I915_BO_ACTIVE(bo) \ ((READ_ONCE((bo)->flags) >> I915_BO_ACTIVE_SHIFT) & I915_BO_ACTIVE_MASK) + /** + * Have we taken a reference for the object for incomplete GPU + * activity? + */ +#define I915_BO_ACTIVE_REF (I915_BO_ACTIVE_SHIFT + I915_NUM_ENGINES) + /** * This is set if the object has been written to since last bound * to the GTT @@ -2407,6 +2413,28 @@ i915_gem_object_has_active_engine(const struct drm_i915_gem_object *obj, return obj->flags & BIT(engine + I915_BO_ACTIVE_SHIFT); } +static inline bool +i915_gem_object_has_active_reference(const struct drm_i915_gem_object *obj) +{ + return test_bit(I915_BO_ACTIVE_REF, &obj->flags); +} + +static inline void +i915_gem_object_set_active_reference(struct drm_i915_gem_object *obj) +{ + lockdep_assert_held(&obj->base.dev->struct_mutex); + __set_bit(I915_BO_ACTIVE_REF, &obj->flags); +} + +static inline void +i915_gem_object_clear_active_reference(struct drm_i915_gem_object *obj) +{ + lockdep_assert_held(&obj->base.dev->struct_mutex); + __clear_bit(I915_BO_ACTIVE_REF, &obj->flags); +} + +void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj); + static inline unsigned int i915_gem_object_get_tiling(struct drm_i915_gem_object *obj) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 537f502123ea..c0103044dede 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2661,7 +2661,10 @@ i915_gem_object_retire__read(struct i915_gem_active *active, list_move_tail(&obj->global_list, &request->i915->mm.bound_list); - i915_gem_object_put(obj); + if (i915_gem_object_has_active_reference(obj)) { + i915_gem_object_clear_active_reference(obj); + i915_gem_object_put(obj); + } } static bool i915_context_is_banned(const struct i915_gem_context *ctx) @@ -2935,6 +2938,12 @@ void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file) list_for_each_entry_safe(vma, vn, &obj->vma_list, obj_link) if (vma->vm->file == fpriv) i915_vma_close(vma); + + if (i915_gem_object_is_active(obj) && + !i915_gem_object_has_active_reference(obj)) { + i915_gem_object_set_active_reference(obj); + i915_gem_object_get(obj); + } mutex_unlock(&obj->base.dev->struct_mutex); } @@ -4475,6 +4484,17 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) intel_runtime_pm_put(dev_priv); } +void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj) +{ + lockdep_assert_held(&obj->base.dev->struct_mutex); + + GEM_BUG_ON(i915_gem_object_has_active_reference(obj)); + if (i915_gem_object_is_active(obj)) + i915_gem_object_set_active_reference(obj); + else + i915_gem_object_put(obj); +} + int i915_gem_suspend(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index ed989596d9a3..cb25cad3318c 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -73,7 +73,7 @@ void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool) list_for_each_entry_safe(obj, next, &pool->cache_list[n], batch_pool_link) - i915_gem_object_put(obj); + __i915_gem_object_release_unless_active(obj); INIT_LIST_HEAD(&pool->cache_list[n]); } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 5dca32ac1c67..47e888cc721f 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -155,7 +155,7 @@ void i915_gem_context_free(struct kref *ctx_ref) if (ce->ring) intel_ring_free(ce->ring); - i915_vma_put(ce->state); + __i915_gem_object_release_unless_active(ce->state->obj); } put_pid(ctx->pid); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 61365ae22b53..4cafce97998a 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1290,8 +1290,6 @@ void i915_vma_move_to_active(struct i915_vma *vma, * add the active reference first and queue for it to be dropped * *last*. */ - if (!i915_gem_object_is_active(obj)) - i915_gem_object_get(obj); i915_gem_object_set_active(obj, idx); i915_gem_active_set(&obj->last_read[idx], req); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 947d5ad51fb7..a3a364478a89 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3734,11 +3734,16 @@ void __iomem *i915_vma_pin_iomap(struct i915_vma *vma) void i915_vma_unpin_and_release(struct i915_vma **p_vma) { struct i915_vma *vma; + struct drm_i915_gem_object *obj; vma = fetch_and_zero(p_vma); if (!vma) return; + obj = vma->obj; + i915_vma_unpin(vma); - i915_vma_put(vma); + i915_vma_close(vma); + + __i915_gem_object_release_unless_active(obj); } diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index a98c0f42badd..e7c3dbcc6c81 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -224,7 +224,8 @@ int i915_gem_render_state_init(struct drm_i915_gem_request *req) i915_vma_move_to_active(so.vma, req, 0); err_unpin: i915_vma_unpin(so.vma); + i915_vma_close(so.vma); err_obj: - i915_gem_object_put(obj); + __i915_gem_object_release_unless_active(obj); return ret; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8ef735faa603..8eee9675d3bf 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1762,14 +1762,19 @@ static void cleanup_phys_status_page(struct intel_engine_cs *engine) static void cleanup_status_page(struct intel_engine_cs *engine) { struct i915_vma *vma; + struct drm_i915_gem_object *obj; vma = fetch_and_zero(&engine->status_page.vma); if (!vma) return; + obj = vma->obj; + i915_vma_unpin(vma); - i915_gem_object_unpin_map(vma->obj); - i915_vma_put(vma); + i915_vma_close(vma); + + i915_gem_object_unpin_map(obj); + __i915_gem_object_release_unless_active(obj); } static int init_status_page(struct intel_engine_cs *engine) @@ -1967,7 +1972,11 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size) void intel_ring_free(struct intel_ring *ring) { - i915_vma_put(ring->vma); + struct drm_i915_gem_object *obj = ring->vma->obj; + + i915_vma_close(ring->vma); + __i915_gem_object_release_unless_active(obj); + kfree(ring); } -- cgit v1.2.3 From e95433c73a11759203af1cae5958f998c9673370 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:27 +0100 Subject: drm/i915: Rearrange i915_wait_request() accounting with callers Our low-level wait routine has evolved from our generic wait interface that handled unlocked, RPS boosting, waits with time tracking. If we push our GEM fence tracking to use reservation_objects (required for handling multiple timelines), we lose the ability to pass the required information down to i915_wait_request(). However, if we push the extra functionality from i915_wait_request() to the individual callsites (i915_gem_object_wait_rendering and i915_gem_wait_ioctl) that make use of those extras, we can both simplify our low level wait and prepare for extending the GEM interface for use of reservation_objects. v2: Rewrite i915_wait_request() kerneldocs Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gvt/scheduler.c | 9 +- drivers/gpu/drm/i915/i915_drv.h | 7 +- drivers/gpu/drm/i915/i915_gem.c | 309 ++++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_request.c | 146 ++++----------- drivers/gpu/drm/i915/i915_gem_request.h | 32 ++-- drivers/gpu/drm/i915/i915_gem_userptr.c | 12 +- drivers/gpu/drm/i915/intel_display.c | 27 +-- drivers/gpu/drm/i915/intel_ringbuffer.c | 14 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +- 9 files changed, 316 insertions(+), 243 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index f7e320b9b17a..18acb45dd14d 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -400,6 +400,7 @@ static int workload_thread(void *priv) int ring_id = p->ring_id; struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; struct intel_vgpu_workload *workload = NULL; + long lret; int ret; bool need_force_wake = IS_SKYLAKE(gvt->dev_priv); DEFINE_WAIT_FUNC(wait, woken_wake_function); @@ -449,10 +450,12 @@ static int workload_thread(void *priv) gvt_dbg_sched("ring id %d wait workload %p\n", workload->ring_id, workload); - workload->status = i915_wait_request(workload->req, - 0, NULL, NULL); - if (workload->status != 0) + lret = i915_wait_request(workload->req, + 0, MAX_SCHEDULE_TIMEOUT); + if (lret < 0) { + workload->status = lret; gvt_err("fail to wait workload, skip\n"); + } complete: gvt_dbg_sched("will complete workload %p\n, status: %d\n", diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e95352cc5ac2..cf4b2427aff3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3319,9 +3319,10 @@ int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, int __must_check i915_gem_suspend(struct drm_device *dev); void i915_gem_resume(struct drm_device *dev); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); -int __must_check -i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, - bool readonly); +int i915_gem_object_wait(struct drm_i915_gem_object *obj, + unsigned int flags, + long timeout, + struct intel_rps_client *rps); int __must_check i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1254143ab121..537f502123ea 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -292,7 +292,12 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj) * must wait for all rendering to complete to the object (as unbinding * must anyway), and retire the requests. */ - ret = i915_gem_object_wait_rendering(obj, false); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED | + I915_WAIT_ALL, + MAX_SCHEDULE_TIMEOUT, + NULL); if (ret) return ret; @@ -311,88 +316,172 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj) return ret; } -/** - * Ensures that all rendering to the object has completed and the object is - * safe to unbind from the GTT or access from the CPU. - * @obj: i915 gem object - * @readonly: waiting for just read access or read-write access - */ -int -i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, - bool readonly) +static long +i915_gem_object_wait_fence(struct dma_fence *fence, + unsigned int flags, + long timeout, + struct intel_rps_client *rps) { - struct reservation_object *resv; - struct i915_gem_active *active; - unsigned long active_mask; - int idx; + struct drm_i915_gem_request *rq; - lockdep_assert_held(&obj->base.dev->struct_mutex); + BUILD_BUG_ON(I915_WAIT_INTERRUPTIBLE != 0x1); - if (!readonly) { - active = obj->last_read; - active_mask = i915_gem_object_get_active(obj); - } else { - active_mask = 1; - active = &obj->last_write; + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return timeout; + + if (!dma_fence_is_i915(fence)) + return dma_fence_wait_timeout(fence, + flags & I915_WAIT_INTERRUPTIBLE, + timeout); + + rq = to_request(fence); + if (i915_gem_request_completed(rq)) + goto out; + + /* This client is about to stall waiting for the GPU. In many cases + * this is undesirable and limits the throughput of the system, as + * many clients cannot continue processing user input/output whilst + * blocked. RPS autotuning may take tens of milliseconds to respond + * to the GPU load and thus incurs additional latency for the client. + * We can circumvent that by promoting the GPU frequency to maximum + * before we wait. This makes the GPU throttle up much more quickly + * (good for benchmarks and user experience, e.g. window animations), + * but at a cost of spending more power processing the workload + * (bad for battery). Not all clients even want their results + * immediately and for them we should just let the GPU select its own + * frequency to maximise efficiency. To prevent a single client from + * forcing the clocks too high for the whole system, we only allow + * each client to waitboost once in a busy period. + */ + if (rps) { + if (INTEL_GEN(rq->i915) >= 6) + gen6_rps_boost(rq->i915, rps, rq->emitted_jiffies); + else + rps = NULL; } - for_each_active(active_mask, idx) { + timeout = i915_wait_request(rq, flags, timeout); + +out: + if (flags & I915_WAIT_LOCKED && i915_gem_request_completed(rq)) + i915_gem_request_retire_upto(rq); + + if (rps && rq->fence.seqno == rq->engine->last_submitted_seqno) { + /* The GPU is now idle and this client has stalled. + * Since no other client has submitted a request in the + * meantime, assume that this client is the only one + * supplying work to the GPU but is unable to keep that + * work supplied because it is waiting. Since the GPU is + * then never kept fully busy, RPS autoclocking will + * keep the clocks relatively low, causing further delays. + * Compensate by giving the synchronous client credit for + * a waitboost next time. + */ + spin_lock(&rq->i915->rps.client_lock); + list_del_init(&rps->link); + spin_unlock(&rq->i915->rps.client_lock); + } + + return timeout; +} + +static long +i915_gem_object_wait_reservation(struct reservation_object *resv, + unsigned int flags, + long timeout, + struct intel_rps_client *rps) +{ + struct dma_fence *excl; + + if (flags & I915_WAIT_ALL) { + struct dma_fence **shared; + unsigned int count, i; int ret; - ret = i915_gem_active_wait(&active[idx], - &obj->base.dev->struct_mutex); + ret = reservation_object_get_fences_rcu(resv, + &excl, &count, &shared); if (ret) return ret; - } - resv = i915_gem_object_get_dmabuf_resv(obj); - if (resv) { - long err; + for (i = 0; i < count; i++) { + timeout = i915_gem_object_wait_fence(shared[i], + flags, timeout, + rps); + if (timeout <= 0) + break; + + dma_fence_put(shared[i]); + } - err = reservation_object_wait_timeout_rcu(resv, !readonly, true, - MAX_SCHEDULE_TIMEOUT); - if (err < 0) - return err; + for (; i < count; i++) + dma_fence_put(shared[i]); + kfree(shared); + } else { + excl = reservation_object_get_excl_rcu(resv); } - return 0; + if (excl && timeout > 0) + timeout = i915_gem_object_wait_fence(excl, flags, timeout, rps); + + dma_fence_put(excl); + + return timeout; } -/* A nonblocking variant of the above wait. Must be called prior to - * acquiring the mutex for the object, as the object state may change - * during this call. A reference must be held by the caller for the object. +/** + * Waits for rendering to the object to be completed + * @obj: i915 gem object + * @flags: how to wait (under a lock, for all rendering or just for writes etc) + * @timeout: how long to wait + * @rps: client (user process) to charge for any waitboosting */ -static __must_check int -__unsafe_wait_rendering(struct drm_i915_gem_object *obj, - struct intel_rps_client *rps, - bool readonly) +int +i915_gem_object_wait(struct drm_i915_gem_object *obj, + unsigned int flags, + long timeout, + struct intel_rps_client *rps) { + struct reservation_object *resv; struct i915_gem_active *active; unsigned long active_mask; int idx; - active_mask = __I915_BO_ACTIVE(obj); - if (!active_mask) - return 0; + might_sleep(); +#if IS_ENABLED(CONFIG_LOCKDEP) + GEM_BUG_ON(debug_locks && + !!lockdep_is_held(&obj->base.dev->struct_mutex) != + !!(flags & I915_WAIT_LOCKED)); +#endif + GEM_BUG_ON(timeout < 0); - if (!readonly) { + if (flags & I915_WAIT_ALL) { active = obj->last_read; + active_mask = i915_gem_object_get_active(obj); } else { active_mask = 1; active = &obj->last_write; } for_each_active(active_mask, idx) { - int ret; - - ret = i915_gem_active_wait_unlocked(&active[idx], - I915_WAIT_INTERRUPTIBLE, - NULL, rps); - if (ret) - return ret; + struct drm_i915_gem_request *request; + + request = i915_gem_active_get_unlocked(&active[idx]); + if (request) { + timeout = i915_gem_object_wait_fence(&request->fence, + flags, timeout, + rps); + i915_gem_request_put(request); + } + if (timeout < 0) + return timeout; } - return 0; + resv = i915_gem_object_get_dmabuf_resv(obj); + if (resv) + timeout = i915_gem_object_wait_reservation(resv, + flags, timeout, + rps); + return timeout < 0 ? timeout : 0; } static struct intel_rps_client *to_rps_client(struct drm_file *file) @@ -449,12 +538,18 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, struct drm_device *dev = obj->base.dev; void *vaddr = obj->phys_handle->vaddr + args->offset; char __user *user_data = u64_to_user_ptr(args->data_ptr); - int ret = 0; + int ret; /* We manually control the domain here and pretend that it * remains coherent i.e. in the GTT domain, like shmem_pwrite. */ - ret = i915_gem_object_wait_rendering(obj, false); + lockdep_assert_held(&obj->base.dev->struct_mutex); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED | + I915_WAIT_ALL, + MAX_SCHEDULE_TIMEOUT, + to_rps_client(file_priv)); if (ret) return ret; @@ -614,12 +709,17 @@ int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj, { int ret; - *needs_clflush = 0; + lockdep_assert_held(&obj->base.dev->struct_mutex); + *needs_clflush = 0; if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_wait_rendering(obj, true); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT, + NULL); if (ret) return ret; @@ -661,11 +761,18 @@ int i915_gem_obj_prepare_shmem_write(struct drm_i915_gem_object *obj, { int ret; + lockdep_assert_held(&obj->base.dev->struct_mutex); + *needs_clflush = 0; if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_wait_rendering(obj, false); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED | + I915_WAIT_ALL, + MAX_SCHEDULE_TIMEOUT, + NULL); if (ret) return ret; @@ -1051,7 +1158,10 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, trace_i915_gem_object_pread(obj, args->offset, args->size); - ret = __unsafe_wait_rendering(obj, to_rps_client(file), true); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT, + to_rps_client(file)); if (ret) goto err; @@ -1449,7 +1559,11 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, trace_i915_gem_object_pwrite(obj, args->offset, args->size); - ret = __unsafe_wait_rendering(obj, to_rps_client(file), false); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_ALL, + MAX_SCHEDULE_TIMEOUT, + to_rps_client(file)); if (ret) goto err; @@ -1536,7 +1650,11 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, * We will repeat the flush holding the lock in the normal manner * to catch cases where we are gazumped. */ - ret = __unsafe_wait_rendering(obj, to_rps_client(file), !write_domain); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + (write_domain ? I915_WAIT_ALL : 0), + MAX_SCHEDULE_TIMEOUT, + to_rps_client(file)); if (ret) goto err; @@ -1772,7 +1890,10 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf) * repeat the flush holding the lock in the normal manner to catch cases * where we are gazumped. */ - ret = __unsafe_wait_rendering(obj, NULL, !write); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT, + NULL); if (ret) goto err; @@ -2817,6 +2938,17 @@ void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file) mutex_unlock(&obj->base.dev->struct_mutex); } +static unsigned long to_wait_timeout(s64 timeout_ns) +{ + if (timeout_ns < 0) + return MAX_SCHEDULE_TIMEOUT; + + if (timeout_ns == 0) + return 0; + + return nsecs_to_jiffies_timeout(timeout_ns); +} + /** * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT * @dev: drm device pointer @@ -2845,10 +2977,9 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_gem_wait *args = data; - struct intel_rps_client *rps = to_rps_client(file); struct drm_i915_gem_object *obj; - unsigned long active; - int idx, ret = 0; + ktime_t start; + long ret; if (args->flags != 0) return -EINVAL; @@ -2857,14 +2988,17 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) if (!obj) return -ENOENT; - active = __I915_BO_ACTIVE(obj); - for_each_active(active, idx) { - s64 *timeout = args->timeout_ns >= 0 ? &args->timeout_ns : NULL; - ret = i915_gem_active_wait_unlocked(&obj->last_read[idx], - I915_WAIT_INTERRUPTIBLE, - timeout, rps); - if (ret) - break; + start = ktime_get(); + + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | I915_WAIT_ALL, + to_wait_timeout(args->timeout_ns), + to_rps_client(file)); + + if (args->timeout_ns > 0) { + args->timeout_ns -= ktime_to_ns(ktime_sub(ktime_get(), start)); + if (args->timeout_ns < 0) + args->timeout_ns = 0; } i915_gem_object_put_unlocked(obj); @@ -3283,7 +3417,13 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) uint32_t old_write_domain, old_read_domains; int ret; - ret = i915_gem_object_wait_rendering(obj, !write); + lockdep_assert_held(&obj->base.dev->struct_mutex); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED | + (write ? I915_WAIT_ALL : 0), + MAX_SCHEDULE_TIMEOUT, + NULL); if (ret) return ret; @@ -3400,7 +3540,12 @@ restart: * If we wait upon the object, we know that all the bound * VMA are no longer active. */ - ret = i915_gem_object_wait_rendering(obj, false); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED | + I915_WAIT_ALL, + MAX_SCHEDULE_TIMEOUT, + NULL); if (ret) return ret; @@ -3647,7 +3792,13 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) uint32_t old_write_domain, old_read_domains; int ret; - ret = i915_gem_object_wait_rendering(obj, !write); + lockdep_assert_held(&obj->base.dev->struct_mutex); + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED | + (write ? I915_WAIT_ALL : 0), + MAX_SCHEDULE_TIMEOUT, + NULL); if (ret) return ret; @@ -3703,7 +3854,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) struct drm_i915_file_private *file_priv = file->driver_priv; unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES; struct drm_i915_gem_request *request, *target = NULL; - int ret; + long ret; /* ABI: return -EIO if already wedged */ if (i915_terminally_wedged(&dev_priv->gpu_error)) @@ -3730,10 +3881,12 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (target == NULL) return 0; - ret = i915_wait_request(target, I915_WAIT_INTERRUPTIBLE, NULL, NULL); + ret = i915_wait_request(target, + I915_WAIT_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT); i915_gem_request_put(target); - return ret; + return ret < 0 ? ret : 0; } static bool diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 5e38bc04a4f0..fbe0923fe0bc 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -59,31 +59,9 @@ static bool i915_fence_enable_signaling(struct dma_fence *fence) static signed long i915_fence_wait(struct dma_fence *fence, bool interruptible, - signed long timeout_jiffies) + signed long timeout) { - s64 timeout_ns, *timeout; - int ret; - - if (timeout_jiffies != MAX_SCHEDULE_TIMEOUT) { - timeout_ns = jiffies_to_nsecs(timeout_jiffies); - timeout = &timeout_ns; - } else { - timeout = NULL; - } - - ret = i915_wait_request(to_request(fence), - interruptible, timeout, - NO_WAITBOOST); - if (ret == -ETIME) - return 0; - - if (ret < 0) - return ret; - - if (timeout_jiffies != MAX_SCHEDULE_TIMEOUT) - timeout_jiffies = nsecs_to_jiffies(timeout_ns); - - return timeout_jiffies; + return i915_wait_request(to_request(fence), interruptible, timeout); } static void i915_fence_value_str(struct dma_fence *fence, char *str, int size) @@ -166,7 +144,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) struct i915_gem_active *active, *next; trace_i915_gem_request_retire(request); - list_del(&request->link); + list_del_init(&request->link); /* We know the GPU must have read the request to have * sent us the seqno + interrupt, so use the position @@ -224,7 +202,8 @@ void i915_gem_request_retire_upto(struct drm_i915_gem_request *req) struct drm_i915_gem_request *tmp; lockdep_assert_held(&req->i915->drm.struct_mutex); - GEM_BUG_ON(list_empty(&req->link)); + if (list_empty(&req->link)) + return; do { tmp = list_first_entry(&engine->request_list, @@ -780,75 +759,48 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, /** * i915_wait_request - wait until execution of request has finished - * @req: duh! + * @req: the request to wait upon * @flags: how to wait - * @timeout: in - how long to wait (NULL forever); out - how much time remaining - * @rps: client to charge for RPS boosting + * @timeout: how long to wait in jiffies + * + * i915_wait_request() waits for the request to be completed, for a + * maximum of @timeout jiffies (with MAX_SCHEDULE_TIMEOUT implying an + * unbounded wait). * - * Note: It is of utmost importance that the passed in seqno and reset_counter - * values have been read by the caller in an smp safe manner. Where read-side - * locks are involved, it is sufficient to read the reset_counter before - * unlocking the lock that protects the seqno. For lockless tricks, the - * reset_counter _must_ be read before, and an appropriate smp_rmb must be - * inserted. + * If the caller holds the struct_mutex, the caller must pass I915_WAIT_LOCKED + * in via the flags, and vice versa if the struct_mutex is not held, the caller + * must not specify that the wait is locked. * - * Returns 0 if the request was found within the alloted time. Else returns the - * errno with remaining time filled in timeout argument. + * Returns the remaining time (in jiffies) if the request completed, which may + * be zero or -ETIME if the request is unfinished after the timeout expires. + * May return -EINTR is called with I915_WAIT_INTERRUPTIBLE and a signal is + * pending before the request completes. */ -int i915_wait_request(struct drm_i915_gem_request *req, - unsigned int flags, - s64 *timeout, - struct intel_rps_client *rps) +long i915_wait_request(struct drm_i915_gem_request *req, + unsigned int flags, + long timeout) { const int state = flags & I915_WAIT_INTERRUPTIBLE ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; DEFINE_WAIT(reset); struct intel_wait wait; - unsigned long timeout_remain; - int ret = 0; might_sleep(); #if IS_ENABLED(CONFIG_LOCKDEP) - GEM_BUG_ON(!!lockdep_is_held(&req->i915->drm.struct_mutex) != + GEM_BUG_ON(debug_locks && + !!lockdep_is_held(&req->i915->drm.struct_mutex) != !!(flags & I915_WAIT_LOCKED)); #endif + GEM_BUG_ON(timeout < 0); if (i915_gem_request_completed(req)) - return 0; + return timeout; - timeout_remain = MAX_SCHEDULE_TIMEOUT; - if (timeout) { - if (WARN_ON(*timeout < 0)) - return -EINVAL; - - if (*timeout == 0) - return -ETIME; - - /* Record current time in case interrupted, or wedged */ - timeout_remain = nsecs_to_jiffies_timeout(*timeout); - *timeout += ktime_get_raw_ns(); - } + if (!timeout) + return -ETIME; trace_i915_gem_request_wait_begin(req); - /* This client is about to stall waiting for the GPU. In many cases - * this is undesirable and limits the throughput of the system, as - * many clients cannot continue processing user input/output whilst - * blocked. RPS autotuning may take tens of milliseconds to respond - * to the GPU load and thus incurs additional latency for the client. - * We can circumvent that by promoting the GPU frequency to maximum - * before we wait. This makes the GPU throttle up much more quickly - * (good for benchmarks and user experience, e.g. window animations), - * but at a cost of spending more power processing the workload - * (bad for battery). Not all clients even want their results - * immediately and for them we should just let the GPU select its own - * frequency to maximise efficiency. To prevent a single client from - * forcing the clocks too high for the whole system, we only allow - * each client to waitboost once in a busy period. - */ - if (IS_RPS_CLIENT(rps) && INTEL_GEN(req->i915) >= 6) - gen6_rps_boost(req->i915, rps, req->emitted_jiffies); - /* Optimistic short spin before touching IRQs */ if (i915_spin_request(req, state, 5)) goto complete; @@ -867,16 +819,17 @@ int i915_wait_request(struct drm_i915_gem_request *req, for (;;) { if (signal_pending_state(state, current)) { - ret = -ERESTARTSYS; + timeout = -ERESTARTSYS; break; } - timeout_remain = io_schedule_timeout(timeout_remain); - if (timeout_remain == 0) { - ret = -ETIME; + if (!timeout) { + timeout = -ETIME; break; } + timeout = io_schedule_timeout(timeout); + if (intel_wait_complete(&wait)) break; @@ -923,40 +876,7 @@ wakeup: complete: trace_i915_gem_request_wait_end(req); - if (timeout) { - *timeout -= ktime_get_raw_ns(); - if (*timeout < 0) - *timeout = 0; - - /* - * Apparently ktime isn't accurate enough and occasionally has a - * bit of mismatch in the jiffies<->nsecs<->ktime loop. So patch - * things up to make the test happy. We allow up to 1 jiffy. - * - * This is a regrssion from the timespec->ktime conversion. - */ - if (ret == -ETIME && *timeout < jiffies_to_usecs(1)*1000) - *timeout = 0; - } - - if (IS_RPS_USER(rps) && - req->fence.seqno == req->engine->last_submitted_seqno) { - /* The GPU is now idle and this client has stalled. - * Since no other client has submitted a request in the - * meantime, assume that this client is the only one - * supplying work to the GPU but is unable to keep that - * work supplied because it is waiting. Since the GPU is - * then never kept fully busy, RPS autoclocking will - * keep the clocks relatively low, causing further delays. - * Compensate by giving the synchronous client credit for - * a waitboost next time. - */ - spin_lock(&req->i915->rps.client_lock); - list_del_init(&rps->link); - spin_unlock(&req->i915->rps.client_lock); - } - - return ret; + return timeout; } static bool engine_retire_requests(struct intel_engine_cs *engine) diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 4e6d038cc9de..ae0913adfec6 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -228,13 +228,13 @@ struct intel_rps_client; #define IS_RPS_CLIENT(p) (!IS_ERR(p)) #define IS_RPS_USER(p) (!IS_ERR_OR_NULL(p)) -int i915_wait_request(struct drm_i915_gem_request *req, - unsigned int flags, - s64 *timeout, - struct intel_rps_client *rps) +long i915_wait_request(struct drm_i915_gem_request *req, + unsigned int flags, + long timeout) __attribute__((nonnull(1))); #define I915_WAIT_INTERRUPTIBLE BIT(0) #define I915_WAIT_LOCKED BIT(1) /* struct_mutex held, handle GPU reset */ +#define I915_WAIT_ALL BIT(2) /* used by i915_gem_object_wait() */ static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine); @@ -583,14 +583,16 @@ static inline int __must_check i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) { struct drm_i915_gem_request *request; + long ret; request = i915_gem_active_peek(active, mutex); if (!request) return 0; - return i915_wait_request(request, - I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, - NULL, NULL); + ret = i915_wait_request(request, + I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT); + return ret < 0 ? ret : 0; } /** @@ -617,20 +619,18 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) */ static inline int i915_gem_active_wait_unlocked(const struct i915_gem_active *active, - unsigned int flags, - s64 *timeout, - struct intel_rps_client *rps) + unsigned int flags) { struct drm_i915_gem_request *request; - int ret = 0; + long ret = 0; request = i915_gem_active_get_unlocked(active); if (request) { - ret = i915_wait_request(request, flags, timeout, rps); + ret = i915_wait_request(request, flags, MAX_SCHEDULE_TIMEOUT); i915_gem_request_put(request); } - return ret; + return ret < 0 ? ret : 0; } /** @@ -647,7 +647,7 @@ i915_gem_active_retire(struct i915_gem_active *active, struct mutex *mutex) { struct drm_i915_gem_request *request; - int ret; + long ret; request = i915_gem_active_raw(active, mutex); if (!request) @@ -655,8 +655,8 @@ i915_gem_active_retire(struct i915_gem_active *active, ret = i915_wait_request(request, I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, - NULL, NULL); - if (ret) + MAX_SCHEDULE_TIMEOUT); + if (ret < 0) return ret; list_del_init(&active->link); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index c6f780f5abc9..c49dd95413bd 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -61,23 +61,13 @@ struct i915_mmu_object { bool attached; }; -static void wait_rendering(struct drm_i915_gem_object *obj) -{ - unsigned long active = __I915_BO_ACTIVE(obj); - int idx; - - for_each_active(active, idx) - i915_gem_active_wait_unlocked(&obj->last_read[idx], - 0, NULL, NULL); -} - static void cancel_userptr(struct work_struct *work) { struct i915_mmu_object *mo = container_of(work, typeof(*mo), work); struct drm_i915_gem_object *obj = mo->obj; struct drm_device *dev = obj->base.dev; - wait_rendering(obj); + i915_gem_object_wait(obj, I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT, NULL); mutex_lock(&dev->struct_mutex); /* Cancel any active worker and force us to re-evaluate gup */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cb7dd11277fd..e4800b81c59e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12072,7 +12072,7 @@ static void intel_mmio_flip_work_func(struct work_struct *w) if (work->flip_queued_req) WARN_ON(i915_wait_request(work->flip_queued_req, - 0, NULL, NO_WAITBOOST)); + 0, MAX_SCHEDULE_TIMEOUT) < 0); /* For framebuffer backed by dmabuf, wait for fence */ resv = i915_gem_object_get_dmabuf_resv(obj); @@ -14187,19 +14187,21 @@ static int intel_atomic_prepare_commit(struct drm_device *dev, for_each_plane_in_state(state, plane, plane_state, i) { struct intel_plane_state *intel_plane_state = to_intel_plane_state(plane_state); + long timeout; if (!intel_plane_state->wait_req) continue; - ret = i915_wait_request(intel_plane_state->wait_req, - I915_WAIT_INTERRUPTIBLE, - NULL, NULL); - if (ret) { + timeout = i915_wait_request(intel_plane_state->wait_req, + I915_WAIT_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT); + if (timeout < 0) { /* Any hang should be swallowed by the wait */ - WARN_ON(ret == -EIO); + WARN_ON(timeout == -EIO); mutex_lock(&dev->struct_mutex); drm_atomic_helper_cleanup_planes(dev, state); mutex_unlock(&dev->struct_mutex); + ret = timeout; break; } } @@ -14403,7 +14405,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) bool hw_check = intel_state->modeset; unsigned long put_domains[I915_MAX_PIPES] = {}; unsigned crtc_vblank_mask = 0; - int i, ret; + int i; for_each_plane_in_state(state, plane, plane_state, i) { struct intel_plane_state *intel_plane_state = @@ -14412,11 +14414,10 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) if (!intel_plane_state->wait_req) continue; - ret = i915_wait_request(intel_plane_state->wait_req, - 0, NULL, NULL); /* EIO should be eaten, and we can't get interrupted in the * worker, and blocking commits have waited already. */ - WARN_ON(ret); + WARN_ON(i915_wait_request(intel_plane_state->wait_req, + 0, MAX_SCHEDULE_TIMEOUT) < 0); } drm_atomic_helper_wait_for_dependencies(state); @@ -14780,7 +14781,11 @@ intel_prepare_plane_fb(struct drm_plane *plane, * can safely continue. */ if (needs_modeset(crtc_state)) - ret = i915_gem_object_wait_rendering(old_obj, true); + ret = i915_gem_object_wait(old_obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT, + NULL); if (ret) { /* GPU hangs should have been swallowed by the wait */ WARN_ON(ret == -EIO); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 67a70c5e6453..8ef735faa603 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2155,7 +2155,9 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes) { struct intel_ring *ring = req->ring; struct drm_i915_gem_request *target; - int ret; + long timeout; + + lockdep_assert_held(&req->i915->drm.struct_mutex); intel_ring_update_space(ring); if (ring->space >= bytes) @@ -2185,11 +2187,11 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes) if (WARN_ON(&target->ring_link == &ring->request_list)) return -ENOSPC; - ret = i915_wait_request(target, - I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, - NULL, NO_WAITBOOST); - if (ret) - return ret; + timeout = i915_wait_request(target, + I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT); + if (timeout < 0) + return timeout; i915_gem_request_retire_upto(target); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 32b2e6332ccf..884a5ae2225d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -524,8 +524,7 @@ static inline int intel_engine_idle(struct intel_engine_cs *engine, unsigned int flags) { /* Wait upon the last request to be completed */ - return i915_gem_active_wait_unlocked(&engine->last_request, - flags, NULL, NULL); + return i915_gem_active_wait_unlocked(&engine->last_request, flags); } int intel_init_render_ring_buffer(struct intel_engine_cs *engine); -- cgit v1.2.3 From 920cf4194954ec6f971506013c7fe3b7def178b6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:30 +0100 Subject: drm/i915: Introduce an internal allocator for disposable private objects Quite a few of our objects used for internal hardware programming do not benefit from being swappable or from being zero initialised. As such they do not benefit from using a shmemfs backing storage and since they are internal and never directly exposed to the user, we do not need to worry about providing a filp. For these we can use an drm_i915_gem_object wrapper around a sg_table of plain struct page. They are not swap backed and not automatically pinned. If they are reaped by the shrinker, the pages are released and the contents discarded. For the internal use case, this is fine as for example, ringbuffers are pinned from being written by a request to be read by the hardware. Once they are idle, they can be discarded entirely. As such they are a good match for execlist ringbuffers and a small variety of other internal objects. In the first iteration, this is limited to the scratch batch buffers we use (for command parsing and state initialisation). v2: Allocate physically contiguous pages, where possible. v3: Reduce maximum order on subsequent requests following an allocation failure. v4: Fix up mismatch between swiotlb segment size and page count (it counts in 2k units, not 4k pages) Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-7-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_gem_batch_pool.c | 27 ++--- drivers/gpu/drm/i915/i915_gem_internal.c | 170 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem_render_state.c | 2 +- drivers/gpu/drm/i915/intel_engine_cs.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 14 ++- 7 files changed, 197 insertions(+), 24 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_internal.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 612340097f4b..7faa04c91e1a 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -35,6 +35,7 @@ i915-y += i915_cmd_parser.o \ i915_gem_execbuffer.o \ i915_gem_fence.o \ i915_gem_gtt.o \ + i915_gem_internal.o \ i915_gem.o \ i915_gem_render_state.o \ i915_gem_request.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index edc59d08d017..96995d644da2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3556,6 +3556,11 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, u32 gtt_offset, u32 size); +/* i915_gem_internal.c */ +struct drm_i915_gem_object * +i915_gem_object_create_internal(struct drm_i915_private *dev_priv, + unsigned int size); + /* i915_gem_shrinker.c */ unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv, unsigned long target, diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index cb25cad3318c..aa4e1e043b4e 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -97,9 +97,9 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, size_t size) { struct drm_i915_gem_object *obj = NULL; - struct drm_i915_gem_object *tmp, *next; + struct drm_i915_gem_object *tmp; struct list_head *list; - int n; + int n, ret; lockdep_assert_held(&pool->engine->i915->drm.struct_mutex); @@ -112,19 +112,12 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, n = ARRAY_SIZE(pool->cache_list) - 1; list = &pool->cache_list[n]; - list_for_each_entry_safe(tmp, next, list, batch_pool_link) { + list_for_each_entry(tmp, list, batch_pool_link) { /* The batches are strictly LRU ordered */ if (!i915_gem_active_is_idle(&tmp->last_read[pool->engine->id], &tmp->base.dev->struct_mutex)) break; - /* While we're looping, do some clean up */ - if (tmp->madv == __I915_MADV_PURGED) { - list_del(&tmp->batch_pool_link); - i915_gem_object_put(tmp); - continue; - } - if (tmp->base.size >= size) { obj = tmp; break; @@ -132,19 +125,15 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, } if (obj == NULL) { - int ret; - - obj = i915_gem_object_create(&pool->engine->i915->drm, size); + obj = i915_gem_object_create_internal(pool->engine->i915, size); if (IS_ERR(obj)) return obj; - - ret = i915_gem_object_get_pages(obj); - if (ret) - return ERR_PTR(ret); - - obj->madv = I915_MADV_DONTNEED; } + ret = i915_gem_object_get_pages(obj); + if (ret) + return ERR_PTR(ret); + list_move_tail(&obj->batch_pool_link, list); i915_gem_object_pin_pages(obj); return obj; diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c new file mode 100644 index 000000000000..02e66fa170b0 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -0,0 +1,170 @@ +/* + * Copyright © 2014-2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include +#include +#include "i915_drv.h" + +#define QUIET (__GFP_NORETRY | __GFP_NOWARN) + +/* convert swiotlb segment size into sensible units (pages)! */ +#define IO_TLB_SEGPAGES (IO_TLB_SEGSIZE << IO_TLB_SHIFT >> PAGE_SHIFT) + +static void internal_free_pages(struct sg_table *st) +{ + struct scatterlist *sg; + + for (sg = st->sgl; sg; sg = __sg_next(sg)) + __free_pages(sg_page(sg), get_order(sg->length)); + + sg_free_table(st); + kfree(st); +} + +static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + unsigned int npages = obj->base.size / PAGE_SIZE; + struct sg_table *st; + struct scatterlist *sg; + int max_order; + gfp_t gfp; + + st = kmalloc(sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + if (sg_alloc_table(st, npages, GFP_KERNEL)) { + kfree(st); + return -ENOMEM; + } + + sg = st->sgl; + st->nents = 0; + + max_order = MAX_ORDER; +#ifdef CONFIG_SWIOTLB + if (swiotlb_nr_tbl()) /* minimum max swiotlb size is IO_TLB_SEGSIZE */ + max_order = min(max_order, ilog2(IO_TLB_SEGPAGES)); +#endif + + gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE; + if (IS_CRESTLINE(i915) || IS_BROADWATER(i915)) { + /* 965gm cannot relocate objects above 4GiB. */ + gfp &= ~__GFP_HIGHMEM; + gfp |= __GFP_DMA32; + } + + do { + int order = min(fls(npages) - 1, max_order); + struct page *page; + + do { + page = alloc_pages(gfp | (order ? QUIET : 0), order); + if (page) + break; + if (!order--) + goto err; + + /* Limit subsequent allocations as well */ + max_order = order; + } while (1); + + sg_set_page(sg, page, PAGE_SIZE << order, 0); + st->nents++; + + npages -= 1 << order; + if (!npages) { + sg_mark_end(sg); + break; + } + + sg = __sg_next(sg); + } while (1); + obj->pages = st; + + if (i915_gem_gtt_prepare_object(obj)) { + obj->pages = NULL; + goto err; + } + + /* Mark the pages as dontneed whilst they are still pinned. As soon + * as they are unpinned they are allowed to be reaped by the shrinker, + * and the caller is expected to repopulate - the contents of this + * object are only valid whilst active and pinned. + */ + obj->madv = I915_MADV_DONTNEED; + return 0; + +err: + sg_mark_end(sg); + internal_free_pages(st); + return -ENOMEM; +} + +static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj) +{ + i915_gem_gtt_finish_object(obj); + internal_free_pages(obj->pages); + + obj->dirty = 0; + obj->madv = I915_MADV_WILLNEED; +} + +static const struct drm_i915_gem_object_ops i915_gem_object_internal_ops = { + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE, + .get_pages = i915_gem_object_get_pages_internal, + .put_pages = i915_gem_object_put_pages_internal, +}; + +/** + * Creates a new object that wraps some internal memory for private use. + * This object is not backed by swappable storage, and as such its contents + * are volatile and only valid whilst pinned. If the object is reaped by the + * shrinker, its pages and data will be discarded. Equally, it is not a full + * GEM object and so not valid for access from userspace. This makes it useful + * for hardware interfaces like ringbuffers (which are pinned from the time + * the request is written to the time the hardware stops accessing it), but + * not for contexts (which need to be preserved when not active for later + * reuse). Note that it is not cleared upon allocation. + */ +struct drm_i915_gem_object * +i915_gem_object_create_internal(struct drm_i915_private *i915, + unsigned int size) +{ + struct drm_i915_gem_object *obj; + + obj = i915_gem_object_alloc(&i915->drm); + if (!obj) + return ERR_PTR(-ENOMEM); + + drm_gem_private_object_init(&i915->drm, &obj->base, size); + i915_gem_object_init(obj, &i915_gem_object_internal_ops); + + obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; + + return obj; +} diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index e7c3dbcc6c81..217e0b58b930 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -187,7 +187,7 @@ int i915_gem_render_state_init(struct drm_i915_gem_request *req) if (so.rodata->batch_items * 4 > 4096) return -EINVAL; - obj = i915_gem_object_create(&req->i915->drm, 4096); + obj = i915_gem_object_create_internal(req->i915, 4096); if (IS_ERR(obj)) return PTR_ERR(obj); diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 8cceb345aa0f..b2de371d2bf5 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -264,7 +264,7 @@ int intel_engine_create_scratch(struct intel_engine_cs *engine, int size) obj = i915_gem_object_create_stolen(&engine->i915->drm, size); if (!obj) - obj = i915_gem_object_create(&engine->i915->drm, size); + obj = i915_gem_object_create_internal(engine->i915, size); if (IS_ERR(obj)) { DRM_ERROR("Failed to allocate scratch page\n"); return PTR_ERR(obj); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8eee9675d3bf..a15b9b5f2924 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1782,9 +1782,10 @@ static int init_status_page(struct intel_engine_cs *engine) struct drm_i915_gem_object *obj; struct i915_vma *vma; unsigned int flags; + void *vaddr; int ret; - obj = i915_gem_object_create(&engine->i915->drm, 4096); + obj = i915_gem_object_create_internal(engine->i915, 4096); if (IS_ERR(obj)) { DRM_ERROR("Failed to allocate status page\n"); return PTR_ERR(obj); @@ -1817,15 +1818,22 @@ static int init_status_page(struct intel_engine_cs *engine) if (ret) goto err; + vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + goto err_unpin; + } + engine->status_page.vma = vma; engine->status_page.ggtt_offset = i915_ggtt_offset(vma); - engine->status_page.page_addr = - i915_gem_object_pin_map(obj, I915_MAP_WB); + engine->status_page.page_addr = memset(vaddr, 0, 4096); DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", engine->name, i915_ggtt_offset(vma)); return 0; +err_unpin: + i915_vma_unpin(vma); err: i915_gem_object_put(obj); return ret; -- cgit v1.2.3 From 4e50f082ac51c95046a8315612ce1d9acb2b3d63 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:31 +0100 Subject: drm/i915: Reuse the active golden render state batch The golden render state is constant, but we recreate the batch setting it up for every new context. If we keep that batch in a volatile cache we can safely reuse it whenever we need to initialise a new context. We mark the pages as purgeable and use the shrinker to recover pages from the batch whenever we face memory pressues, recreating that batch afresh on the next new context. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-8-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_render_state.c | 184 +++++++++++++++++---------- drivers/gpu/drm/i915/i915_gem_render_state.h | 4 +- drivers/gpu/drm/i915/intel_engine_cs.c | 5 + drivers/gpu/drm/i915/intel_lrc.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 3 + 6 files changed, 129 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 217e0b58b930..9625e1a662ed 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -28,17 +28,19 @@ #include "i915_drv.h" #include "intel_renderstate.h" -struct render_state { +struct intel_render_state { const struct intel_renderstate_rodata *rodata; struct i915_vma *vma; - u32 aux_batch_size; - u32 aux_batch_offset; + u32 batch_offset; + u32 batch_size; + u32 aux_offset; + u32 aux_size; }; static const struct intel_renderstate_rodata * -render_state_get_rodata(const struct drm_i915_gem_request *req) +render_state_get_rodata(const struct intel_engine_cs *engine) { - switch (INTEL_GEN(req->i915)) { + switch (INTEL_GEN(engine->i915)) { case 6: return &gen6_null_state; case 7: @@ -63,29 +65,27 @@ render_state_get_rodata(const struct drm_i915_gem_request *req) */ #define OUT_BATCH(batch, i, val) \ do { \ - if (WARN_ON((i) >= PAGE_SIZE / sizeof(u32))) { \ - ret = -ENOSPC; \ - goto err_out; \ - } \ + if ((i) >= PAGE_SIZE / sizeof(u32)) \ + goto err; \ (batch)[(i)++] = (val); \ } while(0) -static int render_state_setup(struct render_state *so) +static int render_state_setup(struct intel_render_state *so, + struct drm_i915_private *i915) { - struct drm_i915_private *dev_priv = to_i915(so->vma->vm->dev); const struct intel_renderstate_rodata *rodata = so->rodata; - const bool has_64bit_reloc = INTEL_GEN(dev_priv) >= 8; + const bool has_64bit_reloc = INTEL_GEN(i915) >= 8; + struct drm_i915_gem_object *obj = so->vma->obj; unsigned int i = 0, reloc_index = 0; - struct page *page; + unsigned int needs_clflush; u32 *d; int ret; - ret = i915_gem_object_set_to_cpu_domain(so->vma->obj, true); + ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush); if (ret) return ret; - page = i915_gem_object_get_dirty_page(so->vma->obj, 0); - d = kmap(page); + d = kmap_atomic(i915_gem_object_get_dirty_page(obj, 0)); while (i < rodata->batch_items) { u32 s = rodata->batch[i]; @@ -95,10 +95,8 @@ static int render_state_setup(struct render_state *so) s = lower_32_bits(r); if (has_64bit_reloc) { if (i + 1 >= rodata->batch_items || - rodata->batch[i + 1] != 0) { - ret = -EINVAL; - goto err_out; - } + rodata->batch[i + 1] != 0) + goto err; d[i++] = s; s = upper_32_bits(r); @@ -110,12 +108,20 @@ static int render_state_setup(struct render_state *so) d[i++] = s; } + if (rodata->reloc[reloc_index] != -1) { + DRM_ERROR("only %d relocs resolved\n", reloc_index); + goto err; + } + + so->batch_offset = so->vma->node.start; + so->batch_size = rodata->batch_items * sizeof(u32); + while (i % CACHELINE_DWORDS) OUT_BATCH(d, i, MI_NOOP); - so->aux_batch_offset = i * sizeof(u32); + so->aux_offset = i * sizeof(u32); - if (HAS_POOLED_EU(dev_priv)) { + if (HAS_POOLED_EU(i915)) { /* * We always program 3x6 pool config but depending upon which * subslice is disabled HW drops down to appropriate config @@ -143,89 +149,131 @@ static int render_state_setup(struct render_state *so) } OUT_BATCH(d, i, MI_BATCH_BUFFER_END); - so->aux_batch_size = (i * sizeof(u32)) - so->aux_batch_offset; - + so->aux_size = i * sizeof(u32) - so->aux_offset; + so->aux_offset += so->batch_offset; /* * Since we are sending length, we need to strictly conform to * all requirements. For Gen2 this must be a multiple of 8. */ - so->aux_batch_size = ALIGN(so->aux_batch_size, 8); - - kunmap(page); - - ret = i915_gem_object_set_to_gtt_domain(so->vma->obj, false); - if (ret) - return ret; - - if (rodata->reloc[reloc_index] != -1) { - DRM_ERROR("only %d relocs resolved\n", reloc_index); - return -EINVAL; - } + so->aux_size = ALIGN(so->aux_size, 8); - return 0; + if (needs_clflush) + drm_clflush_virt_range(d, i * sizeof(u32)); + kunmap_atomic(d); -err_out: - kunmap(page); + ret = i915_gem_object_set_to_gtt_domain(obj, false); +out: + i915_gem_obj_finish_shmem_access(obj); return ret; + +err: + kunmap_atomic(d); + ret = -EINVAL; + goto out; } #undef OUT_BATCH -int i915_gem_render_state_init(struct drm_i915_gem_request *req) +int i915_gem_render_state_init(struct intel_engine_cs *engine) { - struct render_state so; + struct intel_render_state *so; + const struct intel_renderstate_rodata *rodata; struct drm_i915_gem_object *obj; int ret; - if (WARN_ON(req->engine->id != RCS)) - return -ENOENT; + if (engine->id != RCS) + return 0; - so.rodata = render_state_get_rodata(req); - if (!so.rodata) + rodata = render_state_get_rodata(engine); + if (!rodata) return 0; - if (so.rodata->batch_items * 4 > 4096) + if (rodata->batch_items * 4 > 4096) return -EINVAL; - obj = i915_gem_object_create_internal(req->i915, 4096); - if (IS_ERR(obj)) - return PTR_ERR(obj); + so = kmalloc(sizeof(*so), GFP_KERNEL); + if (!so) + return -ENOMEM; - so.vma = i915_vma_create(obj, &req->i915->ggtt.base, NULL); - if (IS_ERR(so.vma)) { - ret = PTR_ERR(so.vma); - goto err_obj; + obj = i915_gem_object_create_internal(engine->i915, 4096); + if (IS_ERR(obj)) { + ret = PTR_ERR(obj); + goto err_free; } - ret = i915_vma_pin(so.vma, 0, 0, PIN_GLOBAL); - if (ret) + so->vma = i915_vma_create(obj, &engine->i915->ggtt.base, NULL); + if (IS_ERR(so->vma)) { + ret = PTR_ERR(so->vma); goto err_obj; + } + + so->rodata = rodata; + engine->render_state = so; + return 0; - ret = render_state_setup(&so); +err_obj: + i915_gem_object_put(obj); +err_free: + kfree(so); + return ret; +} + +int i915_gem_render_state_emit(struct drm_i915_gem_request *req) +{ + struct intel_render_state *so; + int ret; + + so = req->engine->render_state; + if (!so) + return 0; + + /* Recreate the page after shrinking */ + if (!so->vma->obj->pages) + so->batch_offset = -1; + + ret = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH); if (ret) - goto err_unpin; + return ret; - ret = req->engine->emit_bb_start(req, so.vma->node.start, - so.rodata->batch_items * 4, + if (so->vma->node.start != so->batch_offset) { + ret = render_state_setup(so, req->i915); + if (ret) + goto err_unpin; + } + + ret = req->engine->emit_bb_start(req, + so->batch_offset, so->batch_size, I915_DISPATCH_SECURE); if (ret) goto err_unpin; - if (so.aux_batch_size > 8) { + if (so->aux_size > 8) { ret = req->engine->emit_bb_start(req, - (so.vma->node.start + - so.aux_batch_offset), - so.aux_batch_size, + so->aux_offset, so->aux_size, I915_DISPATCH_SECURE); if (ret) goto err_unpin; } - i915_vma_move_to_active(so.vma, req, 0); + i915_vma_move_to_active(so->vma, req, 0); err_unpin: - i915_vma_unpin(so.vma); - i915_vma_close(so.vma); -err_obj: - __i915_gem_object_release_unless_active(obj); + i915_vma_unpin(so->vma); return ret; } + +void i915_gem_render_state_fini(struct intel_engine_cs *engine) +{ + struct intel_render_state *so; + struct drm_i915_gem_object *obj; + + so = fetch_and_zero(&engine->render_state); + if (!so) + return; + + obj = so->vma->obj; + + i915_vma_close(so->vma); + __i915_gem_object_release_unless_active(obj); + + kfree(so); +} diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.h b/drivers/gpu/drm/i915/i915_gem_render_state.h index 18cce3f06e9c..87481845799d 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.h +++ b/drivers/gpu/drm/i915/i915_gem_render_state.h @@ -26,6 +26,8 @@ struct drm_i915_gem_request; -int i915_gem_render_state_init(struct drm_i915_gem_request *req); +int i915_gem_render_state_init(struct intel_engine_cs *engine); +int i915_gem_render_state_emit(struct drm_i915_gem_request *req); +void i915_gem_render_state_fini(struct intel_engine_cs *engine); #endif /* _I915_GEM_RENDER_STATE_H_ */ diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index b2de371d2bf5..fd551824adf9 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -314,6 +314,10 @@ int intel_engine_init_common(struct intel_engine_cs *engine) if (ret) return ret; + ret = i915_gem_render_state_init(engine); + if (ret) + return ret; + return 0; } @@ -328,6 +332,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) { intel_engine_cleanup_scratch(engine); + i915_gem_render_state_fini(engine); intel_engine_fini_breadcrumbs(engine); intel_engine_cleanup_cmd_parser(engine); i915_gem_batch_pool_fini(&engine->batch_pool); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index bc86585b9fbb..1c1bd30e8b2d 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1637,7 +1637,7 @@ static int gen8_init_rcs_context(struct drm_i915_gem_request *req) if (ret) DRM_ERROR("MOCS failed to program: expect performance issues.\n"); - return i915_gem_render_state_init(req); + return i915_gem_render_state_emit(req); } /** diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a15b9b5f2924..aaa46d9ffbc1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -648,7 +648,7 @@ static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) if (ret != 0) return ret; - ret = i915_gem_render_state_init(req); + ret = i915_gem_render_state_emit(req); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 09bb89cfb7c3..cb6e96c6cd47 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -157,6 +157,7 @@ struct i915_ctx_workarounds { }; struct drm_i915_gem_request; +struct intel_render_state; struct intel_engine_cs { struct drm_i915_private *i915; @@ -184,6 +185,8 @@ struct intel_engine_cs { unsigned int irq_shift; struct intel_ring *buffer; + struct intel_render_state *render_state; + /* Rather than have every client wait upon all user interrupts, * with the herd waking after every interrupt and each doing the * heavyweight seqno dance, we delegate the task (of being the -- cgit v1.2.3 From 4c7d62c6b8a2b4e2300d977644e78b25a2d5f4d0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:32 +0100 Subject: drm/i915: Markup GEM API with lockdep asserts Add lockdep_assert_held(struct_mutex) to the API preamble of the internal GEM interfaces. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-9-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 21 +++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem_evict.c | 5 ++++- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 ++ drivers/gpu/drm/i915/i915_gem_render_state.c | 2 ++ drivers/gpu/drm/i915/i915_gem_request.c | 6 ++++++ 6 files changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 96995d644da2..a1b980129607 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3432,6 +3432,7 @@ int __must_check i915_vma_put_fence(struct i915_vma *vma); static inline bool i915_vma_pin_fence(struct i915_vma *vma) { + lockdep_assert_held(&vma->vm->dev->struct_mutex); if (vma->fence) { vma->fence->pin_count++; return true; @@ -3450,6 +3451,7 @@ i915_vma_pin_fence(struct i915_vma *vma) static inline void i915_vma_unpin_fence(struct i915_vma *vma) { + lockdep_assert_held(&vma->vm->dev->struct_mutex); if (vma->fence) { GEM_BUG_ON(vma->fence->pin_count <= 0); vma->fence->pin_count--; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c0103044dede..528958d8fa5a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -104,6 +104,8 @@ i915_gem_wait_for_error(struct i915_gpu_error *error) { int ret; + might_sleep(); + if (!i915_reset_in_progress(error)) return 0; @@ -2333,6 +2335,8 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) { const struct drm_i915_gem_object_ops *ops = obj->ops; + lockdep_assert_held(&obj->base.dev->struct_mutex); + if (obj->pages == NULL) return 0; @@ -2509,6 +2513,8 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj) const struct drm_i915_gem_object_ops *ops = obj->ops; int ret; + lockdep_assert_held(&obj->base.dev->struct_mutex); + if (obj->pages) return 0; @@ -2790,6 +2796,8 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) struct intel_engine_cs *engine; enum intel_engine_id id; + lockdep_assert_held(&dev_priv->drm.struct_mutex); + i915_gem_retire_requests(dev_priv); for_each_engine(engine, dev_priv, id) @@ -3031,6 +3039,8 @@ int i915_vma_unbind(struct i915_vma *vma) unsigned long active; int ret; + lockdep_assert_held(&obj->base.dev->struct_mutex); + /* First wait upon any activity as retiring the request may * have side-effects such as unpinning or even unbinding this vma. */ @@ -3427,6 +3437,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) int ret; lockdep_assert_held(&obj->base.dev->struct_mutex); + ret = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED | @@ -3505,6 +3516,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, struct i915_vma *vma; int ret = 0; + lockdep_assert_held(&obj->base.dev->struct_mutex); + if (obj->cache_level == cache_level) goto out; @@ -3709,6 +3722,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, u32 old_read_domains, old_write_domain; int ret; + lockdep_assert_held(&obj->base.dev->struct_mutex); + /* Mark the pin_display early so that we account for the * display coherency whilst setting up the cache domains. */ @@ -3774,6 +3789,8 @@ err_unpin_display: void i915_gem_object_unpin_from_display_plane(struct i915_vma *vma) { + lockdep_assert_held(&vma->vm->dev->struct_mutex); + if (WARN_ON(vma->obj->pin_display == 0)) return; @@ -3802,6 +3819,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) int ret; lockdep_assert_held(&obj->base.dev->struct_mutex); + ret = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED | @@ -3962,6 +3980,7 @@ int __i915_vma_do_pin(struct i915_vma *vma, unsigned int bound = vma->flags; int ret; + lockdep_assert_held(&vma->vm->dev->struct_mutex); GEM_BUG_ON((flags & (PIN_GLOBAL | PIN_USER)) == 0); GEM_BUG_ON((flags & PIN_GLOBAL) && !i915_vma_is_ggtt(vma)); @@ -4003,6 +4022,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, struct i915_vma *vma; int ret; + lockdep_assert_held(&obj->base.dev->struct_mutex); + vma = i915_gem_obj_lookup_or_create_vma(obj, vm, view); if (IS_ERR(vma)) return vma; diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index a934f372c5ce..79b964152cd9 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -103,6 +103,7 @@ i915_gem_evict_something(struct i915_address_space *vm, struct i915_vma *vma, *next; int ret; + lockdep_assert_held(&vm->dev->struct_mutex); trace_i915_gem_evict(vm, min_size, alignment, flags); /* @@ -213,6 +214,8 @@ i915_gem_evict_for_vma(struct i915_vma *target) { struct drm_mm_node *node, *next; + lockdep_assert_held(&target->vm->dev->struct_mutex); + list_for_each_entry_safe(node, next, &target->vm->mm.head_node.node_list, node_list) { @@ -266,7 +269,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) struct i915_vma *vma, *next; int ret; - WARN_ON(!mutex_is_locked(&vm->dev->struct_mutex)); + lockdep_assert_held(&vm->dev->struct_mutex); trace_i915_gem_evict_vm(vm); if (do_idle) { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a3a364478a89..2bbbda191e93 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3449,6 +3449,7 @@ i915_vma_create(struct drm_i915_gem_object *obj, struct i915_address_space *vm, const struct i915_ggtt_view *view) { + lockdep_assert_held(&obj->base.dev->struct_mutex); GEM_BUG_ON(view && !i915_is_ggtt(vm)); GEM_BUG_ON(i915_gem_obj_to_vma(obj, vm, view)); @@ -3476,6 +3477,7 @@ i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, { struct i915_vma *vma; + lockdep_assert_held(&obj->base.dev->struct_mutex); GEM_BUG_ON(view && !i915_is_ggtt(vm)); vma = i915_gem_obj_to_vma(obj, vm, view); diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 9625e1a662ed..05293246e0b9 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -223,6 +223,8 @@ int i915_gem_render_state_emit(struct drm_i915_gem_request *req) struct intel_render_state *so; int ret; + lockdep_assert_held(&req->i915->drm.struct_mutex); + so = req->engine->render_state; if (!so) return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index fbe0923fe0bc..d234c28cbb9f 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -143,6 +143,9 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) { struct i915_gem_active *active, *next; + lockdep_assert_held(&request->i915->drm.struct_mutex); + GEM_BUG_ON(!i915_gem_request_completed(request)); + trace_i915_gem_request_retire(request); list_del_init(&request->link); @@ -268,6 +271,8 @@ int i915_gem_set_seqno(struct drm_device *dev, u32 seqno) struct drm_i915_private *dev_priv = to_i915(dev); int ret; + lockdep_assert_held(&dev_priv->drm.struct_mutex); + if (seqno == 0) return -EINVAL; @@ -612,6 +617,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) u32 reserved_tail; int ret; + lockdep_assert_held(&request->i915->drm.struct_mutex); trace_i915_gem_request_add(request); /* -- cgit v1.2.3 From 96d776345277d81dc96e984f13d8f2b84ab0dee4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:33 +0100 Subject: drm/i915: Use a radixtree for random access to the object's backing storage A while ago we switched from a contiguous array of pages into an sglist, for that was both more convenient for mapping to hardware and avoided the requirement for a vmalloc array of pages on every object. However, certain GEM API calls (like pwrite, pread as well as performing relocations) do desire access to individual struct pages. A quick hack was to introduce a cache of the last access such that finding the following page was quick - this works so long as the caller desired sequential access. Walking backwards, or multiple callers, still hits a slow linear search for each page. One solution is to store each successful lookup in a radix tree. v2: Rewrite building the radixtree for clarity, hopefully. v3: Rearrange execbuf to avoid calling i915_gem_object_get_sg() from within an atomic section and so relax the allocation context to a simple GFP_KERNEL and mutex. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-10-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 69 +++++------- drivers/gpu/drm/i915/i915_gem.c | 185 +++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/i915_gem_stolen.c | 4 +- drivers/gpu/drm/i915/i915_gem_userptr.c | 4 +- 4 files changed, 199 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a1b980129607..85ae83a0c937 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2286,9 +2286,12 @@ struct drm_i915_gem_object { struct sg_table *pages; int pages_pin_count; - struct get_page { - struct scatterlist *sg; - int last; + struct i915_gem_object_page_iter { + struct scatterlist *sg_pos; + unsigned int sg_idx; /* in pages, but 32bit eek! */ + + struct radix_tree_root radix; + struct mutex lock; /* protects this cache */ } get_page; void *mapping; @@ -2491,6 +2494,14 @@ static __always_inline struct sgt_iter { return s; } +static inline struct scatterlist *____sg_next(struct scatterlist *sg) +{ + ++sg; + if (unlikely(sg_is_chain(sg))) + sg = sg_chain_ptr(sg); + return sg; +} + /** * __sg_next - return the next scatterlist entry in a list * @sg: The current sg entry @@ -2505,9 +2516,7 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg) #ifdef CONFIG_DEBUG_SG BUG_ON(sg->sg_magic != SG_MAGIC); #endif - return sg_is_last(sg) ? NULL : - likely(!sg_is_chain(++sg)) ? sg : - sg_chain_ptr(sg); + return sg_is_last(sg) ? NULL : ____sg_next(sg); } /** @@ -3185,45 +3194,21 @@ static inline int __sg_page_count(struct scatterlist *sg) return sg->length >> PAGE_SHIFT; } -struct page * -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n); - -static inline dma_addr_t -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, int n) -{ - if (n < obj->get_page.last) { - obj->get_page.sg = obj->pages->sgl; - obj->get_page.last = 0; - } - - while (obj->get_page.last + __sg_page_count(obj->get_page.sg) <= n) { - obj->get_page.last += __sg_page_count(obj->get_page.sg++); - if (unlikely(sg_is_chain(obj->get_page.sg))) - obj->get_page.sg = sg_chain_ptr(obj->get_page.sg); - } +struct scatterlist * +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, + unsigned int n, unsigned int *offset); - return sg_dma_address(obj->get_page.sg) + ((n - obj->get_page.last) << PAGE_SHIFT); -} - -static inline struct page * -i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n) -{ - if (WARN_ON(n >= obj->base.size >> PAGE_SHIFT)) - return NULL; - - if (n < obj->get_page.last) { - obj->get_page.sg = obj->pages->sgl; - obj->get_page.last = 0; - } +struct page * +i915_gem_object_get_page(struct drm_i915_gem_object *obj, + unsigned int n); - while (obj->get_page.last + __sg_page_count(obj->get_page.sg) <= n) { - obj->get_page.last += __sg_page_count(obj->get_page.sg++); - if (unlikely(sg_is_chain(obj->get_page.sg))) - obj->get_page.sg = sg_chain_ptr(obj->get_page.sg); - } +struct page * +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, + unsigned int n); - return nth_page(sg_page(obj->get_page.sg), n - obj->get_page.last); -} +dma_addr_t +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, + unsigned long n); static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 528958d8fa5a..aa0de3aa2565 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2330,6 +2330,15 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) kfree(obj->pages); } +static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj) +{ + struct radix_tree_iter iter; + void **slot; + + radix_tree_for_each_slot(slot, &obj->get_page.radix, &iter, 0) + radix_tree_delete(&obj->get_page.radix, iter.index); +} + int i915_gem_object_put_pages(struct drm_i915_gem_object *obj) { @@ -2362,6 +2371,8 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) obj->mapping = NULL; } + __i915_gem_object_reset_page_iter(obj); + ops->put_pages(obj); obj->pages = NULL; @@ -2531,8 +2542,8 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj) list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list); - obj->get_page.sg = obj->pages->sgl; - obj->get_page.last = 0; + obj->get_page.sg_pos = obj->pages->sgl; + obj->get_page.sg_idx = 0; return 0; } @@ -4337,6 +4348,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, obj->frontbuffer_ggtt_origin = ORIGIN_GTT; obj->madv = I915_MADV_WILLNEED; + INIT_RADIX_TREE(&obj->get_page.radix, GFP_KERNEL | __GFP_NOWARN); + mutex_init(&obj->get_page.lock); i915_gem_info_add_obj(to_i915(obj->base.dev), obj->base.size); } @@ -5032,21 +5045,6 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old, } } -/* Like i915_gem_object_get_page(), but mark the returned page dirty */ -struct page * -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n) -{ - struct page *page; - - /* Only default objects have per-page dirty tracking */ - if (WARN_ON(!i915_gem_object_has_struct_page(obj))) - return NULL; - - page = i915_gem_object_get_page(obj, n); - set_page_dirty(page); - return page; -} - /* Allocate a new GEM object and fill it with the supplied data */ struct drm_i915_gem_object * i915_gem_object_create_from_data(struct drm_device *dev, @@ -5087,3 +5085,156 @@ fail: i915_gem_object_put(obj); return ERR_PTR(ret); } + +struct scatterlist * +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, + unsigned int n, + unsigned int *offset) +{ + struct i915_gem_object_page_iter *iter = &obj->get_page; + struct scatterlist *sg; + unsigned int idx, count; + + might_sleep(); + GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT); + GEM_BUG_ON(obj->pages_pin_count == 0); + + /* As we iterate forward through the sg, we record each entry in a + * radixtree for quick repeated (backwards) lookups. If we have seen + * this index previously, we will have an entry for it. + * + * Initial lookup is O(N), but this is amortized to O(1) for + * sequential page access (where each new request is consecutive + * to the previous one). Repeated lookups are O(lg(obj->base.size)), + * i.e. O(1) with a large constant! + */ + if (n < READ_ONCE(iter->sg_idx)) + goto lookup; + + mutex_lock(&iter->lock); + + /* We prefer to reuse the last sg so that repeated lookup of this + * (or the subsequent) sg are fast - comparing against the last + * sg is faster than going through the radixtree. + */ + + sg = iter->sg_pos; + idx = iter->sg_idx; + count = __sg_page_count(sg); + + while (idx + count <= n) { + unsigned long exception, i; + int ret; + + /* If we cannot allocate and insert this entry, or the + * individual pages from this range, cancel updating the + * sg_idx so that on this lookup we are forced to linearly + * scan onwards, but on future lookups we will try the + * insertion again (in which case we need to be careful of + * the error return reporting that we have already inserted + * this index). + */ + ret = radix_tree_insert(&iter->radix, idx, sg); + if (ret && ret != -EEXIST) + goto scan; + + exception = + RADIX_TREE_EXCEPTIONAL_ENTRY | + idx << RADIX_TREE_EXCEPTIONAL_SHIFT; + for (i = 1; i < count; i++) { + ret = radix_tree_insert(&iter->radix, idx + i, + (void *)exception); + if (ret && ret != -EEXIST) + goto scan; + } + + idx += count; + sg = ____sg_next(sg); + count = __sg_page_count(sg); + } + +scan: + iter->sg_pos = sg; + iter->sg_idx = idx; + + mutex_unlock(&iter->lock); + + if (unlikely(n < idx)) /* insertion completed by another thread */ + goto lookup; + + /* In case we failed to insert the entry into the radixtree, we need + * to look beyond the current sg. + */ + while (idx + count <= n) { + idx += count; + sg = ____sg_next(sg); + count = __sg_page_count(sg); + } + + *offset = n - idx; + return sg; + +lookup: + rcu_read_lock(); + + sg = radix_tree_lookup(&iter->radix, n); + GEM_BUG_ON(!sg); + + /* If this index is in the middle of multi-page sg entry, + * the radixtree will contain an exceptional entry that points + * to the start of that range. We will return the pointer to + * the base page and the offset of this page within the + * sg entry's range. + */ + *offset = 0; + if (unlikely(radix_tree_exception(sg))) { + unsigned long base = + (unsigned long)sg >> RADIX_TREE_EXCEPTIONAL_SHIFT; + + sg = radix_tree_lookup(&iter->radix, base); + GEM_BUG_ON(!sg); + + *offset = n - base; + } + + rcu_read_unlock(); + + return sg; +} + +struct page * +i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n) +{ + struct scatterlist *sg; + unsigned int offset; + + GEM_BUG_ON(!i915_gem_object_has_struct_page(obj)); + + sg = i915_gem_object_get_sg(obj, n, &offset); + return nth_page(sg_page(sg), offset); +} + +/* Like i915_gem_object_get_page(), but mark the returned page dirty */ +struct page * +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, + unsigned int n) +{ + struct page *page; + + page = i915_gem_object_get_page(obj, n); + if (!obj->dirty) + set_page_dirty(page); + + return page; +} + +dma_addr_t +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, + unsigned long n) +{ + struct scatterlist *sg; + unsigned int offset; + + sg = i915_gem_object_get_sg(obj, n, &offset); + return sg_dma_address(sg) + (offset << PAGE_SHIFT); +} diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index f4f6d3a48b05..70e61bc35c60 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -595,8 +595,8 @@ _i915_gem_object_create_stolen(struct drm_device *dev, if (obj->pages == NULL) goto cleanup; - obj->get_page.sg = obj->pages->sgl; - obj->get_page.last = 0; + obj->get_page.sg_pos = obj->pages->sgl; + obj->get_page.sg_idx = 0; i915_gem_object_pin_pages(obj); obj->stolen = stolen; diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index c49dd95413bd..e2fa970bb629 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -530,8 +530,8 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) if (ret == 0) { list_add_tail(&obj->global_list, &to_i915(dev)->mm.unbound_list); - obj->get_page.sg = obj->pages->sgl; - obj->get_page.last = 0; + obj->get_page.sg_pos = obj->pages->sgl; + obj->get_page.sg_idx = 0; pinned = 0; } } -- cgit v1.2.3 From d2a84a76a3b970fa32e6eda3d85e7782f831379e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:34 +0100 Subject: drm/i915: Use radixtree to jump start intel_partial_pages() We can use the radixtree index of the obj->pages to find the start position of the desired partial range. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-11-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 40 ++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2bbbda191e93..b3f341fe77bf 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3584,35 +3584,47 @@ intel_partial_pages(const struct i915_ggtt_view *view, struct drm_i915_gem_object *obj) { struct sg_table *st; - struct scatterlist *sg; - struct sg_page_iter obj_sg_iter; + struct scatterlist *sg, *iter; + unsigned int count = view->params.partial.size; + unsigned int offset; int ret = -ENOMEM; st = kmalloc(sizeof(*st), GFP_KERNEL); if (!st) goto err_st_alloc; - ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL); + ret = sg_alloc_table(st, count, GFP_KERNEL); if (ret) goto err_sg_alloc; + iter = i915_gem_object_get_sg(obj, + view->params.partial.offset, + &offset); + GEM_BUG_ON(!iter); + sg = st->sgl; st->nents = 0; - for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents, - view->params.partial.offset) - { - if (st->nents >= view->params.partial.size) - break; + do { + unsigned int len; - sg_set_page(sg, NULL, PAGE_SIZE, 0); - sg_dma_address(sg) = sg_page_iter_dma_address(&obj_sg_iter); - sg_dma_len(sg) = PAGE_SIZE; + len = min(iter->length - (offset << PAGE_SHIFT), + count << PAGE_SHIFT); + sg_set_page(sg, NULL, len, 0); + sg_dma_address(sg) = + sg_dma_address(iter) + (offset << PAGE_SHIFT); + sg_dma_len(sg) = len; - sg = sg_next(sg); st->nents++; - } + count -= len >> PAGE_SHIFT; + if (count == 0) { + sg_mark_end(sg); + return st; + } - return st; + sg = __sg_next(sg); + iter = __sg_next(iter); + offset = 0; + } while (1); err_sg_alloc: kfree(st); -- cgit v1.2.3 From a4f5ea64f0a818586b9de71803824b43dd01e517 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:35 +0100 Subject: drm/i915: Refactor object page API The plan is to make obtaining the backing storage for the object avoid struct_mutex (i.e. use its own locking). The first step is to update the API so that normal users only call pin/unpin whilst working on the backing storage. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-12-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_cmd_parser.c | 2 +- drivers/gpu/drm/i915/i915_debugfs.c | 17 +-- drivers/gpu/drm/i915/i915_drv.h | 94 ++++++++---- drivers/gpu/drm/i915/i915_gem.c | 205 +++++++++++++-------------- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 3 +- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 14 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/i915_gem_fence.c | 4 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 10 +- drivers/gpu/drm/i915/i915_gem_internal.c | 12 +- drivers/gpu/drm/i915/i915_gem_render_state.c | 2 +- drivers/gpu/drm/i915/i915_gem_shrinker.c | 10 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 24 ++-- drivers/gpu/drm/i915/i915_gem_tiling.c | 8 +- drivers/gpu/drm/i915/i915_gem_userptr.c | 30 ++-- drivers/gpu/drm/i915/i915_gpu_error.c | 4 +- drivers/gpu/drm/i915/intel_lrc.c | 6 +- 17 files changed, 233 insertions(+), 214 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index f191d7b66b1d..f5039f4f988f 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1290,7 +1290,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, } if (ret == 0 && needs_clflush_after) - drm_clflush_virt_range(shadow_batch_obj->mapping, batch_len); + drm_clflush_virt_range(shadow_batch_obj->mm.mapping, batch_len); i915_gem_object_unpin_map(shadow_batch_obj); return ret; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9f5a39209f52..e97a16cb6b67 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -112,7 +112,7 @@ static char get_global_flag(struct drm_i915_gem_object *obj) static char get_pin_mapped_flag(struct drm_i915_gem_object *obj) { - return obj->mapping ? 'M' : ' '; + return obj->mm.mapping ? 'M' : ' '; } static u64 i915_gem_obj_total_ggtt_size(struct drm_i915_gem_object *obj) @@ -158,8 +158,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) i915_gem_active_get_seqno(&obj->last_write, &obj->base.dev->struct_mutex), i915_cache_level_str(dev_priv, obj->cache_level), - obj->dirty ? " dirty" : "", - obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); + obj->mm.dirty ? " dirty" : "", + obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : ""); if (obj->base.name) seq_printf(m, " (name: %d)", obj->base.name); list_for_each_entry(vma, &obj->vma_list, obj_link) { @@ -403,12 +403,12 @@ static int i915_gem_object_info(struct seq_file *m, void *data) size += obj->base.size; ++count; - if (obj->madv == I915_MADV_DONTNEED) { + if (obj->mm.madv == I915_MADV_DONTNEED) { purgeable_size += obj->base.size; ++purgeable_count; } - if (obj->mapping) { + if (obj->mm.mapping) { mapped_count++; mapped_size += obj->base.size; } @@ -425,12 +425,12 @@ static int i915_gem_object_info(struct seq_file *m, void *data) ++dpy_count; } - if (obj->madv == I915_MADV_DONTNEED) { + if (obj->mm.madv == I915_MADV_DONTNEED) { purgeable_size += obj->base.size; ++purgeable_count; } - if (obj->mapping) { + if (obj->mm.mapping) { mapped_count++; mapped_size += obj->base.size; } @@ -2028,7 +2028,7 @@ static void i915_dump_lrc_obj(struct seq_file *m, seq_printf(m, "\tBound in GGTT at 0x%08x\n", i915_ggtt_offset(vma)); - if (i915_gem_object_get_pages(vma->obj)) { + if (i915_gem_object_pin_pages(vma->obj)) { seq_puts(m, "\tFailed to get pages for context object\n\n"); return; } @@ -2047,6 +2047,7 @@ static void i915_dump_lrc_obj(struct seq_file *m, kunmap_atomic(reg_state); } + i915_gem_object_unpin_pages(vma->obj); seq_putc(m, '\n'); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 85ae83a0c937..50781cbe74d0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2252,17 +2252,6 @@ struct drm_i915_gem_object { */ #define I915_BO_ACTIVE_REF (I915_BO_ACTIVE_SHIFT + I915_NUM_ENGINES) - /** - * This is set if the object has been written to since last bound - * to the GTT - */ - unsigned int dirty:1; - - /** - * Advice: are the backing pages purgeable? - */ - unsigned int madv:2; - /* * Is the object to be mapped as read-only to the GPU * Only honoured if hardware has relevant pte bit @@ -2284,16 +2273,31 @@ struct drm_i915_gem_object { unsigned int bind_count; unsigned int pin_display; - struct sg_table *pages; - int pages_pin_count; - struct i915_gem_object_page_iter { - struct scatterlist *sg_pos; - unsigned int sg_idx; /* in pages, but 32bit eek! */ + struct { + unsigned int pages_pin_count; + + struct sg_table *pages; + void *mapping; - struct radix_tree_root radix; - struct mutex lock; /* protects this cache */ - } get_page; - void *mapping; + struct i915_gem_object_page_iter { + struct scatterlist *sg_pos; + unsigned int sg_idx; /* in pages, but 32bit eek! */ + + struct radix_tree_root radix; + struct mutex lock; /* protects this cache */ + } get_page; + + /** + * Advice: are the backing pages purgeable? + */ + unsigned int madv:2; + + /** + * This is set if the object has been written to since the + * pages were last acquired. + */ + bool dirty:1; + } mm; /** Breadcrumb of last rendering to the buffer. * There can only be one writer, but we allow for multiple readers. @@ -3182,14 +3186,11 @@ void i915_vma_close(struct i915_vma *vma); void i915_vma_destroy(struct i915_vma *vma); int i915_gem_object_unbind(struct drm_i915_gem_object *obj); -int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); void i915_gem_release_mmap(struct drm_i915_gem_object *obj); void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv); -int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj); - -static inline int __sg_page_count(struct scatterlist *sg) +static inline int __sg_page_count(const struct scatterlist *sg) { return sg->length >> PAGE_SHIFT; } @@ -3210,19 +3211,52 @@ dma_addr_t i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, unsigned long n); -static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) +int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj); + +static inline int __must_check +i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) +{ + lockdep_assert_held(&obj->base.dev->struct_mutex); + + if (obj->mm.pages_pin_count++) + return 0; + + return __i915_gem_object_get_pages(obj); +} + +static inline void +__i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { - GEM_BUG_ON(obj->pages == NULL); - obj->pages_pin_count++; + lockdep_assert_held(&obj->base.dev->struct_mutex); + GEM_BUG_ON(!obj->mm.pages); + + obj->mm.pages_pin_count++; +} + +static inline bool +i915_gem_object_has_pinned_pages(struct drm_i915_gem_object *obj) +{ + return obj->mm.pages_pin_count; +} + +static inline void +__i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) +{ + lockdep_assert_held(&obj->base.dev->struct_mutex); + GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); + GEM_BUG_ON(!obj->mm.pages); + + obj->mm.pages_pin_count--; + GEM_BUG_ON(obj->mm.pages_pin_count < obj->bind_count); } static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) { - GEM_BUG_ON(obj->pages_pin_count == 0); - obj->pages_pin_count--; - GEM_BUG_ON(obj->pages_pin_count < obj->bind_count); + __i915_gem_object_unpin_pages(obj); } +int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj); + enum i915_map_type { I915_MAP_WB = 0, I915_MAP_WC, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index aa0de3aa2565..0d702c8f7b7b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -216,7 +216,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) sg_dma_address(sg) = obj->phys_handle->busaddr; sg_dma_len(sg) = obj->base.size; - obj->pages = st; + obj->mm.pages = st; return 0; } @@ -225,7 +225,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj) { int ret; - BUG_ON(obj->madv == __I915_MADV_PURGED); + GEM_BUG_ON(obj->mm.madv == __I915_MADV_PURGED); ret = i915_gem_object_set_to_cpu_domain(obj, true); if (WARN_ON(ret)) { @@ -235,10 +235,10 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj) obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU; } - if (obj->madv == I915_MADV_DONTNEED) - obj->dirty = 0; + if (obj->mm.madv == I915_MADV_DONTNEED) + obj->mm.dirty = false; - if (obj->dirty) { + if (obj->mm.dirty) { struct address_space *mapping = obj->base.filp->f_mapping; char *vaddr = obj->phys_handle->vaddr; int i; @@ -257,22 +257,23 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj) kunmap_atomic(dst); set_page_dirty(page); - if (obj->madv == I915_MADV_WILLNEED) + if (obj->mm.madv == I915_MADV_WILLNEED) mark_page_accessed(page); put_page(page); vaddr += PAGE_SIZE; } - obj->dirty = 0; + obj->mm.dirty = false; } - sg_free_table(obj->pages); - kfree(obj->pages); + sg_free_table(obj->mm.pages); + kfree(obj->mm.pages); } static void i915_gem_object_release_phys(struct drm_i915_gem_object *obj) { drm_pci_free(obj->base.dev, obj->phys_handle); + i915_gem_object_unpin_pages(obj); } static const struct drm_i915_gem_object_ops i915_gem_phys_ops = { @@ -507,7 +508,7 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, return 0; } - if (obj->madv != I915_MADV_WILLNEED) + if (obj->mm.madv != I915_MADV_WILLNEED) return -EFAULT; if (obj->base.filp == NULL) @@ -517,7 +518,7 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, if (ret) return ret; - ret = i915_gem_object_put_pages(obj); + ret = __i915_gem_object_put_pages(obj); if (ret) return ret; @@ -529,7 +530,7 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, obj->phys_handle = phys; obj->ops = &i915_gem_phys_ops; - return i915_gem_object_get_pages(obj); + return i915_gem_object_pin_pages(obj); } static int @@ -725,12 +726,10 @@ int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj, if (ret) return ret; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) return ret; - i915_gem_object_pin_pages(obj); - i915_gem_object_flush_gtt_write_domain(obj); /* If we're not in the cpu read domain, set ourself into the gtt @@ -778,12 +777,10 @@ int i915_gem_obj_prepare_shmem_write(struct drm_i915_gem_object *obj, if (ret) return ret; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) return ret; - i915_gem_object_pin_pages(obj); - i915_gem_object_flush_gtt_write_domain(obj); /* If we're not in the cpu write domain, set ourself into the @@ -813,7 +810,7 @@ int i915_gem_obj_prepare_shmem_write(struct drm_i915_gem_object *obj, obj->cache_dirty = true; intel_fb_obj_invalidate(obj, ORIGIN_CPU); - obj->dirty = 1; + obj->mm.dirty = true; /* return with the pages pinned */ return 0; @@ -951,13 +948,11 @@ i915_gem_gtt_pread(struct drm_device *dev, if (ret) goto out; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) { remove_mappable_node(&node); goto out; } - - i915_gem_object_pin_pages(obj); } ret = i915_gem_object_set_to_gtt_domain(obj, false); @@ -1064,7 +1059,7 @@ i915_gem_shmem_pread(struct drm_device *dev, offset = args->offset; remain = args->size; - for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, + for_each_sg_page(obj->mm.pages->sgl, &sg_iter, obj->mm.pages->nents, offset >> PAGE_SHIFT) { struct page *page = sg_page_iter_page(&sg_iter); @@ -1254,13 +1249,11 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915, if (ret) goto out; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) { remove_mappable_node(&node); goto out; } - - i915_gem_object_pin_pages(obj); } ret = i915_gem_object_set_to_gtt_domain(obj, true); @@ -1268,7 +1261,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915, goto out_unpin; intel_fb_obj_invalidate(obj, ORIGIN_CPU); - obj->dirty = true; + obj->mm.dirty = true; user_data = u64_to_user_ptr(args->data_ptr); offset = args->offset; @@ -1439,7 +1432,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, offset = args->offset; remain = args->size; - for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, + for_each_sg_page(obj->mm.pages->sgl, &sg_iter, obj->mm.pages->nents, offset >> PAGE_SHIFT) { struct page *page = sg_page_iter_page(&sg_iter); int partial_cacheline_write; @@ -2266,7 +2259,7 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj) * backing pages, *now*. */ shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1); - obj->madv = __I915_MADV_PURGED; + obj->mm.madv = __I915_MADV_PURGED; } /* Try to discard unwanted pages */ @@ -2275,7 +2268,7 @@ i915_gem_object_invalidate(struct drm_i915_gem_object *obj) { struct address_space *mapping; - switch (obj->madv) { + switch (obj->mm.madv) { case I915_MADV_DONTNEED: i915_gem_object_truncate(obj); case __I915_MADV_PURGED: @@ -2296,7 +2289,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) struct page *page; int ret; - BUG_ON(obj->madv == __I915_MADV_PURGED); + GEM_BUG_ON(obj->mm.madv == __I915_MADV_PURGED); ret = i915_gem_object_set_to_cpu_domain(obj, true); if (WARN_ON(ret)) { @@ -2312,22 +2305,22 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) if (i915_gem_object_needs_bit17_swizzle(obj)) i915_gem_object_save_bit_17_swizzle(obj); - if (obj->madv == I915_MADV_DONTNEED) - obj->dirty = 0; + if (obj->mm.madv == I915_MADV_DONTNEED) + obj->mm.dirty = false; - for_each_sgt_page(page, sgt_iter, obj->pages) { - if (obj->dirty) + for_each_sgt_page(page, sgt_iter, obj->mm.pages) { + if (obj->mm.dirty) set_page_dirty(page); - if (obj->madv == I915_MADV_WILLNEED) + if (obj->mm.madv == I915_MADV_WILLNEED) mark_page_accessed(page); put_page(page); } - obj->dirty = 0; + obj->mm.dirty = false; - sg_free_table(obj->pages); - kfree(obj->pages); + sg_free_table(obj->mm.pages); + kfree(obj->mm.pages); } static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj) @@ -2335,21 +2328,20 @@ static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj) struct radix_tree_iter iter; void **slot; - radix_tree_for_each_slot(slot, &obj->get_page.radix, &iter, 0) - radix_tree_delete(&obj->get_page.radix, iter.index); + radix_tree_for_each_slot(slot, &obj->mm.get_page.radix, &iter, 0) + radix_tree_delete(&obj->mm.get_page.radix, iter.index); } -int -i915_gem_object_put_pages(struct drm_i915_gem_object *obj) +int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) { const struct drm_i915_gem_object_ops *ops = obj->ops; lockdep_assert_held(&obj->base.dev->struct_mutex); - if (obj->pages == NULL) + if (!obj->mm.pages) return 0; - if (obj->pages_pin_count) + if (i915_gem_object_has_pinned_pages(obj)) return -EBUSY; GEM_BUG_ON(obj->bind_count); @@ -2359,22 +2351,22 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) * lists early. */ list_del(&obj->global_list); - if (obj->mapping) { + if (obj->mm.mapping) { void *ptr; - ptr = ptr_mask_bits(obj->mapping); + ptr = ptr_mask_bits(obj->mm.mapping); if (is_vmalloc_addr(ptr)) vunmap(ptr); else kunmap(kmap_to_page(ptr)); - obj->mapping = NULL; + obj->mm.mapping = NULL; } __i915_gem_object_reset_page_iter(obj); ops->put_pages(obj); - obj->pages = NULL; + obj->mm.pages = NULL; i915_gem_object_invalidate(obj); @@ -2474,7 +2466,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) } if (sg) /* loop terminated early; short sg table */ sg_mark_end(sg); - obj->pages = st; + obj->mm.pages = st; ret = i915_gem_gtt_prepare_object(obj); if (ret) @@ -2485,7 +2477,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) if (i915_gem_object_is_tiled(obj) && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) - i915_gem_object_pin_pages(obj); + __i915_gem_object_pin_pages(obj); return 0; @@ -2517,8 +2509,7 @@ err_pages: * either as a result of memory pressure (reaping pages under the shrinker) * or as the object is itself released. */ -int -i915_gem_object_get_pages(struct drm_i915_gem_object *obj) +int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = to_i915(obj->base.dev); const struct drm_i915_gem_object_ops *ops = obj->ops; @@ -2526,24 +2517,25 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj) lockdep_assert_held(&obj->base.dev->struct_mutex); - if (obj->pages) + if (obj->mm.pages) return 0; - if (obj->madv != I915_MADV_WILLNEED) { + if (obj->mm.madv != I915_MADV_WILLNEED) { DRM_DEBUG("Attempting to obtain a purgeable object\n"); + __i915_gem_object_unpin_pages(obj); return -EFAULT; } - BUG_ON(obj->pages_pin_count); - ret = ops->get_pages(obj); - if (ret) + if (ret) { + __i915_gem_object_unpin_pages(obj); return ret; + } list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list); - obj->get_page.sg_pos = obj->pages->sgl; - obj->get_page.sg_idx = 0; + obj->mm.get_page.sg_pos = obj->mm.pages->sgl; + obj->mm.get_page.sg_idx = 0; return 0; } @@ -2553,7 +2545,7 @@ static void *i915_gem_object_map(const struct drm_i915_gem_object *obj, enum i915_map_type type) { unsigned long n_pages = obj->base.size >> PAGE_SHIFT; - struct sg_table *sgt = obj->pages; + struct sg_table *sgt = obj->mm.pages; struct sgt_iter sgt_iter; struct page *page; struct page *stack_pages[32]; @@ -2607,14 +2599,13 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, lockdep_assert_held(&obj->base.dev->struct_mutex); GEM_BUG_ON(!i915_gem_object_has_struct_page(obj)); - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) return ERR_PTR(ret); - i915_gem_object_pin_pages(obj); - pinned = obj->pages_pin_count > 1; + pinned = obj->mm.pages_pin_count > 1; - ptr = ptr_unpack_bits(obj->mapping, has_type); + ptr = ptr_unpack_bits(obj->mm.mapping, has_type); if (ptr && has_type != type) { if (pinned) { ret = -EBUSY; @@ -2626,7 +2617,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, else kunmap(kmap_to_page(ptr)); - ptr = obj->mapping = NULL; + ptr = obj->mm.mapping = NULL; } if (!ptr) { @@ -2636,7 +2627,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, goto err; } - obj->mapping = ptr_pack_bits(ptr, type); + obj->mm.mapping = ptr_pack_bits(ptr, type); } return ptr; @@ -3087,7 +3078,7 @@ int i915_vma_unbind(struct i915_vma *vma) goto destroy; GEM_BUG_ON(obj->bind_count == 0); - GEM_BUG_ON(!obj->pages); + GEM_BUG_ON(!obj->mm.pages); if (i915_vma_is_map_and_fenceable(vma)) { /* release the fence reg _after_ flushing */ @@ -3111,7 +3102,7 @@ int i915_vma_unbind(struct i915_vma *vma) drm_mm_remove_node(&vma->node); list_move_tail(&vma->vm_link, &vma->vm->unbound_list); - if (vma->pages != obj->pages) { + if (vma->pages != obj->mm.pages) { GEM_BUG_ON(!vma->pages); sg_free_table(vma->pages); kfree(vma->pages); @@ -3244,12 +3235,10 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) return -E2BIG; } - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) return ret; - i915_gem_object_pin_pages(obj); - if (flags & PIN_OFFSET_FIXED) { u64 offset = flags & PIN_OFFSET_MASK; if (offset & (alignment - 1) || offset > end - size) { @@ -3331,7 +3320,7 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj, * to GPU, and we can ignore the cache flush because it'll happen * again at bind time. */ - if (obj->pages == NULL) + if (!obj->mm.pages) return false; /* @@ -3355,7 +3344,7 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj, } trace_i915_gem_object_clflush(obj); - drm_clflush_sg(obj->pages); + drm_clflush_sg(obj->mm.pages); obj->cache_dirty = false; return true; @@ -3469,7 +3458,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) * continue to assume that the obj remained out of the CPU cached * domain. */ - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) return ret; @@ -3493,7 +3482,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) if (write) { obj->base.read_domains = I915_GEM_DOMAIN_GTT; obj->base.write_domain = I915_GEM_DOMAIN_GTT; - obj->dirty = 1; + obj->mm.dirty = true; } trace_i915_gem_object_change_domain(obj, @@ -3502,6 +3491,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) /* And bump the LRU for this access */ i915_gem_object_bump_inactive_ggtt(obj); + i915_gem_object_unpin_pages(obj); return 0; } @@ -4304,23 +4294,23 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, goto unlock; } - if (obj->pages && + if (obj->mm.pages && i915_gem_object_is_tiled(obj) && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { - if (obj->madv == I915_MADV_WILLNEED) - i915_gem_object_unpin_pages(obj); + if (obj->mm.madv == I915_MADV_WILLNEED) + __i915_gem_object_unpin_pages(obj); if (args->madv == I915_MADV_WILLNEED) - i915_gem_object_pin_pages(obj); + __i915_gem_object_pin_pages(obj); } - if (obj->madv != __I915_MADV_PURGED) - obj->madv = args->madv; + if (obj->mm.madv != __I915_MADV_PURGED) + obj->mm.madv = args->madv; /* if the object is no longer attached, discard its backing storage */ - if (obj->madv == I915_MADV_DONTNEED && obj->pages == NULL) + if (obj->mm.madv == I915_MADV_DONTNEED && !obj->mm.pages) i915_gem_object_truncate(obj); - args->retained = obj->madv != __I915_MADV_PURGED; + args->retained = obj->mm.madv != __I915_MADV_PURGED; i915_gem_object_put(obj); unlock: @@ -4347,9 +4337,10 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, obj->ops = ops; obj->frontbuffer_ggtt_origin = ORIGIN_GTT; - obj->madv = I915_MADV_WILLNEED; - INIT_RADIX_TREE(&obj->get_page.radix, GFP_KERNEL | __GFP_NOWARN); - mutex_init(&obj->get_page.lock); + + obj->mm.madv = I915_MADV_WILLNEED; + INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN); + mutex_init(&obj->mm.get_page.lock); i915_gem_info_add_obj(to_i915(obj->base.dev), obj->base.size); } @@ -4441,7 +4432,7 @@ static bool discard_backing_storage(struct drm_i915_gem_object *obj) * back the contents from the GPU. */ - if (obj->madv != I915_MADV_WILLNEED) + if (obj->mm.madv != I915_MADV_WILLNEED) return false; if (obj->base.filp == NULL) @@ -4483,32 +4474,27 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) } GEM_BUG_ON(obj->bind_count); - /* Stolen objects don't hold a ref, but do hold pin count. Fix that up - * before progressing. */ - if (obj->stolen) - i915_gem_object_unpin_pages(obj); - WARN_ON(atomic_read(&obj->frontbuffer_bits)); - if (obj->pages && obj->madv == I915_MADV_WILLNEED && + if (obj->mm.pages && obj->mm.madv == I915_MADV_WILLNEED && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES && i915_gem_object_is_tiled(obj)) - i915_gem_object_unpin_pages(obj); + __i915_gem_object_unpin_pages(obj); - if (WARN_ON(obj->pages_pin_count)) - obj->pages_pin_count = 0; + if (obj->ops->release) + obj->ops->release(obj); + + if (WARN_ON(i915_gem_object_has_pinned_pages(obj))) + obj->mm.pages_pin_count = 0; if (discard_backing_storage(obj)) - obj->madv = I915_MADV_DONTNEED; - i915_gem_object_put_pages(obj); + obj->mm.madv = I915_MADV_DONTNEED; + __i915_gem_object_put_pages(obj); - BUG_ON(obj->pages); + GEM_BUG_ON(obj->mm.pages); if (obj->base.import_attach) drm_prime_gem_destroy(&obj->base, NULL); - if (obj->ops->release) - obj->ops->release(obj); - drm_gem_object_release(&obj->base); i915_gem_info_remove_obj(dev_priv, obj->base.size); @@ -5063,14 +5049,13 @@ i915_gem_object_create_from_data(struct drm_device *dev, if (ret) goto fail; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) goto fail; - i915_gem_object_pin_pages(obj); - sg = obj->pages; + sg = obj->mm.pages; bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size); - obj->dirty = 1; /* Backing store is now out of date */ + obj->mm.dirty = true; /* Backing store is now out of date */ i915_gem_object_unpin_pages(obj); if (WARN_ON(bytes != size)) { @@ -5091,13 +5076,13 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj, unsigned int n, unsigned int *offset) { - struct i915_gem_object_page_iter *iter = &obj->get_page; + struct i915_gem_object_page_iter *iter = &obj->mm.get_page; struct scatterlist *sg; unsigned int idx, count; might_sleep(); GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT); - GEM_BUG_ON(obj->pages_pin_count == 0); + GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); /* As we iterate forward through the sg, we record each entry in a * radixtree for quick repeated (backwards) lookups. If we have seen @@ -5222,7 +5207,7 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, struct page *page; page = i915_gem_object_get_page(obj, n); - if (!obj->dirty) + if (!obj->mm.dirty) set_page_dirty(page); return page; diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index aa4e1e043b4e..e0f38e5c0fbb 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -130,11 +130,10 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, return obj; } - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) return ERR_PTR(ret); list_move_tail(&obj->batch_pool_link, list); - i915_gem_object_pin_pages(obj); return obj; } diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 97c9d68b45df..10441dc72e73 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -48,12 +48,10 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme if (ret) goto err; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_pin_pages(obj); if (ret) goto err_unlock; - i915_gem_object_pin_pages(obj); - /* Copy sg so that we make an independent mapping */ st = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (st == NULL) { @@ -61,13 +59,13 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme goto err_unpin; } - ret = sg_alloc_table(st, obj->pages->nents, GFP_KERNEL); + ret = sg_alloc_table(st, obj->mm.pages->nents, GFP_KERNEL); if (ret) goto err_free; - src = obj->pages->sgl; + src = obj->mm.pages->sgl; dst = st->sgl; - for (i = 0; i < obj->pages->nents; i++) { + for (i = 0; i < obj->mm.pages->nents; i++) { sg_set_page(dst, sg_page(src), src->length, 0); dst = sg_next(dst); src = sg_next(src); @@ -299,14 +297,14 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) if (IS_ERR(sg)) return PTR_ERR(sg); - obj->pages = sg; + obj->mm.pages = sg; return 0; } static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj) { dma_buf_unmap_attachment(obj->base.import_attach, - obj->pages, DMA_BIDIRECTIONAL); + obj->mm.pages, DMA_BIDIRECTIONAL); } static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = { diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 4cafce97998a..d95c4e02eeb9 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1281,7 +1281,7 @@ void i915_vma_move_to_active(struct i915_vma *vma, GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); - obj->dirty = 1; /* be paranoid */ + obj->mm.dirty = true; /* be paranoid */ /* Add a reference if we're newly entering the active list. * The order in which we add operations to the retirement queue is diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index 3c5a8082cac3..5aadab59f071 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -664,7 +664,7 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) return; i = 0; - for_each_sgt_page(page, sgt_iter, obj->pages) { + for_each_sgt_page(page, sgt_iter, obj->mm.pages) { char new_bit_17 = page_to_phys(page) >> 17; if ((new_bit_17 & 0x1) != (test_bit(i, obj->bit_17) != 0)) { @@ -703,7 +703,7 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) i = 0; - for_each_sgt_page(page, sgt_iter, obj->pages) { + for_each_sgt_page(page, sgt_iter, obj->mm.pages) { if (page_to_phys(page) & (1 << 17)) __set_bit(i, obj->bit_17); else diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index b3f341fe77bf..794ccc4cffaa 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -175,7 +175,7 @@ static int ppgtt_bind_vma(struct i915_vma *vma, { u32 pte_flags = 0; - vma->pages = vma->obj->pages; + vma->pages = vma->obj->mm.pages; /* Currently applicable only to VLV */ if (vma->obj->gt_ro) @@ -2373,7 +2373,7 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) { if (!dma_map_sg(&obj->base.dev->pdev->dev, - obj->pages->sgl, obj->pages->nents, + obj->mm.pages->sgl, obj->mm.pages->nents, PCI_DMA_BIDIRECTIONAL)) return -ENOSPC; @@ -2710,7 +2710,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) } } - dma_unmap_sg(kdev, obj->pages->sgl, obj->pages->nents, + dma_unmap_sg(kdev, obj->mm.pages->sgl, obj->mm.pages->nents, PCI_DMA_BIDIRECTIONAL); } @@ -3548,7 +3548,7 @@ intel_rotate_fb_obj_pages(const struct intel_rotation_info *rot_info, /* Populate source page list from the object. */ i = 0; - for_each_sgt_dma(dma_addr, sgt_iter, obj->pages) + for_each_sgt_dma(dma_addr, sgt_iter, obj->mm.pages) page_addr_list[i++] = dma_addr; GEM_BUG_ON(i != n_pages); @@ -3641,7 +3641,7 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) return 0; if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) - vma->pages = vma->obj->pages; + vma->pages = vma->obj->mm.pages; else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED) vma->pages = intel_rotate_fb_obj_pages(&vma->ggtt_view.params.rotated, vma->obj); diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index 02e66fa170b0..08a2576ff7d2 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -102,10 +102,10 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) sg = __sg_next(sg); } while (1); - obj->pages = st; + obj->mm.pages = st; if (i915_gem_gtt_prepare_object(obj)) { - obj->pages = NULL; + obj->mm.pages = NULL; goto err; } @@ -114,7 +114,7 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) * and the caller is expected to repopulate - the contents of this * object are only valid whilst active and pinned. */ - obj->madv = I915_MADV_DONTNEED; + obj->mm.madv = I915_MADV_DONTNEED; return 0; err: @@ -126,10 +126,10 @@ err: static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj) { i915_gem_gtt_finish_object(obj); - internal_free_pages(obj->pages); + internal_free_pages(obj->mm.pages); - obj->dirty = 0; - obj->madv = I915_MADV_WILLNEED; + obj->mm.dirty = false; + obj->mm.madv = I915_MADV_WILLNEED; } static const struct drm_i915_gem_object_ops i915_gem_object_internal_ops = { diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 05293246e0b9..57918f21ecc3 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -230,7 +230,7 @@ int i915_gem_render_state_emit(struct drm_i915_gem_request *req) return 0; /* Recreate the page after shrinking */ - if (!so->vma->obj->pages) + if (!so->vma->obj->mm.pages) so->batch_offset = -1; ret = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH); diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index de25b6e0a101..124f69a80162 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -78,7 +78,7 @@ static bool can_release_pages(struct drm_i915_gem_object *obj) * to the GPU, simply unbinding from the GPU is not going to succeed * in releasing our pin count on the pages themselves. */ - if (obj->pages_pin_count > obj->bind_count) + if (obj->mm.pages_pin_count > obj->bind_count) return false; if (any_vma_pinned(obj)) @@ -88,7 +88,7 @@ static bool can_release_pages(struct drm_i915_gem_object *obj) * discard the contents (because the user has marked them as being * purgeable) or if we can move their contents out to swap. */ - return swap_available() || obj->madv == I915_MADV_DONTNEED; + return swap_available() || obj->mm.madv == I915_MADV_DONTNEED; } /** @@ -175,11 +175,11 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, list_move_tail(&obj->global_list, &still_in_list); if (flags & I915_SHRINK_PURGEABLE && - obj->madv != I915_MADV_DONTNEED) + obj->mm.madv != I915_MADV_DONTNEED) continue; if (flags & I915_SHRINK_VMAPS && - !is_vmalloc_addr(obj->mapping)) + !is_vmalloc_addr(obj->mm.mapping)) continue; if (!(flags & I915_SHRINK_ACTIVE) && @@ -194,7 +194,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, /* For the unbound phase, this should be a no-op! */ i915_gem_object_unbind(obj); - if (i915_gem_object_put_pages(obj) == 0) + if (__i915_gem_object_put_pages(obj) == 0) count += obj->base.size >> PAGE_SHIFT; i915_gem_object_put(obj); diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 70e61bc35c60..0acbdcbd8f3a 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -555,16 +555,17 @@ static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj) static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj) { /* Should only be called during free */ - sg_free_table(obj->pages); - kfree(obj->pages); + sg_free_table(obj->mm.pages); + kfree(obj->mm.pages); } - static void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + __i915_gem_object_unpin_pages(obj); + if (obj->stolen) { i915_gem_stolen_remove_node(dev_priv, obj->stolen); kfree(obj->stolen); @@ -590,15 +591,16 @@ _i915_gem_object_create_stolen(struct drm_device *dev, drm_gem_private_object_init(dev, &obj->base, stolen->size); i915_gem_object_init(obj, &i915_gem_object_stolen_ops); - obj->pages = i915_pages_create_for_stolen(dev, - stolen->start, stolen->size); - if (obj->pages == NULL) + obj->mm.pages = i915_pages_create_for_stolen(dev, + stolen->start, + stolen->size); + if (!obj->mm.pages) goto cleanup; - obj->get_page.sg_pos = obj->pages->sgl; - obj->get_page.sg_idx = 0; + obj->mm.get_page.sg_pos = obj->mm.pages->sgl; + obj->mm.get_page.sg_idx = 0; - i915_gem_object_pin_pages(obj); + __i915_gem_object_pin_pages(obj); obj->stolen = stolen; obj->base.read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; @@ -718,14 +720,14 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, goto err; } - vma->pages = obj->pages; + vma->pages = obj->mm.pages; vma->flags |= I915_VMA_GLOBAL_BIND; __i915_vma_set_map_and_fenceable(vma); list_move_tail(&vma->vm_link, &ggtt->base.inactive_list); obj->bind_count++; list_add_tail(&obj->global_list, &dev_priv->mm.bound_list); - i915_gem_object_pin_pages(obj); + __i915_gem_object_pin_pages(obj); return obj; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 71f80d2a487c..34d5ada49720 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -259,13 +259,13 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, if (!err) { struct i915_vma *vma; - if (obj->pages && - obj->madv == I915_MADV_WILLNEED && + if (obj->mm.pages && + obj->mm.madv == I915_MADV_WILLNEED && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { if (args->tiling_mode == I915_TILING_NONE) - i915_gem_object_unpin_pages(obj); + __i915_gem_object_unpin_pages(obj); if (!i915_gem_object_is_tiled(obj)) - i915_gem_object_pin_pages(obj); + __i915_gem_object_pin_pages(obj); } list_for_each_entry(vma, &obj->vma_list, obj_link) { diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index e2fa970bb629..0cbc8f70317e 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -73,10 +73,10 @@ static void cancel_userptr(struct work_struct *work) /* Cancel any active worker and force us to re-evaluate gup */ obj->userptr.work = NULL; - if (obj->pages != NULL) { + if (obj->mm.pages) { /* We are inside a kthread context and can't be interrupted */ WARN_ON(i915_gem_object_unbind(obj)); - WARN_ON(i915_gem_object_put_pages(obj)); + WARN_ON(__i915_gem_object_put_pages(obj)); } i915_gem_object_put(obj); @@ -432,15 +432,15 @@ __i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj, { int ret; - ret = st_set_pages(&obj->pages, pvec, num_pages); + ret = st_set_pages(&obj->mm.pages, pvec, num_pages); if (ret) return ret; ret = i915_gem_gtt_prepare_object(obj); if (ret) { - sg_free_table(obj->pages); - kfree(obj->pages); - obj->pages = NULL; + sg_free_table(obj->mm.pages); + kfree(obj->mm.pages); + obj->mm.pages = NULL; } return ret; @@ -530,8 +530,8 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) if (ret == 0) { list_add_tail(&obj->global_list, &to_i915(dev)->mm.unbound_list); - obj->get_page.sg_pos = obj->pages->sgl; - obj->get_page.sg_idx = 0; + obj->mm.get_page.sg_pos = obj->mm.pages->sgl; + obj->mm.get_page.sg_idx = 0; pinned = 0; } } @@ -672,22 +672,22 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj) BUG_ON(obj->userptr.work != NULL); __i915_gem_userptr_set_active(obj, false); - if (obj->madv != I915_MADV_WILLNEED) - obj->dirty = 0; + if (obj->mm.madv != I915_MADV_WILLNEED) + obj->mm.dirty = false; i915_gem_gtt_finish_object(obj); - for_each_sgt_page(page, sgt_iter, obj->pages) { - if (obj->dirty) + for_each_sgt_page(page, sgt_iter, obj->mm.pages) { + if (obj->mm.dirty) set_page_dirty(page); mark_page_accessed(page); put_page(page); } - obj->dirty = 0; + obj->mm.dirty = false; - sg_free_table(obj->pages); - kfree(obj->pages); + sg_free_table(obj->mm.pages); + kfree(obj->mm.pages); } static void diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index d5feace8de0d..5bbb37209aa5 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -896,8 +896,8 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->write_domain = obj->base.write_domain; err->fence_reg = vma->fence ? vma->fence->id : -1; err->tiling = i915_gem_object_get_tiling(obj); - err->dirty = obj->dirty; - err->purgeable = obj->madv != I915_MADV_WILLNEED; + err->dirty = obj->mm.dirty; + err->purgeable = obj->mm.madv != I915_MADV_WILLNEED; err->userptr = obj->userptr.mm != NULL; err->cache_level = obj->cache_level; } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 1c1bd30e8b2d..cb30549dfd40 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -744,7 +744,7 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx, ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = i915_ggtt_offset(ce->ring->vma); - ce->state->obj->dirty = true; + ce->state->obj->mm.dirty = true; /* Invalidate GuC TLB. */ if (i915.enable_guc_submission) { @@ -2042,7 +2042,7 @@ populate_lr_context(struct i915_gem_context *ctx, DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret); return ret; } - ctx_obj->dirty = true; + ctx_obj->mm.dirty = true; /* The second page of the context object contains some fields which must * be set up prior to the first execution. */ @@ -2180,7 +2180,7 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv) reg[CTX_RING_HEAD+1] = 0; reg[CTX_RING_TAIL+1] = 0; - ce->state->obj->dirty = true; + ce->state->obj->mm.dirty = true; i915_gem_object_unpin_map(ce->state->obj); ce->ring->head = ce->ring->tail = 0; -- cgit v1.2.3 From 03ac84f1830ec0b90f622500591eb3cc554ee479 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:36 +0100 Subject: drm/i915: Pass around sg_table to get_pages/put_pages backend The plan is to move obj->pages out from under the struct_mutex into its own per-object lock. We need to prune any assumption of the struct_mutex from the get_pages/put_pages backends, and to make it easier we pass around the sg_table to operate on rather than indirectly via the obj. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-13-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 36 +++++-- drivers/gpu/drm/i915/i915_gem.c | 172 +++++++++++++++---------------- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 20 ++-- drivers/gpu/drm/i915/i915_gem_fence.c | 17 +-- drivers/gpu/drm/i915/i915_gem_gtt.c | 19 ++-- drivers/gpu/drm/i915/i915_gem_gtt.h | 6 +- drivers/gpu/drm/i915/i915_gem_internal.c | 23 ++--- drivers/gpu/drm/i915/i915_gem_shrinker.c | 11 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 43 ++++---- drivers/gpu/drm/i915/i915_gem_userptr.c | 88 ++++++++-------- 10 files changed, 227 insertions(+), 208 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 50781cbe74d0..db67bec15ef2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2185,8 +2185,8 @@ struct drm_i915_gem_object_ops { * being released or under memory pressure (where we attempt to * reap pages for the shrinker). */ - int (*get_pages)(struct drm_i915_gem_object *); - void (*put_pages)(struct drm_i915_gem_object *); + struct sg_table *(*get_pages)(struct drm_i915_gem_object *); + void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *); int (*dmabuf_export)(struct drm_i915_gem_object *); void (*release)(struct drm_i915_gem_object *); @@ -2321,8 +2321,6 @@ struct drm_i915_gem_object { struct i915_gem_userptr { uintptr_t ptr; unsigned read_only :1; - unsigned workers :4; -#define I915_GEM_USERPTR_MAX_WORKERS 15 struct i915_mm_struct *mm; struct i915_mmu_object *mmu_object; @@ -2383,6 +2381,19 @@ i915_gem_object_put_unlocked(struct drm_i915_gem_object *obj) __deprecated extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *); +static inline bool +i915_gem_object_is_dead(const struct drm_i915_gem_object *obj) +{ + return atomic_read(&obj->base.refcount.refcount) == 0; +} + +#if IS_ENABLED(CONFIG_LOCKDEP) +#define lockdep_assert_held_unless(lock, cond) \ + GEM_BUG_ON(debug_locks && !lockdep_is_held(lock) && !(cond)) +#else +#define lockdep_assert_held_unless(lock, cond) +#endif + static inline bool i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj) { @@ -3211,6 +3222,8 @@ dma_addr_t i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, unsigned long n); +void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages); int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj); static inline int __must_check @@ -3227,7 +3240,8 @@ i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) static inline void __i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { - lockdep_assert_held(&obj->base.dev->struct_mutex); + lockdep_assert_held_unless(&obj->base.dev->struct_mutex, + i915_gem_object_is_dead(obj)); GEM_BUG_ON(!obj->mm.pages); obj->mm.pages_pin_count++; @@ -3242,7 +3256,8 @@ i915_gem_object_has_pinned_pages(struct drm_i915_gem_object *obj) static inline void __i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) { - lockdep_assert_held(&obj->base.dev->struct_mutex); + lockdep_assert_held_unless(&obj->base.dev->struct_mutex, + i915_gem_object_is_dead(obj)); GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); GEM_BUG_ON(!obj->mm.pages); @@ -3255,7 +3270,8 @@ static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) __i915_gem_object_unpin_pages(obj); } -int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj); +void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj); +void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj); enum i915_map_type { I915_MAP_WB = 0, @@ -3480,8 +3496,10 @@ i915_vma_unpin_fence(struct i915_vma *vma) void i915_gem_restore_fences(struct drm_device *dev); void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); -void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj); -void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj); +void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj, + struct sg_table *pages); +void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj, + struct sg_table *pages); /* i915_gem_context.c */ int __must_check i915_gem_context_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0d702c8f7b7b..56060aeb12e3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -169,7 +169,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, return 0; } -static int +static struct sg_table * i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) { struct address_space *mapping = obj->base.filp->f_mapping; @@ -179,7 +179,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) int i; if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj))) - return -EINVAL; + return ERR_PTR(-EINVAL); for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { struct page *page; @@ -187,7 +187,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) page = shmem_read_mapping_page(mapping, i); if (IS_ERR(page)) - return PTR_ERR(page); + return ERR_CAST(page); src = kmap_atomic(page); memcpy(vaddr, src, PAGE_SIZE); @@ -202,11 +202,11 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) st = kmalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) - return -ENOMEM; + return ERR_PTR(-ENOMEM); if (sg_alloc_table(st, 1, GFP_KERNEL)) { kfree(st); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } sg = st->sgl; @@ -216,28 +216,30 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) sg_dma_address(sg) = obj->phys_handle->busaddr; sg_dma_len(sg) = obj->base.size; - obj->mm.pages = st; - return 0; + return st; } static void -i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj) +__i915_gem_object_release_shmem(struct drm_i915_gem_object *obj) { - int ret; - GEM_BUG_ON(obj->mm.madv == __I915_MADV_PURGED); - ret = i915_gem_object_set_to_cpu_domain(obj, true); - if (WARN_ON(ret)) { - /* In the event of a disaster, abandon all caches and - * hope for the best. - */ - obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU; - } - if (obj->mm.madv == I915_MADV_DONTNEED) obj->mm.dirty = false; + if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) + i915_gem_clflush_object(obj, false); + + obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->base.write_domain = I915_GEM_DOMAIN_CPU; +} + +static void +i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj, + struct sg_table *pages) +{ + __i915_gem_object_release_shmem(obj); + if (obj->mm.dirty) { struct address_space *mapping = obj->base.filp->f_mapping; char *vaddr = obj->phys_handle->vaddr; @@ -265,8 +267,8 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj) obj->mm.dirty = false; } - sg_free_table(obj->mm.pages); - kfree(obj->mm.pages); + sg_free_table(pages); + kfree(pages); } static void @@ -518,9 +520,9 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, if (ret) return ret; - ret = __i915_gem_object_put_pages(obj); - if (ret) - return ret; + __i915_gem_object_put_pages(obj); + if (obj->mm.pages) + return -EBUSY; /* create a new object */ phys = drm_pci_alloc(obj->base.dev, obj->base.size, align); @@ -536,7 +538,7 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, static int i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_device *dev = obj->base.dev; void *vaddr = obj->phys_handle->vaddr + args->offset; @@ -552,7 +554,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, I915_WAIT_LOCKED | I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT, - to_rps_client(file_priv)); + to_rps_client(file)); if (ret) return ret; @@ -2263,8 +2265,7 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj) } /* Try to discard unwanted pages */ -static void -i915_gem_object_invalidate(struct drm_i915_gem_object *obj) +void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj) { struct address_space *mapping; @@ -2283,32 +2284,20 @@ i915_gem_object_invalidate(struct drm_i915_gem_object *obj) } static void -i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) +i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj, + struct sg_table *pages) { struct sgt_iter sgt_iter; struct page *page; - int ret; - GEM_BUG_ON(obj->mm.madv == __I915_MADV_PURGED); - - ret = i915_gem_object_set_to_cpu_domain(obj, true); - if (WARN_ON(ret)) { - /* In the event of a disaster, abandon all caches and - * hope for the best. - */ - i915_gem_clflush_object(obj, true); - obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU; - } + __i915_gem_object_release_shmem(obj); - i915_gem_gtt_finish_object(obj); + i915_gem_gtt_finish_pages(obj, pages); if (i915_gem_object_needs_bit17_swizzle(obj)) - i915_gem_object_save_bit_17_swizzle(obj); - - if (obj->mm.madv == I915_MADV_DONTNEED) - obj->mm.dirty = false; + i915_gem_object_save_bit_17_swizzle(obj, pages); - for_each_sgt_page(page, sgt_iter, obj->mm.pages) { + for_each_sgt_page(page, sgt_iter, pages) { if (obj->mm.dirty) set_page_dirty(page); @@ -2319,8 +2308,8 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) } obj->mm.dirty = false; - sg_free_table(obj->mm.pages); - kfree(obj->mm.pages); + sg_free_table(pages); + kfree(pages); } static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj) @@ -2332,24 +2321,22 @@ static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj) radix_tree_delete(&obj->mm.get_page.radix, iter.index); } -int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) +void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) { - const struct drm_i915_gem_object_ops *ops = obj->ops; + struct sg_table *pages; lockdep_assert_held(&obj->base.dev->struct_mutex); - if (!obj->mm.pages) - return 0; - if (i915_gem_object_has_pinned_pages(obj)) - return -EBUSY; + return; GEM_BUG_ON(obj->bind_count); /* ->put_pages might need to allocate memory for the bit17 swizzle * array, hence protect them from being reaped by removing them from gtt * lists early. */ - list_del(&obj->global_list); + pages = fetch_and_zero(&obj->mm.pages); + GEM_BUG_ON(!pages); if (obj->mm.mapping) { void *ptr; @@ -2365,12 +2352,7 @@ int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) __i915_gem_object_reset_page_iter(obj); - ops->put_pages(obj); - obj->mm.pages = NULL; - - i915_gem_object_invalidate(obj); - - return 0; + obj->ops->put_pages(obj, pages); } static unsigned int swiotlb_max_size(void) @@ -2382,7 +2364,7 @@ static unsigned int swiotlb_max_size(void) #endif } -static int +static struct sg_table * i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = to_i915(obj->base.dev); @@ -2401,8 +2383,8 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) * wasn't in the GTT, there shouldn't be any way it could have been in * a GPU cache */ - BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); - BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); + GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); + GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); max_segment = swiotlb_max_size(); if (!max_segment) @@ -2410,12 +2392,12 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) st = kmalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) - return -ENOMEM; + return ERR_PTR(-ENOMEM); page_count = obj->base.size / PAGE_SIZE; if (sg_alloc_table(st, page_count, GFP_KERNEL)) { kfree(st); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } /* Get the list of pages out of our struct file. They'll be pinned @@ -2466,20 +2448,19 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) } if (sg) /* loop terminated early; short sg table */ sg_mark_end(sg); - obj->mm.pages = st; - ret = i915_gem_gtt_prepare_object(obj); + ret = i915_gem_gtt_prepare_pages(obj, st); if (ret) goto err_pages; if (i915_gem_object_needs_bit17_swizzle(obj)) - i915_gem_object_do_bit_17_swizzle(obj); + i915_gem_object_do_bit_17_swizzle(obj, st); if (i915_gem_object_is_tiled(obj) && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) __i915_gem_object_pin_pages(obj); - return 0; + return st; err_pages: sg_mark_end(sg); @@ -2499,7 +2480,35 @@ err_pages: if (ret == -ENOSPC) ret = -ENOMEM; - return ret; + return ERR_PTR(ret); +} + +void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) +{ + lockdep_assert_held(&obj->base.dev->struct_mutex); + + obj->mm.get_page.sg_pos = pages->sgl; + obj->mm.get_page.sg_idx = 0; + + obj->mm.pages = pages; +} + +static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj) +{ + struct sg_table *pages; + + if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) { + DRM_DEBUG("Attempting to obtain a purgeable object\n"); + return -EFAULT; + } + + pages = obj->ops->get_pages(obj); + if (unlikely(IS_ERR(pages))) + return PTR_ERR(pages); + + __i915_gem_object_set_pages(obj, pages); + return 0; } /* Ensure that the associated pages are gathered from the backing storage @@ -2511,33 +2520,18 @@ err_pages: */ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj) { - struct drm_i915_private *dev_priv = to_i915(obj->base.dev); - const struct drm_i915_gem_object_ops *ops = obj->ops; - int ret; + int err; lockdep_assert_held(&obj->base.dev->struct_mutex); if (obj->mm.pages) return 0; - if (obj->mm.madv != I915_MADV_WILLNEED) { - DRM_DEBUG("Attempting to obtain a purgeable object\n"); - __i915_gem_object_unpin_pages(obj); - return -EFAULT; - } - - ret = ops->get_pages(obj); - if (ret) { + err = ____i915_gem_object_get_pages(obj); + if (err) __i915_gem_object_unpin_pages(obj); - return ret; - } - list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list); - - obj->mm.get_page.sg_pos = obj->mm.pages->sgl; - obj->mm.get_page.sg_idx = 0; - - return 0; + return err; } /* The 'mapping' part of i915_gem_object_pin_map() below */ diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 10441dc72e73..2abd524aba14 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -289,22 +289,18 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, return dma_buf; } -static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) +static struct sg_table * +i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) { - struct sg_table *sg; - - sg = dma_buf_map_attachment(obj->base.import_attach, DMA_BIDIRECTIONAL); - if (IS_ERR(sg)) - return PTR_ERR(sg); - - obj->mm.pages = sg; - return 0; + return dma_buf_map_attachment(obj->base.import_attach, + DMA_BIDIRECTIONAL); } -static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj) +static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj, + struct sg_table *pages) { - dma_buf_unmap_attachment(obj->base.import_attach, - obj->mm.pages, DMA_BIDIRECTIONAL); + dma_buf_unmap_attachment(obj->base.import_attach, pages, + DMA_BIDIRECTIONAL); } static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = { diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index 5aadab59f071..cd59dbc6588c 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -644,6 +644,7 @@ i915_gem_swizzle_page(struct page *page) /** * i915_gem_object_do_bit_17_swizzle - fixup bit 17 swizzling * @obj: i915 GEM buffer object + * @pages: the scattergather list of physical pages * * This function fixes up the swizzling in case any page frame number for this * object has changed in bit 17 since that state has been saved with @@ -654,7 +655,8 @@ i915_gem_swizzle_page(struct page *page) * by swapping them out and back in again). */ void -i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) +i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj, + struct sg_table *pages) { struct sgt_iter sgt_iter; struct page *page; @@ -664,10 +666,9 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) return; i = 0; - for_each_sgt_page(page, sgt_iter, obj->mm.pages) { + for_each_sgt_page(page, sgt_iter, pages) { char new_bit_17 = page_to_phys(page) >> 17; - if ((new_bit_17 & 0x1) != - (test_bit(i, obj->bit_17) != 0)) { + if ((new_bit_17 & 0x1) != (test_bit(i, obj->bit_17) != 0)) { i915_gem_swizzle_page(page); set_page_dirty(page); } @@ -678,17 +679,19 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) /** * i915_gem_object_save_bit_17_swizzle - save bit 17 swizzling * @obj: i915 GEM buffer object + * @pages: the scattergather list of physical pages * * This function saves the bit 17 of each page frame number so that swizzling * can be fixed up later on with i915_gem_object_do_bit_17_swizzle(). This must * be called before the backing storage can be unpinned. */ void -i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) +i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj, + struct sg_table *pages) { + const unsigned int page_count = obj->base.size >> PAGE_SHIFT; struct sgt_iter sgt_iter; struct page *page; - int page_count = obj->base.size >> PAGE_SHIFT; int i; if (obj->bit_17 == NULL) { @@ -703,7 +706,7 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) i = 0; - for_each_sgt_page(page, sgt_iter, obj->mm.pages) { + for_each_sgt_page(page, sgt_iter, pages) { if (page_to_phys(page) & (1 << 17)) __set_bit(i, obj->bit_17); else diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 794ccc4cffaa..1008209ca797 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2370,14 +2370,15 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) i915_ggtt_flush(dev_priv); } -int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) +int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) { - if (!dma_map_sg(&obj->base.dev->pdev->dev, - obj->mm.pages->sgl, obj->mm.pages->nents, - PCI_DMA_BIDIRECTIONAL)) - return -ENOSPC; + if (dma_map_sg(&obj->base.dev->pdev->dev, + pages->sgl, pages->nents, + PCI_DMA_BIDIRECTIONAL)) + return 0; - return 0; + return -ENOSPC; } static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) @@ -2696,7 +2697,8 @@ static void ggtt_unbind_vma(struct i915_vma *vma) vma->node.start, size); } -void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) +void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) { struct drm_i915_private *dev_priv = to_i915(obj->base.dev); struct device *kdev = &dev_priv->drm.pdev->dev; @@ -2710,8 +2712,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) } } - dma_unmap_sg(kdev, obj->mm.pages->sgl, obj->mm.pages->nents, - PCI_DMA_BIDIRECTIONAL); + dma_unmap_sg(kdev, pages->sgl, pages->nents, PCI_DMA_BIDIRECTIONAL); } static void i915_gtt_color_adjust(struct drm_mm_node *node, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index c241d8143255..dbe6a6cec20d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -628,8 +628,10 @@ void i915_check_and_clear_faults(struct drm_i915_private *dev_priv); void i915_gem_suspend_gtt_mappings(struct drm_device *dev); void i915_gem_restore_gtt_mappings(struct drm_device *dev); -int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj); -void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj); +int __must_check i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages); +void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages); /* Flags used by pin/bind&friends. */ #define PIN_NONBLOCK BIT(0) diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index 08a2576ff7d2..1b0607a44a9a 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -42,7 +42,8 @@ static void internal_free_pages(struct sg_table *st) kfree(st); } -static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) +static struct sg_table * +i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = to_i915(obj->base.dev); unsigned int npages = obj->base.size / PAGE_SIZE; @@ -53,11 +54,11 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) st = kmalloc(sizeof(*st), GFP_KERNEL); if (!st) - return -ENOMEM; + return ERR_PTR(-ENOMEM); if (sg_alloc_table(st, npages, GFP_KERNEL)) { kfree(st); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } sg = st->sgl; @@ -102,12 +103,9 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) sg = __sg_next(sg); } while (1); - obj->mm.pages = st; - if (i915_gem_gtt_prepare_object(obj)) { - obj->mm.pages = NULL; + if (i915_gem_gtt_prepare_pages(obj, st)) goto err; - } /* Mark the pages as dontneed whilst they are still pinned. As soon * as they are unpinned they are allowed to be reaped by the shrinker, @@ -115,18 +113,19 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) * object are only valid whilst active and pinned. */ obj->mm.madv = I915_MADV_DONTNEED; - return 0; + return st; err: sg_mark_end(sg); internal_free_pages(st); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } -static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj) +static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj, + struct sg_table *pages) { - i915_gem_gtt_finish_object(obj); - internal_free_pages(obj->mm.pages); + i915_gem_gtt_finish_pages(obj, pages); + internal_free_pages(pages); obj->mm.dirty = false; obj->mm.madv = I915_MADV_WILLNEED; diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 124f69a80162..f95061faeae6 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -91,6 +91,13 @@ static bool can_release_pages(struct drm_i915_gem_object *obj) return swap_available() || obj->mm.madv == I915_MADV_DONTNEED; } +static bool unsafe_drop_pages(struct drm_i915_gem_object *obj) +{ + if (i915_gem_object_unbind(obj) == 0) + __i915_gem_object_put_pages(obj); + return !obj->mm.pages; +} + /** * i915_gem_shrink - Shrink buffer object caches * @dev_priv: i915 device @@ -192,9 +199,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, i915_gem_object_get(obj); - /* For the unbound phase, this should be a no-op! */ - i915_gem_object_unbind(obj); - if (__i915_gem_object_put_pages(obj) == 0) + if (unsafe_drop_pages(obj)) count += obj->base.size >> PAGE_SHIFT; i915_gem_object_put(obj); diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 0acbdcbd8f3a..1a63ffa4d189 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -546,17 +546,20 @@ i915_pages_create_for_stolen(struct drm_device *dev, return st; } -static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj) +static struct sg_table * +i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj) { - BUG(); - return -EINVAL; + return i915_pages_create_for_stolen(obj->base.dev, + obj->stolen->start, + obj->stolen->size); } -static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj) +static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj, + struct sg_table *pages) { /* Should only be called during free */ - sg_free_table(obj->mm.pages); - kfree(obj->mm.pages); + sg_free_table(pages); + kfree(pages); } static void @@ -591,21 +594,13 @@ _i915_gem_object_create_stolen(struct drm_device *dev, drm_gem_private_object_init(dev, &obj->base, stolen->size); i915_gem_object_init(obj, &i915_gem_object_stolen_ops); - obj->mm.pages = i915_pages_create_for_stolen(dev, - stolen->start, - stolen->size); - if (!obj->mm.pages) - goto cleanup; - - obj->mm.get_page.sg_pos = obj->mm.pages->sgl; - obj->mm.get_page.sg_idx = 0; - - __i915_gem_object_pin_pages(obj); obj->stolen = stolen; - obj->base.read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; obj->cache_level = HAS_LLC(dev) ? I915_CACHE_LLC : I915_CACHE_NONE; + if (i915_gem_object_pin_pages(obj)) + goto cleanup; + return obj; cleanup: @@ -700,10 +695,14 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, if (gtt_offset == I915_GTT_OFFSET_NONE) return obj; + ret = i915_gem_object_pin_pages(obj); + if (ret) + goto err; + vma = i915_gem_obj_lookup_or_create_vma(obj, &ggtt->base, NULL); if (IS_ERR(vma)) { ret = PTR_ERR(vma); - goto err; + goto err_pages; } /* To simplify the initialisation sequence between KMS and GTT, @@ -717,20 +716,20 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node); if (ret) { DRM_DEBUG_KMS("failed to allocate stolen GTT space\n"); - goto err; + goto err_pages; } vma->pages = obj->mm.pages; vma->flags |= I915_VMA_GLOBAL_BIND; __i915_vma_set_map_and_fenceable(vma); list_move_tail(&vma->vm_link, &ggtt->base.inactive_list); + list_move_tail(&obj->global_list, &dev_priv->mm.bound_list); obj->bind_count++; - list_add_tail(&obj->global_list, &dev_priv->mm.bound_list); - __i915_gem_object_pin_pages(obj); - return obj; +err_pages: + i915_gem_object_unpin_pages(obj); err: i915_gem_object_put(obj); return NULL; diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 0cbc8f70317e..a421447f1d84 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -73,11 +73,14 @@ static void cancel_userptr(struct work_struct *work) /* Cancel any active worker and force us to re-evaluate gup */ obj->userptr.work = NULL; - if (obj->mm.pages) { - /* We are inside a kthread context and can't be interrupted */ - WARN_ON(i915_gem_object_unbind(obj)); - WARN_ON(__i915_gem_object_put_pages(obj)); - } + /* We are inside a kthread context and can't be interrupted */ + if (i915_gem_object_unbind(obj) == 0) + __i915_gem_object_put_pages(obj); + WARN_ONCE(obj->mm.pages, + "Failed to release pages: bind_count=%d, pages_pin_count=%d, pin_display=%d\n", + obj->bind_count, + obj->mm.pages_pin_count, + obj->pin_display); i915_gem_object_put(obj); mutex_unlock(&dev->struct_mutex); @@ -426,24 +429,25 @@ err: return ret; } -static int +static struct sg_table * __i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj, struct page **pvec, int num_pages) { + struct sg_table *pages; int ret; - ret = st_set_pages(&obj->mm.pages, pvec, num_pages); + ret = st_set_pages(&pages, pvec, num_pages); if (ret) - return ret; + return ERR_PTR(ret); - ret = i915_gem_gtt_prepare_object(obj); + ret = i915_gem_gtt_prepare_pages(obj, pages); if (ret) { - sg_free_table(obj->mm.pages); - kfree(obj->mm.pages); - obj->mm.pages = NULL; + sg_free_table(pages); + kfree(pages); + return ERR_PTR(ret); } - return ret; + return pages; } static int @@ -525,20 +529,20 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) mutex_lock(&dev->struct_mutex); if (obj->userptr.work == &work->work) { + struct sg_table *pages = ERR_PTR(ret); + if (pinned == npages) { - ret = __i915_gem_userptr_set_pages(obj, pvec, npages); - if (ret == 0) { - list_add_tail(&obj->global_list, - &to_i915(dev)->mm.unbound_list); - obj->mm.get_page.sg_pos = obj->mm.pages->sgl; - obj->mm.get_page.sg_idx = 0; + pages = __i915_gem_userptr_set_pages(obj, pvec, npages); + if (!IS_ERR(pages)) { + __i915_gem_object_set_pages(obj, pages); pinned = 0; + pages = NULL; } } - obj->userptr.work = ERR_PTR(ret); + + obj->userptr.work = ERR_CAST(pages); } - obj->userptr.workers--; i915_gem_object_put(obj); mutex_unlock(&dev->struct_mutex); @@ -549,7 +553,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) kfree(work); } -static int +static struct sg_table * __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj, bool *active) { @@ -574,15 +578,11 @@ __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj, * that error back to this function through * obj->userptr.work = ERR_PTR. */ - if (obj->userptr.workers >= I915_GEM_USERPTR_MAX_WORKERS) - return -EAGAIN; - work = kmalloc(sizeof(*work), GFP_KERNEL); if (work == NULL) - return -ENOMEM; + return ERR_PTR(-ENOMEM); obj->userptr.work = &work->work; - obj->userptr.workers++; work->obj = i915_gem_object_get(obj); @@ -593,14 +593,15 @@ __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj, schedule_work(&work->work); *active = true; - return -EAGAIN; + return ERR_PTR(-EAGAIN); } -static int +static struct sg_table * i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) { const int num_pages = obj->base.size >> PAGE_SHIFT; struct page **pvec; + struct sg_table *pages; int pinned, ret; bool active; @@ -624,15 +625,15 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) if (obj->userptr.work) { /* active flag should still be held for the pending work */ if (IS_ERR(obj->userptr.work)) - return PTR_ERR(obj->userptr.work); + return ERR_CAST(obj->userptr.work); else - return -EAGAIN; + return ERR_PTR(-EAGAIN); } /* Let the mmu-notifier know that we have begun and need cancellation */ ret = __i915_gem_userptr_set_active(obj, true); if (ret) - return ret; + return ERR_PTR(ret); pvec = NULL; pinned = 0; @@ -641,7 +642,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) GFP_TEMPORARY); if (pvec == NULL) { __i915_gem_userptr_set_active(obj, false); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages, @@ -650,21 +651,22 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) active = false; if (pinned < 0) - ret = pinned, pinned = 0; + pages = ERR_PTR(pinned), pinned = 0; else if (pinned < num_pages) - ret = __i915_gem_userptr_get_pages_schedule(obj, &active); + pages = __i915_gem_userptr_get_pages_schedule(obj, &active); else - ret = __i915_gem_userptr_set_pages(obj, pvec, num_pages); - if (ret) { + pages = __i915_gem_userptr_set_pages(obj, pvec, num_pages); + if (IS_ERR(pages)) { __i915_gem_userptr_set_active(obj, active); release_pages(pvec, pinned, 0); } drm_free_large(pvec); - return ret; + return pages; } static void -i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj) +i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) { struct sgt_iter sgt_iter; struct page *page; @@ -675,9 +677,9 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj) if (obj->mm.madv != I915_MADV_WILLNEED) obj->mm.dirty = false; - i915_gem_gtt_finish_object(obj); + i915_gem_gtt_finish_pages(obj, pages); - for_each_sgt_page(page, sgt_iter, obj->mm.pages) { + for_each_sgt_page(page, sgt_iter, pages) { if (obj->mm.dirty) set_page_dirty(page); @@ -686,8 +688,8 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj) } obj->mm.dirty = false; - sg_free_table(obj->mm.pages); - kfree(obj->mm.pages); + sg_free_table(pages); + kfree(pages); } static void -- cgit v1.2.3 From 1233e2db199dea015391db03d3478b3392201c41 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:37 +0100 Subject: drm/i915: Move object backing storage manipulation to its own locking Break the allocation of the backing storage away from struct_mutex into a per-object lock. This allows parallel page allocation, provided we can do so outside of struct_mutex (i.e. set-domain-ioctl, pwrite, GTT fault), i.e. before execbuf! The increased cost of the atomic counters are hidden behind i915_vma_pin() for the typical case of execbuf, i.e. as the object is typically bound between execbufs, the page_pin_count is static. The cost will be felt around set-domain and pwrite, but offset by the improvement from reduced struct_mutex contention. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-14-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 36 +++++-------- drivers/gpu/drm/i915/i915_gem.c | 93 +++++++++++++++++++++----------- drivers/gpu/drm/i915/i915_gem_shrinker.c | 51 ++++++++++++------ drivers/gpu/drm/i915/i915_gem_tiling.c | 2 + drivers/gpu/drm/i915/i915_gem_userptr.c | 10 ++-- 5 files changed, 114 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index db67bec15ef2..f69e0e03e259 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2274,7 +2274,8 @@ struct drm_i915_gem_object { unsigned int pin_display; struct { - unsigned int pages_pin_count; + struct mutex lock; /* protects the pages and their use */ + atomic_t pages_pin_count; struct sg_table *pages; void *mapping; @@ -2387,13 +2388,6 @@ i915_gem_object_is_dead(const struct drm_i915_gem_object *obj) return atomic_read(&obj->base.refcount.refcount) == 0; } -#if IS_ENABLED(CONFIG_LOCKDEP) -#define lockdep_assert_held_unless(lock, cond) \ - GEM_BUG_ON(debug_locks && !lockdep_is_held(lock) && !(cond)) -#else -#define lockdep_assert_held_unless(lock, cond) -#endif - static inline bool i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj) { @@ -3229,9 +3223,9 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj); static inline int __must_check i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { - lockdep_assert_held(&obj->base.dev->struct_mutex); + might_lock(&obj->mm.lock); - if (obj->mm.pages_pin_count++) + if (atomic_inc_not_zero(&obj->mm.pages_pin_count)) return 0; return __i915_gem_object_get_pages(obj); @@ -3240,32 +3234,29 @@ i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) static inline void __i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { - lockdep_assert_held_unless(&obj->base.dev->struct_mutex, - i915_gem_object_is_dead(obj)); GEM_BUG_ON(!obj->mm.pages); - obj->mm.pages_pin_count++; + atomic_inc(&obj->mm.pages_pin_count); } static inline bool i915_gem_object_has_pinned_pages(struct drm_i915_gem_object *obj) { - return obj->mm.pages_pin_count; + return atomic_read(&obj->mm.pages_pin_count); } static inline void __i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) { - lockdep_assert_held_unless(&obj->base.dev->struct_mutex, - i915_gem_object_is_dead(obj)); GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); GEM_BUG_ON(!obj->mm.pages); - obj->mm.pages_pin_count--; - GEM_BUG_ON(obj->mm.pages_pin_count < obj->bind_count); + atomic_dec(&obj->mm.pages_pin_count); + GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count); } -static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) +static inline void +i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) { __i915_gem_object_unpin_pages(obj); } @@ -3288,8 +3279,8 @@ enum i915_map_type { * the kernel address space. Based on the @type of mapping, the PTE will be * set to either WriteBack or WriteCombine (via pgprot_t). * - * The caller must hold the struct_mutex, and is responsible for calling - * i915_gem_object_unpin_map() when the mapping is no longer required. + * The caller is responsible for calling i915_gem_object_unpin_map() when the + * mapping is no longer required. * * Returns the pointer through which to access the mapped object, or an * ERR_PTR() on error. @@ -3305,12 +3296,9 @@ void *__must_check i915_gem_object_pin_map(struct drm_i915_gem_object *obj, * with your access, call i915_gem_object_unpin_map() to release the pin * upon the mapping. Once the pin count reaches zero, that mapping may be * removed. - * - * The caller must hold the struct_mutex. */ static inline void i915_gem_object_unpin_map(struct drm_i915_gem_object *obj) { - lockdep_assert_held(&obj->base.dev->struct_mutex); i915_gem_object_unpin_pages(obj); } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 56060aeb12e3..c8e9548adfeb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2269,6 +2269,9 @@ void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj) { struct address_space *mapping; + lockdep_assert_held(&obj->mm.lock); + GEM_BUG_ON(obj->mm.pages); + switch (obj->mm.madv) { case I915_MADV_DONTNEED: i915_gem_object_truncate(obj); @@ -2325,12 +2328,17 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) { struct sg_table *pages; - lockdep_assert_held(&obj->base.dev->struct_mutex); - if (i915_gem_object_has_pinned_pages(obj)) return; GEM_BUG_ON(obj->bind_count); + if (!READ_ONCE(obj->mm.pages)) + return; + + /* May be called by shrinker from within get_pages() (on another bo) */ + mutex_lock_nested(&obj->mm.lock, SINGLE_DEPTH_NESTING); + if (unlikely(atomic_read(&obj->mm.pages_pin_count))) + goto unlock; /* ->put_pages might need to allocate memory for the bit17 swizzle * array, hence protect them from being reaped by removing them from gtt @@ -2353,6 +2361,8 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) __i915_gem_object_reset_page_iter(obj); obj->ops->put_pages(obj, pages); +unlock: + mutex_unlock(&obj->mm.lock); } static unsigned int swiotlb_max_size(void) @@ -2486,7 +2496,7 @@ err_pages: void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, struct sg_table *pages) { - lockdep_assert_held(&obj->base.dev->struct_mutex); + lockdep_assert_held(&obj->mm.lock); obj->mm.get_page.sg_pos = pages->sgl; obj->mm.get_page.sg_idx = 0; @@ -2512,9 +2522,9 @@ static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj) } /* Ensure that the associated pages are gathered from the backing storage - * and pinned into our object. i915_gem_object_get_pages() may be called + * and pinned into our object. i915_gem_object_pin_pages() may be called * multiple times before they are released by a single call to - * i915_gem_object_put_pages() - once the pages are no longer referenced + * i915_gem_object_unpin_pages() - once the pages are no longer referenced * either as a result of memory pressure (reaping pages under the shrinker) * or as the object is itself released. */ @@ -2522,15 +2532,23 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj) { int err; - lockdep_assert_held(&obj->base.dev->struct_mutex); + err = mutex_lock_interruptible(&obj->mm.lock); + if (err) + return err; - if (obj->mm.pages) - return 0; + if (likely(obj->mm.pages)) { + __i915_gem_object_pin_pages(obj); + goto unlock; + } + + GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj)); err = ____i915_gem_object_get_pages(obj); - if (err) - __i915_gem_object_unpin_pages(obj); + if (!err) + atomic_set_release(&obj->mm.pages_pin_count, 1); +unlock: + mutex_unlock(&obj->mm.lock); return err; } @@ -2590,20 +2608,29 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, void *ptr; int ret; - lockdep_assert_held(&obj->base.dev->struct_mutex); GEM_BUG_ON(!i915_gem_object_has_struct_page(obj)); - ret = i915_gem_object_pin_pages(obj); + ret = mutex_lock_interruptible(&obj->mm.lock); if (ret) return ERR_PTR(ret); - pinned = obj->mm.pages_pin_count > 1; + pinned = true; + if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) { + ret = ____i915_gem_object_get_pages(obj); + if (ret) + goto err_unlock; + + GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count)); + atomic_set_release(&obj->mm.pages_pin_count, 1); + pinned = false; + } + GEM_BUG_ON(!obj->mm.pages); ptr = ptr_unpack_bits(obj->mm.mapping, has_type); if (ptr && has_type != type) { if (pinned) { ret = -EBUSY; - goto err; + goto err_unpin; } if (is_vmalloc_addr(ptr)) @@ -2618,17 +2645,21 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, ptr = i915_gem_object_map(obj, type); if (!ptr) { ret = -ENOMEM; - goto err; + goto err_unpin; } obj->mm.mapping = ptr_pack_bits(ptr, type); } +out_unlock: + mutex_unlock(&obj->mm.lock); return ptr; -err: - i915_gem_object_unpin_pages(obj); - return ERR_PTR(ret); +err_unpin: + atomic_dec(&obj->mm.pages_pin_count); +err_unlock: + ptr = ERR_PTR(ret); + goto out_unlock; } static void @@ -4268,7 +4299,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_madvise *args = data; struct drm_i915_gem_object *obj; - int ret; + int err; switch (args->madv) { case I915_MADV_DONTNEED: @@ -4278,15 +4309,13 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, return -EINVAL; } - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; - obj = i915_gem_object_lookup(file_priv, args->handle); - if (!obj) { - ret = -ENOENT; - goto unlock; - } + if (!obj) + return -ENOENT; + + err = mutex_lock_interruptible(&obj->mm.lock); + if (err) + goto out; if (obj->mm.pages && i915_gem_object_is_tiled(obj) && @@ -4305,11 +4334,11 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, i915_gem_object_truncate(obj); args->retained = obj->mm.madv != __I915_MADV_PURGED; + mutex_unlock(&obj->mm.lock); +out: i915_gem_object_put(obj); -unlock: - mutex_unlock(&dev->struct_mutex); - return ret; + return err; } void i915_gem_object_init(struct drm_i915_gem_object *obj, @@ -4317,6 +4346,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, { int i; + mutex_init(&obj->mm.lock); + INIT_LIST_HEAD(&obj->global_list); INIT_LIST_HEAD(&obj->userfault_link); for (i = 0; i < I915_NUM_ENGINES; i++) @@ -4479,7 +4510,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) obj->ops->release(obj); if (WARN_ON(i915_gem_object_has_pinned_pages(obj))) - obj->mm.pages_pin_count = 0; + atomic_set(&obj->mm.pages_pin_count, 0); if (discard_backing_storage(obj)) obj->mm.madv = I915_MADV_DONTNEED; __i915_gem_object_put_pages(obj); diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index f95061faeae6..c8a4c40ec2c2 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -48,6 +48,20 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) #endif } +static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock) +{ + if (!mutex_trylock(&dev->struct_mutex)) { + if (!mutex_is_locked_by(&dev->struct_mutex, current)) + return false; + + *unlock = false; + } else { + *unlock = true; + } + + return true; +} + static bool any_vma_pinned(struct drm_i915_gem_object *obj) { struct i915_vma *vma; @@ -66,6 +80,9 @@ static bool swap_available(void) static bool can_release_pages(struct drm_i915_gem_object *obj) { + if (!obj->mm.pages) + return false; + /* Only shmemfs objects are backed by swap */ if (!obj->base.filp) return false; @@ -78,7 +95,7 @@ static bool can_release_pages(struct drm_i915_gem_object *obj) * to the GPU, simply unbinding from the GPU is not going to succeed * in releasing our pin count on the pages themselves. */ - if (obj->mm.pages_pin_count > obj->bind_count) + if (atomic_read(&obj->mm.pages_pin_count) > obj->bind_count) return false; if (any_vma_pinned(obj)) @@ -95,7 +112,7 @@ static bool unsafe_drop_pages(struct drm_i915_gem_object *obj) { if (i915_gem_object_unbind(obj) == 0) __i915_gem_object_put_pages(obj); - return !obj->mm.pages; + return !READ_ONCE(obj->mm.pages); } /** @@ -135,6 +152,10 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, { NULL, 0 }, }, *phase; unsigned long count = 0; + bool unlock; + + if (!i915_gem_shrinker_lock(&dev_priv->drm, &unlock)) + return 0; trace_i915_gem_shrink(dev_priv, target, flags); i915_gem_retire_requests(dev_priv); @@ -199,8 +220,14 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, i915_gem_object_get(obj); - if (unsafe_drop_pages(obj)) - count += obj->base.size >> PAGE_SHIFT; + if (unsafe_drop_pages(obj)) { + mutex_lock(&obj->mm.lock); + if (!obj->mm.pages) { + __i915_gem_object_invalidate(obj); + count += obj->base.size >> PAGE_SHIFT; + } + mutex_unlock(&obj->mm.lock); + } i915_gem_object_put(obj); } @@ -211,6 +238,9 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, intel_runtime_pm_put(dev_priv); i915_gem_retire_requests(dev_priv); + if (unlock) + mutex_unlock(&dev_priv->drm.struct_mutex); + /* expedite the RCU grace period to free some request slabs */ synchronize_rcu_expedited(); @@ -244,19 +274,6 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv) return freed; } -static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock) -{ - if (!mutex_trylock(&dev->struct_mutex)) { - if (!mutex_is_locked_by(&dev->struct_mutex, current)) - return false; - - *unlock = false; - } else - *unlock = true; - - return true; -} - static unsigned long i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) { diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 34d5ada49720..6608799ee1f9 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -259,6 +259,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, if (!err) { struct i915_vma *vma; + mutex_lock(&obj->mm.lock); if (obj->mm.pages && obj->mm.madv == I915_MADV_WILLNEED && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { @@ -267,6 +268,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, if (!i915_gem_object_is_tiled(obj)) __i915_gem_object_pin_pages(obj); } + mutex_unlock(&obj->mm.lock); list_for_each_entry(vma, &obj->vma_list, obj_link) { if (!vma->fence) diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index a421447f1d84..6c8c7b36f7fc 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -79,7 +79,7 @@ static void cancel_userptr(struct work_struct *work) WARN_ONCE(obj->mm.pages, "Failed to release pages: bind_count=%d, pages_pin_count=%d, pin_display=%d\n", obj->bind_count, - obj->mm.pages_pin_count, + atomic_read(&obj->mm.pages_pin_count), obj->pin_display); i915_gem_object_put(obj); @@ -491,7 +491,6 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) { struct get_pages_work *work = container_of(_work, typeof(*work), work); struct drm_i915_gem_object *obj = work->obj; - struct drm_device *dev = obj->base.dev; const int npages = obj->base.size >> PAGE_SHIFT; struct page **pvec; int pinned, ret; @@ -527,7 +526,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) } } - mutex_lock(&dev->struct_mutex); + mutex_lock(&obj->mm.lock); if (obj->userptr.work == &work->work) { struct sg_table *pages = ERR_PTR(ret); @@ -542,13 +541,12 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) obj->userptr.work = ERR_CAST(pages); } - - i915_gem_object_put(obj); - mutex_unlock(&dev->struct_mutex); + mutex_unlock(&obj->mm.lock); release_pages(pvec, pinned, 0); drm_free_large(pvec); + i915_gem_object_put_unlocked(obj); put_task_struct(work->task); kfree(work); } -- cgit v1.2.3 From 7dd737f377ffb59010b6811f934998d42f24a8bd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:38 +0100 Subject: drm/i915/dmabuf: Acquire the backing storage outside of struct_mutex Use the per-object mm.lock to allocate the backing storage (and hold a reference to it across the dmabuf access) without resorting to struct_mutex. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-15-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 69 +++++++++++++++------------------- 1 file changed, 30 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 2abd524aba14..4d45f20d11ed 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -44,19 +44,15 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme struct scatterlist *src, *dst; int ret, i; - ret = i915_mutex_lock_interruptible(obj->base.dev); - if (ret) - goto err; - ret = i915_gem_object_pin_pages(obj); if (ret) - goto err_unlock; + goto err; /* Copy sg so that we make an independent mapping */ st = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (st == NULL) { ret = -ENOMEM; - goto err_unpin; + goto err_unpin_pages; } ret = sg_alloc_table(st, obj->mm.pages->nents, GFP_KERNEL); @@ -72,21 +68,18 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme } if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) { - ret =-ENOMEM; + ret = -ENOMEM; goto err_free_sg; } - mutex_unlock(&obj->base.dev->struct_mutex); return st; err_free_sg: sg_free_table(st); err_free: kfree(st); -err_unpin: +err_unpin_pages: i915_gem_object_unpin_pages(obj); -err_unlock: - mutex_unlock(&obj->base.dev->struct_mutex); err: return ERR_PTR(ret); } @@ -101,36 +94,21 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, sg_free_table(sg); kfree(sg); - mutex_lock(&obj->base.dev->struct_mutex); i915_gem_object_unpin_pages(obj); - mutex_unlock(&obj->base.dev->struct_mutex); } static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) { struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); - struct drm_device *dev = obj->base.dev; - void *addr; - int ret; - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ERR_PTR(ret); - - addr = i915_gem_object_pin_map(obj, I915_MAP_WB); - mutex_unlock(&dev->struct_mutex); - return addr; + return i915_gem_object_pin_map(obj, I915_MAP_WB); } static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) { struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); - struct drm_device *dev = obj->base.dev; - mutex_lock(&dev->struct_mutex); i915_gem_object_unpin_map(obj); - mutex_unlock(&dev->struct_mutex); } static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num) @@ -177,32 +155,45 @@ static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_dire { struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); struct drm_device *dev = obj->base.dev; - int ret; bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE); + int err; - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; + err = i915_gem_object_pin_pages(obj); + if (err) + return err; + + err = i915_mutex_lock_interruptible(dev); + if (err) + goto out; - ret = i915_gem_object_set_to_cpu_domain(obj, write); + err = i915_gem_object_set_to_cpu_domain(obj, write); mutex_unlock(&dev->struct_mutex); - return ret; + +out: + i915_gem_object_unpin_pages(obj); + return err; } static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction) { struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); struct drm_device *dev = obj->base.dev; - int ret; + int err; - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; + err = i915_gem_object_pin_pages(obj); + if (err) + return err; + + err = i915_mutex_lock_interruptible(dev); + if (err) + goto out; - ret = i915_gem_object_set_to_gtt_domain(obj, false); + err = i915_gem_object_set_to_gtt_domain(obj, false); mutex_unlock(&dev->struct_mutex); - return ret; +out: + i915_gem_object_unpin_pages(obj); + return err; } static const struct dma_buf_ops i915_dmabuf_ops = { -- cgit v1.2.3 From bb6dc8d96b683a6052162c36062cd8e9329e4f21 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:39 +0100 Subject: drm/i915: Implement pread without struct-mutex We only need struct_mutex within pread for a brief window where we need to serialise with rendering and control our cache domains. Elsewhere we can rely on the backing storage being pinned, and forgive userspace any races against us. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-16-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 365 +++++++++++++++++----------------------- 1 file changed, 157 insertions(+), 208 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c8e9548adfeb..d12265872667 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -63,13 +63,13 @@ static bool cpu_write_needs_clflush(struct drm_i915_gem_object *obj) } static int -insert_mappable_node(struct drm_i915_private *i915, +insert_mappable_node(struct i915_ggtt *ggtt, struct drm_mm_node *node, u32 size) { memset(node, 0, sizeof(*node)); - return drm_mm_insert_node_in_range_generic(&i915->ggtt.base.mm, node, - size, 0, 0, 0, - i915->ggtt.mappable_end, + return drm_mm_insert_node_in_range_generic(&ggtt->base.mm, node, + size, 0, -1, + 0, ggtt->mappable_end, DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT); } @@ -821,32 +821,6 @@ err_unpin: return ret; } -/* Per-page copy function for the shmem pread fastpath. - * Flushes invalid cachelines before reading the target if - * needs_clflush is set. */ -static int -shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length, - char __user *user_data, - bool page_do_bit17_swizzling, bool needs_clflush) -{ - char *vaddr; - int ret; - - if (unlikely(page_do_bit17_swizzling)) - return -EINVAL; - - vaddr = kmap_atomic(page); - if (needs_clflush) - drm_clflush_virt_range(vaddr + shmem_page_offset, - page_length); - ret = __copy_to_user_inatomic(user_data, - vaddr + shmem_page_offset, - page_length); - kunmap_atomic(vaddr); - - return ret ? -EFAULT : 0; -} - static void shmem_clflush_swizzled_range(char *addr, unsigned long length, bool swizzled) @@ -872,7 +846,7 @@ shmem_clflush_swizzled_range(char *addr, unsigned long length, /* Only difference to the fast-path function is that this can handle bit17 * and uses non-atomic copy and kmap functions. */ static int -shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length, +shmem_pread_slow(struct page *page, int offset, int length, char __user *user_data, bool page_do_bit17_swizzling, bool needs_clflush) { @@ -881,61 +855,130 @@ shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length, vaddr = kmap(page); if (needs_clflush) - shmem_clflush_swizzled_range(vaddr + shmem_page_offset, - page_length, + shmem_clflush_swizzled_range(vaddr + offset, length, page_do_bit17_swizzling); if (page_do_bit17_swizzling) - ret = __copy_to_user_swizzled(user_data, - vaddr, shmem_page_offset, - page_length); + ret = __copy_to_user_swizzled(user_data, vaddr, offset, length); else - ret = __copy_to_user(user_data, - vaddr + shmem_page_offset, - page_length); + ret = __copy_to_user(user_data, vaddr + offset, length); kunmap(page); return ret ? - EFAULT : 0; } -static inline unsigned long -slow_user_access(struct io_mapping *mapping, - uint64_t page_base, int page_offset, - char __user *user_data, - unsigned long length, bool pwrite) +static int +shmem_pread(struct page *page, int offset, int length, char __user *user_data, + bool page_do_bit17_swizzling, bool needs_clflush) +{ + int ret; + + ret = -ENODEV; + if (!page_do_bit17_swizzling) { + char *vaddr = kmap_atomic(page); + + if (needs_clflush) + drm_clflush_virt_range(vaddr + offset, length); + ret = __copy_to_user_inatomic(user_data, vaddr + offset, length); + kunmap_atomic(vaddr); + } + if (ret == 0) + return 0; + + return shmem_pread_slow(page, offset, length, user_data, + page_do_bit17_swizzling, needs_clflush); +} + +static int +i915_gem_shmem_pread(struct drm_i915_gem_object *obj, + struct drm_i915_gem_pread *args) +{ + char __user *user_data; + u64 remain; + unsigned int obj_do_bit17_swizzling; + unsigned int needs_clflush; + unsigned int idx, offset; + int ret; + + obj_do_bit17_swizzling = 0; + if (i915_gem_object_needs_bit17_swizzle(obj)) + obj_do_bit17_swizzling = BIT(17); + + ret = mutex_lock_interruptible(&obj->base.dev->struct_mutex); + if (ret) + return ret; + + ret = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush); + mutex_unlock(&obj->base.dev->struct_mutex); + if (ret) + return ret; + + remain = args->size; + user_data = u64_to_user_ptr(args->data_ptr); + offset = offset_in_page(args->offset); + for (idx = args->offset >> PAGE_SHIFT; remain; idx++) { + struct page *page = i915_gem_object_get_page(obj, idx); + int length; + + length = remain; + if (offset + length > PAGE_SIZE) + length = PAGE_SIZE - offset; + + ret = shmem_pread(page, offset, length, user_data, + page_to_phys(page) & obj_do_bit17_swizzling, + needs_clflush); + if (ret) + break; + + remain -= length; + user_data += length; + offset = 0; + } + + i915_gem_obj_finish_shmem_access(obj); + return ret; +} + +static inline bool +gtt_user_read(struct io_mapping *mapping, + loff_t base, int offset, + char __user *user_data, int length) { - void __iomem *ioaddr; void *vaddr; - uint64_t unwritten; + unsigned long unwritten; - ioaddr = io_mapping_map_wc(mapping, page_base, PAGE_SIZE); /* We can use the cpu mem copy function because this is X86. */ - vaddr = (void __force *)ioaddr + page_offset; - if (pwrite) - unwritten = __copy_from_user(vaddr, user_data, length); - else - unwritten = __copy_to_user(user_data, vaddr, length); - - io_mapping_unmap(ioaddr); + vaddr = (void __force *)io_mapping_map_atomic_wc(mapping, base); + unwritten = __copy_to_user_inatomic(user_data, vaddr + offset, length); + io_mapping_unmap_atomic(vaddr); + if (unwritten) { + vaddr = (void __force *) + io_mapping_map_wc(mapping, base, PAGE_SIZE); + unwritten = copy_to_user(user_data, vaddr + offset, length); + io_mapping_unmap(vaddr); + } return unwritten; } static int -i915_gem_gtt_pread(struct drm_device *dev, - struct drm_i915_gem_object *obj, uint64_t size, - uint64_t data_offset, uint64_t data_ptr) +i915_gem_gtt_pread(struct drm_i915_gem_object *obj, + const struct drm_i915_gem_pread *args) { - struct drm_i915_private *dev_priv = to_i915(dev); - struct i915_ggtt *ggtt = &dev_priv->ggtt; - struct i915_vma *vma; + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct i915_ggtt *ggtt = &i915->ggtt; struct drm_mm_node node; - char __user *user_data; - uint64_t remain; - uint64_t offset; + struct i915_vma *vma; + void __user *user_data; + u64 remain, offset; int ret; - intel_runtime_pm_get(to_i915(dev)); - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE); + ret = mutex_lock_interruptible(&i915->drm.struct_mutex); + if (ret) + return ret; + + intel_runtime_pm_get(i915); + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, + PIN_MAPPABLE | PIN_NONBLOCK); if (!IS_ERR(vma)) { node.start = i915_ggtt_offset(vma); node.allocated = false; @@ -946,33 +989,21 @@ i915_gem_gtt_pread(struct drm_device *dev, } } if (IS_ERR(vma)) { - ret = insert_mappable_node(dev_priv, &node, PAGE_SIZE); + ret = insert_mappable_node(ggtt, &node, PAGE_SIZE); if (ret) - goto out; - - ret = i915_gem_object_pin_pages(obj); - if (ret) { - remove_mappable_node(&node); - goto out; - } + goto out_unlock; + GEM_BUG_ON(!node.allocated); } ret = i915_gem_object_set_to_gtt_domain(obj, false); if (ret) goto out_unpin; - user_data = u64_to_user_ptr(data_ptr); - remain = size; - offset = data_offset; + mutex_unlock(&i915->drm.struct_mutex); - mutex_unlock(&dev->struct_mutex); - if (likely(!i915.prefault_disable)) { - ret = fault_in_pages_writeable(user_data, remain); - if (ret) { - mutex_lock(&dev->struct_mutex); - goto out_unpin; - } - } + user_data = u64_to_user_ptr(args->data_ptr); + remain = args->size; + offset = args->offset; while (remain > 0) { /* Operation in this page @@ -989,19 +1020,14 @@ i915_gem_gtt_pread(struct drm_device *dev, wmb(); ggtt->base.insert_page(&ggtt->base, i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT), - node.start, - I915_CACHE_NONE, 0); + node.start, I915_CACHE_NONE, 0); wmb(); } else { page_base += offset & PAGE_MASK; } - /* This is a slow read/write as it tries to read from - * and write to user memory which may result into page - * faults, and so we cannot perform this under struct_mutex. - */ - if (slow_user_access(&ggtt->mappable, page_base, - page_offset, user_data, - page_length, false)) { + + if (gtt_user_read(&ggtt->mappable, page_base, page_offset, + user_data, page_length)) { ret = -EFAULT; break; } @@ -1011,111 +1037,19 @@ i915_gem_gtt_pread(struct drm_device *dev, offset += page_length; } - mutex_lock(&dev->struct_mutex); - if (ret == 0 && (obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0) { - /* The user has modified the object whilst we tried - * reading from it, and we now have no idea what domain - * the pages should be in. As we have just been touching - * them directly, flush everything back to the GTT - * domain. - */ - ret = i915_gem_object_set_to_gtt_domain(obj, false); - } - + mutex_lock(&i915->drm.struct_mutex); out_unpin: if (node.allocated) { wmb(); ggtt->base.clear_range(&ggtt->base, node.start, node.size); - i915_gem_object_unpin_pages(obj); remove_mappable_node(&node); } else { i915_vma_unpin(vma); } -out: - intel_runtime_pm_put(to_i915(dev)); - return ret; -} - -static int -i915_gem_shmem_pread(struct drm_device *dev, - struct drm_i915_gem_object *obj, - struct drm_i915_gem_pread *args, - struct drm_file *file) -{ - char __user *user_data; - ssize_t remain; - loff_t offset; - int shmem_page_offset, page_length, ret = 0; - int obj_do_bit17_swizzling, page_do_bit17_swizzling; - int prefaulted = 0; - int needs_clflush = 0; - struct sg_page_iter sg_iter; - - ret = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush); - if (ret) - return ret; - - obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); - user_data = u64_to_user_ptr(args->data_ptr); - offset = args->offset; - remain = args->size; - - for_each_sg_page(obj->mm.pages->sgl, &sg_iter, obj->mm.pages->nents, - offset >> PAGE_SHIFT) { - struct page *page = sg_page_iter_page(&sg_iter); - - if (remain <= 0) - break; - - /* Operation in this page - * - * shmem_page_offset = offset within page in shmem file - * page_length = bytes to copy for this page - */ - shmem_page_offset = offset_in_page(offset); - page_length = remain; - if ((shmem_page_offset + page_length) > PAGE_SIZE) - page_length = PAGE_SIZE - shmem_page_offset; - - page_do_bit17_swizzling = obj_do_bit17_swizzling && - (page_to_phys(page) & (1 << 17)) != 0; - - ret = shmem_pread_fast(page, shmem_page_offset, page_length, - user_data, page_do_bit17_swizzling, - needs_clflush); - if (ret == 0) - goto next_page; - - mutex_unlock(&dev->struct_mutex); - - if (likely(!i915.prefault_disable) && !prefaulted) { - ret = fault_in_pages_writeable(user_data, remain); - /* Userspace is tricking us, but we've already clobbered - * its pages with the prefault and promised to write the - * data up to the first fault. Hence ignore any errors - * and just continue. */ - (void)ret; - prefaulted = 1; - } - - ret = shmem_pread_slow(page, shmem_page_offset, page_length, - user_data, page_do_bit17_swizzling, - needs_clflush); - - mutex_lock(&dev->struct_mutex); - - if (ret) - goto out; - -next_page: - remain -= page_length; - user_data += page_length; - offset += page_length; - } - -out: - i915_gem_obj_finish_shmem_access(obj); +out_unlock: + intel_runtime_pm_put(i915); + mutex_unlock(&i915->drm.struct_mutex); return ret; } @@ -1134,7 +1068,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_pread *args = data; struct drm_i915_gem_object *obj; - int ret = 0; + int ret; if (args->size == 0) return 0; @@ -1152,7 +1086,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, if (args->offset > obj->base.size || args->size > obj->base.size - args->offset) { ret = -EINVAL; - goto err; + goto out; } trace_i915_gem_object_pread(obj, args->offset, args->size); @@ -1162,25 +1096,18 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, MAX_SCHEDULE_TIMEOUT, to_rps_client(file)); if (ret) - goto err; + goto out; - ret = i915_mutex_lock_interruptible(dev); + ret = i915_gem_object_pin_pages(obj); if (ret) - goto err; - - ret = i915_gem_shmem_pread(dev, obj, args, file); + goto out; - /* pread for non shmem backed objects */ + ret = i915_gem_shmem_pread(obj, args); if (ret == -EFAULT || ret == -ENODEV) - ret = i915_gem_gtt_pread(dev, obj, args->size, - args->offset, args->data_ptr); - - i915_gem_object_put(obj); - mutex_unlock(&dev->struct_mutex); - - return ret; + ret = i915_gem_gtt_pread(obj, args); -err: + i915_gem_object_unpin_pages(obj); +out: i915_gem_object_put_unlocked(obj); return ret; } @@ -1208,6 +1135,28 @@ fast_user_write(struct io_mapping *mapping, return unwritten; } +static inline unsigned long +slow_user_access(struct io_mapping *mapping, + unsigned long page_base, int page_offset, + char __user *user_data, + unsigned long length, bool pwrite) +{ + void __iomem *ioaddr; + void *vaddr; + unsigned long unwritten; + + ioaddr = io_mapping_map_wc(mapping, page_base, PAGE_SIZE); + /* We can use the cpu mem copy function because this is X86. */ + vaddr = (void __force *)ioaddr + page_offset; + if (pwrite) + unwritten = __copy_from_user(vaddr, user_data, length); + else + unwritten = __copy_to_user(user_data, vaddr, length); + + io_mapping_unmap(ioaddr); + return unwritten; +} + /** * This is the fast pwrite path, where we copy the data directly from the * user into the GTT, uncached. @@ -1247,7 +1196,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915, } } if (IS_ERR(vma)) { - ret = insert_mappable_node(i915, &node, PAGE_SIZE); + ret = insert_mappable_node(ggtt, &node, PAGE_SIZE); if (ret) goto out; @@ -1276,8 +1225,8 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915, * page_length = bytes to copy for this page */ u32 page_base = node.start; - unsigned page_offset = offset_in_page(offset); - unsigned page_length = PAGE_SIZE - page_offset; + unsigned int page_offset = offset_in_page(offset); + unsigned int page_length = PAGE_SIZE - page_offset; page_length = remain < page_length ? remain : page_length; if (node.allocated) { wmb(); /* flush the write before we modify the GGTT */ -- cgit v1.2.3 From fe115628d567ba83a1498c585604d9035842b57c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:40 +0100 Subject: drm/i915: Implement pwrite without struct-mutex We only need struct_mutex within pwrite for a brief window where we need to serialise with rendering and control our cache domains. Elsewhere we can rely on the backing storage being pinned, and forgive userspace any races against us. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-17-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 353 ++++++++++++++-------------------------- 1 file changed, 122 insertions(+), 231 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d12265872667..fad1487a204b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1116,72 +1116,50 @@ out: * page faults in the source data */ -static inline int -fast_user_write(struct io_mapping *mapping, - loff_t page_base, int page_offset, - char __user *user_data, - int length) +static inline bool +ggtt_write(struct io_mapping *mapping, + loff_t base, int offset, + char __user *user_data, int length) { - void __iomem *vaddr_atomic; void *vaddr; unsigned long unwritten; - vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); /* We can use the cpu mem copy function because this is X86. */ - vaddr = (void __force*)vaddr_atomic + page_offset; - unwritten = __copy_from_user_inatomic_nocache(vaddr, + vaddr = (void __force *)io_mapping_map_atomic_wc(mapping, base); + unwritten = __copy_from_user_inatomic_nocache(vaddr + offset, user_data, length); - io_mapping_unmap_atomic(vaddr_atomic); - return unwritten; -} - -static inline unsigned long -slow_user_access(struct io_mapping *mapping, - unsigned long page_base, int page_offset, - char __user *user_data, - unsigned long length, bool pwrite) -{ - void __iomem *ioaddr; - void *vaddr; - unsigned long unwritten; - - ioaddr = io_mapping_map_wc(mapping, page_base, PAGE_SIZE); - /* We can use the cpu mem copy function because this is X86. */ - vaddr = (void __force *)ioaddr + page_offset; - if (pwrite) - unwritten = __copy_from_user(vaddr, user_data, length); - else - unwritten = __copy_to_user(user_data, vaddr, length); + io_mapping_unmap_atomic(vaddr); + if (unwritten) { + vaddr = (void __force *) + io_mapping_map_wc(mapping, base, PAGE_SIZE); + unwritten = copy_from_user(vaddr + offset, user_data, length); + io_mapping_unmap(vaddr); + } - io_mapping_unmap(ioaddr); return unwritten; } /** * This is the fast pwrite path, where we copy the data directly from the * user into the GTT, uncached. - * @i915: i915 device private data - * @obj: i915 gem object + * @obj: i915 GEM object * @args: pwrite arguments structure - * @file: drm file pointer */ static int -i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915, - struct drm_i915_gem_object *obj, - struct drm_i915_gem_pwrite *args, - struct drm_file *file) +i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, + const struct drm_i915_gem_pwrite *args) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); struct i915_ggtt *ggtt = &i915->ggtt; - struct drm_device *dev = obj->base.dev; - struct i915_vma *vma; struct drm_mm_node node; - uint64_t remain, offset; - char __user *user_data; + struct i915_vma *vma; + u64 remain, offset; + void __user *user_data; int ret; - bool hit_slow_path = false; - if (i915_gem_object_is_tiled(obj)) - return -EFAULT; + ret = mutex_lock_interruptible(&i915->drm.struct_mutex); + if (ret) + return ret; intel_runtime_pm_get(i915); vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, @@ -1198,21 +1176,17 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915, if (IS_ERR(vma)) { ret = insert_mappable_node(ggtt, &node, PAGE_SIZE); if (ret) - goto out; - - ret = i915_gem_object_pin_pages(obj); - if (ret) { - remove_mappable_node(&node); - goto out; - } + goto out_unlock; + GEM_BUG_ON(!node.allocated); } ret = i915_gem_object_set_to_gtt_domain(obj, true); if (ret) goto out_unpin; + mutex_unlock(&i915->drm.struct_mutex); + intel_fb_obj_invalidate(obj, ORIGIN_CPU); - obj->mm.dirty = true; user_data = u64_to_user_ptr(args->data_ptr); offset = args->offset; @@ -1243,92 +1217,36 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915, * If the object is non-shmem backed, we retry again with the * path that handles page fault. */ - if (fast_user_write(&ggtt->mappable, page_base, - page_offset, user_data, page_length)) { - hit_slow_path = true; - mutex_unlock(&dev->struct_mutex); - if (slow_user_access(&ggtt->mappable, - page_base, - page_offset, user_data, - page_length, true)) { - ret = -EFAULT; - mutex_lock(&dev->struct_mutex); - goto out_flush; - } - - mutex_lock(&dev->struct_mutex); + if (ggtt_write(&ggtt->mappable, page_base, page_offset, + user_data, page_length)) { + ret = -EFAULT; + break; } remain -= page_length; user_data += page_length; offset += page_length; } - -out_flush: - if (hit_slow_path) { - if (ret == 0 && - (obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0) { - /* The user has modified the object whilst we tried - * reading from it, and we now have no idea what domain - * the pages should be in. As we have just been touching - * them directly, flush everything back to the GTT - * domain. - */ - ret = i915_gem_object_set_to_gtt_domain(obj, false); - } - } - intel_fb_obj_flush(obj, false, ORIGIN_CPU); + + mutex_lock(&i915->drm.struct_mutex); out_unpin: if (node.allocated) { wmb(); ggtt->base.clear_range(&ggtt->base, node.start, node.size); - i915_gem_object_unpin_pages(obj); remove_mappable_node(&node); } else { i915_vma_unpin(vma); } -out: +out_unlock: intel_runtime_pm_put(i915); + mutex_unlock(&i915->drm.struct_mutex); return ret; } -/* Per-page copy function for the shmem pwrite fastpath. - * Flushes invalid cachelines before writing to the target if - * needs_clflush_before is set and flushes out any written cachelines after - * writing if needs_clflush is set. */ static int -shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length, - char __user *user_data, - bool page_do_bit17_swizzling, - bool needs_clflush_before, - bool needs_clflush_after) -{ - char *vaddr; - int ret; - - if (unlikely(page_do_bit17_swizzling)) - return -EINVAL; - - vaddr = kmap_atomic(page); - if (needs_clflush_before) - drm_clflush_virt_range(vaddr + shmem_page_offset, - page_length); - ret = __copy_from_user_inatomic(vaddr + shmem_page_offset, - user_data, page_length); - if (needs_clflush_after) - drm_clflush_virt_range(vaddr + shmem_page_offset, - page_length); - kunmap_atomic(vaddr); - - return ret ? -EFAULT : 0; -} - -/* Only difference to the fast-path function is that this can handle bit17 - * and uses non-atomic copy and kmap functions. */ -static int -shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length, +shmem_pwrite_slow(struct page *page, int offset, int length, char __user *user_data, bool page_do_bit17_swizzling, bool needs_clflush_before, @@ -1339,124 +1257,114 @@ shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length, vaddr = kmap(page); if (unlikely(needs_clflush_before || page_do_bit17_swizzling)) - shmem_clflush_swizzled_range(vaddr + shmem_page_offset, - page_length, + shmem_clflush_swizzled_range(vaddr + offset, length, page_do_bit17_swizzling); if (page_do_bit17_swizzling) - ret = __copy_from_user_swizzled(vaddr, shmem_page_offset, - user_data, - page_length); + ret = __copy_from_user_swizzled(vaddr, offset, user_data, + length); else - ret = __copy_from_user(vaddr + shmem_page_offset, - user_data, - page_length); + ret = __copy_from_user(vaddr + offset, user_data, length); if (needs_clflush_after) - shmem_clflush_swizzled_range(vaddr + shmem_page_offset, - page_length, + shmem_clflush_swizzled_range(vaddr + offset, length, page_do_bit17_swizzling); kunmap(page); return ret ? -EFAULT : 0; } +/* Per-page copy function for the shmem pwrite fastpath. + * Flushes invalid cachelines before writing to the target if + * needs_clflush_before is set and flushes out any written cachelines after + * writing if needs_clflush is set. + */ static int -i915_gem_shmem_pwrite(struct drm_device *dev, - struct drm_i915_gem_object *obj, - struct drm_i915_gem_pwrite *args, - struct drm_file *file) +shmem_pwrite(struct page *page, int offset, int len, char __user *user_data, + bool page_do_bit17_swizzling, + bool needs_clflush_before, + bool needs_clflush_after) { - ssize_t remain; - loff_t offset; - char __user *user_data; - int shmem_page_offset, page_length, ret = 0; - int obj_do_bit17_swizzling, page_do_bit17_swizzling; - int hit_slowpath = 0; + int ret; + + ret = -ENODEV; + if (!page_do_bit17_swizzling) { + char *vaddr = kmap_atomic(page); + + if (needs_clflush_before) + drm_clflush_virt_range(vaddr + offset, len); + ret = __copy_from_user_inatomic(vaddr + offset, user_data, len); + if (needs_clflush_after) + drm_clflush_virt_range(vaddr + offset, len); + + kunmap_atomic(vaddr); + } + if (ret == 0) + return ret; + + return shmem_pwrite_slow(page, offset, len, user_data, + page_do_bit17_swizzling, + needs_clflush_before, + needs_clflush_after); +} + +static int +i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj, + const struct drm_i915_gem_pwrite *args) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + void __user *user_data; + u64 remain; + unsigned int obj_do_bit17_swizzling; + unsigned int partial_cacheline_write; unsigned int needs_clflush; - struct sg_page_iter sg_iter; + unsigned int offset, idx; + int ret; - ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush); + ret = mutex_lock_interruptible(&i915->drm.struct_mutex); if (ret) return ret; - obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); - user_data = u64_to_user_ptr(args->data_ptr); - offset = args->offset; - remain = args->size; + ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush); + mutex_unlock(&i915->drm.struct_mutex); + if (ret) + return ret; - for_each_sg_page(obj->mm.pages->sgl, &sg_iter, obj->mm.pages->nents, - offset >> PAGE_SHIFT) { - struct page *page = sg_page_iter_page(&sg_iter); - int partial_cacheline_write; + obj_do_bit17_swizzling = 0; + if (i915_gem_object_needs_bit17_swizzle(obj)) + obj_do_bit17_swizzling = BIT(17); - if (remain <= 0) - break; + /* If we don't overwrite a cacheline completely we need to be + * careful to have up-to-date data by first clflushing. Don't + * overcomplicate things and flush the entire patch. + */ + partial_cacheline_write = 0; + if (needs_clflush & CLFLUSH_BEFORE) + partial_cacheline_write = boot_cpu_data.x86_clflush_size - 1; - /* Operation in this page - * - * shmem_page_offset = offset within page in shmem file - * page_length = bytes to copy for this page - */ - shmem_page_offset = offset_in_page(offset); - - page_length = remain; - if ((shmem_page_offset + page_length) > PAGE_SIZE) - page_length = PAGE_SIZE - shmem_page_offset; - - /* If we don't overwrite a cacheline completely we need to be - * careful to have up-to-date data by first clflushing. Don't - * overcomplicate things and flush the entire patch. */ - partial_cacheline_write = needs_clflush & CLFLUSH_BEFORE && - ((shmem_page_offset | page_length) - & (boot_cpu_data.x86_clflush_size - 1)); - - page_do_bit17_swizzling = obj_do_bit17_swizzling && - (page_to_phys(page) & (1 << 17)) != 0; - - ret = shmem_pwrite_fast(page, shmem_page_offset, page_length, - user_data, page_do_bit17_swizzling, - partial_cacheline_write, - needs_clflush & CLFLUSH_AFTER); - if (ret == 0) - goto next_page; - - hit_slowpath = 1; - mutex_unlock(&dev->struct_mutex); - ret = shmem_pwrite_slow(page, shmem_page_offset, page_length, - user_data, page_do_bit17_swizzling, - partial_cacheline_write, - needs_clflush & CLFLUSH_AFTER); + user_data = u64_to_user_ptr(args->data_ptr); + remain = args->size; + offset = offset_in_page(args->offset); + for (idx = args->offset >> PAGE_SHIFT; remain; idx++) { + struct page *page = i915_gem_object_get_page(obj, idx); + int length; - mutex_lock(&dev->struct_mutex); + length = remain; + if (offset + length > PAGE_SIZE) + length = PAGE_SIZE - offset; + ret = shmem_pwrite(page, offset, length, user_data, + page_to_phys(page) & obj_do_bit17_swizzling, + (offset | length) & partial_cacheline_write, + needs_clflush & CLFLUSH_AFTER); if (ret) - goto out; - -next_page: - remain -= page_length; - user_data += page_length; - offset += page_length; - } - -out: - i915_gem_obj_finish_shmem_access(obj); + break; - if (hit_slowpath) { - /* - * Fixup: Flush cpu caches in case we didn't flush the dirty - * cachelines in-line while writing and the object moved - * out of the cpu write domain while we've dropped the lock. - */ - if (!(needs_clflush & CLFLUSH_AFTER) && - obj->base.write_domain != I915_GEM_DOMAIN_CPU) { - if (i915_gem_clflush_object(obj, obj->pin_display)) - needs_clflush |= CLFLUSH_AFTER; - } + remain -= length; + user_data += length; + offset = 0; } - if (needs_clflush & CLFLUSH_AFTER) - i915_gem_chipset_flush(to_i915(dev)); - intel_fb_obj_flush(obj, false, ORIGIN_CPU); + i915_gem_obj_finish_shmem_access(obj); return ret; } @@ -1472,7 +1380,6 @@ int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_pwrite *args = data; struct drm_i915_gem_object *obj; int ret; @@ -1485,13 +1392,6 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, args->size)) return -EFAULT; - if (likely(!i915.prefault_disable)) { - ret = fault_in_pages_readable(u64_to_user_ptr(args->data_ptr), - args->size); - if (ret) - return -EFAULT; - } - obj = i915_gem_object_lookup(file, args->handle); if (!obj) return -ENOENT; @@ -1513,11 +1413,9 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, if (ret) goto err; - intel_runtime_pm_get(dev_priv); - - ret = i915_mutex_lock_interruptible(dev); + ret = i915_gem_object_pin_pages(obj); if (ret) - goto err_rpm; + goto err; ret = -EFAULT; /* We can only do the GTT pwrite on untiled buffers, as otherwise @@ -1532,23 +1430,16 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, * pointers (e.g. gtt mappings when moving data between * textures). Fallback to the shmem path in that case. */ - ret = i915_gem_gtt_pwrite_fast(dev_priv, obj, args, file); + ret = i915_gem_gtt_pwrite_fast(obj, args); if (ret == -EFAULT || ret == -ENOSPC) { if (obj->phys_handle) ret = i915_gem_phys_pwrite(obj, args, file); else - ret = i915_gem_shmem_pwrite(dev, obj, args, file); + ret = i915_gem_shmem_pwrite(obj, args); } - i915_gem_object_put(obj); - mutex_unlock(&dev->struct_mutex); - intel_runtime_pm_put(dev_priv); - - return ret; - -err_rpm: - intel_runtime_pm_put(dev_priv); + i915_gem_object_unpin_pages(obj); err: i915_gem_object_put_unlocked(obj); return ret; -- cgit v1.2.3 From 40e62d5d6be8b4999068da31ee6aca7ca76669ee Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:41 +0100 Subject: drm/i915: Acquire the backing storage outside of struct_mutex in set-domain As we can locklessly (well struct_mutex-lessly) acquire the backing storage, do so in set-domain-ioctl to reduce the contention on the struct_mutex. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-18-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 99 +++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fad1487a204b..9f1bb1f80787 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1452,6 +1452,30 @@ write_origin(struct drm_i915_gem_object *obj, unsigned domain) obj->frontbuffer_ggtt_origin : ORIGIN_CPU); } +static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915; + struct list_head *list; + struct i915_vma *vma; + + list_for_each_entry(vma, &obj->vma_list, obj_link) { + if (!i915_vma_is_ggtt(vma)) + continue; + + if (i915_vma_is_active(vma)) + continue; + + if (!drm_mm_node_allocated(&vma->node)) + continue; + + list_move_tail(&vma->vm_link, &vma->vm->inactive_list); + } + + i915 = to_i915(obj->base.dev); + list = obj->bind_count ? &i915->mm.bound_list : &i915->mm.unbound_list; + list_move_tail(&obj->global_list, list); +} + /** * Called when user space prepares to use an object with the CPU, either * through the mmap ioctl's mapping or a GTT mapping. @@ -1467,7 +1491,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_object *obj; uint32_t read_domains = args->read_domains; uint32_t write_domain = args->write_domain; - int ret; + int err; /* Only handle setting domains to types used by the CPU. */ if ((write_domain | read_domains) & I915_GEM_GPU_DOMAINS) @@ -1487,33 +1511,48 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, * We will repeat the flush holding the lock in the normal manner * to catch cases where we are gazumped. */ - ret = i915_gem_object_wait(obj, + err = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE | (write_domain ? I915_WAIT_ALL : 0), MAX_SCHEDULE_TIMEOUT, to_rps_client(file)); - if (ret) - goto err; + if (err) + goto out_unlocked; - ret = i915_mutex_lock_interruptible(dev); - if (ret) - goto err; + /* Flush and acquire obj->pages so that we are coherent through + * direct access in memory with previous cached writes through + * shmemfs and that our cache domain tracking remains valid. + * For example, if the obj->filp was moved to swap without us + * being notified and releasing the pages, we would mistakenly + * continue to assume that the obj remained out of the CPU cached + * domain. + */ + err = i915_gem_object_pin_pages(obj); + if (err) + goto out_unlocked; + + err = i915_mutex_lock_interruptible(dev); + if (err) + goto out_pages; if (read_domains & I915_GEM_DOMAIN_GTT) - ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); + err = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); else - ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); + err = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); - if (write_domain != 0) - intel_fb_obj_invalidate(obj, write_origin(obj, write_domain)); + /* And bump the LRU for this access */ + i915_gem_object_bump_inactive_ggtt(obj); - i915_gem_object_put(obj); mutex_unlock(&dev->struct_mutex); - return ret; -err: + if (write_domain != 0) + intel_fb_obj_invalidate(obj, write_origin(obj, write_domain)); + +out_pages: + i915_gem_object_unpin_pages(obj); +out_unlocked: i915_gem_object_put_unlocked(obj); - return ret; + return err; } /** @@ -1734,6 +1773,10 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf) if (ret) goto err; + ret = i915_gem_object_pin_pages(obj); + if (ret) + goto err; + intel_runtime_pm_get(dev_priv); ret = i915_mutex_lock_interruptible(dev); @@ -1816,6 +1859,7 @@ err_unlock: mutex_unlock(&dev->struct_mutex); err_rpm: intel_runtime_pm_put(dev_priv); + i915_gem_object_unpin_pages(obj); err: switch (ret) { case -EIO: @@ -3269,24 +3313,6 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj) I915_GEM_DOMAIN_CPU); } -static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj) -{ - struct i915_vma *vma; - - list_for_each_entry(vma, &obj->vma_list, obj_link) { - if (!i915_vma_is_ggtt(vma)) - continue; - - if (i915_vma_is_active(vma)) - continue; - - if (!drm_mm_node_allocated(&vma->node)) - continue; - - list_move_tail(&vma->vm_link, &vma->vm->inactive_list); - } -} - /** * Moves a single object to the GTT read, and possibly write domain. * @obj: object to act on @@ -3342,7 +3368,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0); obj->base.read_domains |= I915_GEM_DOMAIN_GTT; if (write) { obj->base.read_domains = I915_GEM_DOMAIN_GTT; @@ -3354,10 +3380,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) old_read_domains, old_write_domain); - /* And bump the LRU for this access */ - i915_gem_object_bump_inactive_ggtt(obj); i915_gem_object_unpin_pages(obj); - return 0; } @@ -3713,7 +3736,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0); + GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0); /* If we're writing through the CPU, then the GPU read domains will * need to be invalidated at next use. -- cgit v1.2.3 From fbbd37b36fa5e16a03aca07a922192d3db28588d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:42 +0100 Subject: drm/i915: Move object release to a freelist + worker We want to hide the latency of releasing objects and their backing storage from the submission, so we move the actual free to a worker. This allows us to switch to struct_mutex freeing of the object in the next patch. Furthermore, if we know that the object we are dereferencing remains valid for the duration of our access, we can forgo the usual synchronisation barriers and atomic reference counting. To ensure this we defer freeing an object til after an RCU grace period, such that any lookup of the object within an RCU read critical section will remain valid until after we exit that critical section. We also employ this delay for rate-limiting the serialisation on reallocation - we have to slow down object creation in order to prevent resource starvation (in particular, files). v2: Return early in i915_gem_tiling() ioctl to skip over superfluous work on error. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-19-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 15 ++- drivers/gpu/drm/i915/i915_drv.c | 19 ++-- drivers/gpu/drm/i915/i915_drv.h | 44 +++++++- drivers/gpu/drm/i915/i915_gem.c | 166 +++++++++++++++++++++---------- drivers/gpu/drm/i915/i915_gem_shrinker.c | 14 ++- drivers/gpu/drm/i915/i915_gem_tiling.c | 21 ++-- 6 files changed, 202 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e97a16cb6b67..b0b01002c0d1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4957,10 +4957,12 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_test_irq_fops, #define DROP_BOUND 0x2 #define DROP_RETIRE 0x4 #define DROP_ACTIVE 0x8 -#define DROP_ALL (DROP_UNBOUND | \ - DROP_BOUND | \ - DROP_RETIRE | \ - DROP_ACTIVE) +#define DROP_FREED 0x10 +#define DROP_ALL (DROP_UNBOUND | \ + DROP_BOUND | \ + DROP_RETIRE | \ + DROP_ACTIVE | \ + DROP_FREED) static int i915_drop_caches_get(void *data, u64 *val) { @@ -5004,6 +5006,11 @@ i915_drop_caches_set(void *data, u64 val) unlock: mutex_unlock(&dev->struct_mutex); + if (val & DROP_FREED) { + synchronize_rcu(); + flush_work(&dev_priv->mm.free_work); + } + return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index af3559d34328..b308f7173b6d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -537,14 +537,17 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { .can_switch = i915_switcheroo_can_switch, }; -static void i915_gem_fini(struct drm_device *dev) +static void i915_gem_fini(struct drm_i915_private *dev_priv) { - mutex_lock(&dev->struct_mutex); - i915_gem_cleanup_engines(dev); - i915_gem_context_fini(dev); - mutex_unlock(&dev->struct_mutex); + mutex_lock(&dev_priv->drm.struct_mutex); + i915_gem_cleanup_engines(&dev_priv->drm); + i915_gem_context_fini(&dev_priv->drm); + mutex_unlock(&dev_priv->drm.struct_mutex); + + synchronize_rcu(); + flush_work(&dev_priv->mm.free_work); - WARN_ON(!list_empty(&to_i915(dev)->context_list)); + WARN_ON(!list_empty(&dev_priv->context_list)); } static int i915_load_modeset_init(struct drm_device *dev) @@ -619,7 +622,7 @@ static int i915_load_modeset_init(struct drm_device *dev) cleanup_gem: if (i915_gem_suspend(dev)) DRM_ERROR("failed to idle hardware; continuing to unload!\n"); - i915_gem_fini(dev); + i915_gem_fini(dev_priv); cleanup_irq: intel_guc_fini(dev); drm_irq_uninstall(dev); @@ -1305,7 +1308,7 @@ void i915_driver_unload(struct drm_device *dev) drain_workqueue(dev_priv->wq); intel_guc_fini(dev); - i915_gem_fini(dev); + i915_gem_fini(dev_priv); intel_fbc_cleanup_cfb(dev_priv); intel_power_domains_fini(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f69e0e03e259..6f648a3b96f4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1365,8 +1365,8 @@ struct i915_gem_mm { struct list_head bound_list; /** * List of objects which are not bound to the GTT (thus - * are idle and not used by the GPU) but still have - * (presumably uncached) pages still attached. + * are idle and not used by the GPU). These objects may or may + * not actually have any pages attached. */ struct list_head unbound_list; @@ -1375,6 +1375,12 @@ struct i915_gem_mm { */ struct list_head userfault_list; + /** + * List of objects which are pending destruction. + */ + struct llist_head free_list; + struct work_struct free_work; + /** Usable portion of the GTT for GEM */ unsigned long stolen_base; /* limited to low memory (32-bit) */ @@ -2224,6 +2230,10 @@ struct drm_i915_gem_object { /** Stolen memory for this object, instead of being backed by shmem. */ struct drm_mm_node *stolen; struct list_head global_list; + union { + struct rcu_head rcu; + struct llist_node freed; + }; /** * Whether the object is currently in the GGTT mmap. @@ -2341,10 +2351,38 @@ to_intel_bo(struct drm_gem_object *gem) return container_of(gem, struct drm_i915_gem_object, base); } +/** + * i915_gem_object_lookup_rcu - look up a temporary GEM object from its handle + * @filp: DRM file private date + * @handle: userspace handle + * + * Returns: + * + * A pointer to the object named by the handle if such exists on @filp, NULL + * otherwise. This object is only valid whilst under the RCU read lock, and + * note carefully the object may be in the process of being destroyed. + */ +static inline struct drm_i915_gem_object * +i915_gem_object_lookup_rcu(struct drm_file *file, u32 handle) +{ +#ifdef CONFIG_LOCKDEP + WARN_ON(debug_locks && !lock_is_held(&rcu_lock_map)); +#endif + return idr_find(&file->object_idr, handle); +} + static inline struct drm_i915_gem_object * i915_gem_object_lookup(struct drm_file *file, u32 handle) { - return to_intel_bo(drm_gem_object_lookup(file, handle)); + struct drm_i915_gem_object *obj; + + rcu_read_lock(); + obj = i915_gem_object_lookup_rcu(file, handle); + if (obj && !kref_get_unless_zero(&obj->base.refcount)) + obj = NULL; + rcu_read_unlock(); + + return obj; } __deprecated diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9f1bb1f80787..07b2eb6bc572 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -42,6 +42,7 @@ #include #include +static void i915_gem_flush_free_objects(struct drm_i915_private *i915); static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj); static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj); @@ -648,6 +649,8 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_create *args = data; + i915_gem_flush_free_objects(to_i915(dev)); + return i915_gem_create(file, dev, args->size, &args->handle); } @@ -3524,10 +3527,14 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_caching *args = data; struct drm_i915_gem_object *obj; + int err = 0; - obj = i915_gem_object_lookup(file, args->handle); - if (!obj) - return -ENOENT; + rcu_read_lock(); + obj = i915_gem_object_lookup_rcu(file, args->handle); + if (!obj) { + err = -ENOENT; + goto out; + } switch (obj->cache_level) { case I915_CACHE_LLC: @@ -3543,9 +3550,9 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, args->caching = I915_CACHING_NONE; break; } - - i915_gem_object_put_unlocked(obj); - return 0; +out: + rcu_read_unlock(); + return err; } int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, @@ -4089,10 +4096,14 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_busy *args = data; struct drm_i915_gem_object *obj; unsigned long active; + int err; - obj = i915_gem_object_lookup(file, args->handle); - if (!obj) - return -ENOENT; + rcu_read_lock(); + obj = i915_gem_object_lookup_rcu(file, args->handle); + if (!obj) { + err = -ENOENT; + goto out; + } args->busy = 0; active = __I915_BO_ACTIVE(obj); @@ -4122,7 +4133,6 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * are busy is not completely reliable - we only guarantee * that the object was busy. */ - rcu_read_lock(); for_each_active(active, idx) args->busy |= busy_check_reader(&obj->last_read[idx]); @@ -4140,12 +4150,11 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * the result. */ args->busy |= busy_check_writer(&obj->last_write); - - rcu_read_unlock(); } - i915_gem_object_put_unlocked(obj); - return 0; +out: + rcu_read_unlock(); + return err; } int @@ -4308,7 +4317,6 @@ i915_gem_object_create(struct drm_device *dev, u64 size) fail: i915_gem_object_free(obj); - return ERR_PTR(ret); } @@ -4336,16 +4344,69 @@ static bool discard_backing_storage(struct drm_i915_gem_object *obj) return atomic_long_read(&obj->base.filp->f_count) == 1; } -void i915_gem_free_object(struct drm_gem_object *gem_obj) +static void __i915_gem_free_objects(struct drm_i915_private *i915, + struct llist_node *freed) { - struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); - struct drm_device *dev = obj->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct i915_vma *vma, *next; + struct drm_i915_gem_object *obj, *on; - intel_runtime_pm_get(dev_priv); + mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); + llist_for_each_entry(obj, freed, freed) { + struct i915_vma *vma, *vn; + + trace_i915_gem_object_destroy(obj); + + GEM_BUG_ON(i915_gem_object_is_active(obj)); + list_for_each_entry_safe(vma, vn, + &obj->vma_list, obj_link) { + GEM_BUG_ON(!i915_vma_is_ggtt(vma)); + GEM_BUG_ON(i915_vma_is_active(vma)); + vma->flags &= ~I915_VMA_PIN_MASK; + i915_vma_close(vma); + } + + list_del(&obj->global_list); + } + intel_runtime_pm_put(i915); + mutex_unlock(&i915->drm.struct_mutex); + + llist_for_each_entry_safe(obj, on, freed, freed) { + GEM_BUG_ON(obj->bind_count); + GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits)); + + if (obj->ops->release) + obj->ops->release(obj); + + if (WARN_ON(i915_gem_object_has_pinned_pages(obj))) + atomic_set(&obj->mm.pages_pin_count, 0); + __i915_gem_object_put_pages(obj); + GEM_BUG_ON(obj->mm.pages); + + if (obj->base.import_attach) + drm_prime_gem_destroy(&obj->base, NULL); + + drm_gem_object_release(&obj->base); + i915_gem_info_remove_obj(i915, obj->base.size); + + kfree(obj->bit_17); + i915_gem_object_free(obj); + } +} - trace_i915_gem_object_destroy(obj); +static void i915_gem_flush_free_objects(struct drm_i915_private *i915) +{ + struct llist_node *freed; + + freed = llist_del_all(&i915->mm.free_list); + if (unlikely(freed)) + __i915_gem_free_objects(i915, freed); +} + +static void __i915_gem_free_work(struct work_struct *work) +{ + struct drm_i915_private *i915 = + container_of(work, struct drm_i915_private, mm.free_work); + struct llist_node *freed; /* All file-owned VMA should have been released by this point through * i915_gem_close_object(), or earlier by i915_gem_context_close(). @@ -4354,42 +4415,44 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) * the GTT either for the user or for scanout). Those VMA still need to * unbound now. */ - list_for_each_entry_safe(vma, next, &obj->vma_list, obj_link) { - GEM_BUG_ON(!i915_vma_is_ggtt(vma)); - GEM_BUG_ON(i915_vma_is_active(vma)); - vma->flags &= ~I915_VMA_PIN_MASK; - i915_vma_close(vma); - } - GEM_BUG_ON(obj->bind_count); - WARN_ON(atomic_read(&obj->frontbuffer_bits)); + while ((freed = llist_del_all(&i915->mm.free_list))) + __i915_gem_free_objects(i915, freed); +} - if (obj->mm.pages && obj->mm.madv == I915_MADV_WILLNEED && - dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES && - i915_gem_object_is_tiled(obj)) - __i915_gem_object_unpin_pages(obj); +static void __i915_gem_free_object_rcu(struct rcu_head *head) +{ + struct drm_i915_gem_object *obj = + container_of(head, typeof(*obj), rcu); + struct drm_i915_private *i915 = to_i915(obj->base.dev); - if (obj->ops->release) - obj->ops->release(obj); + /* We can't simply use call_rcu() from i915_gem_free_object() + * as we need to block whilst unbinding, and the call_rcu + * task may be called from softirq context. So we take a + * detour through a worker. + */ + if (llist_add(&obj->freed, &i915->mm.free_list)) + schedule_work(&i915->mm.free_work); +} + +void i915_gem_free_object(struct drm_gem_object *gem_obj) +{ + struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); - if (WARN_ON(i915_gem_object_has_pinned_pages(obj))) - atomic_set(&obj->mm.pages_pin_count, 0); if (discard_backing_storage(obj)) obj->mm.madv = I915_MADV_DONTNEED; - __i915_gem_object_put_pages(obj); - GEM_BUG_ON(obj->mm.pages); - - if (obj->base.import_attach) - drm_prime_gem_destroy(&obj->base, NULL); - - drm_gem_object_release(&obj->base); - i915_gem_info_remove_obj(dev_priv, obj->base.size); - - kfree(obj->bit_17); - i915_gem_object_free(obj); + if (obj->mm.pages && obj->mm.madv == I915_MADV_WILLNEED && + to_i915(obj->base.dev)->quirks & QUIRK_PIN_SWIZZLED_PAGES && + i915_gem_object_is_tiled(obj)) + __i915_gem_object_unpin_pages(obj); - intel_runtime_pm_put(dev_priv); + /* Before we free the object, make sure any pure RCU-only + * read-side critical sections are complete, e.g. + * i915_gem_busy_ioctl(). For the corresponding synchronized + * lookup see i915_gem_object_lookup_rcu(). + */ + call_rcu(&obj->rcu, __i915_gem_free_object_rcu); } void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj) @@ -4438,6 +4501,7 @@ int i915_gem_suspend(struct drm_device *dev) cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); cancel_delayed_work_sync(&dev_priv->gt.retire_work); flush_delayed_work(&dev_priv->gt.idle_work); + flush_work(&dev_priv->mm.free_work); /* Assert that we sucessfully flushed all the work and * reset the GPU back to its idle, low power state. @@ -4753,6 +4817,8 @@ i915_gem_load_init(struct drm_device *dev) NULL); INIT_LIST_HEAD(&dev_priv->context_list); + INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work); + init_llist_head(&dev_priv->mm.free_list); INIT_LIST_HEAD(&dev_priv->mm.unbound_list); INIT_LIST_HEAD(&dev_priv->mm.bound_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index c8a4c40ec2c2..0241658af16b 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -201,6 +201,10 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, typeof(*obj), global_list))) { list_move_tail(&obj->global_list, &still_in_list); + if (!obj->mm.pages) { + list_del_init(&obj->global_list); + continue; + } if (flags & I915_SHRINK_PURGEABLE && obj->mm.madv != I915_MADV_DONTNEED) @@ -218,8 +222,6 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, if (!can_release_pages(obj)) continue; - i915_gem_object_get(obj); - if (unsafe_drop_pages(obj)) { mutex_lock(&obj->mm.lock); if (!obj->mm.pages) { @@ -228,8 +230,6 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, } mutex_unlock(&obj->mm.lock); } - - i915_gem_object_put(obj); } list_splice(&still_in_list, phase->list); } @@ -396,12 +396,18 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) */ unbound = bound = unevictable = 0; list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) { + if (!obj->mm.pages) + continue; + if (!can_release_pages(obj)) unevictable += obj->base.size >> PAGE_SHIFT; else unbound += obj->base.size >> PAGE_SHIFT; } list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { + if (!obj->mm.pages) + continue; + if (!can_release_pages(obj)) unevictable += obj->base.size >> PAGE_SHIFT; else diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 6608799ee1f9..c63a9cf4da33 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -325,12 +325,19 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, struct drm_i915_gem_get_tiling *args = data; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_object *obj; + int err = -ENOENT; + + rcu_read_lock(); + obj = i915_gem_object_lookup_rcu(file, args->handle); + if (obj) { + args->tiling_mode = + READ_ONCE(obj->tiling_and_stride) & TILING_MASK; + err = 0; + } + rcu_read_unlock(); + if (unlikely(err)) + return err; - obj = i915_gem_object_lookup(file, args->handle); - if (!obj) - return -ENOENT; - - args->tiling_mode = READ_ONCE(obj->tiling_and_stride) & TILING_MASK; switch (args->tiling_mode) { case I915_TILING_X: args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x; @@ -338,11 +345,10 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, case I915_TILING_Y: args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y; break; + default: case I915_TILING_NONE: args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; break; - default: - DRM_ERROR("unknown tiling mode\n"); } /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */ @@ -355,6 +361,5 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17) args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10; - i915_gem_object_put_unlocked(obj); return 0; } -- cgit v1.2.3 From f0cd518206e1a47e57bc251e1faba9d38eadcc59 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:43 +0100 Subject: drm/i915: Use lockless object free Having moved the locked phase of freeing an object to a separate worker, we can now declare to the core that we only need the unlocked variant of driver->gem_free_object, and can use the simple unreference internally. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-20-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 10 +--------- drivers/gpu/drm/i915/i915_gem.c | 30 +++++++++++++++--------------- drivers/gpu/drm/i915/i915_gem_tiling.c | 2 +- drivers/gpu/drm/i915/i915_gem_userptr.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 6 +++--- drivers/gpu/drm/i915/intel_overlay.c | 4 ++-- drivers/gpu/drm/i915/intel_pm.c | 2 +- 8 files changed, 26 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b308f7173b6d..91cd7b296c0f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2575,7 +2575,7 @@ static struct drm_driver driver = { .set_busid = drm_pci_set_busid, .gem_close_object = i915_gem_close_object, - .gem_free_object = i915_gem_free_object, + .gem_free_object_unlocked = i915_gem_free_object, .gem_vm_ops = &i915_gem_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6f648a3b96f4..c3c49bc4d2ac 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2404,19 +2404,12 @@ __attribute__((nonnull)) static inline void i915_gem_object_put(struct drm_i915_gem_object *obj) { - drm_gem_object_unreference(&obj->base); + __drm_gem_object_unreference(&obj->base); } __deprecated extern void drm_gem_object_unreference(struct drm_gem_object *); -__attribute__((nonnull)) -static inline void -i915_gem_object_put_unlocked(struct drm_i915_gem_object *obj) -{ - drm_gem_object_unreference_unlocked(&obj->base); -} - __deprecated extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *); @@ -2511,7 +2504,6 @@ static inline struct i915_vma *i915_vma_get(struct i915_vma *vma) static inline void i915_vma_put(struct i915_vma *vma) { - lockdep_assert_held(&vma->vm->dev->struct_mutex); i915_gem_object_put(vma->obj); } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 07b2eb6bc572..fdcbaab21fdd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -617,7 +617,7 @@ i915_gem_create(struct drm_file *file, ret = drm_gem_handle_create(file, &obj->base, &handle); /* drop reference from allocate - handle holds it now */ - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); if (ret) return ret; @@ -1111,7 +1111,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, i915_gem_object_unpin_pages(obj); out: - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return ret; } @@ -1444,7 +1444,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, i915_gem_object_unpin_pages(obj); err: - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return ret; } @@ -1520,7 +1520,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, MAX_SCHEDULE_TIMEOUT, to_rps_client(file)); if (err) - goto out_unlocked; + goto out; /* Flush and acquire obj->pages so that we are coherent through * direct access in memory with previous cached writes through @@ -1532,11 +1532,11 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, */ err = i915_gem_object_pin_pages(obj); if (err) - goto out_unlocked; + goto out; err = i915_mutex_lock_interruptible(dev); if (err) - goto out_pages; + goto out_unpin; if (read_domains & I915_GEM_DOMAIN_GTT) err = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); @@ -1551,10 +1551,10 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, if (write_domain != 0) intel_fb_obj_invalidate(obj, write_origin(obj, write_domain)); -out_pages: +out_unpin: i915_gem_object_unpin_pages(obj); -out_unlocked: - i915_gem_object_put_unlocked(obj); +out: + i915_gem_object_put(obj); return err; } @@ -1585,7 +1585,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, } } - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return err; } @@ -1631,7 +1631,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, * pages from. */ if (!obj->base.filp) { - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return -EINVAL; } @@ -1643,7 +1643,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, struct vm_area_struct *vma; if (down_write_killable(&mm->mmap_sem)) { - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return -EINTR; } vma = find_vma(mm, addr); @@ -1657,7 +1657,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, /* This may race, but that's ok, it only gets set */ WRITE_ONCE(obj->frontbuffer_ggtt_origin, ORIGIN_CPU); } - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); if (IS_ERR((void *)addr)) return addr; @@ -2105,7 +2105,7 @@ i915_gem_mmap_gtt(struct drm_file *file, if (ret == 0) *offset = drm_vma_node_offset_addr(&obj->base.vma_node); - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return ret; } @@ -2932,7 +2932,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) args->timeout_ns = 0; } - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index c63a9cf4da33..6395e62bd9e4 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -201,7 +201,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, if (!i915_tiling_ok(dev, args->stride, obj->base.size, args->tiling_mode)) { - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 6c8c7b36f7fc..c30d04f64670 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -546,7 +546,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) release_pages(pvec, pinned, 0); drm_free_large(pvec); - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); put_task_struct(work->task); kfree(work); } @@ -806,7 +806,7 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file ret = drm_gem_handle_create(file, &obj->base, &handle); /* drop reference from allocate - handle holds it now */ - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e4800b81c59e..87135d93e828 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11051,7 +11051,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, fb = intel_framebuffer_create(dev, &mode_cmd, obj); if (IS_ERR(fb)) - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return fb; } @@ -12360,7 +12360,7 @@ cleanup: crtc->primary->fb = old_fb; update_state_fb(crtc->primary); - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); drm_framebuffer_unreference(work->old_fb); spin_lock_irq(&dev->event_lock); @@ -15934,7 +15934,7 @@ intel_user_framebuffer_create(struct drm_device *dev, fb = intel_framebuffer_create(dev, &mode_cmd, obj); if (IS_ERR(fb)) - i915_gem_object_put_unlocked(obj); + i915_gem_object_put(obj); return fb; } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 25bcd4a178d3..fd0e4dac7cc1 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1222,7 +1222,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, out_unlock: mutex_unlock(&dev->struct_mutex); drm_modeset_unlock_all(dev); - i915_gem_object_put_unlocked(new_bo); + i915_gem_object_put(new_bo); out_free: kfree(params); @@ -1466,7 +1466,7 @@ void intel_cleanup_overlay(struct drm_i915_private *dev_priv) * hardware should be off already */ WARN_ON(dev_priv->overlay->active); - i915_gem_object_put_unlocked(dev_priv->overlay->reg_bo); + i915_gem_object_put(dev_priv->overlay->reg_bo); kfree(dev_priv->overlay); } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6f19e60628ed..b544248cfdee 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5878,7 +5878,7 @@ static void valleyview_cleanup_pctx(struct drm_i915_private *dev_priv) if (WARN_ON(!dev_priv->vlv_pctx)) return; - i915_gem_object_put_unlocked(dev_priv->vlv_pctx); + i915_gem_object_put(dev_priv->vlv_pctx); dev_priv->vlv_pctx = NULL; } -- cgit v1.2.3 From d07f0e59b2c762584478920cd2d11fba2980a94a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:44 +0100 Subject: drm/i915: Move GEM activity tracking into a common struct reservation_object In preparation to support many distinct timelines, we need to expand the activity tracking on the GEM object to handle more than just a request per engine. We already use the struct reservation_object on the dma-buf to handle many fence contexts, so integrating that into the GEM object itself is the preferred solution. (For example, we can now share the same reservation_object between every consumer/producer using this buffer and skip the manual import/export via dma-buf.) v2: Reimplement busy-ioctl (by walking the reservation object), postpone the ABI change for another day. Similarly use the reservation object to find the last_write request (if active and from i915) for choosing display CS flips. Caveats: * busy-ioctl: busy-ioctl only reports on the native fences, it will not warn of stalls (in set-domain-ioctl, pread/pwrite etc) if the object is being rendered to by external fences. It also will not report the same busy state as wait-ioctl (or polling on the dma-buf) in the same circumstances. On the plus side, it does retain reporting of which *i915* engines are engaged with this object. * non-blocking atomic modesets take a step backwards as the wait for render completion blocks the ioctl. This is fixed in a subsequent patch to use a fence instead for awaiting on the rendering, see "drm/i915: Restore nonblocking awaits for modesetting" * dynamic array manipulation for shared-fences in reservation is slower than the previous lockless static assignment (e.g. gem_exec_lut_handle runtime on ivb goes from 42s to 66s), mainly due to atomic operations (maintaining the fence refcounts). * loss of object-level retirement callbacks, emulated by VMA retirement tracking. * minor loss of object-level last activity information from debugfs, could be replaced with per-vma information if desired Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-21-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 15 +- drivers/gpu/drm/i915/i915_drv.h | 62 +++---- drivers/gpu/drm/i915/i915_gem.c | 263 ++++++++--------------------- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 11 +- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 53 +----- drivers/gpu/drm/i915/i915_gem_dmabuf.h | 45 ----- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 55 ++---- drivers/gpu/drm/i915/i915_gem_gtt.c | 32 ++++ drivers/gpu/drm/i915/i915_gem_gtt.h | 1 + drivers/gpu/drm/i915/i915_gem_request.c | 48 +++--- drivers/gpu/drm/i915/i915_gem_request.h | 35 +--- drivers/gpu/drm/i915/i915_gpu_error.c | 6 +- drivers/gpu/drm/i915/intel_atomic_plane.c | 2 - drivers/gpu/drm/i915/intel_display.c | 114 +++---------- drivers/gpu/drm/i915/intel_drv.h | 3 - 15 files changed, 212 insertions(+), 533 deletions(-) delete mode 100644 drivers/gpu/drm/i915/i915_gem_dmabuf.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b0b01002c0d1..b6325065c8e8 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -136,11 +136,10 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) struct i915_vma *vma; unsigned int frontbuffer_bits; int pin_count = 0; - enum intel_engine_id id; lockdep_assert_held(&obj->base.dev->struct_mutex); - seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x [ ", + seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x %s%s%s", &obj->base, get_active_flag(obj), get_pin_flag(obj), @@ -149,14 +148,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) get_pin_mapped_flag(obj), obj->base.size / 1024, obj->base.read_domains, - obj->base.write_domain); - for_each_engine(engine, dev_priv, id) - seq_printf(m, "%x ", - i915_gem_active_get_seqno(&obj->last_read[id], - &obj->base.dev->struct_mutex)); - seq_printf(m, "] %x %s%s%s", - i915_gem_active_get_seqno(&obj->last_write, - &obj->base.dev->struct_mutex), + obj->base.write_domain, i915_cache_level_str(dev_priv, obj->cache_level), obj->mm.dirty ? " dirty" : "", obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : ""); @@ -187,8 +179,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) if (obj->stolen) seq_printf(m, " (stolen: %08llx)", obj->stolen->start); - engine = i915_gem_active_get_engine(&obj->last_write, - &dev_priv->drm.struct_mutex); + engine = i915_gem_object_last_write_engine(obj); if (engine) seq_printf(m, " (%s)", engine->name); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c3c49bc4d2ac..693ee69a4715 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -2246,21 +2247,12 @@ struct drm_i915_gem_object { struct list_head batch_pool_link; unsigned long flags; - /** - * This is set if the object is on the active lists (has pending - * rendering and so a non-zero seqno), and is not set if it i s on - * inactive (ready to be unbound) list. - */ -#define I915_BO_ACTIVE_SHIFT 0 -#define I915_BO_ACTIVE_MASK ((1 << I915_NUM_ENGINES) - 1) -#define __I915_BO_ACTIVE(bo) \ - ((READ_ONCE((bo)->flags) >> I915_BO_ACTIVE_SHIFT) & I915_BO_ACTIVE_MASK) /** * Have we taken a reference for the object for incomplete GPU * activity? */ -#define I915_BO_ACTIVE_REF (I915_BO_ACTIVE_SHIFT + I915_NUM_ENGINES) +#define I915_BO_ACTIVE_REF 0 /* * Is the object to be mapped as read-only to the GPU @@ -2281,6 +2273,7 @@ struct drm_i915_gem_object { /** Count of VMA actually bound by this object */ unsigned int bind_count; + unsigned int active_count; unsigned int pin_display; struct { @@ -2320,8 +2313,7 @@ struct drm_i915_gem_object { * read request. This allows for the CPU to read from an active * buffer by only waiting for the write to complete. */ - struct i915_gem_active last_read[I915_NUM_ENGINES]; - struct i915_gem_active last_write; + struct reservation_object *resv; /** References from framebuffers, locks out tiling changes. */ unsigned long framebuffer_references; @@ -2340,6 +2332,8 @@ struct drm_i915_gem_object { /** for phys allocated objects */ struct drm_dma_handle *phys_handle; + + struct reservation_object __builtin_resv; }; static inline struct drm_i915_gem_object * @@ -2425,35 +2419,10 @@ i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj) return obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE; } -static inline unsigned long -i915_gem_object_get_active(const struct drm_i915_gem_object *obj) -{ - return (obj->flags >> I915_BO_ACTIVE_SHIFT) & I915_BO_ACTIVE_MASK; -} - static inline bool i915_gem_object_is_active(const struct drm_i915_gem_object *obj) { - return i915_gem_object_get_active(obj); -} - -static inline void -i915_gem_object_set_active(struct drm_i915_gem_object *obj, int engine) -{ - obj->flags |= BIT(engine + I915_BO_ACTIVE_SHIFT); -} - -static inline void -i915_gem_object_clear_active(struct drm_i915_gem_object *obj, int engine) -{ - obj->flags &= ~BIT(engine + I915_BO_ACTIVE_SHIFT); -} - -static inline bool -i915_gem_object_has_active_engine(const struct drm_i915_gem_object *obj, - int engine) -{ - return obj->flags & BIT(engine + I915_BO_ACTIVE_SHIFT); + return obj->active_count; } static inline bool @@ -2496,6 +2465,23 @@ i915_gem_object_get_stride(struct drm_i915_gem_object *obj) return obj->tiling_and_stride & STRIDE_MASK; } +static inline struct intel_engine_cs * +i915_gem_object_last_write_engine(struct drm_i915_gem_object *obj) +{ + struct intel_engine_cs *engine = NULL; + struct dma_fence *fence; + + rcu_read_lock(); + fence = reservation_object_get_excl_rcu(obj->resv); + rcu_read_unlock(); + + if (fence && dma_fence_is_i915(fence) && !dma_fence_is_signaled(fence)) + engine = to_request(fence)->engine; + dma_fence_put(fence); + + return engine; +} + static inline struct i915_vma *i915_vma_get(struct i915_vma *vma) { i915_gem_object_get(vma->obj); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fdcbaab21fdd..1161a21ec810 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -29,7 +29,6 @@ #include #include #include "i915_drv.h" -#include "i915_gem_dmabuf.h" #include "i915_vgpu.h" #include "i915_trace.h" #include "intel_drv.h" @@ -447,11 +446,6 @@ i915_gem_object_wait(struct drm_i915_gem_object *obj, long timeout, struct intel_rps_client *rps) { - struct reservation_object *resv; - struct i915_gem_active *active; - unsigned long active_mask; - int idx; - might_sleep(); #if IS_ENABLED(CONFIG_LOCKDEP) GEM_BUG_ON(debug_locks && @@ -460,33 +454,9 @@ i915_gem_object_wait(struct drm_i915_gem_object *obj, #endif GEM_BUG_ON(timeout < 0); - if (flags & I915_WAIT_ALL) { - active = obj->last_read; - active_mask = i915_gem_object_get_active(obj); - } else { - active_mask = 1; - active = &obj->last_write; - } - - for_each_active(active_mask, idx) { - struct drm_i915_gem_request *request; - - request = i915_gem_active_get_unlocked(&active[idx]); - if (request) { - timeout = i915_gem_object_wait_fence(&request->fence, - flags, timeout, - rps); - i915_gem_request_put(request); - } - if (timeout < 0) - return timeout; - } - - resv = i915_gem_object_get_dmabuf_resv(obj); - if (resv) - timeout = i915_gem_object_wait_reservation(resv, - flags, timeout, - rps); + timeout = i915_gem_object_wait_reservation(obj->resv, + flags, timeout, + rps); return timeout < 0 ? timeout : 0; } @@ -2549,44 +2519,6 @@ err_unlock: goto out_unlock; } -static void -i915_gem_object_retire__write(struct i915_gem_active *active, - struct drm_i915_gem_request *request) -{ - struct drm_i915_gem_object *obj = - container_of(active, struct drm_i915_gem_object, last_write); - - intel_fb_obj_flush(obj, true, ORIGIN_CS); -} - -static void -i915_gem_object_retire__read(struct i915_gem_active *active, - struct drm_i915_gem_request *request) -{ - int idx = request->engine->id; - struct drm_i915_gem_object *obj = - container_of(active, struct drm_i915_gem_object, last_read[idx]); - - GEM_BUG_ON(!i915_gem_object_has_active_engine(obj, idx)); - - i915_gem_object_clear_active(obj, idx); - if (i915_gem_object_is_active(obj)) - return; - - /* Bump our place on the bound list to keep it roughly in LRU order - * so that we don't steal from recently used but inactive objects - * (unless we are forced to ofc!) - */ - if (obj->bind_count) - list_move_tail(&obj->global_list, - &request->i915->mm.bound_list); - - if (i915_gem_object_has_active_reference(obj)) { - i915_gem_object_clear_active_reference(obj); - i915_gem_object_put(obj); - } -} - static bool i915_context_is_banned(const struct i915_gem_context *ctx) { unsigned long elapsed; @@ -2966,6 +2898,13 @@ int i915_vma_unbind(struct i915_vma *vma) * In order to prevent it from being recursively closed, * take a pin on the vma so that the second unbind is * aborted. + * + * Even more scary is that the retire callback may free + * the object (last active vma). To prevent the explosion + * we defer the actual object free to a worker that can + * only proceed once it acquires the struct_mutex (which + * we currently hold, therefore it cannot free this object + * before we are finished). */ __i915_vma_pin(vma); @@ -4010,83 +3949,42 @@ static __always_inline unsigned int __busy_write_id(unsigned int id) } static __always_inline unsigned int -__busy_set_if_active(const struct i915_gem_active *active, +__busy_set_if_active(const struct dma_fence *fence, unsigned int (*flag)(unsigned int id)) { - struct drm_i915_gem_request *request; - - request = rcu_dereference(active->request); - if (!request || i915_gem_request_completed(request)) - return 0; + struct drm_i915_gem_request *rq; - /* This is racy. See __i915_gem_active_get_rcu() for an in detail - * discussion of how to handle the race correctly, but for reporting - * the busy state we err on the side of potentially reporting the - * wrong engine as being busy (but we guarantee that the result - * is at least self-consistent). - * - * As we use SLAB_DESTROY_BY_RCU, the request may be reallocated - * whilst we are inspecting it, even under the RCU read lock as we are. - * This means that there is a small window for the engine and/or the - * seqno to have been overwritten. The seqno will always be in the - * future compared to the intended, and so we know that if that - * seqno is idle (on whatever engine) our request is idle and the - * return 0 above is correct. + /* We have to check the current hw status of the fence as the uABI + * guarantees forward progress. We could rely on the idle worker + * to eventually flush us, but to minimise latency just ask the + * hardware. * - * The issue is that if the engine is switched, it is just as likely - * to report that it is busy (but since the switch happened, we know - * the request should be idle). So there is a small chance that a busy - * result is actually the wrong engine. - * - * So why don't we care? - * - * For starters, the busy ioctl is a heuristic that is by definition - * racy. Even with perfect serialisation in the driver, the hardware - * state is constantly advancing - the state we report to the user - * is stale. - * - * The critical information for the busy-ioctl is whether the object - * is idle as userspace relies on that to detect whether its next - * access will stall, or if it has missed submitting commands to - * the hardware allowing the GPU to stall. We never generate a - * false-positive for idleness, thus busy-ioctl is reliable at the - * most fundamental level, and we maintain the guarantee that a - * busy object left to itself will eventually become idle (and stay - * idle!). - * - * We allow ourselves the leeway of potentially misreporting the busy - * state because that is an optimisation heuristic that is constantly - * in flux. Being quickly able to detect the busy/idle state is much - * more important than accurate logging of exactly which engines were - * busy. - * - * For accuracy in reporting the engine, we could use - * - * result = 0; - * request = __i915_gem_active_get_rcu(active); - * if (request) { - * if (!i915_gem_request_completed(request)) - * result = flag(request->engine->exec_id); - * i915_gem_request_put(request); - * } - * - * but that still remains susceptible to both hardware and userspace - * races. So we accept making the result of that race slightly worse, - * given the rarity of the race and its low impact on the result. + * Note we only report on the status of native fences. */ - return flag(READ_ONCE(request->engine->exec_id)); + if (!dma_fence_is_i915(fence)) + return 0; + + /* opencode to_request() in order to avoid const warnings */ + rq = container_of(fence, struct drm_i915_gem_request, fence); + if (i915_gem_request_completed(rq)) + return 0; + + return flag(rq->engine->exec_id); } static __always_inline unsigned int -busy_check_reader(const struct i915_gem_active *active) +busy_check_reader(const struct dma_fence *fence) { - return __busy_set_if_active(active, __busy_read_flag); + return __busy_set_if_active(fence, __busy_read_flag); } static __always_inline unsigned int -busy_check_writer(const struct i915_gem_active *active) +busy_check_writer(const struct dma_fence *fence) { - return __busy_set_if_active(active, __busy_write_id); + if (!fence) + return 0; + + return __busy_set_if_active(fence, __busy_write_id); } int @@ -4095,63 +3993,55 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_busy *args = data; struct drm_i915_gem_object *obj; - unsigned long active; + struct reservation_object_list *list; + unsigned int seq; int err; + err = -ENOENT; rcu_read_lock(); obj = i915_gem_object_lookup_rcu(file, args->handle); - if (!obj) { - err = -ENOENT; + if (!obj) goto out; - } - args->busy = 0; - active = __I915_BO_ACTIVE(obj); - if (active) { - int idx; + /* A discrepancy here is that we do not report the status of + * non-i915 fences, i.e. even though we may report the object as idle, + * a call to set-domain may still stall waiting for foreign rendering. + * This also means that wait-ioctl may report an object as busy, + * where busy-ioctl considers it idle. + * + * We trade the ability to warn of foreign fences to report on which + * i915 engines are active for the object. + * + * Alternatively, we can trade that extra information on read/write + * activity with + * args->busy = + * !reservation_object_test_signaled_rcu(obj->resv, true); + * to report the overall busyness. This is what the wait-ioctl does. + * + */ +retry: + seq = raw_read_seqcount(&obj->resv->seq); - /* Yes, the lookups are intentionally racy. - * - * First, we cannot simply rely on __I915_BO_ACTIVE. We have - * to regard the value as stale and as our ABI guarantees - * forward progress, we confirm the status of each active - * request with the hardware. - * - * Even though we guard the pointer lookup by RCU, that only - * guarantees that the pointer and its contents remain - * dereferencable and does *not* mean that the request we - * have is the same as the one being tracked by the object. - * - * Consider that we lookup the request just as it is being - * retired and freed. We take a local copy of the pointer, - * but before we add its engine into the busy set, the other - * thread reallocates it and assigns it to a task on another - * engine with a fresh and incomplete seqno. Guarding against - * that requires careful serialisation and reference counting, - * i.e. using __i915_gem_active_get_request_rcu(). We don't, - * instead we expect that if the result is busy, which engines - * are busy is not completely reliable - we only guarantee - * that the object was busy. - */ + /* Translate the exclusive fence to the READ *and* WRITE engine */ + args->busy = busy_check_writer(rcu_dereference(obj->resv->fence_excl)); - for_each_active(active, idx) - args->busy |= busy_check_reader(&obj->last_read[idx]); + /* Translate shared fences to READ set of engines */ + list = rcu_dereference(obj->resv->fence); + if (list) { + unsigned int shared_count = list->shared_count, i; - /* For ABI sanity, we only care that the write engine is in - * the set of read engines. This should be ensured by the - * ordering of setting last_read/last_write in - * i915_vma_move_to_active(), and then in reverse in retire. - * However, for good measure, we always report the last_write - * request as a busy read as well as being a busy write. - * - * We don't care that the set of active read/write engines - * may change during construction of the result, as it is - * equally liable to change before userspace can inspect - * the result. - */ - args->busy |= busy_check_writer(&obj->last_write); + for (i = 0; i < shared_count; ++i) { + struct dma_fence *fence = + rcu_dereference(list->shared[i]); + + args->busy |= busy_check_reader(fence); + } } + if (args->busy && read_seqcount_retry(&obj->resv->seq, seq)) + goto retry; + + err = 0; out: rcu_read_unlock(); return err; @@ -4216,23 +4106,19 @@ out: void i915_gem_object_init(struct drm_i915_gem_object *obj, const struct drm_i915_gem_object_ops *ops) { - int i; - mutex_init(&obj->mm.lock); INIT_LIST_HEAD(&obj->global_list); INIT_LIST_HEAD(&obj->userfault_link); - for (i = 0; i < I915_NUM_ENGINES; i++) - init_request_active(&obj->last_read[i], - i915_gem_object_retire__read); - init_request_active(&obj->last_write, - i915_gem_object_retire__write); INIT_LIST_HEAD(&obj->obj_exec_link); INIT_LIST_HEAD(&obj->vma_list); INIT_LIST_HEAD(&obj->batch_pool_link); obj->ops = ops; + reservation_object_init(&obj->__builtin_resv); + obj->resv = &obj->__builtin_resv; + obj->frontbuffer_ggtt_origin = ORIGIN_GTT; obj->mm.madv = I915_MADV_WILLNEED; @@ -4385,6 +4271,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, if (obj->base.import_attach) drm_prime_gem_destroy(&obj->base, NULL); + reservation_object_fini(&obj->__builtin_resv); drm_gem_object_release(&obj->base); i915_gem_info_remove_obj(i915, obj->base.size); diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index e0f38e5c0fbb..b3bc119ec1bb 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -114,11 +114,18 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, list_for_each_entry(tmp, list, batch_pool_link) { /* The batches are strictly LRU ordered */ - if (!i915_gem_active_is_idle(&tmp->last_read[pool->engine->id], - &tmp->base.dev->struct_mutex)) + if (i915_gem_object_is_active(tmp)) break; + GEM_BUG_ON(!reservation_object_test_signaled_rcu(tmp->resv, + true)); + if (tmp->base.size >= size) { + /* Clear the set of shared fences early */ + ww_mutex_lock(&tmp->resv->lock, NULL); + reservation_object_add_excl_fence(tmp->resv, NULL); + ww_mutex_unlock(&tmp->resv->lock); + obj = tmp; break; } diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 4d45f20d11ed..5e38299b5df6 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -211,60 +211,17 @@ static const struct dma_buf_ops i915_dmabuf_ops = { .end_cpu_access = i915_gem_end_cpu_access, }; -static void export_fences(struct drm_i915_gem_object *obj, - struct dma_buf *dma_buf) -{ - struct reservation_object *resv = dma_buf->resv; - struct drm_i915_gem_request *req; - unsigned long active; - int idx; - - active = __I915_BO_ACTIVE(obj); - if (!active) - return; - - /* Serialise with execbuf to prevent concurrent fence-loops */ - mutex_lock(&obj->base.dev->struct_mutex); - - /* Mark the object for future fences before racily adding old fences */ - obj->base.dma_buf = dma_buf; - - ww_mutex_lock(&resv->lock, NULL); - - for_each_active(active, idx) { - req = i915_gem_active_get(&obj->last_read[idx], - &obj->base.dev->struct_mutex); - if (!req) - continue; - - if (reservation_object_reserve_shared(resv) == 0) - reservation_object_add_shared_fence(resv, &req->fence); - - i915_gem_request_put(req); - } - - req = i915_gem_active_get(&obj->last_write, - &obj->base.dev->struct_mutex); - if (req) { - reservation_object_add_excl_fence(resv, &req->fence); - i915_gem_request_put(req); - } - - ww_mutex_unlock(&resv->lock); - mutex_unlock(&obj->base.dev->struct_mutex); -} - struct dma_buf *i915_gem_prime_export(struct drm_device *dev, struct drm_gem_object *gem_obj, int flags) { struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); DEFINE_DMA_BUF_EXPORT_INFO(exp_info); - struct dma_buf *dma_buf; exp_info.ops = &i915_dmabuf_ops; exp_info.size = gem_obj->size; exp_info.flags = flags; exp_info.priv = gem_obj; + exp_info.resv = obj->resv; if (obj->ops->dmabuf_export) { int ret = obj->ops->dmabuf_export(obj); @@ -272,12 +229,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, return ERR_PTR(ret); } - dma_buf = drm_gem_dmabuf_export(dev, &exp_info); - if (IS_ERR(dma_buf)) - return dma_buf; - - export_fences(obj, dma_buf); - return dma_buf; + return drm_gem_dmabuf_export(dev, &exp_info); } static struct sg_table * @@ -335,6 +287,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, drm_gem_private_object_init(dev, &obj->base, dma_buf->size); i915_gem_object_init(obj, &i915_gem_object_dmabuf_ops); obj->base.import_attach = attach; + obj->resv = dma_buf->resv; /* We use GTT as shorthand for a coherent domain, one that is * neither in the GPU cache nor in the CPU cache, where all diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.h b/drivers/gpu/drm/i915/i915_gem_dmabuf.h deleted file mode 100644 index 91315557e421..000000000000 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2016 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _I915_GEM_DMABUF_H_ -#define _I915_GEM_DMABUF_H_ - -#include - -static inline struct reservation_object * -i915_gem_object_get_dmabuf_resv(struct drm_i915_gem_object *obj) -{ - struct dma_buf *dma_buf; - - if (obj->base.dma_buf) - dma_buf = obj->base.dma_buf; - else if (obj->base.import_attach) - dma_buf = obj->base.import_attach->dmabuf; - else - return NULL; - - return dma_buf->resv; -} - -#endif diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d95c4e02eeb9..c35e847bb8bc 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -34,7 +34,6 @@ #include #include "i915_drv.h" -#include "i915_gem_dmabuf.h" #include "i915_trace.h" #include "intel_drv.h" #include "intel_frontbuffer.h" @@ -1101,45 +1100,20 @@ err: return ret; } -static unsigned int eb_other_engines(struct drm_i915_gem_request *req) -{ - unsigned int mask; - - mask = ~intel_engine_flag(req->engine) & I915_BO_ACTIVE_MASK; - mask <<= I915_BO_ACTIVE_SHIFT; - - return mask; -} - static int i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, struct list_head *vmas) { - const unsigned int other_rings = eb_other_engines(req); struct i915_vma *vma; int ret; list_for_each_entry(vma, vmas, exec_list) { struct drm_i915_gem_object *obj = vma->obj; - struct reservation_object *resv; - if (obj->flags & other_rings) { - ret = i915_gem_request_await_object - (req, obj, obj->base.pending_write_domain); - if (ret) - return ret; - } - - resv = i915_gem_object_get_dmabuf_resv(obj); - if (resv) { - ret = i915_sw_fence_await_reservation - (&req->submit, resv, &i915_fence_ops, - obj->base.pending_write_domain, - I915_FENCE_TIMEOUT, - GFP_KERNEL | __GFP_NOWARN); - if (ret < 0) - return ret; - } + ret = i915_gem_request_await_object + (req, obj, obj->base.pending_write_domain); + if (ret) + return ret; if (obj->base.write_domain & I915_GEM_DOMAIN_CPU) i915_gem_clflush_object(obj, false); @@ -1281,8 +1255,6 @@ void i915_vma_move_to_active(struct i915_vma *vma, GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); - obj->mm.dirty = true; /* be paranoid */ - /* Add a reference if we're newly entering the active list. * The order in which we add operations to the retirement queue is * vital here: mark_active adds to the start of the callback list, @@ -1290,11 +1262,14 @@ void i915_vma_move_to_active(struct i915_vma *vma, * add the active reference first and queue for it to be dropped * *last*. */ - i915_gem_object_set_active(obj, idx); - i915_gem_active_set(&obj->last_read[idx], req); + if (!i915_vma_is_active(vma)) + obj->active_count++; + i915_vma_set_active(vma, idx); + i915_gem_active_set(&vma->last_read[idx], req); + list_move_tail(&vma->vm_link, &vma->vm->active_list); if (flags & EXEC_OBJECT_WRITE) { - i915_gem_active_set(&obj->last_write, req); + i915_gem_active_set(&vma->last_write, req); intel_fb_obj_invalidate(obj, ORIGIN_CS); @@ -1304,21 +1279,13 @@ void i915_vma_move_to_active(struct i915_vma *vma, if (flags & EXEC_OBJECT_NEEDS_FENCE) i915_gem_active_set(&vma->last_fence, req); - - i915_vma_set_active(vma, idx); - i915_gem_active_set(&vma->last_read[idx], req); - list_move_tail(&vma->vm_link, &vma->vm->active_list); } static void eb_export_fence(struct drm_i915_gem_object *obj, struct drm_i915_gem_request *req, unsigned int flags) { - struct reservation_object *resv; - - resv = i915_gem_object_get_dmabuf_resv(obj); - if (!resv) - return; + struct reservation_object *resv = obj->resv; /* Ignore errors from failing to allocate the new fence, we can't * handle an error right now. Worst case should be missed diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1008209ca797..1b1a459e2b68 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -31,6 +31,7 @@ #include "i915_vgpu.h" #include "i915_trace.h" #include "intel_drv.h" +#include "intel_frontbuffer.h" #define I915_GFP_DMA (GFP_KERNEL | __GFP_HIGHMEM) @@ -3343,6 +3344,7 @@ i915_vma_retire(struct i915_gem_active *active, const unsigned int idx = rq->engine->id; struct i915_vma *vma = container_of(active, struct i915_vma, last_read[idx]); + struct drm_i915_gem_object *obj = vma->obj; GEM_BUG_ON(!i915_vma_has_active_engine(vma, idx)); @@ -3353,6 +3355,34 @@ i915_vma_retire(struct i915_gem_active *active, list_move_tail(&vma->vm_link, &vma->vm->inactive_list); if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma))) WARN_ON(i915_vma_unbind(vma)); + + GEM_BUG_ON(!i915_gem_object_is_active(obj)); + if (--obj->active_count) + return; + + /* Bump our place on the bound list to keep it roughly in LRU order + * so that we don't steal from recently used but inactive objects + * (unless we are forced to ofc!) + */ + if (obj->bind_count) + list_move_tail(&obj->global_list, &rq->i915->mm.bound_list); + + obj->mm.dirty = true; /* be paranoid */ + + if (i915_gem_object_has_active_reference(obj)) { + i915_gem_object_clear_active_reference(obj); + i915_gem_object_put(obj); + } +} + +static void +i915_ggtt_retire__write(struct i915_gem_active *active, + struct drm_i915_gem_request *request) +{ + struct i915_vma *vma = + container_of(active, struct i915_vma, last_write); + + intel_fb_obj_flush(vma->obj, true, ORIGIN_CS); } void i915_vma_destroy(struct i915_vma *vma) @@ -3396,6 +3426,8 @@ __i915_vma_create(struct drm_i915_gem_object *obj, INIT_LIST_HEAD(&vma->exec_list); for (i = 0; i < ARRAY_SIZE(vma->last_read); i++) init_request_active(&vma->last_read[i], i915_vma_retire); + init_request_active(&vma->last_write, + i915_is_ggtt(vm) ? i915_ggtt_retire__write : NULL); init_request_active(&vma->last_fence, NULL); list_add(&vma->vm_link, &vm->unbound_list); vma->vm = vm; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index dbe6a6cec20d..9f0327e5176a 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -211,6 +211,7 @@ struct i915_vma { unsigned int active; struct i915_gem_active last_read[I915_NUM_ENGINES]; + struct i915_gem_active last_write; struct i915_gem_active last_fence; /** diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index d234c28cbb9f..01a7fa513b4a 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -196,6 +196,8 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) } i915_gem_context_put(request->ctx); + + dma_fence_signal(&request->fence); i915_gem_request_put(request); } @@ -553,33 +555,41 @@ i915_gem_request_await_object(struct drm_i915_gem_request *to, struct drm_i915_gem_object *obj, bool write) { - struct i915_gem_active *active; - unsigned long active_mask; - int idx; + struct dma_fence *excl; + int ret = 0; if (write) { - active_mask = i915_gem_object_get_active(obj); - active = obj->last_read; + struct dma_fence **shared; + unsigned int count, i; + + ret = reservation_object_get_fences_rcu(obj->resv, + &excl, &count, &shared); + if (ret) + return ret; + + for (i = 0; i < count; i++) { + ret = i915_gem_request_await_dma_fence(to, shared[i]); + if (ret) + break; + + dma_fence_put(shared[i]); + } + + for (; i < count; i++) + dma_fence_put(shared[i]); + kfree(shared); } else { - active_mask = 1; - active = &obj->last_write; + excl = reservation_object_get_excl_rcu(obj->resv); } - for_each_active(active_mask, idx) { - struct drm_i915_gem_request *request; - int ret; - - request = i915_gem_active_peek(&active[idx], - &obj->base.dev->struct_mutex); - if (!request) - continue; + if (excl) { + if (ret == 0) + ret = i915_gem_request_await_dma_fence(to, excl); - ret = i915_gem_request_await_request(to, request); - if (ret) - return ret; + dma_fence_put(excl); } - return 0; + return ret; } static void i915_gem_mark_busy(const struct intel_engine_cs *engine) diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 602234f91583..a51d596a60ac 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -554,22 +554,7 @@ i915_gem_active_isset(const struct i915_gem_active *active) } /** - * i915_gem_active_is_idle - report whether the active tracker is idle - * @active - the active tracker - * - * i915_gem_active_is_idle() returns true if the active tracker is currently - * unassigned or if the request is complete (but not yet retired). Requires - * the caller to hold struct_mutex (but that can be relaxed if desired). - */ -static inline bool -i915_gem_active_is_idle(const struct i915_gem_active *active, - struct mutex *mutex) -{ - return !i915_gem_active_peek(active, mutex); -} - -/** - * i915_gem_active_wait- waits until the request is completed + * i915_gem_active_wait - waits until the request is completed * @active - the active request on which to wait * @flags - how to wait * @timeout - how long to wait at most @@ -639,24 +624,6 @@ i915_gem_active_retire(struct i915_gem_active *active, return 0; } -/* Convenience functions for peeking at state inside active's request whilst - * guarded by the struct_mutex. - */ - -static inline uint32_t -i915_gem_active_get_seqno(const struct i915_gem_active *active, - struct mutex *mutex) -{ - return i915_gem_request_get_seqno(i915_gem_active_peek(active, mutex)); -} - -static inline struct intel_engine_cs * -i915_gem_active_get_engine(const struct i915_gem_active *active, - struct mutex *mutex) -{ - return i915_gem_request_get_engine(i915_gem_active_peek(active, mutex)); -} - #define for_each_active(mask, idx) \ for (; mask ? idx = ffs(mask) - 1, 1 : 0; mask &= ~BIT(idx)) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 5bbb37209aa5..aa8dadcc669f 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -887,9 +887,9 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->name = obj->base.name; for (i = 0; i < I915_NUM_ENGINES; i++) - err->rseqno[i] = __active_get_seqno(&obj->last_read[i]); - err->wseqno = __active_get_seqno(&obj->last_write); - err->engine = __active_get_engine_id(&obj->last_write); + err->rseqno[i] = __active_get_seqno(&vma->last_read[i]); + err->wseqno = __active_get_seqno(&vma->last_write); + err->engine = __active_get_engine_id(&vma->last_write); err->gtt_offset = vma->node.start; err->read_domains = obj->base.read_domains; diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index c762ae549a1c..cb5594411bb6 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -84,7 +84,6 @@ intel_plane_duplicate_state(struct drm_plane *plane) state = &intel_state->base; __drm_atomic_helper_plane_duplicate_state(plane, state); - intel_state->wait_req = NULL; return state; } @@ -101,7 +100,6 @@ void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { - WARN_ON(state && to_intel_plane_state(state)->wait_req); drm_atomic_helper_plane_destroy_state(plane, state); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 87135d93e828..622f733b9347 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -37,7 +37,6 @@ #include "intel_frontbuffer.h" #include #include "i915_drv.h" -#include "i915_gem_dmabuf.h" #include "intel_dsi.h" #include "i915_trace.h" #include @@ -11967,8 +11966,6 @@ static int intel_gen7_queue_flip(struct drm_device *dev, static bool use_mmio_flip(struct intel_engine_cs *engine, struct drm_i915_gem_object *obj) { - struct reservation_object *resv; - /* * This is not being used for older platforms, because * non-availability of flip done interrupt forces us to use @@ -11990,12 +11987,7 @@ static bool use_mmio_flip(struct intel_engine_cs *engine, else if (i915.enable_execlists) return true; - resv = i915_gem_object_get_dmabuf_resv(obj); - if (resv && !reservation_object_test_signaled_rcu(resv, false)) - return true; - - return engine != i915_gem_active_get_engine(&obj->last_write, - &obj->base.dev->struct_mutex); + return engine != i915_gem_object_last_write_engine(obj); } static void skl_do_mmio_flip(struct intel_crtc *intel_crtc, @@ -12068,17 +12060,8 @@ static void intel_mmio_flip_work_func(struct work_struct *w) struct intel_framebuffer *intel_fb = to_intel_framebuffer(crtc->base.primary->fb); struct drm_i915_gem_object *obj = intel_fb->obj; - struct reservation_object *resv; - if (work->flip_queued_req) - WARN_ON(i915_wait_request(work->flip_queued_req, - 0, MAX_SCHEDULE_TIMEOUT) < 0); - - /* For framebuffer backed by dmabuf, wait for fence */ - resv = i915_gem_object_get_dmabuf_resv(obj); - if (resv) - WARN_ON(reservation_object_wait_timeout_rcu(resv, false, false, - MAX_SCHEDULE_TIMEOUT) < 0); + WARN_ON(i915_gem_object_wait(obj, 0, MAX_SCHEDULE_TIMEOUT, NULL) < 0); intel_pipe_update_start(crtc); @@ -12279,8 +12262,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, } else if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) { engine = dev_priv->engine[BCS]; } else if (INTEL_INFO(dev)->gen >= 7) { - engine = i915_gem_active_get_engine(&obj->last_write, - &obj->base.dev->struct_mutex); + engine = i915_gem_object_last_write_engine(obj); if (engine == NULL || engine->id != RCS) engine = dev_priv->engine[BCS]; } else { @@ -12312,9 +12294,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (mmio_flip) { INIT_WORK(&work->mmio_work, intel_mmio_flip_work_func); - - work->flip_queued_req = i915_gem_active_get(&obj->last_write, - &obj->base.dev->struct_mutex); queue_work(system_unbound_wq, &work->mmio_work); } else { request = i915_gem_request_alloc(engine, engine->last_context); @@ -14154,13 +14133,10 @@ static int intel_atomic_check(struct drm_device *dev, } static int intel_atomic_prepare_commit(struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) + struct drm_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_plane_state *plane_state; struct drm_crtc_state *crtc_state; - struct drm_plane *plane; struct drm_crtc *crtc; int i, ret; @@ -14183,30 +14159,6 @@ static int intel_atomic_prepare_commit(struct drm_device *dev, ret = drm_atomic_helper_prepare_planes(dev, state); mutex_unlock(&dev->struct_mutex); - if (!ret && !nonblock) { - for_each_plane_in_state(state, plane, plane_state, i) { - struct intel_plane_state *intel_plane_state = - to_intel_plane_state(plane_state); - long timeout; - - if (!intel_plane_state->wait_req) - continue; - - timeout = i915_wait_request(intel_plane_state->wait_req, - I915_WAIT_INTERRUPTIBLE, - MAX_SCHEDULE_TIMEOUT); - if (timeout < 0) { - /* Any hang should be swallowed by the wait */ - WARN_ON(timeout == -EIO); - mutex_lock(&dev->struct_mutex); - drm_atomic_helper_cleanup_planes(dev, state); - mutex_unlock(&dev->struct_mutex); - ret = timeout; - break; - } - } - } - return ret; } @@ -14400,26 +14352,11 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) struct drm_crtc_state *old_crtc_state; struct drm_crtc *crtc; struct intel_crtc_state *intel_cstate; - struct drm_plane *plane; - struct drm_plane_state *plane_state; bool hw_check = intel_state->modeset; unsigned long put_domains[I915_MAX_PIPES] = {}; unsigned crtc_vblank_mask = 0; int i; - for_each_plane_in_state(state, plane, plane_state, i) { - struct intel_plane_state *intel_plane_state = - to_intel_plane_state(plane->state); - - if (!intel_plane_state->wait_req) - continue; - - /* EIO should be eaten, and we can't get interrupted in the - * worker, and blocking commits have waited already. */ - WARN_ON(i915_wait_request(intel_plane_state->wait_req, - 0, MAX_SCHEDULE_TIMEOUT) < 0); - } - drm_atomic_helper_wait_for_dependencies(state); if (intel_state->modeset) { @@ -14626,7 +14563,7 @@ static int intel_atomic_commit(struct drm_device *dev, INIT_WORK(&state->commit_work, intel_atomic_commit_work); - ret = intel_atomic_prepare_commit(dev, state, nonblock); + ret = intel_atomic_prepare_commit(dev, state); if (ret) { DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret); return ret; @@ -14759,7 +14696,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, struct drm_framebuffer *fb = new_state->fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb); - struct reservation_object *resv; + long lret; int ret = 0; if (!obj && !old_obj) @@ -14797,39 +14734,34 @@ intel_prepare_plane_fb(struct drm_plane *plane, return 0; /* For framebuffer backed by dmabuf, wait for fence */ - resv = i915_gem_object_get_dmabuf_resv(obj); - if (resv) { - long lret; + lret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT, + NULL); + if (lret == -ERESTARTSYS) + return lret; - lret = reservation_object_wait_timeout_rcu(resv, false, true, - MAX_SCHEDULE_TIMEOUT); - if (lret == -ERESTARTSYS) - return lret; - - WARN(lret < 0, "waiting returns %li\n", lret); - } + WARN(lret < 0, "waiting returns %li\n", lret); if (plane->type == DRM_PLANE_TYPE_CURSOR && INTEL_INFO(dev)->cursor_needs_physical) { int align = IS_I830(dev_priv) ? 16 * 1024 : 256; ret = i915_gem_object_attach_phys(obj, align); - if (ret) + if (ret) { DRM_DEBUG_KMS("failed to attach phys object\n"); + return ret; + } } else { struct i915_vma *vma; vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation); - if (IS_ERR(vma)) - ret = PTR_ERR(vma); - } - - if (ret == 0) { - to_intel_plane_state(new_state)->wait_req = - i915_gem_active_get(&obj->last_write, - &obj->base.dev->struct_mutex); + if (IS_ERR(vma)) { + DRM_DEBUG_KMS("failed to pin object\n"); + return PTR_ERR(vma); + } } - return ret; + return 0; } /** @@ -14847,7 +14779,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane, { struct drm_device *dev = plane->dev; struct intel_plane_state *old_intel_state; - struct intel_plane_state *intel_state = to_intel_plane_state(plane->state); struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb); struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb); @@ -14859,9 +14790,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane, if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR || !INTEL_INFO(dev)->cursor_needs_physical)) intel_unpin_fb_obj(old_state->fb, old_state->rotation); - - i915_gem_request_assign(&intel_state->wait_req, NULL); - i915_gem_request_assign(&old_intel_state->wait_req, NULL); } int diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ace222c74f71..ec7fa592b20a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -401,9 +401,6 @@ struct intel_plane_state { int scaler_id; struct drm_intel_sprite_colorkey ckey; - - /* async flip related structures */ - struct drm_i915_gem_request *wait_req; }; struct intel_initial_plane_config { -- cgit v1.2.3 From c004a90b7263e3d5811f6ec7de0abb143f3099b3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:45 +0100 Subject: drm/i915: Restore nonblocking awaits for modesetting After combining the dma-buf reservation object and the GEM reservation object, we lost the ability to do a nonblocking wait on the i915 request (as we blocked upon the reservation object during prepare_fb). We can instead convert the reservation object into a fence upon which we can asynchronously wait (including a forced timeout in case the DMA fence is never signaled). Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-22-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_display.c | 93 +++++++++++++++++++++++++----------- drivers/gpu/drm/i915/intel_drv.h | 2 + 2 files changed, 66 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 622f733b9347..304073a03c4c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14510,12 +14510,33 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) static void intel_atomic_commit_work(struct work_struct *work) { - struct drm_atomic_state *state = container_of(work, - struct drm_atomic_state, - commit_work); + struct drm_atomic_state *state = + container_of(work, struct drm_atomic_state, commit_work); + intel_atomic_commit_tail(state); } +static int __i915_sw_fence_call +intel_atomic_commit_ready(struct i915_sw_fence *fence, + enum i915_sw_fence_notify notify) +{ + struct intel_atomic_state *state = + container_of(fence, struct intel_atomic_state, commit_ready); + + switch (notify) { + case FENCE_COMPLETE: + if (state->base.commit_work.func) + queue_work(system_unbound_wq, &state->base.commit_work); + break; + + case FENCE_FREE: + drm_atomic_state_put(&state->base); + break; + } + + return NOTIFY_DONE; +} + static void intel_atomic_track_fbs(struct drm_atomic_state *state) { struct drm_plane_state *old_plane_state; @@ -14561,11 +14582,14 @@ static int intel_atomic_commit(struct drm_device *dev, if (ret) return ret; - INIT_WORK(&state->commit_work, intel_atomic_commit_work); + drm_atomic_state_get(state); + i915_sw_fence_init(&intel_state->commit_ready, + intel_atomic_commit_ready); ret = intel_atomic_prepare_commit(dev, state); if (ret) { DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret); + i915_sw_fence_commit(&intel_state->commit_ready); return ret; } @@ -14576,10 +14600,14 @@ static int intel_atomic_commit(struct drm_device *dev, intel_atomic_track_fbs(state); drm_atomic_state_get(state); - if (nonblock) - queue_work(system_unbound_wq, &state->commit_work); - else + INIT_WORK(&state->commit_work, + nonblock ? intel_atomic_commit_work : NULL); + + i915_sw_fence_commit(&intel_state->commit_ready); + if (!nonblock) { + i915_sw_fence_wait(&intel_state->commit_ready); intel_atomic_commit_tail(state); + } return 0; } @@ -14691,20 +14719,22 @@ int intel_prepare_plane_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { + struct intel_atomic_state *intel_state = + to_intel_atomic_state(new_state->state); struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_framebuffer *fb = new_state->fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb); - long lret; - int ret = 0; + int ret; if (!obj && !old_obj) return 0; if (old_obj) { struct drm_crtc_state *crtc_state = - drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc); + drm_atomic_get_existing_crtc_state(new_state->state, + plane->state->crtc); /* Big Hammer, we also need to ensure that any pending * MI_WAIT_FOR_EVENT inside a user batch buffer on the @@ -14717,31 +14747,36 @@ intel_prepare_plane_fb(struct drm_plane *plane, * This should only fail upon a hung GPU, in which case we * can safely continue. */ - if (needs_modeset(crtc_state)) - ret = i915_gem_object_wait(old_obj, - I915_WAIT_INTERRUPTIBLE | - I915_WAIT_LOCKED, - MAX_SCHEDULE_TIMEOUT, - NULL); - if (ret) { - /* GPU hangs should have been swallowed by the wait */ - WARN_ON(ret == -EIO); - return ret; + if (needs_modeset(crtc_state)) { + ret = i915_sw_fence_await_reservation(&intel_state->commit_ready, + old_obj->resv, NULL, + false, 0, + GFP_KERNEL); + if (ret < 0) + return ret; } } + if (new_state->fence) { /* explicit fencing */ + ret = i915_sw_fence_await_dma_fence(&intel_state->commit_ready, + new_state->fence, + I915_FENCE_TIMEOUT, + GFP_KERNEL); + if (ret < 0) + return ret; + } + if (!obj) return 0; - /* For framebuffer backed by dmabuf, wait for fence */ - lret = i915_gem_object_wait(obj, - I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, - MAX_SCHEDULE_TIMEOUT, - NULL); - if (lret == -ERESTARTSYS) - return lret; - - WARN(lret < 0, "waiting returns %li\n", lret); + if (!new_state->fence) { /* implicit fencing */ + ret = i915_sw_fence_await_reservation(&intel_state->commit_ready, + obj->resv, NULL, + false, I915_FENCE_TIMEOUT, + GFP_KERNEL); + if (ret < 0) + return ret; + } if (plane->type == DRM_PLANE_TYPE_CURSOR && INTEL_INFO(dev)->cursor_needs_physical) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ec7fa592b20a..2616d92f9fee 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -365,6 +365,8 @@ struct intel_atomic_state { /* Gen9+ only */ struct skl_wm_values wm_results; + + struct i915_sw_fence commit_ready; }; struct intel_plane_state { -- cgit v1.2.3 From 73cb97010d4fdd2a29f00cac14d206c7641c23d2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:46 +0100 Subject: drm/i915: Combine seqno + tracking into a global timeline struct Our timelines are more than just a seqno. They also provide an ordered list of requests to be executed. Due to the restriction of handling individual address spaces, we are limited to a timeline per address space but we use a fence context per engine within. Our first step to introducing independent timelines per context (i.e. to allow each context to have a queue of requests to execute that have a defined set of dependencies on other requests) is to provide a timeline abstraction for the global execution queue. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-23-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_debugfs.c | 33 +++++------- drivers/gpu/drm/i915/i915_drv.c | 6 ++- drivers/gpu/drm/i915/i915_drv.h | 9 ++-- drivers/gpu/drm/i915/i915_gem.c | 72 ++++++++++++++++++++------ drivers/gpu/drm/i915/i915_gem.h | 2 + drivers/gpu/drm/i915/i915_gem_request.c | 81 ++++++++++++++++++------------ drivers/gpu/drm/i915/i915_gem_request.h | 1 + drivers/gpu/drm/i915/i915_gem_timeline.c | 64 +++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem_timeline.h | 70 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gpu_error.c | 6 +-- drivers/gpu/drm/i915/i915_guc_submission.c | 3 +- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/intel_engine_cs.c | 15 +++--- drivers/gpu/drm/i915/intel_ringbuffer.h | 36 ++----------- 15 files changed, 286 insertions(+), 115 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_timeline.c create mode 100644 drivers/gpu/drm/i915/i915_gem_timeline.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 7faa04c91e1a..240ce9a8d68e 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -42,6 +42,7 @@ i915-y += i915_cmd_parser.o \ i915_gem_shrinker.o \ i915_gem_stolen.o \ i915_gem_tiling.o \ + i915_gem_timeline.o \ i915_gem_userptr.o \ i915_trace_points.o \ intel_breadcrumbs.o \ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b6325065c8e8..3a0ea5eace37 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -552,7 +552,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) seq_printf(m, "Flip queued on %s at seqno %x, next seqno %x [current breadcrumb %x], completed? %d\n", engine->name, i915_gem_request_get_seqno(work->flip_queued_req), - dev_priv->next_seqno, + dev_priv->gt.global_timeline.next_seqno, intel_engine_get_seqno(engine), i915_gem_request_completed(work->flip_queued_req)); } else @@ -662,13 +662,13 @@ static int i915_gem_request_info(struct seq_file *m, void *data) int count; count = 0; - list_for_each_entry(req, &engine->request_list, link) + list_for_each_entry(req, &engine->timeline->requests, link) count++; if (count == 0) continue; seq_printf(m, "%s requests: %d\n", engine->name, count); - list_for_each_entry(req, &engine->request_list, link) + list_for_each_entry(req, &engine->timeline->requests, link) print_request(m, req, " "); any++; @@ -1052,15 +1052,8 @@ static int i915_next_seqno_get(void *data, u64 *val) { struct drm_i915_private *dev_priv = data; - int ret; - - ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex); - if (ret) - return ret; - - *val = dev_priv->next_seqno; - mutex_unlock(&dev_priv->drm.struct_mutex); + *val = READ_ONCE(dev_priv->gt.global_timeline.next_seqno); return 0; } @@ -1075,7 +1068,7 @@ i915_next_seqno_set(void *data, u64 val) if (ret) return ret; - ret = i915_gem_set_seqno(dev, val); + ret = i915_gem_set_global_seqno(dev, val); mutex_unlock(&dev->struct_mutex); return ret; @@ -1364,7 +1357,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seq_printf(m, "\tseqno = %x [current %x, last %x]\n", engine->hangcheck.seqno, seqno[id], - engine->last_submitted_seqno); + engine->timeline->last_submitted_seqno); seq_printf(m, "\twaiters? %s, fake irq active? %s\n", yesno(intel_engine_has_waiter(engine)), yesno(test_bit(engine->id, @@ -3181,7 +3174,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) seq_printf(m, "%s\n", engine->name); seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [score %d]\n", intel_engine_get_seqno(engine), - engine->last_submitted_seqno, + engine->timeline->last_submitted_seqno, engine->hangcheck.seqno, engine->hangcheck.score); @@ -3189,14 +3182,14 @@ static int i915_engine_info(struct seq_file *m, void *unused) seq_printf(m, "\tRequests:\n"); - rq = list_first_entry(&engine->request_list, - struct drm_i915_gem_request, link); - if (&rq->link != &engine->request_list) + rq = list_first_entry(&engine->timeline->requests, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->timeline->requests) print_request(m, rq, "\t\tfirst "); - rq = list_last_entry(&engine->request_list, - struct drm_i915_gem_request, link); - if (&rq->link != &engine->request_list) + rq = list_last_entry(&engine->timeline->requests, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->timeline->requests) print_request(m, rq, "\t\tlast "); rq = i915_gem_find_active_request(engine); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 91cd7b296c0f..839ce2ae38fa 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -831,7 +831,9 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, intel_init_display_hooks(dev_priv); intel_init_clock_gating_hooks(dev_priv); intel_init_audio_hooks(dev_priv); - i915_gem_load_init(&dev_priv->drm); + ret = i915_gem_load_init(&dev_priv->drm); + if (ret < 0) + goto err_gvt; intel_display_crc_init(dev_priv); @@ -841,6 +843,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, return 0; +err_gvt: + intel_gvt_cleanup(dev_priv); err_workqueues: i915_workqueues_cleanup(dev_priv); return ret; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 693ee69a4715..f0f68f64d09c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -63,6 +63,7 @@ #include "i915_gem_gtt.h" #include "i915_gem_render_state.h" #include "i915_gem_request.h" +#include "i915_gem_timeline.h" #include "intel_gvt.h" @@ -1830,7 +1831,6 @@ struct drm_i915_private { struct i915_gem_context *kernel_context; struct intel_engine_cs *engine[I915_NUM_ENGINES]; struct i915_vma *semaphore; - u32 next_seqno; struct drm_dma_handle *status_page_dmah; struct resource mch_res; @@ -2090,6 +2090,9 @@ struct drm_i915_private { void (*resume)(struct drm_i915_private *); void (*cleanup_engine)(struct intel_engine_cs *engine); + struct list_head timelines; + struct i915_gem_timeline global_timeline; + /** * Is the GPU currently considered idle, or busy executing * userspace requests? Whilst idle, we allow runtime power @@ -3175,7 +3178,7 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -void i915_gem_load_init(struct drm_device *dev); +int i915_gem_load_init(struct drm_device *dev); void i915_gem_load_cleanup(struct drm_device *dev); void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); int i915_gem_freeze(struct drm_i915_private *dev_priv); @@ -3347,7 +3350,7 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old, struct drm_i915_gem_object *new, unsigned frontbuffer_bits); -int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno); +int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno); struct drm_i915_gem_request * i915_gem_find_active_request(struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1161a21ec810..525360219bbb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -371,7 +371,7 @@ out: if (flags & I915_WAIT_LOCKED && i915_gem_request_completed(rq)) i915_gem_request_retire_upto(rq); - if (rps && rq->fence.seqno == rq->engine->last_submitted_seqno) { + if (rps && rq->fence.seqno == rq->timeline->last_submitted_seqno) { /* The GPU is now idle and this client has stalled. * Since no other client has submitted a request in the * meantime, assume that this client is the only one @@ -2563,7 +2563,7 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) * extra delay for a recent interrupt is pointless. Hence, we do * not need an engine->irq_seqno_barrier() before the seqno reads. */ - list_for_each_entry(request, &engine->request_list, link) { + list_for_each_entry(request, &engine->timeline->requests, link) { if (i915_gem_request_completed(request)) continue; @@ -2632,7 +2632,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) if (i915_gem_context_is_default(incomplete_ctx)) return; - list_for_each_entry_continue(request, &engine->request_list, link) + list_for_each_entry_continue(request, &engine->timeline->requests, link) if (request->ctx == incomplete_ctx) reset_request(request); } @@ -2671,7 +2671,8 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine) * (lockless) lookup doesn't try and wait upon the request as we * reset it. */ - intel_engine_init_seqno(engine, engine->last_submitted_seqno); + intel_engine_init_global_seqno(engine, + engine->timeline->last_submitted_seqno); /* * Clear the execlists queue up before freeing the requests, as those @@ -2979,18 +2980,26 @@ destroy: return 0; } -int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, - unsigned int flags) +static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags) { - struct intel_engine_cs *engine; - enum intel_engine_id id; - int ret; + int ret, i; - for_each_engine(engine, dev_priv, id) { - if (engine->last_context == NULL) - continue; + for (i = 0; i < ARRAY_SIZE(tl->engine); i++) { + ret = i915_gem_active_wait(&tl->engine[i].last_request, flags); + if (ret) + return ret; + } - ret = intel_engine_idle(engine, flags); + return 0; +} + +int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags) +{ + struct i915_gem_timeline *tl; + int ret; + + list_for_each_entry(tl, &i915->gt.timelines, link) { + ret = wait_for_timeline(tl, flags); if (ret) return ret; } @@ -4680,21 +4689,32 @@ i915_gem_load_init_fences(struct drm_i915_private *dev_priv) i915_gem_detect_bit_6_swizzle(dev); } -void +int i915_gem_load_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + int err; dev_priv->objects = kmem_cache_create("i915_gem_object", sizeof(struct drm_i915_gem_object), 0, SLAB_HWCACHE_ALIGN, NULL); + if (!dev_priv->objects) { + err = -ENOMEM; + goto err_out; + } + dev_priv->vmas = kmem_cache_create("i915_gem_vma", sizeof(struct i915_vma), 0, SLAB_HWCACHE_ALIGN, NULL); + if (!dev_priv->vmas) { + err = -ENOMEM; + goto err_objects; + } + dev_priv->requests = kmem_cache_create("i915_gem_request", sizeof(struct drm_i915_gem_request), 0, @@ -4702,6 +4722,19 @@ i915_gem_load_init(struct drm_device *dev) SLAB_RECLAIM_ACCOUNT | SLAB_DESTROY_BY_RCU, NULL); + if (!dev_priv->requests) { + err = -ENOMEM; + goto err_vmas; + } + + mutex_lock(&dev_priv->drm.struct_mutex); + INIT_LIST_HEAD(&dev_priv->gt.timelines); + err = i915_gem_timeline_init(dev_priv, + &dev_priv->gt.global_timeline, + "[execution]"); + mutex_unlock(&dev_priv->drm.struct_mutex); + if (err) + goto err_requests; INIT_LIST_HEAD(&dev_priv->context_list); INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work); @@ -4726,6 +4759,17 @@ i915_gem_load_init(struct drm_device *dev) atomic_set(&dev_priv->mm.bsd_engine_dispatch_index, 0); spin_lock_init(&dev_priv->fb_tracking.lock); + + return 0; + +err_requests: + kmem_cache_destroy(dev_priv->requests); +err_vmas: + kmem_cache_destroy(dev_priv->vmas); +err_objects: + kmem_cache_destroy(dev_priv->objects); +err_out: + return err; } void i915_gem_load_cleanup(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index 8292e797d9b5..735580d72eb1 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -31,4 +31,6 @@ #define GEM_BUG_ON(expr) #endif +#define I915_NUM_ENGINES 5 + #endif /* __I915_GEM_H__ */ diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 01a7fa513b4a..16d38f87f0a7 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -40,7 +40,7 @@ static const char *i915_fence_get_timeline_name(struct dma_fence *fence) * multiple execution contexts (fence contexts) as we allow * engines within a single timeline to execute in parallel. */ - return "global"; + return to_request(fence)->timeline->common->name; } static bool i915_fence_signaled(struct dma_fence *fence) @@ -211,7 +211,7 @@ void i915_gem_request_retire_upto(struct drm_i915_gem_request *req) return; do { - tmp = list_first_entry(&engine->request_list, + tmp = list_first_entry(&engine->timeline->requests, typeof(*tmp), link); i915_gem_request_retire(tmp); @@ -238,37 +238,39 @@ static int i915_gem_check_wedge(struct drm_i915_private *dev_priv) return 0; } -static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) +static int i915_gem_init_global_seqno(struct drm_i915_private *dev_priv, + u32 seqno) { + struct i915_gem_timeline *timeline = &dev_priv->gt.global_timeline; struct intel_engine_cs *engine; enum intel_engine_id id; int ret; /* Carefully retire all requests without writing to the rings */ - for_each_engine(engine, dev_priv, id) { - ret = intel_engine_idle(engine, - I915_WAIT_INTERRUPTIBLE | - I915_WAIT_LOCKED); - if (ret) - return ret; - } + ret = i915_gem_wait_for_idle(dev_priv, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED); + if (ret) + return ret; + i915_gem_retire_requests(dev_priv); /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ - if (!i915_seqno_passed(seqno, dev_priv->next_seqno)) { + if (!i915_seqno_passed(seqno, timeline->next_seqno)) { while (intel_kick_waiters(dev_priv) || intel_kick_signalers(dev_priv)) yield(); + yield(); } /* Finally reset hw state */ for_each_engine(engine, dev_priv, id) - intel_engine_init_seqno(engine, seqno); + intel_engine_init_global_seqno(engine, seqno); return 0; } -int i915_gem_set_seqno(struct drm_device *dev, u32 seqno) +int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno) { struct drm_i915_private *dev_priv = to_i915(dev); int ret; @@ -281,28 +283,31 @@ int i915_gem_set_seqno(struct drm_device *dev, u32 seqno) /* HWS page needs to be set less than what we * will inject to ring */ - ret = i915_gem_init_seqno(dev_priv, seqno - 1); + ret = i915_gem_init_global_seqno(dev_priv, seqno - 1); if (ret) return ret; - dev_priv->next_seqno = seqno; + dev_priv->gt.global_timeline.next_seqno = seqno; return 0; } -static int i915_gem_get_seqno(struct drm_i915_private *dev_priv, u32 *seqno) +static int i915_gem_get_global_seqno(struct drm_i915_private *dev_priv, + u32 *seqno) { + struct i915_gem_timeline *tl = &dev_priv->gt.global_timeline; + /* reserve 0 for non-seqno */ - if (unlikely(dev_priv->next_seqno == 0)) { + if (unlikely(tl->next_seqno == 0)) { int ret; - ret = i915_gem_init_seqno(dev_priv, 0); + ret = i915_gem_init_global_seqno(dev_priv, 0); if (ret) return ret; - dev_priv->next_seqno = 1; + tl->next_seqno = 1; } - *seqno = dev_priv->next_seqno++; + *seqno = tl->next_seqno++; return 0; } @@ -311,13 +316,14 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct drm_i915_gem_request *request = container_of(fence, typeof(*request), submit); + struct intel_engine_cs *engine = request->engine; /* Will be called from irq-context when using foreign DMA fences */ switch (state) { case FENCE_COMPLETE: - request->engine->last_submitted_seqno = request->fence.seqno; - request->engine->submit_request(request); + engine->timeline->last_submitted_seqno = request->fence.seqno; + engine->submit_request(request); break; case FENCE_FREE: @@ -357,7 +363,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, return ERR_PTR(ret); /* Move the oldest request to the slab-cache (if not in use!) */ - req = list_first_entry_or_null(&engine->request_list, + req = list_first_entry_or_null(&engine->timeline->requests, typeof(*req), link); if (req && i915_gem_request_completed(req)) i915_gem_request_retire(req); @@ -394,15 +400,17 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, if (!req) return ERR_PTR(-ENOMEM); - ret = i915_gem_get_seqno(dev_priv, &seqno); + ret = i915_gem_get_global_seqno(dev_priv, &seqno); if (ret) goto err; + req->timeline = engine->timeline; + spin_lock_init(&req->lock); dma_fence_init(&req->fence, &i915_fence_ops, &req->lock, - engine->fence_context, + req->timeline->fence_context, seqno); i915_sw_fence_init(&req->submit, submit_notify); @@ -457,9 +465,16 @@ i915_gem_request_await_request(struct drm_i915_gem_request *to, GEM_BUG_ON(to == from); - if (to->engine == from->engine) + if (to->timeline == from->timeline) return 0; + if (to->engine == from->engine) { + ret = i915_sw_fence_await_sw_fence_gfp(&to->submit, + &from->submit, + GFP_KERNEL); + return ret < 0 ? ret : 0; + } + idx = intel_engine_sync_index(from->engine, to->engine); if (from->fence.seqno <= from->engine->semaphore.sync_seqno[idx]) return 0; @@ -622,6 +637,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) { struct intel_engine_cs *engine = request->engine; struct intel_ring *ring = request->ring; + struct intel_timeline *timeline = request->timeline; struct drm_i915_gem_request *prev; u32 request_start; u32 reserved_tail; @@ -679,17 +695,17 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) * see a more recent value in the hws than we are tracking. */ - prev = i915_gem_active_raw(&engine->last_request, + prev = i915_gem_active_raw(&timeline->last_request, &request->i915->drm.struct_mutex); if (prev) i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, &request->submitq); request->emitted_jiffies = jiffies; - request->previous_seqno = engine->last_pending_seqno; - engine->last_pending_seqno = request->fence.seqno; - i915_gem_active_set(&engine->last_request, request); - list_add_tail(&request->link, &engine->request_list); + request->previous_seqno = timeline->last_pending_seqno; + timeline->last_pending_seqno = request->fence.seqno; + i915_gem_active_set(&timeline->last_request, request); + list_add_tail(&request->link, &timeline->requests); list_add_tail(&request->ring_link, &ring->request_list); i915_gem_mark_busy(engine); @@ -899,7 +915,8 @@ static bool engine_retire_requests(struct intel_engine_cs *engine) { struct drm_i915_gem_request *request, *next; - list_for_each_entry_safe(request, next, &engine->request_list, link) { + list_for_each_entry_safe(request, next, + &engine->timeline->requests, link) { if (!i915_gem_request_completed(request)) return false; diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index a51d596a60ac..4ac30ae93e49 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -81,6 +81,7 @@ struct drm_i915_gem_request { struct i915_gem_context *ctx; struct intel_engine_cs *engine; struct intel_ring *ring; + struct intel_timeline *timeline; struct intel_signal_node signaling; struct i915_sw_fence submit; diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.c b/drivers/gpu/drm/i915/i915_gem_timeline.c new file mode 100644 index 000000000000..a1bd03d10852 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_timeline.c @@ -0,0 +1,64 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "i915_drv.h" + +int i915_gem_timeline_init(struct drm_i915_private *i915, + struct i915_gem_timeline *timeline, + const char *name) +{ + unsigned int i; + u64 fences; + + lockdep_assert_held(&i915->drm.struct_mutex); + + timeline->i915 = i915; + timeline->name = kstrdup(name ?: "[kernel]", GFP_KERNEL); + if (!timeline->name) + return -ENOMEM; + + list_add(&timeline->link, &i915->gt.timelines); + + /* Called during early_init before we know how many engines there are */ + fences = dma_fence_context_alloc(ARRAY_SIZE(timeline->engine)); + for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) { + struct intel_timeline *tl = &timeline->engine[i]; + + tl->fence_context = fences++; + tl->common = timeline; + + init_request_active(&tl->last_request, NULL); + INIT_LIST_HEAD(&tl->requests); + } + + return 0; +} + +void i915_gem_timeline_fini(struct i915_gem_timeline *tl) +{ + lockdep_assert_held(&tl->i915->drm.struct_mutex); + + list_del(&tl->link); + kfree(tl->name); +} diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_gem_timeline.h new file mode 100644 index 000000000000..bfdf0331cc50 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_timeline.h @@ -0,0 +1,70 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef I915_GEM_TIMELINE_H +#define I915_GEM_TIMELINE_H + +#include + +#include "i915_gem_request.h" + +struct i915_gem_timeline; + +struct intel_timeline { + u64 fence_context; + u32 last_submitted_seqno; + u32 last_pending_seqno; + + /** + * List of breadcrumbs associated with GPU requests currently + * outstanding. + */ + struct list_head requests; + + /* Contains an RCU guarded pointer to the last request. No reference is + * held to the request, users must carefully acquire a reference to + * the request using i915_gem_active_get_request_rcu(), or hold the + * struct_mutex. + */ + struct i915_gem_active last_request; + + struct i915_gem_timeline *common; +}; + +struct i915_gem_timeline { + struct list_head link; + u32 next_seqno; + + struct drm_i915_private *i915; + const char *name; + + struct intel_timeline engine[I915_NUM_ENGINES]; +}; + +int i915_gem_timeline_init(struct drm_i915_private *i915, + struct i915_gem_timeline *tl, + const char *name); +void i915_gem_timeline_fini(struct i915_gem_timeline *tl); + +#endif diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index aa8dadcc669f..12fea57d41fb 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1110,7 +1110,7 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); ee->acthd = intel_engine_get_active_head(engine); ee->seqno = intel_engine_get_seqno(engine); - ee->last_seqno = engine->last_submitted_seqno; + ee->last_seqno = engine->timeline->last_submitted_seqno; ee->start = I915_READ_START(engine); ee->head = I915_READ_HEAD(engine); ee->tail = I915_READ_TAIL(engine); @@ -1195,7 +1195,7 @@ static void engine_record_requests(struct intel_engine_cs *engine, count = 0; request = first; - list_for_each_entry_from(request, &engine->request_list, link) + list_for_each_entry_from(request, &engine->timeline->requests, link) count++; if (!count) return; @@ -1208,7 +1208,7 @@ static void engine_record_requests(struct intel_engine_cs *engine, count = 0; request = first; - list_for_each_entry_from(request, &engine->request_list, link) { + list_for_each_entry_from(request, &engine->timeline->requests, link) { if (count >= ee->num_requests) { /* * If the ring request list was changed in diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 74235ea3950f..cca250e90845 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1522,7 +1522,8 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) engine->submit_request = i915_guc_submit; /* Replay the current set of previously submitted requests */ - list_for_each_entry(request, &engine->request_list, link) { + list_for_each_entry(request, + &engine->timeline->requests, link) { client->wq_rsvd += sizeof(struct guc_wq_item); if (i915_sw_fence_done(&request->submit)) i915_guc_submit(request); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 88239e1b29e4..90d0905592f2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3168,7 +3168,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) acthd = intel_engine_get_active_head(engine); seqno = intel_engine_get_seqno(engine); - submit = READ_ONCE(engine->last_submitted_seqno); + submit = READ_ONCE(engine->timeline->last_submitted_seqno); if (engine->hangcheck.seqno == seqno) { if (i915_seqno_passed(seqno, submit)) { diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index fd551824adf9..6a3105512d18 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -174,7 +174,7 @@ cleanup: return ret; } -void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno) +void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno) { struct drm_i915_private *dev_priv = engine->i915; @@ -210,7 +210,9 @@ void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno) intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); if (engine->irq_seqno_barrier) engine->irq_seqno_barrier(engine); - engine->last_submitted_seqno = seqno; + + GEM_BUG_ON(i915_gem_active_isset(&engine->timeline->last_request)); + engine->timeline->last_submitted_seqno = seqno; engine->hangcheck.seqno = seqno; @@ -225,10 +227,9 @@ void intel_engine_init_hangcheck(struct intel_engine_cs *engine) memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); } -static void intel_engine_init_requests(struct intel_engine_cs *engine) +static void intel_engine_init_timeline(struct intel_engine_cs *engine) { - init_request_active(&engine->last_request, NULL); - INIT_LIST_HEAD(&engine->request_list); + engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; } /** @@ -245,9 +246,7 @@ void intel_engine_setup_common(struct intel_engine_cs *engine) INIT_LIST_HEAD(&engine->execlist_queue); spin_lock_init(&engine->execlist_lock); - engine->fence_context = dma_fence_context_alloc(1); - - intel_engine_init_requests(engine); + intel_engine_init_timeline(engine); intel_engine_init_hangcheck(engine); i915_gem_batch_pool_init(engine, &engine->batch_pool); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index cb6e96c6cd47..a62e396c8863 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -4,6 +4,7 @@ #include #include "i915_gem_batch_pool.h" #include "i915_gem_request.h" +#include "i915_gem_timeline.h" #define I915_CMD_HASH_ORDER 9 @@ -169,7 +170,6 @@ struct intel_engine_cs { VCS2, /* Keep instances of the same type engine together. */ VECS } id; -#define I915_NUM_ENGINES 5 #define _VCS(n) (VCS + (n)) unsigned int exec_id; enum intel_engine_hw_id { @@ -180,10 +180,10 @@ struct intel_engine_cs { VCS2_HW } hw_id; enum intel_engine_hw_id guc_id; /* XXX same as hw_id? */ - u64 fence_context; u32 mmio_base; unsigned int irq_shift; struct intel_ring *buffer; + struct intel_timeline *timeline; struct intel_render_state *render_state; @@ -346,27 +346,6 @@ struct intel_engine_cs { bool preempt_wa; u32 ctx_desc_template; - /** - * List of breadcrumbs associated with GPU requests currently - * outstanding. - */ - struct list_head request_list; - - /** - * Seqno of request most recently submitted to request_list. - * Used exclusively by hang checker to avoid grabbing lock while - * inspecting request list. - */ - u32 last_submitted_seqno; - u32 last_pending_seqno; - - /* An RCU guarded pointer to the last request. No reference is - * held to the request, users must carefully acquire a reference to - * the request using i915_gem_active_get_rcu(), or hold the - * struct_mutex. - */ - struct i915_gem_active last_request; - struct i915_gem_context *last_context; struct intel_engine_hangcheck hangcheck; @@ -516,20 +495,13 @@ static inline u32 intel_ring_offset(struct intel_ring *ring, u32 value) int __intel_ring_space(int head, int tail, int size); void intel_ring_update_space(struct intel_ring *ring); -void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno); +void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno); void intel_engine_setup_common(struct intel_engine_cs *engine); int intel_engine_init_common(struct intel_engine_cs *engine); int intel_engine_create_scratch(struct intel_engine_cs *engine, int size); void intel_engine_cleanup_common(struct intel_engine_cs *engine); -static inline int intel_engine_idle(struct intel_engine_cs *engine, - unsigned int flags) -{ - /* Wait upon the last request to be completed */ - return i915_gem_active_wait(&engine->last_request, flags); -} - int intel_init_render_ring_buffer(struct intel_engine_cs *engine); int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine); int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine); @@ -619,7 +591,7 @@ unsigned int intel_kick_signalers(struct drm_i915_private *i915); static inline bool intel_engine_is_active(struct intel_engine_cs *engine) { - return i915_gem_active_isset(&engine->last_request); + return i915_gem_active_isset(&engine->timeline->last_request); } #endif /* _INTEL_RINGBUFFER_H_ */ -- cgit v1.2.3 From 3033acab07f95c089fb871896406657ad4000ed6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:47 +0100 Subject: drm/i915: Queue the idling context switch after all other timelines Before suspend, we wait for the switch to the kernel context. In order for all the other context images to be complete upon suspend, that switch must be the last operation by the GPU (i.e. this idling request must not overtake any pending requests). To make this request execute last, we make it depend on every other inflight request. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-24-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 10 ++++++++++ drivers/gpu/drm/i915/i915_gem_context.c | 23 +++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 525360219bbb..5ea46a7d991f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4362,6 +4362,15 @@ void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj) i915_gem_object_put(obj); } +static void assert_kernel_context_is_current(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + + for_each_engine(engine, dev_priv, id) + GEM_BUG_ON(engine->last_context != dev_priv->kernel_context); +} + int i915_gem_suspend(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -4391,6 +4400,7 @@ int i915_gem_suspend(struct drm_device *dev) i915_gem_retire_requests(dev_priv); + assert_kernel_context_is_current(dev_priv); i915_gem_context_lost(dev_priv); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 47e888cc721f..a2acb8bb5f34 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -931,22 +931,33 @@ int i915_switch_context(struct drm_i915_gem_request *req) int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + struct i915_gem_timeline *timeline; enum intel_engine_id id; + lockdep_assert_held(&dev_priv->drm.struct_mutex); + for_each_engine(engine, dev_priv, id) { struct drm_i915_gem_request *req; int ret; - if (engine->last_context == NULL) - continue; - - if (engine->last_context == dev_priv->kernel_context) - continue; - req = i915_gem_request_alloc(engine, dev_priv->kernel_context); if (IS_ERR(req)) return PTR_ERR(req); + /* Queue this switch after all other activity */ + list_for_each_entry(timeline, &dev_priv->gt.timelines, link) { + struct drm_i915_gem_request *prev; + struct intel_timeline *tl; + + tl = &timeline->engine[engine->id]; + prev = i915_gem_active_raw(&tl->last_request, + &dev_priv->drm.struct_mutex); + if (prev) + i915_sw_fence_await_sw_fence_gfp(&req->submit, + &prev->submit, + GFP_KERNEL); + } + ret = i915_switch_context(req); i915_add_request_no_flush(req); if (ret) -- cgit v1.2.3 From 4680816be3362bdf6ac712cbdc6098c76febe78f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:48 +0100 Subject: drm/i915: Wait first for submission, before waiting for request completion In future patches, we will no longer be able to wait on a static global seqno and instead have to break our wait up into phases. First we wait for the global seqno assignment (upon submission to hardware), and once submitted we wait for the hardware to complete. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-25-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 16d38f87f0a7..03ae85a1eefb 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -789,6 +789,49 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, return false; } +static long +__i915_request_wait_for_submit(struct drm_i915_gem_request *request, + unsigned int flags, + long timeout) +{ + const int state = flags & I915_WAIT_INTERRUPTIBLE ? + TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; + wait_queue_head_t *q = &request->i915->gpu_error.wait_queue; + DEFINE_WAIT(reset); + DEFINE_WAIT(wait); + + if (flags & I915_WAIT_LOCKED) + add_wait_queue(q, &reset); + + do { + prepare_to_wait(&request->submit.wait, &wait, state); + + if (i915_sw_fence_done(&request->submit)) + break; + + if (flags & I915_WAIT_LOCKED && + i915_reset_in_progress(&request->i915->gpu_error)) { + __set_current_state(TASK_RUNNING); + i915_reset(request->i915); + reset_wait_queue(q, &reset); + continue; + } + + if (signal_pending_state(state, current)) { + timeout = -ERESTARTSYS; + break; + } + + timeout = io_schedule_timeout(timeout); + } while (timeout); + finish_wait(&request->submit.wait, &wait); + + if (flags & I915_WAIT_LOCKED) + remove_wait_queue(q, &reset); + + return timeout; +} + /** * i915_wait_request - wait until execution of request has finished * @req: the request to wait upon @@ -833,6 +876,14 @@ long i915_wait_request(struct drm_i915_gem_request *req, trace_i915_gem_request_wait_begin(req); + if (!i915_sw_fence_done(&req->submit)) { + timeout = __i915_request_wait_for_submit(req, flags, timeout); + if (timeout < 0) + goto complete; + + GEM_BUG_ON(!i915_sw_fence_done(&req->submit)); + } + /* Optimistic short spin before touching IRQs */ if (i915_spin_request(req, state, 5)) goto complete; -- cgit v1.2.3 From 65e4760e3920c21073a9d737929dc36df561380f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:49 +0100 Subject: drm/i915: Introduce a global_seqno for each request Though we will have multiple timelines, we still have a single timeline of execution. This we can use to provide an execution and retirement order of requests. This keeps tracking execution of requests simple, and vital for preserving a single waiter (i.e. so that we can order the waiters so that only the earliest to wakeup need be woken). To accomplish this we distinguish the seqno used to order requests per-context (external) and that used internally for execution. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-26-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_request.c | 19 +++++++++++++----- drivers/gpu/drm/i915/i915_gem_request.h | 32 +++++++++++++++++++++++++----- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- drivers/gpu/drm/i915/i915_guc_submission.c | 4 ++-- drivers/gpu/drm/i915/i915_trace.h | 8 ++++---- drivers/gpu/drm/i915/intel_breadcrumbs.c | 8 +++++--- drivers/gpu/drm/i915/intel_lrc.c | 4 ++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 14 ++++++------- 11 files changed, 66 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3a0ea5eace37..90bc4a89e0d5 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -637,7 +637,7 @@ static void print_request(struct seq_file *m, rcu_read_lock(); task = pid ? pid_task(pid, PIDTYPE_PID) : NULL; seq_printf(m, "%s%x [%x:%x] @ %d: %s [%d]\n", prefix, - rq->fence.seqno, rq->ctx->hw_id, rq->fence.seqno, + rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno, jiffies_to_msecs(jiffies - rq->emitted_jiffies), task ? task->comm : "", task ? task->pid : -1); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f0f68f64d09c..217674bb1495 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -4050,7 +4050,7 @@ __i915_request_irq_complete(struct drm_i915_gem_request *req) /* Before we do the heavier coherent read of the seqno, * check the value (hopefully) in the CPU cacheline. */ - if (i915_gem_request_completed(req)) + if (__i915_gem_request_completed(req)) return true; /* Ensure our read of the seqno is coherent so that we @@ -4101,7 +4101,7 @@ __i915_request_irq_complete(struct drm_i915_gem_request *req) wake_up_process(tsk); rcu_read_unlock(); - if (i915_gem_request_completed(req)) + if (__i915_gem_request_completed(req)) return true; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5ea46a7d991f..f4cfb88bd804 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2615,7 +2615,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) return; DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n", - engine->name, request->fence.seqno); + engine->name, request->global_seqno); /* Setup the CS to resume from the breadcrumb of the hung request */ engine->reset_hw(engine, request); diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 03ae85a1eefb..311cf3fac2e0 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -376,7 +376,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, * of being read by __i915_gem_active_get_rcu(). As such, * we have to be very careful when overwriting the contents. During * the RCU lookup, we change chase the request->engine pointer, - * read the request->fence.seqno and increment the reference count. + * read the request->global_seqno and increment the reference count. * * The reference count is incremented atomically. If it is zero, * the lookup knows the request is unallocated and complete. Otherwise, @@ -418,6 +418,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, INIT_LIST_HEAD(&req->active_list); req->i915 = dev_priv; req->engine = engine; + req->global_seqno = seqno; req->ctx = i915_gem_context_get(ctx); /* No zalloc, must clear what we need by hand */ @@ -475,8 +476,15 @@ i915_gem_request_await_request(struct drm_i915_gem_request *to, return ret < 0 ? ret : 0; } + if (!from->global_seqno) { + ret = i915_sw_fence_await_dma_fence(&to->submit, + &from->fence, 0, + GFP_KERNEL); + return ret < 0 ? ret : 0; + } + idx = intel_engine_sync_index(from->engine, to->engine); - if (from->fence.seqno <= from->engine->semaphore.sync_seqno[idx]) + if (from->global_seqno <= from->engine->semaphore.sync_seqno[idx]) return 0; trace_i915_gem_ring_sync_to(to, from); @@ -494,7 +502,7 @@ i915_gem_request_await_request(struct drm_i915_gem_request *to, return ret; } - from->engine->semaphore.sync_seqno[idx] = from->fence.seqno; + from->engine->semaphore.sync_seqno[idx] = from->global_seqno; return 0; } @@ -774,7 +782,7 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, timeout_us += local_clock_us(&cpu); do { - if (i915_gem_request_completed(req)) + if (__i915_gem_request_completed(req)) return true; if (signal_pending_state(state, current)) @@ -883,6 +891,7 @@ long i915_wait_request(struct drm_i915_gem_request *req, GEM_BUG_ON(!i915_sw_fence_done(&req->submit)); } + GEM_BUG_ON(!req->global_seqno); /* Optimistic short spin before touching IRQs */ if (i915_spin_request(req, state, 5)) @@ -892,7 +901,7 @@ long i915_wait_request(struct drm_i915_gem_request *req, if (flags & I915_WAIT_LOCKED) add_wait_queue(&req->i915->gpu_error.wait_queue, &reset); - intel_wait_init(&wait, req->fence.seqno); + intel_wait_init(&wait, req->global_seqno); if (intel_engine_add_wait(req->engine, &wait)) /* In order to check that we haven't missed the interrupt * as we enabled it, we need to kick ourselves to do a diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 4ac30ae93e49..75f8360b3421 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -87,6 +87,8 @@ struct drm_i915_gem_request { struct i915_sw_fence submit; wait_queue_t submitq; + u32 global_seqno; + /** GEM sequence number associated with the previous request, * when the HWS breadcrumb is equal to this the GPU is processing * this request. @@ -163,7 +165,7 @@ void i915_gem_request_retire_upto(struct drm_i915_gem_request *req); static inline u32 i915_gem_request_get_seqno(struct drm_i915_gem_request *req) { - return req ? req->fence.seqno : 0; + return req ? req->global_seqno : 0; } static inline struct intel_engine_cs * @@ -248,17 +250,37 @@ static inline bool i915_seqno_passed(u32 seq1, u32 seq2) } static inline bool -i915_gem_request_started(const struct drm_i915_gem_request *req) +__i915_gem_request_started(const struct drm_i915_gem_request *req) { + GEM_BUG_ON(!req->global_seqno); return i915_seqno_passed(intel_engine_get_seqno(req->engine), req->previous_seqno); } static inline bool -i915_gem_request_completed(const struct drm_i915_gem_request *req) +i915_gem_request_started(const struct drm_i915_gem_request *req) { + if (!req->global_seqno) + return false; + + return __i915_gem_request_started(req); +} + +static inline bool +__i915_gem_request_completed(const struct drm_i915_gem_request *req) +{ + GEM_BUG_ON(!req->global_seqno); return i915_seqno_passed(intel_engine_get_seqno(req->engine), - req->fence.seqno); + req->global_seqno); +} + +static inline bool +i915_gem_request_completed(const struct drm_i915_gem_request *req) +{ + if (!req->global_seqno) + return false; + + return __i915_gem_request_completed(req); } bool __i915_spin_request(const struct drm_i915_gem_request *request, @@ -266,7 +288,7 @@ bool __i915_spin_request(const struct drm_i915_gem_request *request, static inline bool i915_spin_request(const struct drm_i915_gem_request *request, int state, unsigned long timeout_us) { - return (i915_gem_request_started(request) && + return (__i915_gem_request_started(request) && __i915_spin_request(request, state, timeout_us)); } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 12fea57d41fb..9aa197ca6210 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1176,7 +1176,7 @@ static void record_request(struct drm_i915_gem_request *request, struct drm_i915_error_request *erq) { erq->context = request->ctx->hw_id; - erq->seqno = request->fence.seqno; + erq->seqno = request->global_seqno; erq->jiffies = request->emitted_jiffies; erq->head = request->head; erq->tail = request->tail; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index cca250e90845..857ef914cae7 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -554,7 +554,7 @@ static void guc_wq_item_append(struct i915_guc_client *gc, wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, engine); wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT; - wqi->fence_id = rq->fence.seqno; + wqi->fence_id = rq->global_seqno; kunmap_atomic(base); } @@ -655,7 +655,7 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq) client->b_fail += 1; guc->submissions[engine_id] += 1; - guc->last_seqno[engine_id] = rq->fence.seqno; + guc->last_seqno[engine_id] = rq->global_seqno; spin_unlock(&client->wq_lock); } diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 5c912c25f7d3..c5d210ebaa9a 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -466,7 +466,7 @@ TRACE_EVENT(i915_gem_ring_sync_to, __entry->dev = from->i915->drm.primary->index; __entry->sync_from = from->engine->id; __entry->sync_to = to->engine->id; - __entry->seqno = from->fence.seqno; + __entry->seqno = from->global_seqno; ), TP_printk("dev=%u, sync-from=%u, sync-to=%u, seqno=%u", @@ -489,7 +489,7 @@ TRACE_EVENT(i915_gem_ring_dispatch, TP_fast_assign( __entry->dev = req->i915->drm.primary->index; __entry->ring = req->engine->id; - __entry->seqno = req->fence.seqno; + __entry->seqno = req->global_seqno; __entry->flags = flags; dma_fence_enable_sw_signaling(&req->fence); ), @@ -534,7 +534,7 @@ DECLARE_EVENT_CLASS(i915_gem_request, TP_fast_assign( __entry->dev = req->i915->drm.primary->index; __entry->ring = req->engine->id; - __entry->seqno = req->fence.seqno; + __entry->seqno = req->global_seqno; ), TP_printk("dev=%u, ring=%u, seqno=%u", @@ -596,7 +596,7 @@ TRACE_EVENT(i915_gem_request_wait_begin, TP_fast_assign( __entry->dev = req->i915->drm.primary->index; __entry->ring = req->engine->id; - __entry->seqno = req->fence.seqno; + __entry->seqno = req->global_seqno; __entry->blocking = mutex_is_locked(&req->i915->drm.struct_mutex); ), diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 56efcc507ea2..0d5def0d2dfe 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -504,9 +504,11 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request) /* locked by dma_fence_enable_sw_signaling() */ assert_spin_locked(&request->lock); + if (!request->global_seqno) + return; request->signaling.wait.tsk = b->signaler; - request->signaling.wait.seqno = request->fence.seqno; + request->signaling.wait.seqno = request->global_seqno; i915_gem_request_get(request); spin_lock(&b->lock); @@ -530,8 +532,8 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request) p = &b->signals.rb_node; while (*p) { parent = *p; - if (i915_seqno_passed(request->fence.seqno, - to_signaler(parent)->fence.seqno)) { + if (i915_seqno_passed(request->global_seqno, + to_signaler(parent)->global_seqno)) { p = &parent->rb_right; first = false; } else { diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index cb30549dfd40..e0a9bf81774b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1584,7 +1584,7 @@ static int gen8_emit_request(struct drm_i915_gem_request *request) intel_hws_seqno_address(request->engine) | MI_FLUSH_DW_USE_GTT); intel_ring_emit(ring, 0); - intel_ring_emit(ring, request->fence.seqno); + intel_ring_emit(ring, request->global_seqno); intel_ring_emit(ring, MI_USER_INTERRUPT); intel_ring_emit(ring, MI_NOOP); return intel_logical_ring_advance(request); @@ -1613,7 +1613,7 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request) PIPE_CONTROL_QW_WRITE)); intel_ring_emit(ring, intel_hws_seqno_address(request->engine)); intel_ring_emit(ring, 0); - intel_ring_emit(ring, i915_gem_request_get_seqno(request)); + intel_ring_emit(ring, request->global_seqno); /* We're thrashing one dword of HWS. */ intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_USER_INTERRUPT); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index aaa46d9ffbc1..76c6b70303fb 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1238,7 +1238,7 @@ static int gen8_rcs_signal(struct drm_i915_gem_request *req) PIPE_CONTROL_CS_STALL); intel_ring_emit(ring, lower_32_bits(gtt_offset)); intel_ring_emit(ring, upper_32_bits(gtt_offset)); - intel_ring_emit(ring, req->fence.seqno); + intel_ring_emit(ring, req->global_seqno); intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_SEMAPHORE_SIGNAL | @@ -1274,7 +1274,7 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *req) lower_32_bits(gtt_offset) | MI_FLUSH_DW_USE_GTT); intel_ring_emit(ring, upper_32_bits(gtt_offset)); - intel_ring_emit(ring, req->fence.seqno); + intel_ring_emit(ring, req->global_seqno); intel_ring_emit(ring, MI_SEMAPHORE_SIGNAL | MI_SEMAPHORE_TARGET(waiter->hw_id)); @@ -1308,7 +1308,7 @@ static int gen6_signal(struct drm_i915_gem_request *req) if (i915_mmio_reg_valid(mbox_reg)) { intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit_reg(ring, mbox_reg); - intel_ring_emit(ring, req->fence.seqno); + intel_ring_emit(ring, req->global_seqno); } } @@ -1339,7 +1339,7 @@ static int i9xx_emit_request(struct drm_i915_gem_request *req) intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(ring, req->fence.seqno); + intel_ring_emit(ring, req->global_seqno); intel_ring_emit(ring, MI_USER_INTERRUPT); intel_ring_advance(ring); @@ -1389,7 +1389,7 @@ static int gen8_render_emit_request(struct drm_i915_gem_request *req) PIPE_CONTROL_QW_WRITE)); intel_ring_emit(ring, intel_hws_seqno_address(engine)); intel_ring_emit(ring, 0); - intel_ring_emit(ring, i915_gem_request_get_seqno(req)); + intel_ring_emit(ring, req->global_seqno); /* We're thrashing one dword of HWS. */ intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_USER_INTERRUPT); @@ -1427,7 +1427,7 @@ gen8_ring_sync_to(struct drm_i915_gem_request *req, MI_SEMAPHORE_WAIT | MI_SEMAPHORE_GLOBAL_GTT | MI_SEMAPHORE_SAD_GTE_SDD); - intel_ring_emit(ring, signal->fence.seqno); + intel_ring_emit(ring, signal->global_seqno); intel_ring_emit(ring, lower_32_bits(offset)); intel_ring_emit(ring, upper_32_bits(offset)); intel_ring_advance(ring); @@ -1465,7 +1465,7 @@ gen6_ring_sync_to(struct drm_i915_gem_request *req, * seqno is >= the last seqno executed. However for hardware the * comparison is strictly greater than. */ - intel_ring_emit(ring, signal->fence.seqno - 1); + intel_ring_emit(ring, signal->global_seqno - 1); intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); -- cgit v1.2.3 From 9b81d556b11fe58827dcd87bc5deaf8da2f716ae Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:50 +0100 Subject: drm/i915: Rename ->emit_request to ->emit_breadcrumb Now that the emission of the request tail and its submission to hardware are two separate steps, engine->emit_request() is confusing. engine->emit_request() is called to emit the breadcrumb commands for the request into the ring, name it such (engine->emit_breadcrumb). Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-27-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 4 ++-- drivers/gpu/drm/i915/intel_lrc.c | 10 +++++----- drivers/gpu/drm/i915/intel_ringbuffer.c | 16 ++++++++-------- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 311cf3fac2e0..a626b2638722 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -685,8 +685,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) request->postfix = ring->tail; /* Not allowed to fail! */ - ret = engine->emit_request(request); - WARN(ret, "(%s)->emit_request failed: %d!\n", engine->name, ret); + ret = engine->emit_breadcrumb(request); + WARN(ret, "(%s)->emit_breadcrumb failed: %d!\n", engine->name, ret); /* Sanity check that the reserved size was large enough. */ ret = ring->tail - request_start; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index e0a9bf81774b..57dba458f185 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -440,7 +440,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) if (last) /* WaIdleLiteRestore:bdw,skl * Apply the wa NOOPs to prevent ring:HEAD == req:TAIL - * as we resubmit the request. See gen8_emit_request() + * as we resubmit the request. See gen8_emit_breadcrumb() * for where we prepare the padding after the end of the * request. */ @@ -1567,7 +1567,7 @@ static void bxt_a_seqno_barrier(struct intel_engine_cs *engine) * restore with HEAD==TAIL (WaIdleLiteRestore). */ -static int gen8_emit_request(struct drm_i915_gem_request *request) +static int gen8_emit_breadcrumb(struct drm_i915_gem_request *request) { struct intel_ring *ring = request->ring; int ret; @@ -1590,7 +1590,7 @@ static int gen8_emit_request(struct drm_i915_gem_request *request) return intel_logical_ring_advance(request); } -static int gen8_emit_request_render(struct drm_i915_gem_request *request) +static int gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request) { struct intel_ring *ring = request->ring; int ret; @@ -1694,7 +1694,7 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) engine->init_hw = gen8_init_common_ring; engine->reset_hw = reset_common_ring; engine->emit_flush = gen8_emit_flush; - engine->emit_request = gen8_emit_request; + engine->emit_breadcrumb = gen8_emit_breadcrumb; engine->submit_request = execlists_submit_request; engine->irq_enable = gen8_logical_ring_enable_irq; @@ -1816,7 +1816,7 @@ int logical_render_ring_init(struct intel_engine_cs *engine) engine->init_hw = gen8_init_render_ring; engine->init_context = gen8_init_rcs_context; engine->emit_flush = gen8_emit_flush_render; - engine->emit_request = gen8_emit_request_render; + engine->emit_breadcrumb = gen8_emit_breadcrumb_render; ret = intel_engine_create_scratch(engine, 4096); if (ret) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 76c6b70303fb..54c3981cf716 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1328,7 +1328,7 @@ static void i9xx_submit_request(struct drm_i915_gem_request *request) intel_ring_offset(request->ring, request->tail)); } -static int i9xx_emit_request(struct drm_i915_gem_request *req) +static int i9xx_emit_breadcrumb(struct drm_i915_gem_request *req) { struct intel_ring *ring = req->ring; int ret; @@ -1349,14 +1349,14 @@ static int i9xx_emit_request(struct drm_i915_gem_request *req) } /** - * gen6_sema_emit_request - Update the semaphore mailbox registers + * gen6_sema_emit_breadcrumb - Update the semaphore mailbox registers * * @request - request to write to the ring * * Update the mailbox registers in the *other* rings with the current seqno. * This acts like a signal in the canonical semaphore. */ -static int gen6_sema_emit_request(struct drm_i915_gem_request *req) +static int gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req) { int ret; @@ -1364,10 +1364,10 @@ static int gen6_sema_emit_request(struct drm_i915_gem_request *req) if (ret) return ret; - return i9xx_emit_request(req); + return i9xx_emit_breadcrumb(req); } -static int gen8_render_emit_request(struct drm_i915_gem_request *req) +static int gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req) { struct intel_engine_cs *engine = req->engine; struct intel_ring *ring = req->ring; @@ -2637,9 +2637,9 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, engine->init_hw = init_ring_common; engine->reset_hw = reset_ring_common; - engine->emit_request = i9xx_emit_request; + engine->emit_breadcrumb = i9xx_emit_breadcrumb; if (i915.semaphores) - engine->emit_request = gen6_sema_emit_request; + engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; engine->submit_request = i9xx_submit_request; if (INTEL_GEN(dev_priv) >= 8) @@ -2666,7 +2666,7 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) if (INTEL_GEN(dev_priv) >= 8) { engine->init_context = intel_rcs_ctx_init; - engine->emit_request = gen8_render_emit_request; + engine->emit_breadcrumb = gen8_render_emit_breadcrumb; engine->emit_flush = gen8_render_ring_flush; if (i915.semaphores) engine->semaphore.signal = gen8_rcs_signal; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index a62e396c8863..a5ced1649ecd 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -255,7 +255,7 @@ struct intel_engine_cs { #define I915_DISPATCH_SECURE BIT(0) #define I915_DISPATCH_PINNED BIT(1) #define I915_DISPATCH_RS BIT(2) - int (*emit_request)(struct drm_i915_gem_request *req); + int (*emit_breadcrumb)(struct drm_i915_gem_request *req); /* Pass the request to the hardware queue (e.g. directly into * the legacy ringbuffer or to the end of an execlist). -- cgit v1.2.3 From 98f29e8d908f2b9e3d966f6f7d63cd69b4aaf0a2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:51 +0100 Subject: drm/i915: Record space required for breadcrumb emission In the next patch, we will use deferred breadcrumb emission. That requires reserving sufficient space in the ringbuffer to emit the breadcrumb, which first requires us to know how large the breadcrumb is. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-28-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 1 + drivers/gpu/drm/i915/intel_lrc.c | 6 ++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 29 +++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 35 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index a626b2638722..be9e23b32e4a 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -434,6 +434,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, * away, e.g. because a GPU scheduler has deferred it. */ req->reserved_space = MIN_SPACE_FOR_ADD_REQUEST; + GEM_BUG_ON(req->reserved_space < engine->emit_breadcrumb_sz); if (i915.enable_execlists) ret = intel_logical_ring_alloc_request_extras(req); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 57dba458f185..8229baebb2b3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1590,6 +1590,8 @@ static int gen8_emit_breadcrumb(struct drm_i915_gem_request *request) return intel_logical_ring_advance(request); } +static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS; + static int gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request) { struct intel_ring *ring = request->ring; @@ -1621,6 +1623,8 @@ static int gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request) return intel_logical_ring_advance(request); } +static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS; + static int gen8_init_rcs_context(struct drm_i915_gem_request *req) { int ret; @@ -1695,6 +1699,7 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) engine->reset_hw = reset_common_ring; engine->emit_flush = gen8_emit_flush; engine->emit_breadcrumb = gen8_emit_breadcrumb; + engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_sz; engine->submit_request = execlists_submit_request; engine->irq_enable = gen8_logical_ring_enable_irq; @@ -1817,6 +1822,7 @@ int logical_render_ring_init(struct intel_engine_cs *engine) engine->init_context = gen8_init_rcs_context; engine->emit_flush = gen8_emit_flush_render; engine->emit_breadcrumb = gen8_emit_breadcrumb_render; + engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_render_sz; ret = intel_engine_create_scratch(engine, 4096); if (ret) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 54c3981cf716..ae9cf6bb4def 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1348,6 +1348,8 @@ static int i9xx_emit_breadcrumb(struct drm_i915_gem_request *req) return 0; } +static const int i9xx_emit_breadcrumb_sz = 4; + /** * gen6_sema_emit_breadcrumb - Update the semaphore mailbox registers * @@ -1401,6 +1403,8 @@ static int gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req) return 0; } +static const int gen8_render_emit_breadcrumb_sz = 8; + /** * intel_ring_sync - sync the waiter to the signaller on seqno * @@ -2638,8 +2642,21 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, engine->reset_hw = reset_ring_common; engine->emit_breadcrumb = i9xx_emit_breadcrumb; - if (i915.semaphores) + engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz; + if (i915.semaphores) { + int num_rings; + engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; + + num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1; + if (INTEL_GEN(dev_priv) >= 8) { + engine->emit_breadcrumb_sz += num_rings * 6; + } else { + engine->emit_breadcrumb_sz += num_rings * 3; + if (num_rings & 1) + engine->emit_breadcrumb_sz++; + } + } engine->submit_request = i9xx_submit_request; if (INTEL_GEN(dev_priv) >= 8) @@ -2667,9 +2684,17 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) if (INTEL_GEN(dev_priv) >= 8) { engine->init_context = intel_rcs_ctx_init; engine->emit_breadcrumb = gen8_render_emit_breadcrumb; + engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz; engine->emit_flush = gen8_render_ring_flush; - if (i915.semaphores) + if (i915.semaphores) { + int num_rings; + engine->semaphore.signal = gen8_rcs_signal; + + num_rings = + hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1; + engine->emit_breadcrumb_sz += num_rings * 6; + } } else if (INTEL_GEN(dev_priv) >= 6) { engine->init_context = intel_rcs_ctx_init; engine->emit_flush = gen7_render_ring_flush; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index a5ced1649ecd..7b7aaafac0da 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -256,6 +256,7 @@ struct intel_engine_cs { #define I915_DISPATCH_PINNED BIT(1) #define I915_DISPATCH_RS BIT(2) int (*emit_breadcrumb)(struct drm_i915_gem_request *req); + int emit_breadcrumb_sz; /* Pass the request to the hardware queue (e.g. directly into * the legacy ringbuffer or to the end of an execlist). -- cgit v1.2.3 From caddfe7192f5e74d65ebcfdae614f99e8fd87222 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:52 +0100 Subject: drm/i915: Defer breadcrumb emission Move the actual emission of the breadcrumb for closing the request from i915_add_request() to the submit callback. (It can be moved later when required.) This allows us to defer the allocation of the global_seqno from request construction to actual submission, allowing us to emit the requests out of order (wrt to the order of their construction, they still will only be executed one all of their dependencies are resolved including that all earlier requests on their timeline have been submitted.) We have to specialise how we then emit the request in order to write into the preallocated space, rather than at the tail of the ringbuffer (which will have been advanced by the addition of new requests). Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-29-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 41 +++----- drivers/gpu/drm/i915/intel_lrc.c | 120 ++++++++--------------- drivers/gpu/drm/i915/intel_ringbuffer.c | 169 +++++++++++--------------------- drivers/gpu/drm/i915/intel_ringbuffer.h | 10 +- 4 files changed, 118 insertions(+), 222 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index be9e23b32e4a..06daa4d203a7 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -318,17 +318,16 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) container_of(fence, typeof(*request), submit); struct intel_engine_cs *engine = request->engine; + if (state != FENCE_COMPLETE) + return NOTIFY_DONE; + /* Will be called from irq-context when using foreign DMA fences */ - switch (state) { - case FENCE_COMPLETE: - engine->timeline->last_submitted_seqno = request->fence.seqno; - engine->submit_request(request); - break; + engine->timeline->last_submitted_seqno = request->fence.seqno; - case FENCE_FREE: - break; - } + engine->emit_breadcrumb(request, + request->ring->vaddr + request->postfix); + engine->submit_request(request); return NOTIFY_DONE; } @@ -648,9 +647,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) struct intel_ring *ring = request->ring; struct intel_timeline *timeline = request->timeline; struct drm_i915_gem_request *prev; - u32 request_start; - u32 reserved_tail; - int ret; + int err; lockdep_assert_held(&request->i915->drm.struct_mutex); trace_i915_gem_request_add(request); @@ -660,8 +657,6 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) * should already have been reserved in the ring buffer. Let the ring * know that it is time to use that space up. */ - request_start = ring->tail; - reserved_tail = request->reserved_space; request->reserved_space = 0; /* @@ -672,10 +667,10 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) * what. */ if (flush_caches) { - ret = engine->emit_flush(request, EMIT_FLUSH); + err = engine->emit_flush(request, EMIT_FLUSH); /* Not allowed to fail! */ - WARN(ret, "engine->emit_flush() failed: %d!\n", ret); + WARN(err, "engine->emit_flush() failed: %d!\n", err); } /* Record the position of the start of the breadcrumb so that @@ -683,20 +678,10 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) * GPU processing the request, we never over-estimate the * position of the ring's HEAD. */ + err = intel_ring_begin(request, engine->emit_breadcrumb_sz); + GEM_BUG_ON(err); request->postfix = ring->tail; - - /* Not allowed to fail! */ - ret = engine->emit_breadcrumb(request); - WARN(ret, "(%s)->emit_breadcrumb failed: %d!\n", engine->name, ret); - - /* Sanity check that the reserved size was large enough. */ - ret = ring->tail - request_start; - if (ret < 0) - ret += ring->size; - WARN_ONCE(ret > reserved_tail, - "Not enough space reserved (%d bytes) " - "for adding the request (%d bytes)\n", - reserved_tail, ret); + ring->tail += engine->emit_breadcrumb_sz * sizeof(u32); /* Seal the request and mark it as pending execution. Note that * we may inspect this state, without holding any locks, during diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8229baebb2b3..fa3012c342cc 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -365,7 +365,7 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq) struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt; u32 *reg_state = ce->lrc_reg_state; - reg_state[CTX_RING_TAIL+1] = intel_ring_offset(rq->ring, rq->tail); + reg_state[CTX_RING_TAIL+1] = rq->tail; /* True 32b PPGTT with dynamic page allocation: update PDP * registers and point the unallocated PDPs to scratch page. @@ -599,6 +599,15 @@ static void execlists_submit_request(struct drm_i915_gem_request *request) spin_lock_irqsave(&engine->execlist_lock, flags); + /* We keep the previous context alive until we retire the following + * request. This ensures that any the context object is still pinned + * for any residual writes the HW makes into it on the context switch + * into the next object following the breadcrumb. Otherwise, we may + * retire the context too early. + */ + request->previous_context = engine->last_context; + engine->last_context = request->ctx; + list_add_tail(&request->execlist_link, &engine->execlist_queue); if (execlists_elsp_idle(engine)) tasklet_hi_schedule(&engine->irq_tasklet); @@ -671,46 +680,6 @@ err_unpin: return ret; } -/* - * intel_logical_ring_advance() - advance the tail and prepare for submission - * @request: Request to advance the logical ringbuffer of. - * - * The tail is updated in our logical ringbuffer struct, not in the actual context. What - * really happens during submission is that the context and current tail will be placed - * on a queue waiting for the ELSP to be ready to accept a new context submission. At that - * point, the tail *inside* the context is updated and the ELSP written to. - */ -static int -intel_logical_ring_advance(struct drm_i915_gem_request *request) -{ - struct intel_ring *ring = request->ring; - struct intel_engine_cs *engine = request->engine; - - intel_ring_advance(ring); - request->tail = ring->tail; - - /* - * Here we add two extra NOOPs as padding to avoid - * lite restore of a context with HEAD==TAIL. - * - * Caller must reserve WA_TAIL_DWORDS for us! - */ - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); - request->wa_tail = ring->tail; - - /* We keep the previous context alive until we retire the following - * request. This ensures that any the context object is still pinned - * for any residual writes the HW makes into it on the context switch - * into the next object following the breadcrumb. Otherwise, we may - * retire the context too early. - */ - request->previous_context = engine->last_context; - engine->last_context = request->ctx; - return 0; -} - static int intel_lr_context_pin(struct i915_gem_context *ctx, struct intel_engine_cs *engine) { @@ -1566,41 +1535,35 @@ static void bxt_a_seqno_barrier(struct intel_engine_cs *engine) * used as a workaround for not being allowed to do lite * restore with HEAD==TAIL (WaIdleLiteRestore). */ - -static int gen8_emit_breadcrumb(struct drm_i915_gem_request *request) +static void gen8_emit_wa_tail(struct drm_i915_gem_request *request, u32 *out) { - struct intel_ring *ring = request->ring; - int ret; - - ret = intel_ring_begin(request, 6 + WA_TAIL_DWORDS); - if (ret) - return ret; + *out++ = MI_NOOP; + *out++ = MI_NOOP; + request->wa_tail = intel_ring_offset(request->ring, out); +} +static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request, + u32 *out) +{ /* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */ BUILD_BUG_ON(I915_GEM_HWS_INDEX_ADDR & (1 << 5)); - intel_ring_emit(ring, (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW); - intel_ring_emit(ring, - intel_hws_seqno_address(request->engine) | - MI_FLUSH_DW_USE_GTT); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, request->global_seqno); - intel_ring_emit(ring, MI_USER_INTERRUPT); - intel_ring_emit(ring, MI_NOOP); - return intel_logical_ring_advance(request); + *out++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW; + *out++ = intel_hws_seqno_address(request->engine) | MI_FLUSH_DW_USE_GTT; + *out++ = 0; + *out++ = request->global_seqno; + *out++ = MI_USER_INTERRUPT; + *out++ = MI_NOOP; + request->tail = intel_ring_offset(request->ring, out); + + gen8_emit_wa_tail(request, out); } static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS; -static int gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request) +static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, + u32 *out) { - struct intel_ring *ring = request->ring; - int ret; - - ret = intel_ring_begin(request, 8 + WA_TAIL_DWORDS); - if (ret) - return ret; - /* We're using qword write, seqno should be aligned to 8 bytes. */ BUILD_BUG_ON(I915_GEM_HWS_INDEX & 1); @@ -1608,19 +1571,20 @@ static int gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request) * need a prior CS_STALL, which is emitted by the flush * following the batch. */ - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); - intel_ring_emit(ring, - (PIPE_CONTROL_GLOBAL_GTT_IVB | - PIPE_CONTROL_CS_STALL | - PIPE_CONTROL_QW_WRITE)); - intel_ring_emit(ring, intel_hws_seqno_address(request->engine)); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, request->global_seqno); + *out++ = GFX_OP_PIPE_CONTROL(6); + *out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB | + PIPE_CONTROL_CS_STALL | + PIPE_CONTROL_QW_WRITE); + *out++ = intel_hws_seqno_address(request->engine); + *out++ = 0; + *out++ = request->global_seqno; /* We're thrashing one dword of HWS. */ - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_USER_INTERRUPT); - intel_ring_emit(ring, MI_NOOP); - return intel_logical_ring_advance(request); + *out++ = 0; + *out++ = MI_USER_INTERRUPT; + *out++ = MI_NOOP; + request->tail = intel_ring_offset(request->ring, out); + + gen8_emit_wa_tail(request, out); } static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index ae9cf6bb4def..16244775b9d1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1213,90 +1213,62 @@ static void render_ring_cleanup(struct intel_engine_cs *engine) i915_vma_unpin_and_release(&dev_priv->semaphore); } -static int gen8_rcs_signal(struct drm_i915_gem_request *req) +static u32 *gen8_rcs_signal(struct drm_i915_gem_request *req, u32 *out) { - struct intel_ring *ring = req->ring; struct drm_i915_private *dev_priv = req->i915; struct intel_engine_cs *waiter; enum intel_engine_id id; - int ret, num_rings; - - num_rings = INTEL_INFO(dev_priv)->num_rings; - ret = intel_ring_begin(req, (num_rings-1) * 8); - if (ret) - return ret; for_each_engine(waiter, dev_priv, id) { u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) continue; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); - intel_ring_emit(ring, - PIPE_CONTROL_GLOBAL_GTT_IVB | - PIPE_CONTROL_QW_WRITE | - PIPE_CONTROL_CS_STALL); - intel_ring_emit(ring, lower_32_bits(gtt_offset)); - intel_ring_emit(ring, upper_32_bits(gtt_offset)); - intel_ring_emit(ring, req->global_seqno); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, - MI_SEMAPHORE_SIGNAL | - MI_SEMAPHORE_TARGET(waiter->hw_id)); - intel_ring_emit(ring, 0); + *out++ = GFX_OP_PIPE_CONTROL(6); + *out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB | + PIPE_CONTROL_QW_WRITE | + PIPE_CONTROL_CS_STALL); + *out++ = lower_32_bits(gtt_offset); + *out++ = upper_32_bits(gtt_offset); + *out++ = req->global_seqno; + *out++ = 0; + *out++ = (MI_SEMAPHORE_SIGNAL | + MI_SEMAPHORE_TARGET(waiter->hw_id)); + *out++ = 0; } - intel_ring_advance(ring); - return 0; + return out; } -static int gen8_xcs_signal(struct drm_i915_gem_request *req) +static u32 *gen8_xcs_signal(struct drm_i915_gem_request *req, u32 *out) { - struct intel_ring *ring = req->ring; struct drm_i915_private *dev_priv = req->i915; struct intel_engine_cs *waiter; enum intel_engine_id id; - int ret, num_rings; - - num_rings = INTEL_INFO(dev_priv)->num_rings; - ret = intel_ring_begin(req, (num_rings-1) * 6); - if (ret) - return ret; for_each_engine(waiter, dev_priv, id) { u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) continue; - intel_ring_emit(ring, - (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW); - intel_ring_emit(ring, - lower_32_bits(gtt_offset) | - MI_FLUSH_DW_USE_GTT); - intel_ring_emit(ring, upper_32_bits(gtt_offset)); - intel_ring_emit(ring, req->global_seqno); - intel_ring_emit(ring, - MI_SEMAPHORE_SIGNAL | - MI_SEMAPHORE_TARGET(waiter->hw_id)); - intel_ring_emit(ring, 0); + *out++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW; + *out++ = lower_32_bits(gtt_offset) | MI_FLUSH_DW_USE_GTT; + *out++ = upper_32_bits(gtt_offset); + *out++ = req->global_seqno; + *out++ = (MI_SEMAPHORE_SIGNAL | + MI_SEMAPHORE_TARGET(waiter->hw_id)); + *out++ = 0; } - intel_ring_advance(ring); - return 0; + return out; } -static int gen6_signal(struct drm_i915_gem_request *req) +static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *out) { - struct intel_ring *ring = req->ring; struct drm_i915_private *dev_priv = req->i915; struct intel_engine_cs *engine; enum intel_engine_id id; - int ret, num_rings; - - num_rings = INTEL_INFO(dev_priv)->num_rings; - ret = intel_ring_begin(req, round_up((num_rings-1) * 3, 2)); - if (ret) - return ret; + int num_rings = 0; for_each_engine(engine, dev_priv, id) { i915_reg_t mbox_reg; @@ -1306,46 +1278,34 @@ static int gen6_signal(struct drm_i915_gem_request *req) mbox_reg = req->engine->semaphore.mbox.signal[engine->hw_id]; if (i915_mmio_reg_valid(mbox_reg)) { - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit_reg(ring, mbox_reg); - intel_ring_emit(ring, req->global_seqno); + *out++ = MI_LOAD_REGISTER_IMM(1); + *out++ = i915_mmio_reg_offset(mbox_reg); + *out++ = req->global_seqno; + num_rings++; } } + if (num_rings & 1) + *out++ = MI_NOOP; - /* If num_dwords was rounded, make sure the tail pointer is correct */ - if (num_rings % 2 == 0) - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); - - return 0; + return out; } static void i9xx_submit_request(struct drm_i915_gem_request *request) { struct drm_i915_private *dev_priv = request->i915; - I915_WRITE_TAIL(request->engine, - intel_ring_offset(request->ring, request->tail)); + I915_WRITE_TAIL(request->engine, request->tail); } -static int i9xx_emit_breadcrumb(struct drm_i915_gem_request *req) +static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, + u32 *out) { - struct intel_ring *ring = req->ring; - int ret; - - ret = intel_ring_begin(req, 4); - if (ret) - return ret; - - intel_ring_emit(ring, MI_STORE_DWORD_INDEX); - intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(ring, req->global_seqno); - intel_ring_emit(ring, MI_USER_INTERRUPT); - intel_ring_advance(ring); - - req->tail = ring->tail; + *out++ = MI_STORE_DWORD_INDEX; + *out++ = I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT; + *out++ = req->global_seqno; + *out++ = MI_USER_INTERRUPT; - return 0; + req->tail = intel_ring_offset(req->ring, out); } static const int i9xx_emit_breadcrumb_sz = 4; @@ -1358,49 +1318,34 @@ static const int i9xx_emit_breadcrumb_sz = 4; * Update the mailbox registers in the *other* rings with the current seqno. * This acts like a signal in the canonical semaphore. */ -static int gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req) +static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req, + u32 *out) { - int ret; - - ret = req->engine->semaphore.signal(req); - if (ret) - return ret; - - return i9xx_emit_breadcrumb(req); + return i9xx_emit_breadcrumb(req, + req->engine->semaphore.signal(req, out)); } -static int gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req) +static void gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req, + u32 *out) { struct intel_engine_cs *engine = req->engine; - struct intel_ring *ring = req->ring; - int ret; - if (engine->semaphore.signal) { - ret = engine->semaphore.signal(req); - if (ret) - return ret; - } - - ret = intel_ring_begin(req, 8); - if (ret) - return ret; + if (engine->semaphore.signal) + out = engine->semaphore.signal(req, out); - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); - intel_ring_emit(ring, (PIPE_CONTROL_GLOBAL_GTT_IVB | + *out++ = GFX_OP_PIPE_CONTROL(6); + *out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL | - PIPE_CONTROL_QW_WRITE)); - intel_ring_emit(ring, intel_hws_seqno_address(engine)); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, req->global_seqno); + PIPE_CONTROL_QW_WRITE); + *out++ = intel_hws_seqno_address(engine); + *out++ = 0; + *out++ = req->global_seqno; /* We're thrashing one dword of HWS. */ - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_USER_INTERRUPT); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); - - req->tail = ring->tail; + *out++ = 0; + *out++ = MI_USER_INTERRUPT; + *out++ = MI_NOOP; - return 0; + req->tail = intel_ring_offset(req->ring, out); } static const int gen8_render_emit_breadcrumb_sz = 8; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 7b7aaafac0da..9d228bee3511 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -255,7 +255,8 @@ struct intel_engine_cs { #define I915_DISPATCH_SECURE BIT(0) #define I915_DISPATCH_PINNED BIT(1) #define I915_DISPATCH_RS BIT(2) - int (*emit_breadcrumb)(struct drm_i915_gem_request *req); + void (*emit_breadcrumb)(struct drm_i915_gem_request *req, + u32 *out); int emit_breadcrumb_sz; /* Pass the request to the hardware queue (e.g. directly into @@ -331,7 +332,7 @@ struct intel_engine_cs { /* AKA wait() */ int (*sync_to)(struct drm_i915_gem_request *req, struct drm_i915_gem_request *signal); - int (*signal)(struct drm_i915_gem_request *req); + u32 *(*signal)(struct drm_i915_gem_request *req, u32 *out); } semaphore; /* Execlists */ @@ -487,10 +488,11 @@ static inline void intel_ring_advance(struct intel_ring *ring) */ } -static inline u32 intel_ring_offset(struct intel_ring *ring, u32 value) +static inline u32 intel_ring_offset(struct intel_ring *ring, void *addr) { /* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */ - return value & (ring->size - 1); + u32 offset = addr - ring->vaddr; + return offset & (ring->size - 1); } int __intel_ring_space(int head, int tail, int size); -- cgit v1.2.3 From 85e17f5974b357bc4a127be09de71b430be265e0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:53 +0100 Subject: drm/i915: Move the global sync optimisation to the timeline Currently we try to reduce the number of synchronisations (now the number of requests we need to wait upon) by noting that if we have earlier waited upon a request, all subsequent requests in the timeline will be after the wait. This only applies to requests in this timeline, as other timelines will not be ordered by that waiter. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-30-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 9 ------ drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_gem_request.c | 29 +++++++++++-------- drivers/gpu/drm/i915/i915_gem_timeline.h | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 48 +++++++++++++++++++------------- drivers/gpu/drm/i915/intel_engine_cs.c | 2 -- drivers/gpu/drm/i915/intel_ringbuffer.c | 3 -- drivers/gpu/drm/i915/intel_ringbuffer.h | 23 --------------- 8 files changed, 47 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 90bc4a89e0d5..4655227eb9d9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3347,15 +3347,6 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) seq_putc(m, '\n'); } - seq_puts(m, "\nSync seqno:\n"); - for_each_engine(engine, dev_priv, id) { - for (j = 0; j < num_rings; j++) - seq_printf(m, " 0x%08x ", - engine->semaphore.sync_seqno[j]); - seq_putc(m, '\n'); - } - seq_putc(m, '\n'); - intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 217674bb1495..6bf40276ace6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -802,7 +802,6 @@ struct drm_i915_error_state { u32 cpu_ring_tail; u32 last_seqno; - u32 semaphore_seqno[I915_NUM_ENGINES - 1]; /* Register state */ u32 start; diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 06daa4d203a7..9c34a4c540b5 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -238,35 +238,41 @@ static int i915_gem_check_wedge(struct drm_i915_private *dev_priv) return 0; } -static int i915_gem_init_global_seqno(struct drm_i915_private *dev_priv, - u32 seqno) +static int i915_gem_init_global_seqno(struct drm_i915_private *i915, u32 seqno) { - struct i915_gem_timeline *timeline = &dev_priv->gt.global_timeline; + struct i915_gem_timeline *timeline = &i915->gt.global_timeline; struct intel_engine_cs *engine; enum intel_engine_id id; int ret; /* Carefully retire all requests without writing to the rings */ - ret = i915_gem_wait_for_idle(dev_priv, + ret = i915_gem_wait_for_idle(i915, I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED); if (ret) return ret; - i915_gem_retire_requests(dev_priv); + i915_gem_retire_requests(i915); /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ if (!i915_seqno_passed(seqno, timeline->next_seqno)) { - while (intel_kick_waiters(dev_priv) || - intel_kick_signalers(dev_priv)) + while (intel_kick_waiters(i915) || intel_kick_signalers(i915)) yield(); yield(); } /* Finally reset hw state */ - for_each_engine(engine, dev_priv, id) + for_each_engine(engine, i915, id) intel_engine_init_global_seqno(engine, seqno); + list_for_each_entry(timeline, &i915->gt.timelines, link) { + for_each_engine(engine, i915, id) { + struct intel_timeline *tl = &timeline->engine[id]; + + memset(tl->sync_seqno, 0, sizeof(tl->sync_seqno)); + } + } + return 0; } @@ -462,7 +468,7 @@ static int i915_gem_request_await_request(struct drm_i915_gem_request *to, struct drm_i915_gem_request *from) { - int idx, ret; + int ret; GEM_BUG_ON(to == from); @@ -483,8 +489,7 @@ i915_gem_request_await_request(struct drm_i915_gem_request *to, return ret < 0 ? ret : 0; } - idx = intel_engine_sync_index(from->engine, to->engine); - if (from->global_seqno <= from->engine->semaphore.sync_seqno[idx]) + if (from->global_seqno <= to->timeline->sync_seqno[from->engine->id]) return 0; trace_i915_gem_ring_sync_to(to, from); @@ -502,7 +507,7 @@ i915_gem_request_await_request(struct drm_i915_gem_request *to, return ret; } - from->engine->semaphore.sync_seqno[idx] = from->global_seqno; + to->timeline->sync_seqno[from->engine->id] = from->global_seqno; return 0; } diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_gem_timeline.h index bfdf0331cc50..767b23914ec5 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.h +++ b/drivers/gpu/drm/i915/i915_gem_timeline.h @@ -48,6 +48,7 @@ struct intel_timeline { * struct_mutex. */ struct i915_gem_active last_request; + u32 sync_seqno[I915_NUM_ENGINES]; struct i915_gem_timeline *common; }; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 9aa197ca6210..ef3698120d92 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -415,17 +415,13 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, if (INTEL_GEN(m->i915) >= 6) { err_printf(m, " RC PSMI: 0x%08x\n", ee->rc_psmi); err_printf(m, " FAULT_REG: 0x%08x\n", ee->fault_reg); - err_printf(m, " SYNC_0: 0x%08x [last synced 0x%08x]\n", - ee->semaphore_mboxes[0], - ee->semaphore_seqno[0]); - err_printf(m, " SYNC_1: 0x%08x [last synced 0x%08x]\n", - ee->semaphore_mboxes[1], - ee->semaphore_seqno[1]); - if (HAS_VEBOX(m->i915)) { - err_printf(m, " SYNC_2: 0x%08x [last synced 0x%08x]\n", - ee->semaphore_mboxes[2], - ee->semaphore_seqno[2]); - } + err_printf(m, " SYNC_0: 0x%08x\n", + ee->semaphore_mboxes[0]); + err_printf(m, " SYNC_1: 0x%08x\n", + ee->semaphore_mboxes[1]); + if (HAS_VEBOX(m->i915)) + err_printf(m, " SYNC_2: 0x%08x\n", + ee->semaphore_mboxes[2]); } if (USES_PPGTT(m->i915)) { err_printf(m, " GFX_MODE: 0x%08x\n", ee->vm_info.gfx_mode); @@ -972,6 +968,26 @@ static void i915_gem_record_fences(struct drm_i915_private *dev_priv, } } +static inline u32 +gen8_engine_sync_index(struct intel_engine_cs *engine, + struct intel_engine_cs *other) +{ + int idx; + + /* + * rcs -> 0 = vcs, 1 = bcs, 2 = vecs, 3 = vcs2; + * vcs -> 0 = bcs, 1 = vecs, 2 = vcs2, 3 = rcs; + * bcs -> 0 = vecs, 1 = vcs2. 2 = rcs, 3 = vcs; + * vecs -> 0 = vcs2, 1 = rcs, 2 = vcs, 3 = bcs; + * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs; + */ + + idx = (other - engine) - 1; + if (idx < 0) + idx += I915_NUM_ENGINES; + + return idx; +} static void gen8_record_semaphore_state(struct drm_i915_error_state *error, struct intel_engine_cs *engine, @@ -995,10 +1011,9 @@ static void gen8_record_semaphore_state(struct drm_i915_error_state *error, signal_offset = (GEN8_SIGNAL_OFFSET(engine, id) & (PAGE_SIZE - 1)) / 4; tmp = error->semaphore->pages[0]; - idx = intel_engine_sync_index(engine, to); + idx = gen8_engine_sync_index(engine, to); ee->semaphore_mboxes[idx] = tmp[signal_offset]; - ee->semaphore_seqno[idx] = engine->semaphore.sync_seqno[idx]; } } @@ -1009,14 +1024,9 @@ static void gen6_record_semaphore_state(struct intel_engine_cs *engine, ee->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(engine->mmio_base)); ee->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(engine->mmio_base)); - ee->semaphore_seqno[0] = engine->semaphore.sync_seqno[0]; - ee->semaphore_seqno[1] = engine->semaphore.sync_seqno[1]; - - if (HAS_VEBOX(dev_priv)) { + if (HAS_VEBOX(dev_priv)) ee->semaphore_mboxes[2] = I915_READ(RING_SYNC_2(engine->mmio_base)); - ee->semaphore_seqno[2] = engine->semaphore.sync_seqno[2]; - } } static void error_record_engine_waiters(struct intel_engine_cs *engine, diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 6a3105512d18..94de3d66733d 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -204,8 +204,6 @@ void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno) I915_NUM_ENGINES * gen8_semaphore_seqno_size); kunmap(page); } - memset(engine->semaphore.sync_seqno, 0, - sizeof(engine->semaphore.sync_seqno)); intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); if (engine->irq_seqno_barrier) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 16244775b9d1..188fdec5fa6b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2003,9 +2003,6 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine) intel_engine_setup_common(engine); - memset(engine->semaphore.sync_seqno, 0, - sizeof(engine->semaphore.sync_seqno)); - ret = intel_engine_init_common(engine); if (ret) goto error; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 9d228bee3511..891629caab6c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -314,8 +314,6 @@ struct intel_engine_cs { * ie. transpose of f(x, y) */ struct { - u32 sync_seqno[I915_NUM_ENGINES-1]; - union { #define GEN6_SEMAPHORE_LAST VECS_HW #define GEN6_NUM_SEMAPHORES (GEN6_SEMAPHORE_LAST + 1) @@ -385,27 +383,6 @@ intel_engine_flag(const struct intel_engine_cs *engine) return 1 << engine->id; } -static inline u32 -intel_engine_sync_index(struct intel_engine_cs *engine, - struct intel_engine_cs *other) -{ - int idx; - - /* - * rcs -> 0 = vcs, 1 = bcs, 2 = vecs, 3 = vcs2; - * vcs -> 0 = bcs, 1 = vecs, 2 = vcs2, 3 = rcs; - * bcs -> 0 = vecs, 1 = vcs2. 2 = rcs, 3 = vcs; - * vecs -> 0 = vcs2, 1 = rcs, 2 = vcs, 3 = bcs; - * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs; - */ - - idx = (other->id - engine->id) - 1; - if (idx < 0) - idx += I915_NUM_ENGINES; - - return idx; -} - static inline void intel_flush_status_page(struct intel_engine_cs *engine, int reg) { -- cgit v1.2.3 From 562f5d45508bc376cf537d414cd944cff5e453f7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:54 +0100 Subject: drm/i915: Create a unique name for the context This will be used for communicating issues with this context to userspace, so we want to identify the parent process and the individual context. Note that the name isn't quite unique, it makes the presumption of there only being a single device fd per process. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-31-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 11 ++--------- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem_context.c | 23 ++++++++++++++++++----- 3 files changed, 21 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4655227eb9d9..f8604a09c101 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -631,17 +631,10 @@ static void print_request(struct seq_file *m, struct drm_i915_gem_request *rq, const char *prefix) { - struct pid *pid = rq->ctx->pid; - struct task_struct *task; - - rcu_read_lock(); - task = pid ? pid_task(pid, PIDTYPE_PID) : NULL; - seq_printf(m, "%s%x [%x:%x] @ %d: %s [%d]\n", prefix, + seq_printf(m, "%s%x [%x:%x] @ %d: %s\n", prefix, rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno, jiffies_to_msecs(jiffies - rq->emitted_jiffies), - task ? task->comm : "", - task ? task->pid : -1); - rcu_read_unlock(); + rq->timeline->common->name); } static int i915_gem_request_info(struct seq_file *m, void *data) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6bf40276ace6..8b987f772d47 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -937,6 +937,7 @@ struct i915_gem_context { struct drm_i915_file_private *file_priv; struct i915_hw_ppgtt *ppgtt; struct pid *pid; + const char *name; struct i915_ctx_hang_stats hang_stats; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index a2acb8bb5f34..d3118db244c4 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -158,6 +158,7 @@ void i915_gem_context_free(struct kref *ctx_ref) __i915_gem_object_release_unless_active(ce->state->obj); } + kfree(ctx->name); put_pid(ctx->pid); list_del(&ctx->link); @@ -303,19 +304,28 @@ __create_hw_context(struct drm_device *dev, } /* Default context will never have a file_priv */ - if (file_priv != NULL) { + ret = DEFAULT_CONTEXT_HANDLE; + if (file_priv) { ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_HANDLE, 0, GFP_KERNEL); if (ret < 0) goto err_out; - } else - ret = DEFAULT_CONTEXT_HANDLE; + } + ctx->user_handle = ret; ctx->file_priv = file_priv; - if (file_priv) + if (file_priv) { ctx->pid = get_task_pid(current, PIDTYPE_PID); + ctx->name = kasprintf(GFP_KERNEL, "%s[%d]/%x", + current->comm, + pid_nr(ctx->pid), + ctx->user_handle); + if (!ctx->name) { + ret = -ENOMEM; + goto err_pid; + } + } - ctx->user_handle = ret; /* NB: Mark all slices as needing a remap so that when the context first * loads it will restore whatever remap state already exists. If there * is no remap info, it will be a NOP. */ @@ -329,6 +339,9 @@ __create_hw_context(struct drm_device *dev, return ctx; +err_pid: + put_pid(ctx->pid); + idr_remove(&file_priv->context_idr, ctx->user_handle); err_out: context_close(ctx); return ERR_PTR(ret); -- cgit v1.2.3 From f6168e330438a264123d2e0b502526f06594bb51 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:55 +0100 Subject: drm/i915: Convert breadcrumbs spinlock to be irqsafe The breadcrumbs are about to be used from within IRQ context sections (e.g. nouveau signals a fence from an interrupt handler causing us to submit a new request) and/or from bottom-half tasklets (i.e. intel_lrc_irq_handler), therefore we need to employ the irqsafe spinlock variants. For example, deferring the request submission to the intel_lrc_irq_handler generates this trace: [ 66.388639] ================================= [ 66.388650] [ INFO: inconsistent lock state ] [ 66.388663] 4.9.0-rc2+ #56 Not tainted [ 66.388672] --------------------------------- [ 66.388682] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. [ 66.388695] swapper/1/0 [HC0[0]:SC1[1]:HE0:SE0] takes: [ 66.388706] (&(&b->lock)->rlock){+.?...} , at: [] intel_engine_enable_signaling+0x78/0x150 [ 66.388761] {SOFTIRQ-ON-W} state was registered at: [ 66.388772] [ 66.388783] [] __lock_acquire+0x682/0x1870 [ 66.388795] [ 66.388803] [] lock_acquire+0x6c/0xb0 [ 66.388814] [ 66.388824] [] _raw_spin_lock+0x2a/0x40 [ 66.388835] [ 66.388845] [] intel_engine_reset_breadcrumbs+0x21/0xb0 [ 66.388857] [ 66.388866] [] gen8_init_common_ring+0x67/0x100 [ 66.388878] [ 66.388887] [] gen8_init_render_ring+0x12/0x60 [ 66.388903] [ 66.388912] [] i915_gem_init_hw+0xf7/0x2a0 [ 66.388927] [ 66.388936] [] i915_gem_init+0xbb/0xf0 [ 66.388950] [ 66.388959] [] i915_driver_load+0x7e0/0x1330 [ 66.388978] [ 66.388988] [] i915_pci_probe+0x28/0x40 [ 66.389003] [ 66.389013] [] pci_device_probe+0x8b/0xf0 [ 66.389028] [ 66.389037] [] driver_probe_device+0x21e/0x430 [ 66.389056] [ 66.389065] [] __driver_attach+0xde/0xe0 [ 66.389080] [ 66.389090] [] bus_for_each_dev+0x5d/0x90 [ 66.389105] [ 66.389113] [] driver_attach+0x19/0x20 [ 66.389134] [ 66.389144] [] bus_add_driver+0x15d/0x260 [ 66.389159] [ 66.389168] [] driver_register+0x5b/0xd0 [ 66.389183] [ 66.389281] [] __pci_register_driver+0x5b/0x60 [ 66.389301] [ 66.389312] [] i915_init+0x3e/0x45 [ 66.389326] [ 66.389336] [] do_one_initcall+0x8b/0x118 [ 66.389350] [ 66.389359] [] kernel_init_freeable+0x1b3/0x23b [ 66.389378] [ 66.389387] [] kernel_init+0x9/0x100 [ 66.389402] [ 66.389411] [] ret_from_fork+0x27/0x40 [ 66.389426] irq event stamp: 315865 [ 66.389438] hardirqs last enabled at (315864): [] _raw_spin_unlock_irqrestore+0x31/0x50 [ 66.389469] hardirqs last disabled at (315865): [] _raw_spin_lock_irqsave+0x13/0x50 [ 66.389499] softirqs last enabled at (315818): [] _local_bh_enable+0x1c/0x50 [ 66.389530] softirqs last disabled at (315819): [] irq_exit+0xbe/0xd0 [ 66.389559] [ 66.389559] other info that might help us debug this: [ 66.389580] Possible unsafe locking scenario: [ 66.389580] [ 66.389598] CPU0 [ 66.389609] ---- [ 66.389620] lock(&(&b->lock)->rlock); [ 66.389650] [ 66.389661] lock(&(&b->lock)->rlock); [ 66.389690] [ 66.389690] *** DEADLOCK *** [ 66.389690] [ 66.389715] 2 locks held by swapper/1/0: [ 66.389728] #0: (&(&tl->lock)->rlock){..-...}, at: [] intel_lrc_irq_handler+0x201/0x3c0 [ 66.389785] #1: (&(&req->lock)->rlock/1){..-...}, at: [] __i915_gem_request_submit+0x8f/0x170 [ 66.389854] [ 66.389854] stack backtrace: [ 66.389959] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.9.0-rc2+ #56 [ 66.389976] Hardware name: / , BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015 [ 66.389999] ffff88027fd03c58 ffffffff812beae5 ffff88027696e680 ffffffff822afe20 [ 66.390036] ffff88027fd03ca8 ffffffff810bb420 0000000000000001 0000000000000000 [ 66.390070] 0000000000000000 0000000000000006 0000000000000004 ffff88027696ee10 [ 66.390104] Call Trace: [ 66.390117] [ 66.390128] [] dump_stack+0x68/0x93 [ 66.390147] [] print_usage_bug+0x1d0/0x1e0 [ 66.390164] [] mark_lock+0x470/0x4f0 [ 66.390181] [] ? print_shortest_lock_dependencies+0x1b0/0x1b0 [ 66.390203] [] __lock_acquire+0x59d/0x1870 [ 66.390221] [] lock_acquire+0x6c/0xb0 [ 66.390237] [] ? lock_acquire+0x6c/0xb0 [ 66.390255] [] ? intel_engine_enable_signaling+0x78/0x150 [ 66.390273] [] _raw_spin_lock+0x2a/0x40 [ 66.390291] [] ? intel_engine_enable_signaling+0x78/0x150 [ 66.390309] [] intel_engine_enable_signaling+0x78/0x150 [ 66.390327] [] __i915_gem_request_submit+0x150/0x170 [ 66.390345] [] intel_lrc_irq_handler+0x28b/0x3c0 [ 66.390363] [] tasklet_action+0x57/0xc0 [ 66.390380] [] __do_softirq+0x119/0x240 [ 66.390396] [] irq_exit+0xbe/0xd0 [ 66.390414] [] do_IRQ+0x65/0x110 [ 66.390431] [] common_interrupt+0x86/0x86 [ 66.390446] [ 66.390457] [] ? cpuidle_enter_state+0x151/0x200 [ 66.390480] [] cpuidle_enter+0x12/0x20 [ 66.390498] [] call_cpuidle+0x1e/0x40 [ 66.390516] [] cpu_startup_entry+0x10e/0x1f0 [ 66.390534] [] start_secondary+0x103/0x130 (This is split out of the defer global seqno allocation patch due to realisation that we need a more complete conversion if we want to defer request submission even further.) v2: lockdep was warning about mixed SOFTIRQ contexts not HARDIRQ contexts so we only need to use spin_lock_bh and not disable interrupts. v3: We need full irq protection as we may be called from a third party interrupt handler (via fences). Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-32-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 12 +++++------ drivers/gpu/drm/i915/i915_gpu_error.c | 8 ++++---- drivers/gpu/drm/i915/intel_breadcrumbs.c | 35 ++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 4 files changed, 33 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f8604a09c101..1723a1f5b20e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -683,14 +683,14 @@ static void i915_ring_seqno_info(struct seq_file *m, seq_printf(m, "Current sequence (%s): %x\n", engine->name, intel_engine_get_seqno(engine)); - spin_lock(&b->lock); + spin_lock_irq(&b->lock); for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { struct intel_wait *w = container_of(rb, typeof(*w), node); seq_printf(m, "Waiting (%s): %s [%d] on %x\n", engine->name, w->tsk->comm, w->tsk->pid, w->seqno); } - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); } static int i915_gem_seqno_info(struct seq_file *m, void *data) @@ -1355,14 +1355,14 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) yesno(intel_engine_has_waiter(engine)), yesno(test_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings))); - spin_lock(&b->lock); + spin_lock_irq(&b->lock); for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { struct intel_wait *w = container_of(rb, typeof(*w), node); seq_printf(m, "\t%s [%d] waiting for %x\n", w->tsk->comm, w->tsk->pid, w->seqno); } - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n", (long long)engine->hangcheck.acthd, @@ -3265,14 +3265,14 @@ static int i915_engine_info(struct seq_file *m, void *unused) I915_READ(RING_PP_DIR_DCLV(engine))); } - spin_lock(&b->lock); + spin_lock_irq(&b->lock); for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { struct intel_wait *w = container_of(rb, typeof(*w), node); seq_printf(m, "\t%s [%d] waiting for %x\n", w->tsk->comm, w->tsk->pid, w->seqno); } - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); seq_puts(m, "\n"); } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index ef3698120d92..7ba40487e345 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1043,7 +1043,7 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine, if (RB_EMPTY_ROOT(&b->waiters)) return; - if (!spin_trylock(&b->lock)) { + if (!spin_trylock_irq(&b->lock)) { ee->waiters = ERR_PTR(-EDEADLK); return; } @@ -1051,7 +1051,7 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine, count = 0; for (rb = rb_first(&b->waiters); rb != NULL; rb = rb_next(rb)) count++; - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); waiter = NULL; if (count) @@ -1061,7 +1061,7 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine, if (!waiter) return; - if (!spin_trylock(&b->lock)) { + if (!spin_trylock_irq(&b->lock)) { kfree(waiter); ee->waiters = ERR_PTR(-EDEADLK); return; @@ -1079,7 +1079,7 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine, if (++ee->num_waiters == count) break; } - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); } static void error_record_engine_registers(struct drm_i915_error_state *error, diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 0d5def0d2dfe..c410d3d6465f 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -83,16 +83,18 @@ static void irq_enable(struct intel_engine_cs *engine) */ engine->breadcrumbs.irq_posted = true; - spin_lock_irq(&engine->i915->irq_lock); + /* Caller disables interrupts */ + spin_lock(&engine->i915->irq_lock); engine->irq_enable(engine); - spin_unlock_irq(&engine->i915->irq_lock); + spin_unlock(&engine->i915->irq_lock); } static void irq_disable(struct intel_engine_cs *engine) { - spin_lock_irq(&engine->i915->irq_lock); + /* Caller disables interrupts */ + spin_lock(&engine->i915->irq_lock); engine->irq_disable(engine); - spin_unlock_irq(&engine->i915->irq_lock); + spin_unlock(&engine->i915->irq_lock); engine->breadcrumbs.irq_posted = false; } @@ -293,9 +295,9 @@ bool intel_engine_add_wait(struct intel_engine_cs *engine, struct intel_breadcrumbs *b = &engine->breadcrumbs; bool first; - spin_lock(&b->lock); + spin_lock_irq(&b->lock); first = __intel_engine_add_wait(engine, wait); - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); return first; } @@ -326,7 +328,7 @@ void intel_engine_remove_wait(struct intel_engine_cs *engine, if (RB_EMPTY_NODE(&wait->node)) return; - spin_lock(&b->lock); + spin_lock_irq(&b->lock); if (RB_EMPTY_NODE(&wait->node)) goto out_unlock; @@ -400,7 +402,7 @@ out_unlock: GEM_BUG_ON(rb_first(&b->waiters) != (b->first_wait ? &b->first_wait->node : NULL)); GEM_BUG_ON(!rcu_access_pointer(b->irq_seqno_bh) ^ RB_EMPTY_ROOT(&b->waiters)); - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); } static bool signal_complete(struct drm_i915_gem_request *request) @@ -473,14 +475,14 @@ static int intel_breadcrumbs_signaler(void *arg) * we just completed - so double check we are still * the oldest before picking the next one. */ - spin_lock(&b->lock); + spin_lock_irq(&b->lock); if (request == b->first_signal) { struct rb_node *rb = rb_next(&request->signaling.node); b->first_signal = rb ? to_signaler(rb) : NULL; } rb_erase(&request->signaling.node, &b->signals); - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); i915_gem_request_put(request); } else { @@ -502,7 +504,14 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request) struct rb_node *parent, **p; bool first, wakeup; - /* locked by dma_fence_enable_sw_signaling() */ + /* Note that we may be called from an interrupt handler on another + * device (e.g. nouveau signaling a fence completion causing us + * to submit a request, and so enable signaling). As such, + * we need to make sure that all other users of b->lock protect + * against interrupts, i.e. use spin_lock_irqsave. + */ + + /* locked by dma_fence_enable_sw_signaling() (irqsafe fence->lock) */ assert_spin_locked(&request->lock); if (!request->global_seqno) return; @@ -594,7 +603,7 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) struct intel_breadcrumbs *b = &engine->breadcrumbs; cancel_fake_irq(engine); - spin_lock(&b->lock); + spin_lock_irq(&b->lock); __intel_breadcrumbs_disable_irq(b); if (intel_engine_has_waiter(engine)) { @@ -607,7 +616,7 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) irq_disable(engine); } - spin_unlock(&b->lock); + spin_unlock_irq(&b->lock); } void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 891629caab6c..d16c74ae8f54 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -207,7 +207,7 @@ struct intel_engine_cs { struct task_struct __rcu *irq_seqno_bh; /* bh for interrupts */ bool irq_posted; - spinlock_t lock; /* protects the lists of requests */ + spinlock_t lock; /* protects the lists of requests; irqsafe */ struct rb_root waiters; /* sorted by retirement, priority */ struct rb_root signals; /* sorted by retirement */ struct intel_wait *first_wait; /* oldest waiter by retirement */ -- cgit v1.2.3 From 28176ef4cfa510e5f1498bbf39ff1e4afd0b085d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:56 +0100 Subject: drm/i915: Reserve space in the global seqno during request allocation A restriction on our global seqno is that they cannot wrap, and that we cannot use the value 0. This allows us to detect when a request has not yet been submitted, its global seqno is still 0, and ensures that hardware semaphores are monotonic as required by older hardware. To meet these restrictions when we defer the assignment of the global seqno, we must check that we have an available slot in the global seqno space during request construction. If that test fails, we wait for all requests to be completed and reset the hardware back to 0. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-33-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 10 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 7 ++- drivers/gpu/drm/i915/i915_gem_request.c | 86 +++++++++++++++++--------------- drivers/gpu/drm/i915/i915_gem_timeline.h | 2 +- 5 files changed, 55 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1723a1f5b20e..9bef6f55f99d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -552,7 +552,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) seq_printf(m, "Flip queued on %s at seqno %x, next seqno %x [current breadcrumb %x], completed? %d\n", engine->name, i915_gem_request_get_seqno(work->flip_queued_req), - dev_priv->gt.global_timeline.next_seqno, + atomic_read(&dev_priv->gt.global_timeline.next_seqno), intel_engine_get_seqno(engine), i915_gem_request_completed(work->flip_queued_req)); } else @@ -1046,7 +1046,7 @@ i915_next_seqno_get(void *data, u64 *val) { struct drm_i915_private *dev_priv = data; - *val = READ_ONCE(dev_priv->gt.global_timeline.next_seqno); + *val = atomic_read(&dev_priv->gt.global_timeline.next_seqno); return 0; } @@ -2277,8 +2277,8 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) struct drm_file *file; seq_printf(m, "RPS enabled? %d\n", dev_priv->rps.enabled); - seq_printf(m, "GPU busy? %s [%x]\n", - yesno(dev_priv->gt.awake), dev_priv->gt.active_engines); + seq_printf(m, "GPU busy? %s [%d requests]\n", + yesno(dev_priv->gt.awake), dev_priv->gt.active_requests); seq_printf(m, "CPU waiting? %d\n", count_irq_waiters(dev_priv)); seq_printf(m, "Frequency requested %d\n", intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); @@ -2313,7 +2313,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) if (INTEL_GEN(dev_priv) >= 6 && dev_priv->rps.enabled && - dev_priv->gt.active_engines) { + dev_priv->gt.active_requests) { u32 rpup, rpupei; u32 rpdown, rpdownei; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8b987f772d47..eacb144af29e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2092,6 +2092,7 @@ struct drm_i915_private { struct list_head timelines; struct i915_gem_timeline global_timeline; + u32 active_requests; /** * Is the GPU currently considered idle, or busy executing @@ -2100,7 +2101,6 @@ struct drm_i915_private { * In order to reduce the effect on performance, there * is a slight delay before we do so. */ - unsigned int active_engines; bool awake; /** diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f4cfb88bd804..8a5d20715e5f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2688,8 +2688,6 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine) memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); spin_unlock(&engine->execlist_lock); } - - engine->i915->gt.active_engines &= ~intel_engine_flag(engine); } void i915_gem_set_wedged(struct drm_i915_private *dev_priv) @@ -2746,7 +2744,7 @@ i915_gem_idle_work_handler(struct work_struct *work) if (!READ_ONCE(dev_priv->gt.awake)) return; - if (READ_ONCE(dev_priv->gt.active_engines)) + if (READ_ONCE(dev_priv->gt.active_requests)) return; rearm_hangcheck = @@ -2760,7 +2758,7 @@ i915_gem_idle_work_handler(struct work_struct *work) goto out_rearm; } - if (dev_priv->gt.active_engines) + if (dev_priv->gt.active_requests) goto out_unlock; for_each_engine(engine, dev_priv, id) @@ -4399,6 +4397,7 @@ int i915_gem_suspend(struct drm_device *dev) goto err; i915_gem_retire_requests(dev_priv); + GEM_BUG_ON(dev_priv->gt.active_requests); assert_kernel_context_is_current(dev_priv); i915_gem_context_lost(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 9c34a4c540b5..9b22f66464f0 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -159,6 +159,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) */ list_del(&request->ring_link); request->ring->last_retired_head = request->postfix; + request->i915->gt.active_requests--; /* Walk through the active list, calling retire on each. This allows * objects to track their GPU activity and mark themselves as idle @@ -253,13 +254,15 @@ static int i915_gem_init_global_seqno(struct drm_i915_private *i915, u32 seqno) return ret; i915_gem_retire_requests(i915); + GEM_BUG_ON(i915->gt.active_requests > 1); /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ - if (!i915_seqno_passed(seqno, timeline->next_seqno)) { + if (!i915_seqno_passed(seqno, atomic_read(&timeline->next_seqno))) { while (intel_kick_waiters(i915) || intel_kick_signalers(i915)) yield(); yield(); } + atomic_set(&timeline->next_seqno, seqno); /* Finally reset hw state */ for_each_engine(engine, i915, id) @@ -279,7 +282,6 @@ static int i915_gem_init_global_seqno(struct drm_i915_private *i915, u32 seqno) int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno) { struct drm_i915_private *dev_priv = to_i915(dev); - int ret; lockdep_assert_held(&dev_priv->drm.struct_mutex); @@ -289,34 +291,33 @@ int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno) /* HWS page needs to be set less than what we * will inject to ring */ - ret = i915_gem_init_global_seqno(dev_priv, seqno - 1); - if (ret) - return ret; - - dev_priv->gt.global_timeline.next_seqno = seqno; - return 0; + return i915_gem_init_global_seqno(dev_priv, seqno - 1); } -static int i915_gem_get_global_seqno(struct drm_i915_private *dev_priv, - u32 *seqno) +static int reserve_global_seqno(struct drm_i915_private *i915) { - struct i915_gem_timeline *tl = &dev_priv->gt.global_timeline; - - /* reserve 0 for non-seqno */ - if (unlikely(tl->next_seqno == 0)) { - int ret; + u32 active_requests = ++i915->gt.active_requests; + u32 next_seqno = atomic_read(&i915->gt.global_timeline.next_seqno); + int ret; - ret = i915_gem_init_global_seqno(dev_priv, 0); - if (ret) - return ret; + /* Reservation is fine until we need to wrap around */ + if (likely(next_seqno + active_requests > next_seqno)) + return 0; - tl->next_seqno = 1; + ret = i915_gem_init_global_seqno(i915, 0); + if (ret) { + i915->gt.active_requests--; + return ret; } - *seqno = tl->next_seqno++; return 0; } +static u32 timeline_get_seqno(struct i915_gem_timeline *tl) +{ + return atomic_inc_return(&tl->next_seqno); +} + static int __i915_sw_fence_call submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { @@ -356,9 +357,10 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, { struct drm_i915_private *dev_priv = engine->i915; struct drm_i915_gem_request *req; - u32 seqno; int ret; + lockdep_assert_held(&dev_priv->drm.struct_mutex); + /* ABI: Before userspace accesses the GPU (e.g. execbuffer), report * EIO if the GPU is already wedged, or EAGAIN to drop the struct_mutex * and restart. @@ -367,6 +369,10 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, if (ret) return ERR_PTR(ret); + ret = reserve_global_seqno(dev_priv); + if (ret) + return ERR_PTR(ret); + /* Move the oldest request to the slab-cache (if not in use!) */ req = list_first_entry_or_null(&engine->timeline->requests, typeof(*req), link); @@ -402,12 +408,10 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, * Do not use kmem_cache_zalloc() here! */ req = kmem_cache_alloc(dev_priv->requests, GFP_KERNEL); - if (!req) - return ERR_PTR(-ENOMEM); - - ret = i915_gem_get_global_seqno(dev_priv, &seqno); - if (ret) - goto err; + if (!req) { + ret = -ENOMEM; + goto err_unreserve; + } req->timeline = engine->timeline; @@ -416,14 +420,14 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, &i915_fence_ops, &req->lock, req->timeline->fence_context, - seqno); + timeline_get_seqno(req->timeline->common)); i915_sw_fence_init(&req->submit, submit_notify); INIT_LIST_HEAD(&req->active_list); req->i915 = dev_priv; req->engine = engine; - req->global_seqno = seqno; + req->global_seqno = req->fence.seqno; req->ctx = i915_gem_context_get(ctx); /* No zalloc, must clear what we need by hand */ @@ -459,8 +463,9 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, err_ctx: i915_gem_context_put(ctx); -err: kmem_cache_free(dev_priv->requests, req); +err_unreserve: + dev_priv->gt.active_requests--; return ERR_PTR(ret); } @@ -624,7 +629,6 @@ static void i915_gem_mark_busy(const struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; - dev_priv->gt.active_engines |= intel_engine_flag(engine); if (dev_priv->gt.awake) return; @@ -700,6 +704,9 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, &request->submitq); + GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno, + request->fence.seqno)); + request->emitted_jiffies = jiffies; request->previous_seqno = timeline->last_pending_seqno; timeline->last_pending_seqno = request->fence.seqno; @@ -962,38 +969,35 @@ complete: return timeout; } -static bool engine_retire_requests(struct intel_engine_cs *engine) +static void engine_retire_requests(struct intel_engine_cs *engine) { struct drm_i915_gem_request *request, *next; list_for_each_entry_safe(request, next, &engine->timeline->requests, link) { if (!i915_gem_request_completed(request)) - return false; + return; i915_gem_request_retire(request); } - - return true; } void i915_gem_retire_requests(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; - unsigned int tmp; + enum intel_engine_id id; lockdep_assert_held(&dev_priv->drm.struct_mutex); - if (dev_priv->gt.active_engines == 0) + if (!dev_priv->gt.active_requests) return; GEM_BUG_ON(!dev_priv->gt.awake); - for_each_engine_masked(engine, dev_priv, dev_priv->gt.active_engines, tmp) - if (engine_retire_requests(engine)) - dev_priv->gt.active_engines &= ~intel_engine_flag(engine); + for_each_engine(engine, dev_priv, id) + engine_retire_requests(engine); - if (dev_priv->gt.active_engines == 0) + if (!dev_priv->gt.active_requests) queue_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, msecs_to_jiffies(100)); diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_gem_timeline.h index 767b23914ec5..18e603980dd9 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.h +++ b/drivers/gpu/drm/i915/i915_gem_timeline.h @@ -55,7 +55,7 @@ struct intel_timeline { struct i915_gem_timeline { struct list_head link; - u32 next_seqno; + atomic_t next_seqno; struct drm_i915_private *i915; const char *name; -- cgit v1.2.3 From f2d13290e3275df34c0cd625fbc665965af08c67 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:57 +0100 Subject: drm/i915: Defer setting of global seqno on request to submission Defer the assignment of the global seqno on a request to its submission. In the next patch, we will only allocate the global seqno at that time, here we are just enabling the wait-for-submission before wait-for-seqno paths. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-34-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 9b22f66464f0..7499e3b205c6 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -324,14 +324,32 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) struct drm_i915_gem_request *request = container_of(fence, typeof(*request), submit); struct intel_engine_cs *engine = request->engine; + struct intel_timeline *timeline; + u32 seqno; if (state != FENCE_COMPLETE) return NOTIFY_DONE; /* Will be called from irq-context when using foreign DMA fences */ - engine->timeline->last_submitted_seqno = request->fence.seqno; + timeline = request->timeline; + seqno = request->fence.seqno; + GEM_BUG_ON(!seqno); + GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno)); + + GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno, seqno)); + request->previous_seqno = timeline->last_submitted_seqno; + timeline->last_submitted_seqno = seqno; + + /* We may be recursing from the signal callback of another i915 fence */ + spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); + request->global_seqno = seqno; + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) + intel_engine_enable_signaling(request); + spin_unlock(&request->lock); + + GEM_BUG_ON(!request->global_seqno); engine->emit_breadcrumb(request, request->ring->vaddr + request->postfix); engine->submit_request(request); @@ -427,10 +445,10 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, INIT_LIST_HEAD(&req->active_list); req->i915 = dev_priv; req->engine = engine; - req->global_seqno = req->fence.seqno; req->ctx = i915_gem_context_get(ctx); /* No zalloc, must clear what we need by hand */ + req->global_seqno = 0; req->previous_context = NULL; req->file_priv = NULL; req->batch = NULL; @@ -704,15 +722,13 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, &request->submitq); - GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno, - request->fence.seqno)); + list_add_tail(&request->link, &timeline->requests); - request->emitted_jiffies = jiffies; - request->previous_seqno = timeline->last_pending_seqno; timeline->last_pending_seqno = request->fence.seqno; i915_gem_active_set(&timeline->last_request, request); - list_add_tail(&request->link, &timeline->requests); + list_add_tail(&request->ring_link, &ring->request_list); + request->emitted_jiffies = jiffies; i915_gem_mark_busy(engine); -- cgit v1.2.3 From 80b204bce8f27b52cd65839e0e6144b4452ae3de Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 28 Oct 2016 13:58:58 +0100 Subject: drm/i915: Enable multiple timelines With the infrastructure converted over to tracking multiple timelines in the GEM API whilst preserving the efficiency of using a single execution timeline internally, we can now assign a separate timeline to every context with full-ppgtt. v2: Add a comment to indicate the xfer between timelines upon submission. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-35-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 10 ++++++ drivers/gpu/drm/i915/i915_gem.c | 10 +++--- drivers/gpu/drm/i915/i915_gem_context.c | 4 +-- drivers/gpu/drm/i915/i915_gem_evict.c | 11 +++--- drivers/gpu/drm/i915/i915_gem_gtt.c | 19 ++++++---- drivers/gpu/drm/i915/i915_gem_gtt.h | 4 ++- drivers/gpu/drm/i915/i915_gem_request.c | 61 +++++++++++++++++--------------- drivers/gpu/drm/i915/i915_gem_timeline.c | 1 + drivers/gpu/drm/i915/i915_gem_timeline.h | 3 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 5 --- 10 files changed, 77 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eacb144af29e..42a499681966 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3549,6 +3549,16 @@ static inline void i915_gem_context_put(struct i915_gem_context *ctx) kref_put(&ctx->ref, i915_gem_context_free); } +static inline struct intel_timeline * +i915_gem_context_lookup_timeline(struct i915_gem_context *ctx, + struct intel_engine_cs *engine) +{ + struct i915_address_space *vm; + + vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base; + return &vm->timeline.engine[engine->id]; +} + static inline bool i915_gem_context_is_default(const struct i915_gem_context *c) { return c->user_handle == DEFAULT_CONTEXT_HANDLE; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8a5d20715e5f..1e5d2bf777e4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2564,12 +2564,9 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) * not need an engine->irq_seqno_barrier() before the seqno reads. */ list_for_each_entry(request, &engine->timeline->requests, link) { - if (i915_gem_request_completed(request)) + if (__i915_gem_request_completed(request)) continue; - if (!i915_sw_fence_done(&request->submit)) - break; - return request; } @@ -2597,6 +2594,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) { struct drm_i915_gem_request *request; struct i915_gem_context *incomplete_ctx; + struct intel_timeline *timeline; bool ring_hung; if (engine->irq_seqno_barrier) @@ -2635,6 +2633,10 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) list_for_each_entry_continue(request, &engine->timeline->requests, link) if (request->ctx == incomplete_ctx) reset_request(request); + + timeline = i915_gem_context_lookup_timeline(incomplete_ctx, engine); + list_for_each_entry(request, &timeline->requests, link) + reset_request(request); } void i915_gem_reset(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index d3118db244c4..461aece6c5bd 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -365,9 +365,9 @@ i915_gem_create_context(struct drm_device *dev, return ctx; if (USES_FULL_PPGTT(dev)) { - struct i915_hw_ppgtt *ppgtt = - i915_ppgtt_create(to_i915(dev), file_priv); + struct i915_hw_ppgtt *ppgtt; + ppgtt = i915_ppgtt_create(to_i915(dev), file_priv, ctx->name); if (IS_ERR(ppgtt)) { DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n", PTR_ERR(ppgtt)); diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 79b964152cd9..bd08814b015c 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -33,14 +33,17 @@ #include "intel_drv.h" #include "i915_trace.h" -static bool -gpu_is_idle(struct drm_i915_private *dev_priv) +static bool ggtt_is_idle(struct drm_i915_private *dev_priv) { + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct intel_engine_cs *engine; enum intel_engine_id id; for_each_engine(engine, dev_priv, id) { - if (intel_engine_is_active(engine)) + struct intel_timeline *tl; + + tl = &ggtt->base.timeline.engine[engine->id]; + if (i915_gem_active_isset(&tl->last_request)) return false; } @@ -154,7 +157,7 @@ search_again: if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK) return -ENOSPC; - if (gpu_is_idle(dev_priv)) { + if (ggtt_is_idle(dev_priv)) { /* If we still have pending pageflip completions, drop * back to userspace to give our workqueues time to * acquire our locks and unpin the old scanouts. diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1b1a459e2b68..e7afad585929 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2185,8 +2185,10 @@ static int __hw_ppgtt_init(struct i915_hw_ppgtt *ppgtt, } static void i915_address_space_init(struct i915_address_space *vm, - struct drm_i915_private *dev_priv) + struct drm_i915_private *dev_priv, + const char *name) { + i915_gem_timeline_init(dev_priv, &vm->timeline, name); drm_mm_init(&vm->mm, vm->start, vm->total); INIT_LIST_HEAD(&vm->active_list); INIT_LIST_HEAD(&vm->inactive_list); @@ -2215,14 +2217,15 @@ static void gtt_write_workarounds(struct drm_device *dev) static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt, struct drm_i915_private *dev_priv, - struct drm_i915_file_private *file_priv) + struct drm_i915_file_private *file_priv, + const char *name) { int ret; ret = __hw_ppgtt_init(ppgtt, dev_priv); if (ret == 0) { kref_init(&ppgtt->ref); - i915_address_space_init(&ppgtt->base, dev_priv); + i915_address_space_init(&ppgtt->base, dev_priv, name); ppgtt->base.file = file_priv; } @@ -2258,7 +2261,8 @@ int i915_ppgtt_init_hw(struct drm_device *dev) struct i915_hw_ppgtt * i915_ppgtt_create(struct drm_i915_private *dev_priv, - struct drm_i915_file_private *fpriv) + struct drm_i915_file_private *fpriv, + const char *name) { struct i915_hw_ppgtt *ppgtt; int ret; @@ -2267,7 +2271,7 @@ i915_ppgtt_create(struct drm_i915_private *dev_priv, if (!ppgtt) return ERR_PTR(-ENOMEM); - ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv); + ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv, name); if (ret) { kfree(ppgtt); return ERR_PTR(ret); @@ -2290,6 +2294,7 @@ void i915_ppgtt_release(struct kref *kref) WARN_ON(!list_empty(&ppgtt->base.inactive_list)); WARN_ON(!list_empty(&ppgtt->base.unbound_list)); + i915_gem_timeline_fini(&ppgtt->base.timeline); list_del(&ppgtt->base.global_link); drm_mm_takedown(&ppgtt->base.mm); @@ -3232,11 +3237,13 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv) /* Subtract the guard page before address space initialization to * shrink the range used by drm_mm. */ + mutex_lock(&dev_priv->drm.struct_mutex); ggtt->base.total -= PAGE_SIZE; - i915_address_space_init(&ggtt->base, dev_priv); + i915_address_space_init(&ggtt->base, dev_priv, "[global]"); ggtt->base.total += PAGE_SIZE; if (!HAS_LLC(dev_priv)) ggtt->base.mm.color_adjust = i915_gtt_color_adjust; + mutex_unlock(&dev_priv->drm.struct_mutex); if (!io_mapping_init_wc(&dev_priv->ggtt.mappable, dev_priv->ggtt.mappable_base, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 9f0327e5176a..518e75b64290 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -342,6 +342,7 @@ struct i915_pml4 { struct i915_address_space { struct drm_mm mm; + struct i915_gem_timeline timeline; struct drm_device *dev; /* Every address space belongs to a struct file - except for the global * GTT that is owned by the driver (and so @file is set to NULL). In @@ -613,7 +614,8 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv); int i915_ppgtt_init_hw(struct drm_device *dev); void i915_ppgtt_release(struct kref *kref); struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv, - struct drm_i915_file_private *fpriv); + struct drm_i915_file_private *fpriv, + const char *name); static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt) { if (ppgtt) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 7499e3b205c6..79b0046d9a57 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -34,12 +34,6 @@ static const char *i915_fence_get_driver_name(struct dma_fence *fence) static const char *i915_fence_get_timeline_name(struct dma_fence *fence) { - /* Timelines are bound by eviction to a VM. However, since - * we only have a global seqno at the moment, we only have - * a single timeline. Note that each timeline will have - * multiple execution contexts (fence contexts) as we allow - * engines within a single timeline to execute in parallel. - */ return to_request(fence)->timeline->common->name; } @@ -64,18 +58,6 @@ static signed long i915_fence_wait(struct dma_fence *fence, return i915_wait_request(to_request(fence), interruptible, timeout); } -static void i915_fence_value_str(struct dma_fence *fence, char *str, int size) -{ - snprintf(str, size, "%u", fence->seqno); -} - -static void i915_fence_timeline_value_str(struct dma_fence *fence, char *str, - int size) -{ - snprintf(str, size, "%u", - intel_engine_get_seqno(to_request(fence)->engine)); -} - static void i915_fence_release(struct dma_fence *fence) { struct drm_i915_gem_request *req = to_request(fence); @@ -90,8 +72,6 @@ const struct dma_fence_ops i915_fence_ops = { .signaled = i915_fence_signaled, .wait = i915_fence_wait, .release = i915_fence_release, - .fence_value_str = i915_fence_value_str, - .timeline_value_str = i915_fence_timeline_value_str, }; int i915_gem_request_add_to_client(struct drm_i915_gem_request *req, @@ -147,7 +127,10 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) GEM_BUG_ON(!i915_gem_request_completed(request)); trace_i915_gem_request_retire(request); + + spin_lock_irq(&request->engine->timeline->lock); list_del_init(&request->link); + spin_unlock_irq(&request->engine->timeline->lock); /* We know the GPU must have read the request to have * sent us the seqno + interrupt, so use the position @@ -313,6 +296,12 @@ static int reserve_global_seqno(struct drm_i915_private *i915) return 0; } +static u32 __timeline_get_seqno(struct i915_gem_timeline *tl) +{ + /* next_seqno only incremented under a mutex */ + return ++tl->next_seqno.counter; +} + static u32 timeline_get_seqno(struct i915_gem_timeline *tl) { return atomic_inc_return(&tl->next_seqno); @@ -325,16 +314,20 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) container_of(fence, typeof(*request), submit); struct intel_engine_cs *engine = request->engine; struct intel_timeline *timeline; + unsigned long flags; u32 seqno; if (state != FENCE_COMPLETE) return NOTIFY_DONE; - /* Will be called from irq-context when using foreign DMA fences */ + /* Transfer from per-context onto the global per-engine timeline */ + timeline = engine->timeline; + GEM_BUG_ON(timeline == request->timeline); - timeline = request->timeline; + /* Will be called from irq-context when using foreign DMA fences */ + spin_lock_irqsave(&timeline->lock, flags); - seqno = request->fence.seqno; + seqno = timeline_get_seqno(timeline->common); GEM_BUG_ON(!seqno); GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno)); @@ -354,6 +347,12 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) request->ring->vaddr + request->postfix); engine->submit_request(request); + spin_lock_nested(&request->timeline->lock, SINGLE_DEPTH_NESTING); + list_move_tail(&request->link, &timeline->requests); + spin_unlock(&request->timeline->lock); + + spin_unlock_irqrestore(&timeline->lock, flags); + return NOTIFY_DONE; } @@ -394,7 +393,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, /* Move the oldest request to the slab-cache (if not in use!) */ req = list_first_entry_or_null(&engine->timeline->requests, typeof(*req), link); - if (req && i915_gem_request_completed(req)) + if (req && __i915_gem_request_completed(req)) i915_gem_request_retire(req); /* Beware: Dragons be flying overhead. @@ -431,14 +430,15 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, goto err_unreserve; } - req->timeline = engine->timeline; + req->timeline = i915_gem_context_lookup_timeline(ctx, engine); + GEM_BUG_ON(req->timeline == engine->timeline); spin_lock_init(&req->lock); dma_fence_init(&req->fence, &i915_fence_ops, &req->lock, req->timeline->fence_context, - timeline_get_seqno(req->timeline->common)); + __timeline_get_seqno(req->timeline->common)); i915_sw_fence_init(&req->submit, submit_notify); @@ -722,9 +722,14 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, &request->submitq); + spin_lock_irq(&timeline->lock); list_add_tail(&request->link, &timeline->requests); + spin_unlock_irq(&timeline->lock); + + GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno, + request->fence.seqno)); - timeline->last_pending_seqno = request->fence.seqno; + timeline->last_submitted_seqno = request->fence.seqno; i915_gem_active_set(&timeline->last_request, request); list_add_tail(&request->ring_link, &ring->request_list); @@ -991,7 +996,7 @@ static void engine_retire_requests(struct intel_engine_cs *engine) list_for_each_entry_safe(request, next, &engine->timeline->requests, link) { - if (!i915_gem_request_completed(request)) + if (!__i915_gem_request_completed(request)) return; i915_gem_request_retire(request); diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.c b/drivers/gpu/drm/i915/i915_gem_timeline.c index a1bd03d10852..fc8f13a79f8f 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.c +++ b/drivers/gpu/drm/i915/i915_gem_timeline.c @@ -48,6 +48,7 @@ int i915_gem_timeline_init(struct drm_i915_private *i915, tl->fence_context = fences++; tl->common = timeline; + spin_lock_init(&tl->lock); init_request_active(&tl->last_request, NULL); INIT_LIST_HEAD(&tl->requests); } diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_gem_timeline.h index 18e603980dd9..f2bf7b1d49a1 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.h +++ b/drivers/gpu/drm/i915/i915_gem_timeline.h @@ -34,7 +34,8 @@ struct i915_gem_timeline; struct intel_timeline { u64 fence_context; u32 last_submitted_seqno; - u32 last_pending_seqno; + + spinlock_t lock; /** * List of breadcrumbs associated with GPU requests currently diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index d16c74ae8f54..43f61aa24ed7 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -569,9 +569,4 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); unsigned int intel_kick_waiters(struct drm_i915_private *i915); unsigned int intel_kick_signalers(struct drm_i915_private *i915); -static inline bool intel_engine_is_active(struct intel_engine_cs *engine) -{ - return i915_gem_active_isset(&engine->timeline->last_request); -} - #endif /* _INTEL_RINGBUFFER_H_ */ -- cgit v1.2.3 From 6a84fb4b4e439a8ef0ce19ec7e7661ad76f655c9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 28 Oct 2016 14:34:51 -0700 Subject: device-dax: check devm_nsio_enable() return value If the dax_pmem driver is passed a resource that is already busy the driver probe attempt should fail with a message like the following: dax_pmem dax0.1: could not reserve region [mem 0x100000000-0x11fffffff] However, if we do not catch the error we crash for the obvious reason of accessing memory that is not mapped. BUG: unable to handle kernel paging request at ffffc90020001000 IP: [] __memcpy+0x12/0x20 [..] Call Trace: [] ? nsio_rw_bytes+0x60/0x180 [] nd_pfn_validate+0x75/0x320 [] nvdimm_setup_pfn+0xb9/0x5d0 [] ? devm_nsio_enable+0xff/0x110 [] dax_pmem_probe+0x59/0x260 Cc: Fixes: ab68f2622136 ("/dev/dax, pmem: direct access to persistent memory") Reported-by: Dave Hansen Signed-off-by: Dan Williams --- drivers/dax/pmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c index 4a15fa5df98b..73c6ce93a0d9 100644 --- a/drivers/dax/pmem.c +++ b/drivers/dax/pmem.c @@ -78,7 +78,9 @@ static int dax_pmem_probe(struct device *dev) nsio = to_nd_namespace_io(&ndns->dev); /* parse the 'pfn' info block via ->rw_bytes */ - devm_nsio_enable(dev, nsio); + rc = devm_nsio_enable(dev, nsio); + if (rc) + return rc; altmap = nvdimm_setup_pfn(nd_pfn, &res, &__altmap); if (IS_ERR(altmap)) return PTR_ERR(altmap); -- cgit v1.2.3 From c73d2e8462d0bb1d47b0e8f6a33d97ab9a154824 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Wed, 14 Sep 2016 16:24:31 -0700 Subject: i40e: Fix client interaction This patch fixes a problem in the client interface that was causing random stack traces in RDMA driver load and unload tests. This patch fixes the problem by checking for an existing client before trying to open it. Without this patch, there is a timing related null pointer deref. Change-ID: Ib73d30671a27f6f9770dd53b3e5292b88d6b62da Signed-off-by: Carolyn Wyborny Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_client.c | 29 ++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c index 250db0b244b7..6ffac03d5015 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_client.c +++ b/drivers/net/ethernet/intel/i40e/i40e_client.c @@ -565,7 +565,7 @@ void i40e_client_subtask(struct i40e_pf *pf) if (test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state)) continue; } else { - dev_warn(&pf->pdev->dev, "This client %s is being instanciated at probe\n", + dev_warn(&pf->pdev->dev, "This client %s is being instantiated at probe\n", client->name); } @@ -582,24 +582,21 @@ void i40e_client_subtask(struct i40e_pf *pf) dev_info(&pf->pdev->dev, "Added instance of Client %s to PF%d bus=0x%02x func=0x%02x\n", client->name, pf->hw.pf_id, pf->hw.bus.device, pf->hw.bus.func); - } - - mutex_lock(&i40e_client_instance_mutex); - /* Send an Open request to the client */ - atomic_inc(&cdev->ref_cnt); - if (client->ops && client->ops->open) - ret = client->ops->open(&cdev->lan_info, client); - atomic_dec(&cdev->ref_cnt); - if (!ret) { + mutex_lock(&i40e_client_instance_mutex); + atomic_inc(&cdev->ref_cnt); + if (client->ops && client->ops->open) + ret = client->ops->open(&cdev->lan_info, + client); + atomic_dec(&cdev->ref_cnt); + if (ret < 0) { + mutex_unlock(&i40e_client_instance_mutex); + i40e_client_del_instance(pf, client); + atomic_dec(&client->ref_cnt); + continue; + } set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state); - } else { - /* remove client instance */ mutex_unlock(&i40e_client_instance_mutex); - i40e_client_del_instance(pf, client); - atomic_dec(&client->ref_cnt); - continue; } - mutex_unlock(&i40e_client_instance_mutex); } mutex_unlock(&i40e_client_mutex); } -- cgit v1.2.3 From ed245406da1409437f9d2c4e7c69112fb255964c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 14 Sep 2016 16:24:32 -0700 Subject: i40e: Rewrite Flow Director busy wait loop We can reorder the busy wait loop at the start of the Flow Director transmit function to reduce the overall code size while still retaining the same functionality. As such I am taking advantage of the opportunity to do so. Change-ID: I34c403ca001953c6ac9816e65d5305e73d869026 Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 6287bf63c43c..af36c44c4844 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -122,7 +122,6 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, struct device *dev; dma_addr_t dma; u32 td_cmd = 0; - u16 delay = 0; u16 i; /* find existing FDIR VSI */ @@ -137,15 +136,11 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, dev = tx_ring->dev; /* we need two descriptors to add/del a filter and we can wait */ - do { - if (I40E_DESC_UNUSED(tx_ring) > 1) - break; + for (i = I40E_FD_CLEAN_DELAY; I40E_DESC_UNUSED(tx_ring) < 2; i--) { + if (!i) + return -EAGAIN; msleep_interruptible(1); - delay++; - } while (delay < I40E_FD_CLEAN_DELAY); - - if (!(I40E_DESC_UNUSED(tx_ring) > 1)) - return -EAGAIN; + } dma = dma_map_single(dev, raw_packet, I40E_FDIR_MAX_RAW_PACKET_SIZE, DMA_TO_DEVICE); -- cgit v1.2.3 From 7ed3573223dd6bf36b1bd35c8e5e3d0cd4f6f690 Mon Sep 17 00:00:00 2001 From: Filip Sadowski Date: Wed, 14 Sep 2016 16:24:33 -0700 Subject: i40e: Bit test mask correction Incorrect bit mask was used for testing "get link status" response. Instead of I40E_AQ_LSE_ENABLE (which is actually 0x03) it most probably should be I40E_AQ_LSE_IS_ENABLED (which is defined as 0x01). Change-ID: Ia199142906720507f847de3a33a25c61a9781b2f Signed-off-by: Filip Sadowski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 2154a34c1dd8..fe8100bb1027 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1849,7 +1849,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, else hw_link_info->crc_enable = false; - if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_ENABLE)) + if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_IS_ENABLED)) hw_link_info->lse_enable = true; else hw_link_info->lse_enable = false; -- cgit v1.2.3 From dc7621205a93a00a898c193cf985c4c1a65a47d6 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 14 Sep 2016 16:24:34 -0700 Subject: i40e: Remove unused function i40e_vsi_lookup The function is not used so there is no need to carry it forward. I have plans to add a slightly different function that can be inlined to handle the same kind of functionality. Change-ID: Ie2dfcb189dc75e5fbc156bac23003e3b4210ae0f Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 -- drivers/net/ethernet/intel/i40e/i40e_client.c | 31 --------------------------- 2 files changed, 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 2030d7c1dc94..34c7a5d395f7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -728,8 +728,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi); struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, u16 uplink, u32 param1); int i40e_vsi_release(struct i40e_vsi *vsi); -struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type, - struct i40e_vsi *start_vsi); #ifdef I40E_FCOE void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt, diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c index 6ffac03d5015..417ac1646bc6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_client.c +++ b/drivers/net/ethernet/intel/i40e/i40e_client.c @@ -405,37 +405,6 @@ int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id, return capable; } -/** - * i40e_vsi_lookup - finds a matching VSI from the PF list starting at start_vsi - * @pf: board private structure - * @type: vsi type - * @start_vsi: a VSI pointer from where to start the search - * - * Returns non NULL on success or NULL for failure - **/ -struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, - enum i40e_vsi_type type, - struct i40e_vsi *start_vsi) -{ - struct i40e_vsi *vsi; - int i = 0; - - if (start_vsi) { - for (i = 0; i < pf->num_alloc_vsi; i++) { - vsi = pf->vsi[i]; - if (vsi == start_vsi) - break; - } - } - for (; i < pf->num_alloc_vsi; i++) { - vsi = pf->vsi[i]; - if (vsi && vsi->type == type) - return vsi; - } - - return NULL; -} - /** * i40e_client_add_instance - add a client instance struct to the instance list * @pf: pointer to the board struct -- cgit v1.2.3 From e1da71ca88170d1a6232951294b44dc0c824e464 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 14 Sep 2016 16:24:35 -0700 Subject: i40e: Drop code for unsupported flow types We cannot currently support SCTP in the hardware, and IPV4_FLOW is not used anywhere by the software so we can go through and drop the functionality related to these two flow types. In addition we cannot support masking based on the protocol value so if the user is expecting a value other than TCP or UDP we should simply return an error rather then trying to allocate a filter for a rule that will only partially match what the user requested. Change-ID: I10d52bb97d8104d76255fe244551814ff9531a63 Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 31 +++++------------------------ 1 file changed, 5 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index af36c44c4844..7d160c9497b7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -330,22 +330,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, return err ? -EOPNOTSUPP : 0; } -/** - * i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for - * a specific flow spec - * @vsi: pointer to the targeted VSI - * @fd_data: the flow director data required for the FDir descriptor - * @add: true adds a filter, false removes it - * - * Returns 0 if the filters were successfully added or removed - **/ -static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi, - struct i40e_fdir_filter *fd_data, - bool add) -{ - return -EOPNOTSUPP; -} - #define I40E_IP_DUMMY_PACKET_LEN 34 /** * i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for @@ -428,12 +412,6 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi, case UDP_V4_FLOW: ret = i40e_add_del_fdir_udpv4(vsi, input, add); break; - case SCTP_V4_FLOW: - ret = i40e_add_del_fdir_sctpv4(vsi, input, add); - break; - case IPV4_FLOW: - ret = i40e_add_del_fdir_ipv4(vsi, input, add); - break; case IP_USER_FLOW: switch (input->ip4_proto) { case IPPROTO_TCP: @@ -442,15 +420,16 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi, case IPPROTO_UDP: ret = i40e_add_del_fdir_udpv4(vsi, input, add); break; - case IPPROTO_SCTP: - ret = i40e_add_del_fdir_sctpv4(vsi, input, add); - break; - default: + case IPPROTO_IP: ret = i40e_add_del_fdir_ipv4(vsi, input, add); break; + default: + /* We cannot support masking based on protocol */ + goto unsupported_flow; } break; default: +unsupported_flow: dev_info(&pf->pdev->dev, "Could not specify spec type %d\n", input->flow_type); ret = -EINVAL; -- cgit v1.2.3 From 7be96322a57a3612ea7640e6ff56030a7350fd7f Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 14 Sep 2016 16:24:36 -0700 Subject: i40e: reopen client after reset Allow the client interface to reopen existing clients if they were closed. This allows clients to recover from reset, which is essential for supporting VF RDMA. In one instance, the driver was not clearing the open bit when the client was closed. Add the code to clear this bit so that the state is accurate and the driver will not attempt to reopen already-open clients. Remove the ref_cnt variable; it was just getting in the way and was not being used consistently. Change-ID: Ic71af4553b096963ac0c56a997f887c9a4ed162d Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_client.c | 47 ++++++++++----------------- drivers/net/ethernet/intel/i40e/i40e_client.h | 2 -- 2 files changed, 17 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c index 417ac1646bc6..7fe72abc0b4a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_client.c +++ b/drivers/net/ethernet/intel/i40e/i40e_client.c @@ -287,6 +287,7 @@ void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset) } cdev->client->ops->close(&cdev->lan_info, cdev->client, reset); + clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state); i40e_client_release_qvlist(&cdev->lan_info); } } @@ -544,28 +545,27 @@ void i40e_client_subtask(struct i40e_pf *pf) continue; if (!existing) { - /* Also up the ref_cnt for no. of instances of this - * client. - */ - atomic_inc(&client->ref_cnt); dev_info(&pf->pdev->dev, "Added instance of Client %s to PF%d bus=0x%02x func=0x%02x\n", client->name, pf->hw.pf_id, pf->hw.bus.device, pf->hw.bus.func); - mutex_lock(&i40e_client_instance_mutex); - atomic_inc(&cdev->ref_cnt); + } + + mutex_lock(&i40e_client_instance_mutex); + if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, + &cdev->state)) { + /* Send an Open request to the client */ if (client->ops && client->ops->open) ret = client->ops->open(&cdev->lan_info, client); - atomic_dec(&cdev->ref_cnt); - if (ret < 0) { - mutex_unlock(&i40e_client_instance_mutex); + if (!ret) { + set_bit(__I40E_CLIENT_INSTANCE_OPENED, + &cdev->state); + } else { + /* remove client instance */ i40e_client_del_instance(pf, client); - atomic_dec(&client->ref_cnt); - continue; } - set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state); - mutex_unlock(&i40e_client_instance_mutex); } + mutex_unlock(&i40e_client_instance_mutex); } mutex_unlock(&i40e_client_mutex); } @@ -660,10 +660,6 @@ static int i40e_client_release(struct i40e_client *client) continue; pf = (struct i40e_pf *)cdev->lan_info.pf; if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) { - if (atomic_read(&cdev->ref_cnt) > 0) { - ret = I40E_ERR_NOT_READY; - goto out; - } if (client->ops && client->ops->close) client->ops->close(&cdev->lan_info, client, false); @@ -676,11 +672,9 @@ static int i40e_client_release(struct i40e_client *client) } /* delete the client instance from the list */ list_move(&cdev->list, &cdevs_tmp); - atomic_dec(&client->ref_cnt); dev_info(&pf->pdev->dev, "Deleted client instance of Client %s\n", client->name); } -out: mutex_unlock(&i40e_client_instance_mutex); /* free the client device and release its vsi */ @@ -1006,17 +1000,10 @@ int i40e_unregister_client(struct i40e_client *client) ret = -ENODEV; goto out; } - if (atomic_read(&client->ref_cnt) == 0) { - clear_bit(__I40E_CLIENT_REGISTERED, &client->state); - list_del(&client->list); - pr_info("i40e: Unregistered client %s with return code %d\n", - client->name, ret); - } else { - ret = I40E_ERR_NOT_READY; - pr_err("i40e: Client %s failed unregister - client has open instances\n", - client->name); - } - + clear_bit(__I40E_CLIENT_REGISTERED, &client->state); + list_del(&client->list); + pr_info("i40e: Unregistered client %s with return code %d\n", + client->name, ret); out: mutex_unlock(&i40e_client_mutex); return ret; diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.h b/drivers/net/ethernet/intel/i40e/i40e_client.h index 38a6c36a6a0e..528bd79b05fe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_client.h +++ b/drivers/net/ethernet/intel/i40e/i40e_client.h @@ -203,8 +203,6 @@ struct i40e_client_instance { struct i40e_info lan_info; struct i40e_client *client; unsigned long state; - /* A count of all the in-progress calls to the client */ - atomic_t ref_cnt; }; struct i40e_client { -- cgit v1.2.3 From 6d6fd1be2a1052cbe5b04c3678b30925a9344ac7 Mon Sep 17 00:00:00 2001 From: Preethi Banala Date: Wed, 14 Sep 2016 16:24:37 -0700 Subject: i40e: group base mode VF offload flags Group together the minimum set of offload capabilities that are always supported by VF in base mode. This define would be used by PF to make sure VF in base mode gets minimum of base capabilities . Change-ID: Id5e8f22ba169c8f0a38d22fc36b2cb531c02582c Signed-off-by: Preethi Banala Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl.h | 4 ++++ drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h index f861d3109d1a..974ba2baf6ea 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h @@ -165,6 +165,10 @@ struct i40e_virtchnl_vsi_resource { #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF 0X00080000 #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM 0X00100000 +#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \ + I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \ + I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) + struct i40e_virtchnl_vf_resource { u16 num_vsis; u16 num_queue_pairs; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h index bd691ad86673..fc374f833aa9 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h @@ -162,6 +162,10 @@ struct i40e_virtchnl_vsi_resource { #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF 0X00080000 #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM 0X00100000 +#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \ + I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \ + I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) + struct i40e_virtchnl_vf_resource { u16 num_vsis; u16 num_queue_pairs; -- cgit v1.2.3 From 96db776a368263bcce9f7eb12e878b0aef1a1974 Mon Sep 17 00:00:00 2001 From: Alan Brady Date: Wed, 14 Sep 2016 16:24:38 -0700 Subject: i40e/i40evf: fix interrupt affinity bug There exists a bug in which a 'perfect storm' can occur and cause interrupts to fail to be correctly affinitized. This causes unexpected behavior and has a substantial impact on performance when it happens. The bug occurs if there is heavy traffic, any number of CPUs that have an i40e interrupt are pegged at 100%, and the interrupt afffinity for those CPUs is changed. Instead of moving to the new CPU, the interrupt continues to be polled while there is heavy traffic. The bug is most readily realized as the driver is first brought up and all interrupts start on CPU0. If there is heavy traffic and the interrupt starts polling before the interrupt is affinitized, the interrupt will be stuck on CPU0 until traffic stops. The bug, however, can also be wrought out more simply by affinitizing all the interrupts to a single CPU and then attempting to move any of those interrupts off while there is heavy traffic. This patch fixes the bug by registering for update notifications from the kernel when the interrupt affinity changes. When that fires, we cache the intended affinity mask. Then, while polling, if the cpu is pegged at 100% and we failed to clean the rings, we check to make sure we have the correct affinity and stop polling if we're firing on the wrong CPU. When the kernel successfully moves the interrupt, it will start polling on the correct CPU. The performance impact is minimal since the only time this section gets executed is when performance is already compromised by the CPU. Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830 Signed-off-by: Alan Brady Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 + drivers/net/ethernet/intel/i40e/i40e_main.c | 64 +++++++++++++++++----- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 36 ++++++++++--- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 31 +++++++++-- drivers/net/ethernet/intel/i40evf/i40evf.h | 3 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 71 +++++++++++++++++-------- 6 files changed, 159 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 34c7a5d395f7..01cce5bab861 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -607,6 +607,8 @@ struct i40e_q_vector { unsigned long hung_detected; /* Set/Reset for hung_detection logic */ cpumask_t affinity_mask; + struct irq_affinity_notify affinity_notify; + struct rcu_head rcu; /* to avoid race with update stats on free */ char name[I40E_INT_NAME_STR_LEN]; bool arm_wb_state; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 83edbe8e3618..9382ba80b70c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3316,6 +3316,33 @@ static irqreturn_t i40e_msix_clean_rings(int irq, void *data) return IRQ_HANDLED; } +/** + * i40e_irq_affinity_notify - Callback for affinity changes + * @notify: context as to what irq was changed + * @mask: the new affinity mask + * + * This is a callback function used by the irq_set_affinity_notifier function + * so that we may register to receive changes to the irq affinity masks. + **/ +static void i40e_irq_affinity_notify(struct irq_affinity_notify *notify, + const cpumask_t *mask) +{ + struct i40e_q_vector *q_vector = + container_of(notify, struct i40e_q_vector, affinity_notify); + + q_vector->affinity_mask = *mask; +} + +/** + * i40e_irq_affinity_release - Callback for affinity notifier release + * @ref: internal core kernel usage + * + * This is a callback function used by the irq_set_affinity_notifier function + * to inform the current notification subscriber that they will no longer + * receive notifications. + **/ +static void i40e_irq_affinity_release(struct kref *ref) {} + /** * i40e_vsi_request_irq_msix - Initialize MSI-X interrupts * @vsi: the VSI being configured @@ -3331,10 +3358,13 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename) int rx_int_idx = 0; int tx_int_idx = 0; int vector, err; + int irq_num; for (vector = 0; vector < q_vectors; vector++) { struct i40e_q_vector *q_vector = vsi->q_vectors[vector]; + irq_num = pf->msix_entries[base + vector].vector; + if (q_vector->tx.ring && q_vector->rx.ring) { snprintf(q_vector->name, sizeof(q_vector->name) - 1, "%s-%s-%d", basename, "TxRx", rx_int_idx++); @@ -3349,7 +3379,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename) /* skip this unused q_vector */ continue; } - err = request_irq(pf->msix_entries[base + vector].vector, + err = request_irq(irq_num, vsi->irq_handler, 0, q_vector->name, @@ -3359,9 +3389,13 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename) "MSIX request_irq failed, error: %d\n", err); goto free_queue_irqs; } + + /* register for affinity change notifications */ + q_vector->affinity_notify.notify = i40e_irq_affinity_notify; + q_vector->affinity_notify.release = i40e_irq_affinity_release; + irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify); /* assign the mask for this irq */ - irq_set_affinity_hint(pf->msix_entries[base + vector].vector, - &q_vector->affinity_mask); + irq_set_affinity_hint(irq_num, &q_vector->affinity_mask); } vsi->irqs_ready = true; @@ -3370,10 +3404,10 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename) free_queue_irqs: while (vector) { vector--; - irq_set_affinity_hint(pf->msix_entries[base + vector].vector, - NULL); - free_irq(pf->msix_entries[base + vector].vector, - &(vsi->q_vectors[vector])); + irq_num = pf->msix_entries[base + vector].vector; + irq_set_affinity_notifier(irq_num, NULL); + irq_set_affinity_hint(irq_num, NULL); + free_irq(irq_num, &vsi->q_vectors[vector]); } return err; } @@ -4012,19 +4046,23 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi) vsi->irqs_ready = false; for (i = 0; i < vsi->num_q_vectors; i++) { - u16 vector = i + base; + int irq_num; + u16 vector; + + vector = i + base; + irq_num = pf->msix_entries[vector].vector; /* free only the irqs that were actually requested */ if (!vsi->q_vectors[i] || !vsi->q_vectors[i]->num_ringpairs) continue; + /* clear the affinity notifier in the IRQ descriptor */ + irq_set_affinity_notifier(irq_num, NULL); /* clear the affinity_mask in the IRQ descriptor */ - irq_set_affinity_hint(pf->msix_entries[vector].vector, - NULL); - synchronize_irq(pf->msix_entries[vector].vector); - free_irq(pf->msix_entries[vector].vector, - vsi->q_vectors[i]); + irq_set_affinity_hint(irq_num, NULL); + synchronize_irq(irq_num); + free_irq(irq_num, vsi->q_vectors[i]); /* Tear down the interrupt queue link list * diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 7d160c9497b7..48e65335373f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1999,12 +1999,25 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) /* If work not completed, return budget and polling will return */ if (!clean_complete) { + const cpumask_t *aff_mask = &q_vector->affinity_mask; + int cpu_id = smp_processor_id(); + + /* It is possible that the interrupt affinity has changed but, + * if the cpu is pegged at 100%, polling will never exit while + * traffic continues and the interrupt will be stuck on this + * cpu. We check to make sure affinity is correct before we + * continue to poll, otherwise we must stop polling so the + * interrupt can move to the correct cpu. + */ + if (likely(cpumask_test_cpu(cpu_id, aff_mask) || + !(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))) { tx_only: - if (arm_wb) { - q_vector->tx.ring[0].tx_stats.tx_force_wb++; - i40e_enable_wb_on_itr(vsi, q_vector); + if (arm_wb) { + q_vector->tx.ring[0].tx_stats.tx_force_wb++; + i40e_enable_wb_on_itr(vsi, q_vector); + } + return budget; } - return budget; } if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR) @@ -2012,11 +2025,18 @@ tx_only: /* Work is done so exit the polling mode and re-enable the interrupt */ napi_complete_done(napi, work_done); - if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) { - i40e_update_enable_itr(vsi, q_vector); - } else { /* Legacy mode */ + + /* If we're prematurely stopping polling to fix the interrupt + * affinity we want to make sure polling starts back up so we + * issue a call to i40e_force_wb which triggers a SW interrupt. + */ + if (!clean_complete) + i40e_force_wb(vsi, q_vector); + else if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED)) i40e_irq_dynamic_enable_icr0(vsi->back, false); - } + else + i40e_update_enable_itr(vsi, q_vector); + return 0; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 75f2a2cdd738..dd8ad6b989db 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1461,12 +1461,24 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) /* If work not completed, return budget and polling will return */ if (!clean_complete) { + const cpumask_t *aff_mask = &q_vector->affinity_mask; + int cpu_id = smp_processor_id(); + + /* It is possible that the interrupt affinity has changed but, + * if the cpu is pegged at 100%, polling will never exit while + * traffic continues and the interrupt will be stuck on this + * cpu. We check to make sure affinity is correct before we + * continue to poll, otherwise we must stop polling so the + * interrupt can move to the correct cpu. + */ + if (likely(cpumask_test_cpu(cpu_id, aff_mask))) { tx_only: - if (arm_wb) { - q_vector->tx.ring[0].tx_stats.tx_force_wb++; - i40e_enable_wb_on_itr(vsi, q_vector); + if (arm_wb) { + q_vector->tx.ring[0].tx_stats.tx_force_wb++; + i40e_enable_wb_on_itr(vsi, q_vector); + } + return budget; } - return budget; } if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR) @@ -1474,7 +1486,16 @@ tx_only: /* Work is done so exit the polling mode and re-enable the interrupt */ napi_complete_done(napi, work_done); - i40e_update_enable_itr(vsi, q_vector); + + /* If we're prematurely stopping polling to fix the interrupt + * affinity we want to make sure polling starts back up so we + * issue a call to i40evf_force_wb which triggers a SW interrupt. + */ + if (!clean_complete) + i40evf_force_wb(vsi, q_vector); + else + i40e_update_enable_itr(vsi, q_vector); + return 0; } diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index c5fd724313c7..fffe4cf2c20b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -107,7 +107,8 @@ struct i40e_q_vector { int v_idx; /* vector index in list */ char name[IFNAMSIZ + 9]; bool arm_wb_state; - cpumask_var_t affinity_mask; + cpumask_t affinity_mask; + struct irq_affinity_notify affinity_notify; }; /* Helper macros to switch between ints/sec and what the register uses. diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 777eb29e4ff7..e95e87381962 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -495,6 +495,33 @@ static void i40evf_netpoll(struct net_device *netdev) } #endif +/** + * i40evf_irq_affinity_notify - Callback for affinity changes + * @notify: context as to what irq was changed + * @mask: the new affinity mask + * + * This is a callback function used by the irq_set_affinity_notifier function + * so that we may register to receive changes to the irq affinity masks. + **/ +static void i40evf_irq_affinity_notify(struct irq_affinity_notify *notify, + const cpumask_t *mask) +{ + struct i40e_q_vector *q_vector = + container_of(notify, struct i40e_q_vector, affinity_notify); + + q_vector->affinity_mask = *mask; +} + +/** + * i40evf_irq_affinity_release - Callback for affinity notifier release + * @ref: internal core kernel usage + * + * This is a callback function used by the irq_set_affinity_notifier function + * to inform the current notification subscriber that they will no longer + * receive notifications. + **/ +static void i40evf_irq_affinity_release(struct kref *ref) {} + /** * i40evf_request_traffic_irqs - Initialize MSI-X interrupts * @adapter: board private structure @@ -507,6 +534,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename) { int vector, err, q_vectors; int rx_int_idx = 0, tx_int_idx = 0; + int irq_num; i40evf_irq_disable(adapter); /* Decrement for Other and TCP Timer vectors */ @@ -514,6 +542,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename) for (vector = 0; vector < q_vectors; vector++) { struct i40e_q_vector *q_vector = &adapter->q_vectors[vector]; + irq_num = adapter->msix_entries[vector + NONQ_VECS].vector; if (q_vector->tx.ring && q_vector->rx.ring) { snprintf(q_vector->name, sizeof(q_vector->name) - 1, @@ -532,21 +561,23 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename) /* skip this unused q_vector */ continue; } - err = request_irq( - adapter->msix_entries[vector + NONQ_VECS].vector, - i40evf_msix_clean_rings, - 0, - q_vector->name, - q_vector); + err = request_irq(irq_num, + i40evf_msix_clean_rings, + 0, + q_vector->name, + q_vector); if (err) { dev_info(&adapter->pdev->dev, "Request_irq failed, error: %d\n", err); goto free_queue_irqs; } + /* register for affinity change notifications */ + q_vector->affinity_notify.notify = i40evf_irq_affinity_notify; + q_vector->affinity_notify.release = + i40evf_irq_affinity_release; + irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify); /* assign the mask for this irq */ - irq_set_affinity_hint( - adapter->msix_entries[vector + NONQ_VECS].vector, - q_vector->affinity_mask); + irq_set_affinity_hint(irq_num, &q_vector->affinity_mask); } return 0; @@ -554,11 +585,10 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename) free_queue_irqs: while (vector) { vector--; - irq_set_affinity_hint( - adapter->msix_entries[vector + NONQ_VECS].vector, - NULL); - free_irq(adapter->msix_entries[vector + NONQ_VECS].vector, - &adapter->q_vectors[vector]); + irq_num = adapter->msix_entries[vector + NONQ_VECS].vector; + irq_set_affinity_notifier(irq_num, NULL); + irq_set_affinity_hint(irq_num, NULL); + free_irq(irq_num, &adapter->q_vectors[vector]); } return err; } @@ -599,16 +629,15 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter) **/ static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter) { - int i; - int q_vectors; + int vector, irq_num, q_vectors; q_vectors = adapter->num_msix_vectors - NONQ_VECS; - for (i = 0; i < q_vectors; i++) { - irq_set_affinity_hint(adapter->msix_entries[i+1].vector, - NULL); - free_irq(adapter->msix_entries[i+1].vector, - &adapter->q_vectors[i]); + for (vector = 0; vector < q_vectors; vector++) { + irq_num = adapter->msix_entries[vector + NONQ_VECS].vector; + irq_set_affinity_notifier(irq_num, NULL); + irq_set_affinity_hint(irq_num, NULL); + free_irq(irq_num, &adapter->q_vectors[vector]); } } -- cgit v1.2.3 From 4adbb642eaf53dfe2ea0a4170d8df95d115c12ac Mon Sep 17 00:00:00 2001 From: Bimmy Pujari Date: Wed, 14 Sep 2016 16:24:39 -0700 Subject: i40e/i40evf: Changed version from 1.6.16 to 1.6.19 Signed-off-by: Bimmy Pujari Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 9382ba80b70c..c25247fa3814 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -41,7 +41,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 6 -#define DRV_VERSION_BUILD 16 +#define DRV_VERSION_BUILD 19 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index e95e87381962..3e51ff2f48f8 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -38,7 +38,7 @@ static const char i40evf_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 6 -#define DRV_VERSION_BUILD 16 +#define DRV_VERSION_BUILD 19 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) \ -- cgit v1.2.3 From fe180a5e275adc7430ada9e4881dcca5ea1a8037 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 26 Sep 2016 20:17:01 -0700 Subject: i40e: Make struct i40e_stats const Move some data to text $ size drivers/net/ethernet/intel/i40e/i40e_ethtool.o* text data bss dec hex filename 25012 0 32 25044 61d4 drivers/net/ethernet/intel/i40e/i40e_ethtool.o.new 22868 2120 32 25020 61bc drivers/net/ethernet/intel/i40e/i40e_ethtool.o.old Signed-off-by: Joe Perches Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 92bc8846f1ba..3a1f91efcae2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -104,7 +104,7 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = { * The PF_STATs are appended to the netdev stats only when ethtool -S * is queried on the base PF netdev, not on the VMDq or FCoE netdev. */ -static struct i40e_stats i40e_gstrings_stats[] = { +static const struct i40e_stats i40e_gstrings_stats[] = { I40E_PF_STAT("rx_bytes", stats.eth.rx_bytes), I40E_PF_STAT("tx_bytes", stats.eth.tx_bytes), I40E_PF_STAT("rx_unicast", stats.eth.rx_unicast), -- cgit v1.2.3 From 128150576f85b2745d849aba43980683a6267e50 Mon Sep 17 00:00:00 2001 From: Lihong Yang Date: Tue, 27 Sep 2016 11:28:48 -0700 Subject: i40e: fix confusing dmesg info for ethtool -L option Ethtool -L option with the combined parameter is for changing the number of multi-purpose channels of the specified network device. The pre-set maximum for the combined channels is cpu dependent. Currently, for an i40e device, when the user sets a value between 64 and the maximum that the cpu can support for the combined parameter, the i40e driver displays the confusing info in dmesg to only show 64 as the RSS count regardless of what the accepted user input is as long as it is larger than 64. This patch fixes the message in the i40e driver when the user uses ethtool -L to change the number of the combined channels to consistently display the user requested value if it is valid and accepted by ethtool. Change-ID: Ia80a68bc844b779a49e0f76e7d3dcc915032d9af Signed-off-by: Lihong Yang Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c25247fa3814..a4bae0a4e8ad 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8400,8 +8400,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count) i40e_pf_config_rss(pf); } - dev_info(&pf->pdev->dev, "RSS count/HW max RSS count: %d/%d\n", - pf->alloc_rss_size, pf->rss_size_max); + dev_info(&pf->pdev->dev, "User requested queue count/HW max RSS count: %d/%d\n", + vsi->req_queue_pairs, pf->rss_size_max); return pf->alloc_rss_size; } -- cgit v1.2.3 From 99dad8b34c687cb8c4975fbabced76db35f88c14 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 27 Sep 2016 11:28:50 -0700 Subject: i40e: Drop redundant Rx descriptor processing code This patch cleans up several pieces of redundant code in the Rx clean-up paths. The first bit is that hdr_addr and the status_err_len portions of the Rx descriptor represent the same value. As such there is no point in setting them to 0 before setting them to 0. I'm dropping the second spot where we are updating the value to 0 so that we only have 1 write for this value instead of 2. The second piece is the checking for the DD bit in the packet. We only need to check for a non-zero value for the status_err_len because if the device is done with the descriptor it will have written something back and the DD is just one piece of it. In addition I have moved the reading of the Rx descriptor bits related to rx_ptype down so that they are actually below the dma_rmb() call so that we are guaranteed that we don't have any funky 64b on 32b calls causing any ordering issues. Change-ID: I256e44a025d3c64a7224aaaec37c852bfcb1871b Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 18 ++++++------------ drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 18 ++++++------------ 2 files changed, 12 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 48e65335373f..daade4fe80d6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1220,7 +1220,6 @@ bool i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count) * because each write-back erases this info. */ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); - rx_desc->read.hdr_addr = 0; rx_desc++; bi++; @@ -1741,7 +1740,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) while (likely(total_rx_packets < budget)) { union i40e_rx_desc *rx_desc; struct sk_buff *skb; - u32 rx_status; u16 vlan_tag; u8 rx_ptype; u64 qword; @@ -1755,21 +1753,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean); - qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); - rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> - I40E_RXD_QW1_PTYPE_SHIFT; - rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> - I40E_RXD_QW1_STATUS_SHIFT; - - if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT))) - break; - /* status_error_len will always be zero for unused descriptors * because it's cleared in cleanup, and overlaps with hdr_addr * which is always zero because packet split isn't used, if the * hardware wrote DD then it will be non-zero */ - if (!rx_desc->wb.qword1.status_error_len) + if (!i40e_test_staterr(rx_desc, + BIT(I40E_RX_DESC_STATUS_DD_SHIFT))) break; /* This memory barrier is needed to keep us from reading @@ -1803,6 +1793,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; + qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); + rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> + I40E_RXD_QW1_PTYPE_SHIFT; + /* populate checksum, VLAN, and protocol */ i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index dd8ad6b989db..e2d362238fd7 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -705,7 +705,6 @@ bool i40evf_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count) * because each write-back erases this info. */ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); - rx_desc->read.hdr_addr = 0; rx_desc++; bi++; @@ -1209,7 +1208,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) while (likely(total_rx_packets < budget)) { union i40e_rx_desc *rx_desc; struct sk_buff *skb; - u32 rx_status; u16 vlan_tag; u8 rx_ptype; u64 qword; @@ -1223,21 +1221,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean); - qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); - rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> - I40E_RXD_QW1_PTYPE_SHIFT; - rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> - I40E_RXD_QW1_STATUS_SHIFT; - - if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT))) - break; - /* status_error_len will always be zero for unused descriptors * because it's cleared in cleanup, and overlaps with hdr_addr * which is always zero because packet split isn't used, if the * hardware wrote DD then it will be non-zero */ - if (!rx_desc->wb.qword1.status_error_len) + if (!i40e_test_staterr(rx_desc, + BIT(I40E_RX_DESC_STATUS_DD_SHIFT))) break; /* This memory barrier is needed to keep us from reading @@ -1271,6 +1261,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; + qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); + rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> + I40E_RXD_QW1_PTYPE_SHIFT; + /* populate checksum, VLAN, and protocol */ i40evf_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype); -- cgit v1.2.3 From ab425cb7ffdb024a45b0b3bcbf58d52ead3c347c Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Tue, 27 Sep 2016 11:28:52 -0700 Subject: i40e: Fix for long link down notification time This patch fixes a problem where it could take a very long time (>100 msec) to print the link down notification. This problem is fixed by changing how often we update link info from fw, when link is down. Without this patch, it can take over 100msec to notify user link is down. Change-ID: Ib876eb30834c7080792becd13ee093b9cbb35d78 Signed-off-by: Carolyn Wyborny Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index fe8100bb1027..a47594603d69 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2494,7 +2494,10 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw) if (status) return status; - if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) { + /* extra checking needed to ensure link info to user is timely */ + if ((hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) && + ((hw->phy.link_info.link_info & I40E_AQ_LINK_UP) || + !(hw->phy.link_info_old.link_info & I40E_AQ_LINK_UP))) { status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, NULL); if (status) -- cgit v1.2.3 From 53cb6e9e8949b13f63db0bc96f8fcc249763acfb Mon Sep 17 00:00:00 2001 From: Filip Sadowski Date: Tue, 27 Sep 2016 11:28:53 -0700 Subject: i40e: Removal of workaround for simple MAC address filter deletion This is code refactoring. This patch removes the workaround which deleted a default MAC filter added by the firmware when the interface was brought up. This filter caused frames to pass disregarding the VLAN tagging. It used to be automatically applied after reset in pre-SRA FW versions. This workaround is not needed in production NICs and hence can be removed. Change-ID: I129fe1aae1f17b5a224c9b29a996d916aa1be1ec Signed-off-by: Filip Sadowski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 41 ----------------------------- 1 file changed, 41 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index a4bae0a4e8ad..2e787ffb47ce 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1286,39 +1286,6 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, return -ENOENT; } -/** - * i40e_rm_default_mac_filter - Remove the default MAC filter set by NVM - * @vsi: the PF Main VSI - inappropriate for any other VSI - * @macaddr: the MAC address - * - * Remove whatever filter the firmware set up so the driver can manage - * its own filtering intelligently. - **/ -static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr) -{ - struct i40e_aqc_remove_macvlan_element_data element; - struct i40e_pf *pf = vsi->back; - - /* Only appropriate for the PF main VSI */ - if (vsi->type != I40E_VSI_MAIN) - return; - - memset(&element, 0, sizeof(element)); - ether_addr_copy(element.mac_addr, macaddr); - element.vlan_tag = 0; - /* Ignore error returns, some firmware does it this way... */ - element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; - i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL); - - memset(&element, 0, sizeof(element)); - ether_addr_copy(element.mac_addr, macaddr); - element.vlan_tag = 0; - /* ...and some firmware does it this way. */ - element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH | - I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; - i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL); -} - /** * i40e_add_filter - Add a mac/vlan filter to the VSI * @vsi: the VSI to be searched @@ -9218,12 +9185,6 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) if (vsi->type == I40E_VSI_MAIN) { SET_NETDEV_DEV(netdev, &pf->pdev->dev); ether_addr_copy(mac_addr, hw->mac.perm_addr); - /* The following steps are necessary to prevent reception - * of tagged packets - some older NVM configurations load a - * default a MAC-VLAN filter that accepts any tagged packet - * which must be replaced by a normal filter. - */ - i40e_rm_default_mac_filter(vsi, mac_addr); spin_lock_bh(&vsi->mac_filter_list_lock); i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, true); spin_unlock_bh(&vsi->mac_filter_list_lock); @@ -9741,8 +9702,6 @@ static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi) pf->vsi[pf->lan_vsi]->tc_config.enabled_tc = 0; pf->vsi[pf->lan_vsi]->seid = pf->main_vsi_seid; i40e_vsi_config_tc(pf->vsi[pf->lan_vsi], enabled_tc); - if (vsi->type == I40E_VSI_MAIN) - i40e_rm_default_mac_filter(vsi, pf->hw.mac.perm_addr); /* assign it some queues */ ret = i40e_alloc_rings(vsi); -- cgit v1.2.3 From cf465fe750412335b7a3c75263bd795aecef4fef Mon Sep 17 00:00:00 2001 From: Bimmy Pujari Date: Tue, 27 Sep 2016 11:28:54 -0700 Subject: i40e/i40evf: Changed version from 1.6.19 to 1.6.21 Signed-off-by: Bimmy Pujari Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2e787ffb47ce..00c322d3cbab 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -41,7 +41,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 6 -#define DRV_VERSION_BUILD 19 +#define DRV_VERSION_BUILD 21 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 3e51ff2f48f8..bcb1cafdf28a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -38,7 +38,7 @@ static const char i40evf_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 6 -#define DRV_VERSION_BUILD 19 +#define DRV_VERSION_BUILD 21 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) \ -- cgit v1.2.3 From c17ef430b9fd5f58074f5cdc0128d06a5ae92304 Mon Sep 17 00:00:00 2001 From: David Ertman Date: Fri, 30 Sep 2016 01:36:21 -0700 Subject: i40e: Fix bit logic error in failure case Patch a036244c0686 "i40e: Fix kernel panic on enable/disable LLDP" introduced an error in bit logic. Originally this bit manipulation was meant to clear two bits to indicate that DCB was not enabled or capable. An "&" was incorrectly used instead of an "|" bit operator to combine the two bitmasks into one. This also created a static checker error since the resultant code was a no-op. This patch fixes the error by using the correct bit-wise operator. Signed-off-by: Dave Ertman Reported-by: Dan Carpenter Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 00c322d3cbab..0c2328dab8f7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10970,7 +10970,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = i40e_init_pf_dcb(pf); if (err) { dev_info(&pdev->dev, "DCB init failed %d, disabled\n", err); - pf->flags &= ~(I40E_FLAG_DCB_CAPABLE & I40E_FLAG_DCB_ENABLED); + pf->flags &= ~(I40E_FLAG_DCB_CAPABLE | I40E_FLAG_DCB_ENABLED); /* Continue without DCB enabled */ } #endif /* CONFIG_I40E_DCB */ -- cgit v1.2.3 From 5d4ca23e58f2db7c14b76070f31295244b6edb7b Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 30 Sep 2016 08:21:46 -0400 Subject: i40e: Clean up handling of msglevel flags and debug parameter So the i40e driver had a really convoluted configuration for how to handle the debug flags contained in msg_level. Part of the issue is that the driver has its own 32 bit mask that it was using to track a separate set of debug features. From what I can tell it was trying to use the upper 4 bits to determine if the value was meant to represent a bit-mask or the numeric value provided by debug level. What this patch does is clean this up by compressing those 4 bits into bit 31, as a result we just have to perform a check against the value being negative to determine if we are looking at a debug level (positive), or a debug mask (negative). The debug level will populate the msg_level, and the debug mask will populate the debug_mask in the hardware struct. I added similar logic for ethtool. If the value being provided has bit 31 set we assume the value being provided is a debug mask, otherwise we assume it is a msg_enable mask. For displaying we only provide the msg_enable, and if debug_mask is in use we will print it to the dmesg log. Lastly I removed the debugfs interface. It is redundant with what we already have in ethtool and really doesn't belong anyway. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 19 ------------------- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 7 ++++++- drivers/net/ethernet/intel/i40e/i40e_main.c | 23 ++++++++--------------- 3 files changed, 14 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 0c1875b5b16d..0354632fe2f8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1210,24 +1210,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp, dev_info(&pf->pdev->dev, "dump debug fwdata \n"); } - - } else if (strncmp(cmd_buf, "msg_enable", 10) == 0) { - u32 level; - cnt = sscanf(&cmd_buf[10], "%i", &level); - if (cnt) { - if (I40E_DEBUG_USER & level) { - pf->hw.debug_mask = level; - dev_info(&pf->pdev->dev, - "set hw.debug_mask = 0x%08x\n", - pf->hw.debug_mask); - } - pf->msg_enable = level; - dev_info(&pf->pdev->dev, "set msg_enable = 0x%08x\n", - pf->msg_enable); - } else { - dev_info(&pf->pdev->dev, "msg_enable = 0x%08x\n", - pf->msg_enable); - } } else if (strncmp(cmd_buf, "pfr", 3) == 0) { dev_info(&pf->pdev->dev, "debugfs: forcing PFR\n"); i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED)); @@ -1644,7 +1626,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp, dev_info(&pf->pdev->dev, " dump desc aq\n"); dev_info(&pf->pdev->dev, " dump reset stats\n"); dev_info(&pf->pdev->dev, " dump debug fwdata \n"); - dev_info(&pf->pdev->dev, " msg_enable [level]\n"); dev_info(&pf->pdev->dev, " read \n"); dev_info(&pf->pdev->dev, " write \n"); dev_info(&pf->pdev->dev, " clear_stats vsi [seid]\n"); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 3a1f91efcae2..fb4fb524eab2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -978,6 +978,10 @@ static u32 i40e_get_msglevel(struct net_device *netdev) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; + u32 debug_mask = pf->hw.debug_mask; + + if (debug_mask) + netdev_info(netdev, "i40e debug_mask: 0x%08X\n", debug_mask); return pf->msg_enable; } @@ -989,7 +993,8 @@ static void i40e_set_msglevel(struct net_device *netdev, u32 data) if (I40E_DEBUG_USER & data) pf->hw.debug_mask = data; - pf->msg_enable = data; + else + pf->msg_enable = data; } static int i40e_get_regs_len(struct net_device *netdev) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 0c2328dab8f7..7fa535f57820 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -93,8 +93,8 @@ MODULE_DEVICE_TABLE(pci, i40e_pci_tbl); #define I40E_MAX_VF_COUNT 128 static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); +module_param(debug, uint, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX)"); MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver"); @@ -8511,15 +8511,6 @@ static int i40e_sw_init(struct i40e_pf *pf) int err = 0; int size; - pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE, - (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)); - if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) { - if (I40E_DEBUG_USER & debug) - pf->hw.debug_mask = debug; - pf->msg_enable = netif_msg_init((debug & ~I40E_DEBUG_USER), - I40E_DEFAULT_MSG_ENABLE); - } - /* Set default capability flags */ pf->flags = I40E_FLAG_RX_CSUM_ENABLED | I40E_FLAG_MSI_ENABLED | @@ -10825,10 +10816,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mutex_init(&hw->aq.asq_mutex); mutex_init(&hw->aq.arq_mutex); - if (debug != -1) { - pf->msg_enable = pf->hw.debug_mask; - pf->msg_enable = debug; - } + pf->msg_enable = netif_msg_init(debug, + NETIF_MSG_DRV | + NETIF_MSG_PROBE | + NETIF_MSG_LINK); + if (debug < -1) + pf->hw.debug_mask = debug; /* do a special CORER for clearing PXE mode once at init */ if (hw->revision_id == 0 && -- cgit v1.2.3 From 24d6a91c9df3f6b8096d2e59da31341fc35c9549 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Oct 2016 10:19:05 +0200 Subject: pinctrl: max77620: add OF dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers using pinconf_generic_params tables cannot be built with CONFIG_OF disabled: drivers/pinctrl/pinctrl-max77620.c:53:44: error: array type has incomplete element type ‘struct pinconf_generic_params’ drivers/pinctrl/pinctrl-max77620.c:55:3: error: field name not in record or union initializer drivers/pinctrl/pinctrl-max77620.c:55:3: note: (near initialization for ‘max77620_cfg_params’) drivers/pinctrl/pinctrl-max77620.c:56:3: error: field name not in record or union initializer This adds a dependency for max77620 to disallow that configuration. Alternatively, we could rework the pinctrl infrastructure to make the configuration valid for compile-testing. Cc: Krzysztof Kozlowski Cc: Lee Jones Fixes: 453943dc8f45 ("mfd: Enable compile testing for max77620 and max77686") Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 801fa8bb05e1..3eea73937ce8 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -223,7 +223,7 @@ config PINCTRL_COH901 config PINCTRL_MAX77620 tristate "MAX77620/MAX20024 Pincontrol support" - depends on MFD_MAX77620 + depends on MFD_MAX77620 && OF select PINMUX select GENERIC_PINCONF help -- cgit v1.2.3 From e06c2ee5f13c55a982804d76ea526c630b21b383 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 28 Oct 2016 16:54:21 +0530 Subject: pinctrl: generic: Parse pinmux init nodes if node status is okay During pinmux registration, pinmux table is parsed from DT for making the pinmux table configuration of pins. Parse the only those node whose status is not disabled. This will help on reusing the pin configuration table across platform and disabling the node by status property if that node is not needed on given platform. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf-generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 5020ae534479..ce3335accb5b 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -381,7 +381,7 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev, if (ret < 0) goto exit; - for_each_child_of_node(np_config, np) { + for_each_available_child_of_node(np_config, np) { ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps, type); if (ret < 0) -- cgit v1.2.3 From b9aa65ba8efa810076a081fabd3f3477f751c4ac Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 27 Oct 2016 19:10:15 +0300 Subject: pinctrl: intel: merrifield: Add pin config group handlers Pin config get() and set() handlers for pin groups were previously not implemented by this driver. The pin_config_group_set() is particularly useful for applying a common config setting to all pins in a specified group with a single call, without the caller needing to reference each individual pin by name. Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-merrifield.c | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 7826c7f0cb7c..b21896126f76 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -814,10 +814,51 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin, return 0; } +static int mrfld_config_group_get(struct pinctrl_dev *pctldev, + unsigned int group, unsigned long *config) +{ + const unsigned int *pins; + unsigned int npins; + int ret; + + ret = mrfld_get_group_pins(pctldev, group, &pins, &npins); + if (ret) + return ret; + + ret = mrfld_config_get(pctldev, pins[0], config); + if (ret) + return ret; + + return 0; +} + +static int mrfld_config_group_set(struct pinctrl_dev *pctldev, + unsigned int group, unsigned long *configs, + unsigned int num_configs) +{ + const unsigned int *pins; + unsigned int npins; + int i, ret; + + ret = mrfld_get_group_pins(pctldev, group, &pins, &npins); + if (ret) + return ret; + + for (i = 0; i < npins; i++) { + ret = mrfld_config_set(pctldev, pins[i], configs, num_configs); + if (ret) + return ret; + } + + return 0; +} + static const struct pinconf_ops mrfld_pinconf_ops = { .is_generic = true, .pin_config_get = mrfld_config_get, .pin_config_set = mrfld_config_set, + .pin_config_group_get = mrfld_config_group_get, + .pin_config_group_set = mrfld_config_group_set, }; static const struct pinctrl_desc mrfld_pinctrl_desc = { -- cgit v1.2.3 From e11dee2e98f8abc99ad5336796576a827853ccfa Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 20 Oct 2016 15:49:02 +0200 Subject: pinctrl: sunxi: Deal with configless pins Even though the our binding had the assumption that the allwinner,pull and allwinner,drive properties were optional, the code never took that into account. Fix that. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 51 +++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 7e27204d3eea..ebe2c73d211e 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -261,20 +261,29 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, { unsigned long *pinconfig; unsigned int configlen = 0, idx = 0; + int ret; if (sunxi_pctrl_has_drive_prop(node)) configlen++; if (sunxi_pctrl_has_bias_prop(node)) configlen++; + /* + * If we don't have any configuration, bail out + */ + if (!configlen) + return NULL; + pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); if (!pinconfig) - return NULL; + return ERR_PTR(-ENOMEM); if (sunxi_pctrl_has_drive_prop(node)) { int drive = sunxi_pctrl_parse_drive_prop(node); - if (drive < 0) + if (drive < 0) { + ret = drive; goto err_free; + } pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, drive); @@ -282,8 +291,10 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, if (sunxi_pctrl_has_bias_prop(node)) { int pull = sunxi_pctrl_parse_bias_prop(node); - if (pull < 0) + if (pull < 0) { + ret = pull; goto err_free; + } pinconfig[idx++] = pinconf_to_config_packed(pull, 0); } @@ -294,7 +305,7 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, err_free: kfree(pinconfig); - return NULL; + return ERR_PTR(ret); } static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, @@ -328,7 +339,10 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, /* * We have two maps for each pin: one for the function, one - * for the configuration (bias, strength, etc) + * for the configuration (bias, strength, etc). + * + * We might be slightly overshooting, since we might not have + * any configuration. */ nmaps = npins * 2; *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); @@ -336,8 +350,8 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, return -ENOMEM; pinconfig = sunxi_pctrl_build_pin_config(node, &configlen); - if (!pinconfig) { - ret = -EINVAL; + if (IS_ERR(pinconfig)) { + ret = PTR_ERR(pinconfig); goto err_free_map; } @@ -364,15 +378,24 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, i++; - (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; - (*map)[i].data.configs.group_or_pin = group; - (*map)[i].data.configs.configs = pinconfig; - (*map)[i].data.configs.num_configs = configlen; - - i++; + if (pinconfig) { + (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; + (*map)[i].data.configs.group_or_pin = group; + (*map)[i].data.configs.configs = pinconfig; + (*map)[i].data.configs.num_configs = configlen; + i++; + } } - *num_maps = nmaps; + *num_maps = i; + + /* + * We know have the number of maps we need, we can resize our + * map array + */ + *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL); + if (!map) + return -ENOMEM; return 0; -- cgit v1.2.3 From b64b540931483cca3200d98756bed6ad0e01d75c Mon Sep 17 00:00:00 2001 From: Lyude Date: Wed, 26 Oct 2016 12:36:09 -0400 Subject: drm/i915/vlv: Prevent enabling hpd polling in late suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One of the CI machines began to run into issues with the hpd poller suddenly waking up in the midst of the late suspend phase. It looks like this is getting caused by the fact we now deinitialize power wells in late suspend, which means that intel_hpd_poll_init() gets called in late suspend causing polling to get re-enabled. So, when deinitializing power wells on valleyview we now refrain from enabling polling in the midst of suspend. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98040 Fixes: 19625e85c6ec ("drm/i915: Enable polling when we don't have hpd") Signed-off-by: Lyude Cc: Ville Syrjälä Cc: Jani Saarinen Cc: Petry Latvala Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1477499769-1966-1-git-send-email-lyude@redhat.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 95034a06d4ad..9a3a7455d29c 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1113,7 +1113,9 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv) intel_power_sequencer_reset(dev_priv); - intel_hpd_poll_init(dev_priv); + /* Prevent us from re-enabling polling on accident in late suspend */ + if (!dev_priv->drm.dev->power.is_suspended) + intel_hpd_poll_init(dev_priv); } static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv, -- cgit v1.2.3 From 93a205ee98a4881e8bf608e65562c19d45930a93 Mon Sep 17 00:00:00 2001 From: Aaron Conole Date: Tue, 25 Oct 2016 16:12:12 -0400 Subject: virtio-net: Update the mtu code to match virtio spec The virtio committee recently ratified a change, VIRTIO-152, which defines the mtu field to be 'max' MTU, not simply desired MTU. This commit brings the virtio-net device in compliance with VIRTIO-152. Additionally, drop the max_mtu branch - it cannot be taken since the u16 returned by virtio_cread16 will never exceed the initial value of max_mtu. Signed-off-by: Aaron Conole Acked-by: "Michael S. Tsirkin" Acked-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 720809f82a0e..2cafd12a1075 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1870,10 +1870,12 @@ static int virtnet_probe(struct virtio_device *vdev) mtu = virtio_cread16(vdev, offsetof(struct virtio_net_config, mtu)); - if (mtu < dev->min_mtu || mtu > dev->max_mtu) + if (mtu < dev->min_mtu) { __virtio_clear_bit(vdev, VIRTIO_NET_F_MTU); - else + } else { dev->mtu = mtu; + dev->max_mtu = mtu; + } } if (vi->any_header_sg) -- cgit v1.2.3 From 4911f94dd327d16e492628f04661c1ea6e3d8d23 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 29 Oct 2016 16:25:32 +0000 Subject: usb: ohci-da8xx: remove redundant dev_err call in usb_hcd_da8xx_probe() There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-da8xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 30c48789389e..bd6cf3c9ec60 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -261,7 +261,6 @@ static int ohci_da8xx_probe(struct platform_device *pdev) hcd->regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(hcd->regs)) { error = PTR_ERR(hcd->regs); - dev_err(&pdev->dev, "failed to map ohci.\n"); goto err; } hcd->rsrc_start = mem->start; -- cgit v1.2.3 From b65fba3d87216bfe6ae9bc77be5eb6eabb6514a4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Oct 2016 17:16:36 -0400 Subject: USB: core: add missing license information to some files Some of the USB core files were missing explicit license information. As all files in the kernel tree are implicitly licensed under the GPLv2-only, be explicit in case someone get confused looking at individual files by using the SPDX nomenclature. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/buffer.c | 3 +++ drivers/usb/core/config.c | 5 +++++ drivers/usb/core/driver.c | 3 +++ drivers/usb/core/endpoint.c | 4 +++- drivers/usb/core/file.c | 2 ++ drivers/usb/core/generic.c | 2 ++ drivers/usb/core/hub.c | 2 ++ drivers/usb/core/message.c | 3 +++ drivers/usb/core/notify.c | 2 ++ drivers/usb/core/sysfs.c | 2 ++ drivers/usb/core/urb.c | 5 +++++ drivers/usb/core/usb.c | 3 +++ drivers/usb/core/usb.h | 5 +++++ 13 files changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 98e39f91723a..b9bf6e2eb6fe 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -3,6 +3,9 @@ * * This implementation plugs in through generic "usb_bus" level methods, * and should work with all USB controllers, regardless of bus type. + * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index a2d90aca779f..0aa9e7d697a5 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -1,3 +1,8 @@ +/* + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 + */ + #include #include #include diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index dadd1e8dfe09..cdee5130638b 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -15,6 +15,9 @@ * (usb_device_id matching changes by Adam J. Richter) * (C) Copyright Greg Kroah-Hartman 2002-2003 * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 + * * NOTE! This is not actually a driver at all, rather this is * just a collection of helper routines that implement the * matching, probing, releasing, suspending and resuming for diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 101983b7e8d2..b73b25bd1541 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -5,8 +5,10 @@ * (C) Copyright 2002,2004 IBM Corp. * (C) Copyright 2006 Novell Inc. * - * Endpoint sysfs stuff + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 * + * Endpoint sysfs stuff */ #include diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 822ced9639aa..e26bd5e773ad 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -13,6 +13,8 @@ * (usb_device_id matching changes by Adam J. Richter) * (C) Copyright Greg Kroah-Hartman 2002-2003 * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 358ca8dd784f..bd3e0c5a6db2 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -15,6 +15,8 @@ * (usb_device_id matching changes by Adam J. Richter) * (C) Copyright Greg Kroah-Hartman 2002-2003 * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cbb146736f57..76e80d8657d2 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -6,6 +6,8 @@ * (C) Copyright 1999 Gregory P. Smith * (C) Copyright 2001 Brad Hards (bhards@bigpond.net.au) * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 3a4707746157..dea55914d641 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1,5 +1,8 @@ /* * message.c - synchronous message handling + * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 */ #include /* for scatterlist macros */ diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index 7728c91dfa2e..b12a463a3e22 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -6,6 +6,8 @@ * notifier functions originally based on those in kernel/sys.c * but fixed up to not be so broken. * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 */ diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 84d66d573196..dfc68ed24db1 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -7,6 +7,8 @@ * * All of the sysfs file attributes for usb devices and interfaces. * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 */ diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index a9039696476e..0be49a1e3e66 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -1,3 +1,8 @@ +/* + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 + */ + #include #include #include diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 592151461017..a2ccc69fb45c 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -12,6 +12,9 @@ * (usb_device_id matching changes by Adam J. Richter) * (C) Copyright Greg Kroah-Hartman 2002-2003 * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 + * * NOTE! This is not actually a driver at all, rather this is * just a collection of helper routines that implement the * generic USB things that the real drivers can use.. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 53318126ed91..dc6949248823 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -1,3 +1,8 @@ +/* + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 + */ + #include #include -- cgit v1.2.3 From 66b8053e249c76b0d800805dac7e7dc80c3d7764 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 29 Oct 2016 10:53:19 +0200 Subject: spi: fsl-espi: small fix to error path in fsl_espi_irq spin_lock is used to obtain the spinlock, so spin_unlock has to be used here. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 2f95b19e67f7..1d3c9023391d 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -473,7 +473,7 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) /* Get interrupt events(tx/rx) */ events = fsl_espi_read_reg(mspi, ESPI_SPIE); if (!events) { - spin_unlock_irq(&mspi->lock); + spin_unlock(&mspi->lock); return IRQ_NONE; } -- cgit v1.2.3 From 73aaf15849d9421fa696c3d7785952d8100042b2 Mon Sep 17 00:00:00 2001 From: Paulo Zaneti Date: Sat, 29 Oct 2016 11:02:19 +0200 Subject: spi: fsl-espi: fix support for all available clock rates According to NXP ESPI datasheet, the SPI clock rate is: spi_clk = System_Clock / ( 2 * DIV16 * ( 1 + PM ) ) Where System_Clock is the platform clock divided by 2, DIV16 may be 1 or 16, and PM is a 4 bits integer (0 to 15). Isolating PM on the expression, we get: PM = (System_Clock / ( 2 * DIV16 * spi_clk ) ) - 1 Where System_Clock = mpc8xxx_spi->spibrg / 2, spi_clk = hz, and DIV16 = 1 or DIV16 = 16. So, PM = (mpc8xxx_spi->spibrg / ( 4 * hz) ) - 1 or PM = (mpc8xxx_spi->spibrg / ( 16 * 4 * hz) ) - 1 Current spi-fsl-espi driver can't configure the HW for all supported clock rates. It filters out clock rates for PM = 0 and PM = 1. This patch allows all range of supported clock rates to be configured on the ESPI controller. Signed-off-by: Paulo Zaneti Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 1d3c9023391d..8b3a28739d9a 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -247,8 +247,7 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, { struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); int bits_per_word = t ? t->bits_per_word : spi->bits_per_word; - u32 hz = t ? t->speed_hz : spi->max_speed_hz; - u8 pm; + u32 pm, hz = t ? t->speed_hz : spi->max_speed_hz; struct spi_mpc8xxx_cs *cs = spi->controller_state; /* mask out bits we are going to set */ @@ -256,22 +255,19 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, cs->hw_mode |= CSMODE_LEN(bits_per_word - 1); - if ((mpc8xxx_spi->spibrg / hz) > 64) { + pm = DIV_ROUND_UP(mpc8xxx_spi->spibrg, hz * 4) - 1; + + if (pm > 15) { cs->hw_mode |= CSMODE_DIV16; - pm = DIV_ROUND_UP(mpc8xxx_spi->spibrg, hz * 16 * 4); - - WARN_ONCE(pm > 33, "%s: Requested speed is too low: %d Hz. " - "Will use %d Hz instead.\n", dev_name(&spi->dev), - hz, mpc8xxx_spi->spibrg / (4 * 16 * (32 + 1))); - if (pm > 33) - pm = 33; - } else { - pm = DIV_ROUND_UP(mpc8xxx_spi->spibrg, hz * 4); + pm = DIV_ROUND_UP(mpc8xxx_spi->spibrg, hz * 16 * 4) - 1; + + WARN_ONCE(pm > 15, + "%s: Requested speed is too low: %u Hz. Will use %u Hz instead.\n", + dev_name(&spi->dev), hz, + mpc8xxx_spi->spibrg / (4 * 16 * (15 + 1))); + if (pm > 15) + pm = 15; } - if (pm) - pm--; - if (pm < 2) - pm = 2; cs->hw_mode |= CSMODE_PM(pm); -- cgit v1.2.3 From 196737912da5eab055489e0635662a3b7adef6eb Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Wed, 26 Oct 2016 00:00:31 -0700 Subject: spi: sun4i: Allow transfers larger than FIFO size SPI transfers were limited to one FIFO depth, which is 64 bytes. This was an artificial limitation, however, as the hardware can handle much larger bursts. To accommodate this, we enable the interrupt when the Rx FIFO is 3/4 full, and drain the FIFO within the interrupt handler. The 3/4 ratio was chosen arbitrarily, with the intention to reduce the potential number of interrupts. Since the SUN4I_CTL_TP bit is set, the hardware will pause transmission whenever the FIFO is full, so there is no risk of losing data if we can't service the interrupt in time. For the Tx side, enable and use the Tx FIFO 3/4 empty interrupt to replenish the FIFO on large SPI bursts. This requires more care in when the interrupt is left enabled, as this interrupt will continually trigger when the FIFO is less than 1/4 full, even though we acknowledge it. Signed-off-by: Alexandru Gagniuc Acked-by: Maxime Ripard Signed-off-by: Olliver Schinagl Signed-off-by: Mark Brown --- drivers/spi/spi-sun4i.c | 75 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 4969dc10684a..c5cd635c28f3 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -46,6 +46,8 @@ #define SUN4I_CTL_TP BIT(18) #define SUN4I_INT_CTL_REG 0x0c +#define SUN4I_INT_CTL_RF_F34 BIT(4) +#define SUN4I_INT_CTL_TF_E34 BIT(12) #define SUN4I_INT_CTL_TC BIT(16) #define SUN4I_INT_STA_REG 0x10 @@ -61,11 +63,14 @@ #define SUN4I_CLK_CTL_CDR1(div) (((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8) #define SUN4I_CLK_CTL_DRS BIT(12) +#define SUN4I_MAX_XFER_SIZE 0xffffff + #define SUN4I_BURST_CNT_REG 0x20 -#define SUN4I_BURST_CNT(cnt) ((cnt) & 0xffffff) +#define SUN4I_BURST_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE) #define SUN4I_XMIT_CNT_REG 0x24 -#define SUN4I_XMIT_CNT(cnt) ((cnt) & 0xffffff) +#define SUN4I_XMIT_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE) + #define SUN4I_FIFO_STA_REG 0x28 #define SUN4I_FIFO_STA_RF_CNT_MASK 0x7f @@ -96,6 +101,31 @@ static inline void sun4i_spi_write(struct sun4i_spi *sspi, u32 reg, u32 value) writel(value, sspi->base_addr + reg); } +static inline u32 sun4i_spi_get_tx_fifo_count(struct sun4i_spi *sspi) +{ + u32 reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG); + + reg >>= SUN4I_FIFO_STA_TF_CNT_BITS; + + return reg & SUN4I_FIFO_STA_TF_CNT_MASK; +} + +static inline void sun4i_spi_enable_interrupt(struct sun4i_spi *sspi, u32 mask) +{ + u32 reg = sun4i_spi_read(sspi, SUN4I_INT_CTL_REG); + + reg |= mask; + sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, reg); +} + +static inline void sun4i_spi_disable_interrupt(struct sun4i_spi *sspi, u32 mask) +{ + u32 reg = sun4i_spi_read(sspi, SUN4I_INT_CTL_REG); + + reg &= ~mask; + sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, reg); +} + static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len) { u32 reg, cnt; @@ -118,10 +148,13 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len) static inline void sun4i_spi_fill_fifo(struct sun4i_spi *sspi, int len) { + u32 cnt; u8 byte; - if (len > sspi->len) - len = sspi->len; + /* See how much data we can fit */ + cnt = SUN4I_FIFO_DEPTH - sun4i_spi_get_tx_fifo_count(sspi); + + len = min3(len, (int)cnt, sspi->len); while (len--) { byte = sspi->tx_buf ? *sspi->tx_buf++ : 0; @@ -184,10 +217,10 @@ static int sun4i_spi_transfer_one(struct spi_master *master, u32 reg; /* We don't support transfer larger than the FIFO */ - if (tfr->len > SUN4I_FIFO_DEPTH) + if (tfr->len > SUN4I_MAX_XFER_SIZE) return -EMSGSIZE; - if (tfr->tx_buf && tfr->len >= SUN4I_FIFO_DEPTH) + if (tfr->tx_buf && tfr->len >= SUN4I_MAX_XFER_SIZE) return -EMSGSIZE; reinit_completion(&sspi->done); @@ -286,7 +319,11 @@ static int sun4i_spi_transfer_one(struct spi_master *master, sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1); /* Enable the interrupts */ - sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC); + sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TC | + SUN4I_INT_CTL_RF_F34); + /* Only enable Tx FIFO interrupt if we really need it */ + if (tx_len > SUN4I_FIFO_DEPTH) + sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TF_E34); /* Start the transfer */ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG); @@ -306,7 +343,6 @@ static int sun4i_spi_transfer_one(struct spi_master *master, goto out; } - sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH); out: sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0); @@ -322,10 +358,33 @@ static irqreturn_t sun4i_spi_handler(int irq, void *dev_id) /* Transfer complete */ if (status & SUN4I_INT_CTL_TC) { sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC); + sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH); complete(&sspi->done); return IRQ_HANDLED; } + /* Receive FIFO 3/4 full */ + if (status & SUN4I_INT_CTL_RF_F34) { + sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH); + /* Only clear the interrupt _after_ draining the FIFO */ + sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_RF_F34); + return IRQ_HANDLED; + } + + /* Transmit FIFO 3/4 empty */ + if (status & SUN4I_INT_CTL_TF_E34) { + sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH); + + if (!sspi->len) + /* nothing left to transmit */ + sun4i_spi_disable_interrupt(sspi, SUN4I_INT_CTL_TF_E34); + + /* Only clear the interrupt _after_ re-seeding the FIFO */ + sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TF_E34); + + return IRQ_HANDLED; + } + return IRQ_NONE; } -- cgit v1.2.3 From 0f16bc1355bab719958577b2e519a8cef1637b28 Mon Sep 17 00:00:00 2001 From: Gao Feng Date: Tue, 25 Oct 2016 22:26:09 +0800 Subject: driver: tun: Move tun check into the block of TUNSETIFF condition check When cmd is TUNSETIFF and tun is not null, the original codes go ahead, then reach the default case of switch(cmd) and set the ret is -EINVAL. It is not clear for readers. Now move the tun check into the block of TUNSETIFF condition check, and return -EEXIST instead of -EINVAL when the tfile already owns one tun. Signed-off-by: Gao Feng Signed-off-by: David S. Miller --- drivers/net/tun.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 93285687cf13..9142db847ee1 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2005,7 +2005,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, rtnl_lock(); tun = __tun_get(tfile); - if (cmd == TUNSETIFF && !tun) { + if (cmd == TUNSETIFF) { + ret = -EEXIST; + if (tun) + goto unlock; + ifr.ifr_name[IFNAMSIZ-1] = '\0'; ret = tun_set_iff(sock_net(&tfile->sk), file, &ifr); -- cgit v1.2.3 From 58effd7168e9b74252650a008b5229c7cf224c7b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 26 Oct 2016 14:03:54 -0200 Subject: net: phy: at803x: Add a definition for PHY ID mask Add a definition for PHY ID mask for improving code readability. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index f279a897a5c7..dd47b69ddcff 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -58,6 +58,7 @@ #define ATH8030_PHY_ID 0x004dd076 #define ATH8031_PHY_ID 0x004dd074 #define ATH8035_PHY_ID 0x004dd072 +#define AT803X_PHY_ID_MASK 0xffffffef MODULE_DESCRIPTION("Atheros 803x PHY driver"); MODULE_AUTHOR("Matus Ujhelyi"); @@ -386,7 +387,7 @@ static struct phy_driver at803x_driver[] = { /* ATHEROS 8035 */ .phy_id = ATH8035_PHY_ID, .name = "Atheros 8035 ethernet", - .phy_id_mask = 0xffffffef, + .phy_id_mask = AT803X_PHY_ID_MASK, .probe = at803x_probe, .config_init = at803x_config_init, .set_wol = at803x_set_wol, @@ -403,7 +404,7 @@ static struct phy_driver at803x_driver[] = { /* ATHEROS 8030 */ .phy_id = ATH8030_PHY_ID, .name = "Atheros 8030 ethernet", - .phy_id_mask = 0xffffffef, + .phy_id_mask = AT803X_PHY_ID_MASK, .probe = at803x_probe, .config_init = at803x_config_init, .link_change_notify = at803x_link_change_notify, @@ -421,7 +422,7 @@ static struct phy_driver at803x_driver[] = { /* ATHEROS 8031 */ .phy_id = ATH8031_PHY_ID, .name = "Atheros 8031 ethernet", - .phy_id_mask = 0xffffffef, + .phy_id_mask = AT803X_PHY_ID_MASK, .probe = at803x_probe, .config_init = at803x_config_init, .set_wol = at803x_set_wol, @@ -439,9 +440,9 @@ static struct phy_driver at803x_driver[] = { module_phy_driver(at803x_driver); static struct mdio_device_id __maybe_unused atheros_tbl[] = { - { ATH8030_PHY_ID, 0xffffffef }, - { ATH8031_PHY_ID, 0xffffffef }, - { ATH8035_PHY_ID, 0xffffffef }, + { ATH8030_PHY_ID, AT803X_PHY_ID_MASK }, + { ATH8031_PHY_ID, AT803X_PHY_ID_MASK }, + { ATH8035_PHY_ID, AT803X_PHY_ID_MASK }, { } }; -- cgit v1.2.3 From 976990569360bcd7bb35f370c76904d109d20cc0 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 27 Oct 2016 22:32:22 +0200 Subject: rocker: set physical device for port netdevice Do this so the sysfs has "device" link correctly set. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 2e81b702a927..55b2ab9dc320 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2534,7 +2534,7 @@ static void rocker_port_dev_addr_init(struct rocker_port *rocker_port) #define ROCKER_PORT_MAX_MTU 9000 static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) { - const struct pci_dev *pdev = rocker->pdev; + struct pci_dev *pdev = rocker->pdev; struct rocker_port *rocker_port; struct net_device *dev; int err; @@ -2542,6 +2542,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) dev = alloc_etherdev(sizeof(struct rocker_port)); if (!dev) return -ENOMEM; + SET_NETDEV_DEV(dev, &pdev->dev); rocker_port = netdev_priv(dev); rocker_port->dev = dev; rocker_port->rocker = rocker; -- cgit v1.2.3 From af1fee98219992ba2c12441a447719652ed7e983 Mon Sep 17 00:00:00 2001 From: Raju Lakkaraju Date: Fri, 28 Oct 2016 12:10:11 +0200 Subject: net: phy: Add support for Microsemi VSC 8530/40 Fast Ethernet PHY Signed-off-by: Raju Lakkaraju Signed-off-by: Allan W. Nielsen Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 2 +- drivers/net/phy/mscc.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 45f68eaf9b79..ff31c10a3485 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -290,7 +290,7 @@ config MICROCHIP_PHY config MICROSEMI_PHY tristate "Microsemi PHYs" ---help--- - Currently supports the VSC8531 and VSC8541 PHYs + Currently supports VSC8530, VSC8531, VSC8540 and VSC8541 PHYs config NATIONAL_PHY tristate "National Semiconductor PHYs" diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index 113616b92abb..d0026ab8a220 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -65,7 +65,9 @@ enum rgmii_rx_clock_delay { #define SECURE_ON_PASSWD_LEN_4 0x4000 /* Microsemi PHY ID's */ +#define PHY_ID_VSC8530 0x00070560 #define PHY_ID_VSC8531 0x00070570 +#define PHY_ID_VSC8540 0x00070760 #define PHY_ID_VSC8541 0x00070770 #define MSCC_VDDMAC_1500 1500 @@ -398,6 +400,25 @@ static int vsc85xx_probe(struct phy_device *phydev) /* Microsemi VSC85xx PHYs */ static struct phy_driver vsc85xx_driver[] = { +{ + .phy_id = PHY_ID_VSC8530, + .name = "Microsemi FE VSC8530", + .phy_id_mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .soft_reset = &genphy_soft_reset, + .config_init = &vsc85xx_config_init, + .config_aneg = &genphy_config_aneg, + .aneg_done = &genphy_aneg_done, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc85xx_ack_interrupt, + .config_intr = &vsc85xx_config_intr, + .suspend = &genphy_suspend, + .resume = &genphy_resume, + .probe = &vsc85xx_probe, + .set_wol = &vsc85xx_wol_set, + .get_wol = &vsc85xx_wol_get, +}, { .phy_id = PHY_ID_VSC8531, .name = "Microsemi VSC8531", @@ -417,6 +438,25 @@ static struct phy_driver vsc85xx_driver[] = { .set_wol = &vsc85xx_wol_set, .get_wol = &vsc85xx_wol_get, }, +{ + .phy_id = PHY_ID_VSC8540, + .name = "Microsemi FE VSC8540 SyncE", + .phy_id_mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .soft_reset = &genphy_soft_reset, + .config_init = &vsc85xx_config_init, + .config_aneg = &genphy_config_aneg, + .aneg_done = &genphy_aneg_done, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc85xx_ack_interrupt, + .config_intr = &vsc85xx_config_intr, + .suspend = &genphy_suspend, + .resume = &genphy_resume, + .probe = &vsc85xx_probe, + .set_wol = &vsc85xx_wol_set, + .get_wol = &vsc85xx_wol_get, +}, { .phy_id = PHY_ID_VSC8541, .name = "Microsemi VSC8541 SyncE", @@ -442,7 +482,9 @@ static struct phy_driver vsc85xx_driver[] = { module_phy_driver(vsc85xx_driver); static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { + { PHY_ID_VSC8530, 0xfffffff0, }, { PHY_ID_VSC8531, 0xfffffff0, }, + { PHY_ID_VSC8540, 0xfffffff0, }, { PHY_ID_VSC8541, 0xfffffff0, }, { } }; -- cgit v1.2.3 From 357f4aae859b5d74554b0ccbb18556f1df4166c3 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 29 Oct 2016 22:16:58 +0200 Subject: firewire: net: really fix maximum possible MTU The maximum unicast datagram size /without/ link fragmentation is 4096 - 4 = 4092 (max IEEE 1394 async payload size at >= S800 bus speed, minus unfragmented encapssulation header). Max broadcast datagram size without fragmentation is 8 bytes less than that (due to GASP header). The maximum datagram size /with/ link fragmentation is 0xfff = 4095 for unicast and broadcast. This is because the RFC 2734 fragment encapsulation header field for datagram size is only 12 bits wide. Fixes: 5d48f00d836a('firewire: net: fix maximum possible MTU') Signed-off-by: Stefan Richter Signed-off-by: David S. Miller --- drivers/firewire/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 03715e7d9d92..363fc5ec1a4e 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -1465,7 +1465,7 @@ static int fwnet_probe(struct fw_unit *unit, net->mtu = 1500U; net->min_mtu = ETH_MIN_MTU; - net->max_mtu = ETH_MAX_MTU; + net->max_mtu = 0xfff; /* Set our hardware address while we're at it */ ha = (union fwnet_hwaddr *)net->dev_addr; -- cgit v1.2.3 From 1c387188c60f53b338c20eee32db055dfe022a9b Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Fri, 21 Oct 2016 15:32:05 -0700 Subject: iommu/vt-d: Fix IOMMU lookup for SR-IOV Virtual Functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VT-d specification (§8.3.3) says: ‘Virtual Functions’ of a ‘Physical Function’ are under the scope of the same remapping unit as the ‘Physical Function’. The BIOS is not required to list all the possible VFs in the scope tables, and arguably *shouldn't* make any attempt to do so, since there could be a huge number of them. This has been broken basically for ever — the VF is never going to match against a specific unit's scope, so it ends up being assigned to the INCLUDE_ALL IOMMU. Which was always actually correct by coincidence, but now we're looking at Root-Complex integrated devices with SR-IOV support it's going to start being wrong. Fix it to simply use pci_physfn() before doing the lookup for PCI devices. Cc: stable@vger.kernel.org Signed-off-by: Sainath Grandhi Signed-off-by: Ashok Raj Signed-off-by: David Woodhouse --- drivers/iommu/dmar.c | 4 +++- drivers/iommu/intel-iommu.c | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 58470f5ced04..8c53748a769d 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -338,7 +338,9 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb, struct pci_dev *pdev = to_pci_dev(data); struct dmar_pci_notify_info *info; - /* Only care about add/remove events for physical functions */ + /* Only care about add/remove events for physical functions. + * For VFs we actually do the lookup based on the corresponding + * PF in device_to_iommu() anyway. */ if (pdev->is_virtfn) return NOTIFY_DONE; if (action != BUS_NOTIFY_ADD_DEVICE && diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a4407eabf0e6..2723090a0d54 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -892,7 +892,13 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf return NULL; if (dev_is_pci(dev)) { + struct pci_dev *pf_pdev; + pdev = to_pci_dev(dev); + /* VFs aren't listed in scope tables; we need to look up + * the PF instead to find the IOMMU. */ + pf_pdev = pci_physfn(pdev); + dev = &pf_pdev->dev; segment = pci_domain_nr(pdev->bus); } else if (has_acpi_companion(dev)) dev = &ACPI_COMPANION(dev)->dev; @@ -905,6 +911,13 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, tmp) { if (tmp == dev) { + /* For a VF use its original BDF# not that of the PF + * which we used for the IOMMU lookup. Strictly speaking + * we could do this for all PCI devices; we only need to + * get the BDF# from the scope table for ACPI matches. */ + if (pdev->is_virtfn) + goto got_pdev; + *bus = drhd->devices[i].bus; *devfn = drhd->devices[i].devfn; goto out; -- cgit v1.2.3 From bdc379249c5b844c55213116e34e9b97c9029dbf Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Thu, 29 Sep 2016 19:35:38 +0300 Subject: IB/mlx5: Skip handling unknown events Do not dispatch unknown mlx5 core events on mlx5_ib_event. Signed-off-by: Saeed Mahameed Signed-off-by: Eugenia Emantayev Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/mlx5/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 22174774dbb8..d02341eebddb 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -2358,6 +2358,8 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context, ibev.event = IB_EVENT_CLIENT_REREGISTER; port = (u8)param; break; + default: + return; } ibev.device = &ibdev->ib_dev; -- cgit v1.2.3 From 6887a825dc5cb41ef63fe166e28362590f9f6024 Mon Sep 17 00:00:00 2001 From: Eugenia Emantayev Date: Wed, 28 Sep 2016 17:29:41 +0300 Subject: net/mlx5: Fix length of async_event_mask According to PRM async_event_mask have to be 64 bits long. Signed-off-by: Eugenia Emantayev Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index aaca09002ca6..e74a73be5e0a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -469,7 +469,7 @@ void mlx5_eq_cleanup(struct mlx5_core_dev *dev) int mlx5_start_eqs(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = &dev->priv.eq_table; - u32 async_event_mask = MLX5_ASYNC_EVENT_MASK; + u64 async_event_mask = MLX5_ASYNC_EVENT_MASK; int err; if (MLX5_CAP_GEN(dev, pg)) -- cgit v1.2.3 From 86490d9a5969eaa8217a9329a6f0875cd0b041bc Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Tue, 18 Oct 2016 21:35:35 +0300 Subject: net/mlx5: Add ConnectX-5 PCIe 4.0 VF device ID For the mlx5 driver to support ConnectX-5 PCIe 4.0 VFs, we add the device ID "0x101a" to mlx5_core_pci_table. Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index d9c3c70b29e4..197e04c675fd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1422,6 +1422,7 @@ static const struct pci_device_id mlx5_core_pci_table[] = { { PCI_VDEVICE(MELLANOX, 0x1017) }, /* ConnectX-5, PCIe 3.0 */ { PCI_VDEVICE(MELLANOX, 0x1018), MLX5_PCI_DEV_IS_VF}, /* ConnectX-5 VF */ { PCI_VDEVICE(MELLANOX, 0x1019) }, /* ConnectX-5, PCIe 4.0 */ + { PCI_VDEVICE(MELLANOX, 0x101a), MLX5_PCI_DEV_IS_VF}, /* ConnectX-5, PCIe 4.0 VF */ { 0, } }; -- cgit v1.2.3 From 813f854053c26204e2723c498def4c7870dcc7f4 Mon Sep 17 00:00:00 2001 From: Mohamad Haj Yahia Date: Thu, 11 Aug 2016 11:21:39 +0300 Subject: net/mlx5: Introduce TSAR manipulation firmware commands TSAR (stands for Transmit Scheduling ARbiter) is a hardware component that is responsible for selecting the next entity to serve on the transmit path. The arbitration defines the QoS policy between the agents connected to the TSAR. The TSAR is a consist two main features: 1) BW Allocation between agents: The TSAR implements a defecit weighted round robin between the agents. Each agent attached to the TSAR is assigned with a weight and it is awarded transmission tokens according to this weight. 2) Rate limer per agent: Each agent attached to the TSAR is (optionally) assigned with a rate limit. TSAR will not allow scheduling for an agent exceeding its defined rate limit. In this patch we implement the API of manipulating the TSAR. Signed-off-by: Mohamad Haj Yahia Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 13 +- .../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 7 + drivers/net/ethernet/mellanox/mlx5/core/rl.c | 65 +++++++ include/linux/mlx5/mlx5_ifc.h | 199 ++++++++++++++++++++- 4 files changed, 279 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 1e639f886021..8561102f2563 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -318,6 +318,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: case MLX5_CMD_OP_SET_FLOW_TABLE_ROOT: case MLX5_CMD_OP_DEALLOC_ENCAP_HEADER: + case MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT: + case MLX5_CMD_OP_DESTROY_QOS_PARA_VPORT: return MLX5_CMD_STAT_OK; case MLX5_CMD_OP_QUERY_HCA_CAP: @@ -419,11 +421,14 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, case MLX5_CMD_OP_QUERY_FLOW_TABLE: case MLX5_CMD_OP_CREATE_FLOW_GROUP: case MLX5_CMD_OP_QUERY_FLOW_GROUP: - case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: case MLX5_CMD_OP_QUERY_FLOW_COUNTER: case MLX5_CMD_OP_ALLOC_ENCAP_HEADER: + case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: + case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: + case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: + case MLX5_CMD_OP_CREATE_QOS_PARA_VPORT: *status = MLX5_DRIVER_STATUS_ABORTED; *synd = MLX5_DRIVER_SYND; return -EIO; @@ -580,6 +585,12 @@ const char *mlx5_command_str(int command) MLX5_COMMAND_STR_CASE(MODIFY_FLOW_TABLE); MLX5_COMMAND_STR_CASE(ALLOC_ENCAP_HEADER); MLX5_COMMAND_STR_CASE(DEALLOC_ENCAP_HEADER); + MLX5_COMMAND_STR_CASE(CREATE_SCHEDULING_ELEMENT); + MLX5_COMMAND_STR_CASE(DESTROY_SCHEDULING_ELEMENT); + MLX5_COMMAND_STR_CASE(QUERY_SCHEDULING_ELEMENT); + MLX5_COMMAND_STR_CASE(MODIFY_SCHEDULING_ELEMENT); + MLX5_COMMAND_STR_CASE(CREATE_QOS_PARA_VPORT); + MLX5_COMMAND_STR_CASE(DESTROY_QOS_PARA_VPORT); default: return "unknown command opcode"; } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 3d0cfb9f18f9..bf431715172c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -91,6 +91,13 @@ int mlx5_core_sriov_configure(struct pci_dev *dev, int num_vfs); bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev); int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id); int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id); +int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, + void *context, u32 *element_id); +int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, + void *context, u32 element_id, + u32 modify_bitmask); +int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, + u32 element_id); int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev); cycle_t mlx5_read_internal_timer(struct mlx5_core_dev *dev); u32 mlx5_get_msix_vec(struct mlx5_core_dev *dev, int vecidx); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rl.c b/drivers/net/ethernet/mellanox/mlx5/core/rl.c index 104902a93a0b..e651e4c02867 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/rl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/rl.c @@ -36,6 +36,71 @@ #include #include "mlx5_core.h" +/* Scheduling element fw management */ +int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, + void *ctx, u32 *element_id) +{ + u32 in[MLX5_ST_SZ_DW(create_scheduling_element_in)] = {0}; + u32 out[MLX5_ST_SZ_DW(create_scheduling_element_in)] = {0}; + void *schedc; + int err; + + schedc = MLX5_ADDR_OF(create_scheduling_element_in, in, + scheduling_context); + MLX5_SET(create_scheduling_element_in, in, opcode, + MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT); + MLX5_SET(create_scheduling_element_in, in, scheduling_hierarchy, + hierarchy); + memcpy(schedc, ctx, MLX5_ST_SZ_BYTES(scheduling_context)); + + err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); + if (err) + return err; + + *element_id = MLX5_GET(create_scheduling_element_out, out, + scheduling_element_id); + return 0; +} + +int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, + void *ctx, u32 element_id, + u32 modify_bitmask) +{ + u32 in[MLX5_ST_SZ_DW(modify_scheduling_element_in)] = {0}; + u32 out[MLX5_ST_SZ_DW(modify_scheduling_element_in)] = {0}; + void *schedc; + + schedc = MLX5_ADDR_OF(modify_scheduling_element_in, in, + scheduling_context); + MLX5_SET(modify_scheduling_element_in, in, opcode, + MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT); + MLX5_SET(modify_scheduling_element_in, in, scheduling_element_id, + element_id); + MLX5_SET(modify_scheduling_element_in, in, modify_bitmask, + modify_bitmask); + MLX5_SET(modify_scheduling_element_in, in, scheduling_hierarchy, + hierarchy); + memcpy(schedc, ctx, MLX5_ST_SZ_BYTES(scheduling_context)); + + return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); +} + +int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, + u32 element_id) +{ + u32 in[MLX5_ST_SZ_DW(destroy_scheduling_element_in)] = {0}; + u32 out[MLX5_ST_SZ_DW(destroy_scheduling_element_in)] = {0}; + + MLX5_SET(destroy_scheduling_element_in, in, opcode, + MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT); + MLX5_SET(destroy_scheduling_element_in, in, scheduling_element_id, + element_id); + MLX5_SET(destroy_scheduling_element_in, in, scheduling_hierarchy, + hierarchy); + + return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); +} + /* Finds an entry where we can register the given rate * If the rate already exists, return the entry where it is registered, * otherwise return the first available entry. diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 12f72e45a3f0..2632cb2caf10 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -145,6 +145,12 @@ enum { MLX5_CMD_OP_QUERY_Q_COUNTER = 0x773, MLX5_CMD_OP_SET_RATE_LIMIT = 0x780, MLX5_CMD_OP_QUERY_RATE_LIMIT = 0x781, + MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT = 0x782, + MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT = 0x783, + MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT = 0x784, + MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT = 0x785, + MLX5_CMD_OP_CREATE_QOS_PARA_VPORT = 0x786, + MLX5_CMD_OP_DESTROY_QOS_PARA_VPORT = 0x787, MLX5_CMD_OP_ALLOC_PD = 0x800, MLX5_CMD_OP_DEALLOC_PD = 0x801, MLX5_CMD_OP_ALLOC_UAR = 0x802, @@ -537,13 +543,27 @@ struct mlx5_ifc_e_switch_cap_bits { struct mlx5_ifc_qos_cap_bits { u8 packet_pacing[0x1]; - u8 reserved_0[0x1f]; - u8 reserved_1[0x20]; + u8 esw_scheduling[0x1]; + u8 reserved_at_2[0x1e]; + + u8 reserved_at_20[0x20]; + u8 packet_pacing_max_rate[0x20]; + u8 packet_pacing_min_rate[0x20]; - u8 reserved_2[0x10]; + + u8 reserved_at_80[0x10]; u8 packet_pacing_rate_table_size[0x10]; - u8 reserved_3[0x760]; + + u8 esw_element_type[0x10]; + u8 esw_tsar_type[0x10]; + + u8 reserved_at_c0[0x10]; + u8 max_qos_para_vport[0x10]; + + u8 max_tsar_bw_share[0x20]; + + u8 reserved_at_100[0x700]; }; struct mlx5_ifc_per_protocol_networking_offload_caps_bits { @@ -2333,6 +2353,30 @@ struct mlx5_ifc_sqc_bits { struct mlx5_ifc_wq_bits wq; }; +enum { + SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR = 0x0, + SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT = 0x1, + SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC = 0x2, + SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC = 0x3, +}; + +struct mlx5_ifc_scheduling_context_bits { + u8 element_type[0x8]; + u8 reserved_at_8[0x18]; + + u8 element_attributes[0x20]; + + u8 parent_element_id[0x20]; + + u8 reserved_at_60[0x40]; + + u8 bw_share[0x20]; + + u8 max_average_bw[0x20]; + + u8 reserved_at_e0[0x120]; +}; + struct mlx5_ifc_rqtc_bits { u8 reserved_at_0[0xa0]; @@ -2920,6 +2964,29 @@ struct mlx5_ifc_register_loopback_control_bits { u8 reserved_at_20[0x60]; }; +struct mlx5_ifc_vport_tc_element_bits { + u8 traffic_class[0x4]; + u8 reserved_at_4[0xc]; + u8 vport_number[0x10]; +}; + +struct mlx5_ifc_vport_element_bits { + u8 reserved_at_0[0x10]; + u8 vport_number[0x10]; +}; + +enum { + TSAR_ELEMENT_TSAR_TYPE_DWRR = 0x0, + TSAR_ELEMENT_TSAR_TYPE_ROUND_ROBIN = 0x1, + TSAR_ELEMENT_TSAR_TYPE_ETS = 0x2, +}; + +struct mlx5_ifc_tsar_element_bits { + u8 reserved_at_0[0x8]; + u8 tsar_type[0x8]; + u8 reserved_at_10[0x10]; +}; + struct mlx5_ifc_teardown_hca_out_bits { u8 status[0x8]; u8 reserved_at_8[0x18]; @@ -3540,6 +3607,39 @@ struct mlx5_ifc_query_special_contexts_in_bits { u8 reserved_at_40[0x40]; }; +struct mlx5_ifc_query_scheduling_element_out_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 reserved_at_40[0xc0]; + + struct mlx5_ifc_scheduling_context_bits scheduling_context; + + u8 reserved_at_300[0x100]; +}; + +enum { + SCHEDULING_HIERARCHY_E_SWITCH = 0x2, +}; + +struct mlx5_ifc_query_scheduling_element_in_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 scheduling_hierarchy[0x8]; + u8 reserved_at_48[0x18]; + + u8 scheduling_element_id[0x20]; + + u8 reserved_at_80[0x180]; +}; + struct mlx5_ifc_query_rqt_out_bits { u8 status[0x8]; u8 reserved_at_8[0x18]; @@ -4725,6 +4825,43 @@ struct mlx5_ifc_modify_sq_in_bits { struct mlx5_ifc_sqc_bits ctx; }; +struct mlx5_ifc_modify_scheduling_element_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x1c0]; +}; + +enum { + MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE = 0x1, + MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW = 0x2, +}; + +struct mlx5_ifc_modify_scheduling_element_in_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 scheduling_hierarchy[0x8]; + u8 reserved_at_48[0x18]; + + u8 scheduling_element_id[0x20]; + + u8 reserved_at_80[0x20]; + + u8 modify_bitmask[0x20]; + + u8 reserved_at_c0[0x40]; + + struct mlx5_ifc_scheduling_context_bits scheduling_context; + + u8 reserved_at_300[0x100]; +}; + struct mlx5_ifc_modify_rqt_out_bits { u8 status[0x8]; u8 reserved_at_8[0x18]; @@ -5390,6 +5527,30 @@ struct mlx5_ifc_destroy_sq_in_bits { u8 reserved_at_60[0x20]; }; +struct mlx5_ifc_destroy_scheduling_element_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x1c0]; +}; + +struct mlx5_ifc_destroy_scheduling_element_in_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 scheduling_hierarchy[0x8]; + u8 reserved_at_48[0x18]; + + u8 scheduling_element_id[0x20]; + + u8 reserved_at_80[0x180]; +}; + struct mlx5_ifc_destroy_rqt_out_bits { u8 status[0x8]; u8 reserved_at_8[0x18]; @@ -6017,6 +6178,36 @@ struct mlx5_ifc_create_sq_in_bits { struct mlx5_ifc_sqc_bits ctx; }; +struct mlx5_ifc_create_scheduling_element_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x40]; + + u8 scheduling_element_id[0x20]; + + u8 reserved_at_a0[0x160]; +}; + +struct mlx5_ifc_create_scheduling_element_in_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 scheduling_hierarchy[0x8]; + u8 reserved_at_48[0x18]; + + u8 reserved_at_60[0xa0]; + + struct mlx5_ifc_scheduling_context_bits scheduling_context; + + u8 reserved_at_300[0x100]; +}; + struct mlx5_ifc_create_rqt_out_bits { u8 status[0x8]; u8 reserved_at_8[0x18]; -- cgit v1.2.3 From 1bd27b11c1df33a1dc3277e2a0abbf6bd33cc817 Mon Sep 17 00:00:00 2001 From: Mohamad Haj Yahia Date: Thu, 11 Aug 2016 11:26:36 +0300 Subject: net/mlx5: Introduce E-switch QoS management Add TSAR to the eswitch which will act as the vports rate limiter. Create/Destroy TSAR on Enable/Dsiable SRIOV. Attach/Detach vport to eswitch TSAR on Enable/Disable vport. Signed-off-by: Mohamad Haj Yahia Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 113 +++++++++++++++++++++- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 12 +++ 2 files changed, 124 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index abbf2c369923..2e11a94d8365 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1351,6 +1351,106 @@ out: return err; } +/* Vport QoS management */ +static int esw_create_tsar(struct mlx5_eswitch *esw) +{ + u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; + struct mlx5_core_dev *dev = esw->dev; + int err; + + if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) + return 0; + + if (esw->qos.enabled) + return -EEXIST; + + err = mlx5_create_scheduling_element_cmd(dev, + SCHEDULING_HIERARCHY_E_SWITCH, + &tsar_ctx, + &esw->qos.root_tsar_id); + if (err) { + esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err); + return err; + } + + esw->qos.enabled = true; + return 0; +} + +static void esw_destroy_tsar(struct mlx5_eswitch *esw) +{ + int err; + + if (!esw->qos.enabled) + return; + + err = mlx5_destroy_scheduling_element_cmd(esw->dev, + SCHEDULING_HIERARCHY_E_SWITCH, + esw->qos.root_tsar_id); + if (err) + esw_warn(esw->dev, "E-Switch destroy TSAR failed (%d)\n", err); + + esw->qos.enabled = false; +} + +static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num, + u32 initial_max_rate) +{ + u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; + struct mlx5_vport *vport = &esw->vports[vport_num]; + struct mlx5_core_dev *dev = esw->dev; + void *vport_elem; + int err = 0; + + if (!esw->qos.enabled || !MLX5_CAP_GEN(dev, qos) || + !MLX5_CAP_QOS(dev, esw_scheduling)) + return 0; + + if (vport->qos.enabled) + return -EEXIST; + + MLX5_SET(scheduling_context, &sched_ctx, element_type, + SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT); + vport_elem = MLX5_ADDR_OF(scheduling_context, &sched_ctx, + element_attributes); + MLX5_SET(vport_element, vport_elem, vport_number, vport_num); + MLX5_SET(scheduling_context, &sched_ctx, parent_element_id, + esw->qos.root_tsar_id); + MLX5_SET(scheduling_context, &sched_ctx, max_average_bw, + initial_max_rate); + + err = mlx5_create_scheduling_element_cmd(dev, + SCHEDULING_HIERARCHY_E_SWITCH, + &sched_ctx, + &vport->qos.esw_tsar_ix); + if (err) { + esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n", + vport_num, err); + return err; + } + + vport->qos.enabled = true; + return 0; +} + +static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num) +{ + struct mlx5_vport *vport = &esw->vports[vport_num]; + int err = 0; + + if (!vport->qos.enabled) + return; + + err = mlx5_destroy_scheduling_element_cmd(esw->dev, + SCHEDULING_HIERARCHY_E_SWITCH, + vport->qos.esw_tsar_ix); + if (err) + esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n", + vport_num, err); + + vport->qos.enabled = false; +} + static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN]) { ((u8 *)node_guid)[7] = mac[0]; @@ -1386,6 +1486,7 @@ static void esw_apply_vport_conf(struct mlx5_eswitch *esw, esw_vport_egress_config(esw, vport); } } + static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, int enable_events) { @@ -1399,6 +1500,10 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, /* Restore old vport configuration */ esw_apply_vport_conf(esw, vport); + /* Attach vport to the eswitch rate limiter */ + if (esw_vport_enable_qos(esw, vport_num, vport->info.max_rate)) + esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num); + /* Sync with current vport context */ vport->enabled_events = enable_events; vport->enabled = true; @@ -1437,7 +1542,7 @@ static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num) */ esw_vport_change_handle_locked(vport); vport->enabled_events = 0; - + esw_vport_disable_qos(esw, vport_num); if (vport_num && esw->mode == SRIOV_LEGACY) { mlx5_modify_vport_admin_state(esw->dev, MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT, @@ -1483,6 +1588,10 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) if (err) goto abort; + err = esw_create_tsar(esw); + if (err) + esw_warn(esw->dev, "Failed to create eswitch TSAR"); + enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : UC_ADDR_CHANGE; for (i = 0; i <= nvfs; i++) esw_enable_vport(esw, i, enabled_events); @@ -1519,6 +1628,8 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) if (mc_promisc && mc_promisc->uplink_rule) mlx5_del_flow_rule(mc_promisc->uplink_rule); + esw_destroy_tsar(esw); + if (esw->mode == SRIOV_LEGACY) esw_destroy_legacy_fdb_table(esw); else if (esw->mode == SRIOV_OFFLOADS) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 2e2938e08cda..fb8de34b6baf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -115,6 +115,7 @@ struct mlx5_vport_info { u8 qos; u64 node_guid; int link_state; + u32 max_rate; bool spoofchk; bool trusted; }; @@ -133,6 +134,11 @@ struct mlx5_vport { struct mlx5_vport_info info; + struct { + bool enabled; + u32 esw_tsar_ix; + } qos; + bool enabled; u16 enabled_events; }; @@ -209,6 +215,12 @@ struct mlx5_eswitch { */ struct mutex state_lock; struct esw_mc_addr *mc_promisc; + + struct { + bool enabled; + u32 root_tsar_id; + } qos; + struct mlx5_esw_offload offloads; int mode; }; -- cgit v1.2.3 From bd77bf1cb595477528f06f5c52f913f70acd73bb Mon Sep 17 00:00:00 2001 From: Mohamad Haj Yahia Date: Thu, 11 Aug 2016 11:28:21 +0300 Subject: net/mlx5: Add SRIOV VF max rate configuration support Implement the vf set rate ndo by modifying the TSAR vport rate limit. Signed-off-by: Mohamad Haj Yahia Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 15 ++++++ drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 63 +++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 2 + 3 files changed, 80 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 7eaf38020a8f..7f763d2f63bb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2945,6 +2945,20 @@ static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting) return mlx5_eswitch_set_vport_trust(mdev->priv.eswitch, vf + 1, setting); } + +static int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate, + int max_tx_rate) +{ + struct mlx5e_priv *priv = netdev_priv(dev); + struct mlx5_core_dev *mdev = priv->mdev; + + if (min_tx_rate) + return -EOPNOTSUPP; + + return mlx5_eswitch_set_vport_rate(mdev->priv.eswitch, vf + 1, + max_tx_rate); +} + static int mlx5_vport_link2ifla(u8 esw_link) { switch (esw_link) { @@ -3252,6 +3266,7 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = { .ndo_set_vf_vlan = mlx5e_set_vf_vlan, .ndo_set_vf_spoofchk = mlx5e_set_vf_spoofchk, .ndo_set_vf_trust = mlx5e_set_vf_trust, + .ndo_set_vf_rate = mlx5e_set_vf_rate, .ndo_get_vf_config = mlx5e_get_vf_config, .ndo_set_vf_link_state = mlx5e_set_vf_link_state, .ndo_get_vf_stats = mlx5e_get_vf_stats, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 2e11a94d8365..9ef01d1bea06 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1451,6 +1451,47 @@ static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num) vport->qos.enabled = false; } +static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num, + u32 max_rate) +{ + u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; + struct mlx5_vport *vport = &esw->vports[vport_num]; + struct mlx5_core_dev *dev = esw->dev; + void *vport_elem; + u32 bitmask = 0; + int err = 0; + + if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) + return -EOPNOTSUPP; + + if (!vport->qos.enabled) + return -EIO; + + MLX5_SET(scheduling_context, &sched_ctx, element_type, + SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT); + vport_elem = MLX5_ADDR_OF(scheduling_context, &sched_ctx, + element_attributes); + MLX5_SET(vport_element, vport_elem, vport_number, vport_num); + MLX5_SET(scheduling_context, &sched_ctx, parent_element_id, + esw->qos.root_tsar_id); + MLX5_SET(scheduling_context, &sched_ctx, max_average_bw, + max_rate); + bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW; + + err = mlx5_modify_scheduling_element_cmd(dev, + SCHEDULING_HIERARCHY_E_SWITCH, + &sched_ctx, + vport->qos.esw_tsar_ix, + bitmask); + if (err) { + esw_warn(esw->dev, "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n", + vport_num, err); + return err; + } + + return 0; +} + static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN]) { ((u8 *)node_guid)[7] = mac[0]; @@ -1888,6 +1929,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, ivi->qos = evport->info.qos; ivi->spoofchk = evport->info.spoofchk; ivi->trusted = evport->info.trusted; + ivi->max_tx_rate = evport->info.max_rate; mutex_unlock(&esw->state_lock); return 0; @@ -1981,6 +2023,27 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, return 0; } +int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, + int vport, u32 max_rate) +{ + struct mlx5_vport *evport; + int err = 0; + + if (!ESW_ALLOWED(esw)) + return -EPERM; + if (!LEGAL_VPORT(esw, vport)) + return -EINVAL; + + mutex_lock(&esw->state_lock); + evport = &esw->vports[vport]; + err = esw_vport_qos_config(esw, vport, max_rate); + if (!err) + evport->info.max_rate = max_rate; + + mutex_unlock(&esw->state_lock); + return err; +} + int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, int vport, struct ifla_vf_stats *vf_stats) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index fb8de34b6baf..ddae90c1f15b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -246,6 +246,8 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw, int vport, bool spoofchk); int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, int vport_num, bool setting); +int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, + int vport, u32 max_rate); int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, int vport, struct ifla_vf_info *ivi); int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, -- cgit v1.2.3 From 0fd758d6112f867b2cc6df0f6a856048ff99b211 Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Mon, 5 Sep 2016 10:58:04 +0000 Subject: net/mlx5: Don't unlock fte while still using it When adding a new rule to an fte, we need to hold the fte lock until we add that rule to the fte and increase the fte ref count. Fixes: 0c56b97503fd ("net/mlx5_core: Introduce flow steering API") Signed-off-by: Mark Bloch Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 5da2cc878582..a07ff305b44f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1107,9 +1107,8 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, return rule; } rule = add_rule_fte(fte, fg, dest); - unlock_ref_node(&fte->node); if (IS_ERR(rule)) - goto unlock_fg; + goto unlock_fte; else goto add_rule; } @@ -1127,6 +1126,7 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, goto unlock_fg; } tree_init_node(&fte->node, 0, del_fte); + nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD); rule = add_rule_fte(fte, fg, dest); if (IS_ERR(rule)) { kfree(fte); @@ -1139,6 +1139,8 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, list_add(&fte->node.list, prev); add_rule: tree_add_node(&rule->node, &fte->node); +unlock_fte: + unlock_ref_node(&fte->node); unlock_fg: unlock_ref_node(&fg->node); return rule; -- cgit v1.2.3 From 0501fc477c2bed1cce02acbc22d79418bfa2c8c3 Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Sun, 11 Sep 2016 12:54:50 +0000 Subject: net/mlx5: Use fte status to decide on firmware command An fte status becomes FS_FTE_STATUS_EXISTING only after it was created in HW. We can use this in order to simplify the logic on what firmware command to use. If the status isn't FS_FTE_STATUS_EXISTING we need to create the fte, otherwise we need only to update it. Signed-off-by: Mark Bloch Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index a07ff305b44f..e2bab9d09acb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -946,7 +946,7 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST); } - if (fte->dests_size == 1 || !dest) + if (!(fte->status & FS_FTE_STATUS_EXISTING)) err = mlx5_cmd_create_fte(get_dev(&ft->node), ft, fg->id, fte); else -- cgit v1.2.3 From 814fb8754155ef9535cad4ef1ce06429fe7988c6 Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Fri, 16 Sep 2016 07:00:10 +0000 Subject: net/mlx5: Refactor find_flow_rule The way we compare between two dests will need to be used in other places in the future, so we factor out the comparison logic between two dests into a separate function. Signed-off-by: Mark Bloch Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 29 ++++++++++++++++------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index e2bab9d09acb..fca69379021e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -153,6 +153,8 @@ static void del_rule(struct fs_node *node); static void del_flow_table(struct fs_node *node); static void del_flow_group(struct fs_node *node); static void del_fte(struct fs_node *node); +static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1, + struct mlx5_flow_destination *d2); static void tree_init_node(struct fs_node *node, unsigned int refcount, @@ -1064,21 +1066,30 @@ out: return fg; } +static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1, + struct mlx5_flow_destination *d2) +{ + if (d1->type == d2->type) { + if ((d1->type == MLX5_FLOW_DESTINATION_TYPE_VPORT && + d1->vport_num == d2->vport_num) || + (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE && + d1->ft == d2->ft) || + (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR && + d1->tir_num == d2->tir_num)) + return true; + } + + return false; +} + static struct mlx5_flow_rule *find_flow_rule(struct fs_fte *fte, struct mlx5_flow_destination *dest) { struct mlx5_flow_rule *rule; list_for_each_entry(rule, &fte->node.children, node.list) { - if (rule->dest_attr.type == dest->type) { - if ((dest->type == MLX5_FLOW_DESTINATION_TYPE_VPORT && - dest->vport_num == rule->dest_attr.vport_num) || - (dest->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE && - dest->ft == rule->dest_attr.ft) || - (dest->type == MLX5_FLOW_DESTINATION_TYPE_TIR && - dest->tir_num == rule->dest_attr.tir_num)) - return rule; - } + if (mlx5_flow_dests_cmp(&rule->dest_attr, dest)) + return rule; } return NULL; } -- cgit v1.2.3 From a62249857779733dc7cb5d43d6ecdc35fa81b88f Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Sun, 11 Sep 2016 13:03:06 +0000 Subject: net/mlx5: Group similer rules under the same fte When adding a new rule, if we can match it with compare_match_value and flow tag we might be able to insert the rule to the same fte. In order to do that, there must be an overlap between the actions of the fte and the new rule. When updating the action of an existing fte, we must tell the firmware we are doing so. Signed-off-by: Mark Bloch Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index fca69379021e..43d7052c76fc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -920,7 +920,8 @@ static struct mlx5_flow_rule *alloc_rule(struct mlx5_flow_destination *dest) /* fte should not be deleted while calling this function */ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, struct mlx5_flow_group *fg, - struct mlx5_flow_destination *dest) + struct mlx5_flow_destination *dest, + bool update_action) { struct mlx5_flow_table *ft; struct mlx5_flow_rule *rule; @@ -931,6 +932,9 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, if (!rule) return ERR_PTR(-ENOMEM); + if (update_action) + modify_mask |= BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION); + fs_get_obj(ft, fg->node.parent); /* Add dest to dests list- we need flow tables to be in the * end of the list for forward to next prio rules. @@ -1109,7 +1113,9 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, fs_for_each_fte(fte, fg) { nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD); if (compare_match_value(&fg->mask, match_value, &fte->val) && - action == fte->action && flow_tag == fte->flow_tag) { + (action & fte->action) && flow_tag == fte->flow_tag) { + int old_action = fte->action; + rule = find_flow_rule(fte, dest); if (rule) { atomic_inc(&rule->node.refcount); @@ -1117,11 +1123,15 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, unlock_ref_node(&fg->node); return rule; } - rule = add_rule_fte(fte, fg, dest); - if (IS_ERR(rule)) + fte->action |= action; + rule = add_rule_fte(fte, fg, dest, + old_action != action); + if (IS_ERR(rule)) { + fte->action = old_action; goto unlock_fte; - else + } else { goto add_rule; + } } unlock_ref_node(&fte->node); } @@ -1138,7 +1148,7 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, } tree_init_node(&fte->node, 0, del_fte); nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD); - rule = add_rule_fte(fte, fg, dest); + rule = add_rule_fte(fte, fg, dest, false); if (IS_ERR(rule)) { kfree(fte); goto unlock_fg; -- cgit v1.2.3 From 74491de937125d0c98c9b9c9208b4105717a3caa Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Wed, 31 Aug 2016 11:24:25 +0000 Subject: net/mlx5: Add multi dest support Currently when calling mlx5_add_flow_rule we accept only one flow destination, this commit allows to pass multiple destinations. This change forces us to change the return structure to a more flexible one. We introduce a flow handle (struct mlx5_flow_handle), it holds internally the number for rules created and holds an array where each cell points the to a flow rule. From the consumers (of mlx5_add_flow_rule) point of view this change is only cosmetic and requires only to change the type of the returned value they store. From the core point of view, we now need to use a loop when allocating and deleting rules (e.g given to us a flow handler). Signed-off-by: Mark Bloch Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/mlx5/main.c | 14 +- drivers/infiniband/hw/mlx5/mlx5_ib.h | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en.h | 14 +- drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c | 38 +-- drivers/net/ethernet/mellanox/mlx5/core/en_fs.c | 49 ++-- .../ethernet/mellanox/mlx5/core/en_fs_ethtool.c | 19 +- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 6 +- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 32 +-- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 68 ++--- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 22 +- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 42 +-- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 289 ++++++++++++++------- drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | 5 + include/linux/mlx5/fs.h | 28 +- 14 files changed, 374 insertions(+), 254 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index d02341eebddb..8e0dbd51944e 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -1771,13 +1771,13 @@ static int mlx5_ib_destroy_flow(struct ib_flow *flow_id) mutex_lock(&dev->flow_db.lock); list_for_each_entry_safe(iter, tmp, &handler->list, list) { - mlx5_del_flow_rule(iter->rule); + mlx5_del_flow_rules(iter->rule); put_flow_table(dev, iter->prio, true); list_del(&iter->list); kfree(iter); } - mlx5_del_flow_rule(handler->rule); + mlx5_del_flow_rules(handler->rule); put_flow_table(dev, handler->prio, true); mutex_unlock(&dev->flow_db.lock); @@ -1907,10 +1907,10 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria); action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST : MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; - handler->rule = mlx5_add_flow_rule(ft, spec, + handler->rule = mlx5_add_flow_rules(ft, spec, action, MLX5_FS_DEFAULT_FLOW_TAG, - dst); + dst, 1); if (IS_ERR(handler->rule)) { err = PTR_ERR(handler->rule); @@ -1941,7 +1941,7 @@ static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *de handler_dst = create_flow_rule(dev, ft_prio, flow_attr, dst); if (IS_ERR(handler_dst)) { - mlx5_del_flow_rule(handler->rule); + mlx5_del_flow_rules(handler->rule); ft_prio->refcount--; kfree(handler); handler = handler_dst; @@ -2004,7 +2004,7 @@ static struct mlx5_ib_flow_handler *create_leftovers_rule(struct mlx5_ib_dev *de &leftovers_specs[LEFTOVERS_UC].flow_attr, dst); if (IS_ERR(handler_ucast)) { - mlx5_del_flow_rule(handler->rule); + mlx5_del_flow_rules(handler->rule); ft_prio->refcount--; kfree(handler); handler = handler_ucast; @@ -2046,7 +2046,7 @@ static struct mlx5_ib_flow_handler *create_sniffer_rule(struct mlx5_ib_dev *dev, return handler_rx; err_tx: - mlx5_del_flow_rule(handler_rx->rule); + mlx5_del_flow_rules(handler_rx->rule); ft_rx->refcount--; kfree(handler_rx); err: diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index dcdcd195fe53..d5d007740159 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -153,7 +153,7 @@ struct mlx5_ib_flow_handler { struct list_head list; struct ib_flow ibflow; struct mlx5_ib_flow_prio *prio; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; }; struct mlx5_ib_flow_db { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 460363b66cb1..47ee8ffe987f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -520,7 +520,7 @@ struct mlx5e_vxlan_db { struct mlx5e_l2_rule { u8 addr[ETH_ALEN + 2]; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; }; struct mlx5e_flow_table { @@ -541,10 +541,10 @@ struct mlx5e_tc_table { struct mlx5e_vlan_table { struct mlx5e_flow_table ft; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; - struct mlx5_flow_rule *active_vlans_rule[VLAN_N_VID]; - struct mlx5_flow_rule *untagged_rule; - struct mlx5_flow_rule *any_vlan_rule; - bool filter_disabled; + struct mlx5_flow_handle *active_vlans_rule[VLAN_N_VID]; + struct mlx5_flow_handle *untagged_rule; + struct mlx5_flow_handle *any_vlan_rule; + bool filter_disabled; }; struct mlx5e_l2_table { @@ -562,14 +562,14 @@ struct mlx5e_l2_table { /* L3/L4 traffic type classifier */ struct mlx5e_ttc_table { struct mlx5e_flow_table ft; - struct mlx5_flow_rule *rules[MLX5E_NUM_TT]; + struct mlx5_flow_handle *rules[MLX5E_NUM_TT]; }; #define ARFS_HASH_SHIFT BITS_PER_BYTE #define ARFS_HASH_SIZE BIT(BITS_PER_BYTE) struct arfs_table { struct mlx5e_flow_table ft; - struct mlx5_flow_rule *default_rule; + struct mlx5_flow_handle *default_rule; struct hlist_head rules_hash[ARFS_HASH_SIZE]; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c index a8cb38789774..8ff22e83e1dd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c @@ -56,7 +56,7 @@ struct arfs_tuple { struct arfs_rule { struct mlx5e_priv *priv; struct work_struct arfs_work; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; struct hlist_node hlist; int rxq; /* Flow ID passed to ndo_rx_flow_steer */ @@ -104,7 +104,7 @@ static int arfs_disable(struct mlx5e_priv *priv) tt = arfs_get_tt(i); /* Modify ttc rules destination to bypass the aRFS tables*/ err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt], - &dest); + &dest, NULL); if (err) { netdev_err(priv->netdev, "%s: modify ttc destination failed\n", @@ -137,7 +137,7 @@ int mlx5e_arfs_enable(struct mlx5e_priv *priv) tt = arfs_get_tt(i); /* Modify ttc rules destination to point on the aRFS FTs */ err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt], - &dest); + &dest, NULL); if (err) { netdev_err(priv->netdev, "%s: modify ttc destination failed err=%d\n", @@ -151,7 +151,7 @@ int mlx5e_arfs_enable(struct mlx5e_priv *priv) static void arfs_destroy_table(struct arfs_table *arfs_t) { - mlx5_del_flow_rule(arfs_t->default_rule); + mlx5_del_flow_rules(arfs_t->default_rule); mlx5e_destroy_flow_table(&arfs_t->ft); } @@ -205,10 +205,10 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv, goto out; } - arfs_t->default_rule = mlx5_add_flow_rule(arfs_t->ft.t, spec, - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - MLX5_FS_DEFAULT_FLOW_TAG, - &dest); + arfs_t->default_rule = mlx5_add_flow_rules(arfs_t->ft.t, spec, + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + MLX5_FS_DEFAULT_FLOW_TAG, + &dest, 1); if (IS_ERR(arfs_t->default_rule)) { err = PTR_ERR(arfs_t->default_rule); arfs_t->default_rule = NULL; @@ -396,7 +396,7 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv) spin_unlock_bh(&priv->fs.arfs.arfs_lock); hlist_for_each_entry_safe(arfs_rule, htmp, &del_list, hlist) { if (arfs_rule->rule) - mlx5_del_flow_rule(arfs_rule->rule); + mlx5_del_flow_rules(arfs_rule->rule); hlist_del(&arfs_rule->hlist); kfree(arfs_rule); } @@ -420,7 +420,7 @@ static void arfs_del_rules(struct mlx5e_priv *priv) hlist_for_each_entry_safe(rule, htmp, &del_list, hlist) { cancel_work_sync(&rule->arfs_work); if (rule->rule) - mlx5_del_flow_rule(rule->rule); + mlx5_del_flow_rules(rule->rule); hlist_del(&rule->hlist); kfree(rule); } @@ -462,12 +462,12 @@ static struct arfs_table *arfs_get_table(struct mlx5e_arfs_tables *arfs, return NULL; } -static struct mlx5_flow_rule *arfs_add_rule(struct mlx5e_priv *priv, - struct arfs_rule *arfs_rule) +static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv, + struct arfs_rule *arfs_rule) { struct mlx5e_arfs_tables *arfs = &priv->fs.arfs; struct arfs_tuple *tuple = &arfs_rule->tuple; - struct mlx5_flow_rule *rule = NULL; + struct mlx5_flow_handle *rule = NULL; struct mlx5_flow_destination dest; struct arfs_table *arfs_table; struct mlx5_flow_spec *spec; @@ -544,9 +544,9 @@ static struct mlx5_flow_rule *arfs_add_rule(struct mlx5e_priv *priv, } dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR; dest.tir_num = priv->direct_tir[arfs_rule->rxq].tirn; - rule = mlx5_add_flow_rule(ft, spec, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - MLX5_FS_DEFAULT_FLOW_TAG, - &dest); + rule = mlx5_add_flow_rules(ft, spec, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + MLX5_FS_DEFAULT_FLOW_TAG, + &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); netdev_err(priv->netdev, "%s: add rule(filter id=%d, rq idx=%d) failed, err=%d\n", @@ -559,14 +559,14 @@ out: } static void arfs_modify_rule_rq(struct mlx5e_priv *priv, - struct mlx5_flow_rule *rule, u16 rxq) + struct mlx5_flow_handle *rule, u16 rxq) { struct mlx5_flow_destination dst; int err = 0; dst.type = MLX5_FLOW_DESTINATION_TYPE_TIR; dst.tir_num = priv->direct_tir[rxq].tirn; - err = mlx5_modify_rule_destination(rule, &dst); + err = mlx5_modify_rule_destination(rule, &dst, NULL); if (err) netdev_warn(priv->netdev, "Failed to modfiy aRFS rule destination to rq=%d\n", rxq); @@ -578,7 +578,7 @@ static void arfs_handle_work(struct work_struct *work) struct arfs_rule, arfs_work); struct mlx5e_priv *priv = arfs_rule->priv; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; mutex_lock(&priv->state_lock); if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index 36fbc6b21a33..bed544d47ba1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -160,7 +160,7 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv, { struct mlx5_flow_table *ft = priv->fs.vlan.ft.t; struct mlx5_flow_destination dest; - struct mlx5_flow_rule **rule_p; + struct mlx5_flow_handle **rule_p; int err = 0; dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; @@ -187,10 +187,10 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv, break; } - *rule_p = mlx5_add_flow_rule(ft, spec, - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - MLX5_FS_DEFAULT_FLOW_TAG, - &dest); + *rule_p = mlx5_add_flow_rules(ft, spec, + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + MLX5_FS_DEFAULT_FLOW_TAG, + &dest, 1); if (IS_ERR(*rule_p)) { err = PTR_ERR(*rule_p); @@ -229,20 +229,20 @@ static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv, switch (rule_type) { case MLX5E_VLAN_RULE_TYPE_UNTAGGED: if (priv->fs.vlan.untagged_rule) { - mlx5_del_flow_rule(priv->fs.vlan.untagged_rule); + mlx5_del_flow_rules(priv->fs.vlan.untagged_rule); priv->fs.vlan.untagged_rule = NULL; } break; case MLX5E_VLAN_RULE_TYPE_ANY_VID: if (priv->fs.vlan.any_vlan_rule) { - mlx5_del_flow_rule(priv->fs.vlan.any_vlan_rule); + mlx5_del_flow_rules(priv->fs.vlan.any_vlan_rule); priv->fs.vlan.any_vlan_rule = NULL; } break; case MLX5E_VLAN_RULE_TYPE_MATCH_VID: mlx5e_vport_context_update_vlans(priv); if (priv->fs.vlan.active_vlans_rule[vid]) { - mlx5_del_flow_rule(priv->fs.vlan.active_vlans_rule[vid]); + mlx5_del_flow_rules(priv->fs.vlan.active_vlans_rule[vid]); priv->fs.vlan.active_vlans_rule[vid] = NULL; } mlx5e_vport_context_update_vlans(priv); @@ -560,7 +560,7 @@ static void mlx5e_cleanup_ttc_rules(struct mlx5e_ttc_table *ttc) for (i = 0; i < MLX5E_NUM_TT; i++) { if (!IS_ERR_OR_NULL(ttc->rules[i])) { - mlx5_del_flow_rule(ttc->rules[i]); + mlx5_del_flow_rules(ttc->rules[i]); ttc->rules[i] = NULL; } } @@ -616,13 +616,14 @@ static struct { }, }; -static struct mlx5_flow_rule *mlx5e_generate_ttc_rule(struct mlx5e_priv *priv, - struct mlx5_flow_table *ft, - struct mlx5_flow_destination *dest, - u16 etype, - u8 proto) +static struct mlx5_flow_handle * +mlx5e_generate_ttc_rule(struct mlx5e_priv *priv, + struct mlx5_flow_table *ft, + struct mlx5_flow_destination *dest, + u16 etype, + u8 proto) { - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; int err = 0; @@ -643,10 +644,10 @@ static struct mlx5_flow_rule *mlx5e_generate_ttc_rule(struct mlx5e_priv *priv, MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, etype); } - rule = mlx5_add_flow_rule(ft, spec, - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - MLX5_FS_DEFAULT_FLOW_TAG, - dest); + rule = mlx5_add_flow_rules(ft, spec, + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + MLX5_FS_DEFAULT_FLOW_TAG, + dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); netdev_err(priv->netdev, "%s: add rule failed\n", __func__); @@ -660,7 +661,7 @@ static int mlx5e_generate_ttc_table_rules(struct mlx5e_priv *priv) { struct mlx5_flow_destination dest; struct mlx5e_ttc_table *ttc; - struct mlx5_flow_rule **rules; + struct mlx5_flow_handle **rules; struct mlx5_flow_table *ft; int tt; int err; @@ -801,7 +802,7 @@ static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv, struct mlx5e_l2_rule *ai) { if (!IS_ERR_OR_NULL(ai->rule)) { - mlx5_del_flow_rule(ai->rule); + mlx5_del_flow_rules(ai->rule); ai->rule = NULL; } } @@ -847,9 +848,9 @@ static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv, break; } - ai->rule = mlx5_add_flow_rule(ft, spec, - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - MLX5_FS_DEFAULT_FLOW_TAG, &dest); + ai->rule = mlx5_add_flow_rules(ft, spec, + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + MLX5_FS_DEFAULT_FLOW_TAG, &dest, 1); if (IS_ERR(ai->rule)) { netdev_err(priv->netdev, "%s: add l2 rule(mac:%pM) failed\n", __func__, mv_dmac); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c index d17c24227900..cf52c06377f2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c @@ -36,7 +36,7 @@ struct mlx5e_ethtool_rule { struct list_head list; struct ethtool_rx_flow_spec flow_spec; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; struct mlx5e_ethtool_table *eth_ft; }; @@ -284,13 +284,14 @@ static bool outer_header_zero(u32 *match_criteria) size - 1); } -static struct mlx5_flow_rule *add_ethtool_flow_rule(struct mlx5e_priv *priv, - struct mlx5_flow_table *ft, - struct ethtool_rx_flow_spec *fs) +static struct mlx5_flow_handle * +add_ethtool_flow_rule(struct mlx5e_priv *priv, + struct mlx5_flow_table *ft, + struct ethtool_rx_flow_spec *fs) { struct mlx5_flow_destination *dst = NULL; struct mlx5_flow_spec *spec; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; int err = 0; u32 action; @@ -317,8 +318,8 @@ static struct mlx5_flow_rule *add_ethtool_flow_rule(struct mlx5e_priv *priv, } spec->match_criteria_enable = (!outer_header_zero(spec->match_criteria)); - rule = mlx5_add_flow_rule(ft, spec, action, - MLX5_FS_DEFAULT_FLOW_TAG, dst); + rule = mlx5_add_flow_rules(ft, spec, action, + MLX5_FS_DEFAULT_FLOW_TAG, dst, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); netdev_err(priv->netdev, "%s: failed to add ethtool steering rule: %d\n", @@ -335,7 +336,7 @@ static void del_ethtool_rule(struct mlx5e_priv *priv, struct mlx5e_ethtool_rule *eth_rule) { if (eth_rule->rule) - mlx5_del_flow_rule(eth_rule->rule); + mlx5_del_flow_rules(eth_rule->rule); list_del(ð_rule->list); priv->fs.ethtool.tot_num_rules--; put_flow_table(eth_rule->eth_ft); @@ -475,7 +476,7 @@ int mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv, { struct mlx5e_ethtool_table *eth_ft; struct mlx5e_ethtool_rule *eth_rule; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; int num_tuples; int err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 3c97da103d30..88d3fd132d63 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -328,7 +328,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_eswitch_rep *rep = priv->ppriv; struct mlx5_core_dev *mdev = priv->mdev; - struct mlx5_flow_rule *flow_rule; + struct mlx5_flow_handle *flow_rule; int err; int i; @@ -360,7 +360,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) return 0; err_del_flow_rule: - mlx5_del_flow_rule(rep->vport_rx_rule); + mlx5_del_flow_rules(rep->vport_rx_rule); err_destroy_direct_tirs: mlx5e_destroy_direct_tirs(priv); err_destroy_direct_rqts: @@ -375,7 +375,7 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv) int i; mlx5e_tc_cleanup(priv); - mlx5_del_flow_rule(rep->vport_rx_rule); + mlx5_del_flow_rules(rep->vport_rx_rule); mlx5e_destroy_direct_tirs(priv); for (i = 0; i < priv->params.num_channels; i++) mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index ce8c54d18906..5d9ac0dbf3bf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -47,21 +47,22 @@ struct mlx5e_tc_flow { struct rhash_head node; u64 cookie; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; struct mlx5_esw_flow_attr *attr; }; #define MLX5E_TC_TABLE_NUM_ENTRIES 1024 #define MLX5E_TC_TABLE_NUM_GROUPS 4 -static struct mlx5_flow_rule *mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, - struct mlx5_flow_spec *spec, - u32 action, u32 flow_tag) +static struct mlx5_flow_handle * +mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, + struct mlx5_flow_spec *spec, + u32 action, u32 flow_tag) { struct mlx5_core_dev *dev = priv->mdev; struct mlx5_flow_destination dest = { 0 }; struct mlx5_fc *counter = NULL; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; bool table_created = false; if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { @@ -94,9 +95,9 @@ static struct mlx5_flow_rule *mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, } spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; - rule = mlx5_add_flow_rule(priv->fs.tc.t, spec, - action, flow_tag, - &dest); + rule = mlx5_add_flow_rules(priv->fs.tc.t, spec, + action, flow_tag, + &dest, 1); if (IS_ERR(rule)) goto err_add_rule; @@ -114,9 +115,10 @@ err_create_ft: return rule; } -static struct mlx5_flow_rule *mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, - struct mlx5_flow_spec *spec, - struct mlx5_esw_flow_attr *attr) +static struct mlx5_flow_handle * +mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, + struct mlx5_flow_spec *spec, + struct mlx5_esw_flow_attr *attr) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; int err; @@ -129,7 +131,7 @@ static struct mlx5_flow_rule *mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, } static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, - struct mlx5_flow_rule *rule, + struct mlx5_flow_handle *rule, struct mlx5_esw_flow_attr *attr) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; @@ -140,7 +142,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, if (esw && esw->mode == SRIOV_OFFLOADS) mlx5_eswitch_del_vlan_action(esw, attr); - mlx5_del_flow_rule(rule); + mlx5_del_flow_rules(rule); mlx5_fc_destroy(priv->mdev, counter); @@ -450,7 +452,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol, u32 flow_tag, action; struct mlx5e_tc_flow *flow; struct mlx5_flow_spec *spec; - struct mlx5_flow_rule *old = NULL; + struct mlx5_flow_handle *old = NULL; struct mlx5_esw_flow_attr *old_attr = NULL; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; @@ -511,7 +513,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol, goto out; err_del_rule: - mlx5_del_flow_rule(flow->rule); + mlx5_del_flow_rules(flow->rule); err_free: if (!old) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 9ef01d1bea06..fcd8b15f6625 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -56,7 +56,7 @@ struct esw_uc_addr { /* E-Switch MC FDB table hash node */ struct esw_mc_addr { /* SRIOV only */ struct l2addr_node node; - struct mlx5_flow_rule *uplink_rule; /* Forward to uplink rule */ + struct mlx5_flow_handle *uplink_rule; /* Forward to uplink rule */ u32 refcnt; }; @@ -65,7 +65,7 @@ struct vport_addr { struct l2addr_node node; u8 action; u32 vport; - struct mlx5_flow_rule *flow_rule; /* SRIOV only */ + struct mlx5_flow_handle *flow_rule; /* SRIOV only */ /* A flag indicating that mac was added due to mc promiscuous vport */ bool mc_promisc; }; @@ -237,13 +237,13 @@ static void del_l2_table_entry(struct mlx5_core_dev *dev, u32 index) } /* E-Switch FDB */ -static struct mlx5_flow_rule * +static struct mlx5_flow_handle * __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule, u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN]) { int match_header = (is_zero_ether_addr(mac_c) ? 0 : MLX5_MATCH_OUTER_HEADERS); - struct mlx5_flow_rule *flow_rule = NULL; + struct mlx5_flow_handle *flow_rule = NULL; struct mlx5_flow_destination dest; struct mlx5_flow_spec *spec; void *mv_misc = NULL; @@ -286,9 +286,9 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule, dmac_v, dmac_c, vport); spec->match_criteria_enable = match_header; flow_rule = - mlx5_add_flow_rule(esw->fdb_table.fdb, spec, - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - 0, &dest); + mlx5_add_flow_rules(esw->fdb_table.fdb, spec, + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + 0, &dest, 1); if (IS_ERR(flow_rule)) { esw_warn(esw->dev, "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n", @@ -300,7 +300,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule, return flow_rule; } -static struct mlx5_flow_rule * +static struct mlx5_flow_handle * esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport) { u8 mac_c[ETH_ALEN]; @@ -309,7 +309,7 @@ esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport) return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac); } -static struct mlx5_flow_rule * +static struct mlx5_flow_handle * esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport) { u8 mac_c[ETH_ALEN]; @@ -322,7 +322,7 @@ esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport) return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v); } -static struct mlx5_flow_rule * +static struct mlx5_flow_handle * esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u32 vport) { u8 mac_c[ETH_ALEN]; @@ -515,7 +515,7 @@ static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) del_l2_table_entry(esw->dev, esw_uc->table_index); if (vaddr->flow_rule) - mlx5_del_flow_rule(vaddr->flow_rule); + mlx5_del_flow_rules(vaddr->flow_rule); vaddr->flow_rule = NULL; l2addr_hash_del(esw_uc); @@ -562,7 +562,7 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw, case MLX5_ACTION_DEL: if (!iter_vaddr) continue; - mlx5_del_flow_rule(iter_vaddr->flow_rule); + mlx5_del_flow_rules(iter_vaddr->flow_rule); l2addr_hash_del(iter_vaddr); break; } @@ -632,7 +632,7 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) esw_mc->uplink_rule); if (vaddr->flow_rule) - mlx5_del_flow_rule(vaddr->flow_rule); + mlx5_del_flow_rules(vaddr->flow_rule); vaddr->flow_rule = NULL; /* If the multicast mac is added as a result of mc promiscuous vport, @@ -645,7 +645,7 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) update_allmulti_vports(esw, vaddr, esw_mc); if (esw_mc->uplink_rule) - mlx5_del_flow_rule(esw_mc->uplink_rule); + mlx5_del_flow_rules(esw_mc->uplink_rule); l2addr_hash_del(esw_mc); return 0; @@ -828,14 +828,14 @@ static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num, UPLINK_VPORT); allmulti_addr->refcnt++; } else if (vport->allmulti_rule) { - mlx5_del_flow_rule(vport->allmulti_rule); + mlx5_del_flow_rules(vport->allmulti_rule); vport->allmulti_rule = NULL; if (--allmulti_addr->refcnt > 0) goto promisc; if (allmulti_addr->uplink_rule) - mlx5_del_flow_rule(allmulti_addr->uplink_rule); + mlx5_del_flow_rules(allmulti_addr->uplink_rule); allmulti_addr->uplink_rule = NULL; } @@ -847,7 +847,7 @@ promisc: vport->promisc_rule = esw_fdb_set_vport_promisc_rule(esw, vport_num); } else if (vport->promisc_rule) { - mlx5_del_flow_rule(vport->promisc_rule); + mlx5_del_flow_rules(vport->promisc_rule); vport->promisc_rule = NULL; } } @@ -1015,10 +1015,10 @@ static void esw_vport_cleanup_egress_rules(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { if (!IS_ERR_OR_NULL(vport->egress.allowed_vlan)) - mlx5_del_flow_rule(vport->egress.allowed_vlan); + mlx5_del_flow_rules(vport->egress.allowed_vlan); if (!IS_ERR_OR_NULL(vport->egress.drop_rule)) - mlx5_del_flow_rule(vport->egress.drop_rule); + mlx5_del_flow_rules(vport->egress.drop_rule); vport->egress.allowed_vlan = NULL; vport->egress.drop_rule = NULL; @@ -1173,10 +1173,10 @@ static void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { if (!IS_ERR_OR_NULL(vport->ingress.drop_rule)) - mlx5_del_flow_rule(vport->ingress.drop_rule); + mlx5_del_flow_rules(vport->ingress.drop_rule); if (!IS_ERR_OR_NULL(vport->ingress.allow_rule)) - mlx5_del_flow_rule(vport->ingress.allow_rule); + mlx5_del_flow_rules(vport->ingress.allow_rule); vport->ingress.drop_rule = NULL; vport->ingress.allow_rule = NULL; @@ -1253,9 +1253,9 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw, spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; vport->ingress.allow_rule = - mlx5_add_flow_rule(vport->ingress.acl, spec, - MLX5_FLOW_CONTEXT_ACTION_ALLOW, - 0, NULL); + mlx5_add_flow_rules(vport->ingress.acl, spec, + MLX5_FLOW_CONTEXT_ACTION_ALLOW, + 0, NULL, 0); if (IS_ERR(vport->ingress.allow_rule)) { err = PTR_ERR(vport->ingress.allow_rule); esw_warn(esw->dev, @@ -1267,9 +1267,9 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw, memset(spec, 0, sizeof(*spec)); vport->ingress.drop_rule = - mlx5_add_flow_rule(vport->ingress.acl, spec, - MLX5_FLOW_CONTEXT_ACTION_DROP, - 0, NULL); + mlx5_add_flow_rules(vport->ingress.acl, spec, + MLX5_FLOW_CONTEXT_ACTION_DROP, + 0, NULL, 0); if (IS_ERR(vport->ingress.drop_rule)) { err = PTR_ERR(vport->ingress.drop_rule); esw_warn(esw->dev, @@ -1321,9 +1321,9 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw, spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; vport->egress.allowed_vlan = - mlx5_add_flow_rule(vport->egress.acl, spec, - MLX5_FLOW_CONTEXT_ACTION_ALLOW, - 0, NULL); + mlx5_add_flow_rules(vport->egress.acl, spec, + MLX5_FLOW_CONTEXT_ACTION_ALLOW, + 0, NULL, 0); if (IS_ERR(vport->egress.allowed_vlan)) { err = PTR_ERR(vport->egress.allowed_vlan); esw_warn(esw->dev, @@ -1336,9 +1336,9 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw, /* Drop others rule (star rule) */ memset(spec, 0, sizeof(*spec)); vport->egress.drop_rule = - mlx5_add_flow_rule(vport->egress.acl, spec, - MLX5_FLOW_CONTEXT_ACTION_DROP, - 0, NULL); + mlx5_add_flow_rules(vport->egress.acl, spec, + MLX5_FLOW_CONTEXT_ACTION_DROP, + 0, NULL, 0); if (IS_ERR(vport->egress.drop_rule)) { err = PTR_ERR(vport->egress.drop_rule); esw_warn(esw->dev, @@ -1667,7 +1667,7 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) esw_disable_vport(esw, i); if (mc_promisc && mc_promisc->uplink_rule) - mlx5_del_flow_rule(mc_promisc->uplink_rule); + mlx5_del_flow_rules(mc_promisc->uplink_rule); esw_destroy_tsar(esw); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index ddae90c1f15b..6d414cb1b75f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -97,16 +97,16 @@ struct vport_ingress { struct mlx5_flow_group *allow_spoofchk_only_grp; struct mlx5_flow_group *allow_untagged_only_grp; struct mlx5_flow_group *drop_grp; - struct mlx5_flow_rule *allow_rule; - struct mlx5_flow_rule *drop_rule; + struct mlx5_flow_handle *allow_rule; + struct mlx5_flow_handle *drop_rule; }; struct vport_egress { struct mlx5_flow_table *acl; struct mlx5_flow_group *allowed_vlans_grp; struct mlx5_flow_group *drop_grp; - struct mlx5_flow_rule *allowed_vlan; - struct mlx5_flow_rule *drop_rule; + struct mlx5_flow_handle *allowed_vlan; + struct mlx5_flow_handle *drop_rule; }; struct mlx5_vport_info { @@ -125,8 +125,8 @@ struct mlx5_vport { int vport; struct hlist_head uc_list[MLX5_L2_ADDR_HASH_SIZE]; struct hlist_head mc_list[MLX5_L2_ADDR_HASH_SIZE]; - struct mlx5_flow_rule *promisc_rule; - struct mlx5_flow_rule *allmulti_rule; + struct mlx5_flow_handle *promisc_rule; + struct mlx5_flow_handle *allmulti_rule; struct work_struct vport_change_handler; struct vport_ingress ingress; @@ -162,7 +162,7 @@ struct mlx5_eswitch_fdb { struct mlx5_flow_table *fdb; struct mlx5_flow_group *send_to_vport_grp; struct mlx5_flow_group *miss_grp; - struct mlx5_flow_rule *miss_rule; + struct mlx5_flow_handle *miss_rule; int vlan_push_pop_refcount; } offloads; }; @@ -175,7 +175,7 @@ enum { }; struct mlx5_esw_sq { - struct mlx5_flow_rule *send_to_vport_rule; + struct mlx5_flow_handle *send_to_vport_rule; struct list_head list; }; @@ -188,7 +188,7 @@ struct mlx5_eswitch_rep { u8 hw_id[ETH_ALEN]; void *priv_data; - struct mlx5_flow_rule *vport_rx_rule; + struct mlx5_flow_handle *vport_rx_rule; struct list_head vport_sqs_list; u16 vlan; u32 vlan_refcount; @@ -257,11 +257,11 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, struct mlx5_flow_spec; struct mlx5_esw_flow_attr; -struct mlx5_flow_rule * +struct mlx5_flow_handle * mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, struct mlx5_flow_spec *spec, struct mlx5_esw_flow_attr *attr); -struct mlx5_flow_rule * +struct mlx5_flow_handle * mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn); enum { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index c55ad8d00c05..8b2a3832cd0a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -43,14 +43,14 @@ enum { FDB_SLOW_PATH }; -struct mlx5_flow_rule * +struct mlx5_flow_handle * mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, struct mlx5_flow_spec *spec, struct mlx5_esw_flow_attr *attr) { struct mlx5_flow_destination dest = { 0 }; struct mlx5_fc *counter = NULL; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; void *misc; int action; @@ -80,8 +80,8 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS; - rule = mlx5_add_flow_rule((struct mlx5_flow_table *)esw->fdb_table.fdb, - spec, action, 0, &dest); + rule = mlx5_add_flow_rules((struct mlx5_flow_table *)esw->fdb_table.fdb, + spec, action, 0, &dest, 1); if (IS_ERR(rule)) mlx5_fc_destroy(esw->dev, counter); @@ -269,11 +269,11 @@ out: return err; } -static struct mlx5_flow_rule * +static struct mlx5_flow_handle * mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn) { struct mlx5_flow_destination dest; - struct mlx5_flow_rule *flow_rule; + struct mlx5_flow_handle *flow_rule; struct mlx5_flow_spec *spec; void *misc; @@ -296,9 +296,9 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; dest.vport_num = vport; - flow_rule = mlx5_add_flow_rule(esw->fdb_table.offloads.fdb, spec, - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - 0, &dest); + flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.fdb, spec, + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + 0, &dest, 1); if (IS_ERR(flow_rule)) esw_warn(esw->dev, "FDB: Failed to add send to vport rule err %ld\n", PTR_ERR(flow_rule)); out: @@ -315,7 +315,7 @@ void mlx5_eswitch_sqs2vport_stop(struct mlx5_eswitch *esw, return; list_for_each_entry_safe(esw_sq, tmp, &rep->vport_sqs_list, list) { - mlx5_del_flow_rule(esw_sq->send_to_vport_rule); + mlx5_del_flow_rules(esw_sq->send_to_vport_rule); list_del(&esw_sq->list); kfree(esw_sq); } @@ -325,7 +325,7 @@ int mlx5_eswitch_sqs2vport_start(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, u16 *sqns_array, int sqns_num) { - struct mlx5_flow_rule *flow_rule; + struct mlx5_flow_handle *flow_rule; struct mlx5_esw_sq *esw_sq; int err; int i; @@ -362,7 +362,7 @@ out_err: static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw) { struct mlx5_flow_destination dest; - struct mlx5_flow_rule *flow_rule = NULL; + struct mlx5_flow_handle *flow_rule = NULL; struct mlx5_flow_spec *spec; int err = 0; @@ -376,9 +376,9 @@ static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw) dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; dest.vport_num = 0; - flow_rule = mlx5_add_flow_rule(esw->fdb_table.offloads.fdb, spec, - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - 0, &dest); + flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.fdb, spec, + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + 0, &dest, 1); if (IS_ERR(flow_rule)) { err = PTR_ERR(flow_rule); esw_warn(esw->dev, "FDB: Failed to add miss flow rule err %d\n", err); @@ -501,7 +501,7 @@ static void esw_destroy_offloads_fdb_table(struct mlx5_eswitch *esw) return; esw_debug(esw->dev, "Destroy offloads FDB Table\n"); - mlx5_del_flow_rule(esw->fdb_table.offloads.miss_rule); + mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule); mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp); mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp); @@ -585,11 +585,11 @@ static void esw_destroy_vport_rx_group(struct mlx5_eswitch *esw) mlx5_destroy_flow_group(esw->offloads.vport_rx_group); } -struct mlx5_flow_rule * +struct mlx5_flow_handle * mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn) { struct mlx5_flow_destination dest; - struct mlx5_flow_rule *flow_rule; + struct mlx5_flow_handle *flow_rule; struct mlx5_flow_spec *spec; void *misc; @@ -610,9 +610,9 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn) dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR; dest.tir_num = tirn; - flow_rule = mlx5_add_flow_rule(esw->offloads.ft_offloads, spec, - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, - 0, &dest); + flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec, + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, + 0, &dest, 1); if (IS_ERR(flow_rule)) { esw_warn(esw->dev, "fs offloads: Failed to add vport rx rule err %ld\n", PTR_ERR(flow_rule)); goto out; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 43d7052c76fc..6732287a98c8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -155,6 +155,9 @@ static void del_flow_group(struct fs_node *node); static void del_fte(struct fs_node *node); static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1, struct mlx5_flow_destination *d2); +static struct mlx5_flow_rule * +find_flow_rule(struct fs_fte *fte, + struct mlx5_flow_destination *dest); static void tree_init_node(struct fs_node *node, unsigned int refcount, @@ -640,8 +643,8 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio return err; } -int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, - struct mlx5_flow_destination *dest) +static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, + struct mlx5_flow_destination *dest) { struct mlx5_flow_table *ft; struct mlx5_flow_group *fg; @@ -666,6 +669,28 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, return err; } +int mlx5_modify_rule_destination(struct mlx5_flow_handle *handle, + struct mlx5_flow_destination *new_dest, + struct mlx5_flow_destination *old_dest) +{ + int i; + + if (!old_dest) { + if (handle->num_rules != 1) + return -EINVAL; + return _mlx5_modify_rule_destination(handle->rule[0], + new_dest); + } + + for (i = 0; i < handle->num_rules; i++) { + if (mlx5_flow_dests_cmp(new_dest, &handle->rule[i]->dest_attr)) + return _mlx5_modify_rule_destination(handle->rule[i], + new_dest); + } + + return -EINVAL; +} + /* Modify/set FWD rules that point on old_next_ft to point on new_next_ft */ static int connect_fwd_rules(struct mlx5_core_dev *dev, struct mlx5_flow_table *new_next_ft, @@ -688,7 +713,7 @@ static int connect_fwd_rules(struct mlx5_core_dev *dev, list_splice_init(&old_next_ft->fwd_rules, &new_next_ft->fwd_rules); mutex_unlock(&old_next_ft->lock); list_for_each_entry(iter, &new_next_ft->fwd_rules, next_ft) { - err = mlx5_modify_rule_destination(iter, &dest); + err = _mlx5_modify_rule_destination(iter, &dest); if (err) pr_err("mlx5_core: failed to modify rule to point on flow table %d\n", new_next_ft->id); @@ -917,41 +942,117 @@ static struct mlx5_flow_rule *alloc_rule(struct mlx5_flow_destination *dest) return rule; } -/* fte should not be deleted while calling this function */ -static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, - struct mlx5_flow_group *fg, - struct mlx5_flow_destination *dest, - bool update_action) +static struct mlx5_flow_handle *alloc_handle(int num_rules) { + struct mlx5_flow_handle *handle; + + handle = kzalloc(sizeof(*handle) + sizeof(handle->rule[0]) * + num_rules, GFP_KERNEL); + if (!handle) + return NULL; + + handle->num_rules = num_rules; + + return handle; +} + +static void destroy_flow_handle(struct fs_fte *fte, + struct mlx5_flow_handle *handle, + struct mlx5_flow_destination *dest, + int i) +{ + for (; --i >= 0;) { + if (atomic_dec_and_test(&handle->rule[i]->node.refcount)) { + fte->dests_size--; + list_del(&handle->rule[i]->node.list); + kfree(handle->rule[i]); + } + } + kfree(handle); +} + +static struct mlx5_flow_handle * +create_flow_handle(struct fs_fte *fte, + struct mlx5_flow_destination *dest, + int dest_num, + int *modify_mask, + bool *new_rule) +{ + struct mlx5_flow_handle *handle; + struct mlx5_flow_rule *rule = NULL; + static int count = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS); + static int dst = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST); + int type; + int i = 0; + + handle = alloc_handle((dest_num) ? dest_num : 1); + if (!handle) + return ERR_PTR(-ENOMEM); + + do { + if (dest) { + rule = find_flow_rule(fte, dest + i); + if (rule) { + atomic_inc(&rule->node.refcount); + goto rule_found; + } + } + + *new_rule = true; + rule = alloc_rule(dest + i); + if (!rule) + goto free_rules; + + /* Add dest to dests list- we need flow tables to be in the + * end of the list for forward to next prio rules. + */ + tree_init_node(&rule->node, 1, del_rule); + if (dest && + dest[i].type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) + list_add(&rule->node.list, &fte->node.children); + else + list_add_tail(&rule->node.list, &fte->node.children); + if (dest) { + fte->dests_size++; + + type = dest[i].type == + MLX5_FLOW_DESTINATION_TYPE_COUNTER; + *modify_mask |= type ? count : dst; + } +rule_found: + handle->rule[i] = rule; + } while (++i < dest_num); + + return handle; + +free_rules: + destroy_flow_handle(fte, handle, dest, i); + return ERR_PTR(-ENOMEM); +} + +/* fte should not be deleted while calling this function */ +static struct mlx5_flow_handle * +add_rule_fte(struct fs_fte *fte, + struct mlx5_flow_group *fg, + struct mlx5_flow_destination *dest, + int dest_num, + bool update_action) +{ + struct mlx5_flow_handle *handle; struct mlx5_flow_table *ft; - struct mlx5_flow_rule *rule; int modify_mask = 0; int err; + bool new_rule = false; - rule = alloc_rule(dest); - if (!rule) - return ERR_PTR(-ENOMEM); + handle = create_flow_handle(fte, dest, dest_num, &modify_mask, + &new_rule); + if (IS_ERR(handle) || !new_rule) + goto out; if (update_action) modify_mask |= BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION); fs_get_obj(ft, fg->node.parent); - /* Add dest to dests list- we need flow tables to be in the - * end of the list for forward to next prio rules. - */ - tree_init_node(&rule->node, 1, del_rule); - if (dest && dest->type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) - list_add(&rule->node.list, &fte->node.children); - else - list_add_tail(&rule->node.list, &fte->node.children); - if (dest) { - fte->dests_size++; - - modify_mask |= dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER ? - BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS) : - BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST); - } - if (!(fte->status & FS_FTE_STATUS_EXISTING)) err = mlx5_cmd_create_fte(get_dev(&ft->node), ft, fg->id, fte); @@ -959,17 +1060,15 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, err = mlx5_cmd_update_fte(get_dev(&ft->node), ft, fg->id, modify_mask, fte); if (err) - goto free_rule; + goto free_handle; fte->status |= FS_FTE_STATUS_EXISTING; - return rule; +out: + return handle; -free_rule: - list_del(&rule->node.list); - kfree(rule); - if (dest) - fte->dests_size--; +free_handle: + destroy_flow_handle(fte, handle, dest, handle->num_rules); return ERR_PTR(err); } @@ -1098,16 +1197,18 @@ static struct mlx5_flow_rule *find_flow_rule(struct fs_fte *fte, return NULL; } -static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, - u32 *match_value, - u8 action, - u32 flow_tag, - struct mlx5_flow_destination *dest) +static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg, + u32 *match_value, + u8 action, + u32 flow_tag, + struct mlx5_flow_destination *dest, + int dest_num) { - struct fs_fte *fte; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *handle; struct mlx5_flow_table *ft; struct list_head *prev; + struct fs_fte *fte; + int i; nested_lock_ref_node(&fg->node, FS_MUTEX_PARENT); fs_for_each_fte(fte, fg) { @@ -1116,40 +1217,33 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, (action & fte->action) && flow_tag == fte->flow_tag) { int old_action = fte->action; - rule = find_flow_rule(fte, dest); - if (rule) { - atomic_inc(&rule->node.refcount); - unlock_ref_node(&fte->node); - unlock_ref_node(&fg->node); - return rule; - } fte->action |= action; - rule = add_rule_fte(fte, fg, dest, - old_action != action); - if (IS_ERR(rule)) { + handle = add_rule_fte(fte, fg, dest, dest_num, + old_action != action); + if (IS_ERR(handle)) { fte->action = old_action; goto unlock_fte; } else { - goto add_rule; + goto add_rules; } } unlock_ref_node(&fte->node); } fs_get_obj(ft, fg->node.parent); if (fg->num_ftes >= fg->max_ftes) { - rule = ERR_PTR(-ENOSPC); + handle = ERR_PTR(-ENOSPC); goto unlock_fg; } fte = create_fte(fg, match_value, action, flow_tag, &prev); if (IS_ERR(fte)) { - rule = (void *)fte; + handle = (void *)fte; goto unlock_fg; } tree_init_node(&fte->node, 0, del_fte); nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD); - rule = add_rule_fte(fte, fg, dest, false); - if (IS_ERR(rule)) { + handle = add_rule_fte(fte, fg, dest, dest_num, false); + if (IS_ERR(handle)) { kfree(fte); goto unlock_fg; } @@ -1158,21 +1252,24 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, tree_add_node(&fte->node, &fg->node); list_add(&fte->node.list, prev); -add_rule: - tree_add_node(&rule->node, &fte->node); +add_rules: + for (i = 0; i < handle->num_rules; i++) { + if (atomic_read(&handle->rule[i]->node.refcount) == 1) + tree_add_node(&handle->rule[i]->node, &fte->node); + } unlock_fte: unlock_ref_node(&fte->node); unlock_fg: unlock_ref_node(&fg->node); - return rule; + return handle; } -struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule) +struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_handle *handle) { struct mlx5_flow_rule *dst; struct fs_fte *fte; - fs_get_obj(fte, rule->node.parent); + fs_get_obj(fte, handle->rule[0]->node.parent); fs_for_each_dst(dst, fte) { if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) @@ -1211,18 +1308,22 @@ static bool dest_is_valid(struct mlx5_flow_destination *dest, return true; } -static struct mlx5_flow_rule * -_mlx5_add_flow_rule(struct mlx5_flow_table *ft, - struct mlx5_flow_spec *spec, - u32 action, - u32 flow_tag, - struct mlx5_flow_destination *dest) +static struct mlx5_flow_handle * +_mlx5_add_flow_rules(struct mlx5_flow_table *ft, + struct mlx5_flow_spec *spec, + u32 action, + u32 flow_tag, + struct mlx5_flow_destination *dest, + int dest_num) { struct mlx5_flow_group *g; - struct mlx5_flow_rule *rule; + struct mlx5_flow_handle *rule; + int i; - if (!dest_is_valid(dest, action, ft)) - return ERR_PTR(-EINVAL); + for (i = 0; i < dest_num; i++) { + if (!dest_is_valid(&dest[i], action, ft)) + return ERR_PTR(-EINVAL); + } nested_lock_ref_node(&ft->node, FS_MUTEX_GRANDPARENT); fs_for_each_fg(g, ft) @@ -1231,7 +1332,7 @@ _mlx5_add_flow_rule(struct mlx5_flow_table *ft, g->mask.match_criteria, spec->match_criteria)) { rule = add_rule_fg(g, spec->match_value, - action, flow_tag, dest); + action, flow_tag, dest, dest_num); if (!IS_ERR(rule) || PTR_ERR(rule) != -ENOSPC) goto unlock; } @@ -1244,7 +1345,7 @@ _mlx5_add_flow_rule(struct mlx5_flow_table *ft, } rule = add_rule_fg(g, spec->match_value, - action, flow_tag, dest); + action, flow_tag, dest, dest_num); if (IS_ERR(rule)) { /* Remove assumes refcount > 0 and autogroup creates a group * with a refcount = 0. @@ -1265,17 +1366,18 @@ static bool fwd_next_prio_supported(struct mlx5_flow_table *ft) (MLX5_CAP_FLOWTABLE(get_dev(&ft->node), nic_rx_multi_path_tirs))); } -struct mlx5_flow_rule * -mlx5_add_flow_rule(struct mlx5_flow_table *ft, - struct mlx5_flow_spec *spec, - u32 action, - u32 flow_tag, - struct mlx5_flow_destination *dest) +struct mlx5_flow_handle * +mlx5_add_flow_rules(struct mlx5_flow_table *ft, + struct mlx5_flow_spec *spec, + u32 action, + u32 flow_tag, + struct mlx5_flow_destination *dest, + int dest_num) { struct mlx5_flow_root_namespace *root = find_root(&ft->node); struct mlx5_flow_destination gen_dest; struct mlx5_flow_table *next_ft = NULL; - struct mlx5_flow_rule *rule = NULL; + struct mlx5_flow_handle *handle = NULL; u32 sw_action = action; struct fs_prio *prio; @@ -1291,6 +1393,7 @@ mlx5_add_flow_rule(struct mlx5_flow_table *ft, gen_dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; gen_dest.ft = next_ft; dest = &gen_dest; + dest_num = 1; action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; } else { mutex_unlock(&root->chain_lock); @@ -1298,27 +1401,33 @@ mlx5_add_flow_rule(struct mlx5_flow_table *ft, } } - rule = _mlx5_add_flow_rule(ft, spec, action, flow_tag, dest); + handle = _mlx5_add_flow_rules(ft, spec, action, flow_tag, dest, + dest_num); if (sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) { - if (!IS_ERR_OR_NULL(rule) && - (list_empty(&rule->next_ft))) { + if (!IS_ERR_OR_NULL(handle) && + (list_empty(&handle->rule[0]->next_ft))) { mutex_lock(&next_ft->lock); - list_add(&rule->next_ft, &next_ft->fwd_rules); + list_add(&handle->rule[0]->next_ft, + &next_ft->fwd_rules); mutex_unlock(&next_ft->lock); - rule->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; + handle->rule[0]->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; } mutex_unlock(&root->chain_lock); } - return rule; + return handle; } -EXPORT_SYMBOL(mlx5_add_flow_rule); +EXPORT_SYMBOL(mlx5_add_flow_rules); -void mlx5_del_flow_rule(struct mlx5_flow_rule *rule) +void mlx5_del_flow_rules(struct mlx5_flow_handle *handle) { - tree_remove_node(&rule->node); + int i; + + for (i = handle->num_rules - 1; i >= 0; i--) + tree_remove_node(&handle->rule[i]->node); + kfree(handle); } -EXPORT_SYMBOL(mlx5_del_flow_rule); +EXPORT_SYMBOL(mlx5_del_flow_rules); /* Assuming prio->node.children(flow tables) is sorted by level */ static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 71ff03bceabb..d5150888645c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -94,6 +94,11 @@ struct mlx5_flow_rule { u32 sw_action; }; +struct mlx5_flow_handle { + int num_rules; + struct mlx5_flow_rule *rule[]; +}; + /* Type of children is mlx5_flow_group */ struct mlx5_flow_table { struct fs_node node; diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index 93ebc5e21334..0dcd287f4bd0 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h @@ -69,8 +69,8 @@ enum mlx5_flow_namespace_type { struct mlx5_flow_table; struct mlx5_flow_group; -struct mlx5_flow_rule; struct mlx5_flow_namespace; +struct mlx5_flow_handle; struct mlx5_flow_spec { u8 match_criteria_enable; @@ -127,18 +127,20 @@ void mlx5_destroy_flow_group(struct mlx5_flow_group *fg); /* Single destination per rule. * Group ID is implied by the match criteria. */ -struct mlx5_flow_rule * -mlx5_add_flow_rule(struct mlx5_flow_table *ft, - struct mlx5_flow_spec *spec, - u32 action, - u32 flow_tag, - struct mlx5_flow_destination *dest); -void mlx5_del_flow_rule(struct mlx5_flow_rule *fr); - -int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, - struct mlx5_flow_destination *dest); - -struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule); +struct mlx5_flow_handle * +mlx5_add_flow_rules(struct mlx5_flow_table *ft, + struct mlx5_flow_spec *spec, + u32 action, + u32 flow_tag, + struct mlx5_flow_destination *dest, + int dest_num); +void mlx5_del_flow_rules(struct mlx5_flow_handle *fr); + +int mlx5_modify_rule_destination(struct mlx5_flow_handle *handler, + struct mlx5_flow_destination *new_dest, + struct mlx5_flow_destination *old_dest); + +struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_handle *handler); struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging); void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter); void mlx5_fc_query_cached(struct mlx5_fc *counter, -- cgit v1.2.3 From ae05831424ed99f1432492d6df7e8bfe139d2449 Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Tue, 20 Sep 2016 07:59:05 +0000 Subject: net/mlx5: Add option to add fwd rule with counter Currently the code supports only drop rules to possess counters, add that ability also for fwd rules. Signed-off-by: Mark Bloch Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 24 +++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 6732287a98c8..0dfd998cf49e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -374,6 +374,7 @@ static void del_rule(struct fs_node *node) struct mlx5_core_dev *dev = get_dev(node); int match_len = MLX5_ST_SZ_BYTES(fte_match_param); int err; + bool update_fte = false; match_value = mlx5_vzalloc(match_len); if (!match_value) { @@ -392,13 +393,23 @@ static void del_rule(struct fs_node *node) list_del(&rule->next_ft); mutex_unlock(&rule->dest_attr.ft->lock); } + + if (rule->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER && + --fte->dests_size) { + modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION); + fte->action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT; + update_fte = true; + goto out; + } + if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) && --fte->dests_size) { modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST), - err = mlx5_cmd_update_fte(dev, ft, - fg->id, - modify_mask, - fte); + update_fte = true; + } +out: + if (update_fte && fte->dests_size) { + err = mlx5_cmd_update_fte(dev, ft, fg->id, modify_mask, fte); if (err) mlx5_core_warn(dev, "%s can't del rule fg id=%d fte_index=%d\n", @@ -1287,8 +1298,9 @@ static bool counter_is_valid(struct mlx5_fc *counter, u32 action) if (!counter) return false; - /* Hardware support counter for a drop action only */ - return action == (MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT); + return (action & (MLX5_FLOW_CONTEXT_ACTION_DROP | + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)) && + (action & MLX5_FLOW_CONTEXT_ACTION_COUNT); } static bool dest_is_valid(struct mlx5_flow_destination *dest, -- cgit v1.2.3 From e37a79e5d4cac3831fac3d4afbf2461f56b4b7bd Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Tue, 20 Sep 2016 07:58:29 +0000 Subject: net/mlx5e: Add tc support for FWD rule with counter When creating a FWD rule using tc create also a HW counter for this rule. Signed-off-by: Mark Bloch Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 3 ++- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 5d9ac0dbf3bf..c2e4728aaef8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -419,7 +419,8 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, return -EINVAL; } - attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | + MLX5_FLOW_CONTEXT_ACTION_COUNT; out_priv = netdev_priv(out_dev); attr->out_rep = out_priv->ppriv; continue; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 8b2a3832cd0a..53d9d6ce008b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -48,11 +48,12 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, struct mlx5_flow_spec *spec, struct mlx5_esw_flow_attr *attr) { - struct mlx5_flow_destination dest = { 0 }; + struct mlx5_flow_destination dest[2] = {}; struct mlx5_fc *counter = NULL; struct mlx5_flow_handle *rule; void *misc; int action; + int i = 0; if (esw->mode != SRIOV_OFFLOADS) return ERR_PTR(-EOPNOTSUPP); @@ -60,15 +61,17 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, action = attr->action; if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { - dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; - dest.vport_num = attr->out_rep->vport; - action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; - } else if (action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { + dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT; + dest[i].vport_num = attr->out_rep->vport; + i++; + } + if (action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { counter = mlx5_fc_create(esw->dev, true); if (IS_ERR(counter)) return ERR_CAST(counter); - dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; - dest.counter = counter; + dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest[i].counter = counter; + i++; } misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); @@ -81,8 +84,7 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, MLX5_MATCH_MISC_PARAMETERS; rule = mlx5_add_flow_rules((struct mlx5_flow_table *)esw->fdb_table.fdb, - spec, action, 0, &dest, 1); - + spec, action, 0, dest, i); if (IS_ERR(rule)) mlx5_fc_destroy(esw->dev, counter); -- cgit v1.2.3 From 371bebb4f7dea2f581491b5fa850cd3012cd358d Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 27 Oct 2016 18:11:35 -0400 Subject: staging: lustre: osc: remove handling cl_avail_grant less than zero Earlier cl_avail_grant was changed to an unsigned int. Juila Lawall reported for the upstream client the following which affects the Intel branch as well: drivers/staging/lustre/lustre/osc/osc_request.c:1045:5-24: WARNING: Unsigned expression compared with zero: cli -> cl_avail_grant < 0 Since cl_avail_grant can never be negative we can remove the code handling the negative value case. Signed-off-by: James Simmons Intel-bug-id: LU-8697 https://jira.hpdd.intel.com/browse/LU-6303 Reviewed-on: http://review.whamcloud.com/23155 Reviewed-by: Fan Yong Reviewed-by: Frank Zago Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_request.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 038f00c37ee7..efd938a10c9a 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -801,16 +801,6 @@ static void osc_init_grant(struct client_obd *cli, struct obd_connect_data *ocd) cli->cl_avail_grant = ocd->ocd_grant - (cli->cl_dirty_pages << PAGE_SHIFT); - if (cli->cl_avail_grant < 0) { - CWARN("%s: available grant < 0: avail/ocd/dirty %ld/%u/%ld\n", - cli->cl_import->imp_obd->obd_name, cli->cl_avail_grant, - ocd->ocd_grant, cli->cl_dirty_pages << PAGE_SHIFT); - /* workaround for servers which do not have the patch from - * LU-2679 - */ - cli->cl_avail_grant = ocd->ocd_grant; - } - /* determine the appropriate chunk size used by osc_extent. */ cli->cl_chunkbits = max_t(int, PAGE_SHIFT, ocd->ocd_blocksize); spin_unlock(&cli->cl_loi_list_lock); -- cgit v1.2.3 From 330e2a0f5f9e7410d0937ed35ac34284da17f2e8 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 27 Oct 2016 18:11:36 -0400 Subject: staging: lustre: llite: remove IS_ERR(master_inode) check The kernel function ilookup5_nowait never returns IS_ERR so we can remove the IS_ERR check in the ll_md_blocking_ast() function. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8697 Reviewed-on: http://review.whamcloud.com/23151 Reported-by: Dan Carpenter Reviewed-by: Frank Zago Reviewed-by: Andreas Dilger Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index a69c8af7a567..9b4095f9b095 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -283,7 +283,7 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, master_inode = ilookup5(inode->i_sb, hash, ll_test_inode_by_fid, (void *)&lli->lli_pfid); - if (master_inode && !IS_ERR(master_inode)) { + if (master_inode) { ll_invalidate_negative_children(master_inode); iput(master_inode); } -- cgit v1.2.3 From 623f55c45109e7f802812bff3ecc09d81fd4d0c2 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Thu, 27 Oct 2016 18:11:37 -0400 Subject: staging: lustre: llite: restart short read/write for normal IO If normal IO got short read/write, we'd restart the IO from where we've accomplished until we meet EOF or error happens. Signed-off-by: Bobi Jam Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6389 Reviewed-on: http://review.whamcloud.com/14123 Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/fail.c | 1 + .../staging/lustre/lustre/include/obd_support.h | 2 ++ drivers/staging/lustre/lustre/llite/file.c | 41 +++++++++++++--------- drivers/staging/lustre/lustre/llite/vvp_io.c | 19 ++++++++-- 4 files changed, 45 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/libcfs/fail.c b/drivers/staging/lustre/lnet/libcfs/fail.c index e4b1a0a86eae..3a9c8ddeff50 100644 --- a/drivers/staging/lustre/lnet/libcfs/fail.c +++ b/drivers/staging/lustre/lnet/libcfs/fail.c @@ -113,6 +113,7 @@ int __cfs_fail_check_set(__u32 id, __u32 value, int set) break; case CFS_FAIL_LOC_RESET: cfs_fail_loc = value; + atomic_set(&cfs_fail_count, 0); break; default: LASSERTF(0, "called with bad set %u\n", set); diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 1233c3455b6f..7f3f8cd2be76 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -458,6 +458,8 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LOV_INIT 0x1403 #define OBD_FAIL_GLIMPSE_DELAY 0x1404 #define OBD_FAIL_LLITE_XATTR_ENOMEM 0x1405 +#define OBD_FAIL_MAKE_LOVEA_HOLE 0x1406 +#define OBD_FAIL_LLITE_LOST_LAYOUT 0x1407 #define OBD_FAIL_GETATTR_DELAY 0x1409 #define OBD_FAIL_FID_INDIR 0x1501 diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 0accf2867055..2c8df434416c 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -972,9 +972,11 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, { struct ll_inode_info *lli = ll_i2info(file_inode(file)); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + struct vvp_io *vio = vvp_env_io(env); struct range_lock range; struct cl_io *io; - ssize_t result; + ssize_t result = 0; + int rc = 0; CDEBUG(D_VFSTRACE, "file: %pD, type: %d ppos: %llu, count: %zu\n", file, iot, *ppos, count); @@ -1006,16 +1008,15 @@ restart: CDEBUG(D_VFSTRACE, "Range lock [%llu, %llu]\n", range.rl_node.in_extent.start, range.rl_node.in_extent.end); - result = range_lock(&lli->lli_write_tree, - &range); - if (result < 0) + rc = range_lock(&lli->lli_write_tree, &range); + if (rc < 0) goto out; range_locked = true; } down_read(&lli->lli_trunc_sem); ll_cl_add(file, env, io); - result = cl_io_loop(env, io); + rc = cl_io_loop(env, io); ll_cl_remove(file, env); up_read(&lli->lli_trunc_sem); if (range_locked) { @@ -1026,24 +1027,26 @@ restart: } } else { /* cl_io_rw_init() handled IO */ - result = io->ci_result; + rc = io->ci_result; } if (io->ci_nob > 0) { result = io->ci_nob; + count -= io->ci_nob; *ppos = io->u.ci_wr.wr.crw_pos; + + /* prepare IO restart */ + if (count > 0) + args->u.normal.via_iter = vio->vui_iter; } - goto out; out: cl_io_fini(env, io); - /* If any bit been read/written (result != 0), we just return - * short read/write instead of restart io. - */ - if ((result == 0 || result == -ENODATA) && io->ci_need_restart) { - CDEBUG(D_VFSTRACE, "Restart %s on %pD from %lld, count:%zu\n", + + if ((!rc || rc == -ENODATA) && count > 0 && io->ci_need_restart) { + CDEBUG(D_VFSTRACE, "%s: restart %s from %lld, count:%zu, result: %zd\n", + file_dentry(file)->d_name.name, iot == CIT_READ ? "read" : "write", - file, *ppos, count); - LASSERTF(io->ci_nob == 0, "%zd\n", io->ci_nob); + *ppos, count, result); goto restart; } @@ -1056,13 +1059,19 @@ out: ll_stats_ops_tally(ll_i2sbi(file_inode(file)), LPROC_LL_WRITE_BYTES, result); fd->fd_write_failed = false; - } else if (result != -ERESTARTSYS) { + } else if (!result && !rc) { + rc = io->ci_result; + if (rc < 0) + fd->fd_write_failed = true; + else + fd->fd_write_failed = false; + } else if (rc != -ERESTARTSYS) { fd->fd_write_failed = true; } } CDEBUG(D_VFSTRACE, "iot: %d, result: %zd\n", iot, result); - return result; + return result > 0 ? result : rc; } static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 87fdab240bc0..3d327b4ddc1d 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -72,9 +72,10 @@ static bool can_populate_pages(const struct lu_env *env, struct cl_io *io, /* don't need lock here to check lli_layout_gen as we have held * extent lock and GROUP lock has to hold to swap layout */ - if (ll_layout_version_get(lli) != vio->vui_layout_gen) { + if (ll_layout_version_get(lli) != vio->vui_layout_gen || + OBD_FAIL_CHECK_RESET(OBD_FAIL_LLITE_LOST_LAYOUT, 0)) { io->ci_need_restart = 1; - /* this will return application a short read/write */ + /* this will cause a short read/write */ io->ci_continue = 0; rc = false; } @@ -924,6 +925,20 @@ static int vvp_io_write_start(const struct lu_env *env, CDEBUG(D_VFSTRACE, "write: [%lli, %lli)\n", pos, pos + (long long)cnt); + /* + * The maximum Lustre file size is variable, based on the OST maximum + * object size and number of stripes. This needs another check in + * addition to the VFS checks earlier. + */ + if (pos + cnt > ll_file_maxbytes(inode)) { + CDEBUG(D_INODE, + "%s: file " DFID " offset %llu > maxbytes %llu\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(ll_inode2fid(inode)), pos + cnt, + ll_file_maxbytes(inode)); + return -EFBIG; + } + if (!vio->vui_iter) { /* from a temp io in ll_cl_init(). */ result = 0; -- cgit v1.2.3 From 11c647caf74b10c2716944901249221379991790 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Thu, 27 Oct 2016 18:11:38 -0400 Subject: staging: lustre: obdclass: variable llog chunk size Do not use fix LLOG_CHUNK_SIZE (8192 bytes), and it will get the llog_chunk_size from llog_log_hdr. Accordingly llog header will be variable too, so we can enlarge the bitmap in the header, then have more records in each llog file. Signed-off-by: Andreas Dilger Signed-off-by: wang di Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6602 Reviewed-on: http://review.whamcloud.com/14883 Reviewed-by: Fan Yong Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 39 +++++++++++++----- drivers/staging/lustre/lustre/include/lustre_log.h | 6 +++ drivers/staging/lustre/lustre/obdclass/llog.c | 48 +++++++++++++--------- drivers/staging/lustre/lustre/obdclass/llog_obd.c | 1 + drivers/staging/lustre/lustre/obdclass/llog_swab.c | 8 ++-- drivers/staging/lustre/lustre/ptlrpc/llog_client.c | 20 ++++++--- 6 files changed, 84 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 5d2f845599f2..e542ce6c2b13 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -3122,13 +3122,6 @@ struct llog_gen_rec { struct llog_rec_tail lgr_tail; }; -/* On-disk header structure of each log object, stored in little endian order */ -#define LLOG_CHUNK_SIZE 8192 -#define LLOG_HEADER_SIZE (96) -#define LLOG_BITMAP_BYTES (LLOG_CHUNK_SIZE - LLOG_HEADER_SIZE) - -#define LLOG_MIN_REC_SIZE (24) /* round(llog_rec_hdr + llog_rec_tail) */ - /* flags for the logs */ enum llog_flag { LLOG_F_ZAP_WHEN_EMPTY = 0x1, @@ -3139,6 +3132,15 @@ enum llog_flag { LLOG_F_EXT_MASK = LLOG_F_EXT_JOBID, }; +/* On-disk header structure of each log object, stored in little endian order */ +#define LLOG_MIN_CHUNK_SIZE 8192 +#define LLOG_HEADER_SIZE (96) /* sizeof (llog_log_hdr) + + * sizeof(llh_tail) - sizeof(llh_bitmap) + */ +#define LLOG_BITMAP_BYTES (LLOG_MIN_CHUNK_SIZE - LLOG_HEADER_SIZE) +#define LLOG_MIN_REC_SIZE (24) /* round(llog_rec_hdr + llog_rec_tail) */ + +/* flags for the logs */ struct llog_log_hdr { struct llog_rec_hdr llh_hdr; __s64 llh_timestamp; @@ -3150,13 +3152,30 @@ struct llog_log_hdr { /* for a catalog the first plain slot is next to it */ struct obd_uuid llh_tgtuuid; __u32 llh_reserved[LLOG_HEADER_SIZE / sizeof(__u32) - 23]; + /* These fields must always be at the end of the llog_log_hdr. + * Note: llh_bitmap size is variable because llog chunk size could be + * bigger than LLOG_MIN_CHUNK_SIZE, i.e. sizeof(llog_log_hdr) > 8192 + * bytes, and the real size is stored in llh_hdr.lrh_len, which means + * llh_tail should only be referred by LLOG_HDR_TAIL(). + * But this structure is also used by client/server llog interface + * (see llog_client.c), it will be kept in its original way to avoid + * compatibility issue. + */ __u32 llh_bitmap[LLOG_BITMAP_BYTES / sizeof(__u32)]; struct llog_rec_tail llh_tail; } __packed; -#define LLOG_BITMAP_SIZE(llh) (__u32)((llh->llh_hdr.lrh_len - \ - llh->llh_bitmap_offset - \ - sizeof(llh->llh_tail)) * 8) +#undef LLOG_HEADER_SIZE +#undef LLOG_BITMAP_BYTES + +#define LLOG_HDR_BITMAP_SIZE(llh) (__u32)((llh->llh_hdr.lrh_len - \ + llh->llh_bitmap_offset - \ + sizeof(llh->llh_tail)) * 8) +#define LLOG_HDR_BITMAP(llh) (__u32 *)((char *)(llh) + \ + (llh)->llh_bitmap_offset) +#define LLOG_HDR_TAIL(llh) ((struct llog_rec_tail *)((char *)llh + \ + llh->llh_hdr.lrh_len - \ + sizeof(llh->llh_tail))) /** log cookies are used to reference a specific log file and a record * therein diff --git a/drivers/staging/lustre/lustre/include/lustre_log.h b/drivers/staging/lustre/lustre/include/lustre_log.h index 995b266932e3..35e37eb1bc2c 100644 --- a/drivers/staging/lustre/lustre/include/lustre_log.h +++ b/drivers/staging/lustre/lustre/include/lustre_log.h @@ -214,6 +214,7 @@ struct llog_handle { spinlock_t lgh_hdr_lock; /* protect lgh_hdr data */ struct llog_logid lgh_id; /* id of this log */ struct llog_log_hdr *lgh_hdr; + size_t lgh_hdr_size; int lgh_last_idx; int lgh_cur_idx; /* used during llog_process */ __u64 lgh_cur_offset; /* used during llog_process */ @@ -244,6 +245,11 @@ struct llog_ctxt { struct mutex loc_mutex; /* protect loc_imp */ atomic_t loc_refcount; long loc_flags; /* flags, see above defines */ + /* + * llog chunk size, and llog record size can not be bigger than + * loc_chunk_size + */ + __u32 loc_chunk_size; }; #define LLOG_PROC_BREAK 0x0001 diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index 43797f106745..5c9447ee2046 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -80,8 +80,7 @@ static void llog_free_handle(struct llog_handle *loghandle) LASSERT(list_empty(&loghandle->u.phd.phd_entry)); else if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) LASSERT(list_empty(&loghandle->u.chd.chd_head)); - LASSERT(sizeof(*loghandle->lgh_hdr) == LLOG_CHUNK_SIZE); - kfree(loghandle->lgh_hdr); + kvfree(loghandle->lgh_hdr); out: kfree(loghandle); } @@ -116,19 +115,21 @@ static int llog_read_header(const struct lu_env *env, if (rc == LLOG_EEMPTY) { struct llog_log_hdr *llh = handle->lgh_hdr; + /* lrh_len should be initialized in llog_init_handle */ handle->lgh_last_idx = 0; /* header is record with index 0 */ llh->llh_count = 1; /* for the header record */ llh->llh_hdr.lrh_type = LLOG_HDR_MAGIC; - llh->llh_hdr.lrh_len = LLOG_CHUNK_SIZE; - llh->llh_tail.lrt_len = LLOG_CHUNK_SIZE; + LASSERT(handle->lgh_ctxt->loc_chunk_size >= LLOG_MIN_CHUNK_SIZE); + llh->llh_hdr.lrh_len = handle->lgh_ctxt->loc_chunk_size; llh->llh_hdr.lrh_index = 0; - llh->llh_tail.lrt_index = 0; llh->llh_timestamp = ktime_get_real_seconds(); if (uuid) memcpy(&llh->llh_tgtuuid, uuid, sizeof(llh->llh_tgtuuid)); llh->llh_bitmap_offset = offsetof(typeof(*llh), llh_bitmap); - ext2_set_bit(0, llh->llh_bitmap); + ext2_set_bit(0, LLOG_HDR_BITMAP(llh)); + LLOG_HDR_TAIL(llh)->lrt_len = llh->llh_hdr.lrh_len; + LLOG_HDR_TAIL(llh)->lrt_index = llh->llh_hdr.lrh_index; rc = 0; } return rc; @@ -137,16 +138,19 @@ static int llog_read_header(const struct lu_env *env, int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, int flags, struct obd_uuid *uuid) { + int chunk_size = handle->lgh_ctxt->loc_chunk_size; enum llog_flag fmt = flags & LLOG_F_EXT_MASK; struct llog_log_hdr *llh; int rc; LASSERT(!handle->lgh_hdr); - llh = kzalloc(sizeof(*llh), GFP_NOFS); + LASSERT(chunk_size >= LLOG_MIN_CHUNK_SIZE); + llh = libcfs_kvzalloc(sizeof(*llh), GFP_NOFS); if (!llh) return -ENOMEM; handle->lgh_hdr = llh; + handle->lgh_hdr_size = chunk_size; /* first assign flags to use llog_client_ops */ llh->llh_flags = flags; rc = llog_read_header(env, handle, uuid); @@ -198,7 +202,7 @@ int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, llh->llh_flags |= fmt; out: if (rc) { - kfree(llh); + kvfree(llh); handle->lgh_hdr = NULL; } return rc; @@ -212,15 +216,20 @@ static int llog_process_thread(void *arg) struct llog_log_hdr *llh = loghandle->lgh_hdr; struct llog_process_cat_data *cd = lpi->lpi_catdata; char *buf; - __u64 cur_offset = LLOG_CHUNK_SIZE; + __u64 cur_offset; __u64 last_offset; + int chunk_size; int rc = 0, index = 1, last_index; int saved_index = 0; int last_called_index = 0; - LASSERT(llh); + if (!llh) + return -EINVAL; + + cur_offset = llh->llh_hdr.lrh_len; + chunk_size = llh->llh_hdr.lrh_len; - buf = kzalloc(LLOG_CHUNK_SIZE, GFP_NOFS); + buf = libcfs_kvzalloc(chunk_size, GFP_NOFS); if (!buf) { lpi->lpi_rc = -ENOMEM; return 0; @@ -233,7 +242,7 @@ static int llog_process_thread(void *arg) if (cd && cd->lpcd_last_idx) last_index = cd->lpcd_last_idx; else - last_index = LLOG_BITMAP_BYTES * 8 - 1; + last_index = LLOG_HDR_BITMAP_SIZE(llh) - 1; /* Record is not in this buffer. */ if (index > last_index) @@ -244,7 +253,7 @@ static int llog_process_thread(void *arg) /* skip records not set in bitmap */ while (index <= last_index && - !ext2_test_bit(index, llh->llh_bitmap)) + !ext2_test_bit(index, LLOG_HDR_BITMAP(llh))) ++index; LASSERT(index <= last_index + 1); @@ -255,10 +264,10 @@ repeat: index, last_index); /* get the buf with our target record; avoid old garbage */ - memset(buf, 0, LLOG_CHUNK_SIZE); + memset(buf, 0, chunk_size); last_offset = cur_offset; rc = llog_next_block(lpi->lpi_env, loghandle, &saved_index, - index, &cur_offset, buf, LLOG_CHUNK_SIZE); + index, &cur_offset, buf, chunk_size); if (rc) goto out; @@ -267,7 +276,7 @@ repeat: * swabbing is done at the beginning of the loop. */ for (rec = (struct llog_rec_hdr *)buf; - (char *)rec < buf + LLOG_CHUNK_SIZE; + (char *)rec < buf + chunk_size; rec = llog_rec_hdr_next(rec)) { CDEBUG(D_OTHER, "processing rec 0x%p type %#x\n", rec, rec->lrh_type); @@ -285,8 +294,7 @@ repeat: goto repeat; goto out; /* no more records */ } - if (rec->lrh_len == 0 || - rec->lrh_len > LLOG_CHUNK_SIZE) { + if (!rec->lrh_len || rec->lrh_len > chunk_size) { CWARN("invalid length %d in llog record for index %d/%d\n", rec->lrh_len, rec->lrh_index, index); @@ -303,14 +311,14 @@ repeat: CDEBUG(D_OTHER, "lrh_index: %d lrh_len: %d (%d remains)\n", rec->lrh_index, rec->lrh_len, - (int)(buf + LLOG_CHUNK_SIZE - (char *)rec)); + (int)(buf + chunk_size - (char *)rec)); loghandle->lgh_cur_idx = rec->lrh_index; loghandle->lgh_cur_offset = (char *)rec - (char *)buf + last_offset; /* if set, process the callback on this record */ - if (ext2_test_bit(index, llh->llh_bitmap)) { + if (ext2_test_bit(index, LLOG_HDR_BITMAP(llh))) { rc = lpi->lpi_cb(lpi->lpi_env, loghandle, rec, lpi->lpi_cbdata); last_called_index = index; diff --git a/drivers/staging/lustre/lustre/obdclass/llog_obd.c b/drivers/staging/lustre/lustre/obdclass/llog_obd.c index a4277d684614..8574ad401f66 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_obd.c @@ -158,6 +158,7 @@ int llog_setup(const struct lu_env *env, struct obd_device *obd, mutex_init(&ctxt->loc_mutex); ctxt->loc_exp = class_export_get(disk_obd->obd_self_export); ctxt->loc_flags = LLOG_CTXT_FLAG_UNINITIALIZED; + ctxt->loc_chunk_size = LLOG_MIN_CHUNK_SIZE; rc = llog_group_set_ctxt(olg, ctxt, index); if (rc) { diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index 8c4c1b3f1b45..786909299b72 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -244,7 +244,7 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) __swab32s(&llh->llh_flags); __swab32s(&llh->llh_size); __swab32s(&llh->llh_cat_idx); - tail = &llh->llh_tail; + tail = LLOG_HDR_TAIL(llh); break; } case LLOG_LOGID_MAGIC: @@ -290,8 +290,10 @@ static void print_llog_hdr(struct llog_log_hdr *h) CDEBUG(D_OTHER, "\tllh_flags: %#x\n", h->llh_flags); CDEBUG(D_OTHER, "\tllh_size: %#x\n", h->llh_size); CDEBUG(D_OTHER, "\tllh_cat_idx: %#x\n", h->llh_cat_idx); - CDEBUG(D_OTHER, "\tllh_tail.lrt_index: %#x\n", h->llh_tail.lrt_index); - CDEBUG(D_OTHER, "\tllh_tail.lrt_len: %#x\n", h->llh_tail.lrt_len); + CDEBUG(D_OTHER, "\tllh_tail.lrt_index: %#x\n", + LLOG_HDR_TAIL(h)->lrt_index); + CDEBUG(D_OTHER, "\tllh_tail.lrt_len: %#x\n", + LLOG_HDR_TAIL(h)->lrt_len); } void lustre_swab_llog_hdr(struct llog_log_hdr *h) diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c index 0f55c01feba8..110d9f505787 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c @@ -287,8 +287,13 @@ static int llog_client_read_header(const struct lu_env *env, goto out; } - memcpy(handle->lgh_hdr, hdr, sizeof(*hdr)); - handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index; + if (handle->lgh_hdr_size < hdr->llh_hdr.lrh_len) { + rc = -EFAULT; + goto out; + } + + memcpy(handle->lgh_hdr, hdr, hdr->llh_hdr.lrh_len); + handle->lgh_last_idx = LLOG_HDR_TAIL(handle->lgh_hdr)->lrt_index; /* sanity checks */ llh_hdr = &handle->lgh_hdr->llh_hdr; @@ -296,9 +301,14 @@ static int llog_client_read_header(const struct lu_env *env, CERROR("bad log header magic: %#x (expecting %#x)\n", llh_hdr->lrh_type, LLOG_HDR_MAGIC); rc = -EIO; - } else if (llh_hdr->lrh_len != LLOG_CHUNK_SIZE) { - CERROR("incorrectly sized log header: %#x (expecting %#x)\n", - llh_hdr->lrh_len, LLOG_CHUNK_SIZE); + } else if (llh_hdr->lrh_len != + LLOG_HDR_TAIL(handle->lgh_hdr)->lrt_len || + (llh_hdr->lrh_len & (llh_hdr->lrh_len - 1)) || + llh_hdr->lrh_len < LLOG_MIN_CHUNK_SIZE || + llh_hdr->lrh_len > handle->lgh_hdr_size) { + CERROR("incorrectly sized log header: %#x (expecting %#x) (power of two > 8192)\n", + llh_hdr->lrh_len, + LLOG_HDR_TAIL(handle->lgh_hdr)->lrt_len); CERROR("you may need to re-run lconf --write_conf.\n"); rc = -EIO; } -- cgit v1.2.3 From 662e035ca5266fedd1259bcbe79a50ef4de1bd77 Mon Sep 17 00:00:00 2001 From: wang di Date: Thu, 27 Oct 2016 18:11:39 -0400 Subject: staging: lustre: lmv: allow cross-MDT rename and link Remove checks for cross-MDT operation, so cross-MDT rename and link will be allowed. Remove obsolete locality parameters in MDT lock API after all of cross-MDT operations are allowed. This is the client side changed only so the upstream client can support this. Signed-off-by: wang di Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3537 Reviewed-on: http://review.whamcloud.com/12282 Reviewed-by: James Simmons Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 77 +++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 679cd872045b..7a8d1c8307a7 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1903,7 +1903,10 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; + struct obd_export *target_exp; struct lmv_tgt_desc *src_tgt; + struct lmv_tgt_desc *tgt_tgt; + struct mdt_body *body; int rc; LASSERT(oldlen != 0); @@ -1943,6 +1946,10 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, if (rc) return rc; src_tgt = lmv_find_target(lmv, &op_data->op_fid3); + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); + + target_exp = src_tgt->ltd_exp; } else { if (op_data->op_mea1) { struct lmv_stripe_md *lsm = op_data->op_mea1; @@ -1951,29 +1958,27 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, oldlen, &op_data->op_fid1, &op_data->op_mds); - if (IS_ERR(src_tgt)) - return PTR_ERR(src_tgt); } else { src_tgt = lmv_find_target(lmv, &op_data->op_fid1); - if (IS_ERR(src_tgt)) - return PTR_ERR(src_tgt); - - op_data->op_mds = src_tgt->ltd_idx; } + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); if (op_data->op_mea2) { struct lmv_stripe_md *lsm = op_data->op_mea2; - const struct lmv_oinfo *oinfo; - oinfo = lsm_name_to_stripe_info(lsm, new, newlen); - if (IS_ERR(oinfo)) - return PTR_ERR(oinfo); - - op_data->op_fid2 = oinfo->lmo_fid; + tgt_tgt = lmv_locate_target_for_name(lmv, lsm, new, + newlen, + &op_data->op_fid2, + &op_data->op_mds); + } else { + tgt_tgt = lmv_find_target(lmv, &op_data->op_fid2); } + if (IS_ERR(tgt_tgt)) + return PTR_ERR(tgt_tgt); + + target_exp = tgt_tgt->ltd_exp; } - if (IS_ERR(src_tgt)) - return PTR_ERR(src_tgt); /* * LOOKUP lock on src child (fid3) should also be cancelled for @@ -2014,20 +2019,52 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, return rc; } +retry_rename: /* * Cancel all the locks on tgt child (fid4). */ - if (fid_is_sane(&op_data->op_fid4)) + if (fid_is_sane(&op_data->op_fid4)) { + struct lmv_tgt_desc *tgt; + rc = lmv_early_cancel(exp, NULL, op_data, src_tgt->ltd_idx, LCK_EX, MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID4); + if (rc) + return rc; - CDEBUG(D_INODE, DFID":m%d to "DFID"\n", PFID(&op_data->op_fid1), - op_data->op_mds, PFID(&op_data->op_fid2)); + tgt = lmv_find_target(lmv, &op_data->op_fid4); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); - rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen, - new, newlen, request); - return rc; + /* + * Since the target child might be destroyed, and it might + * become orphan, and we can only check orphan on the local + * MDT right now, so we send rename request to the MDT where + * target child is located. If target child does not exist, + * then it will send the request to the target parent + */ + target_exp = tgt->ltd_exp; + } + + rc = md_rename(target_exp, op_data, old, oldlen, new, newlen, request); + if (rc && rc != -EREMOTE) + return rc; + + body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY); + if (!body) + return -EPROTO; + + /* Not cross-ref case, just get out of here. */ + if (likely(!(body->mbo_valid & OBD_MD_MDS))) + return rc; + + CDEBUG(D_INODE, "%s: try rename to another MDT for " DFID "\n", + exp->exp_obd->obd_name, PFID(&body->mbo_fid1)); + + op_data->op_fid4 = body->mbo_fid1; + ptlrpc_req_finished(*request); + *request = NULL; + goto retry_rename; } static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data, -- cgit v1.2.3 From 8d69af0381930c9ab818cc3aa6bcf00bf328ed00 Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Thu, 27 Oct 2016 18:11:40 -0400 Subject: staging: lustre: ptlrpc: Introduce iovec to bulk descriptor Added a union to ptlrpc_bulk_desc for KVEC and KIOV buffers. bd_type has been changed to be a bit mask. Bits are set in bd_type to specify {put,get}{source,sink}{kvec,kiov} changed all instances in the code to access the union properly ASSUMPTION: all current code only works with KIOV and new DNE code to be added will introduce a different code path that uses IOVEC As part of the implementation buffer operations are added as callbacks to be defined by users of ptlrpc. This enables buffer users to define how to allocate and release buffers. Signed-off-by: Amir Shehata Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5835 Reviewed-on: http://review.whamcloud.com/12525 Reviewed-by: wangdi Reviewed-by: Liang Zhen Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_net.h | 160 +++++++++++++++++---- drivers/staging/lustre/lustre/mdc/mdc_request.c | 8 +- drivers/staging/lustre/lustre/mgc/mgc_request.c | 8 +- drivers/staging/lustre/lustre/osc/osc_page.c | 4 +- drivers/staging/lustre/lustre/osc/osc_request.c | 7 +- drivers/staging/lustre/lustre/ptlrpc/client.c | 121 ++++++++++++---- drivers/staging/lustre/lustre/ptlrpc/events.c | 4 +- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 7 +- drivers/staging/lustre/lustre/ptlrpc/pers.c | 31 ++-- .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h | 9 +- drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c | 19 +-- drivers/staging/lustre/lustre/ptlrpc/sec_plain.c | 20 +-- 12 files changed, 290 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 730223822e1c..67a7095d26b0 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -50,6 +50,7 @@ * @{ */ +#include #include "../../include/linux/libcfs/libcfs.h" #include "../../include/linux/lnet/nidstr.h" #include "../../include/linux/lnet/api.h" @@ -1083,10 +1084,93 @@ struct ptlrpc_bulk_page { struct page *bp_page; }; -#define BULK_GET_SOURCE 0 -#define BULK_PUT_SINK 1 -#define BULK_GET_SINK 2 -#define BULK_PUT_SOURCE 3 +enum ptlrpc_bulk_op_type { + PTLRPC_BULK_OP_ACTIVE = 0x00000001, + PTLRPC_BULK_OP_PASSIVE = 0x00000002, + PTLRPC_BULK_OP_PUT = 0x00000004, + PTLRPC_BULK_OP_GET = 0x00000008, + PTLRPC_BULK_BUF_KVEC = 0x00000010, + PTLRPC_BULK_BUF_KIOV = 0x00000020, + PTLRPC_BULK_GET_SOURCE = PTLRPC_BULK_OP_PASSIVE | PTLRPC_BULK_OP_GET, + PTLRPC_BULK_PUT_SINK = PTLRPC_BULK_OP_PASSIVE | PTLRPC_BULK_OP_PUT, + PTLRPC_BULK_GET_SINK = PTLRPC_BULK_OP_ACTIVE | PTLRPC_BULK_OP_GET, + PTLRPC_BULK_PUT_SOURCE = PTLRPC_BULK_OP_ACTIVE | PTLRPC_BULK_OP_PUT, +}; + +static inline bool ptlrpc_is_bulk_op_get(enum ptlrpc_bulk_op_type type) +{ + return (type & PTLRPC_BULK_OP_GET) == PTLRPC_BULK_OP_GET; +} + +static inline bool ptlrpc_is_bulk_get_source(enum ptlrpc_bulk_op_type type) +{ + return (type & PTLRPC_BULK_GET_SOURCE) == PTLRPC_BULK_GET_SOURCE; +} + +static inline bool ptlrpc_is_bulk_put_sink(enum ptlrpc_bulk_op_type type) +{ + return (type & PTLRPC_BULK_PUT_SINK) == PTLRPC_BULK_PUT_SINK; +} + +static inline bool ptlrpc_is_bulk_get_sink(enum ptlrpc_bulk_op_type type) +{ + return (type & PTLRPC_BULK_GET_SINK) == PTLRPC_BULK_GET_SINK; +} + +static inline bool ptlrpc_is_bulk_put_source(enum ptlrpc_bulk_op_type type) +{ + return (type & PTLRPC_BULK_PUT_SOURCE) == PTLRPC_BULK_PUT_SOURCE; +} + +static inline bool ptlrpc_is_bulk_desc_kvec(enum ptlrpc_bulk_op_type type) +{ + return ((type & PTLRPC_BULK_BUF_KVEC) | (type & PTLRPC_BULK_BUF_KIOV)) + == PTLRPC_BULK_BUF_KVEC; +} + +static inline bool ptlrpc_is_bulk_desc_kiov(enum ptlrpc_bulk_op_type type) +{ + return ((type & PTLRPC_BULK_BUF_KVEC) | (type & PTLRPC_BULK_BUF_KIOV)) + == PTLRPC_BULK_BUF_KIOV; +} + +static inline bool ptlrpc_is_bulk_op_active(enum ptlrpc_bulk_op_type type) +{ + return ((type & PTLRPC_BULK_OP_ACTIVE) | + (type & PTLRPC_BULK_OP_PASSIVE)) == PTLRPC_BULK_OP_ACTIVE; +} + +static inline bool ptlrpc_is_bulk_op_passive(enum ptlrpc_bulk_op_type type) +{ + return ((type & PTLRPC_BULK_OP_ACTIVE) | + (type & PTLRPC_BULK_OP_PASSIVE)) == PTLRPC_BULK_OP_PASSIVE; +} + +struct ptlrpc_bulk_frag_ops { + /** + * Add a page \a page to the bulk descriptor \a desc + * Data to transfer in the page starts at offset \a pageoffset and + * amount of data to transfer from the page is \a len + */ + void (*add_kiov_frag)(struct ptlrpc_bulk_desc *desc, + struct page *page, int pageoffset, int len); + + /* + * Add a \a fragment to the bulk descriptor \a desc. + * Data to transfer in the fragment is pointed to by \a frag + * The size of the fragment is \a len + */ + int (*add_iov_frag)(struct ptlrpc_bulk_desc *desc, void *frag, int len); + + /** + * Uninitialize and free bulk descriptor \a desc. + * Works on bulk descriptors both from server and client side. + */ + void (*release_frags)(struct ptlrpc_bulk_desc *desc); +}; + +extern const struct ptlrpc_bulk_frag_ops ptlrpc_bulk_kiov_pin_ops; +extern const struct ptlrpc_bulk_frag_ops ptlrpc_bulk_kiov_nopin_ops; /** * Definition of bulk descriptor. @@ -1101,14 +1185,14 @@ struct ptlrpc_bulk_page { struct ptlrpc_bulk_desc { /** completed with failure */ unsigned long bd_failure:1; - /** {put,get}{source,sink} */ - unsigned long bd_type:2; /** client side */ unsigned long bd_registered:1; /** For serialization with callback */ spinlock_t bd_lock; /** Import generation when request for this bulk was sent */ int bd_import_generation; + /** {put,get}{source,sink}{kvec,kiov} */ + enum ptlrpc_bulk_op_type bd_type; /** LNet portal for this bulk */ __u32 bd_portal; /** Server side - export this bulk created for */ @@ -1117,6 +1201,7 @@ struct ptlrpc_bulk_desc { struct obd_import *bd_import; /** Back pointer to the request */ struct ptlrpc_request *bd_req; + struct ptlrpc_bulk_frag_ops *bd_frag_ops; wait_queue_head_t bd_waitq; /* server side only WQ */ int bd_iov_count; /* # entries in bd_iov */ int bd_max_iov; /* allocated size of bd_iov */ @@ -1132,14 +1217,31 @@ struct ptlrpc_bulk_desc { /** array of associated MDs */ lnet_handle_md_t bd_mds[PTLRPC_BULK_OPS_COUNT]; - /* - * encrypt iov, size is either 0 or bd_iov_count. - */ - lnet_kiov_t *bd_enc_iov; - - lnet_kiov_t bd_iov[0]; + union { + struct { + /* + * encrypt iov, size is either 0 or bd_iov_count. + */ + struct bio_vec *bd_enc_vec; + struct bio_vec *bd_vec; /* Array of bio_vecs */ + } bd_kiov; + + struct { + struct kvec *bd_enc_kvec; + struct kvec *bd_kvec; /* Array of kvecs */ + } bd_kvec; + } bd_u; }; +#define GET_KIOV(desc) ((desc)->bd_u.bd_kiov.bd_vec) +#define BD_GET_KIOV(desc, i) ((desc)->bd_u.bd_kiov.bd_vec[i]) +#define GET_ENC_KIOV(desc) ((desc)->bd_u.bd_kiov.bd_enc_vec) +#define BD_GET_ENC_KIOV(desc, i) ((desc)->bd_u.bd_kiov.bd_enc_vec[i]) +#define GET_KVEC(desc) ((desc)->bd_u.bd_kvec.bd_kvec) +#define BD_GET_KVEC(desc, i) ((desc)->bd_u.bd_kvec.bd_kvec[i]) +#define GET_ENC_KVEC(desc) ((desc)->bd_u.bd_kvec.bd_enc_kvec) +#define BD_GET_ENC_KVEC(desc, i) ((desc)->bd_u.bd_kvec.bd_enc_kvec[i]) + enum { SVC_STOPPED = 1 << 0, SVC_STOPPING = 1 << 1, @@ -1754,21 +1856,17 @@ int ptlrpc_request_bufs_pack(struct ptlrpc_request *request, void ptlrpc_req_finished(struct ptlrpc_request *request); struct ptlrpc_request *ptlrpc_request_addref(struct ptlrpc_request *req); struct ptlrpc_bulk_desc *ptlrpc_prep_bulk_imp(struct ptlrpc_request *req, - unsigned npages, unsigned max_brw, - unsigned type, unsigned portal); -void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *bulk, int pin); -static inline void ptlrpc_free_bulk_pin(struct ptlrpc_bulk_desc *bulk) -{ - __ptlrpc_free_bulk(bulk, 1); -} - -static inline void ptlrpc_free_bulk_nopin(struct ptlrpc_bulk_desc *bulk) -{ - __ptlrpc_free_bulk(bulk, 0); -} - + unsigned int nfrags, + unsigned int max_brw, + unsigned int type, + unsigned int portal, + const struct ptlrpc_bulk_frag_ops *ops); + +int ptlrpc_prep_bulk_frag(struct ptlrpc_bulk_desc *desc, + void *frag, int len); void __ptlrpc_prep_bulk_page(struct ptlrpc_bulk_desc *desc, - struct page *page, int pageoffset, int len, int); + struct page *page, int pageoffset, int len, + int pin); static inline void ptlrpc_prep_bulk_page_pin(struct ptlrpc_bulk_desc *desc, struct page *page, int pageoffset, int len) @@ -1783,6 +1881,16 @@ static inline void ptlrpc_prep_bulk_page_nopin(struct ptlrpc_bulk_desc *desc, __ptlrpc_prep_bulk_page(desc, page, pageoffset, len, 0); } +void ptlrpc_free_bulk(struct ptlrpc_bulk_desc *bulk); + +static inline void ptlrpc_release_bulk_page_pin(struct ptlrpc_bulk_desc *desc) +{ + int i; + + for (i = 0; i < desc->bd_iov_count ; i++) + put_page(BD_GET_KIOV(desc, i).bv_page); +} + void ptlrpc_retain_replayable_request(struct ptlrpc_request *req, struct obd_import *imp); __u64 ptlrpc_next_xid(void); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 5282c67ab019..4c30ab69a7f6 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -859,8 +859,10 @@ restart_bulk: req->rq_request_portal = MDS_READPAGE_PORTAL; ptlrpc_at_set_req_timeout(req); - desc = ptlrpc_prep_bulk_imp(req, npages, 1, BULK_PUT_SINK, - MDS_BULK_PORTAL); + desc = ptlrpc_prep_bulk_imp(req, npages, 1, + PTLRPC_BULK_PUT_SINK | PTLRPC_BULK_BUF_KIOV, + MDS_BULK_PORTAL, + &ptlrpc_bulk_kiov_pin_ops); if (!desc) { ptlrpc_request_free(req); return -ENOMEM; @@ -868,7 +870,7 @@ restart_bulk: /* NB req now owns desc and will free it when it gets freed */ for (i = 0; i < npages; i++) - ptlrpc_prep_bulk_page_pin(desc, pages[i], 0, PAGE_SIZE); + desc->bd_frag_ops->add_kiov_frag(desc, pages[i], 0, PAGE_SIZE); mdc_readdir_pack(req, offset, PAGE_SIZE * npages, fid); diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 7b5ac4485e3c..2d6fdd004662 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -1386,15 +1386,17 @@ again: body->mcb_units = nrpages; /* allocate bulk transfer descriptor */ - desc = ptlrpc_prep_bulk_imp(req, nrpages, 1, BULK_PUT_SINK, - MGS_BULK_PORTAL); + desc = ptlrpc_prep_bulk_imp(req, nrpages, 1, + PTLRPC_BULK_PUT_SINK | PTLRPC_BULK_BUF_KIOV, + MGS_BULK_PORTAL, + &ptlrpc_bulk_kiov_pin_ops); if (!desc) { rc = -ENOMEM; goto out; } for (i = 0; i < nrpages; i++) - ptlrpc_prep_bulk_page_pin(desc, pages[i], 0, PAGE_SIZE); + desc->bd_frag_ops->add_kiov_frag(desc, pages[i], 0, PAGE_SIZE); ptlrpc_request_set_replen(req); rc = ptlrpc_queue_wait(req); diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 399d36b11a32..2fb0e53c2de2 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -776,8 +776,10 @@ static inline void unstable_page_accounting(struct ptlrpc_bulk_desc *desc, int count = 0; int i; + LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type)); + for (i = 0; i < page_count; i++) { - pg_data_t *pgdat = page_pgdat(desc->bd_iov[i].bv_page); + pg_data_t *pgdat = page_pgdat(BD_GET_KIOV(desc, i).bv_page); if (likely(pgdat == last)) { ++count; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index efd938a10c9a..c570d19715fc 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1030,8 +1030,9 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli, desc = ptlrpc_prep_bulk_imp(req, page_count, cli->cl_import->imp_connect_data.ocd_brw_size >> LNET_MTU_BITS, - opc == OST_WRITE ? BULK_GET_SOURCE : BULK_PUT_SINK, - OST_BULK_PORTAL); + (opc == OST_WRITE ? PTLRPC_BULK_GET_SOURCE : + PTLRPC_BULK_PUT_SINK) | PTLRPC_BULK_BUF_KIOV, OST_BULK_PORTAL, + &ptlrpc_bulk_kiov_pin_ops); if (!desc) { rc = -ENOMEM; @@ -1079,7 +1080,7 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli, LASSERT((pga[0]->flag & OBD_BRW_SRVLOCK) == (pg->flag & OBD_BRW_SRVLOCK)); - ptlrpc_prep_bulk_page_pin(desc, pg->pg, poff, pg->count); + desc->bd_frag_ops->add_kiov_frag(desc, pg->pg, poff, pg->count); requested_nob += pg->count; if (i > 0 && can_merge_pages(pg_prev, pg)) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index fa4d3c9836f8..e4a31eb97495 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -43,6 +43,18 @@ #include "ptlrpc_internal.h" +const struct ptlrpc_bulk_frag_ops ptlrpc_bulk_kiov_pin_ops = { + .add_kiov_frag = ptlrpc_prep_bulk_page_pin, + .release_frags = ptlrpc_release_bulk_page_pin, +}; +EXPORT_SYMBOL(ptlrpc_bulk_kiov_pin_ops); + +const struct ptlrpc_bulk_frag_ops ptlrpc_bulk_kiov_nopin_ops = { + .add_kiov_frag = ptlrpc_prep_bulk_page_nopin, + .release_frags = NULL, +}; +EXPORT_SYMBOL(ptlrpc_bulk_kiov_nopin_ops); + static int ptlrpc_send_new_req(struct ptlrpc_request *req); static int ptlrpcd_check_work(struct ptlrpc_request *req); static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async); @@ -95,24 +107,43 @@ struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid) * Allocate and initialize new bulk descriptor on the sender. * Returns pointer to the descriptor or NULL on error. */ -struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned npages, unsigned max_brw, - unsigned type, unsigned portal) +struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned int nfrags, + unsigned int max_brw, + enum ptlrpc_bulk_op_type type, + unsigned int portal, + const struct ptlrpc_bulk_frag_ops *ops) { struct ptlrpc_bulk_desc *desc; int i; - desc = kzalloc(offsetof(struct ptlrpc_bulk_desc, bd_iov[npages]), - GFP_NOFS); + /* ensure that only one of KIOV or IOVEC is set but not both */ + LASSERT((ptlrpc_is_bulk_desc_kiov(type) && ops->add_kiov_frag) || + (ptlrpc_is_bulk_desc_kvec(type) && ops->add_iov_frag)); + + desc = kzalloc(sizeof(*desc), GFP_NOFS); if (!desc) return NULL; + if (type & PTLRPC_BULK_BUF_KIOV) { + GET_KIOV(desc) = kcalloc(nfrags, sizeof(*GET_KIOV(desc)), + GFP_NOFS); + if (!GET_KIOV(desc)) + goto out; + } else { + GET_KVEC(desc) = kcalloc(nfrags, sizeof(*GET_KVEC(desc)), + GFP_NOFS); + if (!GET_KVEC(desc)) + goto out; + } + spin_lock_init(&desc->bd_lock); init_waitqueue_head(&desc->bd_waitq); - desc->bd_max_iov = npages; + desc->bd_max_iov = nfrags; desc->bd_iov_count = 0; desc->bd_portal = portal; desc->bd_type = type; desc->bd_md_count = 0; + desc->bd_frag_ops = (struct ptlrpc_bulk_frag_ops *)ops; LASSERT(max_brw > 0); desc->bd_md_max_brw = min(max_brw, PTLRPC_BULK_OPS_COUNT); /* @@ -123,24 +154,30 @@ struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned npages, unsigned max_brw, LNetInvalidateHandle(&desc->bd_mds[i]); return desc; +out: + return NULL; } /** * Prepare bulk descriptor for specified outgoing request \a req that - * can fit \a npages * pages. \a type is bulk type. \a portal is where + * can fit \a nfrags * pages. \a type is bulk type. \a portal is where * the bulk to be sent. Used on client-side. * Returns pointer to newly allocated initialized bulk descriptor or NULL on * error. */ struct ptlrpc_bulk_desc *ptlrpc_prep_bulk_imp(struct ptlrpc_request *req, - unsigned npages, unsigned max_brw, - unsigned type, unsigned portal) + unsigned int nfrags, + unsigned int max_brw, + unsigned int type, + unsigned int portal, + const struct ptlrpc_bulk_frag_ops *ops) { struct obd_import *imp = req->rq_import; struct ptlrpc_bulk_desc *desc; - LASSERT(type == BULK_PUT_SINK || type == BULK_GET_SOURCE); - desc = ptlrpc_new_bulk(npages, max_brw, type, portal); + LASSERT(ptlrpc_is_bulk_op_passive(type)); + + desc = ptlrpc_new_bulk(nfrags, max_brw, type, portal, ops); if (!desc) return NULL; @@ -158,56 +195,82 @@ struct ptlrpc_bulk_desc *ptlrpc_prep_bulk_imp(struct ptlrpc_request *req, } EXPORT_SYMBOL(ptlrpc_prep_bulk_imp); -/** - * Add a page \a page to the bulk descriptor \a desc. - * Data to transfer in the page starts at offset \a pageoffset and - * amount of data to transfer from the page is \a len - */ void __ptlrpc_prep_bulk_page(struct ptlrpc_bulk_desc *desc, struct page *page, int pageoffset, int len, int pin) { + struct bio_vec *kiov; + LASSERT(desc->bd_iov_count < desc->bd_max_iov); LASSERT(page); LASSERT(pageoffset >= 0); LASSERT(len > 0); LASSERT(pageoffset + len <= PAGE_SIZE); + LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type)); + + kiov = &BD_GET_KIOV(desc, desc->bd_iov_count); desc->bd_nob += len; if (pin) get_page(page); - ptlrpc_add_bulk_page(desc, page, pageoffset, len); + kiov->bv_page = page; + kiov->bv_offset = pageoffset; + kiov->bv_len = len; + + desc->bd_iov_count++; } EXPORT_SYMBOL(__ptlrpc_prep_bulk_page); -/** - * Uninitialize and free bulk descriptor \a desc. - * Works on bulk descriptors both from server and client side. - */ -void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc, int unpin) +int ptlrpc_prep_bulk_frag(struct ptlrpc_bulk_desc *desc, + void *frag, int len) { - int i; + struct kvec *iovec; + + LASSERT(desc->bd_iov_count < desc->bd_max_iov); + LASSERT(frag); + LASSERT(len > 0); + LASSERT(ptlrpc_is_bulk_desc_kvec(desc->bd_type)); + + iovec = &BD_GET_KVEC(desc, desc->bd_iov_count); + + desc->bd_nob += len; + + iovec->iov_base = frag; + iovec->iov_len = len; + desc->bd_iov_count++; + + return desc->bd_nob; +} +EXPORT_SYMBOL(ptlrpc_prep_bulk_frag); + +void ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc) +{ LASSERT(desc->bd_iov_count != LI_POISON); /* not freed already */ LASSERT(desc->bd_md_count == 0); /* network hands off */ LASSERT((desc->bd_export != NULL) ^ (desc->bd_import != NULL)); + LASSERT(desc->bd_frag_ops); - sptlrpc_enc_pool_put_pages(desc); + if (ptlrpc_is_bulk_desc_kiov(desc->bd_type)) + sptlrpc_enc_pool_put_pages(desc); if (desc->bd_export) class_export_put(desc->bd_export); else class_import_put(desc->bd_import); - if (unpin) { - for (i = 0; i < desc->bd_iov_count; i++) - put_page(desc->bd_iov[i].bv_page); - } + if (desc->bd_frag_ops->release_frags) + desc->bd_frag_ops->release_frags(desc); + + if (ptlrpc_is_bulk_desc_kiov(desc->bd_type)) + kfree(GET_KIOV(desc)); + else + kfree(GET_KVEC(desc)); kfree(desc); } -EXPORT_SYMBOL(__ptlrpc_free_bulk); +EXPORT_SYMBOL(ptlrpc_free_bulk); /** * Set server timelimit for this req, i.e. how long are we willing to wait @@ -2266,7 +2329,7 @@ static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked) request->rq_import = NULL; } if (request->rq_bulk) - ptlrpc_free_bulk_pin(request->rq_bulk); + ptlrpc_free_bulk(request->rq_bulk); if (request->rq_reqbuf || request->rq_clrbuf) sptlrpc_cli_free_reqbuf(request); diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index 283dfb296d35..49f3e6368415 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -182,9 +182,9 @@ void client_bulk_callback(lnet_event_t *ev) struct ptlrpc_bulk_desc *desc = cbid->cbid_arg; struct ptlrpc_request *req; - LASSERT((desc->bd_type == BULK_PUT_SINK && + LASSERT((ptlrpc_is_bulk_put_sink(desc->bd_type) && ev->type == LNET_EVENT_PUT) || - (desc->bd_type == BULK_GET_SOURCE && + (ptlrpc_is_bulk_get_source(desc->bd_type) && ev->type == LNET_EVENT_GET) || ev->type == LNET_EVENT_UNLINK); LASSERT(ev->unlinked); diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 9c937398a085..c2dd948de598 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -127,8 +127,7 @@ static int ptlrpc_register_bulk(struct ptlrpc_request *req) LASSERT(desc->bd_md_max_brw <= PTLRPC_BULK_OPS_COUNT); LASSERT(desc->bd_iov_count <= PTLRPC_MAX_BRW_PAGES); LASSERT(desc->bd_req); - LASSERT(desc->bd_type == BULK_PUT_SINK || - desc->bd_type == BULK_GET_SOURCE); + LASSERT(ptlrpc_is_bulk_op_passive(desc->bd_type)); /* cleanup the state of the bulk for it will be reused */ if (req->rq_resend || req->rq_send_state == LUSTRE_IMP_REPLAY) @@ -168,7 +167,7 @@ static int ptlrpc_register_bulk(struct ptlrpc_request *req) for (posted_md = 0; posted_md < total_md; posted_md++, xid++) { md.options = PTLRPC_MD_OPTIONS | - ((desc->bd_type == BULK_GET_SOURCE) ? + (ptlrpc_is_bulk_op_get(desc->bd_type) ? LNET_MD_OP_GET : LNET_MD_OP_PUT); ptlrpc_fill_bulk_md(&md, desc, posted_md); @@ -223,7 +222,7 @@ static int ptlrpc_register_bulk(struct ptlrpc_request *req) CDEBUG(D_NET, "Setup %u bulk %s buffers: %u pages %u bytes, xid x%#llx-%#llx, portal %u\n", desc->bd_md_count, - desc->bd_type == BULK_GET_SOURCE ? "get-source" : "put-sink", + ptlrpc_is_bulk_op_get(desc->bd_type) ? "get-source" : "put-sink", desc->bd_iov_count, desc->bd_nob, desc->bd_last_xid, req->rq_xid, desc->bd_portal); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pers.c b/drivers/staging/lustre/lustre/ptlrpc/pers.c index 5b9fb11c0b6b..94e9fa85d774 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pers.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pers.c @@ -43,6 +43,8 @@ void ptlrpc_fill_bulk_md(lnet_md_t *md, struct ptlrpc_bulk_desc *desc, int mdidx) { + int offset = mdidx * LNET_MAX_IOV; + CLASSERT(PTLRPC_MAX_BRW_PAGES < LI_POISON); LASSERT(mdidx < desc->bd_md_max_brw); @@ -50,23 +52,20 @@ void ptlrpc_fill_bulk_md(lnet_md_t *md, struct ptlrpc_bulk_desc *desc, LASSERT(!(md->options & (LNET_MD_IOVEC | LNET_MD_KIOV | LNET_MD_PHYS))); - md->options |= LNET_MD_KIOV; md->length = max(0, desc->bd_iov_count - mdidx * LNET_MAX_IOV); md->length = min_t(unsigned int, LNET_MAX_IOV, md->length); - if (desc->bd_enc_iov) - md->start = &desc->bd_enc_iov[mdidx * LNET_MAX_IOV]; - else - md->start = &desc->bd_iov[mdidx * LNET_MAX_IOV]; -} - -void ptlrpc_add_bulk_page(struct ptlrpc_bulk_desc *desc, struct page *page, - int pageoffset, int len) -{ - lnet_kiov_t *kiov = &desc->bd_iov[desc->bd_iov_count]; - - kiov->bv_page = page; - kiov->bv_offset = pageoffset; - kiov->bv_len = len; - desc->bd_iov_count++; + if (ptlrpc_is_bulk_desc_kiov(desc->bd_type)) { + md->options |= LNET_MD_KIOV; + if (GET_ENC_KIOV(desc)) + md->start = &BD_GET_ENC_KIOV(desc, offset); + else + md->start = &BD_GET_KIOV(desc, offset); + } else { + md->options |= LNET_MD_IOVEC; + if (GET_ENC_KVEC(desc)) + md->start = &BD_GET_ENC_KVEC(desc, offset); + else + md->start = &BD_GET_KVEC(desc, offset); + } } diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index f14d193287da..b848c25669cb 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -55,8 +55,11 @@ int ptlrpcd_start(struct ptlrpcd_ctl *pc); /* client.c */ void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req, unsigned int service_time); -struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned npages, unsigned max_brw, - unsigned type, unsigned portal); +struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned int nfrags, + unsigned int max_brw, + enum ptlrpc_bulk_op_type type, + unsigned int portal, + const struct ptlrpc_bulk_frag_ops *ops); int ptlrpc_request_cache_init(void); void ptlrpc_request_cache_fini(void); struct ptlrpc_request *ptlrpc_request_cache_alloc(gfp_t flags); @@ -226,8 +229,6 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink); /* pers.c */ void ptlrpc_fill_bulk_md(lnet_md_t *md, struct ptlrpc_bulk_desc *desc, int mdcnt); -void ptlrpc_add_bulk_page(struct ptlrpc_bulk_desc *desc, struct page *page, - int pageoffset, int len); /* pack_generic.c */ struct ptlrpc_reply_state * diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index b2cc5ea6cb93..ceb805d28f28 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -311,7 +311,9 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc) int p_idx, g_idx; int i; - if (!desc->bd_enc_iov) + LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type)); + + if (!GET_ENC_KIOV(desc)) return; LASSERT(desc->bd_iov_count > 0); @@ -326,12 +328,12 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc) LASSERT(page_pools.epp_pools[p_idx]); for (i = 0; i < desc->bd_iov_count; i++) { - LASSERT(desc->bd_enc_iov[i].bv_page); + LASSERT(BD_GET_ENC_KIOV(desc, i).bv_page); LASSERT(g_idx != 0 || page_pools.epp_pools[p_idx]); LASSERT(!page_pools.epp_pools[p_idx][g_idx]); page_pools.epp_pools[p_idx][g_idx] = - desc->bd_enc_iov[i].bv_page; + BD_GET_ENC_KIOV(desc, i).bv_page; if (++g_idx == PAGES_PER_POOL) { p_idx++; @@ -345,8 +347,8 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc) spin_unlock(&page_pools.epp_lock); - kfree(desc->bd_enc_iov); - desc->bd_enc_iov = NULL; + kfree(GET_ENC_KIOV(desc)); + GET_ENC_KIOV(desc) = NULL; } static inline void enc_pools_alloc(void) @@ -520,10 +522,11 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, hashsize = cfs_crypto_hash_digestsize(cfs_hash_alg_id[alg]); for (i = 0; i < desc->bd_iov_count; i++) { - cfs_crypto_hash_update_page(hdesc, desc->bd_iov[i].bv_page, - desc->bd_iov[i].bv_offset & + cfs_crypto_hash_update_page(hdesc, + BD_GET_KIOV(desc, i).bv_page, + BD_GET_KIOV(desc, i).bv_offset & ~PAGE_MASK, - desc->bd_iov[i].bv_len); + BD_GET_KIOV(desc, i).bv_len); } if (hashsize > buflen) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c index cd305bcb334a..c5e7a2309fce 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c @@ -153,14 +153,16 @@ static void corrupt_bulk_data(struct ptlrpc_bulk_desc *desc) char *ptr; unsigned int off, i; + LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type)); + for (i = 0; i < desc->bd_iov_count; i++) { - if (desc->bd_iov[i].bv_len == 0) + if (!BD_GET_KIOV(desc, i).bv_len) continue; - ptr = kmap(desc->bd_iov[i].bv_page); - off = desc->bd_iov[i].bv_offset & ~PAGE_MASK; + ptr = kmap(BD_GET_KIOV(desc, i).bv_page); + off = BD_GET_KIOV(desc, i).bv_offset & ~PAGE_MASK; ptr[off] ^= 0x1; - kunmap(desc->bd_iov[i].bv_page); + kunmap(BD_GET_KIOV(desc, i).bv_page); return; } } @@ -352,11 +354,11 @@ int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx, /* fix the actual data size */ for (i = 0, nob = 0; i < desc->bd_iov_count; i++) { - if (desc->bd_iov[i].bv_len + nob > desc->bd_nob_transferred) { - desc->bd_iov[i].bv_len = - desc->bd_nob_transferred - nob; - } - nob += desc->bd_iov[i].bv_len; + struct bio_vec bv_desc = BD_GET_KIOV(desc, i); + + if (bv_desc.bv_len + nob > desc->bd_nob_transferred) + bv_desc.bv_len = desc->bd_nob_transferred - nob; + nob += bv_desc.bv_len; } rc = plain_verify_bulk_csum(desc, req->rq_flvr.u_bulk.hash.hash_alg, -- cgit v1.2.3 From 55051039fdadc0cf2c271cc83a976842b443b159 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Thu, 27 Oct 2016 18:11:41 -0400 Subject: staging: lustre: lov: remove LSM from struct lustre_md In struct lustre_md replace the struct lov_stripe_md *lsm member with an opaque struct lu_buf layout which holds the layout metadata returned by the server. Refactor the LOV object initialization and layout change code to accommodate this. Simplify lov_unpackmd() and supporting functions according to the reduced number of use cases. Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/13722 Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/cl_object.h | 2 +- drivers/staging/lustre/lustre/include/obd.h | 2 +- drivers/staging/lustre/lustre/llite/file.c | 29 +----- drivers/staging/lustre/lustre/llite/lcommon_cl.c | 2 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 11 +- drivers/staging/lustre/lustre/llite/namei.c | 7 +- drivers/staging/lustre/lustre/lov/lov_ea.c | 9 +- drivers/staging/lustre/lustre/lov/lov_internal.h | 15 +-- drivers/staging/lustre/lustre/lov/lov_obd.c | 1 - drivers/staging/lustre/lustre/lov/lov_object.c | 120 +++++++++++++--------- drivers/staging/lustre/lustre/lov/lov_pack.c | 100 +++++++----------- drivers/staging/lustre/lustre/mdc/mdc_request.c | 19 ++-- 12 files changed, 134 insertions(+), 183 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index dfef4bce3f85..514d650cea4c 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -267,7 +267,7 @@ struct cl_object_conf { /** * Object layout. This is consumed by lov. */ - struct lustre_md *coc_md; + struct lu_buf coc_layout; /** * Description of particular stripe location in the * cluster. This is consumed by osc. diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index ebb301250931..c8a6e23f279e 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -864,7 +864,7 @@ struct obd_ops { /* lmv structures */ struct lustre_md { struct mdt_body *body; - struct lov_stripe_md *lsm; + struct lu_buf layout; struct lmv_stripe_md *lmv; #ifdef CONFIG_FS_POSIX_ACL struct posix_acl *posix_acl; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 2c8df434416c..0ae78c7c081d 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3275,7 +3275,6 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode, struct ll_inode_info *lli = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); struct ldlm_lock *lock; - struct lustre_md md = { NULL }; struct cl_object_conf conf; int rc = 0; bool lvb_ready; @@ -3310,37 +3309,19 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode, /* for layout lock, lmm is returned in lock's lvb. * lvb_data is immutable if the lock is held so it's safe to access it - * without res lock. See the description in ldlm_lock_decref_internal() - * for the condition to free lvb_data of layout lock - */ - if (lock->l_lvb_data) { - rc = obd_unpackmd(sbi->ll_dt_exp, &md.lsm, - lock->l_lvb_data, lock->l_lvb_len); - if (rc < 0) { - CERROR("%s: file " DFID " unpackmd error: %d\n", - ll_get_fsname(inode->i_sb, NULL, 0), - PFID(&lli->lli_fid), rc); - goto out; - } - - LASSERTF(md.lsm, "lvb_data = %p, lvb_len = %u\n", - lock->l_lvb_data, lock->l_lvb_len); - rc = 0; - } - - /* set layout to file. Unlikely this will fail as old layout was + * without res lock. + * + * set layout to file. Unlikely this will fail as old layout was * surely eliminated */ memset(&conf, 0, sizeof(conf)); conf.coc_opc = OBJECT_CONF_SET; conf.coc_inode = inode; conf.coc_lock = lock; - conf.u.coc_md = &md; + conf.u.coc_layout.lb_buf = lock->l_lvb_data; + conf.u.coc_layout.lb_len = lock->l_lvb_len; rc = ll_layout_conf(inode, &conf); - if (md.lsm) - obd_free_memmd(sbi->ll_dt_exp, &md.lsm); - /* refresh layout failed, need to wait */ wait_layout = rc == -EBUSY; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 4087db0244a9..56e414b1d10f 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -150,7 +150,7 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md) struct cl_object_conf conf = { .coc_inode = inode, .u = { - .coc_md = md + .coc_layout = md->layout, } }; int result = 0; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index fba1499d517b..b896ac1ba0f0 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -469,8 +469,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, ptlrpc_req_finished(request); if (IS_ERR(root)) { - if (lmd.lsm) - obd_free_memmd(sbi->ll_dt_exp, &lmd.lsm); #ifdef CONFIG_FS_POSIX_ACL if (lmd.posix_acl) { posix_acl_release(lmd.posix_acl); @@ -1688,11 +1686,9 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); struct mdt_body *body = md->body; - struct lov_stripe_md *lsm = md->lsm; struct ll_sb_info *sbi = ll_i2sbi(inode); - LASSERT((lsm != NULL) == ((body->mbo_valid & OBD_MD_FLEASIZE) != 0)); - if (lsm) + if (body->mbo_valid & OBD_MD_FLEASIZE) cl_file_inode_init(inode, md); if (S_ISDIR(inode->i_mode)) { @@ -2135,17 +2131,14 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, conf.coc_opc = OBJECT_CONF_SET; conf.coc_inode = *inode; conf.coc_lock = lock; - conf.u.coc_md = &md; + conf.u.coc_layout = md.layout; (void)ll_layout_conf(*inode, &conf); } LDLM_LOCK_PUT(lock); } out: - if (md.lsm) - obd_free_memmd(sbi->ll_dt_exp, &md.lsm); md_free_lustre_md(sbi->ll_md_exp, &md); - cleanup: if (rc != 0 && it && it->it_op & IT_OPEN) ll_open_cleanup(sb ? sb : (*inode)->i_sb, req); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 9b4095f9b095..89fd441e0ce2 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -113,12 +113,9 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash, if (inode->i_state & I_NEW) { rc = ll_read_inode2(inode, md); if (!rc && S_ISREG(inode->i_mode) && - !ll_i2info(inode)->lli_clob) { - CDEBUG(D_INODE, "%s: apply lsm %p to inode "DFID"\n", - ll_get_fsname(sb, NULL, 0), md->lsm, - PFID(ll_inode2fid(inode))); + !ll_i2info(inode)->lli_clob) rc = cl_file_inode_init(inode, md); - } + if (rc) { make_bad_inode(inode); unlock_new_inode(inode); diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c index d7dc0aa113de..53db1707f003 100644 --- a/drivers/staging/lustre/lustre/lov/lov_ea.c +++ b/drivers/staging/lustre/lustre/lov/lov_ea.c @@ -76,18 +76,19 @@ static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes, return 0; } -struct lov_stripe_md *lsm_alloc_plain(__u16 stripe_count, int *size) +struct lov_stripe_md *lsm_alloc_plain(u16 stripe_count) { + size_t oinfo_ptrs_size, lsm_size; struct lov_stripe_md *lsm; struct lov_oinfo *loi; - int i, oinfo_ptrs_size; + unsigned int i; LASSERT(stripe_count <= LOV_MAX_STRIPE_COUNT); oinfo_ptrs_size = sizeof(struct lov_oinfo *) * stripe_count; - *size = sizeof(struct lov_stripe_md) + oinfo_ptrs_size; + lsm_size = sizeof(*lsm) + oinfo_ptrs_size; - lsm = libcfs_kvzalloc(*size, GFP_NOFS); + lsm = libcfs_kvzalloc(lsm_size, GFP_NOFS); if (!lsm) return NULL; diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 41e7c5fc374e..5b151bb40ebe 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -79,13 +79,6 @@ static inline bool lsm_has_objects(struct lov_stripe_md *lsm) return true; } -static inline int lov_stripe_md_size(unsigned int stripe_count) -{ - struct lov_stripe_md lsm; - - return sizeof(lsm) + stripe_count * sizeof(lsm.lsm_oinfo[0]); -} - struct lsm_operations { void (*lsm_free)(struct lov_stripe_md *); void (*lsm_stripe_by_index)(struct lov_stripe_md *, int *, loff_t *, @@ -254,10 +247,8 @@ int lov_del_target(struct obd_device *obd, __u32 index, /* lov_pack.c */ ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf, size_t buf_size); -int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int lmm_bytes); -int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, - int pattern, int magic); +struct lov_stripe_md *lov_unpackmd(struct lov_obd *lov, struct lov_mds_md *lmm, + size_t lmm_size); int lov_free_memmd(struct lov_stripe_md **lsmp); void lov_dump_lmm_v1(int level, struct lov_mds_md_v1 *lmm); @@ -265,7 +256,7 @@ void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm); void lov_dump_lmm_common(int level, void *lmmp); /* lov_ea.c */ -struct lov_stripe_md *lsm_alloc_plain(__u16 stripe_count, int *size); +struct lov_stripe_md *lsm_alloc_plain(u16 stripe_count); void lsm_free_plain(struct lov_stripe_md *lsm); void dump_lsm(unsigned int level, const struct lov_stripe_md *lsm); diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 621f66ef1d9b..421a0e2182bb 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1406,7 +1406,6 @@ static struct obd_ops lov_obd_ops = { .disconnect = lov_disconnect, .statfs = lov_statfs, .statfs_async = lov_statfs_async, - .unpackmd = lov_unpackmd, .iocontrol = lov_iocontrol, .get_info = lov_get_info, .set_info_async = lov_set_info_async, diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 82b99e040b25..711a3b96d90e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -39,6 +39,11 @@ #include "lov_cl_internal.h" +static inline struct lov_device *lov_object_dev(struct lov_object *obj) +{ + return lu2lov_dev(obj->lo_cl.co_lu.lo_dev); +} + /** \addtogroup lov * @{ */ @@ -51,7 +56,7 @@ struct lov_layout_operations { int (*llo_init)(const struct lu_env *env, struct lov_device *dev, - struct lov_object *lov, + struct lov_object *lov, struct lov_stripe_md *lsm, const struct cl_object_conf *conf, union lov_layout_state *state); int (*llo_delete)(const struct lu_env *env, struct lov_object *lov, @@ -96,17 +101,17 @@ static void lov_install_empty(const struct lu_env *env, */ } -static int lov_init_empty(const struct lu_env *env, - struct lov_device *dev, struct lov_object *lov, +static int lov_init_empty(const struct lu_env *env, struct lov_device *dev, + struct lov_object *lov, struct lov_stripe_md *lsm, const struct cl_object_conf *conf, - union lov_layout_state *state) + union lov_layout_state *state) { return 0; } static void lov_install_raid0(const struct lu_env *env, struct lov_object *lov, - union lov_layout_state *state) + union lov_layout_state *state) { } @@ -211,8 +216,8 @@ static int lov_page_slice_fixup(struct lov_object *lov, return cl_object_header(stripe)->coh_page_bufsize; } -static int lov_init_raid0(const struct lu_env *env, - struct lov_device *dev, struct lov_object *lov, +static int lov_init_raid0(const struct lu_env *env, struct lov_device *dev, + struct lov_object *lov, struct lov_stripe_md *lsm, const struct cl_object_conf *conf, union lov_layout_state *state) { @@ -222,7 +227,6 @@ static int lov_init_raid0(const struct lu_env *env, struct cl_object *stripe; struct lov_thread_info *lti = lov_env_info(env); struct cl_object_conf *subconf = <i->lti_stripe_conf; - struct lov_stripe_md *lsm = conf->u.coc_md->lsm; struct lu_fid *ofid = <i->lti_fid; struct lov_layout_raid0 *r0 = &state->raid0; @@ -297,13 +301,11 @@ out: return result; } -static int lov_init_released(const struct lu_env *env, - struct lov_device *dev, struct lov_object *lov, +static int lov_init_released(const struct lu_env *env, struct lov_device *dev, + struct lov_object *lov, struct lov_stripe_md *lsm, const struct cl_object_conf *conf, union lov_layout_state *state) { - struct lov_stripe_md *lsm = conf->u.coc_md->lsm; - LASSERT(lsm); LASSERT(lsm_is_released(lsm)); LASSERT(!lov->lo_lsm); @@ -720,25 +722,20 @@ static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov) } static int lov_layout_change(const struct lu_env *unused, - struct lov_object *lov, + struct lov_object *lov, struct lov_stripe_md *lsm, const struct cl_object_conf *conf) { - int result; - enum lov_layout_type llt = LLT_EMPTY; + enum lov_layout_type llt = lov_type(lsm); union lov_layout_state *state = &lov->u; const struct lov_layout_operations *old_ops; const struct lov_layout_operations *new_ops; - void *cookie; struct lu_env *env; int refcheck; + int rc; LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch)); - if (conf->u.coc_md) - llt = lov_type(conf->u.coc_md->lsm); - LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch)); - cookie = cl_env_reenter(); env = cl_env_get(&refcheck); if (IS_ERR(env)) { @@ -746,6 +743,8 @@ static int lov_layout_change(const struct lu_env *unused, return PTR_ERR(env); } + LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch)); + CDEBUG(D_INODE, DFID" from %s to %s\n", PFID(lu_object_fid(lov2lu(lov))), llt2str(lov->lo_type), llt2str(llt)); @@ -753,38 +752,38 @@ static int lov_layout_change(const struct lu_env *unused, old_ops = &lov_dispatch[lov->lo_type]; new_ops = &lov_dispatch[llt]; - result = cl_object_prune(env, &lov->lo_cl); - if (result != 0) + rc = cl_object_prune(env, &lov->lo_cl); + if (rc) goto out; - result = old_ops->llo_delete(env, lov, &lov->u); - if (result == 0) { - old_ops->llo_fini(env, lov, &lov->u); + rc = old_ops->llo_delete(env, lov, &lov->u); + if (rc) + goto out; - LASSERT(atomic_read(&lov->lo_active_ios) == 0); + old_ops->llo_fini(env, lov, &lov->u); - lov->lo_type = LLT_EMPTY; - /* page bufsize fixup */ - cl_object_header(&lov->lo_cl)->coh_page_bufsize -= + LASSERT(!atomic_read(&lov->lo_active_ios)); + + lov->lo_type = LLT_EMPTY; + + /* page bufsize fixup */ + cl_object_header(&lov->lo_cl)->coh_page_bufsize -= lov_page_slice_fixup(lov, NULL); - result = new_ops->llo_init(env, - lu2lov_dev(lov->lo_cl.co_lu.lo_dev), - lov, conf, state); - if (result == 0) { - new_ops->llo_install(env, lov, state); - lov->lo_type = llt; - } else { - new_ops->llo_delete(env, lov, state); - new_ops->llo_fini(env, lov, state); - /* this file becomes an EMPTY file. */ - } + rc = new_ops->llo_init(env, lov_object_dev(lov), lov, lsm, conf, state); + if (rc) { + new_ops->llo_delete(env, lov, state); + new_ops->llo_fini(env, lov, state); + /* this file becomes an EMPTY file. */ + goto out; } + new_ops->llo_install(env, lov, state); + lov->lo_type = llt; out: cl_env_put(env, &refcheck); cl_env_reexit(cookie); - return result; + return rc; } /***************************************************************************** @@ -795,26 +794,37 @@ out: int lov_object_init(const struct lu_env *env, struct lu_object *obj, const struct lu_object_conf *conf) { - struct lov_device *dev = lu2lov_dev(obj->lo_dev); struct lov_object *lov = lu2lov(obj); + struct lov_device *dev = lov_object_dev(lov); const struct cl_object_conf *cconf = lu2cl_conf(conf); union lov_layout_state *set = &lov->u; const struct lov_layout_operations *ops; - int result; + struct lov_stripe_md *lsm = NULL; + int rc; init_rwsem(&lov->lo_type_guard); atomic_set(&lov->lo_active_ios, 0); init_waitqueue_head(&lov->lo_waitq); - cl_object_page_init(lu2cl(obj), sizeof(struct lov_page)); + if (cconf->u.coc_layout.lb_buf) { + lsm = lov_unpackmd(dev->ld_lov, + cconf->u.coc_layout.lb_buf, + cconf->u.coc_layout.lb_len); + if (IS_ERR(lsm)) + return PTR_ERR(lsm); + } + /* no locking is necessary, as object is being created */ - lov->lo_type = lov_type(cconf->u.coc_md->lsm); + lov->lo_type = lov_type(lsm); ops = &lov_dispatch[lov->lo_type]; - result = ops->llo_init(env, dev, lov, cconf, set); - if (result == 0) + rc = ops->llo_init(env, dev, lov, lsm, cconf, set); + if (!rc) ops->llo_install(env, lov, set); - return result; + + lov_lsm_put(lsm); + + return rc; } static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, @@ -824,6 +834,15 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, struct lov_object *lov = cl2lov(obj); int result = 0; + if (conf->coc_opc == OBJECT_CONF_SET && + conf->u.coc_layout.lb_buf) { + lsm = lov_unpackmd(lov_object_dev(lov)->ld_lov, + conf->u.coc_layout.lb_buf, + conf->u.coc_layout.lb_len); + if (IS_ERR(lsm)) + return PTR_ERR(lsm); + } + lov_conf_lock(lov); if (conf->coc_opc == OBJECT_CONF_INVALIDATE) { lov->lo_layout_invalid = true; @@ -843,8 +862,6 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, LASSERT(conf->coc_opc == OBJECT_CONF_SET); - if (conf->u.coc_md) - lsm = conf->u.coc_md->lsm; if ((!lsm && !lov->lo_lsm) || ((lsm && lov->lo_lsm) && (lov->lo_lsm->lsm_layout_gen == lsm->lsm_layout_gen) && @@ -862,11 +879,12 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, goto out; } - result = lov_layout_change(env, lov, conf); + result = lov_layout_change(env, lov, lsm, conf); lov->lo_layout_invalid = result != 0; out: lov_conf_unlock(lov); + lov_lsm_put(lsm); CDEBUG(D_INODE, DFID" lo_layout_invalid=%d\n", PFID(lu_object_fid(lov2lu(lov))), lov->lo_layout_invalid); return result; diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index ccc1fae35791..9ba87d2626d5 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -195,34 +195,34 @@ static int lov_verify_lmm(void *lmm, int lmm_bytes, __u16 *stripe_count) return rc; } -int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, - int pattern, int magic) +struct lov_stripe_md *lov_lsm_alloc(u16 stripe_count, u32 pattern, u32 magic) { - int i, lsm_size; + struct lov_stripe_md *lsm; + unsigned int i; - CDEBUG(D_INFO, "alloc lsm, stripe_count %d\n", stripe_count); + CDEBUG(D_INFO, "alloc lsm, stripe_count %u\n", stripe_count); - *lsmp = lsm_alloc_plain(stripe_count, &lsm_size); - if (!*lsmp) { - CERROR("can't allocate lsmp stripe_count %d\n", stripe_count); - return -ENOMEM; + lsm = lsm_alloc_plain(stripe_count); + if (!lsm) { + CERROR("cannot allocate LSM stripe_count %u\n", stripe_count); + return ERR_PTR(-ENOMEM); } - atomic_set(&(*lsmp)->lsm_refc, 1); - spin_lock_init(&(*lsmp)->lsm_lock); - (*lsmp)->lsm_magic = magic; - (*lsmp)->lsm_stripe_count = stripe_count; - (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES * stripe_count; - (*lsmp)->lsm_pattern = pattern; - (*lsmp)->lsm_pool_name[0] = '\0'; - (*lsmp)->lsm_layout_gen = 0; + atomic_set(&lsm->lsm_refc, 1); + spin_lock_init(&lsm->lsm_lock); + lsm->lsm_magic = magic; + lsm->lsm_stripe_count = stripe_count; + lsm->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES * stripe_count; + lsm->lsm_pattern = pattern; + lsm->lsm_pool_name[0] = '\0'; + lsm->lsm_layout_gen = 0; if (stripe_count > 0) - (*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0; + lsm->lsm_oinfo[0]->loi_ost_idx = ~0; for (i = 0; i < stripe_count; i++) - loi_init((*lsmp)->lsm_oinfo[i]); + loi_init(lsm->lsm_oinfo[i]); - return lsm_size; + return lsm; } int lov_free_memmd(struct lov_stripe_md **lsmp) @@ -242,56 +242,34 @@ int lov_free_memmd(struct lov_stripe_md **lsmp) /* Unpack LOV object metadata from disk storage. It is packed in LE byte * order and is opaque to the networking layer. */ -int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int lmm_bytes) +struct lov_stripe_md *lov_unpackmd(struct lov_obd *lov, struct lov_mds_md *lmm, + size_t lmm_size) { - struct obd_device *obd = class_exp2obd(exp); - struct lov_obd *lov = &obd->u.lov; - int rc = 0, lsm_size; - __u16 stripe_count; - __u32 magic; - __u32 pattern; - - /* If passed an MDS struct use values from there, otherwise defaults */ - if (lmm) { - rc = lov_verify_lmm(lmm, lmm_bytes, &stripe_count); - if (rc) - return rc; - magic = le32_to_cpu(lmm->lmm_magic); - pattern = le32_to_cpu(lmm->lmm_pattern); - } else { - magic = LOV_MAGIC; - stripe_count = lov_get_stripecnt(lov, magic, 0); - pattern = LOV_PATTERN_RAID0; - } + struct lov_stripe_md *lsm; + u16 stripe_count; + u32 pattern; + u32 magic; + int rc; - /* If we aren't passed an lsmp struct, we just want the size */ - if (!lsmp) { - /* XXX LOV STACKING call into osc for sizes */ - LBUG(); - return lov_stripe_md_size(stripe_count); - } - /* If we are passed an allocated struct but nothing to unpack, free */ - if (*lsmp && !lmm) { - lov_free_memmd(lsmp); - return 0; - } + rc = lov_verify_lmm(lmm, lmm_size, &stripe_count); + if (rc) + return ERR_PTR(rc); - lsm_size = lov_alloc_memmd(lsmp, stripe_count, pattern, magic); - if (lsm_size < 0) - return lsm_size; + magic = le32_to_cpu(lmm->lmm_magic); + pattern = le32_to_cpu(lmm->lmm_pattern); - /* If we are passed a pointer but nothing to unpack, we only alloc */ - if (!lmm) - return lsm_size; + lsm = lov_lsm_alloc(stripe_count, pattern, magic); + if (IS_ERR(lsm)) + return lsm; - rc = lsm_op_find(magic)->lsm_unpackmd(lov, *lsmp, lmm); + LASSERT(lsm_op_find(magic)); + rc = lsm_op_find(magic)->lsm_unpackmd(lov, lsm, lmm); if (rc) { - lov_free_memmd(lsmp); - return rc; + lov_free_memmd(&lsm); + return ERR_PTR(rc); } - return lsm_size; + return lsm; } /* Retrieve object striping information. diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 4c30ab69a7f6..c620f5c5a7da 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -420,9 +420,6 @@ static int mdc_get_lustre_md(struct obd_export *exp, md->body = req_capsule_server_get(pill, &RMF_MDT_BODY); if (md->body->mbo_valid & OBD_MD_FLEASIZE) { - int lmmsize; - struct lov_mds_md *lmm; - if (!S_ISREG(md->body->mbo_mode)) { CDEBUG(D_INFO, "OBD_MD_FLEASIZE set, should be a regular file, but is not\n"); @@ -436,17 +433,15 @@ static int mdc_get_lustre_md(struct obd_export *exp, rc = -EPROTO; goto out; } - lmmsize = md->body->mbo_eadatasize; - lmm = req_capsule_server_sized_get(pill, &RMF_MDT_MD, lmmsize); - if (!lmm) { + + md->layout.lb_len = md->body->mbo_eadatasize; + md->layout.lb_buf = req_capsule_server_sized_get(pill, + &RMF_MDT_MD, + md->layout.lb_len); + if (!md->layout.lb_buf) { rc = -EPROTO; goto out; } - - rc = obd_unpackmd(dt_exp, &md->lsm, lmm, lmmsize); - if (rc < 0) - goto out; - } else if (md->body->mbo_valid & OBD_MD_FLDIREA) { int lmvsize; struct lov_mds_md *lmv; @@ -509,8 +504,6 @@ out: #ifdef CONFIG_FS_POSIX_ACL posix_acl_release(md->posix_acl); #endif - if (md->lsm) - obd_free_memmd(dt_exp, &md->lsm); } return rc; } -- cgit v1.2.3 From 84078adb8131bdc5b004e7c95ca8bbe68c6439bf Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Thu, 27 Oct 2016 18:11:42 -0400 Subject: staging: lustre: clio: update file attributes after sync This really only affects clients that are attached to lustre server running ZFS, because zfs does not update # of blocks until the blocks are flushed to disk. This patch update file's blocks attribute after OST_SYNC completes. Signed-off-by: Bobi Jam Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4389 Reviewed-on: http://review.whamcloud.com/12915 Reviewed-by: Nathaniel Clark Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_internal.h | 2 +- drivers/staging/lustre/lustre/osc/osc_io.c | 3 +-- drivers/staging/lustre/lustre/osc/osc_request.c | 21 ++++++++++++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index dc708ea17b29..12d3b589f39f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -124,7 +124,7 @@ int osc_setattr_async(struct obd_export *exp, struct obdo *oa, int osc_punch_base(struct obd_export *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset); -int osc_sync_base(struct obd_export *exp, struct obdo *oa, +int osc_sync_base(struct osc_object *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset); diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 8eb42757a675..3b82d0a6c45e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -760,8 +760,7 @@ static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj, init_completion(&cbargs->opc_sync); - rc = osc_sync_base(osc_export(obj), oa, osc_async_upcall, cbargs, - PTLRPCD_SET); + rc = osc_sync_base(obj, oa, osc_async_upcall, cbargs, PTLRPCD_SET); return rc; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index c570d19715fc..091558eebd83 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -82,6 +82,7 @@ struct osc_setattr_args { }; struct osc_fsync_args { + struct osc_object *fa_obj; struct obdo *fa_oa; obd_enqueue_update_f fa_upcall; void *fa_cookie; @@ -365,8 +366,11 @@ static int osc_sync_interpret(const struct lu_env *env, struct ptlrpc_request *req, void *arg, int rc) { + struct cl_attr *attr = &osc_env_info(env)->oti_attr; struct osc_fsync_args *fa = arg; + unsigned long valid = 0; struct ost_body *body; + struct cl_object *obj; if (rc) goto out; @@ -379,15 +383,29 @@ static int osc_sync_interpret(const struct lu_env *env, } *fa->fa_oa = body->oa; + obj = osc2cl(fa->fa_obj); + + /* Update osc object's blocks attribute */ + cl_object_attr_lock(obj); + if (body->oa.o_valid & OBD_MD_FLBLOCKS) { + attr->cat_blocks = body->oa.o_blocks; + valid |= CAT_BLOCKS; + } + + if (valid) + cl_object_attr_update(env, obj, attr, valid); + cl_object_attr_unlock(obj); + out: rc = fa->fa_upcall(fa->fa_cookie, rc); return rc; } -int osc_sync_base(struct obd_export *exp, struct obdo *oa, +int osc_sync_base(struct osc_object *obj, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset) { + struct obd_export *exp = osc_export(obj); struct ptlrpc_request *req; struct ost_body *body; struct osc_fsync_args *fa; @@ -414,6 +432,7 @@ int osc_sync_base(struct obd_export *exp, struct obdo *oa, CLASSERT(sizeof(*fa) <= sizeof(req->rq_async_args)); fa = ptlrpc_req_async_args(req); + fa->fa_obj = obj; fa->fa_oa = oa; fa->fa_upcall = upcall; fa->fa_cookie = cookie; -- cgit v1.2.3 From e7291a6d1a807d1391ebf2c4c259681fec149adb Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Thu, 27 Oct 2016 18:11:43 -0400 Subject: staging: lustre: dne: setdirstripe should fail if not supported If MDS doesn't support striped directory, creating striped directory from a userland utility such as 'lfs setdirstripe' should fail. Signed-off-by: Lai Siyao Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6661 Reviewed-on: http://review.whamcloud.com/15123 Reviewed-by: James Simmons Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 929c32c6bb10..6e744a5e9f0d 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -419,6 +419,10 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, PFID(ll_inode2fid(parent)), parent, dirname, (int)lump->lum_stripe_offset, lump->lum_stripe_count); + if (lump->lum_stripe_count > 1 && + !(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_DIR_STRIPE)) + return -EINVAL; + if (lump->lum_magic != cpu_to_le32(LMV_USER_MAGIC)) lustre_swab_lmv_user_md(lump); -- cgit v1.2.3 From 96049bd1ecd0f17cbeccfcc0cf2014f3a9d4b6a0 Mon Sep 17 00:00:00 2001 From: Gregoire Pichon Date: Thu, 27 Oct 2016 18:11:44 -0400 Subject: staging: lustre: ptlrpc: embed highest XID in each request Atomically assign XIDs and put request and sending list so we can learn the lowest unreplied XID at any point. This allows to embed in every resquests the highest XID for which a reply has been received and does not have an unreplied lower-numbered XID. This will be used by the MDT target to release in-memory reply data corresponding to XIDs of reply received by the client. Signed-off-by: Alex Zhuravlev Signed-off-by: Gregoire Pichon Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5319 Reviewed-on: http://review.whamcloud.com/14793 Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_net.h | 1 + drivers/staging/lustre/lustre/ptlrpc/client.c | 34 +++++++++++++++++++++- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 15 ++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 67a7095d26b0..a14f1a453e50 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -2069,6 +2069,7 @@ void lustre_msg_set_handle(struct lustre_msg *msg, struct lustre_handle *handle); void lustre_msg_set_type(struct lustre_msg *msg, __u32 type); void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc); +void lustre_msg_set_last_xid(struct lustre_msg *msg, u64 last_xid); void lustre_msg_set_tag(struct lustre_msg *msg, __u16 tag); void lustre_msg_set_versions(struct lustre_msg *msg, __u64 *versions); void lustre_msg_set_transno(struct lustre_msg *msg, __u64 transno); diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index e4a31eb97495..e4fbdd0d0720 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -700,7 +700,6 @@ int ptlrpc_request_bufs_pack(struct ptlrpc_request *request, ptlrpc_at_set_req_timeout(request); - request->rq_xid = ptlrpc_next_xid(); lustre_msg_set_opc(request->rq_reqmsg, opcode); /* Let's setup deadline for req/reply/bulk unlink for opcode. */ @@ -1436,6 +1435,8 @@ static int after_reply(struct ptlrpc_request *req) static int ptlrpc_send_new_req(struct ptlrpc_request *req) { struct obd_import *imp = req->rq_import; + struct list_head *tmp; + u64 min_xid = ~0ULL; int rc; LASSERT(req->rq_phase == RQ_PHASE_NEW); @@ -1448,6 +1449,18 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) spin_lock(&imp->imp_lock); + /* + * the very first time we assign XID. it's important to assign XID + * and put it on the list atomically, so that the lowest assigned + * XID is always known. this is vital for multislot last_rcvd + */ + if (req->rq_send_state == LUSTRE_IMP_REPLAY) { + LASSERT(req->rq_xid); + } else { + LASSERT(!req->rq_xid); + req->rq_xid = ptlrpc_next_xid(); + } + if (!req->rq_generation_set) req->rq_import_generation = imp->imp_generation; @@ -1477,8 +1490,27 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) LASSERT(list_empty(&req->rq_list)); list_add_tail(&req->rq_list, &imp->imp_sending_list); atomic_inc(&req->rq_import->imp_inflight); + + /* find the lowest unreplied XID */ + list_for_each(tmp, &imp->imp_delayed_list) { + struct ptlrpc_request *r; + + r = list_entry(tmp, struct ptlrpc_request, rq_list); + if (r->rq_xid < min_xid) + min_xid = r->rq_xid; + } + list_for_each(tmp, &imp->imp_sending_list) { + struct ptlrpc_request *r; + + r = list_entry(tmp, struct ptlrpc_request, rq_list); + if (r->rq_xid < min_xid) + min_xid = r->rq_xid; + } spin_unlock(&imp->imp_lock); + if (likely(min_xid != ~0ULL)) + lustre_msg_set_last_xid(req->rq_reqmsg, min_xid - 1); + lustre_msg_set_status(req->rq_reqmsg, current_pid()); rc = sptlrpc_req_refresh_ctx(req, -1); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 1c06b4e8ae88..4f63a80f2639 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1255,6 +1255,21 @@ void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc) } } +void lustre_msg_set_last_xid(struct lustre_msg *msg, u64 last_xid) +{ + switch (msg->lm_magic) { + case LUSTRE_MSG_MAGIC_V2: { + struct ptlrpc_body *pb = lustre_msg_ptlrpc_body(msg); + + LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg); + pb->pb_last_xid = last_xid; + return; + } + default: + LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); + } +} + void lustre_msg_set_tag(struct lustre_msg *msg, __u16 tag) { switch (msg->lm_magic) { -- cgit v1.2.3 From 51cfb8c43be65939c9d3a56ab821a63455a2eeca Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Thu, 27 Oct 2016 18:11:45 -0400 Subject: staging: lustre: llite: basic support of SELinux in CLIO Bring the ability to properly initiate security context on SELinux-enabled client and store it on server side via extended attribute. Security context initialization is not atomic, but that would require a wire protocol change to send security label in the creation request. Filter out security.selinux from xattr cache as it is already cached in system slab. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5560 Reviewed-on: http://review.whamcloud.com/11648 Reviewed-by: Dmitry Eremin Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/Makefile | 6 +- drivers/staging/lustre/lustre/llite/dir.c | 11 +++ .../staging/lustre/lustre/llite/llite_internal.h | 4 + drivers/staging/lustre/lustre/llite/namei.c | 5 +- drivers/staging/lustre/lustre/llite/xattr.c | 60 +++++++-------- drivers/staging/lustre/lustre/llite/xattr_cache.c | 4 + .../staging/lustre/lustre/llite/xattr_security.c | 88 ++++++++++++++++++++++ 7 files changed, 140 insertions(+), 38 deletions(-) create mode 100644 drivers/staging/lustre/lustre/llite/xattr_security.c (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index 3690bee45f09..ca9c275d4a39 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -1,7 +1,7 @@ obj-$(CONFIG_LUSTRE_FS) += lustre.o lustre-y := dcache.o dir.o file.o llite_lib.o llite_nfs.o \ - rw.o namei.o symlink.o llite_mmap.o range_lock.o \ - xattr.o xattr_cache.o rw26.o super25.o statahead.o \ - glimpse.o lcommon_cl.o lcommon_misc.o \ + rw.o rw26.o namei.o symlink.o llite_mmap.o range_lock.o \ + xattr.o xattr_cache.o xattr_security.o \ + super25.o statahead.o glimpse.o lcommon_cl.o lcommon_misc.o \ vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o vvp_req.o \ lproc_llite.o diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 6e744a5e9f0d..fb367aebf14a 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -410,6 +410,8 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, struct ptlrpc_request *request = NULL; struct md_op_data *op_data; struct ll_sb_info *sbi = ll_i2sbi(parent); + struct inode *inode = NULL; + struct dentry dentry; int err; if (unlikely(lump->lum_magic != LMV_USER_MAGIC)) @@ -443,8 +445,17 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, from_kgid(&init_user_ns, current_fsgid()), cfs_curproc_cap_pack(), 0, &request); ll_finish_md_op_data(op_data); + + err = ll_prep_inode(&inode, request, parent->i_sb, NULL); if (err) goto err_exit; + + memset(&dentry, 0, sizeof(dentry)); + dentry.d_inode = inode; + + err = ll_init_security(&dentry, inode, parent); + iput(inode); + err_exit: ptlrpc_req_finished(request); return err; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 80fb862b6d2f..8bd1eb80ce83 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -261,6 +261,9 @@ int ll_xattr_cache_destroy(struct inode *inode); int ll_xattr_cache_get(struct inode *inode, const char *name, char *buffer, size_t size, __u64 valid); +int ll_init_security(struct dentry *dentry, struct inode *inode, + struct inode *dir); + /* * Locking to guarantee consistency of non-atomic updates to long long i_size, * consistency between file size and KMS. @@ -998,6 +1001,7 @@ extern const struct xattr_handler *ll_xattr_handlers[]; ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size); int ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer, size_t size, __u64 valid); +const struct xattr_handler *get_xattr_type(const char *name); /** * Common IO arguments for various VFS I/O interfaces. diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 89fd441e0ce2..74d9b738034a 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -790,7 +790,8 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, return PTR_ERR(inode); d_instantiate(dentry, inode); - return 0; + + return ll_init_security(dentry, inode, dir); } void ll_update_times(struct ptlrpc_request *request, struct inode *inode) @@ -885,6 +886,8 @@ again: goto err_exit; d_instantiate(dentry, inode); + + err = ll_init_security(dentry, inode, dir); err_exit: if (request) ptlrpc_req_finished(request); diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index b8b5c3279ad8..3ae1a02a1966 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -44,48 +44,39 @@ #include "llite_internal.h" -static -int get_xattr_type(const char *name) +const struct xattr_handler *get_xattr_type(const char *name) { - if (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)) - return XATTR_ACL_ACCESS_T; + int i = 0; - if (!strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT)) - return XATTR_ACL_DEFAULT_T; + while (ll_xattr_handlers[i]) { + size_t len = strlen(ll_xattr_handlers[i]->prefix); - if (!strncmp(name, XATTR_USER_PREFIX, - sizeof(XATTR_USER_PREFIX) - 1)) - return XATTR_USER_T; - - if (!strncmp(name, XATTR_TRUSTED_PREFIX, - sizeof(XATTR_TRUSTED_PREFIX) - 1)) - return XATTR_TRUSTED_T; - - if (!strncmp(name, XATTR_SECURITY_PREFIX, - sizeof(XATTR_SECURITY_PREFIX) - 1)) - return XATTR_SECURITY_T; - - if (!strncmp(name, XATTR_LUSTRE_PREFIX, - sizeof(XATTR_LUSTRE_PREFIX) - 1)) - return XATTR_LUSTRE_T; - - return XATTR_OTHER_T; + if (!strncmp(ll_xattr_handlers[i]->prefix, name, len)) + return ll_xattr_handlers[i]; + i++; + } + return NULL; } -static -int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type) +static int xattr_type_filter(struct ll_sb_info *sbi, + const struct xattr_handler *handler) { - if ((xattr_type == XATTR_ACL_ACCESS_T || - xattr_type == XATTR_ACL_DEFAULT_T) && + /* No handler means XATTR_OTHER_T */ + if (!handler) + return -EOPNOTSUPP; + + if ((handler->flags == XATTR_ACL_ACCESS_T || + handler->flags == XATTR_ACL_DEFAULT_T) && !(sbi->ll_flags & LL_SBI_ACL)) return -EOPNOTSUPP; - if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR)) + if (handler->flags == XATTR_USER_T && + !(sbi->ll_flags & LL_SBI_USER_XATTR)) return -EOPNOTSUPP; - if (xattr_type == XATTR_TRUSTED_T && !capable(CFS_CAP_SYS_ADMIN)) + + if (handler->flags == XATTR_TRUSTED_T && + !capable(CFS_CAP_SYS_ADMIN)) return -EPERM; - if (xattr_type == XATTR_OTHER_T) - return -EOPNOTSUPP; return 0; } @@ -111,7 +102,7 @@ ll_xattr_set_common(const struct xattr_handler *handler, valid = OBD_MD_FLXATTR; } - rc = xattr_type_filter(sbi, handler->flags); + rc = xattr_type_filter(sbi, handler); if (rc) return rc; @@ -225,7 +216,8 @@ ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer, void *xdata; int rc; - if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T) { + if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T && + (type != XATTR_SECURITY_T || strcmp(name, "security.selinux"))) { rc = ll_xattr_cache_get(inode, name, buffer, size, valid); if (rc == -EAGAIN) goto getxattr_nocache; @@ -313,7 +305,7 @@ static int ll_xattr_get_common(const struct xattr_handler *handler, ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); - rc = xattr_type_filter(sbi, handler->flags); + rc = xattr_type_filter(sbi, handler); if (rc) return rc; diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c index 50a19a40bd4e..47c1d116dd72 100644 --- a/drivers/staging/lustre/lustre/llite/xattr_cache.c +++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c @@ -415,6 +415,10 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit) CDEBUG(D_CACHE, "not caching %s\n", XATTR_NAME_ACL_ACCESS); rc = 0; + } else if (!strcmp(xdata, "security.selinux")) { + /* Filter out security.selinux, it is cached in slab */ + CDEBUG(D_CACHE, "not caching security.selinux\n"); + rc = 0; } else { rc = ll_xattr_cache_add(&lli->lli_xattrs, xdata, xval, *xsizes); diff --git a/drivers/staging/lustre/lustre/llite/xattr_security.c b/drivers/staging/lustre/lustre/llite/xattr_security.c new file mode 100644 index 000000000000..d61d8018001a --- /dev/null +++ b/drivers/staging/lustre/lustre/llite/xattr_security.c @@ -0,0 +1,88 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see http://www.gnu.org/licenses + * + * GPL HEADER END + */ + +/* + * Copyright (c) 2014 Bull SAS + * Author: Sebastien Buisson sebastien.buisson@bull.net + */ + +/* + * lustre/llite/xattr_security.c + * Handler for storing security labels as extended attributes. + */ +#include +#include +#include "llite_internal.h" + +/** + * A helper function for ll_security_inode_init_security() + * that takes care of setting xattrs + * + * Get security context of @inode from @xattr_array, + * and put it in 'security.xxx' xattr of dentry + * stored in @fs_info. + * + * \retval 0 success + * \retval -ENOMEM if no memory could be allocated for xattr name + * \retval < 0 failure to set xattr + */ +static int +ll_initxattrs(struct inode *inode, const struct xattr *xattr_array, + void *fs_info) +{ + const struct xattr_handler *handler; + struct dentry *dentry = fs_info; + const struct xattr *xattr; + int err = 0; + + handler = get_xattr_type(XATTR_SECURITY_PREFIX); + if (!handler) + return -ENXIO; + + for (xattr = xattr_array; xattr->name; xattr++) { + err = handler->set(handler, dentry, inode, xattr->name, + xattr->value, xattr->value_len, + XATTR_CREATE); + if (err < 0) + break; + } + return err; +} + +/** + * Initializes security context + * + * Get security context of @inode in @dir, + * and put it in 'security.xxx' xattr of @dentry. + * + * \retval 0 success, or SELinux is disabled + * \retval -ENOMEM if no memory could be allocated for xattr name + * \retval < 0 failure to get security context or set xattr + */ +int +ll_init_security(struct dentry *dentry, struct inode *inode, struct inode *dir) +{ + if (!selinux_is_enabled()) + return 0; + + return security_inode_init_security(inode, dir, NULL, + &ll_initxattrs, dentry); +} -- cgit v1.2.3 From d1fc93b730cb7c51a85db07713272bb1dcaa11cd Mon Sep 17 00:00:00 2001 From: wang di Date: Thu, 27 Oct 2016 18:11:47 -0400 Subject: staging: lustre: llite: report back to user bad stripe count If the user is requesting a stripe count larger than what is supported in the file system then report back to the user an error as well as what is the largest possible striping. Signed-off-by: wang di Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6602 Reviewed-on: http://review.whamcloud.com/15162 Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index fb367aebf14a..64a32d5dd116 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1195,6 +1195,7 @@ lmv_out_free: struct lmv_user_md *tmp = NULL; union lmv_mds_md *lmm = NULL; u64 valid = 0; + int max_stripe_count; int stripe_count; int mdt_index; int lum_size; @@ -1206,6 +1207,7 @@ lmv_out_free: if (copy_from_user(&lum, ulmv, sizeof(*ulmv))) return -EFAULT; + max_stripe_count = lum.lum_stripe_count; /* * lum_magic will indicate which stripe the ioctl will like * to get, LMV_MAGIC_V1 is for normal LMV stripe, LMV_USER_MAGIC @@ -1240,6 +1242,16 @@ lmv_out_free: } stripe_count = lmv_mds_md_stripe_count_get(lmm); + if (max_stripe_count < stripe_count) { + lum.lum_stripe_count = stripe_count; + if (copy_to_user(ulmv, &lum, sizeof(lum))) { + rc = -EFAULT; + goto finish_req; + } + rc = -E2BIG; + goto finish_req; + } + lum_size = lmv_user_md_size(stripe_count, LMV_MAGIC_V1); tmp = kzalloc(lum_size, GFP_NOFS); if (!tmp) { -- cgit v1.2.3 From f0a3b550207d3eb2d471772e87e3ab885f7e57c5 Mon Sep 17 00:00:00 2001 From: wang di Date: Thu, 27 Oct 2016 18:11:48 -0400 Subject: staging: lustre: ptlrpc: Do not resend req with allow_replay If the request is allowed to be sent during recovery, and it is not timeout yet, then we do not need to resend it in the final stage of recovery. Unnecessary resend will cause the bulk request to resend the request with different mbit, but same xid, and on the remote server side, it will drop such request with same xid, so it will never get the bulk in this case. Signed-off-by: wang di Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6780 Reviewed-on: http://review.whamcloud.com/15458 Reviewed-by: Alex Zhuravlev Reviewed-by: Liang Zhen Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/recover.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c index 405faf0dc9fc..aa9653498044 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/recover.c +++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c @@ -194,7 +194,13 @@ int ptlrpc_resend(struct obd_import *imp) LASSERTF((long)req > PAGE_SIZE && req != LP_POISON, "req %p bad\n", req); LASSERTF(req->rq_type != LI_POISON, "req %p freed\n", req); - if (!ptlrpc_no_resend(req)) + + /* + * If the request is allowed to be sent during replay and it + * is not timeout yet, then it does not need to be resent. + */ + if (!ptlrpc_no_resend(req) && + (req->rq_timedout || !req->rq_allow_replay)) ptlrpc_resend_req(req); } spin_unlock(&imp->imp_lock); -- cgit v1.2.3 From dac91f85c5df1024770d67c581736fe8ec8e8c88 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Thu, 27 Oct 2016 18:11:49 -0400 Subject: staging: lustre: obdecho: don't copy lu_site While creating an echo device, echo_device_alloc() copies the lu_site from MD stack, such kind of copy result in uninitialized mutex and other potential issues. Instead of copying the lu_site, we'd use the lu_site by pointer directly. Signed-off-by: Niu Yawei Signed-off-by: Olaf Faaland Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6765 Reviewed-on: http://review.whamcloud.com/15657 Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdecho/echo_client.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index c69588cfe814..30caf5f5ec96 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -55,7 +55,7 @@ struct echo_device { struct echo_client_obd *ed_ec; struct cl_site ed_site_myself; - struct cl_site *ed_site; + struct lu_site *ed_site; struct lu_device *ed_next; }; @@ -527,17 +527,19 @@ static int echo_site_init(const struct lu_env *env, struct echo_device *ed) } rc = lu_site_init_finish(&site->cs_lu); - if (rc) + if (rc) { + cl_site_fini(site); return rc; + } - ed->ed_site = site; + ed->ed_site = &site->cs_lu; return 0; } static void echo_site_fini(const struct lu_env *env, struct echo_device *ed) { if (ed->ed_site) { - cl_site_fini(ed->ed_site); + lu_site_fini(ed->ed_site); ed->ed_site = NULL; } } @@ -674,7 +676,7 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, goto out_cleanup; } - next->ld_site = &ed->ed_site->cs_lu; + next->ld_site = ed->ed_site; rc = next->ld_type->ldt_ops->ldto_device_init(env, next, next->ld_type->ldt_name, NULL); @@ -741,7 +743,7 @@ static struct lu_device *echo_device_free(const struct lu_env *env, CDEBUG(D_INFO, "echo device:%p is going to be freed, next = %p\n", ed, next); - lu_site_purge(env, &ed->ed_site->cs_lu, -1); + lu_site_purge(env, ed->ed_site, -1); /* check if there are objects still alive. * It shouldn't have any object because lu_site_purge would cleanup @@ -754,7 +756,7 @@ static struct lu_device *echo_device_free(const struct lu_env *env, spin_unlock(&ec->ec_lock); /* purge again */ - lu_site_purge(env, &ed->ed_site->cs_lu, -1); + lu_site_purge(env, ed->ed_site, -1); CDEBUG(D_INFO, "Waiting for the reference of echo object to be dropped\n"); @@ -766,7 +768,7 @@ static struct lu_device *echo_device_free(const struct lu_env *env, CERROR("echo_client still has objects at cleanup time, wait for 1 second\n"); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(cfs_time_seconds(1)); - lu_site_purge(env, &ed->ed_site->cs_lu, -1); + lu_site_purge(env, ed->ed_site, -1); spin_lock(&ec->ec_lock); } spin_unlock(&ec->ec_lock); @@ -780,7 +782,7 @@ static struct lu_device *echo_device_free(const struct lu_env *env, while (next) next = next->ld_type->ldt_ops->ldto_device_free(env, next); - LASSERT(ed->ed_site == lu2cl_site(d->ld_site)); + LASSERT(ed->ed_site == d->ld_site); echo_site_fini(env, ed); cl_device_fini(&ed->ed_cl); kfree(ed); -- cgit v1.2.3 From bb280ab4c879acdd50d7979b00d81c0e8e2dcc36 Mon Sep 17 00:00:00 2001 From: wang di Date: Thu, 27 Oct 2016 18:11:50 -0400 Subject: staging: lustre: mdc: deactive MDT permanently Add active proc entry for MDC, and mark MDC to be inactive once the MDC is deactivated. Signed-off-by: wang di Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6586 Reviewed-on: http://review.whamcloud.com/14747 Reviewed-by: Lai Siyao Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 1 + drivers/staging/lustre/lustre/mdc/lproc_mdc.c | 37 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 7a8d1c8307a7..12e8b1e577e4 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -62,6 +62,7 @@ static void lmv_activate_target(struct lmv_obd *lmv, tgt->ltd_active = activate; lmv->desc.ld_active_tgt_count += (activate ? 1 : -1); + tgt->ltd_exp->exp_obd->obd_inactive = !activate; } /** diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index 5fdee9e7dec1..76b9afc9425b 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -36,6 +36,42 @@ #include "../include/lprocfs_status.h" #include "mdc_internal.h" +static ssize_t active_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct obd_device *dev = container_of(kobj, struct obd_device, + obd_kobj); + + return sprintf(buf, "%u\n", !dev->u.cli.cl_import->imp_deactive); +} + +static ssize_t active_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct obd_device *dev = container_of(kobj, struct obd_device, + obd_kobj); + unsigned long val; + int rc; + + rc = kstrtoul(buffer, 10, &val); + if (rc) + return rc; + + if (val < 0 || val > 1) + return -ERANGE; + + /* opposite senses */ + if (dev->u.cli.cl_import->imp_deactive == val) { + rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val); + if (rc) + count = rc; + } else { + CDEBUG(D_CONFIG, "activate %lu: ignoring repeat request\n", val); + } + return count; +} +LUSTRE_RW_ATTR(active); + static ssize_t max_rpcs_in_flight_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -153,6 +189,7 @@ static struct lprocfs_vars lprocfs_mdc_obd_vars[] = { }; static struct attribute *mdc_attrs[] = { + &lustre_attr_active.attr, &lustre_attr_max_rpcs_in_flight.attr, &lustre_attr_max_mod_rpcs_in_flight.attr, &lustre_attr_max_pages_per_rpc.attr, -- cgit v1.2.3 From 8ae44c778d8cb5bb3a2fed2c2f9d5ac8ae39df02 Mon Sep 17 00:00:00 2001 From: wang di Date: Thu, 27 Oct 2016 18:11:51 -0400 Subject: staging: lustre: ptlrpc: replay bulk request Even though the server might already got the bulk replay request, but bulk transfer timeout, let's replay the bulk request, i.e. treat such replay as same as no replied replay request (See ptlrpc_replay_interpret()). Signed-off-by: wang di Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6924 Reviewed-on: http://review.whamcloud.com/15793 Reviewed-by: Alex Zhuravlev Reviewed-by: Niu Yawei Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index e4fbdd0d0720..bda925ed5294 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -2762,8 +2762,15 @@ static int ptlrpc_replay_interpret(const struct lu_env *env, atomic_dec(&imp->imp_replay_inflight); - if (!ptlrpc_client_replied(req)) { - CERROR("request replay timed out, restarting recovery\n"); + /* + * Note: if it is bulk replay (MDS-MDS replay), then even if + * server got the request, but bulk transfer timeout, let's + * replay the bulk req again + */ + if (!ptlrpc_client_replied(req) || + (req->rq_bulk && + lustre_msg_get_status(req->rq_repmsg) == -ETIMEDOUT)) { + DEBUG_REQ(D_ERROR, req, "request replay timed out.\n"); rc = -ETIMEDOUT; goto out; } -- cgit v1.2.3 From 115ee9d00cfe6b8a9cb0225a19ea8bcf12f7115a Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Thu, 27 Oct 2016 18:11:52 -0400 Subject: staging: lustre: mdt: disable IMA support For IMA (Integrity Measurement Architecture), there are two xattr "security.ima" and "security.evm" to protect the file to be modified accidentally or maliciously, the two xattr are not compatible with VBR, then disable it to workaround the problem currently and enable it when the conditions are ready. Signed-off-by: Hongchao Zhang Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6455 Reviewed-on: http://review.whamcloud.com/14928 Reviewed-by: Andreas Dilger Reviewed-by: Mike Pershin Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/xattr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 3ae1a02a1966..ea3beccedc6b 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -126,6 +126,11 @@ ll_xattr_set_common(const struct xattr_handler *handler, strcmp(name, "selinux") == 0) return -EOPNOTSUPP; + /*FIXME: enable IMA when the conditions are ready */ + if (handler->flags == XATTR_SECURITY_T && + (!strcmp(name, "ima") || !strcmp(name, "evm"))) + return -EOPNOTSUPP; + sprintf(fullname, "%s%s\n", handler->prefix, name); rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), valid, fullname, pv, size, 0, flags, -- cgit v1.2.3 From c2242d14234a3f68d6ee326d155c8771dc2c6aa8 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Thu, 27 Oct 2016 18:11:53 -0400 Subject: staging: lustre: ldlm: reclaim granted locks defensively It was discovered that to many ldlm locks where being created on the server side to the point of memory exhaustion. The work of LU-6529 introduced watermarks to avoid this memory exhaustion. This is the client side part of this work for the upstream client. Signed-off-by: Niu Yawei Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6529 Reviewed-on: http://review.whamcloud.com/14931 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6929 Reviewed-on: http://review.whamcloud.com/15813 Reviewed-by: Andreas Dilger Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_hash.h | 2 +- drivers/staging/lustre/lnet/libcfs/hash.c | 24 ++++++++++++++++------ drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 4 ++-- drivers/staging/lustre/lustre/ldlm/ldlm_resource.c | 8 +++++--- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 15 +++++--------- 5 files changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h index 6949a1846635..f2b43996213f 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h @@ -705,7 +705,7 @@ void cfs_hash_for_each_safe(struct cfs_hash *hs, cfs_hash_for_each_cb_t, void *data); int cfs_hash_for_each_nolock(struct cfs_hash *hs, cfs_hash_for_each_cb_t, - void *data); + void *data, int start); int cfs_hash_for_each_empty(struct cfs_hash *hs, cfs_hash_for_each_cb_t, void *data); diff --git a/drivers/staging/lustre/lnet/libcfs/hash.c b/drivers/staging/lustre/lnet/libcfs/hash.c index 23283b6e09ab..997b8a5ed8ff 100644 --- a/drivers/staging/lustre/lnet/libcfs/hash.c +++ b/drivers/staging/lustre/lnet/libcfs/hash.c @@ -1552,7 +1552,7 @@ EXPORT_SYMBOL(cfs_hash_size_get); */ static int cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, - void *data) + void *data, int start) { struct hlist_node *hnode; struct hlist_node *tmp; @@ -1560,18 +1560,25 @@ cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, __u32 version; int count = 0; int stop_on_change; - int rc; + int end = -1; + int rc = 0; int i; stop_on_change = cfs_hash_with_rehash_key(hs) || !cfs_hash_with_no_itemref(hs) || !hs->hs_ops->hs_put_locked; cfs_hash_lock(hs, 0); +again: LASSERT(!cfs_hash_is_rehashing(hs)); cfs_hash_for_each_bucket(hs, &bd, i) { struct hlist_head *hhead; + if (i < start) + continue; + else if (end > 0 && i >= end) + break; + cfs_hash_bd_lock(hs, &bd, 0); version = cfs_hash_bd_version_get(&bd); @@ -1611,14 +1618,19 @@ cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, if (rc) /* callback wants to break iteration */ break; } - cfs_hash_unlock(hs, 0); + if (start > 0 && !rc) { + end = start; + start = 0; + goto again; + } + cfs_hash_unlock(hs, 0); return count; } int cfs_hash_for_each_nolock(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, - void *data) + void *data, int start) { if (cfs_hash_with_no_lock(hs) || cfs_hash_with_rehash_key(hs) || @@ -1630,7 +1642,7 @@ cfs_hash_for_each_nolock(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, return -EOPNOTSUPP; cfs_hash_for_each_enter(hs); - cfs_hash_for_each_relax(hs, func, data); + cfs_hash_for_each_relax(hs, func, data, start); cfs_hash_for_each_exit(hs); return 0; @@ -1662,7 +1674,7 @@ cfs_hash_for_each_empty(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, return -EOPNOTSUPP; cfs_hash_for_each_enter(hs); - while (cfs_hash_for_each_relax(hs, func, data)) { + while (cfs_hash_for_each_relax(hs, func, data, 0)) { CDEBUG(D_INFO, "Try to empty hash: %s, loop: %u\n", hs->hs_name, i++); } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index ac1927c54a0f..43856ff14365 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1729,7 +1729,7 @@ int ldlm_cli_cancel_unused(struct ldlm_namespace *ns, opaque); } else { cfs_hash_for_each_nolock(ns->ns_rs_hash, - ldlm_cli_hash_cancel_unused, &arg); + ldlm_cli_hash_cancel_unused, &arg, 0); return ELDLM_OK; } } @@ -1802,7 +1802,7 @@ static void ldlm_namespace_foreach(struct ldlm_namespace *ns, }; cfs_hash_for_each_nolock(ns->ns_rs_hash, - ldlm_res_iter_helper, &helper); + ldlm_res_iter_helper, &helper, 0); } /* non-blocking function to manipulate a lock whose cb_data is being put away. diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 07cb955600fb..c452400cf86a 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -855,8 +855,10 @@ int ldlm_namespace_cleanup(struct ldlm_namespace *ns, __u64 flags) return ELDLM_OK; } - cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_resource_clean, &flags); - cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_resource_complain, NULL); + cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_resource_clean, + &flags, 0); + cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_resource_complain, + NULL, 0); return ELDLM_OK; } EXPORT_SYMBOL(ldlm_namespace_cleanup); @@ -1352,7 +1354,7 @@ void ldlm_namespace_dump(int level, struct ldlm_namespace *ns) cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_res_hash_dump, - (void *)(unsigned long)level); + (void *)(unsigned long)level, 0); spin_lock(&ns->ns_lock); ns->ns_next_dump = cfs_time_shift(10); spin_unlock(&ns->ns_lock); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 5b3d0ba616a5..b9ca14005800 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -760,12 +760,6 @@ resend: if (IS_ERR(req)) return PTR_ERR(req); - if (req && it && it->it_op & IT_CREAT) - /* ask ptlrpc not to resend on EINPROGRESS since we have our own - * retry logic - */ - req->rq_no_retry_einprogress = 1; - if (resends) { req->rq_generation_set = 1; req->rq_import_generation = generation; @@ -823,11 +817,12 @@ resend: lockrep->lock_policy_res2 = ptlrpc_status_ntoh(lockrep->lock_policy_res2); - /* Retry the create infinitely when we get -EINPROGRESS from - * server. This is required by the new quota design. + /* + * Retry infinitely when the server returns -EINPROGRESS for the + * intent operation, when server returns -EINPROGRESS for acquiring + * intent lock, we'll retry in after_reply(). */ - if (it->it_op & IT_CREAT && - (int)lockrep->lock_policy_res2 == -EINPROGRESS) { + if (it->it_op && (int)lockrep->lock_policy_res2 == -EINPROGRESS) { mdc_clear_replay_flag(req, rc); ptlrpc_req_finished(req); resends++; -- cgit v1.2.3 From b44c295dba07da4b235a1bb9281e525b4fbb8263 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Thu, 27 Oct 2016 18:11:54 -0400 Subject: staging: lustre: recovery: don't skip open replay on reconnect Once reconnect happened during replay, we'd continue the open replay with the last failed replay, but not the next. Signed-off-by: Niu Yawei Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6802 Reviewed-on: http://review.whamcloud.com/15871 Reviewed-by: Jinshan Xiong Reviewed-by: Hongchao Zhang Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/recover.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c index aa9653498044..9144cd8deeaa 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/recover.c +++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c @@ -111,7 +111,9 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight) * all of it's requests being replayed, it's safe to * use a cursor to accelerate the search */ - imp->imp_replay_cursor = imp->imp_replay_cursor->next; + if (!imp->imp_resend_replay || + imp->imp_replay_cursor == &imp->imp_committed_list) + imp->imp_replay_cursor = imp->imp_replay_cursor->next; while (imp->imp_replay_cursor != &imp->imp_committed_list) { -- cgit v1.2.3 From f65053dff95e321639eb98c413dada31b457299d Mon Sep 17 00:00:00 2001 From: Hiroya Nozaki Date: Thu, 27 Oct 2016 18:11:55 -0400 Subject: staging: lustre: obdclass: race lustre_profile_list Running multiple mounts at the same time results in lustre_profile_list corruption when adding a new profile. This patch adds a new spin_lock to protect the list and avoid the bug Signed-off-by: Hiroya Nozaki Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6600 Reviewed-on: http://review.whamcloud.com/14896 Reviewed-by: Andreas Dilger Reviewed-by: Jian Yu Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd_class.h | 3 ++ drivers/staging/lustre/lustre/llite/llite_lib.c | 2 + .../staging/lustre/lustre/obdclass/obd_config.c | 57 +++++++++++++++++++--- 3 files changed, 54 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index aba96c33c95e..70b355e3b7ed 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -176,10 +176,13 @@ struct lustre_profile { char *lp_profile; char *lp_dt; char *lp_md; + int lp_refs; + bool lp_list_deleted; }; struct lustre_profile *class_get_profile(const char *prof); void class_del_profile(const char *prof); +void class_put_profile(struct lustre_profile *lprof); void class_del_profiles(void); #if LUSTRE_TRACKS_LOCK_EXP_REFS diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index b896ac1ba0f0..308da0660285 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -929,6 +929,8 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) out_free: kfree(md); kfree(dt); + if (lprof) + class_put_profile(lprof); if (err) ll_put_super(sb); else if (sbi->ll_flags & LL_SBI_VERBOSE) diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index bbed1b72d52e..017bdac55d11 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -585,16 +585,21 @@ static int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg) } static LIST_HEAD(lustre_profile_list); +static DEFINE_SPINLOCK(lustre_profile_list_lock); struct lustre_profile *class_get_profile(const char *prof) { struct lustre_profile *lprof; + spin_lock(&lustre_profile_list_lock); list_for_each_entry(lprof, &lustre_profile_list, lp_list) { if (!strcmp(lprof->lp_profile, prof)) { + lprof->lp_refs++; + spin_unlock(&lustre_profile_list_lock); return lprof; } } + spin_unlock(&lustre_profile_list_lock); return NULL; } EXPORT_SYMBOL(class_get_profile); @@ -639,7 +644,11 @@ static int class_add_profile(int proflen, char *prof, int osclen, char *osc, } } + spin_lock(&lustre_profile_list_lock); + lprof->lp_refs = 1; + lprof->lp_list_deleted = false; list_add(&lprof->lp_list, &lustre_profile_list); + spin_unlock(&lustre_profile_list_lock); return err; free_lp_dt: @@ -659,27 +668,59 @@ void class_del_profile(const char *prof) lprof = class_get_profile(prof); if (lprof) { + spin_lock(&lustre_profile_list_lock); + /* because get profile increments the ref counter */ + lprof->lp_refs--; list_del(&lprof->lp_list); - kfree(lprof->lp_profile); - kfree(lprof->lp_dt); - kfree(lprof->lp_md); - kfree(lprof); + lprof->lp_list_deleted = true; + spin_unlock(&lustre_profile_list_lock); + + class_put_profile(lprof); } } EXPORT_SYMBOL(class_del_profile); +void class_put_profile(struct lustre_profile *lprof) +{ + spin_lock(&lustre_profile_list_lock); + if (--lprof->lp_refs > 0) { + LASSERT(lprof->lp_refs > 0); + spin_unlock(&lustre_profile_list_lock); + return; + } + spin_unlock(&lustre_profile_list_lock); + + /* confirm not a negative number */ + LASSERT(!lprof->lp_refs); + + /* + * At least one class_del_profile/profiles must be called + * on the target profile or lustre_profile_list will corrupt + */ + LASSERT(lprof->lp_list_deleted); + kfree(lprof->lp_profile); + kfree(lprof->lp_dt); + kfree(lprof->lp_md); + kfree(lprof); +} +EXPORT_SYMBOL(class_put_profile); + /* COMPAT_146 */ void class_del_profiles(void) { struct lustre_profile *lprof, *n; + spin_lock(&lustre_profile_list_lock); list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) { list_del(&lprof->lp_list); - kfree(lprof->lp_profile); - kfree(lprof->lp_dt); - kfree(lprof->lp_md); - kfree(lprof); + lprof->lp_list_deleted = true; + spin_unlock(&lustre_profile_list_lock); + + class_put_profile(lprof); + + spin_lock(&lustre_profile_list_lock); } + spin_unlock(&lustre_profile_list_lock); } EXPORT_SYMBOL(class_del_profiles); -- cgit v1.2.3 From d8389249f1ce4fe96c465f45dee1c848d71c06bc Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Thu, 27 Oct 2016 18:11:57 -0400 Subject: staging: lustre: ptlrpc: do not sleep if encpool reached max capacity When encryption is enabled RPCs are encrypted just before being sent. The encryption requires allocating memory in the encoding pool. The current implementation in sptlrpc_enc_pool_get_pages() is deadlock-prone. Indeed, if there is no more free pages in the pool, all ptlrpcd threads can end up waiting in a queue, so there is no thread available to process other requests. It means client is not able to process replies from servers that yet contain last committed transno useful to release memory allocated by previous requests, including enc_pool pages. To fix this, in sptlrpc_enc_pool_get_pages(), do not make ptlrpcd threads wait in queue if encoding pool has already reached its maximum capacity. Instead, return -ENOMEM. If functions calling ptl_send_rpc() get -ENOMEM, then put back request in queue by moving it back to RQ_PHASE_NEW phase. As an optimization, do not call ptl_send_rpc() again for requests that already failed to allocate in the enc_pool, as long as there is not enough memory in the enc_pool to satisfy theirs needs. In /sys/fs/lustre/sptlrpc/encrypt_page_pools, add a new 'out of mem' stat to track how many requests fail to allocate memory in the enc_pool. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6356 Reviewed-on: http://review.whamcloud.com/15070 Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_sec.h | 2 ++ drivers/staging/lustre/lustre/ptlrpc/client.c | 25 +++++++++++++++++++ drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 9 ++++++- drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c | 29 +++++++++++++++++++--- 4 files changed, 60 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_sec.h b/drivers/staging/lustre/lustre/include/lustre_sec.h index 90c183424802..89658e0bd481 100644 --- a/drivers/staging/lustre/lustre/include/lustre_sec.h +++ b/drivers/staging/lustre/lustre/include/lustre_sec.h @@ -1029,6 +1029,8 @@ int sptlrpc_target_export_check(struct obd_export *exp, /* bulk security api */ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc); +int get_free_pages_in_pool(void); +int pool_is_at_full_capacity(void); int sptlrpc_cli_wrap_bulk(struct ptlrpc_request *req, struct ptlrpc_bulk_desc *desc); diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index bda925ed5294..cc4b129e1891 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1440,6 +1440,13 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) int rc; LASSERT(req->rq_phase == RQ_PHASE_NEW); + + /* do not try to go further if there is not enough memory in enc_pool */ + if (req->rq_sent && req->rq_bulk) + if (req->rq_bulk->bd_iov_count > get_free_pages_in_pool() && + pool_is_at_full_capacity()) + return -ENOMEM; + if (req->rq_sent && (req->rq_sent > ktime_get_real_seconds()) && (!req->rq_generation_set || req->rq_import_generation == imp->imp_generation)) @@ -1533,6 +1540,16 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) lustre_msg_get_opc(req->rq_reqmsg)); rc = ptl_send_rpc(req, 0); + if (rc == -ENOMEM) { + spin_lock(&imp->imp_lock); + if (!list_empty(&req->rq_list)) { + list_del_init(&req->rq_list); + atomic_dec(&req->rq_import->imp_inflight); + } + spin_unlock(&imp->imp_lock); + ptlrpc_rqphase_move(req, RQ_PHASE_NEW); + return rc; + } if (rc) { DEBUG_REQ(D_HA, req, "send failed (%d); expect timeout", rc); spin_lock(&req->rq_lock); @@ -1822,6 +1839,14 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) } rc = ptl_send_rpc(req, 0); + if (rc == -ENOMEM) { + spin_lock(&imp->imp_lock); + if (!list_empty(&req->rq_list)) + list_del_init(&req->rq_list); + spin_unlock(&imp->imp_lock); + ptlrpc_rqphase_move(req, RQ_PHASE_NEW); + continue; + } if (rc) { DEBUG_REQ(D_HA, req, "send failed: rc = %d", rc); diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index c2dd948de598..4e80ba935a51 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -536,8 +536,15 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) mpflag = cfs_memory_pressure_get_and_set(); rc = sptlrpc_cli_wrap_request(request); - if (rc) + if (rc) { + /* + * set rq_sent so that this request is treated + * as a delayed send in the upper layers + */ + if (rc == -ENOMEM) + request->rq_sent = ktime_get_seconds(); goto out; + } /* bulk register should be done after wrap_request() */ if (request->rq_bulk) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index ceb805d28f28..2fe9085e2034 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -108,6 +108,7 @@ static struct ptlrpc_enc_page_pool { unsigned long epp_st_lowfree; /* lowest free pages reached */ unsigned int epp_st_max_wqlen; /* highest waitqueue length */ unsigned long epp_st_max_wait; /* in jiffies */ + unsigned long epp_st_outofmem; /* # of out of mem requests */ /* * pointers to pools */ @@ -139,7 +140,8 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v) "cache missing: %lu\n" "low free mark: %lu\n" "max waitqueue depth: %u\n" - "max wait time: %ld/%lu\n", + "max wait time: %ld/%lu\n" + "out of mem: %lu\n", totalram_pages, PAGES_PER_POOL, page_pools.epp_max_pages, @@ -158,7 +160,8 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v) page_pools.epp_st_lowfree, page_pools.epp_st_max_wqlen, page_pools.epp_st_max_wait, - msecs_to_jiffies(MSEC_PER_SEC)); + msecs_to_jiffies(MSEC_PER_SEC), + page_pools.epp_st_outofmem); spin_unlock(&page_pools.epp_lock); @@ -306,6 +309,22 @@ static inline void enc_pools_wakeup(void) } } +/* + * Export the number of free pages in the pool + */ +int get_free_pages_in_pool(void) +{ + return page_pools.epp_free_pages; +} + +/* + * Let outside world know if enc_pool full capacity is reached + */ +int pool_is_at_full_capacity(void) +{ + return (page_pools.epp_total_pages == page_pools.epp_max_pages); +} + void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc) { int p_idx, g_idx; @@ -406,6 +425,7 @@ int sptlrpc_enc_pool_init(void) page_pools.epp_st_lowfree = 0; page_pools.epp_st_max_wqlen = 0; page_pools.epp_st_max_wait = 0; + page_pools.epp_st_outofmem = 0; enc_pools_alloc(); if (!page_pools.epp_pools) @@ -433,13 +453,14 @@ void sptlrpc_enc_pool_fini(void) if (page_pools.epp_st_access > 0) { CDEBUG(D_SEC, - "max pages %lu, grows %u, grow fails %u, shrinks %u, access %lu, missing %lu, max qlen %u, max wait %ld/%ld\n", + "max pages %lu, grows %u, grow fails %u, shrinks %u, access %lu, missing %lu, max qlen %u, max wait %ld/%ld, out of mem %lu\n", page_pools.epp_st_max_pages, page_pools.epp_st_grows, page_pools.epp_st_grow_fails, page_pools.epp_st_shrinks, page_pools.epp_st_access, page_pools.epp_st_missings, page_pools.epp_st_max_wqlen, page_pools.epp_st_max_wait, - msecs_to_jiffies(MSEC_PER_SEC)); + msecs_to_jiffies(MSEC_PER_SEC), + page_pools.epp_st_outofmem); } } -- cgit v1.2.3 From 4e724acca3af1fe377c0ce283d38fb107419a96d Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Thu, 27 Oct 2016 18:11:58 -0400 Subject: staging: lustre: ptlrpc: Forbid too early NRS policy tunings Wait for a NRS policy to be fully started before allowing to apply related tunings, so that all fields are properly initialized. Signed-off-by: Henri Doreau Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6673 Reviewed-on: http://review.whamcloud.com/15104 Reviewed-by: Emoly Liu Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/nrs.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c index d88faf61e740..f8566324f258 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c @@ -619,6 +619,15 @@ static int nrs_policy_ctl(struct ptlrpc_nrs *nrs, char *name, goto out; } + /** + * Wait for the policy to be fully started before attempting + * to operate it. + */ + if (policy->pol_state == NRS_POL_STATE_STARTING) { + rc = -EAGAIN; + goto out; + } + switch (opc) { /** * Unknown opcode, pass it down to the policy-specific control -- cgit v1.2.3 From 539ff1393293d8d1060f1ef856868253fa7ac458 Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Thu, 27 Oct 2016 18:11:59 -0400 Subject: staging: lustre: llite: Inform copytool of dataversion changes Notify copytool that a file could not be archived due to dataversion change. This does not introduce any functional change but ensures that errors are consistently reported in copytool logs. Signed-off-by: Henri Doreau Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5683 Reviewed-on: http://review.whamcloud.com/14377 Reviewed-by: Jinshan Xiong Reviewed-by: Robert Read Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 64a32d5dd116..ce05493bd768 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -837,10 +837,10 @@ static int ll_ioc_copy_end(struct super_block *sb, struct hsm_copy *copy) * when the file will not be modified for some tunable * time */ - /* we do not notify caller */ hpk.hpk_flags &= ~HP_FLAG_RETRY; + rc = -EBUSY; /* hpk_errval must be >= 0 */ - hpk.hpk_errval = EBUSY; + hpk.hpk_errval = -rc; } } -- cgit v1.2.3 From bbadab80d2cb1908705d32b1689fe5cb5a32faab Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Thu, 27 Oct 2016 18:12:00 -0400 Subject: staging: lustre: ptlrpc: do not switch out-of-date context When trying to replace a dead sec context with a new one, we must ensure the new context is already up-to-date. If it is not the case, just return from sptlrpc_req_replace_dead_ctx() and come later when the new context has been updated. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6536 Reviewed-on: http://review.whamcloud.com/15708 Reviewed-by: Mike Pershin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/sec.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index 12f02ed6a91d..e860df7c45a2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -515,6 +515,13 @@ static int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req) set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC)); + } else if (unlikely(!test_bit(PTLRPC_CTX_UPTODATE_BIT, &newctx->cc_flags))) { + /* + * new ctx not up to date yet + */ + CDEBUG(D_SEC, + "ctx (%p, fl %lx) doesn't switch, not up to date yet\n", + newctx, newctx->cc_flags); } else { /* * it's possible newctx == oldctx if we're switching -- cgit v1.2.3 From 5d01897eba2ac6985c362f9f1d8742c36405e56b Mon Sep 17 00:00:00 2001 From: Ben Evans Date: Thu, 27 Oct 2016 18:12:01 -0400 Subject: staging: lustre: headers: Create single .h for lu_seq_range Put lu_seq_range related functions into a single .h. Include directly from files which use it, and remove definitions from lustre_idl.h. Signed-off-by: Ben Evans Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6401 Reviewed-on: http://review.whamcloud.com/15952 Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fid/fid_request.c | 14 +- drivers/staging/lustre/lustre/fid/lproc_fid.c | 2 +- drivers/staging/lustre/lustre/fld/fld_cache.c | 6 +- .../lustre/lustre/include/lustre/lustre_idl.h | 108 ----------- drivers/staging/lustre/lustre/include/lustre_fid.h | 1 + drivers/staging/lustre/lustre/include/seq_range.h | 199 +++++++++++++++++++++ 6 files changed, 211 insertions(+), 119 deletions(-) create mode 100644 drivers/staging/lustre/lustre/include/seq_range.h (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c index edd72b926f81..1148b9ab5e11 100644 --- a/drivers/staging/lustre/lustre/fid/fid_request.c +++ b/drivers/staging/lustre/lustre/fid/fid_request.c @@ -74,7 +74,7 @@ static int seq_client_rpc(struct lu_client_seq *seq, /* Zero out input range, this is not recovery yet. */ in = req_capsule_client_get(&req->rq_pill, &RMF_SEQ_RANGE); - range_init(in); + lu_seq_range_init(in); ptlrpc_request_set_replen(req); @@ -123,14 +123,14 @@ static int seq_client_rpc(struct lu_client_seq *seq, out = req_capsule_server_get(&req->rq_pill, &RMF_SEQ_RANGE); *output = *out; - if (!range_is_sane(output)) { + if (!lu_seq_range_is_sane(output)) { CERROR("%s: Invalid range received from server: " DRANGE "\n", seq->lcs_name, PRANGE(output)); rc = -EINVAL; goto out_req; } - if (range_is_exhausted(output)) { + if (lu_seq_range_is_exhausted(output)) { CERROR("%s: Range received from server is exhausted: " DRANGE "]\n", seq->lcs_name, PRANGE(output)); rc = -EINVAL; @@ -170,9 +170,9 @@ static int seq_client_alloc_seq(const struct lu_env *env, { int rc; - LASSERT(range_is_sane(&seq->lcs_space)); + LASSERT(lu_seq_range_is_sane(&seq->lcs_space)); - if (range_is_exhausted(&seq->lcs_space)) { + if (lu_seq_range_is_exhausted(&seq->lcs_space)) { rc = seq_client_alloc_meta(env, seq); if (rc) { CERROR("%s: Can't allocate new meta-sequence, rc %d\n", @@ -185,7 +185,7 @@ static int seq_client_alloc_seq(const struct lu_env *env, rc = 0; } - LASSERT(!range_is_exhausted(&seq->lcs_space)); + LASSERT(!lu_seq_range_is_exhausted(&seq->lcs_space)); *seqnr = seq->lcs_space.lsr_start; seq->lcs_space.lsr_start += 1; @@ -320,7 +320,7 @@ void seq_client_flush(struct lu_client_seq *seq) seq->lcs_space.lsr_index = -1; - range_init(&seq->lcs_space); + lu_seq_range_init(&seq->lcs_space); mutex_unlock(&seq->lcs_mutex); } EXPORT_SYMBOL(seq_client_flush); diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c index 3ed32d77f38b..97d4849c7199 100644 --- a/drivers/staging/lustre/lustre/fid/lproc_fid.c +++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c @@ -83,7 +83,7 @@ ldebugfs_fid_write_common(const char __user *buffer, size_t count, (unsigned long long *)&tmp.lsr_end); if (rc != 2) return -EINVAL; - if (!range_is_sane(&tmp) || range_is_zero(&tmp) || + if (!lu_seq_range_is_sane(&tmp) || lu_seq_range_is_zero(&tmp) || tmp.lsr_start < range->lsr_start || tmp.lsr_end > range->lsr_end) return -EINVAL; *range = tmp; diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index 0100a935f4ff..11f697496180 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -143,7 +143,7 @@ restart_fixup: c_range = &f_curr->fce_range; n_range = &f_next->fce_range; - LASSERT(range_is_sane(c_range)); + LASSERT(lu_seq_range_is_sane(c_range)); if (&f_next->fce_list == head) break; @@ -358,7 +358,7 @@ struct fld_cache_entry { struct fld_cache_entry *f_new; - LASSERT(range_is_sane(range)); + LASSERT(lu_seq_range_is_sane(range)); f_new = kzalloc(sizeof(*f_new), GFP_NOFS); if (!f_new) @@ -503,7 +503,7 @@ int fld_cache_lookup(struct fld_cache *cache, } prev = flde; - if (range_within(&flde->fce_range, seq)) { + if (lu_seq_range_within(&flde->fce_range, seq)) { *range = flde->fce_range; cache->fci_stat.fst_cache++; diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index e542ce6c2b13..6896c3794e58 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -192,113 +192,6 @@ struct lu_seq_range_array { #define LU_SEQ_RANGE_MASK 0x3 -static inline unsigned fld_range_type(const struct lu_seq_range *range) -{ - return range->lsr_flags & LU_SEQ_RANGE_MASK; -} - -static inline bool fld_range_is_ost(const struct lu_seq_range *range) -{ - return fld_range_type(range) == LU_SEQ_RANGE_OST; -} - -static inline bool fld_range_is_mdt(const struct lu_seq_range *range) -{ - return fld_range_type(range) == LU_SEQ_RANGE_MDT; -} - -/** - * This all range is only being used when fld client sends fld query request, - * but it does not know whether the seq is MDT or OST, so it will send req - * with ALL type, which means either seq type gotten from lookup can be - * expected. - */ -static inline unsigned fld_range_is_any(const struct lu_seq_range *range) -{ - return fld_range_type(range) == LU_SEQ_RANGE_ANY; -} - -static inline void fld_range_set_type(struct lu_seq_range *range, - unsigned flags) -{ - range->lsr_flags |= flags; -} - -static inline void fld_range_set_mdt(struct lu_seq_range *range) -{ - fld_range_set_type(range, LU_SEQ_RANGE_MDT); -} - -static inline void fld_range_set_ost(struct lu_seq_range *range) -{ - fld_range_set_type(range, LU_SEQ_RANGE_OST); -} - -static inline void fld_range_set_any(struct lu_seq_range *range) -{ - fld_range_set_type(range, LU_SEQ_RANGE_ANY); -} - -/** - * returns width of given range \a r - */ - -static inline __u64 range_space(const struct lu_seq_range *range) -{ - return range->lsr_end - range->lsr_start; -} - -/** - * initialize range to zero - */ - -static inline void range_init(struct lu_seq_range *range) -{ - memset(range, 0, sizeof(*range)); -} - -/** - * check if given seq id \a s is within given range \a r - */ - -static inline bool range_within(const struct lu_seq_range *range, - __u64 s) -{ - return s >= range->lsr_start && s < range->lsr_end; -} - -static inline bool range_is_sane(const struct lu_seq_range *range) -{ - return (range->lsr_end >= range->lsr_start); -} - -static inline bool range_is_zero(const struct lu_seq_range *range) -{ - return (range->lsr_start == 0 && range->lsr_end == 0); -} - -static inline bool range_is_exhausted(const struct lu_seq_range *range) - -{ - return range_space(range) == 0; -} - -/* return 0 if two range have the same location */ -static inline int range_compare_loc(const struct lu_seq_range *r1, - const struct lu_seq_range *r2) -{ - return r1->lsr_index != r2->lsr_index || - r1->lsr_flags != r2->lsr_flags; -} - -#define DRANGE "[%#16.16Lx-%#16.16Lx):%x:%s" - -#define PRANGE(range) \ - (range)->lsr_start, \ - (range)->lsr_end, \ - (range)->lsr_index, \ - fld_range_is_mdt(range) ? "mdt" : "ost" - /** \defgroup lu_fid lu_fid * @{ */ @@ -848,7 +741,6 @@ static inline bool fid_is_sane(const struct lu_fid *fid) } void lustre_swab_lu_fid(struct lu_fid *fid); -void lustre_swab_lu_seq_range(struct lu_seq_range *range); static inline bool lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1) { diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 316780693193..b5a1aadbcb93 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -150,6 +150,7 @@ #include "../../include/linux/libcfs/libcfs.h" #include "lustre/lustre_idl.h" +#include "seq_range.h" struct lu_env; struct lu_site; diff --git a/drivers/staging/lustre/lustre/include/seq_range.h b/drivers/staging/lustre/lustre/include/seq_range.h new file mode 100644 index 000000000000..30c4dd66d5c4 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/seq_range.h @@ -0,0 +1,199 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2011, 2014, Intel Corporation. + * + * Copyright 2015 Cray Inc, all rights reserved. + * Author: Ben Evans. + * + * Define lu_seq_range associated functions + */ + +#ifndef _SEQ_RANGE_H_ +#define _SEQ_RANGE_H_ + +#include "lustre/lustre_idl.h" + +/** + * computes the sequence range type \a range + */ + +static inline unsigned int fld_range_type(const struct lu_seq_range *range) +{ + return range->lsr_flags & LU_SEQ_RANGE_MASK; +} + +/** + * Is this sequence range an OST? \a range + */ + +static inline bool fld_range_is_ost(const struct lu_seq_range *range) +{ + return fld_range_type(range) == LU_SEQ_RANGE_OST; +} + +/** + * Is this sequence range an MDT? \a range + */ + +static inline bool fld_range_is_mdt(const struct lu_seq_range *range) +{ + return fld_range_type(range) == LU_SEQ_RANGE_MDT; +} + +/** + * ANY range is only used when the fld client sends a fld query request, + * but it does not know whether the seq is an MDT or OST, so it will send the + * request with ANY type, which means any seq type from the lookup can be + * expected. /a range + */ +static inline unsigned int fld_range_is_any(const struct lu_seq_range *range) +{ + return fld_range_type(range) == LU_SEQ_RANGE_ANY; +} + +/** + * Apply flags to range \a range \a flags + */ + +static inline void fld_range_set_type(struct lu_seq_range *range, + unsigned int flags) +{ + range->lsr_flags |= flags; +} + +/** + * Add MDT to range type \a range + */ + +static inline void fld_range_set_mdt(struct lu_seq_range *range) +{ + fld_range_set_type(range, LU_SEQ_RANGE_MDT); +} + +/** + * Add OST to range type \a range + */ + +static inline void fld_range_set_ost(struct lu_seq_range *range) +{ + fld_range_set_type(range, LU_SEQ_RANGE_OST); +} + +/** + * Add ANY to range type \a range + */ + +static inline void fld_range_set_any(struct lu_seq_range *range) +{ + fld_range_set_type(range, LU_SEQ_RANGE_ANY); +} + +/** + * computes width of given sequence range \a range + */ + +static inline u64 lu_seq_range_space(const struct lu_seq_range *range) +{ + return range->lsr_end - range->lsr_start; +} + +/** + * initialize range to zero \a range + */ + +static inline void lu_seq_range_init(struct lu_seq_range *range) +{ + memset(range, 0, sizeof(*range)); +} + +/** + * check if given seq id \a s is within given range \a range + */ + +static inline bool lu_seq_range_within(const struct lu_seq_range *range, + u64 seq) +{ + return seq >= range->lsr_start && seq < range->lsr_end; +} + +/** + * Is the range sane? Is the end after the beginning? \a range + */ + +static inline bool lu_seq_range_is_sane(const struct lu_seq_range *range) +{ + return range->lsr_end >= range->lsr_start; +} + +/** + * Is the range 0? \a range + */ + +static inline bool lu_seq_range_is_zero(const struct lu_seq_range *range) +{ + return range->lsr_start == 0 && range->lsr_end == 0; +} + +/** + * Is the range out of space? \a range + */ + +static inline bool lu_seq_range_is_exhausted(const struct lu_seq_range *range) +{ + return lu_seq_range_space(range) == 0; +} + +/** + * return 0 if two ranges have the same location, nonzero if they are + * different \a r1 \a r2 + */ + +static inline int lu_seq_range_compare_loc(const struct lu_seq_range *r1, + const struct lu_seq_range *r2) +{ + return r1->lsr_index != r2->lsr_index || + r1->lsr_flags != r2->lsr_flags; +} + +#if !defined(__REQ_LAYOUT_USER__) +/** + * byte swap range structure \a range + */ + +void lustre_swab_lu_seq_range(struct lu_seq_range *range); +#endif +/** + * printf string and argument list for sequence range + */ +#define DRANGE "[%#16.16llx-%#16.16llx]:%x:%s" + +#define PRANGE(range) \ + (range)->lsr_start, \ + (range)->lsr_end, \ + (range)->lsr_index, \ + fld_range_is_mdt(range) ? "mdt" : "ost" + +#endif -- cgit v1.2.3 From f906a246bbbdbb9e46fdc308bae2d72df3328bff Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Thu, 27 Oct 2016 18:12:02 -0400 Subject: staging: lustre: ptlrpc: imp_peer_committed_transno should increase imp_peer_committed_transno should not decrease as this can confuse the users if imp_peer_committed_transno is used to check commit status. Signed-off-by: Alex Zhuravlev Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7079 Reviewed-on: http://review.whamcloud.com/16161 Reviewed-by: Mike Pershin Reviewed-by: wangdi Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index cc4b129e1891..7cbfb4c443ec 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1242,6 +1242,7 @@ static int after_reply(struct ptlrpc_request *req) int rc; struct timespec64 work_start; long timediff; + u64 committed; LASSERT(obd); /* repbuf must be unlinked */ @@ -1400,10 +1401,9 @@ static int after_reply(struct ptlrpc_request *req) } /* Replay-enabled imports return commit-status information. */ - if (lustre_msg_get_last_committed(req->rq_repmsg)) { - imp->imp_peer_committed_transno = - lustre_msg_get_last_committed(req->rq_repmsg); - } + committed = lustre_msg_get_last_committed(req->rq_repmsg); + if (likely(committed > imp->imp_peer_committed_transno)) + imp->imp_peer_committed_transno = committed; ptlrpc_free_committed(imp); -- cgit v1.2.3 From b5367061920a4b9da98817081cada6e13b598e72 Mon Sep 17 00:00:00 2001 From: wang di Date: Thu, 27 Oct 2016 18:12:03 -0400 Subject: staging: lustre: llog: record the minimum record size The minimum record size will be recorded in llh_size, which is only used by fixed size record llog now, and also add another flag LLOG_F_IS_FIXSIZE to indicate the fix size record llog. Signed-off-by: wang di Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7050 Reviewed-on: http://review.whamcloud.com/16103 Reviewed-by: Mike Pershin Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_idl.h | 7 +++++++ drivers/staging/lustre/lustre/obdclass/llog.c | 1 + 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 6896c3794e58..db09f3b000fc 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -3020,7 +3020,14 @@ enum llog_flag { LLOG_F_IS_CAT = 0x2, LLOG_F_IS_PLAIN = 0x4, LLOG_F_EXT_JOBID = BIT(3), + LLOG_F_IS_FIXSIZE = BIT(4), + /* + * Note: Flags covered by LLOG_F_EXT_MASK will be inherited from + * catlog to plain log, so do not add LLOG_F_IS_FIXSIZE here, + * because the catlog record is usually fixed size, but its plain + * log record can be variable + */ LLOG_F_EXT_MASK = LLOG_F_EXT_JOBID, }; diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index 5c9447ee2046..3bc178932366 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -193,6 +193,7 @@ int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, LASSERT(list_empty(&handle->u.chd.chd_head)); INIT_LIST_HEAD(&handle->u.chd.chd_head); llh->llh_size = sizeof(struct llog_logid_rec); + llh->llh_flags |= LLOG_F_IS_FIXSIZE; } else if (!(flags & LLOG_F_IS_PLAIN)) { CERROR("%s: unknown flags: %#x (expected %#x or %#x)\n", handle->lgh_ctxt->loc_obd->obd_name, -- cgit v1.2.3 From 25e3854c83e67914d7b642215cd02fd8976a9dcc Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Fri, 28 Oct 2016 14:46:20 +0200 Subject: staging: most: hdm-usb: add comment This patch adds a comment to function hdm_configure_channel() to clarify its execution paths. Signed-off-by: Christian Gromm Reported-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-usb/hdm_usb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 34336465c5fa..d6db0bd65be0 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -634,6 +634,15 @@ _error: * @iface: interface * @channel: channel ID * @conf: structure that holds the configuration information + * + * The attached network interface controller (NIC) supports a padding mode + * to avoid short packets on USB, hence increasing the performance due to a + * lower interrupt load. This mode is default for synchronous data and can + * be switched on for isochronous data. In case padding is active the + * driver needs to know the frame size of the payload in order to calculate + * the number of bytes it needs to pad when transmitting or to cut off when + * receiving data. + * */ static int hdm_configure_channel(struct most_interface *iface, int channel, struct most_channel_config *conf) @@ -667,6 +676,11 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, !(conf->data_type == MOST_CH_ISOC && conf->packets_per_xact != 0xFF)) { mdev->padding_active[channel] = false; + /* + * Since the NIC's padding mode is not going to be + * used, we can skip the frame size calculations and + * move directly on to exit. + */ goto exit; } -- cgit v1.2.3 From ce9daef8477e3a78b72c1b647023734ed8fe92a8 Mon Sep 17 00:00:00 2001 From: Fernando Apesteguia Date: Fri, 28 Oct 2016 18:16:13 +0200 Subject: staging: dgnc: Fix lines longer than 80 chars. Done by either unindenting some comments or converting them to multi line comments. This fixes some checkpatch warnings. Signed-off-by: Fernando Apesteguia Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_neo.h | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/dgnc_neo.h b/drivers/staging/dgnc/dgnc_neo.h index abddd48353d0..97f038644637 100644 --- a/drivers/staging/dgnc/dgnc_neo.h +++ b/drivers/staging/dgnc/dgnc_neo.h @@ -28,18 +28,20 @@ ************************************************************************/ struct neo_uart_struct { - u8 txrx; /* WR RHR/THR - Holding Reg */ + u8 txrx; /* WR RHR/THR - Holding Reg */ u8 ier; /* WR IER - Interrupt Enable Reg */ - u8 isr_fcr; /* WR ISR/FCR - Interrupt Status Reg/Fifo Control Reg */ + u8 isr_fcr; /* WR ISR/FCR - Interrupt Status Reg/Fifo + * Control Reg + */ u8 lcr; /* WR LCR - Line Control Reg */ u8 mcr; /* WR MCR - Modem Control Reg */ u8 lsr; /* WR LSR - Line Status Reg */ u8 msr; /* WR MSR - Modem Status Reg */ u8 spr; /* WR SPR - Scratch Pad Reg */ - u8 fctr; /* WR FCTR - Feature Control Reg */ + u8 fctr; /* WR FCTR - Feature Control Reg */ u8 efr; /* WR EFR - Enhanced Function Reg */ - u8 tfifo; /* WR TXCNT/TXTRG - Transmit FIFO Reg */ - u8 rfifo; /* WR RXCNT/RXTRG - Receive FIFO Reg */ + u8 tfifo; /* WR TXCNT/TXTRG - Transmit FIFO Reg */ + u8 rfifo; /* WR RXCNT/RXTRG - Receive FIFO Reg */ u8 xoffchar1; /* WR XOFF 1 - XOff Character 1 Reg */ u8 xoffchar2; /* WR XOFF 2 - XOff Character 2 Reg */ u8 xonchar1; /* WR XON 1 - Xon Character 1 Reg */ @@ -108,7 +110,9 @@ struct neo_uart_struct { /* 17158 Extended IIR's */ #define UART_17158_IIR_RDI_TIMEOUT 0x0C /* Receiver data TIMEOUT */ #define UART_17158_IIR_XONXOFF 0x10 /* Received an XON/XOFF char */ -#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20 /* CTS/DSR or RTS/DTR state change */ +#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20 /* CTS/DSR or RTS/DTR + * state change + */ #define UART_17158_IIR_FIFO_ENABLED 0xC0 /* 16550 FIFOs are Enabled */ /* @@ -119,8 +123,12 @@ struct neo_uart_struct { #define UART_17158_RXRDY_TIMEOUT 0x2 /* RX Ready Timeout */ #define UART_17158_TXRDY 0x3 /* TX Ready */ #define UART_17158_MSR 0x4 /* Modem State Change */ -#define UART_17158_TX_AND_FIFO_CLR 0x40 /* Transmitter Holding Reg Empty */ -#define UART_17158_RX_FIFO_DATA_ERROR 0x80 /* UART detected an RX FIFO Data error */ +#define UART_17158_TX_AND_FIFO_CLR 0x40 /* Transmitter Holding + * Reg Empty + */ +#define UART_17158_RX_FIFO_DATA_ERROR 0x80 /* UART detected an RX FIFO + * Data error + */ /* * These are the EXTENDED definitions for the 17C158's Interrupt @@ -132,8 +140,12 @@ struct neo_uart_struct { #define UART_17158_EFR_RTSDTR 0x40 /* Auto RTS/DTR Flow Control Enable */ #define UART_17158_EFR_CTSDSR 0x80 /* Auto CTS/DSR Flow COntrol Enable */ -#define UART_17158_XOFF_DETECT 0x1 /* Indicates whether chip saw an incoming XOFF char */ -#define UART_17158_XON_DETECT 0x2 /* Indicates whether chip saw an incoming XON char */ +#define UART_17158_XOFF_DETECT 0x1 /* Indicates whether chip saw an + * incoming XOFF char + */ +#define UART_17158_XON_DETECT 0x2 /* Indicates whether chip saw an + * incoming XON char + */ #define UART_17158_IER_RSVD1 0x10 /* Reserved by Exar */ #define UART_17158_IER_XOFF 0x20 /* Xoff Interrupt Enable */ -- cgit v1.2.3 From 7dd448f0986a9c2cf076ca0bea7c9be967e7fe07 Mon Sep 17 00:00:00 2001 From: Fernando Apesteguia Date: Fri, 28 Oct 2016 18:39:30 +0200 Subject: staging: dgnc: Fix multi-line comment alignment This fixes a checkpatch warning. Also, change the line above so it is aligned to the others in the same block. Signed-off-by: Fernando Apesteguia Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/digi.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h index 5b983e6f5ee2..4e365739423a 100644 --- a/drivers/staging/dgnc/digi.h +++ b/drivers/staging/dgnc/digi.h @@ -44,11 +44,11 @@ #define DIGI_SETA (('e' << 8) | 95) /* Set params */ #define DIGI_SETAW (('e' << 8) | 96) /* Drain & set params */ #define DIGI_SETAF (('e' << 8) | 97) /* Drain, flush & set params */ -#define DIGI_GET_NI_INFO (('d' << 8) | 250) /* Non-intelligent state info */ -#define DIGI_LOOPBACK (('d' << 8) | 252) /* - * Enable/disable UART - * internal loopback - */ +#define DIGI_GET_NI_INFO (('d' << 8) | 250) /* Non-intelligent state info */ +#define DIGI_LOOPBACK (('d' << 8) | 252) /* + * Enable/disable UART + * internal loopback + */ #define DIGI_FAST 0x0002 /* Fast baud rates */ #define RTSPACE 0x0004 /* RTS input flow control */ #define CTSPACE 0x0008 /* CTS output flow control */ -- cgit v1.2.3 From 15ed5398c94c8e29ee11022926351cb77cf70e7f Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Fri, 28 Oct 2016 22:29:21 -0200 Subject: staging: rtl8192e: Standardize test for NULL. The test for NULL of the return variable of functions was changed from (ret == NULL) to !ret to match the standard. Coccinelle was used with semantic patch: @@ expression e; identifier id, f; statement S; @@ f(...) { <+... id = \(kmalloc\|devm_kzalloc\|kmalloc_array\|devm_ioremap \|usb_alloc_urb\|alloc_netdev\|dev_alloc_skb\) (...) ... when any when != id = e + if (!id) - if (\(NULL == id\|id == NULL\)) S ...+> } Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c | 2 +- drivers/staging/rtl8192e/rtllib_rx.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c index f9003a28cae2..757ffd4f2f89 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c @@ -49,7 +49,7 @@ bool rtl92e_send_cmd_pkt(struct net_device *dev, u32 type, const void *data, else skb = dev_alloc_skb(frag_length + 4); - if (skb == NULL) { + if (!skb) { rt_status = false; goto Failed; } diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index d6777ecda64d..d67e3f3db76d 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -130,7 +130,7 @@ rtllib_frag_cache_get(struct rtllib_device *ieee, ETH_ALEN /* WDS */ + /* QOS Control */ (RTLLIB_QOS_HAS_SEQ(fc) ? 2 : 0)); - if (skb == NULL) + if (!skb) return NULL; entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]]; @@ -1430,7 +1430,7 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, /* skb: hdr + (possible reassembled) full plaintext payload */ payload = skb->data + hdrlen; rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC); - if (rxb == NULL) + if (!rxb) goto rx_dropped; /* to parse amsdu packets */ -- cgit v1.2.3 From 6e8cb1cf26ccf99582826d20032433b1c8d57774 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Fri, 28 Oct 2016 22:29:40 -0200 Subject: staging: rtl8192u: Standardize test for NULL. The test for NULL of the return variable of functions was changed from (ret == NULL) to !ret to match the standard. Coccinelle was used with semantic patch: @@ expression e; identifier id, f; statement S; @@ f(...) { <+... id = \(kmalloc\|devm_kzalloc\|kmalloc_array\|devm_ioremap \|usb_alloc_urb\|alloc_netdev\|dev_alloc_skb\) (...) ... when any when != id = e + if (!id) - if (\(NULL == id\|id == NULL\)) S ...+> } Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 2e4d2d7bc2e7..82f654305414 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -129,7 +129,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, 8 /* WEP */ + ETH_ALEN /* WDS */ + (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */); - if (skb == NULL) + if (!skb) return NULL; entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]]; -- cgit v1.2.3 From 9a3ca7240bc2d300cb6b9b977bbaf475648113da Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Fri, 28 Oct 2016 22:29:57 -0200 Subject: staging: rtl8188eu: Standardize test for NULL. The test for NULL of the return variable of functions was changed from (ret == NULL) to !ret to match the standard. Coccinelle was used with semantic patch: @@ expression e; identifier id, f; statement S; @@ f(...) { <+... id = \(kmalloc\|devm_kzalloc\|kmalloc_array\|devm_ioremap \|usb_alloc_urb\|alloc_netdev\|dev_alloc_skb\) (...) ... when any when != id = e + if (!id) - if (\(NULL == id\|id == NULL\)) S ...+> } Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 34198fe16ca5..e2dbe1b4afd3 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -252,7 +252,7 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i /* Acquire IO memory for vendorreq */ pIo_buf = kmalloc(MAX_USB_IO_CTL_SIZE, GFP_ATOMIC); - if (pIo_buf == NULL) { + if (!pIo_buf) { DBG_88E("[%s] pIo_buf == NULL\n", __func__); status = -ENOMEM; goto release_mutex; -- cgit v1.2.3 From 1fda5b7566561c8e1fc6fd572cbdc7ec32051b16 Mon Sep 17 00:00:00 2001 From: Victor Carvajal Date: Sat, 29 Oct 2016 21:40:38 -0700 Subject: Staging: rtl8188eu: Fix code indention found by checkpatch. ERROR: code indent should use tabs where possible +^I^I uint in_len, uint initial_out_len);$ Signed-off-by: Victor Carvajal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/rtw_mlme.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 9434b869c5e9..18fb7e7b2273 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -504,7 +504,7 @@ void rtw_scan_abort(struct adapter *adapter); int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len); int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len, uint initial_out_len); + uint in_len, uint initial_out_len); void rtw_init_registrypriv_dev_network(struct adapter *adapter); void rtw_update_registrypriv_dev_network(struct adapter *adapter); -- cgit v1.2.3 From cefc2fc61e1f5c80c6240634da01a4b846e9a6db Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Thu, 27 Oct 2016 22:22:28 -0200 Subject: staging: sm750fb: Refine code in set_current_gate(). The 'switch' statement in set_current_gate() had only two possible scenarios, so it was replaced with an 'if' statement to make the code shorter and easier to understand. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index c9ea464e2a78..6c15b1253240 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -74,26 +74,10 @@ void set_power_mode(unsigned int powerMode) void set_current_gate(unsigned int gate) { - unsigned int gate_reg; - unsigned int mode; - - /* Get current power mode. */ - mode = getPowerMode(); - - switch (mode) { - case POWER_MODE_CTRL_MODE_MODE0: - gate_reg = MODE0_GATE; - break; - - case POWER_MODE_CTRL_MODE_MODE1: - gate_reg = MODE1_GATE; - break; - - default: - gate_reg = MODE0_GATE; - break; - } - POKE32(gate_reg, gate); + if (getPowerMode() == POWER_MODE_CTRL_MODE_MODE1) + POKE32(MODE1_GATE, gate); + else + POKE32(MODE0_GATE, gate); } -- cgit v1.2.3 From 03140dabf584555e96440084d1ac426127bdf8c3 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Thu, 27 Oct 2016 22:23:35 -0200 Subject: staging: sm750fb: Replace functions CamelCase naming with underscores. Replace CamelCase function names with underscores to comply with the standard kernel coding style. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 4 ++-- drivers/staging/sm750fb/ddk750_display.c | 2 +- drivers/staging/sm750fb/ddk750_hwi2c.c | 4 ++-- drivers/staging/sm750fb/ddk750_power.c | 14 +++++++------- drivers/staging/sm750fb/ddk750_power.h | 10 +++++----- drivers/staging/sm750fb/ddk750_swi2c.c | 2 +- drivers/staging/sm750fb/sm750_hw.c | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index c8c14eeeb3c7..14b5112dfb03 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -261,7 +261,7 @@ int ddk750_init_hw(struct initchip_param *pInitParam) } if (pInitParam->setAllEngOff == 1) { - enable2DEngine(0); + enable_2d_engine(0); /* Disable Overlay, if a former application left it on */ reg = PEEK32(VIDEO_DISPLAY_CTRL); @@ -284,7 +284,7 @@ int ddk750_init_hw(struct initchip_param *pInitParam) POKE32(DMA_ABORT_INTERRUPT, reg); /* Disable DMA Power, if a former application left it on */ - enableDMA(0); + enable_dma(0); } /* We can add more initialization as needed. */ diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 0f3a875b0ef8..c347803f7e19 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -153,5 +153,5 @@ void ddk750_setLogicalDispOut(disp_output_t output) setDAC((output & DAC_MASK) >> DAC_OFFSET); if (output & DPMS_USAGE) - ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET); + ddk750_set_dpms((output & DPMS_MASK) >> DPMS_OFFSET); } diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index b60bedf6a854..10439e061ae8 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -24,7 +24,7 @@ unsigned char bus_speed_mode * Enable Hardware I2C power. * TODO: Check if we need to enable GPIO power? */ - enableI2C(1); + enable_i2c(1); /* Enable the I2C Controller and set the bus speed mode */ value = PEEK32(I2C_CTRL) & ~(I2C_CTRL_MODE | I2C_CTRL_EN); @@ -45,7 +45,7 @@ void sm750_hw_i2c_close(void) POKE32(I2C_CTRL, value); /* Disable I2C Power */ - enableI2C(0); + enable_i2c(0); /* Set GPIO 30 & 31 back as GPIO pins */ value = PEEK32(GPIO_MUX); diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 6c15b1253240..fda928032897 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -2,7 +2,7 @@ #include "ddk750_reg.h" #include "ddk750_power.h" -void ddk750_setDPMS(DPMS_t state) +void ddk750_set_dpms(DPMS_t state) { unsigned int value; @@ -17,7 +17,7 @@ void ddk750_setDPMS(DPMS_t state) } } -static unsigned int getPowerMode(void) +static unsigned int get_power_mode(void) { if (sm750_get_chip_type() == SM750LE) return 0; @@ -74,7 +74,7 @@ void set_power_mode(unsigned int powerMode) void set_current_gate(unsigned int gate) { - if (getPowerMode() == POWER_MODE_CTRL_MODE_MODE1) + if (get_power_mode() == POWER_MODE_CTRL_MODE_MODE1) POKE32(MODE1_GATE, gate); else POKE32(MODE0_GATE, gate); @@ -85,7 +85,7 @@ void set_current_gate(unsigned int gate) /* * This function enable/disable the 2D engine. */ -void enable2DEngine(unsigned int enable) +void enable_2d_engine(unsigned int enable) { u32 gate; @@ -98,7 +98,7 @@ void enable2DEngine(unsigned int enable) set_current_gate(gate); } -void enableDMA(unsigned int enable) +void enable_dma(unsigned int enable) { u32 gate; @@ -115,7 +115,7 @@ void enableDMA(unsigned int enable) /* * This function enable/disable the GPIO Engine */ -void enableGPIO(unsigned int enable) +void enable_gpio(unsigned int enable) { u32 gate; @@ -132,7 +132,7 @@ void enableGPIO(unsigned int enable) /* * This function enable/disable the I2C Engine */ -void enableI2C(unsigned int enable) +void enable_i2c(unsigned int enable) { u32 gate; diff --git a/drivers/staging/sm750fb/ddk750_power.h b/drivers/staging/sm750fb/ddk750_power.h index 7b24f1185989..ea56026d41b2 100644 --- a/drivers/staging/sm750fb/ddk750_power.h +++ b/drivers/staging/sm750fb/ddk750_power.h @@ -14,29 +14,29 @@ DPMS_t; (PEEK32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF) | (off)); \ } -void ddk750_setDPMS(DPMS_t); +void ddk750_set_dpms(DPMS_t); void set_power_mode(unsigned int powerMode); void set_current_gate(unsigned int gate); /* * This function enable/disable the 2D engine. */ -void enable2DEngine(unsigned int enable); +void enable_2d_engine(unsigned int enable); /* * This function enable/disable the DMA Engine */ -void enableDMA(unsigned int enable); +void enable_dma(unsigned int enable); /* * This function enable/disable the GPIO Engine */ -void enableGPIO(unsigned int enable); +void enable_gpio(unsigned int enable); /* * This function enable/disable the I2C Engine */ -void enableI2C(unsigned int enable); +void enable_i2c(unsigned int enable); #endif diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c index 7fce55df5fa6..e2e3ca64d483 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.c +++ b/drivers/staging/sm750fb/ddk750_swi2c.c @@ -428,7 +428,7 @@ long sm750_sw_i2c_init( PEEK32(sw_i2c_data_gpio_mux_reg) & ~(1 << sw_i2c_data_gpio)); /* Enable GPIO power */ - enableGPIO(1); + enable_gpio(1); /* Clear the i2c lines. */ for (i = 0; i < 9; i++) diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index d2da7a0ef5f0..23b6b1cda529 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -479,7 +479,7 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev) { u32 reg; - enable2DEngine(1); + enable_2d_engine(1); if (sm750_get_chip_type() == SM750LE) { reg = PEEK32(DE_STATE1); -- cgit v1.2.3 From c2b6028fd10617252c679b21b41204c531347a00 Mon Sep 17 00:00:00 2001 From: Elise Lennion Date: Thu, 27 Oct 2016 22:24:27 -0200 Subject: staging: sm750fb: Shorten local variables names. Shorter names are preferred by C variables naming convention, they are easier to write and aren't more difficult to understand. Signed-off-by: Elise Lennion Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index fda928032897..6f4374057405 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -29,26 +29,26 @@ static unsigned int get_power_mode(void) * SM50x can operate in one of three modes: 0, 1 or Sleep. * On hardware reset, power mode 0 is default. */ -void set_power_mode(unsigned int powerMode) +void set_power_mode(unsigned int mode) { - unsigned int control_value = 0; + unsigned int ctrl = 0; - control_value = PEEK32(POWER_MODE_CTRL) & ~POWER_MODE_CTRL_MODE_MASK; + ctrl = PEEK32(POWER_MODE_CTRL) & ~POWER_MODE_CTRL_MODE_MASK; if (sm750_get_chip_type() == SM750LE) return; - switch (powerMode) { + switch (mode) { case POWER_MODE_CTRL_MODE_MODE0: - control_value |= POWER_MODE_CTRL_MODE_MODE0; + ctrl |= POWER_MODE_CTRL_MODE_MODE0; break; case POWER_MODE_CTRL_MODE_MODE1: - control_value |= POWER_MODE_CTRL_MODE_MODE1; + ctrl |= POWER_MODE_CTRL_MODE_MODE1; break; case POWER_MODE_CTRL_MODE_SLEEP: - control_value |= POWER_MODE_CTRL_MODE_SLEEP; + ctrl |= POWER_MODE_CTRL_MODE_SLEEP; break; default: @@ -56,20 +56,20 @@ void set_power_mode(unsigned int powerMode) } /* Set up other fields in Power Control Register */ - if (powerMode == POWER_MODE_CTRL_MODE_SLEEP) { - control_value &= ~POWER_MODE_CTRL_OSC_INPUT; + if (mode == POWER_MODE_CTRL_MODE_SLEEP) { + ctrl &= ~POWER_MODE_CTRL_OSC_INPUT; #ifdef VALIDATION_CHIP - control_value &= ~POWER_MODE_CTRL_336CLK; + ctrl &= ~POWER_MODE_CTRL_336CLK; #endif } else { - control_value |= POWER_MODE_CTRL_OSC_INPUT; + ctrl |= POWER_MODE_CTRL_OSC_INPUT; #ifdef VALIDATION_CHIP - control_value |= POWER_MODE_CTRL_336CLK; + ctrl |= POWER_MODE_CTRL_336CLK; #endif } /* Program new power mode. */ - POKE32(POWER_MODE_CTRL, control_value); + POKE32(POWER_MODE_CTRL, ctrl); } void set_current_gate(unsigned int gate) -- cgit v1.2.3 From 5b0907407e7f28249ddb44ca0e629dda3d300169 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:46 +0200 Subject: mlxsw: core: Zero payload buffers for couple of registers We recently discovered a bug in the firmware in which a field's length in one of the registers was incorrectly set. This caused the firmware to access garbage data that wasn't initialized by the driver and therefore emit error messages. While the bug is already fixed and the driver usually zeros the buffers passed to the firmware, there are a handful of cases where this isn't done. Zero the buffer in these cases and prevent similar bugs from recurring, as they tend to be hard to debug. Fixes: 52581961d83d ("mlxsw: core: Implement fan control using hwmon") Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 4 ++-- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index 1ac8bf187168..ab710e37af99 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -262,7 +262,7 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) { - char mtcap_pl[MLXSW_REG_MTCAP_LEN]; + char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0}; char mtmp_pl[MLXSW_REG_MTMP_LEN]; u8 sensor_count; int i; @@ -295,7 +295,7 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) { - char mfcr_pl[MLXSW_REG_MFCR_LEN]; + char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0}; enum mlxsw_reg_mfcr_pwm_frequency freq; unsigned int type_index; unsigned int num; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index d652f7f030cb..2573faaffea8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -158,7 +158,7 @@ static void mlxsw_sp_txhdr_construct(struct sk_buff *skb, static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp) { - char spad_pl[MLXSW_REG_SPAD_LEN]; + char spad_pl[MLXSW_REG_SPAD_LEN] = {0}; int err; err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(spad), spad_pl); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 8c8f5d8a2113..8d11e5447067 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -890,7 +890,7 @@ static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = { static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx) { - char spad_pl[MLXSW_REG_SPAD_LEN]; + char spad_pl[MLXSW_REG_SPAD_LEN] = {0}; int err; err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(spad), spad_pl); -- cgit v1.2.3 From abc1de256c1987fe42eff80d95946ee9452bcac7 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 28 Oct 2016 21:35:47 +0200 Subject: mlxsw: switchx2: Check if port is usable before calling port create Do it in a same way we do it in spectrum. Check if port is usable first and only in that case create a port instance. Signed-off-by: Jiri Pirko Reviewed-by: Elad Raz Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 32 +++++++++----------------- 1 file changed, 11 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 8d11e5447067..67f1b70baa1d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -256,18 +256,17 @@ mlxsw_sx_port_system_port_mapping_set(struct mlxsw_sx_port *mlxsw_sx_port) return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sspr), sspr_pl); } -static int mlxsw_sx_port_module_check(struct mlxsw_sx_port *mlxsw_sx_port, - bool *p_usable) +static int mlxsw_sx_port_module_info_get(struct mlxsw_sx *mlxsw_sx, + u8 local_port, u8 *p_width) { - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; char pmlp_pl[MLXSW_REG_PMLP_LEN]; int err; - mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sx_port->local_port); + mlxsw_reg_pmlp_pack(pmlp_pl, local_port); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmlp), pmlp_pl); if (err) return err; - *p_usable = mlxsw_reg_pmlp_width_get(pmlp_pl) ? true : false; + *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); return 0; } @@ -962,7 +961,6 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) { struct mlxsw_sx_port *mlxsw_sx_port; struct net_device *dev; - bool usable; int err; dev = alloc_etherdev(sizeof(struct mlxsw_sx_port)); @@ -1005,19 +1003,6 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) */ dev->needed_headroom = MLXSW_TXHDR_LEN; - err = mlxsw_sx_port_module_check(mlxsw_sx_port, &usable); - if (err) { - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to check module\n", - mlxsw_sx_port->local_port); - goto err_port_module_check; - } - - if (!usable) { - dev_dbg(mlxsw_sx->bus_info->dev, "Port %d: Not usable, skipping initialization\n", - mlxsw_sx_port->local_port); - goto port_not_usable; - } - err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port); if (err) { dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n", @@ -1097,8 +1082,6 @@ err_port_speed_set: mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); err_port_swid_set: err_port_system_port_mapping_set: -port_not_usable: -err_port_module_check: err_dev_addr_get: free_percpu(mlxsw_sx_port->pcpu_stats); err_alloc_stats: @@ -1131,6 +1114,7 @@ static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) { size_t alloc_size; + u8 width; int i; int err; @@ -1140,6 +1124,11 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) return -ENOMEM; for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) { + err = mlxsw_sx_port_module_info_get(mlxsw_sx, i, &width); + if (err) + goto err_port_module_info_get; + if (!width) + continue; err = mlxsw_sx_port_create(mlxsw_sx, i); if (err) goto err_port_create; @@ -1147,6 +1136,7 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) return 0; err_port_create: +err_port_module_info_get: for (i--; i >= 1; i--) mlxsw_sx_port_remove(mlxsw_sx, i); kfree(mlxsw_sx->ports); -- cgit v1.2.3 From adc4e04a4bbd7696c9aa99eec951ddaf26ac27e1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 28 Oct 2016 21:35:48 +0200 Subject: mlxsw: switchx2: Move port used check outside port remove function Be symmentrical with create and do the check outside the remove function. Signed-off-by: Jiri Pirko Signed-off-by: Elad Raz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 67f1b70baa1d..6882e352a2cb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1093,21 +1093,26 @@ static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) { struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port]; - if (!mlxsw_sx_port) - return; mlxsw_core_port_fini(&mlxsw_sx_port->core_port); unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */ + mlxsw_sx->ports[local_port] = NULL; mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); free_percpu(mlxsw_sx_port->pcpu_stats); free_netdev(mlxsw_sx_port->dev); } +static bool mlxsw_sx_port_created(struct mlxsw_sx *mlxsw_sx, u8 local_port) +{ + return mlxsw_sx->ports[local_port] != NULL; +} + static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) { int i; for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) - mlxsw_sx_port_remove(mlxsw_sx, i); + if (mlxsw_sx_port_created(mlxsw_sx, i)) + mlxsw_sx_port_remove(mlxsw_sx, i); kfree(mlxsw_sx->ports); } @@ -1138,7 +1143,8 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) err_port_create: err_port_module_info_get: for (i--; i >= 1; i--) - mlxsw_sx_port_remove(mlxsw_sx, i); + if (mlxsw_sx_port_created(mlxsw_sx, i)) + mlxsw_sx_port_remove(mlxsw_sx, i); kfree(mlxsw_sx->ports); return err; } -- cgit v1.2.3 From f83e21027b4d8871d896f6e180171c289b60718c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 28 Oct 2016 21:35:49 +0200 Subject: mlxsw: spectrum: Move port used check outside port remove function Be symmentrical with create and do the check outside the remove function. Signed-off-by: Jiri Pirko Signed-off-by: Elad Raz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 2573faaffea8..d6490641dd3e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2403,8 +2403,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) { struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port]; - if (!mlxsw_sp_port) - return; cancel_delayed_work_sync(&mlxsw_sp_port->hw_stats.update_dw); mlxsw_core_port_fini(&mlxsw_sp_port->core_port); unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ @@ -2422,12 +2420,18 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) free_netdev(mlxsw_sp_port->dev); } +static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port) +{ + return mlxsw_sp->ports[local_port] != NULL; +} + static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp) { int i; for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) - mlxsw_sp_port_remove(mlxsw_sp, i); + if (mlxsw_sp_port_created(mlxsw_sp, i)) + mlxsw_sp_port_remove(mlxsw_sp, i); kfree(mlxsw_sp->ports); } @@ -2461,7 +2465,8 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) err_port_create: err_port_module_info_get: for (i--; i >= 1; i--) - mlxsw_sp_port_remove(mlxsw_sp, i); + if (mlxsw_sp_port_created(mlxsw_sp, i)) + mlxsw_sp_port_remove(mlxsw_sp, i); kfree(mlxsw_sp->ports); return err; } @@ -2503,7 +2508,8 @@ static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port, err_port_create: for (i--; i >= 0; i--) - mlxsw_sp_port_remove(mlxsw_sp, base_port + i); + if (mlxsw_sp_port_created(mlxsw_sp, base_port + i)) + mlxsw_sp_port_remove(mlxsw_sp, base_port + i); i = count; err_port_swid_set: for (i--; i >= 0; i--) @@ -2593,7 +2599,8 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, } for (i = 0; i < count; i++) - mlxsw_sp_port_remove(mlxsw_sp, base_port + i); + if (mlxsw_sp_port_created(mlxsw_sp, base_port + i)) + mlxsw_sp_port_remove(mlxsw_sp, base_port + i); err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, module, count); if (err) { @@ -2638,7 +2645,8 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port) base_port = base_port + 2; for (i = 0; i < count; i++) - mlxsw_sp_port_remove(mlxsw_sp, base_port + i); + if (mlxsw_sp_port_created(mlxsw_sp, base_port + i)) + mlxsw_sp_port_remove(mlxsw_sp, base_port + i); mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count); -- cgit v1.2.3 From e50e789ce178b6ae7c18b3e90884123398bab5f3 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:50 +0200 Subject: mlxsw: switchx2: Add support for physical port names Export to userspace the front panel name of the port, so that udev can rename the ports accordingly. The convention suggested by switchdev documentation is used: pX Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 32 ++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 6882e352a2cb..941393b000c8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -81,6 +81,9 @@ struct mlxsw_sx_port { struct mlxsw_sx_port_pcpu_stats __percpu *pcpu_stats; struct mlxsw_sx *mlxsw_sx; u8 local_port; + struct { + u8 module; + } mapping; }; /* tx_hdr_version @@ -257,7 +260,8 @@ mlxsw_sx_port_system_port_mapping_set(struct mlxsw_sx_port *mlxsw_sx_port) } static int mlxsw_sx_port_module_info_get(struct mlxsw_sx *mlxsw_sx, - u8 local_port, u8 *p_width) + u8 local_port, u8 *p_module, + u8 *p_width) { char pmlp_pl[MLXSW_REG_PMLP_LEN]; int err; @@ -266,6 +270,7 @@ static int mlxsw_sx_port_module_info_get(struct mlxsw_sx *mlxsw_sx, err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmlp), pmlp_pl); if (err) return err; + *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); return 0; } @@ -383,12 +388,26 @@ mlxsw_sx_port_get_stats64(struct net_device *dev, return stats; } +static int mlxsw_sx_port_get_phys_port_name(struct net_device *dev, char *name, + size_t len) +{ + struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); + int err; + + err = snprintf(name, len, "p%d", mlxsw_sx_port->mapping.module + 1); + if (err >= len) + return -EINVAL; + + return 0; +} + static const struct net_device_ops mlxsw_sx_port_netdev_ops = { .ndo_open = mlxsw_sx_port_open, .ndo_stop = mlxsw_sx_port_stop, .ndo_start_xmit = mlxsw_sx_port_xmit, .ndo_change_mtu = mlxsw_sx_port_change_mtu, .ndo_get_stats64 = mlxsw_sx_port_get_stats64, + .ndo_get_phys_port_name = mlxsw_sx_port_get_phys_port_name, }; static void mlxsw_sx_port_get_drvinfo(struct net_device *dev, @@ -957,7 +976,8 @@ mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port, return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spmlr), spmlr_pl); } -static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) +static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, + u8 module) { struct mlxsw_sx_port *mlxsw_sx_port; struct net_device *dev; @@ -971,6 +991,7 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) mlxsw_sx_port->dev = dev; mlxsw_sx_port->mlxsw_sx = mlxsw_sx; mlxsw_sx_port->local_port = local_port; + mlxsw_sx_port->mapping.module = module; mlxsw_sx_port->pcpu_stats = netdev_alloc_pcpu_stats(struct mlxsw_sx_port_pcpu_stats); @@ -1119,7 +1140,7 @@ static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) { size_t alloc_size; - u8 width; + u8 module, width; int i; int err; @@ -1129,12 +1150,13 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) return -ENOMEM; for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) { - err = mlxsw_sx_port_module_info_get(mlxsw_sx, i, &width); + err = mlxsw_sx_port_module_info_get(mlxsw_sx, i, &module, + &width); if (err) goto err_port_module_info_get; if (!width) continue; - err = mlxsw_sx_port_create(mlxsw_sx, i); + err = mlxsw_sx_port_create(mlxsw_sx, i, module); if (err) goto err_port_create; } -- cgit v1.2.3 From 10dbf8f8ec587ca0d23464af30a524cef216b1fa Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:51 +0200 Subject: mlxsw: switchx2: Fix port speed configuration In SwitchX-2 we configure the port speed to negotiate with 40G link only. Add support for all other supported speeds. Fixes: 31557f0f9755 ("mlxsw: Introduce Mellanox SwitchX-2 ASIC support") Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 30 ++++++++++++++++++++------ 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 941393b000c8..44dae8da4ef5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -662,6 +662,7 @@ static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = { }; #define MLXSW_SX_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sx_port_link_mode) +#define MLXSW_SX_PORT_BASE_SPEED 10000 /* Mb/s */ static u32 mlxsw_sx_from_ptys_supported_port(u32 ptys_eth_proto) { @@ -809,6 +810,18 @@ static u32 mlxsw_sx_to_ptys_speed(u32 speed) return ptys_proto; } +static u32 mlxsw_sx_to_ptys_upper_speed(u32 upper_speed) +{ + u32 ptys_proto = 0; + int i; + + for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) { + if (mlxsw_sx_port_link_mode[i].speed <= upper_speed) + ptys_proto |= mlxsw_sx_port_link_mode[i].mask; + } + return ptys_proto; +} + static int mlxsw_sx_port_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { @@ -955,13 +968,17 @@ static int mlxsw_sx_port_stp_state_set(struct mlxsw_sx_port *mlxsw_sx_port, return err; } -static int mlxsw_sx_port_speed_set(struct mlxsw_sx_port *mlxsw_sx_port, - u32 speed) +static int +mlxsw_sx_port_speed_by_width_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 width) { struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; + u32 upper_speed = MLXSW_SX_PORT_BASE_SPEED * width; char ptys_pl[MLXSW_REG_PTYS_LEN]; + u32 eth_proto_admin; - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, speed); + eth_proto_admin = mlxsw_sx_to_ptys_upper_speed(upper_speed); + mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, + eth_proto_admin); return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); } @@ -977,7 +994,7 @@ mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port, } static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, - u8 module) + u8 module, u8 width) { struct mlxsw_sx_port *mlxsw_sx_port; struct net_device *dev; @@ -1038,8 +1055,7 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, goto err_port_swid_set; } - err = mlxsw_sx_port_speed_set(mlxsw_sx_port, - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4); + err = mlxsw_sx_port_speed_by_width_set(mlxsw_sx_port, width); if (err) { dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n", mlxsw_sx_port->local_port); @@ -1156,7 +1172,7 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) goto err_port_module_info_get; if (!width) continue; - err = mlxsw_sx_port_create(mlxsw_sx, i, module); + err = mlxsw_sx_port_create(mlxsw_sx, i, module, width); if (err) goto err_port_create; } -- cgit v1.2.3 From 401c8b4e3cc537b31afee3e130ae37a9c49b47c2 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:52 +0200 Subject: mlxsw: reg: Add eth prefix to PTYS pack and unpack We want to add Infiniband support to PTYS. In order to maintain proper conventions, we will change pack and unpack prefix to eth. Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 11 ++++++----- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 17 +++++++++-------- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 18 ++++++++++-------- 3 files changed, 25 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index debcf2648398..3ecf3486de11 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2131,8 +2131,8 @@ MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32); */ MLXSW_ITEM32(reg, ptys, eth_proto_lp_advertise, 0x30, 0, 32); -static inline void mlxsw_reg_ptys_pack(char *payload, u8 local_port, - u32 proto_admin) +static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port, + u32 proto_admin) { MLXSW_REG_ZERO(ptys, payload); mlxsw_reg_ptys_local_port_set(payload, local_port); @@ -2140,9 +2140,10 @@ static inline void mlxsw_reg_ptys_pack(char *payload, u8 local_port, mlxsw_reg_ptys_eth_proto_admin_set(payload, proto_admin); } -static inline void mlxsw_reg_ptys_unpack(char *payload, u32 *p_eth_proto_cap, - u32 *p_eth_proto_adm, - u32 *p_eth_proto_oper) +static inline void mlxsw_reg_ptys_eth_unpack(char *payload, + u32 *p_eth_proto_cap, + u32 *p_eth_proto_adm, + u32 *p_eth_proto_oper) { if (p_eth_proto_cap) *p_eth_proto_cap = mlxsw_reg_ptys_eth_proto_cap_get(payload); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index d6490641dd3e..d1c2f9f173eb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2003,12 +2003,12 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, int err; autoneg = mlxsw_sp_port->link.autoneg; - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0); + mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); if (err) return err; - mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, ð_proto_admin, - ð_proto_oper); + mlxsw_reg_ptys_eth_unpack(ptys_pl, ð_proto_cap, ð_proto_admin, + ð_proto_oper); mlxsw_sp_port_get_link_supported(eth_proto_cap, cmd); @@ -2037,11 +2037,11 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev, bool autoneg; int err; - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0); + mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); if (err) return err; - mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, NULL, NULL); + mlxsw_reg_ptys_eth_unpack(ptys_pl, ð_proto_cap, NULL, NULL); autoneg = cmd->base.autoneg == AUTONEG_ENABLE; eth_proto_new = autoneg ? @@ -2054,7 +2054,8 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev, return -EINVAL; } - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, eth_proto_new); + mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, + eth_proto_new); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); if (err) return err; @@ -2092,8 +2093,8 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width) u32 eth_proto_admin; eth_proto_admin = mlxsw_sp_to_ptys_upper_speed(upper_speed); - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, - eth_proto_admin); + mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, + eth_proto_admin); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 44dae8da4ef5..7b74dcb2e4fb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -762,14 +762,14 @@ static int mlxsw_sx_port_get_settings(struct net_device *dev, u32 eth_proto_oper; int err; - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, 0); + mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); if (err) { netdev_err(dev, "Failed to get proto"); return err; } - mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, - ð_proto_admin, ð_proto_oper); + mlxsw_reg_ptys_eth_unpack(ptys_pl, ð_proto_cap, + ð_proto_admin, ð_proto_oper); cmd->supported = mlxsw_sx_from_ptys_supported_port(eth_proto_cap) | mlxsw_sx_from_ptys_supported_link(eth_proto_cap) | @@ -841,13 +841,14 @@ static int mlxsw_sx_port_set_settings(struct net_device *dev, mlxsw_sx_to_ptys_advert_link(cmd->advertising) : mlxsw_sx_to_ptys_speed(speed); - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, 0); + mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); if (err) { netdev_err(dev, "Failed to get proto"); return err; } - mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, ð_proto_admin, NULL); + mlxsw_reg_ptys_eth_unpack(ptys_pl, ð_proto_cap, ð_proto_admin, + NULL); eth_proto_new = eth_proto_new & eth_proto_cap; if (!eth_proto_new) { @@ -857,7 +858,8 @@ static int mlxsw_sx_port_set_settings(struct net_device *dev, if (eth_proto_new == eth_proto_admin) return 0; - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, eth_proto_new); + mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, + eth_proto_new); err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); if (err) { netdev_err(dev, "Failed to set proto admin"); @@ -977,8 +979,8 @@ mlxsw_sx_port_speed_by_width_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 width) u32 eth_proto_admin; eth_proto_admin = mlxsw_sx_to_ptys_upper_speed(upper_speed); - mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, - eth_proto_admin); + mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, + eth_proto_admin); return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); } -- cgit v1.2.3 From 794177027b200a2b9b29aa153fe2ae8bd5610c21 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:53 +0200 Subject: mlxsw: reg: Add Infiniband support to PTYS In order to support Infiniband fabric, we need to introduce IB speeds and capabilities to PTYS emads. Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 3ecf3486de11..2f31af04d259 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2054,6 +2054,7 @@ MLXSW_REG_DEFINE(ptys, MLXSW_REG_PTYS_ID, MLXSW_REG_PTYS_LEN); */ MLXSW_ITEM32(reg, ptys, local_port, 0x00, 16, 8); +#define MLXSW_REG_PTYS_PROTO_MASK_IB BIT(0) #define MLXSW_REG_PTYS_PROTO_MASK_ETH BIT(2) /* reg_ptys_proto_mask @@ -2112,18 +2113,61 @@ MLXSW_ITEM32(reg, ptys, an_status, 0x04, 28, 4); */ MLXSW_ITEM32(reg, ptys, eth_proto_cap, 0x0C, 0, 32); +/* reg_ptys_ib_link_width_cap + * IB port supported widths. + * Access: RO + */ +MLXSW_ITEM32(reg, ptys, ib_link_width_cap, 0x10, 16, 16); + +#define MLXSW_REG_PTYS_IB_SPEED_SDR BIT(0) +#define MLXSW_REG_PTYS_IB_SPEED_DDR BIT(1) +#define MLXSW_REG_PTYS_IB_SPEED_QDR BIT(2) +#define MLXSW_REG_PTYS_IB_SPEED_FDR10 BIT(3) +#define MLXSW_REG_PTYS_IB_SPEED_FDR BIT(4) +#define MLXSW_REG_PTYS_IB_SPEED_EDR BIT(5) + +/* reg_ptys_ib_proto_cap + * IB port supported speeds and protocols. + * Access: RO + */ +MLXSW_ITEM32(reg, ptys, ib_proto_cap, 0x10, 0, 16); + /* reg_ptys_eth_proto_admin * Speed and protocol to set port to. * Access: RW */ MLXSW_ITEM32(reg, ptys, eth_proto_admin, 0x18, 0, 32); +/* reg_ptys_ib_link_width_admin + * IB width to set port to. + * Access: RW + */ +MLXSW_ITEM32(reg, ptys, ib_link_width_admin, 0x1C, 16, 16); + +/* reg_ptys_ib_proto_admin + * IB speeds and protocols to set port to. + * Access: RW + */ +MLXSW_ITEM32(reg, ptys, ib_proto_admin, 0x1C, 0, 16); + /* reg_ptys_eth_proto_oper * The current speed and protocol configured for the port. * Access: RO */ MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32); +/* reg_ptys_ib_link_width_oper + * The current IB width to set port to. + * Access: RO + */ +MLXSW_ITEM32(reg, ptys, ib_link_width_oper, 0x28, 16, 16); + +/* reg_ptys_ib_proto_oper + * The current IB speed and protocol. + * Access: RO + */ +MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16); + /* reg_ptys_eth_proto_lp_advertise * The protocols that were advertised by the link partner during * autonegotiation. @@ -2153,6 +2197,33 @@ static inline void mlxsw_reg_ptys_eth_unpack(char *payload, *p_eth_proto_oper = mlxsw_reg_ptys_eth_proto_oper_get(payload); } +static inline void mlxsw_reg_ptys_ib_pack(char *payload, u8 local_port, + u16 proto_admin, u16 link_width) +{ + MLXSW_REG_ZERO(ptys, payload); + mlxsw_reg_ptys_local_port_set(payload, local_port); + mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_IB); + mlxsw_reg_ptys_ib_proto_admin_set(payload, proto_admin); + mlxsw_reg_ptys_ib_link_width_admin_set(payload, link_width); +} + +static inline void mlxsw_reg_ptys_ib_unpack(char *payload, u16 *p_ib_proto_cap, + u16 *p_ib_link_width_cap, + u16 *p_ib_proto_oper, + u16 *p_ib_link_width_oper) +{ + if (p_ib_proto_cap) + *p_ib_proto_cap = mlxsw_reg_ptys_ib_proto_cap_get(payload); + if (p_ib_link_width_cap) + *p_ib_link_width_cap = + mlxsw_reg_ptys_ib_link_width_cap_get(payload); + if (p_ib_proto_oper) + *p_ib_proto_oper = mlxsw_reg_ptys_ib_proto_oper_get(payload); + if (p_ib_link_width_oper) + *p_ib_link_width_oper = + mlxsw_reg_ptys_ib_link_width_oper_get(payload); +} + /* PPAD - Port Physical Address Register * ------------------------------------- * The PPAD register configures the per port physical MAC address. -- cgit v1.2.3 From 7136793e4a44651b273a457e31f00a51751dd123 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:54 +0200 Subject: mlxsw: reg: Add local-port to Infiniband port mapping In order to change a port type to Infiniband port we should change his mapping from local-port to Infiniband. Adding the PLIB (Port Local to InfiniBand) allows this mapping. Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 2f31af04d259..a61ce34ac6d0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2748,6 +2748,27 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port, mlxsw_reg_ppcnt_prio_tc_set(payload, prio_tc); } +/* PLIB - Port Local to InfiniBand Port + * ------------------------------------ + * The PLIB register performs mapping from Local Port into InfiniBand Port. + */ +#define MLXSW_REG_PLIB_ID 0x500A +#define MLXSW_REG_PLIB_LEN 0x10 + +MLXSW_REG_DEFINE(plib, MLXSW_REG_PLIB_ID, MLXSW_REG_PLIB_LEN); + +/* reg_plib_local_port + * Local port number. + * Access: Index + */ +MLXSW_ITEM32(reg, plib, local_port, 0x00, 16, 8); + +/* reg_plib_ib_port + * InfiniBand port remapping for local_port. + * Access: RW + */ +MLXSW_ITEM32(reg, plib, ib_port, 0x00, 0, 8); + /* PPTB - Port Prio To Buffer Register * ----------------------------------- * Configures the switch priority to buffer table. @@ -5188,6 +5209,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(paos), MLXSW_REG(pfcc), MLXSW_REG(ppcnt), + MLXSW_REG(plib), MLXSW_REG(pptb), MLXSW_REG(pbmc), MLXSW_REG(pspa), -- cgit v1.2.3 From 67963a33b4fde8f77b046f80daf83afc6e126991 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 28 Oct 2016 21:35:55 +0200 Subject: mlxsw: Make devlink port instances independent of spectrum/switchx2 port instances Currently, devlink register/unregister is done directly from spectrum/switchx2 port create/remove functions. With a need to introduce a port type change, the devlink port instances have to be persistent across type changes, therefore across port create/remove function calls. So do a bit of reshuffling to achieve that. Signed-off-by: Jiri Pirko Signed-off-by: Elad Raz Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 82 +++++++++++++++++++++----- drivers/net/ethernet/mellanox/mlxsw/core.h | 26 +++----- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 53 +++++++++++------ drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 1 - drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 49 ++++++++++----- 5 files changed, 147 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 02183f6a8b93..b50acb1a7260 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -90,6 +90,22 @@ struct mlxsw_core_pcpu_stats { u32 port_rx_invalid; }; +struct mlxsw_core_port { + struct devlink_port devlink_port; + void *port_driver_priv; +}; + +void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port) +{ + return mlxsw_core_port->port_driver_priv; +} +EXPORT_SYMBOL(mlxsw_core_port_driver_priv); + +static bool mlxsw_core_port_check(struct mlxsw_core_port *mlxsw_core_port) +{ + return mlxsw_core_port->port_driver_priv != NULL; +} + struct mlxsw_core { struct mlxsw_driver *driver; const struct mlxsw_bus *bus; @@ -114,6 +130,7 @@ struct mlxsw_core { } lag; struct mlxsw_res res; struct mlxsw_hwmon *hwmon; + struct mlxsw_core_port ports[MLXSW_PORT_MAX_PORTS]; unsigned long driver_priv[0]; /* driver_priv has to be always the last item */ }; @@ -928,7 +945,8 @@ static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port, struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); - if (!mlxsw_driver->sb_port_pool_get) + if (!mlxsw_driver->sb_port_pool_get || + !mlxsw_core_port_check(mlxsw_core_port)) return -EOPNOTSUPP; return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index, pool_index, p_threshold); @@ -942,7 +960,8 @@ static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port, struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); - if (!mlxsw_driver->sb_port_pool_set) + if (!mlxsw_driver->sb_port_pool_set || + !mlxsw_core_port_check(mlxsw_core_port)) return -EOPNOTSUPP; return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index, pool_index, threshold); @@ -958,7 +977,8 @@ mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port, struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); - if (!mlxsw_driver->sb_tc_pool_bind_get) + if (!mlxsw_driver->sb_tc_pool_bind_get || + !mlxsw_core_port_check(mlxsw_core_port)) return -EOPNOTSUPP; return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index, tc_index, pool_type, @@ -975,7 +995,8 @@ mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); - if (!mlxsw_driver->sb_tc_pool_bind_set) + if (!mlxsw_driver->sb_tc_pool_bind_set || + !mlxsw_core_port_check(mlxsw_core_port)) return -EOPNOTSUPP; return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index, tc_index, pool_type, @@ -1013,7 +1034,8 @@ mlxsw_devlink_sb_occ_port_pool_get(struct devlink_port *devlink_port, struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); - if (!mlxsw_driver->sb_occ_port_pool_get) + if (!mlxsw_driver->sb_occ_port_pool_get || + !mlxsw_core_port_check(mlxsw_core_port)) return -EOPNOTSUPP; return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index, pool_index, p_cur, p_max); @@ -1029,7 +1051,8 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port, struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); - if (!mlxsw_driver->sb_occ_tc_port_bind_get) + if (!mlxsw_driver->sb_occ_tc_port_bind_get || + !mlxsw_core_port_check(mlxsw_core_port)) return -EOPNOTSUPP; return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port, sb_index, tc_index, @@ -1656,28 +1679,59 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_core_res_get); -int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, - struct mlxsw_core_port *mlxsw_core_port, u8 local_port, - struct net_device *dev, bool split, u32 split_group) +int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port) { struct devlink *devlink = priv_to_devlink(mlxsw_core); + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; + int err; - if (split) - devlink_port_split_set(devlink_port, split_group); - devlink_port_type_eth_set(devlink_port, dev); - return devlink_port_register(devlink, devlink_port, local_port); + err = devlink_port_register(devlink, devlink_port, local_port); + if (err) + memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); + return err; } EXPORT_SYMBOL(mlxsw_core_port_init); -void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port) +void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) { + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; devlink_port_unregister(devlink_port); + memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); } EXPORT_SYMBOL(mlxsw_core_port_fini); +void mlxsw_core_port_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv, struct net_device *dev, + bool split, u32 split_group) +{ + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; + struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; + + mlxsw_core_port->port_driver_priv = port_driver_priv; + if (split) + devlink_port_split_set(devlink_port, split_group); + devlink_port_type_eth_set(devlink_port, dev); +} +EXPORT_SYMBOL(mlxsw_core_port_set); + +void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv) +{ + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; + struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; + + mlxsw_core_port->port_driver_priv = port_driver_priv; + devlink_port_type_clear(devlink_port); +} +EXPORT_SYMBOL(mlxsw_core_port_clear); + static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, const char *buf, size_t size) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 0cf721cee7fb..f4bbbd485d87 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -52,6 +52,7 @@ #include "resources.h" struct mlxsw_core; +struct mlxsw_core_port; struct mlxsw_driver; struct mlxsw_bus; struct mlxsw_bus_info; @@ -141,23 +142,14 @@ u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core, void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, u16 lag_id, u8 local_port); -struct mlxsw_core_port { - struct devlink_port devlink_port; -}; - -static inline void * -mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port) -{ - /* mlxsw_core_port is ensured to always be the first field in driver - * port structure. - */ - return mlxsw_core_port; -} - -int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, - struct mlxsw_core_port *mlxsw_core_port, u8 local_port, - struct net_device *dev, bool split, u32 split_group); -void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port); +void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port); +int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port); +void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port); +void mlxsw_core_port_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv, struct net_device *dev, + bool split, u32 split_group); +void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv); int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index d1c2f9f173eb..ad4ff278ccee 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2212,8 +2212,8 @@ static int mlxsw_sp_port_pvid_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_port) return mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1); } -static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, - bool split, u8 module, u8 width, u8 lane) +static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, + bool split, u8 module, u8 width, u8 lane) { struct mlxsw_sp_port *mlxsw_sp_port; struct net_device *dev; @@ -2358,20 +2358,11 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, goto err_register_netdev; } - err = mlxsw_core_port_init(mlxsw_sp->core, &mlxsw_sp_port->core_port, - mlxsw_sp_port->local_port, dev, - mlxsw_sp_port->split, module); - if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n", - mlxsw_sp_port->local_port); - goto err_core_port_init; - } - + mlxsw_core_port_set(mlxsw_sp->core, mlxsw_sp_port->local_port, + mlxsw_sp_port, dev, mlxsw_sp_port->split, module); mlxsw_core_schedule_dw(&mlxsw_sp_port->hw_stats.update_dw, 0); return 0; -err_core_port_init: - unregister_netdev(dev); err_register_netdev: mlxsw_sp->ports[local_port] = NULL; mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); @@ -2400,12 +2391,34 @@ err_port_active_vlans_alloc: return err; } -static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) +static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, + bool split, u8 module, u8 width, u8 lane) +{ + int err; + + err = mlxsw_core_port_init(mlxsw_sp->core, local_port); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n", + local_port); + return err; + } + err = __mlxsw_sp_port_create(mlxsw_sp, local_port, false, + module, width, lane); + if (err) + goto err_port_create; + return 0; + +err_port_create: + mlxsw_core_port_fini(mlxsw_sp->core, local_port); + return err; +} + +static void __mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) { struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port]; cancel_delayed_work_sync(&mlxsw_sp_port->hw_stats.update_dw); - mlxsw_core_port_fini(&mlxsw_sp_port->core_port); + mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp); unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ mlxsw_sp->ports[local_port] = NULL; mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); @@ -2421,6 +2434,12 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) free_netdev(mlxsw_sp_port->dev); } +static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) +{ + __mlxsw_sp_port_remove(mlxsw_sp, local_port); + mlxsw_core_port_fini(mlxsw_sp->core, local_port); +} + static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port) { return mlxsw_sp->ports[local_port] != NULL; @@ -2456,8 +2475,8 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) if (!width) continue; mlxsw_sp->port_to_module[i] = module; - err = mlxsw_sp_port_create(mlxsw_sp, i, false, module, width, - lane); + err = mlxsw_sp_port_create(mlxsw_sp, i, false, + module, width, lane); if (err) goto err_port_create; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index cc5462556a83..04a2bc7043bc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -316,7 +316,6 @@ struct mlxsw_sp_port_pcpu_stats { }; struct mlxsw_sp_port { - struct mlxsw_core_port core_port; /* must be first */ struct net_device *dev; struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats; struct mlxsw_sp *mlxsw_sp; diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 7b74dcb2e4fb..8eac26f42425 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -76,7 +76,6 @@ struct mlxsw_sx_port_pcpu_stats { }; struct mlxsw_sx_port { - struct mlxsw_core_port core_port; /* must be first */ struct net_device *dev; struct mlxsw_sx_port_pcpu_stats __percpu *pcpu_stats; struct mlxsw_sx *mlxsw_sx; @@ -995,8 +994,8 @@ mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port, return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spmlr), spmlr_pl); } -static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, - u8 module, u8 width) +static int __mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, + u8 module, u8 width) { struct mlxsw_sx_port *mlxsw_sx_port; struct net_device *dev; @@ -1099,19 +1098,11 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, goto err_register_netdev; } - err = mlxsw_core_port_init(mlxsw_sx->core, &mlxsw_sx_port->core_port, - mlxsw_sx_port->local_port, dev, false, 0); - if (err) { - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n", - mlxsw_sx_port->local_port); - goto err_core_port_init; - } - + mlxsw_core_port_set(mlxsw_sx->core, mlxsw_sx_port->local_port, + mlxsw_sx_port, dev, false, 0); mlxsw_sx->ports[local_port] = mlxsw_sx_port; return 0; -err_core_port_init: - unregister_netdev(dev); err_register_netdev: err_port_mac_learning_mode_set: err_port_stp_state_set: @@ -1128,11 +1119,33 @@ err_alloc_stats: return err; } -static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) +static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, + u8 module, u8 width) +{ + int err; + + err = mlxsw_core_port_init(mlxsw_sx->core, local_port); + if (err) { + dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n", + local_port); + return err; + } + err = __mlxsw_sx_port_create(mlxsw_sx, local_port, module, width); + if (err) + goto err_port_create; + + return 0; + +err_port_create: + mlxsw_core_port_fini(mlxsw_sx->core, local_port); + return err; +} + +static void __mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) { struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port]; - mlxsw_core_port_fini(&mlxsw_sx_port->core_port); + mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx); unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */ mlxsw_sx->ports[local_port] = NULL; mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); @@ -1140,6 +1153,12 @@ static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) free_netdev(mlxsw_sx_port->dev); } +static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) +{ + __mlxsw_sx_port_remove(mlxsw_sx, local_port); + mlxsw_core_port_fini(mlxsw_sx->core, local_port); +} + static bool mlxsw_sx_port_created(struct mlxsw_sx *mlxsw_sx, u8 local_port) { return mlxsw_sx->ports[local_port] != NULL; -- cgit v1.2.3 From c68b71cb2fa98e2fa1e177278b349cf2653d8d83 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:56 +0200 Subject: mlxsw: switchx2: Add Infiniband switch partition In order to put a port in Infiniband fabric it should be assigned to separate swid (Switch partition) that initialized as IB swid. Signed-off-by: Elad Raz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/port.h | 1 + drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/port.h b/drivers/net/ethernet/mellanox/mlxsw/port.h index af371a82c35b..729607137738 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/port.h +++ b/drivers/net/ethernet/mellanox/mlxsw/port.h @@ -44,6 +44,7 @@ #define MLXSW_PORT_SWID_DISABLED_PORT 255 #define MLXSW_PORT_SWID_ALL_SWIDS 254 +#define MLXSW_PORT_SWID_TYPE_IB 1 #define MLXSW_PORT_SWID_TYPE_ETH 2 #define MLXSW_PORT_MID 0xd000 diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 8eac26f42425..a905589263d9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1590,13 +1590,17 @@ static struct mlxsw_config_profile mlxsw_sx_config_profile = { .used_flood_mode = 1, .flood_mode = 3, .used_max_ib_mc = 1, - .max_ib_mc = 0, + .max_ib_mc = 6, .used_max_pkey = 1, .max_pkey = 0, .swid_config = { { .used_type = 1, .type = MLXSW_PORT_SWID_TYPE_ETH, + }, + { + .used_type = 1, + .type = MLXSW_PORT_SWID_TYPE_IB, } }, .resource_query_enable = 0, -- cgit v1.2.3 From d808c7e490350c51a883dec65c4f47e9c5cad79f Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:57 +0200 Subject: mlxsw: core: Add "eth" prefix to mlxsw_core_port_set Since we are about to introduce IB port APIs, we will add prefixes to existing APIs. Signed-off-by: Elad Raz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 8 ++++---- drivers/net/ethernet/mellanox/mlxsw/core.h | 6 +++--- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 5 +++-- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index b50acb1a7260..dcd7202dd47e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1705,9 +1705,9 @@ void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) } EXPORT_SYMBOL(mlxsw_core_port_fini); -void mlxsw_core_port_set(struct mlxsw_core *mlxsw_core, u8 local_port, - void *port_driver_priv, struct net_device *dev, - bool split, u32 split_group) +void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv, struct net_device *dev, + bool split, u32 split_group) { struct mlxsw_core_port *mlxsw_core_port = &mlxsw_core->ports[local_port]; @@ -1718,7 +1718,7 @@ void mlxsw_core_port_set(struct mlxsw_core *mlxsw_core, u8 local_port, devlink_port_split_set(devlink_port, split_group); devlink_port_type_eth_set(devlink_port, dev); } -EXPORT_SYMBOL(mlxsw_core_port_set); +EXPORT_SYMBOL(mlxsw_core_port_eth_set); void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, void *port_driver_priv) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index f4bbbd485d87..82866d5e23c0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -145,9 +145,9 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port); int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port); void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port); -void mlxsw_core_port_set(struct mlxsw_core *mlxsw_core, u8 local_port, - void *port_driver_priv, struct net_device *dev, - bool split, u32 split_group); +void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv, struct net_device *dev, + bool split, u32 split_group); void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, void *port_driver_priv); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index ad4ff278ccee..8bca020e3fae 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2358,8 +2358,9 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, goto err_register_netdev; } - mlxsw_core_port_set(mlxsw_sp->core, mlxsw_sp_port->local_port, - mlxsw_sp_port, dev, mlxsw_sp_port->split, module); + mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port, + mlxsw_sp_port, dev, mlxsw_sp_port->split, + module); mlxsw_core_schedule_dw(&mlxsw_sp_port->hw_stats.update_dw, 0); return 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index a905589263d9..d110e3f8bbc5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1098,8 +1098,8 @@ static int __mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, goto err_register_netdev; } - mlxsw_core_port_set(mlxsw_sx->core, mlxsw_sx_port->local_port, - mlxsw_sx_port, dev, false, 0); + mlxsw_core_port_eth_set(mlxsw_sx->core, mlxsw_sx_port->local_port, + mlxsw_sx_port, dev, false, 0); mlxsw_sx->ports[local_port] = mlxsw_sx_port; return 0; -- cgit v1.2.3 From 0c81ea5db25986fb2a704105db454a790c59709c Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:58 +0200 Subject: mlxsw: core: Add port type (Eth/IB) set API Add "port_type_set" API to mlxsw core. The core layer send the change type callback to the port along with it's private information. Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 41 ++++++++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 6 +++++ 2 files changed, 47 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index dcd7202dd47e..600481771c04 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -93,6 +93,7 @@ struct mlxsw_core_pcpu_stats { struct mlxsw_core_port { struct devlink_port devlink_port; void *port_driver_priv; + u8 local_port; }; void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port) @@ -937,6 +938,21 @@ static void *__dl_port(struct devlink_port *devlink_port) return container_of(devlink_port, struct mlxsw_core_port, devlink_port); } +static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port, + enum devlink_port_type port_type) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); + + if (!mlxsw_driver->port_type_set) + return -EOPNOTSUPP; + + return mlxsw_driver->port_type_set(mlxsw_core, + mlxsw_core_port->local_port, + port_type); +} + static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port, unsigned int sb_index, u16 pool_index, u32 *p_threshold) @@ -1060,6 +1076,7 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port, } static const struct devlink_ops mlxsw_devlink_ops = { + .port_type_set = mlxsw_devlink_port_type_set, .port_split = mlxsw_devlink_port_split, .port_unsplit = mlxsw_devlink_port_unsplit, .sb_pool_get = mlxsw_devlink_sb_pool_get, @@ -1687,6 +1704,7 @@ int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port) struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; int err; + mlxsw_core_port->local_port = local_port; err = devlink_port_register(devlink, devlink_port, local_port); if (err) memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); @@ -1720,6 +1738,18 @@ void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, } EXPORT_SYMBOL(mlxsw_core_port_eth_set); +void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv) +{ + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; + struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; + + mlxsw_core_port->port_driver_priv = port_driver_priv; + devlink_port_type_ib_set(devlink_port, NULL); +} +EXPORT_SYMBOL(mlxsw_core_port_ib_set); + void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, void *port_driver_priv) { @@ -1732,6 +1762,17 @@ void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, } EXPORT_SYMBOL(mlxsw_core_port_clear); +enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, + u8 local_port) +{ + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; + struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; + + return devlink_port->type; +} +EXPORT_SYMBOL(mlxsw_core_port_type_get); + static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, const char *buf, size_t size) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 82866d5e23c0..c0acc1b9eb2f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -148,8 +148,12 @@ void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port); void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, void *port_driver_priv, struct net_device *dev, bool split, u32 split_group); +void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv); void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, void *port_driver_priv); +enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, + u8 local_port); int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay); @@ -210,6 +214,8 @@ struct mlxsw_driver { int (*init)(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info); void (*fini)(struct mlxsw_core *mlxsw_core); + int (*port_type_set)(struct mlxsw_core *mlxsw_core, u8 local_port, + enum devlink_port_type new_type); int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port, unsigned int count); int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port); -- cgit v1.2.3 From 03ddb787c729fec7b45d5e8640d05351fb0d1b6b Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:35:59 +0200 Subject: mlxsw: switchx2: Add eth prefix to port create and remove Since we are about to add Infiniband port remove and create we will add "eth" prefix to port create and remove APIs. Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index d110e3f8bbc5..3aa094866fbb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -994,8 +994,8 @@ mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port, return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spmlr), spmlr_pl); } -static int __mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, - u8 module, u8 width) +static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, + u8 module, u8 width) { struct mlxsw_sx_port *mlxsw_sx_port; struct net_device *dev; @@ -1119,8 +1119,8 @@ err_alloc_stats: return err; } -static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, - u8 module, u8 width) +static int mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, + u8 module, u8 width) { int err; @@ -1130,7 +1130,7 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, local_port); return err; } - err = __mlxsw_sx_port_create(mlxsw_sx, local_port, module, width); + err = __mlxsw_sx_port_eth_create(mlxsw_sx, local_port, module, width); if (err) goto err_port_create; @@ -1141,7 +1141,7 @@ err_port_create: return err; } -static void __mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) +static void __mlxsw_sx_port_eth_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) { struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port]; @@ -1153,9 +1153,9 @@ static void __mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) free_netdev(mlxsw_sx_port->dev); } -static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) +static void mlxsw_sx_port_eth_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) { - __mlxsw_sx_port_remove(mlxsw_sx, local_port); + __mlxsw_sx_port_eth_remove(mlxsw_sx, local_port); mlxsw_core_port_fini(mlxsw_sx->core, local_port); } @@ -1170,7 +1170,7 @@ static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) if (mlxsw_sx_port_created(mlxsw_sx, i)) - mlxsw_sx_port_remove(mlxsw_sx, i); + mlxsw_sx_port_eth_remove(mlxsw_sx, i); kfree(mlxsw_sx->ports); } @@ -1193,7 +1193,7 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) goto err_port_module_info_get; if (!width) continue; - err = mlxsw_sx_port_create(mlxsw_sx, i, module, width); + err = mlxsw_sx_port_eth_create(mlxsw_sx, i, module, width); if (err) goto err_port_create; } @@ -1203,7 +1203,7 @@ err_port_create: err_port_module_info_get: for (i--; i >= 1; i--) if (mlxsw_sx_port_created(mlxsw_sx, i)) - mlxsw_sx_port_remove(mlxsw_sx, i); + mlxsw_sx_port_eth_remove(mlxsw_sx, i); kfree(mlxsw_sx->ports); return err; } -- cgit v1.2.3 From 64b92b0114122153035a7f95efa4af0a76e02bb5 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:36:00 +0200 Subject: mlxsw: switchx2: Add IB port support SwitchX-2 is IB capable device. This patch add a support to change the port type between Ethernet and Infiniband. When the port is set to IB, the FW implements the Subnet Management Agent (SMA) manage the port. All port attributes can be control remotely by the SM. Usage: $ devlink port show pci/0000:03:00.0/1: type eth netdev eth0 pci/0000:03:00.0/3: type eth netdev eth1 pci/0000:03:00.0/5: type eth netdev eth2 pci/0000:03:00.0/6: type eth netdev eth3 pci/0000:03:00.0/8: type eth netdev eth4 $ devlink port set pci/0000:03:00.0/1 type ib $ devlink port show pci/0000:03:00.0/1: type ib Signed-off-by: Elad Raz Reviewed-by: Jiri Pirko Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/ib.h | 39 +++++ drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 229 +++++++++++++++++++++++-- 2 files changed, 249 insertions(+), 19 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/ib.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/ib.h b/drivers/net/ethernet/mellanox/mlxsw/ib.h new file mode 100644 index 000000000000..ce313aaa6336 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/ib.h @@ -0,0 +1,39 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/ib.h + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Elad Raz + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _MLXSW_IB_H +#define _MLXSW_IB_H + +#define MLXSW_IB_DEFAULT_MTU 4096 + +#endif /* _MLXSW_IB_H */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 3aa094866fbb..5208764797ba 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -3,7 +3,7 @@ * Copyright (c) 2015 Mellanox Technologies. All rights reserved. * Copyright (c) 2015 Jiri Pirko * Copyright (c) 2015 Ido Schimmel - * Copyright (c) 2015 Elad Raz + * Copyright (c) 2015-2016 Elad Raz * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -53,6 +53,7 @@ #include "port.h" #include "trap.h" #include "txheader.h" +#include "ib.h" static const char mlxsw_sx_driver_name[] = "mlxsw_switchx2"; static const char mlxsw_sx_driver_version[] = "1.0"; @@ -218,14 +219,14 @@ static int mlxsw_sx_port_oper_status_get(struct mlxsw_sx_port *mlxsw_sx_port, return 0; } -static int mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port, u16 mtu) +static int __mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port, + u16 mtu) { struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; char pmtu_pl[MLXSW_REG_PMTU_LEN]; int max_mtu; int err; - mtu += MLXSW_TXHDR_LEN + ETH_HLEN; mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sx_port->local_port, 0); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl); if (err) @@ -239,6 +240,32 @@ static int mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port, u16 mtu) return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl); } +static int mlxsw_sx_port_mtu_eth_set(struct mlxsw_sx_port *mlxsw_sx_port, + u16 mtu) +{ + mtu += MLXSW_TXHDR_LEN + ETH_HLEN; + return __mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu); +} + +static int mlxsw_sx_port_mtu_ib_set(struct mlxsw_sx_port *mlxsw_sx_port, + u16 mtu) +{ + return __mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu); +} + +static int mlxsw_sx_port_ib_port_set(struct mlxsw_sx_port *mlxsw_sx_port, + u8 ib_port) +{ + struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; + char plib_pl[MLXSW_REG_PLIB_LEN] = {0}; + int err; + + mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sx_port->local_port); + mlxsw_reg_plib_ib_port_set(plib_pl, ib_port); + err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(plib), plib_pl); + return err; +} + static int mlxsw_sx_port_swid_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 swid) { struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; @@ -348,7 +375,7 @@ static int mlxsw_sx_port_change_mtu(struct net_device *dev, int mtu) struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); int err; - err = mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu); + err = mlxsw_sx_port_mtu_eth_set(mlxsw_sx_port, mtu); if (err) return err; dev->mtu = mtu; @@ -969,6 +996,17 @@ static int mlxsw_sx_port_stp_state_set(struct mlxsw_sx_port *mlxsw_sx_port, return err; } +static int mlxsw_sx_port_ib_speed_set(struct mlxsw_sx_port *mlxsw_sx_port, + u16 speed, u16 width) +{ + struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; + char ptys_pl[MLXSW_REG_PTYS_LEN]; + + mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sx_port->local_port, speed, + width); + return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); +} + static int mlxsw_sx_port_speed_by_width_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 width) { @@ -1063,7 +1101,7 @@ static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, goto err_port_speed_set; } - err = mlxsw_sx_port_mtu_set(mlxsw_sx_port, ETH_DATA_LEN); + err = mlxsw_sx_port_mtu_eth_set(mlxsw_sx_port, ETH_DATA_LEN); if (err) { dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n", mlxsw_sx_port->local_port); @@ -1153,15 +1191,118 @@ static void __mlxsw_sx_port_eth_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) free_netdev(mlxsw_sx_port->dev); } -static void mlxsw_sx_port_eth_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) +static bool mlxsw_sx_port_created(struct mlxsw_sx *mlxsw_sx, u8 local_port) { - __mlxsw_sx_port_eth_remove(mlxsw_sx, local_port); - mlxsw_core_port_fini(mlxsw_sx->core, local_port); + return mlxsw_sx->ports[local_port] != NULL; } -static bool mlxsw_sx_port_created(struct mlxsw_sx *mlxsw_sx, u8 local_port) +static int __mlxsw_sx_port_ib_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, + u8 module, u8 width) { - return mlxsw_sx->ports[local_port] != NULL; + struct mlxsw_sx_port *mlxsw_sx_port; + int err; + + mlxsw_sx_port = kzalloc(sizeof(*mlxsw_sx_port), GFP_KERNEL); + if (!mlxsw_sx_port) + return -ENOMEM; + mlxsw_sx_port->mlxsw_sx = mlxsw_sx; + mlxsw_sx_port->local_port = local_port; + mlxsw_sx_port->mapping.module = module; + + err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port); + if (err) { + dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n", + mlxsw_sx_port->local_port); + goto err_port_system_port_mapping_set; + } + + /* Adding port to Infiniband swid (1) */ + err = mlxsw_sx_port_swid_set(mlxsw_sx_port, 1); + if (err) { + dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set SWID\n", + mlxsw_sx_port->local_port); + goto err_port_swid_set; + } + + /* Expose the IB port number as it's front panel name */ + err = mlxsw_sx_port_ib_port_set(mlxsw_sx_port, module + 1); + if (err) { + dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set IB port\n", + mlxsw_sx_port->local_port); + goto err_port_ib_set; + } + + /* Supports all speeds from SDR to FDR (bitmask) and support bus width + * of 1x, 2x and 4x (3 bits bitmask) + */ + err = mlxsw_sx_port_ib_speed_set(mlxsw_sx_port, + MLXSW_REG_PTYS_IB_SPEED_EDR - 1, + BIT(3) - 1); + if (err) { + dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n", + mlxsw_sx_port->local_port); + goto err_port_speed_set; + } + + /* Change to the maximum MTU the device supports, the SMA will take + * care of the active MTU + */ + err = mlxsw_sx_port_mtu_ib_set(mlxsw_sx_port, MLXSW_IB_DEFAULT_MTU); + if (err) { + dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n", + mlxsw_sx_port->local_port); + goto err_port_mtu_set; + } + + err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true); + if (err) { + dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to change admin state to UP\n", + mlxsw_sx_port->local_port); + goto err_port_admin_set; + } + + mlxsw_core_port_ib_set(mlxsw_sx->core, mlxsw_sx_port->local_port, + mlxsw_sx_port); + mlxsw_sx->ports[local_port] = mlxsw_sx_port; + return 0; + +err_port_admin_set: +err_port_mtu_set: +err_port_speed_set: +err_port_ib_set: + mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); +err_port_swid_set: +err_port_system_port_mapping_set: + kfree(mlxsw_sx_port); + return err; +} + +static void __mlxsw_sx_port_ib_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) +{ + struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port]; + + mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx); + mlxsw_sx->ports[local_port] = NULL; + mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false); + mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); + kfree(mlxsw_sx_port); +} + +static void __mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) +{ + enum devlink_port_type port_type = + mlxsw_core_port_type_get(mlxsw_sx->core, local_port); + + if (port_type == DEVLINK_PORT_TYPE_ETH) + __mlxsw_sx_port_eth_remove(mlxsw_sx, local_port); + else if (port_type == DEVLINK_PORT_TYPE_IB) + __mlxsw_sx_port_ib_remove(mlxsw_sx, local_port); +} + +static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) +{ + __mlxsw_sx_port_remove(mlxsw_sx, local_port); + mlxsw_core_port_fini(mlxsw_sx->core, local_port); } static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) @@ -1170,7 +1311,7 @@ static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) if (mlxsw_sx_port_created(mlxsw_sx, i)) - mlxsw_sx_port_eth_remove(mlxsw_sx, i); + mlxsw_sx_port_remove(mlxsw_sx, i); kfree(mlxsw_sx->ports); } @@ -1203,17 +1344,41 @@ err_port_create: err_port_module_info_get: for (i--; i >= 1; i--) if (mlxsw_sx_port_created(mlxsw_sx, i)) - mlxsw_sx_port_eth_remove(mlxsw_sx, i); + mlxsw_sx_port_remove(mlxsw_sx, i); kfree(mlxsw_sx->ports); return err; } +static void mlxsw_sx_pude_eth_event_func(struct mlxsw_sx_port *mlxsw_sx_port, + enum mlxsw_reg_pude_oper_status status) +{ + if (status == MLXSW_PORT_OPER_STATUS_UP) { + netdev_info(mlxsw_sx_port->dev, "link up\n"); + netif_carrier_on(mlxsw_sx_port->dev); + } else { + netdev_info(mlxsw_sx_port->dev, "link down\n"); + netif_carrier_off(mlxsw_sx_port->dev); + } +} + +static void mlxsw_sx_pude_ib_event_func(struct mlxsw_sx_port *mlxsw_sx_port, + enum mlxsw_reg_pude_oper_status status) +{ + if (status == MLXSW_PORT_OPER_STATUS_UP) + pr_info("ib link for port %d - up\n", + mlxsw_sx_port->mapping.module + 1); + else + pr_info("ib link for port %d - down\n", + mlxsw_sx_port->mapping.module + 1); +} + static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg, char *pude_pl, void *priv) { struct mlxsw_sx *mlxsw_sx = priv; struct mlxsw_sx_port *mlxsw_sx_port; enum mlxsw_reg_pude_oper_status status; + enum devlink_port_type port_type; u8 local_port; local_port = mlxsw_reg_pude_local_port_get(pude_pl); @@ -1225,13 +1390,11 @@ static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg, } status = mlxsw_reg_pude_oper_status_get(pude_pl); - if (status == MLXSW_PORT_OPER_STATUS_UP) { - netdev_info(mlxsw_sx_port->dev, "link up\n"); - netif_carrier_on(mlxsw_sx_port->dev); - } else { - netdev_info(mlxsw_sx_port->dev, "link down\n"); - netif_carrier_off(mlxsw_sx_port->dev); - } + port_type = mlxsw_core_port_type_get(mlxsw_sx->core, local_port); + if (port_type == DEVLINK_PORT_TYPE_ETH) + mlxsw_sx_pude_eth_event_func(mlxsw_sx_port, status); + else if (port_type == DEVLINK_PORT_TYPE_IB) + mlxsw_sx_pude_ib_event_func(mlxsw_sx_port, status); } static struct mlxsw_event_listener mlxsw_sx_pude_event = { @@ -1305,6 +1468,33 @@ static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port, netif_receive_skb(skb); } +static int mlxsw_sx_port_type_set(struct mlxsw_core *mlxsw_core, u8 local_port, + enum devlink_port_type new_type) +{ + struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core); + u8 module, width; + int err; + + if (new_type == DEVLINK_PORT_TYPE_AUTO) + return -EOPNOTSUPP; + + __mlxsw_sx_port_remove(mlxsw_sx, local_port); + err = mlxsw_sx_port_module_info_get(mlxsw_sx, local_port, &module, + &width); + if (err) + goto err_port_module_info_get; + + if (new_type == DEVLINK_PORT_TYPE_ETH) + err = __mlxsw_sx_port_eth_create(mlxsw_sx, local_port, module, + width); + else if (new_type == DEVLINK_PORT_TYPE_IB) + err = __mlxsw_sx_port_ib_create(mlxsw_sx, local_port, module, + width); + +err_port_module_info_get: + return err; +} + static const struct mlxsw_rx_listener mlxsw_sx_rx_listener[] = { { .func = mlxsw_sx_rx_listener_func, @@ -1614,6 +1804,7 @@ static struct mlxsw_driver mlxsw_sx_driver = { .txhdr_construct = mlxsw_sx_txhdr_construct, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sx_config_profile, + .port_type_set = mlxsw_sx_port_type_set, }; static const struct pci_device_id mlxsw_sx_pci_id_table[] = { -- cgit v1.2.3 From d1ba52638456f20f81e9182b74d56ce036b39c6d Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 28 Oct 2016 21:36:01 +0200 Subject: mlxsw: switchib: Introduce SwitchIB and SwitchIB silicon driver SwitchIB and SwitchIB-2 are Infiniband switches with up to 36 ports. This driver initialize the hardware and Firmware which implements the IB management and connection with the SM. Signed-off-by: Elad Raz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Kconfig | 11 + drivers/net/ethernet/mellanox/mlxsw/Makefile | 2 + drivers/net/ethernet/mellanox/mlxsw/pci.h | 2 + drivers/net/ethernet/mellanox/mlxsw/port.h | 3 + drivers/net/ethernet/mellanox/mlxsw/switchib.c | 598 +++++++++++++++++++++++++ 5 files changed, 616 insertions(+) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/switchib.c (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index d0bcf59c1bd6..bac2e5e826e2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig @@ -29,6 +29,17 @@ config MLXSW_PCI To compile this driver as a module, choose M here: the module will be called mlxsw_pci. +config MLXSW_SWITCHIB + tristate "Mellanox Technologies SwitchIB and SwitchIB-2 support" + depends on MLXSW_CORE && NET_SWITCHDEV + default m + ---help--- + This driver supports Mellanox Technologies SwitchIB and SwitchIB-2 + Infiniband Switch ASICs. + + To compile this driver as a module, choose M here: the + module will be called mlxsw_switchib. + config MLXSW_SWITCHX2 tristate "Mellanox Technologies SwitchX-2 support" depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index d20ae1838a64..badef877015a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -3,6 +3,8 @@ mlxsw_core-objs := core.o mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o mlxsw_pci-objs := pci.o +obj-$(CONFIG_MLXSW_SWITCHIB) += mlxsw_switchib.o +mlxsw_switchib-objs := switchib.o obj-$(CONFIG_MLXSW_SWITCHX2) += mlxsw_switchx2.o mlxsw_switchx2-objs := switchx2.o obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h index 35a0011be64d..d65582325cd5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h @@ -39,6 +39,8 @@ #define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738 #define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84 +#define PCI_DEVICE_ID_MELLANOX_SWITCHIB 0xcb20 +#define PCI_DEVICE_ID_MELLANOX_SWITCHIB2 0xcf08 #if IS_ENABLED(CONFIG_MLXSW_PCI) diff --git a/drivers/net/ethernet/mellanox/mlxsw/port.h b/drivers/net/ethernet/mellanox/mlxsw/port.h index 729607137738..3d42146473b3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/port.h +++ b/drivers/net/ethernet/mellanox/mlxsw/port.h @@ -52,6 +52,9 @@ #define MLXSW_PORT_MAX_PHY_PORTS 0x40 #define MLXSW_PORT_MAX_PORTS (MLXSW_PORT_MAX_PHY_PORTS + 1) +#define MLXSW_PORT_MAX_IB_PHY_PORTS 36 +#define MLXSW_PORT_MAX_IB_PORTS (MLXSW_PORT_MAX_IB_PHY_PORTS + 1) + #define MLXSW_PORT_DEVID_BITS_OFFSET 10 #define MLXSW_PORT_PHY_BITS_OFFSET 4 #define MLXSW_PORT_PHY_BITS_MASK (MLXSW_PORT_MAX_PHY_PORTS - 1) diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c new file mode 100644 index 000000000000..ec0b27e72a5d --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c @@ -0,0 +1,598 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/switchib.c + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Elad Raz + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pci.h" +#include "core.h" +#include "reg.h" +#include "port.h" +#include "trap.h" +#include "txheader.h" +#include "ib.h" + +static const char mlxsw_sib_driver_name[] = "mlxsw_switchib"; +static const char mlxsw_sib2_driver_name[] = "mlxsw_switchib2"; + +struct mlxsw_sib_port; + +struct mlxsw_sib { + struct mlxsw_sib_port **ports; + struct mlxsw_core *core; + const struct mlxsw_bus_info *bus_info; +}; + +struct mlxsw_sib_port { + struct mlxsw_sib *mlxsw_sib; + u8 local_port; + struct { + u8 module; + } mapping; +}; + +/* tx_v1_hdr_version + * Tx header version. + * Must be set to 1. + */ +MLXSW_ITEM32(tx_v1, hdr, version, 0x00, 28, 4); + +/* tx_v1_hdr_ctl + * Packet control type. + * 0 - Ethernet control (e.g. EMADs, LACP) + * 1 - Ethernet data + */ +MLXSW_ITEM32(tx_v1, hdr, ctl, 0x00, 26, 2); + +/* tx_v1_hdr_proto + * Packet protocol type. Must be set to 1 (Ethernet). + */ +MLXSW_ITEM32(tx_v1, hdr, proto, 0x00, 21, 3); + +/* tx_v1_hdr_swid + * Switch partition ID. Must be set to 0. + */ +MLXSW_ITEM32(tx_v1, hdr, swid, 0x00, 12, 3); + +/* tx_v1_hdr_control_tclass + * Indicates if the packet should use the control TClass and not one + * of the data TClasses. + */ +MLXSW_ITEM32(tx_v1, hdr, control_tclass, 0x00, 6, 1); + +/* tx_v1_hdr_port_mid + * Destination local port for unicast packets. + * Destination multicast ID for multicast packets. + * + * Control packets are directed to a specific egress port, while data + * packets are transmitted through the CPU port (0) into the switch partition, + * where forwarding rules are applied. + */ +MLXSW_ITEM32(tx_v1, hdr, port_mid, 0x04, 16, 16); + +/* tx_v1_hdr_type + * 0 - Data packets + * 6 - Control packets + */ +MLXSW_ITEM32(tx_v1, hdr, type, 0x0C, 0, 4); + +static void +mlxsw_sib_tx_v1_hdr_construct(struct sk_buff *skb, + const struct mlxsw_tx_info *tx_info) +{ + char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN); + + memset(txhdr, 0, MLXSW_TXHDR_LEN); + + mlxsw_tx_v1_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1); + mlxsw_tx_v1_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL); + mlxsw_tx_v1_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH); + mlxsw_tx_v1_hdr_swid_set(txhdr, 0); + mlxsw_tx_v1_hdr_control_tclass_set(txhdr, 1); + mlxsw_tx_v1_hdr_port_mid_set(txhdr, tx_info->local_port); + mlxsw_tx_v1_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL); +} + +static int +mlxsw_sib_port_admin_status_set(struct mlxsw_sib_port *mlxsw_sib_port, + bool is_up) +{ + struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; + char paos_pl[MLXSW_REG_PAOS_LEN]; + + mlxsw_reg_paos_pack(paos_pl, mlxsw_sib_port->local_port, + is_up ? MLXSW_PORT_ADMIN_STATUS_UP : + MLXSW_PORT_ADMIN_STATUS_DOWN); + return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(paos), paos_pl); +} + +static int mlxsw_sib_port_mtu_set(struct mlxsw_sib_port *mlxsw_sib_port, + u16 mtu) +{ + struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; + char pmtu_pl[MLXSW_REG_PMTU_LEN]; + int max_mtu; + int err; + + mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, 0); + err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl); + if (err) + return err; + max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl); + + if (mtu > max_mtu) + return -EINVAL; + + mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, mtu); + return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl); +} + +static int mlxsw_sib_port_set(struct mlxsw_sib_port *mlxsw_sib_port, u8 port) +{ + struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; + char plib_pl[MLXSW_REG_PLIB_LEN] = {0}; + int err; + + mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sib_port->local_port); + mlxsw_reg_plib_ib_port_set(plib_pl, port); + err = mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(plib), plib_pl); + return err; +} + +static int mlxsw_sib_port_swid_set(struct mlxsw_sib_port *mlxsw_sib_port, + u8 swid) +{ + struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; + char pspa_pl[MLXSW_REG_PSPA_LEN]; + + mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sib_port->local_port); + return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pspa), pspa_pl); +} + +static int mlxsw_sib_port_module_info_get(struct mlxsw_sib *mlxsw_sib, + u8 local_port, u8 *p_module, + u8 *p_width) +{ + char pmlp_pl[MLXSW_REG_PMLP_LEN]; + int err; + + mlxsw_reg_pmlp_pack(pmlp_pl, local_port); + err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmlp), pmlp_pl); + if (err) + return err; + *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); + *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); + return 0; +} + +static int mlxsw_sib_port_speed_set(struct mlxsw_sib_port *mlxsw_sib_port, + u16 speed, u16 width) +{ + struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; + char ptys_pl[MLXSW_REG_PTYS_LEN]; + + mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sib_port->local_port, speed, + width); + return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(ptys), ptys_pl); +} + +static bool mlxsw_sib_port_created(struct mlxsw_sib *mlxsw_sib, u8 local_port) +{ + return mlxsw_sib->ports[local_port] != NULL; +} + +static int __mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port, + u8 module, u8 width) +{ + struct mlxsw_sib_port *mlxsw_sib_port; + int err; + + mlxsw_sib_port = kzalloc(sizeof(*mlxsw_sib_port), GFP_KERNEL); + if (!mlxsw_sib_port) + return -ENOMEM; + mlxsw_sib_port->mlxsw_sib = mlxsw_sib; + mlxsw_sib_port->local_port = local_port; + mlxsw_sib_port->mapping.module = module; + + err = mlxsw_sib_port_swid_set(mlxsw_sib_port, 0); + if (err) { + dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set SWID\n", + mlxsw_sib_port->local_port); + goto err_port_swid_set; + } + + /* Expose the IB port number as it's front panel name */ + err = mlxsw_sib_port_set(mlxsw_sib_port, module + 1); + if (err) { + dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set IB port\n", + mlxsw_sib_port->local_port); + goto err_port_ib_set; + } + + /* Supports all speeds from SDR to FDR (bitmask) and support bus width + * of 1x, 2x and 4x (3 bits bitmask) + */ + err = mlxsw_sib_port_speed_set(mlxsw_sib_port, + MLXSW_REG_PTYS_IB_SPEED_EDR - 1, + BIT(3) - 1); + if (err) { + dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set speed\n", + mlxsw_sib_port->local_port); + goto err_port_speed_set; + } + + /* Change to the maximum MTU the device supports, the SMA will take + * care of the active MTU + */ + err = mlxsw_sib_port_mtu_set(mlxsw_sib_port, MLXSW_IB_DEFAULT_MTU); + if (err) { + dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set MTU\n", + mlxsw_sib_port->local_port); + goto err_port_mtu_set; + } + + err = mlxsw_sib_port_admin_status_set(mlxsw_sib_port, true); + if (err) { + dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to change admin state to UP\n", + mlxsw_sib_port->local_port); + goto err_port_admin_set; + } + + mlxsw_core_port_ib_set(mlxsw_sib->core, mlxsw_sib_port->local_port, + mlxsw_sib_port); + mlxsw_sib->ports[local_port] = mlxsw_sib_port; + return 0; + +err_port_admin_set: +err_port_mtu_set: +err_port_speed_set: +err_port_ib_set: + mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT); +err_port_swid_set: + kfree(mlxsw_sib_port); + return err; +} + +static int mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port, + u8 module, u8 width) +{ + int err; + + err = mlxsw_core_port_init(mlxsw_sib->core, local_port); + if (err) { + dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to init core port\n", + local_port); + return err; + } + err = __mlxsw_sib_port_create(mlxsw_sib, local_port, module, width); + if (err) + goto err_port_create; + + return 0; + +err_port_create: + mlxsw_core_port_fini(mlxsw_sib->core, local_port); + return err; +} + +static void __mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port) +{ + struct mlxsw_sib_port *mlxsw_sib_port = mlxsw_sib->ports[local_port]; + + mlxsw_core_port_clear(mlxsw_sib->core, local_port, mlxsw_sib); + mlxsw_sib->ports[local_port] = NULL; + mlxsw_sib_port_admin_status_set(mlxsw_sib_port, false); + mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT); + kfree(mlxsw_sib_port); +} + +static void mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port) +{ + __mlxsw_sib_port_remove(mlxsw_sib, local_port); + mlxsw_core_port_fini(mlxsw_sib->core, local_port); +} + +static void mlxsw_sib_ports_remove(struct mlxsw_sib *mlxsw_sib) +{ + int i; + + for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++) + if (mlxsw_sib_port_created(mlxsw_sib, i)) + mlxsw_sib_port_remove(mlxsw_sib, i); + kfree(mlxsw_sib->ports); +} + +static int mlxsw_sib_ports_create(struct mlxsw_sib *mlxsw_sib) +{ + size_t alloc_size; + u8 module, width; + int i; + int err; + + alloc_size = sizeof(struct mlxsw_sib_port *) * MLXSW_PORT_MAX_IB_PORTS; + mlxsw_sib->ports = kzalloc(alloc_size, GFP_KERNEL); + if (!mlxsw_sib->ports) + return -ENOMEM; + + for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++) { + err = mlxsw_sib_port_module_info_get(mlxsw_sib, i, &module, + &width); + if (err) + goto err_port_module_info_get; + if (!width) + continue; + err = mlxsw_sib_port_create(mlxsw_sib, i, module, width); + if (err) + goto err_port_create; + } + return 0; + +err_port_create: +err_port_module_info_get: + for (i--; i >= 1; i--) + if (mlxsw_sib_port_created(mlxsw_sib, i)) + mlxsw_sib_port_remove(mlxsw_sib, i); + kfree(mlxsw_sib->ports); + return err; +} + +static void +mlxsw_sib_pude_ib_event_func(struct mlxsw_sib_port *mlxsw_sib_port, + enum mlxsw_reg_pude_oper_status status) +{ + if (status == MLXSW_PORT_OPER_STATUS_UP) + pr_info("ib link for port %d - up\n", + mlxsw_sib_port->mapping.module + 1); + else + pr_info("ib link for port %d - down\n", + mlxsw_sib_port->mapping.module + 1); +} + +static void mlxsw_sib_pude_event_func(const struct mlxsw_reg_info *reg, + char *pude_pl, void *priv) +{ + struct mlxsw_sib *mlxsw_sib = priv; + struct mlxsw_sib_port *mlxsw_sib_port; + enum mlxsw_reg_pude_oper_status status; + u8 local_port; + + local_port = mlxsw_reg_pude_local_port_get(pude_pl); + mlxsw_sib_port = mlxsw_sib->ports[local_port]; + if (!mlxsw_sib_port) { + dev_warn(mlxsw_sib->bus_info->dev, "Port %d: Link event received for non-existent port\n", + local_port); + return; + } + + status = mlxsw_reg_pude_oper_status_get(pude_pl); + mlxsw_sib_pude_ib_event_func(mlxsw_sib_port, status); +} + +static struct mlxsw_event_listener mlxsw_sib_pude_event = { + .func = mlxsw_sib_pude_event_func, + .trap_id = MLXSW_TRAP_ID_PUDE, +}; + +static int mlxsw_sib_event_register(struct mlxsw_sib *mlxsw_sib, + enum mlxsw_event_trap_id trap_id) +{ + struct mlxsw_event_listener *el; + char hpkt_pl[MLXSW_REG_HPKT_LEN]; + int err; + + switch (trap_id) { + case MLXSW_TRAP_ID_PUDE: + el = &mlxsw_sib_pude_event; + break; + } + err = mlxsw_core_event_listener_register(mlxsw_sib->core, el, + mlxsw_sib); + if (err) + return err; + + mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id); + err = mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(hpkt), hpkt_pl); + if (err) + goto err_event_trap_set; + + return 0; + +err_event_trap_set: + mlxsw_core_event_listener_unregister(mlxsw_sib->core, el, mlxsw_sib); + return err; +} + +static void mlxsw_sib_event_unregister(struct mlxsw_sib *mlxsw_sib, + enum mlxsw_event_trap_id trap_id) +{ + struct mlxsw_event_listener *el; + + switch (trap_id) { + case MLXSW_TRAP_ID_PUDE: + el = &mlxsw_sib_pude_event; + break; + } + mlxsw_core_event_listener_unregister(mlxsw_sib->core, el, mlxsw_sib); +} + +static int mlxsw_sib_init(struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info) +{ + struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core); + int err; + + mlxsw_sib->core = mlxsw_core; + mlxsw_sib->bus_info = mlxsw_bus_info; + + err = mlxsw_sib_ports_create(mlxsw_sib); + if (err) { + dev_err(mlxsw_sib->bus_info->dev, "Failed to create ports\n"); + return err; + } + + err = mlxsw_sib_event_register(mlxsw_sib, MLXSW_TRAP_ID_PUDE); + if (err) { + dev_err(mlxsw_sib->bus_info->dev, "Failed to register for PUDE events\n"); + goto err_event_register; + } + + return 0; + +err_event_register: + mlxsw_sib_ports_remove(mlxsw_sib); + return err; +} + +static void mlxsw_sib_fini(struct mlxsw_core *mlxsw_core) +{ + struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core); + + mlxsw_sib_event_unregister(mlxsw_sib, MLXSW_TRAP_ID_PUDE); + mlxsw_sib_ports_remove(mlxsw_sib); +} + +static struct mlxsw_config_profile mlxsw_sib_config_profile = { + .used_max_system_port = 1, + .max_system_port = 48000, + .used_max_ib_mc = 1, + .max_ib_mc = 27, + .used_max_pkey = 1, + .max_pkey = 32, + .swid_config = { + { + .used_type = 1, + .type = MLXSW_PORT_SWID_TYPE_IB, + } + }, + .resource_query_enable = 0, +}; + +static struct mlxsw_driver mlxsw_sib_driver = { + .kind = mlxsw_sib_driver_name, + .priv_size = sizeof(struct mlxsw_sib), + .init = mlxsw_sib_init, + .fini = mlxsw_sib_fini, + .txhdr_construct = mlxsw_sib_tx_v1_hdr_construct, + .txhdr_len = MLXSW_TXHDR_LEN, + .profile = &mlxsw_sib_config_profile, +}; + +static struct mlxsw_driver mlxsw_sib2_driver = { + .kind = mlxsw_sib2_driver_name, + .priv_size = sizeof(struct mlxsw_sib), + .init = mlxsw_sib_init, + .fini = mlxsw_sib_fini, + .txhdr_construct = mlxsw_sib_tx_v1_hdr_construct, + .txhdr_len = MLXSW_TXHDR_LEN, + .profile = &mlxsw_sib_config_profile, +}; + +static const struct pci_device_id mlxsw_sib_pci_id_table[] = { + {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB), 0}, + {0, }, +}; + +static struct pci_driver mlxsw_sib_pci_driver = { + .name = mlxsw_sib_driver_name, + .id_table = mlxsw_sib_pci_id_table, +}; + +static const struct pci_device_id mlxsw_sib2_pci_id_table[] = { + {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB2), 0}, + {0, }, +}; + +static struct pci_driver mlxsw_sib2_pci_driver = { + .name = mlxsw_sib2_driver_name, + .id_table = mlxsw_sib2_pci_id_table, +}; + +static int __init mlxsw_sib_module_init(void) +{ + int err; + + err = mlxsw_core_driver_register(&mlxsw_sib_driver); + if (err) + return err; + + err = mlxsw_core_driver_register(&mlxsw_sib2_driver); + if (err) + goto err_sib2_driver_register; + + err = mlxsw_pci_driver_register(&mlxsw_sib_pci_driver); + if (err) + goto err_sib_pci_driver_register; + + err = mlxsw_pci_driver_register(&mlxsw_sib2_pci_driver); + if (err) + goto err_sib2_pci_driver_register; + + return 0; + +err_sib2_pci_driver_register: + mlxsw_pci_driver_unregister(&mlxsw_sib_pci_driver); +err_sib_pci_driver_register: + mlxsw_core_driver_unregister(&mlxsw_sib2_driver); +err_sib2_driver_register: + mlxsw_core_driver_unregister(&mlxsw_sib_driver); + return err; +} + +static void __exit mlxsw_sib_module_exit(void) +{ + mlxsw_pci_driver_unregister(&mlxsw_sib2_pci_driver); + mlxsw_pci_driver_unregister(&mlxsw_sib_pci_driver); + mlxsw_core_driver_unregister(&mlxsw_sib2_driver); + mlxsw_core_driver_unregister(&mlxsw_sib_driver); +} + +module_init(mlxsw_sib_module_init); +module_exit(mlxsw_sib_module_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Elad Raz "); +MODULE_DESCRIPTION("Mellanox SwitchIB and SwitchIB-2 driver"); +MODULE_ALIAS("mlxsw_switchib2"); +MODULE_DEVICE_TABLE(pci, mlxsw_sib_pci_id_table); +MODULE_DEVICE_TABLE(pci, mlxsw_sib2_pci_id_table); -- cgit v1.2.3 From d46b63494544356ed07ed4f7ec6f8d6edb6ddcf5 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Tue, 25 Oct 2016 18:41:31 +0200 Subject: net: bonding: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index c9944d86d045..5708f17e4cdf 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4080,16 +4080,16 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) return ret; } -static int bond_ethtool_get_settings(struct net_device *bond_dev, - struct ethtool_cmd *ecmd) +static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev, + struct ethtool_link_ksettings *cmd) { struct bonding *bond = netdev_priv(bond_dev); unsigned long speed = 0; struct list_head *iter; struct slave *slave; - ecmd->duplex = DUPLEX_UNKNOWN; - ecmd->port = PORT_OTHER; + cmd->base.duplex = DUPLEX_UNKNOWN; + cmd->base.port = PORT_OTHER; /* Since bond_slave_can_tx returns false for all inactive or down slaves, we * do not need to check mode. Though link speed might not represent @@ -4100,12 +4100,12 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev, if (bond_slave_can_tx(slave)) { if (slave->speed != SPEED_UNKNOWN) speed += slave->speed; - if (ecmd->duplex == DUPLEX_UNKNOWN && + if (cmd->base.duplex == DUPLEX_UNKNOWN && slave->duplex != DUPLEX_UNKNOWN) - ecmd->duplex = slave->duplex; + cmd->base.duplex = slave->duplex; } } - ethtool_cmd_speed_set(ecmd, speed ? : SPEED_UNKNOWN); + cmd->base.speed = speed ? : SPEED_UNKNOWN; return 0; } @@ -4121,8 +4121,8 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, static const struct ethtool_ops bond_ethtool_ops = { .get_drvinfo = bond_ethtool_get_drvinfo, - .get_settings = bond_ethtool_get_settings, .get_link = ethtool_op_get_link, + .get_link_ksettings = bond_ethtool_get_link_ksettings, }; static const struct net_device_ops bond_netdev_ops = { -- cgit v1.2.3 From 6078c651947a148c1de543b54fe55af43a63043a Mon Sep 17 00:00:00 2001 From: James Liao Date: Thu, 20 Oct 2016 16:56:35 +0800 Subject: soc: mediatek: Refine scpsys to support multiple platform Refine scpsys driver common code to support multiple SoC / platform. Signed-off-by: James Liao Reviewed-by: Kevin Hilman Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-scpsys.c | 348 +++++++++++++++++++++++--------------- 1 file changed, 210 insertions(+), 138 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 837effe19907..722aac80e611 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -11,17 +11,15 @@ * GNU General Public License for more details. */ #include -#include +#include #include -#include #include -#include #include #include #include -#include -#include #include +#include + #include #define SPM_VDE_PWR_CON 0x0210 @@ -34,6 +32,7 @@ #define SPM_MFG_2D_PWR_CON 0x02c0 #define SPM_MFG_ASYNC_PWR_CON 0x02c4 #define SPM_USB_PWR_CON 0x02cc + #define SPM_PWR_STATUS 0x060c #define SPM_PWR_STATUS_2ND 0x0610 @@ -55,12 +54,21 @@ #define PWR_STATUS_USB BIT(25) enum clk_id { - MT8173_CLK_NONE, - MT8173_CLK_MM, - MT8173_CLK_MFG, - MT8173_CLK_VENC, - MT8173_CLK_VENC_LT, - MT8173_CLK_MAX, + CLK_NONE, + CLK_MM, + CLK_MFG, + CLK_VENC, + CLK_VENC_LT, + CLK_MAX, +}; + +static const char * const clk_names[] = { + NULL, + "mm", + "mfg", + "venc", + "venc_lt", + NULL, }; #define MAX_CLKS 2 @@ -76,98 +84,6 @@ struct scp_domain_data { bool active_wakeup; }; -static const struct scp_domain_data scp_domain_data[] = { - [MT8173_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = PWR_STATUS_VDEC, - .ctl_offs = SPM_VDE_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {MT8173_CLK_MM}, - }, - [MT8173_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = PWR_STATUS_VENC, - .ctl_offs = SPM_VEN_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC}, - }, - [MT8173_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = PWR_STATUS_ISP, - .ctl_offs = SPM_ISP_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .clk_id = {MT8173_CLK_MM}, - }, - [MT8173_POWER_DOMAIN_MM] = { - .name = "mm", - .sta_mask = PWR_STATUS_DISP, - .ctl_offs = SPM_DIS_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {MT8173_CLK_MM}, - .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | - MT8173_TOP_AXI_PROT_EN_MM_M1, - }, - [MT8173_POWER_DOMAIN_VENC_LT] = { - .name = "venc_lt", - .sta_mask = PWR_STATUS_VENC_LT, - .ctl_offs = SPM_VEN2_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC_LT}, - }, - [MT8173_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = PWR_STATUS_AUDIO, - .ctl_offs = SPM_AUDIO_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {MT8173_CLK_NONE}, - }, - [MT8173_POWER_DOMAIN_USB] = { - .name = "usb", - .sta_mask = PWR_STATUS_USB, - .ctl_offs = SPM_USB_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {MT8173_CLK_NONE}, - .active_wakeup = true, - }, - [MT8173_POWER_DOMAIN_MFG_ASYNC] = { - .name = "mfg_async", - .sta_mask = PWR_STATUS_MFG_ASYNC, - .ctl_offs = SPM_MFG_ASYNC_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = 0, - .clk_id = {MT8173_CLK_MFG}, - }, - [MT8173_POWER_DOMAIN_MFG_2D] = { - .name = "mfg_2d", - .sta_mask = PWR_STATUS_MFG_2D, - .ctl_offs = SPM_MFG_2D_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .clk_id = {MT8173_CLK_NONE}, - }, - [MT8173_POWER_DOMAIN_MFG] = { - .name = "mfg", - .sta_mask = PWR_STATUS_MFG, - .ctl_offs = SPM_MFG_PWR_CON, - .sram_pdn_bits = GENMASK(13, 8), - .sram_pdn_ack_bits = GENMASK(21, 16), - .clk_id = {MT8173_CLK_NONE}, - .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | - MT8173_TOP_AXI_PROT_EN_MFG_M0 | - MT8173_TOP_AXI_PROT_EN_MFG_M1 | - MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, - }, -}; - -#define NUM_DOMAINS ARRAY_SIZE(scp_domain_data) - struct scp; struct scp_domain { @@ -179,7 +95,7 @@ struct scp_domain { }; struct scp { - struct scp_domain domains[NUM_DOMAINS]; + struct scp_domain *domains; struct genpd_onecell_data pd_data; struct device *dev; void __iomem *base; @@ -408,57 +324,55 @@ static bool scpsys_active_wakeup(struct device *dev) return scpd->data->active_wakeup; } -static int scpsys_probe(struct platform_device *pdev) +static void init_clks(struct platform_device *pdev, struct clk **clk) +{ + int i; + + for (i = CLK_NONE + 1; i < CLK_MAX; i++) + clk[i] = devm_clk_get(&pdev->dev, clk_names[i]); +} + +static struct scp *init_scp(struct platform_device *pdev, + const struct scp_domain_data *scp_domain_data, int num) { struct genpd_onecell_data *pd_data; struct resource *res; - int i, j, ret; + int i, j; struct scp *scp; - struct clk *clk[MT8173_CLK_MAX]; + struct clk *clk[CLK_MAX]; scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); if (!scp) - return -ENOMEM; + return ERR_PTR(-ENOMEM); scp->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); scp->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(scp->base)) - return PTR_ERR(scp->base); + return ERR_CAST(scp->base); + + scp->domains = devm_kzalloc(&pdev->dev, + sizeof(*scp->domains) * num, GFP_KERNEL); + if (!scp->domains) + return ERR_PTR(-ENOMEM); pd_data = &scp->pd_data; pd_data->domains = devm_kzalloc(&pdev->dev, - sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL); + sizeof(*pd_data->domains) * num, GFP_KERNEL); if (!pd_data->domains) - return -ENOMEM; - - clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm"); - if (IS_ERR(clk[MT8173_CLK_MM])) - return PTR_ERR(clk[MT8173_CLK_MM]); - - clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg"); - if (IS_ERR(clk[MT8173_CLK_MFG])) - return PTR_ERR(clk[MT8173_CLK_MFG]); - - clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc"); - if (IS_ERR(clk[MT8173_CLK_VENC])) - return PTR_ERR(clk[MT8173_CLK_VENC]); - - clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt"); - if (IS_ERR(clk[MT8173_CLK_VENC_LT])) - return PTR_ERR(clk[MT8173_CLK_VENC_LT]); + return ERR_PTR(-ENOMEM); scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "infracfg"); if (IS_ERR(scp->infracfg)) { dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", PTR_ERR(scp->infracfg)); - return PTR_ERR(scp->infracfg); + return ERR_CAST(scp->infracfg); } - for (i = 0; i < NUM_DOMAINS; i++) { + for (i = 0; i < num; i++) { struct scp_domain *scpd = &scp->domains[i]; const struct scp_domain_data *data = &scp_domain_data[i]; @@ -467,13 +381,15 @@ static int scpsys_probe(struct platform_device *pdev) if (PTR_ERR(scpd->supply) == -ENODEV) scpd->supply = NULL; else - return PTR_ERR(scpd->supply); + return ERR_CAST(scpd->supply); } } - pd_data->num_domains = NUM_DOMAINS; + pd_data->num_domains = num; - for (i = 0; i < NUM_DOMAINS; i++) { + init_clks(pdev, clk); + + for (i = 0; i < num; i++) { struct scp_domain *scpd = &scp->domains[i]; struct generic_pm_domain *genpd = &scpd->genpd; const struct scp_domain_data *data = &scp_domain_data[i]; @@ -482,13 +398,37 @@ static int scpsys_probe(struct platform_device *pdev) scpd->scp = scp; scpd->data = data; - for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) - scpd->clk[j] = clk[data->clk_id[j]]; + + for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) { + struct clk *c = clk[data->clk_id[j]]; + + if (IS_ERR(c)) { + dev_err(&pdev->dev, "%s: clk unavailable\n", + data->name); + return ERR_CAST(c); + } + + scpd->clk[j] = c; + } genpd->name = data->name; genpd->power_off = scpsys_power_off; genpd->power_on = scpsys_power_on; genpd->dev_ops.active_wakeup = scpsys_active_wakeup; + } + + return scp; +} + +static void mtk_register_power_domains(struct platform_device *pdev, + struct scp *scp, int num) +{ + struct genpd_onecell_data *pd_data; + int i, ret; + + for (i = 0; i < num; i++) { + struct scp_domain *scpd = &scp->domains[i]; + struct generic_pm_domain *genpd = &scpd->genpd; /* * Initially turn on all domains to make the domains usable @@ -507,6 +447,123 @@ static int scpsys_probe(struct platform_device *pdev) * valid. */ + pd_data = &scp->pd_data; + + ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); + if (ret) + dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); +} + +/* + * MT8173 power domain support + */ + +static const struct scp_domain_data scp_domain_data_mt8173[] = { + [MT8173_POWER_DOMAIN_VDEC] = { + .name = "vdec", + .sta_mask = PWR_STATUS_VDEC, + .ctl_offs = SPM_VDE_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(12, 12), + .clk_id = {CLK_MM}, + }, + [MT8173_POWER_DOMAIN_VENC] = { + .name = "venc", + .sta_mask = PWR_STATUS_VENC, + .ctl_offs = SPM_VEN_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .clk_id = {CLK_MM, CLK_VENC}, + }, + [MT8173_POWER_DOMAIN_ISP] = { + .name = "isp", + .sta_mask = PWR_STATUS_ISP, + .ctl_offs = SPM_ISP_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(13, 12), + .clk_id = {CLK_MM}, + }, + [MT8173_POWER_DOMAIN_MM] = { + .name = "mm", + .sta_mask = PWR_STATUS_DISP, + .ctl_offs = SPM_DIS_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(12, 12), + .clk_id = {CLK_MM}, + .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | + MT8173_TOP_AXI_PROT_EN_MM_M1, + }, + [MT8173_POWER_DOMAIN_VENC_LT] = { + .name = "venc_lt", + .sta_mask = PWR_STATUS_VENC_LT, + .ctl_offs = SPM_VEN2_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .clk_id = {CLK_MM, CLK_VENC_LT}, + }, + [MT8173_POWER_DOMAIN_AUDIO] = { + .name = "audio", + .sta_mask = PWR_STATUS_AUDIO, + .ctl_offs = SPM_AUDIO_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .clk_id = {CLK_NONE}, + }, + [MT8173_POWER_DOMAIN_USB] = { + .name = "usb", + .sta_mask = PWR_STATUS_USB, + .ctl_offs = SPM_USB_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .clk_id = {CLK_NONE}, + .active_wakeup = true, + }, + [MT8173_POWER_DOMAIN_MFG_ASYNC] = { + .name = "mfg_async", + .sta_mask = PWR_STATUS_MFG_ASYNC, + .ctl_offs = SPM_MFG_ASYNC_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = 0, + .clk_id = {CLK_MFG}, + }, + [MT8173_POWER_DOMAIN_MFG_2D] = { + .name = "mfg_2d", + .sta_mask = PWR_STATUS_MFG_2D, + .ctl_offs = SPM_MFG_2D_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(13, 12), + .clk_id = {CLK_NONE}, + }, + [MT8173_POWER_DOMAIN_MFG] = { + .name = "mfg", + .sta_mask = PWR_STATUS_MFG, + .ctl_offs = SPM_MFG_PWR_CON, + .sram_pdn_bits = GENMASK(13, 8), + .sram_pdn_ack_bits = GENMASK(21, 16), + .clk_id = {CLK_NONE}, + .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | + MT8173_TOP_AXI_PROT_EN_MFG_M0 | + MT8173_TOP_AXI_PROT_EN_MFG_M1 | + MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, + }, +}; + +#define NUM_DOMAINS_MT8173 ARRAY_SIZE(scp_domain_data_mt8173) + +static int __init scpsys_probe_mt8173(struct platform_device *pdev) +{ + struct scp *scp; + struct genpd_onecell_data *pd_data; + int ret; + + scp = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173); + if (IS_ERR(scp)) + return PTR_ERR(scp); + + mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT8173); + + pd_data = &scp->pd_data; + ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC], pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]); if (ret && IS_ENABLED(CONFIG_PM)) @@ -517,21 +574,36 @@ static int scpsys_probe(struct platform_device *pdev) if (ret && IS_ENABLED(CONFIG_PM)) dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); - ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); - if (ret) - dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); - return 0; } +/* + * scpsys driver init + */ + static const struct of_device_id of_scpsys_match_tbl[] = { { .compatible = "mediatek,mt8173-scpsys", + .data = scpsys_probe_mt8173, }, { /* sentinel */ } }; +static int scpsys_probe(struct platform_device *pdev) +{ + int (*probe)(struct platform_device *); + const struct of_device_id *of_id; + + of_id = of_match_node(of_scpsys_match_tbl, pdev->dev.of_node); + if (!of_id || !of_id->data) + return -EINVAL; + + probe = of_id->data; + + return probe(pdev); +} + static struct platform_driver scpsys_drv = { .probe = scpsys_probe, .driver = { -- cgit v1.2.3 From 112ef1882e12094c823937f9d72f2f598db02df7 Mon Sep 17 00:00:00 2001 From: Shunli Wang Date: Thu, 20 Oct 2016 16:56:38 +0800 Subject: soc: mediatek: Add MT2701 scpsys driver Add scpsys driver for MT2701. mtk-scpsys now supports MT8173 (arm64) and MT2701 (arm). So it should be enabled on both arm64 and arm platforms. Signed-off-by: Shunli Wang Signed-off-by: James Liao Reviewed-by: Kevin Hilman Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/Kconfig | 2 +- drivers/soc/mediatek/mtk-scpsys.c | 117 +++++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index 0a4ea809a61b..609bb3424c14 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -23,7 +23,7 @@ config MTK_PMIC_WRAP config MTK_SCPSYS bool "MediaTek SCPSYS Support" depends on ARCH_MEDIATEK || COMPILE_TEST - default ARM64 && ARCH_MEDIATEK + default ARCH_MEDIATEK select REGMAP select MTK_INFRACFG select PM_GENERIC_DOMAINS if PM diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 722aac80e611..beb79162369a 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -20,6 +20,7 @@ #include #include +#include #include #define SPM_VDE_PWR_CON 0x0210 @@ -27,8 +28,13 @@ #define SPM_VEN_PWR_CON 0x0230 #define SPM_ISP_PWR_CON 0x0238 #define SPM_DIS_PWR_CON 0x023c +#define SPM_CONN_PWR_CON 0x0280 #define SPM_VEN2_PWR_CON 0x0298 -#define SPM_AUDIO_PWR_CON 0x029c +#define SPM_AUDIO_PWR_CON 0x029c /* MT8173 */ +#define SPM_BDP_PWR_CON 0x029c /* MT2701 */ +#define SPM_ETH_PWR_CON 0x02a0 +#define SPM_HIF_PWR_CON 0x02a4 +#define SPM_IFR_MSC_PWR_CON 0x02a8 #define SPM_MFG_2D_PWR_CON 0x02c0 #define SPM_MFG_ASYNC_PWR_CON 0x02c4 #define SPM_USB_PWR_CON 0x02cc @@ -42,10 +48,15 @@ #define PWR_ON_2ND_BIT BIT(3) #define PWR_CLK_DIS_BIT BIT(4) +#define PWR_STATUS_CONN BIT(1) #define PWR_STATUS_DISP BIT(3) #define PWR_STATUS_MFG BIT(4) #define PWR_STATUS_ISP BIT(5) #define PWR_STATUS_VDEC BIT(7) +#define PWR_STATUS_BDP BIT(14) +#define PWR_STATUS_ETH BIT(15) +#define PWR_STATUS_HIF BIT(16) +#define PWR_STATUS_IFR_MSC BIT(17) #define PWR_STATUS_VENC_LT BIT(20) #define PWR_STATUS_VENC BIT(21) #define PWR_STATUS_MFG_2D BIT(22) @@ -59,6 +70,7 @@ enum clk_id { CLK_MFG, CLK_VENC, CLK_VENC_LT, + CLK_ETHIF, CLK_MAX, }; @@ -68,6 +80,7 @@ static const char * const clk_names[] = { "mfg", "venc", "venc_lt", + "ethif", NULL, }; @@ -454,6 +467,105 @@ static void mtk_register_power_domains(struct platform_device *pdev, dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); } +/* + * MT2701 power domain support + */ + +static const struct scp_domain_data scp_domain_data_mt2701[] = { + [MT2701_POWER_DOMAIN_CONN] = { + .name = "conn", + .sta_mask = PWR_STATUS_CONN, + .ctl_offs = SPM_CONN_PWR_CON, + .bus_prot_mask = 0x0104, + .clk_id = {CLK_NONE}, + .active_wakeup = true, + }, + [MT2701_POWER_DOMAIN_DISP] = { + .name = "disp", + .sta_mask = PWR_STATUS_DISP, + .ctl_offs = SPM_DIS_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .clk_id = {CLK_MM}, + .bus_prot_mask = 0x0002, + .active_wakeup = true, + }, + [MT2701_POWER_DOMAIN_MFG] = { + .name = "mfg", + .sta_mask = PWR_STATUS_MFG, + .ctl_offs = SPM_MFG_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(12, 12), + .clk_id = {CLK_MFG}, + .active_wakeup = true, + }, + [MT2701_POWER_DOMAIN_VDEC] = { + .name = "vdec", + .sta_mask = PWR_STATUS_VDEC, + .ctl_offs = SPM_VDE_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(12, 12), + .clk_id = {CLK_MM}, + .active_wakeup = true, + }, + [MT2701_POWER_DOMAIN_ISP] = { + .name = "isp", + .sta_mask = PWR_STATUS_ISP, + .ctl_offs = SPM_ISP_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(13, 12), + .clk_id = {CLK_MM}, + .active_wakeup = true, + }, + [MT2701_POWER_DOMAIN_BDP] = { + .name = "bdp", + .sta_mask = PWR_STATUS_BDP, + .ctl_offs = SPM_BDP_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .clk_id = {CLK_NONE}, + .active_wakeup = true, + }, + [MT2701_POWER_DOMAIN_ETH] = { + .name = "eth", + .sta_mask = PWR_STATUS_ETH, + .ctl_offs = SPM_ETH_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .clk_id = {CLK_ETHIF}, + .active_wakeup = true, + }, + [MT2701_POWER_DOMAIN_HIF] = { + .name = "hif", + .sta_mask = PWR_STATUS_HIF, + .ctl_offs = SPM_HIF_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .clk_id = {CLK_ETHIF}, + .active_wakeup = true, + }, + [MT2701_POWER_DOMAIN_IFR_MSC] = { + .name = "ifr_msc", + .sta_mask = PWR_STATUS_IFR_MSC, + .ctl_offs = SPM_IFR_MSC_PWR_CON, + .clk_id = {CLK_NONE}, + .active_wakeup = true, + }, +}; + +#define NUM_DOMAINS_MT2701 ARRAY_SIZE(scp_domain_data_mt2701) + +static int __init scpsys_probe_mt2701(struct platform_device *pdev) +{ + struct scp *scp; + + scp = init_scp(pdev, scp_domain_data_mt2701, NUM_DOMAINS_MT2701); + if (IS_ERR(scp)) + return PTR_ERR(scp); + + mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT2701); + + return 0; +} + /* * MT8173 power domain support */ @@ -583,6 +695,9 @@ static int __init scpsys_probe_mt8173(struct platform_device *pdev) static const struct of_device_id of_scpsys_match_tbl[] = { { + .compatible = "mediatek,mt2701-scpsys", + .data = scpsys_probe_mt2701, + }, { .compatible = "mediatek,mt8173-scpsys", .data = scpsys_probe_mt8173, }, { -- cgit v1.2.3 From 96bb12deadac74ad1053d6bb704aaa33417b85a6 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 28 Oct 2016 15:54:10 +0800 Subject: pinctrl: at91: add support for OUTPUT config Add support for pin output control through the pinctrl config: - support enabling/disabling output on a given pin - support output level setting (high or low) Signed-off-by: Boris BREZILLON Acked-by: Nicolas Ferre Signed-off-by: Wenyou Yang Signed-off-by: Linus Walleij --- .../bindings/pinctrl/atmel,at91-pinctrl.txt | 2 ++ drivers/pinctrl/pinctrl-at91.c | 21 +++++++++++++++++++++ include/dt-bindings/pinctrl/at91.h | 2 ++ 3 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt index b7a93e80a302..9a8a45d9d8ab 100644 --- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt @@ -98,6 +98,8 @@ DRIVE_STRENGTH (3 << 5): indicate the drive strength of the pin using the 01 - Low 10 - Medium 11 - High +OUTPUT (1 << 7): indicate this pin need to be configured as an output. +OUTPUT_VAL (1 << 8): output val (1 = high, 0 = low) DEBOUNCE (1 << 16): indicate this pin needs debounce. DEBOUNCE_VAL (0x3fff << 17): debounce value. diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 9f0904185909..569bc28cb909 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -56,6 +56,9 @@ static int gpio_banks; #define DRIVE_STRENGTH_SHIFT 5 #define DRIVE_STRENGTH_MASK 0x3 #define DRIVE_STRENGTH (DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT) +#define OUTPUT (1 << 7) +#define OUTPUT_VAL_SHIFT 8 +#define OUTPUT_VAL (0x1 << OUTPUT_VAL_SHIFT) #define DEBOUNCE (1 << 16) #define DEBOUNCE_VAL_SHIFT 17 #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT) @@ -375,6 +378,19 @@ static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on) writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR)); } +static bool at91_mux_get_output(void __iomem *pio, unsigned int pin, bool *val) +{ + *val = (readl_relaxed(pio + PIO_ODSR) >> pin) & 0x1; + return (readl_relaxed(pio + PIO_OSR) >> pin) & 0x1; +} + +static void at91_mux_set_output(void __iomem *pio, unsigned int mask, + bool is_on, bool val) +{ + writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR)); + writel_relaxed(mask, pio + (is_on ? PIO_OER : PIO_ODR)); +} + static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin) { return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1; @@ -848,6 +864,7 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, void __iomem *pio; unsigned pin; int div; + bool out; *config = 0; dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id); @@ -875,6 +892,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, if (info->ops->get_drivestrength) *config |= (info->ops->get_drivestrength(pio, pin) << DRIVE_STRENGTH_SHIFT); + if (at91_mux_get_output(pio, pin, &out)) + *config |= OUTPUT | (out << OUTPUT_VAL_SHIFT); return 0; } @@ -907,6 +926,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, if (config & PULL_UP && config & PULL_DOWN) return -EINVAL; + at91_mux_set_output(pio, mask, config & OUTPUT, + (config & OUTPUT_VAL) >> OUTPUT_VAL_SHIFT); at91_mux_set_pullup(pio, mask, config & PULL_UP); at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE); if (info->ops->set_deglitch) diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h index bbca3d038900..2732d6c0fb39 100644 --- a/include/dt-bindings/pinctrl/at91.h +++ b/include/dt-bindings/pinctrl/at91.h @@ -15,6 +15,8 @@ #define AT91_PINCTRL_DEGLITCH (1 << 2) #define AT91_PINCTRL_PULL_DOWN (1 << 3) #define AT91_PINCTRL_DIS_SCHMIT (1 << 4) +#define AT91_PINCTRL_OUTPUT (1 << 7) +#define AT91_PINCTRL_OUTPUT_VAL(x) ((x & 0x1) << 8) #define AT91_PINCTRL_DEBOUNCE (1 << 16) #define AT91_PINCTRL_DEBOUNCE_VAL(x) (x << 17) -- cgit v1.2.3 From 1b6998c96ccc60a61bdb812b4a55866224ab9708 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 29 Oct 2016 16:11:57 +0000 Subject: ACPI / gpio: add missing fwnode_handle_put() in acpi_gpiochip_scan_gpios() fwnode_handle_put() should be used when terminating device_for_each_child_node() iteration with break or return to prevent stale device node references from being left behind. This is detected by Coccinelle semantic patch. Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 53266ef12008..aa879d5eaa19 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -922,6 +922,7 @@ static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip) ret = gpiod_hog(desc, name, lflags, dflags); if (ret) { dev_err(chip->parent, "Failed to hog GPIO\n"); + fwnode_handle_put(fwnode); return; } } -- cgit v1.2.3 From 550a9532b8093ef554947e5d24b469ffb1ff9930 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 29 Oct 2016 16:13:12 +0000 Subject: ACPI / gpio: make acpi_gpiochip_parse_own_gpio static Fixes the following sparse warning: drivers/gpio/gpiolib-acpi.c:863:18: warning: symbol 'acpi_gpiochip_parse_own_gpio' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index aa879d5eaa19..83fcfff19cd6 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -857,9 +857,9 @@ static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip) } } -struct gpio_desc *acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip, - struct fwnode_handle *fwnode, const char **name, unsigned int *lflags, - unsigned int *dflags) +static struct gpio_desc *acpi_gpiochip_parse_own_gpio( + struct acpi_gpio_chip *achip, struct fwnode_handle *fwnode, + const char **name, unsigned int *lflags, unsigned int *dflags) { struct gpio_chip *chip = achip->chip; struct gpio_desc *desc; -- cgit v1.2.3 From 09e258af4edaa10ee9aa3164923ee07d5863d637 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 29 Oct 2016 16:13:52 +0000 Subject: gpio: of: add missing of_node_put() in of_gpiochip_scan_gpios() When terminating for_each_available_child_of_node() iteration with break or return, of_node_put() should be used to prevent stale device node references from being left behind. This is detected by Coccinelle semantic patch. Signed-off-by: Wei Yongjun Reviewed-by: Vladimir Zapolskiy Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 3fa4e84b4327..5236966b1bdf 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -247,8 +247,10 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) continue; ret = gpiod_hog(desc, name, lflags, dflags); - if (ret < 0) + if (ret < 0) { + of_node_put(np); return ret; + } } return 0; -- cgit v1.2.3 From e8f29bb719b47a234f33b0af62974d7a9521a52c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 10:38:11 +0300 Subject: usb: gadget: composite: correctly initialize ep->maxpacket usb_endpoint_maxp() returns wMaxPacketSize in its raw form. Without taking into consideration that it also contains other bits reserved for isochronous endpoints. This patch fixes one occasion where this is a problem by making sure that we initialize ep->maxpacket only with lower 10 bits of the value returned by usb_endpoint_maxp(). Note that seperate patches will be necessary to audit all call sites of usb_endpoint_maxp() and make sure that usb_endpoint_maxp() only returns lower 10 bits of wMaxPacketSize. Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 32176f779861..f6a7583ab6d1 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -197,7 +197,7 @@ int config_ep_by_speed(struct usb_gadget *g, ep_found: /* commit results */ - _ep->maxpacket = usb_endpoint_maxp(chosen_desc); + _ep->maxpacket = usb_endpoint_maxp(chosen_desc) & 0x7ff; _ep->desc = chosen_desc; _ep->comp_desc = NULL; _ep->maxburst = 0; -- cgit v1.2.3 From eaa496ffaaf19591fe471a36cef366146eeb9153 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 12:33:31 +0300 Subject: usb: gadget: composite: always set ep->mult to a sensible value ep->mult is supposed to be set to Isochronous and Interrupt Endapoint's multiplier value. This value is computed from different places depending on the link speed. If we're dealing with HighSpeed, then it's part of bits [12:11] of wMaxPacketSize. This case wasn't taken into consideration before. While at that, also make sure the ep->mult defaults to one so drivers can use it unconditionally and assume they'll never multiply ep->maxpacket to zero. Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 9 +++++++-- drivers/usb/gadget/function/uvc_video.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index f6a7583ab6d1..0426d3c1fff9 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -201,7 +201,12 @@ ep_found: _ep->desc = chosen_desc; _ep->comp_desc = NULL; _ep->maxburst = 0; - _ep->mult = 0; + _ep->mult = 1; + + if (g->speed == USB_SPEED_HIGH && (usb_endpoint_xfer_isoc(_ep->desc) || + usb_endpoint_xfer_int(_ep->desc))) + _ep->mult = usb_endpoint_maxp_mult(_ep->desc); + if (!want_comp_desc) return 0; @@ -218,7 +223,7 @@ ep_found: switch (usb_endpoint_type(_ep->desc)) { case USB_ENDPOINT_XFER_ISOC: /* mult: bits 1:0 of bmAttributes */ - _ep->mult = comp_desc->bmAttributes & 0x3; + _ep->mult = (comp_desc->bmAttributes & 0x3) + 1; case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_INT: _ep->maxburst = comp_desc->bMaxBurst + 1; diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 3d0d5d94a62f..0f01c04d7cbd 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -243,7 +243,7 @@ uvc_video_alloc_requests(struct uvc_video *video) req_size = video->ep->maxpacket * max_t(unsigned int, video->ep->maxburst, 1) - * (video->ep->mult + 1); + * (video->ep->mult); for (i = 0; i < UVC_NUM_REQUESTS; ++i) { video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL); -- cgit v1.2.3 From 6b9018d4c1e5c958625be94a160a5984351d4632 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 22 Sep 2016 11:01:01 +0300 Subject: usb: dwc3: gadget: set PCM1 field of isochronous-first TRBs In case of High-Speed, High-Bandwidth endpoints, we need to tell DWC3 that we have more than one packet per interval. We do that by setting PCM1 field of Isochronous-First TRB. Cc: Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1dfa56a5f1c5..b3687e223e00 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -771,6 +771,9 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, unsigned length, unsigned chain, unsigned node) { struct dwc3_trb *trb; + struct dwc3 *dwc = dep->dwc; + struct usb_gadget *gadget = &dwc->gadget; + enum usb_device_speed speed = gadget->speed; dwc3_trace(trace_dwc3_gadget, "%s: req %p dma %08llx length %d%s", dep->name, req, (unsigned long long) dma, @@ -798,10 +801,16 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, break; case USB_ENDPOINT_XFER_ISOC: - if (!node) + if (!node) { trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; - else + + if (speed == USB_SPEED_HIGH) { + struct usb_ep *ep = &dep->endpoint; + trb->size |= DWC3_TRB_SIZE_PCM1(ep->mult - 1); + } + } else { trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS; + } /* always enable Interrupt on Missed ISOC */ trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; -- cgit v1.2.3 From 5999914f227b20addf01297b3df24be6b4161f69 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 22 Sep 2016 12:25:28 +0300 Subject: usb: dwc3: gadget: properly check ep cmd The cmd argument we pass to dwc3_send_gadget_ep_cmd() could contain extra arguments embedded. When checking for StartTransfer command, we need to make sure to match only lower 4 bits which contain the actual command and ignore the rest. Reported-by: Janusz Dziedzic Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/gadget.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6b60e42626a2..99fa8b8b06fe 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -450,6 +450,8 @@ #define DWC3_DEPCMD_SETTRANSFRESOURCE (0x02 << 0) #define DWC3_DEPCMD_SETEPCONFIG (0x01 << 0) +#define DWC3_DEPCMD_CMD(x) ((x) & 0xf) + /* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ #define DWC3_DALEPENA_EP(n) (1 << n) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index b3687e223e00..4ed8b34540f2 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -258,7 +258,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, } } - if (cmd == DWC3_DEPCMD_STARTTRANSFER) { + if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { int needs_wakeup; needs_wakeup = (dwc->link_state == DWC3_LINK_STATE_U1 || -- cgit v1.2.3 From 8897a761c371ceefda98570953185daa3c059ad1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 22 Sep 2016 10:56:08 +0300 Subject: usb: dwc3: gadget: make use of No Response Update Transfer No Response Update Transfer is a special type of Update Transfer command which can be used whenever we're not relying on XferNotReady to prepare transfers. With this, we don't need to wait for CMDACT to be cleared and issue further commands to the endpoint straight away. Let's start using this version to skip the long-ish wait. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4ed8b34540f2..45782d7ec67b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -233,6 +233,7 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc); int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, struct dwc3_gadget_ep_cmd_params *params) { + const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; struct dwc3 *dwc = dep->dwc; u32 timeout = 500; u32 reg; @@ -276,7 +277,28 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1); dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2); - dwc3_writel(dep->regs, DWC3_DEPCMD, cmd | DWC3_DEPCMD_CMDACT); + /* + * Synopsys Databook 2.60a states in section 6.3.2.5.6 of that if we're + * not relying on XferNotReady, we can make use of a special "No + * Response Update Transfer" command where we should clear both CmdAct + * and CmdIOC bits. + * + * With this, we don't need to wait for command completion and can + * straight away issue further commands to the endpoint. + * + * NOTICE: We're making an assumption that control endpoints will never + * make use of Update Transfer command. This is a safe assumption + * because we can never have more than one request at a time with + * Control Endpoints. If anybody changes that assumption, this chunk + * needs to be updated accordingly. + */ + if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_UPDATETRANSFER && + !usb_endpoint_xfer_isoc(desc)) + cmd &= ~(DWC3_DEPCMD_CMDIOC | DWC3_DEPCMD_CMDACT); + else + cmd |= DWC3_DEPCMD_CMDACT; + + dwc3_writel(dep->regs, DWC3_DEPCMD, cmd); do { reg = dwc3_readl(dep->regs, DWC3_DEPCMD); if (!(reg & DWC3_DEPCMD_CMDACT)) { -- cgit v1.2.3 From 15b8d9332b927d76a0b26cf70c564756d1648133 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 22 Sep 2016 10:59:12 +0300 Subject: usb: dwc3: gadget: giveback request if we can't kick it There might be situations where a Start Transfer command might fail, if that ever happens, instead of simply removing the request from our list, we should give the request back to the gadget driver, otherwise we might eventually starve it from requests. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 45782d7ec67b..99ad3ca498aa 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -987,7 +987,6 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param) { struct dwc3_gadget_ep_cmd_params params; struct dwc3_request *req; - struct dwc3 *dwc = dep->dwc; int starting; int ret; u32 cmd; @@ -1020,9 +1019,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param) * here and stop, unmap, free and del each of the linked * requests instead of what we do now. */ - usb_gadget_unmap_request(&dwc->gadget, &req->request, - req->direction); - list_del(&req->list); + dwc3_gadget_giveback(dep, req, ret); return ret; } -- cgit v1.2.3 From 799e9dc82968c66d6f8faf96d0bd01e515b0b2f2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 23 Sep 2016 11:20:40 +0300 Subject: usb: dwc3: gadget: conditionally disable Link State change events Link State Change events are only needed for debugging and to apply certain workarounds on known errata. Let's save a few cycles by disabling these events completely on working revisions of the core. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 99ad3ca498aa..ee949420ee26 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1537,11 +1537,13 @@ static void dwc3_gadget_enable_irq(struct dwc3 *dwc) DWC3_DEVTEN_CMDCMPLTEN | DWC3_DEVTEN_ERRTICERREN | DWC3_DEVTEN_WKUPEVTEN | - DWC3_DEVTEN_ULSTCNGEN | DWC3_DEVTEN_CONNECTDONEEN | DWC3_DEVTEN_USBRSTEN | DWC3_DEVTEN_DISCONNEVTEN); + if (dwc->revision < DWC3_REVISION_250A) + reg |= DWC3_DEVTEN_ULSTCNGEN; + dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); } -- cgit v1.2.3 From 45a2af2f2b5af38743024a2a4fc154e2be93bd20 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 26 Sep 2016 12:54:04 +0300 Subject: usb: dwc3: debug: decode control endpoint phase too DWC3 can tell us which phase of a setup transfer we're getting into. Let's decode it from the event to make it easier to debug. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/debug.h | 13 +++++++++++++ 2 files changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 99fa8b8b06fe..18e4c09ae286 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1041,6 +1041,7 @@ struct dwc3_event_depevt { /* Control-only Status */ #define DEPEVT_STATUS_CONTROL_DATA 1 #define DEPEVT_STATUS_CONTROL_STATUS 2 +#define DEPEVT_STATUS_CONTROL_PHASE(n) ((n) & 3) /* In response to Start Transfer */ #define DEPEVT_TRANSFER_NO_RESOURCE 1 diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index 33ab2a203c1b..fe8abee31551 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -207,6 +207,19 @@ dwc3_ep_event_string(const struct dwc3_event_depevt *event) strcat(str, "Transfer Not Ready"); status = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE; strcat(str, status ? " (Active)" : " (Not Active)"); + + /* Control Endpoints */ + if (epnum <= 1) { + int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status); + + switch (phase) { + case DEPEVT_STATUS_CONTROL_DATA: + strcat(str, " [Data Phase]"); + break; + case DEPEVT_STATUS_CONTROL_STATUS: + strcat(str, " [Status Phase]"); + } + } break; case DWC3_DEPEVT_RXTXFIFOEVT: strcat(str, "FIFO"); -- cgit v1.2.3 From 8566cd1adf295d5b94e0ba9b4ae66d89c50542d5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 26 Sep 2016 11:16:39 +0300 Subject: usb: dwc3: gadget: remove redundant trace prints Removing some trace prints which were made redundant when we started decoding events and TRBs completely within their respective trace points. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 17 +---------------- drivers/usb/dwc3/gadget.c | 43 +------------------------------------------ 2 files changed, 2 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index fe79d771dee4..2d2f582068cb 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -99,11 +99,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, trace_dwc3_prepare_trb(dep, trb); ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, ¶ms); - if (ret < 0) { - dwc3_trace(trace_dwc3_ep0, "%s STARTTRANSFER failed", - dep->name); + if (ret < 0) return ret; - } dep->flags |= DWC3_EP_BUSY; dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep); @@ -242,11 +239,6 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, goto out; } - dwc3_trace(trace_dwc3_ep0, - "queueing request %p to %s length %d state '%s'", - request, dep->name, request->length, - dwc3_ep0_state_string(dwc->ep0state)); - ret = __dwc3_gadget_ep0_queue(dep, req); out: @@ -940,17 +932,14 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, switch (dwc->ep0state) { case EP0_SETUP_PHASE: - dwc3_trace(trace_dwc3_ep0, "Setup Phase"); dwc3_ep0_inspect_setup(dwc, event); break; case EP0_DATA_PHASE: - dwc3_trace(trace_dwc3_ep0, "Data Phase"); dwc3_ep0_complete_data(dwc, event); break; case EP0_STATUS_PHASE: - dwc3_trace(trace_dwc3_ep0, "Status Phase"); dwc3_ep0_complete_status(dwc, event); break; default: @@ -1065,8 +1054,6 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, { switch (event->status) { case DEPEVT_STATUS_CONTROL_DATA: - dwc3_trace(trace_dwc3_ep0, "Control Data"); - /* * We already have a DATA transfer in the controller's cache, * if we receive a XferNotReady(DATA) we will ignore it, unless @@ -1092,8 +1079,6 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) return; - dwc3_trace(trace_dwc3_ep0, "Control Status"); - dwc->ep0state = EP0_STATUS_PHASE; if (dwc->delayed_status) { diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index ee949420ee26..fb5d65a58ef8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -797,10 +797,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, struct usb_gadget *gadget = &dwc->gadget; enum usb_device_speed speed = gadget->speed; - dwc3_trace(trace_dwc3_gadget, "%s: req %p dma %08llx length %d%s", - dep->name, req, (unsigned long long) dma, - length, chain ? " chain" : ""); - trb = &dep->trb_pool[dep->trb_enqueue]; if (!req->trb) { @@ -2142,9 +2138,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dep->resource_index = 0; if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - dwc3_trace(trace_dwc3_gadget, - "%s is an Isochronous endpoint", - dep->name); + dev_err(dwc->dev, "XferComplete for Isochronous endpoint\n"); return; } @@ -2157,22 +2151,11 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dwc3_gadget_start_isoc(dwc, dep, event); } else { - int active; int ret; - active = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE; - - dwc3_trace(trace_dwc3_gadget, "%s: reason %s", - dep->name, active ? "Transfer Active" - : "Transfer Not Active"); - ret = __dwc3_gadget_kick_transfer(dep, 0); if (!ret || ret == -EBUSY) return; - - dwc3_trace(trace_dwc3_gadget, - "%s: failed to kick transfers", - dep->name); } break; @@ -2182,26 +2165,9 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dep->name); return; } - - switch (event->status) { - case DEPEVT_STREAMEVT_FOUND: - dwc3_trace(trace_dwc3_gadget, - "Stream %d found and started", - event->parameters); - - break; - case DEPEVT_STREAMEVT_NOTFOUND: - /* FALLTHROUGH */ - default: - dwc3_trace(trace_dwc3_gadget, - "unable to find suitable stream"); - } break; case DWC3_DEPEVT_RXTXFIFOEVT: - dwc3_trace(trace_dwc3_gadget, "%s FIFO Overrun", dep->name); - break; case DWC3_DEPEVT_EPCMDCMPLT: - dwc3_trace(trace_dwc3_gadget, "Endpoint Command Complete"); break; } } @@ -2750,16 +2716,9 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc, } break; case DWC3_DEVICE_EVENT_SOF: - dwc3_trace(trace_dwc3_gadget, "Start of Periodic Frame"); - break; case DWC3_DEVICE_EVENT_ERRATIC_ERROR: - dwc3_trace(trace_dwc3_gadget, "Erratic Error"); - break; case DWC3_DEVICE_EVENT_CMD_CMPL: - dwc3_trace(trace_dwc3_gadget, "Command Complete"); - break; case DWC3_DEVICE_EVENT_OVERFLOW: - dwc3_trace(trace_dwc3_gadget, "Overflow"); break; default: dev_WARN(dwc->dev, "UNKNOWN IRQ %d\n", event->type); -- cgit v1.2.3 From cdd72ac20b4a769ad2aaf98223f853c719c5eda7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 26 Sep 2016 13:22:21 +0300 Subject: usb: dwc3: debug: move dwc3_ep0_state_string() to debug.h We will be using dwc3_ep0_state_string() from within our tracepoints, so we need to move that helper to debug.h in order for it to be accessible. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debug.h | 16 ++++++++++++++++ drivers/usb/dwc3/ep0.c | 16 ---------------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index fe8abee31551..61b6f0f207cf 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -124,6 +124,22 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state) } } +static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) +{ + switch (state) { + case EP0_UNCONNECTED: + return "Unconnected"; + case EP0_SETUP_PHASE: + return "Setup Phase"; + case EP0_DATA_PHASE: + return "Data Phase"; + case EP0_STATUS_PHASE: + return "Status Phase"; + default: + return "UNKNOWN"; + } +} + /** * dwc3_gadget_event_string - returns event name * @event: the event code diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2d2f582068cb..1be54712147e 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -39,22 +39,6 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep); static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_request *req); -static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) -{ - switch (state) { - case EP0_UNCONNECTED: - return "Unconnected"; - case EP0_SETUP_PHASE: - return "Setup Phase"; - case EP0_DATA_PHASE: - return "Data Phase"; - case EP0_STATUS_PHASE: - return "Status Phase"; - default: - return "UNKNOWN"; - } -} - static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, u32 len, u32 type, bool chain) { -- cgit v1.2.3 From 43c96be1c46eb6ce292643f659221c7fca90bb84 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 26 Sep 2016 13:23:34 +0300 Subject: usb: dwc3: trace: print out ep0state also from XferComplete With this extra piece of information, it will be easier to find mismatches between driver and HW. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debug.h | 11 ++++++++--- drivers/usb/dwc3/ep0.c | 4 ---- drivers/usb/dwc3/gadget.c | 2 +- drivers/usb/dwc3/trace.h | 12 +++++++----- 4 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index 61b6f0f207cf..b287fc6ab29e 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -200,10 +200,11 @@ dwc3_gadget_event_string(const struct dwc3_event_devt *event) * @event: then event code */ static inline const char * -dwc3_ep_event_string(const struct dwc3_event_depevt *event) +dwc3_ep_event_string(const struct dwc3_event_depevt *event, u32 ep0state) { u8 epnum = event->endpoint_number; static char str[256]; + size_t len; int status; int ret; @@ -215,6 +216,10 @@ dwc3_ep_event_string(const struct dwc3_event_depevt *event) switch (event->endpoint_event) { case DWC3_DEPEVT_XFERCOMPLETE: strcat(str, "Transfer Complete"); + len = strlen(str); + + if (epnum <= 1) + sprintf(str + len, " [%s]", dwc3_ep0_state_string(ep0state)); break; case DWC3_DEPEVT_XFERINPROGRESS: strcat(str, "Transfer In-Progress"); @@ -299,14 +304,14 @@ static inline const char *dwc3_gadget_event_type_string(u8 event) } } -static inline const char *dwc3_decode_event(u32 event) +static inline const char *dwc3_decode_event(u32 event, u32 ep0state) { const union dwc3_event evt = (union dwc3_event) event; if (evt.type.is_devspec) return dwc3_gadget_event_string(&evt.devt); else - return dwc3_ep_event_string(&evt.depevt); + return dwc3_ep_event_string(&evt.depevt, ep0state); } static inline const char *dwc3_ep_cmd_status_string(int status) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 1be54712147e..c562613ccd1a 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -1078,10 +1078,6 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, void dwc3_ep0_interrupt(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { - dwc3_trace(trace_dwc3_ep0, "%s: state '%s'", - dwc3_ep_event_string(event), - dwc3_ep0_state_string(dwc->ep0state)); - switch (event->endpoint_event) { case DWC3_DEPEVT_XFERCOMPLETE: dwc3_ep0_xfer_complete(dwc, event); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fb5d65a58ef8..4d191c8acb59 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2728,7 +2728,7 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc, static void dwc3_process_event_entry(struct dwc3 *dwc, const union dwc3_event *event) { - trace_dwc3_event(event->raw); + trace_dwc3_event(event->raw, dwc); /* Endpoint IRQ, handle it and return early */ if (event->type.is_devspec == 0) { diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index d24cefd191b5..a4ef5e7bf6b8 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -63,21 +63,23 @@ DEFINE_EVENT(dwc3_log_msg, dwc3_ep0, ); DECLARE_EVENT_CLASS(dwc3_log_event, - TP_PROTO(u32 event), - TP_ARGS(event), + TP_PROTO(u32 event, struct dwc3 *dwc), + TP_ARGS(event, dwc), TP_STRUCT__entry( __field(u32, event) + __field(u32, ep0state) ), TP_fast_assign( __entry->event = event; + __entry->ep0state = dwc->ep0state; ), TP_printk("event (%08x): %s", __entry->event, - dwc3_decode_event(__entry->event)) + dwc3_decode_event(__entry->event, __entry->ep0state)) ); DEFINE_EVENT(dwc3_log_event, dwc3_event, - TP_PROTO(u32 event), - TP_ARGS(event) + TP_PROTO(u32 event, struct dwc3 *dwc), + TP_ARGS(event, dwc) ); DECLARE_EVENT_CLASS(dwc3_log_ctrl, -- cgit v1.2.3 From b72b7979c356f06a85ac1de03e5086b5bf461702 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:20:17 +0300 Subject: media: usbtv: core: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Cc: Mauro Carvalho Chehab Cc: Signed-off-by: Felipe Balbi --- drivers/media/usb/usbtv/usbtv-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c index dc76fd41e00f..ceb953be0770 100644 --- a/drivers/media/usb/usbtv/usbtv-core.c +++ b/drivers/media/usb/usbtv/usbtv-core.c @@ -71,6 +71,7 @@ static int usbtv_probe(struct usb_interface *intf, int size; struct device *dev = &intf->dev; struct usbtv *usbtv; + struct usb_host_endpoint *ep; /* Checks that the device is what we think it is. */ if (intf->num_altsetting != 2) @@ -78,10 +79,12 @@ static int usbtv_probe(struct usb_interface *intf, if (intf->altsetting[1].desc.bNumEndpoints != 4) return -ENODEV; + ep = &intf->altsetting[1].endpoint[0]; + /* Packet size is split into 11 bits of base size and count of * extra multiplies of it.*/ - size = usb_endpoint_maxp(&intf->altsetting[1].endpoint[0].desc); - size = (size & 0x07ff) * (((size & 0x1800) >> 11) + 1); + size = usb_endpoint_maxp(&ep->desc); + size = (size & 0x07ff) * usb_endpoint_maxp_mult(&ep->desc); /* Device structure */ usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL); -- cgit v1.2.3 From d3f45647a427ddbb7ac763ed512eab8b809443e8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 4 Oct 2016 15:26:47 -0300 Subject: genwqe: use pci_irq_allocate_vectors Simply the interrupt setup by using the new PCI layer helpers. One odd thing about this driver is that it looks like it could request multiple MSI vectors, but it will then only ever use a single one. Signed-off-by: Christoph Hellwig Acked-by: Gabriel Krisman Bertazi Acked-by: Frank Haverkamp = Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_base.h | 1 - drivers/misc/genwqe/card_utils.c | 12 ++---------- 2 files changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h index cb851c14ca4b..5813b5f25006 100644 --- a/drivers/misc/genwqe/card_base.h +++ b/drivers/misc/genwqe/card_base.h @@ -41,7 +41,6 @@ #include "genwqe_driver.h" #define GENWQE_MSI_IRQS 4 /* Just one supported, no MSIx */ -#define GENWQE_FLAG_MSI_ENABLED (1 << 0) #define GENWQE_MAX_VFS 15 /* maximum 15 VFs are possible */ #define GENWQE_MAX_FUNCS 16 /* 1 PF and 15 VFs */ diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index fc2794b513fa..147b83011b58 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -740,13 +740,10 @@ int genwqe_read_softreset(struct genwqe_dev *cd) int genwqe_set_interrupt_capability(struct genwqe_dev *cd, int count) { int rc; - struct pci_dev *pci_dev = cd->pci_dev; - rc = pci_enable_msi_range(pci_dev, 1, count); + rc = pci_alloc_irq_vectors(cd->pci_dev, 1, count, PCI_IRQ_MSI); if (rc < 0) return rc; - - cd->flags |= GENWQE_FLAG_MSI_ENABLED; return 0; } @@ -756,12 +753,7 @@ int genwqe_set_interrupt_capability(struct genwqe_dev *cd, int count) */ void genwqe_reset_interrupt_capability(struct genwqe_dev *cd) { - struct pci_dev *pci_dev = cd->pci_dev; - - if (cd->flags & GENWQE_FLAG_MSI_ENABLED) { - pci_disable_msi(pci_dev); - cd->flags &= ~GENWQE_FLAG_MSI_ENABLED; - } + pci_free_irq_vectors(cd->pci_dev); } /** -- cgit v1.2.3 From 88d1bece891f85523048de208906258d63678d11 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 30 Oct 2016 01:42:18 +0200 Subject: mei: show the HBM protocol versions in the device attributes The HBM protocol version is negotiated during the setup phase, then settled on a highest possible common version of the driver and the firmware. The sysfs API advertises both negotiated and driver supported versions in the device attributes. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-class-mei | 16 ++++++++++++ drivers/misc/mei/main.c | 43 ++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-class-mei b/Documentation/ABI/testing/sysfs-class-mei index 80d9888a8ece..5096a82f4cde 100644 --- a/Documentation/ABI/testing/sysfs-class-mei +++ b/Documentation/ABI/testing/sysfs-class-mei @@ -29,3 +29,19 @@ Description: Display fw status registers content Also number of registers varies between 1 and 6 depending on generation. +What: /sys/class/mei/meiN/hbm_ver +Date: Aug 2016 +KernelVersion: 4.9 +Contact: Tomas Winkler +Description: Display the negotiated HBM protocol version. + + The HBM protocol version negotiated + between the driver and the device. + +What: /sys/class/mei/meiN/hbm_ver_drv +Date: Aug 2016 +KernelVersion: 4.9 +Contact: Tomas Winkler +Description: Display the driver HBM protocol version. + + The HBM protocol version supported by the driver. diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index fa50635512e8..a1484574cfa8 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -653,7 +653,7 @@ static int mei_fasync(int fd, struct file *file, int band) } /** - * fw_status_show - mei device attribute show method + * fw_status_show - mei device fw_status attribute show method * * @device: device pointer * @attr: attribute pointer @@ -684,8 +684,49 @@ static ssize_t fw_status_show(struct device *device, } static DEVICE_ATTR_RO(fw_status); +/** + * hbm_ver_show - display HBM protocol version negotiated with FW + * + * @device: device pointer + * @attr: attribute pointer + * @buf: char out buffer + * + * Return: number of the bytes printed into buf or error + */ +static ssize_t hbm_ver_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct mei_device *dev = dev_get_drvdata(device); + struct hbm_version ver; + + mutex_lock(&dev->device_lock); + ver = dev->version; + mutex_unlock(&dev->device_lock); + + return sprintf(buf, "%u.%u\n", ver.major_version, ver.minor_version); +} +static DEVICE_ATTR_RO(hbm_ver); + +/** + * hbm_ver_drv_show - display HBM protocol version advertised by driver + * + * @device: device pointer + * @attr: attribute pointer + * @buf: char out buffer + * + * Return: number of the bytes printed into buf or error + */ +static ssize_t hbm_ver_drv_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u.%u\n", HBM_MAJOR_VERSION, HBM_MINOR_VERSION); +} +static DEVICE_ATTR_RO(hbm_ver_drv); + static struct attribute *mei_attrs[] = { &dev_attr_fw_status.attr, + &dev_attr_hbm_ver.attr, + &dev_attr_hbm_ver_drv.attr, NULL }; ATTRIBUTE_GROUPS(mei); -- cgit v1.2.3 From d882039e7617a654161cf03db444e13a2e2554db Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 30 Oct 2016 01:42:19 +0200 Subject: mei: bus: demote error to debug level upon disconnect A mei client driver on the mei client bus can call disconnect function on already internal disconnected client. A client can disconnect internally, for example, during link reset or upon FW request. Those are legitimate flows and we should not log an error message, hence we demote 'Already disconnected' message to the debug level. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 89a694ca624c..8a1e813a548d 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -481,7 +481,7 @@ int mei_cldev_disable(struct mei_cl_device *cldev) mutex_lock(&bus->device_lock); if (!mei_cl_is_connected(cl)) { - dev_err(bus->dev, "Already disconnected"); + dev_dbg(bus->dev, "Already disconnected"); err = 0; goto out; } -- cgit v1.2.3 From 90731c24d2db7ec04df43ddbcee9605183d05187 Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Mon, 24 Oct 2016 15:27:59 +0100 Subject: drm/i2c: tda998x: mali-dp: hdlcd: refactor connector registration Connectors shouldn't be registered until the rest of the whole device is set up, so that consistent state is presented to userspace. As such, remove the calls to drm_connector_register() and drm_connector_unregister() from tda998x, as these are now handled by drm_dev_(un)register() itself. To work with this change, the mali-dp and hdlcd bind and unbind sequences have to be reordered, to ensure that the componentised encoder/connector is bound before drm_dev_register() registers all connectors. Similarly, the device must be unregistered before the component is unbound. Altogether, this allows other drivers using tda998x to be de-midlayered, and to have less racy initialisation of their components. Splitting this commit into three (one per driver) isn't possible without intermediate breakage, so it is all squashed together here. Suggested-by: Russell King Signed-off-by: Brian Starkey Reviewed-by: Liviu Dudau Signed-off-by: Russell King --- drivers/gpu/drm/arm/hdlcd_drv.c | 19 +++++++++++-------- drivers/gpu/drm/arm/malidp_drv.c | 18 +++++++++++------- drivers/gpu/drm/i2c/tda998x_drv.c | 8 -------- 3 files changed, 22 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index d83b46a30327..85aec8b86d89 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -337,14 +337,10 @@ static int hdlcd_drm_bind(struct device *dev) if (ret) goto err_free; - ret = drm_dev_register(drm, 0); - if (ret) - goto err_unload; - ret = component_bind_all(dev, drm); if (ret) { DRM_ERROR("Failed to bind all components\n"); - goto err_unregister; + goto err_unload; } ret = pm_runtime_set_active(dev); @@ -371,8 +367,17 @@ static int hdlcd_drm_bind(struct device *dev) goto err_fbdev; } + ret = drm_dev_register(drm, 0); + if (ret) + goto err_register; + return 0; +err_register: + if (hdlcd->fbdev) { + drm_fbdev_cma_fini(hdlcd->fbdev); + hdlcd->fbdev = NULL; + } err_fbdev: drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); @@ -381,8 +386,6 @@ err_vblank: pm_runtime_disable(drm->dev); err_pm_active: component_unbind_all(dev, drm); -err_unregister: - drm_dev_unregister(drm); err_unload: drm_irq_uninstall(drm); of_reserved_mem_device_release(drm->dev); @@ -398,6 +401,7 @@ static void hdlcd_drm_unbind(struct device *dev) struct drm_device *drm = dev_get_drvdata(dev); struct hdlcd_drm_private *hdlcd = drm->dev_private; + drm_dev_unregister(drm); if (hdlcd->fbdev) { drm_fbdev_cma_fini(hdlcd->fbdev); hdlcd->fbdev = NULL; @@ -411,7 +415,6 @@ static void hdlcd_drm_unbind(struct device *dev) pm_runtime_disable(drm->dev); of_reserved_mem_device_release(drm->dev); drm_mode_config_cleanup(drm); - drm_dev_unregister(drm); drm_dev_unref(drm); drm->dev_private = NULL; dev_set_drvdata(dev, NULL); diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 82171d223f2d..79bfc1360a1b 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -354,10 +354,6 @@ static int malidp_bind(struct device *dev) if (ret < 0) goto init_fail; - ret = drm_dev_register(drm, 0); - if (ret) - goto register_fail; - /* Set the CRTC's port so that the encoder component can find it */ ep = of_graph_get_next_endpoint(dev->of_node, NULL); if (!ep) { @@ -394,8 +390,18 @@ static int malidp_bind(struct device *dev) } drm_kms_helper_poll_init(drm); + + ret = drm_dev_register(drm, 0); + if (ret) + goto register_fail; + return 0; +register_fail: + if (malidp->fbdev) { + drm_fbdev_cma_fini(malidp->fbdev); + malidp->fbdev = NULL; + } fbdev_fail: drm_vblank_cleanup(drm); vblank_fail: @@ -407,8 +413,6 @@ bind_fail: of_node_put(malidp->crtc.port); malidp->crtc.port = NULL; port_fail: - drm_dev_unregister(drm); -register_fail: malidp_de_planes_destroy(drm); drm_mode_config_cleanup(drm); init_fail: @@ -431,6 +435,7 @@ static void malidp_unbind(struct device *dev) struct malidp_drm *malidp = drm->dev_private; struct malidp_hw_device *hwdev = malidp->dev; + drm_dev_unregister(drm); if (malidp->fbdev) { drm_fbdev_cma_fini(malidp->fbdev); malidp->fbdev = NULL; @@ -442,7 +447,6 @@ static void malidp_unbind(struct device *dev) component_unbind_all(dev, drm); of_node_put(malidp->crtc.port); malidp->crtc.port = NULL; - drm_dev_unregister(drm); malidp_de_planes_destroy(drm); drm_mode_config_cleanup(drm); drm->dev_private = NULL; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index f4315bc8d471..6e6fca20ba8b 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1369,7 +1369,6 @@ const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = { static void tda998x_connector_destroy(struct drm_connector *connector) { - drm_connector_unregister(connector); drm_connector_cleanup(connector); } @@ -1441,16 +1440,10 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_connector; - ret = drm_connector_register(&priv->connector); - if (ret) - goto err_sysfs; - drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder); return 0; -err_sysfs: - drm_connector_cleanup(&priv->connector); err_connector: drm_encoder_cleanup(&priv->encoder); err_encoder: @@ -1463,7 +1456,6 @@ static void tda998x_unbind(struct device *dev, struct device *master, { struct tda998x_priv *priv = dev_get_drvdata(dev); - drm_connector_unregister(&priv->connector); drm_connector_cleanup(&priv->connector); drm_encoder_cleanup(&priv->encoder); tda998x_destroy(priv); -- cgit v1.2.3 From d8e4aa070751bfd646b8692cc12b0ee7e55d3266 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 31 Oct 2016 08:59:27 -0400 Subject: mv643xx_eth: Fix merge error. One merge conflict block wasn't resolved. Reported-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 8302c7e660ce..69451b1cfd9a 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -3220,15 +3220,12 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev->priv_flags |= IFF_UNICAST_FLT; dev->gso_max_segs = MV643XX_MAX_TSO_SEGS; -<<<<<<< HEAD /* MTU range: 64 - 9500 */ dev->min_mtu = 64; dev->max_mtu = 9500; SET_NETDEV_DEV(dev, &pdev->dev); -======= ->>>>>>> 2a26d99b251b8625d27aed14e97fc10707a3a81f if (mp->shared->win_protect) wrl(mp, WINDOW_PROTECT(mp->port_num), mp->shared->win_protect); -- cgit v1.2.3 From 7b7a119e8546e27227a7969883a3c34ed7dbb0cf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 31 Oct 2016 12:40:48 +0000 Subject: drm/i915: Mark up obj->mm.lock for shrinker As we may allocate from within the obj->mm.lock we may enter the shrinker for direct reclaim. Operating on the current object is prevented by checking for obj->mm.pages (which is only set as the last operation in the allocation path). However, we need to identify the single recursion of accessing another object's obj->mm.lock as the two locks have identical class and so appear to be the same to lockdep, convincing it that a deadlock is possible. Use mutex_lock_nested() to remove the false positive. [ 2165.945734] ================================= [ 2165.945749] [ INFO: inconsistent lock state ] [ 2165.945765] 4.9.0-rc2+ #2 Tainted: G W [ 2165.945781] --------------------------------- [ 2165.945796] inconsistent {RECLAIM_FS-ON-W} -> {IN-RECLAIM_FS-W} usage. [ 2165.945816] kswapd0/62 [HC0[0]:SC0[0]:HE1:SE1] takes: (&obj->mm.lock){+.+.?.}, at: [] i915_gem_shrink+0x29f/0x500 [i915] [ 2165.945904] {RECLAIM_FS-ON-W} state was registered at: [ 2165.945931] [] mark_held_locks+0x6f/0xa0 [ 2165.945956] [] lockdep_trace_alloc+0x69/0xc0 [ 2165.945982] [] kmem_cache_alloc_trace+0x33/0x2a0 [ 2165.946019] [] i915_gem_object_get_pages_stolen+0x6a/0xd0 [i915] [ 2165.946060] [] ____i915_gem_object_get_pages+0x20/0x60 [i915] [ 2165.946098] [] __i915_gem_object_get_pages+0x58/0x70 [i915] [ 2165.946138] [] _i915_gem_object_create_stolen+0xec/0x120 [i915] [ 2165.946177] [] i915_gem_object_create_stolen_for_preallocated+0xf3/0x3f0 [i915] [ 2165.946222] [] intel_alloc_initial_plane_obj.isra.125+0xd3/0x200 [i915] [ 2165.946266] [] intel_modeset_init+0x931/0x1530 [i915] [ 2165.946301] [] i915_driver_load+0xa14/0x14a0 [i915] [ 2165.946335] [] i915_pci_probe+0x4f/0x70 [i915] [ 2165.946362] [] local_pci_probe+0x42/0xa0 [ 2165.946386] [] pci_device_probe+0x103/0x150 [ 2165.946411] [] driver_probe_device+0x223/0x430 [ 2165.946436] [] __driver_attach+0xe3/0xf0 [ 2165.946461] [] bus_for_each_dev+0x73/0xc0 [ 2165.946485] [] driver_attach+0x1e/0x20 [ 2165.946508] [] bus_add_driver+0x173/0x270 [ 2165.946533] [] driver_register+0x60/0xe0 [ 2165.946557] [] __pci_register_driver+0x5d/0x60 [ 2165.946606] [] soundcore_open+0x17/0x230 [soundcore] [ 2165.946636] [] do_one_initcall+0x50/0x180 [ 2165.946661] [] do_init_module+0x5f/0x1f1 [ 2165.946685] [] load_module+0x2174/0x2a80 [ 2165.946709] [] SYSC_finit_module+0xdf/0x110 [ 2165.946734] [] SyS_finit_module+0xe/0x10 [ 2165.946758] [] entry_SYSCALL_64_fastpath+0x18/0xad [ 2165.946776] irq event stamp: 90871 [ 2165.946788] hardirqs last enabled at (90871): [ 2165.946805] [] __mutex_unlock_slowpath+0x11a/0x1c0 [ 2165.946823] hardirqs last disabled at (90870): [ 2165.946839] [] __mutex_unlock_slowpath+0x5b/0x1c0 [ 2165.946856] softirqs last enabled at (90858): [ 2165.946872] [] __do_softirq+0x39a/0x4c6 [ 2165.946887] softirqs last disabled at (90671): [ 2165.946902] [] irq_exit+0xea/0xf0 [ 2165.946916] other info that might help us debug this: [ 2165.946936] Possible unsafe locking scenario: [ 2165.946955] CPU0 [ 2165.946965] ---- [ 2165.946975] lock(&obj->mm.lock); [ 2165.947000] [ 2165.947010] lock(&obj->mm.lock); [ 2165.947035] *** DEADLOCK *** [ 2165.947054] 2 locks held by kswapd0/62: [ 2165.947067] #0: (shrinker_rwsem){++++..}, at: [] shrink_slab.part.40+0x5e/0x5d0 [ 2165.947120] #1: (&dev->struct_mutex){+.+.+.}, at: [] i915_gem_shrinker_lock+0x1b/0x60 [i915] [ 2165.948909] stack backtrace: [ 2165.950650] CPU: 2 PID: 62 Comm: kswapd0 Tainted: G W 4.9.0-rc2+ #2 [ 2165.951587] Hardware name: LENOVO 80MX/Lenovo E31-80, BIOS DCCN34WW(V2.03) 12/01/2015 [ 2165.952484] ffffc90000b5f8c8 ffffffffb137f645 ffff88016c5a2700 ffffffffb25f20a0 [ 2165.953395] ffffc90000b5f918 ffffffffb10bcecd 0000000000000000 ffff880100000001 [ 2165.954305] 0000000000000001 000000000000000a ffff88016c5a2fd0 ffff88016c5a2700 [ 2165.955240] Call Trace: [ 2165.956170] [] dump_stack+0x68/0x93 [ 2165.957071] [] print_usage_bug+0x1dd/0x1f0 [ 2165.957979] [] mark_lock+0x559/0x5c0 [ 2165.958875] [] ? print_shortest_lock_dependencies+0x1b0/0x1b0 [ 2165.959829] [] __lock_acquire+0x66d/0x12a0 [ 2165.960729] [] ? __slab_free+0xa1/0x340 [ 2165.961625] [] ? debug_lockdep_rcu_enabled+0x1d/0x20 [ 2165.962530] [] ? mark_held_locks+0x6f/0xa0 [ 2165.963457] [] lock_acquire+0xf0/0x1f0 [ 2165.964368] [] ? i915_gem_shrink+0x29f/0x500 [i915] [ 2165.965269] [] ? i915_gem_shrink+0x29f/0x500 [i915] [ 2165.966150] [] mutex_lock_nested+0x77/0x420 [ 2165.967030] [] ? i915_gem_shrink+0x29f/0x500 [i915] [ 2165.967952] [] ? __i915_gem_object_put_pages.part.58+0x161/0x1b0 [i915] [ 2165.968835] [] i915_gem_shrink+0x29f/0x500 [i915] [ 2165.969712] [] i915_gem_shrinker_scan+0x70/0xb0 [i915] [ 2165.970591] [] shrink_slab.part.40+0x1fe/0x5d0 [ 2165.971504] [] shrink_node+0x22c/0x320 [ 2165.972371] [] kswapd+0x38b/0x9b0 [ 2165.973238] [] ? mem_cgroup_shrink_node+0x330/0x330 [ 2165.974068] [] kthread+0xff/0x120 [ 2165.974929] [] ? kthread_park+0x60/0x60 [ 2165.975847] [] ret_from_fork+0x27/0x40 Reported-by: Tvrtko Ursulin Fixes: 1233e2db199d ("drm/i915: Move object backing storage manipulation...") Testcase: igt/gem_ctx_create/maximum-swap Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161031124048.30355-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 0241658af16b..0daa09cabbcc 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -223,7 +223,9 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, continue; if (unsafe_drop_pages(obj)) { - mutex_lock(&obj->mm.lock); + /* May arrive from get_pages on another bo */ + mutex_lock_nested(&obj->mm.lock, + SINGLE_DEPTH_NESTING); if (!obj->mm.pages) { __i915_gem_object_invalidate(obj); count += obj->base.size >> PAGE_SHIFT; -- cgit v1.2.3 From 2a43ca0aa9084c41aaa1006fbf22155b2e94babf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 31 Oct 2016 10:33:08 -0400 Subject: mv643xx_eth: Properly resolve merge conflict. The second SET_NETDEV_DEV() in the hunk should be removed. Reported-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 69451b1cfd9a..6749b831998c 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -3224,8 +3224,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev->min_mtu = 64; dev->max_mtu = 9500; - SET_NETDEV_DEV(dev, &pdev->dev); - if (mp->shared->win_protect) wrl(mp, WINDOW_PROTECT(mp->port_num), mp->shared->win_protect); -- cgit v1.2.3 From 33edc24d12c42710e23f1c2cef434937af73e245 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 25 Oct 2016 18:58:00 +0300 Subject: drm/i915: Don't try to initialize sprite planes on pre-ilk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't currently implement support for sprite planes on pre-ilk platforms, so let's leave num_sprites at 0 so that we don't get spurious errors during driver init. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477411083-19255-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_device_info.c | 5 +++-- drivers/gpu/drm/i915/intel_sprite.c | 3 --- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index d6a8f11813d5..185e3bbc9ec9 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -282,12 +282,13 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) info->num_sprites[PIPE_A] = 2; info->num_sprites[PIPE_B] = 2; info->num_sprites[PIPE_C] = 1; - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { for_each_pipe(dev_priv, pipe) info->num_sprites[pipe] = 2; - else + } else if (INTEL_GEN(dev_priv) >= 5) { for_each_pipe(dev_priv, pipe) info->num_sprites[pipe] = 1; + } if (i915.disable_display) { DRM_INFO("Display disabled (module parameter)\n"); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 43d0350856e7..ae1e3d47951b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1054,9 +1054,6 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) int num_plane_formats; int ret; - if (INTEL_INFO(dev)->gen < 5) - return -ENODEV; - intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); if (!intel_plane) { ret = -ENOMEM; -- cgit v1.2.3 From a81d6fa0966b88b1ddd79302d7d351d493c4db9d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 25 Oct 2016 18:58:01 +0300 Subject: drm/i915: Initialize planes in a reasonable order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The zpos magic sorting uses the object ID to solve conflicting zpos values. Let's initialize our planes in an order that makes the object IDs agree with the normal primary->sprites->cursor z order. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477411083-19255-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 304073a03c4c..b9692f639a9f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15241,7 +15241,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) struct intel_crtc_state *crtc_state = NULL; struct drm_plane *primary = NULL; struct drm_plane *cursor = NULL; - int ret; + int sprite, ret; intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); if (intel_crtc == NULL) @@ -15268,6 +15268,13 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) if (!primary) goto fail; + for_each_sprite(dev_priv, pipe, sprite) { + ret = intel_plane_init(dev, pipe, sprite); + if (ret) + DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n", + pipe_name(pipe), sprite_name(pipe, sprite), ret); + } + cursor = intel_cursor_plane_create(dev, pipe); if (!cursor) goto fail; @@ -16392,7 +16399,6 @@ void intel_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct i915_ggtt *ggtt = &dev_priv->ggtt; - int sprite, ret; enum pipe pipe; struct intel_crtc *crtc; @@ -16463,12 +16469,6 @@ void intel_modeset_init(struct drm_device *dev) for_each_pipe(dev_priv, pipe) { intel_crtc_init(dev, pipe); - for_each_sprite(dev_priv, pipe, sprite) { - ret = intel_plane_init(dev, pipe, sprite); - if (ret) - DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n", - pipe_name(pipe), sprite_name(pipe, sprite), ret); - } } intel_update_czclk(dev_priv); -- cgit v1.2.3 From b079bd17e301708da044b4ea114f44c4aa47160c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 25 Oct 2016 18:58:02 +0300 Subject: drm/i915: Bail if plane/crtc init fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to the plane->index not getting readjusted in drm_plane_cleanup(), we can't continue initialization of some plane/crtc init fails. Well, we sort of could I suppose if we left all initialized planes on the list, but that would expose those planes to userspace as well. But for crtcs the situation is even worse since we assume that pipe==crtc index occasionally, so we can't really deal with a partially initialize set of crtcs. So seems safest to just abort the entire thing if anything goes wrong. All the failure paths here are kmalloc()s anyway, so it seems unlikely we'd get very far if these start failing. v2: Add (enum plane) case to silence gcc Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477411083-19255-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 103 ++++++++++++++++++++++------------- drivers/gpu/drm/i915/intel_drv.h | 3 +- drivers/gpu/drm/i915/intel_sprite.c | 8 +-- 5 files changed, 76 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 839ce2ae38fa..6a99544c98d3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -595,7 +595,9 @@ static int i915_load_modeset_init(struct drm_device *dev) /* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ - intel_modeset_init(dev); + ret = intel_modeset_init(dev); + if (ret) + goto cleanup_irq; intel_guc_init(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 42a499681966..51360d199263 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3799,7 +3799,7 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv); /* modesetting */ extern void intel_modeset_init_hw(struct drm_device *dev); -extern void intel_modeset_init(struct drm_device *dev); +extern int intel_modeset_init(struct drm_device *dev); extern void intel_modeset_gem_init(struct drm_device *dev); extern void intel_modeset_cleanup(struct drm_device *dev); extern int intel_connector_register(struct drm_connector *); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b9692f639a9f..740c68896672 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14944,9 +14944,6 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc, */ void intel_plane_destroy(struct drm_plane *plane) { - if (!plane) - return; - drm_plane_cleanup(plane); kfree(to_intel_plane(plane)); } @@ -14960,11 +14957,10 @@ const struct drm_plane_funcs intel_plane_funcs = { .atomic_set_property = intel_plane_atomic_set_property, .atomic_duplicate_state = intel_plane_duplicate_state, .atomic_destroy_state = intel_plane_destroy_state, - }; -static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, - int pipe) +static struct intel_plane * +intel_primary_plane_create(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *primary = NULL; @@ -14975,12 +14971,17 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, int ret; primary = kzalloc(sizeof(*primary), GFP_KERNEL); - if (!primary) + if (!primary) { + ret = -ENOMEM; goto fail; + } state = intel_create_plane_state(&primary->base); - if (!state) + if (!state) { + ret = -ENOMEM; goto fail; + } + primary->base.state = &state->base; primary->can_scale = false; @@ -15061,13 +15062,13 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); - return &primary->base; + return primary; fail: kfree(state); kfree(primary); - return NULL; + return ERR_PTR(ret); } static int @@ -15163,8 +15164,8 @@ intel_update_cursor_plane(struct drm_plane *plane, intel_crtc_update_cursor(crtc, state); } -static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, - int pipe) +static struct intel_plane * +intel_cursor_plane_create(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *cursor = NULL; @@ -15172,12 +15173,17 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, int ret; cursor = kzalloc(sizeof(*cursor), GFP_KERNEL); - if (!cursor) + if (!cursor) { + ret = -ENOMEM; goto fail; + } state = intel_create_plane_state(&cursor->base); - if (!state) + if (!state) { + ret = -ENOMEM; goto fail; + } + cursor->base.state = &state->base; cursor->can_scale = false; @@ -15209,13 +15215,13 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs); - return &cursor->base; + return cursor; fail: kfree(state); kfree(cursor); - return NULL; + return ERR_PTR(ret); } static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, @@ -15234,22 +15240,24 @@ static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_cr scaler_state->scaler_id = -1; } -static void intel_crtc_init(struct drm_device *dev, int pipe) +static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc; struct intel_crtc_state *crtc_state = NULL; - struct drm_plane *primary = NULL; - struct drm_plane *cursor = NULL; + struct intel_plane *primary = NULL; + struct intel_plane *cursor = NULL; int sprite, ret; intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); - if (intel_crtc == NULL) - return; + if (!intel_crtc) + return -ENOMEM; crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); - if (!crtc_state) + if (!crtc_state) { + ret = -ENOMEM; goto fail; + } intel_crtc->config = crtc_state; intel_crtc->base.state = &crtc_state->base; crtc_state->base.crtc = &intel_crtc->base; @@ -15265,22 +15273,30 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) } primary = intel_primary_plane_create(dev, pipe); - if (!primary) + if (IS_ERR(primary)) { + ret = PTR_ERR(primary); goto fail; + } for_each_sprite(dev_priv, pipe, sprite) { - ret = intel_plane_init(dev, pipe, sprite); - if (ret) - DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n", - pipe_name(pipe), sprite_name(pipe, sprite), ret); + struct intel_plane *plane; + + plane = intel_sprite_plane_create(dev, pipe, sprite); + if (!plane) { + ret = PTR_ERR(plane); + goto fail; + } } cursor = intel_cursor_plane_create(dev, pipe); - if (!cursor) + if (!cursor) { + ret = PTR_ERR(cursor); goto fail; + } - ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary, - cursor, &intel_crtc_funcs, + ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, + &primary->base, &cursor->base, + &intel_crtc_funcs, "pipe %c", pipe_name(pipe)); if (ret) goto fail; @@ -15290,7 +15306,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) * is hooked to pipe B. Hence we want plane A feeding pipe B. */ intel_crtc->pipe = pipe; - intel_crtc->plane = pipe; + intel_crtc->plane = (enum plane) pipe; if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) { DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); intel_crtc->plane = !pipe; @@ -15312,13 +15328,18 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) intel_color_init(&intel_crtc->base); WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe); - return; + + return 0; fail: - intel_plane_destroy(primary); - intel_plane_destroy(cursor); + /* + * drm_mode_config_cleanup() will free up any + * crtcs/planes already initialized. + */ kfree(crtc_state); kfree(intel_crtc); + + return ret; } enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) @@ -16395,7 +16416,7 @@ fail: drm_modeset_acquire_fini(&ctx); } -void intel_modeset_init(struct drm_device *dev) +int intel_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct i915_ggtt *ggtt = &dev_priv->ggtt; @@ -16419,7 +16440,7 @@ void intel_modeset_init(struct drm_device *dev) intel_init_pm(dev); if (INTEL_INFO(dev)->num_pipes == 0) - return; + return 0; /* * There may be no VBT; and if the BIOS enabled SSC we can @@ -16468,7 +16489,13 @@ void intel_modeset_init(struct drm_device *dev) INTEL_INFO(dev)->num_pipes > 1 ? "s" : ""); for_each_pipe(dev_priv, pipe) { - intel_crtc_init(dev, pipe); + int ret; + + ret = intel_crtc_init(dev, pipe); + if (ret) { + drm_mode_config_cleanup(dev); + return ret; + } } intel_update_czclk(dev_priv); @@ -16516,6 +16543,8 @@ void intel_modeset_init(struct drm_device *dev) * since the watermark calculation done here will use pstate->fb. */ sanitize_watermarks(dev); + + return 0; } static void intel_enable_pipe_a(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2616d92f9fee..46233356ed24 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1778,7 +1778,8 @@ bool intel_sdvo_init(struct drm_device *dev, /* intel_sprite.c */ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, int usecs); -int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); +struct intel_plane *intel_sprite_plane_create(struct drm_device *dev, + enum pipe pipe, int plane); int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); void intel_pipe_update_start(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index ae1e3d47951b..41ae7f562eec 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1042,8 +1042,8 @@ static uint32_t skl_plane_formats[] = { DRM_FORMAT_VYUY, }; -int -intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) +struct intel_plane * +intel_sprite_plane_create(struct drm_device *dev, enum pipe pipe, int plane) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *intel_plane = NULL; @@ -1160,11 +1160,11 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); - return 0; + return intel_plane; fail: kfree(state); kfree(intel_plane); - return ret; + return ERR_PTR(ret); } -- cgit v1.2.3 From 1890ae64841a7f304ed9aa6cc400da6102853cbe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 25 Oct 2016 18:58:03 +0300 Subject: drm/i915: Reorganize sprite init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kill the switch statement from the sprite init code and replace with a more straightforward if ladder. Now each significant evolution of the sprite hardware is in its own neat box. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477411083-19255-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 70 ++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 41ae7f562eec..70b50a27763e 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1067,25 +1067,25 @@ intel_sprite_plane_create(struct drm_device *dev, enum pipe pipe, int plane) } intel_plane->base.state = &state->base; - switch (INTEL_INFO(dev)->gen) { - case 5: - case 6: + if (INTEL_GEN(dev_priv) >= 9) { intel_plane->can_scale = true; - intel_plane->max_downscale = 16; - intel_plane->update_plane = ilk_update_plane; - intel_plane->disable_plane = ilk_disable_plane; + state->scaler_id = -1; - if (IS_GEN6(dev_priv)) { - plane_formats = snb_plane_formats; - num_plane_formats = ARRAY_SIZE(snb_plane_formats); - } else { - plane_formats = ilk_plane_formats; - num_plane_formats = ARRAY_SIZE(ilk_plane_formats); - } - break; + intel_plane->update_plane = skl_update_plane; + intel_plane->disable_plane = skl_disable_plane; + + plane_formats = skl_plane_formats; + num_plane_formats = ARRAY_SIZE(skl_plane_formats); + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + intel_plane->can_scale = false; + intel_plane->max_downscale = 1; + + intel_plane->update_plane = vlv_update_plane; + intel_plane->disable_plane = vlv_disable_plane; - case 7: - case 8: + plane_formats = vlv_plane_formats; + num_plane_formats = ARRAY_SIZE(vlv_plane_formats); + } else if (INTEL_GEN(dev_priv) >= 7) { if (IS_IVYBRIDGE(dev_priv)) { intel_plane->can_scale = true; intel_plane->max_downscale = 2; @@ -1094,33 +1094,25 @@ intel_sprite_plane_create(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->max_downscale = 1; } - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - intel_plane->update_plane = vlv_update_plane; - intel_plane->disable_plane = vlv_disable_plane; + intel_plane->update_plane = ivb_update_plane; + intel_plane->disable_plane = ivb_disable_plane; - plane_formats = vlv_plane_formats; - num_plane_formats = ARRAY_SIZE(vlv_plane_formats); - } else { - intel_plane->update_plane = ivb_update_plane; - intel_plane->disable_plane = ivb_disable_plane; + plane_formats = snb_plane_formats; + num_plane_formats = ARRAY_SIZE(snb_plane_formats); + } else { + intel_plane->can_scale = true; + intel_plane->max_downscale = 16; + + intel_plane->update_plane = ilk_update_plane; + intel_plane->disable_plane = ilk_disable_plane; + if (IS_GEN6(dev_priv)) { plane_formats = snb_plane_formats; num_plane_formats = ARRAY_SIZE(snb_plane_formats); + } else { + plane_formats = ilk_plane_formats; + num_plane_formats = ARRAY_SIZE(ilk_plane_formats); } - break; - case 9: - intel_plane->can_scale = true; - intel_plane->update_plane = skl_update_plane; - intel_plane->disable_plane = skl_disable_plane; - state->scaler_id = -1; - - plane_formats = skl_plane_formats; - num_plane_formats = ARRAY_SIZE(skl_plane_formats); - break; - default: - MISSING_CASE(INTEL_INFO(dev)->gen); - ret = -ENODEV; - goto fail; } if (INTEL_GEN(dev_priv) >= 9) { @@ -1139,7 +1131,7 @@ intel_sprite_plane_create(struct drm_device *dev, enum pipe pipe, int plane) possible_crtcs = (1 << pipe); - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats, -- cgit v1.2.3 From 20861f26e33d76a4f3587bcc866fa1dab3e01094 Mon Sep 17 00:00:00 2001 From: Gao Feng Date: Thu, 27 Oct 2016 09:05:22 +0800 Subject: driver: tun: Use new macro SOCK_IOC_TYPE instead of literal number 0x89 The current codes use _IOC_TYPE(cmd) == 0x89 to check if the cmd is one socket ioctl command like SIOCGIFHWADDR. But the literal number 0x89 may confuse readers. So create one macro SOCK_IOC_TYPE to enhance the readability. Signed-off-by: Gao Feng Signed-off-by: David S. Miller --- drivers/net/tun.c | 2 +- include/uapi/linux/sockios.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9142db847ee1..1588469844e7 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1985,7 +1985,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, int le; int ret; - if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) { + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == SOCK_IOC_TYPE) { if (copy_from_user(&ifr, argp, ifreq_len)) return -EFAULT; } else { diff --git a/include/uapi/linux/sockios.h b/include/uapi/linux/sockios.h index 83cc54ce6081..79d029d25310 100644 --- a/include/uapi/linux/sockios.h +++ b/include/uapi/linux/sockios.h @@ -24,6 +24,8 @@ #define SIOCINQ FIONREAD #define SIOCOUTQ TIOCOUTQ /* output queue size (not sent + not acked) */ +#define SOCK_IOC_TYPE 0x89 + /* Routing table calls. */ #define SIOCADDRT 0x890B /* add routing table entry */ #define SIOCDELRT 0x890C /* delete routing table entry */ -- cgit v1.2.3 From 18eddaedc940a49425364df98abda218ce1e771c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 31 Oct 2016 15:04:10 +0000 Subject: mvsas: fix error return code in mvs_task_prep() Fix to return error code -ENOMEM from the error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Tejun Heo --- drivers/scsi/mvsas/mv_sas.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 86eb19902bac..c7cc8035eacb 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -791,8 +791,10 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf slot->slot_tag = tag; slot->buf = pci_pool_alloc(mvi->dma_pool, GFP_ATOMIC, &slot->buf_dma); - if (!slot->buf) + if (!slot->buf) { + rc = -ENOMEM; goto err_out_tag; + } memset(slot->buf, 0, MVS_SLOT_BUF_SZ); tei.task = task; -- cgit v1.2.3 From a00f761f095f90cb3467b630e89a36198454bac6 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 30 Oct 2016 16:37:24 -0400 Subject: s390: cio: make it explicitly non-modular The Makefile currently controlling compilation of this code is: obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o \ fcx.o itcw.o crw.o ccwreq.o trace.o ioasm.o ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o obj-y += ccw_device.o cmf.o ...meaning that the files here are not being built as modular. Lets remove the couple traces of modular infrastructure use, so that when reading the code there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. We replace module.h with export.h where the file does export some symbols. Cc: Sebastian Ott Cc: Peter Oberparleiter Cc: Cornelia Huck Cc: Arnd Bergmann Cc: linux-s390@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cmf.c | 10 ++-------- drivers/s390/cio/css.c | 6 +++--- drivers/s390/cio/device.c | 6 +++--- drivers/s390/cio/device_ops.c | 5 +++-- 4 files changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 268aa23afa01..6b6386e9a500 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include /* get_tod_clock() */ @@ -1389,13 +1389,7 @@ static int __init init_cmf(void) "%s (mode %s)\n", format_string, detect_string); return 0; } -module_init(init_cmf); - - -MODULE_AUTHOR("Arnd Bergmann "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("channel measurement facility base driver\n" - "Copyright IBM Corp. 2003\n"); +device_initcall(init_cmf); EXPORT_SYMBOL_GPL(enable_cmf); EXPORT_SYMBOL_GPL(disable_cmf); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 3d2b20ee613f..bc099b61394d 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -5,12 +5,14 @@ * * Author(s): Arnd Bergmann (arndb@de.ibm.com) * Cornelia Huck (cornelia.huck@de.ibm.com) + * + * License: GPL */ #define KMSG_COMPONENT "cio" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt -#include +#include #include #include #include @@ -1285,5 +1287,3 @@ void css_driver_unregister(struct css_driver *cdrv) driver_unregister(&cdrv->drv); } EXPORT_SYMBOL_GPL(css_driver_unregister); - -MODULE_LICENSE("GPL"); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6a58bc8f46e2..79823ee9c100 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -5,12 +5,14 @@ * Author(s): Arnd Bergmann (arndb@de.ibm.com) * Cornelia Huck (cornelia.huck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * License: GPL */ #define KMSG_COMPONENT "cio" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt -#include +#include #include #include #include @@ -145,7 +147,6 @@ static struct css_device_id io_subchannel_ids[] = { { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, }, { /* end of list */ }, }; -MODULE_DEVICE_TABLE(css, io_subchannel_ids); static int io_subchannel_prepare(struct subchannel *sch) { @@ -2150,7 +2151,6 @@ int ccw_device_siosl(struct ccw_device *cdev) } EXPORT_SYMBOL_GPL(ccw_device_siosl); -MODULE_LICENSE("GPL"); EXPORT_SYMBOL(ccw_device_set_online); EXPORT_SYMBOL(ccw_device_set_offline); EXPORT_SYMBOL(ccw_driver_register); diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 877d9f601e63..cf8c4ac6323a 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -3,8 +3,10 @@ * * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) * Cornelia Huck (cornelia.huck@de.ibm.com) + * + * License: GPL */ -#include +#include #include #include #include @@ -676,7 +678,6 @@ void ccw_device_get_schid(struct ccw_device *cdev, struct subchannel_id *schid) } EXPORT_SYMBOL_GPL(ccw_device_get_schid); -MODULE_LICENSE("GPL"); EXPORT_SYMBOL(ccw_device_set_options_mask); EXPORT_SYMBOL(ccw_device_set_options); EXPORT_SYMBOL(ccw_device_clear_options); -- cgit v1.2.3 From cbe62fac178c5cfd288837d4b88ddd712c50ee73 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 30 Oct 2016 16:37:25 -0400 Subject: s390: char: make zcore explicitly non-modular The Kconfig currently controlling compilation of this code is: arch/s390/Kconfig:config CRASH_DUMP arch/s390/Kconfig: bool "kernel crash dumps" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init wasn't even being used by this file, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. We don't replace module.h with init.h since the file already has that. Cc: linux-s390@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/zcore.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 16992e2a40ad..5aea89a92ff4 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -7,6 +7,7 @@ * * Copyright IBM Corp. 2003, 2008 * Author(s): Michael Holzheu + * License: GPL */ #define KMSG_COMPONENT "zdump" @@ -16,7 +17,6 @@ #include #include #include -#include #include #include @@ -364,22 +364,4 @@ fail: diag308(DIAG308_REL_HSA, NULL); return rc; } - -static void __exit zcore_exit(void) -{ - debug_unregister(zcore_dbf); - sclp_sdias_exit(); - free_page((unsigned long) ipl_block); - debugfs_remove(zcore_hsa_file); - debugfs_remove(zcore_reipl_file); - debugfs_remove(zcore_memmap_file); - debugfs_remove(zcore_dir); - diag308(DIAG308_REL_HSA, NULL); -} - -MODULE_AUTHOR("Copyright IBM Corp. 2003,2008"); -MODULE_DESCRIPTION("zcore module for zfcpdump support"); -MODULE_LICENSE("GPL"); - subsys_initcall(zcore_init); -module_exit(zcore_exit); -- cgit v1.2.3 From 6e4c1d846417cb5ae19190f4b9457c0137632c58 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 30 Oct 2016 16:37:26 -0400 Subject: s390: char: make con3215 explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/s390/char/Kconfig:config TN3215 drivers/s390/char/Kconfig: def_bool y ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We don't replace module.h with init.h since the file already has that. Cc: linux-s390@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/con3215.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 931d10e86837..1b8d825623bd 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -9,7 +9,6 @@ * Dan Morrison, IBM Corporation */ -#include #include #include #include @@ -1215,13 +1214,4 @@ static int __init tty3215_init(void) tty3215_driver = driver; return 0; } - -static void __exit tty3215_exit(void) -{ - tty_unregister_driver(tty3215_driver); - put_tty_driver(tty3215_driver); - ccw_driver_unregister(&raw3215_ccw_driver); -} - -module_init(tty3215_init); -module_exit(tty3215_exit); +device_initcall(tty3215_init); -- cgit v1.2.3 From 238b9285b9d9f3c5e48ebeaa562a5341475bc5be Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 30 Oct 2016 16:37:27 -0400 Subject: s390: char: make sclp_tty explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/s390/char/Kconfig:config SCLP_TTY drivers/s390/char/Kconfig: def_bool y ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular infrastructure use, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We don't replace module.h with init.h since the file already has that. Cc: Peter Oberparleiter Cc: linux-s390@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_tty.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 3c6e174e19b6..9259017a1295 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -7,7 +7,6 @@ * Martin Schwidefsky */ -#include #include #include #include @@ -573,4 +572,4 @@ sclp_tty_init(void) sclp_tty_driver = driver; return 0; } -module_init(sclp_tty_init); +device_initcall(sclp_tty_init); -- cgit v1.2.3 From aae175d2dca8787e0dcf1d7d08f4cca31bdd8a6a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 30 Oct 2016 16:37:28 -0400 Subject: s390: char: make slcp_quiesce explicitly non-modular The Makefile currently controlling compilation of this code is obj-y, meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular infrastructure, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. Cc: linux-s390@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_quiesce.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c index 475e470d9768..e4958511168a 100644 --- a/drivers/s390/char/sclp_quiesce.c +++ b/drivers/s390/char/sclp_quiesce.c @@ -6,7 +6,6 @@ * Peter Oberparleiter */ -#include #include #include #include @@ -80,5 +79,4 @@ static int __init sclp_quiesce_init(void) { return sclp_register(&sclp_quiesce_event); } - -module_init(sclp_quiesce_init); +device_initcall(sclp_quiesce_init); -- cgit v1.2.3 From 0729dcf248325db600f232d7b96e76441ea450dd Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 30 Oct 2016 16:37:29 -0400 Subject: s390: hotplug: make pci_hpc explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/pci/hotplug/Kconfig:config HOTPLUG_PCI_S390 drivers/pci/hotplug/Kconfig: bool "System z PCI Hotplug Support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular infrastructure use, so that when reading the driver there is no doubt it is builtin-only. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. We don't exchange module.h for init.h or export.h since the file does not contain any initcalls or EXPORT of symbols. Cc: Sebastian Ott Cc: Gerald Schaefer Cc: Bjorn Helgaas Cc: linux-s390@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/pci/hotplug/s390_pci_hpc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c index 50b8b7d54416..530d0e49f2ed 100644 --- a/drivers/pci/hotplug/s390_pci_hpc.c +++ b/drivers/pci/hotplug/s390_pci_hpc.c @@ -5,12 +5,13 @@ * * Author(s): * Jan Glauber + * + * License: GPL */ #define KMSG_COMPONENT "zpci" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt -#include #include #include #include @@ -21,10 +22,6 @@ #define SLOT_NAME_SIZE 10 static LIST_HEAD(s390_hotplug_slot_list); -MODULE_AUTHOR("Jan Glauber Date: Sun, 30 Oct 2016 16:37:32 -0400 Subject: s390: virtio: make ccw explicitly non-modular The Kconfig currently controlling compilation of this code is: arch/s390/Kconfig:config S390_GUEST arch/s390/Kconfig: def_bool y ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We replace module.h with moduleparam.h since the file does declare some module_param() and leaving that as-is is currently the easiest way to remain compatible with existing boot arg use cases. Cc: Christian Borntraeger Cc: Cornelia Huck Cc: linux-s390@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/virtio/virtio_ccw.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 8688ad4c825f..639ed4e6afd1 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -235,16 +235,6 @@ static struct airq_info *new_airq_info(void) return info; } -static void destroy_airq_info(struct airq_info *info) -{ - if (!info) - return; - - unregister_adapter_interrupt(&info->airq); - airq_iv_release(info->aiv); - kfree(info); -} - static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs, u64 *first, void **airq_info) { @@ -1294,7 +1284,6 @@ static struct ccw_device_id virtio_ids[] = { { CCW_DEVICE(0x3832, 0) }, {}, }; -MODULE_DEVICE_TABLE(ccw, virtio_ids); static struct ccw_driver virtio_ccw_driver = { .driver = { @@ -1406,14 +1395,4 @@ static int __init virtio_ccw_init(void) no_auto_parse(); return ccw_driver_register(&virtio_ccw_driver); } -module_init(virtio_ccw_init); - -static void __exit virtio_ccw_exit(void) -{ - int i; - - ccw_driver_unregister(&virtio_ccw_driver); - for (i = 0; i < MAX_AIRQ_AREAS; i++) - destroy_airq_info(airq_areas[i]); -} -module_exit(virtio_ccw_exit); +device_initcall(virtio_ccw_init); -- cgit v1.2.3 From 9ed9895370aedd6032af2a9181c62c394d08223b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Oct 2016 17:32:16 +0100 Subject: driver core: Functional dependencies tracking support Currently, there is a problem with taking functional dependencies between devices into account. What I mean by a "functional dependency" is when the driver of device B needs device A to be functional and (generally) its driver to be present in order to work properly. This has certain consequences for power management (suspend/resume and runtime PM ordering) and shutdown ordering of these devices. In general, it also implies that the driver of A needs to be working for B to be probed successfully and it cannot be unbound from the device before the B's driver. Support for representing those functional dependencies between devices is added here to allow the driver core to track them and act on them in certain cases where applicable. The argument for doing that in the driver core is that there are quite a few distinct use cases involving device dependencies, they are relatively hard to get right in a driver (if one wants to address all of them properly) and it only gets worse if multiplied by the number of drivers potentially needing to do it. Morever, at least one case (asynchronous system suspend/resume) cannot be handled in a single driver at all, because it requires the driver of A to wait for B to suspend (during system suspend) and the driver of B to wait for A to resume (during system resume). For this reason, represent dependencies between devices as "links", with the help of struct device_link objects each containing pointers to the "linked" devices, a list node for each of them, status information, flags, and an RCU head for synchronization. Also add two new list heads, representing the lists of links to the devices that depend on the given one (consumers) and to the devices depended on by it (suppliers), and a "driver presence status" field (needed for figuring out initial states of device links) to struct device. The entire data structure consisting of all of the lists of link objects for all devices is protected by a mutex (for link object addition/removal and for list walks during device driver probing and removal) and by SRCU (for list walking in other case that will be introduced by subsequent change sets). If CONFIG_SRCU is not selected, however, an rwsem is used for protecting the entire data structure. In addition, each link object has an internal status field whose value reflects whether or not drivers are bound to the devices pointed to by the link or probing/removal of their drivers is in progress etc. That field is only modified under the device links mutex, but it may be read outside of it in some cases (introduced by subsequent change sets), so modifications of it are annotated with WRITE_ONCE(). New links are added by calling device_link_add() which takes three arguments: pointers to the devices in question and flags. In particular, if DL_FLAG_STATELESS is set in the flags, the link status is not to be taken into account for this link and the driver core will not manage it. In turn, if DL_FLAG_AUTOREMOVE is set in the flags, the driver core will remove the link automatically when the consumer device driver unbinds from it. One of the actions carried out by device_link_add() is to reorder the lists used for device shutdown and system suspend/resume to put the consumer device along with all of its children and all of its consumers (and so on, recursively) to the ends of those lists in order to ensure the right ordering between all of the supplier and consumer devices. For this reason, it is not possible to create a link between two devices if the would-be supplier device already depends on the would-be consumer device as either a direct descendant of it or a consumer of one of its direct descendants or one of its consumers and so on. There are two types of link objects, persistent and non-persistent. The persistent ones stay around until one of the target devices is deleted, while the non-persistent ones are removed automatically when the consumer driver unbinds from its device (ie. they are assumed to be valid only as long as the consumer device has a driver bound to it). Persistent links are created by default and non-persistent links are created when the DL_FLAG_AUTOREMOVE flag is passed to device_link_add(). Both persistent and non-persistent device links can be deleted with an explicit call to device_link_del(). Links created without the DL_FLAG_STATELESS flag set are managed by the driver core using a simple state machine. There are 5 states each link can be in: DORMANT (unused), AVAILABLE (the supplier driver is present and functional), CONSUMER_PROBE (the consumer driver is probing), ACTIVE (both supplier and consumer drivers are present and functional), and SUPPLIER_UNBIND (the supplier driver is unbinding). The driver core updates the link state automatically depending on what happens to the linked devices and for each link state specific actions are taken in addition to that. For example, if the supplier driver unbinds from its device, the driver core will also unbind the drivers of all of its consumers automatically under the assumption that they cannot function properly without the supplier. Analogously, the driver core will only allow the consumer driver to bind to its device if the supplier driver is present and functional (ie. the link is in the AVAILABLE state). If that's not the case, it will rely on the existing deferred probing mechanism to wait for the supplier driver to become available. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 13 ++ drivers/base/core.c | 540 +++++++++++++++++++++++++++++++++++++++++++++ drivers/base/dd.c | 41 +++- drivers/base/power/main.c | 2 + drivers/base/power/power.h | 10 + include/linux/device.h | 80 +++++++ include/linux/pm.h | 1 + 7 files changed, 682 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/base/base.h b/drivers/base/base.h index e05db388bd1c..e19b1008e5fb 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -107,6 +107,9 @@ extern void bus_remove_device(struct device *dev); extern int bus_add_driver(struct device_driver *drv); extern void bus_remove_driver(struct device_driver *drv); +extern void device_release_driver_internal(struct device *dev, + struct device_driver *drv, + struct device *parent); extern void driver_detach(struct device_driver *drv); extern int driver_probe_device(struct device_driver *drv, struct device *dev); @@ -152,3 +155,13 @@ extern int devtmpfs_init(void); #else static inline int devtmpfs_init(void) { return 0; } #endif + +/* Device links support */ +extern int device_links_read_lock(void); +extern void device_links_read_unlock(int idx); +extern int device_links_check_suppliers(struct device *dev); +extern void device_links_driver_bound(struct device *dev); +extern void device_links_driver_cleanup(struct device *dev); +extern void device_links_no_driver(struct device *dev); +extern bool device_links_busy(struct device *dev); +extern void device_links_unbind_consumers(struct device *dev); diff --git a/drivers/base/core.c b/drivers/base/core.c index ce057a568673..3c5ff17f578f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -44,6 +44,541 @@ static int __init sysfs_deprecated_setup(char *arg) early_param("sysfs.deprecated", sysfs_deprecated_setup); #endif +/* Device links support. */ + +#ifdef CONFIG_SRCU +static DEFINE_MUTEX(device_links_lock); +DEFINE_STATIC_SRCU(device_links_srcu); + +static inline void device_links_write_lock(void) +{ + mutex_lock(&device_links_lock); +} + +static inline void device_links_write_unlock(void) +{ + mutex_unlock(&device_links_lock); +} + +int device_links_read_lock(void) +{ + return srcu_read_lock(&device_links_srcu); +} + +void device_links_read_unlock(int idx) +{ + srcu_read_unlock(&device_links_srcu, idx); +} +#else /* !CONFIG_SRCU */ +static DECLARE_RWSEM(device_links_lock); + +static inline void device_links_write_lock(void) +{ + down_write(&device_links_lock); +} + +static inline void device_links_write_unlock(void) +{ + up_write(&device_links_lock); +} + +int device_links_read_lock(void) +{ + down_read(&device_links_lock); + return 0; +} + +void device_links_read_unlock(int not_used) +{ + up_read(&device_links_lock); +} +#endif /* !CONFIG_SRCU */ + +/** + * device_is_dependent - Check if one device depends on another one + * @dev: Device to check dependencies for. + * @target: Device to check against. + * + * Check if @target depends on @dev or any device dependent on it (its child or + * its consumer etc). Return 1 if that is the case or 0 otherwise. + */ +static int device_is_dependent(struct device *dev, void *target) +{ + struct device_link *link; + int ret; + + if (WARN_ON(dev == target)) + return 1; + + ret = device_for_each_child(dev, target, device_is_dependent); + if (ret) + return ret; + + list_for_each_entry(link, &dev->links.consumers, s_node) { + if (WARN_ON(link->consumer == target)) + return 1; + + ret = device_is_dependent(link->consumer, target); + if (ret) + break; + } + return ret; +} + +static int device_reorder_to_tail(struct device *dev, void *not_used) +{ + struct device_link *link; + + /* + * Devices that have not been registered yet will be put to the ends + * of the lists during the registration, so skip them here. + */ + if (device_is_registered(dev)) + devices_kset_move_last(dev); + + if (device_pm_initialized(dev)) + device_pm_move_last(dev); + + device_for_each_child(dev, NULL, device_reorder_to_tail); + list_for_each_entry(link, &dev->links.consumers, s_node) + device_reorder_to_tail(link->consumer, NULL); + + return 0; +} + +/** + * device_link_add - Create a link between two devices. + * @consumer: Consumer end of the link. + * @supplier: Supplier end of the link. + * @flags: Link flags. + * + * If the DL_FLAG_AUTOREMOVE is set, the link will be removed automatically + * when the consumer device driver unbinds from it. The combination of both + * DL_FLAG_AUTOREMOVE and DL_FLAG_STATELESS set is invalid and will cause NULL + * to be returned. + * + * A side effect of the link creation is re-ordering of dpm_list and the + * devices_kset list by moving the consumer device and all devices depending + * on it to the ends of these lists (that does not happen to devices that have + * not been registered when this function is called). + * + * The supplier device is required to be registered when this function is called + * and NULL will be returned if that is not the case. The consumer device need + * not be registerd, however. + */ +struct device_link *device_link_add(struct device *consumer, + struct device *supplier, u32 flags) +{ + struct device_link *link; + + if (!consumer || !supplier || + ((flags & DL_FLAG_STATELESS) && (flags & DL_FLAG_AUTOREMOVE))) + return NULL; + + device_links_write_lock(); + device_pm_lock(); + + /* + * If the supplier has not been fully registered yet or there is a + * reverse dependency between the consumer and the supplier already in + * the graph, return NULL. + */ + if (!device_pm_initialized(supplier) + || device_is_dependent(consumer, supplier)) { + link = NULL; + goto out; + } + + list_for_each_entry(link, &supplier->links.consumers, s_node) + if (link->consumer == consumer) + goto out; + + link = kmalloc(sizeof(*link), GFP_KERNEL); + if (!link) + goto out; + + get_device(supplier); + link->supplier = supplier; + INIT_LIST_HEAD(&link->s_node); + get_device(consumer); + link->consumer = consumer; + INIT_LIST_HEAD(&link->c_node); + link->flags = flags; + + /* Deterine the initial link state. */ + if (flags & DL_FLAG_STATELESS) { + link->status = DL_STATE_NONE; + } else { + switch (supplier->links.status) { + case DL_DEV_DRIVER_BOUND: + switch (consumer->links.status) { + case DL_DEV_PROBING: + link->status = DL_STATE_CONSUMER_PROBE; + break; + case DL_DEV_DRIVER_BOUND: + link->status = DL_STATE_ACTIVE; + break; + default: + link->status = DL_STATE_AVAILABLE; + break; + } + break; + case DL_DEV_UNBINDING: + link->status = DL_STATE_SUPPLIER_UNBIND; + break; + default: + link->status = DL_STATE_DORMANT; + break; + } + } + + /* + * Move the consumer and all of the devices depending on it to the end + * of dpm_list and the devices_kset list. + * + * It is necessary to hold dpm_list locked throughout all that or else + * we may end up suspending with a wrong ordering of it. + */ + device_reorder_to_tail(consumer, NULL); + + list_add_tail_rcu(&link->s_node, &supplier->links.consumers); + list_add_tail_rcu(&link->c_node, &consumer->links.suppliers); + + dev_info(consumer, "Linked as a consumer to %s\n", dev_name(supplier)); + + out: + device_pm_unlock(); + device_links_write_unlock(); + return link; +} +EXPORT_SYMBOL_GPL(device_link_add); + +static void device_link_free(struct device_link *link) +{ + put_device(link->consumer); + put_device(link->supplier); + kfree(link); +} + +#ifdef CONFIG_SRCU +static void __device_link_free_srcu(struct rcu_head *rhead) +{ + device_link_free(container_of(rhead, struct device_link, rcu_head)); +} + +static void __device_link_del(struct device_link *link) +{ + dev_info(link->consumer, "Dropping the link to %s\n", + dev_name(link->supplier)); + + list_del_rcu(&link->s_node); + list_del_rcu(&link->c_node); + call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); +} +#else /* !CONFIG_SRCU */ +static void __device_link_del(struct device_link *link) +{ + dev_info(link->consumer, "Dropping the link to %s\n", + dev_name(link->supplier)); + + list_del(&link->s_node); + list_del(&link->c_node); + device_link_free(link); +} +#endif /* !CONFIG_SRCU */ + +/** + * device_link_del - Delete a link between two devices. + * @link: Device link to delete. + * + * The caller must ensure proper synchronization of this function with runtime + * PM. + */ +void device_link_del(struct device_link *link) +{ + device_links_write_lock(); + device_pm_lock(); + __device_link_del(link); + device_pm_unlock(); + device_links_write_unlock(); +} +EXPORT_SYMBOL_GPL(device_link_del); + +static void device_links_missing_supplier(struct device *dev) +{ + struct device_link *link; + + list_for_each_entry(link, &dev->links.suppliers, c_node) + if (link->status == DL_STATE_CONSUMER_PROBE) + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); +} + +/** + * device_links_check_suppliers - Check presence of supplier drivers. + * @dev: Consumer device. + * + * Check links from this device to any suppliers. Walk the list of the device's + * links to suppliers and see if all of them are available. If not, simply + * return -EPROBE_DEFER. + * + * We need to guarantee that the supplier will not go away after the check has + * been positive here. It only can go away in __device_release_driver() and + * that function checks the device's links to consumers. This means we need to + * mark the link as "consumer probe in progress" to make the supplier removal + * wait for us to complete (or bad things may happen). + * + * Links with the DL_FLAG_STATELESS flag set are ignored. + */ +int device_links_check_suppliers(struct device *dev) +{ + struct device_link *link; + int ret = 0; + + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.suppliers, c_node) { + if (link->flags & DL_FLAG_STATELESS) + continue; + + if (link->status != DL_STATE_AVAILABLE) { + device_links_missing_supplier(dev); + ret = -EPROBE_DEFER; + break; + } + WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE); + } + dev->links.status = DL_DEV_PROBING; + + device_links_write_unlock(); + return ret; +} + +/** + * device_links_driver_bound - Update device links after probing its driver. + * @dev: Device to update the links for. + * + * The probe has been successful, so update links from this device to any + * consumers by changing their status to "available". + * + * Also change the status of @dev's links to suppliers to "active". + * + * Links with the DL_FLAG_STATELESS flag set are ignored. + */ +void device_links_driver_bound(struct device *dev) +{ + struct device_link *link; + + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.consumers, s_node) { + if (link->flags & DL_FLAG_STATELESS) + continue; + + WARN_ON(link->status != DL_STATE_DORMANT); + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); + } + + list_for_each_entry(link, &dev->links.suppliers, c_node) { + if (link->flags & DL_FLAG_STATELESS) + continue; + + WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); + WRITE_ONCE(link->status, DL_STATE_ACTIVE); + } + + dev->links.status = DL_DEV_DRIVER_BOUND; + + device_links_write_unlock(); +} + +/** + * __device_links_no_driver - Update links of a device without a driver. + * @dev: Device without a drvier. + * + * Delete all non-persistent links from this device to any suppliers. + * + * Persistent links stay around, but their status is changed to "available", + * unless they already are in the "supplier unbind in progress" state in which + * case they need not be updated. + * + * Links with the DL_FLAG_STATELESS flag set are ignored. + */ +static void __device_links_no_driver(struct device *dev) +{ + struct device_link *link, *ln; + + list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { + if (link->flags & DL_FLAG_STATELESS) + continue; + + if (link->flags & DL_FLAG_AUTOREMOVE) + __device_link_del(link); + else if (link->status != DL_STATE_SUPPLIER_UNBIND) + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); + } + + dev->links.status = DL_DEV_NO_DRIVER; +} + +void device_links_no_driver(struct device *dev) +{ + device_links_write_lock(); + __device_links_no_driver(dev); + device_links_write_unlock(); +} + +/** + * device_links_driver_cleanup - Update links after driver removal. + * @dev: Device whose driver has just gone away. + * + * Update links to consumers for @dev by changing their status to "dormant" and + * invoke %__device_links_no_driver() to update links to suppliers for it as + * appropriate. + * + * Links with the DL_FLAG_STATELESS flag set are ignored. + */ +void device_links_driver_cleanup(struct device *dev) +{ + struct device_link *link; + + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.consumers, s_node) { + if (link->flags & DL_FLAG_STATELESS) + continue; + + WARN_ON(link->flags & DL_FLAG_AUTOREMOVE); + WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); + WRITE_ONCE(link->status, DL_STATE_DORMANT); + } + + __device_links_no_driver(dev); + + device_links_write_unlock(); +} + +/** + * device_links_busy - Check if there are any busy links to consumers. + * @dev: Device to check. + * + * Check each consumer of the device and return 'true' if its link's status + * is one of "consumer probe" or "active" (meaning that the given consumer is + * probing right now or its driver is present). Otherwise, change the link + * state to "supplier unbind" to prevent the consumer from being probed + * successfully going forward. + * + * Return 'false' if there are no probing or active consumers. + * + * Links with the DL_FLAG_STATELESS flag set are ignored. + */ +bool device_links_busy(struct device *dev) +{ + struct device_link *link; + bool ret = false; + + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.consumers, s_node) { + if (link->flags & DL_FLAG_STATELESS) + continue; + + if (link->status == DL_STATE_CONSUMER_PROBE + || link->status == DL_STATE_ACTIVE) { + ret = true; + break; + } + WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND); + } + + dev->links.status = DL_DEV_UNBINDING; + + device_links_write_unlock(); + return ret; +} + +/** + * device_links_unbind_consumers - Force unbind consumers of the given device. + * @dev: Device to unbind the consumers of. + * + * Walk the list of links to consumers for @dev and if any of them is in the + * "consumer probe" state, wait for all device probes in progress to complete + * and start over. + * + * If that's not the case, change the status of the link to "supplier unbind" + * and check if the link was in the "active" state. If so, force the consumer + * driver to unbind and start over (the consumer will not re-probe as we have + * changed the state of the link already). + * + * Links with the DL_FLAG_STATELESS flag set are ignored. + */ +void device_links_unbind_consumers(struct device *dev) +{ + struct device_link *link; + + start: + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.consumers, s_node) { + enum device_link_state status; + + if (link->flags & DL_FLAG_STATELESS) + continue; + + status = link->status; + if (status == DL_STATE_CONSUMER_PROBE) { + device_links_write_unlock(); + + wait_for_device_probe(); + goto start; + } + WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND); + if (status == DL_STATE_ACTIVE) { + struct device *consumer = link->consumer; + + get_device(consumer); + + device_links_write_unlock(); + + device_release_driver_internal(consumer, NULL, + consumer->parent); + put_device(consumer); + goto start; + } + } + + device_links_write_unlock(); +} + +/** + * device_links_purge - Delete existing links to other devices. + * @dev: Target device. + */ +static void device_links_purge(struct device *dev) +{ + struct device_link *link, *ln; + + /* + * Delete all of the remaining links from this device to any other + * devices (either consumers or suppliers). + */ + device_links_write_lock(); + + list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { + WARN_ON(link->status == DL_STATE_ACTIVE); + __device_link_del(link); + } + + list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) { + WARN_ON(link->status != DL_STATE_DORMANT && + link->status != DL_STATE_NONE); + __device_link_del(link); + } + + device_links_write_unlock(); +} + +/* Device links support end. */ + int (*platform_notify)(struct device *dev) = NULL; int (*platform_notify_remove)(struct device *dev) = NULL; static struct kobject *dev_kobj; @@ -711,6 +1246,9 @@ void device_initialize(struct device *dev) #ifdef CONFIG_GENERIC_MSI_IRQ INIT_LIST_HEAD(&dev->msi_list); #endif + INIT_LIST_HEAD(&dev->links.consumers); + INIT_LIST_HEAD(&dev->links.suppliers); + dev->links.status = DL_DEV_NO_DRIVER; } EXPORT_SYMBOL_GPL(device_initialize); @@ -1258,6 +1796,8 @@ void device_del(struct device *dev) if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DEL_DEVICE, dev); + + device_links_purge(dev); dpm_sysfs_remove(dev); if (parent) klist_del(&dev->p->knode_parent); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index df4ab5509c04..b2bca3cf0dd2 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -244,6 +244,7 @@ static void driver_bound(struct device *dev) __func__, dev_name(dev)); klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); + device_links_driver_bound(dev); device_pm_check_callbacks(dev); @@ -337,6 +338,10 @@ static int really_probe(struct device *dev, struct device_driver *drv) return ret; } + ret = device_links_check_suppliers(dev); + if (ret) + return ret; + atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); @@ -415,6 +420,7 @@ probe_failed: blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DRIVER_NOT_BOUND, dev); pinctrl_bind_failed: + device_links_no_driver(dev); devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; @@ -771,7 +777,7 @@ EXPORT_SYMBOL_GPL(driver_attach); * __device_release_driver() must be called with @dev lock held. * When called for a USB interface, @dev->parent lock must be held as well. */ -static void __device_release_driver(struct device *dev) +static void __device_release_driver(struct device *dev, struct device *parent) { struct device_driver *drv; @@ -780,6 +786,25 @@ static void __device_release_driver(struct device *dev) if (driver_allows_async_probing(drv)) async_synchronize_full(); + while (device_links_busy(dev)) { + device_unlock(dev); + if (parent) + device_unlock(parent); + + device_links_unbind_consumers(dev); + if (parent) + device_lock(parent); + + device_lock(dev); + /* + * A concurrent invocation of the same function might + * have released the driver successfully while this one + * was waiting, so check for that. + */ + if (dev->driver != drv) + return; + } + pm_runtime_get_sync(dev); driver_sysfs_remove(dev); @@ -795,6 +820,8 @@ static void __device_release_driver(struct device *dev) dev->bus->remove(dev); else if (drv->remove) drv->remove(dev); + + device_links_driver_cleanup(dev); devres_release_all(dev); dev->driver = NULL; dev_set_drvdata(dev, NULL); @@ -811,16 +838,16 @@ static void __device_release_driver(struct device *dev) } } -static void device_release_driver_internal(struct device *dev, - struct device_driver *drv, - struct device *parent) +void device_release_driver_internal(struct device *dev, + struct device_driver *drv, + struct device *parent) { if (parent) device_lock(parent); device_lock(dev); if (!drv || drv == dev->driver) - __device_release_driver(dev); + __device_release_driver(dev, parent); device_unlock(dev); if (parent) @@ -833,6 +860,10 @@ static void device_release_driver_internal(struct device *dev, * * Manually detach device from driver. * When called for a USB interface, @dev->parent lock must be held. + * + * If this function is to be called with @dev->parent lock held, ensure that + * the device's consumers are unbound in advance or that their locks can be + * acquired under the @dev->parent lock. */ void device_release_driver(struct device *dev) { diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index e44944f4be77..420914061405 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -131,6 +131,7 @@ void device_pm_add(struct device *dev) dev_warn(dev, "parent %s should not be sleeping\n", dev_name(dev->parent)); list_add_tail(&dev->power.entry, &dpm_list); + dev->power.in_dpm_list = true; mutex_unlock(&dpm_list_mtx); } @@ -145,6 +146,7 @@ void device_pm_remove(struct device *dev) complete_all(&dev->power.completion); mutex_lock(&dpm_list_mtx); list_del_init(&dev->power.entry); + dev->power.in_dpm_list = false; mutex_unlock(&dpm_list_mtx); device_wakeup_disable(dev); pm_runtime_remove(dev); diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 50e30e7b059d..0ba7842d665b 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -127,6 +127,11 @@ extern void device_pm_move_after(struct device *, struct device *); extern void device_pm_move_last(struct device *); extern void device_pm_check_callbacks(struct device *dev); +static inline bool device_pm_initialized(struct device *dev) +{ + return dev->power.in_dpm_list; +} + #else /* !CONFIG_PM_SLEEP */ static inline void device_pm_sleep_init(struct device *dev) {} @@ -146,6 +151,11 @@ static inline void device_pm_move_last(struct device *dev) {} static inline void device_pm_check_callbacks(struct device *dev) {} +static inline bool device_pm_initialized(struct device *dev) +{ + return device_is_registered(dev); +} + #endif /* !CONFIG_PM_SLEEP */ static inline void device_pm_init(struct device *dev) diff --git a/include/linux/device.h b/include/linux/device.h index bc41e87a969b..9cae2feaf5cb 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -707,6 +707,81 @@ struct device_dma_parameters { unsigned long segment_boundary_mask; }; +/** + * enum device_link_state - Device link states. + * @DL_STATE_NONE: The presence of the drivers is not being tracked. + * @DL_STATE_DORMANT: None of the supplier/consumer drivers is present. + * @DL_STATE_AVAILABLE: The supplier driver is present, but the consumer is not. + * @DL_STATE_CONSUMER_PROBE: The consumer is probing (supplier driver present). + * @DL_STATE_ACTIVE: Both the supplier and consumer drivers are present. + * @DL_STATE_SUPPLIER_UNBIND: The supplier driver is unbinding. + */ +enum device_link_state { + DL_STATE_NONE = -1, + DL_STATE_DORMANT = 0, + DL_STATE_AVAILABLE, + DL_STATE_CONSUMER_PROBE, + DL_STATE_ACTIVE, + DL_STATE_SUPPLIER_UNBIND, +}; + +/* + * Device link flags. + * + * STATELESS: The core won't track the presence of supplier/consumer drivers. + * AUTOREMOVE: Remove this link automatically on consumer driver unbind. + */ +#define DL_FLAG_STATELESS BIT(0) +#define DL_FLAG_AUTOREMOVE BIT(1) + +/** + * struct device_link - Device link representation. + * @supplier: The device on the supplier end of the link. + * @s_node: Hook to the supplier device's list of links to consumers. + * @consumer: The device on the consumer end of the link. + * @c_node: Hook to the consumer device's list of links to suppliers. + * @status: The state of the link (with respect to the presence of drivers). + * @flags: Link flags. + * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. + */ +struct device_link { + struct device *supplier; + struct list_head s_node; + struct device *consumer; + struct list_head c_node; + enum device_link_state status; + u32 flags; +#ifdef CONFIG_SRCU + struct rcu_head rcu_head; +#endif +}; + +/** + * enum dl_dev_state - Device driver presence tracking information. + * @DL_DEV_NO_DRIVER: There is no driver attached to the device. + * @DL_DEV_PROBING: A driver is probing. + * @DL_DEV_DRIVER_BOUND: The driver has been bound to the device. + * @DL_DEV_UNBINDING: The driver is unbinding from the device. + */ +enum dl_dev_state { + DL_DEV_NO_DRIVER = 0, + DL_DEV_PROBING, + DL_DEV_DRIVER_BOUND, + DL_DEV_UNBINDING, +}; + +/** + * struct dev_links_info - Device data related to device links. + * @suppliers: List of links to supplier devices. + * @consumers: List of links to consumer devices. + * @status: Driver status information. + */ +struct dev_links_info { + struct list_head suppliers; + struct list_head consumers; + enum dl_dev_state status; +}; + /** * struct device - The basic device structure * @parent: The device's "parent" device, the device to which it is attached. @@ -799,6 +874,7 @@ struct device { core doesn't touch it */ void *driver_data; /* Driver data, set and get with dev_set/get_drvdata */ + struct dev_links_info links; struct dev_pm_info power; struct dev_pm_domain *pm_domain; @@ -1116,6 +1192,10 @@ extern void device_shutdown(void); /* debugging and troubleshooting/diagnostic helpers. */ extern const char *dev_driver_string(const struct device *dev); +/* Device links interface. */ +struct device_link *device_link_add(struct device *consumer, + struct device *supplier, u32 flags); +void device_link_del(struct device_link *link); #ifdef CONFIG_PRINTK diff --git a/include/linux/pm.h b/include/linux/pm.h index 06eb353182ab..721a70241fcd 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -559,6 +559,7 @@ struct dev_pm_info { pm_message_t power_state; unsigned int can_wakeup:1; unsigned int async_suspend:1; + bool in_dpm_list:1; /* Owned by the PM core */ bool is_prepared:1; /* Owned by the PM core */ bool is_suspended:1; /* Ditto */ bool is_noirq_suspended:1; -- cgit v1.2.3 From 8c73b4288496407d91bc616df3f7c62a88356cb2 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Oct 2016 17:28:49 +0100 Subject: PM / sleep: Make async suspend/resume of devices use device links Make the device suspend/resume part of the core system suspend/resume code use device links to ensure that supplier and consumer devices will be suspended and resumed in the right order in case of async suspend/resume. The idea, roughly, is to use dpm_wait() to wait for all consumers before a supplier device suspend and to wait for all suppliers before a consumer device resume. Signed-off-by: Rafael J. Wysocki Tested-by: Marek Szyprowski Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 85 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 420914061405..04bcb11ed8de 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -246,6 +246,62 @@ static void dpm_wait_for_children(struct device *dev, bool async) device_for_each_child(dev, &async, dpm_wait_fn); } +static void dpm_wait_for_suppliers(struct device *dev, bool async) +{ + struct device_link *link; + int idx; + + idx = device_links_read_lock(); + + /* + * If the supplier goes away right after we've checked the link to it, + * we'll wait for its completion to change the state, but that's fine, + * because the only things that will block as a result are the SRCU + * callbacks freeing the link objects for the links in the list we're + * walking. + */ + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) + if (READ_ONCE(link->status) != DL_STATE_DORMANT) + dpm_wait(link->supplier, async); + + device_links_read_unlock(idx); +} + +static void dpm_wait_for_superior(struct device *dev, bool async) +{ + dpm_wait(dev->parent, async); + dpm_wait_for_suppliers(dev, async); +} + +static void dpm_wait_for_consumers(struct device *dev, bool async) +{ + struct device_link *link; + int idx; + + idx = device_links_read_lock(); + + /* + * The status of a device link can only be changed from "dormant" by a + * probe, but that cannot happen during system suspend/resume. In + * theory it can change to "dormant" at that time, but then it is + * reasonable to wait for the target device anyway (eg. if it goes + * away, it's better to wait for it to go away completely and then + * continue instead of trying to continue in parallel with its + * unregistration). + */ + list_for_each_entry_rcu(link, &dev->links.consumers, s_node) + if (READ_ONCE(link->status) != DL_STATE_DORMANT) + dpm_wait(link->consumer, async); + + device_links_read_unlock(idx); +} + +static void dpm_wait_for_subordinate(struct device *dev, bool async) +{ + dpm_wait_for_children(dev, async); + dpm_wait_for_consumers(dev, async); +} + /** * pm_op - Return the PM operation appropriate for given PM event. * @ops: PM operations to choose from. @@ -490,7 +546,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn if (!dev->power.is_noirq_suspended) goto Out; - dpm_wait(dev->parent, async); + dpm_wait_for_superior(dev, async); if (dev->pm_domain) { info = "noirq power domain "; @@ -620,7 +676,7 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn if (!dev->power.is_late_suspended) goto Out; - dpm_wait(dev->parent, async); + dpm_wait_for_superior(dev, async); if (dev->pm_domain) { info = "early power domain "; @@ -752,7 +808,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) goto Complete; } - dpm_wait(dev->parent, async); + dpm_wait_for_superior(dev, async); dpm_watchdog_set(&wd, dev); device_lock(dev); @@ -1040,7 +1096,7 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a if (dev->power.syscore || dev->power.direct_complete) goto Complete; - dpm_wait_for_children(dev, async); + dpm_wait_for_subordinate(dev, async); if (dev->pm_domain) { info = "noirq power domain "; @@ -1187,7 +1243,7 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as if (dev->power.syscore || dev->power.direct_complete) goto Complete; - dpm_wait_for_children(dev, async); + dpm_wait_for_subordinate(dev, async); if (dev->pm_domain) { info = "late power domain "; @@ -1344,6 +1400,22 @@ static int legacy_suspend(struct device *dev, pm_message_t state, return error; } +static void dpm_clear_suppliers_direct_complete(struct device *dev) +{ + struct device_link *link; + int idx; + + idx = device_links_read_lock(); + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) { + spin_lock_irq(&link->supplier->power.lock); + link->supplier->power.direct_complete = false; + spin_unlock_irq(&link->supplier->power.lock); + } + + device_links_read_unlock(idx); +} + /** * device_suspend - Execute "suspend" callbacks for given device. * @dev: Device to handle. @@ -1360,7 +1432,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) TRACE_DEVICE(dev); TRACE_SUSPEND(0); - dpm_wait_for_children(dev, async); + dpm_wait_for_subordinate(dev, async); if (async_error) goto Complete; @@ -1456,6 +1528,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) spin_unlock_irq(&parent->power.lock); } + dpm_clear_suppliers_direct_complete(dev); } device_unlock(dev); -- cgit v1.2.3 From 21d5c57b3726166421251e94dabab047baaf8ce4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Oct 2016 17:32:31 +0100 Subject: PM / runtime: Use device links Modify the runtime PM framework to use device links to ensure that supplier devices will not be suspended if any of their consumer devices are active. The idea is to reference count suppliers on the consumer's resume and drop references to them on its suspend. The information on whether or not the supplier has been reference counted by the consumer's (runtime) resume is stored in a new field (rpm_active) in the link object for each link. It may be necessary to clean up those references when the supplier is unbinding and that's why the links whose status is DEVICE_LINK_SUPPLIER_UNBIND are skipped by the runtime suspend and resume code. The above means that if the consumer device is probed in the runtime-active state, the supplier has to be resumed and reference counted by device_link_add() so the code works as expected on its (runtime) suspend. There is a new flag, DEVICE_LINK_RPM_ACTIVE, to tell device_link_add() about that (in which case the caller is responsible for making sure that the consumer really will be runtime-active when runtime PM is enabled for it). The other new link flag, DEVICE_LINK_PM_RUNTIME, tells the core whether or not the link should be used for runtime PM at all. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 27 +++++++- drivers/base/dd.c | 3 + drivers/base/power/runtime.c | 157 +++++++++++++++++++++++++++++++++++++++++-- include/linux/device.h | 6 ++ include/linux/pm_runtime.h | 6 ++ 5 files changed, 193 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 3c5ff17f578f..876c62b12462 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -152,6 +152,14 @@ static int device_reorder_to_tail(struct device *dev, void *not_used) * @supplier: Supplier end of the link. * @flags: Link flags. * + * The caller is responsible for the proper synchronization of the link creation + * with runtime PM. First, setting the DL_FLAG_PM_RUNTIME flag will cause the + * runtime PM framework to take the link into account. Second, if the + * DL_FLAG_RPM_ACTIVE flag is set in addition to it, the supplier devices will + * be forced into the active metastate and reference-counted upon the creation + * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be + * ignored. + * * If the DL_FLAG_AUTOREMOVE is set, the link will be removed automatically * when the consumer device driver unbinds from it. The combination of both * DL_FLAG_AUTOREMOVE and DL_FLAG_STATELESS set is invalid and will cause NULL @@ -193,10 +201,19 @@ struct device_link *device_link_add(struct device *consumer, if (link->consumer == consumer) goto out; - link = kmalloc(sizeof(*link), GFP_KERNEL); + link = kzalloc(sizeof(*link), GFP_KERNEL); if (!link) goto out; + if ((flags & DL_FLAG_PM_RUNTIME) && (flags & DL_FLAG_RPM_ACTIVE)) { + if (pm_runtime_get_sync(supplier) < 0) { + pm_runtime_put_noidle(supplier); + kfree(link); + link = NULL; + goto out; + } + link->rpm_active = true; + } get_device(supplier); link->supplier = supplier; INIT_LIST_HEAD(&link->s_node); @@ -213,6 +230,14 @@ struct device_link *device_link_add(struct device *consumer, case DL_DEV_DRIVER_BOUND: switch (consumer->links.status) { case DL_DEV_PROBING: + /* + * Balance the decrementation of the supplier's + * runtime PM usage counter after consumer probe + * in driver_probe_device(). + */ + if (flags & DL_FLAG_PM_RUNTIME) + pm_runtime_get_sync(supplier); + link->status = DL_STATE_CONSUMER_PROBE; break; case DL_DEV_DRIVER_BOUND: diff --git a/drivers/base/dd.c b/drivers/base/dd.c index b2bca3cf0dd2..43be1cc751a4 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -513,6 +513,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev) pr_debug("bus: '%s': %s: matched device %s with driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); + pm_runtime_get_suppliers(dev); if (dev->parent) pm_runtime_get_sync(dev->parent); @@ -523,6 +524,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev) if (dev->parent) pm_runtime_put(dev->parent); + pm_runtime_put_suppliers(dev); return ret; } @@ -806,6 +808,7 @@ static void __device_release_driver(struct device *dev, struct device *parent) } pm_runtime_get_sync(dev); + pm_runtime_clean_up_links(dev); driver_sysfs_remove(dev); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 82a081ea4317..462f90e952f8 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -12,6 +12,8 @@ #include #include #include + +#include "../base.h" #include "power.h" typedef int (*pm_callback_t)(struct device *); @@ -258,6 +260,42 @@ static int rpm_check_suspend_allowed(struct device *dev) return retval; } +static int rpm_get_suppliers(struct device *dev) +{ + struct device_link *link; + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) { + int retval; + + if (!(link->flags & DL_FLAG_PM_RUNTIME)) + continue; + + if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND || + link->rpm_active) + continue; + + retval = pm_runtime_get_sync(link->supplier); + if (retval < 0) { + pm_runtime_put_noidle(link->supplier); + return retval; + } + link->rpm_active = true; + } + return 0; +} + +static void rpm_put_suppliers(struct device *dev) +{ + struct device_link *link; + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) + if (link->rpm_active && + READ_ONCE(link->status) != DL_STATE_SUPPLIER_UNBIND) { + pm_runtime_put(link->supplier); + link->rpm_active = false; + } +} + /** * __rpm_callback - Run a given runtime PM callback for a given device. * @cb: Runtime PM callback to run. @@ -266,19 +304,55 @@ static int rpm_check_suspend_allowed(struct device *dev) static int __rpm_callback(int (*cb)(struct device *), struct device *dev) __releases(&dev->power.lock) __acquires(&dev->power.lock) { - int retval; + int retval, idx; - if (dev->power.irq_safe) + if (dev->power.irq_safe) { spin_unlock(&dev->power.lock); - else + } else { spin_unlock_irq(&dev->power.lock); + /* + * Resume suppliers if necessary. + * + * The device's runtime PM status cannot change until this + * routine returns, so it is safe to read the status outside of + * the lock. + */ + if (dev->power.runtime_status == RPM_RESUMING) { + idx = device_links_read_lock(); + + retval = rpm_get_suppliers(dev); + if (retval) + goto fail; + + device_links_read_unlock(idx); + } + } + retval = cb(dev); - if (dev->power.irq_safe) + if (dev->power.irq_safe) { spin_lock(&dev->power.lock); - else + } else { + /* + * If the device is suspending and the callback has returned + * success, drop the usage counters of the suppliers that have + * been reference counted on its resume. + * + * Do that if resume fails too. + */ + if ((dev->power.runtime_status == RPM_SUSPENDING && !retval) + || (dev->power.runtime_status == RPM_RESUMING && retval)) { + idx = device_links_read_lock(); + + fail: + rpm_put_suppliers(dev); + + device_links_read_unlock(idx); + } + spin_lock_irq(&dev->power.lock); + } return retval; } @@ -1446,6 +1520,79 @@ void pm_runtime_remove(struct device *dev) pm_runtime_reinit(dev); } +/** + * pm_runtime_clean_up_links - Prepare links to consumers for driver removal. + * @dev: Device whose driver is going to be removed. + * + * Check links from this device to any consumers and if any of them have active + * runtime PM references to the device, drop the usage counter of the device + * (once per link). + * + * Links with the DL_FLAG_STATELESS flag set are ignored. + * + * Since the device is guaranteed to be runtime-active at the point this is + * called, nothing else needs to be done here. + * + * Moreover, this is called after device_links_busy() has returned 'false', so + * the status of each link is guaranteed to be DL_STATE_SUPPLIER_UNBIND and + * therefore rpm_active can't be manipulated concurrently. + */ +void pm_runtime_clean_up_links(struct device *dev) +{ + struct device_link *link; + int idx; + + idx = device_links_read_lock(); + + list_for_each_entry_rcu(link, &dev->links.consumers, s_node) { + if (link->flags & DL_FLAG_STATELESS) + continue; + + if (link->rpm_active) { + pm_runtime_put_noidle(dev); + link->rpm_active = false; + } + } + + device_links_read_unlock(idx); +} + +/** + * pm_runtime_get_suppliers - Resume and reference-count supplier devices. + * @dev: Consumer device. + */ +void pm_runtime_get_suppliers(struct device *dev) +{ + struct device_link *link; + int idx; + + idx = device_links_read_lock(); + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) + if (link->flags & DL_FLAG_PM_RUNTIME) + pm_runtime_get_sync(link->supplier); + + device_links_read_unlock(idx); +} + +/** + * pm_runtime_put_suppliers - Drop references to supplier devices. + * @dev: Consumer device. + */ +void pm_runtime_put_suppliers(struct device *dev) +{ + struct device_link *link; + int idx; + + idx = device_links_read_lock(); + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) + if (link->flags & DL_FLAG_PM_RUNTIME) + pm_runtime_put(link->supplier); + + device_links_read_unlock(idx); +} + /** * pm_runtime_force_suspend - Force a device into suspend state if needed. * @dev: Device to suspend. diff --git a/include/linux/device.h b/include/linux/device.h index 9cae2feaf5cb..49f453892ca5 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -730,9 +730,13 @@ enum device_link_state { * * STATELESS: The core won't track the presence of supplier/consumer drivers. * AUTOREMOVE: Remove this link automatically on consumer driver unbind. + * PM_RUNTIME: If set, the runtime PM framework will use this link. + * RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation. */ #define DL_FLAG_STATELESS BIT(0) #define DL_FLAG_AUTOREMOVE BIT(1) +#define DL_FLAG_PM_RUNTIME BIT(2) +#define DL_FLAG_RPM_ACTIVE BIT(3) /** * struct device_link - Device link representation. @@ -742,6 +746,7 @@ enum device_link_state { * @c_node: Hook to the consumer device's list of links to suppliers. * @status: The state of the link (with respect to the presence of drivers). * @flags: Link flags. + * @rpm_active: Whether or not the consumer device is runtime-PM-active. * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. */ struct device_link { @@ -751,6 +756,7 @@ struct device_link { struct list_head c_node; enum device_link_state status; u32 flags; + bool rpm_active; #ifdef CONFIG_SRCU struct rcu_head rcu_head; #endif diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 2e14d2667b6c..c2ee87138e4a 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -55,6 +55,9 @@ extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev); extern void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns); extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable); +extern void pm_runtime_clean_up_links(struct device *dev); +extern void pm_runtime_get_suppliers(struct device *dev); +extern void pm_runtime_put_suppliers(struct device *dev); static inline void pm_suspend_ignore_children(struct device *dev, bool enable) { @@ -186,6 +189,9 @@ static inline unsigned long pm_runtime_autosuspend_expiration( struct device *dev) { return 0; } static inline void pm_runtime_set_memalloc_noio(struct device *dev, bool enable){} +static inline void pm_runtime_clean_up_links(struct device *dev) {} +static inline void pm_runtime_get_suppliers(struct device *dev) {} +static inline void pm_runtime_put_suppliers(struct device *dev) {} #endif /* !CONFIG_PM */ -- cgit v1.2.3 From baa8809f60971d10220dfe79248f54b2b265f003 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Oct 2016 17:32:43 +0100 Subject: PM / runtime: Optimize the use of device links If the device has no links to suppliers that should be used for runtime PM (links with DEVICE_LINK_PM_RUNTIME set), there is no reason to walk the list of suppliers for that device during runtime suspend and resume. Add a simple mechanism to detect that case and possibly avoid the extra unnecessary overhead. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 20 +++++++++++++------- drivers/base/power/runtime.c | 23 ++++++++++++++++++++--- include/linux/pm.h | 1 + include/linux/pm_runtime.h | 4 ++++ 4 files changed, 38 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 876c62b12462..d0c9df5cdd9e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -205,14 +205,17 @@ struct device_link *device_link_add(struct device *consumer, if (!link) goto out; - if ((flags & DL_FLAG_PM_RUNTIME) && (flags & DL_FLAG_RPM_ACTIVE)) { - if (pm_runtime_get_sync(supplier) < 0) { - pm_runtime_put_noidle(supplier); - kfree(link); - link = NULL; - goto out; + if (flags & DL_FLAG_PM_RUNTIME) { + if (flags & DL_FLAG_RPM_ACTIVE) { + if (pm_runtime_get_sync(supplier) < 0) { + pm_runtime_put_noidle(supplier); + kfree(link); + link = NULL; + goto out; + } + link->rpm_active = true; } - link->rpm_active = true; + pm_runtime_new_link(consumer); } get_device(supplier); link->supplier = supplier; @@ -296,6 +299,9 @@ static void __device_link_del(struct device_link *link) dev_info(link->consumer, "Dropping the link to %s\n", dev_name(link->supplier)); + if (link->flags & DL_FLAG_PM_RUNTIME) + pm_runtime_drop_link(link->consumer); + list_del_rcu(&link->s_node); list_del_rcu(&link->c_node); call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 462f90e952f8..ba7b4a8c07e5 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -305,6 +305,7 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev) __releases(&dev->power.lock) __acquires(&dev->power.lock) { int retval, idx; + bool use_links = dev->power.links_count > 0; if (dev->power.irq_safe) { spin_unlock(&dev->power.lock); @@ -318,7 +319,7 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev) * routine returns, so it is safe to read the status outside of * the lock. */ - if (dev->power.runtime_status == RPM_RESUMING) { + if (use_links && dev->power.runtime_status == RPM_RESUMING) { idx = device_links_read_lock(); retval = rpm_get_suppliers(dev); @@ -341,8 +342,9 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev) * * Do that if resume fails too. */ - if ((dev->power.runtime_status == RPM_SUSPENDING && !retval) - || (dev->power.runtime_status == RPM_RESUMING && retval)) { + if (use_links + && ((dev->power.runtime_status == RPM_SUSPENDING && !retval) + || (dev->power.runtime_status == RPM_RESUMING && retval))) { idx = device_links_read_lock(); fail: @@ -1593,6 +1595,21 @@ void pm_runtime_put_suppliers(struct device *dev) device_links_read_unlock(idx); } +void pm_runtime_new_link(struct device *dev) +{ + spin_lock_irq(&dev->power.lock); + dev->power.links_count++; + spin_unlock_irq(&dev->power.lock); +} + +void pm_runtime_drop_link(struct device *dev) +{ + spin_lock_irq(&dev->power.lock); + WARN_ON(dev->power.links_count == 0); + dev->power.links_count--; + spin_unlock_irq(&dev->power.lock); +} + /** * pm_runtime_force_suspend - Force a device into suspend state if needed. * @dev: Device to suspend. diff --git a/include/linux/pm.h b/include/linux/pm.h index 721a70241fcd..ccfe00ecc7e6 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -597,6 +597,7 @@ struct dev_pm_info { unsigned int use_autosuspend:1; unsigned int timer_autosuspends:1; unsigned int memalloc_noio:1; + unsigned int links_count; enum rpm_request request; enum rpm_status runtime_status; int runtime_error; diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index c2ee87138e4a..73814877537d 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -58,6 +58,8 @@ extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable); extern void pm_runtime_clean_up_links(struct device *dev); extern void pm_runtime_get_suppliers(struct device *dev); extern void pm_runtime_put_suppliers(struct device *dev); +extern void pm_runtime_new_link(struct device *dev); +extern void pm_runtime_drop_link(struct device *dev); static inline void pm_suspend_ignore_children(struct device *dev, bool enable) { @@ -192,6 +194,8 @@ static inline void pm_runtime_set_memalloc_noio(struct device *dev, static inline void pm_runtime_clean_up_links(struct device *dev) {} static inline void pm_runtime_get_suppliers(struct device *dev) {} static inline void pm_runtime_put_suppliers(struct device *dev) {} +static inline void pm_runtime_new_link(struct device *dev) {} +static inline void pm_runtime_drop_link(struct device *dev) {} #endif /* !CONFIG_PM */ -- cgit v1.2.3 From 542ccf4551fa019a8ae9dfb7c8cd7e73a3d7e614 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 31 Oct 2016 12:04:09 +0100 Subject: PCI: hv: Make unnecessarily global IRQ masking functions static Make hv_irq_mask() and hv_irq_unmask() static as they are only used in pci-hyperv.c This fixes a sparse warning. Signed-off-by: Tobias Klauser Signed-off-by: Bjorn Helgaas Acked-by: K. Y. Srinivasan --- drivers/pci/host/pci-hyperv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index 763ff8745828..06c98695c06c 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -755,7 +755,7 @@ static int hv_set_affinity(struct irq_data *data, const struct cpumask *dest, return parent->chip->irq_set_affinity(parent, dest, force); } -void hv_irq_mask(struct irq_data *data) +static void hv_irq_mask(struct irq_data *data) { pci_msi_mask_irq(data); } @@ -770,7 +770,7 @@ void hv_irq_mask(struct irq_data *data) * is built out of this PCI bus's instance GUID and the function * number of the device. */ -void hv_irq_unmask(struct irq_data *data) +static void hv_irq_unmask(struct irq_data *data) { struct msi_desc *msi_desc = irq_data_get_msi_desc(data); struct irq_cfg *cfg = irqd_cfg(data); -- cgit v1.2.3 From 8778b276645bb156b00d72275541a4e4b188d6dc Mon Sep 17 00:00:00 2001 From: Aaron Young Date: Fri, 28 Oct 2016 14:26:19 -0400 Subject: ldmvsw: tx queue stuck in stopped state after LDC reset The following patch fixes an issue with the ldmvsw driver where the network connection of a guest domain becomes non-functional after the guest domain has panic'd and rebooted. The root cause was determined to be from the following series of events: 1. Guest domain panics - resulting in the guest no longer processing network packets (from ldmvsw driver) 2. The ldmvsw driver (in the control domain) eventually exerts flow control due to no more available tx drings and stops the tx queue for the guest domain 3. The LDC of the network connection for the guest is reset when the guest domain reboots after the panic. 4. The LDC reset event is received by the ldmvsw driver and the ldmvsw responds by clearing the tx queue for the guest. 5. ldmvsw waits indefinitely for a DATA ACK from the guest - which is the normal method to re-enable the tx queue. But the ACK never comes because the tx queue was cleared due to the LDC reset. To fix this issue, in addition to clearing the tx queue, re-enable the tx queue on a LDC reset. This prevents the ldmvsw from getting caught in this deadlocked state of waiting for a DATA ACK which will never come. Signed-off-by: Aaron Young Acked-by: Sowmini Varadhan Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sunvnet_common.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index 58efe69b7ba7..8878b75d68b4 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -704,9 +704,8 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf) return 0; } -/* Got back a STOPPED LDC message on port. If the queue is stopped, - * wake it up so that we'll send out another START message at the - * next TX. +/* If the queue is stopped, wake it up so that we'll + * send out another START message at the next TX. */ static void maybe_tx_wakeup(struct vnet_port *port) { @@ -734,6 +733,7 @@ EXPORT_SYMBOL_GPL(sunvnet_port_is_up_common); static int vnet_event_napi(struct vnet_port *port, int budget) { + struct net_device *dev = VNET_PORT_TO_NET_DEVICE(port); struct vio_driver_state *vio = &port->vio; int tx_wakeup, err; int npkts = 0; @@ -747,6 +747,16 @@ ldc_ctrl: if (event == LDC_EVENT_RESET) { vnet_port_reset(port); vio_port_up(vio); + + /* If the device is running but its tx queue was + * stopped (due to flow control), restart it. + * This is necessary since vnet_port_reset() + * clears the tx drings and thus we may never get + * back a VIO_TYPE_DATA ACK packet - which is + * the normal mechanism to restart the tx queue. + */ + if (netif_running(dev)) + maybe_tx_wakeup(port); } port->rx_event = 0; return 0; -- cgit v1.2.3 From 63215705a6cc4481dde21b5343bb706837f273d9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 29 Oct 2016 21:37:06 +0200 Subject: ptp: use permission-specific DEVICE_ATTR variants Use DEVICE_ATTR_RO for read only attributes. This simplifies the source code, improves readbility, and reduces the chance of inconsistencies. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @ro@ declarer name DEVICE_ATTR; identifier x,x_show; @@ DEVICE_ATTR(x, \(0444\|S_IRUGO\), x_show, NULL); @script:ocaml@ x << ro.x; x_show << ro.x_show; @@ if not (x^"_show" = x_show) then Coccilib.include_match false @@ declarer name DEVICE_ATTR_RO; identifier ro.x,ro.x_show; @@ - DEVICE_ATTR(x, \(0444\|S_IRUGO\), x_show, NULL); + DEVICE_ATTR_RO(x); // Signed-off-by: Julia Lawall Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/ptp/ptp_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c index 302e626fe6b0..53d43954a974 100644 --- a/drivers/ptp/ptp_sysfs.c +++ b/drivers/ptp/ptp_sysfs.c @@ -28,7 +28,7 @@ static ssize_t clock_name_show(struct device *dev, struct ptp_clock *ptp = dev_get_drvdata(dev); return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name); } -static DEVICE_ATTR(clock_name, 0444, clock_name_show, NULL); +static DEVICE_ATTR_RO(clock_name); #define PTP_SHOW_INT(name, var) \ static ssize_t var##_show(struct device *dev, \ -- cgit v1.2.3 From 89d9123e8ee28cb380ce5532038e89fc19471a77 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 29 Oct 2016 21:37:09 +0200 Subject: solos-pci: use permission-specific DEVICE_ATTR variants Use DEVICE_ATTR_RW for read-write attributes. This simplifies the source code, improves readbility, and reduces the chance of inconsistencies. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @rw@ declarer name DEVICE_ATTR; identifier x,x_show,x_store; @@ DEVICE_ATTR(x, \(0644\|S_IRUGO|S_IWUSR\), x_show, x_store); @script:ocaml@ x << rw.x; x_show << rw.x_show; x_store << rw.x_store; @@ if not (x^"_show" = x_show && x^"_store" = x_store) then Coccilib.include_match false @@ declarer name DEVICE_ATTR_RW; identifier rw.x,rw.x_show,rw.x_store; @@ - DEVICE_ATTR(x, \(0644\|S_IRUGO|S_IWUSR\), x_show, x_store); + DEVICE_ATTR_RW(x); // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/atm/solos-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 6ac2b2b1e8de..5ad037c07ec7 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -584,7 +584,7 @@ static ssize_t hardware_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", data32); } -static DEVICE_ATTR(console, 0644, console_show, console_store); +static DEVICE_ATTR_RW(console); #define SOLOS_ATTR_RO(x) static DEVICE_ATTR(x, 0444, solos_param_show, NULL); -- cgit v1.2.3 From 0fefbfbaad298162737d5418eb85065879f99b3e Mon Sep 17 00:00:00 2001 From: Sudarsana Kalluru Date: Mon, 31 Oct 2016 07:14:21 +0200 Subject: qed*: Management firmware - notifications and defaults Management firmware is interested in various tidbits about the driver - including the driver state & several configuration related fields [MTU, primtary MAC, etc.]. This adds the necessray logic to update MFW with such configurations, some of which are passed directly via qed while for others APIs are provide so that qede would be able to later configure if needed. This also introduces a new default configuration for MTU which would replace the default inherited by being an ethernet device. Signed-off-by: Sudarsana Kalluru Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 1 + drivers/net/ethernet/qlogic/qed/qed_dev.c | 52 +++++++- drivers/net/ethernet/qlogic/qed/qed_hsi.h | 59 ++++++++- drivers/net/ethernet/qlogic/qed/qed_main.c | 75 +++++++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 163 ++++++++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.h | 102 +++++++++++++++ drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 2 + drivers/net/ethernet/qlogic/qede/qede_main.c | 8 ++ include/linux/qed/qed_if.h | 28 ++++ 9 files changed, 487 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 653bb5735f0c..f20243c1fb0b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -226,6 +226,7 @@ struct qed_hw_info { u32 port_mode; u32 hw_mode; unsigned long device_capabilities; + u16 mtu; }; struct qed_hw_cid_data { diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index edae5fc5fccd..33fd69e24bae 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -1057,8 +1057,10 @@ int qed_hw_init(struct qed_dev *cdev, bool allow_npar_tx_switch, const u8 *bin_fw_data) { - u32 load_code, param; - int rc, mfw_rc, i; + u32 load_code, param, drv_mb_param; + bool b_default_mtu = true; + struct qed_hwfn *p_hwfn; + int rc = 0, mfw_rc, i; if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n"); @@ -1074,6 +1076,12 @@ int qed_hw_init(struct qed_dev *cdev, for_each_hwfn(cdev, i) { struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + /* If management didn't provide a default, set one of our own */ + if (!p_hwfn->hw_info.mtu) { + p_hwfn->hw_info.mtu = 1500; + b_default_mtu = false; + } + if (IS_VF(cdev)) { p_hwfn->b_int_enabled = 1; continue; @@ -1157,6 +1165,38 @@ int qed_hw_init(struct qed_dev *cdev, p_hwfn->hw_init_done = true; } + if (IS_PF(cdev)) { + p_hwfn = QED_LEADING_HWFN(cdev); + drv_mb_param = (FW_MAJOR_VERSION << 24) | + (FW_MINOR_VERSION << 16) | + (FW_REVISION_VERSION << 8) | + (FW_ENGINEERING_VERSION); + rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, + DRV_MSG_CODE_OV_UPDATE_STORM_FW_VER, + drv_mb_param, &load_code, ¶m); + if (rc) + DP_INFO(p_hwfn, "Failed to update firmware version\n"); + + if (!b_default_mtu) { + rc = qed_mcp_ov_update_mtu(p_hwfn, p_hwfn->p_main_ptt, + p_hwfn->hw_info.mtu); + if (rc) + DP_INFO(p_hwfn, + "Failed to update default mtu\n"); + } + + rc = qed_mcp_ov_update_driver_state(p_hwfn, + p_hwfn->p_main_ptt, + QED_OV_DRIVER_STATE_DISABLED); + if (rc) + DP_INFO(p_hwfn, "Failed to update driver state\n"); + + rc = qed_mcp_ov_update_eswitch(p_hwfn, p_hwfn->p_main_ptt, + QED_OV_ESWITCH_VEB); + if (rc) + DP_INFO(p_hwfn, "Failed to update eswitch mode\n"); + } + return 0; } @@ -1801,6 +1841,9 @@ qed_get_hw_info(struct qed_hwfn *p_hwfn, qed_get_num_funcs(p_hwfn, p_ptt); + if (qed_mcp_is_init(p_hwfn)) + p_hwfn->hw_info.mtu = p_hwfn->mcp_info->func_info.mtu; + return qed_hw_get_resc(p_hwfn); } @@ -1975,8 +2018,13 @@ int qed_hw_prepare(struct qed_dev *cdev, void qed_hw_remove(struct qed_dev *cdev) { + struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); int i; + if (IS_PF(cdev)) + qed_mcp_ov_update_driver_state(p_hwfn, p_hwfn->p_main_ptt, + QED_OV_DRIVER_STATE_NOT_LOADED); + for_each_hwfn(cdev, i) { struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 72eee29c677f..36de87a1befa 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -8564,6 +8564,15 @@ struct public_drv_mb { #define DRV_MSG_CODE_INIT_PHY 0x22000000 #define DRV_MSG_CODE_LINK_RESET 0x23000000 #define DRV_MSG_CODE_SET_DCBX 0x25000000 +#define DRV_MSG_CODE_OV_UPDATE_CURR_CFG 0x26000000 +#define DRV_MSG_CODE_OV_UPDATE_BUS_NUM 0x27000000 +#define DRV_MSG_CODE_OV_UPDATE_BOOT_PROGRESS 0x28000000 +#define DRV_MSG_CODE_OV_UPDATE_STORM_FW_VER 0x29000000 +#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE 0x31000000 +#define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000 +#define DRV_MSG_CODE_OV_UPDATE_MTU 0x33000000 +#define DRV_MSG_CODE_OV_UPDATE_WOL 0x38000000 +#define DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE 0x39000000 #define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000 #define DRV_MSG_CODE_NIG_DRAIN 0x30000000 @@ -8574,6 +8583,13 @@ struct public_drv_mb { #define DRV_MSG_CODE_MCP_RESET 0x00090000 #define DRV_MSG_CODE_SET_VERSION 0x000f0000 #define DRV_MSG_CODE_MCP_HALT 0x00100000 +#define DRV_MSG_CODE_SET_VMAC 0x00110000 +#define DRV_MSG_CODE_GET_VMAC 0x00120000 +#define DRV_MSG_CODE_VMAC_TYPE_SHIFT 4 +#define DRV_MSG_CODE_VMAC_TYPE_MASK 0x30 +#define DRV_MSG_CODE_VMAC_TYPE_MAC 1 +#define DRV_MSG_CODE_VMAC_TYPE_WWNN 2 +#define DRV_MSG_CODE_VMAC_TYPE_WWPN 3 #define DRV_MSG_CODE_GET_STATS 0x00130000 #define DRV_MSG_CODE_STATS_TYPE_LAN 1 @@ -8589,7 +8605,10 @@ struct public_drv_mb { #define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff u32 drv_mb_param; -#define DRV_MB_PARAM_UNLOAD_WOL_MCP 0x00000001 +#define DRV_MB_PARAM_UNLOAD_WOL_UNKNOWN 0x00000000 +#define DRV_MB_PARAM_UNLOAD_WOL_MCP 0x00000001 +#define DRV_MB_PARAM_UNLOAD_WOL_DISABLED 0x00000002 +#define DRV_MB_PARAM_UNLOAD_WOL_ENABLED 0x00000003 #define DRV_MB_PARAM_DCBX_NOTIFY_MASK 0x000000FF #define DRV_MB_PARAM_DCBX_NOTIFY_SHIFT 3 @@ -8602,6 +8621,44 @@ struct public_drv_mb { #define DRV_MB_PARAM_LLDP_SEND_MASK 0x00000001 #define DRV_MB_PARAM_LLDP_SEND_SHIFT 0 +#define DRV_MB_PARAM_OV_CURR_CFG_SHIFT 0 +#define DRV_MB_PARAM_OV_CURR_CFG_MASK 0x0000000F +#define DRV_MB_PARAM_OV_CURR_CFG_NONE 0 +#define DRV_MB_PARAM_OV_CURR_CFG_OS 1 +#define DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC 2 +#define DRV_MB_PARAM_OV_CURR_CFG_OTHER 3 + +#define DRV_MB_PARAM_OV_STORM_FW_VER_SHIFT 0 +#define DRV_MB_PARAM_OV_STORM_FW_VER_MASK 0xFFFFFFFF +#define DRV_MB_PARAM_OV_STORM_FW_VER_MAJOR_MASK 0xFF000000 +#define DRV_MB_PARAM_OV_STORM_FW_VER_MINOR_MASK 0x00FF0000 +#define DRV_MB_PARAM_OV_STORM_FW_VER_BUILD_MASK 0x0000FF00 +#define DRV_MB_PARAM_OV_STORM_FW_VER_DROP_MASK 0x000000FF + +#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_SHIFT 0 +#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_MASK 0xF +#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_UNKNOWN 0x1 +#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED 0x2 +#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_LOADING 0x3 +#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED 0x4 +#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE 0x5 + +#define DRV_MB_PARAM_OV_MTU_SIZE_SHIFT 0 +#define DRV_MB_PARAM_OV_MTU_SIZE_MASK 0xFFFFFFFF + +#define DRV_MB_PARAM_WOL_MASK (DRV_MB_PARAM_WOL_DEFAULT | \ + DRV_MB_PARAM_WOL_DISABLED | \ + DRV_MB_PARAM_WOL_ENABLED) +#define DRV_MB_PARAM_WOL_DEFAULT DRV_MB_PARAM_UNLOAD_WOL_MCP +#define DRV_MB_PARAM_WOL_DISABLED DRV_MB_PARAM_UNLOAD_WOL_DISABLED +#define DRV_MB_PARAM_WOL_ENABLED DRV_MB_PARAM_UNLOAD_WOL_ENABLED + +#define DRV_MB_PARAM_ESWITCH_MODE_MASK (DRV_MB_PARAM_ESWITCH_MODE_NONE | \ + DRV_MB_PARAM_ESWITCH_MODE_VEB | \ + DRV_MB_PARAM_ESWITCH_MODE_VEPA) +#define DRV_MB_PARAM_ESWITCH_MODE_NONE 0x0 +#define DRV_MB_PARAM_ESWITCH_MODE_VEB 0x1 +#define DRV_MB_PARAM_ESWITCH_MODE_VEPA 0x2 #define DRV_MB_PARAM_SET_LED_MODE_OPER 0x0 #define DRV_MB_PARAM_SET_LED_MODE_ON 0x1 diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index c418360ba02a..d9fa52a22667 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -243,6 +243,8 @@ int qed_fill_dev_info(struct qed_dev *cdev, &dev_info->mfw_rev, NULL); } + dev_info->mtu = QED_LEADING_HWFN(cdev)->hw_info.mtu; + return 0; } @@ -1431,6 +1433,76 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) return status; } +static int qed_update_drv_state(struct qed_dev *cdev, bool active) +{ + struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); + struct qed_ptt *ptt; + int status = 0; + + if (IS_VF(cdev)) + return 0; + + ptt = qed_ptt_acquire(hwfn); + if (!ptt) + return -EAGAIN; + + status = qed_mcp_ov_update_driver_state(hwfn, ptt, active ? + QED_OV_DRIVER_STATE_ACTIVE : + QED_OV_DRIVER_STATE_DISABLED); + + qed_ptt_release(hwfn, ptt); + + return status; +} + +static int qed_update_mac(struct qed_dev *cdev, u8 *mac) +{ + struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); + struct qed_ptt *ptt; + int status = 0; + + if (IS_VF(cdev)) + return 0; + + ptt = qed_ptt_acquire(hwfn); + if (!ptt) + return -EAGAIN; + + status = qed_mcp_ov_update_mac(hwfn, ptt, mac); + if (status) + goto out; + + status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); + +out: + qed_ptt_release(hwfn, ptt); + return status; +} + +static int qed_update_mtu(struct qed_dev *cdev, u16 mtu) +{ + struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); + struct qed_ptt *ptt; + int status = 0; + + if (IS_VF(cdev)) + return 0; + + ptt = qed_ptt_acquire(hwfn); + if (!ptt) + return -EAGAIN; + + status = qed_mcp_ov_update_mtu(hwfn, ptt, mtu); + if (status) + goto out; + + status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); + +out: + qed_ptt_release(hwfn, ptt); + return status; +} + static struct qed_selftest_ops qed_selftest_ops_pass = { .selftest_memory = &qed_selftest_memory, .selftest_interrupt = &qed_selftest_interrupt, @@ -1465,6 +1537,9 @@ const struct qed_common_ops qed_common_ops_pass = { .get_coalesce = &qed_get_coalesce, .set_coalesce = &qed_set_coalesce, .set_led = &qed_set_led, + .update_drv_state = &qed_update_drv_state, + .update_mac = &qed_update_mac, + .update_mtu = &qed_update_mtu, }; void qed_get_protocol_stats(struct qed_dev *cdev, diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index bdc9ba92f6d4..98dc913fd76d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "qed.h" #include "qed_dcbx.h" #include "qed_hsi.h" @@ -1068,6 +1069,8 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK); + info->mtu = (u16)shmem_info.mtu_size; + DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_IFUP), "Read configuration from shmem: pause_on_host %02x protocol %02x BW [%02x - %02x] MAC %02x:%02x:%02x:%02x:%02x:%02x wwn port %llx node %llx ovlan %04x\n", info->pause_on_host, info->protocol, @@ -1223,6 +1226,166 @@ int qed_mcp_resume(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) return (cpu_mode & MCP_REG_CPU_MODE_SOFT_HALT) ? -EAGAIN : 0; } +int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_ov_client client) +{ + u32 resp = 0, param = 0; + u32 drv_mb_param; + int rc; + + switch (client) { + case QED_OV_CLIENT_DRV: + drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OS; + break; + case QED_OV_CLIENT_USER: + drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OTHER; + break; + case QED_OV_CLIENT_VENDOR_SPEC: + drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC; + break; + default: + DP_NOTICE(p_hwfn, "Invalid client type %d\n", client); + return -EINVAL; + } + + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_CURR_CFG, + drv_mb_param, &resp, ¶m); + if (rc) + DP_ERR(p_hwfn, "MCP response failure, aborting\n"); + + return rc; +} + +int qed_mcp_ov_update_driver_state(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_ov_driver_state drv_state) +{ + u32 resp = 0, param = 0; + u32 drv_mb_param; + int rc; + + switch (drv_state) { + case QED_OV_DRIVER_STATE_NOT_LOADED: + drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED; + break; + case QED_OV_DRIVER_STATE_DISABLED: + drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED; + break; + case QED_OV_DRIVER_STATE_ACTIVE: + drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE; + break; + default: + DP_NOTICE(p_hwfn, "Invalid driver state %d\n", drv_state); + return -EINVAL; + } + + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE, + drv_mb_param, &resp, ¶m); + if (rc) + DP_ERR(p_hwfn, "Failed to send driver state\n"); + + return rc; +} + +int qed_mcp_ov_update_mtu(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, u16 mtu) +{ + u32 resp = 0, param = 0; + u32 drv_mb_param; + int rc; + + drv_mb_param = (u32)mtu << DRV_MB_PARAM_OV_MTU_SIZE_SHIFT; + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_MTU, + drv_mb_param, &resp, ¶m); + if (rc) + DP_ERR(p_hwfn, "Failed to send mtu value, rc = %d\n", rc); + + return rc; +} + +int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, u8 *mac) +{ + struct qed_mcp_mb_params mb_params; + union drv_union_data union_data; + int rc; + + memset(&mb_params, 0, sizeof(mb_params)); + mb_params.cmd = DRV_MSG_CODE_SET_VMAC; + mb_params.param = DRV_MSG_CODE_VMAC_TYPE_MAC << + DRV_MSG_CODE_VMAC_TYPE_SHIFT; + mb_params.param |= MCP_PF_ID(p_hwfn); + ether_addr_copy(&union_data.raw_data[0], mac); + mb_params.p_data_src = &union_data; + rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); + if (rc) + DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc); + + return rc; +} + +int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, enum qed_ov_wol wol) +{ + u32 resp = 0, param = 0; + u32 drv_mb_param; + int rc; + + switch (wol) { + case QED_OV_WOL_DEFAULT: + drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT; + break; + case QED_OV_WOL_DISABLED: + drv_mb_param = DRV_MB_PARAM_WOL_DISABLED; + break; + case QED_OV_WOL_ENABLED: + drv_mb_param = DRV_MB_PARAM_WOL_ENABLED; + break; + default: + DP_ERR(p_hwfn, "Invalid wol state %d\n", wol); + return -EINVAL; + } + + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_WOL, + drv_mb_param, &resp, ¶m); + if (rc) + DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc); + + return rc; +} + +int qed_mcp_ov_update_eswitch(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_ov_eswitch eswitch) +{ + u32 resp = 0, param = 0; + u32 drv_mb_param; + int rc; + + switch (eswitch) { + case QED_OV_ESWITCH_NONE: + drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_NONE; + break; + case QED_OV_ESWITCH_VEB: + drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEB; + break; + case QED_OV_ESWITCH_VEPA: + drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEPA; + break; + default: + DP_ERR(p_hwfn, "Invalid eswitch mode %d\n", eswitch); + return -EINVAL; + } + + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE, + drv_mb_param, &resp, ¶m); + if (rc) + DP_ERR(p_hwfn, "Failed to send eswitch mode, rc = %d\n", rc); + + return rc; +} + int qed_mcp_set_led(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, enum qed_led_mode mode) { diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index dff520ed069b..89507190628d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -92,6 +92,8 @@ struct qed_mcp_function_info { #define QED_MCP_VLAN_UNSET (0xffff) u16 ovlan; + + u16 mtu; }; struct qed_mcp_nvm_common { @@ -147,6 +149,30 @@ union qed_mcp_protocol_stats { struct qed_mcp_rdma_stats rdma_stats; }; +enum qed_ov_eswitch { + QED_OV_ESWITCH_NONE, + QED_OV_ESWITCH_VEB, + QED_OV_ESWITCH_VEPA +}; + +enum qed_ov_client { + QED_OV_CLIENT_DRV, + QED_OV_CLIENT_USER, + QED_OV_CLIENT_VENDOR_SPEC +}; + +enum qed_ov_driver_state { + QED_OV_DRIVER_STATE_NOT_LOADED, + QED_OV_DRIVER_STATE_DISABLED, + QED_OV_DRIVER_STATE_ACTIVE +}; + +enum qed_ov_wol { + QED_OV_WOL_DEFAULT, + QED_OV_WOL_DISABLED, + QED_OV_WOL_ENABLED +}; + /** * @brief - returns the link params of the hw function * @@ -277,6 +303,69 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, struct qed_mcp_drv_version *p_ver); +/** + * @brief Notify MFW about the change in base device properties + * + * @param p_hwfn + * @param p_ptt + * @param client - qed client type + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_ov_client client); + +/** + * @brief Notify MFW about the driver state + * + * @param p_hwfn + * @param p_ptt + * @param drv_state - Driver state + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_ov_update_driver_state(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_ov_driver_state drv_state); + +/** + * @brief Send MTU size to MFW + * + * @param p_hwfn + * @param p_ptt + * @param mtu - MTU size + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_ov_update_mtu(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, u16 mtu); + +/** + * @brief Send MAC address to MFW + * + * @param p_hwfn + * @param p_ptt + * @param mac - MAC address + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, u8 *mac); + +/** + * @brief Send WOL mode to MFW + * + * @param p_hwfn + * @param p_ptt + * @param wol - WOL mode + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_ov_wol wol); + /** * @brief Set LED status * @@ -546,4 +635,17 @@ int __qed_configure_pf_min_bandwidth(struct qed_hwfn *p_hwfn, int qed_mcp_mask_parities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u32 mask_parities); +/** + * @brief Send eswitch mode to MFW + * + * @param p_hwfn + * @param p_ptt + * @param eswitch - eswitch mode + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_ov_update_eswitch(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_ov_eswitch eswitch); + #endif diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index 0100f5c0a4ec..775fdaafd24d 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -739,6 +739,8 @@ int qede_change_mtu(struct net_device *ndev, int new_mtu) qede_update_mtu(edev, &args); + edev->ops->common->update_mtu(edev->cdev, args.mtu); + return 0; } diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 8488ad36a2b8..df0bd0ce2b18 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -2396,6 +2396,8 @@ static void qede_init_ndev(struct qede_dev *edev) /* Set network device HW mac */ ether_addr_copy(edev->ndev->dev_addr, edev->dev_info.common.hw_mac); + + ndev->mtu = edev->dev_info.common.mtu; } /* This function converts from 32b param to two params of level and module @@ -3751,6 +3753,8 @@ static int qede_open(struct net_device *ndev) udp_tunnel_get_rx_info(ndev); + edev->ops->common->update_drv_state(edev->cdev, true); + return 0; } @@ -3760,6 +3764,8 @@ static int qede_close(struct net_device *ndev) qede_unload(edev, QEDE_UNLOAD_NORMAL); + edev->ops->common->update_drv_state(edev->cdev, false); + return 0; } @@ -3820,6 +3826,8 @@ static int qede_set_mac_addr(struct net_device *ndev, void *p) if (rc) return rc; + edev->ops->common->update_mac(edev->cdev, addr->sa_data); + /* Add MAC filter according to the new unicast HW MAC address */ ether_addr_copy(edev->primary_mac, ndev->dev_addr); return qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_ADD, diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 8978a60371f4..5c909cd02764 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -267,6 +267,7 @@ struct qed_dev_info { u8 mf_mode; bool tx_switching; bool rdma_supported; + u16 mtu; }; enum qed_sb_type { @@ -554,6 +555,33 @@ struct qed_common_ops { */ int (*set_led)(struct qed_dev *cdev, enum qed_led_mode mode); + +/** + * @brief update_drv_state - API to inform the change in the driver state. + * + * @param cdev + * @param active + * + */ + int (*update_drv_state)(struct qed_dev *cdev, bool active); + +/** + * @brief update_mac - API to inform the change in the mac address + * + * @param cdev + * @param mac + * + */ + int (*update_mac)(struct qed_dev *cdev, u8 *mac); + +/** + * @brief update_mtu - API to inform the change in the mtu + * + * @param cdev + * @param mtu + * + */ + int (*update_mtu)(struct qed_dev *cdev, u16 mtu); }; #define MASK_FIELD(_name, _value) \ -- cgit v1.2.3 From 7a4b21b7d1f0644456501e33d3917c9aaee76a75 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Mon, 31 Oct 2016 07:14:22 +0200 Subject: qed: Add nvram selftest Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_hsi.h | 4 + drivers/net/ethernet/qlogic/qed/qed_main.c | 1 + drivers/net/ethernet/qlogic/qed/qed_mcp.c | 94 ++++++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.h | 41 ++++++++++ drivers/net/ethernet/qlogic/qed/qed_selftest.c | 101 ++++++++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_selftest.h | 10 +++ drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 7 ++ include/linux/qed/qed_if.h | 9 +++ 8 files changed, 267 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 36de87a1befa..f7dfa2ec2d19 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -8666,6 +8666,8 @@ struct public_drv_mb { #define DRV_MB_PARAM_BIST_REGISTER_TEST 1 #define DRV_MB_PARAM_BIST_CLOCK_TEST 2 +#define DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES 3 +#define DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX 4 #define DRV_MB_PARAM_BIST_RC_UNKNOWN 0 #define DRV_MB_PARAM_BIST_RC_PASSED 1 @@ -8674,6 +8676,8 @@ struct public_drv_mb { #define DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT 0 #define DRV_MB_PARAM_BIST_TEST_INDEX_MASK 0x000000FF +#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT 8 +#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_MASK 0x0000FF00 u32 fw_mb_header; #define FW_MSG_CODE_MASK 0xffff0000 diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index d9fa52a22667..31f8e420c830 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -1508,6 +1508,7 @@ static struct qed_selftest_ops qed_selftest_ops_pass = { .selftest_interrupt = &qed_selftest_interrupt, .selftest_register = &qed_selftest_register, .selftest_clock = &qed_selftest_clock, + .selftest_nvram = &qed_selftest_nvram, }; const struct qed_common_ops qed_common_ops_pass = { diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 98dc913fd76d..8be61570ce6b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -1434,6 +1434,52 @@ int qed_mcp_mask_parities(struct qed_hwfn *p_hwfn, return rc; } +int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len) +{ + u32 bytes_left = len, offset = 0, bytes_to_copy, read_len = 0; + struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); + u32 resp = 0, resp_param = 0; + struct qed_ptt *p_ptt; + int rc = 0; + + p_ptt = qed_ptt_acquire(p_hwfn); + if (!p_ptt) + return -EBUSY; + + while (bytes_left > 0) { + bytes_to_copy = min_t(u32, bytes_left, MCP_DRV_NVM_BUF_LEN); + + rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt, + DRV_MSG_CODE_NVM_READ_NVRAM, + addr + offset + + (bytes_to_copy << + DRV_MB_PARAM_NVM_LEN_SHIFT), + &resp, &resp_param, + &read_len, + (u32 *)(p_buf + offset)); + + if (rc || (resp != FW_MSG_CODE_NVM_OK)) { + DP_NOTICE(cdev, "MCP command rc = %d\n", rc); + break; + } + + /* This can be a lengthy process, and it's possible scheduler + * isn't preemptable. Sleep a bit to prevent CPU hogging. + */ + if (bytes_left % 0x1000 < + (bytes_left - read_len) % 0x1000) + usleep_range(1000, 2000); + + offset += read_len; + bytes_left -= read_len; + } + + cdev->mcp_nvm_resp = resp; + qed_ptt_release(p_hwfn, p_ptt); + + return rc; +} + int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { u32 drv_mb_param = 0, rsp, param; @@ -1475,3 +1521,51 @@ int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) return rc; } + +int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 *num_images) +{ + u32 drv_mb_param = 0, rsp; + int rc = 0; + + drv_mb_param = (DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES << + DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT); + + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST, + drv_mb_param, &rsp, num_images); + if (rc) + return rc; + + if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK)) + rc = -EINVAL; + + return rc; +} + +int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct bist_nvm_image_att *p_image_att, + u32 image_index) +{ + u32 buf_size = 0, param, resp = 0, resp_param = 0; + int rc; + + param = DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX << + DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT; + param |= image_index << DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT; + + rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt, + DRV_MSG_CODE_BIST_TEST, param, + &resp, &resp_param, + &buf_size, + (u32 *)p_image_att); + if (rc) + return rc; + + if (((resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) || + (p_image_att->return_code != 1)) + rc = -EINVAL; + + return rc; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 89507190628d..be8152d49de2 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -379,6 +379,18 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, enum qed_led_mode mode); +/** + * @brief Read from nvm + * + * @param cdev + * @param addr - nvm offset + * @param p_buf - nvm read buffer + * @param len - buffer len + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len); + /** * @brief Bist register test * @@ -401,6 +413,35 @@ int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); +/** + * @brief Bist nvm test - get number of images + * + * @param p_hwfn - hw function + * @param p_ptt - PTT required for register access + * @param num_images - number of images if operation was + * successful. 0 if not. + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 *num_images); + +/** + * @brief Bist nvm test - get image attributes by index + * + * @param p_hwfn - hw function + * @param p_ptt - PTT required for register access + * @param p_image_att - Attributes of image + * @param image_index - Index of image to get information for + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct bist_nvm_image_att *p_image_att, + u32 image_index); + /* Using hwfn number (and not pf_num) is required since in CMT mode, * same pf_num may be used by two different hwfn * TODO - this shouldn't really be in .h file, but until all fields diff --git a/drivers/net/ethernet/qlogic/qed/qed_selftest.c b/drivers/net/ethernet/qlogic/qed/qed_selftest.c index 9b7678f26909..48bfaecaf6dc 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_selftest.c +++ b/drivers/net/ethernet/qlogic/qed/qed_selftest.c @@ -1,3 +1,4 @@ +#include #include "qed.h" #include "qed_dev_api.h" #include "qed_mcp.h" @@ -75,3 +76,103 @@ int qed_selftest_clock(struct qed_dev *cdev) return rc; } + +int qed_selftest_nvram(struct qed_dev *cdev) +{ + struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); + struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn); + u32 num_images, i, j, nvm_crc, calc_crc; + struct bist_nvm_image_att image_att; + u8 *buf = NULL; + __be32 val; + int rc; + + if (!p_ptt) { + DP_ERR(p_hwfn, "failed to acquire ptt\n"); + return -EBUSY; + } + + /* Acquire from MFW the amount of available images */ + rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images); + if (rc || !num_images) { + DP_ERR(p_hwfn, "Failed getting number of images\n"); + return -EINVAL; + } + + /* Iterate over images and validate CRC */ + for (i = 0; i < num_images; i++) { + /* This mailbox returns information about the image required for + * reading it. + */ + rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt, + &image_att, i); + if (rc) { + DP_ERR(p_hwfn, + "Failed getting image index %d attributes\n", + i); + goto err0; + } + + /* After MFW crash dump is collected - the image's CRC stops + * being valid. + */ + if (image_att.image_type == NVM_TYPE_MDUMP) + continue; + + DP_VERBOSE(p_hwfn, QED_MSG_SP, "image index %d, size %x\n", + i, image_att.len); + + /* Allocate a buffer for holding the nvram image */ + buf = kzalloc(image_att.len, GFP_KERNEL); + if (!buf) { + rc = -ENOMEM; + goto err0; + } + + /* Read image into buffer */ + rc = qed_mcp_nvm_read(p_hwfn->cdev, image_att.nvm_start_addr, + buf, image_att.len); + if (rc) { + DP_ERR(p_hwfn, + "Failed reading image index %d from nvm.\n", i); + goto err1; + } + + /* Convert the buffer into big-endian format (excluding the + * closing 4 bytes of CRC). + */ + for (j = 0; j < image_att.len - 4; j += 4) { + val = cpu_to_be32(*(u32 *)&buf[j]); + *(u32 *)&buf[j] = (__force u32)val; + } + + /* Calc CRC for the "actual" image buffer, i.e. not including + * the last 4 CRC bytes. + */ + nvm_crc = *(u32 *)(buf + image_att.len - 4); + calc_crc = crc32(0xffffffff, buf, image_att.len - 4); + calc_crc = (__force u32)~cpu_to_be32(calc_crc); + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "nvm crc 0x%x, calc_crc 0x%x\n", nvm_crc, calc_crc); + + if (calc_crc != nvm_crc) { + rc = -EINVAL; + goto err1; + } + + /* Done with this image; Free to prevent double release + * on subsequent failure. + */ + kfree(buf); + buf = NULL; + } + + qed_ptt_release(p_hwfn, p_ptt); + return 0; + +err1: + kfree(buf); +err0: + qed_ptt_release(p_hwfn, p_ptt); + return rc; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_selftest.h b/drivers/net/ethernet/qlogic/qed/qed_selftest.h index 50eb0b49950f..739ddb730967 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_selftest.h +++ b/drivers/net/ethernet/qlogic/qed/qed_selftest.h @@ -37,4 +37,14 @@ int qed_selftest_register(struct qed_dev *cdev); * @return int */ int qed_selftest_clock(struct qed_dev *cdev); + +/** + * @brief qed_selftest_nvram - Perform nvram test + * + * @param cdev + * + * @return int + */ +int qed_selftest_nvram(struct qed_dev *cdev); + #endif diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index 775fdaafd24d..a8094088b9ac 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -157,6 +157,7 @@ enum qede_ethtool_tests { QEDE_ETHTOOL_MEMORY_TEST, QEDE_ETHTOOL_REGISTER_TEST, QEDE_ETHTOOL_CLOCK_TEST, + QEDE_ETHTOOL_NVRAM_TEST, QEDE_ETHTOOL_TEST_MAX }; @@ -166,6 +167,7 @@ static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { "Memory (online)\t\t", "Register (online)\t", "Clock (online)\t\t", + "Nvram (online)\t\t", }; static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) @@ -1392,6 +1394,11 @@ static void qede_self_test(struct net_device *dev, buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; etest->flags |= ETH_TEST_FL_FAILED; } + + if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) { + buf[QEDE_ETHTOOL_NVRAM_TEST] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } } static int qede_set_tunable(struct net_device *dev, diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 5c909cd02764..ffc2d2f5e88f 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -402,6 +402,15 @@ struct qed_selftest_ops { * @return 0 on success, error otherwise. */ int (*selftest_clock)(struct qed_dev *cdev); + +/** + * @brief selftest_nvram - Perform nvram test + * + * @param cdev + * + * @return 0 on success, error otherwise. + */ + int (*selftest_nvram) (struct qed_dev *cdev); }; struct qed_common_ops { -- cgit v1.2.3 From 14d39648cbfc6289e3f873d30f282b9517ebe860 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Mon, 31 Oct 2016 07:14:23 +0200 Subject: qed*: Add support for WoL Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 11 ++++- drivers/net/ethernet/qlogic/qed/qed_dev.c | 19 ++++++++- drivers/net/ethernet/qlogic/qed/qed_hsi.h | 4 ++ drivers/net/ethernet/qlogic/qed/qed_main.c | 29 +++++++++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 56 ++++++++++++++++++++++++- drivers/net/ethernet/qlogic/qede/qede.h | 2 + drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 41 ++++++++++++++++++ drivers/net/ethernet/qlogic/qede/qede_main.c | 9 ++++ include/linux/qed/qed_if.h | 10 +++++ 9 files changed, 176 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index f20243c1fb0b..8828ffac4b23 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -195,6 +195,11 @@ enum qed_dev_cap { QED_DEV_CAP_ROCE, }; +enum qed_wol_support { + QED_WOL_SUPPORT_NONE, + QED_WOL_SUPPORT_PME, +}; + struct qed_hw_info { /* PCI personality */ enum qed_pci_personality personality; @@ -227,6 +232,8 @@ struct qed_hw_info { u32 hw_mode; unsigned long device_capabilities; u16 mtu; + + enum qed_wol_support b_wol_support; }; struct qed_hw_cid_data { @@ -539,7 +546,9 @@ struct qed_dev { u8 mcp_rev; u8 boot_mode; - u8 wol; + /* WoL related configurations */ + u8 wol_config; + u8 wol_mac[ETH_ALEN]; u32 int_mode; enum qed_coalescing_mode int_coalescing_mode; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 33fd69e24bae..127ed5f27d8d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -1364,8 +1364,24 @@ int qed_hw_reset(struct qed_dev *cdev) { int rc = 0; u32 unload_resp, unload_param; + u32 wol_param; int i; + switch (cdev->wol_config) { + case QED_OV_WOL_DISABLED: + wol_param = DRV_MB_PARAM_UNLOAD_WOL_DISABLED; + break; + case QED_OV_WOL_ENABLED: + wol_param = DRV_MB_PARAM_UNLOAD_WOL_ENABLED; + break; + default: + DP_NOTICE(cdev, + "Unknown WoL configuration %02x\n", cdev->wol_config); + /* Fallthrough */ + case QED_OV_WOL_DEFAULT: + wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP; + } + for_each_hwfn(cdev, i) { struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; @@ -1394,8 +1410,7 @@ int qed_hw_reset(struct qed_dev *cdev) /* Send unload command to MCP */ rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, - DRV_MSG_CODE_UNLOAD_REQ, - DRV_MB_PARAM_UNLOAD_WOL_MCP, + DRV_MSG_CODE_UNLOAD_REQ, wol_param, &unload_resp, &unload_param); if (rc) { DP_NOTICE(p_hwfn, "qed_hw_reset: UNLOAD_REQ failed\n"); diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index f7dfa2ec2d19..fdb7a099955b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -8601,6 +8601,7 @@ struct public_drv_mb { #define DRV_MSG_CODE_BIST_TEST 0x001e0000 #define DRV_MSG_CODE_SET_LED_MODE 0x00200000 +#define DRV_MSG_CODE_OS_WOL 0x002e0000 #define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff @@ -8697,6 +8698,9 @@ struct public_drv_mb { #define FW_MSG_CODE_NVM_OK 0x00010000 #define FW_MSG_CODE_OK 0x00160000 +#define FW_MSG_CODE_OS_WOL_SUPPORTED 0x00800000 +#define FW_MSG_CODE_OS_WOL_NOT_SUPPORTED 0x00810000 + #define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff u32 fw_mb_param; diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 31f8e420c830..b71d73a41b10 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -221,6 +221,10 @@ int qed_fill_dev_info(struct qed_dev *cdev, dev_info->fw_eng = FW_ENGINEERING_VERSION; dev_info->mf_mode = cdev->mf_mode; dev_info->tx_switching = true; + + if (QED_LEADING_HWFN(cdev)->hw_info.b_wol_support == + QED_WOL_SUPPORT_PME) + dev_info->wol_support = true; } else { qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major, &dev_info->fw_minor, &dev_info->fw_rev, @@ -1433,6 +1437,30 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) return status; } +static int qed_update_wol(struct qed_dev *cdev, bool enabled) +{ + struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); + struct qed_ptt *ptt; + int rc = 0; + + if (IS_VF(cdev)) + return 0; + + ptt = qed_ptt_acquire(hwfn); + if (!ptt) + return -EAGAIN; + + rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED + : QED_OV_WOL_DISABLED); + if (rc) + goto out; + rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); + +out: + qed_ptt_release(hwfn, ptt); + return rc; +} + static int qed_update_drv_state(struct qed_dev *cdev, bool active) { struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); @@ -1541,6 +1569,7 @@ const struct qed_common_ops qed_common_ops_pass = { .update_drv_state = &qed_update_drv_state, .update_mac = &qed_update_mac, .update_mtu = &qed_update_mtu, + .update_wol = &qed_update_wol, }; void qed_get_protocol_stats(struct qed_dev *cdev, diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 8be61570ce6b..768b35b1dca0 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -330,6 +330,7 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, struct qed_mcp_mb_params *p_mb_params) { u32 union_data_addr; + int rc; /* MCP not initialized */ @@ -375,11 +376,32 @@ int qed_mcp_cmd(struct qed_hwfn *p_hwfn, u32 *o_mcp_param) { struct qed_mcp_mb_params mb_params; + union drv_union_data data_src; int rc; memset(&mb_params, 0, sizeof(mb_params)); + memset(&data_src, 0, sizeof(data_src)); mb_params.cmd = cmd; mb_params.param = param; + + /* In case of UNLOAD_DONE, set the primary MAC */ + if ((cmd == DRV_MSG_CODE_UNLOAD_DONE) && + (p_hwfn->cdev->wol_config == QED_OV_WOL_ENABLED)) { + u8 *p_mac = p_hwfn->cdev->wol_mac; + + data_src.wol_mac.mac_upper = p_mac[0] << 8 | p_mac[1]; + data_src.wol_mac.mac_lower = p_mac[2] << 24 | p_mac[3] << 16 | + p_mac[4] << 8 | p_mac[5]; + + DP_VERBOSE(p_hwfn, + (QED_MSG_SP | NETIF_MSG_IFDOWN), + "Setting WoL MAC: %pM --> [%08x,%08x]\n", + p_mac, data_src.wol_mac.mac_upper, + data_src.wol_mac.mac_lower); + + mb_params.p_data_src = &data_src; + } + rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); if (rc) return rc; @@ -1058,6 +1080,9 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, info->mac[3] = (u8)(shmem_info.mac_lower >> 16); info->mac[4] = (u8)(shmem_info.mac_lower >> 8); info->mac[5] = (u8)(shmem_info.mac_lower); + + /* Store primary MAC for later possible WoL */ + memcpy(&p_hwfn->cdev->wol_mac, info->mac, ETH_ALEN); } else { DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n"); } @@ -1071,13 +1096,28 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, info->mtu = (u16)shmem_info.mtu_size; + p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_NONE; + p_hwfn->cdev->wol_config = (u8)QED_OV_WOL_DEFAULT; + if (qed_mcp_is_init(p_hwfn)) { + u32 resp = 0, param = 0; + int rc; + + rc = qed_mcp_cmd(p_hwfn, p_ptt, + DRV_MSG_CODE_OS_WOL, 0, &resp, ¶m); + if (rc) + return rc; + if (resp == FW_MSG_CODE_OS_WOL_SUPPORTED) + p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_PME; + } + DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_IFUP), - "Read configuration from shmem: pause_on_host %02x protocol %02x BW [%02x - %02x] MAC %02x:%02x:%02x:%02x:%02x:%02x wwn port %llx node %llx ovlan %04x\n", + "Read configuration from shmem: pause_on_host %02x protocol %02x BW [%02x - %02x] MAC %02x:%02x:%02x:%02x:%02x:%02x wwn port %llx node %llx ovlan %04x wol %02x\n", info->pause_on_host, info->protocol, info->bandwidth_min, info->bandwidth_max, info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5], - info->wwn_port, info->wwn_node, info->ovlan); + info->wwn_port, info->wwn_node, + info->ovlan, (u8)p_hwfn->hw_info.b_wol_support); return 0; } @@ -1322,6 +1362,9 @@ int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn, if (rc) DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc); + /* Store primary MAC for later possible WoL */ + memcpy(p_hwfn->cdev->wol_mac, mac, ETH_ALEN); + return rc; } @@ -1332,6 +1375,12 @@ int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn, u32 drv_mb_param; int rc; + if (p_hwfn->hw_info.b_wol_support == QED_WOL_SUPPORT_NONE) { + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "Can't change WoL configuration when WoL isn't supported\n"); + return -EINVAL; + } + switch (wol) { case QED_OV_WOL_DEFAULT: drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT; @@ -1352,6 +1401,9 @@ int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn, if (rc) DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc); + /* Store the WoL update for a future unload */ + p_hwfn->cdev->wol_config = (u8)wol; + return rc; } diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index cf8d3547aecf..0cba21bf9d5f 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -193,6 +193,8 @@ struct qede_dev { u16 vxlan_dst_port; u16 geneve_dst_port; + bool wol_enabled; + struct qede_rdma_dev rdma_info; }; diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index a8094088b9ac..327c614e76aa 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -483,6 +483,45 @@ static void qede_get_drvinfo(struct net_device *ndev, strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); } +static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) +{ + struct qede_dev *edev = netdev_priv(ndev); + + if (edev->dev_info.common.wol_support) { + wol->supported = WAKE_MAGIC; + wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0; + } +} + +static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) +{ + struct qede_dev *edev = netdev_priv(ndev); + bool wol_requested; + int rc; + + if (wol->wolopts & ~WAKE_MAGIC) { + DP_INFO(edev, + "Can't support WoL options other than magic-packet\n"); + return -EINVAL; + } + + wol_requested = !!(wol->wolopts & WAKE_MAGIC); + if (wol_requested == edev->wol_enabled) + return 0; + + /* Need to actually change configuration */ + if (!edev->dev_info.common.wol_support) { + DP_INFO(edev, "Device doesn't support WoL\n"); + return -EINVAL; + } + + rc = edev->ops->common->update_wol(edev->cdev, wol_requested); + if (!rc) + edev->wol_enabled = wol_requested; + + return rc; +} + static u32 qede_get_msglevel(struct net_device *ndev) { struct qede_dev *edev = netdev_priv(ndev); @@ -1449,6 +1488,8 @@ static const struct ethtool_ops qede_ethtool_ops = { .get_drvinfo = qede_get_drvinfo, .get_regs_len = qede_get_regs_len, .get_regs = qede_get_regs, + .get_wol = qede_get_wol, + .set_wol = qede_set_wol, .get_msglevel = qede_get_msglevel, .set_msglevel = qede_set_msglevel, .nway_reset = qede_nway_reset, diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index df0bd0ce2b18..873f2ebe249e 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -95,6 +95,7 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id); #define TX_TIMEOUT (5 * HZ) static void qede_remove(struct pci_dev *pdev); +static void qede_shutdown(struct pci_dev *pdev); static int qede_alloc_rx_buffer(struct qede_dev *edev, struct qede_rx_queue *rxq); static void qede_link_update(void *dev, struct qed_link_output *link); @@ -166,6 +167,7 @@ static struct pci_driver qede_pci_driver = { .id_table = qede_pci_tbl, .probe = qede_probe, .remove = qede_remove, + .shutdown = qede_shutdown, #ifdef CONFIG_QED_SRIOV .sriov_configure = qede_sriov_configure, #endif @@ -2705,6 +2707,8 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) /* Use global ops since we've freed edev */ qed_ops->common->slowpath_stop(cdev); + if (system_state == SYSTEM_POWER_OFF) + return; qed_ops->common->remove(cdev); dev_info(&pdev->dev, "Ending qede_remove successfully\n"); @@ -2715,6 +2719,11 @@ static void qede_remove(struct pci_dev *pdev) __qede_remove(pdev, QEDE_REMOVE_NORMAL); } +static void qede_shutdown(struct pci_dev *pdev) +{ + __qede_remove(pdev, QEDE_REMOVE_NORMAL); +} + /* ------------------------------------------------------------------------- * START OF LOAD / UNLOAD * ------------------------------------------------------------------------- diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index ffc2d2f5e88f..ea095b4893aa 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -268,6 +268,8 @@ struct qed_dev_info { bool tx_switching; bool rdma_supported; u16 mtu; + + bool wol_support; }; enum qed_sb_type { @@ -591,6 +593,14 @@ struct qed_common_ops { * */ int (*update_mtu)(struct qed_dev *cdev, u16 mtu); + +/** + * @brief update_wol - update of changes in the WoL configuration + * + * @param cdev + * @param enabled - true iff WoL should be enabled. + */ + int (*update_wol) (struct qed_dev *cdev, bool enabled); }; #define MASK_FIELD(_name, _value) \ -- cgit v1.2.3 From d7455f6e445043aa2fe4bb719a7786e0c3dc1cf1 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Mon, 31 Oct 2016 07:14:24 +0200 Subject: qede: Decouple ethtool caps from qed While the qed_lm_maps is closely tied with the QED_LM_* defines, when iterating over the array use actual size instead of the qed define to prevent future possible issues. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index 327c614e76aa..fe7e7b8650dd 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -320,7 +320,7 @@ static const struct qede_link_mode_mapping qed_lm_map[] = { { \ int i; \ \ - for (i = 0; i < QED_LM_COUNT; i++) { \ + for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ if ((caps) & (qed_lm_map[i].qed_link_mode)) \ __set_bit(qed_lm_map[i].ethtool_link_mode,\ lk_ksettings->link_modes.name); \ @@ -331,7 +331,7 @@ static const struct qede_link_mode_mapping qed_lm_map[] = { { \ int i; \ \ - for (i = 0; i < QED_LM_COUNT; i++) { \ + for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ if (test_bit(qed_lm_map[i].ethtool_link_mode, \ lk_ksettings->link_modes.name)) \ caps |= qed_lm_map[i].qed_link_mode; \ -- cgit v1.2.3 From 6927e82680699f7999d68c648d50574a5e4a8f37 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Mon, 31 Oct 2016 07:14:25 +0200 Subject: qed: Learn of RDMA capabilities per-device Today, RDMA capabilities are learned from management firmware which provides a per-device indication for all interfaces. Newer management firmware is capable of providing a per-device indication [would later be extended to either RoCE/iWARP]. Try using this newer learning mechanism, but fallback in case management firmware is too old to retain current functionality. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_hsi.h | 7 +++ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 78 +++++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index fdb7a099955b..1d113ce814e1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -8601,6 +8601,7 @@ struct public_drv_mb { #define DRV_MSG_CODE_BIST_TEST 0x001e0000 #define DRV_MSG_CODE_SET_LED_MODE 0x00200000 +#define DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL 0x002b0000 #define DRV_MSG_CODE_OS_WOL 0x002e0000 #define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff @@ -8705,6 +8706,12 @@ struct public_drv_mb { u32 fw_mb_param; + /* get pf rdma protocol command responce */ +#define FW_MB_PARAM_GET_PF_RDMA_NONE 0x0 +#define FW_MB_PARAM_GET_PF_RDMA_ROCE 0x1 +#define FW_MB_PARAM_GET_PF_RDMA_IWARP 0x2 +#define FW_MB_PARAM_GET_PF_RDMA_BOTH 0x3 + u32 drv_pulse_mb; #define DRV_PULSE_SEQ_MASK 0x00007fff #define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000 diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 768b35b1dca0..092748832caf 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -1024,28 +1024,89 @@ int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type) return 0; } +/* Old MFW has a global configuration for all PFs regarding RDMA support */ +static void +qed_mcp_get_shmem_proto_legacy(struct qed_hwfn *p_hwfn, + enum qed_pci_personality *p_proto) +{ + /* There wasn't ever a legacy MFW that published iwarp. + * So at this point, this is either plain l2 or RoCE. + */ + if (test_bit(QED_DEV_CAP_ROCE, &p_hwfn->hw_info.device_capabilities)) + *p_proto = QED_PCI_ETH_ROCE; + else + *p_proto = QED_PCI_ETH; + + DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, + "According to Legacy capabilities, L2 personality is %08x\n", + (u32) *p_proto); +} + +static int +qed_mcp_get_shmem_proto_mfw(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_pci_personality *p_proto) +{ + u32 resp = 0, param = 0; + int rc; + + rc = qed_mcp_cmd(p_hwfn, p_ptt, + DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL, 0, &resp, ¶m); + if (rc) + return rc; + if (resp != FW_MSG_CODE_OK) { + DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, + "MFW lacks support for command; Returns %08x\n", + resp); + return -EINVAL; + } + + switch (param) { + case FW_MB_PARAM_GET_PF_RDMA_NONE: + *p_proto = QED_PCI_ETH; + break; + case FW_MB_PARAM_GET_PF_RDMA_ROCE: + *p_proto = QED_PCI_ETH_ROCE; + break; + case FW_MB_PARAM_GET_PF_RDMA_BOTH: + DP_NOTICE(p_hwfn, + "Current day drivers don't support RoCE & iWARP. Default to RoCE-only\n"); + *p_proto = QED_PCI_ETH_ROCE; + break; + case FW_MB_PARAM_GET_PF_RDMA_IWARP: + default: + DP_NOTICE(p_hwfn, + "MFW answers GET_PF_RDMA_PROTOCOL but param is %08x\n", + param); + return -EINVAL; + } + + DP_VERBOSE(p_hwfn, + NETIF_MSG_IFUP, + "According to capabilities, L2 personality is %08x [resp %08x param %08x]\n", + (u32) *p_proto, resp, param); + return 0; +} + static int qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn, struct public_func *p_info, + struct qed_ptt *p_ptt, enum qed_pci_personality *p_proto) { int rc = 0; switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) { case FUNC_MF_CFG_PROTOCOL_ETHERNET: - if (test_bit(QED_DEV_CAP_ROCE, - &p_hwfn->hw_info.device_capabilities)) - *p_proto = QED_PCI_ETH_ROCE; - else - *p_proto = QED_PCI_ETH; + if (qed_mcp_get_shmem_proto_mfw(p_hwfn, p_ptt, p_proto)) + qed_mcp_get_shmem_proto_legacy(p_hwfn, p_proto); break; case FUNC_MF_CFG_PROTOCOL_ISCSI: *p_proto = QED_PCI_ISCSI; break; case FUNC_MF_CFG_PROTOCOL_ROCE: DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n"); - rc = -EINVAL; - break; + /* Fallthrough */ default: rc = -EINVAL; } @@ -1065,7 +1126,8 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, info->pause_on_host = (shmem_info.config & FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0; - if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info, &info->protocol)) { + if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt, + &info->protocol)) { DP_ERR(p_hwfn, "Unknown personality %08x\n", (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK)); return -EINVAL; -- cgit v1.2.3 From 5a1f965aac7acf2bf968fbf6a80567dbd1e389f1 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Mon, 31 Oct 2016 07:14:26 +0200 Subject: qed: Use VF-queue feature Driver sets several restrictions about the number of supported VFs according to available HW/FW resources. This creates a problem as there are constellations which can't be supported [as limitation don't accurately describe the resources], as well as holes where enabling IOV would fail due to supposed lack of resources. This introduces a new interal feature - vf-queues, which would be used to lift some of the restriction and accurately enumerate the queues that can be used by a given PF's VFs. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 1 + drivers/net/ethernet/qlogic/qed/qed_dev.c | 20 ++++++++++++++---- drivers/net/ethernet/qlogic/qed/qed_int.c | 32 ++++++++++++++++++++++++++++- drivers/net/ethernet/qlogic/qed/qed_sriov.c | 17 ++++++--------- 4 files changed, 54 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 8828ffac4b23..6d3013fe6987 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -174,6 +174,7 @@ enum QED_FEATURE { QED_PF_L2_QUE, QED_VF, QED_RDMA_CNQ, + QED_VF_L2_QUE, QED_MAX_FEATURES, }; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 127ed5f27d8d..d996afe833ee 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -1476,6 +1476,7 @@ static void get_function_id(struct qed_hwfn *p_hwfn) static void qed_hw_set_feat(struct qed_hwfn *p_hwfn) { u32 *feat_num = p_hwfn->hw_info.feat_num; + struct qed_sb_cnt_info sb_cnt_info; int num_features = 1; if (IS_ENABLED(CONFIG_QED_RDMA) && @@ -1494,10 +1495,21 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn) feat_num[QED_PF_L2_QUE] = min_t(u32, RESC_NUM(p_hwfn, QED_SB) / num_features, RESC_NUM(p_hwfn, QED_L2_QUEUE)); - DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE, - "#PF_L2_QUEUES=%d #SBS=%d num_features=%d\n", - feat_num[QED_PF_L2_QUE], RESC_NUM(p_hwfn, QED_SB), - num_features); + + memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); + qed_int_get_num_sbs(p_hwfn, &sb_cnt_info); + feat_num[QED_VF_L2_QUE] = + min_t(u32, + RESC_NUM(p_hwfn, QED_L2_QUEUE) - + FEAT_NUM(p_hwfn, QED_PF_L2_QUE), sb_cnt_info.sb_iov_cnt); + + DP_VERBOSE(p_hwfn, + NETIF_MSG_PROBE, + "#PF_L2_QUEUES=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d #SBS=%d num_features=%d\n", + (int)FEAT_NUM(p_hwfn, QED_PF_L2_QUE), + (int)FEAT_NUM(p_hwfn, QED_VF_L2_QUE), + (int)FEAT_NUM(p_hwfn, QED_RDMA_CNQ), + RESC_NUM(p_hwfn, QED_SB), num_features); } static int qed_hw_get_resc(struct qed_hwfn *p_hwfn) diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index 2adedc6fb6cf..bb74e1c10ffe 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -3030,6 +3030,31 @@ int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) } } } + + /* There's a possibility the igu_sb_cnt_iov doesn't properly reflect + * the number of VF SBs [especially for first VF on engine, as we can't + * diffrentiate between empty entries and its entries]. + * Since we don't really support more SBs than VFs today, prevent any + * such configuration by sanitizing the number of SBs to equal the + * number of VFs. + */ + if (IS_PF_SRIOV(p_hwfn)) { + u16 total_vfs = p_hwfn->cdev->p_iov_info->total_vfs; + + if (total_vfs < p_igu_info->free_blks) { + DP_VERBOSE(p_hwfn, + (NETIF_MSG_INTR | QED_MSG_IOV), + "Limiting number of SBs for IOV - %04x --> %04x\n", + p_igu_info->free_blks, + p_hwfn->cdev->p_iov_info->total_vfs); + p_igu_info->free_blks = total_vfs; + } else if (total_vfs > p_igu_info->free_blks) { + DP_NOTICE(p_hwfn, + "IGU has only %04x SBs for VFs while the device has %04x VFs\n", + p_igu_info->free_blks, total_vfs); + return -EINVAL; + } + } p_igu_info->igu_sb_cnt_iov = p_igu_info->free_blks; DP_VERBOSE( @@ -3163,7 +3188,12 @@ u16 qed_int_queue_id_from_sb_id(struct qed_hwfn *p_hwfn, u16 sb_id) return sb_id - p_info->igu_base_sb; } else if ((sb_id >= p_info->igu_base_sb_iov) && (sb_id < p_info->igu_base_sb_iov + p_info->igu_sb_cnt_iov)) { - return sb_id - p_info->igu_base_sb_iov + p_info->igu_sb_cnt; + /* We want the first VF queue to be adjacent to the + * last PF queue. Since L2 queues can be partial to + * SBs, we'll use the feature instead. + */ + return sb_id - p_info->igu_base_sb_iov + + FEAT_NUM(p_hwfn, QED_PF_L2_QUE); } else { DP_NOTICE(p_hwfn, "SB %d not in range for function\n", sb_id); return 0; diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index 6f029f91e4de..f3f742a4e59a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -3470,7 +3470,6 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled) static int qed_sriov_enable(struct qed_dev *cdev, int num) { - struct qed_sb_cnt_info sb_cnt_info; int i, j, rc; if (num >= RESC_NUM(&cdev->hwfns[0], QED_VPORT)) { @@ -3483,7 +3482,11 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num) for_each_hwfn(cdev, j) { struct qed_hwfn *hwfn = &cdev->hwfns[j]; struct qed_ptt *ptt = qed_ptt_acquire(hwfn); - int num_sbs = 0, limit = 16; + int num_queues; + + /* Make sure not to use more than 16 queues per VF */ + num_queues = min_t(int, + FEAT_NUM(hwfn, QED_VF_L2_QUE) / num, 16); if (!ptt) { DP_ERR(hwfn, "Failed to acquire ptt\n"); @@ -3491,19 +3494,11 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num) goto err; } - if (IS_MF_DEFAULT(hwfn)) - limit = MAX_NUM_VFS_BB / hwfn->num_funcs_on_engine; - - memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); - qed_int_get_num_sbs(hwfn, &sb_cnt_info); - num_sbs = min_t(int, sb_cnt_info.sb_free_blk, limit); - for (i = 0; i < num; i++) { if (!qed_iov_is_valid_vfid(hwfn, i, false, true)) continue; - rc = qed_iov_init_hw_for_vf(hwfn, - ptt, i, num_sbs / num); + rc = qed_iov_init_hw_for_vf(hwfn, ptt, i, num_queues); if (rc) { DP_ERR(cdev, "Failed to enable VF[%d]\n", i); qed_ptt_release(hwfn, ptt); -- cgit v1.2.3 From 2edbff8dcb5da324fd4c4fe953629e4f6ca73c99 Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 31 Oct 2016 07:14:27 +0200 Subject: qed: Learn resources from management firmware Currently, each interfaces assumes it receives an equal portion of HW/FW resources, but this is wasteful - different partitions [and specifically, parititions exposing different protocol support] might require different resources. Implement a new resource learning scheme where the information is received directly from the management firmware [which has knowledge of all of the functions and can serve as arbiter]. Signed-off-by: Tomer Tayar Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 6 +- drivers/net/ethernet/qlogic/qed/qed_dev.c | 291 ++++++++++++++++++++++++------ drivers/net/ethernet/qlogic/qed/qed_hsi.h | 46 +++++ drivers/net/ethernet/qlogic/qed/qed_l2.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_mcp.c | 42 +++++ drivers/net/ethernet/qlogic/qed/qed_mcp.h | 15 ++ include/linux/qed/qed_eth_if.h | 2 +- 7 files changed, 341 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 6d3013fe6987..50b8a01ff512 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -154,7 +154,10 @@ struct qed_qm_iids { u32 tids; }; -enum QED_RESOURCES { +/* HW / FW resources, output of features supported below, most information + * is received from MFW. + */ +enum qed_resources { QED_SB, QED_L2_QUEUE, QED_VPORT, @@ -166,6 +169,7 @@ enum QED_RESOURCES { QED_RDMA_CNQ_RAM, QED_ILT, QED_LL2_QUEUE, + QED_CMDQS_CQS, QED_RDMA_STATS_QUEUE, QED_MAX_RESC, }; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index d996afe833ee..5be7b8a25425 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -1512,47 +1512,240 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn) RESC_NUM(p_hwfn, QED_SB), num_features); } -static int qed_hw_get_resc(struct qed_hwfn *p_hwfn) +static enum resource_id_enum qed_hw_get_mfw_res_id(enum qed_resources res_id) +{ + enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID; + + switch (res_id) { + case QED_SB: + mfw_res_id = RESOURCE_NUM_SB_E; + break; + case QED_L2_QUEUE: + mfw_res_id = RESOURCE_NUM_L2_QUEUE_E; + break; + case QED_VPORT: + mfw_res_id = RESOURCE_NUM_VPORT_E; + break; + case QED_RSS_ENG: + mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E; + break; + case QED_PQ: + mfw_res_id = RESOURCE_NUM_PQ_E; + break; + case QED_RL: + mfw_res_id = RESOURCE_NUM_RL_E; + break; + case QED_MAC: + case QED_VLAN: + /* Each VFC resource can accommodate both a MAC and a VLAN */ + mfw_res_id = RESOURCE_VFC_FILTER_E; + break; + case QED_ILT: + mfw_res_id = RESOURCE_ILT_E; + break; + case QED_LL2_QUEUE: + mfw_res_id = RESOURCE_LL2_QUEUE_E; + break; + case QED_RDMA_CNQ_RAM: + case QED_CMDQS_CQS: + /* CNQ/CMDQS are the same resource */ + mfw_res_id = RESOURCE_CQS_E; + break; + case QED_RDMA_STATS_QUEUE: + mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E; + break; + default: + break; + } + + return mfw_res_id; +} + +static u32 qed_hw_get_dflt_resc_num(struct qed_hwfn *p_hwfn, + enum qed_resources res_id) { - u8 enabled_func_idx = p_hwfn->enabled_func_idx; - u32 *resc_start = p_hwfn->hw_info.resc_start; u8 num_funcs = p_hwfn->num_funcs_on_engine; - u32 *resc_num = p_hwfn->hw_info.resc_num; struct qed_sb_cnt_info sb_cnt_info; - int i, max_vf_vlan_filters; + u32 dflt_resc_num = 0; - memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); + switch (res_id) { + case QED_SB: + memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); + qed_int_get_num_sbs(p_hwfn, &sb_cnt_info); + dflt_resc_num = sb_cnt_info.sb_cnt; + break; + case QED_L2_QUEUE: + dflt_resc_num = MAX_NUM_L2_QUEUES_BB / num_funcs; + break; + case QED_VPORT: + dflt_resc_num = MAX_NUM_VPORTS_BB / num_funcs; + break; + case QED_RSS_ENG: + dflt_resc_num = ETH_RSS_ENGINE_NUM_BB / num_funcs; + break; + case QED_PQ: + /* The granularity of the PQs is 8 */ + dflt_resc_num = MAX_QM_TX_QUEUES_BB / num_funcs; + dflt_resc_num &= ~0x7; + break; + case QED_RL: + dflt_resc_num = MAX_QM_GLOBAL_RLS / num_funcs; + break; + case QED_MAC: + case QED_VLAN: + /* Each VFC resource can accommodate both a MAC and a VLAN */ + dflt_resc_num = ETH_NUM_MAC_FILTERS / num_funcs; + break; + case QED_ILT: + dflt_resc_num = PXP_NUM_ILT_RECORDS_BB / num_funcs; + break; + case QED_LL2_QUEUE: + dflt_resc_num = MAX_NUM_LL2_RX_QUEUES / num_funcs; + break; + case QED_RDMA_CNQ_RAM: + case QED_CMDQS_CQS: + /* CNQ/CMDQS are the same resource */ + dflt_resc_num = NUM_OF_CMDQS_CQS / num_funcs; + break; + case QED_RDMA_STATS_QUEUE: + dflt_resc_num = RDMA_NUM_STATISTIC_COUNTERS_BB / num_funcs; + break; + default: + break; + } -#ifdef CONFIG_QED_SRIOV - max_vf_vlan_filters = QED_ETH_MAX_VF_NUM_VLAN_FILTERS; -#else - max_vf_vlan_filters = 0; -#endif + return dflt_resc_num; +} + +static const char *qed_hw_get_resc_name(enum qed_resources res_id) +{ + switch (res_id) { + case QED_SB: + return "SB"; + case QED_L2_QUEUE: + return "L2_QUEUE"; + case QED_VPORT: + return "VPORT"; + case QED_RSS_ENG: + return "RSS_ENG"; + case QED_PQ: + return "PQ"; + case QED_RL: + return "RL"; + case QED_MAC: + return "MAC"; + case QED_VLAN: + return "VLAN"; + case QED_RDMA_CNQ_RAM: + return "RDMA_CNQ_RAM"; + case QED_ILT: + return "ILT"; + case QED_LL2_QUEUE: + return "LL2_QUEUE"; + case QED_CMDQS_CQS: + return "CMDQS_CQS"; + case QED_RDMA_STATS_QUEUE: + return "RDMA_STATS_QUEUE"; + default: + return "UNKNOWN_RESOURCE"; + } +} - qed_int_get_num_sbs(p_hwfn, &sb_cnt_info); +static int qed_hw_set_resc_info(struct qed_hwfn *p_hwfn, + enum qed_resources res_id) +{ + u32 dflt_resc_num = 0, dflt_resc_start = 0, mcp_resp, mcp_param; + u32 *p_resc_num, *p_resc_start; + struct resource_info resc_info; + int rc; + + p_resc_num = &RESC_NUM(p_hwfn, res_id); + p_resc_start = &RESC_START(p_hwfn, res_id); + + /* Default values assumes that each function received equal share */ + dflt_resc_num = qed_hw_get_dflt_resc_num(p_hwfn, res_id); + if (!dflt_resc_num) { + DP_ERR(p_hwfn, + "Failed to get default amount for resource %d [%s]\n", + res_id, qed_hw_get_resc_name(res_id)); + return -EINVAL; + } + dflt_resc_start = dflt_resc_num * p_hwfn->enabled_func_idx; + + memset(&resc_info, 0, sizeof(resc_info)); + resc_info.res_id = qed_hw_get_mfw_res_id(res_id); + if (resc_info.res_id == RESOURCE_NUM_INVALID) { + DP_ERR(p_hwfn, + "Failed to match resource %d [%s] with the MFW resources\n", + res_id, qed_hw_get_resc_name(res_id)); + return -EINVAL; + } + + rc = qed_mcp_get_resc_info(p_hwfn, p_hwfn->p_main_ptt, &resc_info, + &mcp_resp, &mcp_param); + if (rc) { + DP_NOTICE(p_hwfn, + "MFW response failure for an allocation request for resource %d [%s]\n", + res_id, qed_hw_get_resc_name(res_id)); + return rc; + } + + /* Default driver values are applied in the following cases: + * - The resource allocation MB command is not supported by the MFW + * - There is an internal error in the MFW while processing the request + * - The resource ID is unknown to the MFW + */ + if (mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK && + mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_DEPRECATED) { + DP_NOTICE(p_hwfn, + "Resource %d [%s]: No allocation info was received [mcp_resp 0x%x]. Applying default values [num %d, start %d].\n", + res_id, + qed_hw_get_resc_name(res_id), + mcp_resp, dflt_resc_num, dflt_resc_start); + *p_resc_num = dflt_resc_num; + *p_resc_start = dflt_resc_start; + goto out; + } + + /* Special handling for status blocks; Would be revised in future */ + if (res_id == QED_SB) { + resc_info.size -= 1; + resc_info.offset -= p_hwfn->enabled_func_idx; + } + + *p_resc_num = resc_info.size; + *p_resc_start = resc_info.offset; + +out: + /* PQs have to divide by 8 [that's the HW granularity]. + * Reduce number so it would fit. + */ + if ((res_id == QED_PQ) && ((*p_resc_num % 8) || (*p_resc_start % 8))) { + DP_INFO(p_hwfn, + "PQs need to align by 8; Number %08x --> %08x, Start %08x --> %08x\n", + *p_resc_num, + (*p_resc_num) & ~0x7, + *p_resc_start, (*p_resc_start) & ~0x7); + *p_resc_num &= ~0x7; + *p_resc_start &= ~0x7; + } - resc_num[QED_SB] = min_t(u32, - (MAX_SB_PER_PATH_BB / num_funcs), - sb_cnt_info.sb_cnt); - resc_num[QED_L2_QUEUE] = MAX_NUM_L2_QUEUES_BB / num_funcs; - resc_num[QED_VPORT] = MAX_NUM_VPORTS_BB / num_funcs; - resc_num[QED_RSS_ENG] = ETH_RSS_ENGINE_NUM_BB / num_funcs; - resc_num[QED_PQ] = MAX_QM_TX_QUEUES_BB / num_funcs; - resc_num[QED_RL] = min_t(u32, 64, resc_num[QED_VPORT]); - resc_num[QED_MAC] = ETH_NUM_MAC_FILTERS / num_funcs; - resc_num[QED_VLAN] = (ETH_NUM_VLAN_FILTERS - 1 /*For vlan0*/) / - num_funcs; - resc_num[QED_ILT] = PXP_NUM_ILT_RECORDS_BB / num_funcs; - resc_num[QED_LL2_QUEUE] = MAX_NUM_LL2_RX_QUEUES / num_funcs; - resc_num[QED_RDMA_CNQ_RAM] = NUM_OF_CMDQS_CQS / num_funcs; - resc_num[QED_RDMA_STATS_QUEUE] = RDMA_NUM_STATISTIC_COUNTERS_BB / - num_funcs; - - for (i = 0; i < QED_MAX_RESC; i++) - resc_start[i] = resc_num[i] * enabled_func_idx; + return 0; +} + +static int qed_hw_get_resc(struct qed_hwfn *p_hwfn) +{ + u8 res_id; + int rc; + + for (res_id = 0; res_id < QED_MAX_RESC; res_id++) { + rc = qed_hw_set_resc_info(p_hwfn, res_id); + if (rc) + return rc; + } /* Sanity for ILT */ - if (RESC_END(p_hwfn, QED_ILT) > PXP_NUM_ILT_RECORDS_BB) { + if ((RESC_END(p_hwfn, QED_ILT) > PXP_NUM_ILT_RECORDS_BB)) { DP_NOTICE(p_hwfn, "Can't assign ILT pages [%08x,...,%08x]\n", RESC_START(p_hwfn, QED_ILT), RESC_END(p_hwfn, QED_ILT) - 1); @@ -1562,34 +1755,12 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn) qed_hw_set_feat(p_hwfn); DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE, - "The numbers for each resource are:\n" - "SB = %d start = %d\n" - "L2_QUEUE = %d start = %d\n" - "VPORT = %d start = %d\n" - "PQ = %d start = %d\n" - "RL = %d start = %d\n" - "MAC = %d start = %d\n" - "VLAN = %d start = %d\n" - "ILT = %d start = %d\n" - "LL2_QUEUE = %d start = %d\n", - p_hwfn->hw_info.resc_num[QED_SB], - p_hwfn->hw_info.resc_start[QED_SB], - p_hwfn->hw_info.resc_num[QED_L2_QUEUE], - p_hwfn->hw_info.resc_start[QED_L2_QUEUE], - p_hwfn->hw_info.resc_num[QED_VPORT], - p_hwfn->hw_info.resc_start[QED_VPORT], - p_hwfn->hw_info.resc_num[QED_PQ], - p_hwfn->hw_info.resc_start[QED_PQ], - p_hwfn->hw_info.resc_num[QED_RL], - p_hwfn->hw_info.resc_start[QED_RL], - p_hwfn->hw_info.resc_num[QED_MAC], - p_hwfn->hw_info.resc_start[QED_MAC], - p_hwfn->hw_info.resc_num[QED_VLAN], - p_hwfn->hw_info.resc_start[QED_VLAN], - p_hwfn->hw_info.resc_num[QED_ILT], - p_hwfn->hw_info.resc_start[QED_ILT], - RESC_NUM(p_hwfn, QED_LL2_QUEUE), - RESC_START(p_hwfn, QED_LL2_QUEUE)); + "The numbers for each resource are:\n"); + for (res_id = 0; res_id < QED_MAX_RESC; res_id++) + DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE, "%s = %d start = %d\n", + qed_hw_get_resc_name(res_id), + RESC_NUM(p_hwfn, res_id), + RESC_START(p_hwfn, res_id)); return 0; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 1d113ce814e1..048f9a342413 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -8529,6 +8529,41 @@ struct mdump_config_stc { u32 valid_logs; }; +enum resource_id_enum { + RESOURCE_NUM_SB_E = 0, + RESOURCE_NUM_L2_QUEUE_E = 1, + RESOURCE_NUM_VPORT_E = 2, + RESOURCE_NUM_VMQ_E = 3, + RESOURCE_FACTOR_NUM_RSS_PF_E = 4, + RESOURCE_FACTOR_RSS_PER_VF_E = 5, + RESOURCE_NUM_RL_E = 6, + RESOURCE_NUM_PQ_E = 7, + RESOURCE_NUM_VF_E = 8, + RESOURCE_VFC_FILTER_E = 9, + RESOURCE_ILT_E = 10, + RESOURCE_CQS_E = 11, + RESOURCE_GFT_PROFILES_E = 12, + RESOURCE_NUM_TC_E = 13, + RESOURCE_NUM_RSS_ENGINES_E = 14, + RESOURCE_LL2_QUEUE_E = 15, + RESOURCE_RDMA_STATS_QUEUE_E = 16, + RESOURCE_MAX_NUM, + RESOURCE_NUM_INVALID = 0xFFFFFFFF +}; + +/* Resource ID is to be filled by the driver in the MB request + * Size, offset & flags to be filled by the MFW in the MB response + */ +struct resource_info { + enum resource_id_enum res_id; + u32 size; /* number of allocated resources */ + u32 offset; /* Offset of the 1st resource */ + u32 vf_size; + u32 vf_offset; + u32 flags; +#define RESOURCE_ELEMENT_STRICT (1 << 0) +}; + union drv_union_data { u32 ver_str[MCP_DRV_VER_STR_SIZE_DWORD]; struct mcp_mac wol_mac; @@ -8549,6 +8584,7 @@ union drv_union_data { u64 reserved_stats[11]; struct ocbb_data_stc ocbb_info; struct temperature_status_stc temp_info; + struct resource_info resource; struct bist_nvm_image_att nvm_image_att; struct mdump_config_stc mdump_config; }; @@ -8576,6 +8612,7 @@ struct public_drv_mb { #define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000 #define DRV_MSG_CODE_NIG_DRAIN 0x30000000 +#define DRV_MSG_GET_RESOURCE_ALLOC_MSG 0x34000000 #define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000 #define DRV_MSG_CODE_CFG_VF_MSIX 0xc0010000 #define DRV_MSG_CODE_NVM_GET_FILE_ATT 0x00030000 @@ -8666,6 +8703,12 @@ struct public_drv_mb { #define DRV_MB_PARAM_SET_LED_MODE_ON 0x1 #define DRV_MB_PARAM_SET_LED_MODE_OFF 0x2 + /* Resource Allocation params - Driver version support */ +#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_MASK 0xFFFF0000 +#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT 16 +#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_MASK 0x0000FFFF +#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT 0 + #define DRV_MB_PARAM_BIST_REGISTER_TEST 1 #define DRV_MB_PARAM_BIST_CLOCK_TEST 2 #define DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES 3 @@ -8694,6 +8737,9 @@ struct public_drv_mb { #define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20120000 #define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20130000 #define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000 +#define FW_MSG_CODE_RESOURCE_ALLOC_OK 0x34000000 +#define FW_MSG_CODE_RESOURCE_ALLOC_UNKNOWN 0x35000000 +#define FW_MSG_CODE_RESOURCE_ALLOC_DEPRECATED 0x36000000 #define FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE 0xb0010000 #define FW_MSG_CODE_NVM_OK 0x00010000 diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 6b0e22d9fe4c..1e3a16edd16d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1691,7 +1691,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev, } qed_vf_get_num_vlan_filters(&cdev->hwfns[0], - &info->num_vlan_filters); + (u8 *)&info->num_vlan_filters); qed_vf_get_port_mac(&cdev->hwfns[0], info->port_mac); info->is_legacy = !!cdev->hwfns[0].vf_iov_info->b_pre_fp_hsi; diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 092748832caf..d8e499ebb99d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -1683,3 +1683,45 @@ int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn, return rc; } + +#define QED_RESC_ALLOC_VERSION_MAJOR 1 +#define QED_RESC_ALLOC_VERSION_MINOR 0 +#define QED_RESC_ALLOC_VERSION \ + ((QED_RESC_ALLOC_VERSION_MAJOR << \ + DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT) | \ + (QED_RESC_ALLOC_VERSION_MINOR << \ + DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT)) +int qed_mcp_get_resc_info(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct resource_info *p_resc_info, + u32 *p_mcp_resp, u32 *p_mcp_param) +{ + struct qed_mcp_mb_params mb_params; + union drv_union_data *p_union_data; + int rc; + + memset(&mb_params, 0, sizeof(mb_params)); + mb_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG; + mb_params.param = QED_RESC_ALLOC_VERSION; + p_union_data = (union drv_union_data *)p_resc_info; + mb_params.p_data_src = p_union_data; + mb_params.p_data_dst = p_union_data; + rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); + if (rc) + return rc; + + *p_mcp_resp = mb_params.mcp_resp; + *p_mcp_param = mb_params.mcp_param; + + DP_VERBOSE(p_hwfn, + QED_MSG_SP, + "MFW resource_info: version 0x%x, res_id 0x%x, size 0x%x, offset 0x%x, vf_size 0x%x, vf_offset 0x%x, flags 0x%x\n", + *p_mcp_param, + p_resc_info->res_id, + p_resc_info->size, + p_resc_info->offset, + p_resc_info->vf_size, + p_resc_info->vf_offset, p_resc_info->flags); + + return 0; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index be8152d49de2..407a2c1830fb 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -689,4 +689,19 @@ int qed_mcp_ov_update_eswitch(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, enum qed_ov_eswitch eswitch); +/** + * @brief - Gets the MFW allocation info for the given resource + * + * @param p_hwfn + * @param p_ptt + * @param p_resc_info - descriptor of requested resource + * @param p_mcp_resp + * @param p_mcp_param + * + * @return int - 0 - operation was successful. + */ +int qed_mcp_get_resc_info(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct resource_info *p_resc_info, + u32 *p_mcp_resp, u32 *p_mcp_param); #endif diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h index 15130805d792..9755a3feb52e 100644 --- a/include/linux/qed/qed_eth_if.h +++ b/include/linux/qed/qed_eth_if.h @@ -22,7 +22,7 @@ struct qed_dev_eth_info { u8 num_tc; u8 port_mac[ETH_ALEN]; - u8 num_vlan_filters; + u16 num_vlan_filters; u16 num_mac_filters; /* Legacy VF - this affects the datapath, so qede has to know */ -- cgit v1.2.3 From 6819d101dd739dd4e8cbe60a98c9ebb224ecc992 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 17 Aug 2016 14:42:12 -0700 Subject: lkdtm: Add tests for struct list corruption When building under CONFIG_DEBUG_LIST, list addition and removal will be sanity-checked. This validates that the check is working as expected by setting up classic corruption attacks against list manipulations, available with the new lkdtm tests CORRUPT_LIST_ADD and CORRUPT_LIST_DEL. Signed-off-by: Kees Cook Acked-by: Steven Rostedt Signed-off-by: Paul E. McKenney Acked-by: Rik van Riel --- drivers/misc/lkdtm.h | 2 ++ drivers/misc/lkdtm_bugs.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/misc/lkdtm_core.c | 2 ++ 3 files changed, 72 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h index fdf954c2107f..cfa1039c62e7 100644 --- a/drivers/misc/lkdtm.h +++ b/drivers/misc/lkdtm.h @@ -21,6 +21,8 @@ void lkdtm_SPINLOCKUP(void); void lkdtm_HUNG_TASK(void); void lkdtm_ATOMIC_UNDERFLOW(void); void lkdtm_ATOMIC_OVERFLOW(void); +void lkdtm_CORRUPT_LIST_ADD(void); +void lkdtm_CORRUPT_LIST_DEL(void); /* lkdtm_heap.c */ void lkdtm_OVERWRITE_ALLOCATION(void); diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c index 182ae1894b32..f336206d4b1f 100644 --- a/drivers/misc/lkdtm_bugs.c +++ b/drivers/misc/lkdtm_bugs.c @@ -5,8 +5,13 @@ * test source files. */ #include "lkdtm.h" +#include #include +struct lkdtm_list { + struct list_head node; +}; + /* * Make sure our attempts to over run the kernel stack doesn't trigger * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we @@ -146,3 +151,66 @@ void lkdtm_ATOMIC_OVERFLOW(void) pr_info("attempting bad atomic overflow\n"); atomic_inc(&over); } + +void lkdtm_CORRUPT_LIST_ADD(void) +{ + /* + * Initially, an empty list via LIST_HEAD: + * test_head.next = &test_head + * test_head.prev = &test_head + */ + LIST_HEAD(test_head); + struct lkdtm_list good, bad; + void *target[2] = { }; + void *redirection = ⌖ + + pr_info("attempting good list addition\n"); + + /* + * Adding to the list performs these actions: + * test_head.next->prev = &good.node + * good.node.next = test_head.next + * good.node.prev = test_head + * test_head.next = good.node + */ + list_add(&good.node, &test_head); + + pr_info("attempting corrupted list addition\n"); + /* + * In simulating this "write what where" primitive, the "what" is + * the address of &bad.node, and the "where" is the address held + * by "redirection". + */ + test_head.next = redirection; + list_add(&bad.node, &test_head); + + if (target[0] == NULL && target[1] == NULL) + pr_err("Overwrite did not happen, but no BUG?!\n"); + else + pr_err("list_add() corruption not detected!\n"); +} + +void lkdtm_CORRUPT_LIST_DEL(void) +{ + LIST_HEAD(test_head); + struct lkdtm_list item; + void *target[2] = { }; + void *redirection = ⌖ + + list_add(&item.node, &test_head); + + pr_info("attempting good list removal\n"); + list_del(&item.node); + + pr_info("attempting corrupted list removal\n"); + list_add(&item.node, &test_head); + + /* As with the list_add() test above, this corrupts "next". */ + item.node.next = redirection; + list_del(&item.node); + + if (target[0] == NULL && target[1] == NULL) + pr_err("Overwrite did not happen, but no BUG?!\n"); + else + pr_err("list_del() corruption not detected!\n"); +} diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c index f9154b8d67f6..7eeb71a75549 100644 --- a/drivers/misc/lkdtm_core.c +++ b/drivers/misc/lkdtm_core.c @@ -197,6 +197,8 @@ struct crashtype crashtypes[] = { CRASHTYPE(EXCEPTION), CRASHTYPE(LOOP), CRASHTYPE(OVERFLOW), + CRASHTYPE(CORRUPT_LIST_ADD), + CRASHTYPE(CORRUPT_LIST_DEL), CRASHTYPE(CORRUPT_STACK), CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE), CRASHTYPE(OVERWRITE_ALLOCATION), -- cgit v1.2.3 From ff00f3a9670f97203b33ac00eeca81d75768919e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 4 Oct 2016 12:20:16 +0100 Subject: i40e: Add missing \n to end of dev_err message Trival fix, dev_err message is missing a \n, so add it. Signed-off-by: Colin Ian King Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 54b8ee2583f1..64e54a562f41 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2940,7 +2940,7 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, } if (max_tx_rate > speed) { - dev_err(&pf->pdev->dev, "Invalid max tx rate %d specified for VF %d.", + dev_err(&pf->pdev->dev, "Invalid max tx rate %d specified for VF %d.\n", max_tx_rate, vf->vf_id); ret = -EINVAL; goto error; -- cgit v1.2.3 From 1bc87e807a6510eb33402258ec1df9bf22b6ff1f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:31 -0700 Subject: i40e: drop is_vf and is_netdev fields in struct i40e_mac_filter Originally the is_vf and is_netdev fields were added in order to distinguish between VF and netdev filters in a single VSI. However, it can be noted that we use separate VSI for SRIOV VFs and for netdev VSI. Thus, since a single VSI should only ever have one type of filter, we can simply remove the checks and remove the typing. In a similar fashion, we can note that the only remaining way to get multiple filters of a single type is through a debug command that was added to debugfs. This command is useless in practice, and results in causing bugs if we keep counter tracking but lose the is_vf and is_netdev protections as desired above. Since the only time we'd actually have a counter value besides 0 and 1 is through use of this debugfs hook, we can remove this unnecessary command, and the entire counter logic it required. We vastly simplify mac filters by removing (a) the distinction between VF and netdev filters (b) counting logic (c) the ability to add and remove filters bypassing the stack via debugfs Change-ID: Idf916dd2a1159b1188ddbab5bef6b85ea6bf27d9 Signed-off-by: Jacob Keller Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 19 +- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 88 +------- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 8 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 227 ++++++--------------- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 19 +- 5 files changed, 89 insertions(+), 272 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 5a6f8518b4e1..844559188c6b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -458,9 +458,6 @@ struct i40e_mac_filter { u8 macaddr[ETH_ALEN]; #define I40E_VLAN_ANY -1 s16 vlan; - u8 counter; /* number of instances of this filter */ - bool is_vf; /* filter belongs to a VF */ - bool is_netdev; /* filter belongs to a netdev */ enum i40e_filter_state state; }; @@ -723,10 +720,8 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf); bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features); void i40e_set_ethtool_ops(struct net_device *netdev); struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, - u8 *macaddr, s16 vlan, - bool is_vf, bool is_netdev); -void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan, - bool is_vf, bool is_netdev); + u8 *macaddr, s16 vlan); +void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan); int i40e_sync_vsi_filters(struct i40e_vsi *vsi); struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, u16 uplink, u32 param1); @@ -817,13 +812,11 @@ int i40e_vsi_open(struct i40e_vsi *vsi); void i40e_vlan_stripping_disable(struct i40e_vsi *vsi); int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid); int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid); -struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, - bool is_vf, bool is_netdev); -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, - bool is_vf, bool is_netdev); +struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, + u8 *macaddr); +int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr); bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); -struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, - bool is_vf, bool is_netdev); +struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr); #ifdef I40E_FCOE int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, struct tc_to_netdev *tc); diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 0354632fe2f8..8f6ed8d28412 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -168,9 +168,9 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) pf->hw.mac.port_addr); list_for_each_entry(f, &vsi->mac_filter_list, list) { dev_info(&pf->pdev->dev, - " mac_filter_list: %pM vid=%d, is_netdev=%d is_vf=%d counter=%d, state %s\n", - f->macaddr, f->vlan, f->is_netdev, f->is_vf, - f->counter, i40e_filter_state_string[f->state]); + " mac_filter_hash: %pM vid=%d, state %s\n", + f->macaddr, f->vlan, + i40e_filter_state_string[f->state]); } dev_info(&pf->pdev->dev, " active_filters %d, promisc_threshold %d, overflow promisc %s\n", vsi->active_filters, vsi->promisc_threshold, @@ -867,86 +867,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp, dev_info(&pf->pdev->dev, "deleting relay %d\n", veb_seid); i40e_veb_release(pf->veb[i]); - - } else if (strncmp(cmd_buf, "add macaddr", 11) == 0) { - struct i40e_mac_filter *f; - int vlan = 0; - u8 ma[6]; - int ret; - - cnt = sscanf(&cmd_buf[11], - "%i %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %i", - &vsi_seid, - &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5], - &vlan); - if (cnt == 7) { - vlan = 0; - } else if (cnt != 8) { - dev_info(&pf->pdev->dev, - "add macaddr: bad command string, cnt=%d\n", - cnt); - goto command_write_done; - } - - vsi = i40e_dbg_find_vsi(pf, vsi_seid); - if (!vsi) { - dev_info(&pf->pdev->dev, - "add macaddr: VSI %d not found\n", vsi_seid); - goto command_write_done; - } - - spin_lock_bh(&vsi->mac_filter_list_lock); - f = i40e_add_filter(vsi, ma, vlan, false, false); - spin_unlock_bh(&vsi->mac_filter_list_lock); - ret = i40e_sync_vsi_filters(vsi); - if (f && !ret) - dev_info(&pf->pdev->dev, - "add macaddr: %pM vlan=%d added to VSI %d\n", - ma, vlan, vsi_seid); - else - dev_info(&pf->pdev->dev, - "add macaddr: %pM vlan=%d to VSI %d failed, f=%p ret=%d\n", - ma, vlan, vsi_seid, f, ret); - - } else if (strncmp(cmd_buf, "del macaddr", 11) == 0) { - int vlan = 0; - u8 ma[6]; - int ret; - - cnt = sscanf(&cmd_buf[11], - "%i %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %i", - &vsi_seid, - &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5], - &vlan); - if (cnt == 7) { - vlan = 0; - } else if (cnt != 8) { - dev_info(&pf->pdev->dev, - "del macaddr: bad command string, cnt=%d\n", - cnt); - goto command_write_done; - } - - vsi = i40e_dbg_find_vsi(pf, vsi_seid); - if (!vsi) { - dev_info(&pf->pdev->dev, - "del macaddr: VSI %d not found\n", vsi_seid); - goto command_write_done; - } - - spin_lock_bh(&vsi->mac_filter_list_lock); - i40e_del_filter(vsi, ma, vlan, false, false); - spin_unlock_bh(&vsi->mac_filter_list_lock); - ret = i40e_sync_vsi_filters(vsi); - if (!ret) - dev_info(&pf->pdev->dev, - "del macaddr: %pM vlan=%d removed from VSI %d\n", - ma, vlan, vsi_seid); - else - dev_info(&pf->pdev->dev, - "del macaddr: %pM vlan=%d from VSI %d failed, ret=%d\n", - ma, vlan, vsi_seid, ret); - } else if (strncmp(cmd_buf, "add pvid", 8) == 0) { i40e_status ret; u16 vid; @@ -1615,8 +1535,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp, dev_info(&pf->pdev->dev, " del vsi [vsi_seid]\n"); dev_info(&pf->pdev->dev, " add relay \n"); dev_info(&pf->pdev->dev, " del relay \n"); - dev_info(&pf->pdev->dev, " add macaddr [vlan]\n"); - dev_info(&pf->pdev->dev, " del macaddr [vlan]\n"); dev_info(&pf->pdev->dev, " add pvid \n"); dev_info(&pf->pdev->dev, " del pvid \n"); dev_info(&pf->pdev->dev, " dump switch\n"); diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 58e6c1570335..0c2a00d666ad 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -1523,10 +1523,10 @@ void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi) */ netdev->dev_port = 1; spin_lock_bh(&vsi->mac_filter_list_lock); - i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false); - i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false); - i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false); - i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false); + i40e_add_filter(vsi, hw->mac.san_addr, 0); + i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0); + i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0); + i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0); spin_unlock_bh(&vsi->mac_filter_list_lock); /* use san mac */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d78a4dc7b00b..ed49113d858f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1145,14 +1145,11 @@ void i40e_update_stats(struct i40e_vsi *vsi) * @vsi: the VSI to be searched * @macaddr: the MAC address * @vlan: the vlan - * @is_vf: make sure its a VF filter, else doesn't matter - * @is_netdev: make sure its a netdev filter, else doesn't matter * * Returns ptr to the filter object or NULL **/ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi, - u8 *macaddr, s16 vlan, - bool is_vf, bool is_netdev) + u8 *macaddr, s16 vlan) { struct i40e_mac_filter *f; @@ -1161,9 +1158,7 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi, list_for_each_entry(f, &vsi->mac_filter_list, list) { if ((ether_addr_equal(macaddr, f->macaddr)) && - (vlan == f->vlan) && - (!is_vf || f->is_vf) && - (!is_netdev || f->is_netdev)) + (vlan == f->vlan)) return f; } return NULL; @@ -1173,14 +1168,11 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi, * i40e_find_mac - Find a mac addr in the macvlan filters list * @vsi: the VSI to be searched * @macaddr: the MAC address we are searching for - * @is_vf: make sure its a VF filter, else doesn't matter - * @is_netdev: make sure its a netdev filter, else doesn't matter * * Returns the first filter with the provided MAC address or NULL if * MAC address was not found **/ -struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, - bool is_vf, bool is_netdev) +struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr) { struct i40e_mac_filter *f; @@ -1188,9 +1180,7 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, return NULL; list_for_each_entry(f, &vsi->mac_filter_list, list) { - if ((ether_addr_equal(macaddr, f->macaddr)) && - (!is_vf || f->is_vf) && - (!is_netdev || f->is_netdev)) + if ((ether_addr_equal(macaddr, f->macaddr))) return f; } return NULL; @@ -1221,26 +1211,21 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans * @vsi: the VSI to be searched * @macaddr: the mac address to be filtered - * @is_vf: true if it is a VF - * @is_netdev: true if it is a netdev * * Goes through all the macvlan filters and adds a * macvlan filter for each unique vlan that already exists * * Returns first filter found on success, else NULL **/ -struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, - bool is_vf, bool is_netdev) +struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr) { struct i40e_mac_filter *f; list_for_each_entry(f, &vsi->mac_filter_list, list) { if (vsi->info.pvid) f->vlan = le16_to_cpu(vsi->info.pvid); - if (!i40e_find_filter(vsi, macaddr, f->vlan, - is_vf, is_netdev)) { - if (!i40e_add_filter(vsi, macaddr, f->vlan, - is_vf, is_netdev)) + if (!i40e_find_filter(vsi, macaddr, f->vlan)) { + if (!i40e_add_filter(vsi, macaddr, f->vlan)) return NULL; } } @@ -1253,15 +1238,12 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS * @vsi: the VSI to be searched * @macaddr: the mac address to be removed - * @is_vf: true if it is a VF - * @is_netdev: true if it is a netdev * * Removes a given MAC address from a VSI, regardless of VLAN * * Returns 0 for success, or error **/ -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, - bool is_vf, bool is_netdev) +int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr) { struct i40e_mac_filter *f = NULL; int changed = 0; @@ -1269,13 +1251,8 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, WARN(!spin_is_locked(&vsi->mac_filter_list_lock), "Missing mac_filter_list_lock\n"); list_for_each_entry(f, &vsi->mac_filter_list, list) { - if ((ether_addr_equal(macaddr, f->macaddr)) && - (is_vf == f->is_vf) && - (is_netdev == f->is_netdev)) { - f->counter--; - changed = 1; - if (f->counter == 0) - f->state = I40E_FILTER_REMOVE; + if ((ether_addr_equal(macaddr, f->macaddr))) { + f->state = I40E_FILTER_REMOVE; } } if (changed) { @@ -1291,8 +1268,6 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, * @vsi: the VSI to be searched * @macaddr: the MAC address * @vlan: the vlan - * @is_vf: make sure its a VF filter, else doesn't matter - * @is_netdev: make sure its a netdev filter, else doesn't matter * * Returns ptr to the filter object or NULL when no memory available. * @@ -1300,11 +1275,9 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, * being held. **/ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, - u8 *macaddr, s16 vlan, - bool is_vf, bool is_netdev) + u8 *macaddr, s16 vlan) { struct i40e_mac_filter *f; - int changed = false; if (!vsi || !macaddr) return NULL; @@ -1316,11 +1289,11 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, if (is_broadcast_ether_addr(macaddr)) return NULL; - f = i40e_find_filter(vsi, macaddr, vlan, is_vf, is_netdev); + f = i40e_find_filter(vsi, macaddr, vlan); if (!f) { f = kzalloc(sizeof(*f), GFP_ATOMIC); if (!f) - goto add_filter_out; + return NULL; ether_addr_copy(f->macaddr, macaddr); f->vlan = vlan; @@ -1332,32 +1305,24 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, f->state = I40E_FILTER_FAILED; else f->state = I40E_FILTER_NEW; - changed = true; INIT_LIST_HEAD(&f->list); list_add_tail(&f->list, &vsi->mac_filter_list); - } - - /* increment counter and add a new flag if needed */ - if (is_vf) { - if (!f->is_vf) { - f->is_vf = true; - f->counter++; - } - } else if (is_netdev) { - if (!f->is_netdev) { - f->is_netdev = true; - f->counter++; - } - } else { - f->counter++; - } - if (changed) { vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; vsi->back->flags |= I40E_FLAG_FILTER_SYNC; } -add_filter_out: + /* If we're asked to add a filter that has been marked for removal, it + * is safe to simply restore it to active state. __i40e_del_filter + * will have simply deleted any filters which were previously marked + * NEW or FAILED, so if it is currently marked REMOVE it must have + * previously been ACTIVE. Since we haven't yet run the sync filters + * task, just restore this filter to the ACTIVE state so that the + * sync task leaves it in place + */ + if (f->state == I40E_FILTER_REMOVE) + f->state = I40E_FILTER_ACTIVE; + return f; } @@ -1366,8 +1331,6 @@ add_filter_out: * @vsi: the VSI to be searched * @macaddr: the MAC address * @vlan: the vlan - * @is_vf: make sure it's a VF filter, else doesn't matter - * @is_netdev: make sure it's a netdev filter, else doesn't matter * * NOTE: This function is expected to be called with mac_filter_list_lock * being held. @@ -1375,56 +1338,28 @@ add_filter_out: * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() * instead of list_for_each_entry(). **/ -void i40e_del_filter(struct i40e_vsi *vsi, - u8 *macaddr, s16 vlan, - bool is_vf, bool is_netdev) +void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan) { struct i40e_mac_filter *f; if (!vsi || !macaddr) return; - f = i40e_find_filter(vsi, macaddr, vlan, is_vf, is_netdev); - if (!f || f->counter == 0) + f = i40e_find_filter(vsi, macaddr, vlan); + if (!f) return; - if (is_vf) { - if (f->is_vf) { - f->is_vf = false; - f->counter--; - } - } else if (is_netdev) { - if (f->is_netdev) { - f->is_netdev = false; - f->counter--; - } + if ((f->state == I40E_FILTER_FAILED) || + (f->state == I40E_FILTER_NEW)) { + /* this one never got added by the FW. Just remove it, + * no need to sync anything. + */ + list_del(&f->list); + kfree(f); } else { - /* make sure we don't remove a filter in use by VF or netdev */ - int min_f = 0; - - min_f += (f->is_vf ? 1 : 0); - min_f += (f->is_netdev ? 1 : 0); - - if (f->counter > min_f) - f->counter--; - } - - /* counter == 0 tells sync_filters_subtask to - * remove the filter from the firmware's list - */ - if (f->counter == 0) { - if ((f->state == I40E_FILTER_FAILED) || - (f->state == I40E_FILTER_NEW)) { - /* this one never got added by the FW. Just remove it, - * no need to sync anything. - */ - list_del(&f->list); - kfree(f); - } else { - f->state = I40E_FILTER_REMOVE; - vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; - vsi->back->flags |= I40E_FLAG_FILTER_SYNC; - } + f->state = I40E_FILTER_REMOVE; + vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; + vsi->back->flags |= I40E_FLAG_FILTER_SYNC; } } @@ -1467,8 +1402,8 @@ static int i40e_set_mac(struct net_device *netdev, void *p) netdev_info(netdev, "set new mac address %pM\n", addr->sa_data); spin_lock_bh(&vsi->mac_filter_list_lock); - i40e_del_mac_all_vlan(vsi, netdev->dev_addr, false, true); - i40e_put_mac_in_vlan(vsi, addr->sa_data, false, true); + i40e_del_mac_all_vlan(vsi, netdev->dev_addr); + i40e_put_mac_in_vlan(vsi, addr->sa_data); spin_unlock_bh(&vsi->mac_filter_list_lock); ether_addr_copy(netdev->dev_addr, addr->sa_data); if (vsi->type == I40E_VSI_MAIN) { @@ -1653,33 +1588,26 @@ static void i40e_set_rx_mode(struct net_device *netdev) /* add addr if not already in the filter list */ netdev_for_each_uc_addr(uca, netdev) { - if (!i40e_find_mac(vsi, uca->addr, false, true)) { + if (!i40e_find_mac(vsi, uca->addr)) { if (i40e_is_vsi_in_vlan(vsi)) - i40e_put_mac_in_vlan(vsi, uca->addr, - false, true); + i40e_put_mac_in_vlan(vsi, uca->addr); else - i40e_add_filter(vsi, uca->addr, I40E_VLAN_ANY, - false, true); + i40e_add_filter(vsi, uca->addr, I40E_VLAN_ANY); } } netdev_for_each_mc_addr(mca, netdev) { - if (!i40e_find_mac(vsi, mca->addr, false, true)) { + if (!i40e_find_mac(vsi, mca->addr)) { if (i40e_is_vsi_in_vlan(vsi)) - i40e_put_mac_in_vlan(vsi, mca->addr, - false, true); + i40e_put_mac_in_vlan(vsi, mca->addr); else - i40e_add_filter(vsi, mca->addr, I40E_VLAN_ANY, - false, true); + i40e_add_filter(vsi, mca->addr, I40E_VLAN_ANY); } } /* remove filter if not in netdev list */ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - if (!f->is_netdev) - continue; - netdev_for_each_mc_addr(mca, netdev) if (ether_addr_equal(mca->addr, f->macaddr)) goto bottom_of_search_loop; @@ -1693,7 +1621,7 @@ static void i40e_set_rx_mode(struct net_device *netdev) goto bottom_of_search_loop; /* f->macaddr wasn't found in uc, mc, or ha list so delete it */ - i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, false, true); + i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY); bottom_of_search_loop: continue; @@ -1838,13 +1766,11 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) /* Create a list of filters to delete. */ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { if (f->state == I40E_FILTER_REMOVE) { - WARN_ON(f->counter != 0); /* Move the element into temporary del_list */ list_move_tail(&f->list, &tmp_del_list); vsi->active_filters--; } if (f->state == I40E_FILTER_NEW) { - WARN_ON(f->counter == 0); /* Move the element into temporary add_list */ list_move_tail(&f->list, &tmp_add_list); } @@ -2323,17 +2249,12 @@ static void i40e_vlan_rx_register(struct net_device *netdev, u32 features) int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) { struct i40e_mac_filter *f, *ftmp, *add_f; - bool is_netdev, is_vf; - - is_vf = (vsi->type == I40E_VSI_SRIOV); - is_netdev = !!(vsi->netdev); /* Locked once because all functions invoked below iterates list*/ spin_lock_bh(&vsi->mac_filter_list_lock); - if (is_netdev) { - add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, vid, - is_vf, is_netdev); + if (vsi->netdev) { + add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, vid); if (!add_f) { dev_info(&vsi->back->pdev->dev, "Could not add vlan filter %d for %pM\n", @@ -2344,7 +2265,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) } list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - add_f = i40e_add_filter(vsi, f->macaddr, vid, is_vf, is_netdev); + add_f = i40e_add_filter(vsi, f->macaddr, vid); if (!add_f) { dev_info(&vsi->back->pdev->dev, "Could not add vlan filter %d for %pM\n", @@ -2360,13 +2281,11 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) * (and not all tags along with untagged) */ if (vid > 0) { - if (is_netdev && i40e_find_filter(vsi, vsi->netdev->dev_addr, - I40E_VLAN_ANY, - is_vf, is_netdev)) { + if (vsi->netdev && i40e_find_filter(vsi, vsi->netdev->dev_addr, + I40E_VLAN_ANY)) { i40e_del_filter(vsi, vsi->netdev->dev_addr, - I40E_VLAN_ANY, is_vf, is_netdev); - add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, 0, - is_vf, is_netdev); + I40E_VLAN_ANY); + add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, 0); if (!add_f) { dev_info(&vsi->back->pdev->dev, "Could not add filter 0 for %pM\n", @@ -2380,13 +2299,10 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) /* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */ if (vid > 0 && !vsi->info.pvid) { list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY, - is_vf, is_netdev)) + if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY)) continue; - i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, - is_vf, is_netdev); - add_f = i40e_add_filter(vsi, f->macaddr, - 0, is_vf, is_netdev); + i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY); + add_f = i40e_add_filter(vsi, f->macaddr, 0); if (!add_f) { dev_info(&vsi->back->pdev->dev, "Could not add filter 0 for %pM\n", @@ -2417,20 +2333,16 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) { struct net_device *netdev = vsi->netdev; struct i40e_mac_filter *f, *ftmp, *add_f; - bool is_vf, is_netdev; int filter_count = 0; - is_vf = (vsi->type == I40E_VSI_SRIOV); - is_netdev = !!(netdev); - /* Locked once because all functions invoked below iterates list */ spin_lock_bh(&vsi->mac_filter_list_lock); - if (is_netdev) - i40e_del_filter(vsi, netdev->dev_addr, vid, is_vf, is_netdev); + if (vsi->netdev) + i40e_del_filter(vsi, netdev->dev_addr, vid); list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) - i40e_del_filter(vsi, f->macaddr, vid, is_vf, is_netdev); + i40e_del_filter(vsi, f->macaddr, vid); /* go through all the filters for this VSI and if there is only * vid == 0 it means there are no other filters, so vid 0 must @@ -2438,7 +2350,7 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) * on accept any traffic (with any tag present, or untagged) */ list_for_each_entry(f, &vsi->mac_filter_list, list) { - if (is_netdev) { + if (vsi->netdev) { if (f->vlan && ether_addr_equal(netdev->dev_addr, f->macaddr)) filter_count++; @@ -2448,10 +2360,9 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) filter_count++; } - if (!filter_count && is_netdev) { - i40e_del_filter(vsi, netdev->dev_addr, 0, is_vf, is_netdev); - f = i40e_add_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, - is_vf, is_netdev); + if (!filter_count && vsi->netdev) { + i40e_del_filter(vsi, netdev->dev_addr, 0); + f = i40e_add_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY); if (!f) { dev_info(&vsi->back->pdev->dev, "Could not add filter %d for %pM\n", @@ -2463,9 +2374,8 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) if (!filter_count) { list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - i40e_del_filter(vsi, f->macaddr, 0, is_vf, is_netdev); - add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY, - is_vf, is_netdev); + i40e_del_filter(vsi, f->macaddr, 0); + add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY); if (!add_f) { dev_info(&vsi->back->pdev->dev, "Could not add filter %d for %pM\n", @@ -9155,7 +9065,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) SET_NETDEV_DEV(netdev, &pf->pdev->dev); ether_addr_copy(mac_addr, hw->mac.perm_addr); spin_lock_bh(&vsi->mac_filter_list_lock); - i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, true); + i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY); spin_unlock_bh(&vsi->mac_filter_list_lock); } else { /* relate the VSI_VMDQ name to the VSI_MAIN name */ @@ -9164,7 +9074,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) random_ether_addr(mac_addr); spin_lock_bh(&vsi->mac_filter_list_lock); - i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, false); + i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY); spin_unlock_bh(&vsi->mac_filter_list_lock); } @@ -9525,8 +9435,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) spin_lock_bh(&vsi->mac_filter_list_lock); list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) - i40e_del_filter(vsi, f->macaddr, f->vlan, - f->is_vf, f->is_netdev); + i40e_del_filter(vsi, f->macaddr, f->vlan); spin_unlock_bh(&vsi->mac_filter_list_lock); i40e_sync_vsi_filters(vsi); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 64e54a562f41..37e6afcd01b0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -689,8 +689,8 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) spin_lock_bh(&vsi->mac_filter_list_lock); if (is_valid_ether_addr(vf->default_lan_addr.addr)) { f = i40e_add_filter(vsi, vf->default_lan_addr.addr, - vf->port_vlan_id ? vf->port_vlan_id : -1, - true, false); + vf->port_vlan_id ? + vf->port_vlan_id : -1); if (!f) dev_info(&pf->pdev->dev, "Could not add MAC filter %pM for VF %d\n", @@ -1933,14 +1933,12 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) for (i = 0; i < al->num_elements; i++) { struct i40e_mac_filter *f; - f = i40e_find_mac(vsi, al->list[i].addr, true, false); + f = i40e_find_mac(vsi, al->list[i].addr); if (!f) { if (i40e_is_vsi_in_vlan(vsi)) - f = i40e_put_mac_in_vlan(vsi, al->list[i].addr, - true, false); + f = i40e_put_mac_in_vlan(vsi, al->list[i].addr); else - f = i40e_add_filter(vsi, al->list[i].addr, -1, - true, false); + f = i40e_add_filter(vsi, al->list[i].addr, -1); } if (!f) { @@ -2006,7 +2004,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) spin_lock_bh(&vsi->mac_filter_list_lock); /* delete addresses from the list */ for (i = 0; i < al->num_elements; i++) - if (i40e_del_mac_all_vlan(vsi, al->list[i].addr, true, false)) { + if (i40e_del_mac_all_vlan(vsi, al->list[i].addr)) { ret = I40E_ERR_INVALID_MAC_ADDR; spin_unlock_bh(&vsi->mac_filter_list_lock); goto error_param; @@ -2722,14 +2720,13 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) /* delete the temporary mac address */ if (!is_zero_ether_addr(vf->default_lan_addr.addr)) i40e_del_filter(vsi, vf->default_lan_addr.addr, - vf->port_vlan_id ? vf->port_vlan_id : -1, - true, false); + vf->port_vlan_id ? vf->port_vlan_id : -1); /* Delete all the filters for this VSI - we're going to kill it * anyway. */ list_for_each_entry(f, &vsi->mac_filter_list, list) - i40e_del_filter(vsi, f->macaddr, f->vlan, true, false); + i40e_del_filter(vsi, f->macaddr, f->vlan); spin_unlock_bh(&vsi->mac_filter_list_lock); -- cgit v1.2.3 From 6622f5cdbaf3786314d76969d2aab132b36ba2e8 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:32 -0700 Subject: i40e: make use of __dev_uc_sync and __dev_mc_sync The kernel provides __dev_uc_sync and __dev_mc_sync in order for drivers which need individual notification of add and delete for each filter. These functions allow us to vastly simplify our .set_rx_mode handler. We need to implement two functions for sync and unsync which add and remove filters respectively. This change avoids a very complex and inefficient algorithm which resulted in an abnormal latency for the .set_rx_mode NDO operation. The resulting code after this change is more readable, more efficient, and less code. Due to the callback signature used by these functions we also must update several other functions to take a const u8 * pointer. Change-Id: I2ca7fd4e10c0c07ed2291db1ea41bf5987fc6474 Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 10 +-- drivers/net/ethernet/intel/i40e/i40e_main.c | 113 ++++++++++++++++------------ 2 files changed, 69 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 844559188c6b..a9c02289049f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -720,8 +720,8 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf); bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features); void i40e_set_ethtool_ops(struct net_device *netdev); struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, - u8 *macaddr, s16 vlan); -void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan); + const u8 *macaddr, s16 vlan); +void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan); int i40e_sync_vsi_filters(struct i40e_vsi *vsi); struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, u16 uplink, u32 param1); @@ -813,10 +813,10 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi); int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid); int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid); struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, - u8 *macaddr); -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr); + const u8 *macaddr); +int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr); bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); -struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr); +struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr); #ifdef I40E_FCOE int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, struct tc_to_netdev *tc); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index ed49113d858f..c63dc0153765 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1149,7 +1149,7 @@ void i40e_update_stats(struct i40e_vsi *vsi) * Returns ptr to the filter object or NULL **/ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi, - u8 *macaddr, s16 vlan) + const u8 *macaddr, s16 vlan) { struct i40e_mac_filter *f; @@ -1172,7 +1172,7 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi, * Returns the first filter with the provided MAC address or NULL if * MAC address was not found **/ -struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr) +struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr) { struct i40e_mac_filter *f; @@ -1217,7 +1217,8 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) * * Returns first filter found on success, else NULL **/ -struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr) +struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, + const u8 *macaddr) { struct i40e_mac_filter *f; @@ -1243,7 +1244,7 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr) * * Returns 0 for success, or error **/ -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr) +int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr) { struct i40e_mac_filter *f = NULL; int changed = 0; @@ -1275,7 +1276,7 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr) * being held. **/ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, - u8 *macaddr, s16 vlan) + const u8 *macaddr, s16 vlan) { struct i40e_mac_filter *f; @@ -1338,7 +1339,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() * instead of list_for_each_entry(). **/ -void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan) +void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) { struct i40e_mac_filter *f; @@ -1567,6 +1568,52 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, ctxt->info.valid_sections |= cpu_to_le16(sections); } +/** + * i40e_addr_sync - Callback for dev_(mc|uc)_sync to add address + * @netdev: the netdevice + * @addr: address to add + * + * Called by __dev_(mc|uc)_sync when an address needs to be added. We call + * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock. + */ +static int i40e_addr_sync(struct net_device *netdev, const u8 *addr) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_vsi *vsi = np->vsi; + struct i40e_mac_filter *f; + + if (i40e_is_vsi_in_vlan(vsi)) + f = i40e_put_mac_in_vlan(vsi, addr); + else + f = i40e_add_filter(vsi, addr, I40E_VLAN_ANY); + + if (f) + return 0; + else + return -ENOMEM; +} + +/** + * i40e_addr_unsync - Callback for dev_(mc|uc)_sync to remove address + * @netdev: the netdevice + * @addr: address to add + * + * Called by __dev_(mc|uc)_sync when an address needs to be removed. We call + * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock. + */ +static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_vsi *vsi = np->vsi; + + if (i40e_is_vsi_in_vlan(vsi)) + i40e_del_mac_all_vlan(vsi, addr); + else + i40e_del_filter(vsi, addr, I40E_VLAN_ANY); + + return 0; +} + /** * i40e_set_rx_mode - NDO callback to set the netdev filters * @netdev: network interface device structure @@ -1578,54 +1625,13 @@ static void i40e_set_rx_mode(struct net_device *netdev) #endif { struct i40e_netdev_priv *np = netdev_priv(netdev); - struct i40e_mac_filter *f, *ftmp; struct i40e_vsi *vsi = np->vsi; - struct netdev_hw_addr *uca; - struct netdev_hw_addr *mca; - struct netdev_hw_addr *ha; spin_lock_bh(&vsi->mac_filter_list_lock); - /* add addr if not already in the filter list */ - netdev_for_each_uc_addr(uca, netdev) { - if (!i40e_find_mac(vsi, uca->addr)) { - if (i40e_is_vsi_in_vlan(vsi)) - i40e_put_mac_in_vlan(vsi, uca->addr); - else - i40e_add_filter(vsi, uca->addr, I40E_VLAN_ANY); - } - } - - netdev_for_each_mc_addr(mca, netdev) { - if (!i40e_find_mac(vsi, mca->addr)) { - if (i40e_is_vsi_in_vlan(vsi)) - i40e_put_mac_in_vlan(vsi, mca->addr); - else - i40e_add_filter(vsi, mca->addr, I40E_VLAN_ANY); - } - } + __dev_uc_sync(netdev, i40e_addr_sync, i40e_addr_unsync); + __dev_mc_sync(netdev, i40e_addr_sync, i40e_addr_unsync); - /* remove filter if not in netdev list */ - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - - netdev_for_each_mc_addr(mca, netdev) - if (ether_addr_equal(mca->addr, f->macaddr)) - goto bottom_of_search_loop; - - netdev_for_each_uc_addr(uca, netdev) - if (ether_addr_equal(uca->addr, f->macaddr)) - goto bottom_of_search_loop; - - for_each_dev_addr(netdev, ha) - if (ether_addr_equal(ha->addr, f->macaddr)) - goto bottom_of_search_loop; - - /* f->macaddr wasn't found in uc, mc, or ha list so delete it */ - i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY); - -bottom_of_search_loop: - continue; - } spin_unlock_bh(&vsi->mac_filter_list_lock); /* check for other flag changes */ @@ -9434,8 +9440,17 @@ int i40e_vsi_release(struct i40e_vsi *vsi) } spin_lock_bh(&vsi->mac_filter_list_lock); + + /* clear the sync flag on all filters */ + if (vsi->netdev) { + __dev_uc_unsync(vsi->netdev, NULL); + __dev_mc_unsync(vsi->netdev, NULL); + } + + /* make sure any remaining filters are marked for deletion */ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) i40e_del_filter(vsi, f->macaddr, f->vlan); + spin_unlock_bh(&vsi->mac_filter_list_lock); i40e_sync_vsi_filters(vsi); -- cgit v1.2.3 From 35ec2ff37c5a4897e75d408828adac737b17d2bf Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:33 -0700 Subject: i40e: move i40e_put_mac_in_vlan and i40e_del_mac_all_vlan A future patch will be modifying these functions and making a call to a static function which currently is defined after these functions. Move them in a separate patch to ease review and ensure the moved code is correct. Change-ID: I2ca7fd4e10c0c07ed2291db1ea41bf5987fc6474 Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 113 ++++++++++++++-------------- 1 file changed, 56 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c63dc0153765..f7fe020e5e2a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1207,63 +1207,6 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) return false; } -/** - * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans - * @vsi: the VSI to be searched - * @macaddr: the mac address to be filtered - * - * Goes through all the macvlan filters and adds a - * macvlan filter for each unique vlan that already exists - * - * Returns first filter found on success, else NULL - **/ -struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, - const u8 *macaddr) -{ - struct i40e_mac_filter *f; - - list_for_each_entry(f, &vsi->mac_filter_list, list) { - if (vsi->info.pvid) - f->vlan = le16_to_cpu(vsi->info.pvid); - if (!i40e_find_filter(vsi, macaddr, f->vlan)) { - if (!i40e_add_filter(vsi, macaddr, f->vlan)) - return NULL; - } - } - - return list_first_entry_or_null(&vsi->mac_filter_list, - struct i40e_mac_filter, list); -} - -/** - * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS - * @vsi: the VSI to be searched - * @macaddr: the mac address to be removed - * - * Removes a given MAC address from a VSI, regardless of VLAN - * - * Returns 0 for success, or error - **/ -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr) -{ - struct i40e_mac_filter *f = NULL; - int changed = 0; - - WARN(!spin_is_locked(&vsi->mac_filter_list_lock), - "Missing mac_filter_list_lock\n"); - list_for_each_entry(f, &vsi->mac_filter_list, list) { - if ((ether_addr_equal(macaddr, f->macaddr))) { - f->state = I40E_FILTER_REMOVE; - } - } - if (changed) { - vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; - vsi->back->flags |= I40E_FLAG_FILTER_SYNC; - return 0; - } - return -ENOENT; -} - /** * i40e_add_filter - Add a mac/vlan filter to the VSI * @vsi: the VSI to be searched @@ -1364,6 +1307,62 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) } } +/** + * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans + * @vsi: the VSI to be searched + * @macaddr: the mac address to be filtered + * + * Goes through all the macvlan filters and adds a + * macvlan filter for each unique vlan that already exists + * + * Returns first filter found on success, else NULL + **/ +struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, + const u8 *macaddr) +{ + struct i40e_mac_filter *f; + + list_for_each_entry(f, &vsi->mac_filter_list, list) { + if (vsi->info.pvid) + f->vlan = le16_to_cpu(vsi->info.pvid); + if (!i40e_find_filter(vsi, macaddr, f->vlan)) { + if (!i40e_add_filter(vsi, macaddr, f->vlan)) + return NULL; + } + } + + return list_first_entry_or_null(&vsi->mac_filter_list, + struct i40e_mac_filter, list); +} + +/** + * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS + * @vsi: the VSI to be searched + * @macaddr: the mac address to be removed + * + * Removes a given MAC address from a VSI, regardless of VLAN + * + * Returns 0 for success, or error + **/ +int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr) +{ + struct i40e_mac_filter *f = NULL; + int changed = 0; + + WARN(!spin_is_locked(&vsi->mac_filter_list_lock), + "Missing mac_filter_list_lock\n"); + list_for_each_entry(f, &vsi->mac_filter_list, list) { + if (ether_addr_equal(macaddr, f->macaddr)) + f->state = I40E_FILTER_REMOVE; + } + if (changed) { + vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; + vsi->back->flags |= I40E_FLAG_FILTER_SYNC; + return 0; + } + return -ENOENT; +} + /** * i40e_set_mac - NDO callback to set mac address * @netdev: network interface device structure -- cgit v1.2.3 From 5feb3d7b0c0a66c8537ca8a79d8f80f54783e73f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:34 -0700 Subject: i40e: refactor i40e_put_mac_in_vlan to avoid changing f->vlan When a PVID has been assigned to a VSI, the function i40e_put_mac_in_vlan arbitrarily modifies all filters to have the same VLAN. This is obviously incorrect because it could be modifying active filters without putting them into the NEW state. The correct method is to remove then re-add filters which is already done in the code where we assign the PVID. Fix this issue and a few other minor nits at the same time. First, when we have a PVID don't even bother looping and simply add the filter with the PVID immediately. In the case of the loop, we now can remove several checks. We also don't need to use i40e_find_filter first before calling i40e_add_filter, since i40e_add_filter implicitly does a lookup already. Finally, update the return semantics of this function so that on failure to add a filter it returns NULL, but on success, it returns the last filter added. Otherwise, we're just returning the last filter in the list. An alternative fix might be to return 0 or an error code, but this is pretty invasive to every call site. Change-ID: I2325dfd843aec76d89fb0d7cb0e7c4f290a34840 Signed-off-by: Jacob Keller Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f7fe020e5e2a..c09609339bd2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1312,27 +1312,28 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) * @vsi: the VSI to be searched * @macaddr: the mac address to be filtered * - * Goes through all the macvlan filters and adds a - * macvlan filter for each unique vlan that already exists + * Goes through all the macvlan filters and adds a macvlan filter for each + * unique vlan that already exists. If a PVID has been assigned, instead only + * add the macaddr to that VLAN. * - * Returns first filter found on success, else NULL + * Returns last filter added on success, else NULL **/ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, const u8 *macaddr) { - struct i40e_mac_filter *f; + struct i40e_mac_filter *f, *add = NULL; + + if (vsi->info.pvid) + return i40e_add_filter(vsi, macaddr, + le16_to_cpu(vsi->info.pvid)); list_for_each_entry(f, &vsi->mac_filter_list, list) { - if (vsi->info.pvid) - f->vlan = le16_to_cpu(vsi->info.pvid); - if (!i40e_find_filter(vsi, macaddr, f->vlan)) { - if (!i40e_add_filter(vsi, macaddr, f->vlan)) - return NULL; - } + add = i40e_add_filter(vsi, macaddr, f->vlan); + if (!add) + return NULL; } - return list_first_entry_or_null(&vsi->mac_filter_list, - struct i40e_mac_filter, list); + return add; } /** -- cgit v1.2.3 From 57b341d66684e380cae332eadcc210e177a9f289 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:35 -0700 Subject: i40e: When searching all MAC/VLAN filters, ignore removed filters When adding new MAC address filters, the driver determines if it should behave in VLAN mode (where all MAC addresses get assigned to every existing VLAN) or in non-VLAN mode where MAC addresses get assigned the VLAN_ANY identifier. Under some circumstances it is possible that a VLAN has been marked for removal (such that all filters of that VLAN are set to I40E_FILTER_REMOVE), and a subsequent call to i40e_put_mac_in_vlan may occur prior to the driver subtask that syncs filters to the hardware. In this case, we may add filters to the new removed VLAN, even though it should have been removed. This is most obvious when first adding a new VLAN. We will delete all filters which are in I40E_VLAN_ANY (-1) and then re-add them as in VLAN 0 (untagged). Then before we sync filters, we will add new MAC address filter, which will be added to every VLAN that exists. Unfortunately, this will include I40E_VLAN_ANY, so we will end up incorrectly adding filters to the -1 VLAN. This can be fixed by simply skipping all filters which are marked for removal. A similar check is not necessary in i40e_del_mac_all_vlan, since we are deleting, and any filter which we find already marked for removal would simply be deleted again, which doesn't cause any issues. Change-Id: I7962154013ce02fe950584690aeeb3ed853d0086 Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c09609339bd2..86ad9537d44f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1328,6 +1328,8 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, le16_to_cpu(vsi->info.pvid)); list_for_each_entry(f, &vsi->mac_filter_list, list) { + if (f->state == I40E_FILTER_REMOVE) + continue; add = i40e_add_filter(vsi, macaddr, f->vlan); if (!add) return NULL; @@ -2271,6 +2273,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) } list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + if (f->state == I40E_FILTER_REMOVE) + continue; add_f = i40e_add_filter(vsi, f->macaddr, vid); if (!add_f) { dev_info(&vsi->back->pdev->dev, @@ -2305,6 +2309,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) /* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */ if (vid > 0 && !vsi->info.pvid) { list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + if (f->state == I40E_FILTER_REMOVE) + continue; if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY)) continue; i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY); -- cgit v1.2.3 From 290d255719af42ae4baaf49165a69b9ad47f2049 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:36 -0700 Subject: i40e: implement __i40e_del_filter and use where applicable When inside a loop where we call i40e_del_filter we use an O(n^2) pattern where i40e_del_filter calls i40e_find_filter for us. We can avoid this O(n^2) logic by factoring a function, __i40e_del_filter() out from the i40e_del_filter code. This allows us to re-use the delete logic where appropriate without having to search for the filter twice. This new function benefits several functions including i40e_vsi_add_vlan, i40e_vsi_kill_vlan, i40e_del_mac_vlan_all, and i40e_vsi_release. Change-ID: I75fabe0f53bf73f56b80d342e5fdcfcc28f4d3eb Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 92 ++++++++++++++++++----------- 1 file changed, 59 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 86ad9537d44f..25db8d80b684 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1271,10 +1271,13 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, } /** - * i40e_del_filter - Remove a mac/vlan filter from the VSI - * @vsi: the VSI to be searched - * @macaddr: the MAC address - * @vlan: the vlan + * __i40e_del_filter - Remove a specific filter from the VSI + * @vsi: VSI to remove from + * @f: the filter to remove from the list + * + * This function should be called instead of i40e_del_filter only if you know + * the exact filter you will remove already, such as via i40e_find_filter or + * i40e_find_mac. * * NOTE: This function is expected to be called with mac_filter_list_lock * being held. @@ -1282,14 +1285,8 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() * instead of list_for_each_entry(). **/ -void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) +static void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f) { - struct i40e_mac_filter *f; - - if (!vsi || !macaddr) - return; - - f = i40e_find_filter(vsi, macaddr, vlan); if (!f) return; @@ -1307,6 +1304,29 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) } } +/** + * i40e_del_filter - Remove a MAC/VLAN filter from the VSI + * @vsi: the VSI to be searched + * @macaddr: the MAC address + * @vlan: the VLAN + * + * NOTE: This function is expected to be called with mac_filter_list_lock + * being held. + * ANOTHER NOTE: This function MUST be called from within the context of + * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() + * instead of list_for_each_entry(). + **/ +void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) +{ + struct i40e_mac_filter *f; + + if (!vsi || !macaddr) + return; + + f = i40e_find_filter(vsi, macaddr, vlan); + __i40e_del_filter(vsi, f); +} + /** * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans * @vsi: the VSI to be searched @@ -1349,21 +1369,22 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, **/ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr) { - struct i40e_mac_filter *f = NULL; - int changed = 0; + struct i40e_mac_filter *f, *ftmp; + bool found = false; WARN(!spin_is_locked(&vsi->mac_filter_list_lock), "Missing mac_filter_list_lock\n"); - list_for_each_entry(f, &vsi->mac_filter_list, list) { - if (ether_addr_equal(macaddr, f->macaddr)) - f->state = I40E_FILTER_REMOVE; + list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + if (ether_addr_equal(macaddr, f->macaddr)) { + __i40e_del_filter(vsi, f); + found = true; + } } - if (changed) { - vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; - vsi->back->flags |= I40E_FLAG_FILTER_SYNC; + + if (found) return 0; - } - return -ENOENT; + else + return -ENOENT; } /** @@ -2256,7 +2277,7 @@ static void i40e_vlan_rx_register(struct net_device *netdev, u32 features) **/ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) { - struct i40e_mac_filter *f, *ftmp, *add_f; + struct i40e_mac_filter *f, *ftmp, *add_f, *del_f; /* Locked once because all functions invoked below iterates list*/ spin_lock_bh(&vsi->mac_filter_list_lock); @@ -2290,11 +2311,11 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) * with 0, so we now accept untagged and specified tagged traffic * (and not all tags along with untagged) */ - if (vid > 0) { - if (vsi->netdev && i40e_find_filter(vsi, vsi->netdev->dev_addr, - I40E_VLAN_ANY)) { - i40e_del_filter(vsi, vsi->netdev->dev_addr, - I40E_VLAN_ANY); + if (vid > 0 && vsi->netdev) { + del_f = i40e_find_filter(vsi, vsi->netdev->dev_addr, + I40E_VLAN_ANY); + if (del_f) { + __i40e_del_filter(vsi, del_f); add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, 0); if (!add_f) { dev_info(&vsi->back->pdev->dev, @@ -2311,9 +2332,11 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { if (f->state == I40E_FILTER_REMOVE) continue; - if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY)) + del_f = i40e_find_filter(vsi, f->macaddr, + I40E_VLAN_ANY); + if (!del_f) continue; - i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY); + __i40e_del_filter(vsi, del_f); add_f = i40e_add_filter(vsi, f->macaddr, 0); if (!add_f) { dev_info(&vsi->back->pdev->dev, @@ -2353,8 +2376,10 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) if (vsi->netdev) i40e_del_filter(vsi, netdev->dev_addr, vid); - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) - i40e_del_filter(vsi, f->macaddr, vid); + list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + if (f->vlan == vid) + __i40e_del_filter(vsi, f); + } /* go through all the filters for this VSI and if there is only * vid == 0 it means there are no other filters, so vid 0 must @@ -2386,7 +2411,8 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) if (!filter_count) { list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - i40e_del_filter(vsi, f->macaddr, 0); + if (!f->vlan) + __i40e_del_filter(vsi, f); add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY); if (!add_f) { dev_info(&vsi->back->pdev->dev, @@ -9455,7 +9481,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) /* make sure any remaining filters are marked for deletion */ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) - i40e_del_filter(vsi, f->macaddr, f->vlan); + __i40e_del_filter(vsi, f); spin_unlock_bh(&vsi->mac_filter_list_lock); -- cgit v1.2.3 From 278e7d0b9d6864a9749b9473a273892aa1528621 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:37 -0700 Subject: i40e: store MAC/VLAN filters in a hash with the MAC Address as key Replace the mac_filter_list with a static size hash table of 8bits. The primary advantage of this is a decrease in latency of operations related to searching for specific MAC filters, including .set_rx_mode. Using a linked list resulted in several locations which were O(n^2). Using a hash table should give us latency growth closer to O(n*log(n)). Change-ID: I5330bd04053b880e670210933e35830b95948ebb Signed-off-by: Jacob Keller Tested-by: Andrew Bowers --- drivers/net/ethernet/intel/i40e/i40e.h | 24 ++- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 198 ++++++++++++--------- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 38 ++-- 5 files changed, 161 insertions(+), 107 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index a9c02289049f..6545550f5891 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -445,6 +446,20 @@ struct i40e_pf { u16 phy_led_val; }; +/** + * i40e_mac_to_hkey - Convert a 6-byte MAC Address to a u64 hash key + * @macaddr: the MAC Address as the base key + * + * Simply copies the address and returns it as a u64 for hashing + **/ +static inline u64 i40e_addr_to_hkey(const u8 *macaddr) +{ + u64 key = 0; + + ether_addr_copy((u8 *)&key, macaddr); + return key; +} + enum i40e_filter_state { I40E_FILTER_INVALID = 0, /* Invalid state */ I40E_FILTER_NEW, /* New, not sent to FW yet */ @@ -454,7 +469,7 @@ enum i40e_filter_state { /* There is no 'removed' state; the filter struct is freed */ }; struct i40e_mac_filter { - struct list_head list; + struct hlist_node hlist; u8 macaddr[ETH_ALEN]; #define I40E_VLAN_ANY -1 s16 vlan; @@ -498,9 +513,10 @@ struct i40e_vsi { #define I40E_VSI_FLAG_VEB_OWNER BIT(1) unsigned long flags; - /* Per VSI lock to protect elements/list (MAC filter) */ - spinlock_t mac_filter_list_lock; - struct list_head mac_filter_list; + /* Per VSI lock to protect elements/hash (MAC filter) */ + spinlock_t mac_filter_hash_lock; + /* Fixed size hash table with 2^8 buckets for MAC filters */ + DECLARE_HASHTABLE(mac_filter_hash, 8); /* VSI stats */ struct rtnl_link_stats64 net_stats; diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 8f6ed8d28412..b8a03a05c4e8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -134,7 +134,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) struct rtnl_link_stats64 *nstat; struct i40e_mac_filter *f; struct i40e_vsi *vsi; - int i; + int i, bkt; vsi = i40e_dbg_find_vsi(pf, seid); if (!vsi) { @@ -166,7 +166,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) pf->hw.mac.addr, pf->hw.mac.san_addr, pf->hw.mac.port_addr); - list_for_each_entry(f, &vsi->mac_filter_list, list) { + hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) { dev_info(&pf->pdev->dev, " mac_filter_hash: %pM vid=%d, state %s\n", f->macaddr, f->vlan, diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 0c2a00d666ad..b077ef8b00fa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -1522,12 +1522,12 @@ void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi) * same PCI function. */ netdev->dev_port = 1; - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); i40e_add_filter(vsi, hw->mac.san_addr, 0); i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0); i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0); i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); /* use san mac */ ether_addr_copy(netdev->dev_addr, hw->mac.san_addr); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 25db8d80b684..ea4dc9f9c416 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1152,11 +1152,13 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) { struct i40e_mac_filter *f; + u64 key; if (!vsi || !macaddr) return NULL; - list_for_each_entry(f, &vsi->mac_filter_list, list) { + key = i40e_addr_to_hkey(macaddr); + hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) { if ((ether_addr_equal(macaddr, f->macaddr)) && (vlan == f->vlan)) return f; @@ -1175,11 +1177,13 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr) { struct i40e_mac_filter *f; + u64 key; if (!vsi || !macaddr) return NULL; - list_for_each_entry(f, &vsi->mac_filter_list, list) { + key = i40e_addr_to_hkey(macaddr); + hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) { if ((ether_addr_equal(macaddr, f->macaddr))) return f; } @@ -1195,11 +1199,13 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr) bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) { struct i40e_mac_filter *f; + struct hlist_node *h; + int bkt; /* Only -1 for all the filters denotes not in vlan mode * so we have to go through all the list in order to make sure */ - list_for_each_entry(f, &vsi->mac_filter_list, list) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { if (f->vlan >= 0 || vsi->info.pvid) return true; } @@ -1215,13 +1221,14 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) * * Returns ptr to the filter object or NULL when no memory available. * - * NOTE: This function is expected to be called with mac_filter_list_lock + * NOTE: This function is expected to be called with mac_filter_hash_lock * being held. **/ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) { struct i40e_mac_filter *f; + u64 key; if (!vsi || !macaddr) return NULL; @@ -1249,8 +1256,10 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, f->state = I40E_FILTER_FAILED; else f->state = I40E_FILTER_NEW; - INIT_LIST_HEAD(&f->list); - list_add_tail(&f->list, &vsi->mac_filter_list); + INIT_HLIST_NODE(&f->hlist); + + key = i40e_addr_to_hkey(macaddr); + hash_add(vsi->mac_filter_hash, &f->hlist, key); vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; vsi->back->flags |= I40E_FLAG_FILTER_SYNC; @@ -1279,7 +1288,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, * the exact filter you will remove already, such as via i40e_find_filter or * i40e_find_mac. * - * NOTE: This function is expected to be called with mac_filter_list_lock + * NOTE: This function is expected to be called with mac_filter_hash_lock * being held. * ANOTHER NOTE: This function MUST be called from within the context of * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() @@ -1295,7 +1304,7 @@ static void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f) /* this one never got added by the FW. Just remove it, * no need to sync anything. */ - list_del(&f->list); + hash_del(&f->hlist); kfree(f); } else { f->state = I40E_FILTER_REMOVE; @@ -1310,7 +1319,7 @@ static void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f) * @macaddr: the MAC address * @vlan: the VLAN * - * NOTE: This function is expected to be called with mac_filter_list_lock + * NOTE: This function is expected to be called with mac_filter_hash_lock * being held. * ANOTHER NOTE: This function MUST be called from within the context of * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() @@ -1342,12 +1351,14 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, const u8 *macaddr) { struct i40e_mac_filter *f, *add = NULL; + struct hlist_node *h; + int bkt; if (vsi->info.pvid) return i40e_add_filter(vsi, macaddr, le16_to_cpu(vsi->info.pvid)); - list_for_each_entry(f, &vsi->mac_filter_list, list) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { if (f->state == I40E_FILTER_REMOVE) continue; add = i40e_add_filter(vsi, macaddr, f->vlan); @@ -1369,12 +1380,14 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, **/ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr) { - struct i40e_mac_filter *f, *ftmp; + struct i40e_mac_filter *f; + struct hlist_node *h; bool found = false; + int bkt; - WARN(!spin_is_locked(&vsi->mac_filter_list_lock), - "Missing mac_filter_list_lock\n"); - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + WARN(!spin_is_locked(&vsi->mac_filter_hash_lock), + "Missing mac_filter_hash_lock\n"); + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { if (ether_addr_equal(macaddr, f->macaddr)) { __i40e_del_filter(vsi, f); found = true; @@ -1425,10 +1438,10 @@ static int i40e_set_mac(struct net_device *netdev, void *p) else netdev_info(netdev, "set new mac address %pM\n", addr->sa_data); - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); i40e_del_mac_all_vlan(vsi, netdev->dev_addr); i40e_put_mac_in_vlan(vsi, addr->sa_data); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); ether_addr_copy(netdev->dev_addr, addr->sa_data); if (vsi->type == I40E_VSI_MAIN) { i40e_status ret; @@ -1650,12 +1663,12 @@ static void i40e_set_rx_mode(struct net_device *netdev) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); __dev_uc_sync(netdev, i40e_addr_sync, i40e_addr_unsync); __dev_mc_sync(netdev, i40e_addr_sync, i40e_addr_unsync); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); /* check for other flag changes */ if (vsi->current_netdev_flags != vsi->netdev->flags) { @@ -1678,13 +1691,17 @@ static void i40e_set_rx_mode(struct net_device *netdev) * MAC filter entries from list were slated to be removed from device. **/ static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi, - struct list_head *from) + struct hlist_head *from) { - struct i40e_mac_filter *f, *ftmp; + struct i40e_mac_filter *f; + struct hlist_node *h; + + hlist_for_each_entry_safe(f, h, from, hlist) { + u64 key = i40e_addr_to_hkey(f->macaddr); - list_for_each_entry_safe(f, ftmp, from, list) { /* Move the element back into MAC filter list*/ - list_move_tail(&f->list, &vsi->mac_filter_list); + hlist_del(&f->hlist); + hash_add(vsi->mac_filter_hash, &f->hlist, key); } } @@ -1713,7 +1730,9 @@ i40e_update_filter_state(int count, /* Everything's good, mark all filters active. */ for (i = 0; i < count ; i++) { add_head->state = I40E_FILTER_ACTIVE; - add_head = list_next_entry(add_head, list); + add_head = hlist_entry(add_head->hlist.next, + typeof(struct i40e_mac_filter), + hlist); } } else if (aq_err == I40E_AQ_RC_ENOSPC) { /* Device ran out of filter space. Check the return value @@ -1727,14 +1746,18 @@ i40e_update_filter_state(int count, add_head->state = I40E_FILTER_ACTIVE; retval++; } - add_head = list_next_entry(add_head, list); + add_head = hlist_entry(add_head->hlist.next, + typeof(struct i40e_mac_filter), + hlist); } } else { /* Some other horrible thing happened, fail all filters */ retval = 0; for (i = 0; i < count ; i++) { add_head->state = I40E_FILTER_FAILED; - add_head = list_next_entry(add_head, list); + add_head = hlist_entry(add_head->hlist.next, + typeof(struct i40e_mac_filter), + hlist); } } return retval; @@ -1750,14 +1773,15 @@ i40e_update_filter_state(int count, **/ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) { - struct i40e_mac_filter *f, *ftmp, *add_head = NULL; - struct list_head tmp_add_list, tmp_del_list; + struct i40e_mac_filter *f, *add_head = NULL; + struct hlist_head tmp_add_list, tmp_del_list; struct i40e_hw *hw = &vsi->back->hw; bool promisc_changed = false; char vsi_name[16] = "PF"; int filter_list_len = 0; u32 changed_flags = 0; i40e_status aq_ret = 0; + struct hlist_node *h; int retval = 0; struct i40e_pf *pf; int num_add = 0; @@ -1766,6 +1790,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) u16 cmd_flags; int list_size; int fcnt; + int bkt; /* empty array typed pointers, kcalloc later */ struct i40e_aqc_add_macvlan_element_data *add_list; @@ -1780,8 +1805,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) vsi->current_netdev_flags = vsi->netdev->flags; } - INIT_LIST_HEAD(&tmp_add_list); - INIT_LIST_HEAD(&tmp_del_list); + INIT_HLIST_HEAD(&tmp_add_list); + INIT_HLIST_HEAD(&tmp_del_list); if (vsi->type == I40E_VSI_SRIOV) snprintf(vsi_name, sizeof(vsi_name) - 1, "VF %d", vsi->vf_id); @@ -1791,24 +1816,25 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) if (vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) { vsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED; - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); /* Create a list of filters to delete. */ - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { if (f->state == I40E_FILTER_REMOVE) { /* Move the element into temporary del_list */ - list_move_tail(&f->list, &tmp_del_list); + hash_del(&f->hlist); + hlist_add_head(&f->hlist, &tmp_del_list); vsi->active_filters--; } if (f->state == I40E_FILTER_NEW) { - /* Move the element into temporary add_list */ - list_move_tail(&f->list, &tmp_add_list); + hash_del(&f->hlist); + hlist_add_head(&f->hlist, &tmp_add_list); } } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); } /* Now process 'del_list' outside the lock */ - if (!list_empty(&tmp_del_list)) { + if (!hlist_empty(&tmp_del_list)) { filter_list_len = hw->aq.asq_buf_size / sizeof(struct i40e_aqc_remove_macvlan_element_data); list_size = filter_list_len * @@ -1816,14 +1842,14 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) del_list = kzalloc(list_size, GFP_ATOMIC); if (!del_list) { /* Undo VSI's MAC filter entry element updates */ - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); i40e_undo_del_filter_entries(vsi, &tmp_del_list); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); retval = -ENOMEM; goto out; } - list_for_each_entry_safe(f, ftmp, &tmp_del_list, list) { + hlist_for_each_entry_safe(f, h, &tmp_del_list, hlist) { cmd_flags = 0; /* add to delete list */ @@ -1864,7 +1890,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) /* Release memory for MAC filter entries which were * synced up with HW. */ - list_del(&f->list); + hlist_del(&f->hlist); kfree(f); } @@ -1891,7 +1917,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) del_list = NULL; } - if (!list_empty(&tmp_add_list)) { + if (!hlist_empty(&tmp_add_list)) { /* Do all the adds now. */ filter_list_len = hw->aq.asq_buf_size / sizeof(struct i40e_aqc_add_macvlan_element_data); @@ -1903,7 +1929,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) goto out; } num_add = 0; - list_for_each_entry(f, &tmp_add_list, list) { + hlist_for_each_entry(f, &tmp_add_list, hlist) { if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state)) { f->state = I40E_FILTER_FAILED; @@ -1974,11 +2000,14 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) /* Now move all of the filters from the temp add list back to * the VSI's list. */ - spin_lock_bh(&vsi->mac_filter_list_lock); - list_for_each_entry_safe(f, ftmp, &tmp_add_list, list) { - list_move_tail(&f->list, &vsi->mac_filter_list); + spin_lock_bh(&vsi->mac_filter_hash_lock); + hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) { + u64 key = i40e_addr_to_hkey(f->macaddr); + + hlist_del(&f->hlist); + hash_add(vsi->mac_filter_hash, &f->hlist, key); } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); kfree(add_list); add_list = NULL; } @@ -1990,12 +2019,12 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) /* See if we have any failed filters. We can't drop out of * promiscuous until these have all been deleted. */ - spin_lock_bh(&vsi->mac_filter_list_lock); - list_for_each_entry(f, &vsi->mac_filter_list, list) { + spin_lock_bh(&vsi->mac_filter_hash_lock); + hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) { if (f->state == I40E_FILTER_FAILED) failed_count++; } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); if (!failed_count) { dev_info(&pf->pdev->dev, "filter logjam cleared on %s, leaving overflow promiscuous mode\n", @@ -2277,10 +2306,12 @@ static void i40e_vlan_rx_register(struct net_device *netdev, u32 features) **/ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) { - struct i40e_mac_filter *f, *ftmp, *add_f, *del_f; + struct i40e_mac_filter *f, *add_f, *del_f; + struct hlist_node *h; + int bkt; /* Locked once because all functions invoked below iterates list*/ - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); if (vsi->netdev) { add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, vid); @@ -2288,12 +2319,12 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add vlan filter %d for %pM\n", vid, vsi->netdev->dev_addr); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); return -ENOMEM; } } - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { if (f->state == I40E_FILTER_REMOVE) continue; add_f = i40e_add_filter(vsi, f->macaddr, vid); @@ -2301,7 +2332,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add vlan filter %d for %pM\n", vid, f->macaddr); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); return -ENOMEM; } } @@ -2321,7 +2352,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add filter 0 for %pM\n", vsi->netdev->dev_addr); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); return -ENOMEM; } } @@ -2329,7 +2360,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) /* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */ if (vid > 0 && !vsi->info.pvid) { - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { if (f->state == I40E_FILTER_REMOVE) continue; del_f = i40e_find_filter(vsi, f->macaddr, @@ -2342,13 +2373,13 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add filter 0 for %pM\n", f->macaddr); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); return -ENOMEM; } } } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); /* schedule our worker thread which will take care of * applying the new filter changes @@ -2367,16 +2398,18 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) { struct net_device *netdev = vsi->netdev; - struct i40e_mac_filter *f, *ftmp, *add_f; + struct i40e_mac_filter *f, *add_f; + struct hlist_node *h; int filter_count = 0; + int bkt; /* Locked once because all functions invoked below iterates list */ - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); if (vsi->netdev) i40e_del_filter(vsi, netdev->dev_addr, vid); - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { if (f->vlan == vid) __i40e_del_filter(vsi, f); } @@ -2386,7 +2419,7 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) * be replaced with -1. This signifies that we should from now * on accept any traffic (with any tag present, or untagged) */ - list_for_each_entry(f, &vsi->mac_filter_list, list) { + hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) { if (vsi->netdev) { if (f->vlan && ether_addr_equal(netdev->dev_addr, f->macaddr)) @@ -2404,13 +2437,13 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add filter %d for %pM\n", I40E_VLAN_ANY, netdev->dev_addr); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); return -ENOMEM; } } if (!filter_count) { - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { if (!f->vlan) __i40e_del_filter(vsi, f); add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY); @@ -2418,13 +2451,13 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add filter %d for %pM\n", I40E_VLAN_ANY, f->macaddr); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); return -ENOMEM; } } } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); /* schedule our worker thread which will take care of * applying the new filter changes @@ -7302,7 +7335,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) pf->rss_table_size : 64; vsi->netdev_registered = false; vsi->work_limit = I40E_DEFAULT_IRQ_WORK; - INIT_LIST_HEAD(&vsi->mac_filter_list); + hash_init(vsi->mac_filter_hash); vsi->irqs_ready = false; ret = i40e_set_num_rings_in_vsi(vsi); @@ -7317,7 +7350,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings); /* Initialize VSI lock */ - spin_lock_init(&vsi->mac_filter_list_lock); + spin_lock_init(&vsi->mac_filter_hash_lock); pf->vsi[vsi_idx] = vsi; ret = vsi_idx; goto unlock_pf; @@ -9102,18 +9135,18 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) if (vsi->type == I40E_VSI_MAIN) { SET_NETDEV_DEV(netdev, &pf->pdev->dev); ether_addr_copy(mac_addr, hw->mac.perm_addr); - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); } else { /* relate the VSI_VMDQ name to the VSI_MAIN name */ snprintf(netdev->name, IFNAMSIZ, "%sv%%d", pf->vsi[pf->lan_vsi]->netdev->name); random_ether_addr(mac_addr); - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); } ether_addr_copy(netdev->dev_addr, mac_addr); @@ -9202,7 +9235,9 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; struct i40e_vsi_context ctxt; - struct i40e_mac_filter *f, *ftmp; + struct i40e_mac_filter *f; + struct hlist_node *h; + int bkt; u8 enabled_tc = 0x1; /* TC0 enabled */ int f_count = 0; @@ -9401,13 +9436,13 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) vsi->active_filters = 0; clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state); - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); /* If macvlan filters already exist, force them to get loaded */ - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { f->state = I40E_FILTER_NEW; f_count++; } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); if (f_count) { vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; @@ -9437,11 +9472,12 @@ err: **/ int i40e_vsi_release(struct i40e_vsi *vsi) { - struct i40e_mac_filter *f, *ftmp; + struct i40e_mac_filter *f; + struct hlist_node *h; struct i40e_veb *veb = NULL; struct i40e_pf *pf; u16 uplink_seid; - int i, n; + int i, n, bkt; pf = vsi->back; @@ -9471,7 +9507,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) i40e_vsi_disable_irq(vsi); } - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); /* clear the sync flag on all filters */ if (vsi->netdev) { @@ -9480,10 +9516,10 @@ int i40e_vsi_release(struct i40e_vsi *vsi) } /* make sure any remaining filters are marked for deletion */ - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) __i40e_del_filter(vsi, f); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); i40e_sync_vsi_filters(vsi); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 37e6afcd01b0..2f1f5e363857 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -686,7 +686,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) if (vf->port_vlan_id) i40e_vsi_add_pvid(vsi, vf->port_vlan_id); - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); if (is_valid_ether_addr(vf->default_lan_addr.addr)) { f = i40e_add_filter(vsi, vf->default_lan_addr.addr, vf->port_vlan_id ? @@ -696,7 +696,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) "Could not add MAC filter %pM for VF %d\n", vf->default_lan_addr.addr, vf->vf_id); } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id), (u32)hena); i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(1, vf->vf_id), @@ -1449,9 +1449,9 @@ static void i40e_vc_reset_vf_msg(struct i40e_vf *vf) static inline int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi) { struct i40e_mac_filter *f; - int num_vlans = 0; + int num_vlans = 0, bkt; - list_for_each_entry(f, &vsi->mac_filter_list, list) { + hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) { if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) num_vlans++; } @@ -1481,6 +1481,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, struct i40e_vsi *vsi; bool alluni = false; int aq_err = 0; + int bkt; vsi = i40e_find_vsi_from_id(pf, info->vsi_id); if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || @@ -1507,7 +1508,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, vf->port_vlan_id, NULL); } else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) { - list_for_each_entry(f, &vsi->mac_filter_list, list) { + hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) { if (f->vlan < 0 || f->vlan > I40E_MAX_VLANID) continue; aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw, @@ -1557,7 +1558,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, vf->port_vlan_id, NULL); } else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) { - list_for_each_entry(f, &vsi->mac_filter_list, list) { + hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) { aq_ret = 0; if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) { aq_ret = @@ -1927,7 +1928,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) /* Lock once, because all function inside for loop accesses VSI's * MAC filter list which needs to be protected using same lock. */ - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); /* add new addresses to the list */ for (i = 0; i < al->num_elements; i++) { @@ -1946,13 +1947,13 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) "Unable to add MAC filter %pM for VF %d\n", al->list[i].addr, vf->vf_id); ret = I40E_ERR_PARAM; - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); goto error_param; } else { vf->num_mac++; } } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); /* program the updated filter list */ ret = i40e_sync_vsi_filters(vsi); @@ -2001,18 +2002,18 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) } vsi = pf->vsi[vf->lan_vsi_idx]; - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); /* delete addresses from the list */ for (i = 0; i < al->num_elements; i++) if (i40e_del_mac_all_vlan(vsi, al->list[i].addr)) { ret = I40E_ERR_INVALID_MAC_ADDR; - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); goto error_param; } else { vf->num_mac--; } - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); /* program the updated filter list */ ret = i40e_sync_vsi_filters(vsi); @@ -2687,6 +2688,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) struct i40e_mac_filter *f; struct i40e_vf *vf; int ret = 0; + int bkt; /* validate the request */ if (vf_id >= pf->num_alloc_vfs) { @@ -2713,9 +2715,9 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) } /* Lock once because below invoked function add/del_filter requires - * mac_filter_list_lock to be held + * mac_filter_hash_lock to be held */ - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); /* delete the temporary mac address */ if (!is_zero_ether_addr(vf->default_lan_addr.addr)) @@ -2725,10 +2727,10 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) /* Delete all the filters for this VSI - we're going to kill it * anyway. */ - list_for_each_entry(f, &vsi->mac_filter_list, list) + hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) i40e_del_filter(vsi, f->macaddr, f->vlan); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id); /* program mac filter */ @@ -2800,9 +2802,9 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, /* duplicate request, so just return success */ goto error_pvid; - spin_lock_bh(&vsi->mac_filter_list_lock); + spin_lock_bh(&vsi->mac_filter_hash_lock); is_vsi_in_vlan = i40e_is_vsi_in_vlan(vsi); - spin_unlock_bh(&vsi->mac_filter_list_lock); + spin_unlock_bh(&vsi->mac_filter_hash_lock); if (le16_to_cpu(vsi->info.pvid) == 0 && is_vsi_in_vlan) { dev_err(&pf->pdev->dev, -- cgit v1.2.3 From 4a2ce27bb5f291c38d8e49ef16899828289e4d3d Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:38 -0700 Subject: i40e: properly cleanup on allocation failure in i40e_sync_vsi_filters Currently, we fail to correctly restore filters on the temporary add list when we fail to allocate memory either for deletion or addition. Replace calls to "goto out;" with calls to a new location that correctly handles memory allocation failures. Note that it is safe for us to call i40e_undo_filter_entries on the tmp_del_list even after we've deleted filters because at this point it will be empty, so we don't need to separate the logic for add and delete failure. Change-Id: Iee107fd219c6e03e2fd9645c2debf8e8384a8521 Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 39 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index ea4dc9f9c416..35f06ba6bc4e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1683,15 +1683,16 @@ static void i40e_set_rx_mode(struct net_device *netdev) } /** - * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries - * @vsi: pointer to vsi struct + * i40e_undo_filter_entries - Undo the changes made to MAC filter entries + * @vsi: Pointer to VSI struct * @from: Pointer to list which contains MAC filter entries - changes to * those entries needs to be undone. * - * MAC filter entries from list were slated to be removed from device. + * MAC filter entries from list were slated to be sent to firmware, either for + * addition or deletion. **/ -static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi, - struct hlist_head *from) +static void i40e_undo_filter_entries(struct i40e_vsi *vsi, + struct hlist_head *from) { struct i40e_mac_filter *f; struct hlist_node *h; @@ -1840,14 +1841,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) list_size = filter_list_len * sizeof(struct i40e_aqc_remove_macvlan_element_data); del_list = kzalloc(list_size, GFP_ATOMIC); - if (!del_list) { - /* Undo VSI's MAC filter entry element updates */ - spin_lock_bh(&vsi->mac_filter_hash_lock); - i40e_undo_del_filter_entries(vsi, &tmp_del_list); - spin_unlock_bh(&vsi->mac_filter_hash_lock); - retval = -ENOMEM; - goto out; - } + if (!del_list) + goto err_no_memory; hlist_for_each_entry_safe(f, h, &tmp_del_list, hlist) { cmd_flags = 0; @@ -1924,10 +1919,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) list_size = filter_list_len * sizeof(struct i40e_aqc_add_macvlan_element_data); add_list = kzalloc(list_size, GFP_ATOMIC); - if (!add_list) { - retval = -ENOMEM; - goto out; - } + if (!add_list) + goto err_no_memory; + num_add = 0; hlist_for_each_entry(f, &tmp_add_list, hlist) { if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, @@ -2152,6 +2146,17 @@ out: clear_bit(__I40E_CONFIG_BUSY, &vsi->state); return retval; + +err_no_memory: + /* Restore elements on the temporary add and delete lists */ + spin_lock_bh(&vsi->mac_filter_hash_lock); + i40e_undo_filter_entries(vsi, &tmp_del_list); + i40e_undo_filter_entries(vsi, &tmp_add_list); + spin_unlock_bh(&vsi->mac_filter_hash_lock); + + vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; + clear_bit(__I40E_CONFIG_BUSY, &vsi->state); + return -ENOMEM; } /** -- cgit v1.2.3 From 84f5ca6cf4ea1d91fa9ee858ff95211127b0166b Mon Sep 17 00:00:00 2001 From: Alan Brady Date: Wed, 5 Oct 2016 09:30:39 -0700 Subject: i40e: fix MAC filters when removing VLANs Currently there exists a bug where adding at least one VLAN and then removing all VLANs leaves the mac filters for the VSI with an incorrect value for 'vid' which indicates the mac filter's VLAN status. The current implementation for handling the removal of VLANs is wrong for a couple reasons. The first is that when i40e_vsi_kill_vlan iterates through the MAC filters, it fails to account for the MAC filter status; i.e. it's not accommodating for filters that are about to be deleted. The second problem is that MAC filters can be deleted in other places (specifically i40e_set_rx_mode). Thus if it occurs that all the VLAN MAC filters get deleted we need to switch out of VLAN mode, but the code path through i40e_vsi_kill_vlan has already been executed and we're now stuck in VLAN mode. This patch fixes the issue by removing the check from i40e_vsi_kill_vlan and puts the check instead in i40e_sync_vsi_filters where we're guaranteed to see all filter deletions and can properly detect when we need to switch out of VLAN mode. Change-ID: Ib38fe6034b356eee9a0e20b8a9eeed5ff2debcd9 Signed-off-by: Alan Brady Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 120 +++++++++++++++++----------- 1 file changed, 72 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 35f06ba6bc4e..6cf908953185 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1774,19 +1774,22 @@ i40e_update_filter_state(int count, **/ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) { - struct i40e_mac_filter *f, *add_head = NULL; struct hlist_head tmp_add_list, tmp_del_list; + struct i40e_mac_filter *f, *add_head = NULL; struct i40e_hw *hw = &vsi->back->hw; + unsigned int vlan_any_filters = 0; + unsigned int non_vlan_filters = 0; + unsigned int vlan_filters = 0; bool promisc_changed = false; char vsi_name[16] = "PF"; int filter_list_len = 0; - u32 changed_flags = 0; i40e_status aq_ret = 0; + u32 changed_flags = 0; struct hlist_node *h; - int retval = 0; struct i40e_pf *pf; int num_add = 0; int num_del = 0; + int retval = 0; int aq_err = 0; u16 cmd_flags; int list_size; @@ -1825,11 +1828,75 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) hash_del(&f->hlist); hlist_add_head(&f->hlist, &tmp_del_list); vsi->active_filters--; + + /* Avoid counting removed filters */ + continue; } if (f->state == I40E_FILTER_NEW) { hash_del(&f->hlist); hlist_add_head(&f->hlist, &tmp_add_list); } + + /* Count the number of each type of filter we have + * remaining, ignoring any filters we're about to + * delete. + */ + if (f->vlan > 0) + vlan_filters++; + else if (!f->vlan) + non_vlan_filters++; + else + vlan_any_filters++; + } + + /* We should never have VLAN=-1 filters at the same time as we + * have either VLAN=0 or VLAN>0 filters, so warn about this + * case here to help catch any issues. + */ + WARN_ON(vlan_any_filters && (vlan_filters + non_vlan_filters)); + + /* If we only have VLAN=0 filters remaining, and don't have + * any other VLAN filters, we need to convert these VLAN=0 + * filters into VLAN=-1 (I40E_VLAN_ANY) so that we operate + * correctly in non-VLAN mode and receive all traffic tagged + * or untagged. + */ + if (non_vlan_filters && !vlan_filters) { + hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, + hlist) { + /* Only replace VLAN=0 filters */ + if (f->vlan) + continue; + + /* Allocate a replacement element */ + add_head = kzalloc(sizeof(*add_head), + GFP_KERNEL); + if (!add_head) + goto err_no_memory_locked; + + /* Copy the filter, with new state and VLAN */ + *add_head = *f; + add_head->state = I40E_FILTER_NEW; + add_head->vlan = I40E_VLAN_ANY; + + /* Move the replacement to the add list */ + INIT_HLIST_NODE(&add_head->hlist); + hlist_add_head(&add_head->hlist, + &tmp_add_list); + + /* Move the original to the delete list */ + f->state = I40E_FILTER_REMOVE; + hash_del(&f->hlist); + hlist_add_head(&f->hlist, &tmp_del_list); + vsi->active_filters--; + } + + /* Also update any filters on the tmp_add list */ + hlist_for_each_entry(f, &tmp_add_list, hlist) { + if (!f->vlan) + f->vlan = I40E_VLAN_ANY; + } + add_head = NULL; } spin_unlock_bh(&vsi->mac_filter_hash_lock); } @@ -2150,6 +2217,7 @@ out: err_no_memory: /* Restore elements on the temporary add and delete lists */ spin_lock_bh(&vsi->mac_filter_hash_lock); +err_no_memory_locked: i40e_undo_filter_entries(vsi, &tmp_del_list); i40e_undo_filter_entries(vsi, &tmp_add_list); spin_unlock_bh(&vsi->mac_filter_hash_lock); @@ -2403,9 +2471,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) { struct net_device *netdev = vsi->netdev; - struct i40e_mac_filter *f, *add_f; + struct i40e_mac_filter *f; struct hlist_node *h; - int filter_count = 0; int bkt; /* Locked once because all functions invoked below iterates list */ @@ -2419,49 +2486,6 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) __i40e_del_filter(vsi, f); } - /* go through all the filters for this VSI and if there is only - * vid == 0 it means there are no other filters, so vid 0 must - * be replaced with -1. This signifies that we should from now - * on accept any traffic (with any tag present, or untagged) - */ - hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) { - if (vsi->netdev) { - if (f->vlan && - ether_addr_equal(netdev->dev_addr, f->macaddr)) - filter_count++; - } - - if (f->vlan) - filter_count++; - } - - if (!filter_count && vsi->netdev) { - i40e_del_filter(vsi, netdev->dev_addr, 0); - f = i40e_add_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY); - if (!f) { - dev_info(&vsi->back->pdev->dev, - "Could not add filter %d for %pM\n", - I40E_VLAN_ANY, netdev->dev_addr); - spin_unlock_bh(&vsi->mac_filter_hash_lock); - return -ENOMEM; - } - } - - if (!filter_count) { - hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { - if (!f->vlan) - __i40e_del_filter(vsi, f); - add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY); - if (!add_f) { - dev_info(&vsi->back->pdev->dev, - "Could not add filter %d for %pM\n", - I40E_VLAN_ANY, f->macaddr); - spin_unlock_bh(&vsi->mac_filter_hash_lock); - return -ENOMEM; - } - } - } - spin_unlock_bh(&vsi->mac_filter_hash_lock); /* schedule our worker thread which will take care of -- cgit v1.2.3 From cbebb85f306f6023ebaa26ca66380571b4b680bf Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:40 -0700 Subject: i40e: avoid looping to check whether we're in VLAN mode We determine that a VSI is in vlan_mode whenever it has any filters with a VLAN other than -1 (I40E_VLAN_ALL). The previous method of doing so was to perform a loop whenever we needed the check. However, we can notice that only place where filters are added (i40e_add_filter) can change the condition from false to true, and the only place we can return to false is in i40e_vsi_sync_filters_subtask. Thus, we can remove the loop and use a boolean directly. Doing this avoids looping over filters repeatedly especially while we're already inside a loop over all the filters. This should reduce the latency of filter operations throughout the driver. Change-ID: Iafde08df588da2a2ea666997d05e11fad8edc338 Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 48 ++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 6545550f5891..60dbb5b90e1a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -517,6 +517,7 @@ struct i40e_vsi { spinlock_t mac_filter_hash_lock; /* Fixed size hash table with 2^8 buckets for MAC filters */ DECLARE_HASHTABLE(mac_filter_hash, 8); + bool has_vlan_filter; /* VSI stats */ struct rtnl_link_stats64 net_stats; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 6cf908953185..b4529b5a6af6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1198,19 +1198,31 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr) **/ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) { - struct i40e_mac_filter *f; - struct hlist_node *h; - int bkt; + /* If we have a PVID, always operate in VLAN mode */ + if (vsi->info.pvid) + return true; - /* Only -1 for all the filters denotes not in vlan mode - * so we have to go through all the list in order to make sure + /* We need to operate in VLAN mode whenever we have any filters with + * a VLAN other than I40E_VLAN_ALL. We could check the table each + * time, incurring search cost repeatedly. However, we can notice two + * things: + * + * 1) the only place where we can gain a VLAN filter is in + * i40e_add_filter. + * + * 2) the only place where filters are actually removed is in + * i40e_vsi_sync_filters_subtask. + * + * Thus, we can simply use a boolean value, has_vlan_filters which we + * will set to true when we add a VLAN filter in i40e_add_filter. Then + * we have to perform the full search after deleting filters in + * i40e_vsi_sync_filters_subtask, but we already have to search + * filters here and can perform the check at the same time. This + * results in avoiding embedding a loop for VLAN mode inside another + * loop over all the filters, and should maintain correctness as noted + * above. */ - hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { - if (f->vlan >= 0 || vsi->info.pvid) - return true; - } - - return false; + return vsi->has_vlan_filter; } /** @@ -1246,6 +1258,12 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, if (!f) return NULL; + /* Update the boolean indicating if we need to function in + * VLAN mode. + */ + if (vlan >= 0) + vsi->has_vlan_filter = true; + ether_addr_copy(f->macaddr, macaddr); f->vlan = vlan; /* If we're in overflow promisc mode, set the state directly @@ -1979,6 +1997,14 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) del_list = NULL; } + /* After finishing notifying firmware of the deleted filters, update + * the cached value of vsi->has_vlan_filter. Note that we are safe to + * use just !!vlan_filters here because if we only have VLAN=0 (that + * is, non_vlan_filters) these will all be converted to VLAN=-1 in the + * logic above already so this value would still be correct. + */ + vsi->has_vlan_filter = !!vlan_filters; + if (!hlist_empty(&tmp_add_list)) { /* Do all the adds now. */ filter_list_len = hw->aq.asq_buf_size / -- cgit v1.2.3 From 0093631966aad046ddf21e157a43765c295e16a3 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:41 -0700 Subject: i40e: remove duplicate add/delete adminq command code for filters We duplicate some code around adding and deleting filters using the adminq interface. This is prone to errors in case there are bugs. Use functions which extract the logic to their own portion so that we don't duplicate it twice in code. Change-ID: I60d68aeb887976787dec00b23ab386a106e61465 Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 156 +++++++++++++++------------- 1 file changed, 84 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b4529b5a6af6..5fe54e5c8efc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1782,6 +1782,80 @@ i40e_update_filter_state(int count, return retval; } +/** + * i40e_aqc_del_filters - Request firmware to delete a set of filters + * @vsi: ptr to the VSI + * @vsi_name: name to display in messages + * @list: the list of filters to send to firmware + * @num_del: the number of filters to delete + * @retval: Set to -EIO on failure to delete + * + * Send a request to firmware via AdminQ to delete a set of filters. Uses + * *retval instead of a return value so that success does not force ret_val to + * be set to 0. This ensures that a sequence of calls to this function + * preserve the previous value of *retval on successful delete. + */ +static +void i40e_aqc_del_filters(struct i40e_vsi *vsi, const char *vsi_name, + struct i40e_aqc_remove_macvlan_element_data *list, + int num_del, int *retval) +{ + struct i40e_hw *hw = &vsi->back->hw; + i40e_status aq_ret; + int aq_err; + + aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, list, num_del, NULL); + aq_err = hw->aq.asq_last_status; + + /* Explicitly ignore and do not report when firmware returns ENOENT */ + if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) { + *retval = -EIO; + dev_info(&vsi->back->pdev->dev, + "ignoring delete macvlan error on %s, err %s, aq_err %s\n", + vsi_name, i40e_stat_str(hw, aq_ret), + i40e_aq_str(hw, aq_err)); + } +} + +/** + * i40e_aqc_add_filters - Request firmware to add a set of filters + * @vsi: ptr to the VSI + * @vsi_name: name to display in messages + * @list: the list of filters to send to firmware + * @add_head: Position in the add hlist + * @num_add: the number of filters to add + * @promisc_change: set to true on exit if promiscuous mode was forced on + * + * Send a request to firmware via AdminQ to add a chunk of filters. Will set + * promisc_changed to true if the firmware has run out of space for more + * filters. + */ +static +void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name, + struct i40e_aqc_add_macvlan_element_data *list, + struct i40e_mac_filter *add_head, + int num_add, bool *promisc_changed) +{ + struct i40e_hw *hw = &vsi->back->hw; + i40e_status aq_ret; + int aq_err, fcnt; + + aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, list, num_add, NULL); + aq_err = hw->aq.asq_last_status; + fcnt = i40e_update_filter_state(num_add, list, add_head, aq_ret); + vsi->active_filters += fcnt; + + if (fcnt != num_add) { + *promisc_changed = true; + set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state); + vsi->promisc_threshold = (vsi->active_filters * 3) / 4; + dev_warn(&vsi->back->pdev->dev, + "Error %s adding RX filters on %s, promiscuous mode forced on\n", + i40e_aq_str(hw, aq_err), + vsi_name); + } +} + /** * i40e_sync_vsi_filters - Update the VSI filter list to the HW * @vsi: ptr to the VSI @@ -1808,10 +1882,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) int num_add = 0; int num_del = 0; int retval = 0; - int aq_err = 0; u16 cmd_flags; int list_size; - int fcnt; int bkt; /* empty array typed pointers, kcalloc later */ @@ -1948,24 +2020,10 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) /* flush a full buffer */ if (num_del == filter_list_len) { - aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, - del_list, - num_del, NULL); - aq_err = hw->aq.asq_last_status; - num_del = 0; + i40e_aqc_del_filters(vsi, vsi_name, del_list, + num_del, &retval); memset(del_list, 0, list_size); - - /* Explicitly ignore and do not report when - * firmware returns ENOENT. - */ - if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) { - retval = -EIO; - dev_info(&pf->pdev->dev, - "ignoring delete macvlan error on %s, err %s, aq_err %s\n", - vsi_name, - i40e_stat_str(hw, aq_ret), - i40e_aq_str(hw, aq_err)); - } + num_del = 0; } /* Release memory for MAC filter entries which were * synced up with HW. @@ -1975,22 +2033,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) } if (num_del) { - aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, del_list, - num_del, NULL); - aq_err = hw->aq.asq_last_status; - num_del = 0; - - /* Explicitly ignore and do not report when firmware - * returns ENOENT. - */ - if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) { - retval = -EIO; - dev_info(&pf->pdev->dev, - "ignoring delete macvlan error on %s, err %s aq_err %s\n", - vsi_name, - i40e_stat_str(hw, aq_ret), - i40e_aq_str(hw, aq_err)); - } + i40e_aqc_del_filters(vsi, vsi_name, del_list, + num_del, &retval); } kfree(del_list); @@ -2041,48 +2085,16 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) /* flush a full buffer */ if (num_add == filter_list_len) { - aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, - add_list, num_add, - NULL); - aq_err = hw->aq.asq_last_status; - fcnt = i40e_update_filter_state(num_add, - add_list, - add_head, - aq_ret); - vsi->active_filters += fcnt; - - if (fcnt != num_add) { - promisc_changed = true; - set_bit(__I40E_FILTER_OVERFLOW_PROMISC, - &vsi->state); - vsi->promisc_threshold = - (vsi->active_filters * 3) / 4; - dev_warn(&pf->pdev->dev, - "Error %s adding RX filters on %s, promiscuous mode forced on\n", - i40e_aq_str(hw, aq_err), - vsi_name); - } + i40e_aqc_add_filters(vsi, vsi_name, add_list, + add_head, num_add, + &promisc_changed); memset(add_list, 0, list_size); num_add = 0; } } if (num_add) { - aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, - add_list, num_add, NULL); - aq_err = hw->aq.asq_last_status; - fcnt = i40e_update_filter_state(num_add, add_list, - add_head, aq_ret); - vsi->active_filters += fcnt; - if (fcnt != num_add) { - promisc_changed = true; - set_bit(__I40E_FILTER_OVERFLOW_PROMISC, - &vsi->state); - vsi->promisc_threshold = - (vsi->active_filters * 3) / 4; - dev_warn(&pf->pdev->dev, - "Error %s adding RX filters on %s, promiscuous mode forced on\n", - i40e_aq_str(hw, aq_err), vsi_name); - } + i40e_aqc_add_filters(vsi, vsi_name, add_list, add_head, + num_add, &promisc_changed); } /* Now move all of the filters from the temp add list back to * the VSI's list. -- cgit v1.2.3 From 144ed1763003c6a88a4b788cc5da1d8a1ddf061f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:42 -0700 Subject: i40e: correct check for reading TSYNINDX from the receive descriptor When hardware has taken a timestamp for a received packet, it indicates which RXTIME register the timestamp was placed in by some bits in the receive descriptor. It uses 3 bits, one to indicate if the descriptor index is valid (ie: there was a timestamp) and 2 bits to indicate which of the 4 registers to read. However, the driver currently does not check the TSYNVALID bit and only checks the index. It assumes a zero index means no timestamp, and a non zero index means a timestamp occurred. While this appears to be true, it prevents ever reading a timestamp in RXTIME[0], and causes the first timestamp the device captures to be ignored. Fix this by using the TSYNVALID bit correctly as the true indicator of whether the packet has an associated timestamp. Also rename the variable rsyn to tsyn as this is more descriptive and matches the register names. Change-ID: I4437e8f3a3df2c2ddb458b0fb61420f3dafc4c12 Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index daade4fe80d6..c9eb6b852d66 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1410,11 +1410,12 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring, u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; - u32 rsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >> + u32 tsynvalid = rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK; + u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >> I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT; - if (unlikely(rsyn)) { - i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, rsyn); + if (unlikely(tsynvalid)) { + i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn); rx_ring->last_rx_timestamp = jiffies; } -- cgit v1.2.3 From 195512629c956286265dcfeeea2028c42ee0c483 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:43 -0700 Subject: i40e: use a mutex instead of spinlock in PTP user entry points We need a locking mechanism to protect the hardware SYSTIME register which is split over 2 values, and has internal hardware latching. We can't allow multiple accesses at the same time. However.... The spinlock_t is overkill here, especially use of spin_lock_irqsave, since every PTP access will halt hardirqs. Notice that the only places which need the SYSTIME value are user context and are capable of sleeping. Thus, it is safe to use a mutex here instead of the spinlock. Change-ID: I971761a89b58c6aad953590162e85a327fbba232 Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 +- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 60dbb5b90e1a..21f2bb321cb4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -430,7 +430,7 @@ struct i40e_pf { struct sk_buff *ptp_tx_skb; struct hwtstamp_config tstamp_config; unsigned long last_rx_ptp_check; - spinlock_t tmreg_lock; /* Used to protect the device time registers. */ + struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */ u64 ptp_base_adj; u32 tx_hwtstamp_timeouts; u32 rx_hwtstamp_cleared; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index f1feceab758a..177b7fb606af 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -159,16 +159,15 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps); struct timespec64 now, then; - unsigned long flags; then = ns_to_timespec64(delta); - spin_lock_irqsave(&pf->tmreg_lock, flags); + mutex_lock(&pf->tmreg_lock); i40e_ptp_read(pf, &now); now = timespec64_add(now, then); i40e_ptp_write(pf, (const struct timespec64 *)&now); - spin_unlock_irqrestore(&pf->tmreg_lock, flags); + mutex_unlock(&pf->tmreg_lock); return 0; } @@ -184,11 +183,10 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) { struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps); - unsigned long flags; - spin_lock_irqsave(&pf->tmreg_lock, flags); + mutex_lock(&pf->tmreg_lock); i40e_ptp_read(pf, ts); - spin_unlock_irqrestore(&pf->tmreg_lock, flags); + mutex_unlock(&pf->tmreg_lock); return 0; } @@ -205,11 +203,10 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) { struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps); - unsigned long flags; - spin_lock_irqsave(&pf->tmreg_lock, flags); + mutex_lock(&pf->tmreg_lock); i40e_ptp_write(pf, ts); - spin_unlock_irqrestore(&pf->tmreg_lock, flags); + mutex_unlock(&pf->tmreg_lock); return 0; } @@ -658,10 +655,7 @@ void i40e_ptp_init(struct i40e_pf *pf) return; } - /* we have to initialize the lock first, since we can't control - * when the user will enter the PHC device entry points - */ - spin_lock_init(&pf->tmreg_lock); + mutex_init(&pf->tmreg_lock); /* ensure we have a clock device */ err = i40e_ptp_create_clock(pf); -- cgit v1.2.3 From 124905012db8bdeebf5a7d1ddc841eaadda84a75 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:44 -0700 Subject: i40e: replace PTP Rx timestamp hang logic The current Rx timestamp hang logic is not very robust because it does not notice a register is hung until all four timestamps have been latched and we wait a full 5 seconds. Replace this logic with a newer Rx hang detection based on storing the jiffies when we first notice a receive timestamp event. We store each register's time separately, along with a flag indicating if it is currently latched. Upon first transitioning to latch, we will update the latch_events[i] jiffies value. This indicates the time we first noticed this event. The watchdog routine will simply check that the either the flag has been cleared, or we have passed at least one second. In this case, it is able to clear the Rx timestamp register under the assumption that it was for a dropped frame. The benefit if this strategy is that we should be able to detect and clear out stalled RXTIME_H registers before we exhaust the supply of 4, and avoid complete stall of Rx timestamp events. Change-ID: Id55458c0cd7a5dd0c951ff2b8ac0b2509364131f Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 4 +- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 117 +++++++++++++++++++--------- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 2 - 4 files changed, 83 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 21f2bb321cb4..9121e46c2ad9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -429,11 +429,13 @@ struct i40e_pf { struct ptp_clock_info ptp_caps; struct sk_buff *ptp_tx_skb; struct hwtstamp_config tstamp_config; - unsigned long last_rx_ptp_check; struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */ u64 ptp_base_adj; u32 tx_hwtstamp_timeouts; u32 rx_hwtstamp_cleared; + u32 latch_event_flags; + spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */ + unsigned long latch_events[4]; bool ptp_tx; bool ptp_rx; u16 rss_table_size; /* HW RSS table size */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 177b7fb606af..5e2272c9e717 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -226,6 +226,47 @@ static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp, return -EOPNOTSUPP; } +/** + * i40e_ptp_update_latch_events - Read I40E_PRTTSYN_STAT_1 and latch events + * @pf: the PF data structure + * + * This function reads I40E_PRTTSYN_STAT_1 and updates the corresponding timers + * for noticed latch events. This allows the driver to keep track of the first + * time a latch event was noticed which will be used to help clear out Rx + * timestamps for packets that got dropped or lost. + * + * This function will return the current value of I40E_PRTTSYN_STAT_1 and is + * expected to be called only while under the ptp_rx_lock. + **/ +static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf) +{ + struct i40e_hw *hw = &pf->hw; + u32 prttsyn_stat, new_latch_events; + int i; + + prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1); + new_latch_events = prttsyn_stat & ~pf->latch_event_flags; + + /* Update the jiffies time for any newly latched timestamp. This + * ensures that we store the time that we first discovered a timestamp + * was latched by the hardware. The service task will later determine + * if we should free the latch and drop that timestamp should too much + * time pass. This flow ensures that we only update jiffies for new + * events latched since the last time we checked, and not all events + * currently latched, so that the service task accounting remains + * accurate. + */ + for (i = 0; i < 4; i++) { + if (new_latch_events & BIT(i)) + pf->latch_events[i] = jiffies; + } + + /* Finally, we store the current status of the Rx timestamp latches */ + pf->latch_event_flags = prttsyn_stat; + + return prttsyn_stat; +} + /** * i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung * @vsi: The VSI with the rings relevant to 1588 @@ -239,10 +280,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi) { struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; - struct i40e_ring *rx_ring; - unsigned long rx_event; - u32 prttsyn_stat; - int n; + int i; /* Since we cannot turn off the Rx timestamp logic if the device is * configured for Tx timestamping, we check if Rx timestamping is @@ -252,42 +290,30 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi) if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_rx) return; - prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1); + spin_lock_bh(&pf->ptp_rx_lock); - /* Unless all four receive timestamp registers are latched, we are not - * concerned about a possible PTP Rx hang, so just update the timeout - * counter and exit. - */ - if (!(prttsyn_stat & ((I40E_PRTTSYN_STAT_1_RXT0_MASK << - I40E_PRTTSYN_STAT_1_RXT0_SHIFT) | - (I40E_PRTTSYN_STAT_1_RXT1_MASK << - I40E_PRTTSYN_STAT_1_RXT1_SHIFT) | - (I40E_PRTTSYN_STAT_1_RXT2_MASK << - I40E_PRTTSYN_STAT_1_RXT2_SHIFT) | - (I40E_PRTTSYN_STAT_1_RXT3_MASK << - I40E_PRTTSYN_STAT_1_RXT3_SHIFT)))) { - pf->last_rx_ptp_check = jiffies; - return; - } + /* Update current latch times for Rx events */ + i40e_ptp_get_rx_events(pf); - /* Determine the most recent watchdog or rx_timestamp event. */ - rx_event = pf->last_rx_ptp_check; - for (n = 0; n < vsi->num_queue_pairs; n++) { - rx_ring = vsi->rx_rings[n]; - if (time_after(rx_ring->last_rx_timestamp, rx_event)) - rx_event = rx_ring->last_rx_timestamp; + /* Check all the currently latched Rx events and see whether they have + * been latched for over a second. It is assumed that any timestamp + * should have been cleared within this time, or else it was captured + * for a dropped frame that the driver never received. Thus, we will + * clear any timestamp that has been latched for over 1 second. + */ + for (i = 0; i < 4; i++) { + if ((pf->latch_event_flags & BIT(i)) && + time_is_before_jiffies(pf->latch_events[i] + HZ)) { + rd32(hw, I40E_PRTTSYN_RXTIME_H(i)); + pf->latch_event_flags &= ~BIT(i); + pf->rx_hwtstamp_cleared++; + dev_warn(&pf->pdev->dev, + "Clearing a missed Rx timestamp event for RXTIME[%d]\n", + i); + } } - /* Only need to read the high RXSTMP register to clear the lock */ - if (time_is_before_jiffies(rx_event + 5 * HZ)) { - rd32(hw, I40E_PRTTSYN_RXTIME_H(0)); - rd32(hw, I40E_PRTTSYN_RXTIME_H(1)); - rd32(hw, I40E_PRTTSYN_RXTIME_H(2)); - rd32(hw, I40E_PRTTSYN_RXTIME_H(3)); - pf->last_rx_ptp_check = jiffies; - pf->rx_hwtstamp_cleared++; - WARN_ONCE(1, "Detected Rx timestamp register hang\n"); - } + spin_unlock_bh(&pf->ptp_rx_lock); } /** @@ -350,14 +376,25 @@ void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index) hw = &pf->hw; - prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1); + spin_lock_bh(&pf->ptp_rx_lock); + + /* Get current Rx events and update latch times */ + prttsyn_stat = i40e_ptp_get_rx_events(pf); - if (!(prttsyn_stat & BIT(index))) + /* TODO: Should we warn about missing Rx timestamp event? */ + if (!(prttsyn_stat & BIT(index))) { + spin_unlock_bh(&pf->ptp_rx_lock); return; + } + + /* Clear the latched event since we're about to read its register */ + pf->latch_event_flags &= ~BIT(index); lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index)); hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index)); + spin_unlock_bh(&pf->ptp_rx_lock); + ns = (((u64)hi) << 32) | lo; i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns); @@ -511,12 +548,15 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, } /* Clear out all 1588-related registers to clear and unlatch them. */ + spin_lock_bh(&pf->ptp_rx_lock); rd32(hw, I40E_PRTTSYN_STAT_0); rd32(hw, I40E_PRTTSYN_TXTIME_H); rd32(hw, I40E_PRTTSYN_RXTIME_H(0)); rd32(hw, I40E_PRTTSYN_RXTIME_H(1)); rd32(hw, I40E_PRTTSYN_RXTIME_H(2)); rd32(hw, I40E_PRTTSYN_RXTIME_H(3)); + pf->latch_event_flags = 0; + spin_unlock_bh(&pf->ptp_rx_lock); /* Enable/disable the Tx timestamp interrupt based on user input. */ regval = rd32(hw, I40E_PRTTSYN_CTL0); @@ -656,6 +696,7 @@ void i40e_ptp_init(struct i40e_pf *pf) } mutex_init(&pf->tmreg_lock); + spin_lock_init(&pf->ptp_rx_lock); /* ensure we have a clock device */ err = i40e_ptp_create_clock(pf); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index c9eb6b852d66..783ac4ed9c6d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1414,10 +1414,8 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring, u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >> I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT; - if (unlikely(tsynvalid)) { + if (unlikely(tsynvalid)) i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn); - rx_ring->last_rx_timestamp = jiffies; - } i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 508840585645..42f04d69c4d1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -307,8 +307,6 @@ struct i40e_ring { u8 atr_sample_rate; u8 atr_count; - unsigned long last_rx_timestamp; - bool ring_active; /* is ring online or not */ bool arm_wb; /* do something to arm write back */ u8 packet_stride; -- cgit v1.2.3 From 7d3f04af69bed2db87d6a72d100e182f773e54b7 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 5 Oct 2016 09:30:45 -0700 Subject: i40evf: avoid an extra msleep while Remove the second call to msleep outside the loop, and move the msleep within the loop as the first step. This guarantees that a single loop will wait the minimum time first, and then after the reset finishes we no longer need an extra msleep. Change-ID: Ib2086f0a142402b614f67846bc091754203a0b9a Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index bcb1cafdf28a..db36744c6691 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1746,15 +1746,17 @@ static void i40evf_reset_task(struct work_struct *work) /* wait until the reset is complete and the PF is responding to us */ for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) { + /* sleep first to make sure a minimum wait time is met */ + msleep(I40EVF_RESET_WAIT_MS); + reg_val = rd32(hw, I40E_VFGEN_RSTAT) & I40E_VFGEN_RSTAT_VFR_STATE_MASK; if (reg_val == I40E_VFR_VFACTIVE) break; - msleep(I40EVF_RESET_WAIT_MS); } + pci_set_master(adapter->pdev); - /* extra wait to make sure minimum wait is met */ - msleep(I40EVF_RESET_WAIT_MS); + if (i == I40EVF_RESET_WAIT_COUNT) { struct i40evf_mac_filter *ftmp; struct i40evf_vlan_filter *fv, *fvtmp; -- cgit v1.2.3 From 4b8164467b854fbeb7ecbb14cf53b6be9113ef03 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 11 Oct 2016 15:26:53 -0700 Subject: i40e: Add common function for finding VSI by type This patch adds a common method for finding a VSI by type. The main motivation for doing this is that the Flow Director path actually had two ways of handling this, one stopped on first match and one did not. This patch makes it so that all callers of this function will get the same approach for finding a VSI. Change-ID: Ibf25de8acd8466582520694424aa87da66965fbd Signed-off-by: Alexander Duyck Signed-off-by: Bimmy Pujari Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 19 +++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 12 +----------- drivers/net/ethernet/intel/i40e/i40e_main.c | 21 ++++++--------------- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 5 +---- 4 files changed, 27 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 9121e46c2ad9..bb02280bc4c1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -723,6 +723,25 @@ int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size); void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut, u16 rss_table_size, u16 rss_size); struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id); +/** + * i40e_find_vsi_by_type - Find and return Flow Director VSI + * @pf: PF to search for VSI + * @type: Value indicating type of VSI we are looking for + **/ +static inline struct i40e_vsi * +i40e_find_vsi_by_type(struct i40e_pf *pf, u16 type) +{ + int i; + + for (i = 0; i < pf->num_alloc_vsi; i++) { + struct i40e_vsi *vsi = pf->vsi[i]; + + if (vsi && vsi->type == type) + return vsi; + } + + return NULL; +} void i40e_update_stats(struct i40e_vsi *vsi); void i40e_update_eth_stats(struct i40e_vsi *vsi); struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index fb4fb524eab2..962a9bb8a08e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1768,17 +1768,7 @@ static inline bool i40e_active_vfs(struct i40e_pf *pf) static inline bool i40e_active_vmdqs(struct i40e_pf *pf) { - struct i40e_vsi **vsi = pf->vsi; - int i; - - for (i = 0; i < pf->num_alloc_vsi; i++) { - if (!vsi[i]) - continue; - if (vsi[i]->type == I40E_VSI_VMDQ2) - return true; - } - - return false; + return !!i40e_find_vsi_by_type(pf, I40E_VSI_VMDQ2); } static void i40e_diag_test(struct net_device *netdev, diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5fe54e5c8efc..9ec977a425de 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6718,7 +6718,6 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi); static void i40e_fdir_sb_setup(struct i40e_pf *pf) { struct i40e_vsi *vsi; - int i; /* quick workaround for an NVM issue that leaves a critical register * uninitialized @@ -6729,6 +6728,7 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf) 0xeacb7d61, 0xaa4f05b6, 0x9c5c89ed, 0xfc425ddb, 0xa4654832, 0xfc7461d4, 0x8f827619, 0xf5c63c21, 0x95b3a76d}; + int i; for (i = 0; i <= I40E_GLQF_HKEY_MAX_INDEX; i++) wr32(&pf->hw, I40E_GLQF_HKEY(i), hkey[i]); @@ -6738,13 +6738,7 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf) return; /* find existing VSI and see if it needs configuring */ - vsi = NULL; - for (i = 0; i < pf->num_alloc_vsi; i++) { - if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { - vsi = pf->vsi[i]; - break; - } - } + vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR); /* create a new VSI if none exists */ if (!vsi) { @@ -6766,15 +6760,12 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf) **/ static void i40e_fdir_teardown(struct i40e_pf *pf) { - int i; + struct i40e_vsi *vsi; i40e_fdir_filter_exit(pf); - for (i = 0; i < pf->num_alloc_vsi; i++) { - if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { - i40e_vsi_release(pf->vsi[i]); - break; - } - } + vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR); + if (vsi) + i40e_vsi_release(vsi); } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 783ac4ed9c6d..75b8f5b554e1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -125,10 +125,7 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u16 i; /* find existing FDIR VSI */ - vsi = NULL; - for (i = 0; i < pf->num_alloc_vsi; i++) - if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) - vsi = pf->vsi[i]; + vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR); if (!vsi) return -ENOENT; -- cgit v1.2.3 From 1dc8b538795fcf92161cc056ceebb852cf375b17 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 11 Oct 2016 15:26:54 -0700 Subject: i40e: Reorder logic for coalescing RS bits This patch reorders the logic at the end of i40e_tx_map to address the fact that the logic was rather convoluted and much larger than it needed to be. In order to try and coalesce the code paths I have updated some of the comments and repurposed some of the variables in order to reduce unnecessary overhead. This patch does the following: 1. Quit tracking skb->xmit_more with a flag, just max out packet_stride 2. Drop tail_bump and do_rs and instead just use desc_count and td_cmd 3. Pull comments from ixgbe that make need for wmb() more explicit. Change-ID: Ic7da85ec75043c634e87fef958109789bcc6317c Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 105 +++++++++++++------------- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 - drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 105 +++++++++++++------------- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 - 4 files changed, 108 insertions(+), 104 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 75b8f5b554e1..5544b509832f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -616,7 +616,7 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw) return 0; } -#define WB_STRIDE 0x3 +#define WB_STRIDE 4 /** * i40e_clean_tx_irq - Reclaim resources after transmit completes @@ -732,7 +732,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, unsigned int j = i40e_get_tx_pending(tx_ring, false); if (budget && - ((j / (WB_STRIDE + 1)) == 0) && (j != 0) && + ((j / WB_STRIDE) == 0) && (j > 0) && !test_bit(__I40E_DOWN, &vsi->state) && (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) tx_ring->arm_wb = true; @@ -2700,9 +2700,7 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, u32 td_tag = 0; dma_addr_t dma; u16 gso_segs; - u16 desc_count = 0; - bool tail_bump = true; - bool do_rs = false; + u16 desc_count = 1; if (tx_flags & I40E_TX_FLAGS_HW_VLAN) { td_cmd |= I40E_TX_DESC_CMD_IL2TAG1; @@ -2785,8 +2783,7 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_bi = &tx_ring->tx_bi[i]; } - /* set next_to_watch value indicating a packet is present */ - first->next_to_watch = tx_desc; + netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); i++; if (i == tx_ring->count) @@ -2794,66 +2791,72 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_ring->next_to_use = i; - netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); i40e_maybe_stop_tx(tx_ring, DESC_NEEDED); + /* write last descriptor with EOP bit */ + td_cmd |= I40E_TX_DESC_CMD_EOP; + + /* We can OR these values together as they both are checked against + * 4 below and at this point desc_count will be used as a boolean value + * after this if/else block. + */ + desc_count |= ++tx_ring->packet_stride; + /* Algorithm to optimize tail and RS bit setting: - * if xmit_more is supported - * if xmit_more is true - * do not update tail and do not mark RS bit. - * if xmit_more is false and last xmit_more was false - * if every packet spanned less than 4 desc - * then set RS bit on 4th packet and update tail - * on every packet - * else - * update tail and set RS bit on every packet. - * if xmit_more is false and last_xmit_more was true - * update tail and set RS bit. + * if queue is stopped + * mark RS bit + * reset packet counter + * else if xmit_more is supported and is true + * advance packet counter to 4 + * reset desc_count to 0 * - * Optimization: wmb to be issued only in case of tail update. - * Also optimize the Descriptor WB path for RS bit with the same - * algorithm. + * if desc_count >= 4 + * mark RS bit + * reset packet counter + * if desc_count > 0 + * update tail * - * Note: If there are less than 4 packets + * Note: If there are less than 4 descriptors * pending and interrupts were disabled the service task will * trigger a force WB. */ - if (skb->xmit_more && - !netif_xmit_stopped(txring_txq(tx_ring))) { - tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; - tail_bump = false; - } else if (!skb->xmit_more && - !netif_xmit_stopped(txring_txq(tx_ring)) && - (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) && - (tx_ring->packet_stride < WB_STRIDE) && - (desc_count < WB_STRIDE)) { - tx_ring->packet_stride++; - } else { + if (netif_xmit_stopped(txring_txq(tx_ring))) { + goto do_rs; + } else if (skb->xmit_more) { + /* set stride to arm on next packet and reset desc_count */ + tx_ring->packet_stride = WB_STRIDE; + desc_count = 0; + } else if (desc_count >= WB_STRIDE) { +do_rs: + /* write last descriptor with RS bit set */ + td_cmd |= I40E_TX_DESC_CMD_RS; tx_ring->packet_stride = 0; - tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; - do_rs = true; } - if (do_rs) - tx_ring->packet_stride = 0; tx_desc->cmd_type_offset_bsz = - build_ctob(td_cmd, td_offset, size, td_tag) | - cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD : - I40E_TX_DESC_CMD_EOP) << - I40E_TXD_QW1_CMD_SHIFT); + build_ctob(td_cmd, td_offset, size, td_tag); + + /* Force memory writes to complete before letting h/w know there + * are new descriptors to fetch. + * + * We also use this memory barrier to make certain all of the + * status bits have been updated before next_to_watch is written. + */ + wmb(); + + /* set next_to_watch value indicating a packet is present */ + first->next_to_watch = tx_desc; /* notify HW of packet */ - if (!tail_bump) { - prefetchw(tx_desc + 1); - } else { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); + if (desc_count) { writel(i, tx_ring->tail); + + /* we need this if more than one processor can write to our tail + * at a time, it synchronizes IO on IA64/Altix systems + */ + mmiowb(); } + return; dma_error: diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 42f04d69c4d1..de8550f4e3a4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -313,7 +313,6 @@ struct i40e_ring { u16 flags; #define I40E_TXR_FLAGS_WB_ON_ITR BIT(0) -#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2) /* stats structs */ struct i40e_queue_stats stats; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index e2d362238fd7..c4b174afd253 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -150,7 +150,7 @@ u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw) return 0; } -#define WB_STRIDE 0x3 +#define WB_STRIDE 4 /** * i40e_clean_tx_irq - Reclaim resources after transmit completes @@ -266,7 +266,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, unsigned int j = i40evf_get_tx_pending(tx_ring, false); if (budget && - ((j / (WB_STRIDE + 1)) == 0) && (j > 0) && + ((j / WB_STRIDE) == 0) && (j > 0) && !test_bit(__I40E_DOWN, &vsi->state) && (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) tx_ring->arm_wb = true; @@ -1950,9 +1950,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, u32 td_tag = 0; dma_addr_t dma; u16 gso_segs; - u16 desc_count = 0; - bool tail_bump = true; - bool do_rs = false; + u16 desc_count = 1; if (tx_flags & I40E_TX_FLAGS_HW_VLAN) { td_cmd |= I40E_TX_DESC_CMD_IL2TAG1; @@ -2035,8 +2033,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_bi = &tx_ring->tx_bi[i]; } - /* set next_to_watch value indicating a packet is present */ - first->next_to_watch = tx_desc; + netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); i++; if (i == tx_ring->count) @@ -2044,66 +2041,72 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_ring->next_to_use = i; - netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); i40e_maybe_stop_tx(tx_ring, DESC_NEEDED); + /* write last descriptor with EOP bit */ + td_cmd |= I40E_TX_DESC_CMD_EOP; + + /* We can OR these values together as they both are checked against + * 4 below and at this point desc_count will be used as a boolean value + * after this if/else block. + */ + desc_count |= ++tx_ring->packet_stride; + /* Algorithm to optimize tail and RS bit setting: - * if xmit_more is supported - * if xmit_more is true - * do not update tail and do not mark RS bit. - * if xmit_more is false and last xmit_more was false - * if every packet spanned less than 4 desc - * then set RS bit on 4th packet and update tail - * on every packet - * else - * update tail and set RS bit on every packet. - * if xmit_more is false and last_xmit_more was true - * update tail and set RS bit. + * if queue is stopped + * mark RS bit + * reset packet counter + * else if xmit_more is supported and is true + * advance packet counter to 4 + * reset desc_count to 0 * - * Optimization: wmb to be issued only in case of tail update. - * Also optimize the Descriptor WB path for RS bit with the same - * algorithm. + * if desc_count >= 4 + * mark RS bit + * reset packet counter + * if desc_count > 0 + * update tail * - * Note: If there are less than 4 packets + * Note: If there are less than 4 descriptors * pending and interrupts were disabled the service task will * trigger a force WB. */ - if (skb->xmit_more && - !netif_xmit_stopped(txring_txq(tx_ring))) { - tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; - tail_bump = false; - } else if (!skb->xmit_more && - !netif_xmit_stopped(txring_txq(tx_ring)) && - (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) && - (tx_ring->packet_stride < WB_STRIDE) && - (desc_count < WB_STRIDE)) { - tx_ring->packet_stride++; - } else { + if (netif_xmit_stopped(txring_txq(tx_ring))) { + goto do_rs; + } else if (skb->xmit_more) { + /* set stride to arm on next packet and reset desc_count */ + tx_ring->packet_stride = WB_STRIDE; + desc_count = 0; + } else if (desc_count >= WB_STRIDE) { +do_rs: + /* write last descriptor with RS bit set */ + td_cmd |= I40E_TX_DESC_CMD_RS; tx_ring->packet_stride = 0; - tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; - do_rs = true; } - if (do_rs) - tx_ring->packet_stride = 0; tx_desc->cmd_type_offset_bsz = - build_ctob(td_cmd, td_offset, size, td_tag) | - cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD : - I40E_TX_DESC_CMD_EOP) << - I40E_TXD_QW1_CMD_SHIFT); + build_ctob(td_cmd, td_offset, size, td_tag); + + /* Force memory writes to complete before letting h/w know there + * are new descriptors to fetch. + * + * We also use this memory barrier to make certain all of the + * status bits have been updated before next_to_watch is written. + */ + wmb(); + + /* set next_to_watch value indicating a packet is present */ + first->next_to_watch = tx_desc; /* notify HW of packet */ - if (!tail_bump) { - prefetchw(tx_desc + 1); - } else { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); + if (desc_count) { writel(i, tx_ring->tail); + + /* we need this if more than one processor can write to our tail + * at a time, it synchronizes IO on IA64/Altix systems + */ + mmiowb(); } + return; dma_error: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index abcdecabbc56..a586e19cfd1d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -309,7 +309,6 @@ struct i40e_ring { bool ring_active; /* is ring online or not */ bool arm_wb; /* do something to arm write back */ u8 packet_stride; -#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2) u16 flags; #define I40E_TXR_FLAGS_WB_ON_ITR BIT(0) -- cgit v1.2.3 From 13fd3f9cc3def8b276c7913ae4acbfa2653cb198 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Tue, 11 Oct 2016 15:26:55 -0700 Subject: i40e: clear mac filter count on reset When a VF is reset, it gets a new VSI, so all of its MAC filters go away. Correctly set the number of filters to 0 when freeing VF resources. This corrects a problem with failure to add filters when the VF driver is reloaded. Change-ID: I2acbecf734287b67473bb225293e14b5096acbef Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 2f1f5e363857..69e184b3f72f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -811,6 +811,7 @@ static void i40e_free_vf_res(struct i40e_vf *vf) i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]); vf->lan_vsi_idx = 0; vf->lan_vsi_id = 0; + vf->num_mac = 0; } msix_vf = pf->hw.func_caps.num_msix_vectors_vf; -- cgit v1.2.3 From 999b315d39906341fadcb65ee6aba7f5cf38b830 Mon Sep 17 00:00:00 2001 From: Michal Kosiarz Date: Tue, 11 Oct 2016 15:26:56 -0700 Subject: i40e: Fix for division by zero For some cases when reading from device are incorrect or image is incorrect, this part of code causes crash due to division by zero. Change-ID: I8961029a7a87b0a479995823ef8fcbf6471405e1 Signed-off-by: Michal Kosiarz Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index a47594603d69..98791ba57211 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -3313,8 +3313,10 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, /* partition id is 1-based, and functions are evenly spread * across the ports as partitions */ - hw->partition_id = (hw->pf_id / hw->num_ports) + 1; - hw->num_partitions = num_functions / hw->num_ports; + if (hw->num_ports != 0) { + hw->partition_id = (hw->pf_id / hw->num_ports) + 1; + hw->num_partitions = num_functions / hw->num_ports; + } /* additional HW specific goodies that might * someday be HW version specific -- cgit v1.2.3 From 81fa7c97bebd6e1a52c4e059eeffe18df5b3f11f Mon Sep 17 00:00:00 2001 From: Maciej Sosin Date: Tue, 11 Oct 2016 15:26:57 -0700 Subject: i40e: Implementation of ERROR state for NVM update state machine This patch adds I40E_NVMUPD_STATE_ERROR state for NVM update. Without this patch driver has no possibility to return NVM image write failure.This state is being set when ARQ rises error. arq_last_status is also updated every time when ARQ event comes, not only on error cases. Change-ID: I67ce43ba22a240773c2821b436e96054db0b7c81 Signed-off-by: Maciej Sosin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 16 ++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_adminq.c | 4 ++-- drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 + 5 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 738b42a44f20..56fb27298936 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -964,11 +964,11 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc); desc_idx = ntc; + hw->aq.arq_last_status = + (enum i40e_admin_queue_err)le16_to_cpu(desc->retval); flags = le16_to_cpu(desc->flags); if (flags & I40E_AQ_FLAG_ERR) { ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; - hw->aq.arq_last_status = - (enum i40e_admin_queue_err)le16_to_cpu(desc->retval); i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: Event received with error 0x%X.\n", diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 954efe3118db..38ee18f11124 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -722,9 +722,20 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, *((u16 *)&bytes[2]) = hw->nvm_wait_opcode; } + /* Clear error status on read */ + if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + return 0; } + /* Clear status even it is not read and log */ + if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) { + i40e_debug(hw, I40E_DEBUG_NVM, + "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n"); + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + } + switch (hw->nvmupd_state) { case I40E_NVMUPD_STATE_INIT: status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno); @@ -1074,6 +1085,11 @@ void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode) } hw->nvm_wait_opcode = 0; + if (hw->aq.arq_last_status) { + hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR; + return; + } + switch (hw->nvmupd_state) { case I40E_NVMUPD_STATE_INIT_WAIT: hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index bd5f13bef83c..d9a266041bf1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -366,6 +366,7 @@ enum i40e_nvmupd_state { I40E_NVMUPD_STATE_WRITING, I40E_NVMUPD_STATE_INIT_WAIT, I40E_NVMUPD_STATE_WRITE_WAIT, + I40E_NVMUPD_STATE_ERROR }; /* nvm_access definition and its masks/shifts need to be accessible to diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index 44f7ed7583dd..96385156b824 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -912,11 +912,11 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw, desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc); desc_idx = ntc; + hw->aq.arq_last_status = + (enum i40e_admin_queue_err)le16_to_cpu(desc->retval); flags = le16_to_cpu(desc->flags); if (flags & I40E_AQ_FLAG_ERR) { ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; - hw->aq.arq_last_status = - (enum i40e_admin_queue_err)le16_to_cpu(desc->retval); i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: Event received with error 0x%X.\n", diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 97f96e0d9c4c..ca7afe59c55f 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -348,6 +348,7 @@ enum i40e_nvmupd_state { I40E_NVMUPD_STATE_WRITING, I40E_NVMUPD_STATE_INIT_WAIT, I40E_NVMUPD_STATE_WRITE_WAIT, + I40E_NVMUPD_STATE_ERROR }; /* nvm_access definition and its masks/shifts need to be accessible to -- cgit v1.2.3 From 3aa7b74dbeedfb32406fec70cfd76d797209e8c9 Mon Sep 17 00:00:00 2001 From: Filip Sadowski Date: Tue, 11 Oct 2016 15:26:58 -0700 Subject: i40e: removed unreachable code Removed some of unnecessary if statements and unreachable code found by static code analysis tool. The return value of i40e_vsi_control_rings(..., false) is always 0. So, test for non-zero will never be true. The function has been split into "int i40e_vsi_start_rings()" and "void i40e_vsi_stop_rings()" for better understanding. Similarly, the function i40e_vsi_kill_vlan() never fails. So, checking for return value is also unnecessary. Function definition changed to void. The i40e_loopback_test() function is not implemented. The function and all references to loopback testing were removed. Change-ID: Id45cf66f6689ce2bc4e887de13f073e30e8431bd Signed-off-by: Filip Sadowski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 5 +-- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 18 ---------- drivers/net/ethernet/intel/i40e/i40e_main.c | 41 ++++++++++++---------- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 29 +++++---------- 4 files changed, 33 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index bb02280bc4c1..29c23183a0e0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -773,7 +773,8 @@ void i40e_service_event_schedule(struct i40e_pf *pf); void i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id, u8 *msg, u16 len); -int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable); +int i40e_vsi_start_rings(struct i40e_vsi *vsi); +void i40e_vsi_stop_rings(struct i40e_vsi *vsi); int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count); struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid, u16 downlink_seid, u8 enabled_tc); @@ -849,7 +850,7 @@ int i40e_close(struct net_device *netdev); int i40e_vsi_open(struct i40e_vsi *vsi); void i40e_vlan_stripping_disable(struct i40e_vsi *vsi); int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid); -int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid); +void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid); struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, const u8 *macaddr); int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 962a9bb8a08e..b9e1162d927f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -216,7 +216,6 @@ enum i40e_ethtool_test_id { I40E_ETH_TEST_REG = 0, I40E_ETH_TEST_EEPROM, I40E_ETH_TEST_INTR, - I40E_ETH_TEST_LOOPBACK, I40E_ETH_TEST_LINK, }; @@ -224,7 +223,6 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "Eeprom test (offline)", "Interrupt test (offline)", - "Loopback test (offline)", "Link test (on/offline)" }; @@ -1744,17 +1742,6 @@ static int i40e_intr_test(struct net_device *netdev, u64 *data) return *data; } -static int i40e_loopback_test(struct net_device *netdev, u64 *data) -{ - struct i40e_netdev_priv *np = netdev_priv(netdev); - struct i40e_pf *pf = np->vsi->back; - - netif_info(pf, hw, netdev, "loopback test not implemented\n"); - *data = 0; - - return *data; -} - static inline bool i40e_active_vfs(struct i40e_pf *pf) { struct i40e_vf *vfs = pf->vf; @@ -1790,7 +1777,6 @@ static void i40e_diag_test(struct net_device *netdev, data[I40E_ETH_TEST_REG] = 1; data[I40E_ETH_TEST_EEPROM] = 1; data[I40E_ETH_TEST_INTR] = 1; - data[I40E_ETH_TEST_LOOPBACK] = 1; data[I40E_ETH_TEST_LINK] = 1; eth_test->flags |= ETH_TEST_FL_FAILED; clear_bit(__I40E_TESTING, &pf->state); @@ -1818,9 +1804,6 @@ static void i40e_diag_test(struct net_device *netdev, if (i40e_intr_test(netdev, &data[I40E_ETH_TEST_INTR])) eth_test->flags |= ETH_TEST_FL_FAILED; - if (i40e_loopback_test(netdev, &data[I40E_ETH_TEST_LOOPBACK])) - eth_test->flags |= ETH_TEST_FL_FAILED; - /* run reg test last, a reset is required after it */ if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1841,7 +1824,6 @@ static void i40e_diag_test(struct net_device *netdev, data[I40E_ETH_TEST_REG] = 0; data[I40E_ETH_TEST_EEPROM] = 0; data[I40E_ETH_TEST_INTR] = 0; - data[I40E_ETH_TEST_LOOPBACK] = 0; } skip_ol_tests: diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 9ec977a425de..5c6a5ceb8a91 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2503,10 +2503,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) * i40e_vsi_kill_vlan - Remove vsi membership for given vlan * @vsi: the vsi being configured * @vid: vlan id to be removed (0 = untagged only , -1 = any) - * - * Return: 0 on success or negative otherwise **/ -int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) +void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) { struct net_device *netdev = vsi->netdev; struct i40e_mac_filter *f; @@ -2530,7 +2528,6 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) * applying the new filter changes */ i40e_service_event_schedule(vsi->back); - return 0; } /** @@ -4017,29 +4014,35 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable) } /** - * i40e_vsi_control_rings - Start or stop a VSI's rings + * i40e_vsi_start_rings - Start a VSI's rings * @vsi: the VSI being configured - * @enable: start or stop the rings **/ -int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool request) +int i40e_vsi_start_rings(struct i40e_vsi *vsi) { int ret = 0; /* do rx first for enable and last for disable */ - if (request) { - ret = i40e_vsi_control_rx(vsi, request); - if (ret) - return ret; - ret = i40e_vsi_control_tx(vsi, request); - } else { - /* Ignore return value, we need to shutdown whatever we can */ - i40e_vsi_control_tx(vsi, request); - i40e_vsi_control_rx(vsi, request); - } + ret = i40e_vsi_control_rx(vsi, true); + if (ret) + return ret; + ret = i40e_vsi_control_tx(vsi, true); return ret; } +/** + * i40e_vsi_stop_rings - Stop a VSI's rings + * @vsi: the VSI being configured + **/ +void i40e_vsi_stop_rings(struct i40e_vsi *vsi) +{ + /* do rx first for enable and last for disable + * Ignore return value, we need to shutdown whatever we can + */ + i40e_vsi_control_tx(vsi, false); + i40e_vsi_control_rx(vsi, false); +} + /** * i40e_vsi_free_irq - Free the irq association with the OS * @vsi: the VSI being configured @@ -5238,7 +5241,7 @@ static int i40e_up_complete(struct i40e_vsi *vsi) i40e_configure_msi_and_legacy(vsi); /* start rings */ - err = i40e_vsi_control_rings(vsi, true); + err = i40e_vsi_start_rings(vsi); if (err) return err; @@ -5335,7 +5338,7 @@ void i40e_down(struct i40e_vsi *vsi) netif_tx_disable(vsi->netdev); } i40e_vsi_disable_irq(vsi); - i40e_vsi_control_rings(vsi, false); + i40e_vsi_stop_rings(vsi); i40e_napi_disable_all(vsi); for (i = 0; i < vsi->num_queue_pairs; i++) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 69e184b3f72f..53b46553dd8d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -991,7 +991,7 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) if (vf->lan_vsi_idx == 0) goto complete_reset; - i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false); + i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]); complete_reset: /* reallocate VF resources to reset the VSI state */ i40e_free_vf_res(vf); @@ -1032,8 +1032,7 @@ void i40e_free_vfs(struct i40e_pf *pf) i40e_notify_client_of_vf_enable(pf, 0); for (i = 0; i < pf->num_alloc_vfs; i++) if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states)) - i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx], - false); + i40e_vsi_stop_rings(pf->vsi[pf->vf[i].lan_vsi_idx]); /* Disable IOV before freeing resources. This lets any VF drivers * running in the host get themselves cleaned up before we yank @@ -1759,7 +1758,7 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) goto error_param; } - if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], true)) + if (i40e_vsi_start_rings(pf->vsi[vf->lan_vsi_idx])) aq_ret = I40E_ERR_TIMEOUT; error_param: /* send the response to the VF */ @@ -1798,8 +1797,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) goto error_param; } - if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false)) - aq_ret = I40E_ERR_TIMEOUT; + i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]); error_param: /* send the response to the VF */ @@ -2139,9 +2137,8 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) } for (i = 0; i < vfl->num_elements; i++) { - int ret = i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]); - if (!ret) - vf->num_vlan--; + i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]); + vf->num_vlan--; if (test_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states)) i40e_aq_set_vsi_uc_promisc_on_vlan(&pf->hw, vsi->seid, @@ -2153,11 +2150,6 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) false, vfl->vlan_id[i], NULL); - - if (ret) - dev_err(&pf->pdev->dev, - "Unable to delete VLAN filter %d for VF %d, error %d\n", - vfl->vlan_id[i], vf->vf_id, ret); } error_param: @@ -2835,13 +2827,8 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, if (vsi->info.pvid) { /* kill old VLAN */ - ret = i40e_vsi_kill_vlan(vsi, (le16_to_cpu(vsi->info.pvid) & - VLAN_VID_MASK)); - if (ret) { - dev_info(&vsi->back->pdev->dev, - "remove VLAN failed, ret=%d, aq_err=%d\n", - ret, pf->hw.aq.asq_last_status); - } + i40e_vsi_kill_vlan(vsi, (le16_to_cpu(vsi->info.pvid) & + VLAN_VID_MASK)); } if (vlan_id || qos) ret = i40e_vsi_add_pvid(vsi, vlanprio); -- cgit v1.2.3 From 66dca399e60071d93f22023f3fb1c1c358eb2f06 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 7 Oct 2016 21:23:11 -0700 Subject: rpmsg: smd: Reduce restrictions when finding channel SMD channels are created by the remotes in "opening" state, but sometimes as we close and try to reopen them they linger in closing state. Following the search for a matching channel the create_ept() will verify that the channel is in a suitable state, so we can lax the restrictions of the search function to work around above difference in behaviour. Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_smd.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c index 06fef2b4c814..92efa74a0024 100644 --- a/drivers/rpmsg/qcom_smd.c +++ b/drivers/rpmsg/qcom_smd.c @@ -820,20 +820,13 @@ qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name) struct qcom_smd_channel *channel; struct qcom_smd_channel *ret = NULL; unsigned long flags; - unsigned state; spin_lock_irqsave(&edge->channels_lock, flags); list_for_each_entry(channel, &edge->channels, list) { - if (strcmp(channel->name, name)) - continue; - - state = GET_RX_CHANNEL_INFO(channel, state); - if (state != SMD_CHANNEL_OPENING && - state != SMD_CHANNEL_OPENED) - continue; - - ret = channel; - break; + if (!strcmp(channel->name, name)) { + ret = channel; + break; + } } spin_unlock_irqrestore(&edge->channels_lock, flags); -- cgit v1.2.3 From e950604782440c8635d289552bb5db58658fcbe9 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 7 Oct 2016 21:23:12 -0700 Subject: rpmsg: Introduce a driver override mechanism Similar to other subsystems it's useful to provide a mechanism to force a specific driver match on a device, so introduce this. Signed-off-by: Bjorn Andersson --- drivers/rpmsg/rpmsg_core.c | 3 +++ include/linux/rpmsg.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index b6ea9ffa7381..087d4db896c8 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -315,6 +315,9 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv) const struct rpmsg_device_id *ids = rpdrv->id_table; unsigned int i; + if (rpdev->driver_override) + return !strcmp(rpdev->driver_override, drv->name); + if (ids) for (i = 0; ids[i].name[0]; i++) if (rpmsg_id_match(rpdev, &ids[i])) diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 452d393cc8dd..7ad6c205f110 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -64,6 +64,7 @@ struct rpmsg_channel_info { * rpmsg_device - device that belong to the rpmsg bus * @dev: the device struct * @id: device id (used to match between rpmsg drivers and devices) + * @driver_override: driver name to force a match * @src: local address * @dst: destination address * @ept: the rpmsg endpoint of this channel @@ -72,6 +73,7 @@ struct rpmsg_channel_info { struct rpmsg_device { struct device dev; struct rpmsg_device_id id; + char *driver_override; u32 src; u32 dst; struct rpmsg_endpoint *ept; -- cgit v1.2.3 From bbd188092e3bd7536583b37e7d7d2e38a65de74d Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 7 Oct 2016 21:23:13 -0700 Subject: rpmsg: Support drivers without primary endpoint Some types of rpmsg drivers does not have a primary endpoint to tie their existence upon, but wishes to create and destroy endpoints dynamically, e.g. based on user interactions. Allow rpmsg drivers to omit a driver callback to signal this case and make the probe path not create a primary endpoint in this case. Signed-off-by: Bjorn Andersson --- drivers/rpmsg/rpmsg_core.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 087d4db896c8..7561941ba413 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -347,27 +347,30 @@ static int rpmsg_dev_probe(struct device *dev) struct rpmsg_device *rpdev = to_rpmsg_device(dev); struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); struct rpmsg_channel_info chinfo = {}; - struct rpmsg_endpoint *ept; + struct rpmsg_endpoint *ept = NULL; int err; - strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); - chinfo.src = rpdev->src; - chinfo.dst = RPMSG_ADDR_ANY; + if (rpdrv->callback) { + strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); + chinfo.src = rpdev->src; + chinfo.dst = RPMSG_ADDR_ANY; - ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo); - if (!ept) { - dev_err(dev, "failed to create endpoint\n"); - err = -ENOMEM; - goto out; - } + ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo); + if (!ept) { + dev_err(dev, "failed to create endpoint\n"); + err = -ENOMEM; + goto out; + } - rpdev->ept = ept; - rpdev->src = ept->addr; + rpdev->ept = ept; + rpdev->src = ept->addr; + } err = rpdrv->probe(rpdev); if (err) { dev_err(dev, "%s: failed: %d\n", __func__, err); - rpmsg_destroy_ept(ept); + if (ept) + rpmsg_destroy_ept(ept); goto out; } @@ -388,7 +391,8 @@ static int rpmsg_dev_remove(struct device *dev) rpdrv->remove(rpdev); - rpmsg_destroy_ept(rpdev->ept); + if (rpdev->ept) + rpmsg_destroy_ept(rpdev->ept); return err; } -- cgit v1.2.3 From 93e9324431c9628224886f979dcd59d377b0818a Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 18 Oct 2016 17:23:44 -0700 Subject: rpmsg: Handle invalid parameters in public API There are two cases of possible uninitialized pointer usage in the API, either the parameters themselves are invalid or we're trying to jump to functions not required to be implemented by all backends. Suggested-by: Loic Pallardy Signed-off-by: Bjorn Andersson --- drivers/rpmsg/rpmsg_core.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 7561941ba413..a79cb5a9e5f2 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -71,6 +71,9 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv, struct rpmsg_channel_info chinfo) { + if (WARN_ON(!rpdev)) + return ERR_PTR(-EINVAL); + return rpdev->ops->create_ept(rpdev, cb, priv, chinfo); } EXPORT_SYMBOL(rpmsg_create_ept); @@ -80,11 +83,13 @@ EXPORT_SYMBOL(rpmsg_create_ept); * @ept: endpoing to destroy * * Should be used by drivers to destroy an rpmsg endpoint previously - * created with rpmsg_create_ept(). + * created with rpmsg_create_ept(). As with other types of "free" NULL + * is a valid parameter. */ void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) { - ept->ops->destroy_ept(ept); + if (ept) + ept->ops->destroy_ept(ept); } EXPORT_SYMBOL(rpmsg_destroy_ept); @@ -108,6 +113,11 @@ EXPORT_SYMBOL(rpmsg_destroy_ept); */ int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) { + if (WARN_ON(!ept)) + return -EINVAL; + if (!ept->ops->send) + return -ENXIO; + return ept->ops->send(ept, data, len); } EXPORT_SYMBOL(rpmsg_send); @@ -132,6 +142,11 @@ EXPORT_SYMBOL(rpmsg_send); */ int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) { + if (WARN_ON(!ept)) + return -EINVAL; + if (!ept->ops->sendto) + return -ENXIO; + return ept->ops->sendto(ept, data, len, dst); } EXPORT_SYMBOL(rpmsg_sendto); @@ -159,6 +174,11 @@ EXPORT_SYMBOL(rpmsg_sendto); int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len) { + if (WARN_ON(!ept)) + return -EINVAL; + if (!ept->ops->send_offchannel) + return -ENXIO; + return ept->ops->send_offchannel(ept, src, dst, data, len); } EXPORT_SYMBOL(rpmsg_send_offchannel); @@ -182,6 +202,11 @@ EXPORT_SYMBOL(rpmsg_send_offchannel); */ int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) { + if (WARN_ON(!ept)) + return -EINVAL; + if (!ept->ops->trysend) + return -ENXIO; + return ept->ops->trysend(ept, data, len); } EXPORT_SYMBOL(rpmsg_trysend); @@ -205,6 +230,11 @@ EXPORT_SYMBOL(rpmsg_trysend); */ int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) { + if (WARN_ON(!ept)) + return -EINVAL; + if (!ept->ops->trysendto) + return -ENXIO; + return ept->ops->trysendto(ept, data, len, dst); } EXPORT_SYMBOL(rpmsg_trysendto); @@ -231,6 +261,11 @@ EXPORT_SYMBOL(rpmsg_trysendto); int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len) { + if (WARN_ON(!ept)) + return -EINVAL; + if (!ept->ops->trysend_offchannel) + return -ENXIO; + return ept->ops->trysend_offchannel(ept, src, dst, data, len); } EXPORT_SYMBOL(rpmsg_trysend_offchannel); -- cgit v1.2.3 From 2aefbef041498182ce1d186ed2300298b7a7101a Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Wed, 19 Oct 2016 13:05:47 +0100 Subject: remoteproc: Add a sysfs interface for firmware and state This patch adds a sysfs interface to rproc allowing the firmware name and processor state to be changed dynamically. State was previously available in debugfs, and is replicated here. The firmware file allows retrieval of the running firmware name, and a new one to be specified at run time, so long as the remote processor has been stopped. Signed-off-by: Matt Redfearn Signed-off-by: Bjorn Andersson --- Documentation/ABI/testing/sysfs-class-remoteproc | 50 ++++++++ drivers/remoteproc/Makefile | 1 + drivers/remoteproc/remoteproc_core.c | 3 + drivers/remoteproc/remoteproc_internal.h | 5 + drivers/remoteproc/remoteproc_sysfs.c | 151 +++++++++++++++++++++++ 5 files changed, 210 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-remoteproc create mode 100644 drivers/remoteproc/remoteproc_sysfs.c (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc b/Documentation/ABI/testing/sysfs-class-remoteproc new file mode 100644 index 000000000000..d188afebc8ba --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-remoteproc @@ -0,0 +1,50 @@ +What: /sys/class/remoteproc/.../firmware +Date: October 2016 +Contact: Matt Redfearn +Description: Remote processor firmware + + Reports the name of the firmware currently loaded to the + remote processor. + + To change the running firmware, ensure the remote processor is + stopped (using /sys/class/remoteproc/.../state) and write a new filename. + +What: /sys/class/remoteproc/.../state +Date: October 2016 +Contact: Matt Redfearn +Description: Remote processor state + + Reports the state of the remote processor, which will be one of: + + "offline" + "suspended" + "running" + "crashed" + "invalid" + + "offline" means the remote processor is powered off. + + "suspended" means that the remote processor is suspended and + must be woken to receive messages. + + "running" is the normal state of an available remote processor + + "crashed" indicates that a problem/crash has been detected on + the remote processor. + + "invalid" is returned if the remote processor is in an + unknown state. + + Writing this file controls the state of the remote processor. + The following states can be written: + + "start" + "stop" + + Writing "start" will attempt to start the processor running the + firmware indicated by, or written to, + /sys/class/remoteproc/.../firmware. The remote processor should + transition to "running" state. + + Writing "stop" will attempt to halt the remote processor and + return it to the "offline" state. diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 6dfb62ed643f..6da9b12f9798 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_REMOTEPROC) += remoteproc.o remoteproc-y := remoteproc_core.o remoteproc-y += remoteproc_debugfs.o +remoteproc-y += remoteproc_sysfs.o remoteproc-y += remoteproc_virtio.o remoteproc-y += remoteproc_elf_loader.o obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index ccc2a73e94dd..b1860949d106 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1347,6 +1347,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, device_initialize(&rproc->dev); rproc->dev.parent = dev; rproc->dev.type = &rproc_type; + rproc->dev.class = &rproc_class; /* Assign a unique device index and name */ rproc->index = ida_simple_get(&rproc_dev_index, 0, 0, GFP_KERNEL); @@ -1485,6 +1486,7 @@ EXPORT_SYMBOL(rproc_report_crash); static int __init remoteproc_init(void) { + rproc_init_sysfs(); rproc_init_debugfs(); return 0; @@ -1496,6 +1498,7 @@ static void __exit remoteproc_exit(void) ida_destroy(&rproc_dev_index); rproc_exit_debugfs(); + rproc_exit_sysfs(); } module_exit(remoteproc_exit); diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 4cf93ca2816e..c2c3e4762b90 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -63,6 +63,11 @@ void rproc_create_debug_dir(struct rproc *rproc); void rproc_init_debugfs(void); void rproc_exit_debugfs(void); +/* from remoteproc_sysfs.c */ +extern struct class rproc_class; +int rproc_init_sysfs(void); +void rproc_exit_sysfs(void); + void rproc_free_vring(struct rproc_vring *rvring); int rproc_alloc_vring(struct rproc_vdev *rvdev, int i); diff --git a/drivers/remoteproc/remoteproc_sysfs.c b/drivers/remoteproc/remoteproc_sysfs.c new file mode 100644 index 000000000000..bc5b0e00efb1 --- /dev/null +++ b/drivers/remoteproc/remoteproc_sysfs.c @@ -0,0 +1,151 @@ +/* + * Remote Processor Framework + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include "remoteproc_internal.h" + +#define to_rproc(d) container_of(d, struct rproc, dev) + +/* Expose the loaded / running firmware name via sysfs */ +static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct rproc *rproc = to_rproc(dev); + + return sprintf(buf, "%s\n", rproc->firmware); +} + +/* Change firmware name via sysfs */ +static ssize_t firmware_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct rproc *rproc = to_rproc(dev); + char *p; + int err, len = count; + + err = mutex_lock_interruptible(&rproc->lock); + if (err) { + dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, err); + return -EINVAL; + } + + if (rproc->state != RPROC_OFFLINE) { + dev_err(dev, "can't change firmware while running\n"); + err = -EBUSY; + goto out; + } + + len = strcspn(buf, "\n"); + + p = kstrndup(buf, len, GFP_KERNEL); + if (!p) { + err = -ENOMEM; + goto out; + } + + kfree(rproc->firmware); + rproc->firmware = p; +out: + mutex_unlock(&rproc->lock); + + return err ? err : count; +} +static DEVICE_ATTR_RW(firmware); + +/* + * A state-to-string lookup table, for exposing a human readable state + * via sysfs. Always keep in sync with enum rproc_state + */ +static const char * const rproc_state_string[] = { + [RPROC_OFFLINE] = "offline", + [RPROC_SUSPENDED] = "suspended", + [RPROC_RUNNING] = "running", + [RPROC_CRASHED] = "crashed", + [RPROC_LAST] = "invalid", +}; + +/* Expose the state of the remote processor via sysfs */ +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct rproc *rproc = to_rproc(dev); + unsigned int state; + + state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state; + return sprintf(buf, "%s\n", rproc_state_string[state]); +} + +/* Change remote processor state via sysfs */ +static ssize_t state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct rproc *rproc = to_rproc(dev); + int ret = 0; + + if (sysfs_streq(buf, "start")) { + if (rproc->state == RPROC_RUNNING) + return -EBUSY; + + ret = rproc_boot(rproc); + if (ret) + dev_err(&rproc->dev, "Boot failed: %d\n", ret); + } else if (sysfs_streq(buf, "stop")) { + if (rproc->state != RPROC_RUNNING) + return -EINVAL; + + rproc_shutdown(rproc); + } else { + dev_err(&rproc->dev, "Unrecognised option: %s\n", buf); + ret = -EINVAL; + } + return ret ? ret : count; +} +static DEVICE_ATTR_RW(state); + +static struct attribute *rproc_attrs[] = { + &dev_attr_firmware.attr, + &dev_attr_state.attr, + NULL +}; + +static const struct attribute_group rproc_devgroup = { + .attrs = rproc_attrs +}; + +static const struct attribute_group *rproc_devgroups[] = { + &rproc_devgroup, + NULL +}; + +struct class rproc_class = { + .name = "remoteproc", + .dev_groups = rproc_devgroups, +}; + +int __init rproc_init_sysfs(void) +{ + /* create remoteproc device class for sysfs */ + int err = class_register(&rproc_class); + + if (err) + pr_err("remoteproc: unable to register class\n"); + return err; +} + +void __exit rproc_exit_sysfs(void) +{ + class_unregister(&rproc_class); +} -- cgit v1.2.3 From fd50d8c0619ebabee7017ca9358725643cc2b2b6 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Wed, 19 Oct 2016 13:05:48 +0100 Subject: remoteproc: debugfs: Remove state entry which is duplicated is sysfs Since there is now an always available state file in sysfs with the same function as this one in debugfs, remove the redundant entry. Signed-off-by: Matt Redfearn Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_debugfs.c | 71 --------------------------------- 1 file changed, 71 deletions(-) (limited to 'drivers') diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 374797206c79..1c122e230cec 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -59,75 +59,6 @@ static const struct file_operations trace_rproc_ops = { .llseek = generic_file_llseek, }; -/* - * A state-to-string lookup table, for exposing a human readable state - * via debugfs. Always keep in sync with enum rproc_state - */ -static const char * const rproc_state_string[] = { - "offline", - "suspended", - "running", - "crashed", - "invalid", -}; - -/* expose the state of the remote processor via debugfs */ -static ssize_t rproc_state_read(struct file *filp, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct rproc *rproc = filp->private_data; - unsigned int state; - char buf[30]; - int i; - - state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state; - - i = scnprintf(buf, 30, "%.28s (%d)\n", rproc_state_string[state], - rproc->state); - - return simple_read_from_buffer(userbuf, count, ppos, buf, i); -} - -static ssize_t rproc_state_write(struct file *filp, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct rproc *rproc = filp->private_data; - char buf[10]; - int ret; - - if (count > sizeof(buf) || count <= 0) - return -EINVAL; - - ret = copy_from_user(buf, userbuf, count); - if (ret) - return -EFAULT; - - if (buf[count - 1] == '\n') - buf[count - 1] = '\0'; - - if (!strncmp(buf, "start", count)) { - ret = rproc_boot(rproc); - if (ret) { - dev_err(&rproc->dev, "Boot failed: %d\n", ret); - return ret; - } - } else if (!strncmp(buf, "stop", count)) { - rproc_shutdown(rproc); - } else { - dev_err(&rproc->dev, "Unrecognised option: %s\n", buf); - return -EINVAL; - } - - return count; -} - -static const struct file_operations rproc_state_ops = { - .read = rproc_state_read, - .write = rproc_state_write, - .open = simple_open, - .llseek = generic_file_llseek, -}; - /* expose the name of the remote processor via debugfs */ static ssize_t rproc_name_read(struct file *filp, char __user *userbuf, size_t count, loff_t *ppos) @@ -265,8 +196,6 @@ void rproc_create_debug_dir(struct rproc *rproc) debugfs_create_file("name", 0400, rproc->dbg_dir, rproc, &rproc_name_ops); - debugfs_create_file("state", 0400, rproc->dbg_dir, - rproc, &rproc_state_ops); debugfs_create_file("recovery", 0400, rproc->dbg_dir, rproc, &rproc_recovery_ops); } -- cgit v1.2.3 From 1d701d3dd8caf6660ff33c3c23a115b4649c5cdb Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 17 Oct 2016 16:23:35 +0000 Subject: remoteproc: st: Fix error return code in st_rproc_probe() Fix to return a negative error code from the st_rproc_state() error handling case instead of 0, as done elsewhere in this function. Fixes: 63edb0310a5c ("remoteproc: Supply controller driver for ST's Remote Processors") Signed-off-by: Wei Yongjun Signed-off-by: Bjorn Andersson --- drivers/remoteproc/st_remoteproc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c index ae8963fcc8c8..da4e152e9733 100644 --- a/drivers/remoteproc/st_remoteproc.c +++ b/drivers/remoteproc/st_remoteproc.c @@ -245,8 +245,10 @@ static int st_rproc_probe(struct platform_device *pdev) goto free_rproc; enabled = st_rproc_state(pdev); - if (enabled < 0) + if (enabled < 0) { + ret = enabled; goto free_rproc; + } if (enabled) { atomic_inc(&rproc->power); -- cgit v1.2.3 From 2cc751545854d7bd7eedf4d7e377bb52e176cd07 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Sat, 22 Oct 2016 15:57:05 +0200 Subject: hwrng: core - zeroize buffers with random data The HWRNG core allocates two buffers during initialization which are used to obtain random data. After that data is processed, it is now zeroized as it is possible that the HWRNG core will not be asked to produce more random data for a long time. This prevents leaving such sensitive data in memory. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index d2d2c89de5b4..f9766415ff10 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -92,6 +92,7 @@ static void add_early_randomness(struct hwrng *rng) mutex_unlock(&reading_mutex); if (bytes_read > 0) add_device_randomness(rng_buffer, bytes_read); + memset(rng_buffer, 0, size); } static inline void cleanup_rng(struct kref *kref) @@ -287,6 +288,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, } } out: + memset(rng_buffer, 0, rng_buffer_size()); return ret ? : err; out_unlock_reading: @@ -425,6 +427,7 @@ static int hwrng_fillfn(void *unused) /* Outside lock, sure, but y'know: randomness. */ add_hwgenerator_randomness((void *)rng_fillbuf, rc, rc * current_quality * 8 >> 10); + memset(rng_fillbuf, 0, rng_buffer_size()); } hwrng_fill = NULL; return 0; -- cgit v1.2.3 From fc783341f0e65a28d95cba8d6998bf90304017c5 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 24 Oct 2016 14:51:22 +0000 Subject: crypto: atmel - drop pointless static qualifier in atmel_aes_probe() There is no need to have the 'struct atmel_aes_dev *aes_dd' variable static since new value always be assigned before use it. Signed-off-by: Wei Yongjun Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 6b656f4a9378..0e3d0d655b96 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -2311,7 +2311,7 @@ aes_dd_err: static int atmel_aes_remove(struct platform_device *pdev) { - static struct atmel_aes_dev *aes_dd; + struct atmel_aes_dev *aes_dd; aes_dd = platform_get_drvdata(pdev); if (!aes_dd) -- cgit v1.2.3 From 9ae811f28070d6f63a675d7482bd1fc140a3a7c6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 25 Oct 2016 12:07:27 +0100 Subject: crypto: sahara - fix typo "Decidated" -> "Dedicated" Trivial fix to typo in dev_dbg message Signed-off-by: Colin Ian King Signed-off-by: Herbert Xu --- drivers/crypto/sahara.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 0c49956ee0ce..1d9ecd368b5b 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -390,7 +390,7 @@ static void sahara_decode_status(struct sahara_dev *dev, unsigned int status) if (status & SAHARA_STATUS_MODE_BATCH) dev_dbg(dev->device, " - Batch Mode.\n"); else if (status & SAHARA_STATUS_MODE_DEDICATED) - dev_dbg(dev->device, " - Decidated Mode.\n"); + dev_dbg(dev->device, " - Dedicated Mode.\n"); else if (status & SAHARA_STATUS_MODE_DEBUG) dev_dbg(dev->device, " - Debug Mode.\n"); -- cgit v1.2.3 From d69985a07692cbe67c50fa0e0ed8ffbd25cedd71 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 25 Oct 2016 23:29:10 +0200 Subject: crypto: caam - fix type mismatch warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building the caam driver on arm64 produces a harmless warning: drivers/crypto/caam/caamalg.c:140:139: warning: comparison of distinct pointer types lacks a cast We can use min_t to tell the compiler which type we want it to use here. Fixes: 5ecf8ef9103c ("crypto: caam - fix sg dump") Signed-off-by: Arnd Bergmann Reviewed-by: Horia Geantă Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 156aad167cd6..8de85dfb1b04 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -137,7 +137,7 @@ static void dbg_dump_sg(const char *level, const char *prefix_str, } buf = it_page + it->offset; - len = min(tlen, it->length); + len = min_t(size_t, tlen, it->length); print_hex_dump(level, prefix_str, prefix_type, rowsize, groupsize, buf, len, ascii); tlen -= len; -- cgit v1.2.3 From a1fa98d8116fb4f8a5df91fb2267ce8d192f6875 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Fri, 28 Oct 2016 16:00:46 +0800 Subject: hwrng: atmel - disable TRNG during suspend To fix the over consumption on the VDDCore due to the TRNG enabled, disable the TRNG during suspend, not only disable the user interface clock (which is controlled by PMC). Because the user interface clock is independent from any clock that may be used in the entropy source logic circuitry. Signed-off-by: Wenyou Yang Acked-by: Nicolas Ferre Signed-off-by: Herbert Xu --- drivers/char/hw_random/atmel-rng.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index 0fcc9e69a346..ae7cae579eac 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -48,6 +48,16 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max, return 0; } +static void atmel_trng_enable(struct atmel_trng *trng) +{ + writel(TRNG_KEY | 1, trng->base + TRNG_CR); +} + +static void atmel_trng_disable(struct atmel_trng *trng) +{ + writel(TRNG_KEY, trng->base + TRNG_CR); +} + static int atmel_trng_probe(struct platform_device *pdev) { struct atmel_trng *trng; @@ -71,7 +81,7 @@ static int atmel_trng_probe(struct platform_device *pdev) if (ret) return ret; - writel(TRNG_KEY | 1, trng->base + TRNG_CR); + atmel_trng_enable(trng); trng->rng.name = pdev->name; trng->rng.read = atmel_trng_read; @@ -94,7 +104,7 @@ static int atmel_trng_remove(struct platform_device *pdev) hwrng_unregister(&trng->rng); - writel(TRNG_KEY, trng->base + TRNG_CR); + atmel_trng_disable(trng); clk_disable_unprepare(trng->clk); return 0; @@ -105,6 +115,7 @@ static int atmel_trng_suspend(struct device *dev) { struct atmel_trng *trng = dev_get_drvdata(dev); + atmel_trng_disable(trng); clk_disable_unprepare(trng->clk); return 0; @@ -113,8 +124,15 @@ static int atmel_trng_suspend(struct device *dev) static int atmel_trng_resume(struct device *dev) { struct atmel_trng *trng = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(trng->clk); + if (ret) + return ret; - return clk_prepare_enable(trng->clk); + atmel_trng_enable(trng); + + return 0; } static const struct dev_pm_ops atmel_trng_pm_ops = { -- cgit v1.2.3 From a13925a46ebc176c4703c25b5f2edebba5bd2506 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 31 Oct 2016 15:32:16 -0400 Subject: net: cris: make eth_v10.c explicitly non-modular The Makefile/Kconfig currently controlling compilation of this code is: drivers/net/cris/Makefile:obj-$(CONFIG_ETRAX_ARCH_V10) += eth_v10.o arch/cris/Kconfig:config ETRAX_ARCH_V10 arch/cris/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular infrastructure use, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. There was a one line wrapper for the int init function, which made no sense; hence we just put the device_initcall on the true init function itself and delete the pointless wrapper. In doing that we get rid of the following compile warning: WARNING: drivers/net/built-in.o(.text+0x1e28): Section mismatch in reference from the function etrax_init_module() to the function .init.text:etrax_ethernet_init() We don't replace module.h with init.h since the file already has that. Cc: "David S. Miller" Cc: Mikael Starvik Cc: Jesper Nilsson Cc: netdev@vger.kernel.org Cc: linux-cris-kernel@axis.com Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- drivers/net/cris/eth_v10.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index e128826aa117..91c876a0a647 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -7,9 +7,6 @@ * */ - -#include - #include #include #include @@ -411,6 +408,7 @@ etrax_ethernet_init(void) led_next_time = jiffies; return 0; } +device_initcall(etrax_ethernet_init) /* set MAC address of the interface. called from the core after a * SIOCSIFADDR ioctl, and from the bootup above. @@ -1714,11 +1712,6 @@ e100_netpoll(struct net_device* netdev) } #endif -static int -etrax_init_module(void) -{ - return etrax_ethernet_init(); -} static int __init e100_boot_setup(char* str) @@ -1741,5 +1734,3 @@ e100_boot_setup(char* str) } __setup("etrax100_eth=", e100_boot_setup); - -module_init(etrax_init_module); -- cgit v1.2.3 From 650ec6cfe323311165f0c7b6882a63dfd7ae8b63 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Oct 2016 09:21:24 +0200 Subject: cpufreq: enable the DT cpufreq driver on the Integrators This enables the generic DT and OPP-based cpufreq driver on the ARM Integrator/AP and Integrator/CP. Acked-by: Viresh Kumar Signed-off-by: Linus Walleij Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt-platdev.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 71267626456b..142a6f615e52 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -26,6 +26,9 @@ static const struct of_device_id machines[] __initconst = { { .compatible = "allwinner,sun8i-a83t", }, { .compatible = "allwinner,sun8i-h3", }, + { .compatible = "arm,integrator-ap", }, + { .compatible = "arm,integrator-cp", }, + { .compatible = "hisilicon,hi6220", }, { .compatible = "fsl,imx27", }, -- cgit v1.2.3 From ae8b8d8f86a03c19c5ecfd848609b2e9438f1cf2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Oct 2016 09:21:25 +0200 Subject: cpufreq: retire the Integrator cpufreq driver After switching the core module clocks controlling the Integrator clock frequencies to the common clock framework, defining the operating points in the device tree, and activating the generic DT-based CPUfreq driver, we can retire the old Integrator cpufreq driver. Acked-by: Viresh Kumar Signed-off-by: Linus Walleij Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/Kconfig.arm | 8 -- drivers/cpufreq/Makefile | 1 - drivers/cpufreq/integrator-cpufreq.c | 239 ----------------------------------- 3 files changed, 248 deletions(-) delete mode 100644 drivers/cpufreq/integrator-cpufreq.c (limited to 'drivers') diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index d89b8afe23b6..fdbc630272b3 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -60,14 +60,6 @@ config ARM_IMX6Q_CPUFREQ If in doubt, say N. -config ARM_INTEGRATOR - tristate "CPUfreq driver for ARM Integrator CPUs" - depends on ARCH_INTEGRATOR - default y - help - This enables the CPUfreq driver for ARM Integrator CPUs. - If in doubt, say Y. - config ARM_KIRKWOOD_CPUFREQ def_bool MACH_KIRKWOOD help diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 0a9b6a093646..7dde82179d62 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -56,7 +56,6 @@ obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o -obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o obj-$(CONFIG_ARM_MT8173_CPUFREQ) += mt8173-cpufreq.o obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c deleted file mode 100644 index 79e3ff2771a6..000000000000 --- a/drivers/cpufreq/integrator-cpufreq.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2001-2002 Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * CPU support functions - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static void __iomem *cm_base; -/* The cpufreq driver only use the OSC register */ -#define INTEGRATOR_HDR_OSC_OFFSET 0x08 -#define INTEGRATOR_HDR_LOCK_OFFSET 0x14 - -static struct cpufreq_driver integrator_driver; - -static const struct icst_params lclk_params = { - .ref = 24000000, - .vco_max = ICST525_VCO_MAX_5V, - .vco_min = ICST525_VCO_MIN, - .vd_min = 8, - .vd_max = 132, - .rd_min = 24, - .rd_max = 24, - .s2div = icst525_s2div, - .idx2s = icst525_idx2s, -}; - -static const struct icst_params cclk_params = { - .ref = 24000000, - .vco_max = ICST525_VCO_MAX_5V, - .vco_min = ICST525_VCO_MIN, - .vd_min = 12, - .vd_max = 160, - .rd_min = 24, - .rd_max = 24, - .s2div = icst525_s2div, - .idx2s = icst525_idx2s, -}; - -/* - * Validate the speed policy. - */ -static int integrator_verify_policy(struct cpufreq_policy *policy) -{ - struct icst_vco vco; - - cpufreq_verify_within_cpu_limits(policy); - - vco = icst_hz_to_vco(&cclk_params, policy->max * 1000); - policy->max = icst_hz(&cclk_params, vco) / 1000; - - vco = icst_hz_to_vco(&cclk_params, policy->min * 1000); - policy->min = icst_hz(&cclk_params, vco) / 1000; - - cpufreq_verify_within_cpu_limits(policy); - return 0; -} - - -static int integrator_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - cpumask_t cpus_allowed; - int cpu = policy->cpu; - struct icst_vco vco; - struct cpufreq_freqs freqs; - u_int cm_osc; - - /* - * Save this threads cpus_allowed mask. - */ - cpus_allowed = current->cpus_allowed; - - /* - * Bind to the specified CPU. When this call returns, - * we should be running on the right CPU. - */ - set_cpus_allowed_ptr(current, cpumask_of(cpu)); - BUG_ON(cpu != smp_processor_id()); - - /* get current setting */ - cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET); - - if (machine_is_integrator()) - vco.s = (cm_osc >> 8) & 7; - else if (machine_is_cintegrator()) - vco.s = 1; - vco.v = cm_osc & 255; - vco.r = 22; - freqs.old = icst_hz(&cclk_params, vco) / 1000; - - /* icst_hz_to_vco rounds down -- so we need the next - * larger freq in case of CPUFREQ_RELATION_L. - */ - if (relation == CPUFREQ_RELATION_L) - target_freq += 999; - if (target_freq > policy->max) - target_freq = policy->max; - vco = icst_hz_to_vco(&cclk_params, target_freq * 1000); - freqs.new = icst_hz(&cclk_params, vco) / 1000; - - if (freqs.old == freqs.new) { - set_cpus_allowed_ptr(current, &cpus_allowed); - return 0; - } - - cpufreq_freq_transition_begin(policy, &freqs); - - cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET); - - if (machine_is_integrator()) { - cm_osc &= 0xfffff800; - cm_osc |= vco.s << 8; - } else if (machine_is_cintegrator()) { - cm_osc &= 0xffffff00; - } - cm_osc |= vco.v; - - __raw_writel(0xa05f, cm_base + INTEGRATOR_HDR_LOCK_OFFSET); - __raw_writel(cm_osc, cm_base + INTEGRATOR_HDR_OSC_OFFSET); - __raw_writel(0, cm_base + INTEGRATOR_HDR_LOCK_OFFSET); - - /* - * Restore the CPUs allowed mask. - */ - set_cpus_allowed_ptr(current, &cpus_allowed); - - cpufreq_freq_transition_end(policy, &freqs, 0); - - return 0; -} - -static unsigned int integrator_get(unsigned int cpu) -{ - cpumask_t cpus_allowed; - unsigned int current_freq; - u_int cm_osc; - struct icst_vco vco; - - cpus_allowed = current->cpus_allowed; - - set_cpus_allowed_ptr(current, cpumask_of(cpu)); - BUG_ON(cpu != smp_processor_id()); - - /* detect memory etc. */ - cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET); - - if (machine_is_integrator()) - vco.s = (cm_osc >> 8) & 7; - else - vco.s = 1; - vco.v = cm_osc & 255; - vco.r = 22; - - current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */ - - set_cpus_allowed_ptr(current, &cpus_allowed); - - return current_freq; -} - -static int integrator_cpufreq_init(struct cpufreq_policy *policy) -{ - - /* set default policy and cpuinfo */ - policy->max = policy->cpuinfo.max_freq = 160000; - policy->min = policy->cpuinfo.min_freq = 12000; - policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */ - - return 0; -} - -static struct cpufreq_driver integrator_driver = { - .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, - .verify = integrator_verify_policy, - .target = integrator_set_target, - .get = integrator_get, - .init = integrator_cpufreq_init, - .name = "integrator", -}; - -static int __init integrator_cpufreq_probe(struct platform_device *pdev) -{ - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - cm_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!cm_base) - return -ENODEV; - - return cpufreq_register_driver(&integrator_driver); -} - -static int __exit integrator_cpufreq_remove(struct platform_device *pdev) -{ - return cpufreq_unregister_driver(&integrator_driver); -} - -static const struct of_device_id integrator_cpufreq_match[] = { - { .compatible = "arm,core-module-integrator"}, - { }, -}; - -MODULE_DEVICE_TABLE(of, integrator_cpufreq_match); - -static struct platform_driver integrator_cpufreq_driver = { - .driver = { - .name = "integrator-cpufreq", - .of_match_table = integrator_cpufreq_match, - }, - .remove = __exit_p(integrator_cpufreq_remove), -}; - -module_platform_driver_probe(integrator_cpufreq_driver, - integrator_cpufreq_probe); - -MODULE_AUTHOR("Russell M. King"); -MODULE_DESCRIPTION("cpufreq driver for ARM Integrator CPUs"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From eae48f046ffa117afb782cd9b3ae5469df0042e2 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 25 Oct 2016 13:20:40 -0700 Subject: cpufreq: intel_pstate: Per CPU P-State limits Intel P-State offers two interface to set performance limits: - Intel P-State sysfs /sys/devices/system/cpu/intel_pstate/max_perf_pct /sys/devices/system/cpu/intel_pstate/min_perf_pct - cpufreq /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq /sys/devices/system/cpu/cpu*/cpufreq/scaling_min_freq In the current implementation both of the above methods, change limits to every CPU in the system. Moreover the limits placed using cpufreq policy interface also presented in the Intel P-State sysfs via modified max_perf_pct and min_per_pct during sysfs reads. This allows to check percent of reduced/increased performance, irrespective of method used to limit. There are some new generations of processors, where it is possible to have limits placed on individual CPU cores. Using cpufreq interface it is possible to set limits on each CPU. But the current processing will use last limits placed on all CPUs. So the per core limit feature of CPUs can't be used. This change brings in capability to set P-States limits for each CPU, with some limitations. In this case what should be the read of max_perf_pct and min_perf_pct? It can be most restrictive limits placed on any CPU or max possible performance on any given CPU on which no limits are placed. In either case someone will have issue. So the consensus is, we can't have both sysfs controls present when user wants to use limit per core limits. - By default per-core-control feature is not enabled. So no one will notice any difference. - The way to enable is by kernel command line intel_pstate=per_cpu_perf_limits - When the per-core-controls are enabled there is no display of for both read and write on /sys/devices/system/cpu/intel_pstate/max_perf_pct /sys/devices/system/cpu/intel_pstate/min_perf_pct - User can change limits using /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq /sys/devices/system/cpu/cpu*/cpufreq/scaling_min_freq /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor - User can still observe turbo percent and number of P-States from /sys/devices/system/cpu/intel_pstate/turbo_pct /sys/devices/system/cpu/intel_pstate/num_pstates - User can read write system wide turbo status /sys/devices/system/cpu/no_turbo While changing this BUG_ON is changed to WARN_ON, as they are not fatal errors for the system. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 236 +++++++++++++++++++++++++++-------------- 1 file changed, 156 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index d7a9195a8351..b6e9b49bf151 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -176,6 +176,48 @@ struct _pid { int32_t last_err; }; +/** + * struct perf_limits - Store user and policy limits + * @no_turbo: User requested turbo state from intel_pstate sysfs + * @turbo_disabled: Platform turbo status either from msr + * MSR_IA32_MISC_ENABLE or when maximum available pstate + * matches the maximum turbo pstate + * @max_perf_pct: Effective maximum performance limit in percentage, this + * is minimum of either limits enforced by cpufreq policy + * or limits from user set limits via intel_pstate sysfs + * @min_perf_pct: Effective minimum performance limit in percentage, this + * is maximum of either limits enforced by cpufreq policy + * or limits from user set limits via intel_pstate sysfs + * @max_perf: This is a scaled value between 0 to 255 for max_perf_pct + * This value is used to limit max pstate + * @min_perf: This is a scaled value between 0 to 255 for min_perf_pct + * This value is used to limit min pstate + * @max_policy_pct: The maximum performance in percentage enforced by + * cpufreq setpolicy interface + * @max_sysfs_pct: The maximum performance in percentage enforced by + * intel pstate sysfs interface, unused when per cpu + * controls are enforced + * @min_policy_pct: The minimum performance in percentage enforced by + * cpufreq setpolicy interface + * @min_sysfs_pct: The minimum performance in percentage enforced by + * intel pstate sysfs interface, unused when per cpu + * controls are enforced + * + * Storage for user and policy defined limits. + */ +struct perf_limits { + int no_turbo; + int turbo_disabled; + int max_perf_pct; + int min_perf_pct; + int32_t max_perf; + int32_t min_perf; + int max_policy_pct; + int max_sysfs_pct; + int min_policy_pct; + int min_sysfs_pct; +}; + /** * struct cpudata - Per CPU instance data storage * @cpu: CPU number for this instance data @@ -194,6 +236,9 @@ struct _pid { * @prev_cummulative_iowait: IO Wait time difference from last and * current sample * @sample: Storage for storing last Sample data + * @perf_limits: Pointer to perf_limit unique to this CPU + * Not all field in the structure are applicable + * when per cpu controls are enforced * @acpi_perf_data: Stores ACPI perf information read from _PSS * @valid_pss_table: Set to true for valid ACPI _PSS entries found * @@ -217,6 +262,7 @@ struct cpudata { u64 prev_tsc; u64 prev_cummulative_iowait; struct sample sample; + struct perf_limits *perf_limits; #ifdef CONFIG_ACPI struct acpi_processor_performance acpi_perf_data; bool valid_pss_table; @@ -289,51 +335,12 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu); static struct pstate_adjust_policy pid_params __read_mostly; static struct pstate_funcs pstate_funcs __read_mostly; static int hwp_active __read_mostly; +static bool per_cpu_limits __read_mostly; #ifdef CONFIG_ACPI static bool acpi_ppc; #endif -/** - * struct perf_limits - Store user and policy limits - * @no_turbo: User requested turbo state from intel_pstate sysfs - * @turbo_disabled: Platform turbo status either from msr - * MSR_IA32_MISC_ENABLE or when maximum available pstate - * matches the maximum turbo pstate - * @max_perf_pct: Effective maximum performance limit in percentage, this - * is minimum of either limits enforced by cpufreq policy - * or limits from user set limits via intel_pstate sysfs - * @min_perf_pct: Effective minimum performance limit in percentage, this - * is maximum of either limits enforced by cpufreq policy - * or limits from user set limits via intel_pstate sysfs - * @max_perf: This is a scaled value between 0 to 255 for max_perf_pct - * This value is used to limit max pstate - * @min_perf: This is a scaled value between 0 to 255 for min_perf_pct - * This value is used to limit min pstate - * @max_policy_pct: The maximum performance in percentage enforced by - * cpufreq setpolicy interface - * @max_sysfs_pct: The maximum performance in percentage enforced by - * intel pstate sysfs interface - * @min_policy_pct: The minimum performance in percentage enforced by - * cpufreq setpolicy interface - * @min_sysfs_pct: The minimum performance in percentage enforced by - * intel pstate sysfs interface - * - * Storage for user and policy defined limits. - */ -struct perf_limits { - int no_turbo; - int turbo_disabled; - int max_perf_pct; - int min_perf_pct; - int32_t max_perf; - int32_t min_perf; - int max_policy_pct; - int max_sysfs_pct; - int min_policy_pct; - int min_sysfs_pct; -}; - static struct perf_limits performance_limits = { .no_turbo = 0, .turbo_disabled = 0, @@ -560,21 +567,30 @@ static inline void update_turbo_state(void) static void intel_pstate_hwp_set(const struct cpumask *cpumask) { int min, hw_min, max, hw_max, cpu, range, adj_range; + struct perf_limits *perf_limits = limits; u64 value, cap; for_each_cpu(cpu, cpumask) { + int max_perf_pct, min_perf_pct; + + if (per_cpu_limits) + perf_limits = all_cpu_data[cpu]->perf_limits; + rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap); hw_min = HWP_LOWEST_PERF(cap); hw_max = HWP_HIGHEST_PERF(cap); range = hw_max - hw_min; + max_perf_pct = perf_limits->max_perf_pct; + min_perf_pct = perf_limits->min_perf_pct; + rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value); - adj_range = limits->min_perf_pct * range / 100; + adj_range = min_perf_pct * range / 100; min = hw_min + adj_range; value &= ~HWP_MIN_PERF(~0L); value |= HWP_MIN_PERF(min); - adj_range = limits->max_perf_pct * range / 100; + adj_range = max_perf_pct * range / 100; max = hw_min + adj_range; if (limits->no_turbo) { hw_max = HWP_GUARANTEED_PERF(cap); @@ -787,8 +803,6 @@ define_one_global_ro(num_pstates); static struct attribute *intel_pstate_attributes[] = { &no_turbo.attr, - &max_perf_pct.attr, - &min_perf_pct.attr, &turbo_pct.attr, &num_pstates.attr, NULL @@ -805,9 +819,26 @@ static void __init intel_pstate_sysfs_expose_params(void) intel_pstate_kobject = kobject_create_and_add("intel_pstate", &cpu_subsys.dev_root->kobj); - BUG_ON(!intel_pstate_kobject); + if (WARN_ON(!intel_pstate_kobject)) + return; + rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group); - BUG_ON(rc); + if (WARN_ON(rc)) + return; + + /* + * If per cpu limits are enforced there are no global limits, so + * return without creating max/min_perf_pct attributes + */ + if (per_cpu_limits) + return; + + rc = sysfs_create_file(intel_pstate_kobject, &max_perf_pct.attr); + WARN_ON(rc); + + rc = sysfs_create_file(intel_pstate_kobject, &min_perf_pct.attr); + WARN_ON(rc); + } /************************** sysfs end ************************/ @@ -1124,20 +1155,24 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) int max_perf = cpu->pstate.turbo_pstate; int max_perf_adj; int min_perf; + struct perf_limits *perf_limits = limits; if (limits->no_turbo || limits->turbo_disabled) max_perf = cpu->pstate.max_pstate; + if (per_cpu_limits) + perf_limits = cpu->perf_limits; + /* * performance can be limited by user through sysfs, by cpufreq * policy, or by cpu specific default values determined through * experimentation. */ - max_perf_adj = fp_toint(max_perf * limits->max_perf); + max_perf_adj = fp_toint(max_perf * perf_limits->max_perf); *max = clamp_t(int, max_perf_adj, cpu->pstate.min_pstate, cpu->pstate.turbo_pstate); - min_perf = fp_toint(max_perf * limits->min_perf); + min_perf = fp_toint(max_perf * perf_limits->min_perf); *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf); } @@ -1421,11 +1456,23 @@ static int intel_pstate_init_cpu(unsigned int cpunum) { struct cpudata *cpu; - if (!all_cpu_data[cpunum]) - all_cpu_data[cpunum] = kzalloc(sizeof(struct cpudata), - GFP_KERNEL); - if (!all_cpu_data[cpunum]) - return -ENOMEM; + cpu = all_cpu_data[cpunum]; + + if (!cpu) { + unsigned int size = sizeof(struct cpudata); + + if (per_cpu_limits) + size += sizeof(struct perf_limits); + + cpu = kzalloc(size, GFP_KERNEL); + if (!cpu) + return -ENOMEM; + + all_cpu_data[cpunum] = cpu; + if (per_cpu_limits) + cpu->perf_limits = (struct perf_limits *)(cpu + 1); + + } cpu = all_cpu_data[cpunum]; @@ -1493,9 +1540,40 @@ static void intel_pstate_set_performance_limits(struct perf_limits *limits) limits->min_sysfs_pct = 0; } +static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy, + struct perf_limits *limits) +{ + limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; + limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0, 100); + limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100, + policy->cpuinfo.max_freq); + limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0, 100); + + /* Normalize user input to [min_policy_pct, max_policy_pct] */ + limits->min_perf_pct = max(limits->min_policy_pct, + limits->min_sysfs_pct); + limits->min_perf_pct = min(limits->max_policy_pct, + limits->min_perf_pct); + limits->max_perf_pct = min(limits->max_policy_pct, + limits->max_sysfs_pct); + limits->max_perf_pct = max(limits->min_policy_pct, + limits->max_perf_pct); + + /* Make sure min_perf_pct <= max_perf_pct */ + limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct); + + limits->min_perf = div_fp(limits->min_perf_pct, 100); + limits->max_perf = div_fp(limits->max_perf_pct, 100); + limits->max_perf = round_up(limits->max_perf, FRAC_BITS); + + pr_debug("cpu:%d max_perf_pct:%d min_perf_pct:%d\n", policy->cpu, + limits->max_perf_pct, limits->min_perf_pct); +} + static int intel_pstate_set_policy(struct cpufreq_policy *policy) { struct cpudata *cpu; + struct perf_limits *perf_limits = NULL; if (!policy->cpuinfo.max_freq) return -ENODEV; @@ -1513,41 +1591,29 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) policy->max = policy->cpuinfo.max_freq; } - if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) { - limits = &performance_limits; + if (per_cpu_limits) + perf_limits = cpu->perf_limits; + + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { + if (!perf_limits) { + limits = &performance_limits; + perf_limits = limits; + } if (policy->max >= policy->cpuinfo.max_freq) { pr_debug("set performance\n"); - intel_pstate_set_performance_limits(limits); + intel_pstate_set_performance_limits(perf_limits); goto out; } } else { pr_debug("set powersave\n"); - limits = &powersave_limits; - } - - limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; - limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0 , 100); - limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100, - policy->cpuinfo.max_freq); - limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0 , 100); - - /* Normalize user input to [min_policy_pct, max_policy_pct] */ - limits->min_perf_pct = max(limits->min_policy_pct, - limits->min_sysfs_pct); - limits->min_perf_pct = min(limits->max_policy_pct, - limits->min_perf_pct); - limits->max_perf_pct = min(limits->max_policy_pct, - limits->max_sysfs_pct); - limits->max_perf_pct = max(limits->min_policy_pct, - limits->max_perf_pct); - - /* Make sure min_perf_pct <= max_perf_pct */ - limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct); + if (!perf_limits) { + limits = &powersave_limits; + perf_limits = limits; + } - limits->min_perf = div_fp(limits->min_perf_pct, 100); - limits->max_perf = div_fp(limits->max_perf_pct, 100); - limits->max_perf = round_up(limits->max_perf, FRAC_BITS); + } + intel_pstate_update_perf_limits(policy, perf_limits); out: if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) { /* @@ -1607,6 +1673,14 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) else policy->policy = CPUFREQ_POLICY_POWERSAVE; + /* + * We need sane value in the cpu->perf_limits, so inherit from global + * perf_limits limits, which are seeded with values based on the + * CONFIG_CPU_FREQ_DEFAULT_GOV_*, during boot up. + */ + if (per_cpu_limits) + memcpy(cpu->perf_limits, limits, sizeof(struct perf_limits)); + policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling; policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling; @@ -1888,6 +1962,8 @@ static int __init intel_pstate_setup(char *str) force_load = 1; if (!strcmp(str, "hwp_only")) hwp_only = 1; + if (!strcmp(str, "per_cpu_perf_limits")) + per_cpu_limits = true; #ifdef CONFIG_ACPI if (!strcmp(str, "support_acpi_ppc")) -- cgit v1.2.3 From 5879f877398a2a5e5006c6e16a4288e9d4c308a1 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 25 Oct 2016 13:20:41 -0700 Subject: cpufreq: intel_pstate: Reduce impact due to rounding error When policy->max and policy->min are same, in some cases they don't result in the same frequency cap. The max_policy_pct is rounded up but not min_perf_pct. So even when they are same, results in different percentage or maximum and minimum. Since minimum is a conservative value for power, a lower value without rounding is better in most of the cases, unless user wants policy->max = policy->min. This change uses use the same policy percentage when policy->max and policy->min are same. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index b6e9b49bf151..8e7390bb2175 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1543,11 +1543,17 @@ static void intel_pstate_set_performance_limits(struct perf_limits *limits) static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy, struct perf_limits *limits) { - limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; - limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0, 100); limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100, policy->cpuinfo.max_freq); limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0, 100); + if (policy->max == policy->min) { + limits->min_policy_pct = limits->max_policy_pct; + } else { + limits->min_policy_pct = (policy->min * 100) / + policy->cpuinfo.max_freq; + limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, + 0, 100); + } /* Normalize user input to [min_policy_pct, max_policy_pct] */ limits->min_perf_pct = max(limits->min_policy_pct, -- cgit v1.2.3 From 1758b3374bc5b56f60fc07ccc37863a64fc67ecc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 27 Oct 2016 01:41:33 +0900 Subject: cpufreq: dt: add Socionext UniPhier SoCs support Add compatible strings for Pro5, PXs2, LD6b, LD11, LD20 SoCs to use the generic cpufreq driver. Signed-off-by: Masahiro Yamada Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt-platdev.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 142a6f615e52..fba3f61f320c 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -75,6 +75,12 @@ static const struct of_device_id machines[] __initconst = { { .compatible = "sigma,tango4" }, + { .compatible = "socionext,uniphier-pro5", }, + { .compatible = "socionext,uniphier-pxs2", }, + { .compatible = "socionext,uniphier-ld6b", }, + { .compatible = "socionext,uniphier-ld11", }, + { .compatible = "socionext,uniphier-ld20", }, + { .compatible = "ti,am33xx", }, { .compatible = "ti,dra7", }, { .compatible = "ti,omap2", }, -- cgit v1.2.3 From de322e085995b9417582d6f72229dadb5c09d163 Mon Sep 17 00:00:00 2001 From: Markus Mayer Date: Thu, 27 Oct 2016 14:05:35 -0700 Subject: cpufreq: brcmstb-avs-cpufreq: AVS CPUfreq driver for Broadcom STB SoCs This driver supports voltage and frequency scaling on Broadcom STB SoCs using AVS firmware with DFS and DVFS support. Actual frequency or voltage scaling is done exclusively by the AVS firmware. The driver merely provides a standard CPUfreq interface to other kernel components and userland, and instructs the AVS firmware to perform frequency or voltage changes on its behalf. Signed-off-by: Markus Mayer Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- MAINTAINERS | 1 + drivers/cpufreq/Kconfig.arm | 11 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/brcmstb-avs-cpufreq.c | 736 ++++++++++++++++++++++++++++++++++ 4 files changed, 749 insertions(+) create mode 100644 drivers/cpufreq/brcmstb-avs-cpufreq.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 9379aca4bec4..d0ca1198d8ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2744,6 +2744,7 @@ M: bcm-kernel-feedback-list@broadcom.com L: linux-pm@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt +F: drivers/cpufreq/brcmstb* BROADCOM SPECIFIC AMBA DRIVER (BCMA) M: Rafał Miłecki diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index fdbc630272b3..04f7862eacd3 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -12,6 +12,17 @@ config ARM_BIG_LITTLE_CPUFREQ help This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. +config ARM_BRCMSTB_AVS_CPUFREQ + tristate "Broadcom STB AVS CPUfreq driver" + depends on ARCH_BRCMSTB || COMPILE_TEST + default y + help + Some Broadcom STB SoCs use a co-processor running proprietary firmware + ("AVS") to handle voltage and frequency scaling. This driver provides + a standard CPUfreq interface to to the firmware. + + Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS. + config ARM_DT_BL_CPUFREQ tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver" depends on ARM_BIG_LITTLE_CPUFREQ && OF diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 7dde82179d62..1e46c3918e7a 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o # LITTLE drivers, so that it is probed last. obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o +obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c new file mode 100644 index 000000000000..4415fa051283 --- /dev/null +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -0,0 +1,736 @@ +/* + * CPU frequency scaling for Broadcom SoCs with AVS firmware that + * supports DVS or DVFS + * + * Copyright (c) 2016 Broadcom + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * "AVS" is the name of a firmware developed at Broadcom. It derives + * its name from the technique called "Adaptive Voltage Scaling". + * Adaptive voltage scaling was the original purpose of this firmware. + * The AVS firmware still supports "AVS mode", where all it does is + * adaptive voltage scaling. However, on some newer Broadcom SoCs, the + * AVS Firmware, despite its unchanged name, also supports DFS mode and + * DVFS mode. + * + * In the context of this document and the related driver, "AVS" by + * itself always means the Broadcom firmware and never refers to the + * technique called "Adaptive Voltage Scaling". + * + * The Broadcom STB AVS CPUfreq driver provides voltage and frequency + * scaling on Broadcom SoCs using AVS firmware with support for DFS and + * DVFS. The AVS firmware is running on its own co-processor. The + * driver supports both uniprocessor (UP) and symmetric multiprocessor + * (SMP) systems which share clock and voltage across all CPUs. + * + * Actual voltage and frequency scaling is done solely by the AVS + * firmware. This driver does not change frequency or voltage itself. + * It provides a standard CPUfreq interface to the rest of the kernel + * and to userland. It interfaces with the AVS firmware to effect the + * requested changes and to report back the current system status in a + * way that is expected by existing tools. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Max number of arguments AVS calls take */ +#define AVS_MAX_CMD_ARGS 4 +/* + * This macro is used to generate AVS parameter register offsets. For + * x >= AVS_MAX_CMD_ARGS, it returns 0 to protect against accidental memory + * access outside of the parameter range. (Offset 0 is the first parameter.) + */ +#define AVS_PARAM_MULT(x) ((x) < AVS_MAX_CMD_ARGS ? (x) : 0) + +/* AVS Mailbox Register offsets */ +#define AVS_MBOX_COMMAND 0x00 +#define AVS_MBOX_STATUS 0x04 +#define AVS_MBOX_VOLTAGE0 0x08 +#define AVS_MBOX_TEMP0 0x0c +#define AVS_MBOX_PV0 0x10 +#define AVS_MBOX_MV0 0x14 +#define AVS_MBOX_PARAM(x) (0x18 + AVS_PARAM_MULT(x) * sizeof(u32)) +#define AVS_MBOX_REVISION 0x28 +#define AVS_MBOX_PSTATE 0x2c +#define AVS_MBOX_HEARTBEAT 0x30 +#define AVS_MBOX_MAGIC 0x34 +#define AVS_MBOX_SIGMA_HVT 0x38 +#define AVS_MBOX_SIGMA_SVT 0x3c +#define AVS_MBOX_VOLTAGE1 0x40 +#define AVS_MBOX_TEMP1 0x44 +#define AVS_MBOX_PV1 0x48 +#define AVS_MBOX_MV1 0x4c +#define AVS_MBOX_FREQUENCY 0x50 + +/* AVS Commands */ +#define AVS_CMD_AVAILABLE 0x00 +#define AVS_CMD_DISABLE 0x10 +#define AVS_CMD_ENABLE 0x11 +#define AVS_CMD_S2_ENTER 0x12 +#define AVS_CMD_S2_EXIT 0x13 +#define AVS_CMD_BBM_ENTER 0x14 +#define AVS_CMD_BBM_EXIT 0x15 +#define AVS_CMD_S3_ENTER 0x16 +#define AVS_CMD_S3_EXIT 0x17 +#define AVS_CMD_BALANCE 0x18 +/* PMAP and P-STATE commands */ +#define AVS_CMD_GET_PMAP 0x30 +#define AVS_CMD_SET_PMAP 0x31 +#define AVS_CMD_GET_PSTATE 0x40 +#define AVS_CMD_SET_PSTATE 0x41 + +/* Different modes AVS supports (for GET_PMAP/SET_PMAP) */ +#define AVS_MODE_AVS 0x0 +#define AVS_MODE_DFS 0x1 +#define AVS_MODE_DVS 0x2 +#define AVS_MODE_DVFS 0x3 + +/* + * PMAP parameter p1 + * unused:31-24, mdiv_p0:23-16, unused:15-14, pdiv:13-10 , ndiv_int:9-0 + */ +#define NDIV_INT_SHIFT 0 +#define NDIV_INT_MASK 0x3ff +#define PDIV_SHIFT 10 +#define PDIV_MASK 0xf +#define MDIV_P0_SHIFT 16 +#define MDIV_P0_MASK 0xff +/* + * PMAP parameter p2 + * mdiv_p4:31-24, mdiv_p3:23-16, mdiv_p2:15:8, mdiv_p1:7:0 + */ +#define MDIV_P1_SHIFT 0 +#define MDIV_P1_MASK 0xff +#define MDIV_P2_SHIFT 8 +#define MDIV_P2_MASK 0xff +#define MDIV_P3_SHIFT 16 +#define MDIV_P3_MASK 0xff +#define MDIV_P4_SHIFT 24 +#define MDIV_P4_MASK 0xff + +/* Different P-STATES AVS supports (for GET_PSTATE/SET_PSTATE) */ +#define AVS_PSTATE_P0 0x0 +#define AVS_PSTATE_P1 0x1 +#define AVS_PSTATE_P2 0x2 +#define AVS_PSTATE_P3 0x3 +#define AVS_PSTATE_P4 0x4 +#define AVS_PSTATE_MAX AVS_PSTATE_P4 + +/* CPU L2 Interrupt Controller Registers */ +#define AVS_CPU_L2_SET0 0x04 +#define AVS_CPU_L2_INT_MASK BIT(31) + +/* AVS Command Status Values */ +#define AVS_STATUS_CLEAR 0x00 +/* Command/notification accepted */ +#define AVS_STATUS_SUCCESS 0xf0 +/* Command/notification rejected */ +#define AVS_STATUS_FAILURE 0xff +/* Invalid command/notification (unknown) */ +#define AVS_STATUS_INVALID 0xf1 +/* Non-AVS modes are not supported */ +#define AVS_STATUS_NO_SUPP 0xf2 +/* Cannot set P-State until P-Map supplied */ +#define AVS_STATUS_NO_MAP 0xf3 +/* Cannot change P-Map after initial P-Map set */ +#define AVS_STATUS_MAP_SET 0xf4 +/* Max AVS status; higher numbers are used for debugging */ +#define AVS_STATUS_MAX 0xff + +/* Other AVS related constants */ +#define AVS_LOOP_LIMIT 10000 +#define AVS_TIMEOUT 300 /* in ms; expected completion is < 10ms */ +#define AVS_FIRMWARE_MAGIC 0xa11600d1 + +#define BRCM_AVS_CPUFREQ_PREFIX "brcmstb-avs" +#define BRCM_AVS_CPUFREQ_NAME BRCM_AVS_CPUFREQ_PREFIX "-cpufreq" +#define BRCM_AVS_CPU_DATA "brcm,avs-cpu-data-mem" +#define BRCM_AVS_CPU_INTR "brcm,avs-cpu-l2-intr" +#define BRCM_AVS_HOST_INTR "sw_intr" + +struct pmap { + unsigned int mode; + unsigned int p1; + unsigned int p2; + unsigned int state; +}; + +struct private_data { + void __iomem *base; + void __iomem *avs_intr_base; + struct device *dev; + struct completion done; + struct semaphore sem; + struct pmap pmap; +}; + +static void __iomem *__map_region(const char *name) +{ + struct device_node *np; + void __iomem *ptr; + + np = of_find_compatible_node(NULL, NULL, name); + if (!np) + return NULL; + + ptr = of_iomap(np, 0); + of_node_put(np); + + return ptr; +} + +static int __issue_avs_command(struct private_data *priv, int cmd, bool is_send, + u32 args[]) +{ + unsigned long time_left = msecs_to_jiffies(AVS_TIMEOUT); + void __iomem *base = priv->base; + unsigned int i; + int ret; + u32 val; + + ret = down_interruptible(&priv->sem); + if (ret) + return ret; + + /* + * Make sure no other command is currently running: cmd is 0 if AVS + * co-processor is idle. Due to the guard above, we should almost never + * have to wait here. + */ + for (i = 0, val = 1; val != 0 && i < AVS_LOOP_LIMIT; i++) + val = readl(base + AVS_MBOX_COMMAND); + + /* Give the caller a chance to retry if AVS is busy. */ + if (i == AVS_LOOP_LIMIT) { + ret = -EAGAIN; + goto out; + } + + /* Clear status before we begin. */ + writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS); + + /* We need to send arguments for this command. */ + if (args && is_send) { + for (i = 0; i < AVS_MAX_CMD_ARGS; i++) + writel(args[i], base + AVS_MBOX_PARAM(i)); + } + + /* Protect from spurious interrupts. */ + reinit_completion(&priv->done); + + /* Now issue the command & tell firmware to wake up to process it. */ + writel(cmd, base + AVS_MBOX_COMMAND); + writel(AVS_CPU_L2_INT_MASK, priv->avs_intr_base + AVS_CPU_L2_SET0); + + /* Wait for AVS co-processor to finish processing the command. */ + time_left = wait_for_completion_timeout(&priv->done, time_left); + + /* + * If the AVS status is not in the expected range, it means AVS didn't + * complete our command in time, and we return an error. Also, if there + * is no "time left", we timed out waiting for the interrupt. + */ + val = readl(base + AVS_MBOX_STATUS); + if (time_left == 0 || val == 0 || val > AVS_STATUS_MAX) { + dev_err(priv->dev, "AVS command %#x didn't complete in time\n", + cmd); + dev_err(priv->dev, " Time left: %u ms, AVS status: %#x\n", + jiffies_to_msecs(time_left), val); + ret = -ETIMEDOUT; + goto out; + } + + /* This command returned arguments, so we read them back. */ + if (args && !is_send) { + for (i = 0; i < AVS_MAX_CMD_ARGS; i++) + args[i] = readl(base + AVS_MBOX_PARAM(i)); + } + + /* Clear status to tell AVS co-processor we are done. */ + writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS); + + /* Convert firmware errors to errno's as much as possible. */ + switch (val) { + case AVS_STATUS_INVALID: + ret = -EINVAL; + break; + case AVS_STATUS_NO_SUPP: + ret = -ENOTSUPP; + break; + case AVS_STATUS_NO_MAP: + ret = -ENOENT; + break; + case AVS_STATUS_MAP_SET: + ret = -EEXIST; + break; + case AVS_STATUS_FAILURE: + ret = -EIO; + break; + } + +out: + up(&priv->sem); + + return ret; +} + +static irqreturn_t irq_handler(int irq, void *data) +{ + struct private_data *priv = data; + + /* AVS command completed execution. Wake up __issue_avs_command(). */ + complete(&priv->done); + + return IRQ_HANDLED; +} + +static char *brcm_avs_mode_to_string(unsigned int mode) +{ + switch (mode) { + case AVS_MODE_AVS: + return "AVS"; + case AVS_MODE_DFS: + return "DFS"; + case AVS_MODE_DVS: + return "DVS"; + case AVS_MODE_DVFS: + return "DVFS"; + } + return NULL; +} + +static void brcm_avs_parse_p1(u32 p1, unsigned int *mdiv_p0, unsigned int *pdiv, + unsigned int *ndiv) +{ + *mdiv_p0 = (p1 >> MDIV_P0_SHIFT) & MDIV_P0_MASK; + *pdiv = (p1 >> PDIV_SHIFT) & PDIV_MASK; + *ndiv = (p1 >> NDIV_INT_SHIFT) & NDIV_INT_MASK; +} + +static void brcm_avs_parse_p2(u32 p2, unsigned int *mdiv_p1, + unsigned int *mdiv_p2, unsigned int *mdiv_p3, + unsigned int *mdiv_p4) +{ + *mdiv_p4 = (p2 >> MDIV_P4_SHIFT) & MDIV_P4_MASK; + *mdiv_p3 = (p2 >> MDIV_P3_SHIFT) & MDIV_P3_MASK; + *mdiv_p2 = (p2 >> MDIV_P2_SHIFT) & MDIV_P2_MASK; + *mdiv_p1 = (p2 >> MDIV_P1_SHIFT) & MDIV_P1_MASK; +} + +static int brcm_avs_get_pmap(struct private_data *priv, struct pmap *pmap) +{ + u32 args[AVS_MAX_CMD_ARGS]; + int ret; + + ret = __issue_avs_command(priv, AVS_CMD_GET_PMAP, false, args); + if (ret || !pmap) + return ret; + + pmap->mode = args[0]; + pmap->p1 = args[1]; + pmap->p2 = args[2]; + pmap->state = args[3]; + + return 0; +} + +static int brcm_avs_set_pmap(struct private_data *priv, struct pmap *pmap) +{ + u32 args[AVS_MAX_CMD_ARGS]; + + args[0] = pmap->mode; + args[1] = pmap->p1; + args[2] = pmap->p2; + args[3] = pmap->state; + + return __issue_avs_command(priv, AVS_CMD_SET_PMAP, true, args); +} + +static int brcm_avs_get_pstate(struct private_data *priv, unsigned int *pstate) +{ + u32 args[AVS_MAX_CMD_ARGS]; + int ret; + + ret = __issue_avs_command(priv, AVS_CMD_GET_PSTATE, false, args); + if (ret) + return ret; + *pstate = args[0]; + + return 0; +} + +static int brcm_avs_set_pstate(struct private_data *priv, unsigned int pstate) +{ + u32 args[AVS_MAX_CMD_ARGS]; + + args[0] = pstate; + + return __issue_avs_command(priv, AVS_CMD_SET_PSTATE, true, args); +} + +static unsigned long brcm_avs_get_voltage(void __iomem *base) +{ + return readl(base + AVS_MBOX_VOLTAGE1); +} + +static unsigned long brcm_avs_get_frequency(void __iomem *base) +{ + return readl(base + AVS_MBOX_FREQUENCY) * 1000; /* in kHz */ +} + +/* + * We determine which frequencies are supported by cycling through all P-states + * and reading back what frequency we are running at for each P-state. + */ +static struct cpufreq_frequency_table * +brcm_avs_get_freq_table(struct device *dev, struct private_data *priv) +{ + struct cpufreq_frequency_table *table; + unsigned int pstate; + int i, ret; + + /* Remember P-state for later */ + ret = brcm_avs_get_pstate(priv, &pstate); + if (ret) + return ERR_PTR(ret); + + table = devm_kzalloc(dev, (AVS_PSTATE_MAX + 1) * sizeof(*table), + GFP_KERNEL); + if (!table) + return ERR_PTR(-ENOMEM); + + for (i = AVS_PSTATE_P0; i <= AVS_PSTATE_MAX; i++) { + ret = brcm_avs_set_pstate(priv, i); + if (ret) + return ERR_PTR(ret); + table[i].frequency = brcm_avs_get_frequency(priv->base); + table[i].driver_data = i; + } + table[i].frequency = CPUFREQ_TABLE_END; + + /* Restore P-state */ + ret = brcm_avs_set_pstate(priv, pstate); + if (ret) + return ERR_PTR(ret); + + return table; +} + +/* + * To ensure the right firmware is running we need to + * - check the MAGIC matches what we expect + * - brcm_avs_get_pmap() doesn't return -ENOTSUPP or -EINVAL + * We need to set up our interrupt handling before calling brcm_avs_get_pmap()! + */ +static bool brcm_avs_is_firmware_loaded(struct private_data *priv) +{ + u32 magic; + int rc; + + rc = brcm_avs_get_pmap(priv, NULL); + magic = readl(priv->base + AVS_MBOX_MAGIC); + + return (magic == AVS_FIRMWARE_MAGIC) && (rc != -ENOTSUPP) && + (rc != -EINVAL); +} + +static unsigned int brcm_avs_cpufreq_get(unsigned int cpu) +{ + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + struct private_data *priv = policy->driver_data; + + return brcm_avs_get_frequency(priv->base); +} + +static int brcm_avs_target_index(struct cpufreq_policy *policy, + unsigned int index) +{ + return brcm_avs_set_pstate(policy->driver_data, + policy->freq_table[index].driver_data); +} + +static int brcm_avs_suspend(struct cpufreq_policy *policy) +{ + struct private_data *priv = policy->driver_data; + + return brcm_avs_get_pmap(priv, &priv->pmap); +} + +static int brcm_avs_resume(struct cpufreq_policy *policy) +{ + struct private_data *priv = policy->driver_data; + int ret; + + ret = brcm_avs_set_pmap(priv, &priv->pmap); + if (ret == -EEXIST) { + struct platform_device *pdev = cpufreq_get_driver_data(); + struct device *dev = &pdev->dev; + + dev_warn(dev, "PMAP was already set\n"); + ret = 0; + } + + return ret; +} + +/* + * All initialization code that we only want to execute once goes here. Setup + * code that can be re-tried on every core (if it failed before) can go into + * brcm_avs_cpufreq_init(). + */ +static int brcm_avs_prepare_init(struct platform_device *pdev) +{ + struct private_data *priv; + struct device *dev; + int host_irq, ret; + + dev = &pdev->dev; + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + sema_init(&priv->sem, 1); + init_completion(&priv->done); + platform_set_drvdata(pdev, priv); + + priv->base = __map_region(BRCM_AVS_CPU_DATA); + if (!priv->base) { + dev_err(dev, "Couldn't find property %s in device tree.\n", + BRCM_AVS_CPU_DATA); + return -ENOENT; + } + + priv->avs_intr_base = __map_region(BRCM_AVS_CPU_INTR); + if (!priv->avs_intr_base) { + dev_err(dev, "Couldn't find property %s in device tree.\n", + BRCM_AVS_CPU_INTR); + ret = -ENOENT; + goto unmap_base; + } + + host_irq = platform_get_irq_byname(pdev, BRCM_AVS_HOST_INTR); + if (host_irq < 0) { + dev_err(dev, "Couldn't find interrupt %s -- %d\n", + BRCM_AVS_HOST_INTR, host_irq); + ret = host_irq; + goto unmap_intr_base; + } + + ret = devm_request_irq(dev, host_irq, irq_handler, IRQF_TRIGGER_RISING, + BRCM_AVS_HOST_INTR, priv); + if (ret) { + dev_err(dev, "IRQ request failed: %s (%d) -- %d\n", + BRCM_AVS_HOST_INTR, host_irq, ret); + goto unmap_intr_base; + } + + if (brcm_avs_is_firmware_loaded(priv)) + return 0; + + dev_err(dev, "AVS firmware is not loaded or doesn't support DVFS\n"); + ret = -ENODEV; + +unmap_intr_base: + iounmap(priv->avs_intr_base); +unmap_base: + iounmap(priv->base); + platform_set_drvdata(pdev, NULL); + + return ret; +} + +static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy) +{ + struct cpufreq_frequency_table *freq_table; + struct platform_device *pdev; + struct private_data *priv; + struct device *dev; + int ret; + + pdev = cpufreq_get_driver_data(); + priv = platform_get_drvdata(pdev); + policy->driver_data = priv; + dev = &pdev->dev; + + freq_table = brcm_avs_get_freq_table(dev, priv); + if (IS_ERR(freq_table)) { + ret = PTR_ERR(freq_table); + dev_err(dev, "Couldn't determine frequency table (%d).\n", ret); + return ret; + } + + ret = cpufreq_table_validate_and_show(policy, freq_table); + if (ret) { + dev_err(dev, "invalid frequency table: %d\n", ret); + return ret; + } + + /* All cores share the same clock and thus the same policy. */ + cpumask_setall(policy->cpus); + + ret = __issue_avs_command(priv, AVS_CMD_ENABLE, false, NULL); + if (!ret) { + unsigned int pstate; + + ret = brcm_avs_get_pstate(priv, &pstate); + if (!ret) { + policy->cur = freq_table[pstate].frequency; + dev_info(dev, "registered\n"); + return 0; + } + } + + dev_err(dev, "couldn't initialize driver (%d)\n", ret); + + return ret; +} + +static ssize_t show_brcm_avs_pstate(struct cpufreq_policy *policy, char *buf) +{ + struct private_data *priv = policy->driver_data; + unsigned int pstate; + + if (brcm_avs_get_pstate(priv, &pstate)) + return sprintf(buf, "\n"); + + return sprintf(buf, "%u\n", pstate); +} + +static ssize_t show_brcm_avs_mode(struct cpufreq_policy *policy, char *buf) +{ + struct private_data *priv = policy->driver_data; + struct pmap pmap; + + if (brcm_avs_get_pmap(priv, &pmap)) + return sprintf(buf, "\n"); + + return sprintf(buf, "%s %u\n", brcm_avs_mode_to_string(pmap.mode), + pmap.mode); +} + +static ssize_t show_brcm_avs_pmap(struct cpufreq_policy *policy, char *buf) +{ + unsigned int mdiv_p0, mdiv_p1, mdiv_p2, mdiv_p3, mdiv_p4; + struct private_data *priv = policy->driver_data; + unsigned int ndiv, pdiv; + struct pmap pmap; + + if (brcm_avs_get_pmap(priv, &pmap)) + return sprintf(buf, "\n"); + + brcm_avs_parse_p1(pmap.p1, &mdiv_p0, &pdiv, &ndiv); + brcm_avs_parse_p2(pmap.p2, &mdiv_p1, &mdiv_p2, &mdiv_p3, &mdiv_p4); + + return sprintf(buf, "0x%08x 0x%08x %u %u %u %u %u %u %u\n", + pmap.p1, pmap.p2, ndiv, pdiv, mdiv_p0, mdiv_p1, mdiv_p2, + mdiv_p3, mdiv_p4); +} + +static ssize_t show_brcm_avs_voltage(struct cpufreq_policy *policy, char *buf) +{ + struct private_data *priv = policy->driver_data; + + return sprintf(buf, "0x%08lx\n", brcm_avs_get_voltage(priv->base)); +} + +static ssize_t show_brcm_avs_frequency(struct cpufreq_policy *policy, char *buf) +{ + struct private_data *priv = policy->driver_data; + + return sprintf(buf, "0x%08lx\n", brcm_avs_get_frequency(priv->base)); +} + +cpufreq_freq_attr_ro(brcm_avs_pstate); +cpufreq_freq_attr_ro(brcm_avs_mode); +cpufreq_freq_attr_ro(brcm_avs_pmap); +cpufreq_freq_attr_ro(brcm_avs_voltage); +cpufreq_freq_attr_ro(brcm_avs_frequency); + +struct freq_attr *brcm_avs_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + &brcm_avs_pstate, + &brcm_avs_mode, + &brcm_avs_pmap, + &brcm_avs_voltage, + &brcm_avs_frequency, + NULL +}; + +static struct cpufreq_driver brcm_avs_driver = { + .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, + .verify = cpufreq_generic_frequency_table_verify, + .target_index = brcm_avs_target_index, + .get = brcm_avs_cpufreq_get, + .suspend = brcm_avs_suspend, + .resume = brcm_avs_resume, + .init = brcm_avs_cpufreq_init, + .attr = brcm_avs_cpufreq_attr, + .name = BRCM_AVS_CPUFREQ_PREFIX, +}; + +static int brcm_avs_cpufreq_probe(struct platform_device *pdev) +{ + int ret; + + ret = brcm_avs_prepare_init(pdev); + if (ret) + return ret; + + brcm_avs_driver.driver_data = pdev; + + return cpufreq_register_driver(&brcm_avs_driver); +} + +static int brcm_avs_cpufreq_remove(struct platform_device *pdev) +{ + struct private_data *priv; + int ret; + + ret = cpufreq_unregister_driver(&brcm_avs_driver); + if (ret) + return ret; + + priv = platform_get_drvdata(pdev); + iounmap(priv->base); + iounmap(priv->avs_intr_base); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static const struct of_device_id brcm_avs_cpufreq_match[] = { + { .compatible = BRCM_AVS_CPU_DATA }, + { } +}; +MODULE_DEVICE_TABLE(of, brcm_avs_cpufreq_match); + +static struct platform_driver brcm_avs_cpufreq_platdrv = { + .driver = { + .name = BRCM_AVS_CPUFREQ_NAME, + .of_match_table = brcm_avs_cpufreq_match, + }, + .probe = brcm_avs_cpufreq_probe, + .remove = brcm_avs_cpufreq_remove, +}; +module_platform_driver(brcm_avs_cpufreq_platdrv); + +MODULE_AUTHOR("Markus Mayer "); +MODULE_DESCRIPTION("CPUfreq driver for Broadcom STB AVS"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 33de45c133b40a129a880c175af4c2bb39dafc88 Mon Sep 17 00:00:00 2001 From: Markus Mayer Date: Thu, 27 Oct 2016 14:05:36 -0700 Subject: cpufreq: brcmstb-avs-cpufreq: add debugfs support In order to aid debugging, we add a debugfs interface to the driver that allows direct interaction with the AVS co-processor. The debugfs interface provides a means for reading all and writing some of the mailbox registers directly from the shell prompt and enables a user to execute the communications protocol between ARM CPU and AVS CPU step-by-step. This interface should be used for debugging purposes only. Signed-off-by: Markus Mayer Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/Kconfig.arm | 10 ++ drivers/cpufreq/brcmstb-avs-cpufreq.c | 323 +++++++++++++++++++++++++++++++++- 2 files changed, 332 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 04f7862eacd3..920c469f3953 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -23,6 +23,16 @@ config ARM_BRCMSTB_AVS_CPUFREQ Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS. +config ARM_BRCMSTB_AVS_CPUFREQ_DEBUG + bool "Broadcom STB AVS CPUfreq driver sysfs debug capability" + depends on ARM_BRCMSTB_AVS_CPUFREQ + help + Enabling this option turns on debug support via sysfs under + /sys/kernel/debug/brcmstb-avs-cpufreq. It is possible to read all and + write some AVS mailbox registers through sysfs entries. + + If in doubt, say N. + config ARM_DT_BL_CPUFREQ tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver" depends on ARM_BIG_LITTLE_CPUFREQ && OF diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c index 4415fa051283..b761d54bb08d 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -49,6 +49,13 @@ #include #include +#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG +#include +#include +#include +#include +#endif + /* Max number of arguments AVS calls take */ #define AVS_MAX_CMD_ARGS 4 /* @@ -175,11 +182,88 @@ struct private_data { void __iomem *base; void __iomem *avs_intr_base; struct device *dev; +#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG + struct dentry *debugfs; +#endif struct completion done; struct semaphore sem; struct pmap pmap; }; +#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG + +enum debugfs_format { + DEBUGFS_NORMAL, + DEBUGFS_FLOAT, + DEBUGFS_REV, +}; + +struct debugfs_data { + struct debugfs_entry *entry; + struct private_data *priv; +}; + +struct debugfs_entry { + char *name; + u32 offset; + fmode_t mode; + enum debugfs_format format; +}; + +#define DEBUGFS_ENTRY(name, mode, format) { \ + #name, AVS_MBOX_##name, mode, format \ +} + +/* + * These are used for debugfs only. Otherwise we use AVS_MBOX_PARAM() directly. + */ +#define AVS_MBOX_PARAM1 AVS_MBOX_PARAM(0) +#define AVS_MBOX_PARAM2 AVS_MBOX_PARAM(1) +#define AVS_MBOX_PARAM3 AVS_MBOX_PARAM(2) +#define AVS_MBOX_PARAM4 AVS_MBOX_PARAM(3) + +/* + * This table stores the name, access permissions and offset for each hardware + * register and is used to generate debugfs entries. + */ +static struct debugfs_entry debugfs_entries[] = { + DEBUGFS_ENTRY(COMMAND, S_IWUSR, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(STATUS, S_IWUSR, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(VOLTAGE0, 0, DEBUGFS_FLOAT), + DEBUGFS_ENTRY(TEMP0, 0, DEBUGFS_FLOAT), + DEBUGFS_ENTRY(PV0, 0, DEBUGFS_FLOAT), + DEBUGFS_ENTRY(MV0, 0, DEBUGFS_FLOAT), + DEBUGFS_ENTRY(PARAM1, S_IWUSR, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(PARAM2, S_IWUSR, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(PARAM3, S_IWUSR, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(PARAM4, S_IWUSR, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(REVISION, 0, DEBUGFS_REV), + DEBUGFS_ENTRY(PSTATE, 0, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(HEARTBEAT, 0, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(MAGIC, S_IWUSR, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(SIGMA_HVT, 0, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(SIGMA_SVT, 0, DEBUGFS_NORMAL), + DEBUGFS_ENTRY(VOLTAGE1, 0, DEBUGFS_FLOAT), + DEBUGFS_ENTRY(TEMP1, 0, DEBUGFS_FLOAT), + DEBUGFS_ENTRY(PV1, 0, DEBUGFS_FLOAT), + DEBUGFS_ENTRY(MV1, 0, DEBUGFS_FLOAT), + DEBUGFS_ENTRY(FREQUENCY, 0, DEBUGFS_NORMAL), +}; + +static int brcm_avs_target_index(struct cpufreq_policy *, unsigned int); + +static char *__strtolower(char *s) +{ + char *p; + + for (p = s; *p; p++) + *p = tolower(*p); + + return s; +} + +#endif /* CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG */ + static void __iomem *__map_region(const char *name) { struct device_node *np; @@ -432,6 +516,238 @@ brcm_avs_get_freq_table(struct device *dev, struct private_data *priv) return table; } +#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG + +#define MANT(x) (unsigned int)(abs((x)) / 1000) +#define FRAC(x) (unsigned int)(abs((x)) - abs((x)) / 1000 * 1000) + +static int brcm_avs_debug_show(struct seq_file *s, void *data) +{ + struct debugfs_data *dbgfs = s->private; + void __iomem *base; + u32 val, offset; + + if (!dbgfs) { + seq_puts(s, "No device pointer\n"); + return 0; + } + + base = dbgfs->priv->base; + offset = dbgfs->entry->offset; + val = readl(base + offset); + switch (dbgfs->entry->format) { + case DEBUGFS_NORMAL: + seq_printf(s, "%u\n", val); + break; + case DEBUGFS_FLOAT: + seq_printf(s, "%d.%03d\n", MANT(val), FRAC(val)); + break; + case DEBUGFS_REV: + seq_printf(s, "%c.%c.%c.%c\n", (val >> 24 & 0xff), + (val >> 16 & 0xff), (val >> 8 & 0xff), + val & 0xff); + break; + } + seq_printf(s, "0x%08x\n", val); + + return 0; +} + +#undef MANT +#undef FRAC + +static ssize_t brcm_avs_seq_write(struct file *file, const char __user *buf, + size_t size, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct debugfs_data *dbgfs = s->private; + struct private_data *priv = dbgfs->priv; + void __iomem *base, *avs_intr_base; + bool use_issue_command = false; + unsigned long val, offset; + char str[128]; + int ret; + char *str_ptr = str; + + if (size >= sizeof(str)) + return -E2BIG; + + memset(str, 0, sizeof(str)); + ret = copy_from_user(str, buf, size); + if (ret) + return ret; + + base = priv->base; + avs_intr_base = priv->avs_intr_base; + offset = dbgfs->entry->offset; + /* + * Special case writing to "command" entry only: if the string starts + * with a 'c', we use the driver's __issue_avs_command() function. + * Otherwise, we perform a raw write. This should allow testing of raw + * access as well as using the higher level function. (Raw access + * doesn't clear the firmware return status after issuing the command.) + */ + if (str_ptr[0] == 'c' && offset == AVS_MBOX_COMMAND) { + use_issue_command = true; + str_ptr++; + } + if (kstrtoul(str_ptr, 0, &val) != 0) + return -EINVAL; + + /* + * Setting the P-state is a special case. We need to update the CPU + * frequency we report. + */ + if (val == AVS_CMD_SET_PSTATE) { + struct cpufreq_policy *policy; + unsigned int pstate; + + policy = cpufreq_cpu_get(smp_processor_id()); + /* Read back the P-state we are about to set */ + pstate = readl(base + AVS_MBOX_PARAM(0)); + if (use_issue_command) { + ret = brcm_avs_target_index(policy, pstate); + return ret ? ret : size; + } + policy->cur = policy->freq_table[pstate].frequency; + } + + if (use_issue_command) { + ret = __issue_avs_command(priv, val, false, NULL); + } else { + /* Locking here is not perfect, but is only for debug. */ + ret = down_interruptible(&priv->sem); + if (ret) + return ret; + + writel(val, base + offset); + /* We have to wake up the firmware to process a command. */ + if (offset == AVS_MBOX_COMMAND) + writel(AVS_CPU_L2_INT_MASK, + avs_intr_base + AVS_CPU_L2_SET0); + up(&priv->sem); + } + + return ret ? ret : size; +} + +static struct debugfs_entry *__find_debugfs_entry(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(debugfs_entries); i++) + if (strcasecmp(debugfs_entries[i].name, name) == 0) + return &debugfs_entries[i]; + + return NULL; +} + +static int brcm_avs_debug_open(struct inode *inode, struct file *file) +{ + struct debugfs_data *data; + fmode_t fmode; + int ret; + + /* + * seq_open(), which is called by single_open(), clears "write" access. + * We need write access to some files, so we preserve our access mode + * and restore it. + */ + fmode = file->f_mode; + /* + * Check access permissions even for root. We don't want to be writing + * to read-only registers. Access for regular users has already been + * checked by the VFS layer. + */ + if ((fmode & FMODE_WRITER) && !(inode->i_mode & S_IWUSR)) + return -EACCES; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + /* + * We use the same file system operations for all our debug files. To + * produce specific output, we look up the file name upon opening a + * debugfs entry and map it to a memory offset. This offset is then used + * in the generic "show" function to read a specific register. + */ + data->entry = __find_debugfs_entry(file->f_path.dentry->d_iname); + data->priv = inode->i_private; + + ret = single_open(file, brcm_avs_debug_show, data); + if (ret) + kfree(data); + file->f_mode = fmode; + + return ret; +} + +static int brcm_avs_debug_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq_priv = file->private_data; + struct debugfs_data *data = seq_priv->private; + + kfree(data); + return single_release(inode, file); +} + +static const struct file_operations brcm_avs_debug_ops = { + .open = brcm_avs_debug_open, + .read = seq_read, + .write = brcm_avs_seq_write, + .llseek = seq_lseek, + .release = brcm_avs_debug_release, +}; + +static void brcm_avs_cpufreq_debug_init(struct platform_device *pdev) +{ + struct private_data *priv = platform_get_drvdata(pdev); + struct dentry *dir; + int i; + + if (!priv) + return; + + dir = debugfs_create_dir(BRCM_AVS_CPUFREQ_NAME, NULL); + if (IS_ERR_OR_NULL(dir)) + return; + priv->debugfs = dir; + + for (i = 0; i < ARRAY_SIZE(debugfs_entries); i++) { + /* + * The DEBUGFS_ENTRY macro generates uppercase strings. We + * convert them to lowercase before creating the debugfs + * entries. + */ + char *entry = __strtolower(debugfs_entries[i].name); + fmode_t mode = debugfs_entries[i].mode; + + if (!debugfs_create_file(entry, S_IFREG | S_IRUGO | mode, + dir, priv, &brcm_avs_debug_ops)) { + priv->debugfs = NULL; + debugfs_remove_recursive(dir); + break; + } + } +} + +static void brcm_avs_cpufreq_debug_exit(struct platform_device *pdev) +{ + struct private_data *priv = platform_get_drvdata(pdev); + + if (priv && priv->debugfs) { + debugfs_remove_recursive(priv->debugfs); + priv->debugfs = NULL; + } +} + +#else + +static void brcm_avs_cpufreq_debug_init(struct platform_device *pdev) {} +static void brcm_avs_cpufreq_debug_exit(struct platform_device *pdev) {} + +#endif /* CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG */ + /* * To ensure the right firmware is running we need to * - check the MAGIC matches what we expect @@ -694,8 +1010,11 @@ static int brcm_avs_cpufreq_probe(struct platform_device *pdev) return ret; brcm_avs_driver.driver_data = pdev; + ret = cpufreq_register_driver(&brcm_avs_driver); + if (!ret) + brcm_avs_cpufreq_debug_init(pdev); - return cpufreq_register_driver(&brcm_avs_driver); + return ret; } static int brcm_avs_cpufreq_remove(struct platform_device *pdev) @@ -707,6 +1026,8 @@ static int brcm_avs_cpufreq_remove(struct platform_device *pdev) if (ret) return ret; + brcm_avs_cpufreq_debug_exit(pdev); + priv = platform_get_drvdata(pdev); iounmap(priv->base); iounmap(priv->avs_intr_base); -- cgit v1.2.3 From a410c03d668122923ab9b17c0c5728b520edddb4 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 28 Oct 2016 10:44:52 -0700 Subject: cpufreq: intel_pstate: protect limits variable The limits variable gets modified from intel_pstate sysfs and also gets modified from cpufreq sysfs. So protect with a mutex to keep data integrity, when they are getting modified from multiple threads. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 8e7390bb2175..0837175395b9 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -373,6 +373,8 @@ static struct perf_limits *limits = &performance_limits; static struct perf_limits *limits = &powersave_limits; #endif +static DEFINE_MUTEX(intel_pstate_limits_lock); + #ifdef CONFIG_ACPI static bool intel_pstate_get_ppc_enable_status(void) @@ -730,14 +732,19 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, if (ret != 1) return -EINVAL; + mutex_lock(&intel_pstate_limits_lock); + update_turbo_state(); if (limits->turbo_disabled) { pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); + mutex_unlock(&intel_pstate_limits_lock); return -EPERM; } limits->no_turbo = clamp_t(int, input, 0, 1); + mutex_unlock(&intel_pstate_limits_lock); + if (hwp_active) intel_pstate_hwp_set_online_cpus(); @@ -754,6 +761,8 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, if (ret != 1) return -EINVAL; + mutex_lock(&intel_pstate_limits_lock); + limits->max_sysfs_pct = clamp_t(int, input, 0 , 100); limits->max_perf_pct = min(limits->max_policy_pct, limits->max_sysfs_pct); @@ -763,6 +772,8 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, limits->max_perf_pct); limits->max_perf = div_fp(limits->max_perf_pct, 100); + mutex_unlock(&intel_pstate_limits_lock); + if (hwp_active) intel_pstate_hwp_set_online_cpus(); return count; @@ -778,6 +789,8 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, if (ret != 1) return -EINVAL; + mutex_lock(&intel_pstate_limits_lock); + limits->min_sysfs_pct = clamp_t(int, input, 0 , 100); limits->min_perf_pct = max(limits->min_policy_pct, limits->min_sysfs_pct); @@ -787,6 +800,8 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, limits->min_perf_pct); limits->min_perf = div_fp(limits->min_perf_pct, 100); + mutex_unlock(&intel_pstate_limits_lock); + if (hwp_active) intel_pstate_hwp_set_online_cpus(); return count; @@ -1528,6 +1543,7 @@ static void intel_pstate_clear_update_util_hook(unsigned int cpu) static void intel_pstate_set_performance_limits(struct perf_limits *limits) { + mutex_lock(&intel_pstate_limits_lock); limits->no_turbo = 0; limits->turbo_disabled = 0; limits->max_perf_pct = 100; @@ -1538,11 +1554,15 @@ static void intel_pstate_set_performance_limits(struct perf_limits *limits) limits->max_sysfs_pct = 100; limits->min_policy_pct = 0; limits->min_sysfs_pct = 0; + mutex_unlock(&intel_pstate_limits_lock); } static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy, struct perf_limits *limits) { + + mutex_lock(&intel_pstate_limits_lock); + limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100, policy->cpuinfo.max_freq); limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0, 100); @@ -1572,6 +1592,8 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy, limits->max_perf = div_fp(limits->max_perf_pct, 100); limits->max_perf = round_up(limits->max_perf, FRAC_BITS); + mutex_unlock(&intel_pstate_limits_lock); + pr_debug("cpu:%d max_perf_pct:%d min_perf_pct:%d\n", policy->cpu, limits->max_perf_pct, limits->min_perf_pct); } -- cgit v1.2.3 From 5a83d60c074ddf4f6364be25654a643d0e941824 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Mon, 31 Oct 2016 15:18:44 -0700 Subject: x86/fpu: Remove irq_ts_save() and irq_ts_restore() Now that lazy FPU is gone, we don't use CR0.TS (except possibly in KVM guest mode). Remove irq_ts_save(), irq_ts_restore(), and all of their callers. Signed-off-by: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Rik van Riel Cc: Rusty Russell Cc: Thomas Gleixner Cc: kvm list Link: http://lkml.kernel.org/r/70b9b9e7ba70659bedcb08aba63d0f9214f338f2.1477951965.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/fpu/api.h | 10 ---------- arch/x86/kernel/fpu/core.c | 29 ----------------------------- drivers/char/hw_random/via-rng.c | 8 ++------ drivers/crypto/padlock-aes.c | 23 ++--------------------- drivers/crypto/padlock-sha.c | 18 ------------------ 5 files changed, 4 insertions(+), 84 deletions(-) (limited to 'drivers') diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h index 1429a7c736db..0877ae018fc9 100644 --- a/arch/x86/include/asm/fpu/api.h +++ b/arch/x86/include/asm/fpu/api.h @@ -26,16 +26,6 @@ extern void kernel_fpu_begin(void); extern void kernel_fpu_end(void); extern bool irq_fpu_usable(void); -/* - * Some instructions like VIA's padlock instructions generate a spurious - * DNA fault but don't modify SSE registers. And these instructions - * get used from interrupt context as well. To prevent these kernel instructions - * in interrupt context interacting wrongly with other user/kernel fpu usage, we - * should use them only in the context of irq_ts_save/restore() - */ -extern int irq_ts_save(void); -extern void irq_ts_restore(int TS_state); - /* * Query the presence of one or more xfeatures. Works on any legacy CPU as well. * diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 52f5684405c1..7d8e2628e82c 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -137,35 +137,6 @@ void kernel_fpu_end(void) } EXPORT_SYMBOL_GPL(kernel_fpu_end); -/* - * CR0::TS save/restore functions: - */ -int irq_ts_save(void) -{ - /* - * If in process context and not atomic, we can take a spurious DNA fault. - * Otherwise, doing clts() in process context requires disabling preemption - * or some heavy lifting like kernel_fpu_begin() - */ - if (!in_atomic()) - return 0; - - if (read_cr0() & X86_CR0_TS) { - clts(); - return 1; - } - - return 0; -} -EXPORT_SYMBOL_GPL(irq_ts_save); - -void irq_ts_restore(int TS_state) -{ - if (TS_state) - stts(); -} -EXPORT_SYMBOL_GPL(irq_ts_restore); - /* * Save the FPU state (mark it for reload if necessary): * diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 44ce80606944..d1f5bb534e0e 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c @@ -70,21 +70,17 @@ enum { * until we have 4 bytes, thus returning a u32 at a time, * instead of the current u8-at-a-time. * - * Padlock instructions can generate a spurious DNA fault, so - * we have to call them in the context of irq_ts_save/restore() + * Padlock instructions can generate a spurious DNA fault, but the + * kernel doesn't use CR0.TS, so this doesn't matter. */ static inline u32 xstore(u32 *addr, u32 edx_in) { u32 eax_out; - int ts_state; - - ts_state = irq_ts_save(); asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" : "=m" (*addr), "=a" (eax_out), "+d" (edx_in), "+D" (addr)); - irq_ts_restore(ts_state); return eax_out; } diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 441e86b23571..b3869748cc6b 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -183,8 +183,8 @@ static inline void padlock_store_cword(struct cword *cword) /* * While the padlock instructions don't use FP/SSE registers, they - * generate a spurious DNA fault when cr0.ts is '1'. These instructions - * should be used only inside the irq_ts_save/restore() context + * generate a spurious DNA fault when CR0.TS is '1'. Fortunately, + * the kernel doesn't use CR0.TS. */ static inline void rep_xcrypt_ecb(const u8 *input, u8 *output, void *key, @@ -298,24 +298,18 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct aes_ctx *ctx = aes_ctx(tfm); - int ts_state; padlock_reset_key(&ctx->cword.encrypt); - ts_state = irq_ts_save(); ecb_crypt(in, out, ctx->E, &ctx->cword.encrypt, 1); - irq_ts_restore(ts_state); padlock_store_cword(&ctx->cword.encrypt); } static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct aes_ctx *ctx = aes_ctx(tfm); - int ts_state; padlock_reset_key(&ctx->cword.encrypt); - ts_state = irq_ts_save(); ecb_crypt(in, out, ctx->D, &ctx->cword.decrypt, 1); - irq_ts_restore(ts_state); padlock_store_cword(&ctx->cword.encrypt); } @@ -346,14 +340,12 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc, struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); struct blkcipher_walk walk; int err; - int ts_state; padlock_reset_key(&ctx->cword.encrypt); blkcipher_walk_init(&walk, dst, src, nbytes); err = blkcipher_walk_virt(desc, &walk); - ts_state = irq_ts_save(); while ((nbytes = walk.nbytes)) { padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr, ctx->E, &ctx->cword.encrypt, @@ -361,7 +353,6 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc, nbytes &= AES_BLOCK_SIZE - 1; err = blkcipher_walk_done(desc, &walk, nbytes); } - irq_ts_restore(ts_state); padlock_store_cword(&ctx->cword.encrypt); @@ -375,14 +366,12 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc, struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); struct blkcipher_walk walk; int err; - int ts_state; padlock_reset_key(&ctx->cword.decrypt); blkcipher_walk_init(&walk, dst, src, nbytes); err = blkcipher_walk_virt(desc, &walk); - ts_state = irq_ts_save(); while ((nbytes = walk.nbytes)) { padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr, ctx->D, &ctx->cword.decrypt, @@ -390,7 +379,6 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc, nbytes &= AES_BLOCK_SIZE - 1; err = blkcipher_walk_done(desc, &walk, nbytes); } - irq_ts_restore(ts_state); padlock_store_cword(&ctx->cword.encrypt); @@ -425,14 +413,12 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc, struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); struct blkcipher_walk walk; int err; - int ts_state; padlock_reset_key(&ctx->cword.encrypt); blkcipher_walk_init(&walk, dst, src, nbytes); err = blkcipher_walk_virt(desc, &walk); - ts_state = irq_ts_save(); while ((nbytes = walk.nbytes)) { u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr, ctx->E, @@ -442,7 +428,6 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc, nbytes &= AES_BLOCK_SIZE - 1; err = blkcipher_walk_done(desc, &walk, nbytes); } - irq_ts_restore(ts_state); padlock_store_cword(&ctx->cword.decrypt); @@ -456,14 +441,12 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc, struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); struct blkcipher_walk walk; int err; - int ts_state; padlock_reset_key(&ctx->cword.encrypt); blkcipher_walk_init(&walk, dst, src, nbytes); err = blkcipher_walk_virt(desc, &walk); - ts_state = irq_ts_save(); while ((nbytes = walk.nbytes)) { padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr, ctx->D, walk.iv, &ctx->cword.decrypt, @@ -472,8 +455,6 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc, err = blkcipher_walk_done(desc, &walk, nbytes); } - irq_ts_restore(ts_state); - padlock_store_cword(&ctx->cword.encrypt); return err; diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index 8c5f90647b7a..bc72d20c32c3 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c @@ -89,7 +89,6 @@ static int padlock_sha1_finup(struct shash_desc *desc, const u8 *in, struct sha1_state state; unsigned int space; unsigned int leftover; - int ts_state; int err; dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; @@ -120,14 +119,11 @@ static int padlock_sha1_finup(struct shash_desc *desc, const u8 *in, memcpy(result, &state.state, SHA1_DIGEST_SIZE); - /* prevent taking the spurious DNA fault with padlock. */ - ts_state = irq_ts_save(); asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" /* rep xsha1 */ : \ : "c"((unsigned long)state.count + count), \ "a"((unsigned long)state.count), \ "S"(in), "D"(result)); - irq_ts_restore(ts_state); padlock_output_block((uint32_t *)result, (uint32_t *)out, 5); @@ -155,7 +151,6 @@ static int padlock_sha256_finup(struct shash_desc *desc, const u8 *in, struct sha256_state state; unsigned int space; unsigned int leftover; - int ts_state; int err; dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; @@ -186,14 +181,11 @@ static int padlock_sha256_finup(struct shash_desc *desc, const u8 *in, memcpy(result, &state.state, SHA256_DIGEST_SIZE); - /* prevent taking the spurious DNA fault with padlock. */ - ts_state = irq_ts_save(); asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" /* rep xsha256 */ : \ : "c"((unsigned long)state.count + count), \ "a"((unsigned long)state.count), \ "S"(in), "D"(result)); - irq_ts_restore(ts_state); padlock_output_block((uint32_t *)result, (uint32_t *)out, 8); @@ -312,7 +304,6 @@ static int padlock_sha1_update_nano(struct shash_desc *desc, u8 buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__ ((aligned(STACK_ALIGN))); u8 *dst = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); - int ts_state; partial = sctx->count & 0x3f; sctx->count += len; @@ -328,23 +319,19 @@ static int padlock_sha1_update_nano(struct shash_desc *desc, memcpy(sctx->buffer + partial, data, done + SHA1_BLOCK_SIZE); src = sctx->buffer; - ts_state = irq_ts_save(); asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" : "+S"(src), "+D"(dst) \ : "a"((long)-1), "c"((unsigned long)1)); - irq_ts_restore(ts_state); done += SHA1_BLOCK_SIZE; src = data + done; } /* Process the left bytes from the input data */ if (len - done >= SHA1_BLOCK_SIZE) { - ts_state = irq_ts_save(); asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" : "+S"(src), "+D"(dst) : "a"((long)-1), "c"((unsigned long)((len - done) / SHA1_BLOCK_SIZE))); - irq_ts_restore(ts_state); done += ((len - done) - (len - done) % SHA1_BLOCK_SIZE); src = data + done; } @@ -401,7 +388,6 @@ static int padlock_sha256_update_nano(struct shash_desc *desc, const u8 *data, u8 buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__ ((aligned(STACK_ALIGN))); u8 *dst = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); - int ts_state; partial = sctx->count & 0x3f; sctx->count += len; @@ -417,23 +403,19 @@ static int padlock_sha256_update_nano(struct shash_desc *desc, const u8 *data, memcpy(sctx->buf + partial, data, done + SHA256_BLOCK_SIZE); src = sctx->buf; - ts_state = irq_ts_save(); asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" : "+S"(src), "+D"(dst) : "a"((long)-1), "c"((unsigned long)1)); - irq_ts_restore(ts_state); done += SHA256_BLOCK_SIZE; src = data + done; } /* Process the left bytes from input data*/ if (len - done >= SHA256_BLOCK_SIZE) { - ts_state = irq_ts_save(); asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" : "+S"(src), "+D"(dst) : "a"((long)-1), "c"((unsigned long)((len - done) / 64))); - irq_ts_restore(ts_state); done += ((len - done) - (len - done) % 64); src = data + done; } -- cgit v1.2.3 From cd95ea81f25608c403052d0508ee5c9b32e2bc7d Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Mon, 31 Oct 2016 15:18:46 -0700 Subject: x86/fpu, lguest: Remove CR0.TS support Now that Linux never sets CR0.TS, lguest doesn't need to support it. Signed-off-by: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Rik van Riel Cc: Rusty Russell Cc: Thomas Gleixner Cc: kvm list Link: http://lkml.kernel.org/r/8a7bf2c11231c082258fd67705d0f275639b8475.1477951965.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/lguest_hcall.h | 1 - arch/x86/lguest/boot.c | 17 +++++++---------- drivers/lguest/hypercalls.c | 4 ---- drivers/lguest/lg.h | 1 - drivers/lguest/x86/core.c | 19 +------------------ 5 files changed, 8 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/arch/x86/include/asm/lguest_hcall.h b/arch/x86/include/asm/lguest_hcall.h index ef01fef3eebc..6c119cfae218 100644 --- a/arch/x86/include/asm/lguest_hcall.h +++ b/arch/x86/include/asm/lguest_hcall.h @@ -9,7 +9,6 @@ #define LHCALL_FLUSH_TLB 5 #define LHCALL_LOAD_IDT_ENTRY 6 #define LHCALL_SET_STACK 7 -#define LHCALL_TS 8 #define LHCALL_SET_CLOCKEVENT 9 #define LHCALL_HALT 10 #define LHCALL_SET_PMD 13 diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 25da5bc8d83d..d74afcdbc580 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -497,27 +497,24 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx, * a whole series of functions like read_cr0() and write_cr0(). * * We start with cr0. cr0 allows you to turn on and off all kinds of basic - * features, but Linux only really cares about one: the horrifically-named Task - * Switched (TS) bit at bit 3 (ie. 8) + * features, but the only cr0 bit that Linux ever used at runtime was the + * horrifically-named Task Switched (TS) bit at bit 3 (ie. 8) * * What does the TS bit do? Well, it causes the CPU to trap (interrupt 7) if * the floating point unit is used. Which allows us to restore FPU state - * lazily after a task switch, and Linux uses that gratefully, but wouldn't a - * name like "FPUTRAP bit" be a little less cryptic? + * lazily after a task switch if we wanted to, but wouldn't a name like + * "FPUTRAP bit" be a little less cryptic? * - * We store cr0 locally because the Host never changes it. The Guest sometimes - * wants to read it and we'd prefer not to bother the Host unnecessarily. + * Fortunately, Linux keeps it simple and doesn't use TS, so we can ignore + * cr0. */ -static unsigned long current_cr0; static void lguest_write_cr0(unsigned long val) { - lazy_hcall1(LHCALL_TS, val & X86_CR0_TS); - current_cr0 = val; } static unsigned long lguest_read_cr0(void) { - return current_cr0; + return 0; } /* diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 19a32280731d..601f81c04873 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c @@ -109,10 +109,6 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args) case LHCALL_SET_CLOCKEVENT: guest_set_clockevent(cpu, args->arg1); break; - case LHCALL_TS: - /* This sets the TS flag, as we saw used in run_guest(). */ - cpu->ts = args->arg1; - break; case LHCALL_HALT: /* Similarly, this sets the halted flag for run_guest(). */ cpu->halted = 1; diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index 69b3814afd2f..2356a2318034 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -43,7 +43,6 @@ struct lg_cpu { struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */ u32 cr2; - int ts; u32 esp1; u16 ss1; diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 6e9042e3d2a9..743253fc638f 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -246,14 +246,6 @@ unsigned long *lguest_arch_regptr(struct lg_cpu *cpu, size_t reg_off, bool any) */ void lguest_arch_run_guest(struct lg_cpu *cpu) { - /* - * Remember the awfully-named TS bit? If the Guest has asked to set it - * we set it now, so we can trap and pass that trap to the Guest if it - * uses the FPU. - */ - if (cpu->ts && fpregs_active()) - stts(); - /* * SYSENTER is an optimized way of doing system calls. We can't allow * it because it always jumps to privilege level 0. A normal Guest @@ -282,10 +274,6 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - /* Clear the host TS bit if it was set above. */ - if (cpu->ts && fpregs_active()) - clts(); - /* * If the Guest page faulted, then the cr2 register will tell us the * bad virtual address. We have to grab this now, because once we @@ -421,12 +409,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) kill_guest(cpu, "Writing cr2"); break; case 7: /* We've intercepted a Device Not Available fault. */ - /* - * If the Guest doesn't want to know, we already restored the - * Floating Point Unit, so we just continue without telling it. - */ - if (!cpu->ts) - return; + /* No special handling is needed here. */ break; case 32 ... 255: /* This might be a syscall. */ -- cgit v1.2.3 From 08295ee0e6976b060cd5c2a59877d8ea6379075c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:22:53 +0300 Subject: media: usb: uvc: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Acked-by: Laurent Pinchart Cc: Mauro Carvalho Chehab Cc: Signed-off-by: Felipe Balbi --- drivers/media/usb/uvc/uvc_video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index b5589d5f5da4..11e0e5f4e1c2 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1467,6 +1467,7 @@ static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev, struct usb_host_endpoint *ep) { u16 psize; + u16 mult; switch (dev->speed) { case USB_SPEED_SUPER: @@ -1474,7 +1475,8 @@ static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev, return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); case USB_SPEED_HIGH: psize = usb_endpoint_maxp(&ep->desc); - return (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); + mult = usb_endpoint_maxp_mult(&ep->desc); + return (psize & 0x07ff) * mult; case USB_SPEED_WIRELESS: psize = usb_endpoint_maxp(&ep->desc); return psize; -- cgit v1.2.3 From bae203d58b7dce89664071b3fafe20cedaa3e4f6 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 26 Sep 2016 03:03:42 +0300 Subject: clk: imx31: fix rewritten input argument of mx31_clocks_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function mx31_clocks_init() is called during clock intialization on legacy boards with reference clock frequency passed as its input argument, this can be verified by examination of the function declaration found in arch/arm/mach-imx/common.h and actual function users which include that header file. Inside CCF driver the function ignores its input argument, by chance the used value in the function body is the same as input arguments on side of all callers. Fixes: d9388c843237 ("clk: imx31: Do not call mxc_timer_init twice when booting with DT") Signed-off-by: Vladimir Zapolskiy Reviewed-by: Uwe Kleine-König Acked-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx31.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c index 6a964144a5b5..6a49ba2b9671 100644 --- a/drivers/clk/imx/clk-imx31.c +++ b/drivers/clk/imx/clk-imx31.c @@ -157,10 +157,8 @@ static void __init _mx31_clocks_init(unsigned long fref) } } -int __init mx31_clocks_init(void) +int __init mx31_clocks_init(unsigned long fref) { - u32 fref = 26000000; /* default */ - _mx31_clocks_init(fref); clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0"); -- cgit v1.2.3 From 6fe5aeb5e7e9318bb720b1f582fc86b7ac3118c0 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 26 Sep 2016 03:03:43 +0300 Subject: ARM: clk: imx31: properly init clocks for machines with DT Clock initialization for i.MX31 powered machines with DT support should be done by a call of an init function registered with CLK_OF_DECLARE() in common clock framework. The change converts exported mx31_clocks_init_dt() into a static initialization function registered by CLK_OF_DECLARE(). Signed-off-by: Vladimir Zapolskiy Acked-by: Stephen Boyd Signed-off-by: Shawn Guo --- arch/arm/mach-imx/common.h | 1 - arch/arm/mach-imx/imx31-dt.c | 6 ------ drivers/clk/imx/clk-imx31.c | 50 +++++++++++++++++++++++--------------------- 3 files changed, 26 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index c4436d9c52ff..b09a2ec19267 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -43,7 +43,6 @@ int mx21_clocks_init(unsigned long lref, unsigned long fref); int mx27_clocks_init(unsigned long fref); int mx31_clocks_init(unsigned long fref); int mx35_clocks_init(void); -int mx31_clocks_init_dt(void); struct platform_device *mxc_register_gpio(char *name, int id, resource_size_t iobase, resource_size_t iosize, int irq, int irq_high); void mxc_set_cpu_type(unsigned int type); diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c index 62e6b4fb5370..668d74b72511 100644 --- a/arch/arm/mach-imx/imx31-dt.c +++ b/arch/arm/mach-imx/imx31-dt.c @@ -23,11 +23,6 @@ static const char * const imx31_dt_board_compat[] __initconst = { NULL }; -static void __init imx31_dt_timer_init(void) -{ - mx31_clocks_init_dt(); -} - /* FIXME: replace with DT binding */ static const struct resource imx31_rnga_res[] __initconst = { DEFINE_RES_MEM(MX31_RNGA_BASE_ADDR, SZ_16K), @@ -43,7 +38,6 @@ DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .init_time = imx31_dt_timer_init, .init_machine = imx31_dt_mach_init, .dt_compat = imx31_dt_board_compat, MACHINE_END diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c index 6a49ba2b9671..cbce308aad04 100644 --- a/drivers/clk/imx/clk-imx31.c +++ b/drivers/clk/imx/clk-imx31.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -72,14 +73,8 @@ static struct clk ** const uart_clks[] __initconst = { NULL }; -static void __init _mx31_clocks_init(unsigned long fref) +static void __init _mx31_clocks_init(void __iomem *base, unsigned long fref) { - void __iomem *base; - struct device_node *np; - - base = ioremap(MX31_CCM_BASE_ADDR, SZ_4K); - BUG_ON(!base); - clk[dummy] = imx_clk_fixed("dummy", 0); clk[ckih] = imx_clk_fixed("ckih", fref); clk[ckil] = imx_clk_fixed("ckil", 32768); @@ -147,19 +142,17 @@ static void __init _mx31_clocks_init(unsigned long fref) clk_prepare_enable(clk[iim_gate]); mx31_revision(); clk_disable_unprepare(clk[iim_gate]); - - np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm"); - - if (np) { - clk_data.clks = clk; - clk_data.clk_num = ARRAY_SIZE(clk); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); - } } int __init mx31_clocks_init(unsigned long fref) { - _mx31_clocks_init(fref); + void __iomem *base; + + base = ioremap(MX31_CCM_BASE_ADDR, SZ_4K); + if (!base) + panic("%s: failed to map registers\n", __func__); + + _mx31_clocks_init(base, fref); clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0"); clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0"); @@ -222,22 +215,31 @@ int __init mx31_clocks_init(unsigned long fref) return 0; } -int __init mx31_clocks_init_dt(void) +static void __init mx31_clocks_init_dt(struct device_node *np) { - struct device_node *np; + struct device_node *osc_np; u32 fref = 26000000; /* default */ + void __iomem *ccm; - for_each_compatible_node(np, NULL, "fixed-clock") { - if (!of_device_is_compatible(np, "fsl,imx-osc26m")) + for_each_compatible_node(osc_np, NULL, "fixed-clock") { + if (!of_device_is_compatible(osc_np, "fsl,imx-osc26m")) continue; - if (!of_property_read_u32(np, "clock-frequency", &fref)) { - of_node_put(np); + if (!of_property_read_u32(osc_np, "clock-frequency", &fref)) { + of_node_put(osc_np); break; } } - _mx31_clocks_init(fref); + ccm = of_iomap(np, 0); + if (!ccm) + panic("%s: failed to map registers\n", __func__); - return 0; + _mx31_clocks_init(ccm, fref); + + clk_data.clks = clk; + clk_data.clk_num = ARRAY_SIZE(clk); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); } + +CLK_OF_DECLARE(imx31_ccm, "fsl,imx31-ccm", mx31_clocks_init_dt); -- cgit v1.2.3 From 7d5d59e527b43d4efb00467234efbd2a0d5e5a86 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 1 Nov 2016 08:48:41 +0000 Subject: drm/i915: Use the full hammer when shutting down the rcu tasks To flush all call_rcu() tasks (here from i915_gem_free_object()) we need to call rcu_barrier() (not synchronize_rcu()). If we don't then we may still have objects being freed as we continue to teardown the driver - in particular, the recently released rings may race with the memory manager shutdown resulting in sporadic: [ 142.217186] WARNING: CPU: 7 PID: 6185 at drivers/gpu/drm/drm_mm.c:932 drm_mm_takedown+0x2e/0x40 [ 142.217187] Memory manager not clean during takedown. [ 142.217187] Modules linked in: i915(-) x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel lpc_ich snd_hda_codec_realtek snd_hda_codec_generic mei_me mei snd_hda_codec_hdmi snd_hda_codec snd_hwdep snd_hda_core snd_pcm e1000e ptp pps_core [last unloaded: snd_hda_intel] [ 142.217199] CPU: 7 PID: 6185 Comm: rmmod Not tainted 4.9.0-rc2-CI-Trybot_242+ #1 [ 142.217199] Hardware name: LENOVO 10AGS00601/SHARKBAY, BIOS FBKT34AUS 04/24/2013 [ 142.217200] ffffc90002ecfce0 ffffffff8142dd65 ffffc90002ecfd30 0000000000000000 [ 142.217202] ffffc90002ecfd20 ffffffff8107e4e6 000003a40778c2a8 ffff880401355c48 [ 142.217204] ffff88040778c2a8 ffffffffa040f3c0 ffffffffa040f4a0 00005621fbf8b1f0 [ 142.217206] Call Trace: [ 142.217209] [] dump_stack+0x67/0x92 [ 142.217211] [] __warn+0xc6/0xe0 [ 142.217213] [] warn_slowpath_fmt+0x4a/0x50 [ 142.217214] [] drm_mm_takedown+0x2e/0x40 [ 142.217236] [] i915_gem_cleanup_stolen+0x1a/0x20 [i915] [ 142.217246] [] i915_ggtt_cleanup_hw+0x31/0xb0 [i915] [ 142.217253] [] i915_driver_cleanup_hw+0x31/0x40 [i915] [ 142.217260] [] i915_driver_unload+0x141/0x1a0 [i915] [ 142.217268] [] i915_pci_remove+0x14/0x20 [i915] [ 142.217269] [] pci_device_remove+0x34/0xb0 [ 142.217271] [] __device_release_driver+0x9c/0x150 [ 142.217272] [] driver_detach+0xb6/0xc0 [ 142.217273] [] bus_remove_driver+0x53/0xd0 [ 142.217274] [] driver_unregister+0x27/0x50 [ 142.217276] [] pci_unregister_driver+0x25/0x70 [ 142.217287] [] i915_exit+0x1a/0x71 [i915] [ 142.217289] [] SyS_delete_module+0x193/0x1e0 [ 142.217291] [] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 142.217292] ---[ end trace 6fd164859c154772 ]--- [ 142.217505] [drm:show_leaks] *ERROR* node [6b6b6b6b6b6b6b6b + 6b6b6b6b6b6b6b6b]: inserted at [] save_stack.isra.1+0x53/0xa0 [] drm_mm_insert_node_in_range_generic+0x2ad/0x360 [] i915_gem_stolen_insert_node_in_range+0x93/0xe0 [i915] [] i915_gem_object_create_stolen+0x75/0xb0 [i915] [] intel_engine_create_ring+0x9a/0x140 [i915] [] intel_init_ring_buffer+0xf1/0x440 [i915] [] intel_init_render_ring_buffer+0xab/0x1b0 [i915] [] intel_engines_init+0xc8/0x210 [i915] [] i915_gem_init+0xac/0xf0 [i915] [] i915_driver_load+0x9c4/0x1430 [i915] [] i915_pci_probe+0x28/0x40 [i915] [] pci_device_probe+0x85/0xf0 [] driver_probe_device+0x21f/0x430 [] __driver_attach+0xde/0xe0 In particular note that the node was being poisoned as we inspected the list, a clear indication that the object is being freed as we make the assertion. v2: Don't loop, just assert that we do all the work required as that will be better at detecting further errors. Fixes: fbbd37b36fa5 ("drm/i915: Move object release to a freelist + worker") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161101084843.3961-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6a99544c98d3..3b9bfd2cf0c0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -544,7 +544,7 @@ static void i915_gem_fini(struct drm_i915_private *dev_priv) i915_gem_context_fini(&dev_priv->drm); mutex_unlock(&dev_priv->drm.struct_mutex); - synchronize_rcu(); + rcu_barrier(); flush_work(&dev_priv->mm.free_work); WARN_ON(!list_empty(&dev_priv->context_list)); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1e5d2bf777e4..b51274562e79 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4787,6 +4787,8 @@ void i915_gem_load_cleanup(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + WARN_ON(!llist_empty(&dev_priv->mm.free_list)); + kmem_cache_destroy(dev_priv->requests); kmem_cache_destroy(dev_priv->vmas); kmem_cache_destroy(dev_priv->objects); -- cgit v1.2.3 From 415981623f80a08ae36e9757cd4fa25da140b877 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 1 Nov 2016 08:48:42 +0000 Subject: drm/i915: Discard objects from mm global_list after being shrunk In the shrinker, we can safely remove an empty object (obj->mm.pages == NULL) after having discarded the pages because we are holding the struct_mutex. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161101084843.3961-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 0daa09cabbcc..9ace5f9f5317 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -228,6 +228,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, SINGLE_DEPTH_NESTING); if (!obj->mm.pages) { __i915_gem_object_invalidate(obj); + list_del_init(&obj->global_list); count += obj->base.size >> PAGE_SHIFT; } mutex_unlock(&obj->mm.lock); -- cgit v1.2.3 From 535972771d8c99dd53471b54c4dd6a4d22313d84 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 1 Nov 2016 08:48:43 +0000 Subject: drm/i915: Move the recently scanned objects to the tail after shrinking During shrinking, we walk over the list of objects searching for victims. Any that are not removed are put back into the global list. Currently, they are put back in order (at the front) which means they will be first to be scanned again. If we instead move them to the rear of the list, we will scan new potential victims on the next pass and waste less time rescanning unshrinkable objects. Normally the lists are kept in rough order to shrinking (with object least frequently used at the start), by moving just scanned objects to the rear we are acknowledging that they are still in use. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161101084843.3961-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 9ace5f9f5317..0993afc0e725 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -234,7 +234,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, mutex_unlock(&obj->mm.lock); } } - list_splice(&still_in_list, phase->list); + list_splice_tail(&still_in_list, phase->list); } if (flags & I915_SHRINK_BOUND) -- cgit v1.2.3 From cb399eabc41ae0e67fe87fbebee4cb03ab1b5de9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 1 Nov 2016 10:03:16 +0000 Subject: drm/i915: Avoid accessing request->timeline outside of its lifetime Whilst waiting on a request, we may do so without holding any locks or any guards beyond a reference to the request. In order to avoid taking locks within request deallocation, we drop references to its timeline (via the context and ppgtt) upon retirement. We should avoid chasing such pointers outside of their control, in particular we inspect the request->timeline to see if we may restore the RPS waitboost for a client. If we instead look at the engine->timeline, we will have similar behaviour on both full-ppgtt and !full-ppgtt systems and reduce the amount of reward we give towards stalling clients (i.e. only if the client stalls and the GPU is uncontended does it reclaim its boost). This restores behaviour back to pre-timelines, whilst fixing: [ 645.078485] BUG: KASAN: use-after-free in i915_gem_object_wait_fence+0x1ee/0x2e0 at addr ffff8802335643a0 [ 645.078577] Read of size 4 by task gem_exec_schedu/28408 [ 645.078638] CPU: 1 PID: 28408 Comm: gem_exec_schedu Not tainted 4.9.0-rc2+ #64 [ 645.078724] Hardware name: / , BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015 [ 645.078816] ffff88022daef9a0 ffffffff8143d059 ffff880235402a80 ffff880233564200 [ 645.078998] ffff88022daef9c8 ffffffff81229c5c ffff88022daefa48 ffff880233564200 [ 645.079172] ffff880235402a80 ffff88022daefa38 ffffffff81229ef0 000000008110a796 [ 645.079345] Call Trace: [ 645.079404] [] dump_stack+0x68/0x9f [ 645.079467] [] kasan_object_err+0x1c/0x70 [ 645.079534] [] kasan_report_error+0x1f0/0x4b0 [ 645.079601] [] kasan_report+0x34/0x40 [ 645.079676] [] ? i915_gem_object_wait_fence+0x1ee/0x2e0 [ 645.079741] [] __asan_load4+0x61/0x80 [ 645.079807] [] i915_gem_object_wait_fence+0x1ee/0x2e0 [ 645.079876] [] i915_gem_object_wait+0x19f/0x590 [ 645.079944] [] ? i915_gem_object_wait_priority+0x500/0x500 [ 645.080016] [] ? debug_show_all_locks+0x1e0/0x1e0 [ 645.080084] [] ? check_chain_key+0x14c/0x210 [ 645.080157] [] ? __lock_is_held+0x46/0xc0 [ 645.080226] [] ? i915_gem_set_domain_ioctl+0x141/0x690 [ 645.080296] [] i915_gem_set_domain_ioctl+0x1a2/0x690 [ 645.080366] [] ? __might_fault+0x75/0xe0 [ 645.080433] [] drm_ioctl+0x327/0x640 [ 645.080508] [] ? i915_gem_obj_prepare_shmem_write+0x3a0/0x3a0 [ 645.080603] [] ? drm_ioctl_permit+0x120/0x120 [ 645.080670] [] ? check_chain_key+0x14c/0x210 [ 645.080738] [] do_vfs_ioctl+0x127/0xa20 [ 645.080804] [] ? do_mmap+0x47c/0x580 [ 645.080871] [] ? vm_mmap_pgoff+0x117/0x140 [ 645.080938] [] ? ioctl_preallocate+0x150/0x150 [ 645.081011] [] ? up_write+0x23/0x50 [ 645.081078] [] ? vm_mmap_pgoff+0x117/0x140 [ 645.081145] [] ? vma_is_stack_for_current+0x90/0x90 [ 645.081214] [] ? mark_held_locks+0x23/0xc0 [ 645.082030] [] ? __fget+0x168/0x250 [ 645.082106] [] ? entry_SYSCALL_64_fastpath+0x5/0xb1 [ 645.082176] [] ? __fget_light+0xa2/0xc0 [ 645.082242] [] SyS_ioctl+0x3c/0x70 [ 645.082309] [] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 645.082374] Object at ffff880233564200, in cache kmalloc-8192 size: 8192 [ 645.082431] Allocated: [ 645.082480] PID = 28408 [ 645.082535] [ 645.082566] [] save_stack_trace+0x16/0x20 [ 645.082623] [ 645.082656] [] save_stack+0x46/0xd0 [ 645.082716] [ 645.082756] [] kasan_kmalloc+0xad/0xe0 [ 645.082817] [ 645.082848] [] i915_ppgtt_create+0x52/0x220 [ 645.082908] [ 645.082941] [] i915_gem_create_context+0x396/0x560 [ 645.083027] [ 645.083059] [] i915_gem_context_create_ioctl+0x97/0xf0 [ 645.083152] [ 645.083183] [] drm_ioctl+0x327/0x640 [ 645.083243] [ 645.083274] [] do_vfs_ioctl+0x127/0xa20 [ 645.083334] [ 645.083372] [] SyS_ioctl+0x3c/0x70 [ 645.083432] [ 645.083464] [] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 645.083551] Freed: [ 645.083599] PID = 27629 [ 645.083648] [ 645.083676] [] save_stack_trace+0x16/0x20 [ 645.083738] [ 645.083770] [] save_stack+0x46/0xd0 [ 645.083830] [ 645.083862] [] kasan_slab_free+0x73/0xc0 [ 645.083922] [ 645.083961] [] kfree+0xa9/0x170 [ 645.084021] [ 645.084053] [] i915_ppgtt_release+0x100/0x180 [ 645.084139] [ 645.084171] [] i915_gem_context_free+0x1b4/0x230 [ 645.084257] [ 645.084288] [] intel_lr_context_unpin+0x192/0x230 [ 645.084380] [ 645.084413] [] i915_gem_request_retire+0x620/0x630 [ 645.084500] [ 645.085226] [] i915_gem_retire_requests+0x181/0x280 [ 645.085313] [ 645.085352] [] i915_gem_retire_work_handler+0xca/0xe0 [ 645.085440] [ 645.085471] [] process_one_work+0x4fb/0x920 [ 645.085532] [ 645.085562] [] worker_thread+0x8d/0x840 [ 645.085622] [ 645.085653] [] kthread+0x185/0x1b0 [ 645.085718] [ 645.085750] [] ret_from_fork+0x27/0x40 [ 645.085811] Memory state around the buggy address: [ 645.085869] ffff880233564280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 645.085956] ffff880233564300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 645.086053] >ffff880233564380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 645.086138] ^ [ 645.086193] ffff880233564400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 645.086283] ffff880233564480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb v2: Add a comment to document the hint like nature of intel_engine_last_submit() Fixes: 73cb97010d4f ("drm/i915: Combine seqno + tracking into a global timeline struct") Fixes: 80b204bce8f2 ("drm/i915: Enable multiple timelines") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161101100317.11129-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 7 +++---- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 12 ++++++++++++ 5 files changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9bef6f55f99d..bf19192dcc3b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1348,9 +1348,8 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seq_printf(m, "%s:\n", engine->name); seq_printf(m, "\tseqno = %x [current %x, last %x]\n", - engine->hangcheck.seqno, - seqno[id], - engine->timeline->last_submitted_seqno); + engine->hangcheck.seqno, seqno[id], + intel_engine_last_submit(engine)); seq_printf(m, "\twaiters? %s, fake irq active? %s\n", yesno(intel_engine_has_waiter(engine)), yesno(test_bit(engine->id, @@ -3167,7 +3166,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) seq_printf(m, "%s\n", engine->name); seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [score %d]\n", intel_engine_get_seqno(engine), - engine->timeline->last_submitted_seqno, + intel_engine_last_submit(engine), engine->hangcheck.seqno, engine->hangcheck.score); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b51274562e79..6c51b21565d6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -371,7 +371,7 @@ out: if (flags & I915_WAIT_LOCKED && i915_gem_request_completed(rq)) i915_gem_request_retire_upto(rq); - if (rps && rq->fence.seqno == rq->timeline->last_submitted_seqno) { + if (rps && rq->global_seqno == intel_engine_last_submit(rq->engine)) { /* The GPU is now idle and this client has stalled. * Since no other client has submitted a request in the * meantime, assume that this client is the only one @@ -2674,7 +2674,7 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine) * reset it. */ intel_engine_init_global_seqno(engine, - engine->timeline->last_submitted_seqno); + intel_engine_last_submit(engine)); /* * Clear the execlists queue up before freeing the requests, as those diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 7ba40487e345..204093f3eaa5 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1120,7 +1120,7 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); ee->acthd = intel_engine_get_active_head(engine); ee->seqno = intel_engine_get_seqno(engine); - ee->last_seqno = engine->timeline->last_submitted_seqno; + ee->last_seqno = intel_engine_last_submit(engine); ee->start = I915_READ_START(engine); ee->head = I915_READ_HEAD(engine); ee->tail = I915_READ_TAIL(engine); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 90d0905592f2..4dda2b1eefdb 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3168,7 +3168,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) acthd = intel_engine_get_active_head(engine); seqno = intel_engine_get_seqno(engine); - submit = READ_ONCE(engine->timeline->last_submitted_seqno); + submit = intel_engine_last_submit(engine); if (engine->hangcheck.seqno == seqno) { if (i915_seqno_passed(seqno, submit)) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 43f61aa24ed7..642b54692d0d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -496,6 +496,18 @@ static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) return intel_read_status_page(engine, I915_GEM_HWS_INDEX); } +static inline u32 intel_engine_last_submit(struct intel_engine_cs *engine) +{ + /* We are only peeking at the tail of the submit queue (and not the + * queue itself) in order to gain a hint as to the current active + * state of the engine. Callers are not expected to be taking + * engine->timeline->lock, nor are they expected to be concerned + * wtih serialising this hint with anything, so document it as + * a hint and nothing more. + */ + return READ_ONCE(engine->timeline->last_submitted_seqno); +} + int init_workarounds_ring(struct intel_engine_cs *engine); void intel_engine_get_instdone(struct intel_engine_cs *engine, -- cgit v1.2.3 From bc0629a76726991f97ee88c65b87e99dd94c1dc4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 1 Nov 2016 10:03:17 +0000 Subject: drm/i915: Track pages pinned due to swizzling quirk If we have a tiled object and an unknown CPU swizzle pattern, we pin the pages to prevent the object from being swapped out (and us corrupting the contents as we do not know the access pattern and so cannot convert it to linear and back to tiled on reuse). This requires us to remember to drop the extra pinning when freeing the object, or else we trigger warnings about the pin leak. In commit fbbd37b36fa5 ("drm/i915: Move object release to a freelist + worker"), the object free path was deferred to a worker, but the unpinning of the quirk, along with marking the object as reclaimable, was left on the immediate path (so that if required we could reclaim the pages under memory pressure as early as possible). However, this split introduced a bug where the pages were no longer being unpinned if they were marked as unneeded. [ 231.800401] WARNING: CPU: 1 PID: 90 at drivers/gpu/drm/i915/i915_gem.c:4275 __i915_gem_free_objects+0x326/0x3c0 [i915] [ 231.800403] WARN_ON(i915_gem_object_has_pinned_pages(obj)) [ 231.800405] Modules linked in: [ 231.800406] snd_hda_intel i915 snd_hda_codec_generic mei_me snd_hda_codec coretemp snd_hwdep mei lpc_ich snd_hda_core snd_pcm e1000e ptp pps_core [last unloaded: i915] [ 231.800426] CPU: 1 PID: 90 Comm: kworker/1:4 Tainted: G U 4.9.0-rc2-CI-CI_DRM_1780+ #1 [ 231.800428] Hardware name: LENOVO 7465CTO/7465CTO, BIOS 6DET44WW (2.08 ) 04/22/2009 [ 231.800456] Workqueue: events __i915_gem_free_work [i915] [ 231.800459] ffffc9000034fc80 ffffffff8142dd65 ffffc9000034fcd0 0000000000000000 [ 231.800465] ffffc9000034fcc0 ffffffff8107e4e6 000010b300000001 0000000000001000 [ 231.800469] ffff88011d3db740 ffff880130ef0000 0000000000000000 ffff880130ef5ea0 [ 231.800474] Call Trace: [ 231.800479] [] dump_stack+0x67/0x92 [ 231.800484] [] __warn+0xc6/0xe0 [ 231.800487] [] warn_slowpath_fmt+0x4a/0x50 [ 231.800491] [] ? kmem_cache_free+0x2dc/0x340 [ 231.800520] [] __i915_gem_free_objects+0x326/0x3c0 [i915] [ 231.800548] [] __i915_gem_free_work+0x2e/0x50 [i915] [ 231.800552] [] process_one_work+0x1ec/0x6b0 [ 231.800555] [] ? process_one_work+0x166/0x6b0 [ 231.800558] [] worker_thread+0x49/0x490 [ 231.800561] [] ? process_one_work+0x6b0/0x6b0 [ 231.800563] [] ? process_one_work+0x6b0/0x6b0 [ 231.800566] [] kthread+0xeb/0x110 [ 231.800569] [] ? kthread_park+0x60/0x60 [ 231.800573] [] ret_from_fork+0x27/0x40 Moving to a separate flag for tracking the quirked pin is overkill for the bug (since we only have to interchange the two tests in i915_gem_free_object) but it does reduce a complicated test on all objects and provide a sanitycheck for uncommon code paths. Fixes: fbbd37b36fa5 ("drm/i915: Move object release to a freelist + worker") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161101100317.11129-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ drivers/gpu/drm/i915/i915_gem.c | 21 +++++++++++++-------- drivers/gpu/drm/i915/i915_gem_tiling.c | 9 +++++++-- 3 files changed, 26 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 51360d199263..539106a9c1af 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2304,6 +2304,12 @@ struct drm_i915_gem_object { * pages were last acquired. */ bool dirty:1; + + /** + * This is set if the object has been pinned due to unknown + * swizzling. + */ + bool quirked:1; } mm; /** Breadcrumb of last rendering to the buffer. diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6c51b21565d6..c9e52f75e1cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2324,8 +2324,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) i915_gem_object_do_bit_17_swizzle(obj, st); if (i915_gem_object_is_tiled(obj) && - dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) + dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { __i915_gem_object_pin_pages(obj); + obj->mm.quirked = true; + } return st; @@ -4091,10 +4093,15 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, if (obj->mm.pages && i915_gem_object_is_tiled(obj) && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { - if (obj->mm.madv == I915_MADV_WILLNEED) + if (obj->mm.madv == I915_MADV_WILLNEED) { + GEM_BUG_ON(!obj->mm.quirked); __i915_gem_object_unpin_pages(obj); - if (args->madv == I915_MADV_WILLNEED) + obj->mm.quirked = false; + } + if (args->madv == I915_MADV_WILLNEED) { __i915_gem_object_pin_pages(obj); + obj->mm.quirked = true; + } } if (obj->mm.madv != __I915_MADV_PURGED) @@ -4335,14 +4342,12 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) { struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); + if (obj->mm.quirked) + __i915_gem_object_unpin_pages(obj); + if (discard_backing_storage(obj)) obj->mm.madv = I915_MADV_DONTNEED; - if (obj->mm.pages && obj->mm.madv == I915_MADV_WILLNEED && - to_i915(obj->base.dev)->quirks & QUIRK_PIN_SWIZZLED_PAGES && - i915_gem_object_is_tiled(obj)) - __i915_gem_object_unpin_pages(obj); - /* Before we free the object, make sure any pure RCU-only * read-side critical sections are complete, e.g. * i915_gem_busy_ioctl(). For the corresponding synchronized diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 6395e62bd9e4..1577e7810cd6 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -263,10 +263,15 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, if (obj->mm.pages && obj->mm.madv == I915_MADV_WILLNEED && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { - if (args->tiling_mode == I915_TILING_NONE) + if (args->tiling_mode == I915_TILING_NONE) { + GEM_BUG_ON(!obj->mm.quirked); __i915_gem_object_unpin_pages(obj); - if (!i915_gem_object_is_tiled(obj)) + obj->mm.quirked = false; + } + if (!i915_gem_object_is_tiled(obj)) { __i915_gem_object_pin_pages(obj); + obj->mm.quirked = true; + } } mutex_unlock(&obj->mm.lock); -- cgit v1.2.3 From f13abeff2cdee2256e5f1c5a63fcc57ca8357010 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 17 Oct 2016 22:29:12 -0200 Subject: clk: imx6: Mask mmdc_ch1 handshake for periph2_sel and mmdc_ch1_axi_podf MMDC CH1 is not used on i.MX6Q, so the handshake needed to change the parent of periph2_sel or the divider of mmdc_ch1_axi_podf will never succeed. Disable the handshake mechanism to allow changing the frequency of mmdc_ch1_axi, allowing to use it as a possible source for the LDB DI clock. Signed-off-by: Philipp Zabel Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx6q.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index ce8ea10407e4..66825a8238b6 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -156,6 +156,19 @@ static struct clk ** const uart_clks[] __initconst = { NULL }; +#define CCM_CCDR 0x04 + +#define CCDR_MMDC_CH1_MASK BIT(16) + +static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base) +{ + unsigned int reg; + + reg = readl_relaxed(ccm_base + CCM_CCDR); + reg |= CCDR_MMDC_CH1_MASK; + writel_relaxed(reg, ccm_base + CCM_CCDR); +} + static void __init imx6q_clocks_init(struct device_node *ccm_node) { struct device_node *np; @@ -297,6 +310,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) base = of_iomap(np, 0); WARN_ON(!base); + imx6q_mmdc_ch1_mask_handshake(base); + /* name reg shift width parent_names num_parents */ clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); -- cgit v1.2.3 From 03d576f202e8cd40d500aa4f7594ad702d861096 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 17 Oct 2016 22:29:13 -0200 Subject: clk: imx6: Make the LDB_DI0 and LDB_DI1 clocks read-only Due to incorrect placement of the clock gate cell in the ldb_di[x]_clk tree, the glitchy parent mux of ldb_di[x]_clk can cause a glitch to enter the ldb_di_ipu_div divider. If the divider gets locked up, no ldb_di[x]_clk is generated, and the LVDS display will hang when the ipu_di_clk is sourced from ldb_di_clk. To fix the problem, both the new and current parent of the ldb_di_clk should be disabled before the switch. As this can not be guaranteed by the clock framework during runtime, make the ldb_di[x]_sel muxes read-only. A workaround to set the muxes once during boot could be added to the kernel or bootloader. Signed-off-by: Philipp Zabel Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx6q.c | 10 ++-------- drivers/clk/imx/clk.h | 8 ++++++++ 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index 66825a8238b6..a4f4de5c9cb2 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -345,8 +345,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels)); clk[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); clk[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); - clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); - clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); + clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); + clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); @@ -597,12 +597,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL); - if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) || - clk_on_imx6dl()) { - clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); - clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); - } - clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000); if (clk_on_imx6dl()) clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]); diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 3799ff82a9b4..4afad3b96a61 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -75,6 +75,14 @@ static inline struct clk *imx_clk_fixed(const char *name, int rate) return clk_register_fixed_rate(NULL, name, NULL, 0, rate); } +static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg, + u8 shift, u8 width, const char **parents, int num_parents) +{ + return clk_register_mux(NULL, name, parents, num_parents, + CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, reg, + shift, width, CLK_MUX_READ_ONLY, &imx_ccm_lock); +} + static inline struct clk *imx_clk_fixed_factor(const char *name, const char *parent, unsigned int mult, unsigned int div) { -- cgit v1.2.3 From 5d283b083800867dc329e6433576664bf0fc18d5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 17 Oct 2016 22:29:14 -0200 Subject: clk: imx6: Fix procedure to switch the parent of LDB_DI_CLK Due to incorrect placement of the clock gate cell in the ldb_di[x]_clk tree, the glitchy parent mux of ldb_di[x]_clk can cause a glitch to enter the ldb_di_ipu_div divider. If the divider gets locked up, no ldb_di[x]_clk is generated, and the LVDS display will hang when the ipu_di_clk is sourced from ldb_di_clk. To fix the problem, both the new and current parent of the ldb_di_clk should be disabled before the switch. This patch ensures that correct steps are followed when ldb_di_clk parent is switched in the beginning of boot. The glitchy muxes are then registered as read-only. The clock parent can be selected using the assigned-clocks and assigned-clock-parents properties of the ccm device tree node: &clks { assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>; assigned-clock-parents = <&clks IMX6QDL_CLK_MMDC_CH1_AXI>, <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>; }; The issue is explained in detail in EB821 ("LDB Clock Switch Procedure & i.MX6 Asynchronous Clock Switching Guidelines") [1]. [1] http://www.nxp.com/files/32bit/doc/eng_bulletin/EB821.pdf Signed-off-by: Ranjani Vaidyanathan Signed-off-by: Fabio Estevam Signed-off-by: Philipp Zabel Reviewed-by: Akshay Bhat Tested-by Joshua Clayton Tested-by: Charles Kang Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx6q.c | 264 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 259 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index a4f4de5c9cb2..42ffc1c92bab 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -156,9 +156,90 @@ static struct clk ** const uart_clks[] __initconst = { NULL }; +static int ldb_di_sel_by_clock_id(int clock_id) +{ + switch (clock_id) { + case IMX6QDL_CLK_PLL5_VIDEO_DIV: + if (clk_on_imx6q() && + imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) + return -ENOENT; + return 0; + case IMX6QDL_CLK_PLL2_PFD0_352M: + return 1; + case IMX6QDL_CLK_PLL2_PFD2_396M: + return 2; + case IMX6QDL_CLK_MMDC_CH1_AXI: + return 3; + case IMX6QDL_CLK_PLL3_USB_OTG: + return 4; + default: + return -ENOENT; + } +} + +static void of_assigned_ldb_sels(struct device_node *node, + unsigned int *ldb_di0_sel, + unsigned int *ldb_di1_sel) +{ + struct of_phandle_args clkspec; + int index, rc, num_parents; + int parent, child, sel; + + num_parents = of_count_phandle_with_args(node, "assigned-clock-parents", + "#clock-cells"); + for (index = 0; index < num_parents; index++) { + rc = of_parse_phandle_with_args(node, "assigned-clock-parents", + "#clock-cells", index, &clkspec); + if (rc < 0) { + /* skip empty (null) phandles */ + if (rc == -ENOENT) + continue; + else + return; + } + if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) { + pr_err("ccm: parent clock %d not in ccm\n", index); + return; + } + parent = clkspec.args[0]; + + rc = of_parse_phandle_with_args(node, "assigned-clocks", + "#clock-cells", index, &clkspec); + if (rc < 0) + return; + if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) { + pr_err("ccm: child clock %d not in ccm\n", index); + return; + } + child = clkspec.args[0]; + + if (child != IMX6QDL_CLK_LDB_DI0_SEL && + child != IMX6QDL_CLK_LDB_DI1_SEL) + continue; + + sel = ldb_di_sel_by_clock_id(parent); + if (sel < 0) { + pr_err("ccm: invalid ldb_di%d parent clock: %d\n", + child == IMX6QDL_CLK_LDB_DI1_SEL, parent); + continue; + } + + if (child == IMX6QDL_CLK_LDB_DI0_SEL) + *ldb_di0_sel = sel; + if (child == IMX6QDL_CLK_LDB_DI1_SEL) + *ldb_di1_sel = sel; + } +} + #define CCM_CCDR 0x04 +#define CCM_CCSR 0x0c +#define CCM_CS2CDR 0x2c + +#define CCDR_MMDC_CH1_MASK BIT(16) +#define CCSR_PLL3_SW_CLK_SEL BIT(0) -#define CCDR_MMDC_CH1_MASK BIT(16) +#define CS2CDR_LDB_DI0_CLK_SEL_SHIFT 9 +#define CS2CDR_LDB_DI1_CLK_SEL_SHIFT 12 static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base) { @@ -169,10 +250,173 @@ static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base) writel_relaxed(reg, ccm_base + CCM_CCDR); } +/* + * The only way to disable the MMDC_CH1 clock is to move it to pll3_sw_clk + * via periph2_clk2_sel and then to disable pll3_sw_clk by selecting the + * bypass clock source, since there is no CG bit for mmdc_ch1. + */ +static void mmdc_ch1_disable(void __iomem *ccm_base) +{ + unsigned int reg; + + clk_set_parent(clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL], + clk[IMX6QDL_CLK_PLL3_USB_OTG]); + + /* + * Handshake with mmdc_ch1 module must be masked when changing + * periph2_clk_sel. + */ + clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_CLK2]); + + /* Disable pll3_sw_clk by selecting the bypass clock source */ + reg = readl_relaxed(ccm_base + CCM_CCSR); + reg |= CCSR_PLL3_SW_CLK_SEL; + writel_relaxed(reg, ccm_base + CCM_CCSR); +} + +static void mmdc_ch1_reenable(void __iomem *ccm_base) +{ + unsigned int reg; + + /* Enable pll3_sw_clk by disabling the bypass */ + reg = readl_relaxed(ccm_base + CCM_CCSR); + reg &= ~CCSR_PLL3_SW_CLK_SEL; + writel_relaxed(reg, ccm_base + CCM_CCSR); + + clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_PRE]); +} + +/* + * We have to follow a strict procedure when changing the LDB clock source, + * otherwise we risk introducing a glitch that can lock up the LDB divider. + * Things to keep in mind: + * + * 1. The current and new parent clock inputs to the mux must be disabled. + * 2. The default clock input for ldb_di0/1_clk_sel is mmdc_ch1_axi, which + * has no CG bit. + * 3. pll2_pfd2_396m can not be gated if it is used as memory clock. + * 4. In the RTL implementation of the LDB_DI_CLK_SEL muxes the top four + * options are in one mux and the PLL3 option along with three unused + * inputs is in a second mux. There is a third mux with two inputs used + * to decide between the first and second 4-port mux: + * + * pll5_video_div 0 --|\ + * pll2_pfd0_352m 1 --| |_ + * pll2_pfd2_396m 2 --| | `-|\ + * mmdc_ch1_axi 3 --|/ | | + * | |-- + * pll3_usb_otg 4 --|\ | | + * 5 --| |_,-|/ + * 6 --| | + * 7 --|/ + * + * The ldb_di0/1_clk_sel[1:0] bits control both 4-port muxes at the same time. + * The ldb_di0/1_clk_sel[2] bit controls the 2-port mux. The code below + * switches the parent to the bottom mux first and then manipulates the top + * mux to ensure that no glitch will enter the divider. + */ +static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base) +{ + unsigned int reg; + unsigned int sel[2][4]; + int i; + + reg = readl_relaxed(ccm_base + CCM_CS2CDR); + sel[0][0] = (reg >> CS2CDR_LDB_DI0_CLK_SEL_SHIFT) & 7; + sel[1][0] = (reg >> CS2CDR_LDB_DI1_CLK_SEL_SHIFT) & 7; + + sel[0][3] = sel[0][2] = sel[0][1] = sel[0][0]; + sel[1][3] = sel[1][2] = sel[1][1] = sel[1][0]; + + of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]); + + for (i = 0; i < 2; i++) { + /* Warn if a glitch might have been introduced already */ + if (sel[i][0] != 3) { + pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n", + i, sel[i][0]); + } + + if (sel[i][0] == sel[i][3]) + continue; + + /* Only switch to or from pll2_pfd2_396m if it is disabled */ + if ((sel[i][0] == 2 || sel[i][3] == 2) && + (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) == + clk[IMX6QDL_CLK_PLL2_PFD2_396M])) { + pr_err("ccm: ldb_di%d_sel: couldn't disable pll2_pfd2_396m\n", + i); + sel[i][3] = sel[i][2] = sel[i][1] = sel[i][0]; + continue; + } + + /* First switch to the bottom mux */ + sel[i][1] = sel[i][0] | 4; + + /* Then configure the top mux before switching back to it */ + sel[i][2] = sel[i][3] | 4; + + pr_debug("ccm: switching ldb_di%d_sel: %d->%d->%d->%d\n", i, + sel[i][0], sel[i][1], sel[i][2], sel[i][3]); + } + + if (sel[0][0] == sel[0][3] && sel[1][0] == sel[1][3]) + return; + + mmdc_ch1_disable(ccm_base); + + for (i = 1; i < 4; i++) { + reg = readl_relaxed(ccm_base + CCM_CS2CDR); + reg &= ~((7 << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) | + (7 << CS2CDR_LDB_DI1_CLK_SEL_SHIFT)); + reg |= ((sel[0][i] << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) | + (sel[1][i] << CS2CDR_LDB_DI1_CLK_SEL_SHIFT)); + writel_relaxed(reg, ccm_base + CCM_CS2CDR); + } + + mmdc_ch1_reenable(ccm_base); +} + +#define CCM_ANALOG_PLL_VIDEO 0xa0 +#define CCM_ANALOG_PFD_480 0xf0 +#define CCM_ANALOG_PFD_528 0x100 + +#define PLL_ENABLE BIT(13) + +#define PFD0_CLKGATE BIT(7) +#define PFD1_CLKGATE BIT(15) +#define PFD2_CLKGATE BIT(23) +#define PFD3_CLKGATE BIT(31) + +static void disable_anatop_clocks(void __iomem *anatop_base) +{ + unsigned int reg; + + /* Make sure PLL2 PFDs 0-2 are gated */ + reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_528); + /* Cannot gate PFD2 if pll2_pfd2_396m is the parent of MMDC clock */ + if (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) == + clk[IMX6QDL_CLK_PLL2_PFD2_396M]) + reg |= PFD0_CLKGATE | PFD1_CLKGATE; + else + reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE; + writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_528); + + /* Make sure PLL3 PFDs 0-3 are gated */ + reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_480); + reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE | PFD3_CLKGATE; + writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_480); + + /* Make sure PLL5 is disabled */ + reg = readl_relaxed(anatop_base + CCM_ANALOG_PLL_VIDEO); + reg &= ~PLL_ENABLE; + writel_relaxed(reg, anatop_base + CCM_ANALOG_PLL_VIDEO); +} + static void __init imx6q_clocks_init(struct device_node *ccm_node) { struct device_node *np; - void __iomem *base; + void __iomem *anatop_base, *base; int i; int ret; @@ -185,7 +429,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0); np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); - base = of_iomap(np, 0); + anatop_base = base = of_iomap(np, 0); WARN_ON(!base); /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */ @@ -310,8 +554,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) base = of_iomap(np, 0); WARN_ON(!base); - imx6q_mmdc_ch1_mask_handshake(base); - /* name reg shift width parent_names num_parents */ clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); @@ -345,6 +587,18 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels)); clk[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); clk[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); + + disable_anatop_clocks(anatop_base); + + imx6q_mmdc_ch1_mask_handshake(base); + + /* + * The LDB_DI0/1_SEL muxes are registered read-only due to a hardware + * bug. Set the muxes to the requested values before registering the + * ldb_di_sel clocks. + */ + init_ldb_clks(np, base); + clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); -- cgit v1.2.3 From db6c2b4151f2915fe1695cdcac43b32e73d1ad32 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 1 Nov 2016 11:54:00 +0000 Subject: drm/i915: Store the vma in an rbtree under the object With full-ppgtt one of the main bottlenecks is the lookup of the VMA underneath the object. For execbuf there is merit in having a very fast direct lookup of ctx:handle to the vma using a hashtree, but that still leaves a large number of other lookups. One way to speed up the lookup would be to use a rhashtable, but that requires extra allocations and may exhibit poor worse case behaviour. An alternative is to use an embedded rbtree, i.e. no extra allocations and deterministic behaviour, but at the slight cost of O(lgN) lookups (instead of O(1) for rhashtable). The major of such tree will be very shallow and so not much slower, and still scales much, much better than the current unsorted list. v2: Bump vma_compare() to return a long, as we return the result of comparing two pointers. References: https://bugs.freedesktop.org/show_bug.cgi?id=87726 Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161101115400.15647-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 2 + drivers/gpu/drm/i915/i915_gem_gtt.c | 80 +++++++++++++++++++++++++------------ drivers/gpu/drm/i915/i915_gem_gtt.h | 1 + 4 files changed, 59 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 539106a9c1af..9143129cd851 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2230,6 +2230,7 @@ struct drm_i915_gem_object { /** List of VMAs backed by this object */ struct list_head vma_list; + struct rb_root vma_tree; /** Stolen memory for this object, instead of being backed by shmem. */ struct drm_mm_node *stolen; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c9e52f75e1cb..1568f6756430 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4266,6 +4266,8 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, vma->flags &= ~I915_VMA_PIN_MASK; i915_vma_close(vma); } + GEM_BUG_ON(!list_empty(&obj->vma_list)); + GEM_BUG_ON(!RB_EMPTY_ROOT(&obj->vma_tree)); list_del(&obj->global_list); } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index e7afad585929..00606a27e9aa 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3399,6 +3399,7 @@ void i915_vma_destroy(struct i915_vma *vma) GEM_BUG_ON(!i915_vma_is_closed(vma)); GEM_BUG_ON(vma->fence); + rb_erase(&vma->obj_node, &vma->obj->vma_tree); list_del(&vma->vm_link); if (!i915_vma_is_ggtt(vma)) i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm)); @@ -3416,12 +3417,33 @@ void i915_vma_close(struct i915_vma *vma) WARN_ON(i915_vma_unbind(vma)); } +static inline long vma_compare(struct i915_vma *vma, + struct i915_address_space *vm, + const struct i915_ggtt_view *view) +{ + GEM_BUG_ON(view && !i915_vma_is_ggtt(vma)); + + if (vma->vm != vm) + return vma->vm - vm; + + if (!view) + return vma->ggtt_view.type; + + if (vma->ggtt_view.type != view->type) + return vma->ggtt_view.type - view->type; + + return memcmp(&vma->ggtt_view.params, + &view->params, + sizeof(view->params)); +} + static struct i915_vma * __i915_vma_create(struct drm_i915_gem_object *obj, struct i915_address_space *vm, const struct i915_ggtt_view *view) { struct i915_vma *vma; + struct rb_node *rb, **p; int i; GEM_BUG_ON(vm->closed); @@ -3455,33 +3477,28 @@ __i915_vma_create(struct drm_i915_gem_object *obj, if (i915_is_ggtt(vm)) { vma->flags |= I915_VMA_GGTT; + list_add(&vma->obj_link, &obj->vma_list); } else { i915_ppgtt_get(i915_vm_to_ppgtt(vm)); + list_add_tail(&vma->obj_link, &obj->vma_list); } - list_add_tail(&vma->obj_link, &obj->vma_list); - return vma; -} + rb = NULL; + p = &obj->vma_tree.rb_node; + while (*p) { + struct i915_vma *pos; -static inline bool vma_matches(struct i915_vma *vma, - struct i915_address_space *vm, - const struct i915_ggtt_view *view) -{ - if (vma->vm != vm) - return false; - - if (!i915_vma_is_ggtt(vma)) - return true; - - if (!view) - return vma->ggtt_view.type == 0; - - if (vma->ggtt_view.type != view->type) - return false; + rb = *p; + pos = rb_entry(rb, struct i915_vma, obj_node); + if (vma_compare(pos, vm, view) < 0) + p = &rb->rb_right; + else + p = &rb->rb_left; + } + rb_link_node(&vma->obj_node, rb, p); + rb_insert_color(&vma->obj_node, &obj->vma_tree); - return memcmp(&vma->ggtt_view.params, - &view->params, - sizeof(view->params)) == 0; + return vma; } struct i915_vma * @@ -3501,12 +3518,23 @@ i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, struct i915_address_space *vm, const struct i915_ggtt_view *view) { - struct i915_vma *vma; + struct rb_node *rb; + + rb = obj->vma_tree.rb_node; + while (rb) { + struct i915_vma *vma = rb_entry(rb, struct i915_vma, obj_node); + long cmp; - list_for_each_entry_reverse(vma, &obj->vma_list, obj_link) - if (vma_matches(vma, vm, view)) + cmp = vma_compare(vma, vm, view); + if (cmp == 0) return vma; + if (cmp < 0) + rb = rb->rb_right; + else + rb = rb->rb_left; + } + return NULL; } @@ -3521,8 +3549,10 @@ i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, GEM_BUG_ON(view && !i915_is_ggtt(vm)); vma = i915_gem_obj_to_vma(obj, vm, view); - if (!vma) + if (!vma) { vma = __i915_vma_create(obj, vm, view); + GEM_BUG_ON(vma != i915_gem_obj_to_vma(obj, vm, view)); + } GEM_BUG_ON(i915_vma_is_closed(vma)); return vma; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 518e75b64290..c23ef9db1f53 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -227,6 +227,7 @@ struct i915_vma { struct list_head vm_link; struct list_head obj_link; /* Link in the object's VMA list */ + struct rb_node obj_node; /** This vma's place in the batchbuffer or on the eviction list */ struct list_head exec_list; -- cgit v1.2.3 From 548625ee8fde571c32e7976879854410689c4a84 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 1 Nov 2016 12:11:34 +0000 Subject: drm/i915: Improve lockdep tracking for obj->mm.lock The shrinker may appear to recurse into obj->mm.lock as the shrinker may be called from a direct reclaim path whilst handling get_pages. We filter out recursing on the same obj->mm.lock by inspecting obj->mm.pages, but we do want to take the lock on a second object in order to reap their pages. lockdep spots the recursion on the same lockclass and needs annotation to avoid a false positive. To keep the two paths distinct, create an enum to indicate which subclass of obj->mm.lock we are using. This removes the false positive and avoids masking real bugs. Suggested-by: Joonas Lahtinen Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161101121134.27504-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 8 +++++++- drivers/gpu/drm/i915/i915_gem.c | 9 +++++---- drivers/gpu/drm/i915/i915_gem_shrinker.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_userptr.c | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9143129cd851..086396e16de7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3287,7 +3287,13 @@ i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) __i915_gem_object_unpin_pages(obj); } -void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj); +enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock */ + I915_MM_NORMAL = 0, + I915_MM_SHRINKER +}; + +void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, + enum i915_mm_subclass subclass); void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj); enum i915_map_type { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1568f6756430..cbbfaa7761b9 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -491,7 +491,7 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, if (ret) return ret; - __i915_gem_object_put_pages(obj); + __i915_gem_object_put_pages(obj, I915_MM_NORMAL); if (obj->mm.pages) return -EBUSY; @@ -2181,7 +2181,8 @@ static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj) radix_tree_delete(&obj->mm.get_page.radix, iter.index); } -void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) +void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, + enum i915_mm_subclass subclass) { struct sg_table *pages; @@ -2193,7 +2194,7 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) return; /* May be called by shrinker from within get_pages() (on another bo) */ - mutex_lock_nested(&obj->mm.lock, SINGLE_DEPTH_NESTING); + mutex_lock_nested(&obj->mm.lock, subclass); if (unlikely(atomic_read(&obj->mm.pages_pin_count))) goto unlock; @@ -4283,7 +4284,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, if (WARN_ON(i915_gem_object_has_pinned_pages(obj))) atomic_set(&obj->mm.pages_pin_count, 0); - __i915_gem_object_put_pages(obj); + __i915_gem_object_put_pages(obj, I915_MM_NORMAL); GEM_BUG_ON(obj->mm.pages); if (obj->base.import_attach) diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 0993afc0e725..f988652f1e26 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -111,7 +111,7 @@ static bool can_release_pages(struct drm_i915_gem_object *obj) static bool unsafe_drop_pages(struct drm_i915_gem_object *obj) { if (i915_gem_object_unbind(obj) == 0) - __i915_gem_object_put_pages(obj); + __i915_gem_object_put_pages(obj, I915_MM_SHRINKER); return !READ_ONCE(obj->mm.pages); } @@ -225,7 +225,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, if (unsafe_drop_pages(obj)) { /* May arrive from get_pages on another bo */ mutex_lock_nested(&obj->mm.lock, - SINGLE_DEPTH_NESTING); + I915_MM_SHRINKER); if (!obj->mm.pages) { __i915_gem_object_invalidate(obj); list_del_init(&obj->global_list); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index c30d04f64670..9bf44b5bca10 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -75,7 +75,7 @@ static void cancel_userptr(struct work_struct *work) /* We are inside a kthread context and can't be interrupted */ if (i915_gem_object_unbind(obj) == 0) - __i915_gem_object_put_pages(obj); + __i915_gem_object_put_pages(obj, I915_MM_NORMAL); WARN_ONCE(obj->mm.pages, "Failed to release pages: bind_count=%d, pages_pin_count=%d, pin_display=%d\n", obj->bind_count, -- cgit v1.2.3 From c8fe32c13543759fe5de7c4dcf3882f6693b8349 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 26 Oct 2016 15:41:29 +0200 Subject: drm/i915/skl+: Prepare for removing data rate from skl watermark state, v2. Caching is not required, drm_atomic_crtc_state_for_each_plane_state can be used to inspect the states of all planes assigned to the CRTC even if they are not part of _state, so we can just recalculate every time. Changes since v1: - Remove plane->pipe checks, they're implied by the macros. - Split unrelated changes to a separate commit. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1477489299-25777-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Paulo Zanoni Reviewed-by: Matt Roper --- drivers/gpu/drm/i915/intel_pm.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b544248cfdee..87959d9401a9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -31,6 +31,7 @@ #include "intel_drv.h" #include "../../../platform/x86/intel_ips.h" #include +#include /** * DOC: RC6 @@ -3269,24 +3270,20 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate) struct drm_crtc *crtc = cstate->crtc; struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - const struct drm_plane *plane; + struct drm_plane *plane; const struct intel_plane *intel_plane; - struct drm_plane_state *pstate; + const struct drm_plane_state *pstate; unsigned int rate, total_data_rate = 0; int id; - int i; if (WARN_ON(!state)) return 0; /* Calculate and cache data rate for each plane */ - for_each_plane_in_state(state, plane, pstate, i) { + drm_atomic_crtc_state_for_each_plane_state(plane, pstate, cstate) { id = skl_wm_plane_id(to_intel_plane(plane)); intel_plane = to_intel_plane(plane); - if (intel_plane->pipe != intel_crtc->pipe) - continue; - /* packed/uv */ rate = skl_plane_relative_data_rate(intel_cstate, pstate, 0); @@ -3383,7 +3380,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane; struct drm_plane *plane; - struct drm_plane_state *pstate; + const struct drm_plane_state *pstate; enum pipe pipe = intel_crtc->pipe; struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; uint16_t alloc_size, start, cursor_blocks; @@ -3419,14 +3416,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, alloc_size -= cursor_blocks; /* 1. Allocate the mininum required blocks for each active plane */ - for_each_plane_in_state(state, plane, pstate, i) { + drm_atomic_crtc_state_for_each_plane_state(plane, pstate, &cstate->base) { intel_plane = to_intel_plane(plane); id = skl_wm_plane_id(intel_plane); - if (intel_plane->pipe != pipe) - continue; - - if (!to_intel_plane_state(pstate)->base.visible) { + if (!pstate->visible) { minimum[id] = 0; y_minimum[id] = 0; continue; -- cgit v1.2.3 From 220b0965219ec68fcd28bea603dbfe84281245ff Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 26 Oct 2016 15:41:30 +0200 Subject: drm/i915/gen9+: Use cstate plane mask instead of crtc->state. I'm planning on getting rid of all obj->state dereferences, and replace thhem with accessor functions. Remove this one early, they're equivalent because removed planes are already part of the state, else they could not have been removed. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1477489299-25777-3-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Matt Roper --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 87959d9401a9..e6e9cc563484 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3975,7 +3975,7 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc)); - drm_for_each_plane_mask(plane, dev, crtc->state->plane_mask) { + drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) { id = skl_wm_plane_id(to_intel_plane(plane)); if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][id], -- cgit v1.2.3 From 7570498efb693eeee44f58dcb5cb64fdee87f17d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 1 Nov 2016 12:04:10 +0100 Subject: drm/i915/gen9+: Use for_each_intel_plane_on_crtc in skl_print_wm_changes, v2. Using for_each_intel_plane_on_crtc will allow us to find all allocations that may have changed, not just the one added by the atomic state. This will print changes to plane allocations for crtc's when some planes are not added to the atomic state. Changes since v1: - Rephrase commit message. (Ville) - Use plane->base.id and plane->name to kill off cursor special case. (Ville) - Add intel_crtc to prevent a line wrap. (Paulo) - Line wrap debug messages. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/c9f7dc1a-d23a-7c16-b2b7-1c23dd07ed35@linux.intel.com Reviewed-by: Matt Roper Reviewed-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_pm.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e6e9cc563484..56372f41137c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4090,45 +4090,31 @@ skl_print_wm_changes(const struct drm_atomic_state *state) to_intel_atomic_state(state); const struct drm_crtc *crtc; const struct drm_crtc_state *cstate; - const struct drm_plane *plane; const struct intel_plane *intel_plane; - const struct drm_plane_state *pstate; const struct skl_ddb_allocation *old_ddb = &dev_priv->wm.skl_hw.ddb; const struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; - enum pipe pipe; int id; - int i, j; + int i; for_each_crtc_in_state(state, crtc, cstate, i) { - pipe = to_intel_crtc(crtc)->pipe; + const struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + enum pipe pipe = intel_crtc->pipe; - for_each_plane_in_state(state, plane, pstate, j) { + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { const struct skl_ddb_entry *old, *new; - intel_plane = to_intel_plane(plane); id = skl_wm_plane_id(intel_plane); old = &old_ddb->plane[pipe][id]; new = &new_ddb->plane[pipe][id]; - if (intel_plane->pipe != pipe) - continue; - if (skl_ddb_entry_equal(old, new)) continue; - if (id != PLANE_CURSOR) { - DRM_DEBUG_ATOMIC("[PLANE:%d:plane %d%c] ddb (%d - %d) -> (%d - %d)\n", - plane->base.id, id + 1, - pipe_name(pipe), - old->start, old->end, - new->start, new->end); - } else { - DRM_DEBUG_ATOMIC("[PLANE:%d:cursor %c] ddb (%d - %d) -> (%d - %d)\n", - plane->base.id, - pipe_name(pipe), - old->start, old->end, - new->start, new->end); - } + DRM_DEBUG_ATOMIC("[PLANE:%d:%s] ddb (%d - %d) -> (%d - %d)\n", + intel_plane->base.base.id, + intel_plane->base.name, + old->start, old->end, + new->start, new->end); } } } -- cgit v1.2.3 From 1e6ee542262d611a07e15eee0abb4516d7378b93 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 26 Oct 2016 15:41:32 +0200 Subject: drm/i915/skl+: Remove data_rate from watermark struct, v2. It's only used in one function, and can be calculated without caching it in the global struct by using drm_atomic_crtc_state_for_each_plane_state. There are loops over all planes, including planes that don't exist. This is harmless, because data_rate will always be 0 for them and we never program them when updating watermarks. Changes since v1: - Rename rate back to data_rate, and change array name to plane_data_rate. (Matt) - Remove whitespace. (Paulo) Signed-off-by: Maarten Lankhorst Reviewed-by: Matt Roper Cc: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1477489299-25777-5-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_drv.h | 4 ---- drivers/gpu/drm/i915/intel_pm.c | 35 ++++++++++++++++------------------- 2 files changed, 16 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 46233356ed24..66a1965401c8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -501,10 +501,6 @@ struct intel_crtc_wm_state { struct skl_pipe_wm optimal; struct skl_ddb_entry ddb; - /* cached plane data rate */ - unsigned plane_data_rate[I915_MAX_PLANES]; - unsigned plane_y_data_rate[I915_MAX_PLANES]; - /* minimum block allocation */ uint16_t minimum_blocks[I915_MAX_PLANES]; uint16_t minimum_y_blocks[I915_MAX_PLANES]; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 56372f41137c..909e1b1ee5a6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3263,13 +3263,12 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, * 3 * 4096 * 8192 * 4 < 2^32 */ static unsigned int -skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate) +skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, + unsigned *plane_data_rate, + unsigned *plane_y_data_rate) { struct drm_crtc_state *cstate = &intel_cstate->base; struct drm_atomic_state *state = cstate->state; - struct drm_crtc *crtc = cstate->crtc; - struct drm_device *dev = crtc->dev; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_plane *plane; const struct intel_plane *intel_plane; const struct drm_plane_state *pstate; @@ -3287,21 +3286,16 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate) /* packed/uv */ rate = skl_plane_relative_data_rate(intel_cstate, pstate, 0); - intel_cstate->wm.skl.plane_data_rate[id] = rate; + plane_data_rate[id] = rate; + + total_data_rate += rate; /* y-plane */ rate = skl_plane_relative_data_rate(intel_cstate, pstate, 1); - intel_cstate->wm.skl.plane_y_data_rate[id] = rate; - } + plane_y_data_rate[id] = rate; - /* Calculate CRTC's total data rate from cached values */ - for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { - int id = skl_wm_plane_id(intel_plane); - - /* packed/uv */ - total_data_rate += intel_cstate->wm.skl.plane_data_rate[id]; - total_data_rate += intel_cstate->wm.skl.plane_y_data_rate[id]; + total_data_rate += rate; } return total_data_rate; @@ -3389,6 +3383,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, unsigned int total_data_rate; int num_active; int id, i; + unsigned plane_data_rate[I915_MAX_PLANES] = {}; + unsigned plane_y_data_rate[I915_MAX_PLANES] = {}; /* Clear the partitioning for disabled planes. */ memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); @@ -3446,17 +3442,18 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, * * FIXME: we may not allocate every single block here. */ - total_data_rate = skl_get_total_relative_data_rate(cstate); + total_data_rate = skl_get_total_relative_data_rate(cstate, + plane_data_rate, + plane_y_data_rate); if (total_data_rate == 0) return 0; start = alloc->start; - for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + for (id = 0; id < I915_MAX_PLANES; id++) { unsigned int data_rate, y_data_rate; uint16_t plane_blocks, y_plane_blocks = 0; - int id = skl_wm_plane_id(intel_plane); - data_rate = cstate->wm.skl.plane_data_rate[id]; + data_rate = plane_data_rate[id]; /* * allocation for (packed formats) or (uv-plane part of planar format): @@ -3478,7 +3475,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, /* * allocation for y_plane part of planar format: */ - y_data_rate = cstate->wm.skl.plane_y_data_rate[id]; + y_data_rate = plane_y_data_rate[id]; y_plane_blocks = y_minimum[id]; y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate, -- cgit v1.2.3 From fefdd8104d6f574677221c4ba2912483c66ee43c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 26 Oct 2016 15:41:33 +0200 Subject: drm/i915/skl+: Remove minimum block allocation from crtc state. This is not required any more now that we get fresh state from drm_atomic_crtc_state_for_each_plane_state. Zero all state in advance. Signed-off-by: Maarten Lankhorst Reviewed-by: Matt Roper Reviewed-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1477489299-25777-6-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_drv.h | 4 ---- drivers/gpu/drm/i915/intel_pm.c | 15 +++++---------- 2 files changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 66a1965401c8..35a74fe4f415 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -500,10 +500,6 @@ struct intel_crtc_wm_state { /* gen9+ only needs 1-step wm programming */ struct skl_pipe_wm optimal; struct skl_ddb_entry ddb; - - /* minimum block allocation */ - uint16_t minimum_blocks[I915_MAX_PLANES]; - uint16_t minimum_y_blocks[I915_MAX_PLANES]; } skl; }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 909e1b1ee5a6..086bf9e68aa2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3378,8 +3378,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, enum pipe pipe = intel_crtc->pipe; struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; uint16_t alloc_size, start, cursor_blocks; - uint16_t *minimum = cstate->wm.skl.minimum_blocks; - uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; + uint16_t minimum[I915_MAX_PLANES] = {}; + uint16_t y_minimum[I915_MAX_PLANES] = {}; unsigned int total_data_rate; int num_active; int id, i; @@ -3416,16 +3416,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, intel_plane = to_intel_plane(plane); id = skl_wm_plane_id(intel_plane); - if (!pstate->visible) { - minimum[id] = 0; - y_minimum[id] = 0; + if (!pstate->visible) continue; - } - if (plane->type == DRM_PLANE_TYPE_CURSOR) { - minimum[id] = 0; - y_minimum[id] = 0; + + if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - } minimum[id] = skl_ddb_min_alloc(pstate, 0); y_minimum[id] = skl_ddb_min_alloc(pstate, 1); -- cgit v1.2.3 From 49845a7aff5406e10420de08aa34cf55f98f2a3b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 26 Oct 2016 15:41:34 +0200 Subject: drm/i915/skl+: Clean up minimum allocations, v2. Move calculating minimum allocations to a helper, which cleans up the code some more. The cursor is still allocated in advance because it doesn't count towards data rate and should always be reserved. changes since v1: - Change comment to have a extra opening line. (Matt) - Rebase to remove unused plane->pipe == pipe, handled by the iterator now. (Paulo) Reviewed-by: Matt Roper Signed-off-by: Maarten Lankhorst Cc: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1477489299-25777-7-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_pm.c | 62 +++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 086bf9e68aa2..edd37e770c36 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3364,6 +3364,30 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, return DIV_ROUND_UP((4 * src_w * plane_bpp), 512) * min_scanlines/4 + 3; } +static void +skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active, + uint16_t *minimum, uint16_t *y_minimum) +{ + const struct drm_plane_state *pstate; + struct drm_plane *plane; + + drm_atomic_crtc_state_for_each_plane_state(plane, pstate, &cstate->base) { + struct intel_plane *intel_plane = to_intel_plane(plane); + int id = skl_wm_plane_id(intel_plane); + + if (id == PLANE_CURSOR) + continue; + + if (!pstate->visible) + continue; + + minimum[id] = skl_ddb_min_alloc(pstate, 0); + y_minimum[id] = skl_ddb_min_alloc(pstate, 1); + } + + minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active); +} + static int skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, struct skl_ddb_allocation *ddb /* out */) @@ -3372,12 +3396,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, struct drm_crtc *crtc = cstate->base.crtc; struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_plane *intel_plane; - struct drm_plane *plane; - const struct drm_plane_state *pstate; enum pipe pipe = intel_crtc->pipe; struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; - uint16_t alloc_size, start, cursor_blocks; + uint16_t alloc_size, start; uint16_t minimum[I915_MAX_PLANES] = {}; uint16_t y_minimum[I915_MAX_PLANES] = {}; unsigned int total_data_rate; @@ -3405,32 +3426,22 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, return 0; } - cursor_blocks = skl_cursor_allocation(num_active); - ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - cursor_blocks; - ddb->plane[pipe][PLANE_CURSOR].end = alloc->end; - - alloc_size -= cursor_blocks; - - /* 1. Allocate the mininum required blocks for each active plane */ - drm_atomic_crtc_state_for_each_plane_state(plane, pstate, &cstate->base) { - intel_plane = to_intel_plane(plane); - id = skl_wm_plane_id(intel_plane); - - if (!pstate->visible) - continue; - - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; + skl_ddb_calc_min(cstate, num_active, minimum, y_minimum); - minimum[id] = skl_ddb_min_alloc(pstate, 0); - y_minimum[id] = skl_ddb_min_alloc(pstate, 1); - } + /* + * 1. Allocate the mininum required blocks for each active plane + * and allocate the cursor, it doesn't require extra allocation + * proportional to the data rate. + */ - for (i = 0; i < PLANE_CURSOR; i++) { + for (i = 0; i < I915_MAX_PLANES; i++) { alloc_size -= minimum[i]; alloc_size -= y_minimum[i]; } + ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - minimum[PLANE_CURSOR]; + ddb->plane[pipe][PLANE_CURSOR].end = alloc->end; + /* * 2. Distribute the remaining space in proportion to the amount of * data each plane needs to fetch from memory. @@ -3448,6 +3459,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, unsigned int data_rate, y_data_rate; uint16_t plane_blocks, y_plane_blocks = 0; + if (id == PLANE_CURSOR) + continue; + data_rate = plane_data_rate[id]; /* -- cgit v1.2.3 From 03af79e0b801fa5ea817f71a22a932d4b5b62b4b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 26 Oct 2016 15:41:36 +0200 Subject: drm/i915/gen9+: Use the watermarks from crtc_state for everything, v2. There's no need to keep a duplicate skl_pipe_wm around any more, everything can be discovered from crtc_state, which we pass around correctly now even in case of plane disable. The copy in intel_crtc->wm.skl.active is equal to crtc_state->wm.skl.optimal after the atomic commit completes. It's useful for two-step watermark programming, but not required for gen9+ which does it in a single step. We can pull the old allocation from old_crtc_state. Signed-off-by: Maarten Lankhorst Cc: Matt Roper Reviewed-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1477489299-25777-9-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Matt Roper --- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 18 ++++++++---------- 3 files changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 740c68896672..5a87dbf6f090 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13458,7 +13458,7 @@ static void verify_wm_state(struct drm_crtc *crtc, return; skl_pipe_wm_get_hw_state(crtc, &hw_wm); - sw_wm = &intel_crtc->wm.active.skl; + sw_wm = &to_intel_crtc_state(new_state)->wm.skl.optimal; skl_ddb_get_hw_state(dev_priv, &hw_ddb); sw_ddb = &dev_priv->wm.skl_hw.ddb; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 35a74fe4f415..8c931bc1d8b6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -722,7 +722,6 @@ struct intel_crtc { /* watermarks currently being used */ union { struct intel_pipe_wm ilk; - struct skl_pipe_wm skl; } active; /* allow CxSR on this pipe */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index edd37e770c36..9cfc19ece147 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3930,11 +3930,11 @@ bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, } static int skl_update_pipe_wm(struct drm_crtc_state *cstate, - struct skl_ddb_allocation *ddb, /* out */ + const struct skl_pipe_wm *old_pipe_wm, struct skl_pipe_wm *pipe_wm, /* out */ + struct skl_ddb_allocation *ddb, /* out */ bool *changed /* out */) { - struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc); struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate); int ret; @@ -3942,7 +3942,7 @@ static int skl_update_pipe_wm(struct drm_crtc_state *cstate, if (ret) return ret; - if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) + if (!memcmp(old_pipe_wm, pipe_wm, sizeof(*pipe_wm))) *changed = false; else *changed = true; @@ -4169,10 +4169,12 @@ skl_compute_wm(struct drm_atomic_state *state) for_each_crtc_in_state(state, crtc, cstate, i) { struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate); + const struct skl_pipe_wm *old_pipe_wm = + &to_intel_crtc_state(crtc->state)->wm.skl.optimal; pipe_wm = &intel_cstate->wm.skl.optimal; - ret = skl_update_pipe_wm(cstate, &results->ddb, pipe_wm, - &changed); + ret = skl_update_pipe_wm(cstate, old_pipe_wm, pipe_wm, + &results->ddb, &changed); if (ret) return ret; @@ -4205,8 +4207,6 @@ static void skl_update_wm(struct drm_crtc *crtc) if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0) return; - intel_crtc->wm.active.skl = *pipe_wm; - mutex_lock(&dev_priv->wm.wm_mutex); /* @@ -4374,10 +4374,8 @@ void skl_wm_get_hw_state(struct drm_device *dev) skl_pipe_wm_get_hw_state(crtc, &cstate->wm.skl.optimal); - if (intel_crtc->active) { + if (intel_crtc->active) hw->dirty_pipes |= drm_crtc_mask(crtc); - intel_crtc->wm.active.skl = cstate->wm.skl.optimal; - } } if (dev_priv->active_crtcs) { -- cgit v1.2.3 From 07c9a21a0d594c3acc0983e5e0a25d2364188d51 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 30 Oct 2016 13:28:20 +0000 Subject: drm/i915: Export a function to flush the context upon pinning For legacy contexts we employ an optimisation to only flush the context when binding into the global GTT. This avoids stalling on the GPU when reloading an active context. Wrap this detail up into a helper and export it for a potential third user. (Longer term, context pinning needs to be reworked as the current handling of switch context pins too late and so risks eviction and corrupting the request. Plans, plans, plans.) v2: Expand the comment explaining the optimisation for avoiding the stall on active contexts. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161030132820.32163-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/i915_gem_context.c | 39 +++++++++++++++++++++++---------- drivers/gpu/drm/i915/intel_ringbuffer.c | 11 +++++----- 3 files changed, 36 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 086396e16de7..b5bfc4c67aa0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3529,6 +3529,9 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file); void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); int i915_switch_context(struct drm_i915_gem_request *req); int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv); +struct i915_vma * +i915_gem_context_pin_legacy(struct i915_gem_context *ctx, + unsigned int flags); void i915_gem_context_free(struct kref *ctx_ref); struct drm_i915_gem_object * i915_gem_alloc_context_obj(struct drm_device *dev, size_t size); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 461aece6c5bd..6dd475735f0a 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -764,12 +764,36 @@ needs_pd_load_post(struct i915_hw_ppgtt *ppgtt, return false; } +struct i915_vma * +i915_gem_context_pin_legacy(struct i915_gem_context *ctx, + unsigned int flags) +{ + struct i915_vma *vma = ctx->engine[RCS].state; + int ret; + + /* Clear this page out of any CPU caches for coherent swap-in/out. + * We only want to do this on the first bind so that we do not stall + * on an active context (which by nature is already on the GPU). + */ + if (!(vma->flags & I915_VMA_GLOBAL_BIND)) { + ret = i915_gem_object_set_to_gtt_domain(vma->obj, false); + if (ret) + return ERR_PTR(ret); + } + + ret = i915_vma_pin(vma, 0, ctx->ggtt_alignment, PIN_GLOBAL | flags); + if (ret) + return ERR_PTR(ret); + + return vma; +} + static int do_rcs_switch(struct drm_i915_gem_request *req) { struct i915_gem_context *to = req->ctx; struct intel_engine_cs *engine = req->engine; struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt; - struct i915_vma *vma = to->engine[RCS].state; + struct i915_vma *vma; struct i915_gem_context *from; u32 hw_flags; int ret, i; @@ -777,17 +801,10 @@ static int do_rcs_switch(struct drm_i915_gem_request *req) if (skip_rcs_switch(ppgtt, engine, to)) return 0; - /* Clear this page out of any CPU caches for coherent swap-in/out. */ - if (!(vma->flags & I915_VMA_GLOBAL_BIND)) { - ret = i915_gem_object_set_to_gtt_domain(vma->obj, false); - if (ret) - return ret; - } - /* Trying to pin first makes error handling easier. */ - ret = i915_vma_pin(vma, 0, to->ggtt_alignment, PIN_GLOBAL); - if (ret) - return ret; + vma = i915_gem_context_pin_legacy(to, 0); + if (IS_ERR(vma)) + return PTR_ERR(vma); /* * Pin can switch back to the default context if we end up calling into diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 188fdec5fa6b..700e93d80616 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1949,14 +1949,13 @@ static int intel_ring_context_pin(struct i915_gem_context *ctx, return 0; if (ce->state) { - ret = i915_gem_object_set_to_gtt_domain(ce->state->obj, false); - if (ret) - goto error; + struct i915_vma *vma; - ret = i915_vma_pin(ce->state, 0, ctx->ggtt_alignment, - PIN_GLOBAL | PIN_HIGH); - if (ret) + vma = i915_gem_context_pin_legacy(ctx, PIN_HIGH); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); goto error; + } } /* The kernel context is only used as a placeholder for flushing the -- cgit v1.2.3 From 580503c7c52a8605c3be008a93a572be840a4f16 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:00 +0200 Subject: drm/i915: Pass dev_priv to plane constructors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 40 +++++++++++++++++------------------- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_sprite.c | 12 +++++------ 4 files changed, 27 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b5bfc4c67aa0..ea1cfc649961 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -185,7 +185,7 @@ enum plane { }; #define plane_name(p) ((p) + 'A') -#define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites[(p)] + (s) + 'A') +#define sprite_name(p, s) ((p) * INTEL_INFO(dev_priv)->num_sprites[(p)] + (s) + 'A') enum port { PORT_NONE = -1, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5a87dbf6f090..e48656789f37 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14960,9 +14960,8 @@ const struct drm_plane_funcs intel_plane_funcs = { }; static struct intel_plane * -intel_primary_plane_create(struct drm_device *dev, enum pipe pipe) +intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *primary = NULL; struct intel_plane_state *state = NULL; const uint32_t *intel_primary_formats; @@ -14986,7 +14985,7 @@ intel_primary_plane_create(struct drm_device *dev, enum pipe pipe) primary->can_scale = false; primary->max_downscale = 1; - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { primary->can_scale = true; state->scaler_id = -1; } @@ -14994,10 +14993,10 @@ intel_primary_plane_create(struct drm_device *dev, enum pipe pipe) primary->plane = pipe; primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe); primary->check_plane = intel_check_primary_plane; - if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) + if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4) primary->plane = !pipe; - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { intel_primary_formats = skl_primary_formats; num_formats = ARRAY_SIZE(skl_primary_formats); @@ -15009,7 +15008,7 @@ intel_primary_plane_create(struct drm_device *dev, enum pipe pipe) primary->update_plane = ironlake_update_primary_plane; primary->disable_plane = i9xx_disable_primary_plane; - } else if (INTEL_INFO(dev)->gen >= 4) { + } else if (INTEL_GEN(dev_priv) >= 4) { intel_primary_formats = i965_primary_formats; num_formats = ARRAY_SIZE(i965_primary_formats); @@ -15023,21 +15022,21 @@ intel_primary_plane_create(struct drm_device *dev, enum pipe pipe) primary->disable_plane = i9xx_disable_primary_plane; } - if (INTEL_INFO(dev)->gen >= 9) - ret = drm_universal_plane_init(dev, &primary->base, 0, - &intel_plane_funcs, + if (INTEL_GEN(dev_priv) >= 9) + ret = drm_universal_plane_init(&dev_priv->drm, &primary->base, + 0, &intel_plane_funcs, intel_primary_formats, num_formats, DRM_PLANE_TYPE_PRIMARY, "plane 1%c", pipe_name(pipe)); else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) - ret = drm_universal_plane_init(dev, &primary->base, 0, - &intel_plane_funcs, + ret = drm_universal_plane_init(&dev_priv->drm, &primary->base, + 0, &intel_plane_funcs, intel_primary_formats, num_formats, DRM_PLANE_TYPE_PRIMARY, "primary %c", pipe_name(pipe)); else - ret = drm_universal_plane_init(dev, &primary->base, 0, - &intel_plane_funcs, + ret = drm_universal_plane_init(&dev_priv->drm, &primary->base, + 0, &intel_plane_funcs, intel_primary_formats, num_formats, DRM_PLANE_TYPE_PRIMARY, "plane %c", plane_name(primary->plane)); @@ -15165,9 +15164,8 @@ intel_update_cursor_plane(struct drm_plane *plane, } static struct intel_plane * -intel_cursor_plane_create(struct drm_device *dev, enum pipe pipe) +intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *cursor = NULL; struct intel_plane_state *state = NULL; int ret; @@ -15195,8 +15193,8 @@ intel_cursor_plane_create(struct drm_device *dev, enum pipe pipe) cursor->update_plane = intel_update_cursor_plane; cursor->disable_plane = intel_disable_cursor_plane; - ret = drm_universal_plane_init(dev, &cursor->base, 0, - &intel_plane_funcs, + ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base, + 0, &intel_plane_funcs, intel_cursor_formats, ARRAY_SIZE(intel_cursor_formats), DRM_PLANE_TYPE_CURSOR, @@ -15210,7 +15208,7 @@ intel_cursor_plane_create(struct drm_device *dev, enum pipe pipe) DRM_ROTATE_0 | DRM_ROTATE_180); - if (INTEL_INFO(dev)->gen >=9) + if (INTEL_GEN(dev_priv) >= 9) state->scaler_id = -1; drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs); @@ -15272,7 +15270,7 @@ static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) skl_init_scalers(dev, intel_crtc, crtc_state); } - primary = intel_primary_plane_create(dev, pipe); + primary = intel_primary_plane_create(dev_priv, pipe); if (IS_ERR(primary)) { ret = PTR_ERR(primary); goto fail; @@ -15281,14 +15279,14 @@ static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) for_each_sprite(dev_priv, pipe, sprite) { struct intel_plane *plane; - plane = intel_sprite_plane_create(dev, pipe, sprite); + plane = intel_sprite_plane_create(dev_priv, pipe, sprite); if (!plane) { ret = PTR_ERR(plane); goto fail; } } - cursor = intel_cursor_plane_create(dev, pipe); + cursor = intel_cursor_plane_create(dev_priv, pipe); if (!cursor) { ret = PTR_ERR(cursor); goto fail; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8c931bc1d8b6..caa91d713fa2 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1769,7 +1769,7 @@ bool intel_sdvo_init(struct drm_device *dev, /* intel_sprite.c */ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, int usecs); -struct intel_plane *intel_sprite_plane_create(struct drm_device *dev, +struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, int plane); int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 70b50a27763e..df0fbb4b15a3 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1043,9 +1043,9 @@ static uint32_t skl_plane_formats[] = { }; struct intel_plane * -intel_sprite_plane_create(struct drm_device *dev, enum pipe pipe, int plane) +intel_sprite_plane_create(struct drm_i915_private *dev_priv, + enum pipe pipe, int plane) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *intel_plane = NULL; struct intel_plane_state *state = NULL; unsigned long possible_crtcs; @@ -1132,14 +1132,14 @@ intel_sprite_plane_create(struct drm_device *dev, enum pipe pipe, int plane) possible_crtcs = (1 << pipe); if (INTEL_GEN(dev_priv) >= 9) - ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, - &intel_plane_funcs, + ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base, + possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats, DRM_PLANE_TYPE_OVERLAY, "plane %d%c", plane + 2, pipe_name(pipe)); else - ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, - &intel_plane_funcs, + ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base, + possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats, DRM_PLANE_TYPE_OVERLAY, "sprite %c", sprite_name(pipe, plane)); -- cgit v1.2.3 From 65edcccef3b5ea5a67beebe9a6beeea9a837749f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:01 +0200 Subject: drm/i915: Pass dev_priv to skl_init_scalers() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. While at it let's do some house cleaning: s/intel_foo/foo/ and move things into tighter scope. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e48656789f37..0beee9e77fa2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -115,8 +115,9 @@ static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); -static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, - struct intel_crtc_state *crtc_state); +static void skl_init_scalers(struct drm_i915_private *dev_priv, + struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state); static void skylake_pfit_enable(struct intel_crtc *crtc); static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force); static void ironlake_pfit_enable(struct intel_crtc *crtc); @@ -10735,10 +10736,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK; if (INTEL_INFO(dev)->gen >= 9) { - skl_init_scalers(dev, crtc, pipe_config); - } + skl_init_scalers(dev_priv, crtc, pipe_config); - if (INTEL_INFO(dev)->gen >= 9) { pipe_config->scaler_state.scaler_id = -1; pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX); } @@ -15222,17 +15221,19 @@ fail: return ERR_PTR(ret); } -static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, - struct intel_crtc_state *crtc_state) +static void skl_init_scalers(struct drm_i915_private *dev_priv, + struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) { + struct intel_crtc_scaler_state *scaler_state = + &crtc_state->scaler_state; int i; - struct intel_scaler *intel_scaler; - struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; - for (i = 0; i < intel_crtc->num_scalers; i++) { - intel_scaler = &scaler_state->scalers[i]; - intel_scaler->in_use = 0; - intel_scaler->mode = PS_SCALER_MODE_DYN; + for (i = 0; i < crtc->num_scalers; i++) { + struct intel_scaler *scaler = &scaler_state->scalers[i]; + + scaler->in_use = 0; + scaler->mode = PS_SCALER_MODE_DYN; } scaler_state->scaler_id = -1; @@ -15267,7 +15268,7 @@ static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) else intel_crtc->num_scalers = SKL_NUM_SCALERS; - skl_init_scalers(dev, intel_crtc, crtc_state); + skl_init_scalers(dev_priv, intel_crtc, crtc_state); } primary = intel_primary_plane_create(dev_priv, pipe); -- cgit v1.2.3 From 525b9311be957e319680025e06f9f722ccfd54b7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:02 +0200 Subject: drm/i915: Pass intel_crtc to intel_crtc_active() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around intel_crtc instead of drm_crtc. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 8 +++----- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_fbc.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 8 ++++---- 4 files changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0beee9e77fa2..00784d950d51 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1008,10 +1008,8 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, target_clock, refclk, NULL, best_clock); } -bool intel_crtc_active(struct drm_crtc *crtc) +bool intel_crtc_active(struct intel_crtc *crtc) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - /* Be paranoid as we can arrive here with only partial * state retrieved from the hardware during setup. * @@ -1025,8 +1023,8 @@ bool intel_crtc_active(struct drm_crtc *crtc) * crtc->state->active once we have proper CRTC states wired up * for atomic. */ - return intel_crtc->active && crtc->primary->state->fb && - intel_crtc->config->base.adjusted_mode.crtc_clock; + return crtc->active && crtc->base.primary->state->fb && + crtc->config->base.adjusted_mode.crtc_clock; } enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index caa91d713fa2..67b90527217c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1349,7 +1349,7 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, struct dpll *best_clock); int chv_calc_dpll_params(int refclk, struct dpll *pll_clock); -bool intel_crtc_active(struct drm_crtc *crtc); +bool intel_crtc_active(struct intel_crtc *crtc); void hsw_enable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc); enum intel_display_power_domain diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index cbe2ebda4c40..e230d480c5e6 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -1306,7 +1306,7 @@ void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv) return; for_each_intel_crtc(&dev_priv->drm, crtc) - if (intel_crtc_active(&crtc->base) && + if (intel_crtc_active(crtc) && to_intel_plane_state(crtc->base.primary->state)->base.visible) dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe); } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9cfc19ece147..419c5eb88d7c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -630,7 +630,7 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) struct drm_crtc *crtc, *enabled = NULL; for_each_crtc(dev, crtc) { - if (intel_crtc_active(crtc)) { + if (intel_crtc_active(to_intel_crtc(crtc))) { if (enabled) return NULL; enabled = crtc; @@ -725,7 +725,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, int entries, tlb_miss; crtc = intel_get_crtc_for_plane(dev, plane); - if (!intel_crtc_active(crtc)) { + if (!intel_crtc_active(to_intel_crtc(crtc))) { *cursor_wm = cursor->guard_size; *plane_wm = display->guard_size; return false; @@ -1538,7 +1538,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) fifo_size = dev_priv->display.get_fifo_size(dev, 0); crtc = intel_get_crtc_for_plane(dev, 0); - if (intel_crtc_active(crtc)) { + if (intel_crtc_active(to_intel_crtc(crtc))) { const struct drm_display_mode *adjusted_mode; int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); if (IS_GEN2(dev_priv)) @@ -1560,7 +1560,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) fifo_size = dev_priv->display.get_fifo_size(dev, 1); crtc = intel_get_crtc_for_plane(dev, 1); - if (intel_crtc_active(crtc)) { + if (intel_crtc_active(to_intel_crtc(crtc))) { const struct drm_display_mode *adjusted_mode; int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); if (IS_GEN2(dev_priv)) -- cgit v1.2.3 From 432081bcbf9a605ea072f6aa3dd0b0420344878c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:03 +0200 Subject: drm/i915: Pass intel_crtc to update_wm functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around intel_crtc instead of drm_crtc. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 14 +++++----- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 50 +++++++++++++++++------------------- 4 files changed, 33 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ea1cfc649961..98f59863fe6b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -503,7 +503,7 @@ struct drm_i915_display_funcs { void (*initial_watermarks)(struct intel_crtc_state *cstate); void (*optimize_watermarks)(struct intel_crtc_state *cstate); int (*compute_global_watermarks)(struct drm_atomic_state *state); - void (*update_wm)(struct drm_crtc *crtc); + void (*update_wm)(struct intel_crtc *crtc); int (*modeset_calc_cdclk)(struct drm_atomic_state *state); void (*modeset_commit_cdclk)(struct drm_atomic_state *state); /* Returns the active state of the crtc, and if the crtc is active, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 00784d950d51..936870d18851 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5073,7 +5073,7 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) crtc->wm.cxsr_allowed = true; if (pipe_config->update_wm_post && pipe_config->base.active) - intel_update_watermarks(&crtc->base); + intel_update_watermarks(crtc); if (old_pri_state) { struct intel_plane_state *primary_state = @@ -5171,7 +5171,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) if (dev_priv->display.initial_watermarks != NULL) dev_priv->display.initial_watermarks(pipe_config); else if (pipe_config->update_wm_pre) - intel_update_watermarks(&crtc->base); + intel_update_watermarks(crtc); } static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask) @@ -5491,7 +5491,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (dev_priv->display.initial_watermarks != NULL) dev_priv->display.initial_watermarks(pipe_config); else - intel_update_watermarks(crtc); + intel_update_watermarks(intel_crtc); /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) @@ -6744,7 +6744,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, intel_color_load_luts(&pipe_config->base); - intel_update_watermarks(crtc); + intel_update_watermarks(intel_crtc); intel_enable_pipe(intel_crtc); assert_vblank_disabled(crtc); @@ -6797,7 +6797,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, intel_color_load_luts(&pipe_config->base); - intel_update_watermarks(crtc); + intel_update_watermarks(intel_crtc); intel_enable_pipe(intel_crtc); assert_vblank_disabled(crtc); @@ -6913,7 +6913,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) encoder->base.crtc = NULL; intel_fbc_disable(intel_crtc); - intel_update_watermarks(crtc); + intel_update_watermarks(intel_crtc); intel_disable_shared_dpll(intel_crtc); domains = intel_crtc->enabled_power_domains; @@ -14397,7 +14397,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) intel_check_pch_fifo_underruns(dev_priv); if (!crtc->state->active) - intel_update_watermarks(crtc); + intel_update_watermarks(intel_crtc); } } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 67b90527217c..8ae13a6d0cc3 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1709,7 +1709,7 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, void intel_init_clock_gating(struct drm_device *dev); void intel_suspend_hw(struct drm_device *dev); int ilk_wm_max_level(const struct drm_i915_private *dev_priv); -void intel_update_watermarks(struct drm_crtc *crtc); +void intel_update_watermarks(struct intel_crtc *crtc); void intel_init_pm(struct drm_device *dev); void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); void intel_pm_setup(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 419c5eb88d7c..9bcb15a74a83 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -640,9 +640,9 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) return enabled; } -static void pineview_update_wm(struct drm_crtc *unused_crtc) +static void pineview_update_wm(struct intel_crtc *unused_crtc) { - struct drm_device *dev = unused_crtc->dev; + struct drm_device *dev = unused_crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_crtc *crtc; const struct cxsr_latency *latency; @@ -1330,20 +1330,19 @@ static void vlv_merge_wm(struct drm_device *dev, } } -static void vlv_update_wm(struct drm_crtc *crtc) +static void vlv_update_wm(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + enum pipe pipe = crtc->pipe; struct vlv_wm_values wm = {}; - vlv_compute_wm(intel_crtc); + vlv_compute_wm(crtc); vlv_merge_wm(dev, &wm); if (memcmp(&dev_priv->wm.vlv, &wm, sizeof(wm)) == 0) { /* FIXME should be part of crtc atomic commit */ - vlv_pipe_set_fifo_size(intel_crtc); + vlv_pipe_set_fifo_size(crtc); return; } @@ -1359,9 +1358,9 @@ static void vlv_update_wm(struct drm_crtc *crtc) intel_set_memory_cxsr(dev_priv, false); /* FIXME should be part of crtc atomic commit */ - vlv_pipe_set_fifo_size(intel_crtc); + vlv_pipe_set_fifo_size(crtc); - vlv_write_wm_values(intel_crtc, &wm); + vlv_write_wm_values(crtc, &wm); DRM_DEBUG_KMS("Setting FIFO watermarks - %c: plane=%d, cursor=%d, " "sprite0=%d, sprite1=%d, SR: plane=%d, cursor=%d level=%d cxsr=%d\n", @@ -1385,9 +1384,9 @@ static void vlv_update_wm(struct drm_crtc *crtc) #define single_plane_enabled(mask) is_power_of_2(mask) -static void g4x_update_wm(struct drm_crtc *crtc) +static void g4x_update_wm(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev = crtc->base.dev; static const int sr_latency_ns = 12000; struct drm_i915_private *dev_priv = to_i915(dev); int planea_wm, planeb_wm, cursora_wm, cursorb_wm; @@ -1443,9 +1442,9 @@ static void g4x_update_wm(struct drm_crtc *crtc) intel_set_memory_cxsr(dev_priv, true); } -static void i965_update_wm(struct drm_crtc *unused_crtc) +static void i965_update_wm(struct intel_crtc *unused_crtc) { - struct drm_device *dev = unused_crtc->dev; + struct drm_device *dev = unused_crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_crtc *crtc; int srwm = 1; @@ -1517,9 +1516,9 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) #undef FW_WM -static void i9xx_update_wm(struct drm_crtc *unused_crtc) +static void i9xx_update_wm(struct intel_crtc *unused_crtc) { - struct drm_device *dev = unused_crtc->dev; + struct drm_device *dev = unused_crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); const struct intel_watermark_params *wm_info; uint32_t fwater_lo; @@ -1650,9 +1649,9 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) intel_set_memory_cxsr(dev_priv, true); } -static void i845_update_wm(struct drm_crtc *unused_crtc) +static void i845_update_wm(struct intel_crtc *unused_crtc) { - struct drm_device *dev = unused_crtc->dev; + struct drm_device *dev = unused_crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_crtc *crtc; const struct drm_display_mode *adjusted_mode; @@ -4193,18 +4192,17 @@ skl_compute_wm(struct drm_atomic_state *state) return 0; } -static void skl_update_wm(struct drm_crtc *crtc) +static void skl_update_wm(struct intel_crtc *intel_crtc) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_device *dev = crtc->dev; + struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct skl_wm_values *results = &dev_priv->wm.skl_results; struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw; - struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct intel_crtc_state *cstate = to_intel_crtc_state(intel_crtc->base.state); struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal; enum pipe pipe = intel_crtc->pipe; - if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0) + if ((results->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) == 0) return; mutex_lock(&dev_priv->wm.wm_mutex); @@ -4215,7 +4213,7 @@ static void skl_update_wm(struct drm_crtc *crtc) * the pipe's shut off, just do so here. Already active pipes will have * their watermarks updated once we update their planes. */ - if (crtc->state->active_changed) { + if (intel_crtc->base.state->active_changed) { int plane; for_each_universal_plane(dev_priv, pipe, plane) @@ -4654,9 +4652,9 @@ void ilk_wm_get_hw_state(struct drm_device *dev) * We don't use the sprite, so we can ignore that. And on Crestline we have * to set the non-SR watermarks to 8. */ -void intel_update_watermarks(struct drm_crtc *crtc) +void intel_update_watermarks(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (dev_priv->display.update_wm) dev_priv->display.update_wm(crtc); -- cgit v1.2.3 From efc2611e6ecbb14572b55f038a62439b845e3250 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:04 +0200 Subject: drm/i915: Use struct intel_crtc in legacy platform wm code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by using intel_crtc instead of drm_crtc. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-6-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_pm.c | 109 ++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9bcb15a74a83..f3bd2200d7c5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -625,12 +625,12 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, return wm_size; } -static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) +static struct intel_crtc *single_enabled_crtc(struct drm_device *dev) { - struct drm_crtc *crtc, *enabled = NULL; + struct intel_crtc *crtc, *enabled = NULL; - for_each_crtc(dev, crtc) { - if (intel_crtc_active(to_intel_crtc(crtc))) { + for_each_intel_crtc(dev, crtc) { + if (intel_crtc_active(crtc)) { if (enabled) return NULL; enabled = crtc; @@ -644,7 +644,7 @@ static void pineview_update_wm(struct intel_crtc *unused_crtc) { struct drm_device *dev = unused_crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_crtc *crtc; + struct intel_crtc *crtc; const struct cxsr_latency *latency; u32 reg; unsigned long wm; @@ -661,8 +661,11 @@ static void pineview_update_wm(struct intel_crtc *unused_crtc) crtc = single_enabled_crtc(dev); if (crtc) { - const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; - int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); + const struct drm_display_mode *adjusted_mode = + &crtc->config->base.adjusted_mode; + const struct drm_framebuffer *fb = + crtc->base.primary->state->fb; + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); int clock = adjusted_mode->crtc_clock; /* Display SR */ @@ -718,24 +721,26 @@ static bool g4x_compute_wm0(struct drm_device *dev, int *plane_wm, int *cursor_wm) { - struct drm_crtc *crtc; + struct intel_crtc *crtc; const struct drm_display_mode *adjusted_mode; + const struct drm_framebuffer *fb; int htotal, hdisplay, clock, cpp; int line_time_us, line_count; int entries, tlb_miss; - crtc = intel_get_crtc_for_plane(dev, plane); - if (!intel_crtc_active(to_intel_crtc(crtc))) { + crtc = to_intel_crtc(intel_get_crtc_for_plane(dev, plane)); + if (!intel_crtc_active(crtc)) { *cursor_wm = cursor->guard_size; *plane_wm = display->guard_size; return false; } - adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; + adjusted_mode = &crtc->config->base.adjusted_mode; + fb = crtc->base.primary->state->fb; clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->crtc_htotal; - hdisplay = to_intel_crtc(crtc)->config->pipe_src_w; - cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); + hdisplay = crtc->config->pipe_src_w; + cpp = drm_format_plane_cpp(fb->pixel_format, 0); /* Use the small buffer method to calculate plane watermark */ entries = ((clock * cpp / 1000) * display_latency_ns) / 1000; @@ -750,7 +755,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, /* Use the large buffer method to calculate cursor watermark */ line_time_us = max(htotal * 1000 / clock, 1); line_count = (cursor_latency_ns / line_time_us + 1000) / 1000; - entries = line_count * crtc->cursor->state->crtc_w * cpp; + entries = line_count * crtc->base.cursor->state->crtc_w * cpp; tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8; if (tlb_miss > 0) entries += tlb_miss; @@ -804,8 +809,9 @@ static bool g4x_compute_srwm(struct drm_device *dev, const struct intel_watermark_params *cursor, int *display_wm, int *cursor_wm) { - struct drm_crtc *crtc; + struct intel_crtc *crtc; const struct drm_display_mode *adjusted_mode; + const struct drm_framebuffer *fb; int hdisplay, htotal, cpp, clock; unsigned long line_time_us; int line_count, line_size; @@ -817,12 +823,13 @@ static bool g4x_compute_srwm(struct drm_device *dev, return false; } - crtc = intel_get_crtc_for_plane(dev, plane); - adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; + crtc = to_intel_crtc(intel_get_crtc_for_plane(dev, plane)); + adjusted_mode = &crtc->config->base.adjusted_mode; + fb = crtc->base.primary->state->fb; clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->crtc_htotal; - hdisplay = to_intel_crtc(crtc)->config->pipe_src_w; - cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); + hdisplay = crtc->config->pipe_src_w; + cpp = drm_format_plane_cpp(fb->pixel_format, 0); line_time_us = max(htotal * 1000 / clock, 1); line_count = (latency_ns / line_time_us + 1000) / 1000; @@ -836,7 +843,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, *display_wm = entries + display->guard_size; /* calculate the self-refresh watermark for display cursor */ - entries = line_count * cpp * crtc->cursor->state->crtc_w; + entries = line_count * cpp * crtc->base.cursor->state->crtc_w; entries = DIV_ROUND_UP(entries, cursor->cacheline_size); *cursor_wm = entries + cursor->guard_size; @@ -1446,7 +1453,7 @@ static void i965_update_wm(struct intel_crtc *unused_crtc) { struct drm_device *dev = unused_crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_crtc *crtc; + struct intel_crtc *crtc; int srwm = 1; int cursor_sr = 16; bool cxsr_enabled; @@ -1456,11 +1463,14 @@ static void i965_update_wm(struct intel_crtc *unused_crtc) if (crtc) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 12000; - const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = + &crtc->config->base.adjusted_mode; + const struct drm_framebuffer *fb = + crtc->base.primary->state->fb; int clock = adjusted_mode->crtc_clock; int htotal = adjusted_mode->crtc_htotal; - int hdisplay = to_intel_crtc(crtc)->config->pipe_src_w; - int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); + int hdisplay = crtc->config->pipe_src_w; + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); unsigned long line_time_us; int entries; @@ -1478,7 +1488,7 @@ static void i965_update_wm(struct intel_crtc *unused_crtc) entries, srwm); entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * - cpp * crtc->cursor->state->crtc_w; + cpp * crtc->base.cursor->state->crtc_w; entries = DIV_ROUND_UP(entries, i965_cursor_wm_info.cacheline_size); cursor_sr = i965_cursor_wm_info.fifo_size - @@ -1526,7 +1536,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) int cwm, srwm = 1; int fifo_size; int planea_wm, planeb_wm; - struct drm_crtc *crtc, *enabled = NULL; + struct intel_crtc *crtc, *enabled = NULL; if (IS_I945GM(dev)) wm_info = &i945_wm_info; @@ -1536,14 +1546,19 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) wm_info = &i830_a_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 0); - crtc = intel_get_crtc_for_plane(dev, 0); - if (intel_crtc_active(to_intel_crtc(crtc))) { - const struct drm_display_mode *adjusted_mode; - int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); + crtc = to_intel_crtc(intel_get_crtc_for_plane(dev, 0)); + if (intel_crtc_active(crtc)) { + const struct drm_display_mode *adjusted_mode = + &crtc->config->base.adjusted_mode; + const struct drm_framebuffer *fb = + crtc->base.primary->state->fb; + int cpp; + if (IS_GEN2(dev_priv)) cpp = 4; + else + cpp = drm_format_plane_cpp(fb->pixel_format, 0); - adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, wm_info, fifo_size, cpp, pessimal_latency_ns); @@ -1558,14 +1573,19 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) wm_info = &i830_bc_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 1); - crtc = intel_get_crtc_for_plane(dev, 1); - if (intel_crtc_active(to_intel_crtc(crtc))) { - const struct drm_display_mode *adjusted_mode; - int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); + crtc = to_intel_crtc(intel_get_crtc_for_plane(dev, 1)); + if (intel_crtc_active(crtc)) { + const struct drm_display_mode *adjusted_mode = + &crtc->config->base.adjusted_mode; + const struct drm_framebuffer *fb = + crtc->base.primary->state->fb; + int cpp; + if (IS_GEN2(dev_priv)) cpp = 4; + else + cpp = drm_format_plane_cpp(fb->pixel_format, 0); - adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock, wm_info, fifo_size, cpp, pessimal_latency_ns); @@ -1584,7 +1604,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) if (IS_I915GM(dev_priv) && enabled) { struct drm_i915_gem_object *obj; - obj = intel_fb_obj(enabled->primary->state->fb); + obj = intel_fb_obj(enabled->base.primary->state->fb); /* self-refresh seems busted with untiled */ if (!i915_gem_object_is_tiled(obj)) @@ -1603,16 +1623,21 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) if (HAS_FW_BLC(dev) && enabled) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 6000; - const struct drm_display_mode *adjusted_mode = &to_intel_crtc(enabled)->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = + &enabled->config->base.adjusted_mode; + const struct drm_framebuffer *fb = + enabled->base.primary->state->fb; int clock = adjusted_mode->crtc_clock; int htotal = adjusted_mode->crtc_htotal; - int hdisplay = to_intel_crtc(enabled)->config->pipe_src_w; - int cpp = drm_format_plane_cpp(enabled->primary->state->fb->pixel_format, 0); + int hdisplay = enabled->config->pipe_src_w; + int cpp; unsigned long line_time_us; int entries; if (IS_I915GM(dev_priv) || IS_I945GM(dev_priv)) cpp = 4; + else + cpp = drm_format_plane_cpp(fb->pixel_format, 0); line_time_us = max(htotal * 1000 / clock, 1); @@ -1653,7 +1678,7 @@ static void i845_update_wm(struct intel_crtc *unused_crtc) { struct drm_device *dev = unused_crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_crtc *crtc; + struct intel_crtc *crtc; const struct drm_display_mode *adjusted_mode; uint32_t fwater_lo; int planea_wm; @@ -1662,7 +1687,7 @@ static void i845_update_wm(struct intel_crtc *unused_crtc) if (crtc == NULL) return; - adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; + adjusted_mode = &crtc->config->base.adjusted_mode; planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, &i845_wm_info, dev_priv->display.get_fifo_size(dev, 0), -- cgit v1.2.3 From e2af48c66b41fecbec5bc1b07640c2419a724c34 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:05 +0200 Subject: drm/i915: Store struct intel_crtc * in {pipe,plane}_to_crtc_mapping[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A lot of users of the {pipe,plane}_to_crtc_mapping[] will end up casting the result to intel_crtc, so let's just store the intel_crtc pointer in the first place. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-7-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 9 ++-- drivers/gpu/drm/i915/i915_drv.h | 4 +- drivers/gpu/drm/i915/i915_irq.c | 12 +++--- drivers/gpu/drm/i915/intel_display.c | 68 ++++++++++++++---------------- drivers/gpu/drm/i915/intel_drv.h | 7 ++- drivers/gpu/drm/i915/intel_dvo.c | 4 +- drivers/gpu/drm/i915/intel_fifo_underrun.c | 22 +++++----- drivers/gpu/drm/i915/intel_lvds.c | 4 +- drivers/gpu/drm/i915/intel_pm.c | 10 ++--- 9 files changed, 64 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index bf19192dcc3b..1696f7b7321c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4065,8 +4065,7 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv, bool enable) { struct drm_device *dev = &dev_priv->drm; - struct intel_crtc *crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]); + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[PIPE_A]; struct intel_crtc_state *pipe_config; struct drm_atomic_state *state; int ret = 0; @@ -4134,8 +4133,7 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, { struct drm_device *dev = &dev_priv->drm; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - struct intel_crtc *crtc = - to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev, pipe); enum intel_display_power_domain power_domain; u32 val = 0; /* shut up gcc */ int ret; @@ -4206,8 +4204,7 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, /* real source -> none transition */ if (source == INTEL_PIPE_CRC_SOURCE_NONE) { struct intel_pipe_crc_entry *entries; - struct intel_crtc *crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", pipe_name(pipe)); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 98f59863fe6b..eeed752da9df 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1935,8 +1935,8 @@ struct drm_i915_private { /* Kernel Modesetting */ - struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES]; - struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES]; + struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES]; + struct intel_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES]; wait_queue_head_t pending_flip_queue; #ifdef CONFIG_DEBUG_FS diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4dda2b1eefdb..696dc6f339ac 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -725,8 +725,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe) struct drm_i915_private *dev_priv = to_i915(dev); i915_reg_t high_frame, low_frame; u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; - struct intel_crtc *intel_crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + struct intel_crtc *intel_crtc = dev_priv->pipe_to_crtc_mapping[pipe]; const struct drm_display_mode *mode = &intel_crtc->base.hwmode; htotal = mode->crtc_htotal; @@ -831,8 +830,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, const struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *intel_crtc = dev_priv->pipe_to_crtc_mapping[pipe]; int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; bool in_vbl = true; @@ -967,7 +965,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, struct timeval *vblank_time, unsigned flags) { - struct drm_crtc *crtc; + struct intel_crtc *crtc; if (pipe >= INTEL_INFO(dev)->num_pipes) { DRM_ERROR("Invalid crtc %u\n", pipe); @@ -981,7 +979,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, return -EINVAL; } - if (!crtc->hwmode.crtc_clock) { + if (!crtc->base.hwmode.crtc_clock) { DRM_DEBUG_KMS("crtc %u is disabled\n", pipe); return -EBUSY; } @@ -989,7 +987,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, /* Helper routine in DRM core does all the work: */ return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, vblank_time, flags, - &crtc->hwmode); + &crtc->base.hwmode); } static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 936870d18851..bed201a65f09 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1030,10 +1030,9 @@ bool intel_crtc_active(struct intel_crtc *crtc) enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - return intel_crtc->config->cpu_transcoder; + return crtc->config->cpu_transcoder; } static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe) @@ -1786,8 +1785,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *intel_crtc = dev_priv->pipe_to_crtc_mapping[pipe]; i915_reg_t reg; uint32_t val, pipeconf_val; @@ -7073,7 +7071,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, if (pipe_config->fdi_lanes <= 2) return 0; - other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_C)); + other_crtc = intel_get_crtc_for_pipe(dev, PIPE_C); other_crtc_state = intel_atomic_get_crtc_state(state, other_crtc); if (IS_ERR(other_crtc_state)) @@ -7092,7 +7090,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, return -EINVAL; } - other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_B)); + other_crtc = intel_get_crtc_for_pipe(dev, PIPE_B); other_crtc_state = intel_atomic_get_crtc_state(state, other_crtc); if (IS_ERR(other_crtc_state)) @@ -8107,8 +8105,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc, int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, const struct dpll *dpll) { - struct intel_crtc *crtc = - to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev, pipe); struct intel_crtc_state *pipe_config; pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); @@ -11663,8 +11660,7 @@ static bool pageflip_finished(struct intel_crtc *crtc, void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe) { struct drm_device *dev = &dev_priv->drm; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_flip_work *work; unsigned long flags; @@ -11677,12 +11673,12 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe) * lost pageflips) so needs the full irqsave spinlocks. */ spin_lock_irqsave(&dev->event_lock, flags); - work = intel_crtc->flip_work; + work = crtc->flip_work; if (work != NULL && !is_mmio_work(work) && - pageflip_finished(intel_crtc, work)) - page_flip_completed(intel_crtc); + pageflip_finished(crtc, work)) + page_flip_completed(crtc); spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -11690,8 +11686,7 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe) void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe) { struct drm_device *dev = &dev_priv->drm; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_flip_work *work; unsigned long flags; @@ -11704,12 +11699,12 @@ void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe) * lost pageflips) so needs the full irqsave spinlocks. */ spin_lock_irqsave(&dev->event_lock, flags); - work = intel_crtc->flip_work; + work = crtc->flip_work; if (work != NULL && is_mmio_work(work) && - pageflip_finished(intel_crtc, work)) - page_flip_completed(intel_crtc); + pageflip_finished(crtc, work)) + page_flip_completed(crtc); spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -12121,8 +12116,7 @@ static bool __pageflip_stall_check_cs(struct drm_i915_private *dev_priv, void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe) { struct drm_device *dev = &dev_priv->drm; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_flip_work *work; WARN_ON(!in_interrupt()); @@ -12131,19 +12125,19 @@ void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe) return; spin_lock(&dev->event_lock); - work = intel_crtc->flip_work; + work = crtc->flip_work; if (work != NULL && !is_mmio_work(work) && - __pageflip_stall_check_cs(dev_priv, intel_crtc, work)) { + __pageflip_stall_check_cs(dev_priv, crtc, work)) { WARN_ONCE(1, "Kicking stuck page flip: queued at %d, now %d\n", - work->flip_queued_vblank, intel_crtc_get_vblank_counter(intel_crtc)); - page_flip_completed(intel_crtc); + work->flip_queued_vblank, intel_crtc_get_vblank_counter(crtc)); + page_flip_completed(crtc); work = NULL; } if (work != NULL && !is_mmio_work(work) && - intel_crtc_get_vblank_counter(intel_crtc) - work->flip_queued_vblank > 1) + intel_crtc_get_vblank_counter(crtc) - work->flip_queued_vblank > 1) intel_queue_rps_boost_for_request(work->flip_queued_req); spin_unlock(&dev->event_lock); } @@ -14181,22 +14175,22 @@ static void intel_atomic_wait_for_vblanks(struct drm_device *dev, return; for_each_pipe(dev_priv, pipe) { - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; if (!((1 << pipe) & crtc_mask)) continue; - ret = drm_crtc_vblank_get(crtc); + ret = drm_crtc_vblank_get(&crtc->base); if (WARN_ON(ret != 0)) { crtc_mask &= ~(1 << pipe); continue; } - last_vblank_count[pipe] = drm_crtc_vblank_count(crtc); + last_vblank_count[pipe] = drm_crtc_vblank_count(&crtc->base); } for_each_pipe(dev_priv, pipe) { - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; long lret; if (!((1 << pipe) & crtc_mask)) @@ -14204,12 +14198,12 @@ static void intel_atomic_wait_for_vblanks(struct drm_device *dev, lret = wait_event_timeout(dev->vblank[pipe].queue, last_vblank_count[pipe] != - drm_crtc_vblank_count(crtc), + drm_crtc_vblank_count(&crtc->base), msecs_to_jiffies(50)); WARN(!lret, "pipe %c vblank wait timed out\n", pipe_name(pipe)); - drm_crtc_vblank_put(crtc); + drm_crtc_vblank_put(&crtc->base); } } @@ -15317,8 +15311,8 @@ static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL); - dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base; - dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; + dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = intel_crtc; + dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = intel_crtc; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); @@ -16871,7 +16865,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) pipe = 0; if (encoder->get_hw_state(encoder, &pipe)) { - crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + encoder->base.crtc = &crtc->base; crtc->config->output_types |= 1 << encoder->type; encoder->get_config(encoder, crtc->config); @@ -16972,7 +16967,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev) } for_each_pipe(dev_priv, pipe) { - crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + intel_sanitize_crtc(crtc); intel_dump_pipe_config(crtc, crtc->config, "[setup_hw_state]"); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8ae13a6d0cc3..58e33c3a1bdf 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1028,14 +1028,14 @@ vlv_pipe_to_channel(enum pipe pipe) } } -static inline struct drm_crtc * +static inline struct intel_crtc * intel_get_crtc_for_pipe(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); return dev_priv->pipe_to_crtc_mapping[pipe]; } -static inline struct drm_crtc * +static inline struct intel_crtc * intel_get_crtc_for_plane(struct drm_device *dev, int plane) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -1251,8 +1251,7 @@ intel_wait_for_vblank(struct drm_device *dev, int pipe) static inline void intel_wait_for_vblank_if_active(struct drm_device *dev, int pipe) { - const struct intel_crtc *crtc = - to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + const struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev, pipe); if (crtc->active) intel_wait_for_vblank(dev, pipe); diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index cd574900cd8d..61d78fc36b6d 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -393,12 +393,12 @@ intel_dvo_get_current_mode(struct drm_connector *connector) * its timings to get how the BIOS set up the panel. */ if (dvo_val & DVO_ENABLE) { - struct drm_crtc *crtc; + struct intel_crtc *crtc; int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; crtc = intel_get_crtc_for_pipe(dev, pipe); if (crtc) { - mode = intel_crtc_mode_get(dev, crtc); + mode = intel_crtc_mode_get(dev, &crtc->base); if (mode) { mode->type |= DRM_MODE_TYPE_PREFERRED; if (dvo_val & DVO_HSYNC_ACTIVE_HIGH) diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 3018f4f589c8..34f93f112107 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -57,7 +57,7 @@ static bool ivb_can_enable_err_int(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); for_each_pipe(dev_priv, pipe) { - crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; if (crtc->cpu_fifo_underrun_disabled) return false; @@ -75,7 +75,7 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); for_each_pipe(dev_priv, pipe) { - crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; if (crtc->pch_fifo_underrun_disabled) return false; @@ -245,14 +245,13 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, enum pipe pipe, bool enable) { struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; bool old; assert_spin_locked(&dev_priv->irq_lock); - old = !intel_crtc->cpu_fifo_underrun_disabled; - intel_crtc->cpu_fifo_underrun_disabled = !enable; + old = !crtc->cpu_fifo_underrun_disabled; + crtc->cpu_fifo_underrun_disabled = !enable; if (HAS_GMCH_DISPLAY(dev_priv)) i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old); @@ -314,8 +313,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv, enum transcoder pch_transcoder, bool enable) { - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder]; unsigned long flags; bool old; @@ -330,8 +328,8 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv, spin_lock_irqsave(&dev_priv->irq_lock, flags); - old = !intel_crtc->pch_fifo_underrun_disabled; - intel_crtc->pch_fifo_underrun_disabled = !enable; + old = !crtc->pch_fifo_underrun_disabled; + crtc->pch_fifo_underrun_disabled = !enable; if (HAS_PCH_IBX(dev_priv)) ibx_set_fifo_underrun_reporting(&dev_priv->drm, @@ -358,7 +356,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv, void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; /* We may be called too early in init, thanks BIOS! */ if (crtc == NULL) @@ -366,7 +364,7 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, /* GMCH can't disable fifo underruns, filter them. */ if (HAS_GMCH_DISPLAY(dev_priv) && - to_intel_crtc(crtc)->cpu_fifo_underrun_disabled) + crtc->cpu_fifo_underrun_disabled) return; if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 199b90c7907a..81ed32b4f899 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -985,7 +985,7 @@ void intel_lvds_init(struct drm_device *dev) struct drm_display_mode *fixed_mode = NULL; struct drm_display_mode *downclock_mode = NULL; struct edid *edid; - struct drm_crtc *crtc; + struct intel_crtc *crtc; i915_reg_t lvds_reg; u32 lvds; int pipe; @@ -1166,7 +1166,7 @@ void intel_lvds_init(struct drm_device *dev) crtc = intel_get_crtc_for_pipe(dev, pipe); if (crtc && (lvds & LVDS_PORT_EN)) { - fixed_mode = intel_crtc_mode_get(dev, crtc); + fixed_mode = intel_crtc_mode_get(dev, &crtc->base); if (fixed_mode) { DRM_DEBUG_KMS("using current (BIOS) mode: "); drm_mode_debug_printmodeline(fixed_mode); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f3bd2200d7c5..8d1040c7ed8d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -728,7 +728,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, int line_time_us, line_count; int entries, tlb_miss; - crtc = to_intel_crtc(intel_get_crtc_for_plane(dev, plane)); + crtc = intel_get_crtc_for_plane(dev, plane); if (!intel_crtc_active(crtc)) { *cursor_wm = cursor->guard_size; *plane_wm = display->guard_size; @@ -823,7 +823,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, return false; } - crtc = to_intel_crtc(intel_get_crtc_for_plane(dev, plane)); + crtc = intel_get_crtc_for_plane(dev, plane); adjusted_mode = &crtc->config->base.adjusted_mode; fb = crtc->base.primary->state->fb; clock = adjusted_mode->crtc_clock; @@ -1546,7 +1546,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) wm_info = &i830_a_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 0); - crtc = to_intel_crtc(intel_get_crtc_for_plane(dev, 0)); + crtc = intel_get_crtc_for_plane(dev, 0); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; @@ -1573,7 +1573,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) wm_info = &i830_bc_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 1); - crtc = to_intel_crtc(intel_get_crtc_for_plane(dev, 1)); + crtc = intel_get_crtc_for_plane(dev, 1); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; @@ -3066,7 +3066,7 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) /* Since we're now guaranteed to only have one active CRTC... */ pipe = ffs(intel_state->active_crtcs) - 1; - crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; cstate = to_intel_crtc_state(crtc->base.state); if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) -- cgit v1.2.3 From 0f0f74bc83aa2902914d6c4ecee3d5d37338f591 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:06 +0200 Subject: drm/i915: Pass dev_priv to intel_wait_for_vblank() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-8-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 30 ++++++++++++++++-------------- drivers/gpu/drm/i915/intel_dp.c | 18 +++++++++--------- drivers/gpu/drm/i915/intel_drv.h | 10 +++++----- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 4 ++-- drivers/gpu/drm/i915/intel_tv.c | 6 +++--- 8 files changed, 38 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1696f7b7321c..ce6aa7eef188 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4211,7 +4211,7 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, drm_modeset_lock(&crtc->base.mutex, NULL); if (crtc->base.state->active) - intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev_priv, pipe); drm_modeset_unlock(&crtc->base.mutex); spin_lock_irq(&pipe_crc->lock); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index a97151fcb9f4..30eb95b54dcf 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -573,7 +573,7 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe) POSTING_READ(pipeconf_reg); /* Wait for next Vblank to substitue * border color for Color info */ - intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev_priv, pipe); st00 = I915_READ8(_VGA_MSR_WRITE); status = ((st00 & (1 << 4)) != 0) ? connector_status_connected : diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bed201a65f09..50901b030f80 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4249,6 +4249,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) bool intel_has_pending_fb_unpin(struct drm_device *dev) { + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *crtc; /* Note that we don't need to be called with mode_config.lock here @@ -4263,7 +4264,7 @@ bool intel_has_pending_fb_unpin(struct drm_device *dev) continue; if (crtc->flip_work) - intel_wait_for_vblank(dev, crtc->pipe); + intel_wait_for_vblank(dev_priv, crtc->pipe); return true; } @@ -4940,7 +4941,7 @@ void hsw_disable_ips(struct intel_crtc *crtc) } /* We need to wait for a vblank before we can disable the plane. */ - intel_wait_for_vblank(dev, crtc->pipe); + intel_wait_for_vblank(dev_priv, crtc->pipe); } static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc) @@ -5052,7 +5053,7 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) if (HAS_GMCH_DISPLAY(dev_priv)) { intel_set_memory_cxsr(dev_priv, false); dev_priv->wm.vlv.cxsr = false; - intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev_priv, pipe); } } @@ -5129,7 +5130,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) if (old_crtc_state->base.active) { intel_set_memory_cxsr(dev_priv, false); dev_priv->wm.vlv.cxsr = false; - intel_wait_for_vblank(dev, crtc->pipe); + intel_wait_for_vblank(dev_priv, crtc->pipe); } } @@ -5142,7 +5143,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) */ if (pipe_config->disable_lp_wm) { ilk_disable_lp_wm(dev); - intel_wait_for_vblank(dev, crtc->pipe); + intel_wait_for_vblank(dev_priv, crtc->pipe); } /* @@ -5397,7 +5398,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, /* Must wait for vblank to avoid spurious PCH FIFO underruns */ if (intel_crtc->config->has_pch_encoder) - intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev_priv, pipe); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); } @@ -5507,8 +5508,8 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_enable(crtc, pipe_config, old_state); if (intel_crtc->config->has_pch_encoder) { - intel_wait_for_vblank(dev, pipe); - intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev_priv, pipe); + intel_wait_for_vblank(dev_priv, pipe); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, true); @@ -5518,8 +5519,8 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, * to change the workaround. */ hsw_workaround_pipe = pipe_config->hsw_workaround_pipe; if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) { - intel_wait_for_vblank(dev, hsw_workaround_pipe); - intel_wait_for_vblank(dev, hsw_workaround_pipe); + intel_wait_for_vblank(dev_priv, hsw_workaround_pipe); + intel_wait_for_vblank(dev_priv, hsw_workaround_pipe); } } @@ -6833,7 +6834,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, * wait for planes to fully turn off before disabling the pipe. */ if (IS_GEN2(dev_priv)) - intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev_priv, pipe); intel_encoders_disable(crtc, old_crtc_state, old_state); @@ -11129,6 +11130,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = NULL; struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct drm_framebuffer *fb; struct drm_mode_config *config = &dev->mode_config; struct drm_atomic_state *state = NULL, *restore_state = NULL; @@ -11281,7 +11283,7 @@ found: old->restore_state = restore_state; /* let the connector get through one full cycle before testing */ - intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_wait_for_vblank(dev_priv, intel_crtc->pipe); return true; fail: @@ -14277,7 +14279,7 @@ static void intel_update_crtcs(struct drm_atomic_state *state, static void skl_update_crtcs(struct drm_atomic_state *state, unsigned int *crtc_vblank_mask) { - struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(state->dev); struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_crtc *crtc; struct intel_crtc *intel_crtc; @@ -14328,7 +14330,7 @@ static void skl_update_crtcs(struct drm_atomic_state *state, crtc_vblank_mask); if (vbl_wait) - intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev_priv, pipe); progress = true; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1063afe5174d..9c1921a2e239 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2364,7 +2364,7 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp, * 2. Program DP PLL enable */ if (IS_GEN5(dev_priv)) - intel_wait_for_vblank_if_active(&dev_priv->drm, !crtc->pipe); + intel_wait_for_vblank_if_active(dev_priv, !crtc->pipe); intel_dp->DP |= DP_PLL_ENABLE; @@ -3487,7 +3487,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) I915_WRITE(intel_dp->output_reg, DP); POSTING_READ(intel_dp->output_reg); - intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A); + intel_wait_for_vblank_if_active(dev_priv, PIPE_A); intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true); intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } @@ -3667,7 +3667,7 @@ intel_dp_configure_mst(struct intel_dp *intel_dp) static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); u8 buf; int ret = 0; @@ -3688,7 +3688,7 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) } do { - intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_wait_for_vblank(dev_priv, intel_crtc->pipe); if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) { @@ -3711,7 +3711,7 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); u8 buf; int ret; @@ -3739,14 +3739,14 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) return -EIO; } - intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_wait_for_vblank(dev_priv, intel_crtc->pipe); return 0; } int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); u8 buf; int count, ret; @@ -3757,7 +3757,7 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) return ret; do { - intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_wait_for_vblank(dev_priv, intel_crtc->pipe); if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) { @@ -3990,7 +3990,7 @@ intel_dp_retrain_link(struct intel_dp *intel_dp) intel_dp_stop_link_train(intel_dp); /* Keep underrun reporting disabled until things are stable */ - intel_wait_for_vblank(&dev_priv->drm, crtc->pipe); + intel_wait_for_vblank(dev_priv, crtc->pipe); intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true); if (crtc->config->has_pch_encoder) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 58e33c3a1bdf..6c096e4fa7bf 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1244,17 +1244,17 @@ intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state) (1 << INTEL_OUTPUT_EDP)); } static inline void -intel_wait_for_vblank(struct drm_device *dev, int pipe) +intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) { - drm_wait_one_vblank(dev, pipe); + drm_wait_one_vblank(&dev_priv->drm, pipe); } static inline void -intel_wait_for_vblank_if_active(struct drm_device *dev, int pipe) +intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, int pipe) { - const struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev, pipe); + const struct intel_crtc *crtc = intel_get_crtc_for_pipe(&dev_priv->drm, pipe); if (crtc->active) - intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev_priv, pipe); } u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index af8715f31807..35ada4e1c6cf 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1164,7 +1164,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder, I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); - intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A); + intel_wait_for_vblank_if_active(dev_priv, PIPE_A); intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true); intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 49fb95d03d74..5d59a48e3249 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1472,7 +1472,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder, temp &= ~SDVO_ENABLE; intel_sdvo_write_sdvox(intel_sdvo, temp); - intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A); + intel_wait_for_vblank_if_active(dev_priv, PIPE_A); intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true); intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } @@ -1509,7 +1509,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder, intel_sdvo_write_sdvox(intel_sdvo, temp); for (i = 0; i < 2; i++) - intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_wait_for_vblank(dev_priv, intel_crtc->pipe); success = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2); /* Warn if the device reported failure to sync. diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 7118fb55f57f..9212f00d5752 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -856,7 +856,7 @@ intel_enable_tv(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(dev); /* Prevents vblank waits from timing out in intel_tv_detect_type() */ - intel_wait_for_vblank(encoder->base.dev, + intel_wait_for_vblank(dev_priv, to_intel_crtc(encoder->base.crtc)->pipe); I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE); @@ -1238,7 +1238,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv, I915_WRITE(TV_DAC, tv_dac); POSTING_READ(TV_DAC); - intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_wait_for_vblank(dev_priv, intel_crtc->pipe); type = -1; tv_dac = I915_READ(TV_DAC); @@ -1268,7 +1268,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv, POSTING_READ(TV_CTL); /* For unknown reasons the hw barfs if we don't do this vblank wait. */ - intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_wait_for_vblank(dev_priv, intel_crtc->pipe); /* Restore interrupt config */ if (connector->polled & DRM_CONNECTOR_POLL_HPD) { -- cgit v1.2.3 From 30ad9814d5ce93423a0f1e6206ae94f15ed95a24 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:07 +0200 Subject: drm/i915: Pass dev_priv to vlv force pll functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-9-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 14 +++++++------- drivers/gpu/drm/i915/intel_dp.c | 7 +++---- drivers/gpu/drm/i915/intel_drv.h | 4 ++-- 3 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 50901b030f80..419c6a2b3acf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8103,10 +8103,10 @@ static void chv_prepare_pll(struct intel_crtc *crtc, * in cases where we need the PLL enabled even when @pipe is not going to * be enabled. */ -int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, +int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe, const struct dpll *dpll) { - struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev, pipe); + struct intel_crtc *crtc = intel_get_crtc_for_pipe(&dev_priv->drm, pipe); struct intel_crtc_state *pipe_config; pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); @@ -8117,7 +8117,7 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, pipe_config->pixel_multiplier = 1; pipe_config->dpll = *dpll; - if (IS_CHERRYVIEW(to_i915(dev))) { + if (IS_CHERRYVIEW(dev_priv)) { chv_compute_dpll(crtc, pipe_config); chv_prepare_pll(crtc, pipe_config); chv_enable_pll(crtc, pipe_config); @@ -8140,12 +8140,12 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, * Disable the PLL for @pipe. To be used in cases where we need * the PLL enabled even when @pipe is not going to be enabled. */ -void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe) +void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe) { - if (IS_CHERRYVIEW(to_i915(dev))) - chv_disable_pll(to_i915(dev), pipe); + if (IS_CHERRYVIEW(dev_priv)) + chv_disable_pll(dev_priv, pipe); else - vlv_disable_pll(to_i915(dev), pipe); + vlv_disable_pll(dev_priv, pipe); } static void i9xx_compute_dpll(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9c1921a2e239..9df331b3305b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -395,8 +395,7 @@ static void vlv_power_sequencer_kick(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); enum pipe pipe = intel_dp->pps_pipe; bool pll_enabled, release_cl_override = false; enum dpio_phy phy = DPIO_PHY(pipe); @@ -434,7 +433,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) release_cl_override = IS_CHERRYVIEW(dev_priv) && !chv_phy_powergate_ch(dev_priv, phy, ch, true); - if (vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev_priv) ? + if (vlv_force_pll_on(dev_priv, pipe, IS_CHERRYVIEW(dev_priv) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) { DRM_ERROR("Failed to force on pll for pipe %c!\n", pipe_name(pipe)); @@ -458,7 +457,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) POSTING_READ(intel_dp->output_reg); if (!pll_enabled) { - vlv_force_pll_off(dev, pipe); + vlv_force_pll_off(dev_priv, pipe); if (release_cl_override) chv_phy_powergate_ch(dev_priv, phy, ch, false); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6c096e4fa7bf..7c0af57819f9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1301,9 +1301,9 @@ unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, enum pipe pipe); -int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, +int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe, const struct dpll *dpll); -void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe); +void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe); int lpt_get_iclkip(struct drm_i915_private *dev_priv); /* modesetting asserts */ -- cgit v1.2.3 From f0ce23104012d7a153a079890d6070c2a184f8fa Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:08 +0200 Subject: drm/i915: Pass dev_priv to g4x wm functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-10-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_pm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8d1040c7ed8d..c9990a9f9759 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -712,7 +712,7 @@ static void pineview_update_wm(struct intel_crtc *unused_crtc) } } -static bool g4x_compute_wm0(struct drm_device *dev, +static bool g4x_compute_wm0(struct drm_i915_private *dev_priv, int plane, const struct intel_watermark_params *display, int display_latency_ns, @@ -728,7 +728,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, int line_time_us, line_count; int entries, tlb_miss; - crtc = intel_get_crtc_for_plane(dev, plane); + crtc = intel_get_crtc_for_plane(&dev_priv->drm, plane); if (!intel_crtc_active(crtc)) { *cursor_wm = cursor->guard_size; *plane_wm = display->guard_size; @@ -774,7 +774,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, * can be programmed into the associated watermark register, that watermark * must be disabled. */ -static bool g4x_check_srwm(struct drm_device *dev, +static bool g4x_check_srwm(struct drm_i915_private *dev_priv, int display_wm, int cursor_wm, const struct intel_watermark_params *display, const struct intel_watermark_params *cursor) @@ -802,7 +802,7 @@ static bool g4x_check_srwm(struct drm_device *dev, return true; } -static bool g4x_compute_srwm(struct drm_device *dev, +static bool g4x_compute_srwm(struct drm_i915_private *dev_priv, int plane, int latency_ns, const struct intel_watermark_params *display, @@ -823,7 +823,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, return false; } - crtc = intel_get_crtc_for_plane(dev, plane); + crtc = intel_get_crtc_for_plane(&dev_priv->drm, plane); adjusted_mode = &crtc->config->base.adjusted_mode; fb = crtc->base.primary->state->fb; clock = adjusted_mode->crtc_clock; @@ -847,7 +847,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, entries = DIV_ROUND_UP(entries, cursor->cacheline_size); *cursor_wm = entries + cursor->guard_size; - return g4x_check_srwm(dev, + return g4x_check_srwm(dev_priv, *display_wm, *cursor_wm, display, cursor); } @@ -1401,20 +1401,20 @@ static void g4x_update_wm(struct intel_crtc *crtc) unsigned int enabled = 0; bool cxsr_enabled; - if (g4x_compute_wm0(dev, PIPE_A, + if (g4x_compute_wm0(dev_priv, PIPE_A, &g4x_wm_info, pessimal_latency_ns, &g4x_cursor_wm_info, pessimal_latency_ns, &planea_wm, &cursora_wm)) enabled |= 1 << PIPE_A; - if (g4x_compute_wm0(dev, PIPE_B, + if (g4x_compute_wm0(dev_priv, PIPE_B, &g4x_wm_info, pessimal_latency_ns, &g4x_cursor_wm_info, pessimal_latency_ns, &planeb_wm, &cursorb_wm)) enabled |= 1 << PIPE_B; if (single_plane_enabled(enabled) && - g4x_compute_srwm(dev, ffs(enabled) - 1, + g4x_compute_srwm(dev_priv, ffs(enabled) - 1, sr_latency_ns, &g4x_wm_info, &g4x_cursor_wm_info, -- cgit v1.2.3 From b91eb5cce65047eced9d13e8e15b46dced0c3c53 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:09 +0200 Subject: drm/i915: Pass dev_priv to intel_get_crtc_for_pipe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-11-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 3 +-- drivers/gpu/drm/i915/i915_irq.c | 5 +++-- drivers/gpu/drm/i915/intel_display.c | 6 +++--- drivers/gpu/drm/i915/intel_drv.h | 8 +++----- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 11 +++++------ 7 files changed, 17 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ce6aa7eef188..008f91d5df76 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4131,9 +4131,8 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, enum pipe pipe, enum intel_pipe_crc_source source) { - struct drm_device *dev = &dev_priv->drm; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev, pipe); + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); enum intel_display_power_domain power_domain; u32 val = 0; /* shut up gcc */ int ret; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 696dc6f339ac..48bb5debb3ef 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -965,15 +965,16 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, struct timeval *vblank_time, unsigned flags) { + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *crtc; - if (pipe >= INTEL_INFO(dev)->num_pipes) { + if (pipe >= INTEL_INFO(dev_priv)->num_pipes) { DRM_ERROR("Invalid crtc %u\n", pipe); return -EINVAL; } /* Get drm_crtc to timestamp: */ - crtc = intel_get_crtc_for_pipe(dev, pipe); + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); if (crtc == NULL) { DRM_ERROR("Invalid crtc %u\n", pipe); return -EINVAL; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 419c6a2b3acf..3cb41338894c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7072,7 +7072,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, if (pipe_config->fdi_lanes <= 2) return 0; - other_crtc = intel_get_crtc_for_pipe(dev, PIPE_C); + other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_C); other_crtc_state = intel_atomic_get_crtc_state(state, other_crtc); if (IS_ERR(other_crtc_state)) @@ -7091,7 +7091,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, return -EINVAL; } - other_crtc = intel_get_crtc_for_pipe(dev, PIPE_B); + other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_B); other_crtc_state = intel_atomic_get_crtc_state(state, other_crtc); if (IS_ERR(other_crtc_state)) @@ -8106,7 +8106,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc, int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe, const struct dpll *dpll) { - struct intel_crtc *crtc = intel_get_crtc_for_pipe(&dev_priv->drm, pipe); + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); struct intel_crtc_state *pipe_config; pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7c0af57819f9..0fdd546ac8d8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1029,16 +1029,14 @@ vlv_pipe_to_channel(enum pipe pipe) } static inline struct intel_crtc * -intel_get_crtc_for_pipe(struct drm_device *dev, int pipe) +intel_get_crtc_for_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(dev); return dev_priv->pipe_to_crtc_mapping[pipe]; } static inline struct intel_crtc * -intel_get_crtc_for_plane(struct drm_device *dev, int plane) +intel_get_crtc_for_plane(struct drm_i915_private *dev_priv, enum plane plane) { - struct drm_i915_private *dev_priv = to_i915(dev); return dev_priv->plane_to_crtc_mapping[plane]; } @@ -1251,7 +1249,7 @@ intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) static inline void intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, int pipe) { - const struct intel_crtc *crtc = intel_get_crtc_for_pipe(&dev_priv->drm, pipe); + const struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); if (crtc->active) intel_wait_for_vblank(dev_priv, pipe); diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 61d78fc36b6d..708645443046 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -396,7 +396,7 @@ intel_dvo_get_current_mode(struct drm_connector *connector) struct intel_crtc *crtc; int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; - crtc = intel_get_crtc_for_pipe(dev, pipe); + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); if (crtc) { mode = intel_crtc_mode_get(dev, &crtc->base); if (mode) { diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 81ed32b4f899..de7b3e6ed477 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -1163,7 +1163,7 @@ void intel_lvds_init(struct drm_device *dev) goto failed; pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; - crtc = intel_get_crtc_for_pipe(dev, pipe); + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); if (crtc && (lvds & LVDS_PORT_EN)) { fixed_mode = intel_crtc_mode_get(dev, &crtc->base); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c9990a9f9759..976d66aa8662 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -728,7 +728,7 @@ static bool g4x_compute_wm0(struct drm_i915_private *dev_priv, int line_time_us, line_count; int entries, tlb_miss; - crtc = intel_get_crtc_for_plane(&dev_priv->drm, plane); + crtc = intel_get_crtc_for_plane(dev_priv, plane); if (!intel_crtc_active(crtc)) { *cursor_wm = cursor->guard_size; *plane_wm = display->guard_size; @@ -823,7 +823,7 @@ static bool g4x_compute_srwm(struct drm_i915_private *dev_priv, return false; } - crtc = intel_get_crtc_for_plane(&dev_priv->drm, plane); + crtc = intel_get_crtc_for_plane(dev_priv, plane); adjusted_mode = &crtc->config->base.adjusted_mode; fb = crtc->base.primary->state->fb; clock = adjusted_mode->crtc_clock; @@ -1393,9 +1393,8 @@ static void vlv_update_wm(struct intel_crtc *crtc) static void g4x_update_wm(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); static const int sr_latency_ns = 12000; - struct drm_i915_private *dev_priv = to_i915(dev); int planea_wm, planeb_wm, cursora_wm, cursorb_wm; int plane_sr, cursor_sr; unsigned int enabled = 0; @@ -1546,7 +1545,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) wm_info = &i830_a_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 0); - crtc = intel_get_crtc_for_plane(dev, 0); + crtc = intel_get_crtc_for_plane(dev_priv, 0); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; @@ -1573,7 +1572,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) wm_info = &i830_bc_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 1); - crtc = intel_get_crtc_for_plane(dev, 1); + crtc = intel_get_crtc_for_plane(dev_priv, 1); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; -- cgit v1.2.3 From 98187836fc75b7a003db101e19cfa8685da78905 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:10 +0200 Subject: drm/i915: Always use intel_get_crtc_for_pipe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the open coded dev_priv->pipe_to_crtc_mapping[] usage with intel_get_crtc_for_pipe(). Mostly done with coccinelle, with a few manual tweaks @@ expression E1, E2; @@ ( - E1->pipe_to_crtc_mapping[E2] + intel_get_crtc_for_pipe(E1, E2) | - E1->plane_to_crtc_mapping[E2] + intel_get_crtc_for_plane(E1, E2) ) Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-12-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 5 +++-- drivers/gpu/drm/i915/i915_irq.c | 6 ++++-- drivers/gpu/drm/i915/intel_display.c | 21 ++++++++++++--------- drivers/gpu/drm/i915/intel_fifo_underrun.c | 11 ++++++----- drivers/gpu/drm/i915/intel_pm.c | 2 +- 5 files changed, 26 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 008f91d5df76..a13ff4772e28 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4065,7 +4065,7 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv, bool enable) { struct drm_device *dev = &dev_priv->drm; - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[PIPE_A]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A); struct intel_crtc_state *pipe_config; struct drm_atomic_state *state; int ret = 0; @@ -4203,7 +4203,8 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, /* real source -> none transition */ if (source == INTEL_PIPE_CRC_SOURCE_NONE) { struct intel_pipe_crc_entry *entries; - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, + pipe); DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", pipe_name(pipe)); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 48bb5debb3ef..ecd06d301d8b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -725,7 +725,8 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe) struct drm_i915_private *dev_priv = to_i915(dev); i915_reg_t high_frame, low_frame; u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; - struct intel_crtc *intel_crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv, + pipe); const struct drm_display_mode *mode = &intel_crtc->base.hwmode; htotal = mode->crtc_htotal; @@ -830,7 +831,8 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, const struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv, + pipe); int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; bool in_vbl = true; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3cb41338894c..b21dc272bbac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1030,7 +1030,7 @@ bool intel_crtc_active(struct intel_crtc *crtc) enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); return crtc->config->cpu_transcoder; } @@ -1785,7 +1785,8 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct intel_crtc *intel_crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv, + pipe); i915_reg_t reg; uint32_t val, pipeconf_val; @@ -11662,7 +11663,7 @@ static bool pageflip_finished(struct intel_crtc *crtc, void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe) { struct drm_device *dev = &dev_priv->drm; - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); struct intel_flip_work *work; unsigned long flags; @@ -11688,7 +11689,7 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe) void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe) { struct drm_device *dev = &dev_priv->drm; - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); struct intel_flip_work *work; unsigned long flags; @@ -12118,7 +12119,7 @@ static bool __pageflip_stall_check_cs(struct drm_i915_private *dev_priv, void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe) { struct drm_device *dev = &dev_priv->drm; - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); struct intel_flip_work *work; WARN_ON(!in_interrupt()); @@ -14177,7 +14178,8 @@ static void intel_atomic_wait_for_vblanks(struct drm_device *dev, return; for_each_pipe(dev_priv, pipe) { - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, + pipe); if (!((1 << pipe) & crtc_mask)) continue; @@ -14192,7 +14194,8 @@ static void intel_atomic_wait_for_vblanks(struct drm_device *dev, } for_each_pipe(dev_priv, pipe) { - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, + pipe); long lret; if (!((1 << pipe) & crtc_mask)) @@ -16867,7 +16870,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) pipe = 0; if (encoder->get_hw_state(encoder, &pipe)) { - crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); encoder->base.crtc = &crtc->base; crtc->config->output_types |= 1 << encoder->type; @@ -16969,7 +16972,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev) } for_each_pipe(dev_priv, pipe) { - crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); intel_sanitize_crtc(crtc); intel_dump_pipe_config(crtc, crtc->config, diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 34f93f112107..e660d8b4bbc3 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -57,7 +57,7 @@ static bool ivb_can_enable_err_int(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); for_each_pipe(dev_priv, pipe) { - crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); if (crtc->cpu_fifo_underrun_disabled) return false; @@ -75,7 +75,7 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); for_each_pipe(dev_priv, pipe) { - crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); if (crtc->pch_fifo_underrun_disabled) return false; @@ -245,7 +245,7 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, enum pipe pipe, bool enable) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); bool old; assert_spin_locked(&dev_priv->irq_lock); @@ -313,7 +313,8 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv, enum transcoder pch_transcoder, bool enable) { - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder]; + struct intel_crtc *crtc = + intel_get_crtc_for_pipe(dev_priv, (enum pipe) pch_transcoder); unsigned long flags; bool old; @@ -356,7 +357,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv, void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct intel_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); /* We may be called too early in init, thanks BIOS! */ if (crtc == NULL) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 976d66aa8662..4f51f8656cf6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3065,7 +3065,7 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) /* Since we're now guaranteed to only have one active CRTC... */ pipe = ffs(intel_state->active_crtcs) - 1; - crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); cstate = to_intel_crtc_state(crtc->base.state); if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) -- cgit v1.2.3 From 5ab0d85b6bf01a9e47e74ebc2876534115444c6e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:11 +0200 Subject: drm/i915: Pass dev_priv to intel_crtc_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-13-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b21dc272bbac..71a2fc50ed87 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15236,9 +15236,8 @@ static void skl_init_scalers(struct drm_i915_private *dev_priv, scaler_state->scaler_id = -1; } -static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) +static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc; struct intel_crtc_state *crtc_state = NULL; struct intel_plane *primary = NULL; @@ -15259,7 +15258,7 @@ static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) crtc_state->base.crtc = &intel_crtc->base; /* initialize shared scalers */ - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { if (pipe == PIPE_C) intel_crtc->num_scalers = 1; else @@ -15290,7 +15289,7 @@ static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) goto fail; } - ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, + ret = drm_crtc_init_with_planes(&dev_priv->drm, &intel_crtc->base, &primary->base, &cursor->base, &intel_crtc_funcs, "pipe %c", pipe_name(pipe)); @@ -15303,7 +15302,7 @@ static int intel_crtc_init(struct drm_device *dev, enum pipe pipe) */ intel_crtc->pipe = pipe; intel_crtc->plane = (enum plane) pipe; - if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) { + if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4) { DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); intel_crtc->plane = !pipe; } @@ -16487,7 +16486,7 @@ int intel_modeset_init(struct drm_device *dev) for_each_pipe(dev_priv, pipe) { int ret; - ret = intel_crtc_init(dev, pipe); + ret = intel_crtc_init(dev_priv, pipe); if (ret) { drm_mode_config_cleanup(dev); return ret; -- cgit v1.2.3 From 4c75b9405ea34c9223890d6470b809126b45c173 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:12 +0200 Subject: drm/i915: Pass dev_priv to cdclk update funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-14-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 71a2fc50ed87..3c26ea01b7a2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5842,10 +5842,8 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) static int skl_calc_cdclk(int max_pixclk, int vco); -static void intel_update_max_cdclk(struct drm_device *dev) +static void intel_update_max_cdclk(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; int max_cdclk, vco; @@ -5903,11 +5901,9 @@ static void intel_update_max_cdclk(struct drm_device *dev) dev_priv->max_dotclk_freq); } -static void intel_update_cdclk(struct drm_device *dev) +static void intel_update_cdclk(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - - dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev); + dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(&dev_priv->drm); if (INTEL_GEN(dev_priv) >= 9) DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n", @@ -6068,14 +6064,14 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk) return; } - intel_update_cdclk(&dev_priv->drm); + intel_update_cdclk(dev_priv); } static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv) { u32 cdctl, expected; - intel_update_cdclk(&dev_priv->drm); + intel_update_cdclk(dev_priv); if (dev_priv->cdclk_pll.vco == 0 || dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref) @@ -6208,7 +6204,7 @@ void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco) dev_priv->skl_preferred_vco_freq = vco; if (changed) - intel_update_max_cdclk(&dev_priv->drm); + intel_update_max_cdclk(dev_priv); } static void @@ -6294,7 +6290,6 @@ static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv) static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco) { - struct drm_device *dev = &dev_priv->drm; u32 freq_select, pcu_ack; WARN_ON((cdclk == 24000) != (vco == 0)); @@ -6345,7 +6340,7 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco) sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack); mutex_unlock(&dev_priv->rps.hw_lock); - intel_update_cdclk(dev); + intel_update_cdclk(dev_priv); } static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv); @@ -6392,7 +6387,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv) if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0) goto sanitize; - intel_update_cdclk(&dev_priv->drm); + intel_update_cdclk(dev_priv); /* Is PLL enabled and locked ? */ if (dev_priv->cdclk_pll.vco == 0 || dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref) @@ -6483,7 +6478,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) mutex_unlock(&dev_priv->sb_lock); - intel_update_cdclk(dev); + intel_update_cdclk(dev_priv); } static void cherryview_set_cdclk(struct drm_device *dev, int cdclk) @@ -6524,7 +6519,7 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk) } mutex_unlock(&dev_priv->rps.hw_lock); - intel_update_cdclk(dev); + intel_update_cdclk(dev_priv); } static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, @@ -10188,7 +10183,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) } intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); - intel_update_cdclk(&dev_priv->drm); + intel_update_cdclk(dev_priv); } /* @@ -10368,7 +10363,7 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk) I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1); - intel_update_cdclk(dev); + intel_update_cdclk(dev_priv); WARN(cdclk != dev_priv->cdclk_freq, "cdclk requested %d kHz but got %d kHz\n", @@ -16323,7 +16318,7 @@ void intel_modeset_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - intel_update_cdclk(dev); + intel_update_cdclk(dev_priv); dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; @@ -16494,12 +16489,12 @@ int intel_modeset_init(struct drm_device *dev) } intel_update_czclk(dev_priv); - intel_update_cdclk(dev); + intel_update_cdclk(dev_priv); intel_shared_dpll_init(dev); if (dev_priv->max_cdclk_freq == 0) - intel_update_max_cdclk(dev); + intel_update_max_cdclk(dev_priv); /* Just disable it once at startup */ i915_disable_vga(dev); -- cgit v1.2.3 From 1353c4fb1803cc094bb0194bb317b090ab08d83c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:13 +0200 Subject: drm/i915: Pass dev_priv to .get_display_clock_speed() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-15-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 77 +++++++++++++++------------------ drivers/gpu/drm/i915/intel_runtime_pm.c | 2 +- 3 files changed, 38 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eeed752da9df..60c937dce06f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -494,7 +494,7 @@ struct intel_limit; struct dpll; struct drm_i915_display_funcs { - int (*get_display_clock_speed)(struct drm_device *dev); + int (*get_display_clock_speed)(struct drm_i915_private *dev_priv); int (*get_fifo_size)(struct drm_device *dev, int plane); int (*compute_pipe_wm)(struct intel_crtc_state *cstate); int (*compute_intermediate_wm)(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3c26ea01b7a2..b670ae76317b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5903,7 +5903,7 @@ static void intel_update_max_cdclk(struct drm_i915_private *dev_priv) static void intel_update_cdclk(struct drm_i915_private *dev_priv) { - dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(&dev_priv->drm); + dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev_priv); if (INTEL_GEN(dev_priv) >= 9) DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n", @@ -6421,7 +6421,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) struct drm_i915_private *dev_priv = to_i915(dev); u32 val, cmd; - WARN_ON(dev_priv->display.get_display_clock_speed(dev) + WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv) != dev_priv->cdclk_freq); if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ @@ -6486,7 +6486,7 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk) struct drm_i915_private *dev_priv = to_i915(dev); u32 val, cmd; - WARN_ON(dev_priv->display.get_display_clock_speed(dev) + WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv) != dev_priv->cdclk_freq); switch (cdclk) { @@ -7245,10 +7245,9 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, return 0; } -static int skylake_get_display_clock_speed(struct drm_device *dev) +static int skylake_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - uint32_t cdctl; + u32 cdctl; skl_dpll0_update(dev_priv); @@ -7307,9 +7306,8 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv) dev_priv->cdclk_pll.ref; } -static int broxton_get_display_clock_speed(struct drm_device *dev) +static int broxton_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); u32 divider; int div, vco; @@ -7342,9 +7340,8 @@ static int broxton_get_display_clock_speed(struct drm_device *dev) return DIV_ROUND_CLOSEST(vco, div); } -static int broadwell_get_display_clock_speed(struct drm_device *dev) +static int broadwell_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t lcpll = I915_READ(LCPLL_CTL); uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; @@ -7362,9 +7359,8 @@ static int broadwell_get_display_clock_speed(struct drm_device *dev) return 675000; } -static int haswell_get_display_clock_speed(struct drm_device *dev) +static int haswell_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t lcpll = I915_READ(LCPLL_CTL); uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; @@ -7380,35 +7376,35 @@ static int haswell_get_display_clock_speed(struct drm_device *dev) return 540000; } -static int valleyview_get_display_clock_speed(struct drm_device *dev) +static int valleyview_get_display_clock_speed(struct drm_i915_private *dev_priv) { - return vlv_get_cck_clock_hpll(to_i915(dev), "cdclk", + return vlv_get_cck_clock_hpll(dev_priv, "cdclk", CCK_DISPLAY_CLOCK_CONTROL); } -static int ilk_get_display_clock_speed(struct drm_device *dev) +static int ilk_get_display_clock_speed(struct drm_i915_private *dev_priv) { return 450000; } -static int i945_get_display_clock_speed(struct drm_device *dev) +static int i945_get_display_clock_speed(struct drm_i915_private *dev_priv) { return 400000; } -static int i915_get_display_clock_speed(struct drm_device *dev) +static int i915_get_display_clock_speed(struct drm_i915_private *dev_priv) { return 333333; } -static int i9xx_misc_get_display_clock_speed(struct drm_device *dev) +static int i9xx_misc_get_display_clock_speed(struct drm_i915_private *dev_priv) { return 200000; } -static int pnv_get_display_clock_speed(struct drm_device *dev) +static int pnv_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev->pdev; + struct pci_dev *pdev = dev_priv->drm.pdev; u16 gcfgc = 0; pci_read_config_word(pdev, GCFGC, &gcfgc); @@ -7431,9 +7427,9 @@ static int pnv_get_display_clock_speed(struct drm_device *dev) } } -static int i915gm_get_display_clock_speed(struct drm_device *dev) +static int i915gm_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev->pdev; + struct pci_dev *pdev = dev_priv->drm.pdev; u16 gcfgc = 0; pci_read_config_word(pdev, GCFGC, &gcfgc); @@ -7451,14 +7447,14 @@ static int i915gm_get_display_clock_speed(struct drm_device *dev) } } -static int i865_get_display_clock_speed(struct drm_device *dev) +static int i865_get_display_clock_speed(struct drm_i915_private *dev_priv) { return 266667; } -static int i85x_get_display_clock_speed(struct drm_device *dev) +static int i85x_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev->pdev; + struct pci_dev *pdev = dev_priv->drm.pdev; u16 hpllcc = 0; /* @@ -7494,14 +7490,13 @@ static int i85x_get_display_clock_speed(struct drm_device *dev) return 0; } -static int i830_get_display_clock_speed(struct drm_device *dev) +static int i830_get_display_clock_speed(struct drm_i915_private *dev_priv) { return 133333; } -static unsigned int intel_hpll_vco(struct drm_device *dev) +static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); static const unsigned int blb_vco[8] = { [0] = 3200000, [1] = 4000000, @@ -7548,16 +7543,16 @@ static unsigned int intel_hpll_vco(struct drm_device *dev) vco_table = ctg_vco; else if (IS_G4X(dev_priv)) vco_table = elk_vco; - else if (IS_CRESTLINE(dev)) + else if (IS_CRESTLINE(dev_priv)) vco_table = cl_vco; - else if (IS_PINEVIEW(dev)) + else if (IS_PINEVIEW(dev_priv)) vco_table = pnv_vco; - else if (IS_G33(dev)) + else if (IS_G33(dev_priv)) vco_table = blb_vco; else return 0; - tmp = I915_READ(IS_MOBILE(dev) ? HPLLVCO_MOBILE : HPLLVCO); + tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO); vco = vco_table[tmp & 0x7]; if (vco == 0) @@ -7568,10 +7563,10 @@ static unsigned int intel_hpll_vco(struct drm_device *dev) return vco; } -static int gm45_get_display_clock_speed(struct drm_device *dev) +static int gm45_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev->pdev; - unsigned int cdclk_sel, vco = intel_hpll_vco(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; + unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); uint16_t tmp = 0; pci_read_config_word(pdev, GCFGC, &tmp); @@ -7591,14 +7586,14 @@ static int gm45_get_display_clock_speed(struct drm_device *dev) } } -static int i965gm_get_display_clock_speed(struct drm_device *dev) +static int i965gm_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev->pdev; + struct pci_dev *pdev = dev_priv->drm.pdev; static const uint8_t div_3200[] = { 16, 10, 8 }; static const uint8_t div_4000[] = { 20, 12, 10 }; static const uint8_t div_5333[] = { 24, 16, 14 }; const uint8_t *div_table; - unsigned int cdclk_sel, vco = intel_hpll_vco(dev); + unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); uint16_t tmp = 0; pci_read_config_word(pdev, GCFGC, &tmp); @@ -7629,15 +7624,15 @@ fail: return 200000; } -static int g33_get_display_clock_speed(struct drm_device *dev) +static int g33_get_display_clock_speed(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev->pdev; + struct pci_dev *pdev = dev_priv->drm.pdev; static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 }; static const uint8_t div_4000[] = { 14, 12, 10, 8, 6, 20 }; static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 }; static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 }; const uint8_t *div_table; - unsigned int cdclk_sel, vco = intel_hpll_vco(dev); + unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); uint16_t tmp = 0; pci_read_config_word(pdev, GCFGC, &tmp); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 9a3a7455d29c..05994083e161 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -907,7 +907,7 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); WARN_ON(dev_priv->cdclk_freq != - dev_priv->display.get_display_clock_speed(&dev_priv->drm)); + dev_priv->display.get_display_clock_speed(dev_priv)); gen9_assert_dbuf_enabled(dev_priv); -- cgit v1.2.3 From 646d57720969f1abf92f6358af0fe91b04201ba9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:14 +0200 Subject: drm/i915: Pass dev_priv to IS_MOBILE() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-16-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 8 +++----- drivers/gpu/drm/i915/intel_sdvo.c | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 60c937dce06f..474c728a9073 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2749,7 +2749,7 @@ struct drm_i915_cmd_table { #define IS_SKYLAKE(dev_priv) ((dev_priv)->info.is_skylake) #define IS_BROXTON(dev_priv) ((dev_priv)->info.is_broxton) #define IS_KABYLAKE(dev_priv) ((dev_priv)->info.is_kabylake) -#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) +#define IS_MOBILE(dev_priv) ((dev_priv)->info.is_mobile) #define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00) #define IS_BDW_ULT(dev_priv) (IS_BROADWELL(dev_priv) && \ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b670ae76317b..50261c5445c6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15374,11 +15374,9 @@ static int intel_encoder_clones(struct intel_encoder *encoder) return index_mask; } -static bool has_edp_a(struct drm_device *dev) +static bool has_edp_a(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - - if (!IS_MOBILE(dev)) + if (!IS_MOBILE(dev_priv)) return false; if ((I915_READ(DP_A) & DP_DETECTED) == 0) @@ -15518,7 +15516,7 @@ static void intel_setup_outputs(struct drm_device *dev) int found; dpd_is_edp = intel_dp_is_edp(dev, PORT_D); - if (has_edp_a(dev)) + if (has_edp_a(dev_priv)) intel_dp_init(dev, DP_A, PORT_A); if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) { diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 5d59a48e3249..3990c805a5b5 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2411,10 +2411,10 @@ static void intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *connector) { - struct drm_device *dev = connector->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(connector->base.base.dev); intel_attach_force_audio_property(&connector->base.base); - if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev)) { + if (INTEL_GEN(dev_priv) >= 4 && IS_MOBILE(dev_priv)) { intel_attach_broadcast_rgb_property(&connector->base.base); intel_sdvo->color_range_auto = true; } -- cgit v1.2.3 From 9b1e14f4d892e568c0b53aaa53eec6029b750e5f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:15 +0200 Subject: drm/i915: Pass dev_priv to IS_PINEVIEW() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-17-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 19 +++++++++---------- drivers/gpu/drm/i915/intel_pm.c | 9 ++++----- 3 files changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 474c728a9073..8b35cfa6bb86 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2735,7 +2735,7 @@ struct drm_i915_cmd_table { #define IS_G4X(dev_priv) ((dev_priv)->info.is_g4x) #define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001) #define IS_PINEVIEW_M(dev_priv) (INTEL_DEVID(dev_priv) == 0xa011) -#define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) +#define IS_PINEVIEW(dev_priv) ((dev_priv)->info.is_pineview) #define IS_G33(dev) (INTEL_INFO(dev)->is_g33) #define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046) #define IS_IVYBRIDGE(dev_priv) ((dev_priv)->info.is_ivybridge) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 50261c5445c6..53e846158559 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7721,10 +7721,10 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, struct dpll *reduced_clock) { - struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 fp, fp2 = 0; - if (IS_PINEVIEW(dev)) { + if (IS_PINEVIEW(dev_priv)) { fp = pnv_dpll_compute_fp(&crtc_state->dpll); if (reduced_clock) fp2 = pnv_dpll_compute_fp(reduced_clock); @@ -8143,8 +8143,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, struct dpll *reduced_clock) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dpll; struct dpll *clock = &crtc_state->dpll; @@ -8170,7 +8169,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, dpll |= DPLL_SDVO_HIGH_SPEED; /* compute bitmask from p1 value */ - if (IS_PINEVIEW(dev)) + if (IS_PINEVIEW(dev_priv)) dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; else { dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; @@ -8191,7 +8190,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } - if (INTEL_INFO(dev)->gen >= 4) + if (INTEL_GEN(dev_priv) >= 4) dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); if (crtc_state->sdvo_tv_clock) @@ -8205,7 +8204,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, dpll |= DPLL_VCO_ENABLE; crtc_state->dpll_hw_state.dpll = dpll; - if (INTEL_INFO(dev)->gen >= 4) { + if (INTEL_GEN(dev_priv) >= 4) { u32 dpll_md = (crtc_state->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; crtc_state->dpll_hw_state.dpll_md = dpll_md; @@ -11353,7 +11352,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, fp = pipe_config->dpll_hw_state.fp1; clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; - if (IS_PINEVIEW(dev)) { + if (IS_PINEVIEW(dev_priv)) { clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1; clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT; } else { @@ -11362,7 +11361,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, } if (!IS_GEN2(dev_priv)) { - if (IS_PINEVIEW(dev)) + if (IS_PINEVIEW(dev_priv)) clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); else @@ -11384,7 +11383,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, return; } - if (IS_PINEVIEW(dev)) + if (IS_PINEVIEW(dev_priv)) port_clock = pnv_calc_dpll_params(refclk, &clock); else port_clock = i9xx_calc_dpll_params(refclk, &clock); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4f51f8656cf6..11bbc35a4c84 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -320,7 +320,6 @@ static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable) void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) { - struct drm_device *dev = &dev_priv->drm; u32 val; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { @@ -330,7 +329,7 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) } else if (IS_G4X(dev_priv) || IS_CRESTLINE(dev_priv)) { I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0); POSTING_READ(FW_BLC_SELF); - } else if (IS_PINEVIEW(dev)) { + } else if (IS_PINEVIEW(dev_priv)) { val = I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN; val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0; I915_WRITE(DSPFW3, val); @@ -7628,7 +7627,7 @@ static void gen3_init_clock_gating(struct drm_device *dev) DSTATE_DOT_CLOCK_GATING; I915_WRITE(D_STATE, dstate); - if (IS_PINEVIEW(dev)) + if (IS_PINEVIEW(dev_priv)) I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); /* IIR "flip pending" means done if this bit is set */ @@ -7744,7 +7743,7 @@ void intel_init_pm(struct drm_device *dev) intel_fbc_init(dev_priv); /* For cxsr */ - if (IS_PINEVIEW(dev)) + if (IS_PINEVIEW(dev_priv)) i915_pineview_get_mem_freq(dev); else if (IS_GEN5(dev_priv)) i915_ironlake_get_mem_freq(dev); @@ -7778,7 +7777,7 @@ void intel_init_pm(struct drm_device *dev) } else if (IS_VALLEYVIEW(dev_priv)) { vlv_setup_wm_latency(dev); dev_priv->display.update_wm = vlv_update_wm; - } else if (IS_PINEVIEW(dev)) { + } else if (IS_PINEVIEW(dev_priv)) { if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv), dev_priv->is_ddr3, dev_priv->fsb_freq, -- cgit v1.2.3 From 148ac1f375fe9625f08a531d198e2d8559cbdd79 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:16 +0200 Subject: drm/i915: Pass dev_priv to i915_pineview_get_mem_freq() and i915_ironlake_get_mem_freq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-18-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_pm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 11bbc35a4c84..d423fc8661a9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -108,9 +108,8 @@ static void bxt_init_clock_gating(struct drm_device *dev) PWM1_GATING_DIS | PWM2_GATING_DIS); } -static void i915_pineview_get_mem_freq(struct drm_device *dev) +static void i915_pineview_get_mem_freq(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); u32 tmp; tmp = I915_READ(CLKCFG); @@ -147,9 +146,8 @@ static void i915_pineview_get_mem_freq(struct drm_device *dev) dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0; } -static void i915_ironlake_get_mem_freq(struct drm_device *dev) +static void i915_ironlake_get_mem_freq(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); u16 ddrpll, csipll; ddrpll = I915_READ16(DDRMPLL1); @@ -7744,9 +7742,9 @@ void intel_init_pm(struct drm_device *dev) /* For cxsr */ if (IS_PINEVIEW(dev_priv)) - i915_pineview_get_mem_freq(dev); + i915_pineview_get_mem_freq(dev_priv); else if (IS_GEN5(dev_priv)) - i915_ironlake_get_mem_freq(dev); + i915_ironlake_get_mem_freq(dev_priv); /* For FIFO watermark updates */ if (INTEL_INFO(dev)->gen >= 9) { -- cgit v1.2.3 From ef0f5e93bd1ffced24370399b2b6bbe600a840bc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:17 +0200 Subject: drm/i915: Pass dev_priv to .get_fifo_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-19-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 22 +++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8b35cfa6bb86..fd08559f94d4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -495,7 +495,7 @@ struct dpll; struct drm_i915_display_funcs { int (*get_display_clock_speed)(struct drm_i915_private *dev_priv); - int (*get_fifo_size)(struct drm_device *dev, int plane); + int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane); int (*compute_pipe_wm)(struct intel_crtc_state *cstate); int (*compute_intermediate_wm)(struct drm_device *dev, struct intel_crtc *intel_crtc, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d423fc8661a9..83391c28a727 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -375,10 +375,9 @@ static const int pessimal_latency_ns = 5000; #define VLV_FIFO_START(dsparb, dsparb2, lo_shift, hi_shift) \ ((((dsparb) >> (lo_shift)) & 0xff) | ((((dsparb2) >> (hi_shift)) & 0x1) << 8)) -static int vlv_get_fifo_size(struct drm_device *dev, +static int vlv_get_fifo_size(struct drm_i915_private *dev_priv, enum pipe pipe, int plane) { - struct drm_i915_private *dev_priv = to_i915(dev); int sprite0_start, sprite1_start, size; switch (pipe) { @@ -427,9 +426,8 @@ static int vlv_get_fifo_size(struct drm_device *dev, return size; } -static int i9xx_get_fifo_size(struct drm_device *dev, int plane) +static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, int plane) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t dsparb = I915_READ(DSPARB); int size; @@ -443,9 +441,8 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane) return size; } -static int i830_get_fifo_size(struct drm_device *dev, int plane) +static int i830_get_fifo_size(struct drm_i915_private *dev_priv, int plane) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t dsparb = I915_READ(DSPARB); int size; @@ -460,9 +457,8 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane) return size; } -static int i845_get_fifo_size(struct drm_device *dev, int plane) +static int i845_get_fifo_size(struct drm_i915_private *dev_priv, int plane) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t dsparb = I915_READ(DSPARB); int size; @@ -1541,7 +1537,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) else wm_info = &i830_a_wm_info; - fifo_size = dev_priv->display.get_fifo_size(dev, 0); + fifo_size = dev_priv->display.get_fifo_size(dev_priv, 0); crtc = intel_get_crtc_for_plane(dev_priv, 0); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = @@ -1568,7 +1564,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) if (IS_GEN2(dev_priv)) wm_info = &i830_bc_wm_info; - fifo_size = dev_priv->display.get_fifo_size(dev, 1); + fifo_size = dev_priv->display.get_fifo_size(dev_priv, 1); crtc = intel_get_crtc_for_plane(dev_priv, 1); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = @@ -1686,7 +1682,7 @@ static void i845_update_wm(struct intel_crtc *unused_crtc) adjusted_mode = &crtc->config->base.adjusted_mode; planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, &i845_wm_info, - dev_priv->display.get_fifo_size(dev, 0), + dev_priv->display.get_fifo_size(dev_priv, 0), 4, pessimal_latency_ns); fwater_lo = I915_READ(FW_BLC) & ~0xfff; fwater_lo |= (3<<8) | planea_wm; @@ -4556,11 +4552,11 @@ void vlv_wm_get_hw_state(struct drm_device *dev) plane->wm.fifo_size = 63; break; case DRM_PLANE_TYPE_PRIMARY: - plane->wm.fifo_size = vlv_get_fifo_size(dev, plane->pipe, 0); + plane->wm.fifo_size = vlv_get_fifo_size(dev_priv, plane->pipe, 0); break; case DRM_PLANE_TYPE_OVERLAY: sprite = plane->plane; - plane->wm.fifo_size = vlv_get_fifo_size(dev, plane->pipe, sprite + 1); + plane->wm.fifo_size = vlv_get_fifo_size(dev_priv, plane->pipe, sprite + 1); break; } } -- cgit v1.2.3 From 03427fcb75ef0b31f883a2b6075e33e56e668241 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:18 +0200 Subject: drm/i915: Pass dev_priv to HAS_FW_BLC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-20-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fd08559f94d4..fdfb1d20adff 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2893,7 +2893,7 @@ struct drm_i915_cmd_table { #define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) -#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2) +#define HAS_FW_BLC(dev_priv) (INTEL_GEN(dev_priv) > 2) #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) #define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 83391c28a727..afd3babc4a9d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1612,7 +1612,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) intel_set_memory_cxsr(dev_priv, false); /* Calc sr entries for one plane configs */ - if (HAS_FW_BLC(dev) && enabled) { + if (HAS_FW_BLC(dev_priv) && enabled) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 6000; const struct drm_display_mode *adjusted_mode = -- cgit v1.2.3 From a26e52392191f51605af9017058cf5e43334cd5b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:19 +0200 Subject: drm/i915: Pass dev_priv to IS_BROADWATER/IS_CRESTLINE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-21-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 3 +-- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_gem.c | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3b9bfd2cf0c0..77ca07f7f94e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -981,7 +981,6 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) static int i915_driver_init_hw(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = dev_priv->drm.pdev; - struct drm_device *dev = &dev_priv->drm; int ret; if (i915_inject_load_failure()) @@ -1039,7 +1038,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) * behaviour if any general state is accessed within a page above 4GB, * which also needs to be handled carefully. */ - if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) { + if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv)) { ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fdfb1d20adff..888ddf8fbeeb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2729,8 +2729,8 @@ struct drm_i915_cmd_table { #define IS_I915GM(dev_priv) (INTEL_DEVID(dev_priv) == 0x2592) #define IS_I945G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2772) #define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) -#define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) -#define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) +#define IS_BROADWATER(dev_priv) ((dev_priv)->info.is_broadwater) +#define IS_CRESTLINE(dev_priv) ((dev_priv)->info.is_crestline) #define IS_GM45(dev_priv) (INTEL_DEVID(dev_priv) == 0x2A42) #define IS_G4X(dev_priv) ((dev_priv)->info.is_g4x) #define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cbbfaa7761b9..207b8ef85136 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4158,6 +4158,7 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = { struct drm_i915_gem_object * i915_gem_object_create(struct drm_device *dev, u64 size) { + struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_object *obj; struct address_space *mapping; gfp_t mask; @@ -4183,7 +4184,7 @@ i915_gem_object_create(struct drm_device *dev, u64 size) goto fail; mask = GFP_HIGHUSER | __GFP_RECLAIMABLE; - if (IS_CRESTLINE(dev) || IS_BROADWATER(dev)) { + if (IS_CRESTLINE(dev_priv) || IS_BROADWATER(dev_priv)) { /* 965gm cannot relocate objects above 4GiB. */ mask &= ~__GFP_HIGHMEM; mask |= __GFP_DMA32; -- cgit v1.2.3 From a9097be4f980c1b6757bab3c89609f81d390b478 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:20 +0200 Subject: drm/i915: Pass dev_priv to rest of IS_FOO() macros for the old platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-22-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 8 ++++---- drivers/gpu/drm/i915/i915_gem_stolen.c | 4 ++-- drivers/gpu/drm/i915/intel_pm.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 888ddf8fbeeb..63672c3c1118 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2723,12 +2723,12 @@ struct drm_i915_cmd_table { #define IS_I830(dev_priv) (INTEL_DEVID(dev_priv) == 0x3577) #define IS_845G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2562) -#define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) +#define IS_I85X(dev_priv) ((dev_priv)->info.is_i85x) #define IS_I865G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2572) -#define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) +#define IS_I915G(dev_priv) ((dev_priv)->info.is_i915g) #define IS_I915GM(dev_priv) (INTEL_DEVID(dev_priv) == 0x2592) #define IS_I945G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2772) -#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) +#define IS_I945GM(dev_priv) ((dev_priv)->info.is_i945gm) #define IS_BROADWATER(dev_priv) ((dev_priv)->info.is_broadwater) #define IS_CRESTLINE(dev_priv) ((dev_priv)->info.is_crestline) #define IS_GM45(dev_priv) (INTEL_DEVID(dev_priv) == 0x2A42) @@ -2736,7 +2736,7 @@ struct drm_i915_cmd_table { #define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001) #define IS_PINEVIEW_M(dev_priv) (INTEL_DEVID(dev_priv) == 0xa011) #define IS_PINEVIEW(dev_priv) ((dev_priv)->info.is_pineview) -#define IS_G33(dev) (INTEL_INFO(dev)->is_g33) +#define IS_G33(dev_priv) ((dev_priv)->info.is_g33) #define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046) #define IS_IVYBRIDGE(dev_priv) ((dev_priv)->info.is_ivybridge) #define IS_IVB_GT1(dev_priv) (INTEL_DEVID(dev_priv) == 0x0156 || \ diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 1a63ffa4d189..3725a1d3b254 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -109,7 +109,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) * */ base = 0; - if (INTEL_INFO(dev)->gen >= 3) { + if (INTEL_GEN(dev_priv) >= 3) { u32 bsm; pci_read_config_dword(pdev, INTEL_BSM, &bsm); @@ -138,7 +138,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) I865_TOUD, &toud); base = (toud << 16) + tseg_size; - } else if (IS_I85X(dev)) { + } else if (IS_I85X(dev_priv)) { u32 tseg_size = 0; u32 tom; u8 tmp; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index afd3babc4a9d..7199f853b3a0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1530,7 +1530,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) int planea_wm, planeb_wm; struct intel_crtc *crtc, *enabled = NULL; - if (IS_I945GM(dev)) + if (IS_I945GM(dev_priv)) wm_info = &i945_wm_info; else if (!IS_GEN2(dev_priv)) wm_info = &i915_wm_info; -- cgit v1.2.3 From ffc7a76b8bce780aa21b9979198da8ecd8303544 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:21 +0200 Subject: drm/i915: Pass dev_priv to single_enabled_crtc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-23-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_pm.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7199f853b3a0..cb518c506c67 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -618,11 +618,11 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, return wm_size; } -static struct intel_crtc *single_enabled_crtc(struct drm_device *dev) +static struct intel_crtc *single_enabled_crtc(struct drm_i915_private *dev_priv) { struct intel_crtc *crtc, *enabled = NULL; - for_each_intel_crtc(dev, crtc) { + for_each_intel_crtc(&dev_priv->drm, crtc) { if (intel_crtc_active(crtc)) { if (enabled) return NULL; @@ -635,8 +635,7 @@ static struct intel_crtc *single_enabled_crtc(struct drm_device *dev) static void pineview_update_wm(struct intel_crtc *unused_crtc) { - struct drm_device *dev = unused_crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev); struct intel_crtc *crtc; const struct cxsr_latency *latency; u32 reg; @@ -652,7 +651,7 @@ static void pineview_update_wm(struct intel_crtc *unused_crtc) return; } - crtc = single_enabled_crtc(dev); + crtc = single_enabled_crtc(dev_priv); if (crtc) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; @@ -1443,15 +1442,14 @@ static void g4x_update_wm(struct intel_crtc *crtc) static void i965_update_wm(struct intel_crtc *unused_crtc) { - struct drm_device *dev = unused_crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev); struct intel_crtc *crtc; int srwm = 1; int cursor_sr = 16; bool cxsr_enabled; /* Calc sr entries for one plane configs */ - crtc = single_enabled_crtc(dev); + crtc = single_enabled_crtc(dev_priv); if (crtc) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 12000; @@ -1520,8 +1518,7 @@ static void i965_update_wm(struct intel_crtc *unused_crtc) static void i9xx_update_wm(struct intel_crtc *unused_crtc) { - struct drm_device *dev = unused_crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev); const struct intel_watermark_params *wm_info; uint32_t fwater_lo; uint32_t fwater_hi; @@ -1668,14 +1665,13 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) static void i845_update_wm(struct intel_crtc *unused_crtc) { - struct drm_device *dev = unused_crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev); struct intel_crtc *crtc; const struct drm_display_mode *adjusted_mode; uint32_t fwater_lo; int planea_wm; - crtc = single_enabled_crtc(dev); + crtc = single_enabled_crtc(dev_priv); if (crtc == NULL) return; -- cgit v1.2.3 From 46f16e631aa2001cd4a4899b4797d4f0b847ad10 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:22 +0200 Subject: drm/i915: Pass dev_priv to init_clock_gating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-24-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 3 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 129 ++++++++++++----------------------- 5 files changed, 49 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 77ca07f7f94e..f83dde9e36d1 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2264,7 +2264,6 @@ err1: static int vlv_resume_prepare(struct drm_i915_private *dev_priv, bool rpm_resume) { - struct drm_device *dev = &dev_priv->drm; int err; int ret; @@ -2289,7 +2288,7 @@ static int vlv_resume_prepare(struct drm_i915_private *dev_priv, vlv_check_no_gt_access(dev_priv); if (rpm_resume) - intel_init_clock_gating(dev); + intel_init_clock_gating(dev_priv); return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 63672c3c1118..b8e72cdcb713 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -525,7 +525,7 @@ struct drm_i915_display_funcs { const struct drm_display_mode *adjusted_mode); void (*audio_codec_disable)(struct intel_encoder *encoder); void (*fdi_link_train)(struct drm_crtc *crtc); - void (*init_clock_gating)(struct drm_device *dev); + void (*init_clock_gating)(struct drm_i915_private *dev_priv); int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 53e846158559..a46922aec99b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -16314,7 +16314,7 @@ void intel_modeset_init_hw(struct drm_device *dev) dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; - intel_init_clock_gating(dev); + intel_init_clock_gating(dev_priv); } /* diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0fdd546ac8d8..3a9ca2755829 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1703,7 +1703,7 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, /* intel_pm.c */ -void intel_init_clock_gating(struct drm_device *dev); +void intel_init_clock_gating(struct drm_i915_private *dev_priv); void intel_suspend_hw(struct drm_device *dev); int ilk_wm_max_level(const struct drm_i915_private *dev_priv); void intel_update_watermarks(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cb518c506c67..3e9bc2ac26b4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -56,10 +56,8 @@ #define INTEL_RC6p_ENABLE (1<<1) #define INTEL_RC6pp_ENABLE (1<<2) -static void gen9_init_clock_gating(struct drm_device *dev) +static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl */ I915_WRITE(CHICKEN_PAR1_1, I915_READ(CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP); @@ -82,11 +80,9 @@ static void gen9_init_clock_gating(struct drm_device *dev) ILK_DPFC_DISABLE_DUMMY0); } -static void bxt_init_clock_gating(struct drm_device *dev) +static void bxt_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - - gen9_init_clock_gating(dev); + gen9_init_clock_gating(dev_priv); /* WaDisableSDEUnitClockGating:bxt */ I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | @@ -6857,10 +6853,8 @@ void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv) } } -static void ibx_init_clock_gating(struct drm_device *dev) +static void ibx_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - /* * On Ibex Peak and Cougar Point, we need to disable clock * gating for the panel power sequencer or it will fail to @@ -6869,9 +6863,8 @@ static void ibx_init_clock_gating(struct drm_device *dev) I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); } -static void g4x_disable_trickle_feed(struct drm_device *dev) +static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); enum pipe pipe; for_each_pipe(dev_priv, pipe) { @@ -6884,10 +6877,8 @@ static void g4x_disable_trickle_feed(struct drm_device *dev) } } -static void ilk_init_lp_watermarks(struct drm_device *dev) +static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN); I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN); I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN); @@ -6898,9 +6889,8 @@ static void ilk_init_lp_watermarks(struct drm_device *dev) */ } -static void ironlake_init_clock_gating(struct drm_device *dev) +static void ironlake_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; /* @@ -6932,7 +6922,7 @@ static void ironlake_init_clock_gating(struct drm_device *dev) (I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS)); - ilk_init_lp_watermarks(dev); + ilk_init_lp_watermarks(dev_priv); /* * Based on the document from hardware guys the following bits @@ -6967,14 +6957,13 @@ static void ironlake_init_clock_gating(struct drm_device *dev) /* WaDisable_RenderCache_OperationalFlush:ilk */ I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE)); - g4x_disable_trickle_feed(dev); + g4x_disable_trickle_feed(dev_priv); - ibx_init_clock_gating(dev); + ibx_init_clock_gating(dev_priv); } -static void cpt_init_clock_gating(struct drm_device *dev) +static void cpt_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); int pipe; uint32_t val; @@ -7009,9 +6998,8 @@ static void cpt_init_clock_gating(struct drm_device *dev) } } -static void gen6_check_mch_setup(struct drm_device *dev) +static void gen6_check_mch_setup(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t tmp; tmp = I915_READ(MCH_SSKPD); @@ -7020,9 +7008,8 @@ static void gen6_check_mch_setup(struct drm_device *dev) tmp); } -static void gen6_init_clock_gating(struct drm_device *dev) +static void gen6_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate); @@ -7049,7 +7036,7 @@ static void gen6_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN6_GT_MODE, _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4)); - ilk_init_lp_watermarks(dev); + ilk_init_lp_watermarks(dev_priv); I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); @@ -7110,11 +7097,11 @@ static void gen6_init_clock_gating(struct drm_device *dev) ILK_DPARBUNIT_CLOCK_GATE_ENABLE | ILK_DPFDUNIT_CLOCK_GATE_ENABLE); - g4x_disable_trickle_feed(dev); + g4x_disable_trickle_feed(dev_priv); - cpt_init_clock_gating(dev); + cpt_init_clock_gating(dev_priv); - gen6_check_mch_setup(dev); + gen6_check_mch_setup(dev_priv); } static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) @@ -7135,10 +7122,8 @@ static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) I915_WRITE(GEN7_FF_THREAD_MODE, reg); } -static void lpt_init_clock_gating(struct drm_device *dev) +static void lpt_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - /* * TODO: this bit should only be enabled when really needed, then * disabled when not needed anymore in order to save power. @@ -7189,11 +7174,9 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv, I915_WRITE(GEN7_MISCCPCTL, misccpctl); } -static void kabylake_init_clock_gating(struct drm_device *dev) +static void kabylake_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - - gen9_init_clock_gating(dev); + gen9_init_clock_gating(dev_priv); /* WaDisableSDEUnitClockGating:kbl */ if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) @@ -7210,11 +7193,9 @@ static void kabylake_init_clock_gating(struct drm_device *dev) ILK_DPFC_NUKE_ON_ANY_MODIFICATION); } -static void skylake_init_clock_gating(struct drm_device *dev) +static void skylake_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - - gen9_init_clock_gating(dev); + gen9_init_clock_gating(dev_priv); /* WAC6entrylatency:skl */ I915_WRITE(FBC_LLC_READ_CTRL, I915_READ(FBC_LLC_READ_CTRL) | @@ -7225,12 +7206,11 @@ static void skylake_init_clock_gating(struct drm_device *dev) ILK_DPFC_NUKE_ON_ANY_MODIFICATION); } -static void broadwell_init_clock_gating(struct drm_device *dev) +static void broadwell_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); enum pipe pipe; - ilk_init_lp_watermarks(dev); + ilk_init_lp_watermarks(dev_priv); /* WaSwitchSolVfFArbitrationPriority:bdw */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); @@ -7273,14 +7253,12 @@ static void broadwell_init_clock_gating(struct drm_device *dev) I915_WRITE(CHICKEN_PAR2_1, I915_READ(CHICKEN_PAR2_1) | KVM_CONFIG_CHANGE_NOTIFICATION_SELECT); - lpt_init_clock_gating(dev); + lpt_init_clock_gating(dev_priv); } -static void haswell_init_clock_gating(struct drm_device *dev) +static void haswell_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - - ilk_init_lp_watermarks(dev); + ilk_init_lp_watermarks(dev_priv); /* L3 caching of data atomics doesn't work -- disable it. */ I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE); @@ -7329,15 +7307,14 @@ static void haswell_init_clock_gating(struct drm_device *dev) I915_WRITE(CHICKEN_PAR1_1, I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); - lpt_init_clock_gating(dev); + lpt_init_clock_gating(dev_priv); } -static void ivybridge_init_clock_gating(struct drm_device *dev) +static void ivybridge_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t snpcr; - ilk_init_lp_watermarks(dev); + ilk_init_lp_watermarks(dev_priv); I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); @@ -7394,7 +7371,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); - g4x_disable_trickle_feed(dev); + g4x_disable_trickle_feed(dev_priv); gen7_setup_fixed_func_scheduler(dev_priv); @@ -7425,15 +7402,13 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); if (!HAS_PCH_NOP(dev_priv)) - cpt_init_clock_gating(dev); + cpt_init_clock_gating(dev_priv); - gen6_check_mch_setup(dev); + gen6_check_mch_setup(dev_priv); } -static void valleyview_init_clock_gating(struct drm_device *dev) +static void valleyview_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - /* WaDisableEarlyCull:vlv */ I915_WRITE(_3D_CHICKEN3, _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL)); @@ -7512,10 +7487,8 @@ static void valleyview_init_clock_gating(struct drm_device *dev) I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS); } -static void cherryview_init_clock_gating(struct drm_device *dev) +static void cherryview_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - /* WaVSRefCountFullforceMissDisable:chv */ /* WaDSRefCountFullforceMissDisable:chv */ I915_WRITE(GEN7_FF_THREAD_MODE, @@ -7548,9 +7521,8 @@ static void cherryview_init_clock_gating(struct drm_device *dev) I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL); } -static void g4x_init_clock_gating(struct drm_device *dev) +static void g4x_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t dspclk_gate; I915_WRITE(RENCLK_GATE_D1, 0); @@ -7572,13 +7544,11 @@ static void g4x_init_clock_gating(struct drm_device *dev) /* WaDisable_RenderCache_OperationalFlush:g4x */ I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE)); - g4x_disable_trickle_feed(dev); + g4x_disable_trickle_feed(dev_priv); } -static void crestline_init_clock_gating(struct drm_device *dev) +static void crestline_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); I915_WRITE(RENCLK_GATE_D2, 0); I915_WRITE(DSPCLK_GATE_D, 0); @@ -7591,10 +7561,8 @@ static void crestline_init_clock_gating(struct drm_device *dev) I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE)); } -static void broadwater_init_clock_gating(struct drm_device *dev) +static void broadwater_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | I965_RCC_CLOCK_GATE_DISABLE | I965_RCPB_CLOCK_GATE_DISABLE | @@ -7608,9 +7576,8 @@ static void broadwater_init_clock_gating(struct drm_device *dev) I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE)); } -static void gen3_init_clock_gating(struct drm_device *dev) +static void gen3_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); u32 dstate = I915_READ(D_STATE); dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | @@ -7633,10 +7600,8 @@ static void gen3_init_clock_gating(struct drm_device *dev) _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE)); } -static void i85x_init_clock_gating(struct drm_device *dev) +static void i85x_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); /* interrupts should cause a wake up from C3 */ @@ -7647,10 +7612,8 @@ static void i85x_init_clock_gating(struct drm_device *dev) _MASKED_BIT_ENABLE(MEM_DISPLAY_TRICKLE_FEED_DISABLE)); } -static void i830_init_clock_gating(struct drm_device *dev) +static void i830_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); I915_WRITE(MEM_MODE, @@ -7658,11 +7621,9 @@ static void i830_init_clock_gating(struct drm_device *dev) _MASKED_BIT_ENABLE(MEM_DISPLAY_B_TRICKLE_FEED_DISABLE)); } -void intel_init_clock_gating(struct drm_device *dev) +void intel_init_clock_gating(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - - dev_priv->display.init_clock_gating(dev); + dev_priv->display.init_clock_gating(dev_priv); } void intel_suspend_hw(struct drm_device *dev) @@ -7671,7 +7632,7 @@ void intel_suspend_hw(struct drm_device *dev) lpt_suspend_hw(dev); } -static void nop_init_clock_gating(struct drm_device *dev) +static void nop_init_clock_gating(struct drm_i915_private *dev_priv) { DRM_DEBUG_KMS("No clock gating settings or workarounds applied.\n"); } -- cgit v1.2.3 From 712bf36449ef6eb7a130153db9cb13fe897dc2e4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:23 +0200 Subject: drm/i915: Pass dev_priv to intel_suspend_hw() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-25-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f83dde9e36d1..48f4d210baf6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1435,7 +1435,7 @@ static int i915_drm_suspend(struct drm_device *dev) intel_suspend_encoders(dev_priv); - intel_suspend_hw(dev); + intel_suspend_hw(dev_priv); i915_gem_suspend_gtt_mappings(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3a9ca2755829..8765f8d5366c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1704,7 +1704,7 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, /* intel_pm.c */ void intel_init_clock_gating(struct drm_i915_private *dev_priv); -void intel_suspend_hw(struct drm_device *dev); +void intel_suspend_hw(struct drm_i915_private *dev_priv); int ilk_wm_max_level(const struct drm_i915_private *dev_priv); void intel_update_watermarks(struct intel_crtc *crtc); void intel_init_pm(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3e9bc2ac26b4..8c5fb8f6af10 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7139,10 +7139,8 @@ static void lpt_init_clock_gating(struct drm_i915_private *dev_priv) TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); } -static void lpt_suspend_hw(struct drm_device *dev) +static void lpt_suspend_hw(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - if (HAS_PCH_LPT_LP(dev_priv)) { uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D); @@ -7626,10 +7624,10 @@ void intel_init_clock_gating(struct drm_i915_private *dev_priv) dev_priv->display.init_clock_gating(dev_priv); } -void intel_suspend_hw(struct drm_device *dev) +void intel_suspend_hw(struct drm_i915_private *dev_priv) { - if (HAS_PCH_LPT(to_i915(dev))) - lpt_suspend_hw(dev); + if (HAS_PCH_LPT(dev_priv)) + lpt_suspend_hw(dev_priv); } static void nop_init_clock_gating(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From bb7265197a86bd68078825723b572599fcc60d2b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:24 +0200 Subject: drm/i915: Pass dev_priv to ilk_setup_wm_latency() & co. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-26-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_pm.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8c5fb8f6af10..d2320b19034e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -935,10 +935,8 @@ static unsigned int vlv_wm_method2(unsigned int pixel_rate, return ret; } -static void vlv_setup_wm_latency(struct drm_device *dev) +static void vlv_setup_wm_latency(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - /* all latencies in usec */ dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 3; @@ -2087,10 +2085,9 @@ hsw_compute_linetime_wm(const struct intel_crtc_state *cstate) PIPE_WM_LINETIME_TIME(linetime); } -static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) +static void intel_read_wm_latency(struct drm_i915_private *dev_priv, + uint16_t wm[8]) { - struct drm_i915_private *dev_priv = to_i915(dev); - if (IS_GEN9(dev_priv)) { uint32_t val; int ret, i; @@ -2176,14 +2173,14 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) wm[2] = (sskpd >> 12) & 0xFF; wm[3] = (sskpd >> 20) & 0x1FF; wm[4] = (sskpd >> 32) & 0x1FF; - } else if (INTEL_INFO(dev)->gen >= 6) { + } else if (INTEL_GEN(dev_priv) >= 6) { uint32_t sskpd = I915_READ(MCH_SSKPD); wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK; wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK; wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK; wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK; - } else if (INTEL_INFO(dev)->gen >= 5) { + } else if (INTEL_GEN(dev_priv) >= 5) { uint32_t mltr = I915_READ(MLTR_ILK); /* ILK primary LP0 latency is 700 ns */ @@ -2271,9 +2268,8 @@ static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv, return true; } -static void snb_wm_latency_quirk(struct drm_device *dev) +static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); bool changed; /* @@ -2293,11 +2289,9 @@ static void snb_wm_latency_quirk(struct drm_device *dev) intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); } -static void ilk_setup_wm_latency(struct drm_device *dev) +static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - - intel_read_wm_latency(dev, dev_priv->wm.pri_latency); + intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency); memcpy(dev_priv->wm.spr_latency, dev_priv->wm.pri_latency, sizeof(dev_priv->wm.pri_latency)); @@ -2312,14 +2306,12 @@ static void ilk_setup_wm_latency(struct drm_device *dev) intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); if (IS_GEN6(dev_priv)) - snb_wm_latency_quirk(dev); + snb_wm_latency_quirk(dev_priv); } -static void skl_setup_wm_latency(struct drm_device *dev) +static void skl_setup_wm_latency(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - - intel_read_wm_latency(dev, dev_priv->wm.skl_latency); + intel_read_wm_latency(dev_priv, dev_priv->wm.skl_latency); intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency); } @@ -7699,11 +7691,11 @@ void intel_init_pm(struct drm_device *dev) /* For FIFO watermark updates */ if (INTEL_INFO(dev)->gen >= 9) { - skl_setup_wm_latency(dev); + skl_setup_wm_latency(dev_priv); dev_priv->display.update_wm = skl_update_wm; dev_priv->display.compute_global_watermarks = skl_compute_wm; } else if (HAS_PCH_SPLIT(dev_priv)) { - ilk_setup_wm_latency(dev); + ilk_setup_wm_latency(dev_priv); if ((IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[1] && dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) || @@ -7721,10 +7713,10 @@ void intel_init_pm(struct drm_device *dev) "Disable CxSR\n"); } } else if (IS_CHERRYVIEW(dev_priv)) { - vlv_setup_wm_latency(dev); + vlv_setup_wm_latency(dev_priv); dev_priv->display.update_wm = vlv_update_wm; } else if (IS_VALLEYVIEW(dev_priv)) { - vlv_setup_wm_latency(dev); + vlv_setup_wm_latency(dev_priv); dev_priv->display.update_wm = vlv_update_wm; } else if (IS_PINEVIEW(dev_priv)) { if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv), -- cgit v1.2.3 From 62d75df7b00fab9487ba6f8012581c1d88a05abb Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Oct 2016 22:37:25 +0200 Subject: drm/i915: Pass dev_priv to intel_init_pm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify our approach to things by passing around dev_priv instead of dev. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1477946245-14134-27-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a46922aec99b..97589102442c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -16419,7 +16419,7 @@ int intel_modeset_init(struct drm_device *dev) intel_init_quirks(dev); - intel_init_pm(dev); + intel_init_pm(dev_priv); if (INTEL_INFO(dev)->num_pipes == 0) return 0; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8765f8d5366c..398195bf6dd1 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1707,7 +1707,7 @@ void intel_init_clock_gating(struct drm_i915_private *dev_priv); void intel_suspend_hw(struct drm_i915_private *dev_priv); int ilk_wm_max_level(const struct drm_i915_private *dev_priv); void intel_update_watermarks(struct intel_crtc *crtc); -void intel_init_pm(struct drm_device *dev); +void intel_init_pm(struct drm_i915_private *dev_priv); void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); void intel_pm_setup(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d2320b19034e..cc9e0c0f445f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7677,10 +7677,8 @@ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) } /* Set up chip specific power management-related functions */ -void intel_init_pm(struct drm_device *dev) +void intel_init_pm(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - intel_fbc_init(dev_priv); /* For cxsr */ @@ -7690,7 +7688,7 @@ void intel_init_pm(struct drm_device *dev) i915_ironlake_get_mem_freq(dev_priv); /* For FIFO watermark updates */ - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { skl_setup_wm_latency(dev_priv); dev_priv->display.update_wm = skl_update_wm; dev_priv->display.compute_global_watermarks = skl_compute_wm; @@ -7741,7 +7739,7 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.update_wm = i9xx_update_wm; dev_priv->display.get_fifo_size = i9xx_get_fifo_size; } else if (IS_GEN2(dev_priv)) { - if (INTEL_INFO(dev)->num_pipes == 1) { + if (INTEL_INFO(dev_priv)->num_pipes == 1) { dev_priv->display.update_wm = i845_update_wm; dev_priv->display.get_fifo_size = i845_get_fifo_size; } else { -- cgit v1.2.3 From 0183eb1c7504b290221f79bc3c345736f8ad657b Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Mon, 31 Oct 2016 22:26:53 +0200 Subject: qede: Don't override priv_flags Driver is now setting the ndev's priv_flags instead of adding to it, causing pktgen failure to utilize various features due to the loss of the IFF_TX_SKB_SHARING indication. Fixes: 7b7e70f979e3 ("qed*: Allow unicast filtering") Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 873f2ebe249e..df02c454eccc 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -2366,7 +2366,7 @@ static void qede_init_ndev(struct qede_dev *edev) qede_set_ethtool_ops(ndev); - ndev->priv_flags = IFF_UNICAST_FLT; + ndev->priv_flags |= IFF_UNICAST_FLT; /* user-changeble features */ hw_features = NETIF_F_GRO | NETIF_F_SG | -- cgit v1.2.3 From b0fca3122f6220e9a5bd975cdc5c4a87f575b740 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Mon, 31 Oct 2016 22:26:54 +0200 Subject: qed: Correct VF mac number When relaxing the limitation on the number of unicast MAC filters an interface can configure, qed started passing the MAC quota to qede. However, the value is initialized only for PFs, causing VFs to always try and configure themselves as promiscuous [as they believe they lack the resources to configure the rx-mode]. Fixes: 7b7e70f979e3 ("qed*: Allow unicast filtering") Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_l2.c | 2 ++ drivers/net/ethernet/qlogic/qed/qed_vf.c | 7 +++++++ drivers/net/ethernet/qlogic/qed/qed_vf.h | 13 +++++++++++++ 3 files changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 1e3a16edd16d..900b253be317 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1692,6 +1692,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev, qed_vf_get_num_vlan_filters(&cdev->hwfns[0], (u8 *)&info->num_vlan_filters); + qed_vf_get_num_mac_filters(&cdev->hwfns[0], + (u8 *)&info->num_mac_filters); qed_vf_get_port_mac(&cdev->hwfns[0], info->port_mac); info->is_legacy = !!cdev->hwfns[0].vf_iov_info->b_pre_fp_hsi; diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c index f580bf4c97f0..3c0633642f4c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.c +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c @@ -1171,6 +1171,13 @@ void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn, u8 *num_vlan_filters) *num_vlan_filters = p_vf->acquire_resp.resc.num_vlan_filters; } +void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn, u8 *num_mac_filters) +{ + struct qed_vf_iov *p_vf = p_hwfn->vf_iov_info; + + *num_mac_filters = p_vf->acquire_resp.resc.num_mac_filters; +} + bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac) { struct qed_bulletin_content *bulletin; diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.h b/drivers/net/ethernet/qlogic/qed/qed_vf.h index 944745b7c4c0..325c250d4ee5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.h +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.h @@ -622,6 +622,14 @@ void qed_vf_get_port_mac(struct qed_hwfn *p_hwfn, u8 *port_mac); void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn, u8 *num_vlan_filters); +/** + * @brief Get number of MAC filters allocated for VF by qed + * + * @param p_hwfn + * @param num_rxqs - allocated MAC filters + */ +void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn, u8 *num_mac_filters); + /** * @brief Check if VF can set a MAC address * @@ -872,6 +880,11 @@ static inline void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn, { } +static inline void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn, + u8 *num_mac_filters) +{ +} + static inline bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac) { return false; -- cgit v1.2.3 From 7ff5c83a1deb09419eaf33608dec120a00fcf923 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:09 +0000 Subject: nfp: simplify nfp_net_poll() There are few variables in nfp_net_poll() which are used only once or unused but set. Remove them. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index d365760fa75b..f6a42c14a1f0 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1525,21 +1525,15 @@ static int nfp_net_poll(struct napi_struct *napi, int budget) { struct nfp_net_r_vector *r_vec = container_of(napi, struct nfp_net_r_vector, napi); - struct nfp_net_rx_ring *rx_ring = r_vec->rx_ring; - struct nfp_net_tx_ring *tx_ring = r_vec->tx_ring; - struct nfp_net *nn = r_vec->nfp_net; - struct netdev_queue *txq; unsigned int pkts_polled; - tx_ring = &nn->tx_rings[rx_ring->idx]; - txq = netdev_get_tx_queue(nn->netdev, tx_ring->idx); - nfp_net_tx_complete(tx_ring); + nfp_net_tx_complete(r_vec->tx_ring); - pkts_polled = nfp_net_rx(rx_ring, budget); + pkts_polled = nfp_net_rx(r_vec->rx_ring, budget); if (pkts_polled < budget) { napi_complete_done(napi, pkts_polled); - nfp_net_irq_unmask(nn, r_vec->irq_idx); + nfp_net_irq_unmask(r_vec->nfp_net, r_vec->irq_idx); } return pkts_polled; -- cgit v1.2.3 From 416db5c1e448805866a6f23ebf7c78443f3d3bd5 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:10 +0000 Subject: nfp: remove support for nfp3200 Drop all code related to nfp3200. It was never widely deployed as a NIC. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 7 +- .../net/ethernet/netronome/nfp/nfp_net_common.c | 95 ++-------------------- drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 13 +-- .../net/ethernet/netronome/nfp/nfp_netvf_main.c | 45 ++-------- 4 files changed, 22 insertions(+), 138 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index ed824e11a1e3..808c38ae4991 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -421,7 +421,6 @@ struct nfp_stat_pair { * @netdev: Backpointer to net_device structure * @nfp_fallback: Is the driver used in fallback mode? * @is_vf: Is the driver attached to a VF? - * @is_nfp3200: Is the driver for a NFP-3200 card? * @fw_loaded: Is the firmware loaded? * @bpf_offload_skip_sw: Offloaded BPF program will not be rerun by cls_bpf * @ctrl: Local copy of the control register/word. @@ -487,7 +486,6 @@ struct nfp_net { unsigned nfp_fallback:1; unsigned is_vf:1; - unsigned is_nfp3200:1; unsigned fw_loaded:1; unsigned bpf_offload_skip_sw:1; @@ -593,16 +591,13 @@ static inline void nn_writeb(struct nfp_net *nn, int off, u8 val) writeb(val, nn->ctrl_bar + off); } -/* NFP-3200 can't handle 16-bit accesses too well */ static inline u16 nn_readw(struct nfp_net *nn, int off) { - WARN_ON_ONCE(nn->is_nfp3200); return readw(nn->ctrl_bar + off); } static inline void nn_writew(struct nfp_net *nn, int off, u16 val) { - WARN_ON_ONCE(nn->is_nfp3200); writew(val, nn->ctrl_bar + off); } @@ -650,7 +645,7 @@ static inline void nn_pci_flush(struct nfp_net *nn) #define NFP_QCP_QUEUE_STS_HI 0x000c #define NFP_QCP_QUEUE_STS_HI_WRITEPTR_mask 0x3ffff -/* The offset of a QCP queues in the PCIe Target (same on NFP3200 and NFP6000 */ +/* The offset of a QCP queues in the PCIe Target */ #define NFP_PCIE_QUEUE(_q) (0x80000 + (NFP_QCP_QUEUE_ADDR_SZ * ((_q) & 0xff))) /* nfp_qcp_ptr - Read or Write Pointer of a queue */ diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index f6a42c14a1f0..4e4b6e3b30d7 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -248,44 +248,15 @@ int nfp_net_reconfig(struct nfp_net *nn, u32 update) /* Interrupt configuration and handling */ -/** - * nfp_net_irq_unmask_msix() - Unmask MSI-X after automasking - * @nn: NFP Network structure - * @entry_nr: MSI-X table entry - * - * Clear the MSI-X table mask bit for the given entry bypassing Linux irq - * handling subsystem. Use *only* to reenable automasked vectors. - */ -static void nfp_net_irq_unmask_msix(struct nfp_net *nn, unsigned int entry_nr) -{ - struct list_head *msi_head = &nn->pdev->dev.msi_list; - struct msi_desc *entry; - u32 off; - - /* All MSI-Xs have the same mask_base */ - entry = list_first_entry(msi_head, struct msi_desc, list); - - off = (PCI_MSIX_ENTRY_SIZE * entry_nr) + - PCI_MSIX_ENTRY_VECTOR_CTRL; - writel(0, entry->mask_base + off); - readl(entry->mask_base); -} - /** * nfp_net_irq_unmask() - Unmask automasked interrupt * @nn: NFP Network structure * @entry_nr: MSI-X table entry * - * If MSI-X auto-masking is enabled clear the mask bit, otherwise - * clear the ICR for the entry. + * Clear the ICR for the IRQ entry. */ static void nfp_net_irq_unmask(struct nfp_net *nn, unsigned int entry_nr) { - if (nn->ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) { - nfp_net_irq_unmask_msix(nn, entry_nr); - return; - } - nn_writeb(nn, NFP_NET_CFG_ICR(entry_nr), NFP_NET_CFG_ICR_UNMASKED); nn_pci_flush(nn); } @@ -1368,20 +1339,6 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb, * more cleanly separate packet receive code from other bookkeeping * functions performed in the napi poll function. * - * There are differences between the NFP-3200 firmware and the - * NFP-6000 firmware. The NFP-3200 firmware uses a dedicated RX queue - * to indicate that new packets have arrived. The NFP-6000 does not - * have this queue and uses the DD bit in the RX descriptor. This - * method cannot be used on the NFP-3200 as it causes a race - * condition: The RX ring write pointer on the NFP-3200 is updated - * after packets (and descriptors) have been DMAed. If the DD bit is - * used and subsequently the read pointer is updated this may lead to - * the RX queue to underflow (if the firmware has not yet update the - * write pointer). Therefore we use slightly ugly conditional code - * below to handle the differences. We may, in the future update the - * NFP-3200 firmware to behave the same as the firmware on the - * NFP-6000. - * * Return: Number of packets received. */ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) @@ -1389,41 +1346,19 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; unsigned int data_len, meta_len; - int avail = 0, pkts_polled = 0; struct sk_buff *skb, *new_skb; struct nfp_net_rx_desc *rxd; dma_addr_t new_dma_addr; - u32 qcp_wr_p; + int pkts_polled = 0; int idx; - if (nn->is_nfp3200) { - /* Work out how many packets arrived */ - qcp_wr_p = nfp_qcp_wr_ptr_read(rx_ring->qcp_rx); - idx = rx_ring->rd_p % rx_ring->cnt; - - if (qcp_wr_p == idx) - /* No new packets */ - return 0; - - if (qcp_wr_p > idx) - avail = qcp_wr_p - idx; - else - avail = qcp_wr_p + rx_ring->cnt - idx; - } else { - avail = budget + 1; - } - - while (avail > 0 && pkts_polled < budget) { + while (pkts_polled < budget) { idx = rx_ring->rd_p % rx_ring->cnt; rxd = &rx_ring->rxds[idx]; - if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD)) { - if (nn->is_nfp3200) - nn_dbg(nn, "RX descriptor not valid (DD)%d:%u rxd[0]=%#x rxd[1]=%#x\n", - rx_ring->idx, idx, - rxd->vals[0], rxd->vals[1]); + if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD)) break; - } + /* Memory barrier to ensure that we won't do other reads * before the DD bit. */ @@ -1431,7 +1366,6 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) rx_ring->rd_p++; pkts_polled++; - avail--; skb = rx_ring->rxbufs[idx].skb; @@ -1508,9 +1442,6 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) napi_gro_receive(&rx_ring->r_vec->napi, skb); } - if (nn->is_nfp3200) - nfp_qcp_rd_ptr_add(rx_ring->qcp_rx, pkts_polled); - return pkts_polled; } @@ -1895,9 +1826,8 @@ static void nfp_net_write_mac_addr(struct nfp_net *nn) { nn_writel(nn, NFP_NET_CFG_MACADDR + 0, get_unaligned_be32(nn->netdev->dev_addr)); - /* We can't do writew for NFP-3200 compatibility */ - nn_writel(nn, NFP_NET_CFG_MACADDR + 4, - get_unaligned_be16(nn->netdev->dev_addr + 4) << 16); + nn_writew(nn, NFP_NET_CFG_MACADDR + 6, + get_unaligned_be16(nn->netdev->dev_addr + 4)); } static void nfp_net_vec_clear_ring_data(struct nfp_net *nn, unsigned int idx) @@ -2675,8 +2605,7 @@ static const struct net_device_ops nfp_net_netdev_ops = { */ void nfp_net_info(struct nfp_net *nn) { - nn_info(nn, "Netronome %s %sNetdev: TxQs=%d/%d RxQs=%d/%d\n", - nn->is_nfp3200 ? "NFP-32xx" : "NFP-6xxx", + nn_info(nn, "Netronome NFP-6xxx %sNetdev: TxQs=%d/%d RxQs=%d/%d\n", nn->is_vf ? "VF " : "", nn->num_tx_rings, nn->max_tx_rings, nn->num_rx_rings, nn->max_rx_rings); @@ -2891,13 +2820,7 @@ int nfp_net_netdev_init(struct net_device *netdev) nn->ctrl |= NFP_NET_CFG_CTRL_IRQMOD; } - /* On NFP-3200 enable MSI-X auto-masking, if supported and the - * interrupts are not shared. - */ - if (nn->is_nfp3200 && nn->cap & NFP_NET_CFG_CTRL_MSIXAUTO) - nn->ctrl |= NFP_NET_CFG_CTRL_MSIXAUTO; - - /* On NFP4000/NFP6000, determine RX packet/metadata boundary offset */ + /* Determine RX packet/metadata boundary offset */ if (nn->fw_ver.major >= 2) nn->rx_offset = nn_readl(nn, NFP_NET_CFG_RX_OFFSET); else diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h index 93b10b441acb..385ba355c965 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h @@ -50,7 +50,7 @@ /** * Configuration BAR size. * - * The configuration BAR is 8K in size, but on the NFP6000, due to + * The configuration BAR is 8K in size, but due to * THB-350, 32k needs to be reserved. */ #define NFP_NET_CFG_BAR_SZ (32 * 1024) @@ -186,18 +186,13 @@ #define NFP_NET_CFG_START_RXQ 0x004c /** - * NFP-3200 workaround (0x0050 - 0x0058) - * @NFP_NET_CFG_SPARE_ADDR: DMA address for ME code to use (e.g. YDS-155 fix) - */ -#define NFP_NET_CFG_SPARE_ADDR 0x0050 -/** - * NFP6000/NFP4000 - Prepend configuration + * Prepend configuration */ #define NFP_NET_CFG_RX_OFFSET 0x0050 #define NFP_NET_CFG_RX_OFFSET_DYNAMIC 0 /* Prepend mode */ /** - * NFP6000/NFP4000 - VXLAN/UDP encap configuration + * VXLAN/UDP encap configuration * @NFP_NET_CFG_VXLAN_PORT: Base address of table of tunnels' UDP dst ports * @NFP_NET_CFG_VXLAN_SZ: Size of the UDP port table in bytes */ @@ -205,7 +200,7 @@ #define NFP_NET_CFG_VXLAN_SZ 0x0008 /** - * NFP6000 - BPF section + * BPF section * @NFP_NET_CFG_BPF_ABI: BPF ABI version * @NFP_NET_CFG_BPF_CAP: BPF capabilities * @NFP_NET_CFG_BPF_MAX_LEN: Maximum size of JITed BPF code in bytes diff --git a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c index 2800bbf65a89..d065235034d4 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c @@ -63,9 +63,7 @@ static void nfp_netvf_get_mac_addr(struct nfp_net *nn) u8 mac_addr[ETH_ALEN]; put_unaligned_be32(nn_readl(nn, NFP_NET_CFG_MACADDR + 0), &mac_addr[0]); - /* We can't do readw for NFP-3200 compatibility */ - put_unaligned_be16(nn_readl(nn, NFP_NET_CFG_MACADDR + 4) >> 16, - &mac_addr[4]); + put_unaligned_be16(nn_readw(nn, NFP_NET_CFG_MACADDR + 6), &mac_addr[4]); if (!is_valid_ether_addr(mac_addr)) { eth_hw_addr_random(nn->netdev); @@ -86,7 +84,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, int tx_bar_no, rx_bar_no; u8 __iomem *ctrl_bar; struct nfp_net *nn; - int is_nfp3200; u32 startq; int stride; int err; @@ -101,15 +98,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, goto err_pci_disable; } - switch (pdev->device) { - case PCI_DEVICE_NFP6000VF: - is_nfp3200 = 0; - break; - default: - err = -ENODEV; - goto err_pci_regions; - } - pci_set_master(pdev); err = dma_set_mask_and_coherent(&pdev->dev, @@ -149,15 +137,9 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, } else { switch (fw_ver.major) { case 1 ... 4: - if (is_nfp3200) { - stride = 2; - tx_bar_no = NFP_NET_Q0_BAR; - rx_bar_no = NFP_NET_Q1_BAR; - } else { - stride = 4; - tx_bar_no = NFP_NET_Q0_BAR; - rx_bar_no = tx_bar_no; - } + stride = 4; + tx_bar_no = NFP_NET_Q0_BAR; + rx_bar_no = tx_bar_no; break; default: dev_err(&pdev->dev, "Unsupported Firmware ABI %d.%d.%d.%d\n", @@ -189,20 +171,10 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, max_rx_rings = (rx_bar_sz / NFP_QCP_QUEUE_ADDR_SZ) / 2; } - /* XXX Implement a workaround for THB-350 here. Ideally, we - * have a different PCI ID for A rev VFs. - */ - switch (pdev->device) { - case PCI_DEVICE_NFP6000VF: - startq = readl(ctrl_bar + NFP_NET_CFG_START_TXQ); - tx_bar_off = NFP_PCIE_QUEUE(startq); - startq = readl(ctrl_bar + NFP_NET_CFG_START_RXQ); - rx_bar_off = NFP_PCIE_QUEUE(startq); - break; - default: - err = -ENODEV; - goto err_ctrl_unmap; - } + startq = readl(ctrl_bar + NFP_NET_CFG_START_TXQ); + tx_bar_off = NFP_PCIE_QUEUE(startq); + startq = readl(ctrl_bar + NFP_NET_CFG_START_RXQ); + rx_bar_off = NFP_PCIE_QUEUE(startq); /* Allocate and initialise the netdev */ nn = nfp_net_netdev_alloc(pdev, max_tx_rings, max_rx_rings); @@ -214,7 +186,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, nn->fw_ver = fw_ver; nn->ctrl_bar = ctrl_bar; nn->is_vf = 1; - nn->is_nfp3200 = is_nfp3200; nn->stride_tx = stride; nn->stride_rx = stride; -- cgit v1.2.3 From 8c8b0e99eb5c008158e095ecc3a42755ba9a7f8d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:11 +0000 Subject: nfp: remove unnecessary call to ether_setup() ether_setup() will be invoked by alloc_etherdev_mqs(), no need to call it again. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 4e4b6e3b30d7..bd28e42bee2b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2839,7 +2839,6 @@ int nfp_net_netdev_init(struct net_device *netdev) return err; /* Finalise the netdev setup */ - ether_setup(netdev); netdev->netdev_ops = &nfp_net_netdev_ops; netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000); -- cgit v1.2.3 From fa95f1d2bf1816eee736192fa1f75ed96c0ab9cf Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:12 +0000 Subject: nfp: remove inline attributes and dead code Don't declare functions as static inline in .c files and remove dead code it was hiding. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index bd28e42bee2b..025483fb9103 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -576,7 +576,7 @@ static void nfp_net_aux_irq_free(struct nfp_net *nn, u32 ctrl_offset, * * Return: True if the ring is full. */ -static inline int nfp_net_tx_full(struct nfp_net_tx_ring *tx_ring, int dcnt) +static int nfp_net_tx_full(struct nfp_net_tx_ring *tx_ring, int dcnt) { return (tx_ring->wr_p - tx_ring->rd_p) >= (tx_ring->cnt - dcnt); } @@ -1031,19 +1031,6 @@ static void nfp_net_tx_timeout(struct net_device *netdev) /* Receive processing */ -/** - * nfp_net_rx_space() - return the number of free slots on the RX ring - * @rx_ring: RX ring structure - * - * Make sure we leave at least one slot free. - * - * Return: True if there is space on the RX ring - */ -static inline int nfp_net_rx_space(struct nfp_net_rx_ring *rx_ring) -{ - return (rx_ring->cnt - 1) - (rx_ring->wr_p - rx_ring->rd_p); -} - /** * nfp_net_rx_alloc_one() - Allocate and map skb for RX * @rx_ring: RX ring structure of the skb -- cgit v1.2.3 From bf187ea01b07739167420088adb385f9385a7c7f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:13 +0000 Subject: nfp: centralize the buffer size calculation Add a helper function to calculate the buffer size at run time. Buffer lengths will now depend on the FW prepend configuration instead of assuming the most space consuming configuration and defaulting to 2k buffers at initialization time. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 1 - .../net/ethernet/netronome/nfp/nfp_net_common.c | 29 ++++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 808c38ae4991..9b90fab8a6df 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -75,7 +75,6 @@ /* Default size for MTU and freelist buffer sizes */ #define NFP_NET_DEFAULT_MTU 1500 -#define NFP_NET_DEFAULT_RX_BUFSZ 2048 /* Maximum number of bytes prepended to a packet */ #define NFP_NET_MAX_PREPEND 64 diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 025483fb9103..77c645abb827 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1030,6 +1030,19 @@ static void nfp_net_tx_timeout(struct net_device *netdev) /* Receive processing */ +static unsigned int +nfp_net_calc_fl_bufsz(struct nfp_net *nn, unsigned int mtu) +{ + unsigned int fl_bufsz; + + if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) + fl_bufsz = NFP_NET_MAX_PREPEND; + else + fl_bufsz = nn->rx_offset; + fl_bufsz += ETH_HLEN + VLAN_HLEN * 2 + mtu; + + return fl_bufsz; +} /** * nfp_net_rx_alloc_one() - Allocate and map skb for RX @@ -2191,7 +2204,7 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) old_mtu = netdev->mtu; old_fl_bufsz = nn->fl_bufsz; - new_fl_bufsz = NFP_NET_MAX_PREPEND + ETH_HLEN + VLAN_HLEN * 2 + new_mtu; + new_fl_bufsz = nfp_net_calc_fl_bufsz(nn, new_mtu); if (!netif_running(netdev)) { netdev->mtu = new_mtu; @@ -2731,12 +2744,18 @@ int nfp_net_netdev_init(struct net_device *netdev) nfp_net_write_mac_addr(nn); + /* Determine RX packet/metadata boundary offset */ + if (nn->fw_ver.major >= 2) + nn->rx_offset = nn_readl(nn, NFP_NET_CFG_RX_OFFSET); + else + nn->rx_offset = NFP_NET_RX_OFFSET; + /* Set default MTU and Freelist buffer size */ if (nn->max_mtu < NFP_NET_DEFAULT_MTU) netdev->mtu = nn->max_mtu; else netdev->mtu = NFP_NET_DEFAULT_MTU; - nn->fl_bufsz = NFP_NET_DEFAULT_RX_BUFSZ; + nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, netdev->mtu); /* Advertise/enable offloads based on capabilities * @@ -2807,12 +2826,6 @@ int nfp_net_netdev_init(struct net_device *netdev) nn->ctrl |= NFP_NET_CFG_CTRL_IRQMOD; } - /* Determine RX packet/metadata boundary offset */ - if (nn->fw_ver.major >= 2) - nn->rx_offset = nn_readl(nn, NFP_NET_CFG_RX_OFFSET); - else - nn->rx_offset = NFP_NET_RX_OFFSET; - /* Stash the re-configuration queue away. First odd queue in TX Bar */ nn->qcp_cfg = nn->tx_bar + NFP_QCP_QUEUE_ADDR_SZ; -- cgit v1.2.3 From e9949aebe04a1d917a15f4dc71e77deaefe9de94 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:14 +0000 Subject: nfp: add buffer drop/recycle helper for RX nfp_net_rx() is quite long already and about to get longer. Move buffer drop/recycle to a helper. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 77c645abb827..abd4f17e89c7 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1330,6 +1330,20 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb, return data; } +static void +nfp_net_rx_drop(struct nfp_net_r_vector *r_vec, struct nfp_net_rx_ring *rx_ring, + struct nfp_net_rx_buf *rxbuf, struct sk_buff *skb) +{ + u64_stats_update_begin(&r_vec->rx_sync); + r_vec->rx_drops++; + u64_stats_update_end(&r_vec->rx_sync); + + if (rxbuf) + nfp_net_rx_give_one(rx_ring, rxbuf->skb, rxbuf->dma_addr); + if (skb) + dev_kfree_skb_any(skb); +} + /** * nfp_net_rx() - receive up to @budget packets on @rx_ring * @rx_ring: RX ring to receive from @@ -1372,11 +1386,8 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) new_skb = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr, nn->fl_bufsz); if (!new_skb) { - nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[idx].skb, - rx_ring->rxbufs[idx].dma_addr); - u64_stats_update_begin(&r_vec->rx_sync); - r_vec->rx_drops++; - u64_stats_update_end(&r_vec->rx_sync); + nfp_net_rx_drop(r_vec, rx_ring, &rx_ring->rxbufs[idx], + NULL); continue; } @@ -1420,12 +1431,8 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) end = nfp_net_parse_meta(nn->netdev, skb, meta_len); if (unlikely(end != skb->data)) { - u64_stats_update_begin(&r_vec->rx_sync); - r_vec->rx_drops++; - u64_stats_update_end(&r_vec->rx_sync); - - dev_kfree_skb_any(skb); nn_warn_ratelimit(nn, "invalid RX packet metadata\n"); + nfp_net_rx_drop(r_vec, rx_ring, NULL, skb); continue; } } -- cgit v1.2.3 From c0f031bc88660e8b96060b76aa72fbe8859bdcc8 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:15 +0000 Subject: nfp: use alloc_frag() and build_skb() Speed up RX processing by moving to the alloc_frag()/build_skb() paradigm. Since we're no longer mapping the entire buffer for DMA add helpers which take care of calculating offsets and lengths. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 8 +- .../net/ethernet/netronome/nfp/nfp_net_common.c | 115 +++++++++++++-------- .../net/ethernet/netronome/nfp/nfp_net_debugfs.c | 9 +- 3 files changed, 82 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 9b90fab8a6df..9ca066b29f07 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -101,6 +101,10 @@ /* Offload definitions */ #define NFP_NET_N_VXLAN_PORTS (NFP_NET_CFG_VXLAN_SZ / sizeof(__be16)) +#define NFP_NET_RX_BUF_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN) +#define NFP_NET_RX_BUF_NON_DATA (NFP_NET_RX_BUF_HEADROOM + \ + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) + /* Forward declarations */ struct nfp_net; struct nfp_net_r_vector; @@ -277,11 +281,11 @@ struct nfp_net_rx_hash { /** * struct nfp_net_rx_buf - software RX buffer descriptor - * @skb: sk_buff associated with this buffer + * @frag: page fragment buffer * @dma_addr: DMA mapping address of the buffer */ struct nfp_net_rx_buf { - struct sk_buff *skb; + void *frag; dma_addr_t dma_addr; }; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index abd4f17e89c7..449ec798a9b7 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,22 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver, put_unaligned_le32(reg, fw_ver); } +static dma_addr_t +nfp_net_dma_map_rx(struct nfp_net *nn, void *frag, unsigned int bufsz, + int direction) +{ + return dma_map_single(&nn->pdev->dev, frag + NFP_NET_RX_BUF_HEADROOM, + bufsz - NFP_NET_RX_BUF_NON_DATA, direction); +} + +static void +nfp_net_dma_unmap_rx(struct nfp_net *nn, dma_addr_t dma_addr, + unsigned int bufsz, int direction) +{ + dma_unmap_single(&nn->pdev->dev, dma_addr, + bufsz - NFP_NET_RX_BUF_NON_DATA, direction); +} + /* Firmware reconfig * * Firmware reconfig may take a while so we have two versions of it - @@ -1035,64 +1052,67 @@ nfp_net_calc_fl_bufsz(struct nfp_net *nn, unsigned int mtu) { unsigned int fl_bufsz; + fl_bufsz = NFP_NET_RX_BUF_HEADROOM; if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) - fl_bufsz = NFP_NET_MAX_PREPEND; + fl_bufsz += NFP_NET_MAX_PREPEND; else - fl_bufsz = nn->rx_offset; + fl_bufsz += nn->rx_offset; fl_bufsz += ETH_HLEN + VLAN_HLEN * 2 + mtu; + fl_bufsz = SKB_DATA_ALIGN(fl_bufsz); + fl_bufsz += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + return fl_bufsz; } /** - * nfp_net_rx_alloc_one() - Allocate and map skb for RX + * nfp_net_rx_alloc_one() - Allocate and map page frag for RX * @rx_ring: RX ring structure of the skb * @dma_addr: Pointer to storage for DMA address (output param) * @fl_bufsz: size of freelist buffers * - * This function will allcate a new skb, map it for DMA. + * This function will allcate a new page frag, map it for DMA. * - * Return: allocated skb or NULL on failure. + * Return: allocated page frag or NULL on failure. */ -static struct sk_buff * +static void * nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr, unsigned int fl_bufsz) { struct nfp_net *nn = rx_ring->r_vec->nfp_net; - struct sk_buff *skb; + void *frag; - skb = netdev_alloc_skb(nn->netdev, fl_bufsz); - if (!skb) { - nn_warn_ratelimit(nn, "Failed to alloc receive SKB\n"); + frag = netdev_alloc_frag(fl_bufsz); + if (!frag) { + nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n"); return NULL; } - *dma_addr = dma_map_single(&nn->pdev->dev, skb->data, - fl_bufsz, DMA_FROM_DEVICE); + *dma_addr = nfp_net_dma_map_rx(nn, frag, fl_bufsz, DMA_FROM_DEVICE); if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) { - dev_kfree_skb_any(skb); + skb_free_frag(frag); nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n"); return NULL; } - return skb; + return frag; } /** * nfp_net_rx_give_one() - Put mapped skb on the software and hardware rings * @rx_ring: RX ring structure - * @skb: Skb to put on rings + * @frag: page fragment buffer * @dma_addr: DMA address of skb mapping */ static void nfp_net_rx_give_one(struct nfp_net_rx_ring *rx_ring, - struct sk_buff *skb, dma_addr_t dma_addr) + void *frag, dma_addr_t dma_addr) { unsigned int wr_idx; wr_idx = rx_ring->wr_p % rx_ring->cnt; /* Stash SKB and DMA address away */ - rx_ring->rxbufs[wr_idx].skb = skb; + rx_ring->rxbufs[wr_idx].frag = frag; rx_ring->rxbufs[wr_idx].dma_addr = dma_addr; /* Fill freelist descriptor */ @@ -1127,9 +1147,9 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring) wr_idx = rx_ring->wr_p % rx_ring->cnt; last_idx = rx_ring->cnt - 1; rx_ring->rxbufs[wr_idx].dma_addr = rx_ring->rxbufs[last_idx].dma_addr; - rx_ring->rxbufs[wr_idx].skb = rx_ring->rxbufs[last_idx].skb; + rx_ring->rxbufs[wr_idx].frag = rx_ring->rxbufs[last_idx].frag; rx_ring->rxbufs[last_idx].dma_addr = 0; - rx_ring->rxbufs[last_idx].skb = NULL; + rx_ring->rxbufs[last_idx].frag = NULL; memset(rx_ring->rxds, 0, sizeof(*rx_ring->rxds) * rx_ring->cnt); rx_ring->wr_p = 0; @@ -1149,7 +1169,6 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring) static void nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) { - struct pci_dev *pdev = nn->pdev; unsigned int i; for (i = 0; i < rx_ring->cnt - 1; i++) { @@ -1157,14 +1176,14 @@ nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) * fails to allocate enough buffers and calls here to free * already allocated ones. */ - if (!rx_ring->rxbufs[i].skb) + if (!rx_ring->rxbufs[i].frag) continue; - dma_unmap_single(&pdev->dev, rx_ring->rxbufs[i].dma_addr, - rx_ring->bufsz, DMA_FROM_DEVICE); - dev_kfree_skb_any(rx_ring->rxbufs[i].skb); + nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[i].dma_addr, + rx_ring->bufsz, DMA_FROM_DEVICE); + skb_free_frag(rx_ring->rxbufs[i].frag); rx_ring->rxbufs[i].dma_addr = 0; - rx_ring->rxbufs[i].skb = NULL; + rx_ring->rxbufs[i].frag = NULL; } } @@ -1182,10 +1201,10 @@ nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) rxbufs = rx_ring->rxbufs; for (i = 0; i < rx_ring->cnt - 1; i++) { - rxbufs[i].skb = + rxbufs[i].frag = nfp_net_rx_alloc_one(rx_ring, &rxbufs[i].dma_addr, rx_ring->bufsz); - if (!rxbufs[i].skb) { + if (!rxbufs[i].frag) { nfp_net_rx_ring_bufs_free(nn, rx_ring); return -ENOMEM; } @@ -1203,7 +1222,7 @@ static void nfp_net_rx_ring_fill_freelist(struct nfp_net_rx_ring *rx_ring) unsigned int i; for (i = 0; i < rx_ring->cnt - 1; i++) - nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[i].skb, + nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[i].frag, rx_ring->rxbufs[i].dma_addr); } @@ -1338,8 +1357,13 @@ nfp_net_rx_drop(struct nfp_net_r_vector *r_vec, struct nfp_net_rx_ring *rx_ring, r_vec->rx_drops++; u64_stats_update_end(&r_vec->rx_sync); + /* skb is build based on the frag, free_skb() would free the frag + * so to be able to reuse it we need an extra ref. + */ + if (skb && rxbuf && skb->head == rxbuf->frag) + page_ref_inc(virt_to_head_page(rxbuf->frag)); if (rxbuf) - nfp_net_rx_give_one(rx_ring, rxbuf->skb, rxbuf->dma_addr); + nfp_net_rx_give_one(rx_ring, rxbuf->frag, rxbuf->dma_addr); if (skb) dev_kfree_skb_any(skb); } @@ -1360,10 +1384,12 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; unsigned int data_len, meta_len; - struct sk_buff *skb, *new_skb; + struct nfp_net_rx_buf *rxbuf; struct nfp_net_rx_desc *rxd; dma_addr_t new_dma_addr; + struct sk_buff *skb; int pkts_polled = 0; + void *new_frag; int idx; while (pkts_polled < budget) { @@ -1381,21 +1407,23 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) rx_ring->rd_p++; pkts_polled++; - skb = rx_ring->rxbufs[idx].skb; - - new_skb = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr, - nn->fl_bufsz); - if (!new_skb) { - nfp_net_rx_drop(r_vec, rx_ring, &rx_ring->rxbufs[idx], - NULL); + rxbuf = &rx_ring->rxbufs[idx]; + skb = build_skb(rxbuf->frag, nn->fl_bufsz); + if (unlikely(!skb)) { + nfp_net_rx_drop(r_vec, rx_ring, rxbuf, NULL); + continue; + } + new_frag = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr, + nn->fl_bufsz); + if (unlikely(!new_frag)) { + nfp_net_rx_drop(r_vec, rx_ring, rxbuf, skb); continue; } - dma_unmap_single(&nn->pdev->dev, - rx_ring->rxbufs[idx].dma_addr, - nn->fl_bufsz, DMA_FROM_DEVICE); + nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[idx].dma_addr, + nn->fl_bufsz, DMA_FROM_DEVICE); - nfp_net_rx_give_one(rx_ring, new_skb, new_dma_addr); + nfp_net_rx_give_one(rx_ring, new_frag, new_dma_addr); /* < meta_len > * <-- [rx_offset] --> @@ -1413,9 +1441,10 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) data_len = le16_to_cpu(rxd->rxd.data_len); if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) - skb_reserve(skb, meta_len); + skb_reserve(skb, NFP_NET_RX_BUF_HEADROOM + meta_len); else - skb_reserve(skb, nn->rx_offset); + skb_reserve(skb, + NFP_NET_RX_BUF_HEADROOM + nn->rx_offset); skb_put(skb, data_len - meta_len); /* Stats update */ diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c index f7c9a5bc4aa3..180cf70f0093 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c @@ -44,8 +44,8 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data) struct nfp_net_r_vector *r_vec = file->private; struct nfp_net_rx_ring *rx_ring; struct nfp_net_rx_desc *rxd; - struct sk_buff *skb; struct nfp_net *nn; + void *frag; int i; rtnl_lock(); @@ -73,10 +73,9 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data) seq_printf(file, "%04d: 0x%08x 0x%08x", i, rxd->vals[0], rxd->vals[1]); - skb = READ_ONCE(rx_ring->rxbufs[i].skb); - if (skb) - seq_printf(file, " skb->head=%p skb->data=%p", - skb->head, skb->data); + frag = READ_ONCE(rx_ring->rxbufs[i].frag); + if (frag) + seq_printf(file, " frag=%p", frag); if (rx_ring->rxbufs[i].dma_addr) seq_printf(file, " dma_addr=%pad", -- cgit v1.2.3 From b64b7bb6d492ef1bbe9aa9ed7eeb18f7148ece3d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:16 +0000 Subject: nfp: add separate buffer allocation function for napi Introduce a separate buffer allocation function to be called from NAPI. We can make assumptions about the context and buffer size. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 449ec798a9b7..b43d2dbae368 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1098,6 +1098,26 @@ nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr, return frag; } +static void *nfp_net_napi_alloc_one(struct nfp_net *nn, dma_addr_t *dma_addr) +{ + void *frag; + + frag = napi_alloc_frag(nn->fl_bufsz); + if (!frag) { + nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n"); + return NULL; + } + + *dma_addr = nfp_net_dma_map_rx(nn, frag, nn->fl_bufsz, DMA_FROM_DEVICE); + if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) { + skb_free_frag(frag); + nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n"); + return NULL; + } + + return frag; +} + /** * nfp_net_rx_give_one() - Put mapped skb on the software and hardware rings * @rx_ring: RX ring structure @@ -1413,8 +1433,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) nfp_net_rx_drop(r_vec, rx_ring, rxbuf, NULL); continue; } - new_frag = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr, - nn->fl_bufsz); + new_frag = nfp_net_napi_alloc_one(nn, &new_dma_addr); if (unlikely(!new_frag)) { nfp_net_rx_drop(r_vec, rx_ring, rxbuf, skb); continue; -- cgit v1.2.3 From 1a1d74d378b13ad3f93e8975a0ade0980a49d28b Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:17 +0000 Subject: nfp: use AND instead of modulo to get ring indexes We already force ring sizes to be power of 2 so replace modulo operations with AND (size - 1) in index calculations. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index b43d2dbae368..7225ab61a120 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -778,7 +778,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) if (dma_mapping_error(&nn->pdev->dev, dma_addr)) goto err_free; - wr_idx = tx_ring->wr_p % tx_ring->cnt; + wr_idx = tx_ring->wr_p & (tx_ring->cnt - 1); /* Stash the soft descriptor of the head then initialize it */ txbuf = &tx_ring->txbufs[wr_idx]; @@ -822,7 +822,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) if (dma_mapping_error(&nn->pdev->dev, dma_addr)) goto err_unmap; - wr_idx = (wr_idx + 1) % tx_ring->cnt; + wr_idx = (wr_idx + 1) & (tx_ring->cnt - 1); tx_ring->txbufs[wr_idx].skb = skb; tx_ring->txbufs[wr_idx].dma_addr = dma_addr; tx_ring->txbufs[wr_idx].fidx = f; @@ -917,7 +917,7 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring) todo = qcp_rd_p + tx_ring->cnt - tx_ring->qcp_rd_p; while (todo--) { - idx = tx_ring->rd_p % tx_ring->cnt; + idx = tx_ring->rd_p & (tx_ring->cnt - 1); tx_ring->rd_p++; skb = tx_ring->txbufs[idx].skb; @@ -992,7 +992,7 @@ nfp_net_tx_ring_reset(struct nfp_net *nn, struct nfp_net_tx_ring *tx_ring) int nr_frags, fidx, idx; struct sk_buff *skb; - idx = tx_ring->rd_p % tx_ring->cnt; + idx = tx_ring->rd_p & (tx_ring->cnt - 1); skb = tx_ring->txbufs[idx].skb; nr_frags = skb_shinfo(skb)->nr_frags; fidx = tx_ring->txbufs[idx].fidx; @@ -1129,7 +1129,7 @@ static void nfp_net_rx_give_one(struct nfp_net_rx_ring *rx_ring, { unsigned int wr_idx; - wr_idx = rx_ring->wr_p % rx_ring->cnt; + wr_idx = rx_ring->wr_p & (rx_ring->cnt - 1); /* Stash SKB and DMA address away */ rx_ring->rxbufs[wr_idx].frag = frag; @@ -1164,7 +1164,7 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring) unsigned int wr_idx, last_idx; /* Move the empty entry to the end of the list */ - wr_idx = rx_ring->wr_p % rx_ring->cnt; + wr_idx = rx_ring->wr_p & (rx_ring->cnt - 1); last_idx = rx_ring->cnt - 1; rx_ring->rxbufs[wr_idx].dma_addr = rx_ring->rxbufs[last_idx].dma_addr; rx_ring->rxbufs[wr_idx].frag = rx_ring->rxbufs[last_idx].frag; @@ -1413,7 +1413,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) int idx; while (pkts_polled < budget) { - idx = rx_ring->rd_p % rx_ring->cnt; + idx = rx_ring->rd_p & (rx_ring->cnt - 1); rxd = &rx_ring->rxds[idx]; if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD)) -- cgit v1.2.3 From 23a4e389bdc71fda949b5a19a28fa99c4d746d43 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:18 +0000 Subject: nfp: create separate define for max number of vectors We are currently using define for max TX rings to allocate IRQ vectors. It's OK since the max number of rings for TX and RX are currently the same, but lets make the code nicer by taking max of the two. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 9ca066b29f07..55a497c02237 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -87,6 +87,9 @@ /* Queue/Ring definitions */ #define NFP_NET_MAX_TX_RINGS 64 /* Max. # of Tx rings per device */ #define NFP_NET_MAX_RX_RINGS 64 /* Max. # of Rx rings per device */ +#define NFP_NET_MAX_R_VECS (NFP_NET_MAX_TX_RINGS > NFP_NET_MAX_RX_RINGS ? \ + NFP_NET_MAX_TX_RINGS : NFP_NET_MAX_RX_RINGS) +#define NFP_NET_MAX_IRQS (NFP_NET_NON_Q_VECTORS + NFP_NET_MAX_R_VECS) #define NFP_NET_MIN_TX_DESCS 256 /* Min. # of Tx descs per ring */ #define NFP_NET_MIN_RX_DESCS 256 /* Min. # of Rx descs per ring */ @@ -539,9 +542,8 @@ struct nfp_net { u8 num_irqs; u8 num_r_vecs; - struct nfp_net_r_vector r_vecs[NFP_NET_MAX_TX_RINGS]; - struct msix_entry irq_entries[NFP_NET_NON_Q_VECTORS + - NFP_NET_MAX_TX_RINGS]; + struct nfp_net_r_vector r_vecs[NFP_NET_MAX_R_VECS]; + struct msix_entry irq_entries[NFP_NET_MAX_IRQS]; irq_handler_t lsc_handler; char lsc_name[IFNAMSIZ + 8]; -- cgit v1.2.3 From a4b562bb8ebd418dcfeba2840a7ece25a74d8385 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:19 +0000 Subject: nfp: use unsigned int for vector/ring counts Use unsigned int consistently for vector/ring counts. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 17 +++++++++-------- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 5 +++-- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 55a497c02237..0ea6ebd329cf 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -528,11 +528,11 @@ struct nfp_net { struct timer_list rx_filter_stats_timer; spinlock_t rx_filter_lock; - int max_tx_rings; - int max_rx_rings; + unsigned int max_tx_rings; + unsigned int max_rx_rings; - int num_tx_rings; - int num_rx_rings; + unsigned int num_tx_rings; + unsigned int num_rx_rings; int stride_tx; int stride_rx; @@ -540,8 +540,8 @@ struct nfp_net { int txd_cnt; int rxd_cnt; - u8 num_irqs; - u8 num_r_vecs; + unsigned int num_irqs; + unsigned int num_r_vecs; struct nfp_net_r_vector r_vecs[NFP_NET_MAX_R_VECS]; struct msix_entry irq_entries[NFP_NET_MAX_IRQS]; @@ -757,8 +757,9 @@ extern const char nfp_net_driver_version[]; void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver, void __iomem *ctrl_bar); -struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, - int max_tx_rings, int max_rx_rings); +struct nfp_net * +nfp_net_netdev_alloc(struct pci_dev *pdev, + unsigned int max_tx_rings, unsigned int max_rx_rings); void nfp_net_netdev_free(struct nfp_net *nn); int nfp_net_netdev_init(struct net_device *netdev); void nfp_net_netdev_clean(struct net_device *netdev); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 7225ab61a120..49a1f54e0787 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -318,8 +318,8 @@ static int nfp_net_msix_alloc(struct nfp_net *nn, int nr_vecs) */ static int nfp_net_irqs_wanted(struct nfp_net *nn) { + unsigned int vecs; int ncpus; - int vecs; ncpus = num_online_cpus(); @@ -2701,7 +2701,8 @@ void nfp_net_info(struct nfp_net *nn) * Return: NFP Net device structure, or ERR_PTR on error. */ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, - int max_tx_rings, int max_rx_rings) + unsigned int max_tx_rings, + unsigned int max_rx_rings) { struct net_device *netdev; struct nfp_net *nn; -- cgit v1.2.3 From 4b27a1eb7b83da956c3939869ed22f5ca0e1f1e1 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:20 +0000 Subject: nfp: remove nfp_net_irqs_wanted() nfp_net_irqs_wanted() doesn't really encapsulate much logic, remove it and inline the calculations. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 27 ++++------------------ 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 49a1f54e0787..f26c3927746f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -307,28 +307,6 @@ static int nfp_net_msix_alloc(struct nfp_net *nn, int nr_vecs) return nvecs; } -/** - * nfp_net_irqs_wanted() - Work out how many interrupt vectors we want - * @nn: NFP Network structure - * - * We want a vector per CPU (or ring), whatever is smaller plus - * NFP_NET_NON_Q_VECTORS for LSC etc. - * - * Return: Number of interrupts wanted - */ -static int nfp_net_irqs_wanted(struct nfp_net *nn) -{ - unsigned int vecs; - int ncpus; - - ncpus = num_online_cpus(); - - vecs = max_t(int, nn->num_tx_rings, nn->num_rx_rings); - vecs = min_t(int, vecs, ncpus); - - return vecs + NFP_NET_NON_Q_VECTORS; -} - /** * nfp_net_irqs_alloc() - allocates MSI-X irqs * @nn: NFP Network structure @@ -339,7 +317,7 @@ int nfp_net_irqs_alloc(struct nfp_net *nn) { int wanted_irqs; - wanted_irqs = nfp_net_irqs_wanted(nn); + wanted_irqs = nn->num_r_vecs + NFP_NET_NON_Q_VECTORS; nn->num_irqs = nfp_net_msix_alloc(nn, wanted_irqs); if (nn->num_irqs == 0) { @@ -2726,6 +2704,9 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, nn->num_tx_rings = min_t(int, nqs, max_tx_rings); nn->num_rx_rings = min_t(int, nqs, max_rx_rings); + nn->num_r_vecs = max(nn->num_tx_rings, nn->num_rx_rings); + nn->num_r_vecs = min_t(unsigned int, nn->num_r_vecs, num_online_cpus()); + nn->txd_cnt = NFP_NET_TX_DESCS_DEFAULT; nn->rxd_cnt = NFP_NET_RX_DESCS_DEFAULT; -- cgit v1.2.3 From b33ae997a362d64a1178be17804c2c3899770a4b Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:21 +0000 Subject: nfp: replace num_irqs with max_r_vecs num_irqs is not used anywhere, replace it with max_r_vecs which holds number of allocated RX/TX vectors and is going to be useful soon. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 4 ++-- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 0ea6ebd329cf..e8713254786b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -456,7 +456,7 @@ struct nfp_stat_pair { * @rxd_cnt: Size of the RX ring in number of descriptors * @tx_rings: Array of pre-allocated TX ring structures * @rx_rings: Array of pre-allocated RX ring structures - * @num_irqs: Number of allocated interrupt vectors + * @max_r_vecs: Number of allocated interrupt vectors for RX/TX * @num_r_vecs: Number of used ring vectors * @r_vecs: Pre-allocated array of ring vectors * @irq_entries: Pre-allocated array of MSI-X entries @@ -540,7 +540,7 @@ struct nfp_net { int txd_cnt; int rxd_cnt; - unsigned int num_irqs; + unsigned int max_r_vecs; unsigned int num_r_vecs; struct nfp_net_r_vector r_vecs[NFP_NET_MAX_R_VECS]; struct msix_entry irq_entries[NFP_NET_MAX_IRQS]; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index f26c3927746f..4b866fc874b6 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -316,22 +316,24 @@ static int nfp_net_msix_alloc(struct nfp_net *nn, int nr_vecs) int nfp_net_irqs_alloc(struct nfp_net *nn) { int wanted_irqs; + unsigned int n; wanted_irqs = nn->num_r_vecs + NFP_NET_NON_Q_VECTORS; - nn->num_irqs = nfp_net_msix_alloc(nn, wanted_irqs); - if (nn->num_irqs == 0) { + n = nfp_net_msix_alloc(nn, wanted_irqs); + if (n == 0) { nn_err(nn, "Failed to allocate MSI-X IRQs\n"); return 0; } - nn->num_r_vecs = nn->num_irqs - NFP_NET_NON_Q_VECTORS; + nn->max_r_vecs = n - NFP_NET_NON_Q_VECTORS; + nn->num_r_vecs = nn->max_r_vecs; - if (nn->num_irqs < wanted_irqs) + if (n < wanted_irqs) nn_warn(nn, "Unable to allocate %d vectors. Got %d instead\n", - wanted_irqs, nn->num_irqs); + wanted_irqs, n); - return nn->num_irqs; + return n; } /** -- cgit v1.2.3 From cbeaf7aa733a134721cdcda44688e53a6380cd31 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 31 Oct 2016 20:43:22 +0000 Subject: nfp: bring back support for different ring counts We used to always allocate the same number of TX and RX rings so the support for having r_vectors without one of the rings was dropped. That makes us, however, unnecessarily limited to 8 TX rings (8 is the Linux RSS default) most of the time. Also we are about to add channel count configuration via ethtool, so bring that support back. TX rings can now default to num_online_cpus() and RX rings to netif_get_num_default_rss_queues(). Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 118 +++++++++++++-------- 1 file changed, 71 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 4b866fc874b6..97e0bbef13d1 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -483,13 +483,13 @@ static void nfp_net_irqs_assign(struct net_device *netdev) struct nfp_net_r_vector *r_vec; int r; - /* Assumes nn->num_tx_rings == nn->num_rx_rings */ - if (nn->num_tx_rings > nn->num_r_vecs) { - nn_warn(nn, "More rings (%d) than vectors (%d).\n", - nn->num_tx_rings, nn->num_r_vecs); - nn->num_tx_rings = nn->num_r_vecs; - nn->num_rx_rings = nn->num_r_vecs; - } + if (nn->num_rx_rings > nn->num_r_vecs || + nn->num_tx_rings > nn->num_r_vecs) + nn_warn(nn, "More rings (%d,%d) than vectors (%d).\n", + nn->num_rx_rings, nn->num_tx_rings, nn->num_r_vecs); + + nn->num_rx_rings = min(nn->num_r_vecs, nn->num_rx_rings); + nn->num_tx_rings = min(nn->num_r_vecs, nn->num_tx_rings); nn->lsc_handler = nfp_net_irq_lsc; nn->exn_handler = nfp_net_irq_exn; @@ -1491,11 +1491,12 @@ static int nfp_net_poll(struct napi_struct *napi, int budget) { struct nfp_net_r_vector *r_vec = container_of(napi, struct nfp_net_r_vector, napi); - unsigned int pkts_polled; - - nfp_net_tx_complete(r_vec->tx_ring); + unsigned int pkts_polled = 0; - pkts_polled = nfp_net_rx(r_vec->rx_ring, budget); + if (r_vec->tx_ring) + nfp_net_tx_complete(r_vec->tx_ring); + if (r_vec->rx_ring) + pkts_polled = nfp_net_rx(r_vec->rx_ring, budget); if (pkts_polled < budget) { napi_complete_done(napi, pkts_polled); @@ -1743,7 +1744,7 @@ nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings) if (!rings) return; - for (r = 0; r < nn->num_r_vecs; r++) { + for (r = 0; r < nn->num_rx_rings; r++) { nfp_net_rx_ring_bufs_free(nn, &rings[r]); nfp_net_rx_ring_free(&rings[r]); } @@ -1758,11 +1759,19 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx]; int err; - r_vec->tx_ring = &nn->tx_rings[idx]; - nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, idx); + if (idx < nn->num_tx_rings) { + r_vec->tx_ring = &nn->tx_rings[idx]; + nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, idx); + } else { + r_vec->tx_ring = NULL; + } - r_vec->rx_ring = &nn->rx_rings[idx]; - nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, idx); + if (idx < nn->num_rx_rings) { + r_vec->rx_ring = &nn->rx_rings[idx]; + nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, idx); + } else { + r_vec->rx_ring = NULL; + } snprintf(r_vec->name, sizeof(r_vec->name), "%s-rxtx-%d", nn->netdev->name, idx); @@ -1839,13 +1848,13 @@ void nfp_net_coalesce_write_cfg(struct nfp_net *nn) /* copy RX interrupt coalesce parameters */ value = (nn->rx_coalesce_max_frames << 16) | (factor * nn->rx_coalesce_usecs); - for (i = 0; i < nn->num_r_vecs; i++) + for (i = 0; i < nn->num_rx_rings; i++) nn_writel(nn, NFP_NET_CFG_RXR_IRQ_MOD(i), value); /* copy TX interrupt coalesce parameters */ value = (nn->tx_coalesce_max_frames << 16) | (factor * nn->tx_coalesce_usecs); - for (i = 0; i < nn->num_r_vecs; i++) + for (i = 0; i < nn->num_tx_rings; i++) nn_writel(nn, NFP_NET_CFG_TXR_IRQ_MOD(i), value); } @@ -1903,27 +1912,33 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) if (err) nn_err(nn, "Could not disable device: %d\n", err); - for (r = 0; r < nn->num_r_vecs; r++) { + for (r = 0; r < nn->num_rx_rings; r++) nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); + for (r = 0; r < nn->num_tx_rings; r++) nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring); + for (r = 0; r < nn->num_r_vecs; r++) nfp_net_vec_clear_ring_data(nn, r); - } nn->ctrl = new_ctrl; } static void -nfp_net_vec_write_ring_data(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, - unsigned int idx) +nfp_net_rx_ring_hw_cfg_write(struct nfp_net *nn, + struct nfp_net_rx_ring *rx_ring, unsigned int idx) { /* Write the DMA address, size and MSI-X info to the device */ - nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), r_vec->rx_ring->dma); - nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(r_vec->rx_ring->cnt)); - nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), r_vec->irq_idx); + nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), rx_ring->dma); + nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(rx_ring->cnt)); + nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), rx_ring->r_vec->irq_idx); +} - nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(idx), r_vec->tx_ring->dma); - nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), ilog2(r_vec->tx_ring->cnt)); - nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), r_vec->irq_idx); +static void +nfp_net_tx_ring_hw_cfg_write(struct nfp_net *nn, + struct nfp_net_tx_ring *tx_ring, unsigned int idx) +{ + nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(idx), tx_ring->dma); + nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), ilog2(tx_ring->cnt)); + nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), tx_ring->r_vec->irq_idx); } static int __nfp_net_set_config_and_enable(struct nfp_net *nn) @@ -1948,8 +1963,10 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn) update |= NFP_NET_CFG_UPDATE_IRQMOD; } - for (r = 0; r < nn->num_r_vecs; r++) - nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r); + for (r = 0; r < nn->num_tx_rings; r++) + nfp_net_tx_ring_hw_cfg_write(nn, &nn->tx_rings[r], r); + for (r = 0; r < nn->num_rx_rings; r++) + nfp_net_rx_ring_hw_cfg_write(nn, &nn->rx_rings[r], r); nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ? 0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1); @@ -1975,7 +1992,7 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn) nn->ctrl = new_ctrl; - for (r = 0; r < nn->num_r_vecs; r++) + for (r = 0; r < nn->num_rx_rings; r++) nfp_net_rx_ring_fill_freelist(nn->r_vecs[r].rx_ring); /* Since reconfiguration requests while NFP is down are ignored we @@ -2067,20 +2084,22 @@ static int nfp_net_netdev_open(struct net_device *netdev) for (r = 0; r < nn->num_r_vecs; r++) { err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r); if (err) - goto err_free_prev_vecs; - + goto err_cleanup_vec_p; + } + for (r = 0; r < nn->num_tx_rings; r++) { err = nfp_net_tx_ring_alloc(nn->r_vecs[r].tx_ring, nn->txd_cnt); if (err) - goto err_cleanup_vec_p; - + goto err_free_tx_ring_p; + } + for (r = 0; r < nn->num_rx_rings; r++) { err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring, nn->fl_bufsz, nn->rxd_cnt); if (err) - goto err_free_tx_ring_p; + goto err_flush_free_rx_ring_p; err = nfp_net_rx_ring_bufs_alloc(nn, nn->r_vecs[r].rx_ring); if (err) - goto err_flush_rx_ring_p; + goto err_free_rx_ring_p; } err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings); @@ -2113,17 +2132,21 @@ static int nfp_net_netdev_open(struct net_device *netdev) return 0; err_free_rings: - r = nn->num_r_vecs; -err_free_prev_vecs: + r = nn->num_rx_rings; +err_flush_free_rx_ring_p: while (r--) { nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); -err_flush_rx_ring_p: +err_free_rx_ring_p: nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); + } + r = nn->num_tx_rings; err_free_tx_ring_p: + while (r--) nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); + r = nn->num_r_vecs; err_cleanup_vec_p: + while (r--) nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); - } kfree(nn->tx_rings); err_free_rx_rings: kfree(nn->rx_rings); @@ -2162,12 +2185,14 @@ static void nfp_net_close_free_all(struct nfp_net *nn) { unsigned int r; - for (r = 0; r < nn->num_r_vecs; r++) { + for (r = 0; r < nn->num_rx_rings; r++) { nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); + } + for (r = 0; r < nn->num_tx_rings; r++) nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); + for (r = 0; r < nn->num_r_vecs; r++) nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); - } kfree(nn->rx_rings); kfree(nn->tx_rings); @@ -2686,7 +2711,6 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, { struct net_device *netdev; struct nfp_net *nn; - int nqs; netdev = alloc_etherdev_mqs(sizeof(struct nfp_net), max_tx_rings, max_rx_rings); @@ -2702,9 +2726,9 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, nn->max_tx_rings = max_tx_rings; nn->max_rx_rings = max_rx_rings; - nqs = netif_get_num_default_rss_queues(); - nn->num_tx_rings = min_t(int, nqs, max_tx_rings); - nn->num_rx_rings = min_t(int, nqs, max_rx_rings); + nn->num_tx_rings = min_t(unsigned int, max_tx_rings, num_online_cpus()); + nn->num_rx_rings = min_t(unsigned int, max_rx_rings, + netif_get_num_default_rss_queues()); nn->num_r_vecs = max(nn->num_tx_rings, nn->num_rx_rings); nn->num_r_vecs = min_t(unsigned int, nn->num_r_vecs, num_online_cpus()); -- cgit v1.2.3 From 03ea4afa67566a3c4e83c0fde8bf0c48f16ac1a3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 1 Nov 2016 07:40:04 -0600 Subject: umem: use op_is_sync to check for synchronous requests Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/block/umem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/umem.c b/drivers/block/umem.c index be90e15854ed..46f4c719fed9 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -535,7 +535,7 @@ static blk_qc_t mm_make_request(struct request_queue *q, struct bio *bio) *card->biotail = bio; bio->bi_next = NULL; card->biotail = &bio->bi_next; - if (bio->bi_opf & REQ_SYNC || !mm_check_plugged(card)) + if (op_is_sync(bio->bi_opf) || !mm_check_plugged(card)) activate(card); spin_unlock_irq(&card->lock); -- cgit v1.2.3 From 83b5df67c50995ed93b2b7adac3f002ad8bb6069 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 1 Nov 2016 07:40:05 -0600 Subject: bcache: use op_is_sync to check for synchronous requests (and remove one layer of masking for the op_is_write call next to it). Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/md/bcache/request.c | 4 ++-- drivers/md/bcache/writeback.h | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 40ffe5e424b3..e8a2b693c928 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -404,8 +404,8 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio) if (!congested && mode == CACHE_MODE_WRITEBACK && - op_is_write(bio_op(bio)) && - (bio->bi_opf & REQ_SYNC)) + op_is_write(bio->bi_opf) && + op_is_sync(bio->bi_opf)) goto rescale; spin_lock(&dc->io_lock); diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h index 301eaf565167..629bd1a502fd 100644 --- a/drivers/md/bcache/writeback.h +++ b/drivers/md/bcache/writeback.h @@ -57,8 +57,7 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio, if (would_skip) return false; - return bio->bi_opf & REQ_SYNC || - in_use <= CUTOFF_WRITEBACK; + return op_is_sync(bio->bi_opf) || in_use <= CUTOFF_WRITEBACK; } static inline void bch_writeback_queue(struct cached_dev *dc) -- cgit v1.2.3 From a2b809672ee6fcb4d5756ea815725b3dbaea654e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 1 Nov 2016 07:40:09 -0600 Subject: block: replace REQ_NOIDLE with REQ_IDLE Noidle should be the default for writes as seen by all the compounds definitions in fs.h using it. In fact only direct I/O really should be using NODILE, so turn the whole flag around to get the defaults right, which will make our life much easier especially onces the WRITE_* defines go away. This assumes all the existing "raw" users of REQ_SYNC for writes want noidle behavior, which seems to be spot on from a quick audit. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- Documentation/block/cfq-iosched.txt | 32 ++++++++++++++++---------------- block/cfq-iosched.c | 11 ++++++++--- drivers/block/drbd/drbd_actlog.c | 2 +- include/linux/blk_types.h | 4 ++-- include/linux/fs.h | 10 +++++----- include/trace/events/f2fs.h | 2 +- 6 files changed, 33 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/Documentation/block/cfq-iosched.txt b/Documentation/block/cfq-iosched.txt index 1e4f835a659d..895bd3813115 100644 --- a/Documentation/block/cfq-iosched.txt +++ b/Documentation/block/cfq-iosched.txt @@ -240,11 +240,11 @@ All cfq queues doing synchronous sequential IO go on to sync-idle tree. On this tree we idle on each queue individually. All synchronous non-sequential queues go on sync-noidle tree. Also any -request which are marked with REQ_NOIDLE go on this service tree. On this -tree we do not idle on individual queues instead idle on the whole group -of queues or the tree. So if there are 4 queues waiting for IO to dispatch -we will idle only once last queue has dispatched the IO and there is -no more IO on this service tree. +synchronous write request which is not marked with REQ_IDLE goes on this +service tree. On this tree we do not idle on individual queues instead idle +on the whole group of queues or the tree. So if there are 4 queues waiting +for IO to dispatch we will idle only once last queue has dispatched the IO +and there is no more IO on this service tree. All async writes go on async service tree. There is no idling on async queues. @@ -257,17 +257,17 @@ tree idling provides isolation with buffered write queues on async tree. FAQ === -Q1. Why to idle at all on queues marked with REQ_NOIDLE. +Q1. Why to idle at all on queues not marked with REQ_IDLE. -A1. We only do tree idle (all queues on sync-noidle tree) on queues marked - with REQ_NOIDLE. This helps in providing isolation with all the sync-idle +A1. We only do tree idle (all queues on sync-noidle tree) on queues not marked + with REQ_IDLE. This helps in providing isolation with all the sync-idle queues. Otherwise in presence of many sequential readers, other synchronous IO might not get fair share of disk. For example, if there are 10 sequential readers doing IO and they get - 100ms each. If a REQ_NOIDLE request comes in, it will be scheduled - roughly after 1 second. If after completion of REQ_NOIDLE request we - do not idle, and after a couple of milli seconds a another REQ_NOIDLE + 100ms each. If a !REQ_IDLE request comes in, it will be scheduled + roughly after 1 second. If after completion of !REQ_IDLE request we + do not idle, and after a couple of milli seconds a another !REQ_IDLE request comes in, again it will be scheduled after 1second. Repeat it and notice how a workload can lose its disk share and suffer due to multiple sequential readers. @@ -276,16 +276,16 @@ A1. We only do tree idle (all queues on sync-noidle tree) on queues marked context of fsync, and later some journaling data is written. Journaling data comes in only after fsync has finished its IO (atleast for ext4 that seemed to be the case). Now if one decides not to idle on fsync - thread due to REQ_NOIDLE, then next journaling write will not get + thread due to !REQ_IDLE, then next journaling write will not get scheduled for another second. A process doing small fsync, will suffer badly in presence of multiple sequential readers. - Hence doing tree idling on threads using REQ_NOIDLE flag on requests + Hence doing tree idling on threads using !REQ_IDLE flag on requests provides isolation from multiple sequential readers and at the same time we do not idle on individual threads. -Q2. When to specify REQ_NOIDLE -A2. I would think whenever one is doing synchronous write and not expecting +Q2. When to specify REQ_IDLE +A2. I would think whenever one is doing synchronous write and expecting more writes to be dispatched from same context soon, should be able - to specify REQ_NOIDLE on writes and that probably should work well for + to specify REQ_IDLE on writes and that probably should work well for most of the cases. diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index f28db97c3fe0..dcbed8c9c82c 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3914,6 +3914,12 @@ cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_queue *cfqq, cfqq->seek_history |= (sdist > CFQQ_SEEK_THR); } +static inline bool req_noidle(struct request *req) +{ + return req_op(req) == REQ_OP_WRITE && + (req->cmd_flags & (REQ_SYNC | REQ_IDLE)) == REQ_SYNC; +} + /* * Disable idle window if the process thinks too long or seeks so much that * it doesn't matter @@ -3935,7 +3941,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, if (cfqq->queued[0] + cfqq->queued[1] >= 4) cfq_mark_cfqq_deep(cfqq); - if (cfqq->next_rq && (cfqq->next_rq->cmd_flags & REQ_NOIDLE)) + if (cfqq->next_rq && req_noidle(cfqq->next_rq)) enable_idle = 0; else if (!atomic_read(&cic->icq.ioc->active_ref) || !cfqd->cfq_slice_idle || @@ -4220,8 +4226,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) const int sync = rq_is_sync(rq); u64 now = ktime_get_ns(); - cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d", - !!(rq->cmd_flags & REQ_NOIDLE)); + cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d", req_noidle(rq)); cfq_update_hw_tag(cfqd); diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 2d3d50ab74bf..8d7bcfa49c12 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -148,7 +148,7 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, if ((op == REQ_OP_WRITE) && !test_bit(MD_NO_FUA, &device->flags)) op_flags |= REQ_FUA | REQ_PREFLUSH; - op_flags |= REQ_SYNC | REQ_NOIDLE; + op_flags |= REQ_SYNC; bio = bio_alloc_drbd(GFP_NOIO); bio->bi_bdev = bdev->md_bdev; diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 107d23d18096..63b750a3b165 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -175,7 +175,7 @@ enum req_flag_bits { __REQ_META, /* metadata io request */ __REQ_PRIO, /* boost priority in cfq */ __REQ_NOMERGE, /* don't touch this for merging */ - __REQ_NOIDLE, /* don't anticipate more IO after this one */ + __REQ_IDLE, /* anticipate more IO after this one */ __REQ_INTEGRITY, /* I/O includes block integrity payload */ __REQ_FUA, /* forced unit access */ __REQ_PREFLUSH, /* request for cache flush */ @@ -190,7 +190,7 @@ enum req_flag_bits { #define REQ_META (1ULL << __REQ_META) #define REQ_PRIO (1ULL << __REQ_PRIO) #define REQ_NOMERGE (1ULL << __REQ_NOMERGE) -#define REQ_NOIDLE (1ULL << __REQ_NOIDLE) +#define REQ_IDLE (1ULL << __REQ_IDLE) #define REQ_INTEGRITY (1ULL << __REQ_INTEGRITY) #define REQ_FUA (1ULL << __REQ_FUA) #define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH) diff --git a/include/linux/fs.h b/include/linux/fs.h index ccedccb28ec8..46a74209917f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -197,11 +197,11 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define WRITE REQ_OP_WRITE #define READ_SYNC 0 -#define WRITE_SYNC (REQ_SYNC | REQ_NOIDLE) -#define WRITE_ODIRECT REQ_SYNC -#define WRITE_FLUSH (REQ_NOIDLE | REQ_PREFLUSH) -#define WRITE_FUA (REQ_NOIDLE | REQ_FUA) -#define WRITE_FLUSH_FUA (REQ_NOIDLE | REQ_PREFLUSH | REQ_FUA) +#define WRITE_SYNC REQ_SYNC +#define WRITE_ODIRECT (REQ_SYNC | REQ_IDLE) +#define WRITE_FLUSH REQ_PREFLUSH +#define WRITE_FUA REQ_FUA +#define WRITE_FLUSH_FUA (REQ_PREFLUSH | REQ_FUA) /* * Attribute flags. These should be or-ed together to figure out what diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 903a09165bb1..a9d34424450d 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -32,7 +32,7 @@ TRACE_DEFINE_ENUM(LFS); TRACE_DEFINE_ENUM(SSR); TRACE_DEFINE_ENUM(__REQ_RAHEAD); TRACE_DEFINE_ENUM(__REQ_SYNC); -TRACE_DEFINE_ENUM(__REQ_NOIDLE); +TRACE_DEFINE_ENUM(__REQ_IDLE); TRACE_DEFINE_ENUM(__REQ_PREFLUSH); TRACE_DEFINE_ENUM(__REQ_FUA); TRACE_DEFINE_ENUM(__REQ_PRIO); -- cgit v1.2.3 From 70fd76140a6cb63262bd47b68d57b42e889c10ee Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 1 Nov 2016 07:40:10 -0600 Subject: block,fs: use REQ_* flags directly Remove the WRITE_* and READ_SYNC wrappers, and just use the flags directly. Where applicable this also drops usage of the bio_set_op_attrs wrapper. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-flush.c | 4 ++-- drivers/block/drbd/drbd_receiver.c | 2 +- drivers/block/xen-blkback/blkback.c | 10 ++++---- drivers/md/bcache/btree.c | 4 ++-- drivers/md/bcache/debug.c | 4 ++-- drivers/md/bcache/request.c | 2 +- drivers/md/bcache/super.c | 4 ++-- drivers/md/dm-bufio.c | 2 +- drivers/md/dm-log.c | 2 +- drivers/md/dm-raid1.c | 4 ++-- drivers/md/dm-snap-persistent.c | 4 ++-- drivers/md/dm.c | 2 +- drivers/md/md.c | 4 ++-- drivers/md/raid5-cache.c | 4 ++-- drivers/md/raid5.c | 2 +- drivers/nvme/target/io-cmd.c | 4 ++-- drivers/target/target_core_iblock.c | 8 +++---- fs/btrfs/disk-io.c | 6 ++--- fs/btrfs/extent_io.c | 16 ++++++------- fs/btrfs/inode.c | 6 ++--- fs/btrfs/scrub.c | 2 +- fs/btrfs/volumes.c | 2 +- fs/btrfs/volumes.h | 2 +- fs/buffer.c | 8 +++---- fs/direct-io.c | 2 +- fs/ext4/mmp.c | 6 ++--- fs/ext4/page-io.c | 2 +- fs/ext4/super.c | 2 +- fs/f2fs/checkpoint.c | 4 ++-- fs/f2fs/data.c | 16 ++++++------- fs/f2fs/gc.c | 6 ++--- fs/f2fs/inline.c | 2 +- fs/f2fs/node.c | 4 ++-- fs/f2fs/segment.c | 8 +++---- fs/f2fs/super.c | 2 +- fs/gfs2/log.c | 4 ++-- fs/gfs2/meta_io.c | 6 ++--- fs/gfs2/ops_fstype.c | 2 +- fs/hfsplus/super.c | 4 ++-- fs/jbd2/checkpoint.c | 2 +- fs/jbd2/commit.c | 9 +++---- fs/jbd2/journal.c | 15 ++++++------ fs/jbd2/revoke.c | 2 +- fs/jfs/jfs_logmgr.c | 4 ++-- fs/mpage.c | 6 ++--- fs/nilfs2/super.c | 2 +- fs/ocfs2/cluster/heartbeat.c | 2 +- fs/reiserfs/journal.c | 6 +++-- fs/xfs/xfs_aops.c | 11 +++++---- fs/xfs/xfs_buf.c | 2 +- include/linux/fs.h | 47 ------------------------------------- include/trace/events/f2fs.h | 10 ++++---- kernel/power/swap.c | 19 +++++++-------- 53 files changed, 133 insertions(+), 182 deletions(-) (limited to 'drivers') diff --git a/block/blk-flush.c b/block/blk-flush.c index 95f1d4d357df..d35beca18481 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -330,7 +330,7 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq) } flush_rq->cmd_type = REQ_TYPE_FS; - flush_rq->cmd_flags = REQ_OP_FLUSH | WRITE_FLUSH; + flush_rq->cmd_flags = REQ_OP_FLUSH | REQ_PREFLUSH; flush_rq->rq_flags |= RQF_FLUSH_SEQ; flush_rq->rq_disk = first_rq->rq_disk; flush_rq->end_io = flush_end_io; @@ -486,7 +486,7 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, bio = bio_alloc(gfp_mask, 0); bio->bi_bdev = bdev; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; ret = submit_bio_wait(bio); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 942384f34e22..a89538cb3eaa 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1266,7 +1266,7 @@ static void submit_one_flush(struct drbd_device *device, struct issue_flush_cont bio->bi_bdev = device->ldev->backing_bdev; bio->bi_private = octx; bio->bi_end_io = one_flush_endio; - bio_set_op_attrs(bio, REQ_OP_FLUSH, WRITE_FLUSH); + bio->bi_opf = REQ_OP_FLUSH | REQ_PREFLUSH; device->flush_jif = jiffies; set_bit(FLUSH_PENDING, &device->flags); diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 4a80ee752597..726c32e35db9 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -1253,14 +1253,14 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, case BLKIF_OP_WRITE: ring->st_wr_req++; operation = REQ_OP_WRITE; - operation_flags = WRITE_ODIRECT; + operation_flags = REQ_SYNC | REQ_IDLE; break; case BLKIF_OP_WRITE_BARRIER: drain = true; case BLKIF_OP_FLUSH_DISKCACHE: ring->st_f_req++; operation = REQ_OP_WRITE; - operation_flags = WRITE_FLUSH; + operation_flags = REQ_PREFLUSH; break; default: operation = 0; /* make gcc happy */ @@ -1272,7 +1272,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, nseg = req->operation == BLKIF_OP_INDIRECT ? req->u.indirect.nr_segments : req->u.rw.nr_segments; - if (unlikely(nseg == 0 && operation_flags != WRITE_FLUSH) || + if (unlikely(nseg == 0 && operation_flags != REQ_PREFLUSH) || unlikely((req->operation != BLKIF_OP_INDIRECT) && (nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) || unlikely((req->operation == BLKIF_OP_INDIRECT) && @@ -1334,7 +1334,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, } /* Wait on all outstanding I/O's and once that has been completed - * issue the WRITE_FLUSH. + * issue the flush. */ if (drain) xen_blk_drain_io(pending_req->ring); @@ -1380,7 +1380,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, /* This will be hit if the operation was a flush or discard. */ if (!bio) { - BUG_ON(operation_flags != WRITE_FLUSH); + BUG_ON(operation_flags != REQ_PREFLUSH); bio = bio_alloc(GFP_KERNEL, 0); if (unlikely(bio == NULL)) diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 81d3db40cd7b..6fdd8e252760 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -297,7 +297,7 @@ static void bch_btree_node_read(struct btree *b) bio->bi_iter.bi_size = KEY_SIZE(&b->key) << 9; bio->bi_end_io = btree_node_read_endio; bio->bi_private = &cl; - bio_set_op_attrs(bio, REQ_OP_READ, REQ_META|READ_SYNC); + bio->bi_opf = REQ_OP_READ | REQ_META; bch_bio_map(bio, b->keys.set[0].data); @@ -393,7 +393,7 @@ static void do_btree_node_write(struct btree *b) b->bio->bi_end_io = btree_node_write_endio; b->bio->bi_private = cl; b->bio->bi_iter.bi_size = roundup(set_bytes(i), block_bytes(b->c)); - bio_set_op_attrs(b->bio, REQ_OP_WRITE, REQ_META|WRITE_SYNC|REQ_FUA); + b->bio->bi_opf = REQ_OP_WRITE | REQ_META | REQ_FUA; bch_bio_map(b->bio, i); /* diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c index 333a1e5f6ae6..1c9130ae0073 100644 --- a/drivers/md/bcache/debug.c +++ b/drivers/md/bcache/debug.c @@ -52,7 +52,7 @@ void bch_btree_verify(struct btree *b) bio->bi_bdev = PTR_CACHE(b->c, &b->key, 0)->bdev; bio->bi_iter.bi_sector = PTR_OFFSET(&b->key, 0); bio->bi_iter.bi_size = KEY_SIZE(&v->key) << 9; - bio_set_op_attrs(bio, REQ_OP_READ, REQ_META|READ_SYNC); + bio->bi_opf = REQ_OP_READ | REQ_META; bch_bio_map(bio, sorted); submit_bio_wait(bio); @@ -113,7 +113,7 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio) check = bio_clone(bio, GFP_NOIO); if (!check) return; - bio_set_op_attrs(check, REQ_OP_READ, READ_SYNC); + check->bi_opf = REQ_OP_READ; if (bio_alloc_pages(check, GFP_NOIO)) goto out_put; diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index e8a2b693c928..0d99b5f4b3e6 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -923,7 +923,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) flush->bi_bdev = bio->bi_bdev; flush->bi_end_io = request_endio; flush->bi_private = cl; - bio_set_op_attrs(flush, REQ_OP_WRITE, WRITE_FLUSH); + flush->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; closure_bio_submit(flush, cl); } diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 849ad441cd76..988edf928466 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -381,7 +381,7 @@ static char *uuid_read(struct cache_set *c, struct jset *j, struct closure *cl) return "bad uuid pointer"; bkey_copy(&c->uuid_bucket, k); - uuid_io(c, REQ_OP_READ, READ_SYNC, k, cl); + uuid_io(c, REQ_OP_READ, 0, k, cl); if (j->version < BCACHE_JSET_VERSION_UUIDv1) { struct uuid_entry_v0 *u0 = (void *) c->uuids; @@ -600,7 +600,7 @@ static void prio_read(struct cache *ca, uint64_t bucket) ca->prio_last_buckets[bucket_nr] = bucket; bucket_nr++; - prio_io(ca, bucket, REQ_OP_READ, READ_SYNC); + prio_io(ca, bucket, REQ_OP_READ, 0); if (p->csum != bch_crc64(&p->magic, bucket_bytes(ca) - 8)) pr_warn("bad csum reading priorities"); diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 125aedc3875f..b3ba142e59a4 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1316,7 +1316,7 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c) { struct dm_io_request io_req = { .bi_op = REQ_OP_WRITE, - .bi_op_flags = WRITE_FLUSH, + .bi_op_flags = REQ_PREFLUSH, .mem.type = DM_IO_KMEM, .mem.ptr.addr = NULL, .client = c->dm_io, diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 07fc1ad42ec5..33e71ea6cc14 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -308,7 +308,7 @@ static int flush_header(struct log_c *lc) }; lc->io_req.bi_op = REQ_OP_WRITE; - lc->io_req.bi_op_flags = WRITE_FLUSH; + lc->io_req.bi_op_flags = REQ_PREFLUSH; return dm_io(&lc->io_req, 1, &null_location, NULL); } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index bdf1606f67bc..1a176d7c8b90 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -261,7 +261,7 @@ static int mirror_flush(struct dm_target *ti) struct mirror *m; struct dm_io_request io_req = { .bi_op = REQ_OP_WRITE, - .bi_op_flags = WRITE_FLUSH, + .bi_op_flags = REQ_PREFLUSH, .mem.type = DM_IO_KMEM, .mem.ptr.addr = NULL, .client = ms->io_client, @@ -657,7 +657,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio) struct mirror *m; struct dm_io_request io_req = { .bi_op = REQ_OP_WRITE, - .bi_op_flags = bio->bi_opf & WRITE_FLUSH_FUA, + .bi_op_flags = bio->bi_opf & (REQ_FUA | REQ_PREFLUSH), .mem.type = DM_IO_BIO, .mem.ptr.bio = bio, .notify.fn = write_callback, diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index b8cf956b577b..b93476c3ba3f 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -741,7 +741,7 @@ static void persistent_commit_exception(struct dm_exception_store *store, /* * Commit exceptions to disk. */ - if (ps->valid && area_io(ps, REQ_OP_WRITE, WRITE_FLUSH_FUA)) + if (ps->valid && area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA)) ps->valid = 0; /* @@ -818,7 +818,7 @@ static int persistent_commit_merge(struct dm_exception_store *store, for (i = 0; i < nr_merged; i++) clear_exception(ps, ps->current_committed - 1 - i); - r = area_io(ps, REQ_OP_WRITE, WRITE_FLUSH_FUA); + r = area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA); if (r < 0) return r; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 147af9536d0c..b2abfa41af3e 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1527,7 +1527,7 @@ static struct mapped_device *alloc_dev(int minor) bio_init(&md->flush_bio); md->flush_bio.bi_bdev = md->bdev; - bio_set_op_attrs(&md->flush_bio, REQ_OP_WRITE, WRITE_FLUSH); + md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; dm_stats_init(&md->stats); diff --git a/drivers/md/md.c b/drivers/md/md.c index eac84d8ff724..b69ec7da4bae 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -394,7 +394,7 @@ static void submit_flushes(struct work_struct *ws) bi->bi_end_io = md_end_flush; bi->bi_private = rdev; bi->bi_bdev = rdev->bdev; - bio_set_op_attrs(bi, REQ_OP_WRITE, WRITE_FLUSH); + bi->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; atomic_inc(&mddev->flush_pending); submit_bio(bi); rcu_read_lock(); @@ -743,7 +743,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev, bio_add_page(bio, page, size, 0); bio->bi_private = rdev; bio->bi_end_io = super_written; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH_FUA); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA; atomic_inc(&mddev->pending_writes); submit_bio(bio); diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 1b1ab4a1d132..28d015c6fffe 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -685,7 +685,7 @@ void r5l_flush_stripe_to_raid(struct r5l_log *log) bio_reset(&log->flush_bio); log->flush_bio.bi_bdev = log->rdev->bdev; log->flush_bio.bi_end_io = r5l_log_flush_endio; - bio_set_op_attrs(&log->flush_bio, REQ_OP_WRITE, WRITE_FLUSH); + log->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; submit_bio(&log->flush_bio); } @@ -1053,7 +1053,7 @@ static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos, mb->checksum = cpu_to_le32(crc); if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, REQ_OP_WRITE, - WRITE_FUA, false)) { + REQ_FUA, false)) { __free_page(page); return -EIO; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 92ac251e91e6..70acdd379e44 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -913,7 +913,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) { op = REQ_OP_WRITE; if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags)) - op_flags = WRITE_FUA; + op_flags = REQ_FUA; if (test_bit(R5_Discard, &sh->dev[i].flags)) op = REQ_OP_DISCARD; } else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags)) diff --git a/drivers/nvme/target/io-cmd.c b/drivers/nvme/target/io-cmd.c index 4a96c2049b7b..c2784cfc5e29 100644 --- a/drivers/nvme/target/io-cmd.c +++ b/drivers/nvme/target/io-cmd.c @@ -58,7 +58,7 @@ static void nvmet_execute_rw(struct nvmet_req *req) if (req->cmd->rw.opcode == nvme_cmd_write) { op = REQ_OP_WRITE; - op_flags = WRITE_ODIRECT; + op_flags = REQ_SYNC | REQ_IDLE; if (req->cmd->rw.control & cpu_to_le16(NVME_RW_FUA)) op_flags |= REQ_FUA; } else { @@ -109,7 +109,7 @@ static void nvmet_execute_flush(struct nvmet_req *req) bio->bi_bdev = req->ns->bdev; bio->bi_private = req; bio->bi_end_io = nvmet_bio_done; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; submit_bio(bio); } diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 372d744315f3..d316ed537d59 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -388,7 +388,7 @@ iblock_execute_sync_cache(struct se_cmd *cmd) bio = bio_alloc(GFP_KERNEL, 0); bio->bi_end_io = iblock_end_io_flush; bio->bi_bdev = ib_dev->ibd_bd; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; if (!immed) bio->bi_private = cmd; submit_bio(bio); @@ -686,15 +686,15 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, struct iblock_dev *ib_dev = IBLOCK_DEV(dev); struct request_queue *q = bdev_get_queue(ib_dev->ibd_bd); /* - * Force writethrough using WRITE_FUA if a volatile write cache + * Force writethrough using REQ_FUA if a volatile write cache * is not enabled, or if initiator set the Force Unit Access bit. */ op = REQ_OP_WRITE; if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { if (cmd->se_cmd_flags & SCF_FUA) - op_flags = WRITE_FUA; + op_flags = REQ_FUA; else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) - op_flags = WRITE_FUA; + op_flags = REQ_FUA; } } else { op = REQ_OP_READ; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c8454a8e35f2..fe10afd51e02 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3485,9 +3485,9 @@ static int write_dev_supers(struct btrfs_device *device, * to go down lazy. */ if (i == 0) - ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_FUA, bh); + ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_FUA, bh); else - ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh); + ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); if (ret) errors++; } @@ -3551,7 +3551,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait) bio->bi_end_io = btrfs_end_empty_barrier; bio->bi_bdev = device->bdev; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; init_completion(&device->flush_wait); bio->bi_private = &device->flush_wait; device->flush_bio = bio; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 66a755150056..ff87bff7bdb6 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -127,7 +127,7 @@ struct extent_page_data { */ unsigned int extent_locked:1; - /* tells the submit_bio code to use a WRITE_SYNC */ + /* tells the submit_bio code to use REQ_SYNC */ unsigned int sync_io:1; }; @@ -2047,7 +2047,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical, return -EIO; } bio->bi_bdev = dev->bdev; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC); + bio->bi_opf = REQ_OP_WRITE | REQ_SYNC; bio_add_page(bio, page, length, pg_offset); if (btrfsic_submit_bio_wait(bio)) { @@ -2388,7 +2388,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, struct inode *inode = page->mapping->host; struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; struct bio *bio; - int read_mode; + int read_mode = 0; int ret; BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE); @@ -2404,9 +2404,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, } if (failed_bio->bi_vcnt > 1) - read_mode = READ_SYNC | REQ_FAILFAST_DEV; - else - read_mode = READ_SYNC; + read_mode |= REQ_FAILFAST_DEV; phy_offset >>= inode->i_sb->s_blocksize_bits; bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page, @@ -3484,7 +3482,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, unsigned long nr_written = 0; if (wbc->sync_mode == WB_SYNC_ALL) - write_flags = WRITE_SYNC; + write_flags = REQ_SYNC; trace___extent_writepage(page, inode, wbc); @@ -3729,7 +3727,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, unsigned long i, num_pages; unsigned long bio_flags = 0; unsigned long start, end; - int write_flags = (epd->sync_io ? WRITE_SYNC : 0) | REQ_META; + int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META; int ret = 0; clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags); @@ -4076,7 +4074,7 @@ static void flush_epd_write_bio(struct extent_page_data *epd) int ret; bio_set_op_attrs(epd->bio, REQ_OP_WRITE, - epd->sync_io ? WRITE_SYNC : 0); + epd->sync_io ? REQ_SYNC : 0); ret = submit_one_bio(epd->bio, 0, epd->bio_flags); BUG_ON(ret < 0); /* -ENOMEM */ diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9a377079af26..c8eb82a416b3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7917,7 +7917,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio, struct io_failure_record *failrec; struct bio *bio; int isector; - int read_mode; + int read_mode = 0; int ret; BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE); @@ -7936,9 +7936,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio, if ((failed_bio->bi_vcnt > 1) || (failed_bio->bi_io_vec->bv_len > BTRFS_I(inode)->root->sectorsize)) - read_mode = READ_SYNC | REQ_FAILFAST_DEV; - else - read_mode = READ_SYNC; + read_mode |= REQ_FAILFAST_DEV; isector = start - btrfs_io_bio(failed_bio)->logical; isector >>= inode->i_sb->s_blocksize_bits; diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index fffb9ab8526e..ff3078234d94 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -4440,7 +4440,7 @@ static int write_page_nocow(struct scrub_ctx *sctx, bio->bi_iter.bi_size = 0; bio->bi_iter.bi_sector = physical_for_dev_replace >> 9; bio->bi_bdev = dev->bdev; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC); + bio->bi_opf = REQ_OP_WRITE | REQ_SYNC; ret = bio_add_page(bio, page, PAGE_SIZE, 0); if (ret != PAGE_SIZE) { leave_with_eio: diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index deda46cf1292..0d7d635d8bfb 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6023,7 +6023,7 @@ static void btrfs_end_bio(struct bio *bio) else btrfs_dev_stat_inc(dev, BTRFS_DEV_STAT_READ_ERRS); - if ((bio->bi_opf & WRITE_FLUSH) == WRITE_FLUSH) + if (bio->bi_opf & REQ_PREFLUSH) btrfs_dev_stat_inc(dev, BTRFS_DEV_STAT_FLUSH_ERRS); btrfs_dev_stat_print_on_error(dev); diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 09ed29c67848..f137ffe6654c 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -62,7 +62,7 @@ struct btrfs_device { int running_pending; /* regular prio bios */ struct btrfs_pending_bios pending_bios; - /* WRITE_SYNC bios */ + /* sync bios */ struct btrfs_pending_bios pending_sync_bios; struct block_device *bdev; diff --git a/fs/buffer.c b/fs/buffer.c index a29335867e30..bc7c2bb30a9b 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -753,7 +753,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) * still in flight on potentially older * contents. */ - write_dirty_buffer(bh, WRITE_SYNC); + write_dirty_buffer(bh, REQ_SYNC); /* * Kick off IO for the previous mapping. Note @@ -1684,7 +1684,7 @@ static struct buffer_head *create_page_buffers(struct page *page, struct inode * * prevents this contention from occurring. * * If block_write_full_page() is called with wbc->sync_mode == - * WB_SYNC_ALL, the writes are posted using WRITE_SYNC; this + * WB_SYNC_ALL, the writes are posted using REQ_SYNC; this * causes the writes to be flagged as synchronous writes. */ int __block_write_full_page(struct inode *inode, struct page *page, @@ -1697,7 +1697,7 @@ int __block_write_full_page(struct inode *inode, struct page *page, struct buffer_head *bh, *head; unsigned int blocksize, bbits; int nr_underway = 0; - int write_flags = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0); + int write_flags = (wbc->sync_mode == WB_SYNC_ALL ? REQ_SYNC : 0); head = create_page_buffers(page, inode, (1 << BH_Dirty)|(1 << BH_Uptodate)); @@ -3210,7 +3210,7 @@ EXPORT_SYMBOL(__sync_dirty_buffer); int sync_dirty_buffer(struct buffer_head *bh) { - return __sync_dirty_buffer(bh, WRITE_SYNC); + return __sync_dirty_buffer(bh, REQ_SYNC); } EXPORT_SYMBOL(sync_dirty_buffer); diff --git a/fs/direct-io.c b/fs/direct-io.c index fb9aa16a7727..a5138c564019 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -1209,7 +1209,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, dio->inode = inode; if (iov_iter_rw(iter) == WRITE) { dio->op = REQ_OP_WRITE; - dio->op_flags = WRITE_ODIRECT; + dio->op_flags = REQ_SYNC | REQ_IDLE; } else { dio->op = REQ_OP_READ; } diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index d89754ef1aab..eb9835638680 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c @@ -35,7 +35,7 @@ static void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp) } /* - * Write the MMP block using WRITE_SYNC to try to get the block on-disk + * Write the MMP block using REQ_SYNC to try to get the block on-disk * faster. */ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) @@ -52,7 +52,7 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) lock_buffer(bh); bh->b_end_io = end_buffer_write_sync; get_bh(bh); - submit_bh(REQ_OP_WRITE, WRITE_SYNC | REQ_META | REQ_PRIO, bh); + submit_bh(REQ_OP_WRITE, REQ_SYNC | REQ_META | REQ_PRIO, bh); wait_on_buffer(bh); sb_end_write(sb); if (unlikely(!buffer_uptodate(bh))) @@ -88,7 +88,7 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, get_bh(*bh); lock_buffer(*bh); (*bh)->b_end_io = end_buffer_read_sync; - submit_bh(REQ_OP_READ, READ_SYNC | REQ_META | REQ_PRIO, *bh); + submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, *bh); wait_on_buffer(*bh); if (!buffer_uptodate(*bh)) { ret = -EIO; diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 0094923e5ebf..e0b3b54cdef3 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -340,7 +340,7 @@ void ext4_io_submit(struct ext4_io_submit *io) if (bio) { int io_op_flags = io->io_wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC : 0; + REQ_SYNC : 0; bio_set_op_attrs(io->io_bio, REQ_OP_WRITE, io_op_flags); submit_bio(io->io_bio); } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 6db81fbcbaa6..f31eb286af90 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4553,7 +4553,7 @@ static int ext4_commit_super(struct super_block *sb, int sync) unlock_buffer(sbh); if (sync) { error = __sync_dirty_buffer(sbh, - test_opt(sb, BARRIER) ? WRITE_FUA : WRITE_SYNC); + test_opt(sb, BARRIER) ? REQ_FUA : REQ_SYNC); if (error) return error; diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 7e9b504bd8b2..d935c06a84f0 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -65,7 +65,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index, .sbi = sbi, .type = META, .op = REQ_OP_READ, - .op_flags = READ_SYNC | REQ_META | REQ_PRIO, + .op_flags = REQ_META | REQ_PRIO, .old_blkaddr = index, .new_blkaddr = index, .encrypted_page = NULL, @@ -160,7 +160,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, .sbi = sbi, .type = META, .op = REQ_OP_READ, - .op_flags = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : REQ_RAHEAD, + .op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD, .encrypted_page = NULL, }; struct blk_plug plug; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 9ae194fd2fdb..b80bf10603d7 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -198,11 +198,9 @@ static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, if (type >= META_FLUSH) { io->fio.type = META_FLUSH; io->fio.op = REQ_OP_WRITE; - if (test_opt(sbi, NOBARRIER)) - io->fio.op_flags = WRITE_FLUSH | REQ_META | REQ_PRIO; - else - io->fio.op_flags = WRITE_FLUSH_FUA | REQ_META | - REQ_PRIO; + io->fio.op_flags = REQ_PREFLUSH | REQ_META | REQ_PRIO; + if (!test_opt(sbi, NOBARRIER)) + io->fio.op_flags |= REQ_FUA; } __submit_merged_bio(io); out: @@ -483,7 +481,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index) return page; f2fs_put_page(page, 0); - page = get_read_data_page(inode, index, READ_SYNC, false); + page = get_read_data_page(inode, index, 0, false); if (IS_ERR(page)) return page; @@ -509,7 +507,7 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index, struct address_space *mapping = inode->i_mapping; struct page *page; repeat: - page = get_read_data_page(inode, index, READ_SYNC, for_write); + page = get_read_data_page(inode, index, 0, for_write); if (IS_ERR(page)) return page; @@ -1251,7 +1249,7 @@ static int f2fs_write_data_page(struct page *page, .sbi = sbi, .type = DATA, .op = REQ_OP_WRITE, - .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0, + .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? REQ_SYNC : 0, .page = page, .encrypted_page = NULL, }; @@ -1663,7 +1661,7 @@ repeat: err = PTR_ERR(bio); goto fail; } - bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC); + bio->bi_opf = REQ_OP_READ; if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); err = -EFAULT; diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 93985c64d8a8..9eb11b2244ea 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -550,7 +550,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx) .sbi = F2FS_I_SB(inode), .type = DATA, .op = REQ_OP_READ, - .op_flags = READ_SYNC, + .op_flags = 0, .encrypted_page = NULL, }; struct dnode_of_data dn; @@ -625,7 +625,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx) f2fs_wait_on_page_writeback(dn.node_page, NODE, true); fio.op = REQ_OP_WRITE; - fio.op_flags = WRITE_SYNC; + fio.op_flags = REQ_SYNC; fio.new_blkaddr = newaddr; f2fs_submit_page_mbio(&fio); @@ -663,7 +663,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type) .sbi = F2FS_I_SB(inode), .type = DATA, .op = REQ_OP_WRITE, - .op_flags = WRITE_SYNC, + .op_flags = REQ_SYNC, .page = page, .encrypted_page = NULL, }; diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 5f1a67f756af..2e7f54c191b4 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -111,7 +111,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) .sbi = F2FS_I_SB(dn->inode), .type = DATA, .op = REQ_OP_WRITE, - .op_flags = WRITE_SYNC | REQ_PRIO, + .op_flags = REQ_SYNC | REQ_PRIO, .page = page, .encrypted_page = NULL, }; diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 01177ecdeab8..932f3f8bb57b 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1134,7 +1134,7 @@ repeat: if (!page) return ERR_PTR(-ENOMEM); - err = read_node_page(page, READ_SYNC); + err = read_node_page(page, 0); if (err < 0) { f2fs_put_page(page, 1); return ERR_PTR(err); @@ -1570,7 +1570,7 @@ static int f2fs_write_node_page(struct page *page, .sbi = sbi, .type = NODE, .op = REQ_OP_WRITE, - .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0, + .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? REQ_SYNC : 0, .page = page, .encrypted_page = NULL, }; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index fc886f008449..f1b4a1775ebe 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -259,7 +259,7 @@ static int __commit_inmem_pages(struct inode *inode, .sbi = sbi, .type = DATA, .op = REQ_OP_WRITE, - .op_flags = WRITE_SYNC | REQ_PRIO, + .op_flags = REQ_SYNC | REQ_PRIO, .encrypted_page = NULL, }; bool submit_bio = false; @@ -420,7 +420,7 @@ repeat: fcc->dispatch_list = llist_reverse_order(fcc->dispatch_list); bio->bi_bdev = sbi->sb->s_bdev; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; ret = submit_bio_wait(bio); llist_for_each_entry_safe(cmd, next, @@ -454,7 +454,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi) atomic_inc(&fcc->submit_flush); bio->bi_bdev = sbi->sb->s_bdev; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; ret = submit_bio_wait(bio); atomic_dec(&fcc->submit_flush); bio_put(bio); @@ -1515,7 +1515,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) .sbi = sbi, .type = META, .op = REQ_OP_WRITE, - .op_flags = WRITE_SYNC | REQ_META | REQ_PRIO, + .op_flags = REQ_SYNC | REQ_META | REQ_PRIO, .old_blkaddr = page->index, .new_blkaddr = page->index, .page = page, diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 6132b4ce4e4c..2cac6bb86080 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1238,7 +1238,7 @@ static int __f2fs_commit_super(struct buffer_head *bh, unlock_buffer(bh); /* it's rare case, we can do fua all the time */ - return __sync_dirty_buffer(bh, WRITE_FLUSH_FUA); + return __sync_dirty_buffer(bh, REQ_PREFLUSH | REQ_FUA); } static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi, diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index e58ccef09c91..27c00a16def0 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -657,7 +657,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags) struct gfs2_log_header *lh; unsigned int tail; u32 hash; - int op_flags = WRITE_FLUSH_FUA | REQ_META; + int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META; struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); lh = page_address(page); @@ -682,7 +682,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags) if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) { gfs2_ordered_wait(sdp); log_flush_wait(sdp); - op_flags = WRITE_SYNC | REQ_META | REQ_PRIO; + op_flags = REQ_SYNC | REQ_META | REQ_PRIO; } sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 373639a59782..e562b1191c9c 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -38,7 +38,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb struct buffer_head *bh, *head; int nr_underway = 0; int write_flags = REQ_META | REQ_PRIO | - (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0); + (wbc->sync_mode == WB_SYNC_ALL ? REQ_SYNC : 0); BUG_ON(!PageLocked(page)); BUG_ON(!page_has_buffers(page)); @@ -285,7 +285,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, } } - gfs2_submit_bhs(REQ_OP_READ, READ_SYNC | REQ_META | REQ_PRIO, bhs, num); + gfs2_submit_bhs(REQ_OP_READ, REQ_META | REQ_PRIO, bhs, num); if (!(flags & DIO_WAIT)) return 0; @@ -453,7 +453,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) if (buffer_uptodate(first_bh)) goto out; if (!buffer_locked(first_bh)) - ll_rw_block(REQ_OP_READ, READ_SYNC | REQ_META, 1, &first_bh); + ll_rw_block(REQ_OP_READ, REQ_META, 1, &first_bh); dblock++; extlen--; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index ff72ac6439c8..a34308df927f 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -246,7 +246,7 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent) bio->bi_end_io = end_bio_io_page; bio->bi_private = page; - bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC | REQ_META); + bio_set_op_attrs(bio, REQ_OP_READ, REQ_META); submit_bio(bio); wait_on_page_locked(page); bio_put(bio); diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 11854dd84572..67aedf4c2e7c 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -221,7 +221,7 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait) error2 = hfsplus_submit_bio(sb, sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, sbi->s_vhdr_buf, NULL, REQ_OP_WRITE, - WRITE_SYNC); + REQ_SYNC); if (!error) error = error2; if (!write_backup) @@ -230,7 +230,7 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait) error2 = hfsplus_submit_bio(sb, sbi->part_start + sbi->sect_count - 2, sbi->s_backup_vhdr_buf, NULL, REQ_OP_WRITE, - WRITE_SYNC); + REQ_SYNC); if (!error) error2 = error; out: diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 684996c8a3a4..4055f51617ef 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -186,7 +186,7 @@ __flush_batch(journal_t *journal, int *batch_count) blk_start_plug(&plug); for (i = 0; i < *batch_count; i++) - write_dirty_buffer(journal->j_chkpt_bhs[i], WRITE_SYNC); + write_dirty_buffer(journal->j_chkpt_bhs[i], REQ_SYNC); blk_finish_plug(&plug); for (i = 0; i < *batch_count; i++) { diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 31f8ca046639..8c514367ba5a 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -155,9 +155,10 @@ static int journal_submit_commit_record(journal_t *journal, if (journal->j_flags & JBD2_BARRIER && !jbd2_has_feature_async_commit(journal)) - ret = submit_bh(REQ_OP_WRITE, WRITE_SYNC | WRITE_FLUSH_FUA, bh); + ret = submit_bh(REQ_OP_WRITE, + REQ_SYNC | REQ_PREFLUSH | REQ_FUA, bh); else - ret = submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh); + ret = submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); *cbh = bh; return ret; @@ -402,7 +403,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) jbd2_journal_update_sb_log_tail(journal, journal->j_tail_sequence, journal->j_tail, - WRITE_SYNC); + REQ_SYNC); mutex_unlock(&journal->j_checkpoint_mutex); } else { jbd_debug(3, "superblock not updated\n"); @@ -717,7 +718,7 @@ start_journal_io: clear_buffer_dirty(bh); set_buffer_uptodate(bh); bh->b_end_io = journal_end_buffer_io_sync; - submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh); + submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); } cond_resched(); stats.run.rs_blocks_logged += bufs; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 927da4956a89..8ed971eeab44 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -913,7 +913,7 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) * space and if we lose sb update during power failure we'd replay * old transaction with possibly newly overwritten data. */ - ret = jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA); + ret = jbd2_journal_update_sb_log_tail(journal, tid, block, REQ_FUA); if (ret) goto out; @@ -1306,7 +1306,7 @@ static int journal_reset(journal_t *journal) /* Lock here to make assertions happy... */ mutex_lock(&journal->j_checkpoint_mutex); /* - * Update log tail information. We use WRITE_FUA since new + * Update log tail information. We use REQ_FUA since new * transaction will start reusing journal space and so we * must make sure information about current log tail is on * disk before that. @@ -1314,7 +1314,7 @@ static int journal_reset(journal_t *journal) jbd2_journal_update_sb_log_tail(journal, journal->j_tail_sequence, journal->j_tail, - WRITE_FUA); + REQ_FUA); mutex_unlock(&journal->j_checkpoint_mutex); } return jbd2_journal_start_thread(journal); @@ -1454,7 +1454,7 @@ void jbd2_journal_update_sb_errno(journal_t *journal) sb->s_errno = cpu_to_be32(journal->j_errno); read_unlock(&journal->j_state_lock); - jbd2_write_superblock(journal, WRITE_FUA); + jbd2_write_superblock(journal, REQ_FUA); } EXPORT_SYMBOL(jbd2_journal_update_sb_errno); @@ -1720,7 +1720,8 @@ int jbd2_journal_destroy(journal_t *journal) ++journal->j_transaction_sequence; write_unlock(&journal->j_state_lock); - jbd2_mark_journal_empty(journal, WRITE_FLUSH_FUA); + jbd2_mark_journal_empty(journal, + REQ_PREFLUSH | REQ_FUA); mutex_unlock(&journal->j_checkpoint_mutex); } else err = -EIO; @@ -1979,7 +1980,7 @@ int jbd2_journal_flush(journal_t *journal) * the magic code for a fully-recovered superblock. Any future * commits of data to the journal will restore the current * s_start value. */ - jbd2_mark_journal_empty(journal, WRITE_FUA); + jbd2_mark_journal_empty(journal, REQ_FUA); mutex_unlock(&journal->j_checkpoint_mutex); write_lock(&journal->j_state_lock); J_ASSERT(!journal->j_running_transaction); @@ -2025,7 +2026,7 @@ int jbd2_journal_wipe(journal_t *journal, int write) if (write) { /* Lock to make assertions happy... */ mutex_lock(&journal->j_checkpoint_mutex); - jbd2_mark_journal_empty(journal, WRITE_FUA); + jbd2_mark_journal_empty(journal, REQ_FUA); mutex_unlock(&journal->j_checkpoint_mutex); } diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 91171dc352cb..cfc38b552118 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c @@ -648,7 +648,7 @@ static void flush_descriptor(journal_t *journal, set_buffer_jwrite(descriptor); BUFFER_TRACE(descriptor, "write"); set_buffer_dirty(descriptor); - write_dirty_buffer(descriptor, WRITE_SYNC); + write_dirty_buffer(descriptor, REQ_SYNC); } #endif diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index a21ea8b3e5fa..bb1da1feafeb 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -2002,7 +2002,7 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp) bio->bi_end_io = lbmIODone; bio->bi_private = bp; - bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC); + bio->bi_opf = REQ_OP_READ; /*check if journaling to disk has been disabled*/ if (log->no_integrity) { bio->bi_iter.bi_size = 0; @@ -2146,7 +2146,7 @@ static void lbmStartIO(struct lbuf * bp) bio->bi_end_io = lbmIODone; bio->bi_private = bp; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC); + bio->bi_opf = REQ_OP_WRITE | REQ_SYNC; /* check if journaling to disk has been disabled */ if (log->no_integrity) { diff --git a/fs/mpage.c b/fs/mpage.c index d2413af0823a..f35e2819d0c6 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -489,7 +489,7 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc, struct buffer_head map_bh; loff_t i_size = i_size_read(inode); int ret = 0; - int op_flags = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0); + int op_flags = (wbc->sync_mode == WB_SYNC_ALL ? REQ_SYNC : 0); if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); @@ -705,7 +705,7 @@ mpage_writepages(struct address_space *mapping, ret = write_cache_pages(mapping, wbc, __mpage_writepage, &mpd); if (mpd.bio) { int op_flags = (wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC : 0); + REQ_SYNC : 0); mpage_bio_submit(REQ_OP_WRITE, op_flags, mpd.bio); } } @@ -726,7 +726,7 @@ int mpage_writepage(struct page *page, get_block_t get_block, int ret = __mpage_writepage(page, wbc, &mpd); if (mpd.bio) { int op_flags = (wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC : 0); + REQ_SYNC : 0); mpage_bio_submit(REQ_OP_WRITE, op_flags, mpd.bio); } return ret; diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index c95d369e90aa..12eeae62a2b1 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -189,7 +189,7 @@ static int nilfs_sync_super(struct super_block *sb, int flag) set_buffer_dirty(nilfs->ns_sbh[0]); if (nilfs_test_opt(nilfs, BARRIER)) { err = __sync_dirty_buffer(nilfs->ns_sbh[0], - WRITE_SYNC | WRITE_FLUSH_FUA); + REQ_SYNC | REQ_PREFLUSH | REQ_FUA); } else { err = sync_dirty_buffer(nilfs->ns_sbh[0]); } diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 636abcbd4650..52eef16edb01 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -627,7 +627,7 @@ static int o2hb_issue_node_write(struct o2hb_region *reg, slot = o2nm_this_node(); bio = o2hb_setup_one_bio(reg, write_wc, &slot, slot+1, REQ_OP_WRITE, - WRITE_SYNC); + REQ_SYNC); if (IS_ERR(bio)) { status = PTR_ERR(bio); mlog_errno(status); diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index bc2dde2423c2..aa40c242f1db 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1111,7 +1111,8 @@ static int flush_commit_list(struct super_block *s, mark_buffer_dirty(jl->j_commit_bh) ; depth = reiserfs_write_unlock_nested(s); if (reiserfs_barrier_flush(s)) - __sync_dirty_buffer(jl->j_commit_bh, WRITE_FLUSH_FUA); + __sync_dirty_buffer(jl->j_commit_bh, + REQ_PREFLUSH | REQ_FUA); else sync_dirty_buffer(jl->j_commit_bh); reiserfs_write_lock_nested(s, depth); @@ -1269,7 +1270,8 @@ static int _update_journal_header_block(struct super_block *sb, depth = reiserfs_write_unlock_nested(sb); if (reiserfs_barrier_flush(sb)) - __sync_dirty_buffer(journal->j_header_bh, WRITE_FLUSH_FUA); + __sync_dirty_buffer(journal->j_header_bh, + REQ_PREFLUSH | REQ_FUA); else sync_dirty_buffer(journal->j_header_bh); diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 3e57a56cf829..594e02c485b2 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -495,8 +495,10 @@ xfs_submit_ioend( ioend->io_bio->bi_private = ioend; ioend->io_bio->bi_end_io = xfs_end_bio; - bio_set_op_attrs(ioend->io_bio, REQ_OP_WRITE, - (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0); + ioend->io_bio->bi_opf = REQ_OP_WRITE; + if (wbc->sync_mode == WB_SYNC_ALL) + ioend->io_bio->bi_opf |= REQ_SYNC; + /* * If we are failing the IO now, just mark the ioend with an * error and finish it. This will run IO completion immediately @@ -567,8 +569,9 @@ xfs_chain_bio( bio_chain(ioend->io_bio, new); bio_get(ioend->io_bio); /* for xfs_destroy_ioend */ - bio_set_op_attrs(ioend->io_bio, REQ_OP_WRITE, - (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0); + ioend->io_bio->bi_opf = REQ_OP_WRITE; + if (wbc->sync_mode == WB_SYNC_ALL) + ioend->io_bio->bi_opf |= REQ_SYNC; submit_bio(ioend->io_bio); ioend->io_bio = new; } diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index b5b9bffe3520..33c435f3316c 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1304,7 +1304,7 @@ _xfs_buf_ioapply( if (bp->b_flags & XBF_WRITE) { op = REQ_OP_WRITE; if (bp->b_flags & XBF_SYNCIO) - op_flags = WRITE_SYNC; + op_flags = REQ_SYNC; if (bp->b_flags & XBF_FUA) op_flags |= REQ_FUA; if (bp->b_flags & XBF_FLUSH) diff --git a/include/linux/fs.h b/include/linux/fs.h index 46a74209917f..7a1b78ab7c15 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -151,58 +151,11 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, */ #define CHECK_IOVEC_ONLY -1 -/* - * The below are the various read and write flags that we support. Some of - * them include behavioral modifiers that send information down to the - * block layer and IO scheduler. They should be used along with a req_op. - * Terminology: - * - * The block layer uses device plugging to defer IO a little bit, in - * the hope that we will see more IO very shortly. This increases - * coalescing of adjacent IO and thus reduces the number of IOs we - * have to send to the device. It also allows for better queuing, - * if the IO isn't mergeable. If the caller is going to be waiting - * for the IO, then he must ensure that the device is unplugged so - * that the IO is dispatched to the driver. - * - * All IO is handled async in Linux. This is fine for background - * writes, but for reads or writes that someone waits for completion - * on, we want to notify the block layer and IO scheduler so that they - * know about it. That allows them to make better scheduling - * decisions. So when the below references 'sync' and 'async', it - * is referencing this priority hint. - * - * With that in mind, the available types are: - * - * READ A normal read operation. Device will be plugged. - * READ_SYNC A synchronous read. Device is not plugged, caller can - * immediately wait on this read without caring about - * unplugging. - * WRITE A normal async write. Device will be plugged. - * WRITE_SYNC Synchronous write. Identical to WRITE, but passes down - * the hint that someone will be waiting on this IO - * shortly. The write equivalent of READ_SYNC. - * WRITE_ODIRECT Special case write for O_DIRECT only. - * WRITE_FLUSH Like WRITE_SYNC but with preceding cache flush. - * WRITE_FUA Like WRITE_SYNC but data is guaranteed to be on - * non-volatile media on completion. - * WRITE_FLUSH_FUA Combination of WRITE_FLUSH and FUA. The IO is preceded - * by a cache flush and data is guaranteed to be on - * non-volatile media on completion. - * - */ #define RW_MASK REQ_OP_WRITE #define READ REQ_OP_READ #define WRITE REQ_OP_WRITE -#define READ_SYNC 0 -#define WRITE_SYNC REQ_SYNC -#define WRITE_ODIRECT (REQ_SYNC | REQ_IDLE) -#define WRITE_FLUSH REQ_PREFLUSH -#define WRITE_FUA REQ_FUA -#define WRITE_FLUSH_FUA (REQ_PREFLUSH | REQ_FUA) - /* * Attribute flags. These should be or-ed together to figure out what * has been changed! diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index a9d34424450d..5da2c829a718 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -55,7 +55,7 @@ TRACE_DEFINE_ENUM(CP_DISCARD); { IPU, "IN-PLACE" }, \ { OPU, "OUT-OF-PLACE" }) -#define F2FS_BIO_FLAG_MASK(t) (t & (REQ_RAHEAD | WRITE_FLUSH_FUA)) +#define F2FS_BIO_FLAG_MASK(t) (t & (REQ_RAHEAD | REQ_PREFLUSH | REQ_FUA)) #define F2FS_BIO_EXTRA_MASK(t) (t & (REQ_META | REQ_PRIO)) #define show_bio_type(op_flags) show_bio_op_flags(op_flags), \ @@ -65,11 +65,9 @@ TRACE_DEFINE_ENUM(CP_DISCARD); __print_symbolic(F2FS_BIO_FLAG_MASK(flags), \ { 0, "WRITE" }, \ { REQ_RAHEAD, "READAHEAD" }, \ - { READ_SYNC, "READ_SYNC" }, \ - { WRITE_SYNC, "WRITE_SYNC" }, \ - { WRITE_FLUSH, "WRITE_FLUSH" }, \ - { WRITE_FUA, "WRITE_FUA" }, \ - { WRITE_FLUSH_FUA, "WRITE_FLUSH_FUA" }) + { REQ_SYNC, "REQ_SYNC" }, \ + { REQ_PREFLUSH, "REQ_PREFLUSH" }, \ + { REQ_FUA, "REQ_FUA" }) #define show_bio_extra(type) \ __print_symbolic(F2FS_BIO_EXTRA_MASK(type), \ diff --git a/kernel/power/swap.c b/kernel/power/swap.c index a3b1e617bcdc..32e0c232efba 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -307,7 +307,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) { int error; - hib_submit_io(REQ_OP_READ, READ_SYNC, swsusp_resume_block, + hib_submit_io(REQ_OP_READ, 0, swsusp_resume_block, swsusp_header, NULL); if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) || !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) { @@ -317,7 +317,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) swsusp_header->flags = flags; if (flags & SF_CRC32_MODE) swsusp_header->crc32 = handle->crc32; - error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, + error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC, swsusp_resume_block, swsusp_header, NULL); } else { printk(KERN_ERR "PM: Swap header not found!\n"); @@ -397,7 +397,7 @@ static int write_page(void *buf, sector_t offset, struct hib_bio_batch *hb) } else { src = buf; } - return hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, offset, src, hb); + return hib_submit_io(REQ_OP_WRITE, REQ_SYNC, offset, src, hb); } static void release_swap_writer(struct swap_map_handle *handle) @@ -1000,8 +1000,7 @@ static int get_swap_reader(struct swap_map_handle *handle, return -ENOMEM; } - error = hib_submit_io(REQ_OP_READ, READ_SYNC, offset, - tmp->map, NULL); + error = hib_submit_io(REQ_OP_READ, 0, offset, tmp->map, NULL); if (error) { release_swap_reader(handle); return error; @@ -1025,7 +1024,7 @@ static int swap_read_page(struct swap_map_handle *handle, void *buf, offset = handle->cur->entries[handle->k]; if (!offset) return -EFAULT; - error = hib_submit_io(REQ_OP_READ, READ_SYNC, offset, buf, hb); + error = hib_submit_io(REQ_OP_READ, 0, offset, buf, hb); if (error) return error; if (++handle->k >= MAP_PAGE_ENTRIES) { @@ -1534,7 +1533,7 @@ int swsusp_check(void) if (!IS_ERR(hib_resume_bdev)) { set_blocksize(hib_resume_bdev, PAGE_SIZE); clear_page(swsusp_header); - error = hib_submit_io(REQ_OP_READ, READ_SYNC, + error = hib_submit_io(REQ_OP_READ, 0, swsusp_resume_block, swsusp_header, NULL); if (error) @@ -1543,7 +1542,7 @@ int swsusp_check(void) if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) { memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); /* Reset swap signature now */ - error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, + error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC, swsusp_resume_block, swsusp_header, NULL); } else { @@ -1588,11 +1587,11 @@ int swsusp_unmark(void) { int error; - hib_submit_io(REQ_OP_READ, READ_SYNC, swsusp_resume_block, + hib_submit_io(REQ_OP_READ, 0, swsusp_resume_block, swsusp_header, NULL); if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) { memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10); - error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, + error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC, swsusp_resume_block, swsusp_header, NULL); } else { -- cgit v1.2.3 From be297968da22cf40c9c419df51e71ba8856a2ec2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 1 Nov 2016 07:40:16 -0600 Subject: mm: only include blk_types in swap.h if CONFIG_SWAP is enabled It's only needed for the CONFIG_SWAP-only use of bio_end_io_t. Because CONFIG_SWAP implies CONFIG_BLOCK this will allow to drop some ifdefs in blk_types.h. Instead we'll need to add a few explicit includes that were implicit before, though. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/staging/lustre/include/linux/lnet/types.h | 1 + drivers/staging/lustre/lustre/llite/rw.c | 1 + fs/ntfs/aops.c | 1 + fs/ntfs/mft.c | 1 + fs/reiserfs/inode.c | 1 + fs/splice.c | 1 + include/linux/swap.h | 4 +++- 7 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/lnet/types.h b/drivers/staging/lustre/include/linux/lnet/types.h index f8be0e2f7bf7..8ca1e9d0cfe2 100644 --- a/drivers/staging/lustre/include/linux/lnet/types.h +++ b/drivers/staging/lustre/include/linux/lnet/types.h @@ -34,6 +34,7 @@ #define __LNET_TYPES_H__ #include +#include /** \addtogroup lnet * @{ diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 50c0152ba022..76a6836cdf70 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -47,6 +47,7 @@ #include /* current_is_kswapd() */ #include +#include #define DEBUG_SUBSYSTEM S_LLITE diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index fe251f187ff8..d0cf6fee5c77 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "aops.h" #include "attrib.h" diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index d3c009626032..b6f402194f02 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "attrib.h" #include "aops.h" diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 58b2dedb2a3a..cfeae9b0a2b7 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -19,6 +19,7 @@ #include #include #include +#include int reiserfs_commit_write(struct file *f, struct page *page, unsigned from, unsigned to); diff --git a/fs/splice.c b/fs/splice.c index 153d4f3bd441..51492f26915a 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -17,6 +17,7 @@ * Copyright (C) 2006 Ingo Molnar * */ +#include #include #include #include diff --git a/include/linux/swap.h b/include/linux/swap.h index 3a6aebc23001..bfee1af1f54f 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -11,7 +11,6 @@ #include #include #include -#include #include struct notifier_block; @@ -352,6 +351,9 @@ extern int kswapd_run(int nid); extern void kswapd_stop(int nid); #ifdef CONFIG_SWAP + +#include /* for bio_end_io_t */ + /* linux/mm/page_io.c */ extern int swap_readpage(struct page *); extern int swap_writepage(struct page *page, struct writeback_control *wbc); -- cgit v1.2.3 From e58e415968110648231ed6783d38e78032661cee Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 31 Oct 2016 15:54:00 -0700 Subject: net: Enable support for VRF with ipv4 multicast Enable support for IPv4 multicast: - similar to unicast the flow struct is updated to L3 master device if relevant prior to calling fib_rules_lookup. The table id is saved to the lookup arg so the rule action for ipmr can return the table associated with the device. - ip_mr_forward needs to check for master device mismatch as well since the skb->dev is set to it - allow multicast address on VRF device for Rx by checking for the daddr in the VRF device as well as the original ingress device - on Tx need to drop to __mkroute_output when FIB lookup fails for multicast destination address. - if CONFIG_IP_MROUTE_MULTIPLE_TABLES is enabled VRF driver creates IPMR FIB rules on first device create similar to FIB rules. In addition the VRF driver does not divert IPv4 multicast packets: it breaks on Tx since the fib lookup fails on the mcast address. With this patch, ipmr forwarding and local rx/tx work. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 23 ++++++++++++++++++----- net/ipv4/ipmr.c | 13 ++++++++++++- net/ipv4/route.c | 41 ++++++++++++++++++++++++++--------------- 3 files changed, 56 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 820de6a9ddde..3bca24651dc0 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -272,11 +272,6 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, if (IS_ERR(rt)) goto err; - if (rt->rt_type != RTN_UNICAST && rt->rt_type != RTN_LOCAL) { - ip_rt_put(rt); - goto err; - } - skb_dst_drop(skb); /* if dst.dev is loopback or the VRF device again this is locally @@ -611,6 +606,10 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev, struct dst_entry *dst = NULL; struct rtable *rth; + /* don't divert multicast */ + if (ipv4_is_multicast(ip_hdr(skb)->daddr)) + return skb; + rcu_read_lock(); rth = rcu_dereference(vrf->rth); @@ -999,6 +998,9 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev, skb->skb_iif = vrf_dev->ifindex; IPCB(skb)->flags |= IPSKB_L3SLAVE; + if (ipv4_is_multicast(ip_hdr(skb)->daddr)) + goto out; + /* loopback traffic; do not push through packet taps again. * Reset pkt_type for upper layers to process skb */ @@ -1162,8 +1164,19 @@ static int vrf_add_fib_rules(const struct net_device *dev) if (err < 0) goto ipv6_err; +#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES) + err = vrf_fib_rule(dev, RTNL_FAMILY_IPMR, true); + if (err < 0) + goto ipmr_err; +#endif + return 0; +#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES) +ipmr_err: + vrf_fib_rule(dev, AF_INET6, false); +#endif + ipv6_err: vrf_fib_rule(dev, AF_INET, false); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 51d71a70fbbe..f2fd13b07273 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -137,6 +137,9 @@ static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, .flags = FIB_LOOKUP_NOREF, }; + /* update flow if oif or iif point to device enslaved to l3mdev */ + l3mdev_update_flow(net, flowi4_to_flowi(flp4)); + err = fib_rules_lookup(net->ipv4.mr_rules_ops, flowi4_to_flowi(flp4), 0, &arg); if (err < 0) @@ -163,7 +166,9 @@ static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp, return -EINVAL; } - mrt = ipmr_get_table(rule->fr_net, rule->table); + arg->table = fib_rule_get_table(rule, arg); + + mrt = ipmr_get_table(rule->fr_net, arg->table); if (!mrt) return -EAGAIN; res->mrt = mrt; @@ -1809,6 +1814,12 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, /* Wrong interface: drop packet and (maybe) send PIM assert. */ if (mrt->vif_table[vif].dev != skb->dev) { + struct net_device *mdev; + + mdev = l3mdev_master_dev_rcu(mrt->vif_table[vif].dev); + if (mdev == skb->dev) + goto forward; + if (rt_is_output_route(skb_rtable(skb))) { /* It is our own packet, looped back. * Very complicated situation... diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 62d4d90c1389..4392db83d540 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1980,25 +1980,35 @@ int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr, */ if (ipv4_is_multicast(daddr)) { struct in_device *in_dev = __in_dev_get_rcu(dev); + int our = 0; - if (in_dev) { - int our = ip_check_mc_rcu(in_dev, daddr, saddr, - ip_hdr(skb)->protocol); - if (our + if (in_dev) + our = ip_check_mc_rcu(in_dev, daddr, saddr, + ip_hdr(skb)->protocol); + + /* check l3 master if no match yet */ + if ((!in_dev || !our) && netif_is_l3_slave(dev)) { + struct in_device *l3_in_dev; + + l3_in_dev = __in_dev_get_rcu(skb->dev); + if (l3_in_dev) + our = ip_check_mc_rcu(l3_in_dev, daddr, saddr, + ip_hdr(skb)->protocol); + } + + res = -EINVAL; + if (our #ifdef CONFIG_IP_MROUTE - || - (!ipv4_is_local_multicast(daddr) && - IN_DEV_MFORWARD(in_dev)) + || + (!ipv4_is_local_multicast(daddr) && + IN_DEV_MFORWARD(in_dev)) #endif - ) { - int res = ip_route_input_mc(skb, daddr, saddr, - tos, dev, our); - rcu_read_unlock(); - return res; - } + ) { + res = ip_route_input_mc(skb, daddr, saddr, + tos, dev, our); } rcu_read_unlock(); - return -EINVAL; + return res; } res = ip_route_input_slow(skb, daddr, saddr, tos, dev); rcu_read_unlock(); @@ -2266,7 +2276,8 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4, res.fi = NULL; res.table = NULL; if (fl4->flowi4_oif && - !netif_index_is_l3_master(net, fl4->flowi4_oif)) { + (ipv4_is_multicast(fl4->daddr) || + !netif_index_is_l3_master(net, fl4->flowi4_oif))) { /* Apparently, routing tables are wrong. Assume, that the destination is on link. -- cgit v1.2.3 From 3599a91cc8d07542dbeef44034a70ed2d1d1ba98 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 1 Nov 2016 14:44:10 +0000 Subject: drm/i915: Allow shrinking of userptr objects once again Commit 1bec9b0bda3d ("drm/i915/shrinker: Only shmemfs objects are backed by swap") stopped considering the userptr objects in shrinker callbacks. Restore that so idle userptr objects can be discarded in order to free up memory. One change further to what was introduced in 1bec9b0bda3d is to start considering userptr objects in oom but that should also be a correct thing to do. v2: Introduce I915_GEM_OBJECT_IS_SHRINKABLE. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Fixes: 1bec9b0bda3d ("drm/i915/shrinker: Only shmemfs objects are backed by swap") Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Mika Kuoppala Cc: Link: http://patchwork.freedesktop.org/patch/msgid/1478011450-6634-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 7 +++++++ drivers/gpu/drm/i915/i915_gem.c | 3 ++- drivers/gpu/drm/i915/i915_gem_internal.c | 3 ++- drivers/gpu/drm/i915/i915_gem_shrinker.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_userptr.c | 3 ++- 5 files changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b8e72cdcb713..f20e24baf95c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2181,6 +2181,7 @@ enum hdmi_force_audio { struct drm_i915_gem_object_ops { unsigned int flags; #define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1 +#define I915_GEM_OBJECT_IS_SHRINKABLE 0x2 /* Interface between the GEM object and its backing storage. * get_pages() is called once prior to the use of the associated set @@ -2429,6 +2430,12 @@ i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj) return obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE; } +static inline bool +i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj) +{ + return obj->ops->flags & I915_GEM_OBJECT_IS_SHRINKABLE; +} + static inline bool i915_gem_object_is_active(const struct drm_i915_gem_object *obj) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 207b8ef85136..a97fdfa80663 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4146,7 +4146,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, } static const struct drm_i915_gem_object_ops i915_gem_object_ops = { - .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE, + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE | + I915_GEM_OBJECT_IS_SHRINKABLE, .get_pages = i915_gem_object_get_pages_gtt, .put_pages = i915_gem_object_put_pages_gtt, }; diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index 1b0607a44a9a..4b3ff3e5b911 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -132,7 +132,8 @@ static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj, } static const struct drm_i915_gem_object_ops i915_gem_object_internal_ops = { - .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE, + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE | + I915_GEM_OBJECT_IS_SHRINKABLE, .get_pages = i915_gem_object_get_pages_internal, .put_pages = i915_gem_object_put_pages_internal, }; diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index f988652f1e26..87dd27d5146c 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -83,8 +83,8 @@ static bool can_release_pages(struct drm_i915_gem_object *obj) if (!obj->mm.pages) return false; - /* Only shmemfs objects are backed by swap */ - if (!obj->base.filp) + /* Consider only shrinkable ojects. */ + if (!i915_gem_object_is_shrinkable(obj)) return false; /* Only report true if by unbinding the object and putting its pages diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 9bf44b5bca10..64261639f547 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -707,7 +707,8 @@ i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj) } static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { - .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE, + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE | + I915_GEM_OBJECT_IS_SHRINKABLE, .get_pages = i915_gem_userptr_get_pages, .put_pages = i915_gem_userptr_put_pages, .dmabuf_export = i915_gem_userptr_dmabuf_export, -- cgit v1.2.3 From e0029dcb5b6e1c23e68f578ce7a3d6c5caba0501 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 31 Oct 2016 21:06:58 +0100 Subject: libata-scsi: Fixup ata_gen_passthru_sense() There's a typo in ata_gen_passthru_sense(), where the first byte would be overwritten incorrectly later on. Reported-by: Charles Machalow Signed-off-by: Hannes Reinecke Fixes: 11093cb1ef56 ("libata-scsi: generate correct ATA pass-through sense") Cc: stable@vger.kernel.org # v4.7+ Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9cceb4a875a5..c4eb4ae9c3aa 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1088,7 +1088,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) desc[1] = tf->command; /* status */ desc[2] = tf->device; desc[3] = tf->nsect; - desc[0] = 0; + desc[7] = 0; if (tf->flags & ATA_TFLAG_LBA48) { desc[8] |= 0x80; if (tf->hob_nsect) -- cgit v1.2.3 From b4d2192e6fa81fab2000277fd399023d3a23ac96 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 30 Oct 2016 12:08:42 +0000 Subject: iio:cros_ec_sensors: Swap from a select to a depends in Kconfig Would have merged this into the original patch as a fixup but I've already pushed that out as an immutable branch for others to use so it'll have to be a separate patch. The original select had a typo as well. Trying to do this via a select was opening a can of worms due to a tree of other elements that would also have needed selecting. A simple depends seems much mroe straight forward and appropriate in this case. Signed-off-by: Jonathan Cameron Cc: Lee Jones Cc: Enric Balletbo i Serra --- drivers/iio/common/cros_ec_sensors/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig index 3349c9d2cf7a..135f6825903f 100644 --- a/drivers/iio/common/cros_ec_sensors/Kconfig +++ b/drivers/iio/common/cros_ec_sensors/Kconfig @@ -14,8 +14,7 @@ config IIO_CROS_EC_SENSORS_CORE config IIO_CROS_EC_SENSORS tristate "ChromeOS EC Contiguous Sensors" - select IIO_CROS_EC_SENSORS_CORE - select MFD_CROSS_EC + depends on IIO_CROS_EC_SENSORS_CORE help Module to handle 3d contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are -- cgit v1.2.3 From d1c67534123d088289fa847809ba1a6fa11b1932 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 29 Oct 2016 16:11:20 +0000 Subject: iio: humidity: remove duplicated include from hts221_buffer.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/hts221_buffer.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/humidity/hts221_buffer.c b/drivers/iio/humidity/hts221_buffer.c index 76b2e8130b6f..72ddcdac21a2 100644 --- a/drivers/iio/humidity/hts221_buffer.c +++ b/drivers/iio/humidity/hts221_buffer.c @@ -15,7 +15,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From b0d801985418e0890adf14398373b9c4470911d1 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 25 Oct 2016 21:20:10 +0200 Subject: iio: si7020: Add devicetree support and trivial bindings This adds devicetree support for the si7020 iio driver. Since it works well without requiring any additional property, its compatible string is added to the trivial i2c devices bindings list. Signed-off-by: Paul Kocialkowski Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/i2c/trivial-devices.txt | 1 + drivers/iio/humidity/si7020.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 6e4ba816094b..03349ad5abfa 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -152,6 +152,7 @@ ricoh,rv5c387a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC samsung,24ad0xd1 S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power) sgx,vz89x SGX Sensortech VZ89X Sensors sii,s35390a 2-wire CMOS real-time clock +silabs,si7020 Relative Humidity and Temperature Sensors skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply st,24c256 i2c serial eeprom (24cxx) st,m41t00 Serial real-time clock (RTC) diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index ffc2ccf6374e..345a7656c5ef 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c @@ -154,8 +154,17 @@ static const struct i2c_device_id si7020_id[] = { }; MODULE_DEVICE_TABLE(i2c, si7020_id); +static const struct of_device_id si7020_dt_ids[] = { + { .compatible = "silabs,si7020" }, + { } +}; +MODULE_DEVICE_TABLE(of, si7020_dt_ids); + static struct i2c_driver si7020_driver = { - .driver.name = "si7020", + .driver = { + .name = "si7020", + .of_match_table = of_match_ptr(si7020_dt_ids), + }, .probe = si7020_probe, .id_table = si7020_id, }; -- cgit v1.2.3 From dcdb0a78cab39efbfa00f005fd2691a07335f41e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 25 Oct 2016 23:09:03 +0200 Subject: iio: accel: st_accel: add support to lng2dm add support to STMicroelectronics LNG2DM accelerometer to st_accel framework Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/accel/Kconfig | 3 +- drivers/iio/accel/st_accel.h | 1 + drivers/iio/accel/st_accel_core.c | 73 +++++++++++++++++++++++++++++++++++++++ drivers/iio/accel/st_accel_i2c.c | 5 +++ drivers/iio/accel/st_accel_spi.c | 1 + 5 files changed, 82 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index c6cc2c0909a1..c68bdb649005 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -127,7 +127,8 @@ config IIO_ST_ACCEL_3AXIS help Say yes here to build support for STMicroelectronics accelerometers: LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, - LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL. + LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL, + LNG2DM This driver can also be built as a module. If so, these modules will be created: diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index f8dfdb690563..7c231687109a 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -30,6 +30,7 @@ #define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel" #define LIS2DH12_ACCEL_DEV_NAME "lis2dh12_accel" #define LIS3L02DQ_ACCEL_DEV_NAME "lis3l02dq" +#define LNG2DM_ACCEL_DEV_NAME "lng2dm" /** * struct st_sensors_platform_data - default accel platform data diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index da3fb069ec5c..b242457d0c80 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -231,6 +231,12 @@ #define ST_ACCEL_7_DRDY_IRQ_INT1_MASK 0x04 #define ST_ACCEL_7_MULTIREAD_BIT false +/* CUSTOM VALUES FOR SENSOR 8 */ +#define ST_ACCEL_8_FS_AVL_2_GAIN IIO_G_TO_M_S_2(15600) +#define ST_ACCEL_8_FS_AVL_4_GAIN IIO_G_TO_M_S_2(31200) +#define ST_ACCEL_8_FS_AVL_8_GAIN IIO_G_TO_M_S_2(62500) +#define ST_ACCEL_8_FS_AVL_16_GAIN IIO_G_TO_M_S_2(187500) + static const struct iio_chan_spec st_accel_8bit_channels[] = { ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), @@ -726,6 +732,73 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .multi_read_bit = ST_ACCEL_7_MULTIREAD_BIT, .bootime = 2, }, + { + .wai = ST_ACCEL_1_WAI_EXP, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LNG2DM_ACCEL_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_accel_8bit_channels, + .odr = { + .addr = ST_ACCEL_1_ODR_ADDR, + .mask = ST_ACCEL_1_ODR_MASK, + .odr_avl = { + { 1, ST_ACCEL_1_ODR_AVL_1HZ_VAL, }, + { 10, ST_ACCEL_1_ODR_AVL_10HZ_VAL, }, + { 25, ST_ACCEL_1_ODR_AVL_25HZ_VAL, }, + { 50, ST_ACCEL_1_ODR_AVL_50HZ_VAL, }, + { 100, ST_ACCEL_1_ODR_AVL_100HZ_VAL, }, + { 200, ST_ACCEL_1_ODR_AVL_200HZ_VAL, }, + { 400, ST_ACCEL_1_ODR_AVL_400HZ_VAL, }, + { 1600, ST_ACCEL_1_ODR_AVL_1600HZ_VAL, }, + }, + }, + .pw = { + .addr = ST_ACCEL_1_ODR_ADDR, + .mask = ST_ACCEL_1_ODR_MASK, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = ST_ACCEL_1_FS_ADDR, + .mask = ST_ACCEL_1_FS_MASK, + .fs_avl = { + [0] = { + .num = ST_ACCEL_FS_AVL_2G, + .value = ST_ACCEL_1_FS_AVL_2_VAL, + .gain = ST_ACCEL_8_FS_AVL_2_GAIN, + }, + [1] = { + .num = ST_ACCEL_FS_AVL_4G, + .value = ST_ACCEL_1_FS_AVL_4_VAL, + .gain = ST_ACCEL_8_FS_AVL_4_GAIN, + }, + [2] = { + .num = ST_ACCEL_FS_AVL_8G, + .value = ST_ACCEL_1_FS_AVL_8_VAL, + .gain = ST_ACCEL_8_FS_AVL_8_GAIN, + }, + [3] = { + .num = ST_ACCEL_FS_AVL_16G, + .value = ST_ACCEL_1_FS_AVL_16_VAL, + .gain = ST_ACCEL_8_FS_AVL_16_GAIN, + }, + }, + }, + .drdy_irq = { + .addr = ST_ACCEL_1_DRDY_IRQ_ADDR, + .mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK, + .mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR, + .mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, + }, + .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT, + .bootime = 2, + }, }; static int st_accel_read_raw(struct iio_dev *indio_dev, diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index e9d427a5df7c..c0f8867aa1ea 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -84,6 +84,10 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,lis3l02dq", .data = LIS3L02DQ_ACCEL_DEV_NAME, }, + { + .compatible = "st,lng2dm-accel", + .data = LNG2DM_ACCEL_DEV_NAME, + }, {}, }; MODULE_DEVICE_TABLE(of, st_accel_of_match); @@ -135,6 +139,7 @@ static const struct i2c_device_id st_accel_id_table[] = { { LSM303AGR_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME }, { LIS3L02DQ_ACCEL_DEV_NAME }, + { LNG2DM_ACCEL_DEV_NAME }, {}, }; MODULE_DEVICE_TABLE(i2c, st_accel_id_table); diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index efd43941d45d..c25ac50d4600 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -60,6 +60,7 @@ static const struct spi_device_id st_accel_id_table[] = { { LSM303AGR_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME }, { LIS3L02DQ_ACCEL_DEV_NAME }, + { LNG2DM_ACCEL_DEV_NAME }, {}, }; MODULE_DEVICE_TABLE(spi, st_accel_id_table); -- cgit v1.2.3 From a3b6b4b63beda16f3e91fdd942bbaaaf6b1f8b25 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:12 -0400 Subject: staging: iio: tsl2583: add of_match table for device tree support Add device tree support for the tsl2583 IIO driver with no custom properties. Signed-off-by: Brian Masney Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/light/tsl2583.txt | 26 ++++++++++++++++++++++ drivers/staging/iio/light/tsl2583.c | 13 +++++++++++ 2 files changed, 39 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/light/tsl2583.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/light/tsl2583.txt b/Documentation/devicetree/bindings/iio/light/tsl2583.txt new file mode 100644 index 000000000000..8e2066c83f70 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/tsl2583.txt @@ -0,0 +1,26 @@ +* TAOS TSL 2580/2581/2583 ALS sensor + +Required properties: + + - compatible: Should be one of + "amstaos,tsl2580" + "amstaos,tsl2581" + "amstaos,tsl2583" + - reg: the I2C address of the device + +Optional properties: + + - interrupt-parent: should be the phandle for the interrupt controller + - interrupts: the sole interrupt generated by the device + + Refer to interrupt-controller/interrupts.txt for generic interrupt client + node bindings. + + - vcc-supply: phandle to the regulator that provides power to the sensor. + +Example: + +tsl2581@29 { + compatible = "amstaos,tsl2581"; + reg = <0x29>; +}; diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 08f1583ee34e..fd4b6efd3016 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -947,11 +947,24 @@ static struct i2c_device_id taos_idtable[] = { }; MODULE_DEVICE_TABLE(i2c, taos_idtable); +#ifdef CONFIG_OF +static const struct of_device_id taos2583_of_match[] = { + { .compatible = "amstaos,tsl2580", }, + { .compatible = "amstaos,tsl2581", }, + { .compatible = "amstaos,tsl2583", }, + { }, +}; +MODULE_DEVICE_TABLE(of, taos2583_of_match); +#else +#define taos2583_of_match NULL +#endif + /* Driver definition */ static struct i2c_driver taos_driver = { .driver = { .name = "tsl2583", .pm = TAOS_PM_OPS, + .of_match_table = taos2583_of_match, }, .id_table = taos_idtable, .probe = taos_probe, -- cgit v1.2.3 From 9d5f36d2419e488dfa6ba38e4cfc1e90f65a4cff Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:13 -0400 Subject: staging: iio: tsl2583: check for error code from i2c_smbus_read_byte() taos_i2c_read() and taos_als_calibrate() does not check to see if the value returned by i2c_smbus_read_byte() was an error code. This patch adds the appropriate error handling. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index fd4b6efd3016..35c1696a71c5 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -171,7 +171,14 @@ taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) return ret; } /* read the data */ - *val = i2c_smbus_read_byte(client); + ret = i2c_smbus_read_byte(client); + if (ret < 0) { + dev_err(&client->dev, + "%s failed to read byte after writing to register %x\n", + __func__, reg); + return ret; + } + *val = ret; val++; reg++; } @@ -355,6 +362,13 @@ static int taos_als_calibrate(struct iio_dev *indio_dev) } reg_val = i2c_smbus_read_byte(chip->client); + if (reg_val < 0) { + dev_err(&chip->client->dev, + "%s failed to read after writing to the CNTRL register\n", + __func__); + return ret; + } + if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) != (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) { dev_err(&chip->client->dev, @@ -371,6 +385,12 @@ static int taos_als_calibrate(struct iio_dev *indio_dev) return ret; } reg_val = i2c_smbus_read_byte(chip->client); + if (reg_val < 0) { + dev_err(&chip->client->dev, + "%s failed to read after writing to the STATUS register\n", + __func__); + return ret; + } if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { dev_err(&chip->client->dev, -- cgit v1.2.3 From 20d823afff200fa131eb0dfaf6d33d8863ba8acf Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:14 -0400 Subject: staging: iio: tsl2583: return proper error code instead of -1 taos_als_calibrate() has a code path where -1 is returned. This patch changes the code so that a proper error code is returned. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 35c1696a71c5..47fd373e1734 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -373,7 +373,7 @@ static int taos_als_calibrate(struct iio_dev *indio_dev) != (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) { dev_err(&chip->client->dev, "taos_als_calibrate failed: device not powered on with ADC enabled\n"); - return -1; + return -EINVAL; } ret = i2c_smbus_write_byte(chip->client, -- cgit v1.2.3 From 27f4fabd4f9455852ebff253b21423406f24878b Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:15 -0400 Subject: staging: iio: tsl2583: remove redundant power_state sysfs attribute IIO devices have a /sys/bus/iio/devices/iio:deviceX/power/ directory that allows viewing and controling various power parameters. The tsl2583 driver also has an additional custom sysfs attribute named power_state that is not needed. This patch removes the redundant power_state sysfs attribute. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 47fd373e1734..f8ccb4def0a9 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -511,33 +511,6 @@ static int taos_chip_off(struct iio_dev *indio_dev) /* Sysfs Interface Functions */ -static ssize_t taos_power_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", chip->taos_chip_status); -} - -static ssize_t taos_power_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - int value; - - if (kstrtoint(buf, 0, &value)) - return -EINVAL; - - if (!value) - taos_chip_off(indio_dev); - else - taos_chip_on(indio_dev); - - return len; -} - static ssize_t taos_gain_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -785,9 +758,6 @@ static ssize_t taos_luxtable_store(struct device *dev, return len; } -static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, - taos_power_state_show, taos_power_state_store); - static DEVICE_ATTR(illuminance0_calibscale, S_IRUGO | S_IWUSR, taos_gain_show, taos_gain_store); static DEVICE_ATTR(illuminance0_calibscale_available, S_IRUGO, @@ -810,7 +780,6 @@ static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR, taos_luxtable_show, taos_luxtable_store); static struct attribute *sysfs_attrs_ctrl[] = { - &dev_attr_power_state.attr, &dev_attr_illuminance0_calibscale.attr, /* Gain */ &dev_attr_illuminance0_calibscale_available.attr, &dev_attr_illuminance0_integration_time.attr, /* I time*/ -- cgit v1.2.3 From 84bc1704cbf438761f870ca4ce19bbfe5b949fb6 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:16 -0400 Subject: staging: iio: tsl2583: check return values from taos_chip_{on,off} The return value from taos_chip_on() and taos_chip_off() was not checked in taos_luxtable_store() and taos_probe(). This patch adds proper error checking to these function calls. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index f8ccb4def0a9..e975bba0c786 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -727,7 +727,7 @@ static ssize_t taos_luxtable_store(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); int value[ARRAY_SIZE(taos_device_lux) * 3 + 1]; - int n; + int n, ret = -EINVAL; get_options(buf, ARRAY_SIZE(value), value); @@ -739,23 +739,31 @@ static ssize_t taos_luxtable_store(struct device *dev, n = value[0]; if ((n % 3) || n < 6 || n > ((ARRAY_SIZE(taos_device_lux) - 1) * 3)) { dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n); - return -EINVAL; + goto done; } if ((value[(n - 2)] | value[(n - 1)] | value[n]) != 0) { dev_info(dev, "LUX TABLE INPUT ERROR 2 Value[0]=%d\n", n); - return -EINVAL; + goto done; } - if (chip->taos_chip_status == TSL258X_CHIP_WORKING) - taos_chip_off(indio_dev); + if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { + ret = taos_chip_off(indio_dev); + if (ret < 0) + goto done; + } /* Zero out the table */ memset(taos_device_lux, 0, sizeof(taos_device_lux)); memcpy(taos_device_lux, &value[1], (value[0] * 4)); - taos_chip_on(indio_dev); + ret = taos_chip_on(indio_dev); + if (ret < 0) + goto done; - return len; + ret = len; + +done: + return ret; } static DEVICE_ATTR(illuminance0_calibscale, S_IRUGO | S_IWUSR, @@ -883,7 +891,9 @@ static int taos_probe(struct i2c_client *clientp, taos_defaults(chip); /* Make sure the chip is on */ - taos_chip_on(indio_dev); + ret = taos_chip_on(indio_dev); + if (ret < 0) + return ret; dev_info(&clientp->dev, "Light sensor found.\n"); return 0; -- cgit v1.2.3 From b3d941550d9d3753ed76f09c9b1015c777f41f17 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:17 -0400 Subject: staging: iio: tsl2583: convert to use iio_chan_spec and {read,write}_raw The tsl2583 driver directly creates sysfs attributes that should instead be created by the IIO core on behalf of the driver. This patch adds the iio_chan_spec array, the relevant info_mask elements and the read_raw() and write_raw() functions to take advantage of features provided by the IIO core. These sysfs attributes were migrated with this patch: illuminance0_input, illuminance0_calibbias, illuminance0_integration_time. This also exposes the raw values read from the two channels on the sensor. With this change, these four sysfs entries have their prefix changed from illuminance0_ to in_illuminance_. This is deemed to be acceptable since none of the IIO light drivers in mainline use the illuminance0_ prefix, however 8 of the IIO light drivers in mainline use the in_illuminance_ prefix. Also fix the units of integration_time to meet with the ABI. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 236 ++++++++++++++++++++++-------------- 1 file changed, 143 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index e975bba0c786..6a61a86d0d40 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -211,28 +211,23 @@ static int taos_get_lux(struct iio_dev *indio_dev) u32 ch0lux = 0; u32 ch1lux = 0; - if (mutex_trylock(&chip->als_mutex) == 0) { - dev_info(&chip->client->dev, "taos_get_lux device is busy\n"); - return chip->als_cur_info.lux; /* busy, so return LAST VALUE */ - } - if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { /* device is not enabled */ dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n"); ret = -EBUSY; - goto out_unlock; + goto done; } ret = taos_i2c_read(chip->client, (TSL258X_CMD_REG), &buf[0], 1); if (ret < 0) { dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n"); - goto out_unlock; + goto done; } /* is data new & valid */ if (!(buf[0] & TSL258X_STA_ADC_INTR)) { dev_err(&chip->client->dev, "taos_get_lux data not valid\n"); ret = chip->als_cur_info.lux; /* return LAST VALUE */ - goto out_unlock; + goto done; } for (i = 0; i < 4; i++) { @@ -243,7 +238,7 @@ static int taos_get_lux(struct iio_dev *indio_dev) dev_err(&chip->client->dev, "taos_get_lux failed to read register %x\n", reg); - goto out_unlock; + goto done; } } @@ -259,7 +254,7 @@ static int taos_get_lux(struct iio_dev *indio_dev) dev_err(&chip->client->dev, "taos_i2c_write_command failed in taos_get_lux, err = %d\n", ret); - goto out_unlock; /* have no data, so return failure */ + goto done; /* have no data, so return failure */ } /* extract ALS/lux data */ @@ -276,7 +271,7 @@ static int taos_get_lux(struct iio_dev *indio_dev) /* have no data, so return LAST VALUE */ ret = 0; chip->als_cur_info.lux = 0; - goto out_unlock; + goto done; } /* calculate ratio */ ratio = (ch1 << 15) / ch0; @@ -302,7 +297,7 @@ static int taos_get_lux(struct iio_dev *indio_dev) dev_dbg(&chip->client->dev, "No Data - Return last value\n"); ret = 0; chip->als_cur_info.lux = 0; - goto out_unlock; + goto done; } /* adjust for active time scale */ @@ -334,8 +329,7 @@ return_max: chip->als_cur_info.lux = lux; ret = lux; -out_unlock: - mutex_unlock(&chip->als_mutex); +done: return ret; } @@ -575,69 +569,12 @@ static ssize_t taos_gain_available_show(struct device *dev, return sprintf(buf, "%s\n", "1 8 16 111"); } -static ssize_t taos_als_time_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", chip->taos_settings.als_time); -} - -static ssize_t taos_als_time_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); - int value; - - if (kstrtoint(buf, 0, &value)) - return -EINVAL; - - if ((value < 50) || (value > 650)) - return -EINVAL; - - if (value % 50) - return -EINVAL; - - chip->taos_settings.als_time = value; - - return len; -} - static ssize_t taos_als_time_available_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", - "50 100 150 200 250 300 350 400 450 500 550 600 650"); -} - -static ssize_t taos_als_trim_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim); -} - -static ssize_t taos_als_trim_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); - int value; - - if (kstrtoint(buf, 0, &value)) - return -EINVAL; - - if (value) - chip->taos_settings.als_gain_trim = value; - - return len; + "0.000050 0.000100 0.000150 0.000200 0.000250 0.000300 0.000350 0.000400 0.000450 0.000500 0.000550 0.000600 0.000650"); } static ssize_t taos_als_cal_target_show(struct device *dev, @@ -667,18 +604,6 @@ static ssize_t taos_als_cal_target_store(struct device *dev, return len; } -static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int ret; - - ret = taos_get_lux(dev_to_iio_dev(dev)); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", ret); -} - static ssize_t taos_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -771,18 +696,12 @@ static DEVICE_ATTR(illuminance0_calibscale, S_IRUGO | S_IWUSR, static DEVICE_ATTR(illuminance0_calibscale_available, S_IRUGO, taos_gain_available_show, NULL); -static DEVICE_ATTR(illuminance0_integration_time, S_IRUGO | S_IWUSR, - taos_als_time_show, taos_als_time_store); static DEVICE_ATTR(illuminance0_integration_time_available, S_IRUGO, taos_als_time_available_show, NULL); -static DEVICE_ATTR(illuminance0_calibbias, S_IRUGO | S_IWUSR, - taos_als_trim_show, taos_als_trim_store); - static DEVICE_ATTR(illuminance0_input_target, S_IRUGO | S_IWUSR, taos_als_cal_target_show, taos_als_cal_target_store); -static DEVICE_ATTR(illuminance0_input, S_IRUGO, taos_lux_show, NULL); static DEVICE_ATTR(illuminance0_calibrate, S_IWUSR, NULL, taos_do_calibrate); static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR, taos_luxtable_show, taos_luxtable_store); @@ -790,11 +709,8 @@ static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR, static struct attribute *sysfs_attrs_ctrl[] = { &dev_attr_illuminance0_calibscale.attr, /* Gain */ &dev_attr_illuminance0_calibscale_available.attr, - &dev_attr_illuminance0_integration_time.attr, /* I time*/ &dev_attr_illuminance0_integration_time_available.attr, - &dev_attr_illuminance0_calibbias.attr, /* trim */ &dev_attr_illuminance0_input_target.attr, - &dev_attr_illuminance0_input.attr, &dev_attr_illuminance0_calibrate.attr, &dev_attr_illuminance0_lux_table.attr, NULL @@ -810,9 +726,141 @@ static int taos_tsl258x_device(unsigned char *bufp) return ((bufp[TSL258X_CHIPID] & 0xf0) == 0x90); } +static const struct iio_chan_spec tsl2583_channels[] = { + { + .type = IIO_LIGHT, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_IR, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, + { + .type = IIO_LIGHT, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_BOTH, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_INT_TIME), + }, +}; + +static int tsl2583_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct tsl2583_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(&chip->als_mutex); + + if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { + ret = -EBUSY; + goto read_done; + } + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (chan->type == IIO_LIGHT) { + ret = taos_get_lux(indio_dev); + if (ret < 0) + goto read_done; + + /* + * From page 20 of the TSL2581, TSL2583 data + * sheet (TAOS134 − MARCH 2011): + * + * One of the photodiodes (channel 0) is + * sensitive to both visible and infrared light, + * while the second photodiode (channel 1) is + * sensitive primarily to infrared light. + */ + if (chan->channel2 == IIO_MOD_LIGHT_BOTH) + *val = chip->als_cur_info.als_ch0; + else + *val = chip->als_cur_info.als_ch1; + + ret = IIO_VAL_INT; + } + break; + case IIO_CHAN_INFO_PROCESSED: + if (chan->type == IIO_LIGHT) { + ret = taos_get_lux(indio_dev); + if (ret < 0) + goto read_done; + + *val = ret; + ret = IIO_VAL_INT; + } + break; + case IIO_CHAN_INFO_CALIBBIAS: + if (chan->type == IIO_LIGHT) { + *val = chip->taos_settings.als_gain_trim; + ret = IIO_VAL_INT; + } + break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type == IIO_LIGHT) { + *val = 0; + *val2 = chip->taos_settings.als_time; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; + default: + break; + } + +read_done: + mutex_unlock(&chip->als_mutex); + + return ret; +} + +static int tsl2583_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct tsl2583_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(&chip->als_mutex); + + if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { + ret = -EBUSY; + goto write_done; + } + + switch (mask) { + case IIO_CHAN_INFO_CALIBBIAS: + if (chan->type == IIO_LIGHT) { + chip->taos_settings.als_gain_trim = val; + ret = 0; + } + break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type == IIO_LIGHT && !val && val2 >= 50 && + val2 <= 650 && !(val2 % 50)) { + chip->taos_settings.als_time = val2; + ret = 0; + } + break; + default: + break; + } + +write_done: + mutex_unlock(&chip->als_mutex); + + return ret; +} + static const struct iio_info tsl2583_info = { .attrs = &tsl2583_attribute_group, .driver_module = THIS_MODULE, + .read_raw = tsl2583_read_raw, + .write_raw = tsl2583_write_raw, }; /* @@ -878,6 +926,8 @@ static int taos_probe(struct i2c_client *clientp, } indio_dev->info = &tsl2583_info; + indio_dev->channels = tsl2583_channels; + indio_dev->num_channels = ARRAY_SIZE(tsl2583_channels); indio_dev->dev.parent = &clientp->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = chip->client->name; -- cgit v1.2.3 From 143c30f4a51ebff3474643994499468cf56240af Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:18 -0400 Subject: staging: iio: tsl2583: convert illuminance0_calibscale sysfs attr to use iio_chan_spec The illuminance0_calibscale sysfs attribute is not currently created by the IIO core. This patch adds the appropriate mask to iio_chan_spec, along with the appropriate data handling in the read_raw() and write_raw() functions, so that the sysfs attribute is created by the IIO core. With this change, this sysfs entry will have its prefix changed from illuminance0_ to in_illuminance_. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 89 +++++++++++-------------------------- 1 file changed, 25 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 6a61a86d0d40..bfff6ca54fe5 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -124,14 +124,15 @@ static struct taos_lux taos_device_lux[11] = { struct gainadj { s16 ch0; s16 ch1; + s16 mean; }; /* Index = (0 - 3) Used to validate the gain selection index */ static const struct gainadj gainadj[] = { - { 1, 1 }, - { 8, 8 }, - { 16, 16 }, - { 107, 115 } + { 1, 1, 1 }, + { 8, 8, 8 }, + { 16, 16, 16 }, + { 107, 115, 111 } }; /* @@ -505,63 +506,6 @@ static int taos_chip_off(struct iio_dev *indio_dev) /* Sysfs Interface Functions */ -static ssize_t taos_gain_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); - char gain[4] = {0}; - - switch (chip->taos_settings.als_gain) { - case 0: - strcpy(gain, "001"); - break; - case 1: - strcpy(gain, "008"); - break; - case 2: - strcpy(gain, "016"); - break; - case 3: - strcpy(gain, "111"); - break; - } - - return sprintf(buf, "%s\n", gain); -} - -static ssize_t taos_gain_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); - int value; - - if (kstrtoint(buf, 0, &value)) - return -EINVAL; - - switch (value) { - case 1: - chip->taos_settings.als_gain = 0; - break; - case 8: - chip->taos_settings.als_gain = 1; - break; - case 16: - chip->taos_settings.als_gain = 2; - break; - case 111: - chip->taos_settings.als_gain = 3; - break; - default: - dev_err(dev, "Invalid Gain Index (must be 1,8,16,111)\n"); - return -1; - } - - return len; -} - static ssize_t taos_gain_available_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -691,8 +635,6 @@ done: return ret; } -static DEVICE_ATTR(illuminance0_calibscale, S_IRUGO | S_IWUSR, - taos_gain_show, taos_gain_store); static DEVICE_ATTR(illuminance0_calibscale_available, S_IRUGO, taos_gain_available_show, NULL); @@ -707,7 +649,6 @@ static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR, taos_luxtable_show, taos_luxtable_store); static struct attribute *sysfs_attrs_ctrl[] = { - &dev_attr_illuminance0_calibscale.attr, /* Gain */ &dev_attr_illuminance0_calibscale_available.attr, &dev_attr_illuminance0_integration_time_available.attr, &dev_attr_illuminance0_input_target.attr, @@ -743,6 +684,7 @@ static const struct iio_chan_spec tsl2583_channels[] = { .type = IIO_LIGHT, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INT_TIME), }, }; @@ -801,6 +743,12 @@ static int tsl2583_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; } break; + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_LIGHT) { + *val = gainadj[chip->taos_settings.als_gain].mean; + ret = IIO_VAL_INT; + } + break; case IIO_CHAN_INFO_INT_TIME: if (chan->type == IIO_LIGHT) { *val = 0; @@ -839,6 +787,19 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev, ret = 0; } break; + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_LIGHT) { + int i; + + for (i = 0; i < ARRAY_SIZE(gainadj); i++) { + if (gainadj[i].mean == val) { + chip->taos_settings.als_gain = i; + ret = 0; + break; + } + } + } + break; case IIO_CHAN_INFO_INT_TIME: if (chan->type == IIO_LIGHT && !val && val2 >= 50 && val2 <= 650 && !(val2 % 50)) { -- cgit v1.2.3 From b2fa81be96ca315a164ef7bc1d87fbf025fd9954 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:19 -0400 Subject: staging: iio: tsl2583: use IIO_*_ATTR* macros to create sysfs entries Use the IIO_CONST_ATTR, IIO_DEVICE_ATTR_RW, and IIO_DEVICE_ATTR_WO macros for creating the in_illuminance_calibscale_available, in_illuminance_integration_time_available, in_illuminance_input_target, in_illuminance_calibrate, and in_illuminance_lux_table sysfs entries. Previously these sysfs entries were prefixed with illuminance0_, however they are now prefixed with in_illuminance_ to make these sysfs entries consistent with how the IIO core is creating the other sysfs entries. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 73 ++++++++++++++----------------------- 1 file changed, 27 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index bfff6ca54fe5..14623740621d 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -29,6 +29,7 @@ #include #include #include +#include #define TSL258X_MAX_DEVICE_REGS 32 @@ -506,24 +507,9 @@ static int taos_chip_off(struct iio_dev *indio_dev) /* Sysfs Interface Functions */ -static ssize_t taos_gain_available_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%s\n", "1 8 16 111"); -} - -static ssize_t taos_als_time_available_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%s\n", - "0.000050 0.000100 0.000150 0.000200 0.000250 0.000300 0.000350 0.000400 0.000450 0.000500 0.000550 0.000600 0.000650"); -} - -static ssize_t taos_als_cal_target_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t in_illuminance_input_target_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); @@ -531,9 +517,9 @@ static ssize_t taos_als_cal_target_show(struct device *dev, return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target); } -static ssize_t taos_als_cal_target_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t in_illuminance_input_target_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); @@ -548,9 +534,9 @@ static ssize_t taos_als_cal_target_store(struct device *dev, return len; } -static ssize_t taos_do_calibrate(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t in_illuminance_calibrate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); int value; @@ -564,8 +550,9 @@ static ssize_t taos_do_calibrate(struct device *dev, return len; } -static ssize_t taos_luxtable_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t in_illuminance_lux_table_show(struct device *dev, + struct device_attribute *attr, + char *buf) { int i; int offset = 0; @@ -589,9 +576,9 @@ static ssize_t taos_luxtable_show(struct device *dev, return offset; } -static ssize_t taos_luxtable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t in_illuminance_lux_table_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); @@ -635,25 +622,19 @@ done: return ret; } -static DEVICE_ATTR(illuminance0_calibscale_available, S_IRUGO, - taos_gain_available_show, NULL); - -static DEVICE_ATTR(illuminance0_integration_time_available, S_IRUGO, - taos_als_time_available_show, NULL); - -static DEVICE_ATTR(illuminance0_input_target, S_IRUGO | S_IWUSR, - taos_als_cal_target_show, taos_als_cal_target_store); - -static DEVICE_ATTR(illuminance0_calibrate, S_IWUSR, NULL, taos_do_calibrate); -static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR, - taos_luxtable_show, taos_luxtable_store); +static IIO_CONST_ATTR(in_illuminance_calibscale_available, "1 8 16 111"); +static IIO_CONST_ATTR(in_illuminance_integration_time_available, + "0.000050 0.000100 0.000150 0.000200 0.000250 0.000300 0.000350 0.000400 0.000450 0.000500 0.000550 0.000600 0.000650"); +static IIO_DEVICE_ATTR_RW(in_illuminance_input_target, 0); +static IIO_DEVICE_ATTR_WO(in_illuminance_calibrate, 0); +static IIO_DEVICE_ATTR_RW(in_illuminance_lux_table, 0); static struct attribute *sysfs_attrs_ctrl[] = { - &dev_attr_illuminance0_calibscale_available.attr, - &dev_attr_illuminance0_integration_time_available.attr, - &dev_attr_illuminance0_input_target.attr, - &dev_attr_illuminance0_calibrate.attr, - &dev_attr_illuminance0_lux_table.attr, + &iio_const_attr_in_illuminance_calibscale_available.dev_attr.attr, + &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr, + &iio_dev_attr_in_illuminance_input_target.dev_attr.attr, + &iio_dev_attr_in_illuminance_calibrate.dev_attr.attr, + &iio_dev_attr_in_illuminance_lux_table.dev_attr.attr, NULL }; -- cgit v1.2.3 From f375a49f710535b0ac2923274e2a33f04e02514d Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:20 -0400 Subject: staging: iio: tsl2583: add error code to sysfs store functions in_illuminance_input_target_store() and in_illuminance_calibrate_store() validated the data from userspace, however it would not return an error code to userspace if an invalid value was passed in. This patch changes these functions so that they return -EINVAL if invalid data is passed in. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 14623740621d..98afa5bdfb29 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -525,11 +525,10 @@ static ssize_t in_illuminance_input_target_store(struct device *dev, struct tsl2583_chip *chip = iio_priv(indio_dev); int value; - if (kstrtoint(buf, 0, &value)) + if (kstrtoint(buf, 0, &value) || !value) return -EINVAL; - if (value) - chip->taos_settings.als_cal_target = value; + chip->taos_settings.als_cal_target = value; return len; } @@ -541,11 +540,10 @@ static ssize_t in_illuminance_calibrate_store(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); int value; - if (kstrtoint(buf, 0, &value)) + if (kstrtoint(buf, 0, &value) || value != 1) return -EINVAL; - if (value == 1) - taos_als_calibrate(indio_dev); + taos_als_calibrate(indio_dev); return len; } -- cgit v1.2.3 From 1b7e9e2cbd6478e0ebe40639ea36fefd3ffcf916 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 28 Oct 2016 06:00:21 -0400 Subject: staging: iio: tsl2583: add locking to sysfs attributes in_illuminance_input_target_show(), in_illuminance_input_target_store(), in_illuminance_calibrate_store(), and in_illuminance_lux_table_store() accesses data from the tsl2583_chip struct. Some of these fields can be modified by other parts of the driver concurrently. This patch adds the mutex locking to these sysfs attributes. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 98afa5bdfb29..49b19f5c1d84 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -513,8 +513,13 @@ static ssize_t in_illuminance_input_target_show(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); + int ret; + + mutex_lock(&chip->als_mutex); + ret = sprintf(buf, "%d\n", chip->taos_settings.als_cal_target); + mutex_unlock(&chip->als_mutex); - return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target); + return ret; } static ssize_t in_illuminance_input_target_store(struct device *dev, @@ -528,7 +533,9 @@ static ssize_t in_illuminance_input_target_store(struct device *dev, if (kstrtoint(buf, 0, &value) || !value) return -EINVAL; + mutex_lock(&chip->als_mutex); chip->taos_settings.als_cal_target = value; + mutex_unlock(&chip->als_mutex); return len; } @@ -538,12 +545,15 @@ static ssize_t in_illuminance_calibrate_store(struct device *dev, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tsl2583_chip *chip = iio_priv(indio_dev); int value; if (kstrtoint(buf, 0, &value) || value != 1) return -EINVAL; + mutex_lock(&chip->als_mutex); taos_als_calibrate(indio_dev); + mutex_unlock(&chip->als_mutex); return len; } @@ -583,6 +593,8 @@ static ssize_t in_illuminance_lux_table_store(struct device *dev, int value[ARRAY_SIZE(taos_device_lux) * 3 + 1]; int n, ret = -EINVAL; + mutex_lock(&chip->als_mutex); + get_options(buf, ARRAY_SIZE(value), value); /* We now have an array of ints starting at value[1], and @@ -617,6 +629,8 @@ static ssize_t in_illuminance_lux_table_store(struct device *dev, ret = len; done: + mutex_unlock(&chip->als_mutex); + return ret; } -- cgit v1.2.3 From 579d542534c96c9109b63e79a2c6d22e2bca21cc Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Fri, 28 Oct 2016 16:26:52 +0800 Subject: staging: iio: cdc: ad7746: add additional config defines Introduce defines for shifting and mask under the config register for better readability. Also, introduce helper variables for index calculation. Signed-off-by: Eva Rachel Retuya Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index a5828f9aa437..81f8b9ee1120 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -70,8 +70,10 @@ #define AD7746_EXCSETUP_EXCLVL(x) (((x) & 0x3) << 0) /* Config Register Bit Designations (AD7746_REG_CFG) */ -#define AD7746_CONF_VTFS(x) ((x) << 6) -#define AD7746_CONF_CAPFS(x) ((x) << 3) +#define AD7746_CONF_VTFS_SHIFT 6 +#define AD7746_CONF_CAPFS_SHIFT 3 +#define AD7746_CONF_VTFS_MASK GENMASK(7, 6) +#define AD7746_CONF_CAPFS_MASK GENMASK(5, 3) #define AD7746_CONF_MODE_IDLE (0 << 0) #define AD7746_CONF_MODE_CONT_CONV (1 << 0) #define AD7746_CONF_MODE_SINGLE_CONV (2 << 0) @@ -217,15 +219,16 @@ static int ad7746_select_channel(struct iio_dev *indio_dev, struct iio_chan_spec const *chan) { struct ad7746_chip_info *chip = iio_priv(indio_dev); - int ret, delay; + int ret, delay, idx; u8 vt_setup, cap_setup; switch (chan->type) { case IIO_CAPACITANCE: cap_setup = (chan->address & 0xFF) | AD7746_CAPSETUP_CAPEN; vt_setup = chip->vt_setup & ~AD7746_VTSETUP_VTEN; - delay = ad7746_cap_filter_rate_table[(chip->config >> 3) & - 0x7][1]; + idx = (chip->config & AD7746_CONF_CAPFS_MASK) >> + AD7746_CONF_CAPFS_SHIFT; + delay = ad7746_cap_filter_rate_table[idx][1]; if (chip->capdac_set != chan->channel) { ret = i2c_smbus_write_byte_data(chip->client, @@ -246,8 +249,9 @@ static int ad7746_select_channel(struct iio_dev *indio_dev, case IIO_TEMP: vt_setup = (chan->address & 0xFF) | AD7746_VTSETUP_VTEN; cap_setup = chip->cap_setup & ~AD7746_CAPSETUP_CAPEN; - delay = ad7746_cap_filter_rate_table[(chip->config >> 6) & - 0x3][1]; + idx = (chip->config & AD7746_CONF_VTFS_MASK) >> + AD7746_CONF_VTFS_SHIFT; + delay = ad7746_cap_filter_rate_table[idx][1]; break; default: return -EINVAL; @@ -369,8 +373,8 @@ static int ad7746_store_cap_filter_rate_setup(struct ad7746_chip_info *chip, if (i >= ARRAY_SIZE(ad7746_cap_filter_rate_table)) i = ARRAY_SIZE(ad7746_cap_filter_rate_table) - 1; - chip->config &= ~AD7746_CONF_CAPFS(0x7); - chip->config |= AD7746_CONF_CAPFS(i); + chip->config &= ~AD7746_CONF_CAPFS_MASK; + chip->config |= i << AD7746_CONF_CAPFS_SHIFT; return 0; } @@ -387,8 +391,8 @@ static int ad7746_store_vt_filter_rate_setup(struct ad7746_chip_info *chip, if (i >= ARRAY_SIZE(ad7746_vt_filter_rate_table)) i = ARRAY_SIZE(ad7746_vt_filter_rate_table) - 1; - chip->config &= ~AD7746_CONF_VTFS(0x3); - chip->config |= AD7746_CONF_VTFS(i); + chip->config &= ~AD7746_CONF_VTFS_MASK; + chip->config |= i << AD7746_CONF_VTFS_SHIFT; return 0; } @@ -527,7 +531,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, long mask) { struct ad7746_chip_info *chip = iio_priv(indio_dev); - int ret, delay; + int ret, delay, idx; u8 regval, reg; mutex_lock(&indio_dev->mlock); @@ -635,13 +639,15 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_CAPACITANCE: - *val = ad7746_cap_filter_rate_table[ - (chip->config >> 3) & 0x7][0]; + idx = (chip->config & AD7746_CONF_CAPFS_MASK) >> + AD7746_CONF_CAPFS_SHIFT; + *val = ad7746_cap_filter_rate_table[idx][0]; ret = IIO_VAL_INT; break; case IIO_VOLTAGE: - *val = ad7746_vt_filter_rate_table[ - (chip->config >> 6) & 0x3][0]; + idx = (chip->config & AD7746_CONF_VTFS_MASK) >> + AD7746_CONF_VTFS_SHIFT; + *val = ad7746_vt_filter_rate_table[idx][0]; ret = IIO_VAL_INT; break; default: -- cgit v1.2.3 From c8a220c686a596a4f669b441b2ea40486dea0513 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 May 2016 13:51:08 +0100 Subject: drm/armada: add tracing support Add tracing support to the Armada video overlay and interrupt code. Signed-off-by: Russell King --- drivers/gpu/drm/armada/Makefile | 2 +- drivers/gpu/drm/armada/armada_crtc.c | 3 ++ drivers/gpu/drm/armada/armada_overlay.c | 7 ++++ drivers/gpu/drm/armada/armada_trace.c | 4 ++ drivers/gpu/drm/armada/armada_trace.h | 66 +++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/armada/armada_trace.c create mode 100644 drivers/gpu/drm/armada/armada_trace.h (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile index ffd673615772..a18f156c8b66 100644 --- a/drivers/gpu/drm/armada/Makefile +++ b/drivers/gpu/drm/armada/Makefile @@ -1,5 +1,5 @@ armada-y := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \ - armada_gem.o armada_overlay.o + armada_gem.o armada_overlay.o armada_trace.o armada-y += armada_510.o armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 2f58e9e2a59c..135ad844fbb8 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -18,6 +18,7 @@ #include "armada_fb.h" #include "armada_gem.h" #include "armada_hw.h" +#include "armada_trace.h" struct armada_frame_work { struct armada_plane_work work; @@ -464,6 +465,8 @@ static irqreturn_t armada_drm_irq(int irq, void *arg) */ writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR); + trace_armada_drm_irq(&dcrtc->crtc, stat); + /* Mask out those interrupts we haven't enabled */ v = stat & dcrtc->irq_ena; diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 1ee707ef6b8d..94af7c93276e 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -15,6 +15,7 @@ #include "armada_hw.h" #include #include "armada_ioctlP.h" +#include "armada_trace.h" struct armada_ovl_plane_properties { uint32_t colorkey_yr; @@ -87,6 +88,8 @@ static void armada_ovl_plane_work(struct armada_crtc *dcrtc, { struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base); + trace_armada_ovl_plane_work(&dcrtc->crtc, &plane->base); + armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); armada_ovl_retire_fb(dplane, NULL); } @@ -120,6 +123,10 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, bool visible; int ret; + trace_armada_ovl_plane_update(plane, crtc, fb, + crtc_x, crtc_y, crtc_w, crtc_h, + src_x, src_y, src_w, src_h); + ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip, BIT(DRM_ROTATE_0), 0, INT_MAX, true, false, &visible); diff --git a/drivers/gpu/drm/armada/armada_trace.c b/drivers/gpu/drm/armada/armada_trace.c new file mode 100644 index 000000000000..068b336ba75f --- /dev/null +++ b/drivers/gpu/drm/armada/armada_trace.c @@ -0,0 +1,4 @@ +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "armada_trace.h" +#endif diff --git a/drivers/gpu/drm/armada/armada_trace.h b/drivers/gpu/drm/armada/armada_trace.h new file mode 100644 index 000000000000..dc0cba70fd1a --- /dev/null +++ b/drivers/gpu/drm/armada/armada_trace.h @@ -0,0 +1,66 @@ +#if !defined(ARMADA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define ARMADA_TRACE_H + +#include +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM armada +#define TRACE_INCLUDE_FILE armada_trace + +TRACE_EVENT(armada_drm_irq, + TP_PROTO(struct drm_crtc *crtc, u32 stat), + TP_ARGS(crtc, stat), + TP_STRUCT__entry( + __field(struct drm_crtc *, crtc) + __field(u32, stat) + ), + TP_fast_assign( + __entry->crtc = crtc; + __entry->stat = stat; + ), + TP_printk("crtc %p stat 0x%08x", + __entry->crtc, __entry->stat) +); + +TRACE_EVENT(armada_ovl_plane_update, + TP_PROTO(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, + uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h), + TP_ARGS(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h), + TP_STRUCT__entry( + __field(struct drm_plane *, plane) + __field(struct drm_crtc *, crtc) + __field(struct drm_framebuffer *, fb) + ), + TP_fast_assign( + __entry->plane = plane; + __entry->crtc = crtc; + __entry->fb = fb; + ), + TP_printk("plane %p crtc %p fb %p", + __entry->plane, __entry->crtc, __entry->fb) +); + +TRACE_EVENT(armada_ovl_plane_work, + TP_PROTO(struct drm_crtc *crtc, struct drm_plane *plane), + TP_ARGS(crtc, plane), + TP_STRUCT__entry( + __field(struct drm_plane *, plane) + __field(struct drm_crtc *, crtc) + ), + TP_fast_assign( + __entry->plane = plane; + __entry->crtc = crtc; + ), + TP_printk("plane %p crtc %p", + __entry->plane, __entry->crtc) +); + +#endif + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#include -- cgit v1.2.3 From ec6fb1590a17468be36c529983981273a345abca Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 25 Jul 2016 15:16:11 +0100 Subject: drm/armada: clean up armada_drm_plane_work_run() Make armada_drm_plane_work_run() take the drm_plane pointer rather than our private pointer. This allows us to localise the conversion between these two pointers inside armada_drm_plane_work_run(), rather than at every call site. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 135ad844fbb8..9ec7e6136bcc 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -193,17 +193,18 @@ static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb, } static void armada_drm_plane_work_run(struct armada_crtc *dcrtc, - struct armada_plane *plane) + struct drm_plane *plane) { - struct armada_plane_work *work = xchg(&plane->work, NULL); + struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_plane_work *work = xchg(&dplane->work, NULL); /* Handle any pending frame work. */ if (work) { - work->fn(dcrtc, plane, work); + work->fn(dcrtc, dplane, work); drm_crtc_vblank_put(&dcrtc->crtc); } - wake_up(&plane->frame_wait); + wake_up(&dplane->frame_wait); } int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, @@ -308,14 +309,12 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, static void armada_drm_vblank_off(struct armada_crtc *dcrtc) { - struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); - /* * Tell the DRM core that vblank IRQs aren't going to happen for * a while. This cleans up any pending vblank events for us. */ drm_crtc_vblank_off(&dcrtc->crtc); - armada_drm_plane_work_run(dcrtc, plane); + armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary); } void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b, @@ -415,10 +414,8 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) spin_lock(&dcrtc->irq_lock); ovl_plane = dcrtc->plane; - if (ovl_plane) { - struct armada_plane *plane = drm_to_armada_plane(ovl_plane); - armada_drm_plane_work_run(dcrtc, plane); - } + if (ovl_plane) + armada_drm_plane_work_run(dcrtc, ovl_plane); if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) { int i = stat & GRA_FRAME_IRQ0 ? 0 : 1; @@ -448,10 +445,8 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) spin_unlock(&dcrtc->irq_lock); - if (stat & GRA_FRAME_IRQ) { - struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); - armada_drm_plane_work_run(dcrtc, plane); - } + if (stat & GRA_FRAME_IRQ) + armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary); } static irqreturn_t armada_drm_irq(int irq, void *arg) @@ -1039,7 +1034,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, * interrupt, so complete it now. */ if (dpms_blanked(dcrtc->dpms)) - armada_drm_plane_work_run(dcrtc, drm_to_armada_plane(dcrtc->crtc.primary)); + armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary); return 0; } -- cgit v1.2.3 From 8be523db65ad41b6119f59e5a7136c85aad6da29 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 16 Aug 2016 22:09:08 +0100 Subject: drm/armada: move plane state to struct armada_plane Move more of the Armada plane state (source size, and displayed size and position) into a state structure inside struct armada_plane. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 29 ++++++++++++++++++++--------- drivers/gpu/drm/armada/armada_crtc.h | 8 ++++++++ drivers/gpu/drm/armada/armada_overlay.c | 32 ++++++++++++++------------------ 3 files changed, 42 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 9ec7e6136bcc..719873be3beb 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -543,6 +543,19 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE); + val = CFG_GRA_ENA | CFG_GRA_HSMOOTH; + val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt); + val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->mod); + + if (drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt > CFG_420) + val |= CFG_PALETTE_ENA; + + drm_to_armada_plane(crtc->primary)->state.ctrl0 = val; + drm_to_armada_plane(crtc->primary)->state.src_hw = + drm_to_armada_plane(crtc->primary)->state.dst_hw = + adj->crtc_hdisplay << 16 | adj->crtc_vdisplay; + drm_to_armada_plane(crtc->primary)->state.dst_yx = 0; + i = armada_drm_crtc_calc_fb(dcrtc->crtc.primary->fb, x, y, regs, interlaced); @@ -621,8 +634,12 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, val = adj->crtc_vdisplay << 16 | adj->crtc_hdisplay; armada_reg_queue_set(regs, i, val, LCD_SPU_V_H_ACTIVE); - armada_reg_queue_set(regs, i, val, LCD_SPU_GRA_HPXL_VLN); - armada_reg_queue_set(regs, i, val, LCD_SPU_GZM_HPXL_VLN); + armada_reg_queue_set(regs, i, + drm_to_armada_plane(crtc->primary)->state.src_hw, + LCD_SPU_GRA_HPXL_VLN); + armada_reg_queue_set(regs, i, + drm_to_armada_plane(crtc->primary)->state.dst_hw, + LCD_SPU_GZM_HPXL_VLN); armada_reg_queue_set(regs, i, (lm << 16) | rm, LCD_SPU_H_PORCH); armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_porch, LCD_SPU_V_PORCH); armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total, @@ -634,13 +651,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, ADV_VSYNCOFFEN, LCD_SPU_ADV_REG); } - val = CFG_GRA_ENA | CFG_GRA_HSMOOTH; - val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt); - val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->mod); - - if (drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt > CFG_420) - val |= CFG_PALETTE_ENA; - + val = drm_to_armada_plane(crtc->primary)->state.ctrl0; if (interlaced) val |= CFG_GRA_FTOGGLE; diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 04fdd22d483b..5b2b2c55589c 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -41,10 +41,18 @@ struct armada_plane_work { struct armada_plane_work *); }; +struct armada_plane_state { + u32 src_hw; + u32 dst_hw; + u32 dst_yx; + u32 ctrl0; +}; + struct armada_plane { struct drm_plane base; wait_queue_head_t frame_wait; struct armada_plane_work *work; + struct armada_plane_state state; }; #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 94af7c93276e..5e979bbd5d6d 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -33,10 +33,6 @@ struct armada_ovl_plane_properties { struct armada_ovl_plane { struct armada_plane base; struct drm_framebuffer *old_fb; - uint32_t src_hw; - uint32_t dst_hw; - uint32_t dst_yx; - uint32_t ctrl0; struct { struct armada_plane_work work; struct armada_regs regs[13]; @@ -148,22 +144,22 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, /* FIXME: overlay on an interlaced display */ /* Just updating the position/size? */ - if (plane->fb == fb && dplane->ctrl0 == ctrl0) { + if (plane->fb == fb && dplane->base.state.ctrl0 == ctrl0) { val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16; - dplane->src_hw = val; + dplane->base.state.src_hw = val; writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); - dplane->dst_hw = val; + dplane->base.state.dst_hw = val; writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); val = dest.y1 << 16 | dest.x1; - dplane->dst_yx = val; + dplane->base.state.dst_yx = val; writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); return 0; - } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { + } else if (~dplane->base.state.ctrl0 & ctrl0 & CFG_DMA_ENA) { /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66, dcrtc->base + LCD_SPU_SRAM_PARA1); @@ -230,28 +226,28 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, } val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16; - if (dplane->src_hw != val) { - dplane->src_hw = val; + if (dplane->base.state.src_hw != val) { + dplane->base.state.src_hw = val; armada_reg_queue_set(dplane->vbl.regs, idx, val, LCD_SPU_DMA_HPXL_VLN); } val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); - if (dplane->dst_hw != val) { - dplane->dst_hw = val; + if (dplane->base.state.dst_hw != val) { + dplane->base.state.dst_hw = val; armada_reg_queue_set(dplane->vbl.regs, idx, val, LCD_SPU_DZM_HPXL_VLN); } val = dest.y1 << 16 | dest.x1; - if (dplane->dst_yx != val) { - dplane->dst_yx = val; + if (dplane->base.state.dst_yx != val) { + dplane->base.state.dst_yx = val; armada_reg_queue_set(dplane->vbl.regs, idx, val, LCD_SPU_DMA_OVSA_HPXL_VLN); } - if (dplane->ctrl0 != ctrl0) { - dplane->ctrl0 = ctrl0; + if (dplane->base.state.ctrl0 != ctrl0) { + dplane->base.state.ctrl0 = ctrl0; armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | @@ -282,7 +278,7 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) armada_drm_crtc_plane_disable(dcrtc, plane); dcrtc->plane = NULL; - dplane->ctrl0 = 0; + dplane->base.state.ctrl0 = 0; fb = xchg(&dplane->old_fb, NULL); if (fb) -- cgit v1.2.3 From 37af35c778587b3e0e42d7b816fe4f6170f9c304 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 16 Aug 2016 22:09:09 +0100 Subject: drm/armada: split out primary plane update Split out the primary plane update from the mode setting. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 52 ++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 719873be3beb..5fff7cada6f5 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -527,6 +527,34 @@ static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc) return val; } +static void armada_drm_primary_set(struct drm_crtc *crtc, + struct drm_plane *plane, int x, int y) +{ + struct armada_plane_state *state = &drm_to_armada_plane(plane)->state; + struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); + struct armada_regs regs[7]; + bool interlaced = dcrtc->interlaced; + unsigned i; + uint32_t ctrl0; + + i = armada_drm_crtc_calc_fb(plane->fb, x, y, regs, interlaced); + + armada_reg_queue_set(regs, i, state->src_hw, LCD_SPU_GRA_HPXL_VLN); + armada_reg_queue_set(regs, i, state->dst_hw, LCD_SPU_GZM_HPXL_VLN); + + ctrl0 = state->ctrl0; + if (interlaced) + ctrl0 |= CFG_GRA_FTOGGLE; + + armada_reg_queue_mod(regs, i, ctrl0, CFG_GRAFORMAT | + CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV | + CFG_SWAPYU | CFG_YUV2RGB) | + CFG_PALETTE_ENA | CFG_GRA_FTOGGLE, + LCD_SPU_DMA_CTRL0); + armada_reg_queue_end(regs, i); + armada_drm_crtc_update_regs(dcrtc, regs); +} + /* The mode_config.mutex will be held for this call */ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adj, @@ -553,12 +581,10 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, drm_to_armada_plane(crtc->primary)->state.ctrl0 = val; drm_to_armada_plane(crtc->primary)->state.src_hw = drm_to_armada_plane(crtc->primary)->state.dst_hw = - adj->crtc_hdisplay << 16 | adj->crtc_vdisplay; + adj->crtc_vdisplay << 16 | adj->crtc_hdisplay; drm_to_armada_plane(crtc->primary)->state.dst_yx = 0; - i = armada_drm_crtc_calc_fb(dcrtc->crtc.primary->fb, - x, y, regs, interlaced); - + i = 0; rm = adj->crtc_hsync_start - adj->crtc_hdisplay; lm = adj->crtc_htotal - adj->crtc_hsync_end; bm = adj->crtc_vsync_start - adj->crtc_vdisplay; @@ -634,12 +660,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, val = adj->crtc_vdisplay << 16 | adj->crtc_hdisplay; armada_reg_queue_set(regs, i, val, LCD_SPU_V_H_ACTIVE); - armada_reg_queue_set(regs, i, - drm_to_armada_plane(crtc->primary)->state.src_hw, - LCD_SPU_GRA_HPXL_VLN); - armada_reg_queue_set(regs, i, - drm_to_armada_plane(crtc->primary)->state.dst_hw, - LCD_SPU_GZM_HPXL_VLN); armada_reg_queue_set(regs, i, (lm << 16) | rm, LCD_SPU_H_PORCH); armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_porch, LCD_SPU_V_PORCH); armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total, @@ -651,16 +671,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, ADV_VSYNCOFFEN, LCD_SPU_ADV_REG); } - val = drm_to_armada_plane(crtc->primary)->state.ctrl0; - if (interlaced) - val |= CFG_GRA_FTOGGLE; - - armada_reg_queue_mod(regs, i, val, CFG_GRAFORMAT | - CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV | - CFG_SWAPYU | CFG_YUV2RGB) | - CFG_PALETTE_ENA | CFG_GRA_FTOGGLE, - LCD_SPU_DMA_CTRL0); - val = adj->flags & DRM_MODE_FLAG_NVSYNC ? CFG_VSYNC_INV : 0; armada_reg_queue_mod(regs, i, val, CFG_VSYNC_INV, LCD_SPU_DMA_CTRL1); @@ -669,6 +679,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, armada_reg_queue_end(regs, i); armada_drm_crtc_update_regs(dcrtc, regs); + + armada_drm_primary_set(crtc, crtc->primary, x, y); spin_unlock_irqrestore(&dcrtc->irq_lock, flags); armada_drm_crtc_update(dcrtc); -- cgit v1.2.3 From 2925db08174eea7afc32258b6fbb4a57810846a0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 16 Aug 2016 22:09:10 +0100 Subject: drm/armada: move setting primary plane position to armada_drm_primary_set() Move the setting of the primary plane position into armada_drm_primary_set() rather than the initialisation function. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 5fff7cada6f5..6d3b0edde8d7 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -532,13 +532,14 @@ static void armada_drm_primary_set(struct drm_crtc *crtc, { struct armada_plane_state *state = &drm_to_armada_plane(plane)->state; struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); - struct armada_regs regs[7]; + struct armada_regs regs[8]; bool interlaced = dcrtc->interlaced; unsigned i; - uint32_t ctrl0; + u32 ctrl0; i = armada_drm_crtc_calc_fb(plane->fb, x, y, regs, interlaced); + armada_reg_queue_set(regs, i, state->dst_yx, LCD_SPU_GRA_OVSA_HPXL_VLN); armada_reg_queue_set(regs, i, state->src_hw, LCD_SPU_GRA_HPXL_VLN); armada_reg_queue_set(regs, i, state->dst_hw, LCD_SPU_GZM_HPXL_VLN); @@ -1191,7 +1192,6 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 | CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1); - writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN); writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA); writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR); -- cgit v1.2.3 From f0b24871cc3aa71d52553d5a0fa11584b8e4943c Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 16 Aug 2016 22:09:11 +0100 Subject: drm/armada: use common helper for plane base address Use a common helper to calculate the plane base address(es) for the framebuffer. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 26 ++++++++++++++++++++++---- drivers/gpu/drm/armada/armada_crtc.h | 2 ++ drivers/gpu/drm/armada/armada_overlay.c | 26 ++++++++++---------------- 3 files changed, 34 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 6d3b0edde8d7..ceec930696dc 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -165,19 +165,37 @@ static void armada_drm_crtc_update(struct armada_crtc *dcrtc) } } +void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb, + int x, int y) +{ + u32 addr = drm_fb_obj(fb)->dev_addr; + u32 pixel_format = fb->pixel_format; + int num_planes = drm_format_num_planes(pixel_format); + int i; + + if (num_planes > 3) + num_planes = 3; + + for (i = 0; i < num_planes; i++) + addrs[i] = addr + fb->offsets[i] + y * fb->pitches[i] + + x * drm_format_plane_cpp(pixel_format, i); + for (; i < 3; i++) + addrs[i] = 0; +} + static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb, int x, int y, struct armada_regs *regs, bool interlaced) { - struct armada_gem_object *obj = drm_fb_obj(fb); unsigned pitch = fb->pitches[0]; - unsigned offset = y * pitch + x * fb->bits_per_pixel / 8; - uint32_t addr_odd, addr_even; + u32 addrs[3], addr_odd, addr_even; unsigned i = 0; DRM_DEBUG_DRIVER("pitch %u x %d y %d bpp %d\n", pitch, x, y, fb->bits_per_pixel); - addr_odd = addr_even = obj->dev_addr + offset; + armada_drm_plane_calc_addrs(addrs, fb, x, y); + + addr_odd = addr_even = addrs[0]; if (interlaced) { addr_even += pitch; diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 5b2b2c55589c..b08043e8cc3b 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -62,6 +62,8 @@ int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout); struct armada_plane_work *armada_drm_plane_work_cancel( struct armada_crtc *dcrtc, struct armada_plane *plane); +void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb, + int x, int y); struct armada_crtc { struct drm_crtc crtc; diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 5e979bbd5d6d..41fc28b1e7d1 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -169,9 +169,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, armada_drm_plane_work_cancel(dcrtc, &dplane->base); if (plane->fb != fb) { - struct armada_gem_object *obj = drm_fb_obj(fb); - uint32_t addr[3], pixel_format; - int i, num_planes, hsub; + u32 addrs[3], pixel_format; + int num_planes, hsub; /* * Take a reference on the new framebuffer - we want to @@ -185,6 +184,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, src_y = src.y1 >> 16; src_x = src.x1 >> 16; + armada_drm_plane_calc_addrs(addrs, fb, src_x, src_y); + pixel_format = fb->pixel_format; hsub = drm_format_horz_chroma_subsampling(pixel_format); num_planes = drm_format_num_planes(pixel_format); @@ -197,24 +198,17 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, if (src_x & (hsub - 1) && num_planes == 1) ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV); - for (i = 0; i < num_planes; i++) - addr[i] = obj->dev_addr + fb->offsets[i] + - src_y * fb->pitches[i] + - src_x * drm_format_plane_cpp(pixel_format, i); - for (; i < ARRAY_SIZE(addr); i++) - addr[i] = 0; - - armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], + armada_reg_queue_set(dplane->vbl.regs, idx, addrs[0], LCD_SPU_DMA_START_ADDR_Y0); - armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], + armada_reg_queue_set(dplane->vbl.regs, idx, addrs[1], LCD_SPU_DMA_START_ADDR_U0); - armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], + armada_reg_queue_set(dplane->vbl.regs, idx, addrs[2], LCD_SPU_DMA_START_ADDR_V0); - armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], + armada_reg_queue_set(dplane->vbl.regs, idx, addrs[0], LCD_SPU_DMA_START_ADDR_Y1); - armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], + armada_reg_queue_set(dplane->vbl.regs, idx, addrs[1], LCD_SPU_DMA_START_ADDR_U1); - armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], + armada_reg_queue_set(dplane->vbl.regs, idx, addrs[2], LCD_SPU_DMA_START_ADDR_V1); val = fb->pitches[0] << 16 | fb->pitches[0]; -- cgit v1.2.3 From bb789cd12cfc314458f8bd24548dbda3e683bc26 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 5 Oct 2016 09:33:31 +0200 Subject: firmware: arm_scpi: increase MAX_DVFS_OPPS to 16 entries Since Amlogic SoCs supports more than 8 OPPs per domains, we need increase the OPP structure size. This patch increases the MAX_DVFS_OPPS to 16. Signed-off-by: Neil Armstrong Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 9e9b022450eb..21542a32ad9f 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -63,7 +63,7 @@ #define SCPI_SLOT 0 #define MAX_DVFS_DOMAINS 8 -#define MAX_DVFS_OPPS 8 +#define MAX_DVFS_OPPS 16 #define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16) #define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff) -- cgit v1.2.3 From 4dfe32d5cd0586fef6c716d95542e2857afb7add Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 19 Oct 2016 14:51:08 +0200 Subject: firmware: arm_scpi: add alternative legacy structures, functions and macros This patch adds support for the Legacy SCPI protocol that is available in very early JUNO versions and shipped Amlogic ARMv8 based SoCs. Some Rockchip SoC are also known to use this version of protocol with extended vendor commands. In order to support the legacy SCPI protocol variant, we need to add the structures and macros definitions that varies against the final SCPI v1.0 specification. We add the indirection table for legacy commands set so that it can co-exist with the standard v1.0 command set. It also adds bitmap field for channel selection since the legacy protocol mandates to send only selected subset of the commands on the high priority channel. Signed-off-by: Neil Armstrong [sudeep.holla@arm.com: Updated the changelog] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 192 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 174 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 21542a32ad9f..2982bc7b8c33 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -50,13 +50,20 @@ #define CMD_TOKEN_ID_MASK 0xff #define CMD_DATA_SIZE_SHIFT 16 #define CMD_DATA_SIZE_MASK 0x1ff +#define CMD_LEGACY_DATA_SIZE_SHIFT 20 +#define CMD_LEGACY_DATA_SIZE_MASK 0x1ff #define PACK_SCPI_CMD(cmd_id, tx_sz) \ ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \ (((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT)) #define ADD_SCPI_TOKEN(cmd, token) \ ((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT)) +#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz) \ + ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \ + (((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT)) #define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK) +#define CMD_LEGACY_SIZE(cmd) (((cmd) >> CMD_LEGACY_DATA_SIZE_SHIFT) & \ + CMD_LEGACY_DATA_SIZE_MASK) #define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK) #define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK) @@ -133,7 +140,62 @@ enum scpi_std_cmd { SCPI_CMD_COUNT }; -/* List of all commands used by this driver, used as indices */ +/* SCPI Legacy Commands */ +enum legacy_scpi_std_cmd { + LEGACY_SCPI_CMD_INVALID = 0x00, + LEGACY_SCPI_CMD_SCPI_READY = 0x01, + LEGACY_SCPI_CMD_SCPI_CAPABILITIES = 0x02, + LEGACY_SCPI_CMD_EVENT = 0x03, + LEGACY_SCPI_CMD_SET_CSS_PWR_STATE = 0x04, + LEGACY_SCPI_CMD_GET_CSS_PWR_STATE = 0x05, + LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT = 0x06, + LEGACY_SCPI_CMD_GET_PWR_STATE_STAT = 0x07, + LEGACY_SCPI_CMD_SYS_PWR_STATE = 0x08, + LEGACY_SCPI_CMD_L2_READY = 0x09, + LEGACY_SCPI_CMD_SET_AP_TIMER = 0x0a, + LEGACY_SCPI_CMD_CANCEL_AP_TIME = 0x0b, + LEGACY_SCPI_CMD_DVFS_CAPABILITIES = 0x0c, + LEGACY_SCPI_CMD_GET_DVFS_INFO = 0x0d, + LEGACY_SCPI_CMD_SET_DVFS = 0x0e, + LEGACY_SCPI_CMD_GET_DVFS = 0x0f, + LEGACY_SCPI_CMD_GET_DVFS_STAT = 0x10, + LEGACY_SCPI_CMD_SET_RTC = 0x11, + LEGACY_SCPI_CMD_GET_RTC = 0x12, + LEGACY_SCPI_CMD_CLOCK_CAPABILITIES = 0x13, + LEGACY_SCPI_CMD_SET_CLOCK_INDEX = 0x14, + LEGACY_SCPI_CMD_SET_CLOCK_VALUE = 0x15, + LEGACY_SCPI_CMD_GET_CLOCK_VALUE = 0x16, + LEGACY_SCPI_CMD_PSU_CAPABILITIES = 0x17, + LEGACY_SCPI_CMD_SET_PSU = 0x18, + LEGACY_SCPI_CMD_GET_PSU = 0x19, + LEGACY_SCPI_CMD_SENSOR_CAPABILITIES = 0x1a, + LEGACY_SCPI_CMD_SENSOR_INFO = 0x1b, + LEGACY_SCPI_CMD_SENSOR_VALUE = 0x1c, + LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC = 0x1d, + LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS = 0x1e, + LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1f, + LEGACY_SCPI_CMD_COUNT +}; + +/* List all commands that are required to go through the high priority link */ +static int legacy_hpriority_cmds[] = { + LEGACY_SCPI_CMD_GET_CSS_PWR_STATE, + LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT, + LEGACY_SCPI_CMD_GET_PWR_STATE_STAT, + LEGACY_SCPI_CMD_SET_DVFS, + LEGACY_SCPI_CMD_GET_DVFS, + LEGACY_SCPI_CMD_SET_RTC, + LEGACY_SCPI_CMD_GET_RTC, + LEGACY_SCPI_CMD_SET_CLOCK_INDEX, + LEGACY_SCPI_CMD_SET_CLOCK_VALUE, + LEGACY_SCPI_CMD_GET_CLOCK_VALUE, + LEGACY_SCPI_CMD_SET_PSU, + LEGACY_SCPI_CMD_GET_PSU, + LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC, + LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS, +}; + +/* List all commands used by this driver, used as indexes */ enum scpi_drv_cmds { CMD_SCPI_CAPABILITIES = 0, CMD_GET_CLOCK_INFO, @@ -165,6 +227,21 @@ static int scpi_std_commands[CMD_MAX_COUNT] = { SCPI_CMD_GET_DEVICE_PWR_STATE, }; +static int scpi_legacy_commands[CMD_MAX_COUNT] = { + LEGACY_SCPI_CMD_SCPI_CAPABILITIES, + -1, /* GET_CLOCK_INFO */ + LEGACY_SCPI_CMD_GET_CLOCK_VALUE, + LEGACY_SCPI_CMD_SET_CLOCK_VALUE, + LEGACY_SCPI_CMD_GET_DVFS, + LEGACY_SCPI_CMD_SET_DVFS, + LEGACY_SCPI_CMD_GET_DVFS_INFO, + LEGACY_SCPI_CMD_SENSOR_CAPABILITIES, + LEGACY_SCPI_CMD_SENSOR_INFO, + LEGACY_SCPI_CMD_SENSOR_VALUE, + -1, /* SET_DEVICE_PWR_STATE */ + -1, /* GET_DEVICE_PWR_STATE */ +}; + struct scpi_xfer { u32 slot; /* has to be first element */ u32 cmd; @@ -193,8 +270,10 @@ struct scpi_chan { struct scpi_drvinfo { u32 protocol_version; u32 firmware_version; + bool is_legacy; int num_chans; int *commands; + DECLARE_BITMAP(cmd_priority, LEGACY_SCPI_CMD_COUNT); atomic_t next_chan; struct scpi_ops *scpi_ops; struct scpi_chan *channels; @@ -211,6 +290,11 @@ struct scpi_shared_mem { u8 payload[0]; } __packed; +struct legacy_scpi_shared_mem { + __le32 status; + u8 payload[0]; +} __packed; + struct scp_capabilities { __le32 protocol_version; __le32 event_version; @@ -236,6 +320,12 @@ struct clk_set_value { __le32 rate; } __packed; +struct legacy_clk_set_value { + __le32 rate; + __le16 id; + __le16 reserved; +} __packed; + struct dvfs_info { __le32 header; struct { @@ -307,19 +397,43 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd) return; } - list_for_each_entry(t, &ch->rx_pending, node) - if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) { - list_del(&t->node); - match = t; - break; - } + /* Command type is not replied by the SCP Firmware in legacy Mode + * We should consider that command is the head of pending RX commands + * if the list is not empty. In TX only mode, the list would be empty. + */ + if (scpi_info->is_legacy) { + match = list_first_entry(&ch->rx_pending, struct scpi_xfer, + node); + list_del(&match->node); + } else { + list_for_each_entry(t, &ch->rx_pending, node) + if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) { + list_del(&t->node); + match = t; + break; + } + } /* check if wait_for_completion is in progress or timed-out */ if (match && !completion_done(&match->done)) { - struct scpi_shared_mem *mem = ch->rx_payload; - unsigned int len = min(match->rx_len, CMD_SIZE(cmd)); + unsigned int len; + + if (scpi_info->is_legacy) { + struct legacy_scpi_shared_mem *mem = ch->rx_payload; + + /* RX Length is not replied by the legacy Firmware */ + len = match->rx_len; + + match->status = le32_to_cpu(mem->status); + memcpy_fromio(match->rx_buf, mem->payload, len); + } else { + struct scpi_shared_mem *mem = ch->rx_payload; + + len = min(match->rx_len, CMD_SIZE(cmd)); + + match->status = le32_to_cpu(mem->status); + memcpy_fromio(match->rx_buf, mem->payload, len); + } - match->status = le32_to_cpu(mem->status); - memcpy_fromio(match->rx_buf, mem->payload, len); if (match->rx_len > len) memset(match->rx_buf + len, 0, match->rx_len - len); complete(&match->done); @@ -331,7 +445,10 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg) { struct scpi_chan *ch = container_of(c, struct scpi_chan, cl); struct scpi_shared_mem *mem = ch->rx_payload; - u32 cmd = le32_to_cpu(mem->command); + u32 cmd = 0; + + if (!scpi_info->is_legacy) + cmd = le32_to_cpu(mem->command); scpi_process_cmd(ch, cmd); } @@ -343,8 +460,13 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg) struct scpi_chan *ch = container_of(c, struct scpi_chan, cl); struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload; - if (t->tx_buf) - memcpy_toio(mem->payload, t->tx_buf, t->tx_len); + if (t->tx_buf) { + if (scpi_info->is_legacy) + memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len); + else + memcpy_toio(mem->payload, t->tx_buf, t->tx_len); + } + if (t->rx_buf) { if (!(++ch->token)) ++ch->token; @@ -353,7 +475,9 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg) list_add_tail(&t->node, &ch->rx_pending); spin_unlock_irqrestore(&ch->rx_lock, flags); } - mem->command = cpu_to_le32(t->cmd); + + if (!scpi_info->is_legacy) + mem->command = cpu_to_le32(t->cmd); } static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch) @@ -392,15 +516,24 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len, cmd = scpi_info->commands[idx]; - chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans; + if (scpi_info->is_legacy) + chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0; + else + chan = atomic_inc_return(&scpi_info->next_chan) % + scpi_info->num_chans; scpi_chan = scpi_info->channels + chan; msg = get_scpi_xfer(scpi_chan); if (!msg) return -ENOMEM; - msg->slot = BIT(SCPI_SLOT); - msg->cmd = PACK_SCPI_CMD(cmd, tx_len); + if (scpi_info->is_legacy) { + msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len); + msg->slot = msg->cmd; + } else { + msg->slot = BIT(SCPI_SLOT); + msg->cmd = PACK_SCPI_CMD(cmd, tx_len); + } msg->tx_buf = tx_buf; msg->tx_len = tx_len; msg->rx_buf = rx_buf; @@ -470,6 +603,18 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate) &stat, sizeof(stat)); } +static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate) +{ + int stat; + struct legacy_clk_set_value clk = { + .id = cpu_to_le16(clk_id), + .rate = cpu_to_le32(rate) + }; + + return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk), + &stat, sizeof(stat)); +} + static int scpi_dvfs_get_idx(u8 domain) { int ret; @@ -800,6 +945,17 @@ err: platform_set_drvdata(pdev, scpi_info); + if (scpi_info->is_legacy) { + /* Replace with legacy variants */ + scpi_ops.clk_set_val = legacy_scpi_clk_set_val; + scpi_info->commands = scpi_legacy_commands; + + /* Fill priority bitmap */ + for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++) + set_bit(legacy_hpriority_cmds[idx], + scpi_info->cmd_priority); + } + ret = scpi_init_versions(scpi_info); if (ret) { dev_err(dev, "incorrect or no SCP firmware found\n"); -- cgit v1.2.3 From abd3e80545c184f2b472f7527ae8eda34bd59f2d Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 19 Oct 2016 14:51:09 +0200 Subject: firmware: arm_scpi: allow firmware with get_capabilities not implemented On Amlogic SCPI legacy implementation, the GET_CAPABILITIES command is not supported, failover by using 0.0.0 version. Signed-off-by: Neil Armstrong [sudeep.holla@arm.com: changed the subject] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 2982bc7b8c33..902233642bd3 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -783,6 +783,10 @@ static int scpi_init_versions(struct scpi_drvinfo *info) info->protocol_version = le32_to_cpu(caps.protocol_version); info->firmware_version = le32_to_cpu(caps.platform_version); } + /* Ignore error if not implemented */ + if (scpi_info->is_legacy && ret == -EOPNOTSUPP) + return 0; + return ret; } -- cgit v1.2.3 From e4c8cd82d5e1146590611c393001d846535bac5b Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 13 Oct 2016 02:16:08 +0800 Subject: soc: rockchip: power-domain: avoid infinite loop In some cases, we have met the infinite loop in rockchip_pmu_set_idle_request() or rockchip_do_pmu_set_power_domain(). As the crosbug.com/p/57351 reported, the boot hangs right after this [1.629163] bootconsole [uart8250] disabled [1.639286] [drm:drm_core_init] Initialized drm 1.1.0 20060810 [1.645926] [drm:drm_get_platform_dev] Initialized vgem 1.0.0 20120112.. [1.654558] iommu: Adding device ff8f0000.vop to group 0 [1.660569] iommu: Adding device ff900000.vop to group 1 This patch adds the error message and timeout to avoid infinite loop if it fails to get the ack. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 48 +++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 5f106b16e622..988bfd708706 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -105,12 +106,24 @@ static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) return (val & pd_info->idle_mask) == pd_info->idle_mask; } +static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu) +{ + unsigned int val; + + regmap_read(pmu->regmap, pmu->info->ack_offset, &val); + return val; +} + static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, bool idle) { const struct rockchip_domain_info *pd_info = pd->info; + struct generic_pm_domain *genpd = &pd->genpd; struct rockchip_pmu *pmu = pd->pmu; + unsigned int target_ack; unsigned int val; + bool is_idle; + int ret; if (pd_info->req_mask == 0) return 0; @@ -120,12 +133,26 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, dsb(sy); - do { - regmap_read(pmu->regmap, pmu->info->ack_offset, &val); - } while ((val & pd_info->ack_mask) != (idle ? pd_info->ack_mask : 0)); + /* Wait util idle_ack = 1 */ + target_ack = idle ? pd_info->ack_mask : 0; + ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val, + (val & pd_info->ack_mask) == target_ack, + 0, 10000); + if (ret) { + dev_err(pmu->dev, + "failed to get ack on domain '%s', val=0x%x\n", + genpd->name, val); + return ret; + } - while (rockchip_pmu_domain_is_idle(pd) != idle) - cpu_relax(); + ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd, + is_idle, is_idle == idle, 0, 10000); + if (ret) { + dev_err(pmu->dev, + "failed to set idle on domain '%s', val=%d\n", + genpd->name, is_idle); + return ret; + } return 0; } @@ -198,6 +225,8 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, bool on) { struct rockchip_pmu *pmu = pd->pmu; + struct generic_pm_domain *genpd = &pd->genpd; + bool is_on; if (pd->info->pwr_mask == 0) return; @@ -207,8 +236,13 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, dsb(sy); - while (rockchip_pmu_domain_is_on(pd) != on) - cpu_relax(); + if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on, + is_on == on, 0, 10000)) { + dev_err(pmu->dev, + "failed to set domain '%s', val=%d\n", + genpd->name, is_on); + return; + } } static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) -- cgit v1.2.3 From 1dfbec3905548a0cbc820a62e1d8adee1c80bd41 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 1 Nov 2016 11:22:06 +0800 Subject: clk: rockchip: optimize 800MHz and 1GHz pll rates on RK3399 Usually, the 800MHz and 1GHz are supplied for CPLL and NPLL in the RK3399. But dues to the carelessly copying from RK3036 when the RK3399 bringing up, the refdiv == 6, it will increase the lock time, and it is not an optimal configuration. Let's fix them for the lock time and jitter are lower: 800 MHz: - FVCO == 2.4 GHz, revdiv == 1. 1 GHz: - FVCO == 3 GHz, revdiv == 1. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index a5a3f412d09a..28aff4507d96 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -77,7 +77,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), - RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), + RK3036_PLL_RATE(1000000000, 1, 125, 3, 1, 1, 0), RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), @@ -87,7 +87,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), - RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0), + RK3036_PLL_RATE( 800000000, 1, 100, 3, 1, 1, 0), RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0), -- cgit v1.2.3 From c5a8045a553e32529ffb6bfb33fcad4d38aec2c7 Mon Sep 17 00:00:00 2001 From: Emil Lundmark Date: Wed, 12 Oct 2016 12:31:41 +0200 Subject: clk: imx: improve precision of AV PLL to 1 Hz The audio and video PLLs are designed to have a precision of 1 Hz if some conditions are met. The current implementation only allows a precision that depends on the rate of the parent clock. E.g., if the parent clock is 24 MHz, the precision will be 24 Hz; or more generally the precision will be p / 10^6 Hz where p is the parent clock rate. This comes down to how the register values for the PLL's fractional loop divider are chosen. The clock rate calculation for the PLL is PLL output frequency = Fref * (DIV_SELECT + NUM / DENOM) or with a shorter notation r = p * (d + a / b) In addition to all variables being integers, we also have the following conditions: 27 <= d <= 54 -2^29 <= a <= 2^29-1 0 < b <= 2^30-1 |a| < b Here, d, a and b are register values for the fractional loop divider. We want to chose d, a and b such that f(p, r) = p, i.e. f is our round_rate function. Currently, d and b are chosen as d = r / p b = 10^6 hence we get the poor precision. And a is defined in terms of r, d, p and b: a = (r - d * p) * b / p I propose that if p <= 2^30-1 (i.e., the max value for b), we chose b as b = p We can do this since |a| < b |(r - d * p) * b / p| < b |r - d * p| < p Which have two solutions, one of them is when p < 0, so we can skip that one. The other is when p > 0 and p * (d - 1) < r < p * (d + 1) Substitute d = r / p: (r - p) < r < (r + p) <=> p > 0 So, as long as p > 0, we can chose b = p. This is a good choise for b since a = (r - d * p) * b / p = (r - d * p) * p / p = r - d * p r = p * (d + a / b) = p * d + p * a / b = p * d + p * a / p = p * d + a and if d = r / p: a = r - d * p = r - r / p * p = 0 r = p * d + a = p * d + 0 = p * r / p = r I reckon this is the intention by the design of the clock rate formula. Signed-off-by: Emil Lundmark Reviewed-by: Fabio Estevam Acked-by: Shawn Guo Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-pllv3.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 7a6acc3e4a92..ed3a2df536ea 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -234,6 +234,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long max_rate = parent_rate * 54; u32 div; u32 mfn, mfd = 1000000; + u32 max_mfd = 0x3FFFFFFF; u64 temp64; if (rate > max_rate) @@ -241,6 +242,9 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, else if (rate < min_rate) rate = min_rate; + if (parent_rate <= max_mfd) + mfd = parent_rate; + div = rate / parent_rate; temp64 = (u64) (rate - div * parent_rate); temp64 *= mfd; @@ -262,11 +266,15 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long max_rate = parent_rate * 54; u32 val, div; u32 mfn, mfd = 1000000; + u32 max_mfd = 0x3FFFFFFF; u64 temp64; if (rate < min_rate || rate > max_rate) return -EINVAL; + if (parent_rate <= max_mfd) + mfd = parent_rate; + div = rate / parent_rate; temp64 = (u64) (rate - div * parent_rate); temp64 *= mfd; -- cgit v1.2.3 From e7cc455fcd07c9c4ad240a392610f31e1e0460cf Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 20 Oct 2016 15:08:06 +0530 Subject: clk: qcom: Handle the clamp_io assert/deassert sequence Add a flag to mark gdscs which need to support the clamp deassert/assert before and after the gdsc enable/disable Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gdsc.c | 26 +++++++++++++++++++++++++- drivers/clk/qcom/gdsc.h | 2 ++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index f12d7b2bddd7..925d178ba675 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -30,6 +30,7 @@ #define SW_OVERRIDE_MASK BIT(2) #define HW_CONTROL_MASK BIT(1) #define SW_COLLAPSE_MASK BIT(0) +#define GMEM_CLAMP_IO_MASK BIT(0) /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */ #define EN_REST_WAIT_VAL (0x2 << 20) @@ -140,6 +141,18 @@ static inline void gdsc_clear_mem_on(struct gdsc *sc) regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0); } +static inline void gdsc_deassert_clamp_io(struct gdsc *sc) +{ + regmap_update_bits(sc->regmap, sc->clamp_io_ctrl, + GMEM_CLAMP_IO_MASK, 0); +} + +static inline void gdsc_assert_clamp_io(struct gdsc *sc) +{ + regmap_update_bits(sc->regmap, sc->clamp_io_ctrl, + GMEM_CLAMP_IO_MASK, 1); +} + static int gdsc_enable(struct generic_pm_domain *domain) { struct gdsc *sc = domain_to_gdsc(domain); @@ -148,6 +161,9 @@ static int gdsc_enable(struct generic_pm_domain *domain) if (sc->pwrsts == PWRSTS_ON) return gdsc_deassert_reset(sc); + if (sc->flags & CLAMP_IO) + gdsc_deassert_clamp_io(sc); + ret = gdsc_toggle_logic(sc, true); if (ret) return ret; @@ -170,6 +186,7 @@ static int gdsc_enable(struct generic_pm_domain *domain) static int gdsc_disable(struct generic_pm_domain *domain) { struct gdsc *sc = domain_to_gdsc(domain); + int ret; if (sc->pwrsts == PWRSTS_ON) return gdsc_assert_reset(sc); @@ -177,7 +194,14 @@ static int gdsc_disable(struct generic_pm_domain *domain) if (sc->pwrsts & PWRSTS_OFF) gdsc_clear_mem_on(sc); - return gdsc_toggle_logic(sc, false); + ret = gdsc_toggle_logic(sc, false); + if (ret) + return ret; + + if (sc->flags & CLAMP_IO) + gdsc_assert_clamp_io(sc); + + return 0; } static int gdsc_init(struct gdsc *sc) diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 3bf497c36bdf..f011c4957527 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -39,6 +39,7 @@ struct gdsc { struct regmap *regmap; unsigned int gdscr; unsigned int gds_hw_ctrl; + unsigned int clamp_io_ctrl; unsigned int *cxcs; unsigned int cxc_count; const u8 pwrsts; @@ -50,6 +51,7 @@ struct gdsc { #define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON) const u8 flags; #define VOTABLE BIT(0) +#define CLAMP_IO BIT(1) struct reset_controller_dev *rcdev; unsigned int *resets; unsigned int reset_count; -- cgit v1.2.3 From 4154f61997e154a278155676fc9638c20c52ca81 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 20 Oct 2016 15:08:07 +0530 Subject: clk: qcom: mmcc-8996: Add gpu gdscs Add gpu gdsc data for msm8996 Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/mmcc-msm8996.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c index ca97e1151797..f77206f549cc 100644 --- a/drivers/clk/qcom/mmcc-msm8996.c +++ b/drivers/clk/qcom/mmcc-msm8996.c @@ -3034,6 +3034,28 @@ static struct gdsc mdss_gdsc = { .pwrsts = PWRSTS_OFF_ON, }; +static struct gdsc gpu_gdsc = { + .gdscr = 0x4034, + .gds_hw_ctrl = 0x4038, + .pd = { + .name = "gpu", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc gpu_gx_gdsc = { + .gdscr = 0x4024, + .clamp_io_ctrl = 0x4300, + .cxcs = (unsigned int []){ 0x4028 }, + .cxc_count = 1, + .pd = { + .name = "gpu_gx", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = CLAMP_IO, +}; + static struct clk_regmap *mmcc_msm8996_clocks[] = { [MMPLL0_EARLY] = &mmpll0_early.clkr, [MMPLL0_PLL] = &mmpll0.clkr, @@ -3223,6 +3245,8 @@ static struct gdsc *mmcc_msm8996_gdscs[] = { [CPP_GDSC] = &cpp_gdsc, [FD_GDSC] = &fd_gdsc, [MDSS_GDSC] = &mdss_gdsc, + [GPU_GDSC] = &gpu_gdsc, + [GPU_GX_GDSC] = &gpu_gx_gdsc, }; static const struct qcom_reset_map mmcc_msm8996_resets[] = { -- cgit v1.2.3 From f84d42a9cffc4ecd96f1ce3a038f841782142eb2 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 7 Oct 2016 04:16:55 +0300 Subject: clk: lpc32xx: add a quirk for PWM and MS clock dividers In common clock framework CLK_DIVIDER_ONE_BASED or'ed with CLK_DIVIDER_ALLOW_ZERO flags indicates that 1) a divider clock may be set to zero value, 2) divider's zero value is interpreted as a non-divided clock. On the LPC32xx platform clock dividers of PWM and memory card clocks comply with the first condition, but zero value means a gated clock, thus it may happen that the divider value is not updated when the clock is enabled and the clock remains gated. The change adds one-shot quirks, which check for zero value of divider on initialization and set it to a non-zero value, therefore in runtime a gate clock will work as expected. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Sylvain Lemieux Signed-off-by: Stephen Boyd --- drivers/clk/nxp/clk-lpc32xx.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c index 34c97353cdeb..5b98ff9076f3 100644 --- a/drivers/clk/nxp/clk-lpc32xx.c +++ b/drivers/clk/nxp/clk-lpc32xx.c @@ -1282,13 +1282,13 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = { LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0), LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL, - CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), + CLK_DIVIDER_ONE_BASED), LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0), LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE), LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0), LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL, - CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), + CLK_DIVIDER_ONE_BASED), LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0), LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE), @@ -1335,8 +1335,7 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = { LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0), LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE), - LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, - CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), + LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, CLK_DIVIDER_ONE_BASED), LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9), 0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops), LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE), @@ -1478,6 +1477,20 @@ static struct clk * __init lpc32xx_clk_register(u32 id) return clk; } +static void __init lpc32xx_clk_div_quirk(u32 reg, u32 div_mask, u32 gate) +{ + u32 val; + + regmap_read(clk_regmap, reg, &val); + + if (!(val & div_mask)) { + val &= ~gate; + val |= BIT(__ffs(div_mask)); + } + + regmap_update_bits(clk_regmap, reg, gate | div_mask, val); +} + static void __init lpc32xx_clk_init(struct device_node *np) { unsigned int i; @@ -1517,6 +1530,17 @@ static void __init lpc32xx_clk_init(struct device_node *np) return; } + /* + * Divider part of PWM and MS clocks requires a quirk to avoid + * a misinterpretation of formally valid zero value in register + * bitfield, which indicates another clock gate. Instead of + * adding complexity to a gate clock ensure that zero value in + * divider clock is never met in runtime. + */ + lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf0, BIT(0)); + lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf00, BIT(2)); + lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_MS_CTRL, 0xf, BIT(5) | BIT(9)); + for (i = 1; i < LPC32XX_CLK_MAX; i++) { clk[i] = lpc32xx_clk_register(i); if (IS_ERR(clk[i])) { -- cgit v1.2.3 From 45261a3e625dffbfab08f3b9cad84403ddd512e6 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 20 Sep 2016 16:09:47 +0530 Subject: clk: nxp: clk-lpc18xx-ccu: Unmap region obtained by of_iomap Free memory mapping, if lpc18xx_ccu_init() is not successful. Signed-off-by: Arvind Yadav Acked-by: Joachim Eastwood Signed-off-by: Stephen Boyd --- drivers/clk/nxp/clk-lpc18xx-ccu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c index f7136b94fd0e..27781b49eb82 100644 --- a/drivers/clk/nxp/clk-lpc18xx-ccu.c +++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c @@ -277,12 +277,15 @@ static void __init lpc18xx_ccu_init(struct device_node *np) } clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) + if (!clk_data) { + iounmap(reg_base); return; + } clk_data->num = of_property_count_strings(np, "clock-names"); clk_data->name = kcalloc(clk_data->num, sizeof(char *), GFP_KERNEL); if (!clk_data->name) { + iounmap(reg_base); kfree(clk_data); return; } -- cgit v1.2.3 From 16845c1987dde5fd5ca9f04ffc53c289cc92c03d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Oct 2016 15:10:58 +0200 Subject: clk: renesas: cpg-mssr: Fix inverted debug check The intention was to enable the checks if debugging is enabled, not disabled. Signed-off-by: Geert Uytterhoeven Signed-off-by: Stephen Boyd --- drivers/clk/renesas/renesas-cpg-mssr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index e1365e7491ae..25c41cd9cdfc 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -33,9 +33,9 @@ #include "clk-div6.h" #ifdef DEBUG -#define WARN_DEBUG(x) do { } while (0) -#else #define WARN_DEBUG(x) WARN_ON(x) +#else +#define WARN_DEBUG(x) do { } while (0) #endif -- cgit v1.2.3 From 9c1b305c1e8c8d5dcdb06909a15eb0df69cff45f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 2 Oct 2016 22:58:14 +0200 Subject: clk: Enable compile testing for s2mps11 and max77686 s2mps11 and max77686 clock drivers can be compile tested to increase build coverage. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6a8ac04bedeb..56c1998ced3e 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -33,7 +33,7 @@ source "drivers/clk/versatile/Kconfig" config COMMON_CLK_MAX77686 tristate "Clock driver for Maxim 77620/77686/77802 MFD" - depends on MFD_MAX77686 || MFD_MAX77620 + depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST ---help--- This driver supports Maxim 77620/77686/77802 crystal oscillator clock. @@ -119,7 +119,7 @@ config COMMON_CLK_CS2000_CP config COMMON_CLK_S2MPS11 tristate "Clock driver for S2MPS1X/S5M8767 MFD" - depends on MFD_SEC_CORE + depends on MFD_SEC_CORE || COMPILE_TEST ---help--- This driver supports S2MPS11/S2MPS14/S5M8767 crystal oscillator clock. These multi-function devices have two (S2MPS14) or three -- cgit v1.2.3 From 57ecc7a0d3f843e4c02f4a9a67b9da76a7f48b5d Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Sun, 25 Sep 2016 09:47:53 +0200 Subject: clk: mvebu: migrate CP110 system controller to clk_hw API and registration Now that we have clk_hw based provider APIs to register clks, we can get rid of struct clk pointers while registering clks in Armada CP110 system controller driver. This commit introduces new API and registration for all clocks in CP110 HW blocks. Signed-off-by: Marcin Wojtas Signed-off-by: Stephen Boyd --- drivers/clk/mvebu/cp110-system-controller.c | 150 +++++++++++++--------------- 1 file changed, 72 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c index f2303da7fda7..0116808bc15a 100644 --- a/drivers/clk/mvebu/cp110-system-controller.c +++ b/drivers/clk/mvebu/cp110-system-controller.c @@ -87,7 +87,7 @@ struct cp110_gate_clk { u8 bit_idx; }; -#define to_cp110_gate_clk(clk) container_of(clk, struct cp110_gate_clk, hw) +#define to_cp110_gate_clk(hw) container_of(hw, struct cp110_gate_clk, hw) static int cp110_gate_enable(struct clk_hw *hw) { @@ -123,13 +123,14 @@ static const struct clk_ops cp110_gate_ops = { .is_enabled = cp110_gate_is_enabled, }; -static struct clk *cp110_register_gate(const char *name, - const char *parent_name, - struct regmap *regmap, u8 bit_idx) +static struct clk_hw *cp110_register_gate(const char *name, + const char *parent_name, + struct regmap *regmap, u8 bit_idx) { struct cp110_gate_clk *gate; - struct clk *clk; + struct clk_hw *hw; struct clk_init_data init; + int ret; gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) @@ -146,39 +147,37 @@ static struct clk *cp110_register_gate(const char *name, gate->bit_idx = bit_idx; gate->hw.init = &init; - clk = clk_register(NULL, &gate->hw); - if (IS_ERR(clk)) + hw = &gate->hw; + ret = clk_hw_register(NULL, hw); + if (ret) { kfree(gate); + hw = ERR_PTR(ret); + } - return clk; + return hw; } -static void cp110_unregister_gate(struct clk *clk) +static void cp110_unregister_gate(struct clk_hw *hw) { - struct clk_hw *hw; - - hw = __clk_get_hw(clk); - if (!hw) - return; - - clk_unregister(clk); + clk_hw_unregister(hw); kfree(to_cp110_gate_clk(hw)); } -static struct clk *cp110_of_clk_get(struct of_phandle_args *clkspec, void *data) +static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec, + void *data) { - struct clk_onecell_data *clk_data = data; + struct clk_hw_onecell_data *clk_data = data; unsigned int type = clkspec->args[0]; unsigned int idx = clkspec->args[1]; if (type == CP110_CLK_TYPE_CORE) { if (idx > CP110_MAX_CORE_CLOCKS) return ERR_PTR(-EINVAL); - return clk_data->clks[idx]; + return clk_data->hws[idx]; } else if (type == CP110_CLK_TYPE_GATABLE) { if (idx > CP110_MAX_GATABLE_CLOCKS) return ERR_PTR(-EINVAL); - return clk_data->clks[CP110_MAX_CORE_CLOCKS + idx]; + return clk_data->hws[CP110_MAX_CORE_CLOCKS + idx]; } return ERR_PTR(-EINVAL); @@ -189,8 +188,8 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev) struct regmap *regmap; struct device_node *np = pdev->dev.of_node; const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name; - struct clk_onecell_data *cp110_clk_data; - struct clk *clk, **cp110_clks; + struct clk_hw_onecell_data *cp110_clk_data; + struct clk_hw *hw, **cp110_clks; u32 nand_clk_ctrl; int i, ret; @@ -203,80 +202,75 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev) if (ret) return ret; - cp110_clks = devm_kcalloc(&pdev->dev, sizeof(struct clk *), - CP110_CLK_NUM, GFP_KERNEL); - if (!cp110_clks) - return -ENOMEM; - - cp110_clk_data = devm_kzalloc(&pdev->dev, - sizeof(*cp110_clk_data), + cp110_clk_data = devm_kzalloc(&pdev->dev, sizeof(*cp110_clk_data) + + sizeof(struct clk_hw *) * CP110_CLK_NUM, GFP_KERNEL); if (!cp110_clk_data) return -ENOMEM; - cp110_clk_data->clks = cp110_clks; - cp110_clk_data->clk_num = CP110_CLK_NUM; + cp110_clks = cp110_clk_data->hws; + cp110_clk_data->num = CP110_CLK_NUM; - /* Register the APLL which is the root of the clk tree */ + /* Register the APLL which is the root of the hw tree */ of_property_read_string_index(np, "core-clock-output-names", CP110_CORE_APLL, &apll_name); - clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0, - 1000 * 1000 * 1000); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); + hw = clk_hw_register_fixed_rate(NULL, apll_name, NULL, 0, + 1000 * 1000 * 1000); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); goto fail0; } - cp110_clks[CP110_CORE_APLL] = clk; + cp110_clks[CP110_CORE_APLL] = hw; /* PPv2 is APLL/3 */ of_property_read_string_index(np, "core-clock-output-names", CP110_CORE_PPV2, &ppv2_name); - clk = clk_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); + hw = clk_hw_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); goto fail1; } - cp110_clks[CP110_CORE_PPV2] = clk; + cp110_clks[CP110_CORE_PPV2] = hw; /* EIP clock is APLL/2 */ of_property_read_string_index(np, "core-clock-output-names", CP110_CORE_EIP, &eip_name); - clk = clk_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); + hw = clk_hw_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); goto fail2; } - cp110_clks[CP110_CORE_EIP] = clk; + cp110_clks[CP110_CORE_EIP] = hw; /* Core clock is EIP/2 */ of_property_read_string_index(np, "core-clock-output-names", CP110_CORE_CORE, &core_name); - clk = clk_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); + hw = clk_hw_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); goto fail3; } - cp110_clks[CP110_CORE_CORE] = clk; + cp110_clks[CP110_CORE_CORE] = hw; /* NAND can be either APLL/2.5 or core clock */ of_property_read_string_index(np, "core-clock-output-names", CP110_CORE_NAND, &nand_name); if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK) - clk = clk_register_fixed_factor(NULL, nand_name, - apll_name, 0, 2, 5); + hw = clk_hw_register_fixed_factor(NULL, nand_name, + apll_name, 0, 2, 5); else - clk = clk_register_fixed_factor(NULL, nand_name, - core_name, 0, 1, 1); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); + hw = clk_hw_register_fixed_factor(NULL, nand_name, + core_name, 0, 1, 1); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); goto fail4; } - cp110_clks[CP110_CORE_NAND] = clk; + cp110_clks[CP110_CORE_NAND] = hw; for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { const char *parent, *name; @@ -335,16 +329,16 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev) break; } - clk = cp110_register_gate(name, parent, regmap, i); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); + hw = cp110_register_gate(name, parent, regmap, i); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); goto fail_gate; } - cp110_clks[CP110_MAX_CORE_CLOCKS + i] = clk; + cp110_clks[CP110_MAX_CORE_CLOCKS + i] = hw; } - ret = of_clk_add_provider(np, cp110_of_clk_get, cp110_clk_data); + ret = of_clk_add_hw_provider(np, cp110_of_clk_get, cp110_clk_data); if (ret) goto fail_clk_add; @@ -355,44 +349,44 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev) fail_clk_add: fail_gate: for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { - clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; + hw = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; - if (clk) - cp110_unregister_gate(clk); + if (hw) + cp110_unregister_gate(hw); } - clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); + clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); fail4: - clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); + clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); fail3: - clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); + clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); fail2: - clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); + clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); fail1: - clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); + clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); fail0: return ret; } static int cp110_syscon_clk_remove(struct platform_device *pdev) { - struct clk **cp110_clks = platform_get_drvdata(pdev); + struct clk_hw **cp110_clks = platform_get_drvdata(pdev); int i; of_clk_del_provider(pdev->dev.of_node); for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { - struct clk *clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; + struct clk_hw *hw = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; - if (clk) - cp110_unregister_gate(clk); + if (hw) + cp110_unregister_gate(hw); } - clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); - clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); - clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); - clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); - clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); + clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); + clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); + clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); + clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); + clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); return 0; } -- cgit v1.2.3 From 5170d55e2892c8c290a1fab16ffea58a83b167ce Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 1 Oct 2016 21:46:27 +0200 Subject: clk: keystone: improve function-level documentation Adjust the documentation to use the actual function names. Issue detected using Coccinelle (http://coccinelle.lip6.fr/) Signed-off-by: Julia Lawall Signed-off-by: Stephen Boyd --- drivers/clk/keystone/pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c index a26ba2184454..185f19c6836e 100644 --- a/drivers/clk/keystone/pll.c +++ b/drivers/clk/keystone/pll.c @@ -154,7 +154,7 @@ out: } /** - * _of_clk_init - PLL initialisation via DT + * _of_pll_clk_init - PLL initialisation via DT * @node: device tree node for this clock * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of * pll controller, else it is in the control register0(bit 11-6) @@ -235,7 +235,7 @@ CLK_OF_DECLARE(keystone_pll_clock, "ti,keystone,pll-clock", of_keystone_pll_clk_init); /** - * of_keystone_pll_main_clk_init - Main PLL initialisation DT wrapper + * of_keystone_main_pll_clk_init - Main PLL initialisation DT wrapper * @node: device tree node for this clock */ static void __init of_keystone_main_pll_clk_init(struct device_node *node) -- cgit v1.2.3 From 42134fa2b70e2b70c600bf87fbe5ea5faa34ad63 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 1 Oct 2016 21:46:29 +0200 Subject: clk: tegra: dfll: improve function-level documentation Adjust variables to correspond to the names used in the parameter list of the function. Move the struct device * variable up to the place where it appears in the parameter list. Issue detected using Coccinelle (http://coccinelle.lip6.fr/) Signed-off-by: Julia Lawall Signed-off-by: Stephen Boyd --- drivers/clk/tegra/cvb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c index 624115e82ff9..da9e8e7b5ce5 100644 --- a/drivers/clk/tegra/cvb.c +++ b/drivers/clk/tegra/cvb.c @@ -92,19 +92,19 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table, /** * tegra_cvb_add_opp_table - build OPP table from Tegra CVB tables - * @cvb_tables: array of CVB tables - * @sz: size of the previously mentioned array + * @dev: the struct device * for which the OPP table is built + * @tables: array of CVB tables + * @count: size of the previously mentioned array * @process_id: process id of the HW module * @speedo_id: speedo id of the HW module * @speedo_value: speedo value of the HW module - * @max_rate: highest safe clock rate - * @opp_dev: the struct device * for which the OPP table is built + * @max_freq: highest safe clock rate * * On Tegra, a CVB table encodes the relationship between operating voltage * and safe maximal frequency for a given module (e.g. GPU or CPU). This * function calculates the optimal voltage-frequency operating points * for the given arguments and exports them via the OPP library for the - * given @opp_dev. Returns a pointer to the struct cvb_table that matched + * given @dev. Returns a pointer to the struct cvb_table that matched * or an ERR_PTR on failure. */ const struct cvb_table * -- cgit v1.2.3 From 74a484ced26d802ce7fbca86f3205e1c69e27269 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 10 Sep 2016 11:47:30 +0800 Subject: clk: qcom: lcc-ipq806x: Fixup overriding val in regmap_read call Drop the assignment of regmap_read return code to val, so the code checks the value read. Signed-off-by: Axel Lin Signed-off-by: Stephen Boyd --- drivers/clk/qcom/lcc-ipq806x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/lcc-ipq806x.c b/drivers/clk/qcom/lcc-ipq806x.c index db3998e5e2d8..977e98eadbeb 100644 --- a/drivers/clk/qcom/lcc-ipq806x.c +++ b/drivers/clk/qcom/lcc-ipq806x.c @@ -443,7 +443,7 @@ static int lcc_ipq806x_probe(struct platform_device *pdev) return PTR_ERR(regmap); /* Configure the rate of PLL4 if the bootloader hasn't already */ - val = regmap_read(regmap, 0x0, &val); + regmap_read(regmap, 0x0, &val); if (!val) clk_pll_configure_sr(&pll4, regmap, &pll4_config, true); /* Enable PLL4 source on the LPASS Primary PLL Mux */ -- cgit v1.2.3 From 80e521987bf73022dbb55805ce975125d2b293df Mon Sep 17 00:00:00 2001 From: Mingkai Hu Date: Wed, 7 Sep 2016 11:48:30 +0800 Subject: clk: qoriq: add ls1046a support Signed-off-by: Mingkai Hu Signed-off-by: Shaohui Xie Signed-off-by: Stephen Boyd --- drivers/clk/clk-qoriq.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 20b105584f82..9f8c4b8ae603 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -266,6 +266,31 @@ static const struct clockgen_muxinfo ls1043a_hwa2 = { }, }; +static const struct clockgen_muxinfo ls1046a_hwa1 = { + { + {}, + {}, + { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, + { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, + { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, + { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, + { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, + { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, + }, +}; + +static const struct clockgen_muxinfo ls1046a_hwa2 = { + { + {}, + { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, + { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, + { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, + {}, + {}, + { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, + }, +}; + static const struct clockgen_muxinfo t1023_hwa1 = { { {}, @@ -488,6 +513,21 @@ static const struct clockgen_chipinfo chipinfo[] = { .pll_mask = 0x07, .flags = CG_PLL_8BIT, }, + { + .compat = "fsl,ls1046a-clockgen", + .init_periph = t2080_init_periph, + .cmux_groups = { + &t1040_cmux + }, + .hwaccel = { + &ls1046a_hwa1, &ls1046a_hwa2 + }, + .cmux_to_group = { + 0, -1 + }, + .pll_mask = 0x07, + .flags = CG_PLL_8BIT, + }, { .compat = "fsl,ls2080a-clockgen", .cmux_groups = { @@ -1272,6 +1312,7 @@ CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init); CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init); CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init); CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init); +CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init); CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init); /* Legacy nodes */ -- cgit v1.2.3 From 06b8ec4eadde7054528b779974ae5ff998c0b0a2 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 23 Oct 2016 14:19:26 +0200 Subject: clk: pxa: remove unused variables This is a cleanup patch to remove unused values not used in their respective functions. Signed-off-by: Robert Jarzmik Signed-off-by: Stephen Boyd --- drivers/clk/pxa/clk-pxa27x.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index c40b1804f58c..afc395b4148e 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -221,14 +221,12 @@ static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw, unsigned long parent_rate) { unsigned long clkcfg; - unsigned int t, ht, b, osc_forced; + unsigned int ht, osc_forced; unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); - t = clkcfg & (1 << 0); ht = clkcfg & (1 << 2); - b = clkcfg & (1 << 3); if (osc_forced) return parent_rate; @@ -241,7 +239,7 @@ static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw, static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw) { unsigned long clkcfg; - unsigned int t, ht, b, osc_forced; + unsigned int t, ht, osc_forced; unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); @@ -251,7 +249,6 @@ static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw) asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); t = clkcfg & (1 << 0); ht = clkcfg & (1 << 2); - b = clkcfg & (1 << 3); if (ht || t) return PXA_CORE_TURBO; -- cgit v1.2.3 From 26bd423b88a7a5c5fe5a042a8d7209d5ebdcbd1b Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 23 Oct 2016 14:19:27 +0200 Subject: clk: pxa: core pll is not affected by t bit The t bit of clkfcfg doesn't affect the core pll clock, but it makes core clock select between core pll clock and core run clock. As such remove it from the core pll rate reporting function, while it remains in clk_pxa27x_core_get_parent(). Signed-off-by: Robert Jarzmik Signed-off-by: Stephen Boyd --- drivers/clk/pxa/clk-pxa25x.c | 4 +--- drivers/clk/pxa/clk-pxa27x.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c index a98b98e2a9e4..3bb603a27f2b 100644 --- a/drivers/clk/pxa/clk-pxa25x.c +++ b/drivers/clk/pxa/clk-pxa25x.c @@ -182,9 +182,7 @@ static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw, m = M_clk_mult[(cccr >> 5) & 0x03]; n2 = N2_clk_mult[(cccr >> 7) & 0x07]; - if (t) - return m * l * n2 * parent_rate / 2; - return m * l * parent_rate; + return m * l * n2 * parent_rate / 2; } PARENTS(clk_pxa25x_cpll) = { "osc_3_6864mhz" }; RATE_RO_OPS(clk_pxa25x_cpll, "cpll"); diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index afc395b4148e..3930053543a3 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -162,7 +162,7 @@ static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw, L = l * parent_rate; N = (L * n2) / 2; - return t ? N : L; + return N; } PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" }; RATE_RO_OPS(clk_pxa27x_cpll, "cpll"); -- cgit v1.2.3 From 7c5145191b2c5351ebc049f9a7108a6548889d56 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 23 Oct 2016 14:19:28 +0200 Subject: clk: pxa: b bit of clkcfg means fast bus The meaning of this bit was inverted : - when set to 0, system bus clock is half of the CPU run clock - when set to 1, system bus clock is the CPU run clock Signed-off-by: Robert Jarzmik Signed-off-by: Stephen Boyd --- drivers/clk/pxa/clk-pxa27x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index 3930053543a3..3b36e8d0f81e 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -291,9 +291,9 @@ static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw, if (osc_forced) return parent_rate; if (b) - return parent_rate / 2; - else return parent_rate; + else + return parent_rate / 2; } static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw) -- cgit v1.2.3 From fb16d9e50a3351048b56cdb479b52a91f66ac9f9 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 23 Oct 2016 14:19:29 +0200 Subject: clk: pxa: export core clocks pxaxxx_get_clk_frequency_khz() needs several clocks to be available through clk_get(), ie. the cpu clocks, system bus clock and memory clocks. Add the missing clkdev so that their rate can be acquired. Signed-off-by: Robert Jarzmik Signed-off-by: Stephen Boyd --- drivers/clk/pxa/clk-pxa25x.c | 9 ++++++--- drivers/clk/pxa/clk-pxa27x.c | 13 ++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c index 3bb603a27f2b..6a3009eec830 100644 --- a/drivers/clk/pxa/clk-pxa25x.c +++ b/drivers/clk/pxa/clk-pxa25x.c @@ -189,8 +189,10 @@ RATE_RO_OPS(clk_pxa25x_cpll, "cpll"); static void __init pxa25x_register_core(void) { - clk_register_clk_pxa25x_cpll(); - clk_register_clk_pxa25x_run(); + clkdev_pxa_register(CLK_NONE, "cpll", NULL, + clk_register_clk_pxa25x_cpll()); + clkdev_pxa_register(CLK_NONE, "run", NULL, + clk_register_clk_pxa25x_run()); clkdev_pxa_register(CLK_CORE, "core", NULL, clk_register_clk_pxa25x_core()); } @@ -212,7 +214,8 @@ static void __init pxa25x_base_clocks_init(void) { pxa25x_register_plls(); pxa25x_register_core(); - clk_register_clk_pxa25x_memory(); + clkdev_pxa_register(CLK_NONE, "system_bus", NULL, + clk_register_clk_pxa25x_memory()); } #define DUMMY_CLK(_con_id, _dev_id, _parent) \ diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index 3b36e8d0f81e..9fb40e884999 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -270,9 +270,10 @@ RATE_RO_OPS(clk_pxa27x_run, "run"); static void __init pxa27x_register_core(void) { - clk_register_clk_pxa27x_cpll(); - clk_register_clk_pxa27x_run(); - + clkdev_pxa_register(CLK_NONE, "cpll", NULL, + clk_register_clk_pxa27x_cpll()); + clkdev_pxa_register(CLK_NONE, "run", NULL, + clk_register_clk_pxa27x_run()); clkdev_pxa_register(CLK_CORE, "core", NULL, clk_register_clk_pxa27x_core()); } @@ -382,8 +383,10 @@ static void __init pxa27x_base_clocks_init(void) { pxa27x_register_plls(); pxa27x_register_core(); - clk_register_clk_pxa27x_system_bus(); - clk_register_clk_pxa27x_memory(); + clkdev_pxa_register(CLK_NONE, "system_bus", NULL, + clk_register_clk_pxa27x_system_bus()); + clkdev_pxa_register(CLK_NONE, "memory", NULL, + clk_register_clk_pxa27x_memory()); clk_register_clk_pxa27x_lcd_base(); } -- cgit v1.2.3 From f747597ea30a3b9ee9cdef692a1407e0c6be7a00 Mon Sep 17 00:00:00 2001 From: Abhishek Sahu Date: Wed, 21 Sep 2016 17:51:52 +0530 Subject: clk: qcom: ipq4019: changed i2c freq table The current I2C freq table uses MND values which is not applicable for I2C since its RCG does not have MND counter. This patch updates the freq table for 19.05 MHz clk frequency with FEPLL_200 parent. Signed-off-by: Abhishek Sahu Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-ipq4019.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/gcc-ipq4019.c b/drivers/clk/qcom/gcc-ipq4019.c index b593065de8db..33d09138f5e5 100644 --- a/drivers/clk/qcom/gcc-ipq4019.c +++ b/drivers/clk/qcom/gcc-ipq4019.c @@ -185,8 +185,7 @@ static struct clk_branch gcc_audio_pwm_clk = { }; static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] = { - F(19200000, P_XO, 1, 2, 5), - F(24000000, P_XO, 1, 1, 2), + F(19050000, P_FEPLL200, 10.5, 1, 1), { } }; -- cgit v1.2.3 From feb65645c1d259402eda6b45bd5c399a66826019 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 29 Sep 2016 14:05:42 +0530 Subject: clk: qcom: Add support for alpha pll hwfsm ops Some PLLs can support an HW FSM mode (different from the Votable FSMs, though its the same bit used to enable Votable FSMs as well as HW FSMs) which enables the HW to do the bypass/reset/enable-output-ctrl sequence on its own. So all thats needed from SW is to set the FSM_ENA bit. PLL_ACTIVE_FLAG is whats used to check if the PLL is active/enabled. Some of the PLLs which support HW FSM can also need an OFFLINE request that needs to be toggled across the enable/disable. We use a flag to identify such cases and handle them. Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 102 ++++++++++++++++++++++++++++++++++----- drivers/clk/qcom/clk-alpha-pll.h | 3 ++ 2 files changed, 93 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index e6a03eaf7a93..0cfbb2940e3e 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -23,12 +23,15 @@ # define PLL_OUTCTRL BIT(0) # define PLL_BYPASSNL BIT(1) # define PLL_RESET_N BIT(2) +# define PLL_OFFLINE_REQ BIT(7) # define PLL_LOCK_COUNT_SHIFT 8 # define PLL_LOCK_COUNT_MASK 0x3f # define PLL_BIAS_COUNT_SHIFT 14 # define PLL_BIAS_COUNT_MASK 0x3f # define PLL_VOTE_FSM_ENA BIT(20) +# define PLL_FSM_ENA BIT(20) # define PLL_VOTE_FSM_RESET BIT(21) +# define PLL_OFFLINE_ACK BIT(28) # define PLL_ACTIVE_FLAG BIT(30) # define PLL_LOCK_DET BIT(31) @@ -62,9 +65,10 @@ #define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \ struct clk_alpha_pll_postdiv, clkr) -static int wait_for_pll(struct clk_alpha_pll *pll) +static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse, + const char *action) { - u32 val, mask, off; + u32 val, off; int count; int ret; const char *name = clk_hw_get_name(&pll->clkr.hw); @@ -74,26 +78,91 @@ static int wait_for_pll(struct clk_alpha_pll *pll) if (ret) return ret; - if (val & PLL_VOTE_FSM_ENA) - mask = PLL_ACTIVE_FLAG; - else - mask = PLL_LOCK_DET; - - /* Wait for pll to enable. */ for (count = 100; count > 0; count--) { ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); if (ret) return ret; - if ((val & mask) == mask) + if (inverse && !(val & mask)) + return 0; + else if ((val & mask) == mask) return 0; udelay(1); } - WARN(1, "%s didn't enable after voting for it!\n", name); + WARN(1, "%s failed to %s!\n", name, action); return -ETIMEDOUT; } +#define wait_for_pll_enable_active(pll) \ + wait_for_pll(pll, PLL_ACTIVE_FLAG, 0, "enable") + +#define wait_for_pll_enable_lock(pll) \ + wait_for_pll(pll, PLL_LOCK_DET, 0, "enable") + +#define wait_for_pll_disable(pll) \ + wait_for_pll(pll, PLL_ACTIVE_FLAG, 1, "disable") + +#define wait_for_pll_offline(pll) \ + wait_for_pll(pll, PLL_OFFLINE_ACK, 0, "offline") + +static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw) +{ + int ret; + u32 val, off; + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + + off = pll->offset; + ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); + if (ret) + return ret; + + val |= PLL_FSM_ENA; + + if (pll->flags & SUPPORTS_OFFLINE_REQ) + val &= ~PLL_OFFLINE_REQ; + + ret = regmap_write(pll->clkr.regmap, off + PLL_MODE, val); + if (ret) + return ret; + + /* Make sure enable request goes through before waiting for update */ + mb(); + + return wait_for_pll_enable_active(pll); +} + +static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw) +{ + int ret; + u32 val, off; + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + + off = pll->offset; + ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); + if (ret) + return; + + if (pll->flags & SUPPORTS_OFFLINE_REQ) { + ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, + PLL_OFFLINE_REQ, PLL_OFFLINE_REQ); + if (ret) + return; + + ret = wait_for_pll_offline(pll); + if (ret) + return; + } + + /* Disable hwfsm */ + ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, + PLL_FSM_ENA, 0); + if (ret) + return; + + wait_for_pll_disable(pll); +} + static int clk_alpha_pll_enable(struct clk_hw *hw) { int ret; @@ -112,7 +181,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw) ret = clk_enable_regmap(hw); if (ret) return ret; - return wait_for_pll(pll); + return wait_for_pll_enable_active(pll); } /* Skip if already enabled */ @@ -136,7 +205,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw) if (ret) return ret; - ret = wait_for_pll(pll); + ret = wait_for_pll_enable_lock(pll); if (ret) return ret; @@ -300,6 +369,15 @@ const struct clk_ops clk_alpha_pll_ops = { }; EXPORT_SYMBOL_GPL(clk_alpha_pll_ops); +const struct clk_ops clk_alpha_pll_hwfsm_ops = { + .enable = clk_alpha_pll_hwfsm_enable, + .disable = clk_alpha_pll_hwfsm_disable, + .recalc_rate = clk_alpha_pll_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, + .set_rate = clk_alpha_pll_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); + static unsigned long clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 90ce2016e1a0..0deb286da7e3 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -34,6 +34,8 @@ struct clk_alpha_pll { const struct pll_vco *vco_table; size_t num_vco; +#define SUPPORTS_OFFLINE_REQ BIT(0) + u8 flags; struct clk_regmap clkr; }; @@ -52,6 +54,7 @@ struct clk_alpha_pll_postdiv { }; extern const struct clk_ops clk_alpha_pll_ops; +extern const struct clk_ops clk_alpha_pll_hwfsm_ops; extern const struct clk_ops clk_alpha_pll_postdiv_ops; #endif -- cgit v1.2.3 From 9f4e627702c852954b66f221c6c75c54ab78146a Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 29 Sep 2016 14:05:43 +0530 Subject: clk: qcom: Add support to initialize alpha plls Add a function to do initial configuration of the alpha plls Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 31 +++++++++++++++++++++++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 20 ++++++++++++++++++++ 2 files changed, 51 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 0cfbb2940e3e..a1188c86eea5 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -49,6 +49,7 @@ #define PLL_USER_CTL_U 0x14 #define PLL_CONFIG_CTL 0x18 +#define PLL_CONFIG_CTL_U 0x20 #define PLL_TEST_CTL 0x1c #define PLL_TEST_CTL_U 0x20 #define PLL_STATUS 0x24 @@ -106,6 +107,36 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse, #define wait_for_pll_offline(pll) \ wait_for_pll(pll, PLL_OFFLINE_ACK, 0, "offline") +void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config) +{ + u32 val, mask; + u32 off = pll->offset; + + regmap_write(regmap, off + PLL_L_VAL, config->l); + regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha); + regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val); + regmap_write(regmap, off + PLL_CONFIG_CTL_U, config->config_ctl_hi_val); + + val = config->main_output_mask; + val |= config->aux_output_mask; + val |= config->aux2_output_mask; + val |= config->early_output_mask; + val |= config->pre_div_val; + val |= config->post_div_val; + val |= config->vco_val; + + mask = config->main_output_mask; + mask |= config->aux_output_mask; + mask |= config->aux2_output_mask; + mask |= config->early_output_mask; + mask |= config->pre_div_mask; + mask |= config->post_div_mask; + mask |= config->vco_mask; + + regmap_update_bits(regmap, off + PLL_USER_CTL, mask, val); +} + static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw) { int ret; diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 0deb286da7e3..2f48530ec102 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -53,8 +53,28 @@ struct clk_alpha_pll_postdiv { struct clk_regmap clkr; }; +struct alpha_pll_config { + u32 l; + u32 alpha; + u32 config_ctl_val; + u32 config_ctl_hi_val; + u32 main_output_mask; + u32 aux_output_mask; + u32 aux2_output_mask; + u32 early_output_mask; + u32 pre_div_val; + u32 pre_div_mask; + u32 post_div_val; + u32 post_div_mask; + u32 vco_val; + u32 vco_mask; +}; + extern const struct clk_ops clk_alpha_pll_ops; extern const struct clk_ops clk_alpha_pll_hwfsm_ops; extern const struct clk_ops clk_alpha_pll_postdiv_ops; +void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config); + #endif -- cgit v1.2.3 From 31256f4892b443e1cf03de48ea447a86ec32038e Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 29 Sep 2016 14:05:44 +0530 Subject: clk: qcom: handle alpha PLLs with 16bit alpha val registers Some alpha PLLs have support for only a 16bit programable Alpha Value (as against the default 40bits). Add a flag to handle the 16bit alpha registers Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 24 +++++++++++++++++------- drivers/clk/qcom/clk-alpha-pll.h | 1 + 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index a1188c86eea5..fd3e32c2d0a8 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -59,6 +59,7 @@ */ #define ALPHA_REG_BITWIDTH 40 #define ALPHA_BITWIDTH 32 +#define ALPHA_16BIT_MASK 0xffff #define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \ struct clk_alpha_pll, clkr) @@ -334,9 +335,14 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl); if (ctl & PLL_ALPHA_EN) { regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low); - regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, &high); - a = (u64)high << 32 | low; - a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH; + if (pll->flags & SUPPORTS_16BIT_ALPHA) { + a = low & ALPHA_16BIT_MASK; + } else { + regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, + &high); + a = (u64)high << 32 | low; + a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH; + } } return alpha_pll_calc_rate(prate, l, a); @@ -357,11 +363,15 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; } - a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH); - regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l); - regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, a); - regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32); + + if (pll->flags & SUPPORTS_16BIT_ALPHA) { + regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, + a & ALPHA_16BIT_MASK); + } else { + a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH); + regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32); + } regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_VCO_MASK << PLL_VCO_SHIFT, diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 2f48530ec102..4808ff7dd31c 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -35,6 +35,7 @@ struct clk_alpha_pll { const struct pll_vco *vco_table; size_t num_vco; #define SUPPORTS_OFFLINE_REQ BIT(0) +#define SUPPORTS_16BIT_ALPHA BIT(1) u8 flags; struct clk_regmap clkr; -- cgit v1.2.3 From 400d9fda39bc8e16412103796040aef484fe7f5d Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 29 Sep 2016 14:05:45 +0530 Subject: clk: qcom: Enable FSM mode for votable alpha PLLs The votable alpha PLLs need to have the fsm mode enabled as part of the initialization. The sequence seems to be the same as used by clk-pll, so move the function which does this into a common place and reuse it for the clk-alpha-pll Signed-off-by: Rajendra Nayak Signed-off-by: Taniya Das Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 4 ++++ drivers/clk/qcom/clk-alpha-pll.h | 1 + drivers/clk/qcom/clk-pll.c | 31 +++---------------------------- drivers/clk/qcom/common.c | 21 +++++++++++++++++++++ drivers/clk/qcom/common.h | 9 +++++++++ 5 files changed, 38 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index fd3e32c2d0a8..c6ddc04ea2f0 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -18,6 +18,7 @@ #include #include "clk-alpha-pll.h" +#include "common.h" #define PLL_MODE 0x00 # define PLL_OUTCTRL BIT(0) @@ -136,6 +137,9 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, mask |= config->vco_mask; regmap_update_bits(regmap, off + PLL_USER_CTL, mask, val); + + if (pll->flags & SUPPORTS_FSM_MODE) + qcom_pll_set_fsm_mode(regmap, off + PLL_MODE, 6, 0); } static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw) diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 4808ff7dd31c..d6e1ee2c7348 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -36,6 +36,7 @@ struct clk_alpha_pll { size_t num_vco; #define SUPPORTS_OFFLINE_REQ BIT(0) #define SUPPORTS_16BIT_ALPHA BIT(1) +#define SUPPORTS_FSM_MODE BIT(2) u8 flags; struct clk_regmap clkr; diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c index 5b940d629045..cb6cb8710daf 100644 --- a/drivers/clk/qcom/clk-pll.c +++ b/drivers/clk/qcom/clk-pll.c @@ -23,16 +23,11 @@ #include #include "clk-pll.h" +#include "common.h" #define PLL_OUTCTRL BIT(0) #define PLL_BYPASSNL BIT(1) #define PLL_RESET_N BIT(2) -#define PLL_LOCK_COUNT_SHIFT 8 -#define PLL_LOCK_COUNT_MASK 0x3f -#define PLL_BIAS_COUNT_SHIFT 14 -#define PLL_BIAS_COUNT_MASK 0x3f -#define PLL_VOTE_FSM_ENA BIT(20) -#define PLL_VOTE_FSM_RESET BIT(21) static int clk_pll_enable(struct clk_hw *hw) { @@ -228,26 +223,6 @@ const struct clk_ops clk_pll_vote_ops = { }; EXPORT_SYMBOL_GPL(clk_pll_vote_ops); -static void -clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap, u8 lock_count) -{ - u32 val; - u32 mask; - - /* De-assert reset to FSM */ - regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0); - - /* Program bias count and lock count */ - val = 1 << PLL_BIAS_COUNT_SHIFT | lock_count << PLL_LOCK_COUNT_SHIFT; - mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT; - mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT; - regmap_update_bits(regmap, pll->mode_reg, mask, val); - - /* Enable PLL FSM voting */ - regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_ENA, - PLL_VOTE_FSM_ENA); -} - static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap, const struct pll_config *config) { @@ -280,7 +255,7 @@ void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap, { clk_pll_configure(pll, regmap, config); if (fsm_mode) - clk_pll_set_fsm_mode(pll, regmap, 8); + qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 8); } EXPORT_SYMBOL_GPL(clk_pll_configure_sr); @@ -289,7 +264,7 @@ void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap, { clk_pll_configure(pll, regmap, config); if (fsm_mode) - clk_pll_set_fsm_mode(pll, regmap, 0); + qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 0); } EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp); diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index fffcbaf0fba7..6ec81bd92611 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -74,6 +74,27 @@ qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) } EXPORT_SYMBOL_GPL(qcom_cc_map); +void +qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count) +{ + u32 val; + u32 mask; + + /* De-assert reset to FSM */ + regmap_update_bits(map, reg, PLL_VOTE_FSM_RESET, 0); + + /* Program bias count and lock count */ + val = bias_count << PLL_BIAS_COUNT_SHIFT | + lock_count << PLL_LOCK_COUNT_SHIFT; + mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT; + mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT; + regmap_update_bits(map, reg, mask, val); + + /* Enable PLL FSM voting */ + regmap_update_bits(map, reg, PLL_VOTE_FSM_ENA, PLL_VOTE_FSM_ENA); +} +EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode); + static void qcom_cc_del_clk_provider(void *data) { of_clk_del_provider(data); diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h index ae9bdeb21f29..9fb5b8e89071 100644 --- a/drivers/clk/qcom/common.h +++ b/drivers/clk/qcom/common.h @@ -22,6 +22,13 @@ struct freq_tbl; struct clk_hw; struct parent_map; +#define PLL_LOCK_COUNT_SHIFT 8 +#define PLL_LOCK_COUNT_MASK 0x3f +#define PLL_BIAS_COUNT_SHIFT 14 +#define PLL_BIAS_COUNT_MASK 0x3f +#define PLL_VOTE_FSM_ENA BIT(20) +#define PLL_VOTE_FSM_RESET BIT(21) + struct qcom_cc_desc { const struct regmap_config *config; struct clk_regmap **clks; @@ -34,6 +41,8 @@ struct qcom_cc_desc { extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate); +extern void +qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count); extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src); -- cgit v1.2.3 From 0a379e27db5164a7e49a3717b16a59469d944b5d Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Wed, 2 Nov 2016 08:44:56 +0200 Subject: drm/i915/bxt: Don't set OCL2_LDOFUSE_PWR_DIS bit in phy init sequence Hardware engineers confirmed that writing to it has no effect, as implied by the FIXME comment. v2: Also remove comment from bxt_ddi_phy_verify_state(). (Imre) Cc: Imre Deak Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1478069096-11209-1-git-send-email-ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/intel_dpio_phy.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 4a6164a20718..7a8e82dabbf2 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -365,22 +365,6 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, I915_WRITE(BXT_PORT_CL2CM_DW6(phy), val); } - val = I915_READ(BXT_PORT_CL1CM_DW30(phy)); - val &= ~OCL2_LDOFUSE_PWR_DIS; - /* - * On PHY1 disable power on the second channel, since no port is - * connected there. On PHY0 both channels have a port, so leave it - * enabled. - * TODO: port C is only connected on BXT-P, so on BXT0/1 we should - * power down the second channel on PHY0 as well. - * - * FIXME: Clarify programming of the following, the register is - * read-only with bit 6 fixed at 0 at least in stepping A. - */ - if (!phy_info->dual_channel) - val |= OCL2_LDOFUSE_PWR_DIS; - I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val); - if (phy_info->rcomp_phy != -1) { uint32_t grc_code; /* @@ -508,11 +492,6 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN, "BXT_PORT_CL2CM_DW6(%d)", phy); - /* - * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS, - * at least on stepping A this bit is read-only and fixed at 0. - */ - if (phy_info->rcomp_phy != -1) { u32 grc_code = dev_priv->bxt_phy_grc; -- cgit v1.2.3 From aaf7642e98917fc95c260cbee98d2f426754b265 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 10 Jun 2016 12:50:39 +0300 Subject: drm/omap: fix plane check when crtc is disabled I sometimes see: [drm:drm_framebuffer_remove [drm]] *ERROR* failed to reset crtc ed2a6c00 when fb was deleted: -22 which comes from drm_framebuffer_remove() when it's disabling the crtc with zeroed drm_mode_set. The problem in omap_plane_atomic_check() is that it will use those zeroed fields to verify if the setup is correct. This patch makes omap_plane_atomic_check() return 0 if the crtc is disabled. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_plane.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 0ffd5b930ec0..7bd24185f33c 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -164,6 +164,9 @@ static int omap_plane_atomic_check(struct drm_plane *plane, if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); + if (!crtc_state->enable) + return 0; + if (state->crtc_x < 0 || state->crtc_y < 0) return -EINVAL; -- cgit v1.2.3 From 70dd2a62aa35687ee01c756ea201ea3e970c28ad Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 10 Jun 2016 12:50:53 +0300 Subject: drm/omap: cleanup omap_plane_atomic_check() Clean up omap_plane_atomic_check() with: - Check state->fb first. If no fb, return 0. - use drm_atomic_get_existing_crtc_state() instead of drm_atomic_get_crtc_state() Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_plane.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 7bd24185f33c..adab71b17017 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -157,12 +157,17 @@ static int omap_plane_atomic_check(struct drm_plane *plane, { struct drm_crtc_state *crtc_state; - if (!state->crtc) + if (!state->fb) return 0; - crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); + /* crtc should only be NULL when disabling (i.e., !state->fb) */ + if (WARN_ON(!state->crtc)) + return 0; + + crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc); + /* we should have a crtc state if the plane is attached to a crtc */ + if (WARN_ON(!crtc_state)) + return 0; if (!crtc_state->enable) return 0; @@ -176,11 +181,9 @@ static int omap_plane_atomic_check(struct drm_plane *plane, if (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay) return -EINVAL; - if (state->fb) { - if (state->rotation != DRM_ROTATE_0 && - !omap_framebuffer_supports_rotation(state->fb)) - return -EINVAL; - } + if (state->rotation != DRM_ROTATE_0 && + !omap_framebuffer_supports_rotation(state->fb)) + return -EINVAL; return 0; } -- cgit v1.2.3 From cfb73f202dd9952bbcdb12895813ea32008db3c5 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 10 Jun 2016 12:44:31 +0300 Subject: drm/omap: print error instead of WARN() if plane setup fails omap_plane_atomic_update() does WARN_ON() if dispc rejects the given plane config. Change that to dev_err() to lessen the possible spam. To fix this correctly, the plane setup needs much more work by creating a check function for dispc setup, so that we could reliably check the config in atomic_check, instead of only noticing the problem when programming dispc. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_plane.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index adab71b17017..9c43cb481e62 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -131,7 +131,9 @@ static void omap_plane_atomic_update(struct drm_plane *plane, /* and finally, update omapdss: */ ret = dispc_ovl_setup(omap_plane->id, &info, false, omap_crtc_timings(state->crtc), false); - if (WARN_ON(ret)) { + if (ret) { + dev_err(plane->dev->dev, "Failed to setup plane %s\n", + omap_plane->name); dispc_ovl_enable(omap_plane->id, false); return; } -- cgit v1.2.3 From 0cac5b61ff3c145dcba7f39880f8ca94e848162b Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 1 Jul 2016 09:27:21 -0500 Subject: drm/omap: remove unneeded conversions to bool Found with scripts/coccinelle/misc/boolconv.cocci. Signed-off-by: Andrew F. Davis Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dispc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 535240fba671..818df6be97fa 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -1679,7 +1679,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, { int scale_x = out_width != orig_width; int scale_y = out_height != orig_height; - bool chroma_upscale = plane != OMAP_DSS_WB ? true : false; + bool chroma_upscale = plane != OMAP_DSS_WB; if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) return; @@ -3110,9 +3110,9 @@ static bool _dispc_mgr_pclk_ok(enum omap_channel channel, unsigned long pclk) { if (dss_mgr_is_lcd(channel)) - return pclk <= dispc.feat->max_lcd_pclk ? true : false; + return pclk <= dispc.feat->max_lcd_pclk; else - return pclk <= dispc.feat->max_tv_pclk ? true : false; + return pclk <= dispc.feat->max_tv_pclk; } bool dispc_mgr_timings_ok(enum omap_channel channel, -- cgit v1.2.3 From a7e8cd39af6ac815736c31a65898a9951d9d2bd3 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 31 Aug 2016 20:17:05 +0300 Subject: drm/omapdrm: Remove double gamma table write in omap_crtc_atomic_flush() Remove double gamma table write in omap_crtc_atomic_flush(). Fixes commit 492a426a2fc53 ("drm/omapdrm: Implement gamma_lut atomic crtc properties") Signed-off-by: Jyri Sarha Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 16c691dbc372..a25d5f769d6f 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -411,19 +411,6 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, dispc_mgr_set_gamma(omap_crtc->channel, lut, length); } - if (crtc->state->color_mgmt_changed) { - struct drm_color_lut *lut = NULL; - uint length = 0; - - if (crtc->state->gamma_lut) { - lut = (struct drm_color_lut *) - crtc->state->gamma_lut->data; - length = crtc->state->gamma_lut->length / - sizeof(*lut); - } - dispc_mgr_set_gamma(omap_crtc->channel, lut, length); - } - if (dispc_mgr_is_enabled(omap_crtc->channel)) { DBG("%s: GO", omap_crtc->name); -- cgit v1.2.3 From 6cb096562e36009d9d6427851a6b441edabe66ab Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 27 Nov 2015 11:00:37 +0200 Subject: drm/omap: omap_gem: Do not try to unmap page which is not mapped It might be possible that the page has been unmapped already in omap_gem_cpu_sync() so check before calling dma_unmap_page(). Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_gem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 505dee0db973..d4e1e11466f8 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -336,8 +336,10 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj) if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { int i, npages = obj->size >> PAGE_SHIFT; for (i = 0; i < npages; i++) { - dma_unmap_page(obj->dev->dev, omap_obj->addrs[i], - PAGE_SIZE, DMA_BIDIRECTIONAL); + if (omap_obj->addrs[i]) + dma_unmap_page(obj->dev->dev, + omap_obj->addrs[i], + PAGE_SIZE, DMA_BIDIRECTIONAL); } } -- cgit v1.2.3 From bda63d5c709361f09ecdc3f67778081c455065f9 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 17 Sep 2016 15:53:54 +0000 Subject: drm/omap: fix return value check in dsi_bind() Fix the retrn value check which testing the wrong variable in dsi_bind(). Signed-off-by: Wei Yongjun Reviewed-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index e1be5e795cd8..a567ebd7ccb3 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -5342,7 +5342,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) dsi->phy_base = devm_ioremap(&dsidev->dev, res->start, resource_size(res)); - if (!dsi->proto_base) { + if (!dsi->phy_base) { DSSERR("can't ioremap DSI PHY\n"); return -ENOMEM; } @@ -5362,7 +5362,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) dsi->pll_base = devm_ioremap(&dsidev->dev, res->start, resource_size(res)); - if (!dsi->proto_base) { + if (!dsi->pll_base) { DSSERR("can't ioremap DSI PLL\n"); return -ENOMEM; } -- cgit v1.2.3 From bd9642b9b8d329bcb0b187aee34c89fc182f2c4d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 13:35:26 +0300 Subject: video: of: display_timing: Add support for syncclk-active property Configure the DISPLAY_FLAGS_SYNC_POSEDGE/NEGEDGE flags according to the binding document. If the syncclk-active is present in DT, configure the flags accordingly, if it is omitted it means that the SYNC edge is following the pixdata configuration. Signed-off-by: Peter Ujfalusi CC: Rob Herring CC: Mark Rutland CC: devicetree@vger.kernel.org Signed-off-by: Tomi Valkeinen --- drivers/video/of_display_timing.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c index 8a1076beecd3..db992c684f09 100644 --- a/drivers/video/of_display_timing.c +++ b/drivers/video/of_display_timing.c @@ -88,6 +88,15 @@ static int of_parse_display_timing(const struct device_node *np, dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : DISPLAY_FLAGS_PIXDATA_NEGEDGE; + if (!of_property_read_u32(np, "syncclk-active", &val)) + dt->flags |= val ? DISPLAY_FLAGS_SYNC_POSEDGE : + DISPLAY_FLAGS_SYNC_NEGEDGE; + else if (dt->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_PIXDATA_NEGEDGE)) + dt->flags |= dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? + DISPLAY_FLAGS_SYNC_POSEDGE : + DISPLAY_FLAGS_SYNC_NEGEDGE; + if (of_property_read_bool(np, "interlaced")) dt->flags |= DISPLAY_FLAGS_INTERLACED; if (of_property_read_bool(np, "doublescan")) -- cgit v1.2.3 From 81899060de35d80f17020d322e77311f1b255885 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:46 +0300 Subject: drm/omap: omap_display_timings: rename x_res to hactive In preparation to move the stack to use the generic videmode struct for display timing information rename the x_res member to hactive. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- .../gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 8 ++++---- .../drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 2 +- .../gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 2 +- .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 2 +- .../gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 2 +- .../gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 +- .../gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 16 ++++++++-------- drivers/gpu/drm/omapdrm/dss/display.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/dpi.c | 2 +- drivers/gpu/drm/omapdrm/dss/dsi.c | 20 ++++++++++---------- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 2 +- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/venc.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 ++-- 22 files changed, 49 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 3485d1ecd655..190a03672181 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -30,7 +30,7 @@ struct panel_drv_data { }; static const struct omap_video_timings tvc_pal_timings = { - .x_res = 720, + .hactive = 720, .y_res = 574, .pixelclock = 13500000, .hsw = 64, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index 684b7aeda411..c6e02e1a3799 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -20,7 +20,7 @@ #include "../dss/omapdss.h" static const struct omap_video_timings dvic_default_timings = { - .x_res = 640, + .hactive = 640, .y_res = 480, .pixelclock = 23500000, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 7bdf83af9797..ef5ae08b362b 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -22,7 +22,7 @@ #include "../dss/omapdss.h" static const struct omap_video_timings hdmic_default_timings = { - .x_res = 640, + .hactive = 640, .y_res = 480, .pixelclock = 25175000, .hsw = 96, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c index b1f3b818edf4..c34f2aa0118b 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c @@ -382,7 +382,7 @@ static const struct backlight_ops dsicm_bl_ops = { static void dsicm_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { - *xres = dssdev->panel.timings.x_res; + *xres = dssdev->panel.timings.hactive; *yres = dssdev->panel.timings.y_res; } @@ -892,7 +892,7 @@ static int dsicm_update(struct omap_dss_device *dssdev, /* XXX no need to send this every frame, but dsi break if not done */ r = dsicm_set_update_window(ddata, 0, 0, - dssdev->panel.timings.x_res, + dssdev->panel.timings.hactive, dssdev->panel.timings.y_res); if (r) goto err; @@ -1024,7 +1024,7 @@ static int dsicm_memory_read(struct omap_dss_device *dssdev, } size = min(w * h * 3, - dssdev->panel.timings.x_res * + dssdev->panel.timings.hactive * dssdev->panel.timings.y_res * 3); in->ops.dsi->bus_lock(in); @@ -1186,7 +1186,7 @@ static int dsicm_probe(struct platform_device *pdev) if (r) return r; - ddata->timings.x_res = 864; + ddata->timings.hactive = 864; ddata->timings.y_res = 480; ddata->timings.pixelclock = 864 * 480 * 60; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 6dfb96cea293..c8b5462f462f 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -20,7 +20,7 @@ #include "../dss/omapdss.h" static struct omap_video_timings lb035q02_timings = { - .x_res = 320, + .hactive = 320, .y_res = 240, .pixelclock = 6500000, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index 9f3d6f48f3e1..f0895c7b6d5c 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -66,7 +66,7 @@ static const struct { }; static const struct omap_video_timings nec_8048_panel_timings = { - .x_res = LCD_XRES, + .hactive = LCD_XRES, .y_res = LCD_YRES, .pixelclock = LCD_PIXEL_CLOCK, .hfp = 6, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index 3d3efc561ea9..b66ad743c607 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -36,7 +36,7 @@ struct panel_drv_data { }; static const struct omap_video_timings sharp_ls_timings = { - .x_res = 480, + .hactive = 480, .y_res = 640, .pixelclock = 19200000, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 3557a4c7dd7b..2764bc94a205 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -93,7 +93,7 @@ struct panel_drv_data { }; static const struct omap_video_timings acx565akm_panel_timings = { - .x_res = 800, + .hactive = 800, .y_res = 480, .pixelclock = 24000000, .hfp = 28, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index e859b3f893f7..935728405cde 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -43,7 +43,7 @@ struct panel_drv_data { }; static struct omap_video_timings td028ttec1_panel_timings = { - .x_res = 480, + .hactive = 480, .y_res = 640, .pixelclock = 22153000, .hfp = 24, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 66c6bbe6472b..fe8166640da8 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -73,7 +73,7 @@ struct panel_drv_data { }; static const struct omap_video_timings tpo_td043_timings = { - .x_res = 800, + .hactive = 800, .y_res = 480, .pixelclock = 36000000, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 818df6be97fa..b34ac915a761 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2189,7 +2189,7 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, u64 val, blank; int i; - nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; + nonactive = t->hactive + t->hfp + t->hsw + t->hbp - out_width; i = 0; if (out_height < height) @@ -2242,7 +2242,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, return (unsigned long) pclk; if (height > out_height) { - unsigned int ppl = mgr_timings->x_res; + unsigned int ppl = mgr_timings->hactive; tmp = (u64)pclk * height * out_width; do_div(tmp, 2 * out_height * ppl); @@ -2819,7 +2819,7 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, const u8 zorder = 0, global_alpha = 0; const bool replication = false; bool truncation; - int in_width = mgr_timings->x_res; + int in_width = mgr_timings->hactive; int in_height = mgr_timings->y_res; enum omap_overlay_caps caps = OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA; @@ -3118,7 +3118,7 @@ static bool _dispc_mgr_pclk_ok(enum omap_channel channel, bool dispc_mgr_timings_ok(enum omap_channel channel, const struct omap_video_timings *timings) { - if (!_dispc_mgr_size_ok(timings->x_res, timings->y_res)) + if (!_dispc_mgr_size_ok(timings->hactive, timings->y_res)) return false; if (!_dispc_mgr_pclk_ok(channel, timings->pixelclock)) @@ -3259,7 +3259,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, unsigned long ht, vt; struct omap_video_timings t = *timings; - DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res); + DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.y_res); if (!dispc_mgr_timings_ok(channel, &t)) { BUG(); @@ -3271,7 +3271,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, t.vfp, t.vbp, t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); - xtot = t.x_res + t.hfp + t.hsw + t.hbp; + xtot = t.hactive + t.hfp + t.hsw + t.hbp; ytot = t.y_res + t.vfp + t.vsw + t.vbp; ht = timings->pixelclock / xtot; @@ -3294,7 +3294,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, 19, 17); } - dispc_mgr_set_size(channel, t.x_res, t.y_res); + dispc_mgr_set_size(channel, t.hactive, t.y_res); } EXPORT_SYMBOL(dispc_mgr_set_timings); @@ -4220,7 +4220,7 @@ static const struct dispc_errata_i734_data { struct dss_lcd_mgr_config lcd_conf; } i734 = { .timings = { - .x_res = 8, .y_res = 1, + .hactive = 8, .y_res = 1, .pixelclock = 16000000, .hsw = 8, .hfp = 4, .hbp = 4, .vsw = 1, .vfp = 1, .vbp = 1, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 8dcdd7cf9937..4808cc8368c5 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -35,7 +35,7 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { - *xres = dssdev->panel.timings.x_res; + *xres = dssdev->panel.timings.hactive; *yres = dssdev->panel.timings.y_res; } EXPORT_SYMBOL(omapdss_default_get_resolution); @@ -224,7 +224,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, memset(ovt, 0, sizeof(*ovt)); ovt->pixelclock = vm->pixelclock; - ovt->x_res = vm->hactive; + ovt->hactive = vm->hactive; ovt->hbp = vm->hback_porch; ovt->hfp = vm->hfront_porch; ovt->hsw = vm->hsync_len; @@ -257,7 +257,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->pixelclock = ovt->pixelclock; - vm->hactive = ovt->x_res; + vm->hactive = ovt->hactive; vm->hback_porch = ovt->hbp; vm->hfront_porch = ovt->hfp; vm->hsync_len = ovt->hsw; diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index b268295b76cf..d653f492cbfd 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c @@ -512,7 +512,7 @@ static int dpi_check_timings(struct omap_dss_device *dssdev, struct dpi_clk_calc_ctx ctx; bool ok; - if (timings->x_res % 8 != 0) + if (timings->hactive % 8 != 0) return -EINVAL; if (!dispc_mgr_timings_ok(channel, timings)) diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index a567ebd7ccb3..2bd4d0cdd2f2 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -3326,7 +3326,7 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev) * Don't use line buffers if width is greater than the video * port's line buffer size */ - if (dsi->line_buffer_size <= timings->x_res * bpp / 8) + if (dsi->line_buffer_size <= timings->hactive * bpp / 8) num_line_buffers = 0; else num_line_buffers = 2; @@ -3494,7 +3494,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev) exiths_clk = ths_exit + tclk_trail; - width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); + width_bytes = DIV_ROUND_UP(timings->hactive * bpp, 8); bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl); if (!hsa_blanking_mode) { @@ -3713,7 +3713,7 @@ static void dsi_proto_timings(struct platform_device *dsidev) t_he = hsync_end ? ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; - width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); + width_bytes = DIV_ROUND_UP(timings->hactive * bpp, 8); /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */ tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp + @@ -3856,7 +3856,7 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) /* MODE, 1 = video mode */ REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); - word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8); + word_count = DIV_ROUND_UP(dsi->timings.hactive * bpp, 8); dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); @@ -3918,7 +3918,7 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev) int r; const unsigned channel = dsi->update_channel; const unsigned line_buf_size = dsi->line_buffer_size; - u16 w = dsi->timings.x_res; + u16 w = dsi->timings.hactive; u16 h = dsi->timings.y_res; DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); @@ -4056,7 +4056,7 @@ static int dsi_update(struct omap_dss_device *dssdev, int channel, dsi->framedone_callback = callback; dsi->framedone_data = data; - dw = dsi->timings.x_res; + dw = dsi->timings.hactive; dh = dsi->timings.y_res; #ifdef DSI_PERF_MEASURE @@ -4361,7 +4361,7 @@ static void print_dispc_vm(const char *str, const struct omap_video_timings *t) unsigned long pck = t->pixelclock; int hact, bl, tot; - hact = t->x_res; + hact = t->hactive; bl = t->hsw + t->hbp + t->hfp; tot = hact + bl; @@ -4402,7 +4402,7 @@ static void print_dsi_dispc_vm(const char *str, vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); vm.hbp = div64_u64((u64)t->hbp * pck, byteclk); vm.hfp = div64_u64((u64)t->hfp * pck, byteclk); - vm.x_res = t->hact; + vm.hactive = t->hact; print_dispc_vm(str, &vm); } @@ -4421,7 +4421,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, *t = *ctx->config->timings; t->pixelclock = pck; - t->x_res = ctx->config->timings->x_res; + t->hactive = ctx->config->timings->hactive; t->y_res = ctx->config->timings->y_res; t->hsw = t->hfp = t->hbp = t->vsw = 1; t->vfp = t->vbp = 0; @@ -4525,7 +4525,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) dispc_pck = ctx->dispc_cinfo.pck; dispc_tput = (u64)dispc_pck * bitspp; - xres = req_vm->x_res; + xres = req_vm->hactive; panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw; panel_htot = xres + panel_hbl; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index cbd28dfdb86a..c5e89c887687 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -171,7 +171,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) p = &hdmi.cfg.timings; - DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); + DSSDBG("hdmi_power_on hactive= %d y_res = %d\n", p->hactive, p->y_res); pc = p->pixelclock; if (p->double_pixel) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 0c0a5139a301..829d22253972 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -183,7 +183,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) p = &hdmi.cfg.timings; - DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); + DSSDBG("hdmi_power_on hactive= %d y_res = %d\n", p->hactive, p->y_res); pc = p->pixelclock; if (p->double_pixel) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 8ab2093daa12..cecc400b08e2 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -316,7 +316,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, } if (cfg->timings.double_pixel) { - video_cfg->v_fc_config.timings.x_res *= 2; + video_cfg->v_fc_config.timings.hactive *= 2; video_cfg->hblank *= 2; video_cfg->v_fc_config.timings.hfp *= 2; video_cfg->v_fc_config.timings.hsw *= 2; @@ -348,9 +348,9 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, /* set x resolution */ REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1, - cfg->v_fc_config.timings.x_res >> 8, 4, 0); + cfg->v_fc_config.timings.hactive >> 8, 4, 0); REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0, - cfg->v_fc_config.timings.x_res & 0xFF, 7, 0); + cfg->v_fc_config.timings.hactive & 0xFF, 7, 0); /* set y resolution */ REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 203694a52d18..17f0d7afb855 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -199,7 +199,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; video_fmt->y_res = param->timings.y_res; - video_fmt->x_res = param->timings.x_res; + video_fmt->x_res = param->timings.hactive; timings->hbp = param->timings.hbp; timings->hfp = param->timings.hfp; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 6eaf1adbd606..ddd6d14049d0 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -301,7 +301,7 @@ struct omap_dss_dsi_config { struct omap_video_timings { /* Unit: pixels */ - u16 x_res; + u16 hactive; /* Unit: pixels */ u16 y_res; /* Unit: Hz */ diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index cd53566d75eb..81d26d1562f6 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -308,7 +308,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev, u32 l; int r; struct omap_overlay_manager *mgr = rfbi.output.manager; - u16 width = rfbi.timings.x_res; + u16 width = rfbi.timings.hactive; u16 height = rfbi.timings.y_res; /*BUG_ON(callback == 0);*/ @@ -777,7 +777,7 @@ static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *), static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) { - rfbi.timings.x_res = w; + rfbi.timings.hactive = w; rfbi.timings.y_res = h; } @@ -854,7 +854,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) dss_mgr_set_lcd_config(mgr, &mgr_config); /* - * Set rfbi.timings with default values, the x_res and y_res fields + * Set rfbi.timings with default values, the hactive and y_res fields * are expected to be already configured by the panel driver via * omapdss_rfbi_set_size() */ diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 6eedf2118708..970c3cb97a8c 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -263,7 +263,7 @@ static const struct venc_config venc_config_pal_bdghi = { }; const struct omap_video_timings omap_dss_pal_timings = { - .x_res = 720, + .hactive = 720, .y_res = 574, .pixelclock = 13500000, .hsw = 64, @@ -284,7 +284,7 @@ const struct omap_video_timings omap_dss_pal_timings = { EXPORT_SYMBOL(omap_dss_pal_timings); const struct omap_video_timings omap_dss_ntsc_timings = { - .x_res = 720, + .hactive = 720, .y_res = 482, .pixelclock = 13500000, .hsw = 64, diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 137fe690a0da..bc33ce34a856 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -47,7 +47,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, { mode->clock = timings->pixelclock / 1000; - mode->hdisplay = timings->x_res; + mode->hdisplay = timings->hactive; mode->hsync_start = mode->hdisplay + timings->hfp; mode->hsync_end = mode->hsync_start + timings->hsw; mode->htotal = mode->hsync_end + timings->hbp; @@ -81,7 +81,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, { timings->pixelclock = mode->clock * 1000; - timings->x_res = mode->hdisplay; + timings->hactive = mode->hdisplay; timings->hfp = mode->hsync_start - mode->hdisplay; timings->hsw = mode->hsync_end - mode->hsync_start; timings->hbp = mode->htotal - mode->hsync_end; -- cgit v1.2.3 From fb7f3c4399ffa75bc31aaaaeab45238ea60c3d1a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:47 +0300 Subject: drm/omap: omap_display_timings: rename y_res to vactive In preparation to move the stack to use the generic videmode struct for display timing information rename the y_res member to vactive. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 8 ++++---- .../gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 14 +++++++------- drivers/gpu/drm/omapdrm/dss/display.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/dsi.c | 12 ++++++------ drivers/gpu/drm/omapdrm/dss/hdmi4.c | 3 ++- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 3 ++- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 2 +- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/venc.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 ++-- 21 files changed, 45 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 190a03672181..a57e1efb12ac 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -31,7 +31,7 @@ struct panel_drv_data { static const struct omap_video_timings tvc_pal_timings = { .hactive = 720, - .y_res = 574, + .vactive = 574, .pixelclock = 13500000, .hsw = 64, .hfp = 12, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index c6e02e1a3799..b25c05c27c80 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -21,7 +21,7 @@ static const struct omap_video_timings dvic_default_timings = { .hactive = 640, - .y_res = 480, + .vactive = 480, .pixelclock = 23500000, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index ef5ae08b362b..33bc41c5cf71 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -23,7 +23,7 @@ static const struct omap_video_timings hdmic_default_timings = { .hactive = 640, - .y_res = 480, + .vactive = 480, .pixelclock = 25175000, .hsw = 96, .hfp = 16, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c index c34f2aa0118b..c3d2a12358fa 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c @@ -383,7 +383,7 @@ static void dsicm_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { *xres = dssdev->panel.timings.hactive; - *yres = dssdev->panel.timings.y_res; + *yres = dssdev->panel.timings.vactive; } static ssize_t dsicm_num_errors_show(struct device *dev, @@ -893,7 +893,7 @@ static int dsicm_update(struct omap_dss_device *dssdev, /* XXX no need to send this every frame, but dsi break if not done */ r = dsicm_set_update_window(ddata, 0, 0, dssdev->panel.timings.hactive, - dssdev->panel.timings.y_res); + dssdev->panel.timings.vactive); if (r) goto err; @@ -1025,7 +1025,7 @@ static int dsicm_memory_read(struct omap_dss_device *dssdev, size = min(w * h * 3, dssdev->panel.timings.hactive * - dssdev->panel.timings.y_res * 3); + dssdev->panel.timings.vactive * 3); in->ops.dsi->bus_lock(in); @@ -1187,7 +1187,7 @@ static int dsicm_probe(struct platform_device *pdev) return r; ddata->timings.hactive = 864; - ddata->timings.y_res = 480; + ddata->timings.vactive = 480; ddata->timings.pixelclock = 864 * 480 * 60; dssdev = &ddata->dssdev; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index c8b5462f462f..dc8d191e3635 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -21,7 +21,7 @@ static struct omap_video_timings lb035q02_timings = { .hactive = 320, - .y_res = 240, + .vactive = 240, .pixelclock = 6500000, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index f0895c7b6d5c..83658b9077fc 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -67,7 +67,7 @@ static const struct { static const struct omap_video_timings nec_8048_panel_timings = { .hactive = LCD_XRES, - .y_res = LCD_YRES, + .vactive = LCD_YRES, .pixelclock = LCD_PIXEL_CLOCK, .hfp = 6, .hsw = 1, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index b66ad743c607..c2dda73ac466 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -37,7 +37,7 @@ struct panel_drv_data { static const struct omap_video_timings sharp_ls_timings = { .hactive = 480, - .y_res = 640, + .vactive = 640, .pixelclock = 19200000, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 2764bc94a205..a7a6d5239f31 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -94,7 +94,7 @@ struct panel_drv_data { static const struct omap_video_timings acx565akm_panel_timings = { .hactive = 800, - .y_res = 480, + .vactive = 480, .pixelclock = 24000000, .hfp = 28, .hsw = 4, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 935728405cde..013286abbfda 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -44,7 +44,7 @@ struct panel_drv_data { static struct omap_video_timings td028ttec1_panel_timings = { .hactive = 480, - .y_res = 640, + .vactive = 640, .pixelclock = 22153000, .hfp = 24, .hsw = 8, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index fe8166640da8..eedbea62c51d 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -74,7 +74,7 @@ struct panel_drv_data { static const struct omap_video_timings tpo_td043_timings = { .hactive = 800, - .y_res = 480, + .vactive = 480, .pixelclock = 36000000, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index b34ac915a761..3d208ce67794 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2820,7 +2820,7 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, const bool replication = false; bool truncation; int in_width = mgr_timings->hactive; - int in_height = mgr_timings->y_res; + int in_height = mgr_timings->vactive; enum omap_overlay_caps caps = OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA; @@ -3118,7 +3118,7 @@ static bool _dispc_mgr_pclk_ok(enum omap_channel channel, bool dispc_mgr_timings_ok(enum omap_channel channel, const struct omap_video_timings *timings) { - if (!_dispc_mgr_size_ok(timings->hactive, timings->y_res)) + if (!_dispc_mgr_size_ok(timings->hactive, timings->vactive)) return false; if (!_dispc_mgr_pclk_ok(channel, timings->pixelclock)) @@ -3259,7 +3259,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, unsigned long ht, vt; struct omap_video_timings t = *timings; - DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.y_res); + DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.vactive); if (!dispc_mgr_timings_ok(channel, &t)) { BUG(); @@ -3272,7 +3272,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); xtot = t.hactive + t.hfp + t.hsw + t.hbp; - ytot = t.y_res + t.vfp + t.vsw + t.vbp; + ytot = t.vactive + t.vfp + t.vsw + t.vbp; ht = timings->pixelclock / xtot; vt = timings->pixelclock / xtot / ytot; @@ -3287,14 +3287,14 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); } else { if (t.interlace) - t.y_res /= 2; + t.vactive /= 2; if (dispc.feat->supports_double_pixel) REG_FLD_MOD(DISPC_CONTROL, t.double_pixel ? 1 : 0, 19, 17); } - dispc_mgr_set_size(channel, t.hactive, t.y_res); + dispc_mgr_set_size(channel, t.hactive, t.vactive); } EXPORT_SYMBOL(dispc_mgr_set_timings); @@ -4220,7 +4220,7 @@ static const struct dispc_errata_i734_data { struct dss_lcd_mgr_config lcd_conf; } i734 = { .timings = { - .hactive = 8, .y_res = 1, + .hactive = 8, .vactive = 1, .pixelclock = 16000000, .hsw = 8, .hfp = 4, .hbp = 4, .vsw = 1, .vfp = 1, .vbp = 1, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 4808cc8368c5..29ae5d6e1508 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -36,7 +36,7 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { *xres = dssdev->panel.timings.hactive; - *yres = dssdev->panel.timings.y_res; + *yres = dssdev->panel.timings.vactive; } EXPORT_SYMBOL(omapdss_default_get_resolution); @@ -228,7 +228,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->hbp = vm->hback_porch; ovt->hfp = vm->hfront_porch; ovt->hsw = vm->hsync_len; - ovt->y_res = vm->vactive; + ovt->vactive = vm->vactive; ovt->vbp = vm->vback_porch; ovt->vfp = vm->vfront_porch; ovt->vsw = vm->vsync_len; @@ -261,7 +261,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->hback_porch = ovt->hbp; vm->hfront_porch = ovt->hfp; vm->hsync_len = ovt->hsw; - vm->vactive = ovt->y_res; + vm->vactive = ovt->vactive; vm->vback_porch = ovt->vbp; vm->vfront_porch = ovt->vfp; vm->vsync_len = ovt->vsw; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 2bd4d0cdd2f2..06b15091d62f 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -3722,7 +3722,7 @@ static void dsi_proto_timings(struct platform_device *dsidev) DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp, hfp, hsync_end ? hsa : 0, tl); DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp, - vsa, timings->y_res); + vsa, timings->vactive); r = dsi_read_reg(dsidev, DSI_VM_TIMING1); r = FLD_MOD(r, hbp, 11, 0); /* HBP */ @@ -3738,7 +3738,7 @@ static void dsi_proto_timings(struct platform_device *dsidev) dsi_write_reg(dsidev, DSI_VM_TIMING2, r); r = dsi_read_reg(dsidev, DSI_VM_TIMING3); - r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */ + r = FLD_MOD(r, timings->vactive, 14, 0); /* VACT */ r = FLD_MOD(r, tl, 31, 16); /* TL */ dsi_write_reg(dsidev, DSI_VM_TIMING3, r); } @@ -3919,7 +3919,7 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev) const unsigned channel = dsi->update_channel; const unsigned line_buf_size = dsi->line_buffer_size; u16 w = dsi->timings.hactive; - u16 h = dsi->timings.y_res; + u16 h = dsi->timings.vactive; DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); @@ -4057,7 +4057,7 @@ static int dsi_update(struct omap_dss_device *dssdev, int channel, dsi->framedone_data = data; dw = dsi->timings.hactive; - dh = dsi->timings.y_res; + dh = dsi->timings.vactive; #ifdef DSI_PERF_MEASURE dsi->update_bytes = dw * dh * @@ -4422,7 +4422,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, *t = *ctx->config->timings; t->pixelclock = pck; t->hactive = ctx->config->timings->hactive; - t->y_res = ctx->config->timings->y_res; + t->vactive = ctx->config->timings->vactive; t->hsw = t->hfp = t->hbp = t->vsw = 1; t->vfp = t->vbp = 0; @@ -4635,7 +4635,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) dsi_vm->vsa = req_vm->vsw; dsi_vm->vbp = req_vm->vbp; - dsi_vm->vact = req_vm->y_res; + dsi_vm->vact = req_vm->vactive; dsi_vm->vfp = req_vm->vfp; dsi_vm->trans_mode = cfg->trans_mode; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index c5e89c887687..2a5a71a25423 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -171,7 +171,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) p = &hdmi.cfg.timings; - DSSDBG("hdmi_power_on hactive= %d y_res = %d\n", p->hactive, p->y_res); + DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", p->hactive, + p->vactive); pc = p->pixelclock; if (p->double_pixel) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 829d22253972..45f445523a4f 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -183,7 +183,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) p = &hdmi.cfg.timings; - DSSDBG("hdmi_power_on hactive= %d y_res = %d\n", p->hactive, p->y_res); + DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", p->hactive, + p->vactive); pc = p->pixelclock; if (p->double_pixel) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index cecc400b08e2..3f76976b0e38 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -308,7 +308,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, if (video_cfg->vblank % 2 != 0) video_cfg->vblank_osc = 1; - video_cfg->v_fc_config.timings.y_res /= 2; + video_cfg->v_fc_config.timings.vactive /= 2; video_cfg->vblank /= 2; video_cfg->v_fc_config.timings.vfp /= 2; video_cfg->v_fc_config.timings.vsw /= 2; @@ -354,9 +354,9 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, /* set y resolution */ REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, - cfg->v_fc_config.timings.y_res >> 8, 4, 0); + cfg->v_fc_config.timings.vactive >> 8, 4, 0); REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0, - cfg->v_fc_config.timings.y_res & 0xFF, 7, 0); + cfg->v_fc_config.timings.vactive & 0xFF, 7, 0); /* set horizontal blanking pixels */ REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK1, cfg->hblank >> 8, 4, 0); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 17f0d7afb855..05462cfe5af8 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -198,7 +198,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, DSSDBG("Enter hdmi_wp_video_init_format\n"); video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; - video_fmt->y_res = param->timings.y_res; + video_fmt->y_res = param->timings.vactive; video_fmt->x_res = param->timings.hactive; timings->hbp = param->timings.hbp; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index ddd6d14049d0..0b969f6f5701 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -303,7 +303,7 @@ struct omap_video_timings { /* Unit: pixels */ u16 hactive; /* Unit: pixels */ - u16 y_res; + u16 vactive; /* Unit: Hz */ u32 pixelclock; /* Unit: pixel clocks */ diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index 81d26d1562f6..ef9984c3d906 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -309,7 +309,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev, int r; struct omap_overlay_manager *mgr = rfbi.output.manager; u16 width = rfbi.timings.hactive; - u16 height = rfbi.timings.y_res; + u16 height = rfbi.timings.vactive; /*BUG_ON(callback == 0);*/ BUG_ON(rfbi.framedone_callback != NULL); @@ -778,7 +778,7 @@ static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *), static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) { rfbi.timings.hactive = w; - rfbi.timings.y_res = h; + rfbi.timings.vactive = h; } static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size) @@ -854,7 +854,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) dss_mgr_set_lcd_config(mgr, &mgr_config); /* - * Set rfbi.timings with default values, the hactive and y_res fields + * Set rfbi.timings with default values, the hactive and vactive fields * are expected to be already configured by the panel driver via * omapdss_rfbi_set_size() */ diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 970c3cb97a8c..463dc4e27f7a 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -264,7 +264,7 @@ static const struct venc_config venc_config_pal_bdghi = { const struct omap_video_timings omap_dss_pal_timings = { .hactive = 720, - .y_res = 574, + .vactive = 574, .pixelclock = 13500000, .hsw = 64, .hfp = 12, @@ -285,7 +285,7 @@ EXPORT_SYMBOL(omap_dss_pal_timings); const struct omap_video_timings omap_dss_ntsc_timings = { .hactive = 720, - .y_res = 482, + .vactive = 482, .pixelclock = 13500000, .hsw = 64, .hfp = 16, diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index bc33ce34a856..e3833efb6db8 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -52,7 +52,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->hsync_end = mode->hsync_start + timings->hsw; mode->htotal = mode->hsync_end + timings->hbp; - mode->vdisplay = timings->y_res; + mode->vdisplay = timings->vactive; mode->vsync_start = mode->vdisplay + timings->vfp; mode->vsync_end = mode->vsync_start + timings->vsw; mode->vtotal = mode->vsync_end + timings->vbp; @@ -86,7 +86,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->hsw = mode->hsync_end - mode->hsync_start; timings->hbp = mode->htotal - mode->hsync_end; - timings->y_res = mode->vdisplay; + timings->vactive = mode->vdisplay; timings->vfp = mode->vsync_start - mode->vdisplay; timings->vsw = mode->vsync_end - mode->vsync_start; timings->vbp = mode->vtotal - mode->vsync_end; -- cgit v1.2.3 From 4dc2250d7d9e816b986d656cde90f55c096012ed Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:48 +0300 Subject: drm/omap: omap_display_timings: rename hsw to hsync_len In preparation to move the stack to use the generic videmode struct for display timing information rename the hsw member to hsync_len. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- .../gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 +- .../omapdrm/displays/panel-lgphilips-lb035q02.c | 2 +- .../drm/omapdrm/displays/panel-nec-nl8048hl11.c | 2 +- .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 2 +- .../drm/omapdrm/displays/panel-sony-acx565akm.c | 2 +- .../drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 +- .../drm/omapdrm/displays/panel-tpo-td043mtea1.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 29 +++++++++++----------- drivers/gpu/drm/omapdrm/dss/display.c | 4 +-- drivers/gpu/drm/omapdrm/dss/dsi.c | 22 ++++++++-------- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 8 +++--- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 12 ++++----- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 4 +-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 +-- 18 files changed, 53 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index a57e1efb12ac..5205a8ef6038 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -33,7 +33,7 @@ static const struct omap_video_timings tvc_pal_timings = { .hactive = 720, .vactive = 574, .pixelclock = 13500000, - .hsw = 64, + .hsync_len = 64, .hfp = 12, .hbp = 68, .vsw = 5, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index b25c05c27c80..e9a8ea5043e6 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -26,7 +26,7 @@ static const struct omap_video_timings dvic_default_timings = { .pixelclock = 23500000, .hfp = 48, - .hsw = 32, + .hsync_len = 32, .hbp = 80, .vfp = 3, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 33bc41c5cf71..707fd62cb99c 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -25,7 +25,7 @@ static const struct omap_video_timings hdmic_default_timings = { .hactive = 640, .vactive = 480, .pixelclock = 25175000, - .hsw = 96, + .hsync_len = 96, .hfp = 16, .hbp = 48, .vsw = 2, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index dc8d191e3635..6fbf07048df0 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -25,7 +25,7 @@ static struct omap_video_timings lb035q02_timings = { .pixelclock = 6500000, - .hsw = 2, + .hsync_len = 2, .hfp = 20, .hbp = 68, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index 83658b9077fc..e0462aaf62f1 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -70,7 +70,7 @@ static const struct omap_video_timings nec_8048_panel_timings = { .vactive = LCD_YRES, .pixelclock = LCD_PIXEL_CLOCK, .hfp = 6, - .hsw = 1, + .hsync_len = 1, .hbp = 4, .vfp = 3, .vsw = 1, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index c2dda73ac466..5e96edebdd5c 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -41,7 +41,7 @@ static const struct omap_video_timings sharp_ls_timings = { .pixelclock = 19200000, - .hsw = 2, + .hsync_len = 2, .hfp = 1, .hbp = 28, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index a7a6d5239f31..e679d8d62e18 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -97,7 +97,7 @@ static const struct omap_video_timings acx565akm_panel_timings = { .vactive = 480, .pixelclock = 24000000, .hfp = 28, - .hsw = 4, + .hsync_len = 4, .hbp = 24, .vfp = 3, .vsw = 3, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 013286abbfda..bc8e82abc0ba 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -47,7 +47,7 @@ static struct omap_video_timings td028ttec1_panel_timings = { .vactive = 640, .pixelclock = 22153000, .hfp = 24, - .hsw = 8, + .hsync_len = 8, .hbp = 8, .vfp = 4, .vsw = 2, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index eedbea62c51d..1255e8c128d5 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -78,7 +78,7 @@ static const struct omap_video_timings tpo_td043_timings = { .pixelclock = 36000000, - .hsw = 1, + .hsync_len = 1, .hfp = 68, .hbp = 214, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 3d208ce67794..8f97a11a2e97 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2189,14 +2189,14 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, u64 val, blank; int i; - nonactive = t->hactive + t->hfp + t->hsw + t->hbp - out_width; + nonactive = t->hactive + t->hfp + t->hsync_len + t->hbp - out_width; i = 0; if (out_height < height) i++; if (out_width < width) i++; - blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk); + blank = div_u64((u64)(t->hbp + t->hsync_len + t->hfp) * lclk, pclk); DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]); if (blank <= limits[i]) return -EINVAL; @@ -3093,10 +3093,10 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height) height <= dispc.feat->mgr_height_max; } -static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, +static bool _dispc_lcd_timings_ok(int hsync_len, int hfp, int hbp, int vsw, int vfp, int vbp) { - if (hsw < 1 || hsw > dispc.feat->sw_max || + if (hsync_len < 1 || hsync_len > dispc.feat->sw_max || hfp < 1 || hfp > dispc.feat->hp_max || hbp < 1 || hbp > dispc.feat->hp_max || vsw < 1 || vsw > dispc.feat->sw_max || @@ -3129,7 +3129,7 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, if (timings->interlace) return false; - if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, + if (!_dispc_lcd_timings_ok(timings->hsync_len, timings->hfp, timings->hbp, timings->vsw, timings->vfp, timings->vbp)) return false; @@ -3138,7 +3138,7 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, return true; } -static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, +static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsync_len, int hfp, int hbp, int vsw, int vfp, int vbp, enum omap_dss_signal_level vsync_level, enum omap_dss_signal_level hsync_level, @@ -3150,7 +3150,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, u32 timing_h, timing_v, l; bool onoff, rf, ipc, vs, hs, de; - timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) | + timing_h = FLD_VAL(hsync_len-1, dispc.feat->sw_start, 0) | FLD_VAL(hfp-1, dispc.feat->fp_start, 8) | FLD_VAL(hbp-1, dispc.feat->bp_start, 20); timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) | @@ -3267,19 +3267,20 @@ void dispc_mgr_set_timings(enum omap_channel channel, } if (dss_mgr_is_lcd(channel)) { - _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw, - t.vfp, t.vbp, t.vsync_level, t.hsync_level, - t.data_pclk_edge, t.de_level, t.sync_pclk_edge); + _dispc_mgr_set_lcd_timings(channel, t.hsync_len, t.hfp, t.hbp, + t.vsw, t.vfp, t.vbp, t.vsync_level, + t.hsync_level, t.data_pclk_edge, t.de_level, + t.sync_pclk_edge); - xtot = t.hactive + t.hfp + t.hsw + t.hbp; + xtot = t.hactive + t.hfp + t.hsync_len + t.hbp; ytot = t.vactive + t.vfp + t.vsw + t.vbp; ht = timings->pixelclock / xtot; vt = timings->pixelclock / xtot / ytot; DSSDBG("pck %u\n", timings->pixelclock); - DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", - t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp); + DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", + t.hsync_len, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp); DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); @@ -4222,7 +4223,7 @@ static const struct dispc_errata_i734_data { .timings = { .hactive = 8, .vactive = 1, .pixelclock = 16000000, - .hsw = 8, .hfp = 4, .hbp = 4, + .hsync_len = 8, .hfp = 4, .hbp = 4, .vsw = 1, .vfp = 1, .vbp = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 29ae5d6e1508..78ceaa5e8198 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -227,7 +227,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->hactive = vm->hactive; ovt->hbp = vm->hback_porch; ovt->hfp = vm->hfront_porch; - ovt->hsw = vm->hsync_len; + ovt->hsync_len = vm->hsync_len; ovt->vactive = vm->vactive; ovt->vbp = vm->vback_porch; ovt->vfp = vm->vfront_porch; @@ -260,7 +260,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->hactive = ovt->hactive; vm->hback_porch = ovt->hbp; vm->hfront_porch = ovt->hfp; - vm->hsync_len = ovt->hsw; + vm->hsync_len = ovt->hsync_len; vm->vactive = ovt->vactive; vm->vback_porch = ovt->vbp; vm->vfront_porch = ovt->vfp; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 06b15091d62f..002b450b0649 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4362,7 +4362,7 @@ static void print_dispc_vm(const char *str, const struct omap_video_timings *t) int hact, bl, tot; hact = t->hactive; - bl = t->hsw + t->hbp + t->hfp; + bl = t->hsync_len + t->hbp + t->hfp; tot = hact + bl; #define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck)) @@ -4371,9 +4371,9 @@ static void print_dispc_vm(const char *str, const struct omap_video_timings *t) "%u/%u/%u/%u = %u + %u = %u\n", str, pck, - t->hsw, t->hbp, hact, t->hfp, + t->hsync_len, t->hbp, hact, t->hfp, bl, hact, tot, - TO_DISPC_T(t->hsw), + TO_DISPC_T(t->hsync_len), TO_DISPC_T(t->hbp), TO_DISPC_T(hact), TO_DISPC_T(t->hfp), @@ -4399,7 +4399,7 @@ static void print_dsi_dispc_vm(const char *str, dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp; vm.pixelclock = pck; - vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); + vm.hsync_len = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); vm.hbp = div64_u64((u64)t->hbp * pck, byteclk); vm.hfp = div64_u64((u64)t->hfp * pck, byteclk); vm.hactive = t->hact; @@ -4423,7 +4423,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, t->pixelclock = pck; t->hactive = ctx->config->timings->hactive; t->vactive = ctx->config->timings->vactive; - t->hsw = t->hfp = t->hbp = t->vsw = 1; + t->hsync_len = t->hfp = t->hbp = t->vsw = 1; t->vfp = t->vbp = 0; return true; @@ -4527,7 +4527,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) xres = req_vm->hactive; - panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw; + panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsync_len; panel_htot = xres + panel_hbl; dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl); @@ -4557,7 +4557,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) hss = DIV_ROUND_UP(4, ndl); if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) { - if (ndl == 3 && req_vm->hsw == 0) + if (ndl == 3 && req_vm->hsync_len == 0) hse = 1; else hse = DIV_ROUND_UP(4, ndl); @@ -4596,10 +4596,10 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) { hsa = 0; - } else if (ndl == 3 && req_vm->hsw == 0) { + } else if (ndl == 3 && req_vm->hsync_len == 0) { hsa = 0; } else { - hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom); + hsa = div64_u64((u64)req_vm->hsync_len * byteclk, req_pck_nom); hsa = max(hsa - hse, 1); } @@ -4655,7 +4655,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) dispc_vm->pixelclock = dispc_pck; if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) { - hsa = div64_u64((u64)req_vm->hsw * dispc_pck, + hsa = div64_u64((u64)req_vm->hsync_len * dispc_pck, req_pck_nom); hsa = max(hsa, 1); } else { @@ -4686,7 +4686,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) return false; dispc_vm->hfp = hfp; - dispc_vm->hsw = hsa; + dispc_vm->hsync_len = hsa; dispc_vm->hbp = hbp; return true; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 3f76976b0e38..dd4c989c44ce 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -297,7 +297,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, /* video core */ video_cfg->data_enable_pol = 1; /* It is always 1*/ video_cfg->hblank = cfg->timings.hfp + - cfg->timings.hbp + cfg->timings.hsw; + cfg->timings.hbp + cfg->timings.hsync_len; video_cfg->vblank_osc = 0; video_cfg->vblank = cfg->timings.vsw + cfg->timings.vfp + cfg->timings.vbp; @@ -319,7 +319,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, video_cfg->v_fc_config.timings.hactive *= 2; video_cfg->hblank *= 2; video_cfg->v_fc_config.timings.hfp *= 2; - video_cfg->v_fc_config.timings.hsw *= 2; + video_cfg->v_fc_config.timings.hsync_len *= 2; video_cfg->v_fc_config.timings.hbp *= 2; } } @@ -377,9 +377,9 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, /* set horizontal sync pulse width */ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, - (cfg->v_fc_config.timings.hsw >> 8), 1, 0); + (cfg->v_fc_config.timings.hsync_len >> 8), 1, 0); REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0, - cfg->v_fc_config.timings.hsw & 0xFF, 7, 0); + cfg->v_fc_config.timings.hsync_len & 0xFF, 7, 0); /* set vertical sync pulse width */ REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 05462cfe5af8..89914a7a2bf9 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -166,24 +166,24 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, { u32 timing_h = 0; u32 timing_v = 0; - unsigned hsw_offset = 1; + unsigned hsync_len_offset = 1; DSSDBG("Enter hdmi_wp_video_config_timing\n"); /* * On OMAP4 and OMAP5 ES1 the HSW field is programmed as is. On OMAP5 - * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsw-1. + * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsync_len-1. * However, we don't support OMAP5 ES1 at all, so we can just check for * OMAP4 here. */ if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 || omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 || omapdss_get_version() == OMAPDSS_VER_OMAP4) - hsw_offset = 0; + hsync_len_offset = 0; timing_h |= FLD_VAL(timings->hbp, 31, 20); timing_h |= FLD_VAL(timings->hfp, 19, 8); - timing_h |= FLD_VAL(timings->hsw - hsw_offset, 7, 0); + timing_h |= FLD_VAL(timings->hsync_len - hsync_len_offset, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h); timing_v |= FLD_VAL(timings->vbp, 31, 20); @@ -203,7 +203,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, timings->hbp = param->timings.hbp; timings->hfp = param->timings.hfp; - timings->hsw = param->timings.hsw; + timings->hsync_len = param->timings.hsync_len; timings->vbp = param->timings.vbp; timings->vfp = param->timings.vfp; timings->vsw = param->timings.vsw; @@ -223,7 +223,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, if (param->timings.double_pixel) { video_fmt->x_res *= 2; timings->hfp *= 2; - timings->hsw *= 2; + timings->hsync_len *= 2; timings->hbp *= 2; } } diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 0b969f6f5701..6468afa2a85b 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -307,7 +307,7 @@ struct omap_video_timings { /* Unit: Hz */ u32 pixelclock; /* Unit: pixel clocks */ - u16 hsw; /* Horizontal synchronization pulse width */ + u16 hsync_len; /* Horizontal synchronization pulse width */ /* Unit: pixel clocks */ u16 hfp; /* Horizontal front porch */ /* Unit: pixel clocks */ diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index ef9984c3d906..11d70691c4b1 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -858,7 +858,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) * are expected to be already configured by the panel driver via * omapdss_rfbi_set_size() */ - rfbi.timings.hsw = 1; + rfbi.timings.hsync_len = 1; rfbi.timings.hfp = 1; rfbi.timings.hbp = 1; rfbi.timings.vsw = 1; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 463dc4e27f7a..9f53e9a21706 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -266,7 +266,7 @@ const struct omap_video_timings omap_dss_pal_timings = { .hactive = 720, .vactive = 574, .pixelclock = 13500000, - .hsw = 64, + .hsync_len = 64, .hfp = 12, .hbp = 68, .vsw = 5, @@ -287,7 +287,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .hactive = 720, .vactive = 482, .pixelclock = 13500000, - .hsw = 64, + .hsync_len = 64, .hfp = 16, .hbp = 58, .vsw = 6, diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index e3833efb6db8..86620396a561 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -49,7 +49,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->hdisplay = timings->hactive; mode->hsync_start = mode->hdisplay + timings->hfp; - mode->hsync_end = mode->hsync_start + timings->hsw; + mode->hsync_end = mode->hsync_start + timings->hsync_len; mode->htotal = mode->hsync_end + timings->hbp; mode->vdisplay = timings->vactive; @@ -83,7 +83,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->hactive = mode->hdisplay; timings->hfp = mode->hsync_start - mode->hdisplay; - timings->hsw = mode->hsync_end - mode->hsync_start; + timings->hsync_len = mode->hsync_end - mode->hsync_start; timings->hbp = mode->htotal - mode->hsync_end; timings->vactive = mode->vdisplay; -- cgit v1.2.3 From 0a30e150f053e609f7820d81efebde28802035f3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:49 +0300 Subject: drm/omap: omap_display_timings: rename hfp to hfront_porch In preparation to move the stack to use the generic videmode struct for display timing information rename the hfp member to hfront_porch. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- .../gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 +- .../omapdrm/displays/panel-lgphilips-lb035q02.c | 2 +- .../drm/omapdrm/displays/panel-nec-nl8048hl11.c | 2 +- .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 2 +- .../drm/omapdrm/displays/panel-sony-acx565akm.c | 2 +- .../drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 +- .../drm/omapdrm/displays/panel-tpo-td043mtea1.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 22 ++++++++++++---------- drivers/gpu/drm/omapdrm/dss/display.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/dsi.c | 22 +++++++++++----------- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 8 ++++---- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 ++-- 18 files changed, 47 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 5205a8ef6038..6d089b337bcb 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -34,7 +34,7 @@ static const struct omap_video_timings tvc_pal_timings = { .vactive = 574, .pixelclock = 13500000, .hsync_len = 64, - .hfp = 12, + .hfront_porch = 12, .hbp = 68, .vsw = 5, .vfp = 5, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index e9a8ea5043e6..cf893866aca0 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -25,7 +25,7 @@ static const struct omap_video_timings dvic_default_timings = { .pixelclock = 23500000, - .hfp = 48, + .hfront_porch = 48, .hsync_len = 32, .hbp = 80, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 707fd62cb99c..fd1178b57f79 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -26,7 +26,7 @@ static const struct omap_video_timings hdmic_default_timings = { .vactive = 480, .pixelclock = 25175000, .hsync_len = 96, - .hfp = 16, + .hfront_porch = 16, .hbp = 48, .vsw = 2, .vfp = 11, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 6fbf07048df0..677db7b22a02 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -26,7 +26,7 @@ static struct omap_video_timings lb035q02_timings = { .pixelclock = 6500000, .hsync_len = 2, - .hfp = 20, + .hfront_porch = 20, .hbp = 68, .vsw = 2, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index e0462aaf62f1..aff07f810796 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -69,7 +69,7 @@ static const struct omap_video_timings nec_8048_panel_timings = { .hactive = LCD_XRES, .vactive = LCD_YRES, .pixelclock = LCD_PIXEL_CLOCK, - .hfp = 6, + .hfront_porch = 6, .hsync_len = 1, .hbp = 4, .vfp = 3, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index 5e96edebdd5c..c8348090e745 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -42,7 +42,7 @@ static const struct omap_video_timings sharp_ls_timings = { .pixelclock = 19200000, .hsync_len = 2, - .hfp = 1, + .hfront_porch = 1, .hbp = 28, .vsw = 1, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index e679d8d62e18..fab0e98577f5 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -96,7 +96,7 @@ static const struct omap_video_timings acx565akm_panel_timings = { .hactive = 800, .vactive = 480, .pixelclock = 24000000, - .hfp = 28, + .hfront_porch = 28, .hsync_len = 4, .hbp = 24, .vfp = 3, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index bc8e82abc0ba..694b2e117e08 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -46,7 +46,7 @@ static struct omap_video_timings td028ttec1_panel_timings = { .hactive = 480, .vactive = 640, .pixelclock = 22153000, - .hfp = 24, + .hfront_porch = 24, .hsync_len = 8, .hbp = 8, .vfp = 4, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 1255e8c128d5..8960e8389d6a 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -79,7 +79,7 @@ static const struct omap_video_timings tpo_td043_timings = { .pixelclock = 36000000, .hsync_len = 1, - .hfp = 68, + .hfront_porch = 68, .hbp = 214, .vsw = 1, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 8f97a11a2e97..3f5c57fbfa94 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2189,14 +2189,16 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, u64 val, blank; int i; - nonactive = t->hactive + t->hfp + t->hsync_len + t->hbp - out_width; + nonactive = t->hactive + t->hfront_porch + t->hsync_len + + t->hbp - out_width; i = 0; if (out_height < height) i++; if (out_width < width) i++; - blank = div_u64((u64)(t->hbp + t->hsync_len + t->hfp) * lclk, pclk); + blank = div_u64((u64)(t->hbp + t->hsync_len + t->hfront_porch) * + lclk, pclk); DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]); if (blank <= limits[i]) return -EINVAL; @@ -3129,9 +3131,9 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, if (timings->interlace) return false; - if (!_dispc_lcd_timings_ok(timings->hsync_len, timings->hfp, - timings->hbp, timings->vsw, timings->vfp, - timings->vbp)) + if (!_dispc_lcd_timings_ok(timings->hsync_len, + timings->hfront_porch, timings->hbp, + timings->vsw, timings->vfp, timings->vbp)) return false; } @@ -3267,12 +3269,12 @@ void dispc_mgr_set_timings(enum omap_channel channel, } if (dss_mgr_is_lcd(channel)) { - _dispc_mgr_set_lcd_timings(channel, t.hsync_len, t.hfp, t.hbp, - t.vsw, t.vfp, t.vbp, t.vsync_level, + _dispc_mgr_set_lcd_timings(channel, t.hsync_len, t.hfront_porch, + t.hbp, t.vsw, t.vfp, t.vbp, t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); - xtot = t.hactive + t.hfp + t.hsync_len + t.hbp; + xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hbp; ytot = t.vactive + t.vfp + t.vsw + t.vbp; ht = timings->pixelclock / xtot; @@ -3280,7 +3282,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("pck %u\n", timings->pixelclock); DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", - t.hsync_len, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp); + t.hsync_len, t.hfront_porch, t.hbp, t.vsw, t.vfp, t.vbp); DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); @@ -4223,7 +4225,7 @@ static const struct dispc_errata_i734_data { .timings = { .hactive = 8, .vactive = 1, .pixelclock = 16000000, - .hsync_len = 8, .hfp = 4, .hbp = 4, + .hsync_len = 8, .hfront_porch = 4, .hbp = 4, .vsw = 1, .vfp = 1, .vbp = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 78ceaa5e8198..f147c6c663d3 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -226,7 +226,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->pixelclock = vm->pixelclock; ovt->hactive = vm->hactive; ovt->hbp = vm->hback_porch; - ovt->hfp = vm->hfront_porch; + ovt->hfront_porch = vm->hfront_porch; ovt->hsync_len = vm->hsync_len; ovt->vactive = vm->vactive; ovt->vbp = vm->vback_porch; @@ -259,7 +259,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->hactive = ovt->hactive; vm->hback_porch = ovt->hbp; - vm->hfront_porch = ovt->hfp; + vm->hfront_porch = ovt->hfront_porch; vm->hsync_len = ovt->hsync_len; vm->vactive = ovt->vactive; vm->vback_porch = ovt->vbp; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 002b450b0649..17eb16f86adc 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4331,7 +4331,7 @@ static void print_dsi_vm(const char *str, wc = DIV_ROUND_UP(t->hact * t->bitspp, 8); pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */ - bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp; + bl = t->hss + t->hsa + t->hse + t->hbp + t->hfront_porch; tot = bl + pps; #define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk)) @@ -4340,14 +4340,14 @@ static void print_dsi_vm(const char *str, "%u/%u/%u/%u/%u/%u = %u + %u = %u\n", str, byteclk, - t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp, + t->hss, t->hsa, t->hse, t->hbp, pps, t->hfront_porch, bl, pps, tot, TO_DSI_T(t->hss), TO_DSI_T(t->hsa), TO_DSI_T(t->hse), TO_DSI_T(t->hbp), TO_DSI_T(pps), - TO_DSI_T(t->hfp), + TO_DSI_T(t->hfront_porch), TO_DSI_T(bl), TO_DSI_T(pps), @@ -4362,7 +4362,7 @@ static void print_dispc_vm(const char *str, const struct omap_video_timings *t) int hact, bl, tot; hact = t->hactive; - bl = t->hsync_len + t->hbp + t->hfp; + bl = t->hsync_len + t->hbp + t->hfront_porch; tot = hact + bl; #define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck)) @@ -4371,12 +4371,12 @@ static void print_dispc_vm(const char *str, const struct omap_video_timings *t) "%u/%u/%u/%u = %u + %u = %u\n", str, pck, - t->hsync_len, t->hbp, hact, t->hfp, + t->hsync_len, t->hbp, hact, t->hfront_porch, bl, hact, tot, TO_DISPC_T(t->hsync_len), TO_DISPC_T(t->hbp), TO_DISPC_T(hact), - TO_DISPC_T(t->hfp), + TO_DISPC_T(t->hfront_porch), TO_DISPC_T(bl), TO_DISPC_T(hact), TO_DISPC_T(tot)); @@ -4396,12 +4396,12 @@ static void print_dsi_dispc_vm(const char *str, dsi_tput = (u64)byteclk * t->ndl * 8; pck = (u32)div64_u64(dsi_tput, t->bitspp); dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl); - dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp; + dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfront_porch; vm.pixelclock = pck; vm.hsync_len = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); vm.hbp = div64_u64((u64)t->hbp * pck, byteclk); - vm.hfp = div64_u64((u64)t->hfp * pck, byteclk); + vm.hfront_porch = div64_u64((u64)t->hfront_porch * pck, byteclk); vm.hactive = t->hact; print_dispc_vm(str, &vm); @@ -4423,7 +4423,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, t->pixelclock = pck; t->hactive = ctx->config->timings->hactive; t->vactive = ctx->config->timings->vactive; - t->hsync_len = t->hfp = t->hbp = t->vsw = 1; + t->hsync_len = t->hfront_porch = t->hbp = t->vsw = 1; t->vfp = t->vbp = 0; return true; @@ -4527,7 +4527,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) xres = req_vm->hactive; - panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsync_len; + panel_hbl = req_vm->hfront_porch + req_vm->hbp + req_vm->hsync_len; panel_htot = xres + panel_hbl; dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl); @@ -4685,7 +4685,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) if (hfp < 1) return false; - dispc_vm->hfp = hfp; + dispc_vm->hfront_porch = hfp; dispc_vm->hsync_len = hsa; dispc_vm->hbp = hbp; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index dd4c989c44ce..26012224e7e4 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -296,7 +296,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, /* video core */ video_cfg->data_enable_pol = 1; /* It is always 1*/ - video_cfg->hblank = cfg->timings.hfp + + video_cfg->hblank = cfg->timings.hfront_porch + cfg->timings.hbp + cfg->timings.hsync_len; video_cfg->vblank_osc = 0; video_cfg->vblank = cfg->timings.vsw + @@ -318,7 +318,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, if (cfg->timings.double_pixel) { video_cfg->v_fc_config.timings.hactive *= 2; video_cfg->hblank *= 2; - video_cfg->v_fc_config.timings.hfp *= 2; + video_cfg->v_fc_config.timings.hfront_porch *= 2; video_cfg->v_fc_config.timings.hsync_len *= 2; video_cfg->v_fc_config.timings.hbp *= 2; } @@ -367,9 +367,9 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, /* set horizontal sync offset */ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1, - cfg->v_fc_config.timings.hfp >> 8, 4, 0); + cfg->v_fc_config.timings.hfront_porch >> 8, 4, 0); REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0, - cfg->v_fc_config.timings.hfp & 0xFF, 7, 0); + cfg->v_fc_config.timings.hfront_porch & 0xFF, 7, 0); /* set vertical sync offset */ REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 89914a7a2bf9..7b7efb6dc5d7 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -182,7 +182,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, hsync_len_offset = 0; timing_h |= FLD_VAL(timings->hbp, 31, 20); - timing_h |= FLD_VAL(timings->hfp, 19, 8); + timing_h |= FLD_VAL(timings->hfront_porch, 19, 8); timing_h |= FLD_VAL(timings->hsync_len - hsync_len_offset, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h); @@ -202,7 +202,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, video_fmt->x_res = param->timings.hactive; timings->hbp = param->timings.hbp; - timings->hfp = param->timings.hfp; + timings->hfront_porch = param->timings.hfront_porch; timings->hsync_len = param->timings.hsync_len; timings->vbp = param->timings.vbp; timings->vfp = param->timings.vfp; @@ -222,7 +222,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, if (param->timings.double_pixel) { video_fmt->x_res *= 2; - timings->hfp *= 2; + timings->hfront_porch *= 2; timings->hsync_len *= 2; timings->hbp *= 2; } diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 6468afa2a85b..b540baf81e0d 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -309,7 +309,7 @@ struct omap_video_timings { /* Unit: pixel clocks */ u16 hsync_len; /* Horizontal synchronization pulse width */ /* Unit: pixel clocks */ - u16 hfp; /* Horizontal front porch */ + u16 hfront_porch; /* Horizontal front porch */ /* Unit: pixel clocks */ u16 hbp; /* Horizontal back porch */ /* Unit: line clocks */ diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index 11d70691c4b1..32b87bfd6d3f 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -859,7 +859,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) * omapdss_rfbi_set_size() */ rfbi.timings.hsync_len = 1; - rfbi.timings.hfp = 1; + rfbi.timings.hfront_porch = 1; rfbi.timings.hbp = 1; rfbi.timings.vsw = 1; rfbi.timings.vfp = 0; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 9f53e9a21706..92dbcab2d72a 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -267,7 +267,7 @@ const struct omap_video_timings omap_dss_pal_timings = { .vactive = 574, .pixelclock = 13500000, .hsync_len = 64, - .hfp = 12, + .hfront_porch = 12, .hbp = 68, .vsw = 5, .vfp = 5, @@ -288,7 +288,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .vactive = 482, .pixelclock = 13500000, .hsync_len = 64, - .hfp = 16, + .hfront_porch = 16, .hbp = 58, .vsw = 6, .vfp = 6, diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 86620396a561..2399a6facea4 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -48,7 +48,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->clock = timings->pixelclock / 1000; mode->hdisplay = timings->hactive; - mode->hsync_start = mode->hdisplay + timings->hfp; + mode->hsync_start = mode->hdisplay + timings->hfront_porch; mode->hsync_end = mode->hsync_start + timings->hsync_len; mode->htotal = mode->hsync_end + timings->hbp; @@ -82,7 +82,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->pixelclock = mode->clock * 1000; timings->hactive = mode->hdisplay; - timings->hfp = mode->hsync_start - mode->hdisplay; + timings->hfront_porch = mode->hsync_start - mode->hdisplay; timings->hsync_len = mode->hsync_end - mode->hsync_start; timings->hbp = mode->htotal - mode->hsync_end; -- cgit v1.2.3 From a85f4a80784b34362568a0ff1f34aaa3357462a0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:50 +0300 Subject: drm/omap: omap_display_timings: rename hbp to hback_porch In preparation to move the stack to use the generic videmode struct for display timing information rename the hbp member to hback_porch. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- .../gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 +- .../drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 2 +- .../gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 2 +- .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 2 +- .../gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 2 +- .../gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 +- .../gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 19 ++++++++++--------- drivers/gpu/drm/omapdrm/dss/display.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/dsi.c | 11 ++++++----- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 ++-- 18 files changed, 38 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 6d089b337bcb..2dbc6a42fb32 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -35,7 +35,7 @@ static const struct omap_video_timings tvc_pal_timings = { .pixelclock = 13500000, .hsync_len = 64, .hfront_porch = 12, - .hbp = 68, + .hback_porch = 68, .vsw = 5, .vfp = 5, .vbp = 41, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index cf893866aca0..6cf541cb9933 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -27,7 +27,7 @@ static const struct omap_video_timings dvic_default_timings = { .hfront_porch = 48, .hsync_len = 32, - .hbp = 80, + .hback_porch = 80, .vfp = 3, .vsw = 4, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index fd1178b57f79..24d047844b7c 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -27,7 +27,7 @@ static const struct omap_video_timings hdmic_default_timings = { .pixelclock = 25175000, .hsync_len = 96, .hfront_porch = 16, - .hbp = 48, + .hback_porch = 48, .vsw = 2, .vfp = 11, .vbp = 31, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 677db7b22a02..295904a5f28d 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -27,7 +27,7 @@ static struct omap_video_timings lb035q02_timings = { .hsync_len = 2, .hfront_porch = 20, - .hbp = 68, + .hback_porch = 68, .vsw = 2, .vfp = 4, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index aff07f810796..d408824a3341 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -71,7 +71,7 @@ static const struct omap_video_timings nec_8048_panel_timings = { .pixelclock = LCD_PIXEL_CLOCK, .hfront_porch = 6, .hsync_len = 1, - .hbp = 4, + .hback_porch = 4, .vfp = 3, .vsw = 1, .vbp = 4, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index c8348090e745..b36df2c66db1 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -43,7 +43,7 @@ static const struct omap_video_timings sharp_ls_timings = { .hsync_len = 2, .hfront_porch = 1, - .hbp = 28, + .hback_porch = 28, .vsw = 1, .vfp = 1, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index fab0e98577f5..ed55ad9fa731 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -98,7 +98,7 @@ static const struct omap_video_timings acx565akm_panel_timings = { .pixelclock = 24000000, .hfront_porch = 28, .hsync_len = 4, - .hbp = 24, + .hback_porch = 24, .vfp = 3, .vsw = 3, .vbp = 4, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 694b2e117e08..f1cc3fa275e6 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -48,7 +48,7 @@ static struct omap_video_timings td028ttec1_panel_timings = { .pixelclock = 22153000, .hfront_porch = 24, .hsync_len = 8, - .hbp = 8, + .hback_porch = 8, .vfp = 4, .vsw = 2, .vbp = 2, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 8960e8389d6a..458a4541f85c 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -80,7 +80,7 @@ static const struct omap_video_timings tpo_td043_timings = { .hsync_len = 1, .hfront_porch = 68, - .hbp = 214, + .hback_porch = 214, .vsw = 1, .vfp = 39, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 3f5c57fbfa94..0d115aa6c86e 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2190,14 +2190,14 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, int i; nonactive = t->hactive + t->hfront_porch + t->hsync_len + - t->hbp - out_width; + t->hback_porch - out_width; i = 0; if (out_height < height) i++; if (out_width < width) i++; - blank = div_u64((u64)(t->hbp + t->hsync_len + t->hfront_porch) * + blank = div_u64((u64)(t->hback_porch + t->hsync_len + t->hfront_porch) * lclk, pclk); DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]); if (blank <= limits[i]) @@ -3132,7 +3132,7 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, return false; if (!_dispc_lcd_timings_ok(timings->hsync_len, - timings->hfront_porch, timings->hbp, + timings->hfront_porch, timings->hback_porch, timings->vsw, timings->vfp, timings->vbp)) return false; } @@ -3270,11 +3270,11 @@ void dispc_mgr_set_timings(enum omap_channel channel, if (dss_mgr_is_lcd(channel)) { _dispc_mgr_set_lcd_timings(channel, t.hsync_len, t.hfront_porch, - t.hbp, t.vsw, t.vfp, t.vbp, t.vsync_level, - t.hsync_level, t.data_pclk_edge, t.de_level, - t.sync_pclk_edge); + t.hback_porch, t.vsw, t.vfp, t.vbp, + t.vsync_level, t.hsync_level, t.data_pclk_edge, + t.de_level, t.sync_pclk_edge); - xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hbp; + xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hback_porch; ytot = t.vactive + t.vfp + t.vsw + t.vbp; ht = timings->pixelclock / xtot; @@ -3282,7 +3282,8 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("pck %u\n", timings->pixelclock); DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", - t.hsync_len, t.hfront_porch, t.hbp, t.vsw, t.vfp, t.vbp); + t.hsync_len, t.hfront_porch, t.hback_porch, + t.vsw, t.vfp, t.vbp); DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); @@ -4225,7 +4226,7 @@ static const struct dispc_errata_i734_data { .timings = { .hactive = 8, .vactive = 1, .pixelclock = 16000000, - .hsync_len = 8, .hfront_porch = 4, .hbp = 4, + .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, .vsw = 1, .vfp = 1, .vbp = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index f147c6c663d3..336521cdf824 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -225,7 +225,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->pixelclock = vm->pixelclock; ovt->hactive = vm->hactive; - ovt->hbp = vm->hback_porch; + ovt->hback_porch = vm->hback_porch; ovt->hfront_porch = vm->hfront_porch; ovt->hsync_len = vm->hsync_len; ovt->vactive = vm->vactive; @@ -258,7 +258,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->pixelclock = ovt->pixelclock; vm->hactive = ovt->hactive; - vm->hback_porch = ovt->hbp; + vm->hback_porch = ovt->hback_porch; vm->hfront_porch = ovt->hfront_porch; vm->hsync_len = ovt->hsync_len; vm->vactive = ovt->vactive; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 17eb16f86adc..a542d44ed53a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4423,7 +4423,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, t->pixelclock = pck; t->hactive = ctx->config->timings->hactive; t->vactive = ctx->config->timings->vactive; - t->hsync_len = t->hfront_porch = t->hbp = t->vsw = 1; + t->hsync_len = t->hfront_porch = t->hback_porch = t->vsw = 1; t->vfp = t->vbp = 0; return true; @@ -4527,7 +4527,8 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) xres = req_vm->hactive; - panel_hbl = req_vm->hfront_porch + req_vm->hbp + req_vm->hsync_len; + panel_hbl = req_vm->hfront_porch + req_vm->hback_porch + + req_vm->hsync_len; panel_htot = xres + panel_hbl; dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl); @@ -4603,7 +4604,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) hsa = max(hsa - hse, 1); } - hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom); + hbp = div64_u64((u64)req_vm->hback_porch * byteclk, req_pck_nom); hbp = max(hbp, 1); hfp = dsi_hbl - (hss + hsa + hse + hbp); @@ -4662,7 +4663,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) hsa = 1; } - hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom); + hbp = div64_u64((u64)req_vm->hback_porch * dispc_pck, req_pck_nom); hbp = max(hbp, 1); hfp = dispc_hbl - hsa - hbp; @@ -4687,7 +4688,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) dispc_vm->hfront_porch = hfp; dispc_vm->hsync_len = hsa; - dispc_vm->hbp = hbp; + dispc_vm->hback_porch = hbp; return true; } diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 26012224e7e4..f986b323764b 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -297,7 +297,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, /* video core */ video_cfg->data_enable_pol = 1; /* It is always 1*/ video_cfg->hblank = cfg->timings.hfront_porch + - cfg->timings.hbp + cfg->timings.hsync_len; + cfg->timings.hback_porch + cfg->timings.hsync_len; video_cfg->vblank_osc = 0; video_cfg->vblank = cfg->timings.vsw + cfg->timings.vfp + cfg->timings.vbp; @@ -320,7 +320,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, video_cfg->hblank *= 2; video_cfg->v_fc_config.timings.hfront_porch *= 2; video_cfg->v_fc_config.timings.hsync_len *= 2; - video_cfg->v_fc_config.timings.hbp *= 2; + video_cfg->v_fc_config.timings.hback_porch *= 2; } } diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 7b7efb6dc5d7..e4a431cb33a4 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -181,7 +181,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, omapdss_get_version() == OMAPDSS_VER_OMAP4) hsync_len_offset = 0; - timing_h |= FLD_VAL(timings->hbp, 31, 20); + timing_h |= FLD_VAL(timings->hback_porch, 31, 20); timing_h |= FLD_VAL(timings->hfront_porch, 19, 8); timing_h |= FLD_VAL(timings->hsync_len - hsync_len_offset, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h); @@ -201,7 +201,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, video_fmt->y_res = param->timings.vactive; video_fmt->x_res = param->timings.hactive; - timings->hbp = param->timings.hbp; + timings->hback_porch = param->timings.hback_porch; timings->hfront_porch = param->timings.hfront_porch; timings->hsync_len = param->timings.hsync_len; timings->vbp = param->timings.vbp; @@ -224,7 +224,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, video_fmt->x_res *= 2; timings->hfront_porch *= 2; timings->hsync_len *= 2; - timings->hbp *= 2; + timings->hback_porch *= 2; } } diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index b540baf81e0d..f8db4c29be83 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -311,7 +311,7 @@ struct omap_video_timings { /* Unit: pixel clocks */ u16 hfront_porch; /* Horizontal front porch */ /* Unit: pixel clocks */ - u16 hbp; /* Horizontal back porch */ + u16 hback_porch; /* Horizontal back porch */ /* Unit: line clocks */ u16 vsw; /* Vertical synchronization pulse width */ /* Unit: line clocks */ diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index 32b87bfd6d3f..0f721fbbe570 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -860,7 +860,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) */ rfbi.timings.hsync_len = 1; rfbi.timings.hfront_porch = 1; - rfbi.timings.hbp = 1; + rfbi.timings.hback_porch = 1; rfbi.timings.vsw = 1; rfbi.timings.vfp = 0; rfbi.timings.vbp = 0; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 92dbcab2d72a..f192368bec60 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -268,7 +268,7 @@ const struct omap_video_timings omap_dss_pal_timings = { .pixelclock = 13500000, .hsync_len = 64, .hfront_porch = 12, - .hbp = 68, + .hback_porch = 68, .vsw = 5, .vfp = 5, .vbp = 41, @@ -289,7 +289,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .pixelclock = 13500000, .hsync_len = 64, .hfront_porch = 16, - .hbp = 58, + .hback_porch = 58, .vsw = 6, .vfp = 6, .vbp = 31, diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 2399a6facea4..3d1b418fd858 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -50,7 +50,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->hdisplay = timings->hactive; mode->hsync_start = mode->hdisplay + timings->hfront_porch; mode->hsync_end = mode->hsync_start + timings->hsync_len; - mode->htotal = mode->hsync_end + timings->hbp; + mode->htotal = mode->hsync_end + timings->hback_porch; mode->vdisplay = timings->vactive; mode->vsync_start = mode->vdisplay + timings->vfp; @@ -84,7 +84,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->hactive = mode->hdisplay; timings->hfront_porch = mode->hsync_start - mode->hdisplay; timings->hsync_len = mode->hsync_end - mode->hsync_start; - timings->hbp = mode->htotal - mode->hsync_end; + timings->hback_porch = mode->htotal - mode->hsync_end; timings->vactive = mode->vdisplay; timings->vfp = mode->vsync_start - mode->vdisplay; -- cgit v1.2.3 From d5bcf0aa3f6fb396fc8099a4e5960f9274b0dae9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:51 +0300 Subject: drm/omap: omap_display_timings: rename vsw to vsync_len In preparation to move the stack to use the generic videmode struct for display timing information rename the vsw member to vsync_len. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 12 ++++++------ drivers/gpu/drm/omapdrm/dss/display.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 ++-- 18 files changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 2dbc6a42fb32..ce33f47f4eea 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -36,7 +36,7 @@ static const struct omap_video_timings tvc_pal_timings = { .hsync_len = 64, .hfront_porch = 12, .hback_porch = 68, - .vsw = 5, + .vsync_len = 5, .vfp = 5, .vbp = 41, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index 6cf541cb9933..91516fbc711b 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -30,7 +30,7 @@ static const struct omap_video_timings dvic_default_timings = { .hback_porch = 80, .vfp = 3, - .vsw = 4, + .vsync_len = 4, .vbp = 7, .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 24d047844b7c..6e75da30dc9d 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -28,7 +28,7 @@ static const struct omap_video_timings hdmic_default_timings = { .hsync_len = 96, .hfront_porch = 16, .hback_porch = 48, - .vsw = 2, + .vsync_len = 2, .vfp = 11, .vbp = 31, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 295904a5f28d..5b2dd1e48705 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -29,7 +29,7 @@ static struct omap_video_timings lb035q02_timings = { .hfront_porch = 20, .hback_porch = 68, - .vsw = 2, + .vsync_len = 2, .vfp = 4, .vbp = 18, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index d408824a3341..ce0ab77a6fcd 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -73,7 +73,7 @@ static const struct omap_video_timings nec_8048_panel_timings = { .hsync_len = 1, .hback_porch = 4, .vfp = 3, - .vsw = 1, + .vsync_len = 1, .vbp = 4, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index b36df2c66db1..917f145e8d88 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -45,7 +45,7 @@ static const struct omap_video_timings sharp_ls_timings = { .hfront_porch = 1, .hback_porch = 28, - .vsw = 1, + .vsync_len = 1, .vfp = 1, .vbp = 1, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index ed55ad9fa731..2a42985782fd 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -100,7 +100,7 @@ static const struct omap_video_timings acx565akm_panel_timings = { .hsync_len = 4, .hback_porch = 24, .vfp = 3, - .vsw = 3, + .vsync_len = 3, .vbp = 4, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index f1cc3fa275e6..693b9ec9326e 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -50,7 +50,7 @@ static struct omap_video_timings td028ttec1_panel_timings = { .hsync_len = 8, .hback_porch = 8, .vfp = 4, - .vsw = 2, + .vsync_len = 2, .vbp = 2, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 458a4541f85c..6301701c820e 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -82,7 +82,7 @@ static const struct omap_video_timings tpo_td043_timings = { .hfront_porch = 68, .hback_porch = 214, - .vsw = 1, + .vsync_len = 1, .vfp = 39, .vbp = 34, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 0d115aa6c86e..ddb9d9d28157 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2869,7 +2869,7 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, } else { int wbdelay; - wbdelay = min(mgr_timings->vfp + mgr_timings->vsw + + wbdelay = min(mgr_timings->vfp + mgr_timings->vsync_len + mgr_timings->vbp, 255); /* WBDELAYCOUNT */ @@ -3133,7 +3133,7 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, if (!_dispc_lcd_timings_ok(timings->hsync_len, timings->hfront_porch, timings->hback_porch, - timings->vsw, timings->vfp, timings->vbp)) + timings->vsync_len, timings->vfp, timings->vbp)) return false; } @@ -3270,12 +3270,12 @@ void dispc_mgr_set_timings(enum omap_channel channel, if (dss_mgr_is_lcd(channel)) { _dispc_mgr_set_lcd_timings(channel, t.hsync_len, t.hfront_porch, - t.hback_porch, t.vsw, t.vfp, t.vbp, + t.hback_porch, t.vsync_len, t.vfp, t.vbp, t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hback_porch; - ytot = t.vactive + t.vfp + t.vsw + t.vbp; + ytot = t.vactive + t.vfp + t.vsync_len + t.vbp; ht = timings->pixelclock / xtot; vt = timings->pixelclock / xtot / ytot; @@ -3283,7 +3283,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("pck %u\n", timings->pixelclock); DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", t.hsync_len, t.hfront_porch, t.hback_porch, - t.vsw, t.vfp, t.vbp); + t.vsync_len, t.vfp, t.vbp); DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); @@ -4227,7 +4227,7 @@ static const struct dispc_errata_i734_data { .hactive = 8, .vactive = 1, .pixelclock = 16000000, .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, - .vsw = 1, .vfp = 1, .vbp = 1, + .vsync_len = 1, .vfp = 1, .vbp = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .interlace = false, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 336521cdf824..372a16ad770f 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -231,7 +231,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->vactive = vm->vactive; ovt->vbp = vm->vback_porch; ovt->vfp = vm->vfront_porch; - ovt->vsw = vm->vsync_len; + ovt->vsync_len = vm->vsync_len; ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ? OMAPDSS_SIG_ACTIVE_HIGH : @@ -264,7 +264,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->vactive = ovt->vactive; vm->vback_porch = ovt->vbp; vm->vfront_porch = ovt->vfp; - vm->vsync_len = ovt->vsw; + vm->vsync_len = ovt->vsync_len; if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index a542d44ed53a..850478b2ee7c 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4423,7 +4423,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, t->pixelclock = pck; t->hactive = ctx->config->timings->hactive; t->vactive = ctx->config->timings->vactive; - t->hsync_len = t->hfront_porch = t->hback_porch = t->vsw = 1; + t->hsync_len = t->hfront_porch = t->hback_porch = t->vsync_len = 1; t->vfp = t->vbp = 0; return true; @@ -4634,7 +4634,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) dsi_vm->hact = xres; dsi_vm->hfp = hfp; - dsi_vm->vsa = req_vm->vsw; + dsi_vm->vsa = req_vm->vsync_len; dsi_vm->vbp = req_vm->vbp; dsi_vm->vact = req_vm->vactive; dsi_vm->vfp = req_vm->vfp; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index f986b323764b..39944749c160 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -299,7 +299,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, video_cfg->hblank = cfg->timings.hfront_porch + cfg->timings.hback_porch + cfg->timings.hsync_len; video_cfg->vblank_osc = 0; - video_cfg->vblank = cfg->timings.vsw + + video_cfg->vblank = cfg->timings.vsync_len + cfg->timings.vfp + cfg->timings.vbp; video_cfg->v_fc_config.hdmi_dvi_mode = cfg->hdmi_dvi_mode; @@ -311,7 +311,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, video_cfg->v_fc_config.timings.vactive /= 2; video_cfg->vblank /= 2; video_cfg->v_fc_config.timings.vfp /= 2; - video_cfg->v_fc_config.timings.vsw /= 2; + video_cfg->v_fc_config.timings.vsync_len /= 2; video_cfg->v_fc_config.timings.vbp /= 2; } @@ -383,7 +383,7 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, /* set vertical sync pulse width */ REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, - cfg->v_fc_config.timings.vsw, 5, 0); + cfg->v_fc_config.timings.vsync_len, 5, 0); /* select DVI mode */ REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index e4a431cb33a4..ba964c12148d 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -188,7 +188,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, timing_v |= FLD_VAL(timings->vbp, 31, 20); timing_v |= FLD_VAL(timings->vfp, 19, 8); - timing_v |= FLD_VAL(timings->vsw, 7, 0); + timing_v |= FLD_VAL(timings->vsync_len, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v); } @@ -206,7 +206,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, timings->hsync_len = param->timings.hsync_len; timings->vbp = param->timings.vbp; timings->vfp = param->timings.vfp; - timings->vsw = param->timings.vsw; + timings->vsync_len = param->timings.vsync_len; timings->vsync_level = param->timings.vsync_level; timings->hsync_level = param->timings.hsync_level; @@ -217,7 +217,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, video_fmt->y_res /= 2; timings->vbp /= 2; timings->vfp /= 2; - timings->vsw /= 2; + timings->vsync_len /= 2; } if (param->timings.double_pixel) { diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index f8db4c29be83..c761583b0b24 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -313,7 +313,7 @@ struct omap_video_timings { /* Unit: pixel clocks */ u16 hback_porch; /* Horizontal back porch */ /* Unit: line clocks */ - u16 vsw; /* Vertical synchronization pulse width */ + u16 vsync_len; /* Vertical synchronization pulse width */ /* Unit: line clocks */ u16 vfp; /* Vertical front porch */ /* Unit: line clocks */ diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index 0f721fbbe570..b90348ad2e31 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -861,7 +861,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.hsync_len = 1; rfbi.timings.hfront_porch = 1; rfbi.timings.hback_porch = 1; - rfbi.timings.vsw = 1; + rfbi.timings.vsync_len = 1; rfbi.timings.vfp = 0; rfbi.timings.vbp = 0; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index f192368bec60..5e8ea7e00b68 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -269,7 +269,7 @@ const struct omap_video_timings omap_dss_pal_timings = { .hsync_len = 64, .hfront_porch = 12, .hback_porch = 68, - .vsw = 5, + .vsync_len = 5, .vfp = 5, .vbp = 41, @@ -290,7 +290,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .hsync_len = 64, .hfront_porch = 16, .hback_porch = 58, - .vsw = 6, + .vsync_len = 6, .vfp = 6, .vbp = 31, diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 3d1b418fd858..2c9b429da5cc 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -54,7 +54,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->vdisplay = timings->vactive; mode->vsync_start = mode->vdisplay + timings->vfp; - mode->vsync_end = mode->vsync_start + timings->vsw; + mode->vsync_end = mode->vsync_start + timings->vsync_len; mode->vtotal = mode->vsync_end + timings->vbp; mode->flags = 0; @@ -88,7 +88,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->vactive = mode->vdisplay; timings->vfp = mode->vsync_start - mode->vdisplay; - timings->vsw = mode->vsync_end - mode->vsync_start; + timings->vsync_len = mode->vsync_end - mode->vsync_start; timings->vbp = mode->vtotal - mode->vsync_end; timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); -- cgit v1.2.3 From 0996c68e1bf7364ca7f02ac06048c12abb56c37a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:52 +0300 Subject: drm/omap: omap_display_timings: rename vfp to vfront_porch In preparation to move the stack to use the generic videmode struct for display timing information rename the vfp member to vfront_porch. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 +- .../gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 2 +- .../gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 15 ++++++++------- drivers/gpu/drm/omapdrm/dss/display.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 ++-- 18 files changed, 33 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index ce33f47f4eea..51d0d45a6675 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -37,7 +37,7 @@ static const struct omap_video_timings tvc_pal_timings = { .hfront_porch = 12, .hback_porch = 68, .vsync_len = 5, - .vfp = 5, + .vfront_porch = 5, .vbp = 41, .interlace = true, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index 91516fbc711b..efd122760833 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -29,7 +29,7 @@ static const struct omap_video_timings dvic_default_timings = { .hsync_len = 32, .hback_porch = 80, - .vfp = 3, + .vfront_porch = 3, .vsync_len = 4, .vbp = 7, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 6e75da30dc9d..7d60e465d354 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -29,7 +29,7 @@ static const struct omap_video_timings hdmic_default_timings = { .hfront_porch = 16, .hback_porch = 48, .vsync_len = 2, - .vfp = 11, + .vfront_porch = 11, .vbp = 31, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 5b2dd1e48705..66d30ba7db81 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -30,7 +30,7 @@ static struct omap_video_timings lb035q02_timings = { .hback_porch = 68, .vsync_len = 2, - .vfp = 4, + .vfront_porch = 4, .vbp = 18, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index ce0ab77a6fcd..9cb02c4bce41 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -72,7 +72,7 @@ static const struct omap_video_timings nec_8048_panel_timings = { .hfront_porch = 6, .hsync_len = 1, .hback_porch = 4, - .vfp = 3, + .vfront_porch = 3, .vsync_len = 1, .vbp = 4, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index 917f145e8d88..3b23aaf2676d 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -46,7 +46,7 @@ static const struct omap_video_timings sharp_ls_timings = { .hback_porch = 28, .vsync_len = 1, - .vfp = 1, + .vfront_porch = 1, .vbp = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 2a42985782fd..6b1140b82f6e 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -99,7 +99,7 @@ static const struct omap_video_timings acx565akm_panel_timings = { .hfront_porch = 28, .hsync_len = 4, .hback_porch = 24, - .vfp = 3, + .vfront_porch = 3, .vsync_len = 3, .vbp = 4, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 693b9ec9326e..48fa05974158 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -49,7 +49,7 @@ static struct omap_video_timings td028ttec1_panel_timings = { .hfront_porch = 24, .hsync_len = 8, .hback_porch = 8, - .vfp = 4, + .vfront_porch = 4, .vsync_len = 2, .vbp = 2, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 6301701c820e..2d3bda3c9376 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -83,7 +83,7 @@ static const struct omap_video_timings tpo_td043_timings = { .hback_porch = 214, .vsync_len = 1, - .vfp = 39, + .vfront_porch = 39, .vbp = 34, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index ddb9d9d28157..c732d6c70c66 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2869,8 +2869,8 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, } else { int wbdelay; - wbdelay = min(mgr_timings->vfp + mgr_timings->vsync_len + - mgr_timings->vbp, 255); + wbdelay = min(mgr_timings->vfront_porch + + mgr_timings->vsync_len + mgr_timings->vbp, 255); /* WBDELAYCOUNT */ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0); @@ -3133,7 +3133,8 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, if (!_dispc_lcd_timings_ok(timings->hsync_len, timings->hfront_porch, timings->hback_porch, - timings->vsync_len, timings->vfp, timings->vbp)) + timings->vsync_len, timings->vfront_porch, + timings->vbp)) return false; } @@ -3270,12 +3271,12 @@ void dispc_mgr_set_timings(enum omap_channel channel, if (dss_mgr_is_lcd(channel)) { _dispc_mgr_set_lcd_timings(channel, t.hsync_len, t.hfront_porch, - t.hback_porch, t.vsync_len, t.vfp, t.vbp, + t.hback_porch, t.vsync_len, t.vfront_porch, t.vbp, t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hback_porch; - ytot = t.vactive + t.vfp + t.vsync_len + t.vbp; + ytot = t.vactive + t.vfront_porch + t.vsync_len + t.vbp; ht = timings->pixelclock / xtot; vt = timings->pixelclock / xtot / ytot; @@ -3283,7 +3284,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("pck %u\n", timings->pixelclock); DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", t.hsync_len, t.hfront_porch, t.hback_porch, - t.vsync_len, t.vfp, t.vbp); + t.vsync_len, t.vfront_porch, t.vbp); DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); @@ -4227,7 +4228,7 @@ static const struct dispc_errata_i734_data { .hactive = 8, .vactive = 1, .pixelclock = 16000000, .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, - .vsync_len = 1, .vfp = 1, .vbp = 1, + .vsync_len = 1, .vfront_porch = 1, .vbp = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .interlace = false, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 372a16ad770f..30060b5e46a2 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -230,7 +230,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->hsync_len = vm->hsync_len; ovt->vactive = vm->vactive; ovt->vbp = vm->vback_porch; - ovt->vfp = vm->vfront_porch; + ovt->vfront_porch = vm->vfront_porch; ovt->vsync_len = vm->vsync_len; ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ? @@ -263,7 +263,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->hsync_len = ovt->hsync_len; vm->vactive = ovt->vactive; vm->vback_porch = ovt->vbp; - vm->vfront_porch = ovt->vfp; + vm->vfront_porch = ovt->vfront_porch; vm->vsync_len = ovt->vsync_len; if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 850478b2ee7c..f7857bbfda4e 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4424,7 +4424,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, t->hactive = ctx->config->timings->hactive; t->vactive = ctx->config->timings->vactive; t->hsync_len = t->hfront_porch = t->hback_porch = t->vsync_len = 1; - t->vfp = t->vbp = 0; + t->vfront_porch = t->vbp = 0; return true; } @@ -4637,7 +4637,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) dsi_vm->vsa = req_vm->vsync_len; dsi_vm->vbp = req_vm->vbp; dsi_vm->vact = req_vm->vactive; - dsi_vm->vfp = req_vm->vfp; + dsi_vm->vfp = req_vm->vfront_porch; dsi_vm->trans_mode = cfg->trans_mode; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 39944749c160..932975b372c0 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -300,7 +300,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, cfg->timings.hback_porch + cfg->timings.hsync_len; video_cfg->vblank_osc = 0; video_cfg->vblank = cfg->timings.vsync_len + - cfg->timings.vfp + cfg->timings.vbp; + cfg->timings.vfront_porch + cfg->timings.vbp; video_cfg->v_fc_config.hdmi_dvi_mode = cfg->hdmi_dvi_mode; if (cfg->timings.interlace) { @@ -310,7 +310,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, video_cfg->v_fc_config.timings.vactive /= 2; video_cfg->vblank /= 2; - video_cfg->v_fc_config.timings.vfp /= 2; + video_cfg->v_fc_config.timings.vfront_porch /= 2; video_cfg->v_fc_config.timings.vsync_len /= 2; video_cfg->v_fc_config.timings.vbp /= 2; } @@ -373,7 +373,7 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, /* set vertical sync offset */ REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, - cfg->v_fc_config.timings.vfp, 7, 0); + cfg->v_fc_config.timings.vfront_porch, 7, 0); /* set horizontal sync pulse width */ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index ba964c12148d..ed6ce7474bad 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -187,7 +187,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h); timing_v |= FLD_VAL(timings->vbp, 31, 20); - timing_v |= FLD_VAL(timings->vfp, 19, 8); + timing_v |= FLD_VAL(timings->vfront_porch, 19, 8); timing_v |= FLD_VAL(timings->vsync_len, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v); } @@ -205,7 +205,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, timings->hfront_porch = param->timings.hfront_porch; timings->hsync_len = param->timings.hsync_len; timings->vbp = param->timings.vbp; - timings->vfp = param->timings.vfp; + timings->vfront_porch = param->timings.vfront_porch; timings->vsync_len = param->timings.vsync_len; timings->vsync_level = param->timings.vsync_level; @@ -216,7 +216,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, if (param->timings.interlace) { video_fmt->y_res /= 2; timings->vbp /= 2; - timings->vfp /= 2; + timings->vfront_porch /= 2; timings->vsync_len /= 2; } diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index c761583b0b24..141bcb34db78 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -315,7 +315,7 @@ struct omap_video_timings { /* Unit: line clocks */ u16 vsync_len; /* Vertical synchronization pulse width */ /* Unit: line clocks */ - u16 vfp; /* Vertical front porch */ + u16 vfront_porch; /* Vertical front porch */ /* Unit: line clocks */ u16 vbp; /* Vertical back porch */ diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index b90348ad2e31..de7f904f6e91 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -862,7 +862,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.hfront_porch = 1; rfbi.timings.hback_porch = 1; rfbi.timings.vsync_len = 1; - rfbi.timings.vfp = 0; + rfbi.timings.vfront_porch = 0; rfbi.timings.vbp = 0; rfbi.timings.interlace = false; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 5e8ea7e00b68..77d4c826b2e5 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -270,7 +270,7 @@ const struct omap_video_timings omap_dss_pal_timings = { .hfront_porch = 12, .hback_porch = 68, .vsync_len = 5, - .vfp = 5, + .vfront_porch = 5, .vbp = 41, .interlace = true, @@ -291,7 +291,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .hfront_porch = 16, .hback_porch = 58, .vsync_len = 6, - .vfp = 6, + .vfront_porch = 6, .vbp = 31, .interlace = true, diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 2c9b429da5cc..3798617b1d7b 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -53,7 +53,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->htotal = mode->hsync_end + timings->hback_porch; mode->vdisplay = timings->vactive; - mode->vsync_start = mode->vdisplay + timings->vfp; + mode->vsync_start = mode->vdisplay + timings->vfront_porch; mode->vsync_end = mode->vsync_start + timings->vsync_len; mode->vtotal = mode->vsync_end + timings->vbp; @@ -87,7 +87,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->hback_porch = mode->htotal - mode->hsync_end; timings->vactive = mode->vdisplay; - timings->vfp = mode->vsync_start - mode->vdisplay; + timings->vfront_porch = mode->vsync_start - mode->vdisplay; timings->vsync_len = mode->vsync_end - mode->vsync_start; timings->vbp = mode->vtotal - mode->vsync_end; -- cgit v1.2.3 From 458540c606757a4b52476f8e4d937a36ed94c577 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:53 +0300 Subject: drm/omap: omap_display_timings: rename vbp to vback_porch In preparation to move the stack to use the generic videmode struct for display timing information rename the vbp member to vback_porch. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 +- .../gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 2 +- .../gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 +- drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 15 ++++++++------- drivers/gpu/drm/omapdrm/dss/display.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 ++-- 18 files changed, 33 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 51d0d45a6675..d14cc2e3b8e2 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -38,7 +38,7 @@ static const struct omap_video_timings tvc_pal_timings = { .hback_porch = 68, .vsync_len = 5, .vfront_porch = 5, - .vbp = 41, + .vback_porch = 41, .interlace = true, }; diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index efd122760833..adbcd566a7ec 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -31,7 +31,7 @@ static const struct omap_video_timings dvic_default_timings = { .vfront_porch = 3, .vsync_len = 4, - .vbp = 7, + .vback_porch = 7, .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH, .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH, diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 7d60e465d354..00e3aa212202 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -30,7 +30,7 @@ static const struct omap_video_timings hdmic_default_timings = { .hback_porch = 48, .vsync_len = 2, .vfront_porch = 11, - .vbp = 31, + .vback_porch = 31, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 66d30ba7db81..9c114da37a6b 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -31,7 +31,7 @@ static struct omap_video_timings lb035q02_timings = { .vsync_len = 2, .vfront_porch = 4, - .vbp = 18, + .vback_porch = 18, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index 9cb02c4bce41..1e1acc6e06cb 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -74,7 +74,7 @@ static const struct omap_video_timings nec_8048_panel_timings = { .hback_porch = 4, .vfront_porch = 3, .vsync_len = 1, - .vbp = 4, + .vback_porch = 4, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index 3b23aaf2676d..79cb8bde1cca 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -47,7 +47,7 @@ static const struct omap_video_timings sharp_ls_timings = { .vsync_len = 1, .vfront_porch = 1, - .vbp = 1, + .vback_porch = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 6b1140b82f6e..30d689818518 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -101,7 +101,7 @@ static const struct omap_video_timings acx565akm_panel_timings = { .hback_porch = 24, .vfront_porch = 3, .vsync_len = 3, - .vbp = 4, + .vback_porch = 4, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 48fa05974158..a367b615d808 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -51,7 +51,7 @@ static struct omap_video_timings td028ttec1_panel_timings = { .hback_porch = 8, .vfront_porch = 4, .vsync_len = 2, - .vbp = 2, + .vback_porch = 2, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 2d3bda3c9376..16d24381b270 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -84,7 +84,7 @@ static const struct omap_video_timings tpo_td043_timings = { .vsync_len = 1, .vfront_porch = 39, - .vbp = 34, + .vback_porch = 34, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index c732d6c70c66..d46a0a2c6b7b 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2870,7 +2870,7 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, int wbdelay; wbdelay = min(mgr_timings->vfront_porch + - mgr_timings->vsync_len + mgr_timings->vbp, 255); + mgr_timings->vsync_len + mgr_timings->vback_porch, 255); /* WBDELAYCOUNT */ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0); @@ -3134,7 +3134,7 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, if (!_dispc_lcd_timings_ok(timings->hsync_len, timings->hfront_porch, timings->hback_porch, timings->vsync_len, timings->vfront_porch, - timings->vbp)) + timings->vback_porch)) return false; } @@ -3270,13 +3270,14 @@ void dispc_mgr_set_timings(enum omap_channel channel, } if (dss_mgr_is_lcd(channel)) { - _dispc_mgr_set_lcd_timings(channel, t.hsync_len, t.hfront_porch, - t.hback_porch, t.vsync_len, t.vfront_porch, t.vbp, + _dispc_mgr_set_lcd_timings(channel, + t.hsync_len, t.hfront_porch, t.hback_porch, + t.vsync_len, t.vfront_porch, t.vback_porch, t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hback_porch; - ytot = t.vactive + t.vfront_porch + t.vsync_len + t.vbp; + ytot = t.vactive + t.vfront_porch + t.vsync_len + t.vback_porch; ht = timings->pixelclock / xtot; vt = timings->pixelclock / xtot / ytot; @@ -3284,7 +3285,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("pck %u\n", timings->pixelclock); DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", t.hsync_len, t.hfront_porch, t.hback_porch, - t.vsync_len, t.vfront_porch, t.vbp); + t.vsync_len, t.vfront_porch, t.vback_porch); DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", t.vsync_level, t.hsync_level, t.data_pclk_edge, t.de_level, t.sync_pclk_edge); @@ -4228,7 +4229,7 @@ static const struct dispc_errata_i734_data { .hactive = 8, .vactive = 1, .pixelclock = 16000000, .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, - .vsync_len = 1, .vfront_porch = 1, .vbp = 1, + .vsync_len = 1, .vfront_porch = 1, .vback_porch = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .interlace = false, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 30060b5e46a2..d63ea2d5d812 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -229,7 +229,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->hfront_porch = vm->hfront_porch; ovt->hsync_len = vm->hsync_len; ovt->vactive = vm->vactive; - ovt->vbp = vm->vback_porch; + ovt->vback_porch = vm->vback_porch; ovt->vfront_porch = vm->vfront_porch; ovt->vsync_len = vm->vsync_len; @@ -262,7 +262,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->hfront_porch = ovt->hfront_porch; vm->hsync_len = ovt->hsync_len; vm->vactive = ovt->vactive; - vm->vback_porch = ovt->vbp; + vm->vback_porch = ovt->vback_porch; vm->vfront_porch = ovt->vfront_porch; vm->vsync_len = ovt->vsync_len; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index f7857bbfda4e..e1fdb2a63309 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4424,7 +4424,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, t->hactive = ctx->config->timings->hactive; t->vactive = ctx->config->timings->vactive; t->hsync_len = t->hfront_porch = t->hback_porch = t->vsync_len = 1; - t->vfront_porch = t->vbp = 0; + t->vfront_porch = t->vback_porch = 0; return true; } @@ -4635,7 +4635,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) dsi_vm->hfp = hfp; dsi_vm->vsa = req_vm->vsync_len; - dsi_vm->vbp = req_vm->vbp; + dsi_vm->vbp = req_vm->vback_porch; dsi_vm->vact = req_vm->vactive; dsi_vm->vfp = req_vm->vfront_porch; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 932975b372c0..457dbd2f93a2 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -299,8 +299,8 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, video_cfg->hblank = cfg->timings.hfront_porch + cfg->timings.hback_porch + cfg->timings.hsync_len; video_cfg->vblank_osc = 0; - video_cfg->vblank = cfg->timings.vsync_len + - cfg->timings.vfront_porch + cfg->timings.vbp; + video_cfg->vblank = cfg->timings.vsync_len + cfg->timings.vfront_porch + + cfg->timings.vback_porch; video_cfg->v_fc_config.hdmi_dvi_mode = cfg->hdmi_dvi_mode; if (cfg->timings.interlace) { @@ -312,7 +312,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, video_cfg->vblank /= 2; video_cfg->v_fc_config.timings.vfront_porch /= 2; video_cfg->v_fc_config.timings.vsync_len /= 2; - video_cfg->v_fc_config.timings.vbp /= 2; + video_cfg->v_fc_config.timings.vback_porch /= 2; } if (cfg->timings.double_pixel) { diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index ed6ce7474bad..90a36b009b1c 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -186,7 +186,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, timing_h |= FLD_VAL(timings->hsync_len - hsync_len_offset, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h); - timing_v |= FLD_VAL(timings->vbp, 31, 20); + timing_v |= FLD_VAL(timings->vback_porch, 31, 20); timing_v |= FLD_VAL(timings->vfront_porch, 19, 8); timing_v |= FLD_VAL(timings->vsync_len, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v); @@ -204,7 +204,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, timings->hback_porch = param->timings.hback_porch; timings->hfront_porch = param->timings.hfront_porch; timings->hsync_len = param->timings.hsync_len; - timings->vbp = param->timings.vbp; + timings->vback_porch = param->timings.vback_porch; timings->vfront_porch = param->timings.vfront_porch; timings->vsync_len = param->timings.vsync_len; @@ -215,7 +215,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, if (param->timings.interlace) { video_fmt->y_res /= 2; - timings->vbp /= 2; + timings->vback_porch /= 2; timings->vfront_porch /= 2; timings->vsync_len /= 2; } diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 141bcb34db78..aca9d3028155 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -317,7 +317,7 @@ struct omap_video_timings { /* Unit: line clocks */ u16 vfront_porch; /* Vertical front porch */ /* Unit: line clocks */ - u16 vbp; /* Vertical back porch */ + u16 vback_porch; /* Vertical back porch */ /* Vsync logic level */ enum omap_dss_signal_level vsync_level; diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index de7f904f6e91..cc59e644ea52 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -863,7 +863,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.hback_porch = 1; rfbi.timings.vsync_len = 1; rfbi.timings.vfront_porch = 0; - rfbi.timings.vbp = 0; + rfbi.timings.vback_porch = 0; rfbi.timings.interlace = false; rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 77d4c826b2e5..411eea6bc99f 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -271,7 +271,7 @@ const struct omap_video_timings omap_dss_pal_timings = { .hback_porch = 68, .vsync_len = 5, .vfront_porch = 5, - .vbp = 41, + .vback_porch = 41, .interlace = true, @@ -292,7 +292,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .hback_porch = 58, .vsync_len = 6, .vfront_porch = 6, - .vbp = 31, + .vback_porch = 31, .interlace = true, diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 3798617b1d7b..d6c4dc1c1fcb 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -55,7 +55,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->vdisplay = timings->vactive; mode->vsync_start = mode->vdisplay + timings->vfront_porch; mode->vsync_end = mode->vsync_start + timings->vsync_len; - mode->vtotal = mode->vsync_end + timings->vbp; + mode->vtotal = mode->vsync_end + timings->vback_porch; mode->flags = 0; @@ -89,7 +89,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->vactive = mode->vdisplay; timings->vfront_porch = mode->vsync_start - mode->vdisplay; timings->vsync_len = mode->vsync_end - mode->vsync_start; - timings->vbp = mode->vtotal - mode->vsync_end; + timings->vback_porch = mode->vtotal - mode->vsync_end; timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); timings->double_pixel = !!(mode->flags & DRM_MODE_FLAG_DBLCLK); -- cgit v1.2.3 From fe70cd7667edd339c64ed4600cd93c63ba83dd4e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:54 +0300 Subject: drm/omap: HDMI5: Use pointer to cfg->v_fc_config.timings in hdmi_core_video_config By using a pointer to the omap_mode_timings struct we can unwrap lines to make the code easier to follow. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 47 ++++++++++++++------------------ 1 file changed, 20 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 457dbd2f93a2..2baef4f7714b 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -329,13 +329,12 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, struct hdmi_core_vid_config *cfg) { void __iomem *base = core->base; + struct omap_video_timings *ovt = &cfg->v_fc_config.timings; unsigned char r = 0; bool vsync_pol, hsync_pol; - vsync_pol = - cfg->v_fc_config.timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; - hsync_pol = - cfg->v_fc_config.timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; + vsync_pol = ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; + hsync_pol = ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; /* Set hsync, vsync and data-enable polarity */ r = hdmi_read_reg(base, HDMI_CORE_FC_INVIDCONF); @@ -343,20 +342,16 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, r = FLD_MOD(r, hsync_pol, 5, 5); r = FLD_MOD(r, cfg->data_enable_pol, 4, 4); r = FLD_MOD(r, cfg->vblank_osc, 1, 1); - r = FLD_MOD(r, cfg->v_fc_config.timings.interlace, 0, 0); + r = FLD_MOD(r, ovt->interlace, 0, 0); hdmi_write_reg(base, HDMI_CORE_FC_INVIDCONF, r); /* set x resolution */ - REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1, - cfg->v_fc_config.timings.hactive >> 8, 4, 0); - REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0, - cfg->v_fc_config.timings.hactive & 0xFF, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1, ovt->hactive >> 8, 4, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0, ovt->hactive & 0xFF, 7, 0); /* set y resolution */ - REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, - cfg->v_fc_config.timings.vactive >> 8, 4, 0); - REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0, - cfg->v_fc_config.timings.vactive & 0xFF, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, ovt->vactive >> 8, 4, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0, ovt->vactive & 0xFF, 7, 0); /* set horizontal blanking pixels */ REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK1, cfg->hblank >> 8, 4, 0); @@ -366,30 +361,28 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, REG_FLD_MOD(base, HDMI_CORE_FC_INVBLANK, cfg->vblank, 7, 0); /* set horizontal sync offset */ - REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1, - cfg->v_fc_config.timings.hfront_porch >> 8, 4, 0); - REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0, - cfg->v_fc_config.timings.hfront_porch & 0xFF, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1, ovt->hfront_porch >> 8, + 4, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0, ovt->hfront_porch & 0xFF, + 7, 0); /* set vertical sync offset */ - REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, - cfg->v_fc_config.timings.vfront_porch, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, ovt->vfront_porch, 7, 0); /* set horizontal sync pulse width */ - REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, - (cfg->v_fc_config.timings.hsync_len >> 8), 1, 0); - REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0, - cfg->v_fc_config.timings.hsync_len & 0xFF, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, (ovt->hsync_len >> 8), + 1, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0, ovt->hsync_len & 0xFF, + 7, 0); /* set vertical sync pulse width */ - REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, - cfg->v_fc_config.timings.vsync_len, 5, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, ovt->vsync_len, 5, 0); /* select DVI mode */ REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF, - cfg->v_fc_config.hdmi_dvi_mode, 3, 3); + cfg->v_fc_config.hdmi_dvi_mode, 3, 3); - if (cfg->v_fc_config.timings.double_pixel) + if (ovt->double_pixel) REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 2, 7, 4); else REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 1, 7, 4); -- cgit v1.2.3 From 530582998acef0a6f9aafed7c82a2bb11b4405f6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:55 +0300 Subject: drm/omap: omap_display_timings: Use display_flags for interlace mode Remove the interlace member and add display_flags to omap_video_timings to configure the interlace mode. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 2 -- drivers/gpu/drm/omapdrm/dss/dispc.c | 7 +++---- drivers/gpu/drm/omapdrm/dss/dsi.c | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/omapdss.h | 4 ++-- drivers/gpu/drm/omapdrm/dss/rfbi.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 8 ++++---- drivers/gpu/drm/omapdrm/omap_connector.c | 6 ++++-- 10 files changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index d14cc2e3b8e2..0a7491427832 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -40,7 +40,7 @@ static const struct omap_video_timings tvc_pal_timings = { .vfront_porch = 5, .vback_porch = 41, - .interlace = true, + .flags = DISPLAY_FLAGS_INTERLACED, }; static const struct of_device_id tvc_of_match[]; diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 00e3aa212202..8e246b9142d7 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -34,8 +34,6 @@ static const struct omap_video_timings hdmic_default_timings = { .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, - - .interlace = false, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index d46a0a2c6b7b..f11bfe5378d1 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2607,7 +2607,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, u16 in_height = height; u16 in_width = width; int x_predecim = 1, y_predecim = 1; - bool ilace = mgr_timings->interlace; + bool ilace = !!(mgr_timings->flags & DISPLAY_FLAGS_INTERLACED); unsigned long pclk = dispc_plane_pclk_rate(plane); unsigned long lclk = dispc_plane_lclk_rate(plane); @@ -3128,7 +3128,7 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, if (dss_mgr_is_lcd(channel)) { /* TODO: OMAP4+ supports interlace for LCD outputs */ - if (timings->interlace) + if (timings->flags & DISPLAY_FLAGS_INTERLACED) return false; if (!_dispc_lcd_timings_ok(timings->hsync_len, @@ -3292,7 +3292,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); } else { - if (t.interlace) + if (t.flags & DISPLAY_FLAGS_INTERLACED) t.vactive /= 2; if (dispc.feat->supports_double_pixel) @@ -4232,7 +4232,6 @@ static const struct dispc_errata_i734_data { .vsync_len = 1, .vfront_porch = 1, .vback_porch = 1, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .interlace = false, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index e1fdb2a63309..313c8e24ac84 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4122,7 +4122,7 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, * override interlace, logic level and edge related parameters in * omap_video_timings with default values */ - dsi->timings.interlace = false; + dsi->timings.flags &= ~DISPLAY_FLAGS_INTERLACED; dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 2baef4f7714b..62268f8d62c6 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -303,7 +303,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, cfg->timings.vback_porch; video_cfg->v_fc_config.hdmi_dvi_mode = cfg->hdmi_dvi_mode; - if (cfg->timings.interlace) { + if (cfg->timings.flags & DISPLAY_FLAGS_INTERLACED) { /* set vblank_osc if vblank is fractional */ if (video_cfg->vblank % 2 != 0) video_cfg->vblank_osc = 1; @@ -342,7 +342,7 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, r = FLD_MOD(r, hsync_pol, 5, 5); r = FLD_MOD(r, cfg->data_enable_pol, 4, 4); r = FLD_MOD(r, cfg->vblank_osc, 1, 1); - r = FLD_MOD(r, ovt->interlace, 0, 0); + r = FLD_MOD(r, !!(ovt->flags & DISPLAY_FLAGS_INTERLACED), 0, 0); hdmi_write_reg(base, HDMI_CORE_FC_INVIDCONF, r); /* set x resolution */ diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 90a36b009b1c..231f62ed86ff 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -156,7 +156,7 @@ void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG); r = FLD_MOD(r, vsync_pol, 7, 7); r = FLD_MOD(r, hsync_pol, 6, 6); - r = FLD_MOD(r, timings->interlace, 3, 3); + r = FLD_MOD(r, !!(timings->flags & DISPLAY_FLAGS_INTERLACED), 3, 3); r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r); } @@ -210,10 +210,10 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, timings->vsync_level = param->timings.vsync_level; timings->hsync_level = param->timings.hsync_level; - timings->interlace = param->timings.interlace; timings->double_pixel = param->timings.double_pixel; + timings->flags = param->timings.flags; - if (param->timings.interlace) { + if (param->timings.flags & DISPLAY_FLAGS_INTERLACED) { video_fmt->y_res /= 2; timings->vback_porch /= 2; timings->vfront_porch /= 2; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index aca9d3028155..23fec72bacac 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -323,8 +323,6 @@ struct omap_video_timings { enum omap_dss_signal_level vsync_level; /* Hsync logic level */ enum omap_dss_signal_level hsync_level; - /* Interlaced or Progressive timings */ - bool interlace; /* Pixel clock edge to drive LCD data */ enum omap_dss_signal_edge data_pclk_edge; /* Data enable logic level */ @@ -333,6 +331,8 @@ struct omap_video_timings { enum omap_dss_signal_edge sync_pclk_edge; bool double_pixel; + + enum display_flags flags; }; /* Hardcoded timings for tv modes. Venc only uses these to diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index cc59e644ea52..d5639a5099c8 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -865,7 +865,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.vfront_porch = 0; rfbi.timings.vback_porch = 0; - rfbi.timings.interlace = false; + rfbi.timings.flags &= ~DISPLAY_FLAGS_INTERLACED; rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 411eea6bc99f..e271c75ef632 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -273,13 +273,13 @@ const struct omap_video_timings omap_dss_pal_timings = { .vfront_porch = 5, .vback_porch = 41, - .interlace = true, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, + + .flags = DISPLAY_FLAGS_INTERLACED, }; EXPORT_SYMBOL(omap_dss_pal_timings); @@ -294,13 +294,13 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .vfront_porch = 6, .vback_porch = 31, - .interlace = true, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, + + .flags = DISPLAY_FLAGS_INTERLACED, }; EXPORT_SYMBOL(omap_dss_ntsc_timings); diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index d6c4dc1c1fcb..5effce40817f 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -59,7 +59,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->flags = 0; - if (timings->interlace) + if (timings->flags & DISPLAY_FLAGS_INTERLACED) mode->flags |= DRM_MODE_FLAG_INTERLACE; if (timings->double_pixel) @@ -91,7 +91,9 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->vsync_len = mode->vsync_end - mode->vsync_start; timings->vback_porch = mode->vtotal - mode->vsync_end; - timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + timings->flags |= DISPLAY_FLAGS_INTERLACED; + timings->double_pixel = !!(mode->flags & DRM_MODE_FLAG_DBLCLK); if (mode->flags & DRM_MODE_FLAG_PHSYNC) -- cgit v1.2.3 From 3b592939b7c02db19a50545834d2eeaa7eff6df6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:56 +0300 Subject: drm/omap: dispc: Simplify _dispc_mgr_set_lcd_timings() parameters Instead of passing the omap_video_timings structure's members individually, use the pointer to the struct. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dispc.c | 38 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index f11bfe5378d1..6a0c13d97cc1 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -3141,29 +3141,23 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, return true; } -static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsync_len, - int hfp, int hbp, int vsw, int vfp, int vbp, - enum omap_dss_signal_level vsync_level, - enum omap_dss_signal_level hsync_level, - enum omap_dss_signal_edge data_pclk_edge, - enum omap_dss_signal_level de_level, - enum omap_dss_signal_edge sync_pclk_edge) - +static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, + const struct omap_video_timings *ovt) { u32 timing_h, timing_v, l; bool onoff, rf, ipc, vs, hs, de; - timing_h = FLD_VAL(hsync_len-1, dispc.feat->sw_start, 0) | - FLD_VAL(hfp-1, dispc.feat->fp_start, 8) | - FLD_VAL(hbp-1, dispc.feat->bp_start, 20); - timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) | - FLD_VAL(vfp, dispc.feat->fp_start, 8) | - FLD_VAL(vbp, dispc.feat->bp_start, 20); + timing_h = FLD_VAL(ovt->hsync_len - 1, dispc.feat->sw_start, 0) | + FLD_VAL(ovt->hfront_porch - 1, dispc.feat->fp_start, 8) | + FLD_VAL(ovt->hback_porch - 1, dispc.feat->bp_start, 20); + timing_v = FLD_VAL(ovt->vsync_len - 1, dispc.feat->sw_start, 0) | + FLD_VAL(ovt->vfront_porch, dispc.feat->fp_start, 8) | + FLD_VAL(ovt->vback_porch, dispc.feat->bp_start, 20); dispc_write_reg(DISPC_TIMING_H(channel), timing_h); dispc_write_reg(DISPC_TIMING_V(channel), timing_v); - switch (vsync_level) { + switch (ovt->vsync_level) { case OMAPDSS_SIG_ACTIVE_LOW: vs = true; break; @@ -3174,7 +3168,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsync_len, BUG(); } - switch (hsync_level) { + switch (ovt->hsync_level) { case OMAPDSS_SIG_ACTIVE_LOW: hs = true; break; @@ -3185,7 +3179,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsync_len, BUG(); } - switch (de_level) { + switch (ovt->de_level) { case OMAPDSS_SIG_ACTIVE_LOW: de = true; break; @@ -3196,7 +3190,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsync_len, BUG(); } - switch (data_pclk_edge) { + switch (ovt->data_pclk_edge) { case OMAPDSS_DRIVE_SIG_RISING_EDGE: ipc = false; break; @@ -3210,7 +3204,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsync_len, /* always use the 'rf' setting */ onoff = true; - switch (sync_pclk_edge) { + switch (ovt->sync_pclk_edge) { case OMAPDSS_DRIVE_SIG_FALLING_EDGE: rf = false; break; @@ -3270,11 +3264,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, } if (dss_mgr_is_lcd(channel)) { - _dispc_mgr_set_lcd_timings(channel, - t.hsync_len, t.hfront_porch, t.hback_porch, - t.vsync_len, t.vfront_porch, t.vback_porch, - t.vsync_level, t.hsync_level, t.data_pclk_edge, - t.de_level, t.sync_pclk_edge); + _dispc_mgr_set_lcd_timings(channel, &t); xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hback_porch; ytot = t.vactive + t.vfront_porch + t.vsync_len + t.vback_porch; -- cgit v1.2.3 From 6b44cd2748d6efa09a83fe97a2d35fb90f80e489 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:57 +0300 Subject: drm/omap: omap_display_timings: Use display_flags for h/vsync level In preparation to move the stack to use the generic videmode struct for display timing information use display_flags for h/vsync level. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- .../gpu/drm/omapdrm/displays/connector-analog-tv.c | 3 +- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 4 +-- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 3 +- .../omapdrm/displays/panel-lgphilips-lb035q02.c | 4 +-- .../drm/omapdrm/displays/panel-nec-nl8048hl11.c | 4 +-- .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 4 +-- .../drm/omapdrm/displays/panel-sony-acx565akm.c | 5 ++-- .../drm/omapdrm/displays/panel-tpo-td028ttec1.c | 5 ++-- .../drm/omapdrm/displays/panel-tpo-td043mtea1.c | 4 +-- drivers/gpu/drm/omapdrm/dss/dispc.c | 33 ++++++++-------------- drivers/gpu/drm/omapdrm/dss/display.c | 18 ++---------- drivers/gpu/drm/omapdrm/dss/dsi.c | 6 ++-- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 4 +-- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 6 ++-- drivers/gpu/drm/omapdrm/dss/omapdss.h | 4 --- drivers/gpu/drm/omapdrm/dss/rfbi.c | 6 ++-- drivers/gpu/drm/omapdrm/dss/venc.c | 10 +++---- drivers/gpu/drm/omapdrm/omap_connector.c | 12 ++++---- 18 files changed, 52 insertions(+), 83 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 0a7491427832..264182f97194 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -40,7 +40,8 @@ static const struct omap_video_timings tvc_pal_timings = { .vfront_porch = 5, .vback_porch = 41, - .flags = DISPLAY_FLAGS_INTERLACED, + .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | + DISPLAY_FLAGS_VSYNC_LOW, }; static const struct of_device_id tvc_of_match[]; diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index adbcd566a7ec..b81c366ba63a 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -33,11 +33,11 @@ static const struct omap_video_timings dvic_default_timings = { .vsync_len = 4, .vback_porch = 7, - .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH, - .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, + + .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 8e246b9142d7..f9809f4eb390 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -32,8 +32,7 @@ static const struct omap_video_timings hdmic_default_timings = { .vfront_porch = 11, .vback_porch = 31, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 9c114da37a6b..999dec6c2cff 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -33,11 +33,11 @@ static struct omap_video_timings lb035q02_timings = { .vfront_porch = 4, .vback_porch = 18, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, + + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index 1e1acc6e06cb..c45eb3520346 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -76,11 +76,11 @@ static const struct omap_video_timings nec_8048_panel_timings = { .vsync_len = 1, .vback_porch = 4, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, + + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index 79cb8bde1cca..a83e6a1b894b 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -49,11 +49,11 @@ static const struct omap_video_timings sharp_ls_timings = { .vfront_porch = 1, .vback_porch = 1, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, + + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 30d689818518..40c882599c96 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -103,12 +103,11 @@ static const struct omap_video_timings acx565akm_panel_timings = { .vsync_len = 3, .vback_porch = 4, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, + + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index a367b615d808..d98a16e8ce4a 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -53,12 +53,11 @@ static struct omap_video_timings td028ttec1_panel_timings = { .vsync_len = 2, .vback_porch = 2, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, + + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, }; #define JBT_COMMAND 0x000 diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 16d24381b270..65eeda51dbef 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -86,11 +86,11 @@ static const struct omap_video_timings tpo_td043_timings = { .vfront_porch = 39, .vback_porch = 34, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, + + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 6a0c13d97cc1..6acdd2194122 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -3157,27 +3157,15 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, dispc_write_reg(DISPC_TIMING_H(channel), timing_h); dispc_write_reg(DISPC_TIMING_V(channel), timing_v); - switch (ovt->vsync_level) { - case OMAPDSS_SIG_ACTIVE_LOW: - vs = true; - break; - case OMAPDSS_SIG_ACTIVE_HIGH: + if (ovt->flags & DISPLAY_FLAGS_VSYNC_HIGH) vs = false; - break; - default: - BUG(); - } + else + vs = true; - switch (ovt->hsync_level) { - case OMAPDSS_SIG_ACTIVE_LOW: - hs = true; - break; - case OMAPDSS_SIG_ACTIVE_HIGH: + if (ovt->flags & DISPLAY_FLAGS_HSYNC_HIGH) hs = false; - break; - default: - BUG(); - } + else + hs = true; switch (ovt->de_level) { case OMAPDSS_SIG_ACTIVE_LOW: @@ -3277,8 +3265,9 @@ void dispc_mgr_set_timings(enum omap_channel channel, t.hsync_len, t.hfront_porch, t.hback_porch, t.vsync_len, t.vfront_porch, t.vback_porch); DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", - t.vsync_level, t.hsync_level, t.data_pclk_edge, - t.de_level, t.sync_pclk_edge); + !!(t.flags & DISPLAY_FLAGS_VSYNC_HIGH), + !!(t.flags & DISPLAY_FLAGS_HSYNC_HIGH), + t.data_pclk_edge, t.de_level, t.sync_pclk_edge); DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); } else { @@ -4220,12 +4209,12 @@ static const struct dispc_errata_i734_data { .pixelclock = 16000000, .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, .vsync_len = 1, .vfront_porch = 1, .vback_porch = 1, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .double_pixel = false, + + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, }, .ovli = { .screen_width = 1, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index d63ea2d5d812..ddb5bbd41dfb 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -232,13 +232,8 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->vback_porch = vm->vback_porch; ovt->vfront_porch = vm->vfront_porch; ovt->vsync_len = vm->vsync_len; + ovt->flags = vm->flags; - ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ? - OMAPDSS_SIG_ACTIVE_HIGH : - OMAPDSS_SIG_ACTIVE_LOW; - ovt->hsync_level = vm->flags & DISPLAY_FLAGS_HSYNC_HIGH ? - OMAPDSS_SIG_ACTIVE_HIGH : - OMAPDSS_SIG_ACTIVE_LOW; ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ? OMAPDSS_SIG_ACTIVE_HIGH : OMAPDSS_SIG_ACTIVE_LOW; @@ -265,16 +260,7 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->vback_porch = ovt->vback_porch; vm->vfront_porch = ovt->vfront_porch; vm->vsync_len = ovt->vsync_len; - - if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) - vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH; - else - vm->flags |= DISPLAY_FLAGS_HSYNC_LOW; - - if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) - vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH; - else - vm->flags |= DISPLAY_FLAGS_VSYNC_LOW; + vm->flags = ovt->flags; if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH) vm->flags |= DISPLAY_FLAGS_DE_HIGH; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 313c8e24ac84..fb47e82e4e98 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4123,8 +4123,10 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, * omap_video_timings with default values */ dsi->timings.flags &= ~DISPLAY_FLAGS_INTERLACED; - dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; - dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + dsi->timings.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; + dsi->timings.flags |= DISPLAY_FLAGS_HSYNC_HIGH; + dsi->timings.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; + dsi->timings.flags |= DISPLAY_FLAGS_VSYNC_HIGH; dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 62268f8d62c6..f64f389939d1 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -333,8 +333,8 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, unsigned char r = 0; bool vsync_pol, hsync_pol; - vsync_pol = ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; - hsync_pol = ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; + vsync_pol = !!(ovt->flags & DISPLAY_FLAGS_VSYNC_HIGH); + hsync_pol = !!(ovt->flags & DISPLAY_FLAGS_HSYNC_HIGH); /* Set hsync, vsync and data-enable polarity */ r = hdmi_read_reg(base, HDMI_CORE_FC_INVIDCONF); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 231f62ed86ff..b86e5a357456 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -150,8 +150,8 @@ void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, bool vsync_pol, hsync_pol; DSSDBG("Enter hdmi_wp_video_config_interface\n"); - vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; - hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; + vsync_pol = !!(timings->flags & DISPLAY_FLAGS_VSYNC_HIGH); + hsync_pol = !!(timings->flags & DISPLAY_FLAGS_HSYNC_HIGH); r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG); r = FLD_MOD(r, vsync_pol, 7, 7); @@ -208,8 +208,6 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, timings->vfront_porch = param->timings.vfront_porch; timings->vsync_len = param->timings.vsync_len; - timings->vsync_level = param->timings.vsync_level; - timings->hsync_level = param->timings.hsync_level; timings->double_pixel = param->timings.double_pixel; timings->flags = param->timings.flags; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 23fec72bacac..23ab45447b0d 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -319,10 +319,6 @@ struct omap_video_timings { /* Unit: line clocks */ u16 vback_porch; /* Vertical back porch */ - /* Vsync logic level */ - enum omap_dss_signal_level vsync_level; - /* Hsync logic level */ - enum omap_dss_signal_level hsync_level; /* Pixel clock edge to drive LCD data */ enum omap_dss_signal_edge data_pclk_edge; /* Data enable logic level */ diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index d5639a5099c8..62f037ebfe6d 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -866,8 +866,10 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.vback_porch = 0; rfbi.timings.flags &= ~DISPLAY_FLAGS_INTERLACED; - rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; - rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + rfbi.timings.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; + rfbi.timings.flags |= DISPLAY_FLAGS_HSYNC_HIGH; + rfbi.timings.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; + rfbi.timings.flags |= DISPLAY_FLAGS_VSYNC_HIGH; rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index e271c75ef632..e80ec809f0c7 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -273,13 +273,12 @@ const struct omap_video_timings omap_dss_pal_timings = { .vfront_porch = 5, .vback_porch = 41, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_INTERLACED, + .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | + DISPLAY_FLAGS_VSYNC_LOW, }; EXPORT_SYMBOL(omap_dss_pal_timings); @@ -294,13 +293,12 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .vfront_porch = 6, .vback_porch = 31, - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_INTERLACED, + .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | + DISPLAY_FLAGS_VSYNC_LOW, }; EXPORT_SYMBOL(omap_dss_ntsc_timings); diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 5effce40817f..695386256d18 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -65,12 +65,12 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, if (timings->double_pixel) mode->flags |= DRM_MODE_FLAG_DBLCLK; - if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + if (timings->flags & DISPLAY_FLAGS_HSYNC_HIGH) mode->flags |= DRM_MODE_FLAG_PHSYNC; else mode->flags |= DRM_MODE_FLAG_NHSYNC; - if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + if (timings->flags & DISPLAY_FLAGS_VSYNC_HIGH) mode->flags |= DRM_MODE_FLAG_PVSYNC; else mode->flags |= DRM_MODE_FLAG_NVSYNC; @@ -97,14 +97,14 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->double_pixel = !!(mode->flags & DRM_MODE_FLAG_DBLCLK); if (mode->flags & DRM_MODE_FLAG_PHSYNC) - timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + timings->flags |= DISPLAY_FLAGS_HSYNC_HIGH; else - timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW; + timings->flags |= DISPLAY_FLAGS_HSYNC_LOW; if (mode->flags & DRM_MODE_FLAG_PVSYNC) - timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + timings->flags |= DISPLAY_FLAGS_VSYNC_HIGH; else - timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW; + timings->flags |= DISPLAY_FLAGS_VSYNC_LOW; timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; -- cgit v1.2.3 From 3fa3ab4a881b9c464cb3168b476825ae5a02bfa6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:58 +0300 Subject: drm/omap: omap_display_timings: Use display_flags for DE level In preparation to move the stack to use the generic videmode struct for display timing information use display_flags for DE level. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 4 ++-- drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c | 2 +- .../drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 4 ++-- .../gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 4 ++-- .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 4 ++-- .../gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 4 ++-- .../gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 4 ++-- .../gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/dispc.c | 19 +++++++------------ drivers/gpu/drm/omapdrm/dss/display.c | 8 -------- drivers/gpu/drm/omapdrm/dss/dsi.c | 3 ++- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 -- drivers/gpu/drm/omapdrm/dss/rfbi.c | 3 ++- drivers/gpu/drm/omapdrm/dss/venc.c | 6 ++---- drivers/gpu/drm/omapdrm/omap_connector.c | 2 +- 15 files changed, 29 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index b81c366ba63a..b94bfca0ecae 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -34,10 +34,10 @@ static const struct omap_video_timings dvic_default_timings = { .vback_porch = 7, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH, + .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH | + DISPLAY_FLAGS_DE_HIGH, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c index d768217cefe0..e3b8dddc90bd 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c @@ -117,7 +117,7 @@ static void tfp410_fix_timings(struct omap_video_timings *timings) { timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; + timings->flags |= DISPLAY_FLAGS_DE_HIGH; } static void tfp410_set_timings(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 999dec6c2cff..7d4c59bf1950 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -34,10 +34,10 @@ static struct omap_video_timings lb035q02_timings = { .vback_porch = 18, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index c45eb3520346..6f7bc89ff9ee 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -77,10 +77,10 @@ static const struct omap_video_timings nec_8048_panel_timings = { .vback_porch = 4, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index a83e6a1b894b..a18dd7160df0 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -50,10 +50,10 @@ static const struct omap_video_timings sharp_ls_timings = { .vback_porch = 1, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 40c882599c96..6aecc24d20bc 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -104,10 +104,10 @@ static const struct omap_video_timings acx565akm_panel_timings = { .vback_porch = 4, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index d98a16e8ce4a..8570ad5aeb55 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -54,10 +54,10 @@ static struct omap_video_timings td028ttec1_panel_timings = { .vback_porch = 2, .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH, }; #define JBT_COMMAND 0x000 diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 65eeda51dbef..03497708c4c9 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -87,10 +87,10 @@ static const struct omap_video_timings tpo_td043_timings = { .vback_porch = 34, .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 6acdd2194122..5f88b7848415 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -3167,16 +3167,10 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, else hs = true; - switch (ovt->de_level) { - case OMAPDSS_SIG_ACTIVE_LOW: - de = true; - break; - case OMAPDSS_SIG_ACTIVE_HIGH: + if (ovt->flags & DISPLAY_FLAGS_DE_HIGH) de = false; - break; - default: - BUG(); - } + else + de = true; switch (ovt->data_pclk_edge) { case OMAPDSS_DRIVE_SIG_RISING_EDGE: @@ -3267,7 +3261,8 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", !!(t.flags & DISPLAY_FLAGS_VSYNC_HIGH), !!(t.flags & DISPLAY_FLAGS_HSYNC_HIGH), - t.data_pclk_edge, t.de_level, t.sync_pclk_edge); + t.data_pclk_edge, !!(t.flags & DISPLAY_FLAGS_DE_HIGH), + t.sync_pclk_edge); DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); } else { @@ -4210,11 +4205,11 @@ static const struct dispc_errata_i734_data { .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, .vsync_len = 1, .vfront_porch = 1, .vback_porch = 1, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .double_pixel = false, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH, }, .ovli = { .screen_width = 1, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index ddb5bbd41dfb..8d2fcb705ae8 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -234,9 +234,6 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->vsync_len = vm->vsync_len; ovt->flags = vm->flags; - ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ? - OMAPDSS_SIG_ACTIVE_HIGH : - OMAPDSS_SIG_ACTIVE_LOW; ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? OMAPDSS_DRIVE_SIG_RISING_EDGE : OMAPDSS_DRIVE_SIG_FALLING_EDGE; @@ -262,11 +259,6 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->vsync_len = ovt->vsync_len; vm->flags = ovt->flags; - if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH) - vm->flags |= DISPLAY_FLAGS_DE_HIGH; - else - vm->flags |= DISPLAY_FLAGS_DE_LOW; - if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE) vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; else diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index fb47e82e4e98..e0532c75acdc 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4128,7 +4128,8 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, dsi->timings.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; dsi->timings.flags |= DISPLAY_FLAGS_VSYNC_HIGH; dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; + dsi->timings.flags &= ~DISPLAY_FLAGS_DE_LOW; + dsi->timings.flags |= DISPLAY_FLAGS_DE_HIGH; dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; dss_mgr_set_timings(channel, &dsi->timings); diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 23ab45447b0d..b1934d55acb1 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -321,8 +321,6 @@ struct omap_video_timings { /* Pixel clock edge to drive LCD data */ enum omap_dss_signal_edge data_pclk_edge; - /* Data enable logic level */ - enum omap_dss_signal_level de_level; /* Pixel clock edges to drive HSYNC and VSYNC signals */ enum omap_dss_signal_edge sync_pclk_edge; diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index 62f037ebfe6d..449d6aafb71f 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -871,7 +871,8 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; rfbi.timings.flags |= DISPLAY_FLAGS_VSYNC_HIGH; rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; + rfbi.timings.flags &= ~DISPLAY_FLAGS_DE_LOW; + rfbi.timings.flags |= DISPLAY_FLAGS_DE_HIGH; rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; dss_mgr_set_timings(mgr, &rfbi.timings); diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index e80ec809f0c7..8657e3c09e32 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -274,11 +274,10 @@ const struct omap_video_timings omap_dss_pal_timings = { .vback_porch = 41, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | - DISPLAY_FLAGS_VSYNC_LOW, + DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH, }; EXPORT_SYMBOL(omap_dss_pal_timings); @@ -294,11 +293,10 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .vback_porch = 31, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | - DISPLAY_FLAGS_VSYNC_LOW, + DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH, }; EXPORT_SYMBOL(omap_dss_ntsc_timings); diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 695386256d18..8817e38761ae 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -107,7 +107,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->flags |= DISPLAY_FLAGS_VSYNC_LOW; timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; + timings->flags |= DISPLAY_FLAGS_DE_HIGH; timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; } -- cgit v1.2.3 From 531efb380c6d11025e1afe8ef7300c26f0f1b226 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:06:59 +0300 Subject: drm/omap: omap_display_timings: Use display_flags for double_pixel mode In preparation to move the stack to use the generic videmode struct for display timing information use display_flags for double_pixel mode. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dispc.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 3 +-- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 -- drivers/gpu/drm/omapdrm/omap_connector.c | 5 +++-- 7 files changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 5f88b7848415..cedec84429f5 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -3270,8 +3270,9 @@ void dispc_mgr_set_timings(enum omap_channel channel, t.vactive /= 2; if (dispc.feat->supports_double_pixel) - REG_FLD_MOD(DISPC_CONTROL, t.double_pixel ? 1 : 0, - 19, 17); + REG_FLD_MOD(DISPC_CONTROL, + !!(t.flags & DISPLAY_FLAGS_DOUBLECLK), + 19, 17); } dispc_mgr_set_size(channel, t.hactive, t.vactive); @@ -4206,7 +4207,6 @@ static const struct dispc_errata_i734_data { .vsync_len = 1, .vfront_porch = 1, .vback_porch = 1, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .double_pixel = false, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 2a5a71a25423..891518502d3d 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -175,7 +175,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) p->vactive); pc = p->pixelclock; - if (p->double_pixel) + if (p->flags & DISPLAY_FLAGS_DOUBLECLK) pc *= 2; /* DSS_HDMI_TCLK is bitclk / 10 */ diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 45f445523a4f..8206ef69caf1 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -187,7 +187,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) p->vactive); pc = p->pixelclock; - if (p->double_pixel) + if (p->flags & DISPLAY_FLAGS_DOUBLECLK) pc *= 2; /* DSS_HDMI_TCLK is bitclk / 10 */ diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index f64f389939d1..e86972b98a91 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -315,7 +315,7 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, video_cfg->v_fc_config.timings.vback_porch /= 2; } - if (cfg->timings.double_pixel) { + if (cfg->timings.flags & DISPLAY_FLAGS_DOUBLECLK) { video_cfg->v_fc_config.timings.hactive *= 2; video_cfg->hblank *= 2; video_cfg->v_fc_config.timings.hfront_porch *= 2; @@ -382,7 +382,7 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF, cfg->v_fc_config.hdmi_dvi_mode, 3, 3); - if (ovt->double_pixel) + if (ovt->flags & DISPLAY_FLAGS_DOUBLECLK) REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 2, 7, 4); else REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 1, 7, 4); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index b86e5a357456..20effa9260ec 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -208,7 +208,6 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, timings->vfront_porch = param->timings.vfront_porch; timings->vsync_len = param->timings.vsync_len; - timings->double_pixel = param->timings.double_pixel; timings->flags = param->timings.flags; if (param->timings.flags & DISPLAY_FLAGS_INTERLACED) { @@ -218,7 +217,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, timings->vsync_len /= 2; } - if (param->timings.double_pixel) { + if (param->timings.flags & DISPLAY_FLAGS_DOUBLECLK) { video_fmt->x_res *= 2; timings->hfront_porch *= 2; timings->hsync_len *= 2; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index b1934d55acb1..342993154d6d 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -324,8 +324,6 @@ struct omap_video_timings { /* Pixel clock edges to drive HSYNC and VSYNC signals */ enum omap_dss_signal_edge sync_pclk_edge; - bool double_pixel; - enum display_flags flags; }; diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 8817e38761ae..f3e9bcf1f784 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -62,7 +62,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, if (timings->flags & DISPLAY_FLAGS_INTERLACED) mode->flags |= DRM_MODE_FLAG_INTERLACE; - if (timings->double_pixel) + if (timings->flags & DISPLAY_FLAGS_DOUBLECLK) mode->flags |= DRM_MODE_FLAG_DBLCLK; if (timings->flags & DISPLAY_FLAGS_HSYNC_HIGH) @@ -94,7 +94,8 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, if (mode->flags & DRM_MODE_FLAG_INTERLACE) timings->flags |= DISPLAY_FLAGS_INTERLACED; - timings->double_pixel = !!(mode->flags & DRM_MODE_FLAG_DBLCLK); + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + timings->flags |= DISPLAY_FLAGS_DOUBLECLK; if (mode->flags & DRM_MODE_FLAG_PHSYNC) timings->flags |= DISPLAY_FLAGS_HSYNC_HIGH; -- cgit v1.2.3 From f149e17a7bf904c55f69e2aef5a0fc5915e40e04 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:00 +0300 Subject: drm/omap: omap_display_timings: Use display_flags for pixel data edge In preparation to move the stack to use the generic videmode struct for display timing information use display_flags for pixel data edge. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 3 +-- drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c | 3 +-- .../gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 3 +-- drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 3 +-- .../gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 3 +-- drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 3 +-- drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 3 +-- drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 3 +-- drivers/gpu/drm/omapdrm/dss/dispc.c | 16 +++++----------- drivers/gpu/drm/omapdrm/dss/display.c | 9 +-------- drivers/gpu/drm/omapdrm/dss/dsi.c | 3 ++- drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 -- drivers/gpu/drm/omapdrm/dss/rfbi.c | 3 ++- drivers/gpu/drm/omapdrm/dss/sdi.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 8 ++++---- drivers/gpu/drm/omapdrm/omap_connector.c | 3 +-- 16 files changed, 24 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index b94bfca0ecae..6f130862db8a 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -33,11 +33,10 @@ static const struct omap_video_timings dvic_default_timings = { .vsync_len = 4, .vback_porch = 7, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH | - DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c index e3b8dddc90bd..eec079e017f0 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c @@ -115,9 +115,8 @@ static void tfp410_disable(struct omap_dss_device *dssdev) static void tfp410_fix_timings(struct omap_video_timings *timings) { - timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - timings->flags |= DISPLAY_FLAGS_DE_HIGH; + timings->flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE; } static void tfp410_set_timings(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 7d4c59bf1950..33cdc107ed21 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -33,11 +33,10 @@ static struct omap_video_timings lb035q02_timings = { .vfront_porch = 4, .vback_porch = 18, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index 6f7bc89ff9ee..64f6f42dbe92 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -76,11 +76,10 @@ static const struct omap_video_timings nec_8048_panel_timings = { .vsync_len = 1, .vback_porch = 4, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index a18dd7160df0..fb7e032209bd 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -49,11 +49,10 @@ static const struct omap_video_timings sharp_ls_timings = { .vfront_porch = 1, .vback_porch = 1, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 6aecc24d20bc..599908958066 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -103,11 +103,10 @@ static const struct omap_video_timings acx565akm_panel_timings = { .vsync_len = 3, .vback_porch = 4, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 8570ad5aeb55..717b4577ac49 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -53,11 +53,10 @@ static struct omap_video_timings td028ttec1_panel_timings = { .vsync_len = 2, .vback_porch = 2, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE, }; #define JBT_COMMAND 0x000 diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 03497708c4c9..71fa7aabd062 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -86,11 +86,10 @@ static const struct omap_video_timings tpo_td043_timings = { .vfront_porch = 39, .vback_porch = 34, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index cedec84429f5..6b017e1f9245 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -3172,16 +3172,10 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, else de = true; - switch (ovt->data_pclk_edge) { - case OMAPDSS_DRIVE_SIG_RISING_EDGE: + if (ovt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) ipc = false; - break; - case OMAPDSS_DRIVE_SIG_FALLING_EDGE: + else ipc = true; - break; - default: - BUG(); - } /* always use the 'rf' setting */ onoff = true; @@ -3261,7 +3255,8 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", !!(t.flags & DISPLAY_FLAGS_VSYNC_HIGH), !!(t.flags & DISPLAY_FLAGS_HSYNC_HIGH), - t.data_pclk_edge, !!(t.flags & DISPLAY_FLAGS_DE_HIGH), + !!(t.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE), + !!(t.flags & DISPLAY_FLAGS_DE_HIGH), t.sync_pclk_edge); DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); @@ -4205,11 +4200,10 @@ static const struct dispc_errata_i734_data { .pixelclock = 16000000, .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, .vsync_len = 1, .vfront_porch = 1, .vback_porch = 1, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, }, .ovli = { .screen_width = 1, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 8d2fcb705ae8..1cd503cc95fe 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -234,11 +234,9 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->vsync_len = vm->vsync_len; ovt->flags = vm->flags; - ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? + ovt->sync_pclk_edge = ovt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? OMAPDSS_DRIVE_SIG_RISING_EDGE : OMAPDSS_DRIVE_SIG_FALLING_EDGE; - - ovt->sync_pclk_edge = ovt->data_pclk_edge; } EXPORT_SYMBOL(videomode_to_omap_video_timings); @@ -258,10 +256,5 @@ void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, vm->vfront_porch = ovt->vfront_porch; vm->vsync_len = ovt->vsync_len; vm->flags = ovt->flags; - - if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE) - vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; - else - vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE; } EXPORT_SYMBOL(omap_video_timings_to_videomode); diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index e0532c75acdc..ba3a2da7c80d 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4127,7 +4127,8 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, dsi->timings.flags |= DISPLAY_FLAGS_HSYNC_HIGH; dsi->timings.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; dsi->timings.flags |= DISPLAY_FLAGS_VSYNC_HIGH; - dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + dsi->timings.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; + dsi->timings.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; dsi->timings.flags &= ~DISPLAY_FLAGS_DE_LOW; dsi->timings.flags |= DISPLAY_FLAGS_DE_HIGH; dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 342993154d6d..1bc186110106 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -319,8 +319,6 @@ struct omap_video_timings { /* Unit: line clocks */ u16 vback_porch; /* Vertical back porch */ - /* Pixel clock edge to drive LCD data */ - enum omap_dss_signal_edge data_pclk_edge; /* Pixel clock edges to drive HSYNC and VSYNC signals */ enum omap_dss_signal_edge sync_pclk_edge; diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index 449d6aafb71f..7a9598e93bc9 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -870,7 +870,8 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.flags |= DISPLAY_FLAGS_HSYNC_HIGH; rfbi.timings.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; rfbi.timings.flags |= DISPLAY_FLAGS_VSYNC_HIGH; - rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + rfbi.timings.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; + rfbi.timings.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; rfbi.timings.flags &= ~DISPLAY_FLAGS_DE_LOW; rfbi.timings.flags |= DISPLAY_FLAGS_DE_HIGH; rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index 0a96c321ce62..a886f9051b33 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c @@ -151,7 +151,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) goto err_get_dispc; /* 15.5.9.1.2 */ - t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + t->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo); diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 8657e3c09e32..82d0cda9a499 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -273,11 +273,11 @@ const struct omap_video_timings omap_dss_pal_timings = { .vfront_porch = 5, .vback_porch = 41, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | - DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | + DISPLAY_FLAGS_PIXDATA_POSEDGE, }; EXPORT_SYMBOL(omap_dss_pal_timings); @@ -292,11 +292,11 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .vfront_porch = 6, .vback_porch = 31, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | - DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH, + DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | + DISPLAY_FLAGS_PIXDATA_POSEDGE, }; EXPORT_SYMBOL(omap_dss_ntsc_timings); diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index f3e9bcf1f784..5fa15da78a8c 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -107,8 +107,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, else timings->flags |= DISPLAY_FLAGS_VSYNC_LOW; - timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - timings->flags |= DISPLAY_FLAGS_DE_HIGH; + timings->flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE; timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; } -- cgit v1.2.3 From d34afb73c3e8906e558c272229e78c8b265196ba Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:01 +0300 Subject: drm/omap: omap_display_timings: Use display_flags for sync edge In preparation to move the stack to use the generic videmode struct for display timing information use display_flags for sync edge. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 5 ++--- drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c | 5 +++-- .../drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 5 ++--- .../gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c | 5 ++--- .../gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 5 ++--- .../gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 5 ++--- .../gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 5 ++--- .../gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 5 ++--- drivers/gpu/drm/omapdrm/dss/dispc.c | 18 ++++++------------ drivers/gpu/drm/omapdrm/dss/display.c | 4 ---- drivers/gpu/drm/omapdrm/dss/dsi.c | 3 ++- drivers/gpu/drm/omapdrm/dss/omapdss.h | 3 --- drivers/gpu/drm/omapdrm/dss/rfbi.c | 3 ++- drivers/gpu/drm/omapdrm/dss/sdi.c | 3 +-- drivers/gpu/drm/omapdrm/dss/venc.c | 10 ++++------ drivers/gpu/drm/omapdrm/omap_connector.c | 5 +++-- 16 files changed, 35 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index 6f130862db8a..53967a4a96a7 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -33,10 +33,9 @@ static const struct omap_video_timings dvic_default_timings = { .vsync_len = 4, .vback_porch = 7, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH | - DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, + DISPLAY_FLAGS_SYNC_NEGEDGE | DISPLAY_FLAGS_DE_HIGH | + DISPLAY_FLAGS_PIXDATA_POSEDGE, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c index eec079e017f0..69b4feab964c 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c @@ -115,8 +115,9 @@ static void tfp410_disable(struct omap_dss_device *dssdev) static void tfp410_fix_timings(struct omap_video_timings *timings) { - timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - timings->flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE; + timings->flags |= DISPLAY_FLAGS_DE_HIGH | + DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_POSEDGE; } static void tfp410_set_timings(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 33cdc107ed21..4328d6781228 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -33,10 +33,9 @@ static struct omap_video_timings lb035q02_timings = { .vfront_porch = 4, .vback_porch = 18, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE | + DISPLAY_FLAGS_PIXDATA_POSEDGE, }; struct panel_drv_data { diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index 64f6f42dbe92..58f39f588c62 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -76,10 +76,9 @@ static const struct omap_video_timings nec_8048_panel_timings = { .vsync_len = 1, .vback_porch = 4, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE | + DISPLAY_FLAGS_PIXDATA_POSEDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index fb7e032209bd..d41ba3152859 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -49,10 +49,9 @@ static const struct omap_video_timings sharp_ls_timings = { .vfront_porch = 1, .vback_porch = 1, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE | + DISPLAY_FLAGS_PIXDATA_POSEDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 599908958066..1e0980635113 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -103,10 +103,9 @@ static const struct omap_video_timings acx565akm_panel_timings = { .vsync_len = 3, .vback_porch = 4, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE | + DISPLAY_FLAGS_PIXDATA_POSEDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 717b4577ac49..9711ec469f39 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -53,10 +53,9 @@ static struct omap_video_timings td028ttec1_panel_timings = { .vsync_len = 2, .vback_porch = 2, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE | + DISPLAY_FLAGS_PIXDATA_NEGEDGE, }; #define JBT_COMMAND 0x000 diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 71fa7aabd062..3f701686f992 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -86,10 +86,9 @@ static const struct omap_video_timings tpo_td043_timings = { .vfront_porch = 39, .vback_porch = 34, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE | + DISPLAY_FLAGS_PIXDATA_NEGEDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 6b017e1f9245..83b7a7a2a9e7 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -3180,16 +3180,10 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, /* always use the 'rf' setting */ onoff = true; - switch (ovt->sync_pclk_edge) { - case OMAPDSS_DRIVE_SIG_FALLING_EDGE: - rf = false; - break; - case OMAPDSS_DRIVE_SIG_RISING_EDGE: + if (ovt->flags & DISPLAY_FLAGS_SYNC_POSEDGE) rf = true; - break; - default: - BUG(); - } + else + rf = false; l = FLD_VAL(onoff, 17, 17) | FLD_VAL(rf, 16, 16) | @@ -3257,7 +3251,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, !!(t.flags & DISPLAY_FLAGS_HSYNC_HIGH), !!(t.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE), !!(t.flags & DISPLAY_FLAGS_DE_HIGH), - t.sync_pclk_edge); + !!(t.flags & DISPLAY_FLAGS_SYNC_POSEDGE)); DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); } else { @@ -4200,10 +4194,10 @@ static const struct dispc_errata_i734_data { .pixelclock = 16000000, .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, .vsync_len = 1, .vfront_porch = 1, .vback_porch = 1, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | - DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE | + DISPLAY_FLAGS_PIXDATA_POSEDGE, }, .ovli = { .screen_width = 1, diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 1cd503cc95fe..1e19a2c00f8f 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -233,10 +233,6 @@ void videomode_to_omap_video_timings(const struct videomode *vm, ovt->vfront_porch = vm->vfront_porch; ovt->vsync_len = vm->vsync_len; ovt->flags = vm->flags; - - ovt->sync_pclk_edge = ovt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? - OMAPDSS_DRIVE_SIG_RISING_EDGE : - OMAPDSS_DRIVE_SIG_FALLING_EDGE; } EXPORT_SYMBOL(videomode_to_omap_video_timings); diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index ba3a2da7c80d..1dec7dd38029 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4131,7 +4131,8 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, dsi->timings.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; dsi->timings.flags &= ~DISPLAY_FLAGS_DE_LOW; dsi->timings.flags |= DISPLAY_FLAGS_DE_HIGH; - dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; + dsi->timings.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; + dsi->timings.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; dss_mgr_set_timings(channel, &dsi->timings); diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 1bc186110106..84d34242d5a4 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -319,9 +319,6 @@ struct omap_video_timings { /* Unit: line clocks */ u16 vback_porch; /* Vertical back porch */ - /* Pixel clock edges to drive HSYNC and VSYNC signals */ - enum omap_dss_signal_edge sync_pclk_edge; - enum display_flags flags; }; diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index 7a9598e93bc9..ce431817e781 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -874,7 +874,8 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; rfbi.timings.flags &= ~DISPLAY_FLAGS_DE_LOW; rfbi.timings.flags |= DISPLAY_FLAGS_DE_HIGH; - rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; + rfbi.timings.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; + rfbi.timings.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; dss_mgr_set_timings(mgr, &rfbi.timings); } diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index a886f9051b33..3b076329a3ac 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c @@ -151,8 +151,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) goto err_get_dispc; /* 15.5.9.1.2 */ - t->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; - t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + t->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_POSEDGE; r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo); if (r) diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 82d0cda9a499..43f98547e9fc 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -273,11 +273,10 @@ const struct omap_video_timings omap_dss_pal_timings = { .vfront_porch = 5, .vback_porch = 41, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | - DISPLAY_FLAGS_PIXDATA_POSEDGE, + DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_NEGEDGE, }; EXPORT_SYMBOL(omap_dss_pal_timings); @@ -292,11 +291,10 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .vfront_porch = 6, .vback_porch = 31, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, - .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | - DISPLAY_FLAGS_PIXDATA_POSEDGE, + DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_NEGEDGE, }; EXPORT_SYMBOL(omap_dss_ntsc_timings); diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 5fa15da78a8c..562a04d49939 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -107,8 +107,9 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, else timings->flags |= DISPLAY_FLAGS_VSYNC_LOW; - timings->flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE; - timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; + timings->flags |= DISPLAY_FLAGS_DE_HIGH | + DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_NEGEDGE; } static enum drm_connector_status omap_connector_detect( -- cgit v1.2.3 From 7aa91e76aec9dda35ae643c572a8d1b1d596d27b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:02 +0300 Subject: drm/omap: Change the types of struct omap_video_timings members omap_video_timings struct have the same members as struct videomode, but their types are different. As first step change the types of the omap_video_timings struct members to match their counterpart in struct videomode to catch any type cast related issues. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 2 +- drivers/gpu/drm/omapdrm/dss/dispc.c | 5 +++-- drivers/gpu/drm/omapdrm/dss/dpi.c | 2 +- drivers/gpu/drm/omapdrm/dss/omapdss.h | 18 +++++++++--------- drivers/gpu/drm/omapdrm/dss/sdi.c | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c index c3d2a12358fa..8f676b8ac038 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c @@ -1023,7 +1023,7 @@ static int dsicm_memory_read(struct omap_dss_device *dssdev, goto err1; } - size = min(w * h * 3, + size = min((u32)w * h * 3, dssdev->panel.timings.hactive * dssdev->panel.timings.vactive * 3); diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 83b7a7a2a9e7..63d3dc44913c 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2870,7 +2870,8 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, int wbdelay; wbdelay = min(mgr_timings->vfront_porch + - mgr_timings->vsync_len + mgr_timings->vback_porch, 255); + mgr_timings->vsync_len + mgr_timings->vback_porch, + (u32)255); /* WBDELAYCOUNT */ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0); @@ -3242,7 +3243,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, ht = timings->pixelclock / xtot; vt = timings->pixelclock / xtot / ytot; - DSSDBG("pck %u\n", timings->pixelclock); + DSSDBG("pck %lu\n", timings->pixelclock); DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", t.hsync_len, t.hfront_porch, t.hback_porch, t.vsync_len, t.vfront_porch, t.vback_porch); diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index d653f492cbfd..8fb40efa65af 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c @@ -351,7 +351,7 @@ static int dpi_set_mode(struct dpi_data *dpi) pck = fck / lck_div / pck_div; if (pck != t->pixelclock) { - DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n", + DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n", t->pixelclock, pck); t->pixelclock = pck; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 84d34242d5a4..bd38da3af01f 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -301,23 +301,23 @@ struct omap_dss_dsi_config { struct omap_video_timings { /* Unit: pixels */ - u16 hactive; + u32 hactive; /* Unit: pixels */ - u16 vactive; + u32 vactive; /* Unit: Hz */ - u32 pixelclock; + unsigned long pixelclock; /* Unit: pixel clocks */ - u16 hsync_len; /* Horizontal synchronization pulse width */ + u32 hsync_len; /* Horizontal synchronization pulse width */ /* Unit: pixel clocks */ - u16 hfront_porch; /* Horizontal front porch */ + u32 hfront_porch; /* Horizontal front porch */ /* Unit: pixel clocks */ - u16 hback_porch; /* Horizontal back porch */ + u32 hback_porch; /* Horizontal back porch */ /* Unit: line clocks */ - u16 vsync_len; /* Vertical synchronization pulse width */ + u32 vsync_len; /* Vertical synchronization pulse width */ /* Unit: line clocks */ - u16 vfront_porch; /* Vertical front porch */ + u32 vfront_porch; /* Vertical front porch */ /* Unit: line clocks */ - u16 vback_porch; /* Vertical back porch */ + u32 vback_porch; /* Vertical back porch */ enum display_flags flags; }; diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index 3b076329a3ac..c8658f97ab7d 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c @@ -162,7 +162,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div; if (pck != t->pixelclock) { - DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n", + DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n", t->pixelclock, pck); t->pixelclock = pck; -- cgit v1.2.3 From 4520ff28aaa1e7f1b45f3abc0c45429ea9e93817 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:03 +0300 Subject: drm/omap: Replace struct omap_video_timings with videomode omap_video_timings can be replaced with the generic videomode in omapdrm and the omap_video_timings can be removed. This patch will replace the omap_video_timings with videomode. With the change we no longer need the functions to convert to/from videomode and drm_display_mode to omap_video_timings, these can be removed as well. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- .../gpu/drm/omapdrm/displays/connector-analog-tv.c | 10 +-- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 10 +-- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 10 +-- drivers/gpu/drm/omapdrm/displays/encoder-opa362.c | 8 +-- drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c | 10 +-- .../gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 8 +-- drivers/gpu/drm/omapdrm/displays/panel-dpi.c | 16 ++--- drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 2 +- .../omapdrm/displays/panel-lgphilips-lb035q02.c | 10 +-- .../drm/omapdrm/displays/panel-nec-nl8048hl11.c | 10 +-- .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 10 +-- .../drm/omapdrm/displays/panel-sony-acx565akm.c | 10 +-- .../drm/omapdrm/displays/panel-tpo-td028ttec1.c | 10 +-- .../drm/omapdrm/displays/panel-tpo-td043mtea1.c | 10 +-- drivers/gpu/drm/omapdrm/dss/dispc.c | 30 ++++---- drivers/gpu/drm/omapdrm/dss/display.c | 39 +--------- drivers/gpu/drm/omapdrm/dss/dpi.c | 10 +-- drivers/gpu/drm/omapdrm/dss/dsi.c | 24 +++---- drivers/gpu/drm/omapdrm/dss/dss.h | 4 +- drivers/gpu/drm/omapdrm/dss/hdmi.h | 8 +-- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 8 +-- drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 8 +-- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 4 +- drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 6 +- drivers/gpu/drm/omapdrm/dss/omapdss.h | 82 +++++++-------------- drivers/gpu/drm/omapdrm/dss/output.c | 2 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 2 +- drivers/gpu/drm/omapdrm/dss/sdi.c | 10 +-- drivers/gpu/drm/omapdrm/dss/venc.c | 14 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 84 +++------------------- drivers/gpu/drm/omapdrm/omap_crtc.c | 11 +-- drivers/gpu/drm/omapdrm/omap_drv.h | 7 +- drivers/gpu/drm/omapdrm/omap_encoder.c | 6 +- 34 files changed, 178 insertions(+), 317 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 264182f97194..53a4e6942616 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -24,12 +24,12 @@ struct panel_drv_data { struct device *dev; - struct omap_video_timings timings; + struct videomode timings; bool invert_polarity; }; -static const struct omap_video_timings tvc_pal_timings = { +static const struct videomode tvc_pal_timings = { .hactive = 720, .vactive = 574, .pixelclock = 13500000, @@ -127,7 +127,7 @@ static void tvc_disable(struct omap_dss_device *dssdev) } static void tvc_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -139,7 +139,7 @@ static void tvc_set_timings(struct omap_dss_device *dssdev, } static void tvc_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -147,7 +147,7 @@ static void tvc_get_timings(struct omap_dss_device *dssdev, } static int tvc_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index 53967a4a96a7..f4f8bf07f38b 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -19,7 +19,7 @@ #include "../dss/omapdss.h" -static const struct omap_video_timings dvic_default_timings = { +static const struct videomode dvic_default_timings = { .hactive = 640, .vactive = 480, @@ -42,7 +42,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - struct omap_video_timings timings; + struct videomode timings; struct i2c_adapter *i2c_adapter; }; @@ -113,7 +113,7 @@ static void dvic_disable(struct omap_dss_device *dssdev) } static void dvic_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -125,7 +125,7 @@ static void dvic_set_timings(struct omap_dss_device *dssdev, } static void dvic_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -133,7 +133,7 @@ static void dvic_get_timings(struct omap_dss_device *dssdev, } static int dvic_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index f9809f4eb390..4f77e03abd43 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -21,7 +21,7 @@ #include "../dss/omapdss.h" -static const struct omap_video_timings hdmic_default_timings = { +static const struct videomode hdmic_default_timings = { .hactive = 640, .vactive = 480, .pixelclock = 25175000, @@ -41,7 +41,7 @@ struct panel_drv_data { struct device *dev; - struct omap_video_timings timings; + struct videomode timings; int hpd_gpio; }; @@ -120,7 +120,7 @@ static void hdmic_disable(struct omap_dss_device *dssdev) } static void hdmic_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -132,7 +132,7 @@ static void hdmic_set_timings(struct omap_dss_device *dssdev, } static void hdmic_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -140,7 +140,7 @@ static void hdmic_get_timings(struct omap_dss_device *dssdev, } static int hdmic_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c index fe4e7ec3bab0..e997128343c1 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c @@ -27,7 +27,7 @@ struct panel_drv_data { struct gpio_desc *enable_gpio; - struct omap_video_timings timings; + struct videomode timings; }; #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -123,7 +123,7 @@ static void opa362_disable(struct omap_dss_device *dssdev) } static void opa362_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -137,7 +137,7 @@ static void opa362_set_timings(struct omap_dss_device *dssdev, } static void opa362_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -147,7 +147,7 @@ static void opa362_get_timings(struct omap_dss_device *dssdev, } static int opa362_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c index 69b4feab964c..96f0e7e7f889 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c @@ -24,7 +24,7 @@ struct panel_drv_data { int pd_gpio; int data_lines; - struct omap_video_timings timings; + struct videomode timings; }; #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -113,7 +113,7 @@ static void tfp410_disable(struct omap_dss_device *dssdev) dssdev->state = OMAP_DSS_DISPLAY_DISABLED; } -static void tfp410_fix_timings(struct omap_video_timings *timings) +static void tfp410_fix_timings(struct videomode *timings) { timings->flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | @@ -121,7 +121,7 @@ static void tfp410_fix_timings(struct omap_video_timings *timings) } static void tfp410_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -135,7 +135,7 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev, } static void tfp410_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -143,7 +143,7 @@ static void tfp410_get_timings(struct omap_dss_device *dssdev, } static int tfp410_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c index 46855c8f5cbf..f4608c5a9e93 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c @@ -26,7 +26,7 @@ struct panel_drv_data { struct gpio_desc *ls_oe_gpio; struct gpio_desc *hpd_gpio; - struct omap_video_timings timings; + struct videomode timings; }; #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -105,7 +105,7 @@ static void tpd_disable(struct omap_dss_device *dssdev) } static void tpd_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -117,7 +117,7 @@ static void tpd_set_timings(struct omap_dss_device *dssdev, } static void tpd_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -125,7 +125,7 @@ static void tpd_get_timings(struct omap_dss_device *dssdev, } static int tpd_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c index 7f16f985ab22..50359b3d9db2 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c @@ -28,7 +28,7 @@ struct panel_drv_data { int data_lines; - struct omap_video_timings videomode; + struct videomode videomode; /* used for non-DT boot, to be removed */ int backlight_gpio; @@ -122,7 +122,7 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev) } static void panel_dpi_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -134,7 +134,7 @@ static void panel_dpi_set_timings(struct omap_dss_device *dssdev, } static void panel_dpi_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -142,7 +142,7 @@ static void panel_dpi_get_timings(struct omap_dss_device *dssdev, } static int panel_dpi_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -169,7 +169,6 @@ static int panel_dpi_probe_pdata(struct platform_device *pdev) const struct panel_dpi_platform_data *pdata; struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct omap_dss_device *dssdev, *in; - struct videomode vm; int r; pdata = dev_get_platdata(&pdev->dev); @@ -185,8 +184,7 @@ static int panel_dpi_probe_pdata(struct platform_device *pdev) ddata->data_lines = pdata->data_lines; - videomode_from_timing(pdata->display_timing, &vm); - videomode_to_omap_video_timings(&vm, &ddata->videomode); + videomode_from_timing(pdata->display_timing, &ddata->videomode); dssdev = &ddata->dssdev; dssdev->name = pdata->name; @@ -214,7 +212,6 @@ static int panel_dpi_probe_of(struct platform_device *pdev) struct omap_dss_device *in; int r; struct display_timing timing; - struct videomode vm; struct gpio_desc *gpio; gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW); @@ -245,8 +242,7 @@ static int panel_dpi_probe_of(struct platform_device *pdev) return r; } - videomode_from_timing(&timing, &vm); - videomode_to_omap_video_timings(&vm, &ddata->videomode); + videomode_from_timing(&timing, &ddata->videomode); in = omapdss_of_find_source_for_first_ep(node); if (IS_ERR(in)) { diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c index 8f676b8ac038..10a2a69ced2a 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c @@ -42,7 +42,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - struct omap_video_timings timings; + struct videomode timings; struct platform_device *pdev; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 4328d6781228..3559efd6170d 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -19,7 +19,7 @@ #include "../dss/omapdss.h" -static struct omap_video_timings lb035q02_timings = { +static struct videomode lb035q02_timings = { .hactive = 320, .vactive = 240, @@ -46,7 +46,7 @@ struct panel_drv_data { int data_lines; - struct omap_video_timings videomode; + struct videomode videomode; struct gpio_desc *enable_gpio; }; @@ -187,7 +187,7 @@ static void lb035q02_disable(struct omap_dss_device *dssdev) } static void lb035q02_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -199,7 +199,7 @@ static void lb035q02_set_timings(struct omap_dss_device *dssdev, } static void lb035q02_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -207,7 +207,7 @@ static void lb035q02_get_timings(struct omap_dss_device *dssdev, } static int lb035q02_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index 58f39f588c62..5e1e3a02c32b 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -23,7 +23,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - struct omap_video_timings videomode; + struct videomode videomode; int data_lines; @@ -65,7 +65,7 @@ static const struct { { 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 }, }; -static const struct omap_video_timings nec_8048_panel_timings = { +static const struct videomode nec_8048_panel_timings = { .hactive = LCD_XRES, .vactive = LCD_YRES, .pixelclock = LCD_PIXEL_CLOCK, @@ -186,7 +186,7 @@ static void nec_8048_disable(struct omap_dss_device *dssdev) } static void nec_8048_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -198,7 +198,7 @@ static void nec_8048_set_timings(struct omap_dss_device *dssdev, } static void nec_8048_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -206,7 +206,7 @@ static void nec_8048_get_timings(struct omap_dss_device *dssdev, } static int nec_8048_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index d41ba3152859..0aac8aa0f685 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -26,7 +26,7 @@ struct panel_drv_data { int data_lines; - struct omap_video_timings videomode; + struct videomode videomode; struct gpio_desc *resb_gpio; /* low = reset active min 20 us */ struct gpio_desc *ini_gpio; /* high = power on */ @@ -35,7 +35,7 @@ struct panel_drv_data { struct gpio_desc *ud_gpio; /* high = conventional vertical scanning */ }; -static const struct omap_video_timings sharp_ls_timings = { +static const struct videomode sharp_ls_timings = { .hactive = 480, .vactive = 640, @@ -152,7 +152,7 @@ static void sharp_ls_disable(struct omap_dss_device *dssdev) } static void sharp_ls_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -164,7 +164,7 @@ static void sharp_ls_set_timings(struct omap_dss_device *dssdev, } static void sharp_ls_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -172,7 +172,7 @@ static void sharp_ls_get_timings(struct omap_dss_device *dssdev, } static int sharp_ls_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 1e0980635113..e83e12724ff5 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -71,7 +71,7 @@ struct panel_drv_data { int reset_gpio; int datapairs; - struct omap_video_timings videomode; + struct videomode videomode; char *name; int enabled; @@ -92,7 +92,7 @@ struct panel_drv_data { struct backlight_device *bl_dev; }; -static const struct omap_video_timings acx565akm_panel_timings = { +static const struct videomode acx565akm_panel_timings = { .hactive = 800, .vactive = 480, .pixelclock = 24000000, @@ -659,7 +659,7 @@ static void acx565akm_disable(struct omap_dss_device *dssdev) } static void acx565akm_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -671,7 +671,7 @@ static void acx565akm_set_timings(struct omap_dss_device *dssdev, } static void acx565akm_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -679,7 +679,7 @@ static void acx565akm_get_timings(struct omap_dss_device *dssdev, } static int acx565akm_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 9711ec469f39..2b38867e17a5 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -37,12 +37,12 @@ struct panel_drv_data { int data_lines; - struct omap_video_timings videomode; + struct videomode videomode; struct spi_device *spi_dev; }; -static struct omap_video_timings td028ttec1_panel_timings = { +static struct videomode td028ttec1_panel_timings = { .hactive = 480, .vactive = 640, .pixelclock = 22153000, @@ -322,7 +322,7 @@ static void td028ttec1_panel_disable(struct omap_dss_device *dssdev) } static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -334,7 +334,7 @@ static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev, } static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -342,7 +342,7 @@ static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev, } static int td028ttec1_panel_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index 3f701686f992..da7b75751c71 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -56,7 +56,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - struct omap_video_timings videomode; + struct videomode videomode; int data_lines; @@ -72,7 +72,7 @@ struct panel_drv_data { u32 power_on_resume:1; }; -static const struct omap_video_timings tpo_td043_timings = { +static const struct videomode tpo_td043_timings = { .hactive = 800, .vactive = 480, @@ -416,7 +416,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev) } static void tpo_td043_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; @@ -428,7 +428,7 @@ static void tpo_td043_set_timings(struct omap_dss_device *dssdev, } static void tpo_td043_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -436,7 +436,7 @@ static void tpo_td043_get_timings(struct omap_dss_device *dssdev, } static int tpo_td043_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 63d3dc44913c..a5b7488a5cfb 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -75,7 +75,7 @@ struct dispc_features { unsigned long max_lcd_pclk; unsigned long max_tv_pclk; int (*calc_scaling) (unsigned long pclk, unsigned long lclk, - const struct omap_video_timings *mgr_timings, + const struct videomode *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, @@ -2179,7 +2179,7 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width, * undocumented horizontal position and timing related limitations. */ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, - const struct omap_video_timings *t, u16 pos_x, + const struct videomode *t, u16 pos_x, u16 width, u16 height, u16 out_width, u16 out_height, bool five_taps) { @@ -2233,7 +2233,7 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, } static unsigned long calc_core_clk_five_taps(unsigned long pclk, - const struct omap_video_timings *mgr_timings, u16 width, + const struct videomode *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode) { @@ -2326,7 +2326,7 @@ static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width, } static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, - const struct omap_video_timings *mgr_timings, + const struct videomode *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, @@ -2372,7 +2372,7 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, } static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, - const struct omap_video_timings *mgr_timings, + const struct videomode *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, @@ -2457,7 +2457,7 @@ again: } static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, - const struct omap_video_timings *mgr_timings, + const struct videomode *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, @@ -2503,7 +2503,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, enum omap_overlay_caps caps, - const struct omap_video_timings *mgr_timings, + const struct videomode *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, u16 pos_x, @@ -2593,7 +2593,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, u16 out_width, u16 out_height, enum omap_color_mode color_mode, u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha, u8 global_alpha, enum omap_dss_rotation_type rotation_type, - bool replication, const struct omap_video_timings *mgr_timings, + bool replication, const struct videomode *mgr_timings, bool mem_to_mem) { bool five_taps = true; @@ -2786,7 +2786,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, } int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, - bool replication, const struct omap_video_timings *mgr_timings, + bool replication, const struct videomode *mgr_timings, bool mem_to_mem) { int r; @@ -2812,7 +2812,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, EXPORT_SYMBOL(dispc_ovl_setup); int dispc_wb_setup(const struct omap_dss_writeback_info *wi, - bool mem_to_mem, const struct omap_video_timings *mgr_timings) + bool mem_to_mem, const struct videomode *mgr_timings) { int r; u32 l; @@ -3119,7 +3119,7 @@ static bool _dispc_mgr_pclk_ok(enum omap_channel channel, } bool dispc_mgr_timings_ok(enum omap_channel channel, - const struct omap_video_timings *timings) + const struct videomode *timings) { if (!_dispc_mgr_size_ok(timings->hactive, timings->vactive)) return false; @@ -3143,7 +3143,7 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, } static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, - const struct omap_video_timings *ovt) + const struct videomode *ovt) { u32 timing_h, timing_v, l; bool onoff, rf, ipc, vs, hs, de; @@ -3221,11 +3221,11 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, /* change name to mode? */ void dispc_mgr_set_timings(enum omap_channel channel, - const struct omap_video_timings *timings) + const struct videomode *timings) { unsigned xtot, ytot; unsigned long ht, vt; - struct omap_video_timings t = *timings; + struct videomode t = *timings; DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.vactive); @@ -4185,7 +4185,7 @@ EXPORT_SYMBOL(dispc_free_irq); */ static const struct dispc_errata_i734_data { - struct omap_video_timings timings; + struct videomode timings; struct omap_overlay_info ovli; struct omap_overlay_manager_info mgri; struct dss_lcd_mgr_config lcd_conf; diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 1e19a2c00f8f..56cc071b6223 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -72,7 +72,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); void omapdss_default_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { *timings = dssdev->panel.timings; } @@ -217,40 +217,3 @@ struct omap_dss_device *omap_dss_find_device(void *data, return NULL; } EXPORT_SYMBOL(omap_dss_find_device); - -void videomode_to_omap_video_timings(const struct videomode *vm, - struct omap_video_timings *ovt) -{ - memset(ovt, 0, sizeof(*ovt)); - - ovt->pixelclock = vm->pixelclock; - ovt->hactive = vm->hactive; - ovt->hback_porch = vm->hback_porch; - ovt->hfront_porch = vm->hfront_porch; - ovt->hsync_len = vm->hsync_len; - ovt->vactive = vm->vactive; - ovt->vback_porch = vm->vback_porch; - ovt->vfront_porch = vm->vfront_porch; - ovt->vsync_len = vm->vsync_len; - ovt->flags = vm->flags; -} -EXPORT_SYMBOL(videomode_to_omap_video_timings); - -void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, - struct videomode *vm) -{ - memset(vm, 0, sizeof(*vm)); - - vm->pixelclock = ovt->pixelclock; - - vm->hactive = ovt->hactive; - vm->hback_porch = ovt->hback_porch; - vm->hfront_porch = ovt->hfront_porch; - vm->hsync_len = ovt->hsync_len; - vm->vactive = ovt->vactive; - vm->vback_porch = ovt->vback_porch; - vm->vfront_porch = ovt->vfront_porch; - vm->vsync_len = ovt->vsync_len; - vm->flags = ovt->flags; -} -EXPORT_SYMBOL(omap_video_timings_to_videomode); diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index 8fb40efa65af..178335094288 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c @@ -47,7 +47,7 @@ struct dpi_data { struct mutex lock; - struct omap_video_timings timings; + struct videomode timings; struct dss_lcd_mgr_config mgr_config; int data_lines; @@ -333,7 +333,7 @@ static int dpi_set_mode(struct dpi_data *dpi) { struct omap_dss_device *out = &dpi->output; enum omap_channel channel = out->dispc_channel; - struct omap_video_timings *t = &dpi->timings; + struct videomode *t = &dpi->timings; int lck_div = 0, pck_div = 0; unsigned long fck = 0; unsigned long pck; @@ -476,7 +476,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev) } static void dpi_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); @@ -490,7 +490,7 @@ static void dpi_set_timings(struct omap_dss_device *dssdev, } static void dpi_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); @@ -502,7 +502,7 @@ static void dpi_get_timings(struct omap_dss_device *dssdev, } static int dpi_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); enum omap_channel channel = dpi->output.dispc_channel; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 1dec7dd38029..13569cb3f786 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -289,7 +289,7 @@ struct dsi_clk_calc_ctx { struct dss_pll_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; - struct omap_video_timings dispc_vm; + struct videomode dispc_vm; struct omap_dss_dsi_videomode_timings dsi_vm; }; @@ -383,7 +383,7 @@ struct dsi_data { unsigned scp_clk_refcount; struct dss_lcd_mgr_config mgr_config; - struct omap_video_timings timings; + struct videomode timings; enum omap_dss_dsi_pixel_format pix_fmt; enum omap_dss_dsi_mode mode; struct omap_dss_dsi_videomode_timings vm_timings; @@ -3321,7 +3321,7 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev) if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { int bpp = dsi_get_pixel_size(dsi->pix_fmt); - struct omap_video_timings *timings = &dsi->timings; + struct videomode *timings = &dsi->timings; /* * Don't use line buffers if width is greater than the video * port's line buffer size @@ -3453,7 +3453,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev) int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; int tclk_trail, ths_exit, exiths_clk; bool ddr_alwon; - struct omap_video_timings *timings = &dsi->timings; + struct videomode *timings = &dsi->timings; int bpp = dsi_get_pixel_size(dsi->pix_fmt); int ndl = dsi->num_lanes_used - 1; int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1; @@ -3705,7 +3705,7 @@ static void dsi_proto_timings(struct platform_device *dsidev) int vbp = dsi->vm_timings.vbp; int window_sync = dsi->vm_timings.window_sync; bool hsync_end; - struct omap_video_timings *timings = &dsi->timings; + struct videomode *timings = &dsi->timings; int bpp = dsi_get_pixel_size(dsi->pix_fmt); int tl, t_he, width_bytes; @@ -4120,7 +4120,7 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, /* * override interlace, logic level and edge related parameters in - * omap_video_timings with default values + * videomode with default values */ dsi->timings.flags &= ~DISPLAY_FLAGS_INTERLACED; dsi->timings.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; @@ -4361,7 +4361,7 @@ static void print_dsi_vm(const char *str, #undef TO_DSI_T } -static void print_dispc_vm(const char *str, const struct omap_video_timings *t) +static void print_dispc_vm(const char *str, const struct videomode *t) { unsigned long pck = t->pixelclock; int hact, bl, tot; @@ -4392,7 +4392,7 @@ static void print_dispc_vm(const char *str, const struct omap_video_timings *t) static void print_dsi_dispc_vm(const char *str, const struct omap_dss_dsi_videomode_timings *t) { - struct omap_video_timings vm = { 0 }; + struct videomode vm = { 0 }; unsigned long byteclk = t->hsclk / 4; unsigned long pck; u64 dsi_tput; @@ -4417,7 +4417,7 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, unsigned long pck, void *data) { struct dsi_clk_calc_ctx *ctx = data; - struct omap_video_timings *t = &ctx->dispc_vm; + struct videomode *t = &ctx->dispc_vm; ctx->dispc_cinfo.lck_div = lckd; ctx->dispc_cinfo.pck_div = pckd; @@ -4515,8 +4515,8 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) int dispc_htot, dispc_hbl; /* pixels */ int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */ int hfp, hsa, hbp; - const struct omap_video_timings *req_vm; - struct omap_video_timings *dispc_vm; + const struct videomode *req_vm; + struct videomode *dispc_vm; struct omap_dss_dsi_videomode_timings *dsi_vm; u64 dsi_tput, dispc_tput; @@ -4764,7 +4764,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi, const struct omap_dss_dsi_config *cfg, struct dsi_clk_calc_ctx *ctx) { - const struct omap_video_timings *t = cfg->timings; + const struct videomode *t = cfg->timings; unsigned long clkin; unsigned long pll_min; unsigned long pll_max; diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index 4fd06dc41cb3..384267591b12 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -367,7 +367,7 @@ bool dispc_div_calc(unsigned long dispc, dispc_div_calc_func func, void *data); bool dispc_mgr_timings_ok(enum omap_channel channel, - const struct omap_video_timings *timings); + const struct videomode *timings); int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, struct dispc_clock_info *cinfo); @@ -390,7 +390,7 @@ void dispc_wb_enable(bool enable); bool dispc_wb_is_enabled(void); void dispc_wb_set_channel_in(enum dss_writeback_channel channel); int dispc_wb_setup(const struct omap_dss_writeback_info *wi, - bool mem_to_mem, const struct omap_video_timings *timings); + bool mem_to_mem, const struct videomode *timings); /* VENC */ int venc_init_platform_driver(void) __init; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h index 63e711545865..b97ee6702e6f 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h @@ -181,7 +181,7 @@ struct hdmi_video_format { }; struct hdmi_config { - struct omap_video_timings timings; + struct videomode timings; struct hdmi_avi_infoframe infoframe; enum hdmi_core_hdmi_dvi hdmi_dvi_mode; }; @@ -298,11 +298,11 @@ int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val); void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, struct hdmi_video_format *video_fmt); void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, - struct omap_video_timings *timings); + struct videomode *timings); void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, - struct omap_video_timings *timings); + struct videomode *timings); void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, - struct omap_video_timings *timings, struct hdmi_config *param); + struct videomode *timings, struct hdmi_config *param); int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 891518502d3d..a53dfd0bc3b3 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -155,7 +155,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev) static int hdmi_power_on_full(struct omap_dss_device *dssdev) { int r; - struct omap_video_timings *p; + struct videomode *p; enum omap_channel channel = dssdev->dispc_channel; struct hdmi_wp_data *wp = &hdmi.wp; struct dss_pll_clock_info hdmi_cinfo = { 0 }; @@ -256,7 +256,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev) } static int hdmi_display_check_timing(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings)) return -EINVAL; @@ -265,7 +265,7 @@ static int hdmi_display_check_timing(struct omap_dss_device *dssdev, } static void hdmi_display_set_timing(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { mutex_lock(&hdmi.lock); @@ -277,7 +277,7 @@ static void hdmi_display_set_timing(struct omap_dss_device *dssdev, } static void hdmi_display_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { *timings = hdmi.cfg.timings; } diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index ef3afe99e487..505cfee892aa 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -310,7 +310,7 @@ void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg) { /* HDMI */ - struct omap_video_timings video_timing; + struct videomode video_timing; struct hdmi_video_format video_format; /* HDMI core */ struct hdmi_core_video_config v_core_cfg; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 8206ef69caf1..880f67ae6e9b 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -172,7 +172,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev) static int hdmi_power_on_full(struct omap_dss_device *dssdev) { int r; - struct omap_video_timings *p; + struct videomode *p; enum omap_channel channel = dssdev->dispc_channel; struct dss_pll_clock_info hdmi_cinfo = { 0 }; unsigned pc; @@ -273,7 +273,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev) } static int hdmi_display_check_timing(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings)) return -EINVAL; @@ -282,7 +282,7 @@ static int hdmi_display_check_timing(struct omap_dss_device *dssdev, } static void hdmi_display_set_timing(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { mutex_lock(&hdmi.lock); @@ -294,7 +294,7 @@ static void hdmi_display_set_timing(struct omap_dss_device *dssdev, } static void hdmi_display_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { *timings = hdmi.cfg.timings; } diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index e86972b98a91..a5ac9318a11d 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -329,7 +329,7 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, struct hdmi_core_vid_config *cfg) { void __iomem *base = core->base; - struct omap_video_timings *ovt = &cfg->v_fc_config.timings; + struct videomode *ovt = &cfg->v_fc_config.timings; unsigned char r = 0; bool vsync_pol, hsync_pol; @@ -609,7 +609,7 @@ int hdmi5_core_handle_irqs(struct hdmi_core_data *core) void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg) { - struct omap_video_timings video_timing; + struct videomode video_timing; struct hdmi_video_format video_format; struct hdmi_core_vid_config v_core_cfg; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 20effa9260ec..b490e335b3df 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -144,7 +144,7 @@ void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, } void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, - struct omap_video_timings *timings) + struct videomode *timings) { u32 r; bool vsync_pol, hsync_pol; @@ -162,7 +162,7 @@ void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, } void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, - struct omap_video_timings *timings) + struct videomode *timings) { u32 timing_h = 0; u32 timing_v = 0; @@ -193,7 +193,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, } void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, - struct omap_video_timings *timings, struct hdmi_config *param) + struct videomode *timings, struct hdmi_config *param) { DSSDBG("Enter hdmi_wp_video_init_format\n"); diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index bd38da3af01f..54e88ee3ef8e 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -290,7 +290,7 @@ struct omap_dss_dsi_videomode_timings { struct omap_dss_dsi_config { enum omap_dss_dsi_mode mode; enum omap_dss_dsi_pixel_format pixel_format; - const struct omap_video_timings *timings; + const struct videomode *timings; unsigned long hs_clk_min, hs_clk_max; unsigned long lp_clk_min, lp_clk_max; @@ -299,35 +299,12 @@ struct omap_dss_dsi_config { enum omap_dss_dsi_trans_mode trans_mode; }; -struct omap_video_timings { - /* Unit: pixels */ - u32 hactive; - /* Unit: pixels */ - u32 vactive; - /* Unit: Hz */ - unsigned long pixelclock; - /* Unit: pixel clocks */ - u32 hsync_len; /* Horizontal synchronization pulse width */ - /* Unit: pixel clocks */ - u32 hfront_porch; /* Horizontal front porch */ - /* Unit: pixel clocks */ - u32 hback_porch; /* Horizontal back porch */ - /* Unit: line clocks */ - u32 vsync_len; /* Vertical synchronization pulse width */ - /* Unit: line clocks */ - u32 vfront_porch; /* Vertical front porch */ - /* Unit: line clocks */ - u32 vback_porch; /* Vertical back porch */ - - enum display_flags flags; -}; - /* Hardcoded timings for tv modes. Venc only uses these to * identify the mode, and does not actually use the configs * itself. However, the configs should be something that * a normal monitor can also show */ -extern const struct omap_video_timings omap_dss_pal_timings; -extern const struct omap_video_timings omap_dss_ntsc_timings; +extern const struct videomode omap_dss_pal_timings; +extern const struct videomode omap_dss_ntsc_timings; struct omap_dss_cpr_coefs { s16 rr, rg, rb; @@ -489,11 +466,11 @@ struct omapdss_dpi_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*get_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_data_lines)(struct omap_dss_device *dssdev, int data_lines); }; @@ -508,11 +485,11 @@ struct omapdss_sdi_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*get_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_datapairs)(struct omap_dss_device *dssdev, int datapairs); }; @@ -527,11 +504,11 @@ struct omapdss_dvi_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*get_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); }; struct omapdss_atv_ops { @@ -544,11 +521,11 @@ struct omapdss_atv_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*get_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_type)(struct omap_dss_device *dssdev, enum omap_dss_venc_type type); @@ -569,11 +546,11 @@ struct omapdss_hdmi_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*get_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); bool (*detect)(struct omap_dss_device *dssdev); @@ -679,7 +656,7 @@ struct omap_dss_device { } phy; struct { - struct omap_video_timings timings; + struct videomode timings; enum omap_dss_dsi_pixel_format dsi_pix_fmt; enum omap_dss_dsi_mode dsi_mode; @@ -772,11 +749,11 @@ struct omap_dss_driver { int (*get_recommended_bpp)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*set_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); void (*get_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); u32 (*get_wss)(struct omap_dss_device *dssdev); @@ -806,11 +783,6 @@ struct omap_dss_device *omap_dss_find_device(void *data, int (*match)(struct omap_dss_device *dssdev, void *data)); const char *omapdss_get_default_display_name(void); -void videomode_to_omap_video_timings(const struct videomode *vm, - struct omap_video_timings *ovt); -void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, - struct videomode *vm); - int dss_feat_get_num_mgrs(void); int dss_feat_get_num_ovls(void); enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); @@ -839,7 +811,7 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres); int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); void omapdss_default_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); + struct videomode *timings); typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); @@ -893,7 +865,7 @@ void dispc_mgr_go(enum omap_channel channel); void dispc_mgr_set_lcd_config(enum omap_channel channel, const struct dss_lcd_mgr_config *config); void dispc_mgr_set_timings(enum omap_channel channel, - const struct omap_video_timings *timings); + const struct videomode *timings); void dispc_mgr_setup(enum omap_channel channel, const struct omap_overlay_manager_info *info); u32 dispc_mgr_gamma_size(enum omap_channel channel); @@ -906,7 +878,7 @@ bool dispc_ovl_enabled(enum omap_plane plane); void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel); int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, - bool replication, const struct omap_video_timings *mgr_timings, + bool replication, const struct videomode *mgr_timings, bool mem_to_mem); enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel); @@ -921,7 +893,7 @@ struct dss_mgr_ops { int (*enable)(enum omap_channel channel); void (*disable)(enum omap_channel channel); void (*set_timings)(enum omap_channel channel, - const struct omap_video_timings *timings); + const struct videomode *timings); void (*set_lcd_config)(enum omap_channel channel, const struct dss_lcd_mgr_config *config); int (*register_framedone_handler)(enum omap_channel channel, @@ -938,7 +910,7 @@ int dss_mgr_connect(enum omap_channel channel, void dss_mgr_disconnect(enum omap_channel channel, struct omap_dss_device *dst); void dss_mgr_set_timings(enum omap_channel channel, - const struct omap_video_timings *timings); + const struct videomode *timings); void dss_mgr_set_lcd_config(enum omap_channel channel, const struct dss_lcd_mgr_config *config); int dss_mgr_enable(enum omap_channel channel); diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c index 24f859488201..28fc5c159066 100644 --- a/drivers/gpu/drm/omapdrm/dss/output.c +++ b/drivers/gpu/drm/omapdrm/dss/output.c @@ -202,7 +202,7 @@ void dss_mgr_disconnect(enum omap_channel channel, EXPORT_SYMBOL(dss_mgr_disconnect); void dss_mgr_set_timings(enum omap_channel channel, - const struct omap_video_timings *timings) + const struct videomode *timings) { dss_mgr_ops->set_timings(channel, timings); } diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index ce431817e781..a08734ae2253 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -113,7 +113,7 @@ static struct { struct semaphore bus_lock; - struct omap_video_timings timings; + struct videomode timings; int pixel_size; int data_lines; struct rfbi_timings intf_timings; diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index c8658f97ab7d..e2f2d6b2aa76 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c @@ -39,7 +39,7 @@ static struct { struct regulator *vdds_sdi_reg; struct dss_lcd_mgr_config mgr_config; - struct omap_video_timings timings; + struct videomode timings; int datapairs; struct omap_dss_device output; @@ -131,7 +131,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) { struct omap_dss_device *out = &sdi.output; enum omap_channel channel = dssdev->dispc_channel; - struct omap_video_timings *t = &sdi.timings; + struct videomode *t = &sdi.timings; unsigned long fck; struct dispc_clock_info dispc_cinfo; unsigned long pck; @@ -228,19 +228,19 @@ static void sdi_display_disable(struct omap_dss_device *dssdev) } static void sdi_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { sdi.timings = *timings; } static void sdi_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { *timings = sdi.timings; } static int sdi_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { enum omap_channel channel = dssdev->dispc_channel; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 43f98547e9fc..68a04a8753b0 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -262,7 +262,7 @@ static const struct venc_config venc_config_pal_bdghi = { .fid_ext_start_y__fid_ext_offset_y = 0x01380005, }; -const struct omap_video_timings omap_dss_pal_timings = { +const struct videomode omap_dss_pal_timings = { .hactive = 720, .vactive = 574, .pixelclock = 13500000, @@ -280,7 +280,7 @@ const struct omap_video_timings omap_dss_pal_timings = { }; EXPORT_SYMBOL(omap_dss_pal_timings); -const struct omap_video_timings omap_dss_ntsc_timings = { +const struct videomode omap_dss_ntsc_timings = { .hactive = 720, .vactive = 482, .pixelclock = 13500000, @@ -307,7 +307,7 @@ static struct { struct clk *tv_dac_clk; - struct omap_video_timings timings; + struct videomode timings; enum omap_dss_venc_type type; bool invert_polarity; @@ -422,7 +422,7 @@ static void venc_runtime_put(void) } static const struct venc_config *venc_timings_to_config( - struct omap_video_timings *timings) + struct videomode *timings) { if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) return &venc_config_pal_trm; @@ -540,7 +540,7 @@ static void venc_display_disable(struct omap_dss_device *dssdev) } static void venc_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { DSSDBG("venc_set_timings\n"); @@ -558,7 +558,7 @@ static void venc_set_timings(struct omap_dss_device *dssdev, } static int venc_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { DSSDBG("venc_check_timings\n"); @@ -572,7 +572,7 @@ static int venc_check_timings(struct omap_dss_device *dssdev, } static void venc_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) + struct videomode *timings) { mutex_lock(&venc.venc_lock); diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 562a04d49939..b04586b7e594 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -42,76 +42,6 @@ bool omap_connector_get_hdmi_mode(struct drm_connector *connector) return omap_connector->hdmi_mode; } -void copy_timings_omap_to_drm(struct drm_display_mode *mode, - struct omap_video_timings *timings) -{ - mode->clock = timings->pixelclock / 1000; - - mode->hdisplay = timings->hactive; - mode->hsync_start = mode->hdisplay + timings->hfront_porch; - mode->hsync_end = mode->hsync_start + timings->hsync_len; - mode->htotal = mode->hsync_end + timings->hback_porch; - - mode->vdisplay = timings->vactive; - mode->vsync_start = mode->vdisplay + timings->vfront_porch; - mode->vsync_end = mode->vsync_start + timings->vsync_len; - mode->vtotal = mode->vsync_end + timings->vback_porch; - - mode->flags = 0; - - if (timings->flags & DISPLAY_FLAGS_INTERLACED) - mode->flags |= DRM_MODE_FLAG_INTERLACE; - - if (timings->flags & DISPLAY_FLAGS_DOUBLECLK) - mode->flags |= DRM_MODE_FLAG_DBLCLK; - - if (timings->flags & DISPLAY_FLAGS_HSYNC_HIGH) - mode->flags |= DRM_MODE_FLAG_PHSYNC; - else - mode->flags |= DRM_MODE_FLAG_NHSYNC; - - if (timings->flags & DISPLAY_FLAGS_VSYNC_HIGH) - mode->flags |= DRM_MODE_FLAG_PVSYNC; - else - mode->flags |= DRM_MODE_FLAG_NVSYNC; -} - -void copy_timings_drm_to_omap(struct omap_video_timings *timings, - struct drm_display_mode *mode) -{ - timings->pixelclock = mode->clock * 1000; - - timings->hactive = mode->hdisplay; - timings->hfront_porch = mode->hsync_start - mode->hdisplay; - timings->hsync_len = mode->hsync_end - mode->hsync_start; - timings->hback_porch = mode->htotal - mode->hsync_end; - - timings->vactive = mode->vdisplay; - timings->vfront_porch = mode->vsync_start - mode->vdisplay; - timings->vsync_len = mode->vsync_end - mode->vsync_start; - timings->vback_porch = mode->vtotal - mode->vsync_end; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - timings->flags |= DISPLAY_FLAGS_INTERLACED; - - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - timings->flags |= DISPLAY_FLAGS_DOUBLECLK; - - if (mode->flags & DRM_MODE_FLAG_PHSYNC) - timings->flags |= DISPLAY_FLAGS_HSYNC_HIGH; - else - timings->flags |= DISPLAY_FLAGS_HSYNC_LOW; - - if (mode->flags & DRM_MODE_FLAG_PVSYNC) - timings->flags |= DISPLAY_FLAGS_VSYNC_HIGH; - else - timings->flags |= DISPLAY_FLAGS_VSYNC_LOW; - - timings->flags |= DISPLAY_FLAGS_DE_HIGH | - DISPLAY_FLAGS_PIXDATA_POSEDGE | - DISPLAY_FLAGS_SYNC_NEGEDGE; -} - static enum drm_connector_status omap_connector_detect( struct drm_connector *connector, bool force) { @@ -188,11 +118,11 @@ static int omap_connector_get_modes(struct drm_connector *connector) kfree(edid); } else { struct drm_display_mode *mode = drm_mode_create(dev); - struct omap_video_timings timings = {0}; + struct videomode timings = {0}; dssdrv->get_timings(dssdev, &timings); - copy_timings_omap_to_drm(mode, &timings); + drm_display_mode_from_videomode(&timings, mode); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); @@ -210,12 +140,14 @@ static int omap_connector_mode_valid(struct drm_connector *connector, struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; - struct omap_video_timings timings = {0}; + struct videomode timings = {0}; struct drm_device *dev = connector->dev; struct drm_display_mode *new_mode; int r, ret = MODE_BAD; - copy_timings_drm_to_omap(&timings, mode); + drm_display_mode_to_videomode(mode, &timings); + timings.flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_NEGEDGE; mode->vrefresh = drm_mode_vrefresh(mode); /* @@ -226,11 +158,11 @@ static int omap_connector_mode_valid(struct drm_connector *connector, if (dssdrv->check_timings) { r = dssdrv->check_timings(dssdev, &timings); } else { - struct omap_video_timings t = {0}; + struct videomode t = {0}; dssdrv->get_timings(dssdev, &t); - if (memcmp(&timings, &t, sizeof(struct omap_video_timings))) + if (memcmp(&timings, &t, sizeof(struct videomode))) r = -EINVAL; else r = 0; diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index a25d5f769d6f..c819e350fb1b 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -34,7 +34,7 @@ struct omap_crtc { const char *name; enum omap_channel channel; - struct omap_video_timings timings; + struct videomode timings; struct omap_drm_irq vblank_irq; struct omap_drm_irq error_irq; @@ -56,7 +56,7 @@ uint32_t pipe2vbl(struct drm_crtc *crtc) return dispc_mgr_get_vsync_irq(omap_crtc->channel); } -struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc) +struct videomode *omap_crtc_timings(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); return &omap_crtc->timings; @@ -215,7 +215,7 @@ static void omap_crtc_dss_disable(enum omap_channel channel) } static void omap_crtc_dss_set_timings(enum omap_channel channel, - const struct omap_video_timings *timings) + const struct videomode *timings) { struct omap_crtc *omap_crtc = omap_crtcs[channel]; DBG("%s", omap_crtc->name); @@ -369,7 +369,10 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, mode->type, mode->flags); - copy_timings_drm_to_omap(&omap_crtc->timings, mode); + drm_display_mode_to_videomode(mode, &omap_crtc->timings); + omap_crtc->timings.flags |= DISPLAY_FLAGS_DE_HIGH | + DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_NEGEDGE; } static int omap_crtc_atomic_check(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index dcc30a98b9d4..4c51135eb9a6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -148,7 +148,7 @@ static inline void omap_fbdev_free(struct drm_device *dev) } #endif -struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc); +struct videomode *omap_crtc_timings(struct drm_crtc *crtc); enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); void omap_crtc_pre_init(void); void omap_crtc_pre_uninit(void); @@ -171,11 +171,6 @@ struct drm_encoder *omap_connector_attached_encoder( struct drm_connector *connector); bool omap_connector_get_hdmi_mode(struct drm_connector *connector); -void copy_timings_omap_to_drm(struct drm_display_mode *mode, - struct omap_video_timings *timings); -void copy_timings_drm_to_omap(struct omap_video_timings *timings, - struct drm_display_mode *mode); - uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats, uint32_t max_formats, enum omap_color_mode supported_modes); struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index 0bbb9c59622e..f54065e9e2bf 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c @@ -102,7 +102,7 @@ static void omap_encoder_disable(struct drm_encoder *encoder) static int omap_encoder_update(struct drm_encoder *encoder, enum omap_channel channel, - struct omap_video_timings *timings) + struct videomode *timings) { struct drm_device *dev = encoder->dev; struct omap_encoder *omap_encoder = to_omap_encoder(encoder); @@ -113,11 +113,11 @@ static int omap_encoder_update(struct drm_encoder *encoder, if (dssdrv->check_timings) { ret = dssdrv->check_timings(dssdev, timings); } else { - struct omap_video_timings t = {0}; + struct videomode t = {0}; dssdrv->get_timings(dssdev, &t); - if (memcmp(timings, &t, sizeof(struct omap_video_timings))) + if (memcmp(timings, &t, sizeof(struct videomode))) ret = -EINVAL; else ret = 0; -- cgit v1.2.3 From da11bbbb10a964c293c2e2e702ea62ad6cba48b4 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:04 +0300 Subject: drm/omap: Use consistent name for struct videomode Use 'vm' to refer to a struct videomode instead of 'p', 't', 'timings' or something else. The code will be easier to follow if we use consistent names. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- .../gpu/drm/omapdrm/displays/connector-analog-tv.c | 26 ++--- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 26 ++--- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 26 ++--- drivers/gpu/drm/omapdrm/displays/encoder-opa362.c | 20 ++-- drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c | 31 +++--- .../gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 20 ++-- drivers/gpu/drm/omapdrm/displays/panel-dpi.c | 26 ++--- drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 23 ++--- .../omapdrm/displays/panel-lgphilips-lb035q02.c | 26 ++--- .../drm/omapdrm/displays/panel-nec-nl8048hl11.c | 26 ++--- .../drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 26 ++--- .../drm/omapdrm/displays/panel-sony-acx565akm.c | 26 ++--- .../drm/omapdrm/displays/panel-tpo-td028ttec1.c | 26 ++--- .../drm/omapdrm/displays/panel-tpo-td043mtea1.c | 26 ++--- drivers/gpu/drm/omapdrm/dss/dispc.c | 114 ++++++++++----------- drivers/gpu/drm/omapdrm/dss/display.c | 8 +- drivers/gpu/drm/omapdrm/dss/dpi.c | 38 +++---- drivers/gpu/drm/omapdrm/dss/dsi.c | 108 +++++++++---------- drivers/gpu/drm/omapdrm/dss/dss.h | 5 +- drivers/gpu/drm/omapdrm/dss/hdmi.h | 8 +- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 32 +++--- drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 8 +- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 32 +++--- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 68 ++++++------ drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 58 +++++------ drivers/gpu/drm/omapdrm/dss/omapdss.h | 57 +++++------ drivers/gpu/drm/omapdrm/dss/output.c | 5 +- drivers/gpu/drm/omapdrm/dss/rfbi.c | 52 +++++----- drivers/gpu/drm/omapdrm/dss/sdi.c | 30 +++--- drivers/gpu/drm/omapdrm/dss/venc.c | 39 ++++--- drivers/gpu/drm/omapdrm/omap_connector.c | 20 ++-- drivers/gpu/drm/omapdrm/omap_crtc.c | 18 ++-- drivers/gpu/drm/omapdrm/omap_encoder.c | 8 +- 33 files changed, 527 insertions(+), 535 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c index 53a4e6942616..aaa8a58390f1 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c @@ -24,12 +24,12 @@ struct panel_drv_data { struct device *dev; - struct videomode timings; + struct videomode vm; bool invert_polarity; }; -static const struct videomode tvc_pal_timings = { +static const struct videomode tvc_pal_vm = { .hactive = 720, .vactive = 574, .pixelclock = 13500000, @@ -93,7 +93,7 @@ static int tvc_enable(struct omap_dss_device *dssdev) if (omapdss_device_is_enabled(dssdev)) return 0; - in->ops.atv->set_timings(in, &ddata->timings); + in->ops.atv->set_timings(in, &ddata->vm); if (!ddata->dev->of_node) { in->ops.atv->set_type(in, OMAP_DSS_VENC_TYPE_COMPOSITE); @@ -127,32 +127,32 @@ static void tvc_disable(struct omap_dss_device *dssdev) } static void tvc_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->timings = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.atv->set_timings(in, timings); + in->ops.atv->set_timings(in, vm); } static void tvc_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->timings; + *vm = ddata->vm; } static int tvc_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.atv->check_timings(in, timings); + return in->ops.atv->check_timings(in, vm); } static u32 tvc_get_wss(struct omap_dss_device *dssdev) @@ -254,14 +254,14 @@ static int tvc_probe(struct platform_device *pdev) return -ENODEV; } - ddata->timings = tvc_pal_timings; + ddata->vm = tvc_pal_vm; dssdev = &ddata->dssdev; dssdev->driver = &tvc_driver; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_VENC; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = tvc_pal_timings; + dssdev->panel.vm = tvc_pal_vm; r = omapdss_register_display(dssdev); if (r) { diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index f4f8bf07f38b..d6875d9fcefa 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -19,7 +19,7 @@ #include "../dss/omapdss.h" -static const struct videomode dvic_default_timings = { +static const struct videomode dvic_default_vm = { .hactive = 640, .vactive = 480, @@ -42,7 +42,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - struct videomode timings; + struct videomode vm; struct i2c_adapter *i2c_adapter; }; @@ -88,7 +88,7 @@ static int dvic_enable(struct omap_dss_device *dssdev) if (omapdss_device_is_enabled(dssdev)) return 0; - in->ops.dvi->set_timings(in, &ddata->timings); + in->ops.dvi->set_timings(in, &ddata->vm); r = in->ops.dvi->enable(in); if (r) @@ -113,32 +113,32 @@ static void dvic_disable(struct omap_dss_device *dssdev) } static void dvic_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->timings = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.dvi->set_timings(in, timings); + in->ops.dvi->set_timings(in, vm); } static void dvic_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->timings; + *vm = ddata->vm; } static int dvic_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.dvi->check_timings(in, timings); + return in->ops.dvi->check_timings(in, vm); } static int dvic_ddc_read(struct i2c_adapter *adapter, @@ -285,14 +285,14 @@ static int dvic_probe(struct platform_device *pdev) if (r) return r; - ddata->timings = dvic_default_timings; + ddata->vm = dvic_default_vm; dssdev = &ddata->dssdev; dssdev->driver = &dvic_driver; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_DVI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = dvic_default_timings; + dssdev->panel.vm = dvic_default_vm; r = omapdss_register_display(dssdev); if (r) { diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index 4f77e03abd43..1ef130641bae 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -21,7 +21,7 @@ #include "../dss/omapdss.h" -static const struct videomode hdmic_default_timings = { +static const struct videomode hdmic_default_vm = { .hactive = 640, .vactive = 480, .pixelclock = 25175000, @@ -41,7 +41,7 @@ struct panel_drv_data { struct device *dev; - struct videomode timings; + struct videomode vm; int hpd_gpio; }; @@ -93,7 +93,7 @@ static int hdmic_enable(struct omap_dss_device *dssdev) if (omapdss_device_is_enabled(dssdev)) return 0; - in->ops.hdmi->set_timings(in, &ddata->timings); + in->ops.hdmi->set_timings(in, &ddata->vm); r = in->ops.hdmi->enable(in); if (r) @@ -120,32 +120,32 @@ static void hdmic_disable(struct omap_dss_device *dssdev) } static void hdmic_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->timings = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.hdmi->set_timings(in, timings); + in->ops.hdmi->set_timings(in, vm); } static void hdmic_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->timings; + *vm = ddata->vm; } static int hdmic_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.hdmi->check_timings(in, timings); + return in->ops.hdmi->check_timings(in, vm); } static int hdmic_read_edid(struct omap_dss_device *dssdev, @@ -256,14 +256,14 @@ static int hdmic_probe(struct platform_device *pdev) goto err_reg; } - ddata->timings = hdmic_default_timings; + ddata->vm = hdmic_default_vm; dssdev = &ddata->dssdev; dssdev->driver = &hdmic_driver; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_HDMI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = hdmic_default_timings; + dssdev->panel.vm = hdmic_default_vm; r = omapdss_register_display(dssdev); if (r) { diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c index e997128343c1..f7a5731492d0 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c @@ -27,7 +27,7 @@ struct panel_drv_data { struct gpio_desc *enable_gpio; - struct videomode timings; + struct videomode vm; }; #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -90,7 +90,7 @@ static int opa362_enable(struct omap_dss_device *dssdev) if (omapdss_device_is_enabled(dssdev)) return 0; - in->ops.atv->set_timings(in, &ddata->timings); + in->ops.atv->set_timings(in, &ddata->vm); r = in->ops.atv->enable(in); if (r) @@ -123,38 +123,38 @@ static void opa362_disable(struct omap_dss_device *dssdev) } static void opa362_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; dev_dbg(dssdev->dev, "set_timings\n"); - ddata->timings = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.atv->set_timings(in, timings); + in->ops.atv->set_timings(in, vm); } static void opa362_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); dev_dbg(dssdev->dev, "get_timings\n"); - *timings = ddata->timings; + *vm = ddata->vm; } static int opa362_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; dev_dbg(dssdev->dev, "check_timings\n"); - return in->ops.atv->check_timings(in, timings); + return in->ops.atv->check_timings(in, vm); } static void opa362_set_type(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c index 96f0e7e7f889..13e32d02c884 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c @@ -24,7 +24,7 @@ struct panel_drv_data { int pd_gpio; int data_lines; - struct videomode timings; + struct videomode vm; }; #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -81,7 +81,7 @@ static int tfp410_enable(struct omap_dss_device *dssdev) if (omapdss_device_is_enabled(dssdev)) return 0; - in->ops.dpi->set_timings(in, &ddata->timings); + in->ops.dpi->set_timings(in, &ddata->vm); if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); @@ -113,44 +113,43 @@ static void tfp410_disable(struct omap_dss_device *dssdev) dssdev->state = OMAP_DSS_DISPLAY_DISABLED; } -static void tfp410_fix_timings(struct videomode *timings) +static void tfp410_fix_timings(struct videomode *vm) { - timings->flags |= DISPLAY_FLAGS_DE_HIGH | - DISPLAY_FLAGS_PIXDATA_POSEDGE | - DISPLAY_FLAGS_SYNC_POSEDGE; + vm->flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_POSEDGE; } static void tfp410_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - tfp410_fix_timings(timings); + tfp410_fix_timings(vm); - ddata->timings = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.dpi->set_timings(in, timings); + in->ops.dpi->set_timings(in, vm); } static void tfp410_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->timings; + *vm = ddata->vm; } static int tfp410_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - tfp410_fix_timings(timings); + tfp410_fix_timings(vm); - return in->ops.dpi->check_timings(in, timings); + return in->ops.dpi->check_timings(in, vm); } static const struct omapdss_dvi_ops tfp410_dvi_ops = { diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c index f4608c5a9e93..6d8f79b29af6 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c @@ -26,7 +26,7 @@ struct panel_drv_data { struct gpio_desc *ls_oe_gpio; struct gpio_desc *hpd_gpio; - struct videomode timings; + struct videomode vm; }; #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -80,7 +80,7 @@ static int tpd_enable(struct omap_dss_device *dssdev) if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) return 0; - in->ops.hdmi->set_timings(in, &ddata->timings); + in->ops.hdmi->set_timings(in, &ddata->vm); r = in->ops.hdmi->enable(in); if (r) @@ -105,33 +105,33 @@ static void tpd_disable(struct omap_dss_device *dssdev) } static void tpd_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->timings = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.hdmi->set_timings(in, timings); + in->ops.hdmi->set_timings(in, vm); } static void tpd_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->timings; + *vm = ddata->vm; } static int tpd_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; int r; - r = in->ops.hdmi->check_timings(in, timings); + r = in->ops.hdmi->check_timings(in, vm); return r; } diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c index 50359b3d9db2..38003208d9ca 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c @@ -28,7 +28,7 @@ struct panel_drv_data { int data_lines; - struct videomode videomode; + struct videomode vm; /* used for non-DT boot, to be removed */ int backlight_gpio; @@ -80,7 +80,7 @@ static int panel_dpi_enable(struct omap_dss_device *dssdev) if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); - in->ops.dpi->set_timings(in, &ddata->videomode); + in->ops.dpi->set_timings(in, &ddata->vm); r = in->ops.dpi->enable(in); if (r) @@ -122,32 +122,32 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev) } static void panel_dpi_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->videomode = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.dpi->set_timings(in, timings); + in->ops.dpi->set_timings(in, vm); } static void panel_dpi_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->videomode; + *vm = ddata->vm; } static int panel_dpi_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.dpi->check_timings(in, timings); + return in->ops.dpi->check_timings(in, vm); } static struct omap_dss_driver panel_dpi_ops = { @@ -184,7 +184,7 @@ static int panel_dpi_probe_pdata(struct platform_device *pdev) ddata->data_lines = pdata->data_lines; - videomode_from_timing(pdata->display_timing, &ddata->videomode); + videomode_from_timing(pdata->display_timing, &ddata->vm); dssdev = &ddata->dssdev; dssdev->name = pdata->name; @@ -242,7 +242,7 @@ static int panel_dpi_probe_of(struct platform_device *pdev) return r; } - videomode_from_timing(&timing, &ddata->videomode); + videomode_from_timing(&timing, &ddata->vm); in = omapdss_of_find_source_for_first_ep(node); if (IS_ERR(in)) { @@ -291,7 +291,7 @@ static int panel_dpi_probe(struct platform_device *pdev) dssdev->driver = &panel_dpi_ops; dssdev->type = OMAP_DISPLAY_TYPE_DPI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = ddata->videomode; + dssdev->panel.vm = ddata->vm; dssdev->phy.dpi.data_lines = ddata->data_lines; r = omapdss_register_display(dssdev); diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c index 10a2a69ced2a..dc026a843712 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c @@ -42,7 +42,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - struct videomode timings; + struct videomode vm; struct platform_device *pdev; @@ -382,8 +382,8 @@ static const struct backlight_ops dsicm_bl_ops = { static void dsicm_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { - *xres = dssdev->panel.timings.hactive; - *yres = dssdev->panel.timings.vactive; + *xres = dssdev->panel.vm.hactive; + *yres = dssdev->panel.vm.vactive; } static ssize_t dsicm_num_errors_show(struct device *dev, @@ -589,7 +589,7 @@ static int dsicm_power_on(struct panel_drv_data *ddata) struct omap_dss_dsi_config dsi_config = { .mode = OMAP_DSS_DSI_CMD_MODE, .pixel_format = OMAP_DSS_DSI_FMT_RGB888, - .timings = &ddata->timings, + .vm = &ddata->vm, .hs_clk_min = 150000000, .hs_clk_max = 300000000, .lp_clk_min = 7000000, @@ -892,8 +892,8 @@ static int dsicm_update(struct omap_dss_device *dssdev, /* XXX no need to send this every frame, but dsi break if not done */ r = dsicm_set_update_window(ddata, 0, 0, - dssdev->panel.timings.hactive, - dssdev->panel.timings.vactive); + dssdev->panel.vm.hactive, + dssdev->panel.vm.vactive); if (r) goto err; @@ -1024,8 +1024,7 @@ static int dsicm_memory_read(struct omap_dss_device *dssdev, } size = min((u32)w * h * 3, - dssdev->panel.timings.hactive * - dssdev->panel.timings.vactive * 3); + dssdev->panel.vm.hactive * dssdev->panel.vm.vactive * 3); in->ops.dsi->bus_lock(in); @@ -1186,14 +1185,14 @@ static int dsicm_probe(struct platform_device *pdev) if (r) return r; - ddata->timings.hactive = 864; - ddata->timings.vactive = 480; - ddata->timings.pixelclock = 864 * 480 * 60; + ddata->vm.hactive = 864; + ddata->vm.vactive = 480; + ddata->vm.pixelclock = 864 * 480 * 60; dssdev = &ddata->dssdev; dssdev->dev = dev; dssdev->driver = &dsicm_ops; - dssdev->panel.timings = ddata->timings; + dssdev->panel.vm = ddata->vm; dssdev->type = OMAP_DISPLAY_TYPE_DSI; dssdev->owner = THIS_MODULE; diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index 3559efd6170d..b36fa0a57b61 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -19,7 +19,7 @@ #include "../dss/omapdss.h" -static struct videomode lb035q02_timings = { +static struct videomode lb035q02_vm = { .hactive = 320, .vactive = 240, @@ -46,7 +46,7 @@ struct panel_drv_data { int data_lines; - struct videomode videomode; + struct videomode vm; struct gpio_desc *enable_gpio; }; @@ -156,7 +156,7 @@ static int lb035q02_enable(struct omap_dss_device *dssdev) if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); - in->ops.dpi->set_timings(in, &ddata->videomode); + in->ops.dpi->set_timings(in, &ddata->vm); r = in->ops.dpi->enable(in); if (r) @@ -187,32 +187,32 @@ static void lb035q02_disable(struct omap_dss_device *dssdev) } static void lb035q02_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->videomode = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.dpi->set_timings(in, timings); + in->ops.dpi->set_timings(in, vm); } static void lb035q02_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->videomode; + *vm = ddata->vm; } static int lb035q02_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.dpi->check_timings(in, timings); + return in->ops.dpi->check_timings(in, vm); } static struct omap_dss_driver lb035q02_ops = { @@ -276,14 +276,14 @@ static int lb035q02_panel_spi_probe(struct spi_device *spi) if (r) return r; - ddata->videomode = lb035q02_timings; + ddata->vm = lb035q02_vm; dssdev = &ddata->dssdev; dssdev->dev = &spi->dev; dssdev->driver = &lb035q02_ops; dssdev->type = OMAP_DISPLAY_TYPE_DPI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = ddata->videomode; + dssdev->panel.vm = ddata->vm; dssdev->phy.dpi.data_lines = ddata->data_lines; r = omapdss_register_display(dssdev); diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c index 5e1e3a02c32b..2de27ba01552 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c @@ -23,7 +23,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - struct videomode videomode; + struct videomode vm; int data_lines; @@ -65,7 +65,7 @@ static const struct { { 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 }, }; -static const struct videomode nec_8048_panel_timings = { +static const struct videomode nec_8048_panel_vm = { .hactive = LCD_XRES, .vactive = LCD_YRES, .pixelclock = LCD_PIXEL_CLOCK, @@ -155,7 +155,7 @@ static int nec_8048_enable(struct omap_dss_device *dssdev) if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); - in->ops.dpi->set_timings(in, &ddata->videomode); + in->ops.dpi->set_timings(in, &ddata->vm); r = in->ops.dpi->enable(in); if (r) @@ -186,32 +186,32 @@ static void nec_8048_disable(struct omap_dss_device *dssdev) } static void nec_8048_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->videomode = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.dpi->set_timings(in, timings); + in->ops.dpi->set_timings(in, vm); } static void nec_8048_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->videomode; + *vm = ddata->vm; } static int nec_8048_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.dpi->check_timings(in, timings); + return in->ops.dpi->check_timings(in, vm); } static struct omap_dss_driver nec_8048_ops = { @@ -304,14 +304,14 @@ static int nec_8048_probe(struct spi_device *spi) goto err_gpio; } - ddata->videomode = nec_8048_panel_timings; + ddata->vm = nec_8048_panel_vm; dssdev = &ddata->dssdev; dssdev->dev = &spi->dev; dssdev->driver = &nec_8048_ops; dssdev->type = OMAP_DISPLAY_TYPE_DPI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = ddata->videomode; + dssdev->panel.vm = ddata->vm; r = omapdss_register_display(dssdev); if (r) { diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index 0aac8aa0f685..fd33156bc34c 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -26,7 +26,7 @@ struct panel_drv_data { int data_lines; - struct videomode videomode; + struct videomode vm; struct gpio_desc *resb_gpio; /* low = reset active min 20 us */ struct gpio_desc *ini_gpio; /* high = power on */ @@ -35,7 +35,7 @@ struct panel_drv_data { struct gpio_desc *ud_gpio; /* high = conventional vertical scanning */ }; -static const struct videomode sharp_ls_timings = { +static const struct videomode sharp_ls_vm = { .hactive = 480, .vactive = 640, @@ -97,7 +97,7 @@ static int sharp_ls_enable(struct omap_dss_device *dssdev) if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); - in->ops.dpi->set_timings(in, &ddata->videomode); + in->ops.dpi->set_timings(in, &ddata->vm); if (ddata->vcc) { r = regulator_enable(ddata->vcc); @@ -152,32 +152,32 @@ static void sharp_ls_disable(struct omap_dss_device *dssdev) } static void sharp_ls_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->videomode = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.dpi->set_timings(in, timings); + in->ops.dpi->set_timings(in, vm); } static void sharp_ls_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->videomode; + *vm = ddata->vm; } static int sharp_ls_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.dpi->check_timings(in, timings); + return in->ops.dpi->check_timings(in, vm); } static struct omap_dss_driver sharp_ls_ops = { @@ -277,14 +277,14 @@ static int sharp_ls_probe(struct platform_device *pdev) if (r) return r; - ddata->videomode = sharp_ls_timings; + ddata->vm = sharp_ls_vm; dssdev = &ddata->dssdev; dssdev->dev = &pdev->dev; dssdev->driver = &sharp_ls_ops; dssdev->type = OMAP_DISPLAY_TYPE_DPI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = ddata->videomode; + dssdev->panel.vm = ddata->vm; dssdev->phy.dpi.data_lines = ddata->data_lines; r = omapdss_register_display(dssdev); diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index e83e12724ff5..746cb8d9cba1 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c @@ -71,7 +71,7 @@ struct panel_drv_data { int reset_gpio; int datapairs; - struct videomode videomode; + struct videomode vm; char *name; int enabled; @@ -92,7 +92,7 @@ struct panel_drv_data { struct backlight_device *bl_dev; }; -static const struct videomode acx565akm_panel_timings = { +static const struct videomode acx565akm_panel_vm = { .hactive = 800, .vactive = 480, .pixelclock = 24000000, @@ -545,7 +545,7 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev) dev_dbg(&ddata->spi->dev, "%s\n", __func__); - in->ops.sdi->set_timings(in, &ddata->videomode); + in->ops.sdi->set_timings(in, &ddata->vm); if (ddata->datapairs > 0) in->ops.sdi->set_datapairs(in, ddata->datapairs); @@ -659,32 +659,32 @@ static void acx565akm_disable(struct omap_dss_device *dssdev) } static void acx565akm_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->videomode = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.sdi->set_timings(in, timings); + in->ops.sdi->set_timings(in, vm); } static void acx565akm_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->videomode; + *vm = ddata->vm; } static int acx565akm_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.sdi->check_timings(in, timings); + return in->ops.sdi->check_timings(in, vm); } static struct omap_dss_driver acx565akm_ops = { @@ -842,14 +842,14 @@ static int acx565akm_probe(struct spi_device *spi) acx565akm_bl_update_status(bldev); - ddata->videomode = acx565akm_panel_timings; + ddata->vm = acx565akm_panel_vm; dssdev = &ddata->dssdev; dssdev->dev = &spi->dev; dssdev->driver = &acx565akm_ops; dssdev->type = OMAP_DISPLAY_TYPE_SDI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = ddata->videomode; + dssdev->panel.vm = ddata->vm; r = omapdss_register_display(dssdev); if (r) { diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index 2b38867e17a5..c003f4dd2a18 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -37,12 +37,12 @@ struct panel_drv_data { int data_lines; - struct videomode videomode; + struct videomode vm; struct spi_device *spi_dev; }; -static struct videomode td028ttec1_panel_timings = { +static struct videomode td028ttec1_panel_vm = { .hactive = 480, .vactive = 640, .pixelclock = 22153000, @@ -205,7 +205,7 @@ static int td028ttec1_panel_enable(struct omap_dss_device *dssdev) if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); - in->ops.dpi->set_timings(in, &ddata->videomode); + in->ops.dpi->set_timings(in, &ddata->vm); r = in->ops.dpi->enable(in); if (r) @@ -322,32 +322,32 @@ static void td028ttec1_panel_disable(struct omap_dss_device *dssdev) } static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->videomode = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.dpi->set_timings(in, timings); + in->ops.dpi->set_timings(in, vm); } static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->videomode; + *vm = ddata->vm; } static int td028ttec1_panel_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.dpi->check_timings(in, timings); + return in->ops.dpi->check_timings(in, vm); } static struct omap_dss_driver td028ttec1_ops = { @@ -411,14 +411,14 @@ static int td028ttec1_panel_probe(struct spi_device *spi) if (r) return r; - ddata->videomode = td028ttec1_panel_timings; + ddata->vm = td028ttec1_panel_vm; dssdev = &ddata->dssdev; dssdev->dev = &spi->dev; dssdev->driver = &td028ttec1_ops; dssdev->type = OMAP_DISPLAY_TYPE_DPI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = ddata->videomode; + dssdev->panel.vm = ddata->vm; dssdev->phy.dpi.data_lines = ddata->data_lines; r = omapdss_register_display(dssdev); diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index da7b75751c71..f78102aab2e6 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -56,7 +56,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - struct videomode videomode; + struct videomode vm; int data_lines; @@ -72,7 +72,7 @@ struct panel_drv_data { u32 power_on_resume:1; }; -static const struct videomode tpo_td043_timings = { +static const struct videomode tpo_td043_vm = { .hactive = 800, .vactive = 480, @@ -376,7 +376,7 @@ static int tpo_td043_enable(struct omap_dss_device *dssdev) if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); - in->ops.dpi->set_timings(in, &ddata->videomode); + in->ops.dpi->set_timings(in, &ddata->vm); r = in->ops.dpi->enable(in); if (r) @@ -416,32 +416,32 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev) } static void tpo_td043_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - ddata->videomode = *timings; - dssdev->panel.timings = *timings; + ddata->vm = *vm; + dssdev->panel.vm = *vm; - in->ops.dpi->set_timings(in, timings); + in->ops.dpi->set_timings(in, vm); } static void tpo_td043_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *timings = ddata->videomode; + *vm = ddata->vm; } static int tpo_td043_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - return in->ops.dpi->check_timings(in, timings); + return in->ops.dpi->check_timings(in, vm); } static struct omap_dss_driver tpo_td043_ops = { @@ -544,14 +544,14 @@ static int tpo_td043_probe(struct spi_device *spi) goto err_sysfs; } - ddata->videomode = tpo_td043_timings; + ddata->vm = tpo_td043_vm; dssdev = &ddata->dssdev; dssdev->dev = &spi->dev; dssdev->driver = &tpo_td043_ops; dssdev->type = OMAP_DISPLAY_TYPE_DPI; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = ddata->videomode; + dssdev->panel.vm = ddata->vm; r = omapdss_register_display(dssdev); if (r) { diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index a5b7488a5cfb..c839f6456db2 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -75,7 +75,7 @@ struct dispc_features { unsigned long max_lcd_pclk; unsigned long max_tv_pclk; int (*calc_scaling) (unsigned long pclk, unsigned long lclk, - const struct videomode *mgr_timings, + const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, @@ -2179,7 +2179,7 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width, * undocumented horizontal position and timing related limitations. */ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, - const struct videomode *t, u16 pos_x, + const struct videomode *vm, u16 pos_x, u16 width, u16 height, u16 out_width, u16 out_height, bool five_taps) { @@ -2189,15 +2189,15 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, u64 val, blank; int i; - nonactive = t->hactive + t->hfront_porch + t->hsync_len + - t->hback_porch - out_width; + nonactive = vm->hactive + vm->hfront_porch + vm->hsync_len + + vm->hback_porch - out_width; i = 0; if (out_height < height) i++; if (out_width < width) i++; - blank = div_u64((u64)(t->hback_porch + t->hsync_len + t->hfront_porch) * + blank = div_u64((u64)(vm->hback_porch + vm->hsync_len + vm->hfront_porch) * lclk, pclk); DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]); if (blank <= limits[i]) @@ -2233,7 +2233,7 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, } static unsigned long calc_core_clk_five_taps(unsigned long pclk, - const struct videomode *mgr_timings, u16 width, + const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode) { @@ -2244,7 +2244,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, return (unsigned long) pclk; if (height > out_height) { - unsigned int ppl = mgr_timings->hactive; + unsigned int ppl = vm->hactive; tmp = (u64)pclk * height * out_width; do_div(tmp, 2 * out_height * ppl); @@ -2326,7 +2326,7 @@ static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width, } static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, - const struct videomode *mgr_timings, + const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, @@ -2372,7 +2372,7 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, } static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, - const struct videomode *mgr_timings, + const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, @@ -2394,7 +2394,7 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, *five_taps = false; again: if (*five_taps) - *core_clk = calc_core_clk_five_taps(pclk, mgr_timings, + *core_clk = calc_core_clk_five_taps(pclk, vm, in_width, in_height, out_width, out_height, color_mode); else @@ -2402,7 +2402,7 @@ again: in_height, out_width, out_height, mem_to_mem); - error = check_horiz_timing_omap3(pclk, lclk, mgr_timings, + error = check_horiz_timing_omap3(pclk, lclk, vm, pos_x, in_width, in_height, out_width, out_height, *five_taps); if (error && *five_taps) { @@ -2437,7 +2437,7 @@ again: return -EINVAL; } - if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width, + if (check_horiz_timing_omap3(pclk, lclk, vm, pos_x, in_width, in_height, out_width, out_height, *five_taps)) { DSSERR("horizontal timing too tight\n"); return -EINVAL; @@ -2457,7 +2457,7 @@ again: } static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, - const struct videomode *mgr_timings, + const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, @@ -2503,7 +2503,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, enum omap_overlay_caps caps, - const struct videomode *mgr_timings, + const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, u16 pos_x, @@ -2517,7 +2517,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, if (width == out_width && height == out_height) return 0; - if (!mem_to_mem && (pclk == 0 || mgr_timings->pixelclock == 0)) { + if (!mem_to_mem && (pclk == 0 || vm->pixelclock == 0)) { DSSERR("cannot calculate scaling settings: pclk is zero\n"); return -EINVAL; } @@ -2553,7 +2553,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, if (decim_y > *y_predecim || out_height > height * 8) return -EINVAL; - ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height, + ret = dispc.feat->calc_scaling(pclk, lclk, vm, width, height, out_width, out_height, color_mode, five_taps, x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk, mem_to_mem); @@ -2593,7 +2593,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, u16 out_width, u16 out_height, enum omap_color_mode color_mode, u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha, u8 global_alpha, enum omap_dss_rotation_type rotation_type, - bool replication, const struct videomode *mgr_timings, + bool replication, const struct videomode *vm, bool mem_to_mem) { bool five_taps = true; @@ -2607,7 +2607,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, u16 in_height = height; u16 in_width = width; int x_predecim = 1, y_predecim = 1; - bool ilace = !!(mgr_timings->flags & DISPLAY_FLAGS_INTERLACED); + bool ilace = !!(vm->flags & DISPLAY_FLAGS_INTERLACED); unsigned long pclk = dispc_plane_pclk_rate(plane); unsigned long lclk = dispc_plane_lclk_rate(plane); @@ -2649,7 +2649,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, if (!dss_feat_color_mode_supported(plane, color_mode)) return -EINVAL; - r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width, + r = dispc_ovl_calc_scaling(pclk, lclk, caps, vm, in_width, in_height, out_width, out_height, color_mode, &five_taps, &x_predecim, &y_predecim, pos_x, rotation_type, mem_to_mem); @@ -2786,7 +2786,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, } int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, - bool replication, const struct videomode *mgr_timings, + bool replication, const struct videomode *vm, bool mem_to_mem) { int r; @@ -2805,14 +2805,14 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height, oi->color_mode, oi->rotation, oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, - oi->rotation_type, replication, mgr_timings, mem_to_mem); + oi->rotation_type, replication, vm, mem_to_mem); return r; } EXPORT_SYMBOL(dispc_ovl_setup); int dispc_wb_setup(const struct omap_dss_writeback_info *wi, - bool mem_to_mem, const struct videomode *mgr_timings) + bool mem_to_mem, const struct videomode *vm) { int r; u32 l; @@ -2821,8 +2821,8 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, const u8 zorder = 0, global_alpha = 0; const bool replication = false; bool truncation; - int in_width = mgr_timings->hactive; - int in_height = mgr_timings->vactive; + int in_width = vm->hactive; + int in_height = vm->vactive; enum omap_overlay_caps caps = OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA; @@ -2835,7 +2835,7 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width, wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder, wi->pre_mult_alpha, global_alpha, wi->rotation_type, - replication, mgr_timings, mem_to_mem); + replication, vm, mem_to_mem); switch (wi->color_mode) { case OMAP_DSS_COLOR_RGB16: @@ -2869,9 +2869,8 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, } else { int wbdelay; - wbdelay = min(mgr_timings->vfront_porch + - mgr_timings->vsync_len + mgr_timings->vback_porch, - (u32)255); + wbdelay = min(vm->vfront_porch + + vm->vsync_len + vm->vback_porch, (u32)255); /* WBDELAYCOUNT */ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0); @@ -3118,24 +3117,23 @@ static bool _dispc_mgr_pclk_ok(enum omap_channel channel, return pclk <= dispc.feat->max_tv_pclk; } -bool dispc_mgr_timings_ok(enum omap_channel channel, - const struct videomode *timings) +bool dispc_mgr_timings_ok(enum omap_channel channel, const struct videomode *vm) { - if (!_dispc_mgr_size_ok(timings->hactive, timings->vactive)) + if (!_dispc_mgr_size_ok(vm->hactive, vm->vactive)) return false; - if (!_dispc_mgr_pclk_ok(channel, timings->pixelclock)) + if (!_dispc_mgr_pclk_ok(channel, vm->pixelclock)) return false; if (dss_mgr_is_lcd(channel)) { /* TODO: OMAP4+ supports interlace for LCD outputs */ - if (timings->flags & DISPLAY_FLAGS_INTERLACED) + if (vm->flags & DISPLAY_FLAGS_INTERLACED) return false; - if (!_dispc_lcd_timings_ok(timings->hsync_len, - timings->hfront_porch, timings->hback_porch, - timings->vsync_len, timings->vfront_porch, - timings->vback_porch)) + if (!_dispc_lcd_timings_ok(vm->hsync_len, + vm->hfront_porch, vm->hback_porch, + vm->vsync_len, vm->vfront_porch, + vm->vback_porch)) return false; } @@ -3143,37 +3141,37 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, } static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, - const struct videomode *ovt) + const struct videomode *vm) { u32 timing_h, timing_v, l; bool onoff, rf, ipc, vs, hs, de; - timing_h = FLD_VAL(ovt->hsync_len - 1, dispc.feat->sw_start, 0) | - FLD_VAL(ovt->hfront_porch - 1, dispc.feat->fp_start, 8) | - FLD_VAL(ovt->hback_porch - 1, dispc.feat->bp_start, 20); - timing_v = FLD_VAL(ovt->vsync_len - 1, dispc.feat->sw_start, 0) | - FLD_VAL(ovt->vfront_porch, dispc.feat->fp_start, 8) | - FLD_VAL(ovt->vback_porch, dispc.feat->bp_start, 20); + timing_h = FLD_VAL(vm->hsync_len - 1, dispc.feat->sw_start, 0) | + FLD_VAL(vm->hfront_porch - 1, dispc.feat->fp_start, 8) | + FLD_VAL(vm->hback_porch - 1, dispc.feat->bp_start, 20); + timing_v = FLD_VAL(vm->vsync_len - 1, dispc.feat->sw_start, 0) | + FLD_VAL(vm->vfront_porch, dispc.feat->fp_start, 8) | + FLD_VAL(vm->vback_porch, dispc.feat->bp_start, 20); dispc_write_reg(DISPC_TIMING_H(channel), timing_h); dispc_write_reg(DISPC_TIMING_V(channel), timing_v); - if (ovt->flags & DISPLAY_FLAGS_VSYNC_HIGH) + if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH) vs = false; else vs = true; - if (ovt->flags & DISPLAY_FLAGS_HSYNC_HIGH) + if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH) hs = false; else hs = true; - if (ovt->flags & DISPLAY_FLAGS_DE_HIGH) + if (vm->flags & DISPLAY_FLAGS_DE_HIGH) de = false; else de = true; - if (ovt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) + if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) ipc = false; else ipc = true; @@ -3181,7 +3179,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, /* always use the 'rf' setting */ onoff = true; - if (ovt->flags & DISPLAY_FLAGS_SYNC_POSEDGE) + if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE) rf = true; else rf = false; @@ -3221,11 +3219,11 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, /* change name to mode? */ void dispc_mgr_set_timings(enum omap_channel channel, - const struct videomode *timings) + const struct videomode *vm) { unsigned xtot, ytot; unsigned long ht, vt; - struct videomode t = *timings; + struct videomode t = *vm; DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.vactive); @@ -3240,10 +3238,10 @@ void dispc_mgr_set_timings(enum omap_channel channel, xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hback_porch; ytot = t.vactive + t.vfront_porch + t.vsync_len + t.vback_porch; - ht = timings->pixelclock / xtot; - vt = timings->pixelclock / xtot / ytot; + ht = vm->pixelclock / xtot; + vt = vm->pixelclock / xtot / ytot; - DSSDBG("pck %lu\n", timings->pixelclock); + DSSDBG("pck %lu\n", vm->pixelclock); DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", t.hsync_len, t.hfront_porch, t.hback_porch, t.vsync_len, t.vfront_porch, t.vback_porch); @@ -4185,12 +4183,12 @@ EXPORT_SYMBOL(dispc_free_irq); */ static const struct dispc_errata_i734_data { - struct videomode timings; + struct videomode vm; struct omap_overlay_info ovli; struct omap_overlay_manager_info mgri; struct dss_lcd_mgr_config lcd_conf; } i734 = { - .timings = { + .vm = { .hactive = 8, .vactive = 1, .pixelclock = 16000000, .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4, @@ -4288,7 +4286,7 @@ static void dispc_errata_i734_wa(void) /* Setup and enable GFX plane */ dispc_ovl_set_channel_out(OMAP_DSS_GFX, OMAP_DSS_CHANNEL_LCD); - dispc_ovl_setup(OMAP_DSS_GFX, &ovli, false, &i734.timings, false); + dispc_ovl_setup(OMAP_DSS_GFX, &ovli, false, &i734.vm, false); dispc_ovl_enable(OMAP_DSS_GFX, true); /* Set up and enable display manager for LCD1 */ @@ -4296,7 +4294,7 @@ static void dispc_errata_i734_wa(void) dispc_calc_clock_rates(dss_get_dispc_clk_rate(), &lcd_conf.clock_info); dispc_mgr_set_lcd_config(OMAP_DSS_CHANNEL_LCD, &lcd_conf); - dispc_mgr_set_timings(OMAP_DSS_CHANNEL_LCD, &i734.timings); + dispc_mgr_set_timings(OMAP_DSS_CHANNEL_LCD, &i734.vm); dispc_clear_irqstatus(framedone_irq); diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 56cc071b6223..425a5a8dff8b 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -35,8 +35,8 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { - *xres = dssdev->panel.timings.hactive; - *yres = dssdev->panel.timings.vactive; + *xres = dssdev->panel.vm.hactive; + *yres = dssdev->panel.vm.vactive; } EXPORT_SYMBOL(omapdss_default_get_resolution); @@ -72,9 +72,9 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); void omapdss_default_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { - *timings = dssdev->panel.timings; + *vm = dssdev->panel.vm; } EXPORT_SYMBOL(omapdss_default_get_timings); diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index 178335094288..e75162d26ac0 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c @@ -47,7 +47,7 @@ struct dpi_data { struct mutex lock; - struct videomode timings; + struct videomode vm; struct dss_lcd_mgr_config mgr_config; int data_lines; @@ -333,31 +333,31 @@ static int dpi_set_mode(struct dpi_data *dpi) { struct omap_dss_device *out = &dpi->output; enum omap_channel channel = out->dispc_channel; - struct videomode *t = &dpi->timings; + struct videomode *vm = &dpi->vm; int lck_div = 0, pck_div = 0; unsigned long fck = 0; unsigned long pck; int r = 0; if (dpi->pll) - r = dpi_set_pll_clk(dpi, channel, t->pixelclock, &fck, + r = dpi_set_pll_clk(dpi, channel, vm->pixelclock, &fck, &lck_div, &pck_div); else - r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck, + r = dpi_set_dispc_clk(dpi, vm->pixelclock, &fck, &lck_div, &pck_div); if (r) return r; pck = fck / lck_div / pck_div; - if (pck != t->pixelclock) { + if (pck != vm->pixelclock) { DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n", - t->pixelclock, pck); + vm->pixelclock, pck); - t->pixelclock = pck; + vm->pixelclock = pck; } - dss_mgr_set_timings(channel, t); + dss_mgr_set_timings(channel, vm); return 0; } @@ -476,7 +476,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev) } static void dpi_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); @@ -484,25 +484,25 @@ static void dpi_set_timings(struct omap_dss_device *dssdev, mutex_lock(&dpi->lock); - dpi->timings = *timings; + dpi->vm = *vm; mutex_unlock(&dpi->lock); } static void dpi_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); mutex_lock(&dpi->lock); - *timings = dpi->timings; + *vm = dpi->vm; mutex_unlock(&dpi->lock); } static int dpi_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); enum omap_channel channel = dpi->output.dispc_channel; @@ -512,23 +512,23 @@ static int dpi_check_timings(struct omap_dss_device *dssdev, struct dpi_clk_calc_ctx ctx; bool ok; - if (timings->hactive % 8 != 0) + if (vm->hactive % 8 != 0) return -EINVAL; - if (!dispc_mgr_timings_ok(channel, timings)) + if (!dispc_mgr_timings_ok(channel, vm)) return -EINVAL; - if (timings->pixelclock == 0) + if (vm->pixelclock == 0) return -EINVAL; if (dpi->pll) { - ok = dpi_pll_clk_calc(dpi, timings->pixelclock, &ctx); + ok = dpi_pll_clk_calc(dpi, vm->pixelclock, &ctx); if (!ok) return -EINVAL; fck = ctx.pll_cinfo.clkout[ctx.clkout_idx]; } else { - ok = dpi_dss_clk_calc(timings->pixelclock, &ctx); + ok = dpi_dss_clk_calc(vm->pixelclock, &ctx); if (!ok) return -EINVAL; @@ -540,7 +540,7 @@ static int dpi_check_timings(struct omap_dss_device *dssdev, pck = fck / lck_div / pck_div; - timings->pixelclock = pck; + vm->pixelclock = pck; return 0; } diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 13569cb3f786..f060bda31235 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -289,7 +289,7 @@ struct dsi_clk_calc_ctx { struct dss_pll_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; - struct videomode dispc_vm; + struct videomode vm; struct omap_dss_dsi_videomode_timings dsi_vm; }; @@ -383,7 +383,7 @@ struct dsi_data { unsigned scp_clk_refcount; struct dss_lcd_mgr_config mgr_config; - struct videomode timings; + struct videomode vm; enum omap_dss_dsi_pixel_format pix_fmt; enum omap_dss_dsi_mode mode; struct omap_dss_dsi_videomode_timings vm_timings; @@ -3321,12 +3321,12 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev) if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { int bpp = dsi_get_pixel_size(dsi->pix_fmt); - struct videomode *timings = &dsi->timings; + struct videomode *vm = &dsi->vm; /* * Don't use line buffers if width is greater than the video * port's line buffer size */ - if (dsi->line_buffer_size <= timings->hactive * bpp / 8) + if (dsi->line_buffer_size <= vm->hactive * bpp / 8) num_line_buffers = 0; else num_line_buffers = 2; @@ -3453,7 +3453,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev) int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; int tclk_trail, ths_exit, exiths_clk; bool ddr_alwon; - struct videomode *timings = &dsi->timings; + struct videomode *vm = &dsi->vm; int bpp = dsi_get_pixel_size(dsi->pix_fmt); int ndl = dsi->num_lanes_used - 1; int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1; @@ -3494,7 +3494,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev) exiths_clk = ths_exit + tclk_trail; - width_bytes = DIV_ROUND_UP(timings->hactive * bpp, 8); + width_bytes = DIV_ROUND_UP(vm->hactive * bpp, 8); bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl); if (!hsa_blanking_mode) { @@ -3705,7 +3705,7 @@ static void dsi_proto_timings(struct platform_device *dsidev) int vbp = dsi->vm_timings.vbp; int window_sync = dsi->vm_timings.window_sync; bool hsync_end; - struct videomode *timings = &dsi->timings; + struct videomode *vm = &dsi->vm; int bpp = dsi_get_pixel_size(dsi->pix_fmt); int tl, t_he, width_bytes; @@ -3713,7 +3713,7 @@ static void dsi_proto_timings(struct platform_device *dsidev) t_he = hsync_end ? ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; - width_bytes = DIV_ROUND_UP(timings->hactive * bpp, 8); + width_bytes = DIV_ROUND_UP(vm->hactive * bpp, 8); /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */ tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp + @@ -3722,7 +3722,7 @@ static void dsi_proto_timings(struct platform_device *dsidev) DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp, hfp, hsync_end ? hsa : 0, tl); DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp, - vsa, timings->vactive); + vsa, vm->vactive); r = dsi_read_reg(dsidev, DSI_VM_TIMING1); r = FLD_MOD(r, hbp, 11, 0); /* HBP */ @@ -3738,7 +3738,7 @@ static void dsi_proto_timings(struct platform_device *dsidev) dsi_write_reg(dsidev, DSI_VM_TIMING2, r); r = dsi_read_reg(dsidev, DSI_VM_TIMING3); - r = FLD_MOD(r, timings->vactive, 14, 0); /* VACT */ + r = FLD_MOD(r, vm->vactive, 14, 0); /* VACT */ r = FLD_MOD(r, tl, 31, 16); /* TL */ dsi_write_reg(dsidev, DSI_VM_TIMING3, r); } @@ -3856,7 +3856,7 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) /* MODE, 1 = video mode */ REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); - word_count = DIV_ROUND_UP(dsi->timings.hactive * bpp, 8); + word_count = DIV_ROUND_UP(dsi->vm.hactive * bpp, 8); dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); @@ -3918,8 +3918,8 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev) int r; const unsigned channel = dsi->update_channel; const unsigned line_buf_size = dsi->line_buffer_size; - u16 w = dsi->timings.hactive; - u16 h = dsi->timings.vactive; + u16 w = dsi->vm.hactive; + u16 h = dsi->vm.vactive; DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); @@ -3969,7 +3969,7 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev) msecs_to_jiffies(250)); BUG_ON(r == 0); - dss_mgr_set_timings(dispc_channel, &dsi->timings); + dss_mgr_set_timings(dispc_channel, &dsi->vm); dss_mgr_start_update(dispc_channel); @@ -4056,8 +4056,8 @@ static int dsi_update(struct omap_dss_device *dssdev, int channel, dsi->framedone_callback = callback; dsi->framedone_data = data; - dw = dsi->timings.hactive; - dh = dsi->timings.vactive; + dw = dsi->vm.hactive; + dh = dsi->vm.vactive; #ifdef DSI_PERF_MEASURE dsi->update_bytes = dw * dh * @@ -4122,19 +4122,19 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, * override interlace, logic level and edge related parameters in * videomode with default values */ - dsi->timings.flags &= ~DISPLAY_FLAGS_INTERLACED; - dsi->timings.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; - dsi->timings.flags |= DISPLAY_FLAGS_HSYNC_HIGH; - dsi->timings.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; - dsi->timings.flags |= DISPLAY_FLAGS_VSYNC_HIGH; - dsi->timings.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; - dsi->timings.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; - dsi->timings.flags &= ~DISPLAY_FLAGS_DE_LOW; - dsi->timings.flags |= DISPLAY_FLAGS_DE_HIGH; - dsi->timings.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; - dsi->timings.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; - - dss_mgr_set_timings(channel, &dsi->timings); + dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED; + dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; + dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; + dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; + dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; + dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; + dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; + dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW; + dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH; + dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; + dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; + + dss_mgr_set_timings(channel, &dsi->vm); r = dsi_configure_dispc_clocks(dsidev); if (r) @@ -4361,13 +4361,13 @@ static void print_dsi_vm(const char *str, #undef TO_DSI_T } -static void print_dispc_vm(const char *str, const struct videomode *t) +static void print_dispc_vm(const char *str, const struct videomode *vm) { - unsigned long pck = t->pixelclock; + unsigned long pck = vm->pixelclock; int hact, bl, tot; - hact = t->hactive; - bl = t->hsync_len + t->hbp + t->hfront_porch; + hact = vm->hactive; + bl = vm->hsync_len + vm->hbp + vm->hfront_porch; tot = hact + bl; #define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck)) @@ -4376,12 +4376,12 @@ static void print_dispc_vm(const char *str, const struct videomode *t) "%u/%u/%u/%u = %u + %u = %u\n", str, pck, - t->hsync_len, t->hbp, hact, t->hfront_porch, + vm->hsync_len, vm->hbp, hact, vm->hfront_porch, bl, hact, tot, - TO_DISPC_T(t->hsync_len), - TO_DISPC_T(t->hbp), + TO_DISPC_T(vm->hsync_len), + TO_DISPC_T(vm->hbp), TO_DISPC_T(hact), - TO_DISPC_T(t->hfront_porch), + TO_DISPC_T(vm->hfront_porch), TO_DISPC_T(bl), TO_DISPC_T(hact), TO_DISPC_T(tot)); @@ -4417,19 +4417,19 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, unsigned long pck, void *data) { struct dsi_clk_calc_ctx *ctx = data; - struct videomode *t = &ctx->dispc_vm; + struct videomode *vm = &ctx->vm; ctx->dispc_cinfo.lck_div = lckd; ctx->dispc_cinfo.pck_div = pckd; ctx->dispc_cinfo.lck = lck; ctx->dispc_cinfo.pck = pck; - *t = *ctx->config->timings; - t->pixelclock = pck; - t->hactive = ctx->config->timings->hactive; - t->vactive = ctx->config->timings->vactive; - t->hsync_len = t->hfront_porch = t->hback_porch = t->vsync_len = 1; - t->vfront_porch = t->vback_porch = 0; + *vm = *ctx->config->vm; + vm->pixelclock = pck; + vm->hactive = ctx->config->vm->hactive; + vm->vactive = ctx->config->vm->vactive; + vm->hsync_len = vm->hfront_porch = vm->hback_porch = vm->vsync_len = 1; + vm->vfront_porch = vm->vback_porch = 0; return true; } @@ -4480,7 +4480,7 @@ static bool dsi_cm_calc(struct dsi_data *dsi, * especially as we go to LP between each pixel packet due to HW * "feature". So let's just estimate very roughly and multiply by 1.5. */ - pck = cfg->timings->pixelclock; + pck = cfg->vm->pixelclock; pck = pck * 3 / 2; txbyteclk = pck * bitspp / 8 / ndl; @@ -4522,7 +4522,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) dsi_tput = (u64)byteclk * ndl * 8; - req_vm = cfg->timings; + req_vm = cfg->vm; req_pck_min = ctx->req_pck_min; req_pck_max = ctx->req_pck_max; req_pck_nom = ctx->req_pck_nom; @@ -4656,7 +4656,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) /* setup DISPC videomode */ - dispc_vm = &ctx->dispc_vm; + dispc_vm = &ctx->vm; *dispc_vm = *req_vm; dispc_vm->pixelclock = dispc_pck; @@ -4713,9 +4713,9 @@ static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, return false; #ifdef PRINT_VERBOSE_VM_TIMINGS - print_dispc_vm("dispc", &ctx->dispc_vm); + print_dispc_vm("dispc", &ctx->vm); print_dsi_vm("dsi ", &ctx->dsi_vm); - print_dispc_vm("req ", ctx->config->timings); + print_dispc_vm("req ", ctx->config->vm); print_dsi_dispc_vm("act ", &ctx->dsi_vm); #endif @@ -4764,7 +4764,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi, const struct omap_dss_dsi_config *cfg, struct dsi_clk_calc_ctx *ctx) { - const struct videomode *t = cfg->timings; + const struct videomode *vm = cfg->vm; unsigned long clkin; unsigned long pll_min; unsigned long pll_max; @@ -4780,9 +4780,9 @@ static bool dsi_vm_calc(struct dsi_data *dsi, ctx->config = cfg; /* these limits should come from the panel driver */ - ctx->req_pck_min = t->pixelclock - 1000; - ctx->req_pck_nom = t->pixelclock; - ctx->req_pck_max = t->pixelclock + 1000; + ctx->req_pck_min = vm->pixelclock - 1000; + ctx->req_pck_nom = vm->pixelclock; + ctx->req_pck_max = vm->pixelclock + 1000; byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8); pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4); @@ -4839,7 +4839,7 @@ static int dsi_set_config(struct omap_dss_device *dssdev, dsi->user_dsi_cinfo = ctx.dsi_cinfo; dsi->user_dispc_cinfo = ctx.dispc_cinfo; - dsi->timings = ctx.dispc_vm; + dsi->vm = ctx.vm; dsi->vm_timings = ctx.dsi_vm; mutex_unlock(&dsi->lock); diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index 384267591b12..56493b290731 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -366,8 +366,7 @@ bool dispc_div_calc(unsigned long dispc, unsigned long pck_min, unsigned long pck_max, dispc_div_calc_func func, void *data); -bool dispc_mgr_timings_ok(enum omap_channel channel, - const struct videomode *timings); +bool dispc_mgr_timings_ok(enum omap_channel channel, const struct videomode *vm); int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, struct dispc_clock_info *cinfo); @@ -390,7 +389,7 @@ void dispc_wb_enable(bool enable); bool dispc_wb_is_enabled(void); void dispc_wb_set_channel_in(enum dss_writeback_channel channel); int dispc_wb_setup(const struct omap_dss_writeback_info *wi, - bool mem_to_mem, const struct videomode *timings); + bool mem_to_mem, const struct videomode *vm); /* VENC */ int venc_init_platform_driver(void) __init; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h index b97ee6702e6f..fb6cccd02374 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h @@ -181,7 +181,7 @@ struct hdmi_video_format { }; struct hdmi_config { - struct videomode timings; + struct videomode vm; struct hdmi_avi_infoframe infoframe; enum hdmi_core_hdmi_dvi hdmi_dvi_mode; }; @@ -298,11 +298,11 @@ int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val); void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, struct hdmi_video_format *video_fmt); void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, - struct videomode *timings); + struct videomode *vm); void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, - struct videomode *timings); + struct videomode *vm); void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, - struct videomode *timings, struct hdmi_config *param); + struct videomode *vm, struct hdmi_config *param); int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index a53dfd0bc3b3..e7162c16de2e 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -155,7 +155,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev) static int hdmi_power_on_full(struct omap_dss_device *dssdev) { int r; - struct videomode *p; + struct videomode *vm; enum omap_channel channel = dssdev->dispc_channel; struct hdmi_wp_data *wp = &hdmi.wp; struct dss_pll_clock_info hdmi_cinfo = { 0 }; @@ -169,13 +169,13 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) hdmi_wp_clear_irqenable(wp, 0xffffffff); hdmi_wp_set_irqstatus(wp, 0xffffffff); - p = &hdmi.cfg.timings; + vm = &hdmi.cfg.vm; - DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", p->hactive, - p->vactive); + DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", vm->hactive, + vm->vactive); - pc = p->pixelclock; - if (p->flags & DISPLAY_FLAGS_DOUBLECLK) + pc = vm->pixelclock; + if (vm->flags & DISPLAY_FLAGS_DOUBLECLK) pc *= 2; /* DSS_HDMI_TCLK is bitclk / 10 */ @@ -210,7 +210,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); /* tv size */ - dss_mgr_set_timings(channel, p); + dss_mgr_set_timings(channel, vm); r = dss_mgr_enable(channel); if (r) @@ -256,30 +256,30 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev) } static int hdmi_display_check_timing(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { - if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings)) + if (!dispc_mgr_timings_ok(dssdev->dispc_channel, vm)) return -EINVAL; return 0; } static void hdmi_display_set_timing(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { mutex_lock(&hdmi.lock); - hdmi.cfg.timings = *timings; + hdmi.cfg.vm = *vm; - dispc_set_tv_pclk(timings->pixelclock); + dispc_set_tv_pclk(vm->pixelclock); mutex_unlock(&hdmi.lock); } static void hdmi_display_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { - *timings = hdmi.cfg.timings; + *vm = hdmi.cfg.vm; } static void hdmi_dump_regs(struct seq_file *s) @@ -353,7 +353,7 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev) if (hdmi.audio_configured) { r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config, - hdmi.cfg.timings.pixelclock); + hdmi.cfg.vm.pixelclock); if (r) { DSSERR("Error restoring audio configuration: %d", r); hdmi.audio_abort_cb(&hdmi.pdev->dev); @@ -644,7 +644,7 @@ static int hdmi_audio_config(struct device *dev, } ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio, - hd->cfg.timings.pixelclock); + hd->cfg.vm.pixelclock); if (!ret) { hd->audio_configured = true; hd->audio_config = *dss_audio; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index 505cfee892aa..e05b7ac4f7dd 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -310,7 +310,7 @@ void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg) { /* HDMI */ - struct videomode video_timing; + struct videomode vm; struct hdmi_video_format video_format; /* HDMI core */ struct hdmi_core_video_config v_core_cfg; @@ -318,16 +318,16 @@ void hdmi4_configure(struct hdmi_core_data *core, hdmi_core_init(&v_core_cfg); - hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg); + hdmi_wp_init_vid_fmt_timings(&video_format, &vm, cfg); - hdmi_wp_video_config_timing(wp, &video_timing); + hdmi_wp_video_config_timing(wp, &vm); /* video config */ video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; hdmi_wp_video_config_format(wp, &video_format); - hdmi_wp_video_config_interface(wp, &video_timing); + hdmi_wp_video_config_interface(wp, &vm); /* * configure core video part diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 880f67ae6e9b..678dfb02764a 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -172,7 +172,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev) static int hdmi_power_on_full(struct omap_dss_device *dssdev) { int r; - struct videomode *p; + struct videomode *vm; enum omap_channel channel = dssdev->dispc_channel; struct dss_pll_clock_info hdmi_cinfo = { 0 }; unsigned pc; @@ -181,13 +181,13 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) if (r) return r; - p = &hdmi.cfg.timings; + vm = &hdmi.cfg.vm; - DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", p->hactive, - p->vactive); + DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", vm->hactive, + vm->vactive); - pc = p->pixelclock; - if (p->flags & DISPLAY_FLAGS_DOUBLECLK) + pc = vm->pixelclock; + if (vm->flags & DISPLAY_FLAGS_DOUBLECLK) pc *= 2; /* DSS_HDMI_TCLK is bitclk / 10 */ @@ -227,7 +227,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); /* tv size */ - dss_mgr_set_timings(channel, p); + dss_mgr_set_timings(channel, vm); r = dss_mgr_enable(channel); if (r) @@ -273,30 +273,30 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev) } static int hdmi_display_check_timing(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { - if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings)) + if (!dispc_mgr_timings_ok(dssdev->dispc_channel, vm)) return -EINVAL; return 0; } static void hdmi_display_set_timing(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { mutex_lock(&hdmi.lock); - hdmi.cfg.timings = *timings; + hdmi.cfg.vm = *vm; - dispc_set_tv_pclk(timings->pixelclock); + dispc_set_tv_pclk(vm->pixelclock); mutex_unlock(&hdmi.lock); } static void hdmi_display_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { - *timings = hdmi.cfg.timings; + *vm = hdmi.cfg.vm; } static void hdmi_dump_regs(struct seq_file *s) @@ -379,7 +379,7 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev) if (hdmi.audio_configured) { r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config, - hdmi.cfg.timings.pixelclock); + hdmi.cfg.vm.pixelclock); if (r) { DSSERR("Error restoring audio configuration: %d", r); hdmi.audio_abort_cb(&hdmi.pdev->dev); @@ -670,7 +670,7 @@ static int hdmi_audio_config(struct device *dev, } ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio, - hd->cfg.timings.pixelclock); + hd->cfg.vm.pixelclock); if (!ret) { hd->audio_configured = true; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index a5ac9318a11d..8de1d7b2ae55 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -292,35 +292,35 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, { DSSDBG("hdmi_core_init\n"); - video_cfg->v_fc_config.timings = cfg->timings; + video_cfg->v_fc_config.vm = cfg->vm; /* video core */ video_cfg->data_enable_pol = 1; /* It is always 1*/ - video_cfg->hblank = cfg->timings.hfront_porch + - cfg->timings.hback_porch + cfg->timings.hsync_len; + video_cfg->hblank = cfg->vm.hfront_porch + + cfg->vm.hback_porch + cfg->vm.hsync_len; video_cfg->vblank_osc = 0; - video_cfg->vblank = cfg->timings.vsync_len + cfg->timings.vfront_porch + - cfg->timings.vback_porch; + video_cfg->vblank = cfg->vm.vsync_len + cfg->vm.vfront_porch + + cfg->vm.vback_porch; video_cfg->v_fc_config.hdmi_dvi_mode = cfg->hdmi_dvi_mode; - if (cfg->timings.flags & DISPLAY_FLAGS_INTERLACED) { + if (cfg->vm.flags & DISPLAY_FLAGS_INTERLACED) { /* set vblank_osc if vblank is fractional */ if (video_cfg->vblank % 2 != 0) video_cfg->vblank_osc = 1; - video_cfg->v_fc_config.timings.vactive /= 2; + video_cfg->v_fc_config.vm.vactive /= 2; video_cfg->vblank /= 2; - video_cfg->v_fc_config.timings.vfront_porch /= 2; - video_cfg->v_fc_config.timings.vsync_len /= 2; - video_cfg->v_fc_config.timings.vback_porch /= 2; + video_cfg->v_fc_config.vm.vfront_porch /= 2; + video_cfg->v_fc_config.vm.vsync_len /= 2; + video_cfg->v_fc_config.vm.vback_porch /= 2; } - if (cfg->timings.flags & DISPLAY_FLAGS_DOUBLECLK) { - video_cfg->v_fc_config.timings.hactive *= 2; + if (cfg->vm.flags & DISPLAY_FLAGS_DOUBLECLK) { + video_cfg->v_fc_config.vm.hactive *= 2; video_cfg->hblank *= 2; - video_cfg->v_fc_config.timings.hfront_porch *= 2; - video_cfg->v_fc_config.timings.hsync_len *= 2; - video_cfg->v_fc_config.timings.hback_porch *= 2; + video_cfg->v_fc_config.vm.hfront_porch *= 2; + video_cfg->v_fc_config.vm.hsync_len *= 2; + video_cfg->v_fc_config.vm.hback_porch *= 2; } } @@ -329,12 +329,12 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, struct hdmi_core_vid_config *cfg) { void __iomem *base = core->base; - struct videomode *ovt = &cfg->v_fc_config.timings; + struct videomode *vm = &cfg->v_fc_config.vm; unsigned char r = 0; bool vsync_pol, hsync_pol; - vsync_pol = !!(ovt->flags & DISPLAY_FLAGS_VSYNC_HIGH); - hsync_pol = !!(ovt->flags & DISPLAY_FLAGS_HSYNC_HIGH); + vsync_pol = !!(vm->flags & DISPLAY_FLAGS_VSYNC_HIGH); + hsync_pol = !!(vm->flags & DISPLAY_FLAGS_HSYNC_HIGH); /* Set hsync, vsync and data-enable polarity */ r = hdmi_read_reg(base, HDMI_CORE_FC_INVIDCONF); @@ -342,16 +342,16 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, r = FLD_MOD(r, hsync_pol, 5, 5); r = FLD_MOD(r, cfg->data_enable_pol, 4, 4); r = FLD_MOD(r, cfg->vblank_osc, 1, 1); - r = FLD_MOD(r, !!(ovt->flags & DISPLAY_FLAGS_INTERLACED), 0, 0); + r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 0, 0); hdmi_write_reg(base, HDMI_CORE_FC_INVIDCONF, r); /* set x resolution */ - REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1, ovt->hactive >> 8, 4, 0); - REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0, ovt->hactive & 0xFF, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1, vm->hactive >> 8, 4, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0, vm->hactive & 0xFF, 7, 0); /* set y resolution */ - REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, ovt->vactive >> 8, 4, 0); - REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0, ovt->vactive & 0xFF, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, vm->vactive >> 8, 4, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0, vm->vactive & 0xFF, 7, 0); /* set horizontal blanking pixels */ REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK1, cfg->hblank >> 8, 4, 0); @@ -361,28 +361,28 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, REG_FLD_MOD(base, HDMI_CORE_FC_INVBLANK, cfg->vblank, 7, 0); /* set horizontal sync offset */ - REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1, ovt->hfront_porch >> 8, + REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1, vm->hfront_porch >> 8, 4, 0); - REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0, ovt->hfront_porch & 0xFF, + REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0, vm->hfront_porch & 0xFF, 7, 0); /* set vertical sync offset */ - REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, ovt->vfront_porch, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, vm->vfront_porch, 7, 0); /* set horizontal sync pulse width */ - REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, (ovt->hsync_len >> 8), + REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, (vm->hsync_len >> 8), 1, 0); - REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0, ovt->hsync_len & 0xFF, + REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0, vm->hsync_len & 0xFF, 7, 0); /* set vertical sync pulse width */ - REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, ovt->vsync_len, 5, 0); + REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, vm->vsync_len, 5, 0); /* select DVI mode */ REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF, cfg->v_fc_config.hdmi_dvi_mode, 3, 3); - if (ovt->flags & DISPLAY_FLAGS_DOUBLECLK) + if (vm->flags & DISPLAY_FLAGS_DOUBLECLK) REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 2, 7, 4); else REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 1, 7, 4); @@ -609,7 +609,7 @@ int hdmi5_core_handle_irqs(struct hdmi_core_data *core) void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg) { - struct videomode video_timing; + struct videomode vm; struct hdmi_video_format video_format; struct hdmi_core_vid_config v_core_cfg; @@ -617,16 +617,16 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, hdmi_core_init(&v_core_cfg, cfg); - hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg); + hdmi_wp_init_vid_fmt_timings(&video_format, &vm, cfg); - hdmi_wp_video_config_timing(wp, &video_timing); + hdmi_wp_video_config_timing(wp, &vm); /* video config */ video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; hdmi_wp_video_config_format(wp, &video_format); - hdmi_wp_video_config_interface(wp, &video_timing); + hdmi_wp_video_config_interface(wp, &vm); /* support limited range with 24 bit color depth for now */ hdmi_core_configure_range(core); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index b490e335b3df..b783d5a0750e 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -144,25 +144,25 @@ void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, } void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, - struct videomode *timings) + struct videomode *vm) { u32 r; bool vsync_pol, hsync_pol; DSSDBG("Enter hdmi_wp_video_config_interface\n"); - vsync_pol = !!(timings->flags & DISPLAY_FLAGS_VSYNC_HIGH); - hsync_pol = !!(timings->flags & DISPLAY_FLAGS_HSYNC_HIGH); + vsync_pol = !!(vm->flags & DISPLAY_FLAGS_VSYNC_HIGH); + hsync_pol = !!(vm->flags & DISPLAY_FLAGS_HSYNC_HIGH); r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG); r = FLD_MOD(r, vsync_pol, 7, 7); r = FLD_MOD(r, hsync_pol, 6, 6); - r = FLD_MOD(r, !!(timings->flags & DISPLAY_FLAGS_INTERLACED), 3, 3); + r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 3, 3); r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r); } void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, - struct videomode *timings) + struct videomode *vm) { u32 timing_h = 0; u32 timing_v = 0; @@ -181,47 +181,47 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, omapdss_get_version() == OMAPDSS_VER_OMAP4) hsync_len_offset = 0; - timing_h |= FLD_VAL(timings->hback_porch, 31, 20); - timing_h |= FLD_VAL(timings->hfront_porch, 19, 8); - timing_h |= FLD_VAL(timings->hsync_len - hsync_len_offset, 7, 0); + timing_h |= FLD_VAL(vm->hback_porch, 31, 20); + timing_h |= FLD_VAL(vm->hfront_porch, 19, 8); + timing_h |= FLD_VAL(vm->hsync_len - hsync_len_offset, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h); - timing_v |= FLD_VAL(timings->vback_porch, 31, 20); - timing_v |= FLD_VAL(timings->vfront_porch, 19, 8); - timing_v |= FLD_VAL(timings->vsync_len, 7, 0); + timing_v |= FLD_VAL(vm->vback_porch, 31, 20); + timing_v |= FLD_VAL(vm->vfront_porch, 19, 8); + timing_v |= FLD_VAL(vm->vsync_len, 7, 0); hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v); } void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, - struct videomode *timings, struct hdmi_config *param) + struct videomode *vm, struct hdmi_config *param) { DSSDBG("Enter hdmi_wp_video_init_format\n"); video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; - video_fmt->y_res = param->timings.vactive; - video_fmt->x_res = param->timings.hactive; + video_fmt->y_res = param->vm.vactive; + video_fmt->x_res = param->vm.hactive; - timings->hback_porch = param->timings.hback_porch; - timings->hfront_porch = param->timings.hfront_porch; - timings->hsync_len = param->timings.hsync_len; - timings->vback_porch = param->timings.vback_porch; - timings->vfront_porch = param->timings.vfront_porch; - timings->vsync_len = param->timings.vsync_len; + vm->hback_porch = param->vm.hback_porch; + vm->hfront_porch = param->vm.hfront_porch; + vm->hsync_len = param->vm.hsync_len; + vm->vback_porch = param->vm.vback_porch; + vm->vfront_porch = param->vm.vfront_porch; + vm->vsync_len = param->vm.vsync_len; - timings->flags = param->timings.flags; + vm->flags = param->vm.flags; - if (param->timings.flags & DISPLAY_FLAGS_INTERLACED) { + if (param->vm.flags & DISPLAY_FLAGS_INTERLACED) { video_fmt->y_res /= 2; - timings->vback_porch /= 2; - timings->vfront_porch /= 2; - timings->vsync_len /= 2; + vm->vback_porch /= 2; + vm->vfront_porch /= 2; + vm->vsync_len /= 2; } - if (param->timings.flags & DISPLAY_FLAGS_DOUBLECLK) { + if (param->vm.flags & DISPLAY_FLAGS_DOUBLECLK) { video_fmt->x_res *= 2; - timings->hfront_porch *= 2; - timings->hsync_len *= 2; - timings->hback_porch *= 2; + vm->hfront_porch *= 2; + vm->hsync_len *= 2; + vm->hback_porch *= 2; } } diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 54e88ee3ef8e..b420dde8c0fb 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -290,7 +290,7 @@ struct omap_dss_dsi_videomode_timings { struct omap_dss_dsi_config { enum omap_dss_dsi_mode mode; enum omap_dss_dsi_pixel_format pixel_format; - const struct videomode *timings; + const struct videomode *vm; unsigned long hs_clk_min, hs_clk_max; unsigned long lp_clk_min, lp_clk_max; @@ -299,12 +299,12 @@ struct omap_dss_dsi_config { enum omap_dss_dsi_trans_mode trans_mode; }; -/* Hardcoded timings for tv modes. Venc only uses these to +/* Hardcoded videomodes for tv. Venc only uses these to * identify the mode, and does not actually use the configs * itself. However, the configs should be something that * a normal monitor can also show */ -extern const struct videomode omap_dss_pal_timings; -extern const struct videomode omap_dss_ntsc_timings; +extern const struct videomode omap_dss_pal_vm; +extern const struct videomode omap_dss_ntsc_vm; struct omap_dss_cpr_coefs { s16 rr, rg, rb; @@ -466,11 +466,11 @@ struct omapdss_dpi_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*get_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_data_lines)(struct omap_dss_device *dssdev, int data_lines); }; @@ -485,11 +485,11 @@ struct omapdss_sdi_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*get_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_datapairs)(struct omap_dss_device *dssdev, int datapairs); }; @@ -504,11 +504,11 @@ struct omapdss_dvi_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*get_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); }; struct omapdss_atv_ops { @@ -521,11 +521,11 @@ struct omapdss_atv_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*get_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_type)(struct omap_dss_device *dssdev, enum omap_dss_venc_type type); @@ -546,11 +546,11 @@ struct omapdss_hdmi_ops { void (*disable)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*get_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); bool (*detect)(struct omap_dss_device *dssdev); @@ -656,7 +656,7 @@ struct omap_dss_device { } phy; struct { - struct videomode timings; + struct videomode vm; enum omap_dss_dsi_pixel_format dsi_pix_fmt; enum omap_dss_dsi_mode dsi_mode; @@ -749,11 +749,11 @@ struct omap_dss_driver { int (*get_recommended_bpp)(struct omap_dss_device *dssdev); int (*check_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*set_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); void (*get_timings)(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); u32 (*get_wss)(struct omap_dss_device *dssdev); @@ -811,7 +811,7 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres); int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); void omapdss_default_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings); + struct videomode *vm); typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); @@ -865,7 +865,7 @@ void dispc_mgr_go(enum omap_channel channel); void dispc_mgr_set_lcd_config(enum omap_channel channel, const struct dss_lcd_mgr_config *config); void dispc_mgr_set_timings(enum omap_channel channel, - const struct videomode *timings); + const struct videomode *vm); void dispc_mgr_setup(enum omap_channel channel, const struct omap_overlay_manager_info *info); u32 dispc_mgr_gamma_size(enum omap_channel channel); @@ -878,8 +878,7 @@ bool dispc_ovl_enabled(enum omap_plane plane); void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel); int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, - bool replication, const struct videomode *mgr_timings, - bool mem_to_mem); + bool replication, const struct videomode *vm, bool mem_to_mem); enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel); @@ -893,7 +892,7 @@ struct dss_mgr_ops { int (*enable)(enum omap_channel channel); void (*disable)(enum omap_channel channel); void (*set_timings)(enum omap_channel channel, - const struct videomode *timings); + const struct videomode *vm); void (*set_lcd_config)(enum omap_channel channel, const struct dss_lcd_mgr_config *config); int (*register_framedone_handler)(enum omap_channel channel, @@ -910,7 +909,7 @@ int dss_mgr_connect(enum omap_channel channel, void dss_mgr_disconnect(enum omap_channel channel, struct omap_dss_device *dst); void dss_mgr_set_timings(enum omap_channel channel, - const struct videomode *timings); + const struct videomode *vm); void dss_mgr_set_lcd_config(enum omap_channel channel, const struct dss_lcd_mgr_config *config); int dss_mgr_enable(enum omap_channel channel); diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c index 28fc5c159066..a901af5a9bc3 100644 --- a/drivers/gpu/drm/omapdrm/dss/output.c +++ b/drivers/gpu/drm/omapdrm/dss/output.c @@ -201,10 +201,9 @@ void dss_mgr_disconnect(enum omap_channel channel, } EXPORT_SYMBOL(dss_mgr_disconnect); -void dss_mgr_set_timings(enum omap_channel channel, - const struct videomode *timings) +void dss_mgr_set_timings(enum omap_channel channel, const struct videomode *vm) { - dss_mgr_ops->set_timings(channel, timings); + dss_mgr_ops->set_timings(channel, vm); } EXPORT_SYMBOL(dss_mgr_set_timings); diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c index a08734ae2253..09724757366a 100644 --- a/drivers/gpu/drm/omapdrm/dss/rfbi.c +++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c @@ -113,7 +113,7 @@ static struct { struct semaphore bus_lock; - struct videomode timings; + struct videomode vm; int pixel_size; int data_lines; struct rfbi_timings intf_timings; @@ -308,15 +308,15 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev, u32 l; int r; struct omap_overlay_manager *mgr = rfbi.output.manager; - u16 width = rfbi.timings.hactive; - u16 height = rfbi.timings.vactive; + u16 width = rfbi.vm.hactive; + u16 height = rfbi.vm.vactive; /*BUG_ON(callback == 0);*/ BUG_ON(rfbi.framedone_callback != NULL); DSSDBG("rfbi_transfer_area %dx%d\n", width, height); - dss_mgr_set_timings(mgr, &rfbi.timings); + dss_mgr_set_timings(mgr, &rfbi.vm); r = dss_mgr_enable(mgr); if (r) @@ -777,8 +777,8 @@ static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *), static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) { - rfbi.timings.hactive = w; - rfbi.timings.vactive = h; + rfbi.vm.hactive = w; + rfbi.vm.vactive = h; } static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size) @@ -858,26 +858,26 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) * are expected to be already configured by the panel driver via * omapdss_rfbi_set_size() */ - rfbi.timings.hsync_len = 1; - rfbi.timings.hfront_porch = 1; - rfbi.timings.hback_porch = 1; - rfbi.timings.vsync_len = 1; - rfbi.timings.vfront_porch = 0; - rfbi.timings.vback_porch = 0; - - rfbi.timings.flags &= ~DISPLAY_FLAGS_INTERLACED; - rfbi.timings.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; - rfbi.timings.flags |= DISPLAY_FLAGS_HSYNC_HIGH; - rfbi.timings.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; - rfbi.timings.flags |= DISPLAY_FLAGS_VSYNC_HIGH; - rfbi.timings.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; - rfbi.timings.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; - rfbi.timings.flags &= ~DISPLAY_FLAGS_DE_LOW; - rfbi.timings.flags |= DISPLAY_FLAGS_DE_HIGH; - rfbi.timings.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; - rfbi.timings.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; - - dss_mgr_set_timings(mgr, &rfbi.timings); + rfbi.vm.hsync_len = 1; + rfbi.vm.hfront_porch = 1; + rfbi.vm.hback_porch = 1; + rfbi.vm.vsync_len = 1; + rfbi.vm.vfront_porch = 0; + rfbi.vm.vback_porch = 0; + + rfbi.vm.flags &= ~DISPLAY_FLAGS_INTERLACED; + rfbi.vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; + rfbi.vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; + rfbi.vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; + rfbi.vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; + rfbi.vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; + rfbi.vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; + rfbi.vm.flags &= ~DISPLAY_FLAGS_DE_LOW; + rfbi.vm.flags |= DISPLAY_FLAGS_DE_HIGH; + rfbi.vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; + rfbi.vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; + + dss_mgr_set_timings(mgr, &rfbi.vm); } static int rfbi_display_enable(struct omap_dss_device *dssdev) diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index e2f2d6b2aa76..b3bda2d3c08d 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c @@ -39,7 +39,7 @@ static struct { struct regulator *vdds_sdi_reg; struct dss_lcd_mgr_config mgr_config; - struct videomode timings; + struct videomode vm; int datapairs; struct omap_dss_device output; @@ -131,7 +131,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) { struct omap_dss_device *out = &sdi.output; enum omap_channel channel = dssdev->dispc_channel; - struct videomode *t = &sdi.timings; + struct videomode *vm = &sdi.vm; unsigned long fck; struct dispc_clock_info dispc_cinfo; unsigned long pck; @@ -151,9 +151,9 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) goto err_get_dispc; /* 15.5.9.1.2 */ - t->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_POSEDGE; + vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_POSEDGE; - r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo); + r = sdi_calc_clock_div(vm->pixelclock, &fck, &dispc_cinfo); if (r) goto err_calc_clock_div; @@ -161,15 +161,15 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div; - if (pck != t->pixelclock) { + if (pck != vm->pixelclock) { DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n", - t->pixelclock, pck); + vm->pixelclock, pck); - t->pixelclock = pck; + vm->pixelclock = pck; } - dss_mgr_set_timings(channel, t); + dss_mgr_set_timings(channel, vm); r = dss_set_fck_rate(fck); if (r) @@ -228,26 +228,26 @@ static void sdi_display_disable(struct omap_dss_device *dssdev) } static void sdi_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { - sdi.timings = *timings; + sdi.vm = *vm; } static void sdi_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { - *timings = sdi.timings; + *vm = sdi.vm; } static int sdi_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { enum omap_channel channel = dssdev->dispc_channel; - if (!dispc_mgr_timings_ok(channel, timings)) + if (!dispc_mgr_timings_ok(channel, vm)) return -EINVAL; - if (timings->pixelclock == 0) + if (vm->pixelclock == 0) return -EINVAL; return 0; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 68a04a8753b0..d74f7fcc2e46 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -262,7 +262,7 @@ static const struct venc_config venc_config_pal_bdghi = { .fid_ext_start_y__fid_ext_offset_y = 0x01380005, }; -const struct videomode omap_dss_pal_timings = { +const struct videomode omap_dss_pal_vm = { .hactive = 720, .vactive = 574, .pixelclock = 13500000, @@ -278,9 +278,9 @@ const struct videomode omap_dss_pal_timings = { DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_NEGEDGE, }; -EXPORT_SYMBOL(omap_dss_pal_timings); +EXPORT_SYMBOL(omap_dss_pal_vm); -const struct videomode omap_dss_ntsc_timings = { +const struct videomode omap_dss_ntsc_vm = { .hactive = 720, .vactive = 482, .pixelclock = 13500000, @@ -296,7 +296,7 @@ const struct videomode omap_dss_ntsc_timings = { DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_NEGEDGE, }; -EXPORT_SYMBOL(omap_dss_ntsc_timings); +EXPORT_SYMBOL(omap_dss_ntsc_vm); static struct { struct platform_device *pdev; @@ -307,7 +307,7 @@ static struct { struct clk *tv_dac_clk; - struct videomode timings; + struct videomode vm; enum omap_dss_venc_type type; bool invert_polarity; @@ -421,13 +421,12 @@ static void venc_runtime_put(void) WARN_ON(r < 0 && r != -ENOSYS); } -static const struct venc_config *venc_timings_to_config( - struct videomode *timings) +static const struct venc_config *venc_timings_to_config(struct videomode *vm) { - if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) + if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0) return &venc_config_pal_trm; - if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) + if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0) return &venc_config_ntsc_trm; BUG(); @@ -445,7 +444,7 @@ static int venc_power_on(struct omap_dss_device *dssdev) goto err0; venc_reset(); - venc_write_config(venc_timings_to_config(&venc.timings)); + venc_write_config(venc_timings_to_config(&venc.vm)); dss_set_venc_output(venc.type); dss_set_dac_pwrdn_bgz(1); @@ -462,7 +461,7 @@ static int venc_power_on(struct omap_dss_device *dssdev) venc_write_reg(VENC_OUTPUT_CONTROL, l); - dss_mgr_set_timings(channel, &venc.timings); + dss_mgr_set_timings(channel, &venc.vm); r = regulator_enable(venc.vdda_dac_reg); if (r) @@ -540,17 +539,17 @@ static void venc_display_disable(struct omap_dss_device *dssdev) } static void venc_set_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { DSSDBG("venc_set_timings\n"); mutex_lock(&venc.venc_lock); /* Reset WSS data when the TV standard changes. */ - if (memcmp(&venc.timings, timings, sizeof(*timings))) + if (memcmp(&venc.vm, vm, sizeof(*vm))) venc.wss_data = 0; - venc.timings = *timings; + venc.vm = *vm; dispc_set_tv_pclk(13500000); @@ -558,25 +557,25 @@ static void venc_set_timings(struct omap_dss_device *dssdev, } static int venc_check_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { DSSDBG("venc_check_timings\n"); - if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) + if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0) return 0; - if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) + if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0) return 0; return -EINVAL; } static void venc_get_timings(struct omap_dss_device *dssdev, - struct videomode *timings) + struct videomode *vm) { mutex_lock(&venc.venc_lock); - *timings = venc.timings; + *vm = venc.vm; mutex_unlock(&venc.venc_lock); } @@ -596,7 +595,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) mutex_lock(&venc.venc_lock); - config = venc_timings_to_config(&venc.timings); + config = venc_timings_to_config(&venc.vm); /* Invert due to VENC_L21_WC_CTL:INV=1 */ venc.wss_data = (wss ^ 0xfffff) << 8; diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index b04586b7e594..2580e8673908 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -118,11 +118,11 @@ static int omap_connector_get_modes(struct drm_connector *connector) kfree(edid); } else { struct drm_display_mode *mode = drm_mode_create(dev); - struct videomode timings = {0}; + struct videomode vm = {0}; - dssdrv->get_timings(dssdev, &timings); + dssdrv->get_timings(dssdev, &vm); - drm_display_mode_from_videomode(&timings, mode); + drm_display_mode_from_videomode(&vm, mode); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); @@ -140,14 +140,14 @@ static int omap_connector_mode_valid(struct drm_connector *connector, struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; - struct videomode timings = {0}; + struct videomode vm = {0}; struct drm_device *dev = connector->dev; struct drm_display_mode *new_mode; int r, ret = MODE_BAD; - drm_display_mode_to_videomode(mode, &timings); - timings.flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | - DISPLAY_FLAGS_SYNC_NEGEDGE; + drm_display_mode_to_videomode(mode, &vm); + vm.flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_NEGEDGE; mode->vrefresh = drm_mode_vrefresh(mode); /* @@ -156,13 +156,13 @@ static int omap_connector_mode_valid(struct drm_connector *connector, * panel's timings */ if (dssdrv->check_timings) { - r = dssdrv->check_timings(dssdev, &timings); + r = dssdrv->check_timings(dssdev, &vm); } else { struct videomode t = {0}; dssdrv->get_timings(dssdev, &t); - if (memcmp(&timings, &t, sizeof(struct videomode))) + if (memcmp(&vm, &t, sizeof(struct videomode))) r = -EINVAL; else r = 0; @@ -171,7 +171,7 @@ static int omap_connector_mode_valid(struct drm_connector *connector, if (!r) { /* check if vrefresh is still valid */ new_mode = drm_mode_duplicate(dev, mode); - new_mode->clock = timings.pixelclock / 1000; + new_mode->clock = vm.pixelclock / 1000; new_mode->vrefresh = 0; if (mode->vrefresh == drm_mode_vrefresh(new_mode)) ret = MODE_OK; diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index c819e350fb1b..8dea89030e66 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -34,7 +34,7 @@ struct omap_crtc { const char *name; enum omap_channel channel; - struct videomode timings; + struct videomode vm; struct omap_drm_irq vblank_irq; struct omap_drm_irq error_irq; @@ -59,7 +59,7 @@ uint32_t pipe2vbl(struct drm_crtc *crtc) struct videomode *omap_crtc_timings(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - return &omap_crtc->timings; + return &omap_crtc->vm; } enum omap_channel omap_crtc_channel(struct drm_crtc *crtc) @@ -201,7 +201,7 @@ static int omap_crtc_dss_enable(enum omap_channel channel) dispc_mgr_setup(omap_crtc->channel, &info); dispc_mgr_set_timings(omap_crtc->channel, - &omap_crtc->timings); + &omap_crtc->vm); omap_crtc_set_enabled(&omap_crtc->base, true); return 0; @@ -215,11 +215,11 @@ static void omap_crtc_dss_disable(enum omap_channel channel) } static void omap_crtc_dss_set_timings(enum omap_channel channel, - const struct videomode *timings) + const struct videomode *vm) { struct omap_crtc *omap_crtc = omap_crtcs[channel]; DBG("%s", omap_crtc->name); - omap_crtc->timings = *timings; + omap_crtc->vm = *vm; } static void omap_crtc_dss_set_lcd_config(enum omap_channel channel, @@ -369,10 +369,10 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, mode->type, mode->flags); - drm_display_mode_to_videomode(mode, &omap_crtc->timings); - omap_crtc->timings.flags |= DISPLAY_FLAGS_DE_HIGH | - DISPLAY_FLAGS_PIXDATA_POSEDGE | - DISPLAY_FLAGS_SYNC_NEGEDGE; + drm_display_mode_to_videomode(mode, &omap_crtc->vm); + omap_crtc->vm.flags |= DISPLAY_FLAGS_DE_HIGH | + DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_SYNC_NEGEDGE; } static int omap_crtc_atomic_check(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index f54065e9e2bf..a20f30039aee 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c @@ -102,7 +102,7 @@ static void omap_encoder_disable(struct drm_encoder *encoder) static int omap_encoder_update(struct drm_encoder *encoder, enum omap_channel channel, - struct videomode *timings) + struct videomode *vm) { struct drm_device *dev = encoder->dev; struct omap_encoder *omap_encoder = to_omap_encoder(encoder); @@ -111,13 +111,13 @@ static int omap_encoder_update(struct drm_encoder *encoder, int ret; if (dssdrv->check_timings) { - ret = dssdrv->check_timings(dssdev, timings); + ret = dssdrv->check_timings(dssdev, vm); } else { struct videomode t = {0}; dssdrv->get_timings(dssdev, &t); - if (memcmp(timings, &t, sizeof(struct videomode))) + if (memcmp(vm, &t, sizeof(struct videomode))) ret = -EINVAL; else ret = 0; @@ -129,7 +129,7 @@ static int omap_encoder_update(struct drm_encoder *encoder, } if (dssdrv->set_timings) - dssdrv->set_timings(dssdev, timings); + dssdrv->set_timings(dssdev, vm); return 0; } -- cgit v1.2.3 From 26a8d210d2d4a0b005935541a689b93cc6bc4cdc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:05 +0300 Subject: drm/omap: panel-tpo-td043mtea1: Add note for incorrect sync drive edge According to the datasheet of the panel, both data, DEN and sync signals are expected to be driven on the falling edge of the DOTCLK. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c index f78102aab2e6..0787dba44faa 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c @@ -89,6 +89,10 @@ static const struct videomode tpo_td043_vm = { .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE | DISPLAY_FLAGS_PIXDATA_NEGEDGE, + /* + * Note: According to the panel documentation: + * SYNC needs to be driven on the FALLING edge + */ }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) -- cgit v1.2.3 From 737b513b4c6341fe43d9a5d5d97fc4fe7c6e2659 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:06 +0300 Subject: drm/omap: panel-tpo-td028ttec1: Add note for incorrect sync drive edge According to the datasheet of the panel, both data, DEN and sync signals are expected to be driven on the falling edge of the DOTCLK. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index c003f4dd2a18..f313dbfcbacb 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c @@ -56,6 +56,10 @@ static struct videomode td028ttec1_panel_vm = { .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE | DISPLAY_FLAGS_PIXDATA_NEGEDGE, + /* + * Note: According to the panel documentation: + * SYNC needs to be driven on the FALLING edge + */ }; #define JBT_COMMAND 0x000 -- cgit v1.2.3 From 3a3caf305f53ddacb2fc374abfac1aeac4e4799c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:07 +0300 Subject: drm/omap: panel-sharp-ls037v7dw01: Add note for incorrect data drive edge According to the datasheet of the panel, both data, DEN and sync signals are expected to be driven on the falling edge of the DOTCLK. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c index fd33156bc34c..04fe235b7cac 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c @@ -52,6 +52,10 @@ static const struct videomode sharp_ls_vm = { .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE | DISPLAY_FLAGS_PIXDATA_POSEDGE, + /* + * Note: According to the panel documentation: + * DATA needs to be driven on the FALLING edge + */ }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) -- cgit v1.2.3 From d7b56e6f4e34b6d182b3c4e03c1bd88a3acfb210 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 22 Sep 2016 14:07:08 +0300 Subject: drm/omap: panel-lgphilips-lb035q02: Add note for incorrect data drive edge and DE level According to the datasheet of the panel, both data, DEN and sync signals are expected to be driven on the falling edge of the DOTCLK. The DE is active low according to the documentation. Signed-off-by: Peter Ujfalusi Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c index b36fa0a57b61..43d21edb51f5 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c @@ -36,6 +36,11 @@ static struct videomode lb035q02_vm = { .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE | DISPLAY_FLAGS_PIXDATA_POSEDGE, + /* + * Note: According to the panel documentation: + * DE is active LOW + * DATA needs to be driven on the FALLING edge + */ }; struct panel_drv_data { -- cgit v1.2.3 From 37c6393431bf526d6f465e095c1201c1b890dd51 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 1 Nov 2016 15:27:36 +0200 Subject: drm/i915/gtt: Fix pte clear range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comparing pte index to a number of entries is wrong when clearing a range of pte entries. Use end marker of 'one past' to correctly point adequate number of ptes to the scratch page. v2: assert early instead of warning late (Chris) v3: removed consts (Joonas) Fixes: d209b9c3cd28 ("drm/i915/gtt: Split gen8_ppgtt_clear_pte_range") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98282 Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Michel Thierry Cc: Michał Winiarski Reported-by: Mike Lothian Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Tested-by: Mike Lothian Reviewed-by: Joonas Lahtinen Signed-off-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_gem_gtt.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 00606a27e9aa..dc279ca61974 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -716,9 +716,9 @@ static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm, uint64_t length) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - unsigned int pte_start = gen8_pte_index(start); unsigned int num_entries = gen8_pte_count(start, length); - uint64_t pte; + unsigned int pte = gen8_pte_index(start); + unsigned int pte_end = pte + num_entries; gen8_pte_t *pt_vaddr; gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC); @@ -726,7 +726,9 @@ static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm, if (WARN_ON(!px_page(pt))) return false; - bitmap_clear(pt->used_ptes, pte_start, num_entries); + GEM_BUG_ON(pte_end > GEN8_PTES); + + bitmap_clear(pt->used_ptes, pte, num_entries); if (bitmap_empty(pt->used_ptes, GEN8_PTES)) { free_pt(vm->dev, pt); @@ -735,8 +737,8 @@ static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm, pt_vaddr = kmap_px(pt); - for (pte = pte_start; pte < num_entries; pte++) - pt_vaddr[pte] = scratch_pte; + while (pte < pte_end) + pt_vaddr[pte++] = scratch_pte; kunmap_px(ppgtt, pt_vaddr); -- cgit v1.2.3 From fce937559ef04aa2e29719842ec0d56b14eaf8c8 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Mon, 31 Oct 2016 17:24:46 +0200 Subject: drm/i915/gtt: Mark tlbs dirty on clear Now when clearing ptes can modify upper level pdp's, we need to mark them dirty so that they will be flushed correctly. Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1478006856-8313-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index dc279ca61974..67606bf8232b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -707,6 +707,16 @@ static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt, return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4)); } +/* PDE TLBs are a pain to invalidate on GEN8+. When we modify + * the page table structures, we mark them dirty so that + * context switching/execlist queuing code takes extra steps + * to ensure that tlbs are flushed. + */ +static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt) +{ + ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask; +} + /* Removes entries from a single page table, releasing it if it's empty. * Caller can use the return value to update higher-level entries. */ @@ -809,6 +819,8 @@ static bool gen8_ppgtt_clear_pdp(struct i915_address_space *vm, } } + mark_tlbs_dirty(ppgtt); + if (USES_FULL_48BIT_PPGTT(vm->dev) && bitmap_empty(pdp->used_pdpes, I915_PDPES_PER_PDP(vm->dev))) { free_pdp(vm->dev, pdp); @@ -1283,16 +1295,6 @@ err_out: return -ENOMEM; } -/* PDE TLBs are a pain to invalidate on GEN8+. When we modify - * the page table structures, we mark them dirty so that - * context switching/execlist queuing code takes extra steps - * to ensure that tlbs are flushed. - */ -static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt) -{ - ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask; -} - static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, struct i915_page_directory_pointer *pdp, uint64_t start, -- cgit v1.2.3 From 3ac168a70b2417c602fb86d48cb0cd12102890e1 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 1 Nov 2016 18:43:03 +0200 Subject: drm/i915: Move hangcheck code out from i915_irq.c Create new file for hangcheck specific code, intel_hangcheck.c, and move all related code in it. v2: s/intel_engine_hangcheck/intel_engine (Chris) No functional changes. Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1478018583-5816-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_irq.c | 417 ------------------------------ drivers/gpu/drm/i915/intel_engine_cs.c | 5 - drivers/gpu/drm/i915/intel_hangcheck.c | 450 +++++++++++++++++++++++++++++++++ 6 files changed, 453 insertions(+), 422 deletions(-) create mode 100644 drivers/gpu/drm/i915/intel_hangcheck.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 240ce9a8d68e..0857e5035f4d 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -47,6 +47,7 @@ i915-y += i915_cmd_parser.o \ i915_trace_points.o \ intel_breadcrumbs.o \ intel_engine_cs.o \ + intel_hangcheck.o \ intel_lrc.o \ intel_mocs.o \ intel_ringbuffer.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 48f4d210baf6..9e5a547a67ab 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -830,6 +830,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, intel_init_dpio(dev_priv); intel_power_domains_init(dev_priv); intel_irq_init(dev_priv); + intel_hangcheck_init(dev_priv); intel_init_display_hooks(dev_priv); intel_init_clock_gating_hooks(dev_priv); intel_init_audio_hooks(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f20e24baf95c..d8689792e75e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3009,6 +3009,7 @@ extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); extern void i915_reset(struct drm_i915_private *dev_priv); extern int intel_guc_reset(struct drm_i915_private *dev_priv); extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine); +extern void intel_hangcheck_init(struct drm_i915_private *dev_priv); extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ecd06d301d8b..6d7505b5c5e7 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2848,420 +2848,6 @@ static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -static bool -ipehr_is_semaphore_wait(struct intel_engine_cs *engine, u32 ipehr) -{ - if (INTEL_GEN(engine->i915) >= 8) { - return (ipehr >> 23) == 0x1c; - } else { - ipehr &= ~MI_SEMAPHORE_SYNC_MASK; - return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | - MI_SEMAPHORE_REGISTER); - } -} - -static struct intel_engine_cs * -semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, - u64 offset) -{ - struct drm_i915_private *dev_priv = engine->i915; - struct intel_engine_cs *signaller; - enum intel_engine_id id; - - if (INTEL_GEN(dev_priv) >= 8) { - for_each_engine(signaller, dev_priv, id) { - if (engine == signaller) - continue; - - if (offset == signaller->semaphore.signal_ggtt[engine->hw_id]) - return signaller; - } - } else { - u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; - - for_each_engine(signaller, dev_priv, id) { - if(engine == signaller) - continue; - - if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id]) - return signaller; - } - } - - DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n", - engine->name, ipehr, offset); - - return ERR_PTR(-ENODEV); -} - -static struct intel_engine_cs * -semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno) -{ - struct drm_i915_private *dev_priv = engine->i915; - void __iomem *vaddr; - u32 cmd, ipehr, head; - u64 offset = 0; - int i, backwards; - - /* - * This function does not support execlist mode - any attempt to - * proceed further into this function will result in a kernel panic - * when dereferencing ring->buffer, which is not set up in execlist - * mode. - * - * The correct way of doing it would be to derive the currently - * executing ring buffer from the current context, which is derived - * from the currently running request. Unfortunately, to get the - * current request we would have to grab the struct_mutex before doing - * anything else, which would be ill-advised since some other thread - * might have grabbed it already and managed to hang itself, causing - * the hang checker to deadlock. - * - * Therefore, this function does not support execlist mode in its - * current form. Just return NULL and move on. - */ - if (engine->buffer == NULL) - return NULL; - - ipehr = I915_READ(RING_IPEHR(engine->mmio_base)); - if (!ipehr_is_semaphore_wait(engine, ipehr)) - return NULL; - - /* - * HEAD is likely pointing to the dword after the actual command, - * so scan backwards until we find the MBOX. But limit it to just 3 - * or 4 dwords depending on the semaphore wait command size. - * Note that we don't care about ACTHD here since that might - * point at at batch, and semaphores are always emitted into the - * ringbuffer itself. - */ - head = I915_READ_HEAD(engine) & HEAD_ADDR; - backwards = (INTEL_GEN(dev_priv) >= 8) ? 5 : 4; - vaddr = (void __iomem *)engine->buffer->vaddr; - - for (i = backwards; i; --i) { - /* - * Be paranoid and presume the hw has gone off into the wild - - * our ring is smaller than what the hardware (and hence - * HEAD_ADDR) allows. Also handles wrap-around. - */ - head &= engine->buffer->size - 1; - - /* This here seems to blow up */ - cmd = ioread32(vaddr + head); - if (cmd == ipehr) - break; - - head -= 4; - } - - if (!i) - return NULL; - - *seqno = ioread32(vaddr + head + 4) + 1; - if (INTEL_GEN(dev_priv) >= 8) { - offset = ioread32(vaddr + head + 12); - offset <<= 32; - offset |= ioread32(vaddr + head + 8); - } - return semaphore_wait_to_signaller_ring(engine, ipehr, offset); -} - -static int semaphore_passed(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - struct intel_engine_cs *signaller; - u32 seqno; - - engine->hangcheck.deadlock++; - - signaller = semaphore_waits_for(engine, &seqno); - if (signaller == NULL) - return -1; - - if (IS_ERR(signaller)) - return 0; - - /* Prevent pathological recursion due to driver bugs */ - if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES) - return -1; - - if (i915_seqno_passed(intel_engine_get_seqno(signaller), seqno)) - return 1; - - /* cursory check for an unkickable deadlock */ - if (I915_READ_CTL(signaller) & RING_WAIT_SEMAPHORE && - semaphore_passed(signaller) < 0) - return -1; - - return 0; -} - -static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) -{ - struct intel_engine_cs *engine; - enum intel_engine_id id; - - for_each_engine(engine, dev_priv, id) - engine->hangcheck.deadlock = 0; -} - -static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone) -{ - u32 tmp = current_instdone | *old_instdone; - bool unchanged; - - unchanged = tmp == *old_instdone; - *old_instdone |= tmp; - - return unchanged; -} - -static bool subunits_stuck(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - struct intel_instdone instdone; - struct intel_instdone *accu_instdone = &engine->hangcheck.instdone; - bool stuck; - int slice; - int subslice; - - if (engine->id != RCS) - return true; - - intel_engine_get_instdone(engine, &instdone); - - /* There might be unstable subunit states even when - * actual head is not moving. Filter out the unstable ones by - * accumulating the undone -> done transitions and only - * consider those as progress. - */ - stuck = instdone_unchanged(instdone.instdone, - &accu_instdone->instdone); - stuck &= instdone_unchanged(instdone.slice_common, - &accu_instdone->slice_common); - - for_each_instdone_slice_subslice(dev_priv, slice, subslice) { - stuck &= instdone_unchanged(instdone.sampler[slice][subslice], - &accu_instdone->sampler[slice][subslice]); - stuck &= instdone_unchanged(instdone.row[slice][subslice], - &accu_instdone->row[slice][subslice]); - } - - return stuck; -} - -static enum intel_engine_hangcheck_action -head_stuck(struct intel_engine_cs *engine, u64 acthd) -{ - if (acthd != engine->hangcheck.acthd) { - - /* Clear subunit states on head movement */ - memset(&engine->hangcheck.instdone, 0, - sizeof(engine->hangcheck.instdone)); - - return HANGCHECK_ACTIVE; - } - - if (!subunits_stuck(engine)) - return HANGCHECK_ACTIVE; - - return HANGCHECK_HUNG; -} - -static enum intel_engine_hangcheck_action -engine_stuck(struct intel_engine_cs *engine, u64 acthd) -{ - struct drm_i915_private *dev_priv = engine->i915; - enum intel_engine_hangcheck_action ha; - u32 tmp; - - ha = head_stuck(engine, acthd); - if (ha != HANGCHECK_HUNG) - return ha; - - if (IS_GEN2(dev_priv)) - return HANGCHECK_HUNG; - - /* Is the chip hanging on a WAIT_FOR_EVENT? - * If so we can simply poke the RB_WAIT bit - * and break the hang. This should work on - * all but the second generation chipsets. - */ - tmp = I915_READ_CTL(engine); - if (tmp & RING_WAIT) { - i915_handle_error(dev_priv, 0, - "Kicking stuck wait on %s", - engine->name); - I915_WRITE_CTL(engine, tmp); - return HANGCHECK_KICK; - } - - if (INTEL_GEN(dev_priv) >= 6 && tmp & RING_WAIT_SEMAPHORE) { - switch (semaphore_passed(engine)) { - default: - return HANGCHECK_HUNG; - case 1: - i915_handle_error(dev_priv, 0, - "Kicking stuck semaphore on %s", - engine->name); - I915_WRITE_CTL(engine, tmp); - return HANGCHECK_KICK; - case 0: - return HANGCHECK_WAIT; - } - } - - return HANGCHECK_HUNG; -} - -/* - * This is called when the chip hasn't reported back with completed - * batchbuffers in a long time. We keep track per ring seqno progress and - * if there are no progress, hangcheck score for that ring is increased. - * Further, acthd is inspected to see if the ring is stuck. On stuck case - * we kick the ring. If we see no progress on three subsequent calls - * we assume chip is wedged and try to fix it by resetting the chip. - */ -static void i915_hangcheck_elapsed(struct work_struct *work) -{ - struct drm_i915_private *dev_priv = - container_of(work, typeof(*dev_priv), - gpu_error.hangcheck_work.work); - struct intel_engine_cs *engine; - enum intel_engine_id id; - unsigned int hung = 0, stuck = 0; - int busy_count = 0; -#define BUSY 1 -#define KICK 5 -#define HUNG 20 -#define ACTIVE_DECAY 15 - - if (!i915.enable_hangcheck) - return; - - if (!READ_ONCE(dev_priv->gt.awake)) - return; - - /* As enabling the GPU requires fairly extensive mmio access, - * periodically arm the mmio checker to see if we are triggering - * any invalid access. - */ - intel_uncore_arm_unclaimed_mmio_detection(dev_priv); - - for_each_engine(engine, dev_priv, id) { - bool busy = intel_engine_has_waiter(engine); - u64 acthd; - u32 seqno; - u32 submit; - - semaphore_clear_deadlocks(dev_priv); - - /* We don't strictly need an irq-barrier here, as we are not - * serving an interrupt request, be paranoid in case the - * barrier has side-effects (such as preventing a broken - * cacheline snoop) and so be sure that we can see the seqno - * advance. If the seqno should stick, due to a stale - * cacheline, we would erroneously declare the GPU hung. - */ - if (engine->irq_seqno_barrier) - engine->irq_seqno_barrier(engine); - - acthd = intel_engine_get_active_head(engine); - seqno = intel_engine_get_seqno(engine); - submit = intel_engine_last_submit(engine); - - if (engine->hangcheck.seqno == seqno) { - if (i915_seqno_passed(seqno, submit)) { - engine->hangcheck.action = HANGCHECK_IDLE; - } else { - /* We always increment the hangcheck score - * if the engine is busy and still processing - * the same request, so that no single request - * can run indefinitely (such as a chain of - * batches). The only time we do not increment - * the hangcheck score on this ring, if this - * engine is in a legitimate wait for another - * engine. In that case the waiting engine is a - * victim and we want to be sure we catch the - * right culprit. Then every time we do kick - * the ring, add a small increment to the - * score so that we can catch a batch that is - * being repeatedly kicked and so responsible - * for stalling the machine. - */ - engine->hangcheck.action = - engine_stuck(engine, acthd); - - switch (engine->hangcheck.action) { - case HANGCHECK_IDLE: - case HANGCHECK_WAIT: - break; - case HANGCHECK_ACTIVE: - engine->hangcheck.score += BUSY; - break; - case HANGCHECK_KICK: - engine->hangcheck.score += KICK; - break; - case HANGCHECK_HUNG: - engine->hangcheck.score += HUNG; - break; - } - } - - if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) { - hung |= intel_engine_flag(engine); - if (engine->hangcheck.action != HANGCHECK_HUNG) - stuck |= intel_engine_flag(engine); - } - } else { - engine->hangcheck.action = HANGCHECK_ACTIVE; - - /* Gradually reduce the count so that we catch DoS - * attempts across multiple batches. - */ - if (engine->hangcheck.score > 0) - engine->hangcheck.score -= ACTIVE_DECAY; - if (engine->hangcheck.score < 0) - engine->hangcheck.score = 0; - - /* Clear head and subunit states on seqno movement */ - acthd = 0; - - memset(&engine->hangcheck.instdone, 0, - sizeof(engine->hangcheck.instdone)); - } - - engine->hangcheck.seqno = seqno; - engine->hangcheck.acthd = acthd; - busy_count += busy; - } - - if (hung) { - char msg[80]; - unsigned int tmp; - int len; - - /* If some rings hung but others were still busy, only - * blame the hanging rings in the synopsis. - */ - if (stuck != hung) - hung &= ~stuck; - len = scnprintf(msg, sizeof(msg), - "%s on ", stuck == hung ? "No progress" : "Hang"); - for_each_engine_masked(engine, dev_priv, hung, tmp) - len += scnprintf(msg + len, sizeof(msg) - len, - "%s, ", engine->name); - msg[len-2] = '\0'; - - return i915_handle_error(dev_priv, hung, msg); - } - - /* Reset timer in case GPU hangs without another request being added */ - if (busy_count) - i915_queue_hangcheck(dev_priv); -} - static void ibx_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -4583,9 +4169,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (INTEL_INFO(dev_priv)->gen >= 8) dev_priv->rps.pm_intr_keep |= GEN8_PMINTR_REDIRECT_TO_GUC; - INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work, - i915_hangcheck_elapsed); - if (IS_GEN2(dev_priv)) { /* Gen2 doesn't have a hardware frame counter */ dev->max_vblank_count = 0; diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 94de3d66733d..841f8d1e1410 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -220,11 +220,6 @@ void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno) intel_engine_wakeup(engine); } -void intel_engine_init_hangcheck(struct intel_engine_cs *engine) -{ - memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); -} - static void intel_engine_init_timeline(struct intel_engine_cs *engine) { engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c new file mode 100644 index 000000000000..53df5b11bff4 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_hangcheck.c @@ -0,0 +1,450 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "i915_drv.h" + +static bool +ipehr_is_semaphore_wait(struct intel_engine_cs *engine, u32 ipehr) +{ + if (INTEL_GEN(engine->i915) >= 8) { + return (ipehr >> 23) == 0x1c; + } else { + ipehr &= ~MI_SEMAPHORE_SYNC_MASK; + return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | + MI_SEMAPHORE_REGISTER); + } +} + +static struct intel_engine_cs * +semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, + u64 offset) +{ + struct drm_i915_private *dev_priv = engine->i915; + struct intel_engine_cs *signaller; + enum intel_engine_id id; + + if (INTEL_GEN(dev_priv) >= 8) { + for_each_engine(signaller, dev_priv, id) { + if (engine == signaller) + continue; + + if (offset == signaller->semaphore.signal_ggtt[engine->hw_id]) + return signaller; + } + } else { + u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; + + for_each_engine(signaller, dev_priv, id) { + if(engine == signaller) + continue; + + if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id]) + return signaller; + } + } + + DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n", + engine->name, ipehr, offset); + + return ERR_PTR(-ENODEV); +} + +static struct intel_engine_cs * +semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno) +{ + struct drm_i915_private *dev_priv = engine->i915; + void __iomem *vaddr; + u32 cmd, ipehr, head; + u64 offset = 0; + int i, backwards; + + /* + * This function does not support execlist mode - any attempt to + * proceed further into this function will result in a kernel panic + * when dereferencing ring->buffer, which is not set up in execlist + * mode. + * + * The correct way of doing it would be to derive the currently + * executing ring buffer from the current context, which is derived + * from the currently running request. Unfortunately, to get the + * current request we would have to grab the struct_mutex before doing + * anything else, which would be ill-advised since some other thread + * might have grabbed it already and managed to hang itself, causing + * the hang checker to deadlock. + * + * Therefore, this function does not support execlist mode in its + * current form. Just return NULL and move on. + */ + if (engine->buffer == NULL) + return NULL; + + ipehr = I915_READ(RING_IPEHR(engine->mmio_base)); + if (!ipehr_is_semaphore_wait(engine, ipehr)) + return NULL; + + /* + * HEAD is likely pointing to the dword after the actual command, + * so scan backwards until we find the MBOX. But limit it to just 3 + * or 4 dwords depending on the semaphore wait command size. + * Note that we don't care about ACTHD here since that might + * point at at batch, and semaphores are always emitted into the + * ringbuffer itself. + */ + head = I915_READ_HEAD(engine) & HEAD_ADDR; + backwards = (INTEL_GEN(dev_priv) >= 8) ? 5 : 4; + vaddr = (void __iomem *)engine->buffer->vaddr; + + for (i = backwards; i; --i) { + /* + * Be paranoid and presume the hw has gone off into the wild - + * our ring is smaller than what the hardware (and hence + * HEAD_ADDR) allows. Also handles wrap-around. + */ + head &= engine->buffer->size - 1; + + /* This here seems to blow up */ + cmd = ioread32(vaddr + head); + if (cmd == ipehr) + break; + + head -= 4; + } + + if (!i) + return NULL; + + *seqno = ioread32(vaddr + head + 4) + 1; + if (INTEL_GEN(dev_priv) >= 8) { + offset = ioread32(vaddr + head + 12); + offset <<= 32; + offset |= ioread32(vaddr + head + 8); + } + return semaphore_wait_to_signaller_ring(engine, ipehr, offset); +} + +static int semaphore_passed(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + struct intel_engine_cs *signaller; + u32 seqno; + + engine->hangcheck.deadlock++; + + signaller = semaphore_waits_for(engine, &seqno); + if (signaller == NULL) + return -1; + + if (IS_ERR(signaller)) + return 0; + + /* Prevent pathological recursion due to driver bugs */ + if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES) + return -1; + + if (i915_seqno_passed(intel_engine_get_seqno(signaller), seqno)) + return 1; + + /* cursory check for an unkickable deadlock */ + if (I915_READ_CTL(signaller) & RING_WAIT_SEMAPHORE && + semaphore_passed(signaller) < 0) + return -1; + + return 0; +} + +static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + + for_each_engine(engine, dev_priv, id) + engine->hangcheck.deadlock = 0; +} + +static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone) +{ + u32 tmp = current_instdone | *old_instdone; + bool unchanged; + + unchanged = tmp == *old_instdone; + *old_instdone |= tmp; + + return unchanged; +} + +static bool subunits_stuck(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + struct intel_instdone instdone; + struct intel_instdone *accu_instdone = &engine->hangcheck.instdone; + bool stuck; + int slice; + int subslice; + + if (engine->id != RCS) + return true; + + intel_engine_get_instdone(engine, &instdone); + + /* There might be unstable subunit states even when + * actual head is not moving. Filter out the unstable ones by + * accumulating the undone -> done transitions and only + * consider those as progress. + */ + stuck = instdone_unchanged(instdone.instdone, + &accu_instdone->instdone); + stuck &= instdone_unchanged(instdone.slice_common, + &accu_instdone->slice_common); + + for_each_instdone_slice_subslice(dev_priv, slice, subslice) { + stuck &= instdone_unchanged(instdone.sampler[slice][subslice], + &accu_instdone->sampler[slice][subslice]); + stuck &= instdone_unchanged(instdone.row[slice][subslice], + &accu_instdone->row[slice][subslice]); + } + + return stuck; +} + +static enum intel_engine_hangcheck_action +head_stuck(struct intel_engine_cs *engine, u64 acthd) +{ + if (acthd != engine->hangcheck.acthd) { + + /* Clear subunit states on head movement */ + memset(&engine->hangcheck.instdone, 0, + sizeof(engine->hangcheck.instdone)); + + return HANGCHECK_ACTIVE; + } + + if (!subunits_stuck(engine)) + return HANGCHECK_ACTIVE; + + return HANGCHECK_HUNG; +} + +static enum intel_engine_hangcheck_action +engine_stuck(struct intel_engine_cs *engine, u64 acthd) +{ + struct drm_i915_private *dev_priv = engine->i915; + enum intel_engine_hangcheck_action ha; + u32 tmp; + + ha = head_stuck(engine, acthd); + if (ha != HANGCHECK_HUNG) + return ha; + + if (IS_GEN2(dev_priv)) + return HANGCHECK_HUNG; + + /* Is the chip hanging on a WAIT_FOR_EVENT? + * If so we can simply poke the RB_WAIT bit + * and break the hang. This should work on + * all but the second generation chipsets. + */ + tmp = I915_READ_CTL(engine); + if (tmp & RING_WAIT) { + i915_handle_error(dev_priv, 0, + "Kicking stuck wait on %s", + engine->name); + I915_WRITE_CTL(engine, tmp); + return HANGCHECK_KICK; + } + + if (INTEL_GEN(dev_priv) >= 6 && tmp & RING_WAIT_SEMAPHORE) { + switch (semaphore_passed(engine)) { + default: + return HANGCHECK_HUNG; + case 1: + i915_handle_error(dev_priv, 0, + "Kicking stuck semaphore on %s", + engine->name); + I915_WRITE_CTL(engine, tmp); + return HANGCHECK_KICK; + case 0: + return HANGCHECK_WAIT; + } + } + + return HANGCHECK_HUNG; +} + +/* + * This is called when the chip hasn't reported back with completed + * batchbuffers in a long time. We keep track per ring seqno progress and + * if there are no progress, hangcheck score for that ring is increased. + * Further, acthd is inspected to see if the ring is stuck. On stuck case + * we kick the ring. If we see no progress on three subsequent calls + * we assume chip is wedged and try to fix it by resetting the chip. + */ +static void i915_hangcheck_elapsed(struct work_struct *work) +{ + struct drm_i915_private *dev_priv = + container_of(work, typeof(*dev_priv), + gpu_error.hangcheck_work.work); + struct intel_engine_cs *engine; + enum intel_engine_id id; + unsigned int hung = 0, stuck = 0; + int busy_count = 0; +#define BUSY 1 +#define KICK 5 +#define HUNG 20 +#define ACTIVE_DECAY 15 + + if (!i915.enable_hangcheck) + return; + + if (!READ_ONCE(dev_priv->gt.awake)) + return; + + /* As enabling the GPU requires fairly extensive mmio access, + * periodically arm the mmio checker to see if we are triggering + * any invalid access. + */ + intel_uncore_arm_unclaimed_mmio_detection(dev_priv); + + for_each_engine(engine, dev_priv, id) { + bool busy = intel_engine_has_waiter(engine); + u64 acthd; + u32 seqno; + u32 submit; + + semaphore_clear_deadlocks(dev_priv); + + /* We don't strictly need an irq-barrier here, as we are not + * serving an interrupt request, be paranoid in case the + * barrier has side-effects (such as preventing a broken + * cacheline snoop) and so be sure that we can see the seqno + * advance. If the seqno should stick, due to a stale + * cacheline, we would erroneously declare the GPU hung. + */ + if (engine->irq_seqno_barrier) + engine->irq_seqno_barrier(engine); + + acthd = intel_engine_get_active_head(engine); + seqno = intel_engine_get_seqno(engine); + submit = intel_engine_last_submit(engine); + + if (engine->hangcheck.seqno == seqno) { + if (i915_seqno_passed(seqno, submit)) { + engine->hangcheck.action = HANGCHECK_IDLE; + } else { + /* We always increment the hangcheck score + * if the engine is busy and still processing + * the same request, so that no single request + * can run indefinitely (such as a chain of + * batches). The only time we do not increment + * the hangcheck score on this ring, if this + * engine is in a legitimate wait for another + * engine. In that case the waiting engine is a + * victim and we want to be sure we catch the + * right culprit. Then every time we do kick + * the ring, add a small increment to the + * score so that we can catch a batch that is + * being repeatedly kicked and so responsible + * for stalling the machine. + */ + engine->hangcheck.action = + engine_stuck(engine, acthd); + + switch (engine->hangcheck.action) { + case HANGCHECK_IDLE: + case HANGCHECK_WAIT: + break; + case HANGCHECK_ACTIVE: + engine->hangcheck.score += BUSY; + break; + case HANGCHECK_KICK: + engine->hangcheck.score += KICK; + break; + case HANGCHECK_HUNG: + engine->hangcheck.score += HUNG; + break; + } + } + + if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) { + hung |= intel_engine_flag(engine); + if (engine->hangcheck.action != HANGCHECK_HUNG) + stuck |= intel_engine_flag(engine); + } + } else { + engine->hangcheck.action = HANGCHECK_ACTIVE; + + /* Gradually reduce the count so that we catch DoS + * attempts across multiple batches. + */ + if (engine->hangcheck.score > 0) + engine->hangcheck.score -= ACTIVE_DECAY; + if (engine->hangcheck.score < 0) + engine->hangcheck.score = 0; + + /* Clear head and subunit states on seqno movement */ + acthd = 0; + + memset(&engine->hangcheck.instdone, 0, + sizeof(engine->hangcheck.instdone)); + } + + engine->hangcheck.seqno = seqno; + engine->hangcheck.acthd = acthd; + busy_count += busy; + } + + if (hung) { + char msg[80]; + unsigned int tmp; + int len; + + /* If some rings hung but others were still busy, only + * blame the hanging rings in the synopsis. + */ + if (stuck != hung) + hung &= ~stuck; + len = scnprintf(msg, sizeof(msg), + "%s on ", stuck == hung ? "No progress" : "Hang"); + for_each_engine_masked(engine, dev_priv, hung, tmp) + len += scnprintf(msg + len, sizeof(msg) - len, + "%s, ", engine->name); + msg[len-2] = '\0'; + + return i915_handle_error(dev_priv, hung, msg); + } + + /* Reset timer in case GPU hangs without another request being added */ + if (busy_count) + i915_queue_hangcheck(dev_priv); +} + +void intel_engine_init_hangcheck(struct intel_engine_cs *engine) +{ + memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); +} + +void intel_hangcheck_init(struct drm_i915_private *i915) +{ + INIT_DELAYED_WORK(&i915->gpu_error.hangcheck_work, + i915_hangcheck_elapsed); +} -- cgit v1.2.3 From 56cea32382bcad7eea0a1af5c448089c08ec9f1f Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 2 Nov 2016 12:16:04 +0200 Subject: drm/i915: Unify global_list into global_link $ sed -i -r 's/\bglobal_list\b/global_link/g' *.c *.h Cc: Chris Wilson Signed-off-by: Joonas Lahtinen Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1478081764-8058-1-git-send-email-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 10 +++++----- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 12 ++++++------ drivers/gpu/drm/i915/i915_gem_gtt.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_shrinker.c | 16 ++++++++-------- drivers/gpu/drm/i915/i915_gem_stolen.c | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a13ff4772e28..bc9c0cdeb3b3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -217,7 +217,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) return ret; total_obj_size = total_gtt_size = count = 0; - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { + list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { if (obj->stolen == NULL) continue; @@ -227,7 +227,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) total_gtt_size += i915_gem_obj_total_ggtt_size(obj); count++; } - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) { + list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) { if (obj->stolen == NULL) continue; @@ -390,7 +390,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data) size = count = 0; mapped_size = mapped_count = 0; purgeable_size = purgeable_count = 0; - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) { + list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) { size += obj->base.size; ++count; @@ -407,7 +407,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data) seq_printf(m, "%u unbound objects, %llu bytes\n", count, size); size = count = dpy_size = dpy_count = 0; - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { + list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { size += obj->base.size; ++count; @@ -493,7 +493,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data) return ret; total_obj_size = total_gtt_size = count = 0; - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { + list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { if (show_pin_display_only && !obj->pin_display) continue; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d8689792e75e..eaa01da892a4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2235,7 +2235,7 @@ struct drm_i915_gem_object { /** Stolen memory for this object, instead of being backed by shmem. */ struct drm_mm_node *stolen; - struct list_head global_list; + struct list_head global_link; union { struct rcu_head rcu; struct llist_node freed; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a97fdfa80663..5839bebba64a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1446,7 +1446,7 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj) i915 = to_i915(obj->base.dev); list = obj->bind_count ? &i915->mm.bound_list : &i915->mm.unbound_list; - list_move_tail(&obj->global_list, list); + list_move_tail(&obj->global_link, list); } /** @@ -2967,7 +2967,7 @@ int i915_vma_unbind(struct i915_vma *vma) /* Since the unbound list is global, only move to that list if * no more VMAs exist. */ if (--obj->bind_count == 0) - list_move_tail(&obj->global_list, + list_move_tail(&obj->global_link, &to_i915(obj->base.dev)->mm.unbound_list); /* And finally now the object is completely decoupled from this vma, @@ -3164,7 +3164,7 @@ search_free: } GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level)); - list_move_tail(&obj->global_list, &dev_priv->mm.bound_list); + list_move_tail(&obj->global_link, &dev_priv->mm.bound_list); list_move_tail(&vma->vm_link, &vma->vm->inactive_list); obj->bind_count++; @@ -4125,7 +4125,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, { mutex_init(&obj->mm.lock); - INIT_LIST_HEAD(&obj->global_list); + INIT_LIST_HEAD(&obj->global_link); INIT_LIST_HEAD(&obj->userfault_link); INIT_LIST_HEAD(&obj->obj_exec_link); INIT_LIST_HEAD(&obj->vma_list); @@ -4272,7 +4272,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, GEM_BUG_ON(!list_empty(&obj->vma_list)); GEM_BUG_ON(!RB_EMPTY_ROOT(&obj->vma_tree)); - list_del(&obj->global_list); + list_del(&obj->global_link); } intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); @@ -4847,7 +4847,7 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) i915_gem_shrink(dev_priv, -1UL, I915_SHRINK_UNBOUND); for (p = phases; *p; p++) { - list_for_each_entry(obj, *p, global_list) { + list_for_each_entry(obj, *p, global_link) { obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->base.write_domain = I915_GEM_DOMAIN_CPU; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 67606bf8232b..0c1f5b4750b6 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3296,7 +3296,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) /* clflush objects bound into the GGTT and rebind them. */ list_for_each_entry_safe(obj, on, - &dev_priv->mm.bound_list, global_list) { + &dev_priv->mm.bound_list, global_link) { bool ggtt_bound = false; struct i915_vma *vma; @@ -3376,7 +3376,7 @@ i915_vma_retire(struct i915_gem_active *active, * (unless we are forced to ofc!) */ if (obj->bind_count) - list_move_tail(&obj->global_list, &rq->i915->mm.bound_list); + list_move_tail(&obj->global_link, &rq->i915->mm.bound_list); obj->mm.dirty = true; /* be paranoid */ diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 87dd27d5146c..a6fc1bdc48af 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -199,10 +199,10 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, while (count < target && (obj = list_first_entry_or_null(phase->list, typeof(*obj), - global_list))) { - list_move_tail(&obj->global_list, &still_in_list); + global_link))) { + list_move_tail(&obj->global_link, &still_in_list); if (!obj->mm.pages) { - list_del_init(&obj->global_list); + list_del_init(&obj->global_link); continue; } @@ -228,7 +228,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, I915_MM_SHRINKER); if (!obj->mm.pages) { __i915_gem_object_invalidate(obj); - list_del_init(&obj->global_list); + list_del_init(&obj->global_link); count += obj->base.size >> PAGE_SHIFT; } mutex_unlock(&obj->mm.lock); @@ -293,11 +293,11 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) i915_gem_retire_requests(dev_priv); count = 0; - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) + list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) if (can_release_pages(obj)) count += obj->base.size >> PAGE_SHIFT; - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { + list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { if (!i915_gem_object_is_active(obj) && can_release_pages(obj)) count += obj->base.size >> PAGE_SHIFT; } @@ -398,7 +398,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) * being pointed to by hardware. */ unbound = bound = unevictable = 0; - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) { + list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) { if (!obj->mm.pages) continue; @@ -407,7 +407,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) else unbound += obj->base.size >> PAGE_SHIFT; } - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { + list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { if (!obj->mm.pages) continue; diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 3725a1d3b254..b1d367dba347 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -723,7 +723,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, vma->flags |= I915_VMA_GLOBAL_BIND; __i915_vma_set_map_and_fenceable(vma); list_move_tail(&vma->vm_link, &ggtt->base.inactive_list); - list_move_tail(&obj->global_list, &dev_priv->mm.bound_list); + list_move_tail(&obj->global_link, &dev_priv->mm.bound_list); obj->bind_count++; return obj; -- cgit v1.2.3 From c8247c067159782a27c4f2c371c9e26827131a78 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 27 Oct 2016 01:03:43 +0100 Subject: drm/i915: Show the execlist queue in debugfs/i915_engine_info When looking at freezes whilst working on execlists, knowing the order of the pending requests in the driver is useful. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161027000348.4641-2-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index bc9c0cdeb3b3..c9465fbff2df 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3255,6 +3255,12 @@ static int i915_engine_info(struct seq_file *m, void *unused) else seq_printf(m, "\t\tELSP[1] idle\n"); rcu_read_unlock(); + + spin_lock_irq(&engine->execlist_lock); + list_for_each_entry(rq, &engine->execlist_queue, execlist_link) { + print_request(m, rq, "\t\tQ "); + } + spin_unlock_irq(&engine->execlist_lock); } else if (INTEL_GEN(dev_priv) > 6) { seq_printf(m, "\tPP_DIR_BASE: 0x%08x\n", I915_READ(RING_PP_DIR_BASE(engine))); -- cgit v1.2.3 From 32df9ff2b88f9b3ef0865837cd6a39c957dab875 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 1 Nov 2016 22:18:39 +0100 Subject: spi: imx: set spi_bus_clk for mx21 and mx27 Introduce additional output parameter in spi_imx_clkdiv_1() function to return result frequency and set it to spi_bus_clk. This fixes division by zero bug, which occurred in spi_imx_calculate_timeout() function. Signed-off-by: Robert Baldyga Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 08124b29665e..32ced64a5bb9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -173,15 +173,16 @@ static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, /* MX21, MX27 */ static unsigned int spi_imx_clkdiv_1(unsigned int fin, - unsigned int fspi, unsigned int max) + unsigned int fspi, unsigned int max, unsigned int *fres) { int i; for (i = 2; i < max; i++) if (fspi * mxc_clkdivs[i] >= fin) - return i; + break; - return max; + *fres = fin / mxc_clkdivs[i]; + return i; } /* MX1, MX31, MX35, MX51 CSPI */ @@ -589,9 +590,12 @@ static int mx21_config(struct spi_device *spi, struct spi_imx_config *config) struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER; unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18; + unsigned int clk; + + reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max, &clk) + << MX21_CSPICTRL_DR_SHIFT; + spi_imx->spi_bus_clk = clk; - reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max) << - MX21_CSPICTRL_DR_SHIFT; reg |= config->bpw - 1; if (spi->mode & SPI_CPHA) -- cgit v1.2.3 From 0a97c81a9717431e6c57ea845b59c3c345edce67 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 1 Nov 2016 15:43:15 +0100 Subject: drm/gma500: Add compat ioctl Hook up drm_compat_ioctl to support 32-bit userspace on 64-bit kernels. It turns out that N2600 and N2800 comes with 64-bit enabled. We previously assumed there where no such systems out there. Cc: stable@vger.kernel.org Signed-off-by: Patrik Jakobsson Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/20161101144315.2955-1-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/psb_drv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 50eb944fb78a..8f3ca526bd1b 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -473,6 +473,9 @@ static const struct file_operations psb_gem_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = psb_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, -- cgit v1.2.3 From 55edf41b699bcb31dcf45082d99e91b7e217206e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 1 Nov 2016 17:40:44 +0200 Subject: drm: define drm_compat_ioctl NULL on CONFIG_COMPAT=n and reduce #ifdefs If we define drm_compat_ioctl NULL on CONFIG_COMPAT=n, we don't have to check for the config everywhere. Reviewed-by: Patrik Jakobsson Signed-off-by: Jani Nikula Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1478014844-27454-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/arc/arcpgu_drv.c | 2 -- drivers/gpu/drm/arm/hdlcd_drv.c | 2 -- drivers/gpu/drm/arm/malidp_drv.c | 2 -- drivers/gpu/drm/ast/ast_drv.c | 2 -- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 2 -- drivers/gpu/drm/bochs/bochs_drv.c | 2 -- drivers/gpu/drm/cirrus/cirrus_drv.c | 2 -- drivers/gpu/drm/drm_fops.c | 13 ++++++------- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 2 -- drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 -- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 2 -- drivers/gpu/drm/gma500/psb_drv.c | 2 -- drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 2 -- drivers/gpu/drm/i810/i810_dma.c | 2 -- drivers/gpu/drm/i810/i810_drv.c | 2 -- drivers/gpu/drm/i915/i915_drv.c | 2 -- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 -- drivers/gpu/drm/mgag200/mgag200_drv.c | 2 -- drivers/gpu/drm/msm/msm_drv.c | 2 -- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 -- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 -- drivers/gpu/drm/savage/savage_drv.c | 2 -- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 2 -- drivers/gpu/drm/sis/sis_drv.c | 2 -- drivers/gpu/drm/sti/sti_drv.c | 2 -- drivers/gpu/drm/sun4i/sun4i_drv.c | 2 -- drivers/gpu/drm/tdfx/tdfx_drv.c | 2 -- drivers/gpu/drm/tegra/drm.c | 2 -- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 2 -- drivers/gpu/drm/udl/udl_drv.c | 2 -- drivers/gpu/drm/vc4/vc4_drv.c | 2 -- drivers/gpu/drm/via/via_drv.c | 2 -- drivers/gpu/drm/virtio/virtgpu_drv.c | 2 -- include/drm/drmP.h | 5 +++++ 35 files changed, 13 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 28e6471257d0..0b6eaa49a1db 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -65,9 +65,7 @@ static const struct file_operations arcpgu_drm_ops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 6477d1a65266..59747ecaad54 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -268,9 +268,7 @@ static const struct file_operations fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = noop_llseek, diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 9f4739452a25..d53b625b14fe 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -197,9 +197,7 @@ static const struct file_operations fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = noop_llseek, diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index f54afd2113a9..fd7c9eec92e4 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -188,9 +188,7 @@ static const struct file_operations ast_fops = { .unlocked_ioctl = drm_ioctl, .mmap = ast_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .read = drm_read, }; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 9f6222895212..cbd0070265c9 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -749,9 +749,7 @@ static const struct file_operations fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index 534227df23f3..15a293e65b31 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -70,9 +70,7 @@ static const struct file_operations bochs_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 6c76d125995b..d893ea21a359 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -126,9 +126,7 @@ static const struct file_operations cirrus_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = cirrus_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif }; static struct drm_driver driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM, diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index cf993dbf602e..5d96de40b63f 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -51,10 +51,11 @@ DEFINE_MUTEX(drm_global_mutex); * Drivers must define the file operations structure that forms the DRM * userspace API entry point, even though most of those operations are * implemented in the DRM core. The mandatory functions are drm_open(), - * drm_read(), drm_ioctl() and drm_compat_ioctl if CONFIG_COMPAT is enabled. - * Drivers which implement private ioctls that require 32/64 bit compatibility - * support must provided their onw .compat_ioctl() handler that processes - * private ioctls and calls drm_compat_ioctl() for core ioctls. + * drm_read(), drm_ioctl() and drm_compat_ioctl() if CONFIG_COMPAT is enabled + * (note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n). Drivers which + * implement private ioctls that require 32/64 bit compatibility support must + * provide their own .compat_ioctl() handler that processes private ioctls and + * calls drm_compat_ioctl() for core ioctls. * * In addition drm_read() and drm_poll() provide support for DRM events. DRM * events are a generic and extensible means to send asynchronous events to @@ -75,9 +76,7 @@ DEFINE_MUTEX(drm_global_mutex); * .open = drm_open, * .release = drm_release, * .unlocked_ioctl = drm_ioctl, - * #ifdef CONFIG_COMPAT - * .compat_ioctl = drm_compat_ioctl, - * #endif + * .compat_ioctl = drm_compat_ioctl, // NULL if CONFIG_COMPAT=n * .poll = drm_poll, * .read = drm_read, * .llseek = no_llseek, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 0dee6acbd880..a6799b0aa3d9 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -479,9 +479,7 @@ static const struct file_operations fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 4a21a745c373..b24714976d24 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -346,9 +346,7 @@ static const struct file_operations exynos_drm_driver_fops = { .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .release = drm_release, }; diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index e04efbed1a54..0b0d1cb11641 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -180,9 +180,7 @@ static const struct file_operations fsl_dcu_drm_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 8f3ca526bd1b..ff37ea585664 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -473,9 +473,7 @@ static const struct file_operations psb_gem_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = psb_unlocked_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index e88fde18c946..ebd5f4fe4c23 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -152,9 +152,7 @@ static const struct file_operations kirin_drm_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index d91856779beb..ab4e6cbe1f8b 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -113,9 +113,7 @@ static const struct file_operations i810_buffer_fops = { .release = drm_release, .unlocked_ioctl = drm_ioctl, .mmap = i810_mmap_buffers, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 0be55dc1ef4b..02504a7cfaf2 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -49,9 +49,7 @@ static const struct file_operations i810_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_legacy_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 912d5348e3e7..cf583d4e3a9f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2509,9 +2509,7 @@ static const struct file_operations i915_driver_fops = { .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, -#ifdef CONFIG_COMPAT .compat_ioctl = i915_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f022f438e5b9..74476f55d05e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2901,6 +2901,8 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, #ifdef CONFIG_COMPAT extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +#define i915_compat_ioctl NULL #endif extern const struct dev_pm_ops i915_pm_ops; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 296f541fbe2f..d90152e85ed0 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -249,9 +249,7 @@ static const struct file_operations mtk_drm_fops = { .mmap = mtk_drm_gem_mmap, .poll = drm_poll, .read = drm_read, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif }; static struct drm_driver mtk_drm_driver = { diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 1443b3a34775..b0b874264f9d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -82,9 +82,7 @@ static const struct file_operations mgag200_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = mgag200_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .read = drm_read, }; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 84d38eaea585..8855972303ec 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -768,9 +768,7 @@ static const struct file_operations fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 73c971e39b1c..68fd167d7313 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -201,9 +201,7 @@ static const struct file_operations rcar_du_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 6fe161192bb4..2390c8577617 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -275,9 +275,7 @@ static const struct file_operations rockchip_drm_driver_fops = { .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .release = drm_release, }; diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 3b807135a5cd..78c6d8e9b42c 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -42,9 +42,7 @@ static const struct file_operations savage_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_legacy_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index f0492603ea88..38dd55f4af81 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -245,9 +245,7 @@ static const struct file_operations shmob_drm_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index ae9839886c4d..a836451920f0 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -72,9 +72,7 @@ static const struct file_operations sis_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_legacy_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 6aead2013b62..80ecee9d52b8 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -277,9 +277,7 @@ static const struct file_operations sti_driver_fops = { .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .release = drm_release, }; diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index b3c4ad605e81..aae723cd6d79 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -53,9 +53,7 @@ static const struct file_operations sun4i_drv_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index f418892b0c71..c54138c3a376 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -49,9 +49,7 @@ static const struct file_operations tdfx_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_legacy_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index a9630c2d6cb3..b8be3ee4d3b8 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -802,9 +802,7 @@ static const struct file_operations tegra_drm_fops = { .mmap = tegra_drm_mmap, .poll = drm_poll, .read = drm_read, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 147fb28287ae..0f58a74f25d1 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -573,9 +573,7 @@ static const struct file_operations fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index cc45d98f9bb5..cd8b01727734 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -44,9 +44,7 @@ static const struct file_operations udl_driver_fops = { .read = drm_read, .unlocked_ioctl = drm_ioctl, .release = drm_release, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 8703f56b7947..eaf26d9b5f11 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -103,9 +103,7 @@ static const struct file_operations vc4_drm_fops = { .mmap = vc4_mmap, .poll = drm_poll, .read = drm_read, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index e5582bab7e3c..9e0e5392b6ec 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -64,9 +64,7 @@ static const struct file_operations via_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_legacy_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 5820b7020ae5..04d98db75c64 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -108,9 +108,7 @@ static const struct file_operations virtio_gpu_driver_fops = { .read = drm_read, .unlocked_ioctl = drm_ioctl, .release = drm_release, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index e336e3901876..a3effab98407 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -941,8 +941,13 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv) extern int drm_ioctl_permit(u32 flags, struct drm_file *file_priv); extern long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT extern long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */ +#define drm_compat_ioctl NULL +#endif extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); /* File Operations (drm_fops.c) */ -- cgit v1.2.3 From 47d7fbb32c57c8d1722a3e9bd21e501e80fd0741 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 18 Oct 2016 10:46:14 +0200 Subject: drm/sun4i: Add a few formats The planes can do more than what was previously exposed. Add support for them. Since we still have the issue that the primary plane cannot have any alpha component, we will expose only the non-alpha formats in the primary formats, and the alpha formats will be exposed in the overlays. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai --- drivers/gpu/drm/sun4i/sun4i_backend.c | 20 ++++++++++++++++++++ drivers/gpu/drm/sun4i/sun4i_layer.c | 6 ++++++ 2 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 6e6c59a661b6..7eb2a965f83d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -95,6 +95,22 @@ static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane, *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; break; + case DRM_FORMAT_ARGB4444: + *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB4444; + break; + + case DRM_FORMAT_ARGB1555: + *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB1555; + break; + + case DRM_FORMAT_RGBA5551: + *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA5551; + break; + + case DRM_FORMAT_RGBA4444: + *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA4444; + break; + case DRM_FORMAT_XRGB8888: *mode = SUN4I_BACKEND_LAY_FBFMT_XRGB8888; break; @@ -103,6 +119,10 @@ static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane, *mode = SUN4I_BACKEND_LAY_FBFMT_RGB888; break; + case DRM_FORMAT_RGB565: + *mode = SUN4I_BACKEND_LAY_FBFMT_RGB565; + break; + default: return -EINVAL; } diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index f0035bf5efea..5d53c977bca5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -73,12 +73,18 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = { static const uint32_t sun4i_backend_layer_formats_primary[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, }; static const uint32_t sun4i_backend_layer_formats_overlay[] = { DRM_FORMAT_ARGB8888, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_RGBA4444, DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, }; -- cgit v1.2.3 From 52d7f1b5c2f33b5d34dc2b6af5175fb6a44999f6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Oct 2016 17:20:32 -0700 Subject: blk-mq: Avoid that requeueing starts stopped queues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since blk_mq_requeue_work() starts stopped queues and since execution of this function can be scheduled after a queue has been stopped it is not possible to stop queues without using an additional state variable to track whether or not the queue has been stopped. Hence modify blk_mq_requeue_work() such that it does not start stopped queues. My conclusion after a review of the blk_mq_stop_hw_queues() and blk_mq_{delay_,}kick_requeue_list() callers is as follows: * In the dm driver starting and stopping queues should only happen if __dm_suspend() or __dm_resume() is called and not if the requeue list is processed. * In the SCSI core queue stopping and starting should only be performed by the scsi_internal_device_block() and scsi_internal_device_unblock() functions but not by any other function. Although the blk_mq_stop_hw_queue() call in scsi_queue_rq() may help to reduce CPU load if a LLD queue is full, figuring out whether or not a queue should be restarted when requeueing a command would require to introduce additional locking in scsi_mq_requeue_cmd() to avoid a race with scsi_internal_device_block(). Avoid this complexity by removing the blk_mq_stop_hw_queue() call from scsi_queue_rq(). * In the NVMe core only the functions that call blk_mq_start_stopped_hw_queues() explicitly should start stopped queues. * A blk_mq_start_stopped_hwqueues() call must be added in the xen-blkfront driver in its blkif_recover() function. Signed-off-by: Bart Van Assche Cc: Konrad Rzeszutek Wilk Cc: Roger Pau Monné Cc: Mike Snitzer Cc: James Bottomley Cc: Martin K. Petersen Reviewed-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-mq.c | 6 +----- drivers/block/xen-blkfront.c | 1 + drivers/md/dm-rq.c | 7 +------ drivers/scsi/scsi_lib.c | 1 - 4 files changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/block/blk-mq.c b/block/blk-mq.c index 447c37f39e32..d95034ae64f6 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -501,11 +501,7 @@ static void blk_mq_requeue_work(struct work_struct *work) blk_mq_insert_request(rq, false, false, false); } - /* - * Use the start variant of queue running here, so that running - * the requeue work will kick stopped queues. - */ - blk_mq_start_hw_queues(q); + blk_mq_run_hw_queues(q, false); } void blk_mq_add_to_requeue_list(struct request *rq, bool at_head) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 9908597c5209..71ca36eab558 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -2045,6 +2045,7 @@ static int blkif_recover(struct blkfront_info *info) BUG_ON(req->nr_phys_segments > segs); blk_mq_requeue_request(req); } + blk_mq_start_stopped_hw_queues(info->rq, true); blk_mq_kick_requeue_list(info->rq); while ((bio = bio_list_pop(&info->bio_list)) != NULL) { diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index f76cc36b8546..a9e9e781bb77 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -338,12 +338,7 @@ static void dm_old_requeue_request(struct request *rq) static void __dm_mq_kick_requeue_list(struct request_queue *q, unsigned long msecs) { - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - if (!blk_queue_stopped(q)) - blk_mq_delay_kick_requeue_list(q, msecs); - spin_unlock_irqrestore(q->queue_lock, flags); + blk_mq_delay_kick_requeue_list(q, msecs); } void dm_mq_kick_requeue_list(struct mapped_device *md) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8c52622ac257..2b78ff12bf3c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1952,7 +1952,6 @@ out_put_device: out: switch (ret) { case BLK_MQ_RQ_QUEUE_BUSY: - blk_mq_stop_hw_queue(hctx); if (atomic_read(&sdev->device_busy) == 0 && !scsi_device_blocked(sdev)) blk_mq_delay_queue(hctx, SCSI_QUEUE_DELAY); -- cgit v1.2.3 From 9b7dd572cc439fa92e120290eb74d0295567c5a0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Oct 2016 17:20:49 -0700 Subject: blk-mq: Remove blk_mq_cancel_requeue_work() Since blk_mq_requeue_work() no longer restarts stopped queues canceling requeue work is no longer needed to prevent that a stopped queue would be restarted. Hence remove this function. Signed-off-by: Bart Van Assche Cc: Mike Snitzer Cc: Keith Busch Cc: Hannes Reinecke Cc: Johannes Thumshirn Reviewed-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-mq.c | 6 ------ drivers/md/dm-rq.c | 2 -- drivers/nvme/host/core.c | 1 - include/linux/blk-mq.h | 1 - 4 files changed, 10 deletions(-) (limited to 'drivers') diff --git a/block/blk-mq.c b/block/blk-mq.c index d95034ae64f6..a461823644fb 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -526,12 +526,6 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head) } EXPORT_SYMBOL(blk_mq_add_to_requeue_list); -void blk_mq_cancel_requeue_work(struct request_queue *q) -{ - cancel_delayed_work_sync(&q->requeue_work); -} -EXPORT_SYMBOL_GPL(blk_mq_cancel_requeue_work); - void blk_mq_kick_requeue_list(struct request_queue *q) { kblockd_schedule_delayed_work(&q->requeue_work, 0); diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index a9e9e781bb77..060ccc5a4b1c 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -116,8 +116,6 @@ static void dm_mq_stop_queue(struct request_queue *q) queue_flag_set(QUEUE_FLAG_STOPPED, q); spin_unlock_irqrestore(q->queue_lock, flags); - /* Avoid that requeuing could restart the queue. */ - blk_mq_cancel_requeue_work(q); blk_mq_stop_hw_queues(q); } diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 329381a28edf..a764c2aa00a1 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2081,7 +2081,6 @@ void nvme_stop_queues(struct nvme_ctrl *ctrl) queue_flag_set(QUEUE_FLAG_STOPPED, ns->queue); spin_unlock_irq(ns->queue->queue_lock); - blk_mq_cancel_requeue_work(ns->queue); blk_mq_stop_hw_queues(ns->queue); } mutex_unlock(&ctrl->namespaces_mutex); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index aa930009fcd3..a85a20f80aaa 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -217,7 +217,6 @@ void __blk_mq_end_request(struct request *rq, int error); void blk_mq_requeue_request(struct request *rq); void blk_mq_add_to_requeue_list(struct request *rq, bool at_head); -void blk_mq_cancel_requeue_work(struct request_queue *q); void blk_mq_kick_requeue_list(struct request_queue *q); void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs); void blk_mq_abort_requeue_list(struct request_queue *q); -- cgit v1.2.3 From 2b053aca76b48e681be57b34ca3a8c2c10b275c5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Oct 2016 17:21:41 -0700 Subject: blk-mq: Add a kick_requeue_list argument to blk_mq_requeue_request() Most blk_mq_requeue_request() and blk_mq_add_to_requeue_list() calls are followed by kicking the requeue list. Hence add an argument to these two functions that allows to kick the requeue list. This was proposed by Christoph Hellwig. Signed-off-by: Bart Van Assche Reviewed-by: Johannes Thumshirn Reviewed-by: Christoph Hellwig Cc: Hannes Reinecke Reviewed-by: Sagi Grimberg Signed-off-by: Jens Axboe --- block/blk-flush.c | 5 +---- block/blk-mq.c | 10 +++++++--- drivers/block/xen-blkfront.c | 2 +- drivers/md/dm-rq.c | 2 +- drivers/nvme/host/core.c | 2 +- drivers/scsi/scsi_lib.c | 4 +--- include/linux/blk-mq.h | 5 +++-- 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/block/blk-flush.c b/block/blk-flush.c index d35beca18481..c486b7aa62ee 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -134,10 +134,7 @@ static void blk_flush_restore_request(struct request *rq) static bool blk_flush_queue_rq(struct request *rq, bool add_front) { if (rq->q->mq_ops) { - struct request_queue *q = rq->q; - - blk_mq_add_to_requeue_list(rq, add_front); - blk_mq_kick_requeue_list(q); + blk_mq_add_to_requeue_list(rq, add_front, true); return false; } else { if (add_front) diff --git a/block/blk-mq.c b/block/blk-mq.c index 3dc323543293..8d3de5bd4d6f 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -492,12 +492,12 @@ static void __blk_mq_requeue_request(struct request *rq) } } -void blk_mq_requeue_request(struct request *rq) +void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list) { __blk_mq_requeue_request(rq); BUG_ON(blk_queued_rq(rq)); - blk_mq_add_to_requeue_list(rq, true); + blk_mq_add_to_requeue_list(rq, true, kick_requeue_list); } EXPORT_SYMBOL(blk_mq_requeue_request); @@ -531,7 +531,8 @@ static void blk_mq_requeue_work(struct work_struct *work) blk_mq_run_hw_queues(q, false); } -void blk_mq_add_to_requeue_list(struct request *rq, bool at_head) +void blk_mq_add_to_requeue_list(struct request *rq, bool at_head, + bool kick_requeue_list) { struct request_queue *q = rq->q; unsigned long flags; @@ -550,6 +551,9 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head) list_add_tail(&rq->queuelist, &q->requeue_list); } spin_unlock_irqrestore(&q->requeue_lock, flags); + + if (kick_requeue_list) + blk_mq_kick_requeue_list(q); } EXPORT_SYMBOL(blk_mq_add_to_requeue_list); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 71ca36eab558..c000fdf048b2 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -2043,7 +2043,7 @@ static int blkif_recover(struct blkfront_info *info) /* Requeue pending requests (flush or discard) */ list_del_init(&req->queuelist); BUG_ON(req->nr_phys_segments > segs); - blk_mq_requeue_request(req); + blk_mq_requeue_request(req, false); } blk_mq_start_stopped_hw_queues(info->rq, true); blk_mq_kick_requeue_list(info->rq); diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 060ccc5a4b1c..315257959fc0 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -347,7 +347,7 @@ EXPORT_SYMBOL(dm_mq_kick_requeue_list); static void dm_mq_delay_requeue_request(struct request *rq, unsigned long msecs) { - blk_mq_requeue_request(rq); + blk_mq_requeue_request(rq, false); __dm_mq_kick_requeue_list(rq->q, msecs); } diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index a764c2aa00a1..e8070e3cc7c7 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -203,7 +203,7 @@ void nvme_requeue_req(struct request *req) { unsigned long flags; - blk_mq_requeue_request(req); + blk_mq_requeue_request(req, false); spin_lock_irqsave(req->q->queue_lock, flags); if (!blk_queue_stopped(req->q)) blk_mq_kick_requeue_list(req->q); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 2b78ff12bf3c..2e35132f8be1 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -86,10 +86,8 @@ scsi_set_blocked(struct scsi_cmnd *cmd, int reason) static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd) { struct scsi_device *sdev = cmd->device; - struct request_queue *q = cmd->request->q; - blk_mq_requeue_request(cmd->request); - blk_mq_kick_requeue_list(q); + blk_mq_requeue_request(cmd->request, true); put_device(&sdev->sdev_gendev); } diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index ed20ac74c62a..35a0af5ede6d 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -218,8 +218,9 @@ void blk_mq_start_request(struct request *rq); void blk_mq_end_request(struct request *rq, int error); void __blk_mq_end_request(struct request *rq, int error); -void blk_mq_requeue_request(struct request *rq); -void blk_mq_add_to_requeue_list(struct request *rq, bool at_head); +void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list); +void blk_mq_add_to_requeue_list(struct request *rq, bool at_head, + bool kick_requeue_list); void blk_mq_kick_requeue_list(struct request_queue *q); void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs); void blk_mq_abort_requeue_list(struct request_queue *q); -- cgit v1.2.3 From f0d33ab76cfcd696328c1330e2462b5d62e74f00 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Oct 2016 17:22:00 -0700 Subject: dm: Use BLK_MQ_S_STOPPED instead of QUEUE_FLAG_STOPPED in blk-mq code Instead of manipulating both QUEUE_FLAG_STOPPED and BLK_MQ_S_STOPPED in the dm start and stop queue functions, only manipulate the latter flag. Change blk_queue_stopped() tests into blk_mq_queue_stopped(). Signed-off-by: Bart Van Assche Acked-by: Mike Snitzer Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Jens Axboe --- drivers/md/dm-rq.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 315257959fc0..09c958b6f038 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -75,12 +75,6 @@ static void dm_old_start_queue(struct request_queue *q) static void dm_mq_start_queue(struct request_queue *q) { - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - queue_flag_clear(QUEUE_FLAG_STOPPED, q); - spin_unlock_irqrestore(q->queue_lock, flags); - blk_mq_start_stopped_hw_queues(q, true); blk_mq_kick_requeue_list(q); } @@ -105,16 +99,8 @@ static void dm_old_stop_queue(struct request_queue *q) static void dm_mq_stop_queue(struct request_queue *q) { - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - if (blk_queue_stopped(q)) { - spin_unlock_irqrestore(q->queue_lock, flags); + if (blk_mq_queue_stopped(q)) return; - } - - queue_flag_set(QUEUE_FLAG_STOPPED, q); - spin_unlock_irqrestore(q->queue_lock, flags); blk_mq_stop_hw_queues(q); } -- cgit v1.2.3 From 7b17c2f7292ba1f3f98dae3f7077f9e569653276 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Oct 2016 17:22:16 -0700 Subject: dm: Fix a race condition related to stopping and starting queues Ensure that all ongoing dm_mq_queue_rq() and dm_mq_requeue_request() calls have stopped before setting the "queue stopped" flag. This allows to remove the "queue stopped" test from dm_mq_queue_rq() and dm_mq_requeue_request(). This patch fixes a race condition because dm_mq_queue_rq() is called without holding the queue lock and hence BLK_MQ_S_STOPPED can be set at any time while dm_mq_queue_rq() is in progress. This patch prevents that the following hang occurs sporadically when using dm-mq: INFO: task systemd-udevd:10111 blocked for more than 480 seconds. Call Trace: [] schedule+0x37/0x90 [] schedule_timeout+0x27f/0x470 [] io_schedule_timeout+0x9f/0x110 [] bit_wait_io+0x16/0x60 [] __wait_on_bit_lock+0x49/0xa0 [] __lock_page+0xb9/0xc0 [] truncate_inode_pages_range+0x3e0/0x760 [] truncate_inode_pages+0x10/0x20 [] kill_bdev+0x30/0x40 [] __blkdev_put+0x71/0x360 [] blkdev_put+0x49/0x170 [] blkdev_close+0x20/0x30 [] __fput+0xe8/0x1f0 [] ____fput+0x9/0x10 [] task_work_run+0x83/0xb0 [] do_exit+0x3ee/0xc40 [] do_group_exit+0x4b/0xc0 [] get_signal+0x2ca/0x940 [] do_signal+0x23/0x660 [] exit_to_usermode_loop+0x73/0xb0 [] syscall_return_slowpath+0xb0/0xc0 [] entry_SYSCALL_64_fastpath+0xa6/0xa8 Signed-off-by: Bart Van Assche Acked-by: Mike Snitzer Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/md/dm-rq.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 09c958b6f038..8b92e066bb69 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -102,7 +102,7 @@ static void dm_mq_stop_queue(struct request_queue *q) if (blk_mq_queue_stopped(q)) return; - blk_mq_stop_hw_queues(q); + blk_mq_quiesce_queue(q); } void dm_stop_queue(struct request_queue *q) @@ -880,17 +880,6 @@ static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, dm_put_live_table(md, srcu_idx); } - /* - * On suspend dm_stop_queue() handles stopping the blk-mq - * request_queue BUT: even though the hw_queues are marked - * BLK_MQ_S_STOPPED at that point there is still a race that - * is allowing block/blk-mq.c to call ->queue_rq against a - * hctx that it really shouldn't. The following check guards - * against this rarity (albeit _not_ race-free). - */ - if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state))) - return BLK_MQ_RQ_QUEUE_BUSY; - if (ti->type->busy && ti->type->busy(ti)) return BLK_MQ_RQ_QUEUE_BUSY; -- cgit v1.2.3 From 3174dd33fa8316d29f238f093291ca9bb25e6f58 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Oct 2016 17:23:19 -0700 Subject: nvme: Fix a race condition related to stopping queues Avoid that nvme_queue_rq() is still running when nvme_stop_queues() returns. Signed-off-by: Bart Van Assche Cc: Keith Busch Reviewed-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index e8070e3cc7c7..75565b5951d9 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2081,7 +2081,7 @@ void nvme_stop_queues(struct nvme_ctrl *ctrl) queue_flag_set(QUEUE_FLAG_STOPPED, ns->queue); spin_unlock_irq(ns->queue->queue_lock); - blk_mq_stop_hw_queues(ns->queue); + blk_mq_quiesce_queue(ns->queue); } mutex_unlock(&ctrl->namespaces_mutex); } -- cgit v1.2.3 From a6eaa8849f92a40f8894d6d0dcab2c16243aaf20 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Oct 2016 17:23:40 -0700 Subject: nvme: Use BLK_MQ_S_STOPPED instead of QUEUE_FLAG_STOPPED in blk-mq code Make nvme_requeue_req() check BLK_MQ_S_STOPPED instead of QUEUE_FLAG_STOPPED. Remove the QUEUE_FLAG_STOPPED manipulations that became superfluous because of this change. Change blk_queue_stopped() tests into blk_mq_queue_stopped(). This patch fixes a race condition: using queue_flag_clear_unlocked() is not safe if any other function that manipulates the queue flags can be called concurrently, e.g. blk_cleanup_queue(). Signed-off-by: Bart Van Assche Cc: Keith Busch Cc: Sagi Grimberg Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 75565b5951d9..ef34f2f3566a 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -201,13 +201,7 @@ fail: void nvme_requeue_req(struct request *req) { - unsigned long flags; - - blk_mq_requeue_request(req, false); - spin_lock_irqsave(req->q->queue_lock, flags); - if (!blk_queue_stopped(req->q)) - blk_mq_kick_requeue_list(req->q); - spin_unlock_irqrestore(req->q->queue_lock, flags); + blk_mq_requeue_request(req, !blk_mq_queue_stopped(req->q)); } EXPORT_SYMBOL_GPL(nvme_requeue_req); @@ -2076,13 +2070,8 @@ void nvme_stop_queues(struct nvme_ctrl *ctrl) struct nvme_ns *ns; mutex_lock(&ctrl->namespaces_mutex); - list_for_each_entry(ns, &ctrl->namespaces, list) { - spin_lock_irq(ns->queue->queue_lock); - queue_flag_set(QUEUE_FLAG_STOPPED, ns->queue); - spin_unlock_irq(ns->queue->queue_lock); - + list_for_each_entry(ns, &ctrl->namespaces, list) blk_mq_quiesce_queue(ns->queue); - } mutex_unlock(&ctrl->namespaces_mutex); } EXPORT_SYMBOL_GPL(nvme_stop_queues); @@ -2093,7 +2082,6 @@ void nvme_start_queues(struct nvme_ctrl *ctrl) mutex_lock(&ctrl->namespaces_mutex); list_for_each_entry(ns, &ctrl->namespaces, list) { - queue_flag_clear_unlocked(QUEUE_FLAG_STOPPED, ns->queue); blk_mq_start_stopped_hw_queues(ns->queue, true); blk_mq_kick_requeue_list(ns->queue); } -- cgit v1.2.3 From ccc109b8ed24c6a84cc46a78ec3df9a57a6c674a Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 2 Nov 2016 17:12:23 +0200 Subject: net/mlx4_en: Add TX_XDP for CQ types Support XDP CQ type, and refactor the CQ type enum. Rename the is_tx field to match the change. Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_cq.c | 18 +++++++++--------- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 7 ++++--- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c index e3be7e44ff51..1427311a9640 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c @@ -65,7 +65,7 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv, cq->buf_size = cq->size * mdev->dev->caps.cqe_size; cq->ring = ring; - cq->is_tx = mode; + cq->type = mode; cq->vector = mdev->dev->caps.num_comp_vectors; /* Allocate HW buffers on provided NUMA node. @@ -104,7 +104,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, *cq->mcq.arm_db = 0; memset(cq->buf, 0, cq->buf_size); - if (cq->is_tx == RX) { + if (cq->type == RX) { if (!mlx4_is_eq_vector_valid(mdev->dev, priv->port, cq->vector)) { cq->vector = cpumask_first(priv->rx_ring[cq->ring]->affinity_mask); @@ -141,11 +141,11 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, cq->vector = rx_cq->vector; } - if (!cq->is_tx) + if (cq->type == RX) cq->size = priv->rx_ring[cq->ring]->actual_size; - if ((cq->is_tx && priv->hwtstamp_config.tx_type) || - (!cq->is_tx && priv->hwtstamp_config.rx_filter)) + if ((cq->type != RX && priv->hwtstamp_config.tx_type) || + (cq->type == RX && priv->hwtstamp_config.rx_filter)) timestamp_en = 1; err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, @@ -154,10 +154,10 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, if (err) goto free_eq; - cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq; + cq->mcq.comp = cq->type != RX ? mlx4_en_tx_irq : mlx4_en_rx_irq; cq->mcq.event = mlx4_en_cq_event; - if (cq->is_tx) + if (cq->type != RX) netif_tx_napi_add(cq->dev, &cq->napi, mlx4_en_poll_tx_cq, NAPI_POLL_WEIGHT); else @@ -181,7 +181,7 @@ void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq) mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size); if (mlx4_is_eq_vector_valid(mdev->dev, priv->port, cq->vector) && - cq->is_tx == RX) + cq->type == RX) mlx4_release_eq(priv->mdev->dev, cq->vector); cq->vector = 0; cq->buf_size = 0; @@ -193,7 +193,7 @@ void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq) void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) { napi_disable(&cq->napi); - if (!cq->is_tx) { + if (cq->type == RX) { napi_hash_del(&cq->napi); synchronize_rcu(); } diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index a3528dd1e72e..83c914a79f14 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -207,8 +207,9 @@ enum { */ enum cq_type { - RX = 0, - TX = 1, + TX, + TX_XDP, + RX, }; @@ -361,7 +362,7 @@ struct mlx4_en_cq { int size; int buf_size; int vector; - enum cq_type is_tx; + enum cq_type type; u16 moder_time; u16 moder_cnt; struct mlx4_cqe *buf; -- cgit v1.2.3 From 67f8b1dcb9ee7f1e165da4eb2ec53483a6b141ea Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 2 Nov 2016 17:12:24 +0200 Subject: net/mlx4_en: Refactor the XDP forwarding rings scheme Separately manage the two types of TX rings: regular ones, and XDP. Upon an XDP set, do not borrow regular TX rings and convert them into XDP ones, but allocate new ones, unless we hit the max number of rings. Which means that in systems with smaller #cores we will not consume the current TX rings for XDP, while we are still in the num TX limit. XDP TX rings counters are not shown in ethtool statistics. Instead, XDP counters will be added to the respective RX rings in a downstream patch. This has no performance implications. Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_cq.c | 10 +- drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 76 +++-- drivers/net/ethernet/mellanox/mlx4/en_main.c | 2 +- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 378 ++++++++++++++---------- drivers/net/ethernet/mellanox/mlx4/en_port.c | 4 +- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 8 +- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 9 +- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 11 +- 8 files changed, 293 insertions(+), 205 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c index 1427311a9640..03f05c4d1f98 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c @@ -127,15 +127,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, /* For TX we use the same irq per ring we assigned for the RX */ struct mlx4_en_cq *rx_cq; - int xdp_index; - - /* The xdp tx irq must align with the rx ring that forwards to - * it, so reindex these from 0. This should only happen when - * tx_ring_num is not a multiple of rx_ring_num. - */ - xdp_index = (priv->xdp_ring_num - priv->tx_ring_num) + cq_idx; - if (xdp_index >= 0) - cq_idx = xdp_index; + cq_idx = cq_idx % priv->rx_ring_num; rx_cq = priv->rx_cq[cq_idx]; cq->vector = rx_cq->vector; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index bdda17d2ea0f..e8ccb95680bc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -49,16 +49,19 @@ static int mlx4_en_moderation_update(struct mlx4_en_priv *priv) { - int i; + int i, t; int err = 0; - for (i = 0; i < priv->tx_ring_num; i++) { - priv->tx_cq[i]->moder_cnt = priv->tx_frames; - priv->tx_cq[i]->moder_time = priv->tx_usecs; - if (priv->port_up) { - err = mlx4_en_set_cq_moder(priv, priv->tx_cq[i]); - if (err) - return err; + for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) { + for (i = 0; i < priv->tx_ring_num[t]; i++) { + priv->tx_cq[t][i]->moder_cnt = priv->tx_frames; + priv->tx_cq[t][i]->moder_time = priv->tx_usecs; + if (priv->port_up) { + err = mlx4_en_set_cq_moder(priv, + priv->tx_cq[t][i]); + if (err) + return err; + } } } @@ -336,7 +339,7 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset) switch (sset) { case ETH_SS_STATS: return bitmap_iterator_count(&it) + - (priv->tx_ring_num * 2) + + (priv->tx_ring_num[TX] * 2) + (priv->rx_ring_num * 3); case ETH_SS_TEST: return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags @@ -397,9 +400,9 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, if (bitmap_iterator_test(&it)) data[index++] = ((unsigned long *)&priv->pkstats)[i]; - for (i = 0; i < priv->tx_ring_num; i++) { - data[index++] = priv->tx_ring[i]->packets; - data[index++] = priv->tx_ring[i]->bytes; + for (i = 0; i < priv->tx_ring_num[TX]; i++) { + data[index++] = priv->tx_ring[TX][i]->packets; + data[index++] = priv->tx_ring[TX][i]->bytes; } for (i = 0; i < priv->rx_ring_num; i++) { data[index++] = priv->rx_ring[i]->packets; @@ -467,7 +470,7 @@ static void mlx4_en_get_strings(struct net_device *dev, strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[strings]); - for (i = 0; i < priv->tx_ring_num; i++) { + for (i = 0; i < priv->tx_ring_num[TX]; i++) { sprintf(data + (index++) * ETH_GSTRING_LEN, "tx%d_packets", i); sprintf(data + (index++) * ETH_GSTRING_LEN, @@ -1060,7 +1063,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev, if (rx_size == (priv->port_up ? priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size) && - tx_size == priv->tx_ring[0]->size) + tx_size == priv->tx_ring[TX][0]->size) return 0; tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); @@ -1105,7 +1108,7 @@ static void mlx4_en_get_ringparam(struct net_device *dev, param->tx_max_pending = MLX4_EN_MAX_TX_SIZE; param->rx_pending = priv->port_up ? priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size; - param->tx_pending = priv->tx_ring[0]->size; + param->tx_pending = priv->tx_ring[TX][0]->size; } static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev) @@ -1710,7 +1713,7 @@ static void mlx4_en_get_channels(struct net_device *dev, channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP; channel->rx_count = priv->rx_ring_num; - channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP; + channel->tx_count = priv->tx_ring_num[TX] / MLX4_EN_NUM_UP; } static int mlx4_en_set_channels(struct net_device *dev, @@ -1721,6 +1724,7 @@ static int mlx4_en_set_channels(struct net_device *dev, struct mlx4_en_port_profile new_prof; struct mlx4_en_priv *tmp; int port_up = 0; + int xdp_count; int err = 0; if (channel->other_count || channel->combined_count || @@ -1729,20 +1733,25 @@ static int mlx4_en_set_channels(struct net_device *dev, !channel->tx_count || !channel->rx_count) return -EINVAL; - if (channel->tx_count * MLX4_EN_NUM_UP <= priv->xdp_ring_num) { - en_err(priv, "Minimum %d tx channels required with XDP on\n", - priv->xdp_ring_num / MLX4_EN_NUM_UP + 1); - return -EINVAL; - } - tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); if (!tmp) return -ENOMEM; mutex_lock(&mdev->state_lock); + xdp_count = priv->tx_ring_num[TX_XDP] ? channel->rx_count : 0; + if (channel->tx_count * MLX4_EN_NUM_UP + xdp_count > MAX_TX_RINGS) { + err = -EINVAL; + en_err(priv, + "Total number of TX and XDP rings (%d) exceeds the maximum supported (%d)\n", + channel->tx_count * MLX4_EN_NUM_UP + xdp_count, + MAX_TX_RINGS); + goto out; + } + memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile)); new_prof.num_tx_rings_p_up = channel->tx_count; - new_prof.tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP; + new_prof.tx_ring_num[TX] = channel->tx_count * MLX4_EN_NUM_UP; + new_prof.tx_ring_num[TX_XDP] = xdp_count; new_prof.rx_ring_num = channel->rx_count; err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof); @@ -1756,14 +1765,13 @@ static int mlx4_en_set_channels(struct net_device *dev, mlx4_en_safe_replace_resources(priv, tmp); - netif_set_real_num_tx_queues(dev, priv->tx_ring_num - - priv->xdp_ring_num); + netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]); netif_set_real_num_rx_queues(dev, priv->rx_ring_num); if (dev->num_tc) mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP); - en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num); + en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num[TX]); en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num); if (port_up) { @@ -1774,8 +1782,8 @@ static int mlx4_en_set_channels(struct net_device *dev, err = mlx4_en_moderation_update(priv); out: - kfree(tmp); mutex_unlock(&mdev->state_lock); + kfree(tmp); return err; } @@ -1823,11 +1831,15 @@ static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags) int ret = 0; if (bf_enabled_new != bf_enabled_old) { + int t; + if (bf_enabled_new) { bool bf_supported = true; - for (i = 0; i < priv->tx_ring_num; i++) - bf_supported &= priv->tx_ring[i]->bf_alloced; + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) + for (i = 0; i < priv->tx_ring_num[t]; i++) + bf_supported &= + priv->tx_ring[t][i]->bf_alloced; if (!bf_supported) { en_err(priv, "BlueFlame is not supported\n"); @@ -1839,8 +1851,10 @@ static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags) priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME; } - for (i = 0; i < priv->tx_ring_num; i++) - priv->tx_ring[i]->bf_enabled = bf_enabled_new; + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) + for (i = 0; i < priv->tx_ring_num[t]; i++) + priv->tx_ring[t][i]->bf_enabled = + bf_enabled_new; en_info(priv, "BlueFlame %s\n", bf_enabled_new ? "Enabled" : "Disabled"); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index bf7628db098a..36a7a54bbb82 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -169,7 +169,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->prof[i].tx_ppp = pfctx; params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE; params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; - params->prof[i].tx_ring_num = params->num_tx_rings_p_up * + params->prof[i].tx_ring_num[TX] = params->num_tx_rings_p_up * MLX4_EN_NUM_UP; params->prof[i].rss_rings = 0; params->prof[i].inline_thold = inline_thold; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 58b749dd6125..edf0a99177e1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1214,8 +1214,8 @@ static void mlx4_en_netpoll(struct net_device *dev) struct mlx4_en_cq *cq; int i; - for (i = 0; i < priv->tx_ring_num; i++) { - cq = priv->tx_cq[i]; + for (i = 0; i < priv->tx_ring_num[TX]; i++) { + cq = priv->tx_cq[TX][i]; napi_schedule(&cq->napi); } } @@ -1299,12 +1299,14 @@ static void mlx4_en_tx_timeout(struct net_device *dev) if (netif_msg_timer(priv)) en_warn(priv, "Tx timeout called on port:%d\n", priv->port); - for (i = 0; i < priv->tx_ring_num; i++) { + for (i = 0; i < priv->tx_ring_num[TX]; i++) { + struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX][i]; + if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, i))) continue; en_warn(priv, "TX timeout on queue: %d, QP: 0x%x, CQ: 0x%x, Cons: 0x%x, Prod: 0x%x\n", - i, priv->tx_ring[i]->qpn, priv->tx_ring[i]->cqn, - priv->tx_ring[i]->cons, priv->tx_ring[i]->prod); + i, tx_ring->qpn, tx_ring->cqn, + tx_ring->cons, tx_ring->prod); } priv->port_stats.tx_timeout++; @@ -1328,7 +1330,7 @@ mlx4_en_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv) { struct mlx4_en_cq *cq; - int i; + int i, t; /* If we haven't received a specific coalescing setting * (module param), we set the moderation parameters as follows: @@ -1353,10 +1355,12 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv) priv->last_moder_bytes[i] = 0; } - for (i = 0; i < priv->tx_ring_num; i++) { - cq = priv->tx_cq[i]; - cq->moder_cnt = priv->tx_frames; - cq->moder_time = priv->tx_usecs; + for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) { + for (i = 0; i < priv->tx_ring_num[t]; i++) { + cq = priv->tx_cq[t][i]; + cq->moder_cnt = priv->tx_frames; + cq->moder_time = priv->tx_usecs; + } } /* Reset auto-moderation params */ @@ -1526,19 +1530,13 @@ static void mlx4_en_free_affinity_hint(struct mlx4_en_priv *priv, int ring_idx) static void mlx4_en_init_recycle_ring(struct mlx4_en_priv *priv, int tx_ring_idx) { - struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[tx_ring_idx]; - int rr_index; + struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX_XDP][tx_ring_idx]; + int rr_index = tx_ring_idx; - rr_index = (priv->xdp_ring_num - priv->tx_ring_num) + tx_ring_idx; - if (rr_index >= 0) { - tx_ring->free_tx_desc = mlx4_en_recycle_tx_desc; - tx_ring->recycle_ring = priv->rx_ring[rr_index]; - en_dbg(DRV, priv, - "Set tx_ring[%d]->recycle_ring = rx_ring[%d]\n", - tx_ring_idx, rr_index); - } else { - tx_ring->recycle_ring = NULL; - } + tx_ring->free_tx_desc = mlx4_en_recycle_tx_desc; + tx_ring->recycle_ring = priv->rx_ring[rr_index]; + en_dbg(DRV, priv, "Set tx_ring[%d][%d]->recycle_ring = rx_ring[%d]\n", + TX_XDP, tx_ring_idx, rr_index); } int mlx4_en_start_port(struct net_device *dev) @@ -1548,9 +1546,8 @@ int mlx4_en_start_port(struct net_device *dev) struct mlx4_en_cq *cq; struct mlx4_en_tx_ring *tx_ring; int rx_index = 0; - int tx_index = 0; int err = 0; - int i; + int i, t; int j; u8 mc_list[16] = {0}; @@ -1635,43 +1632,51 @@ int mlx4_en_start_port(struct net_device *dev) goto rss_err; /* Configure tx cq's and rings */ - for (i = 0; i < priv->tx_ring_num; i++) { - /* Configure cq */ - cq = priv->tx_cq[i]; - err = mlx4_en_activate_cq(priv, cq, i); - if (err) { - en_err(priv, "Failed allocating Tx CQ\n"); - goto tx_err; - } - err = mlx4_en_set_cq_moder(priv, cq); - if (err) { - en_err(priv, "Failed setting cq moderation parameters\n"); - mlx4_en_deactivate_cq(priv, cq); - goto tx_err; - } - en_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i); - cq->buf->wqe_index = cpu_to_be16(0xffff); + for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) { + u8 num_tx_rings_p_up = t == TX ? priv->num_tx_rings_p_up : 1; - /* Configure ring */ - tx_ring = priv->tx_ring[i]; - err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn, - i / priv->num_tx_rings_p_up); - if (err) { - en_err(priv, "Failed allocating Tx ring\n"); - mlx4_en_deactivate_cq(priv, cq); - goto tx_err; - } - tx_ring->tx_queue = netdev_get_tx_queue(dev, i); - - mlx4_en_init_recycle_ring(priv, i); + for (i = 0; i < priv->tx_ring_num[t]; i++) { + /* Configure cq */ + cq = priv->tx_cq[t][i]; + err = mlx4_en_activate_cq(priv, cq, i); + if (err) { + en_err(priv, "Failed allocating Tx CQ\n"); + goto tx_err; + } + err = mlx4_en_set_cq_moder(priv, cq); + if (err) { + en_err(priv, "Failed setting cq moderation parameters\n"); + mlx4_en_deactivate_cq(priv, cq); + goto tx_err; + } + en_dbg(DRV, priv, + "Resetting index of collapsed CQ:%d to -1\n", i); + cq->buf->wqe_index = cpu_to_be16(0xffff); + + /* Configure ring */ + tx_ring = priv->tx_ring[t][i]; + err = mlx4_en_activate_tx_ring(priv, tx_ring, + cq->mcq.cqn, + i / num_tx_rings_p_up); + if (err) { + en_err(priv, "Failed allocating Tx ring\n"); + mlx4_en_deactivate_cq(priv, cq); + goto tx_err; + } + if (t != TX_XDP) { + tx_ring->tx_queue = netdev_get_tx_queue(dev, i); + tx_ring->recycle_ring = NULL; + } else { + mlx4_en_init_recycle_ring(priv, i); + } - /* Arm CQ for TX completions */ - mlx4_en_arm_cq(priv, cq); + /* Arm CQ for TX completions */ + mlx4_en_arm_cq(priv, cq); - /* Set initial ownership of all Tx TXBBs to SW (1) */ - for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE) - *((u32 *) (tx_ring->buf + j)) = 0xffffffff; - ++tx_index; + /* Set initial ownership of all Tx TXBBs to SW (1) */ + for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE) + *((u32 *)(tx_ring->buf + j)) = 0xffffffff; + } } /* Configure port */ @@ -1746,9 +1751,18 @@ int mlx4_en_start_port(struct net_device *dev) return 0; tx_err: - while (tx_index--) { - mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[tx_index]); - mlx4_en_deactivate_cq(priv, priv->tx_cq[tx_index]); + if (t == MLX4_EN_NUM_TX_TYPES) { + t--; + i = priv->tx_ring_num[t]; + } + while (t >= 0) { + while (i--) { + mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[t][i]); + mlx4_en_deactivate_cq(priv, priv->tx_cq[t][i]); + } + if (!t--) + break; + i = priv->tx_ring_num[t]; } mlx4_en_destroy_drop_qp(priv); rss_err: @@ -1773,7 +1787,7 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_mc_list *mclist, *tmp; struct ethtool_flow_id *flow, *tmp_flow; - int i; + int i, t; u8 mc_list[16] = {0}; if (!priv->port_up) { @@ -1859,14 +1873,17 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) mlx4_en_destroy_drop_qp(priv); /* Free TX Rings */ - for (i = 0; i < priv->tx_ring_num; i++) { - mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[i]); - mlx4_en_deactivate_cq(priv, priv->tx_cq[i]); + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + for (i = 0; i < priv->tx_ring_num[t]; i++) { + mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[t][i]); + mlx4_en_deactivate_cq(priv, priv->tx_cq[t][i]); + } } msleep(10); - for (i = 0; i < priv->tx_ring_num; i++) - mlx4_en_free_tx_buf(dev, priv->tx_ring[i]); + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) + for (i = 0; i < priv->tx_ring_num[t]; i++) + mlx4_en_free_tx_buf(dev, priv->tx_ring[t][i]); if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0) mlx4_en_delete_rss_steer_rules(priv); @@ -1915,6 +1932,7 @@ static void mlx4_en_clear_stats(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; + struct mlx4_en_tx_ring **tx_ring; int i; if (!mlx4_is_slave(mdev->dev)) @@ -1932,15 +1950,16 @@ static void mlx4_en_clear_stats(struct net_device *dev) sizeof(priv->tx_priority_flowstats)); memset(&priv->pf_stats, 0, sizeof(priv->pf_stats)); - for (i = 0; i < priv->tx_ring_num; i++) { - priv->tx_ring[i]->bytes = 0; - priv->tx_ring[i]->packets = 0; - priv->tx_ring[i]->tx_csum = 0; - priv->tx_ring[i]->tx_dropped = 0; - priv->tx_ring[i]->queue_stopped = 0; - priv->tx_ring[i]->wake_queue = 0; - priv->tx_ring[i]->tso_packets = 0; - priv->tx_ring[i]->xmit_more = 0; + tx_ring = priv->tx_ring[TX]; + for (i = 0; i < priv->tx_ring_num[TX]; i++) { + tx_ring[i]->bytes = 0; + tx_ring[i]->packets = 0; + tx_ring[i]->tx_csum = 0; + tx_ring[i]->tx_dropped = 0; + tx_ring[i]->queue_stopped = 0; + tx_ring[i]->wake_queue = 0; + tx_ring[i]->tso_packets = 0; + tx_ring[i]->xmit_more = 0; } for (i = 0; i < priv->rx_ring_num; i++) { priv->rx_ring[i]->bytes = 0; @@ -1996,17 +2015,20 @@ static int mlx4_en_close(struct net_device *dev) static void mlx4_en_free_resources(struct mlx4_en_priv *priv) { - int i; + int i, t; #ifdef CONFIG_RFS_ACCEL priv->dev->rx_cpu_rmap = NULL; #endif - for (i = 0; i < priv->tx_ring_num; i++) { - if (priv->tx_ring && priv->tx_ring[i]) - mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]); - if (priv->tx_cq && priv->tx_cq[i]) - mlx4_en_destroy_cq(priv, &priv->tx_cq[i]); + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + for (i = 0; i < priv->tx_ring_num[t]; i++) { + if (priv->tx_ring[t] && priv->tx_ring[t][i]) + mlx4_en_destroy_tx_ring(priv, + &priv->tx_ring[t][i]); + if (priv->tx_cq[t] && priv->tx_cq[t][i]) + mlx4_en_destroy_cq(priv, &priv->tx_cq[t][i]); + } } for (i = 0; i < priv->rx_ring_num; i++) { @@ -2022,20 +2044,22 @@ static void mlx4_en_free_resources(struct mlx4_en_priv *priv) static int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) { struct mlx4_en_port_profile *prof = priv->prof; - int i; + int i, t; int node; /* Create tx Rings */ - for (i = 0; i < priv->tx_ring_num; i++) { - node = cpu_to_node(i % num_online_cpus()); - if (mlx4_en_create_cq(priv, &priv->tx_cq[i], - prof->tx_ring_size, i, TX, node)) - goto err; - - if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i], - prof->tx_ring_size, TXBB_SIZE, - node, i)) - goto err; + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + for (i = 0; i < priv->tx_ring_num[t]; i++) { + node = cpu_to_node(i % num_online_cpus()); + if (mlx4_en_create_cq(priv, &priv->tx_cq[t][i], + prof->tx_ring_size, i, t, node)) + goto err; + + if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[t][i], + prof->tx_ring_size, + TXBB_SIZE, node, i)) + goto err; + } } /* Create rx Rings */ @@ -2067,11 +2091,14 @@ err: if (priv->rx_cq[i]) mlx4_en_destroy_cq(priv, &priv->rx_cq[i]); } - for (i = 0; i < priv->tx_ring_num; i++) { - if (priv->tx_ring[i]) - mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]); - if (priv->tx_cq[i]) - mlx4_en_destroy_cq(priv, &priv->tx_cq[i]); + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + for (i = 0; i < priv->tx_ring_num[t]; i++) { + if (priv->tx_ring[t][i]) + mlx4_en_destroy_tx_ring(priv, + &priv->tx_ring[t][i]); + if (priv->tx_cq[t][i]) + mlx4_en_destroy_cq(priv, &priv->tx_cq[t][i]); + } } return -ENOMEM; } @@ -2088,10 +2115,11 @@ static int mlx4_en_copy_priv(struct mlx4_en_priv *dst, struct mlx4_en_priv *src, struct mlx4_en_port_profile *prof) { + int t; + memcpy(&dst->hwtstamp_config, &prof->hwtstamp_config, sizeof(dst->hwtstamp_config)); dst->num_tx_rings_p_up = src->mdev->profile.num_tx_rings_p_up; - dst->tx_ring_num = prof->tx_ring_num; dst->rx_ring_num = prof->rx_ring_num; dst->flags = prof->flags; dst->mdev = src->mdev; @@ -2101,33 +2129,50 @@ static int mlx4_en_copy_priv(struct mlx4_en_priv *dst, dst->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + DS_SIZE * MLX4_EN_MAX_RX_FRAGS); - dst->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring *) * MAX_TX_RINGS, - GFP_KERNEL); - if (!dst->tx_ring) - return -ENOMEM; + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + dst->tx_ring_num[t] = prof->tx_ring_num[t]; + if (!dst->tx_ring_num[t]) + continue; - dst->tx_cq = kzalloc(sizeof(struct mlx4_en_cq *) * MAX_TX_RINGS, - GFP_KERNEL); - if (!dst->tx_cq) { - kfree(dst->tx_ring); - return -ENOMEM; + dst->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) * + MAX_TX_RINGS, GFP_KERNEL); + if (!dst->tx_ring[t]) + goto err_free_tx; + + dst->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) * + MAX_TX_RINGS, GFP_KERNEL); + if (!dst->tx_cq[t]) { + kfree(dst->tx_ring[t]); + goto err_free_tx; + } } + return 0; + +err_free_tx: + while (t--) { + kfree(dst->tx_ring[t]); + kfree(dst->tx_cq[t]); + } + return -ENOMEM; } static void mlx4_en_update_priv(struct mlx4_en_priv *dst, struct mlx4_en_priv *src) { + int t; memcpy(dst->rx_ring, src->rx_ring, sizeof(struct mlx4_en_rx_ring *) * src->rx_ring_num); memcpy(dst->rx_cq, src->rx_cq, sizeof(struct mlx4_en_cq *) * src->rx_ring_num); memcpy(&dst->hwtstamp_config, &src->hwtstamp_config, sizeof(dst->hwtstamp_config)); - dst->tx_ring_num = src->tx_ring_num; + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + dst->tx_ring_num[t] = src->tx_ring_num[t]; + dst->tx_ring[t] = src->tx_ring[t]; + dst->tx_cq[t] = src->tx_cq[t]; + } dst->rx_ring_num = src->rx_ring_num; - dst->tx_ring = src->tx_ring; - dst->tx_cq = src->tx_cq; memcpy(dst->prof, src->prof, sizeof(struct mlx4_en_port_profile)); } @@ -2135,14 +2180,18 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, struct mlx4_en_priv *tmp, struct mlx4_en_port_profile *prof) { + int t; + mlx4_en_copy_priv(tmp, priv, prof); if (mlx4_en_alloc_resources(tmp)) { en_warn(priv, "%s: Resource allocation failed, using previous configuration\n", __func__); - kfree(tmp->tx_ring); - kfree(tmp->tx_cq); + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + kfree(tmp->tx_ring[t]); + kfree(tmp->tx_cq[t]); + } return -ENOMEM; } return 0; @@ -2161,6 +2210,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev) struct mlx4_en_dev *mdev = priv->mdev; bool shutdown = mdev->dev->persist->interface_state & MLX4_INTERFACE_STATE_SHUTDOWN; + int t; en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port); @@ -2197,8 +2247,10 @@ void mlx4_en_destroy_netdev(struct net_device *dev) mlx4_en_free_resources(priv); - kfree(priv->tx_ring); - kfree(priv->tx_cq); + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + kfree(priv->tx_ring[t]); + kfree(priv->tx_cq[t]); + } if (!shutdown) free_netdev(dev); @@ -2214,7 +2266,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) en_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n", dev->mtu, new_mtu); - if (priv->xdp_ring_num && MLX4_EN_EFF_MTU(new_mtu) > FRAG_SZ0) { + if (priv->tx_ring_num[TX_XDP] && MLX4_EN_EFF_MTU(new_mtu) > FRAG_SZ0) { en_err(priv, "MTU size:%d requires frags but XDP running\n", new_mtu); return -EOPNOTSUPP; @@ -2605,7 +2657,7 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb, static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 maxrate) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[queue_index]; + struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX][queue_index]; struct mlx4_update_qp_params params; int err; @@ -2633,18 +2685,21 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; + struct mlx4_en_port_profile new_prof; struct bpf_prog *old_prog; + struct mlx4_en_priv *tmp; + int tx_changed = 0; int xdp_ring_num; int port_up = 0; int err; int i; - xdp_ring_num = prog ? ALIGN(priv->rx_ring_num, MLX4_EN_NUM_UP) : 0; + xdp_ring_num = prog ? priv->rx_ring_num : 0; /* No need to reconfigure buffers when simply swapping the * program for a new one. */ - if (priv->xdp_ring_num == xdp_ring_num) { + if (priv->tx_ring_num[TX_XDP] == xdp_ring_num) { if (prog) { prog = bpf_prog_add(prog, priv->rx_ring_num - 1); if (IS_ERR(prog)) @@ -2668,28 +2723,41 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog) return -EOPNOTSUPP; } - if (priv->tx_ring_num < xdp_ring_num + MLX4_EN_NUM_UP) { - en_err(priv, - "Minimum %d tx channels required to run XDP\n", - (xdp_ring_num + MLX4_EN_NUM_UP) / MLX4_EN_NUM_UP); - return -EINVAL; - } + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; if (prog) { prog = bpf_prog_add(prog, priv->rx_ring_num - 1); - if (IS_ERR(prog)) - return PTR_ERR(prog); + if (IS_ERR(prog)) { + err = PTR_ERR(prog); + goto out; + } } mutex_lock(&mdev->state_lock); + memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile)); + new_prof.tx_ring_num[TX_XDP] = xdp_ring_num; + + if (priv->tx_ring_num[TX] + xdp_ring_num > MAX_TX_RINGS) { + tx_changed = 1; + new_prof.tx_ring_num[TX] = + MAX_TX_RINGS - ALIGN(xdp_ring_num, MLX4_EN_NUM_UP); + en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n"); + } + + err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof); + if (err) + goto unlock_out; + if (priv->port_up) { port_up = 1; mlx4_en_stop_port(dev, 1); } - priv->xdp_ring_num = xdp_ring_num; - netif_set_real_num_tx_queues(dev, priv->tx_ring_num - - priv->xdp_ring_num); + mlx4_en_safe_replace_resources(priv, tmp); + if (tx_changed) + netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]); for (i = 0; i < priv->rx_ring_num; i++) { old_prog = rcu_dereference_protected( @@ -2709,15 +2777,18 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog) } } +unlock_out: mutex_unlock(&mdev->state_lock); - return 0; +out: + kfree(tmp); + return err; } static bool mlx4_xdp_attached(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); - return !!priv->xdp_ring_num; + return !!priv->tx_ring_num[TX_XDP]; } static int mlx4_xdp(struct net_device *dev, struct netdev_xdp *xdp) @@ -3061,7 +3132,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, { struct net_device *dev; struct mlx4_en_priv *priv; - int i; + int i, t; int err; dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv), @@ -3069,7 +3140,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, if (dev == NULL) return -ENOMEM; - netif_set_real_num_tx_queues(dev, prof->tx_ring_num); + netif_set_real_num_tx_queues(dev, prof->tx_ring_num[TX]); netif_set_real_num_rx_queues(dev, prof->rx_ring_num); SET_NETDEV_DEV(dev, &mdev->dev->persist->pdev->dev); @@ -3106,21 +3177,27 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE | MLX4_WQE_CTRL_SOLICITED); priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up; - priv->tx_ring_num = prof->tx_ring_num; priv->tx_work_limit = MLX4_EN_DEFAULT_TX_WORK; netdev_rss_key_fill(priv->rss_key, sizeof(priv->rss_key)); - priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring *) * MAX_TX_RINGS, - GFP_KERNEL); - if (!priv->tx_ring) { - err = -ENOMEM; - goto out; - } - priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq *) * MAX_TX_RINGS, - GFP_KERNEL); - if (!priv->tx_cq) { - err = -ENOMEM; - goto out; + for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) { + priv->tx_ring_num[t] = prof->tx_ring_num[t]; + if (!priv->tx_ring_num[t]) + continue; + + priv->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) * + MAX_TX_RINGS, GFP_KERNEL); + if (!priv->tx_ring[t]) { + err = -ENOMEM; + goto err_free_tx; + } + priv->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) * + MAX_TX_RINGS, GFP_KERNEL); + if (!priv->tx_cq[t]) { + kfree(priv->tx_ring[t]); + err = -ENOMEM; + goto out; + } } priv->rx_ring_num = prof->rx_ring_num; priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0; @@ -3203,7 +3280,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, else dev->netdev_ops = &mlx4_netdev_ops; dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT; - netif_set_real_num_tx_queues(dev, priv->tx_ring_num); + netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]); netif_set_real_num_rx_queues(dev, priv->rx_ring_num); dev->ethtool_ops = &mlx4_en_ethtool_ops; @@ -3303,7 +3380,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, netif_carrier_off(dev); mlx4_en_set_default_moderation(priv); - en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num); + en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num[TX]); en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num); mlx4_en_update_loopback_state(priv->dev, priv->dev->features); @@ -3363,6 +3440,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, return 0; +err_free_tx: + while (t--) { + kfree(priv->tx_ring[t]); + kfree(priv->tx_cq[t]); + } out: mlx4_en_destroy_netdev(dev); return err; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c index 59473a0ebcdf..2e1ab4642569 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_port.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c @@ -196,8 +196,8 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) priv->port_stats.tso_packets = 0; priv->port_stats.xmit_more = 0; - for (i = 0; i < priv->tx_ring_num; i++) { - const struct mlx4_en_tx_ring *ring = priv->tx_ring[i]; + for (i = 0; i < priv->tx_ring_num[TX]; i++) { + const struct mlx4_en_tx_ring *ring = priv->tx_ring[TX][i]; stats->tx_packets += ring->packets; stats->tx_bytes += ring->bytes; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index f2e8beddcf44..71196f68b55d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -788,7 +788,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud struct bpf_prog *xdp_prog; int doorbell_pending; struct sk_buff *skb; - int tx_index; int index; int nr; unsigned int length; @@ -808,7 +807,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud rcu_read_lock(); xdp_prog = rcu_dereference(ring->xdp_prog); doorbell_pending = 0; - tx_index = (priv->tx_ring_num - priv->xdp_ring_num) + cq->ring; /* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx * descriptor offset can be deduced from the CQE index instead of @@ -905,7 +903,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud break; case XDP_TX: if (likely(!mlx4_en_xmit_frame(frags, dev, - length, tx_index, + length, cq->ring, &doorbell_pending))) goto consumed; goto xdp_drop; /* Drop on xmit failure */ @@ -1082,7 +1080,7 @@ consumed: out: rcu_read_unlock(); if (doorbell_pending) - mlx4_en_xmit_doorbell(priv->tx_ring[tx_index]); + mlx4_en_xmit_doorbell(priv->tx_ring[TX_XDP][cq->ring]); AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled); mlx4_cq_set_ci(&cq->mcq); @@ -1162,7 +1160,7 @@ void mlx4_en_calc_rx_buf(struct net_device *dev) /* bpf requires buffers to be set up as 1 packet per page. * This only works when num_frags == 1. */ - if (priv->xdp_ring_num) { + if (priv->tx_ring_num[TX_XDP]) { dma_dir = PCI_DMA_BIDIRECTIONAL; /* This will gain efficient xdp frame recycling at the expense * of more costly truesize accounting diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index e2509bba3e7c..95dc864bb2f7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -392,7 +392,8 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring) cnt++; } - netdev_tx_reset_queue(ring->tx_queue); + if (ring->tx_queue) + netdev_tx_reset_queue(ring->tx_queue); if (cnt) en_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt); @@ -405,7 +406,7 @@ static bool mlx4_en_process_tx_cq(struct net_device *dev, { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_cq *mcq = &cq->mcq; - struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; + struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->type][cq->ring]; struct mlx4_cqe *cqe; u16 index; u16 new_index, ring_index, stamp_index; @@ -807,7 +808,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) bool bf_ok; tx_ind = skb_get_queue_mapping(skb); - ring = priv->tx_ring[tx_ind]; + ring = priv->tx_ring[TX][tx_ind]; if (!priv->port_up) goto tx_drop; @@ -1101,7 +1102,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame, BUILD_BUG_ON_MSG(ALIGN(CTRL_SIZE + DS_SIZE, TXBB_SIZE) != TXBB_SIZE, "mlx4_en_xmit_frame requires minimum size tx desc"); - ring = priv->tx_ring[tx_ind]; + ring = priv->tx_ring[TX_XDP][tx_ind]; if (!priv->port_up) goto tx_drop; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 83c914a79f14..6e0693659f85 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -207,8 +207,10 @@ enum { */ enum cq_type { + /* keep tx types first */ TX, TX_XDP, +#define MLX4_EN_NUM_TX_TYPES (TX_XDP + 1) RX, }; @@ -373,7 +375,7 @@ struct mlx4_en_cq { struct mlx4_en_port_profile { u32 flags; - u32 tx_ring_num; + u32 tx_ring_num[MLX4_EN_NUM_TX_TYPES]; u32 rx_ring_num; u32 tx_ring_size; u32 rx_ring_size; @@ -570,17 +572,16 @@ struct mlx4_en_priv { u32 flags; u8 num_tx_rings_p_up; u32 tx_work_limit; - u32 tx_ring_num; + u32 tx_ring_num[MLX4_EN_NUM_TX_TYPES]; u32 rx_ring_num; u32 rx_skb_size; struct mlx4_en_frag_info frag_info[MLX4_EN_MAX_RX_FRAGS]; u16 num_frags; u16 log_rx_info; - int xdp_ring_num; - struct mlx4_en_tx_ring **tx_ring; + struct mlx4_en_tx_ring **tx_ring[MLX4_EN_NUM_TX_TYPES]; struct mlx4_en_rx_ring *rx_ring[MAX_RX_RINGS]; - struct mlx4_en_cq **tx_cq; + struct mlx4_en_cq **tx_cq[MLX4_EN_NUM_TX_TYPES]; struct mlx4_en_cq *rx_cq[MAX_RX_RINGS]; struct mlx4_qp drop_qp; struct work_struct rx_mode_task; -- cgit v1.2.3 From 15fca2c8eb4166123a3edbd151765b00af190b75 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 2 Nov 2016 17:12:25 +0200 Subject: net/mlx4_en: Add ethtool statistics for XDP cases XDP statistics are reported in ethtool, in total and per ring, as follows: - xdp_drop: the number of packets dropped by xdp. - xdp_tx: the number of packets forwarded by xdp. - xdp_tx_full: the number of times an xdp forward failed due to a full tx xdp ring. In addition, all packets that are dropped/forwarded by XDP are no longer accounted in rx_packets/rx_bytes of the ring, so that they count traffic that is passed to the stack. Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 25 ++++++++++++++++++++++++- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 4 ++++ drivers/net/ethernet/mellanox/mlx4/en_port.c | 6 ++++++ drivers/net/ethernet/mellanox/mlx4/en_rx.c | 12 +++++++----- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 8 ++++---- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 7 ++++++- drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h | 10 +++++++++- 7 files changed, 60 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index e8ccb95680bc..487a58f9c192 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -195,6 +195,10 @@ static const char main_strings[][ETH_GSTRING_LEN] = { "tx_prio_7_packets", "tx_prio_7_bytes", "tx_novlan_packets", "tx_novlan_bytes", + /* xdp statistics */ + "rx_xdp_drop", + "rx_xdp_tx", + "rx_xdp_tx_full", }; static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= { @@ -340,7 +344,7 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset) case ETH_SS_STATS: return bitmap_iterator_count(&it) + (priv->tx_ring_num[TX] * 2) + - (priv->rx_ring_num * 3); + (priv->rx_ring_num * (3 + NUM_XDP_STATS)); case ETH_SS_TEST: return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2; @@ -400,6 +404,10 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, if (bitmap_iterator_test(&it)) data[index++] = ((unsigned long *)&priv->pkstats)[i]; + for (i = 0; i < NUM_XDP_STATS; i++, bitmap_iterator_inc(&it)) + if (bitmap_iterator_test(&it)) + data[index++] = ((unsigned long *)&priv->xdp_stats)[i]; + for (i = 0; i < priv->tx_ring_num[TX]; i++) { data[index++] = priv->tx_ring[TX][i]->packets; data[index++] = priv->tx_ring[TX][i]->bytes; @@ -408,6 +416,9 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, data[index++] = priv->rx_ring[i]->packets; data[index++] = priv->rx_ring[i]->bytes; data[index++] = priv->rx_ring[i]->dropped; + data[index++] = priv->rx_ring[i]->xdp_drop; + data[index++] = priv->rx_ring[i]->xdp_tx; + data[index++] = priv->rx_ring[i]->xdp_tx_full; } spin_unlock_bh(&priv->stats_lock); @@ -470,6 +481,12 @@ static void mlx4_en_get_strings(struct net_device *dev, strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[strings]); + for (i = 0; i < NUM_XDP_STATS; i++, strings++, + bitmap_iterator_inc(&it)) + if (bitmap_iterator_test(&it)) + strcpy(data + (index++) * ETH_GSTRING_LEN, + main_strings[strings]); + for (i = 0; i < priv->tx_ring_num[TX]; i++) { sprintf(data + (index++) * ETH_GSTRING_LEN, "tx%d_packets", i); @@ -483,6 +500,12 @@ static void mlx4_en_get_strings(struct net_device *dev, "rx%d_bytes", i); sprintf(data + (index++) * ETH_GSTRING_LEN, "rx%d_dropped", i); + sprintf(data + (index++) * ETH_GSTRING_LEN, + "rx%d_xdp_drop", i); + sprintf(data + (index++) * ETH_GSTRING_LEN, + "rx%d_xdp_tx", i); + sprintf(data + (index++) * ETH_GSTRING_LEN, + "rx%d_xdp_tx_full", i); } break; case ETH_SS_PRIV_FLAGS: diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index edf0a99177e1..0f6225c042be 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -3125,6 +3125,10 @@ void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev, if (!mlx4_is_slave(dev)) bitmap_set(stats_bitmap->bitmap, last_i, NUM_PKT_STATS); + last_i += NUM_PKT_STATS; + + bitmap_set(stats_bitmap->bitmap, last_i, NUM_XDP_STATS); + last_i += NUM_XDP_STATS; } int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c index 2e1ab4642569..1eb4c1e10bad 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_port.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c @@ -179,6 +179,9 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) priv->port_stats.rx_chksum_good = 0; priv->port_stats.rx_chksum_none = 0; priv->port_stats.rx_chksum_complete = 0; + priv->xdp_stats.rx_xdp_drop = 0; + priv->xdp_stats.rx_xdp_tx = 0; + priv->xdp_stats.rx_xdp_tx_full = 0; for (i = 0; i < priv->rx_ring_num; i++) { stats->rx_packets += priv->rx_ring[i]->packets; stats->rx_bytes += priv->rx_ring[i]->bytes; @@ -186,6 +189,9 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok; priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none; priv->port_stats.rx_chksum_complete += priv->rx_ring[i]->csum_complete; + priv->xdp_stats.rx_xdp_drop += priv->rx_ring[i]->xdp_drop; + priv->xdp_stats.rx_xdp_tx += priv->rx_ring[i]->xdp_tx; + priv->xdp_stats.rx_xdp_tx_full += priv->rx_ring[i]->xdp_tx_full; } stats->tx_packets = 0; stats->tx_bytes = 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 71196f68b55d..2cc91002064f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -875,8 +875,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud */ length = be32_to_cpu(cqe->byte_cnt); length -= ring->fcs_del; - ring->bytes += length; - ring->packets++; l2_tunnel = (dev->hw_enc_features & NETIF_F_RXCSUM) && (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_L2_TUNNEL)); @@ -902,22 +900,26 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud case XDP_PASS: break; case XDP_TX: - if (likely(!mlx4_en_xmit_frame(frags, dev, + if (likely(!mlx4_en_xmit_frame(ring, frags, dev, length, cq->ring, &doorbell_pending))) goto consumed; - goto xdp_drop; /* Drop on xmit failure */ + goto xdp_drop_no_cnt; /* Drop on xmit failure */ default: bpf_warn_invalid_xdp_action(act); case XDP_ABORTED: case XDP_DROP: -xdp_drop: + ring->xdp_drop++; +xdp_drop_no_cnt: if (likely(mlx4_en_rx_recycle(ring, frags))) goto consumed; goto next; } } + ring->bytes += length; + ring->packets++; + if (likely(dev->features & NETIF_F_RXCSUM)) { if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP | MLX4_CQE_STATUS_UDP)) { diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 95dc864bb2f7..5de3cbe24f2b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -1079,7 +1079,8 @@ tx_drop: return NETDEV_TX_OK; } -netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame, +netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_ring *rx_ring, + struct mlx4_en_rx_alloc *frame, struct net_device *dev, unsigned int length, int tx_ind, int *doorbell_pending) { @@ -1154,8 +1155,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame, ((ring->prod & ring->size) ? cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0); - ring->packets++; - ring->bytes += tx_info->nr_bytes; + rx_ring->xdp_tx++; AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, length); ring->prod += nr_txbb; @@ -1179,7 +1179,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame, return NETDEV_TX_OK; tx_drop_count: - ring->tx_dropped++; + rx_ring->xdp_tx_full++; tx_drop: return NETDEV_TX_BUSY; } diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 6e0693659f85..eff21651b673 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -350,6 +350,9 @@ struct mlx4_en_rx_ring { unsigned long csum_ok; unsigned long csum_none; unsigned long csum_complete; + unsigned long xdp_drop; + unsigned long xdp_tx; + unsigned long xdp_tx_full; unsigned long dropped; int hwtstamp_rx_filter; cpumask_var_t affinity_mask; @@ -599,6 +602,7 @@ struct mlx4_en_priv { struct mlx4_en_flow_stats_rx rx_flowstats; struct mlx4_en_flow_stats_tx tx_flowstats; struct mlx4_en_port_stats port_stats; + struct mlx4_en_xdp_stats xdp_stats; struct mlx4_en_stats_bitmap stats_bitmap; struct list_head mc_list; struct list_head curr_list; @@ -687,7 +691,8 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq); u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback); netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev); -netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame, +netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_ring *rx_ring, + struct mlx4_en_rx_alloc *frame, struct net_device *dev, unsigned int length, int tx_ind, int *doorbell_pending); void mlx4_en_xmit_doorbell(struct mlx4_en_tx_ring *ring); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h index 7fd466c0b929..48641cb0367f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h @@ -55,6 +55,13 @@ struct mlx4_en_perf_stats { #define NUM_PERF_COUNTERS 6 }; +struct mlx4_en_xdp_stats { + unsigned long rx_xdp_drop; + unsigned long rx_xdp_tx; + unsigned long rx_xdp_tx_full; +#define NUM_XDP_STATS 3 +}; + #define NUM_MAIN_STATS 21 #define MLX4_NUM_PRIORITIES 8 @@ -107,7 +114,8 @@ enum { }; #define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + \ - NUM_FLOW_STATS + NUM_PERF_STATS + NUM_PF_STATS) + NUM_FLOW_STATS + NUM_PERF_STATS + NUM_PF_STATS + \ + NUM_XDP_STATS) #define MLX4_FIND_NETDEV_STAT(n) (offsetof(struct net_device_stats, n) / \ sizeof(((struct net_device_stats *)0)->n)) -- cgit v1.2.3 From bc8ee596afe8f35b379f87575c46d800dd8e7e68 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Tue, 1 Nov 2016 16:32:25 +0100 Subject: net: mii: add generic function to support ksetting support The old ethtool api (get_setting and set_setting) has generic mii functions mii_ethtool_sset and mii_ethtool_gset. To support the new ethtool api ({get|set}_link_ksettings), we add two generics mii function mii_ethtool_{get|set}_link_ksettings_get. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/mii.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mii.h | 4 ++ 2 files changed, 199 insertions(+) (limited to 'drivers') diff --git a/drivers/net/mii.c b/drivers/net/mii.c index 993570b1e2ae..0443546fc427 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -134,6 +134,101 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) return 0; } +/** + * mii_ethtool_get_link_ksettings - get settings that are specified in @cmd + * @mii: MII interface + * @cmd: requested ethtool_link_ksettings + * + * The @cmd parameter is expected to have been cleared before calling + * mii_ethtool_get_link_ksettings(). + * + * Returns 0 for success, negative on error. + */ +int mii_ethtool_get_link_ksettings(struct mii_if_info *mii, + struct ethtool_link_ksettings *cmd) +{ + struct net_device *dev = mii->dev; + u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0; + u32 nego, supported, advertising, lp_advertising; + + supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); + if (mii->supports_gmii) + supported |= SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full; + + /* only supports twisted-pair */ + cmd->base.port = PORT_MII; + + /* this isn't fully supported at higher layers */ + cmd->base.phy_address = mii->phy_id; + cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22; + + advertising = ADVERTISED_TP | ADVERTISED_MII; + + bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); + bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR); + if (mii->supports_gmii) { + ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); + stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); + } + if (bmcr & BMCR_ANENABLE) { + advertising |= ADVERTISED_Autoneg; + cmd->base.autoneg = AUTONEG_ENABLE; + + advertising |= mii_get_an(mii, MII_ADVERTISE); + if (mii->supports_gmii) + advertising |= mii_ctrl1000_to_ethtool_adv_t(ctrl1000); + + if (bmsr & BMSR_ANEGCOMPLETE) { + lp_advertising = mii_get_an(mii, MII_LPA); + lp_advertising |= + mii_stat1000_to_ethtool_lpa_t(stat1000); + } else { + lp_advertising = 0; + } + + nego = advertising & lp_advertising; + + if (nego & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half)) { + cmd->base.speed = SPEED_1000; + cmd->base.duplex = !!(nego & ADVERTISED_1000baseT_Full); + } else if (nego & (ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half)) { + cmd->base.speed = SPEED_100; + cmd->base.duplex = !!(nego & ADVERTISED_100baseT_Full); + } else { + cmd->base.speed = SPEED_10; + cmd->base.duplex = !!(nego & ADVERTISED_10baseT_Full); + } + } else { + cmd->base.autoneg = AUTONEG_DISABLE; + + cmd->base.speed = ((bmcr & BMCR_SPEED1000 && + (bmcr & BMCR_SPEED100) == 0) ? + SPEED_1000 : + ((bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10)); + cmd->base.duplex = (bmcr & BMCR_FULLDPLX) ? + DUPLEX_FULL : DUPLEX_HALF; + } + + mii->full_duplex = cmd->base.duplex; + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + advertising); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, + lp_advertising); + + /* ignore maxtxpkt, maxrxpkt for now */ + + return 0; +} + /** * mii_ethtool_sset - set settings that are specified in @ecmd * @mii: MII interface @@ -226,6 +321,104 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) return 0; } +/** + * mii_ethtool_set_link_ksettings - set settings that are specified in @cmd + * @mii: MII interfaces + * @cmd: requested ethtool_link_ksettings + * + * Returns 0 for success, negative on error. + */ +int mii_ethtool_set_link_ksettings(struct mii_if_info *mii, + const struct ethtool_link_ksettings *cmd) +{ + struct net_device *dev = mii->dev; + u32 speed = cmd->base.speed; + + if (speed != SPEED_10 && + speed != SPEED_100 && + speed != SPEED_1000) + return -EINVAL; + if (cmd->base.duplex != DUPLEX_HALF && cmd->base.duplex != DUPLEX_FULL) + return -EINVAL; + if (cmd->base.port != PORT_MII) + return -EINVAL; + if (cmd->base.phy_address != mii->phy_id) + return -EINVAL; + if (cmd->base.autoneg != AUTONEG_DISABLE && + cmd->base.autoneg != AUTONEG_ENABLE) + return -EINVAL; + if ((speed == SPEED_1000) && (!mii->supports_gmii)) + return -EINVAL; + + /* ignore supported, maxtxpkt, maxrxpkt */ + + if (cmd->base.autoneg == AUTONEG_ENABLE) { + u32 bmcr, advert, tmp; + u32 advert2 = 0, tmp2 = 0; + u32 advertising; + + ethtool_convert_link_mode_to_legacy_u32( + &advertising, cmd->link_modes.advertising); + + if ((advertising & (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full)) == 0) + return -EINVAL; + + /* advertise only what has been requested */ + advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); + tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); + if (mii->supports_gmii) { + advert2 = mii->mdio_read(dev, mii->phy_id, + MII_CTRL1000); + tmp2 = advert2 & + ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); + } + tmp |= ethtool_adv_to_mii_adv_t(advertising); + + if (mii->supports_gmii) + tmp2 |= ethtool_adv_to_mii_ctrl1000_t(advertising); + if (advert != tmp) { + mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); + mii->advertising = tmp; + } + if ((mii->supports_gmii) && (advert2 != tmp2)) + mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2); + + /* turn on autonegotiation, and force a renegotiate */ + bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); + bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); + mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); + + mii->force_media = 0; + } else { + u32 bmcr, tmp; + + /* turn off auto negotiation, set speed and duplexity */ + bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); + tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | + BMCR_SPEED1000 | BMCR_FULLDPLX); + if (speed == SPEED_1000) + tmp |= BMCR_SPEED1000; + else if (speed == SPEED_100) + tmp |= BMCR_SPEED100; + if (cmd->base.duplex == DUPLEX_FULL) { + tmp |= BMCR_FULLDPLX; + mii->full_duplex = 1; + } else { + mii->full_duplex = 0; + } + if (bmcr != tmp) + mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); + + mii->force_media = 1; + } + return 0; +} + /** * mii_check_gmii_support - check if the MII supports Gb interfaces * @mii: the MII interface @@ -466,7 +659,9 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(mii_link_ok); EXPORT_SYMBOL(mii_nway_restart); EXPORT_SYMBOL(mii_ethtool_gset); +EXPORT_SYMBOL(mii_ethtool_get_link_ksettings); EXPORT_SYMBOL(mii_ethtool_sset); +EXPORT_SYMBOL(mii_ethtool_set_link_ksettings); EXPORT_SYMBOL(mii_check_link); EXPORT_SYMBOL(mii_check_media); EXPORT_SYMBOL(mii_check_gmii_support); diff --git a/include/linux/mii.h b/include/linux/mii.h index 47492c9631b3..1629a0c32679 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -31,7 +31,11 @@ struct mii_if_info { extern int mii_link_ok (struct mii_if_info *mii); extern int mii_nway_restart (struct mii_if_info *mii); extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd); +extern int mii_ethtool_get_link_ksettings( + struct mii_if_info *mii, struct ethtool_link_ksettings *cmd); extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd); +extern int mii_ethtool_set_link_ksettings( + struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd); extern int mii_check_gmii_support(struct mii_if_info *mii); extern void mii_check_link (struct mii_if_info *mii); extern unsigned int mii_check_media (struct mii_if_info *mii, -- cgit v1.2.3 From e19b7883ef8b447a732a603e0bbb6232941cf08a Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Tue, 1 Nov 2016 16:32:26 +0100 Subject: net: 3c59x: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c59x.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 3ecf61382269..b3560a364e53 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -2907,18 +2907,20 @@ static int vortex_nway_reset(struct net_device *dev) return mii_nway_restart(&vp->mii); } -static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +static int vortex_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) { struct vortex_private *vp = netdev_priv(dev); - return mii_ethtool_gset(&vp->mii, cmd); + return mii_ethtool_get_link_ksettings(&vp->mii, cmd); } -static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +static int vortex_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) { struct vortex_private *vp = netdev_priv(dev); - return mii_ethtool_sset(&vp->mii, cmd); + return mii_ethtool_set_link_ksettings(&vp->mii, cmd); } static u32 vortex_get_msglevel(struct net_device *dev) @@ -3031,13 +3033,13 @@ static const struct ethtool_ops vortex_ethtool_ops = { .set_msglevel = vortex_set_msglevel, .get_ethtool_stats = vortex_get_ethtool_stats, .get_sset_count = vortex_get_sset_count, - .get_settings = vortex_get_settings, - .set_settings = vortex_set_settings, .get_link = ethtool_op_get_link, .nway_reset = vortex_nway_reset, .get_wol = vortex_get_wol, .set_wol = vortex_set_wol, .get_ts_info = ethtool_op_get_ts_info, + .get_link_ksettings = vortex_get_link_ksettings, + .set_link_ksettings = vortex_set_link_ksettings, }; #ifdef CONFIG_PCI -- cgit v1.2.3 From b646cf299e14338c7348a68acc006d1673f1ba0a Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Tue, 1 Nov 2016 16:32:27 +0100 Subject: net: 3c509: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c509.c | 55 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index 9f9a5f440e2f..a7533780dddc 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -1040,67 +1040,68 @@ el3_link_ok(struct net_device *dev) } static int -el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) +el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_link_ksettings *cmd) { u16 tmp; int ioaddr = dev->base_addr; + u32 supported; EL3WINDOW(0); /* obtain current transceiver via WN4_MEDIA? */ tmp = inw(ioaddr + WN0_ADDR_CONF); - ecmd->transceiver = XCVR_INTERNAL; switch (tmp >> 14) { case 0: - ecmd->port = PORT_TP; + cmd->base.port = PORT_TP; break; case 1: - ecmd->port = PORT_AUI; - ecmd->transceiver = XCVR_EXTERNAL; + cmd->base.port = PORT_AUI; break; case 3: - ecmd->port = PORT_BNC; + cmd->base.port = PORT_BNC; default: break; } - ecmd->duplex = DUPLEX_HALF; - ecmd->supported = 0; + cmd->base.duplex = DUPLEX_HALF; + supported = 0; tmp = inw(ioaddr + WN0_CONF_CTRL); if (tmp & (1<<13)) - ecmd->supported |= SUPPORTED_AUI; + supported |= SUPPORTED_AUI; if (tmp & (1<<12)) - ecmd->supported |= SUPPORTED_BNC; + supported |= SUPPORTED_BNC; if (tmp & (1<<9)) { - ecmd->supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half | + supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full; /* hmm... */ EL3WINDOW(4); tmp = inw(ioaddr + WN4_NETDIAG); if (tmp & FD_ENABLE) - ecmd->duplex = DUPLEX_FULL; + cmd->base.duplex = DUPLEX_FULL; } - ethtool_cmd_speed_set(ecmd, SPEED_10); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + cmd->base.speed = SPEED_10; EL3WINDOW(1); return 0; } static int -el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) +el3_netdev_set_ecmd(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) { u16 tmp; int ioaddr = dev->base_addr; - if (ecmd->speed != SPEED_10) + if (cmd->base.speed != SPEED_10) return -EINVAL; - if ((ecmd->duplex != DUPLEX_HALF) && (ecmd->duplex != DUPLEX_FULL)) - return -EINVAL; - if ((ecmd->transceiver != XCVR_INTERNAL) && (ecmd->transceiver != XCVR_EXTERNAL)) + if ((cmd->base.duplex != DUPLEX_HALF) && + (cmd->base.duplex != DUPLEX_FULL)) return -EINVAL; /* change XCVR type */ EL3WINDOW(0); tmp = inw(ioaddr + WN0_ADDR_CONF); - switch (ecmd->port) { + switch (cmd->base.port) { case PORT_TP: tmp &= ~(3<<14); dev->if_port = 0; @@ -1130,7 +1131,7 @@ el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) EL3WINDOW(4); tmp = inw(ioaddr + WN4_NETDIAG); - if (ecmd->duplex == DUPLEX_FULL) + if (cmd->base.duplex == DUPLEX_FULL) tmp |= FD_ENABLE; else tmp &= ~FD_ENABLE; @@ -1146,24 +1147,26 @@ static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info strlcpy(info->version, DRV_VERSION, sizeof(info->version)); } -static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +static int el3_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) { struct el3_private *lp = netdev_priv(dev); int ret; spin_lock_irq(&lp->lock); - ret = el3_netdev_get_ecmd(dev, ecmd); + ret = el3_netdev_get_ecmd(dev, cmd); spin_unlock_irq(&lp->lock); return ret; } -static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +static int el3_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) { struct el3_private *lp = netdev_priv(dev); int ret; spin_lock_irq(&lp->lock); - ret = el3_netdev_set_ecmd(dev, ecmd); + ret = el3_netdev_set_ecmd(dev, cmd); spin_unlock_irq(&lp->lock); return ret; } @@ -1191,11 +1194,11 @@ static void el3_set_msglevel(struct net_device *dev, u32 v) static const struct ethtool_ops ethtool_ops = { .get_drvinfo = el3_get_drvinfo, - .get_settings = el3_get_settings, - .set_settings = el3_set_settings, .get_link = el3_get_link, .get_msglevel = el3_get_msglevel, .set_msglevel = el3_set_msglevel, + .get_link_ksettings = el3_get_link_ksettings, + .set_link_ksettings = el3_set_link_ksettings, }; static void -- cgit v1.2.3 From cc89c323a30e73114a21fc125d2f841658a09987 Mon Sep 17 00:00:00 2001 From: Woojung Huh Date: Tue, 1 Nov 2016 20:02:00 +0000 Subject: lan78xx: Use irq_domain for phy interrupt from USB Int. EP To utilize phylib with interrupt fully than handling some of phy stuff in the MAC driver, create irq_domain for USB interrupt EP of phy interrupt and pass the irq number to phy_connect_direct() instead of PHY_IGNORE_INTERRUPT. Idea comes from drivers/gpio/gpio-dl2.c Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 215 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 189 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index c4e748e92db4..bcd9010c1f27 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -30,13 +30,17 @@ #include #include #include +#include +#include +#include +#include #include #include "lan78xx.h" #define DRIVER_AUTHOR "WOOJUNG HUH " #define DRIVER_DESC "LAN78XX USB 3.0 Gigabit Ethernet Devices" #define DRIVER_NAME "lan78xx" -#define DRIVER_VERSION "1.0.4" +#define DRIVER_VERSION "1.0.5" #define TX_TIMEOUT_JIFFIES (5 * HZ) #define THROTTLE_JIFFIES (HZ / 8) @@ -89,6 +93,38 @@ /* statistic update interval (mSec) */ #define STAT_UPDATE_TIMER (1 * 1000) +/* defines interrupts from interrupt EP */ +#define MAX_INT_EP (32) +#define INT_EP_INTEP (31) +#define INT_EP_OTP_WR_DONE (28) +#define INT_EP_EEE_TX_LPI_START (26) +#define INT_EP_EEE_TX_LPI_STOP (25) +#define INT_EP_EEE_RX_LPI (24) +#define INT_EP_MAC_RESET_TIMEOUT (23) +#define INT_EP_RDFO (22) +#define INT_EP_TXE (21) +#define INT_EP_USB_STATUS (20) +#define INT_EP_TX_DIS (19) +#define INT_EP_RX_DIS (18) +#define INT_EP_PHY (17) +#define INT_EP_DP (16) +#define INT_EP_MAC_ERR (15) +#define INT_EP_TDFU (14) +#define INT_EP_TDFO (13) +#define INT_EP_UTX (12) +#define INT_EP_GPIO_11 (11) +#define INT_EP_GPIO_10 (10) +#define INT_EP_GPIO_9 (9) +#define INT_EP_GPIO_8 (8) +#define INT_EP_GPIO_7 (7) +#define INT_EP_GPIO_6 (6) +#define INT_EP_GPIO_5 (5) +#define INT_EP_GPIO_4 (4) +#define INT_EP_GPIO_3 (3) +#define INT_EP_GPIO_2 (2) +#define INT_EP_GPIO_1 (1) +#define INT_EP_GPIO_0 (0) + static const char lan78xx_gstrings[][ETH_GSTRING_LEN] = { "RX FCS Errors", "RX Alignment Errors", @@ -296,6 +332,15 @@ struct statstage { struct lan78xx_statstage64 curr_stat; }; +struct irq_domain_data { + struct irq_domain *irqdomain; + unsigned int phyirq; + struct irq_chip *irqchip; + irq_flow_handler_t irq_handler; + u32 irqenable; + struct mutex irq_lock; /* for irq bus access */ +}; + struct lan78xx_net { struct net_device *net; struct usb_device *udev; @@ -351,6 +396,8 @@ struct lan78xx_net { int delta; struct statstage stats; + + struct irq_domain_data domain_data; }; /* use ethtool to change the level for any given device */ @@ -1096,11 +1143,6 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) int ladv, radv, ret; u32 buf; - /* clear PHY interrupt status */ - ret = phy_read(phydev, LAN88XX_INT_STS); - if (unlikely(ret < 0)) - return -EIO; - /* clear LAN78xx interrupt status */ ret = lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_); if (unlikely(ret < 0)) @@ -1120,16 +1162,12 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) if (unlikely(ret < 0)) return -EIO; - phy_mac_interrupt(phydev, 0); - del_timer(&dev->stat_monitor); } else if (phydev->link && !dev->link_on) { dev->link_on = true; phy_ethtool_ksettings_get(phydev, &ecmd); - ret = phy_read(phydev, LAN88XX_INT_STS); - if (dev->udev->speed == USB_SPEED_SUPER) { if (ecmd.base.speed == 1000) { /* disable U2 */ @@ -1163,7 +1201,6 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) ret = lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv, radv); - phy_mac_interrupt(phydev, 1); if (!timer_pending(&dev->stat_monitor)) { dev->delta = 1; @@ -1202,7 +1239,10 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb) if (intdata & INT_ENP_PHY_INT) { netif_dbg(dev, link, dev->net, "PHY INTR: 0x%08x\n", intdata); - lan78xx_defer_kevent(dev, EVENT_LINK_RESET); + lan78xx_defer_kevent(dev, EVENT_LINK_RESET); + + if (dev->domain_data.phyirq > 0) + generic_handle_irq(dev->domain_data.phyirq); } else netdev_warn(dev->net, "unexpected interrupt: 0x%08x\n", intdata); @@ -1844,6 +1884,127 @@ static void lan78xx_link_status_change(struct net_device *net) } } +static int irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct irq_domain_data *data = d->host_data; + + irq_set_chip_data(irq, data); + irq_set_chip_and_handler(irq, data->irqchip, data->irq_handler); + irq_set_noprobe(irq); + + return 0; +} + +static void irq_unmap(struct irq_domain *d, unsigned int irq) +{ + irq_set_chip_and_handler(irq, NULL, NULL); + irq_set_chip_data(irq, NULL); +} + +static const struct irq_domain_ops chip_domain_ops = { + .map = irq_map, + .unmap = irq_unmap, +}; + +static void lan78xx_irq_mask(struct irq_data *irqd) +{ + struct irq_domain_data *data = irq_data_get_irq_chip_data(irqd); + + data->irqenable &= ~BIT(irqd_to_hwirq(irqd)); +} + +static void lan78xx_irq_unmask(struct irq_data *irqd) +{ + struct irq_domain_data *data = irq_data_get_irq_chip_data(irqd); + + data->irqenable |= BIT(irqd_to_hwirq(irqd)); +} + +static void lan78xx_irq_bus_lock(struct irq_data *irqd) +{ + struct irq_domain_data *data = irq_data_get_irq_chip_data(irqd); + + mutex_lock(&data->irq_lock); +} + +static void lan78xx_irq_bus_sync_unlock(struct irq_data *irqd) +{ + struct irq_domain_data *data = irq_data_get_irq_chip_data(irqd); + struct lan78xx_net *dev = + container_of(data, struct lan78xx_net, domain_data); + u32 buf; + int ret; + + /* call register access here because irq_bus_lock & irq_bus_sync_unlock + * are only two callbacks executed in non-atomic contex. + */ + ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf); + if (buf != data->irqenable) + ret = lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable); + + mutex_unlock(&data->irq_lock); +} + +static struct irq_chip lan78xx_irqchip = { + .name = "lan78xx-irqs", + .irq_mask = lan78xx_irq_mask, + .irq_unmask = lan78xx_irq_unmask, + .irq_bus_lock = lan78xx_irq_bus_lock, + .irq_bus_sync_unlock = lan78xx_irq_bus_sync_unlock, +}; + +static int lan78xx_setup_irq_domain(struct lan78xx_net *dev) +{ + struct device_node *of_node; + struct irq_domain *irqdomain; + unsigned int irqmap = 0; + u32 buf; + int ret = 0; + + of_node = dev->udev->dev.parent->of_node; + + mutex_init(&dev->domain_data.irq_lock); + + lan78xx_read_reg(dev, INT_EP_CTL, &buf); + dev->domain_data.irqenable = buf; + + dev->domain_data.irqchip = &lan78xx_irqchip; + dev->domain_data.irq_handler = handle_simple_irq; + + irqdomain = irq_domain_add_simple(of_node, MAX_INT_EP, 0, + &chip_domain_ops, &dev->domain_data); + if (irqdomain) { + /* create mapping for PHY interrupt */ + irqmap = irq_create_mapping(irqdomain, INT_EP_PHY); + if (!irqmap) { + irq_domain_remove(irqdomain); + + irqdomain = NULL; + ret = -EINVAL; + } + } else { + ret = -EINVAL; + } + + dev->domain_data.irqdomain = irqdomain; + dev->domain_data.phyirq = irqmap; + + return ret; +} + +static void lan78xx_remove_irq_domain(struct lan78xx_net *dev) +{ + if (dev->domain_data.phyirq > 0) { + irq_dispose_mapping(dev->domain_data.phyirq); + + if (dev->domain_data.irqdomain) + irq_domain_remove(dev->domain_data.irqdomain); + } + dev->domain_data.phyirq = 0; + dev->domain_data.irqdomain = NULL; +} + static int lan78xx_phy_init(struct lan78xx_net *dev) { int ret; @@ -1856,15 +2017,12 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) return -EIO; } - /* Enable PHY interrupts. - * We handle our own interrupt - */ - ret = phy_read(phydev, LAN88XX_INT_STS); - ret = phy_write(phydev, LAN88XX_INT_MASK, - LAN88XX_INT_MASK_MDINTPIN_EN_ | - LAN88XX_INT_MASK_LINK_CHANGE_); - - phydev->irq = PHY_IGNORE_INTERRUPT; + /* if phyirq is not set, use polling mode in phylib */ + if (dev->domain_data.phyirq > 0) + phydev->irq = dev->domain_data.phyirq; + else + phydev->irq = 0; + netdev_dbg(dev->net, "phydev->irq = %d\n", phydev->irq); ret = phy_connect_direct(dev->net, phydev, lan78xx_link_status_change, @@ -2255,11 +2413,6 @@ static int lan78xx_reset(struct lan78xx_net *dev) buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; ret = lan78xx_write_reg(dev, MAC_CR, buf); - /* enable PHY interrupts */ - ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf); - buf |= INT_ENP_PHY_INT; - ret = lan78xx_write_reg(dev, INT_EP_CTL, buf); - ret = lan78xx_read_reg(dev, MAC_TX, &buf); buf |= MAC_TX_TXEN_; ret = lan78xx_write_reg(dev, MAC_TX, buf); @@ -2668,6 +2821,14 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf) dev->net->hw_features = dev->net->features; + ret = lan78xx_setup_irq_domain(dev); + if (ret < 0) { + netdev_warn(dev->net, + "lan78xx_setup_irq_domain() failed : %d", ret); + kfree(pdata); + return ret; + } + /* Init all registers */ ret = lan78xx_reset(dev); @@ -2684,6 +2845,8 @@ static void lan78xx_unbind(struct lan78xx_net *dev, struct usb_interface *intf) { struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); + lan78xx_remove_irq_domain(dev); + lan78xx_remove_mdio(dev); if (pdata) { -- cgit v1.2.3 From f7a5537cd2a56b5fdd043f89d37d500b6c698422 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Wed, 2 Nov 2016 00:11:51 +0100 Subject: net: 3com: typhoon: use new api ethtool_{get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move this driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Reviewed-by: David Dillow Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/typhoon.c | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c index 506b507b4158..dbdf06f2af49 100644 --- a/drivers/net/ethernet/3com/typhoon.c +++ b/drivers/net/ethernet/3com/typhoon.c @@ -996,28 +996,30 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) } static int -typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +typhoon_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) { struct typhoon *tp = netdev_priv(dev); + u32 supported, advertising; - cmd->supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg; switch (tp->xcvr_select) { case TYPHOON_XCVR_10HALF: - cmd->advertising = ADVERTISED_10baseT_Half; + advertising = ADVERTISED_10baseT_Half; break; case TYPHOON_XCVR_10FULL: - cmd->advertising = ADVERTISED_10baseT_Full; + advertising = ADVERTISED_10baseT_Full; break; case TYPHOON_XCVR_100HALF: - cmd->advertising = ADVERTISED_100baseT_Half; + advertising = ADVERTISED_100baseT_Half; break; case TYPHOON_XCVR_100FULL: - cmd->advertising = ADVERTISED_100baseT_Full; + advertising = ADVERTISED_100baseT_Full; break; case TYPHOON_XCVR_AUTONEG: - cmd->advertising = ADVERTISED_10baseT_Half | + advertising = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | @@ -1026,54 +1028,52 @@ typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) } if(tp->capabilities & TYPHOON_FIBER) { - cmd->supported |= SUPPORTED_FIBRE; - cmd->advertising |= ADVERTISED_FIBRE; - cmd->port = PORT_FIBRE; + supported |= SUPPORTED_FIBRE; + advertising |= ADVERTISED_FIBRE; + cmd->base.port = PORT_FIBRE; } else { - cmd->supported |= SUPPORTED_10baseT_Half | + supported |= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_TP; - cmd->advertising |= ADVERTISED_TP; - cmd->port = PORT_TP; + advertising |= ADVERTISED_TP; + cmd->base.port = PORT_TP; } /* need to get stats to make these link speed/duplex valid */ typhoon_do_get_stats(tp); - ethtool_cmd_speed_set(cmd, tp->speed); - cmd->duplex = tp->duplex; - cmd->phy_address = 0; - cmd->transceiver = XCVR_INTERNAL; + cmd->base.speed = tp->speed; + cmd->base.duplex = tp->duplex; + cmd->base.phy_address = 0; if(tp->xcvr_select == TYPHOON_XCVR_AUTONEG) - cmd->autoneg = AUTONEG_ENABLE; + cmd->base.autoneg = AUTONEG_ENABLE; else - cmd->autoneg = AUTONEG_DISABLE; - cmd->maxtxpkt = 1; - cmd->maxrxpkt = 1; + cmd->base.autoneg = AUTONEG_DISABLE; return 0; } static int -typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +typhoon_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) { struct typhoon *tp = netdev_priv(dev); - u32 speed = ethtool_cmd_speed(cmd); + u32 speed = cmd->base.speed; struct cmd_desc xp_cmd; __le16 xcvr; int err; err = -EINVAL; - if (cmd->autoneg == AUTONEG_ENABLE) { + if (cmd->base.autoneg == AUTONEG_ENABLE) { xcvr = TYPHOON_XCVR_AUTONEG; } else { - if (cmd->duplex == DUPLEX_HALF) { + if (cmd->base.duplex == DUPLEX_HALF) { if (speed == SPEED_10) xcvr = TYPHOON_XCVR_10HALF; else if (speed == SPEED_100) xcvr = TYPHOON_XCVR_100HALF; else goto out; - } else if (cmd->duplex == DUPLEX_FULL) { + } else if (cmd->base.duplex == DUPLEX_FULL) { if (speed == SPEED_10) xcvr = TYPHOON_XCVR_10FULL; else if (speed == SPEED_100) @@ -1091,12 +1091,12 @@ typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) goto out; tp->xcvr_select = xcvr; - if(cmd->autoneg == AUTONEG_ENABLE) { + if (cmd->base.autoneg == AUTONEG_ENABLE) { tp->speed = 0xff; /* invalid */ tp->duplex = 0xff; /* invalid */ } else { tp->speed = speed; - tp->duplex = cmd->duplex; + tp->duplex = cmd->base.duplex; } out: @@ -1145,13 +1145,13 @@ typhoon_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) } static const struct ethtool_ops typhoon_ethtool_ops = { - .get_settings = typhoon_get_settings, - .set_settings = typhoon_set_settings, .get_drvinfo = typhoon_get_drvinfo, .get_wol = typhoon_get_wol, .set_wol = typhoon_set_wol, .get_link = ethtool_op_get_link, .get_ringparam = typhoon_get_ringparam, + .get_link_ksettings = typhoon_get_link_ksettings, + .set_link_ksettings = typhoon_set_link_ksettings, }; static int -- cgit v1.2.3 From 17197236d62c44da127be461c63ac5cc2cce1e53 Mon Sep 17 00:00:00 2001 From: Govindarajulu Varadarajan <_govind@gmx.com> Date: Tue, 1 Nov 2016 17:58:50 -0700 Subject: enic: set skb->hash type properly Driver sets the skb l4/l3 hash based on NIC_CFG_RSS_HASH_TYPE_*, which is bit mask. This is wrong. Hw actually provides us enum. Use CQ_ENET_RQ_DESC_RSS_TYPE_* to set l3 and l4 hash type. Fixes: bf751ba802fe ("driver/net: enic: record q_number and rss_hash for skb") Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller --- drivers/net/ethernet/cisco/enic/enic.h | 2 +- drivers/net/ethernet/cisco/enic/enic_main.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index 130f910e4785..9023c858715d 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -33,7 +33,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" -#define DRV_VERSION "2.3.0.20" +#define DRV_VERSION "2.3.0.31" #define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index f514faf8b709..cdd7a1a59aa7 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1166,12 +1166,18 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, skb->protocol = eth_type_trans(skb, netdev); skb_record_rx_queue(skb, q_number); if (netdev->features & NETIF_F_RXHASH) { - skb_set_hash(skb, rss_hash, - (rss_type & - (NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX | - NIC_CFG_RSS_HASH_TYPE_TCP_IPV6 | - NIC_CFG_RSS_HASH_TYPE_TCP_IPV4)) ? - PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); + switch (rss_type) { + case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4: + case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6: + case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX: + skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L4); + break; + case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4: + case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6: + case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX: + skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L3); + break; + } } /* Hardware does not provide whole packet checksum. It only -- cgit v1.2.3 From cf31bc71c0f8cdf9c6529ff49b4928ea27b652e2 Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Thu, 13 Oct 2016 10:31:48 +0100 Subject: clk: renesas: r8a7796: Add DRIF clock This patch adds DRIF module clocks for r8a7796 SoC. Signed-off-by: Ramesh Shanmugasundaram Acked-by: Stephen Boyd Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index f0302fba948e..f2f56e16a7cf 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -128,6 +128,14 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("sdif0", 314, R8A7796_CLK_SD0), DEF_MOD("rwdt0", 402, R8A7796_CLK_R), DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1), + DEF_MOD("drif7", 508, R8A7796_CLK_S3D2), + DEF_MOD("drif6", 509, R8A7796_CLK_S3D2), + DEF_MOD("drif5", 510, R8A7796_CLK_S3D2), + DEF_MOD("drif4", 511, R8A7796_CLK_S3D2), + DEF_MOD("drif3", 512, R8A7796_CLK_S3D2), + DEF_MOD("drif2", 513, R8A7796_CLK_S3D2), + DEF_MOD("drif1", 514, R8A7796_CLK_S3D2), + DEF_MOD("drif0", 515, R8A7796_CLK_S3D2), DEF_MOD("hscif4", 516, R8A7796_CLK_S3D1), DEF_MOD("hscif3", 517, R8A7796_CLK_S3D1), DEF_MOD("hscif2", 518, R8A7796_CLK_S3D1), -- cgit v1.2.3 From 1b9fe7030cfdd081fc4ae1d3db4ccb1ba6d09dfd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Oct 2016 15:59:13 +0200 Subject: clk: renesas: cpg-mssr: Remove bogus commas from error messages Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 057bb8759e38..bdd46fb08d38 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -308,7 +308,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, return; fail: - dev_err(dev, "Failed to register %s clock %s: %ld\n", "core,", + dev_err(dev, "Failed to register %s clock %s: %ld\n", "core", core->name, PTR_ERR(clk)); } @@ -376,7 +376,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, return; fail: - dev_err(dev, "Failed to register %s clock %s: %ld\n", "module,", + dev_err(dev, "Failed to register %s clock %s: %ld\n", "module", mod->name, PTR_ERR(clk)); kfree(clock); } -- cgit v1.2.3 From f4407a6e26b1abf9a1e168fa893783f999112df2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 22 Oct 2016 14:29:04 +0300 Subject: clk: renesas: r8a7796: Add FCP clocks Signed-off-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index f2f56e16a7cf..b7907138ae3a 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -142,6 +142,14 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("hscif1", 519, R8A7796_CLK_S3D1), DEF_MOD("hscif0", 520, R8A7796_CLK_S3D1), DEF_MOD("thermal", 522, R8A7796_CLK_CP), + DEF_MOD("fcpvd2", 601, R8A7796_CLK_S0D2), + DEF_MOD("fcpvd1", 602, R8A7796_CLK_S0D2), + DEF_MOD("fcpvd0", 603, R8A7796_CLK_S0D2), + DEF_MOD("fcpvb0", 607, R8A7796_CLK_S0D1), + DEF_MOD("fcpvi0", 611, R8A7796_CLK_S0D1), + DEF_MOD("fcpf0", 615, R8A7796_CLK_S0D1), + DEF_MOD("fcpci0", 617, R8A7796_CLK_S0D2), + DEF_MOD("fcpcs", 619, R8A7796_CLK_S0D2), DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6), DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4), DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4), -- cgit v1.2.3 From 88ddc1f8e3674f0b71016f5461868f14a02281a2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 22 Oct 2016 14:29:05 +0300 Subject: clk: renesas: r8a7796: Add VSP clocks Signed-off-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index b7907138ae3a..b537ec80125f 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -150,6 +150,11 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("fcpf0", 615, R8A7796_CLK_S0D1), DEF_MOD("fcpci0", 617, R8A7796_CLK_S0D2), DEF_MOD("fcpcs", 619, R8A7796_CLK_S0D2), + DEF_MOD("vspd2", 621, R8A7796_CLK_S0D2), + DEF_MOD("vspd1", 622, R8A7796_CLK_S0D2), + DEF_MOD("vspd0", 623, R8A7796_CLK_S0D2), + DEF_MOD("vspb", 626, R8A7796_CLK_S0D1), + DEF_MOD("vspi0", 631, R8A7796_CLK_S0D1), DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6), DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4), DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4), -- cgit v1.2.3 From dbdcc4f996df280eb2758095b4774ea62da8a2a7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 22 Oct 2016 14:29:06 +0300 Subject: clk: renesas: r8a7796: Add DU and LVDS clocks Signed-off-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index b537ec80125f..c880d72106e1 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -155,6 +155,10 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("vspd0", 623, R8A7796_CLK_S0D2), DEF_MOD("vspb", 626, R8A7796_CLK_S0D1), DEF_MOD("vspi0", 631, R8A7796_CLK_S0D1), + DEF_MOD("du2", 722, R8A7796_CLK_S2D1), + DEF_MOD("du1", 723, R8A7796_CLK_S2D1), + DEF_MOD("du0", 724, R8A7796_CLK_S2D1), + DEF_MOD("lvds", 727, R8A7796_CLK_S2D1), DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6), DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4), DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4), -- cgit v1.2.3 From 527c02f66d263d2eeff237a2326c3278cfc03d3b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 27 May 2016 11:56:53 +0200 Subject: soc: renesas: Add R-Car RST driver Add a driver for the Renesas R-Car Gen1 RESET/WDT and R-Car Gen2/Gen3 and RZ/G RST module. For now this driver just provides an API to obtain the state of the mode pins, as latched at reset time. As this is typically called from the probe function of a clock driver, which can run much earlier than any initcall, calling rcar_rst_read_mode_pins() just forces an early initialization of the driver. Despite the current simple and almost identical handling for all supported SoCs, the driver matches against SoC-specific compatible values, as the features provided by the hardware module differ a lot across the various SoC families and members. Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme --- drivers/soc/renesas/Makefile | 5 ++ drivers/soc/renesas/rcar-rst.c | 92 ++++++++++++++++++++++++++++++++++++ include/linux/soc/renesas/rcar-rst.h | 6 +++ 3 files changed, 103 insertions(+) create mode 100644 drivers/soc/renesas/rcar-rst.c create mode 100644 include/linux/soc/renesas/rcar-rst.h (limited to 'drivers') diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 623039c3514c..86cc78cd1962 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -1,3 +1,8 @@ +obj-$(CONFIG_ARCH_RCAR_GEN1) += rcar-rst.o +obj-$(CONFIG_ARCH_RCAR_GEN2) += rcar-rst.o +obj-$(CONFIG_ARCH_R8A7795) += rcar-rst.o +obj-$(CONFIG_ARCH_R8A7796) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c new file mode 100644 index 000000000000..a6d1c26d3167 --- /dev/null +++ b/drivers/soc/renesas/rcar-rst.c @@ -0,0 +1,92 @@ +/* + * R-Car Gen1 RESET/WDT, R-Car Gen2, Gen3, and RZ/G RST Driver + * + * Copyright (C) 2016 Glider bvba + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include + +struct rst_config { + unsigned int modemr; /* Mode Monitoring Register Offset */ +}; + +static const struct rst_config rcar_rst_gen1 __initconst = { + .modemr = 0x20, +}; + +static const struct rst_config rcar_rst_gen2 __initconst = { + .modemr = 0x60, +}; + +static const struct of_device_id rcar_rst_matches[] __initconst = { + /* RZ/G is handled like R-Car Gen2 */ + { .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 }, + /* R-Car Gen1 */ + { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 }, + { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 }, + /* R-Car Gen2 */ + { .compatible = "renesas,r8a7790-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7791-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7792-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7793-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7794-rst", .data = &rcar_rst_gen2 }, + /* R-Car Gen3 is handled like R-Car Gen2 */ + { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, + { /* sentinel */ } +}; + +static void __iomem *rcar_rst_base __initdata; +static u32 saved_mode __initdata; + +static int __init rcar_rst_init(void) +{ + const struct of_device_id *match; + const struct rst_config *cfg; + struct device_node *np; + void __iomem *base; + int error = 0; + + np = of_find_matching_node_and_match(NULL, rcar_rst_matches, &match); + if (!np) + return -ENODEV; + + base = of_iomap(np, 0); + if (!base) { + pr_warn("%s: Cannot map regs\n", np->full_name); + error = -ENOMEM; + goto out_put; + } + + rcar_rst_base = base; + cfg = match->data; + saved_mode = ioread32(base + cfg->modemr); + + pr_debug("%s: MODE = 0x%08x\n", np->full_name, saved_mode); + +out_put: + of_node_put(np); + return error; +} + +int __init rcar_rst_read_mode_pins(u32 *mode) +{ + int error; + + if (!rcar_rst_base) { + error = rcar_rst_init(); + if (error) + return error; + } + + *mode = saved_mode; + return 0; +} diff --git a/include/linux/soc/renesas/rcar-rst.h b/include/linux/soc/renesas/rcar-rst.h new file mode 100644 index 000000000000..a18e0783946b --- /dev/null +++ b/include/linux/soc/renesas/rcar-rst.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_SOC_RENESAS_RCAR_RST_H__ +#define __LINUX_SOC_RENESAS_RCAR_RST_H__ + +int rcar_rst_read_mode_pins(u32 *mode); + +#endif /* __LINUX_SOC_RENESAS_RCAR_RST_H__ */ -- cgit v1.2.3 From 578d601cbc514b92bc9ed71fd4fb700180275211 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2016 14:46:01 +0200 Subject: clk: renesas: r8a7778: Obtain mode pin values using R-Car RST driver Obtain the values of the mode pins from the R-Car RST driver, which relies on the presence in DT of a device node for the RESET/WDT module. Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme --- drivers/clk/renesas/clk-r8a7778.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/clk-r8a7778.c b/drivers/clk/renesas/clk-r8a7778.c index 40e3a501a50e..07ea411098a7 100644 --- a/drivers/clk/renesas/clk-r8a7778.c +++ b/drivers/clk/renesas/clk-r8a7778.c @@ -12,6 +12,7 @@ #include #include #include +#include struct r8a7778_cpg { struct clk_onecell_data data; @@ -83,6 +84,18 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np) struct clk **clks; unsigned int i; int num_clks; + u32 mode; + + if (rcar_rst_read_mode_pins(&mode)) + return; + + BUG_ON(!(mode & BIT(19))); + + cpg_mode_rates = (!!(mode & BIT(18)) << 2) | + (!!(mode & BIT(12)) << 1) | + (!!(mode & BIT(11))); + cpg_mode_divs = (!!(mode & BIT(2)) << 1) | + (!!(mode & BIT(1))); num_clks = of_property_count_strings(np, "clock-output-names"); if (num_clks < 0) { -- cgit v1.2.3 From 931db8a0c646e23f0c5a3e2175742997d7e60ff5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2016 14:49:41 +0200 Subject: clk: renesas: r8a7779: Obtain mode pin values from R-Car RST driver Obtain the values of the mode pins from the R-Car RST driver, which relies on the presence in DT of a device node for the RESET/WDT module. Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme --- drivers/clk/renesas/clk-r8a7779.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/clk-r8a7779.c b/drivers/clk/renesas/clk-r8a7779.c index cf2a37df03b1..ca7551bcb115 100644 --- a/drivers/clk/renesas/clk-r8a7779.c +++ b/drivers/clk/renesas/clk-r8a7779.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -127,6 +128,10 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np) struct clk **clks; unsigned int i, plla_mult; int num_clks; + u32 mode; + + if (rcar_rst_read_mode_pins(&mode)) + return; num_clks = of_property_count_strings(np, "clock-output-names"); if (num_clks < 0) { @@ -148,8 +153,8 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np) cpg->data.clks = clks; cpg->data.clk_num = num_clks; - config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(cpg_mode)]; - plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(cpg_mode)]; + config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(mode)]; + plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(mode)]; for (i = 0; i < num_clks; ++i) { const char *name; -- cgit v1.2.3 From f84c9c3ca9770bd847cb361d67bd385499a20d37 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 7 Jul 2015 14:57:37 +0200 Subject: clk: renesas: rcar-gen2: Obtain mode pin values using RST driver Obtain the values of the mode pins from the R-Car RST driver, which relies on the presence in DT of a device node for the RST module. Fall back to our own private copy of rcar_gen2_read_mode_pins() for backward-compatibility with old DTs. Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme --- drivers/clk/renesas/clk-rcar-gen2.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index 00e6aba4b9c0..3291fd430ad4 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c @@ -19,6 +19,7 @@ #include #include #include +#include struct rcar_gen2_cpg { struct clk_onecell_data data; @@ -364,6 +365,23 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, 4, 0, table, &cpg->lock); } +/* + * Reset register definitions. + */ +#define MODEMR 0xe6160060 + +static u32 __init rcar_gen2_read_mode_pins(void) +{ + void __iomem *modemr = ioremap_nocache(MODEMR, 4); + u32 mode; + + BUG_ON(!modemr); + mode = ioread32(modemr); + iounmap(modemr); + + return mode; +} + static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) { const struct cpg_pll_config *config; @@ -372,6 +390,13 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) unsigned int i; int num_clks; + if (rcar_rst_read_mode_pins(&cpg_mode)) { + /* Backward-compatibility with old DT */ + pr_warn("%s: failed to obtain mode pins from RST\n", + np->full_name); + cpg_mode = rcar_gen2_read_mode_pins(); + } + num_clks = of_property_count_strings(np, "clock-output-names"); if (num_clks < 0) { pr_err("%s: failed to count clocks\n", __func__); -- cgit v1.2.3 From 969921e0d2b5a582aa6a28cb2208273a2d5679d6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2016 14:54:10 +0200 Subject: clk: renesas: r8a7795: Obtain mode pin values from R-Car RST driver Obtain the values of the mode pins from the R-Car RST driver, which relies on the presence in DT of a device node for the RST module. Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme Reviewed-by: Laurent Pinchart --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index f255e451e8ca..726c3d7940b4 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -311,7 +312,12 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { static int __init r8a7795_cpg_mssr_init(struct device *dev) { const struct rcar_gen3_cpg_pll_config *cpg_pll_config; - u32 cpg_mode = rcar_gen3_read_mode_pins(); + u32 cpg_mode; + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; if (!cpg_pll_config->extal_div) { -- cgit v1.2.3 From 05972d48d23927e9d4932a10c8c172ccee4b1a6d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2016 14:54:45 +0200 Subject: clk: renesas: r8a7796: Obtain mode pin values from R-Car RST driver Obtain the values of the mode pins from the R-Car RST driver, which relies on the presence in DT of a device node for the RST module. Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme Reviewed-by: Laurent Pinchart --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index eb347ed265f2..1c144b21869d 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -190,7 +191,12 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { static int __init r8a7796_cpg_mssr_init(struct device *dev) { const struct rcar_gen3_cpg_pll_config *cpg_pll_config; - u32 cpg_mode = rcar_gen3_read_mode_pins(); + u32 cpg_mode; + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; if (!cpg_pll_config->extal_div) { -- cgit v1.2.3 From ddab5aed8ecd277bd34b6421736c882fdff2dfe1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2016 14:56:58 +0200 Subject: clk: renesas: rcar-gen3-cpg: Remove obsolete rcar_gen3_read_mode_pins() All R-Car Gen3 clock drivers now obtain the values of the mode pins from the R-Car RST driver. Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme Reviewed-by: Laurent Pinchart --- drivers/clk/renesas/rcar-gen3-cpg.c | 17 ----------------- drivers/clk/renesas/rcar-gen3-cpg.h | 1 - 2 files changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index bb4f2f9a8c2f..9d76076da494 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -333,23 +333,6 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, __clk_get_name(parent), 0, mult, div); } -/* - * Reset register definitions. - */ -#define MODEMR 0xe6160060 - -u32 __init rcar_gen3_read_mode_pins(void) -{ - void __iomem *modemr = ioremap_nocache(MODEMR, 4); - u32 mode; - - BUG_ON(!modemr); - mode = ioread32(modemr); - iounmap(modemr); - - return mode; -} - int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, unsigned int clk_extalr) { diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index f699085147d1..f788f481dd42 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -33,7 +33,6 @@ struct rcar_gen3_cpg_pll_config { #define CPG_RCKCR 0x240 -u32 rcar_gen3_read_mode_pins(void); struct clk *rcar_gen3_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, struct clk **clks, void __iomem *base); -- cgit v1.2.3 From 7978a78c828ac8d5351b85480e60ada865b9bea9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2016 15:23:22 +0200 Subject: clk: renesas: r8a7778: Remove obsolete r8a7778_clocks_init() The R-Car M1A board code no longer calls r8a7778_clocks_init(). Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme --- drivers/clk/renesas/clk-r8a7778.c | 13 ------------- include/linux/clk/renesas.h | 1 - 2 files changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/clk-r8a7778.c b/drivers/clk/renesas/clk-r8a7778.c index 07ea411098a7..886a8380e912 100644 --- a/drivers/clk/renesas/clk-r8a7778.c +++ b/drivers/clk/renesas/clk-r8a7778.c @@ -143,16 +143,3 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np) CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks", r8a7778_cpg_clocks_init); - -void __init r8a7778_clocks_init(u32 mode) -{ - BUG_ON(!(mode & BIT(19))); - - cpg_mode_rates = (!!(mode & BIT(18)) << 2) | - (!!(mode & BIT(12)) << 1) | - (!!(mode & BIT(11))); - cpg_mode_divs = (!!(mode & BIT(2)) << 1) | - (!!(mode & BIT(1))); - - of_clk_init(NULL); -} diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index ba6fa4148515..2b663bba1adc 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -20,7 +20,6 @@ struct device; struct device_node; struct generic_pm_domain; -void r8a7778_clocks_init(u32 mode); void r8a7779_clocks_init(u32 mode); void rcar_gen2_clocks_init(u32 mode); -- cgit v1.2.3 From b9fe9421d06653d735df07954730795d907e618d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2016 15:24:58 +0200 Subject: clk: renesas: r8a7779: Remove obsolete r8a7779_clocks_init() The R-Car H1 board code no longer calls r8a7779_clocks_init(). Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme --- drivers/clk/renesas/clk-r8a7779.c | 9 --------- include/linux/clk/renesas.h | 1 - 2 files changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/clk-r8a7779.c b/drivers/clk/renesas/clk-r8a7779.c index ca7551bcb115..27fbfafaf2cd 100644 --- a/drivers/clk/renesas/clk-r8a7779.c +++ b/drivers/clk/renesas/clk-r8a7779.c @@ -89,8 +89,6 @@ static const unsigned int cpg_plla_mult[4] __initconst = { 42, 48, 56, 64 }; * Initialization */ -static u32 cpg_mode __initdata; - static struct clk * __init r8a7779_cpg_register_clock(struct device_node *np, struct r8a7779_cpg *cpg, const struct cpg_clk_config *config, @@ -178,10 +176,3 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np) } CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks", r8a7779_cpg_clocks_init); - -void __init r8a7779_clocks_init(u32 mode) -{ - cpg_mode = mode; - - of_clk_init(NULL); -} diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index 2b663bba1adc..9e969941f3f6 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -20,7 +20,6 @@ struct device; struct device_node; struct generic_pm_domain; -void r8a7779_clocks_init(u32 mode); void rcar_gen2_clocks_init(u32 mode); void cpg_mstp_add_clk_domain(struct device_node *np); -- cgit v1.2.3 From 3e91d07bb592895982400002020d510fd7b6e85f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2016 15:26:53 +0200 Subject: clk: renesas: rcar-gen2: Remove obsolete rcar_gen2_clocks_init() The R-Car Gen2 board code no longer calls rcar_gen2_clocks_init(). Signed-off-by: Geert Uytterhoeven Acked-by: Dirk Behme --- drivers/clk/renesas/clk-rcar-gen2.c | 7 ------- include/linux/clk/renesas.h | 2 -- 2 files changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index 3291fd430ad4..f39519edc645 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c @@ -445,10 +445,3 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) } CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks", rcar_gen2_cpg_clocks_init); - -void __init rcar_gen2_clocks_init(u32 mode) -{ - cpg_mode = mode; - - of_clk_init(NULL); -} diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index 9e969941f3f6..9ebf1f8243bb 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -20,8 +20,6 @@ struct device; struct device_node; struct generic_pm_domain; -void rcar_gen2_clocks_init(u32 mode); - void cpg_mstp_add_clk_domain(struct device_node *np); #ifdef CONFIG_CLK_RENESAS_CPG_MSTP int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev); -- cgit v1.2.3 From 10565dfd35488c45826201b4ce28597d6b5de3dd Mon Sep 17 00:00:00 2001 From: Milo Kim Date: Fri, 28 Oct 2016 15:54:12 +0900 Subject: spi: sun6i: Support Allwinner H3 SPI controller H3 has two SPI controllers. The size of the buffer is 64 * 8. (8 bit transfer by 64 entry FIFO) A31 has four controllers. The size of the buffer is 128 * 8. (8 bit transfer by 128 entry FIFO) Register maps are sharable, so sun6i SPI driver is reusable with device configuration. Use the variable, 'fifo_depth' instead of fixed value to support both SPI controllers. Signed-off-by: Milo Kim Acked-by: Maxime Ripard Signed-off-by: Mark Brown --- drivers/spi/spi-sun6i.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 9918a57a6a6e..e3114832c485 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #define SUN6I_FIFO_DEPTH 128 +#define SUN8I_FIFO_DEPTH 64 #define SUN6I_GBL_CTL_REG 0x04 #define SUN6I_GBL_CTL_BUS_ENABLE BIT(0) @@ -90,6 +92,7 @@ struct sun6i_spi { const u8 *tx_buf; u8 *rx_buf; int len; + unsigned long fifo_depth; }; static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg) @@ -155,7 +158,9 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable) static size_t sun6i_spi_max_transfer_size(struct spi_device *spi) { - return SUN6I_FIFO_DEPTH - 1; + struct sun6i_spi *sspi = spi_master_get_devdata(spi->master); + + return sspi->fifo_depth - 1; } static int sun6i_spi_transfer_one(struct spi_master *master, @@ -170,7 +175,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, u32 reg; /* We don't support transfer larger than the FIFO */ - if (tfr->len > SUN6I_FIFO_DEPTH) + if (tfr->len > sspi->fifo_depth) return -EINVAL; reinit_completion(&sspi->done); @@ -265,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, SUN6I_BURST_CTL_CNT_STC(tx_len)); /* Fill the TX FIFO */ - sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH); + sun6i_spi_fill_fifo(sspi, sspi->fifo_depth); /* Enable the interrupts */ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC); @@ -288,7 +293,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, goto out; } - sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH); + sun6i_spi_drain_fifo(sspi, sspi->fifo_depth); out: sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0); @@ -398,6 +403,8 @@ static int sun6i_spi_probe(struct platform_device *pdev) } sspi->master = master; + sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev); + master->max_speed_hz = 100 * 1000 * 1000; master->min_speed_hz = 3 * 1000; master->set_cs = sun6i_spi_set_cs; @@ -470,7 +477,8 @@ static int sun6i_spi_remove(struct platform_device *pdev) } static const struct of_device_id sun6i_spi_match[] = { - { .compatible = "allwinner,sun6i-a31-spi", }, + { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH }, + { .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH }, {} }; MODULE_DEVICE_TABLE(of, sun6i_spi_match); -- cgit v1.2.3 From 86c390dcd8cd1e248d60d5ce83575a02f029fda9 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 29 Sep 2016 14:05:46 +0530 Subject: clk: qcom: Add .is_enabled ops for clk-alpha-pll This would be useful in subsequent patches when the .set_rate operation would need to identify if the PLL is actually enabled Signed-off-by: Rajendra Nayak [sboyd@codeaurora.org: Simplify return statement of is_enabled op] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index c6ddc04ea2f0..47a1da3739ce 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -199,6 +199,30 @@ static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw) wait_for_pll_disable(pll); } +static int pll_is_enabled(struct clk_hw *hw, u32 mask) +{ + int ret; + u32 val, off; + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + + off = pll->offset; + ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); + if (ret) + return ret; + + return !!(val & mask); +} + +static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw) +{ + return pll_is_enabled(hw, PLL_ACTIVE_FLAG); +} + +static int clk_alpha_pll_is_enabled(struct clk_hw *hw) +{ + return pll_is_enabled(hw, PLL_LOCK_DET); +} + static int clk_alpha_pll_enable(struct clk_hw *hw) { int ret; @@ -408,6 +432,7 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate, const struct clk_ops clk_alpha_pll_ops = { .enable = clk_alpha_pll_enable, .disable = clk_alpha_pll_disable, + .is_enabled = clk_alpha_pll_is_enabled, .recalc_rate = clk_alpha_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = clk_alpha_pll_set_rate, @@ -417,6 +442,7 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_ops); const struct clk_ops clk_alpha_pll_hwfsm_ops = { .enable = clk_alpha_pll_hwfsm_enable, .disable = clk_alpha_pll_hwfsm_disable, + .is_enabled = clk_alpha_pll_hwfsm_is_enabled, .recalc_rate = clk_alpha_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = clk_alpha_pll_set_rate, -- cgit v1.2.3 From 3bd31cdc4aa673f5b5227bc25aba8d8ace61e594 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Wed, 19 Oct 2016 16:58:40 +0530 Subject: clk: qcom: Add freq tables for a few rcgs Add frequency tables for a few RCG clocks in msm8996 Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8996.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index fe03e6fbc7df..e22bbc27c907 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -464,10 +464,18 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { }, }; +static struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + { } +}; + static struct clk_rcg2 sdcc1_ice_core_clk_src = { .cmd_rcgr = 0x13024, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map, + .freq_tbl = ftbl_sdcc1_ice_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "sdcc1_ice_core_clk_src", .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div, @@ -1230,10 +1238,18 @@ static struct clk_rcg2 ufs_axi_clk_src = { }, }; +static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + { } +}; + static struct clk_rcg2 ufs_ice_core_clk_src = { .cmd_rcgr = 0x76014, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_ufs_ice_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "ufs_ice_core_clk_src", .parent_names = gcc_xo_gpll0, @@ -1242,10 +1258,19 @@ static struct clk_rcg2 ufs_ice_core_clk_src = { }, }; +static const struct freq_tbl ftbl_qspi_ser_clk_src[] = { + F(75000000, P_GPLL0, 8, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(256000000, P_GPLL4, 1.5, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + { } +}; + static struct clk_rcg2 qspi_ser_clk_src = { .cmd_rcgr = 0x8b00c, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map, + .freq_tbl = ftbl_qspi_ser_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "qspi_ser_clk_src", .parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div, -- cgit v1.2.3 From aad389634066e35be0114edca6d26efda6ab884d Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Thu, 21 Jul 2016 16:09:38 +0100 Subject: drm: mali-dp: Clear the config_valid flag before using it in wait_event. config_valid variable is used to signal the activation of the CVAL request when the vsync interrupt has fired. malidp_set_and_wait_config_valid() uses the variable in wait_event_interruptible_timeout without clearing it first, so the wait is skipped. Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 9f4739452a25..f15dc5484f31 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -42,6 +42,7 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm) struct malidp_hw_device *hwdev = malidp->dev; int ret; + atomic_set(&malidp->config_valid, 0); hwdev->set_config_valid(hwdev); /* don't wait for config_valid flag if we are in config mode */ if (hwdev->in_config_mode(hwdev)) -- cgit v1.2.3 From a6a7b9a207d46c6a32ecd1ed3ddd877640f90df4 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Fri, 29 Jul 2016 14:21:29 +0100 Subject: drm: mali-dp: Set the drm->irq_enabled flag to match driver's state. Mali DP driver does not use drm_irq_{un,}install() function so the drm->irq_enabled flag does not get set automatically. drm_wait_vblank() checks the value of the flag among other functions. Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index f15dc5484f31..9468dfd52336 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -378,6 +378,8 @@ static int malidp_bind(struct device *dev) if (ret < 0) goto irq_init_fail; + drm->irq_enabled = true; + ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) { DRM_ERROR("failed to initialise vblank\n"); @@ -403,6 +405,7 @@ fbdev_fail: vblank_fail: malidp_se_irq_fini(drm); malidp_de_irq_fini(drm); + drm->irq_enabled = false; irq_init_fail: component_unbind_all(dev, drm); bind_fail: -- cgit v1.2.3 From c7faee2109f978f3ef826c48b7e60609061fda4f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 3 Nov 2016 07:16:43 +0100 Subject: locking/drm: Fix i915_gem_shrinker_lock() locking Mike Krinkin reported hangs in the DRM code and bisected it to: 3ab7c086d5ec72585ef0 ("locking/drm: Kill mutex trickery") Hugh Dickins observed: "i915_gem_shrinker_lock() is broken: but copy the pattern from msm_gem_shrinker_lock() and it's okay - patch below." Pick up the fix in isolation to make sure the bug is fixed, cleanup patch will follow up. Originally-From: Hugh Dickins Reported-by: Hugh Dickins Reported-by: Mike Krinkin Cc: Andrew Morton Cc: Dave Airlie Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: chris@chris-wilson.co.uk Cc: jason.low2@hpe.com Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1610301645180.28429@eggly.anvils Signed-off-by: Ingo Molnar --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 36953757687e..e9bd2a81d03a 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -228,8 +228,9 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv) static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock) { if (!mutex_trylock(&dev->struct_mutex)) - *unlock = false; + return false; + *unlock = true; return true; } -- cgit v1.2.3 From c6a0637460c29799f1e63a6a4a65bda22caf4a54 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 6 Jul 2016 08:31:34 +0200 Subject: clk: sunxi-ng: Add A64 clocks Add the A64 CCU clocks set. Acked-by: Rob Herring Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- .../devicetree/bindings/clock/sunxi-ccu.txt | 1 + drivers/clk/sunxi-ng/Kconfig | 11 + drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 915 +++++++++++++++++++++ drivers/clk/sunxi-ng/ccu-sun50i-a64.h | 72 ++ include/dt-bindings/clock/sun50i-a64-ccu.h | 134 +++ include/dt-bindings/reset/sun50i-a64-ccu.h | 98 +++ 7 files changed, 1232 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-a64.c create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-a64.h create mode 100644 include/dt-bindings/clock/sun50i-a64-ccu.h create mode 100644 include/dt-bindings/reset/sun50i-a64-ccu.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt index 3868458a5feb..74d44a4273f2 100644 --- a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt +++ b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt @@ -7,6 +7,7 @@ Required properties : - "allwinner,sun8i-a23-ccu" - "allwinner,sun8i-a33-ccu" - "allwinner,sun8i-h3-ccu" + - "allwinner,sun50i-a64-ccu" - reg: Must contain the registers base address and length - clocks: phandle to the oscillators feeding the CCU. Two are needed: diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 1b4c55a53d7a..8454c6e3dd65 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -53,6 +53,17 @@ config SUNXI_CCU_MP # SoC Drivers +config SUN50I_A64_CCU + bool "Support for the Allwinner A64 CCU" + select SUNXI_CCU_DIV + select SUNXI_CCU_NK + select SUNXI_CCU_NKM + select SUNXI_CCU_NKMP + select SUNXI_CCU_NM + select SUNXI_CCU_MP + select SUNXI_CCU_PHASE + default ARM64 && ARCH_SUNXI + config SUN6I_A31_CCU bool "Support for the Allwinner A31/A31s CCU" select SUNXI_CCU_DIV diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 106cba27c331..24fbc6e5deb8 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_SUNXI_CCU_NM) += ccu_nm.o obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o # SoC support +obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c new file mode 100644 index 000000000000..0674515e2bad --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -0,0 +1,915 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_mult.h" +#include "ccu_nk.h" +#include "ccu_nkm.h" +#include "ccu_nkmp.h" +#include "ccu_nm.h" +#include "ccu_phase.h" + +#include "ccu-sun50i-a64.h" + +static struct ccu_nkmp pll_cpux_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 5), + .k = _SUNXI_CCU_MULT(4, 2), + .m = _SUNXI_CCU_DIV(0, 2), + .p = _SUNXI_CCU_DIV_MAX(16, 2, 4), + .common = { + .reg = 0x000, + .hw.init = CLK_HW_INIT("pll-cpux", + "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from + * the base (2x, 4x and 8x), and one variable divider (the one true + * pll audio). + * + * We don't have any need for the variable divider for now, so we just + * hardcode it to match with the clock names + */ +#define SUN50I_A64_PLL_AUDIO_REG 0x008 + +static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", + "osc24M", 0x010, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", + "osc24M", 0x018, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0", + "osc24M", 0x020, + 8, 5, /* N */ + 4, 2, /* K */ + 0, 2, /* M */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static struct ccu_nk pll_periph0_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 5), + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), + .fixed_post_div = 2, + .common = { + .reg = 0x028, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph0", "osc24M", + &ccu_nk_ops, CLK_SET_RATE_UNGATE), + }, +}; + +static struct ccu_nk pll_periph1_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 5), + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), + .fixed_post_div = 2, + .common = { + .reg = 0x02c, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph1", "osc24M", + &ccu_nk_ops, CLK_SET_RATE_UNGATE), + }, +}; + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", + "osc24M", 0x030, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", + "osc24M", 0x038, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +/* + * The output function can be changed to something more complex that + * we do not handle yet. + * + * Hardcode the mode so that we don't fall in that case. + */ +#define SUN50I_A64_PLL_MIPI_REG 0x040 + +struct ccu_nkm pll_mipi_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 4), + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), + .m = _SUNXI_CCU_DIV(0, 4), + .common = { + .reg = 0x040, + .hw.init = CLK_HW_INIT("pll-mipi", "pll-video0", + &ccu_nkm_ops, CLK_SET_RATE_UNGATE), + }, +}; + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_hsic_clk, "pll-hsic", + "osc24M", 0x044, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", + "osc24M", 0x048, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1", + "osc24M", 0x04c, + 8, 7, /* N */ + 0, 2, /* M */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static const char * const cpux_parents[] = { "osc32k", "osc24M", + "pll-cpux" , "pll-cpux" }; +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, + 0x050, 16, 2, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); + +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0); + +static const char * const ahb1_parents[] = { "osc32k", "osc24M", + "axi" , "pll-periph0" }; +static struct ccu_div ahb1_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), + + .mux = { + .shift = 12, + .width = 2, + + .variable_prediv = { + .index = 3, + .shift = 6, + .width = 2, + }, + }, + + .common = { + .reg = 0x054, + .features = CCU_FEATURE_VARIABLE_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("ahb1", + ahb1_parents, + &ccu_div_ops, + 0), + }, +}; + +static struct clk_div_table apb1_div_table[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 8 }, + { /* Sentinel */ }, +}; +static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1", + 0x054, 8, 2, apb1_div_table, 0); + +static const char * const apb2_parents[] = { "osc32k", "osc24M", + "pll-periph0-2x" , + "pll-periph0-2x" }; +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058, + 0, 5, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + 0); + +static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" }; +static const struct ccu_mux_fixed_prediv ahb2_fixed_predivs[] = { + { .index = 1, .div = 2 }, +}; +static struct ccu_mux ahb2_clk = { + .mux = { + .shift = 0, + .width = 1, + .fixed_predivs = ahb2_fixed_predivs, + .n_predivs = ARRAY_SIZE(ahb2_fixed_predivs), + }, + + .common = { + .reg = 0x05c, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("ahb2", + ahb2_parents, + &ccu_mux_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb1", + 0x060, BIT(1), 0); +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb1", + 0x060, BIT(5), 0); +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1", + 0x060, BIT(6), 0); +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1", + 0x060, BIT(8), 0); +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1", + 0x060, BIT(9), 0); +static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1", + 0x060, BIT(10), 0); +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1", + 0x060, BIT(13), 0); +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1", + 0x060, BIT(14), 0); +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb2", + 0x060, BIT(17), 0); +static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb1", + 0x060, BIT(18), 0); +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1", + 0x060, BIT(19), 0); +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1", + 0x060, BIT(20), 0); +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1", + 0x060, BIT(21), 0); +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1", + 0x060, BIT(23), 0); +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb1", + 0x060, BIT(24), 0); +static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb2", + 0x060, BIT(25), 0); +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb1", + 0x060, BIT(28), 0); +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb2", + 0x060, BIT(29), 0); + +static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1", + 0x064, BIT(0), 0); +static SUNXI_CCU_GATE(bus_tcon0_clk, "bus-tcon0", "ahb1", + 0x064, BIT(3), 0); +static SUNXI_CCU_GATE(bus_tcon1_clk, "bus-tcon1", "ahb1", + 0x064, BIT(4), 0); +static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb1", + 0x064, BIT(5), 0); +static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb1", + 0x064, BIT(8), 0); +static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb1", + 0x064, BIT(11), 0); +static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1", + 0x064, BIT(12), 0); +static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1", + 0x064, BIT(20), 0); +static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb1", + 0x064, BIT(21), 0); +static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb1", + 0x064, BIT(22), 0); + +static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1", + 0x068, BIT(0), 0); +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", + 0x068, BIT(1), 0); +static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1", + 0x068, BIT(5), 0); +static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", + 0x068, BIT(8), 0); +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", + 0x068, BIT(12), 0); +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", + 0x068, BIT(13), 0); +static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", + 0x068, BIT(14), 0); + +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", + 0x06c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", + 0x06c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", + 0x06c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", + 0x06c, BIT(5), 0); +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", + 0x06c, BIT(16), 0); +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", + 0x06c, BIT(17), 0); +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", + 0x06c, BIT(18), 0); +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", + 0x06c, BIT(19), 0); +static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", + 0x06c, BIT(20), 0); + +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb1", + 0x070, BIT(7), 0); + +static struct clk_div_table ths_div_table[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, +}; +static const char * const ths_parents[] = { "osc24M" }; +static struct ccu_div ths_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_TABLE(0, 2, ths_div_table), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0x074, + .hw.init = CLK_HW_INIT_PARENTS("ths", + ths_parents, + &ccu_div_ops, + 0), + }, +}; + +static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0", + "pll-periph1" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const mmc_default_parents[] = { "osc24M", "pll-periph0-2x", + "pll-periph1-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_default_parents, 0x088, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_default_parents, 0x08c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_default_parents, 0x090, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const ts_parents[] = { "osc24M", "pll-periph0", }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 4, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", mmc_default_parents, 0x09c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", + "pll-audio-2x", "pll-audio" }; +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, + 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, + 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents, + 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio", + 0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", + 0x0cc, BIT(8), 0); +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", + 0x0cc, BIT(9), 0); +static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "pll-hsic", + 0x0cc, BIT(10), 0); +static SUNXI_CCU_GATE(usb_hsic_12m_clk, "usb-hsic-12M", "osc12M", + 0x0cc, BIT(11), 0); +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", + 0x0cc, BIT(16), 0); +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "usb-ohci0", + 0x0cc, BIT(17), 0); + +static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" }; +static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents, + 0x0f4, 0, 4, 20, 2, CLK_IS_CRITICAL); + +static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram", + 0x100, BIT(0), 0); +static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "dram", + 0x100, BIT(1), 0); +static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", "dram", + 0x100, BIT(2), 0); +static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram", + 0x100, BIT(3), 0); + +static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" }; +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, + 0x104, 0, 4, 24, 3, BIT(31), 0); + +static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" }; +static const u8 tcon0_table[] = { 0, 2, }; +static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents, + tcon0_table, 0x118, 24, 3, BIT(31), + CLK_SET_RATE_PARENT); + +static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" }; +static const u8 tcon1_table[] = { 0, 2, }; +struct ccu_div tcon1_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV(0, 4), + .mux = _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table), + .common = { + .reg = 0x11c, + .hw.init = CLK_HW_INIT_PARENTS("tcon1", + tcon1_parents, + &ccu_div_ops, + CLK_SET_RATE_PARENT), + }, +}; + +static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents, + 0x124, 0, 4, 24, 3, BIT(31), 0); + +static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", + 0x130, BIT(31), 0); + +static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, + 0x134, 16, 4, 24, 3, BIT(31), 0); + +static const char * const csi_mclk_parents[] = { "osc24M", "pll-video1", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents, + 0x134, 0, 5, 8, 3, BIT(15), 0); + +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", + 0x13c, 16, 3, BIT(31), 0); + +static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio", + 0x140, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(ac_dig_4x_clk, "ac-dig-4x", "pll-audio-4x", + 0x140, BIT(30), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", + 0x144, BIT(31), 0); + +static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, + 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", + 0x154, BIT(31), 0); + +static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", + "pll-ddr0", "pll-ddr1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, + 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL); + +static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" }; +static const u8 dsi_dphy_table[] = { 0, 2, }; +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy", + dsi_dphy_parents, dsi_dphy_table, + 0x168, 0, 4, 8, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", + 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); + +/* Fixed Factor clocks */ +static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 1, 2, 0); + +/* We hardcode the divider to 4 for now */ +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", + "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", + "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", + "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x", + "pll-periph0", 1, 2, 0); +static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x", + "pll-periph1", 1, 2, 0); +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", + "pll-video0", 1, 2, CLK_SET_RATE_PARENT); + +static struct ccu_common *sun50i_a64_ccu_clks[] = { + &pll_cpux_clk.common, + &pll_audio_base_clk.common, + &pll_video0_clk.common, + &pll_ve_clk.common, + &pll_ddr0_clk.common, + &pll_periph0_clk.common, + &pll_periph1_clk.common, + &pll_video1_clk.common, + &pll_gpu_clk.common, + &pll_mipi_clk.common, + &pll_hsic_clk.common, + &pll_de_clk.common, + &pll_ddr1_clk.common, + &cpux_clk.common, + &axi_clk.common, + &ahb1_clk.common, + &apb1_clk.common, + &apb2_clk.common, + &ahb2_clk.common, + &bus_mipi_dsi_clk.common, + &bus_ce_clk.common, + &bus_dma_clk.common, + &bus_mmc0_clk.common, + &bus_mmc1_clk.common, + &bus_mmc2_clk.common, + &bus_nand_clk.common, + &bus_dram_clk.common, + &bus_emac_clk.common, + &bus_ts_clk.common, + &bus_hstimer_clk.common, + &bus_spi0_clk.common, + &bus_spi1_clk.common, + &bus_otg_clk.common, + &bus_ehci0_clk.common, + &bus_ehci1_clk.common, + &bus_ohci0_clk.common, + &bus_ohci1_clk.common, + &bus_ve_clk.common, + &bus_tcon0_clk.common, + &bus_tcon1_clk.common, + &bus_deinterlace_clk.common, + &bus_csi_clk.common, + &bus_hdmi_clk.common, + &bus_de_clk.common, + &bus_gpu_clk.common, + &bus_msgbox_clk.common, + &bus_spinlock_clk.common, + &bus_codec_clk.common, + &bus_spdif_clk.common, + &bus_pio_clk.common, + &bus_ths_clk.common, + &bus_i2s0_clk.common, + &bus_i2s1_clk.common, + &bus_i2s2_clk.common, + &bus_i2c0_clk.common, + &bus_i2c1_clk.common, + &bus_i2c2_clk.common, + &bus_scr_clk.common, + &bus_uart0_clk.common, + &bus_uart1_clk.common, + &bus_uart2_clk.common, + &bus_uart3_clk.common, + &bus_uart4_clk.common, + &bus_dbg_clk.common, + &ths_clk.common, + &nand_clk.common, + &mmc0_clk.common, + &mmc1_clk.common, + &mmc2_clk.common, + &ts_clk.common, + &ce_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &i2s0_clk.common, + &i2s1_clk.common, + &i2s2_clk.common, + &spdif_clk.common, + &usb_phy0_clk.common, + &usb_phy1_clk.common, + &usb_hsic_clk.common, + &usb_hsic_12m_clk.common, + &usb_ohci0_clk.common, + &usb_ohci1_clk.common, + &dram_clk.common, + &dram_ve_clk.common, + &dram_csi_clk.common, + &dram_deinterlace_clk.common, + &dram_ts_clk.common, + &de_clk.common, + &tcon0_clk.common, + &tcon1_clk.common, + &deinterlace_clk.common, + &csi_misc_clk.common, + &csi_sclk_clk.common, + &csi_mclk_clk.common, + &ve_clk.common, + &ac_dig_clk.common, + &ac_dig_4x_clk.common, + &avs_clk.common, + &hdmi_clk.common, + &hdmi_ddc_clk.common, + &mbus_clk.common, + &dsi_dphy_clk.common, + &gpu_clk.common, +}; + +static struct clk_hw_onecell_data sun50i_a64_hw_clks = { + .hws = { + [CLK_OSC_12M] = &osc12M_clk.hw, + [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, + [CLK_PLL_VE] = &pll_ve_clk.common.hw, + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, + [CLK_PLL_MIPI] = &pll_mipi_clk.common.hw, + [CLK_PLL_HSIC] = &pll_hsic_clk.common.hw, + [CLK_PLL_DE] = &pll_de_clk.common.hw, + [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, + [CLK_CPUX] = &cpux_clk.common.hw, + [CLK_AXI] = &axi_clk.common.hw, + [CLK_AHB1] = &ahb1_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_APB2] = &apb2_clk.common.hw, + [CLK_AHB2] = &ahb2_clk.common.hw, + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, + [CLK_BUS_CE] = &bus_ce_clk.common.hw, + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, + [CLK_BUS_NAND] = &bus_nand_clk.common.hw, + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, + [CLK_BUS_TS] = &bus_ts_clk.common.hw, + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, + [CLK_BUS_VE] = &bus_ve_clk.common.hw, + [CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw, + [CLK_BUS_TCON1] = &bus_tcon1_clk.common.hw, + [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, + [CLK_BUS_CSI] = &bus_csi_clk.common.hw, + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, + [CLK_BUS_DE] = &bus_de_clk.common.hw, + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, + [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw, + [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, + [CLK_BUS_CODEC] = &bus_codec_clk.common.hw, + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, + [CLK_BUS_PIO] = &bus_pio_clk.common.hw, + [CLK_BUS_THS] = &bus_ths_clk.common.hw, + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, + [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, + [CLK_BUS_SCR] = &bus_scr_clk.common.hw, + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, + [CLK_THS] = &ths_clk.common.hw, + [CLK_NAND] = &nand_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_TS] = &ts_clk.common.hw, + [CLK_CE] = &ce_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_I2S0] = &i2s0_clk.common.hw, + [CLK_I2S1] = &i2s1_clk.common.hw, + [CLK_I2S2] = &i2s2_clk.common.hw, + [CLK_SPDIF] = &spdif_clk.common.hw, + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, + [CLK_USB_HSIC] = &usb_hsic_clk.common.hw, + [CLK_USB_HSIC_12M] = &usb_hsic_12m_clk.common.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_DRAM] = &dram_clk.common.hw, + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, + [CLK_DRAM_CSI] = &dram_csi_clk.common.hw, + [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw, + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, + [CLK_DE] = &de_clk.common.hw, + [CLK_TCON0] = &tcon0_clk.common.hw, + [CLK_TCON1] = &tcon1_clk.common.hw, + [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, + [CLK_CSI_MISC] = &csi_misc_clk.common.hw, + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, + [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_AC_DIG] = &ac_dig_clk.common.hw, + [CLK_AC_DIG_4X] = &ac_dig_4x_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_HDMI] = &hdmi_clk.common.hw, + [CLK_HDMI_DDC] = &hdmi_ddc_clk.common.hw, + [CLK_MBUS] = &mbus_clk.common.hw, + [CLK_DSI_DPHY] = &dsi_dphy_clk.common.hw, + [CLK_GPU] = &gpu_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun50i_a64_ccu_resets[] = { + [RST_USB_PHY0] = { 0x0cc, BIT(0) }, + [RST_USB_PHY1] = { 0x0cc, BIT(1) }, + [RST_USB_HSIC] = { 0x0cc, BIT(2) }, + + [RST_DRAM] = { 0x0f4, BIT(31) }, + [RST_MBUS] = { 0x0fc, BIT(31) }, + + [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) }, + [RST_BUS_CE] = { 0x2c0, BIT(5) }, + [RST_BUS_DMA] = { 0x2c0, BIT(6) }, + [RST_BUS_MMC0] = { 0x2c0, BIT(8) }, + [RST_BUS_MMC1] = { 0x2c0, BIT(9) }, + [RST_BUS_MMC2] = { 0x2c0, BIT(10) }, + [RST_BUS_NAND] = { 0x2c0, BIT(13) }, + [RST_BUS_DRAM] = { 0x2c0, BIT(14) }, + [RST_BUS_EMAC] = { 0x2c0, BIT(17) }, + [RST_BUS_TS] = { 0x2c0, BIT(18) }, + [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) }, + [RST_BUS_SPI0] = { 0x2c0, BIT(20) }, + [RST_BUS_SPI1] = { 0x2c0, BIT(21) }, + [RST_BUS_OTG] = { 0x2c0, BIT(23) }, + [RST_BUS_EHCI0] = { 0x2c0, BIT(24) }, + [RST_BUS_EHCI1] = { 0x2c0, BIT(25) }, + [RST_BUS_OHCI0] = { 0x2c0, BIT(28) }, + [RST_BUS_OHCI1] = { 0x2c0, BIT(29) }, + + [RST_BUS_VE] = { 0x2c4, BIT(0) }, + [RST_BUS_TCON0] = { 0x2c4, BIT(3) }, + [RST_BUS_TCON1] = { 0x2c4, BIT(4) }, + [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) }, + [RST_BUS_CSI] = { 0x2c4, BIT(8) }, + [RST_BUS_HDMI0] = { 0x2c4, BIT(10) }, + [RST_BUS_HDMI1] = { 0x2c4, BIT(11) }, + [RST_BUS_DE] = { 0x2c4, BIT(12) }, + [RST_BUS_GPU] = { 0x2c4, BIT(20) }, + [RST_BUS_MSGBOX] = { 0x2c4, BIT(21) }, + [RST_BUS_SPINLOCK] = { 0x2c4, BIT(22) }, + [RST_BUS_DBG] = { 0x2c4, BIT(31) }, + + [RST_BUS_LVDS] = { 0x2c8, BIT(0) }, + + [RST_BUS_CODEC] = { 0x2d0, BIT(0) }, + [RST_BUS_SPDIF] = { 0x2d0, BIT(1) }, + [RST_BUS_THS] = { 0x2d0, BIT(8) }, + [RST_BUS_I2S0] = { 0x2d0, BIT(12) }, + [RST_BUS_I2S1] = { 0x2d0, BIT(13) }, + [RST_BUS_I2S2] = { 0x2d0, BIT(14) }, + + [RST_BUS_I2C0] = { 0x2d8, BIT(0) }, + [RST_BUS_I2C1] = { 0x2d8, BIT(1) }, + [RST_BUS_I2C2] = { 0x2d8, BIT(2) }, + [RST_BUS_SCR] = { 0x2d8, BIT(5) }, + [RST_BUS_UART0] = { 0x2d8, BIT(16) }, + [RST_BUS_UART1] = { 0x2d8, BIT(17) }, + [RST_BUS_UART2] = { 0x2d8, BIT(18) }, + [RST_BUS_UART3] = { 0x2d8, BIT(19) }, + [RST_BUS_UART4] = { 0x2d8, BIT(20) }, +}; + +static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = { + .ccu_clks = sun50i_a64_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_a64_ccu_clks), + + .hw_clks = &sun50i_a64_hw_clks, + + .resets = sun50i_a64_ccu_resets, + .num_resets = ARRAY_SIZE(sun50i_a64_ccu_resets), +}; + +static int sun50i_a64_ccu_probe(struct platform_device *pdev) +{ + struct resource *res; + void __iomem *reg; + u32 val; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + /* Force the PLL-Audio-1x divider to 4 */ + val = readl(reg + SUN50I_A64_PLL_AUDIO_REG); + val &= ~GENMASK(19, 16); + writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG); + + writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); + + return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc); +} + +static const struct of_device_id sun50i_a64_ccu_ids[] = { + { .compatible = "allwinner,sun50i-a64-ccu" }, + { } +}; + +static struct platform_driver sun50i_a64_ccu_driver = { + .probe = sun50i_a64_ccu_probe, + .driver = { + .name = "sun50i-a64-ccu", + .of_match_table = sun50i_a64_ccu_ids, + }, +}; +builtin_platform_driver(sun50i_a64_ccu_driver); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h new file mode 100644 index 000000000000..9b3cd24b78d2 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h @@ -0,0 +1,72 @@ +/* + * Copyright 2016 Maxime Ripard + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CCU_SUN50I_A64_H_ +#define _CCU_SUN50I_A64_H_ + +#include +#include + +#define CLK_OSC_12M 0 +#define CLK_PLL_CPUX 1 +#define CLK_PLL_AUDIO_BASE 2 +#define CLK_PLL_AUDIO 3 +#define CLK_PLL_AUDIO_2X 4 +#define CLK_PLL_AUDIO_4X 5 +#define CLK_PLL_AUDIO_8X 6 +#define CLK_PLL_VIDEO0 7 +#define CLK_PLL_VIDEO0_2X 8 +#define CLK_PLL_VE 9 +#define CLK_PLL_DDR0 10 +#define CLK_PLL_PERIPH0 11 +#define CLK_PLL_PERIPH0_2X 12 +#define CLK_PLL_PERIPH1 13 +#define CLK_PLL_PERIPH1_2X 14 +#define CLK_PLL_VIDEO1 15 +#define CLK_PLL_GPU 16 +#define CLK_PLL_MIPI 17 +#define CLK_PLL_HSIC 18 +#define CLK_PLL_DE 19 +#define CLK_PLL_DDR1 20 +#define CLK_CPUX 21 +#define CLK_AXI 22 +#define CLK_APB 23 +#define CLK_AHB1 24 +#define CLK_APB1 25 +#define CLK_APB2 26 +#define CLK_AHB2 27 + +/* All the bus gates are exported */ + +/* The first bunch of module clocks are exported */ + +#define CLK_USB_OHCI0_12M 90 + +#define CLK_USB_OHCI1_12M 92 + +#define CLK_DRAM 94 + +/* All the DRAM gates are exported */ + +/* Some more module clocks are exported */ + +#define CLK_MBUS 112 + +/* And the DSI and GPU module clock is exported */ + +#define CLK_NUMBER (CLK_GPU + 1) + +#endif /* _CCU_SUN50I_A64_H_ */ diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h new file mode 100644 index 000000000000..370c0a0473fc --- /dev/null +++ b/include/dt-bindings/clock/sun50i-a64-ccu.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_ +#define _DT_BINDINGS_CLK_SUN50I_A64_H_ + +#define CLK_BUS_MIPI_DSI 28 +#define CLK_BUS_CE 29 +#define CLK_BUS_DMA 30 +#define CLK_BUS_MMC0 31 +#define CLK_BUS_MMC1 32 +#define CLK_BUS_MMC2 33 +#define CLK_BUS_NAND 34 +#define CLK_BUS_DRAM 35 +#define CLK_BUS_EMAC 36 +#define CLK_BUS_TS 37 +#define CLK_BUS_HSTIMER 38 +#define CLK_BUS_SPI0 39 +#define CLK_BUS_SPI1 40 +#define CLK_BUS_OTG 41 +#define CLK_BUS_EHCI0 42 +#define CLK_BUS_EHCI1 43 +#define CLK_BUS_OHCI0 44 +#define CLK_BUS_OHCI1 45 +#define CLK_BUS_VE 46 +#define CLK_BUS_TCON0 47 +#define CLK_BUS_TCON1 48 +#define CLK_BUS_DEINTERLACE 49 +#define CLK_BUS_CSI 50 +#define CLK_BUS_HDMI 51 +#define CLK_BUS_DE 52 +#define CLK_BUS_GPU 53 +#define CLK_BUS_MSGBOX 54 +#define CLK_BUS_SPINLOCK 55 +#define CLK_BUS_CODEC 56 +#define CLK_BUS_SPDIF 57 +#define CLK_BUS_PIO 58 +#define CLK_BUS_THS 59 +#define CLK_BUS_I2S0 60 +#define CLK_BUS_I2S1 61 +#define CLK_BUS_I2S2 62 +#define CLK_BUS_I2C0 63 +#define CLK_BUS_I2C1 64 +#define CLK_BUS_I2C2 65 +#define CLK_BUS_SCR 66 +#define CLK_BUS_UART0 67 +#define CLK_BUS_UART1 68 +#define CLK_BUS_UART2 69 +#define CLK_BUS_UART3 70 +#define CLK_BUS_UART4 71 +#define CLK_BUS_DBG 72 +#define CLK_THS 73 +#define CLK_NAND 74 +#define CLK_MMC0 75 +#define CLK_MMC1 76 +#define CLK_MMC2 77 +#define CLK_TS 78 +#define CLK_CE 79 +#define CLK_SPI0 80 +#define CLK_SPI1 81 +#define CLK_I2S0 82 +#define CLK_I2S1 83 +#define CLK_I2S2 84 +#define CLK_SPDIF 85 +#define CLK_USB_PHY0 86 +#define CLK_USB_PHY1 87 +#define CLK_USB_HSIC 88 +#define CLK_USB_HSIC_12M 89 + +#define CLK_USB_OHCI0 91 + +#define CLK_USB_OHCI1 93 + +#define CLK_DRAM_VE 95 +#define CLK_DRAM_CSI 96 +#define CLK_DRAM_DEINTERLACE 97 +#define CLK_DRAM_TS 98 +#define CLK_DE 99 +#define CLK_TCON0 100 +#define CLK_TCON1 101 +#define CLK_DEINTERLACE 102 +#define CLK_CSI_MISC 103 +#define CLK_CSI_SCLK 104 +#define CLK_CSI_MCLK 105 +#define CLK_VE 106 +#define CLK_AC_DIG 107 +#define CLK_AC_DIG_4X 108 +#define CLK_AVS 109 +#define CLK_HDMI 110 +#define CLK_HDMI_DDC 111 + +#define CLK_DSI_DPHY 113 +#define CLK_GPU 114 + +#endif /* _DT_BINDINGS_CLK_SUN50I_H_ */ diff --git a/include/dt-bindings/reset/sun50i-a64-ccu.h b/include/dt-bindings/reset/sun50i-a64-ccu.h new file mode 100644 index 000000000000..db60b29ddb11 --- /dev/null +++ b/include/dt-bindings/reset/sun50i-a64-ccu.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_RST_SUN50I_A64_H_ +#define _DT_BINDINGS_RST_SUN50I_A64_H_ + +#define RST_USB_PHY0 0 +#define RST_USB_PHY1 1 +#define RST_USB_HSIC 2 +#define RST_DRAM 3 +#define RST_MBUS 4 +#define RST_BUS_MIPI_DSI 5 +#define RST_BUS_CE 6 +#define RST_BUS_DMA 7 +#define RST_BUS_MMC0 8 +#define RST_BUS_MMC1 9 +#define RST_BUS_MMC2 10 +#define RST_BUS_NAND 11 +#define RST_BUS_DRAM 12 +#define RST_BUS_EMAC 13 +#define RST_BUS_TS 14 +#define RST_BUS_HSTIMER 15 +#define RST_BUS_SPI0 16 +#define RST_BUS_SPI1 17 +#define RST_BUS_OTG 18 +#define RST_BUS_EHCI0 19 +#define RST_BUS_EHCI1 20 +#define RST_BUS_OHCI0 21 +#define RST_BUS_OHCI1 22 +#define RST_BUS_VE 23 +#define RST_BUS_TCON0 24 +#define RST_BUS_TCON1 25 +#define RST_BUS_DEINTERLACE 26 +#define RST_BUS_CSI 27 +#define RST_BUS_HDMI0 28 +#define RST_BUS_HDMI1 29 +#define RST_BUS_DE 30 +#define RST_BUS_GPU 31 +#define RST_BUS_MSGBOX 32 +#define RST_BUS_SPINLOCK 33 +#define RST_BUS_DBG 34 +#define RST_BUS_LVDS 35 +#define RST_BUS_CODEC 36 +#define RST_BUS_SPDIF 37 +#define RST_BUS_THS 38 +#define RST_BUS_I2S0 39 +#define RST_BUS_I2S1 40 +#define RST_BUS_I2S2 41 +#define RST_BUS_I2C0 42 +#define RST_BUS_I2C1 43 +#define RST_BUS_I2C2 44 +#define RST_BUS_SCR 45 +#define RST_BUS_UART0 46 +#define RST_BUS_UART1 47 +#define RST_BUS_UART2 48 +#define RST_BUS_UART3 49 +#define RST_BUS_UART4 50 + +#endif /* _DT_BINDINGS_RST_SUN50I_A64_H_ */ -- cgit v1.2.3 From a98e25e71d115702d79ef0f4f8009ce5d4cf37eb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:26:18 +0300 Subject: usb: chipidea: udc: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Acked-by: Peter Chen Cc: Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 661f43fe0f9e..7a535be3024e 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -821,7 +821,7 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req, } if (usb_endpoint_xfer_isoc(hwep->ep.desc) && - hwreq->req.length > (1 + hwep->ep.mult) * hwep->ep.maxpacket) { + hwreq->req.length > hwep->ep.mult * hwep->ep.maxpacket) { dev_err(hwep->ci->dev, "request length too big for isochronous\n"); return -EMSGSIZE; } @@ -1254,7 +1254,7 @@ static int ep_enable(struct usb_ep *ep, hwep->type = usb_endpoint_type(desc); hwep->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff; - hwep->ep.mult = QH_ISO_MULT(usb_endpoint_maxp(desc)); + hwep->ep.mult = usb_endpoint_maxp_mult(desc); if (hwep->type == USB_ENDPOINT_XFER_CONTROL) cap |= QH_IOS; -- cgit v1.2.3 From 91f97521bb3f42f7a0447c130c789cb7c1810714 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:27:55 +0300 Subject: usb: core: devices: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Cc: Greg Kroah-Hartman Cc: Acked-by: Greg Kroah-Hartman Signed-off-by: Felipe Balbi --- drivers/usb/core/devices.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index ef04b50e6bbb..00d1b26a81d3 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -182,14 +182,8 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, dir = usb_endpoint_dir_in(desc) ? 'I' : 'O'; - if (speed == USB_SPEED_HIGH) { - switch (usb_endpoint_maxp(desc) & (0x03 << 11)) { - case 1 << 11: - bandwidth = 2; break; - case 2 << 11: - bandwidth = 3; break; - } - } + if (speed == USB_SPEED_HIGH) + bandwidth = usb_endpoint_maxp_mult(desc); /* this isn't checking for illegal values */ switch (usb_endpoint_type(desc)) { -- cgit v1.2.3 From f0419d9fdf402b4ac07db974df9f3cd3f5de2cdd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:28:44 +0300 Subject: usb: gadget: udc: atmel: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Acked-by: Nicolas Ferre Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/atmel_usba_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 45bc997d0711..c57012b1ddf4 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -573,7 +573,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) * Bits 11:12 specify number of _additional_ * transactions per microframe. */ - nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1; + nr_trans = usb_endpoint_maxp_mult(desc); if (nr_trans > 3) return -EINVAL; -- cgit v1.2.3 From 1f5bba7381c58670dbb1b50885b45c2660e12eb5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:29:39 +0300 Subject: usb: gadget: udc: bdc: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Cc: Ashwini Pahuja Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/bdc/bdc_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/bdc/bdc_cmd.c b/drivers/usb/gadget/udc/bdc/bdc_cmd.c index 4d5e9188beae..6e920f1dce02 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_cmd.c +++ b/drivers/usb/gadget/udc/bdc/bdc_cmd.c @@ -182,7 +182,7 @@ int bdc_config_ep(struct bdc *bdc, struct bdc_ep *ep) usb_endpoint_xfer_int(desc)) { param2 |= si; - mbs = (usb_endpoint_maxp(desc) & 0x1800) >> 11; + mbs = usb_endpoint_maxp_mult(desc); param2 |= mbs << MB_SHIFT; } break; -- cgit v1.2.3 From ee8ac85596ec0b45c7dd49e2a2a0af50f98542cd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:30:59 +0300 Subject: usb: gadget: udc: dummy: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Cc: Alan Stern Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/dummy_hcd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 77d07904f932..14004cf88d4d 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -1483,8 +1483,7 @@ static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep) int tmp; /* high bandwidth mode */ - tmp = usb_endpoint_maxp(ep->desc); - tmp = (tmp >> 11) & 0x03; + tmp = usb_endpoint_maxp_mult(ep->desc); tmp *= 8 /* applies to entire frame */; limit += limit * tmp; } -- cgit v1.2.3 From 4250914d3a298aea7a6e940180d225b64e95a6e3 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:33:23 +0300 Subject: usb: gadget: udc: fsl: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Cc: Li Yang Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fsl_udc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index aab5221d6c2e..4459644b9b55 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -585,7 +585,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, break; case USB_ENDPOINT_XFER_ISOC: /* Calculate transactions needed for high bandwidth iso */ - mult = (unsigned char)(1 + ((max >> 11) & 0x03)); + mult = usb_endpoint_maxp_mult(desc); max = max & 0x7ff; /* bit 0~10 */ /* 3 transactions at most */ if (mult > 3) -- cgit v1.2.3 From 2f237451a815775d8616fe5dca9272839357a86b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:35:15 +0300 Subject: usb: gadget: udc: fusb300: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fusb300_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c index 948845c90e47..42ff308578df 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.c +++ b/drivers/usb/gadget/udc/fusb300_udc.c @@ -218,7 +218,7 @@ static int config_ep(struct fusb300_ep *ep, (info.type == USB_ENDPOINT_XFER_ISOC)) { info.interval = desc->bInterval; if (info.type == USB_ENDPOINT_XFER_ISOC) - info.bw_num = ((desc->wMaxPacketSize & 0x1800) >> 11); + info.bw_num = usb_endpoint_maxp_mult(desc); } ep_fifo_setting(fusb300, info); -- cgit v1.2.3 From a0fefbde4680b64582ebb2ca1a3c175e6871f905 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:36:58 +0300 Subject: usb: gadget: udc: gr: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/gr_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index 39b7136d31d9..b16f8af34050 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c @@ -1539,7 +1539,7 @@ static int gr_ep_enable(struct usb_ep *_ep, * additional transactions. */ max = 0x7ff & usb_endpoint_maxp(desc); - nt = 0x3 & (usb_endpoint_maxp(desc) >> 11); + nt = usb_endpoint_maxp_mult(desc) - 1; buffer_size = GR_BUFFER_SIZE(epctrl); if (nt && (mode == 0 || mode == 2)) { dev_err(dev->dev, -- cgit v1.2.3 From df4769e37a1f4244a997904ccdedb8eef85437ad Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:37:46 +0300 Subject: usb: gadget: udc: mv_udc: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/mv_udc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index ce73b3552269..542b70a83ee6 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -494,7 +494,7 @@ static int mv_ep_enable(struct usb_ep *_ep, break; case USB_ENDPOINT_XFER_ISOC: /* Calculate transactions needed for high bandwidth iso */ - mult = (unsigned char)(1 + ((max >> 11) & 0x03)); + mult = usb_endpoint_maxp_mult(desc); max = max & 0x7ff; /* bit 0~10 */ /* 3 transactions at most */ if (mult > 3) -- cgit v1.2.3 From e3b89080f2c50936a9f6eccedb1e07e293777f0a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:38:18 +0300 Subject: usb: host: ehci: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Cc: Alan Stern Cc: Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-q.c | 10 ++++++---- drivers/usb/host/ehci-sched.c | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index eca3710d8fc4..a45a5dc7ed9f 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -550,8 +550,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) /*-------------------------------------------------------------------------*/ -// high bandwidth multiplier, as encoded in highspeed endpoint descriptors -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) // ... and packet size, for any kind of endpoint descriptor #define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) @@ -770,9 +768,11 @@ qh_make ( gfp_t flags ) { struct ehci_qh *qh = ehci_qh_alloc (ehci, flags); + struct usb_host_endpoint *ep; u32 info1 = 0, info2 = 0; int is_input, type; int maxp = 0; + int mult; struct usb_tt *tt = urb->dev->tt; struct ehci_qh_hw *hw; @@ -787,7 +787,9 @@ qh_make ( is_input = usb_pipein (urb->pipe); type = usb_pipetype (urb->pipe); + ep = usb_pipe_endpoint (urb->dev, urb->pipe); maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input); + mult = usb_endpoint_maxp_mult (&ep->desc); /* 1024 byte maxpacket is a hardware ceiling. High bandwidth * acts like up to 3KB, but is built from smaller packets. @@ -810,7 +812,7 @@ qh_make ( qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, is_input, 0, - hb_mult(maxp) * max_packet(maxp))); + mult * max_packet(maxp))); qh->ps.phase = NO_FRAME; if (urb->dev->speed == USB_SPEED_HIGH) { @@ -929,7 +931,7 @@ qh_make ( info2 |= (EHCI_TUNE_MULT_HS << 30); } else { /* PIPE_INTERRUPT */ info1 |= max_packet (maxp) << 16; - info2 |= hb_mult (maxp) << 30; + info2 |= mult << 30; } break; default: diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 1dfe54f14737..6a9fa2c3a24e 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1064,7 +1064,7 @@ iso_stream_init( /* knows about ITD vs SITD */ if (dev->speed == USB_SPEED_HIGH) { - unsigned multi = hb_mult(maxp); + unsigned multi = usb_endpoint_maxp_mult(&urb->ep->desc); stream->highspeed = 1; -- cgit v1.2.3 From dcf5228c1c78c217eedade8455e20af32d359e00 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:39:22 +0300 Subject: usb: host: xhci: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Cc: Mathias Nyman Cc: Signed-off-by: Felipe Balbi --- drivers/usb/host/xhci-mem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 6afe32381209..679672da58ed 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1370,7 +1370,7 @@ static u32 xhci_get_endpoint_max_burst(struct usb_device *udev, if (udev->speed == USB_SPEED_HIGH && (usb_endpoint_xfer_isoc(&ep->desc) || usb_endpoint_xfer_int(&ep->desc))) - return (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; + return usb_endpoint_maxp_mult(&ep->desc) - 1; return 0; } @@ -1416,9 +1416,9 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev, return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); - max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; + max_burst = usb_endpoint_maxp_mult(&ep->desc); /* A 0 in max burst means 1 transfer per ESIT */ - return max_packet * (max_burst + 1); + return max_packet * max_burst; } /* Set up an endpoint with one ring segment. Do not allocate stream rings. -- cgit v1.2.3 From 131e19b9e3a5a463ab790db737c72040a918967c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:40:03 +0300 Subject: usb: misc: usbtest: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Signed-off-by: Felipe Balbi --- drivers/usb/misc/usbtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 5c8210dc6fd9..8edfbc8bf345 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1915,7 +1915,7 @@ static struct urb *iso_alloc_urb( if (bytes < 0 || !desc) return NULL; maxp = 0x7ff & usb_endpoint_maxp(desc); - maxp *= 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)); + maxp *= usb_endpoint_maxp_mult(desc); packets = DIV_ROUND_UP(bytes, maxp); urb = usb_alloc_urb(packets, GFP_KERNEL); @@ -2002,7 +2002,7 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param, 1 << (desc->bInterval - 1), (udev->speed == USB_SPEED_HIGH) ? "micro" : "", usb_endpoint_maxp(desc) & 0x7ff, - 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11))); + usb_endpoint_maxp_mult(desc)); dev_info(&dev->intf->dev, "total %lu msec (%lu packets)\n", -- cgit v1.2.3 From 6ddcabc2aa40ea3c45a4e2c00ae7ed1a1d990121 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:40:40 +0300 Subject: usb: musb: make use of new usb_endpoint_maxp_mult() We have introduced a helper to calculate multiplier value from wMaxPacketSize. Start using it. Cc: Bin Liu Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 8 ++++---- drivers/usb/musb/musb_host.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 4042ea017985..47304560f105 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -974,8 +974,8 @@ static int musb_gadget_enable(struct usb_ep *ep, goto fail; /* REVISIT this rules out high bandwidth periodic transfers */ - tmp = usb_endpoint_maxp(desc); - if (tmp & ~0x07ff) { + tmp = usb_endpoint_maxp_mult(desc) - 1; + if (tmp) { int ok; if (usb_endpoint_dir_in(desc)) @@ -987,12 +987,12 @@ static int musb_gadget_enable(struct usb_ep *ep, musb_dbg(musb, "no support for high bandwidth ISO"); goto fail; } - musb_ep->hb_mult = (tmp >> 11) & 3; + musb_ep->hb_mult = tmp; } else { musb_ep->hb_mult = 0; } - musb_ep->packet_sz = tmp & 0x7ff; + musb_ep->packet_sz = usb_endpoint_maxp(desc); tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1); /* enable the interrupts for the endpoint, set the endpoint diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 53bc4ceefe89..f6cdbad00dac 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2237,7 +2237,7 @@ static int musb_urb_enqueue( * Some musb cores don't support high bandwidth ISO transfers; and * we don't (yet!) support high bandwidth interrupt transfers. */ - qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03); + qh->hb_mult = usb_endpoint_maxp_mult(epd); if (qh->hb_mult > 1) { int ok = (qh->type == USB_ENDPOINT_XFER_ISOC); -- cgit v1.2.3 From 734d3ddd81902d839e5bba50601b011f6ae40d05 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 13:46:37 +0300 Subject: usb: host: xhci: purge GET_MAX_PACKET() usb_endpoint_maxp() is now returning maxpacket correctly - iow only bits 10:0. We can finaly remove XHCI's private GET_MAX_PACKET macro. Signed-off-by: Felipe Balbi --- drivers/usb/host/xhci-mem.c | 4 ++-- drivers/usb/host/xhci-mtk-sch.c | 4 ++-- drivers/usb/host/xhci-ring.c | 6 +++--- drivers/usb/host/xhci.c | 2 +- drivers/usb/host/xhci.h | 5 ----- 5 files changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 679672da58ed..48a26d378ef8 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1415,7 +1415,7 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev, else if (udev->speed >= USB_SPEED_SUPER) return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); + max_packet = usb_endpoint_maxp(&ep->desc); max_burst = usb_endpoint_maxp_mult(&ep->desc); /* A 0 in max burst means 1 transfer per ESIT */ return max_packet * max_burst; @@ -1461,7 +1461,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, max_esit_payload = xhci_get_max_esit_payload(udev, ep); interval = xhci_get_endpoint_interval(udev, ep); mult = xhci_get_endpoint_mult(udev, ep); - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); + max_packet = usb_endpoint_maxp(&ep->desc); max_burst = xhci_get_endpoint_max_burst(udev, ep); avg_trb_len = max_esit_payload; diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index 73f763c4f5f5..6e7ddf6cafae 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -337,7 +337,7 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n", __func__, usb_endpoint_type(&ep->desc), udev->speed, - GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)), + usb_endpoint_maxp(&ep->desc), usb_endpoint_dir_in(&ep->desc), ep); if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) { @@ -403,7 +403,7 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, xhci_dbg(xhci, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n", __func__, usb_endpoint_type(&ep->desc), udev->speed, - GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)), + usb_endpoint_maxp(&ep->desc), usb_endpoint_dir_in(&ep->desc), ep); if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 797137e26549..d4159117ceff 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3120,7 +3120,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred, if (xhci->quirks & XHCI_MTK_HOST) trb_buff_len = 0; - maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); + maxp = usb_endpoint_maxp(&urb->ep->desc); total_packet_count = DIV_ROUND_UP(td_total_len, maxp); /* Queueing functions don't count the current TRB into transferred */ @@ -3136,7 +3136,7 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, unsigned int max_pkt; u32 new_buff_len; - max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); + max_pkt = usb_endpoint_maxp(&urb->ep->desc); unalign = (enqd_len + *trb_buff_len) % max_pkt; /* we got lucky, last normal TRB data on segment is packet aligned */ @@ -3650,7 +3650,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, addr = start_addr + urb->iso_frame_desc[i].offset; td_len = urb->iso_frame_desc[i].length; td_remain_len = td_len; - max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); + max_pkt = usb_endpoint_maxp(&urb->ep->desc); total_pkt_count = DIV_ROUND_UP(td_len, max_pkt); /* A zero-length transfer still involves at least one packet. */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1a4ca02729c2..cf30cb696e75 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3209,7 +3209,7 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, for (i = 0; i < num_eps; i++) { ep_index = xhci_get_endpoint_index(&eps[i]->desc); - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&eps[i]->desc)); + max_packet = usb_endpoint_maxp(&eps[i]->desc); vdev->eps[ep_index].stream_info = xhci_alloc_stream_info(xhci, num_stream_ctxs, num_streams, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f945380035d0..3e5922dcc2f9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -747,11 +747,6 @@ struct xhci_ep_ctx { #define MAX_PACKET_MASK (0xffff << 16) #define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) -/* Get max packet size from ep desc. Bit 10..0 specify the max packet size. - * USB2.0 spec 9.6.6. - */ -#define GET_MAX_PACKET(p) ((p) & 0x7ff) - /* tx_info bitmasks */ #define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff) #define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16) -- cgit v1.2.3 From 670216f4d38bb128aa525450fe6ff9a5b3a2b8b0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: media: usb: uvc: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Cc: Laurent Pinchart Cc: Mauro Carvalho Chehab Cc: Acked-by: Laurent Pinchart Signed-off-by: Felipe Balbi --- drivers/media/usb/uvc/uvc_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 11e0e5f4e1c2..f3c1c852e401 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1553,7 +1553,7 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, u16 psize; u32 size; - psize = usb_endpoint_maxp(&ep->desc) & 0x7ff; + psize = usb_endpoint_maxp(&ep->desc); size = stream->ctrl.dwMaxPayloadTransferSize; stream->bulk.max_payload_size = size; -- cgit v1.2.3 From 63b9e901e461079f8efe5d7b60ffaa3ce88a0262 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: chipidea: udc: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Cc: Peter Chen Cc: Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 7a535be3024e..a7b383dc3d07 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1253,7 +1253,7 @@ static int ep_enable(struct usb_ep *ep, hwep->num = usb_endpoint_num(desc); hwep->type = usb_endpoint_type(desc); - hwep->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff; + hwep->ep.maxpacket = usb_endpoint_maxp(desc); hwep->ep.mult = usb_endpoint_maxp_mult(desc); if (hwep->type == USB_ENDPOINT_XFER_CONTROL) -- cgit v1.2.3 From c091b6b34b55423c023c91924babccf32528a430 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: core: devices: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Cc: Greg Kroah-Hartman Cc: Acked-by: Greg Kroah-Hartman Signed-off-by: Felipe Balbi --- drivers/usb/core/devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 00d1b26a81d3..f2987ddb1cde 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -227,7 +227,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, start += sprintf(start, format_endpt, desc->bEndpointAddress, dir, desc->bmAttributes, type, - (usb_endpoint_maxp(desc) & 0x07ff) * + usb_endpoint_maxp(desc) * bandwidth, interval, unit); return start; -- cgit v1.2.3 From 5f9492ff1dd7164e3785b9fbd1221fc717efe2c4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: core: endpoint: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Cc: Greg Kroah-Hartman Acked-by: Greg Kroah-Hartman Signed-off-by: Felipe Balbi --- drivers/usb/core/endpoint.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 101983b7e8d2..d8f37fbee848 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -50,8 +50,7 @@ static ssize_t wMaxPacketSize_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ep_device *ep = to_ep_device(dev); - return sprintf(buf, "%04x\n", - usb_endpoint_maxp(ep->desc) & 0x07ff); + return sprintf(buf, "%04x\n", usb_endpoint_maxp(ep->desc)); } static DEVICE_ATTR_RO(wMaxPacketSize); -- cgit v1.2.3 From 8437ab99a68363a1c56270932f705e56ff2b6b37 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 30 Sep 2016 11:24:59 +0300 Subject: usb: host: ehci: remove unnecessary max_packet() macro Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove this macro from the driver. Cc: Alan Stern Cc: Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-q.c | 22 +++++++++------------- drivers/usb/host/ehci-sched.c | 1 - 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index a45a5dc7ed9f..8f3f055c05fa 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -550,9 +550,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) /*-------------------------------------------------------------------------*/ -// ... and packet size, for any kind of endpoint descriptor -#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) - /* * reverse of qh_urb_transaction: free a list of TDs. * used for cleanup after errors, before HC sees an URB's TDs. @@ -649,7 +646,7 @@ qh_urb_transaction ( token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ - maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); + maxpacket = usb_maxpacket(urb->dev, urb->pipe, !is_input); /* * buffer gets wrapped in one or more qtds; @@ -788,14 +785,14 @@ qh_make ( is_input = usb_pipein (urb->pipe); type = usb_pipetype (urb->pipe); ep = usb_pipe_endpoint (urb->dev, urb->pipe); - maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input); + maxp = usb_endpoint_maxp (&ep->desc); mult = usb_endpoint_maxp_mult (&ep->desc); /* 1024 byte maxpacket is a hardware ceiling. High bandwidth * acts like up to 3KB, but is built from smaller packets. */ - if (max_packet(maxp) > 1024) { - ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp)); + if (maxp > 1024) { + ehci_dbg(ehci, "bogus qh maxpacket %d\n", maxp); goto done; } @@ -811,8 +808,7 @@ qh_make ( unsigned tmp; qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, - is_input, 0, - mult * max_packet(maxp))); + is_input, 0, mult * maxp)); qh->ps.phase = NO_FRAME; if (urb->dev->speed == USB_SPEED_HIGH) { @@ -856,7 +852,7 @@ qh_make ( think_time = tt ? tt->think_time : 0; qh->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time (urb->dev->speed, - is_input, 0, max_packet (maxp))); + is_input, 0, maxp)); if (urb->interval > ehci->periodic_size) urb->interval = ehci->periodic_size; qh->ps.period = urb->interval; @@ -927,10 +923,10 @@ qh_make ( * to help them do so. So now people expect to use * such nonconformant devices with Linux too; sigh. */ - info1 |= max_packet(maxp) << 16; + info1 |= maxp << 16; info2 |= (EHCI_TUNE_MULT_HS << 30); } else { /* PIPE_INTERRUPT */ - info1 |= max_packet (maxp) << 16; + info1 |= maxp << 16; info2 |= mult << 30; } break; @@ -1223,7 +1219,7 @@ static int submit_single_step_set_feature( token |= (1 /* "in" */ << 8); /*This is IN stage*/ - maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, 0)); + maxpacket = usb_maxpacket(urb->dev, urb->pipe, 0); qtd_fill(ehci, qtd, buf, len, token, maxpacket); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 6a9fa2c3a24e..980a6b3b2da2 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1068,7 +1068,6 @@ iso_stream_init( stream->highspeed = 1; - maxp = max_packet(maxp); buf1 |= maxp; maxp *= multi; -- cgit v1.2.3 From 9ad587710a2f7704d47ddb49ce60c909be836c2b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: composite: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 0426d3c1fff9..919d7d1b611c 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -197,7 +197,7 @@ int config_ep_by_speed(struct usb_gadget *g, ep_found: /* commit results */ - _ep->maxpacket = usb_endpoint_maxp(chosen_desc) & 0x7ff; + _ep->maxpacket = usb_endpoint_maxp(chosen_desc); _ep->desc = chosen_desc; _ep->comp_desc = NULL; _ep->maxburst = 0; -- cgit v1.2.3 From 44fbbf1f837f99cae0970bd72fefd72d90d73016 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: udc: atmel: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Acked-by: Nicolas Ferre Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/atmel_usba_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index c57012b1ddf4..125680db9379 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -529,7 +529,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc); - maxpacket = usb_endpoint_maxp(desc) & 0x7ff; + maxpacket = usb_endpoint_maxp(desc); if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index) || ep->index == 0 -- cgit v1.2.3 From cc2e895c604c480b7bc9603bc51963158bdb3b8c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: udc: bdc: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Cc: Ashwini Pahuja Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/bdc/bdc_ep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c index ccaa74ab6c0e..ff1ef24d1777 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.c +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c @@ -446,7 +446,7 @@ static int setup_bd_list_xfr(struct bdc *bdc, struct bdc_req *req, int num_bds) bd_xfr->start_bdi = bd_list->eqp_bdi; bd = bdi_to_bd(ep, bd_list->eqp_bdi); req_len = req->usb_req.length; - maxp = usb_endpoint_maxp(ep->desc) & 0x7ff; + maxp = usb_endpoint_maxp(ep->desc); tfs = roundup(req->usb_req.length, maxp); tfs = tfs/maxp; dev_vdbg(bdc->dev, "%s ep:%s num_bds:%d tfs:%d r_len:%d bd:%p\n", -- cgit v1.2.3 From c2b4d863e1dcb7f5b71926a45ee20de2f2c26cb2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: udc: dummy: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Cc: Alan Stern Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/dummy_hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 14004cf88d4d..02b14e91ae6c 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -503,7 +503,7 @@ static int dummy_enable(struct usb_ep *_ep, * maximum packet size. * For SS devices the wMaxPacketSize is limited by 1024. */ - max = usb_endpoint_maxp(desc) & 0x7ff; + max = usb_endpoint_maxp(desc); /* drivers must not request bad settings, since lower levels * (hardware or its drivers) may not check. some endpoints -- cgit v1.2.3 From 8c683c43fb8fe6549ca8a6527c2b742351d1e6ac Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: udc: net2272: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/net2272.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 7c6113432093..078c91d546e0 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -202,10 +202,10 @@ net2272_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - max = usb_endpoint_maxp(desc) & 0x1fff; + max = usb_endpoint_maxp(desc); spin_lock_irqsave(&dev->lock, flags); - _ep->maxpacket = max & 0x7fff; + _ep->maxpacket = max; ep->desc = desc; /* net2272_ep_reset() has already been called */ -- cgit v1.2.3 From 090bdb5c1f9c46fb6e08af583ef3ee270ed34072 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: udc: net2280: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/net2280.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 61c938c36d88..85504419ab31 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -224,14 +224,14 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) } /* sanity check ep-e/ep-f since their fifos are small */ - max = usb_endpoint_maxp(desc) & 0x1fff; + max = usb_endpoint_maxp(desc); if (ep->num > 4 && max > 64 && (dev->quirks & PLX_LEGACY)) { ret = -ERANGE; goto print_err; } spin_lock_irqsave(&dev->lock, flags); - _ep->maxpacket = max & 0x7ff; + _ep->maxpacket = max; ep->desc = desc; /* ep_reset() has already been called */ @@ -1839,7 +1839,7 @@ static ssize_t queues_show(struct device *_dev, struct device_attribute *attr, ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK, (t & USB_DIR_IN) ? "in" : "out", type_string(d->bmAttributes), - usb_endpoint_maxp(d) & 0x1fff, + usb_endpoint_maxp(d), ep->dma ? "dma" : "pio", ep->fifo_size ); } else /* ep0 should only have one transfer queued */ -- cgit v1.2.3 From 1e1eea0eeb39801a32103b948d02e4d811b92fd2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: udc: s3c2410: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/s3c2410_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index eb3571ee59e3..4643a01262b4 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -1047,10 +1047,10 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - max = usb_endpoint_maxp(desc) & 0x1fff; + max = usb_endpoint_maxp(desc); local_irq_save(flags); - _ep->maxpacket = max & 0x7ff; + _ep->maxpacket = max; ep->ep.desc = desc; ep->halted = 0; ep->bEndpointAddress = desc->bEndpointAddress; -- cgit v1.2.3 From efdd17e66718306c58cd8bab3a50cf8cfa645e8e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: misc: usbtest: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Signed-off-by: Felipe Balbi --- drivers/usb/misc/usbtest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 8edfbc8bf345..3525626bf086 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -2001,7 +2001,7 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param, "iso period %d %sframes, wMaxPacket %d, transactions: %d\n", 1 << (desc->bInterval - 1), (udev->speed == USB_SPEED_HIGH) ? "micro" : "", - usb_endpoint_maxp(desc) & 0x7ff, + usb_endpoint_maxp(desc), usb_endpoint_maxp_mult(desc)); dev_info(&dev->intf->dev, -- cgit v1.2.3 From 14f91dd524c42cdf137bda01c44e5e2f69a4c25e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: ip: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Cc: Valentina Manea Cc: Shuah Khan Cc: Signed-off-by: Felipe Balbi --- drivers/usb/usbip/vudc_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c index 7091848df6c8..2fdcdeb13a86 100644 --- a/drivers/usb/usbip/vudc_dev.c +++ b/drivers/usb/usbip/vudc_dev.c @@ -259,7 +259,7 @@ static int vep_enable(struct usb_ep *_ep, spin_lock_irqsave(&udc->lock, flags); - maxp = usb_endpoint_maxp(desc) & 0x7ff; + maxp = usb_endpoint_maxp(desc); _ep->maxpacket = maxp; ep->desc = desc; ep->type = usb_endpoint_type(desc); -- cgit v1.2.3 From 0eb862e9c4f7a6a3abee25bc561ffdbe3d57a9d1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: udc: fsl: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Cc: Li Yang Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fsl_udc_core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index 4459644b9b55..71094e479a96 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -586,7 +586,6 @@ static int fsl_ep_enable(struct usb_ep *_ep, case USB_ENDPOINT_XFER_ISOC: /* Calculate transactions needed for high bandwidth iso */ mult = usb_endpoint_maxp_mult(desc); - max = max & 0x7ff; /* bit 0~10 */ /* 3 transactions at most */ if (mult > 3) goto en_done; -- cgit v1.2.3 From 9d8ee9c4b65176dd7e79b444d6da0288edca2efc Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:17:38 +0300 Subject: usb: gadget: udc: mv: remove unnecessary & operation Now that usb_endpoint_maxp() only returns the lowest 11 bits from wMaxPacketSize, we can remove the & operation from this driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/mv_udc_core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 542b70a83ee6..d82a91bddbd9 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -495,7 +495,6 @@ static int mv_ep_enable(struct usb_ep *_ep, case USB_ENDPOINT_XFER_ISOC: /* Calculate transactions needed for high bandwidth iso */ mult = usb_endpoint_maxp_mult(desc); - max = max & 0x7ff; /* bit 0~10 */ /* 3 transactions at most */ if (mult > 3) goto en_done; -- cgit v1.2.3 From fa8d965d736be5a0e1e9206ebe1703b07b69217d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 28 Sep 2016 14:58:33 +0300 Subject: usb: dwc3: trace: pretty print high-bandwidth transfers too In case of periodic transfers, let's pretty print the size field as a multiplier followed by length, such as : 3x 1024 instead of: 33555456 Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/trace.h | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index a4ef5e7bf6b8..88ddd01c42af 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -239,6 +239,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, __field(u32, bph) __field(u32, size) __field(u32, ctrl) + __field(u32, type) ), TP_fast_assign( snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); @@ -249,11 +250,31 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, __entry->bph = trb->bph; __entry->size = trb->size; __entry->ctrl = trb->ctrl; + __entry->type = usb_endpoint_type(dep->endpoint.desc); ), - TP_printk("%s: %d/%d trb %p buf %08x%08x size %d ctrl %08x (%c%c%c%c:%c%c:%s)", + TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)", __get_str(name), __entry->queued, __entry->allocated, __entry->trb, __entry->bph, __entry->bpl, - __entry->size, __entry->ctrl, + ({char *s; + int pcm = ((__entry->size >> 24) & 3) + 1; + switch (__entry->type) { + case USB_ENDPOINT_XFER_INT: + case USB_ENDPOINT_XFER_ISOC: + switch (pcm) { + case 1: + s = "1x "; + break; + case 2: + s = "2x "; + break; + case 3: + s = "3x "; + break; + } + default: + s = ""; + } s; }), + DWC3_TRB_SIZE_LENGTH(__entry->size), __entry->ctrl, __entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h', __entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l', __entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c', -- cgit v1.2.3 From a97ea994605e805efeb1dc07a6d10ec5dd8e16d4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 29 Sep 2016 16:28:56 +0300 Subject: usb: dwc3: gadget: offset Start Transfer latency for bulk EPs We can offset the latency of a full Start Transfer command - where we _must_ poll for its completion - to usb_ep_enable() time. This means that once requests start showing up from the gadget driver, we can rely on No Response Update Transfer command - where we don't need to poll for completion. This patch, starts implementing this method for Bulk endpoints, even though, technically, we could extend it to all other endpoints in future commits. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4d191c8acb59..c692aafa7397 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -617,6 +617,35 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, trb_link->ctrl |= DWC3_TRB_CTRL_HWO; } + /* + * Issue StartTransfer here with no-op TRB so we can always rely on No + * Response Update Transfer command. + */ + if (usb_endpoint_xfer_bulk(desc)) { + struct dwc3_gadget_ep_cmd_params params; + struct dwc3_trb *trb; + dma_addr_t trb_dma; + u32 cmd; + + memset(¶ms, 0, sizeof(params)); + trb = &dep->trb_pool[0]; + trb_dma = dwc3_trb_dma_offset(dep, trb); + + params.param0 = upper_32_bits(trb_dma); + params.param1 = lower_32_bits(trb_dma); + + cmd = DWC3_DEPCMD_STARTTRANSFER; + + ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); + if (ret < 0) + return ret; + + dep->flags |= DWC3_EP_BUSY; + + dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep); + WARN_ON_ONCE(!dep->resource_index); + } + return 0; } -- cgit v1.2.3 From 57b14da56227217424493c9e0632877b740d2a09 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 30 Sep 2016 14:12:34 +0300 Subject: usb: dwc3: don't compile dwc3_trace() unless CONFIG_FTRACE=y We don't need dwc3_trace() unless we're building a kernel with CONFIG_FTRACE. This patch reduces dwc3.ko text size a bit while also removing overhead of dwc3_trace() calls. text data bss dec hex filename 50796 581 0 51377 c8b1 drivers/usb/dwc3/dwc3.o 43961 581 0 44542 adfe drivers/usb/dwc3/dwc3.o.patched Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Makefile | 6 +++++- drivers/usb/dwc3/debug.h | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 22420e17d68b..84de1e4151c4 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -3,7 +3,11 @@ CFLAGS_trace.o := -I$(src) obj-$(CONFIG_USB_DWC3) += dwc3.o -dwc3-y := core.o debug.o trace.o +dwc3-y := core.o + +ifneq ($(CONFIG_FTRACE),) + dwc3-y += debug.o trace.o +endif ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),) dwc3-y += host.o diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index b287fc6ab29e..d93780e84f07 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -344,7 +344,13 @@ static inline const char *dwc3_gadget_generic_cmd_status_string(int status) } } + +#if IS_ENABLED(CONFIG_FTRACE) void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...); +#else +static inline void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...) +{ } +#endif #ifdef CONFIG_DEBUG_FS extern void dwc3_debugfs_init(struct dwc3 *); -- cgit v1.2.3 From ba1773fb7de92498d3cd51a1cb5a8855b8996912 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 30 Sep 2016 15:01:45 +0300 Subject: usb: dwc3: Kconfig: allow all glues to build if COMPILE_TEST We shouldn't have any glue layer which doesn't compile everywhere. In order to make sure this is always the case, make sure COMPILE_TEST is properly added at dependency list of a config entry. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index b97cde76914d..a45b4f1ba689 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -62,7 +62,7 @@ config USB_DWC3_OMAP config USB_DWC3_EXYNOS tristate "Samsung Exynos Platform" - depends on ARCH_EXYNOS && OF || COMPILE_TEST + depends on (ARCH_EXYNOS || COMPILE_TEST) && OF default USB_DWC3 help Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside, @@ -98,7 +98,7 @@ config USB_DWC3_OF_SIMPLE config USB_DWC3_ST tristate "STMicroelectronics Platforms" - depends on ARCH_STI && OF + depends on (ARCH_STI || COMPILE_TEST) && OF default USB_DWC3 help STMicroelectronics SoCs with one DesignWare Core USB3 IP -- cgit v1.2.3 From 4dd5a69e495b71491bb21c273b6d5a979e2f685b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 30 Sep 2016 15:52:19 +0300 Subject: usb: dwc3: trace: add a proper tracepoint for reg accessors We want to reduce the usage of dwc3_trace() in favor of proper tracepoints which can be enabled/disabled by the user. Let's start with our register accessors. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/io.h | 6 ++---- drivers/usb/dwc3/trace.h | 35 ++++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h index a06f9a8fecc7..c69b06696824 100644 --- a/drivers/usb/dwc3/io.h +++ b/drivers/usb/dwc3/io.h @@ -40,8 +40,7 @@ static inline u32 dwc3_readl(void __iomem *base, u32 offset) * documentation, so we revert it back to the proper addresses, the * same way they are described on SNPS documentation */ - dwc3_trace(trace_dwc3_readl, "addr %p value %08x", - base - DWC3_GLOBALS_REGS_START + offset, value); + trace_dwc3_readl(base - DWC3_GLOBALS_REGS_START, offset, value); return value; } @@ -60,8 +59,7 @@ static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value) * documentation, so we revert it back to the proper addresses, the * same way they are described on SNPS documentation */ - dwc3_trace(trace_dwc3_writel, "addr %p value %08x", - base - DWC3_GLOBALS_REGS_START + offset, value); + trace_dwc3_writel(base - DWC3_GLOBALS_REGS_START, offset, value); } #endif /* __DRIVERS_USB_DWC3_IO_H */ diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index 88ddd01c42af..b2153f231cf0 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -37,29 +37,46 @@ DECLARE_EVENT_CLASS(dwc3_log_msg, TP_printk("%s", __get_str(msg)) ); -DEFINE_EVENT(dwc3_log_msg, dwc3_readl, +DEFINE_EVENT(dwc3_log_msg, dwc3_gadget, TP_PROTO(struct va_format *vaf), TP_ARGS(vaf) ); -DEFINE_EVENT(dwc3_log_msg, dwc3_writel, +DEFINE_EVENT(dwc3_log_msg, dwc3_core, TP_PROTO(struct va_format *vaf), TP_ARGS(vaf) ); -DEFINE_EVENT(dwc3_log_msg, dwc3_gadget, +DEFINE_EVENT(dwc3_log_msg, dwc3_ep0, TP_PROTO(struct va_format *vaf), TP_ARGS(vaf) ); -DEFINE_EVENT(dwc3_log_msg, dwc3_core, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) +DECLARE_EVENT_CLASS(dwc3_log_io, + TP_PROTO(void *base, u32 offset, u32 value), + TP_ARGS(base, offset, value), + TP_STRUCT__entry( + __field(void *, base) + __field(u32, offset) + __field(u32, value) + ), + TP_fast_assign( + __entry->base = base; + __entry->offset = offset; + __entry->value = value; + ), + TP_printk("addr %p value %08x", __entry->base + __entry->offset, + __entry->value) ); -DEFINE_EVENT(dwc3_log_msg, dwc3_ep0, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) +DEFINE_EVENT(dwc3_log_io, dwc3_readl, + TP_PROTO(void *base, u32 offset, u32 value), + TP_ARGS(base, offset, value) +); + +DEFINE_EVENT(dwc3_log_io, dwc3_writel, + TP_PROTO(void *base, u32 offset, u32 value), + TP_ARGS(base, offset, value) ); DECLARE_EVENT_CLASS(dwc3_log_event, -- cgit v1.2.3 From 6db3812e09db2577e0b1ebfd99ef0a0a1536fe0d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 3 Oct 2016 11:27:01 +0300 Subject: usb: dwc3: gadget: extract dwc3_gadget_get_irq() Cleanup only, no functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 62 +++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c692aafa7397..45a3325ff5b1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2871,6 +2871,39 @@ static irqreturn_t dwc3_interrupt(int irq, void *_evt) return dwc3_check_event_buf(evt); } +static int dwc3_gadget_get_irq(struct dwc3 *dwc) +{ + struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); + int irq; + + irq = platform_get_irq_byname(dwc3_pdev, "peripheral"); + if (irq > 0) + goto out; + + if (irq == -EPROBE_DEFER) + goto out; + + irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3"); + if (irq > 0) + goto out; + + if (irq == -EPROBE_DEFER) + goto out; + + irq = platform_get_irq(dwc3_pdev, 0); + if (irq > 0) + goto out; + + if (irq != -EPROBE_DEFER) + dev_err(dwc->dev, "missing peripheral IRQ\n"); + + if (!irq) + irq = -EINVAL; + +out: + return irq; +} + /** * dwc3_gadget_init - Initializes gadget related registers * @dwc: pointer to our controller context structure @@ -2879,30 +2912,13 @@ static irqreturn_t dwc3_interrupt(int irq, void *_evt) */ int dwc3_gadget_init(struct dwc3 *dwc) { - int ret, irq; - struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); + int ret; + int irq; - irq = platform_get_irq_byname(dwc3_pdev, "peripheral"); - if (irq == -EPROBE_DEFER) - return irq; - - if (irq <= 0) { - irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3"); - if (irq == -EPROBE_DEFER) - return irq; - - if (irq <= 0) { - irq = platform_get_irq(dwc3_pdev, 0); - if (irq <= 0) { - if (irq != -EPROBE_DEFER) { - dev_err(dwc->dev, - "missing peripheral IRQ\n"); - } - if (!irq) - irq = -EINVAL; - return irq; - } - } + irq = dwc3_gadget_get_irq(dwc); + if (irq < 0) { + ret = irq; + goto err0; } dwc->irq_gadget = irq; -- cgit v1.2.3 From 6d729a55cc0fc9f9a003b61491ee5868c9df5baf Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 3 Oct 2016 12:31:48 +0300 Subject: usb: dwc3: host: extract dwc3_host_get_irq() Cleanup only, no functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/host.c | 72 ++++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index f6533c68fed1..8c2679e7d4a7 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -19,6 +19,39 @@ #include "core.h" +static int dwc3_host_get_irq(struct dwc3 *dwc) +{ + struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); + int irq; + + irq = platform_get_irq_byname(dwc3_pdev, "host"); + if (irq > 0) + goto out; + + if (irq == -EPROBE_DEFER) + goto out; + + irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3"); + if (irq > 0) + goto out; + + if (irq == -EPROBE_DEFER) + goto out; + + irq = platform_get_irq(dwc3_pdev, 0); + if (irq > 0) + goto out; + + if (irq != -EPROBE_DEFER) + dev_err(dwc->dev, "missing host IRQ\n"); + + if (!irq) + irq = -EINVAL; + +out: + return irq; +} + int dwc3_host_init(struct dwc3 *dwc) { struct property_entry props[2]; @@ -27,39 +60,18 @@ int dwc3_host_init(struct dwc3 *dwc) struct resource *res; struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); - irq = platform_get_irq_byname(dwc3_pdev, "host"); - if (irq == -EPROBE_DEFER) + irq = dwc3_host_get_irq(dwc); + if (irq < 0) return irq; - if (irq <= 0) { - irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3"); - if (irq == -EPROBE_DEFER) - return irq; - - if (irq <= 0) { - irq = platform_get_irq(dwc3_pdev, 0); - if (irq <= 0) { - if (irq != -EPROBE_DEFER) { - dev_err(dwc->dev, - "missing host IRQ\n"); - } - if (!irq) - irq = -EINVAL; - return irq; - } else { - res = platform_get_resource(dwc3_pdev, - IORESOURCE_IRQ, 0); - } - } else { - res = platform_get_resource_byname(dwc3_pdev, - IORESOURCE_IRQ, - "dwc_usb3"); - } - - } else { + res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ, "host"); + if (!res) res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ, - "host"); - } + "dwc_usb3"); + if (!res) + res = platform_get_resource(dwc3_pdev, IORESOURCE_IRQ, 0); + if (!res) + return -ENOMEM; dwc->xhci_resources[1].start = irq; dwc->xhci_resources[1].end = irq; -- cgit v1.2.3 From 39e07ffb1c3d65c207c69cd7f65766c8e7721eeb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 3 Oct 2016 12:55:29 +0300 Subject: usb: dwc3: ep0: simplify dwc3_ep0_handle_feature() By extracting smaller functions from dwc3_ep0_handle_feature(), it becomes far easier to understand what's going on. Cleanup only, no functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 257 +++++++++++++++++++++++++++++++------------------ 1 file changed, 164 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index c562613ccd1a..a1f7c2b4b000 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -371,126 +371,197 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req); } -static int dwc3_ep0_handle_feature(struct dwc3 *dwc, +static int dwc3_ep0_handle_u1(struct dwc3 *dwc, enum usb_device_state state, + int set) +{ + u32 reg; + + if (state != USB_STATE_CONFIGURED) + return -EINVAL; + if ((dwc->speed != DWC3_DSTS_SUPERSPEED) && + (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS)) + return -EINVAL; + + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + if (set) + reg |= DWC3_DCTL_INITU1ENA; + else + reg &= ~DWC3_DCTL_INITU1ENA; + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + + return 0; +} + +static int dwc3_ep0_handle_u2(struct dwc3 *dwc, enum usb_device_state state, + int set) +{ + u32 reg; + + + if (state != USB_STATE_CONFIGURED) + return -EINVAL; + if ((dwc->speed != DWC3_DSTS_SUPERSPEED) && + (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS)) + return -EINVAL; + + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + if (set) + reg |= DWC3_DCTL_INITU2ENA; + else + reg &= ~DWC3_DCTL_INITU2ENA; + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + + return 0; +} + +static int dwc3_ep0_handle_test(struct dwc3 *dwc, enum usb_device_state state, + u32 wIndex, int set) +{ + if ((wIndex & 0xff) != 0) + return -EINVAL; + if (!set) + return -EINVAL; + + switch (wIndex >> 8) { + case TEST_J: + case TEST_K: + case TEST_SE0_NAK: + case TEST_PACKET: + case TEST_FORCE_EN: + dwc->test_mode_nr = wIndex >> 8; + dwc->test_mode = true; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int dwc3_ep0_handle_device(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl, int set) { - struct dwc3_ep *dep; - u32 recip; + enum usb_device_state state; u32 wValue; u32 wIndex; - u32 reg; - int ret; - enum usb_device_state state; + int ret = 0; wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); - recip = ctrl->bRequestType & USB_RECIP_MASK; state = dwc->gadget.state; - switch (recip) { - case USB_RECIP_DEVICE: + switch (wValue) { + case USB_DEVICE_REMOTE_WAKEUP: + break; + /* + * 9.4.1 says only only for SS, in AddressState only for + * default control pipe + */ + case USB_DEVICE_U1_ENABLE: + ret = dwc3_ep0_handle_u1(dwc, state, set); + break; + case USB_DEVICE_U2_ENABLE: + ret = dwc3_ep0_handle_u2(dwc, state, set); + break; + case USB_DEVICE_LTM_ENABLE: + ret = -EINVAL; + break; + case USB_DEVICE_TEST_MODE: + ret = dwc3_ep0_handle_test(dwc, state, wIndex, set); + break; + default: + ret = -EINVAL; + } - switch (wValue) { - case USB_DEVICE_REMOTE_WAKEUP: - break; - /* - * 9.4.1 says only only for SS, in AddressState only for - * default control pipe - */ - case USB_DEVICE_U1_ENABLE: - if (state != USB_STATE_CONFIGURED) - return -EINVAL; - if ((dwc->speed != DWC3_DSTS_SUPERSPEED) && - (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS)) - return -EINVAL; + return ret; +} - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - if (set) - reg |= DWC3_DCTL_INITU1ENA; - else - reg &= ~DWC3_DCTL_INITU1ENA; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - break; +static int dwc3_ep0_handle_intf(struct dwc3 *dwc, + struct usb_ctrlrequest *ctrl, int set) +{ + enum usb_device_state state; + u32 wValue; + u32 wIndex; + int ret = 0; - case USB_DEVICE_U2_ENABLE: - if (state != USB_STATE_CONFIGURED) - return -EINVAL; - if ((dwc->speed != DWC3_DSTS_SUPERSPEED) && - (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS)) - return -EINVAL; + wValue = le16_to_cpu(ctrl->wValue); + wIndex = le16_to_cpu(ctrl->wIndex); + state = dwc->gadget.state; - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - if (set) - reg |= DWC3_DCTL_INITU2ENA; - else - reg &= ~DWC3_DCTL_INITU2ENA; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - break; + switch (wValue) { + case USB_INTRF_FUNC_SUSPEND: + if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) + /* XXX enable Low power suspend */ + ; + if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) + /* XXX enable remote wakeup */ + ; + break; + default: + ret = -EINVAL; + } - case USB_DEVICE_LTM_ENABLE: + return ret; +} + +static int dwc3_ep0_handle_endpoint(struct dwc3 *dwc, + struct usb_ctrlrequest *ctrl, int set) +{ + struct dwc3_ep *dep; + enum usb_device_state state; + u32 wValue; + u32 wIndex; + int ret; + + wValue = le16_to_cpu(ctrl->wValue); + wIndex = le16_to_cpu(ctrl->wIndex); + state = dwc->gadget.state; + + switch (wValue) { + case USB_ENDPOINT_HALT: + dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); + if (!dep) return -EINVAL; - case USB_DEVICE_TEST_MODE: - if ((wIndex & 0xff) != 0) - return -EINVAL; - if (!set) - return -EINVAL; - - switch (wIndex >> 8) { - case TEST_J: - case TEST_K: - case TEST_SE0_NAK: - case TEST_PACKET: - case TEST_FORCE_EN: - dwc->test_mode_nr = wIndex >> 8; - dwc->test_mode = true; - break; - default: - return -EINVAL; - } + if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) break; - default: + + ret = __dwc3_gadget_ep_set_halt(dep, set, true); + if (ret) return -EINVAL; - } break; + default: + return -EINVAL; + } + + return 0; +} + +static int dwc3_ep0_handle_feature(struct dwc3 *dwc, + struct usb_ctrlrequest *ctrl, int set) +{ + u32 recip; + int ret; + enum usb_device_state state; + + recip = ctrl->bRequestType & USB_RECIP_MASK; + state = dwc->gadget.state; + switch (recip) { + case USB_RECIP_DEVICE: + ret = dwc3_ep0_handle_device(dwc, ctrl, set); + break; case USB_RECIP_INTERFACE: - switch (wValue) { - case USB_INTRF_FUNC_SUSPEND: - if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) - /* XXX enable Low power suspend */ - ; - if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) - /* XXX enable remote wakeup */ - ; - break; - default: - return -EINVAL; - } + ret = dwc3_ep0_handle_intf(dwc, ctrl, set); break; - case USB_RECIP_ENDPOINT: - switch (wValue) { - case USB_ENDPOINT_HALT: - dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); - if (!dep) - return -EINVAL; - if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) - break; - ret = __dwc3_gadget_ep_set_halt(dep, set, true); - if (ret) - return -EINVAL; - break; - default: - return -EINVAL; - } + ret = dwc3_ep0_handle_endpoint(dwc, ctrl, set); break; - default: - return -EINVAL; + ret = -EINVAL; } - return 0; + return ret; } static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) -- cgit v1.2.3 From b9bd138e06b931a4f668776fbf6d82e5ec8417b5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Oct 2016 10:55:15 +0300 Subject: usb: dwc3: gadget: remove unused 'first_trb_index' Recent changes have turned this field obsolete. Remove it. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 -- drivers/usb/dwc3/gadget.c | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 18e4c09ae286..bdd37871fc6c 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -705,7 +705,6 @@ struct dwc3_hwparams { * @dep: struct dwc3_ep owning this request * @sg: pointer to first incomplete sg * @num_pending_sgs: counter to pending sgs - * @first_trb_index: index to first trb used by this request * @epnum: endpoint number to which this request refers * @trb: pointer to struct dwc3_trb * @trb_dma: DMA address of @trb @@ -720,7 +719,6 @@ struct dwc3_request { struct scatterlist *sg; unsigned num_pending_sgs; - u8 first_trb_index; u8 epnum; struct dwc3_trb *trb; dma_addr_t trb_dma; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 45a3325ff5b1..2dfcbecec25c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -832,7 +832,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, dwc3_gadget_move_started_request(req); req->trb = trb; req->trb_dma = dwc3_trb_dma_offset(dep, trb); - req->first_trb_index = dep->trb_enqueue; dep->queued_requests++; } -- cgit v1.2.3 From 58f29034b4c47b202f76de055f843316c8a9325f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Oct 2016 17:10:39 +0300 Subject: usb: dwc3: gadget: CSP is only valid for OUT endpoints CSP bit is only valid for OUT endpoints. Synopsys databook is unclear if HW ignores CSP for IN endpoints (chances are, it does) but to avoid problems, let's make sure to set CSP only when valid to do so. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2dfcbecec25c..270e837f16e0 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -875,7 +875,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, } /* always enable Continue on Short Packet */ - trb->ctrl |= DWC3_TRB_CTRL_CSP; + if (usb_endpoint_dir_out(dep->endpoint.desc)) + trb->ctrl |= DWC3_TRB_CTRL_CSP; if ((!req->request.no_interrupt && !chain) || (dwc3_calc_trbs_left(dep) == 0)) -- cgit v1.2.3 From c9508c8c50f9ec6fc3e7e823f35c76fafba7e929 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 5 Oct 2016 14:26:23 +0300 Subject: usb: dwc3: gadget: only interrupt on short if short_not_ok is set We don't need to know about short packets unless gadget driver told us it's not ok to see them on the bus. In the normal situation we can continue processing the list of requests if we get a Short packet. Also, note that we're making sure ISP is only set for OUT endpoints, where that setting is valid. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 270e837f16e0..71d01b29e7b5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -875,12 +875,16 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, } /* always enable Continue on Short Packet */ - if (usb_endpoint_dir_out(dep->endpoint.desc)) + if (usb_endpoint_dir_out(dep->endpoint.desc)) { trb->ctrl |= DWC3_TRB_CTRL_CSP; + if (req->request.short_not_ok) + trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; + } + if ((!req->request.no_interrupt && !chain) || (dwc3_calc_trbs_left(dep) == 0)) - trb->ctrl |= DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_ISP_IMI; + trb->ctrl |= DWC3_TRB_CTRL_IOC; if (chain) trb->ctrl |= DWC3_TRB_CTRL_CHN; -- cgit v1.2.3 From 0a695d4c75ff13ab04dc1b6ff91a6f3407d27b63 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 7 Oct 2016 11:20:01 +0300 Subject: usb: dwc3: gadget: never ever kill the machine We should never kill the machine just because some USB endpoint type is wrong. WARN about it and move on. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 71d01b29e7b5..bcd0d32ed4e9 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -871,7 +871,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, * This is only possible with faulty memory because we * checked it already :) */ - BUG(); + dev_WARN(dwc->dev, "Unknown endpoint type %d\n", + usb_endpoint_type(dep->endpoint.desc)); } /* always enable Continue on Short Packet */ -- cgit v1.2.3 From f9d2f9228cde6bbb40f2cd0b96a6903b0c2d5052 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Thu, 13 Oct 2016 09:08:14 +0800 Subject: usb: dwc3: remove unused struct member dwc3->mem Member @mem in struct dwc3 is not used in any places. Clean up it. Signed-off-by: Lu Baolu Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 1 - drivers/usb/dwc3/core.h | 3 --- 2 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7287a763cd0c..3dc535a703f1 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -941,7 +941,6 @@ static int dwc3_probe(struct platform_device *pdev) return -ENOMEM; dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); - dwc->mem = mem; dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index bdd37871fc6c..29fd7aa5fc72 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -784,7 +784,6 @@ struct dwc3_scratchpad_array { * @ep0state: state of endpoint zero * @link_state: link state * @speed: device speed (super, high, full, low) - * @mem: points to start of memory which is used for this struct. * @hwparams: copy of hwparams registers * @root: debugfs root folder pointer * @regset: debugfs pointer to regdump file @@ -934,8 +933,6 @@ struct dwc3 { u8 num_out_eps; u8 num_in_eps; - void *mem; - struct dwc3_hwparams hwparams; struct dentry *root; struct debugfs_regset32 *regset; -- cgit v1.2.3 From 0bb39ca1ad8758f109cd2e7b30a5316f3097346a Mon Sep 17 00:00:00 2001 From: John Youn Date: Wed, 12 Oct 2016 18:00:55 -0700 Subject: usb: dwc3: Add support for device L1 exit For the usb31 IP and from version 2.90a of the usb3 IP, the core supports HW exit from L1 in HS. Enable it, otherwise the controller may never exit from LPM to do a transfer. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 10 ++++++++++ drivers/usb/dwc3/core.h | 4 ++++ 2 files changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 3dc535a703f1..fe1ecae73086 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -766,6 +766,16 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); } + /* + * Enable hardware control of sending remote wakeup in HS when + * the device is in the L1 state. + */ + if (dwc->revision >= DWC3_REVISION_290A) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); + reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; + dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); + } + return 0; err4: diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 29fd7aa5fc72..e878366ead00 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -198,6 +198,9 @@ #define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1) #define DWC3_GCTL_DSBLCLKGTNG (1 << 0) +/* Global User Control 1 Register */ +#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW (1 << 24) + /* Global USB2 PHY Configuration Register */ #define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) #define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS (1 << 30) @@ -908,6 +911,7 @@ struct dwc3 { #define DWC3_REVISION_260A 0x5533260a #define DWC3_REVISION_270A 0x5533270a #define DWC3_REVISION_280A 0x5533280a +#define DWC3_REVISION_290A 0x5533290a #define DWC3_REVISION_300A 0x5533300a #define DWC3_REVISION_310A 0x5533310a -- cgit v1.2.3 From 0759956f8ae7e230e2349e02045484bb5657b836 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 14 Oct 2016 16:19:01 +0300 Subject: usb: dwc3: core: introduce dwc3_core_is_valid() This little helper will be used to make sure we're dealing with a valid Synopsys DWC3 or DWC3.1 core. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index fe1ecae73086..3e9515073e05 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -594,19 +594,12 @@ static void dwc3_core_exit(struct dwc3 *dwc) phy_power_off(dwc->usb3_generic_phy); } -/** - * dwc3_core_init - Low-level initialization of DWC3 Core - * @dwc: Pointer to our controller context structure - * - * Returns 0 on success otherwise negative errno. - */ -static int dwc3_core_init(struct dwc3 *dwc) +static bool dwc3_core_is_valid(struct dwc3 *dwc) { - u32 hwparams4 = dwc->hwparams.hwparams4; - u32 reg; - int ret; + u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); + /* This should read as U3 followed by revision number */ if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { /* Detected DWC_usb3 IP */ @@ -616,6 +609,25 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); dwc->revision |= DWC3_REVISION_IS_DWC31; } else { + return false; + } + + return true; +} + +/** + * dwc3_core_init - Low-level initialization of DWC3 Core + * @dwc: Pointer to our controller context structure + * + * Returns 0 on success otherwise negative errno. + */ +static int dwc3_core_init(struct dwc3 *dwc) +{ + u32 hwparams4 = dwc->hwparams.hwparams4; + u32 reg; + int ret; + + if (!dwc3_core_is_valid(dwc)) { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; -- cgit v1.2.3 From 941f918ecfa757640fa8fa09086700cf5a188e77 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 14 Oct 2016 16:23:24 +0300 Subject: usb: dwc3: core: introduce dwc3_core_setup_global_control() This little helper will be used to setup anything related to GCTL register. There are no functional changes, this is a cleanup only patch. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 90 ++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 3e9515073e05..e65f30afb89a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -615,49 +615,10 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc) return true; } -/** - * dwc3_core_init - Low-level initialization of DWC3 Core - * @dwc: Pointer to our controller context structure - * - * Returns 0 on success otherwise negative errno. - */ -static int dwc3_core_init(struct dwc3 *dwc) +static void dwc3_core_setup_global_control(struct dwc3 *dwc) { - u32 hwparams4 = dwc->hwparams.hwparams4; - u32 reg; - int ret; - - if (!dwc3_core_is_valid(dwc)) { - dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); - ret = -ENODEV; - goto err0; - } - - /* - * Write Linux Version Code to our GUID register so it's easy to figure - * out which kernel version a bug was found. - */ - dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); - - /* Handle USB2.0-only core configuration */ - if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == - DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { - if (dwc->maximum_speed == USB_SPEED_SUPER) - dwc->maximum_speed = USB_SPEED_HIGH; - } - - /* issue device SoftReset too */ - ret = dwc3_soft_reset(dwc); - if (ret) - goto err0; - - ret = dwc3_core_soft_reset(dwc); - if (ret) - goto err0; - - ret = dwc3_phy_setup(dwc); - if (ret) - goto err0; + u32 hwparams4 = dwc->hwparams.hwparams4; + u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; @@ -726,7 +687,52 @@ static int dwc3_core_init(struct dwc3 *dwc) reg |= DWC3_GCTL_U2RSTECN; dwc3_writel(dwc->regs, DWC3_GCTL, reg); +} + +/** + * dwc3_core_init - Low-level initialization of DWC3 Core + * @dwc: Pointer to our controller context structure + * + * Returns 0 on success otherwise negative errno. + */ +static int dwc3_core_init(struct dwc3 *dwc) +{ + u32 reg; + int ret; + + if (!dwc3_core_is_valid(dwc)) { + dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); + ret = -ENODEV; + goto err0; + } + + /* + * Write Linux Version Code to our GUID register so it's easy to figure + * out which kernel version a bug was found. + */ + dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); + + /* Handle USB2.0-only core configuration */ + if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == + DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { + if (dwc->maximum_speed == USB_SPEED_SUPER) + dwc->maximum_speed = USB_SPEED_HIGH; + } + + /* issue device SoftReset too */ + ret = dwc3_soft_reset(dwc); + if (ret) + goto err0; + + ret = dwc3_core_soft_reset(dwc); + if (ret) + goto err0; + + ret = dwc3_phy_setup(dwc); + if (ret) + goto err0; + dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); ret = dwc3_setup_scratch_buffers(dwc); -- cgit v1.2.3 From 3b2733227f4018ea0be44c477806cfd3bf819f0b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 14 Oct 2016 16:28:32 +0300 Subject: usb: dwc3: core: remove unnecessary alignment Kernel will give us page aligned memory anyway. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index e65f30afb89a..1f33abf21e0f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -948,8 +948,6 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) } } -#define DWC3_ALIGN_MASK (16 - 1) - static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -962,13 +960,11 @@ static int dwc3_probe(struct platform_device *pdev) int ret; void __iomem *regs; - void *mem; - mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); - if (!mem) + dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); + if (!dwc) return -ENOMEM; - dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit v1.2.3 From c5ac6116db35db0d750216b3ac5e1db1e2bd59c2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 14 Oct 2016 16:30:52 +0300 Subject: usb: dwc3: core: add dwc3_get_properties() This helper will be responsible for reading and parsing our properties. No functional changes in this patch, cleanup only. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 90 +++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 1f33abf21e0f..5e61ef6a378d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -948,52 +948,13 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) } } -static int dwc3_probe(struct platform_device *pdev) +static void dwc3_get_properties(struct dwc3 *dwc) { - struct device *dev = &pdev->dev; - struct resource *res; - struct dwc3 *dwc; + struct device *dev = dwc->dev; u8 lpm_nyet_threshold; u8 tx_de_emphasis; u8 hird_threshold; - int ret; - - void __iomem *regs; - - dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); - if (!dwc) - return -ENOMEM; - - dwc->dev = dev; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "missing memory resource\n"); - return -ENODEV; - } - - dwc->xhci_resources[0].start = res->start; - dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + - DWC3_XHCI_REGS_END; - dwc->xhci_resources[0].flags = res->flags; - dwc->xhci_resources[0].name = res->name; - - res->start += DWC3_GLOBALS_REGS_START; - - /* - * Request memory region but exclude xHCI regs, - * since it will be requested by the xhci-plat driver. - */ - regs = devm_ioremap_resource(dev, res); - if (IS_ERR(regs)) { - ret = PTR_ERR(regs); - goto err0; - } - - dwc->regs = regs; - dwc->regs_size = resource_size(res); - /* default to highest possible threshold */ lpm_nyet_threshold = 0xff; @@ -1065,6 +1026,53 @@ static int dwc3_probe(struct platform_device *pdev) dwc->hird_threshold = hird_threshold | (dwc->is_utmi_l1_suspend << 4); +} + +static int dwc3_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct dwc3 *dwc; + + int ret; + + void __iomem *regs; + + dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); + if (!dwc) + return -ENOMEM; + + dwc->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "missing memory resource\n"); + return -ENODEV; + } + + dwc->xhci_resources[0].start = res->start; + dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + + DWC3_XHCI_REGS_END; + dwc->xhci_resources[0].flags = res->flags; + dwc->xhci_resources[0].name = res->name; + + res->start += DWC3_GLOBALS_REGS_START; + + /* + * Request memory region but exclude xHCI regs, + * since it will be requested by the xhci-plat driver. + */ + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) { + ret = PTR_ERR(regs); + goto err0; + } + + dwc->regs = regs; + dwc->regs_size = resource_size(res); + + dwc3_get_properties(dwc); + platform_set_drvdata(pdev, dwc); dwc3_cache_hwparams(dwc); -- cgit v1.2.3 From cf68923055cbb3a2d6a819a7197e4f69bf68cc44 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 14 Oct 2016 13:46:50 +0300 Subject: usb: dwc3: gadget: purge dwc3_stop_active_transfers() That function is unnecessarily called from dwc3_gadget_reset_interrupt(). Gadget drivers (and thus, functions) are required to dequeue all pending requests when they get notified about a USB Bus Reset. Trying to make sure there are no pending requests only serves the purpose of working around possibly bad gadgets. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index bcd0d32ed4e9..daebc089635b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2302,24 +2302,6 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) udelay(100); } -static void dwc3_stop_active_transfers(struct dwc3 *dwc) -{ - u32 epnum; - - for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { - struct dwc3_ep *dep; - - dep = dwc->eps[epnum]; - if (!dep) - continue; - - if (!(dep->flags & DWC3_EP_ENABLED)) - continue; - - dwc3_remove_requests(dwc, dep); - } -} - static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) { u32 epnum; @@ -2405,8 +2387,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) reg &= ~DWC3_DCTL_TSTCTRL_MASK; dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc->test_mode = false; - - dwc3_stop_active_transfers(dwc); dwc3_clear_stall_all_ep(dwc); /* Reset device address to zero */ -- cgit v1.2.3 From bb0147364850c42db2a0dff5ef018e57413eaf79 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 14 Oct 2016 17:11:33 +0800 Subject: usb: dwc3: gadget: don't clear RUN/STOP when it's invalid to do so When we change the USB function with configfs dynamically, we possibly met this situation: one core is doing the control transfer, another core is trying to unregister the USB gadget from userspace, we must wait for completing this control tranfer, or it will hang the controller to set the DEVCTRLHLT flag. [ felipe.balbi@linux.intel.com: several fixes to the patch - call complete() before starting following SETUP transfer - add a macro for ep0_in_setup's timeout - change commit subject slightly - break lines at 72 characters (git adds an 8-character tab) - avoid changes to dwc3_gadget_run_stop() ] Signed-off-by: Baolin Wang Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 3 +++ drivers/usb/dwc3/ep0.c | 2 ++ drivers/usb/dwc3/gadget.c | 17 +++++++++++++++++ 3 files changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index e878366ead00..5fc437021ac7 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -37,6 +37,7 @@ #define DWC3_MSG_MAX 500 /* Global constants */ +#define DWC3_PULL_UP_TIMEOUT 500 /* ms */ #define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */ #define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 @@ -751,6 +752,7 @@ struct dwc3_scratchpad_array { * @ep0_usb_req: dummy req used while handling STD USB requests * @ep0_bounce_addr: dma address of ep0_bounce * @scratch_addr: dma address of scratchbuf + * @ep0_in_setup: one control transfer is completed and enter setup phase * @lock: for synchronizing * @dev: pointer to our struct device * @xhci: pointer to our xHCI child @@ -848,6 +850,7 @@ struct dwc3 { dma_addr_t ep0_bounce_addr; dma_addr_t scratch_addr; struct dwc3_request ep0_usb_req; + struct completion ep0_in_setup; /* device lock */ spinlock_t lock; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index a1f7c2b4b000..15b62a5aaff8 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -284,6 +284,8 @@ void dwc3_ep0_out_start(struct dwc3 *dwc) { int ret; + complete(&dwc->ep0_in_setup); + ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8, DWC3_TRBCTL_CONTROL_SETUP, false); WARN_ON(ret < 0); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index daebc089635b..4743e53cc295 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1550,6 +1550,21 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) is_on = !!is_on; + /* + * Per databook, when we want to stop the gadget, if a control transfer + * is still in process, complete it and get the core into setup phase. + */ + if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) { + reinit_completion(&dwc->ep0_in_setup); + + ret = wait_for_completion_timeout(&dwc->ep0_in_setup, + msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT)); + if (ret == 0) { + dev_err(dwc->dev, "timed out waiting for SETUP phase\n"); + return -ETIMEDOUT; + } + } + spin_lock_irqsave(&dwc->lock, flags); ret = dwc3_gadget_run_stop(dwc, is_on, false); spin_unlock_irqrestore(&dwc->lock, flags); @@ -2945,6 +2960,8 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err4; } + init_completion(&dwc->ep0_in_setup); + dwc->gadget.ops = &dwc3_gadget_ops; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.sg_supported = true; -- cgit v1.2.3 From 5002c93135947881f4f35caadf7292f40df7ef6b Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 10 Oct 2016 12:48:36 +0200 Subject: usb: gadget: composite: use kasprintf() instead of open coding it Let's not reimplement generic kernel helpers, instead call kasprintf(). [ felipe.balbi@linux.intel.com: better commit log ] Signed-off-by: Juergen Gross Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 919d7d1b611c..41ab61f9b6e0 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2387,18 +2387,8 @@ EXPORT_SYMBOL_GPL(usb_composite_setup_continue); static char *composite_default_mfr(struct usb_gadget *gadget) { - char *mfr; - int len; - - len = snprintf(NULL, 0, "%s %s with %s", init_utsname()->sysname, - init_utsname()->release, gadget->name); - len++; - mfr = kmalloc(len, GFP_KERNEL); - if (!mfr) - return NULL; - snprintf(mfr, len, "%s %s with %s", init_utsname()->sysname, - init_utsname()->release, gadget->name); - return mfr; + return kasprintf(GFP_KERNEL, "%s %s with %s", init_utsname()->sysname, + init_utsname()->release, gadget->name); } void usb_composite_overwrite_options(struct usb_composite_dev *cdev, -- cgit v1.2.3 From 3f5ad8640cd1b5e95a26d9ec500435bd1ce57d72 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 27 Sep 2016 09:16:59 -0700 Subject: usb: Convert pr_warning to pr_warn Use the more common logging mechanism. Miscellanea: o Realign multiline statements o Coalesce format Acked-by: Robert Jarzmik Acked-by: Nicolas Ferre Signed-off-by: Joe Perches Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/rndis.c | 9 ++++----- drivers/usb/gadget/function/u_serial.c | 4 ++-- drivers/usb/gadget/udc/at91_udc.h | 2 +- drivers/usb/gadget/udc/atmel_usba_udc.c | 4 ++-- drivers/usb/gadget/udc/fsl_usb2_udc.h | 2 +- drivers/usb/gadget/udc/m66592-udc.c | 4 ++-- drivers/usb/gadget/udc/omap_udc.h | 2 +- drivers/usb/gadget/udc/pxa25x_udc.h | 2 +- drivers/usb/host/isp1362-hcd.c | 27 ++++++++++++++------------- drivers/usb/isp1760/isp1760-if.c | 2 +- 10 files changed, 29 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index ab6ac1b74ac0..766c328c15c0 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -474,8 +474,7 @@ static int gen_ndis_query_resp(struct rndis_params *params, u32 OID, u8 *buf, break; default: - pr_warning("%s: query unknown OID 0x%08X\n", - __func__, OID); + pr_warn("%s: query unknown OID 0x%08X\n", __func__, OID); } if (retval < 0) length = 0; @@ -546,8 +545,8 @@ static int gen_ndis_set_resp(struct rndis_params *params, u32 OID, break; default: - pr_warning("%s: set unknown OID 0x%08X, size %d\n", - __func__, OID, buf_len); + pr_warn("%s: set unknown OID 0x%08X, size %d\n", + __func__, OID, buf_len); } return retval; @@ -854,7 +853,7 @@ int rndis_msg_parser(struct rndis_params *params, u8 *buf) * In one case those messages seemed to relate to the host * suspending itself. */ - pr_warning("%s: unknown RNDIS message 0x%08X len %d\n", + pr_warn("%s: unknown RNDIS message 0x%08X len %d\n", __func__, MsgType, MsgLength); print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET, buf, MsgLength); diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index e0cd1e4c8892..62ec842874aa 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -622,8 +622,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) switch (req->status) { default: /* presumably a transient fault */ - pr_warning("%s: unexpected %s status %d\n", - __func__, ep->name, req->status); + pr_warn("%s: unexpected %s status %d\n", + __func__, ep->name, req->status); /* FALL THROUGH */ case 0: /* normal completion */ diff --git a/drivers/usb/gadget/udc/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h index 0a433e6b346b..9bbe72764f31 100644 --- a/drivers/usb/gadget/udc/at91_udc.h +++ b/drivers/usb/gadget/udc/at91_udc.h @@ -175,7 +175,7 @@ struct at91_request { #endif #define ERR(stuff...) pr_err("udc: " stuff) -#define WARNING(stuff...) pr_warning("udc: " stuff) +#define WARNING(stuff...) pr_warn("udc: " stuff) #define INFO(stuff...) pr_info("udc: " stuff) #define DBG(stuff...) pr_debug("udc: " stuff) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 125680db9379..f3212db9bc37 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -1464,8 +1464,8 @@ restart: pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA)); DBG(DBG_HW, "Packet length: %u\n", pkt_len); if (pkt_len != sizeof(crq)) { - pr_warning("udc: Invalid packet length %u " - "(expected %zu)\n", pkt_len, sizeof(crq)); + pr_warn("udc: Invalid packet length %u (expected %zu)\n", + pkt_len, sizeof(crq)); set_protocol_stall(udc, ep); return; } diff --git a/drivers/usb/gadget/udc/fsl_usb2_udc.h b/drivers/usb/gadget/udc/fsl_usb2_udc.h index 84715625b2b3..e92b8408b6f6 100644 --- a/drivers/usb/gadget/udc/fsl_usb2_udc.h +++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h @@ -554,7 +554,7 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) #endif #define ERR(stuff...) pr_err("udc: " stuff) -#define WARNING(stuff...) pr_warning("udc: " stuff) +#define WARNING(stuff...) pr_warn("udc: " stuff) #define INFO(stuff...) pr_info("udc: " stuff) /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c index 6e977dc22570..de3e03483659 100644 --- a/drivers/usb/gadget/udc/m66592-udc.c +++ b/drivers/usb/gadget/udc/m66592-udc.c @@ -637,7 +637,7 @@ static void init_controller(struct m66592 *m66592) clock = M66592_XTAL48; break; default: - pr_warning("m66592-udc: xtal configuration error\n"); + pr_warn("m66592-udc: xtal configuration error\n"); clock = 0; } @@ -649,7 +649,7 @@ static void init_controller(struct m66592 *m66592) irq_sense = 0; break; default: - pr_warning("m66592-udc: irq trigger config error\n"); + pr_warn("m66592-udc: irq trigger config error\n"); irq_sense = 0; } diff --git a/drivers/usb/gadget/udc/omap_udc.h b/drivers/usb/gadget/udc/omap_udc.h index cfadeb5fc5de..26974196cf44 100644 --- a/drivers/usb/gadget/udc/omap_udc.h +++ b/drivers/usb/gadget/udc/omap_udc.h @@ -187,7 +187,7 @@ struct omap_udc { #endif #define ERR(stuff...) pr_err("udc: " stuff) -#define WARNING(stuff...) pr_warning("udc: " stuff) +#define WARNING(stuff...) pr_warn("udc: " stuff) #define INFO(stuff...) pr_info("udc: " stuff) #define DBG(stuff...) pr_debug("udc: " stuff) diff --git a/drivers/usb/gadget/udc/pxa25x_udc.h b/drivers/usb/gadget/udc/pxa25x_udc.h index 4b8b72d7ab37..a458bec2536d 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.h +++ b/drivers/usb/gadget/udc/pxa25x_udc.h @@ -248,7 +248,7 @@ dump_state(struct pxa25x_udc *dev) #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0) #define ERR(stuff...) pr_err("udc: " stuff) -#define WARNING(stuff...) pr_warning("udc: " stuff) +#define WARNING(stuff...) pr_warn("udc: " stuff) #define INFO(stuff...) pr_info("udc: " stuff) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 6cf82ee460a6..0f2b4b358e1a 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -147,7 +147,7 @@ static inline struct isp1362_ep_queue *get_ptd_queue(struct isp1362_hcd *isp1362 if (epq) DBG(1, "%s: PTD $%04x is on %s queue\n", __func__, offset, epq->name); else - pr_warning("%s: invalid PTD $%04x\n", __func__, offset); + pr_warn("%s: invalid PTD $%04x\n", __func__, offset); return epq; } @@ -157,8 +157,9 @@ static inline int get_ptd_offset(struct isp1362_ep_queue *epq, u8 index) int offset; if (index * epq->blk_size > epq->buf_size) { - pr_warning("%s: Bad %s index %d(%d)\n", __func__, epq->name, index, - epq->buf_size / epq->blk_size); + pr_warn("%s: Bad %s index %d(%d)\n", + __func__, epq->name, index, + epq->buf_size / epq->blk_size); return -EINVAL; } offset = epq->buf_start + index * epq->blk_size; @@ -902,8 +903,8 @@ static void start_iso_transfers(struct isp1362_hcd *isp1362_hcd) ptd_offset = next_ptd(epq, ep); if (ptd_offset < 0) { - pr_warning("%s: req %d No more %s PTD buffers available\n", __func__, - ep->num_req, epq->name); + pr_warn("%s: req %d No more %s PTD buffers available\n", + __func__, ep->num_req, epq->name); break; } } @@ -973,8 +974,8 @@ static void finish_transfers(struct isp1362_hcd *isp1362_hcd, unsigned long done break; } if (done_map) - pr_warning("%s: done_map not clear: %08lx:%08lx\n", __func__, done_map, - epq->skip_map); + pr_warn("%s: done_map not clear: %08lx:%08lx\n", + __func__, done_map, epq->skip_map); atomic_dec(&epq->finishing); } @@ -1433,7 +1434,7 @@ static int isp1362_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) } else DBG(1, "%s: urb %p active; wait4irq\n", __func__, urb); } else { - pr_warning("%s: No EP in URB %p\n", __func__, urb); + pr_warn("%s: No EP in URB %p\n", __func__, urb); retval = -EINVAL; } done: @@ -1748,10 +1749,10 @@ static int isp1362_bus_suspend(struct usb_hcd *hcd) /* FALL THROUGH */ case OHCI_USB_RESET: status = -EBUSY; - pr_warning("%s: needs reinit!\n", __func__); + pr_warn("%s: needs reinit!\n", __func__); goto done; case OHCI_USB_SUSPEND: - pr_warning("%s: already suspended?\n", __func__); + pr_warn("%s: already suspended?\n", __func__); goto done; } DBG(0, "%s: suspend root hub\n", __func__); @@ -1839,7 +1840,7 @@ static int isp1362_bus_resume(struct usb_hcd *hcd) isp1362_hcd->hc_control = isp1362_read_reg32(isp1362_hcd, HCCONTROL); pr_info("%s: HCCONTROL: %08x\n", __func__, isp1362_hcd->hc_control); if (hcd->state == HC_STATE_RESUMING) { - pr_warning("%s: duplicate resume\n", __func__); + pr_warn("%s: duplicate resume\n", __func__); status = 0; } else switch (isp1362_hcd->hc_control & OHCI_CTRL_HCFS) { @@ -2474,8 +2475,8 @@ static int isp1362_chip_test(struct isp1362_hcd *isp1362_hcd) __func__, offset); break; } - pr_warning("%s: memory check with offset %02x ok after second read\n", - __func__, offset); + pr_warn("%s: memory check with offset %02x ok after second read\n", + __func__, offset); } } kfree(ref); diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c index 9535b2872183..79205b31e4a9 100644 --- a/drivers/usb/isp1760/isp1760-if.c +++ b/drivers/usb/isp1760/isp1760-if.c @@ -197,7 +197,7 @@ static int isp1760_plat_probe(struct platform_device *pdev) irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { - pr_warning("isp1760: IRQ resource not available\n"); + pr_warn("isp1760: IRQ resource not available\n"); return -ENODEV; } irqflags = irq_res->flags & IRQF_TRIGGER_MASK; -- cgit v1.2.3 From ffc4b4067e1bb639834a716b4148efce736b2ba6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 19 Sep 2016 01:03:13 +0900 Subject: usb: dwc2: cleanup with list_first_entry_or_null() The combo of list_empty() check and return list_first_entry() can be replaced with list_first_entry_or_null(). Signed-off-by: Masahiro Yamada Acked-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 24fbebc9b409..9dc6c482b89e 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1099,10 +1099,8 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now); */ static struct dwc2_hsotg_req *get_ep_head(struct dwc2_hsotg_ep *hs_ep) { - if (list_empty(&hs_ep->queue)) - return NULL; - - return list_first_entry(&hs_ep->queue, struct dwc2_hsotg_req, queue); + return list_first_entry_or_null(&hs_ep->queue, struct dwc2_hsotg_req, + queue); } /** -- cgit v1.2.3 From 785c91f8ae4d65efbe4d3366e30bb9bbe84b5f43 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 19 Sep 2016 01:03:14 +0900 Subject: usb: dwc3: cleanup with list_first_entry_or_null() The combo of list_empty() check and return list_first_entry() can be replaced with list_first_entry_or_null(). Signed-off-by: Masahiro Yamada Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index e4a1d974a5ae..3129bcf74d7d 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -62,10 +62,7 @@ struct dwc3; static inline struct dwc3_request *next_request(struct list_head *list) { - if (list_empty(list)) - return NULL; - - return list_first_entry(list, struct dwc3_request, list); + return list_first_entry_or_null(list, struct dwc3_request, list); } static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) -- cgit v1.2.3 From 31faf878bd8c7e2c078a3b75f65efe64f23b0f18 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 19 Sep 2016 01:03:15 +0900 Subject: usb: renesas_usbhs: cleanup with list_first_entry_or_null() The combo of list_empty() check and return list_first_entry() can be replaced with list_first_entry_or_null(). Acked-by: Yoshihiro Shimoda Signed-off-by: Masahiro Yamada Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 857e78337324..d1af831f43eb 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -100,10 +100,7 @@ static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) { - if (list_empty(&pipe->list)) - return NULL; - - return list_first_entry(&pipe->list, struct usbhs_pkt, node); + return list_first_entry_or_null(&pipe->list, struct usbhs_pkt, node); } static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, -- cgit v1.2.3 From 5bdcde90d745e111069900742d127310fb827b71 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Thu, 22 Sep 2016 15:51:53 +0200 Subject: usb: gadget: f_fs: use complete() instead complete_all() There is only one waiter for the completion, therefore there is no need to use complete_all(). Let's make that clear by using complete() instead of complete_all(). The usage pattern of the completion is: waiter context waker context reinit_completion() usb_esp_queue() wait_for_completion_interruptible() ffs_ep0_complete() complete() Acked-by: Michal Nazarewicz Signed-off-by: Daniel Wagner Cc: Felipe Balbi Cc: Michal Nazarewicz Cc: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index e40d47d47d82..dff72a873297 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -266,7 +266,7 @@ static void ffs_ep0_complete(struct usb_ep *ep, struct usb_request *req) { struct ffs_data *ffs = req->context; - complete_all(&ffs->ep0req_completion); + complete(&ffs->ep0req_completion); } static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) -- cgit v1.2.3 From 9a5380c3ba17b85b753ee7d6c42e94e1da81c00c Mon Sep 17 00:00:00 2001 From: Torsten Polle Date: Mon, 19 Sep 2016 10:05:40 +0200 Subject: usb: gadget: NCM: link socket buffers to the device for tx packets Socket buffers should be linked to the (network) device that allocated the buffers. Signed-off-by: Torsten Polle Signed-off-by: Harish Jenny K N Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_ncm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 639603722709..b6771ad2485a 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1078,6 +1078,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port, if (!ncm->skb_tx_data) goto err; + ncm->skb_tx_data->dev = ncm->netdev; ntb_data = (void *) skb_put(ncm->skb_tx_data, ncb_len); memset(ntb_data, 0, ncb_len); /* dwSignature */ @@ -1096,6 +1097,8 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port, GFP_ATOMIC); if (!ncm->skb_tx_ndp) goto err; + + ncm->skb_tx_ndp->dev = ncm->netdev; ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp, opts->ndp_size); memset(ntb_ndp, 0, ncb_len); -- cgit v1.2.3 From 18d4689643b08c61e15b11bc78830e1d6d28df63 Mon Sep 17 00:00:00 2001 From: Torsten Polle Date: Mon, 19 Sep 2016 10:05:41 +0200 Subject: usb: gadget: u_ether: link socket buffers to the device for received packets Socket buffers should be linked to the (network) device that allocated the buffers. __netdev_alloc_skb performs this task. Signed-off-by: Torsten Polle Signed-off-by: Jim Baxter Signed-off-by: Harish Jenny K N Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/u_ether.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index fe1811650dbc..5aeb6d903075 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -224,7 +224,7 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) if (dev->port_usb->is_fixed) size = max_t(size_t, size, dev->port_usb->fixed_out_len); - skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); + skb = __netdev_alloc_skb(dev->net, size + NET_IP_ALIGN, gfp_flags); if (skb == NULL) { DBG(dev, "no rx skb\n"); goto enomem; -- cgit v1.2.3 From 38314e59a901696e437c7ee6ea2831f9ecae977d Mon Sep 17 00:00:00 2001 From: Torsten Polle Date: Mon, 19 Sep 2016 10:05:42 +0200 Subject: usb: gadget: NCM: differentiate consumed packets from dropped packets dev_kfree_skb_any() is used to free packets that are dropped by the network stack. Therefore the function should not be used for packets that have been successfully processed by the network stack. Instead dev_consume_skb_any() has to be used for such consumed packets. This separation helps to identify dropped packets. Signed-off-by: Torsten Polle Signed-off-by: Harish Jenny K N Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_ncm.c | 8 ++++---- drivers/usb/gadget/function/u_ether.c | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index b6771ad2485a..e8008fa35e1e 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -998,7 +998,7 @@ static struct sk_buff *package_for_tx(struct f_ncm *ncm) /* Merge the skbs */ swap(skb2, ncm->skb_tx_data); if (ncm->skb_tx_data) { - dev_kfree_skb_any(ncm->skb_tx_data); + dev_consume_skb_any(ncm->skb_tx_data); ncm->skb_tx_data = NULL; } @@ -1009,7 +1009,7 @@ static struct sk_buff *package_for_tx(struct f_ncm *ncm) /* Copy NTB across. */ ntb_iter = (void *) skb_put(skb2, ncm->skb_tx_ndp->len); memcpy(ntb_iter, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len); - dev_kfree_skb_any(ncm->skb_tx_ndp); + dev_consume_skb_any(ncm->skb_tx_ndp); ncm->skb_tx_ndp = NULL; /* Insert zero'd datagram. */ @@ -1136,7 +1136,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port, memset(ntb_data, 0, dgram_pad); ntb_data = (void *) skb_put(ncm->skb_tx_data, skb->len); memcpy(ntb_data, skb->data, skb->len); - dev_kfree_skb_any(skb); + dev_consume_skb_any(skb); skb = NULL; } else if (ncm->skb_tx_data && ncm->timer_force_tx) { @@ -1332,7 +1332,7 @@ static int ncm_unwrap_ntb(struct gether *port, } while (ndp_len > 2 * (opts->dgram_item_len * 2)); } while (ndp_index); - dev_kfree_skb_any(skb); + dev_consume_skb_any(skb); VDBG(port->func.config->cdev, "Parsed NTB with %d frames\n", dgram_counter); diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 5aeb6d903075..f4a640216913 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -455,16 +455,17 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req) /* FALLTHROUGH */ case -ECONNRESET: /* unlink */ case -ESHUTDOWN: /* disconnect etc */ + dev_kfree_skb_any(skb); break; case 0: dev->net->stats.tx_bytes += skb->len; + dev_consume_skb_any(skb); } dev->net->stats.tx_packets++; spin_lock(&dev->req_lock); list_add(&req->list, &dev->tx_reqs); spin_unlock(&dev->req_lock); - dev_kfree_skb_any(skb); atomic_dec(&dev->tx_qlen); if (netif_carrier_ok(dev->net)) -- cgit v1.2.3 From 76a638f8ac0dd1dadee8f87acff36174d473b7c1 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 31 Oct 2016 19:38:36 +0800 Subject: usb: dwc3: gadget: wait for End Transfer to complete Instead of just delaying for 100us, we should actually wait for End Transfer Command Complete interrupt before moving on. Note that this should only be done if we're dealing with one of the core revisions that actually require the interrupt before moving on. [ felipe.balbi@linux.intel.com: minor improvements ] Signed-off-by: Baolin Wang Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 8 ++++++++ drivers/usb/dwc3/gadget.c | 49 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 5fc437021ac7..c2b86856e85d 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -505,6 +506,7 @@ struct dwc3_event_buffer { * @endpoint: usb endpoint * @pending_list: list of pending requests for this endpoint * @started_list: list of started requests on this endpoint + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete * @lock: spinlock for endpoint request queue traversal * @regs: pointer to first endpoint register * @trb_pool: array of transaction buffers @@ -530,6 +532,8 @@ struct dwc3_ep { struct list_head pending_list; struct list_head started_list; + wait_queue_head_t wait_end_transfer; + spinlock_t lock; void __iomem *regs; @@ -546,6 +550,7 @@ struct dwc3_ep { #define DWC3_EP_BUSY (1 << 4) #define DWC3_EP_PENDING_REQUEST (1 << 5) #define DWC3_EP_MISSED_ISOC (1 << 6) +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN (1 << 31) @@ -1050,6 +1055,9 @@ struct dwc3_event_depevt { #define DEPEVT_TRANSFER_BUS_EXPIRY 2 u32 parameters:16; + +/* For Command Complete Events */ +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 8)) >> 8) } __packed; /** diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4743e53cc295..64d01ff8c119 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -593,11 +593,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, dep->comp_desc = comp_desc; dep->type = usb_endpoint_type(desc); dep->flags |= DWC3_EP_ENABLED; + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + init_waitqueue_head(&dep->wait_end_transfer); + if (usb_endpoint_xfer_control(desc)) return 0; @@ -699,7 +702,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->endpoint.desc = NULL; dep->comp_desc = NULL; dep->type = 0; - dep->flags = 0; + dep->flags &= DWC3_EP_END_TRANSFER_PENDING; return 0; } @@ -1783,9 +1786,6 @@ err0: static void __dwc3_gadget_stop(struct dwc3 *dwc) { - if (pm_runtime_suspended(dwc->dev)) - return; - dwc3_gadget_disable_irq(dwc); __dwc3_gadget_ep_disable(dwc->eps[0]); __dwc3_gadget_ep_disable(dwc->eps[1]); @@ -1795,9 +1795,30 @@ static int dwc3_gadget_stop(struct usb_gadget *g) { struct dwc3 *dwc = gadget_to_dwc(g); unsigned long flags; + int epnum; spin_lock_irqsave(&dwc->lock, flags); + + if (pm_runtime_suspended(dwc->dev)) + goto out; + __dwc3_gadget_stop(dwc); + + for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { + struct dwc3_ep *dep = dwc->eps[epnum]; + + if (!dep) + continue; + + if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) + continue; + + wait_event_lock_irq(dep->wait_end_transfer, + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), + dwc->lock); + } + +out: dwc->gadget_driver = NULL; spin_unlock_irqrestore(&dwc->lock, flags); @@ -2171,10 +2192,12 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, { struct dwc3_ep *dep; u8 epnum = event->endpoint_number; + u8 cmd; dep = dwc->eps[epnum]; - if (!(dep->flags & DWC3_EP_ENABLED)) + if (!(dep->flags & DWC3_EP_ENABLED) && + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) return; if (epnum == 0 || epnum == 1) { @@ -2215,8 +2238,15 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, return; } break; - case DWC3_DEPEVT_RXTXFIFOEVT: case DWC3_DEPEVT_EPCMDCMPLT: + cmd = DEPEVT_PARAMETER_CMD(event->parameters); + + if (cmd == DWC3_DEPCMD_ENDTRANSFER) { + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; + wake_up(&dep->wait_end_transfer); + } + break; + case DWC3_DEPEVT_RXTXFIFOEVT: break; } } @@ -2269,7 +2299,8 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) dep = dwc->eps[epnum]; - if (!dep->resource_index) + if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || + !dep->resource_index) return; /* @@ -2313,8 +2344,10 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) dep->resource_index = 0; dep->flags &= ~DWC3_EP_BUSY; - if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) + if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) { + dep->flags |= DWC3_EP_END_TRANSFER_PENDING; udelay(100); + } } static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) -- cgit v1.2.3 From 6cb2e4e3de10893f38dbf3923a9cc50c76548a89 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 21 Oct 2016 13:07:09 +0300 Subject: usb: dwc3: gadget: cope with XferNotReady before usb_ep_queue() If XferNotReady comes before usb_ep_queue() we will set our PENDING request flag and wait for a request. However, originally, we were assuming usb_ep_queue() would always happen before our first XferNotReady and that causes a corner case where we could try to issue ENDTRANSFER command before STARTTRANSFER. Let's fix that by tracking endpoints which have been started. Reported-by: Janusz Dziedzic Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/gadget.c | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c2b86856e85d..ebc8a542407f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -551,6 +551,7 @@ struct dwc3_ep { #define DWC3_EP_PENDING_REQUEST (1 << 5) #define DWC3_EP_MISSED_ISOC (1 << 6) #define DWC3_EP_END_TRANSFER_PENDING (1 << 7) +#define DWC3_EP_TRANSFER_STARTED (1 << 8) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN (1 << 31) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 64d01ff8c119..4191b00c0058 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -340,6 +340,20 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status); + if (ret == 0) { + switch (DWC3_DEPCMD_CMD(cmd)) { + case DWC3_DEPCMD_STARTTRANSFER: + dep->flags |= DWC3_EP_TRANSFER_STARTED; + break; + case DWC3_DEPCMD_ENDTRANSFER: + dep->flags &= ~DWC3_EP_TRANSFER_STARTED; + break; + default: + /* nothing */ + break; + } + } + if (unlikely(susphy)) { reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_SUSPHY; @@ -1066,6 +1080,14 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param) return 0; } +static int __dwc3_gadget_get_frame(struct dwc3 *dwc) +{ + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_DSTS); + return DWC3_DSTS_SOFFN(reg); +} + static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, struct dwc3_ep *dep, u32 cur_uf) { @@ -1143,10 +1165,16 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * errors which will force us issue EndTransfer command. */ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - if ((dep->flags & DWC3_EP_PENDING_REQUEST) && - list_empty(&dep->started_list)) { - dwc3_stop_active_transfer(dwc, dep->number, true); - dep->flags = DWC3_EP_ENABLED; + if ((dep->flags & DWC3_EP_PENDING_REQUEST)) { + if (dep->flags & DWC3_EP_TRANSFER_STARTED) { + dwc3_stop_active_transfer(dwc, dep->number, true); + dep->flags = DWC3_EP_ENABLED; + } else { + u32 cur_uf; + + cur_uf = __dwc3_gadget_get_frame(dwc); + __dwc3_gadget_start_isoc(dwc, dep, cur_uf); + } } return 0; } @@ -1392,10 +1420,8 @@ static const struct usb_ep_ops dwc3_gadget_ep_ops = { static int dwc3_gadget_get_frame(struct usb_gadget *g) { struct dwc3 *dwc = gadget_to_dwc(g); - u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - return DWC3_DSTS_SOFFN(reg); + return __dwc3_gadget_get_frame(dwc); } static int __dwc3_gadget_wakeup(struct dwc3 *dwc) -- cgit v1.2.3 From e62c5bc57367ac277b932571943c9a09e737ad88 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 25 Oct 2016 13:47:21 +0300 Subject: usb: dwc3: gadget: tracking per-TRB remaining bytes This will give us a simpler way of figuring out how many bytes were left in each TRB. It's useful for cases where we queue only part of an SG-list due to amount of available TRBs at the time of kicking the transfer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/gadget.c | 19 ++++++------------- 2 files changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index ebc8a542407f..2322863e3cf7 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -715,6 +715,7 @@ struct dwc3_hwparams { * @dep: struct dwc3_ep owning this request * @sg: pointer to first incomplete sg * @num_pending_sgs: counter to pending sgs + * @remaining: amount of data remaining * @epnum: endpoint number to which this request refers * @trb: pointer to struct dwc3_trb * @trb_dma: DMA address of @trb @@ -729,6 +730,7 @@ struct dwc3_request { struct scatterlist *sg; unsigned num_pending_sgs; + unsigned remaining; u8 epnum; struct dwc3_trb *trb; dma_addr_t trb_dma; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4191b00c0058..4e66e91fe883 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -178,6 +178,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, req->started = false; list_del(&req->list); req->trb = NULL; + req->remaining = 0; if (req->request.status == -EINPROGRESS) req->request.status = status; @@ -2014,7 +2015,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, return 1; count = trb->size & DWC3_TRB_SIZE_MASK; - req->request.actual += count; + req->remaining += count; if (dep->direction) { if (count) { @@ -2068,11 +2069,10 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_request *req, *n; struct dwc3_trb *trb; bool ioc = false; - int ret; + int ret = 0; list_for_each_entry_safe(req, n, &dep->started_list, list) { unsigned length; - unsigned actual; int chain; length = req->request.length; @@ -2100,17 +2100,10 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, event, status, chain); } - /* - * We assume here we will always receive the entire data block - * which we should receive. Meaning, if we program RX to - * receive 4K but we receive only 2K, we assume that's all we - * should receive and we simply bounce the request back to the - * gadget driver for further processing. - */ - actual = length - req->request.actual; - req->request.actual = actual; + req->request.actual = length - req->remaining; - if (ret && chain && (actual < length) && req->num_pending_sgs) + if (ret && chain && (req->request.actual < length) + && req->num_pending_sgs) return __dwc3_gadget_kick_transfer(dep, 0); dwc3_gadget_giveback(dep, req, status); -- cgit v1.2.3 From d86c5a676e5b1ee89da0cf9c845760c36cfde6d3 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 25 Oct 2016 13:48:52 +0300 Subject: usb: dwc3: gadget: always try to prepare on started_list first In cases where we're given an SG-list which is longer than the amount of currently available TRBs, we will be left with the same request on started_list and we should prioritize that request over possible new requests on pending_list. That's a way to guarantee requests complete in order. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4e66e91fe883..317bb9aed4a4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1020,6 +1020,24 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) if (!dwc3_calc_trbs_left(dep)) return; + /* + * We can get in a situation where there's a request in the started list + * but there weren't enough TRBs to fully kick it in the first time + * around, so it has been waiting for more TRBs to be freed up. + * + * In that case, we should check if we have a request with pending_sgs + * in the started list and prepare TRBs for that request first, + * otherwise we will prepare TRBs completely out of order and that will + * break things. + */ + list_for_each_entry(req, &dep->started_list, list) { + if (req->num_pending_sgs > 0) + dwc3_prepare_one_trb_sg(dep, req); + + if (!dwc3_calc_trbs_left(dep)) + return; + } + list_for_each_entry_safe(req, n, &dep->pending_list, list) { if (req->num_pending_sgs > 0) dwc3_prepare_one_trb_sg(dep, req); -- cgit v1.2.3 From 7282c4ef0b66bb3b715ba8875e4e30392e77c7c1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 25 Oct 2016 13:50:46 +0300 Subject: usb: dwc3: gadget: stop touching HWO TRBs Say we have three requests prepared to the HW (reqA, reqB, and reqC). All of them are composed of SG-lists with several entries and they all requests interrupt only on last TRBs of the SG-list. When we get interrupt for reqA, it could be that reqB is already half-way transferred and some of its TRBs will have HWO already cleared. It's okay to free up TRBs without HWO bit set, but we need to guarantee we don't giveback a request that's half-way transferred as that will confuse gadget drivers. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 317bb9aed4a4..4643c25702ae 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2104,6 +2104,9 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, for_each_sg(sg, s, pending, i) { trb = &dep->trb_pool[dep->trb_dequeue]; + if (trb->ctrl & DWC3_TRB_CTRL_HWO) + break; + req->sg = sg_next(s); req->num_pending_sgs--; -- cgit v1.2.3 From ff377ae47de5c395ec47baabcde0f3011e71ae70 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 25 Oct 2016 13:54:00 +0300 Subject: usb: dwc3: gadget: always kick if num_pending_sgs > 0 When we get a half-way processed request, we should make sure to try to prepare further TRBs for it or for any possibly queued up request held in our pending_list. This will make sure our controller is kept busy for as long as possible. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4643c25702ae..a9c1d75ba7d5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2123,8 +2123,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, req->request.actual = length - req->remaining; - if (ret && chain && (req->request.actual < length) - && req->num_pending_sgs) + if ((req->request.actual < length) && req->num_pending_sgs) return __dwc3_gadget_kick_transfer(dep, 0); dwc3_gadget_giveback(dep, req, status); -- cgit v1.2.3 From 0f817ae696b0485f7f83ba3e62f2f40fdde8f5c9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 24 Oct 2016 10:29:01 +0300 Subject: usb: dwc3: pci: add a private driver structure We'll be tracking a little more information for PCI drivers, it's about time we add a private structure for that. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 49 +++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 6df0f5dad9a4..0f54b8166e54 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -39,6 +39,16 @@ #define PCI_DEVICE_ID_INTEL_APL 0x5aaa #define PCI_DEVICE_ID_INTEL_KBP 0xa2b0 +/** + * struct dwc3_pci - Driver private structure + * @dwc3: child dwc3 platform_device + * @pci: our link to PCI bus + */ +struct dwc3_pci { + struct platform_device *dwc3; + struct pci_dev *pci; +}; + static const struct acpi_gpio_params reset_gpios = { 0, 0, false }; static const struct acpi_gpio_params cs_gpios = { 1, 0, false }; @@ -48,8 +58,11 @@ static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = { { }, }; -static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3) +static int dwc3_pci_quirks(struct dwc3_pci *dwc) { + struct platform_device *dwc3 = dwc->dwc3; + struct pci_dev *pdev = dwc->pci; + if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == PCI_DEVICE_ID_AMD_NL_USB) { struct property_entry properties[] = { @@ -139,8 +152,8 @@ static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3) static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { + struct dwc3_pci *dwc; struct resource res[2]; - struct platform_device *dwc3; int ret; struct device *dev = &pci->dev; @@ -152,11 +165,13 @@ static int dwc3_pci_probe(struct pci_dev *pci, pci_set_master(pci); - dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); - if (!dwc3) { - dev_err(dev, "couldn't allocate dwc3 device\n"); + dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); + if (!dwc) + return -ENOMEM; + + dwc->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); + if (!dwc->dwc3) return -ENOMEM; - } memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); @@ -169,20 +184,21 @@ static int dwc3_pci_probe(struct pci_dev *pci, res[1].name = "dwc_usb3"; res[1].flags = IORESOURCE_IRQ; - ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); + ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res)); if (ret) { dev_err(dev, "couldn't add resources to dwc3 device\n"); return ret; } - dwc3->dev.parent = dev; - ACPI_COMPANION_SET(&dwc3->dev, ACPI_COMPANION(dev)); + dwc->pci = pci; + dwc->dwc3->dev.parent = dev; + ACPI_COMPANION_SET(&dwc->dwc3->dev, ACPI_COMPANION(dev)); - ret = dwc3_pci_quirks(pci, dwc3); + ret = dwc3_pci_quirks(dwc); if (ret) goto err; - ret = platform_device_add(dwc3); + ret = platform_device_add(dwc->dwc3); if (ret) { dev_err(dev, "failed to register dwc3 device\n"); goto err; @@ -190,21 +206,23 @@ static int dwc3_pci_probe(struct pci_dev *pci, device_init_wakeup(dev, true); device_set_run_wake(dev, true); - pci_set_drvdata(pci, dwc3); + pci_set_drvdata(pci, dwc); pm_runtime_put(dev); return 0; err: - platform_device_put(dwc3); + platform_device_put(dwc->dwc3); return ret; } static void dwc3_pci_remove(struct pci_dev *pci) { + struct dwc3_pci *dwc = pci_get_drvdata(pci); + device_init_wakeup(&pci->dev, false); pm_runtime_get(&pci->dev); acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev)); - platform_device_unregister(pci_get_drvdata(pci)); + platform_device_unregister(dwc->dwc3); } static const struct pci_device_id dwc3_pci_id_table[] = { @@ -245,7 +263,8 @@ static int dwc3_pci_runtime_suspend(struct device *dev) static int dwc3_pci_runtime_resume(struct device *dev) { - struct platform_device *dwc3 = dev_get_drvdata(dev); + struct dwc3_pci *dwc = dev_get_drvdata(dev); + struct platform_device *dwc3 = dwc->dwc3; return pm_runtime_get(&dwc3->dev); } -- cgit v1.2.3 From 9cecca75b5a0da1bb70465ed3863db5cbf00850b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 24 Oct 2016 10:40:18 +0300 Subject: usb: dwc3: pci: call _DSM for suspend/resume Intel's BXT devices need to execute a _DSM method during {runtime_,}{suspend,resume} in order to get a chunk of dwc3 to power gate and save some extra power. Let's do that now. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Kconfig | 2 +- drivers/usb/dwc3/dwc3-pci.c | 73 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index a45b4f1ba689..c5aa235863e8 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -70,7 +70,7 @@ config USB_DWC3_EXYNOS config USB_DWC3_PCI tristate "PCIe-based Platforms" - depends on PCI + depends on PCI && ACPI default USB_DWC3 help If you're using the DesignWare Core IP with a PCIe, please say diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 0f54b8166e54..8c39ec6522fd 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -39,14 +39,25 @@ #define PCI_DEVICE_ID_INTEL_APL 0x5aaa #define PCI_DEVICE_ID_INTEL_KBP 0xa2b0 +#define PCI_INTEL_BXT_DSM_UUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511" +#define PCI_INTEL_BXT_FUNC_PMU_PWR 4 +#define PCI_INTEL_BXT_STATE_D0 0 +#define PCI_INTEL_BXT_STATE_D3 3 + /** * struct dwc3_pci - Driver private structure * @dwc3: child dwc3 platform_device * @pci: our link to PCI bus + * @uuid: _DSM UUID + * @has_dsm_for_pm: true for devices which need to run _DSM on runtime PM */ struct dwc3_pci { struct platform_device *dwc3; struct pci_dev *pci; + + u8 uuid[16]; + + unsigned int has_dsm_for_pm:1; }; static const struct acpi_gpio_params reset_gpios = { 0, 0, false }; @@ -102,6 +113,12 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) if (ret < 0) return ret; + if (pdev->device == PCI_DEVICE_ID_INTEL_BXT || + pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) { + acpi_str_to_uuid(PCI_INTEL_BXT_DSM_UUID, dwc->uuid); + dwc->has_dsm_for_pm = true; + } + if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) { struct gpio_desc *gpio; @@ -149,6 +166,30 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) return 0; } +static int dwc3_pci_dsm(struct dwc3_pci *dwc, int param) +{ + union acpi_object *obj; + union acpi_object tmp; + union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); + + if (!dwc->has_dsm_for_pm) + return 0; + + tmp.type = ACPI_TYPE_INTEGER; + tmp.integer.value = param; + + obj = acpi_evaluate_dsm(ACPI_HANDLE(&dwc->pci->dev), dwc->uuid, + 1, PCI_INTEL_BXT_FUNC_PMU_PWR, &argv4); + if (!obj) { + dev_err(&dwc->pci->dev, "failed to evaluate _DSM\n"); + return -EIO; + } + + ACPI_FREE(obj); + + return 0; +} + static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { @@ -255,8 +296,10 @@ MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); #ifdef CONFIG_PM static int dwc3_pci_runtime_suspend(struct device *dev) { + struct dwc3_pci *dwc = dev_get_drvdata(dev); + if (device_run_wake(dev)) - return 0; + return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3); return -EBUSY; } @@ -265,28 +308,34 @@ static int dwc3_pci_runtime_resume(struct device *dev) { struct dwc3_pci *dwc = dev_get_drvdata(dev); struct platform_device *dwc3 = dwc->dwc3; + int ret; + + ret = dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0); + if (ret) + return ret; return pm_runtime_get(&dwc3->dev); } #endif /* CONFIG_PM */ #ifdef CONFIG_PM_SLEEP -static int dwc3_pci_pm_dummy(struct device *dev) +static int dwc3_pci_suspend(struct device *dev) { - /* - * There's nothing to do here. No, seriously. Everything is either taken - * care either by PCI subsystem or dwc3/core.c, so we have nothing - * missing here. - * - * So you'd think we didn't need this at all, but PCI subsystem will - * bail out if we don't have a valid callback :-s - */ - return 0; + struct dwc3_pci *dwc = dev_get_drvdata(dev); + + return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3); +} + +static int dwc3_pci_resume(struct device *dev) +{ + struct dwc3_pci *dwc = dev_get_drvdata(dev); + + return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0); } #endif /* CONFIG_PM_SLEEP */ static struct dev_pm_ops dwc3_pci_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_pm_dummy, dwc3_pci_pm_dummy) + SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume) SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_runtime_resume, NULL) }; -- cgit v1.2.3 From dfc5148fb3f935936e47b55f270cf10fcaf08487 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Thu, 3 Nov 2016 10:39:46 +0200 Subject: drm/i915: Introduce HAS_64BIT_RELOC Move has_64bit_reloc into dev_priv->info. This will make it visible in the feature listing debug output. v2: - Keep the struct member to keep GCC fragile but happy (Chris) v3: - More detailed commit message (Chris) - Include forgotten CHV and BXT (Chris) Cc: Chris Wilson Signed-off-by: Joonas Lahtinen Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1478162386-5018-1-git-send-email-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 ++- drivers/gpu/drm/i915/i915_gem_render_state.c | 3 +-- drivers/gpu/drm/i915/i915_pci.c | 5 ++++- 4 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eaa01da892a4..ae0217d70b99 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -670,6 +670,7 @@ struct intel_csr { func(is_kabylake); \ func(is_preliminary); \ /* Keep has_* in alphabetical order */ \ + func(has_64bit_reloc); \ func(has_csr); \ func(has_ddi); \ func(has_dp_mst); \ @@ -2917,6 +2918,8 @@ struct drm_i915_cmd_table { #define HAS_CSR(dev) (INTEL_INFO(dev)->has_csr) #define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm) +#define HAS_64BIT_RELOC(dev_priv) ((dev_priv)->info.has_64bit_reloc) + /* * For now, anything with a GuC requires uCode loading, and then supports * command submission once loaded. But these are logically independent diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index c35e847bb8bc..322c580a739f 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -331,7 +331,8 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->page = -1; cache->vaddr = 0; cache->i915 = i915; - cache->use_64bit_reloc = INTEL_GEN(cache->i915) >= 8; + /* Must be a variable in the struct to allow GCC to unroll. */ + cache->use_64bit_reloc = HAS_64BIT_RELOC(i915); cache->node.allocated = false; } diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 57918f21ecc3..5af19b0bf713 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -74,7 +74,6 @@ static int render_state_setup(struct intel_render_state *so, struct drm_i915_private *i915) { const struct intel_renderstate_rodata *rodata = so->rodata; - const bool has_64bit_reloc = INTEL_GEN(i915) >= 8; struct drm_i915_gem_object *obj = so->vma->obj; unsigned int i = 0, reloc_index = 0; unsigned int needs_clflush; @@ -93,7 +92,7 @@ static int render_state_setup(struct intel_render_state *so, if (i * 4 == rodata->reloc[reloc_index]) { u64 r = s + so->vma->node.start; s = lower_32_bits(r); - if (has_64bit_reloc) { + if (HAS_64BIT_RELOC(i915)) { if (i + 1 >= rodata->batch_items || rodata->batch[i + 1] != 0) goto err; diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 31e6edd08dd0..2a419500b81a 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -288,7 +288,8 @@ static const struct intel_device_info intel_haswell_info = { #define BDW_FEATURES \ HSW_FEATURES, \ BDW_COLORS, \ - .has_logical_ring_contexts = 1 + .has_logical_ring_contexts = 1, \ + .has_64bit_reloc = 1 static const struct intel_device_info intel_broadwell_info = { BDW_FEATURES, @@ -308,6 +309,7 @@ static const struct intel_device_info intel_cherryview_info = { .has_hotplug = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .is_cherryview = 1, + .has_64bit_reloc = 1, .has_psr = 1, .has_runtime_pm = 1, .has_resource_streamer = 1, @@ -347,6 +349,7 @@ static const struct intel_device_info intel_broxton_info = { .has_hotplug = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .num_pipes = 3, + .has_64bit_reloc = 1, .has_ddi = 1, .has_fpga_dbg = 1, .has_fbc = 1, -- cgit v1.2.3 From 184e13969fe68e57f863be7b6daf202f2cc18818 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Fri, 21 Oct 2016 09:44:25 +0100 Subject: dmaengine: st_fdma: Update st_fdma to 'depends on REMOTEPROC'. During randconfig builds you can get the following warning "warning: (ST_FDMA) selects ST_SLIM_REMOTEPROC which has unmet direct dependencies (REMOTEPROC)" randconfig builds should always build without any warnings so update fdma to depend on REMOTEPROC so this can not happen. Signed-off-by: Peter Griffin Reported-by: Arnd Bergmann Tested-by: Arnd Bergmann Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 661f21791fee..6b9671066aef 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -438,6 +438,7 @@ config STE_DMA40 config ST_FDMA tristate "ST FDMA dmaengine support" depends on ARCH_STI + depends on REMOTEPROC select ST_SLIM_REMOTEPROC select DMA_ENGINE select DMA_VIRTUAL_CHANNELS -- cgit v1.2.3 From bdcfddfd7481d7756edfeb30fc28b550f6c64812 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Fri, 21 Oct 2016 12:37:56 -0400 Subject: dmaengine: qcom_hidma: make pending_tre_count atomic Getting ready for the MSI interrupts. The pending_tre_count is used in the interrupt handler to make sure all outstanding requests are serviced. The driver will allocate 11 MSI interrupts. Each MSI interrupt can be assigned to a different CPU. Then, we have a race condition for common variables as they share the same interrupt handler with a different cause bit and they can potentially be executed in parallel. Making this variable atomic so that it can be updated from multiple processor contexts. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma.h | 2 +- drivers/dma/qcom/hidma_dbg.c | 3 ++- drivers/dma/qcom/hidma_ll.c | 13 ++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h index de6176497524..181f7e0d08f6 100644 --- a/drivers/dma/qcom/hidma.h +++ b/drivers/dma/qcom/hidma.h @@ -59,7 +59,7 @@ struct hidma_lldev { void __iomem *evca; /* Event Channel address */ struct hidma_tre **pending_tre_list; /* Pointers to pending TREs */ - s32 pending_tre_count; /* Number of TREs pending */ + atomic_t pending_tre_count; /* Number of TREs pending */ void *tre_ring; /* TRE ring */ dma_addr_t tre_dma; /* TRE ring to be shared with HW */ diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c index 3d83b9962220..3bdcb8056a36 100644 --- a/drivers/dma/qcom/hidma_dbg.c +++ b/drivers/dma/qcom/hidma_dbg.c @@ -74,7 +74,8 @@ static void hidma_ll_devstats(struct seq_file *s, void *llhndl) seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma); seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size); seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off); - seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count); + seq_printf(s, "pending_tre_count=%d\n", + atomic_read(&lldev->pending_tre_count)); seq_printf(s, "evca=%p\n", lldev->evca); seq_printf(s, "evre_ring=%p\n", lldev->evre_ring); seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma); diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index e605c9096545..114409e7eec1 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -218,10 +218,9 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator, * Keep track of pending TREs that SW is expecting to receive * from HW. We got one now. Decrement our counter. */ - lldev->pending_tre_count--; - if (lldev->pending_tre_count < 0) { + if (atomic_dec_return(&lldev->pending_tre_count) < 0) { dev_warn(lldev->dev, "tre count mismatch on completion"); - lldev->pending_tre_count = 0; + atomic_set(&lldev->pending_tre_count, 0); } spin_unlock_irqrestore(&lldev->lock, flags); @@ -328,7 +327,7 @@ void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info, u32 tre_read_off; tre_iterator = lldev->tre_processed_off; - while (lldev->pending_tre_count) { + while (atomic_read(&lldev->pending_tre_count)) { if (hidma_post_completed(lldev, tre_iterator, err_info, err_code)) break; @@ -555,7 +554,7 @@ void hidma_ll_queue_request(struct hidma_lldev *lldev, u32 tre_ch) tre->err_code = 0; tre->err_info = 0; tre->queued = 1; - lldev->pending_tre_count++; + atomic_inc(&lldev->pending_tre_count); lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE) % lldev->tre_ring_size; spin_unlock_irqrestore(&lldev->lock, flags); @@ -650,7 +649,7 @@ int hidma_ll_setup(struct hidma_lldev *lldev) u32 val; u32 nr_tres = lldev->nr_tres; - lldev->pending_tre_count = 0; + atomic_set(&lldev->pending_tre_count, 0); lldev->tre_processed_off = 0; lldev->evre_processed_off = 0; lldev->tre_write_offset = 0; @@ -831,7 +830,7 @@ int hidma_ll_uninit(struct hidma_lldev *lldev) tasklet_kill(&lldev->task); memset(lldev->trepool, 0, required_bytes); lldev->trepool = NULL; - lldev->pending_tre_count = 0; + atomic_set(&lldev->pending_tre_count, 0); lldev->tre_write_offset = 0; rc = hidma_ll_reset(lldev); -- cgit v1.2.3 From 9483d9ae09452ad4cdf7f0bb0c0fae2775278c85 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Fri, 21 Oct 2016 12:37:57 -0400 Subject: dmaengine: qcom_hidma: bring out interrupt cause Bring out the interrupt cause to the top level so that MSI interrupts can be hooked at a later stage. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma_ll.c | 62 ++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index 114409e7eec1..9193f466c9e7 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -418,12 +418,24 @@ static int hidma_ll_reset(struct hidma_lldev *lldev) * requests traditionally to the destination, this concept does not apply * here for this HW. */ -irqreturn_t hidma_ll_inthandler(int chirq, void *arg) +static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause) { - struct hidma_lldev *lldev = arg; - u32 status; - u32 enable; - u32 cause; + if (cause & HIDMA_ERR_INT_MASK) { + dev_err(lldev->dev, "error 0x%x, disabling...\n", + cause); + + /* Clear out pending interrupts */ + writel(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG); + + /* No further submissions. */ + hidma_ll_disable(lldev); + + /* Driver completes the txn and intimates the client.*/ + hidma_cleanup_pending_tre(lldev, 0xFF, + HIDMA_EVRE_STATUS_ERROR); + + return; + } /* * Fine tuned for this HW... @@ -432,35 +444,28 @@ irqreturn_t hidma_ll_inthandler(int chirq, void *arg) * read and write accessors are used for performance reasons due to * interrupt delivery guarantees. Do not copy this code blindly and * expect that to work. + * + * Try to consume as many EVREs as possible. */ + hidma_handle_tre_completion(lldev); + + /* We consumed TREs or there are pending TREs or EVREs. */ + writel_relaxed(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG); +} + +irqreturn_t hidma_ll_inthandler(int chirq, void *arg) +{ + struct hidma_lldev *lldev = arg; + u32 status; + u32 enable; + u32 cause; + status = readl_relaxed(lldev->evca + HIDMA_EVCA_IRQ_STAT_REG); enable = readl_relaxed(lldev->evca + HIDMA_EVCA_IRQ_EN_REG); cause = status & enable; while (cause) { - if (cause & HIDMA_ERR_INT_MASK) { - dev_err(lldev->dev, "error 0x%x, disabling...\n", - cause); - - /* Clear out pending interrupts */ - writel(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG); - - /* No further submissions. */ - hidma_ll_disable(lldev); - - /* Driver completes the txn and intimates the client.*/ - hidma_cleanup_pending_tre(lldev, 0xFF, - HIDMA_EVRE_STATUS_ERROR); - goto out; - } - - /* - * Try to consume as many EVREs as possible. - */ - hidma_handle_tre_completion(lldev); - - /* We consumed TREs or there are pending TREs or EVREs. */ - writel_relaxed(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG); + hidma_ll_int_handler_internal(lldev, cause); /* * Another interrupt might have arrived while we are @@ -471,7 +476,6 @@ irqreturn_t hidma_ll_inthandler(int chirq, void *arg) cause = status & enable; } -out: return IRQ_HANDLED; } -- cgit v1.2.3 From 0e858f8d6f66df25545861759e174023bd7d5c1f Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Fri, 21 Oct 2016 12:37:58 -0400 Subject: dmaengine: qcom_hidma: protect common data structures When MSI interrupts are supported, error and the transfer interrupt can come from multiple processor contexts. Each error interrupt is an MSI interrupt. If the channel is disabled by the first error interrupt, the remaining error interrupts will gracefully return in the interrupt handler. If an error is observed while servicing the completions in success case, the posting of the completions will be aborted as soon as channel disabled state is observed. The error interrupt handler will take it from there and finish the remaining completions. We don't want to create multiple success and error messages to be delivered to the client in mixed order. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma_ll.c | 44 +++++++++++--------------------------------- 1 file changed, 11 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index 9193f466c9e7..7fe43afcbe32 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -198,13 +198,16 @@ static void hidma_ll_tre_complete(unsigned long arg) } } -static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator, - u8 err_info, u8 err_code) +static int hidma_post_completed(struct hidma_lldev *lldev, u8 err_info, + u8 err_code) { struct hidma_tre *tre; unsigned long flags; + u32 tre_iterator; spin_lock_irqsave(&lldev->lock, flags); + + tre_iterator = lldev->tre_processed_off; tre = lldev->pending_tre_list[tre_iterator / HIDMA_TRE_SIZE]; if (!tre) { spin_unlock_irqrestore(&lldev->lock, flags); @@ -223,6 +226,9 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator, atomic_set(&lldev->pending_tre_count, 0); } + HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE, + lldev->tre_ring_size); + lldev->tre_processed_off = tre_iterator; spin_unlock_irqrestore(&lldev->lock, flags); tre->err_info = err_info; @@ -244,13 +250,11 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator, static int hidma_handle_tre_completion(struct hidma_lldev *lldev) { u32 evre_ring_size = lldev->evre_ring_size; - u32 tre_ring_size = lldev->tre_ring_size; u32 err_info, err_code, evre_write_off; - u32 tre_iterator, evre_iterator; + u32 evre_iterator; u32 num_completed = 0; evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG); - tre_iterator = lldev->tre_processed_off; evre_iterator = lldev->evre_processed_off; if ((evre_write_off > evre_ring_size) || @@ -273,12 +277,9 @@ static int hidma_handle_tre_completion(struct hidma_lldev *lldev) err_code = (cfg >> HIDMA_EVRE_CODE_BIT_POS) & HIDMA_EVRE_CODE_MASK; - if (hidma_post_completed(lldev, tre_iterator, err_info, - err_code)) + if (hidma_post_completed(lldev, err_info, err_code)) break; - HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE, - tre_ring_size); HIDMA_INCREMENT_ITERATOR(evre_iterator, HIDMA_EVRE_SIZE, evre_ring_size); @@ -302,16 +303,10 @@ static int hidma_handle_tre_completion(struct hidma_lldev *lldev) if (num_completed) { u32 evre_read_off = (lldev->evre_processed_off + HIDMA_EVRE_SIZE * num_completed); - u32 tre_read_off = (lldev->tre_processed_off + - HIDMA_TRE_SIZE * num_completed); - evre_read_off = evre_read_off % evre_ring_size; - tre_read_off = tre_read_off % tre_ring_size; - writel(evre_read_off, lldev->evca + HIDMA_EVCA_DOORBELL_REG); /* record the last processed tre offset */ - lldev->tre_processed_off = tre_read_off; lldev->evre_processed_off = evre_read_off; } @@ -321,27 +316,10 @@ static int hidma_handle_tre_completion(struct hidma_lldev *lldev) void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info, u8 err_code) { - u32 tre_iterator; - u32 tre_ring_size = lldev->tre_ring_size; - int num_completed = 0; - u32 tre_read_off; - - tre_iterator = lldev->tre_processed_off; while (atomic_read(&lldev->pending_tre_count)) { - if (hidma_post_completed(lldev, tre_iterator, err_info, - err_code)) + if (hidma_post_completed(lldev, err_info, err_code)) break; - HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE, - tre_ring_size); - num_completed++; } - tre_read_off = (lldev->tre_processed_off + - HIDMA_TRE_SIZE * num_completed); - - tre_read_off = tre_read_off % tre_ring_size; - - /* record the last processed tre offset */ - lldev->tre_processed_off = tre_read_off; } static int hidma_ll_reset(struct hidma_lldev *lldev) -- cgit v1.2.3 From 1c0e3e82a7fb01c7398ea9533f57c0a77099428f Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Fri, 21 Oct 2016 12:37:59 -0400 Subject: dmaengine: qcom_hidma: add MSI support for interrupts The interrupts can now be delivered as platform MSI interrupts on newer platforms. The code looks for a new OF and ACPI strings in order to enable the functionality. Signed-off-by: Sinan Kaya Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma.c | 143 ++++++++++++++++++++++++++++++++++++++++++-- drivers/dma/qcom/hidma.h | 2 + drivers/dma/qcom/hidma_ll.c | 8 +++ 3 files changed, 147 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index e244e10a94b5..d5e7991ad737 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -56,6 +56,7 @@ #include #include #include +#include #include "../dmaengine.h" #include "hidma.h" @@ -70,6 +71,7 @@ #define HIDMA_ERR_INFO_SW 0xFF #define HIDMA_ERR_CODE_UNEXPECTED_TERMINATE 0x0 #define HIDMA_NR_DEFAULT_DESC 10 +#define HIDMA_MSI_INTS 11 static inline struct hidma_dev *to_hidma_dev(struct dma_device *dmadev) { @@ -553,6 +555,15 @@ static irqreturn_t hidma_chirq_handler(int chirq, void *arg) return hidma_ll_inthandler(chirq, lldev); } +static irqreturn_t hidma_chirq_handler_msi(int chirq, void *arg) +{ + struct hidma_lldev **lldevp = arg; + struct hidma_dev *dmadev = to_hidma_dev_from_lldev(lldevp); + + return hidma_ll_inthandler_msi(chirq, *lldevp, + 1 << (chirq - dmadev->msi_virqbase)); +} + static ssize_t hidma_show_values(struct device *dev, struct device_attribute *attr, char *buf) { @@ -590,6 +601,104 @@ static int hidma_create_sysfs_entry(struct hidma_dev *dev, char *name, return device_create_file(dev->ddev.dev, attrs); } +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN +static void hidma_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) +{ + struct device *dev = msi_desc_to_dev(desc); + struct hidma_dev *dmadev = dev_get_drvdata(dev); + + if (!desc->platform.msi_index) { + writel(msg->address_lo, dmadev->dev_evca + 0x118); + writel(msg->address_hi, dmadev->dev_evca + 0x11C); + writel(msg->data, dmadev->dev_evca + 0x120); + } +} +#endif + +static void hidma_free_msis(struct hidma_dev *dmadev) +{ +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN + struct device *dev = dmadev->ddev.dev; + struct msi_desc *desc; + + /* free allocated MSI interrupts above */ + for_each_msi_entry(desc, dev) + devm_free_irq(dev, desc->irq, &dmadev->lldev); + + platform_msi_domain_free_irqs(dev); +#endif +} + +static int hidma_request_msi(struct hidma_dev *dmadev, + struct platform_device *pdev) +{ +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN + int rc; + struct msi_desc *desc; + struct msi_desc *failed_desc = NULL; + + rc = platform_msi_domain_alloc_irqs(&pdev->dev, HIDMA_MSI_INTS, + hidma_write_msi_msg); + if (rc) + return rc; + + for_each_msi_entry(desc, &pdev->dev) { + if (!desc->platform.msi_index) + dmadev->msi_virqbase = desc->irq; + + rc = devm_request_irq(&pdev->dev, desc->irq, + hidma_chirq_handler_msi, + 0, "qcom-hidma-msi", + &dmadev->lldev); + if (rc) { + failed_desc = desc; + break; + } + } + + if (rc) { + /* free allocated MSI interrupts above */ + for_each_msi_entry(desc, &pdev->dev) { + if (desc == failed_desc) + break; + devm_free_irq(&pdev->dev, desc->irq, + &dmadev->lldev); + } + } else { + /* Add callback to free MSIs on teardown */ + hidma_ll_setup_irq(dmadev->lldev, true); + + } + if (rc) + dev_warn(&pdev->dev, + "failed to request MSI irq, falling back to wired IRQ\n"); + return rc; +#else + return -EINVAL; +#endif +} + +static bool hidma_msi_capable(struct device *dev) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + const char *of_compat; + int ret = -EINVAL; + + if (!adev || acpi_disabled) { + ret = device_property_read_string(dev, "compatible", + &of_compat); + if (ret) + return false; + + ret = strcmp(of_compat, "qcom,hidma-1.1"); + } else { +#ifdef CONFIG_ACPI + ret = strcmp(acpi_device_hid(adev), "QCOM8062"); +#endif + } + return ret == 0; +} + static int hidma_probe(struct platform_device *pdev) { struct hidma_dev *dmadev; @@ -599,6 +708,7 @@ static int hidma_probe(struct platform_device *pdev) void __iomem *evca; void __iomem *trca; int rc; + bool msi; pm_runtime_set_autosuspend_delay(&pdev->dev, HIDMA_AUTOSUSPEND_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); @@ -660,6 +770,12 @@ static int hidma_probe(struct platform_device *pdev) dmadev->ddev.device_terminate_all = hidma_terminate_all; dmadev->ddev.copy_align = 8; + /* + * Determine the MSI capability of the platform. Old HW doesn't + * support MSI. + */ + msi = hidma_msi_capable(&pdev->dev); + device_property_read_u32(&pdev->dev, "desc-count", &dmadev->nr_descriptors); @@ -688,10 +804,17 @@ static int hidma_probe(struct platform_device *pdev) goto dmafree; } - rc = devm_request_irq(&pdev->dev, chirq, hidma_chirq_handler, 0, - "qcom-hidma", dmadev->lldev); - if (rc) - goto uninit; + platform_set_drvdata(pdev, dmadev); + if (msi) + rc = hidma_request_msi(dmadev, pdev); + + if (!msi || rc) { + hidma_ll_setup_irq(dmadev->lldev, false); + rc = devm_request_irq(&pdev->dev, chirq, hidma_chirq_handler, + 0, "qcom-hidma", dmadev->lldev); + if (rc) + goto uninit; + } INIT_LIST_HEAD(&dmadev->ddev.channels); rc = hidma_chan_init(dmadev, 0); @@ -707,12 +830,14 @@ static int hidma_probe(struct platform_device *pdev) hidma_debug_init(dmadev); hidma_create_sysfs_entry(dmadev, "chid", S_IRUGO); dev_info(&pdev->dev, "HI-DMA engine driver registration complete\n"); - platform_set_drvdata(pdev, dmadev); pm_runtime_mark_last_busy(dmadev->ddev.dev); pm_runtime_put_autosuspend(dmadev->ddev.dev); return 0; uninit: + if (msi) + hidma_free_msis(dmadev); + hidma_debug_uninit(dmadev); hidma_ll_uninit(dmadev->lldev); dmafree: @@ -730,7 +855,11 @@ static int hidma_remove(struct platform_device *pdev) pm_runtime_get_sync(dmadev->ddev.dev); dma_async_device_unregister(&dmadev->ddev); - devm_free_irq(dmadev->ddev.dev, dmadev->irq, dmadev->lldev); + if (!dmadev->lldev->msi_support) + devm_free_irq(dmadev->ddev.dev, dmadev->irq, dmadev->lldev); + else + hidma_free_msis(dmadev); + tasklet_kill(&dmadev->task); hidma_debug_uninit(dmadev); hidma_ll_uninit(dmadev->lldev); @@ -746,12 +875,14 @@ static int hidma_remove(struct platform_device *pdev) #if IS_ENABLED(CONFIG_ACPI) static const struct acpi_device_id hidma_acpi_ids[] = { {"QCOM8061"}, + {"QCOM8062"}, {}, }; #endif static const struct of_device_id hidma_match[] = { {.compatible = "qcom,hidma-1.0",}, + {.compatible = "qcom,hidma-1.1",}, {}, }; MODULE_DEVICE_TABLE(of, hidma_match); diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h index 181f7e0d08f6..05f8ba49e6c6 100644 --- a/drivers/dma/qcom/hidma.h +++ b/drivers/dma/qcom/hidma.h @@ -115,6 +115,7 @@ struct hidma_dev { int irq; int chidx; u32 nr_descriptors; + int msi_virqbase; struct hidma_lldev *lldev; void __iomem *dev_trca; @@ -153,6 +154,7 @@ struct hidma_lldev *hidma_ll_init(struct device *dev, u32 max_channels, u8 chidx); int hidma_ll_uninit(struct hidma_lldev *llhndl); irqreturn_t hidma_ll_inthandler(int irq, void *arg); +irqreturn_t hidma_ll_inthandler_msi(int irq, void *arg, int cause); void hidma_cleanup_pending_tre(struct hidma_lldev *llhndl, u8 err_info, u8 err_code); int hidma_debug_init(struct hidma_dev *dmadev); diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index 7fe43afcbe32..6645bdf0d151 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -457,6 +457,14 @@ irqreturn_t hidma_ll_inthandler(int chirq, void *arg) return IRQ_HANDLED; } +irqreturn_t hidma_ll_inthandler_msi(int chirq, void *arg, int cause) +{ + struct hidma_lldev *lldev = arg; + + hidma_ll_int_handler_internal(lldev, cause); + return IRQ_HANDLED; +} + int hidma_ll_enable(struct hidma_lldev *lldev) { u32 val; -- cgit v1.2.3 From a933568eb61d6c0b12af4264ae1ba316447a2189 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 2 Nov 2016 15:14:59 +0000 Subject: drm/i915: Tidy slab cache allocations We can use the preferred KMEM_CACHE helper for brevity. Also simplifiy error unwind by only setting the ENOMEM error code once. v2: Add forgotten changes. (Joonas Lahtinen) Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen (v1) Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1478099699-28652-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_gem.c | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5839bebba64a..1f995ced524e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4714,39 +4714,22 @@ int i915_gem_load_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int err; + int err = -ENOMEM; - dev_priv->objects = - kmem_cache_create("i915_gem_object", - sizeof(struct drm_i915_gem_object), 0, - SLAB_HWCACHE_ALIGN, - NULL); - if (!dev_priv->objects) { - err = -ENOMEM; + dev_priv->objects = KMEM_CACHE(drm_i915_gem_object, SLAB_HWCACHE_ALIGN); + if (!dev_priv->objects) goto err_out; - } - dev_priv->vmas = - kmem_cache_create("i915_gem_vma", - sizeof(struct i915_vma), 0, - SLAB_HWCACHE_ALIGN, - NULL); - if (!dev_priv->vmas) { - err = -ENOMEM; + dev_priv->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN); + if (!dev_priv->vmas) goto err_objects; - } - dev_priv->requests = - kmem_cache_create("i915_gem_request", - sizeof(struct drm_i915_gem_request), 0, - SLAB_HWCACHE_ALIGN | - SLAB_RECLAIM_ACCOUNT | - SLAB_DESTROY_BY_RCU, - NULL); - if (!dev_priv->requests) { - err = -ENOMEM; + dev_priv->requests = KMEM_CACHE(drm_i915_gem_request, + SLAB_HWCACHE_ALIGN | + SLAB_RECLAIM_ACCOUNT | + SLAB_DESTROY_BY_RCU); + if (!dev_priv->requests) goto err_vmas; - } mutex_lock(&dev_priv->drm.struct_mutex); INIT_LIST_HEAD(&dev_priv->gt.timelines); -- cgit v1.2.3 From 5ed7414062e7cc63759529b9d82a1e73e86fe6c0 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 2 Nov 2016 15:02:36 +0100 Subject: net: stmmac: Add OXNAS Glue Driver Add Synopsys Designware MAC Glue layer for the Oxford Semiconductor OX820. Acked-by: Joachim Eastwood Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++ drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 217 ++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 3818c5e06eba..6e9fcc345798 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -69,6 +69,17 @@ config DWMAC_MESON the stmmac device driver. This driver is used for Meson6, Meson8, Meson8b and GXBB SoCs. +config DWMAC_OXNAS + tristate "Oxford Semiconductor OXNAS dwmac support" + default ARCH_OXNAS + depends on OF && COMMON_CLK && (ARCH_OXNAS || COMPILE_TEST) + select MFD_SYSCON + help + Support for Ethernet controller on Oxford Semiconductor OXNAS SoCs. + + This selects the Oxford Semiconductor OXNASSoC glue layer support for + the stmmac device driver. This driver is used for OX820. + config DWMAC_ROCKCHIP tristate "Rockchip dwmac support" default ARCH_ROCKCHIP diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 5d6ece5919b3..8f83a86ba13c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o +obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c new file mode 100644 index 000000000000..c35597586121 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c @@ -0,0 +1,217 @@ +/* + * Oxford Semiconductor OXNAS DWMAC glue layer + * + * Copyright (C) 2016 Neil Armstrong + * Copyright (C) 2014 Daniel Golle + * Copyright (C) 2013 Ma Haijun + * Copyright (C) 2012 John Crispin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stmmac_platform.h" + +/* System Control regmap offsets */ +#define OXNAS_DWMAC_CTRL_REGOFFSET 0x78 +#define OXNAS_DWMAC_DELAY_REGOFFSET 0x100 + +/* Control Register */ +#define DWMAC_CKEN_RX_IN 14 +#define DWMAC_CKEN_RXN_OUT 13 +#define DWMAC_CKEN_RX_OUT 12 +#define DWMAC_CKEN_TX_IN 10 +#define DWMAC_CKEN_TXN_OUT 9 +#define DWMAC_CKEN_TX_OUT 8 +#define DWMAC_RX_SOURCE 7 +#define DWMAC_TX_SOURCE 6 +#define DWMAC_LOW_TX_SOURCE 4 +#define DWMAC_AUTO_TX_SOURCE 3 +#define DWMAC_RGMII 2 +#define DWMAC_SIMPLE_MUX 1 +#define DWMAC_CKEN_GTX 0 + +/* Delay register */ +#define DWMAC_TX_VARDELAY_SHIFT 0 +#define DWMAC_TXN_VARDELAY_SHIFT 8 +#define DWMAC_RX_VARDELAY_SHIFT 16 +#define DWMAC_RXN_VARDELAY_SHIFT 24 +#define DWMAC_TX_VARDELAY(d) ((d) << DWMAC_TX_VARDELAY_SHIFT) +#define DWMAC_TXN_VARDELAY(d) ((d) << DWMAC_TXN_VARDELAY_SHIFT) +#define DWMAC_RX_VARDELAY(d) ((d) << DWMAC_RX_VARDELAY_SHIFT) +#define DWMAC_RXN_VARDELAY(d) ((d) << DWMAC_RXN_VARDELAY_SHIFT) + +struct oxnas_dwmac { + struct device *dev; + struct clk *clk; + struct regmap *regmap; +}; + +static int oxnas_dwmac_init(struct oxnas_dwmac *dwmac) +{ + unsigned int value; + int ret; + + /* Reset HW here before changing the glue configuration */ + ret = device_reset(dwmac->dev); + if (ret) + return ret; + + ret = clk_prepare_enable(dwmac->clk); + if (ret) + return ret; + + ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value); + if (ret < 0) { + clk_disable_unprepare(dwmac->clk); + return ret; + } + + /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ + value |= BIT(DWMAC_CKEN_GTX) | + /* Use simple mux for 25/125 Mhz clock switching */ + BIT(DWMAC_SIMPLE_MUX) | + /* set auto switch tx clock source */ + BIT(DWMAC_AUTO_TX_SOURCE) | + /* enable tx & rx vardelay */ + BIT(DWMAC_CKEN_TX_OUT) | + BIT(DWMAC_CKEN_TXN_OUT) | + BIT(DWMAC_CKEN_TX_IN) | + BIT(DWMAC_CKEN_RX_OUT) | + BIT(DWMAC_CKEN_RXN_OUT) | + BIT(DWMAC_CKEN_RX_IN); + regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value); + + /* set tx & rx vardelay */ + value = DWMAC_TX_VARDELAY(4) | + DWMAC_TXN_VARDELAY(2) | + DWMAC_RX_VARDELAY(10) | + DWMAC_RXN_VARDELAY(8); + regmap_write(dwmac->regmap, OXNAS_DWMAC_DELAY_REGOFFSET, value); + + return 0; +} + +static int oxnas_dwmac_probe(struct platform_device *pdev) +{ + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + struct device_node *sysctrl; + struct oxnas_dwmac *dwmac; + int ret; + + sysctrl = of_parse_phandle(pdev->dev.of_node, "oxsemi,sys-ctrl", 0); + if (!sysctrl) { + dev_err(&pdev->dev, "failed to get sys-ctrl node\n"); + return -EINVAL; + } + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); + if (!dwmac) + return -ENOMEM; + + dwmac->dev = &pdev->dev; + plat_dat->bsp_priv = dwmac; + + dwmac->regmap = syscon_node_to_regmap(sysctrl); + if (IS_ERR(dwmac->regmap)) { + dev_err(&pdev->dev, "failed to have sysctrl regmap\n"); + return PTR_ERR(dwmac->regmap); + } + + dwmac->clk = devm_clk_get(&pdev->dev, "gmac"); + if (IS_ERR(dwmac->clk)) + return PTR_ERR(dwmac->clk); + + ret = oxnas_dwmac_init(dwmac); + if (ret) + return ret; + + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + clk_disable_unprepare(dwmac->clk); + + return ret; +} + +static int oxnas_dwmac_remove(struct platform_device *pdev) +{ + struct oxnas_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev); + int ret = stmmac_dvr_remove(&pdev->dev); + + clk_disable_unprepare(dwmac->clk); + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int oxnas_dwmac_suspend(struct device *dev) +{ + struct oxnas_dwmac *dwmac = get_stmmac_bsp_priv(dev); + int ret; + + ret = stmmac_suspend(dev); + clk_disable_unprepare(dwmac->clk); + + return ret; +} + +static int oxnas_dwmac_resume(struct device *dev) +{ + struct oxnas_dwmac *dwmac = get_stmmac_bsp_priv(dev); + int ret; + + ret = oxnas_dwmac_init(dwmac); + if (ret) + return ret; + + ret = stmmac_resume(dev); + + return ret; +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(oxnas_dwmac_pm_ops, + oxnas_dwmac_suspend, oxnas_dwmac_resume); + +static const struct of_device_id oxnas_dwmac_match[] = { + { .compatible = "oxsemi,ox820-dwmac" }, + { } +}; +MODULE_DEVICE_TABLE(of, oxnas_dwmac_match); + +static struct platform_driver oxnas_dwmac_driver = { + .probe = oxnas_dwmac_probe, + .remove = oxnas_dwmac_remove, + .driver = { + .name = "oxnas-dwmac", + .pm = &oxnas_dwmac_pm_ops, + .of_match_table = oxnas_dwmac_match, + }, +}; +module_platform_driver(oxnas_dwmac_driver); + +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION("Oxford Semiconductor OXNAS DWMAC glue layer"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 72aa0d899a3ea7e14436ac0b869cf3333277b92e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 2 Nov 2016 17:50:47 +0000 Subject: drm/i915/guc: Cache the client mapping Use i915_gem_object_pin_map() for the guc client's lifetime to replace the peristent kmap + frequent kmap_atomic with a permanent vmapping. This avoids taking the obj->mm.lock mutex whilst inside irq context later. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98571 Fixes: 96d776345277 ("drm/i915: Use a radixtree for random access..."); Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20161102175051.29163-9-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 38 +++++++++++++++--------------- drivers/gpu/drm/i915/intel_guc.h | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 857ef914cae7..666dab7a675a 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -220,7 +220,7 @@ static int guc_update_doorbell_id(struct intel_guc *guc, struct guc_context_desc desc; size_t len; - doorbell = client->client_base + client->doorbell_offset; + doorbell = client->vaddr + client->doorbell_offset; if (client->doorbell_id != GUC_INVALID_DOORBELL_ID && test_bit(client->doorbell_id, doorbell_bitmap)) { @@ -326,7 +326,7 @@ static void guc_proc_desc_init(struct intel_guc *guc, { struct guc_process_desc *desc; - desc = client->client_base + client->proc_desc_offset; + desc = client->vaddr + client->proc_desc_offset; memset(desc, 0, sizeof(*desc)); @@ -413,8 +413,8 @@ static void guc_ctx_desc_init(struct intel_guc *guc, gfx_addr = i915_ggtt_offset(client->vma); desc.db_trigger_phy = sg_dma_address(client->vma->pages->sgl) + client->doorbell_offset; - desc.db_trigger_cpu = (uintptr_t)client->client_base + - client->doorbell_offset; + desc.db_trigger_cpu = + (uintptr_t)client->vaddr + client->doorbell_offset; desc.db_trigger_uk = gfx_addr + client->doorbell_offset; desc.process_desc = gfx_addr + client->proc_desc_offset; desc.wq_addr = gfx_addr + client->wq_offset; @@ -465,7 +465,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request) { const size_t wqi_size = sizeof(struct guc_wq_item); struct i915_guc_client *gc = request->i915->guc.execbuf_client; - struct guc_process_desc *desc = gc->client_base + gc->proc_desc_offset; + struct guc_process_desc *desc = gc->vaddr + gc->proc_desc_offset; u32 freespace; int ret; @@ -506,10 +506,9 @@ static void guc_wq_item_append(struct i915_guc_client *gc, struct intel_engine_cs *engine = rq->engine; struct guc_process_desc *desc; struct guc_wq_item *wqi; - void *base; - u32 freespace, tail, wq_off, wq_page; + u32 freespace, tail, wq_off; - desc = gc->client_base + gc->proc_desc_offset; + desc = gc->vaddr + gc->proc_desc_offset; /* Free space is guaranteed, see i915_guc_wq_reserve() above */ freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size); @@ -539,10 +538,7 @@ static void guc_wq_item_append(struct i915_guc_client *gc, gc->wq_rsvd -= wqi_size; /* WQ starts from the page after doorbell / process_desc */ - wq_page = (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT; - wq_off &= PAGE_SIZE - 1; - base = kmap_atomic(i915_gem_object_get_page(gc->vma->obj, wq_page)); - wqi = (struct guc_wq_item *)((char *)base + wq_off); + wqi = gc->vaddr + wq_off + GUC_DB_SIZE; /* Now fill in the 4-word work queue item */ wqi->header = WQ_TYPE_INORDER | @@ -555,8 +551,6 @@ static void guc_wq_item_append(struct i915_guc_client *gc, wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT; wqi->fence_id = rq->global_seqno; - - kunmap_atomic(base); } static int guc_ring_doorbell(struct i915_guc_client *gc) @@ -566,7 +560,7 @@ static int guc_ring_doorbell(struct i915_guc_client *gc) union guc_doorbell_qw *db; int attempt = 2, ret = -EAGAIN; - desc = gc->client_base + gc->proc_desc_offset; + desc = gc->vaddr + gc->proc_desc_offset; /* Update the tail so it is visible to GuC */ desc->tail = gc->wq_tail; @@ -582,7 +576,7 @@ static int guc_ring_doorbell(struct i915_guc_client *gc) db_exc.cookie = 1; /* pointer of current doorbell cacheline */ - db = gc->client_base + gc->doorbell_offset; + db = gc->vaddr + gc->doorbell_offset; while (attempt--) { /* lets ring the doorbell */ @@ -724,14 +718,14 @@ guc_client_free(struct drm_i915_private *dev_priv, * Be sure to drop any locks */ - if (client->client_base) { + if (client->vaddr) { /* * If we got as far as setting up a doorbell, make sure we * shut it down before unmapping & deallocating the memory. */ guc_disable_doorbell(guc, client); - kunmap(kmap_to_page(client->client_base)); + i915_gem_object_unpin_map(client->vma->obj); } i915_vma_unpin_and_release(&client->vma); @@ -820,6 +814,7 @@ guc_client_alloc(struct drm_i915_private *dev_priv, struct i915_guc_client *client; struct intel_guc *guc = &dev_priv->guc; struct i915_vma *vma; + void *vaddr; uint16_t db_id; client = kzalloc(sizeof(*client), GFP_KERNEL); @@ -846,7 +841,12 @@ guc_client_alloc(struct drm_i915_private *dev_priv, /* We'll keep just the first (doorbell/proc) page permanently kmap'd. */ client->vma = vma; - client->client_base = kmap(i915_vma_first_page(vma)); + + vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); + if (IS_ERR(vaddr)) + goto err; + + client->vaddr = vaddr; spin_lock_init(&client->wq_lock); client->wq_offset = GUC_DB_SIZE; diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 49ced0bad0f5..0053258e03d3 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -64,7 +64,7 @@ struct drm_i915_gem_request; */ struct i915_guc_client { struct i915_vma *vma; - void *client_base; /* first page (only) of above */ + void *vaddr; struct i915_gem_context *owner; struct intel_guc *guc; -- cgit v1.2.3 From 5e5f89e70b29153cb28011f0cc47984bfcc3bef4 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Thu, 3 Nov 2016 09:41:55 +0100 Subject: mlxsw: pci: Fix the FW ready mask length The system-status register is actually 16-bit wide and not 8 bit-wide. Fixes: 233fa44bd67ae ("mlxsw: pci: Implement reset done check") Signed-off-by: Elad Raz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci_hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h index 708736f387e2..d147ddd97997 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h @@ -60,7 +60,7 @@ #define MLXSW_PCI_SW_RESET_RST_BIT BIT(0) #define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 5000 #define MLXSW_PCI_FW_READY 0xA1844 -#define MLXSW_PCI_FW_READY_MASK 0xFF +#define MLXSW_PCI_FW_READY_MASK 0xFFFF #define MLXSW_PCI_FW_READY_MAGIC 0x5E #define MLXSW_PCI_DOORBELL_SDQ_OFFSET 0x000 -- cgit v1.2.3 From b2554000f5b5d2a3a368d09c6debf7da64901fcf Mon Sep 17 00:00:00 2001 From: Marcel Hasler Date: Thu, 3 Nov 2016 19:47:26 +0100 Subject: HID: usbhid: Add quirks for Mayflash/Dragonrise GameCube and PS3 adapters All known gamepad adapters by Mayflash (identified as Dragonrise) need HID_QUIRK_MULTI_INPUT to split them up into four input devices. Without this quirk those adapters are falsely recognized as tablets. Fixes bug 115841 (https://bugzilla.kernel.org/show_bug.cgi?id=115841). Signed-off-by: Marcel Hasler Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 6 ++++-- drivers/hid/usbhid/hid-quirks.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 6cfb5cacc253..642e64861654 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -314,8 +314,10 @@ #define USB_VENDOR_ID_DMI 0x0c0b #define USB_DEVICE_ID_DMI_ENC 0x5fab -#define USB_VENDOR_ID_DRAGONRISE 0x0079 -#define USB_DEVICE_ID_DRAGONRISE_WIIU 0x1800 +#define USB_VENDOR_ID_DRAGONRISE 0x0079 +#define USB_DEVICE_ID_DRAGONRISE_WIIU 0x1800 +#define USB_DEVICE_ID_DRAGONRISE_PS3 0x1801 +#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE 0x1843 #define USB_VENDOR_ID_DWAV 0x0eef #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 354d49ea36dd..05f6f61f0213 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -81,6 +81,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, -- cgit v1.2.3 From f8690450f3d0d415f42c94f7e69258d8ba54ff29 Mon Sep 17 00:00:00 2001 From: Marcel Hasler Date: Thu, 3 Nov 2016 19:47:42 +0100 Subject: HID: Add new force feedback driver for Mayflash game controller adapters Add a new module named hid-mf that implements force feedback for game controller adapters manufactured by Mayflash. Currently only the PS3 adapter is supported, other adapters still need to be tested. Signed-off-by: Marcel Hasler Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 8 +++ drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 3 + drivers/hid/hid-mf.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 drivers/hid/hid-mf.c (limited to 'drivers') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index cd4599c0523b..1530d28ecc61 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -512,6 +512,14 @@ config HID_MAGICMOUSE Say Y here if you want support for the multi-touch features of the Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad. +config HID_MAYFLASH + tristate "Mayflash game controller adapter force feedback" + depends on HID + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you have HJZ Mayflash PS3 game controller adapters + and want to enable force feedback support. + config HID_MICROSOFT tristate "Microsoft non-fully HID-compliant devices" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 86b2b5785fd2..c0453f196c06 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o +obj-$(CONFIG_HID_MAYFLASH) += hid-mf.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2b89c701076f..39694a514726 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1883,6 +1883,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, +#if IS_ENABLED(CONFIG_HID_MAYFLASH) + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) }, +#endif { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, diff --git a/drivers/hid/hid-mf.c b/drivers/hid/hid-mf.c new file mode 100644 index 000000000000..d9090765a6e5 --- /dev/null +++ b/drivers/hid/hid-mf.c @@ -0,0 +1,166 @@ +/* + * Force feedback support for Mayflash game controller adapters. + * + * These devices are manufactured by Mayflash but identify themselves + * using the vendor ID of DragonRise Inc. + * + * Tested with: + * 0079:1801 "DragonRise Inc. Mayflash PS3 Game Controller Adapter" + * + * The following adapters probably work too, but need to be tested: + * 0079:1800 "DragonRise Inc. Mayflash WIIU Game Controller Adapter" + * 0079:1843 "DragonRise Inc. Mayflash GameCube Game Controller Adapter" + * + * Copyright (c) 2016 Marcel Hasler + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "hid-ids.h" + +struct mf_device { + struct hid_report *report; +}; + +static int mf_play(struct input_dev *dev, void *data, struct ff_effect *effect) +{ + struct hid_device *hid = input_get_drvdata(dev); + struct mf_device *mf = data; + int strong, weak; + + strong = effect->u.rumble.strong_magnitude; + weak = effect->u.rumble.weak_magnitude; + + dbg_hid("Called with 0x%04x 0x%04x.\n", strong, weak); + + strong = strong * 0xff / 0xffff; + weak = weak * 0xff / 0xffff; + + dbg_hid("Running with 0x%02x 0x%02x.\n", strong, weak); + + mf->report->field[0]->value[0] = weak; + mf->report->field[0]->value[1] = strong; + hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT); + + return 0; +} + +static int mf_init(struct hid_device *hid) +{ + struct mf_device *mf; + + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; + + struct list_head *report_ptr; + struct hid_report *report; + + struct list_head *input_ptr = &hid->inputs; + struct hid_input *input; + + struct input_dev *dev; + + int error; + + /* Setup each of the four inputs */ + list_for_each(report_ptr, report_list) { + report = list_entry(report_ptr, struct hid_report, list); + + if (report->maxfield < 1 || report->field[0]->report_count < 2) { + hid_err(hid, "Invalid report, this should never happen!\n"); + return -ENODEV; + } + + if (list_is_last(input_ptr, &hid->inputs)) { + hid_err(hid, "Missing input, this should never happen!\n"); + return -ENODEV; + } + + input_ptr = input_ptr->next; + input = list_entry(input_ptr, struct hid_input, list); + + mf = kzalloc(sizeof(struct mf_device), GFP_KERNEL); + if (!mf) + return -ENOMEM; + + dev = input->input; + set_bit(FF_RUMBLE, dev->ffbit); + + error = input_ff_create_memless(dev, mf, mf_play); + if (error) { + kfree(mf); + return error; + } + + mf->report = report; + mf->report->field[0]->value[0] = 0x00; + mf->report->field[0]->value[1] = 0x00; + hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT); + } + + hid_info(hid, "Force feedback for HJZ Mayflash game controller " + "adapters by Marcel Hasler \n"); + + return 0; +} + +static int mf_probe(struct hid_device *hid, const struct hid_device_id *id) +{ + int error; + + dev_dbg(&hid->dev, "Mayflash HID hardware probe...\n"); + + /* Split device into four inputs */ + hid->quirks |= HID_QUIRK_MULTI_INPUT; + + error = hid_parse(hid); + if (error) { + hid_err(hid, "HID parse failed.\n"); + return error; + } + + error = hid_hw_start(hid, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); + if (error) { + hid_err(hid, "HID hw start failed\n"); + return error; + } + + error = mf_init(hid); + if (error) { + hid_err(hid, "Force feedback init failed.\n"); + hid_hw_stop(hid); + return error; + } + + return 0; +} + +static const struct hid_device_id mf_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), }, + { } +}; +MODULE_DEVICE_TABLE(hid, mf_devices); + +static struct hid_driver mf_driver = { + .name = "hid_mf", + .id_table = mf_devices, + .probe = mf_probe, +}; +module_hid_driver(mf_driver); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From a44342acde304425fa70fd4f06c0e662a79ba5aa Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 3 Nov 2016 20:08:52 +0000 Subject: drm/i915: Fix test on inputs for vma_compare() When supplying a view to vma_compare() it is required that the supplied i915_address_space is the global GTT. I tested the VMA instead (which is the current position in the rbtree and maybe from any address space). Reported-by: Matthew Auld Tested-by: Matthew Auld Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98579 Fixes: db6c2b4151f2 ("drm/i915: Store the vma in an rbtree...") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Matthew Auld Link: http://patchwork.freedesktop.org/patch/msgid/20161103200852.23431-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0c1f5b4750b6..cad6de65947d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3425,7 +3425,7 @@ static inline long vma_compare(struct i915_vma *vma, struct i915_address_space *vm, const struct i915_ggtt_view *view) { - GEM_BUG_ON(view && !i915_vma_is_ggtt(vma)); + GEM_BUG_ON(view && !i915_is_ggtt(vm)); if (vma->vm != vm) return vma->vm - vm; -- cgit v1.2.3 From 457e67a728696c4f8e6423c64e93def50530db9a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Oct 2016 16:48:12 -0700 Subject: drm/vc4: Fix termination of the initial scan for branch targets. The loop is scanning until the original max_ip (size of the BO), but we want to not examine any code after the PROG_END's delay slots. There was a block trying to do that, except that we had some early continue statements if the signal wasn't a PROG_END or a BRANCH. The failure mode would be that a valid shader is rejected because some undefined memory after the PROG_END slots is parsed as a branch and the rest of its setup is illegal. I haven't seen this in the wild, but valgrind was complaining when about this up in the userland simulator mode. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_validate_shaders.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c index 2543cf5b8b51..917321ce832f 100644 --- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c +++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c @@ -608,9 +608,7 @@ static bool vc4_validate_branches(struct vc4_shader_validation_state *validation_state) { uint32_t max_branch_target = 0; - bool found_shader_end = false; int ip; - int shader_end_ip = 0; int last_branch = -2; for (ip = 0; ip < validation_state->max_ip; ip++) { @@ -621,8 +619,13 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state) uint32_t branch_target_ip; if (sig == QPU_SIG_PROG_END) { - shader_end_ip = ip; - found_shader_end = true; + /* There are two delay slots after program end is + * signaled that are still executed, then we're + * finished. validation_state->max_ip is the + * instruction after the last valid instruction in the + * program. + */ + validation_state->max_ip = ip + 3; continue; } @@ -676,15 +679,9 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state) } set_bit(after_delay_ip, validation_state->branch_targets); max_branch_target = max(max_branch_target, after_delay_ip); - - /* There are two delay slots after program end is signaled - * that are still executed, then we're finished. - */ - if (found_shader_end && ip == shader_end_ip + 2) - break; } - if (max_branch_target > shader_end_ip) { + if (max_branch_target > validation_state->max_ip - 3) { DRM_ERROR("Branch landed after QPU_SIG_PROG_END"); return false; } -- cgit v1.2.3 From 7154d76fedf549607afbc0d13db9aaf02da5cebf Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 3 Nov 2016 18:53:10 -0700 Subject: drm/vc4: Add support for rendering with ETC1 textures. The validation for it ends up being quite simple, but I hadn't got around to it before merging the driver. For backwards compatibility, we also need to add a flag so that the userspace GL driver can easily tell if the kernel will allow ETC1 textures (on an old kernel, it will continue to convert to RGBA8) Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_drv.c | 1 + drivers/gpu/drm/vc4/vc4_validate.c | 7 +++++++ include/uapi/drm/vc4_drm.h | 1 + 3 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 8703f56b7947..b087404c2784 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -78,6 +78,7 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, pm_runtime_put(&vc4->v3d->pdev->dev); break; case DRM_VC4_PARAM_SUPPORTS_BRANCHES: + case DRM_VC4_PARAM_SUPPORTS_ETC1: args->value = true; break; default: diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index 26503e307438..e18f88203d32 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c @@ -644,6 +644,13 @@ reloc_tex(struct vc4_exec_info *exec, cpp = 1; break; case VC4_TEXTURE_TYPE_ETC1: + /* ETC1 is arranged as 64-bit blocks, where each block is 4x4 + * pixels. + */ + cpp = 8; + width = (width + 3) >> 2; + height = (height + 3) >> 2; + break; case VC4_TEXTURE_TYPE_BW1: case VC4_TEXTURE_TYPE_A4: case VC4_TEXTURE_TYPE_A1: diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h index ad7edc3edf7c..69caa21f0cb2 100644 --- a/include/uapi/drm/vc4_drm.h +++ b/include/uapi/drm/vc4_drm.h @@ -286,6 +286,7 @@ struct drm_vc4_get_hang_state { #define DRM_VC4_PARAM_V3D_IDENT1 1 #define DRM_VC4_PARAM_V3D_IDENT2 2 #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 +#define DRM_VC4_PARAM_SUPPORTS_ETC1 4 struct drm_vc4_get_param { __u32 param; -- cgit v1.2.3 From ac95330b96376550ae7a533d1396272d675adfa2 Mon Sep 17 00:00:00 2001 From: Stéphan Rafin Date: Fri, 4 Nov 2016 00:53:56 +0100 Subject: clk: sunxi: Fix M factor computation for APB1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cfa636886033 ("clk: sunxi: factors: Consolidate get_factors parameters into a struct") introduced a regression for m factor computation in sun4i_get_apb1_factors function. The old code reassigned the "parent_rate" parameter to the targeted divisor value and was buggy for the returned frequency but not for the computed factors. Now, returned frequency is good but m factor is incorrectly computed (its max value 31 is always set resulting in a significantly slower frequency than the requested one...) This patch simply restores the original proper computation for m while keeping the good changes for returned rate. Fixes: cfa636886033 ("clk: sunxi: factors: Consolidate get_factors parameters into a struct") Signed-off-by: Stéphan Rafin Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sunxi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 838b22aa8b67..f2c9274b8bd5 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -373,7 +373,7 @@ static void sun4i_get_apb1_factors(struct factors_request *req) else calcp = 3; - calcm = (req->parent_rate >> calcp) - 1; + calcm = (div >> calcp) - 1; req->rate = (req->parent_rate >> calcp) / (calcm + 1); req->m = calcm; -- cgit v1.2.3 From 2c3a3f44dc13a7c964e93385e1c1ca848656bed0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 4 Nov 2016 10:30:01 +0000 Subject: drm/i915: Fix pages pin counting around swizzle quirk commit bc0629a76726 ("drm/i915: Track pages pinned due to swizzling quirk") fixed one problem, but revealed a whole lot more. The root cause of the pin count mismatch for the swizzle quirk (for L-shaped memory on gen3/4) was that we were incrementing the pages_pin_count upon getting the backing pages but then overwriting the pages_pin_count to set it to 1 afterwards. With a little bit of adjustment to satisfy the GEM_BUG_ON sanitychecks, the fix is to replace the explicit atomic_set with an atomic_inc. v2: Consistently use atomics (not mix atomics and helpers) within the lowlevel get_pages routines. This makes the atomic operations much clearer. Fixes: 1233e2db199d ("drm/i915: Move object backing storage manipulation") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161104103001.27643-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem.c | 47 +++++++++++++++++++--------------- drivers/gpu/drm/i915/i915_gem_gtt.c | 7 +++++ drivers/gpu/drm/i915/i915_gem_tiling.c | 1 + 3 files changed, 34 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1f995ced524e..0dbf38c51d14 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2324,12 +2324,6 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) if (i915_gem_object_needs_bit17_swizzle(obj)) i915_gem_object_do_bit_17_swizzle(obj, st); - if (i915_gem_object_is_tiled(obj) && - dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { - __i915_gem_object_pin_pages(obj); - obj->mm.quirked = true; - } - return st; err_pages: @@ -2362,12 +2356,21 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, obj->mm.get_page.sg_idx = 0; obj->mm.pages = pages; + + if (i915_gem_object_is_tiled(obj) && + to_i915(obj->base.dev)->quirks & QUIRK_PIN_SWIZZLED_PAGES) { + GEM_BUG_ON(obj->mm.quirked); + __i915_gem_object_pin_pages(obj); + obj->mm.quirked = true; + } } static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj) { struct sg_table *pages; + GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj)); + if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) { DRM_DEBUG("Attempting to obtain a purgeable object\n"); return -EFAULT; @@ -2396,16 +2399,14 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj) if (err) return err; - if (likely(obj->mm.pages)) { - __i915_gem_object_pin_pages(obj); - goto unlock; - } + if (unlikely(!obj->mm.pages)) { + err = ____i915_gem_object_get_pages(obj); + if (err) + goto unlock; - GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj)); - - err = ____i915_gem_object_get_pages(obj); - if (!err) - atomic_set_release(&obj->mm.pages_pin_count, 1); + smp_mb__before_atomic(); + } + atomic_inc(&obj->mm.pages_pin_count); unlock: mutex_unlock(&obj->mm.lock); @@ -2476,12 +2477,14 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, pinned = true; if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) { - ret = ____i915_gem_object_get_pages(obj); - if (ret) - goto err_unlock; + if (unlikely(!obj->mm.pages)) { + ret = ____i915_gem_object_get_pages(obj); + if (ret) + goto err_unlock; - GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count)); - atomic_set_release(&obj->mm.pages_pin_count, 1); + smp_mb__before_atomic(); + } + atomic_inc(&obj->mm.pages_pin_count); pinned = false; } GEM_BUG_ON(!obj->mm.pages); @@ -2933,7 +2936,7 @@ int i915_vma_unbind(struct i915_vma *vma) goto destroy; GEM_BUG_ON(obj->bind_count == 0); - GEM_BUG_ON(!obj->mm.pages); + GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); if (i915_vma_is_map_and_fenceable(vma)) { /* release the fence reg _after_ flushing */ @@ -3167,6 +3170,7 @@ search_free: list_move_tail(&obj->global_link, &dev_priv->mm.bound_list); list_move_tail(&vma->vm_link, &vma->vm->inactive_list); obj->bind_count++; + GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count); return 0; @@ -4100,6 +4104,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, obj->mm.quirked = false; } if (args->madv == I915_MADV_WILLNEED) { + GEM_BUG_ON(obj->mm.quirked); __i915_gem_object_pin_pages(obj); obj->mm.quirked = true; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index cad6de65947d..7531bca29f7a 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3711,6 +3711,13 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) { int ret = 0; + /* The vma->pages are only valid within the lifespan of the borrowed + * obj->mm.pages. When the obj->mm.pages sg_table is regenerated, so + * must be the vma->pages. A simple rule is that vma->pages must only + * be accessed when the obj->mm.pages are pinned. + */ + GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj)); + if (vma->pages) return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 1577e7810cd6..251d51b01174 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -269,6 +269,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, obj->mm.quirked = false; } if (!i915_gem_object_is_tiled(obj)) { + GEM_BUG_ON(!obj->mm.quirked); __i915_gem_object_pin_pages(obj); obj->mm.quirked = true; } -- cgit v1.2.3 From 951f033d969a6deff668286ed4bf0783f905a413 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Wed, 26 Oct 2016 12:04:54 -0600 Subject: pinctrl: zynq: Add a 8 bit wide nand option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware supports a 16 and 8 bit wide NAND bus, let users pick either. Signed-off-by: Jason Gunthorpe Acked-by: Sören Brinkmann Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-zynq.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c index e0ecffcbe11f..b51a46dfdcc3 100644 --- a/drivers/pinctrl/pinctrl-zynq.c +++ b/drivers/pinctrl/pinctrl-zynq.c @@ -247,6 +247,8 @@ static const unsigned int smc0_nor_addr25_pins[] = {1}; static const unsigned int smc0_nand_pins[] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23}; +static const unsigned int smc0_nand8_pins[] = {0, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14}; /* Note: CAN MIO clock inputs are modeled in the clock framework */ static const unsigned int can0_0_pins[] = {10, 11}; static const unsigned int can0_1_pins[] = {14, 15}; @@ -445,6 +447,7 @@ static const struct zynq_pctrl_group zynq_pctrl_groups[] = { DEFINE_ZYNQ_PINCTRL_GRP(smc0_nor_cs1), DEFINE_ZYNQ_PINCTRL_GRP(smc0_nor_addr25), DEFINE_ZYNQ_PINCTRL_GRP(smc0_nand), + DEFINE_ZYNQ_PINCTRL_GRP(smc0_nand8), DEFINE_ZYNQ_PINCTRL_GRP(can0_0), DEFINE_ZYNQ_PINCTRL_GRP(can0_1), DEFINE_ZYNQ_PINCTRL_GRP(can0_2), @@ -709,7 +712,8 @@ static const char * const sdio1_wp_groups[] = {"gpio0_0_grp", static const char * const smc0_nor_groups[] = {"smc0_nor_grp"}; static const char * const smc0_nor_cs1_groups[] = {"smc0_nor_cs1_grp"}; static const char * const smc0_nor_addr25_groups[] = {"smc0_nor_addr25_grp"}; -static const char * const smc0_nand_groups[] = {"smc0_nand_grp"}; +static const char * const smc0_nand_groups[] = {"smc0_nand_grp", + "smc0_nand8_grp"}; static const char * const can0_groups[] = {"can0_0_grp", "can0_1_grp", "can0_2_grp", "can0_3_grp", "can0_4_grp", "can0_5_grp", "can0_6_grp", "can0_7_grp", "can0_8_grp", "can0_9_grp", -- cgit v1.2.3 From 684373eaa95fe6f85ef527281d87ff9ef07b084e Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 31 Oct 2016 16:57:34 +0200 Subject: pinctrl: cherryview: Drop ctrlX prefix from the pin debugfs output Printing the prefix does not provide any additional information. In addition this makes the output look more consistent with pinctrl-intel.c. Signed-off-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-cherryview.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 30389f4ccab4..13644768ae1c 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -762,7 +762,7 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, seq_printf(s, "mode %d ", mode); } - seq_printf(s, "ctrl0 0x%08x ctrl1 0x%08x", ctrl0, ctrl1); + seq_printf(s, "0x%08x 0x%08x", ctrl0, ctrl1); if (locked) seq_puts(s, " [LOCKED]"); -- cgit v1.2.3 From b83bd893f3a04d35f5bfcf399c1034660e5b2403 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 31 Oct 2016 13:21:33 +0000 Subject: pinctrl: bcm2835: reduce GPPUD set-up time Since the BCM2835 datasheet doesn't exactly specify the set-up time for the GPIO Pull-up/down Clock Registers there was an assumption of 150 cycles at a clock rate of 1 MHz. During a discussion [1] in the Raspberry Pi forum it turns out that clock rate refers to the VPU which has a rate of 250 MHz. So we can reduce the delay to a sensible value and update the comment above. I tested this optimization with a Raspberry Pi B and a multimeter. [1] - https://www.raspberrypi.org/forums/viewtopic.php?f=72&t=163352 Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index fa77165fab2c..b2dd278f18b1 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -917,12 +917,14 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev, bcm2835_gpio_wr(pc, GPPUD, arg & 3); /* - * Docs say to wait 150 cycles, but not of what. We assume a - * 1 MHz clock here, which is pretty slow... + * BCM2835 datasheet say to wait 150 cycles, but not of what. + * But the VideoCore firmware delay for this operation + * based nearly on the same amount of VPU cycles and this clock + * runs at 250 MHz. */ - udelay(150); + udelay(1); bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit)); - udelay(150); + udelay(1); bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0); } /* for each config */ -- cgit v1.2.3 From b30ce9e0552aa017ac6f2243f3c2d8e36fe52e69 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Tue, 1 Nov 2016 11:47:59 -0700 Subject: drm/i915/dp: BDW cdclk fix for DP audio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to BSpec, cdclk for BDW has to be not less than 432 MHz with DP audio enabled, port width x4, and link rate HBR2 (5.4 GHz). With cdclk less than 432 MHz, enabling audio leads to pipe FIFO underruns and displays cycling on/off. From BSpec: "Display» BDW-SKL» dpr» [Register] DP_TP_CTL [BDW+,EXCLUDE(CHV)] Workaround : Do not use DisplayPort with CDCLK less than 432 MHz, audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else there may be audio corruption or screen corruption." Since, some DP configurations (e.g., MST) use port width x4 and HBR2 link rate, let's increase the cdclk to >= 432 MHz to enable audio for those cases. v4: Changed commit message v3: Combine BDW pixel rate adjustments into a function (Jani) v2: Restrict fix to BDW Retain the set cdclk across modesets (Ville) Cc: stable@vger.kernel.org Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1478026080-2925-1-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_display.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 97589102442c..7f9970a1fd00 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10247,6 +10247,27 @@ static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state) bxt_set_cdclk(to_i915(dev), req_cdclk); } +static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state, + int pixel_rate) +{ + /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ + if (crtc_state->ips_enabled) + pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); + + /* BSpec says "Do not use DisplayPort with CDCLK less than + * 432 MHz, audio enabled, port width x4, and link rate + * HBR2 (5.4 GHz), or else there may be audio corruption or + * screen corruption." + */ + if (intel_crtc_has_dp_encoder(crtc_state) && + crtc_state->has_audio && + crtc_state->port_clock >= 540000 && + crtc_state->lane_count == 4) + pixel_rate = max(432000, pixel_rate); + + return pixel_rate; +} + /* compute the max rate for new configuration */ static int ilk_max_pixel_rate(struct drm_atomic_state *state) { @@ -10272,9 +10293,9 @@ static int ilk_max_pixel_rate(struct drm_atomic_state *state) pixel_rate = ilk_pipe_pixel_rate(crtc_state); - /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ - if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) - pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); + if (IS_BROADWELL(dev_priv)) + pixel_rate = bdw_adjust_min_pipe_pixel_rate(crtc_state, + pixel_rate); intel_state->min_pixclk[i] = pixel_rate; } -- cgit v1.2.3 From 9c7540241885838cfc7fa58c4a8bd75be0303ed1 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Wed, 2 Nov 2016 13:13:21 -0700 Subject: drm/i915/dp: Extend BDW DP audio workaround to GEN9 platforms According to BSpec, cdclk for BDW has to be not less than 432 MHz with DP audio enabled, port width x4, and link rate HBR2 (5.4 GHz). With cdclk less than 432 MHz, enabling audio leads to pipe FIFO underruns and displays cycling on/off. Let's apply this work around to GEN9 platforms too, as it fixes the same issue. v2: Move drm_device to drm_i915_private conversion Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97907 Cc: stable@vger.kernel.org Cc: Libin Yang Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Jani Nikula Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1478117601-19122-1-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_display.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7f9970a1fd00..92ab01f33208 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10250,8 +10250,10 @@ static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state) static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state, int pixel_rate) { + struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ - if (crtc_state->ips_enabled) + if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); /* BSpec says "Do not use DisplayPort with CDCLK less than @@ -10293,7 +10295,7 @@ static int ilk_max_pixel_rate(struct drm_atomic_state *state) pixel_rate = ilk_pipe_pixel_rate(crtc_state); - if (IS_BROADWELL(dev_priv)) + if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv)) pixel_rate = bdw_adjust_min_pipe_pixel_rate(crtc_state, pixel_rate); -- cgit v1.2.3 From 3be09bec42a800d4f8ead8119c462f3eb4fad435 Mon Sep 17 00:00:00 2001 From: Hiep Cao Minh Date: Fri, 4 Nov 2016 17:38:54 +0900 Subject: spi: rspi: supports 32bytes buffer for DUAL and QUAD This patch supports 32bytes of buffer for DUAL and QUAD in QSPI by Using Transmit/Receive Buffer Data Triggering Number. In order to improve the DUAL and QUAD's performance of SPI while transferring data in PIO mode, it sends/receives each 32bytes data instead of each byte data as current situation. Signed-off-by: Hiep Cao Minh Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index a816f07e168e..3bab75ab1b25 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -413,7 +413,7 @@ static unsigned int qspi_set_send_trigger(struct rspi_data *rspi, return n; } -static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) +static int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) { unsigned int n; @@ -428,6 +428,7 @@ static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) qspi_update(rspi, SPBFCR_RXTRG_MASK, SPBFCR_RXTRG_1B, QSPI_SPBFCR); } + return n; } #define set_config_register(spi, n) spi->ops->set_config_register(spi, n) @@ -514,6 +515,51 @@ static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, return 0; } +static int rspi_pio_transfer_in_or_our(struct rspi_data *rspi, const u8 *tx, + u8 *rx, unsigned int n) +{ + unsigned int i, len; + int ret; + + while (n > 0) { + if (tx) { + len = qspi_set_send_trigger(rspi, n); + if (len == QSPI_BUFFER_SIZE) { + ret = rspi_wait_for_tx_empty(rspi); + if (ret < 0) { + dev_err(&rspi->master->dev, "transmit timeout\n"); + return ret; + } + for (i = 0; i < len; i++) + rspi_write_data(rspi, *tx++); + } else { + ret = rspi_pio_transfer(rspi, tx, NULL, n); + if (ret < 0) + return ret; + } + } + if (rx) { + len = qspi_set_receive_trigger(rspi, n); + if (len == QSPI_BUFFER_SIZE) { + ret = rspi_wait_for_rx_full(rspi); + if (ret < 0) { + dev_err(&rspi->master->dev, "receive timeout\n"); + return ret; + } + for (i = 0; i < len; i++) + *rx++ = rspi_read_data(rspi); + } else { + ret = rspi_pio_transfer(rspi, NULL, rx, n); + if (ret < 0) + return ret; + *rx++ = ret; + } + } + n -= len; + } + return 0; +} + static void rspi_dma_complete(void *arg) { struct rspi_data *rspi = arg; @@ -793,7 +839,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) return ret; } - ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len); + ret = rspi_pio_transfer_in_or_our(rspi, xfer->tx_buf, NULL, xfer->len); if (ret < 0) return ret; @@ -811,7 +857,7 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) return ret; } - return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len); + return rspi_pio_transfer_in_or_our(rspi, NULL, xfer->rx_buf, xfer->len); } static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, -- cgit v1.2.3 From a228062cb4e43e0f94bf48107338757d4d5857b9 Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Tue, 11 Oct 2016 15:26:04 +0100 Subject: drm: mali-dp: Add pitch alignment check function Different hardware versions have different requirements when it comes to pitch alignment. Add a function which can be used to check pitch alignment for a device. Signed-off-by: Brian Starkey Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_hw.c | 3 +++ drivers/gpu/drm/arm/malidp_hw.h | 9 +++++++++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index be815d0cc772..18c476605c0c 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -436,6 +436,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { }, .input_formats = malidp500_de_formats, .n_input_formats = ARRAY_SIZE(malidp500_de_formats), + .bus_align_bytes = 8, }, .query_hw = malidp500_query_hw, .enter_config_mode = malidp500_enter_config_mode, @@ -468,6 +469,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { }, .input_formats = malidp550_de_formats, .n_input_formats = ARRAY_SIZE(malidp550_de_formats), + .bus_align_bytes = 8, }, .query_hw = malidp550_query_hw, .enter_config_mode = malidp550_enter_config_mode, @@ -501,6 +503,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { }, .input_formats = malidp550_de_formats, .n_input_formats = ARRAY_SIZE(malidp550_de_formats), + .bus_align_bytes = 16, }, .query_hw = malidp650_query_hw, .enter_config_mode = malidp550_enter_config_mode, diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index 141743e9f3a6..087e1202db3d 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h @@ -88,6 +88,9 @@ struct malidp_hw_regmap { /* list of supported input formats for each layer */ const struct malidp_input_format *input_formats; const u8 n_input_formats; + + /* pitch alignment requirement in bytes */ + const u8 bus_align_bytes; }; struct malidp_hw_device { @@ -229,6 +232,12 @@ void malidp_se_irq_fini(struct drm_device *drm); u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, u8 layer_id, u32 format); +static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev, + unsigned int pitch) +{ + return !(pitch & (hwdev->map.bus_align_bytes - 1)); +} + /* * background color components are defined as 12bits values, * they will be shifted right when stored on hardware that -- cgit v1.2.3 From a46a096a40c8533f94e781d376b798c1a5208cfd Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Tue, 11 Oct 2016 15:26:05 +0100 Subject: drm: mali-dp: Add pitch alignment check for planes Check that the framebuffer pitches are appropriately aligned when checking planes. Signed-off-by: Brian Starkey Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_planes.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index abaca03b9d36..eaae81908de2 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -86,17 +86,30 @@ static int malidp_de_plane_check(struct drm_plane *plane, { struct malidp_plane *mp = to_malidp_plane(plane); struct malidp_plane_state *ms = to_malidp_plane_state(state); + struct drm_framebuffer *fb; + int n_planes, i; u8 format_id; u32 src_w, src_h; if (!state->crtc || !state->fb) return 0; + fb = state->fb; + format_id = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, - state->fb->pixel_format); + fb->pixel_format); if (format_id == MALIDP_INVALID_FORMAT_ID) return -EINVAL; + n_planes = drm_format_num_planes(fb->pixel_format); + for (i = 0; i < n_planes; i++) { + if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) { + DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", + fb->pitches[i], i); + return -EINVAL; + } + } + src_w = state->src_w >> 16; src_h = state->src_h >> 16; -- cgit v1.2.3 From de9c4810abc6a2e38c93a31bddfa9c0a502f7212 Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Tue, 11 Oct 2016 15:26:06 +0100 Subject: arm: mali-dp: Extract mode_config cleanup into malidp_fini Split out malidp_fini as the opposite of malidp_init. This helps keep the cleanup paths neat and easier to manage. Signed-off-by: Brian Starkey Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 9468dfd52336..9bd6b072a405 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -156,6 +156,12 @@ static int malidp_init(struct drm_device *drm) return 0; } +static void malidp_fini(struct drm_device *drm) +{ + malidp_de_planes_destroy(drm); + drm_mode_config_cleanup(drm); +} + static int malidp_irq_init(struct platform_device *pdev) { int irq_de, irq_se, ret = 0; @@ -414,8 +420,7 @@ bind_fail: port_fail: drm_dev_unregister(drm); register_fail: - malidp_de_planes_destroy(drm); - drm_mode_config_cleanup(drm); + malidp_fini(drm); init_fail: drm->dev_private = NULL; dev_set_drvdata(dev, NULL); @@ -448,8 +453,7 @@ static void malidp_unbind(struct device *dev) of_node_put(malidp->crtc.port); malidp->crtc.port = NULL; drm_dev_unregister(drm); - malidp_de_planes_destroy(drm); - drm_mode_config_cleanup(drm); + malidp_fini(drm); drm->dev_private = NULL; dev_set_drvdata(dev, NULL); clk_disable_unprepare(hwdev->mclk); -- cgit v1.2.3 From 15807780684646949ba9e8f6f56cc3542b04c1ae Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Tue, 11 Oct 2016 15:26:07 +0100 Subject: drm: mali-dp: Refactor plane initialisation As we add more features, it makes sense to skip all the features not supported by the smart layer together, instead of checking each one individually. Achieve this by refactoring the plane init loop. Signed-off-by: Brian Starkey [re-factor code after upstream changed rotation property to be per-plane] Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_planes.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index eaae81908de2..11578debc1ee 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -235,6 +235,8 @@ int malidp_de_planes_init(struct drm_device *drm) struct malidp_plane *plane = NULL; enum drm_plane_type plane_type; unsigned long crtcs = 1 << drm->mode_config.num_crtc; + unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 | + DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y; u32 *formats; int ret, i, j, n; @@ -267,23 +269,16 @@ int malidp_de_planes_init(struct drm_device *drm) if (ret < 0) goto cleanup; - /* SMART layer can't be rotated */ - if (id != DE_SMART) { - unsigned long flags = DRM_ROTATE_0 | - DRM_ROTATE_90 | - DRM_ROTATE_180 | - DRM_ROTATE_270 | - DRM_REFLECT_X | - DRM_REFLECT_Y; - drm_plane_create_rotation_property(&plane->base, - DRM_ROTATE_0, - flags); - } - drm_plane_helper_add(&plane->base, &malidp_de_plane_helper_funcs); plane->hwdev = malidp->dev; plane->layer = &map->layers[i]; + + /* Skip the features which the SMART layer doesn't have */ + if (id == DE_SMART) + continue; + + drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags); } kfree(formats); -- cgit v1.2.3 From c57eb710b6575d12a3b93ee7c8bf5fdcc9d3860d Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Tue, 11 Oct 2016 15:26:08 +0100 Subject: drm: mali-dp: Enable alpha blending Always enable pixel-level alpha blending with the background, so that buffers which include an alpha channel are displayed correctly. Signed-off-by: Brian Starkey Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_planes.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 11578debc1ee..ce328a50bc69 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -27,6 +27,10 @@ #define LAYER_H_FLIP (1 << 10) #define LAYER_V_FLIP (1 << 11) #define LAYER_ROT_MASK (0xf << 8) +#define LAYER_COMP_MASK (0x3 << 12) +#define LAYER_COMP_PIXEL (0x3 << 12) +#define LAYER_COMP_PLANE (0x2 << 12) +#define MALIDP_LAYER_COMPOSE 0x008 #define MALIDP_LAYER_SIZE 0x00c #define LAYER_H_VAL(x) (((x) & 0x1fff) << 0) #define LAYER_V_VAL(x) (((x) & 0x1fff) << 16) @@ -34,6 +38,14 @@ #define MALIDP_LAYER_OFFSET 0x014 #define MALIDP_LAYER_STRIDE 0x018 +/* + * This 4-entry look-up-table is used to determine the full 8-bit alpha value + * for formats with 1- or 2-bit alpha channels. + * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0% + * opacity for 2-bit formats. + */ +#define MALIDP_ALPHA_LUT 0xffaa5500 + static void malidp_de_plane_destroy(struct drm_plane *plane) { struct malidp_plane *mp = to_malidp_plane(plane); @@ -150,7 +162,7 @@ static void malidp_de_plane_update(struct drm_plane *plane, const struct malidp_hw_regmap *map; u8 format_id; u16 ptr; - u32 format, src_w, src_h, dest_w, dest_h, val = 0; + u32 format, src_w, src_h, dest_w, dest_h, val; int num_planes, i; mp = to_malidp_plane(plane); @@ -194,9 +206,9 @@ static void malidp_de_plane_update(struct drm_plane *plane, LAYER_V_VAL(plane->state->crtc_y), mp->layer->base + MALIDP_LAYER_OFFSET); - /* first clear the rotation bits in the register */ - malidp_hw_clearbits(mp->hwdev, LAYER_ROT_MASK, - mp->layer->base + MALIDP_LAYER_CONTROL); + /* first clear the rotation bits */ + val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL); + val &= ~LAYER_ROT_MASK; /* setup the rotation and axis flip bits */ if (plane->state->rotation & DRM_ROTATE_MASK) @@ -206,11 +218,18 @@ static void malidp_de_plane_update(struct drm_plane *plane, if (plane->state->rotation & DRM_REFLECT_Y) val |= LAYER_H_FLIP; + /* + * always enable pixel alpha blending until we have a way to change + * blend modes + */ + val &= ~LAYER_COMP_MASK; + val |= LAYER_COMP_PIXEL; + /* set the 'enable layer' bit */ val |= LAYER_ENABLE; - malidp_hw_setbits(mp->hwdev, val, - mp->layer->base + MALIDP_LAYER_CONTROL); + malidp_hw_write(mp->hwdev, val, + mp->layer->base + MALIDP_LAYER_CONTROL); } static void malidp_de_plane_disable(struct drm_plane *plane, @@ -279,6 +298,8 @@ int malidp_de_planes_init(struct drm_device *drm) continue; drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags); + malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, + plane->layer->base + MALIDP_LAYER_COMPOSE); } kfree(formats); -- cgit v1.2.3 From 70c94a3c8f68187b272e5aa4e1a9df354df461eb Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Tue, 11 Oct 2016 15:26:09 +0100 Subject: drm: mali-dp: Store internal format and n_planes in plane state Save a search through the format lists at commit-time by storing the internal format ID and number of planes in our plane state. Signed-off-by: Brian Starkey Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.h | 3 +++ drivers/gpu/drm/arm/malidp_planes.c | 27 ++++++++++++--------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index 271d2fb9711c..9fc8a2e405e4 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h @@ -39,6 +39,9 @@ struct malidp_plane_state { /* size of the required rotation memory if plane is rotated */ u32 rotmem_size; + /* internal format ID */ + u8 format; + u8 n_planes; }; #define to_malidp_plane(x) container_of(x, struct malidp_plane, base) diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index ce328a50bc69..bb1c52864f13 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -70,6 +70,8 @@ struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) m_state = to_malidp_plane_state(plane->state); __drm_atomic_helper_plane_duplicate_state(plane, &state->base); state->rotmem_size = m_state->rotmem_size; + state->format = m_state->format; + state->n_planes = m_state->n_planes; } return &state->base; @@ -99,8 +101,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, struct malidp_plane *mp = to_malidp_plane(plane); struct malidp_plane_state *ms = to_malidp_plane_state(state); struct drm_framebuffer *fb; - int n_planes, i; - u8 format_id; + int i; u32 src_w, src_h; if (!state->crtc || !state->fb) @@ -108,13 +109,13 @@ static int malidp_de_plane_check(struct drm_plane *plane, fb = state->fb; - format_id = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, + ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, fb->pixel_format); - if (format_id == MALIDP_INVALID_FORMAT_ID) + if (ms->format == MALIDP_INVALID_FORMAT_ID) return -EINVAL; - n_planes = drm_format_num_planes(fb->pixel_format); - for (i = 0; i < n_planes; i++) { + ms->n_planes = drm_format_num_planes(fb->pixel_format); + for (i = 0; i < ms->n_planes; i++) { if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) { DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", fb->pitches[i], i); @@ -160,17 +161,13 @@ static void malidp_de_plane_update(struct drm_plane *plane, struct drm_gem_cma_object *obj; struct malidp_plane *mp; const struct malidp_hw_regmap *map; - u8 format_id; + struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); u16 ptr; - u32 format, src_w, src_h, dest_w, dest_h, val; - int num_planes, i; + u32 src_w, src_h, dest_w, dest_h, val; + int i; mp = to_malidp_plane(plane); - map = &mp->hwdev->map; - format = plane->state->fb->pixel_format; - format_id = malidp_hw_get_format_id(map, mp->layer->id, format); - num_planes = drm_format_num_planes(format); /* convert src values from Q16 fixed point to integer */ src_w = plane->state->src_w >> 16; @@ -183,9 +180,9 @@ static void malidp_de_plane_update(struct drm_plane *plane, dest_h = plane->state->crtc_h; } - malidp_hw_write(mp->hwdev, format_id, mp->layer->base); + malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); - for (i = 0; i < num_planes; i++) { + for (i = 0; i < ms->n_planes; i++) { /* calculate the offset for the layer's plane registers */ ptr = mp->layer->ptr + (i << 4); -- cgit v1.2.3 From fe37ed6a2dd63b5cc945b6b354c02b58473c0abf Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Mon, 24 Oct 2016 14:55:17 +0100 Subject: drm: mali-dp: Don't set DRM_PLANE_COMMIT_ACTIVE_ONLY We need to explicitly disable our planes, so don't set the flag which would otherwise skip the plane disable when the CRTC is disabled. Signed-off-by: Brian Starkey Acked-by: Liviu Dudau Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 9bd6b072a405..6cbf4fa90ea0 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -92,8 +92,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_commit_modeset_disables(drm, state); drm_atomic_helper_commit_modeset_enables(drm, state); - drm_atomic_helper_commit_planes(drm, state, - DRM_PLANE_COMMIT_ACTIVE_ONLY); + drm_atomic_helper_commit_planes(drm, state, 0); malidp_atomic_commit_hw_done(state); -- cgit v1.2.3 From 2fe1f08ee06e9f2eabdaf9fdaba31360920abfcb Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Mon, 24 Oct 2016 18:35:09 +0100 Subject: drm: mali-dp: Add support for setting plane's rotation property from userspace. In order to support DRM_IOCTL_MODE_OBJ_SETPROPERTY for the rotation property we need to have a ->set_property hook defined for the planes. Set the plane's ->set_property hook to drm_atomic_helper_plane_set_property() Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_planes.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index bb1c52864f13..8eef9a891261 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -89,6 +89,7 @@ void malidp_destroy_plane_state(struct drm_plane *plane, static const struct drm_plane_funcs malidp_de_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, + .set_property = drm_atomic_helper_plane_set_property, .destroy = malidp_de_plane_destroy, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = malidp_duplicate_plane_state, -- cgit v1.2.3 From ed8b0c0f93fd91447770ced4a7ecac1a1f39eae2 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sat, 22 Oct 2016 17:13:01 +0800 Subject: drm/arm: mark symbols static where possible We get 2 warnings when building kernel with W=1: drivers/gpu/drm/arm/malidp_planes.c:49:25: warning: no previous prototype for 'malidp_duplicate_plane_state' [-Wmissing-prototypes] drivers/gpu/drm/arm/malidp_planes.c:66:6: warning: no previous prototype for 'malidp_destroy_plane_state' [-Wmissing-prototypes] In fact, both functions are only used in the file in which they are declared and don't need a declaration, but can be made static. So this patch marks these functions with 'static'. Signed-off-by: Baoyou Xie Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_planes.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 8eef9a891261..63eec8f37cfc 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -58,7 +58,8 @@ static void malidp_de_plane_destroy(struct drm_plane *plane) devm_kfree(plane->dev->dev, mp); } -struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) +static struct +drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) { struct malidp_plane_state *state, *m_state; @@ -77,8 +78,8 @@ struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) return &state->base; } -void malidp_destroy_plane_state(struct drm_plane *plane, - struct drm_plane_state *state) +static void malidp_destroy_plane_state(struct drm_plane *plane, + struct drm_plane_state *state) { struct malidp_plane_state *m_state = to_malidp_plane_state(state); -- cgit v1.2.3 From f97f193613dc7b723fa1b7e187da0ba585a7f2de Mon Sep 17 00:00:00 2001 From: Lyude Date: Tue, 1 Nov 2016 17:31:32 -0400 Subject: drm/i915: Remove redundant reprobe in i915_drm_resume Weine's investigation on benchmarking the suspend/resume process pointed out a lot of the time in suspend/resume is being spent reprobing. While the reprobing process is a lengthy one for good reason, we don't need to hold up the entire suspend/resume process while we wait for it to finish. Luckily as it turns out, we already trigger a full connector reprobe in i915_hpd_poll_init_work(), so we can just ditch reprobing in i915_drm_resume() entirely. This won't lead to less time spent resuming just yet since now the bottleneck will be waiting for the mode_config lock in drm_kms_helper_poll_enable(), since that will be held as long as i915_hpd_poll_init_work() is reprobing all of the connectors. But we'll address that in the next patch. Signed-off-by: Lyude Tested-by: David Weinehall Reviewed-by: David Weinehall Testcase: analyze_suspend.py -config config/suspend-callgraph.cfg -filter i915 --- drivers/gpu/drm/i915/i915_drv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9e5a547a67ab..0e45665efd7f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1607,8 +1607,6 @@ static int i915_drm_resume(struct drm_device *dev) * notifications. * */ intel_hpd_init(dev_priv); - /* Config may have changed between suspend and resume */ - drm_helper_hpd_irq_event(dev); intel_opregion_register(dev_priv); -- cgit v1.2.3 From e0b70061404f64f592d6d082a63c504b66d65c6e Mon Sep 17 00:00:00 2001 From: Lyude Date: Tue, 1 Nov 2016 21:06:30 -0400 Subject: drm/i915: Reinit polling before hpd when resuming Now that we don't run the connector reprobing from i915_drm_resume(), we need to make it so we don't have to wait for reprobing to finish so that we actually speed things up. In order to do this, we need to make sure that i915_drm_resume() doesn't get blocked by i915_hpd_poll_init_work() while trying to acquire the mode_config lock that drm_kms_helper_poll_enable() needs to acquire. The easiest way to do this is to just enable polling before hpd. This shouldn't break anything since at that point we have everything else we need for polling enabled. As well, this should result in a rather significant improvement in how quickly we can resume the system. Signed-off-by: Lyude Tested-by: David Weinehall Reviewed-by: David Weinehall Testcase: analyze_suspend.py -config config/suspend-callgraph.cfg -filter i915 --- drivers/gpu/drm/i915/i915_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0e45665efd7f..b72c24ff39c3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1600,6 +1600,8 @@ static int i915_drm_resume(struct drm_device *dev) intel_display_resume(dev); + drm_kms_helper_poll_enable(dev); + /* * ... but also need to make sure that hotplug processing * doesn't cause havoc. Like in the driver load code we don't @@ -1619,7 +1621,6 @@ static int i915_drm_resume(struct drm_device *dev) intel_opregion_notify_adapter(dev_priv, PCI_D0); intel_autoenable_gt_powersave(dev_priv); - drm_kms_helper_poll_enable(dev); enable_rpm_wakeref_asserts(dev_priv); -- cgit v1.2.3 From 1b5b42216469b05ef4b5916cb40b127dfab1da88 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Thu, 3 Nov 2016 12:11:42 +0100 Subject: regulator: core: Add new API to poll for error conditions Regulator consumers can receive event notifications when errors are reported to the driver, but currently, there is no way for a regulator consumer to know when the error is over. To allow a regulator consumer to poll for error conditions add a new API: regulator_get_error_flags. Signed-off-by: Axel Haslam Signed-off-by: Mark Brown --- drivers/regulator/core.c | 33 +++++++++++++++++++++++++++++++++ include/linux/regulator/consumer.h | 26 ++++++++++++++++++++++++++ include/linux/regulator/driver.h | 4 ++++ 3 files changed, 63 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 67426c0477d3..08260c215895 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3359,6 +3359,39 @@ unsigned int regulator_get_mode(struct regulator *regulator) } EXPORT_SYMBOL_GPL(regulator_get_mode); +static int _regulator_get_error_flags(struct regulator_dev *rdev, + unsigned int *flags) +{ + int ret; + + mutex_lock(&rdev->mutex); + + /* sanity check */ + if (!rdev->desc->ops->get_error_flags) { + ret = -EINVAL; + goto out; + } + + ret = rdev->desc->ops->get_error_flags(rdev, flags); +out: + mutex_unlock(&rdev->mutex); + return ret; +} + +/** + * regulator_get_error_flags - get regulator error information + * @regulator: regulator source + * @flags: pointer to store error flags + * + * Get the current regulator error information. + */ +int regulator_get_error_flags(struct regulator *regulator, + unsigned int *flags) +{ + return _regulator_get_error_flags(regulator->rdev, flags); +} +EXPORT_SYMBOL_GPL(regulator_get_error_flags); + /** * regulator_set_load - set regulator load * @regulator: regulator source diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 692108222271..528eb1f5273e 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -120,6 +120,25 @@ struct regmap; #define REGULATOR_EVENT_PRE_DISABLE 0x400 #define REGULATOR_EVENT_ABORT_DISABLE 0x800 +/* + * Regulator errors that can be queried using regulator_get_error_flags + * + * UNDER_VOLTAGE Regulator output is under voltage. + * OVER_CURRENT Regulator output current is too high. + * REGULATION_OUT Regulator output is out of regulation. + * FAIL Regulator output has failed. + * OVER_TEMP Regulator over temp. + * + * NOTE: These errors can be OR'ed together. + */ + +#define REGULATOR_ERROR_UNDER_VOLTAGE BIT(1) +#define REGULATOR_ERROR_OVER_CURRENT BIT(2) +#define REGULATOR_ERROR_REGULATION_OUT BIT(3) +#define REGULATOR_ERROR_FAIL BIT(4) +#define REGULATOR_ERROR_OVER_TEMP BIT(5) + + /** * struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event * @@ -237,6 +256,8 @@ int regulator_get_current_limit(struct regulator *regulator); int regulator_set_mode(struct regulator *regulator, unsigned int mode); unsigned int regulator_get_mode(struct regulator *regulator); +int regulator_get_error_flags(struct regulator *regulator, + unsigned int *flags); int regulator_set_load(struct regulator *regulator, int load_uA); int regulator_allow_bypass(struct regulator *regulator, bool allow); @@ -477,6 +498,11 @@ static inline unsigned int regulator_get_mode(struct regulator *regulator) return REGULATOR_MODE_NORMAL; } +static inline int regulator_get_error_flags(struct regulator *regulator) +{ + return -EINVAL; +} + static inline int regulator_set_load(struct regulator *regulator, int load_uA) { return REGULATOR_MODE_NORMAL; diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 37b532410528..dac8e7b16bc6 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -100,6 +100,7 @@ struct regulator_linear_range { * * @set_mode: Set the configured operating mode for the regulator. * @get_mode: Get the configured operating mode for the regulator. + * @get_error_flags: Get the current error(s) for the regulator. * @get_status: Return actual (not as-configured) status of regulator, as a * REGULATOR_STATUS value (or negative errno) * @get_optimum_mode: Get the most efficient operating mode for the regulator @@ -169,6 +170,9 @@ struct regulator_ops { int (*set_mode) (struct regulator_dev *, unsigned int mode); unsigned int (*get_mode) (struct regulator_dev *); + /* retrieve current error flags on the regulator */ + int (*get_error_flags)(struct regulator_dev *, unsigned int *flags); + /* Time taken to enable or set voltage on the regulator */ int (*enable_time) (struct regulator_dev *); int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay); -- cgit v1.2.3 From 18abed211c0503167a566d3ff330dc7ca44e5fc6 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:26 +0100 Subject: net: dsa: mv88e6xxx: add port files The Marvell switches contains one internal SMI device per port, called "Port Registers". Depending on the model, the addresses of these devices start from 0x0, 0x8 or 0x10. Start moving Port Registers specific code to their own files. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/Makefile | 1 + drivers/net/dsa/mv88e6xxx/chip.c | 17 +---------------- drivers/net/dsa/mv88e6xxx/port.c | 31 +++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 24 ++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/port.c create mode 100644 drivers/net/dsa/mv88e6xxx/port.h (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile index 10ce820daa48..c36be318de1a 100644 --- a/drivers/net/dsa/mv88e6xxx/Makefile +++ b/drivers/net/dsa/mv88e6xxx/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o mv88e6xxx-objs := chip.o mv88e6xxx-objs += global1.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o +mv88e6xxx-objs += port.o diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 72b9dac29901..b32b24256065 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -37,6 +37,7 @@ #include "mv88e6xxx.h" #include "global1.h" #include "global2.h" +#include "port.h" static void assert_reg_lock(struct mv88e6xxx_chip *chip) { @@ -221,22 +222,6 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val) return 0; } -static int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, - u16 *val) -{ - int addr = chip->info->port_base_addr + port; - - return mv88e6xxx_read(chip, addr, reg, val); -} - -static int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, - u16 val) -{ - int addr = chip->info->port_base_addr + port; - - return mv88e6xxx_write(chip, addr, reg, val); -} - static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy, int reg, u16 *val) { diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c new file mode 100644 index 000000000000..3b36c9290ea8 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -0,0 +1,31 @@ +/* + * Marvell 88E6xxx Switch Port Registers support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2016 Vivien Didelot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include "mv88e6xxx.h" +#include "port.h" + +int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, + u16 *val) +{ + int addr = chip->info->port_base_addr + port; + + return mv88e6xxx_read(chip, addr, reg, val); +} + +int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, + u16 val) +{ + int addr = chip->info->port_base_addr + port; + + return mv88e6xxx_write(chip, addr, reg, val); +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h new file mode 100644 index 000000000000..ae1ae2b501b6 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -0,0 +1,24 @@ +/* + * Marvell 88E6xxx Switch Port Registers support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2016 Vivien Didelot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _MV88E6XXX_PORT_H +#define _MV88E6XXX_PORT_H + +#include "mv88e6xxx.h" + +int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, + u16 *val); +int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, + u16 val); + +#endif /* _MV88E6XXX_PORT_H */ -- cgit v1.2.3 From e28def33291c2b1e3a53da2dddd46a04f9f985ab Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:27 +0100 Subject: net: dsa: mv88e6xxx: add port state setter Add the port STP state setter to the port files. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 49 ++++------------------------------------ drivers/net/dsa/mv88e6xxx/port.c | 31 +++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 3 files changed, 37 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index b32b24256065..12c1175ce55d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1215,41 +1215,6 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, return _mv88e6xxx_atu_move(chip, fid, port, 0x0f, static_too); } -static const char * const mv88e6xxx_port_state_names[] = { - [PORT_CONTROL_STATE_DISABLED] = "Disabled", - [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening", - [PORT_CONTROL_STATE_LEARNING] = "Learning", - [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", -}; - -static int _mv88e6xxx_port_state(struct mv88e6xxx_chip *chip, int port, - u8 state) -{ - struct dsa_switch *ds = chip->ds; - u16 reg; - int err; - u8 oldstate; - - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®); - if (err) - return err; - - oldstate = reg & PORT_CONTROL_STATE_MASK; - - reg &= ~PORT_CONTROL_STATE_MASK; - reg |= state; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, "PortState %s (was %s)\n", - mv88e6xxx_port_state_names[state], - mv88e6xxx_port_state_names[oldstate]); - - return 0; -} - static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) { struct net_device *bridge = chip->ports[port].bridge_dev; @@ -1313,13 +1278,11 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, } mutex_lock(&chip->reg_lock); - err = _mv88e6xxx_port_state(chip, port, stp_state); + err = mv88e6xxx_port_set_state(chip, port, stp_state); mutex_unlock(&chip->reg_lock); if (err) - netdev_err(ds->ports[port].netdev, - "failed to update state to %s\n", - mv88e6xxx_port_state_names[stp_state]); + netdev_err(ds->ports[port].netdev, "failed to update state\n"); } static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) @@ -2526,12 +2489,8 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip) /* Set all ports to the disabled state. */ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { - err = mv88e6xxx_port_read(chip, i, PORT_CONTROL, ®); - if (err) - return err; - - err = mv88e6xxx_port_write(chip, i, PORT_CONTROL, - reg & 0xfffc); + err = mv88e6xxx_port_set_state(chip, i, + PORT_CONTROL_STATE_DISABLED); if (err) return err; } diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 3b36c9290ea8..8d59fe73a834 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -29,3 +29,34 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, return mv88e6xxx_write(chip, addr, reg, val); } + +/* Offset 0x04: Port Control Register */ + +static const char * const mv88e6xxx_port_state_names[] = { + [PORT_CONTROL_STATE_DISABLED] = "Disabled", + [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening", + [PORT_CONTROL_STATE_LEARNING] = "Learning", + [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", +}; + +int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®); + if (err) + return err; + + reg &= ~PORT_CONTROL_STATE_MASK; + reg |= state; + + err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n", + mv88e6xxx_port_state_names[state]); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index ae1ae2b501b6..ac13988fc79a 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -21,4 +21,6 @@ int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, u16 val); +int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); + #endif /* _MV88E6XXX_PORT_H */ -- cgit v1.2.3 From 5a7921f46df2aded2c3e49b3e2104a0d1041dea4 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:28 +0100 Subject: net: dsa: mv88e6xxx: add port vlan map setter Add a port function to access the Port Based VLAN Map register. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 14 ++------------ drivers/net/dsa/mv88e6xxx/port.c | 25 +++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 3 files changed, 29 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 12c1175ce55d..0877777c4693 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1218,16 +1218,13 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) { struct net_device *bridge = chip->ports[port].bridge_dev; - const u16 mask = (1 << mv88e6xxx_num_ports(chip)) - 1; struct dsa_switch *ds = chip->ds; u16 output_ports = 0; - u16 reg; - int err; int i; /* allow CPU port or DSA link(s) to send frames to every port */ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { - output_ports = mask; + output_ports = ~0; } else { for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { /* allow sending frames to every group member */ @@ -1243,14 +1240,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) /* prevent frames from going back out of the port they came in on */ output_ports &= ~BIT(port); - err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); - if (err) - return err; - - reg &= ~mask; - reg |= output_ports & mask; - - return mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); + return mv88e6xxx_port_set_vlan_map(chip, port, output_ports); } static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 8d59fe73a834..c6a22ae23181 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -60,3 +60,28 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) return 0; } + +/* Offset 0x06: Port Based VLAN Map */ + +int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) +{ + const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0); + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); + if (err) + return err; + + reg &= ~mask; + reg |= map & mask; + + err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n", + map); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index ac13988fc79a..037d6384b3aa 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -23,4 +23,6 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); +int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map); + #endif /* _MV88E6XXX_PORT_H */ -- cgit v1.2.3 From b4e48c500eb80120df1a4259a04b131e71c5ca62 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:29 +0100 Subject: net: dsa: mv88e6xxx: add port FID accessors Add functions to port files to access the ports default FID. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 77 +++------------------------------------- drivers/net/dsa/mv88e6xxx/port.c | 67 ++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 3 ++ 3 files changed, 74 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 0877777c4693..20f59f1e449f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1674,75 +1674,6 @@ loadpurge: return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE); } -static int _mv88e6xxx_port_fid(struct mv88e6xxx_chip *chip, int port, - u16 *new, u16 *old) -{ - struct dsa_switch *ds = chip->ds; - u16 upper_mask; - u16 fid; - u16 reg; - int err; - - if (mv88e6xxx_num_databases(chip) == 4096) - upper_mask = 0xff; - else if (mv88e6xxx_num_databases(chip) == 256) - upper_mask = 0xf; - else - return -EOPNOTSUPP; - - /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */ - err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); - if (err) - return err; - - fid = (reg & PORT_BASE_VLAN_FID_3_0_MASK) >> 12; - - if (new) { - reg &= ~PORT_BASE_VLAN_FID_3_0_MASK; - reg |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); - if (err) - return err; - } - - /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */ - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, ®); - if (err) - return err; - - fid |= (reg & upper_mask) << 4; - - if (new) { - reg &= ~upper_mask; - reg |= (*new >> 4) & upper_mask; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, - "FID %d (was %d)\n", *new, fid); - } - - if (old) - *old = fid; - - return 0; -} - -static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_chip *chip, - int port, u16 *fid) -{ - return _mv88e6xxx_port_fid(chip, port, NULL, fid); -} - -static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_chip *chip, - int port, u16 fid) -{ - return _mv88e6xxx_port_fid(chip, port, &fid, NULL); -} - static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid) { DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID); @@ -1753,7 +1684,7 @@ static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid) /* Set every FID bit used by the (un)bridged ports */ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { - err = _mv88e6xxx_port_fid_get(chip, i, fid); + err = mv88e6xxx_port_get_fid(chip, i, fid); if (err) return err; @@ -2203,7 +2134,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, /* Null VLAN ID corresponds to the port private database */ if (vid == 0) - err = _mv88e6xxx_port_fid_get(chip, port, &vlan.fid); + err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid); else err = _mv88e6xxx_vtu_get(chip, vid, &vlan, false); if (err) @@ -2379,7 +2310,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, int err; /* Dump port's default Filtering Information Database (VLAN ID 0) */ - err = _mv88e6xxx_port_fid_get(chip, port, &fid); + err = mv88e6xxx_port_get_fid(chip, port, &fid); if (err) return err; @@ -2782,7 +2713,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) * database, and allow bidirectional communication between the * CPU and DSA port(s), and the other ports. */ - err = _mv88e6xxx_port_fid_set(chip, port, 0); + err = mv88e6xxx_port_set_fid(chip, port, 0); if (err) return err; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index c6a22ae23181..a7da81248bcf 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -61,6 +61,8 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) return 0; } +/* Offset 0x05: Port Control 1 */ + /* Offset 0x06: Port Based VLAN Map */ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) @@ -85,3 +87,68 @@ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) return 0; } + +int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid) +{ + const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4; + u16 reg; + int err; + + /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */ + err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); + if (err) + return err; + + *fid = (reg & 0xf000) >> 12; + + /* Port's default FID upper bits are located in reg 0x05, offset 0 */ + if (upper_mask) { + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, ®); + if (err) + return err; + + *fid |= (reg & upper_mask) << 4; + } + + return 0; +} + +int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid) +{ + const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4; + u16 reg; + int err; + + if (fid >= mv88e6xxx_num_databases(chip)) + return -EINVAL; + + /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */ + err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); + if (err) + return err; + + reg &= 0x0fff; + reg |= (fid & 0x000f) << 12; + + err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); + if (err) + return err; + + /* Port's default FID upper bits are located in reg 0x05, offset 0 */ + if (upper_mask) { + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, ®); + if (err) + return err; + + reg &= ~upper_mask; + reg |= (fid >> 4) & upper_mask; + + err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg); + if (err) + return err; + } + + netdev_dbg(chip->ds->ports[port].netdev, "FID set to %u\n", fid); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 037d6384b3aa..0df29b957811 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -25,4 +25,7 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map); +int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid); +int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid); + #endif /* _MV88E6XXX_PORT_H */ -- cgit v1.2.3 From 77064f37b9c26e13290c06f90951d8f0482837dc Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:30 +0100 Subject: net: dsa: mv88e6xxx: add port PVID accessors Add port functions to access the ports default VID. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 51 ++++------------------------------------ drivers/net/dsa/mv88e6xxx/port.c | 38 ++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 3 +++ 3 files changed, 45 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 20f59f1e449f..9c0a0283f961 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1288,49 +1288,6 @@ static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) netdev_err(ds->ports[port].netdev, "failed to flush ATU\n"); } -static int _mv88e6xxx_port_pvid(struct mv88e6xxx_chip *chip, int port, - u16 *new, u16 *old) -{ - struct dsa_switch *ds = chip->ds; - u16 pvid, reg; - int err; - - err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ®); - if (err) - return err; - - pvid = reg & PORT_DEFAULT_VLAN_MASK; - - if (new) { - reg &= ~PORT_DEFAULT_VLAN_MASK; - reg |= *new & PORT_DEFAULT_VLAN_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, - "DefaultVID %d (was %d)\n", *new, pvid); - } - - if (old) - *old = pvid; - - return 0; -} - -static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_chip *chip, - int port, u16 *pvid) -{ - return _mv88e6xxx_port_pvid(chip, port, NULL, pvid); -} - -static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_chip *chip, - int port, u16 pvid) -{ - return _mv88e6xxx_port_pvid(chip, port, &pvid, NULL); -} - static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_chip *chip) { return mv88e6xxx_g1_wait(chip, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY); @@ -1510,7 +1467,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, mutex_lock(&chip->reg_lock); - err = _mv88e6xxx_port_pvid_get(chip, port, &pvid); + err = mv88e6xxx_port_get_pvid(chip, port, &pvid); if (err) goto unlock; @@ -1958,7 +1915,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, "failed to add VLAN %d%c\n", vid, untagged ? 'u' : 't'); - if (pvid && _mv88e6xxx_port_pvid_set(chip, port, vlan->vid_end)) + if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end)) netdev_err(ds->ports[port].netdev, "failed to set PVID %d\n", vlan->vid_end); @@ -2013,7 +1970,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, mutex_lock(&chip->reg_lock); - err = _mv88e6xxx_port_pvid_get(chip, port, &pvid); + err = mv88e6xxx_port_get_pvid(chip, port, &pvid); if (err) goto unlock; @@ -2023,7 +1980,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, goto unlock; if (vid == pvid) { - err = _mv88e6xxx_port_pvid_set(chip, port, 0); + err = mv88e6xxx_port_set_pvid(chip, port, 0); if (err) goto unlock; } diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index a7da81248bcf..104fe2d9d4e1 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -152,3 +152,41 @@ int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid) return 0; } + +/* Offset 0x07: Default Port VLAN ID & Priority */ + +int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ®); + if (err) + return err; + + *pvid = reg & PORT_DEFAULT_VLAN_MASK; + + return 0; +} + +int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ®); + if (err) + return err; + + reg &= ~PORT_DEFAULT_VLAN_MASK; + reg |= pvid & PORT_DEFAULT_VLAN_MASK; + + err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n", + pvid); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 0df29b957811..4489d9e88689 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -28,4 +28,7 @@ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map); int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid); int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid); +int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid); +int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid); + #endif /* _MV88E6XXX_PORT_H */ -- cgit v1.2.3 From 385a0995cc646d5df0ec06e375db47225776ab31 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:31 +0100 Subject: net: dsa: mv88e6xxx: add port 802.1Q mode setter Add port functions to set the port 802.1Q mode. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 33 ++------------------------------- drivers/net/dsa/mv88e6xxx/port.c | 32 ++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 3 +++ 3 files changed, 37 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9c0a0283f961..181d3b9aad06 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1806,48 +1806,19 @@ unlock: return err; } -static const char * const mv88e6xxx_port_8021q_mode_names[] = { - [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", - [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", - [PORT_CONTROL_2_8021Q_CHECK] = "Check", - [PORT_CONTROL_2_8021Q_SECURE] = "Secure", -}; - static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) { struct mv88e6xxx_chip *chip = ds->priv; - u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE : + u16 mode = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE : PORT_CONTROL_2_8021Q_DISABLED; - u16 reg; int err; if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU)) return -EOPNOTSUPP; mutex_lock(&chip->reg_lock); - - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, ®); - if (err) - goto unlock; - - old = reg & PORT_CONTROL_2_8021Q_MASK; - - if (new != old) { - reg &= ~PORT_CONTROL_2_8021Q_MASK; - reg |= new & PORT_CONTROL_2_8021Q_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); - if (err) - goto unlock; - - netdev_dbg(ds->ports[port].netdev, "802.1Q Mode %s (was %s)\n", - mv88e6xxx_port_8021q_mode_names[new], - mv88e6xxx_port_8021q_mode_names[old]); - } - - err = 0; -unlock: + err = mv88e6xxx_port_set_8021q_mode(chip, port, mode); mutex_unlock(&chip->reg_lock); return err; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 104fe2d9d4e1..53d17e63b04a 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -190,3 +190,35 @@ int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid) return 0; } + +/* Offset 0x08: Port Control 2 Register */ + +static const char * const mv88e6xxx_port_8021q_mode_names[] = { + [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", + [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", + [PORT_CONTROL_2_8021Q_CHECK] = "Check", + [PORT_CONTROL_2_8021Q_SECURE] = "Secure", +}; + +int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, ®); + if (err) + return err; + + reg &= ~PORT_CONTROL_2_8021Q_MASK; + reg |= mode & PORT_CONTROL_2_8021Q_MASK; + + err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n", + mv88e6xxx_port_8021q_mode_names[mode]); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 4489d9e88689..921eecf8acb8 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -31,4 +31,7 @@ int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid); int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid); int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid); +int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode); + #endif /* _MV88E6XXX_PORT_H */ -- cgit v1.2.3 From 08ef7f1022e85539d5e3ce925e1fab60b205ae39 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:32 +0100 Subject: net: dsa: mv88e6xxx: add port link setter Most of the chips will have a port register control bits to force the port's link up, down, or let normal link detection occurs. Implement such operation to use it later when setting duplex, etc. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 17 +++++++++++++++ drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 10 +++++++++ drivers/net/dsa/mv88e6xxx/port.c | 41 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 4 files changed, 70 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 181d3b9aad06..cc43e6f09c5d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3160,42 +3160,49 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6095_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6123_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6131_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6161_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6165_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6171_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6172_ops = { @@ -3204,12 +3211,14 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6175_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6176_ops = { @@ -3218,12 +3227,14 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6185_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -3232,6 +3243,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3240,6 +3252,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6321_ops = { @@ -3248,18 +3261,21 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6350_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6351_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6352_ops = { @@ -3268,6 +3284,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index 6f48e5886b2a..474d16d64629 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -727,6 +727,16 @@ struct mv88e6xxx_ops { u16 *val); int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); + +#define LINK_FORCED_DOWN 0 +#define LINK_FORCED_UP 1 +#define LINK_UNFORCED -2 + + /* Port's MAC link state + * Use LINK_FORCED_UP or LINK_FORCED_DOWN to force link up or down, + * or LINK_UNFORCED for normal link detection. + */ + int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link); }; enum stat_type { diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 53d17e63b04a..09e25f975b25 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -30,6 +30,47 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, return mv88e6xxx_write(chip, addr, reg, val); } +/* Offset 0x01: MAC (or PCS or Physical) Control Register + * + * Link, Duplex and Flow Control have one force bit, one value bit. + */ + +int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); + if (err) + return err; + + reg &= ~(PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP); + + switch (link) { + case LINK_FORCED_DOWN: + reg |= PORT_PCS_CTRL_FORCE_LINK; + break; + case LINK_FORCED_UP: + reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP; + break; + case LINK_UNFORCED: + /* normal link detection */ + break; + default: + return -EINVAL; + } + + err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "%s link %s\n", + reg & PORT_PCS_CTRL_FORCE_LINK ? "Force" : "Unforce", + reg & PORT_PCS_CTRL_LINK_UP ? "up" : "down"); + + return 0; +} + /* Offset 0x04: Port Control Register */ static const char * const mv88e6xxx_port_state_names[] = { diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 921eecf8acb8..87e7249d516b 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -21,6 +21,8 @@ int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, u16 val); +int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link); + int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map); -- cgit v1.2.3 From 7f1ae07b51e8b617922b2b73850361eafa17a684 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:33 +0100 Subject: net: dsa: mv88e6xxx: add port duplex setter Similarly to port's link, add setter to force port's half duplex, full duplex or let normal duplex detection occurs. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 17 +++++++++++++++++ drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 9 +++++++++ drivers/net/dsa/mv88e6xxx/port.c | 36 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 4 files changed, 64 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index cc43e6f09c5d..49a69354b5b3 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3161,6 +3161,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6095_ops = { @@ -3168,6 +3169,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6123_ops = { @@ -3175,6 +3177,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6131_ops = { @@ -3182,6 +3185,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6161_ops = { @@ -3189,6 +3193,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6165_ops = { @@ -3196,6 +3201,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6171_ops = { @@ -3203,6 +3209,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6172_ops = { @@ -3212,6 +3219,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -3219,6 +3227,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6176_ops = { @@ -3228,6 +3237,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -3235,6 +3245,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -3244,6 +3255,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3253,6 +3265,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6321_ops = { @@ -3262,6 +3275,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6350_ops = { @@ -3269,6 +3283,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6351_ops = { @@ -3276,6 +3291,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6352_ops = { @@ -3285,6 +3301,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index 474d16d64629..ab48eb996667 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -737,6 +737,15 @@ struct mv88e6xxx_ops { * or LINK_UNFORCED for normal link detection. */ int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link); + +#define DUPLEX_UNFORCED -2 + + /* Port's MAC duplex mode + * + * Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex, + * or DUPLEX_UNFORCED for normal duplex detection. + */ + int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup); }; enum stat_type { diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 09e25f975b25..17b54441b0e9 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -71,6 +71,42 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link) return 0; } +int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); + if (err) + return err; + + reg &= ~(PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL); + + switch (dup) { + case DUPLEX_HALF: + reg |= PORT_PCS_CTRL_FORCE_DUPLEX; + break; + case DUPLEX_FULL: + reg |= PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL; + break; + case DUPLEX_UNFORCED: + /* normal duplex detection */ + break; + default: + return -EINVAL; + } + + err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "%s %s duplex\n", + reg & PORT_PCS_CTRL_FORCE_DUPLEX ? "Force" : "Unforce", + reg & PORT_PCS_CTRL_DUPLEX_FULL ? "full" : "half"); + + return 0; +} + /* Offset 0x04: Port Control Register */ static const char * const mv88e6xxx_port_state_names[] = { diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 87e7249d516b..f73e90efa615 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -23,6 +23,8 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link); +int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup); + int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map); -- cgit v1.2.3 From a0a0f6229b81c6398b6614767a2e227c9224a38b Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:34 +0100 Subject: net: dsa: mv88e6xxx: add port's RGMII delay setter Some chips such as 88E6352 and 88E6390 can be programmed to add delays to RXCLK for IND inputs or to GTXCLK for OUTD outputs when port is in RGMII mode. Add a port function to program such delays according to the provided PHY interface mode. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 4 +++ drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 6 ++++ drivers/net/dsa/mv88e6xxx/port.c | 58 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 5 +++ 4 files changed, 73 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 49a69354b5b3..bb93d0aefb81 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3220,6 +3220,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -3238,6 +3239,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -3256,6 +3258,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3302,6 +3305,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index ab48eb996667..c7527c0c77cc 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -728,6 +728,12 @@ struct mv88e6xxx_ops { int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); + /* RGMII Receive/Transmit Timing Control + * Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise. + */ + int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode); + #define LINK_FORCED_DOWN 0 #define LINK_FORCED_UP 1 #define LINK_UNFORCED -2 diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 17b54441b0e9..838068d2b581 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -35,6 +35,64 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, * Link, Duplex and Flow Control have one force bit, one value bit. */ +static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); + if (err) + return err; + + reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK | + PORT_PCS_CTRL_RGMII_DELAY_TXCLK); + + switch (mode) { + case PHY_INTERFACE_MODE_RGMII_RXID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK; + break; + case PHY_INTERFACE_MODE_RGMII_ID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK | + PORT_PCS_CTRL_RGMII_DELAY_TXCLK; + break; + default: + /* no delay */ + break; + } + + err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n", + reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no", + reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no"); + + return 0; +} + +int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + if (port < 5) + return -EOPNOTSUPP; + + return mv88e6xxx_port_set_rgmii_delay(chip, port, mode); +} + +int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + if (port != 0) + return -EOPNOTSUPP; + + return mv88e6xxx_port_set_rgmii_delay(chip, port, mode); +} + int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link) { u16 reg; diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index f73e90efa615..3472b792ab59 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -21,6 +21,11 @@ int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, u16 val); +int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode); +int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode); + int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link); int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup); -- cgit v1.2.3 From 96a2b40c7bd32a955a47a4d521afa4940886f4e5 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:35 +0100 Subject: net: dsa: mv88e6xxx: add port's MAC speed setter While the two bits for link, duplex or RGMII delays are used the same way on chips supporting the said feature, the two bits for speed have different meaning for most of the chips out there. Speed value is stored in bits 1:0, 0x3 means unforce (normal detection). Some chips reuse values for alternative speeds when bit 12 is set. Newer chips with speed > 1Gbps reuse value 0x3 thus need a new bit 13. Here are the values to write in register 0x1 to (un)force speed: | Speed | 88E6065 | 88E6185 | 88E6352 | 88E6390 | 88E6390X | | ------- | ------- | ------- | ------- | ------- | -------- | | 10 | 0x0000 | 0x0000 | 0x0000 | 0x2000 | 0x2000 | | 100 | 0x0001 | 0x0001 | 0x0001 | 0x2001 | 0x2001 | | 200 | 0x0002 | NA | 0x1001 | 0x3001 | 0x3001 | | 1000 | NA | 0x0002 | 0x0002 | 0x2002 | 0x2002 | | 2500 | NA | NA | NA | 0x3003 | 0x3003 | | 10000 | NA | NA | NA | NA | 0x2003 | | unforce | 0x0003 | 0x0003 | 0x0003 | 0x0000 | 0x0000 | This patch implements a generic mv88e6xxx_port_set_speed() function used by chip-specific wrappers to filter supported ports and speeds. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 33 ++++++-- drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 24 +++++- drivers/net/dsa/mv88e6xxx/port.c | 138 ++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 6 ++ 4 files changed, 189 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index bb93d0aefb81..23c05e3c9ed5 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -725,7 +725,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_DUPLEX_FULL | PORT_PCS_CTRL_FORCE_DUPLEX | - PORT_PCS_CTRL_UNFORCED); + PORT_PCS_CTRL_SPEED_UNFORCED); reg |= PORT_PCS_CTRL_FORCE_LINK; if (phydev->link) @@ -736,13 +736,13 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, switch (phydev->speed) { case SPEED_1000: - reg |= PORT_PCS_CTRL_1000; + reg |= PORT_PCS_CTRL_SPEED_1000; break; case SPEED_100: - reg |= PORT_PCS_CTRL_100; + reg |= PORT_PCS_CTRL_SPEED_100; break; case SPEED_10: - reg |= PORT_PCS_CTRL_10; + reg |= PORT_PCS_CTRL_SPEED_10; break; default: pr_info("Unknown speed"); @@ -2421,17 +2421,17 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) */ err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { - reg &= ~PORT_PCS_CTRL_UNFORCED; + reg &= ~PORT_PCS_CTRL_SPEED_UNFORCED; reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP | PORT_PCS_CTRL_DUPLEX_FULL | PORT_PCS_CTRL_FORCE_DUPLEX; if (mv88e6xxx_6065_family(chip)) - reg |= PORT_PCS_CTRL_100; + reg |= PORT_PCS_CTRL_SPEED_100; else - reg |= PORT_PCS_CTRL_1000; + reg |= PORT_PCS_CTRL_SPEED_1000; } else { - reg |= PORT_PCS_CTRL_UNFORCED; + reg |= PORT_PCS_CTRL_SPEED_UNFORCED; } err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); @@ -3162,6 +3162,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6095_ops = { @@ -3170,6 +3171,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6123_ops = { @@ -3178,6 +3180,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6131_ops = { @@ -3186,6 +3189,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6161_ops = { @@ -3194,6 +3198,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6165_ops = { @@ -3202,6 +3207,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6171_ops = { @@ -3210,6 +3216,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6172_ops = { @@ -3221,6 +3228,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, + .port_set_speed = mv88e6352_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -3229,6 +3237,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6176_ops = { @@ -3240,6 +3249,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, + .port_set_speed = mv88e6352_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -3248,6 +3258,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -3259,6 +3270,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, + .port_set_speed = mv88e6352_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3269,6 +3281,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6321_ops = { @@ -3279,6 +3292,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6350_ops = { @@ -3287,6 +3301,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6351_ops = { @@ -3295,6 +3310,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6352_ops = { @@ -3306,6 +3322,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, + .port_set_speed = mv88e6352_port_set_speed, }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index c7527c0c77cc..929613021eff 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -61,16 +61,22 @@ #define PORT_PCS_CTRL 0x01 #define PORT_PCS_CTRL_RGMII_DELAY_RXCLK BIT(15) #define PORT_PCS_CTRL_RGMII_DELAY_TXCLK BIT(14) +#define PORT_PCS_CTRL_FORCE_SPEED BIT(13) /* 6390 */ +#define PORT_PCS_CTRL_ALTSPEED BIT(12) /* 6390 */ +#define PORT_PCS_CTRL_200BASE BIT(12) /* 6352 */ #define PORT_PCS_CTRL_FC BIT(7) #define PORT_PCS_CTRL_FORCE_FC BIT(6) #define PORT_PCS_CTRL_LINK_UP BIT(5) #define PORT_PCS_CTRL_FORCE_LINK BIT(4) #define PORT_PCS_CTRL_DUPLEX_FULL BIT(3) #define PORT_PCS_CTRL_FORCE_DUPLEX BIT(2) -#define PORT_PCS_CTRL_10 0x00 -#define PORT_PCS_CTRL_100 0x01 -#define PORT_PCS_CTRL_1000 0x02 -#define PORT_PCS_CTRL_UNFORCED 0x03 +#define PORT_PCS_CTRL_SPEED_MASK (0x03) +#define PORT_PCS_CTRL_SPEED_10 (0x00) +#define PORT_PCS_CTRL_SPEED_100 (0x01) +#define PORT_PCS_CTRL_SPEED_200 (0x02) /* 6065 and non Gb chips */ +#define PORT_PCS_CTRL_SPEED_1000 (0x02) +#define PORT_PCS_CTRL_SPEED_10000 (0x03) /* 6390X */ +#define PORT_PCS_CTRL_SPEED_UNFORCED (0x03) #define PORT_PAUSE_CTRL 0x02 #define PORT_SWITCH_ID 0x03 #define PORT_SWITCH_ID_PROD_NUM_6085 0x04a @@ -752,6 +758,16 @@ struct mv88e6xxx_ops { * or DUPLEX_UNFORCED for normal duplex detection. */ int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup); + +#define SPEED_MAX INT_MAX +#define SPEED_UNFORCED -2 + + /* Port's MAC speed (in Mbps) + * + * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid. + * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value. + */ + int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed); }; enum stat_type { diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 838068d2b581..18eeed083cbd 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -33,6 +33,10 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, /* Offset 0x01: MAC (or PCS or Physical) Control Register * * Link, Duplex and Flow Control have one force bit, one value bit. + * + * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value. + * Alternative values require the 200BASE (or AltSpeed) bit 12 set. + * Newer chips need a ForcedSpd bit 13 set to consider the value. */ static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, @@ -165,6 +169,140 @@ int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup) return 0; } +static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port, + int speed, bool alt_bit, bool force_bit) +{ + u16 reg, ctrl; + int err; + + switch (speed) { + case 10: + ctrl = PORT_PCS_CTRL_SPEED_10; + break; + case 100: + ctrl = PORT_PCS_CTRL_SPEED_100; + break; + case 200: + if (alt_bit) + ctrl = PORT_PCS_CTRL_SPEED_100 | PORT_PCS_CTRL_ALTSPEED; + else + ctrl = PORT_PCS_CTRL_SPEED_200; + break; + case 1000: + ctrl = PORT_PCS_CTRL_SPEED_1000; + break; + case 2500: + ctrl = PORT_PCS_CTRL_SPEED_1000 | PORT_PCS_CTRL_ALTSPEED; + break; + case 10000: + /* all bits set, fall through... */ + case SPEED_UNFORCED: + ctrl = PORT_PCS_CTRL_SPEED_UNFORCED; + break; + default: + return -EOPNOTSUPP; + } + + err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); + if (err) + return err; + + reg &= ~PORT_PCS_CTRL_SPEED_MASK; + if (alt_bit) + reg &= ~PORT_PCS_CTRL_ALTSPEED; + if (force_bit) { + reg &= ~PORT_PCS_CTRL_FORCE_SPEED; + if (speed) + ctrl |= PORT_PCS_CTRL_FORCE_SPEED; + } + reg |= ctrl; + + err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); + if (err) + return err; + + if (speed) + netdev_dbg(chip->ds->ports[port].netdev, + "Speed set to %d Mbps\n", speed); + else + netdev_dbg(chip->ds->ports[port].netdev, "Speed unforced\n"); + + return 0; +} + +/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */ +int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) +{ + if (speed == SPEED_MAX) + speed = 200; + + if (speed > 200) + return -EOPNOTSUPP; + + /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */ + return mv88e6xxx_port_set_speed(chip, port, speed, false, false); +} + +/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */ +int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) +{ + if (speed == SPEED_MAX) + speed = 1000; + + if (speed == 200 || speed > 1000) + return -EOPNOTSUPP; + + return mv88e6xxx_port_set_speed(chip, port, speed, false, false); +} + +/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */ +int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) +{ + if (speed == SPEED_MAX) + speed = 1000; + + if (speed > 1000) + return -EOPNOTSUPP; + + if (speed == 200 && port < 5) + return -EOPNOTSUPP; + + return mv88e6xxx_port_set_speed(chip, port, speed, true, false); +} + +/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */ +int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) +{ + if (speed == SPEED_MAX) + speed = port < 9 ? 1000 : 2500; + + if (speed > 2500) + return -EOPNOTSUPP; + + if (speed == 200 && port != 0) + return -EOPNOTSUPP; + + if (speed == 2500 && port < 9) + return -EOPNOTSUPP; + + return mv88e6xxx_port_set_speed(chip, port, speed, true, true); +} + +/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */ +int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) +{ + if (speed == SPEED_MAX) + speed = port < 9 ? 1000 : 10000; + + if (speed == 200 && port != 0) + return -EOPNOTSUPP; + + if (speed >= 2500 && port < 9) + return -EOPNOTSUPP; + + return mv88e6xxx_port_set_speed(chip, port, speed, true, true); +} + /* Offset 0x04: Port Control Register */ static const char * const mv88e6xxx_port_state_names[] = { diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 3472b792ab59..499129c1489c 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -30,6 +30,12 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link); int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup); +int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); +int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); +int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); +int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); +int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); + int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map); -- cgit v1.2.3 From d78343d2d796dbfe61450490b885782c72c820b5 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Nov 2016 03:23:36 +0100 Subject: net: dsa: mv88e6xxx: setup port's MAC Now that we have setters to configure the port's MAC, use them to refactor the port setup and adjust_link code. Note that port's MAC speed, duplex or RGMII delay must not be changed unless the port's link is forced down. So wrap all that in a mv88e6xxx_port_setup_mac function. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 140 +++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 23c05e3c9ed5..c8f824d4ff26 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -701,6 +701,47 @@ static bool mv88e6xxx_6352_family(struct mv88e6xxx_chip *chip) return chip->info->family == MV88E6XXX_FAMILY_6352; } +static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, + int link, int speed, int duplex, + phy_interface_t mode) +{ + int err; + + if (!chip->info->ops->port_set_link) + return 0; + + /* Port's MAC control must not be changed unless the link is down */ + err = chip->info->ops->port_set_link(chip, port, 0); + if (err) + return err; + + if (chip->info->ops->port_set_speed) { + err = chip->info->ops->port_set_speed(chip, port, speed); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + if (chip->info->ops->port_set_duplex) { + err = chip->info->ops->port_set_duplex(chip, port, duplex); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + if (chip->info->ops->port_set_rgmii_delay) { + err = chip->info->ops->port_set_rgmii_delay(chip, port, mode); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + err = 0; +restore_link: + if (chip->info->ops->port_set_link(chip, port, link)) + netdev_err(chip->ds->ports[port].netdev, + "failed to restore MAC's link\n"); + + return err; +} + /* We expect the switch to perform auto negotiation if there is a real * phy. However, in the case of a fixed link phy, we force the port * settings from the fixed link settings. @@ -709,64 +750,18 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phydev) { struct mv88e6xxx_chip *chip = ds->priv; - u16 reg; int err; if (!phy_is_pseudo_fixed_link(phydev)) return; mutex_lock(&chip->reg_lock); - - err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); - if (err) - goto out; - - reg &= ~(PORT_PCS_CTRL_LINK_UP | - PORT_PCS_CTRL_FORCE_LINK | - PORT_PCS_CTRL_DUPLEX_FULL | - PORT_PCS_CTRL_FORCE_DUPLEX | - PORT_PCS_CTRL_SPEED_UNFORCED); - - reg |= PORT_PCS_CTRL_FORCE_LINK; - if (phydev->link) - reg |= PORT_PCS_CTRL_LINK_UP; - - if (mv88e6xxx_6065_family(chip) && phydev->speed > SPEED_100) - goto out; - - switch (phydev->speed) { - case SPEED_1000: - reg |= PORT_PCS_CTRL_SPEED_1000; - break; - case SPEED_100: - reg |= PORT_PCS_CTRL_SPEED_100; - break; - case SPEED_10: - reg |= PORT_PCS_CTRL_SPEED_10; - break; - default: - pr_info("Unknown speed"); - goto out; - } - - reg |= PORT_PCS_CTRL_FORCE_DUPLEX; - if (phydev->duplex == DUPLEX_FULL) - reg |= PORT_PCS_CTRL_DUPLEX_FULL; - - if ((mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip)) && - (port >= mv88e6xxx_num_ports(chip) - 2)) { - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) - reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) - reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK | - PORT_PCS_CTRL_RGMII_DELAY_TXCLK); - } - mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); - -out: + err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed, + phydev->duplex, phydev->interface); mutex_unlock(&chip->reg_lock); + + if (err && err != -EOPNOTSUPP) + netdev_err(ds->ports[port].netdev, "failed to configure MAC\n"); } static int _mv88e6xxx_stats_wait(struct mv88e6xxx_chip *chip) @@ -2409,35 +2404,20 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) int err; u16 reg; - if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) || - mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) || - mv88e6xxx_6185_family(chip) || mv88e6xxx_6095_family(chip) || - mv88e6xxx_6065_family(chip) || mv88e6xxx_6320_family(chip)) { - /* MAC Forcing register: don't force link, speed, - * duplex or flow control state to any particular - * values on physical ports, but force the CPU port - * and all DSA ports to their maximum bandwidth and - * full duplex. - */ - err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); - if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { - reg &= ~PORT_PCS_CTRL_SPEED_UNFORCED; - reg |= PORT_PCS_CTRL_FORCE_LINK | - PORT_PCS_CTRL_LINK_UP | - PORT_PCS_CTRL_DUPLEX_FULL | - PORT_PCS_CTRL_FORCE_DUPLEX; - if (mv88e6xxx_6065_family(chip)) - reg |= PORT_PCS_CTRL_SPEED_100; - else - reg |= PORT_PCS_CTRL_SPEED_1000; - } else { - reg |= PORT_PCS_CTRL_SPEED_UNFORCED; - } - - err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); - if (err) - return err; - } + /* MAC Forcing register: don't force link, speed, duplex or flow control + * state to any particular values on physical ports, but force the CPU + * port and all DSA ports to their maximum bandwidth and full duplex. + */ + if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) + err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP, + SPEED_MAX, DUPLEX_FULL, + PHY_INTERFACE_MODE_NA); + else + err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, + SPEED_UNFORCED, DUPLEX_UNFORCED, + PHY_INTERFACE_MODE_NA); + if (err) + return err; /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock, * disable Header mode, enable IGMP/MLD snooping, disable VLAN -- cgit v1.2.3 From d9682c90cf5468bd7277d85ae7d80911f25c5edf Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:17:38 -0500 Subject: amd-xgbe: Fix formatting of PCS register dump Fix the length value used for the PCS register dump so that the full value can be displayed. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 84c5d296d13e..e9b01fc88098 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -1257,33 +1257,33 @@ static void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata) dev_dbg(dev, "\n************* PHY Reg dump **********************\n"); - dev_dbg(dev, "PCS Control Reg (%#04x) = %#04x\n", MDIO_CTRL1, + dev_dbg(dev, "PCS Control Reg (%#06x) = %#06x\n", MDIO_CTRL1, XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1)); - dev_dbg(dev, "PCS Status Reg (%#04x) = %#04x\n", MDIO_STAT1, + dev_dbg(dev, "PCS Status Reg (%#06x) = %#06x\n", MDIO_STAT1, XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1)); - dev_dbg(dev, "Phy Id (PHYS ID 1 %#04x)= %#04x\n", MDIO_DEVID1, + dev_dbg(dev, "Phy Id (PHYS ID 1 %#06x)= %#06x\n", MDIO_DEVID1, XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID1)); - dev_dbg(dev, "Phy Id (PHYS ID 2 %#04x)= %#04x\n", MDIO_DEVID2, + dev_dbg(dev, "Phy Id (PHYS ID 2 %#06x)= %#06x\n", MDIO_DEVID2, XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID2)); - dev_dbg(dev, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS1, + dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS1, XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS1)); - dev_dbg(dev, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS2, + dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS2, XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS2)); - dev_dbg(dev, "Auto-Neg Control Reg (%#04x) = %#04x\n", MDIO_CTRL1, + dev_dbg(dev, "Auto-Neg Control Reg (%#06x) = %#06x\n", MDIO_CTRL1, XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1)); - dev_dbg(dev, "Auto-Neg Status Reg (%#04x) = %#04x\n", MDIO_STAT1, + dev_dbg(dev, "Auto-Neg Status Reg (%#06x) = %#06x\n", MDIO_STAT1, XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_STAT1)); - dev_dbg(dev, "Auto-Neg Ad Reg 1 (%#04x) = %#04x\n", + dev_dbg(dev, "Auto-Neg Ad Reg 1 (%#06x) = %#06x\n", MDIO_AN_ADVERTISE, XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE)); - dev_dbg(dev, "Auto-Neg Ad Reg 2 (%#04x) = %#04x\n", + dev_dbg(dev, "Auto-Neg Ad Reg 2 (%#06x) = %#06x\n", MDIO_AN_ADVERTISE + 1, XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1)); - dev_dbg(dev, "Auto-Neg Ad Reg 3 (%#04x) = %#04x\n", + dev_dbg(dev, "Auto-Neg Ad Reg 3 (%#06x) = %#06x\n", MDIO_AN_ADVERTISE + 2, XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2)); - dev_dbg(dev, "Auto-Neg Completion Reg (%#04x) = %#04x\n", + dev_dbg(dev, "Auto-Neg Completion Reg (%#06x) = %#06x\n", MDIO_AN_COMP_STAT, XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_COMP_STAT)); -- cgit v1.2.3 From 586e3cfb260a0c6026321417bb5af331cc717f40 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:17:48 -0500 Subject: amd-xgbe: Prepare for priority-based FIFO allocation Currently, the Rx and Tx fifos are evenly allocated between the hardware queues of the device. As more queues are instantiated, the fifo memory needs to be able to be allocated based on queue priority. This allows for higher priority queues to have more fifo memory than lower priority queues. Prepare for this by modifying the current fifo calculation to assign the fifo queue allocation in an array that is then used to program the hardware. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 55 ++++++++++++++++++++++---------- drivers/net/ethernet/amd/xgbe/xgbe.h | 3 +- 2 files changed, 41 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 1babcc11a248..18f8001fdacd 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -2000,19 +2000,37 @@ static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata) XGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP); } -static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size, - unsigned int queue_count) +static unsigned int xgbe_get_tx_fifo_size(struct xgbe_prv_data *pdata) { - unsigned int q_fifo_size; - unsigned int p_fifo; + unsigned int fifo_size; /* Calculate the configured fifo size */ - q_fifo_size = 1 << (fifo_size + 7); + fifo_size = 1 << (pdata->hw_feat.tx_fifo_size + 7); /* The configured value may not be the actual amount of fifo RAM */ - q_fifo_size = min_t(unsigned int, XGBE_FIFO_MAX, q_fifo_size); + return min_t(unsigned int, XGMAC_FIFO_TX_MAX, fifo_size); +} + +static unsigned int xgbe_get_rx_fifo_size(struct xgbe_prv_data *pdata) +{ + unsigned int fifo_size; - q_fifo_size = q_fifo_size / queue_count; + /* Calculate the configured fifo size */ + fifo_size = 1 << (pdata->hw_feat.rx_fifo_size + 7); + + /* The configured value may not be the actual amount of fifo RAM */ + return min_t(unsigned int, XGMAC_FIFO_RX_MAX, fifo_size); +} + +static void xgbe_calculate_equal_fifo(unsigned int fifo_size, + unsigned int queue_count, + unsigned int *fifo) +{ + unsigned int q_fifo_size; + unsigned int p_fifo; + unsigned int i; + + q_fifo_size = fifo_size / queue_count; /* Each increment in the queue fifo size represents 256 bytes of * fifo, with 0 representing 256 bytes. Distribute the fifo equally @@ -2022,39 +2040,44 @@ static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size, if (p_fifo) p_fifo--; - return p_fifo; + for (i = 0; i < queue_count; i++) + fifo[i] = p_fifo; } static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata) { unsigned int fifo_size; + unsigned int fifo[XGBE_MAX_QUEUES]; unsigned int i; - fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size, - pdata->tx_q_count); + fifo_size = xgbe_get_tx_fifo_size(pdata); + + xgbe_calculate_equal_fifo(fifo_size, pdata->tx_q_count, fifo); for (i = 0; i < pdata->tx_q_count; i++) - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo_size); + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo[i]); netif_info(pdata, drv, pdata->netdev, "%d Tx hardware queues, %d byte fifo per queue\n", - pdata->tx_q_count, ((fifo_size + 1) * 256)); + pdata->tx_q_count, ((fifo[0] + 1) * 256)); } static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata) { unsigned int fifo_size; + unsigned int fifo[XGBE_MAX_QUEUES]; unsigned int i; - fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size, - pdata->rx_q_count); + fifo_size = xgbe_get_rx_fifo_size(pdata); + + xgbe_calculate_equal_fifo(fifo_size, pdata->rx_q_count, fifo); for (i = 0; i < pdata->rx_q_count; i++) - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo_size); + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo[i]); netif_info(pdata, drv, pdata->netdev, "%d Rx hardware queues, %d byte fifo per queue\n", - pdata->rx_q_count, ((fifo_size + 1) * 256)); + pdata->rx_q_count, ((fifo[0] + 1) * 256)); } static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 5dd17dcea2f8..d838b44a9952 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -208,7 +208,8 @@ #define XGMAC_DRIVER_CONTEXT 1 #define XGMAC_IOCTL_CONTEXT 2 -#define XGBE_FIFO_MAX 81920 +#define XGMAC_FIFO_RX_MAX 81920 +#define XGMAC_FIFO_TX_MAX 81920 #define XGBE_TC_MIN_QUANTUM 10 -- cgit v1.2.3 From 43e0dcf7084014258ed555690fd6653f689ec368 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:18:16 -0500 Subject: amd-xgbe: Perform priority-based hardware FIFO allocation Allocate the FIFO across the hardware Rx queues based on the priority of the queues. Giving more FIFO resources to queues with a higher priority. If PFC is active but not enabled for a queue, then less resources can allocated to the queue. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 547 +++++++++++++++++++++++-------- drivers/net/ethernet/amd/xgbe/xgbe.h | 26 ++ 2 files changed, 434 insertions(+), 139 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 18f8001fdacd..f8fffea6ced5 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -123,6 +123,11 @@ #include "xgbe.h" #include "xgbe-common.h" +static inline unsigned int xgbe_get_max_frame(struct xgbe_prv_data *pdata) +{ + return pdata->netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; +} + static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata, unsigned int usec) { @@ -491,6 +496,27 @@ static void xgbe_config_rss(struct xgbe_prv_data *pdata) "error configuring RSS, RSS disabled\n"); } +static bool xgbe_is_pfc_queue(struct xgbe_prv_data *pdata, + unsigned int queue) +{ + unsigned int prio, tc; + + for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) { + /* Does this queue handle the priority? */ + if (pdata->prio2q_map[prio] != queue) + continue; + + /* Get the Traffic Class for this priority */ + tc = pdata->ets->prio_tc[prio]; + + /* Check if PFC is enabled for this traffic class */ + if (pdata->pfc->pfc_en & (1 << tc)) + return true; + } + + return false; +} + static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata) { unsigned int max_q_count, q_count; @@ -528,27 +554,14 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata) for (i = 0; i < pdata->rx_q_count; i++) { unsigned int ehfc = 0; - if (pfc && ets) { - unsigned int prio; - - for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) { - unsigned int tc; - - /* Does this queue handle the priority? */ - if (pdata->prio2q_map[prio] != i) - continue; - - /* Get the Traffic Class for this priority */ - tc = ets->prio_tc[prio]; - - /* Check if flow control should be enabled */ - if (pfc->pfc_en & (1 << tc)) { + if (pdata->rx_rfd[i]) { + /* Flow control thresholds are established */ + if (pfc && ets) { + if (xgbe_is_pfc_queue(pdata, i)) ehfc = 1; - break; - } + } else { + ehfc = 1; } - } else { - ehfc = 1; } XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, ehfc); @@ -1327,106 +1340,6 @@ static int xgbe_config_tstamp(struct xgbe_prv_data *pdata, return 0; } -static void xgbe_config_tc(struct xgbe_prv_data *pdata) -{ - unsigned int offset, queue, prio; - u8 i; - - netdev_reset_tc(pdata->netdev); - if (!pdata->num_tcs) - return; - - netdev_set_num_tc(pdata->netdev, pdata->num_tcs); - - for (i = 0, queue = 0, offset = 0; i < pdata->num_tcs; i++) { - while ((queue < pdata->tx_q_count) && - (pdata->q2tc_map[queue] == i)) - queue++; - - netif_dbg(pdata, drv, pdata->netdev, "TC%u using TXq%u-%u\n", - i, offset, queue - 1); - netdev_set_tc_queue(pdata->netdev, i, queue - offset, offset); - offset = queue; - } - - if (!pdata->ets) - return; - - for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) - netdev_set_prio_tc_map(pdata->netdev, prio, - pdata->ets->prio_tc[prio]); -} - -static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata) -{ - struct ieee_ets *ets = pdata->ets; - unsigned int total_weight, min_weight, weight; - unsigned int mask, reg, reg_val; - unsigned int i, prio; - - if (!ets) - return; - - /* Set Tx to deficit weighted round robin scheduling algorithm (when - * traffic class is using ETS algorithm) - */ - XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_DWRR); - - /* Set Traffic Class algorithms */ - total_weight = pdata->netdev->mtu * pdata->hw_feat.tc_cnt; - min_weight = total_weight / 100; - if (!min_weight) - min_weight = 1; - - for (i = 0; i < pdata->hw_feat.tc_cnt; i++) { - /* Map the priorities to the traffic class */ - mask = 0; - for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) { - if (ets->prio_tc[prio] == i) - mask |= (1 << prio); - } - mask &= 0xff; - - netif_dbg(pdata, drv, pdata->netdev, "TC%u PRIO mask=%#x\n", - i, mask); - reg = MTL_TCPM0R + (MTL_TCPM_INC * (i / MTL_TCPM_TC_PER_REG)); - reg_val = XGMAC_IOREAD(pdata, reg); - - reg_val &= ~(0xff << ((i % MTL_TCPM_TC_PER_REG) << 3)); - reg_val |= (mask << ((i % MTL_TCPM_TC_PER_REG) << 3)); - - XGMAC_IOWRITE(pdata, reg, reg_val); - - /* Set the traffic class algorithm */ - switch (ets->tc_tsa[i]) { - case IEEE_8021QAZ_TSA_STRICT: - netif_dbg(pdata, drv, pdata->netdev, - "TC%u using SP\n", i); - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, - MTL_TSA_SP); - break; - case IEEE_8021QAZ_TSA_ETS: - weight = total_weight * ets->tc_tx_bw[i] / 100; - weight = clamp(weight, min_weight, total_weight); - - netif_dbg(pdata, drv, pdata->netdev, - "TC%u using DWRR (weight %u)\n", i, weight); - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, - MTL_TSA_ETS); - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW, - weight); - break; - } - } - - xgbe_config_tc(pdata); -} - -static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata) -{ - xgbe_config_flow_control(pdata); -} - static void xgbe_tx_start_xmit(struct xgbe_channel *channel, struct xgbe_ring *ring) { @@ -2000,6 +1913,96 @@ static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata) XGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP); } +static void xgbe_queue_flow_control_threshold(struct xgbe_prv_data *pdata, + unsigned int queue, + unsigned int q_fifo_size) +{ + unsigned int frame_fifo_size; + unsigned int rfa, rfd; + + frame_fifo_size = XGMAC_FLOW_CONTROL_ALIGN(xgbe_get_max_frame(pdata)); + + if (pdata->pfcq[queue] && (q_fifo_size > pdata->pfc_rfa)) { + /* PFC is active for this queue */ + rfa = pdata->pfc_rfa; + rfd = rfa + frame_fifo_size; + if (rfd > XGMAC_FLOW_CONTROL_MAX) + rfd = XGMAC_FLOW_CONTROL_MAX; + if (rfa >= XGMAC_FLOW_CONTROL_MAX) + rfa = XGMAC_FLOW_CONTROL_MAX - XGMAC_FLOW_CONTROL_UNIT; + } else { + /* This path deals with just maximum frame sizes which are + * limited to a jumbo frame of 9,000 (plus headers, etc.) + * so we can never exceed the maximum allowable RFA/RFD + * values. + */ + if (q_fifo_size <= 2048) { + /* rx_rfd to zero to signal no flow control */ + pdata->rx_rfa[queue] = 0; + pdata->rx_rfd[queue] = 0; + return; + } + + if (q_fifo_size <= 4096) { + /* Between 2048 and 4096 */ + pdata->rx_rfa[queue] = 0; /* Full - 1024 bytes */ + pdata->rx_rfd[queue] = 1; /* Full - 1536 bytes */ + return; + } + + if (q_fifo_size <= frame_fifo_size) { + /* Between 4096 and max-frame */ + pdata->rx_rfa[queue] = 2; /* Full - 2048 bytes */ + pdata->rx_rfd[queue] = 5; /* Full - 3584 bytes */ + return; + } + + if (q_fifo_size <= (frame_fifo_size * 3)) { + /* Between max-frame and 3 max-frames, + * trigger if we get just over a frame of data and + * resume when we have just under half a frame left. + */ + rfa = q_fifo_size - frame_fifo_size; + rfd = rfa + (frame_fifo_size / 2); + } else { + /* Above 3 max-frames - trigger when just over + * 2 frames of space available + */ + rfa = frame_fifo_size * 2; + rfa += XGMAC_FLOW_CONTROL_UNIT; + rfd = rfa + frame_fifo_size; + } + } + + pdata->rx_rfa[queue] = XGMAC_FLOW_CONTROL_VALUE(rfa); + pdata->rx_rfd[queue] = XGMAC_FLOW_CONTROL_VALUE(rfd); +} + +static void xgbe_calculate_flow_control_threshold(struct xgbe_prv_data *pdata, + unsigned int *fifo) +{ + unsigned int q_fifo_size; + unsigned int i; + + for (i = 0; i < pdata->rx_q_count; i++) { + q_fifo_size = (fifo[i] + 1) * XGMAC_FIFO_UNIT; + + xgbe_queue_flow_control_threshold(pdata, i, q_fifo_size); + } +} + +static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata) +{ + unsigned int i; + + for (i = 0; i < pdata->rx_q_count; i++) { + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFA, + pdata->rx_rfa[i]); + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFD, + pdata->rx_rfd[i]); + } +} + static unsigned int xgbe_get_tx_fifo_size(struct xgbe_prv_data *pdata) { unsigned int fifo_size; @@ -2032,18 +2035,158 @@ static void xgbe_calculate_equal_fifo(unsigned int fifo_size, q_fifo_size = fifo_size / queue_count; - /* Each increment in the queue fifo size represents 256 bytes of - * fifo, with 0 representing 256 bytes. Distribute the fifo equally - * between the queues. + /* Calculate the fifo setting by dividing the queue's fifo size + * by the fifo allocation increment (with 0 representing the + * base allocation increment so decrement the result by 1). */ - p_fifo = q_fifo_size / 256; + p_fifo = q_fifo_size / XGMAC_FIFO_UNIT; if (p_fifo) p_fifo--; + /* Distribute the fifo equally amongst the queues */ for (i = 0; i < queue_count; i++) fifo[i] = p_fifo; } +static unsigned int xgbe_set_nonprio_fifos(unsigned int fifo_size, + unsigned int queue_count, + unsigned int *fifo) +{ + unsigned int i; + + BUILD_BUG_ON_NOT_POWER_OF_2(XGMAC_FIFO_MIN_ALLOC); + + if (queue_count <= IEEE_8021QAZ_MAX_TCS) + return fifo_size; + + /* Rx queues 9 and up are for specialized packets, + * such as PTP or DCB control packets, etc. and + * don't require a large fifo + */ + for (i = IEEE_8021QAZ_MAX_TCS; i < queue_count; i++) { + fifo[i] = (XGMAC_FIFO_MIN_ALLOC / XGMAC_FIFO_UNIT) - 1; + fifo_size -= XGMAC_FIFO_MIN_ALLOC; + } + + return fifo_size; +} + +static unsigned int xgbe_get_pfc_delay(struct xgbe_prv_data *pdata) +{ + unsigned int delay; + + /* If a delay has been provided, use that */ + if (pdata->pfc->delay) + return pdata->pfc->delay / 8; + + /* Allow for two maximum size frames */ + delay = xgbe_get_max_frame(pdata); + delay += XGMAC_ETH_PREAMBLE; + delay *= 2; + + /* Allow for PFC frame */ + delay += XGMAC_PFC_DATA_LEN; + delay += ETH_HLEN + ETH_FCS_LEN; + delay += XGMAC_ETH_PREAMBLE; + + /* Allow for miscellaneous delays (LPI exit, cable, etc.) */ + delay += XGMAC_PFC_DELAYS; + + return delay; +} + +static unsigned int xgbe_get_pfc_queues(struct xgbe_prv_data *pdata) +{ + unsigned int count, prio_queues; + unsigned int i; + + if (!pdata->pfc->pfc_en) + return 0; + + count = 0; + prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count); + for (i = 0; i < prio_queues; i++) { + if (!xgbe_is_pfc_queue(pdata, i)) + continue; + + pdata->pfcq[i] = 1; + count++; + } + + return count; +} + +static void xgbe_calculate_dcb_fifo(struct xgbe_prv_data *pdata, + unsigned int fifo_size, + unsigned int *fifo) +{ + unsigned int q_fifo_size, rem_fifo, addn_fifo; + unsigned int prio_queues; + unsigned int pfc_count; + unsigned int i; + + q_fifo_size = XGMAC_FIFO_ALIGN(xgbe_get_max_frame(pdata)); + prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count); + pfc_count = xgbe_get_pfc_queues(pdata); + + if (!pfc_count || ((q_fifo_size * prio_queues) > fifo_size)) { + /* No traffic classes with PFC enabled or can't do lossless */ + xgbe_calculate_equal_fifo(fifo_size, prio_queues, fifo); + return; + } + + /* Calculate how much fifo we have to play with */ + rem_fifo = fifo_size - (q_fifo_size * prio_queues); + + /* Calculate how much more than base fifo PFC needs, which also + * becomes the threshold activation point (RFA) + */ + pdata->pfc_rfa = xgbe_get_pfc_delay(pdata); + pdata->pfc_rfa = XGMAC_FLOW_CONTROL_ALIGN(pdata->pfc_rfa); + + if (pdata->pfc_rfa > q_fifo_size) { + addn_fifo = pdata->pfc_rfa - q_fifo_size; + addn_fifo = XGMAC_FIFO_ALIGN(addn_fifo); + } else { + addn_fifo = 0; + } + + /* Calculate DCB fifo settings: + * - distribute remaining fifo between the VLAN priority + * queues based on traffic class PFC enablement and overall + * priority (0 is lowest priority, so start at highest) + */ + i = prio_queues; + while (i > 0) { + i--; + + fifo[i] = (q_fifo_size / XGMAC_FIFO_UNIT) - 1; + + if (!pdata->pfcq[i] || !addn_fifo) + continue; + + if (addn_fifo > rem_fifo) { + netdev_warn(pdata->netdev, + "RXq%u cannot set needed fifo size\n", i); + if (!rem_fifo) + continue; + + addn_fifo = rem_fifo; + } + + fifo[i] += (addn_fifo / XGMAC_FIFO_UNIT); + rem_fifo -= addn_fifo; + } + + if (rem_fifo) { + unsigned int inc_fifo = rem_fifo / prio_queues; + + /* Distribute remaining fifo across queues */ + for (i = 0; i < prio_queues; i++) + fifo[i] += (inc_fifo / XGMAC_FIFO_UNIT); + } +} + static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata) { unsigned int fifo_size; @@ -2059,25 +2202,50 @@ static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata) netif_info(pdata, drv, pdata->netdev, "%d Tx hardware queues, %d byte fifo per queue\n", - pdata->tx_q_count, ((fifo[0] + 1) * 256)); + pdata->tx_q_count, ((fifo[0] + 1) * XGMAC_FIFO_UNIT)); } static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata) { unsigned int fifo_size; unsigned int fifo[XGBE_MAX_QUEUES]; + unsigned int prio_queues; unsigned int i; + /* Clear any DCB related fifo/queue information */ + memset(pdata->pfcq, 0, sizeof(pdata->pfcq)); + pdata->pfc_rfa = 0; + fifo_size = xgbe_get_rx_fifo_size(pdata); + prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count); + + /* Assign a minimum fifo to the non-VLAN priority queues */ + fifo_size = xgbe_set_nonprio_fifos(fifo_size, pdata->rx_q_count, fifo); - xgbe_calculate_equal_fifo(fifo_size, pdata->rx_q_count, fifo); + if (pdata->pfc && pdata->ets) + xgbe_calculate_dcb_fifo(pdata, fifo_size, fifo); + else + xgbe_calculate_equal_fifo(fifo_size, prio_queues, fifo); for (i = 0; i < pdata->rx_q_count; i++) XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo[i]); - netif_info(pdata, drv, pdata->netdev, - "%d Rx hardware queues, %d byte fifo per queue\n", - pdata->rx_q_count, ((fifo[0] + 1) * 256)); + xgbe_calculate_flow_control_threshold(pdata, fifo); + xgbe_config_flow_control_threshold(pdata); + + if (pdata->pfc && pdata->ets && pdata->pfc->pfc_en) { + netif_info(pdata, drv, pdata->netdev, + "%u Rx hardware queues\n", pdata->rx_q_count); + for (i = 0; i < pdata->rx_q_count; i++) + netif_info(pdata, drv, pdata->netdev, + "RxQ%u, %u byte fifo queue\n", i, + ((fifo[i] + 1) * XGMAC_FIFO_UNIT)); + } else { + netif_info(pdata, drv, pdata->netdev, + "%u Rx hardware queues, %u byte fifo per queue\n", + pdata->rx_q_count, + ((fifo[0] + 1) * XGMAC_FIFO_UNIT)); + } } static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata) @@ -2113,8 +2281,7 @@ static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata) } /* Map the 8 VLAN priority values to available MTL Rx queues */ - prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS, - pdata->rx_q_count); + prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count); ppq = IEEE_8021QAZ_MAX_TCS / prio_queues; ppq_extra = IEEE_8021QAZ_MAX_TCS % prio_queues; @@ -2162,16 +2329,120 @@ static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata) } } -static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata) +static void xgbe_config_tc(struct xgbe_prv_data *pdata) { - unsigned int i; + unsigned int offset, queue, prio; + u8 i; - for (i = 0; i < pdata->rx_q_count; i++) { - /* Activate flow control when less than 4k left in fifo */ - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFA, 2); + netdev_reset_tc(pdata->netdev); + if (!pdata->num_tcs) + return; + + netdev_set_num_tc(pdata->netdev, pdata->num_tcs); + + for (i = 0, queue = 0, offset = 0; i < pdata->num_tcs; i++) { + while ((queue < pdata->tx_q_count) && + (pdata->q2tc_map[queue] == i)) + queue++; + + netif_dbg(pdata, drv, pdata->netdev, "TC%u using TXq%u-%u\n", + i, offset, queue - 1); + netdev_set_tc_queue(pdata->netdev, i, queue - offset, offset); + offset = queue; + } + + if (!pdata->ets) + return; + + for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) + netdev_set_prio_tc_map(pdata->netdev, prio, + pdata->ets->prio_tc[prio]); +} + +static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata) +{ + struct ieee_ets *ets = pdata->ets; + unsigned int total_weight, min_weight, weight; + unsigned int mask, reg, reg_val; + unsigned int i, prio; + + if (!ets) + return; + + /* Set Tx to deficit weighted round robin scheduling algorithm (when + * traffic class is using ETS algorithm) + */ + XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_DWRR); + + /* Set Traffic Class algorithms */ + total_weight = pdata->netdev->mtu * pdata->hw_feat.tc_cnt; + min_weight = total_weight / 100; + if (!min_weight) + min_weight = 1; + + for (i = 0; i < pdata->hw_feat.tc_cnt; i++) { + /* Map the priorities to the traffic class */ + mask = 0; + for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) { + if (ets->prio_tc[prio] == i) + mask |= (1 << prio); + } + mask &= 0xff; + + netif_dbg(pdata, drv, pdata->netdev, "TC%u PRIO mask=%#x\n", + i, mask); + reg = MTL_TCPM0R + (MTL_TCPM_INC * (i / MTL_TCPM_TC_PER_REG)); + reg_val = XGMAC_IOREAD(pdata, reg); - /* De-activate flow control when more than 6k left in fifo */ - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFD, 4); + reg_val &= ~(0xff << ((i % MTL_TCPM_TC_PER_REG) << 3)); + reg_val |= (mask << ((i % MTL_TCPM_TC_PER_REG) << 3)); + + XGMAC_IOWRITE(pdata, reg, reg_val); + + /* Set the traffic class algorithm */ + switch (ets->tc_tsa[i]) { + case IEEE_8021QAZ_TSA_STRICT: + netif_dbg(pdata, drv, pdata->netdev, + "TC%u using SP\n", i); + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, + MTL_TSA_SP); + break; + case IEEE_8021QAZ_TSA_ETS: + weight = total_weight * ets->tc_tx_bw[i] / 100; + weight = clamp(weight, min_weight, total_weight); + + netif_dbg(pdata, drv, pdata->netdev, + "TC%u using DWRR (weight %u)\n", i, weight); + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, + MTL_TSA_ETS); + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW, + weight); + break; + } + } + + xgbe_config_tc(pdata); +} + +static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata) +{ + if (!test_bit(XGBE_DOWN, &pdata->dev_state)) { + /* Just stop the Tx queues while Rx fifo is changed */ + netif_tx_stop_all_queues(pdata->netdev); + + /* Suspend Rx so that fifo's can be adjusted */ + pdata->hw_if.disable_rx(pdata); + } + + xgbe_config_rx_fifo_size(pdata); + xgbe_config_flow_control(pdata); + + if (!test_bit(XGBE_DOWN, &pdata->dev_state)) { + /* Resume Rx */ + pdata->hw_if.enable_rx(pdata); + + /* Resume Tx queues */ + netif_tx_start_all_queues(pdata->netdev); } } @@ -2879,12 +3150,10 @@ static int xgbe_init(struct xgbe_prv_data *pdata) xgbe_config_rx_threshold(pdata, pdata->rx_threshold); xgbe_config_tx_fifo_size(pdata); xgbe_config_rx_fifo_size(pdata); - xgbe_config_flow_control_threshold(pdata); /*TODO: Error Packet and undersized good Packet forwarding enable (FEP and FUP) */ xgbe_config_dcb_tc(pdata); - xgbe_config_dcb_pfc(pdata); xgbe_enable_mtl_interrupts(pdata); /* diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index d838b44a9952..a4e1b8d01491 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -158,6 +158,7 @@ #define XGBE_MAX_DMA_CHANNELS 16 #define XGBE_MAX_QUEUES 16 +#define XGBE_PRIORITY_QUEUES 8 #define XGBE_DMA_STOP_TIMEOUT 5 /* DMA cache settings - Outer sharable, write-back, write-allocate */ @@ -177,6 +178,13 @@ #define XGMAC_MAX_STD_PACKET 1518 #define XGMAC_JUMBO_PACKET_MTU 9000 #define XGMAC_MAX_JUMBO_PACKET 9018 +#define XGMAC_ETH_PREAMBLE (12 + 8) /* Inter-frame gap + preamble */ + +#define XGMAC_PFC_DATA_LEN 46 +#define XGMAC_PFC_DELAYS 14000 + +#define XGMAC_PRIO_QUEUES(_cnt) \ + min_t(unsigned int, IEEE_8021QAZ_MAX_TCS, (_cnt)) /* Common property names */ #define XGBE_MAC_ADDR_PROPERTY "mac-address" @@ -210,6 +218,12 @@ #define XGMAC_FIFO_RX_MAX 81920 #define XGMAC_FIFO_TX_MAX 81920 +#define XGMAC_FIFO_MIN_ALLOC 2048 +#define XGMAC_FIFO_UNIT 256 +#define XGMAC_FIFO_ALIGN(_x) \ + (((_x) + XGMAC_FIFO_UNIT - 1) & ~(XGMAC_FIFO_UNIT - 1)) +#define XGMAC_FIFO_FC_OFF 2048 +#define XGMAC_FIFO_FC_MIN 4096 #define XGBE_TC_MIN_QUANTUM 10 @@ -234,6 +248,14 @@ /* Flow control queue count */ #define XGMAC_MAX_FLOW_CONTROL_QUEUES 8 +/* Flow control threshold units */ +#define XGMAC_FLOW_CONTROL_UNIT 512 +#define XGMAC_FLOW_CONTROL_ALIGN(_x) \ + (((_x) + XGMAC_FLOW_CONTROL_UNIT - 1) & ~(XGMAC_FLOW_CONTROL_UNIT - 1)) +#define XGMAC_FLOW_CONTROL_VALUE(_x) \ + (((_x) < 1024) ? 0 : ((_x) / XGMAC_FLOW_CONTROL_UNIT) - 2) +#define XGMAC_FLOW_CONTROL_MAX 33280 + /* Maximum MAC address hash table size (256 bits = 8 bytes) */ #define XGBE_MAC_HASH_TABLE_SIZE 8 @@ -843,6 +865,8 @@ struct xgbe_prv_data { unsigned int pause_autoneg; unsigned int tx_pause; unsigned int rx_pause; + unsigned int rx_rfa[XGBE_MAX_QUEUES]; + unsigned int rx_rfd[XGBE_MAX_QUEUES]; /* Receive Side Scaling settings */ u8 rss_key[XGBE_RSS_HASH_KEY_SIZE]; @@ -882,6 +906,8 @@ struct xgbe_prv_data { struct ieee_pfc *pfc; unsigned int q2tc_map[XGBE_MAX_QUEUES]; unsigned int prio2q_map[IEEE_8021QAZ_MAX_TCS]; + unsigned int pfcq[XGBE_MAX_QUEUES]; + unsigned int pfc_rfa; u8 num_tcs; /* Hardware features of the device */ -- cgit v1.2.3 From e57f7a3feaef0e9e196801f1625bca1337405421 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:18:27 -0500 Subject: amd-xgbe: Prepare for working with more than one type of phy Prepare the code to be able to work with more than one type of phy by adding additional callable functions into the phy interface and removing phy specific settings/functions from non-phy related files. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/Makefile | 3 +- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 58 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 6 +- drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 19 +- drivers/net/ethernet/amd/xgbe/xgbe-main.c | 214 ++----- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 549 ++++++------------ drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c | 821 +++++++++++++++++++++++++++ drivers/net/ethernet/amd/xgbe/xgbe.h | 130 +++-- 8 files changed, 1140 insertions(+), 660 deletions(-) create mode 100644 drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/Makefile b/drivers/net/ethernet/amd/xgbe/Makefile index 171a7e68048d..60b4ae2f05fb 100644 --- a/drivers/net/ethernet/amd/xgbe/Makefile +++ b/drivers/net/ethernet/amd/xgbe/Makefile @@ -2,7 +2,8 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \ xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \ - xgbe-ptp.o + xgbe-ptp.o \ + xgbe-phy-v1.o amd-xgbe-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o amd-xgbe-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index f8fffea6ced5..75c3df1251c8 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -717,32 +717,26 @@ static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata) XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff); } -static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata) +static int xgbe_set_speed(struct xgbe_prv_data *pdata, int speed) { - if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x3) - return 0; - - XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3); - - return 0; -} - -static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata) -{ - if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x2) - return 0; + unsigned int ss; - XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2); - - return 0; -} - -static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata) -{ - if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0) - return 0; + switch (speed) { + case SPEED_1000: + ss = 0x03; + break; + case SPEED_2500: + ss = 0x02; + break; + case SPEED_10000: + ss = 0x00; + break; + default: + return -EINVAL; + } - XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0); + if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) != ss) + XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, ss); return 0; } @@ -2469,19 +2463,7 @@ static void xgbe_config_jumbo_enable(struct xgbe_prv_data *pdata) static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata) { - switch (pdata->phy_speed) { - case SPEED_10000: - xgbe_set_xgmii_speed(pdata); - break; - - case SPEED_2500: - xgbe_set_gmii_2500_speed(pdata); - break; - - case SPEED_1000: - xgbe_set_gmii_speed(pdata); - break; - } + xgbe_set_speed(pdata, pdata->phy_speed); } static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata) @@ -3195,9 +3177,7 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) hw_if->read_mmd_regs = xgbe_read_mmd_regs; hw_if->write_mmd_regs = xgbe_write_mmd_regs; - hw_if->set_gmii_speed = xgbe_set_gmii_speed; - hw_if->set_gmii_2500_speed = xgbe_set_gmii_2500_speed; - hw_if->set_xgmii_speed = xgbe_set_xgmii_speed; + hw_if->set_speed = xgbe_set_speed; hw_if->enable_tx = xgbe_enable_tx; hw_if->disable_tx = xgbe_disable_tx; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index c4e668208e04..dd166a003572 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -778,7 +778,7 @@ static void xgbe_free_rx_data(struct xgbe_prv_data *pdata) DBGPR("<--xgbe_free_rx_data\n"); } -static int xgbe_phy_init(struct xgbe_prv_data *pdata) +static int xgbe_phy_reset(struct xgbe_prv_data *pdata) { pdata->phy_link = -1; pdata->phy_speed = SPEED_UNKNOWN; @@ -1292,8 +1292,8 @@ static int xgbe_open(struct net_device *netdev) DBGPR("-->xgbe_open\n"); - /* Initialize the phy */ - ret = xgbe_phy_init(pdata); + /* Reset the phy settings */ + ret = xgbe_phy_reset(pdata); if (ret) return ret; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 4007b429c80c..46c959b994a7 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -316,24 +316,7 @@ static int xgbe_set_settings(struct net_device *netdev, } if (cmd->autoneg == AUTONEG_DISABLE) { - switch (speed) { - case SPEED_10000: - break; - case SPEED_2500: - if (pdata->speed_set != XGBE_SPEEDSET_2500_10000) { - netdev_err(netdev, "unsupported speed %u\n", - speed); - return -EINVAL; - } - break; - case SPEED_1000: - if (pdata->speed_set != XGBE_SPEEDSET_1000_10000) { - netdev_err(netdev, "unsupported speed %u\n", - speed); - return -EINVAL; - } - break; - default: + if (!pdata->phy_if.phy_valid_speed(pdata, speed)) { netdev_err(netdev, "unsupported speed %u\n", speed); return -EINVAL; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 6997f1110ece..38c5985c52ef 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -125,6 +125,7 @@ #include #include #include +#include #include #include #include @@ -145,42 +146,6 @@ MODULE_PARM_DESC(debug, " Network interface message level setting"); static const u32 default_msg_level = (NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP); -static const u32 xgbe_serdes_blwc[] = { - XGBE_SPEED_1000_BLWC, - XGBE_SPEED_2500_BLWC, - XGBE_SPEED_10000_BLWC, -}; - -static const u32 xgbe_serdes_cdr_rate[] = { - XGBE_SPEED_1000_CDR, - XGBE_SPEED_2500_CDR, - XGBE_SPEED_10000_CDR, -}; - -static const u32 xgbe_serdes_pq_skew[] = { - XGBE_SPEED_1000_PQ, - XGBE_SPEED_2500_PQ, - XGBE_SPEED_10000_PQ, -}; - -static const u32 xgbe_serdes_tx_amp[] = { - XGBE_SPEED_1000_TXAMP, - XGBE_SPEED_2500_TXAMP, - XGBE_SPEED_10000_TXAMP, -}; - -static const u32 xgbe_serdes_dfe_tap_cfg[] = { - XGBE_SPEED_1000_DFE_TAP_CONFIG, - XGBE_SPEED_2500_DFE_TAP_CONFIG, - XGBE_SPEED_10000_DFE_TAP_CONFIG, -}; - -static const u32 xgbe_serdes_dfe_tap_ena[] = { - XGBE_SPEED_1000_DFE_TAP_ENABLE, - XGBE_SPEED_2500_DFE_TAP_ENABLE, - XGBE_SPEED_10000_DFE_TAP_ENABLE, -}; - static void xgbe_default_config(struct xgbe_prv_data *pdata) { DBGPR("-->xgbe_default_config\n"); @@ -207,9 +172,22 @@ static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata) xgbe_init_function_ptrs_dev(&pdata->hw_if); xgbe_init_function_ptrs_phy(&pdata->phy_if); xgbe_init_function_ptrs_desc(&pdata->desc_if); + + pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if); } #ifdef CONFIG_ACPI +static const struct acpi_device_id xgbe_acpi_match[]; + +static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(xgbe_acpi_match, pdata->dev); + + return id ? (struct xgbe_version_data *)id->driver_data : NULL; +} + static int xgbe_acpi_support(struct xgbe_prv_data *pdata) { struct device *dev = pdata->dev; @@ -237,6 +215,11 @@ static int xgbe_acpi_support(struct xgbe_prv_data *pdata) return 0; } #else /* CONFIG_ACPI */ +static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata) +{ + return NULL; +} + static int xgbe_acpi_support(struct xgbe_prv_data *pdata) { return -EINVAL; @@ -244,6 +227,17 @@ static int xgbe_acpi_support(struct xgbe_prv_data *pdata) #endif /* CONFIG_ACPI */ #ifdef CONFIG_OF +static const struct of_device_id xgbe_of_match[]; + +static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata) +{ + const struct of_device_id *id; + + id = of_match_device(xgbe_of_match, pdata->dev); + + return id ? (struct xgbe_version_data *)id->data : NULL; +} + static int xgbe_of_support(struct xgbe_prv_data *pdata) { struct device *dev = pdata->dev; @@ -292,6 +286,11 @@ static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata) return phy_pdev; } #else /* CONFIG_OF */ +static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata) +{ + return NULL; +} + static int xgbe_of_support(struct xgbe_prv_data *pdata) { return -EINVAL; @@ -333,11 +332,17 @@ static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata) return phy_pdev; } +static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata) +{ + return pdata->use_acpi ? xgbe_acpi_vdata(pdata) + : xgbe_of_vdata(pdata); +} + static int xgbe_probe(struct platform_device *pdev) { struct xgbe_prv_data *pdata; struct net_device *netdev; - struct device *dev = &pdev->dev, *phy_dev; + struct device *dev = &pdev->dev; struct platform_device *phy_pdev; struct resource *res; const char *phy_mode; @@ -374,13 +379,17 @@ static int xgbe_probe(struct platform_device *pdev) /* Check if we should use ACPI or DT */ pdata->use_acpi = dev->of_node ? 0 : 1; + /* Get the version data */ + pdata->vdata = xgbe_get_vdata(pdata); + phy_pdev = xgbe_get_phy_pdev(pdata); if (!phy_pdev) { dev_err(dev, "unable to obtain phy device\n"); ret = -EINVAL; goto err_phydev; } - phy_dev = &phy_pdev->dev; + pdata->phy_pdev = phy_pdev; + pdata->phy_dev = &phy_pdev->dev; if (pdev == phy_pdev) { /* New style device tree or ACPI: @@ -492,115 +501,6 @@ static int xgbe_probe(struct platform_device *pdev) if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY)) pdata->per_channel_irq = 1; - /* Retrieve the PHY speedset */ - ret = device_property_read_u32(phy_dev, XGBE_SPEEDSET_PROPERTY, - &pdata->speed_set); - if (ret) { - dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY); - goto err_io; - } - - switch (pdata->speed_set) { - case XGBE_SPEEDSET_1000_10000: - case XGBE_SPEEDSET_2500_10000: - break; - default: - dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY); - ret = -EINVAL; - goto err_io; - } - - /* Retrieve the PHY configuration properties */ - if (device_property_present(phy_dev, XGBE_BLWC_PROPERTY)) { - ret = device_property_read_u32_array(phy_dev, - XGBE_BLWC_PROPERTY, - pdata->serdes_blwc, - XGBE_SPEEDS); - if (ret) { - dev_err(dev, "invalid %s property\n", - XGBE_BLWC_PROPERTY); - goto err_io; - } - } else { - memcpy(pdata->serdes_blwc, xgbe_serdes_blwc, - sizeof(pdata->serdes_blwc)); - } - - if (device_property_present(phy_dev, XGBE_CDR_RATE_PROPERTY)) { - ret = device_property_read_u32_array(phy_dev, - XGBE_CDR_RATE_PROPERTY, - pdata->serdes_cdr_rate, - XGBE_SPEEDS); - if (ret) { - dev_err(dev, "invalid %s property\n", - XGBE_CDR_RATE_PROPERTY); - goto err_io; - } - } else { - memcpy(pdata->serdes_cdr_rate, xgbe_serdes_cdr_rate, - sizeof(pdata->serdes_cdr_rate)); - } - - if (device_property_present(phy_dev, XGBE_PQ_SKEW_PROPERTY)) { - ret = device_property_read_u32_array(phy_dev, - XGBE_PQ_SKEW_PROPERTY, - pdata->serdes_pq_skew, - XGBE_SPEEDS); - if (ret) { - dev_err(dev, "invalid %s property\n", - XGBE_PQ_SKEW_PROPERTY); - goto err_io; - } - } else { - memcpy(pdata->serdes_pq_skew, xgbe_serdes_pq_skew, - sizeof(pdata->serdes_pq_skew)); - } - - if (device_property_present(phy_dev, XGBE_TX_AMP_PROPERTY)) { - ret = device_property_read_u32_array(phy_dev, - XGBE_TX_AMP_PROPERTY, - pdata->serdes_tx_amp, - XGBE_SPEEDS); - if (ret) { - dev_err(dev, "invalid %s property\n", - XGBE_TX_AMP_PROPERTY); - goto err_io; - } - } else { - memcpy(pdata->serdes_tx_amp, xgbe_serdes_tx_amp, - sizeof(pdata->serdes_tx_amp)); - } - - if (device_property_present(phy_dev, XGBE_DFE_CFG_PROPERTY)) { - ret = device_property_read_u32_array(phy_dev, - XGBE_DFE_CFG_PROPERTY, - pdata->serdes_dfe_tap_cfg, - XGBE_SPEEDS); - if (ret) { - dev_err(dev, "invalid %s property\n", - XGBE_DFE_CFG_PROPERTY); - goto err_io; - } - } else { - memcpy(pdata->serdes_dfe_tap_cfg, xgbe_serdes_dfe_tap_cfg, - sizeof(pdata->serdes_dfe_tap_cfg)); - } - - if (device_property_present(phy_dev, XGBE_DFE_ENA_PROPERTY)) { - ret = device_property_read_u32_array(phy_dev, - XGBE_DFE_ENA_PROPERTY, - pdata->serdes_dfe_tap_ena, - XGBE_SPEEDS); - if (ret) { - dev_err(dev, "invalid %s property\n", - XGBE_DFE_ENA_PROPERTY); - goto err_io; - } - } else { - memcpy(pdata->serdes_dfe_tap_ena, xgbe_serdes_dfe_tap_ena, - sizeof(pdata->serdes_dfe_tap_ena)); - } - /* Obtain device settings unique to ACPI/OF */ if (pdata->use_acpi) ret = xgbe_acpi_support(pdata); @@ -705,7 +605,9 @@ static int xgbe_probe(struct platform_device *pdev) XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); /* Call MDIO/PHY initialization routine */ - pdata->phy_if.phy_init(pdata); + ret = pdata->phy_if.phy_init(pdata); + if (ret) + goto err_io; /* Set device operations */ netdev->netdev_ops = xgbe_get_netdev_ops(); @@ -780,8 +682,6 @@ static int xgbe_probe(struct platform_device *pdev) xgbe_debugfs_init(pdata); - platform_device_put(phy_pdev); - netdev_notice(netdev, "net device enabled\n"); DBGPR("<-- xgbe_probe\n"); @@ -817,6 +717,8 @@ static int xgbe_remove(struct platform_device *pdev) xgbe_ptp_unregister(pdata); + pdata->phy_if.phy_exit(pdata); + flush_workqueue(pdata->an_workqueue); destroy_workqueue(pdata->an_workqueue); @@ -825,6 +727,8 @@ static int xgbe_remove(struct platform_device *pdev) unregister_netdev(netdev); + platform_device_put(pdata->phy_pdev); + free_netdev(netdev); DBGPR("<--xgbe_remove\n"); @@ -879,9 +783,14 @@ static int xgbe_resume(struct device *dev) } #endif /* CONFIG_PM */ +static const struct xgbe_version_data xgbe_v1 = { + .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1, +}; + #ifdef CONFIG_ACPI static const struct acpi_device_id xgbe_acpi_match[] = { - { "AMDI8001", 0 }, + { .id = "AMDI8001", + .driver_data = (kernel_ulong_t)&xgbe_v1 }, {}, }; @@ -890,7 +799,8 @@ MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match); #ifdef CONFIG_OF static const struct of_device_id xgbe_of_match[] = { - { .compatible = "amd,xgbe-seattle-v1a", }, + { .compatible = "amd,xgbe-seattle-v1a", + .data = &xgbe_v1 }, {}, }; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index e9b01fc88098..35c302f7889c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -145,280 +145,91 @@ static void xgbe_an_disable_kr_training(struct xgbe_prv_data *pdata) XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); } -static void xgbe_pcs_power_cycle(struct xgbe_prv_data *pdata) +static void xgbe_kr_mode(struct xgbe_prv_data *pdata) { - unsigned int reg; - - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); - - reg |= MDIO_CTRL1_LPOWER; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); - - usleep_range(75, 100); - - reg &= ~MDIO_CTRL1_LPOWER; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); -} - -static void xgbe_serdes_start_ratechange(struct xgbe_prv_data *pdata) -{ - /* Assert Rx and Tx ratechange */ - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1); -} - -static void xgbe_serdes_complete_ratechange(struct xgbe_prv_data *pdata) -{ - unsigned int wait; - u16 status; - - /* Release Rx and Tx ratechange */ - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0); - - /* Wait for Rx and Tx ready */ - wait = XGBE_RATECHANGE_COUNT; - while (wait--) { - usleep_range(50, 75); - - status = XSIR0_IOREAD(pdata, SIR0_STATUS); - if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) && - XSIR_GET_BITS(status, SIR0_STATUS, TX_READY)) - goto rx_reset; - } - - netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n", - status); - -rx_reset: - /* Perform Rx reset for the DFE changes */ - XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1); -} - -static void xgbe_xgmii_mode(struct xgbe_prv_data *pdata) -{ - unsigned int reg; - /* Enable KR training */ xgbe_an_enable_kr_training(pdata); /* Set MAC to 10G speed */ - pdata->hw_if.set_xgmii_speed(pdata); - - /* Set PCS to KR/10G speed */ - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); - reg &= ~MDIO_PCS_CTRL2_TYPE; - reg |= MDIO_PCS_CTRL2_10GBR; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); - - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); - reg &= ~MDIO_CTRL1_SPEEDSEL; - reg |= MDIO_CTRL1_SPEED10G; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); - - xgbe_pcs_power_cycle(pdata); - - /* Set SerDes to 10G speed */ - xgbe_serdes_start_ratechange(pdata); - - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL); - - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, - pdata->serdes_cdr_rate[XGBE_SPEED_10000]); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, - pdata->serdes_tx_amp[XGBE_SPEED_10000]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, - pdata->serdes_blwc[XGBE_SPEED_10000]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, - pdata->serdes_pq_skew[XGBE_SPEED_10000]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, - pdata->serdes_dfe_tap_cfg[XGBE_SPEED_10000]); - XRXTX_IOWRITE(pdata, RXTX_REG22, - pdata->serdes_dfe_tap_ena[XGBE_SPEED_10000]); - - xgbe_serdes_complete_ratechange(pdata); - - netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n"); + pdata->hw_if.set_speed(pdata, SPEED_10000); + + /* Call PHY implementation support to complete rate change */ + pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR); } -static void xgbe_gmii_2500_mode(struct xgbe_prv_data *pdata) +static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata) { - unsigned int reg; - /* Disable KR training */ xgbe_an_disable_kr_training(pdata); /* Set MAC to 2.5G speed */ - pdata->hw_if.set_gmii_2500_speed(pdata); - - /* Set PCS to KX/1G speed */ - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); - reg &= ~MDIO_PCS_CTRL2_TYPE; - reg |= MDIO_PCS_CTRL2_10GBX; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); - - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); - reg &= ~MDIO_CTRL1_SPEEDSEL; - reg |= MDIO_CTRL1_SPEED1G; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); - - xgbe_pcs_power_cycle(pdata); - - /* Set SerDes to 2.5G speed */ - xgbe_serdes_start_ratechange(pdata); - - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL); - - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, - pdata->serdes_cdr_rate[XGBE_SPEED_2500]); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, - pdata->serdes_tx_amp[XGBE_SPEED_2500]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, - pdata->serdes_blwc[XGBE_SPEED_2500]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, - pdata->serdes_pq_skew[XGBE_SPEED_2500]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, - pdata->serdes_dfe_tap_cfg[XGBE_SPEED_2500]); - XRXTX_IOWRITE(pdata, RXTX_REG22, - pdata->serdes_dfe_tap_ena[XGBE_SPEED_2500]); - - xgbe_serdes_complete_ratechange(pdata); - - netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n"); + pdata->hw_if.set_speed(pdata, SPEED_2500); + + /* Call PHY implementation support to complete rate change */ + pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500); } -static void xgbe_gmii_mode(struct xgbe_prv_data *pdata) +static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata) { - unsigned int reg; - /* Disable KR training */ xgbe_an_disable_kr_training(pdata); /* Set MAC to 1G speed */ - pdata->hw_if.set_gmii_speed(pdata); - - /* Set PCS to KX/1G speed */ - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); - reg &= ~MDIO_PCS_CTRL2_TYPE; - reg |= MDIO_PCS_CTRL2_10GBX; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); - - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); - reg &= ~MDIO_CTRL1_SPEEDSEL; - reg |= MDIO_CTRL1_SPEED1G; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); - - xgbe_pcs_power_cycle(pdata); - - /* Set SerDes to 1G speed */ - xgbe_serdes_start_ratechange(pdata); - - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL); - - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, - pdata->serdes_cdr_rate[XGBE_SPEED_1000]); - XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, - pdata->serdes_tx_amp[XGBE_SPEED_1000]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, - pdata->serdes_blwc[XGBE_SPEED_1000]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, - pdata->serdes_pq_skew[XGBE_SPEED_1000]); - XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, - pdata->serdes_dfe_tap_cfg[XGBE_SPEED_1000]); - XRXTX_IOWRITE(pdata, RXTX_REG22, - pdata->serdes_dfe_tap_ena[XGBE_SPEED_1000]); - - xgbe_serdes_complete_ratechange(pdata); - - netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n"); + pdata->hw_if.set_speed(pdata, SPEED_1000); + + /* Call PHY implementation support to complete rate change */ + pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000); } -static void xgbe_cur_mode(struct xgbe_prv_data *pdata, - enum xgbe_mode *mode) +static enum xgbe_mode xgbe_cur_mode(struct xgbe_prv_data *pdata) { - unsigned int reg; - - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); - if ((reg & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR) - *mode = XGBE_MODE_KR; - else - *mode = XGBE_MODE_KX; + return pdata->phy_if.phy_impl.cur_mode(pdata); } static bool xgbe_in_kr_mode(struct xgbe_prv_data *pdata) { - enum xgbe_mode mode; - - xgbe_cur_mode(pdata, &mode); - - return (mode == XGBE_MODE_KR); + return (xgbe_cur_mode(pdata) == XGBE_MODE_KR); } -static void xgbe_switch_mode(struct xgbe_prv_data *pdata) +static void xgbe_change_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) { - /* If we are in KR switch to KX, and vice-versa */ - if (xgbe_in_kr_mode(pdata)) { - if (pdata->speed_set == XGBE_SPEEDSET_1000_10000) - xgbe_gmii_mode(pdata); - else - xgbe_gmii_2500_mode(pdata); - } else { - xgbe_xgmii_mode(pdata); + switch (mode) { + case XGBE_MODE_KX_1000: + xgbe_kx_1000_mode(pdata); + break; + case XGBE_MODE_KX_2500: + xgbe_kx_2500_mode(pdata); + break; + case XGBE_MODE_KR: + xgbe_kr_mode(pdata); + break; + case XGBE_MODE_UNKNOWN: + break; + default: + netif_dbg(pdata, link, pdata->netdev, + "invalid operation mode requested (%u)\n", mode); } } -static void xgbe_set_mode(struct xgbe_prv_data *pdata, - enum xgbe_mode mode) -{ - enum xgbe_mode cur_mode; - - xgbe_cur_mode(pdata, &cur_mode); - if (mode != cur_mode) - xgbe_switch_mode(pdata); -} - -static bool xgbe_use_xgmii_mode(struct xgbe_prv_data *pdata) +static void xgbe_switch_mode(struct xgbe_prv_data *pdata) { - if (pdata->phy.autoneg == AUTONEG_ENABLE) { - if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) - return true; - } else { - if (pdata->phy.speed == SPEED_10000) - return true; - } - - return false; + xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata)); } -static bool xgbe_use_gmii_2500_mode(struct xgbe_prv_data *pdata) +static void xgbe_set_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) { - if (pdata->phy.autoneg == AUTONEG_ENABLE) { - if (pdata->phy.advertising & ADVERTISED_2500baseX_Full) - return true; - } else { - if (pdata->phy.speed == SPEED_2500) - return true; - } + if (mode == xgbe_cur_mode(pdata)) + return; - return false; + xgbe_change_mode(pdata, mode); } -static bool xgbe_use_gmii_mode(struct xgbe_prv_data *pdata) +static bool xgbe_use_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) { - if (pdata->phy.autoneg == AUTONEG_ENABLE) { - if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full) - return true; - } else { - if (pdata->phy.speed == SPEED_1000) - return true; - } - - return false; + return pdata->phy_if.phy_impl.use_mode(pdata, mode); } static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart) @@ -476,13 +287,15 @@ static enum xgbe_an xgbe_an_tx_training(struct xgbe_prv_data *pdata, /* Start KR training */ reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); if (reg & XGBE_KR_TRAINING_ENABLE) { - XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1); + if (pdata->phy_if.phy_impl.kr_training_pre) + pdata->phy_if.phy_impl.kr_training_pre(pdata); reg |= XGBE_KR_TRAINING_START; XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); - XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0); + if (pdata->phy_if.phy_impl.kr_training_post) + pdata->phy_if.phy_impl.kr_training_post(pdata); netif_dbg(pdata, link, pdata->netdev, "KR training initiated\n"); @@ -571,7 +384,7 @@ static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata) } state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state - : &pdata->kx_state; + : &pdata->kx_state; switch (*state) { case XGBE_RX_BPA: @@ -907,24 +720,28 @@ static void xgbe_phy_adjust_link(struct xgbe_prv_data *pdata) xgbe_phy_print_status(pdata); } +static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed) +{ + return pdata->phy_if.phy_impl.valid_speed(pdata, speed); +} + static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata) { + enum xgbe_mode mode; + netif_dbg(pdata, link, pdata->netdev, "fixed PHY configuration\n"); /* Disable auto-negotiation */ xgbe_disable_an(pdata); - /* Validate/Set specified speed */ - switch (pdata->phy.speed) { - case SPEED_10000: - xgbe_set_mode(pdata, XGBE_MODE_KR); - break; - - case SPEED_2500: - case SPEED_1000: - xgbe_set_mode(pdata, XGBE_MODE_KX); + /* Set specified mode for specified speed */ + mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed); + switch (mode) { + case XGBE_MODE_KX_1000: + case XGBE_MODE_KX_2500: + case XGBE_MODE_KR: break; - + case XGBE_MODE_UNKNOWN: default: return -EINVAL; } @@ -933,6 +750,8 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata) if (pdata->phy.duplex != DUPLEX_FULL) return -EINVAL; + xgbe_set_mode(pdata, mode); + return 0; } @@ -950,11 +769,12 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) disable_irq(pdata->an_irq); /* Start auto-negotiation in a supported mode */ - if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) { + if (xgbe_use_mode(pdata, XGBE_MODE_KR)) { xgbe_set_mode(pdata, XGBE_MODE_KR); - } else if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) || - (pdata->phy.advertising & ADVERTISED_2500baseX_Full)) { - xgbe_set_mode(pdata, XGBE_MODE_KX); + } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) { + xgbe_set_mode(pdata, XGBE_MODE_KX_2500); + } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) { + xgbe_set_mode(pdata, XGBE_MODE_KX_1000); } else { enable_irq(pdata->an_irq); return -EINVAL; @@ -1016,108 +836,45 @@ static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata) } } -static void xgbe_phy_status_force(struct xgbe_prv_data *pdata) +static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata) { - if (xgbe_in_kr_mode(pdata)) { - pdata->phy.speed = SPEED_10000; - } else { - switch (pdata->speed_set) { - case XGBE_SPEEDSET_1000_10000: - pdata->phy.speed = SPEED_1000; - break; - - case XGBE_SPEEDSET_2500_10000: - pdata->phy.speed = SPEED_2500; - break; - } - } - pdata->phy.duplex = DUPLEX_FULL; + return pdata->phy_if.phy_impl.an_outcome(pdata); } -static void xgbe_phy_status_aneg(struct xgbe_prv_data *pdata) +static void xgbe_phy_status_result(struct xgbe_prv_data *pdata) { - unsigned int ad_reg, lp_reg; + enum xgbe_mode mode; pdata->phy.lp_advertising = 0; if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect) - return xgbe_phy_status_force(pdata); - - pdata->phy.lp_advertising |= ADVERTISED_Autoneg; - pdata->phy.lp_advertising |= ADVERTISED_Backplane; - - /* Compare Advertisement and Link Partner register 1 */ - ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); - lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA); - if (lp_reg & 0x400) - pdata->phy.lp_advertising |= ADVERTISED_Pause; - if (lp_reg & 0x800) - pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; - - if (pdata->phy.pause_autoneg) { - /* Set flow control based on auto-negotiation result */ - pdata->phy.tx_pause = 0; - pdata->phy.rx_pause = 0; - - if (ad_reg & lp_reg & 0x400) { - pdata->phy.tx_pause = 1; - pdata->phy.rx_pause = 1; - } else if (ad_reg & lp_reg & 0x800) { - if (ad_reg & 0x400) - pdata->phy.rx_pause = 1; - else if (lp_reg & 0x400) - pdata->phy.tx_pause = 1; - } - } - - /* Compare Advertisement and Link Partner register 2 */ - ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); - lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); - if (lp_reg & 0x80) - pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; - if (lp_reg & 0x20) { - switch (pdata->speed_set) { - case XGBE_SPEEDSET_1000_10000: - pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; - break; - case XGBE_SPEEDSET_2500_10000: - pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full; - break; - } - } + mode = xgbe_cur_mode(pdata); + else + mode = xgbe_phy_status_aneg(pdata); - ad_reg &= lp_reg; - if (ad_reg & 0x80) { + switch (mode) { + case XGBE_MODE_KX_1000: + pdata->phy.speed = SPEED_1000; + break; + case XGBE_MODE_KX_2500: + pdata->phy.speed = SPEED_2500; + break; + case XGBE_MODE_KR: pdata->phy.speed = SPEED_10000; - xgbe_set_mode(pdata, XGBE_MODE_KR); - } else if (ad_reg & 0x20) { - switch (pdata->speed_set) { - case XGBE_SPEEDSET_1000_10000: - pdata->phy.speed = SPEED_1000; - break; - - case XGBE_SPEEDSET_2500_10000: - pdata->phy.speed = SPEED_2500; - break; - } - - xgbe_set_mode(pdata, XGBE_MODE_KX); - } else { + break; + case XGBE_MODE_UNKNOWN: + default: pdata->phy.speed = SPEED_UNKNOWN; } - /* Compare Advertisement and Link Partner register 3 */ - ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); - lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); - if (lp_reg & 0xc000) - pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; - pdata->phy.duplex = DUPLEX_FULL; + + xgbe_set_mode(pdata, mode); } static void xgbe_phy_status(struct xgbe_prv_data *pdata) { - unsigned int reg, link_aneg; + unsigned int link_aneg; if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) { netif_carrier_off(pdata->netdev); @@ -1128,20 +885,14 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE); - /* Get the link status. Link status is latched low, so read - * once to clear and then read again to get current state - */ - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); - pdata->phy.link = (reg & MDIO_STAT1_LSTATUS) ? 1 : 0; - + pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata); if (pdata->phy.link) { if (link_aneg && !xgbe_phy_aneg_done(pdata)) { xgbe_check_link_timeout(pdata); return; } - xgbe_phy_status_aneg(pdata); + xgbe_phy_status_result(pdata); if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) clear_bit(XGBE_LINK_INIT, &pdata->dev_state); @@ -1155,7 +906,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) return; } - xgbe_phy_status_aneg(pdata); + xgbe_phy_status_result(pdata); netif_carrier_off(pdata->netdev); } @@ -1168,6 +919,12 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) { netif_dbg(pdata, link, pdata->netdev, "stopping PHY\n"); + if (!pdata->phy_started) + return; + + /* Indicate the PHY is down */ + pdata->phy_started = 0; + /* Disable auto-negotiation */ xgbe_disable_an(pdata); @@ -1176,6 +933,8 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) devm_free_irq(pdata->dev, pdata->an_irq, pdata); + pdata->phy_if.phy_impl.stop(pdata); + pdata->phy.link = 0; netif_carrier_off(pdata->netdev); @@ -1189,28 +948,35 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata) netif_dbg(pdata, link, pdata->netdev, "starting PHY\n"); + ret = pdata->phy_if.phy_impl.start(pdata); + if (ret) + return ret; + ret = devm_request_irq(pdata->dev, pdata->an_irq, xgbe_an_isr, 0, pdata->an_name, pdata); if (ret) { netdev_err(netdev, "phy irq request failed\n"); - return ret; + goto err_stop; } /* Set initial mode - call the mode setting routines * directly to insure we are properly configured */ - if (xgbe_use_xgmii_mode(pdata)) { - xgbe_xgmii_mode(pdata); - } else if (xgbe_use_gmii_mode(pdata)) { - xgbe_gmii_mode(pdata); - } else if (xgbe_use_gmii_2500_mode(pdata)) { - xgbe_gmii_2500_mode(pdata); + if (xgbe_use_mode(pdata, XGBE_MODE_KR)) { + xgbe_kr_mode(pdata); + } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) { + xgbe_kx_2500_mode(pdata); + } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) { + xgbe_kx_1000_mode(pdata); } else { ret = -EINVAL; goto err_irq; } + /* Indicate the PHY is up and running */ + pdata->phy_started = 1; + /* Set up advertisement registers based on current settings */ xgbe_an_init(pdata); @@ -1222,25 +988,19 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata) err_irq: devm_free_irq(pdata->dev, pdata->an_irq, pdata); +err_stop: + pdata->phy_if.phy_impl.stop(pdata); + return ret; } static int xgbe_phy_reset(struct xgbe_prv_data *pdata) { - unsigned int count, reg; - - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); - reg |= MDIO_CTRL1_RESET; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); - - count = 50; - do { - msleep(20); - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); - } while ((reg & MDIO_CTRL1_RESET) && --count); + int ret; - if (reg & MDIO_CTRL1_RESET) - return -ETIMEDOUT; + ret = pdata->phy_if.phy_impl.reset(pdata); + if (ret) + return ret; /* Disable auto-negotiation for now */ xgbe_disable_an(pdata); @@ -1290,41 +1050,57 @@ static void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata) dev_dbg(dev, "\n*************************************************\n"); } -static void xgbe_phy_init(struct xgbe_prv_data *pdata) +static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata) +{ + if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) + return SPEED_10000; + else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full) + return SPEED_2500; + else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full) + return SPEED_1000; + + return SPEED_UNKNOWN; +} + +static void xgbe_phy_exit(struct xgbe_prv_data *pdata) { + xgbe_phy_stop(pdata); + + pdata->phy_if.phy_impl.exit(pdata); +} + +static int xgbe_phy_init(struct xgbe_prv_data *pdata) +{ + int ret; + mutex_init(&pdata->an_mutex); INIT_WORK(&pdata->an_irq_work, xgbe_an_irq_work); INIT_WORK(&pdata->an_work, xgbe_an_state_machine); pdata->mdio_mmd = MDIO_MMD_PCS; - /* Initialize supported features */ - pdata->phy.supported = SUPPORTED_Autoneg; - pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; - pdata->phy.supported |= SUPPORTED_Backplane; - pdata->phy.supported |= SUPPORTED_10000baseKR_Full; - switch (pdata->speed_set) { - case XGBE_SPEEDSET_1000_10000: - pdata->phy.supported |= SUPPORTED_1000baseKX_Full; - break; - case XGBE_SPEEDSET_2500_10000: - pdata->phy.supported |= SUPPORTED_2500baseX_Full; - break; - } - + /* Check for FEC support */ pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECABLE); pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE | MDIO_PMA_10GBR_FECABLE_ERRABLE); - if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) - pdata->phy.supported |= SUPPORTED_10000baseR_FEC; + /* Setup the phy (including supported features) */ + ret = pdata->phy_if.phy_impl.init(pdata); + if (ret) + return ret; pdata->phy.advertising = pdata->phy.supported; pdata->phy.address = 0; - pdata->phy.autoneg = AUTONEG_ENABLE; - pdata->phy.speed = SPEED_UNKNOWN; - pdata->phy.duplex = DUPLEX_UNKNOWN; + if (pdata->phy.advertising & ADVERTISED_Autoneg) { + pdata->phy.autoneg = AUTONEG_ENABLE; + pdata->phy.speed = SPEED_UNKNOWN; + pdata->phy.duplex = DUPLEX_UNKNOWN; + } else { + pdata->phy.autoneg = AUTONEG_DISABLE; + pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata); + pdata->phy.duplex = DUPLEX_FULL; + } pdata->phy.link = 0; @@ -1346,11 +1122,14 @@ static void xgbe_phy_init(struct xgbe_prv_data *pdata) if (netif_msg_drv(pdata)) xgbe_dump_phy_registers(pdata); + + return 0; } void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if) { phy_if->phy_init = xgbe_phy_init; + phy_if->phy_exit = xgbe_phy_exit; phy_if->phy_reset = xgbe_phy_reset; phy_if->phy_start = xgbe_phy_start; @@ -1358,4 +1137,6 @@ void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if) phy_if->phy_status = xgbe_phy_status; phy_if->phy_config_aneg = xgbe_phy_config_aneg; + + phy_if->phy_valid_speed = xgbe_phy_valid_speed; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c new file mode 100644 index 000000000000..20ccb99bbe88 --- /dev/null +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c @@ -0,0 +1,821 @@ +/* + * AMD 10Gb Ethernet driver + * + * This file is available to you under your choice of the following two + * licenses: + * + * License 1: GPLv2 + * + * Copyright (c) 2016 Advanced Micro Devices, Inc. + * + * This file is free software; you may copy, redistribute and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or (at + * your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * + * License 2: Modified BSD + * + * Copyright (c) 2016 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices, Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include "xgbe.h" +#include "xgbe-common.h" + +#define XGBE_BLWC_PROPERTY "amd,serdes-blwc" +#define XGBE_CDR_RATE_PROPERTY "amd,serdes-cdr-rate" +#define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew" +#define XGBE_TX_AMP_PROPERTY "amd,serdes-tx-amp" +#define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config" +#define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable" + +/* Default SerDes settings */ +#define XGBE_SPEED_1000_BLWC 1 +#define XGBE_SPEED_1000_CDR 0x2 +#define XGBE_SPEED_1000_PLL 0x0 +#define XGBE_SPEED_1000_PQ 0xa +#define XGBE_SPEED_1000_RATE 0x3 +#define XGBE_SPEED_1000_TXAMP 0xf +#define XGBE_SPEED_1000_WORD 0x1 +#define XGBE_SPEED_1000_DFE_TAP_CONFIG 0x3 +#define XGBE_SPEED_1000_DFE_TAP_ENABLE 0x0 + +#define XGBE_SPEED_2500_BLWC 1 +#define XGBE_SPEED_2500_CDR 0x2 +#define XGBE_SPEED_2500_PLL 0x0 +#define XGBE_SPEED_2500_PQ 0xa +#define XGBE_SPEED_2500_RATE 0x1 +#define XGBE_SPEED_2500_TXAMP 0xf +#define XGBE_SPEED_2500_WORD 0x1 +#define XGBE_SPEED_2500_DFE_TAP_CONFIG 0x3 +#define XGBE_SPEED_2500_DFE_TAP_ENABLE 0x0 + +#define XGBE_SPEED_10000_BLWC 0 +#define XGBE_SPEED_10000_CDR 0x7 +#define XGBE_SPEED_10000_PLL 0x1 +#define XGBE_SPEED_10000_PQ 0x12 +#define XGBE_SPEED_10000_RATE 0x0 +#define XGBE_SPEED_10000_TXAMP 0xa +#define XGBE_SPEED_10000_WORD 0x7 +#define XGBE_SPEED_10000_DFE_TAP_CONFIG 0x1 +#define XGBE_SPEED_10000_DFE_TAP_ENABLE 0x7f + +/* Rate-change complete wait/retry count */ +#define XGBE_RATECHANGE_COUNT 500 + +static const u32 xgbe_phy_blwc[] = { + XGBE_SPEED_1000_BLWC, + XGBE_SPEED_2500_BLWC, + XGBE_SPEED_10000_BLWC, +}; + +static const u32 xgbe_phy_cdr_rate[] = { + XGBE_SPEED_1000_CDR, + XGBE_SPEED_2500_CDR, + XGBE_SPEED_10000_CDR, +}; + +static const u32 xgbe_phy_pq_skew[] = { + XGBE_SPEED_1000_PQ, + XGBE_SPEED_2500_PQ, + XGBE_SPEED_10000_PQ, +}; + +static const u32 xgbe_phy_tx_amp[] = { + XGBE_SPEED_1000_TXAMP, + XGBE_SPEED_2500_TXAMP, + XGBE_SPEED_10000_TXAMP, +}; + +static const u32 xgbe_phy_dfe_tap_cfg[] = { + XGBE_SPEED_1000_DFE_TAP_CONFIG, + XGBE_SPEED_2500_DFE_TAP_CONFIG, + XGBE_SPEED_10000_DFE_TAP_CONFIG, +}; + +static const u32 xgbe_phy_dfe_tap_ena[] = { + XGBE_SPEED_1000_DFE_TAP_ENABLE, + XGBE_SPEED_2500_DFE_TAP_ENABLE, + XGBE_SPEED_10000_DFE_TAP_ENABLE, +}; + +struct xgbe_phy_data { + /* 1000/10000 vs 2500/10000 indicator */ + unsigned int speed_set; + + /* SerDes UEFI configurable settings. + * Switching between modes/speeds requires new values for some + * SerDes settings. The values can be supplied as device + * properties in array format. The first array entry is for + * 1GbE, second for 2.5GbE and third for 10GbE + */ + u32 blwc[XGBE_SPEEDS]; + u32 cdr_rate[XGBE_SPEEDS]; + u32 pq_skew[XGBE_SPEEDS]; + u32 tx_amp[XGBE_SPEEDS]; + u32 dfe_tap_cfg[XGBE_SPEEDS]; + u32 dfe_tap_ena[XGBE_SPEEDS]; +}; + +static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata) +{ + XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1); +} + +static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata) +{ + XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0); +} + +static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + enum xgbe_mode mode; + unsigned int ad_reg, lp_reg; + + pdata->phy.lp_advertising |= ADVERTISED_Autoneg; + pdata->phy.lp_advertising |= ADVERTISED_Backplane; + + /* Compare Advertisement and Link Partner register 1 */ + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA); + if (lp_reg & 0x400) + pdata->phy.lp_advertising |= ADVERTISED_Pause; + if (lp_reg & 0x800) + pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; + + if (pdata->phy.pause_autoneg) { + /* Set flow control based on auto-negotiation result */ + pdata->phy.tx_pause = 0; + pdata->phy.rx_pause = 0; + + if (ad_reg & lp_reg & 0x400) { + pdata->phy.tx_pause = 1; + pdata->phy.rx_pause = 1; + } else if (ad_reg & lp_reg & 0x800) { + if (ad_reg & 0x400) + pdata->phy.rx_pause = 1; + else if (lp_reg & 0x400) + pdata->phy.tx_pause = 1; + } + } + + /* Compare Advertisement and Link Partner register 2 */ + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); + if (lp_reg & 0x80) + pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; + if (lp_reg & 0x20) { + if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) + pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full; + else + pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; + } + + ad_reg &= lp_reg; + if (ad_reg & 0x80) { + mode = XGBE_MODE_KR; + } else if (ad_reg & 0x20) { + if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) + mode = XGBE_MODE_KX_2500; + else + mode = XGBE_MODE_KX_1000; + } else { + mode = XGBE_MODE_UNKNOWN; + } + + /* Compare Advertisement and Link Partner register 3 */ + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); + if (lp_reg & 0xc000) + pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; + + return mode; +} + +static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata) +{ + unsigned int reg; + + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); + + reg |= MDIO_CTRL1_LPOWER; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); + + usleep_range(75, 100); + + reg &= ~MDIO_CTRL1_LPOWER; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); +} + +static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata) +{ + /* Assert Rx and Tx ratechange */ + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1); +} + +static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata) +{ + unsigned int wait; + u16 status; + + /* Release Rx and Tx ratechange */ + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0); + + /* Wait for Rx and Tx ready */ + wait = XGBE_RATECHANGE_COUNT; + while (wait--) { + usleep_range(50, 75); + + status = XSIR0_IOREAD(pdata, SIR0_STATUS); + if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) && + XSIR_GET_BITS(status, SIR0_STATUS, TX_READY)) + goto rx_reset; + } + + netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n", + status); + +rx_reset: + /* Perform Rx reset for the DFE changes */ + XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1); +} + +static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + unsigned int reg; + + /* Set PCS to KR/10G speed */ + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); + reg &= ~MDIO_PCS_CTRL2_TYPE; + reg |= MDIO_PCS_CTRL2_10GBR; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); + + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); + reg &= ~MDIO_CTRL1_SPEEDSEL; + reg |= MDIO_CTRL1_SPEED10G; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); + + xgbe_phy_pcs_power_cycle(pdata); + + /* Set SerDes to 10G speed */ + xgbe_phy_start_ratechange(pdata); + + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL); + + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, + phy_data->cdr_rate[XGBE_SPEED_10000]); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, + phy_data->tx_amp[XGBE_SPEED_10000]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, + phy_data->blwc[XGBE_SPEED_10000]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, + phy_data->pq_skew[XGBE_SPEED_10000]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, + phy_data->dfe_tap_cfg[XGBE_SPEED_10000]); + XRXTX_IOWRITE(pdata, RXTX_REG22, + phy_data->dfe_tap_ena[XGBE_SPEED_10000]); + + xgbe_phy_complete_ratechange(pdata); + + netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n"); +} + +static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + unsigned int reg; + + /* Set PCS to KX/1G speed */ + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); + reg &= ~MDIO_PCS_CTRL2_TYPE; + reg |= MDIO_PCS_CTRL2_10GBX; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); + + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); + reg &= ~MDIO_CTRL1_SPEEDSEL; + reg |= MDIO_CTRL1_SPEED1G; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); + + xgbe_phy_pcs_power_cycle(pdata); + + /* Set SerDes to 2.5G speed */ + xgbe_phy_start_ratechange(pdata); + + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL); + + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, + phy_data->cdr_rate[XGBE_SPEED_2500]); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, + phy_data->tx_amp[XGBE_SPEED_2500]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, + phy_data->blwc[XGBE_SPEED_2500]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, + phy_data->pq_skew[XGBE_SPEED_2500]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, + phy_data->dfe_tap_cfg[XGBE_SPEED_2500]); + XRXTX_IOWRITE(pdata, RXTX_REG22, + phy_data->dfe_tap_ena[XGBE_SPEED_2500]); + + xgbe_phy_complete_ratechange(pdata); + + netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n"); +} + +static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + unsigned int reg; + + /* Set PCS to KX/1G speed */ + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); + reg &= ~MDIO_PCS_CTRL2_TYPE; + reg |= MDIO_PCS_CTRL2_10GBX; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); + + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); + reg &= ~MDIO_CTRL1_SPEEDSEL; + reg |= MDIO_CTRL1_SPEED1G; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); + + xgbe_phy_pcs_power_cycle(pdata); + + /* Set SerDes to 1G speed */ + xgbe_phy_start_ratechange(pdata); + + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL); + + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, + phy_data->cdr_rate[XGBE_SPEED_1000]); + XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, + phy_data->tx_amp[XGBE_SPEED_1000]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, + phy_data->blwc[XGBE_SPEED_1000]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, + phy_data->pq_skew[XGBE_SPEED_1000]); + XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, + phy_data->dfe_tap_cfg[XGBE_SPEED_1000]); + XRXTX_IOWRITE(pdata, RXTX_REG22, + phy_data->dfe_tap_ena[XGBE_SPEED_1000]); + + xgbe_phy_complete_ratechange(pdata); + + netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n"); +} + +static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + enum xgbe_mode mode; + unsigned int reg; + + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); + reg &= MDIO_PCS_CTRL2_TYPE; + + if (reg == MDIO_PCS_CTRL2_10GBR) { + mode = XGBE_MODE_KR; + } else { + if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) + mode = XGBE_MODE_KX_2500; + else + mode = XGBE_MODE_KX_1000; + } + + return mode; +} + +static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + enum xgbe_mode mode; + + /* If we are in KR switch to KX, and vice-versa */ + if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) { + if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) + mode = XGBE_MODE_KX_2500; + else + mode = XGBE_MODE_KX_1000; + } else { + mode = XGBE_MODE_KR; + } + + return mode; +} + +static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata, + int speed) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + + switch (speed) { + case SPEED_1000: + return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000) + ? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN; + case SPEED_2500: + return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) + ? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN; + case SPEED_10000: + return XGBE_MODE_KR; + default: + return XGBE_MODE_UNKNOWN; + } +} + +static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode) +{ + switch (mode) { + case XGBE_MODE_KX_1000: + xgbe_phy_kx_1000_mode(pdata); + break; + case XGBE_MODE_KX_2500: + xgbe_phy_kx_2500_mode(pdata); + break; + case XGBE_MODE_KR: + xgbe_phy_kr_mode(pdata); + break; + default: + break; + } +} + +static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode, u32 advert) +{ + if (pdata->phy.autoneg == AUTONEG_ENABLE) { + if (pdata->phy.advertising & advert) + return true; + } else { + enum xgbe_mode cur_mode; + + cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed); + if (cur_mode == mode) + return true; + } + + return false; +} + +static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode) +{ + switch (mode) { + case XGBE_MODE_KX_1000: + return xgbe_phy_check_mode(pdata, mode, + ADVERTISED_1000baseKX_Full); + case XGBE_MODE_KX_2500: + return xgbe_phy_check_mode(pdata, mode, + ADVERTISED_2500baseX_Full); + case XGBE_MODE_KR: + return xgbe_phy_check_mode(pdata, mode, + ADVERTISED_10000baseKR_Full); + default: + return false; + } +} + +static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + + switch (speed) { + case SPEED_1000: + if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000) + return false; + return true; + case SPEED_2500: + if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000) + return false; + return true; + case SPEED_10000: + return true; + default: + return false; + } +} + +static int xgbe_phy_link_status(struct xgbe_prv_data *pdata) +{ + unsigned int reg; + + /* Link status is latched low, so read once to clear + * and then read again to get current state + */ + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); + + return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0; +} + +static void xgbe_phy_stop(struct xgbe_prv_data *pdata) +{ + /* Nothing uniquely required for stop */ +} + +static int xgbe_phy_start(struct xgbe_prv_data *pdata) +{ + /* Nothing uniquely required for start */ + return 0; +} + +static int xgbe_phy_reset(struct xgbe_prv_data *pdata) +{ + unsigned int reg, count; + + /* Perform a software reset of the PCS */ + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); + reg |= MDIO_CTRL1_RESET; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); + + count = 50; + do { + msleep(20); + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); + } while ((reg & MDIO_CTRL1_RESET) && --count); + + if (reg & MDIO_CTRL1_RESET) + return -ETIMEDOUT; + + return 0; +} + +static void xgbe_phy_exit(struct xgbe_prv_data *pdata) +{ + /* Nothing uniquely required for exit */ +} + +static int xgbe_phy_init(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data; + int ret; + + phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL); + if (!phy_data) + return -ENOMEM; + + /* Retrieve the PHY speedset */ + ret = device_property_read_u32(pdata->phy_dev, XGBE_SPEEDSET_PROPERTY, + &phy_data->speed_set); + if (ret) { + dev_err(pdata->dev, "invalid %s property\n", + XGBE_SPEEDSET_PROPERTY); + return ret; + } + + switch (phy_data->speed_set) { + case XGBE_SPEEDSET_1000_10000: + case XGBE_SPEEDSET_2500_10000: + break; + default: + dev_err(pdata->dev, "invalid %s property\n", + XGBE_SPEEDSET_PROPERTY); + return -EINVAL; + } + + /* Retrieve the PHY configuration properties */ + if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) { + ret = device_property_read_u32_array(pdata->phy_dev, + XGBE_BLWC_PROPERTY, + phy_data->blwc, + XGBE_SPEEDS); + if (ret) { + dev_err(pdata->dev, "invalid %s property\n", + XGBE_BLWC_PROPERTY); + return ret; + } + } else { + memcpy(phy_data->blwc, xgbe_phy_blwc, + sizeof(phy_data->blwc)); + } + + if (device_property_present(pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) { + ret = device_property_read_u32_array(pdata->phy_dev, + XGBE_CDR_RATE_PROPERTY, + phy_data->cdr_rate, + XGBE_SPEEDS); + if (ret) { + dev_err(pdata->dev, "invalid %s property\n", + XGBE_CDR_RATE_PROPERTY); + return ret; + } + } else { + memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate, + sizeof(phy_data->cdr_rate)); + } + + if (device_property_present(pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) { + ret = device_property_read_u32_array(pdata->phy_dev, + XGBE_PQ_SKEW_PROPERTY, + phy_data->pq_skew, + XGBE_SPEEDS); + if (ret) { + dev_err(pdata->dev, "invalid %s property\n", + XGBE_PQ_SKEW_PROPERTY); + return ret; + } + } else { + memcpy(phy_data->pq_skew, xgbe_phy_pq_skew, + sizeof(phy_data->pq_skew)); + } + + if (device_property_present(pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) { + ret = device_property_read_u32_array(pdata->phy_dev, + XGBE_TX_AMP_PROPERTY, + phy_data->tx_amp, + XGBE_SPEEDS); + if (ret) { + dev_err(pdata->dev, "invalid %s property\n", + XGBE_TX_AMP_PROPERTY); + return ret; + } + } else { + memcpy(phy_data->tx_amp, xgbe_phy_tx_amp, + sizeof(phy_data->tx_amp)); + } + + if (device_property_present(pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) { + ret = device_property_read_u32_array(pdata->phy_dev, + XGBE_DFE_CFG_PROPERTY, + phy_data->dfe_tap_cfg, + XGBE_SPEEDS); + if (ret) { + dev_err(pdata->dev, "invalid %s property\n", + XGBE_DFE_CFG_PROPERTY); + return ret; + } + } else { + memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg, + sizeof(phy_data->dfe_tap_cfg)); + } + + if (device_property_present(pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) { + ret = device_property_read_u32_array(pdata->phy_dev, + XGBE_DFE_ENA_PROPERTY, + phy_data->dfe_tap_ena, + XGBE_SPEEDS); + if (ret) { + dev_err(pdata->dev, "invalid %s property\n", + XGBE_DFE_ENA_PROPERTY); + return ret; + } + } else { + memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena, + sizeof(phy_data->dfe_tap_ena)); + } + + /* Initialize supported features */ + pdata->phy.supported = SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_Backplane; + pdata->phy.supported |= SUPPORTED_10000baseKR_Full; + switch (phy_data->speed_set) { + case XGBE_SPEEDSET_1000_10000: + pdata->phy.supported |= SUPPORTED_1000baseKX_Full; + break; + case XGBE_SPEEDSET_2500_10000: + pdata->phy.supported |= SUPPORTED_2500baseX_Full; + break; + } + + if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) + pdata->phy.supported |= SUPPORTED_10000baseR_FEC; + + pdata->phy_data = phy_data; + + return 0; +} + +void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if) +{ + struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl; + + phy_impl->init = xgbe_phy_init; + phy_impl->exit = xgbe_phy_exit; + + phy_impl->reset = xgbe_phy_reset; + phy_impl->start = xgbe_phy_start; + phy_impl->stop = xgbe_phy_stop; + + phy_impl->link_status = xgbe_phy_link_status; + + phy_impl->valid_speed = xgbe_phy_valid_speed; + + phy_impl->use_mode = xgbe_phy_use_mode; + phy_impl->set_mode = xgbe_phy_set_mode; + phy_impl->get_mode = xgbe_phy_get_mode; + phy_impl->switch_mode = xgbe_phy_switch_mode; + phy_impl->cur_mode = xgbe_phy_cur_mode; + + phy_impl->an_outcome = xgbe_phy_an_outcome; + + phy_impl->kr_training_pre = xgbe_phy_kr_training_pre; + phy_impl->kr_training_post = xgbe_phy_kr_training_post; +} diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index a4e1b8d01491..0d33aef36b71 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -129,7 +129,7 @@ #include #define XGBE_DRV_NAME "amd-xgbe" -#define XGBE_DRV_VERSION "1.0.2" +#define XGBE_DRV_VERSION "1.0.3" #define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver" /* Descriptor related defines */ @@ -191,12 +191,6 @@ #define XGBE_PHY_MODE_PROPERTY "phy-mode" #define XGBE_DMA_IRQS_PROPERTY "amd,per-channel-interrupt" #define XGBE_SPEEDSET_PROPERTY "amd,speed-set" -#define XGBE_BLWC_PROPERTY "amd,serdes-blwc" -#define XGBE_CDR_RATE_PROPERTY "amd,serdes-cdr-rate" -#define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew" -#define XGBE_TX_AMP_PROPERTY "amd,serdes-tx-amp" -#define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config" -#define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable" /* Device-tree clock names */ #define XGBE_DMA_CLOCK "dma_clk" @@ -274,40 +268,6 @@ #define XGBE_AN_PG_RCV 0x04 #define XGBE_AN_INT_MASK 0x07 -/* Rate-change complete wait/retry count */ -#define XGBE_RATECHANGE_COUNT 500 - -/* Default SerDes settings */ -#define XGBE_SPEED_10000_BLWC 0 -#define XGBE_SPEED_10000_CDR 0x7 -#define XGBE_SPEED_10000_PLL 0x1 -#define XGBE_SPEED_10000_PQ 0x12 -#define XGBE_SPEED_10000_RATE 0x0 -#define XGBE_SPEED_10000_TXAMP 0xa -#define XGBE_SPEED_10000_WORD 0x7 -#define XGBE_SPEED_10000_DFE_TAP_CONFIG 0x1 -#define XGBE_SPEED_10000_DFE_TAP_ENABLE 0x7f - -#define XGBE_SPEED_2500_BLWC 1 -#define XGBE_SPEED_2500_CDR 0x2 -#define XGBE_SPEED_2500_PLL 0x0 -#define XGBE_SPEED_2500_PQ 0xa -#define XGBE_SPEED_2500_RATE 0x1 -#define XGBE_SPEED_2500_TXAMP 0xf -#define XGBE_SPEED_2500_WORD 0x1 -#define XGBE_SPEED_2500_DFE_TAP_CONFIG 0x3 -#define XGBE_SPEED_2500_DFE_TAP_ENABLE 0x0 - -#define XGBE_SPEED_1000_BLWC 1 -#define XGBE_SPEED_1000_CDR 0x2 -#define XGBE_SPEED_1000_PLL 0x0 -#define XGBE_SPEED_1000_PQ 0xa -#define XGBE_SPEED_1000_RATE 0x3 -#define XGBE_SPEED_1000_TXAMP 0xf -#define XGBE_SPEED_1000_WORD 0x1 -#define XGBE_SPEED_1000_DFE_TAP_CONFIG 0x3 -#define XGBE_SPEED_1000_DFE_TAP_ENABLE 0x0 - struct xgbe_prv_data; struct xgbe_packet_data { @@ -527,8 +487,10 @@ enum xgbe_rx { }; enum xgbe_mode { - XGBE_MODE_KR = 0, - XGBE_MODE_KX, + XGBE_MODE_KX_1000 = 0, + XGBE_MODE_KX_2500, + XGBE_MODE_KR, + XGBE_MODE_UNKNOWN, }; enum xgbe_speedset { @@ -624,9 +586,7 @@ struct xgbe_hw_if { int (*read_mmd_regs)(struct xgbe_prv_data *, int, int); void (*write_mmd_regs)(struct xgbe_prv_data *, int, int, int); - int (*set_gmii_speed)(struct xgbe_prv_data *); - int (*set_gmii_2500_speed)(struct xgbe_prv_data *); - int (*set_xgmii_speed)(struct xgbe_prv_data *); + int (*set_speed)(struct xgbe_prv_data *, int); void (*enable_tx)(struct xgbe_prv_data *); void (*disable_tx)(struct xgbe_prv_data *); @@ -707,9 +667,50 @@ struct xgbe_hw_if { int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *); }; +/* This structure represents implementation specific routines for an + * implementation of a PHY. All routines are required unless noted below. + * Optional routines: + * kr_training_pre, kr_training_post + */ +struct xgbe_phy_impl_if { + /* Perform Setup/teardown actions */ + int (*init)(struct xgbe_prv_data *); + void (*exit)(struct xgbe_prv_data *); + + /* Perform start/stop specific actions */ + int (*reset)(struct xgbe_prv_data *); + int (*start)(struct xgbe_prv_data *); + void (*stop)(struct xgbe_prv_data *); + + /* Return the link status */ + int (*link_status)(struct xgbe_prv_data *); + + /* Indicate if a particular speed is valid */ + bool (*valid_speed)(struct xgbe_prv_data *, int); + + /* Check if the specified mode can/should be used */ + bool (*use_mode)(struct xgbe_prv_data *, enum xgbe_mode); + /* Switch the PHY into various modes */ + void (*set_mode)(struct xgbe_prv_data *, enum xgbe_mode); + /* Retrieve mode needed for a specific speed */ + enum xgbe_mode (*get_mode)(struct xgbe_prv_data *, int); + /* Retrieve new/next mode when trying to auto-negotiate */ + enum xgbe_mode (*switch_mode)(struct xgbe_prv_data *); + /* Retrieve current mode */ + enum xgbe_mode (*cur_mode)(struct xgbe_prv_data *); + + /* Process results of auto-negotiation */ + enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *); + + /* Pre/Post KR training enablement support */ + void (*kr_training_pre)(struct xgbe_prv_data *); + void (*kr_training_post)(struct xgbe_prv_data *); +}; + struct xgbe_phy_if { - /* For initial PHY setup */ - void (*phy_init)(struct xgbe_prv_data *); + /* For PHY setup/teardown */ + int (*phy_init)(struct xgbe_prv_data *); + void (*phy_exit)(struct xgbe_prv_data *); /* For PHY support when setting device up/down */ int (*phy_reset)(struct xgbe_prv_data *); @@ -719,6 +720,12 @@ struct xgbe_phy_if { /* For PHY support while device is up */ void (*phy_status)(struct xgbe_prv_data *); int (*phy_config_aneg)(struct xgbe_prv_data *); + + /* For PHY settings validation */ + bool (*phy_valid_speed)(struct xgbe_prv_data *, int); + + /* PHY implementation specific services */ + struct xgbe_phy_impl_if phy_impl; }; struct xgbe_desc_if { @@ -778,11 +785,20 @@ struct xgbe_hw_features { unsigned int aux_snap_num; /* Number of Aux snapshot inputs */ }; +struct xgbe_version_data { + void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *); +}; + struct xgbe_prv_data { struct net_device *netdev; struct platform_device *pdev; struct acpi_device *adev; struct device *dev; + struct platform_device *phy_pdev; + struct device *phy_dev; + + /* Version related data */ + struct xgbe_version_data *vdata; /* ACPI or DT flag */ unsigned int use_acpi; @@ -928,6 +944,8 @@ struct xgbe_prv_data { int phy_speed; /* MDIO/PHY related settings */ + unsigned int phy_started; + void *phy_data; struct xgbe_phy phy; int mdio_mmd; unsigned long link_check; @@ -938,21 +956,6 @@ struct xgbe_prv_data { int an_irq; struct work_struct an_irq_work; - unsigned int speed_set; - - /* SerDes UEFI configurable settings. - * Switching between modes/speeds requires new values for some - * SerDes settings. The values can be supplied as device - * properties in array format. The first array entry is for - * 1GbE, second for 2.5GbE and third for 10GbE - */ - u32 serdes_blwc[XGBE_SPEEDS]; - u32 serdes_cdr_rate[XGBE_SPEEDS]; - u32 serdes_pq_skew[XGBE_SPEEDS]; - u32 serdes_tx_amp[XGBE_SPEEDS]; - u32 serdes_dfe_tap_cfg[XGBE_SPEEDS]; - u32 serdes_dfe_tap_ena[XGBE_SPEEDS]; - /* Auto-negotiation state machine support */ unsigned int an_int; struct mutex an_mutex; @@ -982,6 +985,7 @@ struct xgbe_prv_data { void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *); void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *); +void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *); void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *); const struct net_device_ops *xgbe_get_netdev_ops(void); const struct ethtool_ops *xgbe_get_ethtool_ops(void); -- cgit v1.2.3 From a64def4161d4b8fffea43807f582ffc3e4e5d128 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:18:38 -0500 Subject: amd-xgbe: Prepare for introduction of clause 37 autoneg Prepare for the future introduction of clause 37 auto-negotiation by updating the current auto-negotiation related functions to identify them as clause 73 functions. Move interrupt enablement to the enable/disable auto-negotiation functions. Update what will be common routines to check for the current type of AN and process accordingly. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 5 + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 235 ++++++++++++++++++---------- drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c | 7 + drivers/net/ethernet/amd/xgbe/xgbe.h | 14 +- 4 files changed, 176 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index bbef95973c27..695e9820b8b3 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -1052,6 +1052,11 @@ #endif /* MDIO mask values */ +#define XGBE_AN_CL73_INT_CMPLT BIT(0) +#define XGBE_AN_CL73_INC_LINK BIT(1) +#define XGBE_AN_CL73_PG_RCV BIT(2) +#define XGBE_AN_CL73_INT_MASK 0x07 + #define XGBE_XNP_MCF_NULL_MESSAGE 0x001 #define XGBE_XNP_ACK_PROCESSED BIT(12) #define XGBE_XNP_MP_FORMATTED BIT(13) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 35c302f7889c..d5bfbe432c07 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -125,7 +125,33 @@ #include "xgbe.h" #include "xgbe-common.h" -static void xgbe_an_enable_kr_training(struct xgbe_prv_data *pdata) +static void xgbe_an73_clear_interrupts(struct xgbe_prv_data *pdata) +{ + XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); +} + +static void xgbe_an73_disable_interrupts(struct xgbe_prv_data *pdata) +{ + XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0); +} + +static void xgbe_an73_enable_interrupts(struct xgbe_prv_data *pdata) +{ + XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_CL73_INT_MASK); +} + +static void xgbe_an_enable_interrupts(struct xgbe_prv_data *pdata) +{ + switch (pdata->an_mode) { + case XGBE_AN_MODE_CL73: + xgbe_an73_enable_interrupts(pdata); + break; + default: + break; + } +} + +static void xgbe_an73_enable_kr_training(struct xgbe_prv_data *pdata) { unsigned int reg; @@ -135,7 +161,7 @@ static void xgbe_an_enable_kr_training(struct xgbe_prv_data *pdata) XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); } -static void xgbe_an_disable_kr_training(struct xgbe_prv_data *pdata) +static void xgbe_an73_disable_kr_training(struct xgbe_prv_data *pdata) { unsigned int reg; @@ -148,7 +174,7 @@ static void xgbe_an_disable_kr_training(struct xgbe_prv_data *pdata) static void xgbe_kr_mode(struct xgbe_prv_data *pdata) { /* Enable KR training */ - xgbe_an_enable_kr_training(pdata); + xgbe_an73_enable_kr_training(pdata); /* Set MAC to 10G speed */ pdata->hw_if.set_speed(pdata, SPEED_10000); @@ -160,7 +186,7 @@ static void xgbe_kr_mode(struct xgbe_prv_data *pdata) static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata) { /* Disable KR training */ - xgbe_an_disable_kr_training(pdata); + xgbe_an73_disable_kr_training(pdata); /* Set MAC to 2.5G speed */ pdata->hw_if.set_speed(pdata, SPEED_2500); @@ -172,7 +198,7 @@ static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata) static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata) { /* Disable KR training */ - xgbe_an_disable_kr_training(pdata); + xgbe_an73_disable_kr_training(pdata); /* Set MAC to 1G speed */ pdata->hw_if.set_speed(pdata, SPEED_1000); @@ -232,7 +258,8 @@ static bool xgbe_use_mode(struct xgbe_prv_data *pdata, return pdata->phy_if.phy_impl.use_mode(pdata, mode); } -static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart) +static void xgbe_an73_set(struct xgbe_prv_data *pdata, bool enable, + bool restart) { unsigned int reg; @@ -248,22 +275,46 @@ static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart) XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg); } -static void xgbe_restart_an(struct xgbe_prv_data *pdata) +static void xgbe_an73_restart(struct xgbe_prv_data *pdata) { - xgbe_set_an(pdata, true, true); + xgbe_an73_enable_interrupts(pdata); + xgbe_an73_set(pdata, true, true); - netif_dbg(pdata, link, pdata->netdev, "AN enabled/restarted\n"); + netif_dbg(pdata, link, pdata->netdev, "CL73 AN enabled/restarted\n"); } -static void xgbe_disable_an(struct xgbe_prv_data *pdata) +static void xgbe_an73_disable(struct xgbe_prv_data *pdata) { - xgbe_set_an(pdata, false, false); + xgbe_an73_set(pdata, false, false); + xgbe_an73_disable_interrupts(pdata); - netif_dbg(pdata, link, pdata->netdev, "AN disabled\n"); + netif_dbg(pdata, link, pdata->netdev, "CL73 AN disabled\n"); } -static enum xgbe_an xgbe_an_tx_training(struct xgbe_prv_data *pdata, - enum xgbe_rx *state) +static void xgbe_an_restart(struct xgbe_prv_data *pdata) +{ + switch (pdata->an_mode) { + case XGBE_AN_MODE_CL73: + xgbe_an73_restart(pdata); + break; + default: + break; + } +} + +static void xgbe_an_disable(struct xgbe_prv_data *pdata) +{ + switch (pdata->an_mode) { + case XGBE_AN_MODE_CL73: + xgbe_an73_disable(pdata); + break; + default: + break; + } +} + +static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata, + enum xgbe_rx *state) { unsigned int ad_reg, lp_reg, reg; @@ -304,8 +355,8 @@ static enum xgbe_an xgbe_an_tx_training(struct xgbe_prv_data *pdata, return XGBE_AN_PAGE_RECEIVED; } -static enum xgbe_an xgbe_an_tx_xnp(struct xgbe_prv_data *pdata, - enum xgbe_rx *state) +static enum xgbe_an xgbe_an73_tx_xnp(struct xgbe_prv_data *pdata, + enum xgbe_rx *state) { u16 msg; @@ -321,8 +372,8 @@ static enum xgbe_an xgbe_an_tx_xnp(struct xgbe_prv_data *pdata, return XGBE_AN_PAGE_RECEIVED; } -static enum xgbe_an xgbe_an_rx_bpa(struct xgbe_prv_data *pdata, - enum xgbe_rx *state) +static enum xgbe_an xgbe_an73_rx_bpa(struct xgbe_prv_data *pdata, + enum xgbe_rx *state) { unsigned int link_support; unsigned int reg, ad_reg, lp_reg; @@ -341,12 +392,12 @@ static enum xgbe_an xgbe_an_rx_bpa(struct xgbe_prv_data *pdata, return ((ad_reg & XGBE_XNP_NP_EXCHANGE) || (lp_reg & XGBE_XNP_NP_EXCHANGE)) - ? xgbe_an_tx_xnp(pdata, state) - : xgbe_an_tx_training(pdata, state); + ? xgbe_an73_tx_xnp(pdata, state) + : xgbe_an73_tx_training(pdata, state); } -static enum xgbe_an xgbe_an_rx_xnp(struct xgbe_prv_data *pdata, - enum xgbe_rx *state) +static enum xgbe_an xgbe_an73_rx_xnp(struct xgbe_prv_data *pdata, + enum xgbe_rx *state) { unsigned int ad_reg, lp_reg; @@ -356,11 +407,11 @@ static enum xgbe_an xgbe_an_rx_xnp(struct xgbe_prv_data *pdata, return ((ad_reg & XGBE_XNP_NP_EXCHANGE) || (lp_reg & XGBE_XNP_NP_EXCHANGE)) - ? xgbe_an_tx_xnp(pdata, state) - : xgbe_an_tx_training(pdata, state); + ? xgbe_an73_tx_xnp(pdata, state) + : xgbe_an73_tx_training(pdata, state); } -static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata) +static enum xgbe_an xgbe_an73_page_received(struct xgbe_prv_data *pdata) { enum xgbe_rx *state; unsigned long an_timeout; @@ -379,7 +430,7 @@ static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata) pdata->an_start = jiffies; netif_dbg(pdata, link, pdata->netdev, - "AN timed out, resetting state\n"); + "CL73 AN timed out, resetting state\n"); } } @@ -388,11 +439,11 @@ static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata) switch (*state) { case XGBE_RX_BPA: - ret = xgbe_an_rx_bpa(pdata, state); + ret = xgbe_an73_rx_bpa(pdata, state); break; case XGBE_RX_XNP: - ret = xgbe_an_rx_xnp(pdata, state); + ret = xgbe_an73_rx_xnp(pdata, state); break; default: @@ -402,7 +453,7 @@ static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata) return ret; } -static enum xgbe_an xgbe_an_incompat_link(struct xgbe_prv_data *pdata) +static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata) { /* Be sure we aren't looping trying to negotiate */ if (xgbe_in_kr_mode(pdata)) { @@ -424,23 +475,19 @@ static enum xgbe_an xgbe_an_incompat_link(struct xgbe_prv_data *pdata) return XGBE_AN_NO_LINK; } - xgbe_disable_an(pdata); + xgbe_an73_disable(pdata); xgbe_switch_mode(pdata); - xgbe_restart_an(pdata); + xgbe_an73_restart(pdata); return XGBE_AN_INCOMPAT_LINK; } -static irqreturn_t xgbe_an_isr(int irq, void *data) +static void xgbe_an73_isr(struct xgbe_prv_data *pdata) { - struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; - - netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n"); - /* Disable AN interrupts */ - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0); + xgbe_an73_disable_interrupts(pdata); /* Save the interrupt(s) that fired */ pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT); @@ -452,8 +499,22 @@ static irqreturn_t xgbe_an_isr(int irq, void *data) queue_work(pdata->an_workqueue, &pdata->an_irq_work); } else { /* Enable AN interrupts */ - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, - XGBE_AN_INT_MASK); + xgbe_an73_enable_interrupts(pdata); + } +} + +static irqreturn_t xgbe_an_isr(int irq, void *data) +{ + struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + + netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n"); + + switch (pdata->an_mode) { + case XGBE_AN_MODE_CL73: + xgbe_an73_isr(pdata); + break; + default: + break; } return IRQ_HANDLED; @@ -492,28 +553,23 @@ static const char *xgbe_state_as_string(enum xgbe_an state) } } -static void xgbe_an_state_machine(struct work_struct *work) +static void xgbe_an73_state_machine(struct xgbe_prv_data *pdata) { - struct xgbe_prv_data *pdata = container_of(work, - struct xgbe_prv_data, - an_work); enum xgbe_an cur_state = pdata->an_state; - mutex_lock(&pdata->an_mutex); - if (!pdata->an_int) - goto out; + return; next_int: - if (pdata->an_int & XGBE_AN_PG_RCV) { + if (pdata->an_int & XGBE_AN_CL73_PG_RCV) { pdata->an_state = XGBE_AN_PAGE_RECEIVED; - pdata->an_int &= ~XGBE_AN_PG_RCV; - } else if (pdata->an_int & XGBE_AN_INC_LINK) { + pdata->an_int &= ~XGBE_AN_CL73_PG_RCV; + } else if (pdata->an_int & XGBE_AN_CL73_INC_LINK) { pdata->an_state = XGBE_AN_INCOMPAT_LINK; - pdata->an_int &= ~XGBE_AN_INC_LINK; - } else if (pdata->an_int & XGBE_AN_INT_CMPLT) { + pdata->an_int &= ~XGBE_AN_CL73_INC_LINK; + } else if (pdata->an_int & XGBE_AN_CL73_INT_CMPLT) { pdata->an_state = XGBE_AN_COMPLETE; - pdata->an_int &= ~XGBE_AN_INT_CMPLT; + pdata->an_int &= ~XGBE_AN_CL73_INT_CMPLT; } else { pdata->an_state = XGBE_AN_ERROR; } @@ -521,7 +577,7 @@ next_int: pdata->an_result = pdata->an_state; again: - netif_dbg(pdata, link, pdata->netdev, "AN %s\n", + netif_dbg(pdata, link, pdata->netdev, "CL73 AN %s\n", xgbe_state_as_string(pdata->an_state)); cur_state = pdata->an_state; @@ -532,14 +588,14 @@ again: break; case XGBE_AN_PAGE_RECEIVED: - pdata->an_state = xgbe_an_page_received(pdata); + pdata->an_state = xgbe_an73_page_received(pdata); pdata->an_supported++; break; case XGBE_AN_INCOMPAT_LINK: pdata->an_supported = 0; pdata->parallel_detect = 0; - pdata->an_state = xgbe_an_incompat_link(pdata); + pdata->an_state = xgbe_an73_incompat_link(pdata); break; case XGBE_AN_COMPLETE: @@ -558,14 +614,14 @@ again: if (pdata->an_state == XGBE_AN_NO_LINK) { pdata->an_int = 0; - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); + xgbe_an73_clear_interrupts(pdata); } else if (pdata->an_state == XGBE_AN_ERROR) { netdev_err(pdata->netdev, "error during auto-negotiation, state=%u\n", cur_state); pdata->an_int = 0; - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); + xgbe_an73_clear_interrupts(pdata); } if (pdata->an_state >= XGBE_AN_COMPLETE) { @@ -575,7 +631,7 @@ again: pdata->kx_state = XGBE_RX_BPA; pdata->an_start = 0; - netif_dbg(pdata, link, pdata->netdev, "AN result: %s\n", + netif_dbg(pdata, link, pdata->netdev, "CL73 AN result: %s\n", xgbe_state_as_string(pdata->an_result)); } @@ -585,14 +641,29 @@ again: if (pdata->an_int) goto next_int; -out: - /* Enable AN interrupts on the way out */ - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_INT_MASK); + xgbe_an73_enable_interrupts(pdata); +} + +static void xgbe_an_state_machine(struct work_struct *work) +{ + struct xgbe_prv_data *pdata = container_of(work, + struct xgbe_prv_data, + an_work); + + mutex_lock(&pdata->an_mutex); + + switch (pdata->an_mode) { + case XGBE_AN_MODE_CL73: + xgbe_an73_state_machine(pdata); + break; + default: + break; + } mutex_unlock(&pdata->an_mutex); } -static void xgbe_an_init(struct xgbe_prv_data *pdata) +static void xgbe_an73_init(struct xgbe_prv_data *pdata) { unsigned int reg; @@ -637,7 +708,20 @@ static void xgbe_an_init(struct xgbe_prv_data *pdata) XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); - netif_dbg(pdata, link, pdata->netdev, "AN initialized\n"); + netif_dbg(pdata, link, pdata->netdev, "CL73 AN initialized\n"); +} + +static void xgbe_an_init(struct xgbe_prv_data *pdata) +{ + /* Set up advertisement registers based on current settings */ + pdata->an_mode = pdata->phy_if.phy_impl.an_mode(pdata); + switch (pdata->an_mode) { + case XGBE_AN_MODE_CL73: + xgbe_an73_init(pdata); + break; + default: + break; + } } static const char *xgbe_phy_fc_string(struct xgbe_prv_data *pdata) @@ -732,7 +816,7 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata) netif_dbg(pdata, link, pdata->netdev, "fixed PHY configuration\n"); /* Disable auto-negotiation */ - xgbe_disable_an(pdata); + xgbe_an_disable(pdata); /* Set specified mode for specified speed */ mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed); @@ -781,10 +865,10 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) } /* Disable and stop any in progress auto-negotiation */ - xgbe_disable_an(pdata); + xgbe_an_disable(pdata); /* Clear any auto-negotitation interrupts */ - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); + xgbe_an73_clear_interrupts(pdata); pdata->an_result = XGBE_AN_READY; pdata->an_state = XGBE_AN_READY; @@ -794,11 +878,8 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) /* Re-enable auto-negotiation interrupt */ enable_irq(pdata->an_irq); - /* Set up advertisement registers based on current settings */ xgbe_an_init(pdata); - - /* Enable and start auto-negotiation */ - xgbe_restart_an(pdata); + xgbe_an_restart(pdata); return 0; } @@ -926,10 +1007,7 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) pdata->phy_started = 0; /* Disable auto-negotiation */ - xgbe_disable_an(pdata); - - /* Disable auto-negotiation interrupts */ - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0); + xgbe_an_disable(pdata); devm_free_irq(pdata->dev, pdata->an_irq, pdata); @@ -977,11 +1055,8 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata) /* Indicate the PHY is up and running */ pdata->phy_started = 1; - /* Set up advertisement registers based on current settings */ xgbe_an_init(pdata); - - /* Enable auto-negotiation interrupts */ - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07); + xgbe_an_enable_interrupts(pdata); return xgbe_phy_config_aneg(pdata); @@ -1003,10 +1078,10 @@ static int xgbe_phy_reset(struct xgbe_prv_data *pdata) return ret; /* Disable auto-negotiation for now */ - xgbe_disable_an(pdata); + xgbe_an_disable(pdata); /* Clear auto-negotiation interrupts */ - XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); + xgbe_an73_clear_interrupts(pdata); return 0; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c index 20ccb99bbe88..9c913a06efcc 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c @@ -295,6 +295,11 @@ static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata) return mode; } +static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata) +{ + return XGBE_AN_MODE_CL73; +} + static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata) { unsigned int reg; @@ -814,6 +819,8 @@ void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if) phy_impl->switch_mode = xgbe_phy_switch_mode; phy_impl->cur_mode = xgbe_phy_cur_mode; + phy_impl->an_mode = xgbe_phy_an_mode; + phy_impl->an_outcome = xgbe_phy_an_outcome; phy_impl->kr_training_pre = xgbe_phy_kr_training_pre; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 0d33aef36b71..d90ecbcb97a6 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -263,11 +263,6 @@ #define XGBE_AN_MS_TIMEOUT 500 #define XGBE_LINK_TIMEOUT 10 -#define XGBE_AN_INT_CMPLT 0x01 -#define XGBE_AN_INC_LINK 0x02 -#define XGBE_AN_PG_RCV 0x04 -#define XGBE_AN_INT_MASK 0x07 - struct xgbe_prv_data; struct xgbe_packet_data { @@ -470,6 +465,11 @@ enum xgbe_speed { XGBE_SPEEDS, }; +enum xgbe_an_mode { + XGBE_AN_MODE_CL73 = 0, + XGBE_AN_MODE_NONE, +}; + enum xgbe_an { XGBE_AN_READY = 0, XGBE_AN_PAGE_RECEIVED, @@ -699,6 +699,9 @@ struct xgbe_phy_impl_if { /* Retrieve current mode */ enum xgbe_mode (*cur_mode)(struct xgbe_prv_data *); + /* Retrieve current auto-negotiation mode */ + enum xgbe_an_mode (*an_mode)(struct xgbe_prv_data *); + /* Process results of auto-negotiation */ enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *); @@ -968,6 +971,7 @@ struct xgbe_prv_data { unsigned int parallel_detect; unsigned int fec_ability; unsigned long an_start; + enum xgbe_an_mode an_mode; unsigned int lpm_ctrl; /* CTRL1 for resume */ -- cgit v1.2.3 From 1bf40ada62901e14395902d0934a4e51e04afe46 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:18:47 -0500 Subject: amd-xgbe: Add support for clause 37 auto-negotiation Add support to be able to use clause 37 auto-negotiation. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 41 +++++ drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 242 +++++++++++++++++++++++++++- drivers/net/ethernet/amd/xgbe/xgbe.h | 11 +- 3 files changed, 286 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 695e9820b8b3..8bcf4ef050d6 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -1027,6 +1027,10 @@ #define MDIO_PMA_10GBR_FECCTRL 0x00ab #endif +#ifndef MDIO_PCS_DIG_CTRL +#define MDIO_PCS_DIG_CTRL 0x8000 +#endif + #ifndef MDIO_AN_XNP #define MDIO_AN_XNP 0x0016 #endif @@ -1047,10 +1051,34 @@ #define MDIO_AN_INT 0x8002 #endif +#ifndef MDIO_VEND2_AN_ADVERTISE +#define MDIO_VEND2_AN_ADVERTISE 0x0004 +#endif + +#ifndef MDIO_VEND2_AN_LP_ABILITY +#define MDIO_VEND2_AN_LP_ABILITY 0x0005 +#endif + +#ifndef MDIO_VEND2_AN_CTRL +#define MDIO_VEND2_AN_CTRL 0x8001 +#endif + +#ifndef MDIO_VEND2_AN_STAT +#define MDIO_VEND2_AN_STAT 0x8002 +#endif + #ifndef MDIO_CTRL1_SPEED1G #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) #endif +#ifndef MDIO_VEND2_CTRL1_AN_ENABLE +#define MDIO_VEND2_CTRL1_AN_ENABLE BIT(12) +#endif + +#ifndef MDIO_VEND2_CTRL1_AN_RESTART +#define MDIO_VEND2_CTRL1_AN_RESTART BIT(9) +#endif + /* MDIO mask values */ #define XGBE_AN_CL73_INT_CMPLT BIT(0) #define XGBE_AN_CL73_INC_LINK BIT(1) @@ -1065,6 +1093,19 @@ #define XGBE_KR_TRAINING_START BIT(0) #define XGBE_KR_TRAINING_ENABLE BIT(1) +#define XGBE_PCS_CL37_BP BIT(12) + +#define XGBE_AN_CL37_INT_CMPLT BIT(0) +#define XGBE_AN_CL37_INT_MASK 0x01 + +#define XGBE_AN_CL37_HD_MASK 0x40 +#define XGBE_AN_CL37_FD_MASK 0x20 + +#define XGBE_AN_CL37_PCS_MODE_MASK 0x06 +#define XGBE_AN_CL37_PCS_MODE_BASEX 0x00 +#define XGBE_AN_CL37_PCS_MODE_SGMII 0x04 +#define XGBE_AN_CL37_TX_CONFIG_MASK 0x08 + /* Bit setting and getting macros * The get macro will extract the current bit field value from within * the variable diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index d5bfbe432c07..723eb908b262 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -125,6 +125,41 @@ #include "xgbe.h" #include "xgbe-common.h" +static void xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata) +{ + int reg; + + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT); + reg &= ~XGBE_AN_CL37_INT_MASK; + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg); +} + +static void xgbe_an37_disable_interrupts(struct xgbe_prv_data *pdata) +{ + int reg; + + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL); + reg &= ~XGBE_AN_CL37_INT_MASK; + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg); + + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL); + reg &= ~XGBE_PCS_CL37_BP; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg); +} + +static void xgbe_an37_enable_interrupts(struct xgbe_prv_data *pdata) +{ + int reg; + + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL); + reg |= XGBE_PCS_CL37_BP; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg); + + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL); + reg |= XGBE_AN_CL37_INT_MASK; + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg); +} + static void xgbe_an73_clear_interrupts(struct xgbe_prv_data *pdata) { XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); @@ -146,11 +181,21 @@ static void xgbe_an_enable_interrupts(struct xgbe_prv_data *pdata) case XGBE_AN_MODE_CL73: xgbe_an73_enable_interrupts(pdata); break; + case XGBE_AN_MODE_CL37: + case XGBE_AN_MODE_CL37_SGMII: + xgbe_an37_enable_interrupts(pdata); + break; default: break; } } +static void xgbe_an_clear_interrupts_all(struct xgbe_prv_data *pdata) +{ + xgbe_an73_clear_interrupts(pdata); + xgbe_an37_clear_interrupts(pdata); +} + static void xgbe_an73_enable_kr_training(struct xgbe_prv_data *pdata) { unsigned int reg; @@ -258,6 +303,39 @@ static bool xgbe_use_mode(struct xgbe_prv_data *pdata, return pdata->phy_if.phy_impl.use_mode(pdata, mode); } +static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, + bool restart) +{ + unsigned int reg; + + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_CTRL1); + reg &= ~MDIO_VEND2_CTRL1_AN_ENABLE; + + if (enable) + reg |= MDIO_VEND2_CTRL1_AN_ENABLE; + + if (restart) + reg |= MDIO_VEND2_CTRL1_AN_RESTART; + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); +} + +static void xgbe_an37_restart(struct xgbe_prv_data *pdata) +{ + xgbe_an37_enable_interrupts(pdata); + xgbe_an37_set(pdata, true, true); + + netif_dbg(pdata, link, pdata->netdev, "CL37 AN enabled/restarted\n"); +} + +static void xgbe_an37_disable(struct xgbe_prv_data *pdata) +{ + xgbe_an37_set(pdata, false, false); + xgbe_an37_disable_interrupts(pdata); + + netif_dbg(pdata, link, pdata->netdev, "CL37 AN disabled\n"); +} + static void xgbe_an73_set(struct xgbe_prv_data *pdata, bool enable, bool restart) { @@ -297,6 +375,10 @@ static void xgbe_an_restart(struct xgbe_prv_data *pdata) case XGBE_AN_MODE_CL73: xgbe_an73_restart(pdata); break; + case XGBE_AN_MODE_CL37: + case XGBE_AN_MODE_CL37_SGMII: + xgbe_an37_restart(pdata); + break; default: break; } @@ -308,11 +390,21 @@ static void xgbe_an_disable(struct xgbe_prv_data *pdata) case XGBE_AN_MODE_CL73: xgbe_an73_disable(pdata); break; + case XGBE_AN_MODE_CL37: + case XGBE_AN_MODE_CL37_SGMII: + xgbe_an37_disable(pdata); + break; default: break; } } +static void xgbe_an_disable_all(struct xgbe_prv_data *pdata) +{ + xgbe_an73_disable(pdata); + xgbe_an37_disable(pdata); +} + static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata, enum xgbe_rx *state) { @@ -484,6 +576,30 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata) return XGBE_AN_INCOMPAT_LINK; } +static void xgbe_an37_isr(struct xgbe_prv_data *pdata) +{ + unsigned int reg; + + /* Disable AN interrupts */ + xgbe_an37_disable_interrupts(pdata); + + /* Save the interrupt(s) that fired */ + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT); + pdata->an_int = reg & XGBE_AN_CL37_INT_MASK; + pdata->an_status = reg & ~XGBE_AN_CL37_INT_MASK; + + if (pdata->an_int) { + /* Clear the interrupt(s) that fired and process them */ + reg &= ~XGBE_AN_CL37_INT_MASK; + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg); + + queue_work(pdata->an_workqueue, &pdata->an_irq_work); + } else { + /* Enable AN interrupts */ + xgbe_an37_enable_interrupts(pdata); + } +} + static void xgbe_an73_isr(struct xgbe_prv_data *pdata) { /* Disable AN interrupts */ @@ -513,6 +629,10 @@ static irqreturn_t xgbe_an_isr(int irq, void *data) case XGBE_AN_MODE_CL73: xgbe_an73_isr(pdata); break; + case XGBE_AN_MODE_CL37: + case XGBE_AN_MODE_CL37_SGMII: + xgbe_an37_isr(pdata); + break; default: break; } @@ -553,6 +673,64 @@ static const char *xgbe_state_as_string(enum xgbe_an state) } } +static void xgbe_an37_state_machine(struct xgbe_prv_data *pdata) +{ + enum xgbe_an cur_state = pdata->an_state; + + if (!pdata->an_int) + return; + + if (pdata->an_int & XGBE_AN_CL37_INT_CMPLT) { + pdata->an_state = XGBE_AN_COMPLETE; + pdata->an_int &= ~XGBE_AN_CL37_INT_CMPLT; + + /* If SGMII is enabled, check the link status */ + if ((pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) && + !(pdata->an_status & XGBE_SGMII_AN_LINK_STATUS)) + pdata->an_state = XGBE_AN_NO_LINK; + } + + netif_dbg(pdata, link, pdata->netdev, "CL37 AN %s\n", + xgbe_state_as_string(pdata->an_state)); + + cur_state = pdata->an_state; + + switch (pdata->an_state) { + case XGBE_AN_READY: + break; + + case XGBE_AN_COMPLETE: + netif_dbg(pdata, link, pdata->netdev, + "Auto negotiation successful\n"); + break; + + case XGBE_AN_NO_LINK: + break; + + default: + pdata->an_state = XGBE_AN_ERROR; + } + + if (pdata->an_state == XGBE_AN_ERROR) { + netdev_err(pdata->netdev, + "error during auto-negotiation, state=%u\n", + cur_state); + + pdata->an_int = 0; + xgbe_an37_clear_interrupts(pdata); + } + + if (pdata->an_state >= XGBE_AN_COMPLETE) { + pdata->an_result = pdata->an_state; + pdata->an_state = XGBE_AN_READY; + + netif_dbg(pdata, link, pdata->netdev, "CL37 AN result: %s\n", + xgbe_state_as_string(pdata->an_result)); + } + + xgbe_an37_enable_interrupts(pdata); +} + static void xgbe_an73_state_machine(struct xgbe_prv_data *pdata) { enum xgbe_an cur_state = pdata->an_state; @@ -574,8 +752,6 @@ next_int: pdata->an_state = XGBE_AN_ERROR; } - pdata->an_result = pdata->an_state; - again: netif_dbg(pdata, link, pdata->netdev, "CL73 AN %s\n", xgbe_state_as_string(pdata->an_state)); @@ -656,6 +832,10 @@ static void xgbe_an_state_machine(struct work_struct *work) case XGBE_AN_MODE_CL73: xgbe_an73_state_machine(pdata); break; + case XGBE_AN_MODE_CL37: + case XGBE_AN_MODE_CL37_SGMII: + xgbe_an37_state_machine(pdata); + break; default: break; } @@ -663,6 +843,50 @@ static void xgbe_an_state_machine(struct work_struct *work) mutex_unlock(&pdata->an_mutex); } +static void xgbe_an37_init(struct xgbe_prv_data *pdata) +{ + unsigned int reg; + + /* Set up Advertisement register */ + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE); + if (pdata->phy.advertising & ADVERTISED_Pause) + reg |= 0x100; + else + reg &= ~0x100; + + if (pdata->phy.advertising & ADVERTISED_Asym_Pause) + reg |= 0x80; + else + reg &= ~0x80; + + /* Full duplex, but not half */ + reg |= XGBE_AN_CL37_FD_MASK; + reg &= ~XGBE_AN_CL37_HD_MASK; + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE, reg); + + /* Set up the Control register */ + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL); + reg &= XGBE_AN_CL37_TX_CONFIG_MASK; + reg &= XGBE_AN_CL37_PCS_MODE_MASK; + + switch (pdata->an_mode) { + case XGBE_AN_MODE_CL37: + reg |= XGBE_AN_CL37_PCS_MODE_BASEX; + break; + case XGBE_AN_MODE_CL37_SGMII: + reg |= XGBE_AN_CL37_PCS_MODE_SGMII; + break; + default: + break; + } + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg); + + netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n", + (pdata->an_mode == XGBE_AN_MODE_CL37) ? "BaseX" : "SGMII"); +} + static void xgbe_an73_init(struct xgbe_prv_data *pdata) { unsigned int reg; @@ -719,6 +943,10 @@ static void xgbe_an_init(struct xgbe_prv_data *pdata) case XGBE_AN_MODE_CL73: xgbe_an73_init(pdata); break; + case XGBE_AN_MODE_CL37: + case XGBE_AN_MODE_CL37_SGMII: + xgbe_an37_init(pdata); + break; default: break; } @@ -865,10 +1093,10 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) } /* Disable and stop any in progress auto-negotiation */ - xgbe_an_disable(pdata); + xgbe_an_disable_all(pdata); /* Clear any auto-negotitation interrupts */ - xgbe_an73_clear_interrupts(pdata); + xgbe_an_clear_interrupts_all(pdata); pdata->an_result = XGBE_AN_READY; pdata->an_state = XGBE_AN_READY; @@ -1007,7 +1235,7 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) pdata->phy_started = 0; /* Disable auto-negotiation */ - xgbe_an_disable(pdata); + xgbe_an_disable_all(pdata); devm_free_irq(pdata->dev, pdata->an_irq, pdata); @@ -1078,10 +1306,10 @@ static int xgbe_phy_reset(struct xgbe_prv_data *pdata) return ret; /* Disable auto-negotiation for now */ - xgbe_an_disable(pdata); + xgbe_an_disable_all(pdata); /* Clear auto-negotiation interrupts */ - xgbe_an73_clear_interrupts(pdata); + xgbe_an_clear_interrupts_all(pdata); return 0; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index d90ecbcb97a6..8cb4f20ddab4 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -261,7 +261,13 @@ /* Auto-negotiation */ #define XGBE_AN_MS_TIMEOUT 500 -#define XGBE_LINK_TIMEOUT 10 +#define XGBE_LINK_TIMEOUT 5 + +#define XGBE_SGMII_AN_LINK_STATUS BIT(1) +#define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3)) +#define XGBE_SGMII_AN_LINK_SPEED_100 0x04 +#define XGBE_SGMII_AN_LINK_SPEED_1000 0x08 +#define XGBE_SGMII_AN_LINK_DUPLEX BIT(4) struct xgbe_prv_data; @@ -467,6 +473,8 @@ enum xgbe_speed { enum xgbe_an_mode { XGBE_AN_MODE_CL73 = 0, + XGBE_AN_MODE_CL37, + XGBE_AN_MODE_CL37_SGMII, XGBE_AN_MODE_NONE, }; @@ -961,6 +969,7 @@ struct xgbe_prv_data { /* Auto-negotiation state machine support */ unsigned int an_int; + unsigned int an_status; struct mutex an_mutex; enum xgbe_an an_result; enum xgbe_an an_state; -- cgit v1.2.3 From b03a4a6fb309a000a0fba5f2af06ffc5767b0e45 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:18:56 -0500 Subject: amd-xgbe: Prepare for a new PCS register access method Prepare the code to be able to support accessing of the PCS registers in a new way, while maintaining the current access method. Provide a version specific field that indicates the method to use. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 21 +++--- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 107 +++++++++++++++++++++++++--- drivers/net/ethernet/amd/xgbe/xgbe-main.c | 1 + drivers/net/ethernet/amd/xgbe/xgbe.h | 9 +++ 4 files changed, 119 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 8bcf4ef050d6..6c40915d065b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -852,14 +852,9 @@ #define MTL_TSA_SP 0x00 #define MTL_TSA_ETS 0x02 -/* PCS MMD select register offset - * The MMD select register is used for accessing PCS registers - * when the underlying APB3 interface is using indirect addressing. - * Indirect addressing requires accessing registers in two phases, - * an address phase and a data phase. The address phases requires - * writing an address selection value to the MMD select regiesters. - */ -#define PCS_MMD_SELECT 0xff +/* PCS register offsets */ +#define PCS_V1_WINDOW_SELECT 0x03fc +#define PCS_V2_WINDOW_SELECT 0x9064 /* SerDes integration register offsets */ #define SIR0_KR_RT_1 0x002c @@ -1241,12 +1236,18 @@ do { \ /* Macros for building, reading or writing register values or bits * within the register values of XPCS registers. */ -#define XPCS_IOWRITE(_pdata, _off, _val) \ +#define XPCS32_IOWRITE(_pdata, _off, _val) \ iowrite32(_val, (_pdata)->xpcs_regs + (_off)) -#define XPCS_IOREAD(_pdata, _off) \ +#define XPCS32_IOREAD(_pdata, _off) \ ioread32((_pdata)->xpcs_regs + (_off)) +#define XPCS16_IOWRITE(_pdata, _off, _val) \ + iowrite16(_val, (_pdata)->xpcs_regs + (_off)) + +#define XPCS16_IOREAD(_pdata, _off) \ + ioread16((_pdata)->xpcs_regs + (_off)) + /* Macros for building, reading or writing register values or bits * within the register values of SerDes integration registers. */ diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 75c3df1251c8..b8a04e739344 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1026,8 +1026,71 @@ static int xgbe_config_rx_mode(struct xgbe_prv_data *pdata) return 0; } -static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad, - int mmd_reg) +static int xgbe_read_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad, + int mmd_reg) +{ + unsigned long flags; + unsigned int mmd_address, index, offset; + int mmd_data; + + if (mmd_reg & MII_ADDR_C45) + mmd_address = mmd_reg & ~MII_ADDR_C45; + else + mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); + + /* The PCS registers are accessed using mmio. The underlying + * management interface uses indirect addressing to access the MMD + * register sets. This requires accessing of the PCS register in two + * phases, an address phase and a data phase. + * + * The mmio interface is based on 16-bit offsets and values. All + * register offsets must therefore be adjusted by left shifting the + * offset 1 bit and reading 16 bits of data. + */ + mmd_address <<= 1; + index = mmd_address & ~pdata->xpcs_window_mask; + offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask); + + spin_lock_irqsave(&pdata->xpcs_lock, flags); + XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index); + mmd_data = XPCS16_IOREAD(pdata, offset); + spin_unlock_irqrestore(&pdata->xpcs_lock, flags); + + return mmd_data; +} + +static void xgbe_write_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad, + int mmd_reg, int mmd_data) +{ + unsigned long flags; + unsigned int mmd_address, index, offset; + + if (mmd_reg & MII_ADDR_C45) + mmd_address = mmd_reg & ~MII_ADDR_C45; + else + mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); + + /* The PCS registers are accessed using mmio. The underlying + * management interface uses indirect addressing to access the MMD + * register sets. This requires accessing of the PCS register in two + * phases, an address phase and a data phase. + * + * The mmio interface is based on 16-bit offsets and values. All + * register offsets must therefore be adjusted by left shifting the + * offset 1 bit and writing 16 bits of data. + */ + mmd_address <<= 1; + index = mmd_address & ~pdata->xpcs_window_mask; + offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask); + + spin_lock_irqsave(&pdata->xpcs_lock, flags); + XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index); + XPCS16_IOWRITE(pdata, offset, mmd_data); + spin_unlock_irqrestore(&pdata->xpcs_lock, flags); +} + +static int xgbe_read_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad, + int mmd_reg) { unsigned long flags; unsigned int mmd_address; @@ -1048,15 +1111,15 @@ static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad, * offset 2 bits and reading 32 bits of data. */ spin_lock_irqsave(&pdata->xpcs_lock, flags); - XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8); - mmd_data = XPCS_IOREAD(pdata, (mmd_address & 0xff) << 2); + XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8); + mmd_data = XPCS32_IOREAD(pdata, (mmd_address & 0xff) << 2); spin_unlock_irqrestore(&pdata->xpcs_lock, flags); return mmd_data; } -static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, - int mmd_reg, int mmd_data) +static void xgbe_write_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad, + int mmd_reg, int mmd_data) { unsigned int mmd_address; unsigned long flags; @@ -1073,14 +1136,40 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, * * The mmio interface is based on 32-bit offsets and values. All * register offsets must therefore be adjusted by left shifting the - * offset 2 bits and reading 32 bits of data. + * offset 2 bits and writing 32 bits of data. */ spin_lock_irqsave(&pdata->xpcs_lock, flags); - XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8); - XPCS_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data); + XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8); + XPCS32_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data); spin_unlock_irqrestore(&pdata->xpcs_lock, flags); } +static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad, + int mmd_reg) +{ + switch (pdata->vdata->xpcs_access) { + case XGBE_XPCS_ACCESS_V1: + return xgbe_read_mmd_regs_v1(pdata, prtad, mmd_reg); + + case XGBE_XPCS_ACCESS_V2: + default: + return xgbe_read_mmd_regs_v2(pdata, prtad, mmd_reg); + } +} + +static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, + int mmd_reg, int mmd_data) +{ + switch (pdata->vdata->xpcs_access) { + case XGBE_XPCS_ACCESS_V1: + return xgbe_write_mmd_regs_v1(pdata, prtad, mmd_reg, mmd_data); + + case XGBE_XPCS_ACCESS_V2: + default: + return xgbe_write_mmd_regs_v2(pdata, prtad, mmd_reg, mmd_data); + } +} + static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc) { return !XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 38c5985c52ef..d9864f0c331a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -785,6 +785,7 @@ static int xgbe_resume(struct device *dev) static const struct xgbe_version_data xgbe_v1 = { .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1, + .xpcs_access = XGBE_XPCS_ACCESS_V1, }; #ifdef CONFIG_ACPI diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 8cb4f20ddab4..160b4980b2eb 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -471,6 +471,11 @@ enum xgbe_speed { XGBE_SPEEDS, }; +enum xgbe_xpcs_access { + XGBE_XPCS_ACCESS_V1 = 0, + XGBE_XPCS_ACCESS_V2, +}; + enum xgbe_an_mode { XGBE_AN_MODE_CL73 = 0, XGBE_AN_MODE_CL37, @@ -798,6 +803,7 @@ struct xgbe_hw_features { struct xgbe_version_data { void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *); + enum xgbe_xpcs_access xpcs_access; }; struct xgbe_prv_data { @@ -826,6 +832,9 @@ struct xgbe_prv_data { /* XPCS indirect addressing lock */ spinlock_t xpcs_lock; + unsigned int xpcs_window; + unsigned int xpcs_window_size; + unsigned int xpcs_window_mask; /* RSS addressing mutex */ struct mutex rss_mutex; -- cgit v1.2.3 From e5a20b9072eb38fad9b8cff4e6824c6cdbee5a00 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:19:07 -0500 Subject: amd-xgbe: Support for 64-bit management counter registers Add support for reading all management counter registers as 64-bit values. The indication of whether to read the high 32-bits to form a 64-bit value is indicated in the version data. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 36 +++++++++++++++++++++++--------- drivers/net/ethernet/amd/xgbe/xgbe.h | 1 + 2 files changed, 27 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index b8a04e739344..fbd60ee0260b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -2588,17 +2588,33 @@ static u64 xgbe_mmc_read(struct xgbe_prv_data *pdata, unsigned int reg_lo) bool read_hi; u64 val; - switch (reg_lo) { - /* These registers are always 64 bit */ - case MMC_TXOCTETCOUNT_GB_LO: - case MMC_TXOCTETCOUNT_G_LO: - case MMC_RXOCTETCOUNT_GB_LO: - case MMC_RXOCTETCOUNT_G_LO: - read_hi = true; - break; + if (pdata->vdata->mmc_64bit) { + switch (reg_lo) { + /* These registers are always 32 bit */ + case MMC_RXRUNTERROR: + case MMC_RXJABBERERROR: + case MMC_RXUNDERSIZE_G: + case MMC_RXOVERSIZE_G: + case MMC_RXWATCHDOGERROR: + read_hi = false; + break; - default: - read_hi = false; + default: + read_hi = true; + } + } else { + switch (reg_lo) { + /* These registers are always 64 bit */ + case MMC_TXOCTETCOUNT_GB_LO: + case MMC_TXOCTETCOUNT_G_LO: + case MMC_RXOCTETCOUNT_GB_LO: + case MMC_RXOCTETCOUNT_G_LO: + read_hi = true; + break; + + default: + read_hi = false; + } } val = XGMAC_IOREAD(pdata, reg_lo); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 160b4980b2eb..7cbf91b4aa79 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -804,6 +804,7 @@ struct xgbe_hw_features { struct xgbe_version_data { void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *); enum xgbe_xpcs_access xpcs_access; + unsigned int mmc_64bit; }; struct xgbe_prv_data { -- cgit v1.2.3 From 4b8acdf5fe97d01962f3a62eaff3f010f8de5869 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:19:17 -0500 Subject: amd-xgbe: Update how to determine DMA channel status Tx and Rx DMA channel status determiniation is different depending on the version of the hardware. Update the channel status processing code to account for the change. Also, reduce the timeout value used when stopping the channels. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 4 ++ drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 58 +++++++++++++++++++---------- drivers/net/ethernet/amd/xgbe/xgbe.h | 2 +- 3 files changed, 43 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 6c40915d065b..8036ee52add6 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -790,6 +790,10 @@ #define MTL_Q_RQOMR_RSF_WIDTH 1 #define MTL_Q_RQOMR_RTC_INDEX 0 #define MTL_Q_RQOMR_RTC_WIDTH 2 +#define MTL_Q_TQDR_TRCSTS_INDEX 1 +#define MTL_Q_TQDR_TRCSTS_WIDTH 2 +#define MTL_Q_TQDR_TXQSTS_INDEX 4 +#define MTL_Q_TQDR_TXQSTS_WIDTH 1 #define MTL_Q_TQOMR_FTQ_INDEX 0 #define MTL_Q_TQOMR_FTQ_WIDTH 1 #define MTL_Q_TQOMR_Q2TCMAP_INDEX 8 diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index fbd60ee0260b..0a7ab63deaf9 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -2944,20 +2944,48 @@ static void xgbe_config_mmc(struct xgbe_prv_data *pdata) XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1); } +static void xgbe_txq_prepare_tx_stop(struct xgbe_prv_data *pdata, + unsigned int queue) +{ + unsigned int tx_status; + unsigned long tx_timeout; + + /* The Tx engine cannot be stopped if it is actively processing + * packets. Wait for the Tx queue to empty the Tx fifo. Don't + * wait forever though... + */ + tx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ); + while (time_before(jiffies, tx_timeout)) { + tx_status = XGMAC_MTL_IOREAD(pdata, queue, MTL_Q_TQDR); + if ((XGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TRCSTS) != 1) && + (XGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TXQSTS) == 0)) + break; + + usleep_range(500, 1000); + } + + if (!time_before(jiffies, tx_timeout)) + netdev_info(pdata->netdev, + "timed out waiting for Tx queue %u to empty\n", + queue); +} + static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata, - struct xgbe_channel *channel) + unsigned int queue) { unsigned int tx_dsr, tx_pos, tx_qidx; unsigned int tx_status; unsigned long tx_timeout; + if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) > 0x20) + return xgbe_txq_prepare_tx_stop(pdata, queue); + /* Calculate the status register to read and the position within */ - if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) { + if (queue < DMA_DSRX_FIRST_QUEUE) { tx_dsr = DMA_DSR0; - tx_pos = (channel->queue_index * DMA_DSR_Q_WIDTH) + - DMA_DSR0_TPS_START; + tx_pos = (queue * DMA_DSR_Q_WIDTH) + DMA_DSR0_TPS_START; } else { - tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE; + tx_qidx = queue - DMA_DSRX_FIRST_QUEUE; tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC); tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) + @@ -2982,7 +3010,7 @@ static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata, if (!time_before(jiffies, tx_timeout)) netdev_info(pdata->netdev, "timed out waiting for Tx DMA channel %u to stop\n", - channel->queue_index); + queue); } static void xgbe_enable_tx(struct xgbe_prv_data *pdata) @@ -3014,13 +3042,8 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata) unsigned int i; /* Prepare for Tx DMA channel stop */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - - xgbe_prepare_tx_stop(pdata, channel); - } + for (i = 0; i < pdata->tx_q_count; i++) + xgbe_prepare_tx_stop(pdata, i); /* Disable MAC Tx */ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0); @@ -3144,13 +3167,8 @@ static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata) unsigned int i; /* Prepare for Tx DMA channel stop */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - - xgbe_prepare_tx_stop(pdata, channel); - } + for (i = 0; i < pdata->tx_q_count; i++) + xgbe_prepare_tx_stop(pdata, i); /* Disable MAC Tx */ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 7cbf91b4aa79..d5cae1557908 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -159,7 +159,7 @@ #define XGBE_MAX_DMA_CHANNELS 16 #define XGBE_MAX_QUEUES 16 #define XGBE_PRIORITY_QUEUES 8 -#define XGBE_DMA_STOP_TIMEOUT 5 +#define XGBE_DMA_STOP_TIMEOUT 1 /* DMA cache settings - Outer sharable, write-back, write-allocate */ #define XGBE_DMA_OS_AXDOMAIN 0x2 -- cgit v1.2.3 From bd8255d8ba35ae03f0a6d4d7d55b46660f2fc198 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Thu, 3 Nov 2016 13:19:27 -0500 Subject: amd-xgbe: Prepare for supporting PCI devices Update the driver framework to separate out platform/ACPI specific code from general code during device initialization. This will allow for the introduction of PCI device support. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/Makefile | 3 +- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 16 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 22 +- drivers/net/ethernet/amd/xgbe/xgbe-main.c | 569 ++++------------------- drivers/net/ethernet/amd/xgbe/xgbe-platform.c | 632 ++++++++++++++++++++++++++ drivers/net/ethernet/amd/xgbe/xgbe.h | 23 +- 6 files changed, 755 insertions(+), 510 deletions(-) create mode 100644 drivers/net/ethernet/amd/xgbe/xgbe-platform.c (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/Makefile b/drivers/net/ethernet/amd/xgbe/Makefile index 60b4ae2f05fb..217d59ea1c52 100644 --- a/drivers/net/ethernet/amd/xgbe/Makefile +++ b/drivers/net/ethernet/amd/xgbe/Makefile @@ -3,7 +3,8 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \ xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \ xgbe-ptp.o \ - xgbe-phy-v1.o + xgbe-phy-v1.o \ + xgbe-platform.o amd-xgbe-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o amd-xgbe-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 0a7ab63deaf9..903731902153 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -2088,24 +2088,16 @@ static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata) static unsigned int xgbe_get_tx_fifo_size(struct xgbe_prv_data *pdata) { - unsigned int fifo_size; - - /* Calculate the configured fifo size */ - fifo_size = 1 << (pdata->hw_feat.tx_fifo_size + 7); - /* The configured value may not be the actual amount of fifo RAM */ - return min_t(unsigned int, XGMAC_FIFO_TX_MAX, fifo_size); + return min_t(unsigned int, pdata->tx_max_fifo_size, + pdata->hw_feat.tx_fifo_size); } static unsigned int xgbe_get_rx_fifo_size(struct xgbe_prv_data *pdata) { - unsigned int fifo_size; - - /* Calculate the configured fifo size */ - fifo_size = 1 << (pdata->hw_feat.rx_fifo_size + 7); - /* The configured value may not be the actual amount of fifo RAM */ - return min_t(unsigned int, XGMAC_FIFO_RX_MAX, fifo_size); + return min_t(unsigned int, pdata->rx_max_fifo_size, + pdata->hw_feat.rx_fifo_size); } static void xgbe_calculate_equal_fifo(unsigned int fifo_size, diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index dd166a003572..a43e9303be90 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -114,7 +114,6 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include @@ -160,18 +159,8 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + (DMA_CH_INC * i); - if (pdata->per_channel_irq) { - /* Get the DMA interrupt (offset 1) */ - ret = platform_get_irq(pdata->pdev, i + 1); - if (ret < 0) { - netdev_err(pdata->netdev, - "platform_get_irq %u failed\n", - i + 1); - goto err_irq; - } - - channel->dma_irq = ret; - } + if (pdata->per_channel_irq) + channel->dma_irq = pdata->channel_irq[i]; if (i < pdata->tx_ring_count) { spin_lock_init(&tx_ring->lock); @@ -194,9 +183,6 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) return 0; -err_irq: - kfree(rx_ring); - err_rx_ring: kfree(tx_ring); @@ -590,6 +576,10 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) hw_feat->tx_ch_cnt++; hw_feat->tc_cnt++; + /* Translate the fifo sizes into actual numbers */ + hw_feat->rx_fifo_size = 1 << (hw_feat->rx_fifo_size + 7); + hw_feat->tx_fifo_size = 1 << (hw_feat->tx_fifo_size + 7); + DBGPR("<--xgbe_get_all_hw_features\n"); } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index d9864f0c331a..c7187fca5fb7 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -116,20 +116,10 @@ #include #include -#include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "xgbe.h" #include "xgbe-common.h" @@ -176,196 +166,21 @@ static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata) pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if); } -#ifdef CONFIG_ACPI -static const struct acpi_device_id xgbe_acpi_match[]; - -static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata) -{ - const struct acpi_device_id *id; - - id = acpi_match_device(xgbe_acpi_match, pdata->dev); - - return id ? (struct xgbe_version_data *)id->driver_data : NULL; -} - -static int xgbe_acpi_support(struct xgbe_prv_data *pdata) -{ - struct device *dev = pdata->dev; - u32 property; - int ret; - - /* Obtain the system clock setting */ - ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property); - if (ret) { - dev_err(dev, "unable to obtain %s property\n", - XGBE_ACPI_DMA_FREQ); - return ret; - } - pdata->sysclk_rate = property; - - /* Obtain the PTP clock setting */ - ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property); - if (ret) { - dev_err(dev, "unable to obtain %s property\n", - XGBE_ACPI_PTP_FREQ); - return ret; - } - pdata->ptpclk_rate = property; - - return 0; -} -#else /* CONFIG_ACPI */ -static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata) -{ - return NULL; -} - -static int xgbe_acpi_support(struct xgbe_prv_data *pdata) -{ - return -EINVAL; -} -#endif /* CONFIG_ACPI */ - -#ifdef CONFIG_OF -static const struct of_device_id xgbe_of_match[]; - -static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata) -{ - const struct of_device_id *id; - - id = of_match_device(xgbe_of_match, pdata->dev); - - return id ? (struct xgbe_version_data *)id->data : NULL; -} - -static int xgbe_of_support(struct xgbe_prv_data *pdata) -{ - struct device *dev = pdata->dev; - - /* Obtain the system clock setting */ - pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK); - if (IS_ERR(pdata->sysclk)) { - dev_err(dev, "dma devm_clk_get failed\n"); - return PTR_ERR(pdata->sysclk); - } - pdata->sysclk_rate = clk_get_rate(pdata->sysclk); - - /* Obtain the PTP clock setting */ - pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK); - if (IS_ERR(pdata->ptpclk)) { - dev_err(dev, "ptp devm_clk_get failed\n"); - return PTR_ERR(pdata->ptpclk); - } - pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk); - - return 0; -} - -static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata) -{ - struct device *dev = pdata->dev; - struct device_node *phy_node; - struct platform_device *phy_pdev; - - phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0); - if (phy_node) { - /* Old style device tree: - * The XGBE and PHY resources are separate - */ - phy_pdev = of_find_device_by_node(phy_node); - of_node_put(phy_node); - } else { - /* New style device tree: - * The XGBE and PHY resources are grouped together with - * the PHY resources listed last - */ - get_device(dev); - phy_pdev = pdata->pdev; - } - - return phy_pdev; -} -#else /* CONFIG_OF */ -static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata) -{ - return NULL; -} - -static int xgbe_of_support(struct xgbe_prv_data *pdata) -{ - return -EINVAL; -} - -static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata) -{ - return NULL; -} -#endif /* CONFIG_OF */ - -static unsigned int xgbe_resource_count(struct platform_device *pdev, - unsigned int type) -{ - unsigned int count; - int i; - - for (i = 0, count = 0; i < pdev->num_resources; i++) { - struct resource *res = &pdev->resource[i]; - - if (type == resource_type(res)) - count++; - } - - return count; -} - -static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata) -{ - struct platform_device *phy_pdev; - - if (pdata->use_acpi) { - get_device(pdata->dev); - phy_pdev = pdata->pdev; - } else { - phy_pdev = xgbe_of_get_phy_pdev(pdata); - } - - return phy_pdev; -} - -static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata) -{ - return pdata->use_acpi ? xgbe_acpi_vdata(pdata) - : xgbe_of_vdata(pdata); -} - -static int xgbe_probe(struct platform_device *pdev) +struct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev) { struct xgbe_prv_data *pdata; struct net_device *netdev; - struct device *dev = &pdev->dev; - struct platform_device *phy_pdev; - struct resource *res; - const char *phy_mode; - unsigned int i, phy_memnum, phy_irqnum; - enum dev_dma_attr attr; - int ret; - - DBGPR("--> xgbe_probe\n"); netdev = alloc_etherdev_mq(sizeof(struct xgbe_prv_data), XGBE_MAX_DMA_CHANNELS); if (!netdev) { - dev_err(dev, "alloc_etherdev failed\n"); - ret = -ENOMEM; - goto err_alloc; + dev_err(dev, "alloc_etherdev_mq failed\n"); + return ERR_PTR(-ENOMEM); } SET_NETDEV_DEV(netdev, dev); pdata = netdev_priv(netdev); pdata->netdev = netdev; - pdata->pdev = pdev; - pdata->adev = ACPI_COMPANION(dev); pdata->dev = dev; - platform_set_drvdata(pdev, netdev); spin_lock_init(&pdata->lock); spin_lock_init(&pdata->xpcs_lock); @@ -376,186 +191,82 @@ static int xgbe_probe(struct platform_device *pdev) set_bit(XGBE_DOWN, &pdata->dev_state); - /* Check if we should use ACPI or DT */ - pdata->use_acpi = dev->of_node ? 0 : 1; + return pdata; +} - /* Get the version data */ - pdata->vdata = xgbe_get_vdata(pdata); +void xgbe_free_pdata(struct xgbe_prv_data *pdata) +{ + struct net_device *netdev = pdata->netdev; - phy_pdev = xgbe_get_phy_pdev(pdata); - if (!phy_pdev) { - dev_err(dev, "unable to obtain phy device\n"); - ret = -EINVAL; - goto err_phydev; - } - pdata->phy_pdev = phy_pdev; - pdata->phy_dev = &phy_pdev->dev; - - if (pdev == phy_pdev) { - /* New style device tree or ACPI: - * The XGBE and PHY resources are grouped together with - * the PHY resources listed last - */ - phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3; - phy_irqnum = xgbe_resource_count(pdev, IORESOURCE_IRQ) - 1; - } else { - /* Old style device tree: - * The XGBE and PHY resources are separate - */ - phy_memnum = 0; - phy_irqnum = 0; - } + free_netdev(netdev); +} - /* Set and validate the number of descriptors for a ring */ - BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT); - pdata->tx_desc_count = XGBE_TX_DESC_CNT; - if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) { - dev_err(dev, "tx descriptor count (%d) is not valid\n", - pdata->tx_desc_count); - ret = -EINVAL; - goto err_io; - } - BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT); - pdata->rx_desc_count = XGBE_RX_DESC_CNT; - if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) { - dev_err(dev, "rx descriptor count (%d) is not valid\n", - pdata->rx_desc_count); - ret = -EINVAL; - goto err_io; - } +void xgbe_set_counts(struct xgbe_prv_data *pdata) +{ + /* Set all the function pointers */ + xgbe_init_all_fptrs(pdata); - /* Obtain the mmio areas for the device */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pdata->xgmac_regs = devm_ioremap_resource(dev, res); - if (IS_ERR(pdata->xgmac_regs)) { - dev_err(dev, "xgmac ioremap failed\n"); - ret = PTR_ERR(pdata->xgmac_regs); - goto err_io; - } - if (netif_msg_probe(pdata)) - dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - pdata->xpcs_regs = devm_ioremap_resource(dev, res); - if (IS_ERR(pdata->xpcs_regs)) { - dev_err(dev, "xpcs ioremap failed\n"); - ret = PTR_ERR(pdata->xpcs_regs); - goto err_io; - } - if (netif_msg_probe(pdata)) - dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs); - - res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); - pdata->rxtx_regs = devm_ioremap_resource(dev, res); - if (IS_ERR(pdata->rxtx_regs)) { - dev_err(dev, "rxtx ioremap failed\n"); - ret = PTR_ERR(pdata->rxtx_regs); - goto err_io; - } - if (netif_msg_probe(pdata)) - dev_dbg(dev, "rxtx_regs = %p\n", pdata->rxtx_regs); - - res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); - pdata->sir0_regs = devm_ioremap_resource(dev, res); - if (IS_ERR(pdata->sir0_regs)) { - dev_err(dev, "sir0 ioremap failed\n"); - ret = PTR_ERR(pdata->sir0_regs); - goto err_io; - } - if (netif_msg_probe(pdata)) - dev_dbg(dev, "sir0_regs = %p\n", pdata->sir0_regs); - - res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); - pdata->sir1_regs = devm_ioremap_resource(dev, res); - if (IS_ERR(pdata->sir1_regs)) { - dev_err(dev, "sir1 ioremap failed\n"); - ret = PTR_ERR(pdata->sir1_regs); - goto err_io; - } - if (netif_msg_probe(pdata)) - dev_dbg(dev, "sir1_regs = %p\n", pdata->sir1_regs); - - /* Retrieve the MAC address */ - ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY, - pdata->mac_addr, - sizeof(pdata->mac_addr)); - if (ret || !is_valid_ether_addr(pdata->mac_addr)) { - dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY); - if (!ret) - ret = -EINVAL; - goto err_io; - } + /* Populate the hardware features */ + xgbe_get_all_hw_features(pdata); - /* Retrieve the PHY mode - it must be "xgmii" */ - ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY, - &phy_mode); - if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) { - dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY); - if (!ret) - ret = -EINVAL; - goto err_io; - } - pdata->phy_mode = PHY_INTERFACE_MODE_XGMII; + /* Set default max values if not provided */ + if (!pdata->tx_max_channel_count) + pdata->tx_max_channel_count = pdata->hw_feat.tx_ch_cnt; + if (!pdata->rx_max_channel_count) + pdata->rx_max_channel_count = pdata->hw_feat.rx_ch_cnt; - /* Check for per channel interrupt support */ - if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY)) - pdata->per_channel_irq = 1; + if (!pdata->tx_max_q_count) + pdata->tx_max_q_count = pdata->hw_feat.tx_q_cnt; + if (!pdata->rx_max_q_count) + pdata->rx_max_q_count = pdata->hw_feat.rx_q_cnt; - /* Obtain device settings unique to ACPI/OF */ - if (pdata->use_acpi) - ret = xgbe_acpi_support(pdata); - else - ret = xgbe_of_support(pdata); - if (ret) - goto err_io; - - /* Set the DMA coherency values */ - attr = device_get_dma_attr(dev); - if (attr == DEV_DMA_NOT_SUPPORTED) { - dev_err(dev, "DMA is not supported"); - ret = -ENODEV; - goto err_io; - } - pdata->coherent = (attr == DEV_DMA_COHERENT); - if (pdata->coherent) { - pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; - pdata->arcache = XGBE_DMA_OS_ARCACHE; - pdata->awcache = XGBE_DMA_OS_AWCACHE; - } else { - pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN; - pdata->arcache = XGBE_DMA_SYS_ARCACHE; - pdata->awcache = XGBE_DMA_SYS_AWCACHE; - } + /* Calculate the number of Tx and Rx rings to be created + * -Tx (DMA) Channels map 1-to-1 to Tx Queues so set + * the number of Tx queues to the number of Tx channels + * enabled + * -Rx (DMA) Channels do not map 1-to-1 so use the actual + * number of Rx queues or maximum allowed + */ + pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(), + pdata->hw_feat.tx_ch_cnt); + pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count, + pdata->tx_max_channel_count); + pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count, + pdata->tx_max_q_count); - /* Get the device interrupt */ - ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "platform_get_irq 0 failed\n"); - goto err_io; - } - pdata->dev_irq = ret; + pdata->tx_q_count = pdata->tx_ring_count; + + pdata->rx_ring_count = min_t(unsigned int, + netif_get_num_default_rss_queues(), + pdata->hw_feat.rx_ch_cnt); + pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count, + pdata->rx_max_channel_count); + + pdata->rx_q_count = min_t(unsigned int, pdata->hw_feat.rx_q_cnt, + pdata->rx_max_q_count); - /* Get the auto-negotiation interrupt */ - ret = platform_get_irq(phy_pdev, phy_irqnum++); - if (ret < 0) { - dev_err(dev, "platform_get_irq phy 0 failed\n"); - goto err_io; + if (netif_msg_probe(pdata)) { + dev_dbg(pdata->dev, "TX/RX DMA channel count = %u/%u\n", + pdata->tx_ring_count, pdata->rx_ring_count); + dev_dbg(pdata->dev, "TX/RX hardware queue count = %u/%u\n", + pdata->tx_q_count, pdata->rx_q_count); } - pdata->an_irq = ret; +} + +int xgbe_config_netdev(struct xgbe_prv_data *pdata) +{ + struct net_device *netdev = pdata->netdev; + struct device *dev = pdata->dev; + unsigned int i; + int ret; netdev->irq = pdata->dev_irq; netdev->base_addr = (unsigned long)pdata->xgmac_regs; memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len); - /* Set all the function pointers */ - xgbe_init_all_fptrs(pdata); - /* Issue software reset to device */ pdata->hw_if.exit(pdata); - /* Populate the hardware features */ - xgbe_get_all_hw_features(pdata); - /* Set default configuration data */ xgbe_default_config(pdata); @@ -564,33 +275,33 @@ static int xgbe_probe(struct platform_device *pdev) DMA_BIT_MASK(pdata->hw_feat.dma_width)); if (ret) { dev_err(dev, "dma_set_mask_and_coherent failed\n"); - goto err_io; + return ret; } - /* Calculate the number of Tx and Rx rings to be created - * -Tx (DMA) Channels map 1-to-1 to Tx Queues so set - * the number of Tx queues to the number of Tx channels - * enabled - * -Rx (DMA) Channels do not map 1-to-1 so use the actual - * number of Rx queues - */ - pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(), - pdata->hw_feat.tx_ch_cnt); - pdata->tx_q_count = pdata->tx_ring_count; + /* Set default max values if not provided */ + if (!pdata->tx_max_fifo_size) + pdata->tx_max_fifo_size = pdata->hw_feat.tx_fifo_size; + if (!pdata->rx_max_fifo_size) + pdata->rx_max_fifo_size = pdata->hw_feat.rx_fifo_size; + + /* Set and validate the number of descriptors for a ring */ + BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT); + pdata->tx_desc_count = XGBE_TX_DESC_CNT; + + BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT); + pdata->rx_desc_count = XGBE_RX_DESC_CNT; + + /* Set the number of queues */ ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count); if (ret) { dev_err(dev, "error setting real tx queue count\n"); - goto err_io; + return ret; } - pdata->rx_ring_count = min_t(unsigned int, - netif_get_num_default_rss_queues(), - pdata->hw_feat.rx_ch_cnt); - pdata->rx_q_count = pdata->hw_feat.rx_q_cnt; ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count); if (ret) { dev_err(dev, "error setting real rx queue count\n"); - goto err_io; + return ret; } /* Initialize RSS hash key and lookup table */ @@ -607,7 +318,7 @@ static int xgbe_probe(struct platform_device *pdev) /* Call MDIO/PHY initialization routine */ ret = pdata->phy_if.phy_init(pdata); if (ret) - goto err_io; + return ret; /* Set device operations */ netdev->netdev_ops = xgbe_get_netdev_ops(); @@ -654,7 +365,7 @@ static int xgbe_probe(struct platform_device *pdev) ret = register_netdev(netdev); if (ret) { dev_err(dev, "net device registration failed\n"); - goto err_io; + return ret; } /* Create the PHY/ANEG name based on netdev name */ @@ -682,10 +393,6 @@ static int xgbe_probe(struct platform_device *pdev) xgbe_debugfs_init(pdata); - netdev_notice(netdev, "net device enabled\n"); - - DBGPR("<-- xgbe_probe\n"); - return 0; err_wq: @@ -694,24 +401,12 @@ err_wq: err_netdev: unregister_netdev(netdev); -err_io: - platform_device_put(phy_pdev); - -err_phydev: - free_netdev(netdev); - -err_alloc: - dev_notice(dev, "net device not enabled\n"); - return ret; } -static int xgbe_remove(struct platform_device *pdev) +void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata) { - struct net_device *netdev = platform_get_drvdata(pdev); - struct xgbe_prv_data *pdata = netdev_priv(netdev); - - DBGPR("-->xgbe_remove\n"); + struct net_device *netdev = pdata->netdev; xgbe_debugfs_exit(pdata); @@ -726,103 +421,23 @@ static int xgbe_remove(struct platform_device *pdev) destroy_workqueue(pdata->dev_workqueue); unregister_netdev(netdev); - - platform_device_put(pdata->phy_pdev); - - free_netdev(netdev); - - DBGPR("<--xgbe_remove\n"); - - return 0; } -#ifdef CONFIG_PM -static int xgbe_suspend(struct device *dev) +static int __init xgbe_mod_init(void) { - struct net_device *netdev = dev_get_drvdata(dev); - struct xgbe_prv_data *pdata = netdev_priv(netdev); - int ret = 0; - - DBGPR("-->xgbe_suspend\n"); - - if (netif_running(netdev)) - ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT); - - pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); - pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); + int ret; - DBGPR("<--xgbe_suspend\n"); + ret = xgbe_platform_init(); + if (ret) + return ret; - return ret; + return 0; } -static int xgbe_resume(struct device *dev) +static void __exit xgbe_mod_exit(void) { - struct net_device *netdev = dev_get_drvdata(dev); - struct xgbe_prv_data *pdata = netdev_priv(netdev); - int ret = 0; - - DBGPR("-->xgbe_resume\n"); - - pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER; - XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); - - if (netif_running(netdev)) { - ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT); - - /* Schedule a restart in case the link or phy state changed - * while we were powered down. - */ - schedule_work(&pdata->restart_work); - } - - DBGPR("<--xgbe_resume\n"); - - return ret; + xgbe_platform_exit(); } -#endif /* CONFIG_PM */ - -static const struct xgbe_version_data xgbe_v1 = { - .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1, - .xpcs_access = XGBE_XPCS_ACCESS_V1, -}; - -#ifdef CONFIG_ACPI -static const struct acpi_device_id xgbe_acpi_match[] = { - { .id = "AMDI8001", - .driver_data = (kernel_ulong_t)&xgbe_v1 }, - {}, -}; - -MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match); -#endif - -#ifdef CONFIG_OF -static const struct of_device_id xgbe_of_match[] = { - { .compatible = "amd,xgbe-seattle-v1a", - .data = &xgbe_v1 }, - {}, -}; - -MODULE_DEVICE_TABLE(of, xgbe_of_match); -#endif - -static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume); - -static struct platform_driver xgbe_driver = { - .driver = { - .name = "amd-xgbe", -#ifdef CONFIG_ACPI - .acpi_match_table = xgbe_acpi_match, -#endif -#ifdef CONFIG_OF - .of_match_table = xgbe_of_match, -#endif - .pm = &xgbe_pm_ops, - }, - .probe = xgbe_probe, - .remove = xgbe_remove, -}; -module_platform_driver(xgbe_driver); +module_init(xgbe_mod_init); +module_exit(xgbe_mod_exit); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c new file mode 100644 index 000000000000..0edbcd523f8f --- /dev/null +++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c @@ -0,0 +1,632 @@ +/* + * AMD 10Gb Ethernet driver + * + * This file is available to you under your choice of the following two + * licenses: + * + * License 1: GPLv2 + * + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. + * + * This file is free software; you may copy, redistribute and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or (at + * your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * + * License 2: Modified BSD + * + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices, Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xgbe.h" +#include "xgbe-common.h" + +#ifdef CONFIG_ACPI +static const struct acpi_device_id xgbe_acpi_match[]; + +static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(xgbe_acpi_match, pdata->dev); + + return id ? (struct xgbe_version_data *)id->driver_data : NULL; +} + +static int xgbe_acpi_support(struct xgbe_prv_data *pdata) +{ + struct device *dev = pdata->dev; + u32 property; + int ret; + + /* Obtain the system clock setting */ + ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property); + if (ret) { + dev_err(dev, "unable to obtain %s property\n", + XGBE_ACPI_DMA_FREQ); + return ret; + } + pdata->sysclk_rate = property; + + /* Obtain the PTP clock setting */ + ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property); + if (ret) { + dev_err(dev, "unable to obtain %s property\n", + XGBE_ACPI_PTP_FREQ); + return ret; + } + pdata->ptpclk_rate = property; + + return 0; +} +#else /* CONFIG_ACPI */ +static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata) +{ + return NULL; +} + +static int xgbe_acpi_support(struct xgbe_prv_data *pdata) +{ + return -EINVAL; +} +#endif /* CONFIG_ACPI */ + +#ifdef CONFIG_OF +static const struct of_device_id xgbe_of_match[]; + +static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata) +{ + const struct of_device_id *id; + + id = of_match_device(xgbe_of_match, pdata->dev); + + return id ? (struct xgbe_version_data *)id->data : NULL; +} + +static int xgbe_of_support(struct xgbe_prv_data *pdata) +{ + struct device *dev = pdata->dev; + + /* Obtain the system clock setting */ + pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK); + if (IS_ERR(pdata->sysclk)) { + dev_err(dev, "dma devm_clk_get failed\n"); + return PTR_ERR(pdata->sysclk); + } + pdata->sysclk_rate = clk_get_rate(pdata->sysclk); + + /* Obtain the PTP clock setting */ + pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK); + if (IS_ERR(pdata->ptpclk)) { + dev_err(dev, "ptp devm_clk_get failed\n"); + return PTR_ERR(pdata->ptpclk); + } + pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk); + + return 0; +} + +static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata) +{ + struct device *dev = pdata->dev; + struct device_node *phy_node; + struct platform_device *phy_pdev; + + phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0); + if (phy_node) { + /* Old style device tree: + * The XGBE and PHY resources are separate + */ + phy_pdev = of_find_device_by_node(phy_node); + of_node_put(phy_node); + } else { + /* New style device tree: + * The XGBE and PHY resources are grouped together with + * the PHY resources listed last + */ + get_device(dev); + phy_pdev = pdata->platdev; + } + + return phy_pdev; +} +#else /* CONFIG_OF */ +static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata) +{ + return NULL; +} + +static int xgbe_of_support(struct xgbe_prv_data *pdata) +{ + return -EINVAL; +} + +static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata) +{ + return NULL; +} +#endif /* CONFIG_OF */ + +static unsigned int xgbe_resource_count(struct platform_device *pdev, + unsigned int type) +{ + unsigned int count; + int i; + + for (i = 0, count = 0; i < pdev->num_resources; i++) { + struct resource *res = &pdev->resource[i]; + + if (type == resource_type(res)) + count++; + } + + return count; +} + +static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata) +{ + struct platform_device *phy_pdev; + + if (pdata->use_acpi) { + get_device(pdata->dev); + phy_pdev = pdata->platdev; + } else { + phy_pdev = xgbe_of_get_phy_pdev(pdata); + } + + return phy_pdev; +} + +static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata) +{ + return pdata->use_acpi ? xgbe_acpi_vdata(pdata) + : xgbe_of_vdata(pdata); +} + +static int xgbe_platform_probe(struct platform_device *pdev) +{ + struct xgbe_prv_data *pdata; + struct device *dev = &pdev->dev; + struct platform_device *phy_pdev; + struct resource *res; + const char *phy_mode; + unsigned int phy_memnum, phy_irqnum; + unsigned int dma_irqnum, dma_irqend; + enum dev_dma_attr attr; + int ret; + + pdata = xgbe_alloc_pdata(dev); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + goto err_alloc; + } + + pdata->platdev = pdev; + pdata->adev = ACPI_COMPANION(dev); + platform_set_drvdata(pdev, pdata); + + /* Check if we should use ACPI or DT */ + pdata->use_acpi = dev->of_node ? 0 : 1; + + /* Get the version data */ + pdata->vdata = xgbe_get_vdata(pdata); + + phy_pdev = xgbe_get_phy_pdev(pdata); + if (!phy_pdev) { + dev_err(dev, "unable to obtain phy device\n"); + ret = -EINVAL; + goto err_phydev; + } + pdata->phy_platdev = phy_pdev; + pdata->phy_dev = &phy_pdev->dev; + + if (pdev == phy_pdev) { + /* New style device tree or ACPI: + * The XGBE and PHY resources are grouped together with + * the PHY resources listed last + */ + phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3; + phy_irqnum = xgbe_resource_count(pdev, IORESOURCE_IRQ) - 1; + dma_irqnum = 1; + dma_irqend = phy_irqnum; + } else { + /* Old style device tree: + * The XGBE and PHY resources are separate + */ + phy_memnum = 0; + phy_irqnum = 0; + dma_irqnum = 1; + dma_irqend = xgbe_resource_count(pdev, IORESOURCE_IRQ); + } + + /* Obtain the mmio areas for the device */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pdata->xgmac_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(pdata->xgmac_regs)) { + dev_err(dev, "xgmac ioremap failed\n"); + ret = PTR_ERR(pdata->xgmac_regs); + goto err_io; + } + if (netif_msg_probe(pdata)) + dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + pdata->xpcs_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(pdata->xpcs_regs)) { + dev_err(dev, "xpcs ioremap failed\n"); + ret = PTR_ERR(pdata->xpcs_regs); + goto err_io; + } + if (netif_msg_probe(pdata)) + dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs); + + res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); + pdata->rxtx_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(pdata->rxtx_regs)) { + dev_err(dev, "rxtx ioremap failed\n"); + ret = PTR_ERR(pdata->rxtx_regs); + goto err_io; + } + if (netif_msg_probe(pdata)) + dev_dbg(dev, "rxtx_regs = %p\n", pdata->rxtx_regs); + + res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); + pdata->sir0_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(pdata->sir0_regs)) { + dev_err(dev, "sir0 ioremap failed\n"); + ret = PTR_ERR(pdata->sir0_regs); + goto err_io; + } + if (netif_msg_probe(pdata)) + dev_dbg(dev, "sir0_regs = %p\n", pdata->sir0_regs); + + res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); + pdata->sir1_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(pdata->sir1_regs)) { + dev_err(dev, "sir1 ioremap failed\n"); + ret = PTR_ERR(pdata->sir1_regs); + goto err_io; + } + if (netif_msg_probe(pdata)) + dev_dbg(dev, "sir1_regs = %p\n", pdata->sir1_regs); + + /* Retrieve the MAC address */ + ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY, + pdata->mac_addr, + sizeof(pdata->mac_addr)); + if (ret || !is_valid_ether_addr(pdata->mac_addr)) { + dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY); + if (!ret) + ret = -EINVAL; + goto err_io; + } + + /* Retrieve the PHY mode - it must be "xgmii" */ + ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY, + &phy_mode); + if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) { + dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY); + if (!ret) + ret = -EINVAL; + goto err_io; + } + pdata->phy_mode = PHY_INTERFACE_MODE_XGMII; + + /* Check for per channel interrupt support */ + if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY)) + pdata->per_channel_irq = 1; + + /* Obtain device settings unique to ACPI/OF */ + if (pdata->use_acpi) + ret = xgbe_acpi_support(pdata); + else + ret = xgbe_of_support(pdata); + if (ret) + goto err_io; + + /* Set the DMA coherency values */ + attr = device_get_dma_attr(dev); + if (attr == DEV_DMA_NOT_SUPPORTED) { + dev_err(dev, "DMA is not supported"); + ret = -ENODEV; + goto err_io; + } + pdata->coherent = (attr == DEV_DMA_COHERENT); + if (pdata->coherent) { + pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; + pdata->arcache = XGBE_DMA_OS_ARCACHE; + pdata->awcache = XGBE_DMA_OS_AWCACHE; + } else { + pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN; + pdata->arcache = XGBE_DMA_SYS_ARCACHE; + pdata->awcache = XGBE_DMA_SYS_AWCACHE; + } + + /* Set the maximum fifo amounts */ + pdata->tx_max_fifo_size = pdata->vdata->tx_max_fifo_size; + pdata->rx_max_fifo_size = pdata->vdata->rx_max_fifo_size; + + /* Set the hardware channel and queue counts */ + xgbe_set_counts(pdata); + + /* Get the device interrupt */ + ret = platform_get_irq(pdev, 0); + if (ret < 0) { + dev_err(dev, "platform_get_irq 0 failed\n"); + goto err_io; + } + pdata->dev_irq = ret; + + /* Get the per channel DMA interrupts */ + if (pdata->per_channel_irq) { + unsigned int i, max = ARRAY_SIZE(pdata->channel_irq); + + for (i = 0; (i < max) && (dma_irqnum < dma_irqend); i++) { + ret = platform_get_irq(pdata->platdev, dma_irqnum++); + if (ret < 0) { + netdev_err(pdata->netdev, + "platform_get_irq %u failed\n", + dma_irqnum - 1); + goto err_io; + } + + pdata->channel_irq[i] = ret; + } + } + + /* Get the auto-negotiation interrupt */ + ret = platform_get_irq(phy_pdev, phy_irqnum++); + if (ret < 0) { + dev_err(dev, "platform_get_irq phy 0 failed\n"); + goto err_io; + } + pdata->an_irq = ret; + + /* Configure the netdev resource */ + ret = xgbe_config_netdev(pdata); + if (ret) + goto err_io; + + netdev_notice(pdata->netdev, "net device enabled\n"); + + return 0; + +err_io: + platform_device_put(phy_pdev); + +err_phydev: + xgbe_free_pdata(pdata); + +err_alloc: + dev_notice(dev, "net device not enabled\n"); + + return ret; +} + +static int xgbe_platform_remove(struct platform_device *pdev) +{ + struct xgbe_prv_data *pdata = platform_get_drvdata(pdev); + + xgbe_deconfig_netdev(pdata); + + platform_device_put(pdata->phy_platdev); + + xgbe_free_pdata(pdata); + + return 0; +} + +#ifdef CONFIG_PM +static int xgbe_platform_suspend(struct device *dev) +{ + struct xgbe_prv_data *pdata = dev_get_drvdata(dev); + struct net_device *netdev = pdata->netdev; + int ret = 0; + + DBGPR("-->xgbe_suspend\n"); + + if (netif_running(netdev)) + ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT); + + pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); + pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); + + DBGPR("<--xgbe_suspend\n"); + + return ret; +} + +static int xgbe_platform_resume(struct device *dev) +{ + struct xgbe_prv_data *pdata = dev_get_drvdata(dev); + struct net_device *netdev = pdata->netdev; + int ret = 0; + + DBGPR("-->xgbe_resume\n"); + + pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); + + if (netif_running(netdev)) { + ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT); + + /* Schedule a restart in case the link or phy state changed + * while we were powered down. + */ + schedule_work(&pdata->restart_work); + } + + DBGPR("<--xgbe_resume\n"); + + return ret; +} +#endif /* CONFIG_PM */ + +static const struct xgbe_version_data xgbe_v1 = { + .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1, + .xpcs_access = XGBE_XPCS_ACCESS_V1, + .tx_max_fifo_size = 81920, + .rx_max_fifo_size = 81920, +}; + +#ifdef CONFIG_ACPI +static const struct acpi_device_id xgbe_acpi_match[] = { + { .id = "AMDI8001", + .driver_data = (kernel_ulong_t)&xgbe_v1 }, + {}, +}; + +MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match); +#endif + +#ifdef CONFIG_OF +static const struct of_device_id xgbe_of_match[] = { + { .compatible = "amd,xgbe-seattle-v1a", + .data = &xgbe_v1 }, + {}, +}; + +MODULE_DEVICE_TABLE(of, xgbe_of_match); +#endif + +static SIMPLE_DEV_PM_OPS(xgbe_platform_pm_ops, + xgbe_platform_suspend, xgbe_platform_resume); + +static struct platform_driver xgbe_driver = { + .driver = { + .name = "amd-xgbe", +#ifdef CONFIG_ACPI + .acpi_match_table = xgbe_acpi_match, +#endif +#ifdef CONFIG_OF + .of_match_table = xgbe_of_match, +#endif + .pm = &xgbe_platform_pm_ops, + }, + .probe = xgbe_platform_probe, + .remove = xgbe_platform_remove, +}; + +int xgbe_platform_init(void) +{ + return platform_driver_register(&xgbe_driver); +} + +void xgbe_platform_exit(void) +{ + platform_driver_unregister(&xgbe_driver); +} diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index d5cae1557908..0779247057fb 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -210,8 +210,6 @@ #define XGMAC_DRIVER_CONTEXT 1 #define XGMAC_IOCTL_CONTEXT 2 -#define XGMAC_FIFO_RX_MAX 81920 -#define XGMAC_FIFO_TX_MAX 81920 #define XGMAC_FIFO_MIN_ALLOC 2048 #define XGMAC_FIFO_UNIT 256 #define XGMAC_FIFO_ALIGN(_x) \ @@ -805,14 +803,16 @@ struct xgbe_version_data { void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *); enum xgbe_xpcs_access xpcs_access; unsigned int mmc_64bit; + unsigned int tx_max_fifo_size; + unsigned int rx_max_fifo_size; }; struct xgbe_prv_data { struct net_device *netdev; - struct platform_device *pdev; + struct platform_device *platdev; struct acpi_device *adev; struct device *dev; - struct platform_device *phy_pdev; + struct platform_device *phy_platdev; struct device *phy_dev; /* Version related data */ @@ -845,6 +845,7 @@ struct xgbe_prv_data { int dev_irq; unsigned int per_channel_irq; + int channel_irq[XGBE_MAX_DMA_CHANNELS]; struct xgbe_hw_if hw_if; struct xgbe_phy_if phy_if; @@ -863,12 +864,16 @@ struct xgbe_prv_data { /* Rings for Tx/Rx on a DMA channel */ struct xgbe_channel *channel; + unsigned int tx_max_channel_count; + unsigned int rx_max_channel_count; unsigned int channel_count; unsigned int tx_ring_count; unsigned int tx_desc_count; unsigned int rx_ring_count; unsigned int rx_desc_count; + unsigned int tx_max_q_count; + unsigned int rx_max_q_count; unsigned int tx_q_count; unsigned int rx_q_count; @@ -880,11 +885,13 @@ struct xgbe_prv_data { unsigned int tx_threshold; unsigned int tx_pbl; unsigned int tx_osp_mode; + unsigned int tx_max_fifo_size; /* Rx settings */ unsigned int rx_sf_mode; unsigned int rx_threshold; unsigned int rx_pbl; + unsigned int rx_max_fifo_size; /* Tx coalescing settings */ unsigned int tx_usecs; @@ -1005,6 +1012,14 @@ struct xgbe_prv_data { }; /* Function prototypes*/ +struct xgbe_prv_data *xgbe_alloc_pdata(struct device *); +void xgbe_free_pdata(struct xgbe_prv_data *); +void xgbe_set_counts(struct xgbe_prv_data *); +int xgbe_config_netdev(struct xgbe_prv_data *); +void xgbe_deconfig_netdev(struct xgbe_prv_data *); + +int xgbe_platform_init(void); +void xgbe_platform_exit(void); void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *); void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *); -- cgit v1.2.3 From 81cc2e434a9e8514bfad030683f7464c26306e35 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:11:57 +0000 Subject: nfp: add support for ethtool .get_channels Report number of rings via ethtool .get_channels API. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 3418f2277e9d..a7386d1b2883 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -614,6 +614,21 @@ static int nfp_net_set_coalesce(struct net_device *netdev, return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD); } +static void nfp_net_get_channels(struct net_device *netdev, + struct ethtool_channels *channel) +{ + struct nfp_net *nn = netdev_priv(netdev); + + channel->max_rx = min(nn->max_rx_rings, nn->max_r_vecs); + channel->max_tx = min(nn->max_tx_rings, nn->max_r_vecs); + channel->max_combined = min(channel->max_rx, channel->max_tx); + channel->max_other = NFP_NET_NON_Q_VECTORS; + channel->combined_count = min(nn->num_rx_rings, nn->num_tx_rings); + channel->rx_count = nn->num_rx_rings - channel->combined_count; + channel->tx_count = nn->num_tx_rings - channel->combined_count; + channel->other_count = NFP_NET_NON_Q_VECTORS; +} + static const struct ethtool_ops nfp_net_ethtool_ops = { .get_drvinfo = nfp_net_get_drvinfo, .get_link = ethtool_op_get_link, @@ -632,6 +647,7 @@ static const struct ethtool_ops nfp_net_ethtool_ops = { .get_regs = nfp_net_get_regs, .get_coalesce = nfp_net_get_coalesce, .set_coalesce = nfp_net_set_coalesce, + .get_channels = nfp_net_get_channels, }; void nfp_net_set_ethtool_ops(struct net_device *netdev) -- cgit v1.2.3 From 68453c7a8973399441080bcb20512d38033e64f7 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:11:58 +0000 Subject: nfp: centralize runtime reconfiguration logic All functions which need to reallocate ring resources at runtime look very similar. Centralize that logic into a separate function. Encapsulate configuration parameters in a structure. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 10 +- .../net/ethernet/netronome/nfp/nfp_net_common.c | 208 +++++++++------------ .../net/ethernet/netronome/nfp/nfp_net_ethtool.c | 19 ++ 3 files changed, 118 insertions(+), 119 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index e8713254786b..14b5e21cabf1 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -583,6 +583,12 @@ struct nfp_net { struct dentry *debugfs_dir; }; +struct nfp_net_ring_set { + unsigned int mtu; + unsigned int dcnt; + void *rings; +}; + /* Functions to read/write from/to a BAR * Performs any endian conversion necessary. */ @@ -771,7 +777,9 @@ void nfp_net_rss_write_key(struct nfp_net *nn); void nfp_net_coalesce_write_cfg(struct nfp_net *nn); int nfp_net_irqs_alloc(struct nfp_net *nn); void nfp_net_irqs_disable(struct nfp_net *nn); -int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt); +int +nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, + struct nfp_net_ring_set *tx); #ifdef CONFIG_NFP_NET_DEBUG void nfp_net_debugfs_create(void); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 97e0bbef13d1..e58532d27c5b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1573,7 +1573,7 @@ err_alloc: } static struct nfp_net_tx_ring * -nfp_net_shadow_tx_rings_prepare(struct nfp_net *nn, u32 buf_cnt) +nfp_net_shadow_tx_rings_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) { struct nfp_net_tx_ring *rings; unsigned int r; @@ -1585,11 +1585,11 @@ nfp_net_shadow_tx_rings_prepare(struct nfp_net *nn, u32 buf_cnt) for (r = 0; r < nn->num_tx_rings; r++) { nfp_net_tx_ring_init(&rings[r], nn->tx_rings[r].r_vec, r); - if (nfp_net_tx_ring_alloc(&rings[r], buf_cnt)) + if (nfp_net_tx_ring_alloc(&rings[r], s->dcnt)) goto err_free_prev; } - return rings; + return s->rings = rings; err_free_prev: while (r--) @@ -1598,27 +1598,29 @@ err_free_prev: return NULL; } -static struct nfp_net_tx_ring * -nfp_net_shadow_tx_rings_swap(struct nfp_net *nn, struct nfp_net_tx_ring *rings) +static void +nfp_net_shadow_tx_rings_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) { - struct nfp_net_tx_ring *old = nn->tx_rings; + struct nfp_net_tx_ring *rings = s->rings; + struct nfp_net_ring_set new = *s; unsigned int r; + s->dcnt = nn->txd_cnt; + s->rings = nn->tx_rings; + for (r = 0; r < nn->num_tx_rings; r++) - old[r].r_vec->tx_ring = &rings[r]; + nn->tx_rings[r].r_vec->tx_ring = &rings[r]; - nn->tx_rings = rings; - return old; + nn->txd_cnt = new.dcnt; + nn->tx_rings = new.rings; } static void -nfp_net_shadow_tx_rings_free(struct nfp_net *nn, struct nfp_net_tx_ring *rings) +nfp_net_shadow_tx_rings_free(struct nfp_net *nn, struct nfp_net_ring_set *s) { + struct nfp_net_tx_ring *rings = s->rings; unsigned int r; - if (!rings) - return; - for (r = 0; r < nn->num_tx_rings; r++) nfp_net_tx_ring_free(&rings[r]); @@ -1691,9 +1693,9 @@ err_alloc: } static struct nfp_net_rx_ring * -nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, unsigned int fl_bufsz, - u32 buf_cnt) +nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) { + unsigned int fl_bufsz = nfp_net_calc_fl_bufsz(nn, s->mtu); struct nfp_net_rx_ring *rings; unsigned int r; @@ -1704,14 +1706,14 @@ nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, unsigned int fl_bufsz, for (r = 0; r < nn->num_rx_rings; r++) { nfp_net_rx_ring_init(&rings[r], nn->rx_rings[r].r_vec, r); - if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz, buf_cnt)) + if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz, s->dcnt)) goto err_free_prev; if (nfp_net_rx_ring_bufs_alloc(nn, &rings[r])) goto err_free_ring; } - return rings; + return s->rings = rings; err_free_prev: while (r--) { @@ -1723,27 +1725,32 @@ err_free_ring: return NULL; } -static struct nfp_net_rx_ring * -nfp_net_shadow_rx_rings_swap(struct nfp_net *nn, struct nfp_net_rx_ring *rings) +static void +nfp_net_shadow_rx_rings_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) { - struct nfp_net_rx_ring *old = nn->rx_rings; + struct nfp_net_rx_ring *rings = s->rings; + struct nfp_net_ring_set new = *s; unsigned int r; + s->mtu = nn->netdev->mtu; + s->dcnt = nn->rxd_cnt; + s->rings = nn->rx_rings; + for (r = 0; r < nn->num_rx_rings; r++) - old[r].r_vec->rx_ring = &rings[r]; + nn->rx_rings[r].r_vec->rx_ring = &rings[r]; - nn->rx_rings = rings; - return old; + nn->netdev->mtu = new.mtu; + nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, new.mtu); + nn->rxd_cnt = new.dcnt; + nn->rx_rings = new.rings; } static void -nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings) +nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_ring_set *s) { + struct nfp_net_rx_ring *rings = s->rings; unsigned int r; - if (!rings) - return; - for (r = 0; r < nn->num_rx_rings; r++) { nfp_net_rx_ring_bufs_free(nn, &rings[r]); nfp_net_rx_ring_free(&rings[r]); @@ -2255,89 +2262,50 @@ static void nfp_net_set_rx_mode(struct net_device *netdev) nn->ctrl = new_ctrl; } -static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) +static int +nfp_net_ring_swap_enable(struct nfp_net *nn, + struct nfp_net_ring_set *rx, + struct nfp_net_ring_set *tx) { - unsigned int old_mtu, old_fl_bufsz, new_fl_bufsz; - struct nfp_net *nn = netdev_priv(netdev); - struct nfp_net_rx_ring *tmp_rings; - int err; - - old_mtu = netdev->mtu; - old_fl_bufsz = nn->fl_bufsz; - new_fl_bufsz = nfp_net_calc_fl_bufsz(nn, new_mtu); - - if (!netif_running(netdev)) { - netdev->mtu = new_mtu; - nn->fl_bufsz = new_fl_bufsz; - return 0; - } - - /* Prepare new rings */ - tmp_rings = nfp_net_shadow_rx_rings_prepare(nn, new_fl_bufsz, - nn->rxd_cnt); - if (!tmp_rings) - return -ENOMEM; - - /* Stop device, swap in new rings, try to start the firmware */ - nfp_net_close_stack(nn); - nfp_net_clear_config_and_disable(nn); - - tmp_rings = nfp_net_shadow_rx_rings_swap(nn, tmp_rings); - - netdev->mtu = new_mtu; - nn->fl_bufsz = new_fl_bufsz; - - err = nfp_net_set_config_and_enable(nn); - if (err) { - const int err_new = err; + if (rx) + nfp_net_shadow_rx_rings_swap(nn, rx); + if (tx) + nfp_net_shadow_tx_rings_swap(nn, tx); - /* Try with old configuration and old rings */ - tmp_rings = nfp_net_shadow_rx_rings_swap(nn, tmp_rings); - - netdev->mtu = old_mtu; - nn->fl_bufsz = old_fl_bufsz; - - err = __nfp_net_set_config_and_enable(nn); - if (err) - nn_err(nn, "Can't restore MTU - FW communication failed (%d,%d)\n", - err_new, err); - } - - nfp_net_shadow_rx_rings_free(nn, tmp_rings); - - nfp_net_open_stack(nn); + return __nfp_net_set_config_and_enable(nn); +} - return err; +static void +nfp_net_ring_reconfig_down(struct nfp_net *nn, + struct nfp_net_ring_set *rx, + struct nfp_net_ring_set *tx) +{ + nn->netdev->mtu = rx ? rx->mtu : nn->netdev->mtu; + nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, nn->netdev->mtu); + nn->rxd_cnt = rx ? rx->dcnt : nn->rxd_cnt; + nn->txd_cnt = tx ? tx->dcnt : nn->txd_cnt; } -int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt) +int +nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, + struct nfp_net_ring_set *tx) { - struct nfp_net_tx_ring *tx_rings = NULL; - struct nfp_net_rx_ring *rx_rings = NULL; - u32 old_rxd_cnt, old_txd_cnt; int err; if (!netif_running(nn->netdev)) { - nn->rxd_cnt = rxd_cnt; - nn->txd_cnt = txd_cnt; + nfp_net_ring_reconfig_down(nn, rx, tx); return 0; } - old_rxd_cnt = nn->rxd_cnt; - old_txd_cnt = nn->txd_cnt; - /* Prepare new rings */ - if (nn->rxd_cnt != rxd_cnt) { - rx_rings = nfp_net_shadow_rx_rings_prepare(nn, nn->fl_bufsz, - rxd_cnt); - if (!rx_rings) + if (rx) { + if (!nfp_net_shadow_rx_rings_prepare(nn, rx)) return -ENOMEM; } - if (nn->txd_cnt != txd_cnt) { - tx_rings = nfp_net_shadow_tx_rings_prepare(nn, txd_cnt); - if (!tx_rings) { - nfp_net_shadow_rx_rings_free(nn, rx_rings); - return -ENOMEM; + if (tx) { + if (!nfp_net_shadow_tx_rings_prepare(nn, tx)) { + err = -ENOMEM; + goto err_free_rx; } } @@ -2345,39 +2313,43 @@ int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt) nfp_net_close_stack(nn); nfp_net_clear_config_and_disable(nn); - if (rx_rings) - rx_rings = nfp_net_shadow_rx_rings_swap(nn, rx_rings); - if (tx_rings) - tx_rings = nfp_net_shadow_tx_rings_swap(nn, tx_rings); - - nn->rxd_cnt = rxd_cnt; - nn->txd_cnt = txd_cnt; - - err = nfp_net_set_config_and_enable(nn); + err = nfp_net_ring_swap_enable(nn, rx, tx); if (err) { - const int err_new = err; - - /* Try with old configuration and old rings */ - if (rx_rings) - rx_rings = nfp_net_shadow_rx_rings_swap(nn, rx_rings); - if (tx_rings) - tx_rings = nfp_net_shadow_tx_rings_swap(nn, tx_rings); + int err2; - nn->rxd_cnt = old_rxd_cnt; - nn->txd_cnt = old_txd_cnt; + nfp_net_clear_config_and_disable(nn); - err = __nfp_net_set_config_and_enable(nn); - if (err) + /* Try with old configuration and old rings */ + err2 = nfp_net_ring_swap_enable(nn, rx, tx); + if (err2) nn_err(nn, "Can't restore ring config - FW communication failed (%d,%d)\n", - err_new, err); + err, err2); } - nfp_net_shadow_rx_rings_free(nn, rx_rings); - nfp_net_shadow_tx_rings_free(nn, tx_rings); + if (rx) + nfp_net_shadow_rx_rings_free(nn, rx); + if (tx) + nfp_net_shadow_tx_rings_free(nn, tx); nfp_net_open_stack(nn); return err; + +err_free_rx: + if (rx) + nfp_net_shadow_rx_rings_free(nn, rx); + return err; +} + +static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct nfp_net *nn = netdev_priv(netdev); + struct nfp_net_ring_set rx = { + .mtu = new_mtu, + .dcnt = nn->rxd_cnt, + }; + + return nfp_net_ring_reconfig(nn, &rx, NULL); } static struct rtnl_link_stats64 *nfp_net_stat64(struct net_device *netdev, diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index a7386d1b2883..3f48256dc03c 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -158,6 +158,25 @@ static void nfp_net_get_ringparam(struct net_device *netdev, ring->tx_pending = nn->txd_cnt; } +static int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt) +{ + struct nfp_net_ring_set *reconfig_rx = NULL, *reconfig_tx = NULL; + struct nfp_net_ring_set rx = { + .mtu = nn->netdev->mtu, + .dcnt = rxd_cnt, + }; + struct nfp_net_ring_set tx = { + .dcnt = txd_cnt, + }; + + if (nn->rxd_cnt != rxd_cnt) + reconfig_rx = ℞ + if (nn->txd_cnt != txd_cnt) + reconfig_tx = &tx; + + return nfp_net_ring_reconfig(nn, reconfig_rx, reconfig_tx); +} + static int nfp_net_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { -- cgit v1.2.3 From 0ae42dfcf249a6b6535d37e119e06efb31eef979 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:11:59 +0000 Subject: nfp: rename ring allocation helpers "Shadow" in ring helpers used to mean that the helper will allocate rings without touching existing configuration, this was used for reconfiguration while the device was running. We will soon use the same helpers for .ndo_open() path, so replace "shadow" with "ring_set". No functional changes. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index e58532d27c5b..b7b2851ebb6b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1573,7 +1573,7 @@ err_alloc: } static struct nfp_net_tx_ring * -nfp_net_shadow_tx_rings_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_tx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) { struct nfp_net_tx_ring *rings; unsigned int r; @@ -1599,7 +1599,7 @@ err_free_prev: } static void -nfp_net_shadow_tx_rings_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_tx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) { struct nfp_net_tx_ring *rings = s->rings; struct nfp_net_ring_set new = *s; @@ -1616,7 +1616,7 @@ nfp_net_shadow_tx_rings_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) } static void -nfp_net_shadow_tx_rings_free(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_tx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s) { struct nfp_net_tx_ring *rings = s->rings; unsigned int r; @@ -1693,7 +1693,7 @@ err_alloc: } static struct nfp_net_rx_ring * -nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_rx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) { unsigned int fl_bufsz = nfp_net_calc_fl_bufsz(nn, s->mtu); struct nfp_net_rx_ring *rings; @@ -1726,7 +1726,7 @@ err_free_ring: } static void -nfp_net_shadow_rx_rings_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_rx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) { struct nfp_net_rx_ring *rings = s->rings; struct nfp_net_ring_set new = *s; @@ -1746,7 +1746,7 @@ nfp_net_shadow_rx_rings_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) } static void -nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_rx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s) { struct nfp_net_rx_ring *rings = s->rings; unsigned int r; @@ -2268,9 +2268,9 @@ nfp_net_ring_swap_enable(struct nfp_net *nn, struct nfp_net_ring_set *tx) { if (rx) - nfp_net_shadow_rx_rings_swap(nn, rx); + nfp_net_rx_ring_set_swap(nn, rx); if (tx) - nfp_net_shadow_tx_rings_swap(nn, tx); + nfp_net_tx_ring_set_swap(nn, tx); return __nfp_net_set_config_and_enable(nn); } @@ -2299,11 +2299,11 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, /* Prepare new rings */ if (rx) { - if (!nfp_net_shadow_rx_rings_prepare(nn, rx)) + if (!nfp_net_rx_ring_set_prepare(nn, rx)) return -ENOMEM; } if (tx) { - if (!nfp_net_shadow_tx_rings_prepare(nn, tx)) { + if (!nfp_net_tx_ring_set_prepare(nn, tx)) { err = -ENOMEM; goto err_free_rx; } @@ -2327,9 +2327,9 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, } if (rx) - nfp_net_shadow_rx_rings_free(nn, rx); + nfp_net_rx_ring_set_free(nn, rx); if (tx) - nfp_net_shadow_tx_rings_free(nn, tx); + nfp_net_tx_ring_set_free(nn, tx); nfp_net_open_stack(nn); @@ -2337,7 +2337,7 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, err_free_rx: if (rx) - nfp_net_shadow_rx_rings_free(nn, rx); + nfp_net_rx_ring_set_free(nn, rx); return err; } -- cgit v1.2.3 From a10b563d8846c8171bacdcad0aa5078b6d06da33 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:00 +0000 Subject: nfp: reuse ring helpers on .ndo_open() path Ring allocation helpers encapsulate all ring allocation and initialization steps nicely. Reuse them on .ndo_open() path. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 60 ++++++++-------------- 1 file changed, 20 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index b7b2851ebb6b..50aeaea9e318 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2051,6 +2051,13 @@ static void nfp_net_open_stack(struct nfp_net *nn) static int nfp_net_netdev_open(struct net_device *netdev) { struct nfp_net *nn = netdev_priv(netdev); + struct nfp_net_ring_set rx = { + .mtu = nn->netdev->mtu, + .dcnt = nn->rxd_cnt, + }; + struct nfp_net_ring_set tx = { + .dcnt = nn->txd_cnt, + }; int err, r; if (nn->ctrl & NFP_NET_CFG_CTRL_ENABLE) { @@ -2075,38 +2082,22 @@ static int nfp_net_netdev_open(struct net_device *netdev) goto err_free_exn; disable_irq(nn->irq_entries[NFP_NET_IRQ_LSC_IDX].vector); - nn->rx_rings = kcalloc(nn->num_rx_rings, sizeof(*nn->rx_rings), - GFP_KERNEL); - if (!nn->rx_rings) { - err = -ENOMEM; - goto err_free_lsc; - } - nn->tx_rings = kcalloc(nn->num_tx_rings, sizeof(*nn->tx_rings), - GFP_KERNEL); - if (!nn->tx_rings) { - err = -ENOMEM; - goto err_free_rx_rings; - } - for (r = 0; r < nn->num_r_vecs; r++) { err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r); if (err) goto err_cleanup_vec_p; } - for (r = 0; r < nn->num_tx_rings; r++) { - err = nfp_net_tx_ring_alloc(nn->r_vecs[r].tx_ring, nn->txd_cnt); - if (err) - goto err_free_tx_ring_p; + + nn->rx_rings = nfp_net_rx_ring_set_prepare(nn, &rx); + if (!nn->rx_rings) { + err = -ENOMEM; + goto err_cleanup_vec; } - for (r = 0; r < nn->num_rx_rings; r++) { - err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring, - nn->fl_bufsz, nn->rxd_cnt); - if (err) - goto err_flush_free_rx_ring_p; - err = nfp_net_rx_ring_bufs_alloc(nn, nn->r_vecs[r].rx_ring); - if (err) - goto err_free_rx_ring_p; + nn->tx_rings = nfp_net_tx_ring_set_prepare(nn, &tx); + if (!nn->tx_rings) { + err = -ENOMEM; + goto err_free_rx_rings; } err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings); @@ -2139,25 +2130,14 @@ static int nfp_net_netdev_open(struct net_device *netdev) return 0; err_free_rings: - r = nn->num_rx_rings; -err_flush_free_rx_ring_p: - while (r--) { - nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); -err_free_rx_ring_p: - nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); - } - r = nn->num_tx_rings; -err_free_tx_ring_p: - while (r--) - nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); + nfp_net_tx_ring_set_free(nn, &tx); +err_free_rx_rings: + nfp_net_rx_ring_set_free(nn, &rx); +err_cleanup_vec: r = nn->num_r_vecs; err_cleanup_vec_p: while (r--) nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); - kfree(nn->tx_rings); -err_free_rx_rings: - kfree(nn->rx_rings); -err_free_lsc: nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); err_free_exn: nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX); -- cgit v1.2.3 From 0668b60ba60228cb0fa21bc69baa6269edf7b6d3 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:01 +0000 Subject: nfp: loosen relation between rings and IRQs vectors Upcoming XDP support will break the assumption that one can iterate over IRQ vectors to get to all the rings easily. Use nn->.x_ring arrays directly. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 50aeaea9e318..97cc21eae466 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1920,9 +1920,9 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) nn_err(nn, "Could not disable device: %d\n", err); for (r = 0; r < nn->num_rx_rings; r++) - nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); + nfp_net_rx_ring_reset(&nn->rx_rings[r]); for (r = 0; r < nn->num_tx_rings; r++) - nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring); + nfp_net_tx_ring_reset(nn, &nn->tx_rings[r]); for (r = 0; r < nn->num_r_vecs; r++) nfp_net_vec_clear_ring_data(nn, r); @@ -2000,7 +2000,7 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn) nn->ctrl = new_ctrl; for (r = 0; r < nn->num_rx_rings; r++) - nfp_net_rx_ring_fill_freelist(nn->r_vecs[r].rx_ring); + nfp_net_rx_ring_fill_freelist(&nn->rx_rings[r]); /* Since reconfiguration requests while NFP is down are ignored we * have to wipe the entire VXLAN configuration and reinitialize it. @@ -2173,11 +2173,11 @@ static void nfp_net_close_free_all(struct nfp_net *nn) unsigned int r; for (r = 0; r < nn->num_rx_rings; r++) { - nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); - nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); + nfp_net_rx_ring_bufs_free(nn, &nn->rx_rings[r]); + nfp_net_rx_ring_free(&nn->rx_rings[r]); } for (r = 0; r < nn->num_tx_rings; r++) - nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); + nfp_net_tx_ring_free(&nn->tx_rings[r]); for (r = 0; r < nn->num_r_vecs; r++) nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); -- cgit v1.2.3 From e31230f9260f7bcf069e3962111f7e4656a1bfd4 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:02 +0000 Subject: nfp: add helper to reassign rings to IRQ vectors Instead of fixing ring -> vector relations up in ring swap functions put the reassignment into a helper function which will reinit all links. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 40 +++++++++------------- 1 file changed, 16 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 97cc21eae466..2a4e1f1cb3c9 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1601,16 +1601,11 @@ err_free_prev: static void nfp_net_tx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) { - struct nfp_net_tx_ring *rings = s->rings; struct nfp_net_ring_set new = *s; - unsigned int r; s->dcnt = nn->txd_cnt; s->rings = nn->tx_rings; - for (r = 0; r < nn->num_tx_rings; r++) - nn->tx_rings[r].r_vec->tx_ring = &rings[r]; - nn->txd_cnt = new.dcnt; nn->tx_rings = new.rings; } @@ -1728,17 +1723,12 @@ err_free_ring: static void nfp_net_rx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) { - struct nfp_net_rx_ring *rings = s->rings; struct nfp_net_ring_set new = *s; - unsigned int r; s->mtu = nn->netdev->mtu; s->dcnt = nn->rxd_cnt; s->rings = nn->rx_rings; - for (r = 0; r < nn->num_rx_rings; r++) - nn->rx_rings[r].r_vec->rx_ring = &rings[r]; - nn->netdev->mtu = new.mtu; nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, new.mtu); nn->rxd_cnt = new.dcnt; @@ -1759,6 +1749,14 @@ nfp_net_rx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s) kfree(rings); } +static void +nfp_net_vector_assign_rings(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, + int idx) +{ + r_vec->rx_ring = idx < nn->num_rx_rings ? &nn->rx_rings[idx] : NULL; + r_vec->tx_ring = idx < nn->num_tx_rings ? &nn->tx_rings[idx] : NULL; +} + static int nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, int idx) @@ -1766,20 +1764,6 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx]; int err; - if (idx < nn->num_tx_rings) { - r_vec->tx_ring = &nn->tx_rings[idx]; - nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, idx); - } else { - r_vec->tx_ring = NULL; - } - - if (idx < nn->num_rx_rings) { - r_vec->rx_ring = &nn->rx_rings[idx]; - nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, idx); - } else { - r_vec->rx_ring = NULL; - } - snprintf(r_vec->name, sizeof(r_vec->name), "%s-rxtx-%d", nn->netdev->name, idx); err = request_irq(entry->vector, r_vec->handler, 0, r_vec->name, r_vec); @@ -2100,6 +2084,9 @@ static int nfp_net_netdev_open(struct net_device *netdev) goto err_free_rx_rings; } + for (r = 0; r < nn->max_r_vecs; r++) + nfp_net_vector_assign_rings(nn, &nn->r_vecs[r], r); + err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings); if (err) goto err_free_rings; @@ -2247,11 +2234,16 @@ nfp_net_ring_swap_enable(struct nfp_net *nn, struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx) { + unsigned int r; + if (rx) nfp_net_rx_ring_set_swap(nn, rx); if (tx) nfp_net_tx_ring_set_swap(nn, tx); + for (r = 0; r < nn->max_r_vecs; r++) + nfp_net_vector_assign_rings(nn, &nn->r_vecs[r], r); + return __nfp_net_set_config_and_enable(nn); } -- cgit v1.2.3 From 1e9e10d0c1365092972552d8c8f9d97517bcf581 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:03 +0000 Subject: nfp: move RSS indirection table init into a separate function We will need to rerun the initialization of the RSS indirection table after the number of rings is changed. Move the code to a separate function. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 2a4e1f1cb3c9..09cec6e2c6cf 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2229,6 +2229,15 @@ static void nfp_net_set_rx_mode(struct net_device *netdev) nn->ctrl = new_ctrl; } +static void nfp_net_rss_init_itbl(struct nfp_net *nn) +{ + int i; + + for (i = 0; i < sizeof(nn->rss_itbl); i++) + nn->rss_itbl[i] = + ethtool_rxfh_indir_default(i, nn->num_rx_rings); +} + static int nfp_net_ring_swap_enable(struct nfp_net *nn, struct nfp_net_ring_set *rx, @@ -2707,13 +2716,9 @@ void nfp_net_netdev_free(struct nfp_net *nn) */ static void nfp_net_rss_init(struct nfp_net *nn) { - int i; - netdev_rss_key_fill(nn->rss_key, NFP_NET_CFG_RSS_KEY_SZ); - for (i = 0; i < sizeof(nn->rss_itbl); i++) - nn->rss_itbl[i] = - ethtool_rxfh_indir_default(i, nn->num_rx_rings); + nfp_net_rss_init_itbl(nn); /* Enable IPv4/IPv6 TCP by default */ nn->rss_cfg = NFP_NET_CFG_RSS_IPV4_TCP | -- cgit v1.2.3 From 164d1e9e5d5235c44851e606d01dd699d8bb15d3 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:04 +0000 Subject: nfp: add support for ethtool .set_channels Allow changing the number of rings via ethtool .set_channels API. Runtime reconfig needs to be extended to handle number of rings. We need to be able to activate interrupt vectors before rings are assigned to them. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 1 + .../net/ethernet/netronome/nfp/nfp_net_common.c | 93 +++++++++++++++++----- .../net/ethernet/netronome/nfp/nfp_net_debugfs.c | 4 +- .../net/ethernet/netronome/nfp/nfp_net_ethtool.c | 47 +++++++++++ 4 files changed, 123 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 14b5e21cabf1..486e7c6453bc 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -584,6 +584,7 @@ struct nfp_net { }; struct nfp_net_ring_set { + unsigned int n_rings; unsigned int mtu; unsigned int dcnt; void *rings; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 09cec6e2c6cf..506362729607 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -494,7 +494,7 @@ static void nfp_net_irqs_assign(struct net_device *netdev) nn->lsc_handler = nfp_net_irq_lsc; nn->exn_handler = nfp_net_irq_exn; - for (r = 0; r < nn->num_r_vecs; r++) { + for (r = 0; r < nn->max_r_vecs; r++) { r_vec = &nn->r_vecs[r]; r_vec->nfp_net = nn; r_vec->handler = nfp_net_irq_rxtx; @@ -1578,12 +1578,12 @@ nfp_net_tx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) struct nfp_net_tx_ring *rings; unsigned int r; - rings = kcalloc(nn->num_tx_rings, sizeof(*rings), GFP_KERNEL); + rings = kcalloc(s->n_rings, sizeof(*rings), GFP_KERNEL); if (!rings) return NULL; - for (r = 0; r < nn->num_tx_rings; r++) { - nfp_net_tx_ring_init(&rings[r], nn->tx_rings[r].r_vec, r); + for (r = 0; r < s->n_rings; r++) { + nfp_net_tx_ring_init(&rings[r], &nn->r_vecs[r], r); if (nfp_net_tx_ring_alloc(&rings[r], s->dcnt)) goto err_free_prev; @@ -1605,9 +1605,11 @@ nfp_net_tx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) s->dcnt = nn->txd_cnt; s->rings = nn->tx_rings; + s->n_rings = nn->num_tx_rings; nn->txd_cnt = new.dcnt; nn->tx_rings = new.rings; + nn->num_tx_rings = new.n_rings; } static void @@ -1616,7 +1618,7 @@ nfp_net_tx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s) struct nfp_net_tx_ring *rings = s->rings; unsigned int r; - for (r = 0; r < nn->num_tx_rings; r++) + for (r = 0; r < s->n_rings; r++) nfp_net_tx_ring_free(&rings[r]); kfree(rings); @@ -1694,12 +1696,12 @@ nfp_net_rx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) struct nfp_net_rx_ring *rings; unsigned int r; - rings = kcalloc(nn->num_rx_rings, sizeof(*rings), GFP_KERNEL); + rings = kcalloc(s->n_rings, sizeof(*rings), GFP_KERNEL); if (!rings) return NULL; - for (r = 0; r < nn->num_rx_rings; r++) { - nfp_net_rx_ring_init(&rings[r], nn->rx_rings[r].r_vec, r); + for (r = 0; r < s->n_rings; r++) { + nfp_net_rx_ring_init(&rings[r], &nn->r_vecs[r], r); if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz, s->dcnt)) goto err_free_prev; @@ -1728,11 +1730,13 @@ nfp_net_rx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) s->mtu = nn->netdev->mtu; s->dcnt = nn->rxd_cnt; s->rings = nn->rx_rings; + s->n_rings = nn->num_rx_rings; nn->netdev->mtu = new.mtu; nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, new.mtu); nn->rxd_cnt = new.dcnt; nn->rx_rings = new.rings; + nn->num_rx_rings = new.n_rings; } static void @@ -1741,7 +1745,7 @@ nfp_net_rx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s) struct nfp_net_rx_ring *rings = s->rings; unsigned int r; - for (r = 0; r < nn->num_rx_rings; r++) { + for (r = 0; r < s->n_rings; r++) { nfp_net_rx_ring_bufs_free(nn, &rings[r]); nfp_net_rx_ring_free(&rings[r]); } @@ -1764,19 +1768,20 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx]; int err; + /* Setup NAPI */ + netif_napi_add(nn->netdev, &r_vec->napi, + nfp_net_poll, NAPI_POLL_WEIGHT); + snprintf(r_vec->name, sizeof(r_vec->name), "%s-rxtx-%d", nn->netdev->name, idx); err = request_irq(entry->vector, r_vec->handler, 0, r_vec->name, r_vec); if (err) { + netif_napi_del(&r_vec->napi); nn_err(nn, "Error requesting IRQ %d\n", entry->vector); return err; } disable_irq(entry->vector); - /* Setup NAPI */ - netif_napi_add(nn->netdev, &r_vec->napi, - nfp_net_poll, NAPI_POLL_WEIGHT); - irq_set_affinity_hint(entry->vector, &r_vec->affinity_mask); nn_dbg(nn, "RV%02d: irq=%03d/%03d\n", idx, entry->vector, entry->entry); @@ -2036,10 +2041,12 @@ static int nfp_net_netdev_open(struct net_device *netdev) { struct nfp_net *nn = netdev_priv(netdev); struct nfp_net_ring_set rx = { + .n_rings = nn->num_rx_rings, .mtu = nn->netdev->mtu, .dcnt = nn->rxd_cnt, }; struct nfp_net_ring_set tx = { + .n_rings = nn->num_tx_rings, .dcnt = nn->txd_cnt, }; int err, r; @@ -2239,49 +2246,89 @@ static void nfp_net_rss_init_itbl(struct nfp_net *nn) } static int -nfp_net_ring_swap_enable(struct nfp_net *nn, +nfp_net_ring_swap_enable(struct nfp_net *nn, unsigned int *num_vecs, struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx) { unsigned int r; + int err; if (rx) nfp_net_rx_ring_set_swap(nn, rx); if (tx) nfp_net_tx_ring_set_swap(nn, tx); + swap(*num_vecs, nn->num_r_vecs); + for (r = 0; r < nn->max_r_vecs; r++) nfp_net_vector_assign_rings(nn, &nn->r_vecs[r], r); + if (nn->netdev->real_num_rx_queues != nn->num_rx_rings) { + if (!netif_is_rxfh_configured(nn->netdev)) + nfp_net_rss_init_itbl(nn); + + err = netif_set_real_num_rx_queues(nn->netdev, + nn->num_rx_rings); + if (err) + return err; + } + + if (nn->netdev->real_num_tx_queues != nn->num_tx_rings) { + err = netif_set_real_num_tx_queues(nn->netdev, + nn->num_tx_rings); + if (err) + return err; + } + return __nfp_net_set_config_and_enable(nn); } static void nfp_net_ring_reconfig_down(struct nfp_net *nn, struct nfp_net_ring_set *rx, - struct nfp_net_ring_set *tx) + struct nfp_net_ring_set *tx, + unsigned int num_vecs) { nn->netdev->mtu = rx ? rx->mtu : nn->netdev->mtu; nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, nn->netdev->mtu); nn->rxd_cnt = rx ? rx->dcnt : nn->rxd_cnt; nn->txd_cnt = tx ? tx->dcnt : nn->txd_cnt; + nn->num_rx_rings = rx ? rx->n_rings : nn->num_rx_rings; + nn->num_tx_rings = tx ? tx->n_rings : nn->num_tx_rings; + nn->num_r_vecs = num_vecs; + + if (!netif_is_rxfh_configured(nn->netdev)) + nfp_net_rss_init_itbl(nn); } int nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx) { + unsigned int num_vecs, r; int err; + num_vecs = max(rx ? rx->n_rings : nn->num_rx_rings, + tx ? tx->n_rings : nn->num_tx_rings); + if (!netif_running(nn->netdev)) { - nfp_net_ring_reconfig_down(nn, rx, tx); + nfp_net_ring_reconfig_down(nn, rx, tx, num_vecs); return 0; } /* Prepare new rings */ + for (r = nn->num_r_vecs; r < num_vecs; r++) { + err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r); + if (err) { + num_vecs = r; + goto err_cleanup_vecs; + } + } if (rx) { - if (!nfp_net_rx_ring_set_prepare(nn, rx)) - return -ENOMEM; + if (!nfp_net_rx_ring_set_prepare(nn, rx)) { + err = -ENOMEM; + goto err_cleanup_vecs; + } } if (tx) { if (!nfp_net_tx_ring_set_prepare(nn, tx)) { @@ -2294,18 +2341,20 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, nfp_net_close_stack(nn); nfp_net_clear_config_and_disable(nn); - err = nfp_net_ring_swap_enable(nn, rx, tx); + err = nfp_net_ring_swap_enable(nn, &num_vecs, rx, tx); if (err) { int err2; nfp_net_clear_config_and_disable(nn); /* Try with old configuration and old rings */ - err2 = nfp_net_ring_swap_enable(nn, rx, tx); + err2 = nfp_net_ring_swap_enable(nn, &num_vecs, rx, tx); if (err2) nn_err(nn, "Can't restore ring config - FW communication failed (%d,%d)\n", err, err2); } + for (r = num_vecs - 1; r >= nn->num_r_vecs; r--) + nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); if (rx) nfp_net_rx_ring_set_free(nn, rx); @@ -2319,6 +2368,9 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, err_free_rx: if (rx) nfp_net_rx_ring_set_free(nn, rx); +err_cleanup_vecs: + for (r = num_vecs - 1; r >= nn->num_r_vecs; r--) + nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); return err; } @@ -2326,6 +2378,7 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) { struct nfp_net *nn = netdev_priv(netdev); struct nfp_net_ring_set rx = { + .n_rings = nn->num_rx_rings, .mtu = new_mtu, .dcnt = nn->rxd_cnt, }; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c index 180cf70f0093..e90df8145323 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c @@ -207,13 +207,13 @@ void nfp_net_debugfs_adapter_add(struct nfp_net *nn) if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx)) return; - for (i = 0; i < nn->num_rx_rings; i++) { + for (i = 0; i < min(nn->max_rx_rings, nn->max_r_vecs); i++) { sprintf(int_name, "%d", i); debugfs_create_file(int_name, S_IRUSR, rx, &nn->r_vecs[i], &nfp_rx_q_fops); } - for (i = 0; i < nn->num_tx_rings; i++) { + for (i = 0; i < min(nn->max_tx_rings, nn->max_r_vecs); i++) { sprintf(int_name, "%d", i); debugfs_create_file(int_name, S_IRUSR, tx, &nn->r_vecs[i], &nfp_tx_q_fops); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 3f48256dc03c..b87f1b73f200 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -162,10 +162,12 @@ static int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt) { struct nfp_net_ring_set *reconfig_rx = NULL, *reconfig_tx = NULL; struct nfp_net_ring_set rx = { + .n_rings = nn->num_rx_rings, .mtu = nn->netdev->mtu, .dcnt = rxd_cnt, }; struct nfp_net_ring_set tx = { + .n_rings = nn->num_tx_rings, .dcnt = txd_cnt, }; @@ -648,6 +650,50 @@ static void nfp_net_get_channels(struct net_device *netdev, channel->other_count = NFP_NET_NON_Q_VECTORS; } +static int nfp_net_set_num_rings(struct nfp_net *nn, unsigned int total_rx, + unsigned int total_tx) +{ + struct nfp_net_ring_set *reconfig_rx = NULL, *reconfig_tx = NULL; + struct nfp_net_ring_set rx = { + .n_rings = total_rx, + .mtu = nn->netdev->mtu, + .dcnt = nn->rxd_cnt, + }; + struct nfp_net_ring_set tx = { + .n_rings = total_tx, + .dcnt = nn->txd_cnt, + }; + + if (nn->num_rx_rings != total_rx) + reconfig_rx = ℞ + if (nn->num_tx_rings != total_tx) + reconfig_tx = &tx; + + return nfp_net_ring_reconfig(nn, reconfig_rx, reconfig_tx); +} + +static int nfp_net_set_channels(struct net_device *netdev, + struct ethtool_channels *channel) +{ + struct nfp_net *nn = netdev_priv(netdev); + unsigned int total_rx, total_tx; + + /* Reject unsupported */ + if (!channel->combined_count || + channel->other_count != NFP_NET_NON_Q_VECTORS || + (channel->rx_count && channel->tx_count)) + return -EINVAL; + + total_rx = channel->combined_count + channel->rx_count; + total_tx = channel->combined_count + channel->tx_count; + + if (total_rx > min(nn->max_rx_rings, nn->max_r_vecs) || + total_tx > min(nn->max_tx_rings, nn->max_r_vecs)) + return -EINVAL; + + return nfp_net_set_num_rings(nn, total_rx, total_tx); +} + static const struct ethtool_ops nfp_net_ethtool_ops = { .get_drvinfo = nfp_net_get_drvinfo, .get_link = ethtool_op_get_link, @@ -667,6 +713,7 @@ static const struct ethtool_ops nfp_net_ethtool_ops = { .get_coalesce = nfp_net_get_coalesce, .set_coalesce = nfp_net_set_coalesce, .get_channels = nfp_net_get_channels, + .set_channels = nfp_net_set_channels, }; void nfp_net_set_ethtool_ops(struct net_device *netdev) -- cgit v1.2.3 From 13df4c666c551bba97618d7e3908c2ecd03ceefb Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:05 +0000 Subject: nfp: reorganize nfp_net_rx() to get packet offsets early Calculate packet offsets early in nfp_net_rx() so that we will be able to use them in upcoming XDP handler. While at it move relevant variables into the loop scope. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 56 ++++++++++++---------- 1 file changed, 30 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 506362729607..2ab63661a6fd 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1383,16 +1383,17 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) { struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; - unsigned int data_len, meta_len; - struct nfp_net_rx_buf *rxbuf; - struct nfp_net_rx_desc *rxd; - dma_addr_t new_dma_addr; struct sk_buff *skb; int pkts_polled = 0; - void *new_frag; int idx; while (pkts_polled < budget) { + unsigned int meta_len, data_len, data_off, pkt_len, pkt_off; + struct nfp_net_rx_buf *rxbuf; + struct nfp_net_rx_desc *rxd; + dma_addr_t new_dma_addr; + void *new_frag; + idx = rx_ring->rd_p & (rx_ring->cnt - 1); rxd = &rx_ring->rxds[idx]; @@ -1408,22 +1409,6 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) pkts_polled++; rxbuf = &rx_ring->rxbufs[idx]; - skb = build_skb(rxbuf->frag, nn->fl_bufsz); - if (unlikely(!skb)) { - nfp_net_rx_drop(r_vec, rx_ring, rxbuf, NULL); - continue; - } - new_frag = nfp_net_napi_alloc_one(nn, &new_dma_addr); - if (unlikely(!new_frag)) { - nfp_net_rx_drop(r_vec, rx_ring, rxbuf, skb); - continue; - } - - nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[idx].dma_addr, - nn->fl_bufsz, DMA_FROM_DEVICE); - - nfp_net_rx_give_one(rx_ring, new_frag, new_dma_addr); - /* < meta_len > * <-- [rx_offset] --> * --------------------------------------------------------- @@ -1438,20 +1423,39 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) */ meta_len = rxd->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK; data_len = le16_to_cpu(rxd->rxd.data_len); + pkt_len = data_len - meta_len; if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) - skb_reserve(skb, NFP_NET_RX_BUF_HEADROOM + meta_len); + pkt_off = meta_len; else - skb_reserve(skb, - NFP_NET_RX_BUF_HEADROOM + nn->rx_offset); - skb_put(skb, data_len - meta_len); + pkt_off = nn->rx_offset; + data_off = NFP_NET_RX_BUF_HEADROOM + pkt_off; /* Stats update */ u64_stats_update_begin(&r_vec->rx_sync); r_vec->rx_pkts++; - r_vec->rx_bytes += skb->len; + r_vec->rx_bytes += pkt_len; u64_stats_update_end(&r_vec->rx_sync); + skb = build_skb(rxbuf->frag, nn->fl_bufsz); + if (unlikely(!skb)) { + nfp_net_rx_drop(r_vec, rx_ring, rxbuf, NULL); + continue; + } + new_frag = nfp_net_napi_alloc_one(nn, &new_dma_addr); + if (unlikely(!new_frag)) { + nfp_net_rx_drop(r_vec, rx_ring, rxbuf, skb); + continue; + } + + nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[idx].dma_addr, + nn->fl_bufsz, DMA_FROM_DEVICE); + + nfp_net_rx_give_one(rx_ring, new_frag, new_dma_addr); + + skb_reserve(skb, data_off); + skb_put(skb, pkt_len); + if (nn->fw_ver.major <= 3) { nfp_net_set_hash_desc(nn->netdev, skb, rxd); } else if (meta_len) { -- cgit v1.2.3 From ecd63a0217d5f1e8a92f7516f5586d1177b95de2 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:07 +0000 Subject: nfp: add XDP support in the driver Add XDP support. Separate stack's and XDP's TX rings logically. Add functions for handling XDP_TX and cleanup of XDP's TX rings. For XDP allocate all RX buffers as separate pages and map them with DMA_BIDIRECTIONAL. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 17 +- .../net/ethernet/netronome/nfp/nfp_net_common.c | 474 +++++++++++++++++---- .../net/ethernet/netronome/nfp/nfp_net_debugfs.c | 37 +- .../net/ethernet/netronome/nfp/nfp_net_ethtool.c | 22 +- 4 files changed, 449 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 486e7c6453bc..abc9e56e93b8 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -171,7 +171,10 @@ struct nfp_net_tx_desc { * on the head's buffer). Equal to skb->len for non-TSO packets. */ struct nfp_net_tx_buf { - struct sk_buff *skb; + union { + struct sk_buff *skb; + void *frag; + }; dma_addr_t dma_addr; short int fidx; u16 pkt_cnt; @@ -341,6 +344,7 @@ struct nfp_net_rx_ring { * @napi: NAPI structure for this ring vec * @tx_ring: Pointer to TX ring * @rx_ring: Pointer to RX ring + * @xdp_ring: Pointer to an extra TX ring for XDP * @irq_idx: Index into MSI-X table * @rx_sync: Seqlock for atomic updates of RX stats * @rx_pkts: Number of received packets @@ -384,6 +388,8 @@ struct nfp_net_r_vector { u64 hw_csum_rx_inner_ok; u64 hw_csum_rx_error; + struct nfp_net_tx_ring *xdp_ring; + struct u64_stats_sync tx_sync; u64 tx_pkts; u64 tx_bytes; @@ -432,6 +438,7 @@ struct nfp_stat_pair { * @ctrl: Local copy of the control register/word. * @fl_bufsz: Currently configured size of the freelist buffers * @rx_offset: Offset in the RX buffers where packet data starts + * @xdp_prog: Installed XDP program * @cpp: Pointer to the CPP handle * @nfp_dev_cpp: Pointer to the NFP Device handle * @ctrl_area: Pointer to the CPP area for the control BAR @@ -451,6 +458,7 @@ struct nfp_stat_pair { * @max_tx_rings: Maximum number of TX rings supported by the Firmware * @max_rx_rings: Maximum number of RX rings supported by the Firmware * @num_tx_rings: Currently configured number of TX rings + * @num_stack_tx_rings: Number of TX rings used by the stack (not XDP) * @num_rx_rings: Currently configured number of RX rings * @txd_cnt: Size of the TX ring in number of descriptors * @rxd_cnt: Size of the RX ring in number of descriptors @@ -500,6 +508,8 @@ struct nfp_net { u32 rx_offset; + struct bpf_prog *xdp_prog; + struct nfp_net_tx_ring *tx_rings; struct nfp_net_rx_ring *rx_rings; @@ -532,6 +542,7 @@ struct nfp_net { unsigned int max_rx_rings; unsigned int num_tx_rings; + unsigned int num_stack_tx_rings; unsigned int num_rx_rings; int stride_tx; @@ -779,8 +790,8 @@ void nfp_net_coalesce_write_cfg(struct nfp_net *nn); int nfp_net_irqs_alloc(struct nfp_net *nn); void nfp_net_irqs_disable(struct nfp_net *nn); int -nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, - struct nfp_net_ring_set *tx); +nfp_net_ring_reconfig(struct nfp_net *nn, struct bpf_prog **xdp_prog, + struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx); #ifdef CONFIG_NFP_NET_DEBUG void nfp_net_debugfs_create(void); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 2ab63661a6fd..fa43dbcecc4f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -41,6 +41,7 @@ * Chris Telfer */ +#include #include #include #include @@ -490,6 +491,7 @@ static void nfp_net_irqs_assign(struct net_device *netdev) nn->num_rx_rings = min(nn->num_r_vecs, nn->num_rx_rings); nn->num_tx_rings = min(nn->num_r_vecs, nn->num_tx_rings); + nn->num_stack_tx_rings = nn->num_tx_rings; nn->lsc_handler = nfp_net_irq_lsc; nn->exn_handler = nfp_net_irq_exn; @@ -713,6 +715,13 @@ static void nfp_net_tx_csum(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, u64_stats_update_end(&r_vec->tx_sync); } +static void nfp_net_tx_xmit_more_flush(struct nfp_net_tx_ring *tx_ring) +{ + wmb(); + nfp_qcp_wr_ptr_add(tx_ring->qcp_q, tx_ring->wr_ptr_add); + tx_ring->wr_ptr_add = 0; +} + /** * nfp_net_tx() - Main transmit entry point * @skb: SKB to transmit @@ -827,12 +836,8 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) nfp_net_tx_ring_stop(nd_q, tx_ring); tx_ring->wr_ptr_add += nr_frags + 1; - if (!skb->xmit_more || netif_xmit_stopped(nd_q)) { - /* force memory write before we let HW know */ - wmb(); - nfp_qcp_wr_ptr_add(tx_ring->qcp_q, tx_ring->wr_ptr_add); - tx_ring->wr_ptr_add = 0; - } + if (!skb->xmit_more || netif_xmit_stopped(nd_q)) + nfp_net_tx_xmit_more_flush(tx_ring); skb_tx_timestamp(skb); @@ -954,6 +959,56 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring) tx_ring->rd_p, tx_ring->wr_p, tx_ring->cnt); } +static void nfp_net_xdp_complete(struct nfp_net_tx_ring *tx_ring) +{ + struct nfp_net_r_vector *r_vec = tx_ring->r_vec; + struct nfp_net *nn = r_vec->nfp_net; + u32 done_pkts = 0, done_bytes = 0; + int idx, todo; + u32 qcp_rd_p; + + /* Work out how many descriptors have been transmitted */ + qcp_rd_p = nfp_qcp_rd_ptr_read(tx_ring->qcp_q); + + if (qcp_rd_p == tx_ring->qcp_rd_p) + return; + + if (qcp_rd_p > tx_ring->qcp_rd_p) + todo = qcp_rd_p - tx_ring->qcp_rd_p; + else + todo = qcp_rd_p + tx_ring->cnt - tx_ring->qcp_rd_p; + + while (todo--) { + idx = tx_ring->rd_p & (tx_ring->cnt - 1); + tx_ring->rd_p++; + + if (!tx_ring->txbufs[idx].frag) + continue; + + nfp_net_dma_unmap_rx(nn, tx_ring->txbufs[idx].dma_addr, + nn->fl_bufsz, DMA_BIDIRECTIONAL); + __free_page(virt_to_page(tx_ring->txbufs[idx].frag)); + + done_pkts++; + done_bytes += tx_ring->txbufs[idx].real_len; + + tx_ring->txbufs[idx].dma_addr = 0; + tx_ring->txbufs[idx].frag = NULL; + tx_ring->txbufs[idx].fidx = -2; + } + + tx_ring->qcp_rd_p = qcp_rd_p; + + u64_stats_update_begin(&r_vec->tx_sync); + r_vec->tx_bytes += done_bytes; + r_vec->tx_pkts += done_pkts; + u64_stats_update_end(&r_vec->tx_sync); + + WARN_ONCE(tx_ring->wr_p - tx_ring->rd_p > tx_ring->cnt, + "TX ring corruption rd_p=%u wr_p=%u cnt=%u\n", + tx_ring->rd_p, tx_ring->wr_p, tx_ring->cnt); +} + /** * nfp_net_tx_ring_reset() - Free any untransmitted buffers and reset pointers * @nn: NFP Net device @@ -964,39 +1019,47 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring) static void nfp_net_tx_ring_reset(struct nfp_net *nn, struct nfp_net_tx_ring *tx_ring) { + struct nfp_net_r_vector *r_vec = tx_ring->r_vec; const struct skb_frag_struct *frag; - struct netdev_queue *nd_q; struct pci_dev *pdev = nn->pdev; + struct netdev_queue *nd_q; while (tx_ring->rd_p != tx_ring->wr_p) { - int nr_frags, fidx, idx; - struct sk_buff *skb; + struct nfp_net_tx_buf *tx_buf; + int idx; idx = tx_ring->rd_p & (tx_ring->cnt - 1); - skb = tx_ring->txbufs[idx].skb; - nr_frags = skb_shinfo(skb)->nr_frags; - fidx = tx_ring->txbufs[idx].fidx; + tx_buf = &tx_ring->txbufs[idx]; - if (fidx == -1) { - /* unmap head */ - dma_unmap_single(&pdev->dev, - tx_ring->txbufs[idx].dma_addr, - skb_headlen(skb), DMA_TO_DEVICE); + if (tx_ring == r_vec->xdp_ring) { + nfp_net_dma_unmap_rx(nn, tx_buf->dma_addr, + nn->fl_bufsz, DMA_BIDIRECTIONAL); + __free_page(virt_to_page(tx_ring->txbufs[idx].frag)); } else { - /* unmap fragment */ - frag = &skb_shinfo(skb)->frags[fidx]; - dma_unmap_page(&pdev->dev, - tx_ring->txbufs[idx].dma_addr, - skb_frag_size(frag), DMA_TO_DEVICE); - } + struct sk_buff *skb = tx_ring->txbufs[idx].skb; + int nr_frags = skb_shinfo(skb)->nr_frags; + + if (tx_buf->fidx == -1) { + /* unmap head */ + dma_unmap_single(&pdev->dev, tx_buf->dma_addr, + skb_headlen(skb), + DMA_TO_DEVICE); + } else { + /* unmap fragment */ + frag = &skb_shinfo(skb)->frags[tx_buf->fidx]; + dma_unmap_page(&pdev->dev, tx_buf->dma_addr, + skb_frag_size(frag), + DMA_TO_DEVICE); + } - /* check for last gather fragment */ - if (fidx == nr_frags - 1) - dev_kfree_skb_any(skb); + /* check for last gather fragment */ + if (tx_buf->fidx == nr_frags - 1) + dev_kfree_skb_any(skb); + } - tx_ring->txbufs[idx].dma_addr = 0; - tx_ring->txbufs[idx].skb = NULL; - tx_ring->txbufs[idx].fidx = -2; + tx_buf->dma_addr = 0; + tx_buf->skb = NULL; + tx_buf->fidx = -2; tx_ring->qcp_rd_p++; tx_ring->rd_p++; @@ -1008,6 +1071,9 @@ nfp_net_tx_ring_reset(struct nfp_net *nn, struct nfp_net_tx_ring *tx_ring) tx_ring->qcp_rd_p = 0; tx_ring->wr_ptr_add = 0; + if (tx_ring == r_vec->xdp_ring) + return; + nd_q = netdev_get_tx_queue(nn->netdev, tx_ring->idx); netdev_tx_reset_queue(nd_q); } @@ -1017,7 +1083,7 @@ static void nfp_net_tx_timeout(struct net_device *netdev) struct nfp_net *nn = netdev_priv(netdev); int i; - for (i = 0; i < nn->num_tx_rings; i++) { + for (i = 0; i < nn->netdev->real_num_tx_queues; i++) { if (!netif_tx_queue_stopped(netdev_get_tx_queue(netdev, i))) continue; nn_warn(nn, "TX timeout on ring: %d\n", i); @@ -1045,11 +1111,21 @@ nfp_net_calc_fl_bufsz(struct nfp_net *nn, unsigned int mtu) return fl_bufsz; } +static void +nfp_net_free_frag(void *frag, bool xdp) +{ + if (!xdp) + skb_free_frag(frag); + else + __free_page(virt_to_page(frag)); +} + /** * nfp_net_rx_alloc_one() - Allocate and map page frag for RX * @rx_ring: RX ring structure of the skb * @dma_addr: Pointer to storage for DMA address (output param) * @fl_bufsz: size of freelist buffers + * @xdp: Whether XDP is enabled * * This function will allcate a new page frag, map it for DMA. * @@ -1057,20 +1133,26 @@ nfp_net_calc_fl_bufsz(struct nfp_net *nn, unsigned int mtu) */ static void * nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr, - unsigned int fl_bufsz) + unsigned int fl_bufsz, bool xdp) { struct nfp_net *nn = rx_ring->r_vec->nfp_net; + int direction; void *frag; - frag = netdev_alloc_frag(fl_bufsz); + if (!xdp) + frag = netdev_alloc_frag(fl_bufsz); + else + frag = page_address(alloc_page(GFP_KERNEL | __GFP_COLD)); if (!frag) { nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n"); return NULL; } - *dma_addr = nfp_net_dma_map_rx(nn, frag, fl_bufsz, DMA_FROM_DEVICE); + direction = xdp ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE; + + *dma_addr = nfp_net_dma_map_rx(nn, frag, fl_bufsz, direction); if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) { - skb_free_frag(frag); + nfp_net_free_frag(frag, xdp); nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n"); return NULL; } @@ -1078,19 +1160,23 @@ nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr, return frag; } -static void *nfp_net_napi_alloc_one(struct nfp_net *nn, dma_addr_t *dma_addr) +static void * +nfp_net_napi_alloc_one(struct nfp_net *nn, int direction, dma_addr_t *dma_addr) { void *frag; - frag = napi_alloc_frag(nn->fl_bufsz); + if (!nn->xdp_prog) + frag = napi_alloc_frag(nn->fl_bufsz); + else + frag = page_address(alloc_page(GFP_ATOMIC | __GFP_COLD)); if (!frag) { nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n"); return NULL; } - *dma_addr = nfp_net_dma_map_rx(nn, frag, nn->fl_bufsz, DMA_FROM_DEVICE); + *dma_addr = nfp_net_dma_map_rx(nn, frag, nn->fl_bufsz, direction); if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) { - skb_free_frag(frag); + nfp_net_free_frag(frag, nn->xdp_prog); nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n"); return NULL; } @@ -1161,14 +1247,17 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring) * nfp_net_rx_ring_bufs_free() - Free any buffers currently on the RX ring * @nn: NFP Net device * @rx_ring: RX ring to remove buffers from + * @xdp: Whether XDP is enabled * * Assumes that the device is stopped and buffers are in [0, ring->cnt - 1) * entries. After device is disabled nfp_net_rx_ring_reset() must be called * to restore required ring geometry. */ static void -nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) +nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring, + bool xdp) { + int direction = xdp ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE; unsigned int i; for (i = 0; i < rx_ring->cnt - 1; i++) { @@ -1180,8 +1269,8 @@ nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) continue; nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[i].dma_addr, - rx_ring->bufsz, DMA_FROM_DEVICE); - skb_free_frag(rx_ring->rxbufs[i].frag); + rx_ring->bufsz, direction); + nfp_net_free_frag(rx_ring->rxbufs[i].frag, xdp); rx_ring->rxbufs[i].dma_addr = 0; rx_ring->rxbufs[i].frag = NULL; } @@ -1191,9 +1280,11 @@ nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) * nfp_net_rx_ring_bufs_alloc() - Fill RX ring with buffers (don't give to FW) * @nn: NFP Net device * @rx_ring: RX ring to remove buffers from + * @xdp: Whether XDP is enabled */ static int -nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) +nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring, + bool xdp) { struct nfp_net_rx_buf *rxbufs; unsigned int i; @@ -1203,9 +1294,9 @@ nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) for (i = 0; i < rx_ring->cnt - 1; i++) { rxbufs[i].frag = nfp_net_rx_alloc_one(rx_ring, &rxbufs[i].dma_addr, - rx_ring->bufsz); + rx_ring->bufsz, xdp); if (!rxbufs[i].frag) { - nfp_net_rx_ring_bufs_free(nn, rx_ring); + nfp_net_rx_ring_bufs_free(nn, rx_ring, xdp); return -ENOMEM; } } @@ -1368,6 +1459,68 @@ nfp_net_rx_drop(struct nfp_net_r_vector *r_vec, struct nfp_net_rx_ring *rx_ring, dev_kfree_skb_any(skb); } +static void +nfp_net_tx_xdp_buf(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring, + struct nfp_net_tx_ring *tx_ring, + struct nfp_net_rx_buf *rxbuf, unsigned int pkt_off, + unsigned int pkt_len) +{ + struct nfp_net_tx_buf *txbuf; + struct nfp_net_tx_desc *txd; + dma_addr_t new_dma_addr; + void *new_frag; + int wr_idx; + + if (unlikely(nfp_net_tx_full(tx_ring, 1))) { + nfp_net_rx_drop(rx_ring->r_vec, rx_ring, rxbuf, NULL); + return; + } + + new_frag = nfp_net_napi_alloc_one(nn, DMA_BIDIRECTIONAL, &new_dma_addr); + if (unlikely(!new_frag)) { + nfp_net_rx_drop(rx_ring->r_vec, rx_ring, rxbuf, NULL); + return; + } + nfp_net_rx_give_one(rx_ring, new_frag, new_dma_addr); + + wr_idx = tx_ring->wr_p & (tx_ring->cnt - 1); + + /* Stash the soft descriptor of the head then initialize it */ + txbuf = &tx_ring->txbufs[wr_idx]; + txbuf->frag = rxbuf->frag; + txbuf->dma_addr = rxbuf->dma_addr; + txbuf->fidx = -1; + txbuf->pkt_cnt = 1; + txbuf->real_len = pkt_len; + + dma_sync_single_for_device(&nn->pdev->dev, rxbuf->dma_addr + pkt_off, + pkt_len, DMA_TO_DEVICE); + + /* Build TX descriptor */ + txd = &tx_ring->txds[wr_idx]; + txd->offset_eop = PCIE_DESC_TX_EOP; + txd->dma_len = cpu_to_le16(pkt_len); + nfp_desc_set_dma_addr(txd, rxbuf->dma_addr + pkt_off); + txd->data_len = cpu_to_le16(pkt_len); + + txd->flags = 0; + txd->mss = 0; + txd->l4_offset = 0; + + tx_ring->wr_p++; + tx_ring->wr_ptr_add++; +} + +static int nfp_net_run_xdp(struct bpf_prog *prog, void *data, unsigned int len) +{ + struct xdp_buff xdp; + + xdp.data = data; + xdp.data_end = data + len; + + return BPF_PROG_RUN(prog, (void *)&xdp); +} + /** * nfp_net_rx() - receive up to @budget packets on @rx_ring * @rx_ring: RX ring to receive from @@ -1383,10 +1536,20 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) { struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; + struct nfp_net_tx_ring *tx_ring; + struct bpf_prog *xdp_prog; + unsigned int true_bufsz; struct sk_buff *skb; int pkts_polled = 0; + int rx_dma_map_dir; int idx; + rcu_read_lock(); + xdp_prog = READ_ONCE(nn->xdp_prog); + rx_dma_map_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE; + true_bufsz = xdp_prog ? PAGE_SIZE : nn->fl_bufsz; + tx_ring = r_vec->xdp_ring; + while (pkts_polled < budget) { unsigned int meta_len, data_len, data_off, pkt_len, pkt_off; struct nfp_net_rx_buf *rxbuf; @@ -1437,19 +1600,45 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) r_vec->rx_bytes += pkt_len; u64_stats_update_end(&r_vec->rx_sync); - skb = build_skb(rxbuf->frag, nn->fl_bufsz); + if (xdp_prog) { + int act; + + dma_sync_single_for_cpu(&nn->pdev->dev, + rxbuf->dma_addr + pkt_off, + pkt_len, DMA_FROM_DEVICE); + act = nfp_net_run_xdp(xdp_prog, rxbuf->frag + data_off, + pkt_len); + switch (act) { + case XDP_PASS: + break; + case XDP_TX: + nfp_net_tx_xdp_buf(nn, rx_ring, tx_ring, rxbuf, + pkt_off, pkt_len); + continue; + default: + bpf_warn_invalid_xdp_action(act); + case XDP_ABORTED: + case XDP_DROP: + nfp_net_rx_give_one(rx_ring, rxbuf->frag, + rxbuf->dma_addr); + continue; + } + } + + skb = build_skb(rxbuf->frag, true_bufsz); if (unlikely(!skb)) { nfp_net_rx_drop(r_vec, rx_ring, rxbuf, NULL); continue; } - new_frag = nfp_net_napi_alloc_one(nn, &new_dma_addr); + new_frag = nfp_net_napi_alloc_one(nn, rx_dma_map_dir, + &new_dma_addr); if (unlikely(!new_frag)) { nfp_net_rx_drop(r_vec, rx_ring, rxbuf, skb); continue; } - nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[idx].dma_addr, - nn->fl_bufsz, DMA_FROM_DEVICE); + nfp_net_dma_unmap_rx(nn, rxbuf->dma_addr, nn->fl_bufsz, + rx_dma_map_dir); nfp_net_rx_give_one(rx_ring, new_frag, new_dma_addr); @@ -1481,6 +1670,10 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) napi_gro_receive(&rx_ring->r_vec->napi, skb); } + if (xdp_prog && tx_ring->wr_ptr_add) + nfp_net_tx_xmit_more_flush(tx_ring); + rcu_read_unlock(); + return pkts_polled; } @@ -1499,8 +1692,11 @@ static int nfp_net_poll(struct napi_struct *napi, int budget) if (r_vec->tx_ring) nfp_net_tx_complete(r_vec->tx_ring); - if (r_vec->rx_ring) + if (r_vec->rx_ring) { pkts_polled = nfp_net_rx(r_vec->rx_ring, budget); + if (r_vec->xdp_ring) + nfp_net_xdp_complete(r_vec->xdp_ring); + } if (pkts_polled < budget) { napi_complete_done(napi, pkts_polled); @@ -1540,10 +1736,12 @@ static void nfp_net_tx_ring_free(struct nfp_net_tx_ring *tx_ring) * nfp_net_tx_ring_alloc() - Allocate resource for a TX ring * @tx_ring: TX Ring structure to allocate * @cnt: Ring buffer count + * @is_xdp: True if ring will be used for XDP * * Return: 0 on success, negative errno otherwise. */ -static int nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring, u32 cnt) +static int +nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring, u32 cnt, bool is_xdp) { struct nfp_net_r_vector *r_vec = tx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; @@ -1563,11 +1761,14 @@ static int nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring, u32 cnt) if (!tx_ring->txbufs) goto err_alloc; - netif_set_xps_queue(nn->netdev, &r_vec->affinity_mask, tx_ring->idx); + if (!is_xdp) + netif_set_xps_queue(nn->netdev, &r_vec->affinity_mask, + tx_ring->idx); - nn_dbg(nn, "TxQ%02d: QCidx=%02d cnt=%d dma=%#llx host=%p\n", + nn_dbg(nn, "TxQ%02d: QCidx=%02d cnt=%d dma=%#llx host=%p %s\n", tx_ring->idx, tx_ring->qcidx, - tx_ring->cnt, (unsigned long long)tx_ring->dma, tx_ring->txds); + tx_ring->cnt, (unsigned long long)tx_ring->dma, tx_ring->txds, + is_xdp ? "XDP" : ""); return 0; @@ -1577,7 +1778,8 @@ err_alloc: } static struct nfp_net_tx_ring * -nfp_net_tx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_tx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s, + unsigned int num_stack_tx_rings) { struct nfp_net_tx_ring *rings; unsigned int r; @@ -1587,9 +1789,14 @@ nfp_net_tx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) return NULL; for (r = 0; r < s->n_rings; r++) { - nfp_net_tx_ring_init(&rings[r], &nn->r_vecs[r], r); + int bias = 0; + + if (r >= num_stack_tx_rings) + bias = num_stack_tx_rings; - if (nfp_net_tx_ring_alloc(&rings[r], s->dcnt)) + nfp_net_tx_ring_init(&rings[r], &nn->r_vecs[r - bias], r); + + if (nfp_net_tx_ring_alloc(&rings[r], s->dcnt, bias)) goto err_free_prev; } @@ -1694,7 +1901,8 @@ err_alloc: } static struct nfp_net_rx_ring * -nfp_net_rx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_rx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s, + bool xdp) { unsigned int fl_bufsz = nfp_net_calc_fl_bufsz(nn, s->mtu); struct nfp_net_rx_ring *rings; @@ -1710,7 +1918,7 @@ nfp_net_rx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz, s->dcnt)) goto err_free_prev; - if (nfp_net_rx_ring_bufs_alloc(nn, &rings[r])) + if (nfp_net_rx_ring_bufs_alloc(nn, &rings[r], xdp)) goto err_free_ring; } @@ -1718,7 +1926,7 @@ nfp_net_rx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s) err_free_prev: while (r--) { - nfp_net_rx_ring_bufs_free(nn, &rings[r]); + nfp_net_rx_ring_bufs_free(nn, &rings[r], xdp); err_free_ring: nfp_net_rx_ring_free(&rings[r]); } @@ -1744,13 +1952,14 @@ nfp_net_rx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s) } static void -nfp_net_rx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s) +nfp_net_rx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s, + bool xdp) { struct nfp_net_rx_ring *rings = s->rings; unsigned int r; for (r = 0; r < s->n_rings; r++) { - nfp_net_rx_ring_bufs_free(nn, &rings[r]); + nfp_net_rx_ring_bufs_free(nn, &rings[r], xdp); nfp_net_rx_ring_free(&rings[r]); } @@ -1762,7 +1971,11 @@ nfp_net_vector_assign_rings(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, int idx) { r_vec->rx_ring = idx < nn->num_rx_rings ? &nn->rx_rings[idx] : NULL; - r_vec->tx_ring = idx < nn->num_tx_rings ? &nn->tx_rings[idx] : NULL; + r_vec->tx_ring = + idx < nn->num_stack_tx_rings ? &nn->tx_rings[idx] : NULL; + + r_vec->xdp_ring = idx < nn->num_tx_rings - nn->num_stack_tx_rings ? + &nn->tx_rings[nn->num_stack_tx_rings + idx] : NULL; } static int @@ -2083,13 +2296,14 @@ static int nfp_net_netdev_open(struct net_device *netdev) goto err_cleanup_vec_p; } - nn->rx_rings = nfp_net_rx_ring_set_prepare(nn, &rx); + nn->rx_rings = nfp_net_rx_ring_set_prepare(nn, &rx, nn->xdp_prog); if (!nn->rx_rings) { err = -ENOMEM; goto err_cleanup_vec; } - nn->tx_rings = nfp_net_tx_ring_set_prepare(nn, &tx); + nn->tx_rings = nfp_net_tx_ring_set_prepare(nn, &tx, + nn->num_stack_tx_rings); if (!nn->tx_rings) { err = -ENOMEM; goto err_free_rx_rings; @@ -2098,7 +2312,7 @@ static int nfp_net_netdev_open(struct net_device *netdev) for (r = 0; r < nn->max_r_vecs; r++) nfp_net_vector_assign_rings(nn, &nn->r_vecs[r], r); - err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings); + err = netif_set_real_num_tx_queues(netdev, nn->num_stack_tx_rings); if (err) goto err_free_rings; @@ -2130,7 +2344,7 @@ static int nfp_net_netdev_open(struct net_device *netdev) err_free_rings: nfp_net_tx_ring_set_free(nn, &tx); err_free_rx_rings: - nfp_net_rx_ring_set_free(nn, &rx); + nfp_net_rx_ring_set_free(nn, &rx, nn->xdp_prog); err_cleanup_vec: r = nn->num_r_vecs; err_cleanup_vec_p: @@ -2171,7 +2385,7 @@ static void nfp_net_close_free_all(struct nfp_net *nn) unsigned int r; for (r = 0; r < nn->num_rx_rings; r++) { - nfp_net_rx_ring_bufs_free(nn, &nn->rx_rings[r]); + nfp_net_rx_ring_bufs_free(nn, &nn->rx_rings[r], nn->xdp_prog); nfp_net_rx_ring_free(&nn->rx_rings[r]); } for (r = 0; r < nn->num_tx_rings; r++) @@ -2251,6 +2465,8 @@ static void nfp_net_rss_init_itbl(struct nfp_net *nn) static int nfp_net_ring_swap_enable(struct nfp_net *nn, unsigned int *num_vecs, + unsigned int *stack_tx_rings, + struct bpf_prog **xdp_prog, struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx) { @@ -2263,6 +2479,8 @@ nfp_net_ring_swap_enable(struct nfp_net *nn, unsigned int *num_vecs, nfp_net_tx_ring_set_swap(nn, tx); swap(*num_vecs, nn->num_r_vecs); + swap(*stack_tx_rings, nn->num_stack_tx_rings); + *xdp_prog = xchg(&nn->xdp_prog, *xdp_prog); for (r = 0; r < nn->max_r_vecs; r++) nfp_net_vector_assign_rings(nn, &nn->r_vecs[r], r); @@ -2277,9 +2495,9 @@ nfp_net_ring_swap_enable(struct nfp_net *nn, unsigned int *num_vecs, return err; } - if (nn->netdev->real_num_tx_queues != nn->num_tx_rings) { + if (nn->netdev->real_num_tx_queues != nn->num_stack_tx_rings) { err = netif_set_real_num_tx_queues(nn->netdev, - nn->num_tx_rings); + nn->num_stack_tx_rings); if (err) return err; } @@ -2287,11 +2505,30 @@ nfp_net_ring_swap_enable(struct nfp_net *nn, unsigned int *num_vecs, return __nfp_net_set_config_and_enable(nn); } +static int +nfp_net_check_config(struct nfp_net *nn, struct bpf_prog *xdp_prog, + struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx) +{ + /* XDP-enabled tests */ + if (!xdp_prog) + return 0; + if (rx && nfp_net_calc_fl_bufsz(nn, rx->mtu) > PAGE_SIZE) { + nn_warn(nn, "MTU too large w/ XDP enabled\n"); + return -EINVAL; + } + if (tx && tx->n_rings > nn->max_tx_rings) { + nn_warn(nn, "Insufficient number of TX rings w/ XDP enabled\n"); + return -EINVAL; + } + + return 0; +} + static void -nfp_net_ring_reconfig_down(struct nfp_net *nn, +nfp_net_ring_reconfig_down(struct nfp_net *nn, struct bpf_prog **xdp_prog, struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx, - unsigned int num_vecs) + unsigned int stack_tx_rings, unsigned int num_vecs) { nn->netdev->mtu = rx ? rx->mtu : nn->netdev->mtu; nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, nn->netdev->mtu); @@ -2299,24 +2536,34 @@ nfp_net_ring_reconfig_down(struct nfp_net *nn, nn->txd_cnt = tx ? tx->dcnt : nn->txd_cnt; nn->num_rx_rings = rx ? rx->n_rings : nn->num_rx_rings; nn->num_tx_rings = tx ? tx->n_rings : nn->num_tx_rings; + nn->num_stack_tx_rings = stack_tx_rings; nn->num_r_vecs = num_vecs; + *xdp_prog = xchg(&nn->xdp_prog, *xdp_prog); if (!netif_is_rxfh_configured(nn->netdev)) nfp_net_rss_init_itbl(nn); } int -nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, - struct nfp_net_ring_set *tx) +nfp_net_ring_reconfig(struct nfp_net *nn, struct bpf_prog **xdp_prog, + struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx) { - unsigned int num_vecs, r; + unsigned int stack_tx_rings, num_vecs, r; int err; - num_vecs = max(rx ? rx->n_rings : nn->num_rx_rings, - tx ? tx->n_rings : nn->num_tx_rings); + stack_tx_rings = tx ? tx->n_rings : nn->num_tx_rings; + if (*xdp_prog) + stack_tx_rings -= rx ? rx->n_rings : nn->num_rx_rings; + + num_vecs = max(rx ? rx->n_rings : nn->num_rx_rings, stack_tx_rings); + + err = nfp_net_check_config(nn, *xdp_prog, rx, tx); + if (err) + return err; if (!netif_running(nn->netdev)) { - nfp_net_ring_reconfig_down(nn, rx, tx, num_vecs); + nfp_net_ring_reconfig_down(nn, xdp_prog, rx, tx, + stack_tx_rings, num_vecs); return 0; } @@ -2329,13 +2576,13 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, } } if (rx) { - if (!nfp_net_rx_ring_set_prepare(nn, rx)) { + if (!nfp_net_rx_ring_set_prepare(nn, rx, *xdp_prog)) { err = -ENOMEM; goto err_cleanup_vecs; } } if (tx) { - if (!nfp_net_tx_ring_set_prepare(nn, tx)) { + if (!nfp_net_tx_ring_set_prepare(nn, tx, stack_tx_rings)) { err = -ENOMEM; goto err_free_rx; } @@ -2345,14 +2592,16 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, nfp_net_close_stack(nn); nfp_net_clear_config_and_disable(nn); - err = nfp_net_ring_swap_enable(nn, &num_vecs, rx, tx); + err = nfp_net_ring_swap_enable(nn, &num_vecs, &stack_tx_rings, + xdp_prog, rx, tx); if (err) { int err2; nfp_net_clear_config_and_disable(nn); /* Try with old configuration and old rings */ - err2 = nfp_net_ring_swap_enable(nn, &num_vecs, rx, tx); + err2 = nfp_net_ring_swap_enable(nn, &num_vecs, &stack_tx_rings, + xdp_prog, rx, tx); if (err2) nn_err(nn, "Can't restore ring config - FW communication failed (%d,%d)\n", err, err2); @@ -2361,7 +2610,7 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); if (rx) - nfp_net_rx_ring_set_free(nn, rx); + nfp_net_rx_ring_set_free(nn, rx, *xdp_prog); if (tx) nfp_net_tx_ring_set_free(nn, tx); @@ -2371,7 +2620,7 @@ nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx, err_free_rx: if (rx) - nfp_net_rx_ring_set_free(nn, rx); + nfp_net_rx_ring_set_free(nn, rx, *xdp_prog); err_cleanup_vecs: for (r = num_vecs - 1; r >= nn->num_r_vecs; r--) nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); @@ -2387,7 +2636,7 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) .dcnt = nn->rxd_cnt, }; - return nfp_net_ring_reconfig(nn, &rx, NULL); + return nfp_net_ring_reconfig(nn, &nn->xdp_prog, &rx, NULL); } static struct rtnl_link_stats64 *nfp_net_stat64(struct net_device *netdev, @@ -2653,6 +2902,56 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev, nfp_net_set_vxlan_port(nn, idx, 0); } +static int nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog) +{ + struct nfp_net_ring_set rx = { + .n_rings = nn->num_rx_rings, + .mtu = nn->netdev->mtu, + .dcnt = nn->rxd_cnt, + }; + struct nfp_net_ring_set tx = { + .n_rings = nn->num_tx_rings, + .dcnt = nn->txd_cnt, + }; + int err; + + if (!prog && !nn->xdp_prog) + return 0; + if (prog && nn->xdp_prog) { + prog = xchg(&nn->xdp_prog, prog); + bpf_prog_put(prog); + return 0; + } + + tx.n_rings += prog ? nn->num_rx_rings : -nn->num_rx_rings; + + /* We need RX reconfig to remap the buffers (BIDIR vs FROM_DEV) */ + err = nfp_net_ring_reconfig(nn, &prog, &rx, &tx); + if (err) + return err; + + /* @prog got swapped and is now the old one */ + if (prog) + bpf_prog_put(prog); + + return 0; +} + +static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp) +{ + struct nfp_net *nn = netdev_priv(netdev); + + switch (xdp->command) { + case XDP_SETUP_PROG: + return nfp_net_xdp_setup(nn, xdp->prog); + case XDP_QUERY_PROG: + xdp->prog_attached = !!nn->xdp_prog; + return 0; + default: + return -EINVAL; + } +} + static const struct net_device_ops nfp_net_netdev_ops = { .ndo_open = nfp_net_netdev_open, .ndo_stop = nfp_net_netdev_close, @@ -2667,6 +2966,7 @@ static const struct net_device_ops nfp_net_netdev_ops = { .ndo_features_check = nfp_net_features_check, .ndo_udp_tunnel_add = nfp_net_add_vxlan_port, .ndo_udp_tunnel_del = nfp_net_del_vxlan_port, + .ndo_xdp = nfp_net_xdp, }; /** @@ -2929,5 +3229,9 @@ int nfp_net_netdev_init(struct net_device *netdev) */ void nfp_net_netdev_clean(struct net_device *netdev) { - unregister_netdev(netdev); + struct nfp_net *nn = netdev_priv(netdev); + + if (nn->xdp_prog) + bpf_prog_put(nn->xdp_prog); + unregister_netdev(nn->netdev); } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c index e90df8145323..c66f3f954aa8 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c @@ -114,6 +114,16 @@ static const struct file_operations nfp_rx_q_fops = { .llseek = seq_lseek }; +static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f); + +static const struct file_operations nfp_tx_q_fops = { + .owner = THIS_MODULE, + .open = nfp_net_debugfs_tx_q_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek +}; + static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data) { struct nfp_net_r_vector *r_vec = file->private; @@ -126,10 +136,13 @@ static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data) rtnl_lock(); - if (!r_vec->nfp_net || !r_vec->tx_ring) + if (debugfs_real_fops(file->file) == &nfp_tx_q_fops) + tx_ring = r_vec->tx_ring; + else + tx_ring = r_vec->xdp_ring; + if (!r_vec->nfp_net || !tx_ring) goto out; nn = r_vec->nfp_net; - tx_ring = r_vec->tx_ring; if (!netif_running(nn->netdev)) goto out; @@ -148,9 +161,14 @@ static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data) txd->vals[2], txd->vals[3]); skb = READ_ONCE(tx_ring->txbufs[i].skb); - if (skb) - seq_printf(file, " skb->head=%p skb->data=%p", - skb->head, skb->data); + if (skb) { + if (tx_ring == r_vec->tx_ring) + seq_printf(file, " skb->head=%p skb->data=%p", + skb->head, skb->data); + else + seq_printf(file, " frag=%p", skb); + } + if (tx_ring->txbufs[i].dma_addr) seq_printf(file, " dma_addr=%pad", &tx_ring->txbufs[i].dma_addr); @@ -176,7 +194,7 @@ static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f) return single_open(f, nfp_net_debugfs_tx_q_read, inode->i_private); } -static const struct file_operations nfp_tx_q_fops = { +static const struct file_operations nfp_xdp_q_fops = { .owner = THIS_MODULE, .open = nfp_net_debugfs_tx_q_open, .release = single_release, @@ -186,7 +204,7 @@ static const struct file_operations nfp_tx_q_fops = { void nfp_net_debugfs_adapter_add(struct nfp_net *nn) { - struct dentry *queues, *tx, *rx; + struct dentry *queues, *tx, *rx, *xdp; char int_name[16]; int i; @@ -204,13 +222,16 @@ void nfp_net_debugfs_adapter_add(struct nfp_net *nn) rx = debugfs_create_dir("rx", queues); tx = debugfs_create_dir("tx", queues); - if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx)) + xdp = debugfs_create_dir("xdp", queues); + if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx) || IS_ERR_OR_NULL(xdp)) return; for (i = 0; i < min(nn->max_rx_rings, nn->max_r_vecs); i++) { sprintf(int_name, "%d", i); debugfs_create_file(int_name, S_IRUSR, rx, &nn->r_vecs[i], &nfp_rx_q_fops); + debugfs_create_file(int_name, S_IRUSR, xdp, + &nn->r_vecs[i], &nfp_xdp_q_fops); } for (i = 0; i < min(nn->max_tx_rings, nn->max_r_vecs); i++) { diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index b87f1b73f200..1b26e9646574 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -176,7 +176,8 @@ static int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt) if (nn->txd_cnt != txd_cnt) reconfig_tx = &tx; - return nfp_net_ring_reconfig(nn, reconfig_rx, reconfig_tx); + return nfp_net_ring_reconfig(nn, &nn->xdp_prog, + reconfig_rx, reconfig_tx); } static int nfp_net_set_ringparam(struct net_device *netdev, @@ -639,14 +640,19 @@ static void nfp_net_get_channels(struct net_device *netdev, struct ethtool_channels *channel) { struct nfp_net *nn = netdev_priv(netdev); + unsigned int num_tx_rings; + + num_tx_rings = nn->num_tx_rings; + if (nn->xdp_prog) + num_tx_rings -= nn->num_rx_rings; channel->max_rx = min(nn->max_rx_rings, nn->max_r_vecs); channel->max_tx = min(nn->max_tx_rings, nn->max_r_vecs); channel->max_combined = min(channel->max_rx, channel->max_tx); channel->max_other = NFP_NET_NON_Q_VECTORS; - channel->combined_count = min(nn->num_rx_rings, nn->num_tx_rings); + channel->combined_count = min(nn->num_rx_rings, num_tx_rings); channel->rx_count = nn->num_rx_rings - channel->combined_count; - channel->tx_count = nn->num_tx_rings - channel->combined_count; + channel->tx_count = num_tx_rings - channel->combined_count; channel->other_count = NFP_NET_NON_Q_VECTORS; } @@ -666,10 +672,16 @@ static int nfp_net_set_num_rings(struct nfp_net *nn, unsigned int total_rx, if (nn->num_rx_rings != total_rx) reconfig_rx = ℞ - if (nn->num_tx_rings != total_tx) + if (nn->num_stack_tx_rings != total_tx || + (nn->xdp_prog && reconfig_rx)) reconfig_tx = &tx; - return nfp_net_ring_reconfig(nn, reconfig_rx, reconfig_tx); + /* nfp_net_check_config() will catch tx.n_rings > nn->max_tx_rings */ + if (nn->xdp_prog) + tx.n_rings += total_rx; + + return nfp_net_ring_reconfig(nn, &nn->xdp_prog, + reconfig_rx, reconfig_tx); } static int nfp_net_set_channels(struct net_device *netdev, -- cgit v1.2.3 From 2e9d594d50652395f35744ea98624430c57aae2b Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:08 +0000 Subject: nfp: remove unnecessary parameters from nfp_net_bpf_offload() nfp_net_bpf_offload() takes all .setup_tc() parameters but it doesn't use them at the moment. Remove unnecessary ones to make it possible for XDP to reuse this function. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 4 +--- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 2 +- drivers/net/ethernet/netronome/nfp/nfp_net_offload.c | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index abc9e56e93b8..fd29a6306991 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -817,8 +817,6 @@ static inline void nfp_net_debugfs_adapter_del(struct nfp_net *nn) #endif /* CONFIG_NFP_NET_DEBUG */ void nfp_net_filter_stats_timer(unsigned long data); -int -nfp_net_bpf_offload(struct nfp_net *nn, u32 handle, __be16 proto, - struct tc_cls_bpf_offload *cls_bpf); +int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf); #endif /* _NFP_NET_H_ */ diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index fa43dbcecc4f..1e8e00d25c51 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2694,7 +2694,7 @@ nfp_net_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, return -ENOTSUPP; if (tc->type == TC_SETUP_CLSBPF && nfp_net_ebpf_capable(nn)) - return nfp_net_bpf_offload(nn, handle, proto, tc->cls_bpf); + return nfp_net_bpf_offload(nn, tc->cls_bpf); return -EINVAL; } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c b/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c index cfed40c0e310..4bb6f16e2a7a 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c @@ -233,9 +233,7 @@ static int nfp_net_bpf_stop(struct nfp_net *nn) return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN); } -int -nfp_net_bpf_offload(struct nfp_net *nn, u32 handle, __be16 proto, - struct tc_cls_bpf_offload *cls_bpf) +int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf) { struct nfp_bpf_result res; dma_addr_t dma_addr; -- cgit v1.2.3 From 6d6770755f053e0ab2f7c3ffcfeaaf8dbbe89092 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Nov 2016 17:12:09 +0000 Subject: nfp: add support for offload of XDP programs Most infrastructure can be reused, provide separate handling of context offsets and exit codes. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_bpf.h | 1 + drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c | 92 +++++++++++++++++++++- .../net/ethernet/netronome/nfp/nfp_bpf_verifier.c | 3 + drivers/net/ethernet/netronome/nfp/nfp_net.h | 2 + .../net/ethernet/netronome/nfp/nfp_net_common.c | 44 ++++++++++- .../net/ethernet/netronome/nfp/nfp_net_offload.c | 3 + 6 files changed, 139 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_bpf.h b/drivers/net/ethernet/netronome/nfp/nfp_bpf.h index 87aa8a3e9112..76a19f1796af 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_bpf.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_bpf.h @@ -62,6 +62,7 @@ enum nfp_bpf_action_type { NN_ACT_TC_DROP, NN_ACT_TC_REDIR, NN_ACT_DIRECT, + NN_ACT_XDP, }; /* Software register representation, hardware encoding in asm.h */ diff --git a/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c b/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c index f8df5300f49c..335beb8b8b45 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c @@ -1126,7 +1126,7 @@ static int data_ind_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) meta->insn.src_reg * 2, true, 4); } -static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +static int mem_ldx4_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { if (meta->insn.off == offsetof(struct sk_buff, len)) emit_alu(nfp_prog, reg_both(meta->insn.dst_reg * 2), @@ -1134,12 +1134,42 @@ static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) else return -ENOTSUPP; - wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0); + return 0; +} + +static int mem_ldx4_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +{ + u32 dst = reg_both(meta->insn.dst_reg * 2); + + if (meta->insn.off != offsetof(struct xdp_md, data) && + meta->insn.off != offsetof(struct xdp_md, data_end)) + return -ENOTSUPP; + + emit_alu(nfp_prog, dst, reg_none(), ALU_OP_NONE, NFP_BPF_ABI_PKT); + + if (meta->insn.off == offsetof(struct xdp_md, data)) + return 0; + + emit_alu(nfp_prog, dst, dst, ALU_OP_ADD, NFP_BPF_ABI_LEN); return 0; } -static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +{ + int ret; + + if (nfp_prog->act == NN_ACT_XDP) + ret = mem_ldx4_xdp(nfp_prog, meta); + else + ret = mem_ldx4_skb(nfp_prog, meta); + + wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0); + + return ret; +} + +static int mem_stx4_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { if (meta->insn.off == offsetof(struct sk_buff, mark)) return wrp_set_mark(nfp_prog, meta->insn.src_reg * 2); @@ -1147,6 +1177,18 @@ static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) return -ENOTSUPP; } +static int mem_stx4_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +{ + return -ENOTSUPP; +} + +static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +{ + if (nfp_prog->act == NN_ACT_XDP) + return mem_stx4_xdp(nfp_prog, meta); + return mem_stx4_skb(nfp_prog, meta); +} + static int jump(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { if (meta->insn.off < 0) /* TODO */ @@ -1530,6 +1572,47 @@ static void nfp_outro_tc_da(struct nfp_prog *nfp_prog) emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16); } +static void nfp_outro_xdp(struct nfp_prog *nfp_prog) +{ + /* XDP return codes: + * 0 aborted 0x82 -> drop, count as stat3 + * 1 drop 0x22 -> drop, count as stat1 + * 2 pass 0x11 -> pass, count as stat0 + * 3 tx 0x44 -> redir, count as stat2 + * * unknown 0x82 -> drop, count as stat3 + */ + /* Target for aborts */ + nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog); + + emit_br_def(nfp_prog, nfp_prog->tgt_done, 2); + + emit_alu(nfp_prog, reg_a(0), + reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS); + emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x82), SHF_SC_L_SHF, 16); + + /* Target for normal exits */ + nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog); + + /* if R0 > 3 jump to abort */ + emit_alu(nfp_prog, reg_none(), reg_imm(3), ALU_OP_SUB, reg_b(0)); + emit_br(nfp_prog, BR_BLO, nfp_prog->tgt_abort, 0); + + wrp_immed(nfp_prog, reg_b(2), 0x44112282); + + emit_shf(nfp_prog, reg_a(1), + reg_none(), SHF_OP_NONE, reg_b(0), SHF_SC_L_SHF, 3); + + emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0)); + emit_shf(nfp_prog, reg_b(2), + reg_imm(0xff), SHF_OP_AND, reg_b(2), SHF_SC_R_SHF, 0); + + emit_br_def(nfp_prog, nfp_prog->tgt_done, 2); + + emit_alu(nfp_prog, reg_a(0), + reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS); + emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16); +} + static void nfp_outro(struct nfp_prog *nfp_prog) { switch (nfp_prog->act) { @@ -1540,6 +1623,9 @@ static void nfp_outro(struct nfp_prog *nfp_prog) case NN_ACT_TC_REDIR: nfp_outro_tc_legacy(nfp_prog); break; + case NN_ACT_XDP: + nfp_outro_xdp(nfp_prog); + break; } } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c b/drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c index 144cae87f63a..b3361f9b8e5c 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c @@ -80,6 +80,9 @@ nfp_bpf_check_exit(struct nfp_prog *nfp_prog, { const struct bpf_reg_state *reg0 = &env->cur_state.regs[0]; + if (nfp_prog->act == NN_ACT_XDP) + return 0; + if (reg0->type != CONST_IMM) { pr_info("unsupported exit state: %d, imm: %llx\n", reg0->type, reg0->imm); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index fd29a6306991..2115f446031e 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -435,6 +435,7 @@ struct nfp_stat_pair { * @is_vf: Is the driver attached to a VF? * @fw_loaded: Is the firmware loaded? * @bpf_offload_skip_sw: Offloaded BPF program will not be rerun by cls_bpf + * @bpf_offload_xdp: Offloaded BPF program is XDP * @ctrl: Local copy of the control register/word. * @fl_bufsz: Currently configured size of the freelist buffers * @rx_offset: Offset in the RX buffers where packet data starts @@ -502,6 +503,7 @@ struct nfp_net { unsigned is_vf:1; unsigned fw_loaded:1; unsigned bpf_offload_skip_sw:1; + unsigned bpf_offload_xdp:1; u32 ctrl; u32 fl_bufsz; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 1e8e00d25c51..99edb9fd84bf 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1600,7 +1600,8 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) r_vec->rx_bytes += pkt_len; u64_stats_update_end(&r_vec->rx_sync); - if (xdp_prog) { + if (xdp_prog && !(rxd->rxd.flags & PCIE_DESC_RX_BPF && + nn->bpf_offload_xdp)) { int act; dma_sync_single_for_cpu(&nn->pdev->dev, @@ -2693,8 +2694,12 @@ nfp_net_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, if (proto != htons(ETH_P_ALL)) return -ENOTSUPP; - if (tc->type == TC_SETUP_CLSBPF && nfp_net_ebpf_capable(nn)) - return nfp_net_bpf_offload(nn, tc->cls_bpf); + if (tc->type == TC_SETUP_CLSBPF && nfp_net_ebpf_capable(nn)) { + if (!nn->bpf_offload_xdp) + return nfp_net_bpf_offload(nn, tc->cls_bpf); + else + return -EBUSY; + } return -EINVAL; } @@ -2902,6 +2907,34 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev, nfp_net_set_vxlan_port(nn, idx, 0); } +static int nfp_net_xdp_offload(struct nfp_net *nn, struct bpf_prog *prog) +{ + struct tc_cls_bpf_offload cmd = { + .prog = prog, + }; + int ret; + + if (!nfp_net_ebpf_capable(nn)) + return -EINVAL; + + if (nn->ctrl & NFP_NET_CFG_CTRL_BPF) { + if (!nn->bpf_offload_xdp) + return prog ? -EBUSY : 0; + cmd.command = prog ? TC_CLSBPF_REPLACE : TC_CLSBPF_DESTROY; + } else { + if (!prog) + return 0; + cmd.command = TC_CLSBPF_ADD; + } + + ret = nfp_net_bpf_offload(nn, &cmd); + /* Stop offload if replace not possible */ + if (ret && cmd.command == TC_CLSBPF_REPLACE) + nfp_net_xdp_offload(nn, NULL); + nn->bpf_offload_xdp = prog && !ret; + return ret; +} + static int nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog) { struct nfp_net_ring_set rx = { @@ -2920,6 +2953,7 @@ static int nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog) if (prog && nn->xdp_prog) { prog = xchg(&nn->xdp_prog, prog); bpf_prog_put(prog); + nfp_net_xdp_offload(nn, nn->xdp_prog); return 0; } @@ -2934,6 +2968,8 @@ static int nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog) if (prog) bpf_prog_put(prog); + nfp_net_xdp_offload(nn, nn->xdp_prog); + return 0; } @@ -3233,5 +3269,7 @@ void nfp_net_netdev_clean(struct net_device *netdev) if (nn->xdp_prog) bpf_prog_put(nn->xdp_prog); + if (nn->bpf_offload_xdp) + nfp_net_xdp_offload(nn, NULL); unregister_netdev(nn->netdev); } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c b/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c index 4bb6f16e2a7a..18a851eb3508 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c @@ -111,6 +111,9 @@ nfp_net_bpf_get_act(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf) const struct tc_action *a; LIST_HEAD(actions); + if (!cls_bpf->exts) + return NN_ACT_XDP; + /* TC direct action */ if (cls_bpf->exts_integrated) { if (tc_no_actions(cls_bpf->exts)) -- cgit v1.2.3 From 9fe69429509858d9db6ae123c4cb078351ec2623 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Wed, 2 Nov 2016 22:33:06 +0100 Subject: clk: pxa: transfer CPU clock setting from pxa2xx-cpufreq This is the initial stage to transfer the pxa25x and pxa27x CPU clocks handling from cpufreq to the clock API. More precisely, the clocks transferred are : - cpll : core pll, known also as the CPU core turbo frequency - core : core, known also as the CPU actual frequency, being either the CPU core turbo frequency or the CPU core run frequency This transfer is a prequel to shrink the code in pxa2xx-cpufreq.c, so that it can become, at least in devicetree builds, the casual cpufreq-dt driver. Signed-off-by: Robert Jarzmik Signed-off-by: Stephen Boyd --- drivers/clk/pxa/clk-pxa.c | 139 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/pxa/clk-pxa.h | 57 ++++++++++++++++- drivers/clk/pxa/clk-pxa25x.c | 101 ++++++++++++++++++++++++++++-- drivers/clk/pxa/clk-pxa27x.c | 144 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 414 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c index 29cee9e8d4d9..50fb9d0ea58d 100644 --- a/drivers/clk/pxa/clk-pxa.c +++ b/drivers/clk/pxa/clk-pxa.c @@ -18,6 +18,26 @@ #include #include "clk-pxa.h" +#define KHz 1000 +#define MHz (1000 * 1000) + +#define MDREFR_K0DB4 (1 << 29) /* SDCLK0 Divide by 4 Control/Status */ +#define MDREFR_K2FREE (1 << 25) /* SDRAM Free-Running Control */ +#define MDREFR_K1FREE (1 << 24) /* SDRAM Free-Running Control */ +#define MDREFR_K0FREE (1 << 23) /* SDRAM Free-Running Control */ +#define MDREFR_SLFRSH (1 << 22) /* SDRAM Self-Refresh Control/Status */ +#define MDREFR_APD (1 << 20) /* SDRAM/SSRAM Auto-Power-Down Enable */ +#define MDREFR_K2DB2 (1 << 19) /* SDCLK2 Divide by 2 Control/Status */ +#define MDREFR_K2RUN (1 << 18) /* SDCLK2 Run Control/Status */ +#define MDREFR_K1DB2 (1 << 17) /* SDCLK1 Divide by 2 Control/Status */ +#define MDREFR_K1RUN (1 << 16) /* SDCLK1 Run Control/Status */ +#define MDREFR_E1PIN (1 << 15) /* SDCKE1 Level Control/Status */ +#define MDREFR_K0DB2 (1 << 14) /* SDCLK0 Divide by 2 Control/Status */ +#define MDREFR_K0RUN (1 << 13) /* SDCLK0 Run Control/Status */ +#define MDREFR_E0PIN (1 << 12) /* SDCKE0 Level Control/Status */ +#define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) +#define MDREFR_DRI_MASK 0xFFF + DEFINE_SPINLOCK(lock); static struct clk *pxa_clocks[CLK_MAX]; @@ -106,3 +126,122 @@ void __init clk_pxa_dt_common_init(struct device_node *np) { of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data); } + +void pxa2xx_core_turbo_switch(bool on) +{ + unsigned long flags; + unsigned int unused, clkcfg; + + local_irq_save(flags); + + asm("mrc p14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); + clkcfg &= ~CLKCFG_TURBO & ~CLKCFG_HALFTURBO; + if (on) + clkcfg |= CLKCFG_TURBO; + clkcfg |= CLKCFG_FCS; + + asm volatile( + " b 2f\n" + " .align 5\n" + "1: mcr p14, 0, %1, c6, c0, 0\n" + " b 3f\n" + "2: b 1b\n" + "3: nop\n" + : "=&r" (unused) + : "r" (clkcfg) + : ); + + local_irq_restore(flags); +} + +void pxa2xx_cpll_change(struct pxa2xx_freq *freq, + u32 (*mdrefr_dri)(unsigned int), u32 *mdrefr, u32 *cccr) +{ + unsigned int clkcfg = freq->clkcfg; + unsigned int unused, preset_mdrefr, postset_mdrefr; + unsigned long flags; + + local_irq_save(flags); + + /* Calculate the next MDREFR. If we're slowing down the SDRAM clock + * we need to preset the smaller DRI before the change. If we're + * speeding up we need to set the larger DRI value after the change. + */ + preset_mdrefr = postset_mdrefr = readl(mdrefr); + if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(freq->membus_khz)) { + preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK); + preset_mdrefr |= mdrefr_dri(freq->membus_khz); + } + postset_mdrefr = + (postset_mdrefr & ~MDREFR_DRI_MASK) | + mdrefr_dri(freq->membus_khz); + + /* If we're dividing the memory clock by two for the SDRAM clock, this + * must be set prior to the change. Clearing the divide must be done + * after the change. + */ + if (freq->div2) { + preset_mdrefr |= MDREFR_DB2_MASK; + postset_mdrefr |= MDREFR_DB2_MASK; + } else { + postset_mdrefr &= ~MDREFR_DB2_MASK; + } + + /* Set new the CCCR and prepare CLKCFG */ + writel(freq->cccr, cccr); + + asm volatile( + " ldr r4, [%1]\n" + " b 2f\n" + " .align 5\n" + "1: str %3, [%1] /* preset the MDREFR */\n" + " mcr p14, 0, %2, c6, c0, 0 /* set CLKCFG[FCS] */\n" + " str %4, [%1] /* postset the MDREFR */\n" + " b 3f\n" + "2: b 1b\n" + "3: nop\n" + : "=&r" (unused) + : "r" (mdrefr), "r" (clkcfg), "r" (preset_mdrefr), + "r" (postset_mdrefr) + : "r4", "r5"); + + local_irq_restore(flags); +} + +int pxa2xx_determine_rate(struct clk_rate_request *req, + struct pxa2xx_freq *freqs, int nb_freqs) +{ + int i, closest_below = -1, closest_above = -1, ret = 0; + unsigned long rate; + + for (i = 0; i < nb_freqs; i++) { + rate = freqs[i].cpll; + if (rate == req->rate) + break; + if (rate < req->min_rate) + continue; + if (rate > req->max_rate) + continue; + if (rate <= req->rate) + closest_below = i; + if ((rate >= req->rate) && (closest_above == -1)) + closest_above = i; + } + + req->best_parent_hw = NULL; + + if (i < nb_freqs) + ret = 0; + else if (closest_below >= 0) + rate = freqs[closest_below].cpll; + else if (closest_above >= 0) + rate = freqs[closest_above].cpll; + else + ret = -EINVAL; + + pr_debug("%s(rate=%lu) rate=%lu: %d\n", __func__, req->rate, rate, ret); + if (!rate) + req->rate = rate; + + return ret; +} diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h index d1de805df867..f60a7bccae4e 100644 --- a/drivers/clk/pxa/clk-pxa.h +++ b/drivers/clk/pxa/clk-pxa.h @@ -13,6 +13,11 @@ #ifndef _CLK_PXA_ #define _CLK_PXA_ +#define CLKCFG_TURBO 0x1 +#define CLKCFG_FCS 0x2 +#define CLKCFG_HALFTURBO 0x4 +#define CLKCFG_FASTBUS 0x8 + #define PARENTS(name) \ static const char *const name ## _parents[] __initconst #define MUX_RO_RATE_RO_OPS(name, clk_name) \ @@ -35,10 +40,27 @@ NULL, NULL, CLK_GET_RATE_NOCACHE); \ } -#define RATE_RO_OPS(name, clk_name) \ +#define RATE_RO_OPS(name, clk_name) \ + static struct clk_hw name ## _rate_hw; \ + static const struct clk_ops name ## _rate_ops = { \ + .recalc_rate = name ## _get_rate, \ + }; \ + static struct clk * __init clk_register_ ## name(void) \ + { \ + return clk_register_composite(NULL, clk_name, \ + name ## _parents, \ + ARRAY_SIZE(name ## _parents), \ + NULL, NULL, \ + &name ## _rate_hw, &name ## _rate_ops, \ + NULL, NULL, CLK_GET_RATE_NOCACHE); \ + } + +#define RATE_OPS(name, clk_name) \ static struct clk_hw name ## _rate_hw; \ static struct clk_ops name ## _rate_ops = { \ .recalc_rate = name ## _get_rate, \ + .set_rate = name ## _set_rate, \ + .determine_rate = name ## _determine_rate, \ }; \ static struct clk * __init clk_register_ ## name(void) \ { \ @@ -50,6 +72,24 @@ NULL, NULL, CLK_GET_RATE_NOCACHE); \ } +#define MUX_OPS(name, clk_name, flags) \ + static struct clk_hw name ## _mux_hw; \ + static const struct clk_ops name ## _mux_ops = { \ + .get_parent = name ## _get_parent, \ + .set_parent = name ## _set_parent, \ + .determine_rate = name ## _determine_rate, \ + }; \ + static struct clk * __init clk_register_ ## name(void) \ + { \ + return clk_register_composite(NULL, clk_name, \ + name ## _parents, \ + ARRAY_SIZE(name ## _parents), \ + &name ## _mux_hw, &name ## _mux_ops, \ + NULL, NULL, \ + NULL, NULL, \ + CLK_GET_RATE_NOCACHE | flags); \ + } + /* * CKEN clock type * This clock takes it source from 2 possible parents : @@ -95,6 +135,14 @@ struct desc_clk_cken { PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1, \ NULL, cken_reg, cken_bit, flag) +struct pxa2xx_freq { + unsigned long cpll; + unsigned int membus_khz; + unsigned int cccr; + unsigned int div2; + unsigned int clkcfg; +}; + static int dummy_clk_set_parent(struct clk_hw *hw, u8 index) { return 0; @@ -105,4 +153,11 @@ extern void clkdev_pxa_register(int ckid, const char *con_id, extern int clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks); void clk_pxa_dt_common_init(struct device_node *np); +void pxa2xx_core_turbo_switch(bool on); +void pxa2xx_cpll_change(struct pxa2xx_freq *freq, + u32 (*mdrefr_dri)(unsigned int), u32 *mdrefr, + u32 *cccr); +int pxa2xx_determine_rate(struct clk_rate_request *req, + struct pxa2xx_freq *freqs, int nb_freqs); + #endif diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c index 6a3009eec830..c53993b6bf87 100644 --- a/drivers/clk/pxa/clk-pxa25x.c +++ b/drivers/clk/pxa/clk-pxa25x.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "clk-pxa.h" @@ -30,6 +31,17 @@ enum { PXA_CORE_TURBO, }; +#define PXA25x_CLKCFG(T) \ + (CLKCFG_FCS | \ + ((T) ? CLKCFG_TURBO : 0)) +#define PXA25x_CCCR(N2, M, L) (N2 << 7 | M << 5 | L) + +#define MDCNFG_DRAC2(mdcnfg) (((mdcnfg) >> 21) & 0x3) +#define MDCNFG_DRAC0(mdcnfg) (((mdcnfg) >> 5) & 0x3) + +/* Define the refresh period in mSec for the SDRAM and the number of rows */ +#define SDRAM_TREF 64 /* standard 64ms SDRAM */ + /* * Various clock factors driven by the CCCR register. */ @@ -48,6 +60,34 @@ static const char * const get_freq_khz[] = { "core", "run", "cpll", "memory" }; +static int get_sdram_rows(void) +{ + static int sdram_rows; + unsigned int drac2 = 0, drac0 = 0; + u32 mdcnfg; + + if (sdram_rows) + return sdram_rows; + + mdcnfg = readl_relaxed(MDCNFG); + + if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3)) + drac2 = MDCNFG_DRAC2(mdcnfg); + + if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1)) + drac0 = MDCNFG_DRAC0(mdcnfg); + + sdram_rows = 1 << (11 + max(drac0, drac2)); + return sdram_rows; +} + +static u32 mdrefr_dri(unsigned int freq_khz) +{ + u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows(); + + return interval / 32; +} + /* * Get the clock frequency as reflected by CCCR and the turbo flag. * We assume these values have been applied via a fcs. @@ -139,6 +179,21 @@ static struct desc_clk_cken pxa25x_clocks[] __initdata = { clk_pxa25x_memory_parents, 0), }; +/* + * In this table, PXA25x_CCCR(N2, M, L) has the following meaning, where : + * - freq_cpll = n * m * L * 3.6864 MHz + * - n = N2 / 2 + * - m = 2^(M - 1), where 1 <= M <= 3 + * - l = L_clk_mult[L], ie. { 0, 27, 32, 36, 40, 45, 0, }[L] + */ +static struct pxa2xx_freq pxa25x_freqs[] = { + /* CPU MEMBUS CCCR DIV2 CCLKCFG */ + { 99532800, 99500, PXA25x_CCCR(2, 1, 1), 1, PXA25x_CLKCFG(1)}, + {199065600, 99500, PXA25x_CCCR(4, 1, 1), 0, PXA25x_CLKCFG(1)}, + {298598400, 99500, PXA25x_CCCR(3, 2, 1), 0, PXA25x_CLKCFG(1)}, + {398131200, 99500, PXA25x_CCCR(4, 2, 1), 0, PXA25x_CLKCFG(1)}, +}; + static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw) { unsigned long clkcfg; @@ -151,13 +206,24 @@ static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw) return PXA_CORE_RUN; } -static unsigned long clk_pxa25x_core_get_rate(struct clk_hw *hw, - unsigned long parent_rate) +static int clk_pxa25x_core_set_parent(struct clk_hw *hw, u8 index) { - return parent_rate; + if (index > PXA_CORE_TURBO) + return -EINVAL; + + pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO); + + return 0; } + +static int clk_pxa25x_core_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + return __clk_mux_determine_rate(hw, req); +} + PARENTS(clk_pxa25x_core) = { "run", "cpll" }; -MUX_RO_RATE_RO_OPS(clk_pxa25x_core, "core"); +MUX_OPS(clk_pxa25x_core, "core", CLK_SET_RATE_PARENT); static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -184,8 +250,33 @@ static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw, return m * l * n2 * parent_rate / 2; } + +static int clk_pxa25x_cpll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + return pxa2xx_determine_rate(req, pxa25x_freqs, + ARRAY_SIZE(pxa25x_freqs)); +} + +static int clk_pxa25x_cpll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + int i; + + pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate); + for (i = 0; i < ARRAY_SIZE(pxa25x_freqs); i++) + if (pxa25x_freqs[i].cpll == rate) + break; + + if (i >= ARRAY_SIZE(pxa25x_freqs)) + return -EINVAL; + + pxa2xx_cpll_change(&pxa25x_freqs[i], mdrefr_dri, MDREFR, CCCR); + + return 0; +} PARENTS(clk_pxa25x_cpll) = { "osc_3_6864mhz" }; -RATE_RO_OPS(clk_pxa25x_cpll, "cpll"); +RATE_OPS(clk_pxa25x_cpll, "cpll"); static void __init pxa25x_register_core(void) { diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index 9fb40e884999..25a30194d27a 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -17,6 +17,8 @@ #include #include +#include + #include #include "clk-pxa.h" @@ -45,11 +47,52 @@ enum { PXA_MEM_RUN, }; +#define PXA27x_CLKCFG(B, HT, T) \ + (CLKCFG_FCS | \ + ((B) ? CLKCFG_FASTBUS : 0) | \ + ((HT) ? CLKCFG_HALFTURBO : 0) | \ + ((T) ? CLKCFG_TURBO : 0)) +#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L) + +#define MDCNFG_DRAC2(mdcnfg) (((mdcnfg) >> 21) & 0x3) +#define MDCNFG_DRAC0(mdcnfg) (((mdcnfg) >> 5) & 0x3) + +/* Define the refresh period in mSec for the SDRAM and the number of rows */ +#define SDRAM_TREF 64 /* standard 64ms SDRAM */ + static const char * const get_freq_khz[] = { "core", "run", "cpll", "memory", "system_bus" }; +static int get_sdram_rows(void) +{ + static int sdram_rows; + unsigned int drac2 = 0, drac0 = 0; + u32 mdcnfg; + + if (sdram_rows) + return sdram_rows; + + mdcnfg = readl_relaxed(MDCNFG); + + if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3)) + drac2 = MDCNFG_DRAC2(mdcnfg); + + if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1)) + drac0 = MDCNFG_DRAC0(mdcnfg); + + sdram_rows = 1 << (11 + max(drac0, drac2)); + return sdram_rows; +} + +static u32 mdrefr_dri(unsigned int freq_khz) +{ + u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows(); + + return (interval - 31) / 32; +} + /* * Get the clock frequency as reflected by CCSR and the turbo flag. * We assume these values have been applied via a fcs. @@ -145,6 +188,42 @@ static struct desc_clk_cken pxa27x_clocks[] __initdata = { }; +/* + * PXA270 definitions + * + * For the PXA27x: + * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG. + * + * A = 0 => memory controller clock from table 3-7, + * A = 1 => memory controller clock = system bus clock + * Run mode frequency = 13 MHz * L + * Turbo mode frequency = 13 MHz * L * N + * System bus frequency = 13 MHz * L / (B + 1) + * + * In CCCR: + * A = 1 + * L = 16 oscillator to run mode ratio + * 2N = 6 2 * (turbo mode to run mode ratio) + * + * In CCLKCFG: + * B = 1 Fast bus mode + * HT = 0 Half-Turbo mode + * T = 1 Turbo mode + * + * For now, just support some of the combinations in table 3-7 of + * PXA27x Processor Family Developer's Manual to simplify frequency + * change sequences. + */ +static struct pxa2xx_freq pxa27x_freqs[] = { + {104000000, 104000, PXA27x_CCCR(1, 8, 2), 0, PXA27x_CLKCFG(1, 0, 1) }, + {156000000, 104000, PXA27x_CCCR(1, 8, 3), 0, PXA27x_CLKCFG(1, 0, 1) }, + {208000000, 208000, PXA27x_CCCR(0, 16, 2), 1, PXA27x_CLKCFG(0, 0, 1) }, + {312000000, 208000, PXA27x_CCCR(1, 16, 3), 1, PXA27x_CLKCFG(1, 0, 1) }, + {416000000, 208000, PXA27x_CCCR(1, 16, 4), 1, PXA27x_CLKCFG(1, 0, 1) }, + {520000000, 208000, PXA27x_CCCR(1, 16, 5), 1, PXA27x_CLKCFG(1, 0, 1) }, + {624000000, 208000, PXA27x_CCCR(1, 16, 6), 1, PXA27x_CLKCFG(1, 0, 1) }, +}; + static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -164,8 +243,33 @@ static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw, return N; } + +static int clk_pxa27x_cpll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + return pxa2xx_determine_rate(req, pxa27x_freqs, + ARRAY_SIZE(pxa27x_freqs)); +} + +static int clk_pxa27x_cpll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + int i; + + pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate); + for (i = 0; i < ARRAY_SIZE(pxa27x_freqs); i++) + if (pxa27x_freqs[i].cpll == rate) + break; + + if (i >= ARRAY_SIZE(pxa27x_freqs)) + return -EINVAL; + + pxa2xx_cpll_change(&pxa27x_freqs[i], mdrefr_dri, MDREFR, CCCR); + return 0; +} + PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" }; -RATE_RO_OPS(clk_pxa27x_cpll, "cpll"); +RATE_OPS(clk_pxa27x_cpll, "cpll"); static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -217,25 +321,6 @@ static void __init pxa27x_register_plls(void) clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1); } -static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - unsigned long clkcfg; - unsigned int ht, osc_forced; - unsigned long ccsr = readl(CCSR); - - osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); - asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); - ht = clkcfg & (1 << 2); - - if (osc_forced) - return parent_rate; - if (ht) - return parent_rate / 2; - else - return parent_rate; -} - static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw) { unsigned long clkcfg; @@ -254,8 +339,25 @@ static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw) return PXA_CORE_TURBO; return PXA_CORE_RUN; } + +static int clk_pxa27x_core_set_parent(struct clk_hw *hw, u8 index) +{ + if (index > PXA_CORE_TURBO) + return -EINVAL; + + pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO); + + return 0; +} + +static int clk_pxa27x_core_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + return __clk_mux_determine_rate(hw, req); +} + PARENTS(clk_pxa27x_core) = { "osc_13mhz", "run", "cpll" }; -MUX_RO_RATE_RO_OPS(clk_pxa27x_core, "core"); +MUX_OPS(clk_pxa27x_core, "core", CLK_SET_RATE_PARENT); static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw, unsigned long parent_rate) -- cgit v1.2.3 From 7acf751ea5d0462657c4f6437c2952cc40fb41d9 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:13 -0400 Subject: clk: mvebu: make cp110-system-controller explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/clk/mvebu/Kconfig:config ARMADA_CP110_SYSCON drivers/clk/mvebu/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Michael Turquette Cc: Stephen Boyd Cc: Thomas Petazzoni Cc: linux-clk@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Stephen Boyd --- drivers/clk/mvebu/cp110-system-controller.c | 35 +++-------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c index 0116808bc15a..32e5b43c086f 100644 --- a/drivers/clk/mvebu/cp110-system-controller.c +++ b/drivers/clk/mvebu/cp110-system-controller.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include #include @@ -368,46 +368,17 @@ fail0: return ret; } -static int cp110_syscon_clk_remove(struct platform_device *pdev) -{ - struct clk_hw **cp110_clks = platform_get_drvdata(pdev); - int i; - - of_clk_del_provider(pdev->dev.of_node); - - for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { - struct clk_hw *hw = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; - - if (hw) - cp110_unregister_gate(hw); - } - - clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); - clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); - clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); - clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); - clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); - - return 0; -} - static const struct of_device_id cp110_syscon_of_match[] = { { .compatible = "marvell,cp110-system-controller0", }, { } }; -MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match); static struct platform_driver cp110_syscon_driver = { .probe = cp110_syscon_clk_probe, - .remove = cp110_syscon_clk_remove, .driver = { .name = "marvell-cp110-system-controller0", .of_match_table = cp110_syscon_of_match, + .suppress_bind_attrs = true, }, }; - -module_platform_driver(cp110_syscon_driver); - -MODULE_DESCRIPTION("Marvell CP110 System Controller 0 driver"); -MODULE_AUTHOR("Thomas Petazzoni "); -MODULE_LICENSE("GPL"); +builtin_platform_driver(cp110_syscon_driver); -- cgit v1.2.3 From 188e8719c50d7b092868729f09c2541e677f49df Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:14 -0400 Subject: clk: mvebu: make ap806-system-controller explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/clk/mvebu/Kconfig:config ARMADA_AP806_SYSCON drivers/clk/mvebu/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Michael Turquette Cc: Stephen Boyd Cc: Thomas Petazzoni Cc: linux-clk@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Stephen Boyd --- drivers/clk/mvebu/ap806-system-controller.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c index 02023baf86c9..8181b919f062 100644 --- a/drivers/clk/mvebu/ap806-system-controller.c +++ b/drivers/clk/mvebu/ap806-system-controller.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -135,34 +135,17 @@ fail0: return ret; } -static int ap806_syscon_clk_remove(struct platform_device *pdev) -{ - of_clk_del_provider(pdev->dev.of_node); - clk_unregister_fixed_factor(ap806_clks[3]); - clk_unregister_fixed_rate(ap806_clks[2]); - clk_unregister_fixed_rate(ap806_clks[1]); - clk_unregister_fixed_rate(ap806_clks[0]); - - return 0; -} - static const struct of_device_id ap806_syscon_of_match[] = { { .compatible = "marvell,ap806-system-controller", }, { } }; -MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match); static struct platform_driver ap806_syscon_driver = { .probe = ap806_syscon_clk_probe, - .remove = ap806_syscon_clk_remove, .driver = { .name = "marvell-ap806-system-controller", .of_match_table = ap806_syscon_of_match, + .suppress_bind_attrs = true, }, }; - -module_platform_driver(ap806_syscon_driver); - -MODULE_DESCRIPTION("Marvell AP806 System Controller driver"); -MODULE_AUTHOR("Thomas Petazzoni "); -MODULE_LICENSE("GPL"); +builtin_platform_driver(ap806_syscon_driver); -- cgit v1.2.3 From 33996b029de836c5e70271fe73d075ed6ff829d0 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:19 -0400 Subject: clk: tegra: make clk-tegra124-dfll-fcpu explicitly non-modular The Kconfig currently controlling compilation of this code is: arch/arm/mach-tegra/Kconfig:config ARCH_TEGRA_124_SOC arch/arm/mach-tegra/Kconfig: bool "Enable support for Tegra124 family" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tags etc. since all that information is already contained at the top of the file in the comments. Cc: Peter De Schrijver Cc: Prashant Gaikwad Cc: Michael Turquette Cc: Stephen Boyd Cc: Stephen Warren Cc: Thierry Reding Cc: Alexandre Courbot Cc: Aleksandr Frid Cc: Paul Walmsley Cc: linux-clk@vger.kernel.org Cc: linux-tegra@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Stephen Boyd --- drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index c205809ba580..4301569d072a 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -148,7 +148,6 @@ static const struct of_device_id tegra124_dfll_fcpu_of_match[] = { { .compatible = "nvidia,tegra124-dfll", }, { }, }; -MODULE_DEVICE_TABLE(of, tegra124_dfll_fcpu_of_match); static const struct dev_pm_ops tegra124_dfll_pm_ops = { SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend, @@ -169,15 +168,4 @@ static int __init tegra124_dfll_fcpu_init(void) { return platform_driver_register(&tegra124_dfll_fcpu_driver); } -module_init(tegra124_dfll_fcpu_init); - -static void __exit tegra124_dfll_fcpu_exit(void) -{ - platform_driver_unregister(&tegra124_dfll_fcpu_driver); -} -module_exit(tegra124_dfll_fcpu_exit); - -MODULE_DESCRIPTION("Tegra124 DFLL clock source driver"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Aleksandr Frid "); -MODULE_AUTHOR("Paul Walmsley "); +device_initcall(tegra124_dfll_fcpu_init); -- cgit v1.2.3 From 172ff5a22d4cdc9394bd9e4c64045bfc9415a67c Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:20 -0400 Subject: clk: ti: make clk-dra7-atl explicitly non-modular The Kconfig currently controlling compilation of this code is: arch/arm/mach-omap2/Kconfig:config SOC_DRA7XX arch/arm/mach-omap2/Kconfig: bool "TI DRA7XX" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tags etc. since all that information is already contained at the top of the file in the comments. Cc: Tero Kristo Cc: Michael Turquette Cc: Peter Ujfalusi Cc: Stephen Boyd Cc: linux-omap@vger.kernel.org Cc: linux-clk@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Stephen Boyd --- drivers/clk/ti/clk-dra7-atl.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index c77333230bdf..45d05339d583 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c @@ -15,7 +15,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -295,31 +295,17 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) return ret; } -static int of_dra7_atl_clk_remove(struct platform_device *pdev) -{ - pm_runtime_disable(&pdev->dev); - - return 0; -} - static const struct of_device_id of_dra7_atl_clk_match_tbl[] = { { .compatible = "ti,dra7-atl", }, {}, }; -MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl); static struct platform_driver dra7_atl_clk_driver = { .driver = { .name = "dra7-atl", + .suppress_bind_attrs = true, .of_match_table = of_dra7_atl_clk_match_tbl, }, .probe = of_dra7_atl_clk_probe, - .remove = of_dra7_atl_clk_remove, }; - -module_platform_driver(dra7_atl_clk_driver); - -MODULE_DESCRIPTION("Clock driver for DRA7 Audio Tracking Logic"); -MODULE_ALIAS("platform:dra7-atl-clock"); -MODULE_AUTHOR("Peter Ujfalusi "); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(dra7_atl_clk_driver); -- cgit v1.2.3 From 60d9531a61efc8e6b69d04089d50a0a929090fe1 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 4 Nov 2016 21:00:40 +0100 Subject: spi: fsl-espi: remove unneeded call to fsl_espi_setup_transfer Resetting the chip to a default transfer mode after each transfer doesn't provide any benefit. Therefore remove this call. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 8b3a28739d9a..1029bd2ff5f1 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -331,8 +331,6 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) if (trans->delay_usecs) udelay(trans->delay_usecs); - fsl_espi_setup_transfer(spi, NULL); - if (!ret) fsl_espi_copy_from_buf(m, mspi); -- cgit v1.2.3 From 8f3086d2a9c1104f42d2d0247ef52b01c6d898d8 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 4 Nov 2016 21:01:12 +0100 Subject: spi: fsl-espi: don't write ESPI_SPMODE register if the mode doesn't change There's no need to bother the chip if the mode doesn't change. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 1029bd2ff5f1..edb524f831a3 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -249,6 +249,7 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, int bits_per_word = t ? t->bits_per_word : spi->bits_per_word; u32 pm, hz = t ? t->speed_hz : spi->max_speed_hz; struct spi_mpc8xxx_cs *cs = spi->controller_state; + u32 hw_mode_old = cs->hw_mode; /* mask out bits we are going to set */ cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF)); @@ -271,8 +272,10 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, cs->hw_mode |= CSMODE_PM(pm); - fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODEx(spi->chip_select), - cs->hw_mode); + /* don't write the mode register if the mode doesn't change */ + if (cs->hw_mode != hw_mode_old) + fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODEx(spi->chip_select), + cs->hw_mode); } static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) -- cgit v1.2.3 From 42124bc598f64f84b3335d5a058304207695b84f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 3 Nov 2016 09:35:47 -0700 Subject: pinctrl: Introduce generic #pinctrl-cells and pinctrl_parse_index_with_args Introduce #pinctrl-cells helper binding and generic helper functions pinctrl_count_index_with_args() and pinctrl_parse_index_with_args(). Acked-by: Rob Herring Signed-off-by: Tony Lindgren [Forward-declare of_phandle_args] Signed-off-by: Linus Walleij --- .../bindings/pinctrl/pinctrl-bindings.txt | 44 ++++++- drivers/pinctrl/devicetree.c | 144 +++++++++++++++++++++ drivers/pinctrl/devicetree.h | 23 ++++ 3 files changed, 210 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt index b73c96d24f59..bf3f7b014724 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt @@ -97,6 +97,11 @@ For example: }; == Pin controller devices == +Required properties: See the pin controller driver specific documentation + +Optional properties: +#pinctrl-cells: Number of pin control cells in addition to the index within the + pin controller device instance Pin controller devices should contain the pin configuration nodes that client devices reference. @@ -119,7 +124,8 @@ For example: The contents of each of those pin configuration child nodes is defined entirely by the binding for the individual pin controller device. There -exists no common standard for this content. +exists no common standard for this content. The pinctrl framework only +provides generic helper bindings that the pin controller driver can use. The pin configuration nodes need not be direct children of the pin controller device; they may be grandchildren, for example. Whether this is legal, and @@ -156,6 +162,42 @@ state_2_node_a { pins = "mfio29", "mfio30"; }; +Optionally an altenative binding can be used if more suitable depending on the +pin controller hardware. For hardaware where there is a large number of identical +pin controller instances, naming each pin and function can easily become +unmaintainable. This is especially the case if the same controller is used for +different pins and functions depending on the SoC revision and packaging. + +For cases like this, the pin controller driver may use pinctrl-pin-array helper +binding with a hardware based index and a number of pin configuration values: + +pincontroller { + ... /* Standard DT properties for the device itself elided */ + #pinctrl-cells = <2>; + + state_0_node_a { + pinctrl-pin-array = < + 0 A_DELAY_PS(0) G_DELAY_PS(120) + 4 A_DELAY_PS(0) G_DELAY_PS(360) + ... + >; + }; + ... +}; + +Above #pinctrl-cells specifies the number of value cells in addition to the +index of the registers. This is similar to the interrupts-extended binding with +one exception. There is no need to specify the phandle for each entry as that +is already known as the defined pins are always children of the pin controller +node. Further having the phandle pointing to another pin controller would not +currently work as the pinctrl framework uses named modes to group pins for each +pin control device. + +The index for pinctrl-pin-array must relate to the hardware for the pinctrl +registers, and must not be a virtual index of pin instances. The reason for +this is to avoid mapping of the index in the dts files and the pin controller +driver as it can change. + == Generic pin configuration node content == Many data items that are represented in a pin configuration node are common diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index 54dad89fc9bf..260908480075 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -253,3 +253,147 @@ err: pinctrl_dt_free_maps(p); return ret; } + +/* + * For pinctrl binding, typically #pinctrl-cells is for the pin controller + * device, so either parent or grandparent. See pinctrl-bindings.txt. + */ +static int pinctrl_find_cells_size(const struct device_node *np) +{ + const char *cells_name = "#pinctrl-cells"; + int cells_size, error; + + error = of_property_read_u32(np->parent, cells_name, &cells_size); + if (error) { + error = of_property_read_u32(np->parent->parent, + cells_name, &cells_size); + if (error) + return -ENOENT; + } + + return cells_size; +} + +/** + * pinctrl_get_list_and_count - Gets the list and it's cell size and number + * @np: pointer to device node with the property + * @list_name: property that contains the list + * @list: pointer for the list found + * @cells_size: pointer for the cell size found + * @nr_elements: pointer for the number of elements found + * + * Typically np is a single pinctrl entry containing the list. + */ +static int pinctrl_get_list_and_count(const struct device_node *np, + const char *list_name, + const __be32 **list, + int *cells_size, + int *nr_elements) +{ + int size; + + *cells_size = 0; + *nr_elements = 0; + + *list = of_get_property(np, list_name, &size); + if (!*list) + return -ENOENT; + + *cells_size = pinctrl_find_cells_size(np); + if (*cells_size < 0) + return -ENOENT; + + /* First element is always the index within the pinctrl device */ + *nr_elements = (size / sizeof(**list)) / (*cells_size + 1); + + return 0; +} + +/** + * pinctrl_count_index_with_args - Count number of elements in a pinctrl entry + * @np: pointer to device node with the property + * @list_name: property that contains the list + * + * Counts the number of elements in a pinctrl array consisting of an index + * within the controller and a number of u32 entries specified for each + * entry. Note that device_node is always for the parent pin controller device. + */ +int pinctrl_count_index_with_args(const struct device_node *np, + const char *list_name) +{ + const __be32 *list; + int size, nr_cells, error; + + error = pinctrl_get_list_and_count(np, list_name, &list, + &nr_cells, &size); + if (error) + return error; + + return size; +} +EXPORT_SYMBOL_GPL(pinctrl_count_index_with_args); + +/** + * pinctrl_copy_args - Populates of_phandle_args based on index + * @np: pointer to device node with the property + * @list: pointer to a list with the elements + * @index: entry within the list of elements + * @nr_cells: number of cells in the list + * @nr_elem: number of elements for each entry in the list + * @out_args: returned values + * + * Populates the of_phandle_args based on the index in the list. + */ +static int pinctrl_copy_args(const struct device_node *np, + const __be32 *list, + int index, int nr_cells, int nr_elem, + struct of_phandle_args *out_args) +{ + int i; + + memset(out_args, 0, sizeof(*out_args)); + out_args->np = (struct device_node *)np; + out_args->args_count = nr_cells + 1; + + if (index >= nr_elem) + return -EINVAL; + + list += index * (nr_cells + 1); + + for (i = 0; i < nr_cells + 1; i++) + out_args->args[i] = be32_to_cpup(list++); + + return 0; +} + +/** + * pinctrl_parse_index_with_args - Find a node pointed by index in a list + * @np: pointer to device node with the property + * @list_name: property that contains the list + * @index: index within the list + * @out_arts: entries in the list pointed by index + * + * Finds the selected element in a pinctrl array consisting of an index + * within the controller and a number of u32 entries specified for each + * entry. Note that device_node is always for the parent pin controller device. + */ +int pinctrl_parse_index_with_args(const struct device_node *np, + const char *list_name, int index, + struct of_phandle_args *out_args) +{ + const __be32 *list; + int nr_elem, nr_cells, error; + + error = pinctrl_get_list_and_count(np, list_name, &list, + &nr_cells, &nr_elem); + if (error || !nr_cells) + return error; + + error = pinctrl_copy_args(np, list, index, nr_cells, nr_elem, + out_args); + if (error) + return error; + + return 0; +} +EXPORT_SYMBOL_GPL(pinctrl_parse_index_with_args); diff --git a/drivers/pinctrl/devicetree.h b/drivers/pinctrl/devicetree.h index 760bc4960f58..c2d1a5505850 100644 --- a/drivers/pinctrl/devicetree.h +++ b/drivers/pinctrl/devicetree.h @@ -16,11 +16,20 @@ * along with this program. If not, see . */ +struct of_phandle_args; + #ifdef CONFIG_OF void pinctrl_dt_free_maps(struct pinctrl *p); int pinctrl_dt_to_map(struct pinctrl *p); +int pinctrl_count_index_with_args(const struct device_node *np, + const char *list_name); + +int pinctrl_parse_index_with_args(const struct device_node *np, + const char *list_name, int index, + struct of_phandle_args *out_args); + #else static inline int pinctrl_dt_to_map(struct pinctrl *p) @@ -32,4 +41,18 @@ static inline void pinctrl_dt_free_maps(struct pinctrl *p) { } +static inline int pinctrl_count_index_with_args(const struct device_node *np, + const char *list_name) +{ + return -ENODEV; +} + +static inline int +pinctrl_parse_index_with_args(const struct device_node *np, + const char *list_name, int index, + struct of_phandle_args *out_args) +{ + return -ENODEV; +} + #endif -- cgit v1.2.3 From 4622215fb1dda40bcebab31553765ee9cacb476d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 3 Nov 2016 09:35:48 -0700 Subject: pinctrl: single: Use generic parser and #pinctrl-cells for pinctrl-single,pins We can now use generic parser. To support the legacy binding without #pinctrl-cells, add pcs_quirk_missing_pinctrl_cells() and warn about missing #pinctrl-cells. Let's also update the documentation for struct pcs_soc_data while at it as that seems to be out of date. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 111 ++++++++++++++++++++++++++++++++------- 1 file changed, 93 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 7cc9b7dc8656..07c427367237 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -31,10 +31,10 @@ #include #include "core.h" +#include "devicetree.h" #include "pinconf.h" #define DRIVER_NAME "pinctrl-single" -#define PCS_MUX_PINS_NAME "pinctrl-single,pins" #define PCS_MUX_BITS_NAME "pinctrl-single,bits" #define PCS_OFF_DISABLED ~0U @@ -162,8 +162,11 @@ struct pcs_soc_data { * @base: virtual address of the controller * @size: size of the ioremapped area * @dev: device entry + * @np: device tree node * @pctl: pin controller device * @flags: mask of PCS_FEAT_xxx values + * @missing_nr_pinctrl_cells: for legacy binding, may go away + * @socdata: soc specific data * @lock: spinlock for register access * @mutex: mutex protecting the lists * @width: bits per mux register @@ -171,7 +174,8 @@ struct pcs_soc_data { * @fshift: function register shift * @foff: value to turn mux off * @fmax: max number of functions in fmask - * @bits_per_pin:number of bits per pin + * @bits_per_mux: number of bits per mux + * @bits_per_pin: number of bits per pin * @pins: physical pins on the SoC * @pgtree: pingroup index radix tree * @ftree: function index radix tree @@ -192,11 +196,13 @@ struct pcs_device { void __iomem *base; unsigned size; struct device *dev; + struct device_node *np; struct pinctrl_dev *pctl; unsigned flags; #define PCS_QUIRK_SHARED_IRQ (1 << 2) #define PCS_FEAT_IRQ (1 << 1) #define PCS_FEAT_PINCONF (1 << 0) + struct property *missing_nr_pinctrl_cells; struct pcs_soc_data socdata; raw_spinlock_t lock; struct mutex mutex; @@ -1122,20 +1128,14 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, unsigned *num_maps, const char **pgnames) { + const char *name = "pinctrl-single,pins"; struct pcs_func_vals *vals; - const __be32 *mux; - int size, rows, *pins, index = 0, found = 0, res = -ENOMEM; + int rows, *pins, found = 0, res = -ENOMEM, i; struct pcs_function *function; - mux = of_get_property(np, PCS_MUX_PINS_NAME, &size); - if ((!mux) || (size < sizeof(*mux) * 2)) { - dev_err(pcs->dev, "bad data for mux %s\n", - np->name); - return -EINVAL; - } - - size /= sizeof(*mux); /* Number of elements in array */ - rows = size / 2; + rows = pinctrl_count_index_with_args(np, name); + if (rows == -EINVAL) + return rows; vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); if (!vals) @@ -1145,14 +1145,28 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, if (!pins) goto free_vals; - while (index < size) { - unsigned offset, val; + for (i = 0; i < rows; i++) { + struct of_phandle_args pinctrl_spec; + unsigned int offset; int pin; - offset = be32_to_cpup(mux + index++); - val = be32_to_cpup(mux + index++); + res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec); + if (res) + return res; + + if (pinctrl_spec.args_count < 2) { + dev_err(pcs->dev, "invalid args_count for spec: %i\n", + pinctrl_spec.args_count); + break; + } + + /* Index plus one value cell */ + offset = pinctrl_spec.args[0]; vals[found].reg = pcs->base + offset; - vals[found].val = val; + vals[found].val = pinctrl_spec.args[1]; + + dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x\n", + pinctrl_spec.np->name, offset, pinctrl_spec.args[1]); pin = pcs_get_pin_by_offset(pcs, offset); if (pin < 0) { @@ -1470,6 +1484,10 @@ static void pcs_free_resources(struct pcs_device *pcs) pinctrl_unregister(pcs->pctl); pcs_free_funcs(pcs); pcs_free_pingroups(pcs); +#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE) + if (pcs->missing_nr_pinctrl_cells) + of_remove_property(pcs->np, pcs->missing_nr_pinctrl_cells); +#endif } static const struct of_device_id pcs_of_match[]; @@ -1787,6 +1805,55 @@ static int pinctrl_single_resume(struct platform_device *pdev) } #endif +/** + * pcs_quirk_missing_pinctrl_cells - handle legacy binding + * @pcs: pinctrl driver instance + * @np: device tree node + * @cells: number of cells + * + * Handle legacy binding with no #pinctrl-cells. This should be + * always two pinctrl-single,bit-per-mux and one for others. + * At some point we may want to consider removing this. + */ +static int pcs_quirk_missing_pinctrl_cells(struct pcs_device *pcs, + struct device_node *np, + int cells) +{ + struct property *p; + const char *name = "#pinctrl-cells"; + int error; + u32 val; + + error = of_property_read_u32(np, name, &val); + if (!error) + return 0; + + dev_warn(pcs->dev, "please update dts to use %s = <%i>\n", + name, cells); + + p = devm_kzalloc(pcs->dev, sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + p->length = sizeof(__be32); + p->value = devm_kzalloc(pcs->dev, sizeof(__be32), GFP_KERNEL); + if (!p->value) + return -ENOMEM; + *(__be32 *)p->value = cpu_to_be32(cells); + + p->name = devm_kstrdup(pcs->dev, name, GFP_KERNEL); + if (!p->name) + return -ENOMEM; + + pcs->missing_nr_pinctrl_cells = p; + +#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE) + error = of_add_property(np, pcs->missing_nr_pinctrl_cells); +#endif + + return error; +} + static int pcs_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1807,6 +1874,7 @@ static int pcs_probe(struct platform_device *pdev) return -ENOMEM; } pcs->dev = &pdev->dev; + pcs->np = np; raw_spin_lock_init(&pcs->lock); mutex_init(&pcs->mutex); INIT_LIST_HEAD(&pcs->pingroups); @@ -1843,6 +1911,13 @@ static int pcs_probe(struct platform_device *pdev) pcs->bits_per_mux = of_property_read_bool(np, "pinctrl-single,bit-per-mux"); + ret = pcs_quirk_missing_pinctrl_cells(pcs, np, + pcs->bits_per_mux ? 2 : 1); + if (ret) { + dev_err(&pdev->dev, "unable to patch #pinctrl-cells\n"); + + return ret; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { -- cgit v1.2.3 From 22d5127ec916e8eac607eebbbafc026ef59afb36 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 3 Nov 2016 09:35:49 -0700 Subject: pinctrl: single: Use generic parser and #pinctrl-cells for pinctrl-single,bits We can now use generic parser and keep things compatible with the old binding. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 07c427367237..539f31cd8e00 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -35,7 +35,6 @@ #include "pinconf.h" #define DRIVER_NAME "pinctrl-single" -#define PCS_MUX_BITS_NAME "pinctrl-single,bits" #define PCS_OFF_DISABLED ~0U /** @@ -1216,36 +1215,22 @@ free_vals: return res; } -#define PARAMS_FOR_BITS_PER_MUX 3 - static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, struct device_node *np, struct pinctrl_map **map, unsigned *num_maps, const char **pgnames) { + const char *name = "pinctrl-single,pins"; struct pcs_func_vals *vals; - const __be32 *mux; - int size, rows, *pins, index = 0, found = 0, res = -ENOMEM; + int rows, *pins, found = 0, res = -ENOMEM, i; int npins_in_row; struct pcs_function *function; - mux = of_get_property(np, PCS_MUX_BITS_NAME, &size); - - if (!mux) { - dev_err(pcs->dev, "no valid property for %s\n", np->name); - return -EINVAL; - } - - if (size < (sizeof(*mux) * PARAMS_FOR_BITS_PER_MUX)) { - dev_err(pcs->dev, "bad data for %s\n", np->name); - return -EINVAL; - } - - /* Number of elements in array */ - size /= sizeof(*mux); + rows = pinctrl_count_index_with_args(np, name); + if (rows == -EINVAL) + return rows; - rows = size / PARAMS_FOR_BITS_PER_MUX; npins_in_row = pcs->width / pcs->bits_per_pin; vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row, @@ -1258,15 +1243,30 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, if (!pins) goto free_vals; - while (index < size) { + for (i = 0; i < rows; i++) { + struct of_phandle_args pinctrl_spec; unsigned offset, val; unsigned mask, bit_pos, val_pos, mask_pos, submask; unsigned pin_num_from_lsb; int pin; - offset = be32_to_cpup(mux + index++); - val = be32_to_cpup(mux + index++); - mask = be32_to_cpup(mux + index++); + res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec); + if (res) + return res; + + if (pinctrl_spec.args_count < 3) { + dev_err(pcs->dev, "invalid args_count for spec: %i\n", + pinctrl_spec.args_count); + break; + } + + /* Index plus two value cells */ + offset = pinctrl_spec.args[0]; + val = pinctrl_spec.args[1]; + mask = pinctrl_spec.args[2]; + + dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x mask: 0x%x\n", + pinctrl_spec.np->name, offset, val, mask); /* Parse pins in each row from LSB */ while (mask) { -- cgit v1.2.3 From 43bbf94c333ac1b1bee2bf05efb48e9ae8ea3e82 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 31 Oct 2016 14:27:07 -0400 Subject: gpio: htc-egpio: Make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config HTC_EGPIO drivers/gpio/Kconfig: bool "HTC EGPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Kevin O'Connor Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-htc-egpio.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-htc-egpio.c b/drivers/gpio/gpio-htc-egpio.c index 0b4df6051097..5ab895b41819 100644 --- a/drivers/gpio/gpio-htc-egpio.c +++ b/drivers/gpio/gpio-htc-egpio.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include struct egpio_chip { int reg_start; @@ -367,24 +367,6 @@ fail: return ret; } -static int __exit egpio_remove(struct platform_device *pdev) -{ - struct egpio_info *ei = platform_get_drvdata(pdev); - unsigned int irq, irq_end; - - if (ei->chained_irq) { - irq_end = ei->irq_start + ei->nirqs; - for (irq = ei->irq_start; irq < irq_end; irq++) { - irq_set_chip_and_handler(irq, NULL, NULL); - irq_set_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); - } - irq_set_chained_handler(ei->chained_irq, NULL); - device_init_wakeup(&pdev->dev, 0); - } - - return 0; -} - #ifdef CONFIG_PM static int egpio_suspend(struct platform_device *pdev, pm_message_t state) { @@ -416,8 +398,8 @@ static int egpio_resume(struct platform_device *pdev) static struct platform_driver egpio_driver = { .driver = { .name = "htc-egpio", + .suppress_bind_attrs = true, }, - .remove = __exit_p(egpio_remove), .suspend = egpio_suspend, .resume = egpio_resume, }; @@ -426,15 +408,5 @@ static int __init egpio_init(void) { return platform_driver_probe(&egpio_driver, egpio_probe); } - -static void __exit egpio_exit(void) -{ - platform_driver_unregister(&egpio_driver); -} - /* start early for dependencies */ subsys_initcall(egpio_init); -module_exit(egpio_exit) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kevin O'Connor "); -- cgit v1.2.3 From 0f15f500ff2c67cc5fa8fa74b270d7352dff1dba Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 31 Oct 2016 17:32:11 +0100 Subject: pinctrl: meson: Add GXL pinctrl definitions Add support for the Amlogic Meson GXL SoC, this is a partially complete definition only based on the Amlogic Vendor tree. This definition differs a lot from the GXBB and needs a separate entry. Acked-by: Rob Herring Signed-off-by: Neil Armstrong Acked-by: Kevin Hilman Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/meson,pinctrl.txt | 2 + drivers/pinctrl/meson/Makefile | 3 +- drivers/pinctrl/meson/pinctrl-meson-gxl.c | 589 +++++++++++++++++++++ drivers/pinctrl/meson/pinctrl-meson.c | 8 + drivers/pinctrl/meson/pinctrl-meson.h | 2 + include/dt-bindings/gpio/meson-gxl-gpio.h | 131 +++++ 6 files changed, 734 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxl.c create mode 100644 include/dt-bindings/gpio/meson-gxl-gpio.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt index fe7fe0b03cfb..2392557ede27 100644 --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt @@ -7,6 +7,8 @@ Required properties for the root node: "amlogic,meson8b-aobus-pinctrl" "amlogic,meson-gxbb-periphs-pinctrl" "amlogic,meson-gxbb-aobus-pinctrl" + "amlogic,meson-gxl-periphs-pinctrl" + "amlogic,meson-gxl-aobus-pinctrl" - reg: address and size of registers controlling irq functionality === GPIO sub-nodes === diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile index 24434f139947..27c5b5126008 100644 --- a/drivers/pinctrl/meson/Makefile +++ b/drivers/pinctrl/meson/Makefile @@ -1,2 +1,3 @@ -obj-y += pinctrl-meson8.o pinctrl-meson8b.o pinctrl-meson-gxbb.o +obj-y += pinctrl-meson8.o pinctrl-meson8b.o +obj-y += pinctrl-meson-gxbb.o pinctrl-meson-gxl.o obj-y += pinctrl-meson.o diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c new file mode 100644 index 000000000000..25694f7094c7 --- /dev/null +++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c @@ -0,0 +1,589 @@ +/* + * Pin controller and GPIO driver for Amlogic Meson GXL. + * + * Copyright (C) 2016 Endless Mobile, Inc. + * Author: Carlo Caione + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "pinctrl-meson.h" + +#define EE_OFF 10 + +static const struct pinctrl_pin_desc meson_gxl_periphs_pins[] = { + MESON_PIN(GPIOZ_0, EE_OFF), + MESON_PIN(GPIOZ_1, EE_OFF), + MESON_PIN(GPIOZ_2, EE_OFF), + MESON_PIN(GPIOZ_3, EE_OFF), + MESON_PIN(GPIOZ_4, EE_OFF), + MESON_PIN(GPIOZ_5, EE_OFF), + MESON_PIN(GPIOZ_6, EE_OFF), + MESON_PIN(GPIOZ_7, EE_OFF), + MESON_PIN(GPIOZ_8, EE_OFF), + MESON_PIN(GPIOZ_9, EE_OFF), + MESON_PIN(GPIOZ_10, EE_OFF), + MESON_PIN(GPIOZ_11, EE_OFF), + MESON_PIN(GPIOZ_12, EE_OFF), + MESON_PIN(GPIOZ_13, EE_OFF), + MESON_PIN(GPIOZ_14, EE_OFF), + MESON_PIN(GPIOZ_15, EE_OFF), + + MESON_PIN(GPIOH_0, EE_OFF), + MESON_PIN(GPIOH_1, EE_OFF), + MESON_PIN(GPIOH_2, EE_OFF), + MESON_PIN(GPIOH_3, EE_OFF), + MESON_PIN(GPIOH_4, EE_OFF), + MESON_PIN(GPIOH_5, EE_OFF), + MESON_PIN(GPIOH_6, EE_OFF), + MESON_PIN(GPIOH_7, EE_OFF), + MESON_PIN(GPIOH_8, EE_OFF), + MESON_PIN(GPIOH_9, EE_OFF), + + MESON_PIN(BOOT_0, EE_OFF), + MESON_PIN(BOOT_1, EE_OFF), + MESON_PIN(BOOT_2, EE_OFF), + MESON_PIN(BOOT_3, EE_OFF), + MESON_PIN(BOOT_4, EE_OFF), + MESON_PIN(BOOT_5, EE_OFF), + MESON_PIN(BOOT_6, EE_OFF), + MESON_PIN(BOOT_7, EE_OFF), + MESON_PIN(BOOT_8, EE_OFF), + MESON_PIN(BOOT_9, EE_OFF), + MESON_PIN(BOOT_10, EE_OFF), + MESON_PIN(BOOT_11, EE_OFF), + MESON_PIN(BOOT_12, EE_OFF), + MESON_PIN(BOOT_13, EE_OFF), + MESON_PIN(BOOT_14, EE_OFF), + MESON_PIN(BOOT_15, EE_OFF), + + MESON_PIN(CARD_0, EE_OFF), + MESON_PIN(CARD_1, EE_OFF), + MESON_PIN(CARD_2, EE_OFF), + MESON_PIN(CARD_3, EE_OFF), + MESON_PIN(CARD_4, EE_OFF), + MESON_PIN(CARD_5, EE_OFF), + MESON_PIN(CARD_6, EE_OFF), + + MESON_PIN(GPIODV_0, EE_OFF), + MESON_PIN(GPIODV_1, EE_OFF), + MESON_PIN(GPIODV_2, EE_OFF), + MESON_PIN(GPIODV_3, EE_OFF), + MESON_PIN(GPIODV_4, EE_OFF), + MESON_PIN(GPIODV_5, EE_OFF), + MESON_PIN(GPIODV_6, EE_OFF), + MESON_PIN(GPIODV_7, EE_OFF), + MESON_PIN(GPIODV_8, EE_OFF), + MESON_PIN(GPIODV_9, EE_OFF), + MESON_PIN(GPIODV_10, EE_OFF), + MESON_PIN(GPIODV_11, EE_OFF), + MESON_PIN(GPIODV_12, EE_OFF), + MESON_PIN(GPIODV_13, EE_OFF), + MESON_PIN(GPIODV_14, EE_OFF), + MESON_PIN(GPIODV_15, EE_OFF), + MESON_PIN(GPIODV_16, EE_OFF), + MESON_PIN(GPIODV_17, EE_OFF), + MESON_PIN(GPIODV_19, EE_OFF), + MESON_PIN(GPIODV_20, EE_OFF), + MESON_PIN(GPIODV_21, EE_OFF), + MESON_PIN(GPIODV_22, EE_OFF), + MESON_PIN(GPIODV_23, EE_OFF), + MESON_PIN(GPIODV_24, EE_OFF), + MESON_PIN(GPIODV_25, EE_OFF), + MESON_PIN(GPIODV_26, EE_OFF), + MESON_PIN(GPIODV_27, EE_OFF), + MESON_PIN(GPIODV_28, EE_OFF), + MESON_PIN(GPIODV_29, EE_OFF), + + MESON_PIN(GPIOX_0, EE_OFF), + MESON_PIN(GPIOX_1, EE_OFF), + MESON_PIN(GPIOX_2, EE_OFF), + MESON_PIN(GPIOX_3, EE_OFF), + MESON_PIN(GPIOX_4, EE_OFF), + MESON_PIN(GPIOX_5, EE_OFF), + MESON_PIN(GPIOX_6, EE_OFF), + MESON_PIN(GPIOX_7, EE_OFF), + MESON_PIN(GPIOX_8, EE_OFF), + MESON_PIN(GPIOX_9, EE_OFF), + MESON_PIN(GPIOX_10, EE_OFF), + MESON_PIN(GPIOX_11, EE_OFF), + MESON_PIN(GPIOX_12, EE_OFF), + MESON_PIN(GPIOX_13, EE_OFF), + MESON_PIN(GPIOX_14, EE_OFF), + MESON_PIN(GPIOX_15, EE_OFF), + MESON_PIN(GPIOX_16, EE_OFF), + MESON_PIN(GPIOX_17, EE_OFF), + MESON_PIN(GPIOX_18, EE_OFF), + + MESON_PIN(GPIOCLK_0, EE_OFF), + MESON_PIN(GPIOCLK_1, EE_OFF), + + MESON_PIN(GPIO_TEST_N, EE_OFF), +}; + +static const unsigned int emmc_nand_d07_pins[] = { + PIN(BOOT_0, EE_OFF), PIN(BOOT_1, EE_OFF), PIN(BOOT_2, EE_OFF), + PIN(BOOT_3, EE_OFF), PIN(BOOT_4, EE_OFF), PIN(BOOT_5, EE_OFF), + PIN(BOOT_6, EE_OFF), PIN(BOOT_7, EE_OFF), +}; +static const unsigned int emmc_clk_pins[] = { PIN(BOOT_8, EE_OFF) }; +static const unsigned int emmc_cmd_pins[] = { PIN(BOOT_10, EE_OFF) }; +static const unsigned int emmc_ds_pins[] = { PIN(BOOT_15, EE_OFF) }; + +static const unsigned int sdcard_d0_pins[] = { PIN(CARD_1, EE_OFF) }; +static const unsigned int sdcard_d1_pins[] = { PIN(CARD_0, EE_OFF) }; +static const unsigned int sdcard_d2_pins[] = { PIN(CARD_5, EE_OFF) }; +static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) }; +static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) }; +static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) }; + +static const unsigned int sdio_d0_pins[] = { PIN(GPIOX_0, EE_OFF) }; +static const unsigned int sdio_d1_pins[] = { PIN(GPIOX_1, EE_OFF) }; +static const unsigned int sdio_d2_pins[] = { PIN(GPIOX_2, EE_OFF) }; +static const unsigned int sdio_d3_pins[] = { PIN(GPIOX_3, EE_OFF) }; +static const unsigned int sdio_cmd_pins[] = { PIN(GPIOX_4, EE_OFF) }; +static const unsigned int sdio_clk_pins[] = { PIN(GPIOX_5, EE_OFF) }; +static const unsigned int sdio_irq_pins[] = { PIN(GPIOX_7, EE_OFF) }; + +static const unsigned int nand_ce0_pins[] = { PIN(BOOT_8, EE_OFF) }; +static const unsigned int nand_ce1_pins[] = { PIN(BOOT_9, EE_OFF) }; +static const unsigned int nand_rb0_pins[] = { PIN(BOOT_10, EE_OFF) }; +static const unsigned int nand_ale_pins[] = { PIN(BOOT_11, EE_OFF) }; +static const unsigned int nand_cle_pins[] = { PIN(BOOT_12, EE_OFF) }; +static const unsigned int nand_wen_clk_pins[] = { PIN(BOOT_13, EE_OFF) }; +static const unsigned int nand_ren_wr_pins[] = { PIN(BOOT_14, EE_OFF) }; +static const unsigned int nand_dqs_pins[] = { PIN(BOOT_15, EE_OFF) }; + +static const unsigned int uart_tx_a_pins[] = { PIN(GPIOX_12, EE_OFF) }; +static const unsigned int uart_rx_a_pins[] = { PIN(GPIOX_13, EE_OFF) }; +static const unsigned int uart_cts_a_pins[] = { PIN(GPIOX_14, EE_OFF) }; +static const unsigned int uart_rts_a_pins[] = { PIN(GPIOX_15, EE_OFF) }; + +static const unsigned int uart_tx_b_pins[] = { PIN(GPIODV_24, EE_OFF) }; +static const unsigned int uart_rx_b_pins[] = { PIN(GPIODV_25, EE_OFF) }; + +static const unsigned int uart_tx_c_pins[] = { PIN(GPIOX_8, EE_OFF) }; +static const unsigned int uart_rx_c_pins[] = { PIN(GPIOX_9, EE_OFF) }; + +static const unsigned int i2c_sck_a_pins[] = { PIN(GPIODV_25, EE_OFF) }; +static const unsigned int i2c_sda_a_pins[] = { PIN(GPIODV_24, EE_OFF) }; + +static const unsigned int i2c_sck_b_pins[] = { PIN(GPIODV_27, EE_OFF) }; +static const unsigned int i2c_sda_b_pins[] = { PIN(GPIODV_26, EE_OFF) }; + +static const unsigned int i2c_sck_c_pins[] = { PIN(GPIODV_29, EE_OFF) }; +static const unsigned int i2c_sda_c_pins[] = { PIN(GPIODV_28, EE_OFF) }; + +static const unsigned int eth_mdio_pins[] = { PIN(GPIOZ_0, EE_OFF) }; +static const unsigned int eth_mdc_pins[] = { PIN(GPIOZ_1, EE_OFF) }; +static const unsigned int eth_clk_rx_clk_pins[] = { PIN(GPIOZ_2, EE_OFF) }; +static const unsigned int eth_rx_dv_pins[] = { PIN(GPIOZ_3, EE_OFF) }; +static const unsigned int eth_rxd0_pins[] = { PIN(GPIOZ_4, EE_OFF) }; +static const unsigned int eth_rxd1_pins[] = { PIN(GPIOZ_5, EE_OFF) }; +static const unsigned int eth_rxd2_pins[] = { PIN(GPIOZ_6, EE_OFF) }; +static const unsigned int eth_rxd3_pins[] = { PIN(GPIOZ_7, EE_OFF) }; +static const unsigned int eth_rgmii_tx_clk_pins[] = { PIN(GPIOZ_8, EE_OFF) }; +static const unsigned int eth_tx_en_pins[] = { PIN(GPIOZ_9, EE_OFF) }; +static const unsigned int eth_txd0_pins[] = { PIN(GPIOZ_10, EE_OFF) }; +static const unsigned int eth_txd1_pins[] = { PIN(GPIOZ_11, EE_OFF) }; +static const unsigned int eth_txd2_pins[] = { PIN(GPIOZ_12, EE_OFF) }; +static const unsigned int eth_txd3_pins[] = { PIN(GPIOZ_13, EE_OFF) }; + +static const unsigned int pwm_e_pins[] = { PIN(GPIOX_16, EE_OFF) }; + +static const struct pinctrl_pin_desc meson_gxl_aobus_pins[] = { + MESON_PIN(GPIOAO_0, 0), + MESON_PIN(GPIOAO_1, 0), + MESON_PIN(GPIOAO_2, 0), + MESON_PIN(GPIOAO_3, 0), + MESON_PIN(GPIOAO_4, 0), + MESON_PIN(GPIOAO_5, 0), + MESON_PIN(GPIOAO_6, 0), + MESON_PIN(GPIOAO_7, 0), + MESON_PIN(GPIOAO_8, 0), + MESON_PIN(GPIOAO_9, 0), +}; + +static const unsigned int uart_tx_ao_a_pins[] = { PIN(GPIOAO_0, 0) }; +static const unsigned int uart_rx_ao_a_pins[] = { PIN(GPIOAO_1, 0) }; +static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, 0) }; +static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, 0) }; +static const unsigned int uart_tx_ao_b_pins[] = { PIN(GPIOAO_0, 0) }; +static const unsigned int uart_rx_ao_b_pins[] = { PIN(GPIOAO_1, 0), + PIN(GPIOAO_5, 0) }; +static const unsigned int uart_cts_ao_b_pins[] = { PIN(GPIOAO_2, 0) }; +static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, 0) }; + +static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) }; + +static struct meson_pmx_group meson_gxl_periphs_groups[] = { + GPIO_GROUP(GPIOZ_0, EE_OFF), + GPIO_GROUP(GPIOZ_1, EE_OFF), + GPIO_GROUP(GPIOZ_2, EE_OFF), + GPIO_GROUP(GPIOZ_3, EE_OFF), + GPIO_GROUP(GPIOZ_4, EE_OFF), + GPIO_GROUP(GPIOZ_5, EE_OFF), + GPIO_GROUP(GPIOZ_6, EE_OFF), + GPIO_GROUP(GPIOZ_7, EE_OFF), + GPIO_GROUP(GPIOZ_8, EE_OFF), + GPIO_GROUP(GPIOZ_9, EE_OFF), + GPIO_GROUP(GPIOZ_10, EE_OFF), + GPIO_GROUP(GPIOZ_11, EE_OFF), + GPIO_GROUP(GPIOZ_12, EE_OFF), + GPIO_GROUP(GPIOZ_13, EE_OFF), + GPIO_GROUP(GPIOZ_14, EE_OFF), + GPIO_GROUP(GPIOZ_15, EE_OFF), + + GPIO_GROUP(GPIOH_0, EE_OFF), + GPIO_GROUP(GPIOH_1, EE_OFF), + GPIO_GROUP(GPIOH_2, EE_OFF), + GPIO_GROUP(GPIOH_3, EE_OFF), + GPIO_GROUP(GPIOH_4, EE_OFF), + GPIO_GROUP(GPIOH_5, EE_OFF), + GPIO_GROUP(GPIOH_6, EE_OFF), + GPIO_GROUP(GPIOH_7, EE_OFF), + GPIO_GROUP(GPIOH_8, EE_OFF), + GPIO_GROUP(GPIOH_9, EE_OFF), + + GPIO_GROUP(BOOT_0, EE_OFF), + GPIO_GROUP(BOOT_1, EE_OFF), + GPIO_GROUP(BOOT_2, EE_OFF), + GPIO_GROUP(BOOT_3, EE_OFF), + GPIO_GROUP(BOOT_4, EE_OFF), + GPIO_GROUP(BOOT_5, EE_OFF), + GPIO_GROUP(BOOT_6, EE_OFF), + GPIO_GROUP(BOOT_7, EE_OFF), + GPIO_GROUP(BOOT_8, EE_OFF), + GPIO_GROUP(BOOT_9, EE_OFF), + GPIO_GROUP(BOOT_10, EE_OFF), + GPIO_GROUP(BOOT_11, EE_OFF), + GPIO_GROUP(BOOT_12, EE_OFF), + GPIO_GROUP(BOOT_13, EE_OFF), + GPIO_GROUP(BOOT_14, EE_OFF), + GPIO_GROUP(BOOT_15, EE_OFF), + + GPIO_GROUP(CARD_0, EE_OFF), + GPIO_GROUP(CARD_1, EE_OFF), + GPIO_GROUP(CARD_2, EE_OFF), + GPIO_GROUP(CARD_3, EE_OFF), + GPIO_GROUP(CARD_4, EE_OFF), + GPIO_GROUP(CARD_5, EE_OFF), + GPIO_GROUP(CARD_6, EE_OFF), + + GPIO_GROUP(GPIODV_0, EE_OFF), + GPIO_GROUP(GPIODV_1, EE_OFF), + GPIO_GROUP(GPIODV_2, EE_OFF), + GPIO_GROUP(GPIODV_3, EE_OFF), + GPIO_GROUP(GPIODV_4, EE_OFF), + GPIO_GROUP(GPIODV_5, EE_OFF), + GPIO_GROUP(GPIODV_6, EE_OFF), + GPIO_GROUP(GPIODV_7, EE_OFF), + GPIO_GROUP(GPIODV_8, EE_OFF), + GPIO_GROUP(GPIODV_9, EE_OFF), + GPIO_GROUP(GPIODV_10, EE_OFF), + GPIO_GROUP(GPIODV_11, EE_OFF), + GPIO_GROUP(GPIODV_12, EE_OFF), + GPIO_GROUP(GPIODV_13, EE_OFF), + GPIO_GROUP(GPIODV_14, EE_OFF), + GPIO_GROUP(GPIODV_15, EE_OFF), + GPIO_GROUP(GPIODV_16, EE_OFF), + GPIO_GROUP(GPIODV_17, EE_OFF), + GPIO_GROUP(GPIODV_19, EE_OFF), + GPIO_GROUP(GPIODV_20, EE_OFF), + GPIO_GROUP(GPIODV_21, EE_OFF), + GPIO_GROUP(GPIODV_22, EE_OFF), + GPIO_GROUP(GPIODV_23, EE_OFF), + GPIO_GROUP(GPIODV_24, EE_OFF), + GPIO_GROUP(GPIODV_25, EE_OFF), + GPIO_GROUP(GPIODV_26, EE_OFF), + GPIO_GROUP(GPIODV_27, EE_OFF), + GPIO_GROUP(GPIODV_28, EE_OFF), + GPIO_GROUP(GPIODV_29, EE_OFF), + + GPIO_GROUP(GPIOX_0, EE_OFF), + GPIO_GROUP(GPIOX_1, EE_OFF), + GPIO_GROUP(GPIOX_2, EE_OFF), + GPIO_GROUP(GPIOX_3, EE_OFF), + GPIO_GROUP(GPIOX_4, EE_OFF), + GPIO_GROUP(GPIOX_5, EE_OFF), + GPIO_GROUP(GPIOX_6, EE_OFF), + GPIO_GROUP(GPIOX_7, EE_OFF), + GPIO_GROUP(GPIOX_8, EE_OFF), + GPIO_GROUP(GPIOX_9, EE_OFF), + GPIO_GROUP(GPIOX_10, EE_OFF), + GPIO_GROUP(GPIOX_11, EE_OFF), + GPIO_GROUP(GPIOX_12, EE_OFF), + GPIO_GROUP(GPIOX_13, EE_OFF), + GPIO_GROUP(GPIOX_14, EE_OFF), + GPIO_GROUP(GPIOX_15, EE_OFF), + GPIO_GROUP(GPIOX_16, EE_OFF), + GPIO_GROUP(GPIOX_17, EE_OFF), + GPIO_GROUP(GPIOX_18, EE_OFF), + + GPIO_GROUP(GPIOCLK_0, EE_OFF), + GPIO_GROUP(GPIOCLK_1, EE_OFF), + + GPIO_GROUP(GPIO_TEST_N, EE_OFF), + + /* Bank X */ + GROUP(sdio_d0, 5, 31), + GROUP(sdio_d1, 5, 30), + GROUP(sdio_d2, 5, 29), + GROUP(sdio_d3, 5, 28), + GROUP(sdio_cmd, 5, 27), + GROUP(sdio_clk, 5, 26), + GROUP(sdio_irq, 5, 24), + GROUP(uart_tx_a, 5, 19), + GROUP(uart_rx_a, 5, 18), + GROUP(uart_cts_a, 5, 17), + GROUP(uart_rts_a, 5, 16), + GROUP(uart_tx_c, 5, 13), + GROUP(uart_rx_c, 5, 12), + GROUP(pwm_e, 5, 15), + + /* Bank Z */ + GROUP(eth_mdio, 4, 22), + GROUP(eth_mdc, 4, 23), + GROUP(eth_clk_rx_clk, 4, 21), + GROUP(eth_rx_dv, 4, 20), + GROUP(eth_rxd0, 4, 19), + GROUP(eth_rxd1, 4, 18), + GROUP(eth_rxd2, 4, 17), + GROUP(eth_rxd3, 4, 16), + GROUP(eth_rgmii_tx_clk, 4, 15), + GROUP(eth_tx_en, 4, 14), + GROUP(eth_txd0, 4, 13), + GROUP(eth_txd1, 4, 12), + GROUP(eth_txd2, 4, 11), + GROUP(eth_txd3, 4, 10), + + /* Bank DV */ + GROUP(uart_tx_b, 2, 16), + GROUP(uart_rx_b, 2, 15), + GROUP(i2c_sck_a, 1, 15), + GROUP(i2c_sda_a, 1, 14), + GROUP(i2c_sck_b, 1, 13), + GROUP(i2c_sda_b, 1, 12), + GROUP(i2c_sck_c, 1, 11), + GROUP(i2c_sda_c, 1, 10), + + /* Bank BOOT */ + GROUP(emmc_nand_d07, 7, 31), + GROUP(emmc_clk, 7, 30), + GROUP(emmc_cmd, 7, 29), + GROUP(emmc_ds, 7, 28), + GROUP(nand_ce0, 7, 7), + GROUP(nand_ce1, 7, 6), + GROUP(nand_rb0, 7, 5), + GROUP(nand_ale, 7, 4), + GROUP(nand_cle, 7, 3), + GROUP(nand_wen_clk, 7, 2), + GROUP(nand_ren_wr, 7, 1), + GROUP(nand_dqs, 7, 0), + + /* Bank CARD */ + GROUP(sdcard_d1, 6, 5), + GROUP(sdcard_d0, 6, 4), + GROUP(sdcard_d3, 6, 1), + GROUP(sdcard_d2, 6, 0), + GROUP(sdcard_cmd, 6, 2), + GROUP(sdcard_clk, 6, 3), +}; + +static struct meson_pmx_group meson_gxl_aobus_groups[] = { + GPIO_GROUP(GPIOAO_0, 0), + GPIO_GROUP(GPIOAO_1, 0), + GPIO_GROUP(GPIOAO_2, 0), + GPIO_GROUP(GPIOAO_3, 0), + GPIO_GROUP(GPIOAO_4, 0), + GPIO_GROUP(GPIOAO_5, 0), + GPIO_GROUP(GPIOAO_6, 0), + GPIO_GROUP(GPIOAO_7, 0), + GPIO_GROUP(GPIOAO_8, 0), + GPIO_GROUP(GPIOAO_9, 0), + + /* bank AO */ + GROUP(uart_tx_ao_b, 0, 26), + GROUP(uart_rx_ao_b, 0, 25), + GROUP(uart_tx_ao_a, 0, 12), + GROUP(uart_rx_ao_a, 0, 11), + GROUP(uart_cts_ao_a, 0, 10), + GROUP(uart_rts_ao_a, 0, 9), + GROUP(uart_cts_ao_b, 0, 8), + GROUP(uart_rts_ao_b, 0, 7), + GROUP(remote_input_ao, 0, 0), +}; + +static const char * const gpio_periphs_groups[] = { + "GPIOZ_0", "GPIOZ_1", "GPIOZ_2", "GPIOZ_3", "GPIOZ_4", + "GPIOZ_5", "GPIOZ_6", "GPIOZ_7", "GPIOZ_8", "GPIOZ_9", + "GPIOZ_10", "GPIOZ_11", "GPIOZ_12", "GPIOZ_13", "GPIOZ_14", + "GPIOZ_15", + + "GPIOH_0", "GPIOH_1", "GPIOH_2", "GPIOH_3", "GPIOH_4", + "GPIOH_5", "GPIOH_6", "GPIOH_7", "GPIOH_8", "GPIOH_9", + + "BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4", + "BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9", + "BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14", + "BOOT_15", + + "CARD_0", "CARD_1", "CARD_2", "CARD_3", "CARD_4", + "CARD_5", "CARD_6", + + "GPIODV_0", "GPIODV_1", "GPIODV_2", "GPIODV_3", "GPIODV_4", + "GPIODV_5", "GPIODV_6", "GPIODV_7", "GPIODV_8", "GPIODV_9", + "GPIODV_10", "GPIODV_11", "GPIODV_12", "GPIODV_13", "GPIODV_14", + "GPIODV_15", "GPIODV_16", "GPIODV_17", "GPIODV_18", "GPIODV_19", + "GPIODV_20", "GPIODV_21", "GPIODV_22", "GPIODV_23", "GPIODV_24", + "GPIODV_25", "GPIODV_26", "GPIODV_27", "GPIODV_28", "GPIODV_29", + + "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4", + "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9", + "GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14", + "GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18", + + "GPIO_TEST_N", +}; + +static const char * const emmc_groups[] = { + "emmc_nand_d07", "emmc_clk", "emmc_cmd", "emmc_ds", +}; + +static const char * const sdcard_groups[] = { + "sdcard_d0", "sdcard_d1", "sdcard_d2", "sdcard_d3", + "sdcard_cmd", "sdcard_clk", +}; + +static const char * const sdio_groups[] = { + "sdio_d0", "sdio_d1", "sdio_d2", "sdio_d3", + "sdio_cmd", "sdio_clk", "sdio_irq", +}; + +static const char * const nand_groups[] = { + "nand_ce0", "nand_ce1", "nand_rb0", "nand_ale", "nand_cle", + "nand_wen_clk", "nand_ren_wr", "nand_dqs", +}; + +static const char * const uart_a_groups[] = { + "uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a", +}; + +static const char * const uart_b_groups[] = { + "uart_tx_b", "uart_rx_b", +}; + +static const char * const uart_c_groups[] = { + "uart_tx_c", "uart_rx_c", +}; + +static const char * const i2c_a_groups[] = { + "i2c_sck_a", "i2c_sda_a", +}; + +static const char * const i2c_b_groups[] = { + "i2c_sck_b", "i2c_sda_b", +}; + +static const char * const i2c_c_groups[] = { + "i2c_sck_c", "i2c_sda_c", +}; + +static const char * const eth_groups[] = { + "eth_mdio", "eth_mdc", "eth_clk_rx_clk", "eth_rx_dv", + "eth_rxd0", "eth_rxd1", "eth_rxd2", "eth_rxd3", + "eth_rgmii_tx_clk", "eth_tx_en", + "eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3", +}; + +static const char * const pwm_e_groups[] = { + "pwm_e", +}; + +static const char * const gpio_aobus_groups[] = { + "GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4", + "GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9", +}; + +static const char * const uart_ao_groups[] = { + "uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a", +}; + +static const char * const uart_ao_b_groups[] = { + "uart_tx_ao_b", "uart_rx_ao_b", "uart_cts_ao_b", "uart_rts_ao_b", +}; + +static const char * const remote_input_ao_groups[] = { + "remote_input_ao", +}; + +static struct meson_pmx_func meson_gxl_periphs_functions[] = { + FUNCTION(gpio_periphs), + FUNCTION(emmc), + FUNCTION(sdcard), + FUNCTION(sdio), + FUNCTION(nand), + FUNCTION(uart_a), + FUNCTION(uart_b), + FUNCTION(uart_c), + FUNCTION(i2c_a), + FUNCTION(i2c_b), + FUNCTION(i2c_c), + FUNCTION(eth), + FUNCTION(pwm_e), +}; + +static struct meson_pmx_func meson_gxl_aobus_functions[] = { + FUNCTION(gpio_aobus), + FUNCTION(uart_ao), + FUNCTION(uart_ao_b), + FUNCTION(remote_input_ao), +}; + +static struct meson_bank meson_gxl_periphs_banks[] = { + /* name first last pullen pull dir out in */ + BANK("X", PIN(GPIOX_0, EE_OFF), PIN(GPIOX_18, EE_OFF), 4, 0, 4, 0, 12, 0, 13, 0, 14, 0), + BANK("DV", PIN(GPIODV_0, EE_OFF), PIN(GPIODV_29, EE_OFF), 0, 0, 0, 0, 0, 0, 1, 0, 2, 0), + BANK("H", PIN(GPIOH_0, EE_OFF), PIN(GPIOH_9, EE_OFF), 1, 20, 1, 20, 3, 20, 4, 20, 5, 20), + BANK("Z", PIN(GPIOZ_0, EE_OFF), PIN(GPIOZ_15, EE_OFF), 3, 0, 3, 0, 9, 0, 10, 0, 11, 0), + BANK("CARD", PIN(CARD_0, EE_OFF), PIN(CARD_6, EE_OFF), 2, 20, 2, 20, 6, 20, 7, 20, 8, 20), + BANK("BOOT", PIN(BOOT_0, EE_OFF), PIN(BOOT_15, EE_OFF), 2, 0, 2, 0, 6, 0, 7, 0, 8, 0), + BANK("CLK", PIN(GPIOCLK_0, EE_OFF), PIN(GPIOCLK_1, EE_OFF), 3, 28, 3, 28, 9, 28, 10, 28, 11, 28), +}; + +static struct meson_bank meson_gxl_aobus_banks[] = { + /* name first last pullen pull dir out in */ + BANK("AO", PIN(GPIOAO_0, 0), PIN(GPIOAO_9, 0), 0, 0, 0, 16, 0, 0, 0, 16, 1, 0), +}; + +struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data = { + .name = "periphs-banks", + .pin_base = 10, + .pins = meson_gxl_periphs_pins, + .groups = meson_gxl_periphs_groups, + .funcs = meson_gxl_periphs_functions, + .banks = meson_gxl_periphs_banks, + .num_pins = ARRAY_SIZE(meson_gxl_periphs_pins), + .num_groups = ARRAY_SIZE(meson_gxl_periphs_groups), + .num_funcs = ARRAY_SIZE(meson_gxl_periphs_functions), + .num_banks = ARRAY_SIZE(meson_gxl_periphs_banks), +}; + +struct meson_pinctrl_data meson_gxl_aobus_pinctrl_data = { + .name = "aobus-banks", + .pin_base = 0, + .pins = meson_gxl_aobus_pins, + .groups = meson_gxl_aobus_groups, + .funcs = meson_gxl_aobus_functions, + .banks = meson_gxl_aobus_banks, + .num_pins = ARRAY_SIZE(meson_gxl_aobus_pins), + .num_groups = ARRAY_SIZE(meson_gxl_aobus_groups), + .num_funcs = ARRAY_SIZE(meson_gxl_aobus_functions), + .num_banks = ARRAY_SIZE(meson_gxl_aobus_banks), +}; diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index 57122eda155a..a579126832af 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -524,6 +524,14 @@ static const struct of_device_id meson_pinctrl_dt_match[] = { .compatible = "amlogic,meson-gxbb-aobus-pinctrl", .data = &meson_gxbb_aobus_pinctrl_data, }, + { + .compatible = "amlogic,meson-gxl-periphs-pinctrl", + .data = &meson_gxl_periphs_pinctrl_data, + }, + { + .compatible = "amlogic,meson-gxl-aobus-pinctrl", + .data = &meson_gxl_aobus_pinctrl_data, + }, { }, }; diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h index 98b5080650c1..1aa871d5431e 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.h +++ b/drivers/pinctrl/meson/pinctrl-meson.h @@ -169,3 +169,5 @@ extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data; extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data; extern struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data; extern struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data; +extern struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data; +extern struct meson_pinctrl_data meson_gxl_aobus_pinctrl_data; diff --git a/include/dt-bindings/gpio/meson-gxl-gpio.h b/include/dt-bindings/gpio/meson-gxl-gpio.h new file mode 100644 index 000000000000..684d0d7add1c --- /dev/null +++ b/include/dt-bindings/gpio/meson-gxl-gpio.h @@ -0,0 +1,131 @@ +/* + * GPIO definitions for Amlogic Meson GXL SoCs + * + * Copyright (C) 2016 Endless Mobile, Inc. + * Author: Carlo Caione + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _DT_BINDINGS_MESON_GXL_GPIO_H +#define _DT_BINDINGS_MESON_GXL_GPIO_H + +#define GPIOAO_0 0 +#define GPIOAO_1 1 +#define GPIOAO_2 2 +#define GPIOAO_3 3 +#define GPIOAO_4 4 +#define GPIOAO_5 5 +#define GPIOAO_6 6 +#define GPIOAO_7 7 +#define GPIOAO_8 8 +#define GPIOAO_9 9 + +#define GPIOZ_0 0 +#define GPIOZ_1 1 +#define GPIOZ_2 2 +#define GPIOZ_3 3 +#define GPIOZ_4 4 +#define GPIOZ_5 5 +#define GPIOZ_6 6 +#define GPIOZ_7 7 +#define GPIOZ_8 8 +#define GPIOZ_9 9 +#define GPIOZ_10 10 +#define GPIOZ_11 11 +#define GPIOZ_12 12 +#define GPIOZ_13 13 +#define GPIOZ_14 14 +#define GPIOZ_15 15 +#define GPIOH_0 16 +#define GPIOH_1 17 +#define GPIOH_2 18 +#define GPIOH_3 19 +#define GPIOH_4 20 +#define GPIOH_5 21 +#define GPIOH_6 22 +#define GPIOH_7 23 +#define GPIOH_8 24 +#define GPIOH_9 25 +#define BOOT_0 26 +#define BOOT_1 27 +#define BOOT_2 28 +#define BOOT_3 29 +#define BOOT_4 30 +#define BOOT_5 31 +#define BOOT_6 32 +#define BOOT_7 33 +#define BOOT_8 34 +#define BOOT_9 35 +#define BOOT_10 36 +#define BOOT_11 37 +#define BOOT_12 38 +#define BOOT_13 39 +#define BOOT_14 40 +#define BOOT_15 41 +#define CARD_0 42 +#define CARD_1 43 +#define CARD_2 44 +#define CARD_3 45 +#define CARD_4 46 +#define CARD_5 47 +#define CARD_6 48 +#define GPIODV_0 49 +#define GPIODV_1 50 +#define GPIODV_2 51 +#define GPIODV_3 52 +#define GPIODV_4 53 +#define GPIODV_5 54 +#define GPIODV_6 55 +#define GPIODV_7 56 +#define GPIODV_8 57 +#define GPIODV_9 58 +#define GPIODV_10 59 +#define GPIODV_11 60 +#define GPIODV_12 61 +#define GPIODV_13 62 +#define GPIODV_14 63 +#define GPIODV_15 64 +#define GPIODV_16 65 +#define GPIODV_17 66 +#define GPIODV_18 67 +#define GPIODV_19 68 +#define GPIODV_20 69 +#define GPIODV_21 70 +#define GPIODV_22 71 +#define GPIODV_23 72 +#define GPIODV_24 73 +#define GPIODV_25 74 +#define GPIODV_26 75 +#define GPIODV_27 76 +#define GPIODV_28 77 +#define GPIODV_29 78 +#define GPIOX_0 79 +#define GPIOX_1 80 +#define GPIOX_2 81 +#define GPIOX_3 82 +#define GPIOX_4 83 +#define GPIOX_5 84 +#define GPIOX_6 85 +#define GPIOX_7 86 +#define GPIOX_8 87 +#define GPIOX_9 88 +#define GPIOX_10 89 +#define GPIOX_11 90 +#define GPIOX_12 91 +#define GPIOX_13 92 +#define GPIOX_14 93 +#define GPIOX_15 94 +#define GPIOX_16 95 +#define GPIOX_17 96 +#define GPIOX_18 97 +#define GPIOCLK_0 98 +#define GPIOCLK_1 99 +#define GPIO_TEST_N 100 + +#endif -- cgit v1.2.3 From c18b4c52c755175dc62aed7b409dca24f028ce76 Mon Sep 17 00:00:00 2001 From: Mirza Krak Date: Mon, 17 Oct 2016 15:53:31 +0200 Subject: rtc: pcf85063: do not register a RTC device if chip is not present Add a sanity check to see if chip is present. If we can not communicate with the chip there is no point in registering a RTC device. Signed-off-by: Mirza Krak Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85063.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index efb0a08ac117..a06dff994c83 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -191,12 +191,19 @@ static int pcf85063_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct rtc_device *rtc; + int err; dev_dbg(&client->dev, "%s\n", __func__); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; + err = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1); + if (err < 0) { + dev_err(&client->dev, "RTC chip is not present\n"); + return err; + } + rtc = devm_rtc_device_register(&client->dev, pcf85063_driver.driver.name, &pcf85063_rtc_ops, THIS_MODULE); -- cgit v1.2.3 From 0c8c6ba00cbf2c0a6164aa41d43d017d65caf321 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sat, 29 Oct 2016 20:00:30 -0400 Subject: pinctrl: sunxi: make bool drivers explicitly non-modular None of the Kconfigs for any of these drivers are tristate, meaning that they currently are not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the drivers there is no doubt they are builtin-only. All drivers get essentially the same change, so they are handled in batch. Changes are (1) use builtin_platform_driver, (2) use init.h header (3) delete module_exit related code, (4) delete MODULE_DEVICE_TABLE, and (5) delete MODULE_LICENCE/MODULE_AUTHOR and associated tags. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We do delete the MODULE_LICENSE etc. tags since all that information is already contained at the top of each file in the comments. Cc: Boris Brezillon Cc: Chen-Yu Tsai Cc: Hans de Goede Cc: Linus Walleij Cc: Patrice Chotard Cc: Hongzhou Yang Cc: Fabian Frederick Cc: Maxime Coquelin Cc: Vishnu Patekar Cc: Mylene Josserand Cc: linux-gpio@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Paul Gortmaker Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-gr8.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c | 10 ++-------- drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c | 11 ++--------- drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c | 10 ++-------- drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c | 9 ++------- 13 files changed, 26 insertions(+), 95 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-gr8.c b/drivers/pinctrl/sunxi/pinctrl-gr8.c index 2904d2b7378b..2f232c3a0579 100644 --- a/drivers/pinctrl/sunxi/pinctrl-gr8.c +++ b/drivers/pinctrl/sunxi/pinctrl-gr8.c @@ -12,7 +12,7 @@ * warranty of any kind, whether express or implied. */ -#include +#include #include #include #include @@ -525,7 +525,6 @@ static const struct of_device_id sun5i_gr8_pinctrl_match[] = { { .compatible = "nextthing,gr8-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun5i_gr8_pinctrl_match); static struct platform_driver sun5i_gr8_pinctrl_driver = { .probe = sun5i_gr8_pinctrl_probe, @@ -534,8 +533,4 @@ static struct platform_driver sun5i_gr8_pinctrl_driver = { .of_match_table = sun5i_gr8_pinctrl_match, }, }; -module_platform_driver(sun5i_gr8_pinctrl_driver); - -MODULE_AUTHOR("Mylene Josserand +#include #include #include #include @@ -1035,7 +1035,6 @@ static const struct of_device_id sun4i_a10_pinctrl_match[] = { { .compatible = "allwinner,sun4i-a10-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun4i_a10_pinctrl_match); static struct platform_driver sun4i_a10_pinctrl_driver = { .probe = sun4i_a10_pinctrl_probe, @@ -1044,8 +1043,4 @@ static struct platform_driver sun4i_a10_pinctrl_driver = { .of_match_table = sun4i_a10_pinctrl_match, }, }; -module_platform_driver(sun4i_a10_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -674,7 +674,6 @@ static const struct of_device_id sun5i_a10s_pinctrl_match[] = { { .compatible = "allwinner,sun5i-a10s-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun5i_a10s_pinctrl_match); static struct platform_driver sun5i_a10s_pinctrl_driver = { .probe = sun5i_a10s_pinctrl_probe, @@ -683,8 +682,4 @@ static struct platform_driver sun5i_a10s_pinctrl_driver = { .of_match_table = sun5i_a10s_pinctrl_match, }, }; -module_platform_driver(sun5i_a10s_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -392,7 +392,6 @@ static const struct of_device_id sun5i_a13_pinctrl_match[] = { { .compatible = "allwinner,sun5i-a13-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun5i_a13_pinctrl_match); static struct platform_driver sun5i_a13_pinctrl_driver = { .probe = sun5i_a13_pinctrl_probe, @@ -401,8 +400,4 @@ static struct platform_driver sun5i_a13_pinctrl_driver = { .of_match_table = sun5i_a13_pinctrl_match, }, }; -module_platform_driver(sun5i_a13_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -136,7 +136,6 @@ static const struct of_device_id sun6i_a31_r_pinctrl_match[] = { { .compatible = "allwinner,sun6i-a31-r-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun6i_a31_r_pinctrl_match); static struct platform_driver sun6i_a31_r_pinctrl_driver = { .probe = sun6i_a31_r_pinctrl_probe, @@ -145,9 +144,4 @@ static struct platform_driver sun6i_a31_r_pinctrl_driver = { .of_match_table = sun6i_a31_r_pinctrl_match, }, }; -module_platform_driver(sun6i_a31_r_pinctrl_driver); - -MODULE_AUTHOR("Boris Brezillon +#include #include #include #include @@ -934,7 +934,6 @@ static const struct of_device_id sun6i_a31_pinctrl_match[] = { { .compatible = "allwinner,sun6i-a31-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun6i_a31_pinctrl_match); static struct platform_driver sun6i_a31_pinctrl_driver = { .probe = sun6i_a31_pinctrl_probe, @@ -943,8 +942,4 @@ static struct platform_driver sun6i_a31_pinctrl_driver = { .of_match_table = sun6i_a31_pinctrl_match, }, }; -module_platform_driver(sun6i_a31_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -798,7 +798,6 @@ static const struct of_device_id sun6i_a31s_pinctrl_match[] = { { .compatible = "allwinner,sun6i-a31s-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun6i_a31s_pinctrl_match); static struct platform_driver sun6i_a31s_pinctrl_driver = { .probe = sun6i_a31s_pinctrl_probe, @@ -807,8 +806,4 @@ static struct platform_driver sun6i_a31s_pinctrl_driver = { .of_match_table = sun6i_a31s_pinctrl_match, }, }; -module_platform_driver(sun6i_a31s_pinctrl_driver); - -MODULE_AUTHOR("Hans de Goede "); -MODULE_DESCRIPTION("Allwinner A31s pinctrl driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(sun6i_a31s_pinctrl_driver); diff --git a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c index 435ad30f45db..b6f4c68ffb39 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c @@ -10,7 +10,7 @@ * warranty of any kind, whether express or implied. */ -#include +#include #include #include #include @@ -1045,7 +1045,6 @@ static const struct of_device_id sun7i_a20_pinctrl_match[] = { { .compatible = "allwinner,sun7i-a20-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun7i_a20_pinctrl_match); static struct platform_driver sun7i_a20_pinctrl_driver = { .probe = sun7i_a20_pinctrl_probe, @@ -1054,8 +1053,4 @@ static struct platform_driver sun7i_a20_pinctrl_driver = { .of_match_table = sun7i_a20_pinctrl_match, }, }; -module_platform_driver(sun7i_a20_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -123,7 +123,6 @@ static const struct of_device_id sun8i_a23_r_pinctrl_match[] = { { .compatible = "allwinner,sun8i-a23-r-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun8i_a23_r_pinctrl_match); static struct platform_driver sun8i_a23_r_pinctrl_driver = { .probe = sun8i_a23_r_pinctrl_probe, @@ -132,10 +131,4 @@ static struct platform_driver sun8i_a23_r_pinctrl_driver = { .of_match_table = sun8i_a23_r_pinctrl_match, }, }; -module_platform_driver(sun8i_a23_r_pinctrl_driver); - -MODULE_AUTHOR("Chen-Yu Tsai "); -MODULE_AUTHOR("Boris Brezillon +#include #include #include #include @@ -575,7 +575,6 @@ static const struct of_device_id sun8i_a23_pinctrl_match[] = { { .compatible = "allwinner,sun8i-a23-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun8i_a23_pinctrl_match); static struct platform_driver sun8i_a23_pinctrl_driver = { .probe = sun8i_a23_pinctrl_probe, @@ -584,9 +583,4 @@ static struct platform_driver sun8i_a23_pinctrl_driver = { .of_match_table = sun8i_a23_pinctrl_match, }, }; -module_platform_driver(sun8i_a23_pinctrl_driver); - -MODULE_AUTHOR("Chen-Yu Tsai "); -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -498,7 +498,6 @@ static const struct of_device_id sun8i_a33_pinctrl_match[] = { { .compatible = "allwinner,sun8i-a33-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun8i_a33_pinctrl_match); static struct platform_driver sun8i_a33_pinctrl_driver = { .probe = sun8i_a33_pinctrl_probe, @@ -507,8 +506,4 @@ static struct platform_driver sun8i_a33_pinctrl_driver = { .of_match_table = sun8i_a33_pinctrl_match, }, }; -module_platform_driver(sun8i_a33_pinctrl_driver); - -MODULE_AUTHOR("Vishnu Patekar "); -MODULE_DESCRIPTION("Allwinner a33 pinctrl driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(sun8i_a33_pinctrl_driver); diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c index 90b973e15982..9aec1d2232dd 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c @@ -12,7 +12,7 @@ * warranty of any kind, whether express or implied. */ -#include +#include #include #include #include @@ -587,7 +587,6 @@ static const struct of_device_id sun8i_a83t_pinctrl_match[] = { { .compatible = "allwinner,sun8i-a83t-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun8i_a83t_pinctrl_match); static struct platform_driver sun8i_a83t_pinctrl_driver = { .probe = sun8i_a83t_pinctrl_probe, @@ -596,8 +595,4 @@ static struct platform_driver sun8i_a83t_pinctrl_driver = { .of_match_table = sun8i_a83t_pinctrl_match, }, }; -module_platform_driver(sun8i_a83t_pinctrl_driver); - -MODULE_AUTHOR("Vishnu Patekar "); -MODULE_DESCRIPTION("Allwinner a83t pinctrl driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(sun8i_a83t_pinctrl_driver); diff --git a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c index 1b580ba76453..bc14e954d7a2 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c @@ -10,7 +10,7 @@ * warranty of any kind, whether express or implied. */ -#include +#include #include #include #include @@ -733,7 +733,6 @@ static const struct of_device_id sun9i_a80_pinctrl_match[] = { { .compatible = "allwinner,sun9i-a80-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun9i_a80_pinctrl_match); static struct platform_driver sun9i_a80_pinctrl_driver = { .probe = sun9i_a80_pinctrl_probe, @@ -742,8 +741,4 @@ static struct platform_driver sun9i_a80_pinctrl_driver = { .of_match_table = sun9i_a80_pinctrl_match, }, }; -module_platform_driver(sun9i_a80_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard "); -MODULE_DESCRIPTION("Allwinner A80 pinctrl driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(sun9i_a80_pinctrl_driver); -- cgit v1.2.3 From 87ebfd6439c12df09c3b4e319e1fa9e1ebba3d55 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 31 Oct 2016 14:55:25 -0400 Subject: rtc: make rtc-lib explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/rtc/Kconfig:config RTC_LIB drivers/rtc/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular infrastructure use, so that when reading the driver there is no doubt it is builtin-only. We delete the MODULE_LICENSE tag since all that information is already contained at the top of the file in the comments. We don't replace module.h with init.h since the file doesn't need that. However we do add export.h since the file uses EXPORT_SYMBOL. Cc: Alessandro Zummo Cc: Alexandre Belloni Cc: rtc-linux@googlegroups.com Signed-off-by: Paul Gortmaker Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-lib.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index e6bfb9c42a10..1ae7da5cfc60 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c @@ -11,7 +11,7 @@ * published by the Free Software Foundation. */ -#include +#include #include static const unsigned char rtc_days_in_month[] = { @@ -148,5 +148,3 @@ struct rtc_time rtc_ktime_to_tm(ktime_t kt) return ret; } EXPORT_SYMBOL_GPL(rtc_ktime_to_tm); - -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 683cec8a06a0f1e67ff8f00791471e3ff04ce0f0 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 31 Oct 2016 14:55:26 -0400 Subject: rtc: sparc: make starfire explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/rtc/Kconfig:config RTC_DRV_STARFIRE drivers/rtc/Kconfig: bool "Starfire RTC" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular infrastructure use, so that when reading the driver there is no doubt it is builtin-only. We delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Alessandro Zummo Cc: Alexandre Belloni Cc: "David S. Miller" Cc: sparclinux@vger.kernel.org Cc: rtc-linux@googlegroups.com Signed-off-by: Paul Gortmaker Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-starfire.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c index 83a057a03060..7fc36973fa33 100644 --- a/drivers/rtc/rtc-starfire.c +++ b/drivers/rtc/rtc-starfire.c @@ -1,20 +1,18 @@ /* rtc-starfire.c: Starfire platform RTC driver. + * + * Author: David S. Miller + * License: GPL * * Copyright (C) 2008 David S. Miller */ #include -#include #include #include #include #include -MODULE_AUTHOR("David S. Miller "); -MODULE_DESCRIPTION("Starfire RTC driver"); -MODULE_LICENSE("GPL"); - static u32 starfire_get_time(void) { static char obp_gettod[32]; @@ -57,4 +55,4 @@ static struct platform_driver starfire_rtc_driver = { }, }; -module_platform_driver_probe(starfire_rtc_driver, starfire_rtc_probe); +builtin_platform_driver_probe(starfire_rtc_driver, starfire_rtc_probe); -- cgit v1.2.3 From 8b6102534cef64624caca7eb0a15e83f5ab9864c Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 31 Oct 2016 14:55:27 -0400 Subject: rtc: sparc: make sun4v explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/rtc/Kconfig:config RTC_DRV_SUN4V drivers/rtc/Kconfig: bool "SUN4V Hypervisor RTC" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular infrastructure use, so that when reading the driver there is no doubt it is builtin-only. We delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Alessandro Zummo Cc: Alexandre Belloni Cc: "David S. Miller" Cc: sparclinux@vger.kernel.org Cc: rtc-linux@googlegroups.com Signed-off-by: Paul Gortmaker Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sun4v.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c index 7c696c12f28f..11bc562eba5d 100644 --- a/drivers/rtc/rtc-sun4v.c +++ b/drivers/rtc/rtc-sun4v.c @@ -1,4 +1,7 @@ /* rtc-sun4v.c: Hypervisor based RTC for SUN4V systems. + * + * Author: David S. Miller + * License: GPL * * Copyright (C) 2008 David S. Miller */ @@ -6,7 +9,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include #include @@ -98,8 +100,4 @@ static struct platform_driver sun4v_rtc_driver = { }, }; -module_platform_driver_probe(sun4v_rtc_driver, sun4v_rtc_probe); - -MODULE_AUTHOR("David S. Miller "); -MODULE_DESCRIPTION("SUN4V RTC driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver_probe(sun4v_rtc_driver, sun4v_rtc_probe); -- cgit v1.2.3 From cd563200c090de628eb71c7478f272eaedc6fa4d Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Mon, 31 Oct 2016 21:39:45 +0100 Subject: rtc: jz4740: Add support for the RTC in the jz4780 SoC The RTC unit present in the JZ4780 works mostly the same as the one in the JZ4740. The major difference is that register writes need to be explicitly enabled, by writing a magic code (0xA55A) to a "write enable" register before each access. Signed-off-by: Paul Cercueil Acked-by: Maarten ter Huurne Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 6 +++--- drivers/rtc/rtc-jz4740.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4cbea34e6003..1d0ae30e9927 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1550,10 +1550,10 @@ config RTC_DRV_MPC5121 config RTC_DRV_JZ4740 tristate "Ingenic JZ4740 SoC" - depends on MACH_JZ4740 || COMPILE_TEST + depends on MACH_INGENIC || COMPILE_TEST help - If you say yes here you get support for the Ingenic JZ4740 SoC RTC - controller. + If you say yes here you get support for the Ingenic JZ47xx SoCs RTC + controllers. This driver can also be buillt as a module. If so, the module will be called rtc-jz4740. diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index 5e14651b71a8..7ad2d7965b4e 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -29,6 +29,10 @@ #define JZ_REG_RTC_HIBERNATE 0x20 #define JZ_REG_RTC_SCRATCHPAD 0x34 +/* The following are present on the jz4780 */ +#define JZ_REG_RTC_WENR 0x3C +#define JZ_RTC_WENR_WEN BIT(31) + #define JZ_RTC_CTRL_WRDY BIT(7) #define JZ_RTC_CTRL_1HZ BIT(6) #define JZ_RTC_CTRL_1HZ_IRQ BIT(5) @@ -37,8 +41,17 @@ #define JZ_RTC_CTRL_AE BIT(2) #define JZ_RTC_CTRL_ENABLE BIT(0) +/* Magic value to enable writes on jz4780 */ +#define JZ_RTC_WENR_MAGIC 0xA55A + +enum jz4740_rtc_type { + ID_JZ4740, + ID_JZ4780, +}; + struct jz4740_rtc { void __iomem *base; + enum jz4740_rtc_type type; struct rtc_device *rtc; @@ -64,11 +77,33 @@ static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) return timeout ? 0 : -EIO; } +static inline int jz4780_rtc_enable_write(struct jz4740_rtc *rtc) +{ + uint32_t ctrl; + int ret, timeout = 1000; + + ret = jz4740_rtc_wait_write_ready(rtc); + if (ret != 0) + return ret; + + writel(JZ_RTC_WENR_MAGIC, rtc->base + JZ_REG_RTC_WENR); + + do { + ctrl = readl(rtc->base + JZ_REG_RTC_WENR); + } while (!(ctrl & JZ_RTC_WENR_WEN) && --timeout); + + return timeout ? 0 : -EIO; +} + static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, uint32_t val) { - int ret; - ret = jz4740_rtc_wait_write_ready(rtc); + int ret = 0; + + if (rtc->type >= ID_JZ4780) + ret = jz4780_rtc_enable_write(rtc); + if (ret == 0) + ret = jz4740_rtc_wait_write_ready(rtc); if (ret == 0) writel(val, rtc->base + reg); @@ -216,11 +251,14 @@ static int jz4740_rtc_probe(struct platform_device *pdev) struct jz4740_rtc *rtc; uint32_t scratchpad; struct resource *mem; + const struct platform_device_id *id = platform_get_device_id(pdev); rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) return -ENOMEM; + rtc->type = id->driver_data; + rtc->irq = platform_get_irq(pdev, 0); if (rtc->irq < 0) { dev_err(&pdev->dev, "Failed to get platform irq\n"); @@ -295,12 +333,20 @@ static const struct dev_pm_ops jz4740_pm_ops = { #define JZ4740_RTC_PM_OPS NULL #endif /* CONFIG_PM */ +static const struct platform_device_id jz4740_rtc_ids[] = { + { "jz4740-rtc", ID_JZ4740 }, + { "jz4780-rtc", ID_JZ4780 }, + {} +}; +MODULE_DEVICE_TABLE(platform, jz4740_rtc_ids); + static struct platform_driver jz4740_rtc_driver = { .probe = jz4740_rtc_probe, .driver = { .name = "jz4740-rtc", .pm = JZ4740_RTC_PM_OPS, }, + .id_table = jz4740_rtc_ids, }; module_platform_driver(jz4740_rtc_driver); -- cgit v1.2.3 From c05229a893e79dc992abe0e561d7da0e3e84e1d8 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Mon, 31 Oct 2016 21:39:47 +0100 Subject: rtc: jz4740: Add support for devicetree See Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt for a description of the bindings. Signed-off-by: Paul Cercueil Acked-by: Maarten ter Huurne Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-jz4740.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index 7ad2d7965b4e..c2895cec56b4 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -245,6 +246,13 @@ void jz4740_rtc_poweroff(struct device *dev) } EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); +static const struct of_device_id jz4740_rtc_of_match[] = { + { .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 }, + { .compatible = "ingenic,jz4780-rtc", .data = (void *)ID_JZ4780 }, + {}, +}; +MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match); + static int jz4740_rtc_probe(struct platform_device *pdev) { int ret; @@ -252,12 +260,17 @@ static int jz4740_rtc_probe(struct platform_device *pdev) uint32_t scratchpad; struct resource *mem; const struct platform_device_id *id = platform_get_device_id(pdev); + const struct of_device_id *of_id = of_match_device( + jz4740_rtc_of_match, &pdev->dev); rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) return -ENOMEM; - rtc->type = id->driver_data; + if (of_id) + rtc->type = (enum jz4740_rtc_type)of_id->data; + else + rtc->type = id->driver_data; rtc->irq = platform_get_irq(pdev, 0); if (rtc->irq < 0) { @@ -345,6 +358,7 @@ static struct platform_driver jz4740_rtc_driver = { .driver = { .name = "jz4740-rtc", .pm = JZ4740_RTC_PM_OPS, + .of_match_table = of_match_ptr(jz4740_rtc_of_match), }, .id_table = jz4740_rtc_ids, }; -- cgit v1.2.3 From 465e42180cd1065039c09df337efd0a58f007c50 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Thu, 3 Nov 2016 14:15:26 -0700 Subject: pinctrl: qcom: Add msm8994 pinctrl driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initial pinctrl driver for QCOM msm8994 platforms. In order to continue the initial board support for QCOM msm8994/msm8992 presented in patches from Jeremy McNicoll , let's put a proper pinctrl driver in place. Currently, the DT for these platforms uses the msm8x74 pinctrl driver to enable basic UART. Beyond the first few pins the rest are different enough to justify it's own driver. Note: This driver is also used by QCOM's msm8992 platform as it's TLM block is the same. - Initial formatting and style was taken from the msm8x74 pinctrl driver added by Björn Andersson - Data was then adjusted per QCOM MSM8994v2 documentation for Top Level Multiplexing - Bindings documentation was based on qcom,msm8996-pinctrl.txt by Joonwoo Park and then modified for msm8994 content Signed-off-by: Michael Scott Tested-by: Jeremy McNicoll Acked-by: Bjorn Andersson Acked-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/pinctrl/qcom,msm8994-pinctrl.txt | 177 +++ drivers/pinctrl/qcom/Kconfig | 9 + drivers/pinctrl/qcom/Makefile | 1 + drivers/pinctrl/qcom/pinctrl-msm8994.c | 1379 ++++++++++++++++++++ 4 files changed, 1566 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt create mode 100644 drivers/pinctrl/qcom/pinctrl-msm8994.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt new file mode 100644 index 000000000000..13cd629f896e --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt @@ -0,0 +1,177 @@ +Qualcomm MSM8994 TLMM block + +This binding describes the Top Level Mode Multiplexer block found in the +MSM8994 platform. + +- compatible: + Usage: required + Value type: + Definition: Should contain one of: + "qcom,msm8992-pinctrl", + "qcom,msm8994-pinctrl". + +- reg: + Usage: required + Value type: + Definition: the base address and size of the TLMM register space. + +- interrupts: + Usage: required + Value type: + Definition: should specify the TLMM summary IRQ. + +- interrupt-controller: + Usage: required + Value type: + Definition: identifies this node as an interrupt controller + +- #interrupt-cells: + Usage: required + Value type: + Definition: must be 2. Specifying the pin number and flags, as defined + in + +- gpio-controller: + Usage: required + Value type: + Definition: identifies this node as a gpio controller + +- #gpio-cells: + Usage: required + Value type: + Definition: must be 2. Specifying the pin number and flags, as defined + in + +Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for +a general description of GPIO and interrupt bindings. + +Please refer to pinctrl-bindings.txt in this directory for details of the +common pinctrl bindings used by client devices, including the meaning of the +phrase "pin configuration node". + +The pin configuration nodes act as a container for an arbitrary number of +subnodes. Each of these subnodes represents some desired configuration for a +pin, a group, or a list of pins or groups. This configuration can include the +mux function to select on those pin(s)/group(s), and various pin configuration +parameters, such as pull-up, drive strength, etc. + + +PIN CONFIGURATION NODES: + +The name of each subnode is not important; all subnodes should be enumerated +and processed purely based on their content. + +Each subnode only affects those parameters that are explicitly listed. In +other words, a subnode that lists a mux function but no pin configuration +parameters implies no information about any pin configuration parameters. +Similarly, a pin subnode that describes a pullup parameter implies no +information about e.g. the mux function. + + +The following generic properties as defined in pinctrl-bindings.txt are valid +to specify in a pin configuration subnode: + +- pins: + Usage: required + Value type: + Definition: List of gpio pins affected by the properties specified in + this subnode. + + Valid pins are: + gpio0-gpio145 + Supports mux, bias and drive-strength + + sdc1_clk, sdc1_cmd, sdc1_data sdc1_rclk, sdc2_clk, + sdc2_cmd, sdc2_data + Supports bias and drive-strength + +- function: + Usage: required + Value type: + Definition: Specify the alternative function to be configured for the + specified pins. Functions are only valid for gpio pins. + Valid values are: + + audio_ref_clk, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5, + blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11, + blsp_i2c12, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3, + blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3, + blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9, + blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3, blsp_spi11, + blsp_spi12, blsp_uart1, blsp_uart2, blsp_uart3, blsp_uart4, blsp_uart5, + blsp_uart6, blsp_uart7, blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11, + blsp_uart12, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5, + blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10, blsp_uim11, + blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b, blsp11_uart_rx_b, + blsp11_uart_tx_b, cam_mclk0, cam_mclk1, cam_mclk2, cam_mclk3, + cci_async_in0, cci_async_in1, cci_async_in2, cci_i2c0, cci_i2c1, + cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4, + gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, gcc_gp2_clk_b, gcc_gp3_clk_a, + gcc_gp3_clk_b, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk, + gp1_clk, gps_tx, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd, hdmi_rcv, + mdp_vsync, mss_lte, nav_pps, nav_tsync, qdss_cti_trig_in_a, + qdss_cti_trig_in_b, qdss_cti_trig_in_c, qdss_cti_trig_in_d, + qdss_cti_trig_out_a, qdss_cti_trig_out_b, qdss_cti_trig_out_c, + qdss_cti_trig_out_d, qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a, + qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0, + pci_e1, pri_mi2s, sdc4, sec_mi2s, slimbus, spkr_i2s, ter_mi2s, tsif1, + tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4, gpio + +- bias-disable: + Usage: optional + Value type: + Definition: The specified pins should be configued as no pull. + +- bias-pull-down: + Usage: optional + Value type: + Definition: The specified pins should be configued as pull down. + +- bias-pull-up: + Usage: optional + Value type: + Definition: The specified pins should be configued as pull up. + +- output-high: + Usage: optional + Value type: + Definition: The specified pins are configured in output mode, driven + high. + Not valid for sdc pins. + +- output-low: + Usage: optional + Value type: + Definition: The specified pins are configured in output mode, driven + low. + Not valid for sdc pins. + +- drive-strength: + Usage: optional + Value type: + Definition: Selects the drive strength for the specified pins, in mA. + Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16 + +Example: + + msmgpio: pinctrl@fd510000 { + compatible = "qcom,msm8994-pinctrl"; + reg = <0xfd510000 0x4000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + + blsp1_uart2_default: blsp1_uart2_default { + pinmux { + pins = "gpio4", "gpio5"; + function = "blsp_uart2"; + }; + pinconf { + pins = "gpio4", "gpio5"; + drive-strength = <16>; + bias-disable; + }; + }; + }; diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 93ef268d5ccd..3ebdc01f53c0 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -79,6 +79,15 @@ config PINCTRL_MSM8916 This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block found on the Qualcomm 8916 platform. +config PINCTRL_MSM8994 + tristate "Qualcomm 8994 pin controller driver" + depends on GPIOLIB && OF + select PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8994 platform. The + Qualcomm 8992 platform is also supported by this driver. + config PINCTRL_MSM8996 tristate "Qualcomm MSM8996 pin controller driver" depends on GPIOLIB && OF diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 8319e11cecb5..ab47764dbc5c 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o +obj-$(CONFIG_PINCTRL_MSM8994) += pinctrl-msm8994.o obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c new file mode 100644 index 000000000000..8e16d9ae0c39 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c @@ -0,0 +1,1379 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "pinctrl-msm.h" + +#define FUNCTION(fname) \ + [MSM_MUX_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + MSM_MUX_gpio, \ + MSM_MUX_##f1, \ + MSM_MUX_##f2, \ + MSM_MUX_##f3, \ + MSM_MUX_##f4, \ + MSM_MUX_##f5, \ + MSM_MUX_##f6, \ + MSM_MUX_##f7, \ + MSM_MUX_##f8, \ + MSM_MUX_##f9, \ + MSM_MUX_##f10, \ + MSM_MUX_##f11 \ + }, \ + .nfuncs = 12, \ + .ctl_reg = 0x1000 + 0x10 * id, \ + .io_reg = 0x1004 + 0x10 * id, \ + .intr_cfg_reg = 0x1008 + 0x10 * id, \ + .intr_status_reg = 0x100c + 0x10 * id, \ + .intr_target_reg = 0x1008 + 0x10 * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 4, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +#define SDC_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_target_kpss_val = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } +static const struct pinctrl_pin_desc msm8994_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "GPIO_133"), + PINCTRL_PIN(134, "GPIO_134"), + PINCTRL_PIN(135, "GPIO_135"), + PINCTRL_PIN(136, "GPIO_136"), + PINCTRL_PIN(137, "GPIO_137"), + PINCTRL_PIN(138, "GPIO_138"), + PINCTRL_PIN(139, "GPIO_139"), + PINCTRL_PIN(140, "GPIO_140"), + PINCTRL_PIN(141, "GPIO_141"), + PINCTRL_PIN(142, "GPIO_142"), + PINCTRL_PIN(143, "GPIO_143"), + PINCTRL_PIN(144, "GPIO_144"), + PINCTRL_PIN(145, "GPIO_145"), + PINCTRL_PIN(146, "SDC1_RCLK"), + PINCTRL_PIN(147, "SDC1_CLK"), + PINCTRL_PIN(148, "SDC1_CMD"), + PINCTRL_PIN(149, "SDC1_DATA"), + PINCTRL_PIN(150, "SDC2_CLK"), + PINCTRL_PIN(151, "SDC2_CMD"), + PINCTRL_PIN(152, "SDC2_DATA"), + PINCTRL_PIN(153, "SDC3_CLK"), + PINCTRL_PIN(154, "SDC3_CMD"), + PINCTRL_PIN(155, "SDC3_DATA"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); +DECLARE_MSM_GPIO_PINS(133); +DECLARE_MSM_GPIO_PINS(134); +DECLARE_MSM_GPIO_PINS(135); +DECLARE_MSM_GPIO_PINS(136); +DECLARE_MSM_GPIO_PINS(137); +DECLARE_MSM_GPIO_PINS(138); +DECLARE_MSM_GPIO_PINS(139); +DECLARE_MSM_GPIO_PINS(140); +DECLARE_MSM_GPIO_PINS(141); +DECLARE_MSM_GPIO_PINS(142); +DECLARE_MSM_GPIO_PINS(143); +DECLARE_MSM_GPIO_PINS(144); +DECLARE_MSM_GPIO_PINS(145); + +static const unsigned int sdc1_rclk_pins[] = { 146 }; +static const unsigned int sdc1_clk_pins[] = { 147 }; +static const unsigned int sdc1_cmd_pins[] = { 148 }; +static const unsigned int sdc1_data_pins[] = { 149 }; +static const unsigned int sdc2_clk_pins[] = { 150 }; +static const unsigned int sdc2_cmd_pins[] = { 151 }; +static const unsigned int sdc2_data_pins[] = { 152 }; +static const unsigned int sdc3_clk_pins[] = { 153 }; +static const unsigned int sdc3_cmd_pins[] = { 154 }; +static const unsigned int sdc3_data_pins[] = { 155 }; + +enum msm8994_functions { + MSM_MUX_audio_ref_clk, + MSM_MUX_blsp_i2c1, + MSM_MUX_blsp_i2c2, + MSM_MUX_blsp_i2c3, + MSM_MUX_blsp_i2c4, + MSM_MUX_blsp_i2c5, + MSM_MUX_blsp_i2c6, + MSM_MUX_blsp_i2c7, + MSM_MUX_blsp_i2c8, + MSM_MUX_blsp_i2c9, + MSM_MUX_blsp_i2c10, + MSM_MUX_blsp_i2c11, + MSM_MUX_blsp_i2c12, + MSM_MUX_blsp_spi1, + MSM_MUX_blsp_spi1_cs1, + MSM_MUX_blsp_spi1_cs2, + MSM_MUX_blsp_spi1_cs3, + MSM_MUX_blsp_spi2, + MSM_MUX_blsp_spi2_cs1, + MSM_MUX_blsp_spi2_cs2, + MSM_MUX_blsp_spi2_cs3, + MSM_MUX_blsp_spi3, + MSM_MUX_blsp_spi4, + MSM_MUX_blsp_spi5, + MSM_MUX_blsp_spi6, + MSM_MUX_blsp_spi7, + MSM_MUX_blsp_spi8, + MSM_MUX_blsp_spi9, + MSM_MUX_blsp_spi10, + MSM_MUX_blsp_spi10_cs1, + MSM_MUX_blsp_spi10_cs2, + MSM_MUX_blsp_spi10_cs3, + MSM_MUX_blsp_spi11, + MSM_MUX_blsp_spi12, + MSM_MUX_blsp_uart1, + MSM_MUX_blsp_uart2, + MSM_MUX_blsp_uart3, + MSM_MUX_blsp_uart4, + MSM_MUX_blsp_uart5, + MSM_MUX_blsp_uart6, + MSM_MUX_blsp_uart7, + MSM_MUX_blsp_uart8, + MSM_MUX_blsp_uart9, + MSM_MUX_blsp_uart10, + MSM_MUX_blsp_uart11, + MSM_MUX_blsp_uart12, + MSM_MUX_blsp_uim1, + MSM_MUX_blsp_uim2, + MSM_MUX_blsp_uim3, + MSM_MUX_blsp_uim4, + MSM_MUX_blsp_uim5, + MSM_MUX_blsp_uim6, + MSM_MUX_blsp_uim7, + MSM_MUX_blsp_uim8, + MSM_MUX_blsp_uim9, + MSM_MUX_blsp_uim10, + MSM_MUX_blsp_uim11, + MSM_MUX_blsp_uim12, + MSM_MUX_blsp11_i2c_scl_b, + MSM_MUX_blsp11_i2c_sda_b, + MSM_MUX_blsp11_uart_rx_b, + MSM_MUX_blsp11_uart_tx_b, + MSM_MUX_cam_mclk0, + MSM_MUX_cam_mclk1, + MSM_MUX_cam_mclk2, + MSM_MUX_cam_mclk3, + MSM_MUX_cci_async_in0, + MSM_MUX_cci_async_in1, + MSM_MUX_cci_async_in2, + MSM_MUX_cci_i2c0, + MSM_MUX_cci_i2c1, + MSM_MUX_cci_timer0, + MSM_MUX_cci_timer1, + MSM_MUX_cci_timer2, + MSM_MUX_cci_timer3, + MSM_MUX_cci_timer4, + MSM_MUX_gcc_gp1_clk_a, + MSM_MUX_gcc_gp1_clk_b, + MSM_MUX_gcc_gp2_clk_a, + MSM_MUX_gcc_gp2_clk_b, + MSM_MUX_gcc_gp3_clk_a, + MSM_MUX_gcc_gp3_clk_b, + MSM_MUX_gp_mn, + MSM_MUX_gp_pdm0, + MSM_MUX_gp_pdm1, + MSM_MUX_gp_pdm2, + MSM_MUX_gp0_clk, + MSM_MUX_gp1_clk, + MSM_MUX_gps_tx, + MSM_MUX_gsm_tx, + MSM_MUX_hdmi_cec, + MSM_MUX_hdmi_ddc, + MSM_MUX_hdmi_hpd, + MSM_MUX_hdmi_rcv, + MSM_MUX_mdp_vsync, + MSM_MUX_mss_lte, + MSM_MUX_nav_pps, + MSM_MUX_nav_tsync, + MSM_MUX_qdss_cti_trig_in_a, + MSM_MUX_qdss_cti_trig_in_b, + MSM_MUX_qdss_cti_trig_in_c, + MSM_MUX_qdss_cti_trig_in_d, + MSM_MUX_qdss_cti_trig_out_a, + MSM_MUX_qdss_cti_trig_out_b, + MSM_MUX_qdss_cti_trig_out_c, + MSM_MUX_qdss_cti_trig_out_d, + MSM_MUX_qdss_traceclk_a, + MSM_MUX_qdss_traceclk_b, + MSM_MUX_qdss_tracectl_a, + MSM_MUX_qdss_tracectl_b, + MSM_MUX_qdss_tracedata_a, + MSM_MUX_qdss_tracedata_b, + MSM_MUX_qua_mi2s, + MSM_MUX_pci_e0, + MSM_MUX_pci_e1, + MSM_MUX_pri_mi2s, + MSM_MUX_sdc4, + MSM_MUX_sec_mi2s, + MSM_MUX_slimbus, + MSM_MUX_spkr_i2s, + MSM_MUX_ter_mi2s, + MSM_MUX_tsif1, + MSM_MUX_tsif2, + MSM_MUX_uim1, + MSM_MUX_uim2, + MSM_MUX_uim3, + MSM_MUX_uim4, + MSM_MUX_uim_batt_alarm, + MSM_MUX_gpio, + MSM_MUX_NA, +}; + +static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84", + "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91", + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", + "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", + "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", + "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122", + "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128", + "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134", + "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140", + "gpio141", "gpio142", "gpio143", "gpio144", "gpio145", +}; + +static const char * const blsp_spi1_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3" +}; +static const char * const blsp_uart1_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3" +}; +static const char * const blsp_uim1_groups[] = { + "gpio0", "gpio1" +}; +static const char * const hdmi_rcv_groups[] = { + "gpio0" +}; +static const char * const blsp_i2c1_groups[] = { + "gpio2", "gpio3" +}; +static const char * const blsp_spi2_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7" +}; +static const char * const blsp_uart2_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7" +}; +static const char * const blsp_uim2_groups[] = { + "gpio4", "gpio5" +}; +static const char * const qdss_cti_trig_out_b_groups[] = { + "gpio4", +}; +static const char * const qdss_cti_trig_in_b_groups[] = { + "gpio5", +}; +static const char * const blsp_i2c2_groups[] = { + "gpio6", "gpio7" +}; +static const char * const blsp_spi3_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11" +}; +static const char * const blsp_uart3_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11" +}; +static const char * const blsp_uim3_groups[] = { + "gpio8", "gpio9" +}; +static const char * const blsp_spi1_cs1_groups[] = { + "gpio8" +}; +static const char * const blsp_spi1_cs2_groups[] = { + "gpio9", "gpio11" +}; +static const char * const mdp_vsync_groups[] = { + "gpio10", "gpio11", "gpio12" +}; +static const char * const blsp_i2c3_groups[] = { + "gpio10", "gpio11" +}; +static const char * const blsp_spi1_cs3_groups[] = { + "gpio10" +}; +static const char * const qdss_tracedata_b_groups[] = { + "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", + "gpio19", "gpio21", "gpio22", "gpio23", "gpio25", "gpio26", + "gpio57", "gpio58", "gpio92", "gpio93", +}; +static const char * const cam_mclk0_groups[] = { + "gpio13" +}; +static const char * const cam_mclk1_groups[] = { + "gpio14" +}; +static const char * const cam_mclk2_groups[] = { + "gpio15" +}; +static const char * const cam_mclk3_groups[] = { + "gpio16" +}; +static const char * const cci_i2c0_groups[] = { + "gpio17", "gpio18" +}; +static const char * const blsp_spi4_groups[] = { + "gpio17", "gpio18", "gpio19", "gpio20" +}; +static const char * const blsp_uart4_groups[] = { + "gpio17", "gpio18", "gpio19", "gpio20" +}; +static const char * const blsp_uim4_groups[] = { + "gpio17", "gpio18" +}; +static const char * const cci_i2c1_groups[] = { + "gpio19", "gpio20" +}; +static const char * const blsp_i2c4_groups[] = { + "gpio19", "gpio20" +}; +static const char * const cci_timer0_groups[] = { + "gpio21" +}; +static const char * const blsp_spi5_groups[] = { + "gpio21", "gpio22", "gpio23", "gpio24" +}; +static const char * const blsp_uart5_groups[] = { + "gpio21", "gpio22", "gpio23", "gpio24" +}; +static const char * const blsp_uim5_groups[] = { + "gpio21", "gpio22" +}; +static const char * const cci_timer1_groups[] = { + "gpio22" +}; +static const char * const cci_timer2_groups[] = { + "gpio23" +}; +static const char * const blsp_i2c5_groups[] = { + "gpio23", "gpio24" +}; +static const char * const cci_timer3_groups[] = { + "gpio24" +}; +static const char * const cci_async_in1_groups[] = { + "gpio24" +}; +static const char * const cci_timer4_groups[] = { + "gpio25" +}; +static const char * const cci_async_in2_groups[] = { + "gpio25" +}; +static const char * const blsp_spi6_groups[] = { + "gpio25", "gpio26", "gpio27", "gpio28" +}; +static const char * const blsp_uart6_groups[] = { + "gpio25", "gpio26", "gpio27", "gpio28" +}; +static const char * const blsp_uim6_groups[] = { + "gpio25", "gpio26" +}; +static const char * const cci_async_in0_groups[] = { + "gpio26" +}; +static const char * const gp0_clk_groups[] = { + "gpio26" +}; +static const char * const gp1_clk_groups[] = { + "gpio27", "gpio57", "gpio78" +}; +static const char * const blsp_i2c6_groups[] = { + "gpio27", "gpio28" +}; +static const char * const qdss_tracectl_a_groups[] = { + "gpio27", +}; +static const char * const qdss_traceclk_a_groups[] = { + "gpio28", +}; +static const char * const gp_mn_groups[] = { + "gpio29" +}; +static const char * const hdmi_cec_groups[] = { + "gpio31" +}; +static const char * const hdmi_ddc_groups[] = { + "gpio32", "gpio33" +}; +static const char * const hdmi_hpd_groups[] = { + "gpio34" +}; +static const char * const uim3_groups[] = { + "gpio35", "gpio36", "gpio37", "gpio38" +}; +static const char * const pci_e1_groups[] = { + "gpio35", "gpio36", +}; +static const char * const blsp_spi7_groups[] = { + "gpio41", "gpio42", "gpio43", "gpio44" +}; +static const char * const blsp_uart7_groups[] = { + "gpio41", "gpio42", "gpio43", "gpio44" +}; +static const char * const blsp_uim7_groups[] = { + "gpio41", "gpio42" +}; +static const char * const qdss_cti_trig_out_c_groups[] = { + "gpio41", +}; +static const char * const qdss_cti_trig_in_c_groups[] = { + "gpio42", +}; +static const char * const blsp_i2c7_groups[] = { + "gpio43", "gpio44" +}; +static const char * const blsp_spi8_groups[] = { + "gpio45", "gpio46", "gpio47", "gpio48" +}; +static const char * const blsp_uart8_groups[] = { + "gpio45", "gpio46", "gpio47", "gpio48" +}; +static const char * const blsp_uim8_groups[] = { + "gpio45", "gpio46" +}; +static const char * const blsp_i2c8_groups[] = { + "gpio47", "gpio48" +}; +static const char * const blsp_spi10_cs1_groups[] = { + "gpio47", "gpio67" +}; +static const char * const blsp_spi10_cs2_groups[] = { + "gpio48", "gpio68" +}; +static const char * const uim2_groups[] = { + "gpio49", "gpio50", "gpio51", "gpio52" +}; +static const char * const blsp_spi9_groups[] = { + "gpio49", "gpio50", "gpio51", "gpio52" +}; +static const char * const blsp_uart9_groups[] = { + "gpio49", "gpio50", "gpio51", "gpio52" +}; +static const char * const blsp_uim9_groups[] = { + "gpio49", "gpio50" +}; +static const char * const blsp_i2c9_groups[] = { + "gpio51", "gpio52" +}; +static const char * const pci_e0_groups[] = { + "gpio53", "gpio54", +}; +static const char * const uim4_groups[] = { + "gpio53", "gpio54", "gpio55", "gpio56" +}; +static const char * const blsp_spi10_groups[] = { + "gpio53", "gpio54", "gpio55", "gpio56" +}; +static const char * const blsp_uart10_groups[] = { + "gpio53", "gpio54", "gpio55", "gpio56" +}; +static const char * const blsp_uim10_groups[] = { + "gpio53", "gpio54" +}; +static const char * const qdss_tracedata_a_groups[] = { + "gpio53", "gpio54", "gpio63", "gpio64", "gpio65", + "gpio66", "gpio67", "gpio74", "gpio75", "gpio76", + "gpio77", "gpio85", "gpio86", "gpio87", "gpio89", + "gpio90" +}; +static const char * const gp_pdm0_groups[] = { + "gpio54", "gpio95" +}; +static const char * const blsp_i2c10_groups[] = { + "gpio55", "gpio56" +}; +static const char * const qdss_cti_trig_in_a_groups[] = { + "gpio55", +}; +static const char * const qdss_cti_trig_out_a_groups[] = { + "gpio56", +}; +static const char * const qua_mi2s_groups[] = { + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", +}; +static const char * const gcc_gp1_clk_a_groups[] = { + "gpio57" +}; +static const char * const gcc_gp2_clk_a_groups[] = { + "gpio58" +}; +static const char * const gcc_gp3_clk_a_groups[] = { + "gpio59" +}; +static const char * const blsp_spi2_cs1_groups[] = { + "gpio62" +}; +static const char * const blsp_spi2_cs2_groups[] = { + "gpio63" +}; +static const char * const gp_pdm2_groups[] = { + "gpio63", "gpio79" +}; +static const char * const pri_mi2s_groups[] = { + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68" +}; +static const char * const blsp_spi2_cs3_groups[] = { + "gpio66" +}; +static const char * const spkr_i2s_groups[] = { + "gpio69", "gpio70", "gpio71", "gpio72" +}; +static const char * const audio_ref_clk_groups[] = { + "gpio69" +}; +static const char * const slimbus_groups[] = { + "gpio70", "gpio71" +}; +static const char * const ter_mi2s_groups[] = { + "gpio73", "gpio74", "gpio75", "gpio76", "gpio77" +}; +static const char * const gp_pdm1_groups[] = { + "gpio74", "gpio86" +}; +static const char * const sec_mi2s_groups[] = { + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82" +}; +static const char * const gcc_gp1_clk_b_groups[] = { + "gpio78" +}; +static const char * const blsp_spi11_groups[] = { + "gpio81", "gpio82", "gpio83", "gpio84" +}; +static const char * const blsp_uart11_groups[] = { + "gpio81", "gpio82", "gpio83", "gpio84" +}; +static const char * const blsp_uim11_groups[] = { + "gpio81", "gpio82" +}; +static const char * const gcc_gp2_clk_b_groups[] = { + "gpio81" +}; +static const char * const gcc_gp3_clk_b_groups[] = { + "gpio82" +}; +static const char * const blsp_i2c11_groups[] = { + "gpio83", "gpio84" +}; +static const char * const blsp_uart12_groups[] = { + "gpio85", "gpio86", "gpio87", "gpio88" +}; +static const char * const blsp_uim12_groups[] = { + "gpio85", "gpio86" +}; +static const char * const blsp_i2c12_groups[] = { + "gpio87", "gpio88" +}; +static const char * const blsp_spi12_groups[] = { + "gpio85", "gpio86", "gpio87", "gpio88" +}; +static const char * const tsif1_groups[] = { + "gpio89", "gpio90", "gpio91", "gpio110", "gpio111" +}; +static const char * const blsp_spi10_cs3_groups[] = { + "gpio90" +}; +static const char * const sdc4_groups[] = { + "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96" +}; +static const char * const qdss_traceclk_b_groups[] = { + "gpio91", +}; +static const char * const tsif2_groups[] = { + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96" +}; +static const char * const qdss_tracectl_b_groups[] = { + "gpio94", +}; +static const char * const qdss_cti_trig_out_d_groups[] = { + "gpio95", +}; +static const char * const qdss_cti_trig_in_d_groups[] = { + "gpio96", +}; +static const char * const uim1_groups[] = { + "gpio97", "gpio98", "gpio99", "gpio100" +}; +static const char * const uim_batt_alarm_groups[] = { + "gpio101" +}; +static const char * const blsp11_uart_tx_b_groups[] = { + "gpio111" +}; +static const char * const blsp11_uart_rx_b_groups[] = { + "gpio112" +}; +static const char * const blsp11_i2c_sda_b_groups[] = { + "gpio113" +}; +static const char * const blsp11_i2c_scl_b_groups[] = { + "gpio114" +}; +static const char * const gsm_tx_groups[] = { + "gpio126", "gpio131", "gpio132", "gpio133" +}; +static const char * const nav_tsync_groups[] = { + "gpio127" +}; +static const char * const nav_pps_groups[] = { + "gpio127" +}; +static const char * const gps_tx_groups[] = { + "gpio130" +}; +static const char * const mss_lte_groups[] = { + "gpio134", "gpio135" +}; + +static const struct msm_function msm8994_functions[] = { + FUNCTION(audio_ref_clk), + FUNCTION(blsp_i2c1), + FUNCTION(blsp_i2c2), + FUNCTION(blsp_i2c3), + FUNCTION(blsp_i2c4), + FUNCTION(blsp_i2c5), + FUNCTION(blsp_i2c6), + FUNCTION(blsp_i2c7), + FUNCTION(blsp_i2c8), + FUNCTION(blsp_i2c9), + FUNCTION(blsp_i2c10), + FUNCTION(blsp_i2c11), + FUNCTION(blsp_i2c12), + FUNCTION(blsp_spi1), + FUNCTION(blsp_spi1_cs1), + FUNCTION(blsp_spi1_cs2), + FUNCTION(blsp_spi1_cs3), + FUNCTION(blsp_spi2), + FUNCTION(blsp_spi2_cs1), + FUNCTION(blsp_spi2_cs2), + FUNCTION(blsp_spi2_cs3), + FUNCTION(blsp_spi3), + FUNCTION(blsp_spi4), + FUNCTION(blsp_spi5), + FUNCTION(blsp_spi6), + FUNCTION(blsp_spi7), + FUNCTION(blsp_spi8), + FUNCTION(blsp_spi9), + FUNCTION(blsp_spi10), + FUNCTION(blsp_spi10_cs1), + FUNCTION(blsp_spi10_cs2), + FUNCTION(blsp_spi10_cs3), + FUNCTION(blsp_spi11), + FUNCTION(blsp_spi12), + FUNCTION(blsp_uart1), + FUNCTION(blsp_uart2), + FUNCTION(blsp_uart3), + FUNCTION(blsp_uart4), + FUNCTION(blsp_uart5), + FUNCTION(blsp_uart6), + FUNCTION(blsp_uart7), + FUNCTION(blsp_uart8), + FUNCTION(blsp_uart9), + FUNCTION(blsp_uart10), + FUNCTION(blsp_uart11), + FUNCTION(blsp_uart12), + FUNCTION(blsp_uim1), + FUNCTION(blsp_uim2), + FUNCTION(blsp_uim3), + FUNCTION(blsp_uim4), + FUNCTION(blsp_uim5), + FUNCTION(blsp_uim6), + FUNCTION(blsp_uim7), + FUNCTION(blsp_uim8), + FUNCTION(blsp_uim9), + FUNCTION(blsp_uim10), + FUNCTION(blsp_uim11), + FUNCTION(blsp_uim12), + FUNCTION(blsp11_i2c_scl_b), + FUNCTION(blsp11_i2c_sda_b), + FUNCTION(blsp11_uart_rx_b), + FUNCTION(blsp11_uart_tx_b), + FUNCTION(cam_mclk0), + FUNCTION(cam_mclk1), + FUNCTION(cam_mclk2), + FUNCTION(cam_mclk3), + FUNCTION(cci_async_in0), + FUNCTION(cci_async_in1), + FUNCTION(cci_async_in2), + FUNCTION(cci_i2c0), + FUNCTION(cci_i2c1), + FUNCTION(cci_timer0), + FUNCTION(cci_timer1), + FUNCTION(cci_timer2), + FUNCTION(cci_timer3), + FUNCTION(cci_timer4), + FUNCTION(gcc_gp1_clk_a), + FUNCTION(gcc_gp1_clk_b), + FUNCTION(gcc_gp2_clk_a), + FUNCTION(gcc_gp2_clk_b), + FUNCTION(gcc_gp3_clk_a), + FUNCTION(gcc_gp3_clk_b), + FUNCTION(gp_mn), + FUNCTION(gp_pdm0), + FUNCTION(gp_pdm1), + FUNCTION(gp_pdm2), + FUNCTION(gp0_clk), + FUNCTION(gp1_clk), + FUNCTION(gps_tx), + FUNCTION(gsm_tx), + FUNCTION(hdmi_cec), + FUNCTION(hdmi_ddc), + FUNCTION(hdmi_hpd), + FUNCTION(hdmi_rcv), + FUNCTION(mdp_vsync), + FUNCTION(mss_lte), + FUNCTION(nav_pps), + FUNCTION(nav_tsync), + FUNCTION(qdss_cti_trig_in_a), + FUNCTION(qdss_cti_trig_in_b), + FUNCTION(qdss_cti_trig_in_c), + FUNCTION(qdss_cti_trig_in_d), + FUNCTION(qdss_cti_trig_out_a), + FUNCTION(qdss_cti_trig_out_b), + FUNCTION(qdss_cti_trig_out_c), + FUNCTION(qdss_cti_trig_out_d), + FUNCTION(qdss_traceclk_a), + FUNCTION(qdss_traceclk_b), + FUNCTION(qdss_tracectl_a), + FUNCTION(qdss_tracectl_b), + FUNCTION(qdss_tracedata_a), + FUNCTION(qdss_tracedata_b), + FUNCTION(qua_mi2s), + FUNCTION(pci_e0), + FUNCTION(pci_e1), + FUNCTION(pri_mi2s), + FUNCTION(sdc4), + FUNCTION(sec_mi2s), + FUNCTION(slimbus), + FUNCTION(spkr_i2s), + FUNCTION(ter_mi2s), + FUNCTION(tsif1), + FUNCTION(tsif2), + FUNCTION(uim_batt_alarm), + FUNCTION(uim1), + FUNCTION(uim2), + FUNCTION(uim3), + FUNCTION(uim4), + FUNCTION(gpio), +}; + +static const struct msm_pingroup msm8994_groups[] = { + PINGROUP(0, blsp_spi1, blsp_uart1, blsp_uim1, hdmi_rcv, NA, NA, NA, + NA, NA, NA, NA), + PINGROUP(1, blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(2, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(3, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(4, blsp_spi2, blsp_uart2, blsp_uim2, NA, qdss_cti_trig_out_b, + NA, NA, NA, NA, NA, NA), + PINGROUP(5, blsp_spi2, blsp_uart2, blsp_uim2, NA, qdss_cti_trig_in_b, + NA, NA, NA, NA, NA, NA), + PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(8, blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs1, NA, NA, + NA, NA, NA, NA, NA), + PINGROUP(9, blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs2, NA, NA, + NA, NA, NA, NA, NA), + PINGROUP(10, mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3, + blsp_spi1_cs3, NA, NA, NA, NA, NA, NA), + PINGROUP(11, mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3, + blsp_spi1_cs2, NA, NA, NA, NA, NA, NA), + PINGROUP(12, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(13, cam_mclk0, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(14, cam_mclk1, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(15, cam_mclk2, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(16, cam_mclk3, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(17, cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(18, cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(19, cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(20, cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, + NA, NA, NA, NA), + PINGROUP(21, cci_timer0, blsp_spi5, blsp_uart5, blsp_uim5, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(22, cci_timer1, blsp_spi5, blsp_uart5, blsp_uim5, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(23, cci_timer2, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA, + qdss_tracedata_b, NA, NA, NA, NA), + PINGROUP(24, cci_timer3, cci_async_in1, blsp_spi5, blsp_uart5, + blsp_i2c5, NA, NA, NA, NA, NA, NA), + PINGROUP(25, cci_timer4, cci_async_in2, blsp_spi6, blsp_uart6, + blsp_uim6, NA, NA, qdss_tracedata_b, NA, NA, NA), + PINGROUP(26, cci_async_in0, blsp_spi6, blsp_uart6, blsp_uim6, gp0_clk, + NA, qdss_tracedata_b, NA, NA, NA, NA), + PINGROUP(27, blsp_spi6, blsp_uart6, blsp_i2c6, gp1_clk, + qdss_tracectl_a, NA, NA, NA, NA, NA, NA), + PINGROUP(28, blsp_spi6, blsp_uart6, blsp_i2c6, qdss_traceclk_a, NA, + NA, NA, NA, NA, NA, NA), + PINGROUP(29, gp_mn, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(30, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(31, hdmi_cec, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(32, hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(33, hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(34, hdmi_hpd, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(35, uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(36, uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(37, uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(38, uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(39, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(40, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(41, blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_out_c, + NA, NA, NA, NA, NA, NA, NA), + PINGROUP(42, blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_in_c, NA, + NA, NA, NA, NA, NA, NA), + PINGROUP(43, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(44, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(45, blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(46, blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(47, blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs1, NA, NA, + NA, NA, NA, NA, NA), + PINGROUP(48, blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs2, NA, NA, + NA, NA, NA, NA, NA), + PINGROUP(49, uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(50, uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(51, uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(52, uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(53, uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10, NA, + NA, qdss_tracedata_a, NA, NA, NA), + PINGROUP(54, uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10, + gp_pdm0, NA, NA, qdss_tracedata_a, NA, NA), + PINGROUP(55, uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA, + qdss_cti_trig_in_a, NA, NA, NA), + PINGROUP(56, uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, + qdss_cti_trig_out_a, NA, NA, NA, NA), + PINGROUP(57, qua_mi2s, gcc_gp1_clk_a, NA, NA, qdss_tracedata_b, NA, NA, + NA, NA, NA, NA), + PINGROUP(58, qua_mi2s, gcc_gp2_clk_a, NA, NA, qdss_tracedata_b, NA, NA, + NA, NA, NA, NA), + PINGROUP(59, qua_mi2s, gcc_gp3_clk_a, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(60, qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(61, qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(62, qua_mi2s, blsp_spi2_cs1, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(63, qua_mi2s, blsp_spi2_cs2, gp_pdm2, NA, NA, NA, NA, NA, + qdss_tracedata_a, NA, NA), + PINGROUP(64, pri_mi2s, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, + NA, NA), + PINGROUP(65, pri_mi2s, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, + NA, NA), + PINGROUP(66, pri_mi2s, blsp_spi2_cs3, NA, NA, NA, qdss_tracedata_a, + NA, NA, NA, NA, NA), + PINGROUP(67, pri_mi2s, blsp_spi10_cs1, NA, NA, NA, qdss_tracedata_a, + NA, NA, NA, NA, NA), + PINGROUP(68, pri_mi2s, blsp_spi10_cs2, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(69, spkr_i2s, audio_ref_clk, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(70, slimbus, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(71, slimbus, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(72, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(73, ter_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(74, ter_mi2s, gp_pdm1, NA, NA, NA, qdss_tracedata_a, NA, NA, + NA, NA, NA), + PINGROUP(75, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(76, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(77, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(78, sec_mi2s, gcc_gp1_clk_b, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(79, sec_mi2s, gp_pdm2, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(80, sec_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(81, sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11, + gcc_gp2_clk_b, NA, NA, NA, NA, NA, NA), + PINGROUP(82, sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11, + gcc_gp3_clk_b, NA, NA, NA, NA, NA, NA), + PINGROUP(83, blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(84, blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(85, blsp_spi12, blsp_uart12, blsp_uim12, NA, NA, + qdss_tracedata_a, NA, NA, NA, NA, NA), + PINGROUP(86, blsp_spi12, blsp_uart12, blsp_uim12, gp_pdm1, NA, + qdss_tracedata_a, NA, NA, NA, NA, NA), + PINGROUP(87, blsp_spi12, blsp_uart12, blsp_i2c12, NA, + qdss_tracedata_a, NA, NA, NA, NA, NA, NA), + PINGROUP(88, blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(89, tsif1, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(90, tsif1, blsp_spi10_cs3, qdss_tracedata_a, NA, NA, NA, NA, + NA, NA, NA, NA), + PINGROUP(91, tsif1, sdc4, NA, NA, NA, NA, qdss_traceclk_b, NA, NA, NA, + NA), + PINGROUP(92, tsif2, sdc4, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, + NA, NA), + PINGROUP(93, tsif2, sdc4, NA, NA, NA, NA, qdss_tracedata_b, NA, NA, + NA, NA), + PINGROUP(94, tsif2, sdc4, NA, NA, NA, NA, qdss_tracectl_b, NA, NA, NA, + NA), + PINGROUP(95, tsif2, sdc4, gp_pdm0, NA, NA, NA, qdss_cti_trig_out_d, + NA, NA, NA, NA), + PINGROUP(96, tsif2, sdc4, qdss_cti_trig_in_d, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(97, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(98, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(99, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(100, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(101, uim_batt_alarm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(102, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(108, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(110, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(111, tsif1, blsp11_uart_tx_b, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(112, blsp11_uart_rx_b, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(113, blsp11_i2c_sda_b, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(114, blsp11_i2c_scl_b, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(115, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(116, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(118, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(119, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(120, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(121, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(122, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(123, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(124, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(125, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(126, NA, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(127, NA, nav_tsync, nav_pps, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(128, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(129, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(130, gps_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(131, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(132, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(133, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(134, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(135, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(136, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(137, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(138, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(139, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(140, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(141, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(142, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(143, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(144, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(145, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + SDC_PINGROUP(sdc1_rclk, 0x2044, 15, 0), + SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6), + SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3), + SDC_PINGROUP(sdc1_data, 0x2044, 9, 0), + SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6), + SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3), + SDC_PINGROUP(sdc2_data, 0x2048, 9, 0), + SDC_PINGROUP(sdc3_clk, 0x206c, 14, 6), + SDC_PINGROUP(sdc3_cmd, 0x206c, 11, 3), + SDC_PINGROUP(sdc3_data, 0x206c, 9, 0), +}; + +#define NUM_GPIO_PINGROUPS 146 + +static const struct msm_pinctrl_soc_data msm8994_pinctrl = { + .pins = msm8994_pins, + .npins = ARRAY_SIZE(msm8994_pins), + .functions = msm8994_functions, + .nfunctions = ARRAY_SIZE(msm8994_functions), + .groups = msm8994_groups, + .ngroups = ARRAY_SIZE(msm8994_groups), + .ngpios = NUM_GPIO_PINGROUPS, +}; + +static int msm8994_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &msm8994_pinctrl); +} + +static const struct of_device_id msm8994_pinctrl_of_match[] = { + { .compatible = "qcom,msm8992-pinctrl", }, + { .compatible = "qcom,msm8994-pinctrl", }, + { } +}; + +static struct platform_driver msm8994_pinctrl_driver = { + .driver = { + .name = "msm8994-pinctrl", + .of_match_table = msm8994_pinctrl_of_match, + }, + .probe = msm8994_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init msm8994_pinctrl_init(void) +{ + return platform_driver_register(&msm8994_pinctrl_driver); +} +arch_initcall(msm8994_pinctrl_init); + +static void __exit msm8994_pinctrl_exit(void) +{ + platform_driver_unregister(&msm8994_pinctrl_driver); +} +module_exit(msm8994_pinctrl_exit); + +MODULE_DESCRIPTION("Qualcomm MSM8994 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, msm8994_pinctrl_of_match); -- cgit v1.2.3 From f9eb69d1ae2f82b0e556852bf719f550c2a34193 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Mon, 31 Oct 2016 21:39:48 +0100 Subject: rtc: jz4740: Add support for acting as the system power controller The 'system-power-controller' singleton entry can be used in the devicetree node of the jz4740-rtc driver to specify that the driver is granted the right to power off the system through the registers of the RTC unit. See the documentation for more details: Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt Signed-off-by: Paul Cercueil Acked-by: Maarten ter Huurne Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-jz4740.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index c2895cec56b4..33ccd73ee947 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -14,11 +14,13 @@ * */ +#include #include #include #include #include #include +#include #include #include #include @@ -28,6 +30,8 @@ #define JZ_REG_RTC_SEC_ALARM 0x08 #define JZ_REG_RTC_REGULATOR 0x0C #define JZ_REG_RTC_HIBERNATE 0x20 +#define JZ_REG_RTC_WAKEUP_FILTER 0x24 +#define JZ_REG_RTC_RESET_COUNTER 0x28 #define JZ_REG_RTC_SCRATCHPAD 0x34 /* The following are present on the jz4780 */ @@ -45,6 +49,9 @@ /* Magic value to enable writes on jz4780 */ #define JZ_RTC_WENR_MAGIC 0xA55A +#define JZ_RTC_WAKEUP_FILTER_MASK 0x0000FFE0 +#define JZ_RTC_RESET_COUNTER_MASK 0x00000FE0 + enum jz4740_rtc_type { ID_JZ4740, ID_JZ4780, @@ -55,12 +62,18 @@ struct jz4740_rtc { enum jz4740_rtc_type type; struct rtc_device *rtc; + struct clk *clk; int irq; spinlock_t lock; + + unsigned int min_wakeup_pin_assert_time; + unsigned int reset_pin_assert_time; }; +static struct device *dev_for_power_off; + static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) { return readl(rtc->base + reg); @@ -246,6 +259,46 @@ void jz4740_rtc_poweroff(struct device *dev) } EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); +static void jz4740_rtc_power_off(void) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev_for_power_off); + unsigned long rtc_rate; + unsigned long wakeup_filter_ticks; + unsigned long reset_counter_ticks; + + clk_prepare_enable(rtc->clk); + + rtc_rate = clk_get_rate(rtc->clk); + + /* + * Set minimum wakeup pin assertion time: 100 ms. + * Range is 0 to 2 sec if RTC is clocked at 32 kHz. + */ + wakeup_filter_ticks = + (rtc->min_wakeup_pin_assert_time * rtc_rate) / 1000; + if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK) + wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK; + else + wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK; + jz4740_rtc_reg_write(rtc, + JZ_REG_RTC_WAKEUP_FILTER, wakeup_filter_ticks); + + /* + * Set reset pin low-level assertion time after wakeup: 60 ms. + * Range is 0 to 125 ms if RTC is clocked at 32 kHz. + */ + reset_counter_ticks = (rtc->reset_pin_assert_time * rtc_rate) / 1000; + if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK) + reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK; + else + reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK; + jz4740_rtc_reg_write(rtc, + JZ_REG_RTC_RESET_COUNTER, reset_counter_ticks); + + jz4740_rtc_poweroff(dev_for_power_off); + machine_halt(); +} + static const struct of_device_id jz4740_rtc_of_match[] = { { .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 }, { .compatible = "ingenic,jz4780-rtc", .data = (void *)ID_JZ4780 }, @@ -262,6 +315,7 @@ static int jz4740_rtc_probe(struct platform_device *pdev) const struct platform_device_id *id = platform_get_device_id(pdev); const struct of_device_id *of_id = of_match_device( jz4740_rtc_of_match, &pdev->dev); + struct device_node *np = pdev->dev.of_node; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) @@ -283,6 +337,12 @@ static int jz4740_rtc_probe(struct platform_device *pdev) if (IS_ERR(rtc->base)) return PTR_ERR(rtc->base); + rtc->clk = devm_clk_get(&pdev->dev, "rtc"); + if (IS_ERR(rtc->clk)) { + dev_err(&pdev->dev, "Failed to get RTC clock\n"); + return PTR_ERR(rtc->clk); + } + spin_lock_init(&rtc->lock); platform_set_drvdata(pdev, rtc); @@ -314,6 +374,27 @@ static int jz4740_rtc_probe(struct platform_device *pdev) } } + if (np && of_device_is_system_power_controller(np)) { + if (!pm_power_off) { + /* Default: 60ms */ + rtc->reset_pin_assert_time = 60; + of_property_read_u32(np, "reset-pin-assert-time-ms", + &rtc->reset_pin_assert_time); + + /* Default: 100ms */ + rtc->min_wakeup_pin_assert_time = 100; + of_property_read_u32(np, + "min-wakeup-pin-assert-time-ms", + &rtc->min_wakeup_pin_assert_time); + + dev_for_power_off = &pdev->dev; + pm_power_off = jz4740_rtc_power_off; + } else { + dev_warn(&pdev->dev, + "Poweroff handler already present!\n"); + } + } + return 0; } -- cgit v1.2.3 From 959df7778bbd3003fe2ade67e3b41ecb5e0ca25d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 2 Oct 2016 22:58:16 +0200 Subject: rtc: Enable compile testing for Maxim and Samsung drivers max8907, max77686 and s5m RTC drivers can be compile tested to increase build coverage. The s5m-rtc uses REGMAP_IRQ so add this as explicit dependency. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 1d0ae30e9927..4259ce61c31b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -303,7 +303,7 @@ config RTC_DRV_MAX6900 config RTC_DRV_MAX8907 tristate "Maxim MAX8907" - depends on MFD_MAX8907 + depends on MFD_MAX8907 || COMPILE_TEST help If you say yes here you will get support for the RTC of Maxim MAX8907 PMIC. @@ -343,7 +343,7 @@ config RTC_DRV_MAX8997 config RTC_DRV_MAX77686 tristate "Maxim MAX77686" - depends on MFD_MAX77686 || MFD_MAX77620 + depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST help If you say yes here you will get support for the RTC of Maxim MAX77686/MAX77620/MAX77802 PMIC. @@ -602,7 +602,8 @@ config RTC_DRV_RV8803 config RTC_DRV_S5M tristate "Samsung S2M/S5M series" - depends on MFD_SEC_CORE + depends on MFD_SEC_CORE || COMPILE_TEST + select REGMAP_IRQ help If you say yes here you will get support for the RTC of Samsung S2MPS14 and S5M PMIC series. -- cgit v1.2.3 From 3a62234680d86efa0239665ed8a0e908f1aef147 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 4 Nov 2016 15:58:38 -0700 Subject: drm/vc4: Use runtime autosuspend to avoid thrashing V3D power state. The pm_runtime_put() we were using immediately released power on the device, which meant that we were generally turning the device off and on once per frame. In many profiles I've looked at, that added up to about 1% of CPU time, but this could get worse in the case of frequent rendering and readback (as may happen in X rendering). By keeping the device on until we've been idle for a couple of frames, we drop the overhead of runtime PM down to sub-.1%. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_drv.c | 9 ++++++--- drivers/gpu/drm/vc4/vc4_gem.c | 6 ++++-- drivers/gpu/drm/vc4/vc4_v3d.c | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index b087404c2784..7abfe088f2d1 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -61,21 +61,24 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, if (ret < 0) return ret; args->value = V3D_READ(V3D_IDENT0); - pm_runtime_put(&vc4->v3d->pdev->dev); + pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); + pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); break; case DRM_VC4_PARAM_V3D_IDENT1: ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); if (ret < 0) return ret; args->value = V3D_READ(V3D_IDENT1); - pm_runtime_put(&vc4->v3d->pdev->dev); + pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); + pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); break; case DRM_VC4_PARAM_V3D_IDENT2: ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); if (ret < 0) return ret; args->value = V3D_READ(V3D_IDENT2); - pm_runtime_put(&vc4->v3d->pdev->dev); + pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); + pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); break; case DRM_VC4_PARAM_SUPPORTS_BRANCHES: case DRM_VC4_PARAM_SUPPORTS_ETC1: diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 303f23c96220..db920771bfb5 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -709,8 +709,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) } mutex_lock(&vc4->power_lock); - if (--vc4->power_refcount == 0) - pm_runtime_put(&vc4->v3d->pdev->dev); + if (--vc4->power_refcount == 0) { + pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); + pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); + } mutex_unlock(&vc4->power_lock); kfree(exec); diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index e6d3c6028341..7cc346ad9b0b 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -222,6 +222,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) return ret; } + pm_runtime_use_autosuspend(dev); + pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ pm_runtime_enable(dev); return 0; -- cgit v1.2.3 From 0c1b7de4f33f64665c45a15980a02582740034ff Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Wed, 21 Sep 2016 20:21:52 -0400 Subject: ixgbe: Add X552 iXFI configuration helper function X553 doesn't need all the initialization that X552 did for iXFI. This patch will allow native SPI SFP+ to work with X553 devices. Future patches will add additional configuration as needed. Signed-off-by: Don Skidmore Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 86 ++++++++++++++++----------- 1 file changed, 52 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 7e6b9267ca9d..3e3458e29934 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1128,47 +1128,17 @@ out: return ret; } -/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. +/** + * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration * @hw: pointer to hardware structure - * @speed: the link speed to force * - * Configures the integrated KR PHY to use iXFI mode. Used to connect an - * internal and external PHY at a specific speed, without autonegotiation. + * iXfI configuration needed for ixgbe_mac_X550EM_x devices. **/ -static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) +static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) { s32 status; u32 reg_val; - /* Disable AN and force speed to 10G Serial. */ - status = ixgbe_read_iosf_sb_reg_x550(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); - if (status) - return status; - - reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; - reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; - - /* Select forced link speed for internal PHY. */ - switch (*speed) { - case IXGBE_LINK_SPEED_10GB_FULL: - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; - break; - case IXGBE_LINK_SPEED_1GB_FULL: - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; - break; - default: - /* Other link speeds are not supported by internal KR PHY. */ - return IXGBE_ERR_LINK_SETUP; - } - - status = ixgbe_write_iosf_sb_reg_x550(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); - if (status) - return status; - /* Disable training protocol FSM. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), @@ -1228,9 +1198,57 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + return status; +} + +/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. + * @hw: pointer to hardware structure + * @speed: the link speed to force + * + * Configures the integrated KR PHY to use iXFI mode. Used to connect an + * internal and external PHY at a specific speed, without autonegotiation. + **/ +static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) +{ + s32 status; + u32 reg_val; + + /* Disable AN and force speed to 10G Serial. */ + status = ixgbe_read_iosf_sb_reg_x550(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + if (status) + return status; + + reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; + reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; + + /* Select forced link speed for internal PHY. */ + switch (*speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; + break; + default: + /* Other link speeds are not supported by internal KR PHY. */ + return IXGBE_ERR_LINK_SETUP; + } + + status = ixgbe_write_iosf_sb_reg_x550(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status) return status; + /* Additional configuration needed for x550em_x */ + if (hw->mac.type == ixgbe_mac_X550EM_x) { + status = ixgbe_setup_ixfi_x550em_x(hw); + if (status) + return status; + } + /* Toggle port SW reset by AN reset. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -- cgit v1.2.3 From 805cedd663549bfc74dbbc5dca73810df0589396 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 20 Oct 2016 21:42:00 -0400 Subject: ixgbe: Add support to retrieve and store LED link active This patch adds support to get the LED link active via the LEDCTL register. If the LEDCTL register does not have LED link active (LED mode field = 0x0100) set then default LED link active returned. Signed-off-by: Don Skidmore Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 46 ++++++++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 4 +-- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 3 ++ 8 files changed, 57 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index fb51be74dd4c..506e346f50a0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -1179,6 +1179,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = { .get_link_capabilities = &ixgbe_get_link_capabilities_82598, .led_on = &ixgbe_led_on_generic, .led_off = &ixgbe_led_off_generic, + .init_led_link_act = ixgbe_init_led_link_act_generic, .blink_led_start = &ixgbe_blink_led_start_generic, .blink_led_stop = &ixgbe_blink_led_stop_generic, .set_rar = &ixgbe_set_rar_generic, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 63b25006ac90..1c1076b4c6fc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -2204,6 +2204,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = { .get_link_capabilities = &ixgbe_get_link_capabilities_82599, .led_on = &ixgbe_led_on_generic, .led_off = &ixgbe_led_off_generic, + .init_led_link_act = ixgbe_init_led_link_act_generic, .blink_led_start = &ixgbe_blink_led_start_generic, .blink_led_stop = &ixgbe_blink_led_stop_generic, .set_rar = &ixgbe_set_rar_generic, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 77d3039283f6..f7600dd7f8e2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -390,6 +390,9 @@ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) status = hw->mac.ops.start_hw(hw); } + /* Initialize the LED link active for LED blink support */ + hw->mac.ops.init_led_link_act(hw); + return status; } @@ -772,6 +775,49 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) return ixgbe_disable_pcie_master(hw); } +/** + * ixgbe_init_led_link_act_generic - Store the LED index link/activity. + * @hw: pointer to hardware structure + * + * Store the index for the link active LED. This will be used to support + * blinking the LED. + **/ +s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) +{ + struct ixgbe_mac_info *mac = &hw->mac; + u32 led_reg, led_mode; + u16 i; + + led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + + /* Get LED link active from the LEDCTL register */ + for (i = 0; i < 4; i++) { + led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); + + if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == + IXGBE_LED_LINK_ACTIVE) { + mac->led_link_act = i; + return 0; + } + } + + /* If LEDCTL register does not have the LED link active set, then use + * known MAC defaults. + */ + switch (hw->mac.type) { + case ixgbe_mac_x550em_a: + mac->led_link_act = 0; + break; + case ixgbe_mac_X550EM_x: + mac->led_link_act = 1; + break; + default: + mac->led_link_act = 2; + } + + return 0; +} + /** * ixgbe_led_on_generic - Turns on the software controllable LEDs. * @hw: pointer to hardware structure diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index 6d4c260d0cbd..5b3e3c65927e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -49,6 +49,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw); s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index); +s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw); s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index f49f80380aa5..fd192bf29b26 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2225,11 +2225,11 @@ static int ixgbe_set_phys_id(struct net_device *netdev, return 2; case ETHTOOL_ID_ON: - hw->mac.ops.led_on(hw, hw->bus.func); + hw->mac.ops.led_on(hw, hw->mac.led_link_act); break; case ETHTOOL_ID_OFF: - hw->mac.ops.led_off(hw, hw->bus.func); + hw->mac.ops.led_off(hw, hw->mac.led_link_act); break; case ETHTOOL_ID_INACTIVE: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 31d82e3abac8..82813f98b8c1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3352,6 +3352,7 @@ struct ixgbe_mac_operations { s32 (*led_off)(struct ixgbe_hw *, u32); s32 (*blink_led_start)(struct ixgbe_hw *, u32); s32 (*blink_led_stop)(struct ixgbe_hw *, u32); + s32 (*init_led_link_act)(struct ixgbe_hw *); /* RAR, Multicast, VLAN */ s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32); @@ -3462,6 +3463,7 @@ struct ixgbe_mac_info { u8 san_mac_rar_index; struct ixgbe_thermal_sensor_data thermal_sensor_data; bool set_lben; + u8 led_link_act; }; struct ixgbe_phy_info { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index f2b1d48a16c3..5bf1d49c39d7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -851,6 +851,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = { .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, .led_on = &ixgbe_led_on_generic, .led_off = &ixgbe_led_off_generic, + .init_led_link_act = ixgbe_init_led_link_act_generic, .blink_led_start = &ixgbe_blink_led_start_X540, .blink_led_stop = &ixgbe_blink_led_stop_X540, .set_rar = &ixgbe_set_rar_generic, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 3e3458e29934..f4385fcd7147 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2952,6 +2952,7 @@ static const struct ixgbe_mac_operations mac_ops_X550 = { X550_COMMON_MAC .led_on = ixgbe_led_on_generic, .led_off = ixgbe_led_off_generic, + .init_led_link_act = ixgbe_init_led_link_act_generic, .reset_hw = &ixgbe_reset_hw_X540, .get_media_type = &ixgbe_get_media_type_X540, .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, @@ -2972,6 +2973,7 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = { X550_COMMON_MAC .led_on = ixgbe_led_on_t_x550em, .led_off = ixgbe_led_off_t_x550em, + .init_led_link_act = ixgbe_init_led_link_act_generic, .reset_hw = &ixgbe_reset_hw_X550em, .get_media_type = &ixgbe_get_media_type_X550em, .get_san_mac_addr = NULL, @@ -2992,6 +2994,7 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = { X550_COMMON_MAC .led_on = ixgbe_led_on_t_x550em, .led_off = ixgbe_led_off_t_x550em, + .init_led_link_act = ixgbe_init_led_link_act_generic, .reset_hw = ixgbe_reset_hw_X550em, .get_media_type = ixgbe_get_media_type_X550em, .get_san_mac_addr = NULL, -- cgit v1.2.3 From d2e455a8884dcf5549ef67fcc2714ac0a64b9dc8 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Fri, 21 Oct 2016 21:10:54 -0400 Subject: ixgbe: Update setup PHY link to unset all speeds This patch updates ixgbe_setup_phy_link_generic to set/unset auto-negotiation for all speeds. This ensures that unsupported speeds are unset. This is necessary since the PHY NVM may advertise unsupported speeds. Signed-off-by: Don Skidmore Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 77 ++++++++++++++-------------- 1 file changed, 38 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 021ab9b89c71..648739a3904a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -705,53 +705,52 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); - if (speed & IXGBE_LINK_SPEED_10GB_FULL) { - /* Set or unset auto-negotiation 10G advertisement */ - hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, - MDIO_MMD_AN, - &autoneg_reg); + /* Set or unset auto-negotiation 10G advertisement */ + hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, &autoneg_reg); - autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G; - if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) - autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; + autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G; + if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) && + (speed & IXGBE_LINK_SPEED_10GB_FULL)) + autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; - hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, - MDIO_MMD_AN, - autoneg_reg); - } + hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, autoneg_reg); - if (speed & IXGBE_LINK_SPEED_1GB_FULL) { - /* Set or unset auto-negotiation 1G advertisement */ - hw->phy.ops.read_reg(hw, - IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, - MDIO_MMD_AN, - &autoneg_reg); - - autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; - if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) - autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; + hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + MDIO_MMD_AN, &autoneg_reg); - hw->phy.ops.write_reg(hw, - IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, - MDIO_MMD_AN, - autoneg_reg); + if (hw->mac.type == ixgbe_mac_X550) { + /* Set or unset auto-negotiation 5G advertisement */ + autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE; + if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) && + (speed & IXGBE_LINK_SPEED_5GB_FULL)) + autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE; + + /* Set or unset auto-negotiation 2.5G advertisement */ + autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE; + if ((hw->phy.autoneg_advertised & + IXGBE_LINK_SPEED_2_5GB_FULL) && + (speed & IXGBE_LINK_SPEED_2_5GB_FULL)) + autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE; } - if (speed & IXGBE_LINK_SPEED_100_FULL) { - /* Set or unset auto-negotiation 100M advertisement */ - hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, - MDIO_MMD_AN, - &autoneg_reg); + /* Set or unset auto-negotiation 1G advertisement */ + autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; + if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) && + (speed & IXGBE_LINK_SPEED_1GB_FULL)) + autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; - autoneg_reg &= ~(ADVERTISE_100FULL | - ADVERTISE_100HALF); - if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) - autoneg_reg |= ADVERTISE_100FULL; + hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + MDIO_MMD_AN, autoneg_reg); - hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, - MDIO_MMD_AN, - autoneg_reg); - } + /* Set or unset auto-negotiation 100M advertisement */ + hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg); + + autoneg_reg &= ~(ADVERTISE_100FULL | ADVERTISE_100HALF); + if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) && + (speed & IXGBE_LINK_SPEED_100_FULL)) + autoneg_reg |= ADVERTISE_100FULL; + + hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg); /* Blocked by MNG FW so don't reset PHY */ if (ixgbe_check_reset_blocked(hw)) -- cgit v1.2.3 From 4dc4000b35119fb83266f978475f5881e263358e Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Mon, 26 Sep 2016 14:08:13 -0700 Subject: ixgbe: do not use ixgbe specific mdio defines Replace some ixgbe specific MDIO defines with their equivalent from the kernel. Signed-off-by: Emil Tantilov Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 8 +--- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 16 ------- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 65 +++++++++++++-------------- 3 files changed, 33 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 648739a3904a..ebf46afd08b0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -2395,9 +2395,7 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on) if (!on && ixgbe_mng_present(hw)) return 0; - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - ®); + status = hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, ®); if (status) return status; @@ -2409,8 +2407,6 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on) reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE; } - status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - reg); + status = hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, reg); return status; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 82813f98b8c1..6886e57d12f7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -874,19 +874,13 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB 0x4 /* 1Gb/s */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB 0x6 /* 10Gb/s */ -#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG 0x20 /* 10G Control Reg */ #define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */ #define IXGBE_MII_AUTONEG_XNP_TX_REG 0x17 /* 1G XNP Transmit */ -#define IXGBE_MII_AUTONEG_ADVERTISE_REG 0x10 /* 100M Advertisement */ -#define IXGBE_MII_10GBASE_T_ADVERTISE 0x1000 /* full duplex, bit:12*/ #define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14*/ #define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15*/ #define IXGBE_MII_2_5GBASE_T_ADVERTISE 0x0400 #define IXGBE_MII_5GBASE_T_ADVERTISE 0x0800 -#define IXGBE_MII_100BASE_T_ADVERTISE 0x0100 /* full duplex, bit:8 */ -#define IXGBE_MII_100BASE_T_ADVERTISE_HALF 0x0080 /* half duplex, bit:7 */ #define IXGBE_MII_RESTART 0x200 -#define IXGBE_MII_AUTONEG_COMPLETE 0x20 #define IXGBE_MII_AUTONEG_LINK_UP 0x04 #define IXGBE_MII_AUTONEG_REG 0x0 @@ -1320,30 +1314,20 @@ struct ixgbe_thermal_sensor_data { /* MDIO definitions */ #define IXGBE_MDIO_ZERO_DEV_TYPE 0x0 -#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1 #define IXGBE_MDIO_PCS_DEV_TYPE 0x3 -#define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4 -#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7 -#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */ #define IXGBE_TWINAX_DEV 1 #define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */ -#define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL 0x0 /* VS1 Control Reg */ -#define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS 0x1 /* VS1 Status Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS 0x0008 /* 1 = Link Up */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS 0x0010 /* 0 - 10G, 1 - 1G */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED 0x0018 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED 0x0010 -#define IXGBE_MDIO_AUTO_NEG_CONTROL 0x0 /* AUTO_NEG Control Reg */ -#define IXGBE_MDIO_AUTO_NEG_STATUS 0x1 /* AUTO_NEG Status Reg */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STAT 0xC800 /* AUTO_NEG Vendor Status Reg */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM 0xCC00 /* AUTO_NEG Vendor TX Reg */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2 0xCC01 /* AUTO_NEG Vendor Tx Reg */ #define IXGBE_MDIO_AUTO_NEG_VEN_LSC 0x1 /* AUTO_NEG Vendor Tx LSC */ -#define IXGBE_MDIO_AUTO_NEG_ADVT 0x10 /* AUTO_NEG Advt Reg */ -#define IXGBE_MDIO_AUTO_NEG_LP 0x13 /* AUTO_NEG LP Status Reg */ #define IXGBE_MDIO_AUTO_NEG_EEE_ADVT 0x3C /* AUTO_NEG EEE Advt Reg */ #define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE 0x0800 /* Set low power mode */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index f4385fcd7147..e9fa83baa00a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1571,8 +1571,7 @@ static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, /* MAC link is up, so check external PHY link. * Read this twice back to back to indicate current status. */ - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, &autoneg_status); if (status) return status; @@ -1758,7 +1757,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) /* Vendor alarm triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, ®); if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) @@ -1766,7 +1765,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, ®); if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | @@ -1775,7 +1774,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) /* Global alarm triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, ®); if (status) @@ -1790,7 +1789,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { /* device fault alarm triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, ®); if (status) return status; @@ -1805,14 +1804,14 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) /* Vendor alarm 2 triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); + MDIO_MMD_AN, ®); if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) return status; /* link connect/disconnect event occurred */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); + MDIO_MMD_AN, ®); if (status) return status; @@ -1844,20 +1843,20 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) /* Enable link status change alarm */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); + MDIO_MMD_AN, ®); if (status) return status; reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); + MDIO_MMD_AN, reg); if (status) return status; /* Enable high temperature failure and global fault alarms */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, ®); if (status) return status; @@ -1866,14 +1865,14 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, reg); if (status) return status; /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, ®); if (status) return status; @@ -1882,14 +1881,14 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) IXGBE_MDIO_GLOBAL_ALARM_1_INT); status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, reg); if (status) return status; /* Enable chip-wide vendor alarm */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, ®); if (status) return status; @@ -1897,7 +1896,7 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, reg); return status; @@ -2038,14 +2037,12 @@ static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) *link_up = false; /* read this twice back to back to indicate current status */ - ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, &autoneg_status); if (ret) return ret; - ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, &autoneg_status); if (ret) return ret; @@ -2091,7 +2088,7 @@ static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) return 0; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + MDIO_MMD_AN, &speed); if (status) return status; @@ -2152,10 +2149,10 @@ static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) /* To turn on the LED, set mode to ON. */ hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); + MDIO_MMD_VEND1, &phy_data); phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); + MDIO_MMD_VEND1, phy_data); return 0; } @@ -2174,10 +2171,10 @@ static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) /* To turn on the LED, set mode to ON. */ hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); + MDIO_MMD_VEND1, &phy_data); phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); + MDIO_MMD_VEND1, phy_data); return 0; } @@ -2198,7 +2195,7 @@ static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + MDIO_MMD_AN, &an_lp_status); if (status) return status; @@ -2345,7 +2342,7 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) return ixgbe_set_copper_phy_power(hw, false); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + MDIO_MMD_AN, &speed); if (status) return status; @@ -2367,20 +2364,20 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) /* Clear AN completed indication */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + MDIO_MMD_AN, &autoneg_reg); if (status) return status; - status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, + MDIO_MMD_AN, &an_10g_cntl_reg); if (status) return status; status = hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + MDIO_MMD_AN, &autoneg_reg); if (status) return status; @@ -2538,7 +2535,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_TX_VENDOR_ALARMS_3, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + MDIO_MMD_PMAPMD, ®); if (status) return status; @@ -2549,7 +2546,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_RES_PR_10, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, ®); if (status) return status; @@ -2558,7 +2555,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_RES_PR_10, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, reg); if (status) return status; -- cgit v1.2.3 From 21d882eb3a7e8d706247f32c0352390791751e8f Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Mon, 26 Sep 2016 14:08:18 -0700 Subject: ixgbe: fix link status check for copper X550em Read the PHY register twice in order to get the correct value for autoneg_status. Signed-off-by: Emil Tantilov Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index e9fa83baa00a..51b6ade6c83a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1556,7 +1556,7 @@ static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, bool link_up_wait_to_complete) { u32 status; - u16 autoneg_status; + u16 i, autoneg_status; if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) return IXGBE_ERR_CONFIG; @@ -1568,13 +1568,18 @@ static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, if (status || !(*link_up)) return status; - /* MAC link is up, so check external PHY link. - * Read this twice back to back to indicate current status. - */ - status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, - &autoneg_status); - if (status) - return status; + /* MAC link is up, so check external PHY link. + * Link status is latching low, and can only be used to detect link + * drop, and not the current status of the link without performing + * back-to-back reads. + */ + for (i = 0; i < 2; i++) { + status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, + &autoneg_status); + + if (status) + return status; + } /* If external PHY link is not up, then indicate link not up */ if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) -- cgit v1.2.3 From 2916500db3075cf2dd7968fe0f140ef4df7c6d31 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Tue, 27 Sep 2016 14:31:12 -0400 Subject: ixgbe: Add X553 PHY FC autoneg support This patch adds X553 flow control auto negotiation for fiber and backplain. To enable this new function pointers were added as well as creating a function to dynamically set function pointer we can't define only on MAC type. Signed-off-by: Don Skidmore Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 3 +- drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 16 +- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 6 + drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 211 ++++++++++++++++++++++++ 7 files changed, 232 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index b06e32d0d22a..ef81c3d8c295 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -1027,4 +1027,6 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct ixgbe_ring *tx_ring); u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter); void ixgbe_store_reta(struct ixgbe_adapter *adapter); +s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, + u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm); #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index 506e346f50a0..805ab319e578 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -367,7 +367,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw) } /* Negotiate the fc mode to use */ - ixgbe_fc_autoneg(hw); + hw->mac.ops.fc_autoneg(hw); /* Disable any previous flow control settings */ fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); @@ -1194,6 +1194,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = { .set_vfta = &ixgbe_set_vfta_82598, .fc_enable = &ixgbe_fc_enable_82598, .setup_fc = ixgbe_setup_fc_generic, + .fc_autoneg = ixgbe_fc_autoneg, .set_fw_drv_ver = NULL, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync, .release_swfw_sync = &ixgbe_release_swfw_sync, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 1c1076b4c6fc..e00aaeb91827 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -2220,6 +2220,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = { .set_vfta = &ixgbe_set_vfta_generic, .fc_enable = &ixgbe_fc_enable_generic, .setup_fc = ixgbe_setup_fc_generic, + .fc_autoneg = ixgbe_fc_autoneg, .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, .init_uta_tables = &ixgbe_init_uta_tables_generic, .setup_sfp = &ixgbe_setup_sfp_modules_82599, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index f7600dd7f8e2..8832df3eba25 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -298,10 +298,12 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); IXGBE_WRITE_FLUSH(hw); - /* Setup flow control */ - ret_val = hw->mac.ops.setup_fc(hw); - if (ret_val) - return ret_val; + /* Setup flow control if method for doing so */ + if (hw->mac.ops.setup_fc) { + ret_val = hw->mac.ops.setup_fc(hw); + if (ret_val) + return ret_val; + } /* Cashe bit indicating need for crosstalk fix */ switch (hw->mac.type) { @@ -2173,7 +2175,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) } /* Negotiate the fc mode to use */ - ixgbe_fc_autoneg(hw); + hw->mac.ops.fc_autoneg(hw); /* Disable any previous flow control settings */ mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); @@ -2277,8 +2279,8 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) * Find the intersection between advertised settings and link partner's * advertised settings **/ -static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, - u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) +s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, + u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) { if ((!(adv_reg)) || (!(lp_reg))) return IXGBE_ERR_FC_NOT_NEGOTIATED; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 6886e57d12f7..f2f60cc57e84 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3357,6 +3357,7 @@ struct ixgbe_mac_operations { /* Flow Control */ s32 (*fc_enable)(struct ixgbe_hw *); s32 (*setup_fc)(struct ixgbe_hw *); + void (*fc_autoneg)(struct ixgbe_hw *); /* Manageability interface */ s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8); @@ -3579,10 +3580,12 @@ struct ixgbe_info { #define IXGBE_FUSES0_REV_MASK (3u << 6) #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010) +#define IXGBE_KRM_LINK_S1(P) ((P) ? 0x8200 : 0x4200) #define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C) #define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C) #define IXGBE_KRM_AN_CNTL_8(P) ((P) ? 0x8248 : 0x4248) #define IXGBE_KRM_SGMII_CTRL(P) ((P) ? 0x82A0 : 0x42A0) +#define IXGBE_KRM_LP_BASE_PAGE_HIGH(P) ((P) ? 0x836C : 0x436C) #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634) #define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638) #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00) @@ -3604,6 +3607,7 @@ struct ixgbe_info { #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR BIT(18) #define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX BIT(24) #define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR BIT(26) +#define IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE BIT(28) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE BIT(29) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART BIT(31) @@ -3613,6 +3617,8 @@ struct ixgbe_info { #define IXGBE_KRM_AN_CNTL_8_LINEAR BIT(0) #define IXGBE_KRM_AN_CNTL_8_LIMITING BIT(1) +#define IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE BIT(10) +#define IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE BIT(11) #define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D BIT(12) #define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D BIT(19) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index 5bf1d49c39d7..e2ff823ee202 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -867,6 +867,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = { .set_vfta = &ixgbe_set_vfta_generic, .fc_enable = &ixgbe_fc_enable_generic, .setup_fc = ixgbe_setup_fc_generic, + .fc_autoneg = ixgbe_fc_autoneg, .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, .init_uta_tables = &ixgbe_init_uta_tables_generic, .setup_sfp = NULL, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 51b6ade6c83a..961ce3a8bfc7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -28,6 +28,9 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed); static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); +static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *); +static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *); +static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *); static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) { @@ -1639,6 +1642,27 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, return rc; } +/** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers + * @hw: pointer to hardware structure + **/ +static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw) +{ + struct ixgbe_mac_info *mac = &hw->mac; + + switch (mac->ops.get_media_type(hw)) { + case ixgbe_media_type_fiber: + mac->ops.setup_fc = NULL; + mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; + break; + case ixgbe_media_type_backplane: + mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; + mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; + break; + default: + break; + } +} + /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers * @hw: pointer to hardware structure **/ @@ -1686,6 +1710,10 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) default: break; } + + /* Additional modification for X550em_a devices */ + if (hw->mac.type == ixgbe_mac_x550em_a) + ixgbe_init_mac_link_ops_X550em_a(hw); } /** ixgbe_setup_sfp_modules_X550em - Setup SFP module @@ -2301,6 +2329,90 @@ static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) return rc; } +/** + * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 + * @hw: pointer to hardware structure + **/ +static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) +{ + u32 link_s1, lp_an_page_low, an_cntl_1; + s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; + ixgbe_link_speed speed; + bool link_up; + + /* AN should have completed when the cable was plugged in. + * Look for reasons to bail out. Bail out if: + * - FC autoneg is disabled, or if + * - link is not up. + */ + if (hw->fc.disable_fc_autoneg) { + hw_err(hw, "Flow control autoneg is disabled"); + goto out; + } + + hw->mac.ops.check_link(hw, &speed, &link_up, false); + if (!link_up) { + hw_err(hw, "The link is down"); + goto out; + } + + /* Check at auto-negotiation has completed */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LINK_S1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); + + if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { + hw_dbg(hw, "Auto-Negotiation did not complete\n"); + status = IXGBE_ERR_FC_NOT_NEGOTIATED; + goto out; + } + + /* Read the 10g AN autoc and LP ability registers and resolve + * local flow control settings accordingly + */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); + + if (status) { + hw_dbg(hw, "Auto-Negotiation did not complete\n"); + goto out; + } + + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); + + if (status) { + hw_dbg(hw, "Auto-Negotiation did not complete\n"); + goto out; + } + + status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, + IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, + IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, + IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, + IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); + +out: + if (!status) { + hw->fc.fc_was_autonegged = true; + } else { + hw->fc.fc_was_autonegged = false; + hw->fc.current_mode = hw->fc.requested_mode; + } +} + +/** + * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings + * @hw: pointer to hardware structure + **/ +static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) +{ + hw->fc.fc_was_autonegged = false; + hw->fc.current_mode = hw->fc.requested_mode; +} + /** ixgbe_enter_lplu_x550em - Transition to low power states * @hw: pointer to hardware structure * @@ -2748,6 +2860,102 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); } +/** + * ixgbe_setup_fc_backplane_x550em_a - Set up flow control + * @hw: pointer to hardware structure + * + * Called at init time to set up flow control. + **/ +static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) +{ + s32 status = 0; + u32 link_ctrl = 0; + u32 an_cntl = 0; + + /* Validate the requested mode */ + if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { + hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); + return IXGBE_ERR_INVALID_LINK_SETTINGS; + } + + if (hw->fc.requested_mode == ixgbe_fc_default) + hw->fc.requested_mode = ixgbe_fc_full; + + /* Set up the 1G and 10G flow control advertisement registers so the + * HW will be able to do FC autoneg once the cable is plugged in. If + * we link at 10G, the 1G advertisement is harmless and vice versa. + */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); + + if (status) { + hw_dbg(hw, "Auto-Negotiation did not complete\n"); + return status; + } + + /* The possible values of fc.requested_mode are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but + * we do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + * other: Invalid. + */ + switch (hw->fc.requested_mode) { + case ixgbe_fc_none: + /* Flow control completely disabled by software override. */ + an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | + IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); + break; + case ixgbe_fc_tx_pause: + /* Tx Flow control is enabled, and Rx Flow control is + * disabled by software override. + */ + an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; + an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; + break; + case ixgbe_fc_rx_pause: + /* Rx Flow control is enabled and Tx Flow control is + * disabled by software override. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric Rx PAUSE, as such we fall + * through to the fc_full statement. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + case ixgbe_fc_full: + /* Flow control (both Rx and Tx) is enabled by SW override. */ + an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | + IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; + break; + default: + hw_err(hw, "Flow control param set incorrectly\n"); + return IXGBE_ERR_CONFIG; + } + + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); + + /* Restart auto-negotiation. */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); + if (status) { + hw_dbg(hw, "Auto-Negotiation did not complete\n"); + return status; + } + + link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); + + return status; +} + /** * ixgbe_set_mux - Set mux for port 1 access with CS4227 * @hw: pointer to hardware structure @@ -2969,6 +3177,7 @@ static const struct ixgbe_mac_operations mac_ops_X550 = { .prot_autoc_read = prot_autoc_read_generic, .prot_autoc_write = prot_autoc_write_generic, .setup_fc = ixgbe_setup_fc_generic, + .fc_autoneg = ixgbe_fc_autoneg, }; static const struct ixgbe_mac_operations mac_ops_X550EM_x = { @@ -2988,6 +3197,7 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = { .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, .init_swfw_sync = &ixgbe_init_swfw_sync_X540, .setup_fc = NULL, /* defined later */ + .fc_autoneg = ixgbe_fc_autoneg, .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, }; @@ -3008,6 +3218,7 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = { .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, .setup_fc = ixgbe_setup_fc_x550em, + .fc_autoneg = NULL, /* defined later */ .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, }; -- cgit v1.2.3 From 1fa71252778d6fe151438b009416e4ce7bc1c802 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Wed, 28 Sep 2016 15:36:38 -0700 Subject: ixgbe: Handle previously-freed msix_entries The msix_entries memory can be freed by a previous suspend or remove, so don't crash on close when it isn't there. Signed-off-by: Mark Rustad Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5e1f57c7ee1b..de634f0c2e6d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3070,6 +3070,9 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) return; } + if (!adapter->msix_entries) + return; + for (vector = 0; vector < adapter->num_q_vectors; vector++) { struct ixgbe_q_vector *q_vector = adapter->q_vector[vector]; struct msix_entry *entry = &adapter->msix_entries[vector]; -- cgit v1.2.3 From 812d7dff107fa272caf9aa4f8e2420d1d1eaa429 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Mon, 3 Oct 2016 17:09:58 -0700 Subject: ixgbe: remove SFP ixfi support Remove SFP ixfi code since there is no HW that currently supports it. Signed-off-by: Emil Tantilov Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 76 ++++----------------------- 1 file changed, 11 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 961ce3a8bfc7..c6669c27bc38 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1313,7 +1313,7 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, __always_unused bool autoneg_wait_to_complete) { s32 status; - u16 slice, value; + u16 reg_slice, reg_val; bool setup_linear = false; /* Check if SFP module is supported and linear */ @@ -1329,71 +1329,17 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, if (status) return status; - if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { - /* Configure CS4227 LINE side to 10G SR. */ - slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); - value = IXGBE_CS4227_SPEED_10G; - status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, - slice, value); - if (status) - goto i2c_err; - - slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); - value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; - status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, - slice, value); - if (status) - goto i2c_err; - - /* Configure CS4227 for HOST connection rate then type. */ - slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); - value = speed & IXGBE_LINK_SPEED_10GB_FULL ? - IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; - status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, - slice, value); - if (status) - goto i2c_err; - - slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); - if (setup_linear) - value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; - else - value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; - status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, - slice, value); - if (status) - goto i2c_err; - - /* Setup XFI internal link. */ - status = ixgbe_setup_ixfi_x550em(hw, &speed); - if (status) { - hw_dbg(hw, "setup_ixfi failed with %d\n", status); - return status; - } - } else { - /* Configure internal PHY for KR/KX. */ - status = ixgbe_setup_kr_speed_x550em(hw, speed); - if (status) { - hw_dbg(hw, "setup_kr_speed failed with %d\n", status); - return status; - } - - /* Configure CS4227 LINE side to proper mode. */ - slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); - if (setup_linear) - value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; - else - value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; - status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, - slice, value); - if (status) - goto i2c_err; - } - - return 0; + /* Configure internal PHY for KR/KX. */ + ixgbe_setup_kr_speed_x550em(hw, speed); -i2c_err: - hw_dbg(hw, "combined i2c access failed with %d\n", status); + /* Configure CS4227 LINE side to proper mode. */ + reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); + if (setup_linear) + reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; + else + reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; + status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, + reg_slice, reg_val); return status; } -- cgit v1.2.3 From b71f6c40bb36f9691420f66283f3c3acca11016b Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Mon, 10 Oct 2016 14:54:03 -0700 Subject: ixgbe: use link instead of I2C combined abstraction Introduce ixgbe_link_operations struct with the following changes: read_i2c_combined => read_link read_i2c_combined_unlocked => read_link_unlocked write_i2c_combined => write_link write_i2c_combined_unlocked => write_link_unlocked This will allow X550EM_a to override these methods for MDIO access while X550EM_x provides methods to use I2C combined access. This also adds a new structure, ixgbe_link_info, to hold information about the link. Initially this is just method pointers and a bus address. The functions involved in combined I2C accesses were moved from ixgbe_phy.c to ixgbe_x550.c. The underlying functions that carry out the combined I2C accesses were left in ixgbe_phy.c because they share some functions with other I2C methods. v2 - set hw->link.ops in probe. v3 - check ii->link_ops before setting it since we don't have it for all devices. Signed-off-by: Emil Tantilov Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 68 +---------------- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 12 +-- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 26 +++++-- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 106 +++++++++++++++++++++++--- 5 files changed, 124 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index de634f0c2e6d..9a62b5545160 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -9507,6 +9507,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->mac.ops = *ii->mac_ops; hw->mac.type = ii->mac; hw->mvals = ii->mvals; + if (ii->link_ops) + hw->link.ops = *ii->link_ops; /* EEPROM */ hw->eeprom.ops = *ii->eeprom_ops; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index ebf46afd08b0..0c65814f5803 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -109,8 +109,8 @@ static u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2) * * Returns an error code on error. */ -static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 *val, bool lock) +s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 *val, bool lock) { u32 swfw_mask = hw->phy.phy_semaphore_mask; int max_retry = 10; @@ -177,36 +177,6 @@ fail: return IXGBE_ERR_I2C; } -/** - * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation - * @hw: pointer to the hardware structure - * @addr: I2C bus address to read from - * @reg: I2C device register to read from - * @val: pointer to location to receive read value - * - * Returns an error code on error. - */ -s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 *val) -{ - return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); -} - -/** - * ixgbe_read_i2c_combined_generic_unlocked - Unlocked I2C read combined - * @hw: pointer to the hardware structure - * @addr: I2C bus address to read from - * @reg: I2C device register to read from - * @val: pointer to location to receive read value - * - * Returns an error code on error. - */ -s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 *val) -{ - return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); -} - /** * ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation * @hw: pointer to the hardware structure @@ -217,8 +187,8 @@ s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, * * Returns an error code on error. */ -static s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 val, bool lock) +s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 val, bool lock) { u32 swfw_mask = hw->phy.phy_semaphore_mask; int max_retry = 1; @@ -272,36 +242,6 @@ fail: return IXGBE_ERR_I2C; } -/** - * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation - * @hw: pointer to the hardware structure - * @addr: I2C bus address to write to - * @reg: I2C device register to write to - * @val: value to write - * - * Returns an error code on error. - */ -s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, - u8 addr, u16 reg, u16 val) -{ - return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); -} - -/** - * ixgbe_write_i2c_combined_generic_unlocked - Unlocked I2C write combined - * @hw: pointer to the hardware structure - * @addr: I2C bus address to write to - * @reg: I2C device register to write to - * @val: value to write - * - * Returns an error code on error. - */ -s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, - u8 addr, u16 reg, u16 val) -{ - return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); -} - /** * ixgbe_identify_phy_generic - Get physical layer module * @hw: pointer to hardware structure diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index cc735ec3e045..ecf05f838fc5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -195,12 +195,8 @@ s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *sff8472_data); s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data); -s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 *val); -s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 *val); -s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 val); -s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 val); +s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg, + u16 *val, bool lock); +s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg, + u16 val, bool lock); #endif /* _IXGBE_PHY_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index f2f60cc57e84..fe9c6ae41a35 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3396,16 +3396,28 @@ struct ixgbe_phy_operations { s32 (*read_i2c_sff8472)(struct ixgbe_hw *, u8 , u8 *); s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *); s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8); - s32 (*read_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val); - s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val); s32 (*check_overtemp)(struct ixgbe_hw *); s32 (*set_phy_power)(struct ixgbe_hw *, bool on); s32 (*enter_lplu)(struct ixgbe_hw *); s32 (*handle_lasi)(struct ixgbe_hw *hw); - s32 (*read_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, - u16 *value); - s32 (*write_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, - u16 value); + s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr, + u8 *value); + s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr, + u8 value); +}; + +struct ixgbe_link_operations { + s32 (*read_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val); + s32 (*read_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, + u16 *val); + s32 (*write_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val); + s32 (*write_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, + u16 val); +}; + +struct ixgbe_link_info { + struct ixgbe_link_operations ops; + u8 addr; }; struct ixgbe_eeprom_info { @@ -3510,6 +3522,7 @@ struct ixgbe_hw { struct ixgbe_addr_filter_info addr_ctrl; struct ixgbe_fc_info fc; struct ixgbe_phy_info phy; + struct ixgbe_link_info link; struct ixgbe_eeprom_info eeprom; struct ixgbe_bus_info bus; struct ixgbe_mbx_info mbx; @@ -3533,6 +3546,7 @@ struct ixgbe_info { const struct ixgbe_eeprom_operations *eeprom_ops; const struct ixgbe_phy_operations *phy_ops; const struct ixgbe_mbx_operations *mbx_ops; + const struct ixgbe_link_operations *link_ops; const u32 *mvals; }; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index c6669c27bc38..252e52d7c03d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -33,6 +33,23 @@ static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *); static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *); static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) +{ + struct ixgbe_mac_info *mac = &hw->mac; + struct ixgbe_phy_info *phy = &hw->phy; + struct ixgbe_link_info *link = &hw->link; + + /* Start with X540 invariants, since so simular */ + ixgbe_get_invariants_X540(hw); + + if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) + phy->ops.set_phy_power = NULL; + + link->addr = IXGBE_CS4227; + + return 0; +} + +static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; @@ -72,8 +89,7 @@ static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) */ static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) { - return hw->phy.ops.read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, - value); + return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value); } /** @@ -86,8 +102,7 @@ static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) */ static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) { - return hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, - value); + return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value); } /** @@ -325,6 +340,68 @@ static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, return IXGBE_NOT_IMPLEMENTED; } +/** + * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to read from + * @reg: I2C device register to read from + * @val: pointer to location to receive read value + * + * Returns an error code on error. + **/ +static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 *val) +{ + return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); +} + +/** + * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to read from + * @reg: I2C device register to read from + * @val: pointer to location to receive read value + * + * Returns an error code on error. + **/ +static s32 +ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 *val) +{ + return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); +} + +/** + * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to write to + * @reg: I2C device register to write to + * @val: value to write + * + * Returns an error code on error. + **/ +static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, + u8 addr, u16 reg, u16 val) +{ + return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); +} + +/** + * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to write to + * @reg: I2C device register to write to + * @val: value to write + * + * Returns an error code on error. + **/ +static s32 +ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, + u8 addr, u16 reg, u16 val) +{ + return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); +} + /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params * @hw: pointer to hardware structure * @@ -1338,8 +1415,10 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; else reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; - status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, - reg_slice, reg_val); + + status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, + reg_val); + return status; } @@ -3216,11 +3295,6 @@ static const struct ixgbe_phy_operations phy_ops_X550EM_x = { .identify = &ixgbe_identify_phy_x550em, .read_reg = &ixgbe_read_phy_reg_generic, .write_reg = &ixgbe_write_phy_reg_generic, - .read_i2c_combined = &ixgbe_read_i2c_combined_generic, - .write_i2c_combined = &ixgbe_write_i2c_combined_generic, - .read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, - .write_i2c_combined_unlocked = - &ixgbe_write_i2c_combined_generic_unlocked, }; static const struct ixgbe_phy_operations phy_ops_x550em_a = { @@ -3233,6 +3307,13 @@ static const struct ixgbe_phy_operations phy_ops_x550em_a = { .write_reg_mdi = &ixgbe_write_phy_reg_mdi, }; +static const struct ixgbe_link_operations link_ops_x550em_x = { + .read_link = &ixgbe_read_i2c_combined_generic, + .read_link_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, + .write_link = &ixgbe_write_i2c_combined_generic, + .write_link_unlocked = &ixgbe_write_i2c_combined_generic_unlocked, +}; + static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(X550) }; @@ -3263,11 +3344,12 @@ const struct ixgbe_info ixgbe_X550EM_x_info = { .phy_ops = &phy_ops_X550EM_x, .mbx_ops = &mbx_ops_generic, .mvals = ixgbe_mvals_X550EM_x, + .link_ops = &link_ops_x550em_x, }; const struct ixgbe_info ixgbe_x550em_a_info = { .mac = ixgbe_mac_x550em_a, - .get_invariants = &ixgbe_get_invariants_X550_x, + .get_invariants = &ixgbe_get_invariants_X550_a, .mac_ops = &mac_ops_x550em_a, .eeprom_ops = &eeprom_ops_X550EM_x, .phy_ops = &phy_ops_x550em_a, -- cgit v1.2.3 From 55570b6f5e2caa37a5bbd634cbe5ed126d3656f9 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 12 Oct 2016 12:34:25 -0700 Subject: ixgbe: set device if before calling get_invariants Fix an issue where set_phy_power was NULL for X550 copper devices because get_invariants was called before hw->device_id was set. Signed-off-by: Emil Tantilov Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 9a62b5545160..a582bea145b3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -5624,7 +5624,8 @@ static void ixgbe_init_dcb(struct ixgbe_adapter *adapter) * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/ -static int ixgbe_sw_init(struct ixgbe_adapter *adapter) +static int ixgbe_sw_init(struct ixgbe_adapter *adapter, + const struct ixgbe_info *ii) { struct ixgbe_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; @@ -5640,6 +5641,9 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) hw->subsystem_vendor_id = pdev->subsystem_vendor; hw->subsystem_device_id = pdev->subsystem_device; + /* get_invariants needs the device IDs */ + ii->get_invariants(hw); + /* Set common capability flags and settings */ rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus()); adapter->ring_feature[RING_F_RSS].limit = rss; @@ -9532,10 +9536,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->phy.mdio.mdio_read = ixgbe_mdio_read; hw->phy.mdio.mdio_write = ixgbe_mdio_write; - ii->get_invariants(hw); - /* setup the private structure */ - err = ixgbe_sw_init(adapter); + err = ixgbe_sw_init(adapter, ii); if (err) goto err_sw_init; -- cgit v1.2.3 From 470739b56386dd59df046e84e54a075d8f965b84 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 3 Nov 2016 21:01:37 -0400 Subject: ixgbe: Add X553 FW ALEF support This patch add X553 FW ALEF support for B0. ALEF is the new unified FW. This contains updated register defines for ALEF speed configuration. Likewise it also removes the AN_CNTL_8 usage from the native SFI flow as it is no longer supported by FW. Signed-off-by: Don Skidmore Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 96 +++++++---- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 17 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 239 +++++++++++++++++++------- 3 files changed, 255 insertions(+), 97 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 0c65814f5803..5dadae60fe23 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -242,6 +242,42 @@ fail: return IXGBE_ERR_I2C; } +/** + * ixgbe_probe_phy - Probe a single address for a PHY + * @hw: pointer to hardware structure + * @phy_addr: PHY address to probe + * + * Returns true if PHY found + **/ +static bool ixgbe_probe_phy(struct ixgbe_hw *hw, u16 phy_addr) +{ + u16 ext_ability = 0; + + hw->phy.mdio.prtad = phy_addr; + if (mdio45_probe(&hw->phy.mdio, phy_addr) != 0) + return false; + + if (ixgbe_get_phy_id(hw)) + return false; + + hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id); + + if (hw->phy.type == ixgbe_phy_unknown) { + hw->phy.ops.read_reg(hw, + MDIO_PMA_EXTABLE, + MDIO_MMD_PMAPMD, + &ext_ability); + if (ext_ability & + (MDIO_PMA_EXTABLE_10GBT | + MDIO_PMA_EXTABLE_1000BT)) + hw->phy.type = ixgbe_phy_cu_unknown; + else + hw->phy.type = ixgbe_phy_generic; + } + + return true; +} + /** * ixgbe_identify_phy_generic - Get physical layer module * @hw: pointer to hardware structure @@ -251,7 +287,7 @@ fail: s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) { u32 phy_addr; - u16 ext_ability = 0; + u32 status = IXGBE_ERR_PHY_ADDR_INVALID; if (!hw->phy.phy_semaphore_mask) { if (hw->bus.lan_id) @@ -260,37 +296,34 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; } - if (hw->phy.type == ixgbe_phy_unknown) { - for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { - hw->phy.mdio.prtad = phy_addr; - if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { - ixgbe_get_phy_id(hw); - hw->phy.type = - ixgbe_get_phy_type_from_id(hw->phy.id); - - if (hw->phy.type == ixgbe_phy_unknown) { - hw->phy.ops.read_reg(hw, - MDIO_PMA_EXTABLE, - MDIO_MMD_PMAPMD, - &ext_ability); - if (ext_ability & - (MDIO_PMA_EXTABLE_10GBT | - MDIO_PMA_EXTABLE_1000BT)) - hw->phy.type = - ixgbe_phy_cu_unknown; - else - hw->phy.type = - ixgbe_phy_generic; - } + if (hw->phy.type != ixgbe_phy_unknown) + return 0; - return 0; - } + if (hw->phy.nw_mng_if_sel) { + phy_addr = (hw->phy.nw_mng_if_sel & + IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> + IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; + if (ixgbe_probe_phy(hw, phy_addr)) + return 0; + else + return IXGBE_ERR_PHY_ADDR_INVALID; + } + + for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { + if (ixgbe_probe_phy(hw, phy_addr)) { + status = 0; + break; } - /* indicate no PHY found */ - hw->phy.mdio.prtad = MDIO_PRTAD_NONE; - return IXGBE_ERR_PHY_ADDR_INVALID; } - return 0; + + /* Certain media types do not have a phy so an address will not + * be found and the code will take this path. Caller has to + * decide if it is an error or not. + */ + if (status) + hw->phy.mdio.prtad = MDIO_PRTAD_NONE; + + return status; } /** @@ -367,6 +400,7 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) phy_type = ixgbe_phy_nl; break; case X557_PHY_ID: + case X557_PHY_ID2: phy_type = ixgbe_phy_x550em_ext_t; break; default: @@ -417,8 +451,7 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) */ for (i = 0; i < 30; i++) { msleep(100); - hw->phy.ops.read_reg(hw, MDIO_CTRL1, - MDIO_MMD_PHYXS, &ctrl); + hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &ctrl); if (!(ctrl & MDIO_CTRL1_RESET)) { udelay(2); break; @@ -769,6 +802,7 @@ static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw) hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL; break; case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL; break; default: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index fe9c6ae41a35..856152fac4bb 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1379,6 +1379,7 @@ struct ixgbe_thermal_sensor_data { #define X540_PHY_ID 0x01540200 #define X550_PHY_ID 0x01540220 #define X557_PHY_ID 0x01540240 +#define X557_PHY_ID2 0x01540250 #define QT2022_PHY_ID 0x0043A400 #define ATH_PHY_ID 0x03429050 #define AQ_FW_REV 0x20 @@ -3604,9 +3605,25 @@ struct ixgbe_info { #define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638) #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00) #define IXGBE_KRM_PMD_DFX_BURNIN(P) ((P) ? 0x8E00 : 0x4E00) +#define IXGBE_KRM_PMD_FLX_MASK_ST20(P) ((P) ? 0x9054 : 0x5054) #define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P) ? 0x9520 : 0x5520) #define IXGBE_KRM_RX_ANA_CTL(P) ((P) ? 0x9A00 : 0x5A00) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA ~(0x3 << 20) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR BIT(20) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_LR (0x2 << 20) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN BIT(25) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN BIT(26) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN BIT(27) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10M ~(0x7 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_100M BIT(28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G (0x2 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G (0x3 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN (0x4 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_2_5G (0x7 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK (0x7 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART BIT(31) + #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B BIT(9) #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS BIT(11) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 252e52d7c03d..11fb433eb924 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1281,6 +1281,53 @@ static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) return status; } +/** + * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the + * internal PHY + * @hw: pointer to hardware structure + **/ +static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) +{ + s32 status; + u32 link_ctrl; + + /* Restart auto-negotiation. */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); + + if (status) { + hw_dbg(hw, "Auto-negotiation did not complete\n"); + return status; + } + + link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); + + if (hw->mac.type == ixgbe_mac_x550em_a) { + u32 flx_mask_st20; + + /* Indicate to FW that AN restart has been asserted */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); + + if (status) { + hw_dbg(hw, "Auto-negotiation did not complete\n"); + return status; + } + + flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); + } + + return status; +} + /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. * @hw: pointer to hardware structure * @speed: the link speed to force @@ -1330,16 +1377,7 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) } /* Toggle port SW reset by AN reset. */ - status = ixgbe_read_iosf_sb_reg_x550(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); - if (status) - return status; - - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; - status = ixgbe_write_iosf_sb_reg_x550(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + status = ixgbe_restart_an_internal_phy_x550em(hw); return status; } @@ -1422,6 +1460,55 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, return status; } +/** + * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode + * @hw: pointer to hardware structure + * @speed: the link speed to force + * + * Configures the integrated PHY for native SFI mode. Used to connect the + * internal PHY directly to an SFP cage, without autonegotiation. + **/ +static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) +{ + struct ixgbe_mac_info *mac = &hw->mac; + s32 status; + u32 reg_val; + + /* Disable all AN and force speed to 10G Serial. */ + status = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + if (status) + return status; + + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; + + /* Select forced link speed for internal PHY. */ + switch (*speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; + break; + default: + /* Other link speeds are not supported by internal PHY. */ + return IXGBE_ERR_LINK_SETUP; + } + + status = mac->ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + + /* Toggle port SW reset by AN reset. */ + status = ixgbe_restart_an_internal_phy_x550em(hw); + + return status; +} + /** * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP * @hw: pointer to hardware structure @@ -1434,45 +1521,39 @@ ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, { bool setup_linear = false; u32 reg_phy_int; - s32 rc; + s32 ret_val; /* Check if SFP module is supported and linear */ - rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); + ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); /* If no SFP module present, then return success. Return success since * SFP not present error is not excepted in the setup MAC link flow. */ - if (rc == IXGBE_ERR_SFP_NOT_PRESENT) + if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) return 0; - if (!rc) - return rc; + if (!ret_val) + return ret_val; - /* Configure internal PHY for native SFI */ - rc = hw->mac.ops.read_iosf_sb_reg(hw, - IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, - ®_phy_int); - if (rc) - return rc; + /* Configure internal PHY for native SFI based on module type */ + ret_val = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); + if (!ret_val) + return ret_val; - if (setup_linear) { - reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING; - reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR; - } else { - reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING; - reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR; - } + reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; + if (!setup_linear) + reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; - rc = hw->mac.ops.write_iosf_sb_reg(hw, - IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, - reg_phy_int); - if (rc) - return rc; + ret_val = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); + if (!ret_val) + return ret_val; - /* Setup XFI/SFI internal link */ - return ixgbe_setup_ixfi_x550em(hw, &speed); + /* Setup SFI internal link. */ + return ixgbe_setup_sfi_x550a(hw, &speed); } /** @@ -1488,19 +1569,19 @@ ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, u32 reg_slice, slice_offset; bool setup_linear = false; u16 reg_phy_ext; - s32 rc; + s32 ret_val; /* Check if SFP module is supported and linear */ - rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); + ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); /* If no SFP module present, then return success. Return success since * SFP not present error is not excepted in the setup MAC link flow. */ - if (rc == IXGBE_ERR_SFP_NOT_PRESENT) + if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) return 0; - if (!rc) - return rc; + if (!ret_val) + return ret_val; /* Configure internal PHY for KR/KX. */ ixgbe_setup_kr_speed_x550em(hw, speed); @@ -1509,10 +1590,10 @@ ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, return IXGBE_ERR_PHY_ADDR_INVALID; /* Get external PHY device id */ - rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, + ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); - if (rc) - return rc; + if (ret_val) + return ret_val; /* When configuring quad port CS4223, the MAC instance is part * of the slice offset. @@ -1625,7 +1706,7 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, __always_unused bool autoneg_wait_to_complete) { struct ixgbe_mac_info *mac = &hw->mac; - u32 lval, sval; + u32 lval, sval, flx_val; s32 rc; rc = mac->ops.read_iosf_sb_reg(hw, @@ -1659,11 +1740,31 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, if (rc) return rc; - lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; + rc = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); + if (rc) + return rc; + + rc = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); + if (rc) + return rc; + + flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; + flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; + flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; + flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; + flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; + rc = mac->ops.write_iosf_sb_reg(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, lval); + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); + if (rc) + return rc; + rc = ixgbe_restart_an_internal_phy_x550em(hw); return rc; } @@ -2020,13 +2121,31 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, if (speed & IXGBE_LINK_SPEED_1GB_FULL) reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; - /* Restart auto-negotiation. */ - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); - return status; + if (hw->mac.type == ixgbe_mac_x550em_a) { + /* Set lane mode to KR auto negotiation */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + + if (status) + return status; + + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; + reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; + reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; + + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + } + + return ixgbe_restart_an_internal_phy_x550em(hw); } /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. @@ -2894,7 +3013,6 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) { s32 status = 0; - u32 link_ctrl = 0; u32 an_cntl = 0; /* Validate the requested mode */ @@ -2965,18 +3083,7 @@ static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); /* Restart auto-negotiation. */ - status = hw->mac.ops.read_iosf_sb_reg(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); - if (status) { - hw_dbg(hw, "Auto-Negotiation did not complete\n"); - return status; - } - - link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; - status = hw->mac.ops.write_iosf_sb_reg(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); + status = ixgbe_restart_an_internal_phy_x550em(hw); return status; } @@ -3243,7 +3350,7 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = { .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, .setup_fc = ixgbe_setup_fc_x550em, - .fc_autoneg = NULL, /* defined later */ + .fc_autoneg = ixgbe_fc_autoneg, .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, }; -- cgit v1.2.3 From 5f1c3589b0f0feb2c99b985d3a3bbda0dd790626 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Fri, 4 Nov 2016 16:46:16 -0400 Subject: ixgbe: Correct X550 phy ID We were using an old Alpha version of the X550 phy ID. This was leading to unnecessary queries of the PHY. I removed the old ID (which shouldn't be on any HW) and add the two that are. Signed-off-by: Don Skidmore Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 3 ++- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 5dadae60fe23..3b8362085f57 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -389,7 +389,8 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) case TN1010_PHY_ID: phy_type = ixgbe_phy_tn; break; - case X550_PHY_ID: + case X550_PHY_ID2: + case X550_PHY_ID3: case X540_PHY_ID: phy_type = ixgbe_phy_aq; break; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 856152fac4bb..cf21273db201 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1377,7 +1377,8 @@ struct ixgbe_thermal_sensor_data { #define TN1010_PHY_ID 0x00A19410 #define TNX_FW_REV 0xB #define X540_PHY_ID 0x01540200 -#define X550_PHY_ID 0x01540220 +#define X550_PHY_ID2 0x01540223 +#define X550_PHY_ID3 0x01540221 #define X557_PHY_ID 0x01540240 #define X557_PHY_ID2 0x01540250 #define QT2022_PHY_ID 0x0043A400 -- cgit v1.2.3 From 520288218cf233f442aa815496a95622c2672c62 Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Mon, 24 Oct 2016 15:36:38 -0700 Subject: ixgbe: ixgbe_atr() should access udp_hdr(skb) only for UDP packets Commit 9f12df906cd8 ("ixgbe: Store VXLAN port number in network order") incorrectly checks for hdr.ipv4->protocol != IPPROTO_UDP in ixgbe_atr(). This check should be for "==" instead. Signed-off-by: Sowmini Varadhan Reviewed-by: Alexander Duyck Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index a582bea145b3..e4a3227cd74b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7662,7 +7662,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring, hdr.network = skb_network_header(skb); if (skb->encapsulation && first->protocol == htons(ETH_P_IP) && - hdr.ipv4->protocol != IPPROTO_UDP) { + hdr.ipv4->protocol == IPPROTO_UDP) { struct ixgbe_adapter *adapter = q_vector->adapter; /* verify the port is recognized as VXLAN */ -- cgit v1.2.3 From 9f3c7504fa005e2aab5ba9e1f2d8b4f4fcc6c077 Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Mon, 24 Oct 2016 15:36:39 -0700 Subject: ixgbe: ixgbe_atr() compute l4_proto only if non-paged data has network/transport headers For some Tx paths (e.g., tpacket_snd()), ixgbe_atr may be passed down an sk_buff that has the network and transport header in the paged data, so it needs to make sure these headers are available in the headlen bytes to calculate the l4_proto. This patch expect that network and transport headers are already available in the non-paged header dat. The assumption is that the caller has set this up if l4_proto based Tx steering is desired. Signed-off-by: Sowmini Varadhan Reviewed-by: Alexander Duyck Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index e4a3227cd74b..2436984481cc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -54,6 +54,7 @@ #include #include #include +#include #include "ixgbe.h" #include "ixgbe_common.h" @@ -7660,11 +7661,17 @@ static void ixgbe_atr(struct ixgbe_ring *ring, /* snag network header to get L4 type and address */ skb = first->skb; hdr.network = skb_network_header(skb); + if (unlikely(hdr.network <= skb->data)) + return; if (skb->encapsulation && first->protocol == htons(ETH_P_IP) && hdr.ipv4->protocol == IPPROTO_UDP) { struct ixgbe_adapter *adapter = q_vector->adapter; + if (unlikely(skb_tail_pointer(skb) < hdr.network + + VXLAN_HEADROOM)) + return; + /* verify the port is recognized as VXLAN */ if (adapter->vxlan_port && udp_hdr(skb)->dest == adapter->vxlan_port) @@ -7675,6 +7682,12 @@ static void ixgbe_atr(struct ixgbe_ring *ring, hdr.network = skb_inner_network_header(skb); } + /* Make sure we have at least [minimum IPv4 header + TCP] + * or [IPv6 header] bytes + */ + if (unlikely(skb_tail_pointer(skb) < hdr.network + 40)) + return; + /* Currently only IPv4/IPv6 with TCP is supported */ switch (hdr.ipv4->version) { case IPVERSION: @@ -7694,6 +7707,10 @@ static void ixgbe_atr(struct ixgbe_ring *ring, if (l4_proto != IPPROTO_TCP) return; + if (unlikely(skb_tail_pointer(skb) < hdr.network + + hlen + sizeof(struct tcphdr))) + return; + th = (struct tcphdr *)(hdr.network + hlen); /* skip this packet since the socket is closing */ -- cgit v1.2.3 From eeffceee421b17a1d484679d738f278fbaa01384 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 28 Oct 2016 10:46:39 -0700 Subject: ixgbevf: Handle previously-freed msix_entries The msix_entries memory can be freed by a previous suspend or remove, so don't crash on close when it isn't there. Also only clear the interrupts when the interface is up, because there aren't any when it is not up. Signed-off-by: Mark Rustad Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index d2775f032f74..d316f503a727 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1498,6 +1498,9 @@ static void ixgbevf_free_irq(struct ixgbevf_adapter *adapter) { int i, q_vectors; + if (!adapter->msix_entries) + return; + q_vectors = adapter->num_msix_vectors; i = q_vectors - 1; @@ -2552,6 +2555,9 @@ static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter) **/ static void ixgbevf_reset_interrupt_capability(struct ixgbevf_adapter *adapter) { + if (!adapter->msix_entries) + return; + pci_disable_msix(adapter->pdev); kfree(adapter->msix_entries); adapter->msix_entries = NULL; @@ -3794,11 +3800,10 @@ static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state) ixgbevf_free_irq(adapter); ixgbevf_free_all_tx_resources(adapter); ixgbevf_free_all_rx_resources(adapter); + ixgbevf_clear_interrupt_scheme(adapter); rtnl_unlock(); } - ixgbevf_clear_interrupt_scheme(adapter); - #ifdef CONFIG_PM retval = pci_save_state(pdev); if (retval) -- cgit v1.2.3 From c834e1718aae6150936af718db9e483993d2c63f Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Tue, 1 Nov 2016 01:04:30 +0800 Subject: staging: iio: set proper supply name to devm_regulator_get() The name passed to devm_regulator_get() should match the name of the supply as specified in the device datasheet. This makes it clear what power supply is being referred to in case of presence of other regulators. Currently, the supply name specified on the affected devices is 'vcc'. Use lowercase version of the datasheet name to specify the supply voltage. Suggested-by: Lars-Peter Clausen Signed-off-by: Eva Rachel Retuya Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 2 +- drivers/staging/iio/adc/ad7780.c | 2 +- drivers/staging/iio/frequency/ad9832.c | 2 +- drivers/staging/iio/frequency/ad9834.c | 2 +- drivers/staging/iio/impedance-analyzer/ad5933.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index bfa12ceb1e1f..41fb32de5992 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -633,7 +633,7 @@ static int ad7192_probe(struct spi_device *spi) st = iio_priv(indio_dev); - st->reg = devm_regulator_get(&spi->dev, "vcc"); + st->reg = devm_regulator_get(&spi->dev, "avdd"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index c9a0c2aa602f..a88236e74cdb 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -173,7 +173,7 @@ static int ad7780_probe(struct spi_device *spi) ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info); - st->reg = devm_regulator_get(&spi->dev, "vcc"); + st->reg = devm_regulator_get(&spi->dev, "avdd"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index 358400b22d33..744c8ee9c5a6 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -212,7 +212,7 @@ static int ad9832_probe(struct spi_device *spi) return -ENODEV; } - reg = devm_regulator_get(&spi->dev, "vcc"); + reg = devm_regulator_get(&spi->dev, "avdd"); if (!IS_ERR(reg)) { ret = regulator_enable(reg); if (ret) diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 6366216e4f37..ca3cea68d8d7 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -329,7 +329,7 @@ static int ad9834_probe(struct spi_device *spi) return -ENODEV; } - reg = devm_regulator_get(&spi->dev, "vcc"); + reg = devm_regulator_get(&spi->dev, "avdd"); if (!IS_ERR(reg)) { ret = regulator_enable(reg); if (ret) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 5eecf1cb1028..62f61bcc0003 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -723,7 +723,7 @@ static int ad5933_probe(struct i2c_client *client, if (!pdata) pdata = &ad5933_default_pdata; - st->reg = devm_regulator_get(&client->dev, "vcc"); + st->reg = devm_regulator_get(&client->dev, "vdd"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) -- cgit v1.2.3 From 3925ff0fcba71a27be14b19b01c0b67efbab0be9 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Tue, 1 Nov 2016 01:04:31 +0800 Subject: staging: iio: rework regulator handling Currently, the affected drivers ignore all errors from regulator_get(). The way it is now, it also breaks probe deferral (EPROBE_DEFER). The correct behavior is to propagate the error to the upper layers so they can handle it accordingly. Rework the regulator handling so that it matches the standard behavior. If the specific design uses a static always-on regulator and does not explicitly specify it, regulator_get() will return the dummy regulator. The following semantic patch was used to apply the change: @r1@ expression reg, dev, en, volt; @@ reg = \(devm_regulator_get\|regulator_get\)(dev, ...); if ( - ! IS_ERR(reg)) + return PTR_ERR(reg); ( - { en = regulator_enable(reg); - if (en) return en; } + + en = regulator_enable(reg); + if (en) { + dev_err(dev, "Failed to enable specified supply\n"); + return en; } | + - { en = regulator_enable(reg); - if (en) return en; - volt = regulator_get_voltage(reg); } + en = regulator_enable(reg); + if (en) { + dev_err(dev, "Failed to enable specified supply\n"); + return en; + } + volt = regulator_get_voltage(reg); ) @r2@ expression arg; @@ - if (!IS_ERR(arg)) regulator_disable(arg); + regulator_disable(arg); Hand-edit the debugging prints with the supply name to become more specific. Suggested-by: Lars-Peter Clausen Signed-off-by: Eva Rachel Retuya Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 18 +++++++++--------- drivers/staging/iio/adc/ad7780.c | 18 +++++++++--------- drivers/staging/iio/frequency/ad9832.c | 17 +++++++++-------- drivers/staging/iio/frequency/ad9834.c | 17 +++++++++-------- drivers/staging/iio/impedance-analyzer/ad5933.c | 19 ++++++++++--------- 5 files changed, 46 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 41fb32de5992..29e32b71f0f7 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -634,13 +634,15 @@ static int ad7192_probe(struct spi_device *spi) st = iio_priv(indio_dev); st->reg = devm_regulator_get(&spi->dev, "avdd"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - return ret; + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); - voltage_uv = regulator_get_voltage(st->reg); + ret = regulator_enable(st->reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable specified AVdd supply\n"); + return ret; } + voltage_uv = regulator_get_voltage(st->reg); if (pdata->vref_mv) st->int_vref_mv = pdata->vref_mv; @@ -689,8 +691,7 @@ static int ad7192_probe(struct spi_device *spi) error_remove_trigger: ad_sd_cleanup_buffer_and_trigger(indio_dev); error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return ret; } @@ -703,8 +704,7 @@ static int ad7192_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ad_sd_cleanup_buffer_and_trigger(indio_dev); - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return 0; } diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index a88236e74cdb..e14960038d3e 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -174,13 +174,15 @@ static int ad7780_probe(struct spi_device *spi) ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info); st->reg = devm_regulator_get(&spi->dev, "avdd"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - return ret; + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); - voltage_uv = regulator_get_voltage(st->reg); + ret = regulator_enable(st->reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable specified AVdd supply\n"); + return ret; } + voltage_uv = regulator_get_voltage(st->reg); st->chip_info = &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; @@ -222,8 +224,7 @@ static int ad7780_probe(struct spi_device *spi) error_cleanup_buffer_and_trigger: ad_sd_cleanup_buffer_and_trigger(indio_dev); error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return ret; } @@ -236,8 +237,7 @@ static int ad7780_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ad_sd_cleanup_buffer_and_trigger(indio_dev); - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return 0; } diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index 744c8ee9c5a6..7d8dc6cab720 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -213,10 +213,13 @@ static int ad9832_probe(struct spi_device *spi) } reg = devm_regulator_get(&spi->dev, "avdd"); - if (!IS_ERR(reg)) { - ret = regulator_enable(reg); - if (ret) - return ret; + if (IS_ERR(reg)) + return PTR_ERR(reg); + + ret = regulator_enable(reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable specified AVDD supply\n"); + return ret; } indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); @@ -311,8 +314,7 @@ static int ad9832_probe(struct spi_device *spi) return 0; error_disable_reg: - if (!IS_ERR(reg)) - regulator_disable(reg); + regulator_disable(reg); return ret; } @@ -323,8 +325,7 @@ static int ad9832_remove(struct spi_device *spi) struct ad9832_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return 0; } diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index ca3cea68d8d7..19216af1dfc9 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -330,10 +330,13 @@ static int ad9834_probe(struct spi_device *spi) } reg = devm_regulator_get(&spi->dev, "avdd"); - if (!IS_ERR(reg)) { - ret = regulator_enable(reg); - if (ret) - return ret; + if (IS_ERR(reg)) + return PTR_ERR(reg); + + ret = regulator_enable(reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable specified AVDD supply\n"); + return ret; } indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); @@ -416,8 +419,7 @@ static int ad9834_probe(struct spi_device *spi) return 0; error_disable_reg: - if (!IS_ERR(reg)) - regulator_disable(reg); + regulator_disable(reg); return ret; } @@ -428,8 +430,7 @@ static int ad9834_remove(struct spi_device *spi) struct ad9834_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return 0; } diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 62f61bcc0003..8f2736a0f854 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -724,12 +724,15 @@ static int ad5933_probe(struct i2c_client *client, pdata = &ad5933_default_pdata; st->reg = devm_regulator_get(&client->dev, "vdd"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - return ret; - voltage_uv = regulator_get_voltage(st->reg); + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); + + ret = regulator_enable(st->reg); + if (ret) { + dev_err(&client->dev, "Failed to enable specified VDD supply\n"); + return ret; } + voltage_uv = regulator_get_voltage(st->reg); if (voltage_uv) st->vref_mv = voltage_uv / 1000; @@ -772,8 +775,7 @@ static int ad5933_probe(struct i2c_client *client, error_unreg_ring: iio_kfifo_free(indio_dev->buffer); error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return ret; } @@ -785,8 +787,7 @@ static int ad5933_remove(struct i2c_client *client) iio_device_unregister(indio_dev); iio_kfifo_free(indio_dev->buffer); - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + regulator_disable(st->reg); return 0; } -- cgit v1.2.3 From cb8bb16caf42fd4f7eba69ee1889260af6e43ca1 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Tue, 1 Nov 2016 01:04:32 +0800 Subject: staging: iio: ad7192: add DVdd regulator The AD7190/AD7192/AD7193/AD7195 is supplied with two power sources: AVdd as analog supply voltage and DVdd as digital supply voltage. Attempt to fetch and enable the regulator 'dvdd'. Bail out if any error occurs. Suggested-by: Lars-Peter Clausen Signed-off-by: Eva Rachel Retuya Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 29e32b71f0f7..3f8dc6608fe7 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -153,6 +153,7 @@ struct ad7192_state { struct regulator *reg; + struct regulator *dvdd; u16 int_vref_mv; u32 mclk; u32 f_order; @@ -642,6 +643,19 @@ static int ad7192_probe(struct spi_device *spi) dev_err(&spi->dev, "Failed to enable specified AVdd supply\n"); return ret; } + + st->dvdd = devm_regulator_get(&spi->dev, "dvdd"); + if (IS_ERR(st->dvdd)) { + ret = PTR_ERR(st->dvdd); + goto error_disable_reg; + } + + ret = regulator_enable(st->dvdd); + if (ret) { + dev_err(&spi->dev, "Failed to enable specified DVdd supply\n"); + goto error_disable_reg; + } + voltage_uv = regulator_get_voltage(st->reg); if (pdata->vref_mv) @@ -677,7 +691,7 @@ static int ad7192_probe(struct spi_device *spi) ret = ad_sd_setup_buffer_and_trigger(indio_dev); if (ret) - goto error_disable_reg; + goto error_disable_dvdd; ret = ad7192_setup(st, pdata); if (ret) @@ -690,6 +704,8 @@ static int ad7192_probe(struct spi_device *spi) error_remove_trigger: ad_sd_cleanup_buffer_and_trigger(indio_dev); +error_disable_dvdd: + regulator_disable(st->dvdd); error_disable_reg: regulator_disable(st->reg); @@ -704,6 +720,7 @@ static int ad7192_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ad_sd_cleanup_buffer_and_trigger(indio_dev); + regulator_disable(st->dvdd); regulator_disable(st->reg); return 0; -- cgit v1.2.3 From 9d1548143faf00142937e37c359047a52a2d0d1d Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Tue, 1 Nov 2016 01:04:33 +0800 Subject: staging: iio: ad7192: rename regulator 'reg' to 'avdd' Rename regulator 'reg' to 'avdd' so as to be clear what regulator it stands for specifically. Also, update the goto label accordingly. Signed-off-by: Eva Rachel Retuya Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 3f8dc6608fe7..1fb68c01abd5 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -152,7 +152,7 @@ */ struct ad7192_state { - struct regulator *reg; + struct regulator *avdd; struct regulator *dvdd; u16 int_vref_mv; u32 mclk; @@ -634,11 +634,11 @@ static int ad7192_probe(struct spi_device *spi) st = iio_priv(indio_dev); - st->reg = devm_regulator_get(&spi->dev, "avdd"); - if (IS_ERR(st->reg)) - return PTR_ERR(st->reg); + st->avdd = devm_regulator_get(&spi->dev, "avdd"); + if (IS_ERR(st->avdd)) + return PTR_ERR(st->avdd); - ret = regulator_enable(st->reg); + ret = regulator_enable(st->avdd); if (ret) { dev_err(&spi->dev, "Failed to enable specified AVdd supply\n"); return ret; @@ -647,16 +647,16 @@ static int ad7192_probe(struct spi_device *spi) st->dvdd = devm_regulator_get(&spi->dev, "dvdd"); if (IS_ERR(st->dvdd)) { ret = PTR_ERR(st->dvdd); - goto error_disable_reg; + goto error_disable_avdd; } ret = regulator_enable(st->dvdd); if (ret) { dev_err(&spi->dev, "Failed to enable specified DVdd supply\n"); - goto error_disable_reg; + goto error_disable_avdd; } - voltage_uv = regulator_get_voltage(st->reg); + voltage_uv = regulator_get_voltage(st->avdd); if (pdata->vref_mv) st->int_vref_mv = pdata->vref_mv; @@ -706,8 +706,8 @@ error_remove_trigger: ad_sd_cleanup_buffer_and_trigger(indio_dev); error_disable_dvdd: regulator_disable(st->dvdd); -error_disable_reg: - regulator_disable(st->reg); +error_disable_avdd: + regulator_disable(st->avdd); return ret; } @@ -721,7 +721,7 @@ static int ad7192_remove(struct spi_device *spi) ad_sd_cleanup_buffer_and_trigger(indio_dev); regulator_disable(st->dvdd); - regulator_disable(st->reg); + regulator_disable(st->avdd); return 0; } -- cgit v1.2.3 From a98461d79ba5bd9c5a83be3f5860cba5d5b54617 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Tue, 1 Nov 2016 01:04:34 +0800 Subject: staging: iio: ad9832: add DVDD regulator The AD9832/AD9835 is supplied with two power sources: AVDD as analog supply voltage and DVDD as digital supply voltage. Attempt to fetch and enable the regulator 'dvdd'. Bail out if any error occurs. Suggested-by: Lars-Peter Clausen Signed-off-by: Eva Rachel Retuya Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9832.c | 33 ++++++++++++++++++++++++--------- drivers/staging/iio/frequency/ad9832.h | 2 ++ 2 files changed, 26 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index 7d8dc6cab720..6a5ab02e64ef 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -222,10 +222,22 @@ static int ad9832_probe(struct spi_device *spi) return ret; } + st->dvdd = devm_regulator_get(&spi->dev, "dvdd"); + if (IS_ERR(st->dvdd)) { + ret = PTR_ERR(st->dvdd); + goto error_disable_reg; + } + + ret = regulator_enable(st->dvdd); + if (ret) { + dev_err(&spi->dev, "Failed to enable specified DVDD supply\n"); + goto error_disable_reg; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) { ret = -ENOMEM; - goto error_disable_reg; + goto error_disable_dvdd; } spi_set_drvdata(spi, indio_dev); st = iio_priv(indio_dev); @@ -280,39 +292,41 @@ static int ad9832_probe(struct spi_device *spi) ret = spi_sync(st->spi, &st->msg); if (ret) { dev_err(&spi->dev, "device init failed\n"); - goto error_disable_reg; + goto error_disable_dvdd; } ret = ad9832_write_frequency(st, AD9832_FREQ0HM, pdata->freq0); if (ret) - goto error_disable_reg; + goto error_disable_dvdd; ret = ad9832_write_frequency(st, AD9832_FREQ1HM, pdata->freq1); if (ret) - goto error_disable_reg; + goto error_disable_dvdd; ret = ad9832_write_phase(st, AD9832_PHASE0H, pdata->phase0); if (ret) - goto error_disable_reg; + goto error_disable_dvdd; ret = ad9832_write_phase(st, AD9832_PHASE1H, pdata->phase1); if (ret) - goto error_disable_reg; + goto error_disable_dvdd; ret = ad9832_write_phase(st, AD9832_PHASE2H, pdata->phase2); if (ret) - goto error_disable_reg; + goto error_disable_dvdd; ret = ad9832_write_phase(st, AD9832_PHASE3H, pdata->phase3); if (ret) - goto error_disable_reg; + goto error_disable_dvdd; ret = iio_device_register(indio_dev); if (ret) - goto error_disable_reg; + goto error_disable_dvdd; return 0; +error_disable_dvdd: + regulator_disable(st->dvdd); error_disable_reg: regulator_disable(reg); @@ -325,6 +339,7 @@ static int ad9832_remove(struct spi_device *spi) struct ad9832_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); + regulator_disable(st->dvdd); regulator_disable(st->reg); return 0; diff --git a/drivers/staging/iio/frequency/ad9832.h b/drivers/staging/iio/frequency/ad9832.h index d32323b46be6..eb0e7f293169 100644 --- a/drivers/staging/iio/frequency/ad9832.h +++ b/drivers/staging/iio/frequency/ad9832.h @@ -59,6 +59,7 @@ * struct ad9832_state - driver instance specific data * @spi: spi_device * @reg: supply regulator + * @dvdd: supply regulator for the digital section * @mclk: external master clock * @ctrl_fp: cached frequency/phase control word * @ctrl_ss: cached sync/selsrc control word @@ -77,6 +78,7 @@ struct ad9832_state { struct spi_device *spi; struct regulator *reg; + struct regulator *dvdd; unsigned long mclk; unsigned short ctrl_fp; unsigned short ctrl_ss; -- cgit v1.2.3 From 43a07e48af44c153f960e4a204771d5911e10134 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Tue, 1 Nov 2016 01:04:35 +0800 Subject: staging: iio: ad9832: clean-up regulator 'reg' Rename regulator 'reg' to 'avdd' so as to be clear what regulator it stands for specifically. Additionally, get rid of local variable 'reg' and use direct assignment instead. Update also the goto label pertaining to the avdd regulator during disable. Signed-off-by: Eva Rachel Retuya Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9832.c | 20 +++++++++----------- drivers/staging/iio/frequency/ad9832.h | 4 ++-- 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index 6a5ab02e64ef..639047fade30 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -204,7 +204,6 @@ static int ad9832_probe(struct spi_device *spi) struct ad9832_platform_data *pdata = dev_get_platdata(&spi->dev); struct iio_dev *indio_dev; struct ad9832_state *st; - struct regulator *reg; int ret; if (!pdata) { @@ -212,11 +211,11 @@ static int ad9832_probe(struct spi_device *spi) return -ENODEV; } - reg = devm_regulator_get(&spi->dev, "avdd"); - if (IS_ERR(reg)) - return PTR_ERR(reg); + st->avdd = devm_regulator_get(&spi->dev, "avdd"); + if (IS_ERR(st->avdd)) + return PTR_ERR(st->avdd); - ret = regulator_enable(reg); + ret = regulator_enable(st->avdd); if (ret) { dev_err(&spi->dev, "Failed to enable specified AVDD supply\n"); return ret; @@ -225,13 +224,13 @@ static int ad9832_probe(struct spi_device *spi) st->dvdd = devm_regulator_get(&spi->dev, "dvdd"); if (IS_ERR(st->dvdd)) { ret = PTR_ERR(st->dvdd); - goto error_disable_reg; + goto error_disable_avdd; } ret = regulator_enable(st->dvdd); if (ret) { dev_err(&spi->dev, "Failed to enable specified DVDD supply\n"); - goto error_disable_reg; + goto error_disable_avdd; } indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); @@ -241,7 +240,6 @@ static int ad9832_probe(struct spi_device *spi) } spi_set_drvdata(spi, indio_dev); st = iio_priv(indio_dev); - st->reg = reg; st->mclk = pdata->mclk; st->spi = spi; @@ -327,8 +325,8 @@ static int ad9832_probe(struct spi_device *spi) error_disable_dvdd: regulator_disable(st->dvdd); -error_disable_reg: - regulator_disable(reg); +error_disable_avdd: + regulator_disable(st->avdd); return ret; } @@ -340,7 +338,7 @@ static int ad9832_remove(struct spi_device *spi) iio_device_unregister(indio_dev); regulator_disable(st->dvdd); - regulator_disable(st->reg); + regulator_disable(st->avdd); return 0; } diff --git a/drivers/staging/iio/frequency/ad9832.h b/drivers/staging/iio/frequency/ad9832.h index eb0e7f293169..1b08b04482a4 100644 --- a/drivers/staging/iio/frequency/ad9832.h +++ b/drivers/staging/iio/frequency/ad9832.h @@ -58,7 +58,7 @@ /** * struct ad9832_state - driver instance specific data * @spi: spi_device - * @reg: supply regulator + * @avdd: supply regulator for the analog section * @dvdd: supply regulator for the digital section * @mclk: external master clock * @ctrl_fp: cached frequency/phase control word @@ -77,7 +77,7 @@ struct ad9832_state { struct spi_device *spi; - struct regulator *reg; + struct regulator *avdd; struct regulator *dvdd; unsigned long mclk; unsigned short ctrl_fp; -- cgit v1.2.3 From ab54163190f236e30772e6e8b4efc56a319ed0a6 Mon Sep 17 00:00:00 2001 From: Song Hongyan Date: Thu, 3 Nov 2016 00:45:48 +0000 Subject: iio: hid-sensor-attributes: Check sample_frequency/hysteresis write data legitimacy Neither sample frequency value nor hysteresis value can be set to be a negative number, check and return "Invalid argument" if they are negative. If not do this change, sample_frequency will be set into some unknown value, read hysteresis value after write negative number will return "Invalid argument". Signed-off-by: Song Hongyan Acked-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/common/hid-sensors/hid-sensor-attributes.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index dc33c1dd5191..4509f8475c54 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -201,7 +201,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, int ret; if (val1 < 0 || val2 < 0) - ret = -EINVAL; + return -EINVAL; value = val1 * pow_10(6) + val2; if (value) { @@ -250,6 +250,9 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, s32 value; int ret; + if (val1 < 0 || val2 < 0) + return -EINVAL; + value = convert_to_vtf_format(st->sensitivity.size, st->sensitivity.unit_expo, val1, val2); -- cgit v1.2.3 From bc3ae982e2fb498e2f5492497ea927a161380bc1 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Wed, 2 Nov 2016 17:21:48 +0800 Subject: iio: adc: at91: add suspend and resume callback Add suspend/resume callback, support the pinctrl sleep state when the system suspend as well. Signed-off-by: Wenyou Yang Acked-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index bbdac07f4aaa..34b928cefeed 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -30,6 +30,7 @@ #include #include #include +#include /* Registers */ #define AT91_ADC_CR 0x00 /* Control Register */ @@ -1347,6 +1348,32 @@ static int at91_adc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int at91_adc_suspend(struct device *dev) +{ + struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(idev); + + pinctrl_pm_select_sleep_state(dev); + clk_disable_unprepare(st->clk); + + return 0; +} + +static int at91_adc_resume(struct device *dev) +{ + struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(idev); + + clk_prepare_enable(st->clk); + pinctrl_pm_select_default_state(dev); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume); + static struct at91_adc_caps at91sam9260_caps = { .calc_startup_ticks = calc_startup_ticks_9260, .num_channels = 4, @@ -1441,6 +1468,7 @@ static struct platform_driver at91_adc_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(at91_adc_dt_ids), + .pm = &at91_adc_pm_ops, }, }; -- cgit v1.2.3 From c9329d8638cfa1a86faf4fb8bd4922a3d9c6c437 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Wed, 5 Oct 2016 14:34:40 +0530 Subject: mfd: ti_am335x_tscadc: store physical address store the physical address of the device in its priv to use it for DMA addressing in the client drivers. Signed-off-by: Mugunthan V N Acked-for-MFD-by: Lee Jones Signed-off-by: Jonathan Cameron --- drivers/mfd/ti_am335x_tscadc.c | 1 + include/linux/mfd/ti_am335x_tscadc.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index c8f027b4ea4c..0f3fab47fe48 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -183,6 +183,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) tscadc->irq = err; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + tscadc->tscadc_phys_base = res->start; tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(tscadc->tscadc_base)) return PTR_ERR(tscadc->tscadc_base); diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 7f55b8b41032..e45a208d9944 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -155,6 +155,7 @@ struct ti_tscadc_dev { struct device *dev; struct regmap *regmap; void __iomem *tscadc_base; + phys_addr_t tscadc_phys_base; int irq; int used_cells; /* 1-2 */ int tsc_wires; -- cgit v1.2.3 From f438b9da75eb80eb6c4095a5b75324cc9a7f0570 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Wed, 5 Oct 2016 14:34:41 +0530 Subject: drivers: iio: ti_am335x_adc: add dma support This patch adds the required pieces to ti_am335x_adc driver for DMA support Signed-off-by: Mugunthan V N Reviewed-by: Peter Ujfalusi Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 148 ++++++++++++++++++++++++++++++++++- include/linux/mfd/ti_am335x_tscadc.h | 7 ++ 2 files changed, 152 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index c3cfacca2541..ad9dec30bb30 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -30,10 +30,28 @@ #include #include +#include +#include + +#define DMA_BUFFER_SIZE SZ_2K + +struct tiadc_dma { + struct dma_slave_config conf; + struct dma_chan *chan; + dma_addr_t addr; + dma_cookie_t cookie; + u8 *buf; + int current_period; + int period_size; + u8 fifo_thresh; +}; + struct tiadc_device { struct ti_tscadc_dev *mfd_tscadc; + struct tiadc_dma dma; struct mutex fifo1_lock; /* to protect fifo access */ int channels; + int total_ch_enabled; u8 channel_line[8]; u8 channel_step[8]; int buffer_en_ch_steps; @@ -198,6 +216,67 @@ static irqreturn_t tiadc_worker_h(int irq, void *private) return IRQ_HANDLED; } +static void tiadc_dma_rx_complete(void *param) +{ + struct iio_dev *indio_dev = param; + struct tiadc_device *adc_dev = iio_priv(indio_dev); + struct tiadc_dma *dma = &adc_dev->dma; + u8 *data; + int i; + + data = dma->buf + dma->current_period * dma->period_size; + dma->current_period = 1 - dma->current_period; /* swap the buffer ID */ + + for (i = 0; i < dma->period_size; i += indio_dev->scan_bytes) { + iio_push_to_buffers(indio_dev, data); + data += indio_dev->scan_bytes; + } +} + +static int tiadc_start_dma(struct iio_dev *indio_dev) +{ + struct tiadc_device *adc_dev = iio_priv(indio_dev); + struct tiadc_dma *dma = &adc_dev->dma; + struct dma_async_tx_descriptor *desc; + + dma->current_period = 0; /* We start to fill period 0 */ + /* + * Make the fifo thresh as the multiple of total number of + * channels enabled, so make sure that cyclic DMA period + * length is also a multiple of total number of channels + * enabled. This ensures that no invalid data is reported + * to the stack via iio_push_to_buffers(). + */ + dma->fifo_thresh = rounddown(FIFO1_THRESHOLD + 1, + adc_dev->total_ch_enabled) - 1; + /* Make sure that period length is multiple of fifo thresh level */ + dma->period_size = rounddown(DMA_BUFFER_SIZE / 2, + (dma->fifo_thresh + 1) * sizeof(u16)); + + dma->conf.src_maxburst = dma->fifo_thresh + 1; + dmaengine_slave_config(dma->chan, &dma->conf); + + desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr, + dma->period_size * 2, + dma->period_size, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + if (!desc) + return -EBUSY; + + desc->callback = tiadc_dma_rx_complete; + desc->callback_param = indio_dev; + + dma->cookie = dmaengine_submit(desc); + + dma_async_issue_pending(dma->chan); + + tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh); + tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh); + tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1); + + return 0; +} + static int tiadc_buffer_preenable(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); @@ -218,20 +297,30 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev) static int tiadc_buffer_postenable(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); + struct tiadc_dma *dma = &adc_dev->dma; + unsigned int irq_enable; unsigned int enb = 0; u8 bit; tiadc_step_config(indio_dev); - for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) + for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) { enb |= (get_adc_step_bit(adc_dev, bit) << 1); + adc_dev->total_ch_enabled++; + } adc_dev->buffer_en_ch_steps = enb; + if (dma->chan) + tiadc_start_dma(indio_dev); + am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb); tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW); - tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES - | IRQENB_FIFO1OVRRUN); + + irq_enable = IRQENB_FIFO1OVRRUN; + if (!dma->chan) + irq_enable |= IRQENB_FIFO1THRES; + tiadc_writel(adc_dev, REG_IRQENABLE, irq_enable); return 0; } @@ -239,12 +328,18 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev) static int tiadc_buffer_predisable(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); + struct tiadc_dma *dma = &adc_dev->dma; int fifo1count, i, read; tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps); adc_dev->buffer_en_ch_steps = 0; + adc_dev->total_ch_enabled = 0; + if (dma->chan) { + tiadc_writel(adc_dev, REG_DMAENABLE_CLEAR, 0x2); + dmaengine_terminate_async(dma->chan); + } /* Flush FIFO of leftover data in the time it takes to disable adc */ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); @@ -430,6 +525,41 @@ static const struct iio_info tiadc_info = { .driver_module = THIS_MODULE, }; +static int tiadc_request_dma(struct platform_device *pdev, + struct tiadc_device *adc_dev) +{ + struct tiadc_dma *dma = &adc_dev->dma; + dma_cap_mask_t mask; + + /* Default slave configuration parameters */ + dma->conf.direction = DMA_DEV_TO_MEM; + dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1; + + dma_cap_zero(mask); + dma_cap_set(DMA_CYCLIC, mask); + + /* Get a channel for RX */ + dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1"); + if (IS_ERR(dma->chan)) { + int ret = PTR_ERR(dma->chan); + + dma->chan = NULL; + return ret; + } + + /* RX buffer */ + dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE, + &dma->addr, GFP_KERNEL); + if (!dma->buf) + goto err; + + return 0; +err: + dma_release_channel(dma->chan); + return -ENOMEM; +} + static int tiadc_parse_dt(struct platform_device *pdev, struct tiadc_device *adc_dev) { @@ -512,8 +642,14 @@ static int tiadc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); + err = tiadc_request_dma(pdev, adc_dev); + if (err && err == -EPROBE_DEFER) + goto err_dma; + return 0; +err_dma: + iio_device_unregister(indio_dev); err_buffer_unregister: tiadc_iio_buffered_hardware_remove(indio_dev); err_free_channels: @@ -525,8 +661,14 @@ static int tiadc_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct tiadc_device *adc_dev = iio_priv(indio_dev); + struct tiadc_dma *dma = &adc_dev->dma; u32 step_en; + if (dma->chan) { + dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE, + dma->buf, dma->addr); + dma_release_channel(dma->chan); + } iio_device_unregister(indio_dev); tiadc_iio_buffered_hardware_remove(indio_dev); tiadc_channels_remove(indio_dev); diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index e45a208d9944..b9a53e013bff 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -23,6 +23,8 @@ #define REG_IRQENABLE 0x02C #define REG_IRQCLR 0x030 #define REG_IRQWAKEUP 0x034 +#define REG_DMAENABLE_SET 0x038 +#define REG_DMAENABLE_CLEAR 0x03c #define REG_CTRL 0x040 #define REG_ADCFSM 0x044 #define REG_CLKDIV 0x04C @@ -36,6 +38,7 @@ #define REG_FIFO0THR 0xE8 #define REG_FIFO1CNT 0xF0 #define REG_FIFO1THR 0xF4 +#define REG_DMA1REQ 0xF8 #define REG_FIFO0 0x100 #define REG_FIFO1 0x200 @@ -126,6 +129,10 @@ #define FIFOREAD_DATA_MASK (0xfff << 0) #define FIFOREAD_CHNLID_MASK (0xf << 16) +/* DMA ENABLE/CLEAR Register */ +#define DMA_FIFO0 BIT(0) +#define DMA_FIFO1 BIT(1) + /* Sequencer Status */ #define SEQ_STATUS BIT(5) #define CHARGE_STEP 0x11 -- cgit v1.2.3 From b6e417977da87b246e356797c2af42002343aa9f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 2 Nov 2016 12:49:57 +0000 Subject: mlxsw: Remove unused including Remove including that don't need it. Signed-off-by: Wei Yongjun Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 1 - drivers/net/ethernet/mellanox/mlxsw/switchib.c | 1 - drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 8bca020e3fae..a5433e425484 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c index ec0b27e72a5d..1552594b2d1f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchib.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c @@ -43,7 +43,6 @@ #include #include #include -#include #include "pci.h" #include "core.h" diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 5208764797ba..60f19fb68e5f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -45,7 +45,6 @@ #include #include #include -#include #include "pci.h" #include "core.h" -- cgit v1.2.3 From 15607a3ad4272ed6f781a5250479c87746746dda Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Sat, 5 Nov 2016 16:15:03 +0100 Subject: HID: intel-ish-hid: initialize ts_format.reserved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ts_format.reserved is not used anywhere yet, but the compiler generates a warning when the struct's (uninitialized) field is being copied around drivers/hid/intel-ish-hid/ipc/ipc.c: In function ‘write_ipc_from_queue’: drivers/hid/intel-ish-hid/ipc/ipc.c:316: warning: ‘ts_format.reserved’ may be used uninitialized in this function Avoid this by force-initializing the field to zero. Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ipc/ipc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index e2517c11e0ee..37f069749672 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -310,6 +310,7 @@ static int write_ipc_from_queue(struct ishtp_device *dev) ((uint32_t)tv_utc.tv_usec); ts_format.ts1_source = HOST_SYSTEM_TIME_USEC; ts_format.ts2_source = HOST_UTC_TIME_USEC; + ts_format.reserved = 0; time_update.primary_host_time = usec_system; time_update.secondary_host_time = usec_utc; -- cgit v1.2.3 From 82e56393a80b99cf8986616447d71cbcff90e9d1 Mon Sep 17 00:00:00 2001 From: Paweł Jarosz Date: Fri, 4 Nov 2016 14:10:56 +0100 Subject: clk: rockchip: add 400MHz to rk3066 clock rates table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need this to init PLL_CPLL to 400MHz at boot. Signed-off-by: Paweł Jarosz Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3188.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index a6d398f4b18f..062ef4960244 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -89,6 +89,7 @@ static struct rockchip_pll_rate_table rk3188_pll_rates[] = { RK3066_PLL_RATE( 504000000, 1, 84, 4), RK3066_PLL_RATE( 456000000, 1, 76, 4), RK3066_PLL_RATE( 408000000, 1, 68, 4), + RK3066_PLL_RATE( 400000000, 3, 100, 2), RK3066_PLL_RATE( 384000000, 2, 128, 4), RK3066_PLL_RATE( 360000000, 1, 60, 4), RK3066_PLL_RATE( 312000000, 1, 52, 4), -- cgit v1.2.3 From 161baaea7c34e5b91174d994b82570ef0555eb1d Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 3 Nov 2016 11:38:53 +0800 Subject: clk: rockchip: remove more CLK_IGNORE_UNUSED for rk3399 clocktree Optimize rk3399 clocktree by removing CLK_IGNORE_UNUSED of some clocks. clocks will managered by usb: - clk_usbphy0_480m_src - clk_usbphy1_480m_src - clk_usbphy_480m clocks will be managered by pvtm: - clk_pvtm_core_l - clk_pvtm_core_b - clk_pvtm_ddr clocks will be managered by dfi: - pclk_ddr_mon - clk_dfimon0_timer - clk_dfimon1_timer - aclk_dcf - pclk_dcf Signed-off-by: Jianqun Xu Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 28aff4507d96..828005556376 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -411,11 +411,11 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(6), 6, GFLAGS), - GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", CLK_IGNORE_UNUSED, + GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", 0, RK3399_CLKGATE_CON(13), 12, GFLAGS), - GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", CLK_IGNORE_UNUSED, + GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", 0, RK3399_CLKGATE_CON(13), 12, GFLAGS), - MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, CLK_IGNORE_UNUSED, + MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, 0, RK3399_CLKSEL_CON(14), 6, 1, MFLAGS), MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0, @@ -499,7 +499,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(14), 10, GFLAGS), GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(14), 11, GFLAGS), - GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", 0, RK3399_CLKGATE_CON(0), 7, GFLAGS), /* big core */ @@ -540,7 +540,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(14), 2, GFLAGS), - GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", 0, RK3399_CLKGATE_CON(1), 7, GFLAGS), /* gmac */ @@ -676,18 +676,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(18), 10, GFLAGS), - GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED, + GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", 0, RK3399_CLKGATE_CON(18), 12, GFLAGS), GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(18), 15, GFLAGS), GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(19), 2, GFLAGS), - GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", 0, RK3399_CLKGATE_CON(4), 11, GFLAGS), - GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", 0, RK3399_CLKGATE_CON(3), 5, GFLAGS), - GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", 0, RK3399_CLKGATE_CON(3), 6, GFLAGS), /* cci */ @@ -967,7 +967,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS), GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS), GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS), - GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS), + GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", 0, RK3399_CLKGATE_CON(23), 8, GFLAGS), GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS), GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS), GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS), @@ -981,7 +981,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS), /* pclk_perilp0 gates */ - GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS), + GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", 0, RK3399_CLKGATE_CON(23), 9, GFLAGS), /* crypto */ COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0, -- cgit v1.2.3 From bf92384b6d729b22916ba832b4a225ca196e98ba Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Wed, 2 Nov 2016 16:43:24 -0700 Subject: clk: rockchip: Ignore frac divisor for PLL equivalence when it's unused Rockchip RK3399 PLLs can be used in two separate modes: integral and fractional. We can select between these two modes with the unambiguously named DSMPD bit. During boot, we check all PLL settings to confirm that they match our PLL table for that frequency, and reinitialize the PLLs where they don't. The settings checked for this include the fractional divider field that is only used in fractional mode, even if we're in integral mode (DSMPD = 1) and that field has no effect. This patch changes the check to only compare the fractional divider if we're actually in fractional mode. This way, we won't reinitialize the PLL in cases where there's absolutely no reason for that, which may avoid glitching child clocks that should better not be glitched (e.g. PWM regulators). Signed-off-by: Julius Werner [cloned the fix to the pretty similar rk3036 pll] Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-pll.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 9c1373e81683..6ed605776abd 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -319,7 +319,8 @@ static void rockchip_rk3036_pll_init(struct clk_hw *hw) if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || - rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) { + rate->dsmpd != cur.dsmpd || + (!cur.dsmpd && (rate->frac != cur.frac))) { struct clk *parent = clk_get_parent(hw->clk); if (!parent) { @@ -795,7 +796,8 @@ static void rockchip_rk3399_pll_init(struct clk_hw *hw) if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || - rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) { + rate->dsmpd != cur.dsmpd || + (!cur.dsmpd && (rate->frac != cur.frac))) { struct clk *parent = clk_get_parent(hw->clk); if (!parent) { -- cgit v1.2.3 From d278d4a8892f13b6a9eb6102b356402f0e062324 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:21:08 -0600 Subject: block: add code to track actual device queue depth For blk-mq, ->nr_requests does track queue depth, at least at init time. But for the older queue paths, it's simply a soft setting. On top of that, it's generally larger than the hardware setting on purpose, to allow backup of requests for merging. Fill a hole in struct request with a 'queue_depth' member, that drivers can call to more closely inform the block layer of the real queue depth. Signed-off-by: Jens Axboe Reviewed-by: Jan Kara --- block/blk-settings.c | 12 ++++++++++++ drivers/scsi/scsi.c | 3 +++ include/linux/blkdev.h | 11 +++++++++++ 3 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/block/blk-settings.c b/block/blk-settings.c index 55369a65dea2..9cf053759363 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -836,6 +836,18 @@ void blk_queue_flush_queueable(struct request_queue *q, bool queueable) } EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); +/** + * blk_set_queue_depth - tell the block layer about the device queue depth + * @q: the request queue for the device + * @depth: queue depth + * + */ +void blk_set_queue_depth(struct request_queue *q, unsigned int depth) +{ + q->queue_depth = depth; +} +EXPORT_SYMBOL(blk_set_queue_depth); + /** * blk_queue_write_cache - configure queue's write cache * @q: the request queue for the device diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 1deb6adc411f..75455d4dab68 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -621,6 +621,9 @@ int scsi_change_queue_depth(struct scsi_device *sdev, int depth) wmb(); } + if (sdev->request_queue) + blk_set_queue_depth(sdev->request_queue, depth); + return sdev->queue_depth; } EXPORT_SYMBOL(scsi_change_queue_depth); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9189a2d5c392..d364be6e6959 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -405,6 +405,8 @@ struct request_queue { struct blk_mq_ctx __percpu *queue_ctx; unsigned int nr_queues; + unsigned int queue_depth; + /* hw dispatch queues */ struct blk_mq_hw_ctx **queue_hw_ctx; unsigned int nr_hw_queues; @@ -777,6 +779,14 @@ static inline bool blk_write_same_mergeable(struct bio *a, struct bio *b) return false; } +static inline unsigned int blk_queue_depth(struct request_queue *q) +{ + if (q->queue_depth) + return q->queue_depth; + + return q->nr_requests; +} + /* * q->prep_rq_fn return values */ @@ -1094,6 +1104,7 @@ extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min); extern void blk_queue_io_min(struct request_queue *q, unsigned int min); extern void blk_limits_io_opt(struct queue_limits *limits, unsigned int opt); extern void blk_queue_io_opt(struct request_queue *q, unsigned int opt); +extern void blk_set_queue_depth(struct request_queue *q, unsigned int depth); extern void blk_set_default_limits(struct queue_limits *lim); extern void blk_set_stacking_limits(struct queue_limits *lim); extern int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, -- cgit v1.2.3 From 6ba5dee90b2483f8a78081376f56e6b65c10ea92 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 3 Nov 2016 08:56:12 -0400 Subject: staging: iio: tsl2583: i2c_smbus_write_byte() / i2c_smbus_read_byte() migration There were several places where the driver would first call i2c_smbus_write_byte() to select the register on the device, and then call i2c_smbus_read_byte() to get the contents of that register. The code would look roughly like: /* Select register */ i2c_smbus_write_byte(client, REGISTER); /* Read the the last register that was written to */ int data = i2c_smbus_read_byte(client); Rewrite this to use i2c_smbus_read_byte_data() to combine the two calls into one: int data = i2c_smbus_read_byte_data(chip->client, REGISTER); Verified that the driver still functions correctly using a TSL2581 hooked up to a Raspberry Pi 2. This fixes the following warnings that were found by the kbuild test robot that were introduced by commit 8ba355cce3c6 ("staging: iio: tsl2583: check for error code from i2c_smbus_read_byte()"). drivers/staging/iio/light/tsl2583.c:365:5-12: WARNING: Unsigned expression compared with zero: reg_val < 0 drivers/staging/iio/light/tsl2583.c:388:5-12: WARNING: Unsigned expression compared with zero: reg_val < 0 This also removes the need for the taos_i2c_read() function since all callers were only calling the function with a length of 1. Signed-off-by: Brian Masney Cc: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 85 +++++++------------------------------ 1 file changed, 16 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 49b19f5c1d84..a3a909560c88 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -154,39 +154,6 @@ static void taos_defaults(struct tsl2583_chip *chip) /* Known external ALS reading used for calibration */ } -/* - * Read a number of bytes starting at register (reg) location. - * Return 0, or i2c_smbus_write_byte ERROR code. - */ -static int -taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) -{ - int i, ret; - - for (i = 0; i < len; i++) { - /* select register to write */ - ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | reg)); - if (ret < 0) { - dev_err(&client->dev, - "taos_i2c_read failed to write register %x\n", - reg); - return ret; - } - /* read the data */ - ret = i2c_smbus_read_byte(client); - if (ret < 0) { - dev_err(&client->dev, - "%s failed to read byte after writing to register %x\n", - __func__, reg); - return ret; - } - *val = ret; - val++; - reg++; - } - return 0; -} - /* * Reads and calculates current lux value. * The raw ch0 and ch1 values of the ambient light sensed in the last @@ -220,13 +187,14 @@ static int taos_get_lux(struct iio_dev *indio_dev) goto done; } - ret = taos_i2c_read(chip->client, (TSL258X_CMD_REG), &buf[0], 1); + ret = i2c_smbus_read_byte_data(chip->client, TSL258X_CMD_REG); if (ret < 0) { dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n"); goto done; } + /* is data new & valid */ - if (!(buf[0] & TSL258X_STA_ADC_INTR)) { + if (!(ret & TSL258X_STA_ADC_INTR)) { dev_err(&chip->client->dev, "taos_get_lux data not valid\n"); ret = chip->als_cur_info.lux; /* return LAST VALUE */ goto done; @@ -235,13 +203,14 @@ static int taos_get_lux(struct iio_dev *indio_dev) for (i = 0; i < 4; i++) { int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i); - ret = taos_i2c_read(chip->client, reg, &buf[i], 1); + ret = i2c_smbus_read_byte_data(chip->client, reg); if (ret < 0) { dev_err(&chip->client->dev, "taos_get_lux failed to read register %x\n", reg); goto done; } + buf[i] = ret; } /* @@ -343,52 +312,36 @@ done: static int taos_als_calibrate(struct iio_dev *indio_dev) { struct tsl2583_chip *chip = iio_priv(indio_dev); - u8 reg_val; unsigned int gain_trim_val; int ret; int lux_val; - ret = i2c_smbus_write_byte(chip->client, - (TSL258X_CMD_REG | TSL258X_CNTRL)); + ret = i2c_smbus_read_byte_data(chip->client, + TSL258X_CMD_REG | TSL258X_CNTRL); if (ret < 0) { dev_err(&chip->client->dev, - "taos_als_calibrate failed to reach the CNTRL register, ret=%d\n", - ret); - return ret; - } - - reg_val = i2c_smbus_read_byte(chip->client); - if (reg_val < 0) { - dev_err(&chip->client->dev, - "%s failed to read after writing to the CNTRL register\n", + "%s failed to read from the CNTRL register\n", __func__); return ret; } - if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) + if ((ret & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) != (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) { dev_err(&chip->client->dev, "taos_als_calibrate failed: device not powered on with ADC enabled\n"); return -EINVAL; } - ret = i2c_smbus_write_byte(chip->client, - (TSL258X_CMD_REG | TSL258X_CNTRL)); + ret = i2c_smbus_read_byte_data(chip->client, + TSL258X_CMD_REG | TSL258X_CNTRL); if (ret < 0) { dev_err(&chip->client->dev, - "taos_als_calibrate failed to reach the STATUS register, ret=%d\n", - ret); - return ret; - } - reg_val = i2c_smbus_read_byte(chip->client); - if (reg_val < 0) { - dev_err(&chip->client->dev, - "%s failed to read after writing to the STATUS register\n", + "%s failed to read from the CNTRL register\n", __func__); return ret; } - if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { + if ((ret & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { dev_err(&chip->client->dev, "taos_als_calibrate failed: STATUS - ADC not valid.\n"); return -ENODATA; @@ -847,15 +800,9 @@ static int taos_probe(struct i2c_client *clientp, memcpy(chip->taos_config, taos_config, sizeof(chip->taos_config)); for (i = 0; i < TSL258X_MAX_DEVICE_REGS; i++) { - ret = i2c_smbus_write_byte(clientp, - (TSL258X_CMD_REG | (TSL258X_CNTRL + i))); - if (ret < 0) { - dev_err(&clientp->dev, - "i2c_smbus_write_byte to cmd reg failed in taos_probe(), err = %d\n", - ret); - return ret; - } - ret = i2c_smbus_read_byte(clientp); + ret = i2c_smbus_read_byte_data(clientp, + (TSL258X_CMD_REG | + (TSL258X_CNTRL + i))); if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_read_byte from reg failed in taos_probe(), err = %d\n", -- cgit v1.2.3 From 6bd0cb2b594b4a735301245cf9387c9c671e6168 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 3 Nov 2016 08:56:13 -0400 Subject: staging: iio: tsl2583: removed unused code from device probing taos_probe() queries the all of the sensor's registers and loads all of the values into a buffer stored on the stack. Only the chip ID register was actually used. Change the probe function to just query the chip ID register on the device. Verified that the driver still functions correctly using a TSL2581 hooked up to a Raspberry Pi 2. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index a3a909560c88..388440b4fcd7 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -31,8 +31,6 @@ #include #include -#define TSL258X_MAX_DEVICE_REGS 32 - /* Triton register offsets */ #define TSL258X_REG_MAX 8 @@ -66,6 +64,9 @@ /* Lux calculation constants */ #define TSL258X_LUX_CALC_OVER_FLOW 65535 +#define TSL2583_CHIP_ID 0x90 +#define TSL2583_CHIP_ID_MASK 0xf0 + enum { TSL258X_CHIP_UNKNOWN = 0, TSL258X_CHIP_WORKING = 1, @@ -607,12 +608,6 @@ static const struct attribute_group tsl2583_attribute_group = { .attrs = sysfs_attrs_ctrl, }; -/* Use the default register values to identify the Taos device */ -static int taos_tsl258x_device(unsigned char *bufp) -{ - return ((bufp[TSL258X_CHIPID] & 0xf0) == 0x90); -} - static const struct iio_chan_spec tsl2583_channels[] = { { .type = IIO_LIGHT, @@ -777,8 +772,7 @@ static const struct iio_info tsl2583_info = { static int taos_probe(struct i2c_client *clientp, const struct i2c_device_id *idp) { - int i, ret; - unsigned char buf[TSL258X_MAX_DEVICE_REGS]; + int ret; struct tsl2583_chip *chip; struct iio_dev *indio_dev; @@ -799,22 +793,17 @@ static int taos_probe(struct i2c_client *clientp, chip->taos_chip_status = TSL258X_CHIP_UNKNOWN; memcpy(chip->taos_config, taos_config, sizeof(chip->taos_config)); - for (i = 0; i < TSL258X_MAX_DEVICE_REGS; i++) { - ret = i2c_smbus_read_byte_data(clientp, - (TSL258X_CMD_REG | - (TSL258X_CNTRL + i))); - if (ret < 0) { - dev_err(&clientp->dev, - "i2c_smbus_read_byte from reg failed in taos_probe(), err = %d\n", - ret); - return ret; - } - buf[i] = ret; + ret = i2c_smbus_read_byte_data(clientp, + TSL258X_CMD_REG | TSL258X_CHIPID); + if (ret < 0) { + dev_err(&clientp->dev, + "%s failed to read the chip ID register\n", __func__); + return ret; } - if (!taos_tsl258x_device(buf)) { - dev_info(&clientp->dev, - "i2c device found but does not match expected id in taos_probe()\n"); + if ((ret & TSL2583_CHIP_ID_MASK) != TSL2583_CHIP_ID) { + dev_info(&clientp->dev, "%s received an unknown chip ID %x\n", + __func__, ret); return -EINVAL; } -- cgit v1.2.3 From 4a0f36144c2504313f62cad31564e405ebbbb47b Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 3 Nov 2016 08:56:14 -0400 Subject: staging: iio: tsl2583: fixed ordering of comments in taos_defaults() The comments in taos_defaults() appear after the line of code that they apply to. This patch moves the comments so that they appear before the code. Some of the comments were updated to be more informative. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 388440b4fcd7..709f44662a9f 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -143,16 +143,23 @@ static const struct gainadj gainadj[] = { */ static void taos_defaults(struct tsl2583_chip *chip) { - /* Operational parameters */ + /* + * The integration time must be a multiple of 50ms and within the + * range [50, 600] ms. + */ chip->taos_settings.als_time = 100; - /* must be a multiple of 50mS */ + + /* + * This is an index into the gainadj table. Assume clear glass as the + * default. + */ chip->taos_settings.als_gain = 0; - /* this is actually an index into the gain table */ - /* assume clear glass as default */ + + /* Default gain trim to account for aperture effects */ chip->taos_settings.als_gain_trim = 1000; - /* default gain trim to account for aperture effects */ - chip->taos_settings.als_cal_target = 130; + /* Known external ALS reading used for calibration */ + chip->taos_settings.als_cal_target = 130; } /* -- cgit v1.2.3 From babe444798ebfe02f2e870322927c7018957c7f3 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 3 Nov 2016 08:56:15 -0400 Subject: staging: iio: tsl2583: remove redundant power off sequence in taos_chip_on() taos_chip_on() explicitly turns the sensor power on and then writes the 8 registers that are stored in taos_config. The first register in taos_config is the CONTROL register and the configuration is set to turn the power off. The existing state sequence in taos_chip_on() is: - Turn device power on - Turn device power off (via taos_config) - Configure other 7 registers (via taos_config) - Turn device power on, enable ADC This patch changes the code so that the device is not powered off via taos_config. Verified that the driver still functions correctly using a TSL2581 hooked up to a Raspberry Pi 2. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 709f44662a9f..7fb09c641822 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -410,17 +410,8 @@ static int taos_chip_on(struct iio_dev *indio_dev) chip->als_saturation = als_count * 922; /* 90% of full scale */ chip->als_time_scale = (als_time + 25) / 50; - /* - * TSL258x Specific power-on / adc enable sequence - * Power on the device 1st. - */ - utmp = TSL258X_CNTL_PWR_ON; - ret = i2c_smbus_write_byte_data(chip->client, - TSL258X_CMD_REG | TSL258X_CNTRL, utmp); - if (ret < 0) { - dev_err(&chip->client->dev, "taos_chip_on failed on CNTRL reg.\n"); - return ret; - } + /* Power on the device; ADC off. */ + chip->taos_config[TSL258X_CNTRL] = TSL258X_CNTL_PWR_ON; /* * Use the following shadow copy for our delay before enabling ADC. -- cgit v1.2.3 From 0561155f6fc5d4e3702b3805fea0ec1f55e5f08e Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 3 Nov 2016 08:56:16 -0400 Subject: staging: iio: tsl2583: don't shutdown chip when updating the lux table in_illuminance_lux_table_store() shuts down the chip, updates the contents of the lux table, and then turns the chip back on. The values in lux table are not used by the chip and are only used internally by the driver. It is not necessary to change the power state on the chip. This patch removes the calls to taos_chip_off() and taos_chip_on() in in_illuminance_lux_table_store(). Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 7fb09c641822..af1cf9bdbd85 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -564,20 +564,10 @@ static ssize_t in_illuminance_lux_table_store(struct device *dev, goto done; } - if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { - ret = taos_chip_off(indio_dev); - if (ret < 0) - goto done; - } - /* Zero out the table */ memset(taos_device_lux, 0, sizeof(taos_device_lux)); memcpy(taos_device_lux, &value[1], (value[0] * 4)); - ret = taos_chip_on(indio_dev); - if (ret < 0) - goto done; - ret = len; done: -- cgit v1.2.3 From c2b0d2cfb0317275cf04257fc3f5dfbdd9ffa274 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 3 Nov 2016 08:56:17 -0400 Subject: staging: iio: tsl2583: remove redudant i2c call in taos_als_calibrate() taos_als_calibrate() queries the control register to determine if the unit is powered on and has the ADC enabled. It then queries the same register a second time to determine if the ADC reading is valid. This patch removes the redundant i2c_smbus_read_byte_data() call. Verified that the driver still functions correctly using a TSL2581 hooked up to a Raspberry Pi 2. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2583.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index af1cf9bdbd85..7eab17f4557e 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -338,18 +338,7 @@ static int taos_als_calibrate(struct iio_dev *indio_dev) dev_err(&chip->client->dev, "taos_als_calibrate failed: device not powered on with ADC enabled\n"); return -EINVAL; - } - - ret = i2c_smbus_read_byte_data(chip->client, - TSL258X_CMD_REG | TSL258X_CNTRL); - if (ret < 0) { - dev_err(&chip->client->dev, - "%s failed to read from the CNTRL register\n", - __func__); - return ret; - } - - if ((ret & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { + } else if ((ret & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { dev_err(&chip->client->dev, "taos_als_calibrate failed: STATUS - ADC not valid.\n"); return -ENODATA; -- cgit v1.2.3 From e2474541032db65d02bf88b6a8c2f954654b443f Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 3 Oct 2016 22:06:08 +0200 Subject: i2c: bcm2835: Fix hang for writing messages larger than 16 bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Writing messages larger than the FIFO size results in a hang, rendering the machine unusable. This is because the RXD status flag is set on the first interrupt which results in bcm2835_drain_rxfifo() stealing bytes from the buffer. The controller continues to trigger interrupts waiting for the missing bytes, but bcm2835_fill_txfifo() has none to give. In this situation wait_for_completion_timeout() apparently is unable to stop the madness. The BCM2835 ARM Peripherals datasheet has this to say about the flags: TXD: is set when the FIFO has space for at least one byte of data. RXD: is set when the FIFO contains at least one byte of data. TXW: is set during a write transfer and the FIFO is less than full. RXR: is set during a read transfer and the FIFO is or more full. Implementing the logic from the downstream i2c-bcm2708 driver solved the hang problem. Signed-off-by: Noralf Trønnes Reviewed-by: Eric Anholt Reviewed-by: Martin Sperl Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index d4f3239b5686..f283b714aa79 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -64,6 +64,7 @@ struct bcm2835_i2c_dev { int irq; struct i2c_adapter adapter; struct completion completion; + struct i2c_msg *curr_msg; u32 msg_err; u8 *msg_buf; size_t msg_buf_remaining; @@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) return IRQ_HANDLED; } - if (val & BCM2835_I2C_S_RXD) { - bcm2835_drain_rxfifo(i2c_dev); - if (!(val & BCM2835_I2C_S_DONE)) - return IRQ_HANDLED; - } - if (val & BCM2835_I2C_S_DONE) { - if (i2c_dev->msg_buf_remaining) + if (i2c_dev->curr_msg->flags & I2C_M_RD) { + bcm2835_drain_rxfifo(i2c_dev); + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); + } + + if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) i2c_dev->msg_err = BCM2835_I2C_S_LEN; else i2c_dev->msg_err = 0; @@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) return IRQ_HANDLED; } - if (val & BCM2835_I2C_S_TXD) { + if (val & BCM2835_I2C_S_TXW) { bcm2835_fill_txfifo(i2c_dev); return IRQ_HANDLED; } + if (val & BCM2835_I2C_S_RXR) { + bcm2835_drain_rxfifo(i2c_dev); + return IRQ_HANDLED; + } + return IRQ_NONE; } @@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, u32 c; unsigned long time_left; + i2c_dev->curr_msg = msg; i2c_dev->msg_buf = msg->buf; i2c_dev->msg_buf_remaining = msg->len; reinit_completion(&i2c_dev->completion); -- cgit v1.2.3 From d4030d75c7cbb434b2a3e5f6af5065879d2615a5 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 3 Oct 2016 22:06:09 +0200 Subject: i2c: bcm2835: Protect against unexpected TXW/RXR interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0), the driver has no way to fill/drain the FIFO to stop the interrupts. In this case the controller has to be disabled and the transfer completed to avoid hang. (CLKT | ERR) and DONE interrupts are completed in their own paths, and the controller is disabled in the transfer function after completion. Unite the code paths and do disabling inside the interrupt routine. Clear interrupt status bits in the united completion path instead of trying to do it on every interrupt which isn't necessary. Only CLKT, ERR and DONE can be cleared that way. Add the status value to the error value in case of TXW/RXR errors to distinguish them from the other S_LEN error. Signed-off-by: Noralf Trønnes Reviewed-by: Eric Anholt Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index f283b714aa79..d2ba1a4de36a 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -50,8 +50,6 @@ #define BCM2835_I2C_S_CLKT BIT(9) #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ -#define BCM2835_I2C_BITMSK_S 0x03FF - #define BCM2835_I2C_CDIV_MIN 0x0002 #define BCM2835_I2C_CDIV_MAX 0xFFFE @@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) } } +/* + * Note about I2C_C_CLEAR on error: + * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in + * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through + * the state machine to send a NACK and a STOP. Since we're setting CLEAR + * without I2CEN, that NACK will be hanging around queued up for next time + * we start the engine. + */ + static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) { struct bcm2835_i2c_dev *i2c_dev = data; u32 val, err; val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); - val &= BCM2835_I2C_BITMSK_S; - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val); err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); if (err) { i2c_dev->msg_err = err; - complete(&i2c_dev->completion); - return IRQ_HANDLED; + goto complete; } if (val & BCM2835_I2C_S_DONE) { @@ -137,21 +141,38 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) i2c_dev->msg_err = BCM2835_I2C_S_LEN; else i2c_dev->msg_err = 0; - complete(&i2c_dev->completion); - return IRQ_HANDLED; + goto complete; } if (val & BCM2835_I2C_S_TXW) { + if (!i2c_dev->msg_buf_remaining) { + i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; + goto complete; + } + bcm2835_fill_txfifo(i2c_dev); return IRQ_HANDLED; } if (val & BCM2835_I2C_S_RXR) { + if (!i2c_dev->msg_buf_remaining) { + i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; + goto complete; + } + bcm2835_drain_rxfifo(i2c_dev); return IRQ_HANDLED; } return IRQ_NONE; + +complete: + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT | + BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE); + complete(&i2c_dev->completion); + + return IRQ_HANDLED; } static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, @@ -181,8 +202,9 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, time_left = wait_for_completion_timeout(&i2c_dev->completion, BCM2835_I2C_TIMEOUT); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); if (!time_left) { + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, + BCM2835_I2C_C_CLEAR); dev_err(i2c_dev->dev, "i2c transfer timed out\n"); return -ETIMEDOUT; } -- cgit v1.2.3 From 23c9540b3ad1d7473fe40df80074d0fb0bf04869 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 3 Oct 2016 22:06:10 +0200 Subject: i2c: bcm2835: Use dev_dbg logging on transfer errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Writing to an AT24C32 generates on average 2x i2c transfer errors per 32-byte page write. Which amounts to a lot for a 4k write. This is due to the fact that the chip doesn't respond during it's internal write cycle when the at24 driver tries and retries the next write. Only a handful drivers use dev_err() on transfer error, so switch to dev_dbg() instead. Signed-off-by: Noralf Trønnes Reviewed-by: Eric Anholt Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index d2ba1a4de36a..54d510abd46a 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -216,7 +216,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, (msg->flags & I2C_M_IGNORE_NAK)) return 0; - dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) return -EREMOTEIO; -- cgit v1.2.3 From 8d2cc5cc6ee5c0fc48a96bb29af55fc700f66fdf Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 3 Oct 2016 22:06:11 +0200 Subject: i2c: bcm2835: Can't support I2C_M_IGNORE_NAK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The controller can't support this flag, so remove it. Documentation/i2c/i2c-protocol states that all of the message is sent: I2C_M_IGNORE_NAK: Normally message is interrupted immediately if there is [NA] from the client. Setting this flag treats any [NA] as [A], and all of message is sent. >From the BCM2835 ARM Peripherals datasheet: The ERR field is set when the slave fails to acknowledge either its address or a data byte written to it. So when the controller doesn't receive an ack, it sets ERR and raises an interrupt. In other words, the whole message is not sent. Signed-off-by: Noralf Trønnes Reviewed-by: Eric Anholt Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 54d510abd46a..565ef69ce614 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -212,10 +212,6 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, if (likely(!i2c_dev->msg_err)) return 0; - if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) && - (msg->flags & I2C_M_IGNORE_NAK)) - return 0; - dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) -- cgit v1.2.3 From ee05fea21b017b81a9477569b6a0c2d8e2946ac9 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 3 Oct 2016 22:06:12 +0200 Subject: i2c: bcm2835: Add support for Repeated Start Condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documentation/i2c/i2c-protocol states that Combined transactions should separate messages with a Start bit and end the whole transaction with a Stop bit. This patch adds support for issuing only a Start between messages instead of a Stop followed by a Start. This implementation differs from downstream i2c-bcm2708 in 2 respects: - it uses an interrupt to detect that the transfer is active instead of using polling. There is no interrupt for Transfer Active, but by not prefilling the FIFO it's possible to use the TXW interrupt. - when resetting/disabling the controller between transfers it writes CLEAR to the control register instead of just zero. Using just zero gave many errors. This might be the reason why downstream had to disable this feature and make it available with a module parameter. I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel) and AT24C32 (eeprom) in parallel without problems. Signed-off-by: Noralf Trønnes Acked-by: Eric Anholt Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 565ef69ce614..241e08ae7c27 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -63,6 +63,7 @@ struct bcm2835_i2c_dev { struct i2c_adapter adapter; struct completion completion; struct i2c_msg *curr_msg; + int num_msgs; u32 msg_err; u8 *msg_buf; size_t msg_buf_remaining; @@ -109,6 +110,45 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) } } +/* + * Repeated Start Condition (Sr) + * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it + * talks about reading from a slave with 10 bit address. This is achieved by + * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then + * issue a read. + * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the + * firmware actually does it using polling and says that it's a workaround for + * a problem in the state machine. + * It turns out that it is possible to use the TXW interrupt to know when the + * transfer is active, provided the FIFO has not been prefilled. + */ + +static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) +{ + u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN; + struct i2c_msg *msg = i2c_dev->curr_msg; + bool last_msg = (i2c_dev->num_msgs == 1); + + if (!i2c_dev->num_msgs) + return; + + i2c_dev->num_msgs--; + i2c_dev->msg_buf = msg->buf; + i2c_dev->msg_buf_remaining = msg->len; + + if (msg->flags & I2C_M_RD) + c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; + else + c |= BCM2835_I2C_C_INTT; + + if (last_msg) + c |= BCM2835_I2C_C_INTD; + + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); +} + /* * Note about I2C_C_CLEAR on error: * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in @@ -151,6 +191,12 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) } bcm2835_fill_txfifo(i2c_dev); + + if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) { + i2c_dev->curr_msg++; + bcm2835_i2c_start_transfer(i2c_dev); + } + return IRQ_HANDLED; } @@ -175,30 +221,25 @@ complete: return IRQ_HANDLED; } -static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - struct i2c_msg *msg) +static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + int num) { - u32 c; + struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); unsigned long time_left; + int i; - i2c_dev->curr_msg = msg; - i2c_dev->msg_buf = msg->buf; - i2c_dev->msg_buf_remaining = msg->len; - reinit_completion(&i2c_dev->completion); - - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); + for (i = 0; i < (num - 1); i++) + if (msgs[i].flags & I2C_M_RD) { + dev_warn_once(i2c_dev->dev, + "only one read message supported, has to be last\n"); + return -EOPNOTSUPP; + } - if (msg->flags & I2C_M_RD) { - c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; - } else { - c = BCM2835_I2C_C_INTT; - bcm2835_fill_txfifo(i2c_dev); - } - c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN; + i2c_dev->curr_msg = msgs; + i2c_dev->num_msgs = num; + reinit_completion(&i2c_dev->completion); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); + bcm2835_i2c_start_transfer(i2c_dev); time_left = wait_for_completion_timeout(&i2c_dev->completion, BCM2835_I2C_TIMEOUT); @@ -209,31 +250,15 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, return -ETIMEDOUT; } - if (likely(!i2c_dev->msg_err)) - return 0; + if (!i2c_dev->msg_err) + return num; dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) return -EREMOTEIO; - else - return -EIO; -} - -static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - int num) -{ - struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); - int i; - int ret = 0; - - for (i = 0; i < num; i++) { - ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]); - if (ret) - break; - } - return ret ?: i; + return -EIO; } static u32 bcm2835_i2c_func(struct i2c_adapter *adap) -- cgit v1.2.3 From e13e19e12f66401ce1e21ab491715835852babe7 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 3 Oct 2016 22:06:13 +0200 Subject: i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use i2c_adapter->timeout for the completion timeout value. The core default is 1 second. Signed-off-by: Noralf Trønnes Reviewed-by: Eric Anholt Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 241e08ae7c27..d2085dd3742e 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -53,8 +53,6 @@ #define BCM2835_I2C_CDIV_MIN 0x0002 #define BCM2835_I2C_CDIV_MAX 0xFFFE -#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000)) - struct bcm2835_i2c_dev { struct device *dev; void __iomem *regs; @@ -242,7 +240,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], bcm2835_i2c_start_transfer(i2c_dev); time_left = wait_for_completion_timeout(&i2c_dev->completion, - BCM2835_I2C_TIMEOUT); + adap->timeout); if (!time_left) { bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); -- cgit v1.2.3 From 9446f62e8e18057fceb179d947508df2f7253b26 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 3 Oct 2016 22:06:14 +0200 Subject: i2c: bcm2835: Add support for dynamic clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support a dynamic clock by reading the frequency and setting the divisor in the transfer function instead of during probe. Signed-off-by: Noralf Trønnes Reviewed-by: Martin Sperl Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm2835.c | 51 +++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index d2085dd3742e..c3436f627028 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -58,6 +58,7 @@ struct bcm2835_i2c_dev { void __iomem *regs; struct clk *clk; int irq; + u32 bus_clk_rate; struct i2c_adapter adapter; struct completion completion; struct i2c_msg *curr_msg; @@ -78,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) return readl(i2c_dev->regs + reg); } +static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) +{ + u32 divider; + + divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), + i2c_dev->bus_clk_rate); + /* + * Per the datasheet, the register is always interpreted as an even + * number, by rounding down. In other words, the LSB is ignored. So, + * if the LSB is set, increment the divider to avoid any issue. + */ + if (divider & 1) + divider++; + if ((divider < BCM2835_I2C_CDIV_MIN) || + (divider > BCM2835_I2C_CDIV_MAX)) { + dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n"); + return -EINVAL; + } + + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); + + return 0; +} + static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) { u32 val; @@ -224,7 +249,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], { struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); unsigned long time_left; - int i; + int i, ret; for (i = 0; i < (num - 1); i++) if (msgs[i].flags & I2C_M_RD) { @@ -233,6 +258,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], return -EOPNOTSUPP; } + ret = bcm2835_i2c_set_divider(i2c_dev); + if (ret) + return ret; + i2c_dev->curr_msg = msgs; i2c_dev->num_msgs = num; reinit_completion(&i2c_dev->completion); @@ -282,7 +311,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) { struct bcm2835_i2c_dev *i2c_dev; struct resource *mem, *irq; - u32 bus_clk_rate, divider; int ret; struct i2c_adapter *adap; @@ -306,27 +334,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) } ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &bus_clk_rate); + &i2c_dev->bus_clk_rate); if (ret < 0) { dev_warn(&pdev->dev, "Could not read clock-frequency property\n"); - bus_clk_rate = 100000; - } - - divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate); - /* - * Per the datasheet, the register is always interpreted as an even - * number, by rounding down. In other words, the LSB is ignored. So, - * if the LSB is set, increment the divider to avoid any issue. - */ - if (divider & 1) - divider++; - if ((divider < BCM2835_I2C_CDIV_MIN) || - (divider > BCM2835_I2C_CDIV_MAX)) { - dev_err(&pdev->dev, "Invalid clock-frequency\n"); - return -ENODEV; + i2c_dev->bus_clk_rate = 100000; } - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq) { -- cgit v1.2.3 From a4c48ad7370ba57ad899c2a4abd223ba7c6d9c32 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 4 Nov 2016 18:54:05 +0100 Subject: stmmac: dwmac-sti: remove useless of_node check Since dwmac-sti is a DT only driver checking for OF node is not necessary. Signed-off-by: Joachim Eastwood Acked-by: Giuseppe Cavallaro Tested-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index 58c05acc2aab..075ed425d39b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -270,9 +270,6 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, struct regmap *regmap; int err; - if (!np) - return -EINVAL; - /* clk selection from extra syscfg register */ dwmac->clk_sel_reg = -ENXIO; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf"); -- cgit v1.2.3 From b211aa655d264bd2a1f8b05eb75aeda508bd0ade Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 4 Nov 2016 18:54:06 +0100 Subject: stmmac: dwmac-sti: remove clk NULL checks Since sti_dwmac_parse_data() sets dwmac->clk to NULL if not clock was provided in DT and NULL is a valid clock there is no need to check for NULL before using this clock. Signed-off-by: Joachim Eastwood Acked-by: Giuseppe Cavallaro Tested-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index 075ed425d39b..f009bf467ba0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -191,7 +191,7 @@ static void stih4xx_fix_retime_src(void *priv, u32 spd) } } - if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk && freq) + if (src == TX_RETIME_SRC_CLKGEN && freq) clk_set_rate(dwmac->clk, freq); regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK, @@ -222,7 +222,7 @@ static void stid127_fix_retime_src(void *priv, u32 spd) freq = DWMAC_2_5MHZ; } - if (dwmac->clk && freq) + if (freq) clk_set_rate(dwmac->clk, freq); regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val); @@ -238,8 +238,7 @@ static int sti_dwmac_init(struct platform_device *pdev, void *priv) u32 reg = dwmac->ctrl_reg; u32 val; - if (dwmac->clk) - clk_prepare_enable(dwmac->clk); + clk_prepare_enable(dwmac->clk); if (of_property_read_bool(np, "st,gmac_en")) regmap_update_bits(regmap, reg, EN_MASK, EN); @@ -258,8 +257,7 @@ static void sti_dwmac_exit(struct platform_device *pdev, void *priv) { struct sti_dwmac *dwmac = priv; - if (dwmac->clk) - clk_disable_unprepare(dwmac->clk); + clk_disable_unprepare(dwmac->clk); } static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, struct platform_device *pdev) -- cgit v1.2.3 From 2517cfd4ca78359dfc2bebbb121207d712c9b319 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 4 Nov 2016 18:54:07 +0100 Subject: stmmac: dwmac-sti: add PM ops and resume function Implement PM callbacks and driver remove in the driver instead of relying on the init/exit hooks in stmmac_platform. This gives the driver more flexibility in how the code is organized. Eventually the init/exit callbacks will be deprecated in favor of the standard PM callbacks and driver remove function. Signed-off-by: Joachim Eastwood Acked-by: Giuseppe Cavallaro Tested-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 47 +++++++++++++++++++------ 1 file changed, 37 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index f009bf467ba0..bd6db2252a96 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -253,12 +253,6 @@ static int sti_dwmac_init(struct platform_device *pdev, void *priv) return 0; } -static void sti_dwmac_exit(struct platform_device *pdev, void *priv) -{ - struct sti_dwmac *dwmac = priv; - - clk_disable_unprepare(dwmac->clk); -} static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, struct platform_device *pdev) { @@ -352,8 +346,6 @@ static int sti_dwmac_probe(struct platform_device *pdev) dwmac->fix_retime_src = data->fix_retime_src; plat_dat->bsp_priv = dwmac; - plat_dat->init = sti_dwmac_init; - plat_dat->exit = sti_dwmac_exit; plat_dat->fix_mac_speed = data->fix_retime_src; ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); @@ -363,6 +355,41 @@ static int sti_dwmac_probe(struct platform_device *pdev) return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); } +static int sti_dwmac_remove(struct platform_device *pdev) +{ + struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev); + int ret = stmmac_dvr_remove(&pdev->dev); + + clk_disable_unprepare(dwmac->clk); + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int sti_dwmac_suspend(struct device *dev) +{ + struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev); + int ret = stmmac_suspend(dev); + + clk_disable_unprepare(dwmac->clk); + + return ret; +} + +static int sti_dwmac_resume(struct device *dev) +{ + struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev); + struct platform_device *pdev = to_platform_device(dev); + + sti_dwmac_init(pdev, dwmac); + + return stmmac_resume(dev); +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(sti_dwmac_pm_ops, sti_dwmac_suspend, + sti_dwmac_resume); + static const struct sti_dwmac_of_data stih4xx_dwmac_data = { .fix_retime_src = stih4xx_fix_retime_src, }; @@ -382,10 +409,10 @@ MODULE_DEVICE_TABLE(of, sti_dwmac_match); static struct platform_driver sti_dwmac_driver = { .probe = sti_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove = sti_dwmac_remove, .driver = { .name = "sti-dwmac", - .pm = &stmmac_pltfr_pm_ops, + .pm = &sti_dwmac_pm_ops, .of_match_table = sti_dwmac_match, }, }; -- cgit v1.2.3 From 06a6e829bdaf4df5616db2d47978e10e88f1dc32 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 4 Nov 2016 18:54:08 +0100 Subject: stmmac: dwmac-sti: move st, gmac_en parsing to sti_dwmac_parse_data The sti_dwmac_init() function is called both from probe and resume. Since DT properties doesn't change between suspend/resume cycles move parsing of this parameter into sti_dwmac_parse_data() where it belongs. Signed-off-by: Joachim Eastwood Acked-by: Giuseppe Cavallaro Tested-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index bd6db2252a96..269c7a55ab1d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -128,6 +128,7 @@ struct sti_dwmac { int clk_sel_reg; /* GMAC ext clk selection register */ struct device *dev; struct regmap *regmap; + bool gmac_en; u32 speed; void (*fix_retime_src)(void *priv, unsigned int speed); }; @@ -233,14 +234,12 @@ static int sti_dwmac_init(struct platform_device *pdev, void *priv) struct sti_dwmac *dwmac = priv; struct regmap *regmap = dwmac->regmap; int iface = dwmac->interface; - struct device *dev = dwmac->dev; - struct device_node *np = dev->of_node; u32 reg = dwmac->ctrl_reg; u32 val; clk_prepare_enable(dwmac->clk); - if (of_property_read_bool(np, "st,gmac_en")) + if (dwmac->gmac_en) regmap_update_bits(regmap, reg, EN_MASK, EN); regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]); @@ -281,6 +280,7 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, dwmac->dev = dev; dwmac->interface = of_get_phy_mode(np); dwmac->regmap = regmap; + dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en"); dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk"); dwmac->tx_retime_src = TX_RETIME_SRC_NA; dwmac->speed = SPEED_100; -- cgit v1.2.3 From b89cbfb01a2855b5c4e2f9121195439ac210d65b Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 4 Nov 2016 18:54:09 +0100 Subject: stmmac: dwmac-sti: move clk_prepare_enable out of init and add error handling Add clock error handling to probe and in the process move clock enabling out of sti_dwmac_init() to make this easier. Signed-off-by: Joachim Eastwood Acked-by: Giuseppe Cavallaro Tested-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index 269c7a55ab1d..b71888a307ff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -237,8 +237,6 @@ static int sti_dwmac_init(struct platform_device *pdev, void *priv) u32 reg = dwmac->ctrl_reg; u32 val; - clk_prepare_enable(dwmac->clk); - if (dwmac->gmac_en) regmap_update_bits(regmap, reg, EN_MASK, EN); @@ -348,11 +346,23 @@ static int sti_dwmac_probe(struct platform_device *pdev) plat_dat->bsp_priv = dwmac; plat_dat->fix_mac_speed = data->fix_retime_src; - ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); + ret = clk_prepare_enable(dwmac->clk); if (ret) return ret; - return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); + if (ret) + goto disable_clk; + + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + goto disable_clk; + + return 0; + +disable_clk: + clk_disable_unprepare(dwmac->clk); + return ret; } static int sti_dwmac_remove(struct platform_device *pdev) @@ -381,6 +391,7 @@ static int sti_dwmac_resume(struct device *dev) struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev); struct platform_device *pdev = to_platform_device(dev); + clk_prepare_enable(dwmac->clk); sti_dwmac_init(pdev, dwmac); return stmmac_resume(dev); -- cgit v1.2.3 From 0eebedc2fd284e145fe054a87254b112f9b5ada4 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 4 Nov 2016 18:54:10 +0100 Subject: stmmac: dwmac-sti: clean up and rename sti_dwmac_init Rename sti_dwmac_init to sti_dwmac_set_mode which is a better description for what it really does. Signed-off-by: Joachim Eastwood Acked-by: Giuseppe Cavallaro Tested-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index b71888a307ff..ac17bff9500e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -229,9 +229,8 @@ static void stid127_fix_retime_src(void *priv, u32 spd) regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val); } -static int sti_dwmac_init(struct platform_device *pdev, void *priv) +static int sti_dwmac_set_mode(struct sti_dwmac *dwmac) { - struct sti_dwmac *dwmac = priv; struct regmap *regmap = dwmac->regmap; int iface = dwmac->interface; u32 reg = dwmac->ctrl_reg; @@ -245,7 +244,7 @@ static int sti_dwmac_init(struct platform_device *pdev, void *priv) val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII; regmap_update_bits(regmap, reg, ENMII_MASK, val); - dwmac->fix_retime_src(priv, dwmac->speed); + dwmac->fix_retime_src(dwmac, dwmac->speed); return 0; } @@ -350,7 +349,7 @@ static int sti_dwmac_probe(struct platform_device *pdev) if (ret) return ret; - ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); + ret = sti_dwmac_set_mode(dwmac); if (ret) goto disable_clk; @@ -389,10 +388,9 @@ static int sti_dwmac_suspend(struct device *dev) static int sti_dwmac_resume(struct device *dev) { struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev); - struct platform_device *pdev = to_platform_device(dev); clk_prepare_enable(dwmac->clk); - sti_dwmac_init(pdev, dwmac); + sti_dwmac_set_mode(dwmac); return stmmac_resume(dev); } -- cgit v1.2.3 From cb42d4b64b1af1de70297c695644b178ff0dd5b7 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 4 Nov 2016 18:54:11 +0100 Subject: stmmac: dwmac-sti: remove unused priv dev member The dev member of struct sti_dwmac is not used anywhere in the driver so lets just remove it. Signed-off-by: Joachim Eastwood Acked-by: Giuseppe Cavallaro Tested-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index ac17bff9500e..c9006ab083d5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -126,7 +126,6 @@ struct sti_dwmac { struct clk *clk; /* PHY clock */ u32 ctrl_reg; /* GMAC glue-logic control register */ int clk_sel_reg; /* GMAC ext clk selection register */ - struct device *dev; struct regmap *regmap; bool gmac_en; u32 speed; @@ -274,7 +273,6 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, return err; } - dwmac->dev = dev; dwmac->interface = of_get_phy_mode(np); dwmac->regmap = regmap; dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en"); -- cgit v1.2.3 From 0a886f59528aac568cf9e4981167b5dcdd3d1676 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 22 Sep 2016 19:52:39 +0800 Subject: drm: zte: add initial vou drm driver It adds the initial ZTE VOU display controller DRM driver. There are still some features to be added, like overlay plane, scaling, and more output devices support. But it's already useful with dual CRTCs and HDMI monitor working. Signed-off-by: Shawn Guo --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/zte/Kconfig | 8 + drivers/gpu/drm/zte/Makefile | 7 + drivers/gpu/drm/zte/zx_drm_drv.c | 267 +++++++++++++++ drivers/gpu/drm/zte/zx_drm_drv.h | 36 ++ drivers/gpu/drm/zte/zx_hdmi.c | 624 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/zte/zx_hdmi_regs.h | 56 +++ drivers/gpu/drm/zte/zx_plane.c | 299 ++++++++++++++++ drivers/gpu/drm/zte/zx_plane.h | 26 ++ drivers/gpu/drm/zte/zx_plane_regs.h | 91 +++++ drivers/gpu/drm/zte/zx_vou.c | 661 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/zte/zx_vou.h | 46 +++ drivers/gpu/drm/zte/zx_vou_regs.h | 157 +++++++++ 14 files changed, 2281 insertions(+) create mode 100644 drivers/gpu/drm/zte/Kconfig create mode 100644 drivers/gpu/drm/zte/Makefile create mode 100644 drivers/gpu/drm/zte/zx_drm_drv.c create mode 100644 drivers/gpu/drm/zte/zx_drm_drv.h create mode 100644 drivers/gpu/drm/zte/zx_hdmi.c create mode 100644 drivers/gpu/drm/zte/zx_hdmi_regs.h create mode 100644 drivers/gpu/drm/zte/zx_plane.c create mode 100644 drivers/gpu/drm/zte/zx_plane.h create mode 100644 drivers/gpu/drm/zte/zx_plane_regs.h create mode 100644 drivers/gpu/drm/zte/zx_vou.c create mode 100644 drivers/gpu/drm/zte/zx_vou.h create mode 100644 drivers/gpu/drm/zte/zx_vou_regs.h (limited to 'drivers') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 483059a22b1b..a91f8cecbe0f 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -223,6 +223,8 @@ source "drivers/gpu/drm/hisilicon/Kconfig" source "drivers/gpu/drm/mediatek/Kconfig" +source "drivers/gpu/drm/zte/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACY diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 25c720454017..f3251750c92b 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -86,3 +86,4 @@ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/ obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/ obj-$(CONFIG_DRM_ARCPGU)+= arc/ obj-y += hisilicon/ +obj-$(CONFIG_DRM_ZTE) += zte/ diff --git a/drivers/gpu/drm/zte/Kconfig b/drivers/gpu/drm/zte/Kconfig new file mode 100644 index 000000000000..4065b2840f1c --- /dev/null +++ b/drivers/gpu/drm/zte/Kconfig @@ -0,0 +1,8 @@ +config DRM_ZTE + tristate "DRM Support for ZTE SoCs" + depends on DRM && ARCH_ZX + select DRM_KMS_CMA_HELPER + select DRM_KMS_FB_HELPER + select DRM_KMS_HELPER + help + Choose this option to enable DRM on ZTE ZX SoCs. diff --git a/drivers/gpu/drm/zte/Makefile b/drivers/gpu/drm/zte/Makefile new file mode 100644 index 000000000000..699180bfd57c --- /dev/null +++ b/drivers/gpu/drm/zte/Makefile @@ -0,0 +1,7 @@ +zxdrm-y := \ + zx_drm_drv.o \ + zx_hdmi.o \ + zx_plane.o \ + zx_vou.o + +obj-$(CONFIG_DRM_ZTE) += zxdrm.o diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c new file mode 100644 index 000000000000..abc8099e6f53 --- /dev/null +++ b/drivers/gpu/drm/zte/zx_drm_drv.c @@ -0,0 +1,267 @@ +/* + * Copyright 2016 Linaro Ltd. + * Copyright 2016 ZTE Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zx_drm_drv.h" +#include "zx_vou.h" + +struct zx_drm_private { + struct drm_fbdev_cma *fbdev; +}; + +static void zx_drm_fb_output_poll_changed(struct drm_device *drm) +{ + struct zx_drm_private *priv = drm->dev_private; + + drm_fbdev_cma_hotplug_event(priv->fbdev); +} + +static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = { + .fb_create = drm_fb_cma_create, + .output_poll_changed = zx_drm_fb_output_poll_changed, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static void zx_drm_lastclose(struct drm_device *drm) +{ + struct zx_drm_private *priv = drm->dev_private; + + drm_fbdev_cma_restore_mode(priv->fbdev); +} + +static const struct file_operations zx_drm_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif + .poll = drm_poll, + .read = drm_read, + .llseek = noop_llseek, + .mmap = drm_gem_cma_mmap, +}; + +static struct drm_driver zx_drm_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | + DRIVER_ATOMIC, + .lastclose = zx_drm_lastclose, + .get_vblank_counter = drm_vblank_no_hw_counter, + .enable_vblank = zx_vou_enable_vblank, + .disable_vblank = zx_vou_disable_vblank, + .gem_free_object = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + .dumb_create = drm_gem_cma_dumb_create, + .dumb_map_offset = drm_gem_cma_dumb_map_offset, + .dumb_destroy = drm_gem_dumb_destroy, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_vmap = drm_gem_cma_prime_vmap, + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, + .gem_prime_mmap = drm_gem_cma_prime_mmap, + .fops = &zx_drm_fops, + .name = "zx-vou", + .desc = "ZTE VOU Controller DRM", + .date = "20160811", + .major = 1, + .minor = 0, +}; + +static int zx_drm_bind(struct device *dev) +{ + struct drm_device *drm; + struct zx_drm_private *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + drm = drm_dev_alloc(&zx_drm_driver, dev); + if (!drm) + return -ENOMEM; + + drm->dev_private = priv; + dev_set_drvdata(dev, drm); + + drm_mode_config_init(drm); + drm->mode_config.min_width = 16; + drm->mode_config.min_height = 16; + drm->mode_config.max_width = 4096; + drm->mode_config.max_height = 4096; + drm->mode_config.funcs = &zx_drm_mode_config_funcs; + + ret = component_bind_all(dev, drm); + if (ret) { + DRM_DEV_ERROR(dev, "failed to bind all components: %d\n", ret); + goto out_unregister; + } + + ret = drm_vblank_init(drm, drm->mode_config.num_crtc); + if (ret < 0) { + DRM_DEV_ERROR(dev, "failed to init vblank: %d\n", ret); + goto out_unbind; + } + + /* + * We will manage irq handler on our own. In this case, irq_enabled + * need to be true for using vblank core support. + */ + drm->irq_enabled = true; + + drm_mode_config_reset(drm); + drm_kms_helper_poll_init(drm); + + priv->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, + drm->mode_config.num_connector); + if (IS_ERR(priv->fbdev)) { + ret = PTR_ERR(priv->fbdev); + DRM_DEV_ERROR(dev, "failed to init cma fbdev: %d\n", ret); + priv->fbdev = NULL; + goto out_poll_fini; + } + + ret = drm_dev_register(drm, 0); + if (ret) + goto out_fbdev_fini; + + return 0; + +out_fbdev_fini: + if (priv->fbdev) { + drm_fbdev_cma_fini(priv->fbdev); + priv->fbdev = NULL; + } +out_poll_fini: + drm_kms_helper_poll_fini(drm); + drm_mode_config_cleanup(drm); + drm_vblank_cleanup(drm); +out_unbind: + component_unbind_all(dev, drm); +out_unregister: + dev_set_drvdata(dev, NULL); + drm->dev_private = NULL; + drm_dev_unref(drm); + return ret; +} + +static void zx_drm_unbind(struct device *dev) +{ + struct drm_device *drm = dev_get_drvdata(dev); + struct zx_drm_private *priv = drm->dev_private; + + drm_dev_unregister(drm); + if (priv->fbdev) { + drm_fbdev_cma_fini(priv->fbdev); + priv->fbdev = NULL; + } + drm_kms_helper_poll_fini(drm); + drm_mode_config_cleanup(drm); + drm_vblank_cleanup(drm); + component_unbind_all(dev, drm); + dev_set_drvdata(dev, NULL); + drm->dev_private = NULL; + drm_dev_unref(drm); +} + +static const struct component_master_ops zx_drm_master_ops = { + .bind = zx_drm_bind, + .unbind = zx_drm_unbind, +}; + +static int compare_of(struct device *dev, void *data) +{ + return dev->of_node == data; +} + +static int zx_drm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *parent = dev->of_node; + struct device_node *child; + struct component_match *match = NULL; + int ret; + + ret = of_platform_populate(parent, NULL, NULL, dev); + if (ret) + return ret; + + for_each_available_child_of_node(parent, child) { + component_match_add(dev, &match, compare_of, child); + of_node_put(child); + } + + return component_master_add_with_match(dev, &zx_drm_master_ops, match); +} + +static int zx_drm_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &zx_drm_master_ops); + return 0; +} + +static const struct of_device_id zx_drm_of_match[] = { + { .compatible = "zte,zx296718-vou", }, + { /* end */ }, +}; +MODULE_DEVICE_TABLE(of, zx_drm_of_match); + +static struct platform_driver zx_drm_platform_driver = { + .probe = zx_drm_probe, + .remove = zx_drm_remove, + .driver = { + .name = "zx-drm", + .of_match_table = zx_drm_of_match, + }, +}; + +static struct platform_driver *drivers[] = { + &zx_crtc_driver, + &zx_hdmi_driver, + &zx_drm_platform_driver, +}; + +static int zx_drm_init(void) +{ + return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); +} +module_init(zx_drm_init); + +static void zx_drm_exit(void) +{ + platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); +} +module_exit(zx_drm_exit); + +MODULE_AUTHOR("Shawn Guo "); +MODULE_DESCRIPTION("ZTE ZX VOU DRM driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/zte/zx_drm_drv.h b/drivers/gpu/drm/zte/zx_drm_drv.h new file mode 100644 index 000000000000..e65cd18a6cba --- /dev/null +++ b/drivers/gpu/drm/zte/zx_drm_drv.h @@ -0,0 +1,36 @@ +/* + * Copyright 2016 Linaro Ltd. + * Copyright 2016 ZTE Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __ZX_DRM_DRV_H__ +#define __ZX_DRM_DRV_H__ + +extern struct platform_driver zx_crtc_driver; +extern struct platform_driver zx_hdmi_driver; + +static inline u32 zx_readl(void __iomem *reg) +{ + return readl_relaxed(reg); +} + +static inline void zx_writel(void __iomem *reg, u32 val) +{ + writel_relaxed(val, reg); +} + +static inline void zx_writel_mask(void __iomem *reg, u32 mask, u32 val) +{ + u32 tmp; + + tmp = zx_readl(reg); + tmp = (tmp & ~mask) | (val & mask); + zx_writel(reg, tmp); +} + +#endif /* __ZX_DRM_DRV_H__ */ diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c new file mode 100644 index 000000000000..6bf6c364811e --- /dev/null +++ b/drivers/gpu/drm/zte/zx_hdmi.c @@ -0,0 +1,624 @@ +/* + * Copyright 2016 Linaro Ltd. + * Copyright 2016 ZTE Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "zx_hdmi_regs.h" +#include "zx_vou.h" + +#define ZX_HDMI_INFOFRAME_SIZE 31 +#define DDC_SEGMENT_ADDR 0x30 + +struct zx_hdmi_i2c { + struct i2c_adapter adap; + struct mutex lock; +}; + +struct zx_hdmi { + struct drm_connector connector; + struct drm_encoder encoder; + struct zx_hdmi_i2c *ddc; + struct device *dev; + struct drm_device *drm; + void __iomem *mmio; + struct clk *cec_clk; + struct clk *osc_clk; + struct clk *xclk; + bool sink_is_hdmi; + bool sink_has_audio; + const struct vou_inf *inf; +}; + +#define to_zx_hdmi(x) container_of(x, struct zx_hdmi, x) + +static const struct vou_inf vou_inf_hdmi = { + .id = VOU_HDMI, + .data_sel = VOU_YUV444, + .clocks_en_bits = BIT(24) | BIT(18) | BIT(6), + .clocks_sel_bits = BIT(13) | BIT(2), +}; + +static inline u8 hdmi_readb(struct zx_hdmi *hdmi, u16 offset) +{ + return readl_relaxed(hdmi->mmio + offset * 4); +} + +static inline void hdmi_writeb(struct zx_hdmi *hdmi, u16 offset, u8 val) +{ + writel_relaxed(val, hdmi->mmio + offset * 4); +} + +static inline void hdmi_writeb_mask(struct zx_hdmi *hdmi, u16 offset, + u8 mask, u8 val) +{ + u8 tmp; + + tmp = hdmi_readb(hdmi, offset); + tmp = (tmp & ~mask) | (val & mask); + hdmi_writeb(hdmi, offset, tmp); +} + +static int zx_hdmi_infoframe_trans(struct zx_hdmi *hdmi, + union hdmi_infoframe *frame, u8 fsel) +{ + u8 buffer[ZX_HDMI_INFOFRAME_SIZE]; + int num; + int i; + + hdmi_writeb(hdmi, TPI_INFO_FSEL, fsel); + + num = hdmi_infoframe_pack(frame, buffer, ZX_HDMI_INFOFRAME_SIZE); + if (num < 0) { + DRM_DEV_ERROR(hdmi->dev, "failed to pack infoframe: %d\n", num); + return num; + } + + for (i = 0; i < num; i++) + hdmi_writeb(hdmi, TPI_INFO_B0 + i, buffer[i]); + + hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_RPT, + TPI_INFO_TRANS_RPT); + hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_EN, + TPI_INFO_TRANS_EN); + + return num; +} + +static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi, + struct drm_display_mode *mode) +{ + union hdmi_infoframe frame; + int ret; + + ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi, + mode); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n", + ret); + return ret; + } + + return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_VSIF); +} + +static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi, + struct drm_display_mode *mode) +{ + union hdmi_infoframe frame; + int ret; + + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n", + ret); + return ret; + } + + /* We always use YUV444 for HDMI output. */ + frame.avi.colorspace = HDMI_COLORSPACE_YUV444; + + return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AVI); +} + +static void zx_hdmi_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) +{ + struct zx_hdmi *hdmi = to_zx_hdmi(encoder); + + if (hdmi->sink_is_hdmi) { + zx_hdmi_config_video_avi(hdmi, mode); + zx_hdmi_config_video_vsi(hdmi, mode); + } +} + +static void zx_hdmi_phy_start(struct zx_hdmi *hdmi) +{ + /* Copy from ZTE BSP code */ + hdmi_writeb(hdmi, 0x222, 0x0); + hdmi_writeb(hdmi, 0x224, 0x4); + hdmi_writeb(hdmi, 0x909, 0x0); + hdmi_writeb(hdmi, 0x7b0, 0x90); + hdmi_writeb(hdmi, 0x7b1, 0x00); + hdmi_writeb(hdmi, 0x7b2, 0xa7); + hdmi_writeb(hdmi, 0x7b8, 0xaa); + hdmi_writeb(hdmi, 0x7b2, 0xa7); + hdmi_writeb(hdmi, 0x7b3, 0x0f); + hdmi_writeb(hdmi, 0x7b4, 0x0f); + hdmi_writeb(hdmi, 0x7b5, 0x55); + hdmi_writeb(hdmi, 0x7b7, 0x03); + hdmi_writeb(hdmi, 0x7b9, 0x12); + hdmi_writeb(hdmi, 0x7ba, 0x32); + hdmi_writeb(hdmi, 0x7bc, 0x68); + hdmi_writeb(hdmi, 0x7be, 0x40); + hdmi_writeb(hdmi, 0x7bf, 0x84); + hdmi_writeb(hdmi, 0x7c1, 0x0f); + hdmi_writeb(hdmi, 0x7c8, 0x02); + hdmi_writeb(hdmi, 0x7c9, 0x03); + hdmi_writeb(hdmi, 0x7ca, 0x40); + hdmi_writeb(hdmi, 0x7dc, 0x31); + hdmi_writeb(hdmi, 0x7e2, 0x04); + hdmi_writeb(hdmi, 0x7e0, 0x06); + hdmi_writeb(hdmi, 0x7cb, 0x68); + hdmi_writeb(hdmi, 0x7f9, 0x02); + hdmi_writeb(hdmi, 0x7b6, 0x02); + hdmi_writeb(hdmi, 0x7f3, 0x0); +} + +static void zx_hdmi_hw_enable(struct zx_hdmi *hdmi) +{ + /* Enable pclk */ + hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, CLKPWD_PDIDCK); + + /* Enable HDMI for TX */ + hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, FUNC_HDMI_EN); + + /* Enable deep color packet */ + hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN); + + /* Enable HDMI/MHL mode for output */ + hdmi_writeb_mask(hdmi, TEST_TXCTRL, TEST_TXCTRL_HDMI_MODE, + TEST_TXCTRL_HDMI_MODE); + + /* Configure reg_qc_sel */ + hdmi_writeb(hdmi, HDMICTL4, 0x3); + + /* Enable interrupt */ + hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT, + INTR1_MONITOR_DETECT); + + /* Start up phy */ + zx_hdmi_phy_start(hdmi); +} + +static void zx_hdmi_hw_disable(struct zx_hdmi *hdmi) +{ + /* Disable interrupt */ + hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT, 0); + + /* Disable deep color packet */ + hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN); + + /* Disable HDMI for TX */ + hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, 0); + + /* Disable pclk */ + hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, 0); +} + +static void zx_hdmi_encoder_enable(struct drm_encoder *encoder) +{ + struct zx_hdmi *hdmi = to_zx_hdmi(encoder); + + clk_prepare_enable(hdmi->cec_clk); + clk_prepare_enable(hdmi->osc_clk); + clk_prepare_enable(hdmi->xclk); + + zx_hdmi_hw_enable(hdmi); + + vou_inf_enable(hdmi->inf, encoder->crtc); +} + +static void zx_hdmi_encoder_disable(struct drm_encoder *encoder) +{ + struct zx_hdmi *hdmi = to_zx_hdmi(encoder); + + vou_inf_disable(hdmi->inf, encoder->crtc); + + zx_hdmi_hw_disable(hdmi); + + clk_disable_unprepare(hdmi->xclk); + clk_disable_unprepare(hdmi->osc_clk); + clk_disable_unprepare(hdmi->cec_clk); +} + +static const struct drm_encoder_helper_funcs zx_hdmi_encoder_helper_funcs = { + .enable = zx_hdmi_encoder_enable, + .disable = zx_hdmi_encoder_disable, + .mode_set = zx_hdmi_encoder_mode_set, +}; + +static const struct drm_encoder_funcs zx_hdmi_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static int zx_hdmi_connector_get_modes(struct drm_connector *connector) +{ + struct zx_hdmi *hdmi = to_zx_hdmi(connector); + struct edid *edid; + int ret; + + edid = drm_get_edid(connector, &hdmi->ddc->adap); + if (!edid) + return 0; + + hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); + hdmi->sink_has_audio = drm_detect_monitor_audio(edid); + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + kfree(edid); + + return ret; +} + +static enum drm_mode_status +zx_hdmi_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + return MODE_OK; +} + +static struct drm_connector_helper_funcs zx_hdmi_connector_helper_funcs = { + .get_modes = zx_hdmi_connector_get_modes, + .mode_valid = zx_hdmi_connector_mode_valid, +}; + +static enum drm_connector_status +zx_hdmi_connector_detect(struct drm_connector *connector, bool force) +{ + struct zx_hdmi *hdmi = to_zx_hdmi(connector); + + return (hdmi_readb(hdmi, TPI_HPD_RSEN) & TPI_HPD_CONNECTION) ? + connector_status_connected : connector_status_disconnected; +} + +static const struct drm_connector_funcs zx_hdmi_connector_funcs = { + .dpms = drm_atomic_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = zx_hdmi_connector_detect, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi) +{ + struct drm_encoder *encoder = &hdmi->encoder; + + encoder->possible_crtcs = VOU_CRTC_MASK; + + drm_encoder_init(drm, encoder, &zx_hdmi_encoder_funcs, + DRM_MODE_ENCODER_TMDS, NULL); + drm_encoder_helper_add(encoder, &zx_hdmi_encoder_helper_funcs); + + hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD; + + drm_connector_init(drm, &hdmi->connector, &zx_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA); + drm_connector_helper_add(&hdmi->connector, + &zx_hdmi_connector_helper_funcs); + + drm_mode_connector_attach_encoder(&hdmi->connector, encoder); + + return 0; +} + +static irqreturn_t zx_hdmi_irq_thread(int irq, void *dev_id) +{ + struct zx_hdmi *hdmi = dev_id; + + drm_helper_hpd_irq_event(hdmi->connector.dev); + + return IRQ_HANDLED; +} + +static irqreturn_t zx_hdmi_irq_handler(int irq, void *dev_id) +{ + struct zx_hdmi *hdmi = dev_id; + u8 lstat; + + lstat = hdmi_readb(hdmi, L1_INTR_STAT); + + /* Monitor detect/HPD interrupt */ + if (lstat & L1_INTR_STAT_INTR1) { + u8 stat; + + stat = hdmi_readb(hdmi, INTR1_STAT); + hdmi_writeb(hdmi, INTR1_STAT, stat); + + if (stat & INTR1_MONITOR_DETECT) + return IRQ_WAKE_THREAD; + } + + return IRQ_NONE; +} + +static int zx_hdmi_i2c_read(struct zx_hdmi *hdmi, struct i2c_msg *msg) +{ + int len = msg->len; + u8 *buf = msg->buf; + int retry = 0; + int ret = 0; + + /* Bits [9:8] of bytes */ + hdmi_writeb(hdmi, ZX_DDC_DIN_CNT2, (len >> 8) & 0xff); + /* Bits [7:0] of bytes */ + hdmi_writeb(hdmi, ZX_DDC_DIN_CNT1, len & 0xff); + + /* Clear FIFO */ + hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, DDC_CMD_CLEAR_FIFO); + + /* Kick off the read */ + hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, + DDC_CMD_SEQUENTIAL_READ); + + while (len > 0) { + int cnt, i; + + /* FIFO needs some time to get ready */ + usleep_range(500, 1000); + + cnt = hdmi_readb(hdmi, ZX_DDC_DOUT_CNT) & DDC_DOUT_CNT_MASK; + if (cnt == 0) { + if (++retry > 5) { + DRM_DEV_ERROR(hdmi->dev, + "DDC FIFO read timed out!"); + return -ETIMEDOUT; + } + continue; + } + + for (i = 0; i < cnt; i++) + *buf++ = hdmi_readb(hdmi, ZX_DDC_DATA); + len -= cnt; + } + + return ret; +} + +static int zx_hdmi_i2c_write(struct zx_hdmi *hdmi, struct i2c_msg *msg) +{ + /* + * The DDC I2C adapter is only for reading EDID data, so we assume + * that the write to this adapter must be the EDID data offset. + */ + if ((msg->len != 1) || + ((msg->addr != DDC_ADDR) && (msg->addr != DDC_SEGMENT_ADDR))) + return -EINVAL; + + if (msg->addr == DDC_SEGMENT_ADDR) + hdmi_writeb(hdmi, ZX_DDC_SEGM, msg->addr << 1); + else if (msg->addr == DDC_ADDR) + hdmi_writeb(hdmi, ZX_DDC_ADDR, msg->addr << 1); + + hdmi_writeb(hdmi, ZX_DDC_OFFSET, msg->buf[0]); + + return 0; +} + +static int zx_hdmi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + struct zx_hdmi *hdmi = i2c_get_adapdata(adap); + struct zx_hdmi_i2c *ddc = hdmi->ddc; + int i, ret = 0; + + mutex_lock(&ddc->lock); + + /* Enable DDC master access */ + hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, HW_DDC_MASTER); + + for (i = 0; i < num; i++) { + DRM_DEV_DEBUG(hdmi->dev, + "xfer: num: %d/%d, len: %d, flags: %#x\n", + i + 1, num, msgs[i].len, msgs[i].flags); + + if (msgs[i].flags & I2C_M_RD) + ret = zx_hdmi_i2c_read(hdmi, &msgs[i]); + else + ret = zx_hdmi_i2c_write(hdmi, &msgs[i]); + + if (ret < 0) + break; + } + + if (!ret) + ret = num; + + /* Disable DDC master access */ + hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, 0); + + mutex_unlock(&ddc->lock); + + return ret; +} + +static u32 zx_hdmi_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm zx_hdmi_algorithm = { + .master_xfer = zx_hdmi_i2c_xfer, + .functionality = zx_hdmi_i2c_func, +}; + +static int zx_hdmi_ddc_register(struct zx_hdmi *hdmi) +{ + struct i2c_adapter *adap; + struct zx_hdmi_i2c *ddc; + int ret; + + ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL); + if (!ddc) + return -ENOMEM; + + hdmi->ddc = ddc; + mutex_init(&ddc->lock); + + adap = &ddc->adap; + adap->owner = THIS_MODULE; + adap->class = I2C_CLASS_DDC; + adap->dev.parent = hdmi->dev; + adap->algo = &zx_hdmi_algorithm; + snprintf(adap->name, sizeof(adap->name), "zx hdmi i2c"); + + ret = i2c_add_adapter(adap); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, "failed to add I2C adapter: %d\n", + ret); + return ret; + } + + i2c_set_adapdata(adap, hdmi); + + return 0; +} + +static int zx_hdmi_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm = data; + struct resource *res; + struct zx_hdmi *hdmi; + int irq; + int ret; + + hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); + if (!hdmi) + return -ENOMEM; + + hdmi->dev = dev; + hdmi->drm = drm; + hdmi->inf = &vou_inf_hdmi; + + dev_set_drvdata(dev, hdmi); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hdmi->mmio = devm_ioremap_resource(dev, res); + if (IS_ERR(hdmi->mmio)) { + ret = PTR_ERR(hdmi->mmio); + DRM_DEV_ERROR(dev, "failed to remap hdmi region: %d\n", ret); + return ret; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + hdmi->cec_clk = devm_clk_get(hdmi->dev, "osc_cec"); + if (IS_ERR(hdmi->cec_clk)) { + ret = PTR_ERR(hdmi->cec_clk); + DRM_DEV_ERROR(dev, "failed to get cec_clk: %d\n", ret); + return ret; + } + + hdmi->osc_clk = devm_clk_get(hdmi->dev, "osc_clk"); + if (IS_ERR(hdmi->osc_clk)) { + ret = PTR_ERR(hdmi->osc_clk); + DRM_DEV_ERROR(dev, "failed to get osc_clk: %d\n", ret); + return ret; + } + + hdmi->xclk = devm_clk_get(hdmi->dev, "xclk"); + if (IS_ERR(hdmi->xclk)) { + ret = PTR_ERR(hdmi->xclk); + DRM_DEV_ERROR(dev, "failed to get xclk: %d\n", ret); + return ret; + } + + ret = zx_hdmi_ddc_register(hdmi); + if (ret) { + DRM_DEV_ERROR(dev, "failed to register ddc: %d\n", ret); + return ret; + } + + ret = zx_hdmi_register(drm, hdmi); + if (ret) { + DRM_DEV_ERROR(dev, "failed to register hdmi: %d\n", ret); + return ret; + } + + ret = devm_request_threaded_irq(dev, irq, zx_hdmi_irq_handler, + zx_hdmi_irq_thread, IRQF_SHARED, + dev_name(dev), hdmi); + if (ret) { + DRM_DEV_ERROR(dev, "failed to request threaded irq: %d\n", ret); + return ret; + } + + return 0; +} + +static void zx_hdmi_unbind(struct device *dev, struct device *master, + void *data) +{ + struct zx_hdmi *hdmi = dev_get_drvdata(dev); + + hdmi->connector.funcs->destroy(&hdmi->connector); + hdmi->encoder.funcs->destroy(&hdmi->encoder); +} + +static const struct component_ops zx_hdmi_component_ops = { + .bind = zx_hdmi_bind, + .unbind = zx_hdmi_unbind, +}; + +static int zx_hdmi_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &zx_hdmi_component_ops); +} + +static int zx_hdmi_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &zx_hdmi_component_ops); + return 0; +} + +static const struct of_device_id zx_hdmi_of_match[] = { + { .compatible = "zte,zx296718-hdmi", }, + { /* end */ }, +}; +MODULE_DEVICE_TABLE(of, zx_hdmi_of_match); + +struct platform_driver zx_hdmi_driver = { + .probe = zx_hdmi_probe, + .remove = zx_hdmi_remove, + .driver = { + .name = "zx-hdmi", + .of_match_table = zx_hdmi_of_match, + }, +}; diff --git a/drivers/gpu/drm/zte/zx_hdmi_regs.h b/drivers/gpu/drm/zte/zx_hdmi_regs.h new file mode 100644 index 000000000000..de911f66b658 --- /dev/null +++ b/drivers/gpu/drm/zte/zx_hdmi_regs.h @@ -0,0 +1,56 @@ +/* + * Copyright 2016 Linaro Ltd. + * Copyright 2016 ZTE Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __ZX_HDMI_REGS_H__ +#define __ZX_HDMI_REGS_H__ + +#define FUNC_SEL 0x000b +#define FUNC_HDMI_EN BIT(0) +#define CLKPWD 0x000d +#define CLKPWD_PDIDCK BIT(2) +#define P2T_CTRL 0x0066 +#define P2T_DC_PKT_EN BIT(7) +#define L1_INTR_STAT 0x007e +#define L1_INTR_STAT_INTR1 BIT(0) +#define INTR1_STAT 0x008f +#define INTR1_MASK 0x0095 +#define INTR1_MONITOR_DETECT (BIT(5) | BIT(6)) +#define ZX_DDC_ADDR 0x00ed +#define ZX_DDC_SEGM 0x00ee +#define ZX_DDC_OFFSET 0x00ef +#define ZX_DDC_DIN_CNT1 0x00f0 +#define ZX_DDC_DIN_CNT2 0x00f1 +#define ZX_DDC_CMD 0x00f3 +#define DDC_CMD_MASK 0xf +#define DDC_CMD_CLEAR_FIFO 0x9 +#define DDC_CMD_SEQUENTIAL_READ 0x2 +#define ZX_DDC_DATA 0x00f4 +#define ZX_DDC_DOUT_CNT 0x00f5 +#define DDC_DOUT_CNT_MASK 0x1f +#define TEST_TXCTRL 0x00f7 +#define TEST_TXCTRL_HDMI_MODE BIT(1) +#define HDMICTL4 0x0235 +#define TPI_HPD_RSEN 0x063b +#define TPI_HPD_CONNECTION (BIT(1) | BIT(2)) +#define TPI_INFO_FSEL 0x06bf +#define FSEL_AVI 0 +#define FSEL_GBD 1 +#define FSEL_AUDIO 2 +#define FSEL_SPD 3 +#define FSEL_MPEG 4 +#define FSEL_VSIF 5 +#define TPI_INFO_B0 0x06c0 +#define TPI_INFO_EN 0x06df +#define TPI_INFO_TRANS_EN BIT(7) +#define TPI_INFO_TRANS_RPT BIT(6) +#define TPI_DDC_MASTER_EN 0x06f8 +#define HW_DDC_MASTER BIT(7) + +#endif /* __ZX_HDMI_REGS_H__ */ diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c new file mode 100644 index 000000000000..70dfea9267dd --- /dev/null +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -0,0 +1,299 @@ +/* + * Copyright 2016 Linaro Ltd. + * Copyright 2016 ZTE Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "zx_drm_drv.h" +#include "zx_plane.h" +#include "zx_plane_regs.h" +#include "zx_vou.h" + +struct zx_plane { + struct drm_plane plane; + void __iomem *layer; + void __iomem *csc; + void __iomem *hbsc; + void __iomem *rsz; +}; + +#define to_zx_plane(plane) container_of(plane, struct zx_plane, plane) + +static const uint32_t gl_formats[] = { + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ARGB4444, +}; + +static int zx_gl_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + struct drm_framebuffer *fb = plane_state->fb; + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state; + struct drm_rect clip; + + if (!crtc || !fb) + return 0; + + crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state, + crtc); + if (WARN_ON(!crtc_state)) + return -EINVAL; + + /* nothing to check when disabling or disabled */ + if (!crtc_state->enable) + return 0; + + /* plane must be enabled */ + if (!plane_state->crtc) + return -EINVAL; + + clip.x1 = 0; + clip.y1 = 0; + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; + + return drm_plane_helper_check_state(plane_state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); +} + +static int zx_gl_get_fmt(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + return GL_FMT_ARGB8888; + case DRM_FORMAT_RGB888: + return GL_FMT_RGB888; + case DRM_FORMAT_RGB565: + return GL_FMT_RGB565; + case DRM_FORMAT_ARGB1555: + return GL_FMT_ARGB1555; + case DRM_FORMAT_ARGB4444: + return GL_FMT_ARGB4444; + default: + WARN_ONCE(1, "invalid pixel format %d\n", format); + return -EINVAL; + } +} + +static inline void zx_gl_set_update(struct zx_plane *zplane) +{ + void __iomem *layer = zplane->layer; + + zx_writel_mask(layer + GL_CTRL0, GL_UPDATE, GL_UPDATE); +} + +static inline void zx_gl_rsz_set_update(struct zx_plane *zplane) +{ + zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1); +} + +void zx_plane_set_update(struct drm_plane *plane) +{ + struct zx_plane *zplane = to_zx_plane(plane); + + zx_gl_rsz_set_update(zplane); + zx_gl_set_update(zplane); +} + +static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h, + u32 dst_w, u32 dst_h) +{ + void __iomem *rsz = zplane->rsz; + + zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1)); + zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1)); + + zx_gl_rsz_set_update(zplane); +} + +static void zx_gl_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct zx_plane *zplane = to_zx_plane(plane); + struct drm_framebuffer *fb = plane->state->fb; + struct drm_gem_cma_object *cma_obj; + void __iomem *layer = zplane->layer; + void __iomem *csc = zplane->csc; + void __iomem *hbsc = zplane->hbsc; + u32 src_x, src_y, src_w, src_h; + u32 dst_x, dst_y, dst_w, dst_h; + unsigned int depth, bpp; + uint32_t format; + dma_addr_t paddr; + u32 stride; + int fmt; + + if (!fb) + return; + + format = fb->pixel_format; + stride = fb->pitches[0]; + + src_x = plane->state->src_x >> 16; + src_y = plane->state->src_y >> 16; + src_w = plane->state->src_w >> 16; + src_h = plane->state->src_h >> 16; + + dst_x = plane->state->crtc_x; + dst_y = plane->state->crtc_y; + dst_w = plane->state->crtc_w; + dst_h = plane->state->crtc_h; + + drm_fb_get_bpp_depth(format, &depth, &bpp); + + cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + paddr = cma_obj->paddr + fb->offsets[0]; + paddr += src_y * stride + src_x * bpp / 8; + zx_writel(layer + GL_ADDR, paddr); + + /* Set up source height/width register */ + zx_writel(layer + GL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h)); + + /* Set up start position register */ + zx_writel(layer + GL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y)); + + /* Set up end position register */ + zx_writel(layer + GL_POS_END, + GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h)); + + /* Set up stride register */ + zx_writel(layer + GL_STRIDE, stride & 0xffff); + + /* Set up graphic layer data format */ + fmt = zx_gl_get_fmt(format); + if (fmt >= 0) + zx_writel_mask(layer + GL_CTRL1, GL_DATA_FMT_MASK, + fmt << GL_DATA_FMT_SHIFT); + + /* Initialize global alpha with a sane value */ + zx_writel_mask(layer + GL_CTRL2, GL_GLOBAL_ALPHA_MASK, + 0xff << GL_GLOBAL_ALPHA_SHIFT); + + /* Setup CSC for the GL */ + if (dst_h > 720) + zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK, + CSC_BT709_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT); + else + zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK, + CSC_BT601_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT); + zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, CSC_WORK_ENABLE); + + /* Always use scaler since it exists (set for not bypass) */ + zx_writel_mask(layer + GL_CTRL3, GL_SCALER_BYPASS_MODE, + GL_SCALER_BYPASS_MODE); + + zx_gl_rsz_setup(zplane, src_w, src_h, dst_w, dst_h); + + /* Enable HBSC block */ + zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN); + + zx_gl_set_update(zplane); +} + +static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = { + .atomic_check = zx_gl_plane_atomic_check, + .atomic_update = zx_gl_plane_atomic_update, +}; + +static void zx_plane_destroy(struct drm_plane *plane) +{ + drm_plane_helper_disable(plane); + drm_plane_cleanup(plane); +} + +static const struct drm_plane_funcs zx_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = zx_plane_destroy, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static void zx_plane_hbsc_init(struct zx_plane *zplane) +{ + void __iomem *hbsc = zplane->hbsc; + + /* + * Initialize HBSC block with a sane configuration per recommedation + * from ZTE BSP code. + */ + zx_writel(hbsc + HBSC_SATURATION, 0x200); + zx_writel(hbsc + HBSC_HUE, 0x0); + zx_writel(hbsc + HBSC_BRIGHT, 0x0); + zx_writel(hbsc + HBSC_CONTRAST, 0x200); + + zx_writel(hbsc + HBSC_THRESHOLD_COL1, (0x3ac << 16) | 0x40); + zx_writel(hbsc + HBSC_THRESHOLD_COL2, (0x3c0 << 16) | 0x40); + zx_writel(hbsc + HBSC_THRESHOLD_COL3, (0x3c0 << 16) | 0x40); +} + +struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev, + struct zx_layer_data *data, + enum drm_plane_type type) +{ + const struct drm_plane_helper_funcs *helper; + struct zx_plane *zplane; + struct drm_plane *plane; + const uint32_t *formats; + unsigned int format_count; + int ret; + + zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL); + if (!zplane) + return ERR_PTR(-ENOMEM); + + plane = &zplane->plane; + + zplane->layer = data->layer; + zplane->hbsc = data->hbsc; + zplane->csc = data->csc; + zplane->rsz = data->rsz; + + zx_plane_hbsc_init(zplane); + + switch (type) { + case DRM_PLANE_TYPE_PRIMARY: + helper = &zx_gl_plane_helper_funcs; + formats = gl_formats; + format_count = ARRAY_SIZE(gl_formats); + break; + case DRM_PLANE_TYPE_OVERLAY: + /* TODO: add video layer (vl) support */ + break; + default: + return ERR_PTR(-ENODEV); + } + + ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK, + &zx_plane_funcs, formats, format_count, + type, NULL); + if (ret) { + DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret); + return ERR_PTR(ret); + } + + drm_plane_helper_add(plane, helper); + + return plane; +} diff --git a/drivers/gpu/drm/zte/zx_plane.h b/drivers/gpu/drm/zte/zx_plane.h new file mode 100644 index 000000000000..2b82cd558d9d --- /dev/null +++ b/drivers/gpu/drm/zte/zx_plane.h @@ -0,0 +1,26 @@ +/* + * Copyright 2016 Linaro Ltd. + * Copyright 2016 ZTE Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __ZX_PLANE_H__ +#define __ZX_PLANE_H__ + +struct zx_layer_data { + void __iomem *layer; + void __iomem *csc; + void __iomem *hbsc; + void __iomem *rsz; +}; + +struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev, + struct zx_layer_data *data, + enum drm_plane_type type); +void zx_plane_set_update(struct drm_plane *plane); + +#endif /* __ZX_PLANE_H__ */ diff --git a/drivers/gpu/drm/zte/zx_plane_regs.h b/drivers/gpu/drm/zte/zx_plane_regs.h new file mode 100644 index 000000000000..3dde6716a558 --- /dev/null +++ b/drivers/gpu/drm/zte/zx_plane_regs.h @@ -0,0 +1,91 @@ +/* + * Copyright 2016 Linaro Ltd. + * Copyright 2016 ZTE Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __ZX_PLANE_REGS_H__ +#define __ZX_PLANE_REGS_H__ + +/* GL registers */ +#define GL_CTRL0 0x00 +#define GL_UPDATE BIT(5) +#define GL_CTRL1 0x04 +#define GL_DATA_FMT_SHIFT 0 +#define GL_DATA_FMT_MASK (0xf << GL_DATA_FMT_SHIFT) +#define GL_FMT_ARGB8888 0 +#define GL_FMT_RGB888 1 +#define GL_FMT_RGB565 2 +#define GL_FMT_ARGB1555 3 +#define GL_FMT_ARGB4444 4 +#define GL_CTRL2 0x08 +#define GL_GLOBAL_ALPHA_SHIFT 8 +#define GL_GLOBAL_ALPHA_MASK (0xff << GL_GLOBAL_ALPHA_SHIFT) +#define GL_CTRL3 0x0c +#define GL_SCALER_BYPASS_MODE BIT(0) +#define GL_STRIDE 0x18 +#define GL_ADDR 0x1c +#define GL_SRC_SIZE 0x38 +#define GL_SRC_W_SHIFT 16 +#define GL_SRC_W_MASK (0x3fff << GL_SRC_W_SHIFT) +#define GL_SRC_H_SHIFT 0 +#define GL_SRC_H_MASK (0x3fff << GL_SRC_H_SHIFT) +#define GL_POS_START 0x9c +#define GL_POS_END 0xa0 +#define GL_POS_X_SHIFT 16 +#define GL_POS_X_MASK (0x1fff << GL_POS_X_SHIFT) +#define GL_POS_Y_SHIFT 0 +#define GL_POS_Y_MASK (0x1fff << GL_POS_Y_SHIFT) + +#define GL_SRC_W(x) (((x) << GL_SRC_W_SHIFT) & GL_SRC_W_MASK) +#define GL_SRC_H(x) (((x) << GL_SRC_H_SHIFT) & GL_SRC_H_MASK) +#define GL_POS_X(x) (((x) << GL_POS_X_SHIFT) & GL_POS_X_MASK) +#define GL_POS_Y(x) (((x) << GL_POS_Y_SHIFT) & GL_POS_Y_MASK) + +/* CSC registers */ +#define CSC_CTRL0 0x30 +#define CSC_COV_MODE_SHIFT 16 +#define CSC_COV_MODE_MASK (0xffff << CSC_COV_MODE_SHIFT) +#define CSC_BT601_IMAGE_RGB2YCBCR 0 +#define CSC_BT601_IMAGE_YCBCR2RGB 1 +#define CSC_BT601_VIDEO_RGB2YCBCR 2 +#define CSC_BT601_VIDEO_YCBCR2RGB 3 +#define CSC_BT709_IMAGE_RGB2YCBCR 4 +#define CSC_BT709_IMAGE_YCBCR2RGB 5 +#define CSC_BT709_VIDEO_RGB2YCBCR 6 +#define CSC_BT709_VIDEO_YCBCR2RGB 7 +#define CSC_BT2020_IMAGE_RGB2YCBCR 8 +#define CSC_BT2020_IMAGE_YCBCR2RGB 9 +#define CSC_BT2020_VIDEO_RGB2YCBCR 10 +#define CSC_BT2020_VIDEO_YCBCR2RGB 11 +#define CSC_WORK_ENABLE BIT(0) + +/* RSZ registers */ +#define RSZ_SRC_CFG 0x00 +#define RSZ_DEST_CFG 0x04 +#define RSZ_ENABLE_CFG 0x14 + +#define RSZ_VER_SHIFT 16 +#define RSZ_VER_MASK (0xffff << RSZ_VER_SHIFT) +#define RSZ_HOR_SHIFT 0 +#define RSZ_HOR_MASK (0xffff << RSZ_HOR_SHIFT) + +#define RSZ_VER(x) (((x) << RSZ_VER_SHIFT) & RSZ_VER_MASK) +#define RSZ_HOR(x) (((x) << RSZ_HOR_SHIFT) & RSZ_HOR_MASK) + +/* HBSC registers */ +#define HBSC_SATURATION 0x00 +#define HBSC_HUE 0x04 +#define HBSC_BRIGHT 0x08 +#define HBSC_CONTRAST 0x0c +#define HBSC_THRESHOLD_COL1 0x10 +#define HBSC_THRESHOLD_COL2 0x14 +#define HBSC_THRESHOLD_COL3 0x18 +#define HBSC_CTRL0 0x28 +#define HBSC_CTRL_EN BIT(2) + +#endif /* __ZX_PLANE_REGS_H__ */ diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c new file mode 100644 index 000000000000..73fe15c17c32 --- /dev/null +++ b/drivers/gpu/drm/zte/zx_vou.c @@ -0,0 +1,661 @@ +/* + * Copyright 2016 Linaro Ltd. + * Copyright 2016 ZTE Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include